feat(ai-sdk): re-export full Supermemory tool set from @supermemory/tools

Thin @supermemory/ai-sdk package now mirrors the canonical 7-tool surface
with updated tests.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Dhravya Shah 2026-08-07 19:39:57 -07:00
parent d5937b8b26
commit 9c3f84b5cb
4 changed files with 58 additions and 163 deletions

View file

@ -1,19 +1,21 @@
{
"name": "@supermemory/ai-sdk",
"type": "module",
"version": "1.0.8",
"version": "1.0.9",
"scripts": {
"build": "tsdown",
"dev": "tsdown --watch --ignore-watch .turbo",
"check-types": "tsc --noEmit",
"test": "vitest",
"test:unit": "vitest run src/tools.unit.test.ts",
"test:watch": "vitest --watch"
},
"dependencies": {
"@ai-sdk/openai": "^2.0.22",
"@ai-sdk/provider": "^2.0.0",
"@supermemory/tools": "workspace:*",
"ai": "^5.0.113",
"supermemory": "^3.0.0-alpha.26"
"supermemory": "^4.25.4"
},
"devDependencies": {
"@total-typescript/tsconfig": "^1.0.4",
@ -24,7 +26,7 @@
},
"main": "./dist/index.js",
"module": "./dist/index.js",
"types": "./dist/index-Dk1U5LBS.d.ts",
"types": "./dist/index-B8qmWxBg.d.ts",
"exports": {
".": "./dist/index.js",
"./package.json": "./package.json"

View file

@ -5,19 +5,12 @@ 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")
}
describe.skipIf(
!process.env.SUPERMEMORY_API_KEY || !process.env.OPENAI_API_KEY,
)("supermemoryTools", () => {
// Required API keys — suite is skipped in CI without them
const testApiKey = process.env.SUPERMEMORY_API_KEY as string
const testOpenAIKey = process.env.OPENAI_API_KEY as string
// Optional configuration with defaults
const testBaseUrl = process.env.SUPERMEMORY_BASE_URL ?? undefined
@ -39,6 +32,11 @@ describe("supermemoryTools", () => {
expect(tools).toBeDefined()
expect(tools.searchMemories).toBeDefined()
expect(tools.addMemory).toBeDefined()
expect(tools.getProfile).toBeDefined()
expect(tools.documentList).toBeDefined()
expect(tools.documentDelete).toBeDefined()
expect(tools.documentAdd).toBeDefined()
expect(tools.memoryForget).toBeDefined()
})
it("should create tools with custom baseUrl", () => {

View file

@ -1,150 +1,17 @@
import { jsonSchema, tool } from "ai"
import Supermemory from "supermemory"
/**
* Supermemory configuration
* Only one of `projectId` or `containerTags` can be provided.
* Re-export the canonical Supermemory AI SDK tools from @supermemory/tools.
* Prefer @supermemory/tools for middleware, OpenAI, Mastra, and VoltAgent integrations.
*/
export interface SupermemoryToolsConfig {
baseUrl?: string
containerTags?: string[]
projectId?: string
}
export {
supermemoryTools,
searchMemoriesTool,
addMemoryTool,
getProfileTool,
documentListTool,
documentDeleteTool,
documentAddTool,
memoryForgetTool,
getContainerTags,
} from "@supermemory/tools/ai-sdk"
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<SearchMemoriesInput>({
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<AddMemoryInput>({
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<string, string | number | boolean> = {}
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
}
export type { SupermemoryToolsConfig } from "@supermemory/tools"

View file

@ -0,0 +1,28 @@
import { describe, expect, it } from "vitest"
import { getContainerTags } from "./tools"
describe("getContainerTags", () => {
it("defaults to the default project when no config is provided", () => {
expect(getContainerTags()).toEqual(["sm_project_default"])
})
it("converts projectId into a project container tag", () => {
expect(getContainerTags({ projectId: "abc" })).toEqual(["sm_project_abc"])
})
it("uses explicit container tags", () => {
expect(getContainerTags({ containerTags: ["tag-a", "tag-b"] })).toEqual([
"tag-a",
"tag-b",
])
})
it("rejects config with both projectId and containerTags", () => {
expect(() =>
getContainerTags({
projectId: "abc",
containerTags: ["tag-a"],
}),
).toThrow("either projectId or containerTags")
})
})