@red-hat-developer-hub/backstage-plugin-intelligent-assistant-backend 3.2.0 → 4.1.0

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.
@@ -1 +1 @@
1
- {"version":3,"file":"router.cjs.js","sources":["../../src/service/router.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { MiddlewareFactory } from '@backstage/backend-defaults/rootHttpRouter';\nimport type {\n AuthService,\n BackstageCredentials,\n LoggerService,\n} from '@backstage/backend-plugin-api';\nimport { NotAllowedError } from '@backstage/errors';\nimport type { BasicPermission } from '@backstage/plugin-permission-common';\nimport { createPermissionIntegrationRouter } from '@backstage/plugin-permission-node';\n\nimport express, { Router } from 'express';\nimport { createProxyMiddleware } from 'http-proxy-middleware';\n\nimport {\n lightspeedChatCreatePermission,\n lightspeedChatDeletePermission,\n lightspeedChatReadPermission,\n lightspeedChatUpdatePermission,\n lightspeedMcpManagePermission,\n lightspeedMcpReadPermission,\n lightspeedPermissions,\n lightspeedSavedPromptsManagePermission,\n} from '@red-hat-developer-hub/backstage-plugin-intelligent-assistant-common';\n\nimport { Readable } from 'node:stream';\n\nimport { ModelCapabilitiesCache } from './attachment-validation';\nimport {\n DEFAULT_LIGHTSPEED_SERVICE_HOST,\n DEFAULT_LIGHTSPEED_SERVICE_PORT,\n EXPRESS_JSON_BODY_LIMIT,\n TEST_VISION_JPEG,\n} from './constant';\nimport { McpUserSettingsStore } from './mcp-server-store';\nimport {\n McpServerAuth,\n McpServerResponse,\n McpServerStatus,\n McpValidationResult,\n} from './mcp-server-types';\nimport { McpServerValidator } from './mcp-server-validator';\nimport { createPermissionMiddleware } from './middleware/createPermissionMiddleware';\nimport { createRateLimitMiddleware } from './middleware/createRateLimitMiddleware';\nimport {\n createIdentityMiddleware,\n getIdentity,\n} from './middleware/getIdentity';\nimport { VectorStoresOperator } from './notebooks/VectorStoresOperator';\nimport { userPermissionAuthorization } from './permission';\nimport { createTokenEncryptor } from './token-encryption';\nimport { QueryRequestBody, RouterOptions } from './types';\nimport { handleLCSFetchError, rewriteProxyPath } from './utils';\nimport {\n validateAttachmentsForModel,\n validateCompletionsRequest,\n} from './validation';\n\n/**\n * MCP Server authentication modes for lightspeed.mcpServers entries.\n *\n * - `'dcr'` — Dynamic Client Registration. The Lightspeed backend mints a\n * short-lived Backstage plugin-request token carrying the current user's\n * identity. This token is forwarded to the MCP server via LCORE's\n * MCP-HEADERS, and the MCP Actions backend validates it against the\n * Backstage Permission Framework (RBAC). Use this for Backstage-internal\n * MCP servers (e.g. `@backstage/plugin-mcp-actions-backend`).\n * A static `token` field is **ignored** when `auth: dcr` is set.\n *\n * - (absent / undefined) — Legacy static-token mode. The token is resolved\n * from the user's DB override first, then from the `token` field in\n * app-config. If neither exists, the server is omitted from MCP-HEADERS.\n * Users can also set their own tokens via the Lightspeed UI.\n */\ninterface StaticMcpServer {\n name: string;\n token?: string;\n auth?: McpServerAuth;\n}\n\n/**\n * Build MCP-HEADERS for LCS. Format matches the LCS \"client\"/\"oauth\" auth\n * model: `{ \"server-name\": { \"Authorization\": \"<token>\" } }`\n *\n * For each admin-configured server:\n *\n * 1. If `auth: 'dcr'`, a Backstage plugin-request token is minted on behalf\n * of the authenticated user. Any static token is ignored.\n *\n * 2. Otherwise, the user's personal token (DB) takes precedence over the\n * admin default from app-config. If neither exists, the server is\n * excluded from MCP-HEADERS (LCORE will skip it or return 401).\n *\n * Servers the user has disabled are always excluded.\n */\nasync function buildMcpHeaders(\n servers: StaticMcpServer[],\n store: McpUserSettingsStore,\n userEntityRef: string,\n options?: {\n dcrAuth?: { authService: AuthService; credentials: BackstageCredentials };\n logger?: LoggerService;\n },\n): Promise<string> {\n const headers: Record<string, { Authorization: string }> = {};\n const userSettings = await store.listByUser(userEntityRef);\n const settingsMap = new Map(userSettings.map(s => [s.server_name, s]));\n\n for (const server of servers) {\n const setting = settingsMap.get(server.name);\n const enabled = setting ? Boolean(setting.enabled) : true;\n if (!enabled) continue;\n\n if (server.auth === 'dcr') {\n if (options?.dcrAuth) {\n try {\n const { token } =\n await options.dcrAuth.authService.getPluginRequestToken({\n onBehalfOf: options.dcrAuth.credentials,\n targetPluginId: 'mcp-actions',\n });\n headers[server.name] = { Authorization: `${token}` };\n } catch (err) {\n options?.logger?.error(\n `Failed to mint DCR token for MCP server '${server.name}': ${err}`,\n );\n }\n } else {\n options?.logger?.warn(\n `MCP server '${server.name}' has auth: dcr but AuthService is not available; skipping`,\n );\n }\n } else {\n // Static token: user's personal token (DB) > admin default (app-config).\n // If neither exists, the server is excluded from MCP-HEADERS.\n const token = setting?.token || server.token;\n if (token) {\n headers[server.name] = { Authorization: `${token}` };\n }\n }\n }\n\n return Object.keys(headers).length > 0 ? JSON.stringify(headers) : '';\n}\n\n/**\n * @public\n * The lightspeed backend router\n */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const { logger, config, database, httpAuth, auth, userInfo, permissions } =\n options;\n\n const router = Router();\n router.use(express.json());\n\n const port =\n config.getOptionalNumber('intelligent-assistant.servicePort') ??\n DEFAULT_LIGHTSPEED_SERVICE_PORT;\n const system_prompt = config.getOptionalString(\n 'intelligent-assistant.systemPrompt',\n );\n const lcsBaseUrl = `http://${DEFAULT_LIGHTSPEED_SERVICE_HOST}:${port}`;\n\n const apiProxy = createProxyMiddleware({\n target: lcsBaseUrl,\n changeOrigin: true,\n pathRewrite: (path, req) => {\n const userEntityRef = (req as any).userEntityRef;\n const newPath = rewriteProxyPath(path, userEntityRef);\n\n if (newPath !== path) {\n logger.info(`Rewriting path from ${path} to ${newPath}`);\n }\n return newPath;\n },\n });\n\n const vectorStoresOperator = VectorStoresOperator.getInstance(\n lcsBaseUrl,\n logger,\n );\n // Parse admin-configured MCP servers from app-config.\n //\n // Each entry supports:\n // name (required) — unique identifier, must match the name in lightspeed-stack.yaml\n // auth (optional) — authentication mode:\n // 'dcr' = the backend mints a per-user Backstage token (for\n // Backstage-internal MCP servers with DCR/OAuth enabled)\n // absent = legacy static-token mode (see `token` below)\n // token (optional) — static fallback token from app-config. Ignored when auth: dcr.\n // Users can also set personal tokens via the Lightspeed UI.\n //\n // URLs come from LCS (GET /v1/mcp-servers), not from app-config.\n const mcpServersConfig = config.getOptionalConfigArray(\n 'intelligent-assistant.mcpServers',\n );\n const staticServers: StaticMcpServer[] = [];\n if (mcpServersConfig) {\n for (const mcpServer of mcpServersConfig) {\n const authValue = mcpServer.getOptionalString('auth')?.toLowerCase();\n if (authValue && authValue !== 'dcr') {\n logger.warn(\n `MCP server '${mcpServer.getString('name')}' has unsupported auth value '${authValue}'; ` +\n `only 'dcr' is supported — falling back to static-token mode`,\n );\n }\n staticServers.push({\n name: mcpServer.getString('name'),\n token: mcpServer.getOptionalString('token'),\n auth: authValue === 'dcr' ? 'dcr' : undefined,\n });\n }\n }\n\n // Initialize database-backed store for per-user preferences and validator\n const dbClient = await database.getClient();\n const encryptor = createTokenEncryptor(config, logger);\n const settingsStore = new McpUserSettingsStore(dbClient, encryptor, logger);\n const mcpValidator = new McpServerValidator(logger);\n\n // URL cache populated from LCS GET /v1/mcp-servers.\n // The canonical URL for each MCP server lives in LCS config, not app-config.\n const lcsUrlCache = new Map<string, string>();\n\n async function refreshLcsUrlCache(): Promise<void> {\n try {\n const response = await fetch(`${lcsBaseUrl}/v1/mcp-servers`, {\n signal: AbortSignal.timeout(5000),\n });\n if (!response.ok) {\n logger.warn(\n `Failed to fetch MCP server URLs from LCS: HTTP ${response.status}`,\n );\n return;\n }\n const data = (await response.json()) as {\n servers: Array<{ name: string; url: string }>;\n };\n for (const s of data.servers) {\n lcsUrlCache.set(s.name, s.url);\n }\n logger.info(`Cached ${lcsUrlCache.size} MCP server URL(s) from LCS`);\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n logger.warn(`Failed to fetch MCP server URLs from LCS: ${msg}`);\n }\n }\n\n function resolveServerUrl(serverName: string): string | undefined {\n return lcsUrlCache.get(serverName);\n }\n\n // Best-effort URL cache on startup (non-blocking)\n refreshLcsUrlCache().catch(() => {});\n\n router.get('/health', (_, response) => {\n response.json({ status: 'ok' });\n });\n\n const permissionIntegrationRouter = createPermissionIntegrationRouter({\n permissions: lightspeedPermissions,\n });\n router.use(permissionIntegrationRouter);\n\n const identityMiddleware = createIdentityMiddleware(\n httpAuth,\n userInfo,\n logger,\n );\n router.use((req, res, next) => {\n // Middleware mounts to notebooks router independently\n // so we skip it here\n if (req.path.startsWith('/notebooks')) {\n return next();\n }\n return identityMiddleware(req, res, next);\n });\n\n const authorizer = userPermissionAuthorization(permissions);\n\n function requirePermission(permission: BasicPermission) {\n return createPermissionMiddleware(authorizer, permission, logger);\n }\n\n const expensiveRateLimiter = createRateLimitMiddleware(\n config,\n 'expensive',\n logger,\n );\n const generalRateLimiter = createRateLimitMiddleware(\n config,\n 'general',\n logger,\n );\n\n // ─── MCP Server Management Endpoints ────────────────────────────────\n // All MCP servers are admin-configured (static). Users can view the\n // list, toggle servers on/off, and provide personal access tokens.\n\n router.get(\n '/mcp-servers',\n generalRateLimiter,\n requirePermission(lightspeedMcpReadPermission),\n async (req, res) => {\n try {\n const { userEntityRef } = getIdentity(req);\n\n const userSettings = await settingsStore.listByUser(userEntityRef);\n const settingsMap = new Map(userSettings.map(s => [s.server_name, s]));\n\n const hasAllUrls = staticServers.every(s => lcsUrlCache.has(s.name));\n if (!hasAllUrls) {\n await refreshLcsUrlCache();\n }\n\n const servers: McpServerResponse[] = staticServers.map(server => {\n const setting = settingsMap.get(server.name);\n return {\n name: server.name,\n url: resolveServerUrl(server.name),\n enabled: setting ? Boolean(setting.enabled) : true,\n status: setting?.status ?? 'unknown',\n toolCount: setting?.tool_count ?? 0,\n // DCR servers always have a token (minted per-request); static servers check DB + config.\n hasToken:\n server.auth === 'dcr' || !!(setting?.token || server.token),\n hasUserToken: !!setting?.token,\n hasOrgToken: server.auth !== 'dcr' && !!server.token,\n auth: server.auth,\n };\n });\n\n res.json({ servers });\n } catch (error) {\n logger.error(`Error listing MCP servers: ${error}`);\n res.status(500).json({ error: 'Failed to list MCP servers' });\n }\n },\n );\n\n router.post(\n '/mcp-servers/validate',\n generalRateLimiter,\n requirePermission(lightspeedMcpReadPermission),\n async (req, res) => {\n try {\n const { url, token } = req.body;\n if (!url || !token) {\n res.status(400).json({ error: 'url and token are required' });\n return;\n }\n\n // SSRF protection: only allow URLs registered in LCS\n let knownUrls = new Set(lcsUrlCache.values());\n if (!knownUrls.has(url)) {\n await refreshLcsUrlCache();\n knownUrls = new Set(lcsUrlCache.values());\n }\n if (!knownUrls.has(url)) {\n res.status(400).json({\n error:\n 'URL not recognized — only MCP server URLs registered in LCS are allowed',\n });\n return;\n }\n\n const result = await mcpValidator.validate(url, token);\n res.json(result);\n } catch (error) {\n logger.error(`Error validating MCP credentials: ${error}`);\n res.status(500).json({ error: 'Validation failed' });\n }\n },\n );\n\n router.post(\n '/mcp-servers/:name/validate',\n generalRateLimiter,\n requirePermission(lightspeedMcpManagePermission),\n async (req, res) => {\n try {\n const { userEntityRef, credentials } = getIdentity(req);\n\n const { name } = req.params;\n const server = staticServers.find(s => s.name === name);\n if (!server) {\n res.status(404).json({\n error: `MCP server '${name}' is not configured — it must be defined in the Lightspeed Stack config and listed under intelligent-assistant.mcpServers in app-config`,\n });\n return;\n }\n // Resolve URL: LCS cache → fresh LCS fetch\n let serverUrl = resolveServerUrl(server.name);\n if (!serverUrl) {\n await refreshLcsUrlCache();\n serverUrl = resolveServerUrl(server.name);\n }\n if (!serverUrl) {\n res\n .status(400)\n .json({ error: 'Server has no URL — not found in LCS or config' });\n return;\n }\n\n let effectiveToken: string | undefined;\n if (server.auth === 'dcr') {\n try {\n const { token: dcrToken } = await auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: 'mcp-actions',\n });\n effectiveToken = dcrToken;\n } catch (err) {\n logger.error(\n `Failed to mint DCR token for server '${name}': ${err}`,\n );\n res.status(502).json({\n error: `Failed to mint authentication token for DCR server '${name}' — check Backstage auth configuration`,\n });\n return;\n }\n } else {\n const setting = await settingsStore.get(name, userEntityRef);\n effectiveToken = setting?.token || server.token;\n }\n if (!effectiveToken) {\n res\n .status(400)\n .json({ error: 'No token available — provide one first' });\n return;\n }\n\n const validation = await mcpValidator.validate(\n serverUrl,\n effectiveToken,\n );\n const status: McpServerStatus = validation.valid\n ? 'connected'\n : 'error';\n\n await settingsStore.updateStatus(\n name,\n userEntityRef,\n status,\n validation.toolCount,\n );\n\n res.json({\n name,\n status,\n toolCount: validation.toolCount,\n validation,\n });\n } catch (error) {\n logger.error(`Error validating MCP server: ${error}`);\n res.status(500).json({ error: 'Validation failed' });\n }\n },\n );\n\n router.patch(\n '/mcp-servers/:name',\n generalRateLimiter,\n requirePermission(lightspeedMcpManagePermission),\n async (req, res) => {\n try {\n const { userEntityRef } = getIdentity(req);\n\n const { name } = req.params;\n const server = staticServers.find(s => s.name === name);\n if (!server) {\n res.status(404).json({\n error: `MCP server '${name}' is not configured — it must be defined in the Lightspeed Stack config and listed under intelligent-assistant.mcpServers in app-config`,\n });\n return;\n }\n\n const body = (req.body ?? {}) as {\n enabled?: boolean;\n token?: string | null;\n };\n const hasEnabledField = Object.prototype.hasOwnProperty.call(\n body,\n 'enabled',\n );\n const hasTokenField = Object.prototype.hasOwnProperty.call(\n body,\n 'token',\n );\n const { enabled, token } = body;\n if (!hasEnabledField && !hasTokenField) {\n res.status(400).json({\n error: 'At least one of enabled or token must be provided',\n });\n return;\n }\n\n const setting = await settingsStore.upsert(name, userEntityRef, {\n enabled: hasEnabledField ? enabled : undefined,\n token: hasTokenField ? token : undefined,\n });\n\n let validation: McpValidationResult | undefined;\n let serverUrl = resolveServerUrl(server.name);\n if (token && !serverUrl) {\n await refreshLcsUrlCache();\n serverUrl = resolveServerUrl(server.name);\n }\n if (token && serverUrl) {\n validation = await mcpValidator.validate(serverUrl, token);\n const newStatus: McpServerStatus = validation.valid\n ? 'connected'\n : 'error';\n await settingsStore.updateStatus(\n name,\n userEntityRef,\n newStatus,\n validation.toolCount,\n );\n setting.status = newStatus;\n setting.tool_count = validation.toolCount;\n }\n\n const result: Record<string, unknown> = {\n server: {\n name: server.name,\n url: resolveServerUrl(server.name),\n enabled: Boolean(setting.enabled),\n status: setting.status,\n toolCount: setting.tool_count,\n hasToken:\n server.auth === 'dcr' || !!(setting.token || server.token),\n hasUserToken: !!setting.token,\n hasOrgToken: server.auth !== 'dcr' && !!server.token,\n auth: server.auth,\n },\n };\n if (validation) result.validation = validation;\n res.json(result);\n } catch (error) {\n logger.error(`Error updating MCP server settings: ${error}`);\n res.status(500).json({ error: 'Failed to update MCP server settings' });\n }\n },\n );\n\n // Returns conversation IDs associated with notebook sessions for filtering\n router.get(\n '/notebook-conversation-ids',\n generalRateLimiter,\n async (req, res) => {\n try {\n const { userEntityRef } = getIdentity(req);\n\n const vectorStoresPage = await vectorStoresOperator.vectorStores.list();\n const vectorStores = vectorStoresPage.data || [];\n\n const conversationIds: string[] = [];\n\n for (const store of vectorStores) {\n const sessionUserId = store.metadata?.user_id as string;\n const conversationId = store.metadata?.conversation_id as\n string | null;\n\n // Only include this user's sessions with a conversation_id\n if (sessionUserId === userEntityRef && conversationId) {\n conversationIds.push(conversationId);\n }\n }\n\n res.json({\n conversation_ids: conversationIds,\n });\n } catch (error) {\n const errormsg = `Error fetching notebook conversation IDs: ${error}`;\n logger.error(errormsg);\n\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else {\n res.status(500).json({ error: errormsg });\n }\n }\n },\n );\n\n // ─── Proxy Routes ───────────────────────────────────────────────────\n\n router.get(\n '/v1/models',\n generalRateLimiter,\n requirePermission(lightspeedChatReadPermission),\n apiProxy,\n );\n router.get(\n '/v1/shields',\n generalRateLimiter,\n requirePermission(lightspeedChatReadPermission),\n apiProxy,\n );\n router.get(\n '/v2/conversations',\n generalRateLimiter,\n requirePermission(lightspeedChatReadPermission),\n apiProxy,\n );\n router.get(\n '/v2/conversations/:conversation_id',\n generalRateLimiter,\n requirePermission(lightspeedChatReadPermission),\n apiProxy,\n );\n router.delete(\n '/v2/conversations/:conversation_id',\n generalRateLimiter,\n requirePermission(lightspeedChatDeletePermission),\n apiProxy,\n );\n router.get(\n '/v1/feedback/status',\n generalRateLimiter,\n requirePermission(lightspeedChatReadPermission),\n apiProxy,\n );\n\n router.get(\n '/v1/saved-prompts/config',\n generalRateLimiter,\n requirePermission(lightspeedSavedPromptsManagePermission),\n apiProxy, // SKIP_USER_ID_ENDPOINTS prevents user_id injection for this endpoint\n );\n router.get(\n '/v1/saved-prompts',\n generalRateLimiter,\n requirePermission(lightspeedSavedPromptsManagePermission),\n apiProxy,\n );\n router.delete(\n '/v1/saved-prompts/:prompt_id',\n generalRateLimiter,\n requirePermission(lightspeedSavedPromptsManagePermission),\n apiProxy,\n );\n\n router.post(\n '/v1/feedback',\n generalRateLimiter,\n requirePermission(lightspeedChatCreatePermission),\n async (request, response) => {\n try {\n const { userEntityRef } = getIdentity(request);\n\n logger.info(`/v1/feedback receives call from user: ${userEntityRef}`);\n\n const userQueryParam = `user_id=${encodeURIComponent(userEntityRef)}`;\n const requestBody = JSON.stringify(request.body);\n const fetchResponse = await fetch(\n `${lcsBaseUrl}/v1/feedback?${userQueryParam}`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: requestBody,\n },\n );\n\n if (!fetchResponse.ok) {\n await handleLCSFetchError(\n fetchResponse,\n logger,\n 'sending feedback',\n response,\n );\n return;\n }\n\n const data = await fetchResponse.json();\n response.status(fetchResponse.status).json(data);\n } catch (error) {\n const errormsg = `Error while sending feedback: ${error}`;\n logger.error(errormsg);\n response.status(500).json({ error: errormsg });\n }\n },\n );\n\n router.post(\n '/v1/saved-prompts',\n generalRateLimiter,\n requirePermission(lightspeedSavedPromptsManagePermission),\n async (request, response) => {\n try {\n const { userEntityRef } = getIdentity(request);\n\n logger.info(\n `/v1/saved-prompts receives call from user: ${userEntityRef}`,\n );\n\n const userQueryParam = `user_id=${encodeURIComponent(userEntityRef)}`;\n const requestBody = JSON.stringify(request.body);\n const fetchResponse = await fetch(\n `${lcsBaseUrl}/v1/saved-prompts?${userQueryParam}`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: requestBody,\n },\n );\n\n if (!fetchResponse.ok) {\n await handleLCSFetchError(\n fetchResponse,\n logger,\n 'creating saved prompt',\n response,\n );\n return;\n }\n\n const data = await fetchResponse.json();\n response.status(fetchResponse.status).json(data);\n } catch (error) {\n const errormsg = `Error while creating saved prompt: ${error}`;\n logger.error(errormsg);\n response.status(500).json({ error: errormsg });\n }\n },\n );\n\n router.post(\n '/v1/query/interrupt',\n generalRateLimiter,\n requirePermission(lightspeedChatCreatePermission),\n async (request, response) => {\n try {\n const { userEntityRef } = getIdentity(request);\n const userQueryParam = `user_id=${encodeURIComponent(userEntityRef)}`;\n const requestBody = JSON.stringify(request.body);\n const fetchResponse = await fetch(\n `${lcsBaseUrl}/v1/streaming_query/interrupt?${userQueryParam}`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: requestBody,\n },\n );\n if (!fetchResponse.ok) {\n await handleLCSFetchError(\n fetchResponse,\n logger,\n 'interrupting query',\n response,\n );\n return;\n }\n response.status(fetchResponse.status).json(await fetchResponse.json());\n } catch (error) {\n const errormsg = `Error while interrupting query: ${error}`;\n logger.error(errormsg);\n response.status(500).json({ error: errormsg });\n }\n },\n );\n\n router.post(\n '/v1/query',\n express.json({ limit: EXPRESS_JSON_BODY_LIMIT }),\n expensiveRateLimiter,\n validateCompletionsRequest,\n validateAttachmentsForModel,\n requirePermission(lightspeedChatCreatePermission),\n async (request, response) => {\n const { provider }: Pick<QueryRequestBody, 'provider'> = request.body;\n try {\n const { userEntityRef, credentials } = getIdentity(request);\n logger.info(`/v1/query receives call from user: ${userEntityRef}`);\n\n if (request.body.attachments?.length) {\n logger.info(\n `/v1/query includes ${request.body.attachments.length} attachment(s): ${request.body.attachments.map((a: { attachment_type: string }) => a.attachment_type).join(', ')}`,\n );\n }\n\n const userQueryParam = `user_id=${encodeURIComponent(userEntityRef)}`;\n request.body.media_type = 'application/json'; // set media_type to receive start and end event\n // if system_prompt is defined in lightspeed config\n // set system_prompt to override the default rhdh system prompt\n if (system_prompt && system_prompt.trim().length > 0) {\n request.body.system_prompt = system_prompt;\n }\n\n const requestBody = JSON.stringify(request.body);\n\n // Build MCP headers from config servers + this user's preferences.\n // For servers with auth: dcr, a per-user Backstage token is minted.\n const mcpHeadersValue = await buildMcpHeaders(\n staticServers,\n settingsStore,\n userEntityRef,\n { dcrAuth: { authService: auth, credentials }, logger },\n );\n\n const abortController = new AbortController();\n\n const fetchResponse = await fetch(\n `${lcsBaseUrl}/v1/streaming_query?${userQueryParam}`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'MCP-HEADERS': mcpHeadersValue,\n },\n body: requestBody,\n signal: abortController.signal,\n },\n );\n\n if (!fetchResponse.ok) {\n await handleLCSFetchError(\n fetchResponse,\n logger,\n 'processing query',\n response,\n );\n return;\n }\n\n // Pipe the response back to the original response\n if (fetchResponse.body) {\n const nodeStream = Readable.fromWeb(fetchResponse.body as any);\n\n nodeStream.on('error', (error: Error) => {\n logger.error(\n `Upstream stream error while processing query: ${error}`,\n );\n if (response.headersSent) {\n response.destroy();\n } else {\n response.status(500).json({ error: 'Stream error occurred' });\n }\n abortController.abort();\n });\n\n response.on('close', () => {\n if (!response.writableFinished) {\n logger.warn('Client disconnected while processing query');\n nodeStream.destroy();\n abortController.abort();\n }\n });\n\n nodeStream.pipe(response);\n }\n } catch (error) {\n const errormsg = `Error fetching completions from ${provider}: ${error}`;\n logger.error(errormsg);\n response.status(500).json({ error: errormsg });\n }\n },\n );\n\n router.put(\n '/v2/conversations/:conversation_id',\n generalRateLimiter,\n requirePermission(lightspeedChatUpdatePermission),\n async (request, response) => {\n try {\n const { userEntityRef } = getIdentity(request);\n const conversation_id = request.params.conversation_id;\n\n const requestBody = JSON.stringify(request.body);\n const userQueryParam = `user_id=${encodeURIComponent(userEntityRef)}`;\n const fetchResponse = await fetch(\n `${lcsBaseUrl}/v2/conversations/${conversation_id}?${userQueryParam}`,\n {\n method: 'PUT',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: requestBody,\n },\n );\n if (!fetchResponse.ok) {\n await handleLCSFetchError(\n fetchResponse,\n logger,\n 'updating conversation',\n response,\n );\n return;\n }\n\n const data = await fetchResponse.json();\n response.status(fetchResponse.status).json(data);\n } catch (error) {\n const errormsg = `Error while updating topic summary: ${error}`;\n logger.error(errormsg);\n response.status(500).json({ error: errormsg });\n }\n },\n );\n\n router.post(\n '/v1/validate-model-vision',\n generalRateLimiter,\n requirePermission(lightspeedChatReadPermission),\n async (request, response) => {\n const { model, provider } = request.body;\n\n if (\n typeof model !== 'string' ||\n !model.trim() ||\n typeof provider !== 'string' ||\n !provider.trim()\n ) {\n response.status(400).json({ error: 'model and provider are required' });\n return;\n }\n\n const cacheKey = `${provider}/${model}`;\n\n try {\n logger.info(`Vision validation requested for model: ${cacheKey}`);\n\n if (ModelCapabilitiesCache.has(cacheKey)) {\n const cached = ModelCapabilitiesCache.get(cacheKey)!;\n logger.info(`Cache hit for ${cacheKey}: ${cached}`);\n response.json({ model, provider, supportsVision: cached });\n return;\n }\n\n const testJpeg = `data:image/jpeg;base64,${TEST_VISION_JPEG}`;\n const testResponse = await fetch(`${lcsBaseUrl}/v1/responses`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n model: cacheKey,\n input: [\n {\n type: 'message',\n role: 'user',\n content: [\n {\n type: 'input_image',\n image_url: testJpeg,\n detail: 'low',\n },\n {\n type: 'input_text',\n text: 'hi, respond with hi.',\n },\n ],\n },\n ],\n tool_choice: 'none',\n temperature: 0,\n store: false,\n stream: false,\n }),\n });\n\n if (testResponse.ok) {\n ModelCapabilitiesCache.set(cacheKey, true);\n response.json({ model, provider, supportsVision: true });\n } else if (testResponse.status >= 500) {\n logger.warn(\n `Vision test for ${cacheKey}: ${testResponse.status} ${testResponse.statusText}, not caching`,\n );\n response.status(502).json({\n error: `Unable to verify vision support for model — upstream returned ${testResponse.status}`,\n model,\n provider,\n });\n } else {\n ModelCapabilitiesCache.set(cacheKey, false);\n response.json({ model, provider, supportsVision: false });\n }\n } catch (error) {\n logger.error(`Vision test error for ${cacheKey}:`, error);\n response.status(502).json({\n error:\n 'Unable to verify vision support for model — upstream unreachable',\n model,\n provider,\n });\n }\n },\n );\n\n router.use((_request, response) => {\n response.status(404).json({ error: 'Requested path is not available' });\n });\n\n const middleware = MiddlewareFactory.create({ logger, config });\n\n router.use(middleware.error());\n return router;\n}\n"],"names":["Router","express","DEFAULT_LIGHTSPEED_SERVICE_PORT","DEFAULT_LIGHTSPEED_SERVICE_HOST","createProxyMiddleware","rewriteProxyPath","VectorStoresOperator","createTokenEncryptor","McpUserSettingsStore","McpServerValidator","createPermissionIntegrationRouter","lightspeedPermissions","createIdentityMiddleware","userPermissionAuthorization","createPermissionMiddleware","createRateLimitMiddleware","lightspeedMcpReadPermission","getIdentity","lightspeedMcpManagePermission","NotAllowedError","lightspeedChatReadPermission","lightspeedChatDeletePermission","lightspeedSavedPromptsManagePermission","lightspeedChatCreatePermission","handleLCSFetchError","EXPRESS_JSON_BODY_LIMIT","validateCompletionsRequest","validateAttachmentsForModel","Readable","lightspeedChatUpdatePermission","ModelCapabilitiesCache","TEST_VISION_JPEG","MiddlewareFactory"],"mappings":"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"}
1
+ {"version":3,"file":"router.cjs.js","sources":["../../src/service/router.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { MiddlewareFactory } from '@backstage/backend-defaults/rootHttpRouter';\nimport type {\n AuthService,\n BackstageCredentials,\n LoggerService,\n} from '@backstage/backend-plugin-api';\nimport { NotAllowedError } from '@backstage/errors';\nimport type { BasicPermission } from '@backstage/plugin-permission-common';\nimport { createPermissionIntegrationRouter } from '@backstage/plugin-permission-node';\n\nimport express, { Router } from 'express';\nimport { createProxyMiddleware } from 'http-proxy-middleware';\n\nimport {\n iaChatAccessPermission,\n iaChatManagePermission,\n iaChatUsePermission,\n iaMcpManagePermission,\n iaMcpUsePermission,\n iaNotebooksUsePermission,\n iaPermissions,\n iaSkillsAccessPermission,\n} from '@red-hat-developer-hub/backstage-plugin-intelligent-assistant-common';\n\nimport { Readable } from 'node:stream';\n\nimport { ModelCapabilitiesCache } from './attachment-validation';\nimport {\n DEFAULT_LIGHTSPEED_SERVICE_HOST,\n DEFAULT_LIGHTSPEED_SERVICE_PORT,\n EXPRESS_JSON_BODY_LIMIT,\n TEST_VISION_JPEG,\n} from './constant';\nimport { McpUserSettingsStore } from './mcp-server-store';\nimport {\n McpServerAuth,\n McpServerResponse,\n McpServerStatus,\n McpValidationResult,\n} from './mcp-server-types';\nimport { McpServerValidator } from './mcp-server-validator';\nimport { createPermissionMiddleware } from './middleware/createPermissionMiddleware';\nimport { createRateLimitMiddleware } from './middleware/createRateLimitMiddleware';\nimport {\n createIdentityMiddleware,\n getIdentity,\n} from './middleware/getIdentity';\nimport { VectorStoresOperator } from './notebooks/VectorStoresOperator';\nimport { userPermissionAuthorization } from './permission';\nimport { createTokenEncryptor } from './token-encryption';\nimport { QueryRequestBody, RouterOptions } from './types';\nimport { handleLCSFetchError, rewriteProxyPath } from './utils';\nimport {\n validateAttachmentsForModel,\n validateCompletionsRequest,\n} from './validation';\n\n/**\n * MCP Server authentication modes for lightspeed.mcpServers entries.\n *\n * - `'dcr'` — Dynamic Client Registration. The Lightspeed backend mints a\n * short-lived Backstage plugin-request token carrying the current user's\n * identity. This token is forwarded to the MCP server via LCORE's\n * MCP-HEADERS, and the MCP Actions backend validates it against the\n * Backstage Permission Framework (RBAC). Use this for Backstage-internal\n * MCP servers (e.g. `@backstage/plugin-mcp-actions-backend`).\n * A static `token` field is **ignored** when `auth: dcr` is set.\n *\n * - (absent / undefined) — Legacy static-token mode. The token is resolved\n * from the user's DB override first, then from the `token` field in\n * app-config. If neither exists, the server is omitted from MCP-HEADERS.\n * Users can also set their own tokens via the Lightspeed UI.\n */\ninterface StaticMcpServer {\n name: string;\n token?: string;\n auth?: McpServerAuth;\n}\n\n/**\n * Build MCP-HEADERS for LCS. Format matches the LCS \"client\"/\"oauth\" auth\n * model: `{ \"server-name\": { \"Authorization\": \"<token>\" } }`\n *\n * For each admin-configured server:\n *\n * 1. If `auth: 'dcr'`, a Backstage plugin-request token is minted on behalf\n * of the authenticated user. Any static token is ignored.\n *\n * 2. Otherwise, the user's personal token (DB) takes precedence over the\n * admin default from app-config. If neither exists, the server is\n * excluded from MCP-HEADERS (LCORE will skip it or return 401).\n *\n * Servers the user has disabled are always excluded.\n */\nasync function buildMcpHeaders(\n servers: StaticMcpServer[],\n store: McpUserSettingsStore,\n userEntityRef: string,\n options?: {\n dcrAuth?: { authService: AuthService; credentials: BackstageCredentials };\n logger?: LoggerService;\n },\n): Promise<string> {\n const headers: Record<string, { Authorization: string }> = {};\n const userSettings = await store.listByUser(userEntityRef);\n const settingsMap = new Map(userSettings.map(s => [s.server_name, s]));\n\n for (const server of servers) {\n const setting = settingsMap.get(server.name);\n const enabled = setting ? Boolean(setting.enabled) : true;\n if (!enabled) continue;\n\n if (server.auth === 'dcr') {\n if (options?.dcrAuth) {\n try {\n const { token } =\n await options.dcrAuth.authService.getPluginRequestToken({\n onBehalfOf: options.dcrAuth.credentials,\n targetPluginId: 'mcp-actions',\n });\n headers[server.name] = { Authorization: `${token}` };\n } catch (err) {\n options?.logger?.error(\n `Failed to mint DCR token for MCP server '${server.name}': ${err}`,\n );\n }\n } else {\n options?.logger?.warn(\n `MCP server '${server.name}' has auth: dcr but AuthService is not available; skipping`,\n );\n }\n } else {\n // Static token: user's personal token (DB) > admin default (app-config).\n // If neither exists, the server is excluded from MCP-HEADERS.\n const token = setting?.token || server.token;\n if (token) {\n headers[server.name] = { Authorization: `${token}` };\n }\n }\n }\n\n return Object.keys(headers).length > 0 ? JSON.stringify(headers) : '';\n}\n\n/**\n * @public\n * The lightspeed backend router\n */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const { logger, config, database, httpAuth, auth, userInfo, permissions } =\n options;\n\n const router = Router();\n router.use(express.json());\n\n const port =\n config.getOptionalNumber('intelligent-assistant.servicePort') ??\n DEFAULT_LIGHTSPEED_SERVICE_PORT;\n const system_prompt = config.getOptionalString(\n 'intelligent-assistant.systemPrompt',\n );\n const lcsBaseUrl = `http://${DEFAULT_LIGHTSPEED_SERVICE_HOST}:${port}`;\n\n const apiProxy = createProxyMiddleware({\n target: lcsBaseUrl,\n changeOrigin: true,\n pathRewrite: (path, req) => {\n const userEntityRef = (req as any).userEntityRef;\n const newPath = rewriteProxyPath(path, userEntityRef);\n\n if (newPath !== path) {\n logger.info(`Rewriting path from ${path} to ${newPath}`);\n }\n return newPath;\n },\n });\n\n const vectorStoresOperator = VectorStoresOperator.getInstance(\n lcsBaseUrl,\n logger,\n );\n // Parse admin-configured MCP servers from app-config.\n //\n // Each entry supports:\n // name (required) — unique identifier, must match the name in lightspeed-stack.yaml\n // auth (optional) — authentication mode:\n // 'dcr' = the backend mints a per-user Backstage token (for\n // Backstage-internal MCP servers with DCR/OAuth enabled)\n // absent = legacy static-token mode (see `token` below)\n // token (optional) — static fallback token from app-config. Ignored when auth: dcr.\n // Users can also set personal tokens via the Lightspeed UI.\n //\n // URLs come from LCS (GET /v1/mcp-servers), not from app-config.\n const mcpServersConfig = config.getOptionalConfigArray(\n 'intelligent-assistant.mcpServers',\n );\n const staticServers: StaticMcpServer[] = [];\n if (mcpServersConfig) {\n for (const mcpServer of mcpServersConfig) {\n const authValue = mcpServer.getOptionalString('auth')?.toLowerCase();\n if (authValue && authValue !== 'dcr') {\n logger.warn(\n `MCP server '${mcpServer.getString('name')}' has unsupported auth value '${authValue}'; ` +\n `only 'dcr' is supported — falling back to static-token mode`,\n );\n }\n staticServers.push({\n name: mcpServer.getString('name'),\n token: mcpServer.getOptionalString('token'),\n auth: authValue === 'dcr' ? 'dcr' : undefined,\n });\n }\n }\n\n // Initialize database-backed store for per-user preferences and validator\n const dbClient = await database.getClient();\n const encryptor = createTokenEncryptor(config, logger);\n const settingsStore = new McpUserSettingsStore(dbClient, encryptor, logger);\n const mcpValidator = new McpServerValidator(logger);\n\n // URL cache populated from LCS GET /v1/mcp-servers.\n // The canonical URL for each MCP server lives in LCS config, not app-config.\n const lcsUrlCache = new Map<string, string>();\n\n async function refreshLcsUrlCache(): Promise<void> {\n try {\n const response = await fetch(`${lcsBaseUrl}/v1/mcp-servers`, {\n signal: AbortSignal.timeout(5000),\n });\n if (!response.ok) {\n logger.warn(\n `Failed to fetch MCP server URLs from LCS: HTTP ${response.status}`,\n );\n return;\n }\n const data = (await response.json()) as {\n servers: Array<{ name: string; url: string }>;\n };\n for (const s of data.servers) {\n lcsUrlCache.set(s.name, s.url);\n }\n logger.info(`Cached ${lcsUrlCache.size} MCP server URL(s) from LCS`);\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n logger.warn(`Failed to fetch MCP server URLs from LCS: ${msg}`);\n }\n }\n\n function resolveServerUrl(serverName: string): string | undefined {\n return lcsUrlCache.get(serverName);\n }\n\n // Best-effort URL cache on startup (non-blocking)\n refreshLcsUrlCache().catch(() => {});\n\n router.get('/health', (_, response) => {\n response.json({ status: 'ok' });\n });\n\n const permissionIntegrationRouter = createPermissionIntegrationRouter({\n permissions: iaPermissions,\n });\n router.use(permissionIntegrationRouter);\n\n const identityMiddleware = createIdentityMiddleware(\n httpAuth,\n userInfo,\n logger,\n );\n router.use((req, res, next) => {\n // Middleware mounts to notebooks router independently\n // so we skip it here\n if (req.path.startsWith('/notebooks')) {\n return next();\n }\n return identityMiddleware(req, res, next);\n });\n\n const authorizer = userPermissionAuthorization(permissions);\n\n function requirePermission(permission: BasicPermission) {\n return createPermissionMiddleware(authorizer, permission, logger);\n }\n\n const expensiveRateLimiter = createRateLimitMiddleware(\n config,\n 'expensive',\n logger,\n );\n const generalRateLimiter = createRateLimitMiddleware(\n config,\n 'general',\n logger,\n );\n\n // ─── MCP Server Management Endpoints ────────────────────────────────\n // All MCP servers are admin-configured (static). Users can view the\n // list, toggle servers on/off, and provide personal access tokens.\n\n router.get(\n '/mcp-servers',\n generalRateLimiter,\n requirePermission(iaMcpUsePermission),\n async (req, res) => {\n try {\n const { userEntityRef } = getIdentity(req);\n\n const userSettings = await settingsStore.listByUser(userEntityRef);\n const settingsMap = new Map(userSettings.map(s => [s.server_name, s]));\n\n const hasAllUrls = staticServers.every(s => lcsUrlCache.has(s.name));\n if (!hasAllUrls) {\n await refreshLcsUrlCache();\n }\n\n const servers: McpServerResponse[] = staticServers.map(server => {\n const setting = settingsMap.get(server.name);\n return {\n name: server.name,\n url: resolveServerUrl(server.name),\n enabled: setting ? Boolean(setting.enabled) : true,\n status: setting?.status ?? 'unknown',\n toolCount: setting?.tool_count ?? 0,\n // DCR servers always have a token (minted per-request); static servers check DB + config.\n hasToken:\n server.auth === 'dcr' || !!(setting?.token || server.token),\n hasUserToken: !!setting?.token,\n hasOrgToken: server.auth !== 'dcr' && !!server.token,\n auth: server.auth,\n };\n });\n\n res.json({ servers });\n } catch (error) {\n logger.error(`Error listing MCP servers: ${error}`);\n res.status(500).json({ error: 'Failed to list MCP servers' });\n }\n },\n );\n\n router.post(\n '/mcp-servers/validate',\n generalRateLimiter,\n requirePermission(iaMcpUsePermission),\n async (req, res) => {\n try {\n const { url, token } = req.body;\n if (!url || !token) {\n res.status(400).json({ error: 'url and token are required' });\n return;\n }\n\n // SSRF protection: only allow URLs registered in LCS\n let knownUrls = new Set(lcsUrlCache.values());\n if (!knownUrls.has(url)) {\n await refreshLcsUrlCache();\n knownUrls = new Set(lcsUrlCache.values());\n }\n if (!knownUrls.has(url)) {\n res.status(400).json({\n error:\n 'URL not recognized — only MCP server URLs registered in LCS are allowed',\n });\n return;\n }\n\n const result = await mcpValidator.validate(url, token);\n res.json(result);\n } catch (error) {\n logger.error(`Error validating MCP credentials: ${error}`);\n res.status(500).json({ error: 'Validation failed' });\n }\n },\n );\n\n router.post(\n '/mcp-servers/:name/validate',\n generalRateLimiter,\n requirePermission(iaMcpManagePermission),\n async (req, res) => {\n try {\n const { userEntityRef, credentials } = getIdentity(req);\n\n const { name } = req.params;\n const server = staticServers.find(s => s.name === name);\n if (!server) {\n res.status(404).json({\n error: `MCP server '${name}' is not configured — it must be defined in the Lightspeed Stack config and listed under intelligent-assistant.mcpServers in app-config`,\n });\n return;\n }\n // Resolve URL: LCS cache → fresh LCS fetch\n let serverUrl = resolveServerUrl(server.name);\n if (!serverUrl) {\n await refreshLcsUrlCache();\n serverUrl = resolveServerUrl(server.name);\n }\n if (!serverUrl) {\n res\n .status(400)\n .json({ error: 'Server has no URL — not found in LCS or config' });\n return;\n }\n\n let effectiveToken: string | undefined;\n if (server.auth === 'dcr') {\n try {\n const { token: dcrToken } = await auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: 'mcp-actions',\n });\n effectiveToken = dcrToken;\n } catch (err) {\n logger.error(\n `Failed to mint DCR token for server '${name}': ${err}`,\n );\n res.status(502).json({\n error: `Failed to mint authentication token for DCR server '${name}' — check Backstage auth configuration`,\n });\n return;\n }\n } else {\n const setting = await settingsStore.get(name, userEntityRef);\n effectiveToken = setting?.token || server.token;\n }\n if (!effectiveToken) {\n res\n .status(400)\n .json({ error: 'No token available — provide one first' });\n return;\n }\n\n const validation = await mcpValidator.validate(\n serverUrl,\n effectiveToken,\n );\n const status: McpServerStatus = validation.valid\n ? 'connected'\n : 'error';\n\n await settingsStore.updateStatus(\n name,\n userEntityRef,\n status,\n validation.toolCount,\n );\n\n res.json({\n name,\n status,\n toolCount: validation.toolCount,\n validation,\n });\n } catch (error) {\n logger.error(`Error validating MCP server: ${error}`);\n res.status(500).json({ error: 'Validation failed' });\n }\n },\n );\n\n router.patch(\n '/mcp-servers/:name',\n generalRateLimiter,\n requirePermission(iaMcpManagePermission),\n async (req, res) => {\n try {\n const { userEntityRef } = getIdentity(req);\n\n const { name } = req.params;\n const server = staticServers.find(s => s.name === name);\n if (!server) {\n res.status(404).json({\n error: `MCP server '${name}' is not configured — it must be defined in the Lightspeed Stack config and listed under intelligent-assistant.mcpServers in app-config`,\n });\n return;\n }\n\n const body = (req.body ?? {}) as {\n enabled?: boolean;\n token?: string | null;\n };\n const hasEnabledField = Object.prototype.hasOwnProperty.call(\n body,\n 'enabled',\n );\n const hasTokenField = Object.prototype.hasOwnProperty.call(\n body,\n 'token',\n );\n const { enabled, token } = body;\n if (!hasEnabledField && !hasTokenField) {\n res.status(400).json({\n error: 'At least one of enabled or token must be provided',\n });\n return;\n }\n\n const setting = await settingsStore.upsert(name, userEntityRef, {\n enabled: hasEnabledField ? enabled : undefined,\n token: hasTokenField ? token : undefined,\n });\n\n let validation: McpValidationResult | undefined;\n let serverUrl = resolveServerUrl(server.name);\n if (token && !serverUrl) {\n await refreshLcsUrlCache();\n serverUrl = resolveServerUrl(server.name);\n }\n if (token && serverUrl) {\n validation = await mcpValidator.validate(serverUrl, token);\n const newStatus: McpServerStatus = validation.valid\n ? 'connected'\n : 'error';\n await settingsStore.updateStatus(\n name,\n userEntityRef,\n newStatus,\n validation.toolCount,\n );\n setting.status = newStatus;\n setting.tool_count = validation.toolCount;\n }\n\n const result: Record<string, unknown> = {\n server: {\n name: server.name,\n url: resolveServerUrl(server.name),\n enabled: Boolean(setting.enabled),\n status: setting.status,\n toolCount: setting.tool_count,\n hasToken:\n server.auth === 'dcr' || !!(setting.token || server.token),\n hasUserToken: !!setting.token,\n hasOrgToken: server.auth !== 'dcr' && !!server.token,\n auth: server.auth,\n },\n };\n if (validation) result.validation = validation;\n res.json(result);\n } catch (error) {\n logger.error(`Error updating MCP server settings: ${error}`);\n res.status(500).json({ error: 'Failed to update MCP server settings' });\n }\n },\n );\n\n // Returns conversation IDs associated with notebook sessions for filtering\n router.get(\n '/notebook-conversation-ids',\n generalRateLimiter,\n requirePermission(iaNotebooksUsePermission),\n async (req, res) => {\n try {\n const { userEntityRef } = getIdentity(req);\n\n const vectorStoresPage = await vectorStoresOperator.vectorStores.list();\n const vectorStores = vectorStoresPage.data || [];\n\n const conversationIds: string[] = [];\n\n for (const store of vectorStores) {\n const sessionUserId = store.metadata?.user_id as string;\n const conversationId = store.metadata?.conversation_id as\n string | null;\n\n // Only include this user's sessions with a conversation_id\n if (sessionUserId === userEntityRef && conversationId) {\n conversationIds.push(conversationId);\n }\n }\n\n res.json({\n conversation_ids: conversationIds,\n });\n } catch (error) {\n const errormsg = `Error fetching notebook conversation IDs: ${error}`;\n logger.error(errormsg);\n\n if (error instanceof NotAllowedError) {\n res.status(403).json({ error: error.message });\n } else {\n res.status(500).json({ error: errormsg });\n }\n }\n },\n );\n\n // ─── Proxy Routes ───────────────────────────────────────────────────\n\n router.get(\n '/v1/models',\n generalRateLimiter,\n requirePermission(iaChatAccessPermission),\n apiProxy,\n );\n router.get(\n '/v1/shields',\n generalRateLimiter,\n requirePermission(iaChatAccessPermission),\n apiProxy,\n );\n router.get(\n '/v2/conversations',\n generalRateLimiter,\n requirePermission(iaChatAccessPermission),\n apiProxy,\n );\n router.get(\n '/v2/conversations/:conversation_id',\n generalRateLimiter,\n requirePermission(iaChatAccessPermission),\n apiProxy,\n );\n router.delete(\n '/v2/conversations/:conversation_id',\n generalRateLimiter,\n requirePermission(iaChatManagePermission),\n apiProxy,\n );\n router.get(\n '/v1/feedback/status',\n generalRateLimiter,\n requirePermission(iaChatAccessPermission),\n apiProxy,\n );\n\n router.get(\n '/v1/saved-prompts/config',\n generalRateLimiter,\n requirePermission(iaChatUsePermission),\n apiProxy, // SKIP_USER_ID_ENDPOINTS prevents user_id injection for this endpoint\n );\n router.get(\n '/v1/saved-prompts',\n generalRateLimiter,\n requirePermission(iaChatUsePermission),\n apiProxy,\n );\n router.delete(\n '/v1/saved-prompts/:prompt_id',\n generalRateLimiter,\n requirePermission(iaChatUsePermission),\n apiProxy,\n );\n\n router.get(\n '/v1/skills',\n generalRateLimiter,\n requirePermission(iaSkillsAccessPermission),\n apiProxy,\n );\n\n router.post(\n '/v1/feedback',\n generalRateLimiter,\n requirePermission(iaChatUsePermission),\n async (request, response) => {\n try {\n const { userEntityRef } = getIdentity(request);\n\n logger.info(`/v1/feedback receives call from user: ${userEntityRef}`);\n\n const userQueryParam = `user_id=${encodeURIComponent(userEntityRef)}`;\n const requestBody = JSON.stringify(request.body);\n const fetchResponse = await fetch(\n `${lcsBaseUrl}/v1/feedback?${userQueryParam}`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: requestBody,\n },\n );\n\n if (!fetchResponse.ok) {\n await handleLCSFetchError(\n fetchResponse,\n logger,\n 'sending feedback',\n response,\n );\n return;\n }\n\n const data = await fetchResponse.json();\n response.status(fetchResponse.status).json(data);\n } catch (error) {\n const errormsg = `Error while sending feedback: ${error}`;\n logger.error(errormsg);\n response.status(500).json({ error: errormsg });\n }\n },\n );\n\n router.post(\n '/v1/saved-prompts',\n generalRateLimiter,\n requirePermission(iaChatUsePermission),\n async (request, response) => {\n try {\n const { userEntityRef } = getIdentity(request);\n\n logger.info(\n `/v1/saved-prompts receives call from user: ${userEntityRef}`,\n );\n\n const userQueryParam = `user_id=${encodeURIComponent(userEntityRef)}`;\n const requestBody = JSON.stringify(request.body);\n const fetchResponse = await fetch(\n `${lcsBaseUrl}/v1/saved-prompts?${userQueryParam}`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: requestBody,\n },\n );\n\n if (!fetchResponse.ok) {\n await handleLCSFetchError(\n fetchResponse,\n logger,\n 'creating saved prompt',\n response,\n );\n return;\n }\n\n const data = await fetchResponse.json();\n response.status(fetchResponse.status).json(data);\n } catch (error) {\n const errormsg = `Error while creating saved prompt: ${error}`;\n logger.error(errormsg);\n response.status(500).json({ error: errormsg });\n }\n },\n );\n\n router.post(\n '/v1/query/interrupt',\n generalRateLimiter,\n requirePermission(iaChatUsePermission),\n async (request, response) => {\n try {\n const { userEntityRef } = getIdentity(request);\n const userQueryParam = `user_id=${encodeURIComponent(userEntityRef)}`;\n const requestBody = JSON.stringify(request.body);\n const fetchResponse = await fetch(\n `${lcsBaseUrl}/v1/streaming_query/interrupt?${userQueryParam}`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: requestBody,\n },\n );\n if (!fetchResponse.ok) {\n await handleLCSFetchError(\n fetchResponse,\n logger,\n 'interrupting query',\n response,\n );\n return;\n }\n response.status(fetchResponse.status).json(await fetchResponse.json());\n } catch (error) {\n const errormsg = `Error while interrupting query: ${error}`;\n logger.error(errormsg);\n response.status(500).json({ error: errormsg });\n }\n },\n );\n\n router.post(\n '/v1/query',\n express.json({ limit: EXPRESS_JSON_BODY_LIMIT }),\n expensiveRateLimiter,\n validateCompletionsRequest,\n validateAttachmentsForModel,\n requirePermission(iaChatUsePermission),\n async (request, response) => {\n const { provider }: Pick<QueryRequestBody, 'provider'> = request.body;\n try {\n const { userEntityRef, credentials } = getIdentity(request);\n logger.info(`/v1/query receives call from user: ${userEntityRef}`);\n if (request.body.attachments?.length) {\n logger.info(\n `/v1/query includes ${request.body.attachments.length} attachment(s): ${request.body.attachments.map((a: { attachment_type: string }) => a.attachment_type).join(', ')}`,\n );\n }\n\n const userQueryParam = `user_id=${encodeURIComponent(userEntityRef)}`;\n request.body.media_type = 'application/json'; // set media_type to receive start and end event\n // if system_prompt is defined in lightspeed config\n // set system_prompt to override the default rhdh system prompt\n if (system_prompt && system_prompt.trim().length > 0) {\n request.body.system_prompt = system_prompt;\n }\n\n const requestBody = JSON.stringify(request.body);\n\n // Build MCP headers from config servers + this user's preferences.\n // For servers with auth: dcr, a per-user Backstage token is minted.\n const mcpHeadersValue = await buildMcpHeaders(\n staticServers,\n settingsStore,\n userEntityRef,\n { dcrAuth: { authService: auth, credentials }, logger },\n );\n\n const abortController = new AbortController();\n\n const fetchResponse = await fetch(\n `${lcsBaseUrl}/v1/streaming_query?${userQueryParam}`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'MCP-HEADERS': mcpHeadersValue,\n },\n body: requestBody,\n signal: abortController.signal,\n },\n );\n\n if (!fetchResponse.ok) {\n await handleLCSFetchError(\n fetchResponse,\n logger,\n 'processing query',\n response,\n );\n return;\n }\n\n // Pipe the response back to the original response\n if (fetchResponse.body) {\n const nodeStream = Readable.fromWeb(fetchResponse.body as any);\n\n nodeStream.on('error', (error: Error) => {\n logger.error(\n `Upstream stream error while processing query: ${error}`,\n );\n if (response.headersSent) {\n response.destroy();\n } else {\n response.status(500).json({ error: 'Stream error occurred' });\n }\n abortController.abort();\n });\n\n response.on('close', () => {\n if (!response.writableFinished) {\n logger.warn('Client disconnected while processing query');\n nodeStream.destroy();\n abortController.abort();\n }\n });\n\n nodeStream.pipe(response);\n }\n } catch (error) {\n const errormsg = `Error fetching completions from ${provider}: ${error}`;\n logger.error(errormsg);\n response.status(500).json({ error: errormsg });\n }\n },\n );\n\n router.put(\n '/v2/conversations/:conversation_id',\n generalRateLimiter,\n requirePermission(iaChatManagePermission),\n async (request, response) => {\n try {\n const { userEntityRef } = getIdentity(request);\n const conversation_id = request.params.conversation_id;\n\n const requestBody = JSON.stringify(request.body);\n const userQueryParam = `user_id=${encodeURIComponent(userEntityRef)}`;\n const fetchResponse = await fetch(\n `${lcsBaseUrl}/v2/conversations/${conversation_id}?${userQueryParam}`,\n {\n method: 'PUT',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: requestBody,\n },\n );\n if (!fetchResponse.ok) {\n await handleLCSFetchError(\n fetchResponse,\n logger,\n 'updating conversation',\n response,\n );\n return;\n }\n\n const data = await fetchResponse.json();\n response.status(fetchResponse.status).json(data);\n } catch (error) {\n const errormsg = `Error while updating topic summary: ${error}`;\n logger.error(errormsg);\n response.status(500).json({ error: errormsg });\n }\n },\n );\n\n router.post(\n '/v1/validate-model-vision',\n generalRateLimiter,\n requirePermission(iaChatUsePermission),\n async (request, response) => {\n const { model, provider } = request.body;\n\n if (\n typeof model !== 'string' ||\n !model.trim() ||\n typeof provider !== 'string' ||\n !provider.trim()\n ) {\n response.status(400).json({ error: 'model and provider are required' });\n return;\n }\n\n const cacheKey = `${provider}/${model}`;\n\n try {\n logger.info(`Vision validation requested for model: ${cacheKey}`);\n\n if (ModelCapabilitiesCache.has(cacheKey)) {\n const cached = ModelCapabilitiesCache.get(cacheKey)!;\n logger.info(`Cache hit for ${cacheKey}: ${cached}`);\n response.json({ model, provider, supportsVision: cached });\n return;\n }\n\n const testJpeg = `data:image/jpeg;base64,${TEST_VISION_JPEG}`;\n const testResponse = await fetch(`${lcsBaseUrl}/v1/responses`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n model: cacheKey,\n input: [\n {\n type: 'message',\n role: 'user',\n content: [\n {\n type: 'input_image',\n image_url: testJpeg,\n detail: 'low',\n },\n {\n type: 'input_text',\n text: 'hi, respond with hi.',\n },\n ],\n },\n ],\n tool_choice: 'none',\n temperature: 0,\n store: false,\n stream: false,\n }),\n });\n\n if (testResponse.ok) {\n ModelCapabilitiesCache.set(cacheKey, true);\n response.json({ model, provider, supportsVision: true });\n }\n } catch (error) {\n logger.error(`Vision test error for ${cacheKey}:`, error);\n response.status(502).json({\n error:\n 'Unable to verify vision support for model — upstream unreachable',\n model,\n provider,\n });\n }\n },\n );\n\n router.use((_request, response) => {\n response.status(404).json({ error: 'Requested path is not available' });\n });\n\n const middleware = MiddlewareFactory.create({ logger, config });\n\n router.use(middleware.error());\n return router;\n}\n"],"names":["Router","express","DEFAULT_LIGHTSPEED_SERVICE_PORT","DEFAULT_LIGHTSPEED_SERVICE_HOST","createProxyMiddleware","rewriteProxyPath","VectorStoresOperator","createTokenEncryptor","McpUserSettingsStore","McpServerValidator","createPermissionIntegrationRouter","iaPermissions","createIdentityMiddleware","userPermissionAuthorization","createPermissionMiddleware","createRateLimitMiddleware","iaMcpUsePermission","getIdentity","iaMcpManagePermission","iaNotebooksUsePermission","NotAllowedError","iaChatAccessPermission","iaChatManagePermission","iaChatUsePermission","iaSkillsAccessPermission","handleLCSFetchError","EXPRESS_JSON_BODY_LIMIT","validateCompletionsRequest","validateAttachmentsForModel","Readable","ModelCapabilitiesCache","TEST_VISION_JPEG","MiddlewareFactory"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@red-hat-developer-hub/backstage-plugin-intelligent-assistant-backend",
3
- "version": "3.2.0",
3
+ "version": "4.1.0",
4
4
  "main": "./dist/index.cjs.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "license": "Apache-2.0",
@@ -56,18 +56,14 @@
56
56
  "@backstage/errors": "^1.3.1",
57
57
  "@backstage/plugin-permission-common": "^0.9.9",
58
58
  "@backstage/plugin-permission-node": "^0.11.1",
59
- "@langchain/core": "^0.3.80",
60
- "@langchain/openai": "^0.6.0",
61
- "@red-hat-developer-hub/backstage-plugin-intelligent-assistant-common": "^3.2.0",
59
+ "@red-hat-developer-hub/backstage-plugin-intelligent-assistant-common": "^4.1.0",
62
60
  "express": "^4.21.1",
63
61
  "express-rate-limit": "^8.2.2",
64
62
  "form-data": "^4.0.6",
65
- "htmlparser2": "^9.1.0",
66
63
  "http-proxy-middleware": "^3.0.7",
67
- "js-yaml": "^4.1.1",
68
64
  "knex": "^3.1.0",
69
- "multer": "^2.2.0",
70
- "pdfjs-dist": "^4.10.38"
65
+ "markitdown-ts": "^0.0.10",
66
+ "multer": "^2.2.0"
71
67
  },
72
68
  "devDependencies": {
73
69
  "@backstage/backend-test-utils": "^1.11.4",
@@ -75,16 +71,12 @@
75
71
  "@ianvs/prettier-plugin-sort-imports": "^4.4.0",
76
72
  "@spotify/prettier-config": "^15.0.0",
77
73
  "@types/express": "4.17.25",
78
- "@types/js-yaml": "^4",
79
74
  "@types/multer": "^1.4.12",
80
75
  "@types/supertest": "2.0.16",
81
76
  "msw": "2.14.6",
82
77
  "prettier": "3.9.6",
83
78
  "supertest": "6.3.4"
84
79
  },
85
- "resolutions": {
86
- "langsmith": "^0.7.0"
87
- },
88
80
  "files": [
89
81
  "dist",
90
82
  "config.d.ts",
@@ -1,139 +0,0 @@
1
- 'use strict';
2
-
3
- var errors = require('@backstage/errors');
4
- var yaml = require('js-yaml');
5
- var pdfjsLib = require('pdfjs-dist');
6
- var stream = require('stream');
7
- var constant = require('../../constant.cjs.js');
8
-
9
- function _interopNamespaceCompat(e) {
10
- if (e && typeof e === 'object' && 'default' in e) return e;
11
- var n = Object.create(null);
12
- if (e) {
13
- Object.keys(e).forEach(function (k) {
14
- if (k !== 'default') {
15
- var d = Object.getOwnPropertyDescriptor(e, k);
16
- Object.defineProperty(n, k, d.get ? d : {
17
- enumerable: true,
18
- get: function () { return e[k]; }
19
- });
20
- }
21
- });
22
- }
23
- n.default = e;
24
- return Object.freeze(n);
25
- }
26
-
27
- var yaml__namespace = /*#__PURE__*/_interopNamespaceCompat(yaml);
28
- var pdfjsLib__namespace = /*#__PURE__*/_interopNamespaceCompat(pdfjsLib);
29
-
30
- function parseTextFile(buffer, fileName, fileType) {
31
- const content = buffer.toString("utf-8");
32
- return {
33
- content,
34
- metadata: {
35
- fileName,
36
- fileType,
37
- parseTimestamp: (/* @__PURE__ */ new Date()).toISOString()
38
- }
39
- };
40
- }
41
- function parseJSONFile(buffer, fileName, fileType) {
42
- try {
43
- const content = buffer.toString("utf-8");
44
- JSON.parse(content);
45
- return {
46
- content,
47
- metadata: {
48
- fileName,
49
- fileType,
50
- parseTimestamp: (/* @__PURE__ */ new Date()).toISOString()
51
- }
52
- };
53
- } catch (error) {
54
- throw new errors.InputError(`Invalid JSON file: ${error}`);
55
- }
56
- }
57
- function parseYAMLFile(buffer, fileName, fileType) {
58
- try {
59
- const content = buffer.toString("utf-8");
60
- yaml__namespace.load(content);
61
- return {
62
- content,
63
- metadata: {
64
- fileName,
65
- fileType,
66
- parseTimestamp: (/* @__PURE__ */ new Date()).toISOString()
67
- }
68
- };
69
- } catch (error) {
70
- throw new errors.InputError(`Invalid YAML file: ${error}`);
71
- }
72
- }
73
- async function parsePDFFile(buffer, fileName, fileType) {
74
- try {
75
- const loadingTask = pdfjsLib__namespace.getDocument({
76
- data: new Uint8Array(buffer),
77
- useSystemFonts: true
78
- });
79
- const pdf = await loadingTask.promise;
80
- const textParts = [];
81
- for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
82
- const page = await pdf.getPage(pageNum);
83
- const textContent = await page.getTextContent();
84
- const pageText = textContent.items.map((item) => {
85
- if ("str" in item) {
86
- return item.str;
87
- }
88
- return "";
89
- }).filter((str) => str.trim().length > 0).join(" ");
90
- if (pageText.trim().length > 0) {
91
- textParts.push(`--- Page ${pageNum} ---
92
- ${pageText}`);
93
- }
94
- }
95
- const content = textParts.join("\n\n");
96
- return {
97
- content,
98
- metadata: {
99
- fileName,
100
- fileType,
101
- pageCount: pdf.numPages,
102
- parseTimestamp: (/* @__PURE__ */ new Date()).toISOString()
103
- }
104
- };
105
- } catch (error) {
106
- throw new errors.InputError(`Error parsing PDF: ${error}`);
107
- }
108
- }
109
- async function parseFile(buffer, fileName, fileType) {
110
- const normalizedType = fileType.toLowerCase().replace(/^\./, "");
111
- switch (normalizedType) {
112
- case constant.SupportedFileType.MARKDOWN:
113
- case constant.SupportedFileType.TEXT:
114
- case constant.SupportedFileType.LOG:
115
- return parseTextFile(buffer, fileName, fileType);
116
- case constant.SupportedFileType.JSON:
117
- return parseJSONFile(buffer, fileName, fileType);
118
- case constant.SupportedFileType.YAML:
119
- case constant.SupportedFileType.YML:
120
- return parseYAMLFile(buffer, fileName, fileType);
121
- case constant.SupportedFileType.PDF:
122
- return parsePDFFile(buffer, fileName, fileType);
123
- default:
124
- throw new errors.InputError(`Unsupported file type: ${fileType}`);
125
- }
126
- }
127
- async function toFile(buffer, filename, options) {
128
- const stream$1 = stream.Readable.from(buffer);
129
- return {
130
- name: filename,
131
- stream: stream$1,
132
- buffer,
133
- type: options?.type || "application/octet-stream"
134
- };
135
- }
136
-
137
- exports.parseFile = parseFile;
138
- exports.toFile = toFile;
139
- //# sourceMappingURL=fileParser.cjs.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"fileParser.cjs.js","sources":["../../../../src/service/notebooks/documents/fileParser.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { InputError } from '@backstage/errors';\n\nimport * as yaml from 'js-yaml';\nimport * as pdfjsLib from 'pdfjs-dist';\n\nimport { Readable } from 'stream';\n\nimport { SupportedFileType } from '../../constant';\n\nexport interface ParsedDocument {\n content: string;\n metadata: {\n fileName: string;\n fileType: string;\n pageCount?: number;\n parseTimestamp: string;\n };\n}\n\n/**\n * Parse text-based files (md, txt, log)\n */\nfunction parseTextFile(\n buffer: Buffer,\n fileName: string,\n fileType: string,\n): ParsedDocument {\n const content = buffer.toString('utf-8');\n\n return {\n content,\n metadata: {\n fileName,\n fileType,\n parseTimestamp: new Date().toISOString(),\n },\n };\n}\n\n/**\n * Parse JSON files\n */\nfunction parseJSONFile(\n buffer: Buffer,\n fileName: string,\n fileType: string,\n): ParsedDocument {\n try {\n const content = buffer.toString('utf-8');\n // Validate JSON but keep original formatting\n JSON.parse(content);\n\n return {\n content,\n metadata: {\n fileName,\n fileType,\n parseTimestamp: new Date().toISOString(),\n },\n };\n } catch (error) {\n throw new InputError(`Invalid JSON file: ${error}`);\n }\n}\n\n/**\n * Parse YAML files\n */\nfunction parseYAMLFile(\n buffer: Buffer,\n fileName: string,\n fileType: string,\n): ParsedDocument {\n try {\n const content = buffer.toString('utf-8');\n // Validate YAML but keep original formatting and comments\n yaml.load(content);\n\n return {\n content,\n metadata: {\n fileName,\n fileType,\n parseTimestamp: new Date().toISOString(),\n },\n };\n } catch (error) {\n throw new InputError(`Invalid YAML file: ${error}`);\n }\n}\n\n/**\n * Parse PDF files\n * Extracts text content from PDF using PDF.js\n */\nasync function parsePDFFile(\n buffer: Buffer,\n fileName: string,\n fileType: string,\n): Promise<ParsedDocument> {\n try {\n const loadingTask = pdfjsLib.getDocument({\n data: new Uint8Array(buffer),\n useSystemFonts: true,\n });\n\n const pdf = await loadingTask.promise;\n const textParts: string[] = [];\n\n // Extract text from each page\n for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {\n const page = await pdf.getPage(pageNum);\n const textContent = await page.getTextContent();\n\n const pageText = textContent.items\n .map((item: any) => {\n if ('str' in item) {\n return item.str;\n }\n return '';\n })\n .filter((str: string) => str.trim().length > 0)\n .join(' ');\n\n if (pageText.trim().length > 0) {\n textParts.push(`--- Page ${pageNum} ---\\n${pageText}`);\n }\n }\n\n const content = textParts.join('\\n\\n');\n\n return {\n content,\n metadata: {\n fileName,\n fileType,\n pageCount: pdf.numPages,\n parseTimestamp: new Date().toISOString(),\n },\n };\n } catch (error) {\n throw new InputError(`Error parsing PDF: ${error}`);\n }\n}\n\n/**\n * Parse file based on its type\n * @param buffer - File buffer\n * @param fileName - File name\n * @param fileType - File type (md, txt, pdf, json, yaml, yml, log)\n * @returns Parsed document with content and metadata\n */\nexport async function parseFile(\n buffer: Buffer,\n fileName: string,\n fileType: string,\n): Promise<ParsedDocument> {\n // Normalize file type: lowercase and remove leading dot\n const normalizedType = fileType.toLowerCase().replace(/^\\./, '');\n\n switch (normalizedType) {\n case SupportedFileType.MARKDOWN:\n case SupportedFileType.TEXT:\n case SupportedFileType.LOG:\n return parseTextFile(buffer, fileName, fileType);\n\n case SupportedFileType.JSON:\n return parseJSONFile(buffer, fileName, fileType);\n\n case SupportedFileType.YAML:\n case SupportedFileType.YML:\n return parseYAMLFile(buffer, fileName, fileType);\n\n case SupportedFileType.PDF:\n return parsePDFFile(buffer, fileName, fileType);\n\n default:\n throw new InputError(`Unsupported file type: ${fileType}`);\n }\n}\n\n/**\n * File-like object interface matching what toFile() returns\n */\nexport interface FileObject {\n name: string;\n stream: Readable;\n buffer: Buffer;\n type: string;\n}\n\n/**\n * Convert Buffer to File-like object for upload\n */\nexport async function toFile(\n buffer: Buffer,\n filename: string,\n options?: { type?: string },\n): Promise<FileObject> {\n const stream = Readable.from(buffer);\n\n return {\n name: filename,\n stream,\n buffer,\n type: options?.type || 'application/octet-stream',\n };\n}\n"],"names":["InputError","yaml","pdfjsLib","SupportedFileType","stream","Readable"],"mappings":"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"}