C-01 · 主动控制面
PLANNED · 设计
主环 #3
ContextObserver
把原生事件转换为按 session 隔离的语义上下文片段。
← session 事实源 · observe→ C-02 SessionRuntime · scope
/* C-01 ContextObserver — 原生事件 → 按 session 隔离的语义上下文片段 */
function observe(env: EventEnvelope): Segment | null {
if (env.schemaVersion !== 1) return null // 版本不符直接丢
const text = sliceByKind(env) // 按事件类型切片, 不粗暴取最后 N token
return {
id: uid(), sessionId: env.sessionId, kind: env.sourceKind,
eventSeq: env.eventSeq, text,
entities: extract(text), digest: digest(text), ts: now(),
}
}
// 约束: 跨 session 合并事件 = 污染后续所有检索;
// contextVersion 单调递增; 过期异步结果可丢弃;
// reasoning chunk 可作可选 reasoning segment, 默认不持久化
C-02 · 主动控制面
PLANNED · 设计
主环 #4
SessionRuntime
每个 agent/session 的工作状态、上下文环、pending packet 和冷却。
← C-01 ContextObserver · scope→ M-01 Working Memory · window
/* C-02 SessionRuntime — per-agent/session 运行态(消灭全局状态) */
const states = new WeakMap<Agent, AgentMemoryState>() // 执行 token 用 Map 关联嵌套观测
interface AgentMemoryState {
working: RingBuffer<Segment> // → M-01 工作记忆
cursor: ContextCursor // 单调递增
pending: MemoryPacket[] // 待注入队列
cooldown: Map<string, number> // 触发冷却
sidecarJob?: AbortController
}
function teardown(agent) {
states.get(agent)?.sidecarJob?.abort() // abort 检索 → sidecar quiescence → 清理 map
states.delete(agent)
}
// 验收: 并发 A/B session 隔离为零泄漏;
// 不再依赖进程级 _lastAgent / 全局 _consolidating / 全局 pending queue
C-03 · 主动控制面
PLANNED · 设计
主环 #6
Retrieval Gate
动态判断现在是否值得检索,而不是每一步固定召回。
← M-01 Working Memory · signal← R-01 Research Signals · trigger→ C-04 Association Engine · retrieve
/* C-03 Retrieval Gate — 动态判断"现在值不值得检索"(无 CoT 也成立) */
interface GateDecision { action: 'retrieve' | 'prefetch' | 'suppress'; reason: string }
function decide(win: Segment[], seg: Segment, cur: ContextCursor): GateDecision {
const signals = {
novelty: !win.some(s => s.digest === seg.digest), // 新颖度
unresolved: unresolvedEntities(win).length > 0, // 未决实体
phaseShift: taskPhase(win) !== taskPhase(win.slice(0, -1)), // 任务阶段变化
toolFailure: seg.kind === 'tool' && !seg.ok, // 工具失败
conflict: conflictCount(cur.sessionId) > 0, // 冲突
historical: hitRecent(cur.sessionId) !== null, // 相似历史命中
}
if (cooldownActive(cur)) return { action: 'suppress', reason: 'cooldown' }
if (ignoredMemory(cur, seg.digest)) return { action: 'suppress', reason: 'user-ignored' }
const s = weighted(signals) // 权重来自 R-02 认知模型 + R-01 论文启发
return s >= HOT ? { action: 'retrieve', reason: 'above-threshold' }
: s >= WARM ? { action: 'prefetch', reason: 'warm' }
: { action: 'suppress', reason: 'below-threshold' }
}
// 公开模型可增加 uncertainty / reasoning 信号, 但不是硬依赖;
// cognitive load 不是"记忆只在困难时出现"的硬门;
// 滞回 + 冷却 + "已忽略记忆"抑制避免反复打扰
C-04 · 主动控制面
PLANNED · 设计
主环 #7
Association Engine
从预索引记忆中找出当前情境可能自动唤回的候选。
← C-03 Retrieval Gate · retrieve← M-02 Episodic Memory · recall← M-03 Semantic / Profile · recall← M-04 Procedural Memory · checklist← M-05 Lexical / Entity · entity← M-07 Python Memory Engine · sidecar← G-05 Fallback / Degrade · degrade← R-02 Cognitive Model · model→ C-05 Rank / Dedupe / Budget · candidates
/* C-04 Association Engine — 三级检索: 词法初筛 → 向量/时间过滤 → 图扩散 */
async function recall(seg: Segment, cur: ContextCursor): Promise<Candidate[]> {
const hits: Candidate[] = []
// ① 关键词 / 实体快速初筛(永远可用)
hits.push(...lexical.hits(seg.entities, seg.text)) // M-05
// ② 向量 + 时间过滤(sidecar, 可降级)
const emb = await sidecar.embed(seg.text, cur) // M-07
if (emb.ok) hits.push(...await sidecar.vsearch(emb.vec, cur.scope))
else hits.push(...fallbackKeyword(seg.text)) // G-05 词法回退
// ③ 必要时图扩散(HippoRAG PPR / A-MEM 链接)
if (graphEnabled && hits.length < k)
hits.push(...await sidecar.graphExpand(seg.entities))
// embedding 元数据(model / dimension / version)随索引持久化, 版本不一致不得混用
// 图链接追加证据且可撤销, 避免一次错误扩散污染整个图
return hits
}
C-05 · 主动控制面
PLANNED · 设计
主环 #8
Rank / Dedupe / Budget
把"相关"变成有限、可解释、不会重复的候选集合。
← C-04 Association Engine · candidates→ C-06 Injection Broker · policy
/* C-05 Rank / Dedupe / Budget — 把"相关"变成有限、可解释、不重复的候选集 */
function run(cands: Candidate[], cur: ContextCursor): RankedResult {
const scored = cands
.filter(c => c.scope === cur.scope && c.expiresAt > now()) // scope + TTL
.map(c => ({ c, s: wSim * c.similarity + wSal * c.salience
+ wNov * novelty(c, cur) + wRec * recency(c, cur) }))
.sort((a, b) => b.s - a.s)
const kept = [], dropped = []
const seen = new Set()
for (const x of scored) {
const key = dedupeKey(x.c, cur) // session/agent + context cursor
// + exact/semantic digest + schema/index 版本
if (seen.has(key)) { dropped.push({ id: x.c.id, reason: 'duplicate' }); continue }
if (bytes + x.c.payload.length > budget.candidateBytes)
{ dropped.push({ id: x.c.id, reason: 'budget' }); continue }
seen.add(key); kept.push(x)
}
return { ranked: kept, dropped } // 每个 drop 都有理由
// 预算分层: 摄取上限 → 候选延迟上限 → packet UTF-8 bytes → token/context window
// 超预算候选不得标记 delivered; TTL 只触发重检索, 不充当内容 identity
}
C-06 · 主动控制面
PLANNED · 设计
主环 #9
Injection Broker
决定未来候选记忆是否在下一请求边界变成 MemoryPacket;不负责当前 native runtime-context snapshot。
← C-05 Rank / Dedupe / Budget · policy← G-02 Injection Audit · audit← G-03 Safety Gate · gate← C-07 Provider Adapter · adapter→ N-03 Agent Inbox · future packet
/* C-06 Injection Broker — 候选 → 下一请求边界的 MemoryPacket(或放弃) */
function build(ranked, verdict: SafetyVerdict, cap): MemoryPacket | null {
if (!cap.packetPatch || cap.packetPatch === 'none') return null // runtime-context 不是未来 packet 通道
if (verdict.action !== 'allow') return null // G-03 拦截
return {
packetSchemaVersion: 1,
contextCursor: cur, // 与 retrievalVersion 一起校验新鲜度
retrievalVersion: indexVersion(),
triggerReason: verdict.trigger,
strength: pickStrength(ranked, cap), // soft hint / direct context / checklist
items: ranked,
exactDigest: exactDigest(ranked), semanticDigest: semanticDigest(ranked),
sourceSeqs: ranked.map(c => c.sourceSeq),
budgetBytes: totalBytes(ranked), expiry: now() + ttl,
}
}
// 约束: packet 不是高优先级新指令; 请求发出后不回写隐藏状态;
// 任何注入都能回答 why / what / source / cost / expiry
C-07 · 主动控制面
PLANNED · 设计
支线模块
Provider Adapter
按 Provider、model、version 分开协商 reasoning、native runtime context 与未来 packet surface。
→ C-06 Injection Broker · adapter
/* C-07 Provider Adapter — 分开声明 native runtime context 与 future packet surface */
function snapshot(route): CapabilitySnapshot {
const m = manifest(route.provider, route.model, route.modelVersion)
return {
reasoningVisibility: m.reasoning ?? 'unknown', // none / summary / full / unknown
runtimeContext: m.includeRuntimeContext !== false ? 'native' : 'none',
packetPatch: m.supportsPreStep ? 'pre-step'
: m.supportsUserMessage ? 'user-message'
: 'none',
abortAndResume: !!m.abortAndResume,
}
}
// runtimeContext = native systemPrompt.context() + RuntimeContextProjection
// packetPatch = future Agent Inbox / next-step MemoryPacket path
// includeRuntimeContext:false suppresses the first channel; it does not create the second
// Minimal complete persona: complete:true + includeRuntimeContext:false
// → native runtime-context 被抑制, 不能假设已挂载 dsh-agent-instructions
// → 未来需自建 packetPatch user/message 路径, 否则安全降级 shadow retrieval
// 约束: 不能按"模型名称"硬编码能力; preset 不支持 patch 时不强行改请求