/** * List the paths inside a `configuration` block that the calling factory will NOT read. * * `consumedPaths` entries are either a whole key (`baseURL`) or a dotted one-level path * (`defaultHeaders.X-Title`). The dotted form matters because consumption is genuinely PARTIAL: * openrouter reads two named attribution headers out of `defaultHeaders` and drops every other * header in it. Reporting `defaultHeaders` as wholly consumed would silence the warning for * exactly the case the user most needs it for — an auth header for a self-hosted gateway that is * quietly discarded. * * A `configuration` that is not a record at all (`configuration: "https://x/v1"`, a plausible typo * for the block) has no paths and is reported as nothing. That is NOT a silent drop: `llm.configuration` * is `z.record` in `schema.ts`, and every config layer goes through the loader's `validateRawConfigLayer`, * so a non-record value is a hard, path-scoped validation error that ends the run before any provider * factory is reached. The schema is the gate for the shape; this function is the gate for the * contents. `configurationPassthrough.spec.ts` pins that boundary — if the schema ever stops * requiring a record, the case has to be handled here instead. */ export declare function findUnusedConfigurationPaths(configuration: unknown, consumedPaths: readonly string[]): string[]; /** * The `reason` for a provider built on a NATIVE client: there is no OpenAI client anywhere in the * chain, so the block has nothing to be handed to. * * A shared clause is only safe while it is true of every caller that passes it, and nothing in the * language can check that: the field takes any string, so a caller can pass this sentence — or * another provider's — for a provider it is false of, and a warning that states a false reason is * the same defect as the silence it replaces. Requiring the field stops one narrow version of that * (a default nobody re-read against the new caller) and stops nothing else; copying the neighbouring * call site is the likelier move and is exactly how a false clause would spread. * * What actually holds it is `configurationPassthrough.spec.ts`, which pins every warned provider's * printed clause IN ITS SLOT beside that provider's own name. A clause that migrates to a provider * it is false of reddens a cell, and editing THIS sentence reddens every caller that passes it — * which is the point: a shared clause has to be re-checked against each of them. */ export declare const NATIVE_CLIENT_REASON = "does not build an OpenAI client, so a \"configuration\" block is not passed through to one"; /** * Warn — naming the provider, saying why the block is dropped, naming every dropped path, and * pointing at the replacement — when a user's `configuration` block carries settings this provider * cannot consume. * * Warn rather than throw: a provider that reads SOME of the block (openrouter still honours * `configuration.baseURL`) would otherwise refuse a config that is partly valid, and an upgrading * user whose only config sets one dead transport key would be left with no way to start at all. * * Takes ONE named-field object rather than a positional list. `reason` and `guidance` are both free * text, so as adjacent positionals they could be transposed with nothing to catch it: `tsc` sees two * strings, and the rendered message still contains both sentences — only their order is wrong, which * no `toContain` check on either one can see. Named fields make that mistake visible where it is * written; the slot-anchored pins in `configurationPassthrough.spec.ts` are what catch it if it is * written anyway. */ export interface UnusedConfigurationWarning { /** The gth provider namespace, printed to the user (`anthropic`, `xai`, …). */ provider: string; /** The user's `llm.configuration` block, exactly as it arrived. */ configuration: unknown; /** * The paths inside the block this factory genuinely reads — whole keys or dotted one-level paths. * Required rather than defaulted to `[]`, so a new caller has to state what its factory consumes * instead of inheriting an answer. */ consumedPaths: readonly string[]; /** * Why THIS provider drops the block, as a clause completing `the "" provider …`. Pass * {@link NATIVE_CLIENT_REASON} for a native-client provider; a provider that builds an OpenAI * client and then overrides the block needs its own, because that sentence would be false for it. */ reason: string; /** * What to do instead, naming the replacement on THIS provider's own client — never a generic * "move it up a level", which for some keys moves a setting from a warned location to an unwarned * one. */ guidance: string; } export declare function warnUnusedConfiguration({ provider, configuration, consumedPaths, reason, guidance, }: UnusedConfigurationWarning): void; /** * Warn when one honoured location of the `llm` block silently beats another that sets the same * thing. * * Neither value is unusable here and neither location is wrong, so this is not a case for * {@link warnUnusedConfiguration}: both are honoured surfaces, and the only defect is that one wins * without saying so. The user's config then reads as two settings and behaves as one. * * **The two paths are arbitrary, and they have to be**, because the precedence in this block is not * one direction. For `baseURL` the `configuration` value beats the top-level field; for the * OpenRouter attribution headers the top-level `siteUrl`/`siteName` beat the header inside the * block, and the losing path is a nested one that shares no name with the winner. A helper that * took a single `field` and hardcoded which side of it wins could only ever announce the first of * those, which is how the second stayed silent. * * Values are never printed — a base URL can carry credentials — so the message names the two paths * and which of them takes effect. * * **Named fields, and the reason the names are not the whole guard.** `ignoredPath`/`appliedPath` * are two strings and `ignoredValue`/`appliedValue` two `unknown`s, so a transposition type-checks * either way round; the rendered message still contains both paths and only their ROLES are * swapped, which no `toContain` on either path can see. What catches it is in * `configurationPassthrough.spec.ts`: the paths are pinned IN THEIR SLOTS in the rendered sentence, * and the values by the discriminating pair around the empty-value guard below (an empty LOSER is * silent, an empty WINNER is not). */ export interface ShadowedFieldWarning { /** The gth provider namespace, printed to the user (`openrouter`, …). */ provider: string; /** * The path whose value is NOT used, relative to the `llm` block and printed with an `llm.` * prefix — `baseURL`, or `configuration.defaultHeaders.HTTP-Referer`. */ ignoredPath: string; /** The path whose value IS used, in the same form. */ appliedPath: string; /** The value at {@link ignoredPath}, as the user wrote it. Never printed. */ ignoredValue: unknown; /** * The value the factory actually applied. Pass the result of the SAME expression that decides it, * never a second copy of the test, for the reason given on {@link warnUnappliedConfigurationPath}. * Never printed. */ appliedValue: unknown; } export declare function warnShadowedField({ provider, ignoredPath, appliedPath, ignoredValue, appliedValue, }: ShadowedFieldWarning): void; /** * Warn when a path the factory DECLARES it consumes is present in the user's block but was not in * fact applied — the empty string or `null` a factory's own guard skips. * * {@link findUnusedConfigurationPaths} cannot see this and must not: the path genuinely IS consumed, * so it is correctly absent from the unused list — and the user's setting still goes nowhere. * "Declared supported, in fact dropped" is the same silence this module exists to end, so it gets * its own message: the "no OpenAI client" reason above would be the wrong reason for it. * * @param applied Whether the factory actually used the value. Pass the result of the SAME expression * that decides it (`'baseURL' in baseURLOverride`), never a second copy of the test — a re-test is * exactly how the guard and what the user is told drift apart. */ export declare function warnUnappliedConfigurationPath(provider: string, configuration: unknown, path: string, applied: boolean, guidance: string): void;