@revealui/ai 0.10.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +10 -10
  2. package/dist/client/hooks/useAgentStream.d.ts +2 -0
  3. package/dist/client/hooks/useAgentStream.d.ts.map +1 -1
  4. package/dist/index.d.ts +2 -0
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +2 -0
  7. package/dist/llm/artifact-provenance.d.ts +73 -0
  8. package/dist/llm/artifact-provenance.d.ts.map +1 -0
  9. package/dist/llm/artifact-provenance.js +189 -0
  10. package/dist/llm/cache-utils.d.ts +0 -9
  11. package/dist/llm/cache-utils.d.ts.map +1 -1
  12. package/dist/llm/cache-utils.js +0 -17
  13. package/dist/llm/client.d.ts +16 -9
  14. package/dist/llm/client.d.ts.map +1 -1
  15. package/dist/llm/client.js +113 -61
  16. package/dist/llm/inference-route.d.ts +46 -0
  17. package/dist/llm/inference-route.d.ts.map +1 -0
  18. package/dist/llm/inference-route.js +154 -0
  19. package/dist/llm/local-ai-profile.d.ts.map +1 -1
  20. package/dist/llm/local-ai-profile.js +3 -3
  21. package/dist/llm/providers/groq.d.ts +1 -1
  22. package/dist/llm/providers/groq.d.ts.map +1 -1
  23. package/dist/llm/providers/groq.js +6 -3
  24. package/dist/llm/providers/inference-snaps.d.ts +6 -5
  25. package/dist/llm/providers/inference-snaps.d.ts.map +1 -1
  26. package/dist/llm/providers/inference-snaps.js +6 -5
  27. package/dist/llm/providers/ollama.d.ts +1 -1
  28. package/dist/llm/providers/ollama.d.ts.map +1 -1
  29. package/dist/llm/providers/ollama.js +3 -2
  30. package/dist/llm/providers/us-origin-snaps.d.ts +21 -11
  31. package/dist/llm/providers/us-origin-snaps.d.ts.map +1 -1
  32. package/dist/llm/providers/us-origin-snaps.js +23 -13
  33. package/dist/llm/resolve.d.ts.map +1 -1
  34. package/dist/llm/resolve.js +9 -2
  35. package/dist/llm/token-counter.d.ts.map +1 -1
  36. package/dist/llm/token-counter.js +4 -1
  37. package/dist/llm/tool-json-schema.d.ts +16 -0
  38. package/dist/llm/tool-json-schema.d.ts.map +1 -0
  39. package/dist/llm/tool-json-schema.js +64 -0
  40. package/dist/llm/workspace-provider-config.d.ts.map +1 -1
  41. package/dist/llm/workspace-provider-config.js +9 -2
  42. package/dist/orchestration/runtime.d.ts +3 -17
  43. package/dist/orchestration/runtime.d.ts.map +1 -1
  44. package/dist/orchestration/runtime.js +4 -15
  45. package/dist/orchestration/streaming-runtime.d.ts.map +1 -1
  46. package/dist/orchestration/streaming-runtime.js +2 -2
  47. package/dist/tools/admin/factory.d.ts +6 -0
  48. package/dist/tools/admin/factory.d.ts.map +1 -1
  49. package/dist/tools/admin/factory.js +6 -1
  50. package/dist/tools/admin/user-tools.js +2 -2
  51. package/dist/tools/mcp-adapter.d.ts +10 -94
  52. package/dist/tools/mcp-adapter.d.ts.map +1 -1
  53. package/dist/tools/mcp-adapter.js +10 -146
  54. package/dist/tools/mcp-sampling.d.ts +3 -3
  55. package/dist/tools/mcp-sampling.js +3 -3
  56. package/dist/tools/registry.d.ts.map +1 -1
  57. package/dist/tools/registry.js +2 -1
  58. package/package.json +29 -4
@@ -10,6 +10,7 @@ import { decryptApiKey } from '@revealui/db/crypto';
10
10
  import { tenantProviderConfigs, userApiKeys } from '@revealui/db/schema';
11
11
  import { CircuitBreaker, CircuitBreakerOpenError, } from '@revealui/resilience';
12
12
  import { and, eq } from 'drizzle-orm';
13
+ import { defaultBaseURLForProvider, defaultModelForProvider, isGroqCatalogModel, resolveInferenceRoute, } from './inference-route.js';
13
14
  import { applyLocalAiProfileToEnv } from './local-ai-profile.js';
14
15
  import { AnthropicProvider } from './providers/anthropic.js';
15
16
  import { GroqProvider } from './providers/groq.js';
@@ -17,11 +18,10 @@ import { InferenceSnapsProvider, } from './providers/inference-snaps.js';
17
18
  import { OllamaProvider } from './providers/ollama.js';
18
19
  import { OpenAIProvider } from './providers/openai.js';
19
20
  import { OpenAICompatProvider } from './providers/openai-compat.js';
20
- import { DEFAULT_US_ORIGIN_INFERENCE_SNAP } from './providers/us-origin-snaps.js';
21
21
  import { XaiProvider } from './providers/xai.js';
22
22
  import { ResponseCache } from './response-cache.js';
23
- import { SemanticCache, } from './semantic-cache.js';
24
23
  import { estimateRequest as _estimateRequestTokens } from './token-counter.js';
