@revealui/ai 0.2.9 → 0.4.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 (82) hide show
  1. package/README.md +200 -26
  2. package/dist/a2a/handler.d.ts +3 -1
  3. package/dist/a2a/handler.d.ts.map +1 -1
  4. package/dist/a2a/handler.js +24 -7
  5. package/dist/a2a/task-store.d.ts.map +1 -1
  6. package/dist/a2a/task-store.js +5 -1
  7. package/dist/client/hooks/useAgentStream.d.ts +84 -1
  8. package/dist/client/hooks/useAgentStream.d.ts.map +1 -1
  9. package/dist/client/hooks/useAgentStream.js +106 -10
  10. package/dist/index.d.ts +4 -6
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +4 -15
  13. package/dist/ingestion/admin-indexer.js +1 -1
  14. package/dist/ingestion/pipeline.d.ts +1 -1
  15. package/dist/ingestion/pipeline.d.ts.map +1 -1
  16. package/dist/llm/client.d.ts +33 -10
  17. package/dist/llm/client.d.ts.map +1 -1
  18. package/dist/llm/client.js +70 -57
  19. package/dist/llm/key-validator.d.ts.map +1 -1
  20. package/dist/llm/key-validator.js +0 -27
  21. package/dist/llm/providers/inference-snaps.d.ts +7 -5
  22. package/dist/llm/providers/inference-snaps.d.ts.map +1 -1
  23. package/dist/llm/providers/inference-snaps.js +7 -5
  24. package/dist/llm/providers/openai-compat.d.ts +1 -1
  25. package/dist/llm/providers/openai-compat.js +1 -1
  26. package/dist/llm/response-cache.d.ts +1 -2
  27. package/dist/llm/response-cache.d.ts.map +1 -1
  28. package/dist/llm/response-cache.js +1 -2
  29. package/dist/llm/server.d.ts +1 -1
  30. package/dist/llm/server.d.ts.map +1 -1
  31. package/dist/llm/server.js +3 -1
  32. package/dist/memory/crdt/lww-register.js +1 -1
  33. package/dist/memory/preferences/user-preferences-manager.d.ts.map +1 -1
  34. package/dist/memory/preferences/user-preferences-manager.js +1 -1
  35. package/dist/memory/services/index.d.ts +2 -0
  36. package/dist/memory/services/index.d.ts.map +1 -1
  37. package/dist/memory/services/index.js +1 -0
  38. package/dist/memory/services/reconciliation-service.d.ts +64 -0
  39. package/dist/memory/services/reconciliation-service.d.ts.map +1 -0
  40. package/dist/memory/services/reconciliation-service.js +127 -0
  41. package/dist/memory/stores/working-memory.d.ts.map +1 -1
  42. package/dist/memory/stores/working-memory.js +1 -1
  43. package/dist/memory/utils/index.d.ts +1 -2
  44. package/dist/memory/utils/index.d.ts.map +1 -1
  45. package/dist/memory/utils/index.js +1 -2
  46. package/dist/memory/utils/sql-helpers.d.ts +21 -66
  47. package/dist/memory/utils/sql-helpers.d.ts.map +1 -1
  48. package/dist/memory/utils/sql-helpers.js +34 -169
  49. package/dist/memory/vector/vector-memory-service.d.ts.map +1 -1
  50. package/dist/memory/vector/vector-memory-service.js +6 -1
  51. package/dist/orchestration/runtime.d.ts +30 -1
  52. package/dist/orchestration/runtime.d.ts.map +1 -1
  53. package/dist/orchestration/runtime.js +20 -3
  54. package/dist/orchestration/streaming-runtime.d.ts +48 -1
  55. package/dist/orchestration/streaming-runtime.d.ts.map +1 -1
  56. package/dist/orchestration/ticket-agent.d.ts +10 -1
  57. package/dist/orchestration/ticket-agent.d.ts.map +1 -1
  58. package/dist/orchestration/ticket-agent.js +11 -2
  59. package/dist/skills/catalog/vercel-catalog.d.ts.map +1 -1
  60. package/dist/skills/catalog/vercel-catalog.js +13 -7
  61. package/dist/tools/mcp-adapter.d.ts +192 -1
  62. package/dist/tools/mcp-adapter.d.ts.map +1 -1
  63. package/dist/tools/mcp-adapter.js +434 -1
  64. package/dist/tools/mcp-elicitation.d.ts +128 -0
  65. package/dist/tools/mcp-elicitation.d.ts.map +1 -0
  66. package/dist/tools/mcp-elicitation.js +121 -0
  67. package/dist/tools/mcp-events.d.ts +270 -0
  68. package/dist/tools/mcp-events.d.ts.map +1 -0
  69. package/dist/tools/mcp-events.js +165 -0
  70. package/dist/tools/mcp-sampling.d.ts +155 -0
  71. package/dist/tools/mcp-sampling.d.ts.map +1 -0
  72. package/dist/tools/mcp-sampling.js +171 -0
  73. package/dist/tools/ticket-tools.d.ts +35 -2
  74. package/dist/tools/ticket-tools.d.ts.map +1 -1
  75. package/dist/tools/ticket-tools.js +32 -2
  76. package/package.json +38 -12
  77. package/dist/llm/providers/vultr.d.ts +0 -18
  78. package/dist/llm/providers/vultr.d.ts.map +0 -1
  79. package/dist/llm/providers/vultr.js +0 -169
  80. package/dist/memory/utils/deep-clone.d.ts +0 -10
  81. package/dist/memory/utils/deep-clone.d.ts.map +0 -1
  82. package/dist/memory/utils/deep-clone.js +0 -9
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAKH;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,OAAO,CASxC;AAGD,cAAc,gBAAgB,CAAC;AAE/B,cAAc,kBAAkB,CAAC;AAIjC,cAAc,uBAAuB,CAAC;AAEtC,cAAc,sBAAsB,CAAC;AAErC,cAAc,iBAAiB,CAAC;AAChC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,kCAAkC,CAAC;AACjD,cAAc,wBAAwB,CAAC;AACvC,cAAc,oCAAoC,CAAC;AAEnD,cAAc,mBAAmB,CAAC;AAElC,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uCAAuC,CAAC;AACtD,cAAc,iCAAiC,CAAC;AAChD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sCAAsC,CAAC;AACrD,cAAc,iCAAiC,CAAC;AAEhD,cAAc,mBAAmB,CAAC;AAElC,cAAc,sBAAsB,CAAC;AAErC,cAAc,iBAAiB,CAAC;AAChC,cAAc,yBAAyB,CAAC;AACxC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAGH,cAAc,gBAAgB,CAAC;AAE/B,cAAc,kBAAkB,CAAC;AAIjC,cAAc,uBAAuB,CAAC;AAEtC,cAAc,sBAAsB,CAAC;AAErC,cAAc,iBAAiB,CAAC;AAChC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oCAAoC,CAAC;AACnD,cAAc,kCAAkC,CAAC;AACjD,cAAc,wBAAwB,CAAC;AACvC,cAAc,oCAAoC,CAAC;AAEnD,cAAc,mBAAmB,CAAC;AAElC,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uCAAuC,CAAC;AACtD,cAAc,iCAAiC,CAAC;AAChD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sCAAsC,CAAC;AACrD,cAAc,iCAAiC,CAAC;AAEhD,cAAc,mBAAmB,CAAC;AAElC,cAAc,sBAAsB,CAAC;AAErC,cAAc,iBAAiB,CAAC;AAChC,cAAc,yBAAyB,CAAC;AACxC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC"}
package/dist/index.js CHANGED
@@ -45,21 +45,6 @@
45
45
  *
