Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions apps/sim/lib/copilot/generated/tool-catalog-v1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3346,6 +3346,7 @@ export const ManageKnowledgeBase: ToolCatalogEntry = {
type: 'array',
description:
'Tag definition IDs to opt out of (optional for add_connector). See tagDefinitions in the connector schema.',
items: { type: 'string' },
},
documentId: { type: 'string', description: 'Document ID (required for update_document)' },
documentIds: {
Expand Down Expand Up @@ -4224,6 +4225,14 @@ export const QueryUserTable: ToolCatalogEntry = {
type: 'array',
description:
'Sort spec for query_rows (optional). Ordered list of {field, direction} where direction is asc or desc, e.g. [{"field":"wins","direction":"desc"},{"field":"name","direction":"asc"}].',
items: {
type: 'object',
properties: {
direction: { type: 'string', enum: ['asc', 'desc'] },
field: { type: 'string' },
},
required: ['field', 'direction'],
},
},
rowId: { type: 'string', description: 'Row ID (required for get_row)' },
tableId: { type: 'string', description: 'Table ID (required for all operations)' },
Expand Down Expand Up @@ -5484,6 +5493,7 @@ export const TableColumns: ToolCatalogEntry = {
type: 'array',
description:
'Array of column names to delete at once (preferred for multi-column delete_column)',
items: { type: 'string' },
},
multiple: {
type: 'boolean',
Expand Down Expand Up @@ -5751,12 +5761,18 @@ export const TableRows: ToolCatalogEntry = {
type: 'array',
description:
'Array of row data objects (required for batch_insert_rows). TTL cells take absolute whole Unix epoch seconds, never JavaScript milliseconds; a missing or null TTL means no expiration.',
items: { type: 'object' },
},
tableId: { type: 'string', description: 'Table ID (required for every operation)' },
updates: {
type: 'array',
description:
"Array of per-row updates: [{ rowId, data: { col: val } }] (batch_update_rows format a). TTL values are absolute whole Unix epoch seconds, never JavaScript milliseconds; omit a row's TTL key to preserve it or set it to null to clear the expiration.",
items: {
type: 'object',
properties: { data: { type: 'object' }, rowId: { type: 'string' } },
required: ['rowId', 'data'],
},
},
values: {
type: 'object',
Expand Down Expand Up @@ -6098,6 +6114,7 @@ export const UserTable: ToolCatalogEntry = {
type: 'array',
description:
'Array of column names to delete at once (for delete_column). Preferred over columnName when deleting multiple columns.',
items: { type: 'string' },
},
cursor: {
type: 'string',
Expand Down Expand Up @@ -6237,6 +6254,14 @@ export const UserTable: ToolCatalogEntry = {
type: 'array',
description:
'Sort spec for query_rows (optional). Ordered list of {field, direction} where direction is asc or desc, e.g. [{"field":"wins","direction":"desc"},{"field":"name","direction":"asc"}].',
items: {
type: 'object',
properties: {
direction: { type: 'string', enum: ['asc', 'desc'] },
field: { type: 'string' },
},
required: ['field', 'direction'],
},
},
outputColumnNames: {
type: 'object',
Expand Down Expand Up @@ -6305,6 +6330,7 @@ export const UserTable: ToolCatalogEntry = {
type: 'array',
description:
'Array of row data objects (required for batch_insert_rows). TTL cells take absolute whole Unix epoch seconds, never JavaScript milliseconds; a missing or null TTL means no expiration.',
items: { type: 'object' },
},
runMode: {
type: 'string',
Expand Down Expand Up @@ -6341,6 +6367,11 @@ export const UserTable: ToolCatalogEntry = {
type: 'array',
description:
"Array of per-row updates: [{ rowId, data: { col: val } }] (for batch_update_rows). TTL values are absolute whole Unix epoch seconds, never JavaScript milliseconds; omit a row's TTL key to preserve it or set it to null to clear the expiration.",
items: {
type: 'object',
properties: { data: { type: 'object' }, rowId: { type: 'string' } },
required: ['rowId', 'data'],
},
},
values: {
type: 'object',
Expand Down
65 changes: 65 additions & 0 deletions apps/sim/lib/copilot/generated/tool-schemas-v1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3227,6 +3227,9 @@ export const TOOL_RUNTIME_SCHEMAS: Record<string, ToolRuntimeSchemaEntry> = {
type: 'array',
description:
'Tag definition IDs to opt out of (optional for add_connector). See tagDefinitions in the connector schema.',
items: {
type: 'string',
},
},
documentId: {
type: 'string',
Expand Down Expand Up @@ -4105,6 +4108,19 @@ export const TOOL_RUNTIME_SCHEMAS: Record<string, ToolRuntimeSchemaEntry> = {
type: 'array',
description:
'Sort spec for query_rows (optional). Ordered list of {field, direction} where direction is asc or desc, e.g. [{"field":"wins","direction":"desc"},{"field":"name","direction":"asc"}].',
items: {
type: 'object',
properties: {
direction: {
type: 'string',
enum: ['asc', 'desc'],
},
field: {
type: 'string',
},
},
required: ['field', 'direction'],
},
},
rowId: {
type: 'string',
Expand Down Expand Up @@ -5359,6 +5375,9 @@ export const TOOL_RUNTIME_SCHEMAS: Record<string, ToolRuntimeSchemaEntry> = {
type: 'array',
description:
'Array of column names to delete at once (preferred for multi-column delete_column)',
items: {
type: 'string',
},
},
multiple: {
type: 'boolean',
Expand Down Expand Up @@ -5665,6 +5684,9 @@ export const TOOL_RUNTIME_SCHEMAS: Record<string, ToolRuntimeSchemaEntry> = {
type: 'array',
description:
'Array of row data objects (required for batch_insert_rows). TTL cells take absolute whole Unix epoch seconds, never JavaScript milliseconds; a missing or null TTL means no expiration.',
items: {
type: 'object',
},
},
tableId: {
type: 'string',
Expand All @@ -5674,6 +5696,18 @@ export const TOOL_RUNTIME_SCHEMAS: Record<string, ToolRuntimeSchemaEntry> = {
type: 'array',
description:
"Array of per-row updates: [{ rowId, data: { col: val } }] (batch_update_rows format a). TTL values are absolute whole Unix epoch seconds, never JavaScript milliseconds; omit a row's TTL key to preserve it or set it to null to clear the expiration.",
items: {
type: 'object',
properties: {
data: {
type: 'object',
},
rowId: {
type: 'string',
},
},
required: ['rowId', 'data'],
},
},
values: {
type: 'object',
Expand Down Expand Up @@ -6032,6 +6066,9 @@ export const TOOL_RUNTIME_SCHEMAS: Record<string, ToolRuntimeSchemaEntry> = {
type: 'array',
description:
'Array of column names to delete at once (for delete_column). Preferred over columnName when deleting multiple columns.',
items: {
type: 'string',
},
},
cursor: {
type: 'string',
Expand Down Expand Up @@ -6186,6 +6223,19 @@ export const TOOL_RUNTIME_SCHEMAS: Record<string, ToolRuntimeSchemaEntry> = {
type: 'array',
description:
'Sort spec for query_rows (optional). Ordered list of {field, direction} where direction is asc or desc, e.g. [{"field":"wins","direction":"desc"},{"field":"name","direction":"asc"}].',
items: {
type: 'object',
properties: {
direction: {
type: 'string',
enum: ['asc', 'desc'],
},
field: {
type: 'string',
},
},
required: ['field', 'direction'],
},
},
outputColumnNames: {
type: 'object',
Expand Down Expand Up @@ -6262,6 +6312,9 @@ export const TOOL_RUNTIME_SCHEMAS: Record<string, ToolRuntimeSchemaEntry> = {
type: 'array',
description:
'Array of row data objects (required for batch_insert_rows). TTL cells take absolute whole Unix epoch seconds, never JavaScript milliseconds; a missing or null TTL means no expiration.',
items: {
type: 'object',
},
},
runMode: {
type: 'string',
Expand Down Expand Up @@ -6300,6 +6353,18 @@ export const TOOL_RUNTIME_SCHEMAS: Record<string, ToolRuntimeSchemaEntry> = {
type: 'array',
description:
"Array of per-row updates: [{ rowId, data: { col: val } }] (for batch_update_rows). TTL values are absolute whole Unix epoch seconds, never JavaScript milliseconds; omit a row's TTL key to preserve it or set it to null to clear the expiration.",
items: {
type: 'object',
properties: {
data: {
type: 'object',
},
rowId: {
type: 'string',
},
},
required: ['rowId', 'data'],
},
},
values: {
type: 'object',
Expand Down
71 changes: 71 additions & 0 deletions apps/sim/lib/copilot/tools/server/generated-schema.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/**
* @vitest-environment node
*/
import { describe, expect, it } from 'vitest'
import { validateGeneratedToolPayload } from '@/lib/copilot/tools/server/generated-schema'
import { OrchestrationError } from '@/lib/core/orchestration/types'

/**
* The shapes below are what an agent actually sent when the catalog advertised
* `updates` as a bare array: the provider-path sanitizer filled the missing
* `items` with {type: "string"}, so the model produced `["rowId", "data"]` and
* `[]`, and the executor crashed on the strings. With the item schema synced
* from the catalog, the router refuses them as a classified input error the
* model can correct.
*/
describe('validateGeneratedToolPayload table_rows parameters', () => {
it('rejects string elements in updates as the caller error they are', () => {
expect(() =>
validateGeneratedToolPayload('table_rows', 'parameters', {
operation: 'batch_update_rows',
args: { tableId: 'tbl_1', updates: ['rowId', 'data'] },
})
).toThrow(OrchestrationError)
expect(() =>
validateGeneratedToolPayload('table_rows', 'parameters', {
operation: 'batch_update_rows',
args: { tableId: 'tbl_1', updates: ['rowId', 'data'] },
})
).toThrow(/\/args\/updates\/0 must be object/)
})

it('rejects an update patch that omits its data object', () => {
expect(() =>
validateGeneratedToolPayload('table_rows', 'parameters', {
operation: 'batch_update_rows',
args: { tableId: 'tbl_1', updates: [{ rowId: 'row-1' }] },
})
).toThrow(/\/args\/updates\/0 must have required property 'data'/)
})

it('rejects a non-object row in batch_insert_rows', () => {
expect(() =>
validateGeneratedToolPayload('table_rows', 'parameters', {
operation: 'batch_insert_rows',
args: { tableId: 'tbl_1', rows: [{ name: 'Ada' }, 'Bob'] },
})
).toThrow(/\/args\/rows\/1 must be object/)
})

it('accepts the documented per-row patch shape', () => {
const payload = {
operation: 'batch_update_rows',
args: { tableId: 'tbl_1', updates: [{ rowId: 'row-1', data: { status: 'active' } }] },
}
expect(validateGeneratedToolPayload('table_rows', 'parameters', payload)).toBe(payload)
})

it('accepts a sort spec on query_user_table order', () => {
const payload = {
operation: 'query_rows',
args: { tableId: 'tbl_1', order: [{ field: 'age', direction: 'desc' }] },
}
expect(validateGeneratedToolPayload('query_user_table', 'parameters', payload)).toBe(payload)
expect(() =>
validateGeneratedToolPayload('query_user_table', 'parameters', {
operation: 'query_rows',
args: { tableId: 'tbl_1', order: ['age'] },
})
).toThrow(/\/args\/order\/0 must be object/)
})
})
Loading
Loading