Skip to content

Commit b209f0d

Browse files
committed
fix(tables): name a real column in the wildcard example
Review finding. Instruction 5 hardcoded `{"field":"name",...}` while every other example in the block is derived from the table's own columns. An unknown field is rejected outright — `Unknown filter column "name". It is not a column on this table.` — so on a table without that column the example invited the model to write a query that cannot run. Derived from a real text column now, and dropped entirely when the table has none rather than falling back to a placeholder.
1 parent 02d9c6f commit b209f0d

2 files changed

Lines changed: 29 additions & 1 deletion

File tree

‎apps/sim/lib/table/llm/enrichment.test.ts‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,25 @@ describe('enrichTableToolDescription for table_query_rows_v2', () => {
7171
expect(textual).not.toContain('"op":"gte"')
7272
})
7373

74+
/**
75+
* An unknown field is rejected outright, so every field the instructions name
76+
* has to be a column the table actually has.
77+
*/
78+
it('names a real text column in the wildcard example', () => {
79+
expect(enriched).toContain('{"field":"status","op":"ilike","value":"*jo*"}')
80+
expect(enriched).not.toContain('{"field":"name"')
81+
})
82+
83+
it('drops the wildcard example when the table has no text column', () => {
84+
const numeric = enrichTableToolDescription(
85+
'Query rows.',
86+
{ name: 'Scores', columns: [{ name: 'wins', type: 'number' }] },
87+
'table_query_rows_v2'
88+
)
89+
expect(numeric).toContain('matching anywhere in a text value')
90+
expect(numeric).not.toContain('"op":"ilike"')
91+
})
92+
7493
it('omits the example rather than naming a placeholder column', () => {
7594
const bare = enrichTableToolDescription(
7695
'Query rows.',

‎apps/sim/lib/table/llm/enrichment.ts‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,15 @@ export function enrichTableToolDescription(
127127

128128
if (toolId === TABLE_QUERY_ROWS_V2) {
129129
const v2ColumnList = table.columns.map(v2ColumnLine).join('\n')
130+
/*
131+
* An unknown field is rejected outright (`Unknown filter column`), so the
132+
* wildcard example names a real text column or is dropped entirely rather
133+
* than inviting the model to copy a placeholder.
134+
*/
135+
const textCol = table.columns.find((c) => c.type === 'string')
136+
const wildcardRule = textCol
137+
? `5. like/ilike use * as the wildcard, e.g. {"field":"${textCol.name}","op":"ilike","value":"*jo*"}`
138+
: '5. like/ilike use * as the wildcard, matching anywhere in a text value'
130139
const numberCol = table.columns.find((c) => c.type === 'number')
131140
const orderExample = numberCol
132141
? `
@@ -140,7 +149,7 @@ INSTRUCTIONS:
140149
2. A single condition is a plain object: {"field":"<column>","op":"<operator>","value":<value>}
141150
3. For multiple conditions wrap them in {"all":[...]} for AND or {"any":[...]} for OR; groups nest
142151
4. Operators: eq, ne, gt, gte, lt, lte, in, nin, like, ilike, nlike, nilike, contains, ncontains, startsWith, endsWith, isNull, isNotNull, isEmpty, isNotEmpty
143-
5. like/ilike use * as the wildcard, e.g. {"field":"name","op":"ilike","value":"*jo*"}
152+
${wildcardRule}
144153
6. Any column listed below with a restricted operator set accepts ONLY those operators - the query is rejected outright otherwise. A multi-select cell holds a list, so match it by option name with contains, never ilike
145154
7. For substring matching on a text column use ilike with *x*
146155
8. For ranking queries (highest, lowest, Nth, top N) set order and a small limit, e.g. limit 1 for the highest, 2 for the second highest

0 commit comments

Comments
 (0)