@dommaker/harness 0.7.3 → 0.7.4
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 +239 -2
- package/dist/architecture/constraint-engine.d.ts +49 -0
- package/dist/architecture/constraint-engine.d.ts.map +1 -0
- package/dist/architecture/constraint-engine.js +207 -0
- package/dist/architecture/constraint-engine.js.map +1 -0
- package/dist/architecture/cross-project-checker.d.ts +34 -0
- package/dist/architecture/cross-project-checker.d.ts.map +1 -0
- package/dist/architecture/cross-project-checker.js +260 -0
- package/dist/architecture/cross-project-checker.js.map +1 -0
- package/dist/context/progressive-loader.d.ts +110 -0
- package/dist/context/progressive-loader.d.ts.map +1 -0
- package/dist/context/progressive-loader.js +183 -0
- package/dist/context/progressive-loader.js.map +1 -0
- package/dist/context/token-budget.d.ts +144 -0
- package/dist/context/token-budget.d.ts.map +1 -0
- package/dist/context/token-budget.js +264 -0
- package/dist/context/token-budget.js.map +1 -0
- package/dist/core/constraints/definitions.d.ts.map +1 -1
- package/dist/core/constraints/definitions.js +33 -0
- package/dist/core/constraints/definitions.js.map +1 -1
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +4 -0
- package/dist/core/index.js.map +1 -1
- package/dist/failure/classifier.d.ts +63 -0
- package/dist/failure/classifier.d.ts.map +1 -0
- package/dist/failure/classifier.js +123 -0
- package/dist/failure/classifier.js.map +1 -0
- package/dist/failure/index.d.ts +10 -0
- package/dist/failure/index.d.ts.map +1 -0
- package/dist/failure/index.js +36 -0
- package/dist/failure/index.js.map +1 -0
- package/dist/failure/recorder.d.ts +78 -0
- package/dist/failure/recorder.d.ts.map +1 -0
- package/dist/failure/recorder.js +193 -0
- package/dist/failure/recorder.js.map +1 -0
- package/dist/failure/types.d.ts +89 -0
- package/dist/failure/types.d.ts.map +1 -0
- package/dist/failure/types.js +121 -0
- package/dist/failure/types.js.map +1 -0
- package/dist/gates/acceptance.d.ts +159 -0
- package/dist/gates/acceptance.d.ts.map +1 -0
- package/dist/gates/acceptance.js +368 -0
- package/dist/gates/acceptance.js.map +1 -0
- package/dist/gates/index.d.ts +5 -2
- package/dist/gates/index.d.ts.map +1 -1
- package/dist/gates/index.js +8 -1
- package/dist/gates/index.js.map +1 -1
- package/dist/gates/types.d.ts +33 -0
- package/dist/gates/types.d.ts.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -5
- package/dist/index.js.map +1 -1
- package/dist/monitoring/index.d.ts +6 -0
- package/dist/monitoring/index.d.ts.map +1 -1
- package/dist/monitoring/index.js +6 -0
- package/dist/monitoring/index.js.map +1 -1
- package/dist/monitoring/performance-analyzer.d.ts +104 -0
- package/dist/monitoring/performance-analyzer.d.ts.map +1 -0
- package/dist/monitoring/performance-analyzer.js +417 -0
- package/dist/monitoring/performance-analyzer.js.map +1 -0
- package/dist/monitoring/performance-collector.d.ts +111 -0
- package/dist/monitoring/performance-collector.d.ts.map +1 -0
- package/dist/monitoring/performance-collector.js +319 -0
- package/dist/monitoring/performance-collector.js.map +1 -0
- package/dist/monitoring/trace-analyzer.js +1 -1
- package/dist/monitoring/trace-analyzer.js.map +1 -1
- package/dist/monitoring/traces.js +1 -1
- package/dist/monitoring/traces.js.map +1 -1
- package/dist/presets/index.d.ts +0 -1
- package/dist/presets/index.d.ts.map +1 -1
- package/dist/presets/index.js +1 -6
- package/dist/presets/index.js.map +1 -1
- package/dist/spec/annotation-checker.d.ts +47 -0
- package/dist/spec/annotation-checker.d.ts.map +1 -0
- package/dist/spec/annotation-checker.js +299 -0
- package/dist/spec/annotation-checker.js.map +1 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +9 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/performance.d.ts +204 -0
- package/dist/types/performance.d.ts.map +1 -0
- package/dist/types/performance.js +12 -0
- package/dist/types/performance.js.map +1 -0
- package/package.json +3 -1
- package/dist/extensions/long-running/constraints.d.ts +0 -38
- package/dist/extensions/long-running/constraints.d.ts.map +0 -1
- package/dist/extensions/long-running/constraints.js +0 -153
- package/dist/extensions/long-running/constraints.js.map +0 -1
- package/dist/extensions/long-running/index.d.ts +0 -30
- package/dist/extensions/long-running/index.d.ts.map +0 -1
- package/dist/extensions/long-running/index.js +0 -50
- package/dist/extensions/long-running/index.js.map +0 -1
- package/dist/extensions/long-running/types.d.ts +0 -154
- package/dist/extensions/long-running/types.d.ts.map +0 -1
- package/dist/extensions/long-running/types.js +0 -9
- package/dist/extensions/long-running/types.js.map +0 -1
- package/dist/presets/long-running.d.ts +0 -33
- package/dist/presets/long-running.d.ts.map +0 -1
- package/dist/presets/long-running.js +0 -52
- package/dist/presets/long-running.js.map +0 -1
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* 跨工程接口契约检查
|
|
4
|
+
*
|
|
5
|
+
* 检测多工程开发时的接口不一致问题
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
+
var ownKeys = function(o) {
|
|
25
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
+
var ar = [];
|
|
27
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
+
return ar;
|
|
29
|
+
};
|
|
30
|
+
return ownKeys(o);
|
|
31
|
+
};
|
|
32
|
+
return function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
})();
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
exports.checkCrossProjectContracts = checkCrossProjectContracts;
|
|
42
|
+
exports.checkDocCodeConsistency = checkDocCodeConsistency;
|
|
43
|
+
const child_process_1 = require("child_process");
|
|
44
|
+
const path = __importStar(require("path"));
|
|
45
|
+
// 工程依赖关系图
|
|
46
|
+
const PROJECT_DEPENDENCIES = {
|
|
47
|
+
'agent-studio': ['agent-runtime', 'harness'],
|
|
48
|
+
'agent-runtime': ['harness', 'agent-workflows'],
|
|
49
|
+
'agent-workflows': ['harness'],
|
|
50
|
+
'harness': [],
|
|
51
|
+
};
|
|
52
|
+
// 接口契约定义位置
|
|
53
|
+
const CONTRACT_LOCATIONS = {
|
|
54
|
+
'studio-runtime': [
|
|
55
|
+
'agent-runtime/src/api/types.ts', // runtime 导出的 API 类型
|
|
56
|
+
'agent-studio/src/services/runtime-client.ts', // studio 调用 runtime 的客户端
|
|
57
|
+
],
|
|
58
|
+
'runtime-harness': [
|
|
59
|
+
'harness/src/index.ts', // harness 导出
|
|
60
|
+
'agent-runtime/src/core/harness-adapter.ts', // runtime 使用 harness
|
|
61
|
+
],
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* 检查跨工程接口一致性
|
|
65
|
+
*/
|
|
66
|
+
async function checkCrossProjectContracts(context) {
|
|
67
|
+
const violations = [];
|
|
68
|
+
// 1. 检查 API 变更是否同步到调用方
|
|
69
|
+
violations.push(...await checkApiSync(context));
|
|
70
|
+
// 2. 检查类型定义一致性
|
|
71
|
+
violations.push(...await checkTypeConsistency(context));
|
|
72
|
+
// 3. 检查破坏性变更
|
|
73
|
+
violations.push(...await checkBreakingChanges(context));
|
|
74
|
+
return violations;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* 检查 API 变更同步
|
|
78
|
+
* 场景:改了 runtime API,studio 没更新
|
|
79
|
+
*/
|
|
80
|
+
async function checkApiSync(context) {
|
|
81
|
+
const violations = [];
|
|
82
|
+
// 检查 runtime API 变更
|
|
83
|
+
if (context.changedProjects.includes('agent-runtime')) {
|
|
84
|
+
const runtimeApiChanges = getApiChanges('agent-runtime', context.baseBranch);
|
|
85
|
+
for (const change of runtimeApiChanges) {
|
|
86
|
+
// 检查 studio 是否同步更新
|
|
87
|
+
const studioUpdated = context.changedFiles.some(f => f.includes('agent-studio/src/services/') ||
|
|
88
|
+
f.includes('agent-studio/src/api/'));
|
|
89
|
+
if (!studioUpdated && isPublicApi(change)) {
|
|
90
|
+
violations.push({
|
|
91
|
+
type: 'api-mismatch',
|
|
92
|
+
severity: 'error',
|
|
93
|
+
message: `Runtime API '${change.name}' 变更未同步到 Studio`,
|
|
94
|
+
fromProject: 'agent-runtime',
|
|
95
|
+
toProject: 'agent-studio',
|
|
96
|
+
details: {
|
|
97
|
+
interfaceName: change.name,
|
|
98
|
+
location: change.file,
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return violations;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* 检查类型定义一致性
|
|
108
|
+
* 场景:同一接口在不同工程定义不一致
|
|
109
|
+
*/
|
|
110
|
+
async function checkTypeConsistency(context) {
|
|
111
|
+
const violations = [];
|
|
112
|
+
// 检查 harness 类型是否在 runtime 中一致使用
|
|
113
|
+
const harnessTypes = extractExportedTypes('harness');
|
|
114
|
+
const runtimeUsage = extractTypeUsage('agent-runtime', harnessTypes);
|
|
115
|
+
for (const [typeName, usage] of Object.entries(runtimeUsage)) {
|
|
116
|
+
if (usage.hasMismatch) {
|
|
117
|
+
violations.push({
|
|
118
|
+
type: 'doc-code-mismatch',
|
|
119
|
+
severity: 'error',
|
|
120
|
+
message: `类型 '${typeName}' 在 runtime 中的使用与 harness 定义不一致`,
|
|
121
|
+
fromProject: 'harness',
|
|
122
|
+
toProject: 'agent-runtime',
|
|
123
|
+
details: {
|
|
124
|
+
interfaceName: typeName,
|
|
125
|
+
expectedType: usage.expected,
|
|
126
|
+
actualType: usage.actual,
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return violations;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* 检查破坏性变更
|
|
135
|
+
*/
|
|
136
|
+
async function checkBreakingChanges(context) {
|
|
137
|
+
const violations = [];
|
|
138
|
+
for (const project of context.changedProjects) {
|
|
139
|
+
const dependents = getDependents(project);
|
|
140
|
+
for (const change of getApiChanges(project, context.baseBranch)) {
|
|
141
|
+
if (isBreakingChange(change)) {
|
|
142
|
+
// 检查所有依赖方是否已适配
|
|
143
|
+
for (const dependent of dependents) {
|
|
144
|
+
const adapted = context.changedProjects.includes(dependent);
|
|
145
|
+
if (!adapted) {
|
|
146
|
+
violations.push({
|
|
147
|
+
type: 'breaking-change',
|
|
148
|
+
severity: 'error',
|
|
149
|
+
message: `破坏性变更 '${change.name}' 需要 ${dependent} 适配`,
|
|
150
|
+
fromProject: project,
|
|
151
|
+
toProject: dependent,
|
|
152
|
+
details: {
|
|
153
|
+
interfaceName: change.name,
|
|
154
|
+
location: change.file,
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return violations;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* 检查文档-代码一致性
|
|
166
|
+
* 场景:文档写了接口,代码没实现
|
|
167
|
+
*/
|
|
168
|
+
async function checkDocCodeConsistency(docPath, projects) {
|
|
169
|
+
const violations = [];
|
|
170
|
+
// 解析文档中的接口定义
|
|
171
|
+
const docInterfaces = parseDocInterfaces(docPath);
|
|
172
|
+
for (const [project, interfaces] of Object.entries(docInterfaces)) {
|
|
173
|
+
if (!projects.includes(project))
|
|
174
|
+
continue;
|
|
175
|
+
const actualExports = extractExportedApis(project);
|
|
176
|
+
for (const docInterface of interfaces) {
|
|
177
|
+
const implemented = actualExports.find(e => e.name === docInterface.name);
|
|
178
|
+
if (!implemented) {
|
|
179
|
+
violations.push({
|
|
180
|
+
type: 'missing-implementation',
|
|
181
|
+
severity: 'error',
|
|
182
|
+
message: `文档接口 '${docInterface.name}' 在 ${project} 中未实现`,
|
|
183
|
+
fromProject: 'documentation',
|
|
184
|
+
toProject: project,
|
|
185
|
+
details: {
|
|
186
|
+
interfaceName: docInterface.name,
|
|
187
|
+
location: docPath,
|
|
188
|
+
},
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
else if (!isCompatible(docInterface, implemented)) {
|
|
192
|
+
violations.push({
|
|
193
|
+
type: 'doc-code-mismatch',
|
|
194
|
+
severity: 'warning',
|
|
195
|
+
message: `接口 '${docInterface.name}' 实现与文档不一致`,
|
|
196
|
+
fromProject: 'documentation',
|
|
197
|
+
toProject: project,
|
|
198
|
+
details: {
|
|
199
|
+
interfaceName: docInterface.name,
|
|
200
|
+
expectedType: JSON.stringify(docInterface.signature),
|
|
201
|
+
actualType: JSON.stringify(implemented.signature),
|
|
202
|
+
},
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return violations;
|
|
208
|
+
}
|
|
209
|
+
// ============ 辅助函数 ============
|
|
210
|
+
function getApiChanges(project, baseBranch) {
|
|
211
|
+
try {
|
|
212
|
+
const output = (0, child_process_1.execSync)(`git diff ${baseBranch}...HEAD --name-only -- "projects/${project}/src/api/**/*"`, { encoding: 'utf-8' });
|
|
213
|
+
return output.trim().split('\n').filter(f => f).map(f => ({
|
|
214
|
+
file: f,
|
|
215
|
+
name: extractApiName(f),
|
|
216
|
+
changeType: detectChangeType(f),
|
|
217
|
+
}));
|
|
218
|
+
}
|
|
219
|
+
catch {
|
|
220
|
+
return [];
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
function isPublicApi(change) {
|
|
224
|
+
// 检查是否为公开 API(导出、非内部)
|
|
225
|
+
return !change.name.startsWith('_') && !change.file.includes('/internal/');
|
|
226
|
+
}
|
|
227
|
+
function isBreakingChange(change) {
|
|
228
|
+
// 检测是否为破坏性变更
|
|
229
|
+
return change.changeType === 'remove' ||
|
|
230
|
+
change.changeType === 'signature-change' ||
|
|
231
|
+
change.changeType === 'rename';
|
|
232
|
+
}
|
|
233
|
+
function getDependents(project) {
|
|
234
|
+
return Object.entries(PROJECT_DEPENDENCIES)
|
|
235
|
+
.filter(([_, deps]) => deps.includes(project))
|
|
236
|
+
.map(([name, _]) => name);
|
|
237
|
+
}
|
|
238
|
+
// 占位函数(需要具体实现)
|
|
239
|
+
function extractApiName(file) {
|
|
240
|
+
return path.basename(file, '.ts');
|
|
241
|
+
}
|
|
242
|
+
function detectChangeType(file) {
|
|
243
|
+
return 'modify';
|
|
244
|
+
}
|
|
245
|
+
function extractExportedTypes(project) {
|
|
246
|
+
return [];
|
|
247
|
+
}
|
|
248
|
+
function extractTypeUsage(project, types) {
|
|
249
|
+
return {};
|
|
250
|
+
}
|
|
251
|
+
function parseDocInterfaces(docPath) {
|
|
252
|
+
return {};
|
|
253
|
+
}
|
|
254
|
+
function extractExportedApis(project) {
|
|
255
|
+
return [];
|
|
256
|
+
}
|
|
257
|
+
function isCompatible(doc, actual) {
|
|
258
|
+
return JSON.stringify(doc.signature) === JSON.stringify(actual.signature);
|
|
259
|
+
}
|
|
260
|
+
//# sourceMappingURL=cross-project-checker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cross-project-checker.js","sourceRoot":"","sources":["../../src/architecture/cross-project-checker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @spec HZ-002
|
|
3
|
+
* @implements HZ-002-C1
|
|
4
|
+
* @acceptance AC-001-1, AC-001-4
|
|
5
|
+
*
|
|
6
|
+
* Progressive Content Loader
|
|
7
|
+
*
|
|
8
|
+
* 通用内容分片加载能力
|
|
9
|
+
* - 支持大数据集分片加载
|
|
10
|
+
* - 支持 Token 预算管理
|
|
11
|
+
* - 零业务逻辑,可被任意系统使用
|
|
12
|
+
*/
|
|
13
|
+
export interface ChunkLoadOptions<T = any> {
|
|
14
|
+
/** 每片大小 */
|
|
15
|
+
chunkSize: number;
|
|
16
|
+
/** 每片加载回调 */
|
|
17
|
+
onChunk?: (chunk: T[], index: number) => Promise<void> | void;
|
|
18
|
+
/** 进度回调 (loaded, total) */
|
|
19
|
+
onProgress?: (loaded: number, total: number) => void;
|
|
20
|
+
/** 是否并行加载 */
|
|
21
|
+
parallel?: boolean;
|
|
22
|
+
/** 延迟(毫秒),用于节流 */
|
|
23
|
+
delay?: number;
|
|
24
|
+
}
|
|
25
|
+
export interface TokenBudgetOptions<T = any> {
|
|
26
|
+
/** Token 预算 */
|
|
27
|
+
budget: number;
|
|
28
|
+
/** Token 估算函数 */
|
|
29
|
+
estimator: (item: T) => number;
|
|
30
|
+
/** 预算超限策略 */
|
|
31
|
+
onBudgetExceeded?: 'truncate' | 'error' | 'skip';
|
|
32
|
+
/** 最小保留项数(即使超预算) */
|
|
33
|
+
minItems?: number;
|
|
34
|
+
}
|
|
35
|
+
export interface LoadResult<T> {
|
|
36
|
+
/** 加载的项 */
|
|
37
|
+
items: T[];
|
|
38
|
+
/** 实际消耗的 Token */
|
|
39
|
+
tokensUsed: number;
|
|
40
|
+
/** 是否被截断 */
|
|
41
|
+
truncated: boolean;
|
|
42
|
+
/** 跳过的项数 */
|
|
43
|
+
skipped: number;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* 渐进式内容加载器
|
|
47
|
+
*
|
|
48
|
+
* 提供通用的内容分片加载和 Token 预算管理能力
|
|
49
|
+
*/
|
|
50
|
+
export declare class ProgressiveLoader {
|
|
51
|
+
/**
|
|
52
|
+
* 分片加载
|
|
53
|
+
*
|
|
54
|
+
* 将大数据集分片加载,避免一次性加载全部内容
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```typescript
|
|
58
|
+
* const loader = new ProgressiveLoader();
|
|
59
|
+
* const largeData = Array.from({ length: 1000 }, (_, i) => ({ id: i }));
|
|
60
|
+
*
|
|
61
|
+
* await loader.loadInChunks(largeData, {
|
|
62
|
+
* chunkSize: 100,
|
|
63
|
+
* onChunk: async (chunk, index) => {
|
|
64
|
+
* console.log(`Loaded chunk ${index}: ${chunk.length} items`);
|
|
65
|
+
* },
|
|
66
|
+
* onProgress: (loaded, total) => {
|
|
67
|
+
* console.log(`Progress: ${loaded}/${total}`);
|
|
68
|
+
* }
|
|
69
|
+
* });
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
loadInChunks<T>(items: T[], options: ChunkLoadOptions<T>): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* Token 预算加载
|
|
75
|
+
*
|
|
76
|
+
* 在 Token 预算范围内加载内容,超预算时按策略处理
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```typescript
|
|
80
|
+
* const loader = new ProgressiveLoader();
|
|
81
|
+
* const items = [
|
|
82
|
+
* { content: 'short text' },
|
|
83
|
+
* { content: 'long text '.repeat(100) }
|
|
84
|
+
* ];
|
|
85
|
+
*
|
|
86
|
+
* const result = await loader.loadWithBudget(items, {
|
|
87
|
+
* budget: 1000,
|
|
88
|
+
* estimator: (item) => item.content.length,
|
|
89
|
+
* onBudgetExceeded: 'truncate'
|
|
90
|
+
* });
|
|
91
|
+
*
|
|
92
|
+
* console.log(`Loaded ${result.items.length} items, used ${result.tokensUsed} tokens`);
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
loadWithBudget<T>(items: T[], options: TokenBudgetOptions<T>): Promise<LoadResult<T>>;
|
|
96
|
+
/**
|
|
97
|
+
* 创建流式加载器
|
|
98
|
+
*
|
|
99
|
+
* 支持大文件/大内容的流式分片加载
|
|
100
|
+
*/
|
|
101
|
+
createStream<T>(source: AsyncIterable<T>, chunkSize: number): AsyncIterable<T[]>;
|
|
102
|
+
/**
|
|
103
|
+
* 批量处理(带并发控制)
|
|
104
|
+
*/
|
|
105
|
+
processBatch<T, R>(items: T[], processor: (item: T) => Promise<R>, concurrency?: number): Promise<R[]>;
|
|
106
|
+
private processChunk;
|
|
107
|
+
private sleep;
|
|
108
|
+
}
|
|
109
|
+
export declare const progressiveLoader: ProgressiveLoader;
|
|
110
|
+
//# sourceMappingURL=progressive-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"progressive-loader.d.ts","sourceRoot":"","sources":["../../src/context/progressive-loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,gBAAgB,CAAC,CAAC,GAAG,GAAG;IACvC,WAAW;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa;IACb,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC9D,2BAA2B;IAC3B,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACrD,aAAa;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,kBAAkB;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB,CAAC,CAAC,GAAG,GAAG;IACzC,eAAe;IACf,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB;IACjB,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;IAC/B,aAAa;IACb,gBAAgB,CAAC,EAAE,UAAU,GAAG,OAAO,GAAG,MAAM,CAAC;IACjD,oBAAoB;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,WAAW;IACX,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,kBAAkB;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY;IACZ,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY;IACZ,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,qBAAa,iBAAiB;IAC5B;;;;;;;;;;;;;;;;;;;;OAoBG;IACG,YAAY,CAAC,CAAC,EAClB,KAAK,EAAE,CAAC,EAAE,EACV,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAC3B,OAAO,CAAC,IAAI,CAAC;IAgChB;;;;;;;;;;;;;;;;;;;;;OAqBG;IACG,cAAc,CAAC,CAAC,EACpB,KAAK,EAAE,CAAC,EAAE,EACV,OAAO,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAC7B,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAkDzB;;;;OAIG;IACI,YAAY,CAAC,CAAC,EACnB,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,EACxB,SAAS,EAAE,MAAM,GAChB,aAAa,CAAC,CAAC,EAAE,CAAC;IAkBrB;;OAEG;IACG,YAAY,CAAC,CAAC,EAAE,CAAC,EACrB,KAAK,EAAE,CAAC,EAAE,EACV,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,EAClC,WAAW,GAAE,MAAU,GACtB,OAAO,CAAC,CAAC,EAAE,CAAC;YAwBD,YAAY;IAiB1B,OAAO,CAAC,KAAK;CAGd;AAGD,eAAO,MAAM,iBAAiB,mBAA0B,CAAC"}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @spec HZ-002
|
|
4
|
+
* @implements HZ-002-C1
|
|
5
|
+
* @acceptance AC-001-1, AC-001-4
|
|
6
|
+
*
|
|
7
|
+
* Progressive Content Loader
|
|
8
|
+
*
|
|
9
|
+
* 通用内容分片加载能力
|
|
10
|
+
* - 支持大数据集分片加载
|
|
11
|
+
* - 支持 Token 预算管理
|
|
12
|
+
* - 零业务逻辑,可被任意系统使用
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.progressiveLoader = exports.ProgressiveLoader = void 0;
|
|
16
|
+
/**
|
|
17
|
+
* 渐进式内容加载器
|
|
18
|
+
*
|
|
19
|
+
* 提供通用的内容分片加载和 Token 预算管理能力
|
|
20
|
+
*/
|
|
21
|
+
class ProgressiveLoader {
|
|
22
|
+
/**
|
|
23
|
+
* 分片加载
|
|
24
|
+
*
|
|
25
|
+
* 将大数据集分片加载,避免一次性加载全部内容
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* const loader = new ProgressiveLoader();
|
|
30
|
+
* const largeData = Array.from({ length: 1000 }, (_, i) => ({ id: i }));
|
|
31
|
+
*
|
|
32
|
+
* await loader.loadInChunks(largeData, {
|
|
33
|
+
* chunkSize: 100,
|
|
34
|
+
* onChunk: async (chunk, index) => {
|
|
35
|
+
* console.log(`Loaded chunk ${index}: ${chunk.length} items`);
|
|
36
|
+
* },
|
|
37
|
+
* onProgress: (loaded, total) => {
|
|
38
|
+
* console.log(`Progress: ${loaded}/${total}`);
|
|
39
|
+
* }
|
|
40
|
+
* });
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
async loadInChunks(items, options) {
|
|
44
|
+
const { chunkSize, onChunk, onProgress, parallel = false, delay = 0 } = options;
|
|
45
|
+
const total = items.length;
|
|
46
|
+
const chunks = [];
|
|
47
|
+
// 分片
|
|
48
|
+
for (let i = 0; i < total; i += chunkSize) {
|
|
49
|
+
chunks.push(items.slice(i, i + chunkSize));
|
|
50
|
+
}
|
|
51
|
+
// 加载
|
|
52
|
+
if (parallel) {
|
|
53
|
+
// 并行加载
|
|
54
|
+
await Promise.all(chunks.map(async (chunk, index) => {
|
|
55
|
+
if (delay > 0) {
|
|
56
|
+
await this.sleep(delay * index);
|
|
57
|
+
}
|
|
58
|
+
await this.processChunk(chunk, index, onChunk, onProgress, total);
|
|
59
|
+
}));
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
// 串行加载
|
|
63
|
+
for (let i = 0; i < chunks.length; i++) {
|
|
64
|
+
if (delay > 0 && i > 0) {
|
|
65
|
+
await this.sleep(delay);
|
|
66
|
+
}
|
|
67
|
+
await this.processChunk(chunks[i], i, onChunk, onProgress, total);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Token 预算加载
|
|
73
|
+
*
|
|
74
|
+
* 在 Token 预算范围内加载内容,超预算时按策略处理
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```typescript
|
|
78
|
+
* const loader = new ProgressiveLoader();
|
|
79
|
+
* const items = [
|
|
80
|
+
* { content: 'short text' },
|
|
81
|
+
* { content: 'long text '.repeat(100) }
|
|
82
|
+
* ];
|
|
83
|
+
*
|
|
84
|
+
* const result = await loader.loadWithBudget(items, {
|
|
85
|
+
* budget: 1000,
|
|
86
|
+
* estimator: (item) => item.content.length,
|
|
87
|
+
* onBudgetExceeded: 'truncate'
|
|
88
|
+
* });
|
|
89
|
+
*
|
|
90
|
+
* console.log(`Loaded ${result.items.length} items, used ${result.tokensUsed} tokens`);
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
async loadWithBudget(items, options) {
|
|
94
|
+
const { budget, estimator, onBudgetExceeded = 'truncate', minItems = 1 } = options;
|
|
95
|
+
const result = {
|
|
96
|
+
items: [],
|
|
97
|
+
tokensUsed: 0,
|
|
98
|
+
truncated: false,
|
|
99
|
+
skipped: 0
|
|
100
|
+
};
|
|
101
|
+
let currentBudget = budget;
|
|
102
|
+
for (const item of items) {
|
|
103
|
+
const itemTokens = estimator(item);
|
|
104
|
+
// 检查预算
|
|
105
|
+
if (itemTokens > currentBudget) {
|
|
106
|
+
// 预算超限
|
|
107
|
+
if (result.items.length >= minItems) {
|
|
108
|
+
// 已达到最小项数,按策略处理
|
|
109
|
+
switch (onBudgetExceeded) {
|
|
110
|
+
case 'truncate':
|
|
111
|
+
result.truncated = true;
|
|
112
|
+
return result;
|
|
113
|
+
case 'error':
|
|
114
|
+
throw new Error(`Token budget exceeded: need ${itemTokens}, remaining ${currentBudget}`);
|
|
115
|
+
case 'skip':
|
|
116
|
+
result.skipped++;
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// 未达到最小项数,强制添加(可能超预算)
|
|
121
|
+
}
|
|
122
|
+
// 添加项
|
|
123
|
+
result.items.push(item);
|
|
124
|
+
result.tokensUsed += itemTokens;
|
|
125
|
+
currentBudget -= itemTokens;
|
|
126
|
+
}
|
|
127
|
+
return result;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* 创建流式加载器
|
|
131
|
+
*
|
|
132
|
+
* 支持大文件/大内容的流式分片加载
|
|
133
|
+
*/
|
|
134
|
+
async *createStream(source, chunkSize) {
|
|
135
|
+
let chunk = [];
|
|
136
|
+
for await (const item of source) {
|
|
137
|
+
chunk.push(item);
|
|
138
|
+
if (chunk.length >= chunkSize) {
|
|
139
|
+
yield chunk;
|
|
140
|
+
chunk = [];
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// yield remaining items
|
|
144
|
+
if (chunk.length > 0) {
|
|
145
|
+
yield chunk;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* 批量处理(带并发控制)
|
|
150
|
+
*/
|
|
151
|
+
async processBatch(items, processor, concurrency = 5) {
|
|
152
|
+
const results = [];
|
|
153
|
+
const executing = [];
|
|
154
|
+
for (const item of items) {
|
|
155
|
+
const promise = processor(item).then(result => {
|
|
156
|
+
results.push(result);
|
|
157
|
+
});
|
|
158
|
+
executing.push(promise);
|
|
159
|
+
if (executing.length >= concurrency) {
|
|
160
|
+
await Promise.race(executing);
|
|
161
|
+
executing.splice(executing.findIndex(p => p === promise), 1);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
await Promise.all(executing);
|
|
165
|
+
return results;
|
|
166
|
+
}
|
|
167
|
+
async processChunk(chunk, index, onChunk, onProgress, total) {
|
|
168
|
+
if (onChunk) {
|
|
169
|
+
await onChunk(chunk, index);
|
|
170
|
+
}
|
|
171
|
+
if (onProgress) {
|
|
172
|
+
const loaded = Math.min((index + 1) * chunk.length, total);
|
|
173
|
+
onProgress(loaded, total);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
sleep(ms) {
|
|
177
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
exports.ProgressiveLoader = ProgressiveLoader;
|
|
181
|
+
// 默认实例
|
|
182
|
+
exports.progressiveLoader = new ProgressiveLoader();
|
|
183
|
+
//# sourceMappingURL=progressive-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"progressive-loader.js","sourceRoot":"","sources":["../../src/context/progressive-loader.ts"],"names":[],"mappings":"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"}
|