/** * runManifest — the run-configuration manifest, composed. * * Pattern: Pure builder over already-resolved configuration. * Role: Turn what an Agent HOLDS into what `agentfootprint.agent.run_configured` * SAYS. Kept out of Agent.ts so the rule that governs it — names only, * absence never guessed — is testable without building an agent, and * so the one place that decides what may leave the process is one * small file rather than a paragraph inside a 3,000-line class. * Emits: N/A — the Agent dispatches what this returns. * * ## The rule this file exists to keep * * The manifest carries NAMES AND IDS ONLY. Not endpoints, not directories, not * connection strings, not keys, not tenants, not principals — and not a config * VALUE that could be any of those. It rides into every recording, every vendor * sink and every shared trace, which is exactly where a secret must not go. * * That rule is why this file takes an already-narrowed input rather than the * Agent: nothing here can reach a store's options bag even by accident, because * a store is never passed in. Where the only handle on a component is a value * (a directory, a URL, a table name), the component is reported as PRESENT and * left unnamed — {@link RunManifestSources.artifacts} is the shape of that * answer. A field the configuration did not declare is ABSENT: "the strategy * did not say" and "the default" are different facts, and only the first one is * true here. */ import type { AgentRunConfiguredPayload } from '../../events/payloads.js'; import type { MemoryDefinition } from '../../memory/define.types.js'; import type { AppliedRecipe } from '../../recipes/types.js'; /** * What the Agent hands over — already resolved, already narrowed to names. * * Every member is something the Agent knows at `createExecutor()` time, before * the first stage runs. Anything it does not know then is deliberately not on * this type: a manifest that had to run a stage to fill itself in would be * describing a run already in progress. */ export interface RunManifestSources { readonly agentId: string; /** `LLMProvider.name` of the effective (decorators included) provider. */ readonly providerName: string; /** The agent's resolved default model — the one this run starts with. */ readonly model: string; /** A `.configure()` resolver is mounted: it may replace the model per run, * and it runs in seed, AFTER this event. */ readonly hasRunConfig: boolean; /** Per-skill brains are mounted: they may replace provider/model per call. */ readonly hasSkillBrains: boolean; readonly reactMode: 'classic' | 'dynamic' | 'dynamic-grouped'; readonly memories: readonly MemoryDefinition[]; /** `WindowStrategy.name` from `.window()` / `.compaction()`. */ readonly windowStrategyName?: string; /** A skill graph is mounted — the OBJECT's presence in the payload means * exactly this, and each of its fields is separately optional. */ readonly skillGraph?: { readonly routing?: 'assist' | 'guard' | 'rails'; readonly continuity?: 'turn' | 'conversation'; /** `IntentScorer.name`. Undefined for a graph with no `.classify()`. */ readonly scorerName?: string; }; readonly evidenceGatePosture?: 'assist' | 'guard' | 'rails'; /** * The artifacts wiring, as booleans. * * `ArtifactStore` declares no id, so WHICH store is unnameable — and the * things that would identify one (a directory, a bucket, a table) are the * values this manifest exists not to carry. `configured` is the honest * remainder: a store IS in play. Omit the whole member when none is. */ readonly artifacts?: { readonly configured: true; readonly placement: boolean; readonly recordings: boolean; }; /** * The recipes `.recipe()` applied, in declaration order. * * Names and versions only — the same law the rest of this file keeps. A * recipe's `description` is prose about the composition and never travels; * what a consumer GROUPS on is the pair, and the pair stays two fields (a * composed `'id@version'` would be one string two different pairs could * produce). * * ABSENT, not `[]`, when an agent applied none — and this is the one place * that differs from {@link memories}, deliberately. "No memory is mounted" is * an arm a study compares against, so it is stated. "No recipe" is the state * of every agent written before recipes existed, and stamping an empty list * on all of them would put new bytes in every recording, every vendor sink * and every stored manifest for a feature nobody used. */ readonly recipes?: readonly AppliedRecipe[]; } /** * Compose the manifest. Pure: same input, same payload, no clock, no ids * minted here (the runId the arms are grouped by is already on `meta`). */ export declare function buildRunManifest(sources: RunManifestSources): AgentRunConfiguredPayload;