/** * Skills activation pipeline. * * Renders the **active-skill block** that lands in the wire `instructions` * field above the slim-index block whenever the SDK has any caller-pinned * skills to activate. The block is the on-the-wire shape of "this skill's * body is loaded into the conversation and authoritative for the rest of * the run". * * Inputs: a manager, a list of pinned `ParsedSkill`s (in pin order), and * the resolved trust + caps state from `SkillsManager`. * * Outputs: rendered text + telemetry events. Pure — no side effects; the * caller forwards events to the configured sink and decides what to do * with the text. * * `requires:` resolution lives here too — caller-pin activation is the * one path where the SDK resolves a transitive requires graph eagerly * (the MCP server's `get_skill` handler does the same for LLM-driven * activation, sharing the same helper functions). * * Per `skills-activation.md` §2 the block contract: * * - One `` ... `` per skill, in * resolution order (deps before dependents). * - Combined body text is wrapped in `` so the renderer * can defensively close the block at a single known footer regardless * of what skill authors put in their bodies. * - A preamble warns the model the entries are authoritative skill * bodies, distinct from the *advisory* `` index * that follows. */ import type { ResolvedRequiresCaps, SkillsManager } from './manager.js'; import type { ParsedSkill, SkillEvent } from './types.js'; /** * Resolved activation graph for one caller-pinned root. Carries every * `ParsedSkill` that should be activated (root + transitive `requires`), * in body-injection order (deps first, root last). */ export interface ActivationGraph { readonly root: ParsedSkill; readonly ordered: readonly ParsedSkill[]; } /** * Outcome of `resolveActivationGraph` for one root. */ export type ActivationGraphResult = { readonly outcome: 'ok'; readonly graph: ActivationGraph; } | { readonly outcome: 'requires_trust_violation'; readonly child: ParsedSkill; readonly reason: string; } | { readonly outcome: 'requires_cap_exceeded'; readonly kind: 'depth' | 'breadth' | 'token_budget'; readonly limit: number; readonly actual: number; } | { readonly outcome: 'requires_cycle'; readonly fqn: string; } | { readonly outcome: 'requires_unresolved'; readonly specifier: string; }; /** * Synchronous lookup adapter the resolver uses to walk a `requires:` * chain. Both call sites (the SDK's caller-pin path and the MCP server's * `get_skill` LLM-driven path) build one of these from an already-loaded * catalog snapshot — the catalog is `discover()`'d once at connect time, * so the lookup itself is always sync. */ export interface SkillLookup { get(specifier: string): ParsedSkill | null; isTrusted(skill: ParsedSkill): boolean; readonly caps: ResolvedRequiresCaps; } /** * Build a sync `SkillLookup` from an already-loaded catalog snapshot * plus a `SkillsManager` (for trust + caps). Callers acquire the * snapshot via `await manager.discover()` (or `manager.currentSnapshot` * when already present) before constructing the lookup. */ export declare function lookupFromSnapshot(skills: readonly ParsedSkill[], manager: SkillsManager): SkillLookup; /** * Resolve a single root skill's `requires:` chain with the depth / * breadth / token caps applied. Trust is enforced transitively per * `skills-trust.md` §3. * * The resolver runs *before* any body injection — if any check fails, * the result carries a `non-ok` outcome and the caller never composes * a partial body block. */ export declare function resolveActivationGraph(root: ParsedSkill, lookup: SkillLookup): ActivationGraphResult; /** * Resolution outcome for a multi-pin activation. `ok` carries the * combined ordered list (deps first, dependents next) with duplicates * deduplicated by FQN. A failure carries the FQN of the root whose * graph couldn't be resolved plus the same per-root outcome shape. */ export type MultiActivationResult = { readonly outcome: 'ok'; readonly ordered: readonly ParsedSkill[]; readonly events: readonly SkillEvent[]; } | { readonly outcome: 'failed'; readonly events: readonly SkillEvent[]; readonly failure: { readonly root: ParsedSkill; readonly result: Exclude; }; }; /** * Resolve the activation graphs for every caller-pinned root and stitch * them into one ordered list (deps before dependents, deduplicated by * FQN). On first-failure-encountered, return early with the failure * payload — the caller throws a `QodoSkillError` so no partial body * lands in the wire payload. * * Events emitted across the resolve are accumulated in `events` so the * caller can forward them to the `SkillsManager` sink. (Failure paths * emit `requires_*` events; the success path emits nothing — the * `activated` events fire when the body is *injected*, which is the * caller's responsibility.) */ export declare function resolveAllActivations(roots: readonly ParsedSkill[], lookup: SkillLookup): MultiActivationResult; /** * Renderer output for the active-skill block. `text` is the block ready * to prepend to the wire `instructions`; `events` records caller-side * telemetry (`activated`, `disable_model_invocation_overridden`, * `allowed_tools_applied` / `_advisory`, `hooks_ignored`) the caller * forwards to `SkillsManager.forwardEvents`. */ export interface ActiveSkillsRenderResult { readonly text: string; readonly skills: readonly ParsedSkill[]; readonly events: readonly SkillEvent[]; } /** * Render the active-skill block from an ordered list of skills (deps * first, dependents next; output of `resolveAllActivations`). Empty input * → empty text + no events. * * Also generates per-skill activation telemetry. The events cover: * * - `sdk.skill.activated { source: 'caller' }` for every skill. * - `sdk.skill.disable_model_invocation_overridden` when a caller pin * forces a `disable-model-invocation: true` skill into the run * (`skills-activation.md` §2.85). * - `sdk.skill.allowed_tools_applied` / `_advisory` per the trust gate. * - `sdk.skill.hooks_ignored` for third-party skills declaring `hooks:` * (`skills-trust.md` §6). */ export declare function renderActiveSkillsBlock(ordered: readonly ParsedSkill[], manager: SkillsManager): ActiveSkillsRenderResult; /** * Convert a non-ok `ActivationGraphResult` into the human-readable error * message thrown from the caller-pin path. Kept here so the MCP server's * LLM-driven path and the SDK's caller-pin path produce the same wording * on the same failure shape. */ export declare function activationFailureMessage(root: ParsedSkill, failure: Exclude): string; /** * Cap on the `agent` field carried inside `sdk.skill.fork_declined` * telemetry. The skill-file hard cap is 256 KB; without a per-field * cap on telemetry payloads, a misconfigured (or hostile) skill could * emit multi-KB events that bloat downstream sinks. 128 chars covers * every realistic agent identifier seen in the OSS skill survey; * anything longer gets truncated with an ellipsis marker so the * observability layer sees that overflow happened. */ export declare const MAX_AGENT_FIELD_CHARS = 128; export declare function capAgentField(agent: string): string; //# sourceMappingURL=activation.d.ts.map