Skip to content
Draft
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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ anything else fails, they exit cleanly without breaking your Codex session.
| Variable | Purpose |
| ------------------------------ | ------------------------------------------------------ |
| `SUPERMEMORY_CODEX_API_KEY` | Your Supermemory API key (browser auth is preferred). |
| `SUPERMEMORY_API_URL` | Override the Supermemory API base URL (takes precedence over config). |
| `SUPERMEMORY_DEBUG` | Set to any truthy value to enable debug logging to `~/.codex-supermemory.log`. |

### `~/.codex/supermemory.json` (optional)
Expand All @@ -86,6 +87,7 @@ Drop this file in to override defaults:
| Key | Type | Default | Description |
| ------------------------ | ---------- | -------------- | -------------------------------------------------------------------------------------------- |
| `apiKey` | `string` | — | API key (env var takes precedence, browser auth is preferred). |
| `baseUrl` | `string` | `https://api.supermemory.ai` | Supermemory API base URL (`SUPERMEMORY_API_URL`/`SUPERMEMORY_BASE_URL` env vars take precedence). |
| `similarityThreshold` | `number` | `0.6` | Minimum similarity score for retrieved memories. |
| `maxMemories` | `number` | `5` | Max memories injected per prompt. |
| `maxProfileItems` | `number` | `5` | Max profile items considered. |
Expand Down
28 changes: 28 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { loadCredentials } from "./services/auth.js";

export const CONFIG_FILE = join(homedir(), ".codex", "supermemory.json");
export const PLUGIN_VERSION = "1.0.7";
export const DEFAULT_BASE_URL = "https://api.supermemory.ai";

export interface CustomContainer {
tag: string;
Expand All @@ -13,6 +14,7 @@ export interface CustomContainer {

interface CodexSupermemoryConfig {
apiKey?: string;
baseUrl?: string;
similarityThreshold?: number;
maxMemories?: number;
maxProfileItems?: number;
Expand Down Expand Up @@ -132,6 +134,32 @@ export function getApiKeyValue(): string | undefined {
return SUPERMEMORY_API_KEY;
}

function normalizeBaseUrl(baseUrl: unknown): string | null {
if (typeof baseUrl !== "string" || !baseUrl.trim()) return null;

const trimmed = baseUrl.trim();
try {
const url = new URL(trimmed);
if (url.protocol !== "http:" && url.protocol !== "https:") return null;
return trimmed;
} catch {
return null;
}
}

export function getBaseUrl(): string {
const configured =
process.env.SUPERMEMORY_API_URL ||
process.env.SUPERMEMORY_BASE_URL ||
fileConfig.baseUrl ||
DEFAULT_BASE_URL;
const normalized = normalizeBaseUrl(configured);
if (!normalized) {
throw new Error("Invalid baseUrl: expected an absolute http(s) URL");
}
return normalized;
}

export function getSignalConfig(): {
enabled: boolean;
keywords: string[];
Expand Down
12 changes: 5 additions & 7 deletions src/services/client.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
import Supermemory from "supermemory";
import { CONFIG, isConfigured, getApiKeyValue, PLUGIN_VERSION } from "../config.js";
import { CONFIG, isConfigured, getApiKeyValue, getBaseUrl, PLUGIN_VERSION } from "../config.js";
import { log } from "./logger.js";
import type { MemoryType } from "../types/index.js";

const TIMEOUT_MS = 30000;
const SPACE_NAME_TIMEOUT_MS = 5000;
const API_URL =
process.env.SUPERMEMORY_API_URL ||
process.env.SUPERMEMORY_BASE_URL ||
"https://api.supermemory.ai";
const CODEX_SOURCE = "codex";

function withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {
Expand Down Expand Up @@ -74,6 +70,7 @@ export class SupermemoryClient {
// writes to the Codex plugin in PostHog / `document.source`.
this.client = new Supermemory({
apiKey: getApiKeyValue(),
baseURL: getBaseUrl(),
defaultHeaders: { "x-sm-source": CODEX_SOURCE },
});
}
Expand Down Expand Up @@ -237,8 +234,9 @@ export class SupermemoryClient {
async updateContainerTagName(containerTag: string, name: string) {
log("updateContainerTagName: start", { containerTag, name });
try {
const baseUrl = getBaseUrl();
const currentResponse = await withTimeout(
fetch(`${API_URL}/v3/container-tags/${encodeURIComponent(containerTag)}`, {
fetch(`${baseUrl}/v3/container-tags/${encodeURIComponent(containerTag)}`, {
headers: {
Authorization: `Bearer ${getApiKeyValue()}`,
},
Expand Down Expand Up @@ -270,7 +268,7 @@ export class SupermemoryClient {
}

const response = await withTimeout(
fetch(`${API_URL}/v3/container-tags/${encodeURIComponent(containerTag)}`, {
fetch(`${baseUrl}/v3/container-tags/${encodeURIComponent(containerTag)}`, {
method: "PATCH",
headers: {
Authorization: `Bearer ${getApiKeyValue()}`,
Expand Down