24
+ export { defaultBaseURLForProvider, defaultModelForProvider, GROQ_DEFAULT_BASE_URL, GROQ_DEFAULT_MODEL, groqAcceptedModel, isGroqCatalogModel, resolveInferenceRoute, resolveModelForProvider, } from './inference-route.js';
25
25
  /**
26
26
  * Providers reachable from a hosted (serverless) deployment. Localhost-only
27
27
  * providers are false. Consumed by PR-2/PR-3 (resolver + settings UI) to pick
@@ -51,13 +51,20 @@ export class LLMClient {
51
51
  rateLimitState;
52
52
  responseCache;
53
53
  semanticCache;
54
+ semanticCacheLoading;
54
55
  healthMonitor;
55
56
  circuitBreaker;
56
57
  fallbackCircuitBreaker;
57
58
  /** Tracks the last resolved API key so we only recreate the provider when it changes */
58
59
  currentApiKey;
59
60
  constructor(config) {
60
- this.config = config;
61
+ const route = resolveInferenceRoute({
62
+ provider: config.provider,
63
+ model: config.model,
64
+ baseURL: config.baseURL,
65
+ groqCredentialAvailable: config.provider === 'groq',
66
+ });
67
+ this.config = { ...config, ...route };
61
68
  this.currentApiKey = config.apiKey;
62
69
  this.rateLimitState = {
63
70
  requests: [],
@@ -68,10 +75,10 @@ export class LLMClient {
68
75
  if (config.enableResponseCache) {
69
76
  this.responseCache = new ResponseCache(config.responseCacheOptions);
70
77
  }
71
- // Initialize semantic cache if enabled
72
- if (config.enableSemanticCache) {
73
- this.semanticCache = new SemanticCache(config.semanticCacheOptions);
74
- }
78
+ // SemanticCache is loaded on first chat() when enableSemanticCache is
79
+ // set. A static import pulls VectorMemoryService → @revealui/db/client →
80
+ // @revealui/config, which throws REVEALUI_PUBLIC_SERVER_URL in production
81
+ // (Apify Store 0.1.8). BYOK construction must not evaluate that graph.
75
82
  // Wire health monitor if provided
76
83
  this.healthMonitor = config.healthMonitor;
77
84
  // Per-provider circuit breakers — isolate outages so one provider's failure
@@ -87,22 +94,22 @@ export class LLMClient {
87
94
  }
88
95
  // Wire dedicated embed provider if supplied
89
96
  this.embedProviderOverride = config.embedProvider;
90
- // Create primary provider
91
- this.provider = this.createProvider(config.provider, {
92
- apiKey: config.apiKey,
93
- baseURL: config.baseURL,
94
- model: config.model,
95
- temperature: config.temperature,
96
- maxTokens: config.maxTokens,
97
+ // Create primary provider from the resolved route (never a Groq id on OpenAI)
98
+ this.provider = this.createProvider(this.config.provider, {
99
+ apiKey: this.config.apiKey,
100
+ baseURL: this.config.baseURL,
101
+ model: this.config.model,
102
+ temperature: this.config.temperature,
103
+ maxTokens: this.config.maxTokens,
97
104
  });
98
105
  // Create fallback provider if specified
99
- if (config.fallbackProvider) {
100
- this.fallbackProvider = this.createProvider(config.fallbackProvider, {
101
- apiKey: config.apiKey, // Note: In practice, you'd want separate API keys
102
- baseURL: config.baseURL,
103
- model: config.model,
104
- temperature: config.temperature,
105
- maxTokens: config.maxTokens,
106
+ if (this.config.fallbackProvider) {
107
+ this.fallbackProvider = this.createProvider(this.config.fallbackProvider, {
108
+ apiKey: this.config.apiKey, // Note: In practice, you'd want separate API keys
109
+ baseURL: this.config.baseURL,
110
+ model: this.config.model,
111
+ temperature: this.config.temperature,
112
+ maxTokens: this.config.maxTokens,
106
113
  });
107
114
  }
108
115
  }
@@ -185,13 +192,29 @@ export class LLMClient {
185
192
  this.rateLimitState.requests.push(now);
186
193
  this.rateLimitState.dailyRequests++;
187
194
  }
195
+ async ensureSemanticCache() {
196
+ if (!this.config.enableSemanticCache) {
197
+ return undefined;
198
+ }
199
+ if (this.semanticCache) {
200
+ return this.semanticCache;
201
+ }
202
+ if (!this.semanticCacheLoading) {
203
+ this.semanticCacheLoading = import('./semantic-cache.js').then(({ SemanticCache }) => {
204
+ this.semanticCache = new SemanticCache(this.config.semanticCacheOptions);
205
+ return this.semanticCache;
206
+ });
207
+ }
208
+ return this.semanticCacheLoading;
209
+ }
188
210
  async chat(messages, options) {
189
211
  await this.refreshProviderIfNeeded();
190
212
  // Check semantic cache first (if enabled)
191
213
  // Semantic cache is more powerful - matches similar queries, not just exact matches
192
- if (this.semanticCache) {
193
- const query = this.semanticCache.extractQuery(messages);
194
- const cached = await this.semanticCache.get(query);
214
+ const semanticCache = await this.ensureSemanticCache();
215
+ if (semanticCache) {
216
+ const query = semanticCache.extractQuery(messages);
217
+ const cached = await semanticCache.get(query);
195
218
  if (cached) {
196
219
  // Semantic cache hit - return immediately without API call
197
220
  return {
@@ -241,9 +264,9 @@ export class LLMClient {
241
264
  const response = await this.circuitBreaker.execute(() => this.provider.chat(messages, options));
242
265
  this.healthMonitor?.recordCall(this.config.provider, Date.now() - callStart);
243
266
  // Store in semantic cache (if enabled)
244
- if (this.semanticCache) {
245
- const query = this.semanticCache.extractQuery(messages);
246
- await this.semanticCache.set(query, response.content, response.usage);
267
+ if (semanticCache) {
268
+ const query = semanticCache.extractQuery(messages);
269
+ await semanticCache.set(query, response.content, response.usage);
247
270
  }
248
271
  // Store in response cache (if enabled)
249
272
  if (this.responseCache) {
@@ -464,13 +487,13 @@ export class LLMClient {
464
487
  *
465
488
  * Canonical Inference Snaps is the reference local provider on Ubuntu — offline,
466
489
  * silicon-optimized, no API key required. Product usage is **US-origin snaps
467
- * only** (nemotron-3-nano default; gemma3/4 also allowlisted). See
490
+ * only** (gemma3 default; gemma4 and nemotron also allowlisted). See
468
491
  * `providers/us-origin-snaps.ts` and `providers/inference-snaps.ts`.
469
492
  *
470
493
  * Provider defaults:
471
- * inference-snaps → nemotron-3-nano (base URL defaults to http://localhost:9090/v1)
472
- * groq → qwen/qwen3-32b
473
- * ollama → gemma4:e2b (base URL defaults to http://localhost:11434)
494
+ * inference-snaps → gemma3 (base URL defaults to http://localhost:9090/v1)
495
+ * groq → openai/gpt-oss-120b (Groq-accepted default; retired llama ids remap)
496
+ * ollama → DEFAULT_DAILY_OLLAMA_MODEL (qwen2.5:3b; base URL http://localhost:11434)
474
497
  * anthropic → claude-sonnet-4-6 (base URL defaults to https://api.anthropic.com/v1)
475
498
  * openai → gpt-4o (base URL defaults to https://api.openai.com/v1)
476
499
  * xai → grok-4.5 (base URL defaults to https://api.x.ai/v1)
@@ -521,18 +544,18 @@ export function createLLMClientFromEnv() {
521
544
  let defaultModel;
522
545
  if (provider === 'anthropic') {
523
546
  apiKey = process.env.ANTHROPIC_API_KEY;
524
- baseURL = process.env.ANTHROPIC_BASE_URL ?? 'https://api.anthropic.com/v1';
525
- defaultModel = 'claude-sonnet-4-6';
547
+ baseURL = process.env.ANTHROPIC_BASE_URL ?? defaultBaseURLForProvider('anthropic');
548
+ defaultModel = defaultModelForProvider('anthropic');
526
549
  }
527
550
  else if (provider === 'openai') {
528
551
  apiKey = process.env.OPENAI_API_KEY;
529
- baseURL = process.env.OPENAI_BASE_URL ?? 'https://api.openai.com/v1';
530
- defaultModel = 'gpt-4o';
552
+ baseURL = process.env.OPENAI_BASE_URL ?? defaultBaseURLForProvider('openai');
553
+ defaultModel = defaultModelForProvider('openai');
531
554
  }
532
555
  else if (provider === 'xai') {
533
556
  apiKey = process.env.XAI_API_KEY;
534
- baseURL = process.env.XAI_BASE_URL ?? 'https://api.x.ai/v1';
535
- defaultModel = 'grok-4.5';
557
+ baseURL = process.env.XAI_BASE_URL ?? defaultBaseURLForProvider('xai');
558
+ defaultModel = defaultModelForProvider('xai');
536
559
  }
537
560
  else if (provider === 'huggingface') {
538
561
  apiKey = process.env.HF_TOKEN;
@@ -540,34 +563,43 @@ export function createLLMClientFromEnv() {
540
563
  }
541
564
  else if (provider === 'groq') {
542
565
  apiKey = process.env.GROQ_API_KEY;
543
- baseURL = process.env.GROQ_BASE_URL;
544
- defaultModel = 'qwen/qwen3-32b';
566
+ baseURL = process.env.GROQ_BASE_URL ?? defaultBaseURLForProvider('groq');
567
+ defaultModel = defaultModelForProvider('groq');
545
568
  }
546
569
  else if (provider === 'ollama') {
547
570
  apiKey = 'ollama'; // Ollama ignores the API key
548
571
  // Ollama's OpenAI-compatible endpoint lives at /v1
549
572
  const ollamaBase = process.env.OLLAMA_BASE_URL ?? 'http://localhost:11434';
550
573
  baseURL = ollamaBase.endsWith('/v1') ? ollamaBase : `${ollamaBase}/v1`;
551
- defaultModel = 'gemma4:e2b';
574
+ defaultModel = defaultModelForProvider('ollama');
552
575
  }
553
576
  else if (provider === 'inference-snaps') {
554
577
  apiKey = 'inference-snaps'; // inference-snaps ignores the API key
555
578
  // Defaults to Canonical's Inference Snap local service on port 9090; override
556
579
  // via INFERENCE_SNAPS_BASE_URL when the snap listens on a non-default port.
557
580
  // Model defaults to the US-origin allowlist default (asserted in provider ctor).
558
- baseURL = process.env.INFERENCE_SNAPS_BASE_URL ?? 'http://localhost:9090/v1';
559
- defaultModel = DEFAULT_US_ORIGIN_INFERENCE_SNAP;
581
+ baseURL = process.env.INFERENCE_SNAPS_BASE_URL ?? defaultBaseURLForProvider('inference-snaps');
582
+ defaultModel = defaultModelForProvider('inference-snaps');
583
+ }
584
+ const route = resolveInferenceRoute({
585
+ provider,
586
+ model: process.env.LLM_MODEL ?? defaultModel,
587
+ baseURL,
588
+ groqCredentialAvailable: Boolean(process.env.GROQ_API_KEY),
589
+ });
590
+ if (route.provider === 'groq' && provider !== 'groq') {
591
+ apiKey = process.env.GROQ_API_KEY;
560
592
  }
561
593
  if (!apiKey) {
562
- throw new Error(`API key not found for provider "${provider}". Set the corresponding env var ` +
594
+ throw new Error(`API key not found for provider "${route.provider}". Set the corresponding env var ` +
563
595
  `(INFERENCE_SNAPS_BASE_URL, GROQ_API_KEY, OLLAMA_BASE_URL, HF_TOKEN, ` +
564
596
  `ANTHROPIC_API_KEY, OPENAI_API_KEY, or XAI_API_KEY).`);
565
597
  }
566
598
  return new LLMClient({
567
- provider,
599
+ provider: route.provider,
568
600
  apiKey,
569
- baseURL,
570
- model: process.env.LLM_MODEL ?? defaultModel,
601
+ baseURL: route.baseURL,
602
+ model: route.model,
571
603
  temperature: process.env.LLM_TEMPERATURE ? parseFloat(process.env.LLM_TEMPERATURE) : undefined,
572
604
  maxTokens: process.env.LLM_MAX_TOKENS ? parseInt(process.env.LLM_MAX_TOKENS, 10) : undefined,
573
605
  enableCacheByDefault: process.env.LLM_ENABLE_CACHE === 'true' || process.env.ANTHROPIC_ENABLE_CACHE === 'true',
@@ -580,9 +612,12 @@ export function createLLMClientFromEnv() {
580
612
  /**
581
613
  * Create an LLM client using a user's stored BYOK API key.
582
614
  *
583
- * Looks up the user's preferred provider from `tenant_provider_configs`
584
- * (falling back to the first key in `user_api_keys`), decrypts the key
585
- * with AES-256-GCM, and returns a configured LLMClient.
615
+ * Looks up the user's preferred provider from `tenant_provider_configs`.
616
+ * If that provider has no saved key, uses another saved key (hosted-viable
617
+ * when `opts.hostedViableOnly` is set — e.g. a saved Groq key). Decrypts
618
+ * with AES-256-GCM and returns a configured LLMClient whose model and
619
+ * base URL match the **key's** provider, never a stale preferred-provider
620
+ * model (a Groq id must not be sent to OpenAI).
586
621
  *
587
622
  * Returns `null` if the user has no stored keys (callers should fall back
588
623
  * to `createLLMClientFromEnv()` or return a 402/feature-unavailable error).
@@ -606,15 +641,22 @@ auditStore, opts) {
606
641
  .from(tenantProviderConfigs)
607
642
  .where(and(eq(tenantProviderConfigs.userId, userId), eq(tenantProviderConfigs.isDefault, true)))
608
643
  .limit(1);
609
- // Find the matching API key (preferred provider, or any available key)
610
- const keyQuery = db
611
- .select()
612
- .from(userApiKeys)
613
- .where(preferredConfig
614
- ? and(eq(userApiKeys.userId, userId), eq(userApiKeys.provider, preferredConfig.provider))
615
- : eq(userApiKeys.userId, userId))
616
- .limit(1);
617
- const [keyRow] = await keyQuery;
644
+ // All of this user's keys. Preferred provider wins when it has a key;
645
+ // otherwise use another saved key (hosted-viable on hosted).
646
+ const keyRows = await db.select().from(userApiKeys).where(eq(userApiKeys.userId, userId));
647
+ const preferredKey = preferredConfig
648
+ ? keyRows.find((row) => row.provider === preferredConfig.provider)
649
+ : undefined;
650
+ const groqKey = keyRows.find((row) => row.provider === 'groq');
651
+ const fallbackKey = keyRows.find((row) => {
652
+ if (opts?.hostedViableOnly && !isHostedViable(row.provider)) {
653
+ return false;
654
+ }
655
+ return true;
656
+ });
657
+ const preferredModel = preferredConfig?.model ?? undefined;
658
+ const groqModelSelected = Boolean(preferredModel && isGroqCatalogModel(preferredModel));
659
+ const keyRow = groqModelSelected && groqKey ? groqKey : (preferredKey ?? fallbackKey);
618
660
  if (!keyRow)
619
661
  return null;
620
662
  const provider = keyRow.provider;
@@ -623,7 +665,12 @@ auditStore, opts) {
623
665
  if (opts?.hostedViableOnly && !isHostedViable(provider))
624
666
  return null;
625
667
  const plaintext = decryptApiKey(keyRow.encryptedKey);
626
- const model = preferredConfig?.model ?? undefined;
668
+ const requestedModel = preferredConfig?.provider === provider || groqModelSelected ? preferredModel : undefined;
669
+ const route = resolveInferenceRoute({
670
+ provider,
671
+ model: requestedModel,
672
+ groqCredentialAvailable: provider === 'groq' || Boolean(groqKey),
673
+ });
627
674
  // Fire-and-forget: record when this key was last used (best-effort, never blocks)
628
675
  db.update(userApiKeys)
629
676
  .set({ lastUsedAt: new Date() })
@@ -638,10 +685,15 @@ auditStore, opts) {
638
685
  eventType: 'byok:key:accessed',
639
686
  severity: 'info',
640
687
  agentId: 'system',
641
- payload: { userId, provider, keyId: keyRow.id },
688
+ payload: { userId, provider: route.provider, keyId: keyRow.id },
642
689
  policyViolations: [],
643
690
  })
644
691
  .catch(() => undefined);
645
692
  }
646
- return new LLMClient({ provider, apiKey: plaintext, model });
693
+ return new LLMClient({
694
+ provider: route.provider,
695
+ apiKey: plaintext,
696
+ model: route.model,
697
+ baseURL: route.baseURL,
698
+ });
647
699
  }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Provider + model + host pairing for LLM clients.
3
+ *
4
+ * A2A Send Task and /api/agent-stream both construct an LLMClient through
5
+ * resolveLLMClientForRequest. This module is the single place that refuses
6
+ * the production pairing: a Groq catalog id on an OpenAI host
7
+ * (`llama-3.3-70b-versatile` posted to api.openai.com).
8
+ */
9
+ export type LLMProviderType = 'anthropic' | 'openai' | 'groq' | 'huggingface' | 'ollama' | 'inference-snaps' | 'xai';
10
+ /** Groq's recommended replacement for llama-3.3-70b-versatile (retired 2026-08-16). */
11
+ export declare const GROQ_DEFAULT_MODEL = "openai/gpt-oss-120b";
12
+ export declare const GROQ_DEFAULT_BASE_URL = "https://api.groq.com/openai/v1";
13
+ export declare function isGroqCatalogModel(model: string): boolean;
14
+ /** Default catalog model for a provider. */
15
+ export declare function defaultModelForProvider(provider: LLMProviderType): string | undefined;
16
+ /** Default OpenAI-compatible base URL for a provider. */
17
+ export declare function defaultBaseURLForProvider(provider: LLMProviderType): string | undefined;
18
+ /** Current Groq-accepted model. Retired catalog ids map to the Groq default. */
19
+ export declare function groqAcceptedModel(requested: string | undefined): string;
20
+ /**
21
+ * Pick a model that belongs to `provider`. A Groq catalog id is never
22
+ * forwarded to OpenAI (walk residual: `llama-3.3-70b-versatile` on api.openai.com).
23
+ */
24
+ export declare function resolveModelForProvider(provider: LLMProviderType, requested: string | undefined): string | undefined;
25
+ export interface InferenceRouteInput {
26
+ provider: LLMProviderType;
27
+ model?: string;
28
+ baseURL?: string;
29
+ /** True when a Groq credential is available (saved key or GROQ_API_KEY). */
30
+ groqCredentialAvailable?: boolean;
31
+ }
32
+ export interface InferenceRoute {
33
+ provider: LLMProviderType;
34
+ model?: string;
35
+ baseURL?: string;
36
+ }
37
+ /**
38
+ * Resolve provider, model, and host together.
39
+ *
40
+ * When the selected model is a Groq catalog id and a Groq credential exists,
41
+ * the request goes to Groq's OpenAI-compatible host with a Groq-accepted
42
+ * model. When the OpenAI client is actually used, a Groq id is replaced
43
+ * with the OpenAI default — never posted to api.openai.com.
44
+ */
45
+ export declare function resolveInferenceRoute(input: InferenceRouteInput): InferenceRoute;
46
+ //# sourceMappingURL=inference-route.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inference-route.d.ts","sourceRoot":"","sources":["../../src/llm/inference-route.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAOH,MAAM,MAAM,eAAe,GACvB,WAAW,GACX,QAAQ,GACR,MAAM,GACN,aAAa,GACb,QAAQ,GACR,iBAAiB,GACjB,KAAK,CAAC;AAEV,uFAAuF;AACvF,eAAO,MAAM,kBAAkB,wBAAwB,CAAC;AACxD,eAAO,MAAM,qBAAqB,mCAAmC,CAAC;AAyCtE,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CASzD;AAED,4CAA4C;AAC5C,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM,GAAG,SAAS,CAiBrF;AAED,yDAAyD;AACzD,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM,GAAG,SAAS,CAiBvF;AAED,gFAAgF;AAChF,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAKvE;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,eAAe,EACzB,SAAS,EAAE,MAAM,GAAG,SAAS,GAC5B,MAAM,GAAG,SAAS,CAQpB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,eAAe,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4EAA4E;IAC5E,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,eAAe,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAiBD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,mBAAmB,GAAG,cAAc,CAkBhF"}
@@ -0,0 +1,154 @@
1
+ /**
2
+ * Provider + model + host pairing for LLM clients.
3
+ *
4
+ * A2A Send Task and /api/agent-stream both construct an LLMClient through
5
+ * resolveLLMClientForRequest. This module is the single place that refuses
6
+ * the production pairing: a Groq catalog id on an OpenAI host
7
+ * (`llama-3.3-70b-versatile` posted to api.openai.com).
8
+ */
9
+ import { DEFAULT_DAILY_OLLAMA_MODEL, DEFAULT_US_ORIGIN_INFERENCE_SNAP, } from './providers/us-origin-snaps.js';
10
+ /** Groq's recommended replacement for llama-3.3-70b-versatile (retired 2026-08-16). */
11
+ export const GROQ_DEFAULT_MODEL = 'openai/gpt-oss-120b';
12
+ export const GROQ_DEFAULT_BASE_URL = 'https://api.groq.com/openai/v1';
13
+ /**
14
+ * Groq catalog ids — current and retired — that must never be sent to
15
+ * api.openai.com. Set lookup plus prefix checks; no regex (M2).
16
+ */
17
+ const GROQ_CATALOG_MODELS = new Set([
18
+ 'llama-3.3-70b-versatile',
19
+ 'llama-3.3-70b-specdec',
20
+ 'llama-3.1-70b-versatile',
21
+ 'llama-3.1-8b-instant',
22
+ 'llama-3.2-90b-vision-preview',
23
+ 'llama-3.2-11b-vision-preview',
24
+ 'llama-3.2-3b-preview',
25
+ 'llama-3.2-1b-preview',
26
+ 'mixtral-8x7b-32768',
27
+ 'gemma2-9b-it',
28
+ 'gemma-7b-it',
29
+ 'qwen/qwen3-32b',
30
+ 'qwen/qwen3.6-27b',
31
+ 'openai/gpt-oss-120b',
32
+ 'openai/gpt-oss-20b',
33
+ 'openai/gpt-oss-safeguard-20b',
34
+ ]);
35
+ /** Retired Groq ids that the public API rejects (same error text as OpenAI). */
36
+ const GROQ_RETIRED_MODELS = new Set([
37
+ 'llama-3.3-70b-versatile',
38
+ 'llama-3.3-70b-specdec',
39
+ 'llama-3.1-70b-versatile',
40
+ 'llama-3.1-8b-instant',
41
+ 'llama-3.2-90b-vision-preview',
42
+ 'llama-3.2-11b-vision-preview',
43
+ 'llama-3.2-3b-preview',
44
+ 'llama-3.2-1b-preview',
45
+ 'mixtral-8x7b-32768',
46
+ 'gemma2-9b-it',
47
+ 'gemma-7b-it',
48
+ 'qwen/qwen3-32b',
49
+ ]);
50
+ export function isGroqCatalogModel(model) {
51
+ if (GROQ_CATALOG_MODELS.has(model))
52
+ return true;
53
+ return (model.startsWith('llama-3.') ||
54
+ model.startsWith('mixtral-') ||
55
+ model.startsWith('gemma2-') ||
56
+ model.startsWith('openai/gpt-oss') ||
57
+ model.startsWith('qwen/qwen3'));
58
+ }
59
+ /** Default catalog model for a provider. */
60
+ export function defaultModelForProvider(provider) {
61
+ switch (provider) {
62
+ case 'anthropic':
63
+ return 'claude-sonnet-4-6';
64
+ case 'openai':
65
+ return 'gpt-4o';
66
+ case 'xai':
67
+ return 'grok-4.5';
68
+ case 'groq':
69
+ return GROQ_DEFAULT_MODEL;
70
+ case 'ollama':
71
+ return DEFAULT_DAILY_OLLAMA_MODEL;
72
+ case 'inference-snaps':
73
+ return DEFAULT_US_ORIGIN_INFERENCE_SNAP;
74
+ default:
75
+ return undefined;
76
+ }
77
+ }
78
+ /** Default OpenAI-compatible base URL for a provider. */
79
+ export function defaultBaseURLForProvider(provider) {
80
+ switch (provider) {
81
+ case 'anthropic':
82
+ return 'https://api.anthropic.com/v1';
83
+ case 'openai':
84
+ return 'https://api.openai.com/v1';
85
+ case 'xai':
86
+ return 'https://api.x.ai/v1';
87
+ case 'groq':
88
+ return GROQ_DEFAULT_BASE_URL;
89
+ case 'ollama':
90
+ return 'http://localhost:11434/v1';
91
+ case 'inference-snaps':
92
+ return 'http://localhost:9090/v1';
93
+ default:
94
+ return undefined;
95
+ }
96
+ }
97
+ /** Current Groq-accepted model. Retired catalog ids map to the Groq default. */
98
+ export function groqAcceptedModel(requested) {
99
+ if (requested && isGroqCatalogModel(requested) && !GROQ_RETIRED_MODELS.has(requested)) {
100
+ return requested;
101
+ }
102
+ return GROQ_DEFAULT_MODEL;
103
+ }
104
+ /**
105
+ * Pick a model that belongs to `provider`. A Groq catalog id is never
106
+ * forwarded to OpenAI (walk residual: `llama-3.3-70b-versatile` on api.openai.com).
107
+ */
108
+ export function resolveModelForProvider(provider, requested) {
109
+ if (provider === 'groq') {
110
+ return groqAcceptedModel(requested);
111
+ }
112
+ if (requested && !isGroqCatalogModel(requested)) {
113
+ return requested;
114
+ }
115
+ return defaultModelForProvider(provider);
116
+ }
117
+ const OPENAI_API_HOSTNAME = 'api.openai.com';
118
+ /**
119
+ * True only when `url` is a parseable absolute URL whose hostname is exactly
120
+ * api.openai.com. Prefix/substring checks are not used — `api.openai.com.evil.com`
121
+ * must not count as OpenAI (CodeQL js/incomplete-url-substring-sanitization).
122
+ */
123
+ function isOpenAiHost(url) {
124
+ try {
125
+ return new URL(url).hostname === OPENAI_API_HOSTNAME;
126
+ }
127
+ catch {
128
+ return false;
129
+ }
130
+ }
131
+ /**
132
+ * Resolve provider, model, and host together.
133
+ *
134
+ * When the selected model is a Groq catalog id and a Groq credential exists,
135
+ * the request goes to Groq's OpenAI-compatible host with a Groq-accepted
136
+ * model. When the OpenAI client is actually used, a Groq id is replaced
137
+ * with the OpenAI default — never posted to api.openai.com.
138
+ */
139
+ export function resolveInferenceRoute(input) {
140
+ const groqModel = Boolean(input.model && isGroqCatalogModel(input.model));
141
+ if (groqModel && (input.provider === 'groq' || input.groqCredentialAvailable)) {
142
+ const keepCustomGroqUrl = Boolean(input.provider === 'groq' && input.baseURL && !isOpenAiHost(input.baseURL));
143
+ return {
144
+ provider: 'groq',
145
+ model: groqAcceptedModel(input.model),
146
+ baseURL: keepCustomGroqUrl ? input.baseURL : defaultBaseURLForProvider('groq'),
147
+ };
148
+ }
149
+ return {
150
+ provider: input.provider,
151
+ model: resolveModelForProvider(input.provider, input.model),
152
+ baseURL: input.baseURL ?? defaultBaseURLForProvider(input.provider),
153
+ };
154
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"local-ai-profile.d.ts","sourceRoot":"","sources":["../../src/llm/local-ai-profile.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAWH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAE/D,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,iBAAiB,GAAG,IAAI,CAAC;AAElE,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,WAAW,CAAC;IAClB,QAAQ,EAAE,eAAe,CAAC;IAC1B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,0CAA0C;IAC1C,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,8DAA8D;IAC9D,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,iDAAiD;IACjD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAK9C;AAED,gEAAgE;AAChE,wBAAgB,uBAAuB,IAAI,MAAM,CAEhD;AAED,6DAA6D;AAC7D,wBAAgB,gBAAgB,IAAI,cAAc,CAiBjD;AAED,wBAAgB,kBAAkB,CAAC,IAAI,GAAE,MAAgC,GAAG,cAAc,GAAG,IAAI,CAShG;AAED,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,cAAc,EACvB,IAAI,GAAE,MAAgC,GACrC,IAAI,CAqCN;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,OAAO,GAAE,cAAc,GAAG,IAA2B,GACpD,IAAI,CAyBN;AAED,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,WAAW,GAChB,IAAI,CAAC,cAAc,EAAE,UAAU,GAAG,OAAO,GAAG,SAAS,GAAG,WAAW,GAAG,MAAM,CAAC,CAuC/E"}
1
+ {"version":3,"file":"local-ai-profile.d.ts","sourceRoot":"","sources":["../../src/llm/local-ai-profile.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAUH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAE/D,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,iBAAiB,GAAG,IAAI,CAAC;AAElE,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,WAAW,CAAC;IAClB,QAAQ,EAAE,eAAe,CAAC;IAC1B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,0CAA0C;IAC1C,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,8DAA8D;IAC9D,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,iDAAiD;IACjD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAK9C;AAED,gEAAgE;AAChE,wBAAgB,uBAAuB,IAAI,MAAM,CAEhD;AAED,6DAA6D;AAC7D,wBAAgB,gBAAgB,IAAI,cAAc,CAiBjD;AAED,wBAAgB,kBAAkB,CAAC,IAAI,GAAE,MAAgC,GAAG,cAAc,GAAG,IAAI,CAShG;AAED,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,cAAc,EACvB,IAAI,GAAE,MAAgC,GACrC,IAAI,CAqCN;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,OAAO,GAAE,cAAc,GAAG,IAA2B,GACpD,IAAI,CAyBN;AAED,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,WAAW,GAChB,IAAI,CAAC,cAAc,EAAE,UAAU,GAAG,OAAO,GAAG,SAAS,GAAG,WAAW,GAAG,MAAM,CAAC,CAuC/E"}
@@ -10,7 +10,7 @@
10
10
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
11
11
  import { homedir } from 'node:os';
12
12
  import { dirname, join } from 'node:path';
13
- import { DEFAULT_DAILY_OLLAMA_MODEL, DEFAULT_LOW_RAM_INFERENCE_SNAP, DEFAULT_US_ORIGIN_INFERENCE_SNAP, } from './providers/us-origin-snaps.js';
13
+ import { DEFAULT_DAILY_OLLAMA_MODEL, DEFAULT_LOW_RAM_INFERENCE_SNAP, } from './providers/us-origin-snaps.js';
14
14
  export function getLocalAiProfilePath() {
15
15
  return (process.env.REVEALUI_INFERENCE_PROFILE_PATH ??
16
16
  join(homedir(), '.local', 'share', 'revealui', 'inference-profile.json'));
@@ -139,7 +139,7 @@ export function profileDefaultsForTier(tier) {
139
139
  model: DEFAULT_DAILY_OLLAMA_MODEL,
140
140
  baseURL: 'http://127.0.0.1:11434',
141
141
  keepAlive: '0',
142
- note: 'Ollama small US model; weights unload after each request',
142
+ note: 'Ollama daily default (qwen2.5:3b); weights unload after each request',
143
143
  };
144
144
  case 'snaps':
145
145
  return {
@@ -152,7 +152,7 @@ export function profileDefaultsForTier(tier) {
152
152
  case 'heavy':
153
153
  return {
154
154
  provider: 'inference-snaps',
155
- model: DEFAULT_US_ORIGIN_INFERENCE_SNAP,
155
+ model: 'nemotron-3-nano',
156
156
  baseURL: null,
157
157
  keepAlive: null,
158
158
  note: 'Heavy snap — needs substantial RAM; avoid concurrent IDE load on 4GB WSL',
@@ -10,7 +10,7 @@ export interface GroqProviderConfig extends Omit<LLMProviderConfig, 'apiKey'> {
10
10
  apiKey: string;
11
11
  /** Defaults to https://api.groq.com/openai/v1 */
12
12
  baseURL?: string;
13
- /** Defaults to qwen/qwen3-32b */
13
+ /** Defaults to openai/gpt-oss-120b (current Groq-accepted catalog) */
14
14
  model?: string;
15
15
  }
16
16
  export declare class GroqProvider implements LLMProvider {
@@ -1 +1 @@
1
- {"version":3,"file":"groq.d.ts","sourceRoot":"","sources":["../../../src/llm/providers/groq.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,cAAc,EACd,QAAQ,EACR,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,gBAAgB,EAChB,OAAO,EACP,oBAAoB,EACrB,MAAM,WAAW,CAAC;AAGnB,MAAM,WAAW,kBAAmB,SAAQ,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC;IAC3E,MAAM,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,YAAa,YAAW,WAAW;IAC9C,OAAO,CAAC,KAAK,CAAuB;gBAExB,MAAM,EAAE,kBAAkB;IAQtC,YAAY,IAAI,oBAAoB;IAepC,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC;IAIzE,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,aAAa,CAAC,QAAQ,CAAC;IAIhF,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,QAAQ,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,EAAE,CAAC;CAG9F"}
1
+ {"version":3,"file":"groq.d.ts","sourceRoot":"","sources":["../../../src/llm/providers/groq.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EACV,SAAS,EACT,cAAc,EACd,QAAQ,EACR,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,gBAAgB,EAChB,OAAO,EACP,oBAAoB,EACrB,MAAM,WAAW,CAAC;AAGnB,MAAM,WAAW,kBAAmB,SAAQ,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC;IAC3E,MAAM,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sEAAsE;IACtE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,YAAa,YAAW,WAAW;IAC9C,OAAO,CAAC,KAAK,CAAuB;gBAExB,MAAM,EAAE,kBAAkB;IAUtC,YAAY,IAAI,oBAAoB;IAepC,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC;IAIzE,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,aAAa,CAAC,QAAQ,CAAC;IAIhF,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,QAAQ,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,EAAE,CAAC;CAG9F"}
@@ -5,18 +5,21 @@
5
5
  * Free tier: 6,000 TPM / 500k TPD.
6
6
  * Sign up: console.groq.com
7
7
  */
8
+ import { GROQ_DEFAULT_BASE_URL, GROQ_DEFAULT_MODEL } from '../inference-route.js';
8
9
  import { OpenAICompatProvider } from './openai-compat.js';
9
10
  export class GroqProvider {
10
11
  inner;
11
12
  constructor(config) {
12
13
  this.inner = new OpenAICompatProvider({
13
14
  ...config,
14
- baseURL: config.baseURL ?? 'https://api.groq.com/openai/v1',
15
- model: config.model ?? 'qwen/qwen3-32b',
15
+ baseURL: config.baseURL ?? GROQ_DEFAULT_BASE_URL,
16
+ // Retired catalog ids (llama-3.3-70b-versatile, qwen/qwen3-32b) 404 on
17
+ // Groq's public API as of 2026-08-16. Prefer the current Groq default.
18
+ model: config.model ?? GROQ_DEFAULT_MODEL,
16
19
  });
17
20
  }
18
21
  capabilities() {
19
- // Profile for the default model (qwen/qwen3-32b). Groq exposes no embeddings endpoint.
22
+ // Profile for the default model. Groq exposes no embeddings endpoint.
20
23
  return {
21
24
  providerTag: 'groq',
22
25
  tools: true,
@@ -6,17 +6,18 @@
6
6
  *
7
7
  * Product hardline: US-origin snap models only (see us-origin-snaps.ts).
8
8
  * Allowlisted snaps (install these):
9
- * nemotron-3-nano - NVIDIA general + tools (default)
9
+ * gemma3 - Google general + vision (default; WSL-supported)
10
+ * gemma4 - Google general + vision + tools
11
+ * nemotron-3-nano - NVIDIA general + tools (heavy / capable hosts)
10
12
  * nemotron-3-nano-omni - NVIDIA multimodal
11
- * gemma3 / gemma4 - Google general + vision + tools
12
13
  *
13
14
  * Canonical also publishes non-US snaps (deepseek-r1, qwen-*, glm-*). Those
14
15
  * are rejected at construction unless REVEALUI_ALLOW_NON_US_MODELS=1.
15
16
  *
16
17
  * Install a model:
17
- * sudo snap install nemotron-3-nano
18
- * nemotron-3-nano set http.port=9090 # optional: change port
19
- * nemotron-3-nano status # shows base URL and available models
18
+ * sudo snap install gemma3
19
+ * gemma3 set http.port=9090 --assume-yes
20
+ * gemma3 status # shows base URL and available models
20
21
  *
21
22
  * Set env vars:
22
23
  * INFERENCE_SNAPS_BASE_URL=http://localhost:9090/v1
@@ -1 +1 @@
1
- {"version":3,"file":"inference-snaps.d.ts","sourceRoot":"","sources":["../../../src/llm/providers/inference-snaps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,cAAc,EACd,QAAQ,EACR,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,gBAAgB,EAChB,OAAO,EACP,oBAAoB,EACrB,MAAM,WAAW,CAAC;AAEnB,OAAO,EAEL,gCAAgC,EACjC,MAAM,sBAAsB,CAAC;AAE9B,MAAM,WAAW,4BAA6B,SAAQ,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC;IACrF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,qBAAa,sBAAuB,YAAW,WAAW;IACxD,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,OAAO,CAAS;gBAEZ,MAAM,EAAE,4BAA4B;IAchD,YAAY,IAAI,oBAAoB;IAgBpC,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC;IAIzE,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,aAAa,CAAC,QAAQ,CAAC;IAI1E,KAAK,CACT,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EACvB,QAAQ,CAAC,EAAE,eAAe,GACzB,OAAO,CAAC,SAAS,GAAG,SAAS,EAAE,CAAC;CAsBpC;AAED,OAAO,EAAE,gCAAgC,EAAE,CAAC"}
1
+ {"version":3,"file":"inference-snaps.d.ts","sourceRoot":"","sources":["../../../src/llm/providers/inference-snaps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,cAAc,EACd,QAAQ,EACR,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,gBAAgB,EAChB,OAAO,EACP,oBAAoB,EACrB,MAAM,WAAW,CAAC;AAEnB,OAAO,EAEL,gCAAgC,EACjC,MAAM,sBAAsB,CAAC;AAE9B,MAAM,WAAW,4BAA6B,SAAQ,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC;IACrF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,qBAAa,sBAAuB,YAAW,WAAW;IACxD,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,OAAO,CAAS;gBAEZ,MAAM,EAAE,4BAA4B;IAchD,YAAY,IAAI,oBAAoB;IAgBpC,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC;IAIzE,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,aAAa,CAAC,QAAQ,CAAC;IAI1E,KAAK,CACT,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EACvB,QAAQ,CAAC,EAAE,eAAe,GACzB,OAAO,CAAC,SAAS,GAAG,SAAS,EAAE,CAAC;CAsBpC;AAED,OAAO,EAAE,gCAAgC,EAAE,CAAC"}