@revealui/ai 0.3.0 → 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 (69) 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/llm/client.d.ts +33 -4
  14. package/dist/llm/client.d.ts.map +1 -1
  15. package/dist/llm/client.js +70 -21
  16. package/dist/llm/key-validator.d.ts.map +1 -1
  17. package/dist/llm/key-validator.js +0 -27
  18. package/dist/llm/providers/inference-snaps.d.ts +7 -5
  19. package/dist/llm/providers/inference-snaps.d.ts.map +1 -1
  20. package/dist/llm/providers/inference-snaps.js +7 -5
  21. package/dist/llm/providers/openai-compat.d.ts +1 -1
  22. package/dist/llm/providers/openai-compat.js +1 -1
  23. package/dist/llm/response-cache.d.ts +1 -2
  24. package/dist/llm/response-cache.d.ts.map +1 -1
  25. package/dist/llm/response-cache.js +1 -2
  26. package/dist/llm/server.d.ts +1 -1
  27. package/dist/llm/server.d.ts.map +1 -1
  28. package/dist/llm/server.js +3 -1
  29. package/dist/memory/services/index.d.ts +2 -0
  30. package/dist/memory/services/index.d.ts.map +1 -1
  31. package/dist/memory/services/index.js +1 -0
  32. package/dist/memory/services/reconciliation-service.d.ts +64 -0
  33. package/dist/memory/services/reconciliation-service.d.ts.map +1 -0
  34. package/dist/memory/services/reconciliation-service.js +127 -0
  35. package/dist/memory/utils/sql-helpers.d.ts +19 -25
  36. package/dist/memory/utils/sql-helpers.d.ts.map +1 -1
  37. package/dist/memory/utils/sql-helpers.js +34 -81
  38. package/dist/memory/vector/vector-memory-service.d.ts.map +1 -1
  39. package/dist/memory/vector/vector-memory-service.js +6 -1
  40. package/dist/orchestration/runtime.d.ts +30 -1
  41. package/dist/orchestration/runtime.d.ts.map +1 -1
  42. package/dist/orchestration/runtime.js +20 -3
  43. package/dist/orchestration/streaming-runtime.d.ts +48 -1
  44. package/dist/orchestration/streaming-runtime.d.ts.map +1 -1
  45. package/dist/orchestration/ticket-agent.d.ts +10 -1
  46. package/dist/orchestration/ticket-agent.d.ts.map +1 -1
  47. package/dist/orchestration/ticket-agent.js +11 -2
  48. package/dist/tools/mcp-adapter.d.ts +192 -1
  49. package/dist/tools/mcp-adapter.d.ts.map +1 -1
  50. package/dist/tools/mcp-adapter.js +434 -1
  51. package/dist/tools/mcp-elicitation.d.ts +128 -0
  52. package/dist/tools/mcp-elicitation.d.ts.map +1 -0
  53. package/dist/tools/mcp-elicitation.js +121 -0
  54. package/dist/tools/mcp-events.d.ts +270 -0
  55. package/dist/tools/mcp-events.d.ts.map +1 -0
  56. package/dist/tools/mcp-events.js +165 -0
  57. package/dist/tools/mcp-sampling.d.ts +155 -0
  58. package/dist/tools/mcp-sampling.d.ts.map +1 -0
  59. package/dist/tools/mcp-sampling.js +171 -0
  60. package/dist/tools/ticket-tools.d.ts +35 -2
  61. package/dist/tools/ticket-tools.d.ts.map +1 -1
  62. package/dist/tools/ticket-tools.js +32 -2
  63. package/package.json +13 -11
  64. package/dist/llm/providers/vultr.d.ts +0 -18
  65. package/dist/llm/providers/vultr.d.ts.map +0 -1
  66. package/dist/llm/providers/vultr.js +0 -169
  67. package/dist/memory/utils/deep-clone.d.ts +0 -10
  68. package/dist/memory/utils/deep-clone.d.ts.map +0 -1
  69. 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';
@@ -4,12 +4,13 @@
4
4
  * Single interface for all LLM providers with fallback and rate limiting
5
5
  */
6
6
  import type { Database } from '@revealui/db/client';
