@cachly-dev/mcp-server 0.9.16 → 0.9.18
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/.github/workflows/publish.yml +42 -0
- package/LICENSE +202 -0
- package/dist/__tests__/brain-flow.test.d.ts +12 -0
- package/dist/__tests__/brain-flow.test.js +504 -0
- package/dist/__tests__/brain-flow.test.js.map +1 -0
- package/dist/ckg.d.ts +22 -0
- package/dist/ckg.js +40 -0
- package/dist/ckg.js.map +1 -0
- package/dist/confidence.d.ts +19 -0
- package/dist/confidence.js +38 -0
- package/dist/confidence.js.map +1 -0
- package/dist/embeddings.d.ts +48 -0
- package/dist/embeddings.js +213 -0
- package/dist/embeddings.js.map +1 -0
- package/dist/handlers/brain.d.ts +21 -0
- package/dist/handlers/brain.js +1322 -0
- package/dist/handlers/brain.js.map +1 -0
- package/dist/index.d.ts +1 -62
- package/dist/index.js +61 -5070
- package/dist/index.js.map +1 -1
- package/dist/search.d.ts +101 -0
- package/dist/search.js +1818 -0
- package/dist/search.js.map +1 -0
- package/dist/tools.d.ts +1955 -0
- package/dist/tools.js +1632 -0
- package/dist/tools.js.map +1 -0
- package/glama.json +6 -0
- package/package.json +1 -1
- package/src/__tests__/brain-flow.test.ts +608 -0
- package/src/ckg.ts +53 -0
- package/src/confidence.ts +38 -0
- package/src/embeddings.ts +217 -0
- package/src/handlers/brain.ts +1506 -0
- package/src/index.ts +41 -5262
- package/src/search.ts +1781 -0
- package/src/tools.ts +1723 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
// ── Confidence Decay Config ───────────────────────────────────────────────────
|
|
3
|
+
export const CONFIDENCE_WARN_DAYS = Number(process.env.CACHLY_CONFIDENCE_WARN_DAYS ?? 5);
|
|
4
|
+
export const CONFIDENCE_STALE_DAYS = Number(process.env.CACHLY_CONFIDENCE_STALE_DAYS ?? 10);
|
|
5
|
+
export const CONFIDENCE_WARN_VALUE = 0.7;
|
|
6
|
+
export const CONFIDENCE_STALE_VALUE = 0.5;
|
|
7
|
+
/** Calculate current confidence for a lesson based on how long since last verified. */
|
|
8
|
+
export function calculateConfidence(lesson) {
|
|
9
|
+
const ref = lesson.verified_at ?? lesson.ts;
|
|
10
|
+
const ageMs = Date.now() - new Date(ref).getTime();
|
|
11
|
+
const ageDays = ageMs / 86400000;
|
|
12
|
+
if (ageDays >= CONFIDENCE_STALE_DAYS)
|
|
13
|
+
return CONFIDENCE_STALE_VALUE;
|
|
14
|
+
if (ageDays >= CONFIDENCE_WARN_DAYS)
|
|
15
|
+
return CONFIDENCE_WARN_VALUE;
|
|
16
|
+
return 1.0 - (ageDays / CONFIDENCE_WARN_DAYS) * (1.0 - CONFIDENCE_WARN_VALUE);
|
|
17
|
+
}
|
|
18
|
+
/** Render a confidence badge string. */
|
|
19
|
+
export function confidenceBadge(confidence, ageDays) {
|
|
20
|
+
if (confidence >= 0.9)
|
|
21
|
+
return '✅';
|
|
22
|
+
if (confidence >= 0.7)
|
|
23
|
+
return `⚠️ (${Math.round(ageDays)}d old, confidence ${(confidence * 100).toFixed(0)}% — verify before applying)`;
|
|
24
|
+
return `🔴 STALE (${Math.round(ageDays)}d old, confidence ${(confidence * 100).toFixed(0)}% — likely outdated!)`;
|
|
25
|
+
}
|
|
26
|
+
/** Category-specific required fields for structured lessons. */
|
|
27
|
+
export const STRUCTURED_TEMPLATES = {
|
|
28
|
+
'deploy': { required: ['commands'], hint: 'deploy:* needs commands[]' },
|
|
29
|
+
'bash': { required: ['commands'], hint: 'bash:* needs commands[]' },
|
|
30
|
+
'infra': { required: ['commands'], hint: 'infra:* needs commands[] + verified on real system' },
|
|
31
|
+
'pricing': { required: [], hint: 'pricing:* — add context with source (e.g. "Stripe Dashboard Apr 2026")' },
|
|
32
|
+
'stripe': { required: [], hint: 'stripe:* — add context with Stripe API version' },
|
|
33
|
+
};
|
|
34
|
+
/** Fast content hash for index invalidation (not cryptographic, just change detection) */
|
|
35
|
+
export function simpleHash(text) {
|
|
36
|
+
return createHash('md5').update(text).digest('hex').slice(0, 12);
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=confidence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confidence.js","sourceRoot":"","sources":["../src/confidence.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,iFAAiF;AACjF,MAAM,CAAC,MAAM,oBAAoB,GAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,2BAA2B,IAAK,CAAC,CAAC,CAAC;AAC3F,MAAM,CAAC,MAAM,qBAAqB,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,4BAA4B,IAAI,EAAE,CAAC,CAAC;AAC5F,MAAM,CAAC,MAAM,qBAAqB,GAAI,GAAG,CAAC;AAC1C,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,CAAC;AAE1C,uFAAuF;AACvF,MAAM,UAAU,mBAAmB,CAAC,MAAmE;IACrG,MAAM,GAAG,GAAG,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,EAAE,CAAC;IAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;IACnD,MAAM,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAC;IACjC,IAAI,OAAO,IAAI,qBAAqB;QAAE,OAAO,sBAAsB,CAAC;IACpE,IAAI,OAAO,IAAI,oBAAoB;QAAG,OAAO,qBAAqB,CAAC;IACnE,OAAO,GAAG,GAAG,CAAC,OAAO,GAAG,oBAAoB,CAAC,GAAG,CAAC,GAAG,GAAG,qBAAqB,CAAC,CAAC;AAChF,CAAC;AAED,wCAAwC;AACxC,MAAM,UAAU,eAAe,CAAC,UAAkB,EAAE,OAAe;IACjE,IAAI,UAAU,IAAI,GAAG;QAAE,OAAO,GAAG,CAAC;IAClC,IAAI,UAAU,IAAI,GAAG;QAAE,OAAO,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,qBAAqB,CAAC,UAAU,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,6BAA6B,CAAC;IACxI,OAAO,aAAa,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,qBAAqB,CAAC,UAAU,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,uBAAuB,CAAC;AACnH,CAAC;AAED,gEAAgE;AAChE,MAAM,CAAC,MAAM,oBAAoB,GAAyD;IACxF,QAAQ,EAAG,EAAE,QAAQ,EAAE,CAAC,UAAU,CAAC,EAAiB,IAAI,EAAE,2BAA2B,EAAE;IACvF,MAAM,EAAK,EAAE,QAAQ,EAAE,CAAC,UAAU,CAAC,EAAiB,IAAI,EAAE,yBAAyB,EAAE;IACrF,OAAO,EAAI,EAAE,QAAQ,EAAE,CAAC,UAAU,CAAC,EAAiB,IAAI,EAAE,oDAAoD,EAAE;IAChH,SAAS,EAAE,EAAE,QAAQ,EAAE,EAAE,EAA2B,IAAI,EAAE,wEAAwE,EAAE;IACpI,QAAQ,EAAG,EAAE,QAAQ,EAAE,EAAE,EAA2B,IAAI,EAAE,gDAAgD,EAAE;CAC7G,CAAC;AAEF,0FAA0F;AAC1F,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AACnE,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ┌──────────────────────────────────────────────────────────────────────┐
|
|
3
|
+
* │ EMBEDDING PROVIDER — pluggable, client-side first │
|
|
4
|
+
* │ │
|
|
5
|
+
* │ Auto-detects from env vars. To force a provider, set: │
|
|
6
|
+
* │ CACHLY_EMBED_PROVIDER=openai (+ OPENAI_API_KEY) │
|
|
7
|
+
* │ CACHLY_EMBED_PROVIDER=gemini (+ GEMINI_API_KEY) │
|
|
8
|
+
* │ CACHLY_EMBED_PROVIDER=mistral (+ MISTRAL_API_KEY) │
|
|
9
|
+
* │ CACHLY_EMBED_PROVIDER=cohere (+ COHERE_API_KEY) │
|
|
10
|
+
* │ CACHLY_EMBED_PROVIDER=ollama (+ OLLAMA_BASE_URL, local) │
|
|
11
|
+
* │ CACHLY_EMBED_PROVIDER=cachly (server-side fallback, no key) │
|
|
12
|
+
* │ │
|
|
13
|
+
* │ Priority: openai > gemini > mistral > cohere > ollama > cachly │
|
|
14
|
+
* │ Brain works WITHOUT embedding (keyword search + exact key lookup). │
|
|
15
|
+
* │ Embedding is an optional boost for semantic_search/index_project. │
|
|
16
|
+
* └──────────────────────────────────────────────────────────────────────┘
|
|
17
|
+
*
|
|
18
|
+
* Mutable config — call setEmbedJwt() when the JWT changes (device flow).
|
|
19
|
+
*/
|
|
20
|
+
export declare const embedConfig: {
|
|
21
|
+
apiUrl: string;
|
|
22
|
+
jwt: string;
|
|
23
|
+
model: string;
|
|
24
|
+
};
|
|
25
|
+
/** Call this when JWT is refreshed (e.g. after device flow). */
|
|
26
|
+
export declare function setEmbedJwt(jwt: string): void;
|
|
27
|
+
export declare const EMBED_PROVIDER: string;
|
|
28
|
+
/**
|
|
29
|
+
* Compute an embedding vector for `text` using the configured provider.
|
|
30
|
+
*
|
|
31
|
+
* Client-side (recommended — set one API key in your .env):
|
|
32
|
+
* openai – OPENAI_API_KEY · text-embedding-3-small
|
|
33
|
+
* gemini – GEMINI_API_KEY · text-embedding-004
|
|
34
|
+
* mistral – MISTRAL_API_KEY · mistral-embed
|
|
35
|
+
* cohere – COHERE_API_KEY · embed-english-v3.0
|
|
36
|
+
* ollama – OLLAMA_BASE_URL · nomic-embed-text (local, free)
|
|
37
|
+
*
|
|
38
|
+
* Server-side fallback (no key needed on client):
|
|
39
|
+
* cachly – POST /api/v1/embed (requires CACHLY_JWT)
|
|
40
|
+
*
|
|
41
|
+
* Note: Brain works fully WITHOUT embedding (keyword search + exact keys).
|
|
42
|
+
* Embedding is an OPTIONAL boost for semantic_search and index_project.
|
|
43
|
+
*/
|
|
44
|
+
export declare function computeEmbedding(text: string): Promise<number[]>;
|
|
45
|
+
/** Returns true if the configured embedding provider has its required key/URL set. */
|
|
46
|
+
export declare function hasEmbedProvider(): boolean;
|
|
47
|
+
/** Returns a human-readable description of the current embed provider/model for error messages. */
|
|
48
|
+
export declare function embedProviderHint(): string;
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ┌──────────────────────────────────────────────────────────────────────┐
|
|
3
|
+
* │ EMBEDDING PROVIDER — pluggable, client-side first │
|
|
4
|
+
* │ │
|
|
5
|
+
* │ Auto-detects from env vars. To force a provider, set: │
|
|
6
|
+
* │ CACHLY_EMBED_PROVIDER=openai (+ OPENAI_API_KEY) │
|
|
7
|
+
* │ CACHLY_EMBED_PROVIDER=gemini (+ GEMINI_API_KEY) │
|
|
8
|
+
* │ CACHLY_EMBED_PROVIDER=mistral (+ MISTRAL_API_KEY) │
|
|
9
|
+
* │ CACHLY_EMBED_PROVIDER=cohere (+ COHERE_API_KEY) │
|
|
10
|
+
* │ CACHLY_EMBED_PROVIDER=ollama (+ OLLAMA_BASE_URL, local) │
|
|
11
|
+
* │ CACHLY_EMBED_PROVIDER=cachly (server-side fallback, no key) │
|
|
12
|
+
* │ │
|
|
13
|
+
* │ Priority: openai > gemini > mistral > cohere > ollama > cachly │
|
|
14
|
+
* │ Brain works WITHOUT embedding (keyword search + exact key lookup). │
|
|
15
|
+
* │ Embedding is an optional boost for semantic_search/index_project. │
|
|
16
|
+
* └──────────────────────────────────────────────────────────────────────┘
|
|
17
|
+
*
|
|
18
|
+
* Mutable config — call setEmbedJwt() when the JWT changes (device flow).
|
|
19
|
+
*/
|
|
20
|
+
// ── Mutable config (synced with index.ts JWT on device-flow auth) ────────────
|
|
21
|
+
export const embedConfig = {
|
|
22
|
+
apiUrl: process.env.CACHLY_API_URL ?? 'https://api.cachly.dev',
|
|
23
|
+
jwt: process.env.CACHLY_JWT ?? '',
|
|
24
|
+
model: process.env.CACHLY_EMBED_MODEL ?? '',
|
|
25
|
+
};
|
|
26
|
+
/** Call this when JWT is refreshed (e.g. after device flow). */
|
|
27
|
+
export function setEmbedJwt(jwt) {
|
|
28
|
+
embedConfig.jwt = jwt;
|
|
29
|
+
}
|
|
30
|
+
// ── Provider auto-detection ───────────────────────────────────────────────────
|
|
31
|
+
function detectEmbedProvider() {
|
|
32
|
+
// Client-side keys first (direct, fast, no server roundtrip)
|
|
33
|
+
if (process.env.OPENAI_API_KEY)
|
|
34
|
+
return 'openai';
|
|
35
|
+
if (process.env.GEMINI_API_KEY)
|
|
36
|
+
return 'gemini';
|
|
37
|
+
if (process.env.MISTRAL_API_KEY)
|
|
38
|
+
return 'mistral';
|
|
39
|
+
if (process.env.COHERE_API_KEY)
|
|
40
|
+
return 'cohere';
|
|
41
|
+
if (process.env.OLLAMA_BASE_URL)
|
|
42
|
+
return 'ollama';
|
|
43
|
+
// Server-side fallback — no API key needed, but adds latency
|
|
44
|
+
if (process.env.CACHLY_JWT)
|
|
45
|
+
return 'cachly';
|
|
46
|
+
return 'none'; // no provider → embedding disabled, brain still works via exact keys
|
|
47
|
+
}
|
|
48
|
+
export const EMBED_PROVIDER = (process.env.CACHLY_EMBED_PROVIDER ?? detectEmbedProvider()).toLowerCase();
|
|
49
|
+
// ── Multi-provider embedding ─────────────────────────────────────────────────
|
|
50
|
+
/**
|
|
51
|
+
* Compute an embedding vector for `text` using the configured provider.
|
|
52
|
+
*
|
|
53
|
+
* Client-side (recommended — set one API key in your .env):
|
|
54
|
+
* openai – OPENAI_API_KEY · text-embedding-3-small
|
|
55
|
+
* gemini – GEMINI_API_KEY · text-embedding-004
|
|
56
|
+
* mistral – MISTRAL_API_KEY · mistral-embed
|
|
57
|
+
* cohere – COHERE_API_KEY · embed-english-v3.0
|
|
58
|
+
* ollama – OLLAMA_BASE_URL · nomic-embed-text (local, free)
|
|
59
|
+
*
|
|
60
|
+
* Server-side fallback (no key needed on client):
|
|
61
|
+
* cachly – POST /api/v1/embed (requires CACHLY_JWT)
|
|
62
|
+
*
|
|
63
|
+
* Note: Brain works fully WITHOUT embedding (keyword search + exact keys).
|
|
64
|
+
* Embedding is an OPTIONAL boost for semantic_search and index_project.
|
|
65
|
+
*/
|
|
66
|
+
export async function computeEmbedding(text) {
|
|
67
|
+
switch (EMBED_PROVIDER) {
|
|
68
|
+
case 'cachly': {
|
|
69
|
+
// Server-side embedding — the Cachly API computes the embedding
|
|
70
|
+
// using whatever provider is configured on the server. No client-side API key needed.
|
|
71
|
+
if (!embedConfig.jwt)
|
|
72
|
+
throw new Error('CACHLY_JWT not set.\n\n' +
|
|
73
|
+
'The "cachly" provider uses server-side embeddings via the Cachly API.\n' +
|
|
74
|
+
'Set CACHLY_JWT, or use another provider via CACHLY_EMBED_PROVIDER:\n' +
|
|
75
|
+
' openai → OPENAI_API_KEY\n' +
|
|
76
|
+
' gemini → GEMINI_API_KEY\n' +
|
|
77
|
+
' ollama → OLLAMA_BASE_URL (local, no key needed)');
|
|
78
|
+
const url = `${embedConfig.apiUrl}/api/v1/embed`;
|
|
79
|
+
const body = { text };
|
|
80
|
+
if (embedConfig.model)
|
|
81
|
+
body.model = embedConfig.model;
|
|
82
|
+
const res = await fetch(url, {
|
|
83
|
+
method: 'POST',
|
|
84
|
+
headers: {
|
|
85
|
+
'Content-Type': 'application/json',
|
|
86
|
+
'Authorization': `Bearer ${embedConfig.jwt}`,
|
|
87
|
+
},
|
|
88
|
+
body: JSON.stringify(body),
|
|
89
|
+
});
|
|
90
|
+
if (!res.ok) {
|
|
91
|
+
const errBody = await res.text();
|
|
92
|
+
throw new Error(`Cachly embed API error ${res.status}: ${errBody}`);
|
|
93
|
+
}
|
|
94
|
+
const json = (await res.json());
|
|
95
|
+
return json.embedding;
|
|
96
|
+
}
|
|
97
|
+
case 'mistral': {
|
|
98
|
+
const key = process.env.MISTRAL_API_KEY;
|
|
99
|
+
if (!key)
|
|
100
|
+
throw new Error('MISTRAL_API_KEY not set');
|
|
101
|
+
const model = embedConfig.model !== 'text-embedding-3-small' ? embedConfig.model : 'mistral-embed';
|
|
102
|
+
const res = await fetch('https://api.mistral.ai/v1/embeddings', {
|
|
103
|
+
method: 'POST',
|
|
104
|
+
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${key}` },
|
|
105
|
+
body: JSON.stringify({ model, input: [text] }),
|
|
106
|
+
});
|
|
107
|
+
if (!res.ok)
|
|
108
|
+
throw new Error(`Mistral embedding error: ${res.statusText}`);
|
|
109
|
+
const json = (await res.json());
|
|
110
|
+
if (!json.data?.[0]?.embedding)
|
|
111
|
+
throw new Error('Mistral returned empty embedding response');
|
|
112
|
+
return json.data[0].embedding;
|
|
113
|
+
}
|
|
114
|
+
case 'cohere': {
|
|
115
|
+
const key = process.env.COHERE_API_KEY;
|
|
116
|
+
if (!key)
|
|
117
|
+
throw new Error('COHERE_API_KEY not set');
|
|
118
|
+
const model = embedConfig.model !== 'text-embedding-3-small' ? embedConfig.model : 'embed-english-v3.0';
|
|
119
|
+
const res = await fetch('https://api.cohere.com/v2/embed', {
|
|
120
|
+
method: 'POST',
|
|
121
|
+
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${key}` },
|
|
122
|
+
body: JSON.stringify({ model, texts: [text], input_type: 'search_query', embedding_types: ['float'] }),
|
|
123
|
+
});
|
|
124
|
+
if (!res.ok)
|
|
125
|
+
throw new Error(`Cohere embedding error: ${res.statusText}`);
|
|
126
|
+
const json = (await res.json());
|
|
127
|
+
return json.embeddings.float[0];
|
|
128
|
+
}
|
|
129
|
+
case 'ollama': {
|
|
130
|
+
const base = process.env.OLLAMA_BASE_URL ?? 'http://localhost:11434';
|
|
131
|
+
const model = embedConfig.model !== 'text-embedding-3-small' ? embedConfig.model : 'nomic-embed-text';
|
|
132
|
+
const res = await fetch(`${base}/api/embeddings`, {
|
|
133
|
+
method: 'POST',
|
|
134
|
+
headers: { 'Content-Type': 'application/json' },
|
|
135
|
+
body: JSON.stringify({ model, prompt: text }),
|
|
136
|
+
});
|
|
137
|
+
if (!res.ok)
|
|
138
|
+
throw new Error(`Ollama embedding error: ${res.statusText}`);
|
|
139
|
+
const json = (await res.json());
|
|
140
|
+
return json.embedding;
|
|
141
|
+
}
|
|
142
|
+
case 'gemini': {
|
|
143
|
+
const key = process.env.GEMINI_API_KEY;
|
|
144
|
+
if (!key)
|
|
145
|
+
throw new Error('GEMINI_API_KEY not set');
|
|
146
|
+
const model = embedConfig.model !== 'text-embedding-3-small' ? embedConfig.model : 'text-embedding-004';
|
|
147
|
+
const res = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/${model}:embedContent?key=${key}`, {
|
|
148
|
+
method: 'POST',
|
|
149
|
+
headers: { 'Content-Type': 'application/json' },
|
|
150
|
+
body: JSON.stringify({ model: `models/${model}`, content: { parts: [{ text }] } }),
|
|
151
|
+
});
|
|
152
|
+
if (!res.ok)
|
|
153
|
+
throw new Error(`Gemini embedding error: ${res.statusText}`);
|
|
154
|
+
const json = (await res.json());
|
|
155
|
+
return json.embedding.values;
|
|
156
|
+
}
|
|
157
|
+
case 'openai': {
|
|
158
|
+
const key = process.env.OPENAI_API_KEY;
|
|
159
|
+
if (!key)
|
|
160
|
+
throw new Error('OPENAI_API_KEY not set.\n\n' +
|
|
161
|
+
'Set OPENAI_API_KEY in your .env, or switch provider:\n' +
|
|
162
|
+
' CACHLY_EMBED_PROVIDER=gemini (+ GEMINI_API_KEY)\n' +
|
|
163
|
+
' CACHLY_EMBED_PROVIDER=ollama (local, free)\n' +
|
|
164
|
+
' CACHLY_EMBED_PROVIDER=cachly (server-side, no key needed)');
|
|
165
|
+
const model = embedConfig.model || 'text-embedding-3-small';
|
|
166
|
+
const res = await fetch('https://api.openai.com/v1/embeddings', {
|
|
167
|
+
method: 'POST',
|
|
168
|
+
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${key}` },
|
|
169
|
+
body: JSON.stringify({ model, input: text }),
|
|
170
|
+
});
|
|
171
|
+
if (!res.ok)
|
|
172
|
+
throw new Error(`OpenAI embedding error: ${res.statusText}`);
|
|
173
|
+
const json = (await res.json());
|
|
174
|
+
if (!json.data?.[0]?.embedding)
|
|
175
|
+
throw new Error('OpenAI returned empty embedding response');
|
|
176
|
+
return json.data[0].embedding;
|
|
177
|
+
}
|
|
178
|
+
default: {
|
|
179
|
+
throw new Error(`Unknown CACHLY_EMBED_PROVIDER="${EMBED_PROVIDER}".\n` +
|
|
180
|
+
'Supported: cachly (default), openai, mistral, cohere, ollama, gemini');
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
/** Returns true if the configured embedding provider has its required key/URL set. */
|
|
185
|
+
export function hasEmbedProvider() {
|
|
186
|
+
switch (EMBED_PROVIDER) {
|
|
187
|
+
case 'cachly': return !!embedConfig.jwt;
|
|
188
|
+
case 'mistral': return !!process.env.MISTRAL_API_KEY;
|
|
189
|
+
case 'cohere': return !!process.env.COHERE_API_KEY;
|
|
190
|
+
case 'ollama': return true; // OLLAMA_BASE_URL is optional (defaults to localhost)
|
|
191
|
+
case 'gemini': return !!process.env.GEMINI_API_KEY;
|
|
192
|
+
case 'openai': return !!process.env.OPENAI_API_KEY;
|
|
193
|
+
case 'none': return false;
|
|
194
|
+
default: return false;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/** Returns a human-readable description of the current embed provider/model for error messages. */
|
|
198
|
+
export function embedProviderHint() {
|
|
199
|
+
const providerKeys = {
|
|
200
|
+
cachly: 'CACHLY_JWT (server-side, no extra key needed)',
|
|
201
|
+
openai: 'OPENAI_API_KEY',
|
|
202
|
+
mistral: 'MISTRAL_API_KEY',
|
|
203
|
+
cohere: 'COHERE_API_KEY',
|
|
204
|
+
ollama: 'OLLAMA_BASE_URL (optional, default: http://localhost:11434)',
|
|
205
|
+
gemini: 'GEMINI_API_KEY',
|
|
206
|
+
};
|
|
207
|
+
if (EMBED_PROVIDER === 'none') {
|
|
208
|
+
return 'No embedding provider configured. Set OPENAI_API_KEY, GEMINI_API_KEY, or another provider key in .env. Brain works without embedding.';
|
|
209
|
+
}
|
|
210
|
+
const key = providerKeys[EMBED_PROVIDER] ?? 'CACHLY_JWT';
|
|
211
|
+
return `CACHLY_EMBED_PROVIDER=${EMBED_PROVIDER} → requires ${key}`;
|
|
212
|
+
}
|
|
213
|
+
//# sourceMappingURL=embeddings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embeddings.js","sourceRoot":"","sources":["../src/embeddings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Redis } from 'ioredis';
|
|
2
|
+
export interface Instance {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
tier: string;
|
|
6
|
+
status: string;
|
|
7
|
+
region: string;
|
|
8
|
+
host?: string;
|
|
9
|
+
port?: number;
|
|
10
|
+
password?: string;
|
|
11
|
+
tls_enabled?: boolean;
|
|
12
|
+
vector_token?: string;
|
|
13
|
+
memory_mb: number;
|
|
14
|
+
encryption_at_rest: boolean;
|
|
15
|
+
created_at: string;
|
|
16
|
+
}
|
|
17
|
+
type GetConnection = (instanceId: string) => Promise<Redis>;
|
|
18
|
+
type ApiFetch = <T>(path: string, options?: RequestInit) => Promise<T>;
|
|
19
|
+
export declare const BRAIN_TOOL_NAMES: Set<string>;
|
|
20
|
+
export declare function handleBrainTool(name: string, args: Record<string, unknown>, getConnection: GetConnection, apiFetch: ApiFetch): Promise<string | null>;
|
|
21
|
+
export {};
|