(
llmSchema: { properties?: Record<string, any>; required?: string[] },
table: TableSummary,
toolId: string
)
| 124 | * Enriches LLM tool parameters with table-specific information. |
| 125 | */ |
| 126 | export function enrichTableToolParameters( |
| 127 | llmSchema: { properties?: Record<string, any>; required?: string[] }, |
| 128 | table: TableSummary, |
| 129 | toolId: string |
| 130 | ): { properties: Record<string, any>; required: string[] } { |
| 131 | if (!table.columns || table.columns.length === 0) { |
| 132 | return { |
| 133 | properties: llmSchema.properties || {}, |
| 134 | required: llmSchema.required || [], |
| 135 | } |
| 136 | } |
| 137 | |
| 138 | const columnNames = table.columns.map((c) => c.name).join(', ') |
| 139 | const enrichedProperties = { ...llmSchema.properties } |
| 140 | const enrichedRequired = llmSchema.required ? [...llmSchema.required] : [] |
| 141 | |
| 142 | if (enrichedProperties.filter && FILTER_OPERATIONS.has(toolId)) { |
| 143 | enrichedProperties.filter = { |
| 144 | ...enrichedProperties.filter, |
| 145 | description: `REQUIRED - query will fail without a filter. Construct filter from user's question using columns: ${columnNames}. Syntax: {"column": {"$eq": "value"}}`, |
| 146 | } |
| 147 | } |
| 148 | |
| 149 | if (FILTER_OPERATIONS.has(toolId) && !enrichedRequired.includes('filter')) { |
| 150 | enrichedRequired.push('filter') |
| 151 | } |
| 152 | |
| 153 | if (enrichedProperties.sort && toolId === 'table_query_rows') { |
| 154 | enrichedProperties.sort = { |
| 155 | ...enrichedProperties.sort, |
| 156 | description: `Sort order as {field: "asc"|"desc"}. REQUIRED for ranking queries (highest, lowest, Nth). Example: {"salary": "desc"} for highest salary first.`, |
| 157 | } |
| 158 | } |
| 159 | |
| 160 | if (enrichedProperties.limit && toolId === 'table_query_rows') { |
| 161 | enrichedProperties.limit = { |
| 162 | ...enrichedProperties.limit, |
| 163 | description: `Maximum rows to return (min: 1, max: 1000, default: 100). For ranking queries: use limit=1 for highest/lowest, limit=2 for second highest, etc.`, |
| 164 | } |
| 165 | } |
| 166 | |
| 167 | if (enrichedProperties.data && DATA_OPERATIONS.has(toolId)) { |
| 168 | const exampleCols = table.columns.slice(0, 2) |
| 169 | const exampleData = exampleCols.reduce( |
| 170 | (obj: Record<string, unknown>, col: { name: string; type: string }) => { |
| 171 | obj[col.name] = col.type === 'number' ? 123 : col.type === 'boolean' ? true : 'value' |
| 172 | return obj |
| 173 | }, |
| 174 | {} as Record<string, unknown> |
| 175 | ) |
| 176 | |
| 177 | if (toolId === 'table_update_row') { |
| 178 | enrichedProperties.data = { |
| 179 | ...enrichedProperties.data, |
| 180 | description: `Object containing fields to update. Only include fields you want to change. Available columns: ${columnNames}`, |
| 181 | } |
| 182 | } else { |
| 183 | enrichedProperties.data = { |
no test coverage detected