diff --git a/apps/browser-extension/entrypoints/background.ts b/apps/browser-extension/entrypoints/background.ts index 3b0a545fa..e6dba3eb6 100644 --- a/apps/browser-extension/entrypoints/background.ts +++ b/apps/browser-extension/entrypoints/background.ts @@ -273,7 +273,6 @@ export default defineBackground(() => { })() return true } - }, ) }) diff --git a/apps/mcp/src/server.ts b/apps/mcp/src/server.ts index b188b2c34..cc0394662 100644 --- a/apps/mcp/src/server.ts +++ b/apps/mcp/src/server.ts @@ -65,25 +65,16 @@ export class SupermemoryMCP extends McpAgent { const memorySchema = z.object({ content: z .string() - .max( - 200000, - "Content exceeds maximum length of 200,000 characters", - ) + .max(200000, "Content exceeds maximum length of 200,000 characters") .describe("The memory content to save or forget"), - action: z - .enum(["save", "forget"]) - .optional() - .default("save"), + action: z.enum(["save", "forget"]).optional().default("save"), ...(hasRootContainerTag ? {} : containerTagField), }) const recallSchema = z.object({ query: z .string() - .max( - 1000, - "Query exceeds maximum length of 1,000 characters", - ) + .max(1000, "Query exceeds maximum length of 1,000 characters") .describe("The search query to find relevant memories"), includeProfile: z.boolean().optional().default(true), ...(hasRootContainerTag ? {} : containerTagField), diff --git a/apps/web/components/add-document/connections.tsx b/apps/web/components/add-document/connections.tsx index 9d158f6f2..d4dc2a83b 100644 --- a/apps/web/components/add-document/connections.tsx +++ b/apps/web/components/add-document/connections.tsx @@ -59,8 +59,9 @@ export function ConnectContent({ selectedProject }: ConnectContentProps) { useEffect(() => { if (!autumn.isLoading) { setIsProUser( - autumn.customer?.products?.some((product) => product.id === "api_pro") ?? - false, + autumn.customer?.products?.some( + (product) => product.id === "api_pro", + ) ?? false, ) } }, [autumn.isLoading, autumn.customer]) diff --git a/apps/web/components/chat/message/agent-message.tsx b/apps/web/components/chat/message/agent-message.tsx index 8cf2a1a75..3b3ecb22d 100644 --- a/apps/web/components/chat/message/agent-message.tsx +++ b/apps/web/components/chat/message/agent-message.tsx @@ -29,14 +29,25 @@ const TOOL_META: Record = { cancelSchedule: { label: "Cancel Schedule", icon: XCircleIcon }, } -function ToolCallDisplay({ part }: { part: { type: string; state: string; input?: unknown; output?: unknown; toolCallId?: string } }) { +function ToolCallDisplay({ + part, +}: { + part: { + type: string + state: string + input?: unknown + output?: unknown + toolCallId?: string + } +}) { const [expanded, setExpanded] = useState(false) const toolName = part.type.replace("tool-", "") const meta = TOOL_META[toolName] const Icon = meta?.icon ?? WrenchIcon const label = meta?.label ?? toolName - const isLoading = part.state === "input-streaming" || part.state === "input-available" + const isLoading = + part.state === "input-streaming" || part.state === "input-available" const isDone = part.state === "output-available" const isError = part.state === "error" @@ -53,9 +64,27 @@ function ToolCallDisplay({ part }: { part: { type: string; state: string; input? {isLoading ? ( ) : ( - + )} - + {label} {isLoading && running...} @@ -74,7 +103,9 @@ function ToolCallDisplay({ part }: { part: { type: string; state: string; input?
Input
-								{typeof part.input === "string" ? part.input : JSON.stringify(part.input, null, 2)}
+								{typeof part.input === "string"
+									? part.input
+									: JSON.stringify(part.input, null, 2)}
 							
)} @@ -82,7 +113,9 @@ function ToolCallDisplay({ part }: { part: { type: string; state: string; input?
Output
-								{typeof part.output === "string" ? part.output : JSON.stringify(part.output, null, 2)}
+								{typeof part.output === "string"
+									? part.output
+									: JSON.stringify(part.output, null, 2)}
 							
)} diff --git a/apps/web/components/integrations/plugins-detail.tsx b/apps/web/components/integrations/plugins-detail.tsx index b01753a48..caf78b145 100644 --- a/apps/web/components/integrations/plugins-detail.tsx +++ b/apps/web/components/integrations/plugins-detail.tsx @@ -47,7 +47,8 @@ const PLUGIN_CATALOG: Record = { claude_code: { id: "claude_code", name: "Claude Code", - description: "Persistent memory for Claude Code. Remembers your coding context, patterns, and decisions across sessions.", + description: + "Persistent memory for Claude Code. Remembers your coding context, patterns, and decisions across sessions.", features: [ "Auto-recalls relevant context at session start", "Captures important observations from tool usage", @@ -60,7 +61,8 @@ const PLUGIN_CATALOG: Record = { opencode: { id: "opencode", name: "OpenCode", - description: "Memory layer for OpenCode. Enhances your coding assistant with long-term memory capabilities.", + description: + "Memory layer for OpenCode. Enhances your coding assistant with long-term memory capabilities.", features: [ "Semantic search across previous sessions", "Auto-capture of coding decisions", @@ -72,7 +74,8 @@ const PLUGIN_CATALOG: Record = { clawdbot: { id: "clawdbot", name: "ClawdBot", - description: "Multi-platform memory for OpenClaw. Works across Telegram, WhatsApp, Discord, Slack and more.", + description: + "Multi-platform memory for OpenClaw. Works across Telegram, WhatsApp, Discord, Slack and more.", features: [ "Cross-channel memory persistence", "Automatic conversation capture", @@ -98,18 +101,26 @@ export function PluginsDetail() { const autumn = useCustomer() const queryClient = useQueryClient() const [connectingPlugin, setConnectingPlugin] = useState(null) - const [newKey, setNewKey] = useState<{ open: boolean; key: string }>({ open: false, key: "" }) + const [newKey, setNewKey] = useState<{ open: boolean; key: string }>({ + open: false, + key: "", + }) const [keyCopied, setKeyCopied] = useState(false) - const { data: status = { api_pro: { allowed: false, status: null } }, isLoading: isCheckingStatus } = - fetchSubscriptionStatus(autumn, !autumn.isLoading) + const { + data: status = { api_pro: { allowed: false, status: null } }, + isLoading: isCheckingStatus, + } = fetchSubscriptionStatus(autumn, !autumn.isLoading) const hasProProduct = status.api_pro?.status !== null const { data: pluginsData } = useQuery({ queryFn: async () => { - const API_URL = process.env.NEXT_PUBLIC_BACKEND_URL ?? "https://api.supermemory.ai" - const res = await fetch(`${API_URL}/v3/auth/plugins`, { credentials: "include" }) + const API_URL = + process.env.NEXT_PUBLIC_BACKEND_URL ?? "https://api.supermemory.ai" + const res = await fetch(`${API_URL}/v3/auth/plugins`, { + credentials: "include", + }) if (!res.ok) throw new Error("Failed to fetch plugins") return (await res.json()) as { plugins: string[] } }, @@ -133,9 +144,13 @@ export function PluginsDetail() { for (const key of apiKeys) { if (!key.metadata) continue try { - const metadata = typeof key.metadata === "string" - ? (JSON.parse(key.metadata) as { sm_type?: string; sm_client?: string }) - : (key.metadata as { sm_type?: string; sm_client?: string }) + const metadata = + typeof key.metadata === "string" + ? (JSON.parse(key.metadata) as { + sm_type?: string + sm_client?: string + }) + : (key.metadata as { sm_type?: string; sm_client?: string }) if (metadata.sm_type === "plugin_auth" && metadata.sm_client) { plugins.push({ @@ -152,15 +167,23 @@ export function PluginsDetail() { return plugins }, [apiKeys]) - const connectedPluginIds = useMemo(() => connectedPlugins.map((p) => p.pluginId), [connectedPlugins]) + const connectedPluginIds = useMemo( + () => connectedPlugins.map((p) => p.pluginId), + [connectedPlugins], + ) const createPluginKeyMutation = useMutation({ mutationFn: async (pluginId: string) => { - const API_URL = process.env.NEXT_PUBLIC_BACKEND_URL ?? "https://api.supermemory.ai" + const API_URL = + process.env.NEXT_PUBLIC_BACKEND_URL ?? "https://api.supermemory.ai" const params = new URLSearchParams({ client: pluginId }) - const res = await fetch(`${API_URL}/v3/auth/key?${params}`, { credentials: "include" }) + const res = await fetch(`${API_URL}/v3/auth/key?${params}`, { + credentials: "include", + }) if (!res.ok) { - const errorData = (await res.json().catch(() => ({}))) as { message?: string } + const errorData = (await res.json().catch(() => ({}))) as { + message?: string + } throw new Error(errorData.message || "Failed to create plugin key") } return (await res.json()) as { key: string } @@ -193,7 +216,10 @@ export function PluginsDetail() { const handleUpgrade = async () => { try { - await autumn.attach({ productId: "api_pro", successUrl: "https://app.supermemory.ai/?view=integrations" }) + await autumn.attach({ + productId: "api_pro", + successUrl: "https://app.supermemory.ai/?view=integrations", + }) window.location.reload() } catch (error) { console.error(error) @@ -218,36 +244,75 @@ export function PluginsDetail() { <> {/* Marketing hero for free users */} {!hasProProduct && !isLoading && ( -
+
-

+

Unlock Persistent Memory for Your Tools

-

- Upgrade to Pro to connect plugins and give your AI tools long-term memory +

+ Upgrade to Pro to connect plugins and give your AI tools + long-term memory

{[ - { icon: Brain, title: "Context Retention", desc: "AI remembers your preferences across sessions" }, - { icon: Zap, title: "Instant Recall", desc: "Past decisions surface automatically when relevant" }, - { icon: Key, title: "Secure & Private", desc: "Your data stays yours with encrypted storage" }, + { + icon: Brain, + title: "Context Retention", + desc: "AI remembers your preferences across sessions", + }, + { + icon: Zap, + title: "Instant Recall", + desc: "Past decisions surface automatically when relevant", + }, + { + icon: Key, + title: "Secure & Private", + desc: "Your data stays yours with encrypted storage", + }, ].map(({ icon: Icon, title, desc }) => (
-

{title}

-

{desc}

+

+ {title} +

+

+ {desc} +

))} @@ -255,11 +320,25 @@ export function PluginsDetail() {
{Object.values(PLUGIN_CATALOG).map((plugin) => ( -
- {plugin.name} +
+ {plugin.name}
))} - + Claude Code, OpenCode, ClawdBot & more
@@ -280,12 +359,27 @@ export function PluginsDetail() {
)} -
-
+
+
{/* Connected plugins */} {connectedPlugins.length > 0 && (
- + Connected Plugins {connectedPlugins.map((plugin) => { @@ -293,23 +387,51 @@ export function PluginsDetail() { return (
{info && (
- {info.name} + {info.name}
)}
-

+

{info?.name || plugin.pluginId}

- Connected + + Connected + {plugin.keyStart && ( - {plugin.keyStart}... + + {plugin.keyStart}... + )}
@@ -329,8 +451,15 @@ export function PluginsDetail() { {/* Available plugins */}
- - {connectedPlugins.length > 0 ? "Add More Plugins" : "Available Plugins"} + + {connectedPlugins.length > 0 + ? "Add More Plugins" + : "Available Plugins"}
{availablePlugins.map((pluginId) => { @@ -345,23 +474,45 @@ export function PluginsDetail() { key={pluginId} className={cn( "bg-[#0D121A] rounded-[12px] p-4 flex flex-col gap-3 border", - isConnected ? "border-[#4BA0FA]/30" : "border-[rgba(82,89,102,0.2)]", + isConnected + ? "border-[#4BA0FA]/30" + : "border-[rgba(82,89,102,0.2)]", )} >
- {plugin.name} + {plugin.name}
- {plugin.name} + + {plugin.name} + {isConnected && ( Connected )}
-

{plugin.description}

+

+ {plugin.description} +

@@ -369,7 +520,14 @@ export function PluginsDetail() { {plugin.features.map((feature) => (
  • - {feature} + + {feature} +
  • ))} @@ -390,7 +548,9 @@ export function PluginsDetail() { ) : (
    {/* API Key modal */} - setNewKey({ open, key: open ? newKey.key : "" })}> + + setNewKey({ open, key: open ? newKey.key : "" }) + } + > - + Plugin Connected @@ -455,14 +634,21 @@ export function PluginsDetail() { type="text" value={newKey.key} readOnly - className={cn("flex-1 bg-[#0D121A] border border-white/10 rounded-lg px-3 py-2 text-sm text-[#FAFAFA] font-mono", dmSans125ClassName())} + className={cn( + "flex-1 bg-[#0D121A] border border-white/10 rounded-lg px-3 py-2 text-sm text-[#FAFAFA] font-mono", + dmSans125ClassName(), + )} />
    ) : ( diff --git a/apps/web/components/onboarding/welcome/profile-step.tsx b/apps/web/components/onboarding/welcome/profile-step.tsx index 6bb67f424..6e91ebd9d 100644 --- a/apps/web/components/onboarding/welcome/profile-step.tsx +++ b/apps/web/components/onboarding/welcome/profile-step.tsx @@ -241,7 +241,9 @@ export function ProfileStep({ onSubmit }: ProfileStepProps) { onClick={() => { const formData = { twitter: toXProfileUrl(parseXHandle(twitterHandle)), - linkedin: toLinkedInProfileUrl(parseLinkedInHandle(linkedinProfile)), + linkedin: toLinkedInProfileUrl( + parseLinkedInHandle(linkedinProfile), + ), description: description, otherLinks: otherLinks .filter((l) => l.trim()) diff --git a/packages/lib/posthog.tsx b/packages/lib/posthog.tsx index 87a28d555..5b9c49247 100644 --- a/packages/lib/posthog.tsx +++ b/packages/lib/posthog.tsx @@ -38,23 +38,18 @@ export function PostHogProvider({ children }: { children: React.ReactNode }) { useEffect(() => { if (typeof window !== "undefined") { - const posthogKey = "phc_uO09ylgCPmQl3wHukVvvwhphtoIaGmCMUTTwDo3PRlt" const backendUrl = process.env.NEXT_PUBLIC_BACKEND_URL ?? "https://api.supermemory.ai" - if (posthogKey) { - posthog.init(posthogKey, { - api_host: `${backendUrl}/orange`, - ui_host: "https://us.i.posthog.com", - person_profiles: "identified_only", - capture_pageview: false, - capture_pageleave: true, - }) - } else { - console.warn( - "PostHog API key is not set. PostHog will not be initialized.", - ) - } + posthog.init("phc_ShqecfUPQgf16lWu6ZMUzduQvcWzCywrkCz5KHwmWsv", { + api_host: `${backendUrl}/orange`, + ui_host: "https://us.i.posthog.com", + person_profiles: "identified_only", + capture_pageview: false, + capture_pageleave: true, + cookie_domain: ".supermemory.ai", + }) + posthog.register({ app: "app" }) } }, [])