chore: import upstream snapshot with attribution
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
import { TABLE_LIMITS } from '@/lib/table/constants'
|
||||
import { enrichTableToolSchema } from '@/tools/schema-enrichers'
|
||||
import type { TableBatchInsertParams, TableBatchInsertResponse } from '@/tools/table/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const tableBatchInsertRowsTool: ToolConfig<
|
||||
TableBatchInsertParams,
|
||||
TableBatchInsertResponse
|
||||
> = {
|
||||
id: 'table_batch_insert_rows',
|
||||
name: 'Batch Insert Rows',
|
||||
description: `Insert multiple rows into a table at once (up to ${TABLE_LIMITS.MAX_BATCH_INSERT_SIZE} rows)`,
|
||||
version: '1.0.0',
|
||||
|
||||
toolEnrichment: {
|
||||
dependsOn: 'tableId',
|
||||
enrichTool: (tableId, schema, desc) =>
|
||||
enrichTableToolSchema(tableId, 'table_batch_insert_rows', schema, desc),
|
||||
},
|
||||
|
||||
params: {
|
||||
tableId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
description: 'Table ID',
|
||||
visibility: 'user-only',
|
||||
},
|
||||
rows: {
|
||||
type: 'array',
|
||||
required: true,
|
||||
description: `Array of row data objects (max ${TABLE_LIMITS.MAX_BATCH_INSERT_SIZE} rows)`,
|
||||
visibility: 'user-or-llm',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: TableBatchInsertParams) => `/api/table/${params.tableId}/rows`,
|
||||
method: 'POST',
|
||||
headers: () => ({
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params: TableBatchInsertParams) => {
|
||||
const workspaceId = params._context?.workspaceId
|
||||
if (!workspaceId) {
|
||||
throw new Error('Workspace ID is required in execution context')
|
||||
}
|
||||
|
||||
return {
|
||||
rows: params.rows,
|
||||
workspaceId,
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response): Promise<TableBatchInsertResponse> => {
|
||||
const result = await response.json()
|
||||
const data = result.data || result
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
rows: data.rows,
|
||||
insertedCount: data.insertedCount,
|
||||
message: data.message || 'Rows inserted successfully',
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
success: { type: 'boolean', description: 'Whether rows were inserted' },
|
||||
rows: { type: 'array', description: 'Inserted rows data' },
|
||||
insertedCount: { type: 'number', description: 'Number of rows inserted' },
|
||||
message: { type: 'string', description: 'Status message' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
import type { TableCreateParams, TableCreateResponse } from '@/tools/table/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const tableCreateTool: ToolConfig<TableCreateParams, TableCreateResponse> = {
|
||||
id: 'table_create',
|
||||
name: 'Create Table',
|
||||
description: 'Create a new user-defined table with schema',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
name: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
description: 'Table name (alphanumeric, underscores, 1-50 chars)',
|
||||
visibility: 'user-or-llm',
|
||||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
description: 'Optional table description',
|
||||
visibility: 'user-or-llm',
|
||||
},
|
||||
schema: {
|
||||
type: 'object',
|
||||
required: true,
|
||||
description: 'Table schema with column definitions',
|
||||
visibility: 'user-or-llm',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: '/api/table',
|
||||
method: 'POST',
|
||||
headers: () => ({
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params) => {
|
||||
const workspaceId = params._context?.workspaceId
|
||||
if (!workspaceId) {
|
||||
throw new Error('Workspace ID is required in execution context')
|
||||
}
|
||||
|
||||
return {
|
||||
name: params.name,
|
||||
description: params.description,
|
||||
schema: params.schema,
|
||||
workspaceId,
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response): Promise<TableCreateResponse> => {
|
||||
const result = await response.json()
|
||||
const data = result.data || result
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
table: data.table,
|
||||
message: data.message || 'Table created successfully',
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
success: { type: 'boolean', description: 'Whether table was created' },
|
||||
table: { type: 'json', description: 'Created table metadata' },
|
||||
message: { type: 'string', description: 'Status message' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
import type { TableDeleteResponse, TableRowDeleteParams } from '@/tools/table/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const tableDeleteRowTool: ToolConfig<TableRowDeleteParams, TableDeleteResponse> = {
|
||||
id: 'table_delete_row',
|
||||
name: 'Delete Row',
|
||||
description: 'Delete a row from a table',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tableId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
description: 'Table ID',
|
||||
visibility: 'user-only',
|
||||
},
|
||||
rowId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
description: 'Row ID to delete',
|
||||
visibility: 'user-or-llm',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: TableRowDeleteParams) => `/api/table/${params.tableId}/rows/${params.rowId}`,
|
||||
method: 'DELETE',
|
||||
headers: () => ({
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params: TableRowDeleteParams) => {
|
||||
const workspaceId = params._context?.workspaceId
|
||||
if (!workspaceId) {
|
||||
throw new Error('Workspace ID is required in execution context')
|
||||
}
|
||||
|
||||
return {
|
||||
workspaceId,
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response): Promise<TableDeleteResponse> => {
|
||||
const result = await response.json()
|
||||
const data = result.data || result
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
deletedCount: data.deletedCount,
|
||||
message: data.message || 'Row deleted successfully',
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
success: { type: 'boolean', description: 'Whether row was deleted' },
|
||||
deletedCount: { type: 'number', description: 'Number of rows deleted' },
|
||||
message: { type: 'string', description: 'Status message' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
import { TABLE_LIMITS } from '@/lib/table/constants'
|
||||
import { enrichTableToolSchema } from '@/tools/schema-enrichers'
|
||||
import type { TableBulkOperationResponse, TableDeleteByFilterParams } from '@/tools/table/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const tableDeleteRowsByFilterTool: ToolConfig<
|
||||
TableDeleteByFilterParams,
|
||||
TableBulkOperationResponse
|
||||
> = {
|
||||
id: 'table_delete_rows_by_filter',
|
||||
name: 'Delete Rows by Filter',
|
||||
description:
|
||||
'Delete multiple rows that match filter criteria. Use with caution - supports optional limit for safety.',
|
||||
version: '1.0.0',
|
||||
|
||||
toolEnrichment: {
|
||||
dependsOn: 'tableId',
|
||||
enrichTool: (tableId, schema, desc) =>
|
||||
enrichTableToolSchema(tableId, 'table_delete_rows_by_filter', schema, desc),
|
||||
},
|
||||
|
||||
params: {
|
||||
tableId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
description: 'Table ID',
|
||||
visibility: 'user-only',
|
||||
},
|
||||
filter: {
|
||||
type: 'object',
|
||||
required: true,
|
||||
description:
|
||||
'Filter criteria using operators like $eq, $ne, $gt, $lt, $contains, $ncontains, $startsWith, $endsWith, $in, $nin, $empty, etc.',
|
||||
visibility: 'user-or-llm',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
description: `Maximum number of rows to delete (default: no limit, max: ${TABLE_LIMITS.MAX_BULK_OPERATION_SIZE})`,
|
||||
visibility: 'user-or-llm',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: TableDeleteByFilterParams) => `/api/table/${params.tableId}/rows`,
|
||||
method: 'DELETE',
|
||||
headers: () => ({
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params: TableDeleteByFilterParams) => {
|
||||
const workspaceId = params._context?.workspaceId
|
||||
if (!workspaceId) {
|
||||
throw new Error('Workspace ID is required in execution context')
|
||||
}
|
||||
|
||||
return {
|
||||
filter: params.filter,
|
||||
limit: params.limit,
|
||||
workspaceId,
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response): Promise<TableBulkOperationResponse> => {
|
||||
const result = await response.json()
|
||||
const data = result.data || result
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
deletedCount: data.deletedCount || 0,
|
||||
deletedRowIds: data.deletedRowIds || [],
|
||||
message: data.message || 'Rows deleted successfully',
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
success: { type: 'boolean', description: 'Whether rows were deleted' },
|
||||
deletedCount: { type: 'number', description: 'Number of rows deleted' },
|
||||
deletedRowIds: { type: 'array', description: 'IDs of deleted rows' },
|
||||
message: { type: 'string', description: 'Status message' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import type { TableRowGetParams, TableRowResponse } from '@/tools/table/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const tableGetRowTool: ToolConfig<TableRowGetParams, TableRowResponse> = {
|
||||
id: 'table_get_row',
|
||||
name: 'Get Row',
|
||||
description: 'Get a single row by ID',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tableId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
description: 'Table ID',
|
||||
visibility: 'user-only',
|
||||
},
|
||||
rowId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
description: 'Row ID to retrieve',
|
||||
visibility: 'user-or-llm',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: TableRowGetParams) => {
|
||||
const workspaceId = params._context?.workspaceId
|
||||
if (!workspaceId) {
|
||||
throw new Error('Workspace ID is required in execution context')
|
||||
}
|
||||
|
||||
return `/api/table/${params.tableId}/rows/${params.rowId}?workspaceId=${encodeURIComponent(workspaceId)}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: () => ({
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response): Promise<TableRowResponse> => {
|
||||
const result = await response.json()
|
||||
const data = result.data || result
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
row: data.row,
|
||||
message: data.message || 'Row retrieved successfully',
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
success: { type: 'boolean', description: 'Whether row was retrieved' },
|
||||
row: { type: 'json', description: 'Row data' },
|
||||
message: { type: 'string', description: 'Status message' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
import { getColumnId } from '@/lib/table/column-keys'
|
||||
import type { ColumnDefinition } from '@/lib/table/types'
|
||||
import type { TableGetSchemaParams, TableGetSchemaResponse } from '@/tools/table/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const tableGetSchemaTool: ToolConfig<TableGetSchemaParams, TableGetSchemaResponse> = {
|
||||
id: 'table_get_schema',
|
||||
name: 'Get Schema',
|
||||
description: 'Get the schema configuration of a table',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tableId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
description: 'Table ID',
|
||||
visibility: 'user-only',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: TableGetSchemaParams) => {
|
||||
const workspaceId = params._context?.workspaceId
|
||||
if (!workspaceId) {
|
||||
throw new Error('Workspace ID is required in execution context')
|
||||
}
|
||||
|
||||
return `/api/table/${params.tableId}?workspaceId=${encodeURIComponent(workspaceId)}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: () => ({
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response): Promise<TableGetSchemaResponse> => {
|
||||
const result = await response.json()
|
||||
const data = result.data || result
|
||||
|
||||
// Always surface a usable `id` per column. Legacy columns predating the id
|
||||
// backfill have no stored id; their storage key is the name, so project that
|
||||
// as the id rather than leaving it undefined.
|
||||
const columns: ColumnDefinition[] = (
|
||||
(data.table.schema.columns ?? []) as ColumnDefinition[]
|
||||
).map((col) => ({ ...col, id: getColumnId(col) }))
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
name: data.table.name,
|
||||
columns,
|
||||
columnCount: columns.length,
|
||||
rowCount: data.table.rowCount ?? 0,
|
||||
maxRows: data.table.maxRows ?? 0,
|
||||
message: data.message || 'Schema retrieved successfully',
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
success: { type: 'boolean', description: 'Whether schema was retrieved' },
|
||||
name: { type: 'string', description: 'Table name' },
|
||||
columns: { type: 'array', description: 'Column definitions (each includes its stable id)' },
|
||||
columnCount: { type: 'number', description: 'Number of columns' },
|
||||
rowCount: { type: 'number', description: 'Number of rows in the table' },
|
||||
maxRows: {
|
||||
type: 'number',
|
||||
description: "Max rows per table for the workspace's plan",
|
||||
},
|
||||
message: { type: 'string', description: 'Status message' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
export * from './batch_insert_rows'
|
||||
export * from './create'
|
||||
export * from './delete_row'
|
||||
export * from './delete_rows_by_filter'
|
||||
export * from './get_row'
|
||||
export * from './get_schema'
|
||||
export * from './insert_row'
|
||||
export * from './list'
|
||||
export * from './query_rows'
|
||||
export * from './types'
|
||||
export * from './update_row'
|
||||
export * from './update_rows_by_filter'
|
||||
export * from './upsert_row'
|
||||
@@ -0,0 +1,70 @@
|
||||
import { enrichTableToolSchema } from '@/tools/schema-enrichers'
|
||||
import type { TableRowInsertParams, TableRowResponse } from '@/tools/table/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const tableInsertRowTool: ToolConfig<TableRowInsertParams, TableRowResponse> = {
|
||||
id: 'table_insert_row',
|
||||
name: 'Insert Row',
|
||||
description:
|
||||
'Insert a new row into a table. IMPORTANT: You must use the "data" parameter (not "values", "row", "fields", or other variations) to specify the row contents.',
|
||||
version: '1.0.0',
|
||||
|
||||
toolEnrichment: {
|
||||
dependsOn: 'tableId',
|
||||
enrichTool: (tableId, schema, desc) =>
|
||||
enrichTableToolSchema(tableId, 'table_insert_row', schema, desc),
|
||||
},
|
||||
|
||||
params: {
|
||||
tableId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
description: 'Table ID',
|
||||
visibility: 'user-only',
|
||||
},
|
||||
data: {
|
||||
type: 'object',
|
||||
required: true,
|
||||
description: 'Row data as JSON object',
|
||||
visibility: 'user-or-llm',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: TableRowInsertParams) => `/api/table/${params.tableId}/rows`,
|
||||
method: 'POST',
|
||||
headers: () => ({
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params: TableRowInsertParams) => {
|
||||
const workspaceId = params._context?.workspaceId
|
||||
if (!workspaceId) {
|
||||
throw new Error('Workspace ID is required in execution context')
|
||||
}
|
||||
|
||||
return {
|
||||
data: params.data,
|
||||
workspaceId,
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response): Promise<TableRowResponse> => {
|
||||
const result = await response.json()
|
||||
const data = result.data || result
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
row: data.row,
|
||||
message: data.message || 'Row inserted successfully',
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
success: { type: 'boolean', description: 'Whether row was inserted' },
|
||||
row: { type: 'json', description: 'Inserted row data' },
|
||||
message: { type: 'string', description: 'Status message' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
import type { TableListParams, TableListResponse } from '@/tools/table/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const tableListTool: ToolConfig<TableListParams, TableListResponse> = {
|
||||
id: 'table_list',
|
||||
name: 'List Tables',
|
||||
description: 'List all tables in the workspace',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {},
|
||||
|
||||
request: {
|
||||
url: (params: TableListParams) => {
|
||||
const workspaceId = params._context?.workspaceId
|
||||
if (!workspaceId) {
|
||||
throw new Error('Workspace ID is required in execution context')
|
||||
}
|
||||
return `/api/table?workspaceId=${encodeURIComponent(workspaceId)}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: () => ({
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response): Promise<TableListResponse> => {
|
||||
const result = await response.json()
|
||||
const data = result.data || result
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
tables: data.tables,
|
||||
totalCount: data.totalCount,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
success: { type: 'boolean', description: 'Whether operation succeeded' },
|
||||
tables: { type: 'array', description: 'List of tables' },
|
||||
totalCount: { type: 'number', description: 'Total number of tables' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
import { TABLE_LIMITS } from '@/lib/table/constants'
|
||||
import { enrichTableToolSchema } from '@/tools/schema-enrichers'
|
||||
import type { TableQueryResponse, TableRowQueryParams } from '@/tools/table/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const tableQueryRowsTool: ToolConfig<TableRowQueryParams, TableQueryResponse> = {
|
||||
id: 'table_query_rows',
|
||||
name: 'Query Rows',
|
||||
description: 'Query rows from a table with filtering, sorting, and pagination',
|
||||
version: '1.0.0',
|
||||
|
||||
toolEnrichment: {
|
||||
dependsOn: 'tableId',
|
||||
enrichTool: (tableId, schema, desc) =>
|
||||
enrichTableToolSchema(tableId, 'table_query_rows', schema, desc),
|
||||
},
|
||||
|
||||
params: {
|
||||
tableId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
description: 'Table ID',
|
||||
visibility: 'user-only',
|
||||
},
|
||||
filter: {
|
||||
type: 'object',
|
||||
required: false,
|
||||
description:
|
||||
'Filter conditions (MongoDB-style operators: $eq, $ne, $gt, $gte, $lt, $lte, $in, $nin, $contains, $ncontains, $startsWith, $endsWith, $empty)',
|
||||
visibility: 'user-or-llm',
|
||||
},
|
||||
sort: {
|
||||
type: 'object',
|
||||
required: false,
|
||||
description: 'Sort order as {field: "asc"|"desc"}',
|
||||
visibility: 'user-or-llm',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
description: `Maximum rows to return (default: ${TABLE_LIMITS.DEFAULT_QUERY_LIMIT}, max: ${TABLE_LIMITS.MAX_QUERY_LIMIT})`,
|
||||
visibility: 'user-or-llm',
|
||||
},
|
||||
offset: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
description: 'Number of rows to skip (default: 0)',
|
||||
visibility: 'user-or-llm',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: TableRowQueryParams) => {
|
||||
const workspaceId = params._context?.workspaceId
|
||||
if (!workspaceId) {
|
||||
throw new Error('Workspace ID is required in execution context')
|
||||
}
|
||||
|
||||
const searchParams = new URLSearchParams({
|
||||
workspaceId,
|
||||
})
|
||||
|
||||
if (params.filter) {
|
||||
searchParams.append('filter', JSON.stringify(params.filter))
|
||||
}
|
||||
if (params.sort) {
|
||||
searchParams.append('sort', JSON.stringify(params.sort))
|
||||
}
|
||||
if (params.limit !== undefined) {
|
||||
searchParams.append('limit', String(params.limit))
|
||||
}
|
||||
if (params.offset !== undefined) {
|
||||
searchParams.append('offset', String(params.offset))
|
||||
}
|
||||
|
||||
return `/api/table/${params.tableId}/rows?${searchParams.toString()}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: () => ({
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response): Promise<TableQueryResponse> => {
|
||||
const result = await response.json()
|
||||
const data = result.data || result
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
rows: data.rows,
|
||||
rowCount: data.rowCount,
|
||||
totalCount: data.totalCount,
|
||||
limit: data.limit,
|
||||
offset: data.offset,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
success: { type: 'boolean', description: 'Whether query succeeded' },
|
||||
rows: { type: 'array', description: 'Query result rows' },
|
||||
rowCount: { type: 'number', description: 'Number of rows returned' },
|
||||
totalCount: { type: 'number', description: 'Total rows matching filter' },
|
||||
limit: { type: 'number', description: 'Limit used in query' },
|
||||
offset: { type: 'number', description: 'Offset used in query' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
import type {
|
||||
ColumnDefinition,
|
||||
Filter,
|
||||
RowData,
|
||||
Sort,
|
||||
TableDefinition,
|
||||
TableRow,
|
||||
TableSchema,
|
||||
} from '@/lib/table/types'
|
||||
import type { ToolResponse, WorkflowToolExecutionContext } from '@/tools/types'
|
||||
|
||||
export interface TableCreateParams {
|
||||
name: string
|
||||
description?: string
|
||||
schema: TableSchema
|
||||
_context?: WorkflowToolExecutionContext
|
||||
}
|
||||
|
||||
export interface TableListParams {
|
||||
_context?: WorkflowToolExecutionContext
|
||||
}
|
||||
|
||||
export interface TableRowInsertParams {
|
||||
tableId: string
|
||||
data: RowData
|
||||
/** Unique column to match on for upsert; ignored by plain insert */
|
||||
conflictTarget?: string
|
||||
_context?: WorkflowToolExecutionContext
|
||||
}
|
||||
|
||||
export interface TableRowUpdateParams {
|
||||
tableId: string
|
||||
rowId: string
|
||||
data: RowData
|
||||
_context?: WorkflowToolExecutionContext
|
||||
}
|
||||
|
||||
export interface TableRowDeleteParams {
|
||||
tableId: string
|
||||
rowId: string
|
||||
_context?: WorkflowToolExecutionContext
|
||||
}
|
||||
|
||||
export interface TableRowQueryParams {
|
||||
tableId: string
|
||||
filter?: Filter
|
||||
sort?: Sort
|
||||
limit?: number
|
||||
offset?: number
|
||||
_context?: WorkflowToolExecutionContext
|
||||
}
|
||||
|
||||
export interface TableRowGetParams {
|
||||
tableId: string
|
||||
rowId: string
|
||||
_context?: WorkflowToolExecutionContext
|
||||
}
|
||||
|
||||
export interface TableCreateResponse extends ToolResponse {
|
||||
output: {
|
||||
table: TableDefinition
|
||||
message: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface TableListResponse extends ToolResponse {
|
||||
output: {
|
||||
tables: TableDefinition[]
|
||||
totalCount: number
|
||||
}
|
||||
}
|
||||
|
||||
export interface TableRowResponse extends ToolResponse {
|
||||
output: {
|
||||
row: TableRow
|
||||
message: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface TableQueryResponse extends ToolResponse {
|
||||
output: {
|
||||
rows: TableRow[]
|
||||
rowCount: number
|
||||
totalCount: number
|
||||
limit: number
|
||||
offset: number
|
||||
}
|
||||
}
|
||||
|
||||
export interface TableDeleteResponse extends ToolResponse {
|
||||
output: {
|
||||
deletedCount: number
|
||||
message: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface TableBatchInsertParams {
|
||||
tableId: string
|
||||
rows: RowData[]
|
||||
_context?: WorkflowToolExecutionContext
|
||||
}
|
||||
|
||||
export interface TableBatchInsertResponse extends ToolResponse {
|
||||
output: {
|
||||
rows: TableRow[]
|
||||
insertedCount: number
|
||||
message: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface TableUpdateByFilterParams {
|
||||
tableId: string
|
||||
filter: Filter
|
||||
data: RowData
|
||||
limit?: number
|
||||
_context?: WorkflowToolExecutionContext
|
||||
}
|
||||
|
||||
export interface TableDeleteByFilterParams {
|
||||
tableId: string
|
||||
filter: Filter
|
||||
limit?: number
|
||||
_context?: WorkflowToolExecutionContext
|
||||
}
|
||||
|
||||
export interface TableBulkOperationResponse extends ToolResponse {
|
||||
output: {
|
||||
updatedCount?: number
|
||||
deletedCount?: number
|
||||
updatedRowIds?: string[]
|
||||
deletedRowIds?: string[]
|
||||
message: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface TableGetSchemaParams {
|
||||
tableId: string
|
||||
_context?: WorkflowToolExecutionContext
|
||||
}
|
||||
|
||||
export interface TableGetSchemaResponse extends ToolResponse {
|
||||
output: {
|
||||
name: string
|
||||
columns: ColumnDefinition[]
|
||||
columnCount: number
|
||||
rowCount: number
|
||||
maxRows: number
|
||||
message: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface TableUpsertResponse extends ToolResponse {
|
||||
output: {
|
||||
row: TableRow
|
||||
operation: 'insert' | 'update'
|
||||
message: string
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
import { enrichTableToolSchema } from '@/tools/schema-enrichers'
|
||||
import type { TableRowResponse, TableRowUpdateParams } from '@/tools/table/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const tableUpdateRowTool: ToolConfig<TableRowUpdateParams, TableRowResponse> = {
|
||||
id: 'table_update_row',
|
||||
name: 'Update Row',
|
||||
description:
|
||||
'Update an existing row in a table. Supports partial updates - only include the fields you want to change. IMPORTANT: You must use the "data" parameter (not "values", "row", "fields", or other variations) to specify the fields to update.',
|
||||
version: '1.0.0',
|
||||
|
||||
toolEnrichment: {
|
||||
dependsOn: 'tableId',
|
||||
enrichTool: (tableId, schema, desc) =>
|
||||
enrichTableToolSchema(tableId, 'table_update_row', schema, desc),
|
||||
},
|
||||
|
||||
params: {
|
||||
tableId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
description: 'Table ID',
|
||||
visibility: 'user-only',
|
||||
},
|
||||
rowId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
description: 'Row ID to update',
|
||||
visibility: 'user-or-llm',
|
||||
},
|
||||
data: {
|
||||
type: 'object',
|
||||
required: true,
|
||||
description: 'Updated row data',
|
||||
visibility: 'user-or-llm',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: TableRowUpdateParams) => `/api/table/${params.tableId}/rows/${params.rowId}`,
|
||||
method: 'PATCH',
|
||||
headers: () => ({
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params: TableRowUpdateParams) => {
|
||||
const workspaceId = params._context?.workspaceId
|
||||
if (!workspaceId) {
|
||||
throw new Error('Workspace ID is required in execution context')
|
||||
}
|
||||
|
||||
return {
|
||||
data: params.data,
|
||||
workspaceId,
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response): Promise<TableRowResponse> => {
|
||||
const result = await response.json()
|
||||
const data = result.data || result
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
row: data.row,
|
||||
message: data.message || 'Row updated successfully',
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
success: { type: 'boolean', description: 'Whether row was updated' },
|
||||
row: { type: 'json', description: 'Updated row data' },
|
||||
message: { type: 'string', description: 'Status message' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
import { TABLE_LIMITS } from '@/lib/table/constants'
|
||||
import { enrichTableToolSchema } from '@/tools/schema-enrichers'
|
||||
import type { TableBulkOperationResponse, TableUpdateByFilterParams } from '@/tools/table/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const tableUpdateRowsByFilterTool: ToolConfig<
|
||||
TableUpdateByFilterParams,
|
||||
TableBulkOperationResponse
|
||||
> = {
|
||||
id: 'table_update_rows_by_filter',
|
||||
name: 'Update Rows by Filter',
|
||||
description:
|
||||
'Update multiple rows that match filter criteria. Data is merged with existing row data.',
|
||||
version: '1.0.0',
|
||||
|
||||
toolEnrichment: {
|
||||
dependsOn: 'tableId',
|
||||
enrichTool: (tableId, schema, desc) =>
|
||||
enrichTableToolSchema(tableId, 'table_update_rows_by_filter', schema, desc),
|
||||
},
|
||||
|
||||
params: {
|
||||
tableId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
description: 'Table ID',
|
||||
visibility: 'user-only',
|
||||
},
|
||||
filter: {
|
||||
type: 'object',
|
||||
required: true,
|
||||
description:
|
||||
'Filter criteria using operators like $eq, $ne, $gt, $lt, $contains, $ncontains, $startsWith, $endsWith, $in, $nin, $empty, etc.',
|
||||
visibility: 'user-or-llm',
|
||||
},
|
||||
data: {
|
||||
type: 'object',
|
||||
required: true,
|
||||
description: 'Fields to update (merged with existing data)',
|
||||
visibility: 'user-or-llm',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
description: `Maximum number of rows to update (default: no limit, max: ${TABLE_LIMITS.MAX_BULK_OPERATION_SIZE})`,
|
||||
visibility: 'user-or-llm',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: TableUpdateByFilterParams) => `/api/table/${params.tableId}/rows`,
|
||||
method: 'PUT',
|
||||
headers: () => ({
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params: TableUpdateByFilterParams) => {
|
||||
const workspaceId = params._context?.workspaceId
|
||||
if (!workspaceId) {
|
||||
throw new Error('Workspace ID is required in execution context')
|
||||
}
|
||||
|
||||
return {
|
||||
filter: params.filter,
|
||||
data: params.data,
|
||||
limit: params.limit,
|
||||
workspaceId,
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response): Promise<TableBulkOperationResponse> => {
|
||||
const result = await response.json()
|
||||
const data = result.data || result
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
updatedCount: data.updatedCount || 0,
|
||||
updatedRowIds: data.updatedRowIds || [],
|
||||
message: data.message || 'Rows updated successfully',
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
success: { type: 'boolean', description: 'Whether rows were updated' },
|
||||
updatedCount: { type: 'number', description: 'Number of rows updated' },
|
||||
updatedRowIds: { type: 'array', description: 'IDs of updated rows' },
|
||||
message: { type: 'string', description: 'Status message' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
import { enrichTableToolSchema } from '@/tools/schema-enrichers'
|
||||
import type { TableRowInsertParams, TableUpsertResponse } from '@/tools/table/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const tableUpsertRowTool: ToolConfig<TableRowInsertParams, TableUpsertResponse> = {
|
||||
id: 'table_upsert_row',
|
||||
name: 'Upsert Row',
|
||||
description:
|
||||
'Insert or update a row based on unique column constraints. If a row with matching unique field exists, update it; otherwise insert a new row. IMPORTANT: You must use the "data" parameter (not "values", "row", "fields", or other variations) to specify the row contents.',
|
||||
version: '1.0.0',
|
||||
|
||||
toolEnrichment: {
|
||||
dependsOn: 'tableId',
|
||||
enrichTool: (tableId, schema, desc) =>
|
||||
enrichTableToolSchema(tableId, 'table_upsert_row', schema, desc),
|
||||
},
|
||||
|
||||
params: {
|
||||
tableId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
description: 'Table ID',
|
||||
visibility: 'user-only',
|
||||
},
|
||||
data: {
|
||||
type: 'object',
|
||||
required: true,
|
||||
description: 'Row data to insert or update',
|
||||
visibility: 'user-or-llm',
|
||||
},
|
||||
conflictTarget: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
description:
|
||||
'Unique column to match on. Required only when the table has more than one unique column.',
|
||||
visibility: 'user-only',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: TableRowInsertParams) => `/api/table/${params.tableId}/rows/upsert`,
|
||||
method: 'POST',
|
||||
headers: () => ({
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params: TableRowInsertParams) => {
|
||||
const workspaceId = params._context?.workspaceId
|
||||
if (!workspaceId) {
|
||||
throw new Error('Workspace ID is required in execution context')
|
||||
}
|
||||
|
||||
return {
|
||||
data: params.data,
|
||||
workspaceId,
|
||||
...(params.conflictTarget ? { conflictTarget: params.conflictTarget } : {}),
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response): Promise<TableUpsertResponse> => {
|
||||
const result = await response.json()
|
||||
const data = result.data || result
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
row: data.row,
|
||||
operation: data.operation,
|
||||
message: data.message || 'Row upserted successfully',
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
success: { type: 'boolean', description: 'Whether row was upserted' },
|
||||
row: { type: 'json', description: 'Upserted row data' },
|
||||
operation: { type: 'string', description: 'Operation performed: insert or update' },
|
||||
message: { type: 'string', description: 'Status message' },
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user