@hddz/plugin-harness 0.1.19 → 0.2.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.
Potentially problematic release.
This version of @hddz/plugin-harness might be problematic. Click here for more details.
- package/README.md +97 -114
- package/dist/core/auditors/index.d.ts +2 -0
- package/dist/core/auditors/index.js +7 -0
- package/dist/core/auditors/skill-auditor.d.ts +72 -0
- package/dist/core/auditors/skill-auditor.js +488 -0
- package/dist/core/index.d.ts +22 -0
- package/dist/core/index.js +47 -0
- package/dist/core/loggers/config-logger.d.ts +25 -0
- package/dist/core/loggers/config-logger.js +139 -0
- package/dist/core/loggers/index.d.ts +4 -0
- package/dist/core/loggers/index.js +9 -0
- package/dist/core/loggers/operation-logger.d.ts +23 -0
- package/dist/core/loggers/operation-logger.js +125 -0
- package/dist/core/middleware/context-injector.d.ts +25 -0
- package/dist/core/middleware/context-injector.js +174 -0
- package/dist/core/middleware/index.d.ts +5 -0
- package/dist/core/middleware/index.js +11 -0
- package/dist/core/middleware/loop-detector.d.ts +18 -0
- package/dist/core/middleware/loop-detector.js +125 -0
- package/dist/core/middleware/trace-logger.d.ts +34 -0
- package/dist/core/middleware/trace-logger.js +141 -0
- package/dist/core/utils/file.d.ts +28 -0
- package/dist/core/utils/file.js +104 -0
- package/dist/core/utils/format.d.ts +16 -0
- package/dist/core/utils/format.js +60 -0
- package/dist/core/utils/index.d.ts +2 -0
- package/dist/core/utils/index.js +14 -0
- package/dist/core/validators/config-validator.d.ts +25 -0
- package/dist/core/validators/config-validator.js +235 -0
- package/dist/core/validators/index.d.ts +2 -0
- package/dist/core/validators/index.js +7 -0
- package/dist/file-watcher.d.ts +37 -0
- package/dist/file-watcher.js +151 -0
- package/dist/index.d.ts +63 -0
- package/dist/index.js +166 -106
- package/dist/src/file-watcher.d.ts +37 -0
- package/dist/src/file-watcher.js +151 -0
- package/dist/src/index.d.ts +70 -0
- package/dist/src/index.js +192 -0
- package/package.json +4 -12
- package/openclaw.plugin.json +0 -39
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// src/middleware/loop-detector.ts - 循环检测中间件
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
exports.LoopDetector = void 0;
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
class LoopDetector {
|
|
41
|
+
workspacePath;
|
|
42
|
+
fileEditCounts = new Map();
|
|
43
|
+
stateFilePath;
|
|
44
|
+
config;
|
|
45
|
+
constructor(workspacePath, config = {}) {
|
|
46
|
+
this.workspacePath = workspacePath;
|
|
47
|
+
this.config = {
|
|
48
|
+
limit: 5,
|
|
49
|
+
windowMs: 300000, // 5 分钟
|
|
50
|
+
warningMessage: `⚠️ 警告:{file} 已被修改 {count} 次({window}分钟内)\n` +
|
|
51
|
+
'请考虑:\n' +
|
|
52
|
+
'1. 重新阅读任务规格\n' +
|
|
53
|
+
'2. 检查是否有根本性设计问题\n' +
|
|
54
|
+
'3. 考虑寻求人类帮助',
|
|
55
|
+
...config,
|
|
56
|
+
};
|
|
57
|
+
// 状态持久化文件
|
|
58
|
+
const logsDir = path.join(workspacePath, 'logs');
|
|
59
|
+
if (!fs.existsSync(logsDir)) {
|
|
60
|
+
fs.mkdirSync(logsDir, { recursive: true });
|
|
61
|
+
}
|
|
62
|
+
this.stateFilePath = path.join(logsDir, 'loop-detector-state.json');
|
|
63
|
+
// 加载之前的状态
|
|
64
|
+
this.loadState();
|
|
65
|
+
}
|
|
66
|
+
loadState() {
|
|
67
|
+
try {
|
|
68
|
+
if (fs.existsSync(this.stateFilePath)) {
|
|
69
|
+
const data = fs.readFileSync(this.stateFilePath, 'utf8');
|
|
70
|
+
const state = JSON.parse(data);
|
|
71
|
+
this.fileEditCounts = new Map(Object.entries(state));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
// 忽略加载错误,从空状态开始
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
saveState() {
|
|
79
|
+
try {
|
|
80
|
+
const state = Object.fromEntries(this.fileEditCounts);
|
|
81
|
+
fs.writeFileSync(this.stateFilePath, JSON.stringify(state, null, 2));
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
// 忽略保存错误
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
onFileEdit(filePath) {
|
|
88
|
+
const now = Date.now();
|
|
89
|
+
const edits = this.fileEditCounts.get(filePath) || [];
|
|
90
|
+
// 移除超出时间窗口的记录
|
|
91
|
+
const windowStart = now - this.config.windowMs;
|
|
92
|
+
const recentEdits = edits.filter(time => time > windowStart);
|
|
93
|
+
recentEdits.push(now);
|
|
94
|
+
this.fileEditCounts.set(filePath, recentEdits);
|
|
95
|
+
this.saveState();
|
|
96
|
+
if (recentEdits.length >= this.config.limit) {
|
|
97
|
+
return this.config.warningMessage
|
|
98
|
+
.replace('{file}', filePath)
|
|
99
|
+
.replace('{count}', recentEdits.length.toString())
|
|
100
|
+
.replace('{window}', (this.config.windowMs / 60000).toString());
|
|
101
|
+
}
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
reset(filePath) {
|
|
105
|
+
if (filePath) {
|
|
106
|
+
this.fileEditCounts.delete(filePath);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
this.fileEditCounts.clear();
|
|
110
|
+
}
|
|
111
|
+
this.saveState();
|
|
112
|
+
}
|
|
113
|
+
getStats() {
|
|
114
|
+
const stats = {};
|
|
115
|
+
this.fileEditCounts.forEach((edits, file) => {
|
|
116
|
+
stats[file] = edits.length;
|
|
117
|
+
});
|
|
118
|
+
return stats;
|
|
119
|
+
}
|
|
120
|
+
getConfig() {
|
|
121
|
+
return { ...this.config };
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
exports.LoopDetector = LoopDetector;
|
|
125
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9vcC1kZXRlY3Rvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jb3JlL21pZGRsZXdhcmUvbG9vcC1kZXRlY3Rvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsNENBQTRDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFFNUMsdUNBQXlCO0FBQ3pCLDJDQUE2QjtBQVE3QixNQUFhLFlBQVk7SUFNYjtJQUxGLGNBQWMsR0FBMEIsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUNsRCxhQUFhLENBQVM7SUFDdEIsTUFBTSxDQUErQjtJQUU3QyxZQUNVLGFBQXFCLEVBQzdCLFNBQTZCLEVBQUU7UUFEdkIsa0JBQWEsR0FBYixhQUFhLENBQVE7UUFHN0IsSUFBSSxDQUFDLE1BQU0sR0FBRztZQUNaLEtBQUssRUFBRSxDQUFDO1lBQ1IsUUFBUSxFQUFFLE1BQU0sRUFBRSxPQUFPO1lBQ3pCLGNBQWMsRUFBRSw0Q0FBNEM7Z0JBQzVDLFFBQVE7Z0JBQ1IsZUFBZTtnQkFDZixtQkFBbUI7Z0JBQ25CLGFBQWE7WUFDN0IsR0FBRyxNQUFNO1NBQ1YsQ0FBQztRQUVGLFVBQVU7UUFDVixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRSxNQUFNLENBQUMsQ0FBQztRQUNqRCxJQUFJLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1lBQzVCLEVBQUUsQ0FBQyxTQUFTLENBQUMsT0FBTyxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7UUFDN0MsQ0FBQztRQUNELElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsMEJBQTBCLENBQUMsQ0FBQztRQUVwRSxVQUFVO1FBQ1YsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO0lBQ25CLENBQUM7SUFFTyxTQUFTO1FBQ2YsSUFBSSxDQUFDO1lBQ0gsSUFBSSxFQUFFLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsRUFBRSxDQUFDO2dCQUN0QyxNQUFNLElBQUksR0FBRyxFQUFFLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUUsTUFBTSxDQUFDLENBQUM7Z0JBQ3pELE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQy9CLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxHQUFHLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1lBQ3ZELENBQUM7UUFDSCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLGdCQUFnQjtRQUNsQixDQUFDO0lBQ0gsQ0FBQztJQUVPLFNBQVM7UUFDZixJQUFJLENBQUM7WUFDSCxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUN0RCxFQUFFLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDdkUsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixTQUFTO1FBQ1gsQ0FBQztJQUNILENBQUM7SUFFRCxVQUFVLENBQUMsUUFBZ0I7UUFDekIsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQ3ZCLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUV0RCxjQUFjO1FBQ2QsTUFBTSxXQUFXLEdBQUcsR0FBRyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDO1FBQy9DLE1BQU0sV0FBVyxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLEdBQUcsV0FBVyxDQUFDLENBQUM7UUFFN0QsV0FBVyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN0QixJQUFJLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsV0FBVyxDQUFDLENBQUM7UUFDL0MsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBRWpCLElBQUksV0FBVyxDQUFDLE1BQU0sSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQzVDLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxjQUFjO2lCQUM5QixPQUFPLENBQUMsUUFBUSxFQUFFLFFBQVEsQ0FBQztpQkFDM0IsT0FBTyxDQUFDLFNBQVMsRUFBRSxXQUFXLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRSxDQUFDO2lCQUNqRCxPQUFPLENBQUMsVUFBVSxFQUFFLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztRQUNwRSxDQUFDO1FBRUQsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQsS0FBSyxDQUFDLFFBQWlCO1FBQ3JCLElBQUksUUFBUSxFQUFFLENBQUM7WUFDYixJQUFJLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUN2QyxDQUFDO2FBQU0sQ0FBQztZQUNOLElBQUksQ0FBQyxjQUFjLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDOUIsQ0FBQztRQUNELElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztJQUNuQixDQUFDO0lBRUQsUUFBUTtRQUNOLE1BQU0sS0FBSyxHQUEyQixFQUFFLENBQUM7UUFDekMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLEVBQUU7WUFDMUMsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUM7UUFDN0IsQ0FBQyxDQUFDLENBQUM7UUFDSCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFFRCxTQUFTO1FBQ1AsT0FBTyxFQUFFLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO0lBQzVCLENBQUM7Q0FDRjtBQTlGRCxvQ0E4RkMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBzcmMvbWlkZGxld2FyZS9sb29wLWRldGVjdG9yLnRzIC0g5b6q546v5qOA5rWL5Lit6Ze05Lu2XG5cbmltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgTG9vcERldGVjdG9yQ29uZmlnIHtcbiAgbGltaXQ/OiBudW1iZXI7ICAgICAgICAgICAvLyDnvJbovpHmrKHmlbDpmIjlgLxcbiAgd2luZG93TXM/OiBudW1iZXI7ICAgICAgICAvLyDml7bpl7Tnqpflj6PvvIjmr6vnp5LvvIlcbiAgd2FybmluZ01lc3NhZ2U/OiBzdHJpbmc7ICAvLyDorablkYrmtojmga/mqKHmnb9cbn1cblxuZXhwb3J0IGNsYXNzIExvb3BEZXRlY3RvciB7XG4gIHByaXZhdGUgZmlsZUVkaXRDb3VudHM6IE1hcDxzdHJpbmcsIG51bWJlcltdPiA9IG5ldyBNYXAoKTtcbiAgcHJpdmF0ZSBzdGF0ZUZpbGVQYXRoOiBzdHJpbmc7XG4gIHByaXZhdGUgY29uZmlnOiBSZXF1aXJlZDxMb29wRGV0ZWN0b3JDb25maWc+O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgd29ya3NwYWNlUGF0aDogc3RyaW5nLFxuICAgIGNvbmZpZzogTG9vcERldGVjdG9yQ29uZmlnID0ge31cbiAgKSB7XG4gICAgdGhpcy5jb25maWcgPSB7XG4gICAgICBsaW1pdDogNSxcbiAgICAgIHdpbmRvd01zOiAzMDAwMDAsIC8vIDUg5YiG6ZKfXG4gICAgICB3YXJuaW5nTWVzc2FnZTogYOKaoO+4jyDorablkYrvvJp7ZmlsZX0g5bey6KKr5L+u5pS5IHtjb3VudH0g5qyh77yIe3dpbmRvd33liIbpkp/lhoXvvIlcXG5gICtcbiAgICAgICAgICAgICAgICAgICAgICAn6K+36ICD6JmR77yaXFxuJyArXG4gICAgICAgICAgICAgICAgICAgICAgJzEuIOmHjeaWsOmYheivu+S7u+WKoeinhOagvFxcbicgK1xuICAgICAgICAgICAgICAgICAgICAgICcyLiDmo4Dmn6XmmK/lkKbmnInmoLnmnKzmgKforr7orqHpl67pophcXG4nICtcbiAgICAgICAgICAgICAgICAgICAgICAnMy4g6ICD6JmR5a+75rGC5Lq657G75biu5YqpJyxcbiAgICAgIC4uLmNvbmZpZyxcbiAgICB9O1xuXG4gICAgLy8g54q25oCB5oyB5LmF5YyW5paH5Lu2XG4gICAgY29uc3QgbG9nc0RpciA9IHBhdGguam9pbih3b3Jrc3BhY2VQYXRoLCAnbG9ncycpO1xuICAgIGlmICghZnMuZXhpc3RzU3luYyhsb2dzRGlyKSkge1xuICAgICAgZnMubWtkaXJTeW5jKGxvZ3NEaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgIH1cbiAgICB0aGlzLnN0YXRlRmlsZVBhdGggPSBwYXRoLmpvaW4obG9nc0RpciwgJ2xvb3AtZGV0ZWN0b3Itc3RhdGUuanNvbicpO1xuICAgIFxuICAgIC8vIOWKoOi9veS5i+WJjeeahOeKtuaAgVxuICAgIHRoaXMubG9hZFN0YXRlKCk7XG4gIH1cblxuICBwcml2YXRlIGxvYWRTdGF0ZSgpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgaWYgKGZzLmV4aXN0c1N5bmModGhpcy5zdGF0ZUZpbGVQYXRoKSkge1xuICAgICAgICBjb25zdCBkYXRhID0gZnMucmVhZEZpbGVTeW5jKHRoaXMuc3RhdGVGaWxlUGF0aCwgJ3V0ZjgnKTtcbiAgICAgICAgY29uc3Qgc3RhdGUgPSBKU09OLnBhcnNlKGRhdGEpO1xuICAgICAgICB0aGlzLmZpbGVFZGl0Q291bnRzID0gbmV3IE1hcChPYmplY3QuZW50cmllcyhzdGF0ZSkpO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAvLyDlv73nlaXliqDovb3plJnor6/vvIzku47nqbrnirbmgIHlvIDlp4tcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHNhdmVTdGF0ZSgpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgY29uc3Qgc3RhdGUgPSBPYmplY3QuZnJvbUVudHJpZXModGhpcy5maWxlRWRpdENvdW50cyk7XG4gICAgICBmcy53cml0ZUZpbGVTeW5jKHRoaXMuc3RhdGVGaWxlUGF0aCwgSlNPTi5zdHJpbmdpZnkoc3RhdGUsIG51bGwsIDIpKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgLy8g5b+955Wl5L+d5a2Y6ZSZ6K+vXG4gICAgfVxuICB9XG5cbiAgb25GaWxlRWRpdChmaWxlUGF0aDogc3RyaW5nKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcbiAgICBjb25zdCBlZGl0cyA9IHRoaXMuZmlsZUVkaXRDb3VudHMuZ2V0KGZpbGVQYXRoKSB8fCBbXTtcbiAgICBcbiAgICAvLyDnp7vpmaTotoXlh7rml7bpl7Tnqpflj6PnmoTorrDlvZVcbiAgICBjb25zdCB3aW5kb3dTdGFydCA9IG5vdyAtIHRoaXMuY29uZmlnLndpbmRvd01zO1xuICAgIGNvbnN0IHJlY2VudEVkaXRzID0gZWRpdHMuZmlsdGVyKHRpbWUgPT4gdGltZSA+IHdpbmRvd1N0YXJ0KTtcbiAgICBcbiAgICByZWNlbnRFZGl0cy5wdXNoKG5vdyk7XG4gICAgdGhpcy5maWxlRWRpdENvdW50cy5zZXQoZmlsZVBhdGgsIHJlY2VudEVkaXRzKTtcbiAgICB0aGlzLnNhdmVTdGF0ZSgpO1xuXG4gICAgaWYgKHJlY2VudEVkaXRzLmxlbmd0aCA+PSB0aGlzLmNvbmZpZy5saW1pdCkge1xuICAgICAgcmV0dXJuIHRoaXMuY29uZmlnLndhcm5pbmdNZXNzYWdlXG4gICAgICAgIC5yZXBsYWNlKCd7ZmlsZX0nLCBmaWxlUGF0aClcbiAgICAgICAgLnJlcGxhY2UoJ3tjb3VudH0nLCByZWNlbnRFZGl0cy5sZW5ndGgudG9TdHJpbmcoKSlcbiAgICAgICAgLnJlcGxhY2UoJ3t3aW5kb3d9JywgKHRoaXMuY29uZmlnLndpbmRvd01zIC8gNjAwMDApLnRvU3RyaW5nKCkpO1xuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmVzZXQoZmlsZVBhdGg/OiBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAoZmlsZVBhdGgpIHtcbiAgICAgIHRoaXMuZmlsZUVkaXRDb3VudHMuZGVsZXRlKGZpbGVQYXRoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5maWxlRWRpdENvdW50cy5jbGVhcigpO1xuICAgIH1cbiAgICB0aGlzLnNhdmVTdGF0ZSgpO1xuICB9XG5cbiAgZ2V0U3RhdHMoKTogUmVjb3JkPHN0cmluZywgbnVtYmVyPiB7XG4gICAgY29uc3Qgc3RhdHM6IFJlY29yZDxzdHJpbmcsIG51bWJlcj4gPSB7fTtcbiAgICB0aGlzLmZpbGVFZGl0Q291bnRzLmZvckVhY2goKGVkaXRzLCBmaWxlKSA9PiB7XG4gICAgICBzdGF0c1tmaWxlXSA9IGVkaXRzLmxlbmd0aDtcbiAgICB9KTtcbiAgICByZXR1cm4gc3RhdHM7XG4gIH1cblxuICBnZXRDb25maWcoKTogUmVxdWlyZWQ8TG9vcERldGVjdG9yQ29uZmlnPiB7XG4gICAgcmV0dXJuIHsgLi4udGhpcy5jb25maWcgfTtcbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export interface TraceEntry {
|
|
2
|
+
timestamp: string;
|
|
3
|
+
sessionId: string;
|
|
4
|
+
type: 'tool_call' | 'user_request' | 'agent_response' | 'error' | 'config_change';
|
|
5
|
+
data: Record<string, any>;
|
|
6
|
+
metadata?: {
|
|
7
|
+
tokenUsage?: {
|
|
8
|
+
in: number;
|
|
9
|
+
out: number;
|
|
10
|
+
};
|
|
11
|
+
durationMs?: number;
|
|
12
|
+
model?: string;
|
|
13
|
+
modifier?: string;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export declare class TraceLogger {
|
|
17
|
+
private workspacePath;
|
|
18
|
+
private logFilePath;
|
|
19
|
+
constructor(workspacePath: string);
|
|
20
|
+
log(entry: Omit<TraceEntry, 'timestamp'>): void;
|
|
21
|
+
logToolCall(sessionId: string, tool: string, params: any, result: any, metadata?: TraceEntry['metadata']): void;
|
|
22
|
+
logUserRequest(sessionId: string, request: string): void;
|
|
23
|
+
logAgentResponse(sessionId: string, response: string, metadata?: TraceEntry['metadata']): void;
|
|
24
|
+
logError(sessionId: string, error: Error, context?: any): void;
|
|
25
|
+
logConfigChange(sessionId: string, file: string, changes: Array<{
|
|
26
|
+
field: string;
|
|
27
|
+
oldValue: any;
|
|
28
|
+
newValue: any;
|
|
29
|
+
}>, reason: string, modifier?: string): void;
|
|
30
|
+
getSessionTraces(sessionId: string): TraceEntry[];
|
|
31
|
+
getRecentTraces(limit?: number): TraceEntry[];
|
|
32
|
+
getTracesByType(type: TraceEntry['type'], limit?: number): TraceEntry[];
|
|
33
|
+
exportToJson(outputPath: string): void;
|
|
34
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// src/middleware/trace-logger.ts - Trace 记录器
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
exports.TraceLogger = void 0;
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
class TraceLogger {
|
|
41
|
+
workspacePath;
|
|
42
|
+
logFilePath;
|
|
43
|
+
constructor(workspacePath) {
|
|
44
|
+
this.workspacePath = workspacePath;
|
|
45
|
+
const logsDir = path.join(workspacePath, 'logs');
|
|
46
|
+
if (!fs.existsSync(logsDir)) {
|
|
47
|
+
fs.mkdirSync(logsDir, { recursive: true });
|
|
48
|
+
}
|
|
49
|
+
this.logFilePath = path.join(logsDir, 'traces.jsonl');
|
|
50
|
+
}
|
|
51
|
+
log(entry) {
|
|
52
|
+
const fullEntry = {
|
|
53
|
+
...entry,
|
|
54
|
+
timestamp: new Date().toISOString(),
|
|
55
|
+
};
|
|
56
|
+
fs.appendFileSync(this.logFilePath, JSON.stringify(fullEntry) + '\n');
|
|
57
|
+
}
|
|
58
|
+
logToolCall(sessionId, tool, params, result, metadata) {
|
|
59
|
+
this.log({
|
|
60
|
+
sessionId,
|
|
61
|
+
type: 'tool_call',
|
|
62
|
+
data: { tool, params, result },
|
|
63
|
+
metadata,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
logUserRequest(sessionId, request) {
|
|
67
|
+
this.log({
|
|
68
|
+
sessionId,
|
|
69
|
+
type: 'user_request',
|
|
70
|
+
data: { request },
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
logAgentResponse(sessionId, response, metadata) {
|
|
74
|
+
this.log({
|
|
75
|
+
sessionId,
|
|
76
|
+
type: 'agent_response',
|
|
77
|
+
data: { response },
|
|
78
|
+
metadata,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
logError(sessionId, error, context) {
|
|
82
|
+
this.log({
|
|
83
|
+
sessionId,
|
|
84
|
+
type: 'error',
|
|
85
|
+
data: { error: error.message, stack: error.stack, context },
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
logConfigChange(sessionId, file, changes, reason, modifier) {
|
|
89
|
+
this.log({
|
|
90
|
+
sessionId,
|
|
91
|
+
type: 'config_change',
|
|
92
|
+
data: { file, changes, reason },
|
|
93
|
+
metadata: { modifier },
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
getSessionTraces(sessionId) {
|
|
97
|
+
if (!fs.existsSync(this.logFilePath))
|
|
98
|
+
return [];
|
|
99
|
+
const content = fs.readFileSync(this.logFilePath, 'utf8');
|
|
100
|
+
return content
|
|
101
|
+
.split('\n')
|
|
102
|
+
.filter(line => line.trim())
|
|
103
|
+
.map(line => JSON.parse(line))
|
|
104
|
+
.filter(entry => entry.sessionId === sessionId);
|
|
105
|
+
}
|
|
106
|
+
getRecentTraces(limit = 100) {
|
|
107
|
+
if (!fs.existsSync(this.logFilePath))
|
|
108
|
+
return [];
|
|
109
|
+
const content = fs.readFileSync(this.logFilePath, 'utf8');
|
|
110
|
+
return content
|
|
111
|
+
.split('\n')
|
|
112
|
+
.filter(line => line.trim())
|
|
113
|
+
.map(line => JSON.parse(line))
|
|
114
|
+
.slice(-limit);
|
|
115
|
+
}
|
|
116
|
+
getTracesByType(type, limit = 50) {
|
|
117
|
+
if (!fs.existsSync(this.logFilePath))
|
|
118
|
+
return [];
|
|
119
|
+
const content = fs.readFileSync(this.logFilePath, 'utf8');
|
|
120
|
+
return content
|
|
121
|
+
.split('\n')
|
|
122
|
+
.filter(line => line.trim())
|
|
123
|
+
.map(line => JSON.parse(line))
|
|
124
|
+
.filter(entry => entry.type === type)
|
|
125
|
+
.slice(-limit);
|
|
126
|
+
}
|
|
127
|
+
exportToJson(outputPath) {
|
|
128
|
+
if (!fs.existsSync(this.logFilePath)) {
|
|
129
|
+
fs.writeFileSync(outputPath, '[]');
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
const content = fs.readFileSync(this.logFilePath, 'utf8');
|
|
133
|
+
const traces = content
|
|
134
|
+
.split('\n')
|
|
135
|
+
.filter(line => line.trim())
|
|
136
|
+
.map(line => JSON.parse(line));
|
|
137
|
+
fs.writeFileSync(outputPath, JSON.stringify(traces, null, 2));
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
exports.TraceLogger = TraceLogger;
|
|
141
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhY2UtbG9nZ2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NvcmUvbWlkZGxld2FyZS90cmFjZS1sb2dnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLDZDQUE2Qzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBRTdDLHVDQUF5QjtBQUN6QiwyQ0FBNkI7QUFlN0IsTUFBYSxXQUFXO0lBR0Y7SUFGWixXQUFXLENBQVM7SUFFNUIsWUFBb0IsYUFBcUI7UUFBckIsa0JBQWEsR0FBYixhQUFhLENBQVE7UUFDdkMsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDakQsSUFBSSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUM1QixFQUFFLENBQUMsU0FBUyxDQUFDLE9BQU8sRUFBRSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQzdDLENBQUM7UUFDRCxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLGNBQWMsQ0FBQyxDQUFDO0lBQ3hELENBQUM7SUFFRCxHQUFHLENBQUMsS0FBb0M7UUFDdEMsTUFBTSxTQUFTLEdBQWU7WUFDNUIsR0FBRyxLQUFLO1lBQ1IsU0FBUyxFQUFFLElBQUksSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFO1NBQ3BDLENBQUM7UUFDRixFQUFFLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQztJQUN4RSxDQUFDO0lBRUQsV0FBVyxDQUNULFNBQWlCLEVBQ2pCLElBQVksRUFDWixNQUFXLEVBQ1gsTUFBVyxFQUNYLFFBQWlDO1FBRWpDLElBQUksQ0FBQyxHQUFHLENBQUM7WUFDUCxTQUFTO1lBQ1Qs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a0NBOEhDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gc3JjL21pZGRsZXdhcmUvdHJhY2UtbG9nZ2VyLnRzIC0gVHJhY2Ug6K6w5b2V5ZmoXG5cbmltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgVHJhY2VFbnRyeSB7XG4gIHRpbWVzdGFtcDogc3RyaW5nO1xuICBzZXNzaW9uSWQ6IHN0cmluZztcbiAgdHlwZTogJ3Rvb2xfY2FsbCcgfCAndXNlcl9yZXF1ZXN0JyB8ICdhZ2VudF9yZXNwb25zZScgfCAnZXJyb3InIHwgJ2NvbmZpZ19jaGFuZ2UnO1xuICBkYXRhOiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuICBtZXRhZGF0YT86IHtcbiAgICB0b2tlblVzYWdlPzogeyBpbjogbnVtYmVyOyBvdXQ6IG51bWJlciB9O1xuICAgIGR1cmF0aW9uTXM/OiBudW1iZXI7XG4gICAgbW9kZWw/OiBzdHJpbmc7XG4gICAgbW9kaWZpZXI/OiBzdHJpbmc7XG4gIH07XG59XG5cbmV4cG9ydCBjbGFzcyBUcmFjZUxvZ2dlciB7XG4gIHByaXZhdGUgbG9nRmlsZVBhdGg6IHN0cmluZztcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHdvcmtzcGFjZVBhdGg6IHN0cmluZykge1xuICAgIGNvbnN0IGxvZ3NEaXIgPSBwYXRoLmpvaW4od29ya3NwYWNlUGF0aCwgJ2xvZ3MnKTtcbiAgICBpZiAoIWZzLmV4aXN0c1N5bmMobG9nc0RpcikpIHtcbiAgICAgIGZzLm1rZGlyU3luYyhsb2dzRGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICB9XG4gICAgdGhpcy5sb2dGaWxlUGF0aCA9IHBhdGguam9pbihsb2dzRGlyLCAndHJhY2VzLmpzb25sJyk7XG4gIH1cblxuICBsb2coZW50cnk6IE9taXQ8VHJhY2VFbnRyeSwgJ3RpbWVzdGFtcCc+KTogdm9pZCB7XG4gICAgY29uc3QgZnVsbEVudHJ5OiBUcmFjZUVudHJ5ID0ge1xuICAgICAgLi4uZW50cnksXG4gICAgICB0aW1lc3RhbXA6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSxcbiAgICB9O1xuICAgIGZzLmFwcGVuZEZpbGVTeW5jKHRoaXMubG9nRmlsZVBhdGgsIEpTT04uc3RyaW5naWZ5KGZ1bGxFbnRyeSkgKyAnXFxuJyk7XG4gIH1cblxuICBsb2dUb29sQ2FsbChcbiAgICBzZXNzaW9uSWQ6IHN0cmluZyxcbiAgICB0b29sOiBzdHJpbmcsXG4gICAgcGFyYW1zOiBhbnksXG4gICAgcmVzdWx0OiBhbnksXG4gICAgbWV0YWRhdGE/OiBUcmFjZUVudHJ5WydtZXRhZGF0YSddXG4gICk6IHZvaWQge1xuICAgIHRoaXMubG9nKHtcbiAgICAgIHNlc3Npb25JZCxcbiAgICAgIHR5cGU6ICd0b29sX2NhbGwnLFxuICAgICAgZGF0YTogeyB0b29sLCBwYXJhbXMsIHJlc3VsdCB9LFxuICAgICAgbWV0YWRhdGEsXG4gICAgfSk7XG4gIH1cblxuICBsb2dVc2VyUmVxdWVzdChzZXNzaW9uSWQ6IHN0cmluZywgcmVxdWVzdDogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5sb2coe1xuICAgICAgc2Vzc2lvbklkLFxuICAgICAgdHlwZTogJ3VzZXJfcmVxdWVzdCcsXG4gICAgICBkYXRhOiB7IHJlcXVlc3QgfSxcbiAgICB9KTtcbiAgfVxuXG4gIGxvZ0FnZW50UmVzcG9uc2UoXG4gICAgc2Vzc2lvbklkOiBzdHJpbmcsXG4gICAgcmVzcG9uc2U6IHN0cmluZyxcbiAgICBtZXRhZGF0YT86IFRyYWNlRW50cnlbJ21ldGFkYXRhJ11cbiAgKTogdm9pZCB7XG4gICAgdGhpcy5sb2coe1xuICAgICAgc2Vzc2lvbklkLFxuICAgICAgdHlwZTogJ2FnZW50X3Jlc3BvbnNlJyxcbiAgICAgIGRhdGE6IHsgcmVzcG9uc2UgfSxcbiAgICAgIG1ldGFkYXRhLFxuICAgIH0pO1xuICB9XG5cbiAgbG9nRXJyb3Ioc2Vzc2lvbklkOiBzdHJpbmcsIGVycm9yOiBFcnJvciwgY29udGV4dD86IGFueSk6IHZvaWQge1xuICAgIHRoaXMubG9nKHtcbiAgICAgIHNlc3Npb25JZCxcbiAgICAgIHR5cGU6ICdlcnJvcicsXG4gICAgICBkYXRhOiB7IGVycm9yOiBlcnJvci5tZXNzYWdlLCBzdGFjazogZXJyb3Iuc3RhY2ssIGNvbnRleHQgfSxcbiAgICB9KTtcbiAgfVxuXG4gIGxvZ0NvbmZpZ0NoYW5nZShcbiAgICBzZXNzaW9uSWQ6IHN0cmluZyxcbiAgICBmaWxlOiBzdHJpbmcsXG4gICAgY2hhbmdlczogQXJyYXk8eyBmaWVsZDogc3RyaW5nOyBvbGRWYWx1ZTogYW55OyBuZXdWYWx1ZTogYW55IH0+LFxuICAgIHJlYXNvbjogc3RyaW5nLFxuICAgIG1vZGlmaWVyPzogc3RyaW5nXG4gICk6IHZvaWQge1xuICAgIHRoaXMubG9nKHtcbiAgICAgIHNlc3Npb25JZCxcbiAgICAgIHR5cGU6ICdjb25maWdfY2hhbmdlJyxcbiAgICAgIGRhdGE6IHsgZmlsZSwgY2hhbmdlcywgcmVhc29uIH0sXG4gICAgICBtZXRhZGF0YTogeyBtb2RpZmllciB9LFxuICAgIH0pO1xuICB9XG5cbiAgZ2V0U2Vzc2lvblRyYWNlcyhzZXNzaW9uSWQ6IHN0cmluZyk6IFRyYWNlRW50cnlbXSB7XG4gICAgaWYgKCFmcy5leGlzdHNTeW5jKHRoaXMubG9nRmlsZVBhdGgpKSByZXR1cm4gW107XG4gICAgXG4gICAgY29uc3QgY29udGVudCA9IGZzLnJlYWRGaWxlU3luYyh0aGlzLmxvZ0ZpbGVQYXRoLCAndXRmOCcpO1xuICAgIHJldHVybiBjb250ZW50XG4gICAgICAuc3BsaXQoJ1xcbicpXG4gICAgICAuZmlsdGVyKGxpbmUgPT4gbGluZS50cmltKCkpXG4gICAgICAubWFwKGxpbmUgPT4gSlNPTi5wYXJzZShsaW5lKSlcbiAgICAgIC5maWx0ZXIoZW50cnkgPT4gZW50cnkuc2Vzc2lvbklkID09PSBzZXNzaW9uSWQpO1xuICB9XG5cbiAgZ2V0UmVjZW50VHJhY2VzKGxpbWl0OiBudW1iZXIgPSAxMDApOiBUcmFjZUVudHJ5W10ge1xuICAgIGlmICghZnMuZXhpc3RzU3luYyh0aGlzLmxvZ0ZpbGVQYXRoKSkgcmV0dXJuIFtdO1xuICAgIFxuICAgIGNvbnN0IGNvbnRlbnQgPSBmcy5yZWFkRmlsZVN5bmModGhpcy5sb2dGaWxlUGF0aCwgJ3V0ZjgnKTtcbiAgICByZXR1cm4gY29udGVudFxuICAgICAgLnNwbGl0KCdcXG4nKVxuICAgICAgLmZpbHRlcihsaW5lID0+IGxpbmUudHJpbSgpKVxuICAgICAgLm1hcChsaW5lID0+IEpTT04ucGFyc2UobGluZSkpXG4gICAgICAuc2xpY2UoLWxpbWl0KTtcbiAgfVxuXG4gIGdldFRyYWNlc0J5VHlwZSh0eXBlOiBUcmFjZUVudHJ5Wyd0eXBlJ10sIGxpbWl0OiBudW1iZXIgPSA1MCk6IFRyYWNlRW50cnlbXSB7XG4gICAgaWYgKCFmcy5leGlzdHNTeW5jKHRoaXMubG9nRmlsZVBhdGgpKSByZXR1cm4gW107XG4gICAgXG4gICAgY29uc3QgY29udGVudCA9IGZzLnJlYWRGaWxlU3luYyh0aGlzLmxvZ0ZpbGVQYXRoLCAndXRmOCcpO1xuICAgIHJldHVybiBjb250ZW50XG4gICAgICAuc3BsaXQoJ1xcbicpXG4gICAgICAuZmlsdGVyKGxpbmUgPT4gbGluZS50cmltKCkpXG4gICAgICAubWFwKGxpbmUgPT4gSlNPTi5wYXJzZShsaW5lKSlcbiAgICAgIC5maWx0ZXIoZW50cnkgPT4gZW50cnkudHlwZSA9PT0gdHlwZSlcbiAgICAgIC5zbGljZSgtbGltaXQpO1xuICB9XG5cbiAgZXhwb3J0VG9Kc29uKG91dHB1dFBhdGg6IHN0cmluZyk6IHZvaWQge1xuICAgIGlmICghZnMuZXhpc3RzU3luYyh0aGlzLmxvZ0ZpbGVQYXRoKSkge1xuICAgICAgZnMud3JpdGVGaWxlU3luYyhvdXRwdXRQYXRoLCAnW10nKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgXG4gICAgY29uc3QgY29udGVudCA9IGZzLnJlYWRGaWxlU3luYyh0aGlzLmxvZ0ZpbGVQYXRoLCAndXRmOCcpO1xuICAgIGNvbnN0IHRyYWNlcyA9IGNvbnRlbnRcbiAgICAgIC5zcGxpdCgnXFxuJylcbiAgICAgIC5maWx0ZXIobGluZSA9PiBsaW5lLnRyaW0oKSlcbiAgICAgIC5tYXAobGluZSA9PiBKU09OLnBhcnNlKGxpbmUpKTtcbiAgICBcbiAgICBmcy53cml0ZUZpbGVTeW5jKG91dHB1dFBhdGgsIEpTT04uc3RyaW5naWZ5KHRyYWNlcywgbnVsbCwgMikpO1xuICB9XG59XG4iXX0=
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 确保目录存在
|
|
3
|
+
*/
|
|
4
|
+
export declare function ensureDir(dirPath: string): void;
|
|
5
|
+
/**
|
|
6
|
+
* 读取文件
|
|
7
|
+
*/
|
|
8
|
+
export declare function readFile(filePath: string, encoding?: BufferEncoding): string;
|
|
9
|
+
/**
|
|
10
|
+
* 写入文件
|
|
11
|
+
*/
|
|
12
|
+
export declare function writeFile(filePath: string, content: string, encoding?: BufferEncoding): void;
|
|
13
|
+
/**
|
|
14
|
+
* 检查文件是否存在
|
|
15
|
+
*/
|
|
16
|
+
export declare function fileExists(filePath: string): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* 追加内容到文件
|
|
19
|
+
*/
|
|
20
|
+
export declare function appendToFile(filePath: string, content: string, encoding?: BufferEncoding): void;
|
|
21
|
+
/**
|
|
22
|
+
* 安全删除文件(移动到回收站)
|
|
23
|
+
*/
|
|
24
|
+
export declare function safeDelete(filePath: string): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* 备份文件
|
|
27
|
+
*/
|
|
28
|
+
export declare function backupFile(filePath: string, backupPath?: string): string;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// src/utils/file.ts - 文件工具
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
exports.ensureDir = ensureDir;
|
|
38
|
+
exports.readFile = readFile;
|
|
39
|
+
exports.writeFile = writeFile;
|
|
40
|
+
exports.fileExists = fileExists;
|
|
41
|
+
exports.appendToFile = appendToFile;
|
|
42
|
+
exports.safeDelete = safeDelete;
|
|
43
|
+
exports.backupFile = backupFile;
|
|
44
|
+
const fs = __importStar(require("fs"));
|
|
45
|
+
const path = __importStar(require("path"));
|
|
46
|
+
/**
|
|
47
|
+
* 确保目录存在
|
|
48
|
+
*/
|
|
49
|
+
function ensureDir(dirPath) {
|
|
50
|
+
if (!fs.existsSync(dirPath)) {
|
|
51
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* 读取文件
|
|
56
|
+
*/
|
|
57
|
+
function readFile(filePath, encoding = 'utf8') {
|
|
58
|
+
return fs.readFileSync(filePath, encoding);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* 写入文件
|
|
62
|
+
*/
|
|
63
|
+
function writeFile(filePath, content, encoding = 'utf8') {
|
|
64
|
+
const dir = path.dirname(filePath);
|
|
65
|
+
ensureDir(dir);
|
|
66
|
+
fs.writeFileSync(filePath, content, encoding);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* 检查文件是否存在
|
|
70
|
+
*/
|
|
71
|
+
function fileExists(filePath) {
|
|
72
|
+
return fs.existsSync(filePath);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* 追加内容到文件
|
|
76
|
+
*/
|
|
77
|
+
function appendToFile(filePath, content, encoding = 'utf8') {
|
|
78
|
+
const dir = path.dirname(filePath);
|
|
79
|
+
ensureDir(dir);
|
|
80
|
+
fs.appendFileSync(filePath, content, encoding);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* 安全删除文件(移动到回收站)
|
|
84
|
+
*/
|
|
85
|
+
function safeDelete(filePath) {
|
|
86
|
+
try {
|
|
87
|
+
// 简单实现:重命名为 .deleted 后缀
|
|
88
|
+
const deletedPath = filePath + '.deleted';
|
|
89
|
+
fs.renameSync(filePath, deletedPath);
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* 备份文件
|
|
98
|
+
*/
|
|
99
|
+
function backupFile(filePath, backupPath) {
|
|
100
|
+
const dest = backupPath || `${filePath}.bak.${Date.now()}`;
|
|
101
|
+
fs.copyFileSync(filePath, dest);
|
|
102
|
+
return dest;
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jb3JlL3V0aWxzL2ZpbGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLDJCQUEyQjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFRM0IsOEJBSUM7QUFLRCw0QkFFQztBQUtELDhCQUlDO0FBS0QsZ0NBRUM7QUFLRCxvQ0FJQztBQUtELGdDQVNDO0FBS0QsZ0NBSUM7QUFqRUQsdUNBQXlCO0FBQ3pCLDJDQUE2QjtBQUU3Qjs7R0FFRztBQUNILFNBQWdCLFNBQVMsQ0FBQyxPQUFlO0lBQ3ZDLElBQUksQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDNUIsRUFBRSxDQUFDLFNBQVMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUM3QyxDQUFDO0FBQ0gsQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBZ0IsUUFBUSxDQUFDLFFBQWdCLEVBQUUsV0FBMkIsTUFBTTtJQUMxRSxPQUFPLEVBQUUsQ0FBQyxZQUFZLENBQUMsUUFBUSxFQUFFLFFBQVEsQ0FBQyxDQUFDO0FBQzdDLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQWdCLFNBQVMsQ0FBQyxRQUFnQixFQUFFLE9BQWUsRUFBRSxXQUEyQixNQUFNO0lBQzVGLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDbkMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ2YsRUFBRSxDQUFDLGFBQWEsQ0FBQyxRQUFRLEVBQUUsT0FBTyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0FBQ2hELENBQUM7QUFFRDs7R0FFRztBQUNILFNBQWdCLFVBQVUsQ0FBQyxRQUFnQjtJQUN6QyxPQUFPLEVBQUUsQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUM7QUFDakMsQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBZ0IsWUFBWSxDQUFDLFFBQWdCLEVBQUUsT0FBZSxFQUFFLFdBQTJCLE1BQU07SUFDL0YsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUNuQyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDZixFQUFFLENBQUMsY0FBYyxDQUFDLFFBQVEsRUFBRSxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUM7QUFDakQsQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBZ0IsVUFBVSxDQUFDLFFBQWdCO0lBQ3pDLElBQUksQ0FBQztRQUNILHdCQUF3QjtRQUN4QixNQUFNLFdBQVcsR0FBRyxRQUFRLEdBQUcsVUFBVSxDQUFDO1FBQzFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsUUFBUSxFQUFFLFdBQVcsQ0FBQyxDQUFDO1FBQ3JDLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7UUFDZixPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7QUFDSCxDQUFDO0FBRUQ7O0dBRUc7QUFDSCxTQUFnQixVQUFVLENBQUMsUUFBZ0IsRUFBRSxVQUFtQjtJQUM5RCxNQUFNLElBQUksR0FBRyxVQUFVLElBQUksR0FBRyxRQUFRLFFBQVEsSUFBSSxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUM7SUFDM0QsRUFBRSxDQUFDLFlBQVksQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDaEMsT0FBTyxJQUFJLENBQUM7QUFDZCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gc3JjL3V0aWxzL2ZpbGUudHMgLSDmlofku7blt6XlhbdcblxuaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMnO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcblxuLyoqXG4gKiDnoa7kv53nm67lvZXlrZjlnKhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGVuc3VyZURpcihkaXJQYXRoOiBzdHJpbmcpOiB2b2lkIHtcbiAgaWYgKCFmcy5leGlzdHNTeW5jKGRpclBhdGgpKSB7XG4gICAgZnMubWtkaXJTeW5jKGRpclBhdGgsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICB9XG59XG5cbi8qKlxuICog6K+75Y+W5paH5Lu2XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWFkRmlsZShmaWxlUGF0aDogc3RyaW5nLCBlbmNvZGluZzogQnVmZmVyRW5jb2RpbmcgPSAndXRmOCcpOiBzdHJpbmcge1xuICByZXR1cm4gZnMucmVhZEZpbGVTeW5jKGZpbGVQYXRoLCBlbmNvZGluZyk7XG59XG5cbi8qKlxuICog5YaZ5YWl5paH5Lu2XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB3cml0ZUZpbGUoZmlsZVBhdGg6IHN0cmluZywgY29udGVudDogc3RyaW5nLCBlbmNvZGluZzogQnVmZmVyRW5jb2RpbmcgPSAndXRmOCcpOiB2b2lkIHtcbiAgY29uc3QgZGlyID0gcGF0aC5kaXJuYW1lKGZpbGVQYXRoKTtcbiAgZW5zdXJlRGlyKGRpcik7XG4gIGZzLndyaXRlRmlsZVN5bmMoZmlsZVBhdGgsIGNvbnRlbnQsIGVuY29kaW5nKTtcbn1cblxuLyoqXG4gKiDmo4Dmn6Xmlofku7bmmK/lkKblrZjlnKhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZpbGVFeGlzdHMoZmlsZVBhdGg6IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gZnMuZXhpc3RzU3luYyhmaWxlUGF0aCk7XG59XG5cbi8qKlxuICog6L+95Yqg5YaF5a655Yiw5paH5Lu2XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcHBlbmRUb0ZpbGUoZmlsZVBhdGg6IHN0cmluZywgY29udGVudDogc3RyaW5nLCBlbmNvZGluZzogQnVmZmVyRW5jb2RpbmcgPSAndXRmOCcpOiB2b2lkIHtcbiAgY29uc3QgZGlyID0gcGF0aC5kaXJuYW1lKGZpbGVQYXRoKTtcbiAgZW5zdXJlRGlyKGRpcik7XG4gIGZzLmFwcGVuZEZpbGVTeW5jKGZpbGVQYXRoLCBjb250ZW50LCBlbmNvZGluZyk7XG59XG5cbi8qKlxuICog5a6J5YWo5Yig6Zmk5paH5Lu277yI56e75Yqo5Yiw5Zue5pS256uZ77yJXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzYWZlRGVsZXRlKGZpbGVQYXRoOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgdHJ5IHtcbiAgICAvLyDnroDljZXlrp7njrDvvJrph43lkb3lkI3kuLogLmRlbGV0ZWQg5ZCO57yAXG4gICAgY29uc3QgZGVsZXRlZFBhdGggPSBmaWxlUGF0aCArICcuZGVsZXRlZCc7XG4gICAgZnMucmVuYW1lU3luYyhmaWxlUGF0aCwgZGVsZXRlZFBhdGgpO1xuICAgIHJldHVybiB0cnVlO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG4vKipcbiAqIOWkh+S7veaWh+S7tlxuICovXG5leHBvcnQgZnVuY3Rpb24gYmFja3VwRmlsZShmaWxlUGF0aDogc3RyaW5nLCBiYWNrdXBQYXRoPzogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgZGVzdCA9IGJhY2t1cFBhdGggfHwgYCR7ZmlsZVBhdGh9LmJhay4ke0RhdGUubm93KCl9YDtcbiAgZnMuY29weUZpbGVTeW5jKGZpbGVQYXRoLCBkZXN0KTtcbiAgcmV0dXJuIGRlc3Q7XG59XG4iXX0=
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 格式化文件大小
|
|
3
|
+
*/
|
|
4
|
+
export declare function formatFileSize(bytes: number): string;
|
|
5
|
+
/**
|
|
6
|
+
* 格式化日期
|
|
7
|
+
*/
|
|
8
|
+
export declare function formatDate(date: Date | string, format?: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* 截断字符串
|
|
11
|
+
*/
|
|
12
|
+
export declare function truncate(str: string, maxLength: number, suffix?: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* 格式化持续时间
|
|
15
|
+
*/
|
|
16
|
+
export declare function formatDuration(ms: number): string;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// src/utils/format.ts - 格式化工具
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.formatFileSize = formatFileSize;
|
|
5
|
+
exports.formatDate = formatDate;
|
|
6
|
+
exports.truncate = truncate;
|
|
7
|
+
exports.formatDuration = formatDuration;
|
|
8
|
+
/**
|
|
9
|
+
* 格式化文件大小
|
|
10
|
+
*/
|
|
11
|
+
function formatFileSize(bytes) {
|
|
12
|
+
const units = ['B', 'KB', 'MB', 'GB'];
|
|
13
|
+
let unitIndex = 0;
|
|
14
|
+
let size = bytes;
|
|
15
|
+
while (size >= 1024 && unitIndex < units.length - 1) {
|
|
16
|
+
size /= 1024;
|
|
17
|
+
unitIndex++;
|
|
18
|
+
}
|
|
19
|
+
return `${size.toFixed(2)} ${units[unitIndex]}`;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* 格式化日期
|
|
23
|
+
*/
|
|
24
|
+
function formatDate(date, format = 'YYYY-MM-DD HH:mm:ss') {
|
|
25
|
+
const d = typeof date === 'string' ? new Date(date) : date;
|
|
26
|
+
const year = d.getFullYear();
|
|
27
|
+
const month = String(d.getMonth() + 1).padStart(2, '0');
|
|
28
|
+
const day = String(d.getDate()).padStart(2, '0');
|
|
29
|
+
const hours = String(d.getHours()).padStart(2, '0');
|
|
30
|
+
const minutes = String(d.getMinutes()).padStart(2, '0');
|
|
31
|
+
const seconds = String(d.getSeconds()).padStart(2, '0');
|
|
32
|
+
return format
|
|
33
|
+
.replace('YYYY', String(year))
|
|
34
|
+
.replace('MM', month)
|
|
35
|
+
.replace('DD', day)
|
|
36
|
+
.replace('HH', hours)
|
|
37
|
+
.replace('mm', minutes)
|
|
38
|
+
.replace('ss', seconds);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* 截断字符串
|
|
42
|
+
*/
|
|
43
|
+
function truncate(str, maxLength, suffix = '...') {
|
|
44
|
+
if (str.length <= maxLength)
|
|
45
|
+
return str;
|
|
46
|
+
return str.substring(0, maxLength - suffix.length) + suffix;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* 格式化持续时间
|
|
50
|
+
*/
|
|
51
|
+
function formatDuration(ms) {
|
|
52
|
+
if (ms < 1000)
|
|
53
|
+
return `${ms}ms`;
|
|
54
|
+
if (ms < 60000)
|
|
55
|
+
return `${(ms / 1000).toFixed(1)}s`;
|
|
56
|
+
const minutes = Math.floor(ms / 60000);
|
|
57
|
+
const seconds = Math.floor((ms % 60000) / 1000);
|
|
58
|
+
return `${minutes}m ${seconds}s`;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9ybWF0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NvcmUvdXRpbHMvZm9ybWF0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSw4QkFBOEI7O0FBSzlCLHdDQVdDO0FBS0QsZ0NBaUJDO0FBS0QsNEJBR0M7QUFLRCx3Q0FPQztBQXhERDs7R0FFRztBQUNILFNBQWdCLGNBQWMsQ0FBQyxLQUFhO0lBQzFDLE1BQU0sS0FBSyxHQUFHLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDdEMsSUFBSSxTQUFTLEdBQUcsQ0FBQyxDQUFDO0lBQ2xCLElBQUksSUFBSSxHQUFHLEtBQUssQ0FBQztJQUVqQixPQUFPLElBQUksSUFBSSxJQUFJLElBQUksU0FBUyxHQUFHLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDcEQsSUFBSSxJQUFJLElBQUksQ0FBQztRQUNiLFNBQVMsRUFBRSxDQUFDO0lBQ2QsQ0FBQztJQUVELE9BQU8sR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO0FBQ2xELENBQUM7QUFFRDs7R0FFRztBQUNILFNBQWdCLFVBQVUsQ0FBQyxJQUFtQixFQUFFLFNBQWlCLHFCQUFxQjtJQUNwRixNQUFNLENBQUMsR0FBRyxPQUFPLElBQUksS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7SUFFM0QsTUFBTSxJQUFJLEdBQUcsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQzdCLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsUUFBUSxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUN4RCxNQUFNLEdBQUcsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUNqRCxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUNwRCxNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUN4RCxNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUV4RCxPQUFPLE1BQU07U0FDVixPQUFPLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztTQUM3QixPQUFPLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQztTQUNwQixPQUFPLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQztTQUNsQixPQUFPLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQztTQUNwQixPQUFPLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQztTQUN0QixPQUFPLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0FBQzVCLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQWdCLFFBQVEsQ0FBQyxHQUFXLEVBQUUsU0FBaUIsRUFBRSxTQUFpQixLQUFLO0lBQzdFLElBQUksR0FBRyxDQUFDLE1BQU0sSUFBSSxTQUFTO1FBQUUsT0FBTyxHQUFHLENBQUM7SUFDeEMsT0FBTyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxTQUFTLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLE1BQU0sQ0FBQztBQUM5RCxDQUFDO0FBRUQ7O0dBRUc7QUFDSCxTQUFnQixjQUFjLENBQUMsRUFBVTtJQUN2QyxJQUFJLEVBQUUsR0FBRyxJQUFJO1FBQUUsT0FBTyxHQUFHLEVBQUUsSUFBSSxDQUFDO0lBQ2hDLElBQUksRUFBRSxHQUFHLEtBQUs7UUFBRSxPQUFPLEdBQUcsQ0FBQyxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUM7SUFFcEQsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLEdBQUcsS0FBSyxDQUFDLENBQUM7SUFDdkMsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsR0FBRyxLQUFLLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQztJQUNoRCxPQUFPLEdBQUcsT0FBTyxLQUFLLE9BQU8sR0FBRyxDQUFDO0FBQ25DLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBzcmMvdXRpbHMvZm9ybWF0LnRzIC0g5qC85byP5YyW5bel5YW3XG5cbi8qKlxuICog5qC85byP5YyW5paH5Lu25aSn5bCPXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmb3JtYXRGaWxlU2l6ZShieXRlczogbnVtYmVyKTogc3RyaW5nIHtcbiAgY29uc3QgdW5pdHMgPSBbJ0InLCAnS0InLCAnTUInLCAnR0InXTtcbiAgbGV0IHVuaXRJbmRleCA9IDA7XG4gIGxldCBzaXplID0gYnl0ZXM7XG5cbiAgd2hpbGUgKHNpemUgPj0gMTAyNCAmJiB1bml0SW5kZXggPCB1bml0cy5sZW5ndGggLSAxKSB7XG4gICAgc2l6ZSAvPSAxMDI0O1xuICAgIHVuaXRJbmRleCsrO1xuICB9XG5cbiAgcmV0dXJuIGAke3NpemUudG9GaXhlZCgyKX0gJHt1bml0c1t1bml0SW5kZXhdfWA7XG59XG5cbi8qKlxuICog5qC85byP5YyW5pel5pyfXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmb3JtYXREYXRlKGRhdGU6IERhdGUgfCBzdHJpbmcsIGZvcm1hdDogc3RyaW5nID0gJ1lZWVktTU0tREQgSEg6bW06c3MnKTogc3RyaW5nIHtcbiAgY29uc3QgZCA9IHR5cGVvZiBkYXRlID09PSAnc3RyaW5nJyA/IG5ldyBEYXRlKGRhdGUpIDogZGF0ZTtcbiAgXG4gIGNvbnN0IHllYXIgPSBkLmdldEZ1bGxZZWFyKCk7XG4gIGNvbnN0IG1vbnRoID0gU3RyaW5nKGQuZ2V0TW9udGgoKSArIDEpLnBhZFN0YXJ0KDIsICcwJyk7XG4gIGNvbnN0IGRheSA9IFN0cmluZyhkLmdldERhdGUoKSkucGFkU3RhcnQoMiwgJzAnKTtcbiAgY29uc3QgaG91cnMgPSBTdHJpbmcoZC5nZXRIb3VycygpKS5wYWRTdGFydCgyLCAnMCcpO1xuICBjb25zdCBtaW51dGVzID0gU3RyaW5nKGQuZ2V0TWludXRlcygpKS5wYWRTdGFydCgyLCAnMCcpO1xuICBjb25zdCBzZWNvbmRzID0gU3RyaW5nKGQuZ2V0U2Vjb25kcygpKS5wYWRTdGFydCgyLCAnMCcpO1xuXG4gIHJldHVybiBmb3JtYXRcbiAgICAucmVwbGFjZSgnWVlZWScsIFN0cmluZyh5ZWFyKSlcbiAgICAucmVwbGFjZSgnTU0nLCBtb250aClcbiAgICAucmVwbGFjZSgnREQnLCBkYXkpXG4gICAgLnJlcGxhY2UoJ0hIJywgaG91cnMpXG4gICAgLnJlcGxhY2UoJ21tJywgbWludXRlcylcbiAgICAucmVwbGFjZSgnc3MnLCBzZWNvbmRzKTtcbn1cblxuLyoqXG4gKiDmiKrmlq3lrZfnrKbkuLJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRydW5jYXRlKHN0cjogc3RyaW5nLCBtYXhMZW5ndGg6IG51bWJlciwgc3VmZml4OiBzdHJpbmcgPSAnLi4uJyk6IHN0cmluZyB7XG4gIGlmIChzdHIubGVuZ3RoIDw9IG1heExlbmd0aCkgcmV0dXJuIHN0cjtcbiAgcmV0dXJuIHN0ci5zdWJzdHJpbmcoMCwgbWF4TGVuZ3RoIC0gc3VmZml4Lmxlbmd0aCkgKyBzdWZmaXg7XG59XG5cbi8qKlxuICog5qC85byP5YyW5oyB57ut5pe26Ze0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmb3JtYXREdXJhdGlvbihtczogbnVtYmVyKTogc3RyaW5nIHtcbiAgaWYgKG1zIDwgMTAwMCkgcmV0dXJuIGAke21zfW1zYDtcbiAgaWYgKG1zIDwgNjAwMDApIHJldHVybiBgJHsobXMgLyAxMDAwKS50b0ZpeGVkKDEpfXNgO1xuICBcbiAgY29uc3QgbWludXRlcyA9IE1hdGguZmxvb3IobXMgLyA2MDAwMCk7XG4gIGNvbnN0IHNlY29uZHMgPSBNYXRoLmZsb29yKChtcyAlIDYwMDAwKSAvIDEwMDApO1xuICByZXR1cm4gYCR7bWludXRlc31tICR7c2Vjb25kc31zYDtcbn1cbiJdfQ==
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fileExists = exports.writeFile = exports.readFile = exports.ensureDir = exports.truncate = exports.formatDate = exports.formatFileSize = void 0;
|
|
4
|
+
// src/utils/index.ts
|
|
5
|
+
var format_1 = require("./format");
|
|
6
|
+
Object.defineProperty(exports, "formatFileSize", { enumerable: true, get: function () { return format_1.formatFileSize; } });
|
|
7
|
+
Object.defineProperty(exports, "formatDate", { enumerable: true, get: function () { return format_1.formatDate; } });
|
|
8
|
+
Object.defineProperty(exports, "truncate", { enumerable: true, get: function () { return format_1.truncate; } });
|
|
9
|
+
var file_1 = require("./file");
|
|
10
|
+
Object.defineProperty(exports, "ensureDir", { enumerable: true, get: function () { return file_1.ensureDir; } });
|
|
11
|
+
Object.defineProperty(exports, "readFile", { enumerable: true, get: function () { return file_1.readFile; } });
|
|
12
|
+
Object.defineProperty(exports, "writeFile", { enumerable: true, get: function () { return file_1.writeFile; } });
|
|
13
|
+
Object.defineProperty(exports, "fileExists", { enumerable: true, get: function () { return file_1.fileExists; } });
|
|
14
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY29yZS91dGlscy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxxQkFBcUI7QUFDckIsbUNBQWdFO0FBQXZELHdHQUFBLGNBQWMsT0FBQTtBQUFFLG9HQUFBLFVBQVUsT0FBQTtBQUFFLGtHQUFBLFFBQVEsT0FBQTtBQUM3QywrQkFBb0U7QUFBM0QsaUdBQUEsU0FBUyxPQUFBO0FBQUUsZ0dBQUEsUUFBUSxPQUFBO0FBQUUsaUdBQUEsU0FBUyxPQUFBO0FBQUUsa0dBQUEsVUFBVSxPQUFBIiwic291cmNlc0NvbnRlbnQiOlsiLy8gc3JjL3V0aWxzL2luZGV4LnRzXG5leHBvcnQgeyBmb3JtYXRGaWxlU2l6ZSwgZm9ybWF0RGF0ZSwgdHJ1bmNhdGUgfSBmcm9tICcuL2Zvcm1hdCc7XG5leHBvcnQgeyBlbnN1cmVEaXIsIHJlYWRGaWxlLCB3cml0ZUZpbGUsIGZpbGVFeGlzdHMgfSBmcm9tICcuL2ZpbGUnO1xuIl19
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface ValidationResult {
|
|
2
|
+
valid: boolean;
|
|
3
|
+
errors: string[];
|
|
4
|
+
warnings: string[];
|
|
5
|
+
info: string[];
|
|
6
|
+
}
|
|
7
|
+
export declare class ConfigValidator {
|
|
8
|
+
private workspacePath;
|
|
9
|
+
private configPath;
|
|
10
|
+
constructor(workspacePath: string);
|
|
11
|
+
/**
|
|
12
|
+
* 验证配置内容(用于包装层拦截)
|
|
13
|
+
*/
|
|
14
|
+
validateContent(config: any): ValidationResult;
|
|
15
|
+
validate(configPath?: string): ValidationResult;
|
|
16
|
+
validateAndThrow(configPath?: string): void;
|
|
17
|
+
/**
|
|
18
|
+
* 比较两个配置的差异
|
|
19
|
+
*/
|
|
20
|
+
diffConfigs(oldConfigPath: string, newConfigPath: string): Array<{
|
|
21
|
+
field: string;
|
|
22
|
+
oldValue: any;
|
|
23
|
+
newValue: any;
|
|
24
|
+
}>;
|
|
25
|
+
}
|