import type { ModelKeyRef } from "../key-resolver.js"; import type { ServiceConfig } from "../config-types.js"; import type { HookLlmCall } from "./hook-runner.js"; /** * hookLlm(prompt 条目/session titler 的模型载体)= 直连一次非流式 completion,从 main.ts 抽出成可注入 * 单元(fetchImpl/keyResolver 可假),因为这条 wire 在每个默认部署上都活(titler),必须可单测。 * * api 形分派(2026-07-15,黑板 [ref]③b 真缺陷修):被选模型按 `Model.api` 分家 —— * - `openai-completions` ⇒ POST {base}/chat/completions(现状,字节不变); * - `anthropic-messages` ⇒ POST {base}/v1/messages(x-api-key / Authorization: Bearer + anthropic-version * 头,messages 数组,回包取 content[].text)。此前 hookLlm 只会说 openai 形且缺省 baseUrl 恒落 * `config.gatewayBaseUrl`(缺省 http://127.0.0.1:8000/v1)——anthropic 单路由部署(主模型 * provider=anthropic 走 ANTHROPIC_BASE_URL,没配 MODEL_GATEWAY_BASEURL)下 titler 每会话打死 * localhost:8000 ⇒ `session_title_failed: TypeError: fetch failed`;即使端点活着,anthropic-messages * 模型也不能用 /chat/completions 形调。 */ export type HookModelPick = { ok: true; catalogRef: string; providerModelId: string; baseUrl: string; api: "openai-completions" | "anthropic-messages"; } | { ok: false; error: string; }; /** * 🔴 **hook 失败展示文本的唯一铸点**(S-494;`build*` = 返回纯数据的一只纯函数)。 * * 病(codex 对 7.88.1/7.88.2 的补审抓出,存量泄漏,本车红先复现):这一族失败文本是**拼**出来的 —— * 料有四种:core 的路由拒绝文案(`routeRefusalText` 的 `fixHint` 逐字带 `config.baseUrl` 的值)、 * 原生 `fetch` 的**构造期异常正文**(WHATWG:`…includes credentials: <整条 URL>`,口令逐字)、 * 它的 `cause`、per-model key 解析错。改前只有**两个 URL 位**走了 display-safe 铸点 —— 那是名单制: * 组装料换一种(异常正文、cause)就漏,而它的出口是 `hook_runner` 的 `hook_llm_failed` warn 与 * `noteHookFailure` 的 stderr 位。⇒ 把尺放到**出口**:整段组装完了过**一次**律,规则从「N 个 URL 位」 * 减到「一只出口」(那两个 display-safe 调用随之删)。 * * 用的是自由文本那一条律({@link redactSecrets})—— `buildDisplaySafeUrl` 是它加两道 URL 专属闸的 * **已知是一条 URL** 的那个特例,而这里的料是自由文本(一段异常正文里可能一个 URL 都没有,也可能有三个)。 * 同一张名表、同一批记号,不是第二把尺。 * * 🔴 **脱敏器抛 ⇒ 响亮扣下**(不回原串、不 fail-open):文案形与 7.88.1 的 * `fail-open.ts` `renderDetail` 逐字同族(`[… withheld: redactor threw ]`)—— 运维丢掉的是细节、 * 不是「这次失败了」这件事,而一个字节的原串都不会漏出去。 * * 🚧 **已知射程边界(登记,另车修在源头)**:自由文本律对**非规范拼法**的 URL * (`https:alice:pw@h/v1` 省了 `//`、authority 里夹 tab)认不出结构 ⇒ 那两形若出现在料里(目录下发的 * `models[].baseUrl` 今天原样存,`apply-effective.ts` 只校验 `protocol`)仍会原样。修在源头 = * 目录 baseUrl 落库前归一成 `new URL(raw).href`(S-483 收车档未闭环项),不是在这里再加一把尺。 */ export declare function buildHookFailureText(raw: string): string; /** The live object `createHookLlm` produces — model-pick resolution + the direct completion call, both capturing the hot-refreshed keyResolver/fetchImpl in closure. */ export interface HookLlm { hookModelFor: (requested?: string) => HookModelPick; hookLlm: HookLlmCall; } export declare function createHookLlm(deps: { config: ServiceConfig; /** 与 brain 同一 hot-refreshed per-model key 面(main.ts 热应用会整个换引用,故取函数不取值)。 */ getKeyResolver: () => ((model: ModelKeyRef) => Promise<{ apiKey: string; } | undefined>) | undefined; metrics: { inc: (name: string, labels?: Record) => void; }; fetchImpl?: typeof fetch; }): HookLlm; //# sourceMappingURL=hook-llm.d.ts.map