import type { GridApi } from '../../core/grid-api'; import type { PhotonAICommandRegistry } from '../photon-ai-registry'; import { type PhotonAIContextScope, type PhotonGridContext } from './ai-provider.types'; /** * Distills the live grid into the compact {@link PhotonGridContext} a language * model needs to interpret a command: which columns exist, which actions are * possible, and what the grid currently looks like. * * Every piece is read from the *live* {@link GridApi} and * {@link PhotonAICommandRegistry} at build time, so the model always reasons * over the grid's current shape — including any custom intents a host app * registered at runtime (they appear in {@link buildCapabilities} automatically * because it reads the registry, never a hard-coded list). This is what keeps * the generative back-end in lock-step with the deterministic one: both are * driven by the same registry. * * ### Scoping * When a {@link PhotonAIContextScope} is supplied (produced by * `ContextRouter`), the snapshot is narrowed to it: only in-scope capabilities, * only the column fields those domains actually read, and only the state slices * they need. A "sort by price" request therefore carries no filter operators, * no pin state, and no per-column `filterable`/`groupable` flags — which is * where the token saving comes from, since column fields multiply by column * count. Omitting the scope reproduces the original full snapshot exactly. */ export declare class GridContextBuilder { private readonly api; private readonly registry; constructor(api: GridApi, registry: PhotonAICommandRegistry); /** * Builds a fresh snapshot. Cheap enough to call once per prompt. * * @param scope - Optional routing result. Omit to include everything. */ build(scope?: PhotonAIContextScope): PhotonGridContext; private buildColumns; /** * Projects one column down to the fields the in-scope domains actually read. * * `colId`, `header`, and `type` are always sent: the model needs an id to echo * back, a human name to match the user's wording against, and a type to reason * about values. Everything else is per-domain — and since these fields repeat * for every column, dropping them is the single biggest lever on payload size * for a wide grid. */ private toColumnContext; /** Enumerated values a `dropdown`/`enum` column accepts, so the model filters by a real value. */ private columnOptions; /** * The catalog of actions the model may emit — one entry per registered * intent whose domain is in scope. Sourced from the registry so it never * drifts from what `CommandExecutor` can actually run. * * An intent the router cannot attribute to any domain is always included: * that is the signature of a custom intent registered by a host app, and * silently withholding it would make third-party commands unreachable * through the generative path. */ private buildCapabilities; /** * Live grid state, narrowed to the slices the in-scope domains need. * * Row counts are unconditional — they are two numbers, and almost any reply * ("sorted 1,200 rows") reads better with them. The rest is omitted rather * than emptied, so the model is never told "nothing is filtered" by an empty * array when the truth is "filters were not part of this question". */ private buildState; private buildSortState; private buildFilterState; } //# sourceMappingURL=grid-context-builder.d.ts.map