@winspan/claude-forge 0.7.6 → 0.8.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.
Files changed (53) hide show
  1. package/dist/ai-gateway/index.d.ts +4 -0
  2. package/dist/ai-gateway/index.d.ts.map +1 -1
  3. package/dist/ai-gateway/index.js +45 -1
  4. package/dist/ai-gateway/index.js.map +1 -1
  5. package/dist/ai-gateway/response-cache.d.ts +2 -0
  6. package/dist/ai-gateway/response-cache.d.ts.map +1 -1
  7. package/dist/ai-gateway/response-cache.js +7 -2
  8. package/dist/ai-gateway/response-cache.js.map +1 -1
  9. package/dist/ai-gateway/token-budget.d.ts +69 -0
  10. package/dist/ai-gateway/token-budget.d.ts.map +1 -0
  11. package/dist/ai-gateway/token-budget.js +141 -0
  12. package/dist/ai-gateway/token-budget.js.map +1 -0
  13. package/dist/autopilot/issue-tracker.d.ts +5 -1
  14. package/dist/autopilot/issue-tracker.d.ts.map +1 -1
  15. package/dist/autopilot/issue-tracker.js +34 -7
  16. package/dist/autopilot/issue-tracker.js.map +1 -1
  17. package/dist/autopilot/quality-gate.d.ts +2 -0
  18. package/dist/autopilot/quality-gate.d.ts.map +1 -1
  19. package/dist/autopilot/quality-gate.js +14 -0
  20. package/dist/autopilot/quality-gate.js.map +1 -1
  21. package/dist/autopilot/task-completion-detector.d.ts.map +1 -1
  22. package/dist/autopilot/task-completion-detector.js +1 -0
  23. package/dist/autopilot/task-completion-detector.js.map +1 -1
  24. package/dist/daemon/handlers/session-cleanup.d.ts.map +1 -1
  25. package/dist/daemon/handlers/session-cleanup.js +4 -0
  26. package/dist/daemon/handlers/session-cleanup.js.map +1 -1
  27. package/dist/distill/index.d.ts.map +1 -1
  28. package/dist/distill/index.js +10 -7
  29. package/dist/distill/index.js.map +1 -1
  30. package/dist/distill/tree-index.d.ts.map +1 -1
  31. package/dist/distill/tree-index.js +13 -9
  32. package/dist/distill/tree-index.js.map +1 -1
  33. package/dist/distill/trigger.d.ts +1 -1
  34. package/dist/distill/trigger.d.ts.map +1 -1
  35. package/dist/distill/trigger.js +14 -4
  36. package/dist/distill/trigger.js.map +1 -1
  37. package/dist/distill/writer.d.ts +7 -4
  38. package/dist/distill/writer.d.ts.map +1 -1
  39. package/dist/distill/writer.js +45 -15
  40. package/dist/distill/writer.js.map +1 -1
  41. package/dist/pipeline/index.d.ts +6 -0
  42. package/dist/pipeline/index.d.ts.map +1 -1
  43. package/dist/pipeline/index.js +27 -5
  44. package/dist/pipeline/index.js.map +1 -1
  45. package/dist/pipeline/phase-manager.d.ts +1 -0
  46. package/dist/pipeline/phase-manager.d.ts.map +1 -1
  47. package/dist/pipeline/phase-manager.js +64 -64
  48. package/dist/pipeline/phase-manager.js.map +1 -1
  49. package/dist/skill-registry/orchestrator.d.ts +11 -3
  50. package/dist/skill-registry/orchestrator.d.ts.map +1 -1
  51. package/dist/skill-registry/orchestrator.js +28 -6
  52. package/dist/skill-registry/orchestrator.js.map +1 -1
  53. package/package.json +1 -1
@@ -1,4 +1,5 @@
1
1
  import type { AIProvider, CompletionOptions } from '../ai-provider/types.js';
2
+ import type { BudgetConfig } from './token-budget.js';
2
3
  export interface GatewayOptions {
3
4
  maxConcurrent?: number;
4
5
  minIntervalMs?: number;
@@ -13,6 +14,8 @@ export interface GatewayOptions {
13
14
  sonnet?: string;
14
15
  opus?: string;
15
16
  };
17
+ /** Token 预算配置(不配置则不启用预算管理) */
18
+ tokenBudget?: Partial<BudgetConfig>;
16
19
  }
