diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f0226440..20842238 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: - name: Setup Bun uses: oven-sh/setup-bun@v2 with: - bun-version: 1.3.4 + bun-version: 1.3.6 - name: Install dependencies run: bun install --frozen-lockfile diff --git a/.github/workflows/publish-ai-sdk.yml b/.github/workflows/publish-ai-sdk.yml index 848c7a71..27817b20 100644 --- a/.github/workflows/publish-ai-sdk.yml +++ b/.github/workflows/publish-ai-sdk.yml @@ -31,9 +31,6 @@ jobs: - name: Setup Bun uses: oven-sh/setup-bun@v2 - - - name: Setup pnpm - uses: pnpm/action-setup@v4 - name: Install dependencies run: bun install diff --git a/.github/workflows/publish-memory-graph.yml b/.github/workflows/publish-memory-graph.yml index 295a45f6..66dcbf3c 100644 --- a/.github/workflows/publish-memory-graph.yml +++ b/.github/workflows/publish-memory-graph.yml @@ -31,9 +31,6 @@ jobs: - name: Setup Bun uses: oven-sh/setup-bun@v2 - - - name: Setup pnpm - uses: pnpm/action-setup@v4 - name: Install dependencies run: bun install diff --git a/.github/workflows/publish-tools.yml b/.github/workflows/publish-tools.yml index 9d745203..46a56329 100644 --- a/.github/workflows/publish-tools.yml +++ b/.github/workflows/publish-tools.yml @@ -31,9 +31,6 @@ jobs: - name: Setup Bun uses: oven-sh/setup-bun@v2 - - - name: Setup pnpm - uses: pnpm/action-setup@v4 - name: Install dependencies run: bun install diff --git a/apps/docs/integrations/ai-sdk.mdx b/apps/docs/integrations/ai-sdk.mdx index 72355d70..c1a74a44 100644 --- a/apps/docs/integrations/ai-sdk.mdx +++ b/apps/docs/integrations/ai-sdk.mdx @@ -127,6 +127,18 @@ const model = withSupermemory(openai("gpt-4"), { // Console output shows memory retrieval details ``` +### When Supermemory errors (optional: continue without memories) + +If the Supermemory API returns an error (or is unreachable), memory retrieval fails before the LLM runs. By default that error **propagates** (fails the call). + +To continue the LLM request **without** injected memories instead, opt in with `skipMemoryOnError: true`. Use `verbose: true` if you want console output when that happens. + +```typescript +const model = withSupermemory(openai("gpt-5"), "user-123", { + skipMemoryOnError: true +}) +``` + --- ## Memory Tools diff --git a/apps/mcp/src/server.ts b/apps/mcp/src/server.ts index d387fde9..682e75c1 100644 --- a/apps/mcp/src/server.ts +++ b/apps/mcp/src/server.ts @@ -24,9 +24,12 @@ type Props = { name?: string } +const CONTAINER_TAGS_TTL_MS = 5 * 60 * 1000 + export class SupermemoryMCP extends McpAgent { private clientInfo: { name: string; version?: string } | null = null private cachedContainerTags: string[] = [] + private containerTagsLastFetchedAt: number | null = null server = new McpServer({ name: "supermemory", @@ -168,8 +171,8 @@ export class SupermemoryMCP extends McpAgent { "supermemory://projects", {}, async () => { - const client = this.getClient() - const projects = await client.getProjects() + await this.ensureContainerTagsFresh() + const projects = this.cachedContainerTags return { contents: [ @@ -193,15 +196,19 @@ export class SupermemoryMCP extends McpAgent { refresh: z .boolean() .optional() - .default(true) - .describe("Refresh the list from the server (default: true)"), + .default(false) + .describe( + "Force refresh from the server (default: false; uses cache with TTL)", + ), }), }, // @ts-expect-error - zod type inference issue with MCP SDK async (args: { refresh?: boolean }) => { try { - if (args.refresh !== false) { + if (args.refresh === true) { await this.refreshContainerTags() + } else { + await this.ensureContainerTagsFresh() } const projects = this.cachedContainerTags @@ -566,6 +573,10 @@ export class SupermemoryMCP extends McpAgent { const result = await client.createMemory(content) + if (!this.cachedContainerTags.includes(result.containerTag)) { + await this.refreshContainerTags() + } + // Track memory added event posthog .memoryAdded({ @@ -758,10 +769,21 @@ export class SupermemoryMCP extends McpAgent { return this.ctx.id.name || "unknown" } + private async ensureContainerTagsFresh(): Promise { + const now = Date.now() + const needsRefresh = + this.containerTagsLastFetchedAt === null || + now - this.containerTagsLastFetchedAt > CONTAINER_TAGS_TTL_MS + if (needsRefresh) { + await this.refreshContainerTags() + } + } + private async refreshContainerTags(): Promise { try { const client = this.getClient() this.cachedContainerTags = await client.getProjects() + this.containerTagsLastFetchedAt = Date.now() } catch (error) { console.error("Failed to fetch container tags:", error) } diff --git a/apps/mcp/tsconfig.json b/apps/mcp/tsconfig.json index 576d1175..67ab2770 100644 --- a/apps/mcp/tsconfig.json +++ b/apps/mcp/tsconfig.json @@ -13,7 +13,9 @@ "resolveJsonModule": true, "outDir": "dist", "rootDir": "src", - "baseUrl": "." + "paths": { + "*": ["./*"] + } }, "include": ["src/**/*"], "exclude": ["node_modules"] diff --git a/apps/web/app/(app)/layout.tsx b/apps/web/app/(app)/layout.tsx index 4ad8e215..542c0a65 100644 --- a/apps/web/app/(app)/layout.tsx +++ b/apps/web/app/(app)/layout.tsx @@ -2,12 +2,14 @@ import { EnsureWorkspace } from "@/components/ensure-workspace" import { MobileBanner } from "@/components/mobile-banner" +import { NextAppResearchCta } from "@/components/next-app-research-cta" export default function AppLayout({ children }: { children: React.ReactNode }) { return ( <> {children} + ) } diff --git a/apps/web/app/layout.tsx b/apps/web/app/layout.tsx index dfc12a0c..94c238bb 100644 --- a/apps/web/app/layout.tsx +++ b/apps/web/app/layout.tsx @@ -11,6 +11,7 @@ import { Suspense } from "react" import { Toaster } from "@ui/components/sonner" import { NuqsAdapter } from "nuqs/adapters/next/app" import { ThemeProvider } from "@/lib/theme-provider" +import Script from "next/script" const font = Space_Grotesk({ subsets: ["latin"], @@ -69,6 +70,11 @@ export default function RootLayout({ +