supermemory/apps/web/lib/agent-space.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

175 lines
5.5 KiB
TypeScript

import { describe, expect, it } from "bun:test"
import {
agentSourceValues,
groupAgentSpaces,
isAgentContainerTag,
isAgentsSelection,
} from "./agent-space"
describe("Agents spaces", () => {
it("recognizes shared and legacy tags from every unified agent", () => {
expect(isAgentContainerTag("repo_supermemory__0123456789abcdef")).toBe(true)
expect(isAgentContainerTag("user_project_0123456789abcdef")).toBe(true)
expect(isAgentContainerTag("repo_supermemory")).toBe(true)
expect(isAgentContainerTag("claudecode_project_0123456789abcdef")).toBe(
true,
)
expect(isAgentContainerTag("codex_project_0123456789abcdef")).toBe(true)
expect(isAgentContainerTag("codex_user_0123456789abcdef")).toBe(true)
expect(isAgentContainerTag("opencode_project_0123456789abcdef")).toBe(true)
expect(isAgentContainerTag("opencode_user_0123456789abcdef")).toBe(true)
expect(isAgentContainerTag("cursor_project_0123456789abcdef")).toBe(true)
expect(isAgentContainerTag("cursor_user_0123456789abcdef")).toBe(true)
})
it("shows agent filters only for an Agents selection", () => {
expect(
isAgentsSelection([
"repo_supermemory__0123456789abcdef",
"repo_supermemory",
]),
).toBe(true)
expect(isAgentsSelection(["repo_supermemory", "sm_project_default"])).toBe(
false,
)
expect(isAgentsSelection([])).toBe(false)
})
it("maps filter labels to canonical and legacy document sources", () => {
expect(agentSourceValues("claude-code")).toEqual([
"claude-code",
"claude-code-plugin",
])
expect(agentSourceValues("codex")).toEqual(["codex"])
expect(agentSourceValues("opencode")).toEqual(["opencode"])
expect(agentSourceValues("cursor")).toEqual(["cursor"])
expect(agentSourceValues(null)).toBeUndefined()
})
it("groups canonical and legacy project containers without synthetic tags", () => {
const projects = [
{ containerTag: "repo_supermemory__fedcba9876543210" },
{ containerTag: "repo_supermemory" },
{ containerTag: "codex_project_0123456789abcdef" },
{ containerTag: "opencode_project_0123456789abcdef" },
{ containerTag: "claudecode_project_0123456789abcdef" },
{ containerTag: "user_project_0123456789abcdef" },
]
const metadata = new Map(
projects.map((project) => [
project.containerTag,
{ projectName: "supermemory" },
]),
)
const groups = groupAgentSpaces(projects, metadata)
expect(groups).toHaveLength(1)
expect(groups[0]?.label).toBe("supermemory")
expect(groups[0]?.representative.containerTag).toBe(
"repo_supermemory__fedcba9876543210",
)
expect(groups[0]?.containerTags).toEqual([
"repo_supermemory__fedcba9876543210",
"user_project_0123456789abcdef",
"claudecode_project_0123456789abcdef",
"repo_supermemory",
"codex_project_0123456789abcdef",
"opencode_project_0123456789abcdef",
])
})
it("keeps repositories with the same basename in separate agent spaces", () => {
const projects = [
{ containerTag: "repo_api__0123456789abcdef" },
{ containerTag: "repo_api__fedcba9876543210" },
{ containerTag: "repo_api" },
]
const metadata = new Map(
projects.map((project) => [project.containerTag, { projectName: "api" }]),
)
const groups = groupAgentSpaces(projects, metadata)
expect(groups).toHaveLength(3)
expect(
groups.filter((group) => group.key.startsWith("project-id:")),
).toHaveLength(2)
})
it("keeps the old global Codex personal container separate", () => {
const projects = [
{ containerTag: "user_project_0123456789abcdef" },
{ containerTag: "codex_user_fedcba9876543210" },
]
const metadata = new Map(
projects.map((project) => [
project.containerTag,
{ projectName: "supermemory" },
]),
)
const groups = groupAgentSpaces(projects, metadata)
expect(groups).toHaveLength(2)
expect(groups[0]?.label).toBe("supermemory")
expect(groups[1]?.label).toBe("Legacy Codex personal")
expect(groups[1]?.kind).toBe("legacy-personal")
})
it("keeps the old global OpenCode personal container separate", () => {
const projects = [
{ containerTag: "user_project_0123456789abcdef" },
{ containerTag: "opencode_user_fedcba9876543210" },
]
const metadata = new Map(
projects.map((project) => [
project.containerTag,
{ projectName: "supermemory" },
]),
)
const groups = groupAgentSpaces(projects, metadata)
expect(groups).toHaveLength(2)
expect(groups[0]?.label).toBe("supermemory")
expect(groups[1]?.label).toBe("Legacy OpenCode personal")
expect(groups[1]?.kind).toBe("legacy-personal")
})
it("groups path-scoped legacy tags even before metadata loads", () => {
const projects = [
{ containerTag: "claudecode_project_0123456789abcdef" },
{ containerTag: "codex_project_0123456789abcdef" },
{ containerTag: "opencode_project_0123456789abcdef" },
]
const groups = groupAgentSpaces(projects, new Map())
expect(groups).toHaveLength(1)
expect(groups[0]?.representative.containerTag).toBe(
"claudecode_project_0123456789abcdef",
)
})
it("shows an unambiguous Cursor project label before metadata loads", () => {
const groups = groupAgentSpaces(
[{ containerTag: "cursor_project_0123456789abcdef" }],
new Map(),
)
expect(groups).toHaveLength(1)
expect(groups[0]?.label).toBe("Cursor project · 012345")
})
it("shows old Cursor personal memory without a Legacy prefix", () => {
const groups = groupAgentSpaces(
[{ containerTag: "cursor_user_fedcba9876543210" }],
new Map(),
)
expect(groups).toHaveLength(1)
expect(groups[0]?.label).toBe("Cursor personal · fedcba")
expect(groups[0]?.kind).toBe("legacy-personal")
})
})