@revealui/ai 0.2.7 → 0.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +104 -17
- package/README.md +2 -2
- package/dist/a2a/card.d.ts +1 -1
- package/dist/a2a/card.d.ts.map +1 -1
- package/dist/a2a/card.js +4 -4
- package/dist/a2a/handler.d.ts +4 -4
- package/dist/a2a/handler.js +5 -5
- package/dist/a2a/index.d.ts +1 -1
- package/dist/a2a/index.js +1 -1
- package/dist/audit/emitter.d.ts +1 -1
- package/dist/audit/emitter.js +2 -2
- package/dist/audit/index.d.ts +2 -2
- package/dist/audit/index.js +2 -2
- package/dist/audit/store.d.ts +2 -2
- package/dist/audit/store.js +2 -2
- package/dist/client/errors.d.ts +13 -0
- package/dist/client/errors.d.ts.map +1 -0
- package/dist/client/errors.js +28 -0
- package/dist/client/hooks/useAgentContext.d.ts.map +1 -1
- package/dist/client/hooks/useAgentContext.js +6 -5
- package/dist/client/hooks/useAgentStream.d.ts +2 -2
- package/dist/client/hooks/useAgentStream.js +3 -3
- package/dist/client/hooks/useEpisodicMemory.d.ts.map +1 -1
- package/dist/client/hooks/useEpisodicMemory.js +6 -5
- package/dist/client/hooks/useWorkingMemory.d.ts.map +1 -1
- package/dist/client/hooks/useWorkingMemory.js +7 -6
- package/dist/embeddings/index.d.ts +1 -1
- package/dist/embeddings/index.js +4 -4
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -2
- package/dist/inference/context-budget.d.ts +1 -1
- package/dist/inference/context-budget.js +4 -4
- package/dist/inference/index.d.ts +1 -1
- package/dist/inference/index.js +1 -1
- package/dist/inference/runRag.d.ts +3 -3
- package/dist/inference/runRag.d.ts.map +1 -1
- package/dist/inference/runRag.js +1 -1
- package/dist/inference/task-decomposer.d.ts +1 -1
- package/dist/inference/task-decomposer.d.ts.map +1 -1
- package/dist/inference/task-decomposer.js +3 -3
- package/dist/inference/tool-result-compressor.d.ts +1 -1
- package/dist/inference/tool-result-compressor.js +1 -1
- package/dist/ingestion/{cms-indexer.d.ts → admin-indexer.d.ts} +12 -12
- package/dist/ingestion/admin-indexer.d.ts.map +1 -0
- package/dist/ingestion/{cms-indexer.js → admin-indexer.js} +9 -9
- package/dist/ingestion/bm25.d.ts +1 -1
- package/dist/ingestion/bm25.js +1 -1
- package/dist/ingestion/file-parsers.d.ts +1 -1
- package/dist/ingestion/file-parsers.d.ts.map +1 -1
- package/dist/ingestion/file-parsers.js +36 -17
- package/dist/ingestion/hybrid-search.d.ts +1 -1
- package/dist/ingestion/hybrid-search.js +1 -1
- package/dist/ingestion/index.d.ts +1 -1
- package/dist/ingestion/index.d.ts.map +1 -1
- package/dist/ingestion/index.js +1 -1
- package/dist/ingestion/rag-vector-service.d.ts +1 -1
- package/dist/ingestion/rag-vector-service.js +1 -1
- package/dist/ingestion/reranker.d.ts +1 -1
- package/dist/ingestion/reranker.js +1 -1
- package/dist/ingestion/text-splitter.d.ts +1 -1
- package/dist/ingestion/text-splitter.js +2 -2
- package/dist/llm/cache-utils.d.ts.map +1 -1
- package/dist/llm/cache-utils.js +1 -17
- package/dist/llm/client.d.ts +8 -13
- package/dist/llm/client.d.ts.map +1 -1
- package/dist/llm/client.js +12 -60
- package/dist/llm/key-validator.d.ts +1 -1
- package/dist/llm/key-validator.js +8 -8
- package/dist/llm/providers/base.d.ts +2 -2
- package/dist/llm/providers/groq.d.ts +2 -2
- package/dist/llm/providers/groq.d.ts.map +1 -1
- package/dist/llm/providers/groq.js +4 -4
- package/dist/llm/providers/inference-snaps.d.ts +5 -5
- package/dist/llm/providers/inference-snaps.d.ts.map +1 -1
- package/dist/llm/providers/inference-snaps.js +6 -6
- package/dist/llm/providers/ollama.d.ts +2 -2
- package/dist/llm/providers/ollama.d.ts.map +1 -1
- package/dist/llm/providers/ollama.js +3 -3
- package/dist/llm/providers/{openai.d.ts → openai-compat.d.ts} +8 -7
- package/dist/llm/providers/openai-compat.d.ts.map +1 -0
- package/dist/llm/providers/{openai.js → openai-compat.js} +13 -17
- package/dist/llm/providers/vultr.d.ts.map +1 -1
- package/dist/llm/providers/vultr.js +1 -0
- package/dist/llm/server.d.ts +1 -3
- package/dist/llm/server.d.ts.map +1 -1
- package/dist/llm/server.js +1 -3
- package/dist/llm/token-counter.d.ts.map +1 -1
- package/dist/llm/token-counter.js +11 -8
- package/dist/llm/workspace-provider-config.d.ts +1 -1
- package/dist/llm/workspace-provider-config.d.ts.map +1 -1
- package/dist/llm/workspace-provider-config.js +1 -1
- package/dist/memory/crdt/or-set.d.ts +12 -0
- package/dist/memory/crdt/or-set.d.ts.map +1 -1
- package/dist/memory/crdt/or-set.js +27 -0
- package/dist/memory/index.d.ts +1 -0
- package/dist/memory/index.d.ts.map +1 -1
- package/dist/memory/index.js +1 -0
- package/dist/memory/persistence/crdt-persistence.d.ts +21 -1
- package/dist/memory/persistence/crdt-persistence.d.ts.map +1 -1
- package/dist/memory/persistence/crdt-persistence.js +67 -0
- package/dist/memory/preferences/user-preferences-manager.d.ts.map +1 -1
- package/dist/memory/preferences/user-preferences-manager.js +11 -1
- package/dist/memory/stores/episodic-memory.js +2 -2
- package/dist/memory/stores/working-memory.d.ts +7 -2
- package/dist/memory/stores/working-memory.d.ts.map +1 -1
- package/dist/memory/stores/working-memory.js +31 -17
- package/dist/memory/sync/index.d.ts +2 -0
- package/dist/memory/sync/index.d.ts.map +1 -0
- package/dist/memory/sync/index.js +1 -0
- package/dist/memory/sync/sync-manager.d.ts +104 -0
- package/dist/memory/sync/sync-manager.d.ts.map +1 -0
- package/dist/memory/sync/sync-manager.js +137 -0
- package/dist/memory/utils/validation.js +1 -1
- package/dist/memory/vector/vector-memory-service.d.ts +1 -1
- package/dist/memory/vector/vector-memory-service.js +1 -1
- package/dist/orchestration/agent.d.ts +2 -2
- package/dist/orchestration/defaults.d.ts +1 -1
- package/dist/orchestration/defaults.js +1 -1
- package/dist/orchestration/orchestrator.d.ts +3 -3
- package/dist/orchestration/orchestrator.js +3 -3
- package/dist/orchestration/runtime.d.ts +1 -1
- package/dist/orchestration/runtime.js +1 -1
- package/dist/orchestration/streaming-runtime.d.ts +2 -2
- package/dist/orchestration/streaming-runtime.js +2 -2
- package/dist/orchestration/ticket-agent.d.ts +11 -11
- package/dist/orchestration/ticket-agent.d.ts.map +1 -1
- package/dist/orchestration/ticket-agent.js +10 -10
- package/dist/skills/catalog/vercel-catalog.d.ts.map +1 -1
- package/dist/skills/catalog/vercel-catalog.js +7 -4
- package/dist/skills/loader/github-loader.d.ts.map +1 -1
- package/dist/skills/loader/github-loader.js +2 -0
- package/dist/skills/loader/local-loader.js +1 -1
- package/dist/skills/loader/vercel-loader.d.ts.map +1 -1
- package/dist/skills/loader/vercel-loader.js +2 -0
- package/dist/skills/parser/skill-md-parser.js +2 -2
- package/dist/skills/registry/skill-registry.js +1 -1
- package/dist/skills/types.d.ts +6 -6
- package/dist/templates/prompt-spec.js +1 -1
- package/dist/templates/skill-spec.js +1 -1
- package/dist/tools/{cms → admin}/collection-tools.d.ts +2 -2
- package/dist/tools/admin/collection-tools.d.ts.map +1 -0
- package/dist/tools/{cms → admin}/collection-tools.js +8 -8
- package/dist/tools/{cms → admin}/factory.d.ts +11 -11
- package/dist/tools/admin/factory.d.ts.map +1 -0
- package/dist/tools/{cms → admin}/factory.js +4 -4
- package/dist/tools/{cms → admin}/global-tools.d.ts +1 -1
- package/dist/tools/admin/global-tools.d.ts.map +1 -0
- package/dist/tools/{cms → admin}/global-tools.js +4 -4
- package/dist/tools/{cms → admin}/index.d.ts +4 -4
- package/dist/tools/admin/index.d.ts.map +1 -0
- package/dist/tools/{cms → admin}/index.js +3 -3
- package/dist/tools/{cms → admin}/media-tools.d.ts +1 -1
- package/dist/tools/admin/media-tools.d.ts.map +1 -0
- package/dist/tools/{cms → admin}/media-tools.js +4 -4
- package/dist/tools/{cms → admin}/user-tools.d.ts +1 -1
- package/dist/tools/admin/user-tools.d.ts.map +1 -0
- package/dist/tools/{cms → admin}/user-tools.js +1 -1
- package/dist/tools/coding/file-edit.d.ts +1 -1
- package/dist/tools/coding/file-edit.js +2 -2
- package/dist/tools/coding/file-glob.d.ts +1 -1
- package/dist/tools/coding/file-glob.d.ts.map +1 -1
- package/dist/tools/coding/file-glob.js +2 -1
- package/dist/tools/coding/file-grep.d.ts +1 -1
- package/dist/tools/coding/file-grep.d.ts.map +1 -1
- package/dist/tools/coding/file-grep.js +2 -1
- package/dist/tools/coding/file-read.d.ts +1 -1
- package/dist/tools/coding/file-read.d.ts.map +1 -1
- package/dist/tools/coding/file-read.js +15 -9
- package/dist/tools/coding/file-write.d.ts +1 -1
- package/dist/tools/coding/file-write.js +1 -1
- package/dist/tools/coding/git-ops.d.ts +1 -1
- package/dist/tools/coding/git-ops.d.ts.map +1 -1
- package/dist/tools/coding/git-ops.js +5 -7
- package/dist/tools/coding/index.d.ts +1 -1
- package/dist/tools/coding/index.d.ts.map +1 -1
- package/dist/tools/coding/lint-fix.d.ts +1 -1
- package/dist/tools/coding/lint-fix.d.ts.map +1 -1
- package/dist/tools/coding/lint-fix.js +8 -4
- package/dist/tools/coding/project-context.d.ts +1 -1
- package/dist/tools/coding/project-context.d.ts.map +1 -1
- package/dist/tools/coding/project-context.js +25 -24
- package/dist/tools/coding/safety.d.ts +1 -1
- package/dist/tools/coding/safety.d.ts.map +1 -1
- package/dist/tools/coding/shell-exec.d.ts +1 -1
- package/dist/tools/coding/shell-exec.js +1 -1
- package/dist/tools/coding/test-runner.d.ts +1 -1
- package/dist/tools/coding/test-runner.d.ts.map +1 -1
- package/dist/tools/coding/test-runner.js +12 -7
- package/dist/tools/deduplicator.js +1 -1
- package/dist/tools/document-summarizer.js +2 -2
- package/dist/tools/memory/store-memory.d.ts +1 -1
- package/dist/tools/memory/store-memory.js +2 -2
- package/dist/tools/ticket-tools.d.ts +2 -2
- package/dist/tools/ticket-tools.js +3 -3
- package/dist/tools/web/duck-duck-go.d.ts +3 -3
- package/dist/tools/web/duck-duck-go.js +4 -4
- package/dist/tools/web/exa.d.ts +1 -1
- package/dist/tools/web/exa.js +1 -1
- package/dist/tools/web/scraper.js +1 -1
- package/dist/tools/web/tavily.d.ts +2 -2
- package/dist/tools/web/tavily.js +2 -2
- package/dist/tools/web/types.d.ts +2 -2
- package/dist/tools/web/types.js +2 -2
- package/package.json +23 -17
- package/LICENSE.commercial +0 -111
- package/dist/ingestion/cms-indexer.d.ts.map +0 -1
- package/dist/llm/providers/anthropic.d.ts +0 -31
- package/dist/llm/providers/anthropic.d.ts.map +0 -1
- package/dist/llm/providers/anthropic.js +0 -264
- package/dist/llm/providers/bitnet.d.ts +0 -28
- package/dist/llm/providers/bitnet.d.ts.map +0 -1
- package/dist/llm/providers/bitnet.js +0 -36
- package/dist/llm/providers/openai.d.ts.map +0 -1
- package/dist/tools/cms/collection-tools.d.ts.map +0 -1
- package/dist/tools/cms/factory.d.ts.map +0 -1
- package/dist/tools/cms/global-tools.d.ts.map +0 -1
- package/dist/tools/cms/index.d.ts.map +0 -1
- package/dist/tools/cms/media-tools.d.ts.map +0 -1
- package/dist/tools/cms/user-tools.d.ts.map +0 -1
package/dist/llm/cache-utils.js
CHANGED
|
@@ -1,20 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* Prompt Caching Utilities
|
|
3
|
-
*
|
|
4
|
-
* Helper functions for optimizing Anthropic prompt caching usage.
|
|
5
|
-
* Cache hits provide up to 90% cost reduction on input tokens.
|
|
6
|
-
*
|
|
7
|
-
* Cache TTL: 5 minutes
|
|
8
|
-
* Minimum cacheable content: ~1024 tokens (~300 words)
|
|
9
|
-
*
|
|
10
|
-
* Best practices:
|
|
11
|
-
* - Cache stable content that repeats across requests
|
|
12
|
-
* - Place cached content at message boundaries
|
|
13
|
-
* - Cache system prompts, tools, and large context documents
|
|
14
|
-
* - Order matters: place most stable content first
|
|
15
|
-
*
|
|
16
|
-
* @see https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching
|
|
17
|
-
*/
|
|
1
|
+
/* console-allowed */
|
|
18
2
|
/**
|
|
19
3
|
* Mark a message for caching
|
|
20
4
|
* Use this for system prompts, tool definitions, or large context that repeats
|
package/dist/llm/client.d.ts
CHANGED
|
@@ -15,12 +15,12 @@ import type { ProviderHealthMonitor } from './provider-health.js';
|
|
|
15
15
|
import type { Embedding, LLMChatOptions, LLMChunk, LLMEmbedOptions, LLMProvider, LLMResponse, LLMStreamOptions, Message } from './providers/base.js';
|
|
16
16
|
import { type CacheStats, type ResponseCacheOptions } from './response-cache.js';
|
|
17
17
|
import { type SemanticCacheOptions, type SemanticCacheStats } from './semantic-cache.js';
|
|
18
|
-
export type LLMProviderType = '
|
|
18
|
+
export type LLMProviderType = 'vultr' | 'groq' | 'ollama' | 'huggingface' | 'inference-snaps';
|
|
19
19
|
export interface LLMClientConfig {
|
|
20
20
|
provider: LLMProviderType;
|
|
21
21
|
apiKey: string;
|
|
22
22
|
/**
|
|
23
|
-
* Dynamic API key resolver
|
|
23
|
+
* Dynamic API key resolver - called before every LLM request.
|
|
24
24
|
* When set, the resolved key replaces `apiKey` on each call.
|
|
25
25
|
* Use this for OAuth tokens or any credential that expires between requests.
|
|
26
26
|
*/
|
|
@@ -30,10 +30,7 @@ export interface LLMClientConfig {
|
|
|
30
30
|
/**
|
|
31
31
|
* Dedicated embedding provider. When set, all embed() calls are routed here
|
|
32
32
|
* instead of the primary provider. Required when the primary provider does not
|
|
33
|
-
* support embeddings
|
|
34
|
-
*
|
|
35
|
-
* Auto-wired by createLLMClientFromEnv() when BITNET_BASE_URL + OLLAMA_BASE_URL
|
|
36
|
-
* are both set.
|
|
33
|
+
* support embeddings natively.
|
|
37
34
|
*/
|
|
38
35
|
embedProvider?: LLMProvider;
|
|
39
36
|
temperature?: number;
|
|
@@ -53,7 +50,7 @@ export interface LLMClientConfig {
|
|
|
53
50
|
enableSemanticCache?: boolean;
|
|
54
51
|
/** Semantic cache options */
|
|
55
52
|
semanticCacheOptions?: SemanticCacheOptions;
|
|
56
|
-
/** Optional health monitor
|
|
53
|
+
/** Optional health monitor - records latency + error rate per provider */
|
|
57
54
|
healthMonitor?: ProviderHealthMonitor;
|
|
58
55
|
}
|
|
59
56
|
export declare class LLMClient {
|
|
@@ -116,15 +113,13 @@ export declare class LLMClient {
|
|
|
116
113
|
* Create an LLM client from environment variables.
|
|
117
114
|
*
|
|
118
115
|
* When LLM_PROVIDER is not set, auto-detects the provider by checking env vars
|
|
119
|
-
* in priority order:
|
|
116
|
+
* in priority order: INFERENCE_SNAPS → GROQ → OLLAMA.
|
|
120
117
|
*
|
|
121
|
-
*
|
|
122
|
-
* OpenAI is not in the auto-detection chain (no revenue yet — see LLM provider policy).
|
|
123
|
-
* To use OpenAI, set LLM_PROVIDER=openai explicitly.
|
|
118
|
+
* All providers use OpenAI-compatible APIs. No proprietary provider SDKs.
|
|
124
119
|
*
|
|
125
120
|
* Provider defaults:
|
|
126
|
-
* groq →
|
|
127
|
-
* ollama →
|
|
121
|
+
* groq → qwen/qwen3-32b
|
|
122
|
+
* ollama → gemma4:e2b
|
|
128
123
|
*/
|
|
129
124
|
export declare function createLLMClientFromEnv(): LLMClient;
|
|
130
125
|
/**
|
package/dist/llm/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/llm/client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAoBH;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAY3F;AAID,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;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/llm/client.ts"],"names":[],"mappings":"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"}
|
package/dist/llm/client.js
CHANGED
|
@@ -42,12 +42,9 @@ export function redactSensitiveFields(obj) {
|
|
|
42
42
|
import { decryptApiKey } from '@revealui/db/crypto';
|
|
43
43
|
import { tenantProviderConfigs, userApiKeys } from '@revealui/db/schema';
|
|
44
44
|
import { and, eq } from 'drizzle-orm';
|
|
45
|
-
import { AnthropicProvider } from './providers/anthropic.js';
|
|
46
|
-
import { BitnetProvider } from './providers/bitnet.js';
|
|
47
45
|
import { GroqProvider } from './providers/groq.js';
|
|
48
46
|
import { InferenceSnapsProvider, } from './providers/inference-snaps.js';
|
|
49
47
|
import { OllamaProvider } from './providers/ollama.js';
|
|
50
|
-
import { OpenAIProvider } from './providers/openai.js';
|
|
51
48
|
import { VultrProvider } from './providers/vultr.js';
|
|
52
49
|
import { ResponseCache } from './response-cache.js';
|
|
53
50
|
import { SemanticCache, } from './semantic-cache.js';
|
|
@@ -81,7 +78,7 @@ export class LLMClient {
|
|
|
81
78
|
}
|
|
82
79
|
// Wire health monitor if provided
|
|
83
80
|
this.healthMonitor = config.healthMonitor;
|
|
84
|
-
// Wire dedicated embed provider if supplied
|
|
81
|
+
// Wire dedicated embed provider if supplied
|
|
85
82
|
this.embedProviderOverride = config.embedProvider;
|
|
86
83
|
// Create primary provider
|
|
87
84
|
this.provider = this.createProvider(config.provider, {
|
|
@@ -104,21 +101,12 @@ export class LLMClient {
|
|
|
104
101
|
}
|
|
105
102
|
createProvider(type, config) {
|
|
106
103
|
switch (type) {
|
|
107
|
-
case 'openai':
|
|
108
|
-
return new OpenAIProvider(config);
|
|
109
|
-
case 'anthropic':
|
|
110
|
-
return new AnthropicProvider({
|
|
111
|
-
...config,
|
|
112
|
-
enableCacheByDefault: this.config.enableCacheByDefault,
|
|
113
|
-
});
|
|
114
104
|
case 'vultr':
|
|
115
105
|
return new VultrProvider(config);
|
|
116
106
|
case 'groq':
|
|
117
107
|
return new GroqProvider(config);
|
|
118
108
|
case 'ollama':
|
|
119
109
|
return new OllamaProvider(config);
|
|
120
|
-
case 'bitnet':
|
|
121
|
-
return new BitnetProvider(config);
|
|
122
110
|
case 'inference-snaps':
|
|
123
111
|
return new InferenceSnapsProvider(config);
|
|
124
112
|
default:
|
|
@@ -282,7 +270,7 @@ export class LLMClient {
|
|
|
282
270
|
if (!this.checkRateLimit()) {
|
|
283
271
|
throw new Error('Rate limit exceeded');
|
|
284
272
|
}
|
|
285
|
-
// Use dedicated embed provider if one was configured
|
|
273
|
+
// Use dedicated embed provider if one was configured
|
|
286
274
|
const embedProvider = this.embedProviderOverride ?? this.provider;
|
|
287
275
|
try {
|
|
288
276
|
this.recordRequest();
|
|
@@ -372,15 +360,13 @@ export class LLMClient {
|
|
|
372
360
|
* Create an LLM client from environment variables.
|
|
373
361
|
*
|
|
374
362
|
* When LLM_PROVIDER is not set, auto-detects the provider by checking env vars
|
|
375
|
-
* in priority order:
|
|
363
|
+
* in priority order: INFERENCE_SNAPS → GROQ → OLLAMA.
|
|
376
364
|
*
|
|
377
|
-
*
|
|
378
|
-
* OpenAI is not in the auto-detection chain (no revenue yet — see LLM provider policy).
|
|
379
|
-
* To use OpenAI, set LLM_PROVIDER=openai explicitly.
|
|
365
|
+
* All providers use OpenAI-compatible APIs. No proprietary provider SDKs.
|
|
380
366
|
*
|
|
381
367
|
* Provider defaults:
|
|
382
|
-
* groq →
|
|
383
|
-
* ollama →
|
|
368
|
+
* groq → qwen/qwen3-32b
|
|
369
|
+
* ollama → gemma4:e2b
|
|
384
370
|
*/
|
|
385
371
|
export function createLLMClientFromEnv() {
|
|
386
372
|
// Auto-detect provider when LLM_PROVIDER is not explicitly set
|
|
@@ -391,38 +377,21 @@ export function createLLMClientFromEnv() {
|
|
|
391
377
|
else if (process.env.INFERENCE_SNAPS_BASE_URL) {
|
|
392
378
|
provider = 'inference-snaps';
|
|
393
379
|
}
|
|
394
|
-
else if (process.env.BITNET_BASE_URL) {
|
|
395
|
-
provider = 'bitnet';
|
|
396
|
-
}
|
|
397
380
|
else if (process.env.GROQ_API_KEY) {
|
|
398
381
|
provider = 'groq';
|
|
399
382
|
}
|
|
400
383
|
else if (process.env.OLLAMA_BASE_URL) {
|
|
401
384
|
provider = 'ollama';
|
|
402
385
|
}
|
|
403
|
-
else if (process.env.ANTHROPIC_API_KEY) {
|
|
404
|
-
provider = 'anthropic';
|
|
405
|
-
}
|
|
406
386
|
else {
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
throw new Error('No LLM provider configured. Set one of: BITNET_BASE_URL (local BitNet), ' +
|
|
410
|
-
'INFERENCE_SNAPS_BASE_URL (local snap), GROQ_API_KEY (recommended cloud), ' +
|
|
411
|
-
'OLLAMA_BASE_URL (local Ollama), or ANTHROPIC_API_KEY. ' +
|
|
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). ' +
|
|
412
389
|
'Alternatively, set LLM_PROVIDER explicitly.');
|
|
413
390
|
}
|
|
414
391
|
let apiKey;
|
|
415
392
|
let baseURL;
|
|
416
393
|
let defaultModel;
|
|
417
|
-
if (provider === '
|
|
418
|
-
apiKey = process.env.OPENAI_API_KEY;
|
|
419
|
-
baseURL = process.env.OPENAI_BASE_URL;
|
|
420
|
-
}
|
|
421
|
-
else if (provider === 'anthropic') {
|
|
422
|
-
apiKey = process.env.ANTHROPIC_API_KEY;
|
|
423
|
-
baseURL = process.env.ANTHROPIC_BASE_URL;
|
|
424
|
-
}
|
|
425
|
-
else if (provider === 'vultr') {
|
|
394
|
+
if (provider === 'vultr') {
|
|
426
395
|
apiKey = process.env.VULTR_API_KEY;
|
|
427
396
|
baseURL = process.env.VULTR_BASE_URL;
|
|
428
397
|
}
|
|
@@ -433,19 +402,14 @@ export function createLLMClientFromEnv() {
|
|
|
433
402
|
else if (provider === 'groq') {
|
|
434
403
|
apiKey = process.env.GROQ_API_KEY;
|
|
435
404
|
baseURL = process.env.GROQ_BASE_URL;
|
|
436
|
-
defaultModel = '
|
|
405
|
+
defaultModel = 'qwen/qwen3-32b';
|
|
437
406
|
}
|
|
438
407
|
else if (provider === 'ollama') {
|
|
439
408
|
apiKey = 'ollama'; // Ollama ignores the API key
|
|
440
409
|
// Ollama's OpenAI-compatible endpoint lives at /v1
|
|
441
410
|
const ollamaBase = process.env.OLLAMA_BASE_URL ?? 'http://localhost:11434';
|
|
442
411
|
baseURL = ollamaBase.endsWith('/v1') ? ollamaBase : `${ollamaBase}/v1`;
|
|
443
|
-
defaultModel = '
|
|
444
|
-
}
|
|
445
|
-
else if (provider === 'bitnet') {
|
|
446
|
-
apiKey = 'bitnet'; // llama-server ignores the API key
|
|
447
|
-
baseURL = process.env.BITNET_BASE_URL;
|
|
448
|
-
defaultModel = 'bitnet-b1.58-2B-4T';
|
|
412
|
+
defaultModel = 'gemma4:e2b';
|
|
449
413
|
}
|
|
450
414
|
else if (provider === 'inference-snaps') {
|
|
451
415
|
apiKey = 'inference-snaps'; // inference-snaps ignores the API key
|
|
@@ -454,18 +418,7 @@ export function createLLMClientFromEnv() {
|
|
|
454
418
|
}
|
|
455
419
|
if (!apiKey) {
|
|
456
420
|
throw new Error(`API key not found for provider "${provider}". Set the corresponding env var ` +
|
|
457
|
-
`(INFERENCE_SNAPS_BASE_URL, GROQ_API_KEY, OLLAMA_BASE_URL,
|
|
458
|
-
}
|
|
459
|
-
// When BitNet is the chat provider, auto-wire Ollama as the embed backend.
|
|
460
|
-
// BitNet does not support /v1/embeddings; Ollama (nomic-embed-text) fills that role.
|
|
461
|
-
// If OLLAMA_BASE_URL is not set, embed() will throw with a helpful message.
|
|
462
|
-
let embedProvider;
|
|
463
|
-
if (provider === 'bitnet' && process.env.OLLAMA_BASE_URL) {
|
|
464
|
-
embedProvider = new OllamaProvider({
|
|
465
|
-
apiKey: 'ollama',
|
|
466
|
-
baseURL: process.env.OLLAMA_BASE_URL,
|
|
467
|
-
embedModel: process.env.OLLAMA_EMBED_MODEL ?? 'nomic-embed-text',
|
|
468
|
-
});
|
|
421
|
+
`(INFERENCE_SNAPS_BASE_URL, GROQ_API_KEY, OLLAMA_BASE_URL, VULTR_API_KEY, or HF_TOKEN).`);
|
|
469
422
|
}
|
|
470
423
|
return new LLMClient({
|
|
471
424
|
provider,
|
|
@@ -479,7 +432,6 @@ export function createLLMClientFromEnv() {
|
|
|
479
432
|
process.env.RESPONSE_CACHE_ENABLED === 'true',
|
|
480
433
|
enableSemanticCache: process.env.LLM_ENABLE_SEMANTIC_CACHE === 'true' ||
|
|
481
434
|
process.env.SEMANTIC_CACHE_ENABLED === 'true',
|
|
482
|
-
embedProvider,
|
|
483
435
|
});
|
|
484
436
|
}
|
|
485
437
|
/**
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* BYOK Provider Key Validator
|
|
3
3
|
*
|
|
4
4
|
* Validates API keys against their provider before storage.
|
|
5
|
-
* Uses the cheapest available endpoint for each provider
|
|
5
|
+
* Uses the cheapest available endpoint for each provider - typically a
|
|
6
6
|
* models list (read-only, no token cost). Falls back gracefully when the
|
|
7
7
|
* provider is unreachable so that network failures don't block key storage.
|
|
8
8
|
*/
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* BYOK Provider Key Validator
|
|
3
3
|
*
|
|
4
4
|
* Validates API keys against their provider before storage.
|
|
5
|
-
* Uses the cheapest available endpoint for each provider
|
|
5
|
+
* Uses the cheapest available endpoint for each provider - typically a
|
|
6
6
|
* models list (read-only, no token cost). Falls back gracefully when the
|
|
7
7
|
* provider is unreachable so that network failures don't block key storage.
|
|
8
8
|
*/
|
|
@@ -38,7 +38,7 @@ export async function validateProviderKey(provider, apiKey) {
|
|
|
38
38
|
return { valid: true };
|
|
39
39
|
if (res.status === 401)
|
|
40
40
|
return { valid: false, error: 'Invalid Groq API key' };
|
|
41
|
-
// Any other non-OK status (429, 500 etc.)
|
|
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
44
|
case 'anthropic': {
|
|
@@ -50,7 +50,7 @@ export async function validateProviderKey(provider, apiKey) {
|
|
|
50
50
|
return { valid: true };
|
|
51
51
|
}
|
|
52
52
|
case 'openai': {
|
|
53
|
-
// Validate by format
|
|
53
|
+
// Validate by format - keys start with "sk-"
|
|
54
54
|
// (Per LLM policy, OpenAI API calls are blocked until we have revenue.)
|
|
55
55
|
if (!apiKey.startsWith('sk-')) {
|
|
56
56
|
return { valid: false, error: 'OpenAI API key must start with "sk-"' };
|
|
@@ -80,22 +80,22 @@ export async function validateProviderKey(provider, apiKey) {
|
|
|
80
80
|
return { valid: false, error: `Vultr validation failed: HTTP ${res.status}` };
|
|
81
81
|
}
|
|
82
82
|
case 'ollama': {
|
|
83
|
-
// Ollama is local
|
|
83
|
+
// Ollama is local - we cannot reliably probe it from the server.
|
|
84
84
|
// Accept the key as-is (Ollama doesn't use API keys anyway).
|
|
85
85
|
return { valid: true };
|
|
86
86
|
}
|
|
87
87
|
default:
|
|
88
|
-
// Unknown provider
|
|
88
|
+
// Unknown provider - skip validation
|
|
89
89
|
return { valid: true };
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
catch (err) {
|
|
93
|
-
// Network error (AbortError, DNS failure, etc.)
|
|
93
|
+
// Network error (AbortError, DNS failure, etc.) - don't block storage
|
|
94
94
|
if (err instanceof Error && err.name === 'AbortError') {
|
|
95
|
-
// Timeout
|
|
95
|
+
// Timeout - provider unreachable, proceed with storage
|
|
96
96
|
return { valid: true };
|
|
97
97
|
}
|
|
98
|
-
// Other network errors (ECONNREFUSED, etc.)
|
|
98
|
+
// Other network errors (ECONNREFUSED, etc.) - proceed with storage
|
|
99
99
|
return { valid: true };
|
|
100
100
|
}
|
|
101
101
|
}
|
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
* Abstract interface for all LLM providers (OpenAI, Anthropic, etc.)
|
|
5
5
|
*/
|
|
6
6
|
/**
|
|
7
|
-
* A plain text content part
|
|
7
|
+
* A plain text content part - used in multipart messages.
|
|
8
8
|
*/
|
|
9
9
|
export interface TextPart {
|
|
10
10
|
type: 'text';
|
|
11
11
|
text: string;
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
14
|
-
* An image content part
|
|
14
|
+
* An image content part - base64 data URL or HTTPS URL.
|
|
15
15
|
* Supported by OpenAI-compatible providers (inference-snaps, Ollama vision, GPT-4o).
|
|
16
16
|
*
|
|
17
17
|
* @example
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Groq Provider
|
|
3
3
|
*
|
|
4
4
|
* Thin wrapper over OpenAIProvider using Groq's OpenAI-compatible API.
|
|
5
|
-
* Free tier: 6,000 TPM / 500k TPD
|
|
5
|
+
* Free tier: 6,000 TPM / 500k TPD.
|
|
6
6
|
* Sign up: console.groq.com
|
|
7
7
|
*/
|
|
8
8
|
import type { Embedding, LLMChatOptions, LLMChunk, LLMEmbedOptions, LLMProvider, LLMProviderConfig, LLMResponse, LLMStreamOptions, Message } from './base.js';
|
|
@@ -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
|
|
13
|
+
/** Defaults to qwen/qwen3-32b */
|
|
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,EACR,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,
|
|
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,EACR,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,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"}
|
|
@@ -2,17 +2,17 @@
|
|
|
2
2
|
* Groq Provider
|
|
3
3
|
*
|
|
4
4
|
* Thin wrapper over OpenAIProvider using Groq's OpenAI-compatible API.
|
|
5
|
-
* Free tier: 6,000 TPM / 500k TPD
|
|
5
|
+
* Free tier: 6,000 TPM / 500k TPD.
|
|
6
6
|
* Sign up: console.groq.com
|
|
7
7
|
*/
|
|
8
|
-
import {
|
|
8
|
+
import { OpenAICompatProvider } from './openai-compat.js';
|
|
9
9
|
export class GroqProvider {
|
|
10
10
|
inner;
|
|
11
11
|
constructor(config) {
|
|
12
|
-
this.inner = new
|
|
12
|
+
this.inner = new OpenAICompatProvider({
|
|
13
13
|
...config,
|
|
14
14
|
baseURL: config.baseURL ?? 'https://api.groq.com/openai/v1',
|
|
15
|
-
model: config.model ?? '
|
|
15
|
+
model: config.model ?? 'qwen/qwen3-32b',
|
|
16
16
|
});
|
|
17
17
|
}
|
|
18
18
|
chat(messages, options) {
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
* No API key required. Zero cost, fully offline, hardware-optimized.
|
|
6
6
|
*
|
|
7
7
|
* Supported models (snaps):
|
|
8
|
-
* gemma3
|
|
9
|
-
* deepseek-r1
|
|
10
|
-
* qwen-vl
|
|
11
|
-
* nemotron-nano
|
|
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)
|
|
12
12
|
*
|
|
13
13
|
* Install a model:
|
|
14
14
|
* sudo snap install gemma3
|
|
@@ -27,7 +27,7 @@ export interface InferenceSnapsProviderConfig extends Omit<LLMProviderConfig, 'a
|
|
|
27
27
|
apiKey?: string;
|
|
28
28
|
/** Base URL of the inference-snaps service, e.g. http://localhost:9090/v1 */
|
|
29
29
|
baseURL: string;
|
|
30
|
-
/** Chat/vision model name
|
|
30
|
+
/** Chat/vision model name - must match the snap's model ID (e.g. 'gemma3', 'deepseek-r1') */
|
|
31
31
|
model?: string;
|
|
32
32
|
/** Embedding model name. Defaults to the chat model when omitted. */
|
|
33
33
|
embedModel?: string;
|
|
@@ -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
|
|
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"}
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
* No API key required. Zero cost, fully offline, hardware-optimized.
|
|
6
6
|
*
|
|
7
7
|
* Supported models (snaps):
|
|
8
|
-
* gemma3
|
|
9
|
-
* deepseek-r1
|
|
10
|
-
* qwen-vl
|
|
11
|
-
* nemotron-nano
|
|
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)
|
|
12
12
|
*
|
|
13
13
|
* Install a model:
|
|
14
14
|
* sudo snap install gemma3
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
*
|
|
23
23
|
* Docs: https://documentation.ubuntu.com/inference-snaps
|
|
24
24
|
*/
|
|
25
|
-
import {
|
|
25
|
+
import { OpenAICompatProvider } from './openai-compat.js';
|
|
26
26
|
export class InferenceSnapsProvider {
|
|
27
27
|
inner;
|
|
28
28
|
embedModel;
|
|
@@ -31,7 +31,7 @@ export class InferenceSnapsProvider {
|
|
|
31
31
|
this.baseURL = config.baseURL;
|
|
32
32
|
// Use the same model for embeddings unless explicitly overridden
|
|
33
33
|
this.embedModel = config.embedModel ?? config.model ?? 'gemma3';
|
|
34
|
-
this.inner = new
|
|
34
|
+
this.inner = new OpenAICompatProvider({
|
|
35
35
|
...config,
|
|
36
36
|
// inference-snaps ignores the API key; OpenAI client requires a non-empty value
|
|
37
37
|
apiKey: config.apiKey ?? 'inference-snaps',
|
|
@@ -10,9 +10,9 @@ export interface OllamaProviderConfig extends Omit<LLMProviderConfig, 'apiKey'>
|
|
|
10
10
|
apiKey?: string;
|
|
11
11
|
/** Defaults to http://localhost:11434/v1 */
|
|
12
12
|
baseURL?: string;
|
|
13
|
-
/** Chat model. Defaults to
|
|
13
|
+
/** Chat model. Defaults to gemma4:e2b - run `ollama pull gemma4:e2b` first */
|
|
14
14
|
model?: string;
|
|
15
|
-
/** Embedding model. Defaults to nomic-embed-text
|
|
15
|
+
/** Embedding model. Defaults to nomic-embed-text - run `ollama pull nomic-embed-text` first */
|
|
16
16
|
embedModel?: string;
|
|
17
17
|
}
|
|
18
18
|
export declare class OllamaProvider implements LLMProvider {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ollama.d.ts","sourceRoot":"","sources":["../../../src/llm/providers/ollama.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,EACR,MAAM,WAAW,CAAC;AAGnB,MAAM,WAAW,oBAAqB,SAAQ,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC;IAC7E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf
|
|
1
|
+
{"version":3,"file":"ollama.d.ts","sourceRoot":"","sources":["../../../src/llm/providers/ollama.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,EACR,MAAM,WAAW,CAAC;AAGnB,MAAM,WAAW,oBAAqB,SAAQ,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC;IAC7E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iGAAiG;IACjG,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,cAAe,YAAW,WAAW;IAChD,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,OAAO,CAAS;gBAEZ,MAAM,EAAE,oBAAoB;IAaxC,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"}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* No API key required. Zero cost, fully offline.
|
|
6
6
|
* Install: https://ollama.com
|
|
7
7
|
*/
|
|
8
|
-
import {
|
|
8
|
+
import { OpenAICompatProvider } from './openai-compat.js';
|
|
9
9
|
export class OllamaProvider {
|
|
10
10
|
inner;
|
|
11
11
|
embedModel;
|
|
@@ -14,12 +14,12 @@ export class OllamaProvider {
|
|
|
14
14
|
const baseURL = config.baseURL ?? 'http://localhost:11434/v1';
|
|
15
15
|
this.baseURL = baseURL;
|
|
16
16
|
this.embedModel = config.embedModel ?? 'nomic-embed-text';
|
|
17
|
-
this.inner = new
|
|
17
|
+
this.inner = new OpenAICompatProvider({
|
|
18
18
|
...config,
|
|
19
19
|
// Ollama ignores the API key but the OpenAI client requires a non-empty value
|
|
20
20
|
apiKey: config.apiKey ?? 'ollama',
|
|
21
21
|
baseURL,
|
|
22
|
-
model: config.model ?? '
|
|
22
|
+
model: config.model ?? 'gemma4:e2b',
|
|
23
23
|
});
|
|
24
24
|
}
|
|
25
25
|
chat(messages, options) {
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* OpenAI Provider
|
|
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.
|
|
6
|
+
* NOT for direct OpenAI usage - RevealUI uses open-source models only.
|
|
5
7
|
*/
|
|
6
8
|
import type { Embedding, LLMChatOptions, LLMChunk, LLMEmbedOptions, LLMProvider, LLMProviderConfig, LLMResponse, LLMStreamOptions, Message } from './base.js';
|
|
7
|
-
export interface
|
|
8
|
-
organization?: string;
|
|
9
|
+
export interface OpenAICompatConfig extends LLMProviderConfig {
|
|
9
10
|
}
|
|
10
|
-
export declare class
|
|
11
|
+
export declare class OpenAICompatProvider implements LLMProvider {
|
|
11
12
|
private config;
|
|
12
13
|
private baseURL;
|
|
13
|
-
constructor(config:
|
|
14
|
+
constructor(config: OpenAICompatConfig);
|
|
14
15
|
chat(messages: Message[], options?: LLMChatOptions): Promise<LLMResponse>;
|
|
15
16
|
embed(text: string | string[], options?: LLMEmbedOptions): Promise<Embedding | Embedding[]>;
|
|
16
17
|
stream(messages: Message[], options?: LLMStreamOptions): AsyncIterable<LLMChunk>;
|
|
17
18
|
private formatMessages;
|
|
18
19
|
}
|
|
19
|
-
//# sourceMappingURL=openai.d.ts.map
|
|
20
|
+
//# sourceMappingURL=openai-compat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai-compat.d.ts","sourceRoot":"","sources":["../../../src/llm/providers/openai-compat.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,SAAS,EAET,cAAc,EACd,QAAQ,EACR,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,gBAAgB,EAChB,OAAO,EAER,MAAM,WAAW,CAAC;AAEnB,MAAM,WAAW,kBAAmB,SAAQ,iBAAiB;CAAG;AAqDhE,qBAAa,oBAAqB,YAAW,WAAW;IACtD,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,OAAO,CAAS;gBAEZ,MAAM,EAAE,kBAAkB;IAUhC,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC;IA6EzE,KAAK,CACT,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EACvB,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,SAAS,GAAG,SAAS,EAAE,CAAC;IAyC5B,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,aAAa,CAAC,QAAQ,CAAC;IAuFvF,OAAO,CAAC,cAAc;CA4BvB"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* OpenAI Provider
|
|
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.
|
|
6
|
+
* NOT for direct OpenAI usage - RevealUI uses open-source models only.
|
|
5
7
|
*/
|
|
6
8
|
const authorizationHeader = 'Authorization';
|
|
7
|
-
const openAiOrganizationHeader = 'OpenAI-Organization';
|
|
8
9
|
const maxTokensKey = 'max_tokens';
|
|
9
10
|
const toolChoiceKey = 'tool_choice';
|
|
10
11
|
const toolCallsKey = 'tool_calls';
|
|
@@ -27,12 +28,15 @@ const isFunctionToolCall = (call) => {
|
|
|
27
28
|
const fn = asRecord(record.function);
|
|
28
29
|
return !!fn && typeof fn.name === 'string' && typeof fn.arguments === 'string';
|
|
29
30
|
};
|
|
30
|
-
export class
|
|
31
|
+
export class OpenAICompatProvider {
|
|
31
32
|
config;
|
|
32
33
|
baseURL;
|
|
33
34
|
constructor(config) {
|
|
34
35
|
this.config = config;
|
|
35
|
-
|
|
36
|
+
if (!config.baseURL) {
|
|
37
|
+
throw new Error('OpenAICompatProvider requires a baseURL - use a specific provider (InferenceSnapsProvider, OllamaProvider, etc.)');
|
|
38
|
+
}
|
|
39
|
+
this.baseURL = config.baseURL;
|
|
36
40
|
}
|
|
37
41
|
async chat(messages, options) {
|
|
38
42
|
const response = await fetch(`${this.baseURL}/chat/completions`, {
|
|
@@ -40,12 +44,9 @@ export class OpenAIProvider {
|
|
|
40
44
|
headers: {
|
|
41
45
|
'Content-Type': 'application/json',
|
|
42
46
|
[authorizationHeader]: `Bearer ${this.config.apiKey}`,
|
|
43
|
-
...(this.config.organization && {
|
|
44
|
-
[openAiOrganizationHeader]: this.config.organization,
|
|
45
|
-
}),
|
|
46
47
|
},
|
|
47
48
|
body: JSON.stringify({
|
|
48
|
-
model: this.config.model || '
|
|
49
|
+
model: this.config.model || 'default',
|
|
49
50
|
messages: this.formatMessages(messages),
|
|
50
51
|
temperature: options?.temperature ?? this.config.temperature ?? 0.7,
|
|
51
52
|
[maxTokensKey]: options?.maxTokens ?? this.config.maxTokens,
|
|
@@ -111,10 +112,8 @@ export class OpenAIProvider {
|
|
|
111
112
|
headers: {
|
|
112
113
|
'Content-Type': 'application/json',
|
|
113
114
|
[authorizationHeader]: `Bearer ${this.config.apiKey}`,
|
|
114
|
-
...(this.config.organization && {
|
|
115
|
-
[openAiOrganizationHeader]: this.config.organization,
|
|
116
|
-
}),
|
|
117
115
|
},
|
|
116
|
+
// lgtm[js/file-access-to-http] - embedding providers must send text to their API by design
|
|
118
117
|
body: JSON.stringify({
|
|
119
118
|
model,
|
|
120
119
|
input: texts,
|
|
@@ -146,12 +145,9 @@ export class OpenAIProvider {
|
|
|
146
145
|
headers: {
|
|
147
146
|
'Content-Type': 'application/json',
|
|
148
147
|
[authorizationHeader]: `Bearer ${this.config.apiKey}`,
|
|
149
|
-
...(this.config.organization && {
|
|
150
|
-
[openAiOrganizationHeader]: this.config.organization,
|
|
151
|
-
}),
|
|
152
148
|
},
|
|
153
149
|
body: JSON.stringify({
|
|
154
|
-
model: this.config.model || '
|
|
150
|
+
model: this.config.model || 'default',
|
|
155
151
|
messages: this.formatMessages(messages),
|
|
156
152
|
temperature: options?.temperature ?? this.config.temperature ?? 0.7,
|
|
157
153
|
[maxTokensKey]: options?.maxTokens ?? this.config.maxTokens,
|
|
@@ -224,7 +220,7 @@ export class OpenAIProvider {
|
|
|
224
220
|
return messages.map((msg) => {
|
|
225
221
|
const formatted = {
|
|
226
222
|
role: msg.role,
|
|
227
|
-
// Pass array content through as-is
|
|
223
|
+
// Pass array content through as-is - OpenAI-compatible APIs (including
|
|
228
224
|
// inference-snaps vision models) accept the same multipart format natively.
|
|
229
225
|
content: msg.content,
|
|
230
226
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vultr.d.ts","sourceRoot":"","sources":["../../../src/llm/providers/vultr.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,cAAc,EACd,QAAQ,EACR,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,gBAAgB,EAChB,OAAO,EAER,MAAM,WAAW,CAAC;AAEnB,MAAM,WAAW,mBAAoB,SAAQ,iBAAiB;IAC5D,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAgBD,qBAAa,aAAc,YAAW,WAAW;IAC/C,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,OAAO,CAAS;gBAEZ,MAAM,EAAE,mBAAmB;IAKjC,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC;IA2DzE,KAAK,CACT,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EACvB,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,SAAS,GAAG,SAAS,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"vultr.d.ts","sourceRoot":"","sources":["../../../src/llm/providers/vultr.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,cAAc,EACd,QAAQ,EACR,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,gBAAgB,EAChB,OAAO,EAER,MAAM,WAAW,CAAC;AAEnB,MAAM,WAAW,mBAAoB,SAAQ,iBAAiB;IAC5D,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAgBD,qBAAa,aAAc,YAAW,WAAW;IAC/C,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,OAAO,CAAS;gBAEZ,MAAM,EAAE,mBAAmB;IAKjC,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC;IA2DzE,KAAK,CACT,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EACvB,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,SAAS,GAAG,SAAS,EAAE,CAAC;IAwC5B,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,aAAa,CAAC,QAAQ,CAAC;CAkExF"}
|
|
@@ -81,6 +81,7 @@ export class VultrProvider {
|
|
|
81
81
|
[contentTypeHeader]: 'application/json',
|
|
82
82
|
[authorizationHeader]: `Bearer ${this.config.apiKey}`,
|
|
83
83
|
},
|
|
84
|
+
// lgtm[js/file-access-to-http] - embedding providers must send text to their API by design
|
|
84
85
|
body: JSON.stringify({ model, input: inputs }),
|
|
85
86
|
});
|
|
86
87
|
if (!res.ok) {
|