From d7cf2b9bb40f3568e541dccf44f4f5c5389cfc70 Mon Sep 17 00:00:00 2001 From: kui123456789 Date: Mon, 2 Mar 2026 03:08:56 +0800 Subject: [PATCH 1/3] fix: handle missing similarity and object profile items in context display --- src/index.ts | 8 ++++---- src/services/context.ts | 12 +++++++----- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/index.ts b/src/index.ts index 8f0a442..2e7ef90 100644 --- a/src/index.ts +++ b/src/index.ts @@ -372,7 +372,7 @@ export const SupermemoryPlugin: Plugin = async (ctx: PluginInput) => { ...r, scope: "project" as const, })), - ].sort((a, b) => b.similarity - a.similarity); + ].sort((a, b) => (b.similarity ?? 0) - (a.similarity ?? 0)); return JSON.stringify({ success: true, @@ -381,7 +381,7 @@ export const SupermemoryPlugin: Plugin = async (ctx: PluginInput) => { results: combined.slice(0, args.limit || 10).map((r) => ({ id: r.id, content: r.memory || r.chunk, - similarity: Math.round(r.similarity * 100), + similarity: Math.round((r.similarity ?? 0) * 100), scope: r.scope, })), }); @@ -495,7 +495,7 @@ export const SupermemoryPlugin: Plugin = async (ctx: PluginInput) => { function formatSearchResults( query: string, scope: string | undefined, - results: { results?: Array<{ id: string; memory?: string; chunk?: string; similarity: number }> }, + results: { results?: Array<{ id: string; memory?: string; chunk?: string; similarity?: number }> }, limit?: number ): string { const memoryResults = results.results || []; @@ -507,7 +507,7 @@ function formatSearchResults( results: memoryResults.slice(0, limit || 10).map((r) => ({ id: r.id, content: r.memory || r.chunk, - similarity: Math.round(r.similarity * 100), + similarity: Math.round((r.similarity ?? 0) * 100), })), }); } diff --git a/src/services/context.ts b/src/services/context.ts index ae9f76a..3884bea 100644 --- a/src/services/context.ts +++ b/src/services/context.ts @@ -2,7 +2,7 @@ import type { ProfileResponse } from "supermemory/resources"; import { CONFIG } from "../config.js"; interface MemoryResultMinimal { - similarity: number; + similarity?: number; memory?: string; chunk?: string; } @@ -24,14 +24,16 @@ export function formatContextForPrompt( if (staticFacts.length > 0) { parts.push("\nUser Profile:"); staticFacts.slice(0, CONFIG.maxProfileItems).forEach((fact) => { - parts.push(`- ${fact}`); + const text = typeof fact === "string" ? fact : (fact as { content?: string }).content ?? String(fact); + parts.push(`- ${text}`); }); } if (dynamicFacts.length > 0) { parts.push("\nRecent Context:"); dynamicFacts.slice(0, CONFIG.maxProfileItems).forEach((fact) => { - parts.push(`- ${fact}`); + const text = typeof fact === "string" ? fact : (fact as { content?: string }).content ?? String(fact); + parts.push(`- ${text}`); }); } } @@ -40,7 +42,7 @@ export function formatContextForPrompt( if (projectResults.length > 0) { parts.push("\nProject Knowledge:"); projectResults.forEach((mem) => { - const similarity = Math.round(mem.similarity * 100); + const similarity = Math.round((mem.similarity ?? 0) * 100); const content = mem.memory || mem.chunk || ""; parts.push(`- [${similarity}%] ${content}`); }); @@ -50,7 +52,7 @@ export function formatContextForPrompt( if (userResults.length > 0) { parts.push("\nRelevant Memories:"); userResults.forEach((mem) => { - const similarity = Math.round(mem.similarity * 100); + const similarity = Math.round((mem.similarity ?? 0) * 100); const content = mem.memory || mem.chunk || ""; parts.push(`- [${similarity}%] ${content}`); }); From 823ff425f655d38432a6ee3467568633c8f9af74 Mon Sep 17 00:00:00 2001 From: kui123456789 Date: Mon, 2 Mar 2026 03:47:23 +0800 Subject: [PATCH 2/3] fix: populate empty memory content in project knowledge list listMemories API returns null summary by default. Added includeContent param and fallback chain (summary || content || title) so project knowledge entries display actual text instead of blank lines. --- src/index.ts | 2 +- src/services/client.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index 2e7ef90..7a5a441 100644 --- a/src/index.ts +++ b/src/index.ts @@ -140,7 +140,7 @@ export const SupermemoryPlugin: Plugin = async (ctx: PluginInput) => { const projectMemories = { results: (projectMemoriesList.memories || []).map((m: any) => ({ id: m.id, - memory: m.summary, + memory: m.summary || m.content || m.title || "", similarity: 1, title: m.title, metadata: m.metadata, diff --git a/src/services/client.ts b/src/services/client.ts index 2bff479..6fb3c3c 100644 --- a/src/services/client.ts +++ b/src/services/client.ts @@ -151,6 +151,7 @@ export class SupermemoryClient { limit, order: "desc", sort: "createdAt", + includeContent: true, }), TIMEOUT_MS ); From c1451ec72e85300c8d2457494ed5a6f029c27aab Mon Sep 17 00:00:00 2001 From: kui123456789 Date: Mon, 2 Mar 2026 03:49:31 +0800 Subject: [PATCH 3/3] refactor: extract extractFactText helper with JSON.stringify fallback Address Copilot review comments: - Extract duplicated fact-to-text logic into reusable helper - Use JSON.stringify instead of String() for unknown object shapes to avoid [object Object] fallback --- src/services/context.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/services/context.ts b/src/services/context.ts index 3884bea..3d6a18e 100644 --- a/src/services/context.ts +++ b/src/services/context.ts @@ -11,6 +11,16 @@ interface MemoriesResponseMinimal { results?: MemoryResultMinimal[]; } +function extractFactText(fact: unknown): string { + if (typeof fact === "string") return fact; + if (fact != null && typeof fact === "object") { + const content = (fact as { content?: string }).content; + if (typeof content === "string") return content; + return JSON.stringify(fact); + } + return String(fact ?? ""); +} + export function formatContextForPrompt( profile: ProfileResponse | null, userMemories: MemoriesResponseMinimal, @@ -24,7 +34,7 @@ export function formatContextForPrompt( if (staticFacts.length > 0) { parts.push("\nUser Profile:"); staticFacts.slice(0, CONFIG.maxProfileItems).forEach((fact) => { - const text = typeof fact === "string" ? fact : (fact as { content?: string }).content ?? String(fact); + const text = extractFactText(fact); parts.push(`- ${text}`); }); } @@ -32,7 +42,7 @@ export function formatContextForPrompt( if (dynamicFacts.length > 0) { parts.push("\nRecent Context:"); dynamicFacts.slice(0, CONFIG.maxProfileItems).forEach((fact) => { - const text = typeof fact === "string" ? fact : (fact as { content?: string }).content ?? String(fact); + const text = extractFactText(fact); parts.push(`- ${text}`); }); }