17
20
  /**
18
21
  * AI Gateway — 包装 AIProvider,提供全局限流 + 内存缓存 + 统一日志
@@ -28,6 +31,7 @@ export declare class AIGateway implements AIProvider {
28
31
  private maxConcurrent;
29
32
  private degradationCount;
30
33
  private totalCompletions;
34
+ private budgetManager;
31
35
  constructor(inner: AIProvider, opts?: GatewayOptions);
32
36
  complete(prompt: string, label?: string, options?: CompletionOptions): Promise<string>;
33
37
  getStats(): Readonly<import("../ai-provider/types.js").ApiCallStats>;
@@ -1 +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;AAO7E,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;IAC7B,0BAA0B;IAC1B,MAAM,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7D;AAOD;;;GAGG;AACH,qBAAa,SAAU,YAAW,UAAU;IAU9B,OAAO,CAAC,KAAK;IATzB,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,aAAa,CAAc;IACnC,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,gBAAgB,CAAK;gBAET,KAAK,EAAE,UAAU,EAAE,IAAI,GAAE,cAAmB;IAY1D,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC;IAoE5F,QAAQ;IAIR,WAAW,IAAI,MAAM;CAStB"}
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;AAK7E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAItD,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;IAC7B,0BAA0B;IAC1B,MAAM,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5D,8BAA8B;IAC9B,WAAW,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;CACrC;AAOD;;;GAGG;AACH,qBAAa,SAAU,YAAW,UAAU;IAW9B,OAAO,CAAC,KAAK;IAVzB,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,aAAa,CAAc;IACnC,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,aAAa,CAA4B;gBAE7B,KAAK,EAAE,UAAU,EAAE,IAAI,GAAE,cAAmB;IAa1D,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC;IA6G5F,QAAQ;IAIR,WAAW,IAAI,MAAM;CAsBtB"}
@@ -1,6 +1,7 @@
1
1
  import { RateLimiter } from './rate-limiter.js';
2
2
  import { ResponseCache } from './response-cache.js';
3
3
  import { ModelSelector } from './model-selector.js';
4
+ import { TokenBudgetManager } from './token-budget.js';
4
5
  import { logger } from '../utils/logger.js';
5
6
  import { withRetry } from '../utils/error-handler.js';
6
7
  const DEFAULT_NO_CACHE_LABELS = new Set([
@@ -21,6 +22,7 @@ export class AIGateway {
21
22
  maxConcurrent;
22
23
  degradationCount = 0;
23
24
  totalCompletions = 0;
25
+ budgetManager;
24
26
  constructor(inner, opts = {}) {
25
27
  this.inner = inner;
26
28
  this.maxConcurrent = opts.maxConcurrent ?? 3;
@@ -32,8 +34,34 @@ export class AIGateway {
32
34
  ...(opts.noCacheLabels ?? []),
33
35
  ]);
34
36
  this.modelSelector = opts.enableModelTiering !== false ? new ModelSelector(opts.models) : null;
37
+ this.budgetManager = opts.tokenBudget ? new TokenBudgetManager(opts.tokenBudget) : null;
35
38
  }
36
39
  async complete(prompt, label, options) {
40
+ // Token 预算检查(仅检查每日预算,使用当前日期作为 key)
41
+ let estimatedTokens = 0;
42
+ if (this.budgetManager) {
43
+ const today = new Date().toISOString().slice(0, 10);
44
+ const budgetResult = await this.budgetManager.checkAndReserve(label ?? 'unlabeled', prompt, 'day', today);
45
+ estimatedTokens = budgetResult.estimatedTokens;
46
+ if (!budgetResult.allowed) {
47
+ // 超预算,降级到 Haiku(如果启用分层)或拒绝
48
+ if (this.modelSelector) {
49
+ logger.warn(`[AI Gateway] Token 预算不足,强制降级到 Haiku(label=${label ?? '-'})`);
50
+ const haikuModel = this.modelSelector.modelForTier('haiku');
51
+ const degradedOptions = { ...options, model: haikuModel };
52
+ return this.inner.complete(prompt, label, degradedOptions);
53
+ }
54
+ else {
55
+ const today = new Date().toISOString().slice(0, 10);
56
+ const usage = this.budgetManager.getUsage('day', today);
57
+ const resetTime = new Date(new Date().setUTCHours(24, 0, 0, 0)).toISOString().slice(11, 16) + ' UTC';
58
+ const remaining = usage ? usage.remaining : 0;
59
+ const limit = usage ? usage.limit : 0;
60
+ throw new Error(`Token 每日预算已耗尽(剩余 ${remaining}/${limit} tokens,将于 ${resetTime} 重置)。` +
61
+ `如需立即使用,请在配置中调整 tokenBudget.daily 或等待重置。`);
62
+ }
63
+ }
64
+ }
37
65
  // 可缓存的调用先查缓存
38
66
  const cacheable = label ? !this.noCacheLabels.has(label) : false;
39
67
  // 先确定主模型(用于缓存键)
@@ -63,6 +91,12 @@ export class AIGateway {
63
91
  this.degradationCount++;
64
92
  logger.info(`[AI Gateway] 降级成功:${chain.primary} → ${tier}(label=${label ?? '-'})`);
65
93
  }
94
+ // 记录实际 Token 消耗(用响应长度估算:prompt + response)
95
+ if (this.budgetManager && estimatedTokens > 0) {
96
+ const actualTokens = Math.ceil((prompt.length + result.length) * this.budgetManager['estimationFactor']);
97
+ const today = new Date().toISOString().slice(0, 10);
98
+ this.budgetManager.recordActual('day', today, actualTokens, estimatedTokens);
99
+ }
66
100
  if (cacheable) {
67
101
  this.cache.set(prompt, label, result, this.cacheTtlMs, model);
68
102
  }
@@ -102,7 +136,17 @@ export class AIGateway {
102
136
  const degradationRate = this.totalCompletions === 0
103
137
  ? '0.0'
104
138
  : ((this.degradationCount / this.totalCompletions) * 100).toFixed(1);
105
- return `${inner}\n[AI Gateway] 缓存命中率: ${hitRate}% | 缓存条目: ${this.cache.size} | 并发: ${limiter.active}/${this.maxConcurrent} | 累计等待: ${limiter.totalWaitMs}ms | 降级率: ${degradationRate}%`;
139
+ let stats = `${inner}\n[AI Gateway] 缓存命中率: ${hitRate}% | 缓存条目: ${this.cache.size} | 并发: ${limiter.active}/${this.maxConcurrent} | 累计等待: ${limiter.totalWaitMs}ms | 降级率: ${degradationRate}%`;
140
+ // 添加 Token 预算统计
141
+ if (this.budgetManager) {
142
+ const today = new Date().toISOString().slice(0, 10);
143
+ const usage = this.budgetManager.getUsage('day', today);
144
+ if (usage) {
145
+ const usagePercent = ((usage.used / usage.limit) * 100).toFixed(1);
146
+ stats += `\n[Token 预算] 今日已用: ${usage.used}/${usage.limit} (${usagePercent}%) | 剩余: ${usage.remaining}`;
147
+ }
148
+ }
149
+ return stats;
106
150
  }
107
151
  }
108
152
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ai-gateway/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ai-gateway/index.ts"],"names":[],"mappings":"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"}
@@ -9,6 +9,8 @@ export declare class ResponseCache {
9
9
  private cache;
10
10
  private hits;
11
11
  private misses;
12
+ private setCount;
13
+ private evictionInterval;
12
14
  constructor(maxEntries?: number);
13
15
  get(prompt: string, label?: string, model?: string): string | undefined;
14
16
  set(prompt: string, label: string | undefined, value: string, ttlMs?: number, model?: string): void;
@@ -1 +1 @@
1
- {"version":3,"file":"response-cache.d.ts","sourceRoot":"","sources":["../../src/ai-gateway/response-cache.ts"],"names":[],"mappings":"AAOA;;;;;GAKG;AACH,qBAAa,aAAa;IAKZ,OAAO,CAAC,UAAU;IAJ9B,OAAO,CAAC,KAAK,CAAiC;IAC9C,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,MAAM,CAAK;gBAEC,UAAU,SAAM;IAEpC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAqBvE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,SAAU,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IAepG,UAAU,IAAI,IAAI;IAIlB,IAAI,OAAO,IAAI,MAAM,CAGpB;IAED,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,OAAO;CAGhB"}
1
+ {"version":3,"file":"response-cache.d.ts","sourceRoot":"","sources":["../../src/ai-gateway/response-cache.ts"],"names":[],"mappings":"AAOA;;;;;GAKG;AACH,qBAAa,aAAa;IAOZ,OAAO,CAAC,UAAU;IAN9B,OAAO,CAAC,KAAK,CAAiC;IAC9C,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,gBAAgB,CAAO;gBAEX,UAAU,SAAM;IAEpC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAqBvE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,SAAU,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IAkBpG,UAAU,IAAI,IAAI;IAIlB,IAAI,OAAO,IAAI,MAAM,CAGpB;IAED,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,OAAO;CAGhB"}
@@ -10,6 +10,8 @@ export class ResponseCache {
10
10
  cache = new Map();
11
11
  hits = 0;
12
12
  misses = 0;
13
+ setCount = 0;
14
+ evictionInterval = 100;
13
15
  constructor(maxEntries = 500) {
14
16
  this.maxEntries = maxEntries;
15
17
  }
@@ -34,8 +36,11 @@ export class ResponseCache {
34
36
  set(prompt, label, value, ttlMs = 300_000, model) {
35
37
  const key = this.makeKey(prompt, label, model);
36
38
  const entry = { value, expiresAt: Date.now() + ttlMs };
37
- // 先清理已过期条目
38
- this.evictExpired();
39
+ // 定期清理已过期条目(每 100 次 set 执行一次)
40
+ this.setCount++;
41
+ if (this.setCount % this.evictionInterval === 0) {
42
+ this.evictExpired();
43
+ }
39
44
  // 更新同 key 时,先删后插(保持最新顺序)
40
45
  if (this.cache.has(key))
41
46
  this.cache.delete(key);
@@ -1 +1 @@
1
- {"version":3,"file":"response-cache.js","sourceRoot":"","sources":["../../src/ai-gateway/response-cache.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"response-cache.js","sourceRoot":"","sources":["../../src/ai-gateway/response-cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ export interface BudgetConfig {
2
+ /** 每日 Token 预算(默认 100k) */
3
+ daily: number;
4
+ /** 每会话 Token 预算(默认 50k) */
5
+ session?: number;
6
+ /** 每项目 Token 预算(默认 200k) */
7
+ project?: number;
8
+ }
9
+ /**
10
+ * Token 预算管理器 — 按 session/project/day 维度控制 AI 调用成本
11
+ *
12
+ * 预算检查策略:
13
+ * - 每次 AI 调用前预估 Token 消耗(prompt 长度 / 4,动态校准)
14
+ * - 超预算时返回 false,触发降级或拒绝
15
+ * - 每日预算在 UTC 0:00 重置
16
+ * - 会话/项目预算在 24 小时后重置
17
+ * - 记录实际消耗,动态调整预估系数
18
+ */
19
+ export declare class TokenBudgetManager {
20
+ private budgets;
21
+ private defaultConfig;
22
+ /** 预估系数(字符数 → Token 数),初始值 0.25(1 字符 = 0.25 Token),动态校准 */
23
+ private estimationFactor;
24
+ /** 校准样本数 */
25
+ private calibrationSamples;
26
+ constructor(config?: Partial<BudgetConfig>);
27
+ /**
28
+ * 预估 Token 数量(基于字符数和动态校准系数)
29
+ */
30
+ private estimateTokens;
31
+ /**
32
+ * 检查并预留 Token 预算
33
+ * @param label 调用标签(用于日志追踪)
34
+ * @param prompt 原始 prompt(用于预估 Token 数量)
35
+ * @param dimension 预算维度(session/project/day)
36
+ * @param dimensionKey 维度键(sessionId/projectPath/date)
37
+ * @returns true 表示预算充足,false 表示超预算
38
+ */
39
+ checkAndReserve(label: string, prompt: string, dimension: 'session' | 'project' | 'day', dimensionKey: string): Promise<{
40
+ allowed: boolean;
41
+ estimatedTokens: number;
42
+ }>;
43
+ /**
44
+ * 记录实际消耗(用于校准预估误差)
45
+ * @param dimension 预算维度
46
+ * @param dimensionKey 维度键
47
+ * @param actualTokens 实际消耗 Token 数量
48
+ * @param estimatedTokens 预估 Token 数量
49
+ */
50
+ recordActual(dimension: 'session' | 'project' | 'day', dimensionKey: string, actualTokens: number, estimatedTokens: number): void;
51
+ /**
52
+ * 获取预算使用情况
53
+ */
54
+ getUsage(dimension: 'session' | 'project' | 'day', dimensionKey: string): {
55
+ used: number;
56
+ limit: number;
57
+ remaining: number;
58
+ } | null;
59
+ /**
60
+ * 重置指定维度的预算(用于测试或手动重置)
61
+ */
62
+ reset(dimension: 'session' | 'project' | 'day', dimensionKey: string): void;
63
+ /**
64
+ * 清理过期预算条目(定期调用,防止内存泄漏)
65
+ */
66
+ cleanup(): void;
67
+ private getNextMidnightUTC;
68
+ }
69
+ //# sourceMappingURL=token-budget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-budget.d.ts","sourceRoot":"","sources":["../../src/ai-gateway/token-budget.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,YAAY;IAC3B,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,2BAA2B;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4BAA4B;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAQD;;;;;;;;;GASG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,OAAO,CAAkC;IACjD,OAAO,CAAC,aAAa,CAInB;IACF,2DAA2D;IAC3D,OAAO,CAAC,gBAAgB,CAAQ;IAChC,YAAY;IACZ,OAAO,CAAC,kBAAkB,CAAK;gBAEnB,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC;IAM1C;;OAEG;IACH,OAAO,CAAC,cAAc;IAItB;;;;;;;OAOG;IACG,eAAe,CACnB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,SAAS,GAAG,SAAS,GAAG,KAAK,EACxC,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAE,CAAC;IAyCzD;;;;;;OAMG;IACH,YAAY,CACV,SAAS,EAAE,SAAS,GAAG,SAAS,GAAG,KAAK,EACxC,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,MAAM,GACtB,IAAI;IA+BP;;OAEG;IACH,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,SAAS,GAAG,KAAK,EAAE,YAAY,EAAE,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAYnI;;OAEG;IACH,KAAK,CAAC,SAAS,EAAE,SAAS,GAAG,SAAS,GAAG,KAAK,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI;IAK3E;;OAEG;IACH,OAAO,IAAI,IAAI;IASf,OAAO,CAAC,kBAAkB;CAU3B"}
@@ -0,0 +1,141 @@
1
+ import { logger } from '../utils/logger.js';
2
+ /**
3
+ * Token 预算管理器 — 按 session/project/day 维度控制 AI 调用成本
4
+ *
5
+ * 预算检查策略:
6
+ * - 每次 AI 调用前预估 Token 消耗(prompt 长度 / 4,动态校准)
7
+ * - 超预算时返回 false,触发降级或拒绝
8
+ * - 每日预算在 UTC 0:00 重置
9
+ * - 会话/项目预算在 24 小时后重置
10
+ * - 记录实际消耗,动态调整预估系数
11
+ */
12
+ export class TokenBudgetManager {
13
+ budgets = new Map();
14
+ defaultConfig = {
15
+ daily: 100_000,
16
+ session: 50_000,
17
+ project: 200_000,
18
+ };
19
+ /** 预估系数(字符数 → Token 数),初始值 0.25(1 字符 = 0.25 Token),动态校准 */
20
+ estimationFactor = 0.25;
21
+ /** 校准样本数 */
22
+ calibrationSamples = 0;
23
+ constructor(config) {
24
+ if (config) {
25
+ this.defaultConfig = { ...this.defaultConfig, ...config };
26
+ }
27
+ }
28
+ /**
29
+ * 预估 Token 数量(基于字符数和动态校准系数)
30
+ */
31
+ estimateTokens(prompt) {
32
+ return Math.ceil(prompt.length * this.estimationFactor);
33
+ }
34
+ /**
35
+ * 检查并预留 Token 预算
36
+ * @param label 调用标签(用于日志追踪)
37
+ * @param prompt 原始 prompt(用于预估 Token 数量)
38
+ * @param dimension 预算维度(session/project/day)
39
+ * @param dimensionKey 维度键(sessionId/projectPath/date)
40
+ * @returns true 表示预算充足,false 表示超预算
41
+ */
42
+ async checkAndReserve(label, prompt, dimension, dimensionKey) {
43
+ const estimatedTokens = this.estimateTokens(prompt);
44
+ const now = Date.now();
45
+ // 获取或初始化预算条目
46
+ const key = `${dimension}:${dimensionKey}`;
47
+ let entry = this.budgets.get(key);
48
+ if (!entry || now >= entry.resetAt) {
49
+ const limit = dimension === 'day'
50
+ ? this.defaultConfig.daily
51
+ : dimension === 'session'
52
+ ? (this.defaultConfig.session ?? this.defaultConfig.daily)
53
+ : (this.defaultConfig.project ?? this.defaultConfig.daily * 2);
54
+ const resetAt = dimension === 'day'
55
+ ? this.getNextMidnightUTC()
56
+ : now + 86400_000; // 24 小时后
57
+ entry = { limit, used: 0, resetAt };
58
+ this.budgets.set(key, entry);
59
+ }
60
+ // 检查预算
61
+ if (entry.used + estimatedTokens > entry.limit) {
62
+ const remaining = Math.max(0, entry.limit - entry.used);
63
+ logger.warn(`[Token 预算] 超预算:${dimension}=${dimensionKey.slice(0, 20)} ` +
64
+ `label=${label} 预估=${estimatedTokens} 已用=${entry.used}/${entry.limit} 剩余=${remaining}`);
65
+ return { allowed: false, estimatedTokens };
66
+ }
67
+ // 预留预算
68
+ entry.used += estimatedTokens;
69
+ logger.debug(`[Token 预算] 预留成功:${dimension}=${dimensionKey.slice(0, 20)} ` +
70
+ `label=${label} 预估=${estimatedTokens} 已用=${entry.used}/${entry.limit}`);
71
+ return { allowed: true, estimatedTokens };
72
+ }
73
+ /**
74
+ * 记录实际消耗(用于校准预估误差)
75
+ * @param dimension 预算维度
76
+ * @param dimensionKey 维度键
77
+ * @param actualTokens 实际消耗 Token 数量
78
+ * @param estimatedTokens 预估 Token 数量
79
+ */
80
+ recordActual(dimension, dimensionKey, actualTokens, estimatedTokens) {
81
+ const key = `${dimension}:${dimensionKey}`;
82
+ const entry = this.budgets.get(key);
83
+ if (!entry)
84
+ return;
85
+ // 校准:用实际值替换预估值
86
+ const delta = actualTokens - estimatedTokens;
87
+ entry.used += delta;
88
+ // 动态调整预估系数(指数移动平均,权重 0.1)
89
+ if (actualTokens > 0 && estimatedTokens > 0) {
90
+ const actualFactor = actualTokens / (estimatedTokens / this.estimationFactor);
91
+ this.estimationFactor = this.estimationFactor * 0.9 + actualFactor * 0.1;
92
+ this.calibrationSamples++;
93
+ if (this.calibrationSamples % 10 === 0) {
94
+ logger.debug(`[Token 预算] 预估系数校准:${this.estimationFactor.toFixed(4)} ` +
95
+ `(样本数=${this.calibrationSamples})`);
96
+ }
97
+ }
98
+ if (Math.abs(delta) > estimatedTokens * 0.2) {
99
+ logger.debug(`[Token 预算] 预估偏差:${dimension}=${dimensionKey.slice(0, 20)} ` +
100
+ `预估=${estimatedTokens} 实际=${actualTokens} 偏差=${delta}`);
101
+ }
102
+ }
103
+ /**
104
+ * 获取预算使用情况
105
+ */
106
+ getUsage(dimension, dimensionKey) {
107
+ const key = `${dimension}:${dimensionKey}`;
108
+ const entry = this.budgets.get(key);
109
+ if (!entry || Date.now() >= entry.resetAt)
110
+ return null;
111
+ return {
112
+ used: entry.used,
113
+ limit: entry.limit,
114
+ remaining: Math.max(0, entry.limit - entry.used),
115
+ };
116
+ }
117
+ /**
118
+ * 重置指定维度的预算(用于测试或手动重置)
119
+ */
120
+ reset(dimension, dimensionKey) {
121
+ const key = `${dimension}:${dimensionKey}`;
122
+ this.budgets.delete(key);
123
+ }
124
+ /**
125
+ * 清理过期预算条目(定期调用,防止内存泄漏)
126
+ */
127
+ cleanup() {
128
+ const now = Date.now();
129
+ for (const [key, entry] of this.budgets.entries()) {
130
+ if (now >= entry.resetAt) {
131
+ this.budgets.delete(key);
132
+ }
133
+ }
134
+ }
135
+ getNextMidnightUTC() {
136
+ const now = new Date();
137
+ const tomorrow = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate() + 1, 0, 0, 0, 0));
138
+ return tomorrow.getTime();
139
+ }
140
+ }
141
+ //# sourceMappingURL=token-budget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-budget.js","sourceRoot":"","sources":["../../src/ai-gateway/token-budget.ts"],"names":[],"mappings":"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"}
@@ -27,11 +27,15 @@ export interface IssueSummary {
27
27
  /**
28
28
  * IssueTracker — 跨阶段问题台账
29
29
  *
30
- * 纯内存实现,Pipeline 完成时由 PipelineReportGenerator 写入 decisions.md。
30
+ * 使用 LRUCache 限制最大条目数(1000),防止长期运行内存泄漏。
31
+ * Pipeline 完成时由 PipelineReportGenerator 写入 decisions.md。
31
32
  * 每个 Pipeline 独立隔离,通过 pipelineId 区分。
32
33
  */
33
34
  export declare class IssueTracker {
34
35
  private issues;
36
+ /** 二级索引:pipelineId:phase → issue IDs(加速 getOpenByPhase 查询) */
37
+ private phaseIndex;
38
+ constructor();
35
39
  add(pipelineId: string, sourcePhase: PipelinePhase, category: IssueCategory, level: 'warn' | 'fail', message: string, suggestion?: string, filePath?: string): TrackedIssue;
36
40
  resolve(issueId: string, resolvedAtPhase: PipelinePhase): void;
37
41
  wontfix(issueId: string): void;
@@ -1 +1 @@
1
- {"version":3,"file":"issue-tracker.d.ts","sourceRoot":"","sources":["../../src/autopilot/issue-tracker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,aAAa,GAAG,UAAU,GAAG,SAAS,CAAC;AAE1E,MAAM,MAAM,aAAa,GACrB,uBAAuB,GACvB,uBAAuB,GACvB,YAAY,GACZ,cAAc,GACd,UAAU,GACV,eAAe,GACf,aAAa,GACb,gBAAgB,CAAC;AAErB,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,aAAa,CAAC;IAC3B,QAAQ,EAAE,aAAa,CAAC;IACxB,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,WAAW,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,aAAa,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC;CACpD;AAED;;;;;GAKG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAmC;IAEjD,GAAG,CACD,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,aAAa,EAC1B,QAAQ,EAAE,aAAa,EACvB,KAAK,EAAE,MAAM,GAAG,MAAM,EACtB,OAAO,EAAE,MAAM,EACf,UAAU,CAAC,EAAE,MAAM,EACnB,QAAQ,CAAC,EAAE,MAAM,GAChB,YAAY;IAsBf,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,aAAa,GAAG,IAAI;IAQ9D,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAO9B,oBAAoB;IACpB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAS7C,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAOrC,oCAAoC;IACpC,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,aAAa,GAAG,YAAY,EAAE;IAQ9E,iCAAiC;IACjC,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,YAAY,EAAE;IAI1C,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,YAAY;IAe5C,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;CAO3C"}
1
+ {"version":3,"file":"issue-tracker.d.ts","sourceRoot":"","sources":["../../src/autopilot/issue-tracker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAI1D,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,aAAa,GAAG,UAAU,GAAG,SAAS,CAAC;AAE1E,MAAM,MAAM,aAAa,GACrB,uBAAuB,GACvB,uBAAuB,GACvB,YAAY,GACZ,cAAc,GACd,UAAU,GACV,eAAe,GACf,aAAa,GACb,gBAAgB,CAAC;AAErB,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,aAAa,CAAC;IAC3B,QAAQ,EAAE,aAAa,CAAC;IACxB,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,WAAW,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,aAAa,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC;CACpD;AAED;;;;;;GAMG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAiC;IAC/C,8DAA8D;IAC9D,OAAO,CAAC,UAAU,CAAkC;;IAMpD,GAAG,CACD,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,aAAa,EAC1B,QAAQ,EAAE,aAAa,EACvB,KAAK,EAAE,MAAM,GAAG,MAAM,EACtB,OAAO,EAAE,MAAM,EACf,UAAU,CAAC,EAAE,MAAM,EACnB,QAAQ,CAAC,EAAE,MAAM,GAChB,YAAY;IA4Bf,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,aAAa,GAAG,IAAI;IAQ9D,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAO9B,oBAAoB;IACpB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAS7C,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAOrC,oCAAoC;IACpC,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,aAAa,GAAG,YAAY,EAAE;IAe9E,iCAAiC;IACjC,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,YAAY,EAAE;IAI1C,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,YAAY;IAe5C,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;CAa3C"}
@@ -1,11 +1,18 @@
1
+ import { memoryManager } from '../utils/memory-manager.js';
1
2
  /**
2
3
  * IssueTracker — 跨阶段问题台账
3
4
  *
4
- * 纯内存实现,Pipeline 完成时由 PipelineReportGenerator 写入 decisions.md。
5
+ * 使用 LRUCache 限制最大条目数(1000),防止长期运行内存泄漏。
6
+ * Pipeline 完成时由 PipelineReportGenerator 写入 decisions.md。
5
7
  * 每个 Pipeline 独立隔离,通过 pipelineId 区分。
6
8
  */
7
9
  export class IssueTracker {
8
- issues = new Map();
10
+ issues;
11
+ /** 二级索引:pipelineId:phase → issue IDs(加速 getOpenByPhase 查询) */
12
+ phaseIndex = new Map();
13
+ constructor() {
14
+ this.issues = memoryManager.register('quality:issues', { max: 1000 });
15
+ }
9
16
  add(pipelineId, sourcePhase, category, level, message, suggestion, filePath) {
10
17
  const id = `issue_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`;
11
18
  const now = new Date().toISOString();
@@ -25,6 +32,11 @@ export class IssueTracker {
25
32
  updatedAt: now,
26
33
  };
27
34
  this.issues.set(id, issue);
35
+ // 更新二级索引
36
+ const indexKey = `${pipelineId}:${sourcePhase}`;
37
+ if (!this.phaseIndex.has(indexKey))
38
+ this.phaseIndex.set(indexKey, new Set());
39
+ this.phaseIndex.get(indexKey).add(id);
28
40
  return issue;
29
41
  }
30
42
  resolve(issueId, resolvedAtPhase) {
@@ -61,13 +73,22 @@ export class IssueTracker {
61
73
  }
62
74
  /** 获取指定阶段发现的 open/in_progress 问题 */
63
75
  getOpenByPhase(pipelineId, sourcePhase) {
64
- return [...this.issues.values()].filter(i => i.pipelineId === pipelineId &&
65
- i.sourcePhase === sourcePhase &&
66
- (i.status === 'open' || i.status === 'in_progress'));
76
+ const indexKey = `${pipelineId}:${sourcePhase}`;
77
+ const ids = this.phaseIndex.get(indexKey);
78
+ if (!ids || ids.size === 0)
79
+ return [];
80
+ const result = [];
81
+ for (const id of ids) {
82
+ const issue = this.issues.get(id);
83
+ if (issue && (issue.status === 'open' || issue.status === 'in_progress')) {
84
+ result.push(issue);
85
+ }
86
+ }
87
+ return result;
67
88
  }
68
89
  /** 获取指定 Pipeline 的所有问题(含所有状态) */
69
90
  getAll(pipelineId) {
70
- return [...this.issues.values()].filter(i => i.pipelineId === pipelineId);
91
+ return this.issues.values().filter(i => i.pipelineId === pipelineId);
71
92
  }
72
93
  getSummary(pipelineId) {
73
94
  const all = this.getAll(pipelineId);
@@ -84,11 +105,17 @@ export class IssueTracker {
84
105
  };
85
106
  }
86
107
  resetForPipeline(pipelineId) {
87
- for (const [id, issue] of this.issues) {
108
+ for (const [id, issue] of this.issues.entries()) {
88
109
  if (issue.pipelineId === pipelineId) {
89
110
  this.issues.delete(id);
90
111
  }
91
112
  }
113
+ // 清理二级索引
114
+ for (const key of this.phaseIndex.keys()) {
115
+ if (key.startsWith(`${pipelineId}:`)) {
116
+ this.phaseIndex.delete(key);
117
+ }
118
+ }
92
119
  }
93
120
  }
94
121
  //# sourceMappingURL=issue-tracker.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"issue-tracker.js","sourceRoot":"","sources":["../../src/autopilot/issue-tracker.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"issue-tracker.js","sourceRoot":"","sources":["../../src/autopilot/issue-tracker.ts"],"names":[],"mappings":"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"}
@@ -44,6 +44,8 @@ export declare class QualityGateEngine {
44
44
  private skipPatterns;
45
45
  private conventionStandards;
46
46
  private static readonly MAX_HISTORY_LENGTH;
47
+ /** AI 审查结果缓存:filePath:contentHash → QualityResult(TTL 1h) */
48
+ private reviewCache;
47
49
  /** 问题台账:跨阶段追踪所有发现的问题 */
48
50
  private issueTracker;
49
51
  /** 跨阶段补充触发器:供 PhaseManager 在阶段推进时调用 */
@@ -1 +1 @@
1
- {"version":3,"file":"quality-gate.d.ts","sourceRoot":"","sources":["../../src/autopilot/quality-gate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"quality-gate.d.ts","sourceRoot":"","sources":["../../src/autopilot/quality-gate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAG1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAsB,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAG3D,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAEpD,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,YAAY,CAAC;IACpB,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,GAAG,MAAM,GAAG,aAAa,CAAC;IACnE,KAAK,EAAE,YAAY,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,GAAG,CAAa;IACxB,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,kBAAkB,CAAc;IACxC,OAAO,CAAC,gBAAgB,CAAc;IACtC,OAAO,CAAC,kBAAkB,CAAc;IACxC,OAAO,CAAC,iBAAiB,CAAc;IACvC,OAAO,CAAC,aAAa,CAAgG;IACrH,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,YAAY,CAAwG;IAC5H,OAAO,CAAC,mBAAmB,CAAyB;IACpD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAM;IAChD,6DAA6D;IAC7D,OAAO,CAAC,WAAW,CAAqG;IAExH,wBAAwB;IACxB,OAAO,CAAC,YAAY,CAAsB;IAC1C,uCAAuC;IACvC,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB,CAA2C;gBAE1E,GAAG,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,aAAa;IAOpD;;;OAGG;IACH,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI;IAW/D;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAaxB;;;OAGG;IACH,OAAO,CAAC,qBAAqB;IAqC7B;;OAEG;IACH,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAIzC;;OAEG;IACH,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAIvC,2CAA2C;IAC3C,eAAe,IAAI,YAAY;IAI/B;;;OAGG;IACH,sBAAsB,CAAC,SAAS,EAAE,eAAe,EAAE,GAAG,IAAI;IAI1D;;;OAGG;IACG,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IA4B9D;;OAEG;IACH,OAAO,CAAC,4BAA4B;IA0BpC;;OAEG;YACW,QAAQ;IA0HtB;;OAEG;IACH,iBAAiB,CAAC,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IA0BzE;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI;IAoBxD;;OAEG;IACH,cAAc,IAAI,MAAM;IAyCxB;;;OAGG;IACH,qBAAqB,IAAI,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,YAAY,EAAE,CAAA;KAAE,CAAC;IAM3E;;;OAGG;IACH,YAAY,IAAI,MAAM;IAItB;;;OAGG;IACH,YAAY,IAAI,MAAM;IAItB;;OAEG;IACH,KAAK,IAAI,IAAI;IAWb;;;OAGG;IACG,qBAAqB,CAAC,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAqF3H;;;OAGG;IACG,cAAc,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAwF5F,OAAO,CAAC,8BAA8B;IAWtC,0DAA0D;IAC1D,OAAO,CAAC,kBAAkB;IAe1B;;;;;OAKG;IACH,OAAO,CAAC,eAAe;IAevB,OAAO,CAAC,WAAW;IAyEnB,OAAO,CAAC,aAAa;CAQtB"}
@@ -2,6 +2,7 @@ import { logger } from '../utils/logger.js';
2
2
  import { memoryManager } from '../utils/memory-manager.js';
3
3
  import { IssueTracker } from './issue-tracker.js';
4
4
  import { PhaseGapDetector } from './phase-gap-detector.js';
5
+ import { createHash } from 'crypto';
5
6
  /**
6
7
  * QualityGateEngine — AI 驱动的质量门禁
7
8
  *
@@ -28,6 +29,8 @@ export class QualityGateEngine {
28
29
  skipPatterns = memoryManager.register('quality:skipPatterns', { max: 20, ttl: 7 * 24 * 3600_000 }); // 7天 TTL,Map 模拟 Set
29
30
  conventionStandards = []; // 当前项目绑定的 Convention 质量规范
30
31
  static MAX_HISTORY_LENGTH = 50; // 限制历史记录长度,避免内存泄漏
32
+ /** AI 审查结果缓存:filePath:contentHash → QualityResult(TTL 1h) */
33
+ reviewCache = memoryManager.register('quality:reviewCache', { max: 200, ttl: 3600_000 });
31
34
  /** 问题台账:跨阶段追踪所有发现的问题 */
32
35
  issueTracker = new IssueTracker();
33
36
  /** 跨阶段补充触发器:供 PhaseManager 在阶段推进时调用 */
@@ -193,6 +196,14 @@ export class QualityGateEngine {
193
196
  * AI 驱动的代码审查
194
197
  */
195
198
  async aiReview(filePath, content, operation) {
199
+ // 缓存键:filePath + content hash
200
+ const contentHash = createHash('sha256').update(content).digest('hex').slice(0, 16);
201
+ const cacheKey = `${filePath}:${contentHash}`;
202
+ const cached = this.reviewCache.get(cacheKey);
203
+ if (cached) {
204
+ logger.debug(`[质量门禁] 命中缓存:${filePath}`);
205
+ return cached;
206
+ }
196
207
  // 构建审查上下文
197
208
  const suppressedCategories = Array.from(this.skipPatterns.keys());
198
209
  const prompt = `你是一个资深代码审查员。请审查以下代码变更。
@@ -236,8 +247,11 @@ ${suppressedCategories.length > 0 ? `## 已抑制的检查类别(不要重复
236
247
  - security fail 的阈值最低(任何安全问题都应 fail)
237
248
  - test 和 quality 的 warn 可以接受
238
249
  - 只输出 JSON`;
250
+ logger.debug(`[质量门禁] 正在审查 ${filePath}…`);
239
251
  const response = await this.api.complete(prompt, 'quality-gate');
240
252
  const result = this.parseResult(response, filePath);
253
+ // 缓存结果
254
+ this.reviewCache.set(cacheKey, result);
241
255
  // v5 新增:检测历史问题是否已修复
242
256
  this.markHistoricalIssuesResolved(filePath, result);
243
257
  // v5 新增:记录到数据库