/** * The composition merge: every contributor's tools and skills folded into the * registries that already exist — tools into the one tool registry, skills into * the workspace mount. * * There is no wrapper type around a contribution. App generation, automations * and the host's own `createVendo({ tools, skills })` all arrive here as the * same two lists, labelled with WHERE they came from, and the label exists for * exactly one reason: the collision message has to name both claimants. * * Two laws live here and nowhere else: * * - **No renaming, ever.** A name is global as authored. A skill body says * `check_report`, and projecting a skill is a copy rather than a translation, * so a prefixed tool name would point the model at a tool that does not exist. * - **Boot-collision IS the namespacing.** Two contributors claiming one name is * an error at boot that names both of them, so the conflict is fixed by * whoever configured them rather than papered over at runtime. */ import { type Skill, type ToolDefinition, type ToolRegistry } from "../core/index.js"; /** * One source of capability, as composition sees it. * * `from` is a LABEL, not an identity: it names the contributor in a collision * message ("apps", `createVendo({ tools })`) and does nothing else. Nothing is * keyed by it, nothing is looked up by it, and two contributions may not share * one — that would make a collision message ambiguous. */ export interface Contribution { from: string; tools?: readonly ToolDefinition[]; skills?: readonly Skill[]; } export interface MergedCapability { /** Every contributed tool as one registry, ready for `actions.add(...)` — so * they are guarded, audited, and projected identically to host tools. */ tools: ToolRegistry; skills: Skill[]; /** Which contributor declared each tool name, so a collision with the host's * own extracted tools can be reported naming it rather than "added registry". */ toolOwners: ReadonlyMap; } export declare const mergeCapability: (contributions: readonly Contribution[]) => MergedCapability;