/** * RosterStore SQL twins(agent-team S1 server 半场,[ref]① 提货单)——core `RunnerDeps.rosterStore` * 的 TiDB/PG 双方言实现:具名子 agent 的持久名册(具名 spawn advisory 写入;SendMessage 活注册表 * miss 后咨询;v1=诚实指针 roster_only,非跨 run resume)。 * * 语义三条([ref]① 必守,与 core roster-store.js 参考实现字节对齐): * 1. resolve **查询内** filter-before-reduce:access 轴在 SQL WHERE 完成(scope 先拒 → owner 匹配 → * sessionScoped 显式位才认 session 匹配),绝不先取全集再内存过滤(跨租户行连查询结果都不进); * 2. 同 `(normalizedName, owner, scope)` 域 upsert(core upsertKey 同键); * 3. 写失败降级 miss 不出错答案 —— 已核 core 调用侧兜底(subagent.js record=`void …catch(()=>{})`, * resolve=try/catch),store 侧诚实 THROW 即可(绝不吞成假成功)。 * * latest 语义:core `latestOf` 用 `>=`(同 createdAt 后遍历者赢=写入序)。SQL 无插入序 ⇒ 次序键三连 * `created_at_ms DESC, recorded_at_ms DESC, agent_id DESC`——第三键保**确定性**(发版复审 F3:并发 * spawn 可共享毫秒、多副本时钟可偏斜,无第三键的 LIMIT 1 非确定)。诚实记账:同毫秒并写时选择= * agent_id 字典序最大,与 core 单进程的「后遍历者赢」可能不同——多副本本就无全序,确定性优先。 * * normalize 私拷已回收(2026-07-19):core 公共出口落地(黑板 [ref]① 所请的 additive 导出),按 * 头注预案换回单行 import。⚠️ 语义仍是**存储键**:DB 行按 normalize 后的键写入——core 若改语义, * 存量行查不回;test/roster-store-db-integration.test.ts 的 golden corpus 钉守这条(非私拷漂移钉, * 是「core 变语义必须先过迁移裁量」的告警钉)。 */ import type { Pool } from "mysql2/promise"; import { type RosterStore, type RosterEntry, type RosterAccess } from "@sema-agent/core"; import type { PgQueryFn } from "./pg-query.js"; import { type IndexSpec } from "./ensure-index.js"; export declare const ROSTER_TABLE = "agent_roster"; export declare function ensureTiDBRosterSchema(pool: Pool): Promise; /** S-287:本 store 的索引**声明**(两方言共用一份)。PG 侧由下面的 `ensurePgRosterSchema` 应用,MySQL 侧由 `tidb-pool.ts` 的中央 `ensureSchema` 应用(那里内联 `KEY` 已在 `CREATE TABLE` 里 ⇒ 新建库探到即零 DDL,存量库缺谁补谁)。加索引以外的 schema 变更仍归运维,见 `plugins/ensure-index.ts` 头注。 */ export declare const ROSTER_INDEXES: readonly IndexSpec[]; export declare function ensurePgRosterSchema(q: PgQueryFn): Promise; export declare class TiDBRosterStore implements RosterStore { private readonly pool; private readonly clock; constructor(pool: Pool, clock?: () => number); record(entry: RosterEntry): Promise; resolve(name: string, access: RosterAccess): Promise; list(): Promise; releaseAgent(agentId: string): Promise; /** [ref] MED2(server 扩展,非 core 接口;core [ref]②③ 派给部署的清理半场):TTL 清理—— * task-scoped 具名 spawn 的 owner=宿主 taskId=每 run 一新行,无清理=线性无界。按 recorded_at_ms * (最后一次 upsert 触碰)删,latest 语义不受影响(活跃名恒被新 spawn 刷新)。 */ reapOlderThan(cutoffMs: number): Promise; } export declare class PgRosterStore implements RosterStore { private readonly q; private readonly clock; constructor(q: PgQueryFn, clock?: () => number); record(entry: RosterEntry): Promise; resolve(name: string, access: RosterAccess): Promise; list(): Promise; releaseAgent(agentId: string): Promise; /** [ref] MED2(TiDB twin 同案注)。 */ reapOlderThan(cutoffMs: number): Promise; } //# sourceMappingURL=roster-store-sql.d.ts.map