From b73b4cb53ec3d971aeb0790602e3d189e765c516 Mon Sep 17 00:00:00 2001 From: rajashidattapy Date: Sun, 12 Jul 2026 12:58:08 +0530 Subject: [PATCH 1/2] =?UTF-8?q?refactor(ai-sdk)!:=20re-export=20@supermemo?= =?UTF-8?q?ry/tools/ai-sdk=20(#1247)=20=E2=80=94=20the=20!=20marks=20the?= =?UTF-8?q?=20breaking=20default-scope=20change.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/publish-ai-sdk.yml | 3 +- bun.lock | 9 +- packages/ai-sdk/README.md | 13 ++ packages/ai-sdk/package.json | 16 +-- packages/ai-sdk/src/index.ts | 13 +- packages/ai-sdk/src/tools.test.ts | 181 --------------------------- packages/ai-sdk/src/tools.ts | 150 ---------------------- packages/tools/package.json | 4 +- turbo.json | 2 +- 9 files changed, 39 insertions(+), 352 deletions(-) delete mode 100644 packages/ai-sdk/src/tools.test.ts delete mode 100644 packages/ai-sdk/src/tools.ts diff --git a/.github/workflows/publish-ai-sdk.yml b/.github/workflows/publish-ai-sdk.yml index 1ac60cf18..94800708c 100644 --- a/.github/workflows/publish-ai-sdk.yml +++ b/.github/workflows/publish-ai-sdk.yml @@ -56,7 +56,8 @@ jobs: - name: Build if: steps.version-check.outputs.changed == 'true' - run: bun run build + working-directory: . + run: bunx turbo run build --filter='@supermemory/ai-sdk' - name: Publish if: steps.version-check.outputs.changed == 'true' diff --git a/bun.lock b/bun.lock index c6f5c06e2..8c4e67bf1 100644 --- a/bun.lock +++ b/bun.lock @@ -242,19 +242,16 @@ }, "packages/ai-sdk": { "name": "@supermemory/ai-sdk", - "version": "1.0.8", + "version": "2.0.0", "dependencies": { - "@ai-sdk/openai": "^2.0.22", "@ai-sdk/provider": "^2.0.0", - "ai": "^5.0.113", - "supermemory": "^3.0.0-alpha.26", + "@supermemory/tools": "^2.1.0", }, "devDependencies": { "@total-typescript/tsconfig": "^1.0.4", "@types/bun": "^1.2.21", "tsdown": "^0.14.2", "typescript": "^5.9.2", - "vitest": "^3.2.4", }, }, "packages/docs-test": { @@ -320,7 +317,7 @@ }, "packages/tools": { "name": "@supermemory/tools", - "version": "2.0.0", + "version": "2.1.0", "dependencies": { "@ai-sdk/anthropic": "^2.0.25", "@ai-sdk/openai": "^2.0.23", diff --git a/packages/ai-sdk/README.md b/packages/ai-sdk/README.md index 0927cfdf5..0080a25f5 100644 --- a/packages/ai-sdk/README.md +++ b/packages/ai-sdk/README.md @@ -1,5 +1,18 @@ # supermemory AI SDK Utilities +> **Deprecated.** Use [`@supermemory/tools`](../tools) instead: +> +> ```ts +> import { supermemoryTools } from "@supermemory/tools/ai-sdk" +> ``` +> +> As of 2.0.0 this package is a thin re-export of `@supermemory/tools/ai-sdk`, so it +> inherits that package's container-scoping semantics. **This is a behavior change:** +> +> - Passing both `projectId` and `containerTags` now throws instead of silently ignoring `containerTags`. +> - With no config, calls are scoped to `["sm_project_default"]`. Previously they were **unscoped**, i.e. searching and writing across every project. If you relied on that, pass `containerTags` explicitly. +> - `limit` is coerced, so a model emitting `"5"` is accepted rather than rejected. + Vercel AI SDK utilities for supermemory ## Installation diff --git a/packages/ai-sdk/package.json b/packages/ai-sdk/package.json index 30ff931b7..438aecd17 100644 --- a/packages/ai-sdk/package.json +++ b/packages/ai-sdk/package.json @@ -1,30 +1,26 @@ { "name": "@supermemory/ai-sdk", "type": "module", - "version": "1.0.8", + "version": "2.0.0", + "description": "Deprecated: re-exports @supermemory/tools/ai-sdk", "scripts": { "build": "tsdown", "dev": "tsdown --watch --ignore-watch .turbo", - "check-types": "tsc --noEmit", - "test": "vitest", - "test:watch": "vitest --watch" + "check-types": "tsc --noEmit" }, "dependencies": { - "@ai-sdk/openai": "^2.0.22", "@ai-sdk/provider": "^2.0.0", - "ai": "^5.0.113", - "supermemory": "^3.0.0-alpha.26" + "@supermemory/tools": "^2.1.0" }, "devDependencies": { "@total-typescript/tsconfig": "^1.0.4", "@types/bun": "^1.2.21", "tsdown": "^0.14.2", - "typescript": "^5.9.2", - "vitest": "^3.2.4" + "typescript": "^5.9.2" }, "main": "./dist/index.js", "module": "./dist/index.js", - "types": "./dist/index-Dk1U5LBS.d.ts", + "types": "./dist/index-iQkOjAt3.d.ts", "exports": { ".": "./dist/index.js", "./package.json": "./package.json" diff --git a/packages/ai-sdk/src/index.ts b/packages/ai-sdk/src/index.ts index e419075c8..eb133d8ab 100644 --- a/packages/ai-sdk/src/index.ts +++ b/packages/ai-sdk/src/index.ts @@ -1 +1,12 @@ -export * from "./tools" +/** + * @deprecated Use `@supermemory/tools/ai-sdk` instead. This package is now a + * thin re-export of it and will not receive further changes. + * + * Behavior change in 2.0.0 (inherited from `@supermemory/tools`): + * - Passing both `projectId` and `containerTags` now throws instead of silently + * ignoring `containerTags`. + * - With no config, calls are scoped to `["sm_project_default"]` instead of being + * unscoped across every project. + * - `limit`/`offset` are coerced, so a model emitting `"5"` is accepted. + */ +export * from "@supermemory/tools/ai-sdk" diff --git a/packages/ai-sdk/src/tools.test.ts b/packages/ai-sdk/src/tools.test.ts deleted file mode 100644 index 0acfc7ed7..000000000 --- a/packages/ai-sdk/src/tools.test.ts +++ /dev/null @@ -1,181 +0,0 @@ -import { createOpenAI } from "@ai-sdk/openai" -import { generateText } from "ai" -import { describe, expect, it } from "vitest" -import { type SupermemoryToolsConfig, supermemoryTools } from "./tools" - -import "dotenv/config" - -describe("supermemoryTools", () => { - // Required API keys - tests will fail if not provided - const testApiKey = process.env.SUPERMEMORY_API_KEY - const testOpenAIKey = process.env.OPENAI_API_KEY - - if (!testApiKey) { - throw new Error( - "SUPERMEMORY_API_KEY environment variable is required for tests", - ) - } - if (!testOpenAIKey) { - throw new Error("OPENAI_API_KEY environment variable is required for tests") - } - - // Optional configuration with defaults - const testBaseUrl = process.env.SUPERMEMORY_BASE_URL ?? undefined - const testModelName = process.env.MODEL_NAME || "gpt-5-nano" - - const testPrompts = [ - "What do you remember about my preferences?", - "Help me plan my day based on what you know about me", - "What are my current projects?", - "Remind me of my interests and hobbies", - "What should I focus on today?", - ] - - describe("client initialization", () => { - it("should create tools with default configuration", () => { - const config: SupermemoryToolsConfig = {} - const tools = supermemoryTools(testApiKey, config) - - expect(tools).toBeDefined() - expect(tools.searchMemories).toBeDefined() - expect(tools.addMemory).toBeDefined() - }) - - it("should create tools with custom baseUrl", () => { - const config: SupermemoryToolsConfig = { - baseUrl: testBaseUrl, - } - const tools = supermemoryTools(testApiKey, config) - - expect(tools).toBeDefined() - expect(tools.searchMemories).toBeDefined() - expect(tools.addMemory).toBeDefined() - }) - - it("should create tools with projectId configuration", () => { - const config: SupermemoryToolsConfig = { - projectId: "test-project-123", - } - const tools = supermemoryTools(testApiKey, config) - - expect(tools).toBeDefined() - expect(tools.searchMemories).toBeDefined() - expect(tools.addMemory).toBeDefined() - }) - - it("should create tools with custom container tags", () => { - const config: SupermemoryToolsConfig = { - containerTags: ["custom-tag-1", "custom-tag-2"], - } - const tools = supermemoryTools(testApiKey, config) - - expect(tools).toBeDefined() - expect(tools.searchMemories).toBeDefined() - expect(tools.addMemory).toBeDefined() - }) - }) - - describe("AI SDK integration", () => { - it("should work with AI SDK generateText", async () => { - const openai = createOpenAI({ - apiKey: testOpenAIKey, - }) - - const result = await generateText({ - model: openai(testModelName), - messages: [ - { - role: "system", - content: - "You are a helpful assistant with access to user memories. Use the search tool when the user asks about preferences or past information.", - }, - { - role: "user", - content: testPrompts[0]!, - }, - ], - tools: { - ...supermemoryTools(testApiKey, { - projectId: "test-ai-integration", - baseUrl: testBaseUrl, - }), - }, - }) - - expect(result).toBeDefined() - expect(result.text).toBeDefined() - expect(typeof result.text).toBe("string") - }) - - it("should use tools when prompted", async () => { - const openai = createOpenAI({ - apiKey: testOpenAIKey, - }) - - const tools = supermemoryTools(testApiKey, { - projectId: "test-tool-usage", - baseUrl: testBaseUrl, - }) - - const result = await generateText({ - model: openai(testModelName), - messages: [ - { - role: "system", - content: - "You are a helpful assistant. When the user asks you to remember something, use the addMemory tool.", - }, - { - role: "user", - content: "Please remember that I prefer dark roast coffee", - }, - ], - tools: { - addMemory: tools.addMemory, - }, - }) - - expect(result).toBeDefined() - expect(result.text).toBeDefined() - expect(result.toolCalls).toBeDefined() - - if (result.toolCalls && result.toolCalls.length > 0) { - const addMemoryCall = result.toolCalls.find( - (call) => call.toolName === "addMemory", - ) - expect(addMemoryCall).toBeDefined() - } - }) - - it("should handle multiple tool types", async () => { - const openai = createOpenAI({ - apiKey: testOpenAIKey, - }) - - const result = await generateText({ - model: openai(testModelName), - messages: [ - { - role: "system", - content: - "You are a helpful assistant with access to user memories. Use search when asked about preferences, and addMemory when told to remember something.", - }, - { - role: "user", - content: - "Search for my preferences and then remember that I also like green tea", - }, - ], - tools: { - ...supermemoryTools(testApiKey, { - containerTags: ["test-multi-tools"], - }), - }, - }) - - expect(result).toBeDefined() - expect(result.text).toBeDefined() - expect(typeof result.text).toBe("string") - }) - }) -}) diff --git a/packages/ai-sdk/src/tools.ts b/packages/ai-sdk/src/tools.ts deleted file mode 100644 index 7d0b837cb..000000000 --- a/packages/ai-sdk/src/tools.ts +++ /dev/null @@ -1,150 +0,0 @@ -import { jsonSchema, tool } from "ai" -import Supermemory from "supermemory" - -/** - * Supermemory configuration - * Only one of `projectId` or `containerTags` can be provided. - */ -export interface SupermemoryToolsConfig { - baseUrl?: string - containerTags?: string[] - projectId?: string -} - -type SearchMemoriesInput = { - informationToGet: string - includeFullDocs: boolean - limit: number -} - -type AddMemoryInput = { - memory: string -} - -/** - * Create Supermemory tools for AI SDK - */ -export function supermemoryTools( - apiKey: string, - config?: SupermemoryToolsConfig, -) { - const client = new Supermemory({ - apiKey, - ...(config?.baseUrl ? { baseURL: config.baseUrl } : {}), - }) - - const containerTags = config?.projectId - ? [`sm_project_${config?.projectId}`] - : config?.containerTags - - const searchMemories = tool({ - description: - "Search (recall) memories/details/information about the user or other facts or entities. Run when explicitly asked or when context about user's past choices would be helpful.", - inputSchema: jsonSchema({ - type: "object", - properties: { - informationToGet: { - type: "string", - description: "Terms to search for in the user's memories", - }, - includeFullDocs: { - type: "boolean", - description: - "Whether to include the full document content in the response. Defaults to true for better AI context.", - default: true, - }, - limit: { - type: "number", - description: "Maximum number of results to return", - default: 10, - }, - }, - required: ["informationToGet"], - }), - execute: async ({ - informationToGet, - includeFullDocs = true, - limit = 10, - }) => { - try { - const response = await client.search.execute({ - q: informationToGet, - containerTags, - limit, - chunkThreshold: 0.6, - includeFullDocs, - }) - - return { - success: true, - results: response.results, - count: response.results?.length || 0, - } - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : "Unknown error", - } - } - }, - }) - - const addMemory = tool({ - description: - "Add (remember) memories/details/information about the user or other facts or entities. Run when explicitly asked or when the user mentions any information generalizable beyond the context of the current conversation.", - inputSchema: jsonSchema({ - type: "object", - properties: { - memory: { - type: "string", - description: - "The text content of the memory to add. This should be a single sentence or a short paragraph.", - }, - }, - required: ["memory"], - }), - execute: async ({ memory }) => { - try { - const metadata: Record = {} - - const response = await client.add({ - content: memory, - containerTags, - ...(Object.keys(metadata).length > 0 && { metadata }), - }) - - return { - success: true, - memory: response, - } - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : "Unknown error", - } - } - }, - }) - - return { - searchMemories, - addMemory, - } -} - -// Export individual tool creators for more flexibility -export const searchMemoriesTool = ( - apiKey: string, - config?: SupermemoryToolsConfig, -) => { - const { searchMemories } = supermemoryTools(apiKey, config) - return searchMemories -} - -export const addMemoryTool = ( - apiKey: string, - config?: SupermemoryToolsConfig, -) => { - const { addMemory } = supermemoryTools(apiKey, config) - return addMemory -} diff --git a/packages/tools/package.json b/packages/tools/package.json index 053089e52..2d5e270c3 100644 --- a/packages/tools/package.json +++ b/packages/tools/package.json @@ -51,8 +51,8 @@ "./ai-sdk": "./dist/ai-sdk.js", "./claude-memory": "./dist/claude-memory.js", "./mastra": "./dist/mastra.js", - "./openai": "./dist/openai/index.js", - "./voltagent": "./dist/voltagent/index.js", + "./openai\\index": "./dist/openai\\index.js", + "./voltagent\\index": "./dist/voltagent\\index.js", "./package.json": "./package.json" }, "repository": { diff --git a/turbo.json b/turbo.json index d635ddf88..a8e86ba27 100644 --- a/turbo.json +++ b/turbo.json @@ -11,7 +11,7 @@ "dependsOn": ["^lint"] }, "check-types": { - "dependsOn": ["^check-types"] + "dependsOn": ["^build"] }, "dev": { "cache": false, From 699e34d2234e05ac2cd22f943e39cc5f1ecd2e20 Mon Sep 17 00:00:00 2001 From: rajashidattapy Date: Sun, 12 Jul 2026 13:45:10 +0530 Subject: [PATCH 2/2] fix(tools): correct path separators in package exports and update tsdown config --- packages/tools/package.json | 4 ++-- packages/tools/tsdown.config.ts | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/tools/package.json b/packages/tools/package.json index 2d5e270c3..053089e52 100644 --- a/packages/tools/package.json +++ b/packages/tools/package.json @@ -51,8 +51,8 @@ "./ai-sdk": "./dist/ai-sdk.js", "./claude-memory": "./dist/claude-memory.js", "./mastra": "./dist/mastra.js", - "./openai\\index": "./dist/openai\\index.js", - "./voltagent\\index": "./dist/voltagent\\index.js", + "./openai": "./dist/openai/index.js", + "./voltagent": "./dist/voltagent/index.js", "./package.json": "./package.json" }, "repository": { diff --git a/packages/tools/tsdown.config.ts b/packages/tools/tsdown.config.ts index 139dd7df4..b0de5b7c9 100644 --- a/packages/tools/tsdown.config.ts +++ b/packages/tools/tsdown.config.ts @@ -18,6 +18,8 @@ export default defineConfig({ dts: { sourcemap: false, }, - exports: true, + // exports are hand-maintained in package.json: tsdown's generator emits + // native path separators, producing broken "./openai\\index" on Windows. + exports: false, unbundle: true, })