@zooique/memora 1.0.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/agent/agent.d.ts +66 -99
- package/dist/agent/agent.d.ts.map +1 -1
- package/dist/agent/agent.js +263 -208
- package/dist/agent/agent.js.map +1 -1
- package/dist/agent/assembler.d.ts +3 -3
- package/dist/agent/assembler.d.ts.map +1 -1
- package/dist/agent/assembler.js +10 -9
- 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 -4
- package/dist/agent/builtinToolHandlers.js.map +1 -1
- package/dist/agent/loop.d.ts +79 -1
- package/dist/agent/loop.d.ts.map +1 -1
- package/dist/agent/loop.js +315 -189
- package/dist/agent/loop.js.map +1 -1
- package/dist/agent/managers/chatLockManager.d.ts +116 -0
- package/dist/agent/managers/chatLockManager.d.ts.map +1 -0
- package/dist/agent/managers/chatLockManager.js +191 -0
- package/dist/agent/managers/chatLockManager.js.map +1 -0
- package/dist/agent/managers/insightExtractor.d.ts +31 -3
- package/dist/agent/managers/insightExtractor.d.ts.map +1 -1
- package/dist/agent/managers/insightExtractor.js +122 -51
- package/dist/agent/managers/insightExtractor.js.map +1 -1
- package/dist/agent/managers/memoryAdvisor.d.ts +102 -2
- package/dist/agent/managers/memoryAdvisor.d.ts.map +1 -1
- package/dist/agent/managers/memoryAdvisor.js +262 -4
- package/dist/agent/managers/memoryAdvisor.js.map +1 -1
- package/dist/agent/managers/memoryDecayScheduler.d.ts +85 -0
- package/dist/agent/managers/memoryDecayScheduler.d.ts.map +1 -1
- package/dist/agent/managers/memoryDecayScheduler.js +215 -0
- package/dist/agent/managers/memoryDecayScheduler.js.map +1 -1
- package/dist/agent/managers/memoryInspector.d.ts +222 -14
- package/dist/agent/managers/memoryInspector.d.ts.map +1 -1
- package/dist/agent/managers/memoryInspector.js +436 -10
- package/dist/agent/managers/memoryInspector.js.map +1 -1
- package/dist/agent/managers/relationBuilder.d.ts +4 -4
- package/dist/agent/managers/relationBuilder.d.ts.map +1 -1
- package/dist/agent/managers/relationBuilder.js +3 -2
- package/dist/agent/managers/relationBuilder.js.map +1 -1
- package/dist/agent/managers/sessionArchiver.d.ts +6 -0
- package/dist/agent/managers/sessionArchiver.d.ts.map +1 -1
- package/dist/agent/managers/sessionArchiver.js +68 -8
- package/dist/agent/managers/sessionArchiver.js.map +1 -1
- package/dist/agent/managers/sessionManager.d.ts.map +1 -1
- package/dist/agent/managers/sessionManager.js +9 -17
- package/dist/agent/managers/sessionManager.js.map +1 -1
- package/dist/agent/managers/textPolishManager.d.ts +62 -0
- package/dist/agent/managers/textPolishManager.d.ts.map +1 -0
- package/dist/agent/managers/textPolishManager.js +99 -0
- package/dist/agent/managers/textPolishManager.js.map +1 -0
- package/dist/agent/personaMatcher.d.ts +29 -0
- package/dist/agent/personaMatcher.d.ts.map +1 -0
- package/dist/agent/personaMatcher.js +60 -0
- package/dist/agent/personaMatcher.js.map +1 -0
- package/dist/agent/toolExecutor.d.ts +2 -2
- package/dist/agent/toolExecutor.d.ts.map +1 -1
- package/dist/agent/toolExecutor.js +2 -1
- package/dist/agent/toolExecutor.js.map +1 -1
- package/dist/agent/tracer.d.ts +31 -0
- package/dist/agent/tracer.d.ts.map +1 -1
- package/dist/agent/tracer.js +31 -0
- package/dist/agent/tracer.js.map +1 -1
- package/dist/agent/types.d.ts +124 -0
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js +38 -0
- package/dist/agent/types.js.map +1 -1
- package/dist/config/loader.d.ts +4 -4
- package/dist/config/loader.js +23 -1
- package/dist/config/loader.js.map +1 -1
- package/dist/eval/evalRunner.d.ts +94 -0
- package/dist/eval/evalRunner.d.ts.map +1 -0
- package/dist/eval/evalRunner.js +141 -0
- package/dist/eval/evalRunner.js.map +1 -0
- package/dist/eval/evalTypes.d.ts +21 -0
- package/dist/eval/evalTypes.d.ts.map +1 -1
- package/dist/eval/evalTypes.js +15 -0
- package/dist/eval/evalTypes.js.map +1 -1
- package/dist/eval/scenarios.d.ts +33 -0
- package/dist/eval/scenarios.d.ts.map +1 -0
- package/dist/eval/scenarios.js +109 -0
- package/dist/eval/scenarios.js.map +1 -0
- package/dist/index.d.ts +41 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +36 -5
- package/dist/index.js.map +1 -1
- package/dist/llm/abortSignal.d.ts +27 -0
- package/dist/llm/abortSignal.d.ts.map +1 -0
- package/dist/llm/abortSignal.js +44 -0
- package/dist/llm/abortSignal.js.map +1 -0
- package/dist/llm/embedding.d.ts +1 -12
- package/dist/llm/embedding.d.ts.map +1 -1
- package/dist/llm/embedding.js +5 -17
- package/dist/llm/embedding.js.map +1 -1
- package/dist/llm/openaiCompatible.d.ts.map +1 -1
- package/dist/llm/openaiCompatible.js +15 -25
- package/dist/llm/openaiCompatible.js.map +1 -1
- package/dist/memory/inMemoryStorage.d.ts.map +1 -1
- package/dist/memory/inMemoryStorage.js +7 -6
- package/dist/memory/inMemoryStorage.js.map +1 -1
- package/dist/memory/lockManager.d.ts.map +1 -1
- package/dist/memory/lockManager.js +4 -12
- package/dist/memory/lockManager.js.map +1 -1
- package/dist/memory/projectManager.d.ts +6 -6
- package/dist/memory/projectManager.d.ts.map +1 -1
- package/dist/memory/projectManager.js +12 -12
- package/dist/memory/projectManager.js.map +1 -1
- package/dist/memory/projectRegistry.d.ts.map +1 -1
- package/dist/memory/projectRegistry.js +4 -12
- package/dist/memory/projectRegistry.js.map +1 -1
- package/dist/memory/recall.js +2 -2
- package/dist/memory/recall.js.map +1 -1
- package/dist/memory/sourceValidation.d.ts +6 -0
- package/dist/memory/sourceValidation.d.ts.map +1 -1
- package/dist/memory/sourceValidation.js +3 -1
- package/dist/memory/sourceValidation.js.map +1 -1
- package/dist/memory/vectorStore.d.ts +16 -2
- package/dist/memory/vectorStore.d.ts.map +1 -1
- package/dist/memory/vectorStore.js.map +1 -1
- package/dist/persona/personaManager.d.ts +30 -4
- package/dist/persona/personaManager.d.ts.map +1 -1
- package/dist/persona/personaManager.js +47 -14
- package/dist/persona/personaManager.js.map +1 -1
- package/dist/skill/skillManager.d.ts.map +1 -1
- package/dist/skill/skillManager.js +2 -1
- package/dist/skill/skillManager.js.map +1 -1
- package/dist/utils/array.d.ts +24 -0
- package/dist/utils/array.d.ts.map +1 -0
- package/dist/utils/array.js +24 -0
- package/dist/utils/array.js.map +1 -0
- package/dist/utils/errors.d.ts +10 -8
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/errors.js +12 -9
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/eventEmitter.d.ts +7 -0
- package/dist/utils/eventEmitter.d.ts.map +1 -1
- package/dist/utils/eventEmitter.js.map +1 -1
- package/dist/utils/objects.d.ts +17 -0
- package/dist/utils/objects.d.ts.map +1 -0
- package/dist/utils/objects.js +19 -0
- package/dist/utils/objects.js.map +1 -0
- package/dist/utils/segmenter.d.ts +11 -0
- package/dist/utils/segmenter.d.ts.map +1 -1
- package/dist/utils/segmenter.js +13 -0
- package/dist/utils/segmenter.js.map +1 -1
- package/dist/utils/strings.d.ts +22 -1
- package/dist/utils/strings.d.ts.map +1 -1
- package/dist/utils/strings.js +29 -1
- package/dist/utils/strings.js.map +1 -1
- package/dist/utils/time.d.ts +18 -3
- package/dist/utils/time.d.ts.map +1 -1
- package/dist/utils/time.js +24 -8
- package/dist/utils/time.js.map +1 -1
- package/dist/utils/toError.d.ts +8 -4
- package/dist/utils/toError.d.ts.map +1 -1
- package/dist/utils/toError.js +25 -5
- package/dist/utils/toError.js.map +1 -1
- package/package.json +11 -1
- package/dist/agent/managers/memoryMutator.d.ts +0 -92
- package/dist/agent/managers/memoryMutator.d.ts.map +0 -1
- package/dist/agent/managers/memoryMutator.js +0 -94
- package/dist/agent/managers/memoryMutator.js.map +0 -1
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChatLockManager — chat() 并发锁管理器
|
|
3
|
+
*
|
|
4
|
+
* 职责:
|
|
5
|
+
* - chat() 并发锁(防止多轮 chat 同时执行)
|
|
6
|
+
* - token 校验(防止 race condition:超时释放后新调用获取锁,旧 finally 误清新调用者资源)
|
|
7
|
+
* - 超时保护(LLM 卡死时中断 generator + 释放锁)
|
|
8
|
+
* - 外部 signal 合并(外部 abort 时触发内部 abort)
|
|
9
|
+
*
|
|
10
|
+
* 从 agent.ts 提取(AUDIT-1-1,ADR-017 架构层先行原则首次实践)
|
|
11
|
+
*
|
|
12
|
+
* race condition 防护设计:
|
|
13
|
+
* 原锁是简单布尔值 `_chatBusy`,无 owner 校验。超时回调与 finally 块无差别清理,
|
|
14
|
+
* 导致 race condition:T=0 A 获取锁 → T=180s 超时释放 → T=181s B 获取锁
|
|
15
|
+
* → T=182s A 的 finally 误清 B 的锁/计时器/controller。
|
|
16
|
+
*
|
|
17
|
+
* 防护方案:
|
|
18
|
+
* - 获取锁时 token 递增:`const myToken = ++this._chatLockToken`
|
|
19
|
+
* - 超时回调校验 `this._chatLockToken === myToken` 后才释放
|
|
20
|
+
* - finally 块校验 `this._chatLockToken === myToken` 后才清理
|
|
21
|
+
* - 不匹配时跳过清理,避免误清新调用者的资源
|
|
22
|
+
*
|
|
23
|
+
* 选择 number 而非 Symbol:递增计数器可序列化、零依赖、足够唯一(同一 Agent 实例内)
|
|
24
|
+
*/
|
|
25
|
+
/**
|
|
26
|
+
* chat() 并发锁管理器
|
|
27
|
+
*
|
|
28
|
+
* 使用方式:
|
|
29
|
+
* const mgr = new ChatLockManager();
|
|
30
|
+
* const { token, internalAbort } = mgr.acquire(180_000);
|
|
31
|
+
* const cleanup = mgr.attachExternalSignal(externalSignal, internalAbort);
|
|
32
|
+
* try {
|
|
33
|
+
* // ... 使用 internalAbort.signal 传递给 generator ...
|
|
34
|
+
* } finally {
|
|
35
|
+
* mgr.release(token);
|
|
36
|
+
* cleanup();
|
|
37
|
+
* }
|
|
38
|
+
*
|
|
39
|
+
* 强制释放(宿主兜底):
|
|
40
|
+
* mgr.forceRelease();
|
|
41
|
+
*
|
|
42
|
+
* 销毁(Agent.close 时):
|
|
43
|
+
* mgr.dispose();
|
|
44
|
+
*/
|
|
45
|
+
export declare class ChatLockManager {
|
|
46
|
+
/** chat() 是否正在执行(并发锁) */
|
|
47
|
+
private _chatBusy;
|
|
48
|
+
/**
|
|
49
|
+
* chat() 锁持有者 token(race condition 防护)
|
|
50
|
+
*
|
|
51
|
+
* 获取锁时递增,超时回调和 finally 块据此判断是否仍是当前持有者。
|
|
52
|
+
* 不匹配时跳过清理,避免误清新调用者的资源。
|
|
53
|
+
*/
|
|
54
|
+
private _chatLockToken;
|
|
55
|
+
/** 聊天锁超时计时器(防止 LLM 卡死时锁永久持有) */
|
|
56
|
+
private chatLockTimer;
|
|
57
|
+
/** chat() 内部 AbortController(超时时中断 generator,防止并发) */
|
|
58
|
+
private chatAbortController;
|
|
59
|
+
/** 当前是否持有锁 */
|
|
60
|
+
get isBusy(): boolean;
|
|
61
|
+
/**
|
|
62
|
+
* 获取锁,返回 token + 内部 AbortController
|
|
63
|
+
*
|
|
64
|
+
* @param timeoutMs 锁超时时间(LLM 卡死保护)
|
|
65
|
+
* @param onTimeout 超时回调(用于日志记录等)
|
|
66
|
+
* @returns token(用于 finally 校验)+ internalAbort(用于传递给 loop.processUserInput)
|
|
67
|
+
*/
|
|
68
|
+
acquire(timeoutMs: number, onTimeout?: () => void): {
|
|
69
|
+
token: number;
|
|
70
|
+
internalAbort: AbortController;
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* 合并外部 signal:外部 abort 时触发内部 abort
|
|
74
|
+
*
|
|
75
|
+
* addEventListener 对已 aborted 的 signal 不触发回调,
|
|
76
|
+
* 需手动检查并触发 internalAbort,否则外部已取消的请求仍会进入主流程。
|
|
77
|
+
*
|
|
78
|
+
* @returns 清理函数(finally 块中调用 removeEventListener)
|
|
79
|
+
*/
|
|
80
|
+
attachExternalSignal(externalSignal: AbortSignal | undefined, internalAbort: AbortController): () => void;
|
|
81
|
+
/**
|
|
82
|
+
* finally 块清理(token 校验后)
|
|
83
|
+
*
|
|
84
|
+
* 仅当本调用仍是当前锁持有者时才清理资源。
|
|
85
|
+
* 若 token 已变(超时释放后被新调用者获取),跳过清理避免误清新调用者的状态。
|
|
86
|
+
*/
|
|
87
|
+
release(token: number): void;
|
|
88
|
+
/**
|
|
89
|
+
* 强制释放对话锁(宿主无进展超时兜底)
|
|
90
|
+
*
|
|
91
|
+
* 场景:宿主主进程"无进展超时"兜底后,generator 可能仍卡在不可中断的 await 点
|
|
92
|
+
* (executeToolCalls 和 generateContextSummary 已覆盖 signal 响应,但其他
|
|
93
|
+
* 第三方库或未来新增的 await 点仍可能不响应 signal)。
|
|
94
|
+
* 此时 _chatBusy 锁未释放,用户再发消息会被 chat() 的竞态保护拒绝,
|
|
95
|
+
* 表现为"UI 能操作但发不出消息",需等到 3 分钟锁超时才能恢复。
|
|
96
|
+
*
|
|
97
|
+
* 安全机制:
|
|
98
|
+
* - 递增 _chatLockToken,让原 chat() 的 finally 块检测到 token 不匹配后
|
|
99
|
+
* 跳过资源清理(避免误清新调用者的 _chatBusy/chatAbortController)
|
|
100
|
+
* - abort chatAbortController,让响应 signal 的 await 点(如 fetch)退出
|
|
101
|
+
* - 原 generator 仍可能在后台运行(无法真正中断不响应 signal 的 await),
|
|
102
|
+
* 但其 finally 块的 token 校验会阻止它影响新调用
|
|
103
|
+
*
|
|
104
|
+
* 幂等性:_chatBusy 已 false 时 no-op(多次调用安全)
|
|
105
|
+
*/
|
|
106
|
+
forceRelease(): void;
|
|
107
|
+
/**
|
|
108
|
+
* 销毁管理器(Agent.close 时调用)
|
|
109
|
+
*
|
|
110
|
+
* 与 forceRelease() 的区别:不记录 warn 日志(close 是正常生命周期,非异常场景)。
|
|
111
|
+
* 递增 token 使任何进行中的 chat() generator 的 finally 块检测到 token 变化后
|
|
112
|
+
* 跳过资源清理(close 已接管清理职责)。
|
|
113
|
+
*/
|
|
114
|
+
dispose(): void;
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=chatLockManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chatLockManager.d.ts","sourceRoot":"","sources":["../../../src/agent/managers/chatLockManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAKH;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,eAAe;IAC1B,yBAAyB;IACzB,OAAO,CAAC,SAAS,CAAS;IAC1B;;;;;OAKG;IACH,OAAO,CAAC,cAAc,CAAa;IACnC,gCAAgC;IAChC,OAAO,CAAC,aAAa,CAA8C;IACnE,sDAAsD;IACtD,OAAO,CAAC,mBAAmB,CAAgC;IAE3D,cAAc;IACd,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED;;;;;;OAMG;IACH,OAAO,CACL,SAAS,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,MAAM,IAAI,GACrB;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,eAAe,CAAA;KAAE;IA8BpD;;;;;;;OAOG;IACH,oBAAoB,CAClB,cAAc,EAAE,WAAW,GAAG,SAAS,EACvC,aAAa,EAAE,eAAe,GAC7B,MAAM,IAAI;IAYb;;;;;OAKG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAY5B;;;;;;;;;;;;;;;;;OAiBG;IACH,YAAY,IAAI,IAAI;IAkBpB;;;;;;OAMG;IACH,OAAO,IAAI,IAAI;CAchB"}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChatLockManager — chat() 并发锁管理器
|
|
3
|
+
*
|
|
4
|
+
* 职责:
|
|
5
|
+
* - chat() 并发锁(防止多轮 chat 同时执行)
|
|
6
|
+
* - token 校验(防止 race condition:超时释放后新调用获取锁,旧 finally 误清新调用者资源)
|
|
7
|
+
* - 超时保护(LLM 卡死时中断 generator + 释放锁)
|
|
8
|
+
* - 外部 signal 合并(外部 abort 时触发内部 abort)
|
|
9
|
+
*
|
|
10
|
+
* 从 agent.ts 提取(AUDIT-1-1,ADR-017 架构层先行原则首次实践)
|
|
11
|
+
*
|
|
12
|
+
* race condition 防护设计:
|
|
13
|
+
* 原锁是简单布尔值 `_chatBusy`,无 owner 校验。超时回调与 finally 块无差别清理,
|
|
14
|
+
* 导致 race condition:T=0 A 获取锁 → T=180s 超时释放 → T=181s B 获取锁
|
|
15
|
+
* → T=182s A 的 finally 误清 B 的锁/计时器/controller。
|
|
16
|
+
*
|
|
17
|
+
* 防护方案:
|
|
18
|
+
* - 获取锁时 token 递增:`const myToken = ++this._chatLockToken`
|
|
19
|
+
* - 超时回调校验 `this._chatLockToken === myToken` 后才释放
|
|
20
|
+
* - finally 块校验 `this._chatLockToken === myToken` 后才清理
|
|
21
|
+
* - 不匹配时跳过清理,避免误清新调用者的资源
|
|
22
|
+
*
|
|
23
|
+
* 选择 number 而非 Symbol:递增计数器可序列化、零依赖、足够唯一(同一 Agent 实例内)
|
|
24
|
+
*/
|
|
25
|
+
import { clearSafeTimeout, safeSetTimeout } from '../../utils/safeTimer.js';
|
|
26
|
+
import { logger } from '../../logging/logger.js';
|
|
27
|
+
/**
|
|
28
|
+
* chat() 并发锁管理器
|
|
29
|
+
*
|
|
30
|
+
* 使用方式:
|
|
31
|
+
* const mgr = new ChatLockManager();
|
|
32
|
+
* const { token, internalAbort } = mgr.acquire(180_000);
|
|
33
|
+
* const cleanup = mgr.attachExternalSignal(externalSignal, internalAbort);
|
|
34
|
+
* try {
|
|
35
|
+
* // ... 使用 internalAbort.signal 传递给 generator ...
|
|
36
|
+
* } finally {
|
|
37
|
+
* mgr.release(token);
|
|
38
|
+
* cleanup();
|
|
39
|
+
* }
|
|
40
|
+
*
|
|
41
|
+
* 强制释放(宿主兜底):
|
|
42
|
+
* mgr.forceRelease();
|
|
43
|
+
*
|
|
44
|
+
* 销毁(Agent.close 时):
|
|
45
|
+
* mgr.dispose();
|
|
46
|
+
*/
|
|
47
|
+
export class ChatLockManager {
|
|
48
|
+
/** chat() 是否正在执行(并发锁) */
|
|
49
|
+
_chatBusy = false;
|
|
50
|
+
/**
|
|
51
|
+
* chat() 锁持有者 token(race condition 防护)
|
|
52
|
+
*
|
|
53
|
+
* 获取锁时递增,超时回调和 finally 块据此判断是否仍是当前持有者。
|
|
54
|
+
* 不匹配时跳过清理,避免误清新调用者的资源。
|
|
55
|
+
*/
|
|
56
|
+
_chatLockToken = 0;
|
|
57
|
+
/** 聊天锁超时计时器(防止 LLM 卡死时锁永久持有) */
|
|
58
|
+
chatLockTimer = null;
|
|
59
|
+
/** chat() 内部 AbortController(超时时中断 generator,防止并发) */
|
|
60
|
+
chatAbortController = null;
|
|
61
|
+
/** 当前是否持有锁 */
|
|
62
|
+
get isBusy() {
|
|
63
|
+
return this._chatBusy;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* 获取锁,返回 token + 内部 AbortController
|
|
67
|
+
*
|
|
68
|
+
* @param timeoutMs 锁超时时间(LLM 卡死保护)
|
|
69
|
+
* @param onTimeout 超时回调(用于日志记录等)
|
|
70
|
+
* @returns token(用于 finally 校验)+ internalAbort(用于传递给 loop.processUserInput)
|
|
71
|
+
*/
|
|
72
|
+
acquire(timeoutMs, onTimeout) {
|
|
73
|
+
this._chatBusy = true;
|
|
74
|
+
// 分配本调用的 token,超时回调和 finally 块据此判断是否仍是当前持有者
|
|
75
|
+
// 避免 race condition:超时释放后新调用获取锁,旧 finally 误清新调用者的资源
|
|
76
|
+
const token = ++this._chatLockToken;
|
|
77
|
+
// 内部 AbortController,超时时中断 generator 而非仅释放锁
|
|
78
|
+
const internalAbort = new AbortController();
|
|
79
|
+
this.chatAbortController = internalAbort;
|
|
80
|
+
// 超时保护:LLM 卡死时中断 generator + 释放锁,防止并发
|
|
81
|
+
// 超时回调校验 token 后才清理,避免误清新调用者的资源
|
|
82
|
+
this.chatLockTimer = safeSetTimeout(() => {
|
|
83
|
+
// 令牌不匹配:锁已被新调用者获取(或本调用已正常退出),跳过清理
|
|
84
|
+
if (this._chatLockToken !== token) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
logger.warn({ timeoutMs }, 'chat() 锁超时,中断 generator 并释放锁');
|
|
88
|
+
internalAbort.abort();
|
|
89
|
+
this._chatBusy = false;
|
|
90
|
+
this.chatLockTimer = null;
|
|
91
|
+
this.chatAbortController = null;
|
|
92
|
+
onTimeout?.();
|
|
93
|
+
}, timeoutMs);
|
|
94
|
+
return { token, internalAbort };
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* 合并外部 signal:外部 abort 时触发内部 abort
|
|
98
|
+
*
|
|
99
|
+
* addEventListener 对已 aborted 的 signal 不触发回调,
|
|
100
|
+
* 需手动检查并触发 internalAbort,否则外部已取消的请求仍会进入主流程。
|
|
101
|
+
*
|
|
102
|
+
* @returns 清理函数(finally 块中调用 removeEventListener)
|
|
103
|
+
*/
|
|
104
|
+
attachExternalSignal(externalSignal, internalAbort) {
|
|
105
|
+
if (!externalSignal)
|
|
106
|
+
return () => { };
|
|
107
|
+
const onExternalAbort = () => internalAbort.abort();
|
|
108
|
+
externalSignal.addEventListener('abort', onExternalAbort, { once: true });
|
|
109
|
+
// addEventListener 对已 aborted 的 signal 不触发回调
|
|
110
|
+
// 需手动检查并触发 internalAbort,否则外部已取消的请求仍会进入主流程
|
|
111
|
+
if (externalSignal.aborted) {
|
|
112
|
+
internalAbort.abort();
|
|
113
|
+
}
|
|
114
|
+
return () => externalSignal.removeEventListener('abort', onExternalAbort);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* finally 块清理(token 校验后)
|
|
118
|
+
*
|
|
119
|
+
* 仅当本调用仍是当前锁持有者时才清理资源。
|
|
120
|
+
* 若 token 已变(超时释放后被新调用者获取),跳过清理避免误清新调用者的状态。
|
|
121
|
+
*/
|
|
122
|
+
release(token) {
|
|
123
|
+
if (this._chatLockToken !== token) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
this._chatBusy = false;
|
|
127
|
+
this.chatAbortController = null;
|
|
128
|
+
if (this.chatLockTimer) {
|
|
129
|
+
clearSafeTimeout(this.chatLockTimer);
|
|
130
|
+
this.chatLockTimer = null;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* 强制释放对话锁(宿主无进展超时兜底)
|
|
135
|
+
*
|
|
136
|
+
* 场景:宿主主进程"无进展超时"兜底后,generator 可能仍卡在不可中断的 await 点
|
|
137
|
+
* (executeToolCalls 和 generateContextSummary 已覆盖 signal 响应,但其他
|
|
138
|
+
* 第三方库或未来新增的 await 点仍可能不响应 signal)。
|
|
139
|
+
* 此时 _chatBusy 锁未释放,用户再发消息会被 chat() 的竞态保护拒绝,
|
|
140
|
+
* 表现为"UI 能操作但发不出消息",需等到 3 分钟锁超时才能恢复。
|
|
141
|
+
*
|
|
142
|
+
* 安全机制:
|
|
143
|
+
* - 递增 _chatLockToken,让原 chat() 的 finally 块检测到 token 不匹配后
|
|
144
|
+
* 跳过资源清理(避免误清新调用者的 _chatBusy/chatAbortController)
|
|
145
|
+
* - abort chatAbortController,让响应 signal 的 await 点(如 fetch)退出
|
|
146
|
+
* - 原 generator 仍可能在后台运行(无法真正中断不响应 signal 的 await),
|
|
147
|
+
* 但其 finally 块的 token 校验会阻止它影响新调用
|
|
148
|
+
*
|
|
149
|
+
* 幂等性:_chatBusy 已 false 时 no-op(多次调用安全)
|
|
150
|
+
*/
|
|
151
|
+
forceRelease() {
|
|
152
|
+
if (!this._chatBusy)
|
|
153
|
+
return;
|
|
154
|
+
// 递增 token 让原 chat() 的 finally 块跳过清理(避免误清新调用者的资源)
|
|
155
|
+
this._chatLockToken++;
|
|
156
|
+
// abort 当前 generator(响应 signal 的 await 点会 throw AbortError 退出)
|
|
157
|
+
if (this.chatAbortController) {
|
|
158
|
+
this.chatAbortController.abort();
|
|
159
|
+
this.chatAbortController = null;
|
|
160
|
+
}
|
|
161
|
+
// 清理锁超时定时器(避免后续触发重复清理)
|
|
162
|
+
if (this.chatLockTimer) {
|
|
163
|
+
clearSafeTimeout(this.chatLockTimer);
|
|
164
|
+
this.chatLockTimer = null;
|
|
165
|
+
}
|
|
166
|
+
this._chatBusy = false;
|
|
167
|
+
logger.warn('对话锁被强制释放(宿主无进展超时兜底)');
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* 销毁管理器(Agent.close 时调用)
|
|
171
|
+
*
|
|
172
|
+
* 与 forceRelease() 的区别:不记录 warn 日志(close 是正常生命周期,非异常场景)。
|
|
173
|
+
* 递增 token 使任何进行中的 chat() generator 的 finally 块检测到 token 变化后
|
|
174
|
+
* 跳过资源清理(close 已接管清理职责)。
|
|
175
|
+
*/
|
|
176
|
+
dispose() {
|
|
177
|
+
// 递增 token,使任何进行中的 chat() generator 的 finally 块
|
|
178
|
+
// 检测到 token 变化后跳过资源清理(close 已接管清理职责)
|
|
179
|
+
this._chatLockToken++;
|
|
180
|
+
if (this.chatAbortController) {
|
|
181
|
+
this.chatAbortController.abort();
|
|
182
|
+
this.chatAbortController = null;
|
|
183
|
+
}
|
|
184
|
+
if (this.chatLockTimer) {
|
|
185
|
+
clearSafeTimeout(this.chatLockTimer);
|
|
186
|
+
this.chatLockTimer = null;
|
|
187
|
+
}
|
|
188
|
+
this._chatBusy = false;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=chatLockManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chatLockManager.js","sourceRoot":"","sources":["../../../src/agent/managers/chatLockManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Insight 提取器 — 输入分类 + 记忆提取
|
|
3
|
+
*
|
|
4
|
+
* 从 Agent 拆分出来,负责:
|
|
5
|
+
* - 三层输入分类(通用规则 → 宿主关键词 → 默认提取)
|
|
6
|
+
* - 异步 insight 提取(LLM 判断 + 去重 + 写入 SQLite)
|
|
7
|
+
* - 宿主记忆关键词管理
|
|
8
|
+
*
|
|
9
|
+
* 关系构建逻辑(ADR-014)已拆分至 RelationBuilder,本类通过 relationBuilder 委托调用。
|
|
10
|
+
*
|
|
11
|
+
* 设计原则:
|
|
12
|
+
* - 独立于 Agent 生命周期,仅依赖 Provider/Storage/Loop
|
|
13
|
+
* - 提取失败不影响主对话流程(fire-and-forget)
|
|
14
|
+
*/
|
|
1
15
|
import type { LlmProvider } from '../../llm/provider.js';
|
|
2
16
|
import type { Memory } from '../../memory/types.js';
|
|
3
17
|
import type { IMemoryStorage } from '../../memory/storageInterface.js';
|
|
@@ -23,14 +37,14 @@ export declare class InsightExtractor {
|
|
|
23
37
|
/** 写入扩展回调(宿主注入 diff 对比确认逻辑) */
|
|
24
38
|
writeExtensions: WriteExtensions | null;
|
|
25
39
|
/**
|
|
26
|
-
* 关系构建器(
|
|
40
|
+
* 关系构建器(ADR-014 关系构建委托给 RelationBuilder)
|
|
27
41
|
* 未注入时跳过所有关系构建(保持向后兼容)
|
|
28
42
|
*/
|
|
29
43
|
private readonly relationBuilder;
|
|
30
44
|
/**
|
|
31
45
|
* @param provider - LLM Provider(用于 insight 提取)
|
|
32
46
|
* @param index - 记忆存储(用于去重搜索 + 写入)
|
|
33
|
-
* @param relationBuilder -
|
|
47
|
+
* @param relationBuilder - 关系构建器(可选,替代直接 relationStore 注入)
|
|
34
48
|
* 未注入时跳过关系构建(保持向后兼容,ADR-014 侧车模型)
|
|
35
49
|
*/
|
|
36
50
|
constructor(provider: LlmProvider, index: IMemoryStorage, relationBuilder?: RelationBuilder | null);
|
|
@@ -44,7 +58,7 @@ export declare class InsightExtractor {
|
|
|
44
58
|
content: string;
|
|
45
59
|
}>): void;
|
|
46
60
|
/**
|
|
47
|
-
*
|
|
61
|
+
* 绑定冲突检测回调(委托给 RelationBuilder)
|
|
48
62
|
*
|
|
49
63
|
* 由 Agent.init() 在创建 InsightExtractor 后调用(与 bindGetRecentHistory 同模式),
|
|
50
64
|
* 解决 Agent 实例晚于 InsightExtractor 创建的时序循环依赖。
|
|
@@ -95,6 +109,20 @@ export declare class InsightExtractor {
|
|
|
95
109
|
* low → 0.2(快速衰减)
|
|
96
110
|
*/
|
|
97
111
|
private scoreByQuality;
|
|
112
|
+
/**
|
|
113
|
+
* 利用 LLM 返回的 tags 生成语义化 name
|
|
114
|
+
*
|
|
115
|
+
* name 格式:`{清洗后的tag}-{uuid前6位}`(如 "偏好-a1b2c3")
|
|
116
|
+
* - 取 tags 数组第一个非空 tag
|
|
117
|
+
* - 清洗 tag:保留中文/字母/数字,移除其他字符,取前 8 字符
|
|
118
|
+
* - UUID 前缀保证唯一性,tag 前缀提升 UI 可读性
|
|
119
|
+
* - 无 tags 或清洗后为空时,回退到 `insight-{uuid前8位}`
|
|
120
|
+
*
|
|
121
|
+
* @param tagsRaw - LLM 返回的 tags 字段(类型未知,需运行时校验)
|
|
122
|
+
* @param insightId - UUID,用于保证 name 唯一性
|
|
123
|
+
* @returns 语义化 name 字符串
|
|
124
|
+
*/
|
|
125
|
+
private generateSemanticName;
|
|
98
126
|
/**
|
|
99
127
|
* Layer 1: 通用规则过滤
|
|
100
128
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"insightExtractor.d.ts","sourceRoot":"","sources":["../../../src/agent/managers/insightExtractor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"insightExtractor.d.ts","sourceRoot":"","sources":["../../../src/agent/managers/insightExtractor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,WAAW,EAAW,MAAM,mBAAmB,CAAC;AAC9D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAGhD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAInE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAG/D,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AAiCzF;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,4CAA4C;IAC5C,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,yCAAyC;IACzC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAsFD,qBAAa,gBAAgB;IAoBzB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,KAAK;IApBxB,iCAAiC;IACjC,OAAO,CAAC,YAAY,CAA+B;IAEnD,+BAA+B;IACxB,eAAe,EAAE,eAAe,GAAG,IAAI,CAAQ;IAEtD;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAyB;IAEzD;;;;;OAKG;gBAEgB,QAAQ,EAAE,WAAW,EACrB,KAAK,EAAE,cAAc,EACtC,eAAe,GAAE,eAAe,GAAG,IAAW;IAOhD,8DAA8D;IAC9D,OAAO,CAAC,iBAAiB,CAA6E;IAEtG;;OAEG;IACH,oBAAoB,CAClB,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,GAC7E,IAAI;IAIP;;;;;;;;OAQG;IACH,cAAc,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI;IAM/D;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI;IAQ3C;;OAEG;IACH,kBAAkB,CAAC,GAAG,EAAE,eAAe,GAAG,IAAI,GAAG,IAAI;IAOrD;;;;;;;;OAQG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAe3C;;;;;;;OAOG;IACG,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IA6I7E;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB;IAQzB;;;;;OAKG;IACH,OAAO,CAAC,cAAc;IAQtB;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,oBAAoB;IAuB5B;;;;OAIG;IACH,OAAO,CAAC,eAAe;IAUvB;;;;OAIG;IACH,OAAO,CAAC,sBAAsB;CAU/B"}
|