import { CenterPromptSource, type SwappableDeps } from "@sema-agent/core"; import { buildPricing } from "../budget.js"; import { type PromptsDomainFaces } from "../prompts-domain-validate.js"; import { type Scenario, type ScenarioDeps, type ScenarioDetail } from "../capabilities/scenarios.js"; import type { LoadedSkill } from "../capabilities/skills.js"; import { type ServiceConfig } from "../config.js"; import { type ModelKeyRef } from "../key-resolver.js"; import type { Logger } from "../observability/logger.js"; import type { Metrics } from "../observability/metrics.js"; import type { UnpricedCeilingVerdict } from "./unpriced-ceiling-verdict.js"; import { type RestartSignal } from "../config-center/facade.js"; import { type ConfigApplyLedgerView } from "../config-center/apply-ledger.js"; import type { LimitSync } from "./limit-sync.js"; export interface ConfigCenterRuntimeCtx { config: ServiceConfig; logger: Logger; metrics: Metrics; /** 🔴 与 main 的 remoteExec loader 共用的**同一个**本地根(split-brain 防线,理由见 main.ts 构造点)。 */ localRoot: string; } /** center scenarios overlay 的活引用面(overlay 就地写进 main 持有的两张表)。 */ export interface CenterScenarioOverlayTargets { scenarioDeps: ScenarioDeps; scenarios: Record; scenarioDetails: Record; /** overlay 前捕获的六内建名(centerScenarioDetails 的 shadow 判据)。 */ builtinScenarioNames: string[]; } /** 跨段可变状态的**唯一**对外读口 + 三个原位动作。字段语义见各方法上的注释。 */ export interface ConfigCenterRuntime { /** 配置源形态;`undefined` = 纯 env 部署(本运行时的所有分支不存在)。 */ readonly providerKind: "remote" | "local" | undefined; /** core `CenterPromptSource`(RunnerDeps / subRunner 必须同实例)。 */ readonly promptSource: CenterPromptSource; /** DUAL-MODE §4/§5:local 形从 `config.d/remote-exec.json` 覆写 `config.remoteExec`(坏文件 = fail-closed 抛)。 */ applyLocalRemoteExec(): Promise; /** center skills overlay → plugins 消费 → boot LKG 落盘/skill-stale 判定 → mcp 解析。返回新的 skills 表。 */ applyCenterCapabilities(skills: LoadedSkill[]): Promise; /** center 声明场景 overlay(就地写进传入的两张表)。 */ applyCenterScenarios(t: CenterScenarioOverlayTargets): void; /** per-model key resolver 首建(原位调用,见文件头注 5)。 */ initKeyResolver(): void; /** 60s refresh cadence + boot-deferred 到货续接。 * `limitSync`([ref] 批1)= 恒构造的两只限额座的换代口:commit 之后**零 await 内**推一把,与 pricing / * keyResolver 那两件派生重建同族(缺席 = 这条腿本部署没装配,例如 run-local)。 * `swapRunnerDeps`(core 7.10.0 `Runner.swapDeps` 一扇门;5.49 起的 `swapModels` 口在 7.10.0 退役、 * 本参数同语义改名)= **可换席**的换装口:模型面 plane 变更候选在 commit 前喂给全部 boot Runner * 原子换代(在场 ⇒ models-tiers defer/restart 臂退役,缺席 ⇒ 旧 defer 行为逐字保留);S-174 起 * read **face** 席也走同一只函数(见 refresh 拍里的 `applyCenterReadFace` 调用点)。 * `ceilingVerdict`(S-232)= 「配了 $ 天花板但目录未定价」这条判决的活载体,与 `limitSync` **同族同序** * (commit 之后、零 await 内重判一次;判决不翻转就静默)。缺席 = 这条腿本部署没装配(run-local 一次性 * CLI 之后不再有刷新拍,它继续用纯判据判一次)。 */ startRefreshLoop(a: { runnerTierFrozen: boolean; pricing: ReturnType; limitSync?: LimitSync; swapRunnerDeps?: (next: SwappableDeps) => void; ceilingVerdict?: UnpricedCeilingVerdict; }): void; /** [ref]-2:停刷新环(hardShutdown 收尾链;幂等,未起环时 no-op)。 */ stopRefreshLoop(): void; /** [ref](core 5.50 [ref]):mid-turn MCP 撤销台账读口,喂 `RunnerDeps.mcpRevocations` 席。 * **取走即声明接线**——调用本方法后,restart 信号的 mcp 片对纯删除向豁免(台账即时承接); * 不取 ⇒ 旧 restart 语义逐字保留(fail-closed)。 */ takeMcpRevocations(): import("../config-center/mcp-revocation.js").McpRevocationLedger; /** [ref] 诊断投影:当前被撤销的 MCP 服务器名单;纯 env 部署(无配置管道)= undefined(additive 纪律)。 */ mcpRevocationState(): { revoked: string[]; } | undefined; /** 晚绑取值:refresh 热应用会整个换引用(hook LLM / resolveSpec 每次现取)。 */ getKeyResolver(): ((model: ModelKeyRef) => Promise<{ apiKey: string; } | undefined>) | undefined; /** 晚绑取值:center 提示词面(热采用,新任务边界生效)。 */ getCenterPrompts(): PromptsDomainFaces | undefined; /** boot ready 门:布防(`CONFIG_REQUIRE_ROSTER=true`,远程 registry 非 dryRun)且 roster 未落地 = * 计费提交 503 + /health ready:false。缺省未布防 ⇒ 恒 true。 */ modelReady(): boolean; /** /health.restart(orchestrator 自动重启信号)。 */ restartState(): RestartSignal | undefined; /** /health.modelPlaneDeferred(codex R18 卡死的 plane,无 next-boot handoff)。 */ planeDeferredState(): { version: number; since: number; blocked?: string[]; } | undefined; /** [ref] 世代账:/health 的 target/applied/失败持续时长三键 + 诊断端点的 configApply 段(同一份读数)。 * `undefined` = 本部署没有配置管道(纯 env worker)⇒ 两个读面的形状**逐字不变**(additive 纪律)。 */ configApplyState(): ConfigApplyLedgerView | undefined; /** DESIGN-278 §5 S2([ref]):center **当前在管**的 ServiceConfig 键集 —— `GET /v1/config/catalog` 判 * `effectiveLane` 的 center 半场。投影自最近一次成功应用的候选(`latestEffective`,LKG/refresh 同一 * 份推进点;判据单源 = apply-effective.ts `centerManagedConfigKeys`)。`undefined` = 没有配置管道。 * ⚠️ 部分应用窗(codex R2-F2 登记):某组整拒时 live config 已吃进其它组而 latestEffective 不推进, * 该窗内本键集滞后一代 —— 目录端点只据此报**归因位**(managedNow),值仍是活 config 实算; * 逐键 applied 账(设计稿 §8-7)收口这半格。 */ centerManagedKeys(): ReadonlySet | undefined; /** * [ref] 追加件:手动触发**一次既有** refresh 拍(`POST /v1/admin/config/refresh` 的实现面)。 * * 一拍在飞 ⇒ **join** 它(并发调用共享同一拍,绝不并发双拍、绝不另铸拉取路径);返回时该拍已落地, * 所以调用方紧接着读 `configApplyState()` 就是本次触发的结果。 * `"not-wired"` = 本部署没有配置管道(纯 env 形)或刷新环还没起 —— 端点据此诚实 4xx,不吞成 200。 * `"failed"` = 这一拍真的失败了(中心超时 / 盘读不了 / 应用抛错)—— 端点据此 5xx。定时拍照旧吞掉异常 * 保住循环,但**吞掉的事实必须传给按下刷新的那个人**(codex R2-F3:否则「中心超时」与「已刷新」在 * 回执上不可分辨,这个口的「诚实」二字就是假的)。 */ refreshNow(): Promise<"triggered" | "not-wired" | "failed">; } export declare function createConfigCenterRuntime(ctx: ConfigCenterRuntimeCtx): Promise; //# sourceMappingURL=config-center.d.ts.map