supermemory/apps/web/lib/plugin-document.test.ts
ved015 6f3c835e8f feat(web): add Cursor to Agents (#1361)
Adds Cursor projects to Agents spaces with source filters, legacy labels, icons, and Codex-style structured conversation rendering.

Tests: targeted Agents and plugin-document tests.
2026-07-25 22:09:28 +00:00

166 lines
5 KiB
TypeScript

import { describe, expect, it } from "bun:test"
import { parsePluginDocument } from "./plugin-document"
type PluginDocumentInput = Parameters<typeof parsePluginDocument>[0]
function makeCodexSessionDocument(content: string): PluginDocumentInput {
return {
id: "doc_1",
title: "Codex session",
content,
metadata: { sm_source: "codex" },
memoryEntries: [],
} as unknown as PluginDocumentInput
}
describe("parsePluginDocument — session transcripts", () => {
it("keeps the Codex source badge inside a shared Agents container", () => {
const parsed = parsePluginDocument({
...makeCodexSessionDocument(
["[Session abc-123]", "1. [user] Shared memory"].join("\n"),
),
source: "codex",
containerTags: ["user_project_0123456789abcdef"],
} as unknown as PluginDocumentInput)
expect(parsed?.pluginLabel).toBe("Codex")
expect(parsed?.pluginIconSrc).toBe("/images/plugins/codex.png")
})
it("keeps the Claude Code source badge inside a shared Agents container", () => {
const parsed = parsePluginDocument({
id: "doc_claude",
title: "Claude memory",
content: "Remember this project convention",
source: "claude-code",
metadata: {
sm_source: "claude-code",
type: "manual",
project: "supermemory",
},
containerTags: ["repo_supermemory"],
memoryEntries: [],
} as unknown as PluginDocumentInput)
expect(parsed?.pluginLabel).toBe("Claude Code")
expect(parsed?.pluginIconSrc).toBe("/images/plugins/claude-code.svg")
})
it("renders a new Cursor capture as structured conversation cards", () => {
const parsed = parsePluginDocument({
id: "doc_cursor",
title: "Cursor conversation",
content: [
"[Conversation cursor-session-1]",
"1. [user] Keep the API boundary stable",
"2. [assistant] I will preserve it.",
].join("\n"),
source: "cursor",
metadata: { sm_source: "cursor", type: "conversation" },
containerTags: ["repo_supermemory__0123456789abcdef"],
memoryEntries: [],
} as unknown as PluginDocumentInput)
expect(parsed?.pluginLabel).toBe("Cursor")
expect(parsed?.pluginIconSrc).toBe("/images/plugins/cursor.png")
expect(parsed?.formatLabel).toBe("Conversation")
expect(parsed?.messages).toHaveLength(2)
expect(parsed?.messages[0]?.role).toBe("user")
expect(parsed?.messages[1]?.role).toBe("assistant")
})
it("renders old Cursor tags and transcripts without source metadata", () => {
const parsed = parsePluginDocument({
id: "doc_cursor_legacy",
title: "Cursor session",
content: [
"Cursor IDE session transcript:",
"User: Fix the renderer",
"with the existing card design.",
"Assistant: Implemented the parser.",
].join("\n"),
source: "api",
metadata: {},
containerTags: ["cursor_project_0123456789abcdef"],
memoryEntries: [],
} as unknown as PluginDocumentInput)
expect(parsed?.pluginLabel).toBe("Cursor")
expect(parsed?.pluginIconSrc).toBe("/images/plugins/cursor.png")
expect(parsed?.messages).toHaveLength(2)
expect(parsed?.messages[0]?.text).toBe(
"Fix the renderer\nwith the existing card design.",
)
expect(parsed?.messages[1]?.text).toBe("Implemented the parser.")
})
it("keeps multi-line message bodies intact", () => {
const parsed = parsePluginDocument(
makeCodexSessionDocument(
[
"[Session abc-123]",
"1. [user] Hello there",
"Here is more context on line two",
"2. [assistant] Sure!",
"Second line of the reply",
].join("\n"),
),
)
expect(parsed).not.toBeNull()
expect(parsed?.kind).toBe("codex-session")
expect(parsed?.messages).toHaveLength(2)
expect(parsed?.messages[0]?.text).toBe(
"Hello there\nHere is more context on line two",
)
expect(parsed?.messages[1]?.text).toBe("Sure!\nSecond line of the reply")
})
it("surfaces memory id artifacts from continuation lines", () => {
const parsed = parsePluginDocument(
makeCodexSessionDocument(
[
"[Session abc-123]",
"1. [user] Remember my editor is Neovim",
"memory id: mem_456",
"2. [assistant] Saved it.",
].join("\n"),
),
)
expect(parsed?.messages[0]?.text).toBe("Remember my editor is Neovim")
expect(parsed?.artifacts).toContainEqual({
label: "Memory ID",
value: "mem_456",
})
})
it("normalizes literal \\n escapes before splitting messages", () => {
const parsed = parsePluginDocument(
makeCodexSessionDocument(
"[Session abc-123]\\n1. [user] First line\\nSecond line\\n2. [assistant] Reply",
),
)
expect(parsed?.messages).toHaveLength(2)
expect(parsed?.messages[0]?.text).toBe("First line\nSecond line")
expect(parsed?.messages[1]?.text).toBe("Reply")
})
it("parses single-line messages as before", () => {
const parsed = parsePluginDocument(
makeCodexSessionDocument(
["[Session abc-123]", "1. [user] Hi", "2. [assistant] Hello!"].join(
"\n",
),
),
)
expect(parsed?.messages).toHaveLength(2)
expect(parsed?.messages[0]?.text).toBe("Hi")
expect(parsed?.messages[1]?.text).toBe("Hello!")
expect(parsed?.summary).toBe(
"1 user message and 1 assistant message captured from Codex.",
)
})
})