mirror of
https://github.com/simstudioai/sim.git
synced 2026-01-10 07:27:57 -05:00
* Superagent poc * Checkpoint brokeN * tool call rag * Fix * Fixes * Improvements * Creds stuff * Fix * Fix tools * Fix stream * Prompt * Update sheets descriptions * Better * Copilot components * Delete stuff * Remove db migration * Fix migrations * Fix things * Copilot side superagent * Build workflow from chat * Combine superagent into copilkot * Render tools * Function execution * Max mode indicators * Tool call confirmations * Credential settings * Remove betas * Bump version * Dropdown options in block metadata * Copilot kb tools * Fix lint * Credentials modal * Fix lint * Cleanup * Env var resolution in superagent tools * Get id for workflow vars * Fix insert into subflow * Fix executor for while and do while loops * Fix metadata for parallel * Remove db migration * Rebase * Add migrations back * Clean up code * Fix executor logic issue * Cleanup * Diagram tool * Fix tool naems * Comment out g3p * Remove popup option * Hide o3 * Remove db migration * Fix merge conflicts * Fix lint * Fix tests * Remove webhook change * Remove cb change * Fix lint * Fix * Fix lint * Fix build * comment out gemini * Add gemini back * Remove bad test * Fix * Fix test * Fix * Nuke bad test * Fix lint --------- Co-authored-by: Vikhyath Mondreti <vikhyathvikku@gmail.com> Co-authored-by: Waleed <walif6@gmail.com> Co-authored-by: waleedlatif1 <waleedlatif1@users.noreply.github.com>
239 lines
7.7 KiB
TypeScript
239 lines
7.7 KiB
TypeScript
import type { BaseServerTool } from '@/lib/copilot/tools/server/base-tool'
|
|
import {
|
|
type KnowledgeBaseArgs,
|
|
KnowledgeBaseArgsSchema,
|
|
type KnowledgeBaseResult,
|
|
} from '@/lib/copilot/tools/shared/schemas'
|
|
import { generateSearchEmbedding } from '@/lib/knowledge/embeddings'
|
|
import {
|
|
createKnowledgeBase,
|
|
getKnowledgeBaseById,
|
|
getKnowledgeBases,
|
|
} from '@/lib/knowledge/service'
|
|
import { createLogger } from '@/lib/logs/console/logger'
|
|
import { getQueryStrategy, handleVectorOnlySearch } from '@/app/api/knowledge/search/utils'
|
|
|
|
const logger = createLogger('KnowledgeBaseServerTool')
|
|
|
|
// Re-export for backwards compatibility
|
|
export const KnowledgeBaseInput = KnowledgeBaseArgsSchema
|
|
export type KnowledgeBaseInputType = KnowledgeBaseArgs
|
|
export type KnowledgeBaseResultType = KnowledgeBaseResult
|
|
|
|
/**
|
|
* Knowledge base tool for copilot to create, list, and get knowledge bases
|
|
*/
|
|
export const knowledgeBaseServerTool: BaseServerTool<KnowledgeBaseArgs, KnowledgeBaseResult> = {
|
|
name: 'knowledge_base',
|
|
async execute(
|
|
params: KnowledgeBaseArgs,
|
|
context?: { userId: string }
|
|
): Promise<KnowledgeBaseResult> {
|
|
if (!context?.userId) {
|
|
logger.error('Unauthorized attempt to access knowledge base - no authenticated user context')
|
|
throw new Error('Authentication required')
|
|
}
|
|
|
|
const { operation, args = {} } = params
|
|
|
|
try {
|
|
switch (operation) {
|
|
case 'create': {
|
|
if (!args.name) {
|
|
return {
|
|
success: false,
|
|
message: 'Name is required for creating a knowledge base',
|
|
}
|
|
}
|
|
|
|
const requestId = crypto.randomUUID().slice(0, 8)
|
|
const newKnowledgeBase = await createKnowledgeBase(
|
|
{
|
|
name: args.name,
|
|
description: args.description,
|
|
workspaceId: args.workspaceId,
|
|
userId: context.userId,
|
|
embeddingModel: 'text-embedding-3-small',
|
|
embeddingDimension: 1536,
|
|
chunkingConfig: args.chunkingConfig || {
|
|
maxSize: 1024,
|
|
minSize: 1,
|
|
overlap: 200,
|
|
},
|
|
},
|
|
requestId
|
|
)
|
|
|
|
logger.info('Knowledge base created via copilot', {
|
|
knowledgeBaseId: newKnowledgeBase.id,
|
|
name: newKnowledgeBase.name,
|
|
userId: context.userId,
|
|
})
|
|
|
|
return {
|
|
success: true,
|
|
message: `Knowledge base "${newKnowledgeBase.name}" created successfully`,
|
|
data: {
|
|
id: newKnowledgeBase.id,
|
|
name: newKnowledgeBase.name,
|
|
description: newKnowledgeBase.description,
|
|
workspaceId: newKnowledgeBase.workspaceId,
|
|
docCount: newKnowledgeBase.docCount,
|
|
createdAt: newKnowledgeBase.createdAt,
|
|
},
|
|
}
|
|
}
|
|
|
|
case 'list': {
|
|
const knowledgeBases = await getKnowledgeBases(context.userId, args.workspaceId)
|
|
|
|
logger.info('Knowledge bases listed via copilot', {
|
|
count: knowledgeBases.length,
|
|
userId: context.userId,
|
|
workspaceId: args.workspaceId,
|
|
})
|
|
|
|
return {
|
|
success: true,
|
|
message: `Found ${knowledgeBases.length} knowledge base(s)`,
|
|
data: knowledgeBases.map((kb) => ({
|
|
id: kb.id,
|
|
name: kb.name,
|
|
description: kb.description,
|
|
workspaceId: kb.workspaceId,
|
|
docCount: kb.docCount,
|
|
tokenCount: kb.tokenCount,
|
|
createdAt: kb.createdAt,
|
|
updatedAt: kb.updatedAt,
|
|
})),
|
|
}
|
|
}
|
|
|
|
case 'get': {
|
|
if (!args.knowledgeBaseId) {
|
|
return {
|
|
success: false,
|
|
message: 'Knowledge base ID is required for get operation',
|
|
}
|
|
}
|
|
|
|
const knowledgeBase = await getKnowledgeBaseById(args.knowledgeBaseId)
|
|
if (!knowledgeBase) {
|
|
return {
|
|
success: false,
|
|
message: `Knowledge base with ID "${args.knowledgeBaseId}" not found`,
|
|
}
|
|
}
|
|
|
|
logger.info('Knowledge base metadata retrieved via copilot', {
|
|
knowledgeBaseId: knowledgeBase.id,
|
|
userId: context.userId,
|
|
})
|
|
|
|
return {
|
|
success: true,
|
|
message: `Retrieved knowledge base "${knowledgeBase.name}"`,
|
|
data: {
|
|
id: knowledgeBase.id,
|
|
name: knowledgeBase.name,
|
|
description: knowledgeBase.description,
|
|
workspaceId: knowledgeBase.workspaceId,
|
|
docCount: knowledgeBase.docCount,
|
|
tokenCount: knowledgeBase.tokenCount,
|
|
embeddingModel: knowledgeBase.embeddingModel,
|
|
chunkingConfig: knowledgeBase.chunkingConfig,
|
|
createdAt: knowledgeBase.createdAt,
|
|
updatedAt: knowledgeBase.updatedAt,
|
|
},
|
|
}
|
|
}
|
|
|
|
case 'query': {
|
|
if (!args.knowledgeBaseId) {
|
|
return {
|
|
success: false,
|
|
message: 'Knowledge base ID is required for query operation',
|
|
}
|
|
}
|
|
|
|
if (!args.query) {
|
|
return {
|
|
success: false,
|
|
message: 'Query text is required for query operation',
|
|
}
|
|
}
|
|
|
|
// Verify knowledge base exists
|
|
const kb = await getKnowledgeBaseById(args.knowledgeBaseId)
|
|
if (!kb) {
|
|
return {
|
|
success: false,
|
|
message: `Knowledge base with ID "${args.knowledgeBaseId}" not found`,
|
|
}
|
|
}
|
|
|
|
const topK = args.topK || 5
|
|
|
|
// Generate embedding for the query
|
|
const queryEmbedding = await generateSearchEmbedding(args.query)
|
|
const queryVector = JSON.stringify(queryEmbedding)
|
|
|
|
// Get search strategy
|
|
const strategy = getQueryStrategy(1, topK)
|
|
|
|
// Perform vector search
|
|
const results = await handleVectorOnlySearch({
|
|
knowledgeBaseIds: [args.knowledgeBaseId],
|
|
topK,
|
|
queryVector,
|
|
distanceThreshold: strategy.distanceThreshold,
|
|
})
|
|
|
|
logger.info('Knowledge base queried via copilot', {
|
|
knowledgeBaseId: args.knowledgeBaseId,
|
|
query: args.query.substring(0, 100),
|
|
resultCount: results.length,
|
|
userId: context.userId,
|
|
})
|
|
|
|
return {
|
|
success: true,
|
|
message: `Found ${results.length} result(s) for query "${args.query.substring(0, 50)}${args.query.length > 50 ? '...' : ''}"`,
|
|
data: {
|
|
knowledgeBaseId: args.knowledgeBaseId,
|
|
knowledgeBaseName: kb.name,
|
|
query: args.query,
|
|
topK,
|
|
totalResults: results.length,
|
|
results: results.map((result) => ({
|
|
documentId: result.documentId,
|
|
content: result.content,
|
|
chunkIndex: result.chunkIndex,
|
|
similarity: 1 - result.distance,
|
|
})),
|
|
},
|
|
}
|
|
}
|
|
|
|
default:
|
|
return {
|
|
success: false,
|
|
message: `Unknown operation: ${operation}. Supported operations: create, list, get, query`,
|
|
}
|
|
}
|
|
} catch (error) {
|
|
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'
|
|
logger.error('Error in knowledge_base tool', {
|
|
operation,
|
|
error: errorMessage,
|
|
userId: context.userId,
|
|
})
|
|
|
|
return {
|
|
success: false,
|
|
message: `Failed to ${operation} knowledge base: ${errorMessage}`,
|
|
}
|
|
}
|
|
},
|
|
}
|