chore: import upstream snapshot with attribution
Publish CLI Package / publish-npm (push) Waiting to run
Publish Python SDK / publish-pypi (push) Waiting to run
Publish TypeScript SDK / publish-npm (push) Waiting to run
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) Waiting to run
Publish Python SDK / publish-pypi (push) Waiting to run
Publish TypeScript SDK / publish-npm (push) Waiting to run
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
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
import type { AlgoliaAddRecordParams, AlgoliaAddRecordResponse } from '@/tools/algolia/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const addRecordTool: ToolConfig<AlgoliaAddRecordParams, AlgoliaAddRecordResponse> = {
|
||||
id: 'algolia_add_record',
|
||||
name: 'Algolia Add Record',
|
||||
description: 'Add or replace a record in an Algolia index',
|
||||
version: '1.0',
|
||||
|
||||
params: {
|
||||
applicationId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Algolia Application ID',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Algolia Admin API Key',
|
||||
},
|
||||
indexName: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Name of the Algolia index',
|
||||
},
|
||||
objectID: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Object ID for the record (auto-generated if not provided)',
|
||||
},
|
||||
record: {
|
||||
type: 'json',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'JSON object representing the record to add',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const base = `https://${params.applicationId}.algolia.net/1/indexes/${encodeURIComponent(params.indexName.trim())}`
|
||||
if (params.objectID) {
|
||||
return `${base}/${encodeURIComponent(params.objectID.trim())}`
|
||||
}
|
||||
return base
|
||||
},
|
||||
method: (params) => (params.objectID ? 'PUT' : 'POST'),
|
||||
headers: (params) => ({
|
||||
'x-algolia-application-id': params.applicationId,
|
||||
'x-algolia-api-key': params.apiKey,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params) => {
|
||||
const record = typeof params.record === 'string' ? JSON.parse(params.record) : params.record
|
||||
return record
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
taskID: data.taskID ?? 0,
|
||||
objectID: data.objectID ?? '',
|
||||
createdAt: data.createdAt ?? null,
|
||||
updatedAt: data.updatedAt ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
taskID: {
|
||||
type: 'number',
|
||||
description: 'Algolia task ID for tracking the indexing operation',
|
||||
},
|
||||
objectID: {
|
||||
type: 'string',
|
||||
description: 'The object ID of the added or replaced record',
|
||||
},
|
||||
createdAt: {
|
||||
type: 'string',
|
||||
description:
|
||||
'Timestamp when the record was created (only present when objectID is auto-generated)',
|
||||
optional: true,
|
||||
},
|
||||
updatedAt: {
|
||||
type: 'string',
|
||||
description:
|
||||
'Timestamp when the record was updated (only present when replacing an existing record)',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
import type {
|
||||
AlgoliaBatchOperationsParams,
|
||||
AlgoliaBatchOperationsResponse,
|
||||
} from '@/tools/algolia/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const batchOperationsTool: ToolConfig<
|
||||
AlgoliaBatchOperationsParams,
|
||||
AlgoliaBatchOperationsResponse
|
||||
> = {
|
||||
id: 'algolia_batch_operations',
|
||||
name: 'Algolia Batch Operations',
|
||||
description:
|
||||
'Perform batch add, update, partial update, or delete operations on records in an Algolia index',
|
||||
version: '1.0',
|
||||
|
||||
params: {
|
||||
applicationId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Algolia Application ID',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Algolia Admin API Key',
|
||||
},
|
||||
indexName: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Name of the Algolia index',
|
||||
},
|
||||
requests: {
|
||||
type: 'json',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Array of batch operations. Each item has "action" (addObject, updateObject, partialUpdateObject, partialUpdateObjectNoCreate, deleteObject, delete, clear) and "body" (the record data; must include objectID for update/delete; use an empty object {} for the index-level delete/clear actions)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`https://${params.applicationId}.algolia.net/1/indexes/${encodeURIComponent(params.indexName.trim())}/batch`,
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'x-algolia-application-id': params.applicationId,
|
||||
'x-algolia-api-key': params.apiKey,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params) => {
|
||||
const requests =
|
||||
typeof params.requests === 'string' ? JSON.parse(params.requests) : params.requests
|
||||
return { requests }
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
taskID: data.taskID ?? 0,
|
||||
objectIDs: data.objectIDs ?? [],
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
taskID: {
|
||||
type: 'number',
|
||||
description: 'Algolia task ID for tracking the batch operation',
|
||||
},
|
||||
objectIDs: {
|
||||
type: 'array',
|
||||
description: 'Array of object IDs affected by the batch operation',
|
||||
items: {
|
||||
type: 'string',
|
||||
description: 'Unique identifier of an affected record',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
import type {
|
||||
AlgoliaBrowseRecordsParams,
|
||||
AlgoliaBrowseRecordsResponse,
|
||||
} from '@/tools/algolia/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const browseRecordsTool: ToolConfig<
|
||||
AlgoliaBrowseRecordsParams,
|
||||
AlgoliaBrowseRecordsResponse
|
||||
> = {
|
||||
id: 'algolia_browse_records',
|
||||
name: 'Algolia Browse Records',
|
||||
description: 'Browse and iterate over all records in an Algolia index using cursor pagination',
|
||||
version: '1.0',
|
||||
|
||||
params: {
|
||||
applicationId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Algolia Application ID',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Algolia API Key (must have browse ACL)',
|
||||
},
|
||||
indexName: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Name of the Algolia index to browse',
|
||||
},
|
||||
query: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Search query to filter browsed records',
|
||||
},
|
||||
filters: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter string to narrow down results',
|
||||
},
|
||||
attributesToRetrieve: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comma-separated list of attributes to retrieve',
|
||||
},
|
||||
hitsPerPage: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of hits per page (default: 1000, max: 1000)',
|
||||
},
|
||||
cursor: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Cursor from a previous browse response for pagination',
|
||||
},
|
||||
aroundLatLng: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Coordinates for geo-search (e.g., "40.71,-74.01")',
|
||||
},
|
||||
aroundRadius: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Maximum radius in meters for geo-search, or "all" for unlimited',
|
||||
},
|
||||
insideBoundingBox: {
|
||||
type: 'json',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Bounding box coordinates as [[lat1, lng1, lat2, lng2]] for geo-search',
|
||||
},
|
||||
insidePolygon: {
|
||||
type: 'json',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Polygon coordinates as [[lat1, lng1, lat2, lng2, lat3, lng3, ...]] for geo-search',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`https://${params.applicationId}-dsn.algolia.net/1/indexes/${encodeURIComponent(params.indexName.trim())}/browse`,
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'x-algolia-application-id': params.applicationId,
|
||||
'x-algolia-api-key': params.apiKey,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params) => {
|
||||
if (params.cursor) {
|
||||
return { cursor: params.cursor }
|
||||
}
|
||||
const body: Record<string, unknown> = {}
|
||||
if (params.query) body.query = params.query
|
||||
if (params.filters) body.filters = params.filters
|
||||
if (params.attributesToRetrieve) {
|
||||
body.attributesToRetrieve = params.attributesToRetrieve
|
||||
.split(',')
|
||||
.map((a: string) => a.trim())
|
||||
}
|
||||
if (params.hitsPerPage !== undefined) body.hitsPerPage = Number(params.hitsPerPage)
|
||||
if (params.aroundLatLng) body.aroundLatLng = params.aroundLatLng
|
||||
if (params.aroundRadius !== undefined) {
|
||||
body.aroundRadius = params.aroundRadius === 'all' ? 'all' : Number(params.aroundRadius)
|
||||
}
|
||||
if (params.insideBoundingBox) {
|
||||
body.insideBoundingBox =
|
||||
typeof params.insideBoundingBox === 'string'
|
||||
? JSON.parse(params.insideBoundingBox)
|
||||
: params.insideBoundingBox
|
||||
}
|
||||
if (params.insidePolygon) {
|
||||
body.insidePolygon =
|
||||
typeof params.insidePolygon === 'string'
|
||||
? JSON.parse(params.insidePolygon)
|
||||
: params.insidePolygon
|
||||
}
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
hits: data.hits ?? [],
|
||||
cursor: data.cursor ?? null,
|
||||
nbHits: data.nbHits ?? 0,
|
||||
page: data.page ?? 0,
|
||||
nbPages: data.nbPages ?? 0,
|
||||
hitsPerPage: data.hitsPerPage ?? 1000,
|
||||
processingTimeMS: data.processingTimeMS ?? 0,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
hits: {
|
||||
type: 'array',
|
||||
description: 'Array of records from the index (up to 1000 per request)',
|
||||
items: {
|
||||
type: 'object',
|
||||
description: 'A record object containing objectID plus any requested attributes',
|
||||
properties: {
|
||||
objectID: {
|
||||
type: 'string',
|
||||
description: 'Unique identifier of the record',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
cursor: {
|
||||
type: 'string',
|
||||
description:
|
||||
'Opaque cursor string for retrieving the next page of results. Absent when no more results exist.',
|
||||
optional: true,
|
||||
},
|
||||
nbHits: {
|
||||
type: 'number',
|
||||
description: 'Total number of records matching the browse criteria',
|
||||
},
|
||||
page: {
|
||||
type: 'number',
|
||||
description: 'Current page number (zero-based)',
|
||||
},
|
||||
nbPages: {
|
||||
type: 'number',
|
||||
description: 'Total number of pages available',
|
||||
},
|
||||
hitsPerPage: {
|
||||
type: 'number',
|
||||
description: 'Number of hits per page (1-1000, default 1000 for browse)',
|
||||
},
|
||||
processingTimeMS: {
|
||||
type: 'number',
|
||||
description: 'Server-side processing time in milliseconds',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
import type { AlgoliaClearRecordsParams, AlgoliaClearRecordsResponse } from '@/tools/algolia/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const clearRecordsTool: ToolConfig<AlgoliaClearRecordsParams, AlgoliaClearRecordsResponse> =
|
||||
{
|
||||
id: 'algolia_clear_records',
|
||||
name: 'Algolia Clear Records',
|
||||
description:
|
||||
'Clear all records from an Algolia index while keeping settings, synonyms, and rules',
|
||||
version: '1.0',
|
||||
|
||||
params: {
|
||||
applicationId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Algolia Application ID',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Algolia Admin API Key (must have deleteIndex ACL)',
|
||||
},
|
||||
indexName: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Name of the Algolia index to clear',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`https://${params.applicationId}.algolia.net/1/indexes/${encodeURIComponent(params.indexName.trim())}/clear`,
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'x-algolia-application-id': params.applicationId,
|
||||
'x-algolia-api-key': params.apiKey,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
taskID: data.taskID ?? 0,
|
||||
updatedAt: data.updatedAt ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
taskID: {
|
||||
type: 'number',
|
||||
description: 'Algolia task ID for tracking the clear operation',
|
||||
},
|
||||
updatedAt: {
|
||||
type: 'string',
|
||||
description: 'Timestamp when the records were cleared',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
import type {
|
||||
AlgoliaCopyMoveIndexParams,
|
||||
AlgoliaCopyMoveIndexResponse,
|
||||
} from '@/tools/algolia/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const copyMoveIndexTool: ToolConfig<
|
||||
AlgoliaCopyMoveIndexParams,
|
||||
AlgoliaCopyMoveIndexResponse
|
||||
> = {
|
||||
id: 'algolia_copy_move_index',
|
||||
name: 'Algolia Copy/Move Index',
|
||||
description: 'Copy or move an Algolia index to a new destination',
|
||||
version: '1.0',
|
||||
|
||||
params: {
|
||||
applicationId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Algolia Application ID',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Algolia Admin API Key',
|
||||
},
|
||||
indexName: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Name of the source index',
|
||||
},
|
||||
operation: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Operation to perform: "copy" or "move"',
|
||||
},
|
||||
destination: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Name of the destination index',
|
||||
},
|
||||
scope: {
|
||||
type: 'json',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Array of scopes to copy (only for "copy" operation): ["settings", "synonyms", "rules"]. Omit to copy everything including records.',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`https://${params.applicationId}.algolia.net/1/indexes/${encodeURIComponent(params.indexName.trim())}/operation`,
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'x-algolia-application-id': params.applicationId,
|
||||
'x-algolia-api-key': params.apiKey,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params) => {
|
||||
const body: Record<string, unknown> = {
|
||||
operation: params.operation,
|
||||
destination: params.destination.trim(),
|
||||
}
|
||||
if (params.scope) {
|
||||
const scope = typeof params.scope === 'string' ? JSON.parse(params.scope) : params.scope
|
||||
body.scope = scope
|
||||
}
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
taskID: data.taskID ?? 0,
|
||||
updatedAt: data.updatedAt ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
taskID: {
|
||||
type: 'number',
|
||||
description: 'Algolia task ID for tracking the copy/move operation',
|
||||
},
|
||||
updatedAt: {
|
||||
type: 'string',
|
||||
description: 'Timestamp when the operation was performed',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
import type {
|
||||
AlgoliaDeleteByFilterParams,
|
||||
AlgoliaDeleteByFilterResponse,
|
||||
} from '@/tools/algolia/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const deleteByFilterTool: ToolConfig<
|
||||
AlgoliaDeleteByFilterParams,
|
||||
AlgoliaDeleteByFilterResponse
|
||||
> = {
|
||||
id: 'algolia_delete_by_filter',
|
||||
name: 'Algolia Delete By Filter',
|
||||
description: 'Delete all records matching a filter from an Algolia index',
|
||||
version: '1.0',
|
||||
|
||||
params: {
|
||||
applicationId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Algolia Application ID',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Algolia Admin API Key (must have deleteIndex ACL)',
|
||||
},
|
||||
indexName: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Name of the Algolia index',
|
||||
},
|
||||
filters: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter expression to match records for deletion (e.g., "category:outdated")',
|
||||
},
|
||||
facetFilters: {
|
||||
type: 'json',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Array of facet filters (e.g., ["brand:Acme"])',
|
||||
},
|
||||
numericFilters: {
|
||||
type: 'json',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Array of numeric filters (e.g., ["price > 100"])',
|
||||
},
|
||||
tagFilters: {
|
||||
type: 'json',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Array of tag filters using the _tags attribute (e.g., ["published"])',
|
||||
},
|
||||
aroundLatLng: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Coordinates for geo-search filter (e.g., "40.71,-74.01")',
|
||||
},
|
||||
aroundRadius: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Maximum radius in meters for geo-search, or "all" for unlimited',
|
||||
},
|
||||
insideBoundingBox: {
|
||||
type: 'json',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Bounding box coordinates as [[lat1, lng1, lat2, lng2]] for geo-search filter',
|
||||
},
|
||||
insidePolygon: {
|
||||
type: 'json',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Polygon coordinates as [[lat1, lng1, lat2, lng2, lat3, lng3, ...]] for geo-search filter',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`https://${params.applicationId}.algolia.net/1/indexes/${encodeURIComponent(params.indexName.trim())}/deleteByQuery`,
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'x-algolia-application-id': params.applicationId,
|
||||
'x-algolia-api-key': params.apiKey,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params) => {
|
||||
const body: Record<string, unknown> = {}
|
||||
if (params.filters) {
|
||||
body.filters = params.filters
|
||||
}
|
||||
if (params.facetFilters) {
|
||||
body.facetFilters =
|
||||
typeof params.facetFilters === 'string'
|
||||
? JSON.parse(params.facetFilters)
|
||||
: params.facetFilters
|
||||
}
|
||||
if (params.numericFilters) {
|
||||
body.numericFilters =
|
||||
typeof params.numericFilters === 'string'
|
||||
? JSON.parse(params.numericFilters)
|
||||
: params.numericFilters
|
||||
}
|
||||
if (params.tagFilters) {
|
||||
body.tagFilters =
|
||||
typeof params.tagFilters === 'string' ? JSON.parse(params.tagFilters) : params.tagFilters
|
||||
}
|
||||
if (params.aroundLatLng) {
|
||||
body.aroundLatLng = params.aroundLatLng
|
||||
}
|
||||
if (params.aroundRadius !== undefined) {
|
||||
body.aroundRadius = params.aroundRadius === 'all' ? 'all' : Number(params.aroundRadius)
|
||||
}
|
||||
if (params.insideBoundingBox) {
|
||||
body.insideBoundingBox =
|
||||
typeof params.insideBoundingBox === 'string'
|
||||
? JSON.parse(params.insideBoundingBox)
|
||||
: params.insideBoundingBox
|
||||
}
|
||||
if (params.insidePolygon) {
|
||||
body.insidePolygon =
|
||||
typeof params.insidePolygon === 'string'
|
||||
? JSON.parse(params.insidePolygon)
|
||||
: params.insidePolygon
|
||||
}
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
taskID: data.taskID ?? 0,
|
||||
updatedAt: data.updatedAt ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
taskID: {
|
||||
type: 'number',
|
||||
description: 'Algolia task ID for tracking the delete-by-filter operation',
|
||||
},
|
||||
updatedAt: {
|
||||
type: 'string',
|
||||
description: 'Timestamp when the operation was performed',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
import type { AlgoliaDeleteIndexParams, AlgoliaDeleteIndexResponse } from '@/tools/algolia/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const deleteIndexTool: ToolConfig<AlgoliaDeleteIndexParams, AlgoliaDeleteIndexResponse> = {
|
||||
id: 'algolia_delete_index',
|
||||
name: 'Algolia Delete Index',
|
||||
description: 'Delete an entire Algolia index and all its records',
|
||||
version: '1.0',
|
||||
|
||||
params: {
|
||||
applicationId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Algolia Application ID',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Algolia Admin API Key (must have deleteIndex ACL)',
|
||||
},
|
||||
indexName: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Name of the Algolia index to delete',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
method: 'DELETE',
|
||||
url: (params) =>
|
||||
`https://${params.applicationId}.algolia.net/1/indexes/${encodeURIComponent(params.indexName.trim())}`,
|
||||
headers: (params) => ({
|
||||
'x-algolia-application-id': params.applicationId,
|
||||
'x-algolia-api-key': params.apiKey,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
taskID: data.taskID ?? 0,
|
||||
deletedAt: data.deletedAt ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
taskID: {
|
||||
type: 'number',
|
||||
description: 'Algolia task ID for tracking the index deletion',
|
||||
},
|
||||
deletedAt: {
|
||||
type: 'string',
|
||||
description: 'Timestamp when the index was deleted',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
import type { AlgoliaDeleteRecordParams, AlgoliaDeleteRecordResponse } from '@/tools/algolia/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const deleteRecordTool: ToolConfig<AlgoliaDeleteRecordParams, AlgoliaDeleteRecordResponse> =
|
||||
{
|
||||
id: 'algolia_delete_record',
|
||||
name: 'Algolia Delete Record',
|
||||
description: 'Delete a record by objectID from an Algolia index',
|
||||
version: '1.0',
|
||||
|
||||
params: {
|
||||
applicationId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Algolia Application ID',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Algolia Admin API Key',
|
||||
},
|
||||
indexName: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Name of the Algolia index',
|
||||
},
|
||||
objectID: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The objectID of the record to delete',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
method: 'DELETE',
|
||||
url: (params) =>
|
||||
`https://${params.applicationId}.algolia.net/1/indexes/${encodeURIComponent(params.indexName.trim())}/${encodeURIComponent(params.objectID.trim())}`,
|
||||
headers: (params) => ({
|
||||
'x-algolia-application-id': params.applicationId,
|
||||
'x-algolia-api-key': params.apiKey,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
taskID: data.taskID ?? 0,
|
||||
deletedAt: data.deletedAt ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
taskID: {
|
||||
type: 'number',
|
||||
description: 'Algolia task ID for tracking the deletion',
|
||||
},
|
||||
deletedAt: {
|
||||
type: 'string',
|
||||
description: 'Timestamp when the record was deleted',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
import type { AlgoliaGetRecordParams, AlgoliaGetRecordResponse } from '@/tools/algolia/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const getRecordTool: ToolConfig<AlgoliaGetRecordParams, AlgoliaGetRecordResponse> = {
|
||||
id: 'algolia_get_record',
|
||||
name: 'Algolia Get Record',
|
||||
description: 'Get a record by objectID from an Algolia index',
|
||||
version: '1.0',
|
||||
|
||||
params: {
|
||||
applicationId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Algolia Application ID',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Algolia API Key',
|
||||
},
|
||||
indexName: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Name of the Algolia index',
|
||||
},
|
||||
objectID: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The objectID of the record to retrieve',
|
||||
},
|
||||
attributesToRetrieve: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comma-separated list of attributes to retrieve',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
method: 'GET',
|
||||
url: (params) => {
|
||||
const base = `https://${params.applicationId}-dsn.algolia.net/1/indexes/${encodeURIComponent(params.indexName.trim())}/${encodeURIComponent(params.objectID.trim())}`
|
||||
if (params.attributesToRetrieve) {
|
||||
return `${base}?attributesToRetrieve=${encodeURIComponent(params.attributesToRetrieve)}`
|
||||
}
|
||||
return base
|
||||
},
|
||||
headers: (params) => ({
|
||||
'x-algolia-application-id': params.applicationId,
|
||||
'x-algolia-api-key': params.apiKey,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
const { objectID, ...rest } = data
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
objectID: objectID ?? '',
|
||||
record: rest,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
objectID: {
|
||||
type: 'string',
|
||||
description: 'The objectID of the retrieved record',
|
||||
},
|
||||
record: {
|
||||
type: 'object',
|
||||
description: 'The record data (all attributes)',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
import type { AlgoliaGetRecordsParams, AlgoliaGetRecordsResponse } from '@/tools/algolia/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const getRecordsTool: ToolConfig<AlgoliaGetRecordsParams, AlgoliaGetRecordsResponse> = {
|
||||
id: 'algolia_get_records',
|
||||
name: 'Algolia Get Records',
|
||||
description: 'Retrieve multiple records by objectID from one or more Algolia indices',
|
||||
version: '1.0',
|
||||
|
||||
params: {
|
||||
applicationId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Algolia Application ID',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Algolia API Key',
|
||||
},
|
||||
indexName: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Default index name for all requests',
|
||||
},
|
||||
requests: {
|
||||
type: 'json',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Array of objects specifying records to retrieve. Each must have "objectID" and optionally "indexName" and "attributesToRetrieve".',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => `https://${params.applicationId}-dsn.algolia.net/1/indexes/*/objects`,
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'x-algolia-application-id': params.applicationId,
|
||||
'x-algolia-api-key': params.apiKey,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params) => {
|
||||
const parsed =
|
||||
typeof params.requests === 'string' ? JSON.parse(params.requests) : params.requests
|
||||
const requests = (parsed as Record<string, unknown>[]).map((req) => ({
|
||||
...req,
|
||||
indexName:
|
||||
typeof req.indexName === 'string' ? req.indexName.trim() : params.indexName.trim(),
|
||||
}))
|
||||
return { requests }
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
results: data.results ?? [],
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
results: {
|
||||
type: 'array',
|
||||
description: 'Array of retrieved records (null entries for records not found)',
|
||||
items: {
|
||||
type: 'object',
|
||||
description:
|
||||
'A record object containing objectID and user-defined attributes, or null if not found',
|
||||
properties: {
|
||||
objectID: {
|
||||
type: 'string',
|
||||
description: 'Unique identifier of the record',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
import type { AlgoliaGetSettingsParams, AlgoliaGetSettingsResponse } from '@/tools/algolia/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const getSettingsTool: ToolConfig<AlgoliaGetSettingsParams, AlgoliaGetSettingsResponse> = {
|
||||
id: 'algolia_get_settings',
|
||||
name: 'Algolia Get Settings',
|
||||
description: 'Retrieve the settings of an Algolia index',
|
||||
version: '1.0',
|
||||
|
||||
params: {
|
||||
applicationId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Algolia Application ID',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Algolia API Key',
|
||||
},
|
||||
indexName: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Name of the Algolia index',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
method: 'GET',
|
||||
url: (params) =>
|
||||
`https://${params.applicationId}-dsn.algolia.net/1/indexes/${encodeURIComponent(params.indexName.trim())}/settings`,
|
||||
headers: (params) => ({
|
||||
'x-algolia-application-id': params.applicationId,
|
||||
'x-algolia-api-key': params.apiKey,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
searchableAttributes: data.searchableAttributes ?? null,
|
||||
attributesForFaceting: data.attributesForFaceting ?? [],
|
||||
ranking: data.ranking ?? [],
|
||||
customRanking: data.customRanking ?? [],
|
||||
replicas: data.replicas ?? [],
|
||||
hitsPerPage: data.hitsPerPage ?? 20,
|
||||
maxValuesPerFacet: data.maxValuesPerFacet ?? 100,
|
||||
highlightPreTag: data.highlightPreTag ?? '<em>',
|
||||
highlightPostTag: data.highlightPostTag ?? '</em>',
|
||||
paginationLimitedTo: data.paginationLimitedTo ?? 1000,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
searchableAttributes: {
|
||||
type: 'array',
|
||||
description: 'List of searchable attributes',
|
||||
optional: true,
|
||||
items: { type: 'string', description: 'Searchable attribute name or expression' },
|
||||
},
|
||||
attributesForFaceting: {
|
||||
type: 'array',
|
||||
description: 'Attributes used for faceting',
|
||||
items: { type: 'string', description: 'Faceting attribute name or expression' },
|
||||
},
|
||||
ranking: {
|
||||
type: 'array',
|
||||
description: 'Ranking criteria',
|
||||
items: { type: 'string', description: 'Ranking criterion' },
|
||||
},
|
||||
customRanking: {
|
||||
type: 'array',
|
||||
description: 'Custom ranking criteria',
|
||||
items: { type: 'string', description: 'Custom ranking expression (e.g., desc(popularity))' },
|
||||
},
|
||||
replicas: {
|
||||
type: 'array',
|
||||
description: 'List of replica index names',
|
||||
items: { type: 'string', description: 'Replica index name' },
|
||||
},
|
||||
hitsPerPage: {
|
||||
type: 'number',
|
||||
description: 'Default number of hits per page',
|
||||
},
|
||||
maxValuesPerFacet: {
|
||||
type: 'number',
|
||||
description: 'Maximum number of facet values returned',
|
||||
},
|
||||
highlightPreTag: {
|
||||
type: 'string',
|
||||
description: 'HTML tag inserted before highlighted parts',
|
||||
},
|
||||
highlightPostTag: {
|
||||
type: 'string',
|
||||
description: 'HTML tag inserted after highlighted parts',
|
||||
},
|
||||
paginationLimitedTo: {
|
||||
type: 'number',
|
||||
description: 'Maximum number of hits accessible via pagination',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
import type {
|
||||
AlgoliaGetTaskStatusParams,
|
||||
AlgoliaGetTaskStatusResponse,
|
||||
} from '@/tools/algolia/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const getTaskStatusTool: ToolConfig<
|
||||
AlgoliaGetTaskStatusParams,
|
||||
AlgoliaGetTaskStatusResponse
|
||||
> = {
|
||||
id: 'algolia_get_task_status',
|
||||
name: 'Algolia Get Task Status',
|
||||
description: 'Check whether an Algolia indexing task has finished publishing',
|
||||
version: '1.0',
|
||||
|
||||
params: {
|
||||
applicationId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Algolia Application ID',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Algolia API Key',
|
||||
},
|
||||
indexName: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Name of the Algolia index the task ran against',
|
||||
},
|
||||
taskID: {
|
||||
type: 'number',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The taskID returned by a previous write operation',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
method: 'GET',
|
||||
url: (params) =>
|
||||
`https://${params.applicationId}-dsn.algolia.net/1/indexes/${encodeURIComponent(params.indexName.trim())}/task/${encodeURIComponent(String(params.taskID).trim())}`,
|
||||
headers: (params) => ({
|
||||
'x-algolia-application-id': params.applicationId,
|
||||
'x-algolia-api-key': params.apiKey,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
status: data.status ?? '',
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
status: {
|
||||
type: 'string',
|
||||
description:
|
||||
'Task status: "published" once the operation has been applied, "notPublished" while still pending',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import { addRecordTool } from '@/tools/algolia/add_record'
|
||||
import { batchOperationsTool } from '@/tools/algolia/batch_operations'
|
||||
import { browseRecordsTool } from '@/tools/algolia/browse_records'
|
||||
import { clearRecordsTool } from '@/tools/algolia/clear_records'
|
||||
import { copyMoveIndexTool } from '@/tools/algolia/copy_move_index'
|
||||
import { deleteByFilterTool } from '@/tools/algolia/delete_by_filter'
|
||||
import { deleteIndexTool } from '@/tools/algolia/delete_index'
|
||||
import { deleteRecordTool } from '@/tools/algolia/delete_record'
|
||||
import { getRecordTool } from '@/tools/algolia/get_record'
|
||||
import { getRecordsTool } from '@/tools/algolia/get_records'
|
||||
import { getSettingsTool } from '@/tools/algolia/get_settings'
|
||||
import { getTaskStatusTool } from '@/tools/algolia/get_task_status'
|
||||
import { listIndicesTool } from '@/tools/algolia/list_indices'
|
||||
import { partialUpdateRecordTool } from '@/tools/algolia/partial_update_record'
|
||||
import { searchTool } from '@/tools/algolia/search'
|
||||
import { updateSettingsTool } from '@/tools/algolia/update_settings'
|
||||
|
||||
export const algoliaSearchTool = searchTool
|
||||
export const algoliaAddRecordTool = addRecordTool
|
||||
export const algoliaGetRecordTool = getRecordTool
|
||||
export const algoliaGetRecordsTool = getRecordsTool
|
||||
export const algoliaDeleteRecordTool = deleteRecordTool
|
||||
export const algoliaPartialUpdateRecordTool = partialUpdateRecordTool
|
||||
export const algoliaBrowseRecordsTool = browseRecordsTool
|
||||
export const algoliaBatchOperationsTool = batchOperationsTool
|
||||
export const algoliaListIndicesTool = listIndicesTool
|
||||
export const algoliaGetSettingsTool = getSettingsTool
|
||||
export const algoliaGetTaskStatusTool = getTaskStatusTool
|
||||
export const algoliaUpdateSettingsTool = updateSettingsTool
|
||||
export const algoliaDeleteIndexTool = deleteIndexTool
|
||||
export const algoliaCopyMoveIndexTool = copyMoveIndexTool
|
||||
export const algoliaClearRecordsTool = clearRecordsTool
|
||||
export const algoliaDeleteByFilterTool = deleteByFilterTool
|
||||
@@ -0,0 +1,136 @@
|
||||
import type { AlgoliaListIndicesParams, AlgoliaListIndicesResponse } from '@/tools/algolia/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const listIndicesTool: ToolConfig<AlgoliaListIndicesParams, AlgoliaListIndicesResponse> = {
|
||||
id: 'algolia_list_indices',
|
||||
name: 'Algolia List Indices',
|
||||
description: 'List all indices in an Algolia application',
|
||||
version: '1.0',
|
||||
|
||||
params: {
|
||||
applicationId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Algolia Application ID',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Algolia API Key',
|
||||
},
|
||||
page: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page number for paginating indices (default: not paginated)',
|
||||
},
|
||||
hitsPerPage: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of indices per page (default: 100)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
method: 'GET',
|
||||
url: (params) => {
|
||||
const base = `https://${params.applicationId}-dsn.algolia.net/1/indexes`
|
||||
const queryParams: string[] = []
|
||||
if (params.page !== undefined) queryParams.push(`page=${params.page}`)
|
||||
if (params.hitsPerPage !== undefined) queryParams.push(`hitsPerPage=${params.hitsPerPage}`)
|
||||
return queryParams.length > 0 ? `${base}?${queryParams.join('&')}` : base
|
||||
},
|
||||
headers: (params) => ({
|
||||
'x-algolia-application-id': params.applicationId,
|
||||
'x-algolia-api-key': params.apiKey,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
const indices = (data.items ?? []).map(
|
||||
(item: {
|
||||
name: string
|
||||
entries: number
|
||||
dataSize: number
|
||||
fileSize: number
|
||||
lastBuildTimeS: number
|
||||
numberOfPendingTasks: number
|
||||
pendingTask: boolean
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
primary?: string
|
||||
replicas?: string[]
|
||||
virtual?: boolean
|
||||
}) => ({
|
||||
name: item.name ?? '',
|
||||
entries: item.entries ?? 0,
|
||||
dataSize: item.dataSize ?? 0,
|
||||
fileSize: item.fileSize ?? 0,
|
||||
lastBuildTimeS: item.lastBuildTimeS ?? 0,
|
||||
numberOfPendingTasks: item.numberOfPendingTasks ?? 0,
|
||||
pendingTask: item.pendingTask ?? false,
|
||||
createdAt: item.createdAt ?? '',
|
||||
updatedAt: item.updatedAt ?? '',
|
||||
primary: item.primary ?? null,
|
||||
replicas: item.replicas ?? [],
|
||||
virtual: item.virtual ?? false,
|
||||
})
|
||||
)
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
indices,
|
||||
nbPages: data.nbPages ?? 1,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
indices: {
|
||||
type: 'array',
|
||||
description: 'List of indices in the application',
|
||||
items: {
|
||||
type: 'object',
|
||||
description: 'An Algolia index',
|
||||
properties: {
|
||||
name: { type: 'string', description: 'Name of the index' },
|
||||
entries: { type: 'number', description: 'Number of records in the index' },
|
||||
dataSize: { type: 'number', description: 'Size of the index data in bytes' },
|
||||
fileSize: { type: 'number', description: 'Size of the index files in bytes' },
|
||||
lastBuildTimeS: { type: 'number', description: 'Last build duration in seconds' },
|
||||
numberOfPendingTasks: {
|
||||
type: 'number',
|
||||
description: 'Number of pending indexing tasks',
|
||||
},
|
||||
pendingTask: { type: 'boolean', description: 'Whether the index has pending tasks' },
|
||||
createdAt: { type: 'string', description: 'Timestamp when the index was created' },
|
||||
updatedAt: { type: 'string', description: 'Timestamp when the index was last updated' },
|
||||
primary: {
|
||||
type: 'string',
|
||||
description: 'Name of the primary index (if this is a replica)',
|
||||
optional: true,
|
||||
},
|
||||
replicas: {
|
||||
type: 'array',
|
||||
description: 'List of replica index names',
|
||||
optional: true,
|
||||
items: { type: 'string', description: 'Replica index name' },
|
||||
},
|
||||
virtual: {
|
||||
type: 'boolean',
|
||||
description: 'Whether the index is a virtual replica',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
nbPages: {
|
||||
type: 'number',
|
||||
description: 'Total number of pages of indices',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
import type {
|
||||
AlgoliaPartialUpdateRecordParams,
|
||||
AlgoliaPartialUpdateRecordResponse,
|
||||
} from '@/tools/algolia/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const partialUpdateRecordTool: ToolConfig<
|
||||
AlgoliaPartialUpdateRecordParams,
|
||||
AlgoliaPartialUpdateRecordResponse
|
||||
> = {
|
||||
id: 'algolia_partial_update_record',
|
||||
name: 'Algolia Partial Update Record',
|
||||
description: 'Partially update a record in an Algolia index without replacing it entirely',
|
||||
version: '1.0',
|
||||
|
||||
params: {
|
||||
applicationId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Algolia Application ID',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Algolia Admin API Key',
|
||||
},
|
||||
indexName: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Name of the Algolia index',
|
||||
},
|
||||
objectID: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The objectID of the record to update',
|
||||
},
|
||||
attributes: {
|
||||
type: 'json',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'JSON object with attributes to update. Supports built-in operations like {"stock": {"_operation": "Decrement", "value": 1}}',
|
||||
},
|
||||
createIfNotExists: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Whether to create the record if it does not exist (default: true)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const base = `https://${params.applicationId}.algolia.net/1/indexes/${encodeURIComponent(params.indexName.trim())}/${encodeURIComponent(params.objectID.trim())}/partial`
|
||||
if (params.createIfNotExists === false) {
|
||||
return `${base}?createIfNotExists=false`
|
||||
}
|
||||
return base
|
||||
},
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'x-algolia-application-id': params.applicationId,
|
||||
'x-algolia-api-key': params.apiKey,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params) => {
|
||||
const attributes =
|
||||
typeof params.attributes === 'string' ? JSON.parse(params.attributes) : params.attributes
|
||||
return attributes
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
taskID: data.taskID ?? 0,
|
||||
objectID: data.objectID ?? '',
|
||||
updatedAt: data.updatedAt ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
taskID: {
|
||||
type: 'number',
|
||||
description: 'Algolia task ID for tracking the update operation',
|
||||
},
|
||||
objectID: {
|
||||
type: 'string',
|
||||
description: 'The objectID of the updated record',
|
||||
},
|
||||
updatedAt: {
|
||||
type: 'string',
|
||||
description: 'Timestamp when the record was updated',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,262 @@
|
||||
import type { AlgoliaSearchParams, AlgoliaSearchResponse } from '@/tools/algolia/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const searchTool: ToolConfig<AlgoliaSearchParams, AlgoliaSearchResponse> = {
|
||||
id: 'algolia_search',
|
||||
name: 'Algolia Search',
|
||||
description: 'Search an Algolia index',
|
||||
version: '1.0',
|
||||
|
||||
params: {
|
||||
applicationId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Algolia Application ID',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Algolia API Key',
|
||||
},
|
||||
indexName: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Name of the Algolia index to search',
|
||||
},
|
||||
query: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Search query text',
|
||||
},
|
||||
hitsPerPage: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of hits per page (default: 20)',
|
||||
},
|
||||
page: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page number to retrieve (default: 0)',
|
||||
},
|
||||
filters: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter string (e.g., "category:electronics AND price < 100")',
|
||||
},
|
||||
attributesToRetrieve: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comma-separated list of attributes to retrieve',
|
||||
},
|
||||
facets: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Comma-separated list of facet attribute names to retrieve counts for (use "*" for all)',
|
||||
},
|
||||
getRankingInfo: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Whether to include detailed ranking information in each hit',
|
||||
},
|
||||
aroundLatLng: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Coordinates for geo-search (e.g., "40.71,-74.01")',
|
||||
},
|
||||
aroundRadius: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Maximum radius in meters for geo-search, or "all" for unlimited',
|
||||
},
|
||||
insideBoundingBox: {
|
||||
type: 'json',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Bounding box coordinates as [[lat1, lng1, lat2, lng2]] for geo-search',
|
||||
},
|
||||
insidePolygon: {
|
||||
type: 'json',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Polygon coordinates as [[lat1, lng1, lat2, lng2, lat3, lng3, ...]] for geo-search',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => `https://${params.applicationId}-dsn.algolia.net/1/indexes/*/queries`,
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'x-algolia-application-id': params.applicationId,
|
||||
'x-algolia-api-key': params.apiKey,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params) => {
|
||||
const request: Record<string, unknown> = {
|
||||
indexName: params.indexName.trim(),
|
||||
query: params.query,
|
||||
}
|
||||
if (params.hitsPerPage !== undefined) request.hitsPerPage = Number(params.hitsPerPage)
|
||||
if (params.page !== undefined) request.page = Number(params.page)
|
||||
if (params.filters) request.filters = params.filters
|
||||
if (params.attributesToRetrieve) {
|
||||
request.attributesToRetrieve = params.attributesToRetrieve
|
||||
.split(',')
|
||||
.map((a: string) => a.trim())
|
||||
}
|
||||
if (params.facets) {
|
||||
request.facets = params.facets.split(',').map((f: string) => f.trim())
|
||||
}
|
||||
if (params.getRankingInfo) request.getRankingInfo = true
|
||||
if (params.aroundLatLng) request.aroundLatLng = params.aroundLatLng
|
||||
if (params.aroundRadius !== undefined) {
|
||||
request.aroundRadius = params.aroundRadius === 'all' ? 'all' : Number(params.aroundRadius)
|
||||
}
|
||||
if (params.insideBoundingBox) {
|
||||
request.insideBoundingBox =
|
||||
typeof params.insideBoundingBox === 'string'
|
||||
? JSON.parse(params.insideBoundingBox)
|
||||
: params.insideBoundingBox
|
||||
}
|
||||
if (params.insidePolygon) {
|
||||
request.insidePolygon =
|
||||
typeof params.insidePolygon === 'string'
|
||||
? JSON.parse(params.insidePolygon)
|
||||
: params.insidePolygon
|
||||
}
|
||||
return { requests: [request] }
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
const result = data.results?.[0] ?? {}
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
hits: result.hits ?? [],
|
||||
nbHits: result.nbHits ?? 0,
|
||||
page: result.page ?? 0,
|
||||
nbPages: result.nbPages ?? 0,
|
||||
hitsPerPage: result.hitsPerPage ?? 20,
|
||||
processingTimeMS: result.processingTimeMS ?? 0,
|
||||
query: result.query ?? '',
|
||||
parsedQuery: result.parsedQuery ?? null,
|
||||
facets: result.facets ?? null,
|
||||
facets_stats: result.facets_stats ?? null,
|
||||
exhaustive: result.exhaustive ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
hits: {
|
||||
type: 'array',
|
||||
description: 'Array of matching records',
|
||||
items: {
|
||||
type: 'object',
|
||||
description:
|
||||
'A search result hit containing objectID plus any user-defined attributes from the index',
|
||||
properties: {
|
||||
objectID: {
|
||||
type: 'string',
|
||||
description: 'Unique identifier of the record',
|
||||
},
|
||||
_highlightResult: {
|
||||
type: 'object',
|
||||
description:
|
||||
'Highlighted attributes matching the query. Each attribute has value, matchLevel (none, partial, full), and matchedWords',
|
||||
optional: true,
|
||||
},
|
||||
_snippetResult: {
|
||||
type: 'object',
|
||||
description:
|
||||
'Snippeted attributes matching the query. Each attribute has value and matchLevel',
|
||||
optional: true,
|
||||
},
|
||||
_rankingInfo: {
|
||||
type: 'object',
|
||||
description:
|
||||
'Ranking information for the hit. Only present when getRankingInfo is enabled',
|
||||
optional: true,
|
||||
properties: {
|
||||
nbTypos: { type: 'number', description: 'Number of typos in the query match' },
|
||||
firstMatchedWord: {
|
||||
type: 'number',
|
||||
description: 'Position of the first matched word',
|
||||
},
|
||||
geoDistance: {
|
||||
type: 'number',
|
||||
description: 'Distance in meters for geo-search results',
|
||||
},
|
||||
nbExactWords: {
|
||||
type: 'number',
|
||||
description: 'Number of exactly matched words',
|
||||
},
|
||||
userScore: { type: 'number', description: 'Custom ranking score' },
|
||||
words: { type: 'number', description: 'Number of matched words' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
nbHits: {
|
||||
type: 'number',
|
||||
description: 'Total number of matching hits',
|
||||
},
|
||||
page: {
|
||||
type: 'number',
|
||||
description: 'Current page number (zero-based)',
|
||||
},
|
||||
nbPages: {
|
||||
type: 'number',
|
||||
description: 'Total number of pages available',
|
||||
},
|
||||
hitsPerPage: {
|
||||
type: 'number',
|
||||
description: 'Number of hits per page (1-1000, default 20)',
|
||||
},
|
||||
processingTimeMS: {
|
||||
type: 'number',
|
||||
description: 'Server-side processing time in milliseconds',
|
||||
},
|
||||
query: {
|
||||
type: 'string',
|
||||
description: 'The search query that was executed',
|
||||
},
|
||||
parsedQuery: {
|
||||
type: 'string',
|
||||
description: 'The query string after normalization and stop word removal',
|
||||
optional: true,
|
||||
},
|
||||
facets: {
|
||||
type: 'object',
|
||||
description: 'Facet counts keyed by facet name, each containing value-count pairs',
|
||||
optional: true,
|
||||
},
|
||||
facets_stats: {
|
||||
type: 'object',
|
||||
description: 'Statistics (min, max, avg, sum) for numeric facets',
|
||||
optional: true,
|
||||
},
|
||||
exhaustive: {
|
||||
type: 'object',
|
||||
description:
|
||||
'Exhaustiveness flags for facetsCount, facetValues, nbHits, rulesMatch, and typo',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,290 @@
|
||||
import type { ToolResponse } from '@/tools/types'
|
||||
|
||||
interface AlgoliaBaseParams {
|
||||
applicationId: string
|
||||
apiKey: string
|
||||
}
|
||||
|
||||
// Search
|
||||
export interface AlgoliaSearchParams extends AlgoliaBaseParams {
|
||||
indexName: string
|
||||
query: string
|
||||
hitsPerPage?: number | string
|
||||
page?: number | string
|
||||
filters?: string
|
||||
attributesToRetrieve?: string
|
||||
facets?: string
|
||||
getRankingInfo?: boolean | string
|
||||
aroundLatLng?: string
|
||||
aroundRadius?: number | string
|
||||
insideBoundingBox?: string | number[][]
|
||||
insidePolygon?: string | number[][]
|
||||
}
|
||||
|
||||
export interface AlgoliaSearchResponse extends ToolResponse {
|
||||
output: {
|
||||
hits: Record<string, unknown>[]
|
||||
nbHits: number
|
||||
page: number
|
||||
nbPages: number
|
||||
hitsPerPage: number
|
||||
processingTimeMS: number
|
||||
query: string
|
||||
parsedQuery: string | null
|
||||
facets: Record<string, Record<string, number>> | null
|
||||
facets_stats: Record<string, { min: number; max: number; avg: number; sum: number }> | null
|
||||
exhaustive: Record<string, boolean> | null
|
||||
}
|
||||
}
|
||||
|
||||
// Add Record
|
||||
export interface AlgoliaAddRecordParams extends AlgoliaBaseParams {
|
||||
indexName: string
|
||||
objectID?: string
|
||||
record: string | Record<string, unknown>
|
||||
}
|
||||
|
||||
export interface AlgoliaAddRecordResponse extends ToolResponse {
|
||||
output: {
|
||||
taskID: number
|
||||
objectID: string
|
||||
createdAt: string | null
|
||||
updatedAt: string | null
|
||||
}
|
||||
}
|
||||
|
||||
// Get Record
|
||||
export interface AlgoliaGetRecordParams extends AlgoliaBaseParams {
|
||||
indexName: string
|
||||
objectID: string
|
||||
attributesToRetrieve?: string
|
||||
}
|
||||
|
||||
export interface AlgoliaGetRecordResponse extends ToolResponse {
|
||||
output: {
|
||||
objectID: string
|
||||
record: Record<string, unknown>
|
||||
}
|
||||
}
|
||||
|
||||
// Get Multiple Records
|
||||
export interface AlgoliaGetRecordsParams extends AlgoliaBaseParams {
|
||||
indexName: string
|
||||
requests:
|
||||
| string
|
||||
| {
|
||||
objectID: string
|
||||
indexName?: string
|
||||
attributesToRetrieve?: string[]
|
||||
}[]
|
||||
}
|
||||
|
||||
export interface AlgoliaGetRecordsResponse extends ToolResponse {
|
||||
output: {
|
||||
results: (Record<string, unknown> | null)[]
|
||||
}
|
||||
}
|
||||
|
||||
// Delete Record
|
||||
export interface AlgoliaDeleteRecordParams extends AlgoliaBaseParams {
|
||||
indexName: string
|
||||
objectID: string
|
||||
}
|
||||
|
||||
export interface AlgoliaDeleteRecordResponse extends ToolResponse {
|
||||
output: {
|
||||
taskID: number
|
||||
deletedAt: string | null
|
||||
}
|
||||
}
|
||||
|
||||
// Partial Update Record
|
||||
export interface AlgoliaPartialUpdateRecordParams extends AlgoliaBaseParams {
|
||||
indexName: string
|
||||
objectID: string
|
||||
attributes: string | Record<string, unknown>
|
||||
createIfNotExists?: boolean
|
||||
}
|
||||
|
||||
export interface AlgoliaPartialUpdateRecordResponse extends ToolResponse {
|
||||
output: {
|
||||
taskID: number
|
||||
objectID: string
|
||||
updatedAt: string | null
|
||||
}
|
||||
}
|
||||
|
||||
// Browse Records
|
||||
export interface AlgoliaBrowseRecordsParams extends AlgoliaBaseParams {
|
||||
indexName: string
|
||||
query?: string
|
||||
filters?: string
|
||||
attributesToRetrieve?: string
|
||||
hitsPerPage?: number | string
|
||||
cursor?: string
|
||||
aroundLatLng?: string
|
||||
aroundRadius?: number | string
|
||||
insideBoundingBox?: string | number[][]
|
||||
insidePolygon?: string | number[][]
|
||||
}
|
||||
|
||||
export interface AlgoliaBrowseRecordsResponse extends ToolResponse {
|
||||
output: {
|
||||
hits: Record<string, unknown>[]
|
||||
cursor: string | null
|
||||
nbHits: number
|
||||
page: number
|
||||
nbPages: number
|
||||
hitsPerPage: number
|
||||
processingTimeMS: number
|
||||
}
|
||||
}
|
||||
|
||||
// Batch Operations
|
||||
export interface AlgoliaBatchOperationsParams extends AlgoliaBaseParams {
|
||||
indexName: string
|
||||
requests:
|
||||
| string
|
||||
| {
|
||||
action: string
|
||||
body: Record<string, unknown>
|
||||
}[]
|
||||
}
|
||||
|
||||
export interface AlgoliaBatchOperationsResponse extends ToolResponse {
|
||||
output: {
|
||||
taskID: number
|
||||
objectIDs: string[]
|
||||
}
|
||||
}
|
||||
|
||||
// List Indices
|
||||
export interface AlgoliaListIndicesParams extends AlgoliaBaseParams {
|
||||
page?: number | string
|
||||
hitsPerPage?: number | string
|
||||
}
|
||||
|
||||
export interface AlgoliaListIndicesResponse extends ToolResponse {
|
||||
output: {
|
||||
indices: {
|
||||
name: string
|
||||
entries: number
|
||||
dataSize: number
|
||||
fileSize: number
|
||||
lastBuildTimeS: number
|
||||
numberOfPendingTasks: number
|
||||
pendingTask: boolean
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
primary: string | null
|
||||
replicas: string[]
|
||||
virtual: boolean
|
||||
}[]
|
||||
nbPages: number
|
||||
}
|
||||
}
|
||||
|
||||
// Get Settings
|
||||
export interface AlgoliaGetSettingsParams extends AlgoliaBaseParams {
|
||||
indexName: string
|
||||
}
|
||||
|
||||
export interface AlgoliaGetSettingsResponse extends ToolResponse {
|
||||
output: {
|
||||
searchableAttributes: string[] | null
|
||||
attributesForFaceting: string[]
|
||||
ranking: string[]
|
||||
customRanking: string[]
|
||||
replicas: string[]
|
||||
hitsPerPage: number
|
||||
maxValuesPerFacet: number
|
||||
highlightPreTag: string
|
||||
highlightPostTag: string
|
||||
paginationLimitedTo: number
|
||||
}
|
||||
}
|
||||
|
||||
// Update Settings
|
||||
export interface AlgoliaUpdateSettingsParams extends AlgoliaBaseParams {
|
||||
indexName: string
|
||||
settings: string | Record<string, unknown>
|
||||
forwardToReplicas?: boolean
|
||||
}
|
||||
|
||||
export interface AlgoliaUpdateSettingsResponse extends ToolResponse {
|
||||
output: {
|
||||
taskID: number
|
||||
updatedAt: string | null
|
||||
}
|
||||
}
|
||||
|
||||
// Delete Index
|
||||
export interface AlgoliaDeleteIndexParams extends AlgoliaBaseParams {
|
||||
indexName: string
|
||||
}
|
||||
|
||||
export interface AlgoliaDeleteIndexResponse extends ToolResponse {
|
||||
output: {
|
||||
taskID: number
|
||||
deletedAt: string | null
|
||||
}
|
||||
}
|
||||
|
||||
// Copy/Move Index
|
||||
export interface AlgoliaCopyMoveIndexParams extends AlgoliaBaseParams {
|
||||
indexName: string
|
||||
operation: string
|
||||
destination: string
|
||||
scope?: string | string[]
|
||||
}
|
||||
|
||||
export interface AlgoliaCopyMoveIndexResponse extends ToolResponse {
|
||||
output: {
|
||||
taskID: number
|
||||
updatedAt: string | null
|
||||
}
|
||||
}
|
||||
|
||||
// Clear Records
|
||||
export interface AlgoliaClearRecordsParams extends AlgoliaBaseParams {
|
||||
indexName: string
|
||||
}
|
||||
|
||||
export interface AlgoliaClearRecordsResponse extends ToolResponse {
|
||||
output: {
|
||||
taskID: number
|
||||
updatedAt: string | null
|
||||
}
|
||||
}
|
||||
|
||||
// Delete By Filter
|
||||
export interface AlgoliaDeleteByFilterParams extends AlgoliaBaseParams {
|
||||
indexName: string
|
||||
filters: string
|
||||
facetFilters?: string | string[]
|
||||
numericFilters?: string | string[]
|
||||
tagFilters?: string | string[]
|
||||
aroundLatLng?: string
|
||||
aroundRadius?: number | string
|
||||
insideBoundingBox?: string | number[][]
|
||||
insidePolygon?: string | number[][]
|
||||
}
|
||||
|
||||
export interface AlgoliaDeleteByFilterResponse extends ToolResponse {
|
||||
output: {
|
||||
taskID: number
|
||||
updatedAt: string | null
|
||||
}
|
||||
}
|
||||
|
||||
// Get Task Status
|
||||
export interface AlgoliaGetTaskStatusParams extends AlgoliaBaseParams {
|
||||
indexName: string
|
||||
taskID: number | string
|
||||
}
|
||||
|
||||
export interface AlgoliaGetTaskStatusResponse extends ToolResponse {
|
||||
output: {
|
||||
status: string
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
import type {
|
||||
AlgoliaUpdateSettingsParams,
|
||||
AlgoliaUpdateSettingsResponse,
|
||||
} from '@/tools/algolia/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const updateSettingsTool: ToolConfig<
|
||||
AlgoliaUpdateSettingsParams,
|
||||
AlgoliaUpdateSettingsResponse
|
||||
> = {
|
||||
id: 'algolia_update_settings',
|
||||
name: 'Algolia Update Settings',
|
||||
description: 'Update the settings of an Algolia index',
|
||||
version: '1.0',
|
||||
|
||||
params: {
|
||||
applicationId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Algolia Application ID',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Algolia Admin API Key (must have editSettings ACL)',
|
||||
},
|
||||
indexName: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Name of the Algolia index',
|
||||
},
|
||||
settings: {
|
||||
type: 'json',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'JSON object with settings to update (e.g., {"searchableAttributes": ["name", "description"], "customRanking": ["desc(popularity)"]})',
|
||||
},
|
||||
forwardToReplicas: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Whether to apply changes to replica indices (default: false)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const base = `https://${params.applicationId}.algolia.net/1/indexes/${encodeURIComponent(params.indexName.trim())}/settings`
|
||||
if (params.forwardToReplicas) {
|
||||
return `${base}?forwardToReplicas=true`
|
||||
}
|
||||
return base
|
||||
},
|
||||
method: 'PUT',
|
||||
headers: (params) => ({
|
||||
'x-algolia-application-id': params.applicationId,
|
||||
'x-algolia-api-key': params.apiKey,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params) => {
|
||||
const settings =
|
||||
typeof params.settings === 'string' ? JSON.parse(params.settings) : params.settings
|
||||
return settings
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
taskID: data.taskID ?? 0,
|
||||
updatedAt: data.updatedAt ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
taskID: {
|
||||
type: 'number',
|
||||
description: 'Algolia task ID for tracking the settings update',
|
||||
},
|
||||
updatedAt: {
|
||||
type: 'string',
|
||||
description: 'Timestamp when the settings were updated',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user