@zooique/memora 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/agent.d.ts +155 -23
- package/dist/agent/agent.d.ts.map +1 -1
- package/dist/agent/agent.js +386 -124
- package/dist/agent/agent.js.map +1 -1
- package/dist/agent/assembler.d.ts +8 -2
- package/dist/agent/assembler.d.ts.map +1 -1
- package/dist/agent/assembler.js +17 -6
- package/dist/agent/assembler.js.map +1 -1
- package/dist/agent/builtinToolHandlers.d.ts +1 -1
- package/dist/agent/builtinToolHandlers.d.ts.map +1 -1
- package/dist/agent/builtinToolHandlers.js +5 -3
- package/dist/agent/builtinToolHandlers.js.map +1 -1
- package/dist/agent/builtinTools.d.ts +1 -1
- package/dist/agent/builtinTools.js +2 -2
- package/dist/agent/builtinTools.js.map +1 -1
- package/dist/agent/constants.d.ts +27 -6
- package/dist/agent/constants.d.ts.map +1 -1
- package/dist/agent/constants.js +27 -6
- package/dist/agent/constants.js.map +1 -1
- package/dist/agent/contextManager.d.ts +35 -9
- package/dist/agent/contextManager.d.ts.map +1 -1
- package/dist/agent/contextManager.js +138 -25
- package/dist/agent/contextManager.js.map +1 -1
- package/dist/agent/loop.d.ts +41 -11
- package/dist/agent/loop.d.ts.map +1 -1
- package/dist/agent/loop.js +143 -61
- package/dist/agent/loop.js.map +1 -1
- package/dist/agent/managers/archiveCoordinator.d.ts +100 -0
- package/dist/agent/managers/archiveCoordinator.d.ts.map +1 -0
- package/dist/agent/managers/archiveCoordinator.js +127 -0
- package/dist/agent/managers/archiveCoordinator.js.map +1 -0
- package/dist/agent/managers/autoConfigRefiner.d.ts.map +1 -1
- package/dist/agent/managers/autoConfigRefiner.js +1 -1
- package/dist/agent/managers/autoConfigRefiner.js.map +1 -1
- package/dist/agent/managers/configManager.d.ts +13 -2
- package/dist/agent/managers/configManager.d.ts.map +1 -1
- package/dist/agent/managers/configManager.js +13 -5
- package/dist/agent/managers/configManager.js.map +1 -1
- package/dist/agent/managers/insightExtractor.d.ts +36 -3
- package/dist/agent/managers/insightExtractor.d.ts.map +1 -1
- package/dist/agent/managers/insightExtractor.js +48 -11
- package/dist/agent/managers/insightExtractor.js.map +1 -1
- package/dist/agent/managers/memoryAdvisor.d.ts +4 -2
- package/dist/agent/managers/memoryAdvisor.d.ts.map +1 -1
- package/dist/agent/managers/memoryAdvisor.js +6 -4
- package/dist/agent/managers/memoryAdvisor.js.map +1 -1
- package/dist/agent/managers/memoryDecayScheduler.d.ts +113 -0
- package/dist/agent/managers/memoryDecayScheduler.d.ts.map +1 -0
- package/dist/agent/managers/memoryDecayScheduler.js +134 -0
- package/dist/agent/managers/memoryDecayScheduler.js.map +1 -0
- package/dist/agent/managers/memoryInspector.d.ts +70 -10
- package/dist/agent/managers/memoryInspector.d.ts.map +1 -1
- package/dist/agent/managers/memoryInspector.js +97 -23
- package/dist/agent/managers/memoryInspector.js.map +1 -1
- package/dist/agent/managers/sessionArchiver.d.ts +77 -0
- package/dist/agent/managers/sessionArchiver.d.ts.map +1 -0
- package/dist/agent/managers/sessionArchiver.js +175 -0
- package/dist/agent/managers/sessionArchiver.js.map +1 -0
- package/dist/agent/managers/sessionManager.d.ts +10 -0
- package/dist/agent/managers/sessionManager.d.ts.map +1 -1
- package/dist/agent/managers/sessionManager.js +26 -5
- package/dist/agent/managers/sessionManager.js.map +1 -1
- package/dist/agent/managers/workProjection.d.ts +1 -1
- package/dist/agent/managers/workProjection.d.ts.map +1 -1
- package/dist/agent/managers/workProjection.js +13 -10
- package/dist/agent/managers/workProjection.js.map +1 -1
- package/dist/agent/messageHistory.d.ts +1 -22
- package/dist/agent/messageHistory.d.ts.map +1 -1
- package/dist/agent/messageHistory.js +3 -19
- package/dist/agent/messageHistory.js.map +1 -1
- package/dist/agent/toolExecutor.d.ts +5 -18
- package/dist/agent/toolExecutor.d.ts.map +1 -1
- package/dist/agent/toolExecutor.js +7 -7
- package/dist/agent/toolExecutor.js.map +1 -1
- package/dist/agent/tracer.d.ts +8 -1
- package/dist/agent/tracer.d.ts.map +1 -1
- package/dist/agent/tracer.js +8 -1
- package/dist/agent/tracer.js.map +1 -1
- package/dist/agent/types.d.ts +29 -0
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/{managers/userFactExtractor.d.ts → userFactExtractor.d.ts} +2 -2
- package/dist/agent/userFactExtractor.d.ts.map +1 -0
- package/dist/agent/userFactExtractor.js.map +1 -0
- package/dist/config/loader.d.ts +4 -4
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +11 -2
- package/dist/config/loader.js.map +1 -1
- package/dist/eval/evalTypes.js +1 -1
- package/dist/eval/evalTypes.js.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/llm/embedding.d.ts.map +1 -1
- package/dist/llm/embedding.js +8 -6
- package/dist/llm/embedding.js.map +1 -1
- package/dist/llm/factory.d.ts.map +1 -1
- package/dist/llm/factory.js +2 -1
- package/dist/llm/factory.js.map +1 -1
- package/dist/llm/openaiCompatible.d.ts +9 -0
- package/dist/llm/openaiCompatible.d.ts.map +1 -1
- package/dist/llm/openaiCompatible.js +77 -33
- package/dist/llm/openaiCompatible.js.map +1 -1
- package/dist/llm/provider.d.ts +17 -3
- package/dist/llm/provider.d.ts.map +1 -1
- package/dist/llm/provider.js +6 -2
- package/dist/llm/provider.js.map +1 -1
- package/dist/logging/logger.d.ts.map +1 -1
- package/dist/logging/logger.js +25 -9
- package/dist/logging/logger.js.map +1 -1
- package/dist/memory/hybridMerge.d.ts +54 -0
- package/dist/memory/hybridMerge.d.ts.map +1 -0
- package/dist/memory/hybridMerge.js +36 -0
- package/dist/memory/hybridMerge.js.map +1 -0
- package/dist/memory/inMemoryStorage.d.ts +90 -15
- package/dist/memory/inMemoryStorage.d.ts.map +1 -1
- package/dist/memory/inMemoryStorage.js +179 -28
- package/dist/memory/inMemoryStorage.js.map +1 -1
- package/dist/memory/loader.js +1 -1
- package/dist/memory/loader.js.map +1 -1
- package/dist/memory/projectManager.d.ts +34 -5
- package/dist/memory/projectManager.d.ts.map +1 -1
- package/dist/memory/projectManager.js +98 -62
- package/dist/memory/projectManager.js.map +1 -1
- package/dist/memory/recall.d.ts +7 -18
- package/dist/memory/recall.d.ts.map +1 -1
- package/dist/memory/recall.js +14 -19
- package/dist/memory/recall.js.map +1 -1
- package/dist/memory/storageInterface.d.ts +81 -14
- package/dist/memory/storageInterface.d.ts.map +1 -1
- package/dist/memory/store.js +1 -1
- package/dist/memory/store.js.map +1 -1
- package/dist/memory/types.d.ts +7 -1
- package/dist/memory/types.d.ts.map +1 -1
- package/dist/memory/types.js +5 -1
- package/dist/memory/types.js.map +1 -1
- package/dist/memory/userProfile.d.ts +6 -6
- package/dist/memory/userProfile.d.ts.map +1 -1
- package/dist/memory/userProfile.js +20 -15
- package/dist/memory/userProfile.js.map +1 -1
- package/dist/memory/vectorStore.d.ts +35 -0
- package/dist/memory/vectorStore.d.ts.map +1 -1
- package/dist/memory/vectorStore.js +111 -2
- package/dist/memory/vectorStore.js.map +1 -1
- package/dist/persona/personaManager.d.ts +17 -4
- package/dist/persona/personaManager.d.ts.map +1 -1
- package/dist/persona/personaManager.js +44 -12
- package/dist/persona/personaManager.js.map +1 -1
- package/dist/security/pathGuard.d.ts +29 -7
- package/dist/security/pathGuard.d.ts.map +1 -1
- package/dist/security/pathGuard.js +148 -81
- package/dist/security/pathGuard.js.map +1 -1
- package/dist/skill/skillManager.d.ts +15 -0
- package/dist/skill/skillManager.d.ts.map +1 -1
- package/dist/skill/skillManager.js +25 -3
- package/dist/skill/skillManager.js.map +1 -1
- package/dist/skill/types.d.ts +7 -1
- package/dist/skill/types.d.ts.map +1 -1
- package/dist/utils/errors.d.ts +26 -7
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/errors.js +10 -18
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/eventEmitter.d.ts +9 -2
- package/dist/utils/eventEmitter.d.ts.map +1 -1
- package/dist/utils/eventEmitter.js +1 -1
- package/dist/utils/eventEmitter.js.map +1 -1
- package/dist/utils/frontmatter.d.ts +8 -1
- package/dist/utils/frontmatter.d.ts.map +1 -1
- package/dist/utils/frontmatter.js +14 -3
- package/dist/utils/frontmatter.js.map +1 -1
- package/dist/utils/path.d.ts +5 -1
- package/dist/utils/path.d.ts.map +1 -1
- package/dist/utils/path.js +5 -1
- package/dist/utils/path.js.map +1 -1
- package/dist/utils/safeTimer.d.ts +19 -0
- package/dist/utils/safeTimer.d.ts.map +1 -1
- package/dist/utils/safeTimer.js +27 -0
- package/dist/utils/safeTimer.js.map +1 -1
- package/dist/utils/segmenter.d.ts +0 -12
- package/dist/utils/segmenter.d.ts.map +1 -1
- package/dist/utils/segmenter.js +8 -3
- package/dist/utils/segmenter.js.map +1 -1
- package/dist/utils/strings.d.ts +1 -1
- package/dist/utils/strings.d.ts.map +1 -1
- package/dist/utils/strings.js +4 -2
- package/dist/utils/strings.js.map +1 -1
- package/package.json +1 -1
- package/dist/agent/managers/userFactExtractor.d.ts.map +0 -1
- package/dist/agent/managers/userFactExtractor.js.map +0 -1
- /package/dist/agent/{managers/userFactExtractor.js → userFactExtractor.js} +0 -0
|
@@ -78,10 +78,6 @@ export declare class PersonaManager {
|
|
|
78
78
|
setMode(mode: PersonaMode): void;
|
|
79
79
|
/** 获取当前激活模式 */
|
|
80
80
|
get currentMode(): PersonaMode;
|
|
81
|
-
/**
|
|
82
|
-
* 获取当前激活的角色
|
|
83
|
-
*/
|
|
84
|
-
get active(): Persona | null;
|
|
85
81
|
/**
|
|
86
82
|
* 获取角色列表
|
|
87
83
|
*/
|
|
@@ -93,6 +89,19 @@ export declare class PersonaManager {
|
|
|
93
89
|
* 若不清理,Agent 关闭后定时器仍会触发回调,在已关闭的实例上执行引发异常。
|
|
94
90
|
*/
|
|
95
91
|
close(): void;
|
|
92
|
+
/**
|
|
93
|
+
* 重载角色:清空内存缓存 + 重新扫描目录 + 同步 SQLite 索引 + 保持当前激活角色
|
|
94
|
+
*
|
|
95
|
+
* 事件驱动重载:confirmConfigSuggestion 写入 persona 文件后或用户手动编辑
|
|
96
|
+
* personas/ 目录后,调用此方法使当前会话立即生效,无需重启 Agent。
|
|
97
|
+
*
|
|
98
|
+
* 激活角色保持策略:
|
|
99
|
+
* - 若当前激活角色在重载后仍存在 → 更新为重载后的版本(内容可能已变更)
|
|
100
|
+
* - 若当前激活角色已被删除 → 回退到列表第一个角色(与 load() 默认行为一致)
|
|
101
|
+
*
|
|
102
|
+
* @returns 重载后的角色数量
|
|
103
|
+
*/
|
|
104
|
+
reload(): Promise<number>;
|
|
96
105
|
/**
|
|
97
106
|
* 构建 system prompt 中的角色段
|
|
98
107
|
*/
|
|
@@ -107,10 +116,14 @@ export declare class PersonaManager {
|
|
|
107
116
|
private scanPersonas;
|
|
108
117
|
/**
|
|
109
118
|
* 将所有角色写入 SQLite 索引
|
|
119
|
+
*
|
|
120
|
+
* 本函数循环体内无 await,作为同步函数实现。
|
|
110
121
|
*/
|
|
111
122
|
private writeAllToIndex;
|
|
112
123
|
/**
|
|
113
124
|
* 将单个角色写入 SQLite 索引
|
|
125
|
+
*
|
|
126
|
+
* 函数体无 await,作为同步函数实现。index.upsert 是同步方法。
|
|
114
127
|
*/
|
|
115
128
|
private writePersonaToIndex;
|
|
116
129
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"personaManager.d.ts","sourceRoot":"","sources":["../../src/persona/personaManager.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAKnE,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"personaManager.d.ts","sourceRoot":"","sources":["../../src/persona/personaManager.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAKnE,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AA6B/D;;GAEG;AACH,qBAAa,cAAc;IA0BvB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;IAC3B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC;IA1BzB,cAAc;IACd,OAAO,CAAC,aAAa,CAAwB;IAC7C,sBAAsB;IACtB,OAAO,CAAC,WAAW,CAAiB;IACpC,WAAW;IACX,OAAO,CAAC,IAAI,CAAuB;IACnC,0BAA0B;IAC1B,OAAO,CAAC,gBAAgB,CAAgB;IACxC,4BAA4B;IAC5B,OAAO,CAAC,YAAY,CAAS;IAC7B,cAAc;IACd,OAAO,CAAC,WAAW,CAA8C;IAEjE,gBAAgB;IAChB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAU;IAClD,gBAAgB;IAChB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,sBAAsB,CAAK;IACnD,qBAAqB;IACrB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAW;IAEjD;;;OAGG;gBAEgB,SAAS,CAAC,EAAE,MAAM,YAAA,EAClB,KAAK,CAAC,EAAE,cAAc,YAAA;IAGzC;;;;;OAKG;IACG,IAAI,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAqCnD;;OAEG;IACH,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED;;;;OAIG;IACH,SAAS,IAAI,OAAO,GAAG,IAAI;IAI3B;;;;;;;;;OASG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAyBnC;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IA8B3C;;;;OAIG;IACH,OAAO,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI;IAUhC,eAAe;IACf,IAAI,WAAW,IAAI,WAAW,CAE7B;IAED;;OAEG;IACH,IAAI,IAAI,IAAI,OAAO,EAAE,CAEpB;IAED;;;;;OAKG;IACH,KAAK,IAAI,IAAI;IAOb;;;;;;;;;;;OAWG;IACG,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;IA4B/B;;OAEG;IACH,iBAAiB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM;IAUxC;;OAEG;IACH,OAAO,CAAC,YAAY;IAqBpB;;OAEG;YACW,YAAY;IAyB1B;;;;OAIG;IACH,OAAO,CAAC,eAAe;IAQvB;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;IAe3B;;OAEG;IACH,OAAO,CAAC,oBAAoB;CAU7B"}
|
|
@@ -23,6 +23,7 @@ import { logger } from '../logging/logger.js';
|
|
|
23
23
|
import { configError } from '../utils/errors.js';
|
|
24
24
|
import { scanMarkdownDir, parseKeywords, resolveSubdir } from '../utils/scanner.js';
|
|
25
25
|
import { safeSetTimeout, clearSafeTimeout } from '../utils/safeTimer.js';
|
|
26
|
+
import { nowIso } from '../utils/time.js';
|
|
26
27
|
/**
|
|
27
28
|
* 从 frontmatter 解析 traits.* 键值对
|
|
28
29
|
*
|
|
@@ -91,12 +92,12 @@ export class PersonaManager {
|
|
|
91
92
|
if (this.personaList.length === 0) {
|
|
92
93
|
logger.warn({ personaCount: 0 }, '未找到任何角色文件,将使用默认角色');
|
|
93
94
|
this.activePersona = this.createDefaultPersona();
|
|
94
|
-
|
|
95
|
+
this.writePersonaToIndex(this.activePersona);
|
|
95
96
|
return this.buildSystemPrompt();
|
|
96
97
|
}
|
|
97
98
|
logger.info({ count: this.personaList.length, names: this.personaList.map((p) => p.name) }, '角色文件加载完成');
|
|
98
99
|
// 写入 SQLite 索引(persona 遵循万物皆记忆)
|
|
99
|
-
|
|
100
|
+
this.writeAllToIndex();
|
|
100
101
|
// 激活指定角色
|
|
101
102
|
if (activePersona) {
|
|
102
103
|
const found = this.personaList.find((p) => p.name === activePersona);
|
|
@@ -221,12 +222,6 @@ export class PersonaManager {
|
|
|
221
222
|
get currentMode() {
|
|
222
223
|
return this.mode;
|
|
223
224
|
}
|
|
224
|
-
/**
|
|
225
|
-
* 获取当前激活的角色
|
|
226
|
-
*/
|
|
227
|
-
get active() {
|
|
228
|
-
return this.activePersona;
|
|
229
|
-
}
|
|
230
225
|
/**
|
|
231
226
|
* 获取角色列表
|
|
232
227
|
*/
|
|
@@ -245,6 +240,39 @@ export class PersonaManager {
|
|
|
245
240
|
this.unlockTimer = null;
|
|
246
241
|
}
|
|
247
242
|
}
|
|
243
|
+
/**
|
|
244
|
+
* 重载角色:清空内存缓存 + 重新扫描目录 + 同步 SQLite 索引 + 保持当前激活角色
|
|
245
|
+
*
|
|
246
|
+
* 事件驱动重载:confirmConfigSuggestion 写入 persona 文件后或用户手动编辑
|
|
247
|
+
* personas/ 目录后,调用此方法使当前会话立即生效,无需重启 Agent。
|
|
248
|
+
*
|
|
249
|
+
* 激活角色保持策略:
|
|
250
|
+
* - 若当前激活角色在重载后仍存在 → 更新为重载后的版本(内容可能已变更)
|
|
251
|
+
* - 若当前激活角色已被删除 → 回退到列表第一个角色(与 load() 默认行为一致)
|
|
252
|
+
*
|
|
253
|
+
* @returns 重载后的角色数量
|
|
254
|
+
*/
|
|
255
|
+
async reload() {
|
|
256
|
+
const oldActiveName = this.activePersona?.name;
|
|
257
|
+
this.personaList = await this.scanPersonas();
|
|
258
|
+
this.writeAllToIndex();
|
|
259
|
+
// 保持当前激活角色(若仍存在),否则回退到第一个
|
|
260
|
+
if (oldActiveName) {
|
|
261
|
+
const found = this.personaList.find((p) => p.name === oldActiveName);
|
|
262
|
+
if (found) {
|
|
263
|
+
this.activePersona = found;
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
this.activePersona = this.personaList[0] ?? this.createDefaultPersona();
|
|
267
|
+
logger.warn({ oldActive: oldActiveName, newActive: this.activePersona.name }, '激活角色已被删除,回退到默认');
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
this.activePersona = this.personaList[0] ?? this.createDefaultPersona();
|
|
272
|
+
}
|
|
273
|
+
logger.info({ count: this.personaList.length, active: this.activePersona.name }, '角色已重载');
|
|
274
|
+
return this.personaList.length;
|
|
275
|
+
}
|
|
248
276
|
/**
|
|
249
277
|
* 构建 system prompt 中的角色段
|
|
250
278
|
*/
|
|
@@ -305,22 +333,26 @@ export class PersonaManager {
|
|
|
305
333
|
}
|
|
306
334
|
/**
|
|
307
335
|
* 将所有角色写入 SQLite 索引
|
|
336
|
+
*
|
|
337
|
+
* 本函数循环体内无 await,作为同步函数实现。
|
|
308
338
|
*/
|
|
309
|
-
|
|
339
|
+
writeAllToIndex() {
|
|
310
340
|
if (!this.index)
|
|
311
341
|
return;
|
|
312
342
|
for (const persona of this.personaList) {
|
|
313
|
-
|
|
343
|
+
this.writePersonaToIndex(persona);
|
|
314
344
|
}
|
|
315
345
|
logger.info({ count: this.personaList.length }, '角色记忆已写入 SQLite');
|
|
316
346
|
}
|
|
317
347
|
/**
|
|
318
348
|
* 将单个角色写入 SQLite 索引
|
|
349
|
+
*
|
|
350
|
+
* 函数体无 await,作为同步函数实现。index.upsert 是同步方法。
|
|
319
351
|
*/
|
|
320
|
-
|
|
352
|
+
writePersonaToIndex(persona) {
|
|
321
353
|
if (!this.index)
|
|
322
354
|
return;
|
|
323
|
-
const now =
|
|
355
|
+
const now = nowIso();
|
|
324
356
|
const memory = {
|
|
325
357
|
id: persona.id,
|
|
326
358
|
content: persona.content,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"personaManager.js","sourceRoot":"","sources":["../../src/persona/personaManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnF,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"personaManager.js","sourceRoot":"","sources":["../../src/persona/personaManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,7 +7,7 @@ export interface AuditEvent {
|
|
|
7
7
|
path: string;
|
|
8
8
|
/** 工具名(read_file / write_file / 自定义工具名) */
|
|
9
9
|
tool?: string;
|
|
10
|
-
/**
|
|
10
|
+
/** 调用链来源(builtin / custom / system),标记安全检查的触发方 */
|
|
11
11
|
source?: 'builtin' | 'custom' | 'system';
|
|
12
12
|
/** 用户决策(写入二次确认场景) */
|
|
13
13
|
decision?: WriteDecision;
|
|
@@ -43,6 +43,10 @@ export interface WriteConfirmationInfo {
|
|
|
43
43
|
permission: Permission;
|
|
44
44
|
/** 是否需要确认(owner + confirmWrites=false 时为 false,宿主可跳过弹窗) */
|
|
45
45
|
needsConfirm: boolean;
|
|
46
|
+
/** 文件当前内容预览(截断到 10KB,null 表示新文件)—— 供宿主 UI 展示 diff */
|
|
47
|
+
beforeContent?: string | null;
|
|
48
|
+
/** 写入后内容预览(截断到 10KB)—— 供宿主 UI 展示 diff */
|
|
49
|
+
afterContent?: string;
|
|
46
50
|
}
|
|
47
51
|
export declare class SecurityGuard {
|
|
48
52
|
/** owner 是否启用写入二次确认;guest 强制开启 */
|
|
@@ -96,23 +100,41 @@ export declare class SecurityGuard {
|
|
|
96
100
|
/**
|
|
97
101
|
* 断言路径允许访问
|
|
98
102
|
* @throws Error 不在白名单时
|
|
99
|
-
* @param source
|
|
103
|
+
* @param source 调用链来源标记
|
|
100
104
|
*/
|
|
101
105
|
assertPathAllowed(absolutePath: string, tool?: string, source?: 'builtin' | 'custom' | 'system'): void;
|
|
102
106
|
/**
|
|
103
|
-
*
|
|
107
|
+
* 写入操作前请求用户确认
|
|
104
108
|
*
|
|
105
109
|
* 规则:
|
|
106
110
|
* - guest 模式:始终要求确认
|
|
107
111
|
* - owner + confirmWrites=true:要求确认
|
|
108
112
|
* - owner + confirmWrites=false:自动批准
|
|
109
113
|
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
114
|
+
* 决策(fail-closed):
|
|
115
|
+
* - 需要确认时,必须通过 onWriteConfirmation() 注入 confirmationHandler
|
|
116
|
+
* - 未注入 handler 时,**直接拒绝写入**(返回 false)
|
|
117
|
+
* - 理由:内核纯逻辑库不应依赖交互式终端 I/O;宿主程序负责提供确认 UI
|
|
118
|
+
* - 安全优先:未配置 = 拒绝,避免无意识放行
|
|
112
119
|
*
|
|
113
|
-
* @returns true 确认通过;false
|
|
120
|
+
* @returns true 确认通过;false 用户拒绝或未注入 handler(fail-closed)
|
|
114
121
|
*/
|
|
115
|
-
requestWriteConfirmation(targetPath: string, tool: string, description?: string
|
|
122
|
+
requestWriteConfirmation(targetPath: string, tool: string, description?: string,
|
|
123
|
+
/** diff 内容选项(供宿主 UI 展示变更预览,自动截断到 10KB) */
|
|
124
|
+
options?: {
|
|
125
|
+
beforeContent?: string | null;
|
|
126
|
+
afterContent?: string;
|
|
127
|
+
}): Promise<boolean>;
|
|
128
|
+
/**
|
|
129
|
+
* 通过宿主注入的 confirmationHandler 进行写入确认
|
|
130
|
+
*
|
|
131
|
+
* 从 requestWriteConfirmation 拆分。抛错视为拒绝(fail-closed 安全优先)。
|
|
132
|
+
* 此方法是唯一的确认执行路径。
|
|
133
|
+
*
|
|
134
|
+
* @param info 确认信息(含 diff 内容)
|
|
135
|
+
* @returns true 确认通过;false 用户拒绝或回调异常
|
|
136
|
+
*/
|
|
137
|
+
private confirmViaHandler;
|
|
116
138
|
/**
|
|
117
139
|
* 触发审计事件 + 写入日志 + 通知订阅者
|
|
118
140
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pathGuard.d.ts","sourceRoot":"","sources":["../../src/security/pathGuard.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pathGuard.d.ts","sourceRoot":"","sources":["../../src/security/pathGuard.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,35 +1,100 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 路径白名单 + 审计日志
|
|
3
3
|
*
|
|
4
|
-
* 4
|
|
4
|
+
* 4 类允许根 + 27 类禁止规则
|
|
5
5
|
* 详见 ADR-006 · 安全模型
|
|
6
|
-
*
|
|
6
|
+
*
|
|
7
|
+
* 写入二次确认 + 审计日志:未注入 confirmationHandler 时 fail-closed 拒绝写入。
|
|
8
|
+
* 内核纯逻辑库不应依赖交互式终端 I/O(node:readline/promises + node:process),
|
|
9
|
+
* 宿主程序应通过 onWriteConfirmation() 注入自己的确认 UI(Electron/Web/CLI 各自实现)。
|
|
7
10
|
*/
|
|
8
|
-
import { resolve, sep } from 'node:path';
|
|
9
|
-
import {
|
|
10
|
-
import { stdin, stdout } from 'node:process';
|
|
11
|
+
import { resolve, sep, dirname, basename, join } from 'node:path';
|
|
12
|
+
import { realpathSync } from 'node:fs';
|
|
11
13
|
import { logger } from '../logging/logger.js';
|
|
12
14
|
import { securityError, toError } from '../utils/errors.js';
|
|
13
15
|
import { expandHome } from '../utils/path.js';
|
|
16
|
+
import { nowIso } from '../utils/time.js';
|
|
17
|
+
/**
|
|
18
|
+
* 解析路径的真实绝对路径(解析符号链接链)
|
|
19
|
+
*
|
|
20
|
+
* 安全考量:若不解析符号链接,攻击者可在项目内放置指向 /etc 的符号链接,
|
|
21
|
+
* 绕过白名单前缀匹配访问任意系统目录(P0 符号链接逃逸漏洞)。
|
|
22
|
+
*
|
|
23
|
+
* 策略:
|
|
24
|
+
* - 路径存在时:realpathSync 解析完整符号链接链
|
|
25
|
+
* - 路径不存在时(写入新文件场景):逐级向上查找已存在的父目录并 realpath,再拼接不存在部分
|
|
26
|
+
* - 全程不存在时:回退到 resolve()(白名单/黑名单仍会兜底校验)
|
|
27
|
+
*
|
|
28
|
+
* @param p 任意路径(相对或绝对)
|
|
29
|
+
* @returns 解析符号链接后的真实绝对路径
|
|
30
|
+
*/
|
|
31
|
+
function resolveRealpath(p) {
|
|
32
|
+
const resolved = resolve(p);
|
|
33
|
+
try {
|
|
34
|
+
return realpathSync(resolved);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
// 路径不存在 - 递归解析已存在的父目录
|
|
38
|
+
const parent = dirname(resolved);
|
|
39
|
+
const base = basename(resolved);
|
|
40
|
+
try {
|
|
41
|
+
const realParent = realpathSync(parent);
|
|
42
|
+
return join(realParent, base);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
// 父目录也不存在 - 继续向上递归
|
|
46
|
+
const realGrandParent = resolveRealpath(parent);
|
|
47
|
+
return join(realGrandParent, base);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
14
51
|
const BLOCKED_PATTERNS = [
|
|
15
|
-
//
|
|
52
|
+
// ─── 系统凭证文件(跨平台,路径段匹配)───
|
|
16
53
|
/(^|[\\/])\.ssh([\\/]|$)/i,
|
|
17
54
|
/(^|[\\/])\.gnupg([\\/]|$)/i,
|
|
18
55
|
/(^|[\\/])\.netrc$/i,
|
|
19
56
|
/(^|[\\/])\.pgpass$/i,
|
|
20
|
-
|
|
21
|
-
//
|
|
57
|
+
// ─── 包管理器凭证 ───
|
|
58
|
+
/(^|[\\/])\.gitconfig$/i, // Git 配置(可能含 credential helper token)
|
|
59
|
+
/(^|[\\/])\.git-credentials$/i, // Git credential store 明文存储
|
|
60
|
+
/(^|[\\/])\.npmrc$/i, // npm authToken
|
|
61
|
+
/(^|[\\/])\.pypirc$/i, // PyPI 上传凭证
|
|
62
|
+
/(^|[\\/])\.gem[\\/]credentials$/i, // RubyGems push 凭证
|
|
63
|
+
/(^|[\\/])\.composer[\\/]auth\.json$/i, // Composer 凭证
|
|
64
|
+
/(^|[\\/])\.htpasswd$/i, // Apache Basic Auth 凭证
|
|
65
|
+
// ─── Linux/macOS 特定凭证文件(向后兼容保留)───
|
|
66
|
+
/[\\/]etc[\\/]passwd/i, // 用户密码哈希
|
|
67
|
+
/[\\/]etc[\\/]shadow/i,
|
|
68
|
+
/[\\/]etc[\\/]gshadow/i, // 组密码哈希
|
|
69
|
+
/[\\/]etc[\\/]sudoers/i, // sudo 配置
|
|
70
|
+
// ─── 云服务凭证 ───
|
|
22
71
|
/(^|[\\/])\.aws([\\/]|$)/i,
|
|
23
72
|
/(^|[\\/])\.azure([\\/]|$)/i,
|
|
24
73
|
/(^|[\\/])\.docker([\\/]|$)/i,
|
|
25
74
|
/(^|[\\/])\.kube([\\/]|$)/i,
|
|
26
|
-
/[\\/]gcloud([\\/]|$)/i,
|
|
27
|
-
//
|
|
28
|
-
/(^|[\\/])\.env
|
|
29
|
-
// 系统目录
|
|
30
|
-
/[\\/]
|
|
31
|
-
/[\\/]
|
|
75
|
+
/(^|[\\/])\.config[\\/]gcloud([\\/]|$)/i, // gcloud 配置(加 .config 前缀边界,避免误拦用户 gcloud-tools 目录)
|
|
76
|
+
// ─── 环境变量文件(.env / .env.local / .env.production.local 等多段后缀)───
|
|
77
|
+
/(^|[\\/])\.env(\.[^\\/]+)?$/i,
|
|
78
|
+
// ─── Windows 系统目录 ───
|
|
79
|
+
/[\\/]Windows([\\/]|$)/i, // C:\Windows(含 System、System32 等子目录)
|
|
80
|
+
/[\\/]Program Files([\\/]|$)/i, // C:\Program Files
|
|
81
|
+
/[\\/]Program Files \(x86\)([\\/]|$)/i, // C:\Program Files (x86)
|
|
82
|
+
/[\\/]ProgramData([\\/]|$)/i, // C:\ProgramData(系统级应用数据)
|
|
83
|
+
// ─── Linux/macOS 系统目录(根目录锚定 ^/,避免误伤项目内同名目录)───
|
|
84
|
+
/^\/(etc|usr|bin|sbin|var|root|home|lib|lib64|opt)([\\/]|$)/i,
|
|
85
|
+
// ─── Linux/macOS 虚拟文件系统 + 启动目录(根目录锚定)───
|
|
86
|
+
/^\/(proc|sys|boot)([\\/]|$)/i,
|
|
32
87
|
];
|
|
88
|
+
/** diff 内容最大长度(10KB),防止大文件内容撑爆 IPC 传输和 UI 渲染 */
|
|
89
|
+
const MAX_DIFF_CONTENT_LENGTH = 10240;
|
|
90
|
+
function truncateForDiff(content) {
|
|
91
|
+
if (content === null || content === undefined)
|
|
92
|
+
return content;
|
|
93
|
+
if (content.length <= MAX_DIFF_CONTENT_LENGTH)
|
|
94
|
+
return content;
|
|
95
|
+
// 超过上限时截断并追加标记,让用户知道内容被裁剪
|
|
96
|
+
return content.slice(0, MAX_DIFF_CONTENT_LENGTH) + `\n...(已截断,共 ${content.length} 字符)`;
|
|
97
|
+
}
|
|
33
98
|
export class SecurityGuard {
|
|
34
99
|
confirmWrites;
|
|
35
100
|
permission;
|
|
@@ -56,19 +121,20 @@ export class SecurityGuard {
|
|
|
56
121
|
agentDataDir) {
|
|
57
122
|
this.confirmWrites = confirmWrites;
|
|
58
123
|
this.permission = permission;
|
|
59
|
-
//
|
|
124
|
+
// 构建白名单根目录列表:使用 resolveRealpath 解析符号链接,
|
|
125
|
+
// 确保白名单基准是真实路径,与 assertPathAllowed 中的 resolveRealpath 对齐
|
|
60
126
|
this.allowedRoots = [
|
|
61
|
-
|
|
62
|
-
|
|
127
|
+
resolveRealpath(expandHome(projectPath)),
|
|
128
|
+
resolveRealpath(expandHome(memoraDir)),
|
|
63
129
|
];
|
|
64
130
|
if (configDir) {
|
|
65
|
-
this.allowedRoots.push(
|
|
131
|
+
this.allowedRoots.push(resolveRealpath(expandHome(configDir)));
|
|
66
132
|
}
|
|
67
133
|
if (agentDataDir) {
|
|
68
|
-
this.allowedRoots.push(
|
|
134
|
+
this.allowedRoots.push(resolveRealpath(expandHome(agentDataDir)));
|
|
69
135
|
}
|
|
70
136
|
for (const p of extraAllowedPaths) {
|
|
71
|
-
this.allowedRoots.push(
|
|
137
|
+
this.allowedRoots.push(resolveRealpath(expandHome(p)));
|
|
72
138
|
}
|
|
73
139
|
}
|
|
74
140
|
/**
|
|
@@ -108,12 +174,13 @@ export class SecurityGuard {
|
|
|
108
174
|
/**
|
|
109
175
|
* 断言路径允许访问
|
|
110
176
|
* @throws Error 不在白名单时
|
|
111
|
-
* @param source
|
|
177
|
+
* @param source 调用链来源标记
|
|
112
178
|
*/
|
|
113
179
|
assertPathAllowed(absolutePath, tool, source) {
|
|
114
|
-
//
|
|
180
|
+
// NFKC 规范化,防止全角字符(如 ../)绕过黑名单正则
|
|
115
181
|
const normalized = absolutePath.normalize('NFKC');
|
|
116
|
-
|
|
182
|
+
// resolveRealpath 解析符号链接,防止通过项目内符号链接逃逸到系统目录
|
|
183
|
+
const resolved = resolveRealpath(normalized);
|
|
117
184
|
// 1. 黑名单优先
|
|
118
185
|
for (const pattern of BLOCKED_PATTERNS) {
|
|
119
186
|
if (pattern.test(resolved)) {
|
|
@@ -123,7 +190,7 @@ export class SecurityGuard {
|
|
|
123
190
|
tool,
|
|
124
191
|
source,
|
|
125
192
|
reason: `命中黑名单规则 (${pattern})`,
|
|
126
|
-
timestamp:
|
|
193
|
+
timestamp: nowIso(),
|
|
127
194
|
});
|
|
128
195
|
throw securityError('禁止访问:路径命中黑名单', `路径 ${resolved} 命中黑名单规则 (${pattern})`, ['检查路径是否正确', '如需访问该路径,请联系管理员添加白名单']);
|
|
129
196
|
}
|
|
@@ -136,7 +203,7 @@ export class SecurityGuard {
|
|
|
136
203
|
path: resolved,
|
|
137
204
|
tool,
|
|
138
205
|
source,
|
|
139
|
-
timestamp:
|
|
206
|
+
timestamp: nowIso(),
|
|
140
207
|
});
|
|
141
208
|
return;
|
|
142
209
|
}
|
|
@@ -147,7 +214,7 @@ export class SecurityGuard {
|
|
|
147
214
|
tool,
|
|
148
215
|
source,
|
|
149
216
|
reason: '路径越界,不在白名单内',
|
|
150
|
-
timestamp:
|
|
217
|
+
timestamp: nowIso(),
|
|
151
218
|
});
|
|
152
219
|
throw securityError('路径越界', `${resolved} 不在白名单内`, [
|
|
153
220
|
'检查路径是否在项目目录内',
|
|
@@ -155,96 +222,96 @@ export class SecurityGuard {
|
|
|
155
222
|
]);
|
|
156
223
|
}
|
|
157
224
|
/**
|
|
158
|
-
*
|
|
225
|
+
* 写入操作前请求用户确认
|
|
159
226
|
*
|
|
160
227
|
* 规则:
|
|
161
228
|
* - guest 模式:始终要求确认
|
|
162
229
|
* - owner + confirmWrites=true:要求确认
|
|
163
230
|
* - owner + confirmWrites=false:自动批准
|
|
164
231
|
*
|
|
165
|
-
*
|
|
166
|
-
*
|
|
232
|
+
* 决策(fail-closed):
|
|
233
|
+
* - 需要确认时,必须通过 onWriteConfirmation() 注入 confirmationHandler
|
|
234
|
+
* - 未注入 handler 时,**直接拒绝写入**(返回 false)
|
|
235
|
+
* - 理由:内核纯逻辑库不应依赖交互式终端 I/O;宿主程序负责提供确认 UI
|
|
236
|
+
* - 安全优先:未配置 = 拒绝,避免无意识放行
|
|
167
237
|
*
|
|
168
|
-
* @returns true 确认通过;false
|
|
238
|
+
* @returns true 确认通过;false 用户拒绝或未注入 handler(fail-closed)
|
|
169
239
|
*/
|
|
170
|
-
async requestWriteConfirmation(targetPath, tool, description
|
|
240
|
+
async requestWriteConfirmation(targetPath, tool, description,
|
|
241
|
+
/** diff 内容选项(供宿主 UI 展示变更预览,自动截断到 10KB) */
|
|
242
|
+
options) {
|
|
171
243
|
const needConfirm = this.permission === 'guest' || this.confirmWrites;
|
|
244
|
+
// 无需确认:直接放行并记录审计
|
|
172
245
|
if (!needConfirm) {
|
|
173
246
|
this.emitAudit({
|
|
174
247
|
type: 'write-auto',
|
|
175
248
|
path: targetPath,
|
|
176
249
|
tool,
|
|
177
250
|
decision: 'auto-approved',
|
|
178
|
-
timestamp:
|
|
251
|
+
timestamp: nowIso(),
|
|
179
252
|
});
|
|
180
253
|
return true;
|
|
181
254
|
}
|
|
255
|
+
// 构建确认信息(透传 diff 内容,供宿主 UI 展示变更预览)
|
|
182
256
|
const info = {
|
|
183
257
|
targetPath,
|
|
184
258
|
tool,
|
|
185
259
|
description,
|
|
186
260
|
permission: this.permission,
|
|
187
261
|
needsConfirm: needConfirm,
|
|
262
|
+
beforeContent: truncateForDiff(options?.beforeContent),
|
|
263
|
+
afterContent: truncateForDiff(options?.afterContent),
|
|
188
264
|
};
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
catch (err) {
|
|
202
|
-
// 抛错视为拒绝(fail-closed 安全优先)
|
|
203
|
-
logger.warn({ err, targetPath }, '写入确认回调异常,视为拒绝');
|
|
204
|
-
this.emitAudit({
|
|
205
|
-
type: 'write-decline',
|
|
206
|
-
path: targetPath,
|
|
207
|
-
tool,
|
|
208
|
-
decision: 'declined',
|
|
209
|
-
reason: `回调异常:${toError(err).message}`,
|
|
210
|
-
timestamp: new Date().toISOString(),
|
|
211
|
-
});
|
|
212
|
-
return false;
|
|
213
|
-
}
|
|
265
|
+
// 未注入 confirmationHandler 时 fail-closed 拒绝
|
|
266
|
+
if (!this.confirmationHandler) {
|
|
267
|
+
logger.warn({ targetPath, tool, permission: this.permission }, '写入确认失败:未注入 confirmationHandler,fail-closed 拒绝写入');
|
|
268
|
+
this.emitAudit({
|
|
269
|
+
type: 'write-decline',
|
|
270
|
+
path: targetPath,
|
|
271
|
+
tool,
|
|
272
|
+
decision: 'declined',
|
|
273
|
+
reason: '未注入 confirmationHandler(fail-closed)',
|
|
274
|
+
timestamp: nowIso(),
|
|
275
|
+
});
|
|
276
|
+
return false;
|
|
214
277
|
}
|
|
215
|
-
//
|
|
216
|
-
|
|
278
|
+
// 走宿主注入的 confirmationHandler(此处 handler 必非空,上方已 fail-closed 拦截)
|
|
279
|
+
return this.confirmViaHandler(info, targetPath, tool);
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* 通过宿主注入的 confirmationHandler 进行写入确认
|
|
283
|
+
*
|
|
284
|
+
* 从 requestWriteConfirmation 拆分。抛错视为拒绝(fail-closed 安全优先)。
|
|
285
|
+
* 此方法是唯一的确认执行路径。
|
|
286
|
+
*
|
|
287
|
+
* @param info 确认信息(含 diff 内容)
|
|
288
|
+
* @returns true 确认通过;false 用户拒绝或回调异常
|
|
289
|
+
*/
|
|
290
|
+
async confirmViaHandler(info, targetPath, tool) {
|
|
217
291
|
try {
|
|
218
|
-
const
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
decision: 'confirmed',
|
|
232
|
-
timestamp: new Date().toISOString(),
|
|
233
|
-
});
|
|
234
|
-
return true;
|
|
235
|
-
}
|
|
292
|
+
const ok = await this.confirmationHandler(info);
|
|
293
|
+
this.emitAudit({
|
|
294
|
+
type: ok ? 'write-confirm' : 'write-decline',
|
|
295
|
+
path: targetPath,
|
|
296
|
+
tool,
|
|
297
|
+
decision: ok ? 'confirmed' : 'declined',
|
|
298
|
+
timestamp: nowIso(),
|
|
299
|
+
});
|
|
300
|
+
return ok;
|
|
301
|
+
}
|
|
302
|
+
catch (err) {
|
|
303
|
+
// 抛错视为拒绝(fail-closed 安全优先)
|
|
304
|
+
logger.warn({ err, targetPath }, '写入确认回调异常,视为拒绝');
|
|
236
305
|
this.emitAudit({
|
|
237
306
|
type: 'write-decline',
|
|
238
307
|
path: targetPath,
|
|
239
308
|
tool,
|
|
240
309
|
decision: 'declined',
|
|
241
|
-
|
|
310
|
+
reason: `回调异常:${toError(err).message}`,
|
|
311
|
+
timestamp: nowIso(),
|
|
242
312
|
});
|
|
243
313
|
return false;
|
|
244
314
|
}
|
|
245
|
-
finally {
|
|
246
|
-
rl.close();
|
|
247
|
-
}
|
|
248
315
|
}
|
|
249
316
|
/**
|
|
250
317
|
* 触发审计事件 + 写入日志 + 通知订阅者
|