chore: import upstream snapshot with attribution
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled

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
+210
View File
@@ -0,0 +1,210 @@
import { DEFAULT_RERANKER_MODEL } from '@/lib/knowledge/reranker-models'
import type { KnowledgeSearchResponse } from '@/tools/knowledge/types'
import { enrichKBTagFiltersSchema } from '@/tools/schema-enrichers'
import { parseTagFilters } from '@/tools/shared/tags'
import type { ToolConfig } from '@/tools/types'
export const knowledgeSearchTool: ToolConfig<any, KnowledgeSearchResponse> = {
id: 'knowledge_search',
name: 'Knowledge Search',
description: 'Search for similar content in a knowledge base using vector similarity',
version: '1.0.0',
params: {
knowledgeBaseId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'ID of the knowledge base to search in',
},
query: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Search query text (optional when using tag filters)',
},
topK: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Number of most similar results to return (1-100)',
},
tagFilters: {
type: 'array',
required: false,
visibility: 'user-or-llm',
description: 'Array of tag filters with tagName and tagValue properties',
items: {
type: 'object',
properties: {
tagName: { type: 'string' },
tagValue: { type: 'string' },
},
},
},
rerankerEnabled: {
type: 'boolean',
required: false,
visibility: 'user-only',
description: 'Whether to apply Cohere reranking to vector search results',
},
rerankerModel: {
type: 'string',
required: false,
visibility: 'user-only',
description:
'Cohere rerank model to use (one of: rerank-v4.0-pro, rerank-v4.0-fast, rerank-v3.5)',
},
rerankerInputCount: {
type: 'number',
required: false,
visibility: 'user-only',
description:
'Number of vector results sent to the Cohere reranker (1100). Defaults to topK × 4 capped at 100.',
},
apiKey: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Cohere API key for reranker (self-hosted deployments only)',
},
},
schemaEnrichment: {
tagFilters: {
dependsOn: 'knowledgeBaseId',
enrichSchema: enrichKBTagFiltersSchema,
},
},
request: {
url: () => '/api/knowledge/search',
method: 'POST',
headers: () => ({
'Content-Type': 'application/json',
}),
body: (params) => {
const workflowId = params._context?.workflowId
// Use single knowledge base ID
const knowledgeBaseIds = [params.knowledgeBaseId]
// Parse tag filters from various formats (array, JSON string)
const structuredFilters = parseTagFilters(params.tagFilters)
const rerankerEnabled = params.rerankerEnabled === true || params.rerankerEnabled === 'true'
const rerankerModel =
typeof params.rerankerModel === 'string' && params.rerankerModel.length > 0
? params.rerankerModel
: DEFAULT_RERANKER_MODEL
const rerankerApiKey =
typeof params.apiKey === 'string' && params.apiKey.length > 0 ? params.apiKey : undefined
const rawInputCount =
params.rerankerInputCount !== undefined &&
params.rerankerInputCount !== null &&
params.rerankerInputCount !== ''
? Number(params.rerankerInputCount)
: Number.NaN
const rerankerInputCount = Number.isFinite(rawInputCount)
? Math.max(1, Math.min(100, Math.floor(rawInputCount)))
: undefined
const requestBody = {
knowledgeBaseIds,
query: params.query,
topK: params.topK ? Math.max(1, Math.min(100, Number(params.topK))) : 10,
...(structuredFilters.length > 0 && { tagFilters: structuredFilters }),
...(rerankerEnabled && {
rerankerEnabled: true,
rerankerModel,
...(rerankerInputCount !== undefined && { rerankerInputCount }),
...(rerankerApiKey && { rerankerApiKey }),
}),
...(workflowId && { workflowId }),
// The executor rolls this search's cost up at workflow completion, so
// tell the route not to also meter it (avoids double-billing).
skipUsageBilling: true,
}
return requestBody
},
},
transformResponse: async (response): Promise<KnowledgeSearchResponse> => {
const result = await response.json()
const data = result.data || result
// Restructure cost: extract tokens/model to top level for logging
let costFields: Record<string, unknown> = {}
if (data.cost && typeof data.cost === 'object') {
const {
tokens,
model,
input,
output: outputCost,
total,
rerankerCost,
rerankerModel,
rerankerSearchUnits,
} = data.cost
costFields = {
cost: {
input,
output: outputCost,
total,
...(typeof rerankerCost === 'number' && { rerankerCost }),
...(typeof rerankerModel === 'string' && { rerankerModel }),
...(typeof rerankerSearchUnits === 'number' && { rerankerSearchUnits }),
},
...(tokens && { tokens }),
...(model && { model }),
}
}
return {
success: true,
output: {
results: data.results || [],
query: data.query,
totalResults: data.totalResults || 0,
...costFields,
},
}
},
outputs: {
results: {
type: 'array',
description: 'Array of search results from the knowledge base',
items: {
type: 'object',
properties: {
documentId: { type: 'string', description: 'Document ID' },
documentName: { type: 'string', description: 'Document name' },
sourceUrl: {
type: 'string',
nullable: true,
description:
'URL to the original source document (e.g., Confluence page, Google Doc, Notion page). Null for documents without an external source.',
},
content: { type: 'string', description: 'Content of the result' },
chunkIndex: { type: 'number', description: 'Index of the chunk within the document' },
similarity: { type: 'number', description: 'Similarity score of the result' },
metadata: { type: 'object', description: 'Metadata of the result, including tags' },
},
},
},
query: {
type: 'string',
description: 'The search query that was executed',
},
totalResults: {
type: 'number',
description: 'Total number of results found',
},
cost: {
type: 'object',
description: 'Cost information for the search operation',
optional: true,
},
},
}