@arabold/docs-mcp-server 2.0.4 → 2.1.1
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/README.md +57 -2
- package/db/migrations/012-add-source-content-type.sql +11 -0
- package/dist/assets/main.css +1 -1
- package/dist/assets/main.js +673 -630
- package/dist/assets/main.js.map +1 -1
- package/dist/index.js +7 -18952
- package/dist/index.js.map +1 -1
- package/dist/logger-CLtABTNb.js +99 -0
- package/dist/logger-CLtABTNb.js.map +1 -0
- package/dist/main-ntnRQ8Za.js +18182 -0
- package/dist/main-ntnRQ8Za.js.map +1 -0
- package/dist/utils-CZz1DsHw.js +1063 -0
- package/dist/utils-CZz1DsHw.js.map +1 -0
- package/package.json +48 -45
- package/public/assets/main.css +1 -1
- package/public/assets/main.js +673 -630
- package/public/assets/main.js.map +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils-CZz1DsHw.js","sources":["../src/utils/paths.ts","../src/telemetry/TelemetryConfig.ts","../src/events/types.ts","../src/pipeline/types.ts","../src/telemetry/postHogClient.ts","../src/telemetry/telemetry.ts","../src/telemetry/TelemetryService.ts","../src/events/EventBusService.ts","../src/store/embeddings/EmbeddingConfig.ts","../src/cli/utils.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport envPaths from \"env-paths\";\nimport { logger } from \"./logger\";\n\nlet projectRoot: string | null = null;\n\n/**\n * Reset the cached project root. For testing purposes only.\n * @internal\n */\nexport function _resetProjectRootCache(): void {\n projectRoot = null;\n}\n\n/**\n * Finds the project root directory by searching upwards from the current file\n * for a directory containing 'package.json'. Caches the result.\n *\n * @returns {string} The absolute path to the project root.\n * @throws {Error} If package.json cannot be found.\n */\nexport function getProjectRoot(): string {\n // Return cached result if available\n if (projectRoot) {\n return projectRoot;\n }\n\n // Start from the directory of the current module\n const currentFilePath = fileURLToPath(import.meta.url);\n let currentDir = path.dirname(currentFilePath);\n\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const packageJsonPath = path.join(currentDir, \"package.json\");\n if (fs.existsSync(packageJsonPath)) {\n // Cache the found project root directory\n projectRoot = currentDir;\n return currentDir;\n }\n\n const parentDir = path.dirname(currentDir);\n // Check if we have reached the filesystem root\n if (parentDir === currentDir) {\n throw new Error(\"Could not find project root containing package.json.\");\n }\n currentDir = parentDir;\n }\n}\n\n/**\n * Resolves the data storage path using the following priority:\n * 1. Provided storePath parameter\n * 2. Legacy .store directory in project root (if exists)\n * 3. Standard system data directory using env-paths\n *\n * @param storePath Optional custom storage path\n * @returns Resolved absolute path for data storage\n */\nexport function resolveStorePath(storePath?: string): string {\n let dbDir: string;\n\n // 1. Check storePath parameter\n if (storePath) {\n dbDir = path.resolve(storePath);\n } else {\n // 2. Check Old Local Path\n const projectRoot = getProjectRoot();\n const oldDbDir = path.join(projectRoot, \".store\");\n const oldDbPath = path.join(oldDbDir, \"documents.db\");\n const oldDbExists = fs.existsSync(oldDbPath); // Check file existence specifically\n\n if (oldDbExists) {\n dbDir = oldDbDir;\n } else {\n // 3. Use Standard Path\n const standardPaths = envPaths(\"docs-mcp-server\", { suffix: \"\" });\n dbDir = standardPaths.data;\n }\n }\n\n // Ensure the chosen directory exists\n try {\n fs.mkdirSync(dbDir, { recursive: true });\n } catch (error) {\n // Log potential error during directory creation but proceed\n // The DocumentStore constructor might handle DB file creation errors\n logger.warn(`⚠️ Failed to create database directory ${dbDir}: ${error}`);\n }\n\n return dbDir;\n}\n","/**\n * Telemetry configuration management for enabling/disabling analytics collection.\n * Handles CLI flags, environment variables, and default settings.\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { resolveStorePath } from \"../utils/paths\";\n\nexport class TelemetryConfig {\n private static instance?: TelemetryConfig;\n private enabled: boolean = true; // Default to enabled\n\n private constructor() {\n // Private constructor for singleton pattern\n }\n\n isEnabled(): boolean {\n return this.enabled;\n }\n\n setEnabled(enabled: boolean): void {\n this.enabled = enabled;\n }\n\n static getInstance(): TelemetryConfig {\n if (!TelemetryConfig.instance) {\n TelemetryConfig.instance = new TelemetryConfig();\n }\n return TelemetryConfig.instance;\n }\n}\n\n/**\n * Generate or retrieve a persistent installation identifier.\n * Creates a UUID and stores it in a file in the user data directory.\n * Supports custom store path override for Docker deployments.\n * This ensures truly unique identification that persists across runs.\n */\nexport function generateInstallationId(storePath?: string): string {\n try {\n // Use centralized path resolution logic\n const dataDir = resolveStorePath(storePath);\n const installationIdPath = path.join(dataDir, \"installation.id\");\n\n // Try to read existing installation ID\n if (fs.existsSync(installationIdPath)) {\n const existingId = fs.readFileSync(installationIdPath, \"utf8\").trim();\n if (existingId) {\n return existingId;\n }\n }\n\n // Generate new UUID and store it\n const newId = randomUUID();\n\n // Ensure directory exists\n fs.mkdirSync(dataDir, { recursive: true });\n\n // Write the installation ID\n fs.writeFileSync(installationIdPath, newId, \"utf8\");\n\n return newId;\n } catch {\n // Fallback to a session-only UUID if file operations fail\n // This ensures analytics always has a valid distinct ID\n return randomUUID();\n }\n}\n\n/**\n * Check if telemetry should be enabled based on environment and CLI flags.\n */\nexport function shouldEnableTelemetry(): boolean {\n return TelemetryConfig.getInstance().isEnabled();\n}\n","/**\n * Centralized event type definitions for the event bus system.\n * This serves as the single source of truth for all events in the application.\n */\n\nimport type { PipelineJob } from \"../pipeline/types\";\nimport type { ScraperProgressEvent } from \"../scraper/types\";\n\n/**\n * Event type enum used by the EventBusService.\n * These are the internal event identifiers.\n */\nexport enum EventType {\n JOB_STATUS_CHANGE = \"JOB_STATUS_CHANGE\",\n JOB_PROGRESS = \"JOB_PROGRESS\",\n LIBRARY_CHANGE = \"LIBRARY_CHANGE\",\n JOB_LIST_CHANGE = \"JOB_LIST_CHANGE\",\n}\n\n/**\n * Server-side event names used in SSE messages.\n * These match the event names expected by the frontend EventClient.\n */\nexport const ServerEventName = {\n [EventType.JOB_STATUS_CHANGE]: \"job-status-change\",\n [EventType.JOB_PROGRESS]: \"job-progress\",\n [EventType.LIBRARY_CHANGE]: \"library-change\",\n [EventType.JOB_LIST_CHANGE]: \"job-list-change\",\n} as const;\n\n/**\n * Type-safe mapping of event types to their payload structures.\n */\nexport interface EventPayloads {\n [EventType.JOB_STATUS_CHANGE]: PipelineJob;\n [EventType.JOB_PROGRESS]: {\n job: PipelineJob;\n progress: ScraperProgressEvent;\n };\n [EventType.LIBRARY_CHANGE]: undefined;\n [EventType.JOB_LIST_CHANGE]: undefined;\n}\n\n/**\n * Type-safe event listener callback.\n */\nexport type EventListener<T extends EventType> = (payload: EventPayloads[T]) => void;\n\n/**\n * SSE message payload types that are sent to the frontend.\n * These define the exact structure of data transmitted over the wire.\n */\nexport interface SseEventPayloads {\n \"job-status-change\": {\n id: string;\n library: string;\n version: string | null;\n status: string;\n error: { message: string } | null;\n createdAt: string;\n startedAt: string | null;\n finishedAt: string | null;\n sourceUrl: string | null;\n };\n \"job-progress\": {\n id: string;\n library: string;\n version: string | null;\n progress: {\n pagesScraped: number;\n totalPages: number;\n totalDiscovered: number;\n currentUrl: string;\n depth: number;\n maxDepth: number;\n };\n };\n \"library-change\": Record<string, never>;\n \"job-list-change\": Record<string, never>;\n}\n\n/**\n * Union type of all SSE event names.\n */\nexport type SseEventName = keyof SseEventPayloads;\n","import type {\n ScrapeResult,\n ScraperOptions,\n ScraperProgressEvent,\n} from \"../scraper/types\";\nimport type { VersionStatus } from \"../store/types\";\n\n/**\n * Represents the possible states of a pipeline job.\n */\nexport enum PipelineJobStatus {\n QUEUED = \"queued\",\n RUNNING = \"running\",\n COMPLETED = \"completed\",\n FAILED = \"failed\",\n CANCELLING = \"cancelling\",\n CANCELLED = \"cancelled\",\n}\n\n/**\n * Public interface for pipeline jobs exposed through API boundaries.\n * Contains only serializable fields suitable for JSON transport.\n */\nexport interface PipelineJob {\n /** Unique identifier for the job. */\n id: string;\n /** The library name associated with the job. */\n library: string;\n /** The library version associated with the job. */\n version: string | null;\n /** Current pipeline status of the job. */\n status: PipelineJobStatus;\n /** Detailed progress information. */\n progress: ScraperProgressEvent | null;\n /** Error information if the job failed. */\n error: { message: string } | null;\n /** Timestamp when the job was created. */\n createdAt: Date;\n /** Timestamp when the job started running. */\n startedAt: Date | null;\n /** Timestamp when the job finished (completed, failed, or cancelled). */\n finishedAt: Date | null;\n /** Database version ID for direct updates. */\n versionId?: number;\n /** Database version status (authoritative). */\n versionStatus?: VersionStatus;\n /** Current number of pages processed. */\n progressPages?: number;\n /** Maximum number of pages to process. */\n progressMaxPages?: number;\n /** Database error message (more detailed than Error object). */\n errorMessage?: string | null;\n /** Last update timestamp from database. */\n updatedAt?: Date;\n /** Original scraping URL. */\n sourceUrl: string | null;\n /** Stored scraper options for reproducibility. */\n scraperOptions: ScraperOptions | null;\n}\n\n/**\n * Internal pipeline job representation used within PipelineManager.\n * Contains non-serializable fields for job management and control.\n *\n * Note: scraperOptions is required (non-nullable) for internal jobs as they\n * always have complete runtime configuration available.\n */\nexport interface InternalPipelineJob\n extends Omit<PipelineJob, \"version\" | \"error\" | \"scraperOptions\"> {\n /** The library version associated with the job (internal uses string). */\n version: string;\n /** Error object if the job failed. */\n error: Error | null;\n /** Complete scraper options with runtime configuration. */\n scraperOptions: ScraperOptions;\n /** AbortController to signal cancellation. */\n abortController: AbortController;\n /** Promise that resolves/rejects when the job finishes. */\n completionPromise: Promise<void>;\n /** Resolver function for the completion promise. */\n resolveCompletion: () => void;\n /** Rejector function for the completion promise. */\n rejectCompletion: (reason?: unknown) => void;\n}\n\n/**\n * Defines the structure for callback functions used with the PipelineManager.\n * Allows external components to hook into job lifecycle events.\n * All callbacks receive the public PipelineJob representation to maintain\n * clean separation between internal implementation and external API.\n */\nexport interface PipelineManagerCallbacks {\n /** Callback triggered when a job's status changes. */\n onJobStatusChange?: (job: PipelineJob) => Promise<void>;\n /** Callback triggered when a job makes progress. */\n onJobProgress?: (job: PipelineJob, progress: ScraperProgressEvent) => Promise<void>;\n /** Callback triggered when a job encounters an error during processing (e.g., storing a doc). */\n onJobError?: (job: PipelineJob, error: Error, page?: ScrapeResult) => Promise<void>;\n}\n","/**\n * PostHog client wrapper for telemetry events.\n * Handles PostHog SDK integration and event capture with privacy-first configuration.\n * Automatically converts camelCase property names to snake_case for PostHog compatibility.\n */\n\nimport { PostHog } from \"posthog-node\";\nimport { logger } from \"../utils/logger\";\n\n/**\n * Convert camelCase string to snake_case\n * Specifically designed for PostHog property name conversion\n */\nfunction camelToSnakeCase(str: string): string {\n return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);\n}\n\n/**\n * Recursively convert object keys from camelCase to snake_case\n * Handles nested objects and arrays while preserving values\n */\nfunction convertPropertiesToSnakeCase(\n obj: Record<string, unknown>,\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(obj)) {\n const snakeKey = camelToSnakeCase(key);\n\n if (\n value &&\n typeof value === \"object\" &&\n !Array.isArray(value) &&\n !(value instanceof Date)\n ) {\n // Recursively convert nested objects\n result[snakeKey] = convertPropertiesToSnakeCase(value as Record<string, unknown>);\n } else if (Array.isArray(value)) {\n // Handle arrays - convert elements if they are objects\n result[snakeKey] = value.map((item) =>\n item && typeof item === \"object\" && !(item instanceof Date)\n ? convertPropertiesToSnakeCase(item as Record<string, unknown>)\n : item,\n );\n } else {\n // Primitive values, dates, and null/undefined - keep as-is\n result[snakeKey] = value;\n }\n }\n\n return result;\n}\n\n/**\n * Add PostHog standard properties and remove duplicates\n * Maps our properties to PostHog's expected property names\n */\nfunction addPostHogStandardProperties(\n properties: Record<string, unknown>,\n): Record<string, unknown> {\n const result = { ...properties };\n\n // Add PostHog standard session properties\n if (properties.sessionId) {\n result.$session_id = properties.sessionId;\n delete result.sessionId; // Remove duplicate\n }\n\n if (properties.startTime) {\n result.$start_timestamp = (properties.startTime as Date).toISOString();\n delete result.startTime; // Remove duplicate\n }\n\n // Add PostHog standard app properties\n if (properties.appVersion) {\n result.$app_version = properties.appVersion;\n delete result.appVersion; // Remove duplicate\n }\n\n return result;\n}\n\n/**\n * PostHog client wrapper for telemetry events\n */\nexport class PostHogClient {\n private client?: PostHog;\n private enabled: boolean;\n\n // PostHog configuration\n private static readonly CONFIG = {\n host: \"https://app.posthog.com\",\n\n // Performance optimizations\n flushAt: 20, // Batch size - send after 20 events\n flushInterval: 10000, // 10 seconds - send after time\n\n // Privacy settings\n disableGeoip: true, // Don't collect IP geolocation\n disableSessionRecording: true, // Never record sessions\n disableSurveys: true, // No user surveys\n\n // Data handling\n persistence: \"memory\" as const, // No disk persistence for privacy\n };\n\n constructor(enabled: boolean) {\n this.enabled = enabled;\n\n if (!this.enabled) {\n return; // Early return if analytics is disabled\n }\n\n if (!__POSTHOG_API_KEY__) {\n logger.debug(\"PostHog API key not provided\");\n this.enabled = false;\n return;\n }\n\n try {\n this.client = new PostHog(__POSTHOG_API_KEY__, {\n host: PostHogClient.CONFIG.host,\n flushAt: PostHogClient.CONFIG.flushAt,\n flushInterval: PostHogClient.CONFIG.flushInterval,\n disableGeoip: PostHogClient.CONFIG.disableGeoip,\n });\n logger.debug(\"PostHog client initialized\");\n } catch (error) {\n logger.debug(\n `PostHog initialization failed: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n this.enabled = false;\n }\n }\n\n /**\n * Send event to PostHog\n */\n capture(distinctId: string, event: string, properties: Record<string, unknown>): void {\n if (!this.enabled || !this.client) return;\n\n try {\n // Add PostHog standard properties and remove duplicates\n const enhancedProperties = addPostHogStandardProperties(properties);\n\n // Convert camelCase properties to snake_case for PostHog\n const snakeCaseProperties = convertPropertiesToSnakeCase(enhancedProperties);\n\n this.client.capture({\n distinctId,\n event,\n properties: snakeCaseProperties,\n });\n logger.debug(`PostHog event captured: ${event}`);\n } catch (error) {\n logger.debug(\n `PostHog capture error: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n }\n\n /**\n * Capture exception using PostHog's native error tracking\n */\n captureException(\n distinctId: string,\n error: Error,\n properties?: Record<string, unknown>,\n ): void {\n if (!this.enabled || !this.client) return;\n\n try {\n // Add PostHog standard properties and remove duplicates\n const enhancedProperties = addPostHogStandardProperties(properties || {});\n\n // Convert camelCase properties to snake_case for PostHog\n const snakeCaseProperties = convertPropertiesToSnakeCase(enhancedProperties);\n\n this.client.captureException({\n error,\n distinctId,\n properties: snakeCaseProperties,\n });\n logger.debug(`PostHog exception captured: ${error.constructor.name}`);\n } catch (captureError) {\n logger.debug(\n `PostHog captureException error: ${captureError instanceof Error ? captureError.message : \"Unknown error\"}`,\n );\n }\n }\n\n /**\n * Graceful shutdown with event flushing\n */\n async shutdown(): Promise<void> {\n if (this.client) {\n try {\n await this.client.shutdown();\n logger.debug(\"PostHog client shutdown complete\");\n } catch (error) {\n logger.debug(\n `PostHog shutdown error: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n }\n }\n\n /**\n * Check if client is enabled and ready\n */\n isEnabled(): boolean {\n return this.enabled && !!this.client;\n }\n}\n","/**\n * Telemtry wrapper for privacy-first telemetry using PostHog.\n * Provides global context and automatic data sanitization.\n *\n * Architecture:\n * - PostHogClient: Handles PostHog SDK integration and event capture\n * - Telemtry: High-level coordinator providing public API with global context\n */\n\nimport { logger } from \"../utils/logger\";\nimport type { TelemetryEventPropertiesMap } from \"./eventTypes\";\nimport { PostHogClient } from \"./postHogClient\";\nimport { generateInstallationId, TelemetryConfig } from \"./TelemetryConfig\";\n\n/**\n * Event types for structured telemetry tracking\n */\nexport enum TelemetryEvent {\n APP_STARTED = \"app_started\",\n APP_SHUTDOWN = \"app_shutdown\",\n CLI_COMMAND = \"cli_command\",\n TOOL_USED = \"tool_used\",\n PIPELINE_JOB_STARTED = \"pipeline_job_started\",\n PIPELINE_JOB_COMPLETED = \"pipeline_job_completed\",\n PIPELINE_JOB_FAILED = \"pipeline_job_failed\",\n}\n\n/**\n * Main telemetry class providing privacy-first telemetry\n */\nexport class Telemetry {\n private postHogClient: PostHogClient;\n private enabled: boolean;\n private distinctId: string;\n private globalContext: Record<string, unknown> = {};\n\n /**\n * Create a new Telemetry instance with proper initialization\n * This is the recommended way to create Telemetry instances\n */\n static create(): Telemetry {\n const config = TelemetryConfig.getInstance();\n\n // Single determination point for enabled status\n const shouldEnable = config.isEnabled() && !!__POSTHOG_API_KEY__;\n\n const telemetry = new Telemetry(shouldEnable);\n\n // Single log message after everything is initialized with better context\n if (telemetry.isEnabled()) {\n logger.debug(\"Telemetry enabled\");\n } else if (!config.isEnabled()) {\n logger.debug(\"Telemetry disabled (user preference)\");\n } else if (!__POSTHOG_API_KEY__) {\n logger.debug(\"Telemetry disabled (no API key configured)\");\n } else {\n logger.debug(\"Telemetry disabled\");\n }\n\n return telemetry;\n }\n\n /**\n * Private constructor - use Telemetry.create() instead\n */\n private constructor(enabled: boolean = true) {\n this.enabled = enabled;\n this.distinctId = generateInstallationId();\n this.postHogClient = new PostHogClient(this.enabled);\n }\n\n /**\n * Set global application context that will be included in all events\n */\n setGlobalContext(context: Record<string, unknown>): void {\n this.globalContext = { ...context };\n }\n\n /**\n * Get current global context\n */\n getGlobalContext(): Record<string, unknown> {\n return { ...this.globalContext };\n }\n\n /**\n * Track an event with automatic global context inclusion\n *\n * Type-safe overloads for specific events:\n */\n track<T extends keyof TelemetryEventPropertiesMap>(\n event: T,\n properties: TelemetryEventPropertiesMap[T],\n ): void;\n track(event: string, properties?: Record<string, unknown>): void;\n track(event: string, properties: Record<string, unknown> = {}): void {\n if (!this.enabled) return;\n\n // Merge global context and event properties with timestamp\n const enrichedProperties = {\n ...this.globalContext,\n ...properties,\n timestamp: new Date().toISOString(),\n };\n logger.debug(`Tracking event: ${event}`);\n this.postHogClient.capture(this.distinctId, event, enrichedProperties);\n }\n\n /**\n * Capture exception using PostHog's native error tracking with global context\n */\n captureException(\n error: Error | unknown,\n properties: Record<string, unknown> = {},\n ): void {\n if (!this.enabled) return;\n\n // Merge global context and error properties with timestamp\n const enrichedProperties = {\n ...this.globalContext,\n ...properties,\n timestamp: new Date().toISOString(),\n };\n logger.debug(\n `Capturing exception: ${error instanceof Error ? error.message : String(error)}`,\n );\n this.postHogClient.captureException(\n this.distinctId,\n error instanceof Error ? error : new Error(String(error)),\n enrichedProperties,\n );\n }\n\n /**\n * Graceful shutdown with event flushing\n */\n async shutdown(): Promise<void> {\n if (!this.enabled) return;\n\n await this.postHogClient.shutdown();\n }\n\n /**\n * Check if telemetry is enabled\n */\n isEnabled(): boolean {\n return this.enabled;\n }\n}\n\n/**\n * Global telemetry instance - initialized lazily\n */\nlet telemetryInstance: Telemetry | null = null;\n\n/**\n * Get the global telemetry instance, initializing it if needed\n */\nexport function getTelemetryInstance(): Telemetry {\n if (!telemetryInstance) {\n // Create a basic telemetry instance if not yet initialized\n telemetryInstance = Telemetry.create();\n }\n return telemetryInstance;\n}\n\n/**\n * Initialize telemetry system with proper configuration.\n * This should be called once at application startup.\n */\nexport function initTelemetry(options: { enabled: boolean; storePath?: string }): void {\n // Configure telemetry enabled state\n TelemetryConfig.getInstance().setEnabled(options.enabled);\n\n // Generate/retrieve installation ID with correct storePath\n generateInstallationId(options.storePath);\n\n // Create the telemetry instance with proper configuration (only once)\n telemetryInstance = Telemetry.create();\n}\n\n// Export a proxy object that always delegates to the current telemetry instance.\n// This ensures configuration changes (like disabling telemetry via initTelemetry)\n// are always reflected, avoiding stale cached state.\nexport const telemetry = new Proxy({} as Telemetry, {\n get(_target, prop) {\n const instance = getTelemetryInstance();\n const value = instance[prop as keyof Telemetry];\n\n // Bind methods to the instance to preserve 'this' context\n if (typeof value === \"function\") {\n return value.bind(instance);\n }\n return value;\n },\n});\n","/**\n * TelemetryService listens to events from the EventBusService and tracks them to analytics.\n * This decouples telemetry concerns from the PipelineManager, following the event-driven architecture.\n */\n\nimport type { EventBusService } from \"../events/EventBusService\";\nimport { EventType } from \"../events/types\";\nimport { type PipelineJob, PipelineJobStatus } from \"../pipeline/types\";\nimport type { ScraperProgressEvent } from \"../scraper/types\";\nimport { logger } from \"../utils/logger\";\nimport { TelemetryEvent, telemetry } from \"./telemetry\";\n\nexport class TelemetryService {\n private eventBus: EventBusService;\n private unsubscribers: (() => void)[] = [];\n\n constructor(eventBus: EventBusService) {\n this.eventBus = eventBus;\n this.setupEventListeners();\n }\n\n /**\n * Sets up event listeners for pipeline events.\n */\n private setupEventListeners(): void {\n // Listen to job status changes\n const unsubStatusChange = this.eventBus.on(\n EventType.JOB_STATUS_CHANGE,\n this.handleJobStatusChange.bind(this),\n );\n\n // Listen to job progress events for error tracking\n const unsubProgress = this.eventBus.on(\n EventType.JOB_PROGRESS,\n this.handleJobProgress.bind(this),\n );\n\n this.unsubscribers.push(unsubStatusChange, unsubProgress);\n\n logger.debug(\"TelemetryService initialized and listening to events\");\n }\n\n /**\n * Handles job status change events and tracks them to analytics.\n * Only tracks events for meaningful state transitions: started, completed, and failed.\n */\n private handleJobStatusChange(job: PipelineJob): void {\n const duration = job.startedAt ? Date.now() - job.startedAt.getTime() : null;\n const queueWaitTime =\n job.startedAt && job.createdAt\n ? job.startedAt.getTime() - job.createdAt.getTime()\n : null;\n\n switch (job.status) {\n case PipelineJobStatus.RUNNING:\n telemetry.track(TelemetryEvent.PIPELINE_JOB_STARTED, {\n jobId: job.id,\n library: job.library,\n hasVersion: !!job.version,\n maxPagesConfigured: job.progressMaxPages || 0,\n queueWaitTimeMs: queueWaitTime,\n });\n break;\n\n case PipelineJobStatus.COMPLETED:\n telemetry.track(TelemetryEvent.PIPELINE_JOB_COMPLETED, {\n jobId: job.id,\n library: job.library,\n durationMs: duration,\n pagesProcessed: job.progressPages || 0,\n maxPagesConfigured: job.progressMaxPages || 0,\n hasVersion: !!job.version,\n throughputPagesPerSecond:\n duration && job.progressPages\n ? Math.round((job.progressPages / duration) * 1000)\n : 0,\n });\n break;\n\n case PipelineJobStatus.FAILED:\n telemetry.track(TelemetryEvent.PIPELINE_JOB_FAILED, {\n jobId: job.id,\n library: job.library,\n durationMs: duration,\n pagesProcessed: job.progressPages || 0,\n maxPagesConfigured: job.progressMaxPages || 0,\n hasVersion: !!job.version,\n hasError: !!job.error,\n errorMessage: job.error?.message,\n });\n break;\n\n // Ignore queued, cancelling, and cancelled states - no telemetry needed\n default:\n break;\n }\n }\n\n /**\n * Handles job progress events. Currently a no-op but can be extended\n * for progress-specific telemetry tracking.\n */\n private handleJobProgress(_event: {\n job: PipelineJob;\n progress: ScraperProgressEvent;\n }): void {\n // Currently no telemetry needed for progress events\n // This handler is here for future extensibility\n }\n\n /**\n * Cleans up event listeners.\n */\n shutdown(): void {\n for (const unsubscribe of this.unsubscribers) {\n unsubscribe();\n }\n this.unsubscribers = [];\n logger.debug(\"TelemetryService shut down\");\n }\n}\n","/**\n * Central event bus service for application-wide event distribution.\n *\n * This service provides a pub/sub mechanism that can be used by any service\n * to emit and listen for events. Events emitted here can be:\n * - Consumed locally by in-process subscribers\n * - Broadcast to remote processes via tRPC subscriptions\n * - Forwarded to SSE clients via the web service\n *\n * This decouples event producers (like DocumentManagementService) from\n * consumers (like the Web UI), enabling a clean, scalable architecture.\n */\n\nimport EventEmitter from \"node:events\";\nimport { logger } from \"../utils/logger\";\nimport type { EventListener, EventPayloads, EventType } from \"./types\";\n\n/**\n * Central event bus for application-wide events.\n */\nexport class EventBusService {\n private emitter: EventEmitter;\n\n constructor() {\n this.emitter = new EventEmitter();\n // Increase max listeners to support multiple subscribers\n this.emitter.setMaxListeners(100);\n }\n\n /**\n * Emit an event to all subscribers.\n */\n emit<T extends EventType>(eventType: T, payload: EventPayloads[T]): void {\n logger.debug(`Event emitted: ${eventType}`);\n this.emitter.emit(eventType, payload);\n }\n\n /**\n * Subscribe to events of a specific type.\n * Returns an unsubscribe function.\n */\n on<T extends EventType>(eventType: T, listener: EventListener<T>): () => void {\n this.emitter.on(eventType, listener);\n return () => this.emitter.off(eventType, listener);\n }\n\n /**\n * Subscribe to events once (auto-unsubscribes after first event).\n */\n once<T extends EventType>(eventType: T, listener: EventListener<T>): void {\n this.emitter.once(eventType, listener);\n }\n\n /**\n * Remove a specific listener.\n */\n off<T extends EventType>(eventType: T, listener: EventListener<T>): void {\n this.emitter.off(eventType, listener);\n }\n\n /**\n * Remove all listeners for a specific event type, or all listeners if no type specified.\n */\n removeAllListeners(eventType?: EventType): void {\n if (eventType === undefined) {\n this.emitter.removeAllListeners();\n } else {\n this.emitter.removeAllListeners(eventType);\n }\n }\n\n /**\n * Get the count of listeners for a specific event type.\n */\n listenerCount(eventType: EventType): number {\n return this.emitter.listenerCount(eventType);\n }\n}\n","import { normalizeEnvValue } from \"../../utils/env\";\n\n/**\n * Shared embedding model configuration service.\n * Provides synchronous parsing of embedding model configuration and known dimensions lookup.\n * Eliminates code duplication between DocumentStore and telemetry systems.\n *\n * All model lookups are case-insensitive to handle variations in model name capitalization.\n * Uses class-based approach to avoid mutable global state and improve testability.\n */\n\n/**\n * Supported embedding model providers.\n */\nexport type EmbeddingProvider =\n | \"openai\"\n | \"vertex\"\n | \"gemini\"\n | \"aws\"\n | \"microsoft\"\n | \"sagemaker\";\n\n/**\n * Embedding model configuration parsed from environment variables.\n */\nexport interface EmbeddingModelConfig {\n /** The provider (e.g., \"openai\", \"gemini\") */\n provider: EmbeddingProvider;\n /** The model name (e.g., \"text-embedding-3-small\") */\n model: string;\n /** Known dimensions for this model, or null if unknown */\n dimensions: number | null;\n /** The full model specification string (e.g., \"openai:text-embedding-3-small\") */\n modelSpec: string;\n}\n\n/**\n * Embedding configuration manager that handles model parsing and dimension caching.\n * Encapsulates state to avoid global variable issues and improve testability.\n */\nexport class EmbeddingConfig {\n private static instance: EmbeddingConfig | null = null;\n\n /**\n * Get the singleton instance of EmbeddingConfig.\n * Creates the instance if it doesn't exist.\n */\n static getInstance(): EmbeddingConfig {\n if (EmbeddingConfig.instance === null) {\n EmbeddingConfig.instance = new EmbeddingConfig();\n }\n return EmbeddingConfig.instance;\n }\n\n /**\n * Reset the singleton instance (useful for testing).\n */\n static resetInstance(): void {\n EmbeddingConfig.instance = null;\n }\n /**\n * Known dimensions for common embedding models.\n * This avoids expensive API calls for dimension detection in telemetry.\n *\n * Note: The \"openai\" provider also supports OpenAI-compatible APIs like:\n * - Ollama (local models)\n * - LMStudio (local models)\n * - Any service implementing OpenAI's embedding API\n */\n private readonly knownModelDimensions: Record<string, number> = {\n // OpenAI models (also works with Ollama, LMStudio, and other OpenAI-compatible APIs)\n \"text-embedding-3-small\": 1536,\n \"text-embedding-3-large\": 3072,\n \"text-embedding-ada-002\": 1536,\n\n // Google Vertex AI models\n \"text-embedding-004\": 768,\n \"textembedding-gecko@003\": 768,\n \"textembedding-gecko@002\": 768,\n \"textembedding-gecko@001\": 768,\n\n // Google Gemini models (with MRL support)\n \"text-embedding-preview-0409\": 768,\n \"embedding-001\": 768,\n \"gemini-embedding-2-preview\": 3072,\n\n // AWS Bedrock models\n // Amazon Titan models\n \"amazon.titan-embed-text-v1\": 1536,\n \"amazon.titan-embed-text-v2:0\": 1024,\n \"amazon.titan-embed-image-v1\": 1024, // Image embedding model\n\n // Cohere models\n \"cohere.embed-english-v3\": 1024,\n \"cohere.embed-multilingual-v3\": 1024,\n\n // SageMaker models (hosted on AWS SageMaker)\n \"intfloat/multilingual-e5-large\": 1024,\n\n // Additional AWS models that might be supported\n // Note: Some of these might be placeholders - verify dimensions before use\n // \"amazon.nova-embed-multilingual-v1:0\": 4096, // Commented out as noted in source\n\n // MTEB Leaderboard models (source: https://huggingface.co/spaces/mteb/leaderboard)\n // Top performing models from Massive Text Embedding Benchmark\n \"sentence-transformers/all-MiniLM-L6-v2\": 384,\n \"gemini-embedding-001\": 3072,\n \"Qwen/Qwen3-Embedding-8B\": 4096,\n \"Qwen/Qwen3-Embedding-4B\": 2560,\n \"Qwen/Qwen3-Embedding-0.6B\": 1024,\n \"Linq-AI-Research/Linq-Embed-Mistral\": 4096,\n \"Alibaba-NLP/gte-Qwen2-7B-instruct\": 3584,\n \"intfloat/multilingual-e5-large-instruct\": 1024,\n \"Salesforce/SFR-Embedding-Mistral\": 4096,\n \"text-multilingual-embedding-002\": 768,\n \"GritLM/GritLM-7B\": 4096,\n \"GritLM/GritLM-8x7B\": 4096,\n \"intfloat/e5-mistral-7b-instruct\": 4096,\n \"Cohere/Cohere-embed-multilingual-v3.0\": 1024,\n \"Alibaba-NLP/gte-Qwen2-1.5B-instruct\": 8960,\n \"Lajavaness/bilingual-embedding-large\": 1024,\n \"Salesforce/SFR-Embedding-2_R\": 4096,\n \"NovaSearch/stella_en_1.5B_v5\": 8960,\n \"NovaSearch/jasper_en_vision_language_v1\": 8960,\n \"nvidia/NV-Embed-v2\": 4096,\n \"OrdalieTech/Solon-embeddings-large-0.1\": 1024,\n \"BAAI/bge-m3\": 1024,\n \"HIT-TMG/KaLM-embedding-multilingual-mini-v1\": 896,\n \"jinaai/jina-embeddings-v3\": 1024,\n \"Alibaba-NLP/gte-multilingual-base\": 768,\n \"Lajavaness/bilingual-embedding-base\": 768,\n \"HIT-TMG/KaLM-embedding-multilingual-mini-instruct-v1\": 896,\n \"nvidia/NV-Embed-v1\": 4096,\n \"Cohere/Cohere-embed-multilingual-light-v3.0\": 384,\n \"manu/bge-m3-custom-fr\": 1024,\n \"Lajavaness/bilingual-embedding-small\": 384,\n \"Snowflake/snowflake-arctic-embed-l-v2.0\": 1024,\n \"intfloat/multilingual-e5-base\": 768,\n \"voyage-3-lite\": 512,\n \"voyage-3\": 1024,\n \"intfloat/multilingual-e5-small\": 384,\n \"Alibaba-NLP/gte-Qwen1.5-7B-instruct\": 4096,\n \"Snowflake/snowflake-arctic-embed-m-v2.0\": 768,\n \"deepvk/USER-bge-m3\": 1024,\n \"Cohere/Cohere-embed-english-v3.0\": 1024,\n \"Omartificial-Intelligence-Space/Arabic-labse-Matryoshka\": 768,\n \"ibm-granite/granite-embedding-278m-multilingual\": 768,\n \"NovaSearch/stella_en_400M_v5\": 4096,\n \"omarelshehy/arabic-english-sts-matryoshka\": 1024,\n \"sentence-transformers/paraphrase-multilingual-mpnet-base-v2\": 768,\n \"Omartificial-Intelligence-Space/Arabic-all-nli-triplet-Matryoshka\": 768,\n \"Haon-Chen/speed-embedding-7b-instruct\": 4096,\n \"sentence-transformers/LaBSE\": 768,\n \"WhereIsAI/UAE-Large-V1\": 1024,\n \"ibm-granite/granite-embedding-107m-multilingual\": 384,\n \"mixedbread-ai/mxbai-embed-large-v1\": 1024,\n \"intfloat/e5-large-v2\": 1024,\n \"avsolatorio/GIST-large-Embedding-v0\": 1024,\n \"sdadas/mmlw-e5-large\": 1024,\n \"nomic-ai/nomic-embed-text-v1\": 768,\n \"nomic-ai/nomic-embed-text-v1-ablated\": 768,\n \"intfloat/e5-base-v2\": 768,\n \"BAAI/bge-large-en-v1.5\": 1024,\n \"intfloat/e5-large\": 1024,\n \"Omartificial-Intelligence-Space/Arabic-MiniLM-L12-v2-all-nli-triplet\": 384,\n \"Cohere/Cohere-embed-english-light-v3.0\": 384,\n \"sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2\": 768,\n \"Gameselo/STS-multilingual-mpnet-base-v2\": 768,\n \"thenlper/gte-large\": 1024,\n \"avsolatorio/GIST-Embedding-v0\": 768,\n \"nomic-ai/nomic-embed-text-v1-unsupervised\": 768,\n \"infgrad/stella-base-en-v2\": 768,\n \"avsolatorio/NoInstruct-small-Embedding-v0\": 384,\n \"dwzhu/e5-base-4k\": 768,\n \"sdadas/mmlw-e5-base\": 768,\n \"voyage-multilingual-2\": 1024,\n \"McGill-NLP/LLM2Vec-Mistral-7B-Instruct-v2-mntp-supervised\": 4096,\n \"BAAI/bge-base-en-v1.5\": 768,\n \"avsolatorio/GIST-small-Embedding-v0\": 384,\n \"sdadas/mmlw-roberta-large\": 1024,\n \"nomic-ai/nomic-embed-text-v1.5\": 768,\n \"minishlab/potion-multilingual-128M\": 256,\n \"shibing624/text2vec-base-multilingual\": 384,\n \"thenlper/gte-base\": 768,\n \"intfloat/e5-small-v2\": 384,\n \"intfloat/e5-base\": 768,\n \"sentence-transformers/static-similarity-mrl-multilingual-v1\": 1024,\n \"manu/sentence_croissant_alpha_v0.3\": 2048,\n \"BAAI/bge-small-en-v1.5\": 512,\n \"thenlper/gte-small\": 384,\n \"sdadas/mmlw-e5-small\": 384,\n \"manu/sentence_croissant_alpha_v0.4\": 2048,\n \"manu/sentence_croissant_alpha_v0.2\": 2048,\n \"abhinand/MedEmbed-small-v0.1\": 384,\n \"ibm-granite/granite-embedding-125m-english\": 768,\n \"intfloat/e5-small\": 384,\n \"voyage-large-2-instruct\": 1024,\n \"sdadas/mmlw-roberta-base\": 768,\n \"Snowflake/snowflake-arctic-embed-l\": 1024,\n \"Mihaiii/Ivysaur\": 384,\n \"Snowflake/snowflake-arctic-embed-m-long\": 768,\n \"bigscience/sgpt-bloom-7b1-msmarco\": 4096,\n \"avsolatorio/GIST-all-MiniLM-L6-v2\": 384,\n \"sergeyzh/LaBSE-ru-turbo\": 768,\n \"sentence-transformers/all-mpnet-base-v2\": 768,\n \"Snowflake/snowflake-arctic-embed-m\": 768,\n \"Snowflake/snowflake-arctic-embed-s\": 384,\n \"sentence-transformers/all-MiniLM-L12-v2\": 384,\n \"Mihaiii/gte-micro-v4\": 384,\n \"Snowflake/snowflake-arctic-embed-m-v1.5\": 768,\n \"cointegrated/LaBSE-en-ru\": 768,\n \"Mihaiii/Bulbasaur\": 384,\n \"ibm-granite/granite-embedding-30m-english\": 384,\n \"deepfile/embedder-100p\": 768,\n \"Jaume/gemma-2b-embeddings\": 2048,\n \"OrlikB/KartonBERT-USE-base-v1\": 768,\n \"izhx/udever-bloom-7b1\": 4096,\n \"izhx/udever-bloom-1b1\": 1024,\n \"brahmairesearch/slx-v0.1\": 384,\n \"Mihaiii/Wartortle\": 384,\n \"izhx/udever-bloom-3b\": 2048,\n \"deepvk/USER-base\": 768,\n \"ai-forever/ru-en-RoSBERTa\": 1024,\n \"McGill-NLP/LLM2Vec-Mistral-7B-Instruct-v2-mntp-unsup-simcse\": 4096,\n \"Mihaiii/Venusaur\": 384,\n \"Snowflake/snowflake-arctic-embed-xs\": 384,\n \"jinaai/jina-embedding-b-en-v1\": 768,\n \"Mihaiii/gte-micro\": 384,\n \"aari1995/German_Semantic_STS_V2\": 1024,\n \"Mihaiii/Squirtle\": 384,\n \"OrlikB/st-polish-kartonberta-base-alpha-v1\": 768,\n \"sergeyzh/rubert-tiny-turbo\": 312,\n \"minishlab/potion-base-8M\": 256,\n \"minishlab/M2V_base_glove_subword\": 256,\n \"jinaai/jina-embedding-s-en-v1\": 512,\n \"minishlab/potion-base-4M\": 128,\n \"minishlab/M2V_base_output\": 256,\n \"DeepPavlov/rubert-base-cased-sentence\": 768,\n \"jinaai/jina-embeddings-v2-small-en\": 512,\n \"cointegrated/rubert-tiny2\": 312,\n \"minishlab/M2V_base_glove\": 256,\n \"cointegrated/rubert-tiny\": 312,\n \"silma-ai/silma-embeddding-matryoshka-v0.1\": 768,\n \"DeepPavlov/rubert-base-cased\": 768,\n \"Omartificial-Intelligence-Space/Arabic-mpnet-base-all-nli-triplet\": 768,\n \"izhx/udever-bloom-560m\": 1024,\n \"minishlab/potion-base-2M\": 64,\n \"DeepPavlov/distilrubert-small-cased-conversational\": 768,\n \"consciousAI/cai-lunaris-text-embeddings\": 1024,\n \"deepvk/deberta-v1-base\": 768,\n \"Omartificial-Intelligence-Space/Arabert-all-nli-triplet-Matryoshka\": 768,\n \"Omartificial-Intelligence-Space/Marbert-all-nli-triplet-Matryoshka\": 768,\n \"ai-forever/sbert_large_mt_nlu_ru\": 1024,\n \"ai-forever/sbert_large_nlu_ru\": 1024,\n \"malenia1/ternary-weight-embedding\": 1024,\n \"jinaai/jina-embeddings-v2-base-en\": 768,\n \"VPLabs/SearchMap_Preview\": 4096,\n \"Hum-Works/lodestone-base-4096-v1\": 768,\n \"jinaai/jina-embeddings-v4\": 2048,\n };\n\n /**\n * Lowercase lookup map for case-insensitive model dimension queries.\n * Built lazily from knownModelDimensions to ensure consistency.\n */\n private modelLookup: Map<string, number>;\n\n constructor() {\n this.modelLookup = new Map();\n for (const [model, dimensions] of Object.entries(this.knownModelDimensions)) {\n this.modelLookup.set(model.toLowerCase(), dimensions);\n }\n }\n\n /**\n * Parse embedding model configuration from a provided model specification.\n * This is a synchronous operation that extracts provider, model, and known dimensions.\n *\n * Supports various providers:\n * - openai: OpenAI models and OpenAI-compatible APIs (Ollama, LMStudio, etc.)\n * - vertex: Google Cloud Vertex AI\n * - gemini: Google Generative AI\n * - aws: AWS Bedrock models\n * - microsoft: Azure OpenAI\n * - sagemaker: AWS SageMaker hosted models\n *\n * @param modelSpec Model specification (e.g., \"openai:text-embedding-3-small\"), defaults to \"text-embedding-3-small\"\n * @returns Parsed embedding model configuration\n */\n parse(modelSpec?: string): EmbeddingModelConfig {\n const spec = normalizeEnvValue(modelSpec || \"text-embedding-3-small\");\n\n // Parse provider and model from string (e.g., \"gemini:embedding-001\" or just \"text-embedding-3-small\")\n // Handle models that contain colons in their names (e.g., \"aws:amazon.titan-embed-text-v2:0\")\n const colonIndex = spec.indexOf(\":\");\n let provider: EmbeddingProvider;\n let model: string;\n\n if (colonIndex === -1) {\n // No colon found, default to OpenAI\n provider = \"openai\";\n model = spec;\n } else {\n // Split only on the first colon\n provider = spec.substring(0, colonIndex) as EmbeddingProvider;\n model = spec.substring(colonIndex + 1);\n }\n\n // Look up known dimensions (case-insensitive)\n const dimensions = this.modelLookup?.get(model.toLowerCase()) || null;\n\n return {\n provider,\n model,\n dimensions,\n modelSpec: spec,\n };\n }\n\n /**\n * Get the known dimensions for a specific model.\n * Returns null if the model dimensions are not known.\n * Uses case-insensitive lookup.\n *\n * @param model The model name (e.g., \"text-embedding-3-small\")\n * @returns Known dimensions or null\n */\n getKnownDimensions(model: string): number | null {\n return this.modelLookup?.get(model.toLowerCase()) || null;\n }\n\n /**\n * Add or update known dimensions for a model.\n * This can be used to cache discovered dimensions.\n * Stores both original case and lowercase for consistent lookup.\n *\n * @param model The model name\n * @param dimensions The dimensions to cache\n */\n setKnownDimensions(model: string, dimensions: number): void {\n this.knownModelDimensions[model] = dimensions;\n\n // Update lowercase lookup map\n if (this.modelLookup) {\n this.modelLookup.set(model.toLowerCase(), dimensions);\n }\n }\n\n /**\n * Static method to parse embedding model configuration using the singleton instance.\n * This maintains backward compatibility while using the class-based approach.\n */\n static parseEmbeddingConfig(modelSpec?: string): EmbeddingModelConfig {\n return EmbeddingConfig.getInstance().parse(modelSpec);\n }\n\n /**\n * Static method to get known model dimensions using the singleton instance.\n * This maintains backward compatibility while using the class-based approach.\n */\n static getKnownModelDimensions(model: string): number | null {\n return EmbeddingConfig.getInstance().getKnownDimensions(model);\n }\n\n /**\n * Static method to set known model dimensions using the singleton instance.\n * This maintains backward compatibility while using the class-based approach.\n */\n static setKnownModelDimensions(model: string, dimensions: number): void {\n EmbeddingConfig.getInstance().setKnownDimensions(model, dimensions);\n }\n}\n","/**\n * Shared CLI utilities and helper functions.\n */\n\nimport { execSync } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { chromium } from \"playwright\";\nimport type { AppServerConfig } from \"../app\";\nimport type { AuthConfig } from \"../auth/types\";\nimport { EventBusService } from \"../events\";\nimport {\n EmbeddingConfig,\n type EmbeddingModelConfig,\n} from \"../store/embeddings/EmbeddingConfig\";\nimport { TelemetryService } from \"../telemetry\";\nimport { logger } from \"../utils/logger\";\nimport { getProjectRoot } from \"../utils/paths\";\nimport type { GlobalOptions } from \"./types\";\n\n/**\n * Context extended with EventBusService, injected via middleware.\n */\nexport interface CliContext {\n _eventBus?: EventBusService;\n [key: string]: unknown;\n}\n\n/**\n * Retrieves the global EventBusService from the arguments context.\n * @param argv The parsed arguments context.\n * @returns The global EventBusService.\n * @throws Error if EventBusService is not initialized.\n */\nexport function getEventBus(argv: CliContext): EventBusService {\n const eventBus = argv._eventBus;\n if (!eventBus) {\n throw new Error(\"EventBusService not initialized\");\n }\n return eventBus;\n}\n\n/**\n * Helper to extract GlobalOptions from the argv.\n * In Yargs, all options are in argv, so we just cast/pick.\n */\nexport function getGlobalOptions(argv: Record<string, unknown>): GlobalOptions {\n return argv as unknown as GlobalOptions;\n}\n\n/**\n * Embedding context.\n * Simplified subset of EmbeddingModelConfig for telemetry purposes.\n */\nexport interface EmbeddingContext {\n aiEmbeddingProvider: string;\n aiEmbeddingModel: string;\n aiEmbeddingDimensions: number | null;\n}\n\n/**\n * Ensures that the Playwright browsers are installed, unless a system Chromium path is set.\n */\nexport function ensurePlaywrightBrowsersInstalled(): void {\n if (process.env.PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD === \"1\") {\n logger.debug(\n \"PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD is set, skipping Playwright browser install.\",\n );\n return;\n }\n\n // If PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH is set, skip install\n const chromiumEnvPath = process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH;\n if (chromiumEnvPath && existsSync(chromiumEnvPath)) {\n logger.debug(\n `PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH is set to '${chromiumEnvPath}', skipping Playwright browser install.`,\n );\n return;\n }\n try {\n // Dynamically require Playwright and check for Chromium browser\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const chromiumPath = chromium.executablePath();\n if (!chromiumPath || !existsSync(chromiumPath)) {\n throw new Error(\"Playwright Chromium browser not found\");\n }\n } catch (error) {\n // Not installed or not found, attempt to install\n logger.debug(String(error));\n try {\n logger.info(\n \"🌐 Installing Playwright Chromium browser... (this may take a moment)\",\n );\n execSync(\"npm exec -y playwright install --no-shell --with-deps chromium\", {\n stdio: \"ignore\", // Suppress output\n cwd: getProjectRoot(),\n });\n } catch (_installErr) {\n logger.error(\n \"❌ Failed to install Playwright browsers automatically. Please run:\\n npx playwright install --no-shell --with-deps chromium\\nand try again.\",\n );\n process.exit(1);\n }\n }\n}\n\n/**\n * Resolves the protocol based on auto-detection or explicit specification.\n * Auto-detection uses TTY status to determine appropriate protocol.\n */\nexport function resolveProtocol(protocol: string): \"stdio\" | \"http\" {\n if (protocol === \"auto\") {\n // VS Code and CI/CD typically run without TTY\n if (!process.stdin.isTTY && !process.stdout.isTTY) {\n return \"stdio\";\n }\n return \"http\";\n }\n\n // Explicit protocol specification\n if (protocol === \"stdio\" || protocol === \"http\") {\n return protocol;\n }\n\n throw new Error(`Invalid protocol: ${protocol}. Must be 'auto', 'stdio', or 'http'`);\n}\n\n/**\n * Validates that --resume flag is only used with in-process workers.\n */\nexport function validateResumeFlag(resume: boolean, serverUrl?: string): void {\n if (resume && serverUrl) {\n throw new Error(\n \"--resume flag is incompatible with --server-url. \" +\n \"External workers handle their own job recovery.\",\n );\n }\n}\n\n/**\n * Validates and parses port number\n */\nexport function validatePort(portString: string): number {\n const port = Number.parseInt(portString, 10);\n if (Number.isNaN(port) || port < 1 || port > 65535) {\n throw new Error(\"Invalid port number\");\n }\n return port;\n}\n\n/**\n * Validates host string for basic format checking\n */\nexport function validateHost(hostString: string): string {\n // Basic validation - allow IPv4, IPv6, and hostnames\n const trimmed = hostString.trim();\n if (!trimmed) {\n throw new Error(\"Host cannot be empty\");\n }\n\n // Very basic format check - reject obviously invalid values\n if (trimmed.includes(\" \") || trimmed.includes(\"\\t\") || trimmed.includes(\"\\n\")) {\n throw new Error(\"Host cannot contain whitespace\");\n }\n\n return trimmed;\n}\n\n/**\n * Creates AppServerConfig based on service requirements.\n *\n * AppConfig is the source of truth for host/auth/telemetry/read-only settings.\n * AppServerConfig only selects which services to run and which port to bind to.\n */\nexport function createAppServerConfig(options: {\n enableWebInterface?: boolean;\n enableMcpServer?: boolean;\n enableApiServer?: boolean;\n enableWorker?: boolean;\n port: number;\n externalWorkerUrl?: string;\n showLogo?: boolean;\n startupContext?: {\n cliCommand?: string;\n mcpProtocol?: \"stdio\" | \"http\";\n mcpTransport?: \"sse\" | \"streamable\";\n };\n}): AppServerConfig {\n return {\n enableWebInterface: options.enableWebInterface ?? false,\n enableMcpServer: options.enableMcpServer ?? true,\n enableApiServer: options.enableApiServer ?? false,\n enableWorker: options.enableWorker ?? true,\n port: options.port,\n externalWorkerUrl: options.externalWorkerUrl,\n showLogo: options.showLogo ?? true,\n startupContext: options.startupContext,\n };\n}\n\n/**\n * Parses custom headers from CLI options\n */\nexport function parseHeaders(headerOptions: string[]): Record<string, string> {\n const headers: Record<string, string> = {};\n\n if (Array.isArray(headerOptions)) {\n for (const entry of headerOptions) {\n const idx = entry.indexOf(\":\");\n if (idx > 0) {\n const name = entry.slice(0, idx).trim();\n const value = entry.slice(idx + 1).trim();\n if (name) headers[name] = value;\n }\n }\n }\n\n return headers;\n}\n\n/**\n * Parses auth configuration from CLI options.\n * Environment variables are handled by createOptionWithEnv in command definitions.\n * Precedence: CLI flags > env vars (handled by commander) > defaults\n */\nexport function parseAuthConfig(options: {\n authEnabled?: boolean;\n authIssuerUrl?: string;\n authAudience?: string;\n}): AuthConfig | undefined {\n // Check if auth is enabled via CLI flag (environment variables handled by commander/yargs)\n if (!options.authEnabled) {\n return undefined;\n }\n\n return {\n enabled: true,\n issuerUrl: options.authIssuerUrl,\n audience: options.authAudience,\n scopes: [\"openid\", \"profile\"], // Default scopes for OAuth2/OIDC\n };\n}\n\n/**\n * Validates auth configuration when auth is enabled.\n */\nexport function validateAuthConfig(authConfig: AuthConfig): void {\n if (!authConfig.enabled) {\n return;\n }\n\n const errors: string[] = [];\n\n // Issuer URL is required when auth is enabled\n if (!authConfig.issuerUrl) {\n errors.push(\"--auth-issuer-url is required when auth is enabled\");\n } else {\n try {\n const url = new URL(authConfig.issuerUrl);\n if (url.protocol !== \"https:\") {\n errors.push(\"Issuer URL must use HTTPS protocol\");\n }\n } catch {\n errors.push(\"Issuer URL must be a valid URL\");\n }\n }\n\n // Audience is required when auth is enabled\n if (!authConfig.audience) {\n errors.push(\"--auth-audience is required when auth is enabled\");\n } else {\n // Audience can be any valid URI (URL or URN)\n // Examples: https://api.example.com, urn:docs-mcp-server:api, urn:company:service\n try {\n // Try parsing as URL first (most common case)\n const url = new URL(authConfig.audience);\n if (url.protocol === \"http:\" && url.hostname !== \"localhost\") {\n // Warn about HTTP in production but don't fail\n logger.warn(\n \"⚠️ Audience uses HTTP protocol - consider using HTTPS for production\",\n );\n }\n if (url.hash) {\n errors.push(\"Audience must not contain URL fragments\");\n }\n } catch {\n // If not a valid URL, check if it's a valid URN\n if (authConfig.audience.startsWith(\"urn:\")) {\n // Basic URN validation: urn:namespace:specific-string\n const urnParts = authConfig.audience.split(\":\");\n if (urnParts.length < 3 || !urnParts[1] || !urnParts[2]) {\n errors.push(\"URN audience must follow format: urn:namespace:specific-string\");\n }\n } else {\n errors.push(\n \"Audience must be a valid absolute URL or URN (e.g., https://api.example.com or urn:company:service)\",\n );\n }\n }\n }\n\n // Scopes are not validated in binary authentication mode\n // They're handled internally by the OAuth proxy\n\n if (errors.length > 0) {\n throw new Error(`Auth configuration validation failed:\\n${errors.join(\"\\n\")}`);\n }\n}\n\n/**\n * Warns about HTTP usage in production when auth is enabled.\n */\nexport function warnHttpUsage(authConfig: AuthConfig | undefined, port: number): void {\n if (!authConfig?.enabled) {\n return;\n }\n\n // Check if we're likely running in production (not localhost)\n const isLocalhost =\n process.env.NODE_ENV !== \"production\" ||\n port === 6280 || // default dev port\n process.env.HOSTNAME?.includes(\"localhost\");\n\n if (!isLocalhost) {\n logger.warn(\n \"⚠️ Authentication is enabled but running over HTTP in production. \" +\n \"Consider using HTTPS for security.\",\n );\n }\n}\n\n/**\n * Creates EventBusService and TelemetryService together.\n * The TelemetryService automatically subscribes to events from the EventBusService.\n * @returns Object containing both services\n */\nexport function createEventServices(): {\n eventBus: EventBusService;\n telemetryService: TelemetryService;\n} {\n const eventBus = new EventBusService();\n const telemetryService = new TelemetryService(eventBus);\n return { eventBus, telemetryService };\n}\n\n/**\n * Resolves embedding configuration from the provided model specification.\n * This function centralizes the logic for determining the embedding model.\n *\n * @param embeddingModel The embedding model specification string.\n * @returns Embedding configuration or null if config is unavailable.\n */\nexport function resolveEmbeddingContext(\n embeddingModel?: string,\n): EmbeddingModelConfig | null {\n try {\n const modelSpec = embeddingModel;\n\n if (!modelSpec) {\n logger.debug(\"No embedding model specified. Embeddings are disabled.\");\n return null;\n }\n\n logger.debug(`Resolving embedding configuration for model: ${modelSpec}`);\n return EmbeddingConfig.parseEmbeddingConfig(modelSpec);\n } catch (error) {\n logger.debug(`Failed to resolve embedding configuration: ${error}`);\n return null;\n }\n}\n"],"names":["projectRoot","EventType","PipelineJobStatus","TelemetryEvent","telemetry"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arabold/docs-mcp-server",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.1",
|
|
4
4
|
"description": "MCP server for fetching and searching documentation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"docs-mcp-server": "dist/index.js"
|
|
8
8
|
},
|
|
9
9
|
"license": "MIT",
|
|
10
|
+
"author": "grounded.tools",
|
|
10
11
|
"repository": {
|
|
11
12
|
"type": "git",
|
|
12
13
|
"url": "git+https://github.com/arabold/docs-mcp-server.git"
|
|
@@ -45,53 +46,55 @@
|
|
|
45
46
|
"postinstall": "echo 'Skipping Playwright browser install. See README.md for details.'"
|
|
46
47
|
},
|
|
47
48
|
"dependencies": {
|
|
48
|
-
"@alpinejs/collapse": "^3.15.
|
|
49
|
+
"@alpinejs/collapse": "^3.15.8",
|
|
49
50
|
"@fastify/formbody": "^8.0.2",
|
|
50
51
|
"@fastify/static": "^8.3.0",
|
|
51
52
|
"@joplin/turndown-plugin-gfm": "^1.0.64",
|
|
52
|
-
"@kitajs/html": "^4.2.
|
|
53
|
-
"@kitajs/ts-html-plugin": "^4.1.
|
|
54
|
-
"@
|
|
55
|
-
"@langchain/
|
|
56
|
-
"@langchain/google-
|
|
57
|
-
"@langchain/
|
|
53
|
+
"@kitajs/html": "^4.2.13",
|
|
54
|
+
"@kitajs/ts-html-plugin": "^4.1.4",
|
|
55
|
+
"@kreuzberg/node": "^4.4.6",
|
|
56
|
+
"@langchain/aws": "^1.3.2",
|
|
57
|
+
"@langchain/google-genai": "^2.1.25",
|
|
58
|
+
"@langchain/google-vertexai": "^2.1.25",
|
|
59
|
+
"@langchain/openai": "^1.2.13",
|
|
58
60
|
"@langchain/textsplitters": "^1.0.1",
|
|
59
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
60
|
-
"@
|
|
61
|
+
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
62
|
+
"@toon-format/toon": "^2.1.0",
|
|
63
|
+
"@trpc/client": "^11.13.4",
|
|
61
64
|
"@trpc/server": "^11.4.4",
|
|
62
65
|
"@types/yargs": "^17.0.35",
|
|
63
|
-
"alpinejs": "^3.15.
|
|
64
|
-
"axios": "^1.13.
|
|
66
|
+
"alpinejs": "^3.15.8",
|
|
67
|
+
"axios": "^1.13.6",
|
|
65
68
|
"axios-retry": "^4.5.0",
|
|
66
|
-
"better-sqlite3": "^12.
|
|
67
|
-
"cheerio": "^1.
|
|
68
|
-
"dompurify": "^3.3.
|
|
69
|
-
"dotenv": "^17.
|
|
69
|
+
"better-sqlite3": "^12.8.0",
|
|
70
|
+
"cheerio": "^1.2.0",
|
|
71
|
+
"dompurify": "^3.3.3",
|
|
72
|
+
"dotenv": "^17.3.1",
|
|
70
73
|
"env-paths": "^3.0.0",
|
|
71
|
-
"fastify": "^5.
|
|
74
|
+
"fastify": "^5.8.2",
|
|
72
75
|
"flowbite": "^4.0.1",
|
|
73
76
|
"fuse.js": "^7.1.0",
|
|
74
77
|
"gray-matter": "^4.0.3",
|
|
75
|
-
"header-generator": "^2.1.
|
|
78
|
+
"header-generator": "^2.1.81",
|
|
76
79
|
"htmx.org": "^2.0.8",
|
|
77
80
|
"iconv-lite": "^0.7.2",
|
|
78
81
|
"idiomorph": "^0.7.4",
|
|
79
|
-
"jose": "^6.1
|
|
82
|
+
"jose": "^6.2.1",
|
|
80
83
|
"jsdom": "^27.4.0",
|
|
81
|
-
"langchain": "^1.2.
|
|
82
|
-
"markitdown-ts": "^0.0.8",
|
|
84
|
+
"langchain": "^1.2.32",
|
|
83
85
|
"mime": "^4.1.0",
|
|
84
|
-
"minimatch": "^10.
|
|
85
|
-
"playwright": "^1.
|
|
86
|
-
"posthog-node": "^5.
|
|
86
|
+
"minimatch": "^10.2.4",
|
|
87
|
+
"playwright": "^1.58.2",
|
|
88
|
+
"posthog-node": "^5.21.2",
|
|
87
89
|
"psl": "^1.15.0",
|
|
88
90
|
"remark": "^15.0.1",
|
|
89
91
|
"remark-gfm": "^4.0.1",
|
|
90
92
|
"remark-html": "^16.0.1",
|
|
91
|
-
"
|
|
93
|
+
"remark-parse": "^11.0.0",
|
|
94
|
+
"semver": "^7.7.4",
|
|
92
95
|
"sqlite-vec": "^0.1.7-alpha.2",
|
|
93
96
|
"superjson": "^2.2.6",
|
|
94
|
-
"tar": "^7.5.
|
|
97
|
+
"tar": "^7.5.11",
|
|
95
98
|
"tree-sitter": "^0.21.1",
|
|
96
99
|
"tree-sitter-javascript": "^0.23.1",
|
|
97
100
|
"tree-sitter-python": "^0.21.0",
|
|
@@ -100,26 +103,26 @@
|
|
|
100
103
|
"ws": "^8.19.0",
|
|
101
104
|
"yaml": "^2.8.2",
|
|
102
105
|
"yargs": "^18.0.0",
|
|
103
|
-
"yauzl": "^3.2.
|
|
104
|
-
"zod": "^4.3.
|
|
106
|
+
"yauzl": "^3.2.1",
|
|
107
|
+
"zod": "^4.3.6"
|
|
105
108
|
},
|
|
106
109
|
"devDependencies": {
|
|
107
|
-
"@biomejs/biome": "^2.
|
|
108
|
-
"@commitlint/cli": "^20.
|
|
109
|
-
"@commitlint/config-conventional": "^20.
|
|
110
|
+
"@biomejs/biome": "^2.4.7",
|
|
111
|
+
"@commitlint/cli": "^20.5.0",
|
|
112
|
+
"@commitlint/config-conventional": "^20.5.0",
|
|
110
113
|
"@semantic-release/changelog": "^6.0.3",
|
|
111
114
|
"@semantic-release/git": "^10.0.1",
|
|
112
|
-
"@semantic-release/github": "^12.0.
|
|
113
|
-
"@semantic-release/npm": "^13.1.
|
|
114
|
-
"@tailwindcss/postcss": "^4.1
|
|
115
|
-
"@tailwindcss/vite": "^4.1
|
|
115
|
+
"@semantic-release/github": "^12.0.6",
|
|
116
|
+
"@semantic-release/npm": "^13.1.5",
|
|
117
|
+
"@tailwindcss/postcss": "^4.2.1",
|
|
118
|
+
"@tailwindcss/vite": "^4.2.1",
|
|
116
119
|
"@types/alpinejs": "^3.13.11",
|
|
117
120
|
"@types/alpinejs__collapse": "~3.13.4",
|
|
118
121
|
"@types/archiver": "^7.0.0",
|
|
119
122
|
"@types/better-sqlite3": "^7.6.13",
|
|
120
123
|
"@types/jsdom": "^27.0.0",
|
|
121
124
|
"@types/lint-staged": "~13.3.0",
|
|
122
|
-
"@types/node": "^24.
|
|
125
|
+
"@types/node": "^24.12.0",
|
|
123
126
|
"@types/node-fetch": "^2.6.13",
|
|
124
127
|
"@types/psl": "^1.1.3",
|
|
125
128
|
"@types/semver": "^7.7.1",
|
|
@@ -128,21 +131,21 @@
|
|
|
128
131
|
"@types/ws": "^8.18.1",
|
|
129
132
|
"@types/yauzl": "^2.10.3",
|
|
130
133
|
"archiver": "^7.0.1",
|
|
131
|
-
"autoprefixer": "^10.4.
|
|
134
|
+
"autoprefixer": "^10.4.27",
|
|
132
135
|
"flowbite-typography": "^1.0.5",
|
|
133
136
|
"husky": "^9.1.7",
|
|
134
|
-
"lint-staged": "^16.
|
|
135
|
-
"memfs": "^4.
|
|
136
|
-
"msw": "^2.12.
|
|
137
|
-
"nock": "^14.0.
|
|
137
|
+
"lint-staged": "^16.4.0",
|
|
138
|
+
"memfs": "^4.56.11",
|
|
139
|
+
"msw": "^2.12.10",
|
|
140
|
+
"nock": "^14.0.11",
|
|
138
141
|
"npm-run-all": "^4.1.5",
|
|
139
|
-
"postcss": "^8.5.
|
|
140
|
-
"promptfoo": "^0.120.
|
|
141
|
-
"semantic-release": "^25.0.
|
|
142
|
+
"postcss": "^8.5.8",
|
|
143
|
+
"promptfoo": "^0.120.19",
|
|
144
|
+
"semantic-release": "^25.0.3",
|
|
142
145
|
"tailwindcss": "^4.1.4",
|
|
143
146
|
"typescript": "^5.9.3",
|
|
144
147
|
"vite": "^7.3.1",
|
|
145
|
-
"vite-node": "^5.
|
|
148
|
+
"vite-node": "^5.3.0",
|
|
146
149
|
"vite-plugin-dts": "^4.5.4",
|
|
147
150
|
"vitest": "^3.2.4"
|
|
148
151
|
},
|