7
+ import { CircuitBreaker } from '@revealui/resilience';
7
8
  import type { AuditStore } from '../audit/store.js';
8
9
  import type { ProviderHealthMonitor } from './provider-health.js';
9
10
  import type { Embedding, LLMChatOptions, LLMChunk, LLMEmbedOptions, LLMProvider, LLMResponse, LLMStreamOptions, Message } from './providers/base.js';
10
11
  import { type CacheStats, type ResponseCacheOptions } from './response-cache.js';
11
12
  import { type SemanticCacheOptions, type SemanticCacheStats } from './semantic-cache.js';
12
- export type LLMProviderType = 'vultr' | 'groq' | 'ollama' | 'huggingface' | 'inference-snaps';
13
+ export type LLMProviderType = 'groq' | 'ollama' | 'huggingface' | 'inference-snaps';
13
14
  export interface LLMClientConfig {
14
15
  provider: LLMProviderType;
15
16
  apiKey: string;
@@ -46,6 +47,10 @@ export interface LLMClientConfig {
46
47
  semanticCacheOptions?: SemanticCacheOptions;
47
48
  /** Optional health monitor - records latency + error rate per provider */
48
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;
49
54
  }
50
55
  export declare class LLMClient {
51
56
  private provider;
@@ -56,6 +61,8 @@ export declare class LLMClient {
56
61
  private responseCache?;
57
62
  private semanticCache?;
58
63
  private healthMonitor?;
64
+ private circuitBreaker;
65
+ private fallbackCircuitBreaker?;
59
66
  /** Tracks the last resolved API key so we only recreate the provider when it changes */
60
67
  private currentApiKey;
61
68
  constructor(config: LLMClientConfig);
@@ -78,6 +85,21 @@ export declare class LLMClient {
78
85
  tokens: number;
79
86
  estimatedCostUsd: number;
80
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
+ };
81
103
  /**
82
104
  * Get the provider health monitor if one was configured.
83
105
  */
@@ -107,13 +129,20 @@ export declare class LLMClient {
107
129
  * Create an LLM client from environment variables.
108
130
  *
109
131
  * When LLM_PROVIDER is not set, auto-detects the provider by checking env vars
110
- * 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.
111
135
  *
112
136
  * All providers use OpenAI-compatible APIs. No proprietary provider SDKs.
113
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
+ *
114
142
  * Provider defaults:
115
- * groq qwen/qwen3-32b
116
- * 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)
117
146
  */
118
147
  export declare function createLLMClientFromEnv(): LLMClient;
119
148
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/llm/client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAIpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,KAAK,EACV,SAAS,EACT,cAAc,EACd,QAAQ,EACR,eAAe,EACf,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,OAAO,EACR,MAAM,qBAAqB,CAAC;AAS7B,OAAO,EAAE,KAAK,UAAU,EAAiB,KAAK,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAChG,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACxB,MAAM,qBAAqB,CAAC;AAG7B,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,aAAa,GAAG,iBAAiB,CAAC;AAE9F,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,eAAe,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,aAAa,CAAC,EAAE,WAAW,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,eAAe,CAAC;IACnC,SAAS,CAAC,EAAE;QACV,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;KACzB,CAAC;IACF,oFAAoF;IACpF,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,wEAAwE;IACxE,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,6BAA6B;IAC7B,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C,iEAAiE;IACjE,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,6BAA6B;IAC7B,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C,4EAA4E;IAC5E,aAAa,CAAC,EAAE,qBAAqB,CAAC;CACvC;AAQD,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAc;IAC9B,OAAO,CAAC,gBAAgB,CAAC,CAAc;IACvC,OAAO,CAAC,qBAAqB,CAAC,CAAc;IAC5C,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,aAAa,CAAC,CAAgB;IACtC,OAAO,CAAC,aAAa,CAAC,CAAgB;IACtC,OAAO,CAAC,aAAa,CAAC,CAAwB;IAC9C,wFAAwF;IACxF,OAAO,CAAC,aAAa,CAAS;gBAElB,MAAM,EAAE,eAAe;IA8CnC,OAAO,CAAC,cAAc;IAuBtB;;;OAGG;YACW,uBAAuB;IAmBrC,OAAO,CAAC,cAAc;IAoCtB,OAAO,CAAC,aAAa;IAMf,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC;IAmHzE,KAAK,CACT,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EACvB,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,SAAS,GAAG,SAAS,EAAE,CAAC;IA2B5B,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,aAAa,CAAC,QAAQ,CAAC;IA0BvF;;;OAGG;IACH,eAAe,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAA;KAAE;IAIlF;;OAEG;IACH,gBAAgB,IAAI,qBAAqB,GAAG,SAAS;IAIrD;;;;OAIG;IACH,qBAAqB,IAAI,UAAU,GAAG,SAAS;IAI/C;;OAEG;IACH,kBAAkB,IAAI,IAAI;IAI1B;;;;OAIG;IACH,qBAAqB,IAAI,kBAAkB,GAAG,SAAS;IAIvD;;OAEG;IACH,kBAAkB,IAAI,IAAI;CAG3B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,IAAI,SAAS,CAoElD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,QAAQ,EACZ,UAAU,CAAC,EAAE,UAAU,GACtB,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAiD3B"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/llm/client.ts"],"names":[],"mappings":"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"}
@@ -5,11 +5,11 @@
5
5
  */
6
6
  import { decryptApiKey } from '@revealui/db/crypto';
7
7
  import { tenantProviderConfigs, userApiKeys } from '@revealui/db/schema';
8
+ import { CircuitBreaker, CircuitBreakerOpenError, } from '@revealui/resilience';
8
9
  import { and, eq } from 'drizzle-orm';
9
10
  import { GroqProvider } from './providers/groq.js';
10
11
  import { InferenceSnapsProvider, } from './providers/inference-snaps.js';
11
12
  import { OllamaProvider } from './providers/ollama.js';
12
- import { VultrProvider } from './providers/vultr.js';
13
13
  import { ResponseCache } from './response-cache.js';
14
14
  import { SemanticCache, } from './semantic-cache.js';
15
15
  import { estimateRequest as _estimateRequestTokens } from './token-counter.js';
@@ -22,6 +22,8 @@ export class LLMClient {
22
22
  responseCache;
23
23
  semanticCache;
24
24
  healthMonitor;
25
+ circuitBreaker;
26
+ fallbackCircuitBreaker;
25
27
  /** Tracks the last resolved API key so we only recreate the provider when it changes */
26
28
  currentApiKey;
27
29
  constructor(config) {
@@ -42,6 +44,17 @@ export class LLMClient {
42
44
  }
43
45
  // Wire health monitor if provided
44
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
+ }
45
58
  // Wire dedicated embed provider if supplied
46
59
  this.embedProviderOverride = config.embedProvider;
47
60
  // Create primary provider
@@ -65,8 +78,6 @@ export class LLMClient {
65
78
  }
66
79
  createProvider(type, config) {
67
80
  switch (type) {
68
- case 'vultr':
69
- return new VultrProvider(config);
70
81
  case 'groq':
71
82
  return new GroqProvider(config);
72
83
  case 'ollama':
@@ -185,7 +196,7 @@ export class LLMClient {
185
196
  const callStart = Date.now();
186
197
  try {
187
198
  this.recordRequest();
188
- const response = await this.provider.chat(messages, options);
199
+ const response = await this.circuitBreaker.execute(() => this.provider.chat(messages, options));
189
200
  this.healthMonitor?.recordCall(this.config.provider, Date.now() - callStart);
190
201
  // Store in semantic cache (if enabled)
191
202
  if (this.semanticCache) {
@@ -215,11 +226,14 @@ export class LLMClient {
215
226
  this.healthMonitor?.recordCall(this.config.provider, Date.now() - callStart, error instanceof Error ? error : new Error(String(error)));
216
227
  // Try fallback if available
217
228
  if (this.fallbackProvider && this.config.fallbackProvider) {
229
+ const fp = this.fallbackProvider;
218
230
  const fallbackStart = Date.now();
219
231
  try {
220
- 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);
221
235
  this.healthMonitor?.recordCall(this.config.fallbackProvider, Date.now() - fallbackStart);
222
- return fallbackResponse;
236
+ return fb;
223
237
  }
224
238
  catch (fallbackError) {
225
239
  this.healthMonitor?.recordCall(this.config.fallbackProvider, Date.now() - fallbackStart, fallbackError instanceof Error ? fallbackError : new Error(String(fallbackError)));
@@ -238,13 +252,16 @@ export class LLMClient {
238
252
  const embedProvider = this.embedProviderOverride ?? this.provider;
239
253
  try {
240
254
  this.recordRequest();
241
- return await embedProvider.embed(text, options);
255
+ return await this.circuitBreaker.execute(() => embedProvider.embed(text, options));
242
256
  }
243
257
  catch (error) {
244
258
  // Try fallback if available (only when using the primary provider path)
245
259
  if (!this.embedProviderOverride && this.fallbackProvider) {
260
+ const fp = this.fallbackProvider;
246
261
  try {
247
- 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);
248
265
  }
249
266
  catch {
250
267
  throw new Error(`Both primary and fallback providers failed: ${error instanceof Error ? error.message : String(error)}`);
@@ -260,6 +277,11 @@ export class LLMClient {
260
277
  throw new Error('Rate limit exceeded');
261
278
  }
262
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
+ }
263
285
  this.recordRequest();
264
286
  yield* this.provider.stream(messages, options);
265
287
  }
@@ -267,6 +289,9 @@ export class LLMClient {
267
289
  // Try fallback if available
268
290
  if (this.fallbackProvider) {
269
291
  try {
292
+ if (this.fallbackCircuitBreaker?.isOpen()) {
293
+ throw new CircuitBreakerOpenError(`llm-${this.config.fallbackProvider}`);
294
+ }
270
295
  yield* this.fallbackProvider.stream(messages, options);
271
296
  }
272
297
  catch {
@@ -285,6 +310,25 @@ export class LLMClient {
285
310
  estimateRequest(messages) {
286
311
  return _estimateRequestTokens(messages, this.config.model ?? '');
287
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
+ }
288
332
  /**
289
333
  * Get the provider health monitor if one was configured.
290
334
  */
@@ -324,13 +368,20 @@ export class LLMClient {
324
368
  * Create an LLM client from environment variables.
325
369
  *
326
370
  * When LLM_PROVIDER is not set, auto-detects the provider by checking env vars
327
- * 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.
328
374
  *
329
375
  * All providers use OpenAI-compatible APIs. No proprietary provider SDKs.
330
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
+ *
331
381
  * Provider defaults:
332
- * groq qwen/qwen3-32b
333
- * 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)
334
385
  */
335
386
  export function createLLMClientFromEnv() {
336
387
  // Auto-detect provider when LLM_PROVIDER is not explicitly set
@@ -348,18 +399,14 @@ export function createLLMClientFromEnv() {
348
399
  provider = 'ollama';
349
400
  }
350
401
  else {
351
- throw new Error('No LLM provider configured. Set one of: OLLAMA_BASE_URL (local Ollama), ' +
352
- 'INFERENCE_SNAPS_BASE_URL (local snap), GROQ_API_KEY (cloud). ' +
353
- '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';
354
405
  }
355
406
  let apiKey;
356
407
  let baseURL;
357
408
  let defaultModel;
358
- if (provider === 'vultr') {
359
- apiKey = process.env.VULTR_API_KEY;
360
- baseURL = process.env.VULTR_BASE_URL;
361
- }
362
- else if (provider === 'huggingface') {
409
+ if (provider === 'huggingface') {
363
410
  apiKey = process.env.HF_TOKEN;
364
411
  baseURL = process.env.HF_MODEL_URL;
365
412
  }
@@ -377,12 +424,14 @@ export function createLLMClientFromEnv() {
377
424
  }
378
425
  else if (provider === 'inference-snaps') {
379
426
  apiKey = 'inference-snaps'; // inference-snaps ignores the API key
380
- 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';
381
430
  defaultModel = 'gemma3';
382
431
  }
383
432
  if (!apiKey) {
384
433
  throw new Error(`API key not found for provider "${provider}". Set the corresponding env var ` +
385
- `(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).`);
386
435
  }
387
436
  return new LLMClient({
388
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';
@@ -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
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/memory/services/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,YAAY,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/memory/services/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,YAAY,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,YAAY,EACV,aAAa,EACb,gBAAgB,EAChB,oBAAoB,EACpB,eAAe,GAChB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,yBAAyB,EACzB,2BAA2B,EAC3B,kBAAkB,GACnB,MAAM,6BAA6B,CAAC"}
@@ -4,3 +4,4 @@
4
4
  * Business logic services for memory operations.
5
5
  */
6
6
  export { NodeIdService } from './node-id-service.js';
7
+ export { buildReconciliationPrompt, parseReconciliationResponse, reconcileHeuristic, } from './reconciliation-service.js';
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Reconciliation Service - Fact resolution for multi-agent memory.
3
+ *
4
+ * Reads shared facts from a coordination session, groups related facts,
5
+ * deduplicates, and resolves contradictions. Produces reconciled memories
6
+ * for Layer 3.
7
+ *
8
+ * Layer 3 of the multi-agent shared memory architecture.
9
+ *
10
+ * LICENSING BOUNDARY:
11
+ * - `reconcileHeuristic()` is the production path — no external API calls,
12
+ * safe for all tiers including free customers.
13
+ * - `buildReconciliationPrompt()` and `parseReconciliationResponse()` are
14
+ * reference implementations for internal/developer use only. They build
15
+ * a prompt string but DO NOT call any LLM API. If wired to an LLM provider,
16
+ * the caller is responsible for API pricing and usage compliance.
17
+ * - Customer-facing reconciliation MUST use the heuristic path or a
18
+ * self-hosted model (e.g. Ollama). Do not proxy third-party LLM APIs
19
+ * to end users without a commercial API agreement with the provider.
20
+ */
21
+ export interface SharedFactInput {
22
+ id: string;
23
+ agentId: string;
24
+ content: string;
25
+ factType: string;
26
+ confidence: number;
27
+ tags: string[];
28
+ sourceRef?: Record<string, unknown> | null;
29
+ }
30
+ export interface ReconciledMemory {
31
+ content: string;
32
+ type: string;
33
+ sourceFactIds: string[];
34
+ confidence: number;
35
+ }
36
+ export interface Contradiction {
37
+ factIds: string[];
38
+ description: string;
39
+ resolution: string;
40
+ }
41
+ export interface ReconciliationResult {
42
+ canonicalFacts: ReconciledMemory[];
43
+ contradictions: Contradiction[];
44
+ duplicates: string[][];
45
+ summary: string;
46
+ }
47
+ /**
48
+ * Build the reconciliation prompt for an LLM.
49
+ * The prompt asks the model to analyze facts from multiple agents and
50
+ * produce a structured reconciliation result.
51
+ */
52
+ export declare function buildReconciliationPrompt(facts: SharedFactInput[], scratchpadContent?: Record<string, unknown>): string;
53
+ /**
54
+ * Parse the LLM response into a structured reconciliation result.
55
+ * Maps 1-based fact indices back to actual fact IDs.
56
+ */
57
+ export declare function parseReconciliationResponse(response: string, facts: SharedFactInput[]): ReconciliationResult;
58
+ /**
59
+ * Simple heuristic reconciliation (no LLM required).
60
+ * Deduplicates by normalized content and groups by type.
61
+ * Use this as a fallback when no LLM provider is configured.
62
+ */
63
+ export declare function reconcileHeuristic(facts: SharedFactInput[]): ReconciliationResult;
64
+ //# sourceMappingURL=reconciliation-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconciliation-service.d.ts","sourceRoot":"","sources":["../../../src/memory/services/reconciliation-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC5C;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACnC,cAAc,EAAE,gBAAgB,EAAE,CAAC;IACnC,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,UAAU,EAAE,MAAM,EAAE,EAAE,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,eAAe,EAAE,EACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC1C,MAAM,CAuCR;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,eAAe,EAAE,GACvB,oBAAoB,CAsCtB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,oBAAoB,CAsCjF"}