From 2a18837fbad220821cc1190b96506635c6b4c968 Mon Sep 17 00:00:00 2001 From: RACHKANC Date: Thu, 16 Jul 2026 20:46:47 +0530 Subject: [PATCH] feat: implement OAuth 2.0 authentication and vector search support in CLI --- README.md | 21 +++++++++++++++++++++ src/cli.mjs | 28 ++++++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9e77d73..37e38d0 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,27 @@ node ./scripts/memory-backup.mjs restore --in backup.json --out restored.json These operations are also available programmatically through `backup-restore.mjs`. +## Vector Search & Embeddings OAuth + +Memact Memory supports retrieving memories using hybrid semantic search. To securely integrate with enterprise embedding providers (like Azure OpenAI) and restrict search access, Memory implements an OAuth 2.0 Client Credentials flow. + +### Inbound Authorization +When querying via the API or CLI, clients must provide a JWT containing either the `vector:search` or `vector:read` scope to access semantic capabilities. +```sh +node ./src/cli.mjs --query "startup execution" \ + --access-token "header.eyJzY29wZSI6InZlY3RvcjpzZWFyY2gifQ.sig" +``` + +### Outbound Authentication +You can configure Memory to acquire its own Bearer tokens dynamically to invoke external embedding models, eliminating the need to hardcode static API keys. +```sh +node ./src/cli.mjs --query "startup execution" \ + --oauth-client-id "client_123" \ + --oauth-client-secret "secret_456" \ + --oauth-endpoint "https://auth.enterprise.com/token" \ + --embedding-provider "azure" +``` + ## Development To install and run tests: diff --git a/src/cli.mjs b/src/cli.mjs index f3d4eb9..ffd7f17 100644 --- a/src/cli.mjs +++ b/src/cli.mjs @@ -1,6 +1,7 @@ #!/usr/bin/env node import { readFile } from "node:fs/promises"; import { buildMemoryStore, buildRagContext, formatMemoryReport, retrieveMemories } from "./engine.mjs"; +import { createEmbeddingService } from "./embeddings.mjs"; function argValue(name, fallback = "") { const index = process.argv.indexOf(name); @@ -19,6 +20,12 @@ const query = argValue("--query"); const format = argValue("--format", "report"); const graphLimit = Number(argValue("--limit", "24")) || 24; +const accessToken = argValue("--access-token"); +const oauthClientId = argValue("--oauth-client-id"); +const oauthClientSecret = argValue("--oauth-client-secret"); +const oauthEndpoint = argValue("--oauth-endpoint"); +const provider = argValue("--embedding-provider"); + if (!inferencePath && !schemaPath) { console.error("Usage: memact-memory --inference inference.json --schema schema.json [--memory memory.json] [--query thought] [--format report|json|graph|mermaid|dot]"); process.exit(1); @@ -155,8 +162,25 @@ function formatDot(memoryStore, limit = 24) { } if (query) { - const rag = buildRagContext(query, memoryStore); - const result = retrieveMemories(query, memoryStore); + const options = {}; + if (accessToken) { + options.accessToken = accessToken; + } + + if (oauthClientId && oauthClientSecret && oauthEndpoint) { + const service = createEmbeddingService({ + provider: provider || "openai", + oauth: { + clientId: oauthClientId, + clientSecret: oauthClientSecret, + tokenEndpoint: oauthEndpoint + } + }); + options.queryEmbedding = await service.getEmbedding(query); + } + + const rag = buildRagContext(query, memoryStore, options); + const result = retrieveMemories(query, memoryStore, options); if (format === "json") { console.log(JSON.stringify({ query, rag, memories: result }, null, 2)); } else {