import type { LeaderResult } from "./leader.js"; import { type LeaderRunRecord, type LeaderRunStatus, type NewLeaderRun, type LeaderRunTerminal } from "../plugins/leader-run-store-sql.js"; /** * endpoint 消费的 store 面(结构型,不是 nominal union):真实现是 `SqlLeaderRunStore` 的两个方言孪生, * 测试用进程内假件。窄到只有 endpoint 真调的三个方法 —— 端点不该看见店的其余口。 */ export interface LeaderRunStore { createRun(input: NewLeaderRun): Promise<{ created: boolean; run: LeaderRunRecord; }>; getRun(id: string): Promise; finishRun(id: string, patch: LeaderRunTerminal): Promise; } export interface LeaderRequestBody { /** The task to decompose + execute (the Planner turns it into N disjoint sub-tasks). */ objective: string; /** Durable-remote base the Coordinator pushes onto (`--force-with-lease=:`). */ baseSha?: string; [k: string]: unknown; } export interface LeaderRun { id: string; /** LEADER-REPAIRLOOP-INTEGRATION §5/§10.6 — `needs_human` is the THIRD terminal state: the repair loop / merge * push chokepoint ABSTAINED (a `candidate_only`/`needs_human_oracle`/`conflict` repair terminal), held the push, * and surfaced a candidate awaiting a human `/decide` accept — distinct from "broke" (`failed`). Default runs * never reach it (no `repairTerminal` ⇒ `completed`/`failed` exactly as before). */ status: LeaderRunStatus; result?: LeaderResult; error?: string; startedAt: number; finishedAt?: number; /** BL-4: the principal that submitted this run (null = anonymous/single-tenant). The GET is owner-checked so * an owned run is visible ONLY to its owner (404 to others — no existence oracle), like GET /v1/runs/:id. */ owner?: string | null; } export interface LeaderEndpoint { /** Returns a {status,body} to send, or null if the (method,url) is not a leader route. Kicks the background * run for POST. `body` is the already-parsed request body (server reads it; undefined for GET). `requester` * (BL-4) is the authenticated principal: recorded as the run owner on POST and owner-checked on GET. * `idempotencyKey` is the caller's RAW `Idempotency-Key` header (POST only; scoped by owner before it * reaches the store — see {@link leaderIdemKey}). ASYNC because the durable arm reads/writes SQL. */ handle(method: string, url: string, body: unknown, requester?: string | null, idempotencyKey?: string | null): Promise<{ status: number; body: object; } | null>; /** 交叉复查 B-1(CRITICAL):the number of leader runs still RUNNING in the background — the drain gate * counts them (a SIGTERM used to see 0 and hard-shut mid-leader-run). * * 🔴 刻意**只数本副本**(即使 store 在场):drain 门问的是「这个进程还在驱动几条 run」,不是「全集群 * 还有几条」。读库会把别的副本正在跑的 run 也算进来,于是本副本永远排不干净。 */ inflight(): number; /** In-memory run registry — the DEGRADED arm's storage, and (on both arms) the drain gate's inflight set. * With a store in place this Map holds only the runs THIS replica is driving. Exposed for tests. */ runs: Map; } export declare function createLeaderEndpoint(runLeader: (body: LeaderRequestBody) => Promise, opts?: { logger?: { info?: (m: string, x?: Record) => void; error?: (m: string, x?: Record) => void; }; /** SDK 全量核查(2026-07-24,黑板 GD 组)撞获:`wire.ts` 的 runLeader 实际要求 objective 之外还有 * durableRemote/testCmd/seedCmd/baseSha 全部非空,但这个同步门此前只查 objective——一个不完整的 * 请求会先拿到 202"运行中",然后在后台**必然**失败(wire.ts:369),消费方只能靠后续 GET 才发现。 * 这个字段名列表由调用方(main.ts wire 真实 runLeader 实现)传入,endpoint 本身不需要知道 * runLeader 的内部实现细节,依旧保持 pure/testable。不传 = 向后兼容旧行为(只查 objective) —— * 本文件其余全部既有用例都用最小 {objective} payload,不能被这个修复打红。 */ requiredFields?: readonly string[]; /** [ref] 车4 件1:durable 登记表。缺席 ⇒ 显式的单副本内存降级臂(见文件头注)。 */ store?: LeaderRunStore; }): LeaderEndpoint; //# sourceMappingURL=endpoint.d.ts.map