Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
28 changes: 26 additions & 2 deletions src/cli.mjs
Original file line number Diff line number Diff line change
@@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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 {
Expand Down