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

This commit is contained in:
wehub-resource-sync
2026-07-13 13:20:55 +08:00
commit d25d482dc2
13754 changed files with 4996608 additions and 0 deletions
+98
View File
@@ -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',
},
},
},
}
+192
View File
@@ -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',
},
},
}
+66
View File
@@ -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,
},
},
}
+100
View File
@@ -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,
},
},
}
+160
View File
@@ -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,
},
},
}
+63
View File
@@ -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,
},
},
}
+69
View File
@@ -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',
},
},
}
+80
View File
@@ -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)',
},
},
}
+85
View File
@@ -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',
},
},
},
},
},
}
+108
View File
@@ -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',
},
},
}
+70
View File
@@ -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',
},
},
}
+33
View File
@@ -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
+136
View File
@@ -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',
},
},
}
+262
View File
@@ -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,
},
},
}
+290
View File
@@ -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
}
}
+93
View File
@@ -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,
},
},
}