agentic-flow 2.1.1 โ†’ 2.1.3

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.
Files changed (36) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/agents/claudeAgentDirect.js +4 -4
  3. package/dist/agents/claudeAgentDirect.js.map +1 -1
  4. package/dist/billing/cli.js +0 -0
  5. package/dist/cli/agentdb-proxy.d.ts +3 -0
  6. package/dist/cli/agentdb-proxy.d.ts.map +1 -0
  7. package/dist/cli/agentdb-proxy.js +8 -0
  8. package/dist/cli/agentdb-proxy.js.map +1 -0
  9. package/dist/cli-proxy.js +67 -3
  10. package/dist/cli-proxy.js.map +1 -1
  11. package/dist/router/providers/onnx-local-optimized.d.ts +10 -1
  12. package/dist/router/providers/onnx-local-optimized.d.ts.map +1 -1
  13. package/dist/router/providers/onnx-local-optimized.js +12 -10
  14. package/dist/router/providers/onnx-local-optimized.js.map +1 -1
  15. package/dist/router/providers/onnx-local.d.ts +9 -0
  16. package/dist/router/providers/onnx-local.d.ts.map +1 -1
  17. package/dist/router/providers/onnx-local.js +24 -9
  18. package/dist/router/providers/onnx-local.js.map +1 -1
  19. package/dist/router/providers/onnx-phi4.d.ts.map +1 -1
  20. package/dist/router/providers/onnx-phi4.js +2 -1
  21. package/dist/router/providers/onnx-phi4.js.map +1 -1
  22. package/dist/router/router.d.ts.map +1 -1
  23. package/dist/router/router.js +2 -1
  24. package/dist/router/router.js.map +1 -1
  25. package/dist/router/test-onnx-benchmark.js +2 -1
  26. package/dist/router/test-onnx-benchmark.js.map +1 -1
  27. package/dist/router/test-onnx-local.js +2 -1
  28. package/dist/router/test-onnx-local.js.map +1 -1
  29. package/dist/utils/model-downloader.d.ts +14 -0
  30. package/dist/utils/model-downloader.d.ts.map +1 -1
  31. package/dist/utils/model-downloader.js +19 -3
  32. package/dist/utils/model-downloader.js.map +1 -1
  33. package/package.json +4 -4
  34. package/wasm/reasoningbank/reasoningbank_wasm_bg.js +32 -32
  35. package/wasm/reasoningbank/reasoningbank_wasm_bg.wasm +0 -0
  36. package/wasm/reasoningbank/reasoningbank_wasm_bg.wasm.d.ts +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"onnx-local.d.ts","sourceRoot":"","sources":["../../../src/router/providers/onnx-local.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAiBH,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,YAAY,EACZ,WAAW,EAIZ,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,qBAAa,iBAAkB,YAAW,WAAW;IACnD,IAAI,SAAgB;IACpB,IAAI,EAAG,QAAQ,CAAU;IACzB,iBAAiB,UAAS;IAC1B,aAAa,UAAS;IACtB,WAAW,UAAS;IAEpB,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,SAAS,CAAa;IAC9B,OAAO,CAAC,QAAQ,CAAa;gBAEjB,MAAM,GAAE,eAAoB;IASxC;;OAEG;YACW,aAAa;IAc3B;;OAEG;IACH,OAAO,CAAC,MAAM;IAId;;OAEG;IACH,OAAO,CAAC,MAAM;IAgBd;;OAEG;YACW,iBAAiB;IAiD/B;;OAEG;IACH,OAAO,CAAC,cAAc;IAqBtB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IA8BzB;;OAEG;IACG,IAAI,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC;IA8IrD;;OAEG;IACI,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,cAAc,CAAC,WAAW,CAAC;IAI9D;;OAEG;IACH,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO;IAKjD;;OAEG;IACH,YAAY;;;;;;IASZ;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAU/B"}
