You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A widget whose title restricts WHICH records it counts — "库存低于10的备件预警",
"overdue work orders", "金额超过 2000" — has no way to say so: the `measure`/
`groupBy` slots choose the NUMBER and the axis, not the row set. So the builder
emits a plain count and a "low stock" card counts EVERY part.
Add an optional `condition {field, op, value}` (op ∈ lt|lte|gt|gte|eq|ne) to the
blueprint widget — lenient + strict variants — that the builder compiles to the
framework widget's presentation-scope `filter` (runtimeFilter). Kept to a single
comparison so the model emits it reliably and a bad guess can be dropped rather
than producing an empty card.
Pairs with the cloud dashboardBody mapping + prompt guidance (separate PR).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
.describe('The field this widget aggregates (e.g. "amount", "probability"), or "count" to count records. The aggregation is chosen automatically from the field type — a money field SUMs, a percentage/rate AVERAGEs — so name the FIELD, not "total_amount". A "total revenue" widget sets measure:"amount"; an "average win rate" widget sets measure:"win_rate"; a "number of deals" widget sets measure:"count". Omit to let the builder infer from the title.'),
77
90
groupBy: z.string().regex(SNAKE_CASE).optional()
78
91
.describe('The field to break the widget down by — the category or time axis (e.g. "stage", "created_at"). A "by status" chart MUST set this to the status field; the title and this field MUST name the SAME field. Omit for a single-number metric.'),
.describe('Restrict WHICH records the widget counts/aggregates when its title implies a threshold or status (e.g. "stock below 10" → {field:"stock_quantity", op:"lt", value:10}; "open tickets" → {field:"status", op:"eq", value:"open"}). Without it the widget covers ALL records — so a "低于10的备件预警" / "overdue" card would wrongly count everything. Omit when the widget genuinely spans every record.'),
79
94
})).optional().describe('Widgets to place on the dashboard'),
.describe('The field this widget aggregates (e.g. "amount", "probability"), or "count" to count records, or null to infer from the title. The aggregation (sum vs average) is chosen automatically from the field type — name the FIELD, not "total_amount". "total revenue" → "amount"; "average win rate" → "win_rate"; "number of deals" → "count".'),
206
221
groupBy: z.string().nullable()
207
222
.describe('The field to break the widget down by — the category or time axis (e.g. "stage", "created_at"), or null for a single-number metric. A "by status" chart MUST set this to the status field; the title and this field MUST name the SAME field.'),
223
+
condition: z.object({
224
+
field: z.string().describe('Field on the widget object to filter by (e.g. "stock_quantity", "status")'),
value: z.union([z.number(),z.string(),z.boolean()]).describe('Comparison value (e.g. 10, "open")'),
227
+
}).nullable()
228
+
.describe('Restrict WHICH records the widget counts/aggregates when its title implies a threshold or status (e.g. "stock below 10" → {field:"stock_quantity",op:"lt",value:10}; "open tickets" → {field:"status",op:"eq",value:"open"}), or null when the widget covers every record. Without it a "低于10的预警" / "overdue" card wrongly counts ALL rows.'),
208
229
})).nullable().describe('Widgets to place on the dashboard, or null'),
0 commit comments