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
+107
View File
@@ -0,0 +1,107 @@
import type { PineconeDeleteVectorsParams, PineconeResponse } from '@/tools/pinecone/types'
import { parseJsonParam } from '@/tools/pinecone/utils'
import type { ToolConfig } from '@/tools/types'
export const deleteVectorsTool: ToolConfig<PineconeDeleteVectorsParams, PineconeResponse> = {
id: 'pinecone_delete_vectors',
name: 'Pinecone Delete Vectors',
description: 'Delete vectors from a Pinecone namespace by IDs, by metadata filter, or delete all',
version: '1.0',
params: {
indexHost: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Full Pinecone index host URL (e.g., "https://my-index-abc123.svc.pinecone.io")',
},
namespace: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Namespace to delete vectors from (e.g., "documents", "embeddings")',
},
ids: {
type: 'array',
required: false,
visibility: 'user-or-llm',
description:
'Vector IDs to delete (1-1000 items). Mutually exclusive with deleteAll and filter',
},
deleteAll: {
type: 'boolean',
required: false,
visibility: 'user-or-llm',
description: 'Delete all vectors in the namespace. Mutually exclusive with ids and filter',
},
filter: {
type: 'object',
required: false,
visibility: 'user-or-llm',
description:
'Metadata filter selecting vectors to delete (e.g., {"category": {"$eq": "product"}}). Mutually exclusive with ids and deleteAll',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Pinecone API key',
},
},
request: {
method: 'POST',
url: (params) => `${params.indexHost}/vectors/delete`,
headers: (params) => ({
'Api-Key': params.apiKey,
'Content-Type': 'application/json',
'X-Pinecone-API-Version': '2025-01',
}),
body: (params) => {
const body: Record<string, unknown> = {}
if (params.namespace) {
body.namespace = params.namespace
}
if (params.ids != null && params.ids !== '') {
const ids = parseJsonParam<unknown>(params.ids, 'ids')
if (Array.isArray(ids) && ids.length > 0) {
body.ids = ids
}
}
if (params.deleteAll === true || params.deleteAll === 'true') {
body.deleteAll = true
}
if (params.filter != null && params.filter !== '') {
body.filter = parseJsonParam(params.filter, 'filter')
}
const selectorCount = [body.ids, body.deleteAll, body.filter].filter(
(selector) => selector !== undefined
).length
if (selectorCount === 0) {
throw new Error('Provide exactly one of ids, deleteAll, or filter to delete vectors')
}
if (selectorCount > 1) {
throw new Error('ids, deleteAll, and filter are mutually exclusive — provide only one')
}
return body
},
},
transformResponse: async (response) => {
return {
success: true,
output: {
statusText: response.status === 200 ? 'Deleted' : response.statusText,
},
}
},
outputs: {
statusText: {
type: 'string',
description: 'Status of the delete operation',
},
},
}
+79
View File
@@ -0,0 +1,79 @@
import type {
PineconeDescribeIndexParams,
PineconeIndexModel,
PineconeResponse,
} from '@/tools/pinecone/types'
import type { ToolConfig } from '@/tools/types'
export const describeIndexTool: ToolConfig<PineconeDescribeIndexParams, PineconeResponse> = {
id: 'pinecone_describe_index',
name: 'Pinecone Describe Index',
description: 'Get the configuration and status of a Pinecone index by name',
version: '1.0',
params: {
indexName: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Name of the index to describe',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Pinecone API key',
},
},
request: {
method: 'GET',
url: (params) =>
`https://api.pinecone.io/indexes/${encodeURIComponent(params.indexName.trim())}`,
headers: (params) => ({
'Api-Key': params.apiKey,
Accept: 'application/json',
'X-Pinecone-API-Version': '2025-01',
}),
},
transformResponse: async (response) => {
const data = await response.json()
const index: PineconeIndexModel = {
name: data.name,
dimension: data.dimension ?? null,
metric: data.metric ?? null,
host: data.host ?? null,
vectorType: data.vectorType ?? data.vector_type ?? null,
deletionProtection: data.deletionProtection ?? data.deletion_protection ?? null,
tags: data.tags ?? null,
spec: data.spec ?? null,
status: data.status ?? null,
}
return {
success: true,
output: { index },
}
},
outputs: {
index: {
type: 'object',
description: 'Index configuration and status',
properties: {
name: { type: 'string', description: 'Index name' },
dimension: { type: 'number', description: 'Vector dimensionality' },
metric: { type: 'string', description: 'Distance metric (cosine, euclidean, dotproduct)' },
host: { type: 'string', description: 'Index host URL for data-plane operations' },
vectorType: { type: 'string', description: 'Vector type (dense or sparse)' },
deletionProtection: {
type: 'string',
description: 'Deletion protection (enabled or disabled)',
},
tags: { type: 'object', description: 'Custom user tags on the index' },
spec: { type: 'object', description: 'Index spec (serverless or pod configuration)' },
status: { type: 'object', description: 'Index status with ready and state' },
},
},
},
}
@@ -0,0 +1,92 @@
import type { PineconeDescribeIndexStatsParams, PineconeResponse } from '@/tools/pinecone/types'
import { parseJsonParam } from '@/tools/pinecone/utils'
import type { ToolConfig } from '@/tools/types'
export const describeIndexStatsTool: ToolConfig<
PineconeDescribeIndexStatsParams,
PineconeResponse
> = {
id: 'pinecone_describe_index_stats',
name: 'Pinecone Describe Index Stats',
description: 'Get statistics about a Pinecone index, including per-namespace vector counts',
version: '1.0',
params: {
indexHost: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Full Pinecone index host URL (e.g., "https://my-index-abc123.svc.pinecone.io")',
},
filter: {
type: 'object',
required: false,
visibility: 'user-or-llm',
description:
'Metadata filter to limit which vectors are counted (pod-based indexes only, e.g., {"category": {"$eq": "product"}})',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Pinecone API key',
},
},
request: {
method: 'POST',
url: (params) => `${params.indexHost}/describe_index_stats`,
headers: (params) => ({
'Api-Key': params.apiKey,
'Content-Type': 'application/json',
'X-Pinecone-API-Version': '2025-01',
}),
body: (params) => {
const body: Record<string, unknown> = {}
if (params.filter != null && params.filter !== '') {
body.filter = parseJsonParam(params.filter, 'filter')
}
return body
},
},
transformResponse: async (response) => {
const data = await response.json()
const rawNamespaces = (data.namespaces ?? {}) as Record<
string,
{ vectorCount?: number; vector_count?: number }
>
const namespaces: Record<string, { vectorCount: number | null }> = {}
for (const [name, summary] of Object.entries(rawNamespaces)) {
namespaces[name] = { vectorCount: summary.vectorCount ?? summary.vector_count ?? null }
}
return {
success: true,
output: {
namespaces,
dimension: data.dimension ?? null,
indexFullness: data.indexFullness ?? data.index_fullness ?? null,
totalVectorCount: data.totalVectorCount ?? data.total_vector_count ?? null,
},
}
},
outputs: {
namespaces: {
type: 'json',
description: 'Map of namespace name to its summary including vectorCount',
},
dimension: {
type: 'number',
description: 'Dimensionality of the indexed vectors',
},
indexFullness: {
type: 'number',
description: 'Fullness of the index (pod-based indexes only)',
},
totalVectorCount: {
type: 'number',
description: 'Total number of vectors across all namespaces',
},
},
}
+111
View File
@@ -0,0 +1,111 @@
import type { PineconeFetchParams, PineconeResponse, PineconeVector } from '@/tools/pinecone/types'
import type { ToolConfig } from '@/tools/types'
export const fetchTool: ToolConfig<PineconeFetchParams, PineconeResponse> = {
id: 'pinecone_fetch',
name: 'Pinecone Fetch',
description: 'Fetch vectors by ID from a Pinecone index',
version: '1.0',
params: {
indexHost: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Full Pinecone index host URL (e.g., "https://my-index-abc123.svc.pinecone.io")',
},
ids: {
type: 'array',
required: true,
visibility: 'user-or-llm',
description: 'Array of vector IDs to fetch (e.g., ["vec-001", "vec-002"])',
},
namespace: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Namespace to fetch vectors from (e.g., "documents", "embeddings")',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Pinecone API key',
},
},
request: {
method: 'GET',
url: (params) => {
const baseUrl = `${params.indexHost}/vectors/fetch`
const queryParams = new URLSearchParams()
queryParams.append('ids', params.ids.join(','))
if (params.namespace) {
queryParams.append('namespace', params.namespace)
}
return `${baseUrl}?${queryParams.toString()}`
},
headers: (params) => ({
'Api-Key': params.apiKey,
'Content-Type': 'application/json',
}),
},
transformResponse: async (response) => {
const data = await response.json()
const vectors = data.vectors as Record<string, PineconeVector>
return {
success: true,
output: {
matches: Object.entries(vectors).map(([id, vector]) => ({
id,
values: vector.values,
metadata: vector.metadata,
score: 1.0, // Fetch returns exact matches
})),
data: Object.values(vectors).map((vector) => ({
values: vector.values,
vector_type: 'dense' as const,
})),
usage: {
total_tokens: data.usage?.readUnits || 0,
},
},
}
},
outputs: {
matches: {
type: 'array',
description: 'Fetched vectors with ID, values, metadata, and score',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Vector ID' },
values: { type: 'array', description: 'Vector values' },
metadata: { type: 'object', description: 'Associated metadata' },
score: { type: 'number', description: 'Match score (1.0 for exact matches)' },
},
},
},
data: {
type: 'array',
description: 'Vector data with values and vector type',
items: {
type: 'object',
properties: {
values: { type: 'array', description: 'Vector values' },
vector_type: { type: 'string', description: 'Vector type (dense/sparse)' },
},
},
},
usage: {
type: 'object',
description: 'Usage statistics including total read units',
properties: {
total_tokens: { type: 'number', description: 'Read units consumed' },
},
},
},
}
@@ -0,0 +1,83 @@
import type { PineconeGenerateEmbeddingsParams, PineconeResponse } from '@/tools/pinecone/types'
import type { ToolConfig } from '@/tools/types'
export const generateEmbeddingsTool: ToolConfig<
PineconeGenerateEmbeddingsParams,
PineconeResponse
> = {
id: 'pinecone_generate_embeddings',
name: 'Pinecone Generate Embeddings',
description: "Generate embeddings from text using Pinecone's hosted models",
version: '1.0',
params: {
model: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Model to use for generating embeddings',
},
inputs: {
type: 'array',
required: true,
visibility: 'user-or-llm',
description: 'Array of text inputs to generate embeddings for',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Pinecone API key',
},
},
request: {
method: 'POST',
url: () => 'https://api.pinecone.io/embed',
headers: (params) => ({
'Api-Key': params.apiKey,
'Content-Type': 'application/json',
'X-Pinecone-API-Version': '2025-01',
}),
body: (params) => ({
model: params.model,
inputs: params.inputs,
parameters: params.parameters || {
input_type: 'passage',
truncate: 'END',
},
}),
},
transformResponse: async (response) => {
const data = await response.json()
return {
success: true,
output: {
data: data.data,
model: data.model,
vector_type: data.vector_type,
usage: data.usage,
},
}
},
outputs: {
data: {
type: 'array',
description: 'Generated embeddings data with values and vector type',
},
model: {
type: 'string',
description: 'Model used for generating embeddings',
},
vector_type: {
type: 'string',
description: 'Type of vector generated (dense/sparse)',
},
usage: {
type: 'object',
description: 'Usage statistics for embeddings generation',
},
},
}
+23
View File
@@ -0,0 +1,23 @@
import { deleteVectorsTool } from '@/tools/pinecone/delete_vectors'
import { describeIndexTool } from '@/tools/pinecone/describe_index'
import { describeIndexStatsTool } from '@/tools/pinecone/describe_index_stats'
import { fetchTool } from '@/tools/pinecone/fetch'
import { generateEmbeddingsTool } from '@/tools/pinecone/generate_embeddings'
import { listIndexesTool } from '@/tools/pinecone/list_indexes'
import { listVectorIdsTool } from '@/tools/pinecone/list_vector_ids'
import { searchTextTool } from '@/tools/pinecone/search_text'
import { searchVectorTool } from '@/tools/pinecone/search_vector'
import { updateVectorTool } from '@/tools/pinecone/update_vector'
import { upsertTextTool } from '@/tools/pinecone/upsert_text'
export const pineconeDeleteVectorsTool = deleteVectorsTool
export const pineconeDescribeIndexTool = describeIndexTool
export const pineconeDescribeIndexStatsTool = describeIndexStatsTool
export const pineconeFetchTool = fetchTool
export const pineconeGenerateEmbeddingsTool = generateEmbeddingsTool
export const pineconeListIndexesTool = listIndexesTool
export const pineconeListVectorIdsTool = listVectorIdsTool
export const pineconeSearchTextTool = searchTextTool
export const pineconeSearchVectorTool = searchVectorTool
export const pineconeUpdateVectorTool = updateVectorTool
export const pineconeUpsertTextTool = upsertTextTool
+84
View File
@@ -0,0 +1,84 @@
import type {
PineconeIndexModel,
PineconeListIndexesParams,
PineconeResponse,
} from '@/tools/pinecone/types'
import type { ToolConfig } from '@/tools/types'
/** Map a raw Pinecone index model to a clean output shape. */
function mapIndex(index: any): PineconeIndexModel {
return {
name: index.name,
dimension: index.dimension ?? null,
metric: index.metric ?? null,
host: index.host ?? null,
vectorType: index.vectorType ?? index.vector_type ?? null,
deletionProtection: index.deletionProtection ?? index.deletion_protection ?? null,
tags: index.tags ?? null,
spec: index.spec ?? null,
status: index.status ?? null,
}
}
export const listIndexesTool: ToolConfig<PineconeListIndexesParams, PineconeResponse> = {
id: 'pinecone_list_indexes',
name: 'Pinecone List Indexes',
description: 'List all Pinecone indexes in the project',
version: '1.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Pinecone API key',
},
},
request: {
method: 'GET',
url: () => 'https://api.pinecone.io/indexes',
headers: (params) => ({
'Api-Key': params.apiKey,
Accept: 'application/json',
'X-Pinecone-API-Version': '2025-01',
}),
},
transformResponse: async (response) => {
const data = await response.json()
return {
success: true,
output: {
indexes: (data.indexes ?? []).map(mapIndex),
},
}
},
outputs: {
indexes: {
type: 'array',
description: 'List of indexes with name, dimension, metric, host, spec, and status',
items: {
type: 'object',
properties: {
name: { type: 'string', description: 'Index name' },
dimension: { type: 'number', description: 'Vector dimensionality' },
metric: {
type: 'string',
description: 'Distance metric (cosine, euclidean, dotproduct)',
},
host: { type: 'string', description: 'Index host URL for data-plane operations' },
vectorType: { type: 'string', description: 'Vector type (dense or sparse)' },
deletionProtection: {
type: 'string',
description: 'Deletion protection (enabled or disabled)',
},
tags: { type: 'object', description: 'Custom user tags on the index' },
spec: { type: 'object', description: 'Index spec (serverless or pod configuration)' },
status: { type: 'object', description: 'Index status with ready and state' },
},
},
},
},
}
+112
View File
@@ -0,0 +1,112 @@
import type { PineconeListVectorIdsParams, PineconeResponse } from '@/tools/pinecone/types'
import type { ToolConfig } from '@/tools/types'
export const listVectorIdsTool: ToolConfig<PineconeListVectorIdsParams, PineconeResponse> = {
id: 'pinecone_list_vector_ids',
name: 'Pinecone List Vector IDs',
description: 'List vector IDs in a Pinecone namespace by prefix (serverless indexes only)',
version: '1.0',
params: {
indexHost: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Full Pinecone index host URL (e.g., "https://my-index-abc123.svc.pinecone.io")',
},
namespace: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Namespace to list vector IDs from (e.g., "documents", "embeddings")',
},
prefix: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter vector IDs by a common prefix (e.g., "doc1#")',
},
limit: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of IDs to return per page (default 100)',
},
paginationToken: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Pagination token from a previous response to fetch the next page',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Pinecone API key',
},
},
request: {
method: 'GET',
url: (params) => {
const queryParams = new URLSearchParams()
queryParams.append('namespace', params.namespace)
if (params.prefix) {
queryParams.append('prefix', params.prefix)
}
if (params.limit != null && String(params.limit) !== '') {
queryParams.append('limit', String(params.limit))
}
if (params.paginationToken) {
queryParams.append('paginationToken', params.paginationToken)
}
return `${params.indexHost}/vectors/list?${queryParams.toString()}`
},
headers: (params) => ({
'Api-Key': params.apiKey,
Accept: 'application/json',
'X-Pinecone-API-Version': '2025-01',
}),
},
transformResponse: async (response) => {
const data = await response.json()
return {
success: true,
output: {
vectorIds: (data.vectors ?? []).map((vector: { id: string }) => vector.id),
pagination: data.pagination ?? null,
namespace: data.namespace ?? null,
usage: {
total_tokens: data.usage?.readUnits ?? 0,
},
},
}
},
outputs: {
vectorIds: {
type: 'array',
description: 'Vector IDs in the namespace',
items: { type: 'string', description: 'Vector ID' },
},
pagination: {
type: 'object',
description: 'Pagination info with a next token when more results exist',
properties: {
next: { type: 'string', description: 'Token to fetch the next page' },
},
},
namespace: {
type: 'string',
description: 'Namespace the IDs were listed from',
},
usage: {
type: 'object',
description: 'Usage statistics including read units',
properties: {
total_tokens: { type: 'number', description: 'Read units consumed' },
},
},
},
}
+151
View File
@@ -0,0 +1,151 @@
import type {
PineconeResponse,
PineconeSearchHit,
PineconeSearchTextParams,
} from '@/tools/pinecone/types'
import type { ToolConfig } from '@/tools/types'
export const searchTextTool: ToolConfig<PineconeSearchTextParams, PineconeResponse> = {
id: 'pinecone_search_text',
name: 'Pinecone Search Text',
description: 'Search for similar text in a Pinecone index',
version: '1.0',
params: {
indexHost: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Full Pinecone index host URL (e.g., "https://my-index-abc123.svc.pinecone.io")',
},
namespace: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Namespace to search in (e.g., "documents", "embeddings")',
},
searchQuery: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Text to search for',
},
topK: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Number of results to return (e.g., "10", "25")',
},
fields: {
type: 'array',
required: false,
visibility: 'user-only',
description: 'Fields to return in the results',
},
filter: {
type: 'object',
required: false,
visibility: 'user-or-llm',
description:
'Filter to apply to the search (e.g., {"category": "tech", "year": {"$gte": 2020}})',
},
rerank: {
type: 'object',
required: false,
visibility: 'user-only',
description: 'Reranking parameters',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Pinecone API key',
},
},
request: {
method: 'POST',
url: (params) => `${params.indexHost}/records/namespaces/${params.namespace}/search`,
headers: (params) => ({
'Api-Key': params.apiKey,
'Content-Type': 'application/json',
Accept: 'application/json',
'X-Pinecone-API-Version': '2025-01',
}),
body: (params) => {
// Format the query object
const query = {
inputs: { text: params.searchQuery },
top_k: params.topK ? Number(params.topK) : 10,
}
// Build the request body
const body: any = {
query,
}
// Add optional parameters if provided
if (params.fields) {
body.fields = typeof params.fields === 'string' ? JSON.parse(params.fields) : params.fields
}
if (params.filter) {
body.query.filter =
typeof params.filter === 'string' ? JSON.parse(params.filter) : params.filter
}
if (params.rerank) {
body.rerank = typeof params.rerank === 'string' ? JSON.parse(params.rerank) : params.rerank
// If rerank query is not specified, use the search query
if (!body.rerank.query) {
body.rerank.query = { text: params.searchQuery }
}
}
return body
},
},
transformResponse: async (response) => {
const data = await response.json()
return {
success: true,
output: {
matches: data.result.hits.map((hit: PineconeSearchHit) => ({
id: hit._id,
score: hit._score,
metadata: hit.fields,
})),
usage: {
total_tokens: data.usage.embed_total_tokens || 0,
read_units: data.usage.read_units,
rerank_units: data.usage.rerank_units,
},
},
}
},
outputs: {
matches: {
type: 'array',
description: 'Search results with ID, score, and metadata',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Vector ID' },
score: { type: 'number', description: 'Similarity score' },
metadata: { type: 'object', description: 'Associated metadata' },
},
},
},
usage: {
type: 'object',
description: 'Usage statistics including tokens, read units, and rerank units',
properties: {
total_tokens: { type: 'number', description: 'Total tokens used for embedding' },
read_units: { type: 'number', description: 'Read units consumed' },
rerank_units: { type: 'number', description: 'Rerank units used' },
},
},
},
}
+110
View File
@@ -0,0 +1,110 @@
import type { PineconeResponse, PineconeSearchVectorParams } from '@/tools/pinecone/types'
import type { ToolConfig } from '@/tools/types'
export const searchVectorTool: ToolConfig<PineconeSearchVectorParams, PineconeResponse> = {
id: 'pinecone_search_vector',
name: 'Pinecone Search Vector',
description: 'Search for similar vectors in a Pinecone index',
version: '1.0',
params: {
indexHost: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Full Pinecone index host URL (e.g., "https://my-index-abc123.svc.pinecone.io")',
},
namespace: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Namespace to search in (e.g., "documents", "embeddings")',
},
vector: {
type: 'array',
required: true,
visibility: 'user-only',
description: 'Vector to search for',
},
topK: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Number of results to return (e.g., 10, 25)',
},
filter: {
type: 'object',
required: false,
visibility: 'user-or-llm',
description:
'Filter to apply to the search (e.g., {"category": "tech", "year": {"$gte": 2020}})',
},
includeValues: {
type: 'boolean',
required: false,
visibility: 'user-only',
description: 'Include vector values in response',
},
includeMetadata: {
type: 'boolean',
required: false,
visibility: 'user-or-llm',
description: 'Include metadata in response (true/false)',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Pinecone API key',
},
},
request: {
method: 'POST',
url: (params) => `${params.indexHost}/query`,
headers: (params) => ({
'Api-Key': params.apiKey,
'Content-Type': 'application/json',
Accept: 'application/json',
}),
body: (params) => ({
namespace: params.namespace,
vector: typeof params.vector === 'string' ? JSON.parse(params.vector) : params.vector,
topK: params.topK ? Number(params.topK) : 10,
filter: params.filter
? typeof params.filter === 'string'
? JSON.parse(params.filter)
: params.filter
: undefined,
includeValues: true, //TODO: Make this dynamic
includeMetadata: true, //TODO: Make this dynamic
}),
},
transformResponse: async (response) => {
const data = await response.json()
return {
success: true,
output: {
matches: data.matches.map((match: any) => ({
id: match.id,
score: match.score,
values: match.values,
metadata: match.metadata,
})),
namespace: data.namespace,
},
}
},
outputs: {
matches: {
type: 'array',
description: 'Vector search results with ID, score, values, and metadata',
},
namespace: {
type: 'string',
description: 'Namespace where the search was performed',
},
},
}
+225
View File
@@ -0,0 +1,225 @@
import type { ToolResponse } from '@/tools/types'
// Base Pinecone params shared across all operations
interface PineconeBaseParams {
indexHost: string
namespace: string
apiKey: string
}
// Response types
interface PineconeMatchResponse {
id: string
score: number
values?: number[]
metadata?: Record<string, any>
}
export interface PineconeIndexModel {
name: string
dimension?: number | null
metric?: string | null
host?: string | null
vectorType?: string | null
deletionProtection?: string | null
tags?: Record<string, string> | null
spec?: Record<string, any> | null
status?: { ready?: boolean; state?: string } | null
}
export interface PineconeResponse extends ToolResponse {
output: {
matches?: PineconeMatchResponse[]
statusText?: string
data?: Array<{
values: number[]
vector_type: 'dense' | 'sparse'
}>
model?: string
vector_type?: 'dense' | 'sparse'
namespace?: string | null
usage?: {
total_tokens: number
}
indexes?: PineconeIndexModel[]
index?: PineconeIndexModel
namespaces?: Record<string, { vectorCount: number | null }>
dimension?: number | null
indexFullness?: number | null
totalVectorCount?: number | null
vectorIds?: string[]
pagination?: { next?: string } | null
}
}
// Generate Embeddings
export interface PineconeGenerateEmbeddingsParams {
apiKey: string
model: string
inputs: { text: string }[]
parameters?: {
input_type?: 'passage'
truncate?: 'END'
}
}
// Upsert Text
export interface PineconeUpsertTextRecord {
_id: string
chunk_text: string
category?: string
[key: string]: any
}
export interface PineconeUpsertTextParams extends PineconeBaseParams {
records: PineconeUpsertTextRecord | PineconeUpsertTextRecord[]
}
// Upsert Vectors
interface PineconeUpsertVectorsParams extends PineconeBaseParams {
vectors: {
id: string
values: number[]
metadata?: Record<string, any>
sparseValues?: {
indices: number[]
values: number[]
}
}[]
}
// Search Text
interface PineconeSearchQuery {
inputs?: { text: string }
vector?: {
values: number[]
sparse_values?: number[]
sparse_indices?: number[]
}
id?: string
top_k: number
filter?: Record<string, any>
}
interface PineconeRerank {
model: string
rank_fields: string[]
top_n?: number
parameters?: Record<string, any>
query?: { text: string }
}
export interface PineconeSearchTextParams extends PineconeBaseParams {
searchQuery: string
topK?: string
fields?: string[] | string
filter?: Record<string, any> | string
rerank?: PineconeRerank | string
}
export interface PineconeSearchHit {
_id: string
_score: number
fields?: Record<string, any>
}
interface PineconeSearchResponse {
result: {
hits: PineconeSearchHit[]
}
usage: {
read_units: number
embed_total_tokens?: number
rerank_units?: number
}
}
// Fetch Vectors
export interface PineconeFetchParams extends PineconeBaseParams {
ids: string[]
}
export interface PineconeVector {
id: string
values: number[]
metadata?: Record<string, any>
}
interface PineconeUsage {
readUnits: number
}
interface PineconeFetchResponse {
vectors: Record<string, PineconeVector>
namespace?: string
usage: PineconeUsage
}
interface PineconeParams {
apiKey: string
indexHost: string
operation: 'query' | 'upsert' | 'delete'
// Query operation
queryVector?: number[]
topK?: number
includeMetadata?: boolean
includeValues?: boolean
// Upsert operation
vectors?: Array<{
id: string
values: number[]
metadata?: Record<string, any>
}>
}
// Search Vector
export interface PineconeSearchVectorParams extends PineconeBaseParams {
vector: number[] | string
topK?: number | string
filter?: Record<string, any> | string
includeValues?: boolean
includeMetadata?: boolean
}
export interface PineconeDeleteVectorsParams {
apiKey: string
indexHost: string
namespace?: string
ids?: string[] | string
deleteAll?: boolean | string
filter?: Record<string, any> | string
}
export interface PineconeUpdateVectorParams {
apiKey: string
indexHost: string
id: string
namespace?: string
values?: number[] | string
sparseValues?: { indices: number[]; values: number[] } | string
setMetadata?: Record<string, any> | string
}
export interface PineconeDescribeIndexStatsParams {
apiKey: string
indexHost: string
filter?: Record<string, any> | string
}
export interface PineconeListIndexesParams {
apiKey: string
}
export interface PineconeDescribeIndexParams {
apiKey: string
indexName: string
}
export interface PineconeListVectorIdsParams {
apiKey: string
indexHost: string
namespace: string
prefix?: string
limit?: number | string
paginationToken?: string
}
+97
View File
@@ -0,0 +1,97 @@
import type { PineconeResponse, PineconeUpdateVectorParams } from '@/tools/pinecone/types'
import { parseJsonParam } from '@/tools/pinecone/utils'
import type { ToolConfig } from '@/tools/types'
export const updateVectorTool: ToolConfig<PineconeUpdateVectorParams, PineconeResponse> = {
id: 'pinecone_update_vector',
name: 'Pinecone Update Vector',
description: 'Update the values, sparse values, or metadata of a vector in a Pinecone namespace',
version: '1.0',
params: {
indexHost: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Full Pinecone index host URL (e.g., "https://my-index-abc123.svc.pinecone.io")',
},
id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Unique ID of the vector to update',
},
namespace: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Namespace containing the vector (e.g., "documents", "embeddings")',
},
values: {
type: 'array',
required: false,
visibility: 'user-or-llm',
description: 'New dense vector values to overwrite the existing values',
},
sparseValues: {
type: 'object',
required: false,
visibility: 'user-or-llm',
description: 'New sparse vector values with indices and values arrays',
},
setMetadata: {
type: 'object',
required: false,
visibility: 'user-or-llm',
description: 'Metadata key-value pairs to add or overwrite on the vector',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Pinecone API key',
},
},
request: {
method: 'POST',
url: (params) => `${params.indexHost}/vectors/update`,
headers: (params) => ({
'Api-Key': params.apiKey,
'Content-Type': 'application/json',
'X-Pinecone-API-Version': '2025-01',
}),
body: (params) => {
const body: Record<string, unknown> = { id: params.id.trim() }
if (params.namespace) {
body.namespace = params.namespace
}
if (params.values != null && params.values !== '') {
body.values = parseJsonParam(params.values, 'values')
}
if (params.sparseValues != null && params.sparseValues !== '') {
body.sparseValues = parseJsonParam(params.sparseValues, 'sparseValues')
}
if (params.setMetadata != null && params.setMetadata !== '') {
body.setMetadata = parseJsonParam(params.setMetadata, 'setMetadata')
}
return body
},
},
transformResponse: async (response) => {
return {
success: true,
output: {
statusText: response.status === 200 ? 'Updated' : response.statusText,
},
}
},
outputs: {
statusText: {
type: 'string',
description: 'Status of the update operation',
},
},
}
+89
View File
@@ -0,0 +1,89 @@
import type {
PineconeResponse,
PineconeUpsertTextParams,
PineconeUpsertTextRecord,
} from '@/tools/pinecone/types'
import type { ToolConfig } from '@/tools/types'
export const upsertTextTool: ToolConfig<PineconeUpsertTextParams, PineconeResponse> = {
id: 'pinecone_upsert_text',
name: 'Pinecone Upsert Text',
description: 'Insert or update text records in a Pinecone index',
version: '1.0',
params: {
indexHost: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Full Pinecone index host URL (e.g., "https://my-index-abc123.svc.pinecone.io")',
},
namespace: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Namespace to upsert records into (e.g., "documents", "embeddings")',
},
records: {
type: 'array',
required: true,
visibility: 'user-or-llm',
description:
'Record or array of records to upsert, each containing _id, text, and optional metadata',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Pinecone API key',
},
},
request: {
method: 'POST',
url: (params) => `${params.indexHost}/records/namespaces/${params.namespace}/upsert`,
headers: (params) => ({
'Api-Key': params.apiKey,
'Content-Type': 'application/x-ndjson',
'X-Pinecone-API-Version': '2025-01',
}),
body: (params) => {
// If records is a string, parse it line by line
let records: PineconeUpsertTextRecord[]
if (typeof params.records === 'string') {
// Split by newlines and parse each line
records = (params.records as string)
.split('\n')
.filter((line: string) => line.trim()) // Remove empty lines
.map((line: string) => {
// Clean and parse each line
const cleanJson = line.trim().replace(/'\\''/g, "'")
return JSON.parse(cleanJson) as PineconeUpsertTextRecord
})
} else {
records = Array.isArray(params.records) ? params.records : [params.records]
}
// Convert to NDJSON format
const ndjson = records.map((r: PineconeUpsertTextRecord) => JSON.stringify(r)).join('\n')
return { body: ndjson }
},
},
transformResponse: async (response) => {
// Pinecone upsert returns 201 Created with empty body on success
return {
success: response.status === 201,
output: {
statusText: response.status === 201 ? 'Created' : response.statusText,
},
}
},
outputs: {
statusText: {
type: 'string',
description: 'Status of the upsert operation',
},
},
}
+15
View File
@@ -0,0 +1,15 @@
/**
* Parse a Pinecone param that may arrive as a JSON string (from a block input or
* agent tool-call) or as an already-parsed value. Throws a descriptive error when
* a provided string is not valid JSON, instead of letting `JSON.parse` crash.
*/
export function parseJsonParam<T>(value: unknown, fieldName: string): T {
if (typeof value !== 'string') {
return value as T
}
try {
return JSON.parse(value) as T
} catch {
throw new Error(`${fieldName} must be valid JSON`)
}
}