@open-mercato/ai-assistant 0.4.11-develop.1909.991fce6e6a → 0.4.11-develop.1912.71c0c0adcd

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.
package/AGENTS.md CHANGED
@@ -59,7 +59,7 @@ registerMcpTool({
59
59
  APIs are automatically available via the Code Mode `search` tool (reads the OpenAPI spec at runtime). To add new endpoints:
60
60
 
61
61
  1. Define the endpoint in your module's route file with an `openApi` export
62
- 2. Regenerate the OpenAPI spec (`yarn modules:prepare`)
62
+ 2. Regenerate the OpenAPI spec (`yarn generate`)
63
63
  3. Restart the MCP server — the `search` tool's `spec.paths` will include the new endpoint
64
64
 
65
65
  ### Debug Tool Calls
package/README.md CHANGED
@@ -347,7 +347,7 @@ export const aiTools: AiToolDefinition[] = [
347
347
  Tools are automatically discovered when you run the module generator:
348
348
 
349
349
  ```bash
350
- npm run modules:prepare
350
+ yarn generate
351
351
  ```
352
352
 
353
353
  This scans all modules for `ai-tools.ts` files and generates `ai-tools.generated.ts` in `.mercato/generated/`.
@@ -355,7 +355,7 @@ This scans all modules for `ai-tools.ts` files and generates `ai-tools.generated
355
355
  ### Registration Flow
356
356
 
357
357
  1. Create `ai-tools.ts` in your module
358
- 2. Run `npm run modules:prepare` (or it runs automatically during `predev`/`prebuild`)
358
+ 2. Run `yarn generate` (or it runs automatically during `predev`/`prebuild`)
359
359
  3. Tools are available in the MCP server
360
360
 
361
361
  **Example**: See `packages/search/src/modules/search/ai-tools.ts` for a complete implementation with search-related tools.
@@ -142,7 +142,7 @@ async function parseApiEndpointsFromGeneratedJson() {
142
142
  }
143
143
  const jsonPath = path.join(appRoot.generatedDir, "openapi.generated.json");
144
144
  if (!fs.existsSync(jsonPath)) {
145
- console.error("[API Index] openapi.generated.json not found - run yarn modules:prepare");
145
+ console.error("[API Index] openapi.generated.json not found - run yarn generate");
146
146
  return [];
147
147
  }
148
148
  const doc = JSON.parse(fs.readFileSync(jsonPath, "utf-8"));
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/ai_assistant/lib/api-endpoint-index.ts"],
4
- "sourcesContent": ["/**\n * API Endpoint Index\n *\n * Parses OpenAPI spec and indexes endpoints for discovery via hybrid search.\n */\n\nimport type { OpenApiDocument } from '@open-mercato/shared/lib/openapi'\nimport { buildOpenApiDocument } from '@open-mercato/shared/lib/openapi'\nimport type { Module } from '@open-mercato/shared/modules/registry'\nimport type { SearchService } from '@open-mercato/search/service'\nimport type { IndexableRecord } from '@open-mercato/search/types'\nimport {\n API_ENDPOINT_ENTITY_ID,\n GLOBAL_TENANT_ID,\n API_ENDPOINT_SEARCH_CONFIG,\n endpointToIndexableRecord,\n computeEndpointsChecksum,\n} from './api-endpoint-index-config'\n\n/**\n * Indexed API endpoint structure\n */\nexport interface ApiEndpoint {\n id: string\n operationId: string\n method: string\n path: string\n summary: string\n description: string\n tags: string[]\n requiredFeatures: string[]\n parameters: ApiParameter[]\n requestBodySchema: Record<string, unknown> | null\n deprecated: boolean\n}\n\nexport interface ApiParameter {\n name: string\n in: 'path' | 'query' | 'header'\n required: boolean\n type: string\n description: string\n}\n\n/**\n * Entity type for API endpoints in search index\n * @deprecated Use API_ENDPOINT_ENTITY_ID from api-endpoint-index-config.ts\n */\nexport const API_ENDPOINT_ENTITY = API_ENDPOINT_ENTITY_ID\n\n/**\n * In-memory cache of parsed endpoints (avoid re-parsing on each request)\n */\nlet endpointsCache: ApiEndpoint[] | null = null\nlet endpointsByOperationId: Map<string, ApiEndpoint> | null = null\n\n/**\n * In-memory cache of the raw OpenAPI spec document (for Code Mode search tool)\n */\nlet rawSpecCache: OpenApiDocument | null = null\n\n/**\n * Get all parsed API endpoints (cached)\n */\nexport async function getApiEndpoints(): Promise<ApiEndpoint[]> {\n if (endpointsCache) {\n return endpointsCache\n }\n\n endpointsCache = await parseApiEndpoints()\n endpointsByOperationId = new Map(endpointsCache.map((e) => [e.operationId, e]))\n\n return endpointsCache\n}\n\n/**\n * Get endpoint by operationId\n */\nexport async function getEndpointByOperationId(operationId: string): Promise<ApiEndpoint | null> {\n await getApiEndpoints() // Ensure cache is populated\n return endpointsByOperationId?.get(operationId) ?? null\n}\n\n/**\n * Get the raw OpenAPI spec document (cached).\n * Uses the same 3-tier loading strategy as parseApiEndpoints():\n * generated JSON \u2192 module registry \u2192 HTTP fetch.\n */\nexport async function getRawOpenApiSpec(): Promise<OpenApiDocument | null> {\n if (rawSpecCache) return rawSpecCache\n rawSpecCache = await loadRawOpenApiSpec()\n return rawSpecCache\n}\n\n/**\n * Set the raw OpenAPI spec cache directly.\n * Used by servers that want to inject a pre-built spec.\n */\nexport function setRawSpecCache(doc: OpenApiDocument): void {\n rawSpecCache = doc\n}\n\n/**\n * Clear the raw OpenAPI spec cache.\n */\nexport function clearRawSpecCache(): void {\n rawSpecCache = null\n}\n\n/**\n * Load the rich OpenAPI spec, skipping Tier 1 (static JSON) which lacks requestBody schemas.\n * Prefers Tier 2 (runtime module registry) which has full Zod-converted schemas.\n * Falls back to Tier 1 then Tier 3 if needed.\n */\nexport async function loadRichOpenApiSpec(): Promise<OpenApiDocument | null> {\n if (rawSpecCache) return rawSpecCache\n\n // Tier 2 first: Module registry (has full Zod-converted schemas)\n try {\n const { getModules } = await import('@open-mercato/shared/lib/modules/registry')\n const modules: Module[] = getModules()\n const modulesWithApis = modules.filter((m) => m.apis && m.apis.length > 0)\n\n if (modulesWithApis.length > 0) {\n const doc = buildOpenApiDocument(modules, {\n title: 'Open Mercato API',\n version: '1.0.0',\n servers: [{ url: process.env.NEXT_PUBLIC_APP_URL || 'http://localhost:3000' }],\n })\n if (!doc.paths || Object.keys(doc.paths).length === 0) {\n return null\n }\n console.error(`[API Index] Rich OpenAPI spec built from ${modulesWithApis.length} modules (Tier 2)`)\n rawSpecCache = doc\n return doc\n }\n } catch {\n // Registry not available \u2014 fall through\n }\n\n // Fall back to standard 3-tier loading (Tier 1 \u2192 Tier 3)\n rawSpecCache = await loadRawOpenApiSpec()\n return rawSpecCache\n}\n\n/**\n * Load raw OpenAPI spec using the 3-tier strategy.\n */\nasync function loadRawOpenApiSpec(): Promise<OpenApiDocument | null> {\n // Tier 1: Generated JSON file\n try {\n const fs = await import('node:fs')\n const path = await import('node:path')\n const { findAppRoot, findAllApps } = await import('@open-mercato/shared/lib/bootstrap/appResolver')\n\n let appRoot = findAppRoot()\n if (!appRoot) {\n let current = process.cwd()\n while (current !== path.dirname(current)) {\n const appsDir = path.join(current, 'apps')\n if (fs.existsSync(appsDir)) {\n const apps = findAllApps(current)\n if (apps.length > 0) {\n appRoot = apps[0]\n break\n }\n }\n current = path.dirname(current)\n }\n }\n\n if (appRoot) {\n const jsonPath = path.join(appRoot.generatedDir, 'openapi.generated.json')\n if (fs.existsSync(jsonPath)) {\n const doc = JSON.parse(fs.readFileSync(jsonPath, 'utf-8')) as OpenApiDocument\n console.error(`[API Index] Raw OpenAPI spec loaded from ${jsonPath}`)\n return doc\n }\n }\n } catch (error) {\n console.error('[API Index] Raw spec from JSON failed:', error instanceof Error ? error.message : error)\n }\n\n // Tier 2: Module registry\n try {\n const { getModules } = await import('@open-mercato/shared/lib/modules/registry')\n const modules: Module[] = getModules()\n const modulesWithApis = modules.filter((m) => m.apis && m.apis.length > 0)\n\n if (modulesWithApis.length > 0) {\n const doc = buildOpenApiDocument(modules, {\n title: 'Open Mercato API',\n version: '1.0.0',\n servers: [{ url: process.env.NEXT_PUBLIC_APP_URL || 'http://localhost:3000' }],\n })\n console.error(`[API Index] Raw OpenAPI spec built from ${modulesWithApis.length} modules`)\n return doc\n }\n } catch {\n // Registry not available\n }\n\n // Tier 3: HTTP fetch\n const baseUrl =\n process.env.NEXT_PUBLIC_API_BASE_URL ||\n process.env.NEXT_PUBLIC_APP_URL ||\n process.env.APP_URL ||\n 'http://localhost:3000'\n\n try {\n const response = await fetch(`${baseUrl}/api/docs/openapi`)\n if (response.ok) {\n const doc = (await response.json()) as OpenApiDocument\n console.error('[API Index] Raw OpenAPI spec fetched via HTTP')\n return doc\n }\n } catch (error) {\n console.error('[API Index] Raw spec HTTP fetch failed:', error instanceof Error ? error.message : error)\n }\n\n return null\n}\n\n/**\n * Parse endpoints from generated OpenAPI JSON file (for CLI context).\n * This is generated by `yarn modules:prepare` or `yarn generate all`.\n */\nasync function parseApiEndpointsFromGeneratedJson(): Promise<ApiEndpoint[]> {\n try {\n const fs = await import('node:fs')\n const path = await import('node:path')\n const { findAppRoot, findAllApps } = await import('@open-mercato/shared/lib/bootstrap/appResolver')\n\n let appRoot = findAppRoot()\n\n // Try monorepo structure if not found - walk up to find monorepo root\n if (!appRoot) {\n let current = process.cwd()\n // Walk up until we find a directory containing 'apps' folder\n while (current !== path.dirname(current)) {\n const appsDir = path.join(current, 'apps')\n if (fs.existsSync(appsDir)) {\n const apps = findAllApps(current)\n if (apps.length > 0) {\n appRoot = apps[0]\n break\n }\n }\n current = path.dirname(current)\n }\n }\n\n if (!appRoot) {\n console.error('[API Index] Could not find app root')\n return []\n }\n\n const jsonPath = path.join(appRoot.generatedDir, 'openapi.generated.json')\n if (!fs.existsSync(jsonPath)) {\n console.error('[API Index] openapi.generated.json not found - run yarn modules:prepare')\n return []\n }\n\n const doc = JSON.parse(fs.readFileSync(jsonPath, 'utf-8')) as OpenApiDocument\n console.error(`[API Index] Loaded OpenAPI from ${jsonPath}`)\n return extractEndpoints(doc)\n } catch (error) {\n console.error('[API Index] Error reading generated JSON:', error instanceof Error ? error.message : error)\n return []\n }\n}\n\n/**\n * Parse endpoints from registered modules (works in Next.js context).\n */\nasync function parseApiEndpointsFromModules(): Promise<ApiEndpoint[]> {\n try {\n const { getModules } = await import('@open-mercato/shared/lib/modules/registry')\n const modules: Module[] = getModules()\n\n // Count how many modules have APIs defined\n const modulesWithApis = modules.filter((m) => m.apis && m.apis.length > 0)\n\n if (modulesWithApis.length > 0) {\n console.error(\n `[API Index] Found ${modules.length} modules, ${modulesWithApis.length} with APIs`\n )\n\n // Generate OpenAPI spec from modules\n const doc = buildOpenApiDocument(modules, {\n title: 'Open Mercato API',\n version: '1.0.0',\n servers: [{ url: process.env.NEXT_PUBLIC_APP_URL || 'http://localhost:3000' }],\n })\n if (!doc.paths || Object.keys(doc.paths).length === 0) {\n return []\n }\n\n return extractEndpoints(doc)\n }\n } catch {\n // Registry not available\n }\n\n return []\n}\n\n/**\n * Parse OpenAPI spec via HTTP fetch.\n * Fetches the OpenAPI spec from the running app's /api/docs/openapi endpoint.\n */\nasync function parseApiEndpointsFromHttp(): Promise<ApiEndpoint[]> {\n const baseUrl =\n process.env.NEXT_PUBLIC_API_BASE_URL ||\n process.env.NEXT_PUBLIC_APP_URL ||\n process.env.APP_URL ||\n 'http://localhost:3000'\n\n const openApiUrl = `${baseUrl}/api/docs/openapi`\n\n try {\n console.error(`[API Index] Fetching OpenAPI spec from ${openApiUrl}...`)\n const response = await fetch(openApiUrl)\n\n if (!response.ok) {\n console.error(`[API Index] Failed to fetch OpenAPI spec: ${response.status} ${response.statusText}`)\n return []\n }\n\n const doc = (await response.json()) as OpenApiDocument\n console.error(`[API Index] Successfully fetched OpenAPI spec`)\n return extractEndpoints(doc)\n } catch (error) {\n console.error('[API Index] Could not fetch OpenAPI spec:', error instanceof Error ? error.message : error)\n console.error('[API Index] Make sure the app is running at', baseUrl)\n return []\n }\n}\n\n/**\n * Parse API endpoints - tries generated JSON first (CLI), then modules (Next.js), then HTTP.\n */\nasync function parseApiEndpoints(): Promise<ApiEndpoint[]> {\n // Try generated JSON first (works in CLI context without Next.js)\n const fromJson = await parseApiEndpointsFromGeneratedJson()\n if (fromJson.length > 0) {\n console.error(`[API Index] Loaded ${fromJson.length} endpoints from generated JSON`)\n return fromJson\n }\n\n // Try loading from module registry (works in Next.js context)\n const fromModules = await parseApiEndpointsFromModules()\n if (fromModules.length > 0) {\n console.error(`[API Index] Loaded ${fromModules.length} endpoints from modules registry`)\n return fromModules\n }\n\n // Fall back to HTTP fetch (requires running Next.js app)\n console.error('[API Index] Generated JSON and modules not available, falling back to HTTP fetch...')\n return parseApiEndpointsFromHttp()\n}\n\n/**\n * Extract endpoints from OpenAPI document\n */\nfunction extractEndpoints(doc: OpenApiDocument): ApiEndpoint[] {\n const endpoints: ApiEndpoint[] = []\n const validMethods = ['get', 'post', 'put', 'patch', 'delete']\n\n if (!doc.paths) {\n return endpoints\n }\n\n for (const [path, pathItem] of Object.entries(doc.paths)) {\n if (!pathItem || typeof pathItem !== 'object') continue\n\n for (const [method, operation] of Object.entries(pathItem)) {\n if (!validMethods.includes(method.toLowerCase())) continue\n if (!operation || typeof operation !== 'object') continue\n\n const op = operation as any\n\n // Generate operationId if not present\n const operationId = op.operationId || generateOperationId(path, method)\n\n const endpoint: ApiEndpoint = {\n id: operationId,\n operationId,\n method: method.toUpperCase(),\n path,\n summary: op.summary || '',\n description: op.description || op.summary || `${method.toUpperCase()} ${path}`,\n tags: op.tags || [],\n requiredFeatures: op['x-require-features'] || [],\n deprecated: op.deprecated || false,\n parameters: extractParameters(op.parameters || []),\n requestBodySchema: extractRequestBodySchema(op.requestBody, doc.components?.schemas),\n }\n\n endpoints.push(endpoint)\n }\n }\n\n console.error(`[API Index] Parsed ${endpoints.length} endpoints from OpenAPI spec`)\n return endpoints\n}\n\n/**\n * Generate operationId from path and method\n */\nfunction generateOperationId(path: string, method: string): string {\n const pathParts = path\n .replace(/^\\//, '')\n .replace(/\\{([^}]+)\\}/g, 'by_$1')\n .split('/')\n .filter(Boolean)\n .join('_')\n\n return `${method.toLowerCase()}_${pathParts}`\n}\n\n/**\n * Extract parameter info\n */\nfunction extractParameters(params: any[]): ApiParameter[] {\n return params\n .filter((p) => p.in === 'path' || p.in === 'query')\n .map((p) => ({\n name: p.name,\n in: p.in,\n required: p.required ?? false,\n type: p.schema?.type || 'string',\n description: p.description || '',\n }))\n}\n\n/**\n * Extract request body schema (simplified)\n */\nfunction extractRequestBodySchema(\n requestBody: any,\n schemas?: Record<string, any>\n): Record<string, unknown> | null {\n if (!requestBody?.content?.['application/json']?.schema) {\n return null\n }\n\n const schema = requestBody.content['application/json'].schema\n\n // Resolve $ref if present\n if (schema.$ref && schemas) {\n const refPath = schema.$ref.replace('#/components/schemas/', '')\n return schemas[refPath] || schema\n }\n\n return schema\n}\n\n/**\n * Checksum from last indexing operation\n */\nlet lastIndexChecksum: string | null = null\n\n/**\n * Index endpoints for search discovery using hybrid search strategies.\n * Uses checksum-based change detection to avoid unnecessary re-indexing.\n *\n * @param searchService - The search service to use for indexing\n * @param force - Force re-indexing even if checksum hasn't changed\n * @returns Number of endpoints indexed\n */\nexport async function indexApiEndpoints(\n searchService: SearchService,\n force = false\n): Promise<number> {\n const endpoints = await getApiEndpoints()\n\n if (endpoints.length === 0) {\n console.error('[API Index] No endpoints to index')\n return 0\n }\n\n // Compute checksum to detect changes\n const checksum = computeEndpointsChecksum(\n endpoints.map((e) => ({ operationId: e.operationId, method: e.method, path: e.path }))\n )\n\n // Skip if checksum matches and not forced\n if (!force && lastIndexChecksum === checksum) {\n console.error(`[API Index] Skipping indexing - ${endpoints.length} endpoints unchanged`)\n return 0\n }\n\n // Convert to indexable records using the proper format\n const records: IndexableRecord[] = endpoints.map((endpoint) =>\n endpointToIndexableRecord(endpoint)\n )\n\n try {\n console.error(`[API Index] Starting bulk index of ${records.length} endpoints...`)\n // Bulk index using all available strategies (fulltext + vector)\n // Use Promise.race with timeout to prevent hanging\n const timeoutMs = 60000 // 60 second timeout\n const indexPromise = searchService.bulkIndex(records)\n const timeoutPromise = new Promise<never>((_, reject) =>\n setTimeout(() => reject(new Error(`Bulk index timed out after ${timeoutMs}ms`)), timeoutMs)\n )\n\n await Promise.race([indexPromise, timeoutPromise])\n lastIndexChecksum = checksum\n console.error(`[API Index] Indexed ${records.length} API endpoints for hybrid search`)\n return records.length\n } catch (error) {\n console.error('[API Index] Failed to index endpoints:', error)\n // Still return the count - some strategies may have succeeded\n lastIndexChecksum = checksum\n return records.length\n }\n}\n\n/**\n * Build searchable content from endpoint\n */\nfunction buildSearchableContent(endpoint: ApiEndpoint): string {\n const parts = [\n endpoint.operationId,\n endpoint.method,\n endpoint.path,\n endpoint.summary,\n endpoint.description,\n ...endpoint.tags,\n ...endpoint.parameters.map((p) => `${p.name} ${p.description}`),\n ]\n\n return parts.filter(Boolean).join(' ')\n}\n\n/**\n * Search endpoints using hybrid search (fulltext + vector).\n * Falls back to in-memory search if search service is not available.\n */\nexport async function searchEndpoints(\n searchService: SearchService | null,\n query: string,\n options: { limit?: number; method?: string } = {}\n): Promise<ApiEndpoint[]> {\n const { limit = API_ENDPOINT_SEARCH_CONFIG.defaultLimit, method } = options\n\n // Ensure endpoints are loaded\n await getApiEndpoints()\n\n // Try hybrid search first if search service is available\n if (searchService) {\n try {\n // Use hybrid search (fulltext + vector)\n const results = await searchService.search(query, {\n tenantId: GLOBAL_TENANT_ID,\n organizationId: null,\n entityTypes: [API_ENDPOINT_ENTITY_ID],\n limit: limit * 2, // Get extra to account for filtering\n })\n\n // Map search results back to ApiEndpoint objects\n const endpoints: ApiEndpoint[] = []\n for (const result of results) {\n if (endpoints.length >= limit) break\n\n const endpoint = endpointsByOperationId?.get(result.recordId)\n if (endpoint) {\n // Apply method filter if not handled by search\n if (method && endpoint.method !== method.toUpperCase()) continue\n endpoints.push(endpoint)\n }\n }\n\n if (endpoints.length > 0) {\n return endpoints\n }\n\n // Fall through to fallback if no results from hybrid search\n console.error('[API Index] No hybrid search results, falling back to in-memory search')\n } catch (error) {\n console.error('[API Index] Hybrid search failed, falling back to in-memory:', error)\n }\n }\n\n // Fallback: Simple in-memory text matching\n return searchEndpointsFallback(query, { limit, method })\n}\n\n/**\n * Fallback in-memory search when hybrid search is not available.\n */\nfunction searchEndpointsFallback(\n query: string,\n options: { limit?: number; method?: string } = {}\n): ApiEndpoint[] {\n const { limit = API_ENDPOINT_SEARCH_CONFIG.defaultLimit, method } = options\n\n if (!endpointsCache) {\n return []\n }\n\n const queryLower = query.toLowerCase()\n const queryTerms = queryLower.split(/\\s+/).filter(Boolean)\n\n let matches = endpointsCache.filter((endpoint) => {\n const content = buildSearchableContent(endpoint).toLowerCase()\n return queryTerms.some((term) => content.includes(term))\n })\n\n // Filter by method if specified\n if (method) {\n matches = matches.filter((e) => e.method === method.toUpperCase())\n }\n\n // Sort by relevance (number of matching terms)\n matches.sort((a, b) => {\n const aContent = buildSearchableContent(a).toLowerCase()\n const bContent = buildSearchableContent(b).toLowerCase()\n const aScore = queryTerms.filter((t) => aContent.includes(t)).length\n const bScore = queryTerms.filter((t) => bContent.includes(t)).length\n return bScore - aScore\n })\n\n return matches.slice(0, limit)\n}\n\n/**\n * Clear endpoint cache (for testing)\n */\nexport function clearEndpointCache(): void {\n endpointsCache = null\n endpointsByOperationId = null\n rawSpecCache = null\n}\n\n/**\n * Extract simplified request body schema for LLM consumption.\n * Returns required fields and basic property info without deep nesting.\n */\nexport function simplifyRequestBodySchema(\n schema: Record<string, unknown> | null\n): { required: string[]; properties: Record<string, { type: string; format?: string; enum?: string[] }> } | null {\n if (!schema) return null\n\n const properties: Record<string, { type: string; format?: string; enum?: string[] }> = {}\n const required: string[] = (schema.required as string[]) || []\n\n const schemaProps = (schema.properties || schema) as Record<string, unknown>\n\n for (const [key, value] of Object.entries(schemaProps)) {\n if (typeof value !== 'object' || value === null) continue\n const propSchema = value as Record<string, unknown>\n\n const prop: { type: string; format?: string; enum?: string[] } = {\n type: (propSchema.type as string) || 'unknown',\n }\n\n if (propSchema.format) prop.format = propSchema.format as string\n if (propSchema.enum && Array.isArray(propSchema.enum)) {\n prop.enum = propSchema.enum.slice(0, 10) as string[] // Limit enum values\n }\n\n properties[key] = prop\n }\n\n return { required, properties }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * API Endpoint Index\n *\n * Parses OpenAPI spec and indexes endpoints for discovery via hybrid search.\n */\n\nimport type { OpenApiDocument } from '@open-mercato/shared/lib/openapi'\nimport { buildOpenApiDocument } from '@open-mercato/shared/lib/openapi'\nimport type { Module } from '@open-mercato/shared/modules/registry'\nimport type { SearchService } from '@open-mercato/search/service'\nimport type { IndexableRecord } from '@open-mercato/search/types'\nimport {\n API_ENDPOINT_ENTITY_ID,\n GLOBAL_TENANT_ID,\n API_ENDPOINT_SEARCH_CONFIG,\n endpointToIndexableRecord,\n computeEndpointsChecksum,\n} from './api-endpoint-index-config'\n\n/**\n * Indexed API endpoint structure\n */\nexport interface ApiEndpoint {\n id: string\n operationId: string\n method: string\n path: string\n summary: string\n description: string\n tags: string[]\n requiredFeatures: string[]\n parameters: ApiParameter[]\n requestBodySchema: Record<string, unknown> | null\n deprecated: boolean\n}\n\nexport interface ApiParameter {\n name: string\n in: 'path' | 'query' | 'header'\n required: boolean\n type: string\n description: string\n}\n\n/**\n * Entity type for API endpoints in search index\n * @deprecated Use API_ENDPOINT_ENTITY_ID from api-endpoint-index-config.ts\n */\nexport const API_ENDPOINT_ENTITY = API_ENDPOINT_ENTITY_ID\n\n/**\n * In-memory cache of parsed endpoints (avoid re-parsing on each request)\n */\nlet endpointsCache: ApiEndpoint[] | null = null\nlet endpointsByOperationId: Map<string, ApiEndpoint> | null = null\n\n/**\n * In-memory cache of the raw OpenAPI spec document (for Code Mode search tool)\n */\nlet rawSpecCache: OpenApiDocument | null = null\n\n/**\n * Get all parsed API endpoints (cached)\n */\nexport async function getApiEndpoints(): Promise<ApiEndpoint[]> {\n if (endpointsCache) {\n return endpointsCache\n }\n\n endpointsCache = await parseApiEndpoints()\n endpointsByOperationId = new Map(endpointsCache.map((e) => [e.operationId, e]))\n\n return endpointsCache\n}\n\n/**\n * Get endpoint by operationId\n */\nexport async function getEndpointByOperationId(operationId: string): Promise<ApiEndpoint | null> {\n await getApiEndpoints() // Ensure cache is populated\n return endpointsByOperationId?.get(operationId) ?? null\n}\n\n/**\n * Get the raw OpenAPI spec document (cached).\n * Uses the same 3-tier loading strategy as parseApiEndpoints():\n * generated JSON \u2192 module registry \u2192 HTTP fetch.\n */\nexport async function getRawOpenApiSpec(): Promise<OpenApiDocument | null> {\n if (rawSpecCache) return rawSpecCache\n rawSpecCache = await loadRawOpenApiSpec()\n return rawSpecCache\n}\n\n/**\n * Set the raw OpenAPI spec cache directly.\n * Used by servers that want to inject a pre-built spec.\n */\nexport function setRawSpecCache(doc: OpenApiDocument): void {\n rawSpecCache = doc\n}\n\n/**\n * Clear the raw OpenAPI spec cache.\n */\nexport function clearRawSpecCache(): void {\n rawSpecCache = null\n}\n\n/**\n * Load the rich OpenAPI spec, skipping Tier 1 (static JSON) which lacks requestBody schemas.\n * Prefers Tier 2 (runtime module registry) which has full Zod-converted schemas.\n * Falls back to Tier 1 then Tier 3 if needed.\n */\nexport async function loadRichOpenApiSpec(): Promise<OpenApiDocument | null> {\n if (rawSpecCache) return rawSpecCache\n\n // Tier 2 first: Module registry (has full Zod-converted schemas)\n try {\n const { getModules } = await import('@open-mercato/shared/lib/modules/registry')\n const modules: Module[] = getModules()\n const modulesWithApis = modules.filter((m) => m.apis && m.apis.length > 0)\n\n if (modulesWithApis.length > 0) {\n const doc = buildOpenApiDocument(modules, {\n title: 'Open Mercato API',\n version: '1.0.0',\n servers: [{ url: process.env.NEXT_PUBLIC_APP_URL || 'http://localhost:3000' }],\n })\n if (!doc.paths || Object.keys(doc.paths).length === 0) {\n return null\n }\n console.error(`[API Index] Rich OpenAPI spec built from ${modulesWithApis.length} modules (Tier 2)`)\n rawSpecCache = doc\n return doc\n }\n } catch {\n // Registry not available \u2014 fall through\n }\n\n // Fall back to standard 3-tier loading (Tier 1 \u2192 Tier 3)\n rawSpecCache = await loadRawOpenApiSpec()\n return rawSpecCache\n}\n\n/**\n * Load raw OpenAPI spec using the 3-tier strategy.\n */\nasync function loadRawOpenApiSpec(): Promise<OpenApiDocument | null> {\n // Tier 1: Generated JSON file\n try {\n const fs = await import('node:fs')\n const path = await import('node:path')\n const { findAppRoot, findAllApps } = await import('@open-mercato/shared/lib/bootstrap/appResolver')\n\n let appRoot = findAppRoot()\n if (!appRoot) {\n let current = process.cwd()\n while (current !== path.dirname(current)) {\n const appsDir = path.join(current, 'apps')\n if (fs.existsSync(appsDir)) {\n const apps = findAllApps(current)\n if (apps.length > 0) {\n appRoot = apps[0]\n break\n }\n }\n current = path.dirname(current)\n }\n }\n\n if (appRoot) {\n const jsonPath = path.join(appRoot.generatedDir, 'openapi.generated.json')\n if (fs.existsSync(jsonPath)) {\n const doc = JSON.parse(fs.readFileSync(jsonPath, 'utf-8')) as OpenApiDocument\n console.error(`[API Index] Raw OpenAPI spec loaded from ${jsonPath}`)\n return doc\n }\n }\n } catch (error) {\n console.error('[API Index] Raw spec from JSON failed:', error instanceof Error ? error.message : error)\n }\n\n // Tier 2: Module registry\n try {\n const { getModules } = await import('@open-mercato/shared/lib/modules/registry')\n const modules: Module[] = getModules()\n const modulesWithApis = modules.filter((m) => m.apis && m.apis.length > 0)\n\n if (modulesWithApis.length > 0) {\n const doc = buildOpenApiDocument(modules, {\n title: 'Open Mercato API',\n version: '1.0.0',\n servers: [{ url: process.env.NEXT_PUBLIC_APP_URL || 'http://localhost:3000' }],\n })\n console.error(`[API Index] Raw OpenAPI spec built from ${modulesWithApis.length} modules`)\n return doc\n }\n } catch {\n // Registry not available\n }\n\n // Tier 3: HTTP fetch\n const baseUrl =\n process.env.NEXT_PUBLIC_API_BASE_URL ||\n process.env.NEXT_PUBLIC_APP_URL ||\n process.env.APP_URL ||\n 'http://localhost:3000'\n\n try {\n const response = await fetch(`${baseUrl}/api/docs/openapi`)\n if (response.ok) {\n const doc = (await response.json()) as OpenApiDocument\n console.error('[API Index] Raw OpenAPI spec fetched via HTTP')\n return doc\n }\n } catch (error) {\n console.error('[API Index] Raw spec HTTP fetch failed:', error instanceof Error ? error.message : error)\n }\n\n return null\n}\n\n/**\n * Parse endpoints from generated OpenAPI JSON file (for CLI context).\n * This is generated by `yarn generate`.\n */\nasync function parseApiEndpointsFromGeneratedJson(): Promise<ApiEndpoint[]> {\n try {\n const fs = await import('node:fs')\n const path = await import('node:path')\n const { findAppRoot, findAllApps } = await import('@open-mercato/shared/lib/bootstrap/appResolver')\n\n let appRoot = findAppRoot()\n\n // Try monorepo structure if not found - walk up to find monorepo root\n if (!appRoot) {\n let current = process.cwd()\n // Walk up until we find a directory containing 'apps' folder\n while (current !== path.dirname(current)) {\n const appsDir = path.join(current, 'apps')\n if (fs.existsSync(appsDir)) {\n const apps = findAllApps(current)\n if (apps.length > 0) {\n appRoot = apps[0]\n break\n }\n }\n current = path.dirname(current)\n }\n }\n\n if (!appRoot) {\n console.error('[API Index] Could not find app root')\n return []\n }\n\n const jsonPath = path.join(appRoot.generatedDir, 'openapi.generated.json')\n if (!fs.existsSync(jsonPath)) {\n console.error('[API Index] openapi.generated.json not found - run yarn generate')\n return []\n }\n\n const doc = JSON.parse(fs.readFileSync(jsonPath, 'utf-8')) as OpenApiDocument\n console.error(`[API Index] Loaded OpenAPI from ${jsonPath}`)\n return extractEndpoints(doc)\n } catch (error) {\n console.error('[API Index] Error reading generated JSON:', error instanceof Error ? error.message : error)\n return []\n }\n}\n\n/**\n * Parse endpoints from registered modules (works in Next.js context).\n */\nasync function parseApiEndpointsFromModules(): Promise<ApiEndpoint[]> {\n try {\n const { getModules } = await import('@open-mercato/shared/lib/modules/registry')\n const modules: Module[] = getModules()\n\n // Count how many modules have APIs defined\n const modulesWithApis = modules.filter((m) => m.apis && m.apis.length > 0)\n\n if (modulesWithApis.length > 0) {\n console.error(\n `[API Index] Found ${modules.length} modules, ${modulesWithApis.length} with APIs`\n )\n\n // Generate OpenAPI spec from modules\n const doc = buildOpenApiDocument(modules, {\n title: 'Open Mercato API',\n version: '1.0.0',\n servers: [{ url: process.env.NEXT_PUBLIC_APP_URL || 'http://localhost:3000' }],\n })\n if (!doc.paths || Object.keys(doc.paths).length === 0) {\n return []\n }\n\n return extractEndpoints(doc)\n }\n } catch {\n // Registry not available\n }\n\n return []\n}\n\n/**\n * Parse OpenAPI spec via HTTP fetch.\n * Fetches the OpenAPI spec from the running app's /api/docs/openapi endpoint.\n */\nasync function parseApiEndpointsFromHttp(): Promise<ApiEndpoint[]> {\n const baseUrl =\n process.env.NEXT_PUBLIC_API_BASE_URL ||\n process.env.NEXT_PUBLIC_APP_URL ||\n process.env.APP_URL ||\n 'http://localhost:3000'\n\n const openApiUrl = `${baseUrl}/api/docs/openapi`\n\n try {\n console.error(`[API Index] Fetching OpenAPI spec from ${openApiUrl}...`)\n const response = await fetch(openApiUrl)\n\n if (!response.ok) {\n console.error(`[API Index] Failed to fetch OpenAPI spec: ${response.status} ${response.statusText}`)\n return []\n }\n\n const doc = (await response.json()) as OpenApiDocument\n console.error(`[API Index] Successfully fetched OpenAPI spec`)\n return extractEndpoints(doc)\n } catch (error) {\n console.error('[API Index] Could not fetch OpenAPI spec:', error instanceof Error ? error.message : error)\n console.error('[API Index] Make sure the app is running at', baseUrl)\n return []\n }\n}\n\n/**\n * Parse API endpoints - tries generated JSON first (CLI), then modules (Next.js), then HTTP.\n */\nasync function parseApiEndpoints(): Promise<ApiEndpoint[]> {\n // Try generated JSON first (works in CLI context without Next.js)\n const fromJson = await parseApiEndpointsFromGeneratedJson()\n if (fromJson.length > 0) {\n console.error(`[API Index] Loaded ${fromJson.length} endpoints from generated JSON`)\n return fromJson\n }\n\n // Try loading from module registry (works in Next.js context)\n const fromModules = await parseApiEndpointsFromModules()\n if (fromModules.length > 0) {\n console.error(`[API Index] Loaded ${fromModules.length} endpoints from modules registry`)\n return fromModules\n }\n\n // Fall back to HTTP fetch (requires running Next.js app)\n console.error('[API Index] Generated JSON and modules not available, falling back to HTTP fetch...')\n return parseApiEndpointsFromHttp()\n}\n\n/**\n * Extract endpoints from OpenAPI document\n */\nfunction extractEndpoints(doc: OpenApiDocument): ApiEndpoint[] {\n const endpoints: ApiEndpoint[] = []\n const validMethods = ['get', 'post', 'put', 'patch', 'delete']\n\n if (!doc.paths) {\n return endpoints\n }\n\n for (const [path, pathItem] of Object.entries(doc.paths)) {\n if (!pathItem || typeof pathItem !== 'object') continue\n\n for (const [method, operation] of Object.entries(pathItem)) {\n if (!validMethods.includes(method.toLowerCase())) continue\n if (!operation || typeof operation !== 'object') continue\n\n const op = operation as any\n\n // Generate operationId if not present\n const operationId = op.operationId || generateOperationId(path, method)\n\n const endpoint: ApiEndpoint = {\n id: operationId,\n operationId,\n method: method.toUpperCase(),\n path,\n summary: op.summary || '',\n description: op.description || op.summary || `${method.toUpperCase()} ${path}`,\n tags: op.tags || [],\n requiredFeatures: op['x-require-features'] || [],\n deprecated: op.deprecated || false,\n parameters: extractParameters(op.parameters || []),\n requestBodySchema: extractRequestBodySchema(op.requestBody, doc.components?.schemas),\n }\n\n endpoints.push(endpoint)\n }\n }\n\n console.error(`[API Index] Parsed ${endpoints.length} endpoints from OpenAPI spec`)\n return endpoints\n}\n\n/**\n * Generate operationId from path and method\n */\nfunction generateOperationId(path: string, method: string): string {\n const pathParts = path\n .replace(/^\\//, '')\n .replace(/\\{([^}]+)\\}/g, 'by_$1')\n .split('/')\n .filter(Boolean)\n .join('_')\n\n return `${method.toLowerCase()}_${pathParts}`\n}\n\n/**\n * Extract parameter info\n */\nfunction extractParameters(params: any[]): ApiParameter[] {\n return params\n .filter((p) => p.in === 'path' || p.in === 'query')\n .map((p) => ({\n name: p.name,\n in: p.in,\n required: p.required ?? false,\n type: p.schema?.type || 'string',\n description: p.description || '',\n }))\n}\n\n/**\n * Extract request body schema (simplified)\n */\nfunction extractRequestBodySchema(\n requestBody: any,\n schemas?: Record<string, any>\n): Record<string, unknown> | null {\n if (!requestBody?.content?.['application/json']?.schema) {\n return null\n }\n\n const schema = requestBody.content['application/json'].schema\n\n // Resolve $ref if present\n if (schema.$ref && schemas) {\n const refPath = schema.$ref.replace('#/components/schemas/', '')\n return schemas[refPath] || schema\n }\n\n return schema\n}\n\n/**\n * Checksum from last indexing operation\n */\nlet lastIndexChecksum: string | null = null\n\n/**\n * Index endpoints for search discovery using hybrid search strategies.\n * Uses checksum-based change detection to avoid unnecessary re-indexing.\n *\n * @param searchService - The search service to use for indexing\n * @param force - Force re-indexing even if checksum hasn't changed\n * @returns Number of endpoints indexed\n */\nexport async function indexApiEndpoints(\n searchService: SearchService,\n force = false\n): Promise<number> {\n const endpoints = await getApiEndpoints()\n\n if (endpoints.length === 0) {\n console.error('[API Index] No endpoints to index')\n return 0\n }\n\n // Compute checksum to detect changes\n const checksum = computeEndpointsChecksum(\n endpoints.map((e) => ({ operationId: e.operationId, method: e.method, path: e.path }))\n )\n\n // Skip if checksum matches and not forced\n if (!force && lastIndexChecksum === checksum) {\n console.error(`[API Index] Skipping indexing - ${endpoints.length} endpoints unchanged`)\n return 0\n }\n\n // Convert to indexable records using the proper format\n const records: IndexableRecord[] = endpoints.map((endpoint) =>\n endpointToIndexableRecord(endpoint)\n )\n\n try {\n console.error(`[API Index] Starting bulk index of ${records.length} endpoints...`)\n // Bulk index using all available strategies (fulltext + vector)\n // Use Promise.race with timeout to prevent hanging\n const timeoutMs = 60000 // 60 second timeout\n const indexPromise = searchService.bulkIndex(records)\n const timeoutPromise = new Promise<never>((_, reject) =>\n setTimeout(() => reject(new Error(`Bulk index timed out after ${timeoutMs}ms`)), timeoutMs)\n )\n\n await Promise.race([indexPromise, timeoutPromise])\n lastIndexChecksum = checksum\n console.error(`[API Index] Indexed ${records.length} API endpoints for hybrid search`)\n return records.length\n } catch (error) {\n console.error('[API Index] Failed to index endpoints:', error)\n // Still return the count - some strategies may have succeeded\n lastIndexChecksum = checksum\n return records.length\n }\n}\n\n/**\n * Build searchable content from endpoint\n */\nfunction buildSearchableContent(endpoint: ApiEndpoint): string {\n const parts = [\n endpoint.operationId,\n endpoint.method,\n endpoint.path,\n endpoint.summary,\n endpoint.description,\n ...endpoint.tags,\n ...endpoint.parameters.map((p) => `${p.name} ${p.description}`),\n ]\n\n return parts.filter(Boolean).join(' ')\n}\n\n/**\n * Search endpoints using hybrid search (fulltext + vector).\n * Falls back to in-memory search if search service is not available.\n */\nexport async function searchEndpoints(\n searchService: SearchService | null,\n query: string,\n options: { limit?: number; method?: string } = {}\n): Promise<ApiEndpoint[]> {\n const { limit = API_ENDPOINT_SEARCH_CONFIG.defaultLimit, method } = options\n\n // Ensure endpoints are loaded\n await getApiEndpoints()\n\n // Try hybrid search first if search service is available\n if (searchService) {\n try {\n // Use hybrid search (fulltext + vector)\n const results = await searchService.search(query, {\n tenantId: GLOBAL_TENANT_ID,\n organizationId: null,\n entityTypes: [API_ENDPOINT_ENTITY_ID],\n limit: limit * 2, // Get extra to account for filtering\n })\n\n // Map search results back to ApiEndpoint objects\n const endpoints: ApiEndpoint[] = []\n for (const result of results) {\n if (endpoints.length >= limit) break\n\n const endpoint = endpointsByOperationId?.get(result.recordId)\n if (endpoint) {\n // Apply method filter if not handled by search\n if (method && endpoint.method !== method.toUpperCase()) continue\n endpoints.push(endpoint)\n }\n }\n\n if (endpoints.length > 0) {\n return endpoints\n }\n\n // Fall through to fallback if no results from hybrid search\n console.error('[API Index] No hybrid search results, falling back to in-memory search')\n } catch (error) {\n console.error('[API Index] Hybrid search failed, falling back to in-memory:', error)\n }\n }\n\n // Fallback: Simple in-memory text matching\n return searchEndpointsFallback(query, { limit, method })\n}\n\n/**\n * Fallback in-memory search when hybrid search is not available.\n */\nfunction searchEndpointsFallback(\n query: string,\n options: { limit?: number; method?: string } = {}\n): ApiEndpoint[] {\n const { limit = API_ENDPOINT_SEARCH_CONFIG.defaultLimit, method } = options\n\n if (!endpointsCache) {\n return []\n }\n\n const queryLower = query.toLowerCase()\n const queryTerms = queryLower.split(/\\s+/).filter(Boolean)\n\n let matches = endpointsCache.filter((endpoint) => {\n const content = buildSearchableContent(endpoint).toLowerCase()\n return queryTerms.some((term) => content.includes(term))\n })\n\n // Filter by method if specified\n if (method) {\n matches = matches.filter((e) => e.method === method.toUpperCase())\n }\n\n // Sort by relevance (number of matching terms)\n matches.sort((a, b) => {\n const aContent = buildSearchableContent(a).toLowerCase()\n const bContent = buildSearchableContent(b).toLowerCase()\n const aScore = queryTerms.filter((t) => aContent.includes(t)).length\n const bScore = queryTerms.filter((t) => bContent.includes(t)).length\n return bScore - aScore\n })\n\n return matches.slice(0, limit)\n}\n\n/**\n * Clear endpoint cache (for testing)\n */\nexport function clearEndpointCache(): void {\n endpointsCache = null\n endpointsByOperationId = null\n rawSpecCache = null\n}\n\n/**\n * Extract simplified request body schema for LLM consumption.\n * Returns required fields and basic property info without deep nesting.\n */\nexport function simplifyRequestBodySchema(\n schema: Record<string, unknown> | null\n): { required: string[]; properties: Record<string, { type: string; format?: string; enum?: string[] }> } | null {\n if (!schema) return null\n\n const properties: Record<string, { type: string; format?: string; enum?: string[] }> = {}\n const required: string[] = (schema.required as string[]) || []\n\n const schemaProps = (schema.properties || schema) as Record<string, unknown>\n\n for (const [key, value] of Object.entries(schemaProps)) {\n if (typeof value !== 'object' || value === null) continue\n const propSchema = value as Record<string, unknown>\n\n const prop: { type: string; format?: string; enum?: string[] } = {\n type: (propSchema.type as string) || 'unknown',\n }\n\n if (propSchema.format) prop.format = propSchema.format as string\n if (propSchema.enum && Array.isArray(propSchema.enum)) {\n prop.enum = propSchema.enum.slice(0, 10) as string[] // Limit enum values\n }\n\n properties[key] = prop\n }\n\n return { required, properties }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
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.1909.991fce6e6a",
3
+ "version": "0.4.11-develop.1912.71c0c0adcd",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "scripts": {
@@ -94,12 +94,12 @@
94
94
  "zod-to-json-schema": "^3.25.1"
95
95
  },
96
96
  "peerDependencies": {
97
- "@open-mercato/shared": "0.4.11-develop.1909.991fce6e6a",
98
- "@open-mercato/ui": "0.4.11-develop.1909.991fce6e6a",
97
+ "@open-mercato/shared": "0.4.11-develop.1912.71c0c0adcd",
98
+ "@open-mercato/ui": "0.4.11-develop.1912.71c0c0adcd",
99
99
  "zod": ">=3.23.0"
100
100
  },
101
101
  "devDependencies": {
102
- "@open-mercato/cli": "0.4.11-develop.1909.991fce6e6a",
102
+ "@open-mercato/cli": "0.4.11-develop.1912.71c0c0adcd",
103
103
  "tsx": "^4.21.0"
104
104
  },
105
105
  "publishConfig": {
@@ -223,7 +223,7 @@ async function loadRawOpenApiSpec(): Promise<OpenApiDocument | null> {
223
223
 
224
224
  /**
225
225
  * Parse endpoints from generated OpenAPI JSON file (for CLI context).
226
- * This is generated by `yarn modules:prepare` or `yarn generate all`.
226
+ * This is generated by `yarn generate`.
227
227
  */
228
228
  async function parseApiEndpointsFromGeneratedJson(): Promise<ApiEndpoint[]> {
229
229
  try {
@@ -257,7 +257,7 @@ async function parseApiEndpointsFromGeneratedJson(): Promise<ApiEndpoint[]> {
257
257
 
258
258
  const jsonPath = path.join(appRoot.generatedDir, 'openapi.generated.json')
259
259
  if (!fs.existsSync(jsonPath)) {
260
- console.error('[API Index] openapi.generated.json not found - run yarn modules:prepare')
260
+ console.error('[API Index] openapi.generated.json not found - run yarn generate')
261
261
  return []
262
262
  }
263
263