feat(memory): add gemini embeddings + auto select providers

Co-authored-by: Gustavo Madeira Santana <gumadeiras@gmail.com>
This commit is contained in:
Peter Steinberger
2026-01-18 15:29:16 +00:00
parent 7252938339
commit be7191879a
11 changed files with 536 additions and 352 deletions

View File

@@ -381,19 +381,19 @@ const FIELD_HELP: Record<string, string> = {
"agents.defaults.memorySearch.remote.headers":
"Extra headers for remote embeddings (merged; remote overrides OpenAI headers).",
"agents.defaults.memorySearch.remote.batch.enabled":
"Enable OpenAI Batch API for memory embeddings (default: true).",
"Enable batch API for memory embeddings (OpenAI/Gemini; default: true).",
"agents.defaults.memorySearch.remote.batch.wait":
"Wait for OpenAI batch completion when indexing (default: true).",
"Wait for batch completion when indexing (default: true).",
"agents.defaults.memorySearch.remote.batch.concurrency":
"Max concurrent OpenAI batch jobs for memory indexing (default: 2).",
"Max concurrent embedding batch jobs for memory indexing (default: 2).",
"agents.defaults.memorySearch.remote.batch.pollIntervalMs":
"Polling interval in ms for OpenAI batch status (default: 2000).",
"Polling interval in ms for batch status (default: 2000).",
"agents.defaults.memorySearch.remote.batch.timeoutMinutes":
"Timeout in minutes for OpenAI batch indexing (default: 60).",
"Timeout in minutes for batch indexing (default: 60).",
"agents.defaults.memorySearch.local.modelPath":
"Local GGUF model path or hf: URI (node-llama-cpp).",
"agents.defaults.memorySearch.fallback":
'Fallback to OpenAI when local embeddings fail ("openai" or "none").',
'Fallback provider when embeddings fail ("openai", "gemini", "local", or "none").',
"agents.defaults.memorySearch.store.path":
"SQLite index path (default: ~/.clawdbot/memory/{agentId}.sqlite).",
"agents.defaults.memorySearch.store.vector.enabled":

View File

@@ -121,16 +121,30 @@ export type ToolPolicyConfig = {
};
export type ExecToolConfig = {
/** Exec host routing (default: sandbox). */
host?: "sandbox" | "gateway" | "node";
/** Exec security mode (default: deny). */
security?: "deny" | "allowlist" | "full";
/** Exec ask mode (default: on-miss). */
ask?: "off" | "on-miss" | "always";
/** Default node binding for exec.host=node (node id/name). */
node?: string;
/** Default time (ms) before an exec command auto-backgrounds. */
backgroundMs?: number;
/** Default timeout (seconds) before auto-killing exec commands. */
timeoutSec?: number;
/** How long to keep finished sessions in memory (ms). */
cleanupMs?: number;
/** Emit a system event and heartbeat when a backgrounded exec exits. */
notifyOnExit?: boolean;
/** apply_patch subtool configuration (experimental). */
applyPatch?: {
/** Enable apply_patch for OpenAI models (default: false). */
enabled?: boolean;
/**
* Optional allowlist of model ids that can use apply_patch.
* Accepts either raw ids (e.g. "gpt-5.2") or full ids (e.g. "openai/gpt-5.2").
*/
allowModels?: string[];
};
};
@@ -176,7 +190,7 @@ export type MemorySearchConfig = {
apiKey?: string;
headers?: Record<string, string>;
batch?: {
/** Enable OpenAI Batch API for embedding indexing (default: true). */
/** Enable batch API for embedding indexing (OpenAI/Gemini; default: true). */
enabled?: boolean;
/** Wait for batch completion (default: true). */
wait?: boolean;
@@ -188,8 +202,8 @@ export type MemorySearchConfig = {
timeoutMinutes?: number;
};
};
/** Fallback behavior when local embeddings fail. */
fallback?: "openai" | "none";
/** Fallback behavior when embeddings fail. */
fallback?: "openai" | "gemini" | "local" | "none";
/** Embedding model id (remote) or alias (local). */
model?: string;
/** Local embedding settings (node-llama-cpp). */

View File

@@ -183,24 +183,6 @@ export const AgentToolsSchema = z
allowFrom: ElevatedAllowFromSchema,
})
.optional(),
exec: z
.object({
host: z.enum(["sandbox", "gateway", "node"]).optional(),
security: z.enum(["deny", "allowlist", "full"]).optional(),
ask: z.enum(["off", "on-miss", "always"]).optional(),
node: z.string().optional(),
backgroundMs: z.number().int().positive().optional(),
timeoutSec: z.number().int().positive().optional(),
cleanupMs: z.number().int().positive().optional(),
notifyOnExit: z.boolean().optional(),
applyPatch: z
.object({
enabled: z.boolean().optional(),
allowModels: z.array(z.string()).optional(),
})
.optional(),
})
.optional(),
sandbox: z
.object({
tools: ToolPolicySchema,
@@ -218,7 +200,7 @@ export const MemorySearchSchema = z
sessionMemory: z.boolean().optional(),
})
.optional(),
provider: z.union([z.literal("openai"), z.literal("gemini"), z.literal("local")]).optional(),
provider: z.union([z.literal("openai"), z.literal("local"), z.literal("gemini")]).optional(),
remote: z
.object({
baseUrl: z.string().optional(),
@@ -235,7 +217,9 @@ export const MemorySearchSchema = z
.optional(),
})
.optional(),
fallback: z.union([z.literal("openai"), z.literal("none")]).optional(),
fallback: z
.union([z.literal("openai"), z.literal("gemini"), z.literal("local"), z.literal("none")])
.optional(),
model: z.string().optional(),
local: z
.object({