46
46
  * @packageDocumentation
47
47
  */
48
- import { isFeatureEnabled } from '@revealui/core/features';
49
- import { logger } from '@revealui/core/observability/logger';
50
- /**
51
- * Check if the AI package is licensed for use.
52
- * Returns false with a warning log if no Pro/Enterprise license is active.
53
- * Call at application startup to verify licensing.
54
- */
55
- export function checkAiLicense() {
56
- if (!isFeatureEnabled('ai')) {
57
- logger.warn('[@revealui/ai] AI features require a Pro or Enterprise license. ' +
58
- 'Visit https://revealui.com/pricing for details.');
59
- return false;
60
- }
61
- return true;
62
- }
63
48
  // Re-export A2A protocol
64
49
  export * from './a2a/index.js';
65
50
  // Re-export audit trail
@@ -74,6 +59,7 @@ export * from './ingestion/index.js';
74
59
  export * from './llm/client.js';
75
60
  export * from './llm/provider-health.js';
76
61
  export * from './llm/providers/base.js';
62
+ export * from './llm/providers/inference-snaps.js';
77
63
  export * from './llm/providers/openai-compat.js';
78
64
  export * from './llm/token-counter.js';
79
65
  export * from './llm/workspace-provider-config.js';
@@ -96,6 +82,9 @@ export * from './tools/base.js';
96
82
  export * from './tools/deduplicator.js';
97
83
  export * from './tools/document-summarizer.js';
98
84
  export * from './tools/mcp-adapter.js';
85
+ export * from './tools/mcp-elicitation.js';
86
+ export * from './tools/mcp-events.js';
87
+ export * from './tools/mcp-sampling.js';
99
88
  export * from './tools/memory/index.js';
100
89
  export * from './tools/registry.js';
101
90
  export * from './tools/ticket-tools.js';
