/** * Search-plan resolution: which protocol and endpoint native search runs * through. The initiating Agent's captured chat route (selection plus the * `llm-pi-ai` settings section) is detected and probed — its own protocol * when that can search. The {@link SearchPlan} class owns the probe lifecycle so * `available()` stays synchronous while the verdict lands in the background. * @module dsh-github-copilot/plan */ import type { Context } from '@deepseek-ai/cordis'; import type { ProbeOutcome } from './probe.ts'; import type { CurrentChatRoute } from './current-provider.ts'; /** The two search-capable wire protocols this package speaks. */ export type SearchProtocol = 'openai-responses' | 'anthropic-messages'; /** Credential record that owns GitHub Copilot OAuth state and refresh. */ export declare const GITHUB_COPILOT_CREDENTIAL_KEY = "llm-pi-ai/github-copilot"; /** Default `anthropic-version` header value. */ export declare const DEFAULT_API_VERSION = "2023-06-01"; /** * The server-side Responses web tool spellings. The standard `web_search` * is the preferred Copilot spelling; `web_search_2025_08_26` is retained as * a probe fallback for provider-side protocol variation. */ export type ResponsesWebSearchToolType = 'web_search' | 'web_search_2025_08_26'; /** Standard server-side web search tool type (OpenAI/DeepSeek official). */ export declare const WEB_SEARCH_TOOL_TYPE: ResponsesWebSearchToolType; /** * Versioned Responses spelling retained as a capability-probe fallback. */ export declare const RESPONSES_WEB_SEARCH_TOOL_TYPE: ResponsesWebSearchToolType; /** Anthropic server-side web search tool type (versioned). */ export declare const ANTHROPIC_WEB_SEARCH_TOOL_TYPE = "web_search_20250305"; /** * Fully defaulted endpoint facts one search (or probe) operation runs with. * Every field is resolved once at plan build time so the adapters never fall * back mid-operation. */ export interface SearchPlanCandidate { readonly protocol: SearchProtocol; /** Endpoint base; `/responses` or `/messages` is appended by the adapter. */ readonly baseURL: string; readonly model: string; /** Credential reference resolved through the credentials seam. */ readonly apiKeyEnv: string; /** `anthropic-version` header value (anthropic-messages only). */ readonly apiVersion: string; /** Static provider/model headers inherited from pi-ai's catalog. */ readonly headers?: Readonly>; /** * The Responses web tool spelling this candidate serves with (probe-verified; * openai-responses only). The probe may settle on the fallback spelling, in * which case the chosen candidate carries the verified one. */ readonly webSearchToolType?: ResponsesWebSearchToolType; } /** The plugin-config fields the plan reads; `apply` projects the full section onto this. */ export interface PlanConfig { /** Whether a live capability probe verifies each candidate before use. */ readonly probe: boolean; /** Bound on one probe request, in milliseconds. */ readonly probeTimeoutMs: number; } /** * Normalize an anthropic-messages base so appending `/messages` reaches the * Messages endpoint under either base convention: the SDK-style root * (`https://api.anthropic.com` → `/v1/messages`) and the v1-included base * (`https://api.deepseek.com/anthropic/v1` → `/messages`). * @param baseURL - the configured or catalog base. * @returns the base `/messages` is appended to. */ export declare function ensureV1Base(baseURL: string): string; /** * Return the selected Copilot model's native search protocol. No endpoint or * cross-provider sibling is guessed. * @param route - the current chat route facts. * @returns the single native candidate, or none for an unsupported route. */ export declare function siblingCandidates(route: CurrentChatRoute): readonly { protocol: SearchProtocol; baseURL: string; }[]; /** * Resolve the candidate set for one plan from the current chat route. An * empty result means the plugin auto-disables — nothing to probe, nothing to * register. * @param ctx - plugin context for route detection. * @param config - the currently authoritative plan config. * @returns the candidates in probe order. */ export declare function resolveCandidates(ctx: Context, _config: PlanConfig): readonly SearchPlanCandidate[]; /** * Build only from the route captured by the caller, without rereading selection. * @param route - operation-local route facts. * @returns native Copilot candidates, or none without supported facts. */ export declare function candidatesForRoute(route: CurrentChatRoute | undefined): readonly SearchPlanCandidate[]; /** Lifecycle state of one search plan. */ export type SearchPlanStatus = 'probing' | 'ready' | 'failed'; /** * One candidate set plus its probe lifecycle. The probe runs in the * background so plugin load never blocks on a provider round-trip; * `available()` stays synchronous and `settle()` awaits the verdict. A * failed plan keeps its reason so the first search (or tool call) surfaces * the auto-disable diagnostic instead of a bare "no provider" error. */ export declare class SearchPlan { private readonly probe; /** Captured owner/proof lifetime, shared by probes and every served operation. */ readonly signal?: AbortSignal | undefined; readonly candidates: readonly SearchPlanCandidate[]; /** Resolves when the probe verdict (or the immediate decision) lands. */ readonly settled: Promise; private status; private chosen; private reason; /** * @param candidates - the candidates in probe order; empty disables the plan. * @param probe - verifies one candidate; called sequentially until one passes. * @param probeEnabled - when false the first candidate is trusted outright. * @param signal - captured owner/proof cancellation, retained through final HTTP. */ constructor(candidates: readonly SearchPlanCandidate[], probe: (candidate: SearchPlanCandidate) => Promise, probeEnabled: boolean, /** Captured owner/proof lifetime, shared by probes and every served operation. */ signal?: AbortSignal | undefined); /** Probe candidates in order; the first supported verdict wins. */ private runProbe; /** * Cheap synchronous usability check for the listener gate. While probing * the plan is PROVISIONALLY available — the first gated request may enter * and await {@link settle} — so the probe verdict and the stream start in * parallel; only a failed (or candidate-less) plan is unavailable and keeps * the request on the normal adapter path. * @returns whether a search can currently be served. */ available(): boolean; /** * Await the probe verdict and return the winning candidate. * @returns the candidate whose probe passed (or the first, when probing is off). * @throws WebError `WEB_PROVIDER_UNAVAILABLE` naming the auto-disable reason. */ settle(): Promise; /** The candidate currently serving searches, once the plan settled on one. */ chosenCandidate(): SearchPlanCandidate | undefined; /** The auto-disable reason, once a probe failed (or no candidate existed). */ failureReason(): string | undefined; } /** Whether two candidate sets are identical (skips re-probing on no-op settings changes). */ export declare function sameCandidates(left: readonly SearchPlanCandidate[], right: readonly SearchPlanCandidate[]): boolean; //# sourceMappingURL=plan.d.ts.map