/** * Model capability auto-detection: derive what the harness may load onto a model FROM the model's * own metadata (`Model.contextWindow`), so small open models (4k/8k/16k windows, sub-1B params) * can still hold a usable chat instead of drowning in the stable prompt, tool schemas, and * background-lane prompts. The same class is the single input to prompt shaping and tool/lane gates. * * Derivation is metadata-first; defaults apply only when the metadata is missing (unknown/zero * window keeps today's full behavior rather than guessing). Detection can be disabled or forced * per class via the `modelCapability.mode` setting. */ export type ModelCapabilityClass = "full" | "lean" | "minimal" | "chat"; export type ModelCapabilityMode = "auto" | "off" | ModelCapabilityClass; export interface ModelCapabilityProfile { class: ModelCapabilityClass; contextWindow?: number; reasonCode: string; /** Hard aggregate character envelope for the stable system prompt; undefined = intentionally unbounded. */ systemPromptMaxChars: number | undefined; /** Allow-list; undefined = no allow-list restriction. */ allowedToolNames?: readonly string[]; /** Block-list applied after the allow-list; undefined = nothing blocked. */ blockedToolNames?: readonly string[]; /** Whether resource-heavy research/delegation background lanes may run on this model. */ backgroundLanesEnabled: boolean; /** Output-token cap for lane isolated completions, scaled to the window. */ laneMaxOutputTokens: number; } /** Windows at or above this keep the full harness surface. */ export declare const MODEL_CAPABILITY_FULL_MIN_CONTEXT = 32768; /** Windows at or above this keep core tools but shed background-autonomy extras. */ export declare const MODEL_CAPABILITY_LEAN_MIN_CONTEXT = 16384; /** Windows at or above this get the minimal coding set; below is chat-only. */ export declare const MODEL_CAPABILITY_MINIMAL_MIN_CONTEXT = 8192; /** * Aggregate stable-prompt envelopes. These are deliberately owned beside the classification * thresholds so every harness expansion must fit the same profile that owns tools and lanes. * Full/off profiles are intentionally unbounded; constrained profiles fail visibly on overflow. */ export declare const MODEL_CAPABILITY_SYSTEM_PROMPT_MAX_CHARS: Readonly>; /** * Aggregate rendered budget for tool-guideline bullets. Individual tool definitions retain their * own prose bound; constrained profiles additionally need one cross-tool ceiling so platform-only * guidance cannot overflow the stable system-prompt envelope. The builder admits one rule per tool * before lower-priority rules, preserving each tool owner's first-rule priority convention. */ export declare const MODEL_CAPABILITY_TOOL_GUIDELINES_MAX_CHARS: Readonly>; export declare const MODEL_CAPABILITY_LEAN_BLOCKED_TOOLS: readonly string[]; export declare const MODEL_CAPABILITY_MINIMAL_ALLOWED_TOOLS: readonly string[]; export declare const MODEL_CAPABILITY_CHAT_ALLOWED_TOOLS: readonly string[]; export declare const DEFAULT_LANE_MAX_OUTPUT_TOKENS = 2048; /** * Mandatory provider-neutral gate for a final system prompt. This intentionally rejects rather * than truncates: arbitrary truncation can silently remove security, repair, or project rules. */ export declare function enforceModelCapabilitySystemPromptBudget(systemPrompt: string, profile: Pick): string; export declare function deriveModelCapabilityProfile(args: { contextWindow?: number; mode?: ModelCapabilityMode; }): ModelCapabilityProfile; /** Apply the profile's allow/block lists to a requested tool-name list, preserving order. */ export declare function filterToolNamesForCapability(toolNames: readonly string[], profile: ModelCapabilityProfile): string[]; /** * Lane-worker eligibility: a session bound to a worktree-sync lane (`--worktree-lane` / * `PI_WORKTREE_LANE`, see worktree-sync/runtime.ts) is expected to drive the FULL multi-step * lane-gate/recovery surface -- sync, conflict recovery, land -- unattended. A sub-full capability * class or a model with no working native tool-call path cannot reliably drive that surface. This * rides the SAME capability system every other adaptation in this file rides (class + context * window + the `/toolprobe` verdict) -- no parallel mechanism, no new env var, no new registry field. */ export type LaneWorkerRefusalReason = "capability_class_below_full" | "context_window_unknown" | "tool_calling_unadvertised" | "tool_calling_demoted"; export interface LaneWorkerRefusal { reason: LaneWorkerRefusalReason; capabilityClass: ModelCapabilityClass; contextWindow?: number; } /** * Decide whether the model described by `args` may drive a worktree-sync lane worker. First * failure wins, in order: capability class below full; an unknown/undeclared context window (the * classifier's own registry-derived SSOT -- see `deriveModelCapabilityProfile`; a full class can * still carry an undefined window via the `unknown_context_window_defaults` fallback); no * ADVERTISED native tool-call path (`Model.textToolCallProtocol` unset/false -- set true means * phone-only); or a GRADED `/toolprobe` demotion to "text-protocol"/"none". An UNPROBED model (no * verdict on record yet) is eligible on its advertised support alone -- unprobed is never treated * as demoted. `undefined` means eligible. */ export declare function evaluateLaneWorkerRefusal(args: { capabilityClass: ModelCapabilityClass; contextWindow: number | undefined; toolCallingAdvertised: boolean; toolCallingDemoted: boolean; }): LaneWorkerRefusal | undefined; /** Stable, greppable prefix for {@link formatLaneWorkerRefusal}'s output. */ export declare const LANE_WORKER_REFUSAL_PREFIX = "worktree-sync lane-worker refusal:"; /** Format a refusal into one deterministic, greppable line naming the lane, class, window, and reason. */ export declare function formatLaneWorkerRefusal(refusal: LaneWorkerRefusal, laneKey?: string): string; //# sourceMappingURL=model-capability.d.ts.map