/** * Response builder for `eddie_compose_recipe` (issue #1513). * * The bug this exists to fix: the handler inlined the FULL `guidelines` object * — use, dontUse, accessibility, anatomy, content, related, states — for every * matching page and every matching recipe, with no cap on how many matched. A * routine query ("account settings page with grouped form sections and * save/cancel action bar") produced a 90,419-character response and exceeded * the MCP tool output limit, so the tool errored instead of answering. * * That is the worst possible failure for this particular tool. `CLAUDE.md` * names `eddie_compose_recipe` as the thing to call *before* hand-rolling a * pattern, so when it hard-fails the agent falls back to composing from * primitives — which is Common Mistake #1 in that same document. * * The fix is a shortlist, not a dump: * * - Cap each section. A ranked list of 5 pages is more useful than 13 * unranked ones, and the ranking already exists. * - Carry a summary per hit — enough to CHOOSE — plus the `ref` needed to * get the rest. Full guidelines belong in `eddie_get_component`, which is * one call away and which `CLAUDE.md` already requires before writing * markup. Duplicating them here bought nothing. * - Enforce a hard byte budget as a backstop. If the shortlist is somehow * still too large, shed detail progressively and say so in the response, * rather than failing. A smaller answer beats an error every time. * * `truncated` is always present so the caller can tell a complete answer from * a trimmed one, and `totalMatches` reports what the caps hid — silent * truncation would read as "this is everything". */ import type { ComponentEntry, RecipeComponent } from '../types.js'; /** Ceiling for the serialized response. Well under the MCP tool output limit. */ export declare const MAX_RESPONSE_BYTES = 24000; /** Per-section caps. Ranked, so the head of each list is the useful part. */ export declare const CAPS: { readonly pages: 5; readonly recipeComponents: 8; readonly relevantComponents: 15; }; /** * `eddie_search`'s per-bucket caps. Here beside the compose caps so the routing * benchmark can assert its top-N fits inside the smallest of them instead of * knowing the numbers by heart (#2060). */ export declare const SEARCH_CAPS: { readonly pages: 5; readonly recipeComponents: 5; readonly components: 10; }; export interface ComposeRecipeEntry { name: string; intent: string; status: string; components: RecipeComponent[]; rules?: string[]; } /** * One shortlisted hit. Everything past the identity fields is optional, * because the builder sheds detail level by level to stay inside the budget — * `ref` is the one thing that is always present, since it is how the caller * gets back whatever was dropped. */ export interface ComposeHit { tagName: string; intent: string; package: string; path?: string; slots?: { name: string; description: string; }[]; use?: string[]; dontUse?: string[]; moreGuidelines?: number; ref: string; } export interface ComposeInput { intent: string; siteShell?: unknown; recipes: ComposeRecipeEntry[]; pages: ComponentEntry[]; recipeComponents: ComponentEntry[]; relevantComponents: ComponentEntry[]; } export interface ComposeResponse { query: string; siteShell?: unknown; recipes: ComposeRecipeEntry[]; pages: ComposeHit[]; recipeComponents: ComposeHit[]; relevantComponents: { tagName: string; intent: string; properties: string[]; slots: string[]; }[]; totalMatches: { pages: number; recipeComponents: number; relevantComponents: number; }; truncated: boolean; note?: string; } /** * Build the response, capped by count and then, if still oversized, by detail. * Never throws on size: the whole point is that a smaller answer beats an error. */ export declare function buildComposeResponse(input: ComposeInput): ComposeResponse; //# sourceMappingURL=compose-response.d.ts.map