@ai-agent-forge/plugin-memory 0.88.18 → 0.88.20
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/agent-forge.json +1 -1
- package/dist/capability.d.ts.map +1 -1
- package/dist/capability.js +39 -0
- package/dist/capability.js.map +1 -1
- package/dist/inference-bin.bundle.js +62 -7
- package/dist/memory/command-face.d.ts.map +1 -1
- package/dist/memory/command-face.js +1 -1
- package/dist/memory/command-face.js.map +1 -1
- package/dist/memory/inference-service-main.d.ts.map +1 -1
- package/dist/memory/inference-service-main.js +5 -0
- package/dist/memory/inference-service-main.js.map +1 -1
- package/dist/memory/recall-pipeline.d.ts.map +1 -1
- package/dist/memory/recall-pipeline.js +22 -4
- package/dist/memory/recall-pipeline.js.map +1 -1
- package/dist/memory/vector-channel.d.ts.map +1 -1
- package/dist/memory/vector-channel.js +5 -0
- package/dist/memory/vector-channel.js.map +1 -1
- package/dist/memory/vector-index.d.ts +37 -0
- package/dist/memory/vector-index.d.ts.map +1 -1
- package/dist/memory/vector-index.js +54 -2
- package/dist/memory/vector-index.js.map +1 -1
- package/package.json +2 -2
- package/plugin.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recall-pipeline.js","sourceRoot":"","sources":["../../src/memory/recall-pipeline.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * 召回管线(capability 拆分战役 slice 4):双通道查询、RRF 融合、egress 门、语义召回与召回工具。状态机经 vectorChannel 只读面消费, 降级经回调上报\n */\nimport type { CapabilityAPI, DisposableRegistration, JsonValue } from \"@agent-forge/plugin-sdk\";\nimport { MEMORY_RECALL_TOOL_NAME } from \"@agent-forge/plugin-sdk\";\nimport { Type } from \"typebox\";\nimport type { MemoryEgressFactInfoV1, MemoryEgressPolicyGateV1 } from \"./egress-policy.ts\";\nimport type { MemoryAtomV1, MemoryPreferenceEnvelopeV1, MemorySuiteFilterStatsV1 } from \"./foundation.ts\";\nimport type { DurableMemoryLedgerV1 } from \"./ledger.ts\";\nimport type { MemoryNetworkExpansionV1, MemoryNetworkV1 } from \"./memory-network.ts\";\nimport type { PreferenceDisambiguatorV1 } from \"./preference-disambiguator.ts\";\nimport type { PreferenceContextV1, PreferenceResolverV1 } from \"./preference-resolver.ts\";\nimport type { MemoryRecallPacketV1 } from \"./recall-packet.ts\";\nimport type { MemoryStoreV1 } from \"./store.ts\";\nimport { listDomainMemories, type SuiteMemoryDomainV1 } from \"./suite-memory.ts\";\nimport type { MemoryCapabilityStateV1, MemoryConsentAskV1, MemoryEnablingFailureV1 } from \"./vector-channel.ts\";\nimport type { MemoryVectorHitV1 } from \"./vector-index.ts\";\nimport type { ActiveVectorChannelV1 } from \"./vector-projection.ts\";\n\n/**\n * Memory tools guide(记忆 runtime 注入面,原 system-prompt.ts MEMORY_TOOL_GUIDE,\n * D-071 迁移):the model-facing hint that the persistent memory tools exist.\n * It rides memory_recall's promptGuidelines so the text lives with the plugin\n * that owns the tools (宪法 §3) and renders whenever the tool face is active.\n */\nexport const MEMORY_TOOLS_GUIDE =\n\t\"Memory: You have persistent memory tools (memory_write, memory_recall, memory_list, memory_forget). Use memory_recall only when past decisions, preferences, or project facts are actually relevant to the current question — not on every turn. Use memory_write only for facts the user explicitly stated or that a tool/test verified; never save your own inferences or guesses as facts, and declare the honest evidence class. memory_forget only files a forget request — deletion happens after the user confirms it.\";\n\nconst DEFAULT_RECALL_LIMIT = 5;\n\n/** Bounded supplementary relation references per recall (记忆网络接线). */\nconst MAX_RELATED_REFS = 20;\n\n/** FTS / KNN 通道各自取回深度 (定版管线: depth 50)。 */\nconst HYBRID_CHANNEL_DEPTH = 50;\n/** RRF 常数, 与 vector-index 组件 queryFts 打分口径一致。 */\nconst HYBRID_RRF_K = 60;\n/** 融合候选池上限 (定版管线: top20 → 精排 → top limit)。 */\nconst HYBRID_FUSION_POOL = 20;\n\ninterface MemoryFact {\n\treadonly memoryId: string;\n\treadonly statement: string;\n\treadonly confidence: number;\n}\n\n/**\n * 三通道 RRF 融合 (定版管线): `score(id) += 1/(k + rank + 1)` 对各通道排名累加,\n * 取 top {@link HYBRID_FUSION_POOL}。分数并列时以 memoryId 升序打破, 保证确定性。\n */\nfunction rrfFuseRankings(rankings: readonly (readonly string[])[]): readonly string[] {\n\tconst scores = new Map<string, number>();\n\tfor (const ranking of rankings) {\n\t\tfor (const [rank, memoryId] of ranking.entries()) {\n\t\t\tscores.set(memoryId, (scores.get(memoryId) ?? 0) + 1 / (HYBRID_RRF_K + rank + 1));\n\t\t}\n\t}\n\treturn [...scores.entries()]\n\t\t.sort((left, right) => right[1] - left[1] || (left[0] < right[0] ? -1 : 1))\n\t\t.map(([memoryId]) => memoryId)\n\t\t.slice(0, HYBRID_FUSION_POOL);\n}\n\n/** One unresolvably competing preference, surfaced verbatim instead of a silent pick. */\ninterface RecallConflictV1 {\n\treadonly subject: MemoryPreferenceEnvelopeV1[\"subject\"];\n\treadonly key: string;\n\treadonly candidates: readonly {\n\t\treadonly memoryId: string;\n\t\treadonly statement: string;\n\t\treadonly value: JsonValue;\n\t\treadonly evidenceClass: MemoryPreferenceEnvelopeV1[\"evidence\"][\"class\"];\n\t\treadonly confidence: number;\n\t}[];\n\treadonly explanation: readonly string[];\n}\n\nconst recallSchema = Type.Object({\n\tquery: Type.String({\n\t\tdescription:\n\t\t\t\"Natural-language query; recall fuses semantic (vector) and full-text (BM25) matching and reranks the result. An exact memoryId retrieves that memory directly\",\n\t}),\n\tlimit: Type.Optional(\n\t\tType.Integer({ description: \"Maximum number of memories to return (1-100)\", minimum: 1, maximum: 100 }),\n\t),\n\tcontext: Type.Optional(\n\t\tType.Object(\n\t\t\t{\n\t\t\t\tscenes: Type.Optional(Type.Array(Type.String())),\n\t\t\t\tprojects: Type.Optional(Type.Array(Type.String())),\n\t\t\t\ttasks: Type.Optional(Type.Array(Type.String())),\n\t\t\t},\n\t\t\t{\n\t\t\t\tdescription:\n\t\t\t\t\t\"Current scope context; when present, recalled preferences are resolved against it (out-of-scope preferences drop, competing values resolve by scope specificity or surface as explicit conflicts)\",\n\t\t\t},\n\t\t),\n\t),\n});\n\n/**\n * 召回管线对 capability 闭包的显式依赖视图 (slice 4): 逐项来自\n * createMemoryCapabilityHarness 的闭包捕获核实。状态机 (vectorChannelCtl) 与\n * 写侧投影 (vectorProjection) 归 capability 装配所有, 本模块经只读回调消费与\n * 上报, 不持有任何状态机变量; capability 模块级纯函数经 deps 注入避免双头定义。\n */\nexport interface MemoryRecallPipelineDepsV1 {\n\t/** capability 日志面 (api.logger): 通道降级/增强失败的结构化日志。 */\n\treadonly logger: CapabilityAPI[\"logger\"];\n\t/** 检索行 owner (capability.BUILTIN_MEMORY_OWNER)。 */\n\treadonly owner: string;\n\t/** 会话 id (harness sessionId): egress operationId 组成。 */\n\treadonly sessionId: string;\n\t/** canonical store (per-capability 单例): store 回查与增强段 atom 读取。 */\n\treadonly store: MemoryStoreV1;\n\t/** 域解析 (capability.resolveDomain): 每次 recall 调用时惰性解析 (B1 语义)。 */\n\treadonly resolveDomain: () => {\n\t\treadonly domain: SuiteMemoryDomainV1;\n\t\treadonly domainName: string;\n\t\treadonly ledger: DurableMemoryLedgerV1;\n\t};\n\t/** egress 门 (capability.egressPolicy): 与旧锚点 packet 同一 gate。 */\n\treadonly egressPolicy: MemoryEgressPolicyGateV1;\n\t/** context-scoped 偏好解析 (2.4c/2.4d2)。 */\n\treadonly preferenceResolver: PreferenceResolverV1;\n\t/** 未决偏好的确定性消歧 (2.4c/2.4d2)。 */\n\treadonly preferenceDisambiguator: PreferenceDisambiguatorV1;\n\t/** 关系扩散 (记忆网络接线): recall 种子的一跳扩展。 */\n\treadonly memoryNetwork: MemoryNetworkV1;\n\t// ---- vectorChannel 只读面 (slice 3b 的 vectorChannelCtl, 状态机归其所有) ----\n\t/** warming 守卫: 后台预热在途且未拒绝时 recall 零等待返回 unavailable。 */\n\treadonly warming: () => boolean;\n\t/** 惰性装配 (vectorEnsure 单飞语义原样保留): undefined = 通道不可用。 */\n\treadonly ensureChannel: () => Promise<ActiveVectorChannelV1 | undefined>;\n\t/** 征询拒绝标记 (declined): recall 按模式关闭对待。 */\n\treadonly declined: () => boolean;\n\t/** 待征询信息 (consent-required): recall 返回征询话术包。 */\n\treadonly consentAsk: () => MemoryConsentAskV1 | undefined;\n\t/** enabling 结构化失败 (原因 + 行动清单, 设计 §3.2)。 */\n\treadonly failure: () => MemoryEnablingFailureV1 | undefined;\n\t/** 通道原始状态 (未做 declined 投影): packet 的 state 字段来源。 */\n\treadonly rawState: () => MemoryCapabilityStateV1;\n\t/** 运行期故障的 degraded 转换回调 (状态转换语义归状态机)。 */\n\treadonly markDegraded: () => void;\n\t/** 全通成功的 degraded 自愈回调。 */\n\treadonly recoverDegraded: () => void;\n\t// ---- 写侧投影 (slice 3a 的 vectorProjection) ----\n\t/** 读侧 FIFO 等待 (await vectorQueue): 保写入→召回次序。 */\n\treadonly settleProjection: () => Promise<unknown>;\n\t// ---- capability 模块级纯函数 (留守方, 经 deps 注入避免双头定义) ----\n\treadonly memoryToolInput: (first: unknown, second: unknown) => Record<string, unknown>;\n\treadonly assertNonEmptyString: (value: unknown, label: string) => asserts value is string;\n\treadonly isPlainObject: (value: unknown) => value is Record<string, unknown>;\n\treadonly identityHash: (value: string) => string;\n\treadonly statementOf: (payload: unknown) => string;\n\treadonly unwrapEgressStatement: (statement: string) => string;\n\t/** 工具注册面 (api.registerTool): memory_recall 经同一公共通道注册。 */\n\treadonly registerTool: CapabilityAPI[\"registerTool\"];\n}\n\n/** 召回管线工厂产物: 工具注册项 + auto-recall 直连的执行闭包。 */\nexport interface MemoryRecallPipelineV1 {\n\t/** memory_recall 工具注册项 (capability registrations 收集)。 */\n\treadonly recallTool: DisposableRegistration;\n\t/** 召回执行闭包 (原 recallExecute): autoRecallBlock (留守, slice 7) 直连同一 execute。 */\n\treadonly recallExecute: (first: unknown, second?: unknown) => Promise<unknown>;\n}\n\nexport function createMemoryRecallPipeline(deps: MemoryRecallPipelineDepsV1): MemoryRecallPipelineV1 {\n\t/**\n\t * 语义召回管线 (2.4d6 S2, 设计 §4) — 唯一检索路径: embed(查询, light 加 BGE\n\t * 前缀) → KNN depth50 + FTS depth50 → RRF k=60 top20 → 精排 → store 回查\n\t * (owner/suite/scope/过期, 单一可见性路径, 不足 limit 不回填)。降级层级\n\t * (2026-10-05 裁决 A「宁漏勿错」, 每次降级一条结构化日志, 状态转 degraded\n\t * 可自愈): 精排失败 → RRF 序 + degraded 标记 (不闩锁, 下次重试); 向量失败\n\t * (embed/KNN) → FTS-only + degraded; FTS 失败 → KNN-only + degraded;\n\t * 双通道皆败 → unavailable (语义召回不可用, memory_list 仍是列表入口;\n\t * recency 枚举兜底已移除 — 语义查询返回\"最近的几条\"是对查询语义的错答)。\n\t * degraded 标记对显式召回可见; auto-recall 见标记零注入。\n\t */\n\n\t/** 一次语义召回的中间候选: atom + 融合/降级序位 (精排并列打破用)。 */\n\tinterface RecallCandidateV1 {\n\t\treadonly atom: MemoryAtomV1;\n\t\treadonly position: number;\n\t}\n\n\t/** 出线事实行 (含精排可选分): score 缺席 = 该路径未产生精排分。 */\n\tinterface ScoredRecallFactV1 {\n\t\treadonly memoryId: string;\n\t\treadonly statement: string;\n\t\treadonly confidence: number;\n\t\treadonly position: number;\n\t\treadonly score?: number;\n\t}\n\n\ttype SemanticRecallOutcomeV1 =\n\t\t| {\n\t\t\t\treadonly kind: \"served\";\n\t\t\t\treadonly facts: readonly MemoryFact[];\n\t\t\t\treadonly candidateCount: number;\n\t\t\t\treadonly suiteFilter: MemorySuiteFilterStatsV1;\n\t\t\t\t/**\n\t\t\t\t * 降级原因短语 (2026-10-05 裁决 A「宁漏勿错」): 存在即本次结果未经\n\t\t\t\t * 精排打分。显式召回照常服务并携带该标记 (模型可见); auto-recall\n\t\t\t\t * 见标记零注入。\n\t\t\t\t */\n\t\t\t\treadonly degraded?: string;\n\t\t }\n\t\t| { readonly kind: \"blocked\"; readonly reason: string }\n\t\t| { readonly kind: \"unavailable\"; readonly message: string };\n\n\t/** recency 排序 (occurredAt 降序, memoryId 升序打破并列 — 与 recall index 同口径)。 */\n\tconst recencyOrdered = (entries: readonly RecallCandidateV1[]): readonly RecallCandidateV1[] =>\n\t\t[...entries]\n\t\t\t.sort(\n\t\t\t\t(left, right) =>\n\t\t\t\t\tDate.parse(right.atom.occurredAt) - Date.parse(left.atom.occurredAt) ||\n\t\t\t\t\t(left.atom.memoryId < right.atom.memoryId ? -1 : 1),\n\t\t\t)\n\t\t\t.map((entry, position) => ({ atom: entry.atom, position }));\n\n\t/**\n\t * superseded 过滤 (S3-B, store 回查后 / 精排前): 被某条在场候选的 supersedes\n\t * 关系指向的旧条目不再出线 — 合并后同义查询只出新条目。\"新条目在场\"以候选\n\t * 集为界: 继任条目被遗忘 (purge/过期) 后其关系随之消失, 旧条目自然恢复出线。\n\t * memoryId 主键直查不经此过滤 (引用不失效), memory_list 管理面不过滤\n\t * (nothing silently dropped — 用户可显式 forget 旧条目)。\n\t */\n\tconst filterSupersededCandidates = (candidates: readonly RecallCandidateV1[]): readonly RecallCandidateV1[] => {\n\t\tconst superseded = new Set<string>();\n\t\tfor (const entry of candidates) {\n\t\t\tfor (const relation of entry.atom.relations) {\n\t\t\t\tif (relation.kind === \"supersedes\" && relation.targetMemoryId !== undefined) {\n\t\t\t\t\tsuperseded.add(relation.targetMemoryId);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (superseded.size === 0) return candidates;\n\t\treturn candidates.filter((entry) => !superseded.has(entry.atom.memoryId));\n\t};\n\n\t/**\n\t * store 回查 (正确性关键): 候选 id 逐条走与旧锚点通道相同的可见性单一路径\n\t * (owner + suite 读边界 + 过期, 单一路径); suite 场景下不可见 id 按 legacy/\n\t * 外套件区分计数 (suiteFilter 可观测), 不可见者丢弃且不回填 (诚实分页)。\n\t */\n\tconst lookupCandidates = (\n\t\trankedIds: readonly (readonly [memoryId: string, position: number])[],\n\t\tsuiteId: string | undefined,\n\t): { readonly candidates: readonly RecallCandidateV1[]; readonly suiteFilter: MemorySuiteFilterStatsV1 } => {\n\t\tconst candidates: RecallCandidateV1[] = [];\n\t\tlet legacySkipped = 0;\n\t\tlet foreignSuiteSkipped = 0;\n\t\tfor (const [memoryId, position] of rankedIds) {\n\t\t\tconst record = deps.store.get(memoryId, {\n\t\t\t\towner: deps.owner,\n\t\t\t\t...(suiteId === undefined ? {} : { suiteId }),\n\t\t\t});\n\t\t\tif (record !== undefined) {\n\t\t\t\tcandidates.push({ atom: record.atom, position });\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (suiteId !== undefined) {\n\t\t\t\tconst unfiltered = deps.store.get(memoryId, { owner: deps.owner });\n\t\t\t\tif (unfiltered !== undefined) {\n\t\t\t\t\tif (unfiltered.atom.suiteId === undefined) legacySkipped += 1;\n\t\t\t\t\telse foreignSuiteSkipped += 1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn { candidates, suiteFilter: { legacySkipped, foreignSuiteSkipped } };\n\t};\n\n\t/**\n\t * egress 门重放 (设计 §11 MUST run): 对最终候选统一执行, 与旧锚点 packet 同\n\t * 一 gate、同一 factInfo 来源 (store); blocked 即 fail-closed, 该次 recall\n\t * 返回 failed packet (来源未登记的事实永不越过出界面)。\n\t */\n\tconst egressGate = (candidates: readonly RecallCandidateV1[]) => {\n\t\tconst factInfo: Record<string, MemoryEgressFactInfoV1 | undefined> = {};\n\t\tfor (const entry of candidates) {\n\t\t\tfactInfo[entry.atom.memoryId] = {\n\t\t\t\tsourceRefs: entry.atom.sourceRefs,\n\t\t\t\tpayload: entry.atom.payload as Record<string, unknown>,\n\t\t\t};\n\t\t}\n\t\treturn deps.egressPolicy.apply(\n\t\t\t{\n\t\t\t\toperationId: `memory_recall:${deps.sessionId}:${deps.identityHash(candidates.map((entry) => entry.atom.memoryId).join(\"\\u0000\"))}`,\n\t\t\t\tstatus: \"completed\",\n\t\t\t\tfacts: candidates.map((entry) => ({\n\t\t\t\t\tmemoryId: entry.atom.memoryId,\n\t\t\t\t\tcontentRevision: entry.atom.contentRevision,\n\t\t\t\t\tstatement: JSON.stringify(entry.atom.payload),\n\t\t\t\t\tconfidence: entry.atom.confidence,\n\t\t\t\t})),\n\t\t\t\tqueryPlan: { lookupUsed: false, filtersApplied: [], scorerVersion: \"semantic-rrf@1\" },\n\t\t\t\tattempts: 0,\n\t\t\t\tnarrowingHints: [],\n\t\t\t\tomittedCount: 0,\n\t\t\t\ttruncated: false,\n\t\t\t\ttruncationScope: \"none\",\n\t\t\t\tbudget: {\n\t\t\t\t\tcandidateBudget: 0,\n\t\t\t\t\tmodelInspectionLimit: 0,\n\t\t\t\t\tfinalResultLimit: 0,\n\t\t\t\t\tused: { candidateCount: 0, modelInspectedCount: 0, finalResultCount: 0 },\n\t\t\t\t},\n\t\t\t} satisfies MemoryRecallPacketV1,\n\t\t\tfactInfo,\n\t\t);\n\t};\n\n\tconst recallSemantically = async (input: {\n\t\treadonly query: string;\n\t\treadonly domain: SuiteMemoryDomainV1;\n\t\treadonly limit: number;\n\t\t/**\n\t\t * 自动召回质量门槛 (错误教训与召回质量护栏设计 §2.1, 内部执行缝):\n\t\t * memory_recall 工具 schema 不含该参数, 显式召回行为不变; auto-recall\n\t\t * 钩子经内部闭包恒传。仅精排实际产生 score 且过门槛的候选保留 (裁决 A\n\t\t * 收紧: 无 score 候选一律丢弃)。\n\t\t */\n\t\treadonly minScore?: number;\n\t}): Promise<SemanticRecallOutcomeV1> => {\n\t\t// 后台预热不阻塞读侧 (2026-10-05 流程裁决「后台预热、不阻塞提问」):\n\t\t// 下载/加载进行中时 recall 直接返回 warming 不可用包, 不等待 vectorQueue\n\t\t// (队列此时可能正背着启动对账或下载任务) 与 ensure 单飞。\n\t\tif (deps.warming()) {\n\t\t\treturn {\n\t\t\t\tkind: \"unavailable\",\n\t\t\t\tmessage: \"memory models are loading in the background; recall becomes available once they are ready\",\n\t\t\t};\n\t\t}\n\t\t// 读侧先等写侧队列在调用时刻已入队的部分 (待处理的投影写入 + 启动对账\n\t\t// 已入队的块), 保证写入→召回 FIFO: 本调用之前提交的写入其投影先落地,\n\t\t// 不与后台对账/埋点竞态。启动对账的分块自续 (RECONCILE_CHUNK_UPSERTS)\n\t\t// 在块完成时才入队下一块, 未入队的后续块不阻塞本次召回——未回填条目由\n\t\t// store 回查与 memory_list 兜底, 残行由后续对账继续补齐。\n\t\tawait deps.settleProjection();\n\t\tconst channel = await deps.ensureChannel();\n\t\tif (channel === undefined) {\n\t\t\tif (deps.declined()) {\n\t\t\t\treturn {\n\t\t\t\t\tkind: \"unavailable\",\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t\"memory was declined on this machine — set memory.mode (light|full) in settings.json and restart the session to re-enable\",\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst consentAsk = deps.consentAsk();\n\t\t\tif (consentAsk !== undefined) {\n\t\t\t\treturn { kind: \"unavailable\", message: consentAsk.message };\n\t\t\t}\n\t\t\tconst failure = deps.failure();\n\t\t\treturn {\n\t\t\t\tkind: \"unavailable\",\n\t\t\t\tmessage:\n\t\t\t\t\tfailure === undefined\n\t\t\t\t\t\t? `memory channel is unavailable (state=${deps.rawState()})`\n\t\t\t\t\t\t: `memory enabling failed: ${failure.reason} — actions: ${failure.actions.join(\" | \")}`,\n\t\t\t};\n\t\t}\n\t\tconst suiteId = input.domain.kind === \"suite\" ? input.domain.suiteId : undefined;\n\t\tlet vectorFailed = false;\n\t\tlet ftsFailed = false;\n\t\tlet knnHits: readonly MemoryVectorHitV1[] | undefined;\n\t\tlet ftsHits: readonly MemoryVectorHitV1[] | undefined;\n\t\ttry {\n\t\t\tconst [queryVector] = await channel.embed.embed([channel.queryPrefix + input.query]);\n\t\t\tknnHits = await channel.index.queryKnn(queryVector, {\n\t\t\t\towner: deps.owner,\n\t\t\t\tlimit: HYBRID_CHANNEL_DEPTH,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tvectorFailed = true;\n\t\t\tdeps.logger?.warn(\"memory recall degraded: the vector channel failed; continuing on the FTS channel\", {\n\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t});\n\t\t}\n\t\ttry {\n\t\t\tftsHits = await channel.index.queryFts(input.query, {\n\t\t\t\towner: deps.owner,\n\t\t\t\tlimit: HYBRID_CHANNEL_DEPTH,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tftsFailed = true;\n\t\t\tdeps.logger?.warn(\"memory recall degraded: the FTS channel failed\", {\n\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t});\n\t\t}\n\n\t\tlet candidates: readonly RecallCandidateV1[];\n\t\tlet suiteFilter: MemorySuiteFilterStatsV1 = { legacySkipped: 0, foreignSuiteSkipped: 0 };\n\t\tlet channelDegraded = false;\n\t\t// 裁决 A: 降级原因短语, 透出到工具结果的 degraded 字段 (无精排分数路径)。\n\t\tlet degradedReason: string | undefined;\n\t\tif (!vectorFailed && !ftsFailed && knnHits !== undefined && ftsHits !== undefined) {\n\t\t\t// 主路径: 双通道 RRF k=60 融合 top20。\n\t\t\tconst pool = rrfFuseRankings([ftsHits.map((hit) => hit.memoryId), knnHits.map((hit) => hit.memoryId)]);\n\t\t\tconst lookup = lookupCandidates(\n\t\t\t\tpool.map((memoryId, position) => [memoryId, position] as const),\n\t\t\t\tsuiteId,\n\t\t\t);\n\t\t\tcandidates = lookup.candidates;\n\t\t\tsuiteFilter = lookup.suiteFilter;\n\t\t} else if (ftsHits !== undefined) {\n\t\t\t// 向量失败: FTS-only + recency 排序。\n\t\t\tchannelDegraded = true;\n\t\t\tdegradedReason = \"vector channel failed; full-text-only results, not reranked\";\n\t\t\tconst lookup = lookupCandidates(\n\t\t\t\tftsHits.map((hit, position) => [hit.memoryId, position] as const),\n\t\t\t\tsuiteId,\n\t\t\t);\n\t\t\tcandidates = recencyOrdered(lookup.candidates);\n\t\t\tsuiteFilter = lookup.suiteFilter;\n\t\t} else if (knnHits !== undefined) {\n\t\t\t// FTS 失败: KNN-only + recency 排序 (对称降级)。\n\t\t\tchannelDegraded = true;\n\t\t\tdegradedReason = \"FTS channel failed; vector-only results, not reranked\";\n\t\t\tconst lookup = lookupCandidates(\n\t\t\t\tknnHits.map((hit, position) => [hit.memoryId, position] as const),\n\t\t\t\tsuiteId,\n\t\t\t);\n\t\t\tcandidates = recencyOrdered(lookup.candidates);\n\t\t\tsuiteFilter = lookup.suiteFilter;\n\t\t} else {\n\t\t\t// 双通道皆败 = 语义召回能力不可用 (2026-10-05 裁决 A): 显式召回返回\n\t\t\t// 结构化 unavailable (memory_list 仍是列表入口), recency 枚举兜底从\n\t\t\t// 语义召回路径移除 — 语义查询返回\"最近的几条\"是对查询语义的错答。\n\t\t\tdeps.markDegraded();\n\t\t\tdeps.logger?.warn(\"memory recall unavailable: both the vector and FTS channels failed\");\n\t\t\treturn {\n\t\t\t\tkind: \"unavailable\",\n\t\t\t\tmessage:\n\t\t\t\t\t\"memory recall is unavailable (both retrieval channels failed); use memory_list to enumerate this suite's memories\",\n\t\t\t};\n\t\t}\n\t\t// 运行期通道故障 → degraded (可自愈: 下一次全通 recall 回 ready)。\n\t\tif (channelDegraded) deps.markDegraded();\n\t\telse deps.recoverDegraded();\n\n\t\t// superseded 过滤 (S3-B): 回查后、egress/精排前 (主路径与全部降级路径\n\t\t// 统一收敛于此 — 被继任的旧条目任何通道都不再出线)。\n\t\tcandidates = filterSupersededCandidates(candidates);\n\n\t\tif (candidates.length === 0) {\n\t\t\treturn {\n\t\t\t\tkind: \"served\",\n\t\t\t\tfacts: [],\n\t\t\t\tcandidateCount: 0,\n\t\t\t\tsuiteFilter,\n\t\t\t\t...(degradedReason === undefined ? {} : { degraded: degradedReason }),\n\t\t\t};\n\t\t}\n\t\tconst egressOutcome = egressGate(candidates);\n\t\tif (egressOutcome.status === \"blocked\") return { kind: \"blocked\", reason: egressOutcome.reason };\n\t\tconst statementByMemoryId = new Map(egressOutcome.packet.facts.map((fact) => [fact.memoryId, fact.statement]));\n\t\tlet ordered: readonly ScoredRecallFactV1[] = candidates.map((entry) => ({\n\t\t\tmemoryId: entry.atom.memoryId,\n\t\t\tstatement: deps.unwrapEgressStatement(statementByMemoryId.get(entry.atom.memoryId) ?? \"\"),\n\t\t\tconfidence: entry.atom.confidence,\n\t\t\tposition: entry.position,\n\t\t}));\n\t\t// 精排 (仅主融合路径: 降级页的排序即其降级语义)。reranker 不可用或调用\n\t\t// 失败 → 保持 RRF 序并携带 degraded 标记; 调用失败不闩锁 (裁决 A: 下一次\n\t\t// 召回重试, 与组件层加载重试语义对齐), 每次失败记一条结构化日志。\n\t\tconst reranker = channel.reranker;\n\t\tif (!channelDegraded && reranker !== undefined) {\n\t\t\ttry {\n\t\t\t\tconst scores = await reranker.rerank(\n\t\t\t\t\tinput.query,\n\t\t\t\t\tordered.map((fact) => fact.statement),\n\t\t\t\t);\n\t\t\t\tordered = ordered\n\t\t\t\t\t.map((fact, position) => ({ ...fact, score: scores[position] }))\n\t\t\t\t\t.sort((left, right) => (right.score ?? 0) - (left.score ?? 0) || left.position - right.position);\n\t\t\t} catch (error) {\n\t\t\t\tdegradedReason ??= \"reranker failed; RRF order without rerank scores\";\n\t\t\t\tdeps.logger?.warn(\n\t\t\t\t\t\"memory reranker failed; recall serves the RRF order this round and retries the next recall\",\n\t\t\t\t\t{\n\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\t// minScore 门槛 (§2.1, 裁决 A 收紧): 仅精排实际产生 score 且过门槛的候选\n\t\t// 参与过滤后结果 (无 score 的候选一律丢弃, 不再放行); 过滤先于 limit 截取。\n\t\t// minScore 只经 auto-recall 内部闭包传入, auto-recall 另按 degraded 标记\n\t\t// 零注入, 双保险钉住\"注入 ⟹ 全部条目有分且过门槛\"。\n\t\tconst minScore = input.minScore;\n\t\tconst eligible =\n\t\t\tminScore === undefined\n\t\t\t\t? ordered\n\t\t\t\t: ordered.filter((fact) => fact.score !== undefined && fact.score >= minScore);\n\t\treturn {\n\t\t\tkind: \"served\",\n\t\t\tfacts: eligible\n\t\t\t\t.slice(0, input.limit)\n\t\t\t\t.map(({ memoryId, statement, confidence }) => ({ memoryId, statement, confidence })),\n\t\t\tcandidateCount: ordered.length,\n\t\t\tsuiteFilter,\n\t\t\t...(degradedReason === undefined ? {} : { degraded: degradedReason }),\n\t\t};\n\t};\n\n\t/**\n\t * Context-scoped preference post-processing over the recalled facts: preference\n\t * atoms compete per (subject, key); the resolver drops out-of-scope preferences\n\t * and deterministically ranks the rest, and an unconfirmed ranking goes through\n\t * the scope-specificity disambiguator. Whatever remains unresolvable is\n\t * returned as an explicit conflict block — the recall never silently picks\n\t * between competing stored values. Non-preference facts pass through untouched.\n\t */\n\tfunction applyPreferenceContext(input: {\n\t\treadonly facts: readonly MemoryFact[];\n\t\treadonly context: PreferenceContextV1;\n\t\treadonly resolver: PreferenceResolverV1;\n\t\treadonly disambiguator: PreferenceDisambiguatorV1;\n\t\treadonly atomOf: (memoryId: string) => MemoryAtomV1 | undefined;\n\t}): { readonly facts: readonly MemoryFact[]; readonly conflicts: readonly RecallConflictV1[] } {\n\t\tconst { facts, context, resolver, disambiguator, atomOf } = input;\n\t\tconst preferenceAtoms: MemoryAtomV1[] = [];\n\t\tconst atomsByGroup = new Map<string, MemoryAtomV1[]>();\n\t\tconst preferenceMemoryIds = new Set<string>();\n\t\tfor (const fact of facts) {\n\t\t\tconst atom = atomOf(fact.memoryId);\n\t\t\tif (atom === undefined || atom.memoryKind !== \"preference\" || atom.preference === undefined) continue;\n\t\t\tpreferenceMemoryIds.add(fact.memoryId);\n\t\t\tpreferenceAtoms.push(atom);\n\t\t\tconst groupKey = `${atom.preference.subject}\\u0000${atom.preference.key}`;\n\t\t\tconst group = atomsByGroup.get(groupKey) ?? [];\n\t\t\tgroup.push(atom);\n\t\t\tatomsByGroup.set(groupKey, group);\n\t\t}\n\t\tif (preferenceMemoryIds.size === 0) return { facts, conflicts: [] };\n\n\t\tconst keptMemoryIds = new Set<string>();\n\t\tconst conflicts: RecallConflictV1[] = [];\n\t\tfor (const decision of resolver.resolve(preferenceAtoms, context)) {\n\t\t\tconst groupAtoms = atomsByGroup.get(`${decision.subject}\\u0000${decision.key}`) ?? [];\n\t\t\tif (decision.status === \"applied\") {\n\t\t\t\tif (decision.winnerMemoryId === undefined) {\n\t\t\t\t\tthrow new Error(`applied preference decision without a winnerMemoryId: ${JSON.stringify(decision)}`);\n\t\t\t\t}\n\t\t\t\tkeptMemoryIds.add(decision.winnerMemoryId);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (decision.status === \"instruction_override\") {\n\t\t\t\t// No stored fact survives a current-instruction override (this slice has\n\t\t\t\t// no input source for currentInstructions, so the branch stays inert).\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (decision.status === \"conflict_unconfirmed\") {\n\t\t\t\tconst outcome = disambiguator.disambiguate(\n\t\t\t\t\tgroupAtoms.map((atom) => ({\n\t\t\t\t\t\tmemoryId: atom.memoryId,\n\t\t\t\t\t\tpreferredValue: atom.preference!.preferredValue,\n\t\t\t\t\t\tscope: atom.preference!.scope,\n\t\t\t\t\t\tevidenceClass: atom.preference!.evidence.class,\n\t\t\t\t\t\tapplicabilityConfidence: atom.preference!.applicabilityConfidence,\n\t\t\t\t\t})),\n\t\t\t\t\tcontext,\n\t\t\t\t);\n\t\t\t\tif (outcome.status === \"resolved\") {\n\t\t\t\t\tkeptMemoryIds.add(outcome.winnerMemoryId);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconflicts.push({\n\t\t\t\t\tsubject: decision.subject,\n\t\t\t\t\tkey: decision.key,\n\t\t\t\t\tcandidates: groupAtoms.map((atom) => {\n\t\t\t\t\t\tconst preference = atom.preference!;\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tmemoryId: atom.memoryId,\n\t\t\t\t\t\t\tstatement: deps.unwrapEgressStatement(deps.statementOf(atom.payload)),\n\t\t\t\t\t\t\tvalue: preference.preferredValue,\n\t\t\t\t\t\t\tevidenceClass: preference.evidence.class,\n\t\t\t\t\t\t\tconfidence: preference.applicabilityConfidence,\n\t\t\t\t\t\t};\n\t\t\t\t\t}),\n\t\t\t\t\texplanation: [...outcome.explanation],\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthrow new Error(`unexpected preference decision status: ${JSON.stringify(decision)}`);\n\t\t}\n\n\t\treturn {\n\t\t\tfacts: facts.filter((fact) => !preferenceMemoryIds.has(fact.memoryId) || keptMemoryIds.has(fact.memoryId)),\n\t\t\tconflicts,\n\t\t};\n\t}\n\n\t/**\n\t * Parses the optional recall context (scenes/projects/tasks) into a preference\n\t * resolution context. Returns undefined when absent so the no-context recall\n\t * path stays byte-identical to the pre-disambiguation behavior.\n\t */\n\tfunction parseRecallContext(value: unknown): PreferenceContextV1 | undefined {\n\t\tif (value === undefined) return undefined;\n\t\tif (!deps.isPlainObject(value)) throw new Error(\"context must be an object\");\n\t\tconst stringArray = (field: \"scenes\" | \"projects\" | \"tasks\"): readonly string[] | undefined => {\n\t\t\tconst entries: unknown = value[field];\n\t\t\tif (entries === undefined) return undefined;\n\t\t\tif (!Array.isArray(entries)) throw new Error(`context.${field} must be an array of strings`);\n\t\t\tfor (const entry of entries) {\n\t\t\t\tif (typeof entry !== \"string\") throw new Error(`context.${field} entries must be strings`);\n\t\t\t}\n\t\t\treturn entries;\n\t\t};\n\t\tconst scenes = stringArray(\"scenes\");\n\t\tconst projects = stringArray(\"projects\");\n\t\tconst tasks = stringArray(\"tasks\");\n\t\treturn {\n\t\t\t...(scenes === undefined ? {} : { scenes }),\n\t\t\t...(projects === undefined ? {} : { projects }),\n\t\t\t...(tasks === undefined ? {} : { tasks }),\n\t\t};\n\t}\n\n\t// 提取为具名闭包: 除模型工具面外, 下方的 auto-recall 钩子直接调用同一 execute\n\t// (单参输入约定, memoryToolInput 取第一参), 不经 runtime.invokeTool —— 钩子\n\t// 随插件注册/卸载, 与工具面同生命周期, 替换工具面不会重接自动召回。\n\tconst recallExecute = async (first: unknown, second?: unknown): Promise<unknown> => {\n\t\tconst input = deps.memoryToolInput(first, second);\n\t\tdeps.assertNonEmptyString(input.query, \"query\");\n\t\tconst rawLimit: unknown = input.limit;\n\t\tconst limit =\n\t\t\trawLimit === undefined\n\t\t\t\t? DEFAULT_RECALL_LIMIT\n\t\t\t\t: ((): number => {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\ttypeof rawLimit !== \"number\" ||\n\t\t\t\t\t\t\t!Number.isSafeInteger(rawLimit) ||\n\t\t\t\t\t\t\trawLimit < 1 ||\n\t\t\t\t\t\t\trawLimit > 100\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tthrow new Error(\"limit must be an integer between 1 and 100\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn rawLimit;\n\t\t\t\t\t})();\n\t\t// 内部执行缝 (§2.1): auto-recall 闭包经本字段恒传质量门槛; memory_recall\n\t\t// 工具 schema 不含该参数 (工具面恒 undefined), 显式召回行为不变。\n\t\tconst rawMinScore: unknown = input.minScore;\n\t\tconst minScore =\n\t\t\trawMinScore === undefined\n\t\t\t\t? undefined\n\t\t\t\t: ((): number => {\n\t\t\t\t\t\tif (typeof rawMinScore !== \"number\" || !Number.isFinite(rawMinScore)) {\n\t\t\t\t\t\t\tthrow new Error(\"minScore must be a finite number\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn rawMinScore;\n\t\t\t\t\t})();\n\t\tconst context = parseRecallContext(input.context);\n\t\tconst { domain } = deps.resolveDomain();\n\n\t\t// enabling 失败 = 本实例终态 (mode 记录回退 off): 记忆工具返回携带原因\n\t\t// 与五选一行动清单的不可用 packet (设计 §3.2 硬性要求), 不再重试。\n\t\tif (deps.rawState() === \"failed\") {\n\t\t\tconst failure = deps.failure() ?? { reason: \"memory enabling failed\", actions: [] as const };\n\t\t\treturn {\n\t\t\t\tstatus: \"unavailable\",\n\t\t\t\tstate: \"failed\",\n\t\t\t\tfacts: [] as MemoryFact[],\n\t\t\t\terror: `memory enabling failed: ${failure.reason}`,\n\t\t\t\tactions: failure.actions,\n\t\t\t};\n\t\t}\n\t\t// 征询门早退 (2026-10-05 用户裁决): 拒绝 = 本实例按模式关闭对待; 待征询 =\n\t\t// 返回带行动清单的 consent-required packet (后续 recall 不再反复探测文件)。\n\t\tif (deps.declined()) {\n\t\t\treturn {\n\t\t\t\tstatus: \"unavailable\",\n\t\t\t\tstate: \"off\",\n\t\t\t\tfacts: [] as MemoryFact[],\n\t\t\t\terror: \"memory was declined on this machine — set memory.mode (light|full) in settings.json and restart the session to re-enable\",\n\t\t\t\tactions: [] as const,\n\t\t\t};\n\t\t}\n\t\tconst consentAsk = deps.consentAsk();\n\t\tif (consentAsk !== undefined) {\n\t\t\treturn {\n\t\t\t\tstatus: \"unavailable\",\n\t\t\t\tstate: \"consent-required\",\n\t\t\t\tfacts: [] as MemoryFact[],\n\t\t\t\terror: consentAsk.message,\n\t\t\t\tactions: consentAsk.actions,\n\t\t\t};\n\t\t}\n\n\t\t// 主键快路径 (memoryIdEquals 语义保留, 幂等/引用而非检索): query 恰为本\n\t\t// 域可见 memoryId 时直接取该条, 不依赖向量通道 (enabling 期间也可用)。\n\t\tlet outcome: SemanticRecallOutcomeV1;\n\t\tconst directRecord = deps.store.get(input.query.trim(), {\n\t\t\towner: deps.owner,\n\t\t\t...(domain.kind === \"suite\" ? { suiteId: domain.suiteId } : {}),\n\t\t});\n\t\tif (directRecord !== undefined) {\n\t\t\tconst gate = egressGate([{ atom: directRecord.atom, position: 0 }]);\n\t\t\tif (gate.status === \"blocked\") {\n\t\t\t\treturn { status: \"failed\", facts: [] as MemoryFact[], error: `egress blocked: ${gate.reason}` };\n\t\t\t}\n\t\t\tconst statementByMemoryId = new Map(gate.packet.facts.map((fact) => [fact.memoryId, fact.statement]));\n\t\t\toutcome = {\n\t\t\t\tkind: \"served\",\n\t\t\t\tfacts: [\n\t\t\t\t\t{\n\t\t\t\t\t\tmemoryId: directRecord.atom.memoryId,\n\t\t\t\t\t\tstatement: deps.unwrapEgressStatement(statementByMemoryId.get(directRecord.atom.memoryId) ?? \"\"),\n\t\t\t\t\t\tconfidence: directRecord.atom.confidence,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tcandidateCount: 1,\n\t\t\t\tsuiteFilter: { legacySkipped: 0, foreignSuiteSkipped: 0 },\n\t\t\t\t// 裁决 A 缝隙收口 (2026-10-05 复审后用户裁决「修复」): 直查是引用\n\t\t\t\t// 语义、未经精排 — 显式召回如实带标记, auto-recall 见标记零注入\n\t\t\t\t// (此前用户消息恰为 memoryId 时会绕过质量门注入该条)。\n\t\t\t\tdegraded: \"primary-key direct lookup (reference semantics, not reranked)\",\n\t\t\t};\n\t\t} else {\n\t\t\ttry {\n\t\t\t\toutcome = await recallSemantically({\n\t\t\t\t\tquery: input.query,\n\t\t\t\t\tdomain,\n\t\t\t\t\tlimit,\n\t\t\t\t\t...(minScore === undefined ? {} : { minScore }),\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\t// 意外异常 (管线 throw) → degraded packet: 结构化返回, 不抛给模型。\n\t\t\t\tdeps.markDegraded();\n\t\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\t\tdeps.logger?.warn(\"memory recall degraded: the recall pipeline threw; returning a degraded packet\", {\n\t\t\t\t\terror: message,\n\t\t\t\t});\n\t\t\t\treturn { status: \"failed\", facts: [] as MemoryFact[], error: message };\n\t\t\t}\n\t\t}\n\t\tif (outcome.kind === \"blocked\") {\n\t\t\treturn { status: \"failed\", facts: [] as MemoryFact[], error: `egress blocked: ${outcome.reason}` };\n\t\t}\n\t\tif (outcome.kind === \"unavailable\") {\n\t\t\t// 首次调用即在装配中途失败时, vectorState 在本调用内才翻成 failed —\n\t\t\t// 这里同样必须携带 enabling 失败的原因 + 行动清单 (设计 §3.2 硬性\n\t\t\t// 要求: 终态的第一份可见 packet 就是完整的), 不等下一次调用补。\n\t\t\t// (vectorState 是可变闭包状态, 语义检索内部会改写它, 入口预检的\n\t\t\t// 收窄在此处不成立 — 经函数边界读取以如实表达。)\n\t\t\tconst stateAtEgress = (): MemoryCapabilityStateV1 => deps.rawState();\n\t\t\tconst failureAtEgress = deps.failure();\n\t\t\tconst consentAskAtEgress = deps.consentAsk();\n\t\t\tif (stateAtEgress() === \"failed\" && failureAtEgress !== undefined) {\n\t\t\t\treturn {\n\t\t\t\t\tstatus: \"unavailable\",\n\t\t\t\t\tstate: \"failed\",\n\t\t\t\t\tfacts: [] as MemoryFact[],\n\t\t\t\t\terror: `memory enabling failed: ${failureAtEgress.reason}`,\n\t\t\t\t\tactions: failureAtEgress.actions,\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tstatus: \"unavailable\",\n\t\t\t\tstate: stateAtEgress(),\n\t\t\t\tfacts: [] as MemoryFact[],\n\t\t\t\terror: outcome.message,\n\t\t\t\t...(stateAtEgress() === \"consent-required\" && consentAskAtEgress !== undefined\n\t\t\t\t\t? { actions: consentAskAtEgress.actions }\n\t\t\t\t\t: {}),\n\t\t\t};\n\t\t}\n\t\tconst facts = outcome.facts;\n\t\t// 增强段 (偏好消歧 + 关系扩散) 是增量元数据面: 内部抛错不得砸穿工具面\n\t\t// (结构化失败契约), 也不吞掉整个召回 — 降级为基础事实 + 一条结构化 warn。\n\t\tconst { finalFacts, resolvedConflicts, related, relatedOmittedCount } = await (async () => {\n\t\t\ttry {\n\t\t\t\tconst resolved =\n\t\t\t\t\tcontext === undefined\n\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t: applyPreferenceContext({\n\t\t\t\t\t\t\t\tfacts,\n\t\t\t\t\t\t\t\tcontext,\n\t\t\t\t\t\t\t\tresolver: deps.preferenceResolver,\n\t\t\t\t\t\t\t\tdisambiguator: deps.preferenceDisambiguator,\n\t\t\t\t\t\t\t\tatomOf: (memoryId) => deps.store.get(memoryId, { owner: deps.owner })?.atom,\n\t\t\t\t\t\t\t});\n\t\t\t\t// 偏好消歧先于关系扩散: the diffusion seeds are the atoms the user\n\t\t\t\t// actually sees — preference facts dropped by the conflict resolution\n\t\t\t\t// never diffuse their relations.\n\t\t\t\tconst baseFacts = resolved === undefined ? facts : resolved.facts;\n\t\t\t\tconst seeds: MemoryAtomV1[] = [];\n\t\t\t\tfor (const fact of baseFacts) {\n\t\t\t\t\tconst atom = deps.store.get(fact.memoryId, { owner: deps.owner })?.atom;\n\t\t\t\t\tif (atom !== undefined) seeds.push(atom);\n\t\t\t\t}\n\t\t\t\t// The traversal graph is the recall domain's visible atom set (same\n\t\t\t\t// suite read boundary). Diffusion targets outside this set are dropped,\n\t\t\t\t// so relations never leak across suites.\n\t\t\t\tconst domainMemoryIds = new Set<string>();\n\t\t\t\tconst graph: MemoryAtomV1[] = [];\n\t\t\t\tfor (const entry of listDomainMemories({ store: deps.store }, { owner: deps.owner, domain }).entries) {\n\t\t\t\t\tdomainMemoryIds.add(entry.memoryId);\n\t\t\t\t\tconst atom = deps.store.get(entry.memoryId, { owner: deps.owner })?.atom;\n\t\t\t\t\tif (atom !== undefined) graph.push(atom);\n\t\t\t\t}\n\t\t\t\tconst related: MemoryNetworkExpansionV1[] = [];\n\t\t\t\tlet relatedOmittedCount = 0;\n\t\t\t\tconst seenRelatedMemoryIds = new Set<string>();\n\t\t\t\tfor (const adapterResult of deps.memoryNetwork.expand({ seeds, graph })) {\n\t\t\t\t\tif (adapterResult.status !== \"completed\") continue;\n\t\t\t\t\tfor (const expansion of adapterResult.related) {\n\t\t\t\t\t\tif (!domainMemoryIds.has(expansion.memoryId)) continue;\n\t\t\t\t\t\tif (seenRelatedMemoryIds.has(expansion.memoryId)) continue;\n\t\t\t\t\t\tseenRelatedMemoryIds.add(expansion.memoryId);\n\t\t\t\t\t\tif (related.length >= MAX_RELATED_REFS) {\n\t\t\t\t\t\t\trelatedOmittedCount += 1;\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\trelated.push(expansion);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tfinalFacts: baseFacts,\n\t\t\t\t\tresolvedConflicts: resolved === undefined ? [] : resolved.conflicts,\n\t\t\t\t\trelated,\n\t\t\t\t\trelatedOmittedCount,\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\tdeps.logger?.warn(\n\t\t\t\t\t\"memory recall enhancement failed; serving the base facts without preference resolution and related references\",\n\t\t\t\t\t{ error: error instanceof Error ? error.message : String(error) },\n\t\t\t\t);\n\t\t\t\treturn {\n\t\t\t\t\tfinalFacts: facts,\n\t\t\t\t\tresolvedConflicts: [],\n\t\t\t\t\trelated: [] as MemoryNetworkExpansionV1[],\n\t\t\t\t\trelatedOmittedCount: 0,\n\t\t\t\t};\n\t\t\t}\n\t\t})();\n\t\treturn {\n\t\t\tstatus: finalFacts.length === 0 ? \"empty\" : \"completed\",\n\t\t\tfacts: finalFacts,\n\t\t\t...(outcome.degraded === undefined ? {} : { degraded: outcome.degraded }),\n\t\t\t...(resolvedConflicts.length > 0 ? { conflicts: resolvedConflicts } : {}),\n\t\t\t...(domain.kind === \"suite\" ? { suiteFilter: outcome.suiteFilter } : {}),\n\t\t\tomittedCount: Math.max(0, outcome.candidateCount - finalFacts.length),\n\t\t\ttruncated: false,\n\t\t\t// References only — no statement/payload egress; the model fetches\n\t\t\t// content via memory_list or another memory_recall.\n\t\t\t...(related.length > 0\n\t\t\t\t? {\n\t\t\t\t\t\trelated: related.map((expansion) => ({\n\t\t\t\t\t\t\tmemoryId: expansion.memoryId,\n\t\t\t\t\t\t\trelationKind: expansion.relationKind,\n\t\t\t\t\t\t\thop: expansion.hop,\n\t\t\t\t\t\t\tweight: expansion.weight,\n\t\t\t\t\t\t\tvia: expansion.via,\n\t\t\t\t\t\t})),\n\t\t\t\t\t}\n\t\t\t\t: {}),\n\t\t\t...(relatedOmittedCount > 0 ? { relatedOmittedCount } : {}),\n\t\t};\n\t};\n\tconst recallTool = deps.registerTool({\n\t\tname: MEMORY_RECALL_TOOL_NAME,\n\t\tlabel: \"Recall memories\",\n\t\tpromptGuidelines: [MEMORY_TOOLS_GUIDE],\n\t\tdescription:\n\t\t\t\"Search this suite's durable memories with semantic recall: vector and full-text channels fuse (RRF) and the result is reranked; an exact memoryId retrieves that memory directly; the result may include related memory references (ids and relation metadata only — recall or list a referenced memory again for its content)\",\n\t\tparameters: recallSchema,\n\t\texecute: recallExecute,\n\t});\n\n\treturn { recallTool, recallExecute };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"recall-pipeline.js","sourceRoot":"","sources":["../../src/memory/recall-pipeline.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAS/B,OAAO,EAAE,kBAAkB,EAA4B,MAAM,mBAAmB,CAAC;AAKjF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAC9B,mgBAA+f,CAAC;AAEjgB,MAAM,oBAAoB,GAAG,CAAC,CAAC;AAE/B,iFAAqE;AACrE,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAE5B,qEAA2C;AAC3C,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAChC,yEAAiD;AACjD,MAAM,YAAY,GAAG,EAAE,CAAC;AACxB,8EAA8C;AAC9C,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAQ9B;;;GAGG;AACH,SAAS,eAAe,CAAC,QAAwC,EAAqB;IACrF,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAChC,KAAK,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;YAClD,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,YAAY,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;QACnF,CAAC;IACF,CAAC;IACD,OAAO,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;SAC1B,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SAC1E,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC;SAC7B,KAAK,CAAC,CAAC,EAAE,kBAAkB,CAAC,CAAC;AAAA,CAC/B;AAgBD,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC;IAChC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC;QAClB,WAAW,EACV,+JAA+J;KAChK,CAAC;IACF,KAAK,EAAE,IAAI,CAAC,QAAQ,CACnB,IAAI,CAAC,OAAO,CAAC;QACZ,WAAW,EAAE,yDAAyD;QACtE,OAAO,EAAE,CAAC;QACV,OAAO,EAAE,GAAG;KACZ,CAAC,CACF;IACD,OAAO,EAAE,IAAI,CAAC,QAAQ,CACrB,IAAI,CAAC,MAAM,CACV;QACC,MAAM,EAAE,IAAI,CAAC,QAAQ,CACpB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE;YACzB,WAAW,EAAE,sEAAsE;SACnF,CAAC,CACF;QACD,QAAQ,EAAE,IAAI,CAAC,QAAQ,CACtB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE;YACzB,WAAW,EAAE,+EAA+E;SAC5F,CAAC,CACF;QACD,KAAK,EAAE,IAAI,CAAC,QAAQ,CACnB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE;YACzB,WAAW,EAAE,oFAAoF;SACjG,CAAC,CACF;KACD,EACD;QACC,WAAW,EACV,mMAAmM;KACpM,CACD,CACD;CACD,CAAC,CAAC;AAsEH,MAAM,UAAU,0BAA0B,CAAC,IAAgC,EAA0B;IACpG;;;;;;;;;;OAUG;IAiCH,wGAAwE;IACxE,MAAM,cAAc,GAAG,CAAC,OAAqC,EAAgC,EAAE,CAC9F,CAAC,GAAG,OAAO,CAAC;SACV,IAAI,CACJ,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CACf,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC;QACpE,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CACpD;SACA,GAAG,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;IAE9D;;;;;;OAMG;IACH,MAAM,0BAA0B,GAAG,CAAC,UAAwC,EAAgC,EAAE,CAAC;QAC9G,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;QACrC,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;YAChC,KAAK,MAAM,QAAQ,IAAI,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;gBAC7C,IAAI,QAAQ,CAAC,IAAI,KAAK,YAAY,IAAI,QAAQ,CAAC,cAAc,KAAK,SAAS,EAAE,CAAC;oBAC7E,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;gBACzC,CAAC;YACF,CAAC;QACF,CAAC;QACD,IAAI,UAAU,CAAC,IAAI,KAAK,CAAC;YAAE,OAAO,UAAU,CAAC;QAC7C,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;IAAA,CAC1E,CAAC;IAEF;;;;OAIG;IACH,MAAM,gBAAgB,GAAG,CACxB,SAAqE,EACrE,OAA2B,EAC6E,EAAE,CAAC;QAC3G,MAAM,UAAU,GAAwB,EAAE,CAAC;QAC3C,IAAI,aAAa,GAAG,CAAC,CAAC;QACtB,IAAI,mBAAmB,GAAG,CAAC,CAAC;QAC5B,KAAK,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,IAAI,SAAS,EAAE,CAAC;YAC9C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE;gBACvC,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC;aAC7C,CAAC,CAAC;YACH,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBAC1B,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;gBACjD,SAAS;YACV,CAAC;YACD,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;gBAC3B,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;gBACnE,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;oBAC9B,IAAI,UAAU,CAAC,IAAI,CAAC,OAAO,KAAK,SAAS;wBAAE,aAAa,IAAI,CAAC,CAAC;;wBACzD,mBAAmB,IAAI,CAAC,CAAC;gBAC/B,CAAC;YACF,CAAC;QACF,CAAC;QACD,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,EAAE,aAAa,EAAE,mBAAmB,EAAE,EAAE,CAAC;IAAA,CAC3E,CAAC;IAEF;;;;OAIG;IACH,MAAM,UAAU,GAAG,CAAC,UAAwC,EAAE,EAAE,CAAC;QAChE,MAAM,QAAQ,GAAuD,EAAE,CAAC;QACxE,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;YAChC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG;gBAC/B,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,UAAU;gBACjC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,OAAkC;aACtD,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC,YAAY,CAAC,KAAK,CAC7B;YACC,WAAW,EAAE,iBAAiB,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE;YAClI,MAAM,EAAE,WAAW;YACnB,KAAK,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBACjC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ;gBAC7B,eAAe,EAAE,KAAK,CAAC,IAAI,CAAC,eAAe;gBAC3C,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC;gBAC7C,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,UAAU;aACjC,CAAC,CAAC;YACH,SAAS,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE,EAAE,aAAa,EAAE,gBAAgB,EAAE;YACrF,QAAQ,EAAE,CAAC;YACX,cAAc,EAAE,EAAE;YAClB,YAAY,EAAE,CAAC;YACf,SAAS,EAAE,KAAK;YAChB,eAAe,EAAE,MAAM;YACvB,MAAM,EAAE;gBACP,eAAe,EAAE,CAAC;gBAClB,oBAAoB,EAAE,CAAC;gBACvB,gBAAgB,EAAE,CAAC;gBACnB,IAAI,EAAE,EAAE,cAAc,EAAE,CAAC,EAAE,mBAAmB,EAAE,CAAC,EAAE,gBAAgB,EAAE,CAAC,EAAE;aACxE;SAC8B,EAChC,QAAQ,CACR,CAAC;IAAA,CACF,CAAC;IAEF,MAAM,kBAAkB,GAAG,KAAK,EAAE,KAWjC,EAAoC,EAAE,CAAC;QACvC,6FAA2C;QAC3C,4FAAsD;QACtD,gFAAoC;QACpC,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;YACpB,OAAO;gBACN,IAAI,EAAE,aAAa;gBACnB,OAAO,EAAE,2FAA2F;aACpG,CAAC;QACH,CAAC;QACD,qGAAuC;QACvC,kGAA0C;QAC1C,0FAAkD;QAClD,wGAAsC;QACtC,2EAAyC;QACzC,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;QAC3C,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC3B,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC;gBACrB,OAAO;oBACN,IAAI,EAAE,aAAa;oBACnB,OAAO,EACN,4HAA0H;iBAC3H,CAAC;YACH,CAAC;YACD,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;YACrC,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;gBAC9B,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,UAAU,CAAC,OAAO,EAAE,CAAC;YAC7D,CAAC;YACD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;YAC/B,OAAO;gBACN,IAAI,EAAE,aAAa;gBACnB,OAAO,EACN,OAAO,KAAK,SAAS;oBACpB,CAAC,CAAC,wCAAwC,IAAI,CAAC,QAAQ,EAAE,GAAG;oBAC5D,CAAC,CAAC,2BAA2B,OAAO,CAAC,MAAM,iBAAe,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;aACzF,CAAC;QACH,CAAC;QACD,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;QACjF,IAAI,YAAY,GAAG,KAAK,CAAC;QACzB,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,IAAI,OAAiD,CAAC;QACtD,IAAI,OAAiD,CAAC;QACtD,IAAI,CAAC;YACJ,MAAM,CAAC,WAAW,CAAC,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,WAAW,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;YACrF,OAAO,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,WAAW,EAAE;gBACnD,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,KAAK,EAAE,oBAAoB;aAC3B,CAAC,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,YAAY,GAAG,IAAI,CAAC;YACpB,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,kFAAkF,EAAE;gBACrG,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;aAC7D,CAAC,CAAC;QACJ,CAAC;QACD,IAAI,CAAC;YACJ,OAAO,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE;gBACnD,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,KAAK,EAAE,oBAAoB;aAC3B,CAAC,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,SAAS,GAAG,IAAI,CAAC;YACjB,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,gDAAgD,EAAE;gBACnE,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;aAC7D,CAAC,CAAC;QACJ,CAAC;QAED,IAAI,UAAwC,CAAC;QAC7C,IAAI,WAAW,GAA6B,EAAE,aAAa,EAAE,CAAC,EAAE,mBAAmB,EAAE,CAAC,EAAE,CAAC;QACzF,IAAI,eAAe,GAAG,KAAK,CAAC;QAC5B,oGAAgD;QAChD,IAAI,cAAkC,CAAC;QACvC,IAAI,CAAC,YAAY,IAAI,CAAC,SAAS,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YACnF,gDAA8B;YAC9B,MAAM,IAAI,GAAG,eAAe,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;YACvG,MAAM,MAAM,GAAG,gBAAgB,CAC9B,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAU,CAAC,EAC/D,OAAO,CACP,CAAC;YACF,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;YAC/B,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;QAClC,CAAC;aAAM,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAClC,6CAA+B;YAC/B,eAAe,GAAG,IAAI,CAAC;YACvB,cAAc,GAAG,6DAA6D,CAAC;YAC/E,MAAM,MAAM,GAAG,gBAAgB,CAC9B,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAU,CAAC,EACjE,OAAO,CACP,CAAC;YACF,UAAU,GAAG,cAAc,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YAC/C,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;QAClC,CAAC;aAAM,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAClC,0DAAwC;YACxC,eAAe,GAAG,IAAI,CAAC;YACvB,cAAc,GAAG,uDAAuD,CAAC;YACzE,MAAM,MAAM,GAAG,gBAAgB,CAC9B,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAU,CAAC,EACjE,OAAO,CACP,CAAC;YACF,UAAU,GAAG,cAAc,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YAC/C,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;QAClC,CAAC;aAAM,CAAC;YACP,0FAA8C;YAC9C,kFAAsD;YACtD,iGAAqC;YACrC,IAAI,CAAC,YAAY,EAAE,CAAC;YACpB,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,oEAAoE,CAAC,CAAC;YACxF,OAAO;gBACN,IAAI,EAAE,aAAa;gBACnB,OAAO,EACN,mHAAmH;aACpH,CAAC;QACH,CAAC;QACD,sFAAkD;QAClD,IAAI,eAAe;YAAE,IAAI,CAAC,YAAY,EAAE,CAAC;;YACpC,IAAI,CAAC,eAAe,EAAE,CAAC;QAE5B,yFAAmD;QACnD,8EAA8B;QAC9B,UAAU,GAAG,0BAA0B,CAAC,UAAU,CAAC,CAAC;QAEpD,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,OAAO;gBACN,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,EAAE;gBACT,cAAc,EAAE,CAAC;gBACjB,WAAW;gBACX,GAAG,CAAC,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,cAAc,EAAE,CAAC;aACrE,CAAC;QACH,CAAC;QACD,MAAM,aAAa,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;QAC7C,IAAI,aAAa,CAAC,MAAM,KAAK,SAAS;YAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,CAAC,MAAM,EAAE,CAAC;QACjG,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QAC/G,IAAI,OAAO,GAAkC,UAAU,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACvE,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ;YAC7B,SAAS,EAAE,IAAI,CAAC,qBAAqB,CAAC,mBAAmB,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACzF,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,UAAU;YACjC,QAAQ,EAAE,KAAK,CAAC,QAAQ;SACxB,CAAC,CAAC,CAAC;QACJ,kGAA4C;QAC5C,iGAAmD;QACnD,+FAAqC;QACrC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;QAClC,IAAI,CAAC,eAAe,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAChD,IAAI,CAAC;gBACJ,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,CACnC,KAAK,CAAC,KAAK,EACX,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CACrC,CAAC;gBACF,OAAO,GAAG,OAAO;qBACf,GAAG,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;qBAC/D,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;YACnG,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,cAAc,KAAK,kDAAkD,CAAC;gBACtE,IAAI,CAAC,MAAM,EAAE,IAAI,CAChB,4FAA4F,EAC5F;oBACC,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;iBAC7D,CACD,CAAC;YACH,CAAC;QACF,CAAC;QACD,8FAAqD;QACrD,sGAAkD;QAClD,qFAA6D;QAC7D,2EAA+B;QAC/B,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;QAChC,MAAM,QAAQ,GACb,QAAQ,KAAK,SAAS;YACrB,CAAC,CAAC,OAAO;YACT,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,IAAI,QAAQ,CAAC,CAAC;QACjF,OAAO;YACN,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,QAAQ;iBACb,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC;iBACrB,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,CAAC;YACrF,cAAc,EAAE,OAAO,CAAC,MAAM;YAC9B,WAAW;YACX,GAAG,CAAC,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,cAAc,EAAE,CAAC;SACrE,CAAC;IAAA,CACF,CAAC;IAEF;;;;;;;OAOG;IACH,SAAS,sBAAsB,CAAC,KAM/B,EAA8F;QAC9F,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;QAClE,MAAM,eAAe,GAAmB,EAAE,CAAC;QAC3C,MAAM,YAAY,GAAG,IAAI,GAAG,EAA0B,CAAC;QACvD,MAAM,mBAAmB,GAAG,IAAI,GAAG,EAAU,CAAC;QAC9C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YAC1B,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACnC,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,UAAU,KAAK,YAAY,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS;gBAAE,SAAS;YACtG,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACvC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC3B,MAAM,QAAQ,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,SAAS,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC;YAC1E,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YAC/C,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACjB,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QACnC,CAAC;QACD,IAAI,mBAAmB,CAAC,IAAI,KAAK,CAAC;YAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;QAEpE,MAAM,aAAa,GAAG,IAAI,GAAG,EAAU,CAAC;QACxC,MAAM,SAAS,GAAuB,EAAE,CAAC;QACzC,KAAK,MAAM,QAAQ,IAAI,QAAQ,CAAC,OAAO,CAAC,eAAe,EAAE,OAAO,CAAC,EAAE,CAAC;YACnE,MAAM,UAAU,GAAG,YAAY,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,OAAO,SAAS,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC;YACtF,IAAI,QAAQ,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBACnC,IAAI,QAAQ,CAAC,cAAc,KAAK,SAAS,EAAE,CAAC;oBAC3C,MAAM,IAAI,KAAK,CAAC,yDAAyD,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;gBACtG,CAAC;gBACD,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;gBAC3C,SAAS;YACV,CAAC;YACD,IAAI,QAAQ,CAAC,MAAM,KAAK,sBAAsB,EAAE,CAAC;gBAChD,yEAAyE;gBACzE,uEAAuE;gBACvE,SAAS;YACV,CAAC;YACD,IAAI,QAAQ,CAAC,MAAM,KAAK,sBAAsB,EAAE,CAAC;gBAChD,MAAM,OAAO,GAAG,aAAa,CAAC,YAAY,CACzC,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;oBACzB,QAAQ,EAAE,IAAI,CAAC,QAAQ;oBACvB,cAAc,EAAE,IAAI,CAAC,UAAW,CAAC,cAAc;oBAC/C,KAAK,EAAE,IAAI,CAAC,UAAW,CAAC,KAAK;oBAC7B,aAAa,EAAE,IAAI,CAAC,UAAW,CAAC,QAAQ,CAAC,KAAK;oBAC9C,uBAAuB,EAAE,IAAI,CAAC,UAAW,CAAC,uBAAuB;iBACjE,CAAC,CAAC,EACH,OAAO,CACP,CAAC;gBACF,IAAI,OAAO,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;oBACnC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;oBAC1C,SAAS;gBACV,CAAC;gBACD,SAAS,CAAC,IAAI,CAAC;oBACd,OAAO,EAAE,QAAQ,CAAC,OAAO;oBACzB,GAAG,EAAE,QAAQ,CAAC,GAAG;oBACjB,UAAU,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;wBACpC,MAAM,UAAU,GAAG,IAAI,CAAC,UAAW,CAAC;wBACpC,OAAO;4BACN,QAAQ,EAAE,IAAI,CAAC,QAAQ;4BACvB,SAAS,EAAE,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;4BACrE,KAAK,EAAE,UAAU,CAAC,cAAc;4BAChC,aAAa,EAAE,UAAU,CAAC,QAAQ,CAAC,KAAK;4BACxC,UAAU,EAAE,UAAU,CAAC,uBAAuB;yBAC9C,CAAC;oBAAA,CACF,CAAC;oBACF,WAAW,EAAE,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC;iBACrC,CAAC,CAAC;gBACH,SAAS;YACV,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,0CAA0C,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACvF,CAAC;QAED,OAAO;YACN,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC1G,SAAS;SACT,CAAC;IAAA,CACF;IAED;;;;OAIG;IACH,SAAS,kBAAkB,CAAC,KAAc,EAAmC;QAC5E,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QAC1C,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAC7E,MAAM,WAAW,GAAG,CAAC,KAAsC,EAAiC,EAAE,CAAC;YAC9F,MAAM,OAAO,GAAY,KAAK,CAAC,KAAK,CAAC,CAAC;YACtC,IAAI,OAAO,KAAK,SAAS;gBAAE,OAAO,SAAS,CAAC;YAC5C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,WAAW,KAAK,8BAA8B,CAAC,CAAC;YAC7F,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;gBAC7B,IAAI,OAAO,KAAK,KAAK,QAAQ;oBAAE,MAAM,IAAI,KAAK,CAAC,WAAW,KAAK,0BAA0B,CAAC,CAAC;YAC5F,CAAC;YACD,OAAO,OAAO,CAAC;QAAA,CACf,CAAC;QACF,MAAM,MAAM,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;QACrC,MAAM,QAAQ,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;QACzC,MAAM,KAAK,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;QACnC,OAAO;YACN,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC;YAC3C,GAAG,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC;YAC/C,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC;SACzC,CAAC;IAAA,CACF;IAED,uGAAqD;IACrD,8FAA8D;IAC9D,kGAAsC;IACtC,MAAM,aAAa,GAAG,KAAK,EAAE,KAAc,EAAE,MAAgB,EAAoB,EAAE,CAAC;QACnF,MAAM,KAAK,GAAG,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAClD,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAChD,MAAM,QAAQ,GAAY,KAAK,CAAC,KAAK,CAAC;QACtC,MAAM,KAAK,GACV,QAAQ,KAAK,SAAS;YACrB,CAAC,CAAC,oBAAoB;YACtB,CAAC,CAAC,CAAC,GAAW,EAAE,CAAC;gBACf,IACC,OAAO,QAAQ,KAAK,QAAQ;oBAC5B,CAAC,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC;oBAC/B,QAAQ,GAAG,CAAC;oBACZ,QAAQ,GAAG,GAAG,EACb,CAAC;oBACF,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;gBAC/D,CAAC;gBACD,OAAO,QAAQ,CAAC;YAAA,CAChB,CAAC,EAAE,CAAC;QACR,2FAAwD;QACxD,sFAA8C;QAC9C,MAAM,WAAW,GAAY,KAAK,CAAC,QAAQ,CAAC;QAC5C,MAAM,QAAQ,GACb,WAAW,KAAK,SAAS;YACxB,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,CAAC,GAAW,EAAE,CAAC;gBACf,IAAI,OAAO,WAAW,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;oBACtE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;gBACrD,CAAC;gBACD,OAAO,WAAW,CAAC;YAAA,CACnB,CAAC,EAAE,CAAC;QACR,MAAM,OAAO,GAAG,kBAAkB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAClD,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QAExC,4FAAkD;QAClD,2FAA4C;QAC5C,IAAI,IAAI,CAAC,QAAQ,EAAE,KAAK,QAAQ,EAAE,CAAC;YAClC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,wBAAwB,EAAE,OAAO,EAAE,EAAW,EAAE,CAAC;YAC7F,OAAO;gBACN,MAAM,EAAE,aAAa;gBACrB,KAAK,EAAE,QAAQ;gBACf,KAAK,EAAE,EAAkB;gBACzB,KAAK,EAAE,2BAA2B,OAAO,CAAC,MAAM,EAAE;gBAClD,OAAO,EAAE,OAAO,CAAC,OAAO;aACxB,CAAC;QACH,CAAC;QACD,kGAAkD;QAClD,+FAAyD;QACzD,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC;YACrB,OAAO;gBACN,MAAM,EAAE,aAAa;gBACrB,KAAK,EAAE,KAAK;gBACZ,KAAK,EAAE,EAAkB;gBACzB,KAAK,EAAE,4HAA0H;gBACjI,OAAO,EAAE,EAAW;aACpB,CAAC;QACH,CAAC;QACD,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;QACrC,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC9B,OAAO;gBACN,MAAM,EAAE,aAAa;gBACrB,KAAK,EAAE,kBAAkB;gBACzB,KAAK,EAAE,EAAkB;gBACzB,KAAK,EAAE,UAAU,CAAC,OAAO;gBACzB,OAAO,EAAE,UAAU,CAAC,OAAO;aAC3B,CAAC;QACH,CAAC;QAED,4FAAoD;QACpD,6FAAiD;QACjD,IAAI,OAAgC,CAAC;QACrC,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE;YACvD,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,GAAG,CAAC,MAAM,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC/D,CAAC,CAAC;QACH,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;YAChC,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,EAAE,IAAI,EAAE,YAAY,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YACpE,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBAC/B,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAkB,EAAE,KAAK,EAAE,mBAAmB,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;YACjG,CAAC;YACD,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YACtG,OAAO,GAAG;gBACT,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE;oBACN;wBACC,QAAQ,EAAE,YAAY,CAAC,IAAI,CAAC,QAAQ;wBACpC,SAAS,EAAE,IAAI,CAAC,qBAAqB,CAAC,mBAAmB,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;wBAChG,UAAU,EAAE,YAAY,CAAC,IAAI,CAAC,UAAU;qBACxC;iBACD;gBACD,cAAc,EAAE,CAAC;gBACjB,WAAW,EAAE,EAAE,aAAa,EAAE,CAAC,EAAE,mBAAmB,EAAE,CAAC,EAAE;gBACzD,wFAA4C;gBAC5C,wFAA0C;gBAC1C,2EAAmC;gBACnC,QAAQ,EAAE,+DAA+D;aACzE,CAAC;QACH,CAAC;aAAM,CAAC;YACP,IAAI,CAAC;gBACJ,OAAO,GAAG,MAAM,kBAAkB,CAAC;oBAClC,KAAK,EAAE,KAAK,CAAC,KAAK;oBAClB,MAAM;oBACN,KAAK;oBACL,GAAG,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC;iBAC/C,CAAC,CAAC;YACJ,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,uFAAmD;gBACnD,IAAI,CAAC,YAAY,EAAE,CAAC;gBACpB,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACvE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,gFAAgF,EAAE;oBACnG,KAAK,EAAE,OAAO;iBACd,CAAC,CAAC;gBACH,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAkB,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;YACxE,CAAC;QACF,CAAC;QACD,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAChC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAkB,EAAE,KAAK,EAAE,mBAAmB,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;QACpG,CAAC;QACD,IAAI,OAAO,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YACpC,2FAA+C;YAC/C,wFAA6C;YAC7C,wFAAwC;YACxC,sFAA0C;YAC1C,wEAA4B;YAC5B,MAAM,aAAa,GAAG,GAA4B,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACrE,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;YACvC,MAAM,kBAAkB,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;YAC7C,IAAI,aAAa,EAAE,KAAK,QAAQ,IAAI,eAAe,KAAK,SAAS,EAAE,CAAC;gBACnE,OAAO;oBACN,MAAM,EAAE,aAAa;oBACrB,KAAK,EAAE,QAAQ;oBACf,KAAK,EAAE,EAAkB;oBACzB,KAAK,EAAE,2BAA2B,eAAe,CAAC,MAAM,EAAE;oBAC1D,OAAO,EAAE,eAAe,CAAC,OAAO;iBAChC,CAAC;YACH,CAAC;YACD,OAAO;gBACN,MAAM,EAAE,aAAa;gBACrB,KAAK,EAAE,aAAa,EAAE;gBACtB,KAAK,EAAE,EAAkB;gBACzB,KAAK,EAAE,OAAO,CAAC,OAAO;gBACtB,GAAG,CAAC,aAAa,EAAE,KAAK,kBAAkB,IAAI,kBAAkB,KAAK,SAAS;oBAC7E,CAAC,CAAC,EAAE,OAAO,EAAE,kBAAkB,CAAC,OAAO,EAAE;oBACzC,CAAC,CAAC,EAAE,CAAC;aACN,CAAC;QACH,CAAC;QACD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;QAC5B,mGAAyC;QACzC,wGAA8C;QAC9C,MAAM,EAAE,UAAU,EAAE,iBAAiB,EAAE,OAAO,EAAE,mBAAmB,EAAE,GAAG,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;YAC1F,IAAI,CAAC;gBACJ,MAAM,QAAQ,GACb,OAAO,KAAK,SAAS;oBACpB,CAAC,CAAC,SAAS;oBACX,CAAC,CAAC,sBAAsB,CAAC;wBACvB,KAAK;wBACL,OAAO;wBACP,QAAQ,EAAE,IAAI,CAAC,kBAAkB;wBACjC,aAAa,EAAE,IAAI,CAAC,uBAAuB;wBAC3C,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,IAAI;qBAC3E,CAAC,CAAC;gBACN,6EAAyD;gBACzD,wEAAsE;gBACtE,iCAAiC;gBACjC,MAAM,SAAS,GAAG,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAClE,MAAM,KAAK,GAAmB,EAAE,CAAC;gBACjC,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;oBAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,IAAI,CAAC;oBACxE,IAAI,IAAI,KAAK,SAAS;wBAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC1C,CAAC;gBACD,oEAAoE;gBACpE,wEAAwE;gBACxE,yCAAyC;gBACzC,MAAM,eAAe,GAAG,IAAI,GAAG,EAAU,CAAC;gBAC1C,MAAM,KAAK,GAAmB,EAAE,CAAC;gBACjC,KAAK,MAAM,KAAK,IAAI,kBAAkB,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;oBACtG,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;oBACpC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,IAAI,CAAC;oBACzE,IAAI,IAAI,KAAK,SAAS;wBAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC1C,CAAC;gBACD,MAAM,OAAO,GAA+B,EAAE,CAAC;gBAC/C,IAAI,mBAAmB,GAAG,CAAC,CAAC;gBAC5B,MAAM,oBAAoB,GAAG,IAAI,GAAG,EAAU,CAAC;gBAC/C,KAAK,MAAM,aAAa,IAAI,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;oBACzE,IAAI,aAAa,CAAC,MAAM,KAAK,WAAW;wBAAE,SAAS;oBACnD,KAAK,MAAM,SAAS,IAAI,aAAa,CAAC,OAAO,EAAE,CAAC;wBAC/C,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC;4BAAE,SAAS;wBACvD,IAAI,oBAAoB,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC;4BAAE,SAAS;wBAC3D,oBAAoB,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;wBAC7C,IAAI,OAAO,CAAC,MAAM,IAAI,gBAAgB,EAAE,CAAC;4BACxC,mBAAmB,IAAI,CAAC,CAAC;4BACzB,SAAS;wBACV,CAAC;wBACD,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;oBACzB,CAAC;gBACF,CAAC;gBACD,OAAO;oBACN,UAAU,EAAE,SAAS;oBACrB,iBAAiB,EAAE,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS;oBACnE,OAAO;oBACP,mBAAmB;iBACnB,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,IAAI,CAAC,MAAM,EAAE,IAAI,CAChB,+GAA+G,EAC/G,EAAE,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CACjE,CAAC;gBACF,OAAO;oBACN,UAAU,EAAE,KAAK;oBACjB,iBAAiB,EAAE,EAAE;oBACrB,OAAO,EAAE,EAAgC;oBACzC,mBAAmB,EAAE,CAAC;iBACtB,CAAC;YACH,CAAC;QAAA,CACD,CAAC,EAAE,CAAC;QACL,OAAO;YACN,MAAM,EAAE,UAAU,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW;YACvD,KAAK,EAAE,UAAU;YACjB,yEAAyE;YACzE,4DAA4D;YAC5D,MAAM,EAAE,MAAM,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ;YAC3D,GAAG,CAAC,MAAM,CAAC,IAAI,KAAK,QAAQ;gBAC3B,CAAC,CAAC;oBACA,OAAO,EACN,sIAAsI;iBACvI;gBACF,CAAC,CAAC,EAAE,CAAC;YACN,GAAG,CAAC,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC;YACzE,GAAG,CAAC,iBAAiB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACzE,GAAG,CAAC,MAAM,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACxE,YAAY,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,cAAc,GAAG,UAAU,CAAC,MAAM,CAAC;YACrE,SAAS,EAAE,KAAK;YAChB,qEAAmE;YACnE,oDAAoD;YACpD,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;gBACrB,CAAC,CAAC;oBACA,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;wBACpC,QAAQ,EAAE,SAAS,CAAC,QAAQ;wBAC5B,YAAY,EAAE,SAAS,CAAC,YAAY;wBACpC,GAAG,EAAE,SAAS,CAAC,GAAG;wBAClB,MAAM,EAAE,SAAS,CAAC,MAAM;wBACxB,GAAG,EAAE,SAAS,CAAC,GAAG;qBAClB,CAAC,CAAC;iBACH;gBACF,CAAC,CAAC,EAAE,CAAC;YACN,GAAG,CAAC,mBAAmB,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,mBAAmB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC3D,CAAC;IAAA,CACF,CAAC;IACF,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,CAAC;QACpC,IAAI,EAAE,uBAAuB;QAC7B,KAAK,EAAE,iBAAiB;QACxB,gBAAgB,EAAE,CAAC,kBAAkB,CAAC;QACtC,WAAW,EACV,kUAAgU;QACjU,UAAU,EAAE,YAAY;QACxB,OAAO,EAAE,aAAa;KACtB,CAAC,CAAC;IAEH,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,CAAC;AAAA,CACrC","sourcesContent":["/**\n * 召回管线(capability 拆分战役 slice 4):双通道查询、RRF 融合、egress 门、语义召回与召回工具。状态机经 vectorChannel 只读面消费, 降级经回调上报\n */\nimport type { CapabilityAPI, DisposableRegistration, JsonValue } from \"@agent-forge/plugin-sdk\";\nimport { MEMORY_RECALL_TOOL_NAME } from \"@agent-forge/plugin-sdk\";\nimport { Type } from \"typebox\";\nimport type { MemoryEgressFactInfoV1, MemoryEgressPolicyGateV1 } from \"./egress-policy.ts\";\nimport type { MemoryAtomV1, MemoryPreferenceEnvelopeV1, MemorySuiteFilterStatsV1 } from \"./foundation.ts\";\nimport type { DurableMemoryLedgerV1 } from \"./ledger.ts\";\nimport type { MemoryNetworkExpansionV1, MemoryNetworkV1 } from \"./memory-network.ts\";\nimport type { PreferenceDisambiguatorV1 } from \"./preference-disambiguator.ts\";\nimport type { PreferenceContextV1, PreferenceResolverV1 } from \"./preference-resolver.ts\";\nimport type { MemoryRecallPacketV1 } from \"./recall-packet.ts\";\nimport type { MemoryStoreV1 } from \"./store.ts\";\nimport { listDomainMemories, type SuiteMemoryDomainV1 } from \"./suite-memory.ts\";\nimport type { MemoryCapabilityStateV1, MemoryConsentAskV1, MemoryEnablingFailureV1 } from \"./vector-channel.ts\";\nimport type { MemoryVectorHitV1 } from \"./vector-index.ts\";\nimport type { ActiveVectorChannelV1 } from \"./vector-projection.ts\";\n\n/**\n * Memory tools guide(记忆 runtime 注入面,原 system-prompt.ts MEMORY_TOOL_GUIDE,\n * D-071 迁移):the model-facing hint that the persistent memory tools exist.\n * It rides memory_recall's promptGuidelines so the text lives with the plugin\n * that owns the tools (宪法 §3) and renders whenever the tool face is active.\n */\nexport const MEMORY_TOOLS_GUIDE =\n\t\"Memory: You have persistent memory tools (memory_write, memory_recall, memory_list, memory_forget). Use memory_recall only when past decisions, preferences, or project facts are actually relevant to the current question — not on every turn. Use memory_write only for facts the user explicitly stated or that a tool/test verified; never save your own inferences or guesses as facts, and declare the honest evidence class. memory_forget only files a forget request — deletion happens after the user confirms it.\";\n\nconst DEFAULT_RECALL_LIMIT = 5;\n\n/** Bounded supplementary relation references per recall (记忆网络接线). */\nconst MAX_RELATED_REFS = 20;\n\n/** FTS / KNN 通道各自取回深度 (定版管线: depth 50)。 */\nconst HYBRID_CHANNEL_DEPTH = 50;\n/** RRF 常数, 与 vector-index 组件 queryFts 打分口径一致。 */\nconst HYBRID_RRF_K = 60;\n/** 融合候选池上限 (定版管线: top20 → 精排 → top limit)。 */\nconst HYBRID_FUSION_POOL = 20;\n\ninterface MemoryFact {\n\treadonly memoryId: string;\n\treadonly statement: string;\n\treadonly confidence: number;\n}\n\n/**\n * 三通道 RRF 融合 (定版管线): `score(id) += 1/(k + rank + 1)` 对各通道排名累加,\n * 取 top {@link HYBRID_FUSION_POOL}。分数并列时以 memoryId 升序打破, 保证确定性。\n */\nfunction rrfFuseRankings(rankings: readonly (readonly string[])[]): readonly string[] {\n\tconst scores = new Map<string, number>();\n\tfor (const ranking of rankings) {\n\t\tfor (const [rank, memoryId] of ranking.entries()) {\n\t\t\tscores.set(memoryId, (scores.get(memoryId) ?? 0) + 1 / (HYBRID_RRF_K + rank + 1));\n\t\t}\n\t}\n\treturn [...scores.entries()]\n\t\t.sort((left, right) => right[1] - left[1] || (left[0] < right[0] ? -1 : 1))\n\t\t.map(([memoryId]) => memoryId)\n\t\t.slice(0, HYBRID_FUSION_POOL);\n}\n\n/** One unresolvably competing preference, surfaced verbatim instead of a silent pick. */\ninterface RecallConflictV1 {\n\treadonly subject: MemoryPreferenceEnvelopeV1[\"subject\"];\n\treadonly key: string;\n\treadonly candidates: readonly {\n\t\treadonly memoryId: string;\n\t\treadonly statement: string;\n\t\treadonly value: JsonValue;\n\t\treadonly evidenceClass: MemoryPreferenceEnvelopeV1[\"evidence\"][\"class\"];\n\t\treadonly confidence: number;\n\t}[];\n\treadonly explanation: readonly string[];\n}\n\nconst recallSchema = Type.Object({\n\tquery: Type.String({\n\t\tdescription:\n\t\t\t\"Natural-language query; recall fuses semantic (vector) and full-text (BM25) matching and reranks the result. An exact memoryId retrieves that memory directly\",\n\t}),\n\tlimit: Type.Optional(\n\t\tType.Integer({\n\t\t\tdescription: \"Maximum number of memories to return (1-100, default 5)\",\n\t\t\tminimum: 1,\n\t\t\tmaximum: 100,\n\t\t}),\n\t),\n\tcontext: Type.Optional(\n\t\tType.Object(\n\t\t\t{\n\t\t\t\tscenes: Type.Optional(\n\t\t\t\t\tType.Array(Type.String(), {\n\t\t\t\t\t\tdescription: \"Scene tags of the current task, used to resolve preferences by scope\",\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t\tprojects: Type.Optional(\n\t\t\t\t\tType.Array(Type.String(), {\n\t\t\t\t\t\tdescription: \"Project identifiers of the current task, used to resolve preferences by scope\",\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t\ttasks: Type.Optional(\n\t\t\t\t\tType.Array(Type.String(), {\n\t\t\t\t\t\tdescription: \"Task or goal identifiers of the current task, used to resolve preferences by scope\",\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t},\n\t\t\t{\n\t\t\t\tdescription:\n\t\t\t\t\t\"Current scope context; when present, recalled preferences are resolved against it (out-of-scope preferences drop, competing values resolve by scope specificity or surface as explicit conflicts)\",\n\t\t\t},\n\t\t),\n\t),\n});\n\n/**\n * 召回管线对 capability 闭包的显式依赖视图 (slice 4): 逐项来自\n * createMemoryCapabilityHarness 的闭包捕获核实。状态机 (vectorChannelCtl) 与\n * 写侧投影 (vectorProjection) 归 capability 装配所有, 本模块经只读回调消费与\n * 上报, 不持有任何状态机变量; capability 模块级纯函数经 deps 注入避免双头定义。\n */\nexport interface MemoryRecallPipelineDepsV1 {\n\t/** capability 日志面 (api.logger): 通道降级/增强失败的结构化日志。 */\n\treadonly logger: CapabilityAPI[\"logger\"];\n\t/** 检索行 owner (capability.BUILTIN_MEMORY_OWNER)。 */\n\treadonly owner: string;\n\t/** 会话 id (harness sessionId): egress operationId 组成。 */\n\treadonly sessionId: string;\n\t/** canonical store (per-capability 单例): store 回查与增强段 atom 读取。 */\n\treadonly store: MemoryStoreV1;\n\t/** 域解析 (capability.resolveDomain): 每次 recall 调用时惰性解析 (B1 语义)。 */\n\treadonly resolveDomain: () => {\n\t\treadonly domain: SuiteMemoryDomainV1;\n\t\treadonly domainName: string;\n\t\treadonly ledger: DurableMemoryLedgerV1;\n\t};\n\t/** egress 门 (capability.egressPolicy): 与旧锚点 packet 同一 gate。 */\n\treadonly egressPolicy: MemoryEgressPolicyGateV1;\n\t/** context-scoped 偏好解析 (2.4c/2.4d2)。 */\n\treadonly preferenceResolver: PreferenceResolverV1;\n\t/** 未决偏好的确定性消歧 (2.4c/2.4d2)。 */\n\treadonly preferenceDisambiguator: PreferenceDisambiguatorV1;\n\t/** 关系扩散 (记忆网络接线): recall 种子的一跳扩展。 */\n\treadonly memoryNetwork: MemoryNetworkV1;\n\t// ---- vectorChannel 只读面 (slice 3b 的 vectorChannelCtl, 状态机归其所有) ----\n\t/** warming 守卫: 后台预热在途且未拒绝时 recall 零等待返回 unavailable。 */\n\treadonly warming: () => boolean;\n\t/** 惰性装配 (vectorEnsure 单飞语义原样保留): undefined = 通道不可用。 */\n\treadonly ensureChannel: () => Promise<ActiveVectorChannelV1 | undefined>;\n\t/** 征询拒绝标记 (declined): recall 按模式关闭对待。 */\n\treadonly declined: () => boolean;\n\t/** 待征询信息 (consent-required): recall 返回征询话术包。 */\n\treadonly consentAsk: () => MemoryConsentAskV1 | undefined;\n\t/** enabling 结构化失败 (原因 + 行动清单, 设计 §3.2)。 */\n\treadonly failure: () => MemoryEnablingFailureV1 | undefined;\n\t/** 通道原始状态 (未做 declined 投影): packet 的 state 字段来源。 */\n\treadonly rawState: () => MemoryCapabilityStateV1;\n\t/** 运行期故障的 degraded 转换回调 (状态转换语义归状态机)。 */\n\treadonly markDegraded: () => void;\n\t/** 全通成功的 degraded 自愈回调。 */\n\treadonly recoverDegraded: () => void;\n\t// ---- 写侧投影 (slice 3a 的 vectorProjection) ----\n\t/** 读侧 FIFO 等待 (await vectorQueue): 保写入→召回次序。 */\n\treadonly settleProjection: () => Promise<unknown>;\n\t// ---- capability 模块级纯函数 (留守方, 经 deps 注入避免双头定义) ----\n\treadonly memoryToolInput: (first: unknown, second: unknown) => Record<string, unknown>;\n\treadonly assertNonEmptyString: (value: unknown, label: string) => asserts value is string;\n\treadonly isPlainObject: (value: unknown) => value is Record<string, unknown>;\n\treadonly identityHash: (value: string) => string;\n\treadonly statementOf: (payload: unknown) => string;\n\treadonly unwrapEgressStatement: (statement: string) => string;\n\t/** 工具注册面 (api.registerTool): memory_recall 经同一公共通道注册。 */\n\treadonly registerTool: CapabilityAPI[\"registerTool\"];\n}\n\n/** 召回管线工厂产物: 工具注册项 + auto-recall 直连的执行闭包。 */\nexport interface MemoryRecallPipelineV1 {\n\t/** memory_recall 工具注册项 (capability registrations 收集)。 */\n\treadonly recallTool: DisposableRegistration;\n\t/** 召回执行闭包 (原 recallExecute): autoRecallBlock (留守, slice 7) 直连同一 execute。 */\n\treadonly recallExecute: (first: unknown, second?: unknown) => Promise<unknown>;\n}\n\nexport function createMemoryRecallPipeline(deps: MemoryRecallPipelineDepsV1): MemoryRecallPipelineV1 {\n\t/**\n\t * 语义召回管线 (2.4d6 S2, 设计 §4) — 唯一检索路径: embed(查询, light 加 BGE\n\t * 前缀) → KNN depth50 + FTS depth50 → RRF k=60 top20 → 精排 → store 回查\n\t * (owner/suite/scope/过期, 单一可见性路径, 不足 limit 不回填)。降级层级\n\t * (2026-10-05 裁决 A「宁漏勿错」, 每次降级一条结构化日志, 状态转 degraded\n\t * 可自愈): 精排失败 → RRF 序 + degraded 标记 (不闩锁, 下次重试); 向量失败\n\t * (embed/KNN) → FTS-only + degraded; FTS 失败 → KNN-only + degraded;\n\t * 双通道皆败 → unavailable (语义召回不可用, memory_list 仍是列表入口;\n\t * recency 枚举兜底已移除 — 语义查询返回\"最近的几条\"是对查询语义的错答)。\n\t * degraded 标记对显式召回可见; auto-recall 见标记零注入。\n\t */\n\n\t/** 一次语义召回的中间候选: atom + 融合/降级序位 (精排并列打破用)。 */\n\tinterface RecallCandidateV1 {\n\t\treadonly atom: MemoryAtomV1;\n\t\treadonly position: number;\n\t}\n\n\t/** 出线事实行 (含精排可选分): score 缺席 = 该路径未产生精排分。 */\n\tinterface ScoredRecallFactV1 {\n\t\treadonly memoryId: string;\n\t\treadonly statement: string;\n\t\treadonly confidence: number;\n\t\treadonly position: number;\n\t\treadonly score?: number;\n\t}\n\n\ttype SemanticRecallOutcomeV1 =\n\t\t| {\n\t\t\t\treadonly kind: \"served\";\n\t\t\t\treadonly facts: readonly MemoryFact[];\n\t\t\t\treadonly candidateCount: number;\n\t\t\t\treadonly suiteFilter: MemorySuiteFilterStatsV1;\n\t\t\t\t/**\n\t\t\t\t * 降级原因短语 (2026-10-05 裁决 A「宁漏勿错」): 存在即本次结果未经\n\t\t\t\t * 精排打分。显式召回照常服务并携带该标记 (模型可见); auto-recall\n\t\t\t\t * 见标记零注入。\n\t\t\t\t */\n\t\t\t\treadonly degraded?: string;\n\t\t }\n\t\t| { readonly kind: \"blocked\"; readonly reason: string }\n\t\t| { readonly kind: \"unavailable\"; readonly message: string };\n\n\t/** recency 排序 (occurredAt 降序, memoryId 升序打破并列 — 与 recall index 同口径)。 */\n\tconst recencyOrdered = (entries: readonly RecallCandidateV1[]): readonly RecallCandidateV1[] =>\n\t\t[...entries]\n\t\t\t.sort(\n\t\t\t\t(left, right) =>\n\t\t\t\t\tDate.parse(right.atom.occurredAt) - Date.parse(left.atom.occurredAt) ||\n\t\t\t\t\t(left.atom.memoryId < right.atom.memoryId ? -1 : 1),\n\t\t\t)\n\t\t\t.map((entry, position) => ({ atom: entry.atom, position }));\n\n\t/**\n\t * superseded 过滤 (S3-B, store 回查后 / 精排前): 被某条在场候选的 supersedes\n\t * 关系指向的旧条目不再出线 — 合并后同义查询只出新条目。\"新条目在场\"以候选\n\t * 集为界: 继任条目被遗忘 (purge/过期) 后其关系随之消失, 旧条目自然恢复出线。\n\t * memoryId 主键直查不经此过滤 (引用不失效), memory_list 管理面不过滤\n\t * (nothing silently dropped — 用户可显式 forget 旧条目)。\n\t */\n\tconst filterSupersededCandidates = (candidates: readonly RecallCandidateV1[]): readonly RecallCandidateV1[] => {\n\t\tconst superseded = new Set<string>();\n\t\tfor (const entry of candidates) {\n\t\t\tfor (const relation of entry.atom.relations) {\n\t\t\t\tif (relation.kind === \"supersedes\" && relation.targetMemoryId !== undefined) {\n\t\t\t\t\tsuperseded.add(relation.targetMemoryId);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (superseded.size === 0) return candidates;\n\t\treturn candidates.filter((entry) => !superseded.has(entry.atom.memoryId));\n\t};\n\n\t/**\n\t * store 回查 (正确性关键): 候选 id 逐条走与旧锚点通道相同的可见性单一路径\n\t * (owner + suite 读边界 + 过期, 单一路径); suite 场景下不可见 id 按 legacy/\n\t * 外套件区分计数 (suiteFilter 可观测), 不可见者丢弃且不回填 (诚实分页)。\n\t */\n\tconst lookupCandidates = (\n\t\trankedIds: readonly (readonly [memoryId: string, position: number])[],\n\t\tsuiteId: string | undefined,\n\t): { readonly candidates: readonly RecallCandidateV1[]; readonly suiteFilter: MemorySuiteFilterStatsV1 } => {\n\t\tconst candidates: RecallCandidateV1[] = [];\n\t\tlet legacySkipped = 0;\n\t\tlet foreignSuiteSkipped = 0;\n\t\tfor (const [memoryId, position] of rankedIds) {\n\t\t\tconst record = deps.store.get(memoryId, {\n\t\t\t\towner: deps.owner,\n\t\t\t\t...(suiteId === undefined ? {} : { suiteId }),\n\t\t\t});\n\t\t\tif (record !== undefined) {\n\t\t\t\tcandidates.push({ atom: record.atom, position });\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (suiteId !== undefined) {\n\t\t\t\tconst unfiltered = deps.store.get(memoryId, { owner: deps.owner });\n\t\t\t\tif (unfiltered !== undefined) {\n\t\t\t\t\tif (unfiltered.atom.suiteId === undefined) legacySkipped += 1;\n\t\t\t\t\telse foreignSuiteSkipped += 1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn { candidates, suiteFilter: { legacySkipped, foreignSuiteSkipped } };\n\t};\n\n\t/**\n\t * egress 门重放 (设计 §11 MUST run): 对最终候选统一执行, 与旧锚点 packet 同\n\t * 一 gate、同一 factInfo 来源 (store); blocked 即 fail-closed, 该次 recall\n\t * 返回 failed packet (来源未登记的事实永不越过出界面)。\n\t */\n\tconst egressGate = (candidates: readonly RecallCandidateV1[]) => {\n\t\tconst factInfo: Record<string, MemoryEgressFactInfoV1 | undefined> = {};\n\t\tfor (const entry of candidates) {\n\t\t\tfactInfo[entry.atom.memoryId] = {\n\t\t\t\tsourceRefs: entry.atom.sourceRefs,\n\t\t\t\tpayload: entry.atom.payload as Record<string, unknown>,\n\t\t\t};\n\t\t}\n\t\treturn deps.egressPolicy.apply(\n\t\t\t{\n\t\t\t\toperationId: `memory_recall:${deps.sessionId}:${deps.identityHash(candidates.map((entry) => entry.atom.memoryId).join(\"\\u0000\"))}`,\n\t\t\t\tstatus: \"completed\",\n\t\t\t\tfacts: candidates.map((entry) => ({\n\t\t\t\t\tmemoryId: entry.atom.memoryId,\n\t\t\t\t\tcontentRevision: entry.atom.contentRevision,\n\t\t\t\t\tstatement: JSON.stringify(entry.atom.payload),\n\t\t\t\t\tconfidence: entry.atom.confidence,\n\t\t\t\t})),\n\t\t\t\tqueryPlan: { lookupUsed: false, filtersApplied: [], scorerVersion: \"semantic-rrf@1\" },\n\t\t\t\tattempts: 0,\n\t\t\t\tnarrowingHints: [],\n\t\t\t\tomittedCount: 0,\n\t\t\t\ttruncated: false,\n\t\t\t\ttruncationScope: \"none\",\n\t\t\t\tbudget: {\n\t\t\t\t\tcandidateBudget: 0,\n\t\t\t\t\tmodelInspectionLimit: 0,\n\t\t\t\t\tfinalResultLimit: 0,\n\t\t\t\t\tused: { candidateCount: 0, modelInspectedCount: 0, finalResultCount: 0 },\n\t\t\t\t},\n\t\t\t} satisfies MemoryRecallPacketV1,\n\t\t\tfactInfo,\n\t\t);\n\t};\n\n\tconst recallSemantically = async (input: {\n\t\treadonly query: string;\n\t\treadonly domain: SuiteMemoryDomainV1;\n\t\treadonly limit: number;\n\t\t/**\n\t\t * 自动召回质量门槛 (错误教训与召回质量护栏设计 §2.1, 内部执行缝):\n\t\t * memory_recall 工具 schema 不含该参数, 显式召回行为不变; auto-recall\n\t\t * 钩子经内部闭包恒传。仅精排实际产生 score 且过门槛的候选保留 (裁决 A\n\t\t * 收紧: 无 score 候选一律丢弃)。\n\t\t */\n\t\treadonly minScore?: number;\n\t}): Promise<SemanticRecallOutcomeV1> => {\n\t\t// 后台预热不阻塞读侧 (2026-10-05 流程裁决「后台预热、不阻塞提问」):\n\t\t// 下载/加载进行中时 recall 直接返回 warming 不可用包, 不等待 vectorQueue\n\t\t// (队列此时可能正背着启动对账或下载任务) 与 ensure 单飞。\n\t\tif (deps.warming()) {\n\t\t\treturn {\n\t\t\t\tkind: \"unavailable\",\n\t\t\t\tmessage: \"memory models are loading in the background; recall becomes available once they are ready\",\n\t\t\t};\n\t\t}\n\t\t// 读侧先等写侧队列在调用时刻已入队的部分 (待处理的投影写入 + 启动对账\n\t\t// 已入队的块), 保证写入→召回 FIFO: 本调用之前提交的写入其投影先落地,\n\t\t// 不与后台对账/埋点竞态。启动对账的分块自续 (RECONCILE_CHUNK_UPSERTS)\n\t\t// 在块完成时才入队下一块, 未入队的后续块不阻塞本次召回——未回填条目由\n\t\t// store 回查与 memory_list 兜底, 残行由后续对账继续补齐。\n\t\tawait deps.settleProjection();\n\t\tconst channel = await deps.ensureChannel();\n\t\tif (channel === undefined) {\n\t\t\tif (deps.declined()) {\n\t\t\t\treturn {\n\t\t\t\t\tkind: \"unavailable\",\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t\"memory was declined on this machine — set memory.mode (light|full) in settings.json and restart the session to re-enable\",\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst consentAsk = deps.consentAsk();\n\t\t\tif (consentAsk !== undefined) {\n\t\t\t\treturn { kind: \"unavailable\", message: consentAsk.message };\n\t\t\t}\n\t\t\tconst failure = deps.failure();\n\t\t\treturn {\n\t\t\t\tkind: \"unavailable\",\n\t\t\t\tmessage:\n\t\t\t\t\tfailure === undefined\n\t\t\t\t\t\t? `memory channel is unavailable (state=${deps.rawState()})`\n\t\t\t\t\t\t: `memory enabling failed: ${failure.reason} — actions: ${failure.actions.join(\" | \")}`,\n\t\t\t};\n\t\t}\n\t\tconst suiteId = input.domain.kind === \"suite\" ? input.domain.suiteId : undefined;\n\t\tlet vectorFailed = false;\n\t\tlet ftsFailed = false;\n\t\tlet knnHits: readonly MemoryVectorHitV1[] | undefined;\n\t\tlet ftsHits: readonly MemoryVectorHitV1[] | undefined;\n\t\ttry {\n\t\t\tconst [queryVector] = await channel.embed.embed([channel.queryPrefix + input.query]);\n\t\t\tknnHits = await channel.index.queryKnn(queryVector, {\n\t\t\t\towner: deps.owner,\n\t\t\t\tlimit: HYBRID_CHANNEL_DEPTH,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tvectorFailed = true;\n\t\t\tdeps.logger?.warn(\"memory recall degraded: the vector channel failed; continuing on the FTS channel\", {\n\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t});\n\t\t}\n\t\ttry {\n\t\t\tftsHits = await channel.index.queryFts(input.query, {\n\t\t\t\towner: deps.owner,\n\t\t\t\tlimit: HYBRID_CHANNEL_DEPTH,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tftsFailed = true;\n\t\t\tdeps.logger?.warn(\"memory recall degraded: the FTS channel failed\", {\n\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t});\n\t\t}\n\n\t\tlet candidates: readonly RecallCandidateV1[];\n\t\tlet suiteFilter: MemorySuiteFilterStatsV1 = { legacySkipped: 0, foreignSuiteSkipped: 0 };\n\t\tlet channelDegraded = false;\n\t\t// 裁决 A: 降级原因短语, 透出到工具结果的 degraded 字段 (无精排分数路径)。\n\t\tlet degradedReason: string | undefined;\n\t\tif (!vectorFailed && !ftsFailed && knnHits !== undefined && ftsHits !== undefined) {\n\t\t\t// 主路径: 双通道 RRF k=60 融合 top20。\n\t\t\tconst pool = rrfFuseRankings([ftsHits.map((hit) => hit.memoryId), knnHits.map((hit) => hit.memoryId)]);\n\t\t\tconst lookup = lookupCandidates(\n\t\t\t\tpool.map((memoryId, position) => [memoryId, position] as const),\n\t\t\t\tsuiteId,\n\t\t\t);\n\t\t\tcandidates = lookup.candidates;\n\t\t\tsuiteFilter = lookup.suiteFilter;\n\t\t} else if (ftsHits !== undefined) {\n\t\t\t// 向量失败: FTS-only + recency 排序。\n\t\t\tchannelDegraded = true;\n\t\t\tdegradedReason = \"vector channel failed; full-text-only results, not reranked\";\n\t\t\tconst lookup = lookupCandidates(\n\t\t\t\tftsHits.map((hit, position) => [hit.memoryId, position] as const),\n\t\t\t\tsuiteId,\n\t\t\t);\n\t\t\tcandidates = recencyOrdered(lookup.candidates);\n\t\t\tsuiteFilter = lookup.suiteFilter;\n\t\t} else if (knnHits !== undefined) {\n\t\t\t// FTS 失败: KNN-only + recency 排序 (对称降级)。\n\t\t\tchannelDegraded = true;\n\t\t\tdegradedReason = \"FTS channel failed; vector-only results, not reranked\";\n\t\t\tconst lookup = lookupCandidates(\n\t\t\t\tknnHits.map((hit, position) => [hit.memoryId, position] as const),\n\t\t\t\tsuiteId,\n\t\t\t);\n\t\t\tcandidates = recencyOrdered(lookup.candidates);\n\t\t\tsuiteFilter = lookup.suiteFilter;\n\t\t} else {\n\t\t\t// 双通道皆败 = 语义召回能力不可用 (2026-10-05 裁决 A): 显式召回返回\n\t\t\t// 结构化 unavailable (memory_list 仍是列表入口), recency 枚举兜底从\n\t\t\t// 语义召回路径移除 — 语义查询返回\"最近的几条\"是对查询语义的错答。\n\t\t\tdeps.markDegraded();\n\t\t\tdeps.logger?.warn(\"memory recall unavailable: both the vector and FTS channels failed\");\n\t\t\treturn {\n\t\t\t\tkind: \"unavailable\",\n\t\t\t\tmessage:\n\t\t\t\t\t\"memory recall is unavailable (both retrieval channels failed); use memory_list to enumerate this suite's memories\",\n\t\t\t};\n\t\t}\n\t\t// 运行期通道故障 → degraded (可自愈: 下一次全通 recall 回 ready)。\n\t\tif (channelDegraded) deps.markDegraded();\n\t\telse deps.recoverDegraded();\n\n\t\t// superseded 过滤 (S3-B): 回查后、egress/精排前 (主路径与全部降级路径\n\t\t// 统一收敛于此 — 被继任的旧条目任何通道都不再出线)。\n\t\tcandidates = filterSupersededCandidates(candidates);\n\n\t\tif (candidates.length === 0) {\n\t\t\treturn {\n\t\t\t\tkind: \"served\",\n\t\t\t\tfacts: [],\n\t\t\t\tcandidateCount: 0,\n\t\t\t\tsuiteFilter,\n\t\t\t\t...(degradedReason === undefined ? {} : { degraded: degradedReason }),\n\t\t\t};\n\t\t}\n\t\tconst egressOutcome = egressGate(candidates);\n\t\tif (egressOutcome.status === \"blocked\") return { kind: \"blocked\", reason: egressOutcome.reason };\n\t\tconst statementByMemoryId = new Map(egressOutcome.packet.facts.map((fact) => [fact.memoryId, fact.statement]));\n\t\tlet ordered: readonly ScoredRecallFactV1[] = candidates.map((entry) => ({\n\t\t\tmemoryId: entry.atom.memoryId,\n\t\t\tstatement: deps.unwrapEgressStatement(statementByMemoryId.get(entry.atom.memoryId) ?? \"\"),\n\t\t\tconfidence: entry.atom.confidence,\n\t\t\tposition: entry.position,\n\t\t}));\n\t\t// 精排 (仅主融合路径: 降级页的排序即其降级语义)。reranker 不可用或调用\n\t\t// 失败 → 保持 RRF 序并携带 degraded 标记; 调用失败不闩锁 (裁决 A: 下一次\n\t\t// 召回重试, 与组件层加载重试语义对齐), 每次失败记一条结构化日志。\n\t\tconst reranker = channel.reranker;\n\t\tif (!channelDegraded && reranker !== undefined) {\n\t\t\ttry {\n\t\t\t\tconst scores = await reranker.rerank(\n\t\t\t\t\tinput.query,\n\t\t\t\t\tordered.map((fact) => fact.statement),\n\t\t\t\t);\n\t\t\t\tordered = ordered\n\t\t\t\t\t.map((fact, position) => ({ ...fact, score: scores[position] }))\n\t\t\t\t\t.sort((left, right) => (right.score ?? 0) - (left.score ?? 0) || left.position - right.position);\n\t\t\t} catch (error) {\n\t\t\t\tdegradedReason ??= \"reranker failed; RRF order without rerank scores\";\n\t\t\t\tdeps.logger?.warn(\n\t\t\t\t\t\"memory reranker failed; recall serves the RRF order this round and retries the next recall\",\n\t\t\t\t\t{\n\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\t// minScore 门槛 (§2.1, 裁决 A 收紧): 仅精排实际产生 score 且过门槛的候选\n\t\t// 参与过滤后结果 (无 score 的候选一律丢弃, 不再放行); 过滤先于 limit 截取。\n\t\t// minScore 只经 auto-recall 内部闭包传入, auto-recall 另按 degraded 标记\n\t\t// 零注入, 双保险钉住\"注入 ⟹ 全部条目有分且过门槛\"。\n\t\tconst minScore = input.minScore;\n\t\tconst eligible =\n\t\t\tminScore === undefined\n\t\t\t\t? ordered\n\t\t\t\t: ordered.filter((fact) => fact.score !== undefined && fact.score >= minScore);\n\t\treturn {\n\t\t\tkind: \"served\",\n\t\t\tfacts: eligible\n\t\t\t\t.slice(0, input.limit)\n\t\t\t\t.map(({ memoryId, statement, confidence }) => ({ memoryId, statement, confidence })),\n\t\t\tcandidateCount: ordered.length,\n\t\t\tsuiteFilter,\n\t\t\t...(degradedReason === undefined ? {} : { degraded: degradedReason }),\n\t\t};\n\t};\n\n\t/**\n\t * Context-scoped preference post-processing over the recalled facts: preference\n\t * atoms compete per (subject, key); the resolver drops out-of-scope preferences\n\t * and deterministically ranks the rest, and an unconfirmed ranking goes through\n\t * the scope-specificity disambiguator. Whatever remains unresolvable is\n\t * returned as an explicit conflict block — the recall never silently picks\n\t * between competing stored values. Non-preference facts pass through untouched.\n\t */\n\tfunction applyPreferenceContext(input: {\n\t\treadonly facts: readonly MemoryFact[];\n\t\treadonly context: PreferenceContextV1;\n\t\treadonly resolver: PreferenceResolverV1;\n\t\treadonly disambiguator: PreferenceDisambiguatorV1;\n\t\treadonly atomOf: (memoryId: string) => MemoryAtomV1 | undefined;\n\t}): { readonly facts: readonly MemoryFact[]; readonly conflicts: readonly RecallConflictV1[] } {\n\t\tconst { facts, context, resolver, disambiguator, atomOf } = input;\n\t\tconst preferenceAtoms: MemoryAtomV1[] = [];\n\t\tconst atomsByGroup = new Map<string, MemoryAtomV1[]>();\n\t\tconst preferenceMemoryIds = new Set<string>();\n\t\tfor (const fact of facts) {\n\t\t\tconst atom = atomOf(fact.memoryId);\n\t\t\tif (atom === undefined || atom.memoryKind !== \"preference\" || atom.preference === undefined) continue;\n\t\t\tpreferenceMemoryIds.add(fact.memoryId);\n\t\t\tpreferenceAtoms.push(atom);\n\t\t\tconst groupKey = `${atom.preference.subject}\\u0000${atom.preference.key}`;\n\t\t\tconst group = atomsByGroup.get(groupKey) ?? [];\n\t\t\tgroup.push(atom);\n\t\t\tatomsByGroup.set(groupKey, group);\n\t\t}\n\t\tif (preferenceMemoryIds.size === 0) return { facts, conflicts: [] };\n\n\t\tconst keptMemoryIds = new Set<string>();\n\t\tconst conflicts: RecallConflictV1[] = [];\n\t\tfor (const decision of resolver.resolve(preferenceAtoms, context)) {\n\t\t\tconst groupAtoms = atomsByGroup.get(`${decision.subject}\\u0000${decision.key}`) ?? [];\n\t\t\tif (decision.status === \"applied\") {\n\t\t\t\tif (decision.winnerMemoryId === undefined) {\n\t\t\t\t\tthrow new Error(`applied preference decision without a winnerMemoryId: ${JSON.stringify(decision)}`);\n\t\t\t\t}\n\t\t\t\tkeptMemoryIds.add(decision.winnerMemoryId);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (decision.status === \"instruction_override\") {\n\t\t\t\t// No stored fact survives a current-instruction override (this slice has\n\t\t\t\t// no input source for currentInstructions, so the branch stays inert).\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (decision.status === \"conflict_unconfirmed\") {\n\t\t\t\tconst outcome = disambiguator.disambiguate(\n\t\t\t\t\tgroupAtoms.map((atom) => ({\n\t\t\t\t\t\tmemoryId: atom.memoryId,\n\t\t\t\t\t\tpreferredValue: atom.preference!.preferredValue,\n\t\t\t\t\t\tscope: atom.preference!.scope,\n\t\t\t\t\t\tevidenceClass: atom.preference!.evidence.class,\n\t\t\t\t\t\tapplicabilityConfidence: atom.preference!.applicabilityConfidence,\n\t\t\t\t\t})),\n\t\t\t\t\tcontext,\n\t\t\t\t);\n\t\t\t\tif (outcome.status === \"resolved\") {\n\t\t\t\t\tkeptMemoryIds.add(outcome.winnerMemoryId);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconflicts.push({\n\t\t\t\t\tsubject: decision.subject,\n\t\t\t\t\tkey: decision.key,\n\t\t\t\t\tcandidates: groupAtoms.map((atom) => {\n\t\t\t\t\t\tconst preference = atom.preference!;\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tmemoryId: atom.memoryId,\n\t\t\t\t\t\t\tstatement: deps.unwrapEgressStatement(deps.statementOf(atom.payload)),\n\t\t\t\t\t\t\tvalue: preference.preferredValue,\n\t\t\t\t\t\t\tevidenceClass: preference.evidence.class,\n\t\t\t\t\t\t\tconfidence: preference.applicabilityConfidence,\n\t\t\t\t\t\t};\n\t\t\t\t\t}),\n\t\t\t\t\texplanation: [...outcome.explanation],\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthrow new Error(`unexpected preference decision status: ${JSON.stringify(decision)}`);\n\t\t}\n\n\t\treturn {\n\t\t\tfacts: facts.filter((fact) => !preferenceMemoryIds.has(fact.memoryId) || keptMemoryIds.has(fact.memoryId)),\n\t\t\tconflicts,\n\t\t};\n\t}\n\n\t/**\n\t * Parses the optional recall context (scenes/projects/tasks) into a preference\n\t * resolution context. Returns undefined when absent so the no-context recall\n\t * path stays byte-identical to the pre-disambiguation behavior.\n\t */\n\tfunction parseRecallContext(value: unknown): PreferenceContextV1 | undefined {\n\t\tif (value === undefined) return undefined;\n\t\tif (!deps.isPlainObject(value)) throw new Error(\"context must be an object\");\n\t\tconst stringArray = (field: \"scenes\" | \"projects\" | \"tasks\"): readonly string[] | undefined => {\n\t\t\tconst entries: unknown = value[field];\n\t\t\tif (entries === undefined) return undefined;\n\t\t\tif (!Array.isArray(entries)) throw new Error(`context.${field} must be an array of strings`);\n\t\t\tfor (const entry of entries) {\n\t\t\t\tif (typeof entry !== \"string\") throw new Error(`context.${field} entries must be strings`);\n\t\t\t}\n\t\t\treturn entries;\n\t\t};\n\t\tconst scenes = stringArray(\"scenes\");\n\t\tconst projects = stringArray(\"projects\");\n\t\tconst tasks = stringArray(\"tasks\");\n\t\treturn {\n\t\t\t...(scenes === undefined ? {} : { scenes }),\n\t\t\t...(projects === undefined ? {} : { projects }),\n\t\t\t...(tasks === undefined ? {} : { tasks }),\n\t\t};\n\t}\n\n\t// 提取为具名闭包: 除模型工具面外, 下方的 auto-recall 钩子直接调用同一 execute\n\t// (单参输入约定, memoryToolInput 取第一参), 不经 runtime.invokeTool —— 钩子\n\t// 随插件注册/卸载, 与工具面同生命周期, 替换工具面不会重接自动召回。\n\tconst recallExecute = async (first: unknown, second?: unknown): Promise<unknown> => {\n\t\tconst input = deps.memoryToolInput(first, second);\n\t\tdeps.assertNonEmptyString(input.query, \"query\");\n\t\tconst rawLimit: unknown = input.limit;\n\t\tconst limit =\n\t\t\trawLimit === undefined\n\t\t\t\t? DEFAULT_RECALL_LIMIT\n\t\t\t\t: ((): number => {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\ttypeof rawLimit !== \"number\" ||\n\t\t\t\t\t\t\t!Number.isSafeInteger(rawLimit) ||\n\t\t\t\t\t\t\trawLimit < 1 ||\n\t\t\t\t\t\t\trawLimit > 100\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tthrow new Error(\"limit must be an integer between 1 and 100\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn rawLimit;\n\t\t\t\t\t})();\n\t\t// 内部执行缝 (§2.1): auto-recall 闭包经本字段恒传质量门槛; memory_recall\n\t\t// 工具 schema 不含该参数 (工具面恒 undefined), 显式召回行为不变。\n\t\tconst rawMinScore: unknown = input.minScore;\n\t\tconst minScore =\n\t\t\trawMinScore === undefined\n\t\t\t\t? undefined\n\t\t\t\t: ((): number => {\n\t\t\t\t\t\tif (typeof rawMinScore !== \"number\" || !Number.isFinite(rawMinScore)) {\n\t\t\t\t\t\t\tthrow new Error(\"minScore must be a finite number\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn rawMinScore;\n\t\t\t\t\t})();\n\t\tconst context = parseRecallContext(input.context);\n\t\tconst { domain } = deps.resolveDomain();\n\n\t\t// enabling 失败 = 本实例终态 (mode 记录回退 off): 记忆工具返回携带原因\n\t\t// 与五选一行动清单的不可用 packet (设计 §3.2 硬性要求), 不再重试。\n\t\tif (deps.rawState() === \"failed\") {\n\t\t\tconst failure = deps.failure() ?? { reason: \"memory enabling failed\", actions: [] as const };\n\t\t\treturn {\n\t\t\t\tstatus: \"unavailable\",\n\t\t\t\tstate: \"failed\",\n\t\t\t\tfacts: [] as MemoryFact[],\n\t\t\t\terror: `memory enabling failed: ${failure.reason}`,\n\t\t\t\tactions: failure.actions,\n\t\t\t};\n\t\t}\n\t\t// 征询门早退 (2026-10-05 用户裁决): 拒绝 = 本实例按模式关闭对待; 待征询 =\n\t\t// 返回带行动清单的 consent-required packet (后续 recall 不再反复探测文件)。\n\t\tif (deps.declined()) {\n\t\t\treturn {\n\t\t\t\tstatus: \"unavailable\",\n\t\t\t\tstate: \"off\",\n\t\t\t\tfacts: [] as MemoryFact[],\n\t\t\t\terror: \"memory was declined on this machine — set memory.mode (light|full) in settings.json and restart the session to re-enable\",\n\t\t\t\tactions: [] as const,\n\t\t\t};\n\t\t}\n\t\tconst consentAsk = deps.consentAsk();\n\t\tif (consentAsk !== undefined) {\n\t\t\treturn {\n\t\t\t\tstatus: \"unavailable\",\n\t\t\t\tstate: \"consent-required\",\n\t\t\t\tfacts: [] as MemoryFact[],\n\t\t\t\terror: consentAsk.message,\n\t\t\t\tactions: consentAsk.actions,\n\t\t\t};\n\t\t}\n\n\t\t// 主键快路径 (memoryIdEquals 语义保留, 幂等/引用而非检索): query 恰为本\n\t\t// 域可见 memoryId 时直接取该条, 不依赖向量通道 (enabling 期间也可用)。\n\t\tlet outcome: SemanticRecallOutcomeV1;\n\t\tconst directRecord = deps.store.get(input.query.trim(), {\n\t\t\towner: deps.owner,\n\t\t\t...(domain.kind === \"suite\" ? { suiteId: domain.suiteId } : {}),\n\t\t});\n\t\tif (directRecord !== undefined) {\n\t\t\tconst gate = egressGate([{ atom: directRecord.atom, position: 0 }]);\n\t\t\tif (gate.status === \"blocked\") {\n\t\t\t\treturn { status: \"failed\", facts: [] as MemoryFact[], error: `egress blocked: ${gate.reason}` };\n\t\t\t}\n\t\t\tconst statementByMemoryId = new Map(gate.packet.facts.map((fact) => [fact.memoryId, fact.statement]));\n\t\t\toutcome = {\n\t\t\t\tkind: \"served\",\n\t\t\t\tfacts: [\n\t\t\t\t\t{\n\t\t\t\t\t\tmemoryId: directRecord.atom.memoryId,\n\t\t\t\t\t\tstatement: deps.unwrapEgressStatement(statementByMemoryId.get(directRecord.atom.memoryId) ?? \"\"),\n\t\t\t\t\t\tconfidence: directRecord.atom.confidence,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tcandidateCount: 1,\n\t\t\t\tsuiteFilter: { legacySkipped: 0, foreignSuiteSkipped: 0 },\n\t\t\t\t// 裁决 A 缝隙收口 (2026-10-05 复审后用户裁决「修复」): 直查是引用\n\t\t\t\t// 语义、未经精排 — 显式召回如实带标记, auto-recall 见标记零注入\n\t\t\t\t// (此前用户消息恰为 memoryId 时会绕过质量门注入该条)。\n\t\t\t\tdegraded: \"primary-key direct lookup (reference semantics, not reranked)\",\n\t\t\t};\n\t\t} else {\n\t\t\ttry {\n\t\t\t\toutcome = await recallSemantically({\n\t\t\t\t\tquery: input.query,\n\t\t\t\t\tdomain,\n\t\t\t\t\tlimit,\n\t\t\t\t\t...(minScore === undefined ? {} : { minScore }),\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\t// 意外异常 (管线 throw) → degraded packet: 结构化返回, 不抛给模型。\n\t\t\t\tdeps.markDegraded();\n\t\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\t\tdeps.logger?.warn(\"memory recall degraded: the recall pipeline threw; returning a degraded packet\", {\n\t\t\t\t\terror: message,\n\t\t\t\t});\n\t\t\t\treturn { status: \"failed\", facts: [] as MemoryFact[], error: message };\n\t\t\t}\n\t\t}\n\t\tif (outcome.kind === \"blocked\") {\n\t\t\treturn { status: \"failed\", facts: [] as MemoryFact[], error: `egress blocked: ${outcome.reason}` };\n\t\t}\n\t\tif (outcome.kind === \"unavailable\") {\n\t\t\t// 首次调用即在装配中途失败时, vectorState 在本调用内才翻成 failed —\n\t\t\t// 这里同样必须携带 enabling 失败的原因 + 行动清单 (设计 §3.2 硬性\n\t\t\t// 要求: 终态的第一份可见 packet 就是完整的), 不等下一次调用补。\n\t\t\t// (vectorState 是可变闭包状态, 语义检索内部会改写它, 入口预检的\n\t\t\t// 收窄在此处不成立 — 经函数边界读取以如实表达。)\n\t\t\tconst stateAtEgress = (): MemoryCapabilityStateV1 => deps.rawState();\n\t\t\tconst failureAtEgress = deps.failure();\n\t\t\tconst consentAskAtEgress = deps.consentAsk();\n\t\t\tif (stateAtEgress() === \"failed\" && failureAtEgress !== undefined) {\n\t\t\t\treturn {\n\t\t\t\t\tstatus: \"unavailable\",\n\t\t\t\t\tstate: \"failed\",\n\t\t\t\t\tfacts: [] as MemoryFact[],\n\t\t\t\t\terror: `memory enabling failed: ${failureAtEgress.reason}`,\n\t\t\t\t\tactions: failureAtEgress.actions,\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tstatus: \"unavailable\",\n\t\t\t\tstate: stateAtEgress(),\n\t\t\t\tfacts: [] as MemoryFact[],\n\t\t\t\terror: outcome.message,\n\t\t\t\t...(stateAtEgress() === \"consent-required\" && consentAskAtEgress !== undefined\n\t\t\t\t\t? { actions: consentAskAtEgress.actions }\n\t\t\t\t\t: {}),\n\t\t\t};\n\t\t}\n\t\tconst facts = outcome.facts;\n\t\t// 增强段 (偏好消歧 + 关系扩散) 是增量元数据面: 内部抛错不得砸穿工具面\n\t\t// (结构化失败契约), 也不吞掉整个召回 — 降级为基础事实 + 一条结构化 warn。\n\t\tconst { finalFacts, resolvedConflicts, related, relatedOmittedCount } = await (async () => {\n\t\t\ttry {\n\t\t\t\tconst resolved =\n\t\t\t\t\tcontext === undefined\n\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t: applyPreferenceContext({\n\t\t\t\t\t\t\t\tfacts,\n\t\t\t\t\t\t\t\tcontext,\n\t\t\t\t\t\t\t\tresolver: deps.preferenceResolver,\n\t\t\t\t\t\t\t\tdisambiguator: deps.preferenceDisambiguator,\n\t\t\t\t\t\t\t\tatomOf: (memoryId) => deps.store.get(memoryId, { owner: deps.owner })?.atom,\n\t\t\t\t\t\t\t});\n\t\t\t\t// 偏好消歧先于关系扩散: the diffusion seeds are the atoms the user\n\t\t\t\t// actually sees — preference facts dropped by the conflict resolution\n\t\t\t\t// never diffuse their relations.\n\t\t\t\tconst baseFacts = resolved === undefined ? facts : resolved.facts;\n\t\t\t\tconst seeds: MemoryAtomV1[] = [];\n\t\t\t\tfor (const fact of baseFacts) {\n\t\t\t\t\tconst atom = deps.store.get(fact.memoryId, { owner: deps.owner })?.atom;\n\t\t\t\t\tif (atom !== undefined) seeds.push(atom);\n\t\t\t\t}\n\t\t\t\t// The traversal graph is the recall domain's visible atom set (same\n\t\t\t\t// suite read boundary). Diffusion targets outside this set are dropped,\n\t\t\t\t// so relations never leak across suites.\n\t\t\t\tconst domainMemoryIds = new Set<string>();\n\t\t\t\tconst graph: MemoryAtomV1[] = [];\n\t\t\t\tfor (const entry of listDomainMemories({ store: deps.store }, { owner: deps.owner, domain }).entries) {\n\t\t\t\t\tdomainMemoryIds.add(entry.memoryId);\n\t\t\t\t\tconst atom = deps.store.get(entry.memoryId, { owner: deps.owner })?.atom;\n\t\t\t\t\tif (atom !== undefined) graph.push(atom);\n\t\t\t\t}\n\t\t\t\tconst related: MemoryNetworkExpansionV1[] = [];\n\t\t\t\tlet relatedOmittedCount = 0;\n\t\t\t\tconst seenRelatedMemoryIds = new Set<string>();\n\t\t\t\tfor (const adapterResult of deps.memoryNetwork.expand({ seeds, graph })) {\n\t\t\t\t\tif (adapterResult.status !== \"completed\") continue;\n\t\t\t\t\tfor (const expansion of adapterResult.related) {\n\t\t\t\t\t\tif (!domainMemoryIds.has(expansion.memoryId)) continue;\n\t\t\t\t\t\tif (seenRelatedMemoryIds.has(expansion.memoryId)) continue;\n\t\t\t\t\t\tseenRelatedMemoryIds.add(expansion.memoryId);\n\t\t\t\t\t\tif (related.length >= MAX_RELATED_REFS) {\n\t\t\t\t\t\t\trelatedOmittedCount += 1;\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\trelated.push(expansion);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tfinalFacts: baseFacts,\n\t\t\t\t\tresolvedConflicts: resolved === undefined ? [] : resolved.conflicts,\n\t\t\t\t\trelated,\n\t\t\t\t\trelatedOmittedCount,\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\tdeps.logger?.warn(\n\t\t\t\t\t\"memory recall enhancement failed; serving the base facts without preference resolution and related references\",\n\t\t\t\t\t{ error: error instanceof Error ? error.message : String(error) },\n\t\t\t\t);\n\t\t\t\treturn {\n\t\t\t\t\tfinalFacts: facts,\n\t\t\t\t\tresolvedConflicts: [],\n\t\t\t\t\trelated: [] as MemoryNetworkExpansionV1[],\n\t\t\t\t\trelatedOmittedCount: 0,\n\t\t\t\t};\n\t\t\t}\n\t\t})();\n\t\treturn {\n\t\t\tstatus: finalFacts.length === 0 ? \"empty\" : \"completed\",\n\t\t\tfacts: finalFacts,\n\t\t\t// Domain visibility (P4): an empty result must not read as \"no memories\"\n\t\t\t// when the session fell back to the isolated legacy domain.\n\t\t\tdomain: domain.kind === \"suite\" ? domain.suiteId : \"legacy\",\n\t\t\t...(domain.kind === \"legacy\"\n\t\t\t\t? {\n\t\t\t\t\t\twarning:\n\t\t\t\t\t\t\t\"this session has no suite binding on its current branch; memory is using the isolated legacy domain (suite memories are not visible)\",\n\t\t\t\t\t}\n\t\t\t\t: {}),\n\t\t\t...(outcome.degraded === undefined ? {} : { degraded: outcome.degraded }),\n\t\t\t...(resolvedConflicts.length > 0 ? { conflicts: resolvedConflicts } : {}),\n\t\t\t...(domain.kind === \"suite\" ? { suiteFilter: outcome.suiteFilter } : {}),\n\t\t\tomittedCount: Math.max(0, outcome.candidateCount - finalFacts.length),\n\t\t\ttruncated: false,\n\t\t\t// References only — no statement/payload egress; the model fetches\n\t\t\t// content via memory_list or another memory_recall.\n\t\t\t...(related.length > 0\n\t\t\t\t? {\n\t\t\t\t\t\trelated: related.map((expansion) => ({\n\t\t\t\t\t\t\tmemoryId: expansion.memoryId,\n\t\t\t\t\t\t\trelationKind: expansion.relationKind,\n\t\t\t\t\t\t\thop: expansion.hop,\n\t\t\t\t\t\t\tweight: expansion.weight,\n\t\t\t\t\t\t\tvia: expansion.via,\n\t\t\t\t\t\t})),\n\t\t\t\t\t}\n\t\t\t\t: {}),\n\t\t\t...(relatedOmittedCount > 0 ? { relatedOmittedCount } : {}),\n\t\t};\n\t};\n\tconst recallTool = deps.registerTool({\n\t\tname: MEMORY_RECALL_TOOL_NAME,\n\t\tlabel: \"Recall memories\",\n\t\tpromptGuidelines: [MEMORY_TOOLS_GUIDE],\n\t\tdescription:\n\t\t\t\"Search this suite's durable memories with semantic recall: vector and full-text channels fuse (RRF) and the result is reranked; an exact memoryId retrieves that memory directly; the result may include related memory references (ids and relation metadata only — recall or list a referenced memory again for its content)\",\n\t\tparameters: recallSchema,\n\t\texecute: recallExecute,\n\t});\n\n\treturn { recallTool, recallExecute };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vector-channel.d.ts","sourceRoot":"","sources":["../../src/memory/vector-channel.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * 向量通道状态机(capability 拆分战役 slice 3b):vectorEnsure 状态转换、装配分支(服务/本地/下载/征询门)、dispose 闩锁。共享闭包状态收拢为 channel 对象, 经 deps 显式注入; 降级/投影经 slice 3a 的 vector-projection 上报\n */\n\nimport { join } from \"node:path\";\nimport type {\n\tCapabilityAPI,\n\tMemoryEnablingOverrideV1,\n\tMemoryVectorComponentsOverrideV1,\n} from \"@agent-forge/plugin-sdk\";\nimport {\n\tDISK_HEADROOM_MIN_BYTES,\n\tdiskHeadroomCheck,\n\tenablingActionList,\n\tMODEL_MIN_WEIGHT_BYTES,\n\tmissingHeavyDependencyModules,\n\tmodelFilesCheck,\n\tnativeBinaryCheck,\n\tnormalizeMemoryAgentDirIdentity,\n\tRERANKER_MIN_WEIGHT_BYTES,\n\tremoteHostsForEnabling,\n\tresolveHeavyDependencyEntryPath,\n\tvectorPresetForMode,\n\twriteMemoryConsentDeclined,\n} from \"./enabling.ts\";\nimport { ensureInferenceServiceChannel, serviceFailureActionList } from \"./inference-channel.ts\";\nimport { type MemoryInferenceClientV1, resolveMemoryInferencePort } from \"./inference-client.ts\";\nimport { MEMORY_INFERENCE_DEFAULT_PORT, MEMORY_INFERENCE_PORT_ENV } from \"./inference-protocol.ts\";\nimport type { ActiveVectorChannelV1 } from \"./vector-projection.ts\";\n\n/** enabling 加载/下载期间的周期性进度日志间隔。 */\nconst ENABLING_PROGRESS_LOG_INTERVAL_MS = 15_000;\n\n// 宿主先撤销 CapabilityAPI 再调用 disposer。清理诊断不得依赖已撤销的 logger,\n// 也不得因诊断输出失败而中断其他资源释放或替换原始装配错误。\nfunction reportCleanupFailure(resource: string, error: unknown): void {\n\ttry {\n\t\tconsole.error(`memory ${resource} close failed`, error);\n\t} catch {\n\t\t// 诊断接收端不可用不改变资源生命周期。\n\t}\n}\n\nfunction closeResource(resource: string, close: () => unknown): Promise<void> {\n\treturn Promise.resolve()\n\t\t.then(close)\n\t\t.then(() => undefined)\n\t\t.catch((error: unknown) => reportCleanupFailure(resource, error));\n}\n\n/** 两档共用精排模型 (POC 报告 §8: 官方 Xenova 转换版唯一实测可用)。 */\nexport const VECTOR_RERANKER_MODEL_ID = \"Xenova/bge-reranker-base\";\nexport const VECTOR_DB_DIRNAME = \"vector\";\nexport const VECTOR_MODEL_CACHE_DIRNAME = \"model-cache\";\n\n/** capability 级状态机 (设计 §3.2): off 只出现在模式关闭 (零注册, 不可观测)。 */\nexport type MemoryCapabilityStateV1 = \"consent-required\" | \"enabling\" | \"ready\" | \"degraded\" | \"failed\";\n\n/** enabling 失败的结构化结果: 原因 + 行动清单 (硬性要求, 设计 §3.2)。 */\nexport interface MemoryEnablingFailureV1 {\n\treadonly reason: string;\n\treadonly actions: readonly string[];\n}\n\n/**\n * 征询门待决信息 (2026-10-05 用户裁决「首次使用征询、拒绝即持久化关闭」):\n * 向量通道从未就绪且模式已启用时, 模型下载必须先经用户同意——检索不触发下载,\n * 由 AI 转述征询后经 memory_enable 工具面继续。\n */\nexport interface MemoryConsentNeededV1 {\n\treadonly models: readonly string[];\n\t/** 模型权重体积下限之和 (非精确体积; 实际下载量以镜像文件为准)。 */\n\treadonly approximateBytes: number;\n}\n\n/** 征询面 (consent-required 态的模型可见包): AI 转述话术 + 后续动作 + 注入块。 */\nexport interface MemoryConsentAskV1 {\n\treadonly message: string;\n\treadonly actions: readonly string[];\n\treadonly block: string;\n}\n\n/**\n * 向量通道对 capability 装配上下文的显式依赖视图 (slice 3b): 逐项来自\n * createMemoryCapabilityHarness 的闭包捕获核实, 不再经共享闭包隐式可达。\n */\nexport interface MemoryVectorChannelDepsV1 {\n\t/** agent 根目录 (MemoryCapabilityContext.agentDir): 模型缓存/索引/征询持久化的路径域。 */\n\treadonly agentDir: string;\n\t/** 已解析的全局档位 (harness memoryMode, off 已被工厂入口拦截)。 */\n\treadonly memoryMode: \"light\" | \"full\";\n\t/** capability 日志面 (api.logger): 进度/失败/自愈日志。 */\n\treadonly logger: CapabilityAPI[\"logger\"];\n\t/** 宿主注入的 onnxruntime-node 入口 (MemoryCapabilityContext.hostOnnxRuntimeEntryPath)。 */\n\treadonly hostOnnxRuntimeEntryPath?: string;\n\t/** 宿主注入的 @lancedb/lancedb 入口 (MemoryCapabilityContext.hostLancedbEntryPath)。 */\n\treadonly hostLancedbEntryPath?: string;\n\t/** 宿主注入的 @huggingface/transformers 入口 (MemoryCapabilityContext.hostTransformersEntryPath)。 */\n\treadonly hostTransformersEntryPath?: string;\n\t/** 服务装配缝 (Slice B2): 测试端口直连 (MemoryCapabilityContext.inferenceService.port)。 */\n\treadonly inferenceServicePort?: number;\n\t/** 服务装配缝 (Slice B2): 替换进程拉起的测试缝 (inferenceService.spawnImpl)。 */\n\treadonly inferenceServiceSpawnImpl?: (\n\t\tagentDir: string,\n\t\tmode: \"light\" | \"full\",\n\t\tport: number,\n\t\t/** spawn 异步失败 (EACCES/ENOMEM 等) 的回调; 缺省实现经 child 'error' 事件馈入。 */\n\t\tonError?: (error: Error) => void,\n\t) => Promise<void>;\n\t/** 服务装配缝 (Slice B2): 声明模型在位, 文件检查与征询门让位 (inferenceService.modelsInPlace)。 */\n\treadonly inferenceServiceModelsInPlace?: boolean;\n\t/** enabling 测试缝 (loadImpl 重定向模型加载); undefined = 生产路径。 */\n\treadonly enablingOverride?: MemoryEnablingOverrideV1;\n\t/** 组件注入 (deterministic mock 门禁): 存在时通道直接 ready, 跳过真实装配。 */\n\treadonly injectedComponents?: MemoryVectorComponentsOverrideV1;\n\t/** 写侧投影 (slice 3a 的 vectorProjection.resetReconcile): downloadMemory 就绪后重臂启动对账。 */\n\treadonly resetReconcile: () => void;\n\t/** 写侧投影 (slice 3a 的 vectorProjection.reconcileOnce): downloadMemory 就绪后补跑对账。 */\n\treadonly reconcileOnce: () => void;\n}\n\nexport interface MemoryVectorChannelV1 {\n\t/** harness.vectorState 面: 征询拒绝时投影为 \"off\" (本实例按模式关闭对待)。 */\n\tstate(): \"off\" | MemoryCapabilityStateV1;\n\t/** vectorState 原值 (未做 declined 投影; recall/合并探测等内部消费)。 */\n\trawState(): MemoryCapabilityStateV1;\n\t/** vectorEnabled: failed/consent-required/declined 时 false (写侧埋点门)。 */\n\tenabled(): boolean;\n\t/** 已就绪通道的同步快照 (vectorChannel 只读; projection.readyChannel 面)。 */\n\treadyChannel(): ActiveVectorChannelV1 | undefined;\n\t/** dispose 闩锁只读视图 (capabilityDisposed; projection.isDisposed 面)。 */\n\tisDisposed(): boolean;\n\t/** 征询拒绝标记 (declineMemory 持久化后的本实例内存面)。 */\n\tdeclined(): boolean;\n\t/** 用户显式再启用 (/memory light|full、自动升档) 清除本实例拒绝标记。 */\n\tclearDeclined(): void;\n\t/** 征询一次性注入钉住标记 (auto-recall 每实例只注入一次)。 */\n\tconsentAsked(): boolean;\n\tmarkConsentAsked(): void;\n\t/** 无副作用征询探测 (auto-recall 首轮; 纯本地 stat, 绝不触发下载/加载)。 */\n\tprimeConsentGate(): void;\n\t/** 征询待决面 (consent-required 且待决信息就位时非 undefined; 纯只读, 不探测)。 */\n\tconsentAsk(): MemoryConsentAskV1 | undefined;\n\t/** warming 守卫 (recall 后台预热不阻塞读侧): 装配在途且未拒绝。 */\n\twarming(): boolean;\n\t/** enabling 失败结构化结果 (未失败 = undefined)。 */\n\tfailure(): MemoryEnablingFailureV1 | undefined;\n\t/** 运行期故障 → degraded (可自愈; recall 与投影对账共用)。 */\n\tmarkDegraded(): void;\n\t/** degraded → ready 的自愈转换 (仅从 degraded; 全通 recall 成功后调用)。 */\n\trecoverDegraded(): void;\n\t/** vectorEnsure: 惰性单飞装配 (recall/write/埋点/对账的公共入口)。 */\n\tensure(): Promise<ActiveVectorChannelV1 | undefined>;\n\t/** harness.enablingOutcome 面: 触发惰性 enabling 并等待落定 (ready 或结构化失败)。 */\n\tenablingOutcome(): Promise<\"ready\" | MemoryEnablingFailureV1>;\n\t/** declineMemory 核心: 持久化拒绝 + 本实例按模式关闭。 */\n\tdecline(): { status: \"completed\"; message: string };\n\t/** downloadMemory 核心: 置征询同意 + 装配 + 补跑启动对账。 */\n\tdownload(): Promise<\n\t\t| { status: \"completed\"; message: string }\n\t\t| { status: \"failed\"; message: string; actions?: readonly string[]; next?: string }\n\t>;\n\t/** capabilityTeardown 本体: 资源关闭 + 闩锁置位 (幂等)。 */\n\tdispose(): void;\n}\n\nexport function createMemoryVectorChannel(deps: MemoryVectorChannelDepsV1): MemoryVectorChannelV1 {\n\tconst {\n\t\tagentDir,\n\t\tmemoryMode,\n\t\tlogger,\n\t\thostOnnxRuntimeEntryPath,\n\t\thostLancedbEntryPath,\n\t\thostTransformersEntryPath,\n\t\tinferenceServicePort,\n\t\tinferenceServiceSpawnImpl,\n\t\tinferenceServiceModelsInPlace,\n\t\tenablingOverride,\n\t\tinjectedComponents,\n\t\tresetReconcile,\n\t\treconcileOnce,\n\t} = deps;\n\t// ---- 语义召回通道 (2.4d6 S1/S2; 召回唯一检索路径) ----\n\t// 状态机 (设计 §3.2): enabling = 检查/加载进行中 (惰性触发: 首次向量操作\n\t// 时真正执行); ready = 可用; degraded = ready 后运行期故障 (可自愈回\n\t// ready); failed = enabling 失败, 本实例内终态 (mode 回退 off, 记忆工具\n\t// 返回携带行动清单的不可用 packet, 不再重试)。所有写侧操作经 vectorQueue\n\t// 串行化, 避免 reconcile 与写入埋点在 LanceDB 建表上竞态; recall 等待\n\t// enabling 单飞完成, 不与后台对账并发读索引。transformers/lancedb 的动态\n\t// import 只出现在 vectorEnsure 的装配分支里 (type-position 引类型), 未\n\t// 触发时不加载任何重依赖。\n\tlet vectorState: MemoryCapabilityStateV1 = \"enabling\";\n\tlet vectorChannel: ActiveVectorChannelV1 | undefined;\n\tlet enablingFailure: MemoryEnablingFailureV1 | undefined;\n\tlet enablingSettled: (() => void) | undefined;\n\t// 征询门 (2026-10-05 用户裁决「首次使用征询、拒绝即持久化关闭」): 模型文件\n\t// 缺失时下载必须先经用户同意——consentGranted 只由 memory_enable 工具面置位;\n\t// consentDeclined = 本实例内用户拒绝/跳过 (同时持久化, 见\n\t// writeMemoryConsentDeclined), 之后本实例按模式关闭对待; consentAsked 钉住\n\t// 自动召回的一次性征询注入, 不随查询文本翻新。\n\tlet consentGranted = false;\n\tlet consentDeclined = false;\n\tlet consentAsked = false;\n\tlet consentNeededInfo: MemoryConsentNeededV1 | undefined;\n\tconst enablingSettledPromise = new Promise<\"ready\" | MemoryEnablingFailureV1>((resolve) => {\n\t\tenablingSettled = () => resolve(enablingFailure ?? \"ready\");\n\t});\n\tif (injectedComponents !== undefined) {\n\t\t// 测试注入: 直接 ready, 跳过真实装配与档位解析。\n\t\tvectorState = \"ready\";\n\t\tvectorChannel = {\n\t\t\tembed: injectedComponents.embedProvider,\n\t\t\treranker: injectedComponents.reranker,\n\t\t\tindex: injectedComponents.vectorIndex,\n\t\t\tqueryPrefix: injectedComponents.queryPrefix ?? \"\",\n\t\t\tembeddingModelId: injectedComponents.embedProvider.modelId,\n\t\t};\n\t\tenablingSettled?.();\n\t}\n\tconst vectorEnabled = (): boolean =>\n\t\tvectorState !== \"failed\" && vectorState !== \"consent-required\" && !consentDeclined;\n\t// 尚未发布的本地资源也归本实例拥有;teardown 立即标记 provider 关闭。\n\tlet closeOwnedLocalResources: (() => Promise<void>) | undefined;\n\tconst closeLocalChannel = async (channel: ActiveVectorChannelV1): Promise<void> => {\n\t\tconst results = await Promise.allSettled([\n\t\t\tPromise.resolve().then(() => channel.index.close()),\n\t\t\t(async () => channel.embed.dispose?.())(),\n\t\t\t(async () => channel.reranker?.dispose?.())(),\n\t\t]);\n\t\tconst resources = [\"vector index\", \"embedding provider\", \"reranker\"];\n\t\tfor (const [index, result] of results.entries()) {\n\t\t\tif (result.status === \"rejected\") reportCleanupFailure(resources[index]!, result.reason);\n\t\t}\n\t};\n\t// 征询话术 (AI 转述给用户; 会话语言由 AI 决定): 模型清单 + 体积下限 + 两个\n\t// 后续动作。consent-required 态下的 recall packet、auto-recall 注入块共用。\n\tconst consentAskMessage = (): string => {\n\t\tconst info = consentNeededInfo;\n\t\tconst models = info === undefined ? \"embedding + reranker\" : info.models.join(\" + \");\n\t\tconst floorMb = Math.ceil(\n\t\t\t(info?.approximateBytes ?? MODEL_MIN_WEIGHT_BYTES[memoryMode] + RERANKER_MIN_WEIGHT_BYTES) / (1024 * 1024),\n\t\t);\n\t\treturn (\n\t\t\t`memory needs a one-time model download (${models}, at least ${floorMb} MB total; ` +\n\t\t\t\"actual sizes come from the mirror) into <agentDir>/memory/model-cache before recall can run — \" +\n\t\t\t\"nothing downloads without user consent\"\n\t\t);\n\t};\n\tconst consentAskActions = (): readonly string[] => [\n\t\t\"Ask the user whether to download the memory models now\",\n\t\t'With consent, call memory_enable with action \"download\"',\n\t\t'If the user declines, call memory_enable with action \"decline\" (persists memory off; set memory.mode in settings.json later to re-enable)',\n\t];\n\tconst consentAskBlock = (): string =>\n\t\t[\n\t\t\t\"<memory_setup>\",\n\t\t\tconsentAskMessage(),\n\t\t\t\"Ask the user (in the conversation language) whether to download now; relay that it is one-time and the size.\",\n\t\t\t...consentAskActions()\n\t\t\t\t.slice(1)\n\t\t\t\t.map((line) => `- ${line}`),\n\t\t\t\"</memory_setup>\",\n\t\t].join(\"\\n\");\n\t// 无副作用探测: 初始态是 enabling, 而征询态只在 vectorEnsure 探测后落定——\n\t// 自动召回钩子首轮就要给出征询注入, 这里只做模型文件存在性检查 (纯本地\n\t// stat), 缺失即落定 consent-required, 绝不触发下载/加载。\n\tconst primeConsentGate = (): void => {\n\t\tif (consentGranted || consentDeclined || vectorState !== \"enabling\") return;\n\t\tif (\n\t\t\tenablingOverride?.embeddingLoadImpl !== undefined ||\n\t\t\tenablingOverride?.rerankerLoadImpl !== undefined ||\n\t\t\t// 服务装配缝的模型声明 (Slice B2): 与 vectorEnsure 装配分支同一豁免 —\n\t\t\t// 声明在位时文件检查让位, 征询门不应被 auto-recall 钩子提前翻起。\n\t\t\tinferenceServiceModelsInPlace === true\n\t\t) {\n\t\t\treturn;\n\t\t}\n\t\tconst preset = vectorPresetForMode(memoryMode);\n\t\tconst modelCacheDir = join(agentDir, \"memory\", VECTOR_MODEL_CACHE_DIRNAME);\n\t\tconst modelsMissing =\n\t\t\tmodelFilesCheck(modelCacheDir, preset.embeddingModelId, MODEL_MIN_WEIGHT_BYTES[memoryMode]) === \"missing\" ||\n\t\t\tmodelFilesCheck(modelCacheDir, VECTOR_RERANKER_MODEL_ID, RERANKER_MIN_WEIGHT_BYTES) === \"missing\";\n\t\tif (!modelsMissing) return;\n\t\tvectorState = \"consent-required\";\n\t\tconsentNeededInfo = {\n\t\t\tmodels: [\n\t\t\t\tpreset.embeddingModelId,\n\t\t\t\t...(modelFilesCheck(modelCacheDir, VECTOR_RERANKER_MODEL_ID, RERANKER_MIN_WEIGHT_BYTES) === \"missing\"\n\t\t\t\t\t? [VECTOR_RERANKER_MODEL_ID]\n\t\t\t\t\t: []),\n\t\t\t],\n\t\t\tapproximateBytes: MODEL_MIN_WEIGHT_BYTES[memoryMode] + RERANKER_MIN_WEIGHT_BYTES,\n\t\t};\n\t};\n\tlet vectorInitPromise: Promise<ActiveVectorChannelV1 | undefined> | undefined;\n\n\t/**\n\t * 开启状态机 (设计 §3.2, 惰性单飞): 本地检查 (native .node 可解析 → 重依赖\n\t * 供给 (lancedb/transformers: 宿主入口路径或插件位置自解析) → 模型文件存在\n\t * 与大小 → 磁盘余量) → transformers 加载 (自带下载, 进度周期性\n\t * 落一行日志) → 冒烟 (embed 一条 + getStoredModelId 与档位比对) → ready。\n\t * 任一步失败 → failed (原因 + 五选一行动清单), mode 记录回退 off, 本实例\n\t * 不再重试。\n\t */\n\t/** 服务模式持有的 IPC 客户端 (断连自愈检测用; 本地装配路径恒 undefined)。 */\n\tlet inferenceClient: MemoryInferenceClientV1 | undefined;\n\n\tconst vectorEnsure = (): Promise<ActiveVectorChannelV1 | undefined> => {\n\t\tif (capabilityDisposed) {\n\t\t\tvectorState = \"failed\";\n\t\t\tenablingFailure ??= { reason: \"capability disposed during enabling\", actions: [] };\n\t\t\tenablingSettled?.();\n\t\t\treturn Promise.resolve(undefined);\n\t\t}\n\t\tif (vectorState === \"ready\" || vectorState === \"degraded\") {\n\t\t\t// 服务模式断连自愈 (Slice B2): 缓存 channel 背后的 IPC 客户端死亡时\n\t\t\t// 清缓存重走装配 (重连 + 必要时重拉起服务), 而不是拿着死连接报错。\n\t\t\tif (inferenceClient === undefined || inferenceClient.isAlive()) return Promise.resolve(vectorChannel);\n\t\t\tlogger?.warn(\"memory inference service connection lost; reconnecting\");\n\t\t\tinferenceClient = undefined;\n\t\t\tvectorChannel = undefined;\n\t\t\tvectorState = \"enabling\";\n\t\t\tvectorInitPromise = undefined;\n\t\t}\n\t\tif (vectorState === \"failed\") return Promise.resolve(undefined);\n\t\tif (vectorInitPromise !== undefined) return vectorInitPromise;\n\t\tvectorInitPromise = (async (): Promise<ActiveVectorChannelV1 | undefined> => {\n\t\t\tconst preset = vectorPresetForMode(memoryMode);\n\t\t\tconst modelCacheDir = join(agentDir, \"memory\", VECTOR_MODEL_CACHE_DIRNAME);\n\t\t\tconst failEnabling = (\n\t\t\t\treason: string,\n\t\t\t\tactions: readonly string[] = enablingActionList(modelCacheDir, memoryMode),\n\t\t\t): undefined => {\n\t\t\t\tvectorState = \"failed\";\n\t\t\t\tenablingFailure = { reason, actions };\n\t\t\t\tvectorInitPromise = undefined;\n\t\t\t\tenablingSettled?.();\n\t\t\t\tif (!capabilityDisposed)\n\t\t\t\t\tlogger?.warn(`memory enabling failed: ${reason} — actions: ${enablingFailure.actions.join(\" | \")}`, {\n\t\t\t\t\t\tmode: memoryMode,\n\t\t\t\t\t});\n\t\t\t\treturn undefined;\n\t\t\t};\n\t\t\t// dispose 竞态守卫 (2026-10-06 复审遗留): teardown 与在途 enabling 竞态\n\t\t\t// 时, 装配完成点必须让位——不得把新连接/索引句柄赋回已清空的引用 (那会\n\t\t\t// 复活一条无人关闭的连接: 服务端 connections>0 抑制空闲自杀、挂住嵌入\n\t\t\t// 进程事件循环), 也不得让 enablingOutcome() 等待者悬挂。改为关闭刚取得\n\t\t\t// 的资源并落结构化 failed (MemoryEnablingFailureV1 形状)。\n\t\t\tconst failEnablingDisposed = (closeAcquired?: () => Promise<unknown>): undefined => {\n\t\t\t\tvectorState = \"failed\";\n\t\t\t\tenablingFailure = { reason: \"capability disposed during enabling\", actions: [] };\n\t\t\t\tvectorInitPromise = undefined;\n\t\t\t\tenablingSettled?.();\n\t\t\t\tif (closeAcquired !== undefined) void closeResource(\"inference client\", closeAcquired);\n\t\t\t\treturn undefined;\n\t\t\t};\n\t\t\tlogger?.info(`memory enabling started (mode=${memoryMode}, embedding=${preset.embeddingModelId})`);\n\t\t\t// 检查 1: native .node sidecar (纯本地, 零网络)。宿主注入路径优先\n\t\t\t// (安装店副本自解析不可达, 见 MemoryCapabilityContext.hostOnnxRuntimeEntryPath)。\n\t\t\tconst nativeProblem = nativeBinaryCheck(hostOnnxRuntimeEntryPath);\n\t\t\tif (nativeProblem !== undefined) return failEnabling(nativeProblem);\n\t\t\t// 检查 1b: 重依赖供给。宿主入口路径优先; 未提供时插件位置自解析,\n\t\t\t// 两者都不可达 = 原本要到加载步才以 \"Cannot find module\" 泛化包装\n\t\t\t// 失败的根因, 前置到模型下载之前以 onnx 缺供分支同构的精准文案报告。\n\t\t\t// 路径已提供但包损坏的真实失败仍走加载步, 由泛化包装保留原始错误。\n\t\t\tconst missingHeavyDependencies = missingHeavyDependencyModules(\n\t\t\t\t{ lancedb: hostLancedbEntryPath, transformers: hostTransformersEntryPath },\n\t\t\t\tresolveHeavyDependencyEntryPath,\n\t\t\t);\n\t\t\tif (missingHeavyDependencies.length > 0) {\n\t\t\t\treturn failEnabling(\n\t\t\t\t\t`${missingHeavyDependencies.join(\", \")} are not provided by the host installation and could not be resolved from the plugin location; to enable memory features, install them in the host project (npm i ${missingHeavyDependencies.join(\" \")}) and restart the session`,\n\t\t\t\t);\n\t\t\t}\n\t\t\t// 检查 2: 模型文件 (缺失 = 进入下载; 存在但截断 = 失败提示手动导入)。\n\t\t\tconst embeddingProblem = modelFilesCheck(\n\t\t\t\tmodelCacheDir,\n\t\t\t\tpreset.embeddingModelId,\n\t\t\t\tMODEL_MIN_WEIGHT_BYTES[memoryMode],\n\t\t\t);\n\t\t\tconst rerankerProblem = modelFilesCheck(modelCacheDir, VECTOR_RERANKER_MODEL_ID, RERANKER_MIN_WEIGHT_BYTES);\n\t\t\tconst modelsMissing =\n\t\t\t\tembeddingProblem === \"missing\" || rerankerProblem === \"missing\"\n\t\t\t\t\t? `${preset.embeddingModelId}${rerankerProblem === \"missing\" ? ` + ${VECTOR_RERANKER_MODEL_ID}` : \"\"}`\n\t\t\t\t\t: undefined;\n\t\t\tif (embeddingProblem !== undefined && embeddingProblem !== \"missing\") return failEnabling(embeddingProblem);\n\t\t\tif (rerankerProblem !== undefined && rerankerProblem !== \"missing\") return failEnabling(rerankerProblem);\n\t\t\t// 征询门 (2026-10-05 用户裁决): 模型缺失且未经用户同意时不下载, 停在\n\t\t\t// consent-required 态等 memory_enable 工具面继续。注入 loadImpl 的测试\n\t\t\t// 缝绕过本门 (deterministic mock 门禁路径, 无网络语义)。截断文件不走\n\t\t\t// 征询 (文件在 = 曾有过一次下载意图), 仍走失败行动清单。\n\t\t\tconst hasEnablingTestSeam =\n\t\t\t\tenablingOverride?.embeddingLoadImpl !== undefined || enablingOverride?.rerankerLoadImpl !== undefined;\n\t\t\t// 服务装配缝的模型声明 (Slice B2): modelsInPlace = 测试声明模型已在位\n\t\t\t// (免写假权重文件), 文件检查与征询门相应让位; 生产路径缺省 false,\n\t\t\t// 真实文件检查与征询门语义不变。\n\t\t\tconst serviceModelsDeclared = inferenceServiceModelsInPlace === true;\n\t\t\tif (modelsMissing !== undefined && !consentGranted && !hasEnablingTestSeam && !serviceModelsDeclared) {\n\t\t\t\tvectorState = \"consent-required\";\n\t\t\t\tconsentNeededInfo = {\n\t\t\t\t\tmodels: modelsMissing.split(\" + \"),\n\t\t\t\t\tapproximateBytes: MODEL_MIN_WEIGHT_BYTES[memoryMode] + RERANKER_MIN_WEIGHT_BYTES,\n\t\t\t\t};\n\t\t\t\tvectorInitPromise = undefined;\n\t\t\t\tenablingSettled?.();\n\t\t\t\tlogger?.info(\n\t\t\t\t\t`memory models missing (${modelsMissing}); download waits for user consent (memory_enable tool)`,\n\t\t\t\t);\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\t// 服务路径不下载 (模型归服务所有); 该日志只属于本地装配的下载分支。\n\t\t\tif (modelsMissing !== undefined && !serviceModelsDeclared) {\n\t\t\t\tlogger?.info(`memory enabling: model files missing (${modelsMissing}); downloading via configured mirrors`);\n\t\t\t}\n\t\t\t// 服务装配路径 (Slice B2, 裁决 C「根治」): 模型在位且无本地装配测试缝时,\n\t\t\t// 装配经共享推理服务 — 模型与索引全机一份 (主会话 + 全部 subagent 共享),\n\t\t\t// 本进程零重依赖加载。失败按 enabling failed 呈现 (裁决 A: 不回退本地\n\t\t\t// 装配 — 回退即重开多进程风险)。loadImpl 缝走下方本地装配路径 (既有语义)。\n\t\t\tconst useInferenceService = (modelsMissing === undefined || serviceModelsDeclared) && !hasEnablingTestSeam;\n\t\t\tif (useInferenceService) {\n\t\t\t\t// 端口解析也走结构化失败: 非法 env 值若在此裸抛, vectorInitPromise\n\t\t\t\t// 直接 reject 且 failEnabling 不运行 — 状态机被钉死在 enabling,\n\t\t\t\t// 写路径 (fire-and-forget) 还会丢成 unhandled rejection。\n\t\t\t\tlet servicePort: number;\n\t\t\t\ttry {\n\t\t\t\t\tservicePort = inferenceServicePort ?? resolveMemoryInferencePort(undefined, process.env);\n\t\t\t\t} catch (error) {\n\t\t\t\t\treturn failEnabling(\n\t\t\t\t\t\t`inference service assembly failed (invalid ${MEMORY_INFERENCE_PORT_ENV}: ${\n\t\t\t\t\t\t\terror instanceof Error ? error.message : String(error)\n\t\t\t\t\t\t})`,\n\t\t\t\t\t\tserviceFailureActionList(MEMORY_INFERENCE_DEFAULT_PORT),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tlet client: MemoryInferenceClientV1 | undefined;\n\t\t\t\ttry {\n\t\t\t\t\tclient = await ensureInferenceServiceChannel({\n\t\t\t\t\t\tagentDir,\n\t\t\t\t\t\tmemoryMode,\n\t\t\t\t\t\tport: servicePort,\n\t\t\t\t\t\t...(inferenceServiceSpawnImpl === undefined ? {} : { spawnImpl: inferenceServiceSpawnImpl }),\n\t\t\t\t\t});\n\t\t\t\t\tif (capabilityDisposed) return failEnablingDisposed(() => client!.close());\n\t\t\t\t\t// agentDir 身份校验 (2026-10-06 串线修复): 固定端口单例服务可能\n\t\t\t\t\t// 属于另一个 --agent-dir 的会话 (hello 此前只回报模型身份, 后连\n\t\t\t\t\t// 者握手/冒烟全过却把读写投影进对方的 LanceDB)。在冒烟与档位比\n\t\t\t\t\t// 对之前先核对身份 — 不一致或缺失都绝不触碰该服务。\n\t\t\t\t\tconst helloAgentDir: string | undefined = client.hello.agentDir;\n\t\t\t\t\tif (helloAgentDir === undefined) {\n\t\t\t\t\t\tvoid closeResource(\"inference client\", () => client!.close());\n\t\t\t\t\t\treturn failEnabling(\n\t\t\t\t\t\t\t`inference service on port ${servicePort} reports no agent-dir identity — the service was started by an older version; wait for its idle exit or stop it manually, then restart the session`,\n\t\t\t\t\t\t\tserviceFailureActionList(servicePort),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (normalizeMemoryAgentDirIdentity(helloAgentDir) !== normalizeMemoryAgentDirIdentity(agentDir)) {\n\t\t\t\t\t\tvoid closeResource(\"inference client\", () => client!.close());\n\t\t\t\t\t\treturn failEnabling(\n\t\t\t\t\t\t\t`inference service on port ${servicePort} belongs to agent-dir ${helloAgentDir}, this session runs in ${agentDir} — its memory projection lives in another agent-dir; wait for its idle exit or stop it manually, then restart the session`,\n\t\t\t\t\t\t\tserviceFailureActionList(servicePort),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tconst channel: ActiveVectorChannelV1 = {\n\t\t\t\t\t\tembed: client.embedProvider,\n\t\t\t\t\t\treranker: client.reranker,\n\t\t\t\t\t\tindex: client.vectorIndex,\n\t\t\t\t\t\tqueryPrefix: preset.queryPrefix,\n\t\t\t\t\t\tembeddingModelId: client.hello.embeddingModelId,\n\t\t\t\t\t};\n\t\t\t\t\t// 冒烟经 wire (服务端首次 embed 完成模型加载, 预算放宽)。\n\t\t\t\t\tawait channel.embed.embed([\"memory enabling smoke test\"]);\n\t\t\t\t\tif (capabilityDisposed) return failEnablingDisposed(() => client!.close());\n\t\t\t\t\tif (client.hello.embeddingModelId !== preset.embeddingModelId) {\n\t\t\t\t\t\tvoid closeResource(\"inference client\", () => client!.close());\n\t\t\t\t\t\treturn failEnabling(\n\t\t\t\t\t\t\t`inference service runs embedding model ${client.hello.embeddingModelId}, session preset is ${preset.embeddingModelId} — the service was spawned for another memory tier; wait for its idle exit or stop it, then restart the session`,\n\t\t\t\t\t\t\tserviceFailureActionList(servicePort),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tconst storedModelId = await channel.index.getStoredModelId();\n\t\t\t\t\tif (!capabilityDisposed && storedModelId !== undefined && storedModelId !== preset.embeddingModelId) {\n\t\t\t\t\t\tlogger?.warn(\n\t\t\t\t\t\t\t`memory projection was built for ${storedModelId}, preset is ${preset.embeddingModelId}; startup reconciliation will rebuild it`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\t// dispose 竞态: teardown 已清引用 (capabilityDisposed) 时, 装配成功\n\t\t\t\t\t// 分支不得把新 IPC 连接赋回去——关闭它并落结构化失败, 让在途的\n\t\t\t\t\t// enablingOutcome() 等待者 (如 memory-preheat) 落定为失败而非悬挂。\n\t\t\t\t\tif (capabilityDisposed) return failEnablingDisposed(() => client!.close());\n\t\t\t\t\tinferenceClient = client;\n\t\t\t\t\tvectorChannel = channel;\n\t\t\t\t\tvectorState = \"ready\";\n\t\t\t\t\tlogger?.info(\n\t\t\t\t\t\t`memory ready via shared inference service (mode=${memoryMode}, embedding=${preset.embeddingModelId})`,\n\t\t\t\t\t);\n\t\t\t\t\tenablingSettled?.();\n\t\t\t\t\treturn channel;\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// 连接已建立后的失败 (冒烟/档位比对/getStoredModelId) 必须关掉\n\t\t\t\t\t// 客户端: 悬挂连接会让服务端 connections>0, 空闲自杀永不触发。\n\t\t\t\t\tif (client !== undefined) void closeResource(\"inference client\", () => client!.close());\n\t\t\t\t\treturn failEnabling(\n\t\t\t\t\t\t`inference service assembly failed (${error instanceof Error ? error.message : String(error)})`,\n\t\t\t\t\t\tserviceFailureActionList(servicePort),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// 检查 3: 磁盘余量 (light ≥ 500MB / full ≥ 2GB)。服务装配路径不下载, 已在上面 return。\n\t\t\tconst diskProblem = await diskHeadroomCheck(agentDir, DISK_HEADROOM_MIN_BYTES[memoryMode]);\n\t\t\tif (diskProblem !== undefined) return failEnabling(diskProblem);\n\t\t\t// dispose 竞态 (本地装配路径, 第一道): 已 teardown 就不再打开 LanceDB/\n\t\t\t// 拉起重依赖; 装配完成点还有第二道检查兜住模型下载窗口。\n\t\t\tif (capabilityDisposed) return failEnablingDisposed();\n\t\t\t// 加载: transformers/lancedb 的动态 import 都在这些模块内部, 这里只做\n\t\t\t// 模块级懒加载, 保持未触发会话零重依赖。进度周期性落一行 (下载可达\n\t\t\t// 数百 MB), 完成后清除。\n\t\t\tconst progressTimer = setInterval(() => {\n\t\t\t\tif (!capabilityDisposed) logger?.info(\"memory enabling still in progress (downloading/loading models)\");\n\t\t\t}, ENABLING_PROGRESS_LOG_INTERVAL_MS);\n\t\t\tif (typeof progressTimer === \"object\" && \"unref\" in progressTimer) progressTimer.unref();\n\t\t\tlet closeAcquired: (() => Promise<void>) | undefined;\n\t\t\tlet published = false;\n\t\t\ttry {\n\t\t\t\tconst [vectorIndexModule, embeddingModule, rerankerModule] = await Promise.all([\n\t\t\t\t\timport(\"./vector-index.ts\"),\n\t\t\t\t\timport(\"./embedding-provider.ts\"),\n\t\t\t\t\timport(\"./embedding-reranker.ts\"),\n\t\t\t\t]);\n\t\t\t\tif (capabilityDisposed) return failEnablingDisposed();\n\t\t\t\tconst index = await vectorIndexModule.createMemoryVectorIndex({\n\t\t\t\t\tdbPath: join(agentDir, \"memory\", VECTOR_DB_DIRNAME),\n\t\t\t\t\tdimensions: preset.dimensions,\n\t\t\t\t\t...(hostLancedbEntryPath === undefined ? {} : { moduleEntryPath: hostLancedbEntryPath }),\n\t\t\t\t});\n\t\t\t\tlet indexClosePromise: Promise<void> | undefined;\n\t\t\t\tcloseAcquired = () => {\n\t\t\t\t\tindexClosePromise ??= closeResource(\"vector index\", () => index.close());\n\t\t\t\t\treturn indexClosePromise;\n\t\t\t\t};\n\t\t\t\tcloseOwnedLocalResources = closeAcquired;\n\t\t\t\tif (capabilityDisposed) return failEnablingDisposed();\n\t\t\t\tconst remoteHosts = remoteHostsForEnabling();\n\t\t\t\tconst channel: ActiveVectorChannelV1 = {\n\t\t\t\t\tembed: embeddingModule.createTransformersEmbeddingProvider({\n\t\t\t\t\t\tmodelId: preset.embeddingModelId,\n\t\t\t\t\t\tdimensions: preset.dimensions,\n\t\t\t\t\t\tcacheDir: modelCacheDir,\n\t\t\t\t\t\tremoteHosts,\n\t\t\t\t\t\t...(hostTransformersEntryPath === undefined ? {} : { moduleEntryPath: hostTransformersEntryPath }),\n\t\t\t\t\t\t...(enablingOverride?.embeddingLoadImpl === undefined\n\t\t\t\t\t\t\t? {}\n\t\t\t\t\t\t\t: { loadImpl: enablingOverride.embeddingLoadImpl }),\n\t\t\t\t\t}),\n\t\t\t\t\treranker: rerankerModule.createTransformersReranker({\n\t\t\t\t\t\tmodelId: VECTOR_RERANKER_MODEL_ID,\n\t\t\t\t\t\tcacheDir: modelCacheDir,\n\t\t\t\t\t\tremoteHosts,\n\t\t\t\t\t\t...(hostTransformersEntryPath === undefined ? {} : { moduleEntryPath: hostTransformersEntryPath }),\n\t\t\t\t\t\t...(enablingOverride?.rerankerLoadImpl === undefined\n\t\t\t\t\t\t\t? {}\n\t\t\t\t\t\t\t: { loadImpl: enablingOverride.rerankerLoadImpl }),\n\t\t\t\t\t}),\n\t\t\t\t\tindex,\n\t\t\t\t\tqueryPrefix: preset.queryPrefix,\n\t\t\t\t\tembeddingModelId: preset.embeddingModelId,\n\t\t\t\t};\n\t\t\t\tlet channelClosePromise: Promise<void> | undefined;\n\t\t\t\tcloseAcquired = () => {\n\t\t\t\t\tchannelClosePromise ??= closeLocalChannel(channel);\n\t\t\t\t\treturn channelClosePromise;\n\t\t\t\t};\n\t\t\t\tcloseOwnedLocalResources = closeAcquired;\n\t\t\t\t// 冒烟: embed + rerank 各一条 (同时完成两个模型的下载与加载) +\n\t\t\t\t// 投影档位比对。rerank 冒烟 2026-10-06 live E2E 补齐: reranker\n\t\t\t\t// 懒加载, 只 embed 的冒烟会让 \"ready\" 携带未下载的精排权重 —\n\t\t\t\t// 共享推理服务 (两项文件均前置检查、永不自主下载) 对该会话拒启,\n\t\t\t\t// \"fully usable\" 的自述与服务前置条件必须一致。\n\t\t\t\tawait channel.embed.embed([\"memory enabling smoke test\"]);\n\t\t\t\tif (capabilityDisposed) return failEnablingDisposed();\n\t\t\t\tif (channel.embed.modelId !== preset.embeddingModelId) {\n\t\t\t\t\treturn failEnabling(\n\t\t\t\t\t\t`smoke check failed: embedding modelId ${channel.embed.modelId} does not match the ${memoryMode} preset ${preset.embeddingModelId}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (channel.reranker !== undefined) {\n\t\t\t\t\tawait channel.reranker.rerank(\"memory enabling smoke test\", [\"memory enabling smoke test\"]);\n\t\t\t\t\tif (capabilityDisposed) return failEnablingDisposed();\n\t\t\t\t}\n\t\t\t\tconst storedModelId = await channel.index.getStoredModelId();\n\t\t\t\tif (!capabilityDisposed && storedModelId !== undefined && storedModelId !== preset.embeddingModelId) {\n\t\t\t\t\tlogger?.warn(\n\t\t\t\t\t\t`memory projection was built for ${storedModelId}, preset is ${preset.embeddingModelId}; startup reconciliation will rebuild it`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\t// dispose 竞态 (本地装配路径, 第二道, 兜住模型下载窗口): 不把索引句柄\n\t\t\t\t// 赋回引用——关闭刚打开的 LanceDB 并落结构化失败。\n\t\t\t\tif (capabilityDisposed) return failEnablingDisposed();\n\t\t\t\tvectorChannel = channel;\n\t\t\t\tpublished = true;\n\t\t\t\tvectorState = \"ready\";\n\t\t\t\tlogger?.info(`memory ready (mode=${memoryMode}, embedding=${preset.embeddingModelId})`);\n\t\t\t\tenablingSettled?.();\n\t\t\t\treturn channel;\n\t\t\t} catch (error) {\n\t\t\t\treturn failEnabling(\n\t\t\t\t\t`model load or smoke check failed (${error instanceof Error ? error.message : String(error)})`,\n\t\t\t\t);\n\t\t\t} finally {\n\t\t\t\tclearInterval(progressTimer);\n\t\t\t\tif (!published && closeAcquired !== undefined) {\n\t\t\t\t\tawait closeAcquired();\n\t\t\t\t\tif (closeOwnedLocalResources === closeAcquired) closeOwnedLocalResources = undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t})();\n\t\treturn vectorInitPromise;\n\t};\n\n\t// ---- 征询门执行面 (2026-10-05 用户裁决「首次使用征询、拒绝/失败可跳过」) ----\n\t// memory_enable 是 consent-required / failed 态的唯一下载入口: consentGranted\n\t// 只在这里置位, recall/auto-recall 永不触发下载。decline 同时持久化\n\t// (writeMemoryConsentDeclined), 只抑制默认档——用户显式设置 memory.mode 后\n\t// 下次启用会在首次使用时再次走到征询门。\n\t// ---- 记忆模型下载控制面 (2026-10-05 流程裁决「后台预热、不阻塞提问」) ----\n\t// 生产入口 (交互模式会话绑定后) 经公共工具面调用 memory_enable download\n\t// 触发后台预热; 命令面 /memory off|retry 是用户的直接出口。两处共用同一对\n\t// 闭包; decline 持久化只抑制默认档。\n\tconst declineMemory = (): { status: \"completed\"; message: string } => {\n\t\t// 总是落盘 (幂等写): 升降档会清理文件里的拒绝标记, 之后再次 off 必须\n\t\t// 重新写入——不能用内存 flag 跳过持久化。\n\t\tconst firstDecline = !consentDeclined;\n\t\tconsentDeclined = true;\n\t\twriteMemoryConsentDeclined(agentDir);\n\t\tif (firstDecline) {\n\t\t\tlogger?.info(\"memory disabled by user decision (persisted to the memory agent-dir config)\");\n\t\t}\n\t\treturn {\n\t\t\tstatus: \"completed\",\n\t\t\tmessage:\n\t\t\t\t\"memory disabled for this machine (persisted). Set memory.mode (light|full) in settings.json and restart the session to re-enable\",\n\t\t};\n\t};\n\tconst downloadMemory = async (): Promise<\n\t\t| { status: \"completed\"; message: string }\n\t\t| { status: \"failed\"; message: string; actions?: readonly string[]; next?: string }\n\t> => {\n\t\tif (consentDeclined) {\n\t\t\treturn {\n\t\t\t\tstatus: \"failed\",\n\t\t\t\tmessage:\n\t\t\t\t\t\"memory was declined on this machine — set memory.mode (light|full) in settings.json and restart the session to re-enable\",\n\t\t\t};\n\t\t}\n\t\tconsentGranted = true;\n\t\tif (vectorState === \"failed\" || vectorState === \"consent-required\") {\n\t\t\tvectorState = \"enabling\";\n\t\t\tenablingFailure = undefined;\n\t\t\tvectorInitPromise = undefined;\n\t\t}\n\t\tconst channel = await vectorEnsure();\n\t\tif (channel === undefined) {\n\t\t\tconst failure = enablingFailure ?? {\n\t\t\t\treason: `memory enabling did not complete (state=${vectorState})`,\n\t\t\t\tactions: [] as const,\n\t\t\t};\n\t\t\treturn {\n\t\t\t\tstatus: \"failed\",\n\t\t\t\tmessage: `memory enabling failed: ${failure.reason}`,\n\t\t\t\tactions: failure.actions,\n\t\t\t\tnext: 'Tell the user the download failed and ask whether to skip memory (call memory_enable with action \"decline\" or /memory off — both persist off) or fix the environment and retry (/memory retry)',\n\t\t\t};\n\t\t}\n\t\t// 就绪: 补跑启动对账, 把预热期间写入的 ledger 记忆补进向量投影。\n\t\tresetReconcile();\n\t\treconcileOnce();\n\t\treturn { status: \"completed\", message: \"memory models ready — the memory family is fully usable\" };\n\t};\n\n\t// 会话切换重绑/插件卸载的共享资源释放 (TUI 每次会话切换都重走装配, 不释放\n\t// 即每次泄漏一条 IPC 连接: 服务端 connections>0 抑制空闲自杀, 嵌入方进程因\n\t// socket 未关无法自然退出)。清引用先行: close 的错误经独立 stderr 诊断, 且\n\t// 二次调用因引用已空自然 no-op。服务路径与本地路径互斥 (服务路径的 index\n\t// 归服务进程持有, 客户端只断连; 本地路径才关 LanceDB 句柄)。\n\t// capabilityDisposed 是 teardown 与在途 enabling 的竞态闩锁: teardown 之后\n\t// 才完成的装配在成功分支让位 (见 vectorEnsure 的 failEnablingDisposed),\n\t// 不复活无人关闭的连接/句柄。\n\tlet capabilityDisposed = false;\n\tconst capabilityTeardown = (): void => {\n\t\tcapabilityDisposed = true;\n\t\tif (closeOwnedLocalResources !== undefined) {\n\t\t\tconst close = closeOwnedLocalResources;\n\t\t\tcloseOwnedLocalResources = undefined;\n\t\t\tvectorChannel = undefined;\n\t\t\tvoid close();\n\t\t\treturn;\n\t\t}\n\t\tif (inferenceClient !== undefined) {\n\t\t\tconst client = inferenceClient;\n\t\t\tinferenceClient = undefined;\n\t\t\tvectorChannel = undefined;\n\t\t\tvoid closeResource(\"inference client\", () => client.close());\n\t\t\treturn;\n\t\t}\n\t\tif (vectorChannel !== undefined) {\n\t\t\tconst channel = vectorChannel;\n\t\t\tvectorChannel = undefined;\n\t\t\tvoid closeLocalChannel(channel);\n\t\t}\n\t};\n\n\treturn {\n\t\tstate: (): \"off\" | MemoryCapabilityStateV1 => (consentDeclined ? \"off\" : vectorState),\n\t\trawState: (): MemoryCapabilityStateV1 => vectorState,\n\t\tenabled: vectorEnabled,\n\t\treadyChannel: (): ActiveVectorChannelV1 | undefined => vectorChannel,\n\t\tisDisposed: (): boolean => capabilityDisposed,\n\t\tdeclined: (): boolean => consentDeclined,\n\t\tclearDeclined: (): void => {\n\t\t\tconsentDeclined = false;\n\t\t},\n\t\tconsentAsked: (): boolean => consentAsked,\n\t\tmarkConsentAsked: (): void => {\n\t\t\tconsentAsked = true;\n\t\t},\n\t\tprimeConsentGate,\n\t\tconsentAsk: (): MemoryConsentAskV1 | undefined =>\n\t\t\tvectorState === \"consent-required\" && consentNeededInfo !== undefined\n\t\t\t\t? { message: consentAskMessage(), actions: consentAskActions(), block: consentAskBlock() }\n\t\t\t\t: undefined,\n\t\twarming: (): boolean => vectorState === \"enabling\" && vectorInitPromise !== undefined && !consentDeclined,\n\t\tfailure: (): MemoryEnablingFailureV1 | undefined => enablingFailure,\n\t\tmarkDegraded: (): void => {\n\t\t\tvectorState = \"degraded\";\n\t\t},\n\t\trecoverDegraded: (): void => {\n\t\t\tif (vectorState === \"degraded\") vectorState = \"ready\";\n\t\t},\n\t\tensure: vectorEnsure,\n\t\tenablingOutcome: async (): Promise<\"ready\" | MemoryEnablingFailureV1> => {\n\t\t\tif (vectorState === \"enabling\") void vectorEnsure();\n\t\t\tawait enablingSettledPromise;\n\t\t\treturn enablingFailure ?? \"ready\";\n\t\t},\n\t\tdecline: declineMemory,\n\t\tdownload: downloadMemory,\n\t\tdispose: capabilityTeardown,\n\t};\n}\n"]}
|
|
1
|
+
{"version":3,"file":"vector-channel.d.ts","sourceRoot":"","sources":["../../src/memory/vector-channel.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * 向量通道状态机(capability 拆分战役 slice 3b):vectorEnsure 状态转换、装配分支(服务/本地/下载/征询门)、dispose 闩锁。共享闭包状态收拢为 channel 对象, 经 deps 显式注入; 降级/投影经 slice 3a 的 vector-projection 上报\n */\n\nimport { join } from \"node:path\";\nimport type {\n\tCapabilityAPI,\n\tMemoryEnablingOverrideV1,\n\tMemoryVectorComponentsOverrideV1,\n} from \"@agent-forge/plugin-sdk\";\nimport {\n\tDISK_HEADROOM_MIN_BYTES,\n\tdiskHeadroomCheck,\n\tenablingActionList,\n\tMODEL_MIN_WEIGHT_BYTES,\n\tmissingHeavyDependencyModules,\n\tmodelFilesCheck,\n\tnativeBinaryCheck,\n\tnormalizeMemoryAgentDirIdentity,\n\tRERANKER_MIN_WEIGHT_BYTES,\n\tremoteHostsForEnabling,\n\tresolveHeavyDependencyEntryPath,\n\tvectorPresetForMode,\n\twriteMemoryConsentDeclined,\n} from \"./enabling.ts\";\nimport { ensureInferenceServiceChannel, serviceFailureActionList } from \"./inference-channel.ts\";\nimport { type MemoryInferenceClientV1, resolveMemoryInferencePort } from \"./inference-client.ts\";\nimport { MEMORY_INFERENCE_DEFAULT_PORT, MEMORY_INFERENCE_PORT_ENV } from \"./inference-protocol.ts\";\nimport type { ActiveVectorChannelV1 } from \"./vector-projection.ts\";\n\n/** enabling 加载/下载期间的周期性进度日志间隔。 */\nconst ENABLING_PROGRESS_LOG_INTERVAL_MS = 15_000;\n\n// 宿主先撤销 CapabilityAPI 再调用 disposer。清理诊断不得依赖已撤销的 logger,\n// 也不得因诊断输出失败而中断其他资源释放或替换原始装配错误。\nfunction reportCleanupFailure(resource: string, error: unknown): void {\n\ttry {\n\t\tconsole.error(`memory ${resource} close failed`, error);\n\t} catch {\n\t\t// 诊断接收端不可用不改变资源生命周期。\n\t}\n}\n\nfunction closeResource(resource: string, close: () => unknown): Promise<void> {\n\treturn Promise.resolve()\n\t\t.then(close)\n\t\t.then(() => undefined)\n\t\t.catch((error: unknown) => reportCleanupFailure(resource, error));\n}\n\n/** 两档共用精排模型 (POC 报告 §8: 官方 Xenova 转换版唯一实测可用)。 */\nexport const VECTOR_RERANKER_MODEL_ID = \"Xenova/bge-reranker-base\";\nexport const VECTOR_DB_DIRNAME = \"vector\";\nexport const VECTOR_MODEL_CACHE_DIRNAME = \"model-cache\";\n\n/** capability 级状态机 (设计 §3.2): off 只出现在模式关闭 (零注册, 不可观测)。 */\nexport type MemoryCapabilityStateV1 = \"consent-required\" | \"enabling\" | \"ready\" | \"degraded\" | \"failed\";\n\n/** enabling 失败的结构化结果: 原因 + 行动清单 (硬性要求, 设计 §3.2)。 */\nexport interface MemoryEnablingFailureV1 {\n\treadonly reason: string;\n\treadonly actions: readonly string[];\n}\n\n/**\n * 征询门待决信息 (2026-10-05 用户裁决「首次使用征询、拒绝即持久化关闭」):\n * 向量通道从未就绪且模式已启用时, 模型下载必须先经用户同意——检索不触发下载,\n * 由 AI 转述征询后经 memory_enable 工具面继续。\n */\nexport interface MemoryConsentNeededV1 {\n\treadonly models: readonly string[];\n\t/** 模型权重体积下限之和 (非精确体积; 实际下载量以镜像文件为准)。 */\n\treadonly approximateBytes: number;\n}\n\n/** 征询面 (consent-required 态的模型可见包): AI 转述话术 + 后续动作 + 注入块。 */\nexport interface MemoryConsentAskV1 {\n\treadonly message: string;\n\treadonly actions: readonly string[];\n\treadonly block: string;\n}\n\n/**\n * 向量通道对 capability 装配上下文的显式依赖视图 (slice 3b): 逐项来自\n * createMemoryCapabilityHarness 的闭包捕获核实, 不再经共享闭包隐式可达。\n */\nexport interface MemoryVectorChannelDepsV1 {\n\t/** agent 根目录 (MemoryCapabilityContext.agentDir): 模型缓存/索引/征询持久化的路径域。 */\n\treadonly agentDir: string;\n\t/** 已解析的全局档位 (harness memoryMode, off 已被工厂入口拦截)。 */\n\treadonly memoryMode: \"light\" | \"full\";\n\t/** capability 日志面 (api.logger): 进度/失败/自愈日志。 */\n\treadonly logger: CapabilityAPI[\"logger\"];\n\t/** 宿主注入的 onnxruntime-node 入口 (MemoryCapabilityContext.hostOnnxRuntimeEntryPath)。 */\n\treadonly hostOnnxRuntimeEntryPath?: string;\n\t/** 宿主注入的 @lancedb/lancedb 入口 (MemoryCapabilityContext.hostLancedbEntryPath)。 */\n\treadonly hostLancedbEntryPath?: string;\n\t/** 宿主注入的 @huggingface/transformers 入口 (MemoryCapabilityContext.hostTransformersEntryPath)。 */\n\treadonly hostTransformersEntryPath?: string;\n\t/** 服务装配缝 (Slice B2): 测试端口直连 (MemoryCapabilityContext.inferenceService.port)。 */\n\treadonly inferenceServicePort?: number;\n\t/** 服务装配缝 (Slice B2): 替换进程拉起的测试缝 (inferenceService.spawnImpl)。 */\n\treadonly inferenceServiceSpawnImpl?: (\n\t\tagentDir: string,\n\t\tmode: \"light\" | \"full\",\n\t\tport: number,\n\t\t/** spawn 异步失败 (EACCES/ENOMEM 等) 的回调; 缺省实现经 child 'error' 事件馈入。 */\n\t\tonError?: (error: Error) => void,\n\t) => Promise<void>;\n\t/** 服务装配缝 (Slice B2): 声明模型在位, 文件检查与征询门让位 (inferenceService.modelsInPlace)。 */\n\treadonly inferenceServiceModelsInPlace?: boolean;\n\t/** enabling 测试缝 (loadImpl 重定向模型加载); undefined = 生产路径。 */\n\treadonly enablingOverride?: MemoryEnablingOverrideV1;\n\t/** 组件注入 (deterministic mock 门禁): 存在时通道直接 ready, 跳过真实装配。 */\n\treadonly injectedComponents?: MemoryVectorComponentsOverrideV1;\n\t/** 写侧投影 (slice 3a 的 vectorProjection.resetReconcile): downloadMemory 就绪后重臂启动对账。 */\n\treadonly resetReconcile: () => void;\n\t/** 写侧投影 (slice 3a 的 vectorProjection.reconcileOnce): downloadMemory 就绪后补跑对账。 */\n\treadonly reconcileOnce: () => void;\n}\n\nexport interface MemoryVectorChannelV1 {\n\t/** harness.vectorState 面: 征询拒绝时投影为 \"off\" (本实例按模式关闭对待)。 */\n\tstate(): \"off\" | MemoryCapabilityStateV1;\n\t/** vectorState 原值 (未做 declined 投影; recall/合并探测等内部消费)。 */\n\trawState(): MemoryCapabilityStateV1;\n\t/** vectorEnabled: failed/consent-required/declined 时 false (写侧埋点门)。 */\n\tenabled(): boolean;\n\t/** 已就绪通道的同步快照 (vectorChannel 只读; projection.readyChannel 面)。 */\n\treadyChannel(): ActiveVectorChannelV1 | undefined;\n\t/** dispose 闩锁只读视图 (capabilityDisposed; projection.isDisposed 面)。 */\n\tisDisposed(): boolean;\n\t/** 征询拒绝标记 (declineMemory 持久化后的本实例内存面)。 */\n\tdeclined(): boolean;\n\t/** 用户显式再启用 (/memory light|full、自动升档) 清除本实例拒绝标记。 */\n\tclearDeclined(): void;\n\t/** 征询一次性注入钉住标记 (auto-recall 每实例只注入一次)。 */\n\tconsentAsked(): boolean;\n\tmarkConsentAsked(): void;\n\t/** 无副作用征询探测 (auto-recall 首轮; 纯本地 stat, 绝不触发下载/加载)。 */\n\tprimeConsentGate(): void;\n\t/** 征询待决面 (consent-required 且待决信息就位时非 undefined; 纯只读, 不探测)。 */\n\tconsentAsk(): MemoryConsentAskV1 | undefined;\n\t/** warming 守卫 (recall 后台预热不阻塞读侧): 装配在途且未拒绝。 */\n\twarming(): boolean;\n\t/** enabling 失败结构化结果 (未失败 = undefined)。 */\n\tfailure(): MemoryEnablingFailureV1 | undefined;\n\t/** 运行期故障 → degraded (可自愈; recall 与投影对账共用)。 */\n\tmarkDegraded(): void;\n\t/** degraded → ready 的自愈转换 (仅从 degraded; 全通 recall 成功后调用)。 */\n\trecoverDegraded(): void;\n\t/** vectorEnsure: 惰性单飞装配 (recall/write/埋点/对账的公共入口)。 */\n\tensure(): Promise<ActiveVectorChannelV1 | undefined>;\n\t/** harness.enablingOutcome 面: 触发惰性 enabling 并等待落定 (ready 或结构化失败)。 */\n\tenablingOutcome(): Promise<\"ready\" | MemoryEnablingFailureV1>;\n\t/** declineMemory 核心: 持久化拒绝 + 本实例按模式关闭。 */\n\tdecline(): { status: \"completed\"; message: string };\n\t/** downloadMemory 核心: 置征询同意 + 装配 + 补跑启动对账。 */\n\tdownload(): Promise<\n\t\t| { status: \"completed\"; message: string }\n\t\t| { status: \"failed\"; message: string; actions?: readonly string[]; next?: string }\n\t>;\n\t/** capabilityTeardown 本体: 资源关闭 + 闩锁置位 (幂等)。 */\n\tdispose(): void;\n}\n\nexport function createMemoryVectorChannel(deps: MemoryVectorChannelDepsV1): MemoryVectorChannelV1 {\n\tconst {\n\t\tagentDir,\n\t\tmemoryMode,\n\t\tlogger,\n\t\thostOnnxRuntimeEntryPath,\n\t\thostLancedbEntryPath,\n\t\thostTransformersEntryPath,\n\t\tinferenceServicePort,\n\t\tinferenceServiceSpawnImpl,\n\t\tinferenceServiceModelsInPlace,\n\t\tenablingOverride,\n\t\tinjectedComponents,\n\t\tresetReconcile,\n\t\treconcileOnce,\n\t} = deps;\n\t// ---- 语义召回通道 (2.4d6 S1/S2; 召回唯一检索路径) ----\n\t// 状态机 (设计 §3.2): enabling = 检查/加载进行中 (惰性触发: 首次向量操作\n\t// 时真正执行); ready = 可用; degraded = ready 后运行期故障 (可自愈回\n\t// ready); failed = enabling 失败, 本实例内终态 (mode 回退 off, 记忆工具\n\t// 返回携带行动清单的不可用 packet, 不再重试)。所有写侧操作经 vectorQueue\n\t// 串行化, 避免 reconcile 与写入埋点在 LanceDB 建表上竞态; recall 等待\n\t// enabling 单飞完成, 不与后台对账并发读索引。transformers/lancedb 的动态\n\t// import 只出现在 vectorEnsure 的装配分支里 (type-position 引类型), 未\n\t// 触发时不加载任何重依赖。\n\tlet vectorState: MemoryCapabilityStateV1 = \"enabling\";\n\tlet vectorChannel: ActiveVectorChannelV1 | undefined;\n\tlet enablingFailure: MemoryEnablingFailureV1 | undefined;\n\tlet enablingSettled: (() => void) | undefined;\n\t// 征询门 (2026-10-05 用户裁决「首次使用征询、拒绝即持久化关闭」): 模型文件\n\t// 缺失时下载必须先经用户同意——consentGranted 只由 memory_enable 工具面置位;\n\t// consentDeclined = 本实例内用户拒绝/跳过 (同时持久化, 见\n\t// writeMemoryConsentDeclined), 之后本实例按模式关闭对待; consentAsked 钉住\n\t// 自动召回的一次性征询注入, 不随查询文本翻新。\n\tlet consentGranted = false;\n\tlet consentDeclined = false;\n\tlet consentAsked = false;\n\tlet consentNeededInfo: MemoryConsentNeededV1 | undefined;\n\tconst enablingSettledPromise = new Promise<\"ready\" | MemoryEnablingFailureV1>((resolve) => {\n\t\tenablingSettled = () => resolve(enablingFailure ?? \"ready\");\n\t});\n\tif (injectedComponents !== undefined) {\n\t\t// 测试注入: 直接 ready, 跳过真实装配与档位解析。\n\t\tvectorState = \"ready\";\n\t\tvectorChannel = {\n\t\t\tembed: injectedComponents.embedProvider,\n\t\t\treranker: injectedComponents.reranker,\n\t\t\tindex: injectedComponents.vectorIndex,\n\t\t\tqueryPrefix: injectedComponents.queryPrefix ?? \"\",\n\t\t\tembeddingModelId: injectedComponents.embedProvider.modelId,\n\t\t};\n\t\tenablingSettled?.();\n\t}\n\tconst vectorEnabled = (): boolean =>\n\t\tvectorState !== \"failed\" && vectorState !== \"consent-required\" && !consentDeclined;\n\t// 尚未发布的本地资源也归本实例拥有;teardown 立即标记 provider 关闭。\n\tlet closeOwnedLocalResources: (() => Promise<void>) | undefined;\n\tconst closeLocalChannel = async (channel: ActiveVectorChannelV1): Promise<void> => {\n\t\tconst results = await Promise.allSettled([\n\t\t\tPromise.resolve().then(() => channel.index.close()),\n\t\t\t(async () => channel.embed.dispose?.())(),\n\t\t\t(async () => channel.reranker?.dispose?.())(),\n\t\t]);\n\t\tconst resources = [\"vector index\", \"embedding provider\", \"reranker\"];\n\t\tfor (const [index, result] of results.entries()) {\n\t\t\tif (result.status === \"rejected\") reportCleanupFailure(resources[index]!, result.reason);\n\t\t}\n\t};\n\t// 征询话术 (AI 转述给用户; 会话语言由 AI 决定): 模型清单 + 体积下限 + 两个\n\t// 后续动作。consent-required 态下的 recall packet、auto-recall 注入块共用。\n\tconst consentAskMessage = (): string => {\n\t\tconst info = consentNeededInfo;\n\t\tconst models = info === undefined ? \"embedding + reranker\" : info.models.join(\" + \");\n\t\tconst floorMb = Math.ceil(\n\t\t\t(info?.approximateBytes ?? MODEL_MIN_WEIGHT_BYTES[memoryMode] + RERANKER_MIN_WEIGHT_BYTES) / (1024 * 1024),\n\t\t);\n\t\treturn (\n\t\t\t`memory needs a one-time model download (${models}, at least ${floorMb} MB total; ` +\n\t\t\t\"actual sizes come from the mirror) into <agentDir>/memory/model-cache before recall can run — \" +\n\t\t\t\"nothing downloads without user consent\"\n\t\t);\n\t};\n\tconst consentAskActions = (): readonly string[] => [\n\t\t\"Ask the user whether to download the memory models now\",\n\t\t'With consent, call memory_enable with action \"download\"',\n\t\t'If the user declines, call memory_enable with action \"decline\" (persists memory off; set memory.mode in settings.json later to re-enable)',\n\t];\n\tconst consentAskBlock = (): string =>\n\t\t[\n\t\t\t\"<memory_setup>\",\n\t\t\tconsentAskMessage(),\n\t\t\t\"Ask the user (in the conversation language) whether to download now; relay that it is one-time and the size.\",\n\t\t\t...consentAskActions()\n\t\t\t\t.slice(1)\n\t\t\t\t.map((line) => `- ${line}`),\n\t\t\t\"</memory_setup>\",\n\t\t].join(\"\\n\");\n\t// 无副作用探测: 初始态是 enabling, 而征询态只在 vectorEnsure 探测后落定——\n\t// 自动召回钩子首轮就要给出征询注入, 这里只做模型文件存在性检查 (纯本地\n\t// stat), 缺失即落定 consent-required, 绝不触发下载/加载。\n\tconst primeConsentGate = (): void => {\n\t\tif (consentGranted || consentDeclined || vectorState !== \"enabling\") return;\n\t\tif (\n\t\t\tenablingOverride?.embeddingLoadImpl !== undefined ||\n\t\t\tenablingOverride?.rerankerLoadImpl !== undefined ||\n\t\t\t// 服务装配缝的模型声明 (Slice B2): 与 vectorEnsure 装配分支同一豁免 —\n\t\t\t// 声明在位时文件检查让位, 征询门不应被 auto-recall 钩子提前翻起。\n\t\t\tinferenceServiceModelsInPlace === true\n\t\t) {\n\t\t\treturn;\n\t\t}\n\t\tconst preset = vectorPresetForMode(memoryMode);\n\t\tconst modelCacheDir = join(agentDir, \"memory\", VECTOR_MODEL_CACHE_DIRNAME);\n\t\tconst modelsMissing =\n\t\t\tmodelFilesCheck(modelCacheDir, preset.embeddingModelId, MODEL_MIN_WEIGHT_BYTES[memoryMode]) === \"missing\" ||\n\t\t\tmodelFilesCheck(modelCacheDir, VECTOR_RERANKER_MODEL_ID, RERANKER_MIN_WEIGHT_BYTES) === \"missing\";\n\t\tif (!modelsMissing) return;\n\t\tvectorState = \"consent-required\";\n\t\tconsentNeededInfo = {\n\t\t\tmodels: [\n\t\t\t\tpreset.embeddingModelId,\n\t\t\t\t...(modelFilesCheck(modelCacheDir, VECTOR_RERANKER_MODEL_ID, RERANKER_MIN_WEIGHT_BYTES) === \"missing\"\n\t\t\t\t\t? [VECTOR_RERANKER_MODEL_ID]\n\t\t\t\t\t: []),\n\t\t\t],\n\t\t\tapproximateBytes: MODEL_MIN_WEIGHT_BYTES[memoryMode] + RERANKER_MIN_WEIGHT_BYTES,\n\t\t};\n\t};\n\tlet vectorInitPromise: Promise<ActiveVectorChannelV1 | undefined> | undefined;\n\n\t/**\n\t * 开启状态机 (设计 §3.2, 惰性单飞): 本地检查 (native .node 可解析 → 重依赖\n\t * 供给 (lancedb/transformers: 宿主入口路径或插件位置自解析) → 模型文件存在\n\t * 与大小 → 磁盘余量) → transformers 加载 (自带下载, 进度周期性\n\t * 落一行日志) → 冒烟 (embed 一条 + getStoredModelId 与档位比对) → ready。\n\t * 任一步失败 → failed (原因 + 五选一行动清单), mode 记录回退 off, 本实例\n\t * 不再重试。\n\t */\n\t/** 服务模式持有的 IPC 客户端 (断连自愈检测用; 本地装配路径恒 undefined)。 */\n\tlet inferenceClient: MemoryInferenceClientV1 | undefined;\n\n\tconst vectorEnsure = (): Promise<ActiveVectorChannelV1 | undefined> => {\n\t\tif (capabilityDisposed) {\n\t\t\tvectorState = \"failed\";\n\t\t\tenablingFailure ??= { reason: \"capability disposed during enabling\", actions: [] };\n\t\t\tenablingSettled?.();\n\t\t\treturn Promise.resolve(undefined);\n\t\t}\n\t\tif (vectorState === \"ready\" || vectorState === \"degraded\") {\n\t\t\t// 服务模式断连自愈 (Slice B2): 缓存 channel 背后的 IPC 客户端死亡时\n\t\t\t// 清缓存重走装配 (重连 + 必要时重拉起服务), 而不是拿着死连接报错。\n\t\t\tif (inferenceClient === undefined || inferenceClient.isAlive()) return Promise.resolve(vectorChannel);\n\t\t\tlogger?.warn(\"memory inference service connection lost; reconnecting\");\n\t\t\tinferenceClient = undefined;\n\t\t\tvectorChannel = undefined;\n\t\t\tvectorState = \"enabling\";\n\t\t\tvectorInitPromise = undefined;\n\t\t}\n\t\tif (vectorState === \"failed\") return Promise.resolve(undefined);\n\t\tif (vectorInitPromise !== undefined) return vectorInitPromise;\n\t\tvectorInitPromise = (async (): Promise<ActiveVectorChannelV1 | undefined> => {\n\t\t\tconst preset = vectorPresetForMode(memoryMode);\n\t\t\tconst modelCacheDir = join(agentDir, \"memory\", VECTOR_MODEL_CACHE_DIRNAME);\n\t\t\tconst failEnabling = (\n\t\t\t\treason: string,\n\t\t\t\tactions: readonly string[] = enablingActionList(modelCacheDir, memoryMode),\n\t\t\t): undefined => {\n\t\t\t\tvectorState = \"failed\";\n\t\t\t\tenablingFailure = { reason, actions };\n\t\t\t\tvectorInitPromise = undefined;\n\t\t\t\tenablingSettled?.();\n\t\t\t\tif (!capabilityDisposed)\n\t\t\t\t\tlogger?.warn(`memory enabling failed: ${reason} — actions: ${enablingFailure.actions.join(\" | \")}`, {\n\t\t\t\t\t\tmode: memoryMode,\n\t\t\t\t\t});\n\t\t\t\treturn undefined;\n\t\t\t};\n\t\t\t// dispose 竞态守卫 (2026-10-06 复审遗留): teardown 与在途 enabling 竞态\n\t\t\t// 时, 装配完成点必须让位——不得把新连接/索引句柄赋回已清空的引用 (那会\n\t\t\t// 复活一条无人关闭的连接: 服务端 connections>0 抑制空闲自杀、挂住嵌入\n\t\t\t// 进程事件循环), 也不得让 enablingOutcome() 等待者悬挂。改为关闭刚取得\n\t\t\t// 的资源并落结构化 failed (MemoryEnablingFailureV1 形状)。\n\t\t\tconst failEnablingDisposed = (closeAcquired?: () => Promise<unknown>): undefined => {\n\t\t\t\tvectorState = \"failed\";\n\t\t\t\tenablingFailure = { reason: \"capability disposed during enabling\", actions: [] };\n\t\t\t\tvectorInitPromise = undefined;\n\t\t\t\tenablingSettled?.();\n\t\t\t\tif (closeAcquired !== undefined) void closeResource(\"inference client\", closeAcquired);\n\t\t\t\treturn undefined;\n\t\t\t};\n\t\t\tlogger?.info(`memory enabling started (mode=${memoryMode}, embedding=${preset.embeddingModelId})`);\n\t\t\t// 检查 1: native .node sidecar (纯本地, 零网络)。宿主注入路径优先\n\t\t\t// (安装店副本自解析不可达, 见 MemoryCapabilityContext.hostOnnxRuntimeEntryPath)。\n\t\t\tconst nativeProblem = nativeBinaryCheck(hostOnnxRuntimeEntryPath);\n\t\t\tif (nativeProblem !== undefined) return failEnabling(nativeProblem);\n\t\t\t// 检查 1b: 重依赖供给。宿主入口路径优先; 未提供时插件位置自解析,\n\t\t\t// 两者都不可达 = 原本要到加载步才以 \"Cannot find module\" 泛化包装\n\t\t\t// 失败的根因, 前置到模型下载之前以 onnx 缺供分支同构的精准文案报告。\n\t\t\t// 路径已提供但包损坏的真实失败仍走加载步, 由泛化包装保留原始错误。\n\t\t\tconst missingHeavyDependencies = missingHeavyDependencyModules(\n\t\t\t\t{ lancedb: hostLancedbEntryPath, transformers: hostTransformersEntryPath },\n\t\t\t\tresolveHeavyDependencyEntryPath,\n\t\t\t);\n\t\t\tif (missingHeavyDependencies.length > 0) {\n\t\t\t\treturn failEnabling(\n\t\t\t\t\t`${missingHeavyDependencies.join(\", \")} are not provided by the host installation and could not be resolved from the plugin location; to enable memory features, install them in the host project (npm i ${missingHeavyDependencies.join(\" \")}) and restart the session`,\n\t\t\t\t);\n\t\t\t}\n\t\t\t// 检查 2: 模型文件 (缺失 = 进入下载; 存在但截断 = 失败提示手动导入)。\n\t\t\tconst embeddingProblem = modelFilesCheck(\n\t\t\t\tmodelCacheDir,\n\t\t\t\tpreset.embeddingModelId,\n\t\t\t\tMODEL_MIN_WEIGHT_BYTES[memoryMode],\n\t\t\t);\n\t\t\tconst rerankerProblem = modelFilesCheck(modelCacheDir, VECTOR_RERANKER_MODEL_ID, RERANKER_MIN_WEIGHT_BYTES);\n\t\t\tconst modelsMissing =\n\t\t\t\tembeddingProblem === \"missing\" || rerankerProblem === \"missing\"\n\t\t\t\t\t? `${preset.embeddingModelId}${rerankerProblem === \"missing\" ? ` + ${VECTOR_RERANKER_MODEL_ID}` : \"\"}`\n\t\t\t\t\t: undefined;\n\t\t\tif (embeddingProblem !== undefined && embeddingProblem !== \"missing\") return failEnabling(embeddingProblem);\n\t\t\tif (rerankerProblem !== undefined && rerankerProblem !== \"missing\") return failEnabling(rerankerProblem);\n\t\t\t// 征询门 (2026-10-05 用户裁决): 模型缺失且未经用户同意时不下载, 停在\n\t\t\t// consent-required 态等 memory_enable 工具面继续。注入 loadImpl 的测试\n\t\t\t// 缝绕过本门 (deterministic mock 门禁路径, 无网络语义)。截断文件不走\n\t\t\t// 征询 (文件在 = 曾有过一次下载意图), 仍走失败行动清单。\n\t\t\tconst hasEnablingTestSeam =\n\t\t\t\tenablingOverride?.embeddingLoadImpl !== undefined || enablingOverride?.rerankerLoadImpl !== undefined;\n\t\t\t// 服务装配缝的模型声明 (Slice B2): modelsInPlace = 测试声明模型已在位\n\t\t\t// (免写假权重文件), 文件检查与征询门相应让位; 生产路径缺省 false,\n\t\t\t// 真实文件检查与征询门语义不变。\n\t\t\tconst serviceModelsDeclared = inferenceServiceModelsInPlace === true;\n\t\t\tif (modelsMissing !== undefined && !consentGranted && !hasEnablingTestSeam && !serviceModelsDeclared) {\n\t\t\t\tvectorState = \"consent-required\";\n\t\t\t\tconsentNeededInfo = {\n\t\t\t\t\tmodels: modelsMissing.split(\" + \"),\n\t\t\t\t\tapproximateBytes: MODEL_MIN_WEIGHT_BYTES[memoryMode] + RERANKER_MIN_WEIGHT_BYTES,\n\t\t\t\t};\n\t\t\t\tvectorInitPromise = undefined;\n\t\t\t\tenablingSettled?.();\n\t\t\t\tlogger?.info(\n\t\t\t\t\t`memory models missing (${modelsMissing}); download waits for user consent (memory_enable tool)`,\n\t\t\t\t);\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\t// 服务路径不下载 (模型归服务所有); 该日志只属于本地装配的下载分支。\n\t\t\tif (modelsMissing !== undefined && !serviceModelsDeclared) {\n\t\t\t\tlogger?.info(`memory enabling: model files missing (${modelsMissing}); downloading via configured mirrors`);\n\t\t\t}\n\t\t\t// 服务装配路径 (Slice B2, 裁决 C「根治」): 模型在位且无本地装配测试缝时,\n\t\t\t// 装配经共享推理服务 — 模型与索引全机一份 (主会话 + 全部 subagent 共享),\n\t\t\t// 本进程零重依赖加载。失败按 enabling failed 呈现 (裁决 A: 不回退本地\n\t\t\t// 装配 — 回退即重开多进程风险)。loadImpl 缝走下方本地装配路径 (既有语义)。\n\t\t\tconst useInferenceService = (modelsMissing === undefined || serviceModelsDeclared) && !hasEnablingTestSeam;\n\t\t\tif (useInferenceService) {\n\t\t\t\t// 端口解析也走结构化失败: 非法 env 值若在此裸抛, vectorInitPromise\n\t\t\t\t// 直接 reject 且 failEnabling 不运行 — 状态机被钉死在 enabling,\n\t\t\t\t// 写路径 (fire-and-forget) 还会丢成 unhandled rejection。\n\t\t\t\tlet servicePort: number;\n\t\t\t\ttry {\n\t\t\t\t\tservicePort = inferenceServicePort ?? resolveMemoryInferencePort(undefined, process.env);\n\t\t\t\t} catch (error) {\n\t\t\t\t\treturn failEnabling(\n\t\t\t\t\t\t`inference service assembly failed (invalid ${MEMORY_INFERENCE_PORT_ENV}: ${\n\t\t\t\t\t\t\terror instanceof Error ? error.message : String(error)\n\t\t\t\t\t\t})`,\n\t\t\t\t\t\tserviceFailureActionList(MEMORY_INFERENCE_DEFAULT_PORT),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tlet client: MemoryInferenceClientV1 | undefined;\n\t\t\t\ttry {\n\t\t\t\t\tclient = await ensureInferenceServiceChannel({\n\t\t\t\t\t\tagentDir,\n\t\t\t\t\t\tmemoryMode,\n\t\t\t\t\t\tport: servicePort,\n\t\t\t\t\t\t...(inferenceServiceSpawnImpl === undefined ? {} : { spawnImpl: inferenceServiceSpawnImpl }),\n\t\t\t\t\t});\n\t\t\t\t\tif (capabilityDisposed) return failEnablingDisposed(() => client!.close());\n\t\t\t\t\t// agentDir 身份校验 (2026-10-06 串线修复): 固定端口单例服务可能\n\t\t\t\t\t// 属于另一个 --agent-dir 的会话 (hello 此前只回报模型身份, 后连\n\t\t\t\t\t// 者握手/冒烟全过却把读写投影进对方的 LanceDB)。在冒烟与档位比\n\t\t\t\t\t// 对之前先核对身份 — 不一致或缺失都绝不触碰该服务。\n\t\t\t\t\tconst helloAgentDir: string | undefined = client.hello.agentDir;\n\t\t\t\t\tif (helloAgentDir === undefined) {\n\t\t\t\t\t\tvoid closeResource(\"inference client\", () => client!.close());\n\t\t\t\t\t\treturn failEnabling(\n\t\t\t\t\t\t\t`inference service on port ${servicePort} reports no agent-dir identity — the service was started by an older version; wait for its idle exit or stop it manually, then restart the session`,\n\t\t\t\t\t\t\tserviceFailureActionList(servicePort),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (normalizeMemoryAgentDirIdentity(helloAgentDir) !== normalizeMemoryAgentDirIdentity(agentDir)) {\n\t\t\t\t\t\tvoid closeResource(\"inference client\", () => client!.close());\n\t\t\t\t\t\treturn failEnabling(\n\t\t\t\t\t\t\t`inference service on port ${servicePort} belongs to agent-dir ${helloAgentDir}, this session runs in ${agentDir} — its memory projection lives in another agent-dir; wait for its idle exit or stop it manually, then restart the session`,\n\t\t\t\t\t\t\tserviceFailureActionList(servicePort),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tconst channel: ActiveVectorChannelV1 = {\n\t\t\t\t\t\tembed: client.embedProvider,\n\t\t\t\t\t\treranker: client.reranker,\n\t\t\t\t\t\tindex: client.vectorIndex,\n\t\t\t\t\t\tqueryPrefix: preset.queryPrefix,\n\t\t\t\t\t\tembeddingModelId: client.hello.embeddingModelId,\n\t\t\t\t\t};\n\t\t\t\t\t// 冒烟经 wire (服务端首次 embed 完成模型加载, 预算放宽)。\n\t\t\t\t\tawait channel.embed.embed([\"memory enabling smoke test\"]);\n\t\t\t\t\tif (capabilityDisposed) return failEnablingDisposed(() => client!.close());\n\t\t\t\t\tif (client.hello.embeddingModelId !== preset.embeddingModelId) {\n\t\t\t\t\t\tvoid closeResource(\"inference client\", () => client!.close());\n\t\t\t\t\t\treturn failEnabling(\n\t\t\t\t\t\t\t`inference service runs embedding model ${client.hello.embeddingModelId}, session preset is ${preset.embeddingModelId} — the service was spawned for another memory tier; wait for its idle exit or stop it, then restart the session`,\n\t\t\t\t\t\t\tserviceFailureActionList(servicePort),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tconst storedModelId = await channel.index.getStoredModelId();\n\t\t\t\t\tif (!capabilityDisposed && storedModelId !== undefined && storedModelId !== preset.embeddingModelId) {\n\t\t\t\t\t\tlogger?.warn(\n\t\t\t\t\t\t\t`memory projection was built for ${storedModelId}, preset is ${preset.embeddingModelId}; startup reconciliation will rebuild it`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\t// dispose 竞态: teardown 已清引用 (capabilityDisposed) 时, 装配成功\n\t\t\t\t\t// 分支不得把新 IPC 连接赋回去——关闭它并落结构化失败, 让在途的\n\t\t\t\t\t// enablingOutcome() 等待者 (如 memory-preheat) 落定为失败而非悬挂。\n\t\t\t\t\tif (capabilityDisposed) return failEnablingDisposed(() => client!.close());\n\t\t\t\t\tinferenceClient = client;\n\t\t\t\t\tvectorChannel = channel;\n\t\t\t\t\tvectorState = \"ready\";\n\t\t\t\t\tlogger?.info(\n\t\t\t\t\t\t`memory ready via shared inference service (mode=${memoryMode}, embedding=${preset.embeddingModelId})`,\n\t\t\t\t\t);\n\t\t\t\t\tenablingSettled?.();\n\t\t\t\t\treturn channel;\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// 连接已建立后的失败 (冒烟/档位比对/getStoredModelId) 必须关掉\n\t\t\t\t\t// 客户端: 悬挂连接会让服务端 connections>0, 空闲自杀永不触发。\n\t\t\t\t\tif (client !== undefined) void closeResource(\"inference client\", () => client!.close());\n\t\t\t\t\treturn failEnabling(\n\t\t\t\t\t\t`inference service assembly failed (${error instanceof Error ? error.message : String(error)})`,\n\t\t\t\t\t\tserviceFailureActionList(servicePort),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// 检查 3: 磁盘余量 (light ≥ 500MB / full ≥ 2GB)。服务装配路径不下载, 已在上面 return。\n\t\t\tconst diskProblem = await diskHeadroomCheck(agentDir, DISK_HEADROOM_MIN_BYTES[memoryMode]);\n\t\t\tif (diskProblem !== undefined) return failEnabling(diskProblem);\n\t\t\t// dispose 竞态 (本地装配路径, 第一道): 已 teardown 就不再打开 LanceDB/\n\t\t\t// 拉起重依赖; 装配完成点还有第二道检查兜住模型下载窗口。\n\t\t\tif (capabilityDisposed) return failEnablingDisposed();\n\t\t\t// 加载: transformers/lancedb 的动态 import 都在这些模块内部, 这里只做\n\t\t\t// 模块级懒加载, 保持未触发会话零重依赖。进度周期性落一行 (下载可达\n\t\t\t// 数百 MB), 完成后清除。\n\t\t\tconst progressTimer = setInterval(() => {\n\t\t\t\tif (!capabilityDisposed) logger?.info(\"memory enabling still in progress (downloading/loading models)\");\n\t\t\t}, ENABLING_PROGRESS_LOG_INTERVAL_MS);\n\t\t\tif (typeof progressTimer === \"object\" && \"unref\" in progressTimer) progressTimer.unref();\n\t\t\tlet closeAcquired: (() => Promise<void>) | undefined;\n\t\t\tlet published = false;\n\t\t\ttry {\n\t\t\t\tconst [vectorIndexModule, embeddingModule, rerankerModule] = await Promise.all([\n\t\t\t\t\timport(\"./vector-index.ts\"),\n\t\t\t\t\timport(\"./embedding-provider.ts\"),\n\t\t\t\t\timport(\"./embedding-reranker.ts\"),\n\t\t\t\t]);\n\t\t\t\tif (capabilityDisposed) return failEnablingDisposed();\n\t\t\t\tconst index = await vectorIndexModule.createMemoryVectorIndex({\n\t\t\t\t\tdbPath: join(agentDir, \"memory\", VECTOR_DB_DIRNAME),\n\t\t\t\t\tdimensions: preset.dimensions,\n\t\t\t\t\t...(hostLancedbEntryPath === undefined ? {} : { moduleEntryPath: hostLancedbEntryPath }),\n\t\t\t\t\t// P5 残留守卫: 同 memoryId 不同 body 的写入被拒绝时上报一次; 拒绝本身在\n\t\t\t\t\t// 索引内生效 (先写入的原子排序信号不被跨域 id 复用覆盖)。\n\t\t\t\t\tonCollision: (collision) => {\n\t\t\t\t\t\tlogger?.warn(\n\t\t\t\t\t\t\t\"memory vector projection refused to overwrite a row whose memoryId belongs to a different atom (cross-domain id collision); the incoming atom stays reachable through the store lookup\",\n\t\t\t\t\t\t\t{ memoryId: collision.memoryId },\n\t\t\t\t\t\t);\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tlet indexClosePromise: Promise<void> | undefined;\n\t\t\t\tcloseAcquired = () => {\n\t\t\t\t\tindexClosePromise ??= closeResource(\"vector index\", () => index.close());\n\t\t\t\t\treturn indexClosePromise;\n\t\t\t\t};\n\t\t\t\tcloseOwnedLocalResources = closeAcquired;\n\t\t\t\tif (capabilityDisposed) return failEnablingDisposed();\n\t\t\t\tconst remoteHosts = remoteHostsForEnabling();\n\t\t\t\tconst channel: ActiveVectorChannelV1 = {\n\t\t\t\t\tembed: embeddingModule.createTransformersEmbeddingProvider({\n\t\t\t\t\t\tmodelId: preset.embeddingModelId,\n\t\t\t\t\t\tdimensions: preset.dimensions,\n\t\t\t\t\t\tcacheDir: modelCacheDir,\n\t\t\t\t\t\tremoteHosts,\n\t\t\t\t\t\t...(hostTransformersEntryPath === undefined ? {} : { moduleEntryPath: hostTransformersEntryPath }),\n\t\t\t\t\t\t...(enablingOverride?.embeddingLoadImpl === undefined\n\t\t\t\t\t\t\t? {}\n\t\t\t\t\t\t\t: { loadImpl: enablingOverride.embeddingLoadImpl }),\n\t\t\t\t\t}),\n\t\t\t\t\treranker: rerankerModule.createTransformersReranker({\n\t\t\t\t\t\tmodelId: VECTOR_RERANKER_MODEL_ID,\n\t\t\t\t\t\tcacheDir: modelCacheDir,\n\t\t\t\t\t\tremoteHosts,\n\t\t\t\t\t\t...(hostTransformersEntryPath === undefined ? {} : { moduleEntryPath: hostTransformersEntryPath }),\n\t\t\t\t\t\t...(enablingOverride?.rerankerLoadImpl === undefined\n\t\t\t\t\t\t\t? {}\n\t\t\t\t\t\t\t: { loadImpl: enablingOverride.rerankerLoadImpl }),\n\t\t\t\t\t}),\n\t\t\t\t\tindex,\n\t\t\t\t\tqueryPrefix: preset.queryPrefix,\n\t\t\t\t\tembeddingModelId: preset.embeddingModelId,\n\t\t\t\t};\n\t\t\t\tlet channelClosePromise: Promise<void> | undefined;\n\t\t\t\tcloseAcquired = () => {\n\t\t\t\t\tchannelClosePromise ??= closeLocalChannel(channel);\n\t\t\t\t\treturn channelClosePromise;\n\t\t\t\t};\n\t\t\t\tcloseOwnedLocalResources = closeAcquired;\n\t\t\t\t// 冒烟: embed + rerank 各一条 (同时完成两个模型的下载与加载) +\n\t\t\t\t// 投影档位比对。rerank 冒烟 2026-10-06 live E2E 补齐: reranker\n\t\t\t\t// 懒加载, 只 embed 的冒烟会让 \"ready\" 携带未下载的精排权重 —\n\t\t\t\t// 共享推理服务 (两项文件均前置检查、永不自主下载) 对该会话拒启,\n\t\t\t\t// \"fully usable\" 的自述与服务前置条件必须一致。\n\t\t\t\tawait channel.embed.embed([\"memory enabling smoke test\"]);\n\t\t\t\tif (capabilityDisposed) return failEnablingDisposed();\n\t\t\t\tif (channel.embed.modelId !== preset.embeddingModelId) {\n\t\t\t\t\treturn failEnabling(\n\t\t\t\t\t\t`smoke check failed: embedding modelId ${channel.embed.modelId} does not match the ${memoryMode} preset ${preset.embeddingModelId}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (channel.reranker !== undefined) {\n\t\t\t\t\tawait channel.reranker.rerank(\"memory enabling smoke test\", [\"memory enabling smoke test\"]);\n\t\t\t\t\tif (capabilityDisposed) return failEnablingDisposed();\n\t\t\t\t}\n\t\t\t\tconst storedModelId = await channel.index.getStoredModelId();\n\t\t\t\tif (!capabilityDisposed && storedModelId !== undefined && storedModelId !== preset.embeddingModelId) {\n\t\t\t\t\tlogger?.warn(\n\t\t\t\t\t\t`memory projection was built for ${storedModelId}, preset is ${preset.embeddingModelId}; startup reconciliation will rebuild it`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\t// dispose 竞态 (本地装配路径, 第二道, 兜住模型下载窗口): 不把索引句柄\n\t\t\t\t// 赋回引用——关闭刚打开的 LanceDB 并落结构化失败。\n\t\t\t\tif (capabilityDisposed) return failEnablingDisposed();\n\t\t\t\tvectorChannel = channel;\n\t\t\t\tpublished = true;\n\t\t\t\tvectorState = \"ready\";\n\t\t\t\tlogger?.info(`memory ready (mode=${memoryMode}, embedding=${preset.embeddingModelId})`);\n\t\t\t\tenablingSettled?.();\n\t\t\t\treturn channel;\n\t\t\t} catch (error) {\n\t\t\t\treturn failEnabling(\n\t\t\t\t\t`model load or smoke check failed (${error instanceof Error ? error.message : String(error)})`,\n\t\t\t\t);\n\t\t\t} finally {\n\t\t\t\tclearInterval(progressTimer);\n\t\t\t\tif (!published && closeAcquired !== undefined) {\n\t\t\t\t\tawait closeAcquired();\n\t\t\t\t\tif (closeOwnedLocalResources === closeAcquired) closeOwnedLocalResources = undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t})();\n\t\treturn vectorInitPromise;\n\t};\n\n\t// ---- 征询门执行面 (2026-10-05 用户裁决「首次使用征询、拒绝/失败可跳过」) ----\n\t// memory_enable 是 consent-required / failed 态的唯一下载入口: consentGranted\n\t// 只在这里置位, recall/auto-recall 永不触发下载。decline 同时持久化\n\t// (writeMemoryConsentDeclined), 只抑制默认档——用户显式设置 memory.mode 后\n\t// 下次启用会在首次使用时再次走到征询门。\n\t// ---- 记忆模型下载控制面 (2026-10-05 流程裁决「后台预热、不阻塞提问」) ----\n\t// 生产入口 (交互模式会话绑定后) 经公共工具面调用 memory_enable download\n\t// 触发后台预热; 命令面 /memory off|retry 是用户的直接出口。两处共用同一对\n\t// 闭包; decline 持久化只抑制默认档。\n\tconst declineMemory = (): { status: \"completed\"; message: string } => {\n\t\t// 总是落盘 (幂等写): 升降档会清理文件里的拒绝标记, 之后再次 off 必须\n\t\t// 重新写入——不能用内存 flag 跳过持久化。\n\t\tconst firstDecline = !consentDeclined;\n\t\tconsentDeclined = true;\n\t\twriteMemoryConsentDeclined(agentDir);\n\t\tif (firstDecline) {\n\t\t\tlogger?.info(\"memory disabled by user decision (persisted to the memory agent-dir config)\");\n\t\t}\n\t\treturn {\n\t\t\tstatus: \"completed\",\n\t\t\tmessage:\n\t\t\t\t\"memory disabled for this machine (persisted). Set memory.mode (light|full) in settings.json and restart the session to re-enable\",\n\t\t};\n\t};\n\tconst downloadMemory = async (): Promise<\n\t\t| { status: \"completed\"; message: string }\n\t\t| { status: \"failed\"; message: string; actions?: readonly string[]; next?: string }\n\t> => {\n\t\tif (consentDeclined) {\n\t\t\treturn {\n\t\t\t\tstatus: \"failed\",\n\t\t\t\tmessage:\n\t\t\t\t\t\"memory was declined on this machine — set memory.mode (light|full) in settings.json and restart the session to re-enable\",\n\t\t\t};\n\t\t}\n\t\tconsentGranted = true;\n\t\tif (vectorState === \"failed\" || vectorState === \"consent-required\") {\n\t\t\tvectorState = \"enabling\";\n\t\t\tenablingFailure = undefined;\n\t\t\tvectorInitPromise = undefined;\n\t\t}\n\t\tconst channel = await vectorEnsure();\n\t\tif (channel === undefined) {\n\t\t\tconst failure = enablingFailure ?? {\n\t\t\t\treason: `memory enabling did not complete (state=${vectorState})`,\n\t\t\t\tactions: [] as const,\n\t\t\t};\n\t\t\treturn {\n\t\t\t\tstatus: \"failed\",\n\t\t\t\tmessage: `memory enabling failed: ${failure.reason}`,\n\t\t\t\tactions: failure.actions,\n\t\t\t\tnext: 'Tell the user the download failed and ask whether to skip memory (call memory_enable with action \"decline\" or /memory off — both persist off) or fix the environment and retry (/memory retry)',\n\t\t\t};\n\t\t}\n\t\t// 就绪: 补跑启动对账, 把预热期间写入的 ledger 记忆补进向量投影。\n\t\tresetReconcile();\n\t\treconcileOnce();\n\t\treturn { status: \"completed\", message: \"memory models ready — the memory family is fully usable\" };\n\t};\n\n\t// 会话切换重绑/插件卸载的共享资源释放 (TUI 每次会话切换都重走装配, 不释放\n\t// 即每次泄漏一条 IPC 连接: 服务端 connections>0 抑制空闲自杀, 嵌入方进程因\n\t// socket 未关无法自然退出)。清引用先行: close 的错误经独立 stderr 诊断, 且\n\t// 二次调用因引用已空自然 no-op。服务路径与本地路径互斥 (服务路径的 index\n\t// 归服务进程持有, 客户端只断连; 本地路径才关 LanceDB 句柄)。\n\t// capabilityDisposed 是 teardown 与在途 enabling 的竞态闩锁: teardown 之后\n\t// 才完成的装配在成功分支让位 (见 vectorEnsure 的 failEnablingDisposed),\n\t// 不复活无人关闭的连接/句柄。\n\tlet capabilityDisposed = false;\n\tconst capabilityTeardown = (): void => {\n\t\tcapabilityDisposed = true;\n\t\tif (closeOwnedLocalResources !== undefined) {\n\t\t\tconst close = closeOwnedLocalResources;\n\t\t\tcloseOwnedLocalResources = undefined;\n\t\t\tvectorChannel = undefined;\n\t\t\tvoid close();\n\t\t\treturn;\n\t\t}\n\t\tif (inferenceClient !== undefined) {\n\t\t\tconst client = inferenceClient;\n\t\t\tinferenceClient = undefined;\n\t\t\tvectorChannel = undefined;\n\t\t\tvoid closeResource(\"inference client\", () => client.close());\n\t\t\treturn;\n\t\t}\n\t\tif (vectorChannel !== undefined) {\n\t\t\tconst channel = vectorChannel;\n\t\t\tvectorChannel = undefined;\n\t\t\tvoid closeLocalChannel(channel);\n\t\t}\n\t};\n\n\treturn {\n\t\tstate: (): \"off\" | MemoryCapabilityStateV1 => (consentDeclined ? \"off\" : vectorState),\n\t\trawState: (): MemoryCapabilityStateV1 => vectorState,\n\t\tenabled: vectorEnabled,\n\t\treadyChannel: (): ActiveVectorChannelV1 | undefined => vectorChannel,\n\t\tisDisposed: (): boolean => capabilityDisposed,\n\t\tdeclined: (): boolean => consentDeclined,\n\t\tclearDeclined: (): void => {\n\t\t\tconsentDeclined = false;\n\t\t},\n\t\tconsentAsked: (): boolean => consentAsked,\n\t\tmarkConsentAsked: (): void => {\n\t\t\tconsentAsked = true;\n\t\t},\n\t\tprimeConsentGate,\n\t\tconsentAsk: (): MemoryConsentAskV1 | undefined =>\n\t\t\tvectorState === \"consent-required\" && consentNeededInfo !== undefined\n\t\t\t\t? { message: consentAskMessage(), actions: consentAskActions(), block: consentAskBlock() }\n\t\t\t\t: undefined,\n\t\twarming: (): boolean => vectorState === \"enabling\" && vectorInitPromise !== undefined && !consentDeclined,\n\t\tfailure: (): MemoryEnablingFailureV1 | undefined => enablingFailure,\n\t\tmarkDegraded: (): void => {\n\t\t\tvectorState = \"degraded\";\n\t\t},\n\t\trecoverDegraded: (): void => {\n\t\t\tif (vectorState === \"degraded\") vectorState = \"ready\";\n\t\t},\n\t\tensure: vectorEnsure,\n\t\tenablingOutcome: async (): Promise<\"ready\" | MemoryEnablingFailureV1> => {\n\t\t\tif (vectorState === \"enabling\") void vectorEnsure();\n\t\t\tawait enablingSettledPromise;\n\t\t\treturn enablingFailure ?? \"ready\";\n\t\t},\n\t\tdecline: declineMemory,\n\t\tdownload: downloadMemory,\n\t\tdispose: capabilityTeardown,\n\t};\n}\n"]}
|
|
@@ -354,6 +354,11 @@ export function createMemoryVectorChannel(deps) {
|
|
|
354
354
|
dbPath: join(agentDir, "memory", VECTOR_DB_DIRNAME),
|
|
355
355
|
dimensions: preset.dimensions,
|
|
356
356
|
...(hostLancedbEntryPath === undefined ? {} : { moduleEntryPath: hostLancedbEntryPath }),
|
|
357
|
+
// P5 残留守卫: 同 memoryId 不同 body 的写入被拒绝时上报一次; 拒绝本身在
|
|
358
|
+
// 索引内生效 (先写入的原子排序信号不被跨域 id 复用覆盖)。
|
|
359
|
+
onCollision: (collision) => {
|
|
360
|
+
logger?.warn("memory vector projection refused to overwrite a row whose memoryId belongs to a different atom (cross-domain id collision); the incoming atom stays reachable through the store lookup", { memoryId: collision.memoryId });
|
|
361
|
+
},
|
|
357
362
|
});
|
|
358
363
|
let indexClosePromise;
|
|
359
364
|
closeAcquired = () => {
|