qlogicagent 2.19.12 → 2.19.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent.js +26 -25
- package/dist/cli.js +1 -1
- package/dist/host-contract.js +1 -1
- package/dist/index.js +364 -360
- package/dist/orchestration.js +7 -7
- package/dist/project-memory-host.js +10 -10
- package/dist/protocol.js +1 -1
- package/dist/types/cli/handlers/memory-handler.d.ts +4 -35
- package/dist/types/cli/rpc-registry.d.ts +4 -4
- package/dist/types/cli/task-distillation-coordinator.d.ts +48 -11
- package/dist/types/contracts/error-category.d.ts +11 -0
- package/dist/types/contracts/hooks.d.ts +2 -0
- package/dist/types/host-contract/index.d.ts +3 -3
- package/dist/types/orchestration/error-handling/error-classification.d.ts +2 -2
- package/dist/types/runtime/execution/dream-agent.d.ts +11 -1
- package/dist/types/runtime/hooks/memory-hooks.d.ts +10 -3
- package/dist/types/runtime/infra/llmrouter-managed-inference.d.ts +1 -1
- package/dist/types/runtime/memory/find-relevant-memories.d.ts +0 -44
- package/dist/types/runtime/ports/memory-provider.d.ts +15 -2
- package/dist/types/skills/memory/host-memory-provider.d.ts +43 -0
- package/dist/types/skills/memory/task-distillation.d.ts +29 -19
- package/package.json +2 -2
- package/dist/types/runtime/infra/codex-llmrouter-compat-proxy.d.ts +0 -4
- package/dist/types/skills/memory/local-store-records.d.ts +0 -206
- package/dist/types/skills/memory/local-store.d.ts +0 -376
- package/dist/types/skills/memory/memory-attachment-store.d.ts +0 -62
- package/dist/types/skills/memory/memory-consolidation.d.ts +0 -64
- package/dist/types/skills/memory/memory-db-path.d.ts +0 -13
- package/dist/types/skills/memory/proposal-consumer.d.ts +0 -51
- package/dist/types/skills/memory/sqlite-memory-mappers.d.ts +0 -7
- package/dist/types/skills/memory/sqlite-memory-schema.d.ts +0 -11
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Agent-resident memory brain-compute handlers. Handles: memory.propose (LLM candidate
|
|
3
|
+
* extraction) and memory.search (hybrid retrieval with a memdir fallback). The store/library
|
|
4
|
+
* and memdir file-face methods are Runtime Host-native (gateway MemoryProfileService + memdir
|
|
5
|
+
* file face) and were removed here — see rpc-registry.memory-cut.test.ts.
|
|
4
6
|
*/
|
|
5
7
|
import { type AgentRpcError, type AgentRpcRequest } from "../../protocol/wire/index.js";
|
|
6
8
|
import type { MemoryHandlerProvider, ProjectMemoryStore, ProjectMemoryStoreFactory } from "../../runtime/ports/index.js";
|
|
@@ -29,39 +31,6 @@ export interface MemoryHandlerHost {
|
|
|
29
31
|
sendNotification(method: string, params: Record<string, unknown>): void;
|
|
30
32
|
sendResponse(id: string | number, result?: unknown, error?: AgentRpcError): void;
|
|
31
33
|
}
|
|
32
|
-
export declare function handleMemoryList(this: MemoryHandlerHost, msg: AgentRpcRequest): Promise<void>;
|
|
33
|
-
/** memory.list-files: returns actual topic files from memdir. */
|
|
34
|
-
export declare function handleMemoryListFiles(this: MemoryHandlerHost, msg: AgentRpcRequest): Promise<void>;
|
|
35
|
-
/**
|
|
36
|
-
* memory.proposals: pending factual proposals (implicit-extract / feedback /
|
|
37
|
-
* dream) awaiting corroboration — the candidate surface of the proposal
|
|
38
|
-
* consumer. action=list (default) returns them; action=confirm/dismiss
|
|
39
|
-
* resolves one (confirm commits with manual authority; dismiss rejects).
|
|
40
|
-
*/
|
|
41
|
-
export declare function handleMemoryProposals(this: MemoryHandlerHost, msg: AgentRpcRequest): Promise<void>;
|
|
42
|
-
/**
|
|
43
|
-
* memory.atlas: returns full L2 vector-memory records (wire-safe, no embedding
|
|
44
|
-
* blob) plus category roll-ups, for the 3D memory atlas visualization.
|
|
45
|
-
*/
|
|
46
|
-
export declare function handleMemoryAtlas(this: MemoryHandlerHost, msg: AgentRpcRequest): Promise<void>;
|
|
47
|
-
/**
|
|
48
|
-
* memory.activity: daily activity counts + highlights over the recent window,
|
|
49
|
-
* powering the atlas timeline ticks and the "memory digest" panel.
|
|
50
|
-
*/
|
|
51
|
-
export declare function handleMemoryActivity(this: MemoryHandlerHost, msg: AgentRpcRequest): Promise<void>;
|
|
52
34
|
export declare function handleMemoryPropose(this: MemoryHandlerHost, msg: AgentRpcRequest): Promise<void>;
|
|
53
|
-
export declare function handleMemoryConsolidate(this: MemoryHandlerHost, msg: AgentRpcRequest): Promise<void>;
|
|
54
|
-
export declare function handleMemoryRead(this: MemoryHandlerHost, msg: AgentRpcRequest): Promise<void>;
|
|
55
|
-
export declare function handleMemoryWrite(this: MemoryHandlerHost, msg: AgentRpcRequest): Promise<void>;
|
|
56
35
|
export declare function handleMemorySearch(this: MemoryHandlerHost, msg: AgentRpcRequest): Promise<void>;
|
|
57
|
-
export declare function handleMemoryDelete(this: MemoryHandlerHost, msg: AgentRpcRequest): Promise<void>;
|
|
58
|
-
export declare function handleMemoryUpdate(this: MemoryHandlerHost, msg: AgentRpcRequest): Promise<void>;
|
|
59
|
-
/**
|
|
60
|
-
* memory.attachment.adopt: persist an uploaded attachment into the long-term-memory
|
|
61
|
-
* attachment store from a transient source URL (the gateway's temp MediaStore).
|
|
62
|
-
* The attachment is an orphan until linked to a memory at consolidate time.
|
|
63
|
-
*/
|
|
64
|
-
export declare function handleMemoryAttachmentAdopt(this: MemoryHandlerHost, msg: AgentRpcRequest): Promise<void>;
|
|
65
|
-
/** memory.attachment.locate: resolve an attachment id to its on-disk path (for serving). */
|
|
66
|
-
export declare function handleMemoryAttachmentLocate(this: MemoryHandlerHost, msg: AgentRpcRequest): Promise<void>;
|
|
67
36
|
export {};
|
|
@@ -32,10 +32,10 @@ export type RpcMethodHandler = (msg: AgentRpcRequest) => void | Promise<void>;
|
|
|
32
32
|
*/
|
|
33
33
|
export interface TaskDistillationRpcSurface {
|
|
34
34
|
runPass(reason: "manual"): Promise<object>;
|
|
35
|
-
listProposals(): unknown[]
|
|
36
|
-
dismissProposal(id: string): boolean
|
|
37
|
-
acknowledgeProposal(id: string): boolean
|
|
38
|
-
getMetrics(): object
|
|
35
|
+
listProposals(): Promise<unknown[]>;
|
|
36
|
+
dismissProposal(id: string): Promise<boolean>;
|
|
37
|
+
acknowledgeProposal(id: string): Promise<boolean>;
|
|
38
|
+
getMetrics(): Promise<object>;
|
|
39
39
|
promote(id: string): Promise<object>;
|
|
40
40
|
demote(id: string): Promise<object>;
|
|
41
41
|
}
|
|
@@ -7,8 +7,10 @@
|
|
|
7
7
|
* LLM 摘要(dream 同款小模型)失败时降级确定性模板 —— 蒸馏永不因模型不可用而丢样本。
|
|
8
8
|
* · 晋升(spec:唯一技能入口): accessCount ≥ 阈值且未被负反馈沉底 → system.activity 推荐。
|
|
9
9
|
*/
|
|
10
|
-
import { type PromotionMetrics, type CandidateStoreFile, type PromotionProposal } from "../skills/memory/task-distillation.js";
|
|
10
|
+
import { type PromotionMetrics, type CandidateStoreFile, type PromotionProposal, type ProcedureUsageStoreFile, type PromotionStoreFile } from "../skills/memory/task-distillation.js";
|
|
11
11
|
import type { HostCapabilityClient } from "../transport/host-capability-client.js";
|
|
12
|
+
/** [A4] addProcedure 落库回执分类(见 TaskDistillationDeps.addProcedure)。 */
|
|
13
|
+
export type AddProcedureOutcome = "created" | "merged" | "rejected" | "retryable-failure";
|
|
12
14
|
export interface TaskDistillationDeps {
|
|
13
15
|
profileMemoryDir: () => string;
|
|
14
16
|
/** Gateway-owned skill authority. Missing service is fatal; local skill-store fallback is forbidden. */
|
|
@@ -16,8 +18,12 @@ export interface TaskDistillationDeps {
|
|
|
16
18
|
/** 签名 embedding;null=不可用(候选照存但不参与聚类,宁严勿松)。
|
|
17
19
|
* B3(X7):number[](非 Float32Array)——host 模式下 embedText 结果跨 x/host.request JSON wire。 */
|
|
18
20
|
embed: (text: string) => Promise<number[] | null>;
|
|
19
|
-
/**
|
|
20
|
-
|
|
21
|
+
/** [A4] 落库回执四分类(由 ingestExtracted 的结构化 items 归并):
|
|
22
|
+
* created = 真实新落库 → 标 distilled + 发通知(只有它发);
|
|
23
|
+
* merged = 近重复合并/已入提案管道 —— 合法成功,标 distilled 不通知;
|
|
24
|
+
* rejected = 安全闸拒/冲突 —— 终态,候选标 rejected 不再重试;
|
|
25
|
+
* retryable-failure = RPC 抛错/环境未就绪 —— 候选保持 pending 等下轮。 */
|
|
26
|
+
addProcedure: (text: string, tags: string[]) => Promise<AddProcedureOutcome>;
|
|
21
27
|
/** 小模型摘要(dream 同款);null/失败 → 降级模板 */
|
|
22
28
|
llmExtract?: (prompt: string) => Promise<string | null>;
|
|
23
29
|
/** 晋升扫描数据源:全部 distilled 条目 {id,text,accessCount,importance} */
|
|
@@ -27,8 +33,37 @@ export interface TaskDistillationDeps {
|
|
|
27
33
|
accessCount: number;
|
|
28
34
|
importance: number;
|
|
29
35
|
}>>;
|
|
30
|
-
/** V3 promote/demote:archive(技能接棒)/unarchive(降格回归)。B3(X7)异步化:16 面 proxy 方法。
|
|
36
|
+
/** V3 promote/demote:archive(技能接棒)/unarchive(降格回归)。B3(X7)异步化:16 面 proxy 方法。
|
|
37
|
+
* [A10] 后仅 demote 侧消费(promote 三步已收归 Host saga)。 */
|
|
31
38
|
setMemoryArchived: (id: string, archived: boolean) => Promise<boolean>;
|
|
39
|
+
/** [A10] 升格窄 Saga(Host 协调,memory proxy promoteDistilledProcedure):
|
|
40
|
+
* create+verify → archive → proposal accepted,幂等/补偿/续跑在 Host;
|
|
41
|
+
* 大脑传入推理产物(渲染并校验过的 SKILL.md 全文、确定性 skillName、标题/计数/auto)。 */
|
|
42
|
+
promoteProcedure: (input: {
|
|
43
|
+
procedureId: string;
|
|
44
|
+
skillName: string;
|
|
45
|
+
content: string;
|
|
46
|
+
title: string;
|
|
47
|
+
accessCount: number;
|
|
48
|
+
auto: boolean;
|
|
49
|
+
}) => Promise<{
|
|
50
|
+
outcome: "completed" | "already-completed";
|
|
51
|
+
skillName: string;
|
|
52
|
+
steps: {
|
|
53
|
+
skillCreated: boolean;
|
|
54
|
+
memoryArchived: boolean;
|
|
55
|
+
proposalAccepted: boolean;
|
|
56
|
+
};
|
|
57
|
+
}>;
|
|
58
|
+
/** [X7] procedure-usage.json 读:store-owner 归 gateway,经 x/host proxy(自动档跨-session 数据源)。 */
|
|
59
|
+
readProcedureUsage: () => Promise<ProcedureUsageStoreFile>;
|
|
60
|
+
/** [X7] task-distill-candidates.json 读/写:store-owner 归 gateway;大脑侧裁剪(capCandidateStore)后经 proxy 写。 */
|
|
61
|
+
readCandidates: () => Promise<CandidateStoreFile>;
|
|
62
|
+
writeCandidates: (store: CandidateStoreFile) => Promise<void>;
|
|
63
|
+
/** [X7] promotion-proposals.json 读/写:晋升生命周期大脑逻辑留 qla,store-owner 归 gateway
|
|
64
|
+
* (gateway ActionSurface 也读同一文件;写者唯一=gateway 经此 proxy)。 */
|
|
65
|
+
readProposals: () => Promise<PromotionStoreFile>;
|
|
66
|
+
writeProposals: (store: PromotionStoreFile) => Promise<void>;
|
|
32
67
|
sendNotification: (method: string, params: Record<string, unknown>) => void;
|
|
33
68
|
log: (message: string) => void;
|
|
34
69
|
}
|
|
@@ -59,14 +94,17 @@ export declare class TaskDistillationCoordinator {
|
|
|
59
94
|
/** 晋升扫描(spec:技能的唯一产生入口):复用达标且未被负反馈沉底 → 写持久提议。
|
|
60
95
|
* V3.1:提议是持久待办(promotion-proposals.json),UI 双入口消费;activity 仅作日志。 */
|
|
61
96
|
private scanPromotions;
|
|
62
|
-
listProposals(): PromotionProposal[]
|
|
97
|
+
listProposals(): Promise<PromotionProposal[]>;
|
|
63
98
|
/** V3.2 仪表(接受率/降格率/自动档解锁态);技能激活计数由 skill-lifecycle useCount 承载。 */
|
|
64
|
-
getMetrics(): PromotionMetrics
|
|
99
|
+
getMetrics(): Promise<PromotionMetrics>;
|
|
65
100
|
/** 自动升格开场确认卡「知道了」。 */
|
|
66
|
-
acknowledgeProposal(procedureId: string): boolean
|
|
67
|
-
dismissProposal(procedureId: string): boolean
|
|
68
|
-
/**
|
|
69
|
-
*
|
|
101
|
+
acknowledgeProposal(procedureId: string): Promise<boolean>;
|
|
102
|
+
dismissProposal(procedureId: string): Promise<boolean>;
|
|
103
|
+
/** 升格:大脑只做推理半程(找配方→渲染 SKILL.md→写盘前校验→确定性命名),
|
|
104
|
+
* [A10] 三步执行(create+verify→archive→proposal accepted)收归 Host 窄 Saga ——
|
|
105
|
+
* 它横跨 Capability/Memory 两个 Host 存储,幂等(procedureId+确定性 skillName)、
|
|
106
|
+
* 逐步补偿、崩溃续跑都在 Host;旧实现 create 之后的两步无 catch 无补偿,
|
|
107
|
+
* 该窗口失败即双向死角(重跑撞 already exists,demote 缺 skillName 找不到目标)。 */
|
|
70
108
|
promote(procedureId: string, opts?: {
|
|
71
109
|
auto?: boolean;
|
|
72
110
|
}): Promise<{
|
|
@@ -81,4 +119,3 @@ export declare class TaskDistillationCoordinator {
|
|
|
81
119
|
}>;
|
|
82
120
|
private renderSkillMarkdown;
|
|
83
121
|
}
|
|
84
|
-
export declare function buildCandidateStoreSnapshot(profileMemoryDir: string): CandidateStoreFile;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Every category classifyError can produce. The ErrorCategory type is
|
|
2
|
+
* derived from this array, so the runtime guard below can never drift
|
|
3
|
+
* from the type union. */
|
|
4
|
+
export declare const ERROR_CATEGORIES: readonly ["RETRYABLE_TRANSIENT", "RETRYABLE_DEGRADED", "NON_RETRYABLE_AUTH", "NON_RETRYABLE_CONTENT", "NON_RETRYABLE_QUOTA", "TOOL_EXECUTION_FAILED"];
|
|
5
|
+
export type ErrorCategory = (typeof ERROR_CATEGORIES)[number];
|
|
6
|
+
/** Runtime guard: is this string one of classifyError's categories?
|
|
7
|
+
* turn.failed also carries codes from OUTSIDE this vocabulary (stream codes
|
|
8
|
+
* like PROVIDER_STREAM_ERROR / LLM_STREAM_TIMEOUT / PROMPT_TOO_LONG, or
|
|
9
|
+
* ABORTED) — consumers use this to tell them apart. */
|
|
10
|
+
export declare function isErrorCategory(value: unknown): value is ErrorCategory;
|
|
11
|
+
export declare function isRetryableCategory(category: ErrorCategory): boolean;
|
|
@@ -113,6 +113,7 @@ export interface HookContextMap {
|
|
|
113
113
|
query?: string;
|
|
114
114
|
recalledMemories?: Array<{
|
|
115
115
|
text: string;
|
|
116
|
+
id?: string;
|
|
116
117
|
score?: number;
|
|
117
118
|
category?: string | null;
|
|
118
119
|
source?: string;
|
|
@@ -126,6 +127,7 @@ export interface HookContextMap {
|
|
|
126
127
|
recalledSummaries?: string[];
|
|
127
128
|
injectedCount?: number;
|
|
128
129
|
droppedCount?: number;
|
|
130
|
+
injectedMemoryIds?: string[];
|
|
129
131
|
};
|
|
130
132
|
"subagent.started": HookSubagentContext;
|
|
131
133
|
"subagent.stopped": HookSubagentContext;
|
|
@@ -803,7 +803,7 @@ export interface HostNotificationSink {
|
|
|
803
803
|
* [X7] qlogicagent 大脑经 x/host.request 可调用的 memory proxy 精确方法面。
|
|
804
804
|
* gateway 白名单与 qla HostMemoryProvider 都必须直接消费此常量,禁止两仓手抄后漂移。
|
|
805
805
|
*/
|
|
806
|
-
export declare const HOST_MEMORY_PROXY_METHODS: readonly ["search", "addText", "embedText", "ingestExtracted", "proposeExtracted", "consumePendingProposals", "feedback", "findRelatedEvents", "synthesizeTimeline", "getActivitySummary", "getAllProfiles", "setProfile", "getAtlas", "setMemoryArchived", "triggerDecay", "resolveConflicts"];
|
|
806
|
+
export declare const HOST_MEMORY_PROXY_METHODS: readonly ["search", "addText", "embedText", "ingestExtracted", "proposeExtracted", "consumePendingProposals", "feedback", "findRelatedEvents", "synthesizeTimeline", "getActivitySummary", "getAllProfiles", "setProfile", "getAtlas", "setMemoryArchived", "triggerDecay", "resolveConflicts", "readProcedureUsage", "writeProcedureUsage", "readDistillCandidates", "writeDistillCandidates", "readPromotionProposals", "writePromotionProposals", "listActiveMemoriesByTag", "promoteDistilledProcedure", "recordInjectedAccess"];
|
|
807
807
|
export type HostMemoryProxyMethod = (typeof HOST_MEMORY_PROXY_METHODS)[number];
|
|
808
808
|
/** Project-scoped Markdown memory face. Gateway resolves cwd/project from the supervised caller. */
|
|
809
809
|
export declare const HOST_PROJECT_MEMORY_PROXY_METHODS: readonly ["initialize", "getIndex", "addToIndex", "replaceInIndex", "removeFromIndex", "createFile", "writeFile", "readFile", "deleteFile", "listFiles", "searchLocal"];
|
|
@@ -1697,8 +1697,8 @@ export declare function supportsHostRequestService(capability: unknown, service:
|
|
|
1697
1697
|
/**
|
|
1698
1698
|
* [X7 检索单源] FTS 分词 —— memories.db 的写侧(text_seg 列)与查侧(FTS 查询)**必须同一实现**,
|
|
1699
1699
|
* 漂移即召回静默清零(fts-segment.ts 文件头铁律)。B3 后唯一写者=gateway(runtime 仓),故经本契约包共享
|
|
1700
|
-
* 单一实现(先例:deriveProjectId 同款 re-export);qla 侧
|
|
1701
|
-
* 引用同一份,零复刻。纯函数零依赖(仅正则)。
|
|
1700
|
+
* 单一实现(先例:deriveProjectId 同款 re-export);qla 侧(今天是 memdir 的 FTS 面)与 gateway
|
|
1701
|
+
* memory-profile-sqlite 引用同一份,零复刻。纯函数零依赖(仅正则)。
|
|
1702
1702
|
* 实现体落在本契约模块内(src/host-contract/fts-segment.ts)而非 re-export skills——host-contract 是
|
|
1703
1703
|
* leaf(acp-protocol.ts 文件头依赖此不变式;反向 re-export 曾闭合 host-contract→skills→runtime→
|
|
1704
1704
|
* protocol→host-contract 模块环,check-architecture-boundaries top-level-cycles 抓出)。
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
|
|
1
|
+
import type { ErrorCategory } from "../../contracts/error-category.js";
|
|
2
|
+
export { ERROR_CATEGORIES, isErrorCategory, isRetryableCategory, type ErrorCategory, } from "../../contracts/error-category.js";
|
|
2
3
|
export declare function classifyError(status: number | undefined, message?: string): ErrorCategory;
|
|
3
|
-
export declare function isRetryableCategory(category: ErrorCategory): boolean;
|
|
@@ -69,10 +69,20 @@ export interface DreamRunResult {
|
|
|
69
69
|
* Allowed:
|
|
70
70
|
* - read_file, grep, glob, search — unrestricted read-only tools
|
|
71
71
|
* - bash — only read-only commands (ls, grep, cat, find, stat, wc, head, tail)
|
|
72
|
-
* -
|
|
72
|
+
* - memory — the memdir writer (routes through the gateway projectMemory proxy)
|
|
73
|
+
* - raw write/edit/patch — denied (memory writes must go through the `memory` tool)
|
|
73
74
|
* - Everything else — denied
|
|
74
75
|
*/
|
|
75
76
|
export declare function canUseDreamTool(memoryRoot: string, restriction: DreamToolRestriction): DreamToolVerdict;
|
|
77
|
+
/**
|
|
78
|
+
* Canonical catalog tool names advertised to the dream sub-agent. This trims the
|
|
79
|
+
* full manifest (dozens of irrelevant tools) down to what dream actually uses.
|
|
80
|
+
* Every name here MUST be allowed by canUseDreamTool — raw write/edit/patch are
|
|
81
|
+
* intentionally absent (canUseDreamTool hard-denies them); the `memory` tool is
|
|
82
|
+
* the sole sanctioned memdir writer and routes through the gateway proxy
|
|
83
|
+
* (dream-memdir-migration).
|
|
84
|
+
*/
|
|
85
|
+
export declare const DREAM_ALLOWED_TOOLS: Set<string>;
|
|
76
86
|
/**
|
|
77
87
|
* Build the 4-phase memory consolidation prompt.
|
|
78
88
|
*
|
|
@@ -37,10 +37,16 @@ export interface MemoryHooksDeps {
|
|
|
37
37
|
profileMemoryDir?: () => string;
|
|
38
38
|
/** V3.2: tag marking a distilled procedure memory (recall filter). cli injects so runtime never imports skills. */
|
|
39
39
|
procedureTag?: string;
|
|
40
|
-
/** V3.2: record distilled procedures
|
|
40
|
+
/** V3.2: record distilled procedures whose text reached the prompt (positive reuse signal). cli-injected.
|
|
41
|
+
* [A7] Called from memory.after_recall with the post-cap injected subset — NOT from
|
|
42
|
+
* before_recall: search hits the model never saw must not build promotion evidence. */
|
|
41
43
|
recordProcedureRecalls?: (procedureIds: string[], sessionId: string) => void;
|
|
42
44
|
/** V3.2: record negative feedback against distilled procedures (failed turn). cli-injected. */
|
|
43
45
|
recordProcedureNegatives?: (procedureIds: string[]) => void;
|
|
46
|
+
/** [A7] Host-side access ledger (memories.access_count/last_accessed_at): report the L2 ids
|
|
47
|
+
* actually injected this turn. cli-injected (fire-and-forget; Host stays the single writer —
|
|
48
|
+
* search() no longer counts hits, so skipping this call means the memory goes uncounted). */
|
|
49
|
+
recordInjectedAccess?: (memoryIds: string[]) => void;
|
|
44
50
|
}
|
|
45
51
|
/** Session-scoped state for dedup and byte budget (CC parity). */
|
|
46
52
|
export interface MemoryPrefetchState {
|
|
@@ -57,8 +63,9 @@ export declare function createMemoryPrefetchState(): MemoryPrefetchState;
|
|
|
57
63
|
* Register memory lifecycle hooks on the HookRegistry.
|
|
58
64
|
*
|
|
59
65
|
* Hook points wired:
|
|
60
|
-
* - memory.before_recall: prefetch context from qmemory (query-based)
|
|
61
|
-
*
|
|
66
|
+
* - memory.before_recall: prefetch context from qmemory (query-based); NO reuse
|
|
67
|
+
* accounting here ([A7]: retrieval hits the model never saw are not evidence)
|
|
68
|
+
* - memory.after_recall: reuse accounting off the post-cap injected ids + log
|
|
62
69
|
*
|
|
63
70
|
* CC parity additions:
|
|
64
71
|
* - LRU dedup via surfacedPaths (filterDuplicateMemoryAttachments)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ConfigPort } from "../ports/index.js";
|
|
2
2
|
export interface ManagedInferenceRequest {
|
|
3
|
-
path: "/v1/models" | "/v1/files" | `/v1/files/${string}` | "/v1/cad/plan-grants";
|
|
3
|
+
path: "/v1/models" | "/v1/files" | `/v1/files/${string}` | "/v1/cad/plan-grants" | "/v1/solidworks/plan-grants";
|
|
4
4
|
method: "GET" | "POST" | "DELETE";
|
|
5
5
|
contentType?: string;
|
|
6
6
|
body?: AsyncIterable<Uint8Array>;
|
|
@@ -1,36 +1,9 @@
|
|
|
1
1
|
export declare const RELEVANT_MEMORIES_CONFIG: {
|
|
2
|
-
/** Max topic files to consider during scan. */
|
|
3
|
-
readonly MAX_SCAN_FILES: 100;
|
|
4
2
|
/** Max files to surface per turn. */
|
|
5
3
|
readonly MAX_SELECTED: 5;
|
|
6
4
|
/** Max bytes per surfaced file (CC: 4096). */
|
|
7
5
|
readonly MAX_FILE_BYTES: 4096;
|
|
8
|
-
/** Max total bytes for all surfaced files combined. */
|
|
9
|
-
readonly MAX_TOTAL_BYTES: number;
|
|
10
|
-
/** Minimum score to be selected (0.0-1.0). */
|
|
11
|
-
readonly MIN_SCORE: 0.2;
|
|
12
|
-
/** Lines to read for header/description extraction. */
|
|
13
|
-
readonly HEADER_LINES: 10;
|
|
14
|
-
/** Recency boost: files modified within this many days get a bonus. */
|
|
15
|
-
readonly RECENCY_DAYS: 7;
|
|
16
|
-
/** Recency boost amount. */
|
|
17
|
-
readonly RECENCY_BOOST: 0.15;
|
|
18
6
|
};
|
|
19
|
-
/** Scanned memory file header (CC MemoryHeader parity). */
|
|
20
|
-
export interface MemoryFileHeader {
|
|
21
|
-
/** Filename (e.g. "lesson-docker.md") */
|
|
22
|
-
filename: string;
|
|
23
|
-
/** Absolute path */
|
|
24
|
-
filePath: string;
|
|
25
|
-
/** Last modified timestamp (ms since epoch) */
|
|
26
|
-
mtimeMs: number;
|
|
27
|
-
/** File size in bytes */
|
|
28
|
-
sizeBytes: number;
|
|
29
|
-
/** Description extracted from first non-heading line */
|
|
30
|
-
description: string | null;
|
|
31
|
-
/** Category inferred from filename prefix */
|
|
32
|
-
category: string | null;
|
|
33
|
-
}
|
|
34
7
|
/** A selected relevant memory with content loaded. */
|
|
35
8
|
export interface RelevantMemory {
|
|
36
9
|
/** Filename */
|
|
@@ -46,23 +19,6 @@ export interface RelevantMemory {
|
|
|
46
19
|
/** Whether content was truncated */
|
|
47
20
|
truncated: boolean;
|
|
48
21
|
}
|
|
49
|
-
/**
|
|
50
|
-
* Find memory files relevant to a user query.
|
|
51
|
-
*
|
|
52
|
-
* CC parity: scans topic files, scores by keyword + filename + recency,
|
|
53
|
-
* selects top-N, loads content. No LLM needed (unlike CC's Sonnet call).
|
|
54
|
-
*
|
|
55
|
-
* @param query - User query text
|
|
56
|
-
* @param memoryDir - Root of the MEMDIR directory (~/.qlogicagent/memory/)
|
|
57
|
-
* @param alreadySurfaced - Paths already shown in prior turns (for dedup)
|
|
58
|
-
* @returns Relevant memories with content, sorted by score
|
|
59
|
-
*/
|
|
60
|
-
export declare function findRelevantMemories(query: string, memoryDir: string, alreadySurfaced?: ReadonlySet<string>): Promise<RelevantMemory[]>;
|
|
61
|
-
/**
|
|
62
|
-
* Scan memory directory for topic files (excludes INDEX.md).
|
|
63
|
-
* Returns headers sorted by modification time (newest first).
|
|
64
|
-
*/
|
|
65
|
-
export declare function scanMemoryHeaders(memoryDir: string): Promise<MemoryFileHeader[]>;
|
|
66
22
|
/**
|
|
67
23
|
* Format relevant memories as a single block for system prompt injection.
|
|
68
24
|
* CC parity: includes freshness header per file.
|
|
@@ -9,10 +9,15 @@ export interface MemorySearchOptions {
|
|
|
9
9
|
}
|
|
10
10
|
export interface MemorySearchResult {
|
|
11
11
|
blockId: string;
|
|
12
|
-
id
|
|
12
|
+
/** [A8] REQUIRED — host guarantees id === blockId on every search hit. When id/content
|
|
13
|
+
* were optional, the {blockId,text} ↔ {id,path,content} drift silently type-checked:
|
|
14
|
+
* the LRU dedup key was always "" (dedup dead) and byte accounting always 0. */
|
|
15
|
+
id: string;
|
|
16
|
+
/** Historical field: L2 hits never carry a path (kept optional for legacy readers). */
|
|
13
17
|
path?: string;
|
|
14
18
|
text: string;
|
|
15
|
-
content
|
|
19
|
+
/** [A8] REQUIRED — host guarantees content === text on every search hit (see id). */
|
|
20
|
+
content: string;
|
|
16
21
|
score: number;
|
|
17
22
|
source?: string;
|
|
18
23
|
metadata?: Record<string, unknown>;
|
|
@@ -47,6 +52,14 @@ export interface MemoryConsolidationWriteResult {
|
|
|
47
52
|
conflictsAdded?: number;
|
|
48
53
|
claimIds?: string[];
|
|
49
54
|
conflictIds?: string[];
|
|
55
|
+
/** [A4] ingestExtracted 结构化回执:与入参同序、含被安全闸拒的项;created 带真实落库
|
|
56
|
+
* memoryId;merged(近重复合并)是合法成功不是失败。可重试失败不在带内(RPC 抛错即
|
|
57
|
+
* 调用方的重试通道)。可选:同一类型还约束 observe/propose 返回体,消费处按缺失兜底。 */
|
|
58
|
+
items?: Array<{
|
|
59
|
+
text: string;
|
|
60
|
+
outcome: "created" | "merged" | "conflicted" | "pending" | "rejected";
|
|
61
|
+
memoryId?: string;
|
|
62
|
+
}>;
|
|
50
63
|
}
|
|
51
64
|
export interface MemoryProvider {
|
|
52
65
|
readonly providerId: string;
|
|
@@ -12,6 +12,9 @@
|
|
|
12
12
|
* search / addText / embedText / ingestExtracted / proposeExtracted / consumePendingProposals /
|
|
13
13
|
* feedback / findRelatedEvents / synthesizeTimeline / getActivitySummary / getAllProfiles /
|
|
14
14
|
* setProfile / getAtlas / setMemoryArchived / triggerDecay / resolveConflicts
|
|
15
|
+
* [A9] 追加 listActiveMemoriesByTag(晋升扫描全量列举;无窗/无 clamp/无上限)。
|
|
16
|
+
* [A10] 追加 promoteDistilledProcedure(升格窄 Saga;幂等/补偿/续跑在 Host)。
|
|
17
|
+
* [A7] 追加 recordInjectedAccess(注入后记账:search 去记账后 access_count 的唯一召回侧写点)。
|
|
15
18
|
*
|
|
16
19
|
* 面外方法 = fail-loud throw(护栏抓漏):gate 开时 UI RPC 面(atlas 富查询/update/attachments/
|
|
17
20
|
* proposals 消费等)由 gateway host-native 应答,**不该**再落到 qla 的 provider;到达此处 = 路由/
|
|
@@ -22,6 +25,7 @@
|
|
|
22
25
|
* 纪律:fail-loud;单轨(创建时刻一次选型,非每调用分支);零 mock。
|
|
23
26
|
*/
|
|
24
27
|
import type { HostRequestParams } from "../../host-contract/index.js";
|
|
28
|
+
import type { CandidateStoreFile, ProcedureUsageStoreFile, PromotionStoreFile } from "./task-distillation.js";
|
|
25
29
|
import type { MemoryActivitySummary, MemoryAtlasResult, MemoryConsolidationWriteResult, MemoryDreamRuntimeProvider, MemoryExtractionItem, MemoryHandlerProvider, MemoryIngestOptions, MemoryLearningSink, MemoryRuntimeHookProvider, MemorySearchOptions, MemorySearchResult, MemoryToolProvider } from "../../runtime/ports/index.js";
|
|
26
30
|
/**
|
|
27
31
|
* 最小转发口(结构化契约,由 coordinator-owned HostRequestClient 满足)。
|
|
@@ -107,6 +111,45 @@ export declare class HostMemoryProvider implements MemoryRuntimeHookProvider, Me
|
|
|
107
111
|
conflictsResolved: number;
|
|
108
112
|
claimsPromoted: number;
|
|
109
113
|
}>;
|
|
114
|
+
readProcedureUsage(): Promise<ProcedureUsageStoreFile>;
|
|
115
|
+
writeProcedureUsage(store: ProcedureUsageStoreFile): Promise<void>;
|
|
116
|
+
readDistillCandidates(): Promise<CandidateStoreFile>;
|
|
117
|
+
writeDistillCandidates(store: CandidateStoreFile): Promise<void>;
|
|
118
|
+
readPromotionProposals(): Promise<PromotionStoreFile>;
|
|
119
|
+
writePromotionProposals(store: PromotionStoreFile): Promise<void>;
|
|
120
|
+
/** [A9] 晋升扫描全量列举:owner 活跃(未归档)记忆中标签含 tag 的行,无时间窗、
|
|
121
|
+
* 无页 clamp、无静默上限,created_at 升序(getAtlas 分页会让老配方掉出扫描)。 */
|
|
122
|
+
listActiveMemoriesByTag(userId: string, tag: string): Promise<Array<{
|
|
123
|
+
id: string;
|
|
124
|
+
text: string;
|
|
125
|
+
accessCount: number;
|
|
126
|
+
importance: number;
|
|
127
|
+
}>>;
|
|
128
|
+
/** [A10] 升格窄 Saga(Host 协调):create+verify → archive → proposal accepted 三步
|
|
129
|
+
* 横跨 Capability/Memory 两个 Host 存储,幂等(procedureId+确定性 skillName)、逐步
|
|
130
|
+
* 补偿、崩溃续跑全在 Host;大脑只做推理与提案后单调此法。 */
|
|
131
|
+
promoteDistilledProcedure(input: {
|
|
132
|
+
procedureId: string;
|
|
133
|
+
skillName: string;
|
|
134
|
+
content: string;
|
|
135
|
+
title: string;
|
|
136
|
+
accessCount: number;
|
|
137
|
+
auto: boolean;
|
|
138
|
+
}): Promise<{
|
|
139
|
+
outcome: "completed" | "already-completed";
|
|
140
|
+
skillName: string;
|
|
141
|
+
steps: {
|
|
142
|
+
skillCreated: boolean;
|
|
143
|
+
memoryArchived: boolean;
|
|
144
|
+
proposalAccepted: boolean;
|
|
145
|
+
};
|
|
146
|
+
}>;
|
|
147
|
+
/** [A7] 注入后访问记账:上报本轮真实进 prompt 的 L2 id 集(memory.after_recall 的
|
|
148
|
+
* post-cap 名单)。Host 是 access_count/last_accessed_at 的唯一写者;search() 已不再
|
|
149
|
+
* 命中即记 —— 漏调此法只会低估复用,绝不虚增。 */
|
|
150
|
+
recordInjectedAccess(memoryIds: string[], userId: string): Promise<{
|
|
151
|
+
affected: number;
|
|
152
|
+
}>;
|
|
110
153
|
/** 本 provider 不持有 db 句柄/文件资源;close 为 no-op(shutdown 链 closeMemoryProviders 会调)。 */
|
|
111
154
|
close(): void;
|
|
112
155
|
remove(_memoryId: string): never;
|
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
* 成功闸不用 LLM 自评:正常终态 + 同 session 近窗内未被"重做"(在线否决)。
|
|
9
9
|
* 与 feedback-distillation(反馈域)无关 —— 这里蒸馏的是任务执行模式。
|
|
10
10
|
*
|
|
11
|
-
* 【
|
|
12
|
-
* promotion-proposals
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
11
|
+
* 【X7 已完成】本文件是纯逻辑层,不做任何本地文件 IO。三份 profile JSON
|
|
12
|
+
* (task-distill-candidates / promotion-proposals / procedure-usage,均 A 域)的读写权威
|
|
13
|
+
* 已全部归 gateway MemoryProfileService(唯一写者);qlogicagent 大脑经 HostMemoryProvider
|
|
14
|
+
* proxy 的 read/write{DistillCandidates,PromotionProposals,ProcedureUsage} 存取,本文件只提供
|
|
15
|
+
* 采集/聚类/晋升的确定性算法。单一事实源 docs/agent-supervision-authority-migration-spec.md。
|
|
16
16
|
*/
|
|
17
17
|
/** 同模式判定的余弦下限。错聚有害(把不同任务蒸成一份配方),漏聚无害(下次再攒)。 */
|
|
18
18
|
export declare const TASK_DISTILL_CLUSTER_SIM = 0.86;
|
|
@@ -20,7 +20,12 @@ export declare const TASK_DISTILL_CLUSTER_SIM = 0.86;
|
|
|
20
20
|
export declare const TASK_DISTILL_REDO_WINDOW_TURNS = 3;
|
|
21
21
|
/** 候选滚动上限(jsonl 只保留最近 N 条,防无界增长)。 */
|
|
22
22
|
export declare const TASK_DISTILL_MAX_CANDIDATES = 200;
|
|
23
|
-
/** 晋升推荐阈值:procedure
|
|
23
|
+
/** 晋升推荐阈值:procedure 实际进入 prompt(注入闸后)≥N 次且未被负反馈沉底。
|
|
24
|
+
* [A7 重标定] 记账点已从 before_recall(检索命中)移到实际注入之后:旧口径把 dream/
|
|
25
|
+
* planner brief/写入去重探测等 8 条非召回链路的 search 命中都算成"复用",恒 ≥ 真实值;
|
|
26
|
+
* 新口径 = 模型真看到过的次数。阈值数值保留 3:设计意图本就是"真实复用 3 次",旧记账
|
|
27
|
+
* 只是高估了它 —— 同数值在新口径下只会更严、名副其实。存量 access_count 含检索热度成分,
|
|
28
|
+
* 不回溯清洗(负反馈门与 importance>0.5 门兜底)。 */
|
|
24
29
|
export declare const TASK_DISTILL_PROMOTE_ACCESS = 3;
|
|
25
30
|
export declare const PROCEDURE_TAG = "distilled@v1";
|
|
26
31
|
export declare const PROCEDURE_CATEGORY = "procedure";
|
|
@@ -44,9 +49,9 @@ export interface TaskCandidate {
|
|
|
44
49
|
export interface CandidateStoreFile {
|
|
45
50
|
candidates: TaskCandidate[];
|
|
46
51
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
export declare function
|
|
52
|
+
/** 滚动上限 + 过期清理(与技能模式同款 30 天窗口)。写入前就地裁剪 —— [X7] 代理写盘时
|
|
53
|
+
* 由大脑侧先裁再送 gateway store-owner(store-owner 只忠实持久化,不重述裁剪常量)。 */
|
|
54
|
+
export declare function capCandidateStore(store: CandidateStoreFile, now?: number): void;
|
|
50
55
|
export declare function cosine(a: readonly number[], b: readonly number[]): number;
|
|
51
56
|
export interface CollectInput {
|
|
52
57
|
id: string;
|
|
@@ -101,9 +106,6 @@ export interface PromotionProposal {
|
|
|
101
106
|
export interface PromotionStoreFile {
|
|
102
107
|
proposals: PromotionProposal[];
|
|
103
108
|
}
|
|
104
|
-
export declare function promotionStorePath(profileMemoryDir: string): string;
|
|
105
|
-
export declare function readPromotionStore(path: string): PromotionStoreFile;
|
|
106
|
-
export declare function writePromotionStore(path: string, store: PromotionStoreFile): void;
|
|
107
109
|
/** 达标条目 upsert 为提议。dismissed/accepted 是终态,永不复活(拍板②:暂不=不再打扰)。
|
|
108
110
|
* 已 proposed 的只刷新 accessCount。返回是否新增。 */
|
|
109
111
|
export declare function upsertProposal(store: PromotionStoreFile, input: {
|
|
@@ -115,17 +117,24 @@ export declare function upsertProposal(store: PromotionStoreFile, input: {
|
|
|
115
117
|
export declare function resolveProposal(store: PromotionStoreFile, procedureId: string, status: "accepted" | "dismissed", now: number): boolean;
|
|
116
118
|
/** 降格:accepted → reverted(区分"暂不";降格率=reverted/accepted 家族)。 */
|
|
117
119
|
export declare function revertProposal(store: PromotionStoreFile, procedureId: string, now: number): PromotionProposal | null;
|
|
118
|
-
/** 配方文本 → SKILL.md 的确定性降级模板(LLM 格式转换失败时兜底)。
|
|
120
|
+
/** 配方文本 → SKILL.md 的确定性降级模板(LLM 格式转换失败时兜底)。
|
|
121
|
+
* description 上限与写盘校验器同源(skill-validation MAX_DESCRIPTION_LENGTH):
|
|
122
|
+
* 曾经这里按 100 截,校验器按 60 打回,长标题配方在写盘前被自己仓拒绝。 */
|
|
119
123
|
export declare function renderSkillMarkdownFallback(name: string, procedureText: string): string;
|
|
120
124
|
/** 自动档解锁条件(拍板③):样本、接受率、降格率。 */
|
|
121
125
|
export declare const V3_AUTO_MIN_SAMPLES = 10;
|
|
122
126
|
export declare const V3_AUTO_MIN_ACCEPT_RATE = 0.7;
|
|
123
127
|
export declare const V3_AUTO_MAX_REVERT_RATE = 0.1;
|
|
124
|
-
/** 自动档触发严阈值(拍板④,比手动档 3 更严)。
|
|
128
|
+
/** 自动档触发严阈值(拍板④,比手动档 3 更严)。
|
|
129
|
+
* [A7 重标定] ACCESS 与 SESSIONS 的数据源都已移到"实际注入 prompt 之后"记账
|
|
130
|
+
* (memory.after_recall 的 post-cap 名单):≥5 次 = 真进过 5 次对话,≥3 session =
|
|
131
|
+
* 真在 3 个会话里被模型看到过。数值保留 —— 拍板④要的"严"指真实复用强度,旧记账
|
|
132
|
+
* 用检索命中冒充它;新口径同数值语义只紧不松,无需放宽(若自动档长期不可达,应
|
|
133
|
+
* 优先怀疑召回质量而不是降门槛)。 */
|
|
125
134
|
export declare const V3_AUTO_MIN_ACCESS = 5;
|
|
126
135
|
export declare const V3_AUTO_MIN_SESSIONS = 3;
|
|
127
136
|
export interface ProcedureUsage {
|
|
128
|
-
/**
|
|
137
|
+
/** 实际注入 prompt 复用过它的 session 集合([A7] 记账在注入闸后,不再是检索命中) */
|
|
129
138
|
sessions: string[];
|
|
130
139
|
/** 复用后回合失败次数(零容忍:自动档要求 0) */
|
|
131
140
|
negativeCount: number;
|
|
@@ -133,9 +142,6 @@ export interface ProcedureUsage {
|
|
|
133
142
|
export interface ProcedureUsageStoreFile {
|
|
134
143
|
usage: Record<string, ProcedureUsage>;
|
|
135
144
|
}
|
|
136
|
-
export declare function procedureUsagePath(profileMemoryDir: string): string;
|
|
137
|
-
export declare function readProcedureUsage(path: string): ProcedureUsageStoreFile;
|
|
138
|
-
export declare function writeProcedureUsage(path: string, store: ProcedureUsageStoreFile): void;
|
|
139
145
|
export declare function recordProcedureRecall(store: ProcedureUsageStoreFile, procedureId: string, sessionId: string): void;
|
|
140
146
|
export declare function recordProcedureNegative(store: ProcedureUsageStoreFile, procedureId: string): void;
|
|
141
147
|
export interface PromotionMetrics {
|
|
@@ -150,5 +156,9 @@ export interface PromotionMetrics {
|
|
|
150
156
|
/** 手动阶段仪表(拍板③):接受率=accepted 家族/已决样本;降格率=reverted/accepted 家族。
|
|
151
157
|
* 任何时刻降格率回升超限即自动退回手动档(autoEnabled 现算,无粘滞)。 */
|
|
152
158
|
export declare function computePromotionMetrics(proposals: readonly PromotionProposal[]): PromotionMetrics;
|
|
153
|
-
/** 自动档严阈值(拍板④):复用 ≥5 + 跨 ≥3 session + 零负反馈。
|
|
159
|
+
/** 自动档严阈值(拍板④):复用 ≥5 + 跨 ≥3 session + 零负反馈。
|
|
160
|
+
* [A7] 三个输入如今全部以"实际注入 prompt"为记账点:accessCount 来自 Host 的
|
|
161
|
+
* recordInjectedAccess(post-cap 名单),sessions 来自 after_recall 侧的
|
|
162
|
+
* recordProcedureRecalls,negativeCount 也只指控被注入过的配方 —— 自动落盘技能的
|
|
163
|
+
* 每一分证据都对应模型真实看到并用过它的回合。 */
|
|
154
164
|
export declare function qualifiesForAutoPromotion(accessCount: number, usage: ProcedureUsage | undefined): boolean;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "qlogicagent",
|
|
3
|
-
"version": "2.19.
|
|
3
|
+
"version": "2.19.14",
|
|
4
4
|
"description": "XiaozhiClaw Agent CLI — subprocess architecture (JSON-RPC over stdio)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -146,7 +146,7 @@
|
|
|
146
146
|
"@agentclientprotocol/sdk": "^0.25.0",
|
|
147
147
|
"@napi-rs/canvas": "0.1.100",
|
|
148
148
|
"@xiaozhiclaw/module-sdk": "0.2.1",
|
|
149
|
-
"@xiaozhiclaw/provider-core": "^0.1.
|
|
149
|
+
"@xiaozhiclaw/provider-core": "^0.1.28",
|
|
150
150
|
"better-sqlite3": "^12.10.0",
|
|
151
151
|
"dotenv": "^17.3.1",
|
|
152
152
|
"ioredis": "^5.11.1",
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
export declare function filterCodexResponsesTools(body: unknown): unknown;
|
|
2
|
-
export declare function ensureCodexLlmrouterCompatProxy(upstreamBaseUrl: string): Promise<string>;
|
|
3
|
-
export declare function resetCodexLlmrouterCompatProxyForTests(): Promise<void>;
|
|
4
|
-
export declare function setCodexLlmrouterCompatProxyDiagnosticPathForTests(path: string): void;
|