1
+ {"version":3,"file":"onnx-local.d.ts","sourceRoot":"","sources":["../../../src/router/providers/onnx-local.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAqBH,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,YAAY,EACZ,WAAW,EAIZ,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,qBAAa,iBAAkB,YAAW,WAAW;IACnD,IAAI,SAAgB;IACpB,IAAI,EAAG,QAAQ,CAAU;IACzB,iBAAiB,UAAS;IAC1B,aAAa,UAAS;IACtB,WAAW,UAAS;IAEpB,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,SAAS,CAAa;IAC9B,OAAO,CAAC,QAAQ,CAAa;gBAEjB,MAAM,GAAE,eAAoB;IASxC;;OAEG;YACW,aAAa;IAc3B;;OAEG;IACH,OAAO,CAAC,MAAM;IAId;;OAEG;IACH,OAAO,CAAC,MAAM;IAgBd;;OAEG;YACW,iBAAiB;IAkD/B;;OAEG;IACH,OAAO,CAAC,cAAc;IAqBtB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IA8BzB;;OAEG;IACG,IAAI,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC;IA8IrD;;OAEG;IACI,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,cAAc,CAAC,WAAW,CAAC;IAI9D;;OAEG;IACH,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO;IAKjD;;OAEG;IACH,YAAY;;;;;;IASZ;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAU/B"}
@@ -3,19 +3,33 @@
3
3
  *
4
4
  * Uses onnxruntime-node for true local CPU/GPU inference
5
5
  * Falls back gracefully when native module isn't available (Windows)
6
+ *
7
+ * NOTE (ruvnet/ruflo#2048): `onnxruntime-node` is loaded LAZILY on first
8
+ * `initializeSession()` call, not at module import. The previous top-level
9
+ * `await import('onnxruntime-node')` fired the native-binding load
10
+ * (`onnxruntime_binding.node`) at module load time, which crashed Windows
11
+ * environments where the NAPI binary cannot be loaded โ€” even when the
12
+ * consumer (e.g. `agentic-flow/reasoningbank`) never actually invokes
13
+ * the router. Moving the import inside `loadOrt()` keeps importing
14
+ * `reasoningbank` side-effect-free with respect to native bindings.
6
15
  */
7
16
  let ort = null;
8
17
  let ortAvailable = false;
9
- // Dynamic import for optional onnxruntime-node
10
- try {
11
- ort = await import('onnxruntime-node');
12
- ortAvailable = true;
13
- }
14
- catch {
15
- console.warn('[ONNX] onnxruntime-node not available - local inference disabled');
18
+ let ortLoaded = false;
19
+ async function loadOrt() {
20
+ if (ortLoaded)
21
+ return;
22
+ ortLoaded = true;
23
+ try {
24
+ ort = await import('onnxruntime-node');
25
+ ortAvailable = true;
26
+ }
27
+ catch {
28
+ console.warn('[ONNX] onnxruntime-node not available - local inference disabled');
29
+ }
16
30
  }
17
31
  import { get_encoding } from 'tiktoken';
18
- import { ensurePhi4Model, ModelDownloader } from '../../utils/model-downloader.js';
32
+ import { ensurePhi4Model, ModelDownloader, PHI4_MODEL_PATH } from '../../utils/model-downloader.js';
19
33
  export class ONNXLocalProvider {
20
34
  name = 'onnx-local';
21
35
  type = 'custom';
@@ -28,7 +42,7 @@ export class ONNXLocalProvider {
28
42
  tiktoken = null;
29
43
  constructor(config = {}) {
30
44
  this.config = {
31
- modelPath: config.modelPath || './models/phi-4/cpu_and_mobile/cpu-int4-rtn-block-32-acc-level-4/model.onnx',
45
+ modelPath: config.modelPath || PHI4_MODEL_PATH,
32
46
  executionProviders: config.executionProviders || ['cpu'],
33
47
  maxTokens: config.maxTokens || 100,
34
48
  temperature: config.temperature || 0.7
@@ -82,6 +96,7 @@ export class ONNXLocalProvider {
82
96
  async initializeSession() {
83
97
  if (this.session)
84
98
  return;
99
+ await loadOrt();
85
100
  if (!ortAvailable || !ort) {
86
101
  throw new Error('onnxruntime-node not available - install with: npm install onnxruntime-node');
87
102
  }
@@ -1 +1 @@
1
- {"version":3,"file":"onnx-local.js","sourceRoot":"","sources":["../../../src/router/providers/onnx-local.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * ONNX Runtime Local Inference Provider for Phi-4\n *\n * Uses onnxruntime-node for true local CPU/GPU inference\n * Falls back gracefully when native module isn't available (Windows)\n */\n\nlet ort: any = null;\nlet ortAvailable = false;\n\n// Dynamic import for optional onnxruntime-node\ntry {\n ort = await import('onnxruntime-node');\n ortAvailable = true;\n} catch {\n console.warn('[ONNX] onnxruntime-node not available - local inference disabled');\n}\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { get_encoding } from 'tiktoken';\nimport { ensurePhi4Model, ModelDownloader } from '../../utils/model-downloader.js';\nimport type {\n LLMProvider,\n ChatParams,\n ChatResponse,\n StreamChunk,\n ProviderError,\n Message,\n ContentBlock\n} from '../types.js';\n\nexport interface ONNXLocalConfig {\n modelPath?: string;\n executionProviders?: string[];\n maxTokens?: number;\n temperature?: number;\n}\n\nexport class ONNXLocalProvider implements LLMProvider {\n name = 'onnx-local';\n type = 'custom' as const;\n supportsStreaming = false; // Streaming requires complex token generation loop\n supportsTools = false;\n supportsMCP = false;\n\n private session: any = null;\n private config: Required<ONNXLocalConfig>;\n private tokenizer: any = null;\n private tiktoken: any = null;\n\n constructor(config: ONNXLocalConfig = {}) {\n this.config = {\n modelPath: config.modelPath || './models/phi-4/cpu_and_mobile/cpu-int4-rtn-block-32-acc-level-4/model.onnx',\n executionProviders: config.executionProviders || ['cpu'],\n maxTokens: config.maxTokens || 100,\n temperature: config.temperature || 0.7\n };\n }\n\n /**\n * Load optimized tiktoken tokenizer (cl100k_base for Phi-4)\n */\n private async loadTokenizer(): Promise<void> {\n if (this.tiktoken) return;\n\n try {\n // Use cl100k_base encoding (GPT-4, similar to Phi-4)\n this.tiktoken = get_encoding('cl100k_base');\n\n console.log('โœ… Tokenizer loaded (tiktoken cl100k_base)');\n } catch (error) {\n console.error('โŒ Failed to load tiktoken:', error);\n throw new Error(`Tokenizer loading failed: ${error}`);\n }\n }\n\n /**\n * Encode text using tiktoken (fast BPE)\n */\n private encode(text: string): number[] {\n return Array.from(this.tiktoken.encode(text));\n }\n\n /**\n * Decode tokens using tiktoken\n */\n private decode(ids: number[]): string {\n try {\n const decoded = this.tiktoken.decode(new Uint32Array(ids));\n // tiktoken returns buffer, convert to string\n if (typeof decoded === 'string') {\n return decoded;\n } else if (decoded instanceof Uint8Array || decoded instanceof Buffer) {\n return new TextDecoder().decode(decoded);\n }\n return String(decoded);\n } catch (error) {\n console.warn('Decode error, returning raw IDs:', error);\n return ids.join(',');\n }\n }\n\n /**\n * Initialize ONNX session (with automatic model download)\n */\n private async initializeSession(): Promise<void> {\n if (this.session) return;\n\n if (!ortAvailable || !ort) {\n throw new Error('onnxruntime-node not available - install with: npm install onnxruntime-node');\n }\n\n try {\n // Ensure model is downloaded\n console.log(`๐Ÿ” Checking for Phi-4 ONNX model...`);\n\n const modelPath = await ensurePhi4Model((progress) => {\n if (progress.percentage % 10 < 1) { // Log every ~10%\n console.log(` ๐Ÿ“ฅ Downloading: ${ModelDownloader.formatProgress(progress)}`);\n }\n });\n\n // Update config with actual model path\n this.config.modelPath = modelPath;\n\n console.log(`๐Ÿ“ฆ Loading ONNX model: ${this.config.modelPath}`);\n\n this.session = await ort.InferenceSession.create(\n this.config.modelPath,\n {\n executionProviders: this.config.executionProviders as any,\n graphOptimizationLevel: 'all',\n enableCpuMemArena: true,\n enableMemPattern: true\n }\n );\n\n console.log(`โœ… ONNX model loaded`);\n console.log(`๐Ÿ”ง Execution providers: ${this.config.executionProviders.join(', ')}`);\n\n // Load tokenizer\n await this.loadTokenizer();\n\n } catch (error) {\n const providerError: ProviderError = {\n name: 'ONNXInitError',\n message: `Failed to initialize ONNX model: ${error}`,\n provider: 'onnx-local',\n retryable: false\n };\n throw providerError;\n }\n }\n\n /**\n * Format messages for Phi-4 chat template\n */\n private formatMessages(messages: Message[]): string {\n let prompt = '';\n\n for (const msg of messages) {\n const content = typeof msg.content === 'string'\n ? msg.content\n : msg.content.map(c => c.type === 'text' ? c.text : '').join('');\n\n if (msg.role === 'system') {\n prompt += `<|system|>\\n${content}<|end|>\\n`;\n } else if (msg.role === 'user') {\n prompt += `<|user|>\\n${content}<|end|>\\n`;\n } else if (msg.role === 'assistant') {\n prompt += `<|assistant|>\\n${content}<|end|>\\n`;\n }\n }\n\n prompt += '<|assistant|>\\n';\n return prompt;\n }\n\n /**\n * Initialize KV cache tensors for all 32 layers\n * Phi-4 architecture: 32 layers, 8 KV heads, 128 head_dim\n */\n private initializeKVCache(batchSize: number, sequenceLength: number) {\n const numLayers = 32;\n const numKVHeads = 8;\n const headDim = 128; // 3072 / 24 = 128\n const kvCache: Record<string, any> = {};\n\n // Get Tensor constructor - use any for flexible access\n const TensorClass = (ort as any).Tensor;\n\n // Initialize empty cache for each layer (key and value)\n for (let i = 0; i < numLayers; i++) {\n // Empty cache: [batch_size, num_kv_heads, 0, head_dim]\n const emptyCache = new Float32Array(0);\n\n kvCache[`past_key_values.${i}.key`] = new TensorClass(\n 'float32',\n emptyCache,\n [batchSize, numKVHeads, 0, headDim]\n );\n\n kvCache[`past_key_values.${i}.value`] = new TensorClass(\n 'float32',\n emptyCache,\n [batchSize, numKVHeads, 0, headDim]\n );\n }\n\n return kvCache;\n }\n\n /**\n * Chat completion using ONNX with KV cache\n */\n async chat(params: ChatParams): Promise<ChatResponse> {\n await this.initializeSession();\n\n const startTime = Date.now();\n const prompt = this.formatMessages(params.messages);\n\n try {\n // Tokenize input using optimized tiktoken\n const inputIds = this.encode(prompt);\n console.log(`๐Ÿ“ Input tokens: ${inputIds.length}`);\n\n // Initialize KV cache (reusable for batch)\n let pastKVCache = this.initializeKVCache(1, 0);\n\n // Track all generated tokens\n const allTokenIds = [...inputIds];\n const outputIds: number[] = [];\n\n // Pre-allocate tensor buffers for performance\n const maxSeqLen = inputIds.length + (params.maxTokens || this.config.maxTokens);\n\n // Autoregressive generation loop\n const maxNewTokens = params.maxTokens || this.config.maxTokens;\n\n for (let step = 0; step < maxNewTokens; step++) {\n // For first step, use all input tokens; for subsequent steps, use only last token\n const currentInputIds = step === 0 ? inputIds : [outputIds[outputIds.length - 1]];\n const currentSeqLen = currentInputIds.length;\n\n // Get Tensor constructor - use any for flexible access\n const TensorClass = (ort as any).Tensor;\n\n // Create input tensor for current step\n const inputTensor = new TensorClass(\n 'int64',\n BigInt64Array.from(currentInputIds.map(BigInt)),\n [1, currentSeqLen]\n );\n\n // Create attention mask for current step\n const totalSeqLen = allTokenIds.length;\n const attentionMask = new TensorClass(\n 'int64',\n BigInt64Array.from(Array(totalSeqLen).fill(1n)),\n [1, totalSeqLen]\n );\n\n // Build feeds with input, attention mask, and KV cache\n const feeds: Record<string, any> = {\n input_ids: inputTensor,\n attention_mask: attentionMask,\n ...pastKVCache\n };\n\n // Run inference\n const results = await this.session!.run(feeds);\n\n // Get logits for next token (last position)\n const logits = results.logits.data as Float32Array;\n const vocabSize = results.logits.dims[results.logits.dims.length - 1];\n\n // Extract logits for last token\n const lastTokenLogitsOffset = (currentSeqLen - 1) * vocabSize;\n\n // Apply temperature and get next token\n let nextToken = 0;\n let maxVal = -Infinity;\n\n for (let i = 0; i < vocabSize; i++) {\n const logit = logits[lastTokenLogitsOffset + i] / (params.temperature || this.config.temperature);\n if (logit > maxVal) {\n maxVal = logit;\n nextToken = i;\n }\n }\n\n // Add to output\n outputIds.push(nextToken);\n allTokenIds.push(nextToken);\n\n // Check for end token (2 is typical EOS for Phi models)\n if (nextToken === 2 || nextToken === 0) {\n console.log(`๐Ÿ›‘ Stop token detected: ${nextToken}`);\n break;\n }\n\n // Update KV cache from outputs for next iteration\n pastKVCache = {};\n for (let i = 0; i < 32; i++) {\n pastKVCache[`past_key_values.${i}.key`] = results[`present.${i}.key`];\n pastKVCache[`past_key_values.${i}.value`] = results[`present.${i}.value`];\n }\n\n // Progress indicator\n if ((step + 1) % 10 === 0) {\n console.log(`๐Ÿ”„ Generated ${step + 1} tokens...`);\n }\n }\n\n // Decode output using optimized tiktoken\n const generatedText = this.decode(outputIds);\n const latency = Date.now() - startTime;\n const tokensPerSecond = (outputIds.length / (latency / 1000)).toFixed(1);\n\n console.log(`โœ… Generated: ${generatedText}`);\n console.log(`โฑ๏ธ Latency: ${latency}ms (${tokensPerSecond} tokens/sec)`);\n\n const content: ContentBlock[] = [{\n type: 'text',\n text: generatedText.trim()\n }];\n\n return {\n id: `onnx-local-${Date.now()}`,\n model: this.config.modelPath,\n content,\n stopReason: 'end_turn',\n usage: {\n inputTokens: inputIds.length,\n outputTokens: outputIds.length\n },\n metadata: {\n provider: 'onnx-local',\n model: 'Phi-4-mini-instruct-onnx',\n latency,\n cost: 0, // Local inference is free\n executionProviders: this.config.executionProviders,\n tokensPerSecond: parseFloat(tokensPerSecond)\n }\n };\n\n } catch (error) {\n const providerError: ProviderError = {\n name: 'ONNXInferenceError',\n message: `ONNX inference failed: ${error}`,\n provider: 'onnx-local',\n retryable: true\n };\n throw providerError;\n }\n }\n\n /**\n * Streaming not implemented (requires complex generation loop)\n */\n async *stream(params: ChatParams): AsyncGenerator<StreamChunk> {\n throw new Error('Streaming not yet implemented for ONNX local inference');\n }\n\n /**\n * Validate capabilities\n */\n validateCapabilities(features: string[]): boolean {\n const supported = ['chat'];\n return features.every(f => supported.includes(f));\n }\n\n /**\n * Get model info\n */\n getModelInfo() {\n return {\n modelPath: this.config.modelPath,\n executionProviders: this.config.executionProviders,\n initialized: this.session !== null,\n tokenizerLoaded: this.tiktoken !== null\n };\n }\n\n /**\n * Cleanup resources\n */\n async dispose(): Promise<void> {\n if (this.session) {\n // ONNX Runtime sessions don't have explicit disposal in Node.js\n this.session = null;\n }\n if (this.tiktoken) {\n this.tiktoken.free();\n this.tiktoken = null;\n }\n }\n}\n"]}
1
+ {"version":3,"file":"onnx-local.js","sourceRoot":"","sources":["../../../src/router/providers/onnx-local.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * ONNX Runtime Local Inference Provider for Phi-4\n *\n * Uses onnxruntime-node for true local CPU/GPU inference\n * Falls back gracefully when native module isn't available (Windows)\n *\n * NOTE (ruvnet/ruflo#2048): `onnxruntime-node` is loaded LAZILY on first\n * `initializeSession()` call, not at module import. The previous top-level\n * `await import('onnxruntime-node')` fired the native-binding load\n * (`onnxruntime_binding.node`) at module load time, which crashed Windows\n * environments where the NAPI binary cannot be loaded โ€” even when the\n * consumer (e.g. `agentic-flow/reasoningbank`) never actually invokes\n * the router. Moving the import inside `loadOrt()` keeps importing\n * `reasoningbank` side-effect-free with respect to native bindings.\n */\n\nlet ort: any = null;\nlet ortAvailable = false;\nlet ortLoaded = false;\n\nasync function loadOrt(): Promise<void> {\n if (ortLoaded) return;\n ortLoaded = true;\n try {\n ort = await import('onnxruntime-node');\n ortAvailable = true;\n } catch {\n console.warn('[ONNX] onnxruntime-node not available - local inference disabled');\n }\n}\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { get_encoding } from 'tiktoken';\nimport { ensurePhi4Model, ModelDownloader, PHI4_MODEL_PATH } from '../../utils/model-downloader.js';\nimport type {\n LLMProvider,\n ChatParams,\n ChatResponse,\n StreamChunk,\n ProviderError,\n Message,\n ContentBlock\n} from '../types.js';\n\nexport interface ONNXLocalConfig {\n modelPath?: string;\n executionProviders?: string[];\n maxTokens?: number;\n temperature?: number;\n}\n\nexport class ONNXLocalProvider implements LLMProvider {\n name = 'onnx-local';\n type = 'custom' as const;\n supportsStreaming = false; // Streaming requires complex token generation loop\n supportsTools = false;\n supportsMCP = false;\n\n private session: any = null;\n private config: Required<ONNXLocalConfig>;\n private tokenizer: any = null;\n private tiktoken: any = null;\n\n constructor(config: ONNXLocalConfig = {}) {\n this.config = {\n modelPath: config.modelPath || PHI4_MODEL_PATH,\n executionProviders: config.executionProviders || ['cpu'],\n maxTokens: config.maxTokens || 100,\n temperature: config.temperature || 0.7\n };\n }\n\n /**\n * Load optimized tiktoken tokenizer (cl100k_base for Phi-4)\n */\n private async loadTokenizer(): Promise<void> {\n if (this.tiktoken) return;\n\n try {\n // Use cl100k_base encoding (GPT-4, similar to Phi-4)\n this.tiktoken = get_encoding('cl100k_base');\n\n console.log('โœ… Tokenizer loaded (tiktoken cl100k_base)');\n } catch (error) {\n console.error('โŒ Failed to load tiktoken:', error);\n throw new Error(`Tokenizer loading failed: ${error}`);\n }\n }\n\n /**\n * Encode text using tiktoken (fast BPE)\n */\n private encode(text: string): number[] {\n return Array.from(this.tiktoken.encode(text));\n }\n\n /**\n * Decode tokens using tiktoken\n */\n private decode(ids: number[]): string {\n try {\n const decoded = this.tiktoken.decode(new Uint32Array(ids));\n // tiktoken returns buffer, convert to string\n if (typeof decoded === 'string') {\n return decoded;\n } else if (decoded instanceof Uint8Array || decoded instanceof Buffer) {\n return new TextDecoder().decode(decoded);\n }\n return String(decoded);\n } catch (error) {\n console.warn('Decode error, returning raw IDs:', error);\n return ids.join(',');\n }\n }\n\n /**\n * Initialize ONNX session (with automatic model download)\n */\n private async initializeSession(): Promise<void> {\n if (this.session) return;\n\n await loadOrt();\n if (!ortAvailable || !ort) {\n throw new Error('onnxruntime-node not available - install with: npm install onnxruntime-node');\n }\n\n try {\n // Ensure model is downloaded\n console.log(`๐Ÿ” Checking for Phi-4 ONNX model...`);\n\n const modelPath = await ensurePhi4Model((progress) => {\n if (progress.percentage % 10 < 1) { // Log every ~10%\n console.log(` ๐Ÿ“ฅ Downloading: ${ModelDownloader.formatProgress(progress)}`);\n }\n });\n\n // Update config with actual model path\n this.config.modelPath = modelPath;\n\n console.log(`๐Ÿ“ฆ Loading ONNX model: ${this.config.modelPath}`);\n\n this.session = await ort.InferenceSession.create(\n this.config.modelPath,\n {\n executionProviders: this.config.executionProviders as any,\n graphOptimizationLevel: 'all',\n enableCpuMemArena: true,\n enableMemPattern: true\n }\n );\n\n console.log(`โœ… ONNX model loaded`);\n console.log(`๐Ÿ”ง Execution providers: ${this.config.executionProviders.join(', ')}`);\n\n // Load tokenizer\n await this.loadTokenizer();\n\n } catch (error) {\n const providerError: ProviderError = {\n name: 'ONNXInitError',\n message: `Failed to initialize ONNX model: ${error}`,\n provider: 'onnx-local',\n retryable: false\n };\n throw providerError;\n }\n }\n\n /**\n * Format messages for Phi-4 chat template\n */\n private formatMessages(messages: Message[]): string {\n let prompt = '';\n\n for (const msg of messages) {\n const content = typeof msg.content === 'string'\n ? msg.content\n : msg.content.map(c => c.type === 'text' ? c.text : '').join('');\n\n if (msg.role === 'system') {\n prompt += `<|system|>\\n${content}<|end|>\\n`;\n } else if (msg.role === 'user') {\n prompt += `<|user|>\\n${content}<|end|>\\n`;\n } else if (msg.role === 'assistant') {\n prompt += `<|assistant|>\\n${content}<|end|>\\n`;\n }\n }\n\n prompt += '<|assistant|>\\n';\n return prompt;\n }\n\n /**\n * Initialize KV cache tensors for all 32 layers\n * Phi-4 architecture: 32 layers, 8 KV heads, 128 head_dim\n */\n private initializeKVCache(batchSize: number, sequenceLength: number) {\n const numLayers = 32;\n const numKVHeads = 8;\n const headDim = 128; // 3072 / 24 = 128\n const kvCache: Record<string, any> = {};\n\n // Get Tensor constructor - use any for flexible access\n const TensorClass = (ort as any).Tensor;\n\n // Initialize empty cache for each layer (key and value)\n for (let i = 0; i < numLayers; i++) {\n // Empty cache: [batch_size, num_kv_heads, 0, head_dim]\n const emptyCache = new Float32Array(0);\n\n kvCache[`past_key_values.${i}.key`] = new TensorClass(\n 'float32',\n emptyCache,\n [batchSize, numKVHeads, 0, headDim]\n );\n\n kvCache[`past_key_values.${i}.value`] = new TensorClass(\n 'float32',\n emptyCache,\n [batchSize, numKVHeads, 0, headDim]\n );\n }\n\n return kvCache;\n }\n\n /**\n * Chat completion using ONNX with KV cache\n */\n async chat(params: ChatParams): Promise<ChatResponse> {\n await this.initializeSession();\n\n const startTime = Date.now();\n const prompt = this.formatMessages(params.messages);\n\n try {\n // Tokenize input using optimized tiktoken\n const inputIds = this.encode(prompt);\n console.log(`๐Ÿ“ Input tokens: ${inputIds.length}`);\n\n // Initialize KV cache (reusable for batch)\n let pastKVCache = this.initializeKVCache(1, 0);\n\n // Track all generated tokens\n const allTokenIds = [...inputIds];\n const outputIds: number[] = [];\n\n // Pre-allocate tensor buffers for performance\n const maxSeqLen = inputIds.length + (params.maxTokens || this.config.maxTokens);\n\n // Autoregressive generation loop\n const maxNewTokens = params.maxTokens || this.config.maxTokens;\n\n for (let step = 0; step < maxNewTokens; step++) {\n // For first step, use all input tokens; for subsequent steps, use only last token\n const currentInputIds = step === 0 ? inputIds : [outputIds[outputIds.length - 1]];\n const currentSeqLen = currentInputIds.length;\n\n // Get Tensor constructor - use any for flexible access\n const TensorClass = (ort as any).Tensor;\n\n // Create input tensor for current step\n const inputTensor = new TensorClass(\n 'int64',\n BigInt64Array.from(currentInputIds.map(BigInt)),\n [1, currentSeqLen]\n );\n\n // Create attention mask for current step\n const totalSeqLen = allTokenIds.length;\n const attentionMask = new TensorClass(\n 'int64',\n BigInt64Array.from(Array(totalSeqLen).fill(1n)),\n [1, totalSeqLen]\n );\n\n // Build feeds with input, attention mask, and KV cache\n const feeds: Record<string, any> = {\n input_ids: inputTensor,\n attention_mask: attentionMask,\n ...pastKVCache\n };\n\n // Run inference\n const results = await this.session!.run(feeds);\n\n // Get logits for next token (last position)\n const logits = results.logits.data as Float32Array;\n const vocabSize = results.logits.dims[results.logits.dims.length - 1];\n\n // Extract logits for last token\n const lastTokenLogitsOffset = (currentSeqLen - 1) * vocabSize;\n\n // Apply temperature and get next token\n let nextToken = 0;\n let maxVal = -Infinity;\n\n for (let i = 0; i < vocabSize; i++) {\n const logit = logits[lastTokenLogitsOffset + i] / (params.temperature || this.config.temperature);\n if (logit > maxVal) {\n maxVal = logit;\n nextToken = i;\n }\n }\n\n // Add to output\n outputIds.push(nextToken);\n allTokenIds.push(nextToken);\n\n // Check for end token (2 is typical EOS for Phi models)\n if (nextToken === 2 || nextToken === 0) {\n console.log(`๐Ÿ›‘ Stop token detected: ${nextToken}`);\n break;\n }\n\n // Update KV cache from outputs for next iteration\n pastKVCache = {};\n for (let i = 0; i < 32; i++) {\n pastKVCache[`past_key_values.${i}.key`] = results[`present.${i}.key`];\n pastKVCache[`past_key_values.${i}.value`] = results[`present.${i}.value`];\n }\n\n // Progress indicator\n if ((step + 1) % 10 === 0) {\n console.log(`๐Ÿ”„ Generated ${step + 1} tokens...`);\n }\n }\n\n // Decode output using optimized tiktoken\n const generatedText = this.decode(outputIds);\n const latency = Date.now() - startTime;\n const tokensPerSecond = (outputIds.length / (latency / 1000)).toFixed(1);\n\n console.log(`โœ… Generated: ${generatedText}`);\n console.log(`โฑ๏ธ Latency: ${latency}ms (${tokensPerSecond} tokens/sec)`);\n\n const content: ContentBlock[] = [{\n type: 'text',\n text: generatedText.trim()\n }];\n\n return {\n id: `onnx-local-${Date.now()}`,\n model: this.config.modelPath,\n content,\n stopReason: 'end_turn',\n usage: {\n inputTokens: inputIds.length,\n outputTokens: outputIds.length\n },\n metadata: {\n provider: 'onnx-local',\n model: 'Phi-4-mini-instruct-onnx',\n latency,\n cost: 0, // Local inference is free\n executionProviders: this.config.executionProviders,\n tokensPerSecond: parseFloat(tokensPerSecond)\n }\n };\n\n } catch (error) {\n const providerError: ProviderError = {\n name: 'ONNXInferenceError',\n message: `ONNX inference failed: ${error}`,\n provider: 'onnx-local',\n retryable: true\n };\n throw providerError;\n }\n }\n\n /**\n * Streaming not implemented (requires complex generation loop)\n */\n async *stream(params: ChatParams): AsyncGenerator<StreamChunk> {\n throw new Error('Streaming not yet implemented for ONNX local inference');\n }\n\n /**\n * Validate capabilities\n */\n validateCapabilities(features: string[]): boolean {\n const supported = ['chat'];\n return features.every(f => supported.includes(f));\n }\n\n /**\n * Get model info\n */\n getModelInfo() {\n return {\n modelPath: this.config.modelPath,\n executionProviders: this.config.executionProviders,\n initialized: this.session !== null,\n tokenizerLoaded: this.tiktoken !== null\n };\n }\n\n /**\n * Cleanup resources\n */\n async dispose(): Promise<void> {\n if (this.session) {\n // ONNX Runtime sessions don't have explicit disposal in Node.js\n this.session = null;\n }\n if (this.tiktoken) {\n this.tiktoken.free();\n this.tiktoken = null;\n }\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"onnx-phi4.d.ts","sourceRoot":"","sources":["../../../src/router/providers/onnx-phi4.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,YAAY,EACZ,WAAW,EAIZ,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,qBAAa,gBAAiB,YAAW,WAAW;IAClD,IAAI,SAAe;IACnB,IAAI,EAAG,QAAQ,CAAU;IACzB,iBAAiB,UAAQ;IACzB,aAAa,UAAS;IACtB,WAAW,UAAS;IAEpB,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,EAAE,CAAc;IACxB,OAAO,CAAC,SAAS,CAAgF;gBAErF,MAAM,GAAE,cAAmB;IAYvC;;OAEG;IACH,OAAO,CAAC,cAAc;IAqBtB;;OAEG;YACW,UAAU;IA+DxB;;OAEG;YACW,WAAW;IAIzB;;OAEG;IACG,IAAI,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC;IAQrD;;OAEG;IACI,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,cAAc,CAAC,WAAW,CAAC;IAyC9D;;OAEG;IACH,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO;IAKjD;;OAEG;IACH,YAAY;;;;;;;IAUZ;;OAEG;IACH,OAAO,CAAC,YAAY,EAAE,OAAO;CAG9B"}
1
+ {"version":3,"file":"onnx-phi4.d.ts","sourceRoot":"","sources":["../../../src/router/providers/onnx-phi4.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,YAAY,EACZ,WAAW,EAIZ,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,qBAAa,gBAAiB,YAAW,WAAW;IAClD,IAAI,SAAe;IACnB,IAAI,EAAG,QAAQ,CAAU;IACzB,iBAAiB,UAAQ;IACzB,aAAa,UAAS;IACtB,WAAW,UAAS;IAEpB,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,EAAE,CAAc;IACxB,OAAO,CAAC,SAAS,CAAmB;gBAExB,MAAM,GAAE,cAAmB;IAYvC;;OAEG;IACH,OAAO,CAAC,cAAc;IAqBtB;;OAEG;YACW,UAAU;IA+DxB;;OAEG;YACW,WAAW;IAIzB;;OAEG;IACG,IAAI,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC;IAQrD;;OAEG;IACI,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,cAAc,CAAC,WAAW,CAAC;IAyC9D;;OAEG;IACH,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO;IAKjD;;OAEG;IACH,YAAY;;;;;;;IAUZ;;OAEG;IACH,OAAO,CAAC,YAAY,EAAE,OAAO;CAG9B"}
@@ -5,6 +5,7 @@
5
5
  * when local ONNX model is not available
6
6
  */
7
7
  import { HfInference } from '@huggingface/inference';
8
+ import { PHI4_MODEL_PATH } from '../../utils/model-downloader.js';
8
9
  export class ONNXPhi4Provider {
9
10
  name = 'onnx-phi4';
10
11
  type = 'custom';
@@ -13,7 +14,7 @@ export class ONNXPhi4Provider {
13
14
  supportsMCP = false;
14
15
  config;
15
16
  hf;
16
- modelPath = './models/phi-4/cpu_and_mobile/cpu-int4-rtn-block-32-acc-level-4/model.onnx';
17
+ modelPath = PHI4_MODEL_PATH;
17
18
  constructor(config = {}) {
18
19
  this.config = {
19
20
  modelId: config.modelId || 'microsoft/Phi-3-mini-4k-instruct',
@@ -1 +1 @@
1
- {"version":3,"file":"onnx-phi4.js","sourceRoot":"","sources":["../../../src/router/providers/onnx-phi4.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAmBrD,MAAM,OAAO,gBAAgB;IAC3B,IAAI,GAAG,WAAW,CAAC;IACnB,IAAI,GAAG,QAAiB,CAAC;IACzB,iBAAiB,GAAG,IAAI,CAAC;IACzB,aAAa,GAAG,KAAK,CAAC;IACtB,WAAW,GAAG,KAAK,CAAC;IAEZ,MAAM,CAA2B;IACjC,EAAE,CAAc;IAChB,SAAS,GAAG,4EAA4E,CAAC;IAEjG,YAAY,SAAyB,EAAE;QACrC,IAAI,CAAC,MAAM,GAAG;YACZ,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,kCAAkC;YAC7D,YAAY,EAAE,MAAM,CAAC,YAAY,IAAI,KAAK,EAAE,8CAA8C;YAC1F,iBAAiB,EAAE,MAAM,CAAC,iBAAiB,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,EAAE;YACpF,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,GAAG;YAClC,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,GAAG;SACvC,CAAC;QAEF,IAAI,CAAC,EAAE,GAAG,IAAI,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;IAC3D,CAAC;IAED;;OAEG;IACK,cAAc,CAAC,QAAmB;QACxC,IAAI,MAAM,GAAG,EAAE,CAAC;QAEhB,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;YAC3B,MAAM,OAAO,GAAG,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ;gBAC7C,CAAC,CAAC,GAAG,CAAC,OAAO;gBACb,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEnE,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC1B,MAAM,IAAI,eAAe,OAAO,WAAW,CAAC;YAC9C,CAAC;iBAAM,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBAC/B,MAAM,IAAI,aAAa,OAAO,WAAW,CAAC;YAC5C,CAAC;iBAAM,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;gBACpC,MAAM,IAAI,kBAAkB,OAAO,WAAW,CAAC;YACjD,CAAC;QACH,CAAC;QAED,MAAM,IAAI,iBAAiB,CAAC;QAC5B,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,UAAU,CAAC,MAAkB;QACzC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAEpD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,cAAc,CAAC;gBAC1C,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO;gBAC1B,MAAM,EAAE,MAAM;gBACd,UAAU,EAAE;oBACV,cAAc,EAAE,MAAM,CAAC,SAAS,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS;oBACzD,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW;oBAC1D,gBAAgB,EAAE,KAAK;oBACvB,SAAS,EAAE,IAAI;oBACf,KAAK,EAAE,GAAG;iBACX;aACF,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;YACvC,MAAM,aAAa,GAAG,MAAM,CAAC,cAAc,CAAC;YAE5C,wBAAwB;YACxB,MAAM,iBAAiB,GAAG,aAAa;iBACpC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;iBACnB,IAAI,EAAE,CAAC;YAEV,wBAAwB;YACxB,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YACjD,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAE7D,MAAM,OAAO,GAAmB,CAAC;oBAC/B,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,iBAAiB;iBACxB,CAAC,CAAC;YAEH,OAAO;gBACL,EAAE,EAAE,aAAa,IAAI,CAAC,GAAG,EAAE,EAAE;gBAC7B,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO;gBAC1B,OAAO;gBACP,UAAU,EAAE,UAAU;gBACtB,KAAK,EAAE;oBACL,WAAW;oBACX,YAAY;iBACb;gBACD,QAAQ,EAAE;oBACR,QAAQ,EAAE,WAAW;oBACrB,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO;oBAC1B,OAAO;oBACP,IAAI,EAAE,YAAY,GAAG,QAAQ,EAAE,iBAAiB;oBAChD,IAAI,EAAE,KAAK;iBACZ;aACF,CAAC;QAEJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,aAAa,GAAkB;gBACnC,IAAI,EAAE,kBAAkB;gBACxB,OAAO,EAAE,qCAAqC,KAAK,EAAE;gBACrD,QAAQ,EAAE,WAAW;gBACrB,SAAS,EAAE,IAAI;aAChB,CAAC;YACF,MAAM,aAAa,CAAC;QACtB,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,WAAW,CAAC,MAAkB;QAC1C,MAAM,IAAI,KAAK,CAAC,2EAA2E,CAAC,CAAC;IAC/F,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,IAAI,CAAC,MAAkB;QAC3B,IAAI,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;YAC7B,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAClC,CAAC;aAAM,CAAC;YACN,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,CAAC,MAAM,CAAC,MAAkB;QAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAEpD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,oBAAoB,CAAC;gBAC1C,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO;gBAC1B,MAAM,EAAE,MAAM;gBACd,UAAU,EAAE;oBACV,cAAc,EAAE,MAAM,CAAC,SAAS,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS;oBACzD,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW;oBAC1D,gBAAgB,EAAE,KAAK;iBACxB;aACF,CAAC,CAAC;YAEH,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBACjC,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;oBACrB,MAAM;wBACJ,IAAI,EAAE,qBAAqB;wBAC3B,KAAK,EAAE;4BACL,IAAI,EAAE,YAAY;4BAClB,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI;yBACvB;qBACF,CAAC;gBACJ,CAAC;YACH,CAAC;YAED,MAAM;gBACJ,IAAI,EAAE,cAAc;aACrB,CAAC;QAEJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,aAAa,GAAkB;gBACnC,IAAI,EAAE,qBAAqB;gBAC3B,OAAO,EAAE,qBAAqB,KAAK,EAAE;gBACrC,QAAQ,EAAE,WAAW;gBACrB,SAAS,EAAE,IAAI;aAChB,CAAC;YACF,MAAM,aAAa,CAAC;QACtB,CAAC;IACH,CAAC;IAED;;OAEG;IACH,oBAAoB,CAAC,QAAkB;QACrC,MAAM,SAAS,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACrC,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACpD,CAAC;IAED;;OAEG;IACH,YAAY;QACV,OAAO;YACL,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO;YAC5B,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK;YACrD,sBAAsB,EAAE,KAAK,EAAE,+CAA+C;YAC9E,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;SAC1D,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,YAAqB;QAC3B,IAAI,CAAC,MAAM,CAAC,YAAY,GAAG,YAAY,CAAC;IAC1C,CAAC;CACF","sourcesContent":["/**\n * ONNX Runtime Provider for Phi-4 Model\n *\n * Hybrid implementation with fallback to HuggingFace Inference API\n * when local ONNX model is not available\n */\n\nimport { HfInference } from '@huggingface/inference';\nimport type {\n LLMProvider,\n ChatParams,\n ChatResponse,\n StreamChunk,\n ProviderError,\n Message,\n ContentBlock\n} from '../types.js';\n\nexport interface ONNXPhi4Config {\n modelId?: string;\n useLocalONNX?: boolean;\n huggingfaceApiKey?: string;\n maxTokens?: number;\n temperature?: number;\n}\n\nexport class ONNXPhi4Provider implements LLMProvider {\n name = 'onnx-phi4';\n type = 'custom' as const;\n supportsStreaming = true;\n supportsTools = false;\n supportsMCP = false;\n\n private config: Required<ONNXPhi4Config>;\n private hf: HfInference;\n private modelPath = './models/phi-4/cpu_and_mobile/cpu-int4-rtn-block-32-acc-level-4/model.onnx';\n\n constructor(config: ONNXPhi4Config = {}) {\n this.config = {\n modelId: config.modelId || 'microsoft/Phi-3-mini-4k-instruct',\n useLocalONNX: config.useLocalONNX ?? false, // Default to API until local model downloaded\n huggingfaceApiKey: config.huggingfaceApiKey || process.env.HUGGINGFACE_API_KEY || '',\n maxTokens: config.maxTokens || 512,\n temperature: config.temperature || 0.7\n };\n\n this.hf = new HfInference(this.config.huggingfaceApiKey);\n }\n\n /**\n * Format messages for Phi-4 chat template\n */\n private formatMessages(messages: Message[]): string {\n let prompt = '';\n\n for (const msg of messages) {\n const content = typeof msg.content === 'string'\n ? msg.content\n : msg.content.map(c => c.type === 'text' ? c.text : '').join('');\n\n if (msg.role === 'system') {\n prompt += `<|system|>\\n${content}<|end|>\\n`;\n } else if (msg.role === 'user') {\n prompt += `<|user|>\\n${content}<|end|>\\n`;\n } else if (msg.role === 'assistant') {\n prompt += `<|assistant|>\\n${content}<|end|>\\n`;\n }\n }\n\n prompt += '<|assistant|>\\n';\n return prompt;\n }\n\n /**\n * Chat completion via HuggingFace Inference API\n */\n private async chatViaAPI(params: ChatParams): Promise<ChatResponse> {\n const startTime = Date.now();\n const prompt = this.formatMessages(params.messages);\n\n try {\n const result = await this.hf.textGeneration({\n model: this.config.modelId,\n inputs: prompt,\n parameters: {\n max_new_tokens: params.maxTokens || this.config.maxTokens,\n temperature: params.temperature || this.config.temperature,\n return_full_text: false,\n do_sample: true,\n top_p: 0.9\n }\n });\n\n const latency = Date.now() - startTime;\n const generatedText = result.generated_text;\n\n // Clean up the response\n const assistantResponse = generatedText\n .split('<|end|>')[0]\n .trim();\n\n // Estimate token counts\n const inputTokens = Math.ceil(prompt.length / 4);\n const outputTokens = Math.ceil(assistantResponse.length / 4);\n\n const content: ContentBlock[] = [{\n type: 'text',\n text: assistantResponse\n }];\n\n return {\n id: `onnx-phi4-${Date.now()}`,\n model: this.config.modelId,\n content,\n stopReason: 'end_turn',\n usage: {\n inputTokens,\n outputTokens\n },\n metadata: {\n provider: 'onnx-phi4',\n model: this.config.modelId,\n latency,\n cost: outputTokens * 0.000002, // Rough estimate\n mode: 'api'\n }\n };\n\n } catch (error) {\n const providerError: ProviderError = {\n name: 'ONNXPhi4APIError',\n message: `HuggingFace API inference failed: ${error}`,\n provider: 'onnx-phi4',\n retryable: true\n };\n throw providerError;\n }\n }\n\n /**\n * Chat completion via local ONNX (not yet implemented)\n */\n private async chatViaONNX(params: ChatParams): Promise<ChatResponse> {\n throw new Error('Local ONNX inference not yet implemented. Download model.onnx.data first.');\n }\n\n /**\n * Chat completion (uses API or local ONNX based on config)\n */\n async chat(params: ChatParams): Promise<ChatResponse> {\n if (this.config.useLocalONNX) {\n return this.chatViaONNX(params);\n } else {\n return this.chatViaAPI(params);\n }\n }\n\n /**\n * Streaming generation via HuggingFace API\n */\n async *stream(params: ChatParams): AsyncGenerator<StreamChunk> {\n const prompt = this.formatMessages(params.messages);\n\n try {\n const stream = this.hf.textGenerationStream({\n model: this.config.modelId,\n inputs: prompt,\n parameters: {\n max_new_tokens: params.maxTokens || this.config.maxTokens,\n temperature: params.temperature || this.config.temperature,\n return_full_text: false\n }\n });\n\n for await (const chunk of stream) {\n if (chunk.token.text) {\n yield {\n type: 'content_block_delta',\n delta: {\n type: 'text_delta',\n text: chunk.token.text\n }\n };\n }\n }\n\n yield {\n type: 'message_stop'\n };\n\n } catch (error) {\n const providerError: ProviderError = {\n name: 'ONNXPhi4StreamError',\n message: `Streaming failed: ${error}`,\n provider: 'onnx-phi4',\n retryable: true\n };\n throw providerError;\n }\n }\n\n /**\n * Validate capabilities\n */\n validateCapabilities(features: string[]): boolean {\n const supported = ['chat', 'stream'];\n return features.every(f => supported.includes(f));\n }\n\n /**\n * Get model info\n */\n getModelInfo() {\n return {\n modelId: this.config.modelId,\n mode: this.config.useLocalONNX ? 'local-onnx' : 'api',\n supportsLocalInference: false, // Will be true when model.onnx.data downloaded\n modelPath: this.modelPath,\n apiKey: this.config.huggingfaceApiKey ? '***' : undefined\n };\n }\n\n /**\n * Switch between API and local ONNX\n */\n setMode(useLocalONNX: boolean) {\n this.config.useLocalONNX = useLocalONNX;\n }\n}\n"]}
1
+ {"version":3,"file":"onnx-phi4.js","sourceRoot":"","sources":["../../../src/router/providers/onnx-phi4.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * ONNX Runtime Provider for Phi-4 Model\n *\n * Hybrid implementation with fallback to HuggingFace Inference API\n * when local ONNX model is not available\n */\n\nimport { HfInference } from '@huggingface/inference';\nimport { PHI4_MODEL_PATH } from '../../utils/model-downloader.js';\nimport type {\n LLMProvider,\n ChatParams,\n ChatResponse,\n StreamChunk,\n ProviderError,\n Message,\n ContentBlock\n} from '../types.js';\n\nexport interface ONNXPhi4Config {\n modelId?: string;\n useLocalONNX?: boolean;\n huggingfaceApiKey?: string;\n maxTokens?: number;\n temperature?: number;\n}\n\nexport class ONNXPhi4Provider implements LLMProvider {\n name = 'onnx-phi4';\n type = 'custom' as const;\n supportsStreaming = true;\n supportsTools = false;\n supportsMCP = false;\n\n private config: Required<ONNXPhi4Config>;\n private hf: HfInference;\n private modelPath = PHI4_MODEL_PATH;\n\n constructor(config: ONNXPhi4Config = {}) {\n this.config = {\n modelId: config.modelId || 'microsoft/Phi-3-mini-4k-instruct',\n useLocalONNX: config.useLocalONNX ?? false, // Default to API until local model downloaded\n huggingfaceApiKey: config.huggingfaceApiKey || process.env.HUGGINGFACE_API_KEY || '',\n maxTokens: config.maxTokens || 512,\n temperature: config.temperature || 0.7\n };\n\n this.hf = new HfInference(this.config.huggingfaceApiKey);\n }\n\n /**\n * Format messages for Phi-4 chat template\n */\n private formatMessages(messages: Message[]): string {\n let prompt = '';\n\n for (const msg of messages) {\n const content = typeof msg.content === 'string'\n ? msg.content\n : msg.content.map(c => c.type === 'text' ? c.text : '').join('');\n\n if (msg.role === 'system') {\n prompt += `<|system|>\\n${content}<|end|>\\n`;\n } else if (msg.role === 'user') {\n prompt += `<|user|>\\n${content}<|end|>\\n`;\n } else if (msg.role === 'assistant') {\n prompt += `<|assistant|>\\n${content}<|end|>\\n`;\n }\n }\n\n prompt += '<|assistant|>\\n';\n return prompt;\n }\n\n /**\n * Chat completion via HuggingFace Inference API\n */\n private async chatViaAPI(params: ChatParams): Promise<ChatResponse> {\n const startTime = Date.now();\n const prompt = this.formatMessages(params.messages);\n\n try {\n const result = await this.hf.textGeneration({\n model: this.config.modelId,\n inputs: prompt,\n parameters: {\n max_new_tokens: params.maxTokens || this.config.maxTokens,\n temperature: params.temperature || this.config.temperature,\n return_full_text: false,\n do_sample: true,\n top_p: 0.9\n }\n });\n\n const latency = Date.now() - startTime;\n const generatedText = result.generated_text;\n\n // Clean up the response\n const assistantResponse = generatedText\n .split('<|end|>')[0]\n .trim();\n\n // Estimate token counts\n const inputTokens = Math.ceil(prompt.length / 4);\n const outputTokens = Math.ceil(assistantResponse.length / 4);\n\n const content: ContentBlock[] = [{\n type: 'text',\n text: assistantResponse\n }];\n\n return {\n id: `onnx-phi4-${Date.now()}`,\n model: this.config.modelId,\n content,\n stopReason: 'end_turn',\n usage: {\n inputTokens,\n outputTokens\n },\n metadata: {\n provider: 'onnx-phi4',\n model: this.config.modelId,\n latency,\n cost: outputTokens * 0.000002, // Rough estimate\n mode: 'api'\n }\n };\n\n } catch (error) {\n const providerError: ProviderError = {\n name: 'ONNXPhi4APIError',\n message: `HuggingFace API inference failed: ${error}`,\n provider: 'onnx-phi4',\n retryable: true\n };\n throw providerError;\n }\n }\n\n /**\n * Chat completion via local ONNX (not yet implemented)\n */\n private async chatViaONNX(params: ChatParams): Promise<ChatResponse> {\n throw new Error('Local ONNX inference not yet implemented. Download model.onnx.data first.');\n }\n\n /**\n * Chat completion (uses API or local ONNX based on config)\n */\n async chat(params: ChatParams): Promise<ChatResponse> {\n if (this.config.useLocalONNX) {\n return this.chatViaONNX(params);\n } else {\n return this.chatViaAPI(params);\n }\n }\n\n /**\n * Streaming generation via HuggingFace API\n */\n async *stream(params: ChatParams): AsyncGenerator<StreamChunk> {\n const prompt = this.formatMessages(params.messages);\n\n try {\n const stream = this.hf.textGenerationStream({\n model: this.config.modelId,\n inputs: prompt,\n parameters: {\n max_new_tokens: params.maxTokens || this.config.maxTokens,\n temperature: params.temperature || this.config.temperature,\n return_full_text: false\n }\n });\n\n for await (const chunk of stream) {\n if (chunk.token.text) {\n yield {\n type: 'content_block_delta',\n delta: {\n type: 'text_delta',\n text: chunk.token.text\n }\n };\n }\n }\n\n yield {\n type: 'message_stop'\n };\n\n } catch (error) {\n const providerError: ProviderError = {\n name: 'ONNXPhi4StreamError',\n message: `Streaming failed: ${error}`,\n provider: 'onnx-phi4',\n retryable: true\n };\n throw providerError;\n }\n }\n\n /**\n * Validate capabilities\n */\n validateCapabilities(features: string[]): boolean {\n const supported = ['chat', 'stream'];\n return features.every(f => supported.includes(f));\n }\n\n /**\n * Get model info\n */\n getModelInfo() {\n return {\n modelId: this.config.modelId,\n mode: this.config.useLocalONNX ? 'local-onnx' : 'api',\n supportsLocalInference: false, // Will be true when model.onnx.data downloaded\n modelPath: this.modelPath,\n apiKey: this.config.huggingfaceApiKey ? '***' : undefined\n };\n }\n\n /**\n * Switch between API and local ONNX\n */\n setMode(useLocalONNX: boolean) {\n this.config.useLocalONNX = useLocalONNX;\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/router/router.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,WAAW,EACX,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,aAAa,EAGd,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAO7D,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,SAAS,CAA6C;IAC9D,OAAO,CAAC,OAAO,CAAgB;IAE/B,OAAO,CAAC,iBAAiB,CAAC,CAAoB;IAC9C,OAAO,CAAC,UAAU,CAAC,CAAiD;IAGpE,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAO;gBAElC,UAAU,CAAC,EAAE,MAAM;IAM/B,OAAO,CAAC,UAAU;IAwBlB,OAAO,CAAC,mBAAmB;IAiD3B,OAAO,CAAC,iBAAiB;IAwBzB,OAAO,CAAC,mBAAmB;IAkE3B,OAAO,CAAC,iBAAiB;IAUnB,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAuBlE,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,cAAc,CAAC,WAAW,CAAC;YAapE,cAAc;IAmC5B,OAAO,CAAC,kBAAkB;IAQ1B,OAAO,CAAC,aAAa;IAgBrB,OAAO,CAAC,WAAW;IAkBnB,OAAO,CAAC,YAAY;IAgBpB;;;;OAIG;IACH,wBAAwB,CAAC,IAAI,EAAE;QAC7B,MAAM,EAAE,iBAAiB,CAAC;QAC1B,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC;KACvD,GAAG,IAAI;IAMR;;;OAGG;YACW,WAAW;IAgBzB,sEAAsE;IACtE,OAAO,CAAC,YAAY;IAepB;;;;;;OAMG;YACW,mBAAmB;IAyBjC,OAAO,CAAC,mBAAmB;YAqBb,mBAAmB;IA4BjC,OAAO,CAAC,aAAa;IA8CrB,UAAU,IAAI,aAAa;IAI3B,SAAS,IAAI,YAAY;IAIzB,YAAY,IAAI,GAAG,CAAC,YAAY,EAAE,WAAW,CAAC;CAG/C"}
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/router/router.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,WAAW,EACX,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,aAAa,EAGd,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAQ7D,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,SAAS,CAA6C;IAC9D,OAAO,CAAC,OAAO,CAAgB;IAE/B,OAAO,CAAC,iBAAiB,CAAC,CAAoB;IAC9C,OAAO,CAAC,UAAU,CAAC,CAAiD;IAGpE,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAO;gBAElC,UAAU,CAAC,EAAE,MAAM;IAM/B,OAAO,CAAC,UAAU;IAwBlB,OAAO,CAAC,mBAAmB;IAiD3B,OAAO,CAAC,iBAAiB;IAwBzB,OAAO,CAAC,mBAAmB;IAkE3B,OAAO,CAAC,iBAAiB;IAUnB,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAuBlE,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,cAAc,CAAC,WAAW,CAAC;YAapE,cAAc;IAmC5B,OAAO,CAAC,kBAAkB;IAQ1B,OAAO,CAAC,aAAa;IAgBrB,OAAO,CAAC,WAAW;IAkBnB,OAAO,CAAC,YAAY;IAgBpB;;;;OAIG;IACH,wBAAwB,CAAC,IAAI,EAAE;QAC7B,MAAM,EAAE,iBAAiB,CAAC;QAC1B,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC;KACvD,GAAG,IAAI;IAMR;;;OAGG;YACW,WAAW;IAgBzB,sEAAsE;IACtE,OAAO,CAAC,YAAY;IAepB;;;;;;OAMG;YACW,mBAAmB;IAyBjC,OAAO,CAAC,mBAAmB;YAqBb,mBAAmB;IA4BjC,OAAO,CAAC,aAAa;IA8CrB,UAAU,IAAI,aAAa;IAI3B,SAAS,IAAI,YAAY;IAIzB,YAAY,IAAI,GAAG,CAAC,YAAY,EAAE,WAAW,CAAC;CAG/C"}
@@ -7,6 +7,7 @@ import { AnthropicProvider } from './providers/anthropic.js';
7
7
  import { ONNXLocalProvider } from './providers/onnx-local.js';
8
8
  import { GeminiProvider } from './providers/gemini.js';
9
9
  import { OllamaProvider } from './providers/ollama.js';
10
+ import { PHI4_MODEL_PATH } from '../utils/model-downloader.js';
10
11
  export class ModelRouter {
11
12
  config;
12
13
  providers = new Map();
@@ -138,7 +139,7 @@ export class ModelRouter {
138
139
  try {
139
140
  const provider = new ONNXLocalProvider({
140
141
  modelPath: this.config.providers.onnx.modelPath ||
141
- './models/phi-4/cpu_and_mobile/cpu-int4-rtn-block-32-acc-level-4/model.onnx',
142
+ PHI4_MODEL_PATH,
142
143
  executionProviders: this.config.providers.onnx.executionProviders || ['cpu'],
143
144
  maxTokens: this.config.providers.onnx.maxTokens || 100,
144
145
  temperature: this.config.providers.onnx.temperature || 0.7,
@@ -1 +1 @@
1
- {"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/router/router.ts"],"names":[],"mappings":"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","sourcesContent":["// Multi-model router core implementation\nimport { readFileSync, existsSync } from 'fs';\nimport { homedir } from 'os';\nimport { join } from 'path';\nimport {\n LLMProvider,\n RouterConfig,\n ChatParams,\n ChatResponse,\n StreamChunk,\n ProviderType,\n RouterMetrics,\n ProviderError,\n Message,\n} from './types.js';\nimport { CostOptimalRouter } from './cost-optimal-router.js';\nimport { OpenRouterProvider } from './providers/openrouter.js';\nimport { AnthropicProvider } from './providers/anthropic.js';\nimport { ONNXLocalProvider } from './providers/onnx-local.js';\nimport { GeminiProvider } from './providers/gemini.js';\nimport { OllamaProvider } from './providers/ollama.js';\n\nexport class ModelRouter {\n private config: RouterConfig;\n private providers: Map<ProviderType, LLMProvider> = new Map();\n private metrics: RouterMetrics;\n // ADR-073: learned cost-optimal routing (opt-in via enableCostOptimalRouting).\n private costOptimalRouter?: CostOptimalRouter;\n private embedQuery?: (text: string) => Promise<number[]> | number[];\n // Bounded LRU embedding cache โ€” embedding dominates the cost-optimal hot path\n // (โ‰ˆms) vs the ยตs-scale k-NN, and recurring prompts are common.\n private embedCache = new Map<string, number[]>();\n private static readonly EMBED_CACHE_MAX = 512;\n\n constructor(configPath?: string) {\n this.config = this.loadConfig(configPath);\n this.initializeProviders();\n this.metrics = this.initializeMetrics();\n }\n\n private loadConfig(configPath?: string): RouterConfig {\n const paths = [\n configPath,\n process.env.AGENTIC_FLOW_ROUTER_CONFIG,\n join(homedir(), '.agentic-flow', 'router.config.json'),\n join(process.cwd(), 'router.config.json'),\n join(process.cwd(), 'config', 'router.config.json'),\n join(process.cwd(), 'router.config.example.json'),\n ].filter(Boolean) as string[];\n\n for (const path of paths) {\n if (existsSync(path)) {\n const content = readFileSync(path, 'utf-8');\n const config = JSON.parse(content);\n\n // Substitute environment variables\n return this.substituteEnvVars(config);\n }\n }\n\n // If no config file found, create config from environment variables\n return this.createConfigFromEnv();\n }\n\n private createConfigFromEnv(): RouterConfig {\n // Create minimal config from environment variables\n const config: any = {\n version: '1.0',\n defaultProvider: (process.env.PROVIDER as any) || 'anthropic',\n routing: { mode: 'manual' as const },\n providers: {} as any,\n };\n\n // Add Anthropic if API key exists\n if (process.env.ANTHROPIC_API_KEY) {\n config.providers.anthropic = {\n apiKey: process.env.ANTHROPIC_API_KEY,\n baseUrl: process.env.ANTHROPIC_BASE_URL,\n };\n }\n\n // Add OpenRouter if API key exists\n if (process.env.OPENROUTER_API_KEY) {\n config.providers.openrouter = {\n apiKey: process.env.OPENROUTER_API_KEY,\n baseUrl: process.env.OPENROUTER_BASE_URL,\n };\n }\n\n // Add Gemini if API key exists\n if (process.env.GOOGLE_GEMINI_API_KEY) {\n config.providers.gemini = {\n apiKey: process.env.GOOGLE_GEMINI_API_KEY,\n };\n }\n\n // Add Ollama if API key OR explicit base URL is set (self-hosted needs no key)\n if (process.env.OLLAMA_API_KEY || process.env.OLLAMA_BASE_URL) {\n config.providers.ollama = {\n apiKey: process.env.OLLAMA_API_KEY,\n baseUrl: process.env.OLLAMA_BASE_URL,\n };\n }\n\n // ONNX is always available (no API key needed)\n config.providers.onnx = {\n modelPath: process.env.ONNX_MODEL_PATH,\n executionProviders: ['cpu'],\n };\n\n return config as RouterConfig;\n }\n\n private substituteEnvVars(obj: any): any {\n if (typeof obj === 'string') {\n // Replace ${VAR_NAME} with environment variable value\n return obj.replace(/\\$\\{([^}]+)\\}/g, (_, key) => {\n const [varName, defaultValue] = key.split(':-');\n return process.env[varName] || defaultValue || '';\n });\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => this.substituteEnvVars(item));\n }\n\n if (obj && typeof obj === 'object') {\n const result: any = {};\n for (const [key, value] of Object.entries(obj)) {\n result[key] = this.substituteEnvVars(value);\n }\n return result;\n }\n\n return obj;\n }\n\n private initializeProviders(): void {\n const verbose = process.env.ROUTER_VERBOSE === 'true';\n\n // Initialize Anthropic\n if (this.config.providers.anthropic) {\n try {\n const provider = new AnthropicProvider(this.config.providers.anthropic);\n this.providers.set('anthropic', provider);\n if (verbose) console.log('โœ… Anthropic provider initialized');\n } catch (error) {\n if (verbose) console.error('โŒ Failed to initialize Anthropic:', error);\n }\n }\n\n // Initialize OpenRouter\n if (this.config.providers.openrouter) {\n try {\n const provider = new OpenRouterProvider(this.config.providers.openrouter);\n this.providers.set('openrouter', provider);\n if (verbose) console.log('โœ… OpenRouter provider initialized');\n } catch (error) {\n if (verbose) console.error('โŒ Failed to initialize OpenRouter:', error);\n }\n }\n\n // Initialize ONNX Local\n if (this.config.providers.onnx) {\n try {\n const provider = new ONNXLocalProvider({\n modelPath:\n this.config.providers.onnx.modelPath ||\n './models/phi-4/cpu_and_mobile/cpu-int4-rtn-block-32-acc-level-4/model.onnx',\n executionProviders: this.config.providers.onnx.executionProviders || ['cpu'],\n maxTokens: this.config.providers.onnx.maxTokens || 100,\n temperature: this.config.providers.onnx.temperature || 0.7,\n });\n this.providers.set('onnx', provider);\n if (verbose) console.log('โœ… ONNX Local provider initialized');\n } catch (error) {\n if (verbose) console.error('โŒ Failed to initialize ONNX:', error);\n }\n }\n\n // Initialize Gemini\n if (this.config.providers.gemini) {\n try {\n const provider = new GeminiProvider(this.config.providers.gemini);\n this.providers.set('gemini', provider);\n if (verbose) console.log('โœ… Gemini provider initialized');\n } catch (error) {\n if (verbose) console.error('โŒ Failed to initialize Gemini:', error);\n }\n }\n\n // Initialize Ollama (OpenAI-compat, self-hosted or ollama.com Cloud)\n if (this.config.providers.ollama) {\n try {\n const provider = new OllamaProvider(this.config.providers.ollama);\n this.providers.set('ollama', provider);\n if (verbose) console.log('โœ… Ollama provider initialized');\n } catch (error) {\n if (verbose) console.error('โŒ Failed to initialize Ollama:', error);\n }\n }\n }\n\n private initializeMetrics(): RouterMetrics {\n return {\n totalRequests: 0,\n totalCost: 0,\n totalTokens: { input: 0, output: 0 },\n providerBreakdown: {},\n agentBreakdown: {},\n };\n }\n\n async chat(params: ChatParams, agentType?: string): Promise<ChatResponse> {\n const startTime = Date.now();\n const provider = await this.selectProvider(params, agentType);\n\n try {\n const response = await provider.chat(params);\n\n // Update metrics\n this.updateMetrics(provider.name, response, Date.now() - startTime, agentType);\n\n // Add metadata\n response.metadata = {\n ...response.metadata,\n provider: provider.name,\n latency: Date.now() - startTime,\n };\n\n return response;\n } catch (error) {\n return this.handleProviderError(error as ProviderError, params, agentType);\n }\n }\n\n async *stream(params: ChatParams, agentType?: string): AsyncGenerator<StreamChunk> {\n const provider = await this.selectProvider(params, agentType);\n\n if (!provider.stream) {\n throw new Error(`Provider ${provider.name} does not support streaming`);\n }\n\n const iterator = provider.stream(params);\n for await (const chunk of iterator) {\n yield chunk;\n }\n }\n\n private async selectProvider(params: ChatParams, agentType?: string): Promise<LLMProvider> {\n // If provider is explicitly specified in params, use it\n if (params.provider) {\n const forcedProvider = this.providers.get(params.provider as ProviderType);\n if (forcedProvider) {\n return forcedProvider;\n }\n console.warn(\n `โš ๏ธ Requested provider '${params.provider}' not available, falling back to routing logic`\n );\n }\n\n const routingMode = this.config.routing?.mode || 'manual';\n\n switch (routingMode) {\n case 'manual':\n return this.getDefaultProvider();\n\n case 'rule-based':\n return this.selectByRules(params, agentType);\n\n case 'cost-optimized':\n return this.selectByCost(params);\n\n case 'cost-optimal':\n return this.selectByCostOptimal(params);\n\n case 'performance-optimized':\n return this.selectByPerformance(params);\n\n default:\n return this.getDefaultProvider();\n }\n }\n\n private getDefaultProvider(): LLMProvider {\n const provider = this.providers.get(this.config.defaultProvider);\n if (!provider) {\n throw new Error(`Default provider ${this.config.defaultProvider} not initialized`);\n }\n return provider;\n }\n\n private selectByRules(params: ChatParams, agentType?: string): LLMProvider {\n const rules = this.config.routing?.rules || [];\n\n for (const rule of rules) {\n if (this.matchesRule(rule.condition, params, agentType)) {\n const provider = this.providers.get(rule.action.provider);\n if (provider) {\n console.log(`๐ŸŽฏ Routing via rule: ${rule.reason || 'matched condition'}`);\n return provider;\n }\n }\n }\n\n return this.getDefaultProvider();\n }\n\n private matchesRule(condition: any, params: ChatParams, agentType?: string): boolean {\n if (condition.agentType && agentType) {\n if (!condition.agentType.includes(agentType)) {\n return false;\n }\n }\n\n if (condition.requiresTools !== undefined) {\n if (condition.requiresTools && (!params.tools || params.tools.length === 0)) {\n return false;\n }\n }\n\n // TODO: Add more condition matching logic\n\n return true;\n }\n\n private selectByCost(params: ChatParams): LLMProvider {\n // For now, prefer cheaper providers\n // TODO: Implement actual cost calculation\n const providerOrder: ProviderType[] = ['openrouter', 'anthropic', 'openai'];\n\n for (const providerType of providerOrder) {\n const provider = this.providers.get(providerType);\n if (provider) {\n console.log(`๐Ÿ’ฐ Cost-optimized routing: selected ${provider.name}`);\n return provider;\n }\n }\n\n return this.getDefaultProvider();\n }\n\n /**\n * Enable learned cost-optimal routing (ADR-073). Attaches a\n * {@link CostOptimalRouter} plus an embedder and switches the routing mode to\n * `'cost-optimal'`. Opt-in: until called, routing behaves exactly as before.\n */\n enableCostOptimalRouting(opts: {\n router: CostOptimalRouter;\n embed: (text: string) => Promise<number[]> | number[];\n }): void {\n this.costOptimalRouter = opts.router;\n this.embedQuery = opts.embed;\n this.config.routing = { ...(this.config.routing ?? { mode: 'cost-optimal' }), mode: 'cost-optimal' };\n }\n\n /**\n * Embed `text`, caching the result. Bounded LRU: a cache hit refreshes\n * recency; the oldest entry is evicted past {@link EMBED_CACHE_MAX}.\n */\n private async embedCached(text: string): Promise<number[]> {\n const hit = this.embedCache.get(text);\n if (hit) {\n this.embedCache.delete(text); // move to most-recently-used\n this.embedCache.set(text, hit);\n return hit;\n }\n const embedding = await this.embedQuery!(text);\n this.embedCache.set(text, embedding);\n if (this.embedCache.size > ModelRouter.EMBED_CACHE_MAX) {\n const oldest = this.embedCache.keys().next().value;\n if (oldest !== undefined) this.embedCache.delete(oldest);\n }\n return embedding;\n }\n\n /** Extract the most recent user-message text to embed for routing. */\n private lastUserText(messages: Message[]): string {\n for (let i = messages.length - 1; i >= 0; i--) {\n const m = messages[i];\n if (m.role !== 'user') continue;\n return typeof m.content === 'string'\n ? m.content\n : m.content.map((b) => b.text ?? '').join(' ');\n }\n // No user turn โ€” fall back to all text content.\n return messages\n .map((m) => (typeof m.content === 'string' ? m.content : ''))\n .join(' ')\n .trim();\n }\n\n /**\n * Learned cost-optimal selection (ADR-073): embed the query, route to the\n * cheapest model predicted to clear the quality bar, steer params.model to it,\n * and return the matching provider. Falls back to the {@link selectByCost}\n * heuristic when the learned router/embedder isn't configured or errors โ€”\n * routing never hard-fails on the cost-optimal path.\n */\n private async selectByCostOptimal(params: ChatParams): Promise<LLMProvider> {\n if (this.costOptimalRouter && this.embedQuery) {\n try {\n const text = this.lastUserText(params.messages);\n const embedding = await this.embedCached(text);\n const decision = this.costOptimalRouter.route(embedding);\n const provider = this.providers.get(decision.provider);\n if (provider) {\n params.model = decision.model; // steer model, not just provider\n console.log(\n `๐Ÿ’ก Cost-optimal routing โ†’ ${decision.id} ` +\n `(qฬ‚=${decision.predictedQuality.toFixed(2)}, $${decision.costPerMTok}/Mtok, metBar=${decision.metBar})`,\n );\n return provider;\n }\n console.warn(\n `โš ๏ธ Cost-optimal pick '${decision.provider}' not initialized; falling back to heuristic`,\n );\n } catch (err) {\n console.warn('โš ๏ธ Cost-optimal routing failed; falling back to heuristic', err);\n }\n }\n return this.selectByCost(params);\n }\n\n private selectByPerformance(params: ChatParams): LLMProvider {\n // For now, use metrics to select fastest provider\n let fastestProvider: LLMProvider | null = null;\n let lowestLatency = Infinity;\n\n for (const [providerType, provider] of this.providers) {\n const breakdown = this.metrics.providerBreakdown[providerType];\n if (breakdown && breakdown.avgLatency < lowestLatency) {\n lowestLatency = breakdown.avgLatency;\n fastestProvider = provider;\n }\n }\n\n if (fastestProvider) {\n console.log(`โšก Performance-optimized routing: selected ${fastestProvider.name}`);\n return fastestProvider;\n }\n\n return this.getDefaultProvider();\n }\n\n private async handleProviderError(\n error: ProviderError,\n params: ChatParams,\n agentType?: string\n ): Promise<ChatResponse> {\n console.error(`โŒ Provider error from ${error.provider}:`, error.message);\n\n // Try fallback chain\n const fallbackChain = this.config.fallbackChain || [];\n\n for (const providerType of fallbackChain) {\n if (providerType === error.provider) continue; // Skip failed provider\n\n const provider = this.providers.get(providerType);\n if (provider) {\n console.log(`๐Ÿ”„ Falling back to ${provider.name}`);\n try {\n return await provider.chat(params);\n } catch (fallbackError) {\n console.error(`โŒ Fallback provider ${provider.name} also failed`);\n continue;\n }\n }\n }\n\n throw error; // No fallback succeeded\n }\n\n private updateMetrics(\n providerName: string,\n response: ChatResponse,\n latency: number,\n agentType?: string\n ): void {\n this.metrics.totalRequests++;\n\n if (response.usage) {\n this.metrics.totalTokens.input += response.usage.inputTokens;\n this.metrics.totalTokens.output += response.usage.outputTokens;\n }\n\n if (response.metadata?.cost) {\n this.metrics.totalCost += response.metadata.cost;\n }\n\n // Provider breakdown\n if (!this.metrics.providerBreakdown[providerName]) {\n this.metrics.providerBreakdown[providerName] = {\n requests: 0,\n cost: 0,\n avgLatency: 0,\n errors: 0,\n };\n }\n\n const breakdown = this.metrics.providerBreakdown[providerName];\n breakdown.requests++;\n breakdown.cost += response.metadata?.cost || 0;\n breakdown.avgLatency =\n (breakdown.avgLatency * (breakdown.requests - 1) + latency) / breakdown.requests;\n\n // Agent breakdown\n if (agentType) {\n if (!this.metrics.agentBreakdown) {\n this.metrics.agentBreakdown = {};\n }\n if (!this.metrics.agentBreakdown[agentType]) {\n this.metrics.agentBreakdown[agentType] = { requests: 0, cost: 0 };\n }\n this.metrics.agentBreakdown[agentType].requests++;\n this.metrics.agentBreakdown[agentType].cost += response.metadata?.cost || 0;\n }\n }\n\n getMetrics(): RouterMetrics {\n return { ...this.metrics };\n }\n\n getConfig(): RouterConfig {\n return { ...this.config };\n }\n\n getProviders(): Map<ProviderType, LLMProvider> {\n return new Map(this.providers);\n }\n}\n"]}
1
+ {"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/router/router.ts"],"names":[],"mappings":"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","sourcesContent":["// Multi-model router core implementation\nimport { readFileSync, existsSync } from 'fs';\nimport { homedir } from 'os';\nimport { join } from 'path';\nimport {\n LLMProvider,\n RouterConfig,\n ChatParams,\n ChatResponse,\n StreamChunk,\n ProviderType,\n RouterMetrics,\n ProviderError,\n Message,\n} from './types.js';\nimport { CostOptimalRouter } from './cost-optimal-router.js';\nimport { OpenRouterProvider } from './providers/openrouter.js';\nimport { AnthropicProvider } from './providers/anthropic.js';\nimport { ONNXLocalProvider } from './providers/onnx-local.js';\nimport { GeminiProvider } from './providers/gemini.js';\nimport { OllamaProvider } from './providers/ollama.js';\nimport { PHI4_MODEL_PATH } from '../utils/model-downloader.js';\n\nexport class ModelRouter {\n private config: RouterConfig;\n private providers: Map<ProviderType, LLMProvider> = new Map();\n private metrics: RouterMetrics;\n // ADR-073: learned cost-optimal routing (opt-in via enableCostOptimalRouting).\n private costOptimalRouter?: CostOptimalRouter;\n private embedQuery?: (text: string) => Promise<number[]> | number[];\n // Bounded LRU embedding cache โ€” embedding dominates the cost-optimal hot path\n // (โ‰ˆms) vs the ยตs-scale k-NN, and recurring prompts are common.\n private embedCache = new Map<string, number[]>();\n private static readonly EMBED_CACHE_MAX = 512;\n\n constructor(configPath?: string) {\n this.config = this.loadConfig(configPath);\n this.initializeProviders();\n this.metrics = this.initializeMetrics();\n }\n\n private loadConfig(configPath?: string): RouterConfig {\n const paths = [\n configPath,\n process.env.AGENTIC_FLOW_ROUTER_CONFIG,\n join(homedir(), '.agentic-flow', 'router.config.json'),\n join(process.cwd(), 'router.config.json'),\n join(process.cwd(), 'config', 'router.config.json'),\n join(process.cwd(), 'router.config.example.json'),\n ].filter(Boolean) as string[];\n\n for (const path of paths) {\n if (existsSync(path)) {\n const content = readFileSync(path, 'utf-8');\n const config = JSON.parse(content);\n\n // Substitute environment variables\n return this.substituteEnvVars(config);\n }\n }\n\n // If no config file found, create config from environment variables\n return this.createConfigFromEnv();\n }\n\n private createConfigFromEnv(): RouterConfig {\n // Create minimal config from environment variables\n const config: any = {\n version: '1.0',\n defaultProvider: (process.env.PROVIDER as any) || 'anthropic',\n routing: { mode: 'manual' as const },\n providers: {} as any,\n };\n\n // Add Anthropic if API key exists\n if (process.env.ANTHROPIC_API_KEY) {\n config.providers.anthropic = {\n apiKey: process.env.ANTHROPIC_API_KEY,\n baseUrl: process.env.ANTHROPIC_BASE_URL,\n };\n }\n\n // Add OpenRouter if API key exists\n if (process.env.OPENROUTER_API_KEY) {\n config.providers.openrouter = {\n apiKey: process.env.OPENROUTER_API_KEY,\n baseUrl: process.env.OPENROUTER_BASE_URL,\n };\n }\n\n // Add Gemini if API key exists\n if (process.env.GOOGLE_GEMINI_API_KEY) {\n config.providers.gemini = {\n apiKey: process.env.GOOGLE_GEMINI_API_KEY,\n };\n }\n\n // Add Ollama if API key OR explicit base URL is set (self-hosted needs no key)\n if (process.env.OLLAMA_API_KEY || process.env.OLLAMA_BASE_URL) {\n config.providers.ollama = {\n apiKey: process.env.OLLAMA_API_KEY,\n baseUrl: process.env.OLLAMA_BASE_URL,\n };\n }\n\n // ONNX is always available (no API key needed)\n config.providers.onnx = {\n modelPath: process.env.ONNX_MODEL_PATH,\n executionProviders: ['cpu'],\n };\n\n return config as RouterConfig;\n }\n\n private substituteEnvVars(obj: any): any {\n if (typeof obj === 'string') {\n // Replace ${VAR_NAME} with environment variable value\n return obj.replace(/\\$\\{([^}]+)\\}/g, (_, key) => {\n const [varName, defaultValue] = key.split(':-');\n return process.env[varName] || defaultValue || '';\n });\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => this.substituteEnvVars(item));\n }\n\n if (obj && typeof obj === 'object') {\n const result: any = {};\n for (const [key, value] of Object.entries(obj)) {\n result[key] = this.substituteEnvVars(value);\n }\n return result;\n }\n\n return obj;\n }\n\n private initializeProviders(): void {\n const verbose = process.env.ROUTER_VERBOSE === 'true';\n\n // Initialize Anthropic\n if (this.config.providers.anthropic) {\n try {\n const provider = new AnthropicProvider(this.config.providers.anthropic);\n this.providers.set('anthropic', provider);\n if (verbose) console.log('โœ… Anthropic provider initialized');\n } catch (error) {\n if (verbose) console.error('โŒ Failed to initialize Anthropic:', error);\n }\n }\n\n // Initialize OpenRouter\n if (this.config.providers.openrouter) {\n try {\n const provider = new OpenRouterProvider(this.config.providers.openrouter);\n this.providers.set('openrouter', provider);\n if (verbose) console.log('โœ… OpenRouter provider initialized');\n } catch (error) {\n if (verbose) console.error('โŒ Failed to initialize OpenRouter:', error);\n }\n }\n\n // Initialize ONNX Local\n if (this.config.providers.onnx) {\n try {\n const provider = new ONNXLocalProvider({\n modelPath:\n this.config.providers.onnx.modelPath ||\n PHI4_MODEL_PATH,\n executionProviders: this.config.providers.onnx.executionProviders || ['cpu'],\n maxTokens: this.config.providers.onnx.maxTokens || 100,\n temperature: this.config.providers.onnx.temperature || 0.7,\n });\n this.providers.set('onnx', provider);\n if (verbose) console.log('โœ… ONNX Local provider initialized');\n } catch (error) {\n if (verbose) console.error('โŒ Failed to initialize ONNX:', error);\n }\n }\n\n // Initialize Gemini\n if (this.config.providers.gemini) {\n try {\n const provider = new GeminiProvider(this.config.providers.gemini);\n this.providers.set('gemini', provider);\n if (verbose) console.log('โœ… Gemini provider initialized');\n } catch (error) {\n if (verbose) console.error('โŒ Failed to initialize Gemini:', error);\n }\n }\n\n // Initialize Ollama (OpenAI-compat, self-hosted or ollama.com Cloud)\n if (this.config.providers.ollama) {\n try {\n const provider = new OllamaProvider(this.config.providers.ollama);\n this.providers.set('ollama', provider);\n if (verbose) console.log('โœ… Ollama provider initialized');\n } catch (error) {\n if (verbose) console.error('โŒ Failed to initialize Ollama:', error);\n }\n }\n }\n\n private initializeMetrics(): RouterMetrics {\n return {\n totalRequests: 0,\n totalCost: 0,\n totalTokens: { input: 0, output: 0 },\n providerBreakdown: {},\n agentBreakdown: {},\n };\n }\n\n async chat(params: ChatParams, agentType?: string): Promise<ChatResponse> {\n const startTime = Date.now();\n const provider = await this.selectProvider(params, agentType);\n\n try {\n const response = await provider.chat(params);\n\n // Update metrics\n this.updateMetrics(provider.name, response, Date.now() - startTime, agentType);\n\n // Add metadata\n response.metadata = {\n ...response.metadata,\n provider: provider.name,\n latency: Date.now() - startTime,\n };\n\n return response;\n } catch (error) {\n return this.handleProviderError(error as ProviderError, params, agentType);\n }\n }\n\n async *stream(params: ChatParams, agentType?: string): AsyncGenerator<StreamChunk> {\n const provider = await this.selectProvider(params, agentType);\n\n if (!provider.stream) {\n throw new Error(`Provider ${provider.name} does not support streaming`);\n }\n\n const iterator = provider.stream(params);\n for await (const chunk of iterator) {\n yield chunk;\n }\n }\n\n private async selectProvider(params: ChatParams, agentType?: string): Promise<LLMProvider> {\n // If provider is explicitly specified in params, use it\n if (params.provider) {\n const forcedProvider = this.providers.get(params.provider as ProviderType);\n if (forcedProvider) {\n return forcedProvider;\n }\n console.warn(\n `โš ๏ธ Requested provider '${params.provider}' not available, falling back to routing logic`\n );\n }\n\n const routingMode = this.config.routing?.mode || 'manual';\n\n switch (routingMode) {\n case 'manual':\n return this.getDefaultProvider();\n\n case 'rule-based':\n return this.selectByRules(params, agentType);\n\n case 'cost-optimized':\n return this.selectByCost(params);\n\n case 'cost-optimal':\n return this.selectByCostOptimal(params);\n\n case 'performance-optimized':\n return this.selectByPerformance(params);\n\n default:\n return this.getDefaultProvider();\n }\n }\n\n private getDefaultProvider(): LLMProvider {\n const provider = this.providers.get(this.config.defaultProvider);\n if (!provider) {\n throw new Error(`Default provider ${this.config.defaultProvider} not initialized`);\n }\n return provider;\n }\n\n private selectByRules(params: ChatParams, agentType?: string): LLMProvider {\n const rules = this.config.routing?.rules || [];\n\n for (const rule of rules) {\n if (this.matchesRule(rule.condition, params, agentType)) {\n const provider = this.providers.get(rule.action.provider);\n if (provider) {\n console.log(`๐ŸŽฏ Routing via rule: ${rule.reason || 'matched condition'}`);\n return provider;\n }\n }\n }\n\n return this.getDefaultProvider();\n }\n\n private matchesRule(condition: any, params: ChatParams, agentType?: string): boolean {\n if (condition.agentType && agentType) {\n if (!condition.agentType.includes(agentType)) {\n return false;\n }\n }\n\n if (condition.requiresTools !== undefined) {\n if (condition.requiresTools && (!params.tools || params.tools.length === 0)) {\n return false;\n }\n }\n\n // TODO: Add more condition matching logic\n\n return true;\n }\n\n private selectByCost(params: ChatParams): LLMProvider {\n // For now, prefer cheaper providers\n // TODO: Implement actual cost calculation\n const providerOrder: ProviderType[] = ['openrouter', 'anthropic', 'openai'];\n\n for (const providerType of providerOrder) {\n const provider = this.providers.get(providerType);\n if (provider) {\n console.log(`๐Ÿ’ฐ Cost-optimized routing: selected ${provider.name}`);\n return provider;\n }\n }\n\n return this.getDefaultProvider();\n }\n\n /**\n * Enable learned cost-optimal routing (ADR-073). Attaches a\n * {@link CostOptimalRouter} plus an embedder and switches the routing mode to\n * `'cost-optimal'`. Opt-in: until called, routing behaves exactly as before.\n */\n enableCostOptimalRouting(opts: {\n router: CostOptimalRouter;\n embed: (text: string) => Promise<number[]> | number[];\n }): void {\n this.costOptimalRouter = opts.router;\n this.embedQuery = opts.embed;\n this.config.routing = { ...(this.config.routing ?? { mode: 'cost-optimal' }), mode: 'cost-optimal' };\n }\n\n /**\n * Embed `text`, caching the result. Bounded LRU: a cache hit refreshes\n * recency; the oldest entry is evicted past {@link EMBED_CACHE_MAX}.\n */\n private async embedCached(text: string): Promise<number[]> {\n const hit = this.embedCache.get(text);\n if (hit) {\n this.embedCache.delete(text); // move to most-recently-used\n this.embedCache.set(text, hit);\n return hit;\n }\n const embedding = await this.embedQuery!(text);\n this.embedCache.set(text, embedding);\n if (this.embedCache.size > ModelRouter.EMBED_CACHE_MAX) {\n const oldest = this.embedCache.keys().next().value;\n if (oldest !== undefined) this.embedCache.delete(oldest);\n }\n return embedding;\n }\n\n /** Extract the most recent user-message text to embed for routing. */\n private lastUserText(messages: Message[]): string {\n for (let i = messages.length - 1; i >= 0; i--) {\n const m = messages[i];\n if (m.role !== 'user') continue;\n return typeof m.content === 'string'\n ? m.content\n : m.content.map((b) => b.text ?? '').join(' ');\n }\n // No user turn โ€” fall back to all text content.\n return messages\n .map((m) => (typeof m.content === 'string' ? m.content : ''))\n .join(' ')\n .trim();\n }\n\n /**\n * Learned cost-optimal selection (ADR-073): embed the query, route to the\n * cheapest model predicted to clear the quality bar, steer params.model to it,\n * and return the matching provider. Falls back to the {@link selectByCost}\n * heuristic when the learned router/embedder isn't configured or errors โ€”\n * routing never hard-fails on the cost-optimal path.\n */\n private async selectByCostOptimal(params: ChatParams): Promise<LLMProvider> {\n if (this.costOptimalRouter && this.embedQuery) {\n try {\n const text = this.lastUserText(params.messages);\n const embedding = await this.embedCached(text);\n const decision = this.costOptimalRouter.route(embedding);\n const provider = this.providers.get(decision.provider);\n if (provider) {\n params.model = decision.model; // steer model, not just provider\n console.log(\n `๐Ÿ’ก Cost-optimal routing โ†’ ${decision.id} ` +\n `(qฬ‚=${decision.predictedQuality.toFixed(2)}, $${decision.costPerMTok}/Mtok, metBar=${decision.metBar})`,\n );\n return provider;\n }\n console.warn(\n `โš ๏ธ Cost-optimal pick '${decision.provider}' not initialized; falling back to heuristic`,\n );\n } catch (err) {\n console.warn('โš ๏ธ Cost-optimal routing failed; falling back to heuristic', err);\n }\n }\n return this.selectByCost(params);\n }\n\n private selectByPerformance(params: ChatParams): LLMProvider {\n // For now, use metrics to select fastest provider\n let fastestProvider: LLMProvider | null = null;\n let lowestLatency = Infinity;\n\n for (const [providerType, provider] of this.providers) {\n const breakdown = this.metrics.providerBreakdown[providerType];\n if (breakdown && breakdown.avgLatency < lowestLatency) {\n lowestLatency = breakdown.avgLatency;\n fastestProvider = provider;\n }\n }\n\n if (fastestProvider) {\n console.log(`โšก Performance-optimized routing: selected ${fastestProvider.name}`);\n return fastestProvider;\n }\n\n return this.getDefaultProvider();\n }\n\n private async handleProviderError(\n error: ProviderError,\n params: ChatParams,\n agentType?: string\n ): Promise<ChatResponse> {\n console.error(`โŒ Provider error from ${error.provider}:`, error.message);\n\n // Try fallback chain\n const fallbackChain = this.config.fallbackChain || [];\n\n for (const providerType of fallbackChain) {\n if (providerType === error.provider) continue; // Skip failed provider\n\n const provider = this.providers.get(providerType);\n if (provider) {\n console.log(`๐Ÿ”„ Falling back to ${provider.name}`);\n try {\n return await provider.chat(params);\n } catch (fallbackError) {\n console.error(`โŒ Fallback provider ${provider.name} also failed`);\n continue;\n }\n }\n }\n\n throw error; // No fallback succeeded\n }\n\n private updateMetrics(\n providerName: string,\n response: ChatResponse,\n latency: number,\n agentType?: string\n ): void {\n this.metrics.totalRequests++;\n\n if (response.usage) {\n this.metrics.totalTokens.input += response.usage.inputTokens;\n this.metrics.totalTokens.output += response.usage.outputTokens;\n }\n\n if (response.metadata?.cost) {\n this.metrics.totalCost += response.metadata.cost;\n }\n\n // Provider breakdown\n if (!this.metrics.providerBreakdown[providerName]) {\n this.metrics.providerBreakdown[providerName] = {\n requests: 0,\n cost: 0,\n avgLatency: 0,\n errors: 0,\n };\n }\n\n const breakdown = this.metrics.providerBreakdown[providerName];\n breakdown.requests++;\n breakdown.cost += response.metadata?.cost || 0;\n breakdown.avgLatency =\n (breakdown.avgLatency * (breakdown.requests - 1) + latency) / breakdown.requests;\n\n // Agent breakdown\n if (agentType) {\n if (!this.metrics.agentBreakdown) {\n this.metrics.agentBreakdown = {};\n }\n if (!this.metrics.agentBreakdown[agentType]) {\n this.metrics.agentBreakdown[agentType] = { requests: 0, cost: 0 };\n }\n this.metrics.agentBreakdown[agentType].requests++;\n this.metrics.agentBreakdown[agentType].cost += response.metadata?.cost || 0;\n }\n }\n\n getMetrics(): RouterMetrics {\n return { ...this.metrics };\n }\n\n getConfig(): RouterConfig {\n return { ...this.config };\n }\n\n getProviders(): Map<ProviderType, LLMProvider> {\n return new Map(this.providers);\n }\n}\n"]}
@@ -4,12 +4,13 @@
4
4
  * Tests CPU performance against targets
5
5
  */
6
6
  import { ONNXLocalProvider } from './providers/onnx-local.js';
7
+ import { PHI4_MODEL_PATH } from '../utils/model-downloader.js';
7
8
  async function runBenchmark() {
8
9
  console.log('๐Ÿ ONNX Local Inference Benchmark (Phi-4 CPU)\n');
9
10
  console.log('Target: 15-25 tokens/sec on CPU');
10
11
  console.log('================================================\n');
11
12
  const provider = new ONNXLocalProvider({
12
- modelPath: './models/phi-4/cpu_and_mobile/cpu-int4-rtn-block-32-acc-level-4/model.onnx',
13
+ modelPath: PHI4_MODEL_PATH,
13
14
  executionProviders: ['cpu'],
14
15
  maxTokens: 50,
15
16
  temperature: 0.7
@@ -1 +1 @@
1
- {"version":3,"file":"test-onnx-benchmark.js","sourceRoot":"","sources":["../../src/router/test-onnx-benchmark.ts"],"names":[],"mappings":";AACA;;;GAGG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAS9D,KAAK,UAAU,YAAY;IACzB,OAAO,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC;IAC/D,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;IAC/C,OAAO,CAAC,GAAG,CAAC,oDAAoD,CAAC,CAAC;IAElE,MAAM,QAAQ,GAAG,IAAI,iBAAiB,CAAC;QACrC,SAAS,EAAE,4EAA4E;QACvF,kBAAkB,EAAE,CAAC,KAAK,CAAC;QAC3B,SAAS,EAAE,EAAE;QACb,WAAW,EAAE,GAAG;KACjB,CAAC,CAAC;IAEH,MAAM,OAAO,GAAsB,EAAE,CAAC;IAEtC,yBAAyB;IACzB,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;IAC7C,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;IAE9C,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC9B,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC;QACpC,KAAK,EAAE,OAAO;QACd,QAAQ,EAAE;YACR,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE;SAC1C;QACD,SAAS,EAAE,EAAE;KACd,CAAC,CAAC;IACH,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC;IAC7C,MAAM,QAAQ,GAAG,CAAC,SAAS,CAAC,KAAK,EAAE,YAAY,IAAI,CAAC,CAAC,GAAG,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IAE9E,OAAO,CAAC,GAAG,CAAC,eAAe,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACpG,OAAO,CAAC,GAAG,CAAC,OAAO,YAAY,QAAQ,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC;IAE3E,OAAO,CAAC,IAAI,CAAC;QACX,IAAI,EAAE,YAAY;QAClB,MAAM,EAAE,SAAS,CAAC,KAAK,EAAE,YAAY,IAAI,CAAC;QAC1C,OAAO,EAAE,YAAY;QACrB,eAAe,EAAE,QAAQ;KAC1B,CAAC,CAAC;IAEH,0BAA0B;IAC1B,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;IACnD,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;IAErD,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC9B,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC;QACpC,KAAK,EAAE,OAAO;QACd,QAAQ,EAAE;YACR,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,8CAA8C,EAAE;SAC1E;QACD,SAAS,EAAE,EAAE;KACd,CAAC,CAAC;IACH,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC;IAC7C,MAAM,QAAQ,GAAG,CAAC,SAAS,CAAC,KAAK,EAAE,YAAY,IAAI,CAAC,CAAC,GAAG,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IAE9E,OAAO,CAAC,GAAG,CAAC,eAAe,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACpG,OAAO,CAAC,GAAG,CAAC,OAAO,YAAY,QAAQ,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC;IAE3E,OAAO,CAAC,IAAI,CAAC;QACX,IAAI,EAAE,kBAAkB;QACxB,MAAM,EAAE,SAAS,CAAC,KAAK,EAAE,YAAY,IAAI,CAAC;QAC1C,OAAO,EAAE,YAAY;QACrB,eAAe,EAAE,QAAQ;KAC1B,CAAC,CAAC;IAEH,0BAA0B;IAC1B,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;IAClD,OAAO,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;IAEpD,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC9B,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC;QACpC,KAAK,EAAE,OAAO;QACd,QAAQ,EAAE;YACR,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,+BAA+B,EAAE;SAC3D;QACD,SAAS,EAAE,EAAE;KACd,CAAC,CAAC;IACH,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC;IAC7C,MAAM,QAAQ,GAAG,CAAC,SAAS,CAAC,KAAK,EAAE,YAAY,IAAI,CAAC,CAAC,GAAG,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IAE9E,OAAO,CAAC,GAAG,CAAC,eAAe,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACpG,OAAO,CAAC,GAAG,CAAC,OAAO,YAAY,QAAQ,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC;IAE3E,OAAO,CAAC,IAAI,CAAC;QACX,IAAI,EAAE,iBAAiB;QACvB,MAAM,EAAE,SAAS,CAAC,KAAK,EAAE,YAAY,IAAI,CAAC;QAC1C,OAAO,EAAE,YAAY;QACrB,eAAe,EAAE,QAAQ;KAC1B,CAAC,CAAC;IAEH,kCAAkC;IAClC,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;IAC/C,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;IAEhD,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC9B,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC;QACpC,KAAK,EAAE,OAAO;QACd,QAAQ,EAAE;YACR,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE;YACnC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,kCAAkC,EAAE;YAClE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,qCAAqC,EAAE;SACjE;QACD,SAAS,EAAE,EAAE;KACd,CAAC,CAAC;IACH,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC;IAC7C,MAAM,QAAQ,GAAG,CAAC,SAAS,CAAC,KAAK,EAAE,YAAY,IAAI,CAAC,CAAC,GAAG,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IAE9E,OAAO,CAAC,GAAG,CAAC,eAAe,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACpG,OAAO,CAAC,GAAG,CAAC,OAAO,YAAY,QAAQ,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC;IAE3E,OAAO,CAAC,IAAI,CAAC;QACX,IAAI,EAAE,YAAY;QAClB,MAAM,EAAE,SAAS,CAAC,KAAK,EAAE,YAAY,IAAI,CAAC;QAC1C,OAAO,EAAE,YAAY;QACrB,eAAe,EAAE,QAAQ;KAC1B,CAAC,CAAC;IAEH,UAAU;IACV,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;IACtC,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;IAEtC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IACvF,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IACnF,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAElE,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC9B,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,MAAM,EAAE,CAAC,CAAC,MAAM;QAChB,cAAc,EAAE,CAAC,CAAC,OAAO;QACzB,YAAY,EAAE,CAAC,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;KAC3C,CAAC,CAAC,CAAC,CAAC;IAEL,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;IACzC,OAAO,CAAC,GAAG,CAAC,0BAA0B,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC3D,OAAO,CAAC,GAAG,CAAC,uBAAuB,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC9D,OAAO,CAAC,GAAG,CAAC,8BAA8B,WAAW,EAAE,CAAC,CAAC;IAEzD,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;IACvC,MAAM,SAAS,GAAG,EAAE,CAAC;IACrB,MAAM,SAAS,GAAG,EAAE,CAAC;IAErB,IAAI,MAAM,IAAI,SAAS,IAAI,MAAM,IAAI,SAAS,GAAG,GAAG,EAAE,CAAC;QACrD,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,wCAAwC,CAAC,CAAC;IACvF,CAAC;SAAM,IAAI,MAAM,GAAG,SAAS,EAAE,CAAC;QAC9B,OAAO,CAAC,GAAG,CAAC,gBAAgB,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,gCAAgC,SAAS,IAAI,CAAC,CAAC;IAC9F,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,eAAe,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,6BAA6B,CAAC,CAAC;IAC7E,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IAClC,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;IACzC,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,WAAW,GAAG,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAChF,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IAEhC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAC7B,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;IACzC,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;IAC1C,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;IAEzC,MAAM,QAAQ,CAAC,OAAO,EAAE,CAAC;AAC3B,CAAC;AAED,YAAY,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE;IAC3B,OAAO,CAAC,KAAK,CAAC,qBAAqB,EAAE,KAAK,CAAC,CAAC;IAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC","sourcesContent":["#!/usr/bin/env node\n/**\n * Comprehensive benchmark for ONNX local inference\n * Tests CPU performance against targets\n */\n\nimport { ONNXLocalProvider } from './providers/onnx-local.js';\n\ninterface BenchmarkResult {\n test: string;\n tokens: number;\n latency: number;\n tokensPerSecond: number;\n}\n\nasync function runBenchmark() {\n console.log('๐Ÿ ONNX Local Inference Benchmark (Phi-4 CPU)\\n');\n console.log('Target: 15-25 tokens/sec on CPU');\n console.log('================================================\\n');\n\n const provider = new ONNXLocalProvider({\n modelPath: './models/phi-4/cpu_and_mobile/cpu-int4-rtn-block-32-acc-level-4/model.onnx',\n executionProviders: ['cpu'],\n maxTokens: 50,\n temperature: 0.7\n });\n\n const results: BenchmarkResult[] = [];\n\n // Test 1: Short response\n console.log('Test 1: Short Response (Math)');\n console.log('==============================');\n\n const test1Start = Date.now();\n const response1 = await provider.chat({\n model: 'phi-4',\n messages: [\n { role: 'user', content: 'What is 2+2?' }\n ],\n maxTokens: 20\n });\n const test1Latency = Date.now() - test1Start;\n const test1TPS = (response1.usage?.outputTokens || 0) / (test1Latency / 1000);\n\n console.log(`โœ… Response: ${response1.content[0].type === 'text' ? response1.content[0].text : ''}`);\n console.log(`โฑ๏ธ ${test1Latency}ms | ${test1TPS.toFixed(1)} tokens/sec\\n`);\n\n results.push({\n test: 'Short Math',\n tokens: response1.usage?.outputTokens || 0,\n latency: test1Latency,\n tokensPerSecond: test1TPS\n });\n\n // Test 2: Medium response\n console.log('Test 2: Medium Response (Reasoning)');\n console.log('=====================================');\n\n const test2Start = Date.now();\n const response2 = await provider.chat({\n model: 'phi-4',\n messages: [\n { role: 'user', content: 'Explain why the sky is blue in one sentence.' }\n ],\n maxTokens: 30\n });\n const test2Latency = Date.now() - test2Start;\n const test2TPS = (response2.usage?.outputTokens || 0) / (test2Latency / 1000);\n\n console.log(`โœ… Response: ${response2.content[0].type === 'text' ? response2.content[0].text : ''}`);\n console.log(`โฑ๏ธ ${test2Latency}ms | ${test2TPS.toFixed(1)} tokens/sec\\n`);\n\n results.push({\n test: 'Medium Reasoning',\n tokens: response2.usage?.outputTokens || 0,\n latency: test2Latency,\n tokensPerSecond: test2TPS\n });\n\n // Test 3: Longer response\n console.log('Test 3: Longer Response (Creative)');\n console.log('====================================');\n\n const test3Start = Date.now();\n const response3 = await provider.chat({\n model: 'phi-4',\n messages: [\n { role: 'user', content: 'List 5 programming languages.' }\n ],\n maxTokens: 50\n });\n const test3Latency = Date.now() - test3Start;\n const test3TPS = (response3.usage?.outputTokens || 0) / (test3Latency / 1000);\n\n console.log(`โœ… Response: ${response3.content[0].type === 'text' ? response3.content[0].text : ''}`);\n console.log(`โฑ๏ธ ${test3Latency}ms | ${test3TPS.toFixed(1)} tokens/sec\\n`);\n\n results.push({\n test: 'Longer Creative',\n tokens: response3.usage?.outputTokens || 0,\n latency: test3Latency,\n tokensPerSecond: test3TPS\n });\n\n // Test 4: Multi-turn conversation\n console.log('Test 4: Multi-Turn Conversation');\n console.log('================================');\n\n const test4Start = Date.now();\n const response4 = await provider.chat({\n model: 'phi-4',\n messages: [\n { role: 'user', content: 'Hello!' },\n { role: 'assistant', content: 'Hello! How can I help you today?' },\n { role: 'user', content: 'Tell me a fun fact about computers.' }\n ],\n maxTokens: 40\n });\n const test4Latency = Date.now() - test4Start;\n const test4TPS = (response4.usage?.outputTokens || 0) / (test4Latency / 1000);\n\n console.log(`โœ… Response: ${response4.content[0].type === 'text' ? response4.content[0].text : ''}`);\n console.log(`โฑ๏ธ ${test4Latency}ms | ${test4TPS.toFixed(1)} tokens/sec\\n`);\n\n results.push({\n test: 'Multi-Turn',\n tokens: response4.usage?.outputTokens || 0,\n latency: test4Latency,\n tokensPerSecond: test4TPS\n });\n\n // Summary\n console.log('\\n๐Ÿ“Š Benchmark Summary');\n console.log('====================\\n');\n\n const avgTPS = results.reduce((sum, r) => sum + r.tokensPerSecond, 0) / results.length;\n const avgLatency = results.reduce((sum, r) => sum + r.latency, 0) / results.length;\n const totalTokens = results.reduce((sum, r) => sum + r.tokens, 0);\n\n console.table(results.map(r => ({\n Test: r.test,\n Tokens: r.tokens,\n 'Latency (ms)': r.latency,\n 'Tokens/Sec': r.tokensPerSecond.toFixed(1)\n })));\n\n console.log(`\\n๐Ÿ“ˆ Performance Metrics:`);\n console.log(` Average Tokens/Sec: ${avgTPS.toFixed(1)}`);\n console.log(` Average Latency: ${avgLatency.toFixed(0)}ms`);\n console.log(` Total Tokens Generated: ${totalTokens}`);\n\n console.log(`\\n๐ŸŽฏ Target Validation:`);\n const targetMin = 15;\n const targetMax = 25;\n\n if (avgTPS >= targetMin && avgTPS <= targetMax * 1.5) {\n console.log(` โœ… PASS: ${avgTPS.toFixed(1)} tokens/sec is within acceptable range`);\n } else if (avgTPS < targetMin) {\n console.log(` โš ๏ธ SLOW: ${avgTPS.toFixed(1)} tokens/sec is below target (${targetMin}+)`);\n } else {\n console.log(` ๐Ÿš€ FAST: ${avgTPS.toFixed(1)} tokens/sec exceeds target!`);\n }\n\n console.log(`\\n๐Ÿ’ฐ Cost Savings:`);\n console.log(` Local Inference: $0.00`);\n console.log(` Anthropic Equivalent: ~$${(totalTokens * 0.00003).toFixed(4)}`);\n console.log(` Savings: 100%`);\n\n console.log(`\\n๐Ÿ”’ Privacy:`);\n console.log(` โœ… All processing local`);\n console.log(` โœ… No data sent to cloud`);\n console.log(` โœ… GDPR/HIPAA compliant`);\n\n await provider.dispose();\n}\n\nrunBenchmark().catch(error => {\n console.error('โŒ Benchmark failed:', error);\n process.exit(1);\n});\n"]}
1
+ {"version":3,"file":"test-onnx-benchmark.js","sourceRoot":"","sources":["../../src/router/test-onnx-benchmark.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n/**\n * Comprehensive benchmark for ONNX local inference\n * Tests CPU performance against targets\n */\n\nimport { ONNXLocalProvider } from './providers/onnx-local.js';\nimport { PHI4_MODEL_PATH } from '../utils/model-downloader.js';\n\ninterface BenchmarkResult {\n test: string;\n tokens: number;\n latency: number;\n tokensPerSecond: number;\n}\n\nasync function runBenchmark() {\n console.log('๐Ÿ ONNX Local Inference Benchmark (Phi-4 CPU)\\n');\n console.log('Target: 15-25 tokens/sec on CPU');\n console.log('================================================\\n');\n\n const provider = new ONNXLocalProvider({\n modelPath: PHI4_MODEL_PATH,\n executionProviders: ['cpu'],\n maxTokens: 50,\n temperature: 0.7\n });\n\n const results: BenchmarkResult[] = [];\n\n // Test 1: Short response\n console.log('Test 1: Short Response (Math)');\n console.log('==============================');\n\n const test1Start = Date.now();\n const response1 = await provider.chat({\n model: 'phi-4',\n messages: [\n { role: 'user', content: 'What is 2+2?' }\n ],\n maxTokens: 20\n });\n const test1Latency = Date.now() - test1Start;\n const test1TPS = (response1.usage?.outputTokens || 0) / (test1Latency / 1000);\n\n console.log(`โœ… Response: ${response1.content[0].type === 'text' ? response1.content[0].text : ''}`);\n console.log(`โฑ๏ธ ${test1Latency}ms | ${test1TPS.toFixed(1)} tokens/sec\\n`);\n\n results.push({\n test: 'Short Math',\n tokens: response1.usage?.outputTokens || 0,\n latency: test1Latency,\n tokensPerSecond: test1TPS\n });\n\n // Test 2: Medium response\n console.log('Test 2: Medium Response (Reasoning)');\n console.log('=====================================');\n\n const test2Start = Date.now();\n const response2 = await provider.chat({\n model: 'phi-4',\n messages: [\n { role: 'user', content: 'Explain why the sky is blue in one sentence.' }\n ],\n maxTokens: 30\n });\n const test2Latency = Date.now() - test2Start;\n const test2TPS = (response2.usage?.outputTokens || 0) / (test2Latency / 1000);\n\n console.log(`โœ… Response: ${response2.content[0].type === 'text' ? response2.content[0].text : ''}`);\n console.log(`โฑ๏ธ ${test2Latency}ms | ${test2TPS.toFixed(1)} tokens/sec\\n`);\n\n results.push({\n test: 'Medium Reasoning',\n tokens: response2.usage?.outputTokens || 0,\n latency: test2Latency,\n tokensPerSecond: test2TPS\n });\n\n // Test 3: Longer response\n console.log('Test 3: Longer Response (Creative)');\n console.log('====================================');\n\n const test3Start = Date.now();\n const response3 = await provider.chat({\n model: 'phi-4',\n messages: [\n { role: 'user', content: 'List 5 programming languages.' }\n ],\n maxTokens: 50\n });\n const test3Latency = Date.now() - test3Start;\n const test3TPS = (response3.usage?.outputTokens || 0) / (test3Latency / 1000);\n\n console.log(`โœ… Response: ${response3.content[0].type === 'text' ? response3.content[0].text : ''}`);\n console.log(`โฑ๏ธ ${test3Latency}ms | ${test3TPS.toFixed(1)} tokens/sec\\n`);\n\n results.push({\n test: 'Longer Creative',\n tokens: response3.usage?.outputTokens || 0,\n latency: test3Latency,\n tokensPerSecond: test3TPS\n });\n\n // Test 4: Multi-turn conversation\n console.log('Test 4: Multi-Turn Conversation');\n console.log('================================');\n\n const test4Start = Date.now();\n const response4 = await provider.chat({\n model: 'phi-4',\n messages: [\n { role: 'user', content: 'Hello!' },\n { role: 'assistant', content: 'Hello! How can I help you today?' },\n { role: 'user', content: 'Tell me a fun fact about computers.' }\n ],\n maxTokens: 40\n });\n const test4Latency = Date.now() - test4Start;\n const test4TPS = (response4.usage?.outputTokens || 0) / (test4Latency / 1000);\n\n console.log(`โœ… Response: ${response4.content[0].type === 'text' ? response4.content[0].text : ''}`);\n console.log(`โฑ๏ธ ${test4Latency}ms | ${test4TPS.toFixed(1)} tokens/sec\\n`);\n\n results.push({\n test: 'Multi-Turn',\n tokens: response4.usage?.outputTokens || 0,\n latency: test4Latency,\n tokensPerSecond: test4TPS\n });\n\n // Summary\n console.log('\\n๐Ÿ“Š Benchmark Summary');\n console.log('====================\\n');\n\n const avgTPS = results.reduce((sum, r) => sum + r.tokensPerSecond, 0) / results.length;\n const avgLatency = results.reduce((sum, r) => sum + r.latency, 0) / results.length;\n const totalTokens = results.reduce((sum, r) => sum + r.tokens, 0);\n\n console.table(results.map(r => ({\n Test: r.test,\n Tokens: r.tokens,\n 'Latency (ms)': r.latency,\n 'Tokens/Sec': r.tokensPerSecond.toFixed(1)\n })));\n\n console.log(`\\n๐Ÿ“ˆ Performance Metrics:`);\n console.log(` Average Tokens/Sec: ${avgTPS.toFixed(1)}`);\n console.log(` Average Latency: ${avgLatency.toFixed(0)}ms`);\n console.log(` Total Tokens Generated: ${totalTokens}`);\n\n console.log(`\\n๐ŸŽฏ Target Validation:`);\n const targetMin = 15;\n const targetMax = 25;\n\n if (avgTPS >= targetMin && avgTPS <= targetMax * 1.5) {\n console.log(` โœ… PASS: ${avgTPS.toFixed(1)} tokens/sec is within acceptable range`);\n } else if (avgTPS < targetMin) {\n console.log(` โš ๏ธ SLOW: ${avgTPS.toFixed(1)} tokens/sec is below target (${targetMin}+)`);\n } else {\n console.log(` ๐Ÿš€ FAST: ${avgTPS.toFixed(1)} tokens/sec exceeds target!`);\n }\n\n console.log(`\\n๐Ÿ’ฐ Cost Savings:`);\n console.log(` Local Inference: $0.00`);\n console.log(` Anthropic Equivalent: ~$${(totalTokens * 0.00003).toFixed(4)}`);\n console.log(` Savings: 100%`);\n\n console.log(`\\n๐Ÿ”’ Privacy:`);\n console.log(` โœ… All processing local`);\n console.log(` โœ… No data sent to cloud`);\n console.log(` โœ… GDPR/HIPAA compliant`);\n\n await provider.dispose();\n}\n\nrunBenchmark().catch(error => {\n console.error('โŒ Benchmark failed:', error);\n process.exit(1);\n});\n"]}
@@ -3,11 +3,12 @@
3
3
  * Test ONNX local inference with Phi-4 model
4
4
  */
5
5
  import { ONNXLocalProvider } from './providers/onnx-local.js';
6
+ import { PHI4_MODEL_PATH } from '../utils/model-downloader.js';
6
7
  async function testONNXLocal() {
7
8
  console.log('๐Ÿงช Testing ONNX Local Inference (Phi-4 CPU)\n');
8
9
  try {
9
10
  const provider = new ONNXLocalProvider({
10
- modelPath: './models/phi-4/cpu_and_mobile/cpu-int4-rtn-block-32-acc-level-4/model.onnx',
11
+ modelPath: PHI4_MODEL_PATH,
11
12
  executionProviders: ['cpu'],
12
13
  maxTokens: 50
13
14
  });
@@ -1 +1 @@
1
- {"version":3,"file":"test-onnx-local.js","sourceRoot":"","sources":["../../src/router/test-onnx-local.ts"],"names":[],"mappings":";AACA;;GAEG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAE9D,KAAK,UAAU,aAAa;IAC1B,OAAO,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;IAE7D,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,IAAI,iBAAiB,CAAC;YACrC,SAAS,EAAE,4EAA4E;YACvF,kBAAkB,EAAE,CAAC,KAAK,CAAC;YAC3B,SAAS,EAAE,EAAE;SACd,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;QACtC,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;QAEtC,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC;YACnC,KAAK,EAAE,OAAO;YACd,QAAQ,EAAE;gBACR,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE;aAC1C;YACD,SAAS,EAAE,EAAE;SACd,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;QAC9B,OAAO,CAAC,GAAG,CAAC,WAAW,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC9F,OAAO,CAAC,GAAG,CAAC,cAAc,QAAQ,CAAC,QAAQ,EAAE,OAAO,IAAI,CAAC,CAAC;QAC1D,OAAO,CAAC,GAAG,CAAC,aAAa,QAAQ,CAAC,KAAK,EAAE,WAAW,SAAS,QAAQ,CAAC,KAAK,EAAE,YAAY,MAAM,CAAC,CAAC;QACjG,OAAO,CAAC,GAAG,CAAC,YAAY,QAAQ,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC,gBAAgB,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEjF,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;QAEhC,MAAM,QAAQ,CAAC,OAAO,EAAE,CAAC;IAE3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC;QACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,aAAa,EAAE,CAAC","sourcesContent":["#!/usr/bin/env node\n/**\n * Test ONNX local inference with Phi-4 model\n */\n\nimport { ONNXLocalProvider } from './providers/onnx-local.js';\n\nasync function testONNXLocal() {\n console.log('๐Ÿงช Testing ONNX Local Inference (Phi-4 CPU)\\n');\n\n try {\n const provider = new ONNXLocalProvider({\n modelPath: './models/phi-4/cpu_and_mobile/cpu-int4-rtn-block-32-acc-level-4/model.onnx',\n executionProviders: ['cpu'],\n maxTokens: 50\n });\n\n console.log('Test: Simple Inference');\n console.log('======================');\n\n const response = await provider.chat({\n model: 'phi-4',\n messages: [\n { role: 'user', content: 'What is 2+2?' }\n ],\n maxTokens: 20\n });\n\n console.log('\\n๐Ÿ“ฅ Response:');\n console.log(` Text: ${response.content[0].type === 'text' ? response.content[0].text : ''}`);\n console.log(` Latency: ${response.metadata?.latency}ms`);\n console.log(` Tokens: ${response.usage?.inputTokens} in / ${response.usage?.outputTokens} out`);\n console.log(` Cost: $${response.metadata?.cost}`);\n console.log(` Providers: ${response.metadata?.executionProviders?.join(', ')}`);\n\n console.log('\\nโœ… Test passed!');\n\n await provider.dispose();\n\n } catch (error) {\n console.error('\\nโŒ Test failed:', error);\n process.exit(1);\n }\n}\n\ntestONNXLocal();\n"]}
1
+ {"version":3,"file":"test-onnx-local.js","sourceRoot":"","sources":["../../src/router/test-onnx-local.ts"],"names":[],"mappings":";AACA;;GAEG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAE/D,KAAK,UAAU,aAAa;IAC1B,OAAO,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;IAE7D,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,IAAI,iBAAiB,CAAC;YACrC,SAAS,EAAE,eAAe;YAC1B,kBAAkB,EAAE,CAAC,KAAK,CAAC;YAC3B,SAAS,EAAE,EAAE;SACd,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;QACtC,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;QAEtC,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC;YACnC,KAAK,EAAE,OAAO;YACd,QAAQ,EAAE;gBACR,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE;aAC1C;YACD,SAAS,EAAE,EAAE;SACd,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;QAC9B,OAAO,CAAC,GAAG,CAAC,WAAW,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC9F,OAAO,CAAC,GAAG,CAAC,cAAc,QAAQ,CAAC,QAAQ,EAAE,OAAO,IAAI,CAAC,CAAC;QAC1D,OAAO,CAAC,GAAG,CAAC,aAAa,QAAQ,CAAC,KAAK,EAAE,WAAW,SAAS,QAAQ,CAAC,KAAK,EAAE,YAAY,MAAM,CAAC,CAAC;QACjG,OAAO,CAAC,GAAG,CAAC,YAAY,QAAQ,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC,gBAAgB,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEjF,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;QAEhC,MAAM,QAAQ,CAAC,OAAO,EAAE,CAAC;IAE3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC;QACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,aAAa,EAAE,CAAC","sourcesContent":["#!/usr/bin/env node\n/**\n * Test ONNX local inference with Phi-4 model\n */\n\nimport { ONNXLocalProvider } from './providers/onnx-local.js';\nimport { PHI4_MODEL_PATH } from '../utils/model-downloader.js';\n\nasync function testONNXLocal() {\n console.log('๐Ÿงช Testing ONNX Local Inference (Phi-4 CPU)\\n');\n\n try {\n const provider = new ONNXLocalProvider({\n modelPath: PHI4_MODEL_PATH,\n executionProviders: ['cpu'],\n maxTokens: 50\n });\n\n console.log('Test: Simple Inference');\n console.log('======================');\n\n const response = await provider.chat({\n model: 'phi-4',\n messages: [\n { role: 'user', content: 'What is 2+2?' }\n ],\n maxTokens: 20\n });\n\n console.log('\\n๐Ÿ“ฅ Response:');\n console.log(` Text: ${response.content[0].type === 'text' ? response.content[0].text : ''}`);\n console.log(` Latency: ${response.metadata?.latency}ms`);\n console.log(` Tokens: ${response.usage?.inputTokens} in / ${response.usage?.outputTokens} out`);\n console.log(` Cost: $${response.metadata?.cost}`);\n console.log(` Providers: ${response.metadata?.executionProviders?.join(', ')}`);\n\n console.log('\\nโœ… Test passed!');\n\n await provider.dispose();\n\n } catch (error) {\n console.error('\\nโŒ Test failed:', error);\n process.exit(1);\n }\n}\n\ntestONNXLocal();\n"]}
@@ -3,6 +3,20 @@
3
3
  *
4
4
  * Downloads Phi-4 ONNX model from HuggingFace on first use
5
5
  */
6
+ /**
7
+ * Where ONNX models live on disk.
8
+ *
9
+ * These paths were previously relative ('./models/...'), so they resolved
10
+ * against process.cwd() and a ~4.6GB download landed in whatever directory the
11
+ * command happened to run from โ€” re-downloaded once per working directory, and
12
+ * left untracked inside any repository it was invoked in.
13
+ *
14
+ * Exported so the reader (router/providers/onnx-local.ts) can resolve the same
15
+ * path the writer uses; the two previously disagreed (phi-4 vs phi-4-mini).
16
+ */
17
+ export declare const MODEL_ROOT: string;
18
+ export declare const PHI4_MODEL_PATH: string;
19
+ export declare const PHI4_MODEL_DATA_PATH: string;
6
20
  export interface DownloadProgress {
7
21
  downloaded: number;
8
22
  total: number;
@@ -1 +1 @@
1
- {"version":3,"file":"model-downloader.d.ts","sourceRoot":"","sources":["../../src/utils/model-downloader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,OAAO,CAA4B;IAE3C;;;;OAIG;IACH,OAAO,CAAC,SAAS,CAIf;IAEF,OAAO,CAAC,aAAa,CAInB;IAEF;;OAEG;IACH,iBAAiB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO;IAK9C;;OAEG;IACH,OAAO,CAAC,cAAc;IAItB;;OAEG;IACG,aAAa,CACjB,SAAS,CAAC,EAAE,SAAS,EACrB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,IAAI,GAChD,OAAO,CAAC,MAAM,CAAC;IAkFlB;;OAEG;IACG,eAAe,CAAC,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC;IA+BzF;;OAEG;IACG,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAyB/E;;OAEG;IACH,YAAY,IAAI,SAAS;IAIzB;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,QAAQ,EAAE,gBAAgB,GAAG,MAAM;CAI1D;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,iBAAwB,CAAC;AAErD;;GAEG;AACH,wBAAsB,eAAe,CACnC,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,IAAI,GAChD,OAAO,CAAC,MAAM,CAAC,CAEjB"}
1
+ {"version":3,"file":"model-downloader.d.ts","sourceRoot":"","sources":["../../src/utils/model-downloader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH;;;;;;;;;;GAUG;AACH,eAAO,MAAM,UAAU,QACwB,CAAC;AAEhD,eAAO,MAAM,eAAe,QAE3B,CAAC;AAEF,eAAO,MAAM,oBAAoB,QAA4B,CAAC;AAE9D,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,OAAO,CAA4B;IAE3C;;;;OAIG;IACH,OAAO,CAAC,SAAS,CAIf;IAEF,OAAO,CAAC,aAAa,CAInB;IAEF;;OAEG;IACH,iBAAiB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO;IAK9C;;OAEG;IACH,OAAO,CAAC,cAAc;IAItB;;OAEG;IACG,aAAa,CACjB,SAAS,CAAC,EAAE,SAAS,EACrB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,IAAI,GAChD,OAAO,CAAC,MAAM,CAAC;IAkFlB;;OAEG;IACG,eAAe,CAAC,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC;IA+BzF;;OAEG;IACG,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAyB/E;;OAEG;IACH,YAAY,IAAI,SAAS;IAIzB;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,QAAQ,EAAE,gBAAgB,GAAG,MAAM;CAI1D;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,iBAAwB,CAAC;AAErD;;GAEG;AACH,wBAAsB,eAAe,CACnC,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,IAAI,GAChD,OAAO,CAAC,MAAM,CAAC,CAEjB"}