repositories
loading repo index
repositories
loading repo index
repository
loading code, commits, and activity
public Clawd ADK gateway launch mirror
stars
latest
clone command
git clone gitlawb://did:key:z6Mkq5mY...iFZ5/my-project-publ...git clone gitlawb://did:key:z6Mkq5mY.../my-project-publ...2fa351d6docs: add automaton and perps launch sources16d ago| #1 | "use client"; |
| #2 | |
| #3 | import React, { useState } from "react"; |
| #4 | import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"; |
| #5 | import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; |
| #6 | import { Copy, Check } from "lucide-react"; |
| #7 | import Image from "next/image"; |
| #8 | |
| #9 | const clientTabs = [ |
| #10 | { key: "claude", label: "Claude", icon: "/images/claude.webp" }, |
| #11 | { key: "cursor", label: "Cursor", icon: "/images/cursor.png" }, |
| #12 | { key: "cline", label: "Cline", icon: "/images/cline.png" }, |
| #13 | { key: "roocline", label: "Roo Cline", icon: "/images/roocline.png" }, |
| #14 | { key: "windsurf", label: "Windsurf", icon: "/images/windsurf.png" }, |
| #15 | { key: "witsy", label: "Witsy", icon: "/images/witsy.png" }, |
| #16 | { key: "enconvo", label: "Enconvo", icon: "/images/enconvo.png" }, |
| #17 | { key: "augment", label: "Augment", icon: "/images/augment.png" }, |
| #18 | ]; |
| #19 | |
| #20 | const colorGradientMap: { [key: string]: string } = { |
| #21 | claude: |
| #22 | "data-[state=active]:bg-[linear-gradient(to_top,_rgba(239,108,60,0.3),_rgba(239,108,60,0))] data-[state=active]:border-[#EF6C3C]", |
| #23 | cline: |
| #24 | "data-[state=active]:bg-[linear-gradient(to_top,_rgba(112,128,144,0.3),_rgba(112,128,144,0))] data-[state=active]:border-[#708090]", |
| #25 | cursor: |
| #26 | "data-[state=active]:bg-[linear-gradient(to_top,_rgba(255,255,255,0.08),_rgba(255,255,255,0))] data-[state=active]:border-[#708090]", |
| #27 | roocline: |
| #28 | "data-[state=active]:bg-[linear-gradient(to_top,_rgba(45,32,92,0.8),_rgba(45,32,92,0))] data-[state=active]:border-[#7E3FF2]", |
| #29 | windsurf: |
| #30 | "data-[state=active]:bg-[linear-gradient(to_top,_rgba(0,176,137,0.3),_rgba(0,176,137,0))] data-[state=active]:border-[#00B089]", |
| #31 | witsy: |
| #32 | "data-[state=active]:bg-[linear-gradient(to_top,_rgba(33,135,255,0.3),_rgba(33,135,255,0))] data-[state=active]:border-[#2187FF]", |
| #33 | enconvo: |
| #34 | "data-[state=active]:bg-[linear-gradient(to_top,_rgba(126,63,242,0.3),_rgba(126,63,242,0))] data-[state=active]:border-[#7E3FF2]", |
| #35 | }; |
| #36 | |
| #37 | const getColorGradient = (color: string) => { |
| #38 | if (colorGradientMap[color]) { |
| #39 | return colorGradientMap[color]; |
| #40 | } |
| #41 | return "data-[state=active]:bg-[linear-gradient(to_top,_rgba(126,63,242,0.3),_rgba(126,63,242,0))] data-[state=active]:border-[#7E3FF2]"; |
| #42 | }; |
| #43 | |
| #44 | const allTabs = [{ key: "mcp", label: "MCP Link", icon: "🔗" }, ...clientTabs]; |
| #45 | |
| #46 | export const Install = () => { |
| #47 | const [copiedTab, setCopiedTab] = useState<string | null>(null); |
| #48 | const user = process.env.NEXT_PUBLIC_USER_ID || "user"; |
| #49 | |
| #50 | const URL = process.env.NEXT_PUBLIC_API_URL || "http://localhost:8765"; |
| #51 | |
| #52 | const handleCopy = async (tab: string, isMcp: boolean = false) => { |
| #53 | const text = isMcp |
| #54 | ? `${URL}/mcp/openmemory/sse/${user}` |
| #55 | : `npx @openmemory/install local ${URL}/mcp/${tab}/sse/${user} --client ${tab}`; |
| #56 | |
| #57 | try { |
| #58 | // Try using the Clipboard API first |
| #59 | if (navigator?.clipboard?.writeText) { |
| #60 | await navigator.clipboard.writeText(text); |
| #61 | } else { |
| #62 | // Fallback: Create a temporary textarea element |
| #63 | const textarea = document.createElement("textarea"); |
| #64 | textarea.value = text; |
| #65 | textarea.style.position = "fixed"; |
| #66 | textarea.style.opacity = "0"; |
| #67 | document.body.appendChild(textarea); |
| #68 | textarea.select(); |
| #69 | document.execCommand("copy"); |
| #70 | document.body.removeChild(textarea); |
| #71 | } |
| #72 | |
| #73 | // Update UI to show success |
| #74 | setCopiedTab(tab); |
| #75 | setTimeout(() => setCopiedTab(null), 1500); // Reset after 1.5s |
| #76 | } catch (error) { |
| #77 | console.error("Failed to copy text:", error); |
| #78 | // You might want to add a toast notification here to show the error |
| #79 | } |
| #80 | }; |
| #81 | |
| #82 | return ( |
| #83 | <div> |
| #84 | <h2 className="text-xl font-semibold mb-6">Install OpenMemory</h2> |
| #85 | |
| #86 | <div className="hidden"> |
| #87 | <div className="data-[state=active]:bg-[linear-gradient(to_top,_rgba(239,108,60,0.3),_rgba(239,108,60,0))] data-[state=active]:border-[#EF6C3C]"></div> |
| #88 | <div className="data-[state=active]:bg-[linear-gradient(to_top,_rgba(112,128,144,0.3),_rgba(112,128,144,0))] data-[state=active]:border-[#708090]"></div> |
| #89 | <div className="data-[state=active]:bg-[linear-gradient(to_top,_rgba(45,32,92,0.3),_rgba(45,32,92,0))] data-[state=active]:border-[#2D205C]"></div> |
| #90 | <div className="data-[state=active]:bg-[linear-gradient(to_top,_rgba(0,176,137,0.3),_rgba(0,176,137,0))] data-[state=active]:border-[#00B089]"></div> |
| #91 | <div className="data-[state=active]:bg-[linear-gradient(to_top,_rgba(33,135,255,0.3),_rgba(33,135,255,0))] data-[state=active]:border-[#2187FF]"></div> |
| #92 | <div className="data-[state=active]:bg-[linear-gradient(to_top,_rgba(126,63,242,0.3),_rgba(126,63,242,0))] data-[state=active]:border-[#7E3FF2]"></div> |
| #93 | <div className="data-[state=active]:bg-[linear-gradient(to_top,_rgba(239,108,60,0.3),_rgba(239,108,60,0))] data-[state=active]:border-[#EF6C3C]"></div> |
| #94 | <div className="data-[state=active]:bg-[linear-gradient(to_top,_rgba(107,33,168,0.3),_rgba(107,33,168,0))] data-[state=active]:border-primary"></div> |
| #95 | <div className="data-[state=active]:bg-[linear-gradient(to_top,_rgba(255,255,255,0.08),_rgba(255,255,255,0))] data-[state=active]:border-[#708090]"></div> |
| #96 | </div> |
| #97 | |
| #98 | <Tabs defaultValue="claude" className="w-full"> |
| #99 | <TabsList className="bg-transparent border-b border-zinc-800 rounded-none w-full justify-start gap-0 p-0 grid grid-cols-9"> |
| #100 | {allTabs.map(({ key, label, icon }) => ( |
| #101 | <TabsTrigger |
| #102 | key={key} |
| #103 | value={key} |
| #104 | className={`flex-1 px-0 pb-2 rounded-none ${getColorGradient( |
| #105 | key |
| #106 | )} data-[state=active]:border-b-2 data-[state=active]:shadow-none text-zinc-400 data-[state=active]:text-white flex items-center justify-center gap-2 text-sm`} |
| #107 | > |
| #108 | {icon.startsWith("/") ? ( |
| #109 | <div> |
| #110 | <div className="w-6 h-6 rounded-full bg-zinc-700 flex items-center justify-center overflow-hidden"> |
| #111 | <Image src={icon} alt={label} width={40} height={40} /> |
| #112 | </div> |
| #113 | </div> |
| #114 | ) : ( |
| #115 | <div className="h-6"> |
| #116 | <span className="relative top-1">{icon}</span> |
| #117 | </div> |
| #118 | )} |
| #119 | <span>{label}</span> |
| #120 | </TabsTrigger> |
| #121 | ))} |
| #122 | </TabsList> |
| #123 | |
| #124 | {/* MCP Tab Content */} |
| #125 | <TabsContent value="mcp" className="mt-6"> |
| #126 | <Card className="bg-zinc-900 border-zinc-800"> |
| #127 | <CardHeader className="py-4"> |
| #128 | <CardTitle className="text-white text-xl">MCP Link</CardTitle> |
| #129 | </CardHeader> |
| #130 | <hr className="border-zinc-800" /> |
| #131 | <CardContent className="py-4"> |
| #132 | <div className="relative"> |
| #133 | <pre className="bg-zinc-800 px-4 py-3 rounded-md overflow-x-auto text-sm"> |
| #134 | <code className="text-gray-300"> |
| #135 | {URL}/mcp/openmemory/sse/{user} |
| #136 | </code> |
| #137 | </pre> |
| #138 | <div> |
| #139 | <button |
| #140 | className="absolute top-0 right-0 py-3 px-4 rounded-md hover:bg-zinc-600 bg-zinc-700" |
| #141 | aria-label="Copy to clipboard" |
| #142 | onClick={() => handleCopy("mcp", true)} |
| #143 | > |
| #144 | {copiedTab === "mcp" ? ( |
| #145 | <Check className="h-5 w-5 text-green-400" /> |
| #146 | ) : ( |
| #147 | <Copy className="h-5 w-5 text-zinc-400" /> |
| #148 | )} |
| #149 | </button> |
| #150 | </div> |
| #151 | </div> |
| #152 | </CardContent> |
| #153 | </Card> |
| #154 | </TabsContent> |
| #155 | |
| #156 | {/* Client Tabs Content */} |
| #157 | {clientTabs.map(({ key }) => ( |
| #158 | <TabsContent key={key} value={key} className="mt-6"> |
| #159 | <Card className="bg-zinc-900 border-zinc-800"> |
| #160 | <CardHeader className="py-4"> |
| #161 | <CardTitle className="text-white text-xl"> |
| #162 | {key.charAt(0).toUpperCase() + key.slice(1)} Installation |
| #163 | Command |
| #164 | </CardTitle> |
| #165 | </CardHeader> |
| #166 | <hr className="border-zinc-800" /> |
| #167 | <CardContent className="py-4"> |
| #168 | <div className="relative"> |
| #169 | <pre className="bg-zinc-800 px-4 py-3 rounded-md overflow-x-auto text-sm"> |
| #170 | <code className="text-gray-300"> |
| #171 | {`npx @openmemory/install local ${URL}/mcp/${key}/sse/${user} --client ${key}`} |
| #172 | </code> |
| #173 | </pre> |
| #174 | <div> |
| #175 | <button |
| #176 | className="absolute top-0 right-0 py-3 px-4 rounded-md hover:bg-zinc-600 bg-zinc-700" |
| #177 | aria-label="Copy to clipboard" |
| #178 | onClick={() => handleCopy(key)} |
| #179 | > |
| #180 | {copiedTab === key ? ( |
| #181 | <Check className="h-5 w-5 text-green-400" /> |
| #182 | ) : ( |
| #183 | <Copy className="h-5 w-5 text-zinc-400" /> |
| #184 | )} |
| #185 | </button> |
| #186 | </div> |
| #187 | </div> |
| #188 | </CardContent> |
| #189 | </Card> |
| #190 | </TabsContent> |
| #191 | ))} |
| #192 | </Tabs> |
| #193 | </div> |
| #194 | ); |
| #195 | }; |
| #196 | |
| #197 | export default Install; |
| #198 |