Feat : Skills

This commit is contained in:
decolua
2026-05-04 11:29:02 +07:00
parent f08fa5f78d
commit 9c6be62a54
52 changed files with 2666 additions and 1581 deletions

View File

@@ -0,0 +1,4 @@
// Shared embedding helpers
export function bearerAuth(creds) {
return { "Authorization": `Bearer ${creds.apiKey || creds.accessToken}` };
}

View 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 },
};
},
};

View 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;
}

View 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,
};
}

View 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`;
},
};