@weavelogic/knowledge-graph-agent 0.7.3 → 0.8.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.
- package/README.md +4 -0
- package/dist/_virtual/__vite-browser-external.js +2 -2
- package/dist/_virtual/__vite-browser-external.js.map +1 -1
- package/dist/_virtual/browser.js +2 -3
- package/dist/_virtual/browser.js.map +1 -1
- package/dist/cli/commands/hive-mind/add-frontmatter.js +2 -2
- package/dist/cli/commands/hive-mind/add-frontmatter.js.map +1 -1
- package/dist/cli/commands/hive-mind/analyze-links.js +2 -2
- package/dist/cli/commands/hive-mind/analyze-links.js.map +1 -1
- package/dist/cli/commands/hive-mind/find-connections.js +2 -2
- package/dist/cli/commands/hive-mind/find-connections.js.map +1 -1
- package/dist/cli/commands/hive-mind/validate-names.js +2 -2
- package/dist/cli/commands/hive-mind/validate-names.js.map +1 -1
- package/dist/graphql/server.js +2 -2
- package/dist/graphql/server.js.map +1 -1
- package/dist/mcp-server/tools/audit/index.d.ts +4 -0
- package/dist/mcp-server/tools/audit/index.d.ts.map +1 -1
- package/dist/node_modules/@typescript-eslint/project-service/dist/index.js +1 -1
- package/dist/node_modules/@typescript-eslint/types/dist/index.js +1 -1
- package/dist/node_modules/@typescript-eslint/visitor-keys/dist/index.js +1 -1
- package/dist/node_modules/debug/src/browser.js +1 -1
- package/dist/node_modules/fdir/dist/index.js +13 -13
- package/dist/node_modules/fdir/dist/index.js.map +1 -1
- package/dist/node_modules/tinyglobby/dist/index.js +14 -14
- package/dist/node_modules/tinyglobby/dist/index.js.map +1 -1
- package/dist/node_modules/typescript/lib/typescript.js +24 -24
- package/dist/node_modules/typescript/lib/typescript.js.map +1 -1
- package/dist/vector/services/embedding-service.js +1 -7
- package/dist/vector/services/embedding-service.js.map +1 -1
- package/package.json +3 -2
- package/dist/_virtual/browser2.js +0 -5
- package/dist/_virtual/browser2.js.map +0 -1
- package/dist/_virtual/index12.js +0 -7
- package/dist/_virtual/index12.js.map +0 -1
- package/dist/_virtual/ort-web.min.js +0 -8
- package/dist/_virtual/ort-web.min.js.map +0 -1
- package/dist/_virtual/ort-web.min2.js +0 -5
- package/dist/_virtual/ort-web.min2.js.map +0 -1
- package/dist/node_modules/@huggingface/jinja/dist/index.js +0 -118
- package/dist/node_modules/@huggingface/jinja/dist/index.js.map +0 -1
- package/dist/node_modules/@xenova/transformers/src/backends/onnx.js +0 -24
- package/dist/node_modules/@xenova/transformers/src/backends/onnx.js.map +0 -1
- package/dist/node_modules/@xenova/transformers/src/configs.js +0 -52
- package/dist/node_modules/@xenova/transformers/src/configs.js.map +0 -1
- package/dist/node_modules/@xenova/transformers/src/env.js +0 -35
- package/dist/node_modules/@xenova/transformers/src/env.js.map +0 -1
- package/dist/node_modules/@xenova/transformers/src/models.js +0 -3852
- package/dist/node_modules/@xenova/transformers/src/models.js.map +0 -1
- package/dist/node_modules/@xenova/transformers/src/tokenizers.js +0 -144
- package/dist/node_modules/@xenova/transformers/src/tokenizers.js.map +0 -1
- package/dist/node_modules/@xenova/transformers/src/utils/core.js +0 -52
- package/dist/node_modules/@xenova/transformers/src/utils/core.js.map +0 -1
- package/dist/node_modules/@xenova/transformers/src/utils/generation.js +0 -623
- package/dist/node_modules/@xenova/transformers/src/utils/generation.js.map +0 -1
- package/dist/node_modules/@xenova/transformers/src/utils/hub.js +0 -395
- package/dist/node_modules/@xenova/transformers/src/utils/hub.js.map +0 -1
- package/dist/node_modules/@xenova/transformers/src/utils/image.js +0 -12
- package/dist/node_modules/@xenova/transformers/src/utils/image.js.map +0 -1
- package/dist/node_modules/@xenova/transformers/src/utils/maths.js +0 -89
- package/dist/node_modules/@xenova/transformers/src/utils/maths.js.map +0 -1
- package/dist/node_modules/@xenova/transformers/src/utils/tensor.js +0 -750
- package/dist/node_modules/@xenova/transformers/src/utils/tensor.js.map +0 -1
- package/dist/node_modules/onnxruntime-common/dist/lib/backend-impl.js +0 -67
- package/dist/node_modules/onnxruntime-common/dist/lib/backend-impl.js.map +0 -1
- package/dist/node_modules/onnxruntime-common/dist/lib/env-impl.js +0 -24
- package/dist/node_modules/onnxruntime-common/dist/lib/env-impl.js.map +0 -1
- package/dist/node_modules/onnxruntime-common/dist/lib/env.js +0 -6
- package/dist/node_modules/onnxruntime-common/dist/lib/env.js.map +0 -1
- package/dist/node_modules/onnxruntime-common/dist/lib/index.js +0 -11
- package/dist/node_modules/onnxruntime-common/dist/lib/index.js.map +0 -1
- package/dist/node_modules/onnxruntime-common/dist/lib/inference-session-impl.js +0 -162
- package/dist/node_modules/onnxruntime-common/dist/lib/inference-session-impl.js.map +0 -1
- package/dist/node_modules/onnxruntime-common/dist/lib/inference-session.js +0 -6
- package/dist/node_modules/onnxruntime-common/dist/lib/inference-session.js.map +0 -1
- package/dist/node_modules/onnxruntime-common/dist/lib/tensor-impl.js +0 -393
- package/dist/node_modules/onnxruntime-common/dist/lib/tensor-impl.js.map +0 -1
- package/dist/node_modules/onnxruntime-common/dist/lib/tensor.js +0 -6
- package/dist/node_modules/onnxruntime-common/dist/lib/tensor.js.map +0 -1
- package/dist/node_modules/onnxruntime-web/dist/ort-web.min.js +0 -12919
- package/dist/node_modules/onnxruntime-web/dist/ort-web.min.js.map +0 -1
- package/dist/node_modules/ws/browser.js +0 -16
- package/dist/node_modules/ws/browser.js.map +0 -1
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
import "
|
|
2
|
-
import "../../node_modules/@xenova/transformers/src/models.js";
|
|
3
|
-
import "fs";
|
|
4
|
-
import "path";
|
|
5
|
-
import "../../node_modules/@xenova/transformers/src/env.js";
|
|
6
|
-
import "../../node_modules/@xenova/transformers/src/utils/tensor.js";
|
|
7
|
-
import "../../node_modules/@xenova/transformers/src/utils/image.js";
|
|
1
|
+
import "@xenova/transformers";
|
|
8
2
|
import { createLogger } from "../../utils/logger.js";
|
|
9
3
|
createLogger("embedding-service");
|
|
10
4
|
//# sourceMappingURL=embedding-service.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"embedding-service.js","sources":["../../../src/vector/services/embedding-service.ts"],"sourcesContent":["/**\n * Embedding Service\n *\n * Provides text embedding generation using transformer models via @xenova/transformers.\n * Uses the all-MiniLM-L6-v2 model (384 dimensions) by default for efficient local inference.\n *\n * @module vector/services/embedding-service\n */\n\nimport { pipeline, type Pipeline, type FeatureExtractionPipeline } from '@xenova/transformers';\nimport { createLogger } from '../../utils/index.js';\n\nconst logger = createLogger('embedding-service');\n\n/**\n * Configuration for the embedding service\n */\nexport interface EmbeddingConfig {\n /**\n * Model identifier for the embedding model\n * @default 'Xenova/all-MiniLM-L6-v2'\n */\n model: string;\n\n /**\n * Expected output dimensions for embeddings\n * @default 384\n */\n dimensions: number;\n\n /**\n * Maximum input text length in characters (not tokens)\n * Longer texts will be truncated\n * @default 512\n */\n maxLength: number;\n\n /**\n * Number of texts to process in a single batch\n * @default 32\n */\n batchSize: number;\n\n /**\n * Whether to normalize embeddings to unit length\n * @default true\n */\n normalize: boolean;\n\n /**\n * Pooling strategy for generating embeddings from token outputs\n * @default 'mean'\n */\n pooling: 'mean' | 'cls' | 'none';\n\n /**\n * Enable quantization for reduced memory usage\n * @default false\n */\n quantized: boolean;\n}\n\n/**\n * Default configuration for embedding service\n * Uses all-MiniLM-L6-v2 which provides a good balance of quality and speed\n */\nconst DEFAULT_CONFIG: EmbeddingConfig = {\n model: 'Xenova/all-MiniLM-L6-v2',\n dimensions: 384,\n maxLength: 512,\n batchSize: 32,\n normalize: true,\n pooling: 'mean',\n quantized: false,\n};\n\n/**\n * Result of embedding generation\n */\nexport interface EmbeddingResult {\n /**\n * The embedding vector\n */\n embedding: Float32Array;\n\n /**\n * Time taken to generate the embedding in milliseconds\n */\n durationMs: number;\n\n /**\n * Number of input tokens (approximate)\n */\n tokenCount?: number;\n}\n\n/**\n * Result of batch embedding generation\n */\nexport interface BatchEmbeddingResult {\n /**\n * Array of embedding vectors\n */\n embeddings: Float32Array[];\n\n /**\n * Total time taken in milliseconds\n */\n durationMs: number;\n\n /**\n * Number of texts successfully embedded\n */\n successCount: number;\n\n /**\n * Number of texts that failed\n */\n errorCount: number;\n\n /**\n * Error details for failed texts\n */\n errors?: Array<{ index: number; error: string }>;\n}\n\n/**\n * Embedding Service\n *\n * Provides text embedding generation using transformer models.\n * Supports single and batch operations with automatic initialization.\n *\n * @example\n * ```typescript\n * const service = new EmbeddingService();\n * await service.initialize();\n *\n * // Single embedding\n * const embedding = await service.embed('Hello, world!');\n *\n * // Batch embeddings\n * const embeddings = await service.embedBatch([\n * 'First document',\n * 'Second document',\n * 'Third document'\n * ]);\n * ```\n */\nexport class EmbeddingService {\n private pipeline: FeatureExtractionPipeline | null = null;\n private config: EmbeddingConfig;\n private initPromise: Promise<void> | null = null;\n private isInitialized: boolean = false;\n\n /**\n * Create a new EmbeddingService\n *\n * @param config - Optional configuration overrides\n */\n constructor(config: Partial<EmbeddingConfig> = {}) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n }\n\n /**\n * Initialize the embedding pipeline\n *\n * Loads the transformer model. This is called automatically on first use\n * but can be called explicitly to pre-load the model.\n *\n * @throws Error if model loading fails\n */\n async initialize(): Promise<void> {\n if (this.isInitialized) {\n return;\n }\n\n if (this.initPromise) {\n return this.initPromise;\n }\n\n this.initPromise = this.doInitialize();\n return this.initPromise;\n }\n\n private async doInitialize(): Promise<void> {\n try {\n logger.info('Loading embedding model', { model: this.config.model });\n const startTime = Date.now();\n\n // Load the feature extraction pipeline\n this.pipeline = (await pipeline(\n 'feature-extraction',\n this.config.model,\n { quantized: this.config.quantized }\n )) as FeatureExtractionPipeline;\n\n const durationMs = Date.now() - startTime;\n logger.info('Embedding model loaded', {\n model: this.config.model,\n durationMs,\n });\n\n this.isInitialized = true;\n } catch (error) {\n this.initPromise = null;\n const message = error instanceof Error ? error.message : String(error);\n logger.error('Failed to load embedding model', new Error(message), {\n model: this.config.model,\n });\n throw new Error(`Failed to initialize embedding service: ${message}`);\n }\n }\n\n /**\n * Generate embedding for a single text\n *\n * @param text - Text to embed\n * @returns Embedding result with vector and metadata\n * @throws Error if not initialized or embedding fails\n */\n async embed(text: string): Promise<EmbeddingResult> {\n await this.initialize();\n\n if (!this.pipeline) {\n throw new Error('Embedding pipeline not initialized');\n }\n\n const startTime = Date.now();\n\n // Truncate text if too long\n const truncated = this.truncateText(text);\n\n try {\n const output = await this.pipeline(truncated, {\n pooling: this.config.pooling,\n normalize: this.config.normalize,\n });\n\n // Extract the embedding data\n const embedding = this.extractEmbedding(output);\n\n const durationMs = Date.now() - startTime;\n\n logger.debug('Generated embedding', {\n inputLength: text.length,\n truncated: text.length !== truncated.length,\n durationMs,\n });\n\n return {\n embedding,\n durationMs,\n tokenCount: Math.ceil(truncated.length / 4), // Rough estimate\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logger.error('Embedding generation failed', new Error(message));\n throw new Error(`Failed to generate embedding: ${message}`);\n }\n }\n\n /**\n * Generate embeddings for multiple texts\n *\n * Processes texts in batches for efficiency.\n *\n * @param texts - Array of texts to embed\n * @returns Batch result with embeddings and metadata\n */\n async embedBatch(texts: string[]): Promise<BatchEmbeddingResult> {\n await this.initialize();\n\n if (!this.pipeline) {\n throw new Error('Embedding pipeline not initialized');\n }\n\n const startTime = Date.now();\n const results: Float32Array[] = [];\n const errors: Array<{ index: number; error: string }> = [];\n\n // Process in batches\n for (let i = 0; i < texts.length; i += this.config.batchSize) {\n const batch = texts.slice(i, i + this.config.batchSize);\n const truncatedBatch = batch.map((t) => this.truncateText(t));\n\n try {\n // Process batch\n const outputs = await this.pipeline(truncatedBatch, {\n pooling: this.config.pooling,\n normalize: this.config.normalize,\n });\n\n // Extract embeddings from batch output\n const batchEmbeddings = this.extractBatchEmbeddings(outputs, batch.length);\n results.push(...batchEmbeddings);\n } catch (error) {\n // Fall back to individual processing on batch error\n logger.warn('Batch embedding failed, falling back to individual', {\n batchIndex: i / this.config.batchSize,\n });\n\n for (let j = 0; j < batch.length; j++) {\n try {\n const output = await this.pipeline(truncatedBatch[j], {\n pooling: this.config.pooling,\n normalize: this.config.normalize,\n });\n results.push(this.extractEmbedding(output));\n } catch (individualError) {\n errors.push({\n index: i + j,\n error: individualError instanceof Error ? individualError.message : String(individualError),\n });\n // Push zero vector as placeholder\n results.push(new Float32Array(this.config.dimensions));\n }\n }\n }\n }\n\n const durationMs = Date.now() - startTime;\n\n logger.info('Batch embedding completed', {\n totalTexts: texts.length,\n successCount: texts.length - errors.length,\n errorCount: errors.length,\n durationMs,\n avgTimePerText: durationMs / texts.length,\n });\n\n return {\n embeddings: results,\n durationMs,\n successCount: texts.length - errors.length,\n errorCount: errors.length,\n errors: errors.length > 0 ? errors : undefined,\n };\n }\n\n /**\n * Truncate text to maximum length\n *\n * @param text - Text to truncate\n * @returns Truncated text\n */\n private truncateText(text: string): string {\n if (text.length <= this.config.maxLength * 4) {\n return text;\n }\n // Truncate at word boundary if possible\n const truncated = text.slice(0, this.config.maxLength * 4);\n const lastSpace = truncated.lastIndexOf(' ');\n if (lastSpace > this.config.maxLength * 2) {\n return truncated.slice(0, lastSpace);\n }\n return truncated;\n }\n\n /**\n * Extract embedding from pipeline output\n *\n * @param output - Pipeline output tensor\n * @returns Float32Array embedding\n */\n private extractEmbedding(output: unknown): Float32Array {\n // Handle different output formats from transformers.js\n if (output && typeof output === 'object') {\n const outputObj = output as Record<string, unknown>;\n\n // Check for .data property (Tensor object)\n if ('data' in outputObj && outputObj.data) {\n const data = outputObj.data;\n if (data instanceof Float32Array) {\n return data.slice(0, this.config.dimensions);\n }\n if (ArrayBuffer.isView(data)) {\n return new Float32Array(data.buffer, data.byteOffset, this.config.dimensions);\n }\n if (Array.isArray(data)) {\n return new Float32Array(data.slice(0, this.config.dimensions));\n }\n }\n\n // Check for nested array structure\n if (Array.isArray(outputObj)) {\n const flattened = this.flattenArray(outputObj);\n return new Float32Array(flattened.slice(0, this.config.dimensions));\n }\n }\n\n throw new Error('Unexpected output format from embedding pipeline');\n }\n\n /**\n * Extract multiple embeddings from batch output\n *\n * @param output - Pipeline output tensor for batch\n * @param batchSize - Number of items in the batch\n * @returns Array of embeddings\n */\n private extractBatchEmbeddings(output: unknown, batchSize: number): Float32Array[] {\n const results: Float32Array[] = [];\n\n if (output && typeof output === 'object') {\n const outputObj = output as Record<string, unknown>;\n\n if ('data' in outputObj && outputObj.data) {\n const data = outputObj.data;\n let dataArray: Float32Array;\n\n if (data instanceof Float32Array) {\n dataArray = data;\n } else if (ArrayBuffer.isView(data)) {\n dataArray = new Float32Array(data.buffer, data.byteOffset);\n } else if (Array.isArray(data)) {\n dataArray = new Float32Array(data as number[]);\n } else {\n throw new Error('Unexpected data format in batch output');\n }\n\n // Split the data array into individual embeddings\n for (let i = 0; i < batchSize; i++) {\n const start = i * this.config.dimensions;\n const embedding = dataArray.slice(start, start + this.config.dimensions);\n results.push(embedding);\n }\n\n return results;\n }\n }\n\n throw new Error('Unexpected output format from batch embedding pipeline');\n }\n\n /**\n * Flatten nested array\n *\n * @param arr - Array to flatten\n * @returns Flattened number array\n */\n private flattenArray(arr: unknown[]): number[] {\n const result: number[] = [];\n for (const item of arr) {\n if (Array.isArray(item)) {\n result.push(...this.flattenArray(item));\n } else if (typeof item === 'number') {\n result.push(item);\n }\n }\n return result;\n }\n\n /**\n * Get the embedding dimensions\n *\n * @returns Number of dimensions in generated embeddings\n */\n getDimensions(): number {\n return this.config.dimensions;\n }\n\n /**\n * Get the current configuration\n *\n * @returns Copy of the current configuration\n */\n getConfig(): EmbeddingConfig {\n return { ...this.config };\n }\n\n /**\n * Check if the service is initialized\n *\n * @returns True if initialized\n */\n isReady(): boolean {\n return this.isInitialized;\n }\n\n /**\n * Get model information\n *\n * @returns Model details\n */\n getModelInfo(): { model: string; dimensions: number; quantized: boolean } {\n return {\n model: this.config.model,\n dimensions: this.config.dimensions,\n quantized: this.config.quantized,\n };\n }\n}\n\n/**\n * Create an embedding service instance\n *\n * Factory function for creating embedding services.\n *\n * @param config - Optional configuration overrides\n * @returns New EmbeddingService instance\n *\n * @example\n * ```typescript\n * // Default configuration (all-MiniLM-L6-v2, 384 dimensions)\n * const service = createEmbeddingService();\n *\n * // Custom configuration\n * const customService = createEmbeddingService({\n * model: 'Xenova/all-MiniLM-L12-v2',\n * dimensions: 384,\n * batchSize: 64,\n * });\n * ```\n */\nexport function createEmbeddingService(config?: Partial<EmbeddingConfig>): EmbeddingService {\n return new EmbeddingService(config);\n}\n\n/**\n * Default embedding service singleton\n * Created lazily on first use\n */\nlet defaultService: EmbeddingService | null = null;\n\n/**\n * Get the default embedding service\n *\n * Returns a shared singleton instance for convenience.\n * Use createEmbeddingService() for custom configurations.\n *\n * @returns Default EmbeddingService instance\n */\nexport function getDefaultEmbeddingService(): EmbeddingService {\n if (!defaultService) {\n defaultService = new EmbeddingService();\n }\n return defaultService;\n}\n"],"names":[],"mappings":";;;;;;;;AAYe,aAAa,mBAAmB;"}
|
|
1
|
+
{"version":3,"file":"embedding-service.js","sources":["../../../src/vector/services/embedding-service.ts"],"sourcesContent":["/**\n * Embedding Service\n *\n * Provides text embedding generation using transformer models via @xenova/transformers.\n * Uses the all-MiniLM-L6-v2 model (384 dimensions) by default for efficient local inference.\n *\n * @module vector/services/embedding-service\n */\n\nimport { pipeline, type Pipeline, type FeatureExtractionPipeline } from '@xenova/transformers';\nimport { createLogger } from '../../utils/index.js';\n\nconst logger = createLogger('embedding-service');\n\n/**\n * Configuration for the embedding service\n */\nexport interface EmbeddingConfig {\n /**\n * Model identifier for the embedding model\n * @default 'Xenova/all-MiniLM-L6-v2'\n */\n model: string;\n\n /**\n * Expected output dimensions for embeddings\n * @default 384\n */\n dimensions: number;\n\n /**\n * Maximum input text length in characters (not tokens)\n * Longer texts will be truncated\n * @default 512\n */\n maxLength: number;\n\n /**\n * Number of texts to process in a single batch\n * @default 32\n */\n batchSize: number;\n\n /**\n * Whether to normalize embeddings to unit length\n * @default true\n */\n normalize: boolean;\n\n /**\n * Pooling strategy for generating embeddings from token outputs\n * @default 'mean'\n */\n pooling: 'mean' | 'cls' | 'none';\n\n /**\n * Enable quantization for reduced memory usage\n * @default false\n */\n quantized: boolean;\n}\n\n/**\n * Default configuration for embedding service\n * Uses all-MiniLM-L6-v2 which provides a good balance of quality and speed\n */\nconst DEFAULT_CONFIG: EmbeddingConfig = {\n model: 'Xenova/all-MiniLM-L6-v2',\n dimensions: 384,\n maxLength: 512,\n batchSize: 32,\n normalize: true,\n pooling: 'mean',\n quantized: false,\n};\n\n/**\n * Result of embedding generation\n */\nexport interface EmbeddingResult {\n /**\n * The embedding vector\n */\n embedding: Float32Array;\n\n /**\n * Time taken to generate the embedding in milliseconds\n */\n durationMs: number;\n\n /**\n * Number of input tokens (approximate)\n */\n tokenCount?: number;\n}\n\n/**\n * Result of batch embedding generation\n */\nexport interface BatchEmbeddingResult {\n /**\n * Array of embedding vectors\n */\n embeddings: Float32Array[];\n\n /**\n * Total time taken in milliseconds\n */\n durationMs: number;\n\n /**\n * Number of texts successfully embedded\n */\n successCount: number;\n\n /**\n * Number of texts that failed\n */\n errorCount: number;\n\n /**\n * Error details for failed texts\n */\n errors?: Array<{ index: number; error: string }>;\n}\n\n/**\n * Embedding Service\n *\n * Provides text embedding generation using transformer models.\n * Supports single and batch operations with automatic initialization.\n *\n * @example\n * ```typescript\n * const service = new EmbeddingService();\n * await service.initialize();\n *\n * // Single embedding\n * const embedding = await service.embed('Hello, world!');\n *\n * // Batch embeddings\n * const embeddings = await service.embedBatch([\n * 'First document',\n * 'Second document',\n * 'Third document'\n * ]);\n * ```\n */\nexport class EmbeddingService {\n private pipeline: FeatureExtractionPipeline | null = null;\n private config: EmbeddingConfig;\n private initPromise: Promise<void> | null = null;\n private isInitialized: boolean = false;\n\n /**\n * Create a new EmbeddingService\n *\n * @param config - Optional configuration overrides\n */\n constructor(config: Partial<EmbeddingConfig> = {}) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n }\n\n /**\n * Initialize the embedding pipeline\n *\n * Loads the transformer model. This is called automatically on first use\n * but can be called explicitly to pre-load the model.\n *\n * @throws Error if model loading fails\n */\n async initialize(): Promise<void> {\n if (this.isInitialized) {\n return;\n }\n\n if (this.initPromise) {\n return this.initPromise;\n }\n\n this.initPromise = this.doInitialize();\n return this.initPromise;\n }\n\n private async doInitialize(): Promise<void> {\n try {\n logger.info('Loading embedding model', { model: this.config.model });\n const startTime = Date.now();\n\n // Load the feature extraction pipeline\n this.pipeline = (await pipeline(\n 'feature-extraction',\n this.config.model,\n { quantized: this.config.quantized }\n )) as FeatureExtractionPipeline;\n\n const durationMs = Date.now() - startTime;\n logger.info('Embedding model loaded', {\n model: this.config.model,\n durationMs,\n });\n\n this.isInitialized = true;\n } catch (error) {\n this.initPromise = null;\n const message = error instanceof Error ? error.message : String(error);\n logger.error('Failed to load embedding model', new Error(message), {\n model: this.config.model,\n });\n throw new Error(`Failed to initialize embedding service: ${message}`);\n }\n }\n\n /**\n * Generate embedding for a single text\n *\n * @param text - Text to embed\n * @returns Embedding result with vector and metadata\n * @throws Error if not initialized or embedding fails\n */\n async embed(text: string): Promise<EmbeddingResult> {\n await this.initialize();\n\n if (!this.pipeline) {\n throw new Error('Embedding pipeline not initialized');\n }\n\n const startTime = Date.now();\n\n // Truncate text if too long\n const truncated = this.truncateText(text);\n\n try {\n const output = await this.pipeline(truncated, {\n pooling: this.config.pooling,\n normalize: this.config.normalize,\n });\n\n // Extract the embedding data\n const embedding = this.extractEmbedding(output);\n\n const durationMs = Date.now() - startTime;\n\n logger.debug('Generated embedding', {\n inputLength: text.length,\n truncated: text.length !== truncated.length,\n durationMs,\n });\n\n return {\n embedding,\n durationMs,\n tokenCount: Math.ceil(truncated.length / 4), // Rough estimate\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logger.error('Embedding generation failed', new Error(message));\n throw new Error(`Failed to generate embedding: ${message}`);\n }\n }\n\n /**\n * Generate embeddings for multiple texts\n *\n * Processes texts in batches for efficiency.\n *\n * @param texts - Array of texts to embed\n * @returns Batch result with embeddings and metadata\n */\n async embedBatch(texts: string[]): Promise<BatchEmbeddingResult> {\n await this.initialize();\n\n if (!this.pipeline) {\n throw new Error('Embedding pipeline not initialized');\n }\n\n const startTime = Date.now();\n const results: Float32Array[] = [];\n const errors: Array<{ index: number; error: string }> = [];\n\n // Process in batches\n for (let i = 0; i < texts.length; i += this.config.batchSize) {\n const batch = texts.slice(i, i + this.config.batchSize);\n const truncatedBatch = batch.map((t) => this.truncateText(t));\n\n try {\n // Process batch\n const outputs = await this.pipeline(truncatedBatch, {\n pooling: this.config.pooling,\n normalize: this.config.normalize,\n });\n\n // Extract embeddings from batch output\n const batchEmbeddings = this.extractBatchEmbeddings(outputs, batch.length);\n results.push(...batchEmbeddings);\n } catch (error) {\n // Fall back to individual processing on batch error\n logger.warn('Batch embedding failed, falling back to individual', {\n batchIndex: i / this.config.batchSize,\n });\n\n for (let j = 0; j < batch.length; j++) {\n try {\n const output = await this.pipeline(truncatedBatch[j], {\n pooling: this.config.pooling,\n normalize: this.config.normalize,\n });\n results.push(this.extractEmbedding(output));\n } catch (individualError) {\n errors.push({\n index: i + j,\n error: individualError instanceof Error ? individualError.message : String(individualError),\n });\n // Push zero vector as placeholder\n results.push(new Float32Array(this.config.dimensions));\n }\n }\n }\n }\n\n const durationMs = Date.now() - startTime;\n\n logger.info('Batch embedding completed', {\n totalTexts: texts.length,\n successCount: texts.length - errors.length,\n errorCount: errors.length,\n durationMs,\n avgTimePerText: durationMs / texts.length,\n });\n\n return {\n embeddings: results,\n durationMs,\n successCount: texts.length - errors.length,\n errorCount: errors.length,\n errors: errors.length > 0 ? errors : undefined,\n };\n }\n\n /**\n * Truncate text to maximum length\n *\n * @param text - Text to truncate\n * @returns Truncated text\n */\n private truncateText(text: string): string {\n if (text.length <= this.config.maxLength * 4) {\n return text;\n }\n // Truncate at word boundary if possible\n const truncated = text.slice(0, this.config.maxLength * 4);\n const lastSpace = truncated.lastIndexOf(' ');\n if (lastSpace > this.config.maxLength * 2) {\n return truncated.slice(0, lastSpace);\n }\n return truncated;\n }\n\n /**\n * Extract embedding from pipeline output\n *\n * @param output - Pipeline output tensor\n * @returns Float32Array embedding\n */\n private extractEmbedding(output: unknown): Float32Array {\n // Handle different output formats from transformers.js\n if (output && typeof output === 'object') {\n const outputObj = output as Record<string, unknown>;\n\n // Check for .data property (Tensor object)\n if ('data' in outputObj && outputObj.data) {\n const data = outputObj.data;\n if (data instanceof Float32Array) {\n return data.slice(0, this.config.dimensions);\n }\n if (ArrayBuffer.isView(data)) {\n return new Float32Array(data.buffer, data.byteOffset, this.config.dimensions);\n }\n if (Array.isArray(data)) {\n return new Float32Array(data.slice(0, this.config.dimensions));\n }\n }\n\n // Check for nested array structure\n if (Array.isArray(outputObj)) {\n const flattened = this.flattenArray(outputObj);\n return new Float32Array(flattened.slice(0, this.config.dimensions));\n }\n }\n\n throw new Error('Unexpected output format from embedding pipeline');\n }\n\n /**\n * Extract multiple embeddings from batch output\n *\n * @param output - Pipeline output tensor for batch\n * @param batchSize - Number of items in the batch\n * @returns Array of embeddings\n */\n private extractBatchEmbeddings(output: unknown, batchSize: number): Float32Array[] {\n const results: Float32Array[] = [];\n\n if (output && typeof output === 'object') {\n const outputObj = output as Record<string, unknown>;\n\n if ('data' in outputObj && outputObj.data) {\n const data = outputObj.data;\n let dataArray: Float32Array;\n\n if (data instanceof Float32Array) {\n dataArray = data;\n } else if (ArrayBuffer.isView(data)) {\n dataArray = new Float32Array(data.buffer, data.byteOffset);\n } else if (Array.isArray(data)) {\n dataArray = new Float32Array(data as number[]);\n } else {\n throw new Error('Unexpected data format in batch output');\n }\n\n // Split the data array into individual embeddings\n for (let i = 0; i < batchSize; i++) {\n const start = i * this.config.dimensions;\n const embedding = dataArray.slice(start, start + this.config.dimensions);\n results.push(embedding);\n }\n\n return results;\n }\n }\n\n throw new Error('Unexpected output format from batch embedding pipeline');\n }\n\n /**\n * Flatten nested array\n *\n * @param arr - Array to flatten\n * @returns Flattened number array\n */\n private flattenArray(arr: unknown[]): number[] {\n const result: number[] = [];\n for (const item of arr) {\n if (Array.isArray(item)) {\n result.push(...this.flattenArray(item));\n } else if (typeof item === 'number') {\n result.push(item);\n }\n }\n return result;\n }\n\n /**\n * Get the embedding dimensions\n *\n * @returns Number of dimensions in generated embeddings\n */\n getDimensions(): number {\n return this.config.dimensions;\n }\n\n /**\n * Get the current configuration\n *\n * @returns Copy of the current configuration\n */\n getConfig(): EmbeddingConfig {\n return { ...this.config };\n }\n\n /**\n * Check if the service is initialized\n *\n * @returns True if initialized\n */\n isReady(): boolean {\n return this.isInitialized;\n }\n\n /**\n * Get model information\n *\n * @returns Model details\n */\n getModelInfo(): { model: string; dimensions: number; quantized: boolean } {\n return {\n model: this.config.model,\n dimensions: this.config.dimensions,\n quantized: this.config.quantized,\n };\n }\n}\n\n/**\n * Create an embedding service instance\n *\n * Factory function for creating embedding services.\n *\n * @param config - Optional configuration overrides\n * @returns New EmbeddingService instance\n *\n * @example\n * ```typescript\n * // Default configuration (all-MiniLM-L6-v2, 384 dimensions)\n * const service = createEmbeddingService();\n *\n * // Custom configuration\n * const customService = createEmbeddingService({\n * model: 'Xenova/all-MiniLM-L12-v2',\n * dimensions: 384,\n * batchSize: 64,\n * });\n * ```\n */\nexport function createEmbeddingService(config?: Partial<EmbeddingConfig>): EmbeddingService {\n return new EmbeddingService(config);\n}\n\n/**\n * Default embedding service singleton\n * Created lazily on first use\n */\nlet defaultService: EmbeddingService | null = null;\n\n/**\n * Get the default embedding service\n *\n * Returns a shared singleton instance for convenience.\n * Use createEmbeddingService() for custom configurations.\n *\n * @returns Default EmbeddingService instance\n */\nexport function getDefaultEmbeddingService(): EmbeddingService {\n if (!defaultService) {\n defaultService = new EmbeddingService();\n }\n return defaultService;\n}\n"],"names":[],"mappings":";;AAYe,aAAa,mBAAmB;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@weavelogic/knowledge-graph-agent",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Knowledge graph agent for Claude Code - generates knowledge graphs, initializes docs, and integrates with claude-flow",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"license": "MIT",
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@anthropic-ai/sdk": "^0.32.0",
|
|
41
|
+
"@modelcontextprotocol/sdk": "^1.25.2",
|
|
41
42
|
"@graphql-tools/schema": "^10.0.0",
|
|
42
43
|
"@tanstack/react-query": "^5.62.0",
|
|
43
44
|
"@tanstack/react-table": "^8.20.0",
|
|
@@ -96,7 +97,7 @@
|
|
|
96
97
|
],
|
|
97
98
|
"repository": {
|
|
98
99
|
"type": "git",
|
|
99
|
-
"url": "https://github.com/weave-logic-ai/
|
|
100
|
+
"url": "https://github.com/weave-logic-ai/knowlege-graph-agent"
|
|
100
101
|
},
|
|
101
102
|
"publishConfig": {
|
|
102
103
|
"access": "public"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"browser2.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
|
package/dist/_virtual/index12.js
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { getAugmentedNamespace } from "./_commonjsHelpers.js";
|
|
2
|
-
import * as index from "../node_modules/onnxruntime-common/dist/lib/index.js";
|
|
3
|
-
const require$$0 = /* @__PURE__ */ getAugmentedNamespace(index);
|
|
4
|
-
export {
|
|
5
|
-
require$$0 as default
|
|
6
|
-
};
|
|
7
|
-
//# sourceMappingURL=index12.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index12.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { getDefaultExportFromCjs } from "./_commonjsHelpers.js";
|
|
2
|
-
import { __require as requireOrtWeb_min } from "../node_modules/onnxruntime-web/dist/ort-web.min.js";
|
|
3
|
-
var ortWeb_minExports = requireOrtWeb_min();
|
|
4
|
-
const ortWeb_min = /* @__PURE__ */ getDefaultExportFromCjs(ortWeb_minExports);
|
|
5
|
-
export {
|
|
6
|
-
ortWeb_min as default
|
|
7
|
-
};
|
|
8
|
-
//# sourceMappingURL=ort-web.min.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ort-web.min.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ort-web.min2.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
var TOKEN_TYPES = Object.freeze({
|
|
2
|
-
Text: "Text",
|
|
3
|
-
// The text between Jinja statements or expressions
|
|
4
|
-
NumericLiteral: "NumericLiteral",
|
|
5
|
-
// e.g., 123
|
|
6
|
-
BooleanLiteral: "BooleanLiteral",
|
|
7
|
-
// true or false
|
|
8
|
-
StringLiteral: "StringLiteral",
|
|
9
|
-
// 'string'
|
|
10
|
-
Identifier: "Identifier",
|
|
11
|
-
// Variables, functions, etc.
|
|
12
|
-
Equals: "Equals",
|
|
13
|
-
// =
|
|
14
|
-
OpenParen: "OpenParen",
|
|
15
|
-
// (
|
|
16
|
-
CloseParen: "CloseParen",
|
|
17
|
-
// )
|
|
18
|
-
OpenStatement: "OpenStatement",
|
|
19
|
-
// {%
|
|
20
|
-
CloseStatement: "CloseStatement",
|
|
21
|
-
// %}
|
|
22
|
-
OpenExpression: "OpenExpression",
|
|
23
|
-
// {{
|
|
24
|
-
CloseExpression: "CloseExpression",
|
|
25
|
-
// }}
|
|
26
|
-
OpenSquareBracket: "OpenSquareBracket",
|
|
27
|
-
// [
|
|
28
|
-
CloseSquareBracket: "CloseSquareBracket",
|
|
29
|
-
// ]
|
|
30
|
-
OpenCurlyBracket: "OpenCurlyBracket",
|
|
31
|
-
// {
|
|
32
|
-
CloseCurlyBracket: "CloseCurlyBracket",
|
|
33
|
-
// }
|
|
34
|
-
Comma: "Comma",
|
|
35
|
-
// ,
|
|
36
|
-
Dot: "Dot",
|
|
37
|
-
// .
|
|
38
|
-
Colon: "Colon",
|
|
39
|
-
// :
|
|
40
|
-
Pipe: "Pipe",
|
|
41
|
-
// |
|
|
42
|
-
CallOperator: "CallOperator",
|
|
43
|
-
// ()
|
|
44
|
-
AdditiveBinaryOperator: "AdditiveBinaryOperator",
|
|
45
|
-
// + -
|
|
46
|
-
MultiplicativeBinaryOperator: "MultiplicativeBinaryOperator",
|
|
47
|
-
// * / %
|
|
48
|
-
ComparisonBinaryOperator: "ComparisonBinaryOperator",
|
|
49
|
-
// < > <= >= == !=
|
|
50
|
-
UnaryOperator: "UnaryOperator",
|
|
51
|
-
// ! - +
|
|
52
|
-
// Keywords
|
|
53
|
-
Set: "Set",
|
|
54
|
-
If: "If",
|
|
55
|
-
For: "For",
|
|
56
|
-
In: "In",
|
|
57
|
-
Is: "Is",
|
|
58
|
-
NotIn: "NotIn",
|
|
59
|
-
Else: "Else",
|
|
60
|
-
EndIf: "EndIf",
|
|
61
|
-
ElseIf: "ElseIf",
|
|
62
|
-
EndFor: "EndFor",
|
|
63
|
-
And: "And",
|
|
64
|
-
Or: "Or",
|
|
65
|
-
Not: "UnaryOperator"
|
|
66
|
-
});
|
|
67
|
-
Object.freeze({
|
|
68
|
-
set: TOKEN_TYPES.Set,
|
|
69
|
-
for: TOKEN_TYPES.For,
|
|
70
|
-
in: TOKEN_TYPES.In,
|
|
71
|
-
is: TOKEN_TYPES.Is,
|
|
72
|
-
if: TOKEN_TYPES.If,
|
|
73
|
-
else: TOKEN_TYPES.Else,
|
|
74
|
-
endif: TOKEN_TYPES.EndIf,
|
|
75
|
-
elif: TOKEN_TYPES.ElseIf,
|
|
76
|
-
endfor: TOKEN_TYPES.EndFor,
|
|
77
|
-
and: TOKEN_TYPES.And,
|
|
78
|
-
or: TOKEN_TYPES.Or,
|
|
79
|
-
not: TOKEN_TYPES.Not,
|
|
80
|
-
"not in": TOKEN_TYPES.NotIn,
|
|
81
|
-
// Literals
|
|
82
|
-
true: TOKEN_TYPES.BooleanLiteral,
|
|
83
|
-
false: TOKEN_TYPES.BooleanLiteral
|
|
84
|
-
});
|
|
85
|
-
[
|
|
86
|
-
// Control sequences
|
|
87
|
-
["{%", TOKEN_TYPES.OpenStatement],
|
|
88
|
-
["%}", TOKEN_TYPES.CloseStatement],
|
|
89
|
-
["{{", TOKEN_TYPES.OpenExpression],
|
|
90
|
-
["}}", TOKEN_TYPES.CloseExpression],
|
|
91
|
-
// Single character tokens
|
|
92
|
-
["(", TOKEN_TYPES.OpenParen],
|
|
93
|
-
[")", TOKEN_TYPES.CloseParen],
|
|
94
|
-
["{", TOKEN_TYPES.OpenCurlyBracket],
|
|
95
|
-
["}", TOKEN_TYPES.CloseCurlyBracket],
|
|
96
|
-
["[", TOKEN_TYPES.OpenSquareBracket],
|
|
97
|
-
["]", TOKEN_TYPES.CloseSquareBracket],
|
|
98
|
-
[",", TOKEN_TYPES.Comma],
|
|
99
|
-
[".", TOKEN_TYPES.Dot],
|
|
100
|
-
[":", TOKEN_TYPES.Colon],
|
|
101
|
-
["|", TOKEN_TYPES.Pipe],
|
|
102
|
-
// Comparison operators
|
|
103
|
-
["<=", TOKEN_TYPES.ComparisonBinaryOperator],
|
|
104
|
-
[">=", TOKEN_TYPES.ComparisonBinaryOperator],
|
|
105
|
-
["==", TOKEN_TYPES.ComparisonBinaryOperator],
|
|
106
|
-
["!=", TOKEN_TYPES.ComparisonBinaryOperator],
|
|
107
|
-
["<", TOKEN_TYPES.ComparisonBinaryOperator],
|
|
108
|
-
[">", TOKEN_TYPES.ComparisonBinaryOperator],
|
|
109
|
-
// Arithmetic operators
|
|
110
|
-
["+", TOKEN_TYPES.AdditiveBinaryOperator],
|
|
111
|
-
["-", TOKEN_TYPES.AdditiveBinaryOperator],
|
|
112
|
-
["*", TOKEN_TYPES.MultiplicativeBinaryOperator],
|
|
113
|
-
["/", TOKEN_TYPES.MultiplicativeBinaryOperator],
|
|
114
|
-
["%", TOKEN_TYPES.MultiplicativeBinaryOperator],
|
|
115
|
-
// Assignment operator
|
|
116
|
-
["=", TOKEN_TYPES.Equals]
|
|
117
|
-
];
|
|
118
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../../node_modules/@huggingface/jinja/dist/index.js"],"sourcesContent":["// src/lexer.ts\nvar TOKEN_TYPES = Object.freeze({\n Text: \"Text\",\n // The text between Jinja statements or expressions\n NumericLiteral: \"NumericLiteral\",\n // e.g., 123\n BooleanLiteral: \"BooleanLiteral\",\n // true or false\n StringLiteral: \"StringLiteral\",\n // 'string'\n Identifier: \"Identifier\",\n // Variables, functions, etc.\n Equals: \"Equals\",\n // =\n OpenParen: \"OpenParen\",\n // (\n CloseParen: \"CloseParen\",\n // )\n OpenStatement: \"OpenStatement\",\n // {%\n CloseStatement: \"CloseStatement\",\n // %}\n OpenExpression: \"OpenExpression\",\n // {{\n CloseExpression: \"CloseExpression\",\n // }}\n OpenSquareBracket: \"OpenSquareBracket\",\n // [\n CloseSquareBracket: \"CloseSquareBracket\",\n // ]\n OpenCurlyBracket: \"OpenCurlyBracket\",\n // {\n CloseCurlyBracket: \"CloseCurlyBracket\",\n // }\n Comma: \"Comma\",\n // ,\n Dot: \"Dot\",\n // .\n Colon: \"Colon\",\n // :\n Pipe: \"Pipe\",\n // |\n CallOperator: \"CallOperator\",\n // ()\n AdditiveBinaryOperator: \"AdditiveBinaryOperator\",\n // + -\n MultiplicativeBinaryOperator: \"MultiplicativeBinaryOperator\",\n // * / %\n ComparisonBinaryOperator: \"ComparisonBinaryOperator\",\n // < > <= >= == !=\n UnaryOperator: \"UnaryOperator\",\n // ! - +\n // Keywords\n Set: \"Set\",\n If: \"If\",\n For: \"For\",\n In: \"In\",\n Is: \"Is\",\n NotIn: \"NotIn\",\n Else: \"Else\",\n EndIf: \"EndIf\",\n ElseIf: \"ElseIf\",\n EndFor: \"EndFor\",\n And: \"And\",\n Or: \"Or\",\n Not: \"UnaryOperator\"\n});\nvar KEYWORDS = Object.freeze({\n set: TOKEN_TYPES.Set,\n for: TOKEN_TYPES.For,\n in: TOKEN_TYPES.In,\n is: TOKEN_TYPES.Is,\n if: TOKEN_TYPES.If,\n else: TOKEN_TYPES.Else,\n endif: TOKEN_TYPES.EndIf,\n elif: TOKEN_TYPES.ElseIf,\n endfor: TOKEN_TYPES.EndFor,\n and: TOKEN_TYPES.And,\n or: TOKEN_TYPES.Or,\n not: TOKEN_TYPES.Not,\n \"not in\": TOKEN_TYPES.NotIn,\n // Literals\n true: TOKEN_TYPES.BooleanLiteral,\n false: TOKEN_TYPES.BooleanLiteral\n});\nvar Token = class {\n /**\n * Constructs a new Token.\n * @param {string} value The raw value as seen inside the source code.\n * @param {TokenType} type The type of token.\n */\n constructor(value, type) {\n this.value = value;\n this.type = type;\n }\n};\nfunction isWord(char) {\n return /\\w/.test(char);\n}\nfunction isInteger(char) {\n return /[0-9]/.test(char);\n}\nvar ORDERED_MAPPING_TABLE = [\n // Control sequences\n [\"{%\", TOKEN_TYPES.OpenStatement],\n [\"%}\", TOKEN_TYPES.CloseStatement],\n [\"{{\", TOKEN_TYPES.OpenExpression],\n [\"}}\", TOKEN_TYPES.CloseExpression],\n // Single character tokens\n [\"(\", TOKEN_TYPES.OpenParen],\n [\")\", TOKEN_TYPES.CloseParen],\n [\"{\", TOKEN_TYPES.OpenCurlyBracket],\n [\"}\", TOKEN_TYPES.CloseCurlyBracket],\n [\"[\", TOKEN_TYPES.OpenSquareBracket],\n [\"]\", TOKEN_TYPES.CloseSquareBracket],\n [\",\", TOKEN_TYPES.Comma],\n [\".\", TOKEN_TYPES.Dot],\n [\":\", TOKEN_TYPES.Colon],\n [\"|\", TOKEN_TYPES.Pipe],\n // Comparison operators\n [\"<=\", TOKEN_TYPES.ComparisonBinaryOperator],\n [\">=\", TOKEN_TYPES.ComparisonBinaryOperator],\n [\"==\", TOKEN_TYPES.ComparisonBinaryOperator],\n [\"!=\", TOKEN_TYPES.ComparisonBinaryOperator],\n [\"<\", TOKEN_TYPES.ComparisonBinaryOperator],\n [\">\", TOKEN_TYPES.ComparisonBinaryOperator],\n // Arithmetic operators\n [\"+\", TOKEN_TYPES.AdditiveBinaryOperator],\n [\"-\", TOKEN_TYPES.AdditiveBinaryOperator],\n [\"*\", TOKEN_TYPES.MultiplicativeBinaryOperator],\n [\"/\", TOKEN_TYPES.MultiplicativeBinaryOperator],\n [\"%\", TOKEN_TYPES.MultiplicativeBinaryOperator],\n // Assignment operator\n [\"=\", TOKEN_TYPES.Equals]\n];\nvar ESCAPE_CHARACTERS = /* @__PURE__ */ new Map([\n [\"n\", \"\\n\"],\n // New line\n [\"t\", \"\t\"],\n // Horizontal tab\n [\"r\", \"\\r\"],\n // Carriage return\n [\"b\", \"\\b\"],\n // Backspace\n [\"f\", \"\\f\"],\n // Form feed\n [\"v\", \"\\v\"],\n // Vertical tab\n [\"'\", \"'\"],\n // Single quote\n ['\"', '\"'],\n // Double quote\n [\"\\\\\", \"\\\\\"]\n // Backslash\n]);\nfunction preprocess(template, options = {}) {\n if (template.endsWith(\"\\n\")) {\n template = template.slice(0, -1);\n }\n template = template.replace(/{#.*?#}/gs, \"{##}\");\n if (options.lstrip_blocks) {\n template = template.replace(/^[ \\t]*({[#%])/gm, \"$1\");\n }\n if (options.trim_blocks) {\n template = template.replace(/([#%]})\\n/g, \"$1\");\n }\n return template.replace(/{##}/g, \"\").replace(/-%}\\s*/g, \"%}\").replace(/\\s*{%-/g, \"{%\").replace(/-}}\\s*/g, \"}}\").replace(/\\s*{{-/g, \"{{\");\n}\nfunction tokenize(source, options = {}) {\n const tokens = [];\n const src = preprocess(source, options);\n let cursorPosition = 0;\n const consumeWhile = (predicate) => {\n let str = \"\";\n while (predicate(src[cursorPosition])) {\n if (src[cursorPosition] === \"\\\\\") {\n ++cursorPosition;\n if (cursorPosition >= src.length)\n throw new SyntaxError(\"Unexpected end of input\");\n const escaped = src[cursorPosition++];\n const unescaped = ESCAPE_CHARACTERS.get(escaped);\n if (unescaped === void 0) {\n throw new SyntaxError(`Unexpected escaped character: ${escaped}`);\n }\n str += unescaped;\n continue;\n }\n str += src[cursorPosition++];\n if (cursorPosition >= src.length)\n throw new SyntaxError(\"Unexpected end of input\");\n }\n return str;\n };\n main:\n while (cursorPosition < src.length) {\n const lastTokenType = tokens.at(-1)?.type;\n if (lastTokenType === void 0 || lastTokenType === TOKEN_TYPES.CloseStatement || lastTokenType === TOKEN_TYPES.CloseExpression) {\n let text = \"\";\n while (cursorPosition < src.length && // Keep going until we hit the next Jinja statement or expression\n !(src[cursorPosition] === \"{\" && (src[cursorPosition + 1] === \"%\" || src[cursorPosition + 1] === \"{\"))) {\n text += src[cursorPosition++];\n }\n if (text.length > 0) {\n tokens.push(new Token(text, TOKEN_TYPES.Text));\n continue;\n }\n }\n consumeWhile((char2) => /\\s/.test(char2));\n const char = src[cursorPosition];\n if (char === \"-\" || char === \"+\") {\n const lastTokenType2 = tokens.at(-1)?.type;\n if (lastTokenType2 === TOKEN_TYPES.Text || lastTokenType2 === void 0) {\n throw new SyntaxError(`Unexpected character: ${char}`);\n }\n switch (lastTokenType2) {\n case TOKEN_TYPES.Identifier:\n case TOKEN_TYPES.NumericLiteral:\n case TOKEN_TYPES.BooleanLiteral:\n case TOKEN_TYPES.StringLiteral:\n case TOKEN_TYPES.CloseParen:\n case TOKEN_TYPES.CloseSquareBracket:\n break;\n default: {\n ++cursorPosition;\n const num = consumeWhile(isInteger);\n tokens.push(\n new Token(`${char}${num}`, num.length > 0 ? TOKEN_TYPES.NumericLiteral : TOKEN_TYPES.UnaryOperator)\n );\n continue;\n }\n }\n }\n for (const [char2, token] of ORDERED_MAPPING_TABLE) {\n const slice2 = src.slice(cursorPosition, cursorPosition + char2.length);\n if (slice2 === char2) {\n tokens.push(new Token(char2, token));\n cursorPosition += char2.length;\n continue main;\n }\n }\n if (char === \"'\" || char === '\"') {\n ++cursorPosition;\n const str = consumeWhile((c) => c !== char);\n tokens.push(new Token(str, TOKEN_TYPES.StringLiteral));\n ++cursorPosition;\n continue;\n }\n if (isInteger(char)) {\n const num = consumeWhile(isInteger);\n tokens.push(new Token(num, TOKEN_TYPES.NumericLiteral));\n continue;\n }\n if (isWord(char)) {\n const word = consumeWhile(isWord);\n const type = Object.hasOwn(KEYWORDS, word) ? KEYWORDS[word] : TOKEN_TYPES.Identifier;\n if (type === TOKEN_TYPES.In && tokens.at(-1)?.type === TOKEN_TYPES.Not) {\n tokens.pop();\n tokens.push(new Token(\"not in\", TOKEN_TYPES.NotIn));\n } else {\n tokens.push(new Token(word, type));\n }\n continue;\n }\n throw new SyntaxError(`Unexpected character: ${char}`);\n }\n return tokens;\n}\n\n// src/ast.ts\nvar Statement = class {\n type = \"Statement\";\n};\nvar Program = class extends Statement {\n constructor(body) {\n super();\n this.body = body;\n }\n type = \"Program\";\n};\nvar If = class extends Statement {\n constructor(test, body, alternate) {\n super();\n this.test = test;\n this.body = body;\n this.alternate = alternate;\n }\n type = \"If\";\n};\nvar For = class extends Statement {\n constructor(loopvar, iterable, body) {\n super();\n this.loopvar = loopvar;\n this.iterable = iterable;\n this.body = body;\n }\n type = \"For\";\n};\nvar SetStatement = class extends Statement {\n constructor(assignee, value) {\n super();\n this.assignee = assignee;\n this.value = value;\n }\n type = \"Set\";\n};\nvar Expression = class extends Statement {\n type = \"Expression\";\n};\nvar MemberExpression = class extends Expression {\n constructor(object, property, computed) {\n super();\n this.object = object;\n this.property = property;\n this.computed = computed;\n }\n type = \"MemberExpression\";\n};\nvar CallExpression = class extends Expression {\n constructor(callee, args) {\n super();\n this.callee = callee;\n this.args = args;\n }\n type = \"CallExpression\";\n};\nvar Identifier = class extends Expression {\n /**\n * @param {string} value The name of the identifier\n */\n constructor(value) {\n super();\n this.value = value;\n }\n type = \"Identifier\";\n};\nvar Literal = class extends Expression {\n constructor(value) {\n super();\n this.value = value;\n }\n type = \"Literal\";\n};\nvar NumericLiteral = class extends Literal {\n type = \"NumericLiteral\";\n};\nvar StringLiteral = class extends Literal {\n type = \"StringLiteral\";\n};\nvar BooleanLiteral = class extends Literal {\n type = \"BooleanLiteral\";\n};\nvar ArrayLiteral = class extends Literal {\n type = \"ArrayLiteral\";\n};\nvar TupleLiteral = class extends Literal {\n type = \"TupleLiteral\";\n};\nvar ObjectLiteral = class extends Literal {\n type = \"ObjectLiteral\";\n};\nvar BinaryExpression = class extends Expression {\n constructor(operator, left, right) {\n super();\n this.operator = operator;\n this.left = left;\n this.right = right;\n }\n type = \"BinaryExpression\";\n};\nvar FilterExpression = class extends Expression {\n constructor(operand, filter) {\n super();\n this.operand = operand;\n this.filter = filter;\n }\n type = \"FilterExpression\";\n};\nvar TestExpression = class extends Expression {\n constructor(operand, negate, test) {\n super();\n this.operand = operand;\n this.negate = negate;\n this.test = test;\n }\n type = \"TestExpression\";\n};\nvar UnaryExpression = class extends Expression {\n constructor(operator, argument) {\n super();\n this.operator = operator;\n this.argument = argument;\n }\n type = \"UnaryExpression\";\n};\nvar SliceExpression = class extends Expression {\n constructor(start = void 0, stop = void 0, step = void 0) {\n super();\n this.start = start;\n this.stop = stop;\n this.step = step;\n }\n type = \"SliceExpression\";\n};\nvar KeywordArgumentExpression = class extends Expression {\n constructor(key, value) {\n super();\n this.key = key;\n this.value = value;\n }\n type = \"KeywordArgumentExpression\";\n};\n\n// src/parser.ts\nfunction parse(tokens) {\n const program = new Program([]);\n let current = 0;\n function expect(type, error) {\n const prev = tokens[current++];\n if (!prev || prev.type !== type) {\n throw new Error(`Parser Error: ${error}. ${prev.type} !== ${type}.`);\n }\n return prev;\n }\n function parseAny() {\n switch (tokens[current].type) {\n case TOKEN_TYPES.Text:\n return parseText();\n case TOKEN_TYPES.OpenStatement:\n return parseJinjaStatement();\n case TOKEN_TYPES.OpenExpression:\n return parseJinjaExpression();\n default:\n throw new SyntaxError(`Unexpected token type: ${tokens[current].type}`);\n }\n }\n function not(...types) {\n return current + types.length <= tokens.length && types.some((type, i) => type !== tokens[current + i].type);\n }\n function is(...types) {\n return current + types.length <= tokens.length && types.every((type, i) => type === tokens[current + i].type);\n }\n function parseText() {\n return new StringLiteral(expect(TOKEN_TYPES.Text, \"Expected text token\").value);\n }\n function parseJinjaStatement() {\n expect(TOKEN_TYPES.OpenStatement, \"Expected opening statement token\");\n let result;\n switch (tokens[current].type) {\n case TOKEN_TYPES.Set:\n ++current;\n result = parseSetStatement();\n expect(TOKEN_TYPES.CloseStatement, \"Expected closing statement token\");\n break;\n case TOKEN_TYPES.If:\n ++current;\n result = parseIfStatement();\n expect(TOKEN_TYPES.OpenStatement, \"Expected {% token\");\n expect(TOKEN_TYPES.EndIf, \"Expected endif token\");\n expect(TOKEN_TYPES.CloseStatement, \"Expected %} token\");\n break;\n case TOKEN_TYPES.For:\n ++current;\n result = parseForStatement();\n expect(TOKEN_TYPES.OpenStatement, \"Expected {% token\");\n expect(TOKEN_TYPES.EndFor, \"Expected endfor token\");\n expect(TOKEN_TYPES.CloseStatement, \"Expected %} token\");\n break;\n default:\n throw new SyntaxError(`Unknown statement type: ${tokens[current].type}`);\n }\n return result;\n }\n function parseJinjaExpression() {\n expect(TOKEN_TYPES.OpenExpression, \"Expected opening expression token\");\n const result = parseExpression();\n expect(TOKEN_TYPES.CloseExpression, \"Expected closing expression token\");\n return result;\n }\n function parseSetStatement() {\n const left = parseExpression();\n if (is(TOKEN_TYPES.Equals)) {\n ++current;\n const value = parseSetStatement();\n return new SetStatement(left, value);\n }\n return left;\n }\n function parseIfStatement() {\n const test = parseExpression();\n expect(TOKEN_TYPES.CloseStatement, \"Expected closing statement token\");\n const body = [];\n const alternate = [];\n while (!(tokens[current]?.type === TOKEN_TYPES.OpenStatement && (tokens[current + 1]?.type === TOKEN_TYPES.ElseIf || tokens[current + 1]?.type === TOKEN_TYPES.Else || tokens[current + 1]?.type === TOKEN_TYPES.EndIf))) {\n body.push(parseAny());\n }\n if (tokens[current]?.type === TOKEN_TYPES.OpenStatement && tokens[current + 1]?.type !== TOKEN_TYPES.EndIf) {\n ++current;\n if (is(TOKEN_TYPES.ElseIf)) {\n expect(TOKEN_TYPES.ElseIf, \"Expected elseif token\");\n alternate.push(parseIfStatement());\n } else {\n expect(TOKEN_TYPES.Else, \"Expected else token\");\n expect(TOKEN_TYPES.CloseStatement, \"Expected closing statement token\");\n while (!(tokens[current]?.type === TOKEN_TYPES.OpenStatement && tokens[current + 1]?.type === TOKEN_TYPES.EndIf)) {\n alternate.push(parseAny());\n }\n }\n }\n return new If(test, body, alternate);\n }\n function parseExpressionSequence(primary = false) {\n const fn = primary ? parsePrimaryExpression : parseExpression;\n const expressions = [fn()];\n const isTuple = is(TOKEN_TYPES.Comma);\n while (isTuple) {\n ++current;\n expressions.push(fn());\n if (!is(TOKEN_TYPES.Comma)) {\n break;\n }\n }\n return isTuple ? new TupleLiteral(expressions) : expressions[0];\n }\n function parseForStatement() {\n const loopVariable = parseExpressionSequence(true);\n if (!(loopVariable instanceof Identifier || loopVariable instanceof TupleLiteral)) {\n throw new SyntaxError(`Expected identifier/tuple for the loop variable, got ${loopVariable.type} instead`);\n }\n expect(TOKEN_TYPES.In, \"Expected `in` keyword following loop variable\");\n const iterable = parseExpression();\n expect(TOKEN_TYPES.CloseStatement, \"Expected closing statement token\");\n const body = [];\n while (not(TOKEN_TYPES.OpenStatement, TOKEN_TYPES.EndFor)) {\n body.push(parseAny());\n }\n return new For(loopVariable, iterable, body);\n }\n function parseExpression() {\n return parseTernaryExpression();\n }\n function parseTernaryExpression() {\n const a = parseLogicalOrExpression();\n if (is(TOKEN_TYPES.If)) {\n ++current;\n const predicate = parseLogicalOrExpression();\n expect(TOKEN_TYPES.Else, \"Expected else token\");\n const b = parseLogicalOrExpression();\n return new If(predicate, [a], [b]);\n }\n return a;\n }\n function parseLogicalOrExpression() {\n let left = parseLogicalAndExpression();\n while (is(TOKEN_TYPES.Or)) {\n const operator = tokens[current];\n ++current;\n const right = parseLogicalAndExpression();\n left = new BinaryExpression(operator, left, right);\n }\n return left;\n }\n function parseLogicalAndExpression() {\n let left = parseLogicalNegationExpression();\n while (is(TOKEN_TYPES.And)) {\n const operator = tokens[current];\n ++current;\n const right = parseLogicalNegationExpression();\n left = new BinaryExpression(operator, left, right);\n }\n return left;\n }\n function parseLogicalNegationExpression() {\n let right;\n while (is(TOKEN_TYPES.Not)) {\n const operator = tokens[current];\n ++current;\n const arg = parseLogicalNegationExpression();\n right = new UnaryExpression(operator, arg);\n }\n return right ?? parseComparisonExpression();\n }\n function parseComparisonExpression() {\n let left = parseAdditiveExpression();\n while (is(TOKEN_TYPES.ComparisonBinaryOperator) || is(TOKEN_TYPES.In) || is(TOKEN_TYPES.NotIn)) {\n const operator = tokens[current];\n ++current;\n const right = parseAdditiveExpression();\n left = new BinaryExpression(operator, left, right);\n }\n return left;\n }\n function parseAdditiveExpression() {\n let left = parseMultiplicativeExpression();\n while (is(TOKEN_TYPES.AdditiveBinaryOperator)) {\n const operator = tokens[current];\n ++current;\n const right = parseMultiplicativeExpression();\n left = new BinaryExpression(operator, left, right);\n }\n return left;\n }\n function parseCallMemberExpression() {\n const member = parseMemberExpression();\n if (is(TOKEN_TYPES.OpenParen)) {\n return parseCallExpression(member);\n }\n return member;\n }\n function parseCallExpression(callee) {\n let callExpression = new CallExpression(callee, parseArgs());\n if (is(TOKEN_TYPES.OpenParen)) {\n callExpression = parseCallExpression(callExpression);\n }\n return callExpression;\n }\n function parseArgs() {\n expect(TOKEN_TYPES.OpenParen, \"Expected opening parenthesis for arguments list\");\n const args = parseArgumentsList();\n expect(TOKEN_TYPES.CloseParen, \"Expected closing parenthesis for arguments list\");\n return args;\n }\n function parseArgumentsList() {\n const args = [];\n while (!is(TOKEN_TYPES.CloseParen)) {\n let argument = parseExpression();\n if (is(TOKEN_TYPES.Equals)) {\n ++current;\n if (!(argument instanceof Identifier)) {\n throw new SyntaxError(`Expected identifier for keyword argument`);\n }\n const value = parseExpression();\n argument = new KeywordArgumentExpression(argument, value);\n }\n args.push(argument);\n if (is(TOKEN_TYPES.Comma)) {\n ++current;\n }\n }\n return args;\n }\n function parseMemberExpressionArgumentsList() {\n const slices = [];\n let isSlice = false;\n while (!is(TOKEN_TYPES.CloseSquareBracket)) {\n if (is(TOKEN_TYPES.Colon)) {\n slices.push(void 0);\n ++current;\n isSlice = true;\n } else {\n slices.push(parseExpression());\n if (is(TOKEN_TYPES.Colon)) {\n ++current;\n isSlice = true;\n }\n }\n }\n if (slices.length === 0) {\n throw new SyntaxError(`Expected at least one argument for member/slice expression`);\n }\n if (isSlice) {\n if (slices.length > 3) {\n throw new SyntaxError(`Expected 0-3 arguments for slice expression`);\n }\n return new SliceExpression(...slices);\n }\n return slices[0];\n }\n function parseMemberExpression() {\n let object = parsePrimaryExpression();\n while (is(TOKEN_TYPES.Dot) || is(TOKEN_TYPES.OpenSquareBracket)) {\n const operator = tokens[current];\n ++current;\n let property;\n const computed = operator.type !== TOKEN_TYPES.Dot;\n if (computed) {\n property = parseMemberExpressionArgumentsList();\n expect(TOKEN_TYPES.CloseSquareBracket, \"Expected closing square bracket\");\n } else {\n property = parsePrimaryExpression();\n if (property.type !== \"Identifier\") {\n throw new SyntaxError(`Expected identifier following dot operator`);\n }\n }\n object = new MemberExpression(object, property, computed);\n }\n return object;\n }\n function parseMultiplicativeExpression() {\n let left = parseTestExpression();\n while (is(TOKEN_TYPES.MultiplicativeBinaryOperator)) {\n const operator = tokens[current];\n ++current;\n const right = parseTestExpression();\n left = new BinaryExpression(operator, left, right);\n }\n return left;\n }\n function parseTestExpression() {\n let operand = parseFilterExpression();\n while (is(TOKEN_TYPES.Is)) {\n ++current;\n const negate = is(TOKEN_TYPES.Not);\n if (negate) {\n ++current;\n }\n let filter = parsePrimaryExpression();\n if (filter instanceof BooleanLiteral) {\n filter = new Identifier(filter.value.toString());\n }\n if (!(filter instanceof Identifier)) {\n throw new SyntaxError(`Expected identifier for the test`);\n }\n operand = new TestExpression(operand, negate, filter);\n }\n return operand;\n }\n function parseFilterExpression() {\n let operand = parseCallMemberExpression();\n while (is(TOKEN_TYPES.Pipe)) {\n ++current;\n let filter = parsePrimaryExpression();\n if (!(filter instanceof Identifier)) {\n throw new SyntaxError(`Expected identifier for the filter`);\n }\n if (is(TOKEN_TYPES.OpenParen)) {\n filter = parseCallExpression(filter);\n }\n operand = new FilterExpression(operand, filter);\n }\n return operand;\n }\n function parsePrimaryExpression() {\n const token = tokens[current];\n switch (token.type) {\n case TOKEN_TYPES.NumericLiteral:\n ++current;\n return new NumericLiteral(Number(token.value));\n case TOKEN_TYPES.StringLiteral:\n ++current;\n return new StringLiteral(token.value);\n case TOKEN_TYPES.BooleanLiteral:\n ++current;\n return new BooleanLiteral(token.value === \"true\");\n case TOKEN_TYPES.Identifier:\n ++current;\n return new Identifier(token.value);\n case TOKEN_TYPES.OpenParen: {\n ++current;\n const expression = parseExpressionSequence();\n if (tokens[current].type !== TOKEN_TYPES.CloseParen) {\n throw new SyntaxError(`Expected closing parenthesis, got ${tokens[current].type} instead`);\n }\n ++current;\n return expression;\n }\n case TOKEN_TYPES.OpenSquareBracket: {\n ++current;\n const values = [];\n while (!is(TOKEN_TYPES.CloseSquareBracket)) {\n values.push(parseExpression());\n if (is(TOKEN_TYPES.Comma)) {\n ++current;\n }\n }\n ++current;\n return new ArrayLiteral(values);\n }\n case TOKEN_TYPES.OpenCurlyBracket: {\n ++current;\n const values = /* @__PURE__ */ new Map();\n while (!is(TOKEN_TYPES.CloseCurlyBracket)) {\n const key = parseExpression();\n expect(TOKEN_TYPES.Colon, \"Expected colon between key and value in object literal\");\n const value = parseExpression();\n values.set(key, value);\n if (is(TOKEN_TYPES.Comma)) {\n ++current;\n }\n }\n ++current;\n return new ObjectLiteral(values);\n }\n default:\n throw new SyntaxError(`Unexpected token: ${token.type}`);\n }\n }\n while (current < tokens.length) {\n program.body.push(parseAny());\n }\n return program;\n}\n\n// src/utils.ts\nfunction range(start, stop, step = 1) {\n if (stop === void 0) {\n stop = start;\n start = 0;\n }\n const result = [];\n for (let i = start; i < stop; i += step) {\n result.push(i);\n }\n return result;\n}\nfunction slice(array, start, stop, step = 1) {\n const direction = Math.sign(step);\n if (direction >= 0) {\n start = (start ??= 0) < 0 ? Math.max(array.length + start, 0) : Math.min(start, array.length);\n stop = (stop ??= array.length) < 0 ? Math.max(array.length + stop, 0) : Math.min(stop, array.length);\n } else {\n start = (start ??= array.length - 1) < 0 ? Math.max(array.length + start, -1) : Math.min(start, array.length - 1);\n stop = (stop ??= -1) < -1 ? Math.max(array.length + stop, -1) : Math.min(stop, array.length - 1);\n }\n const result = [];\n for (let i = start; direction * i < direction * stop; i += step) {\n result.push(array[i]);\n }\n return result;\n}\nfunction titleCase(value) {\n return value.replace(/\\b\\w/g, (c) => c.toUpperCase());\n}\n\n// src/runtime.ts\nvar RuntimeValue = class {\n type = \"RuntimeValue\";\n value;\n /**\n * A collection of built-in functions for this type.\n */\n builtins = /* @__PURE__ */ new Map();\n /**\n * Creates a new RuntimeValue.\n */\n constructor(value = void 0) {\n this.value = value;\n }\n /**\n * Determines truthiness or falsiness of the runtime value.\n * This function should be overridden by subclasses if it has custom truthiness criteria.\n * @returns {BooleanValue} BooleanValue(true) if the value is truthy, BooleanValue(false) otherwise.\n */\n __bool__() {\n return new BooleanValue(!!this.value);\n }\n};\nvar NumericValue = class extends RuntimeValue {\n type = \"NumericValue\";\n};\nvar StringValue = class extends RuntimeValue {\n type = \"StringValue\";\n builtins = /* @__PURE__ */ new Map([\n [\n \"upper\",\n new FunctionValue(() => {\n return new StringValue(this.value.toUpperCase());\n })\n ],\n [\n \"lower\",\n new FunctionValue(() => {\n return new StringValue(this.value.toLowerCase());\n })\n ],\n [\n \"strip\",\n new FunctionValue(() => {\n return new StringValue(this.value.trim());\n })\n ],\n [\n \"title\",\n new FunctionValue(() => {\n return new StringValue(titleCase(this.value));\n })\n ],\n [\"length\", new NumericValue(this.value.length)]\n ]);\n};\nvar BooleanValue = class extends RuntimeValue {\n type = \"BooleanValue\";\n};\nvar ObjectValue = class extends RuntimeValue {\n type = \"ObjectValue\";\n /**\n * NOTE: necessary to override since all JavaScript arrays are considered truthy,\n * while only non-empty Python arrays are consider truthy.\n *\n * e.g.,\n * - JavaScript: {} && 5 -> 5\n * - Python: {} and 5 -> {}\n */\n __bool__() {\n return new BooleanValue(this.value.size > 0);\n }\n builtins = /* @__PURE__ */ new Map([\n [\n \"get\",\n new FunctionValue(([key, defaultValue]) => {\n if (!(key instanceof StringValue)) {\n throw new Error(`Object key must be a string: got ${key.type}`);\n }\n return this.value.get(key.value) ?? defaultValue ?? new NullValue();\n })\n ],\n [\n \"items\",\n new FunctionValue(() => {\n return new ArrayValue(\n Array.from(this.value.entries()).map(([key, value]) => new ArrayValue([new StringValue(key), value]))\n );\n })\n ]\n ]);\n};\nvar ArrayValue = class extends RuntimeValue {\n type = \"ArrayValue\";\n builtins = /* @__PURE__ */ new Map([[\"length\", new NumericValue(this.value.length)]]);\n /**\n * NOTE: necessary to override since all JavaScript arrays are considered truthy,\n * while only non-empty Python arrays are consider truthy.\n *\n * e.g.,\n * - JavaScript: [] && 5 -> 5\n * - Python: [] and 5 -> []\n */\n __bool__() {\n return new BooleanValue(this.value.length > 0);\n }\n};\nvar TupleValue = class extends ArrayValue {\n type = \"TupleValue\";\n};\nvar FunctionValue = class extends RuntimeValue {\n type = \"FunctionValue\";\n};\nvar NullValue = class extends RuntimeValue {\n type = \"NullValue\";\n};\nvar UndefinedValue = class extends RuntimeValue {\n type = \"UndefinedValue\";\n};\nvar Environment = class {\n constructor(parent) {\n this.parent = parent;\n }\n /**\n * The variables declared in this environment.\n */\n variables = /* @__PURE__ */ new Map([\n [\n \"namespace\",\n new FunctionValue((args) => {\n if (args.length === 0) {\n return new ObjectValue(/* @__PURE__ */ new Map());\n }\n if (args.length !== 1 || !(args[0] instanceof ObjectValue)) {\n throw new Error(\"`namespace` expects either zero arguments or a single object argument\");\n }\n return args[0];\n })\n ]\n ]);\n /**\n * The tests available in this environment.\n */\n tests = /* @__PURE__ */ new Map([\n [\"boolean\", (operand) => operand.type === \"BooleanValue\"],\n [\"callable\", (operand) => operand instanceof FunctionValue],\n [\n \"odd\",\n (operand) => {\n if (operand.type !== \"NumericValue\") {\n throw new Error(`Cannot apply test \"odd\" to type: ${operand.type}`);\n }\n return operand.value % 2 !== 0;\n }\n ],\n [\n \"even\",\n (operand) => {\n if (operand.type !== \"NumericValue\") {\n throw new Error(`Cannot apply test \"even\" to type: ${operand.type}`);\n }\n return operand.value % 2 === 0;\n }\n ],\n [\"false\", (operand) => operand.type === \"BooleanValue\" && !operand.value],\n [\"true\", (operand) => operand.type === \"BooleanValue\" && operand.value],\n [\"number\", (operand) => operand.type === \"NumericValue\"],\n [\"integer\", (operand) => operand.type === \"NumericValue\" && Number.isInteger(operand.value)],\n [\"iterable\", (operand) => operand instanceof ArrayValue || operand instanceof StringValue],\n [\n \"lower\",\n (operand) => {\n const str = operand.value;\n return operand.type === \"StringValue\" && str === str.toLowerCase();\n }\n ],\n [\n \"upper\",\n (operand) => {\n const str = operand.value;\n return operand.type === \"StringValue\" && str === str.toUpperCase();\n }\n ],\n [\"none\", (operand) => operand.type === \"NullValue\"],\n [\"defined\", (operand) => operand.type !== \"UndefinedValue\"],\n [\"undefined\", (operand) => operand.type === \"UndefinedValue\"],\n [\"equalto\", (a, b) => a.value === b.value]\n ]);\n /**\n * Set the value of a variable in the current environment.\n */\n set(name, value) {\n return this.declareVariable(name, convertToRuntimeValues(value));\n }\n declareVariable(name, value) {\n if (this.variables.has(name)) {\n throw new SyntaxError(`Variable already declared: ${name}`);\n }\n this.variables.set(name, value);\n return value;\n }\n // private assignVariable(name: string, value: AnyRuntimeValue): AnyRuntimeValue {\n // \tconst env = this.resolve(name);\n // \tenv.variables.set(name, value);\n // \treturn value;\n // }\n /**\n * Set variable in the current scope.\n * See https://jinja.palletsprojects.com/en/3.0.x/templates/#assignments for more information.\n */\n setVariable(name, value) {\n this.variables.set(name, value);\n return value;\n }\n /**\n * Resolve the environment in which the variable is declared.\n * @param {string} name The name of the variable.\n * @returns {Environment} The environment in which the variable is declared.\n */\n resolve(name) {\n if (this.variables.has(name)) {\n return this;\n }\n if (this.parent) {\n return this.parent.resolve(name);\n }\n throw new Error(`Unknown variable: ${name}`);\n }\n lookupVariable(name) {\n try {\n return this.resolve(name).variables.get(name) ?? new UndefinedValue();\n } catch {\n return new UndefinedValue();\n }\n }\n};\nvar Interpreter = class {\n global;\n constructor(env) {\n this.global = env ?? new Environment();\n }\n /**\n * Run the program.\n */\n run(program) {\n return this.evaluate(program, this.global);\n }\n /**\n * Evaluates expressions following the binary operation type.\n */\n evaluateBinaryExpression(node, environment) {\n const left = this.evaluate(node.left, environment);\n switch (node.operator.value) {\n case \"and\":\n return left.__bool__().value ? this.evaluate(node.right, environment) : left;\n case \"or\":\n return left.__bool__().value ? left : this.evaluate(node.right, environment);\n }\n const right = this.evaluate(node.right, environment);\n switch (node.operator.value) {\n case \"==\":\n return new BooleanValue(left.value == right.value);\n case \"!=\":\n return new BooleanValue(left.value != right.value);\n }\n if (left instanceof UndefinedValue || right instanceof UndefinedValue) {\n throw new Error(\"Cannot perform operation on undefined values\");\n } else if (left instanceof NullValue || right instanceof NullValue) {\n throw new Error(\"Cannot perform operation on null values\");\n } else if (left instanceof NumericValue && right instanceof NumericValue) {\n switch (node.operator.value) {\n case \"+\":\n return new NumericValue(left.value + right.value);\n case \"-\":\n return new NumericValue(left.value - right.value);\n case \"*\":\n return new NumericValue(left.value * right.value);\n case \"/\":\n return new NumericValue(left.value / right.value);\n case \"%\":\n return new NumericValue(left.value % right.value);\n case \"<\":\n return new BooleanValue(left.value < right.value);\n case \">\":\n return new BooleanValue(left.value > right.value);\n case \">=\":\n return new BooleanValue(left.value >= right.value);\n case \"<=\":\n return new BooleanValue(left.value <= right.value);\n }\n } else if (left instanceof ArrayValue && right instanceof ArrayValue) {\n switch (node.operator.value) {\n case \"+\":\n return new ArrayValue(left.value.concat(right.value));\n }\n } else if (right instanceof ArrayValue) {\n const member = right.value.find((x) => x.value === left.value) !== void 0;\n switch (node.operator.value) {\n case \"in\":\n return new BooleanValue(member);\n case \"not in\":\n return new BooleanValue(!member);\n }\n }\n if (left instanceof StringValue || right instanceof StringValue) {\n switch (node.operator.value) {\n case \"+\":\n return new StringValue(left.value.toString() + right.value.toString());\n }\n }\n if (left instanceof StringValue && right instanceof StringValue) {\n switch (node.operator.value) {\n case \"in\":\n return new BooleanValue(right.value.includes(left.value));\n case \"not in\":\n return new BooleanValue(!right.value.includes(left.value));\n }\n }\n if (left instanceof StringValue && right instanceof ObjectValue) {\n switch (node.operator.value) {\n case \"in\":\n return new BooleanValue(right.value.has(left.value));\n case \"not in\":\n return new BooleanValue(!right.value.has(left.value));\n }\n }\n throw new SyntaxError(`Unknown operator \"${node.operator.value}\" between ${left.type} and ${right.type}`);\n }\n /**\n * Evaluates expressions following the filter operation type.\n */\n evaluateFilterExpression(node, environment) {\n const operand = this.evaluate(node.operand, environment);\n if (node.filter.type === \"Identifier\") {\n const filter = node.filter;\n if (operand instanceof ArrayValue) {\n switch (filter.value) {\n case \"list\":\n return operand;\n case \"first\":\n return operand.value[0];\n case \"last\":\n return operand.value[operand.value.length - 1];\n case \"length\":\n return new NumericValue(operand.value.length);\n case \"reverse\":\n return new ArrayValue(operand.value.reverse());\n case \"sort\":\n return new ArrayValue(\n operand.value.sort((a, b) => {\n if (a.type !== b.type) {\n throw new Error(`Cannot compare different types: ${a.type} and ${b.type}`);\n }\n switch (a.type) {\n case \"NumericValue\":\n return a.value - b.value;\n case \"StringValue\":\n return a.value.localeCompare(b.value);\n default:\n throw new Error(`Cannot compare type: ${a.type}`);\n }\n })\n );\n default:\n throw new Error(`Unknown ArrayValue filter: ${filter.value}`);\n }\n } else if (operand instanceof StringValue) {\n switch (filter.value) {\n case \"length\":\n return new NumericValue(operand.value.length);\n case \"upper\":\n return new StringValue(operand.value.toUpperCase());\n case \"lower\":\n return new StringValue(operand.value.toLowerCase());\n case \"title\":\n return new StringValue(titleCase(operand.value));\n case \"capitalize\":\n return new StringValue(operand.value.charAt(0).toUpperCase() + operand.value.slice(1));\n case \"trim\":\n return new StringValue(operand.value.trim());\n default:\n throw new Error(`Unknown StringValue filter: ${filter.value}`);\n }\n } else if (operand instanceof NumericValue) {\n switch (filter.value) {\n case \"abs\":\n return new NumericValue(Math.abs(operand.value));\n default:\n throw new Error(`Unknown NumericValue filter: ${filter.value}`);\n }\n } else if (operand instanceof ObjectValue) {\n switch (filter.value) {\n case \"items\":\n return new ArrayValue(\n Array.from(operand.value.entries()).map(([key, value]) => new ArrayValue([new StringValue(key), value]))\n );\n case \"length\":\n return new NumericValue(operand.value.size);\n default:\n throw new Error(`Unknown ObjectValue filter: ${filter.value}`);\n }\n }\n throw new Error(`Cannot apply filter \"${filter.value}\" to type: ${operand.type}`);\n } else if (node.filter.type === \"CallExpression\") {\n const filter = node.filter;\n if (filter.callee.type !== \"Identifier\") {\n throw new Error(`Unknown filter: ${filter.callee.type}`);\n }\n const filterName = filter.callee.value;\n if (operand instanceof ArrayValue) {\n switch (filterName) {\n case \"selectattr\": {\n if (operand.value.some((x) => !(x instanceof ObjectValue))) {\n throw new Error(\"`selectattr` can only be applied to array of objects\");\n }\n if (filter.args.some((x) => x.type !== \"StringLiteral\")) {\n throw new Error(\"arguments of `selectattr` must be strings\");\n }\n const [attr, testName, value] = filter.args.map((x) => this.evaluate(x, environment));\n let testFunction;\n if (testName) {\n const test = environment.tests.get(testName.value);\n if (!test) {\n throw new Error(`Unknown test: ${testName.value}`);\n }\n testFunction = test;\n } else {\n testFunction = (...x) => x[0].__bool__().value;\n }\n const filtered = operand.value.filter((item) => {\n const a = item.value.get(attr.value);\n if (a) {\n return testFunction(a, value);\n }\n return false;\n });\n return new ArrayValue(filtered);\n }\n }\n throw new Error(`Unknown ArrayValue filter: ${filterName}`);\n } else {\n throw new Error(`Cannot apply filter \"${filterName}\" to type: ${operand.type}`);\n }\n }\n throw new Error(`Unknown filter: ${node.filter.type}`);\n }\n /**\n * Evaluates expressions following the test operation type.\n */\n evaluateTestExpression(node, environment) {\n const operand = this.evaluate(node.operand, environment);\n const test = environment.tests.get(node.test.value);\n if (!test) {\n throw new Error(`Unknown test: ${node.test.value}`);\n }\n const result = test(operand);\n return new BooleanValue(node.negate ? !result : result);\n }\n /**\n * Evaluates expressions following the unary operation type.\n */\n evaluateUnaryExpression(node, environment) {\n const argument = this.evaluate(node.argument, environment);\n switch (node.operator.value) {\n case \"not\":\n return new BooleanValue(!argument.value);\n default:\n throw new SyntaxError(`Unknown operator: ${node.operator.value}`);\n }\n }\n evalProgram(program, environment) {\n return this.evaluateBlock(program.body, environment);\n }\n evaluateBlock(statements, environment) {\n let result = \"\";\n for (const statement of statements) {\n const lastEvaluated = this.evaluate(statement, environment);\n if (lastEvaluated.type !== \"NullValue\" && lastEvaluated.type !== \"UndefinedValue\") {\n result += lastEvaluated.value;\n }\n }\n return new StringValue(result);\n }\n evaluateIdentifier(node, environment) {\n return environment.lookupVariable(node.value);\n }\n evaluateCallExpression(expr, environment) {\n const args = [];\n const kwargs = /* @__PURE__ */ new Map();\n for (const argument of expr.args) {\n if (argument.type === \"KeywordArgumentExpression\") {\n const kwarg = argument;\n kwargs.set(kwarg.key.value, this.evaluate(kwarg.value, environment));\n } else {\n args.push(this.evaluate(argument, environment));\n }\n }\n if (kwargs.size > 0) {\n args.push(new ObjectValue(kwargs));\n }\n const fn = this.evaluate(expr.callee, environment);\n if (fn.type !== \"FunctionValue\") {\n throw new Error(`Cannot call something that is not a function: got ${fn.type}`);\n }\n return fn.value(args, environment);\n }\n evaluateSliceExpression(object, expr, environment) {\n if (!(object instanceof ArrayValue || object instanceof StringValue)) {\n throw new Error(\"Slice object must be an array or string\");\n }\n const start = this.evaluate(expr.start, environment);\n const stop = this.evaluate(expr.stop, environment);\n const step = this.evaluate(expr.step, environment);\n if (!(start instanceof NumericValue || start instanceof UndefinedValue)) {\n throw new Error(\"Slice start must be numeric or undefined\");\n }\n if (!(stop instanceof NumericValue || stop instanceof UndefinedValue)) {\n throw new Error(\"Slice stop must be numeric or undefined\");\n }\n if (!(step instanceof NumericValue || step instanceof UndefinedValue)) {\n throw new Error(\"Slice step must be numeric or undefined\");\n }\n if (object instanceof ArrayValue) {\n return new ArrayValue(slice(object.value, start.value, stop.value, step.value));\n } else {\n return new StringValue(slice(Array.from(object.value), start.value, stop.value, step.value).join(\"\"));\n }\n }\n evaluateMemberExpression(expr, environment) {\n const object = this.evaluate(expr.object, environment);\n let property;\n if (expr.computed) {\n if (expr.property.type === \"SliceExpression\") {\n return this.evaluateSliceExpression(object, expr.property, environment);\n } else {\n property = this.evaluate(expr.property, environment);\n }\n } else {\n property = new StringValue(expr.property.value);\n }\n let value;\n if (object instanceof ObjectValue) {\n if (!(property instanceof StringValue)) {\n throw new Error(`Cannot access property with non-string: got ${property.type}`);\n }\n value = object.value.get(property.value) ?? object.builtins.get(property.value);\n } else if (object instanceof ArrayValue || object instanceof StringValue) {\n if (property instanceof NumericValue) {\n value = object.value.at(property.value);\n if (object instanceof StringValue) {\n value = new StringValue(object.value.at(property.value));\n }\n } else if (property instanceof StringValue) {\n value = object.builtins.get(property.value);\n } else {\n throw new Error(`Cannot access property with non-string/non-number: got ${property.type}`);\n }\n } else {\n if (!(property instanceof StringValue)) {\n throw new Error(`Cannot access property with non-string: got ${property.type}`);\n }\n value = object.builtins.get(property.value);\n }\n return value instanceof RuntimeValue ? value : new UndefinedValue();\n }\n evaluateSet(node, environment) {\n const rhs = this.evaluate(node.value, environment);\n if (node.assignee.type === \"Identifier\") {\n const variableName = node.assignee.value;\n environment.setVariable(variableName, rhs);\n } else if (node.assignee.type === \"MemberExpression\") {\n const member = node.assignee;\n const object = this.evaluate(member.object, environment);\n if (!(object instanceof ObjectValue)) {\n throw new Error(\"Cannot assign to member of non-object\");\n }\n if (member.property.type !== \"Identifier\") {\n throw new Error(\"Cannot assign to member with non-identifier property\");\n }\n object.value.set(member.property.value, rhs);\n } else {\n throw new Error(`Invalid LHS inside assignment expression: ${JSON.stringify(node.assignee)}`);\n }\n return new NullValue();\n }\n evaluateIf(node, environment) {\n const test = this.evaluate(node.test, environment);\n return this.evaluateBlock(test.__bool__().value ? node.body : node.alternate, environment);\n }\n evaluateFor(node, environment) {\n const scope = new Environment(environment);\n const iterable = this.evaluate(node.iterable, scope);\n if (!(iterable instanceof ArrayValue)) {\n throw new Error(`Expected iterable type in for loop: got ${iterable.type}`);\n }\n let result = \"\";\n for (let i = 0; i < iterable.value.length; ++i) {\n const loop = /* @__PURE__ */ new Map([\n [\"index\", new NumericValue(i + 1)],\n [\"index0\", new NumericValue(i)],\n [\"revindex\", new NumericValue(iterable.value.length - i)],\n [\"revindex0\", new NumericValue(iterable.value.length - i - 1)],\n [\"first\", new BooleanValue(i === 0)],\n [\"last\", new BooleanValue(i === iterable.value.length - 1)],\n [\"length\", new NumericValue(iterable.value.length)],\n [\"previtem\", i > 0 ? iterable.value[i - 1] : new UndefinedValue()],\n [\"nextitem\", i < iterable.value.length - 1 ? iterable.value[i + 1] : new UndefinedValue()]\n ]);\n scope.setVariable(\"loop\", new ObjectValue(loop));\n const current = iterable.value[i];\n if (node.loopvar.type === \"Identifier\") {\n scope.setVariable(node.loopvar.value, current);\n } else if (node.loopvar.type === \"TupleLiteral\") {\n const loopvar = node.loopvar;\n if (current.type !== \"ArrayValue\") {\n throw new Error(`Cannot unpack non-iterable type: ${current.type}`);\n }\n const c = current;\n if (loopvar.value.length !== c.value.length) {\n throw new Error(`Too ${loopvar.value.length > c.value.length ? \"few\" : \"many\"} items to unpack`);\n }\n for (let j = 0; j < loopvar.value.length; ++j) {\n if (loopvar.value[j].type !== \"Identifier\") {\n throw new Error(`Cannot unpack non-identifier type: ${loopvar.value[j].type}`);\n }\n scope.setVariable(loopvar.value[j].value, c.value[j]);\n }\n }\n const evaluated = this.evaluateBlock(node.body, scope);\n result += evaluated.value;\n }\n return new StringValue(result);\n }\n evaluate(statement, environment) {\n if (statement === void 0)\n return new UndefinedValue();\n switch (statement.type) {\n case \"Program\":\n return this.evalProgram(statement, environment);\n case \"Set\":\n return this.evaluateSet(statement, environment);\n case \"If\":\n return this.evaluateIf(statement, environment);\n case \"For\":\n return this.evaluateFor(statement, environment);\n case \"NumericLiteral\":\n return new NumericValue(Number(statement.value));\n case \"StringLiteral\":\n return new StringValue(statement.value);\n case \"BooleanLiteral\":\n return new BooleanValue(statement.value);\n case \"ArrayLiteral\":\n return new ArrayValue(statement.value.map((x) => this.evaluate(x, environment)));\n case \"TupleLiteral\":\n return new TupleValue(statement.value.map((x) => this.evaluate(x, environment)));\n case \"ObjectLiteral\": {\n const mapping = /* @__PURE__ */ new Map();\n for (const [key, value] of statement.value) {\n const evaluatedKey = this.evaluate(key, environment);\n if (!(evaluatedKey instanceof StringValue)) {\n throw new Error(`Object keys must be strings: got ${evaluatedKey.type}`);\n }\n mapping.set(evaluatedKey.value, this.evaluate(value, environment));\n }\n return new ObjectValue(mapping);\n }\n case \"Identifier\":\n return this.evaluateIdentifier(statement, environment);\n case \"CallExpression\":\n return this.evaluateCallExpression(statement, environment);\n case \"MemberExpression\":\n return this.evaluateMemberExpression(statement, environment);\n case \"UnaryExpression\":\n return this.evaluateUnaryExpression(statement, environment);\n case \"BinaryExpression\":\n return this.evaluateBinaryExpression(statement, environment);\n case \"FilterExpression\":\n return this.evaluateFilterExpression(statement, environment);\n case \"TestExpression\":\n return this.evaluateTestExpression(statement, environment);\n default:\n throw new SyntaxError(`Unknown node type: ${statement.type}`);\n }\n }\n};\nfunction convertToRuntimeValues(input) {\n switch (typeof input) {\n case \"number\":\n return new NumericValue(input);\n case \"string\":\n return new StringValue(input);\n case \"boolean\":\n return new BooleanValue(input);\n case \"object\":\n if (input === null) {\n return new NullValue();\n } else if (Array.isArray(input)) {\n return new ArrayValue(input.map(convertToRuntimeValues));\n } else {\n return new ObjectValue(\n new Map(Object.entries(input).map(([key, value]) => [key, convertToRuntimeValues(value)]))\n );\n }\n case \"function\":\n return new FunctionValue((args, _scope) => {\n const result = input(...args.map((x) => x.value)) ?? null;\n return convertToRuntimeValues(result);\n });\n default:\n throw new Error(`Cannot convert to runtime value: ${input}`);\n }\n}\n\n// src/index.ts\nvar Template = class {\n parsed;\n /**\n * @param {string} template The template string\n */\n constructor(template) {\n const tokens = tokenize(template, {\n lstrip_blocks: true,\n trim_blocks: true\n });\n this.parsed = parse(tokens);\n }\n render(items) {\n const env = new Environment();\n env.set(\"false\", false);\n env.set(\"true\", true);\n env.set(\"raise_exception\", (args) => {\n throw new Error(args);\n });\n env.set(\"range\", range);\n for (const [key, value] of Object.entries(items)) {\n env.set(key, value);\n }\n const interpreter = new Interpreter(env);\n const result = interpreter.run(this.parsed);\n return result.value;\n }\n};\nexport {\n Environment,\n Interpreter,\n Template,\n parse,\n tokenize\n};\n"],"names":[],"mappings":"AACA,IAAI,cAAc,OAAO,OAAO;AAAA,EAC9B,MAAM;AAAA;AAAA,EAEN,gBAAgB;AAAA;AAAA,EAEhB,gBAAgB;AAAA;AAAA,EAEhB,eAAe;AAAA;AAAA,EAEf,YAAY;AAAA;AAAA,EAEZ,QAAQ;AAAA;AAAA,EAER,WAAW;AAAA;AAAA,EAEX,YAAY;AAAA;AAAA,EAEZ,eAAe;AAAA;AAAA,EAEf,gBAAgB;AAAA;AAAA,EAEhB,gBAAgB;AAAA;AAAA,EAEhB,iBAAiB;AAAA;AAAA,EAEjB,mBAAmB;AAAA;AAAA,EAEnB,oBAAoB;AAAA;AAAA,EAEpB,kBAAkB;AAAA;AAAA,EAElB,mBAAmB;AAAA;AAAA,EAEnB,OAAO;AAAA;AAAA,EAEP,KAAK;AAAA;AAAA,EAEL,OAAO;AAAA;AAAA,EAEP,MAAM;AAAA;AAAA,EAEN,cAAc;AAAA;AAAA,EAEd,wBAAwB;AAAA;AAAA,EAExB,8BAA8B;AAAA;AAAA,EAE9B,0BAA0B;AAAA;AAAA,EAE1B,eAAe;AAAA;AAAA;AAAA,EAGf,KAAK;AAAA,EACL,IAAI;AAAA,EACJ,KAAK;AAAA,EACL,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,KAAK;AAAA,EACL,IAAI;AAAA,EACJ,KAAK;AACP,CAAC;AACc,OAAO,OAAO;AAAA,EAC3B,KAAK,YAAY;AAAA,EACjB,KAAK,YAAY;AAAA,EACjB,IAAI,YAAY;AAAA,EAChB,IAAI,YAAY;AAAA,EAChB,IAAI,YAAY;AAAA,EAChB,MAAM,YAAY;AAAA,EAClB,OAAO,YAAY;AAAA,EACnB,MAAM,YAAY;AAAA,EAClB,QAAQ,YAAY;AAAA,EACpB,KAAK,YAAY;AAAA,EACjB,IAAI,YAAY;AAAA,EAChB,KAAK,YAAY;AAAA,EACjB,UAAU,YAAY;AAAA;AAAA,EAEtB,MAAM,YAAY;AAAA,EAClB,OAAO,YAAY;AACrB,CAAC;AAkB2B;AAAA;AAAA,EAE1B,CAAC,MAAM,YAAY,aAAa;AAAA,EAChC,CAAC,MAAM,YAAY,cAAc;AAAA,EACjC,CAAC,MAAM,YAAY,cAAc;AAAA,EACjC,CAAC,MAAM,YAAY,eAAe;AAAA;AAAA,EAElC,CAAC,KAAK,YAAY,SAAS;AAAA,EAC3B,CAAC,KAAK,YAAY,UAAU;AAAA,EAC5B,CAAC,KAAK,YAAY,gBAAgB;AAAA,EAClC,CAAC,KAAK,YAAY,iBAAiB;AAAA,EACnC,CAAC,KAAK,YAAY,iBAAiB;AAAA,EACnC,CAAC,KAAK,YAAY,kBAAkB;AAAA,EACpC,CAAC,KAAK,YAAY,KAAK;AAAA,EACvB,CAAC,KAAK,YAAY,GAAG;AAAA,EACrB,CAAC,KAAK,YAAY,KAAK;AAAA,EACvB,CAAC,KAAK,YAAY,IAAI;AAAA;AAAA,EAEtB,CAAC,MAAM,YAAY,wBAAwB;AAAA,EAC3C,CAAC,MAAM,YAAY,wBAAwB;AAAA,EAC3C,CAAC,MAAM,YAAY,wBAAwB;AAAA,EAC3C,CAAC,MAAM,YAAY,wBAAwB;AAAA,EAC3C,CAAC,KAAK,YAAY,wBAAwB;AAAA,EAC1C,CAAC,KAAK,YAAY,wBAAwB;AAAA;AAAA,EAE1C,CAAC,KAAK,YAAY,sBAAsB;AAAA,EACxC,CAAC,KAAK,YAAY,sBAAsB;AAAA,EACxC,CAAC,KAAK,YAAY,4BAA4B;AAAA,EAC9C,CAAC,KAAK,YAAY,4BAA4B;AAAA,EAC9C,CAAC,KAAK,YAAY,4BAA4B;AAAA;AAAA,EAE9C,CAAC,KAAK,YAAY,MAAM;AAC1B;","x_google_ignoreList":[0]}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import * as __viteBrowserExternal from "../../../../../_virtual/__vite-browser-external.js";
|
|
2
|
-
import sharp from "../../../../../_virtual/__vite-browser-external.js";
|
|
3
|
-
import * as ortWeb_min from "../../../../../_virtual/ort-web.min.js";
|
|
4
|
-
import ortWeb_min$1 from "../../../../../_virtual/ort-web.min.js";
|
|
5
|
-
let ONNX;
|
|
6
|
-
const executionProviders = [
|
|
7
|
-
// 'webgpu',
|
|
8
|
-
"wasm"
|
|
9
|
-
];
|
|
10
|
-
if (typeof process !== "undefined" && process?.release?.name === "node") {
|
|
11
|
-
ONNX = sharp ?? __viteBrowserExternal;
|
|
12
|
-
executionProviders.unshift("cpu");
|
|
13
|
-
} else {
|
|
14
|
-
ONNX = ortWeb_min$1 ?? ortWeb_min;
|
|
15
|
-
const isIOS = typeof navigator !== "undefined" && /iP(hone|od|ad).+16_4.+AppleWebKit/.test(navigator.userAgent);
|
|
16
|
-
if (isIOS) {
|
|
17
|
-
ONNX.env.wasm.simd = false;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
export {
|
|
21
|
-
ONNX,
|
|
22
|
-
executionProviders
|
|
23
|
-
};
|
|
24
|
-
//# sourceMappingURL=onnx.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"onnx.js","sources":["../../../../../../node_modules/@xenova/transformers/src/backends/onnx.js"],"sourcesContent":["/**\n * @file Handler file for choosing the correct version of ONNX Runtime, based on the environment.\n * Ideally, we could import the `onnxruntime-web` and `onnxruntime-node` packages only when needed,\n * but dynamic imports don't seem to work with the current webpack version and/or configuration.\n * This is possibly due to the experimental nature of top-level await statements.\n * So, we just import both packages, and use the appropriate one based on the environment:\n * - When running in node, we use `onnxruntime-node`.\n * - When running in the browser, we use `onnxruntime-web` (`onnxruntime-node` is not bundled).\n * \n * This module is not directly exported, but can be accessed through the environment variables:\n * ```javascript\n * import { env } from '@xenova/transformers';\n * console.log(env.backends.onnx);\n * ```\n * \n * @module backends/onnx\n */\n\n// NOTE: Import order matters here. We need to import `onnxruntime-node` before `onnxruntime-web`.\n// In either case, we select the default export if it exists, otherwise we use the named export.\nimport * as ONNX_NODE from 'onnxruntime-node';\nimport * as ONNX_WEB from 'onnxruntime-web';\n\n/** @type {import('onnxruntime-web')} The ONNX runtime module. */\nexport let ONNX;\n\nexport const executionProviders = [\n // 'webgpu',\n 'wasm'\n];\n\nif (typeof process !== 'undefined' && process?.release?.name === 'node') {\n // Running in a node-like environment.\n ONNX = ONNX_NODE.default ?? ONNX_NODE;\n\n // Add `cpu` execution provider, with higher precedence that `wasm`.\n executionProviders.unshift('cpu');\n\n} else {\n // Running in a browser-environment\n ONNX = ONNX_WEB.default ?? ONNX_WEB;\n\n // SIMD for WebAssembly does not operate correctly in some recent versions of iOS (16.4.x).\n // As a temporary fix, we disable it for now.\n // For more information, see: https://github.com/microsoft/onnxruntime/issues/15644\n const isIOS = typeof navigator !== 'undefined' && /iP(hone|od|ad).+16_4.+AppleWebKit/.test(navigator.userAgent);\n if (isIOS) {\n ONNX.env.wasm.simd = false;\n }\n}\n"],"names":["ONNX_NODE.default","ONNX_NODE","ONNX_WEB.default","ONNX_WEB"],"mappings":";;;;AAwBU,IAAC;AAEC,MAAC,qBAAqB;AAAA;AAAA,EAE9B;AACJ;AAEA,IAAI,OAAO,YAAY,eAAe,SAAS,SAAS,SAAS,QAAQ;AAErE,SAAOA,SAAqBC;AAG5B,qBAAmB,QAAQ,KAAK;AAEpC,OAAO;AAEH,SAAOC,gBAAoBC;AAK3B,QAAM,QAAQ,OAAO,cAAc,eAAe,oCAAoC,KAAK,UAAU,SAAS;AAC9G,MAAI,OAAO;AACP,SAAK,IAAI,KAAK,OAAO;AAAA,EACzB;AACJ;","x_google_ignoreList":[0]}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { getModelJSON } from "./utils/hub.js";
|
|
2
|
-
async function loadConfig(pretrained_model_name_or_path, options) {
|
|
3
|
-
let info = await getModelJSON(pretrained_model_name_or_path, "config.json", true, options);
|
|
4
|
-
return info;
|
|
5
|
-
}
|
|
6
|
-
class PretrainedConfig {
|
|
7
|
-
// NOTE: Typo in original
|
|
8
|
-
/**
|
|
9
|
-
* Create a new PreTrainedTokenizer instance.
|
|
10
|
-
* @param {Object} configJSON The JSON of the config.
|
|
11
|
-
*/
|
|
12
|
-
constructor(configJSON) {
|
|
13
|
-
this.model_type = null;
|
|
14
|
-
this.is_encoder_decoder = false;
|
|
15
|
-
Object.assign(this, configJSON);
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Loads a pre-trained config from the given `pretrained_model_name_or_path`.
|
|
19
|
-
*
|
|
20
|
-
* @param {string} pretrained_model_name_or_path The path to the pre-trained config.
|
|
21
|
-
* @param {PretrainedOptions} options Additional options for loading the config.
|
|
22
|
-
* @throws {Error} Throws an error if the config.json is not found in the `pretrained_model_name_or_path`.
|
|
23
|
-
*
|
|
24
|
-
* @returns {Promise<PretrainedConfig>} A new instance of the `PretrainedConfig` class.
|
|
25
|
-
*/
|
|
26
|
-
static async from_pretrained(pretrained_model_name_or_path, {
|
|
27
|
-
progress_callback = null,
|
|
28
|
-
config = null,
|
|
29
|
-
cache_dir = null,
|
|
30
|
-
local_files_only = false,
|
|
31
|
-
revision = "main"
|
|
32
|
-
} = {}) {
|
|
33
|
-
let data = config ?? await loadConfig(pretrained_model_name_or_path, {
|
|
34
|
-
progress_callback,
|
|
35
|
-
cache_dir,
|
|
36
|
-
local_files_only,
|
|
37
|
-
revision
|
|
38
|
-
});
|
|
39
|
-
return new this(data);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
class AutoConfig {
|
|
43
|
-
/** @type {PretrainedConfig.from_pretrained} */
|
|
44
|
-
static async from_pretrained(...args) {
|
|
45
|
-
return PretrainedConfig.from_pretrained(...args);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
export {
|
|
49
|
-
AutoConfig,
|
|
50
|
-
PretrainedConfig
|
|
51
|
-
};
|
|
52
|
-
//# sourceMappingURL=configs.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"configs.js","sources":["../../../../../node_modules/@xenova/transformers/src/configs.js"],"sourcesContent":["\n/**\n * @file Helper module for using model configs. For more information, see the corresponding\n * [Python documentation](https://huggingface.co/docs/transformers/main/en/model_doc/auto#transformers.AutoConfig).\n * \n * **Example:** Load an `AutoConfig`.\n * \n * ```javascript\n * import { AutoConfig } from '@xenova/transformers';\n * let config = await AutoConfig.from_pretrained('bert-base-uncased');\n * console.log(config);\n * // PretrainedConfig {\n * // \"model_type\": \"bert\",\n * // \"is_encoder_decoder\": false,\n * // \"architectures\": [\n * // \"BertForMaskedLM\"\n * // ],\n * // \"vocab_size\": 30522\n * // \"num_attention_heads\": 12,\n * // \"num_hidden_layers\": 12,\n * // \"hidden_size\": 768,\n * // \"max_position_embeddings\": 512,\n * // ...\n * // }\n * ```\n * \n * @module configs\n */\n\nimport {\n getModelJSON,\n} from './utils/hub.js';\n\n/**\n * @typedef {import('./utils/hub.js').PretrainedOptions} PretrainedOptions\n */\n\n\n/**\n * Loads a config from the specified path.\n * @param {string} pretrained_model_name_or_path The path to the config directory.\n * @param {PretrainedOptions} options Additional options for loading the config.\n * @returns {Promise<Array>} A promise that resolves with information about the loaded config.\n */\nasync function loadConfig(pretrained_model_name_or_path, options) {\n let info = await getModelJSON(pretrained_model_name_or_path, 'config.json', true, options);\n return info;\n}\n\n/**\n * Base class for all configuration classes. For more information, see the corresponding\n * [Python documentation](https://huggingface.co/docs/transformers/main/en/main_classes/configuration#transformers.PretrainedConfig).\n */\nexport class PretrainedConfig {\n // NOTE: Typo in original\n\n /**\n * Create a new PreTrainedTokenizer instance.\n * @param {Object} configJSON The JSON of the config.\n */\n constructor(configJSON) {\n this.model_type = null;\n this.is_encoder_decoder = false;\n\n Object.assign(this, configJSON);\n }\n\n /**\n * Loads a pre-trained config from the given `pretrained_model_name_or_path`. \n * \n * @param {string} pretrained_model_name_or_path The path to the pre-trained config.\n * @param {PretrainedOptions} options Additional options for loading the config.\n * @throws {Error} Throws an error if the config.json is not found in the `pretrained_model_name_or_path`.\n * \n * @returns {Promise<PretrainedConfig>} A new instance of the `PretrainedConfig` class.\n */\n static async from_pretrained(pretrained_model_name_or_path, {\n progress_callback = null,\n config = null,\n cache_dir = null,\n local_files_only = false,\n revision = 'main',\n } = {}) {\n\n let data = config ?? await loadConfig(pretrained_model_name_or_path, {\n progress_callback,\n config,\n cache_dir,\n local_files_only,\n revision,\n })\n return new this(data);\n }\n}\n\n/**\n * Helper class which is used to instantiate pretrained configs with the `from_pretrained` function.\n * \n * @example\n * let config = await AutoConfig.from_pretrained('bert-base-uncased'); \n */\nexport class AutoConfig {\n /** @type {PretrainedConfig.from_pretrained} */\n static async from_pretrained(...args) {\n return PretrainedConfig.from_pretrained(...args);\n }\n}\n"],"names":[],"mappings":";AA4CA,eAAe,WAAW,+BAA+B,SAAS;AAC9D,MAAI,OAAO,MAAM,aAAa,+BAA+B,eAAe,MAAM,OAAO;AACzF,SAAO;AACX;AAMO,MAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO1B,YAAY,YAAY;AACpB,SAAK,aAAa;AAClB,SAAK,qBAAqB;AAE1B,WAAO,OAAO,MAAM,UAAU;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,aAAa,gBAAgB,+BAA+B;AAAA,IACxD,oBAAoB;AAAA,IACpB,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,mBAAmB;AAAA,IACnB,WAAW;AAAA,EACnB,IAAQ,IAAI;AAEJ,QAAI,OAAO,UAAU,MAAM,WAAW,+BAA+B;AAAA,MACjE;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,IACZ,CAAS;AACD,WAAO,IAAI,KAAK,IAAI;AAAA,EACxB;AACJ;AAQO,MAAM,WAAW;AAAA;AAAA,EAEpB,aAAa,mBAAmB,MAAM;AAClC,WAAO,iBAAiB,gBAAgB,GAAG,IAAI;AAAA,EACnD;AACJ;","x_google_ignoreList":[0]}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import fs from "fs";
|
|
2
|
-
import path__default from "path";
|
|
3
|
-
import url from "url";
|
|
4
|
-
import { ONNX } from "./backends/onnx.js";
|
|
5
|
-
const { env: onnx_env } = ONNX;
|
|
6
|
-
const VERSION = "2.17.2";
|
|
7
|
-
const WEB_CACHE_AVAILABLE = typeof self !== "undefined" && "caches" in self;
|
|
8
|
-
const FS_AVAILABLE = !isEmpty(fs);
|
|
9
|
-
const PATH_AVAILABLE = !isEmpty(path__default);
|
|
10
|
-
const RUNNING_LOCALLY = FS_AVAILABLE && PATH_AVAILABLE;
|
|
11
|
-
const __dirname$1 = RUNNING_LOCALLY ? path__default.dirname(path__default.dirname(url.fileURLToPath(import.meta.url))) : "./";
|
|
12
|
-
const DEFAULT_CACHE_DIR = RUNNING_LOCALLY ? path__default.join(__dirname$1, "/.cache/") : null;
|
|
13
|
-
const DEFAULT_LOCAL_MODEL_PATH = "/models/";
|
|
14
|
-
const localModelPath = RUNNING_LOCALLY ? path__default.join(__dirname$1, DEFAULT_LOCAL_MODEL_PATH) : DEFAULT_LOCAL_MODEL_PATH;
|
|
15
|
-
if (onnx_env?.wasm) {
|
|
16
|
-
onnx_env.wasm.wasmPaths = RUNNING_LOCALLY ? path__default.join(__dirname$1, "/dist/") : `https://cdn.jsdelivr.net/npm/@xenova/transformers@${VERSION}/dist/`;
|
|
17
|
-
}
|
|
18
|
-
const env = {
|
|
19
|
-
version: VERSION,
|
|
20
|
-
remoteHost: "https://huggingface.co/",
|
|
21
|
-
remotePathTemplate: "{model}/resolve/{revision}/",
|
|
22
|
-
localModelPath,
|
|
23
|
-
useFS: FS_AVAILABLE,
|
|
24
|
-
/////////////////// Cache settings ///////////////////
|
|
25
|
-
useBrowserCache: WEB_CACHE_AVAILABLE,
|
|
26
|
-
useFSCache: FS_AVAILABLE,
|
|
27
|
-
cacheDir: DEFAULT_CACHE_DIR
|
|
28
|
-
};
|
|
29
|
-
function isEmpty(obj) {
|
|
30
|
-
return Object.keys(obj).length === 0;
|
|
31
|
-
}
|
|
32
|
-
export {
|
|
33
|
-
env
|
|
34
|
-
};
|
|
35
|
-
//# sourceMappingURL=env.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"env.js","sources":["../../../../../node_modules/@xenova/transformers/src/env.js"],"sourcesContent":["/**\n * @file Module used to configure Transformers.js.\n * \n * **Example:** Disable remote models.\n * ```javascript\n * import { env } from '@xenova/transformers';\n * env.allowRemoteModels = false;\n * ```\n * \n * **Example:** Set local model path.\n * ```javascript\n * import { env } from '@xenova/transformers';\n * env.localModelPath = '/path/to/local/models/';\n * ```\n * \n * **Example:** Set cache directory.\n * ```javascript\n * import { env } from '@xenova/transformers';\n * env.cacheDir = '/path/to/cache/directory/';\n * ```\n * \n * @module env\n */\n\nimport fs from 'fs';\nimport path from 'path';\nimport url from 'url';\n\nimport { ONNX } from './backends/onnx.js';\nconst { env: onnx_env } = ONNX;\n\nconst VERSION = '2.17.2';\n\n// Check if various APIs are available (depends on environment)\nconst WEB_CACHE_AVAILABLE = typeof self !== 'undefined' && 'caches' in self;\nconst FS_AVAILABLE = !isEmpty(fs); // check if file system is available\nconst PATH_AVAILABLE = !isEmpty(path); // check if path is available\n\nconst RUNNING_LOCALLY = FS_AVAILABLE && PATH_AVAILABLE;\n\nconst __dirname = RUNNING_LOCALLY\n ? path.dirname(path.dirname(url.fileURLToPath(import.meta.url)))\n : './';\n\n// Only used for environments with access to file system\nconst DEFAULT_CACHE_DIR = RUNNING_LOCALLY\n ? path.join(__dirname, '/.cache/')\n : null;\n\n// Set local model path, based on available APIs\nconst DEFAULT_LOCAL_MODEL_PATH = '/models/';\nconst localModelPath = RUNNING_LOCALLY\n ? path.join(__dirname, DEFAULT_LOCAL_MODEL_PATH)\n : DEFAULT_LOCAL_MODEL_PATH;\n\nif (onnx_env?.wasm) {\n // Set path to wasm files. This is needed when running in a web worker.\n // https://onnxruntime.ai/docs/api/js/interfaces/Env.WebAssemblyFlags.html#wasmPaths\n // We use remote wasm files by default to make it easier for newer users.\n // In practice, users should probably self-host the necessary .wasm files.\n onnx_env.wasm.wasmPaths = RUNNING_LOCALLY\n ? path.join(__dirname, '/dist/')\n : `https://cdn.jsdelivr.net/npm/@xenova/transformers@${VERSION}/dist/`;\n}\n\n/**\n * Global variable used to control execution. This provides users a simple way to configure Transformers.js.\n * @property {Object} backends Expose environment variables of different backends,\n * allowing users to set these variables if they want to.\n * @property {string} __dirname Directory name of module. Useful for resolving local paths.\n * @property {string} version This version of Transformers.js.\n * @property {boolean} allowRemoteModels Whether to allow loading of remote files, defaults to `true`.\n * If set to `false`, it will have the same effect as setting `local_files_only=true` when loading pipelines, models, tokenizers, processors, etc.\n * @property {string} remoteHost Host URL to load models from. Defaults to the Hugging Face Hub.\n * @property {string} remotePathTemplate Path template to fill in and append to `remoteHost` when loading models.\n * @property {boolean} allowLocalModels Whether to allow loading of local files, defaults to `true`.\n * If set to `false`, it will skip the local file check and try to load the model from the remote host.\n * @property {string} localModelPath Path to load local models from. Defaults to `/models/`.\n * @property {boolean} useFS Whether to use the file system to load files. By default, it is `true` if available.\n * @property {boolean} useBrowserCache Whether to use Cache API to cache models. By default, it is `true` if available.\n * @property {boolean} useFSCache Whether to use the file system to cache files. By default, it is `true` if available.\n * @property {string} cacheDir The directory to use for caching files with the file system. By default, it is `./.cache`.\n * @property {boolean} useCustomCache Whether to use a custom cache system (defined by `customCache`), defaults to `false`.\n * @property {Object} customCache The custom cache to use. Defaults to `null`. Note: this must be an object which\n * implements the `match` and `put` functions of the Web Cache API. For more information, see https://developer.mozilla.org/en-US/docs/Web/API/Cache\n */\nexport const env = {\n /////////////////// Backends settings ///////////////////\n backends: {\n // onnxruntime-web/onnxruntime-node\n onnx: onnx_env,\n\n // TensorFlow.js\n tfjs: {},\n },\n\n __dirname,\n version: VERSION,\n\n /////////////////// Model settings ///////////////////\n allowRemoteModels: true,\n remoteHost: 'https://huggingface.co/',\n remotePathTemplate: '{model}/resolve/{revision}/',\n\n allowLocalModels: true,\n localModelPath: localModelPath,\n useFS: FS_AVAILABLE,\n\n /////////////////// Cache settings ///////////////////\n useBrowserCache: WEB_CACHE_AVAILABLE,\n\n useFSCache: FS_AVAILABLE,\n cacheDir: DEFAULT_CACHE_DIR,\n\n useCustomCache: false,\n customCache: null,\n //////////////////////////////////////////////////////\n}\n\n\n/**\n * @param {Object} obj\n * @private\n */\nfunction isEmpty(obj) {\n return Object.keys(obj).length === 0;\n}\n\n"],"names":["path","__dirname"],"mappings":";;;;AA6BA,MAAM,EAAE,KAAK,SAAQ,IAAK;AAE1B,MAAM,UAAU;AAGhB,MAAM,sBAAsB,OAAO,SAAS,eAAe,YAAY;AACvE,MAAM,eAAe,CAAC,QAAQ,EAAE;AAChC,MAAM,iBAAiB,CAAC,QAAQA,aAAI;AAEpC,MAAM,kBAAkB,gBAAgB;AAExC,MAAMC,cAAY,kBACZD,cAAK,QAAQA,cAAK,QAAQ,IAAI,cAAc,YAAY,GAAG,CAAC,CAAC,IAC7D;AAGN,MAAM,oBAAoB,kBACpBA,cAAK,KAAKC,aAAW,UAAU,IAC/B;AAGN,MAAM,2BAA2B;AACjC,MAAM,iBAAiB,kBACjBD,cAAK,KAAKC,aAAW,wBAAwB,IAC7C;AAEN,IAAI,UAAU,MAAM;AAKhB,WAAS,KAAK,YAAY,kBACpBD,cAAK,KAAKC,aAAW,QAAQ,IAC7B,qDAAqD,OAAO;AACtE;AAuBY,MAAC,MAAM;AAAA,EAWf,SAAS;AAAA,EAIT,YAAY;AAAA,EACZ,oBAAoB;AAAA,EAGpB;AAAA,EACA,OAAO;AAAA;AAAA,EAGP,iBAAiB;AAAA,EAEjB,YAAY;AAAA,EACZ,UAAU;AAKd;AAOA,SAAS,QAAQ,KAAK;AAClB,SAAO,OAAO,KAAK,GAAG,EAAE,WAAW;AACvC;","x_google_ignoreList":[0]}
|