Feat : Skills
This commit is contained in:
4
open-sse/handlers/embeddingProviders/_base.js
Normal file
4
open-sse/handlers/embeddingProviders/_base.js
Normal file
@@ -0,0 +1,4 @@
|
||||
// Shared embedding helpers
|
||||
export function bearerAuth(creds) {
|
||||
return { "Authorization": `Bearer ${creds.apiKey || creds.accessToken}` };
|
||||
}
|
||||
42
open-sse/handlers/embeddingProviders/gemini.js
Normal file
42
open-sse/handlers/embeddingProviders/gemini.js
Normal file
@@ -0,0 +1,42 @@
|
||||
// Google Gemini embeddings — embedContent / batchEmbedContents
|
||||
const BASE = "https://generativelanguage.googleapis.com/v1beta";
|
||||
|
||||
function modelPath(model) {
|
||||
return model.startsWith("models/") ? model : `models/${model}`;
|
||||
}
|
||||
|
||||
export default {
|
||||
buildUrl: (model, creds, { input } = {}) => {
|
||||
const apiKey = creds.apiKey || creds.accessToken;
|
||||
const path = modelPath(model);
|
||||
const op = Array.isArray(input) ? "batchEmbedContents" : "embedContent";
|
||||
return `${BASE}/${path}:${op}?key=${encodeURIComponent(apiKey)}`;
|
||||
},
|
||||
buildHeaders: () => ({ "Content-Type": "application/json" }),
|
||||
buildBody: (model, { input }) => {
|
||||
const m = modelPath(model);
|
||||
if (Array.isArray(input)) {
|
||||
return { requests: input.map((text) => ({ model: m, content: { parts: [{ text: String(text) }] } })) };
|
||||
}
|
||||
return { model: m, content: { parts: [{ text: String(input) }] } };
|
||||
},
|
||||
normalize: (responseBody, model) => {
|
||||
if (responseBody.object === "list" && Array.isArray(responseBody.data)) return responseBody;
|
||||
let items = [];
|
||||
if (Array.isArray(responseBody.embeddings)) {
|
||||
items = responseBody.embeddings.map((emb, idx) => ({
|
||||
object: "embedding",
|
||||
index: idx,
|
||||
embedding: emb.values || [],
|
||||
}));
|
||||
} else if (responseBody.embedding?.values) {
|
||||
items = [{ object: "embedding", index: 0, embedding: responseBody.embedding.values }];
|
||||
}
|
||||
return {
|
||||
object: "list",
|
||||
data: items,
|
||||
model,
|
||||
usage: { prompt_tokens: 0, total_tokens: 0 },
|
||||
};
|
||||
},
|
||||
};
|
||||
23
open-sse/handlers/embeddingProviders/index.js
Normal file
23
open-sse/handlers/embeddingProviders/index.js
Normal file
@@ -0,0 +1,23 @@
|
||||
// Embeddings provider adapter registry
|
||||
import createOpenAIEmbeddingAdapter from "./openai.js";
|
||||
import gemini from "./gemini.js";
|
||||
import openaiCompatNode from "./openaiCompatNode.js";
|
||||
|
||||
const OPENAI_COMPAT_PROVIDERS = [
|
||||
"openai", "openrouter", "mistral", "voyage-ai", "fireworks",
|
||||
"together", "nebius", "github", "nvidia", "jina-ai",
|
||||
];
|
||||
|
||||
const ADAPTERS = {
|
||||
...Object.fromEntries(OPENAI_COMPAT_PROVIDERS.map((id) => [id, createOpenAIEmbeddingAdapter(id)])),
|
||||
gemini,
|
||||
google_ai_studio: gemini,
|
||||
};
|
||||
|
||||
export function getEmbeddingAdapter(provider) {
|
||||
if (ADAPTERS[provider]) return ADAPTERS[provider];
|
||||
if (provider?.startsWith?.("openai-compatible-") || provider?.startsWith?.("custom-embedding-")) {
|
||||
return openaiCompatNode;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
39
open-sse/handlers/embeddingProviders/openai.js
Normal file
39
open-sse/handlers/embeddingProviders/openai.js
Normal file
@@ -0,0 +1,39 @@
|
||||
// OpenAI-compatible embeddings adapter (most providers)
|
||||
import { bearerAuth } from "./_base.js";
|
||||
|
||||
const ENDPOINTS = {
|
||||
openai: "https://api.openai.com/v1/embeddings",
|
||||
openrouter: "https://openrouter.ai/api/v1/embeddings",
|
||||
mistral: "https://api.mistral.ai/v1/embeddings",
|
||||
"voyage-ai": "https://api.voyageai.com/v1/embeddings",
|
||||
fireworks: "https://api.fireworks.ai/inference/v1/embeddings",
|
||||
together: "https://api.together.xyz/v1/embeddings",
|
||||
nebius: "https://api.tokenfactory.nebius.com/v1/embeddings",
|
||||
github: "https://models.github.ai/inference/embeddings",
|
||||
nvidia: "https://integrate.api.nvidia.com/v1/embeddings",
|
||||
"jina-ai": "https://api.jina.ai/v1/embeddings",
|
||||
};
|
||||
|
||||
export default function createOpenAIEmbeddingAdapter(providerId) {
|
||||
return {
|
||||
buildUrl: () => ENDPOINTS[providerId],
|
||||
buildHeaders: (creds) => {
|
||||
const headers = { "Content-Type": "application/json", ...bearerAuth(creds) };
|
||||
if (providerId === "openrouter") {
|
||||
headers["HTTP-Referer"] = "https://endpoint-proxy.local";
|
||||
headers["X-Title"] = "Endpoint Proxy";
|
||||
}
|
||||
return headers;
|
||||
},
|
||||
buildBody: (model, { input, encoding_format, dimensions }) => {
|
||||
const body = { model, input };
|
||||
if (encoding_format) body.encoding_format = encoding_format;
|
||||
if (dimensions != null && dimensions !== "") {
|
||||
const dim = Number(dimensions);
|
||||
if (Number.isFinite(dim) && dim > 0) body.dimensions = dim;
|
||||
}
|
||||
return body;
|
||||
},
|
||||
normalize: (responseBody) => responseBody,
|
||||
};
|
||||
}
|
||||
13
open-sse/handlers/embeddingProviders/openaiCompatNode.js
Normal file
13
open-sse/handlers/embeddingProviders/openaiCompatNode.js
Normal file
@@ -0,0 +1,13 @@
|
||||
// Custom node providers (openai-compatible-* / custom-embedding-*) — baseUrl from credentials
|
||||
import createOpenAIEmbeddingAdapter from "./openai.js";
|
||||
|
||||
const baseAdapter = createOpenAIEmbeddingAdapter("openai");
|
||||
|
||||
export default {
|
||||
...baseAdapter,
|
||||
buildUrl: (_model, creds) => {
|
||||
const rawBaseUrl = creds?.providerSpecificData?.baseUrl || "https://api.openai.com/v1";
|
||||
const baseUrl = rawBaseUrl.replace(/\/$/, "").replace(/\/embeddings$/, "");
|
||||
return `${baseUrl}/embeddings`;
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user