@toclocoinc/lattice-grid 1.42.0 → 1.44.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/docs/API.html +97 -2
- package/docs/api-detail.html +1 -1
- package/lattice-grid.d.ts +204 -9
- package/lattice-grid.esm.min.js +25 -12
- package/lattice-grid.min.cjs +25 -12
- package/lattice-grid.min.js +25 -12
- package/modules/ai.esm.min.js +2628 -11
- package/modules/ai.min.cjs +2628 -11
- package/modules/ai.min.js +2628 -11
- package/modules/angular.esm.min.js +2 -2
- package/modules/angular.min.cjs +2 -2
- package/modules/angular.min.js +2 -2
- package/modules/chart-alluvial.esm.min.js +1 -1
- package/modules/chart-arc.esm.min.js +1 -1
- package/modules/chart-bubblemap.esm.min.js +1 -1
- package/modules/chart-bump.esm.min.js +1 -1
- package/modules/chart-calendar.esm.min.js +1 -1
- package/modules/chart-decomposition.esm.min.js +1 -1
- package/modules/chart-diverging.esm.min.js +1 -1
- package/modules/chart-dumbbell.esm.min.js +1 -1
- package/modules/chart-fan.esm.min.js +1 -1
- package/modules/chart-hexbin.esm.min.js +1 -1
- package/modules/chart-hexmap.esm.min.js +1 -1
- package/modules/chart-icicle.esm.min.js +1 -1
- package/modules/chart-parallel.esm.min.js +1 -1
- package/modules/chart-ridgeline.esm.min.js +1 -1
- package/modules/chart-roc.esm.min.js +1 -1
- package/modules/chart-slope.esm.min.js +1 -1
- package/modules/chart-splom.esm.min.js +1 -1
- package/modules/chart-waffle.esm.min.js +1 -1
- package/modules/charts.esm.min.js +4 -4
- package/modules/charts.min.cjs +4 -4
- package/modules/charts.min.js +4 -4
- package/modules/data-router.esm.min.js +4 -4
- package/modules/data-router.min.cjs +4 -4
- package/modules/data-router.min.js +4 -4
- package/modules/devtools.esm.min.js +2 -2
- package/modules/devtools.min.cjs +2 -2
- package/modules/devtools.min.js +2 -2
- package/modules/dhtmlx-compat.esm.min.js +4 -4
- package/modules/dhtmlx-compat.min.cjs +4 -4
- package/modules/dhtmlx-compat.min.js +4 -4
- package/modules/gantt.esm.min.js +4 -4
- package/modules/gantt.min.cjs +4 -4
- package/modules/gantt.min.js +4 -4
- package/modules/htmx.esm.min.js +25 -12
- package/modules/htmx.min.cjs +25 -12
- package/modules/htmx.min.js +25 -12
- package/modules/kanban.esm.min.js +16 -13
- package/modules/kanban.min.cjs +16 -13
- package/modules/kanban.min.js +16 -13
- package/modules/kpi.esm.min.js +4 -4
- package/modules/kpi.min.cjs +4 -4
- package/modules/kpi.min.js +4 -4
- package/modules/mock-socket.esm.min.js +2 -2
- package/modules/mock-socket.min.cjs +2 -2
- package/modules/mock-socket.min.js +2 -2
- package/modules/react.esm.min.js +2 -2
- package/modules/react.min.cjs +2 -2
- package/modules/react.min.js +2 -2
- package/modules/svelte.esm.min.js +2 -2
- package/modules/svelte.min.cjs +2 -2
- package/modules/svelte.min.js +2 -2
- package/modules/vue.esm.min.js +2 -2
- package/modules/vue.min.cjs +2 -2
- package/modules/vue.min.js +2 -2
- package/modules/webcomponent.esm.min.js +25 -12
- package/modules/webcomponent.min.cjs +25 -12
- package/modules/webcomponent.min.js +25 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
dependencies, no build step required. Optional adapters for React, Vue, Svelte
|
|
5
5
|
and Web Components ship alongside it.
|
|
6
6
|
|
|
7
|
-
Version 1.
|
|
7
|
+
Version 1.44.0 · [latticegrid.dev](https://www.latticegrid.dev) · TOCLOCO Inc
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
package/docs/API.html
CHANGED
|
@@ -2498,6 +2498,101 @@ grid.permissions.setContext({ role: 'clerk' }); // re-resolves everything</
|
|
|
2498
2498
|
</div>
|
|
2499
2499
|
<div class="note"><p>Actions: <code>setFilters</code>, <code>setSort</code>, <code>groupBy</code>, <code>showColumns</code>, <code>hideColumns</code>, <code>setQuick</code>, <code>clear</code>. Nothing else is executable, so a model cannot be talked into an operation the vocabulary does not contain. <code>docs/AI-SKILL.md</code> is the reference to hand your model.</p></div>
|
|
2500
2500
|
|
|
2501
|
+
<h3 id="ai-askdata">Ask-your-data (<code>modules/ai</code>)</h3>
|
|
2502
|
+
<p>The opt-in AI module (<code>createAI</code>, UMD <code>LatticeGridAI</code>) turns a question into
|
|
2503
|
+
a validated <strong>read-only</strong> query spec, runs it in the grid's own engine over the
|
|
2504
|
+
<code>grid.ai</code> skill layer, and — on apply — fans the answer to any router-attached viewers
|
|
2505
|
+
(a chart, a KPI tile) through the Data Router's <code>load()</code>. It uses the same BYO
|
|
2506
|
+
<code>ask()</code> seam as the rest of the module: the grid makes no model call and holds no key.
|
|
2507
|
+
Ask-your-data is read-only; a write/mutation the model asks for is <strong>refused and never
|
|
2508
|
+
executed</strong> (writes are a separate, human-gated feature).</p>
|
|
2509
|
+
<div class="table-wrap">
|
|
2510
|
+
<table>
|
|
2511
|
+
<thead><tr><th>Method</th><th>Returns</th><th>Description</th></tr></thead>
|
|
2512
|
+
<tbody>
|
|
2513
|
+
<tr><td class="sig">query(question, opts?)</td><td class="type">Promise<result></td><td class="desc">Ask the model, validate the reply into a read-only spec. <code>result.describe()</code> shows the resolved query; nothing applies until <code>result.apply()</code> (or <code>autoApply</code>).</td></tr>
|
|
2514
|
+
<tr><td class="sig">applyQuery(result, opts?)</td><td class="type">object</td><td class="desc">Apply a reviewed result. Re-gated at the seam: an unsafe plan is refused. <code>opts.router</code> fans the answer to other viewers.</td></tr>
|
|
2515
|
+
<tr><td class="sig">askBar(el, opts?)</td><td class="type">controller</td><td class="desc">Mount the ask/review/apply bar with an "auto-apply safe reads" toggle (off by default).</td></tr>
|
|
2516
|
+
</tbody>
|
|
2517
|
+
</table>
|
|
2518
|
+
</div>
|
|
2519
|
+
<pre data-run="js" data-expect="2 rows; write refused" data-covers="export:createAI"><code>const { createHeadlessGrid } = await import('../packages/core/src/index.js');
|
|
2520
|
+
const { createAI } = await import('../packages/modules/ai/index.js');
|
|
2521
|
+
const grid = createHeadlessGrid({
|
|
2522
|
+
rowKey: 'id',
|
|
2523
|
+
columns: [{ field: 'id' }, { field: 'region' }, { field: 'amount', type: 'number' }],
|
|
2524
|
+
rows: [{ id: 1, region: 'EMEA', amount: 100 }, { id: 2, region: 'AMER', amount: 300 }, { id: 3, region: 'EMEA', amount: 200 }],
|
|
2525
|
+
});
|
|
2526
|
+
// Your model returns a schema-constrained SPEC, never rows. WE run it, read-only.
|
|
2527
|
+
const reads = createAI(grid, { ask: async () => ({ actions: [{ type: 'setFilters', filters: { col: 'region', op: 'eq', value: 'EMEA' } }] }) });
|
|
2528
|
+
const result = await reads.query('EMEA only');
|
|
2529
|
+
result.apply();
|
|
2530
|
+
const rows = grid.rows.data().length;
|
|
2531
|
+
// A write verb is refused by the read-only gate and never executed.
|
|
2532
|
+
const writes = createAI(grid, { ask: async () => ({ actions: [{ type: 'setCells', edits: [] }] }) });
|
|
2533
|
+
const write = await writes.query('change the data');
|
|
2534
|
+
return `${rows} rows; write ${write.ok ? 'allowed' : 'refused'}`;</code></pre>
|
|
2535
|
+
|
|
2536
|
+
<h3 id="ai-actor">AI as a governed actor (<code>modules/ai</code>, writes)</h3>
|
|
2537
|
+
<p>The governed actor lets the model <strong>propose</strong> edits — a single NL-targeted
|
|
2538
|
+
change (“set the Network Upgrade project to In Progress”) or a bulk cleanup —
|
|
2539
|
+
that a human previews as a <strong>before/after diff</strong> and approves. The model NEVER writes.
|
|
2540
|
+
On approval the edit applies through the grid's <em>own</em> gate, exactly like a person's edit:
|
|
2541
|
+
a grid cell edit via <code>grid.edit.setCells(writes, 'cell', { origin: 'ai' })</code> (the
|
|
2542
|
+
<code>beforeEdit</code> veto), a Kanban card move via <code>board.move(…, { origin: 'ai' })</code>
|
|
2543
|
+
(the <code>beforeMove</code> veto). <strong>The AI can never bypass the gate:</strong> a host
|
|
2544
|
+
<code>beforeEdit</code>/<code>beforeMove</code> handler that calls <code>preventDefault()</code>
|
|
2545
|
+
(or vetoes async) stops the write, and nothing persists. Writes carry <code>origin: 'ai'</code>
|
|
2546
|
+
on the before-event payload, so a host can allow a person's edit while vetoing the AI's —
|
|
2547
|
+
policing AI writes distinctly. Approved edits are optimistic and revert on a source reject
|
|
2548
|
+
through the shipped write-back (there is no separate <code>beforeCommit</code> event; the edit gate
|
|
2549
|
+
is <code>beforeEdit</code>, and the optimistic/revert half is <code>grid.edit.settle</code>).</p>
|
|
2550
|
+
<p>NL targeting and any bulk edit bind to the <strong>current filtered view</strong>
|
|
2551
|
+
(<code>grid.rows.data()</code>), never the whole table implicitly; a target not in the view is
|
|
2552
|
+
surfaced for an explicit opt-in <code>widen</code>, not edited silently. A human label is resolved
|
|
2553
|
+
to the column's stored option value; an unknown label is rejected, not coerced. An ambiguous match
|
|
2554
|
+
(more than one row) surfaces its candidates for the user to pick.</p>
|
|
2555
|
+
<div class="table-wrap">
|
|
2556
|
+
<table>
|
|
2557
|
+
<thead><tr><th>Method</th><th>Returns</th><th>Description</th></tr></thead>
|
|
2558
|
+
<tbody>
|
|
2559
|
+
<tr><td class="sig">propose(instruction, opts?)</td><td class="type">Promise<proposal></td><td class="desc">Ask the model for structured edits, validate + resolve them against the current view, and return a reviewable proposal with a before/after <code>diff</code>. Nothing is written. <code>opts.widen</code> opts into the full dataset; <code>opts.board</code> routes a Kanban move.</td></tr>
|
|
2560
|
+
<tr><td class="sig">applyProposal(proposal, opts?)</td><td class="type">Promise<report></td><td class="desc">Apply an approved proposal through the gate (<code>origin: 'ai'</code>). A vetoing before-handler stops it; the report gives <code>applied</code>/<code>vetoed</code>.</td></tr>
|
|
2561
|
+
<tr><td class="sig">actorBar(el, opts?)</td><td class="type">controller</td><td class="desc">Mount the propose → review-diff → approve bar, stating the scope.</td></tr>
|
|
2562
|
+
</tbody>
|
|
2563
|
+
</table>
|
|
2564
|
+
</div>
|
|
2565
|
+
<pre data-run="js" data-expect="diff To do then In Progress; vetoed kept todo; approved wrote doing" data-covers="export:createAI"><code>const { createHeadlessGrid } = await import('../packages/core/src/index.js');
|
|
2566
|
+
const { createAI } = await import('../packages/modules/ai/index.js');
|
|
2567
|
+
const status = { options: [{ id: 'todo', label: 'To do' }, { id: 'doing', label: 'In Progress' }] };
|
|
2568
|
+
const seed = () => createHeadlessGrid({
|
|
2569
|
+
rowKey: 'id',
|
|
2570
|
+
columns: [{ field: 'id' }, { field: 'name' }, { field: 'status', lookup: status, edit: { enabled: true } }],
|
|
2571
|
+
rows: [{ id: 'r1', name: 'Network Upgrade', status: 'todo' }, { id: 'r2', name: 'Payroll', status: 'todo' }],
|
|
2572
|
+
});
|
|
2573
|
+
// A MOCK ask() returns a structured PROPOSAL — never a write, never rows.
|
|
2574
|
+
const ask = async () => ({ structured: { edits: [{ match: 'Network Upgrade', column: 'status', value: 'In Progress' }] } });
|
|
2575
|
+
|
|
2576
|
+
// Propose: a before/after diff, nothing written yet.
|
|
2577
|
+
let grid = seed();
|
|
2578
|
+
let ai = createAI(grid, { ask });
|
|
2579
|
+
const proposal = await ai.propose('set the Network Upgrade project to In Progress');
|
|
2580
|
+
const d = proposal.diff[0];
|
|
2581
|
+
const before = `${d.oldDisplay} then ${d.newDisplay}`;
|
|
2582
|
+
|
|
2583
|
+
// A vetoing beforeEdit handler on the AI write => NOTHING persists.
|
|
2584
|
+
grid.on('beforeEdit', (e) => { if (e.origin === 'ai') e.preventDefault('reviewed elsewhere'); });
|
|
2585
|
+
await ai.applyProposal(proposal);
|
|
2586
|
+
const vetoed = grid.rows.byKey('r1').data.status;
|
|
2587
|
+
|
|
2588
|
+
// Approve on a grid with no veto => the edit lands through the gate.
|
|
2589
|
+
grid = seed();
|
|
2590
|
+
ai = createAI(grid, { ask });
|
|
2591
|
+
await ai.applyProposal(await ai.propose('set the Network Upgrade project to In Progress'));
|
|
2592
|
+
const approved = grid.rows.byKey('r1').data.status;
|
|
2593
|
+
|
|
2594
|
+
return `diff ${before}; vetoed kept ${vetoed}; approved wrote ${approved}`;</code></pre>
|
|
2595
|
+
|
|
2501
2596
|
<h2 id="overlay">grid.overlay</h2>
|
|
2502
2597
|
<div class="table-wrap">
|
|
2503
2598
|
<table>
|
|
@@ -7658,7 +7753,7 @@ return `next ${p.mean.toFixed(1)}; r2 ${f.r2.toFixed(1)}; band ${p.upper - p.low
|
|
|
7658
7753
|
<tr><td class="name">stop</td><td class="type">(cancel?: boolean): void</td><td class="desc"></td></tr>
|
|
7659
7754
|
<tr><td class="name">undo</td><td class="type">(): void</td><td class="desc"></td></tr>
|
|
7660
7755
|
<tr><td class="name">redo</td><td class="type">(): void</td><td class="desc"></td></tr>
|
|
7661
|
-
<tr><td class="name">setCells</td><td class="type">(
|
|
7756
|
+
<tr><td class="name">setCells</td><td class="type">(</td><td class="desc">Write several cells as one undoable step (§12). `opts.origin` defaults to `'api'` — the ungated seam every existing caller uses (a fill, a paste, a kanban move), unchanged. Pass `{ origin: 'ai' }` (or `'user'`) to route the write through the cancellable `beforeEdit` gate, exactly as an interactive edit is (BACKLOG-0000967): the AI writes through this so a host `beforeEdit` handler can veto it and nothing persists when it does. With a gated origin and an async (deferring) before-handler, the return is a `Promise<number>`.</td></tr>
|
|
7662
7757
|
<tr><td class="name">bulkSet</td><td class="type">(value: unknown, opts?: { cells?: { key: string; colId: string }[] }): number</td><td class="desc">Set one value across a block of cells as a single undoable step (§12, card 740). Defaults to the selected range; read-only and non-editable cells are skipped and every write runs the normal parse/validate path.</td></tr>
|
|
7663
7758
|
<tr><td class="name">fill</td><td class="type">(opts?: { direction?: 'down' | 'up' | 'left' | 'right'; series?: boolean; range?: CellRange }): number</td><td class="desc">Fill a selected range from its leading edge as one undoable step (§12, card 740). The default copies the anchor across the range (Excel's Ctrl+D and its natural siblings); `series: true` extrapolates a numeric or date series from the first one or two cells of each line, falling back to a copy for types with no series. `direction` defaults to `'down'`.</td></tr>
|
|
7664
7759
|
<tr><td class="name">pasteInto</td><td class="type">(anchor: { key: string; colId: string }, text: string, extent?: { rows?: number; columns?: number }): number</td><td class="desc"></td></tr>
|
|
@@ -8202,7 +8297,7 @@ return `next ${p.mean.toFixed(1)}; r2 ${f.r2.toFixed(1)}; band ${p.upper - p.low
|
|
|
8202
8297
|
<thead><tr><th>Member</th><th>Type</th><th>Description</th></tr></thead>
|
|
8203
8298
|
<tbody>
|
|
8204
8299
|
<tr><td class="name">type</td><td class="type">string</td><td class="desc"></td></tr>
|
|
8205
|
-
<tr><td class="name">origin</td><td class="type">'api' | 'user' | 'init'</td><td class="desc"
|
|
8300
|
+
<tr><td class="name">origin</td><td class="type">'api' | 'user' | 'init' | 'ai'</td><td class="desc">Who caused the action. `'ai'` (BACKLOG-0000967) tags a write an AI proposed and a human approved, applied through `grid.edit.setCells(writes, type, { origin: 'ai' })`; it fires the same cancellable `beforeEdit` gate a `'user'` edit does, so a host can policy-gate AI writes distinctly.</td></tr>
|
|
8206
8301
|
<tr><td class="name">grid</td><td class="type">Grid</td><td class="desc"></td></tr>
|
|
8207
8302
|
</tbody>
|
|
8208
8303
|
</table>
|
package/docs/api-detail.html
CHANGED
|
@@ -437,7 +437,7 @@
|
|
|
437
437
|
<div class="shell">
|
|
438
438
|
<aside class="rail">
|
|
439
439
|
<p class="rail__brand">Lattice Grid</p>
|
|
440
|
-
<p class="rail__sub">Developer guide · v1.
|
|
440
|
+
<p class="rail__sub">Developer guide · v1.44.0</p>
|
|
441
441
|
<nav>
|
|
442
442
|
<div class="rail__group">
|
|
443
443
|
<span class="rail__label">Start here</span>
|
package/lattice-grid.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* Lattice Grid 1.
|
|
2
|
+
* Lattice Grid 1.44.0, type declarations
|
|
3
3
|
* Copyright (c) 2026 TOCLOCO Inc. All rights reserved.
|
|
4
4
|
* https://latticegrid.dev
|
|
5
5
|
*/
|
|
@@ -3772,7 +3772,13 @@ export type EventName =
|
|
|
3772
3772
|
|
|
3773
3773
|
export interface GridEvent {
|
|
3774
3774
|
type: string;
|
|
3775
|
-
|
|
3775
|
+
/**
|
|
3776
|
+
* Who caused the action. `'ai'` (BACKLOG-0000967) tags a write an AI proposed
|
|
3777
|
+
* and a human approved, applied through `grid.edit.setCells(writes, type,
|
|
3778
|
+
* { origin: 'ai' })`; it fires the same cancellable `beforeEdit` gate a
|
|
3779
|
+
* `'user'` edit does, so a host can policy-gate AI writes distinctly.
|
|
3780
|
+
*/
|
|
3781
|
+
origin: 'api' | 'user' | 'init' | 'ai';
|
|
3776
3782
|
grid: Grid;
|
|
3777
3783
|
[key: string]: unknown;
|
|
3778
3784
|
}
|
|
@@ -4101,7 +4107,20 @@ export interface EditApi {
|
|
|
4101
4107
|
stop(cancel?: boolean): void;
|
|
4102
4108
|
undo(): void;
|
|
4103
4109
|
redo(): void;
|
|
4104
|
-
|
|
4110
|
+
/**
|
|
4111
|
+
* Write several cells as one undoable step (§12). `opts.origin` defaults to
|
|
4112
|
+
* `'api'` — the ungated seam every existing caller uses (a fill, a paste, a
|
|
4113
|
+
* kanban move), unchanged. Pass `{ origin: 'ai' }` (or `'user'`) to route the
|
|
4114
|
+
* write through the cancellable `beforeEdit` gate, exactly as an interactive
|
|
4115
|
+
* edit is (BACKLOG-0000967): the AI writes through this so a host `beforeEdit`
|
|
4116
|
+
* handler can veto it and nothing persists when it does. With a gated origin
|
|
4117
|
+
* and an async (deferring) before-handler, the return is a `Promise<number>`.
|
|
4118
|
+
*/
|
|
4119
|
+
setCells(
|
|
4120
|
+
writes: { key: string; colId: string; value: unknown }[],
|
|
4121
|
+
type?: 'cell' | 'fill' | 'paste',
|
|
4122
|
+
opts?: { origin?: 'api' | 'ai' | 'user' },
|
|
4123
|
+
): number | Promise<number>;
|
|
4105
4124
|
/**
|
|
4106
4125
|
* Set one value across a block of cells as a single undoable step (§12, card
|
|
4107
4126
|
* 740). Defaults to the selected range; read-only and non-editable cells are
|
|
@@ -8083,8 +8102,32 @@ declare module 'lattice-grid/modules/ai' {
|
|
|
8083
8102
|
interface AIConfig {
|
|
8084
8103
|
/** The host's model callback. Falls back to the grid's `ai.ask` when omitted. */
|
|
8085
8104
|
ask?: AIAsk;
|
|
8086
|
-
/** Opt into specific features: `'narrative'`, `'insights'`. All on when omitted. */
|
|
8105
|
+
/** Opt into specific features: `'narrative'`, `'insights'`, `'query'`/`'ask'`. All on when omitted. */
|
|
8087
8106
|
enable?: string[];
|
|
8107
|
+
/**
|
|
8108
|
+
* Ask-your-data: apply a safe (read-only) query result without a confirm
|
|
8109
|
+
* step. Off by default — the resolved query is shown and waits for Apply.
|
|
8110
|
+
*/
|
|
8111
|
+
autoApply?: boolean;
|
|
8112
|
+
/**
|
|
8113
|
+
* A Data Router instance; on applying a query the answer rows are fanned to
|
|
8114
|
+
* its attached viewers (grid + chart + KPI together) via `load()`.
|
|
8115
|
+
*/
|
|
8116
|
+
router?: unknown;
|
|
8117
|
+
/** Budgets passed to the schema builder for ask-your-data. */
|
|
8118
|
+
schemaOptions?: object;
|
|
8119
|
+
/** Extra context passed through to `ask()`. */
|
|
8120
|
+
context?: unknown;
|
|
8121
|
+
/** Called with each ask-your-data result. */
|
|
8122
|
+
onQuery?: (result: AIQueryResult) => void;
|
|
8123
|
+
/** Called with each governed-actor proposal (Play C), before any approval. */
|
|
8124
|
+
onProposal?: (result: AIProposal) => void;
|
|
8125
|
+
/**
|
|
8126
|
+
* A Kanban board (from `createKanban`) the governed actor writes moves
|
|
8127
|
+
* through: an NL card move applies via the board's own `beforeMove` gate
|
|
8128
|
+
* (BACKLOG-0000967), never a kanban-specific write bypass.
|
|
8129
|
+
*/
|
|
8130
|
+
board?: unknown;
|
|
8088
8131
|
/** Cap on rows any tool result carries to `ask()`. */
|
|
8089
8132
|
maxRows?: number;
|
|
8090
8133
|
/** Columns whose values must never leave the browser. */
|
|
@@ -8105,11 +8148,124 @@ declare module 'lattice-grid/modules/ai' {
|
|
|
8105
8148
|
onError?: (error: { error: unknown; target: AITarget }) => void;
|
|
8106
8149
|
}
|
|
8107
8150
|
|
|
8151
|
+
/** The report from applying an ask-your-data query. */
|
|
8152
|
+
interface AIApplyReport {
|
|
8153
|
+
ok: boolean;
|
|
8154
|
+
/** The action types that were applied. */
|
|
8155
|
+
applied: string[];
|
|
8156
|
+
/** Actions that threw while applying. */
|
|
8157
|
+
failed: Array<{ type: string; reason: string }>;
|
|
8158
|
+
/** Actions refused by the read-only gate — a mutation is never applied. */
|
|
8159
|
+
refused: Array<{ type: string; reason: string }>;
|
|
8160
|
+
/** How many answer rows were fanned to a router's viewers. */
|
|
8161
|
+
fannedOut: number;
|
|
8162
|
+
}
|
|
8163
|
+
|
|
8108
8164
|
/**
|
|
8109
|
-
*
|
|
8110
|
-
*
|
|
8111
|
-
|
|
8112
|
-
|
|
8165
|
+
* The result of an ask-your-data question (BACKLOG-0000966): a validated,
|
|
8166
|
+
* READ-ONLY query spec — never rows — that the host reviews before applying.
|
|
8167
|
+
*/
|
|
8168
|
+
interface AIQueryResult {
|
|
8169
|
+
/** True when the spec is safe to apply: at least one read, nothing unsafe. */
|
|
8170
|
+
ok: boolean;
|
|
8171
|
+
/** The user's question. */
|
|
8172
|
+
question: string;
|
|
8173
|
+
/** The core plan (from `grid.ai.plan`). */
|
|
8174
|
+
plan: Record<string, unknown>;
|
|
8175
|
+
/** The read-only actions that will run — the validated query spec. */
|
|
8176
|
+
actions: object[];
|
|
8177
|
+
/** Actions refused as not read-only (a mutation the model asked for). */
|
|
8178
|
+
unsafe: Array<{ type: string; reason: string }>;
|
|
8179
|
+
/** Parts the core validator dropped (unknown column, bad operator, …). */
|
|
8180
|
+
rejected: Array<{ at: string; what: string; reason: string }>;
|
|
8181
|
+
/** The model's own one-line summary, if any. */
|
|
8182
|
+
explain: string;
|
|
8183
|
+
/** The validated query spec as data. */
|
|
8184
|
+
spec: { actions: object[] };
|
|
8185
|
+
/** The apply report once applied, or null. */
|
|
8186
|
+
applied: AIApplyReport | null;
|
|
8187
|
+
/** The resolved query in one human sentence, from the validated spec. */
|
|
8188
|
+
describe(): string;
|
|
8189
|
+
/** Apply the query (re-gated), fanning the answer to a router if configured. */
|
|
8190
|
+
apply(opts?: { router?: unknown; onResult?: (rows: object[]) => void }): AIApplyReport;
|
|
8191
|
+
}
|
|
8192
|
+
|
|
8193
|
+
/** One before/after change in a governed-actor proposal (BACKLOG-0000967). */
|
|
8194
|
+
interface AIDiffEntry {
|
|
8195
|
+
/** The target row key. */
|
|
8196
|
+
key: string;
|
|
8197
|
+
/** A human label identifying the row (a name-like column, else the key). */
|
|
8198
|
+
rowLabel: string;
|
|
8199
|
+
/** The target column id. */
|
|
8200
|
+
colId: string;
|
|
8201
|
+
/** The column's title, for the diff header. */
|
|
8202
|
+
colTitle: string;
|
|
8203
|
+
/** The current stored value. */
|
|
8204
|
+
oldValue: unknown;
|
|
8205
|
+
/** The current value as shown (a lookup id mapped to its label). */
|
|
8206
|
+
oldDisplay: string;
|
|
8207
|
+
/** The proposed stored value (a label resolved to its option id). */
|
|
8208
|
+
newValue: unknown;
|
|
8209
|
+
/** The proposed value as shown. */
|
|
8210
|
+
newDisplay: string;
|
|
8211
|
+
}
|
|
8212
|
+
|
|
8213
|
+
/**
|
|
8214
|
+
* A governed-actor proposal (Play C, BACKLOG-0000967): the model's structured
|
|
8215
|
+
* edits, VALIDATED and resolved against the current view — never written until
|
|
8216
|
+
* a human approves. `apply()` writes ONLY through the grid's own gate.
|
|
8217
|
+
*/
|
|
8218
|
+
interface AIProposal {
|
|
8219
|
+
/** True when there is at least one applicable change and nothing needs a pick first. */
|
|
8220
|
+
ok: boolean;
|
|
8221
|
+
/** The user's instruction. */
|
|
8222
|
+
instruction: string;
|
|
8223
|
+
/** `'view'` (the filtered set, the default) or `'all'` (an opted-in widen). */
|
|
8224
|
+
scope: 'view' | 'all';
|
|
8225
|
+
/** How many rows the scope covers. */
|
|
8226
|
+
scopeCount: number;
|
|
8227
|
+
/** The scope in words, always stated in the confirm/diff. */
|
|
8228
|
+
scopeText: string;
|
|
8229
|
+
/** Whether any proposal was a bulk (`scope:'view'`) edit. */
|
|
8230
|
+
bulk: boolean;
|
|
8231
|
+
/** The before/after diff — exactly what would change. Nothing is written yet. */
|
|
8232
|
+
diff: AIDiffEntry[];
|
|
8233
|
+
/** Proposals refused before apply (unknown column, unknown label, bad type/range, no match). */
|
|
8234
|
+
rejected: Array<{ reason: string; [k: string]: unknown }>;
|
|
8235
|
+
/** Matches needing a human pick (>1 row for one phrase), with candidates. */
|
|
8236
|
+
ambiguous: Array<{ reason: string; candidates: Array<{ key: string; label: string }>; [k: string]: unknown }>;
|
|
8237
|
+
/** Named targets found only outside the view, offered for an opt-in widen. */
|
|
8238
|
+
outOfView: Array<{ reason: string; candidates: Array<{ key: string; label: string }>; [k: string]: unknown }>;
|
|
8239
|
+
/** Matches whose value already equals the ask (nothing to change). */
|
|
8240
|
+
noops: Array<{ reason: string; [k: string]: unknown }>;
|
|
8241
|
+
/** The apply report once applied, or null. */
|
|
8242
|
+
applied: AIProposalReport | null;
|
|
8243
|
+
/** The proposal in one human sentence, always stating the scope. */
|
|
8244
|
+
describe(): string;
|
|
8245
|
+
/** Apply the approved diff through the gate (`beforeEdit`, or `beforeMove` for a board). */
|
|
8246
|
+
apply(opts?: { board?: unknown }): Promise<AIProposalReport>;
|
|
8247
|
+
}
|
|
8248
|
+
|
|
8249
|
+
/** The report from applying a governed-actor proposal. */
|
|
8250
|
+
interface AIProposalReport {
|
|
8251
|
+
/** True when at least one edit landed. */
|
|
8252
|
+
ok: boolean;
|
|
8253
|
+
/** How many edits landed through the gate. */
|
|
8254
|
+
applied: number;
|
|
8255
|
+
/** How many edits were attempted. */
|
|
8256
|
+
requested: number;
|
|
8257
|
+
/** How many were stopped by a before-handler veto. */
|
|
8258
|
+
vetoed: number;
|
|
8259
|
+
/** Which gated path applied them: `'setCells'`, `'board.move'`, or `'none'`. */
|
|
8260
|
+
via: string;
|
|
8261
|
+
}
|
|
8262
|
+
|
|
8263
|
+
/**
|
|
8264
|
+
* An AI controller over a live grid. It explains the grid's computed figures
|
|
8265
|
+
* (Play A), answers questions with validated read-only query specs (Play B),
|
|
8266
|
+
* and PROPOSES governed edits a human approves and the grid's own gate applies
|
|
8267
|
+
* (Play C). `grid.ai` (in core) is the complementary intent/plan skill layer
|
|
8268
|
+
* this consumes.
|
|
8113
8269
|
*/
|
|
8114
8270
|
interface AI {
|
|
8115
8271
|
/** The mounted insights panel element, or null. */
|
|
@@ -8126,7 +8282,46 @@ declare module 'lattice-grid/modules/ai' {
|
|
|
8126
8282
|
attachExplain(target: AITarget, opts?: object): HTMLElement | null;
|
|
8127
8283
|
/** Build the facts packet for a target without calling `ask()`. */
|
|
8128
8284
|
facts(target?: AITarget, opts?: object): AIFactsPacket;
|
|
8129
|
-
|
|
8285
|
+
/**
|
|
8286
|
+
* Ask-your-data: turn a question into a validated, read-only query spec, run
|
|
8287
|
+
* it in the engine, and (on apply) fan the answer to router-attached viewers.
|
|
8288
|
+
* Returns a result the host reviews; `autoApply` applies a safe read for you.
|
|
8289
|
+
*/
|
|
8290
|
+
query(question: string, opts?: {
|
|
8291
|
+
autoApply?: boolean; router?: unknown; schemaOptions?: object;
|
|
8292
|
+
context?: unknown; tools?: boolean; signal?: AbortSignal;
|
|
8293
|
+
onResult?: (rows: object[]) => void;
|
|
8294
|
+
}): Promise<AIQueryResult>;
|
|
8295
|
+
/** Apply a reviewed query result (the confirm path); re-gated at the seam. */
|
|
8296
|
+
applyQuery(result: AIQueryResult, opts?: { router?: unknown; onResult?: (rows: object[]) => void }): AIApplyReport;
|
|
8297
|
+
/** Mount the ask-your-data bar (input, Ask, auto-apply toggle, preview, Apply/Discard). */
|
|
8298
|
+
askBar(el?: HTMLElement, opts?: object): AI;
|
|
8299
|
+
/**
|
|
8300
|
+
* Governed actor (Play C): ask the model for structured edit PROPOSALS over
|
|
8301
|
+
* the current view, validate and resolve them (label -> stored value, locate
|
|
8302
|
+
* a named row, reject unknown columns/labels/out-of-range), and return a
|
|
8303
|
+
* reviewable {@link AIProposal} with a before/after diff. NOTHING is written
|
|
8304
|
+
* — the model proposes; a human approves.
|
|
8305
|
+
*/
|
|
8306
|
+
propose(instruction: string, opts?: {
|
|
8307
|
+
widen?: boolean; board?: unknown; schemaOptions?: object; maxRows?: number;
|
|
8308
|
+
context?: unknown; redact?: string | string[] | ((colId: string) => boolean);
|
|
8309
|
+
signal?: AbortSignal;
|
|
8310
|
+
}): Promise<AIProposal>;
|
|
8311
|
+
/**
|
|
8312
|
+
* Apply an approved proposal — the human-approval step. Writes ONLY through
|
|
8313
|
+
* the gate: a grid cell edit via `grid.edit.setCells({ origin: 'ai' })` (the
|
|
8314
|
+
* `beforeEdit` veto), a kanban move via `board.move({ origin: 'ai' })` (the
|
|
8315
|
+
* `beforeMove` veto). A vetoing host handler stops the write.
|
|
8316
|
+
*/
|
|
8317
|
+
applyProposal(result: AIProposal, opts?: { board?: unknown }): Promise<AIProposalReport>;
|
|
8318
|
+
/**
|
|
8319
|
+
* Mount the governed-actor bar: an instruction input, Propose, a before/after
|
|
8320
|
+
* diff preview stating the scope, and Approve/Discard. Approve applies
|
|
8321
|
+
* through the gate.
|
|
8322
|
+
*/
|
|
8323
|
+
actorBar(el?: HTMLElement, opts?: object): AI;
|
|
8324
|
+
on(name: 'narrative' | 'query' | 'proposal' | 'error' | string, fn: (payload: object) => void): () => void;
|
|
8130
8325
|
off(name: string, fn: (payload: object) => void): void;
|
|
8131
8326
|
destroy(): void;
|
|
8132
8327
|
}
|