@open-mercato/ai-assistant 0.4.11-develop.2206.f9b1d1d25e → 0.4.11-develop.2209.62f4737bb7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -104,7 +104,13 @@ class ToolSearchService {
|
|
|
104
104
|
records.push(toolToIndexableRecord(tool, moduleId));
|
|
105
105
|
}
|
|
106
106
|
if (records.length > 0) {
|
|
107
|
-
|
|
107
|
+
try {
|
|
108
|
+
await this.searchService.bulkIndex(records);
|
|
109
|
+
} catch (error) {
|
|
110
|
+
throw new Error(
|
|
111
|
+
`Failed to index ${records.length} tools: ${error instanceof Error ? error.message : error}`
|
|
112
|
+
);
|
|
113
|
+
}
|
|
108
114
|
}
|
|
109
115
|
this.lastIndexChecksum = checksum;
|
|
110
116
|
const status = await this.getStrategyStatus();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/ai_assistant/lib/tool-search.ts"],
|
|
4
|
-
"sourcesContent": ["import type { SearchService } from '@open-mercato/search/service'\nimport type { SearchStrategyId, IndexableRecord } from '@open-mercato/search/types'\nimport type { McpToolRegistry, McpToolDefinition } from './types'\nimport {\n TOOL_ENTITY_ID,\n GLOBAL_TENANT_ID,\n TOOL_SEARCH_CONFIG,\n toolToIndexableRecord,\n computeToolsChecksum,\n} from './tool-index-config'\n\n/**\n * Result from tool search.\n */\nexport type ToolSearchResult = {\n /** Tool name (recordId) */\n toolName: string\n /** Relevance score */\n score: number\n /** Module that registered the tool */\n moduleId?: string\n /** Features required to use this tool */\n requiredFeatures?: string[]\n}\n\n/**\n * Status of available search strategies.\n */\nexport type StrategyStatus = {\n fulltext: boolean\n vector: boolean\n tokens: boolean\n /** Ordered list of available strategies */\n available: SearchStrategyId[]\n /** Strategies that will be used by default */\n default: SearchStrategyId[]\n}\n\n/**\n * Result from tool indexing operation.\n */\nexport type IndexingResult = {\n indexed: number\n skipped: number\n strategies: SearchStrategyId[]\n checksum: string\n}\n\n/**\n * Options for searching tools.\n */\nexport type ToolSearchOptions = {\n /** Maximum results to return (default: 12) */\n limit?: number\n /** Override strategies to use */\n strategies?: SearchStrategyId[]\n /** User's features for ACL filtering */\n userFeatures?: string[]\n /** Is user a super admin (bypasses ACL) */\n isSuperAdmin?: boolean\n /** Minimum score threshold (default: 0.2) */\n minScore?: number\n}\n\n/**\n * Service for searching and indexing MCP tools using hybrid search strategies.\n *\n * Uses the existing search module infrastructure to provide:\n * - Fulltext search (Meilisearch) when configured\n * - Vector/semantic search (PgVector) when configured\n * - Token-based search (PostgreSQL hash) as fallback\n *\n * Results are merged using Reciprocal Rank Fusion (RRF) with weights:\n * - fulltext: 1.2\n * - vector: 1.0\n * - tokens: 0.8\n */\nexport class ToolSearchService {\n private lastIndexChecksum: string | null = null\n\n constructor(\n private readonly searchService: SearchService,\n private readonly toolRegistry: McpToolRegistry\n ) {}\n\n /**\n * Get status of available search strategies.\n * This helps the AI understand which integrations are available.\n */\n async getStrategyStatus(): Promise<StrategyStatus> {\n const [fulltext, vector, tokens] = await Promise.all([\n this.searchService.isStrategyAvailable('fulltext'),\n this.searchService.isStrategyAvailable('vector'),\n this.searchService.isStrategyAvailable('tokens'),\n ])\n\n const available: SearchStrategyId[] = []\n if (fulltext) available.push('fulltext')\n if (vector) available.push('vector')\n if (tokens) available.push('tokens')\n\n const defaultStrategies = this.searchService.getDefaultStrategies()\n\n return {\n fulltext,\n vector,\n tokens,\n available,\n default: defaultStrategies.filter((s) => available.includes(s)),\n }\n }\n\n /**\n * Search for relevant tools using hybrid strategies.\n *\n * @param query - User's search query or message\n * @param options - Search options\n * @returns Array of matching tools sorted by relevance\n */\n async searchTools(\n query: string,\n options: ToolSearchOptions = {}\n ): Promise<ToolSearchResult[]> {\n const {\n limit = TOOL_SEARCH_CONFIG.defaultLimit,\n strategies,\n userFeatures = [],\n isSuperAdmin = false,\n minScore = TOOL_SEARCH_CONFIG.minScore,\n } = options\n\n // Use hybrid search with all available strategies\n const searchResults = await this.searchService.search(query, {\n tenantId: GLOBAL_TENANT_ID,\n organizationId: null,\n entityTypes: [TOOL_ENTITY_ID],\n strategies,\n limit: limit * 2, // Get extra results to account for ACL filtering\n })\n\n // Map to tool results and filter by ACL\n const toolResults: ToolSearchResult[] = []\n\n for (const result of searchResults) {\n // Skip results below minimum score\n if (result.score < minScore) continue\n\n const metadata = result.metadata as Record<string, unknown> | undefined\n const requiredFeatures = (metadata?.requiredFeatures as string[]) ?? []\n const moduleId = metadata?.moduleId as string | undefined\n\n // Filter by user's feature access\n if (!this.hasFeatureAccess(requiredFeatures, userFeatures, isSuperAdmin)) {\n continue\n }\n\n toolResults.push({\n toolName: result.recordId,\n score: result.score,\n moduleId,\n requiredFeatures,\n })\n\n // Stop when we have enough results\n if (toolResults.length >= limit) break\n }\n\n return toolResults\n }\n\n /**\n * Index all tools from the registry using available strategies.\n * Uses checksum-based change detection to avoid unnecessary re-indexing.\n *\n * @param force - Force re-indexing even if checksum hasn't changed\n * @returns Indexing result with statistics\n */\n async indexTools(force = false): Promise<IndexingResult> {\n const tools = Array.from(this.toolRegistry.getTools().values())\n const modules = this.getToolModules()\n\n // Compute checksum to detect changes\n const checksum = computeToolsChecksum(\n tools.map((t) => ({ name: t.name, description: t.description }))\n )\n\n // Skip if checksum matches and not forced\n if (!force && this.lastIndexChecksum === checksum) {\n const status = await this.getStrategyStatus()\n return {\n indexed: 0,\n skipped: tools.length,\n strategies: status.available,\n checksum,\n }\n }\n\n // Build indexable records for all tools\n const records: IndexableRecord[] = []\n for (const tool of tools) {\n const moduleId = modules.get(tool.name)\n records.push(toolToIndexableRecord(tool, moduleId))\n }\n\n // Bulk index using available strategies\n if (records.length > 0) {\n await this.searchService.bulkIndex(records)\n }\n\n // Update checksum\n this.lastIndexChecksum = checksum\n\n const status = await this.getStrategyStatus()\n return {\n indexed: records.length,\n skipped: 0,\n strategies: status.available,\n checksum,\n }\n }\n\n /**\n * Purge all tool records from the search index.\n * Useful for cleanup or complete re-indexing.\n */\n async purgeIndex(): Promise<void> {\n await this.searchService.purge(TOOL_ENTITY_ID, GLOBAL_TENANT_ID)\n this.lastIndexChecksum = null\n }\n\n /**\n * Get tools by module ID from the registry.\n */\n getToolsByModule(moduleId: string): string[] {\n return this.toolRegistry.listToolsByModule(moduleId)\n }\n\n /**\n * Build a map of tool name to module ID.\n */\n private getToolModules(): Map<string, string> {\n const modules = new Map<string, string>()\n\n // Common module prefixes that indicate tool ownership\n const modulePatterns = [\n { pattern: /^customers_/, moduleId: 'customers' },\n { pattern: /^sales_/, moduleId: 'sales' },\n { pattern: /^catalog_/, moduleId: 'catalog' },\n { pattern: /^staff_/, moduleId: 'staff' },\n { pattern: /^resources_/, moduleId: 'resources' },\n { pattern: /^planner/, moduleId: 'planner' },\n { pattern: /^search_/, moduleId: 'search' },\n { pattern: /^context_/, moduleId: 'context' },\n { pattern: /^auth_/, moduleId: 'auth' },\n { pattern: /^directory_/, moduleId: 'directory' },\n { pattern: /^dashboards_/, moduleId: 'dashboards' },\n { pattern: /^entities_/, moduleId: 'entities' },\n { pattern: /^dictionaries_/, moduleId: 'dictionaries' },\n { pattern: /^workflows_/, moduleId: 'workflows' },\n { pattern: /^business_rules_/, moduleId: 'business_rules' },\n { pattern: /^audit_logs_/, moduleId: 'audit_logs' },\n { pattern: /^attachments_/, moduleId: 'attachments' },\n { pattern: /^feature_toggles_/, moduleId: 'feature_toggles' },\n { pattern: /^currencies_/, moduleId: 'currencies' },\n { pattern: /^example_/, moduleId: 'example' },\n { pattern: /^cli_/, moduleId: 'cli' },\n ]\n\n for (const toolName of this.toolRegistry.listToolNames()) {\n for (const { pattern, moduleId } of modulePatterns) {\n if (pattern.test(toolName)) {\n modules.set(toolName, moduleId)\n break\n }\n }\n }\n\n return modules\n }\n\n /**\n * Check if user has required features to access a tool.\n */\n private hasFeatureAccess(\n requiredFeatures: string[] | undefined,\n userFeatures: string[],\n isSuperAdmin: boolean\n ): boolean {\n if (isSuperAdmin) return true\n if (!requiredFeatures?.length) return true\n\n return requiredFeatures.every((required) => {\n // Direct match\n if (userFeatures.includes(required)) return true\n // Wildcard match\n if (userFeatures.includes('*')) return true\n\n // Prefix wildcard match (e.g., 'customers.*' matches 'customers.people.view')\n return userFeatures.some((feature) => {\n if (feature.endsWith('.*')) {\n const prefix = feature.slice(0, -2)\n return required.startsWith(prefix + '.')\n }\n return false\n })\n })\n }\n}\n"],
|
|
5
|
-
"mappings": "AAGA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAoEA,MAAM,kBAAkB;AAAA,EAG7B,YACmB,eACA,cACjB;AAFiB;AACA;AAJnB,SAAQ,oBAAmC;AAAA,EAKxC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMH,MAAM,oBAA6C;AACjD,UAAM,CAAC,UAAU,QAAQ,MAAM,IAAI,MAAM,QAAQ,IAAI;AAAA,MACnD,KAAK,cAAc,oBAAoB,UAAU;AAAA,MACjD,KAAK,cAAc,oBAAoB,QAAQ;AAAA,MAC/C,KAAK,cAAc,oBAAoB,QAAQ;AAAA,IACjD,CAAC;AAED,UAAM,YAAgC,CAAC;AACvC,QAAI,SAAU,WAAU,KAAK,UAAU;AACvC,QAAI,OAAQ,WAAU,KAAK,QAAQ;AACnC,QAAI,OAAQ,WAAU,KAAK,QAAQ;AAEnC,UAAM,oBAAoB,KAAK,cAAc,qBAAqB;AAElE,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS,kBAAkB,OAAO,CAAC,MAAM,UAAU,SAAS,CAAC,CAAC;AAAA,IAChE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,YACJ,OACA,UAA6B,CAAC,GACD;AAC7B,UAAM;AAAA,MACJ,QAAQ,mBAAmB;AAAA,MAC3B;AAAA,MACA,eAAe,CAAC;AAAA,MAChB,eAAe;AAAA,MACf,WAAW,mBAAmB;AAAA,IAChC,IAAI;AAGJ,UAAM,gBAAgB,MAAM,KAAK,cAAc,OAAO,OAAO;AAAA,MAC3D,UAAU;AAAA,MACV,gBAAgB;AAAA,MAChB,aAAa,CAAC,cAAc;AAAA,MAC5B;AAAA,MACA,OAAO,QAAQ;AAAA;AAAA,IACjB,CAAC;AAGD,UAAM,cAAkC,CAAC;AAEzC,eAAW,UAAU,eAAe;AAElC,UAAI,OAAO,QAAQ,SAAU;AAE7B,YAAM,WAAW,OAAO;AACxB,YAAM,mBAAoB,UAAU,oBAAiC,CAAC;AACtE,YAAM,WAAW,UAAU;AAG3B,UAAI,CAAC,KAAK,iBAAiB,kBAAkB,cAAc,YAAY,GAAG;AACxE;AAAA,MACF;AAEA,kBAAY,KAAK;AAAA,QACf,UAAU,OAAO;AAAA,QACjB,OAAO,OAAO;AAAA,QACd;AAAA,QACA;AAAA,MACF,CAAC;AAGD,UAAI,YAAY,UAAU,MAAO;AAAA,IACnC;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,WAAW,QAAQ,OAAgC;AACvD,UAAM,QAAQ,MAAM,KAAK,KAAK,aAAa,SAAS,EAAE,OAAO,CAAC;AAC9D,UAAM,UAAU,KAAK,eAAe;AAGpC,UAAM,WAAW;AAAA,MACf,MAAM,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,EAAE,YAAY,EAAE;AAAA,IACjE;AAGA,QAAI,CAAC,SAAS,KAAK,sBAAsB,UAAU;AACjD,YAAMA,UAAS,MAAM,KAAK,kBAAkB;AAC5C,aAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS,MAAM;AAAA,QACf,YAAYA,QAAO;AAAA,QACnB;AAAA,MACF;AAAA,IACF;AAGA,UAAM,UAA6B,CAAC;AACpC,eAAW,QAAQ,OAAO;AACxB,YAAM,WAAW,QAAQ,IAAI,KAAK,IAAI;AACtC,cAAQ,KAAK,sBAAsB,MAAM,QAAQ,CAAC;AAAA,IACpD;AAGA,QAAI,QAAQ,SAAS,GAAG;AACtB,
|
|
4
|
+
"sourcesContent": ["import type { SearchService } from '@open-mercato/search/service'\nimport type { SearchStrategyId, IndexableRecord } from '@open-mercato/search/types'\nimport type { McpToolRegistry, McpToolDefinition } from './types'\nimport {\n TOOL_ENTITY_ID,\n GLOBAL_TENANT_ID,\n TOOL_SEARCH_CONFIG,\n toolToIndexableRecord,\n computeToolsChecksum,\n} from './tool-index-config'\n\n/**\n * Result from tool search.\n */\nexport type ToolSearchResult = {\n /** Tool name (recordId) */\n toolName: string\n /** Relevance score */\n score: number\n /** Module that registered the tool */\n moduleId?: string\n /** Features required to use this tool */\n requiredFeatures?: string[]\n}\n\n/**\n * Status of available search strategies.\n */\nexport type StrategyStatus = {\n fulltext: boolean\n vector: boolean\n tokens: boolean\n /** Ordered list of available strategies */\n available: SearchStrategyId[]\n /** Strategies that will be used by default */\n default: SearchStrategyId[]\n}\n\n/**\n * Result from tool indexing operation.\n */\nexport type IndexingResult = {\n indexed: number\n skipped: number\n strategies: SearchStrategyId[]\n checksum: string\n}\n\n/**\n * Options for searching tools.\n */\nexport type ToolSearchOptions = {\n /** Maximum results to return (default: 12) */\n limit?: number\n /** Override strategies to use */\n strategies?: SearchStrategyId[]\n /** User's features for ACL filtering */\n userFeatures?: string[]\n /** Is user a super admin (bypasses ACL) */\n isSuperAdmin?: boolean\n /** Minimum score threshold (default: 0.2) */\n minScore?: number\n}\n\n/**\n * Service for searching and indexing MCP tools using hybrid search strategies.\n *\n * Uses the existing search module infrastructure to provide:\n * - Fulltext search (Meilisearch) when configured\n * - Vector/semantic search (PgVector) when configured\n * - Token-based search (PostgreSQL hash) as fallback\n *\n * Results are merged using Reciprocal Rank Fusion (RRF) with weights:\n * - fulltext: 1.2\n * - vector: 1.0\n * - tokens: 0.8\n */\nexport class ToolSearchService {\n private lastIndexChecksum: string | null = null\n\n constructor(\n private readonly searchService: SearchService,\n private readonly toolRegistry: McpToolRegistry\n ) {}\n\n /**\n * Get status of available search strategies.\n * This helps the AI understand which integrations are available.\n */\n async getStrategyStatus(): Promise<StrategyStatus> {\n const [fulltext, vector, tokens] = await Promise.all([\n this.searchService.isStrategyAvailable('fulltext'),\n this.searchService.isStrategyAvailable('vector'),\n this.searchService.isStrategyAvailable('tokens'),\n ])\n\n const available: SearchStrategyId[] = []\n if (fulltext) available.push('fulltext')\n if (vector) available.push('vector')\n if (tokens) available.push('tokens')\n\n const defaultStrategies = this.searchService.getDefaultStrategies()\n\n return {\n fulltext,\n vector,\n tokens,\n available,\n default: defaultStrategies.filter((s) => available.includes(s)),\n }\n }\n\n /**\n * Search for relevant tools using hybrid strategies.\n *\n * @param query - User's search query or message\n * @param options - Search options\n * @returns Array of matching tools sorted by relevance\n */\n async searchTools(\n query: string,\n options: ToolSearchOptions = {}\n ): Promise<ToolSearchResult[]> {\n const {\n limit = TOOL_SEARCH_CONFIG.defaultLimit,\n strategies,\n userFeatures = [],\n isSuperAdmin = false,\n minScore = TOOL_SEARCH_CONFIG.minScore,\n } = options\n\n // Use hybrid search with all available strategies\n const searchResults = await this.searchService.search(query, {\n tenantId: GLOBAL_TENANT_ID,\n organizationId: null,\n entityTypes: [TOOL_ENTITY_ID],\n strategies,\n limit: limit * 2, // Get extra results to account for ACL filtering\n })\n\n // Map to tool results and filter by ACL\n const toolResults: ToolSearchResult[] = []\n\n for (const result of searchResults) {\n // Skip results below minimum score\n if (result.score < minScore) continue\n\n const metadata = result.metadata as Record<string, unknown> | undefined\n const requiredFeatures = (metadata?.requiredFeatures as string[]) ?? []\n const moduleId = metadata?.moduleId as string | undefined\n\n // Filter by user's feature access\n if (!this.hasFeatureAccess(requiredFeatures, userFeatures, isSuperAdmin)) {\n continue\n }\n\n toolResults.push({\n toolName: result.recordId,\n score: result.score,\n moduleId,\n requiredFeatures,\n })\n\n // Stop when we have enough results\n if (toolResults.length >= limit) break\n }\n\n return toolResults\n }\n\n /**\n * Index all tools from the registry using available strategies.\n * Uses checksum-based change detection to avoid unnecessary re-indexing.\n *\n * @param force - Force re-indexing even if checksum hasn't changed\n * @returns Indexing result with statistics\n */\n async indexTools(force = false): Promise<IndexingResult> {\n const tools = Array.from(this.toolRegistry.getTools().values())\n const modules = this.getToolModules()\n\n // Compute checksum to detect changes\n const checksum = computeToolsChecksum(\n tools.map((t) => ({ name: t.name, description: t.description }))\n )\n\n // Skip if checksum matches and not forced\n if (!force && this.lastIndexChecksum === checksum) {\n const status = await this.getStrategyStatus()\n return {\n indexed: 0,\n skipped: tools.length,\n strategies: status.available,\n checksum,\n }\n }\n\n // Build indexable records for all tools\n const records: IndexableRecord[] = []\n for (const tool of tools) {\n const moduleId = modules.get(tool.name)\n records.push(toolToIndexableRecord(tool, moduleId))\n }\n\n // Bulk index using available strategies\n if (records.length > 0) {\n try {\n await this.searchService.bulkIndex(records)\n } catch (error) {\n throw new Error(\n `Failed to index ${records.length} tools: ${\n error instanceof Error ? error.message : error\n }`\n )\n }\n }\n\n // Update checksum\n this.lastIndexChecksum = checksum\n\n const status = await this.getStrategyStatus()\n return {\n indexed: records.length,\n skipped: 0,\n strategies: status.available,\n checksum,\n }\n }\n\n /**\n * Purge all tool records from the search index.\n * Useful for cleanup or complete re-indexing.\n */\n async purgeIndex(): Promise<void> {\n await this.searchService.purge(TOOL_ENTITY_ID, GLOBAL_TENANT_ID)\n this.lastIndexChecksum = null\n }\n\n /**\n * Get tools by module ID from the registry.\n */\n getToolsByModule(moduleId: string): string[] {\n return this.toolRegistry.listToolsByModule(moduleId)\n }\n\n /**\n * Build a map of tool name to module ID.\n */\n private getToolModules(): Map<string, string> {\n const modules = new Map<string, string>()\n\n // Common module prefixes that indicate tool ownership\n const modulePatterns = [\n { pattern: /^customers_/, moduleId: 'customers' },\n { pattern: /^sales_/, moduleId: 'sales' },\n { pattern: /^catalog_/, moduleId: 'catalog' },\n { pattern: /^staff_/, moduleId: 'staff' },\n { pattern: /^resources_/, moduleId: 'resources' },\n { pattern: /^planner/, moduleId: 'planner' },\n { pattern: /^search_/, moduleId: 'search' },\n { pattern: /^context_/, moduleId: 'context' },\n { pattern: /^auth_/, moduleId: 'auth' },\n { pattern: /^directory_/, moduleId: 'directory' },\n { pattern: /^dashboards_/, moduleId: 'dashboards' },\n { pattern: /^entities_/, moduleId: 'entities' },\n { pattern: /^dictionaries_/, moduleId: 'dictionaries' },\n { pattern: /^workflows_/, moduleId: 'workflows' },\n { pattern: /^business_rules_/, moduleId: 'business_rules' },\n { pattern: /^audit_logs_/, moduleId: 'audit_logs' },\n { pattern: /^attachments_/, moduleId: 'attachments' },\n { pattern: /^feature_toggles_/, moduleId: 'feature_toggles' },\n { pattern: /^currencies_/, moduleId: 'currencies' },\n { pattern: /^example_/, moduleId: 'example' },\n { pattern: /^cli_/, moduleId: 'cli' },\n ]\n\n for (const toolName of this.toolRegistry.listToolNames()) {\n for (const { pattern, moduleId } of modulePatterns) {\n if (pattern.test(toolName)) {\n modules.set(toolName, moduleId)\n break\n }\n }\n }\n\n return modules\n }\n\n /**\n * Check if user has required features to access a tool.\n */\n private hasFeatureAccess(\n requiredFeatures: string[] | undefined,\n userFeatures: string[],\n isSuperAdmin: boolean\n ): boolean {\n if (isSuperAdmin) return true\n if (!requiredFeatures?.length) return true\n\n return requiredFeatures.every((required) => {\n // Direct match\n if (userFeatures.includes(required)) return true\n // Wildcard match\n if (userFeatures.includes('*')) return true\n\n // Prefix wildcard match (e.g., 'customers.*' matches 'customers.people.view')\n return userFeatures.some((feature) => {\n if (feature.endsWith('.*')) {\n const prefix = feature.slice(0, -2)\n return required.startsWith(prefix + '.')\n }\n return false\n })\n })\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["status"]
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-mercato/ai-assistant",
|
|
3
|
-
"version": "0.4.11-develop.
|
|
3
|
+
"version": "0.4.11-develop.2209.62f4737bb7",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=22.0.0"
|
|
@@ -98,12 +98,12 @@
|
|
|
98
98
|
"zod-to-json-schema": "^3.25.1"
|
|
99
99
|
},
|
|
100
100
|
"peerDependencies": {
|
|
101
|
-
"@open-mercato/shared": "0.4.11-develop.
|
|
102
|
-
"@open-mercato/ui": "0.4.11-develop.
|
|
101
|
+
"@open-mercato/shared": "0.4.11-develop.2209.62f4737bb7",
|
|
102
|
+
"@open-mercato/ui": "0.4.11-develop.2209.62f4737bb7",
|
|
103
103
|
"zod": ">=3.23.0"
|
|
104
104
|
},
|
|
105
105
|
"devDependencies": {
|
|
106
|
-
"@open-mercato/cli": "0.4.11-develop.
|
|
106
|
+
"@open-mercato/cli": "0.4.11-develop.2209.62f4737bb7",
|
|
107
107
|
"tsx": "^4.21.0"
|
|
108
108
|
},
|
|
109
109
|
"publishConfig": {
|
|
@@ -204,7 +204,15 @@ export class ToolSearchService {
|
|
|
204
204
|
|
|
205
205
|
// Bulk index using available strategies
|
|
206
206
|
if (records.length > 0) {
|
|
207
|
-
|
|
207
|
+
try {
|
|
208
|
+
await this.searchService.bulkIndex(records)
|
|
209
|
+
} catch (error) {
|
|
210
|
+
throw new Error(
|
|
211
|
+
`Failed to index ${records.length} tools: ${
|
|
212
|
+
error instanceof Error ? error.message : error
|
|
213
|
+
}`
|
|
214
|
+
)
|
|
215
|
+
}
|
|
208
216
|
}
|
|
209
217
|
|
|
210
218
|
// Update checksum
|