@open-mercato/search 0.6.6-develop.6309.1.983aeec27a → 0.6.6-develop.6314.1.c7b8291aa2
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.
|
@@ -19,7 +19,7 @@ const resolveCache = (container) => {
|
|
|
19
19
|
return null;
|
|
20
20
|
}
|
|
21
21
|
};
|
|
22
|
-
const ollamaBaseUrl = () => process.env.OLLAMA_BASE_URL
|
|
22
|
+
const ollamaBaseUrl = () => process.env.OLLAMA_BASE_URL?.trim() || "http://localhost:11434";
|
|
23
23
|
const keyPresence = (providerId) => {
|
|
24
24
|
const info = EMBEDDING_PROVIDERS[providerId];
|
|
25
25
|
const envKey = info?.envKeyRequired;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/search/lib/provider-probe.ts"],
|
|
4
|
-
"sourcesContent": ["import type { CacheStrategy } from '@open-mercato/cache'\nimport type { AppContainer } from '@open-mercato/shared/lib/di/container'\nimport type { EmbeddingProviderId } from '../../../vector'\nimport { EMBEDDING_PROVIDERS } from '../../../vector'\n\nconst CACHE_VERSION = 'v1'\nconst CACHE_TTL_MS = 30_000\nconst OLLAMA_PROBE_TIMEOUT_MS = 1500\n\nexport type ProviderAvailability = {\n available: boolean\n reason?: string\n models?: number\n}\n\nexport type ProviderAvailabilityEntry = ProviderAvailability & {\n providerId: EmbeddingProviderId\n}\n\nexport type EmbeddingProviderProbe = {\n checkAvailability(providerId: EmbeddingProviderId, options?: { force?: boolean }): Promise<ProviderAvailability>\n}\n\nconst ALL_PROVIDERS: EmbeddingProviderId[] = ['openai', 'google', 'mistral', 'cohere', 'bedrock', 'ollama']\n\nexport async function checkAllProviders(\n probe: EmbeddingProviderProbe,\n options?: { force?: boolean },\n): Promise<ProviderAvailabilityEntry[]> {\n return Promise.all(\n ALL_PROVIDERS.map(async (providerId) => ({\n providerId,\n ...(await probe.checkAvailability(providerId, options)),\n })),\n )\n}\n\nconst cacheKey = (providerId: string) => `embedding-provider-probe:${CACHE_VERSION}:${providerId}`\n\nconst resolveCache = (container: AppContainer): CacheStrategy | null => {\n try {\n return container.resolve('cache') as CacheStrategy\n } catch {\n return null\n }\n}\n\nconst ollamaBaseUrl = () => process.env.OLLAMA_BASE_URL
|
|
5
|
-
"mappings": "AAGA,SAAS,2BAA2B;AAEpC,MAAM,gBAAgB;AACtB,MAAM,eAAe;AACrB,MAAM,0BAA0B;AAgBhC,MAAM,gBAAuC,CAAC,UAAU,UAAU,WAAW,UAAU,WAAW,QAAQ;AAE1G,eAAsB,kBACpB,OACA,SACsC;AACtC,SAAO,QAAQ;AAAA,IACb,cAAc,IAAI,OAAO,gBAAgB;AAAA,MACvC;AAAA,MACA,GAAI,MAAM,MAAM,kBAAkB,YAAY,OAAO;AAAA,IACvD,EAAE;AAAA,EACJ;AACF;AAEA,MAAM,WAAW,CAAC,eAAuB,4BAA4B,aAAa,IAAI,UAAU;AAEhG,MAAM,eAAe,CAAC,cAAkD;AACtE,MAAI;AACF,WAAO,UAAU,QAAQ,OAAO;AAAA,EAClC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,MAAM,gBAAgB,MAAM,QAAQ,IAAI,
|
|
4
|
+
"sourcesContent": ["import type { CacheStrategy } from '@open-mercato/cache'\nimport type { AppContainer } from '@open-mercato/shared/lib/di/container'\nimport type { EmbeddingProviderId } from '../../../vector'\nimport { EMBEDDING_PROVIDERS } from '../../../vector'\n\nconst CACHE_VERSION = 'v1'\nconst CACHE_TTL_MS = 30_000\nconst OLLAMA_PROBE_TIMEOUT_MS = 1500\n\nexport type ProviderAvailability = {\n available: boolean\n reason?: string\n models?: number\n}\n\nexport type ProviderAvailabilityEntry = ProviderAvailability & {\n providerId: EmbeddingProviderId\n}\n\nexport type EmbeddingProviderProbe = {\n checkAvailability(providerId: EmbeddingProviderId, options?: { force?: boolean }): Promise<ProviderAvailability>\n}\n\nconst ALL_PROVIDERS: EmbeddingProviderId[] = ['openai', 'google', 'mistral', 'cohere', 'bedrock', 'ollama']\n\nexport async function checkAllProviders(\n probe: EmbeddingProviderProbe,\n options?: { force?: boolean },\n): Promise<ProviderAvailabilityEntry[]> {\n return Promise.all(\n ALL_PROVIDERS.map(async (providerId) => ({\n providerId,\n ...(await probe.checkAvailability(providerId, options)),\n })),\n )\n}\n\nconst cacheKey = (providerId: string) => `embedding-provider-probe:${CACHE_VERSION}:${providerId}`\n\nconst resolveCache = (container: AppContainer): CacheStrategy | null => {\n try {\n return container.resolve('cache') as CacheStrategy\n } catch {\n return null\n }\n}\n\nconst ollamaBaseUrl = () => process.env.OLLAMA_BASE_URL?.trim() || 'http://localhost:11434'\n\nconst keyPresence = (providerId: EmbeddingProviderId): ProviderAvailability => {\n const info = EMBEDDING_PROVIDERS[providerId]\n const envKey = info?.envKeyRequired\n switch (providerId) {\n case 'openai':\n return process.env.OPENAI_API_KEY?.trim()\n ? { available: true }\n : { available: false, reason: `Set ${envKey} to enable ${info?.name ?? providerId}` }\n case 'google':\n return process.env.GOOGLE_GENERATIVE_AI_API_KEY?.trim()\n ? { available: true }\n : { available: false, reason: `Set ${envKey} to enable ${info?.name ?? providerId}` }\n case 'mistral':\n return process.env.MISTRAL_API_KEY?.trim()\n ? { available: true }\n : { available: false, reason: `Set ${envKey} to enable ${info?.name ?? providerId}` }\n case 'cohere':\n return process.env.COHERE_API_KEY?.trim()\n ? { available: true }\n : { available: false, reason: `Set ${envKey} to enable ${info?.name ?? providerId}` }\n case 'bedrock':\n return process.env.AWS_ACCESS_KEY_ID?.trim() && process.env.AWS_SECRET_ACCESS_KEY?.trim()\n ? { available: true }\n : { available: false, reason: 'Set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY to enable Bedrock' }\n default:\n return { available: false, reason: `Unknown provider: ${providerId}` }\n }\n}\n\nexport async function probeOllama(baseUrl: string): Promise<ProviderAvailability> {\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), OLLAMA_PROBE_TIMEOUT_MS)\n try {\n const response = await fetch(`${baseUrl.replace(/\\/$/, '')}/api/tags`, {\n method: 'GET',\n signal: controller.signal,\n })\n if (!response.ok) {\n return { available: false, reason: `Ollama responded ${response.status} at ${baseUrl}` }\n }\n let models: number | undefined\n try {\n const payload = (await response.json()) as { models?: unknown[] }\n if (Array.isArray(payload?.models)) models = payload.models.length\n } catch {}\n return { available: true, models }\n } catch (error) {\n const aborted = error instanceof Error && error.name === 'AbortError'\n return {\n available: false,\n reason: aborted ? `Ollama not reachable at ${baseUrl} (timed out)` : `Ollama not reachable at ${baseUrl}`,\n }\n } finally {\n clearTimeout(timer)\n }\n}\n\nasync function computeAvailability(providerId: EmbeddingProviderId): Promise<ProviderAvailability> {\n try {\n if (providerId === 'ollama') {\n return await probeOllama(ollamaBaseUrl())\n }\n return keyPresence(providerId)\n } catch (error) {\n // Fail closed: any unexpected error means the provider is treated as unavailable.\n return { available: false, reason: error instanceof Error ? error.message : 'Availability check failed' }\n }\n}\n\nexport function createEmbeddingProviderProbe(container: AppContainer): EmbeddingProviderProbe {\n const checkAvailability = async (\n providerId: EmbeddingProviderId,\n options?: { force?: boolean },\n ): Promise<ProviderAvailability> => {\n const cache = resolveCache(container)\n const key = cacheKey(providerId)\n if (!options?.force && cache) {\n try {\n const cached = await cache.get(key)\n if (cached && typeof cached === 'object' && 'available' in cached) {\n return cached as ProviderAvailability\n }\n } catch {}\n }\n const result = await computeAvailability(providerId)\n if (cache) {\n try {\n await cache.set(key, result, { ttl: CACHE_TTL_MS })\n } catch {}\n }\n return result\n }\n return { checkAvailability }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-mercato/search",
|
|
3
|
-
"version": "0.6.6-develop.
|
|
3
|
+
"version": "0.6.6-develop.6314.1.c7b8291aa2",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -127,9 +127,9 @@
|
|
|
127
127
|
"zod": "^4.4.3"
|
|
128
128
|
},
|
|
129
129
|
"peerDependencies": {
|
|
130
|
-
"@open-mercato/core": "0.6.6-develop.
|
|
131
|
-
"@open-mercato/queue": "0.6.6-develop.
|
|
132
|
-
"@open-mercato/shared": "0.6.6-develop.
|
|
130
|
+
"@open-mercato/core": "0.6.6-develop.6314.1.c7b8291aa2",
|
|
131
|
+
"@open-mercato/queue": "0.6.6-develop.6314.1.c7b8291aa2",
|
|
132
|
+
"@open-mercato/shared": "0.6.6-develop.6314.1.c7b8291aa2"
|
|
133
133
|
},
|
|
134
134
|
"devDependencies": {
|
|
135
135
|
"@types/jest": "^30.0.0",
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
jest.mock('../../../../vector', () => ({
|
|
2
|
+
EMBEDDING_PROVIDERS: {},
|
|
3
|
+
}))
|
|
4
|
+
|
|
5
|
+
import { createEmbeddingProviderProbe } from '../provider-probe'
|
|
6
|
+
import type { AppContainer } from '@open-mercato/shared/lib/di/container'
|
|
7
|
+
|
|
8
|
+
const ORIGINAL_ENV = { ...process.env }
|
|
9
|
+
const ORIGINAL_FETCH = global.fetch
|
|
10
|
+
|
|
11
|
+
function makeProbeContainer(): AppContainer {
|
|
12
|
+
return {
|
|
13
|
+
resolve: () => {
|
|
14
|
+
throw new Error('no cache in test')
|
|
15
|
+
},
|
|
16
|
+
} as unknown as AppContainer
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
describe('provider-probe — Ollama base URL fallback (issue #3511)', () => {
|
|
20
|
+
beforeEach(() => {
|
|
21
|
+
process.env = { ...ORIGINAL_ENV }
|
|
22
|
+
global.fetch = jest
|
|
23
|
+
.fn()
|
|
24
|
+
.mockRejectedValue(new Error('ECONNREFUSED')) as unknown as typeof fetch
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
afterEach(() => {
|
|
28
|
+
process.env = ORIGINAL_ENV
|
|
29
|
+
global.fetch = ORIGINAL_FETCH
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('falls back to the documented default URL when OLLAMA_BASE_URL is an empty string', async () => {
|
|
33
|
+
process.env.OLLAMA_BASE_URL = ''
|
|
34
|
+
const probe = createEmbeddingProviderProbe(makeProbeContainer())
|
|
35
|
+
const result = await probe.checkAvailability('ollama', { force: true })
|
|
36
|
+
expect(result.available).toBe(false)
|
|
37
|
+
expect(result.reason).toBe('Ollama not reachable at http://localhost:11434')
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it('falls back to the default URL when OLLAMA_BASE_URL is whitespace only', async () => {
|
|
41
|
+
process.env.OLLAMA_BASE_URL = ' '
|
|
42
|
+
const probe = createEmbeddingProviderProbe(makeProbeContainer())
|
|
43
|
+
const result = await probe.checkAvailability('ollama', { force: true })
|
|
44
|
+
expect(result.reason).toBe('Ollama not reachable at http://localhost:11434')
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
it('falls back to the default URL when OLLAMA_BASE_URL is unset', async () => {
|
|
48
|
+
delete process.env.OLLAMA_BASE_URL
|
|
49
|
+
const probe = createEmbeddingProviderProbe(makeProbeContainer())
|
|
50
|
+
const result = await probe.checkAvailability('ollama', { force: true })
|
|
51
|
+
expect(result.reason).toBe('Ollama not reachable at http://localhost:11434')
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
it('uses a configured OLLAMA_BASE_URL verbatim (trimmed)', async () => {
|
|
55
|
+
process.env.OLLAMA_BASE_URL = ' http://ollama.example.com:11434 '
|
|
56
|
+
const probe = createEmbeddingProviderProbe(makeProbeContainer())
|
|
57
|
+
const result = await probe.checkAvailability('ollama', { force: true })
|
|
58
|
+
expect(result.reason).toBe('Ollama not reachable at http://ollama.example.com:11434')
|
|
59
|
+
})
|
|
60
|
+
})
|
|
@@ -45,7 +45,7 @@ const resolveCache = (container: AppContainer): CacheStrategy | null => {
|
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
const ollamaBaseUrl = () => process.env.OLLAMA_BASE_URL
|
|
48
|
+
const ollamaBaseUrl = () => process.env.OLLAMA_BASE_URL?.trim() || 'http://localhost:11434'
|
|
49
49
|
|
|
50
50
|
const keyPresence = (providerId: EmbeddingProviderId): ProviderAvailability => {
|
|
51
51
|
const info = EMBEDDING_PROVIDERS[providerId]
|