@@ -63,7 +63,7 @@ export class AdminIndexer {
63
63
  const title = extractTitle(event.doc);
64
64
  await this.pipeline.ingest({
65
65
  workspaceId,
66
- sourceType: 'cms_collection',
66
+ sourceType: 'admin_collection',
67
67
  sourceCollection,
68
68
  sourceId,
69
69
  title,
@@ -7,7 +7,7 @@
7
7
  import type { Database } from '@revealui/db/client';
8
8
  export interface IngestRequest {
9
9
  workspaceId: string;
10
- sourceType: 'cms_collection' | 'url' | 'file' | 'text';
10
+ sourceType: 'admin_collection' | 'url' | 'file' | 'text';
11
11
  sourceId?: string;
12
12
  sourceCollection?: string;
13
13
  title?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../src/ingestion/pipeline.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAOpD,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,gBAAgB,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;IACvD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAcD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,EAAE,CAAW;IACrB,OAAO,CAAC,MAAM,CAAW;IACzB,OAAO,CAAC,WAAW,CAAsC;IACzD,OAAO,CAAC,QAAQ,CAA6B;gBAEjC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC;IAOtF,MAAM,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;IA6EjD,WAAW,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAa3D,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKjD,cAAc,CAClB,WAAW,EAAE,MAAM,EACnB,gBAAgB,EAAE,MAAM,EACxB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC;CAiBjB"}
1
+ {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../src/ingestion/pipeline.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAOpD,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,kBAAkB,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;IACzD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAcD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,EAAE,CAAW;IACrB,OAAO,CAAC,MAAM,CAAW;IACzB,OAAO,CAAC,WAAW,CAAsC;IACzD,OAAO,CAAC,QAAQ,CAA6B;gBAEjC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC;IAOtF,MAAM,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;IA6EjD,WAAW,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAa3D,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKjD,cAAc,CAClB,WAAW,EAAE,MAAM,EACnB,gBAAgB,EAAE,MAAM,EACxB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC;CAiBjB"}
@@ -3,19 +3,14 @@
3
3
  *
4
4
  * Single interface for all LLM providers with fallback and rate limiting
5
5
  */
6
- /**
7
- * Redact sensitive fields before passing an object to a logger.
8
- * Replaces API keys, tokens, and authorization headers with `[REDACTED]`.
9
- * Recurses into nested plain objects; leaves arrays and primitives as-is.
10
- */
11
- export declare function redactSensitiveFields(obj: Record<string, unknown>): Record<string, unknown>;
12
6
  import type { Database } from '@revealui/db/client';
7
+ import { CircuitBreaker } from '@revealui/resilience';
13
8
  import type { AuditStore } from '../audit/store.js';
14
9
  import type { ProviderHealthMonitor } from './provider-health.js';
15
10
  import type { Embedding, LLMChatOptions, LLMChunk, LLMEmbedOptions, LLMProvider, LLMResponse, LLMStreamOptions, Message } from './providers/base.js';
16
11
  import { type CacheStats, type ResponseCacheOptions } from './response-cache.js';
17
12
  import { type SemanticCacheOptions, type SemanticCacheStats } from './semantic-cache.js';
18
- export type LLMProviderType = 'vultr' | 'groq' | 'ollama' | 'huggingface' | 'inference-snaps';
13
+ export type LLMProviderType = 'groq' | 'ollama' | 'huggingface' | 'inference-snaps';
19
14
  export interface LLMClientConfig {
20
15
  provider: LLMProviderType;
21
16
  apiKey: string;
@@ -52,6 +47,10 @@ export interface LLMClientConfig {
52
47
  semanticCacheOptions?: SemanticCacheOptions;
53
48
  /** Optional health monitor - records latency + error rate per provider */
54
49
  healthMonitor?: ProviderHealthMonitor;
50
+ /** Circuit breaker failure threshold before tripping (default: 5) */
51
+ circuitBreakerFailureThreshold?: number;
52
+ /** Circuit breaker reset timeout in ms before half-open probe (default: 30000) */
53
+ circuitBreakerResetTimeout?: number;
55
54
  }
56
55
  export declare class LLMClient {
57
56
  private provider;
@@ -62,6 +61,8 @@ export declare class LLMClient {
62
61
  private responseCache?;
63
62
  private semanticCache?;
64
63
  private healthMonitor?;
64
+ private circuitBreaker;
65
+ private fallbackCircuitBreaker?;
65
66
  /** Tracks the last resolved API key so we only recreate the provider when it changes */
66
67
  private currentApiKey;
67
68
  constructor(config: LLMClientConfig);
@@ -84,6 +85,21 @@ export declare class LLMClient {
84
85
  tokens: number;
85
86
  estimatedCostUsd: number;
86
87
  };
88
+ /**
89
+ * Get circuit breaker stats for the primary and fallback providers.
90
+ */
91
+ getCircuitBreakerStats(): {
92
+ primary: {
93
+ name: string;
94
+ state: string;
95
+ stats: ReturnType<CircuitBreaker['getStats']>;
96
+ };
97
+ fallback?: {
98
+ name: string;
99
+ state: string;
100
+ stats: ReturnType<CircuitBreaker['getStats']>;
101
+ };
102
+ };
87
103
  /**
88
104
  * Get the provider health monitor if one was configured.
89
105
  */
@@ -113,13 +129,20 @@ export declare class LLMClient {
113
129
  * Create an LLM client from environment variables.
114
130
  *
115
131
  * When LLM_PROVIDER is not set, auto-detects the provider by checking env vars
116
- * in priority order: INFERENCE_SNAPS → GROQ → OLLAMA.
132
+ * in priority order: INFERENCE_SNAPS → GROQ → OLLAMA. If none are set, defaults
133
+ * to Inference Snaps at http://localhost:9090/v1 (Ubuntu local) and emits a
134
+ * one-line stderr warning so the implicit default is discoverable in logs.
117
135
  *
118
136
  * All providers use OpenAI-compatible APIs. No proprietary provider SDKs.
119
137
  *
138
+ * Canonical Inference Snaps is the reference local provider on Ubuntu — offline,
139
+ * silicon-optimized, no API key required. See `providers/inference-snaps.ts` for
140
+ * install docs (`sudo snap install gemma3`, etc.).
141
+ *
120
142
  * Provider defaults:
121
- * groq qwen/qwen3-32b
122
- * ollama gemma4:e2b
143
+ * inference-snaps gemma3 (base URL defaults to http://localhost:9090/v1)
144
+ * groq qwen/qwen3-32b
145
+ * ollama → gemma4:e2b (base URL defaults to http://localhost:11434)
123
146
  */
124
147
  export declare function createLLMClientFromEnv(): LLMClient;
125
148
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/llm/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/llm/client.ts"],"names":[],"mappings":"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"}
@@ -3,49 +3,13 @@
3
3
  *
4
4
  * Single interface for all LLM providers with fallback and rate limiting
5
5
  */
6
- // =============================================================================
7
- // Log redaction
8
- // =============================================================================
9
- const SENSITIVE_KEYS = new Set([
10
- 'apiKey',
11
- 'api_key',
12
- 'authorization',
13
- 'Authorization',
14
- 'x-ai-api-key',
15
- 'X-AI-Api-Key',
16
- 'token',
17
- 'secret',
18
- 'password',
19
- 'encryptedKey',
20
- 'encrypted_key',
21
- ]);
22
- /**
23
- * Redact sensitive fields before passing an object to a logger.
24
- * Replaces API keys, tokens, and authorization headers with `[REDACTED]`.
25
- * Recurses into nested plain objects; leaves arrays and primitives as-is.
26
- */
27
- export function redactSensitiveFields(obj) {
28
- const result = {};
29
- for (const [key, value] of Object.entries(obj)) {
30
- if (SENSITIVE_KEYS.has(key)) {
31
- result[key] = '[REDACTED]';
32
- }
33
- else if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
34
- result[key] = redactSensitiveFields(value);
35
- }
36
- else {
37
- result[key] = value;
38
- }
39
- }
40
- return result;
41
- }
42
6
  import { decryptApiKey } from '@revealui/db/crypto';
43
7
  import { tenantProviderConfigs, userApiKeys } from '@revealui/db/schema';
8
+ import { CircuitBreaker, CircuitBreakerOpenError, } from '@revealui/resilience';
44
9
  import { and, eq } from 'drizzle-orm';
45
10
  import { GroqProvider } from './providers/groq.js';
46
11
  import { InferenceSnapsProvider, } from './providers/inference-snaps.js';
47
12
  import { OllamaProvider } from './providers/ollama.js';
48
- import { VultrProvider } from './providers/vultr.js';
49
13
  import { ResponseCache } from './response-cache.js';
50
14
  import { SemanticCache, } from './semantic-cache.js';
51
15
  import { estimateRequest as _estimateRequestTokens } from './token-counter.js';
@@ -58,6 +22,8 @@ export class LLMClient {
58
22
  responseCache;
59
23
  semanticCache;
60
24
  healthMonitor;
25
+ circuitBreaker;
26
+ fallbackCircuitBreaker;
61
27
  /** Tracks the last resolved API key so we only recreate the provider when it changes */
62
28
  currentApiKey;
63
29
  constructor(config) {
@@ -78,6 +44,17 @@ export class LLMClient {
78
44
  }
79
45
  // Wire health monitor if provided
80
46
  this.healthMonitor = config.healthMonitor;
47
+ // Per-provider circuit breakers — isolate outages so one provider's failure
48
+ // doesn't block calls to a different provider
49
+ const cbConfig = {
50
+ failureThreshold: config.circuitBreakerFailureThreshold ?? 5,
51
+ resetTimeout: config.circuitBreakerResetTimeout ?? 30_000,
52
+ successThreshold: 2,
53
+ };
54
+ this.circuitBreaker = new CircuitBreaker(cbConfig);
55
+ if (config.fallbackProvider) {
56
+ this.fallbackCircuitBreaker = new CircuitBreaker(cbConfig);
57
+ }
81
58
  // Wire dedicated embed provider if supplied
82
59
  this.embedProviderOverride = config.embedProvider;
83
60
  // Create primary provider
@@ -101,8 +78,6 @@ export class LLMClient {
101
78
  }
102
79
  createProvider(type, config) {
103
80
  switch (type) {
104
- case 'vultr':
105
- return new VultrProvider(config);
106
81
  case 'groq':
107
82
  return new GroqProvider(config);
108
83
  case 'ollama':
@@ -221,7 +196,7 @@ export class LLMClient {
221
196
  const callStart = Date.now();
222
197
  try {
223
198
  this.recordRequest();
224
- const response = await this.provider.chat(messages, options);
199
+ const response = await this.circuitBreaker.execute(() => this.provider.chat(messages, options));
225
200
  this.healthMonitor?.recordCall(this.config.provider, Date.now() - callStart);
226
201
  // Store in semantic cache (if enabled)
227
202
  if (this.semanticCache) {
@@ -251,11 +226,14 @@ export class LLMClient {
251
226
  this.healthMonitor?.recordCall(this.config.provider, Date.now() - callStart, error instanceof Error ? error : new Error(String(error)));
252
227
  // Try fallback if available
253
228
  if (this.fallbackProvider && this.config.fallbackProvider) {
229
+ const fp = this.fallbackProvider;
254
230
  const fallbackStart = Date.now();
255
231
  try {
256
- const fallbackResponse = await this.fallbackProvider.chat(messages, options);
232
+ const fb = this.fallbackCircuitBreaker
233
+ ? await this.fallbackCircuitBreaker.execute(() => fp.chat(messages, options))
234
+ : await fp.chat(messages, options);
257
235
  this.healthMonitor?.recordCall(this.config.fallbackProvider, Date.now() - fallbackStart);
258
- return fallbackResponse;
236
+ return fb;
259
237
  }
260
238
  catch (fallbackError) {
261
239
  this.healthMonitor?.recordCall(this.config.fallbackProvider, Date.now() - fallbackStart, fallbackError instanceof Error ? fallbackError : new Error(String(fallbackError)));
@@ -274,13 +252,16 @@ export class LLMClient {
274
252
  const embedProvider = this.embedProviderOverride ?? this.provider;
275
253
  try {
276
254
  this.recordRequest();
277
- return await embedProvider.embed(text, options);
255
+ return await this.circuitBreaker.execute(() => embedProvider.embed(text, options));
278
256
  }
279
257
  catch (error) {
280
258
  // Try fallback if available (only when using the primary provider path)
281
259
  if (!this.embedProviderOverride && this.fallbackProvider) {
260
+ const fp = this.fallbackProvider;
282
261
  try {
283
- return await this.fallbackProvider.embed(text, options);
262
+ return this.fallbackCircuitBreaker
263
+ ? await this.fallbackCircuitBreaker.execute(() => fp.embed(text, options))
264
+ : await fp.embed(text, options);
284
265
  }
285
266
  catch {
286
267
  throw new Error(`Both primary and fallback providers failed: ${error instanceof Error ? error.message : String(error)}`);
@@ -296,6 +277,11 @@ export class LLMClient {
296
277
  throw new Error('Rate limit exceeded');
297
278
  }
298
279
  try {
280
+ // Circuit breaker check — streaming can't use execute() wrapper
281
+ // so we check state and record outcomes manually
282
+ if (this.circuitBreaker.isOpen()) {
283
+ throw new CircuitBreakerOpenError(`llm-${this.config.provider}`);
284
+ }
299
285
  this.recordRequest();
300
286
  yield* this.provider.stream(messages, options);
301
287
  }
@@ -303,6 +289,9 @@ export class LLMClient {
303
289
  // Try fallback if available
304
290
  if (this.fallbackProvider) {
305
291
  try {
292
+ if (this.fallbackCircuitBreaker?.isOpen()) {
293
+ throw new CircuitBreakerOpenError(`llm-${this.config.fallbackProvider}`);
294
+ }
306
295
  yield* this.fallbackProvider.stream(messages, options);
307
296
  }
308
297
  catch {
@@ -321,6 +310,25 @@ export class LLMClient {
321
310
  estimateRequest(messages) {
322
311
  return _estimateRequestTokens(messages, this.config.model ?? '');
323
312
  }
313
+ /**
314
+ * Get circuit breaker stats for the primary and fallback providers.
315
+ */
316
+ getCircuitBreakerStats() {
317
+ return {
318
+ primary: {
319
+ name: `llm-${this.config.provider}`,
320
+ state: this.circuitBreaker.getState(),
321
+ stats: this.circuitBreaker.getStats(),
322
+ },
323
+ fallback: this.fallbackCircuitBreaker && this.config.fallbackProvider
324
+ ? {
325
+ name: `llm-${this.config.fallbackProvider}`,
326
+ state: this.fallbackCircuitBreaker.getState(),
327
+ stats: this.fallbackCircuitBreaker.getStats(),
328
+ }
329
+ : undefined,
330
+ };
331
+ }
324
332
  /**
325
333
  * Get the provider health monitor if one was configured.
326
334
  */
@@ -360,13 +368,20 @@ export class LLMClient {
360
368
  * Create an LLM client from environment variables.
361
369
  *
362
370
  * When LLM_PROVIDER is not set, auto-detects the provider by checking env vars
363
- * in priority order: INFERENCE_SNAPS → GROQ → OLLAMA.
371
+ * in priority order: INFERENCE_SNAPS → GROQ → OLLAMA. If none are set, defaults
372
+ * to Inference Snaps at http://localhost:9090/v1 (Ubuntu local) and emits a
373
+ * one-line stderr warning so the implicit default is discoverable in logs.
364
374
  *
365
375
  * All providers use OpenAI-compatible APIs. No proprietary provider SDKs.
366
376
  *
377
+ * Canonical Inference Snaps is the reference local provider on Ubuntu — offline,
378
+ * silicon-optimized, no API key required. See `providers/inference-snaps.ts` for
379
+ * install docs (`sudo snap install gemma3`, etc.).
380
+ *
367
381
  * Provider defaults:
368
- * groq qwen/qwen3-32b
369
- * ollama gemma4:e2b
382
+ * inference-snaps gemma3 (base URL defaults to http://localhost:9090/v1)
383
+ * groq qwen/qwen3-32b
384
+ * ollama → gemma4:e2b (base URL defaults to http://localhost:11434)
370
385
  */
371
386
  export function createLLMClientFromEnv() {
372
387
  // Auto-detect provider when LLM_PROVIDER is not explicitly set
@@ -384,18 +399,14 @@ export function createLLMClientFromEnv() {
384
399
  provider = 'ollama';
385
400
  }
386
401
  else {
387
- throw new Error('No LLM provider configured. Set one of: OLLAMA_BASE_URL (local Ollama), ' +
388
- 'INFERENCE_SNAPS_BASE_URL (local snap), GROQ_API_KEY (cloud). ' +
389
- 'Alternatively, set LLM_PROVIDER explicitly.');
402
+ // Zero-config Ubuntu default: assume Inference Snaps on the standard
403
+ // local port. Operator sees the warning once at boot.
404
+ provider = 'inference-snaps';
390
405
  }
391
406
  let apiKey;
392
407
  let baseURL;
393
408
  let defaultModel;
394
- if (provider === 'vultr') {
395
- apiKey = process.env.VULTR_API_KEY;
396
- baseURL = process.env.VULTR_BASE_URL;
397
- }
398
- else if (provider === 'huggingface') {
409
+ if (provider === 'huggingface') {
399
410
  apiKey = process.env.HF_TOKEN;
400
411
  baseURL = process.env.HF_MODEL_URL;
401
412
  }
@@ -413,12 +424,14 @@ export function createLLMClientFromEnv() {
413
424
  }
414
425
  else if (provider === 'inference-snaps') {
415
426
  apiKey = 'inference-snaps'; // inference-snaps ignores the API key
416
- baseURL = process.env.INFERENCE_SNAPS_BASE_URL;
427
+ // Defaults to Canonical's Inference Snap local service on port 9090; override
428
+ // via INFERENCE_SNAPS_BASE_URL when the snap listens on a non-default port.
429
+ baseURL = process.env.INFERENCE_SNAPS_BASE_URL ?? 'http://localhost:9090/v1';
417
430
  defaultModel = 'gemma3';
418
431
  }
419
432
  if (!apiKey) {
420
433
  throw new Error(`API key not found for provider "${provider}". Set the corresponding env var ` +
421
- `(INFERENCE_SNAPS_BASE_URL, GROQ_API_KEY, OLLAMA_BASE_URL, VULTR_API_KEY, or HF_TOKEN).`);
434
+ `(INFERENCE_SNAPS_BASE_URL, GROQ_API_KEY, OLLAMA_BASE_URL, or HF_TOKEN).`);
422
435
  }
423
436
  return new LLMClient({
424
437
  provider,
@@ -1 +1 @@
1
- {"version":3,"file":"key-validator.d.ts","sourceRoot":"","sources":["../../src/llm/key-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,MAAM,wBAAwB,GAAG;IAAE,KAAK,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAezF;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,wBAAwB,CAAC,CAuEnC"}
1
+ {"version":3,"file":"key-validator.d.ts","sourceRoot":"","sources":["../../src/llm/key-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,MAAM,wBAAwB,GAAG;IAAE,KAAK,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAezF;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,wBAAwB,CAAC,CA2CnC"}
@@ -41,22 +41,6 @@ export async function validateProviderKey(provider, apiKey) {
41
41
  // Any other non-OK status (429, 500 etc.) - treat as reachable but unknown
42
42
  return { valid: false, error: `Groq validation failed: HTTP ${res.status}` };
43
43
  }
44
- case 'anthropic': {
45
- // Anthropic has no free read endpoint. Validate by key format only.
46
- // Valid Anthropic keys start with "sk-ant-api".
47
- if (!apiKey.startsWith('sk-ant-api')) {
48
- return { valid: false, error: 'Anthropic API key must start with "sk-ant-api"' };
49
- }
50
- return { valid: true };
51
- }
52
- case 'openai': {
53
- // Validate by format - keys start with "sk-"
54
- // (Per LLM policy, OpenAI API calls are blocked until we have revenue.)
55
- if (!apiKey.startsWith('sk-')) {
56
- return { valid: false, error: 'OpenAI API key must start with "sk-"' };
57
- }
58
- return { valid: true };
59
- }
60
44
  case 'huggingface': {
61
45
  const res = await probeFetch('https://huggingface.co/api/whoami-v2', {
62
46
  headers: { Authorization: `Bearer ${apiKey}` },
@@ -68,17 +52,6 @@ export async function validateProviderKey(provider, apiKey) {
68
52
  }
69
53
  return { valid: false, error: `HuggingFace validation failed: HTTP ${res.status}` };
70
54
  }
71
- case 'vultr': {
72
- // Vultr Serverless Inference API (OpenAI-compatible)
73
- const res = await probeFetch('https://api.vultrinference.com/v1/models', {
74
- headers: { Authorization: `Bearer ${apiKey}` },
75
- });
76
- if (res.ok)
77
- return { valid: true };
78
- if (res.status === 401)
79
- return { valid: false, error: 'Invalid Vultr API key' };
80
- return { valid: false, error: `Vultr validation failed: HTTP ${res.status}` };
81
- }
82
55
  case 'ollama': {
83
56
  // Ollama is local - we cannot reliably probe it from the server.
84
57
  // Accept the key as-is (Ollama doesn't use API keys anyway).
@@ -4,11 +4,13 @@
4
4
  * Local inference via Canonical's inference-snaps OpenAI-compatible API.
5
5
  * No API key required. Zero cost, fully offline, hardware-optimized.
6
6
  *
7
- * Supported models (snaps):
8
- * gemma3 - general LLM + vision (text/image in, text out)
9
- * deepseek-r1 - reasoning LLM
10
- * qwen-vl - vision-language model (image + text)
11
- * nemotron-nano - general LLM (reasoning + non-reasoning)
7
+ * Supported models (snaps), per Canonical's official catalog at
8
+ * https://documentation.ubuntu.com/inference-snaps/reference/snaps/ :
9
+ * gemma3 - general LLM + vision (text/image in, text out)
10
+ * deepseek-r1 - reasoning LLM (chat completions)
11
+ * qwen-vl - vision-language model (image + text)
12
+ * nemotron-3-nano - general LLM (reasoning + non-reasoning, text only)
13
+ * nemotron-3-nano-omni - multimodal (text/image/video/audio in, text out)
12
14
  *
13
15
  * Install a model:
14
16
  * sudo snap install gemma3
@@ -1 +1 @@
1
- {"version":3,"file":"inference-snaps.d.ts","sourceRoot":"","sources":["../../../src/llm/providers/inference-snaps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,cAAc,EACd,QAAQ,EACR,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,gBAAgB,EAChB,OAAO,EACR,MAAM,WAAW,CAAC;AAGnB,MAAM,WAAW,4BAA6B,SAAQ,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC;IACrF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,OAAO,EAAE,MAAM,CAAC;IAChB,+FAA+F;IAC/F,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,sBAAuB,YAAW,WAAW;IACxD,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,OAAO,CAAS;gBAEZ,MAAM,EAAE,4BAA4B;IAahD,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"}
1
+ {"version":3,"file":"inference-snaps.d.ts","sourceRoot":"","sources":["../../../src/llm/providers/inference-snaps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,cAAc,EACd,QAAQ,EACR,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,gBAAgB,EAChB,OAAO,EACR,MAAM,WAAW,CAAC;AAGnB,MAAM,WAAW,4BAA6B,SAAQ,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC;IACrF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,OAAO,EAAE,MAAM,CAAC;IAChB,+FAA+F;IAC/F,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,sBAAuB,YAAW,WAAW;IACxD,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,OAAO,CAAS;gBAEZ,MAAM,EAAE,4BAA4B;IAahD,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"}
@@ -4,11 +4,13 @@
4
4
  * Local inference via Canonical's inference-snaps OpenAI-compatible API.
5
5
  * No API key required. Zero cost, fully offline, hardware-optimized.
6
6
  *
7
- * Supported models (snaps):
8
- * gemma3 - general LLM + vision (text/image in, text out)
9
- * deepseek-r1 - reasoning LLM
10
- * qwen-vl - vision-language model (image + text)
11
- * nemotron-nano - general LLM (reasoning + non-reasoning)
7
+ * Supported models (snaps), per Canonical's official catalog at
8
+ * https://documentation.ubuntu.com/inference-snaps/reference/snaps/ :
9
+ * gemma3 - general LLM + vision (text/image in, text out)
10
+ * deepseek-r1 - reasoning LLM (chat completions)
11
+ * qwen-vl - vision-language model (image + text)
12
+ * nemotron-3-nano - general LLM (reasoning + non-reasoning, text only)
13
+ * nemotron-3-nano-omni - multimodal (text/image/video/audio in, text out)
12
14
  *
13
15
  * Install a model:
14
16
  * sudo snap install gemma3
@@ -2,7 +2,7 @@
2
2
  * OpenAI-Compatible Provider
3
3
  *
4
4
  * Base implementation for any LLM API that follows the OpenAI chat/completions
5
- * format. Used by: Ollama, Groq, Inference Snaps, Vultr.
5
+ * format. Used by: Ollama, Groq, Inference Snaps.
6
6
  * NOT for direct OpenAI usage - RevealUI uses open-source models only.
7
7
  */
8
8
  import type { Embedding, LLMChatOptions, LLMChunk, LLMEmbedOptions, LLMProvider, LLMProviderConfig, LLMResponse, LLMStreamOptions, Message } from './base.js';
@@ -2,7 +2,7 @@
2
2
  * OpenAI-Compatible Provider
3
3
  *
4
4
  * Base implementation for any LLM API that follows the OpenAI chat/completions
5
- * format. Used by: Ollama, Groq, Inference Snaps, Vultr.
5
+ * format. Used by: Ollama, Groq, Inference Snaps.
6
6
  * NOT for direct OpenAI usage - RevealUI uses open-source models only.
7
7
  */
8
8
  const authorizationHeader = 'Authorization';
@@ -5,8 +5,7 @@
5
5
  * Provides 100% cost savings on cache hits vs Anthropic's 90% token-level savings.
6
6
  *
7
7
  * Use cases:
8
- * - Vultr (doesn't have prompt caching)
9
- * - OpenAI (doesn't have prompt caching)
8
+ * - Groq (doesn't have prompt caching)
10
9
  * - Any provider without built-in caching
11
10
  * - Supplement to Anthropic prompt caching for exact duplicates
12
11
  *
@@ -1 +1 @@
1
- {"version":3,"file":"response-cache.d.ts","sourceRoot":"","sources":["../../src/llm/response-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE7E,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,WAAW,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,YAAY,GAAG,gBAAgB,CAAC;IACnE,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE;QACN,YAAY,EAAE,MAAM,CAAC;QACrB,gBAAgB,EAAE,MAAM,CAAC;QACzB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;CACH;AAED,MAAM,WAAW,oBAAoB;IACnC,yDAAyD;IACzD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,KAAK,CAAmC;IAChD,OAAO,CAAC,KAAK,CAAsD;IACnE,OAAO,CAAC,WAAW,CAAU;gBAEjB,OAAO,GAAE,oBAAyB;IAqB9C;;;;;;;OAOG;IACH,WAAW,CACT,QAAQ,EAAE,OAAO,EAAE,EACnB,OAAO,CAAC,EAAE;QACR,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;QACzB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GACA,MAAM;IAqBT;;;;OAIG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAiB5C;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,GAAG,IAAI;IAShD;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIzB;;OAEG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAI5B;;OAEG;IACH,KAAK,IAAI,IAAI;IASb;;OAEG;IACH,QAAQ,IAAI,UAAU;IAatB;;OAEG;IACH,UAAU,IAAI,IAAI;IAQlB;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,MAAM,CAEpB;CACF;AAQD;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,aAAa,CAKpF;AAED;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,IAAI,CAI/C;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE;IACP,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;CACxB,GACA;IACD,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;CACzB,CAcA"}
1
+ {"version":3,"file":"response-cache.d.ts","sourceRoot":"","sources":["../../src/llm/response-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE7E,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,WAAW,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,YAAY,GAAG,gBAAgB,CAAC;IACnE,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE;QACN,YAAY,EAAE,MAAM,CAAC;QACrB,gBAAgB,EAAE,MAAM,CAAC;QACzB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;CACH;AAED,MAAM,WAAW,oBAAoB;IACnC,yDAAyD;IACzD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,KAAK,CAAmC;IAChD,OAAO,CAAC,KAAK,CAAsD;IACnE,OAAO,CAAC,WAAW,CAAU;gBAEjB,OAAO,GAAE,oBAAyB;IAqB9C;;;;;;;OAOG;IACH,WAAW,CACT,QAAQ,EAAE,OAAO,EAAE,EACnB,OAAO,CAAC,EAAE;QACR,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;QACzB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GACA,MAAM;IAqBT;;;;OAIG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAiB5C;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,GAAG,IAAI;IAShD;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIzB;;OAEG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAI5B;;OAEG;IACH,KAAK,IAAI,IAAI;IASb;;OAEG;IACH,QAAQ,IAAI,UAAU;IAatB;;OAEG;IACH,UAAU,IAAI,IAAI;IAQlB;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,MAAM,CAEpB;CACF;AAQD;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,aAAa,CAKpF;AAED;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,IAAI,CAI/C;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE;IACP,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;CACxB,GACA;IACD,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;CACzB,CAcA"}
@@ -5,8 +5,7 @@
5
5
  * Provides 100% cost savings on cache hits vs Anthropic's 90% token-level savings.
6
6
  *
7
7
  * Use cases:
8
- * - Vultr (doesn't have prompt caching)
9
- * - OpenAI (doesn't have prompt caching)
8
+ * - Groq (doesn't have prompt caching)
10
9
  * - Any provider without built-in caching
11
10
  * - Supplement to Anthropic prompt caching for exact duplicates
12
11
  *
@@ -10,5 +10,5 @@ export * from './providers/groq.js';
10
10
  export * from './providers/inference-snaps.js';
11
11
  export * from './providers/ollama.js';
12
12
  export * from './providers/openai-compat.js';
13
- export * from './providers/vultr.js';
13
+ export * from './workspace-provider-config.js';
14
14
  //# sourceMappingURL=server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/llm/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,cAAc,aAAa,CAAC;AAG5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,uBAAuB,CAAC;AACtC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,sBAAsB,CAAC"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/llm/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,cAAc,aAAa,CAAC;AAG5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,uBAAuB,CAAC;AACtC,cAAc,8BAA8B,CAAC;AAI7C,cAAc,gCAAgC,CAAC"}
@@ -12,4 +12,6 @@ export * from './providers/groq.js';
12
12
  export * from './providers/inference-snaps.js';
13
13
  export * from './providers/ollama.js';
14
14
  export * from './providers/openai-compat.js';
15
- export * from './providers/vultr.js';
15
+ // Export per-workspace provider registry (used by admin inference-config route
16
+ // to hydrate per-site config at boot + apply changes immediately on PUT)
17
+ export * from './workspace-provider-config.js';
@@ -26,7 +26,7 @@
26
26
  * ```
27
27
  */
28
28
  import { randomUUID } from 'node:crypto';
29
- import { deepClone } from '../utils/deep-clone.js';
29
+ import { deepClone } from '@revealui/core/utils/deep-clone';
30
30
  export class LWWRegister {
31
31
  value;
32
32
  timestamp;
@@ -1 +1 @@
1
- {"version":3,"file":"user-preferences-manager.d.ts","sourceRoot":"","sources":["../../../src/memory/preferences/user-preferences-manager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAGpE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGpD,OAAO,EAAe,KAAK,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAe5E;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,sBAAsB;IACjC,OAAO,CAAC,WAAW,CAA+B;IAClD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,EAAE,CAAW;IACrB,OAAO,CAAC,MAAM,CAAkD;IAEhE;;;;;;OAMG;gBACS,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ;IAcxD;;;;OAIG;IACH,cAAc,IAAI,eAAe;IAIjC;;;;;OAKG;IACH,iBAAiB,CAAC,OAAO,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,IAAI;IAsB1D;;;;OAIG;IACH,cAAc,CAAC,WAAW,EAAE,eAAe,GAAG,IAAI;IAUlD;;;;;OAKG;IACH,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAkBnC;;;;;OAKG;IACH,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI;IAyChD;;;;;;OAMG;IACH,KAAK,CAAC,KAAK,EAAE,sBAAsB,GAAG,sBAAsB;IAM5D;;;;;;;;OAQG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAoF3B;;;;;;;;OAQG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA+E3B;;;;OAIG;IACH,MAAM,IAAI,eAAe,CAAC,eAAe,CAAC;IAI1C;;;;;;;;OAQG;IACH,MAAM,CAAC,QAAQ,CACb,IAAI,EAAE,eAAe,CAAC,eAAe,CAAC,EACtC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,QAAQ,GACX,sBAAsB;IAMzB;;;;OAIG;IACH,KAAK,IAAI,sBAAsB;IAI/B;;OAEG;IACH,SAAS,IAAI,MAAM;IAInB;;OAEG;IACH,SAAS,IAAI,MAAM;CAGpB"}
1
+ {"version":3,"file":"user-preferences-manager.d.ts","sourceRoot":"","sources":["../../../src/memory/preferences/user-preferences-manager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAIpE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGpD,OAAO,EAAe,KAAK,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAc5E;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,sBAAsB;IACjC,OAAO,CAAC,WAAW,CAA+B;IAClD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,EAAE,CAAW;IACrB,OAAO,CAAC,MAAM,CAAkD;IAEhE;;;;;;OAMG;gBACS,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ;IAcxD;;;;OAIG;IACH,cAAc,IAAI,eAAe;IAIjC;;;;;OAKG;IACH,iBAAiB,CAAC,OAAO,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,IAAI;IAsB1D;;;;OAIG;IACH,cAAc,CAAC,WAAW,EAAE,eAAe,GAAG,IAAI;IAUlD;;;;;OAKG;IACH,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAkBnC;;;;;OAKG;IACH,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI;IAyChD;;;;;;OAMG;IACH,KAAK,CAAC,KAAK,EAAE,sBAAsB,GAAG,sBAAsB;IAM5D;;;;;;;;OAQG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAoF3B;;;;;;;;OAQG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA+E3B;;;;OAIG;IACH,MAAM,IAAI,eAAe,CAAC,eAAe,CAAC;IAI1C;;;;;;;;OAQG;IACH,MAAM,CAAC,QAAQ,CACb,IAAI,EAAE,eAAe,CAAC,eAAe,CAAC,EACtC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,QAAQ,GACX,sBAAsB;IAMzB;;;;OAIG;IACH,KAAK,IAAI,sBAAsB;IAI/B;;OAEG;IACH,SAAS,IAAI,MAAM;IAInB;;OAEG;IACH,SAAS,IAAI,MAAM;CAGpB"}
@@ -6,11 +6,11 @@
6
6
  */
7
7
  import { UserPreferencesSchema } from '@revealui/contracts/entities';
8
8
  import { createLogger } from '@revealui/core/observability/logger';
9
+ import { deepClone } from '@revealui/core/utils/deep-clone';
9
10
  import { users } from '@revealui/db/schema';
10
11
  import { eq } from 'drizzle-orm';
11
12
  import { LWWRegister } from '../crdt/lww-register.js';
12
13
  import { DatabaseConnectionError, DatabaseConstraintError, DatabaseOperationError, NotFoundError, ValidationError, } from '../errors/index.js';
13
- import { deepClone } from '../utils/deep-clone.js';
14
14
  import { findUserById } from '../utils/sql-helpers.js';
15
15
  // =============================================================================
16
16
  // User Preferences Manager
@@ -5,4 +5,6 @@
5
5
  */
6
6
  export type { EntityType } from './node-id-service.js';
7
7
  export { NodeIdService } from './node-id-service.js';
8
+ export type { Contradiction, ReconciledMemory, ReconciliationResult, SharedFactInput, } from './reconciliation-service.js';
9
+ export { buildReconciliationPrompt, parseReconciliationResponse, reconcileHeuristic, } from './reconciliation-service.js';
8
10
  //# sourceMappingURL=index.d.ts.map