@cosmicstack/mercury-agent 1.1.9 → 1.1.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +101 -1
- package/README.zh-CN.md +265 -140
- package/dist/index.js +4473 -1842
- package/dist/index.js.map +1 -1
- package/dist/web/ui/assets/{Chat-DCFkzIwn.js → Chat-DXSn2dY8.js} +2 -2
- package/dist/web/ui/assets/{Chat-DCFkzIwn.js.map → Chat-DXSn2dY8.js.map} +1 -1
- package/dist/web/ui/assets/{Dashboard-B81ollv8.js → Dashboard-1rlAqQ-Y.js} +2 -2
- package/dist/web/ui/assets/{Dashboard-B81ollv8.js.map → Dashboard-1rlAqQ-Y.js.map} +1 -1
- package/dist/web/ui/assets/{Goals-D0cR8yIP.js → Goals-CgSUAXLH.js} +2 -2
- package/dist/web/ui/assets/{Goals-D0cR8yIP.js.map → Goals-CgSUAXLH.js.map} +1 -1
- package/dist/web/ui/assets/{Graph-C3eHp3_J.js → Graph-DnlOWkay.js} +2 -2
- package/dist/web/ui/assets/{Graph-C3eHp3_J.js.map → Graph-DnlOWkay.js.map} +1 -1
- package/dist/web/ui/assets/{Kanban-DrkTRyni.js → Kanban-DRlNiNRF.js} +2 -2
- package/dist/web/ui/assets/{Kanban-DrkTRyni.js.map → Kanban-DRlNiNRF.js.map} +1 -1
- package/dist/web/ui/assets/{Login-GRQ-LjgN.js → Login-BP5524pC.js} +2 -2
- package/dist/web/ui/assets/{Login-GRQ-LjgN.js.map → Login-BP5524pC.js.map} +1 -1
- package/dist/web/ui/assets/{MarkdownRenderer-Dvh1jwyj.js → MarkdownRenderer-B9KGVD0X.js} +2 -2
- package/dist/web/ui/assets/{MarkdownRenderer-Dvh1jwyj.js.map → MarkdownRenderer-B9KGVD0X.js.map} +1 -1
- package/dist/web/ui/assets/{Memory-dAZsKmWz.js → Memory-BOQEY0H8.js} +2 -2
- package/dist/web/ui/assets/{Memory-dAZsKmWz.js.map → Memory-BOQEY0H8.js.map} +1 -1
- package/dist/web/ui/assets/{Permissions-DCiyUUfI.js → Permissions-jbFH-toa.js} +2 -2
- package/dist/web/ui/assets/{Permissions-DCiyUUfI.js.map → Permissions-jbFH-toa.js.map} +1 -1
- package/dist/web/ui/assets/{PersonDetail-iZgApJog.js → PersonDetail-Ca8B9io8.js} +2 -2
- package/dist/web/ui/assets/{PersonDetail-iZgApJog.js.map → PersonDetail-Ca8B9io8.js.map} +1 -1
- package/dist/web/ui/assets/{Persons-Bs_HhYjC.js → Persons-epdmUeBM.js} +2 -2
- package/dist/web/ui/assets/{Persons-Bs_HhYjC.js.map → Persons-epdmUeBM.js.map} +1 -1
- package/dist/web/ui/assets/{Providers-CL6wMWni.js → Providers-Bm8sZNZo.js} +2 -2
- package/dist/web/ui/assets/{Providers-CL6wMWni.js.map → Providers-Bm8sZNZo.js.map} +1 -1
- package/dist/web/ui/assets/{Schedules-BQwE1hP5.js → Schedules-BZKhm9R7.js} +2 -2
- package/dist/web/ui/assets/{Schedules-BQwE1hP5.js.map → Schedules-BZKhm9R7.js.map} +1 -1
- package/dist/web/ui/assets/{Settings-26SF-okR.js → Settings-Hii-5oku.js} +2 -2
- package/dist/web/ui/assets/{Settings-26SF-okR.js.map → Settings-Hii-5oku.js.map} +1 -1
- package/dist/web/ui/assets/Skills-BHJp2CgD.js +17 -0
- package/dist/web/ui/assets/Skills-BHJp2CgD.js.map +1 -0
- package/dist/web/ui/assets/{Tasks-DbwRozzx.js → Tasks-D36pqkro.js} +2 -2
- package/dist/web/ui/assets/{Tasks-DbwRozzx.js.map → Tasks-D36pqkro.js.map} +1 -1
- package/dist/web/ui/assets/{Usage-i_q6Ri4s.js → Usage-CmjaYrsT.js} +2 -2
- package/dist/web/ui/assets/{Usage-i_q6Ri4s.js.map → Usage-CmjaYrsT.js.map} +1 -1
- package/dist/web/ui/assets/{Workspace-ZR5syf-9.js → Workspace-BYLf-wTJ.js} +2 -2
- package/dist/web/ui/assets/{Workspace-ZR5syf-9.js.map → Workspace-BYLf-wTJ.js.map} +1 -1
- package/dist/web/ui/assets/{activity-CIP1IzSg.js → activity-MOTqH8zM.js} +2 -2
- package/dist/web/ui/assets/{activity-CIP1IzSg.js.map → activity-MOTqH8zM.js.map} +1 -1
- package/dist/web/ui/assets/{alert-dialog-CW-j2nG4.js → alert-dialog-MbYSbZx5.js} +2 -2
- package/dist/web/ui/assets/{alert-dialog-CW-j2nG4.js.map → alert-dialog-MbYSbZx5.js.map} +1 -1
- package/dist/web/ui/assets/{arrow-left-D2YO-iMS.js → arrow-left-CtqQsBC6.js} +2 -2
- package/dist/web/ui/assets/{arrow-left-D2YO-iMS.js.map → arrow-left-CtqQsBC6.js.map} +1 -1
- package/dist/web/ui/assets/{avatar-BLsf3GhK.js → avatar-BIYaY7pR.js} +2 -2
- package/dist/web/ui/assets/{avatar-BLsf3GhK.js.map → avatar-BIYaY7pR.js.map} +1 -1
- package/dist/web/ui/assets/{badge-DfDJNUtd.js → badge-CUJiWF1y.js} +2 -2
- package/dist/web/ui/assets/{badge-DfDJNUtd.js.map → badge-CUJiWF1y.js.map} +1 -1
- package/dist/web/ui/assets/{button-TaFPR-zy.js → button-CNasMlFE.js} +2 -2
- package/dist/web/ui/assets/{button-TaFPR-zy.js.map → button-CNasMlFE.js.map} +1 -1
- package/dist/web/ui/assets/{card-DAYo4Zl5.js → card-BdsEOP7t.js} +2 -2
- package/dist/web/ui/assets/{card-DAYo4Zl5.js.map → card-BdsEOP7t.js.map} +1 -1
- package/dist/web/ui/assets/{chevron-down-CQi0yuay.js → chevron-down-CB9J_vvZ.js} +2 -2
- package/dist/web/ui/assets/{chevron-down-CQi0yuay.js.map → chevron-down-CB9J_vvZ.js.map} +1 -1
- package/dist/web/ui/assets/{circle-check-DweDcOkA.js → circle-check-DvGSe1uZ.js} +2 -2
- package/dist/web/ui/assets/{circle-check-DweDcOkA.js.map → circle-check-DvGSe1uZ.js.map} +1 -1
- package/dist/web/ui/assets/{circle-x-BmL20etA.js → circle-x-CyaGJ_BM.js} +2 -2
- package/dist/web/ui/assets/{circle-x-BmL20etA.js.map → circle-x-CyaGJ_BM.js.map} +1 -1
- package/dist/web/ui/assets/{dialog-DovgkMhT.js → dialog-Bd1rELXb.js} +2 -2
- package/dist/web/ui/assets/{dialog-DovgkMhT.js.map → dialog-Bd1rELXb.js.map} +1 -1
- package/dist/web/ui/assets/{download-_QBatDio.js → download-C8RvlFqO.js} +2 -2
- package/dist/web/ui/assets/{download-_QBatDio.js.map → download-C8RvlFqO.js.map} +1 -1
- package/dist/web/ui/assets/{eye-Wpgtfmgw.js → eye-BJ0NucMz.js} +2 -2
- package/dist/web/ui/assets/{eye-Wpgtfmgw.js.map → eye-BJ0NucMz.js.map} +1 -1
- package/dist/web/ui/assets/{file-text-2EGFNyc1.js → file-text-BWWBuD_N.js} +2 -2
- package/dist/web/ui/assets/{file-text-2EGFNyc1.js.map → file-text-BWWBuD_N.js.map} +1 -1
- package/dist/web/ui/assets/{folder-open-C-OiZn9P.js → folder-open-BwjemFy7.js} +2 -2
- package/dist/web/ui/assets/{folder-open-C-OiZn9P.js.map → folder-open-BwjemFy7.js.map} +1 -1
- package/dist/web/ui/assets/{git-branch-BT9gCKgG.js → git-branch-D9JVASpC.js} +2 -2
- package/dist/web/ui/assets/{git-branch-BT9gCKgG.js.map → git-branch-D9JVASpC.js.map} +1 -1
- package/dist/web/ui/assets/{index-BhxU0YlT.js → index-C3YiF4qv.js} +6 -6
- package/dist/web/ui/assets/index-C3YiF4qv.js.map +1 -0
- package/dist/web/ui/assets/{index-CUT6Fr2C.js → index-CaqLZNof.js} +2 -2
- package/dist/web/ui/assets/{index-CUT6Fr2C.js.map → index-CaqLZNof.js.map} +1 -1
- package/dist/web/ui/assets/index-CuhiuVab.css +1 -0
- package/dist/web/ui/assets/{input-L1uz5xAQ.js → input-CH3dmo9r.js} +2 -2
- package/dist/web/ui/assets/{input-L1uz5xAQ.js.map → input-CH3dmo9r.js.map} +1 -1
- package/dist/web/ui/assets/{loader-circle-BTFgt3hG.js → loader-circle-DbYKk0_Q.js} +2 -2
- package/dist/web/ui/assets/{loader-circle-BTFgt3hG.js.map → loader-circle-DbYKk0_Q.js.map} +1 -1
- package/dist/web/ui/assets/{pencil-uxK07iYy.js → pencil-gNDEMhav.js} +2 -2
- package/dist/web/ui/assets/{pencil-uxK07iYy.js.map → pencil-gNDEMhav.js.map} +1 -1
- package/dist/web/ui/assets/{plus-DcWFYr4m.js → plus-7rbHkByr.js} +2 -2
- package/dist/web/ui/assets/{plus-DcWFYr4m.js.map → plus-7rbHkByr.js.map} +1 -1
- package/dist/web/ui/assets/{power-DVIqVIMj.js → power-BS7gCDWs.js} +2 -2
- package/dist/web/ui/assets/{power-DVIqVIMj.js.map → power-BS7gCDWs.js.map} +1 -1
- package/dist/web/ui/assets/{progress-DMwOdxli.js → progress-ZzhsBV2v.js} +2 -2
- package/dist/web/ui/assets/{progress-DMwOdxli.js.map → progress-ZzhsBV2v.js.map} +1 -1
- package/dist/web/ui/assets/{search-D1OOxb1X.js → search-BZsbhO0B.js} +2 -2
- package/dist/web/ui/assets/{search-D1OOxb1X.js.map → search-BZsbhO0B.js.map} +1 -1
- package/dist/web/ui/assets/{select-Dnx_bUgy.js → select-vRSgBrHz.js} +2 -2
- package/dist/web/ui/assets/{select-Dnx_bUgy.js.map → select-vRSgBrHz.js.map} +1 -1
- package/dist/web/ui/assets/{send-D4uxqmyH.js → send-BkyTIUtJ.js} +2 -2
- package/dist/web/ui/assets/{send-D4uxqmyH.js.map → send-BkyTIUtJ.js.map} +1 -1
- package/dist/web/ui/assets/{sparkles-DLSJA4xU.js → sparkles-DcP24GEL.js} +2 -2
- package/dist/web/ui/assets/{sparkles-DLSJA4xU.js.map → sparkles-DcP24GEL.js.map} +1 -1
- package/dist/web/ui/assets/{switch-CvDDbCUA.js → switch-LRN9wWy2.js} +2 -2
- package/dist/web/ui/assets/{switch-CvDDbCUA.js.map → switch-LRN9wWy2.js.map} +1 -1
- package/dist/web/ui/assets/{terminal-DI3J3W_z.js → terminal-CWG62zdD.js} +2 -2
- package/dist/web/ui/assets/{terminal-DI3J3W_z.js.map → terminal-CWG62zdD.js.map} +1 -1
- package/dist/web/ui/assets/{textarea-CXLsr8tf.js → textarea-CXh3tmJ1.js} +2 -2
- package/dist/web/ui/assets/{textarea-CXLsr8tf.js.map → textarea-CXh3tmJ1.js.map} +1 -1
- package/dist/web/ui/assets/{zap-C-0oH5gt.js → zap-BEfqVtvZ.js} +2 -2
- package/dist/web/ui/assets/{zap-C-0oH5gt.js.map → zap-BEfqVtvZ.js.map} +1 -1
- package/dist/web/ui/index.html +2 -2
- package/package.json +9 -4
- package/dist/web/ui/assets/Skills-DANyYK_d.js +0 -7
- package/dist/web/ui/assets/Skills-DANyYK_d.js.map +0 -1
- package/dist/web/ui/assets/index-BhxU0YlT.js.map +0 -1
- package/dist/web/ui/assets/index-DOw1nKre.css +0 -1
- package/dist/web/ui/sw.js.map +0 -1
- package/dist/web/ui/workbox-0bb07689.js +0 -3
- package/dist/web/ui/workbox-0bb07689.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PersonDetail-iZgApJog.js","sources":["../../src/pages/brain/PersonDetail.tsx"],"sourcesContent":["import { useCallback, useEffect, useState } from \"react\";\nimport { Link, useParams } from \"react-router-dom\";\nimport { motion } from \"framer-motion\";\nimport { ArrowLeft, Brain, Clock, UserCircle } from \"lucide-react\";\nimport api, { type Person, type Memory } from \"@/lib/api\";\nimport { cn, formatDate } from \"@/lib/utils\";\nimport { Card, CardContent } from \"@/components/ui/card\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { Avatar, AvatarFallback } from \"@/components/ui/avatar\";\n\n// ── Animation ──\n\nconst fadeIn = {\n hidden: { opacity: 0, y: 10 },\n show: { opacity: 1, y: 0, transition: { duration: 0.35, ease: \"easeOut\" as const } },\n};\n\nconst stagger = {\n hidden: {},\n show: { transition: { staggerChildren: 0.03 } },\n};\n\nconst listItem = {\n hidden: { opacity: 0, x: -8 },\n show: { opacity: 1, x: 0, transition: { duration: 0.25 } },\n};\n\n// ── Skeleton ──\n\nfunction DetailSkeleton() {\n return (\n <div className=\"space-y-6 p-6 animate-pulse\">\n <div className=\"h-4 w-32 rounded bg-muted\" />\n <div className=\"flex items-center gap-4\">\n <div className=\"h-16 w-16 rounded-full bg-muted\" />\n <div className=\"space-y-2\">\n <div className=\"h-6 w-40 rounded bg-muted\" />\n <div className=\"h-4 w-20 rounded bg-muted\" />\n </div>\n </div>\n <div className=\"space-y-2\">\n <div className=\"h-4 w-full rounded bg-muted\" />\n <div className=\"h-4 w-3/4 rounded bg-muted\" />\n </div>\n <div className=\"flex gap-2\">\n <div className=\"h-5 w-16 rounded bg-muted\" />\n <div className=\"h-5 w-14 rounded bg-muted\" />\n <div className=\"h-5 w-18 rounded bg-muted\" />\n </div>\n <div className=\"h-5 w-28 rounded bg-muted mt-8\" />\n {Array.from({ length: 4 }).map((_, i) => (\n <div key={i} className=\"rounded-lg border border-border p-4 space-y-2\">\n <div className=\"h-4 w-full rounded bg-muted\" />\n <div className=\"h-3 w-24 rounded bg-muted\" />\n </div>\n ))}\n </div>\n );\n}\n\n// ── Type badge color mapping ──\n\nfunction typeBadgeVariant(\n type: string\n): \"default\" | \"secondary\" | \"success\" | \"warning\" | \"outline\" {\n switch (type) {\n case \"fact\":\n return \"default\";\n case \"preference\":\n return \"success\";\n case \"observation\":\n return \"warning\";\n default:\n return \"secondary\";\n }\n}\n\n// ── Page ──\n\nexport function PersonDetailPage() {\n const { id } = useParams<{ id: string }>();\n const [person, setPerson] = useState<Person | null>(null);\n const [memories, setMemories] = useState<Memory[]>([]);\n const [memoryTotal, setMemoryTotal] = useState(0);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n const fetchData = useCallback(async () => {\n if (!id) return;\n try {\n setError(null);\n setLoading(true);\n const [personRes, memoriesRes] = await Promise.all([\n api.brain.persons.get(id),\n api.brain.persons.memories(id, 50),\n ]);\n setPerson(personRes.person);\n setMemories(memoriesRes.memories);\n setMemoryTotal(memoriesRes.total);\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Failed to load person\");\n } finally {\n setLoading(false);\n }\n }, [id]);\n\n useEffect(() => {\n fetchData();\n }, [fetchData]);\n\n if (loading) return <DetailSkeleton />;\n\n if (error || !person) {\n return (\n <div className=\"space-y-6 p-6\">\n <Link\n to=\"/second-brain/persons\"\n className=\"inline-flex items-center gap-1.5 text-sm text-muted-foreground hover:text-foreground transition-colors\"\n >\n <ArrowLeft className=\"h-4 w-4\" />\n Back to Persons\n </Link>\n <Card>\n <CardContent className=\"flex flex-col items-center gap-3 py-12 text-center text-muted-foreground\">\n <UserCircle className=\"h-10 w-10\" />\n <div>\n <p className=\"font-medium text-foreground\">Person not found</p>\n <p className=\"text-sm\">\n {error || \"This person doesn't exist or has been removed.\"}\n </p>\n </div>\n <Link\n to=\"/second-brain/persons\"\n className=\"mt-2 text-sm text-[#00d4ff] hover:underline\"\n >\n Return to directory\n </Link>\n </CardContent>\n </Card>\n </div>\n );\n }\n\n return (\n <div className=\"space-y-8 p-6\">\n {/* Back */}\n <motion.div variants={fadeIn} initial=\"hidden\" animate=\"show\">\n <Link\n to=\"/second-brain/persons\"\n className=\"inline-flex items-center gap-1.5 text-sm text-muted-foreground hover:text-foreground transition-colors\"\n >\n <ArrowLeft className=\"h-4 w-4\" />\n Back to Persons\n </Link>\n </motion.div>\n\n {/* Person header */}\n <motion.div\n className=\"space-y-4\"\n variants={fadeIn}\n initial=\"hidden\"\n animate=\"show\"\n >\n <div className=\"flex items-center gap-4\">\n <Avatar className=\"h-16 w-16\">\n <AvatarFallback className=\"bg-[#00d4ff]/10 text-[#00d4ff] text-xl font-semibold\">\n {person.name.charAt(0).toUpperCase()}\n </AvatarFallback>\n </Avatar>\n <div>\n <h1 className=\"text-2xl font-bold text-foreground\">\n {person.name}\n </h1>\n {person.relationship && (\n <Badge variant=\"secondary\" className=\"mt-1 capitalize\">\n {person.relationship}\n </Badge>\n )}\n </div>\n </div>\n\n {person.summary && (\n <p className=\"max-w-2xl text-sm leading-relaxed text-muted-foreground\">\n {person.summary}\n </p>\n )}\n\n {person.traits && person.traits.length > 0 && (\n <div className=\"flex flex-wrap gap-1.5\">\n {person.traits.map((trait) => (\n <Badge key={trait} variant=\"outline\" className=\"text-xs\">\n {trait}\n </Badge>\n ))}\n </div>\n )}\n </motion.div>\n\n {/* Memories */}\n <motion.div\n className=\"space-y-4\"\n variants={fadeIn}\n initial=\"hidden\"\n animate=\"show\"\n transition={{ delay: 0.1 }}\n >\n <div className=\"flex items-center gap-2\">\n <Brain className=\"h-5 w-5 text-[#00d4ff]\" />\n <h2 className=\"text-lg font-semibold text-foreground\">\n Memories\n <span className=\"ml-1.5 text-sm font-normal text-muted-foreground\">\n ({memoryTotal})\n </span>\n </h2>\n </div>\n\n {memories.length === 0 ? (\n <Card>\n <CardContent className=\"py-8 text-center text-sm text-muted-foreground\">\n No memories associated with this person yet.\n </CardContent>\n </Card>\n ) : (\n <motion.div\n className=\"space-y-2\"\n variants={stagger}\n initial=\"hidden\"\n animate=\"show\"\n >\n {memories.map((memory) => (\n <motion.div key={memory.id} variants={listItem}>\n <Card\n className={cn(\n \"transition-colors hover:border-[#00d4ff]/20\"\n )}\n >\n <CardContent className=\"flex items-start gap-3 p-4\">\n <Badge\n variant={typeBadgeVariant(memory.type)}\n className=\"mt-0.5 shrink-0 text-[10px] capitalize\"\n >\n {memory.type}\n </Badge>\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm text-foreground\">\n {memory.summary}\n </p>\n <span className=\"mt-1 flex items-center gap-1 text-xs text-muted-foreground\">\n <Clock className=\"h-3 w-3\" />\n {formatDate(memory.createdAt)}\n </span>\n </div>\n </CardContent>\n </Card>\n </motion.div>\n ))}\n </motion.div>\n )}\n </motion.div>\n </div>\n );\n}\n"],"names":["fadeIn","stagger","listItem","DetailSkeleton","jsxs","jsx","_","i","typeBadgeVariant","type","PersonDetailPage","id","useParams","person","setPerson","useState","memories","setMemories","memoryTotal","setMemoryTotal","loading","setLoading","error","setError","fetchData","useCallback","personRes","memoriesRes","api","err","useEffect","Link","ArrowLeft","Card","CardContent","UserCircle","motion","Avatar","AvatarFallback","Badge","trait","Brain","memory","cn","Clock","formatDate"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PersonDetail-Ca8B9io8.js","sources":["../../src/pages/brain/PersonDetail.tsx"],"sourcesContent":["import { useCallback, useEffect, useState } from \"react\";\nimport { Link, useParams } from \"react-router-dom\";\nimport { motion } from \"framer-motion\";\nimport { ArrowLeft, Brain, Clock, UserCircle } from \"lucide-react\";\nimport api, { type Person, type Memory } from \"@/lib/api\";\nimport { cn, formatDate } from \"@/lib/utils\";\nimport { Card, CardContent } from \"@/components/ui/card\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { Avatar, AvatarFallback } from \"@/components/ui/avatar\";\n\n// ── Animation ──\n\nconst fadeIn = {\n hidden: { opacity: 0, y: 10 },\n show: { opacity: 1, y: 0, transition: { duration: 0.35, ease: \"easeOut\" as const } },\n};\n\nconst stagger = {\n hidden: {},\n show: { transition: { staggerChildren: 0.03 } },\n};\n\nconst listItem = {\n hidden: { opacity: 0, x: -8 },\n show: { opacity: 1, x: 0, transition: { duration: 0.25 } },\n};\n\n// ── Skeleton ──\n\nfunction DetailSkeleton() {\n return (\n <div className=\"space-y-6 p-6 animate-pulse\">\n <div className=\"h-4 w-32 rounded bg-muted\" />\n <div className=\"flex items-center gap-4\">\n <div className=\"h-16 w-16 rounded-full bg-muted\" />\n <div className=\"space-y-2\">\n <div className=\"h-6 w-40 rounded bg-muted\" />\n <div className=\"h-4 w-20 rounded bg-muted\" />\n </div>\n </div>\n <div className=\"space-y-2\">\n <div className=\"h-4 w-full rounded bg-muted\" />\n <div className=\"h-4 w-3/4 rounded bg-muted\" />\n </div>\n <div className=\"flex gap-2\">\n <div className=\"h-5 w-16 rounded bg-muted\" />\n <div className=\"h-5 w-14 rounded bg-muted\" />\n <div className=\"h-5 w-18 rounded bg-muted\" />\n </div>\n <div className=\"h-5 w-28 rounded bg-muted mt-8\" />\n {Array.from({ length: 4 }).map((_, i) => (\n <div key={i} className=\"rounded-lg border border-border p-4 space-y-2\">\n <div className=\"h-4 w-full rounded bg-muted\" />\n <div className=\"h-3 w-24 rounded bg-muted\" />\n </div>\n ))}\n </div>\n );\n}\n\n// ── Type badge color mapping ──\n\nfunction typeBadgeVariant(\n type: string\n): \"default\" | \"secondary\" | \"success\" | \"warning\" | \"outline\" {\n switch (type) {\n case \"fact\":\n return \"default\";\n case \"preference\":\n return \"success\";\n case \"observation\":\n return \"warning\";\n default:\n return \"secondary\";\n }\n}\n\n// ── Page ──\n\nexport function PersonDetailPage() {\n const { id } = useParams<{ id: string }>();\n const [person, setPerson] = useState<Person | null>(null);\n const [memories, setMemories] = useState<Memory[]>([]);\n const [memoryTotal, setMemoryTotal] = useState(0);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n const fetchData = useCallback(async () => {\n if (!id) return;\n try {\n setError(null);\n setLoading(true);\n const [personRes, memoriesRes] = await Promise.all([\n api.brain.persons.get(id),\n api.brain.persons.memories(id, 50),\n ]);\n setPerson(personRes.person);\n setMemories(memoriesRes.memories);\n setMemoryTotal(memoriesRes.total);\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Failed to load person\");\n } finally {\n setLoading(false);\n }\n }, [id]);\n\n useEffect(() => {\n fetchData();\n }, [fetchData]);\n\n if (loading) return <DetailSkeleton />;\n\n if (error || !person) {\n return (\n <div className=\"space-y-6 p-6\">\n <Link\n to=\"/second-brain/persons\"\n className=\"inline-flex items-center gap-1.5 text-sm text-muted-foreground hover:text-foreground transition-colors\"\n >\n <ArrowLeft className=\"h-4 w-4\" />\n Back to Persons\n </Link>\n <Card>\n <CardContent className=\"flex flex-col items-center gap-3 py-12 text-center text-muted-foreground\">\n <UserCircle className=\"h-10 w-10\" />\n <div>\n <p className=\"font-medium text-foreground\">Person not found</p>\n <p className=\"text-sm\">\n {error || \"This person doesn't exist or has been removed.\"}\n </p>\n </div>\n <Link\n to=\"/second-brain/persons\"\n className=\"mt-2 text-sm text-[#00d4ff] hover:underline\"\n >\n Return to directory\n </Link>\n </CardContent>\n </Card>\n </div>\n );\n }\n\n return (\n <div className=\"space-y-8 p-6\">\n {/* Back */}\n <motion.div variants={fadeIn} initial=\"hidden\" animate=\"show\">\n <Link\n to=\"/second-brain/persons\"\n className=\"inline-flex items-center gap-1.5 text-sm text-muted-foreground hover:text-foreground transition-colors\"\n >\n <ArrowLeft className=\"h-4 w-4\" />\n Back to Persons\n </Link>\n </motion.div>\n\n {/* Person header */}\n <motion.div\n className=\"space-y-4\"\n variants={fadeIn}\n initial=\"hidden\"\n animate=\"show\"\n >\n <div className=\"flex items-center gap-4\">\n <Avatar className=\"h-16 w-16\">\n <AvatarFallback className=\"bg-[#00d4ff]/10 text-[#00d4ff] text-xl font-semibold\">\n {person.name.charAt(0).toUpperCase()}\n </AvatarFallback>\n </Avatar>\n <div>\n <h1 className=\"text-2xl font-bold text-foreground\">\n {person.name}\n </h1>\n {person.relationship && (\n <Badge variant=\"secondary\" className=\"mt-1 capitalize\">\n {person.relationship}\n </Badge>\n )}\n </div>\n </div>\n\n {person.summary && (\n <p className=\"max-w-2xl text-sm leading-relaxed text-muted-foreground\">\n {person.summary}\n </p>\n )}\n\n {person.traits && person.traits.length > 0 && (\n <div className=\"flex flex-wrap gap-1.5\">\n {person.traits.map((trait) => (\n <Badge key={trait} variant=\"outline\" className=\"text-xs\">\n {trait}\n </Badge>\n ))}\n </div>\n )}\n </motion.div>\n\n {/* Memories */}\n <motion.div\n className=\"space-y-4\"\n variants={fadeIn}\n initial=\"hidden\"\n animate=\"show\"\n transition={{ delay: 0.1 }}\n >\n <div className=\"flex items-center gap-2\">\n <Brain className=\"h-5 w-5 text-[#00d4ff]\" />\n <h2 className=\"text-lg font-semibold text-foreground\">\n Memories\n <span className=\"ml-1.5 text-sm font-normal text-muted-foreground\">\n ({memoryTotal})\n </span>\n </h2>\n </div>\n\n {memories.length === 0 ? (\n <Card>\n <CardContent className=\"py-8 text-center text-sm text-muted-foreground\">\n No memories associated with this person yet.\n </CardContent>\n </Card>\n ) : (\n <motion.div\n className=\"space-y-2\"\n variants={stagger}\n initial=\"hidden\"\n animate=\"show\"\n >\n {memories.map((memory) => (\n <motion.div key={memory.id} variants={listItem}>\n <Card\n className={cn(\n \"transition-colors hover:border-[#00d4ff]/20\"\n )}\n >\n <CardContent className=\"flex items-start gap-3 p-4\">\n <Badge\n variant={typeBadgeVariant(memory.type)}\n className=\"mt-0.5 shrink-0 text-[10px] capitalize\"\n >\n {memory.type}\n </Badge>\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm text-foreground\">\n {memory.summary}\n </p>\n <span className=\"mt-1 flex items-center gap-1 text-xs text-muted-foreground\">\n <Clock className=\"h-3 w-3\" />\n {formatDate(memory.createdAt)}\n </span>\n </div>\n </CardContent>\n </Card>\n </motion.div>\n ))}\n </motion.div>\n )}\n </motion.div>\n </div>\n );\n}\n"],"names":["fadeIn","stagger","listItem","DetailSkeleton","jsxs","jsx","_","i","typeBadgeVariant","type","PersonDetailPage","id","useParams","person","setPerson","useState","memories","setMemories","memoryTotal","setMemoryTotal","loading","setLoading","error","setError","fetchData","useCallback","personRes","memoriesRes","api","err","useEffect","Link","ArrowLeft","Card","CardContent","UserCircle","motion","Avatar","AvatarFallback","Badge","trait","Brain","memory","cn","Clock","formatDate"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{j as e,m as f}from"./vendor-motion-Dwx3-JO5.js";import{r as t,L as y}from"./vendor-react-C7pctHW3.js";import{a as w,U as C,B as S,c as P}from"./index-
|
|
2
|
-
//# sourceMappingURL=Persons-
|
|
1
|
+
import{j as e,m as f}from"./vendor-motion-Dwx3-JO5.js";import{r as t,L as y}from"./vendor-react-C7pctHW3.js";import{a as w,U as C,B as S,c as P}from"./index-C3YiF4qv.js";import{I as k}from"./input-CH3dmo9r.js";import{C as c,c as o}from"./card-BdsEOP7t.js";import{B as p}from"./badge-CUJiWF1y.js";import{C as A,A as E,a as B}from"./avatar-BIYaY7pR.js";import{S as T}from"./search-BZsbhO0B.js";import"./vendor-syntax-xZUI6Op9.js";import"./vendor-radix-3UdfCgs_.js";import"./index-CaqLZNof.js";function U(){return e.jsxs("div",{className:"rounded-xl border border-border bg-card p-5 animate-pulse",children:[e.jsxs("div",{className:"flex items-center gap-3 mb-3",children:[e.jsx("div",{className:"h-11 w-11 rounded-full bg-muted"}),e.jsxs("div",{className:"flex-1 space-y-2",children:[e.jsx("div",{className:"h-4 w-28 rounded bg-muted"}),e.jsx("div",{className:"h-3 w-16 rounded bg-muted"})]})]}),e.jsxs("div",{className:"space-y-2 mb-3",children:[e.jsx("div",{className:"h-3 w-full rounded bg-muted"}),e.jsx("div",{className:"h-3 w-3/4 rounded bg-muted"})]}),e.jsxs("div",{className:"flex gap-1.5",children:[e.jsx("div",{className:"h-5 w-14 rounded bg-muted"}),e.jsx("div",{className:"h-5 w-12 rounded bg-muted"})]})]})}const L={hidden:{},show:{transition:{staggerChildren:.04}}},R={hidden:{opacity:0,y:12},show:{opacity:1,y:0,transition:{duration:.3,ease:"easeOut"}}};function H(){const[n,g]=t.useState([]),[j,N]=t.useState(0),[m,v]=t.useState(""),[r,x]=t.useState(!0),[l,u]=t.useState(null),i=t.useRef(null),d=t.useCallback(async s=>{try{u(null),x(!0);const a=await w.brain.persons.list({q:s||void 0,limit:200});g(a.persons),N(a.total)}catch(a){u(a instanceof Error?a.message:"Failed to load persons")}finally{x(!1)}},[]);t.useEffect(()=>{d("")},[d]);const b=s=>{v(s),i.current&&clearTimeout(i.current),i.current=setTimeout(()=>d(s),300)};return e.jsxs("div",{className:"space-y-6 p-6",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center gap-2.5",children:[e.jsx(C,{className:"h-6 w-6 text-[#00d4ff]"}),e.jsxs("h1",{className:"text-2xl font-semibold text-foreground",children:["Persons",!r&&e.jsxs("span",{className:"ml-2 text-base font-normal text-muted-foreground",children:["(",j,")"]})]})]}),e.jsx("p",{className:"mt-1 text-sm text-muted-foreground",children:"People Mercury knows about"})]}),e.jsxs("div",{className:"relative max-w-md",children:[e.jsx(T,{className:"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground"}),e.jsx(k,{placeholder:"Search by name...",value:m,onChange:s=>b(s.target.value),className:"pl-9"})]}),l&&e.jsx(c,{children:e.jsx(o,{className:"py-8 text-center text-destructive",children:l})}),r&&e.jsx("div",{className:"grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3",children:Array.from({length:6}).map((s,a)=>e.jsx(U,{},a))}),!r&&!l&&n.length===0&&e.jsx(c,{children:e.jsxs(o,{className:"flex flex-col items-center gap-3 py-12 text-center text-muted-foreground",children:[e.jsx(A,{className:"h-10 w-10"}),e.jsxs("div",{children:[e.jsx("p",{className:"font-medium text-foreground",children:"No persons found"}),e.jsx("p",{className:"text-sm",children:m?"Try a different search term.":"Mercury hasn't recorded any people yet."})]})]})}),!r&&!l&&n.length>0&&e.jsx(f.div,{className:"grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3",variants:L,initial:"hidden",animate:"show",children:n.map(s=>{var a;return e.jsx(f.div,{variants:R,children:e.jsx(y,{to:`/second-brain/persons/${s.id}`,className:"block",children:e.jsx(c,{className:P("cursor-pointer transition-all duration-200","hover:-translate-y-0.5 hover:shadow-lg hover:border-[#00d4ff]/30"),children:e.jsxs(o,{className:"p-5",children:[e.jsxs("div",{className:"flex items-center gap-3 mb-3",children:[e.jsx(E,{className:"h-11 w-11",children:e.jsx(B,{className:"bg-[#00d4ff]/10 text-[#00d4ff] font-semibold text-sm",children:s.name.charAt(0).toUpperCase()})}),e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsx("p",{className:"truncate text-base font-semibold text-foreground",children:s.name}),s.relationship&&e.jsx(p,{variant:"secondary",className:"mt-0.5 text-[10px] capitalize",children:s.relationship})]})]}),s.summary&&e.jsx("p",{className:"mb-3 line-clamp-2 text-sm text-muted-foreground",children:s.summary}),e.jsxs("div",{className:"flex flex-wrap items-center gap-1.5",children:[(a=s.traits)==null?void 0:a.slice(0,4).map(h=>e.jsx(p,{variant:"outline",className:"text-[10px]",children:h},h)),s.memoryCount!=null&&s.memoryCount>0&&e.jsxs("span",{className:"ml-auto flex items-center gap-1 text-xs text-muted-foreground",children:[e.jsx(S,{className:"h-3 w-3"}),s.memoryCount," memories"]})]})]})})})},s.id)})})]})}export{H as PersonsPage};
|
|
2
|
+
//# sourceMappingURL=Persons-epdmUeBM.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Persons-Bs_HhYjC.js","sources":["../../src/pages/brain/Persons.tsx"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { Link } from \"react-router-dom\";\nimport { motion } from \"framer-motion\";\nimport { Search, Users, UserCircle, Brain } from \"lucide-react\";\nimport api, { type Person } from \"@/lib/api\";\nimport { cn } from \"@/lib/utils\";\nimport { Input } from \"@/components/ui/input\";\nimport { Card, CardContent } from \"@/components/ui/card\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { Avatar, AvatarFallback } from \"@/components/ui/avatar\";\n\n// ── Skeleton ──\n\nfunction PersonCardSkeleton() {\n return (\n <div className=\"rounded-xl border border-border bg-card p-5 animate-pulse\">\n <div className=\"flex items-center gap-3 mb-3\">\n <div className=\"h-11 w-11 rounded-full bg-muted\" />\n <div className=\"flex-1 space-y-2\">\n <div className=\"h-4 w-28 rounded bg-muted\" />\n <div className=\"h-3 w-16 rounded bg-muted\" />\n </div>\n </div>\n <div className=\"space-y-2 mb-3\">\n <div className=\"h-3 w-full rounded bg-muted\" />\n <div className=\"h-3 w-3/4 rounded bg-muted\" />\n </div>\n <div className=\"flex gap-1.5\">\n <div className=\"h-5 w-14 rounded bg-muted\" />\n <div className=\"h-5 w-12 rounded bg-muted\" />\n </div>\n </div>\n );\n}\n\n// ── Animation variants ──\n\nconst container = {\n hidden: {},\n show: {\n transition: { staggerChildren: 0.04 },\n },\n};\n\nconst item = {\n hidden: { opacity: 0, y: 12 },\n show: { opacity: 1, y: 0, transition: { duration: 0.3, ease: \"easeOut\" as const } },\n};\n\n// ── Page ──\n\nexport function PersonsPage() {\n const [persons, setPersons] = useState<Person[]>([]);\n const [total, setTotal] = useState(0);\n const [query, setQuery] = useState(\"\");\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const fetchPersons = useCallback(async (q: string) => {\n try {\n setError(null);\n setLoading(true);\n const res = await api.brain.persons.list({\n q: q || undefined,\n limit: 200,\n });\n setPersons(res.persons);\n setTotal(res.total);\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Failed to load persons\");\n } finally {\n setLoading(false);\n }\n }, []);\n\n useEffect(() => {\n fetchPersons(\"\");\n }, [fetchPersons]);\n\n const handleSearch = (value: string) => {\n setQuery(value);\n if (debounceRef.current) clearTimeout(debounceRef.current);\n debounceRef.current = setTimeout(() => fetchPersons(value), 300);\n };\n\n return (\n <div className=\"space-y-6 p-6\">\n {/* Header */}\n <div>\n <div className=\"flex items-center gap-2.5\">\n <Users className=\"h-6 w-6 text-[#00d4ff]\" />\n <h1 className=\"text-2xl font-semibold text-foreground\">\n Persons\n {!loading && (\n <span className=\"ml-2 text-base font-normal text-muted-foreground\">\n ({total})\n </span>\n )}\n </h1>\n </div>\n <p className=\"mt-1 text-sm text-muted-foreground\">\n People Mercury knows about\n </p>\n </div>\n\n {/* Search */}\n <div className=\"relative max-w-md\">\n <Search className=\"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground\" />\n <Input\n placeholder=\"Search by name...\"\n value={query}\n onChange={(e) => handleSearch(e.target.value)}\n className=\"pl-9\"\n />\n </div>\n\n {/* Error */}\n {error && (\n <Card>\n <CardContent className=\"py-8 text-center text-destructive\">\n {error}\n </CardContent>\n </Card>\n )}\n\n {/* Loading */}\n {loading && (\n <div className=\"grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3\">\n {Array.from({ length: 6 }).map((_, i) => (\n <PersonCardSkeleton key={i} />\n ))}\n </div>\n )}\n\n {/* Empty */}\n {!loading && !error && persons.length === 0 && (\n <Card>\n <CardContent className=\"flex flex-col items-center gap-3 py-12 text-center text-muted-foreground\">\n <UserCircle className=\"h-10 w-10\" />\n <div>\n <p className=\"font-medium text-foreground\">No persons found</p>\n <p className=\"text-sm\">\n {query\n ? \"Try a different search term.\"\n : \"Mercury hasn't recorded any people yet.\"}\n </p>\n </div>\n </CardContent>\n </Card>\n )}\n\n {/* Grid */}\n {!loading && !error && persons.length > 0 && (\n <motion.div\n className=\"grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3\"\n variants={container}\n initial=\"hidden\"\n animate=\"show\"\n >\n {persons.map((person) => (\n <motion.div key={person.id} variants={item}>\n <Link\n to={`/second-brain/persons/${person.id}`}\n className=\"block\"\n >\n <Card\n className={cn(\n \"cursor-pointer transition-all duration-200\",\n \"hover:-translate-y-0.5 hover:shadow-lg hover:border-[#00d4ff]/30\"\n )}\n >\n <CardContent className=\"p-5\">\n {/* Avatar + name */}\n <div className=\"flex items-center gap-3 mb-3\">\n <Avatar className=\"h-11 w-11\">\n <AvatarFallback className=\"bg-[#00d4ff]/10 text-[#00d4ff] font-semibold text-sm\">\n {person.name.charAt(0).toUpperCase()}\n </AvatarFallback>\n </Avatar>\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-base font-semibold text-foreground\">\n {person.name}\n </p>\n {person.relationship && (\n <Badge\n variant=\"secondary\"\n className=\"mt-0.5 text-[10px] capitalize\"\n >\n {person.relationship}\n </Badge>\n )}\n </div>\n </div>\n\n {/* Summary */}\n {person.summary && (\n <p className=\"mb-3 line-clamp-2 text-sm text-muted-foreground\">\n {person.summary}\n </p>\n )}\n\n {/* Footer: traits + memory count */}\n <div className=\"flex flex-wrap items-center gap-1.5\">\n {person.traits?.slice(0, 4).map((trait) => (\n <Badge\n key={trait}\n variant=\"outline\"\n className=\"text-[10px]\"\n >\n {trait}\n </Badge>\n ))}\n {person.memoryCount != null && person.memoryCount > 0 && (\n <span className=\"ml-auto flex items-center gap-1 text-xs text-muted-foreground\">\n <Brain className=\"h-3 w-3\" />\n {person.memoryCount} memories\n </span>\n )}\n </div>\n </CardContent>\n </Card>\n </Link>\n </motion.div>\n ))}\n </motion.div>\n )}\n </div>\n );\n}\n"],"names":["PersonCardSkeleton","jsxs","jsx","container","item","PersonsPage","persons","setPersons","useState","total","setTotal","query","setQuery","loading","setLoading","error","setError","debounceRef","useRef","fetchPersons","useCallback","q","res","api","err","useEffect","handleSearch","value","Users","Search","Input","e","Card","CardContent","_","i","UserCircle","motion","person","Link","cn","Avatar","AvatarFallback","Badge","_a","trait","Brain"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Persons-epdmUeBM.js","sources":["../../src/pages/brain/Persons.tsx"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { Link } from \"react-router-dom\";\nimport { motion } from \"framer-motion\";\nimport { Search, Users, UserCircle, Brain } from \"lucide-react\";\nimport api, { type Person } from \"@/lib/api\";\nimport { cn } from \"@/lib/utils\";\nimport { Input } from \"@/components/ui/input\";\nimport { Card, CardContent } from \"@/components/ui/card\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { Avatar, AvatarFallback } from \"@/components/ui/avatar\";\n\n// ── Skeleton ──\n\nfunction PersonCardSkeleton() {\n return (\n <div className=\"rounded-xl border border-border bg-card p-5 animate-pulse\">\n <div className=\"flex items-center gap-3 mb-3\">\n <div className=\"h-11 w-11 rounded-full bg-muted\" />\n <div className=\"flex-1 space-y-2\">\n <div className=\"h-4 w-28 rounded bg-muted\" />\n <div className=\"h-3 w-16 rounded bg-muted\" />\n </div>\n </div>\n <div className=\"space-y-2 mb-3\">\n <div className=\"h-3 w-full rounded bg-muted\" />\n <div className=\"h-3 w-3/4 rounded bg-muted\" />\n </div>\n <div className=\"flex gap-1.5\">\n <div className=\"h-5 w-14 rounded bg-muted\" />\n <div className=\"h-5 w-12 rounded bg-muted\" />\n </div>\n </div>\n );\n}\n\n// ── Animation variants ──\n\nconst container = {\n hidden: {},\n show: {\n transition: { staggerChildren: 0.04 },\n },\n};\n\nconst item = {\n hidden: { opacity: 0, y: 12 },\n show: { opacity: 1, y: 0, transition: { duration: 0.3, ease: \"easeOut\" as const } },\n};\n\n// ── Page ──\n\nexport function PersonsPage() {\n const [persons, setPersons] = useState<Person[]>([]);\n const [total, setTotal] = useState(0);\n const [query, setQuery] = useState(\"\");\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const fetchPersons = useCallback(async (q: string) => {\n try {\n setError(null);\n setLoading(true);\n const res = await api.brain.persons.list({\n q: q || undefined,\n limit: 200,\n });\n setPersons(res.persons);\n setTotal(res.total);\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Failed to load persons\");\n } finally {\n setLoading(false);\n }\n }, []);\n\n useEffect(() => {\n fetchPersons(\"\");\n }, [fetchPersons]);\n\n const handleSearch = (value: string) => {\n setQuery(value);\n if (debounceRef.current) clearTimeout(debounceRef.current);\n debounceRef.current = setTimeout(() => fetchPersons(value), 300);\n };\n\n return (\n <div className=\"space-y-6 p-6\">\n {/* Header */}\n <div>\n <div className=\"flex items-center gap-2.5\">\n <Users className=\"h-6 w-6 text-[#00d4ff]\" />\n <h1 className=\"text-2xl font-semibold text-foreground\">\n Persons\n {!loading && (\n <span className=\"ml-2 text-base font-normal text-muted-foreground\">\n ({total})\n </span>\n )}\n </h1>\n </div>\n <p className=\"mt-1 text-sm text-muted-foreground\">\n People Mercury knows about\n </p>\n </div>\n\n {/* Search */}\n <div className=\"relative max-w-md\">\n <Search className=\"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground\" />\n <Input\n placeholder=\"Search by name...\"\n value={query}\n onChange={(e) => handleSearch(e.target.value)}\n className=\"pl-9\"\n />\n </div>\n\n {/* Error */}\n {error && (\n <Card>\n <CardContent className=\"py-8 text-center text-destructive\">\n {error}\n </CardContent>\n </Card>\n )}\n\n {/* Loading */}\n {loading && (\n <div className=\"grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3\">\n {Array.from({ length: 6 }).map((_, i) => (\n <PersonCardSkeleton key={i} />\n ))}\n </div>\n )}\n\n {/* Empty */}\n {!loading && !error && persons.length === 0 && (\n <Card>\n <CardContent className=\"flex flex-col items-center gap-3 py-12 text-center text-muted-foreground\">\n <UserCircle className=\"h-10 w-10\" />\n <div>\n <p className=\"font-medium text-foreground\">No persons found</p>\n <p className=\"text-sm\">\n {query\n ? \"Try a different search term.\"\n : \"Mercury hasn't recorded any people yet.\"}\n </p>\n </div>\n </CardContent>\n </Card>\n )}\n\n {/* Grid */}\n {!loading && !error && persons.length > 0 && (\n <motion.div\n className=\"grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3\"\n variants={container}\n initial=\"hidden\"\n animate=\"show\"\n >\n {persons.map((person) => (\n <motion.div key={person.id} variants={item}>\n <Link\n to={`/second-brain/persons/${person.id}`}\n className=\"block\"\n >\n <Card\n className={cn(\n \"cursor-pointer transition-all duration-200\",\n \"hover:-translate-y-0.5 hover:shadow-lg hover:border-[#00d4ff]/30\"\n )}\n >\n <CardContent className=\"p-5\">\n {/* Avatar + name */}\n <div className=\"flex items-center gap-3 mb-3\">\n <Avatar className=\"h-11 w-11\">\n <AvatarFallback className=\"bg-[#00d4ff]/10 text-[#00d4ff] font-semibold text-sm\">\n {person.name.charAt(0).toUpperCase()}\n </AvatarFallback>\n </Avatar>\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-base font-semibold text-foreground\">\n {person.name}\n </p>\n {person.relationship && (\n <Badge\n variant=\"secondary\"\n className=\"mt-0.5 text-[10px] capitalize\"\n >\n {person.relationship}\n </Badge>\n )}\n </div>\n </div>\n\n {/* Summary */}\n {person.summary && (\n <p className=\"mb-3 line-clamp-2 text-sm text-muted-foreground\">\n {person.summary}\n </p>\n )}\n\n {/* Footer: traits + memory count */}\n <div className=\"flex flex-wrap items-center gap-1.5\">\n {person.traits?.slice(0, 4).map((trait) => (\n <Badge\n key={trait}\n variant=\"outline\"\n className=\"text-[10px]\"\n >\n {trait}\n </Badge>\n ))}\n {person.memoryCount != null && person.memoryCount > 0 && (\n <span className=\"ml-auto flex items-center gap-1 text-xs text-muted-foreground\">\n <Brain className=\"h-3 w-3\" />\n {person.memoryCount} memories\n </span>\n )}\n </div>\n </CardContent>\n </Card>\n </Link>\n </motion.div>\n ))}\n </motion.div>\n )}\n </div>\n );\n}\n"],"names":["PersonCardSkeleton","jsxs","jsx","container","item","PersonsPage","persons","setPersons","useState","total","setTotal","query","setQuery","loading","setLoading","error","setError","debounceRef","useRef","fetchPersons","useCallback","q","res","api","err","useEffect","handleSearch","value","Users","Search","Input","e","Card","CardContent","_","i","UserCircle","motion","person","Link","cn","Avatar","AvatarFallback","Badge","_a","trait","Brain"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{j as e,A as b,m as j}from"./vendor-motion-Dwx3-JO5.js";import{r as c}from"./vendor-react-C7pctHW3.js";import{e as I,a as h,d as y,c as m}from"./index-
|
|
1
|
+
import{j as e,A as b,m as j}from"./vendor-motion-Dwx3-JO5.js";import{r as c}from"./vendor-react-C7pctHW3.js";import{e as I,a as h,d as y,c as m}from"./index-C3YiF4qv.js";import{C as f,c as p,a as S}from"./card-BdsEOP7t.js";import{I as v}from"./input-CH3dmo9r.js";import{B as N}from"./button-CNasMlFE.js";import{S as L}from"./switch-LRN9wWy2.js";import{B as w}from"./badge-CUJiWF1y.js";import{C as K}from"./circle-x-CyaGJ_BM.js";import{E as M}from"./eye-BJ0NucMz.js";import{C as B}from"./circle-check-DvGSe1uZ.js";import{L as E}from"./loader-circle-DbYKk0_Q.js";import"./vendor-syntax-xZUI6Op9.js";import"./vendor-radix-3UdfCgs_.js";import"./index-CaqLZNof.js";/**
|
|
2
2
|
* @license lucide-react v0.511.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
5
5
|
* See the LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/const z=[["path",{d:"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49",key:"ct8e1f"}],["path",{d:"M14.084 14.158a3 3 0 0 1-4.242-4.242",key:"151rxh"}],["path",{d:"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143",key:"13bj9a"}],["path",{d:"m2 2 20 20",key:"1ooewy"}]],O=I("eye-off",z),_=d=>({apiKey:"",baseUrl:d.baseUrl,model:d.model,enabled:d.enabled,showKey:!1,saving:!1,testing:!1,feedback:null,testResult:null});function D(){return e.jsxs(f,{className:"border-border/50 bg-card/60 backdrop-blur",children:[e.jsx(S,{className:"pb-4",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"h-9 w-9 animate-pulse rounded-lg bg-muted"}),e.jsx("div",{className:"h-5 w-28 animate-pulse rounded bg-muted"})]}),e.jsx("div",{className:"h-5 w-9 animate-pulse rounded-full bg-muted"})]})}),e.jsxs(p,{className:"space-y-4",children:[[1,2,3].map(d=>e.jsxs("div",{className:"space-y-1.5",children:[e.jsx("div",{className:"h-3.5 w-16 animate-pulse rounded bg-muted"}),e.jsx("div",{className:"h-9 w-full animate-pulse rounded-md bg-muted"})]},d)),e.jsxs("div",{className:"flex gap-2 pt-2",children:[e.jsx("div",{className:"h-9 w-20 animate-pulse rounded-md bg-muted"}),e.jsx("div",{className:"h-9 w-32 animate-pulse rounded-md bg-muted"})]})]})]})}function re(){const[d,P]=c.useState([]),[k,C]=c.useState({}),[u,T]=c.useState(!0),[g,R]=c.useState(null),x=c.useRef({}),n=c.useCallback(async()=>{try{const s=await h.providers.list();P(s),C(t=>{const a={};for(const i of s)a[i.name]=t[i.name]?{...t[i.name],enabled:i.enabled}:_(i);return a}),R(null)}catch(s){R(s instanceof Error?s.message:"Failed to load providers")}finally{T(!1)}},[]);c.useEffect(()=>(n(),()=>{Object.values(x.current).forEach(clearTimeout)}),[n]);const r=(s,t)=>{C(a=>({...a,[s]:{...a[s],...t}}))},o=(s,t,a)=>{x.current[s]&&clearTimeout(x.current[s]),r(s,{feedback:{type:t,message:a}}),x.current[s]=setTimeout(()=>{r(s,{feedback:null})},4e3)},U=async s=>{const t=k[s];if(t){r(s,{saving:!0});try{await h.providers.update(s,{...t.apiKey?{apiKey:t.apiKey}:{},baseUrl:t.baseUrl,model:t.model,enabled:t.enabled}),o(s,"success","Configuration saved"),r(s,{apiKey:"",saving:!1}),n()}catch(a){o(s,"error",a instanceof Error?a.message:"Save failed"),r(s,{saving:!1})}}},A=async s=>{r(s,{testing:!0,testResult:null});try{const t=await h.providers.test(s);r(s,{testing:!1,testResult:t}),o(s,t.success?"success":"error",t.success?"Connection successful":"Connection failed")}catch(t){r(s,{testing:!1}),o(s,"error",t instanceof Error?t.message:"Test failed")}},F=async(s,t)=>{r(s,{enabled:t});try{await h.providers.update(s,{enabled:t}),n()}catch{o(s,"error","Failed to toggle provider"),r(s,{enabled:!t})}};return e.jsxs("div",{className:"space-y-6 p-6",children:[e.jsx("div",{children:e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"flex h-10 w-10 items-center justify-center rounded-xl bg-gradient-to-br from-[#00d4ff]/20 to-[#a78bfa]/20 ring-1 ring-[#00d4ff]/30",children:e.jsx(y,{className:"h-5 w-5 text-[#00d4ff]"})}),e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-semibold text-foreground",children:"Providers"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Configure your AI model providers"})]})]})}),g&&!u&&e.jsx(f,{className:"border-destructive/50 bg-destructive/5",children:e.jsxs(p,{className:"flex items-center gap-3 py-4",children:[e.jsx(K,{className:"h-5 w-5 text-destructive"}),e.jsx("p",{className:"text-sm text-destructive",children:g}),e.jsx(N,{variant:"outline",size:"sm",className:"ml-auto",onClick:n,children:"Retry"})]})}),u&&e.jsx("div",{className:"grid gap-6 md:grid-cols-1 lg:grid-cols-2",children:[1,2,3,4].map(s=>e.jsx(D,{},s))}),!u&&d.length>0&&e.jsx("div",{className:"grid gap-6 md:grid-cols-1 lg:grid-cols-2",children:e.jsx(b,{mode:"popLayout",children:d.map((s,t)=>{var i;const a=k[s.name];return a?e.jsx(j.div,{initial:{opacity:0,y:20},animate:{opacity:1,y:0},exit:{opacity:0,y:-10},transition:{duration:.3,delay:t*.05},children:e.jsxs(f,{className:m("border-border/50 bg-card/60 backdrop-blur transition-all duration-300",a.enabled&&"ring-1 ring-[#00d4ff]/20"),children:[e.jsx(S,{className:"pb-4",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:m("flex h-9 w-9 items-center justify-center rounded-lg transition-colors",a.enabled?"bg-gradient-to-br from-[#00d4ff]/20 to-[#a78bfa]/20":"bg-muted"),children:e.jsx(y,{className:m("h-4.5 w-4.5 transition-colors",a.enabled?"text-[#00d4ff]":"text-muted-foreground")})}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-base font-medium text-foreground",children:s.name}),e.jsx(w,{variant:a.enabled?"default":"secondary",className:m("text-[10px] px-1.5 py-0",a.enabled&&"bg-[#00d4ff]/15 text-[#00d4ff] border-[#00d4ff]/30 hover:bg-[#00d4ff]/20"),children:a.enabled?"Active":"Disabled"})]})]}),e.jsx(L,{checked:a.enabled,onCheckedChange:l=>F(s.name,l)})]})}),e.jsxs(p,{className:"space-y-4",children:[e.jsxs("div",{className:"space-y-1.5",children:[e.jsx("label",{className:"text-xs font-medium text-muted-foreground",children:"API Key"}),e.jsxs("div",{className:"relative",children:[e.jsx(v,{type:a.showKey?"text":"password",placeholder:s.maskedKey||"Enter API key",value:a.apiKey,onChange:l=>r(s.name,{apiKey:l.target.value}),className:"pr-9 bg-background/50"}),e.jsx("button",{type:"button",onClick:()=>r(s.name,{showKey:!a.showKey}),className:"absolute right-2.5 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground transition-colors",children:a.showKey?e.jsx(O,{className:"h-4 w-4"}):e.jsx(M,{className:"h-4 w-4"})})]})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsxs("label",{className:"text-xs font-medium text-muted-foreground",children:["Base URL"," ",e.jsx("span",{className:"text-muted-foreground/60",children:"(optional)"})]}),e.jsx(v,{placeholder:"https://api.openai.com/v1",value:a.baseUrl,onChange:l=>r(s.name,{baseUrl:l.target.value}),className:"bg-background/50"})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx("label",{className:"text-xs font-medium text-muted-foreground",children:"Model"}),e.jsx(v,{placeholder:"gpt-4o",value:a.model,onChange:l=>r(s.name,{model:l.target.value}),className:"bg-background/50"})]}),e.jsx(b,{children:a.feedback&&e.jsx(j.div,{initial:{opacity:0,height:0},animate:{opacity:1,height:"auto"},exit:{opacity:0,height:0},className:"overflow-hidden",children:e.jsxs("div",{className:m("flex items-center gap-2 rounded-md px-3 py-2 text-sm",a.feedback.type==="success"?"bg-emerald-500/10 text-emerald-400":"bg-destructive/10 text-destructive"),children:[a.feedback.type==="success"?e.jsx(B,{className:"h-4 w-4 shrink-0"}):e.jsx(K,{className:"h-4 w-4 shrink-0"}),a.feedback.message]})})}),e.jsx(b,{children:((i=a.testResult)==null?void 0:i.success)&&a.testResult.models&&e.jsx(j.div,{initial:{opacity:0,height:0},animate:{opacity:1,height:"auto"},exit:{opacity:0,height:0},className:"overflow-hidden",children:e.jsxs("div",{className:"rounded-md border border-border/50 bg-background/30 p-3 space-y-2",children:[a.testResult.recommendedModel&&e.jsxs("p",{className:"text-xs text-muted-foreground",children:["Recommended:"," ",e.jsx("span",{className:"font-medium text-[#00d4ff]",children:a.testResult.recommendedModel})]}),e.jsxs("div",{className:"flex flex-wrap gap-1.5",children:[a.testResult.models.slice(0,12).map(l=>e.jsx(w,{variant:"secondary",className:"text-[10px] cursor-pointer hover:bg-[#00d4ff]/15 hover:text-[#00d4ff] transition-colors",onClick:()=>r(s.name,{model:l}),children:l},l)),a.testResult.models.length>12&&e.jsxs(w,{variant:"secondary",className:"text-[10px]",children:["+",a.testResult.models.length-12," more"]})]})]})})}),e.jsxs("div",{className:"flex gap-2 pt-1",children:[e.jsxs(N,{size:"sm",onClick:()=>U(s.name),disabled:a.saving,className:"bg-gradient-to-r from-[#00d4ff] to-[#a78bfa] text-white hover:opacity-90 transition-opacity",children:[a.saving&&e.jsx(E,{className:"mr-1.5 h-3.5 w-3.5 animate-spin"}),"Save"]}),e.jsxs(N,{size:"sm",variant:"outline",onClick:()=>A(s.name),disabled:a.testing,children:[a.testing&&e.jsx(E,{className:"mr-1.5 h-3.5 w-3.5 animate-spin"}),"Test Connection"]})]})]})]})},s.name):null})})}),!u&&!g&&d.length===0&&e.jsx(f,{className:"border-border/50 bg-card/60",children:e.jsxs(p,{className:"py-12 text-center",children:[e.jsx(y,{className:"mx-auto h-10 w-10 text-muted-foreground/40 mb-3"}),e.jsx("p",{className:"text-muted-foreground",children:"No providers configured yet."})]})})]})}export{re as ProvidersPage};
|
|
7
|
-
//# sourceMappingURL=Providers-
|
|
7
|
+
//# sourceMappingURL=Providers-Bm8sZNZo.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Providers-CL6wMWni.js","sources":["../../node_modules/lucide-react/dist/esm/icons/eye-off.js","../../src/pages/Providers.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49\",\n key: \"ct8e1f\"\n }\n ],\n [\"path\", { d: \"M14.084 14.158a3 3 0 0 1-4.242-4.242\", key: \"151rxh\" }],\n [\n \"path\",\n {\n d: \"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143\",\n key: \"13bj9a\"\n }\n ],\n [\"path\", { d: \"m2 2 20 20\", key: \"1ooewy\" }]\n];\nconst EyeOff = createLucideIcon(\"eye-off\", __iconNode);\n\nexport { __iconNode, EyeOff as default };\n//# sourceMappingURL=eye-off.js.map\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { Cpu, Eye, EyeOff, Loader2, CheckCircle2, XCircle } from \"lucide-react\";\nimport { motion, AnimatePresence } from \"framer-motion\";\nimport api, { type ProviderInfo, type ProviderTestResult } from \"@/lib/api\";\nimport { cn } from \"@/lib/utils\";\nimport { Card, CardHeader, CardContent } from \"@/components/ui/card\";\nimport { Input } from \"@/components/ui/input\";\nimport { Button } from \"@/components/ui/button\";\nimport { Switch } from \"@/components/ui/switch\";\nimport { Badge } from \"@/components/ui/badge\";\n\n/* ── Per-provider local form state ── */\ninterface ProviderForm {\n apiKey: string;\n baseUrl: string;\n model: string;\n enabled: boolean;\n showKey: boolean;\n saving: boolean;\n testing: boolean;\n feedback: { type: \"success\" | \"error\"; message: string } | null;\n testResult: ProviderTestResult | null;\n}\n\nconst emptyForm = (p: ProviderInfo): ProviderForm => ({\n apiKey: \"\",\n baseUrl: p.baseUrl,\n model: p.model,\n enabled: p.enabled,\n showKey: false,\n saving: false,\n testing: false,\n feedback: null,\n testResult: null,\n});\n\n/* ── Skeleton ── */\nfunction ProviderSkeleton() {\n return (\n <Card className=\"border-border/50 bg-card/60 backdrop-blur\">\n <CardHeader className=\"pb-4\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <div className=\"h-9 w-9 animate-pulse rounded-lg bg-muted\" />\n <div className=\"h-5 w-28 animate-pulse rounded bg-muted\" />\n </div>\n <div className=\"h-5 w-9 animate-pulse rounded-full bg-muted\" />\n </div>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {[1, 2, 3].map((i) => (\n <div key={i} className=\"space-y-1.5\">\n <div className=\"h-3.5 w-16 animate-pulse rounded bg-muted\" />\n <div className=\"h-9 w-full animate-pulse rounded-md bg-muted\" />\n </div>\n ))}\n <div className=\"flex gap-2 pt-2\">\n <div className=\"h-9 w-20 animate-pulse rounded-md bg-muted\" />\n <div className=\"h-9 w-32 animate-pulse rounded-md bg-muted\" />\n </div>\n </CardContent>\n </Card>\n );\n}\n\nexport function ProvidersPage() {\n const [providers, setProviders] = useState<ProviderInfo[]>([]);\n const [forms, setForms] = useState<Record<string, ProviderForm>>({});\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const feedbackTimers = useRef<Record<string, ReturnType<typeof setTimeout>>>({});\n\n const fetchProviders = useCallback(async () => {\n try {\n const data = await api.providers.list();\n setProviders(data);\n setForms((prev) => {\n const next: Record<string, ProviderForm> = {};\n for (const p of data) {\n next[p.name] = prev[p.name]\n ? { ...prev[p.name], enabled: p.enabled }\n : emptyForm(p);\n }\n return next;\n });\n setError(null);\n } catch (e) {\n setError(e instanceof Error ? e.message : \"Failed to load providers\");\n } finally {\n setLoading(false);\n }\n }, []);\n\n useEffect(() => {\n fetchProviders();\n return () => {\n Object.values(feedbackTimers.current).forEach(clearTimeout);\n };\n }, [fetchProviders]);\n\n /* helpers */\n const updateForm = (name: string, patch: Partial<ProviderForm>) => {\n setForms((prev) => ({ ...prev, [name]: { ...prev[name], ...patch } }));\n };\n\n const showFeedback = (\n name: string,\n type: \"success\" | \"error\",\n message: string\n ) => {\n if (feedbackTimers.current[name]) clearTimeout(feedbackTimers.current[name]);\n updateForm(name, { feedback: { type, message } });\n feedbackTimers.current[name] = setTimeout(() => {\n updateForm(name, { feedback: null });\n }, 4000);\n };\n\n const handleSave = async (name: string) => {\n const f = forms[name];\n if (!f) return;\n updateForm(name, { saving: true });\n try {\n await api.providers.update(name, {\n ...(f.apiKey ? { apiKey: f.apiKey } : {}),\n baseUrl: f.baseUrl,\n model: f.model,\n enabled: f.enabled,\n });\n showFeedback(name, \"success\", \"Configuration saved\");\n updateForm(name, { apiKey: \"\", saving: false });\n fetchProviders();\n } catch (e) {\n showFeedback(name, \"error\", e instanceof Error ? e.message : \"Save failed\");\n updateForm(name, { saving: false });\n }\n };\n\n const handleTest = async (name: string) => {\n updateForm(name, { testing: true, testResult: null });\n try {\n const result = await api.providers.test(name);\n updateForm(name, { testing: false, testResult: result });\n showFeedback(\n name,\n result.success ? \"success\" : \"error\",\n result.success ? \"Connection successful\" : \"Connection failed\"\n );\n } catch (e) {\n updateForm(name, { testing: false });\n showFeedback(name, \"error\", e instanceof Error ? e.message : \"Test failed\");\n }\n };\n\n const handleToggle = async (name: string, enabled: boolean) => {\n updateForm(name, { enabled });\n try {\n await api.providers.update(name, { enabled });\n fetchProviders();\n } catch (e) {\n showFeedback(name, \"error\", \"Failed to toggle provider\");\n updateForm(name, { enabled: !enabled });\n }\n };\n\n return (\n <div className=\"space-y-6 p-6\">\n {/* Header */}\n <div>\n <div className=\"flex items-center gap-3\">\n <div className=\"flex h-10 w-10 items-center justify-center rounded-xl bg-gradient-to-br from-[#00d4ff]/20 to-[#a78bfa]/20 ring-1 ring-[#00d4ff]/30\">\n <Cpu className=\"h-5 w-5 text-[#00d4ff]\" />\n </div>\n <div>\n <h1 className=\"text-2xl font-semibold text-foreground\">Providers</h1>\n <p className=\"text-sm text-muted-foreground\">\n Configure your AI model providers\n </p>\n </div>\n </div>\n </div>\n\n {/* Error state */}\n {error && !loading && (\n <Card className=\"border-destructive/50 bg-destructive/5\">\n <CardContent className=\"flex items-center gap-3 py-4\">\n <XCircle className=\"h-5 w-5 text-destructive\" />\n <p className=\"text-sm text-destructive\">{error}</p>\n <Button variant=\"outline\" size=\"sm\" className=\"ml-auto\" onClick={fetchProviders}>\n Retry\n </Button>\n </CardContent>\n </Card>\n )}\n\n {/* Loading */}\n {loading && (\n <div className=\"grid gap-6 md:grid-cols-1 lg:grid-cols-2\">\n {[1, 2, 3, 4].map((i) => (\n <ProviderSkeleton key={i} />\n ))}\n </div>\n )}\n\n {/* Provider Grid */}\n {!loading && providers.length > 0 && (\n <div className=\"grid gap-6 md:grid-cols-1 lg:grid-cols-2\">\n <AnimatePresence mode=\"popLayout\">\n {providers.map((provider, idx) => {\n const f = forms[provider.name];\n if (!f) return null;\n return (\n <motion.div\n key={provider.name}\n initial={{ opacity: 0, y: 20 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -10 }}\n transition={{ duration: 0.3, delay: idx * 0.05 }}\n >\n <Card\n className={cn(\n \"border-border/50 bg-card/60 backdrop-blur transition-all duration-300\",\n f.enabled && \"ring-1 ring-[#00d4ff]/20\"\n )}\n >\n <CardHeader className=\"pb-4\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <div\n className={cn(\n \"flex h-9 w-9 items-center justify-center rounded-lg transition-colors\",\n f.enabled\n ? \"bg-gradient-to-br from-[#00d4ff]/20 to-[#a78bfa]/20\"\n : \"bg-muted\"\n )}\n >\n <Cpu\n className={cn(\n \"h-4.5 w-4.5 transition-colors\",\n f.enabled ? \"text-[#00d4ff]\" : \"text-muted-foreground\"\n )}\n />\n </div>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-base font-medium text-foreground\">\n {provider.name}\n </span>\n <Badge\n variant={f.enabled ? \"default\" : \"secondary\"}\n className={cn(\n \"text-[10px] px-1.5 py-0\",\n f.enabled &&\n \"bg-[#00d4ff]/15 text-[#00d4ff] border-[#00d4ff]/30 hover:bg-[#00d4ff]/20\"\n )}\n >\n {f.enabled ? \"Active\" : \"Disabled\"}\n </Badge>\n </div>\n </div>\n <Switch\n checked={f.enabled}\n onCheckedChange={(val) => handleToggle(provider.name, val)}\n />\n </div>\n </CardHeader>\n\n <CardContent className=\"space-y-4\">\n {/* API Key */}\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium text-muted-foreground\">\n API Key\n </label>\n <div className=\"relative\">\n <Input\n type={f.showKey ? \"text\" : \"password\"}\n placeholder={provider.maskedKey || \"Enter API key\"}\n value={f.apiKey}\n onChange={(e) =>\n updateForm(provider.name, { apiKey: e.target.value })\n }\n className=\"pr-9 bg-background/50\"\n />\n <button\n type=\"button\"\n onClick={() =>\n updateForm(provider.name, { showKey: !f.showKey })\n }\n className=\"absolute right-2.5 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground transition-colors\"\n >\n {f.showKey ? (\n <EyeOff className=\"h-4 w-4\" />\n ) : (\n <Eye className=\"h-4 w-4\" />\n )}\n </button>\n </div>\n </div>\n\n {/* Base URL */}\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium text-muted-foreground\">\n Base URL{\" \"}\n <span className=\"text-muted-foreground/60\">(optional)</span>\n </label>\n <Input\n placeholder=\"https://api.openai.com/v1\"\n value={f.baseUrl}\n onChange={(e) =>\n updateForm(provider.name, { baseUrl: e.target.value })\n }\n className=\"bg-background/50\"\n />\n </div>\n\n {/* Model */}\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium text-muted-foreground\">\n Model\n </label>\n <Input\n placeholder=\"gpt-4o\"\n value={f.model}\n onChange={(e) =>\n updateForm(provider.name, { model: e.target.value })\n }\n className=\"bg-background/50\"\n />\n </div>\n\n {/* Feedback */}\n <AnimatePresence>\n {f.feedback && (\n <motion.div\n initial={{ opacity: 0, height: 0 }}\n animate={{ opacity: 1, height: \"auto\" }}\n exit={{ opacity: 0, height: 0 }}\n className=\"overflow-hidden\"\n >\n <div\n className={cn(\n \"flex items-center gap-2 rounded-md px-3 py-2 text-sm\",\n f.feedback.type === \"success\"\n ? \"bg-emerald-500/10 text-emerald-400\"\n : \"bg-destructive/10 text-destructive\"\n )}\n >\n {f.feedback.type === \"success\" ? (\n <CheckCircle2 className=\"h-4 w-4 shrink-0\" />\n ) : (\n <XCircle className=\"h-4 w-4 shrink-0\" />\n )}\n {f.feedback.message}\n </div>\n </motion.div>\n )}\n </AnimatePresence>\n\n {/* Test result details */}\n <AnimatePresence>\n {f.testResult?.success && f.testResult.models && (\n <motion.div\n initial={{ opacity: 0, height: 0 }}\n animate={{ opacity: 1, height: \"auto\" }}\n exit={{ opacity: 0, height: 0 }}\n className=\"overflow-hidden\"\n >\n <div className=\"rounded-md border border-border/50 bg-background/30 p-3 space-y-2\">\n {f.testResult.recommendedModel && (\n <p className=\"text-xs text-muted-foreground\">\n Recommended:{\" \"}\n <span className=\"font-medium text-[#00d4ff]\">\n {f.testResult.recommendedModel}\n </span>\n </p>\n )}\n <div className=\"flex flex-wrap gap-1.5\">\n {f.testResult.models.slice(0, 12).map((m) => (\n <Badge\n key={m}\n variant=\"secondary\"\n className=\"text-[10px] cursor-pointer hover:bg-[#00d4ff]/15 hover:text-[#00d4ff] transition-colors\"\n onClick={() =>\n updateForm(provider.name, { model: m })\n }\n >\n {m}\n </Badge>\n ))}\n {f.testResult.models.length > 12 && (\n <Badge variant=\"secondary\" className=\"text-[10px]\">\n +{f.testResult.models.length - 12} more\n </Badge>\n )}\n </div>\n </div>\n </motion.div>\n )}\n </AnimatePresence>\n\n {/* Actions */}\n <div className=\"flex gap-2 pt-1\">\n <Button\n size=\"sm\"\n onClick={() => handleSave(provider.name)}\n disabled={f.saving}\n className=\"bg-gradient-to-r from-[#00d4ff] to-[#a78bfa] text-white hover:opacity-90 transition-opacity\"\n >\n {f.saving && (\n <Loader2 className=\"mr-1.5 h-3.5 w-3.5 animate-spin\" />\n )}\n Save\n </Button>\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => handleTest(provider.name)}\n disabled={f.testing}\n >\n {f.testing && (\n <Loader2 className=\"mr-1.5 h-3.5 w-3.5 animate-spin\" />\n )}\n Test Connection\n </Button>\n </div>\n </CardContent>\n </Card>\n </motion.div>\n );\n })}\n </AnimatePresence>\n </div>\n )}\n\n {/* Empty state */}\n {!loading && !error && providers.length === 0 && (\n <Card className=\"border-border/50 bg-card/60\">\n <CardContent className=\"py-12 text-center\">\n <Cpu className=\"mx-auto h-10 w-10 text-muted-foreground/40 mb-3\" />\n <p className=\"text-muted-foreground\">No providers configured yet.</p>\n </CardContent>\n </Card>\n )}\n </div>\n );\n}\n"],"names":["__iconNode","EyeOff","createLucideIcon","emptyForm","p","ProviderSkeleton","jsxs","Card","jsx","CardHeader","CardContent","i","ProvidersPage","providers","setProviders","useState","forms","setForms","loading","setLoading","error","setError","feedbackTimers","useRef","fetchProviders","useCallback","data","api","prev","next","e","useEffect","updateForm","name","patch","showFeedback","type","message","handleSave","f","handleTest","result","handleToggle","enabled","Cpu","XCircle","Button","AnimatePresence","provider","idx","motion","cn","Badge","Switch","val","Input","Eye","CheckCircle2","_a","m","Loader2"],"mappings":"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","x_google_ignoreList":[0]}
|
|
1
|
+
{"version":3,"file":"Providers-Bm8sZNZo.js","sources":["../../node_modules/lucide-react/dist/esm/icons/eye-off.js","../../src/pages/Providers.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49\",\n key: \"ct8e1f\"\n }\n ],\n [\"path\", { d: \"M14.084 14.158a3 3 0 0 1-4.242-4.242\", key: \"151rxh\" }],\n [\n \"path\",\n {\n d: \"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143\",\n key: \"13bj9a\"\n }\n ],\n [\"path\", { d: \"m2 2 20 20\", key: \"1ooewy\" }]\n];\nconst EyeOff = createLucideIcon(\"eye-off\", __iconNode);\n\nexport { __iconNode, EyeOff as default };\n//# sourceMappingURL=eye-off.js.map\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { Cpu, Eye, EyeOff, Loader2, CheckCircle2, XCircle } from \"lucide-react\";\nimport { motion, AnimatePresence } from \"framer-motion\";\nimport api, { type ProviderInfo, type ProviderTestResult } from \"@/lib/api\";\nimport { cn } from \"@/lib/utils\";\nimport { Card, CardHeader, CardContent } from \"@/components/ui/card\";\nimport { Input } from \"@/components/ui/input\";\nimport { Button } from \"@/components/ui/button\";\nimport { Switch } from \"@/components/ui/switch\";\nimport { Badge } from \"@/components/ui/badge\";\n\n/* ── Per-provider local form state ── */\ninterface ProviderForm {\n apiKey: string;\n baseUrl: string;\n model: string;\n enabled: boolean;\n showKey: boolean;\n saving: boolean;\n testing: boolean;\n feedback: { type: \"success\" | \"error\"; message: string } | null;\n testResult: ProviderTestResult | null;\n}\n\nconst emptyForm = (p: ProviderInfo): ProviderForm => ({\n apiKey: \"\",\n baseUrl: p.baseUrl,\n model: p.model,\n enabled: p.enabled,\n showKey: false,\n saving: false,\n testing: false,\n feedback: null,\n testResult: null,\n});\n\n/* ── Skeleton ── */\nfunction ProviderSkeleton() {\n return (\n <Card className=\"border-border/50 bg-card/60 backdrop-blur\">\n <CardHeader className=\"pb-4\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <div className=\"h-9 w-9 animate-pulse rounded-lg bg-muted\" />\n <div className=\"h-5 w-28 animate-pulse rounded bg-muted\" />\n </div>\n <div className=\"h-5 w-9 animate-pulse rounded-full bg-muted\" />\n </div>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {[1, 2, 3].map((i) => (\n <div key={i} className=\"space-y-1.5\">\n <div className=\"h-3.5 w-16 animate-pulse rounded bg-muted\" />\n <div className=\"h-9 w-full animate-pulse rounded-md bg-muted\" />\n </div>\n ))}\n <div className=\"flex gap-2 pt-2\">\n <div className=\"h-9 w-20 animate-pulse rounded-md bg-muted\" />\n <div className=\"h-9 w-32 animate-pulse rounded-md bg-muted\" />\n </div>\n </CardContent>\n </Card>\n );\n}\n\nexport function ProvidersPage() {\n const [providers, setProviders] = useState<ProviderInfo[]>([]);\n const [forms, setForms] = useState<Record<string, ProviderForm>>({});\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const feedbackTimers = useRef<Record<string, ReturnType<typeof setTimeout>>>({});\n\n const fetchProviders = useCallback(async () => {\n try {\n const data = await api.providers.list();\n setProviders(data);\n setForms((prev) => {\n const next: Record<string, ProviderForm> = {};\n for (const p of data) {\n next[p.name] = prev[p.name]\n ? { ...prev[p.name], enabled: p.enabled }\n : emptyForm(p);\n }\n return next;\n });\n setError(null);\n } catch (e) {\n setError(e instanceof Error ? e.message : \"Failed to load providers\");\n } finally {\n setLoading(false);\n }\n }, []);\n\n useEffect(() => {\n fetchProviders();\n return () => {\n Object.values(feedbackTimers.current).forEach(clearTimeout);\n };\n }, [fetchProviders]);\n\n /* helpers */\n const updateForm = (name: string, patch: Partial<ProviderForm>) => {\n setForms((prev) => ({ ...prev, [name]: { ...prev[name], ...patch } }));\n };\n\n const showFeedback = (\n name: string,\n type: \"success\" | \"error\",\n message: string\n ) => {\n if (feedbackTimers.current[name]) clearTimeout(feedbackTimers.current[name]);\n updateForm(name, { feedback: { type, message } });\n feedbackTimers.current[name] = setTimeout(() => {\n updateForm(name, { feedback: null });\n }, 4000);\n };\n\n const handleSave = async (name: string) => {\n const f = forms[name];\n if (!f) return;\n updateForm(name, { saving: true });\n try {\n await api.providers.update(name, {\n ...(f.apiKey ? { apiKey: f.apiKey } : {}),\n baseUrl: f.baseUrl,\n model: f.model,\n enabled: f.enabled,\n });\n showFeedback(name, \"success\", \"Configuration saved\");\n updateForm(name, { apiKey: \"\", saving: false });\n fetchProviders();\n } catch (e) {\n showFeedback(name, \"error\", e instanceof Error ? e.message : \"Save failed\");\n updateForm(name, { saving: false });\n }\n };\n\n const handleTest = async (name: string) => {\n updateForm(name, { testing: true, testResult: null });\n try {\n const result = await api.providers.test(name);\n updateForm(name, { testing: false, testResult: result });\n showFeedback(\n name,\n result.success ? \"success\" : \"error\",\n result.success ? \"Connection successful\" : \"Connection failed\"\n );\n } catch (e) {\n updateForm(name, { testing: false });\n showFeedback(name, \"error\", e instanceof Error ? e.message : \"Test failed\");\n }\n };\n\n const handleToggle = async (name: string, enabled: boolean) => {\n updateForm(name, { enabled });\n try {\n await api.providers.update(name, { enabled });\n fetchProviders();\n } catch (e) {\n showFeedback(name, \"error\", \"Failed to toggle provider\");\n updateForm(name, { enabled: !enabled });\n }\n };\n\n return (\n <div className=\"space-y-6 p-6\">\n {/* Header */}\n <div>\n <div className=\"flex items-center gap-3\">\n <div className=\"flex h-10 w-10 items-center justify-center rounded-xl bg-gradient-to-br from-[#00d4ff]/20 to-[#a78bfa]/20 ring-1 ring-[#00d4ff]/30\">\n <Cpu className=\"h-5 w-5 text-[#00d4ff]\" />\n </div>\n <div>\n <h1 className=\"text-2xl font-semibold text-foreground\">Providers</h1>\n <p className=\"text-sm text-muted-foreground\">\n Configure your AI model providers\n </p>\n </div>\n </div>\n </div>\n\n {/* Error state */}\n {error && !loading && (\n <Card className=\"border-destructive/50 bg-destructive/5\">\n <CardContent className=\"flex items-center gap-3 py-4\">\n <XCircle className=\"h-5 w-5 text-destructive\" />\n <p className=\"text-sm text-destructive\">{error}</p>\n <Button variant=\"outline\" size=\"sm\" className=\"ml-auto\" onClick={fetchProviders}>\n Retry\n </Button>\n </CardContent>\n </Card>\n )}\n\n {/* Loading */}\n {loading && (\n <div className=\"grid gap-6 md:grid-cols-1 lg:grid-cols-2\">\n {[1, 2, 3, 4].map((i) => (\n <ProviderSkeleton key={i} />\n ))}\n </div>\n )}\n\n {/* Provider Grid */}\n {!loading && providers.length > 0 && (\n <div className=\"grid gap-6 md:grid-cols-1 lg:grid-cols-2\">\n <AnimatePresence mode=\"popLayout\">\n {providers.map((provider, idx) => {\n const f = forms[provider.name];\n if (!f) return null;\n return (\n <motion.div\n key={provider.name}\n initial={{ opacity: 0, y: 20 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -10 }}\n transition={{ duration: 0.3, delay: idx * 0.05 }}\n >\n <Card\n className={cn(\n \"border-border/50 bg-card/60 backdrop-blur transition-all duration-300\",\n f.enabled && \"ring-1 ring-[#00d4ff]/20\"\n )}\n >\n <CardHeader className=\"pb-4\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <div\n className={cn(\n \"flex h-9 w-9 items-center justify-center rounded-lg transition-colors\",\n f.enabled\n ? \"bg-gradient-to-br from-[#00d4ff]/20 to-[#a78bfa]/20\"\n : \"bg-muted\"\n )}\n >\n <Cpu\n className={cn(\n \"h-4.5 w-4.5 transition-colors\",\n f.enabled ? \"text-[#00d4ff]\" : \"text-muted-foreground\"\n )}\n />\n </div>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-base font-medium text-foreground\">\n {provider.name}\n </span>\n <Badge\n variant={f.enabled ? \"default\" : \"secondary\"}\n className={cn(\n \"text-[10px] px-1.5 py-0\",\n f.enabled &&\n \"bg-[#00d4ff]/15 text-[#00d4ff] border-[#00d4ff]/30 hover:bg-[#00d4ff]/20\"\n )}\n >\n {f.enabled ? \"Active\" : \"Disabled\"}\n </Badge>\n </div>\n </div>\n <Switch\n checked={f.enabled}\n onCheckedChange={(val) => handleToggle(provider.name, val)}\n />\n </div>\n </CardHeader>\n\n <CardContent className=\"space-y-4\">\n {/* API Key */}\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium text-muted-foreground\">\n API Key\n </label>\n <div className=\"relative\">\n <Input\n type={f.showKey ? \"text\" : \"password\"}\n placeholder={provider.maskedKey || \"Enter API key\"}\n value={f.apiKey}\n onChange={(e) =>\n updateForm(provider.name, { apiKey: e.target.value })\n }\n className=\"pr-9 bg-background/50\"\n />\n <button\n type=\"button\"\n onClick={() =>\n updateForm(provider.name, { showKey: !f.showKey })\n }\n className=\"absolute right-2.5 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground transition-colors\"\n >\n {f.showKey ? (\n <EyeOff className=\"h-4 w-4\" />\n ) : (\n <Eye className=\"h-4 w-4\" />\n )}\n </button>\n </div>\n </div>\n\n {/* Base URL */}\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium text-muted-foreground\">\n Base URL{\" \"}\n <span className=\"text-muted-foreground/60\">(optional)</span>\n </label>\n <Input\n placeholder=\"https://api.openai.com/v1\"\n value={f.baseUrl}\n onChange={(e) =>\n updateForm(provider.name, { baseUrl: e.target.value })\n }\n className=\"bg-background/50\"\n />\n </div>\n\n {/* Model */}\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium text-muted-foreground\">\n Model\n </label>\n <Input\n placeholder=\"gpt-4o\"\n value={f.model}\n onChange={(e) =>\n updateForm(provider.name, { model: e.target.value })\n }\n className=\"bg-background/50\"\n />\n </div>\n\n {/* Feedback */}\n <AnimatePresence>\n {f.feedback && (\n <motion.div\n initial={{ opacity: 0, height: 0 }}\n animate={{ opacity: 1, height: \"auto\" }}\n exit={{ opacity: 0, height: 0 }}\n className=\"overflow-hidden\"\n >\n <div\n className={cn(\n \"flex items-center gap-2 rounded-md px-3 py-2 text-sm\",\n f.feedback.type === \"success\"\n ? \"bg-emerald-500/10 text-emerald-400\"\n : \"bg-destructive/10 text-destructive\"\n )}\n >\n {f.feedback.type === \"success\" ? (\n <CheckCircle2 className=\"h-4 w-4 shrink-0\" />\n ) : (\n <XCircle className=\"h-4 w-4 shrink-0\" />\n )}\n {f.feedback.message}\n </div>\n </motion.div>\n )}\n </AnimatePresence>\n\n {/* Test result details */}\n <AnimatePresence>\n {f.testResult?.success && f.testResult.models && (\n <motion.div\n initial={{ opacity: 0, height: 0 }}\n animate={{ opacity: 1, height: \"auto\" }}\n exit={{ opacity: 0, height: 0 }}\n className=\"overflow-hidden\"\n >\n <div className=\"rounded-md border border-border/50 bg-background/30 p-3 space-y-2\">\n {f.testResult.recommendedModel && (\n <p className=\"text-xs text-muted-foreground\">\n Recommended:{\" \"}\n <span className=\"font-medium text-[#00d4ff]\">\n {f.testResult.recommendedModel}\n </span>\n </p>\n )}\n <div className=\"flex flex-wrap gap-1.5\">\n {f.testResult.models.slice(0, 12).map((m) => (\n <Badge\n key={m}\n variant=\"secondary\"\n className=\"text-[10px] cursor-pointer hover:bg-[#00d4ff]/15 hover:text-[#00d4ff] transition-colors\"\n onClick={() =>\n updateForm(provider.name, { model: m })\n }\n >\n {m}\n </Badge>\n ))}\n {f.testResult.models.length > 12 && (\n <Badge variant=\"secondary\" className=\"text-[10px]\">\n +{f.testResult.models.length - 12} more\n </Badge>\n )}\n </div>\n </div>\n </motion.div>\n )}\n </AnimatePresence>\n\n {/* Actions */}\n <div className=\"flex gap-2 pt-1\">\n <Button\n size=\"sm\"\n onClick={() => handleSave(provider.name)}\n disabled={f.saving}\n className=\"bg-gradient-to-r from-[#00d4ff] to-[#a78bfa] text-white hover:opacity-90 transition-opacity\"\n >\n {f.saving && (\n <Loader2 className=\"mr-1.5 h-3.5 w-3.5 animate-spin\" />\n )}\n Save\n </Button>\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => handleTest(provider.name)}\n disabled={f.testing}\n >\n {f.testing && (\n <Loader2 className=\"mr-1.5 h-3.5 w-3.5 animate-spin\" />\n )}\n Test Connection\n </Button>\n </div>\n </CardContent>\n </Card>\n </motion.div>\n );\n })}\n </AnimatePresence>\n </div>\n )}\n\n {/* Empty state */}\n {!loading && !error && providers.length === 0 && (\n <Card className=\"border-border/50 bg-card/60\">\n <CardContent className=\"py-12 text-center\">\n <Cpu className=\"mx-auto h-10 w-10 text-muted-foreground/40 mb-3\" />\n <p className=\"text-muted-foreground\">No providers configured yet.</p>\n </CardContent>\n </Card>\n )}\n </div>\n );\n}\n"],"names":["__iconNode","EyeOff","createLucideIcon","emptyForm","p","ProviderSkeleton","jsxs","Card","jsx","CardHeader","CardContent","i","ProvidersPage","providers","setProviders","useState","forms","setForms","loading","setLoading","error","setError","feedbackTimers","useRef","fetchProviders","useCallback","data","api","prev","next","e","useEffect","updateForm","name","patch","showFeedback","type","message","handleSave","f","handleTest","result","handleToggle","enabled","Cpu","XCircle","Button","AnimatePresence","provider","idx","motion","cn","Badge","Switch","val","Input","Eye","CheckCircle2","_a","m","Loader2"],"mappings":"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","x_google_ignoreList":[0]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{j as e,m as g,A as L}from"./vendor-motion-Dwx3-JO5.js";import{r}from"./vendor-react-C7pctHW3.js";import{C as $,c as O,a as H,b as U}from"./card-
|
|
1
|
+
import{j as e,m as g,A as L}from"./vendor-motion-Dwx3-JO5.js";import{r}from"./vendor-react-C7pctHW3.js";import{C as $,c as O,a as H,b as U}from"./card-BdsEOP7t.js";import{B as b}from"./badge-CUJiWF1y.js";import{B as y}from"./button-CNasMlFE.js";import{I as u}from"./input-CH3dmo9r.js";import{D as q,a as W,b as G,c as J,d as K,e as Q}from"./dialog-Bd1rELXb.js";import{T as V,A as X,a as Y,b as Z,c as ee,d as se,e as te,f as ae,g as ie}from"./alert-dialog-MbYSbZx5.js";import{e as w,a as C,c as _,C as re,t as le,h as P}from"./index-C3YiF4qv.js";import{S as ne}from"./sparkles-DcP24GEL.js";import{P as ce}from"./pencil-gNDEMhav.js";import"./index-CaqLZNof.js";import"./vendor-radix-3UdfCgs_.js";import"./vendor-syntax-xZUI6Op9.js";/**
|
|
2
2
|
* @license lucide-react v0.511.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
@@ -14,4 +14,4 @@ import{j as e,m as g,A as L}from"./vendor-motion-Dwx3-JO5.js";import{r}from"./ve
|
|
|
14
14
|
* This source code is licensed under the ISC license.
|
|
15
15
|
* See the LICENSE file in the root directory of this source tree.
|
|
16
16
|
*/const ue=[["path",{d:"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3",key:"wmoenq"}],["path",{d:"M12 9v4",key:"juzpu7"}],["path",{d:"M12 17h.01",key:"p32p05"}]],xe=w("triangle-alert",ue),he={hidden:{opacity:0,y:12},visible:a=>({opacity:1,y:0,transition:{delay:a*.07,duration:.35,ease:"easeOut"}})};function D({className:a}){return e.jsx("div",{className:_("animate-pulse rounded-lg bg-muted",a)})}function fe(a){const c=a.trim().split(/\s+/);if(c.length<5)return a;const[n,l,x,,d]=c;return a==="* * * * *"?"Every minute":n==="0"&&l==="*"?"Every hour":n==="*/5"&&l==="*"?"Every 5 minutes":n==="*/10"&&l==="*"?"Every 10 minutes":n==="*/15"&&l==="*"?"Every 15 minutes":n==="*/30"&&l==="*"?"Every 30 minutes":x==="*"&&d==="*"&&l!=="*"&&n!=="*"?`Daily at ${l.padStart(2,"0")}:${n.padStart(2,"0")}`:d==="1-5"&&l!=="*"?`Weekdays at ${l.padStart(2,"0")}:${n.padStart(2,"0")}`:a}function ge(a){return a<60?`${a}s delay`:a<3600?`${Math.round(a/60)}m delay`:`${(a/3600).toFixed(1)}h delay`}function $e(){const[a,c]=r.useState([]),[n,l]=r.useState(!0),[x,d]=r.useState(""),[m,p]=r.useState(null),[F,h]=r.useState(!1),[j,M]=r.useState(null),[i,o]=r.useState({description:"",cron:"",delaySeconds:"",prompt:"",skillName:""}),[E,A]=r.useState(!1),[f,v]=r.useState(null),[N,T]=r.useState(!1),I=r.useCallback(()=>{l(!0),C.schedules.list().then(s=>{c(s.schedules),d("")}).catch(s=>d(s.message)).finally(()=>l(!1))},[]);r.useEffect(()=>{I()},[I]),r.useEffect(()=>{if(!m)return;const s=setTimeout(()=>p(null),3e3);return()=>clearTimeout(s)},[m]);function z(s){var t;M(s.id),o({description:s.description,cron:s.cron??"",delaySeconds:((t=s.delaySeconds)==null?void 0:t.toString())??"",prompt:s.prompt??"",skillName:s.skillName??""}),h(!0)}async function R(){if(j){A(!0);try{const s={description:i.description};i.cron.trim()&&(s.cron=i.cron.trim()),i.delaySeconds.trim()&&(s.delaySeconds=Number(i.delaySeconds)),i.prompt.trim()&&(s.prompt=i.prompt.trim()),i.skillName.trim()&&(s.skillName=i.skillName.trim());const t=await C.schedules.update(j,s);t.success&&(c(S=>S.map(k=>k.id===j?{...k,...t.schedule}:k)),p({type:"success",message:"Schedule updated"}),h(!1))}catch(s){p({type:"error",message:s instanceof Error?s.message:"Update failed"})}finally{A(!1)}}}async function B(){if(f){T(!0);try{(await C.schedules.delete(f)).success&&(c(t=>t.filter(S=>S.id!==f)),p({type:"success",message:"Schedule deleted"}))}catch(s){p({type:"error",message:s instanceof Error?s.message:"Delete failed"})}finally{T(!1),v(null)}}}return x&&!a.length?e.jsx("div",{className:"flex h-full items-center justify-center p-8",children:e.jsx("p",{className:"text-sm text-destructive",children:x})}):n?e.jsxs("div",{className:"space-y-6 p-6 lg:p-8",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(D,{className:"h-8 w-40"}),e.jsx(D,{className:"h-4 w-56"})]}),e.jsx("div",{className:"flex flex-col gap-4",children:Array.from({length:3}).map((s,t)=>e.jsx(D,{className:"h-[140px]"},t))})]}):e.jsxs("div",{className:"space-y-6 p-6 lg:p-8",children:[e.jsxs(g.div,{initial:{opacity:0,y:-8},animate:{opacity:1,y:0},transition:{duration:.3},children:[e.jsx("h1",{className:"text-2xl font-bold tracking-tight",children:"Schedules"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Automated recurring tasks"})]}),e.jsx(L,{children:m&&e.jsx(g.div,{initial:{opacity:0,y:-8},animate:{opacity:1,y:0},exit:{opacity:0,y:-8},className:_("rounded-lg border px-4 py-2.5 text-sm font-medium",m.type==="success"?"border-emerald-500/30 bg-emerald-500/10 text-emerald-500":"border-destructive/30 bg-destructive/10 text-destructive"),children:m.message})}),a.length===0?e.jsx(g.div,{initial:{opacity:0,scale:.96},animate:{opacity:1,scale:1},transition:{duration:.3},children:e.jsx($,{children:e.jsxs(O,{className:"flex flex-col items-center justify-center py-16 text-center",children:[e.jsx(re,{className:"mb-4 h-10 w-10 text-muted-foreground/50"}),e.jsx("p",{className:"text-lg font-medium text-muted-foreground",children:"No scheduled tasks"}),e.jsx("p",{className:"mt-1 text-sm text-muted-foreground/70",children:"Schedules will appear here once configured via the API or CLI."})]})})}):e.jsx("div",{className:"flex flex-col gap-4",children:a.map((s,t)=>e.jsx(g.div,{custom:t,variants:he,initial:"hidden",animate:"visible",children:e.jsxs($,{children:[e.jsxs(H,{className:"flex flex-row items-start justify-between gap-4 pb-3",children:[e.jsxs("div",{className:"min-w-0 flex-1 space-y-1",children:[e.jsx(U,{className:"text-base",children:s.description}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[s.cron&&e.jsxs(b,{variant:"secondary",className:"gap-1",children:[e.jsx(de,{className:"h-3 w-3"}),fe(s.cron)]}),s.delaySeconds!=null&&e.jsxs(b,{variant:"secondary",className:"gap-1",children:[e.jsx(pe,{className:"h-3 w-3"}),ge(s.delaySeconds)]}),s.skillName&&e.jsxs(b,{variant:"default",className:"gap-1",children:[e.jsx(ne,{className:"h-3 w-3"}),s.skillName]})]})]}),e.jsxs("div",{className:"flex shrink-0 gap-1",children:[e.jsx(y,{variant:"ghost",size:"icon",onClick:()=>z(s),children:e.jsx(ce,{className:"h-4 w-4"})}),e.jsx(y,{variant:"ghost",size:"icon",onClick:()=>v(s.id),children:e.jsx(V,{className:"h-4 w-4 text-destructive"})})]})]}),e.jsx(O,{children:e.jsxs("div",{className:"flex flex-col gap-2 text-sm",children:[s.prompt&&e.jsxs("p",{className:"text-muted-foreground",children:[e.jsx("span",{className:"font-medium text-foreground",children:"Prompt: "}),le(s.prompt,100)]}),e.jsxs("div",{className:"flex flex-wrap gap-x-6 gap-y-1 text-xs text-muted-foreground",children:[s.lastRun&&e.jsxs("span",{children:["Last run:"," ",e.jsx("span",{className:"font-medium tabular-nums text-foreground",children:P(s.lastRun)})]}),s.nextRun&&e.jsxs("span",{children:["Next run:"," ",e.jsx("span",{className:"font-medium tabular-nums text-foreground",children:P(s.nextRun)})]})]})]})})]})},s.id))}),e.jsx(q,{open:F,onOpenChange:h,children:e.jsxs(W,{children:[e.jsxs(G,{children:[e.jsx(J,{children:"Edit Schedule"}),e.jsx(K,{children:"Update the schedule configuration."})]}),e.jsxs("div",{className:"flex flex-col gap-4 py-2",children:[e.jsxs("div",{className:"space-y-1.5",children:[e.jsx("label",{className:"text-sm font-medium",children:"Description"}),e.jsx(u,{value:i.description,onChange:s=>o(t=>({...t,description:s.target.value})),placeholder:"Schedule description"})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{className:"space-y-1.5",children:[e.jsx("label",{className:"text-sm font-medium",children:"Cron Expression"}),e.jsx(u,{value:i.cron,onChange:s=>o(t=>({...t,cron:s.target.value})),placeholder:"*/30 * * * *"})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx("label",{className:"text-sm font-medium",children:"Delay (seconds)"}),e.jsx(u,{type:"number",value:i.delaySeconds,onChange:s=>o(t=>({...t,delaySeconds:s.target.value})),placeholder:"3600"})]})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx("label",{className:"text-sm font-medium",children:"Prompt"}),e.jsx(u,{value:i.prompt,onChange:s=>o(t=>({...t,prompt:s.target.value})),placeholder:"Optional prompt text"})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx("label",{className:"text-sm font-medium",children:"Skill Name"}),e.jsx(u,{value:i.skillName,onChange:s=>o(t=>({...t,skillName:s.target.value})),placeholder:"Optional skill name"})]})]}),e.jsxs(Q,{children:[e.jsx(y,{variant:"outline",onClick:()=>h(!1),children:"Cancel"}),e.jsx(y,{onClick:R,disabled:E||!i.description.trim(),children:E?"Saving...":"Save"})]})]})}),e.jsx(X,{open:!!f,onOpenChange:s=>!s&&v(null),children:e.jsxs(Y,{children:[e.jsxs(Z,{children:[e.jsxs(ee,{className:"flex items-center gap-2",children:[e.jsx(xe,{className:"h-5 w-5 text-destructive"}),"Delete Schedule"]}),e.jsx(se,{children:"This action cannot be undone. The scheduled task will be permanently removed."})]}),e.jsxs(te,{children:[e.jsx(ae,{disabled:N,children:"Cancel"}),e.jsx(ie,{onClick:B,disabled:N,className:"bg-destructive text-destructive-foreground hover:bg-destructive/90",children:N?"Deleting...":"Delete"})]})]})})]})}export{$e as SchedulesPage};
|
|
17
|
-
//# sourceMappingURL=Schedules-
|
|
17
|
+
//# sourceMappingURL=Schedules-BZKhm9R7.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Schedules-BQwE1hP5.js","sources":["../../node_modules/lucide-react/dist/esm/icons/calendar.js","../../node_modules/lucide-react/dist/esm/icons/timer.js","../../node_modules/lucide-react/dist/esm/icons/triangle-alert.js","../../src/pages/Schedules.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M8 2v4\", key: \"1cmpym\" }],\n [\"path\", { d: \"M16 2v4\", key: \"4m81vk\" }],\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"4\", rx: \"2\", key: \"1hopcy\" }],\n [\"path\", { d: \"M3 10h18\", key: \"8toen8\" }]\n];\nconst Calendar = createLucideIcon(\"calendar\", __iconNode);\n\nexport { __iconNode, Calendar as default };\n//# sourceMappingURL=calendar.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"line\", { x1: \"10\", x2: \"14\", y1: \"2\", y2: \"2\", key: \"14vaq8\" }],\n [\"line\", { x1: \"12\", x2: \"15\", y1: \"14\", y2: \"11\", key: \"17fdiu\" }],\n [\"circle\", { cx: \"12\", cy: \"14\", r: \"8\", key: \"1e1u0o\" }]\n];\nconst Timer = createLucideIcon(\"timer\", __iconNode);\n\nexport { __iconNode, Timer as default };\n//# sourceMappingURL=timer.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\",\n key: \"wmoenq\"\n }\n ],\n [\"path\", { d: \"M12 9v4\", key: \"juzpu7\" }],\n [\"path\", { d: \"M12 17h.01\", key: \"p32p05\" }]\n];\nconst TriangleAlert = createLucideIcon(\"triangle-alert\", __iconNode);\n\nexport { __iconNode, TriangleAlert as default };\n//# sourceMappingURL=triangle-alert.js.map\n","import { useEffect, useState, useCallback } from \"react\";\nimport { motion, AnimatePresence } from \"framer-motion\";\nimport {\n Clock,\n Pencil,\n Trash2,\n Calendar,\n Timer,\n Sparkles,\n AlertTriangle,\n} from \"lucide-react\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"@/components/ui/card\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { Button } from \"@/components/ui/button\";\nimport { Input } from \"@/components/ui/input\";\nimport {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogDescription,\n DialogFooter,\n} from \"@/components/ui/dialog\";\nimport {\n AlertDialog,\n AlertDialogContent,\n AlertDialogHeader,\n AlertDialogTitle,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogAction,\n AlertDialogCancel,\n} from \"@/components/ui/alert-dialog\";\nimport { cn, formatDate, truncate } from \"@/lib/utils\";\nimport api, { type Schedule } from \"@/lib/api\";\n\nconst fadeUp = {\n hidden: { opacity: 0, y: 12 },\n visible: (i: number) => ({\n opacity: 1,\n y: 0,\n transition: { delay: i * 0.07, duration: 0.35, ease: \"easeOut\" as const },\n }),\n};\n\nfunction Skeleton({ className }: { className?: string }) {\n return (\n <div className={cn(\"animate-pulse rounded-lg bg-muted\", className)} />\n );\n}\n\nfunction humanizeCron(cron: string): string {\n const parts = cron.trim().split(/\\s+/);\n if (parts.length < 5) return cron;\n const [min, hour, dom, , dow] = parts;\n\n if (cron === \"* * * * *\") return \"Every minute\";\n if (min === \"0\" && hour === \"*\") return \"Every hour\";\n if (min === \"*/5\" && hour === \"*\") return \"Every 5 minutes\";\n if (min === \"*/10\" && hour === \"*\") return \"Every 10 minutes\";\n if (min === \"*/15\" && hour === \"*\") return \"Every 15 minutes\";\n if (min === \"*/30\" && hour === \"*\") return \"Every 30 minutes\";\n if (dom === \"*\" && dow === \"*\" && hour !== \"*\" && min !== \"*\")\n return `Daily at ${hour.padStart(2, \"0\")}:${min.padStart(2, \"0\")}`;\n if (dow === \"1-5\" && hour !== \"*\")\n return `Weekdays at ${hour.padStart(2, \"0\")}:${min.padStart(2, \"0\")}`;\n return cron;\n}\n\nfunction humanizeDelay(seconds: number): string {\n if (seconds < 60) return `${seconds}s delay`;\n if (seconds < 3600) return `${Math.round(seconds / 60)}m delay`;\n return `${(seconds / 3600).toFixed(1)}h delay`;\n}\n\ninterface EditForm {\n description: string;\n cron: string;\n delaySeconds: string;\n prompt: string;\n skillName: string;\n}\n\nexport function SchedulesPage() {\n const [schedules, setSchedules] = useState<Schedule[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState(\"\");\n const [feedback, setFeedback] = useState<{ type: \"success\" | \"error\"; message: string } | null>(null);\n\n // Edit dialog state\n const [editOpen, setEditOpen] = useState(false);\n const [editId, setEditId] = useState<string | null>(null);\n const [editForm, setEditForm] = useState<EditForm>({\n description: \"\",\n cron: \"\",\n delaySeconds: \"\",\n prompt: \"\",\n skillName: \"\",\n });\n const [saving, setSaving] = useState(false);\n\n // Delete dialog state\n const [deleteId, setDeleteId] = useState<string | null>(null);\n const [deleting, setDeleting] = useState(false);\n\n const load = useCallback(() => {\n setLoading(true);\n api.schedules\n .list()\n .then((res) => {\n setSchedules(res.schedules);\n setError(\"\");\n })\n .catch((err: Error) => setError(err.message))\n .finally(() => setLoading(false));\n }, []);\n\n useEffect(() => {\n load();\n }, [load]);\n\n // Auto-dismiss feedback\n useEffect(() => {\n if (!feedback) return;\n const t = setTimeout(() => setFeedback(null), 3000);\n return () => clearTimeout(t);\n }, [feedback]);\n\n function openEdit(schedule: Schedule) {\n setEditId(schedule.id);\n setEditForm({\n description: schedule.description,\n cron: schedule.cron ?? \"\",\n delaySeconds: schedule.delaySeconds?.toString() ?? \"\",\n prompt: schedule.prompt ?? \"\",\n skillName: schedule.skillName ?? \"\",\n });\n setEditOpen(true);\n }\n\n async function handleSave() {\n if (!editId) return;\n setSaving(true);\n try {\n const payload: Partial<Schedule> = {\n description: editForm.description,\n };\n if (editForm.cron.trim()) payload.cron = editForm.cron.trim();\n if (editForm.delaySeconds.trim())\n payload.delaySeconds = Number(editForm.delaySeconds);\n if (editForm.prompt.trim()) payload.prompt = editForm.prompt.trim();\n if (editForm.skillName.trim())\n payload.skillName = editForm.skillName.trim();\n\n const res = await api.schedules.update(editId, payload);\n if (res.success) {\n setSchedules((prev) =>\n prev.map((s) => (s.id === editId ? { ...s, ...res.schedule } : s))\n );\n setFeedback({ type: \"success\", message: \"Schedule updated\" });\n setEditOpen(false);\n }\n } catch (err) {\n setFeedback({\n type: \"error\",\n message: err instanceof Error ? err.message : \"Update failed\",\n });\n } finally {\n setSaving(false);\n }\n }\n\n async function handleDelete() {\n if (!deleteId) return;\n setDeleting(true);\n try {\n const res = await api.schedules.delete(deleteId);\n if (res.success) {\n setSchedules((prev) => prev.filter((s) => s.id !== deleteId));\n setFeedback({ type: \"success\", message: \"Schedule deleted\" });\n }\n } catch (err) {\n setFeedback({\n type: \"error\",\n message: err instanceof Error ? err.message : \"Delete failed\",\n });\n } finally {\n setDeleting(false);\n setDeleteId(null);\n }\n }\n\n if (error && !schedules.length) {\n return (\n <div className=\"flex h-full items-center justify-center p-8\">\n <p className=\"text-sm text-destructive\">{error}</p>\n </div>\n );\n }\n\n if (loading) {\n return (\n <div className=\"space-y-6 p-6 lg:p-8\">\n <div className=\"space-y-1\">\n <Skeleton className=\"h-8 w-40\" />\n <Skeleton className=\"h-4 w-56\" />\n </div>\n <div className=\"flex flex-col gap-4\">\n {Array.from({ length: 3 }).map((_, i) => (\n <Skeleton key={i} className=\"h-[140px]\" />\n ))}\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"space-y-6 p-6 lg:p-8\">\n {/* Header */}\n <motion.div\n initial={{ opacity: 0, y: -8 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ duration: 0.3 }}\n >\n <h1 className=\"text-2xl font-bold tracking-tight\">Schedules</h1>\n <p className=\"text-sm text-muted-foreground\">\n Automated recurring tasks\n </p>\n </motion.div>\n\n {/* Feedback toast */}\n <AnimatePresence>\n {feedback && (\n <motion.div\n initial={{ opacity: 0, y: -8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n className={cn(\n \"rounded-lg border px-4 py-2.5 text-sm font-medium\",\n feedback.type === \"success\"\n ? \"border-emerald-500/30 bg-emerald-500/10 text-emerald-500\"\n : \"border-destructive/30 bg-destructive/10 text-destructive\"\n )}\n >\n {feedback.message}\n </motion.div>\n )}\n </AnimatePresence>\n\n {/* Empty state */}\n {schedules.length === 0 ? (\n <motion.div\n initial={{ opacity: 0, scale: 0.96 }}\n animate={{ opacity: 1, scale: 1 }}\n transition={{ duration: 0.3 }}\n >\n <Card>\n <CardContent className=\"flex flex-col items-center justify-center py-16 text-center\">\n <Clock className=\"mb-4 h-10 w-10 text-muted-foreground/50\" />\n <p className=\"text-lg font-medium text-muted-foreground\">\n No scheduled tasks\n </p>\n <p className=\"mt-1 text-sm text-muted-foreground/70\">\n Schedules will appear here once configured via the API or CLI.\n </p>\n </CardContent>\n </Card>\n </motion.div>\n ) : (\n <div className=\"flex flex-col gap-4\">\n {schedules.map((schedule, idx) => (\n <motion.div\n key={schedule.id}\n custom={idx}\n variants={fadeUp}\n initial=\"hidden\"\n animate=\"visible\"\n >\n <Card>\n <CardHeader className=\"flex flex-row items-start justify-between gap-4 pb-3\">\n <div className=\"min-w-0 flex-1 space-y-1\">\n <CardTitle className=\"text-base\">\n {schedule.description}\n </CardTitle>\n <div className=\"flex flex-wrap items-center gap-2\">\n {schedule.cron && (\n <Badge variant=\"secondary\" className=\"gap-1\">\n <Calendar className=\"h-3 w-3\" />\n {humanizeCron(schedule.cron)}\n </Badge>\n )}\n {schedule.delaySeconds != null && (\n <Badge variant=\"secondary\" className=\"gap-1\">\n <Timer className=\"h-3 w-3\" />\n {humanizeDelay(schedule.delaySeconds)}\n </Badge>\n )}\n {schedule.skillName && (\n <Badge variant=\"default\" className=\"gap-1\">\n <Sparkles className=\"h-3 w-3\" />\n {schedule.skillName}\n </Badge>\n )}\n </div>\n </div>\n <div className=\"flex shrink-0 gap-1\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => openEdit(schedule)}\n >\n <Pencil className=\"h-4 w-4\" />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => setDeleteId(schedule.id)}\n >\n <Trash2 className=\"h-4 w-4 text-destructive\" />\n </Button>\n </div>\n </CardHeader>\n <CardContent>\n <div className=\"flex flex-col gap-2 text-sm\">\n {schedule.prompt && (\n <p className=\"text-muted-foreground\">\n <span className=\"font-medium text-foreground\">Prompt: </span>\n {truncate(schedule.prompt, 100)}\n </p>\n )}\n <div className=\"flex flex-wrap gap-x-6 gap-y-1 text-xs text-muted-foreground\">\n {schedule.lastRun && (\n <span>\n Last run:{\" \"}\n <span className=\"font-medium tabular-nums text-foreground\">\n {formatDate(schedule.lastRun)}\n </span>\n </span>\n )}\n {schedule.nextRun && (\n <span>\n Next run:{\" \"}\n <span className=\"font-medium tabular-nums text-foreground\">\n {formatDate(schedule.nextRun)}\n </span>\n </span>\n )}\n </div>\n </div>\n </CardContent>\n </Card>\n </motion.div>\n ))}\n </div>\n )}\n\n {/* Edit Dialog */}\n <Dialog open={editOpen} onOpenChange={setEditOpen}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>Edit Schedule</DialogTitle>\n <DialogDescription>\n Update the schedule configuration.\n </DialogDescription>\n </DialogHeader>\n <div className=\"flex flex-col gap-4 py-2\">\n <div className=\"space-y-1.5\">\n <label className=\"text-sm font-medium\">Description</label>\n <Input\n value={editForm.description}\n onChange={(e) =>\n setEditForm((f) => ({ ...f, description: e.target.value }))\n }\n placeholder=\"Schedule description\"\n />\n </div>\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-1.5\">\n <label className=\"text-sm font-medium\">Cron Expression</label>\n <Input\n value={editForm.cron}\n onChange={(e) =>\n setEditForm((f) => ({ ...f, cron: e.target.value }))\n }\n placeholder=\"*/30 * * * *\"\n />\n </div>\n <div className=\"space-y-1.5\">\n <label className=\"text-sm font-medium\">Delay (seconds)</label>\n <Input\n type=\"number\"\n value={editForm.delaySeconds}\n onChange={(e) =>\n setEditForm((f) => ({ ...f, delaySeconds: e.target.value }))\n }\n placeholder=\"3600\"\n />\n </div>\n </div>\n <div className=\"space-y-1.5\">\n <label className=\"text-sm font-medium\">Prompt</label>\n <Input\n value={editForm.prompt}\n onChange={(e) =>\n setEditForm((f) => ({ ...f, prompt: e.target.value }))\n }\n placeholder=\"Optional prompt text\"\n />\n </div>\n <div className=\"space-y-1.5\">\n <label className=\"text-sm font-medium\">Skill Name</label>\n <Input\n value={editForm.skillName}\n onChange={(e) =>\n setEditForm((f) => ({ ...f, skillName: e.target.value }))\n }\n placeholder=\"Optional skill name\"\n />\n </div>\n </div>\n <DialogFooter>\n <Button variant=\"outline\" onClick={() => setEditOpen(false)}>\n Cancel\n </Button>\n <Button onClick={handleSave} disabled={saving || !editForm.description.trim()}>\n {saving ? \"Saving...\" : \"Save\"}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n\n {/* Delete Confirmation */}\n <AlertDialog open={!!deleteId} onOpenChange={(open) => !open && setDeleteId(null)}>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle className=\"flex items-center gap-2\">\n <AlertTriangle className=\"h-5 w-5 text-destructive\" />\n Delete Schedule\n </AlertDialogTitle>\n <AlertDialogDescription>\n This action cannot be undone. The scheduled task will be permanently removed.\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel disabled={deleting}>Cancel</AlertDialogCancel>\n <AlertDialogAction\n onClick={handleDelete}\n disabled={deleting}\n className=\"bg-destructive text-destructive-foreground hover:bg-destructive/90\"\n >\n {deleting ? \"Deleting...\" : \"Delete\"}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n </div>\n );\n}\n"],"names":["__iconNode","Calendar","createLucideIcon","Timer","TriangleAlert","fadeUp","i","Skeleton","className","cn","humanizeCron","cron","parts","min","hour","dom","dow","humanizeDelay","seconds","SchedulesPage","schedules","setSchedules","useState","loading","setLoading","error","setError","feedback","setFeedback","editOpen","setEditOpen","editId","setEditId","editForm","setEditForm","saving","setSaving","deleteId","setDeleteId","deleting","setDeleting","load","useCallback","api","res","err","useEffect","t","openEdit","schedule","_a","handleSave","payload","prev","s","handleDelete","jsx","jsxs","_","motion","AnimatePresence","Card","CardContent","Clock","idx","CardHeader","CardTitle","Badge","Sparkles","Button","Pencil","Trash2","truncate","formatDate","Dialog","DialogContent","DialogHeader","DialogTitle","DialogDescription","Input","e","f","DialogFooter","AlertDialog","open","AlertDialogContent","AlertDialogHeader","AlertDialogTitle","AlertTriangle","AlertDialogDescription","AlertDialogFooter","AlertDialogCancel","AlertDialogAction"],"mappings":"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","x_google_ignoreList":[0,1,2]}
|
|
1
|
+
{"version":3,"file":"Schedules-BZKhm9R7.js","sources":["../../node_modules/lucide-react/dist/esm/icons/calendar.js","../../node_modules/lucide-react/dist/esm/icons/timer.js","../../node_modules/lucide-react/dist/esm/icons/triangle-alert.js","../../src/pages/Schedules.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M8 2v4\", key: \"1cmpym\" }],\n [\"path\", { d: \"M16 2v4\", key: \"4m81vk\" }],\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"4\", rx: \"2\", key: \"1hopcy\" }],\n [\"path\", { d: \"M3 10h18\", key: \"8toen8\" }]\n];\nconst Calendar = createLucideIcon(\"calendar\", __iconNode);\n\nexport { __iconNode, Calendar as default };\n//# sourceMappingURL=calendar.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"line\", { x1: \"10\", x2: \"14\", y1: \"2\", y2: \"2\", key: \"14vaq8\" }],\n [\"line\", { x1: \"12\", x2: \"15\", y1: \"14\", y2: \"11\", key: \"17fdiu\" }],\n [\"circle\", { cx: \"12\", cy: \"14\", r: \"8\", key: \"1e1u0o\" }]\n];\nconst Timer = createLucideIcon(\"timer\", __iconNode);\n\nexport { __iconNode, Timer as default };\n//# sourceMappingURL=timer.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\",\n key: \"wmoenq\"\n }\n ],\n [\"path\", { d: \"M12 9v4\", key: \"juzpu7\" }],\n [\"path\", { d: \"M12 17h.01\", key: \"p32p05\" }]\n];\nconst TriangleAlert = createLucideIcon(\"triangle-alert\", __iconNode);\n\nexport { __iconNode, TriangleAlert as default };\n//# sourceMappingURL=triangle-alert.js.map\n","import { useEffect, useState, useCallback } from \"react\";\nimport { motion, AnimatePresence } from \"framer-motion\";\nimport {\n Clock,\n Pencil,\n Trash2,\n Calendar,\n Timer,\n Sparkles,\n AlertTriangle,\n} from \"lucide-react\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"@/components/ui/card\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { Button } from \"@/components/ui/button\";\nimport { Input } from \"@/components/ui/input\";\nimport {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogDescription,\n DialogFooter,\n} from \"@/components/ui/dialog\";\nimport {\n AlertDialog,\n AlertDialogContent,\n AlertDialogHeader,\n AlertDialogTitle,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogAction,\n AlertDialogCancel,\n} from \"@/components/ui/alert-dialog\";\nimport { cn, formatDate, truncate } from \"@/lib/utils\";\nimport api, { type Schedule } from \"@/lib/api\";\n\nconst fadeUp = {\n hidden: { opacity: 0, y: 12 },\n visible: (i: number) => ({\n opacity: 1,\n y: 0,\n transition: { delay: i * 0.07, duration: 0.35, ease: \"easeOut\" as const },\n }),\n};\n\nfunction Skeleton({ className }: { className?: string }) {\n return (\n <div className={cn(\"animate-pulse rounded-lg bg-muted\", className)} />\n );\n}\n\nfunction humanizeCron(cron: string): string {\n const parts = cron.trim().split(/\\s+/);\n if (parts.length < 5) return cron;\n const [min, hour, dom, , dow] = parts;\n\n if (cron === \"* * * * *\") return \"Every minute\";\n if (min === \"0\" && hour === \"*\") return \"Every hour\";\n if (min === \"*/5\" && hour === \"*\") return \"Every 5 minutes\";\n if (min === \"*/10\" && hour === \"*\") return \"Every 10 minutes\";\n if (min === \"*/15\" && hour === \"*\") return \"Every 15 minutes\";\n if (min === \"*/30\" && hour === \"*\") return \"Every 30 minutes\";\n if (dom === \"*\" && dow === \"*\" && hour !== \"*\" && min !== \"*\")\n return `Daily at ${hour.padStart(2, \"0\")}:${min.padStart(2, \"0\")}`;\n if (dow === \"1-5\" && hour !== \"*\")\n return `Weekdays at ${hour.padStart(2, \"0\")}:${min.padStart(2, \"0\")}`;\n return cron;\n}\n\nfunction humanizeDelay(seconds: number): string {\n if (seconds < 60) return `${seconds}s delay`;\n if (seconds < 3600) return `${Math.round(seconds / 60)}m delay`;\n return `${(seconds / 3600).toFixed(1)}h delay`;\n}\n\ninterface EditForm {\n description: string;\n cron: string;\n delaySeconds: string;\n prompt: string;\n skillName: string;\n}\n\nexport function SchedulesPage() {\n const [schedules, setSchedules] = useState<Schedule[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState(\"\");\n const [feedback, setFeedback] = useState<{ type: \"success\" | \"error\"; message: string } | null>(null);\n\n // Edit dialog state\n const [editOpen, setEditOpen] = useState(false);\n const [editId, setEditId] = useState<string | null>(null);\n const [editForm, setEditForm] = useState<EditForm>({\n description: \"\",\n cron: \"\",\n delaySeconds: \"\",\n prompt: \"\",\n skillName: \"\",\n });\n const [saving, setSaving] = useState(false);\n\n // Delete dialog state\n const [deleteId, setDeleteId] = useState<string | null>(null);\n const [deleting, setDeleting] = useState(false);\n\n const load = useCallback(() => {\n setLoading(true);\n api.schedules\n .list()\n .then((res) => {\n setSchedules(res.schedules);\n setError(\"\");\n })\n .catch((err: Error) => setError(err.message))\n .finally(() => setLoading(false));\n }, []);\n\n useEffect(() => {\n load();\n }, [load]);\n\n // Auto-dismiss feedback\n useEffect(() => {\n if (!feedback) return;\n const t = setTimeout(() => setFeedback(null), 3000);\n return () => clearTimeout(t);\n }, [feedback]);\n\n function openEdit(schedule: Schedule) {\n setEditId(schedule.id);\n setEditForm({\n description: schedule.description,\n cron: schedule.cron ?? \"\",\n delaySeconds: schedule.delaySeconds?.toString() ?? \"\",\n prompt: schedule.prompt ?? \"\",\n skillName: schedule.skillName ?? \"\",\n });\n setEditOpen(true);\n }\n\n async function handleSave() {\n if (!editId) return;\n setSaving(true);\n try {\n const payload: Partial<Schedule> = {\n description: editForm.description,\n };\n if (editForm.cron.trim()) payload.cron = editForm.cron.trim();\n if (editForm.delaySeconds.trim())\n payload.delaySeconds = Number(editForm.delaySeconds);\n if (editForm.prompt.trim()) payload.prompt = editForm.prompt.trim();\n if (editForm.skillName.trim())\n payload.skillName = editForm.skillName.trim();\n\n const res = await api.schedules.update(editId, payload);\n if (res.success) {\n setSchedules((prev) =>\n prev.map((s) => (s.id === editId ? { ...s, ...res.schedule } : s))\n );\n setFeedback({ type: \"success\", message: \"Schedule updated\" });\n setEditOpen(false);\n }\n } catch (err) {\n setFeedback({\n type: \"error\",\n message: err instanceof Error ? err.message : \"Update failed\",\n });\n } finally {\n setSaving(false);\n }\n }\n\n async function handleDelete() {\n if (!deleteId) return;\n setDeleting(true);\n try {\n const res = await api.schedules.delete(deleteId);\n if (res.success) {\n setSchedules((prev) => prev.filter((s) => s.id !== deleteId));\n setFeedback({ type: \"success\", message: \"Schedule deleted\" });\n }\n } catch (err) {\n setFeedback({\n type: \"error\",\n message: err instanceof Error ? err.message : \"Delete failed\",\n });\n } finally {\n setDeleting(false);\n setDeleteId(null);\n }\n }\n\n if (error && !schedules.length) {\n return (\n <div className=\"flex h-full items-center justify-center p-8\">\n <p className=\"text-sm text-destructive\">{error}</p>\n </div>\n );\n }\n\n if (loading) {\n return (\n <div className=\"space-y-6 p-6 lg:p-8\">\n <div className=\"space-y-1\">\n <Skeleton className=\"h-8 w-40\" />\n <Skeleton className=\"h-4 w-56\" />\n </div>\n <div className=\"flex flex-col gap-4\">\n {Array.from({ length: 3 }).map((_, i) => (\n <Skeleton key={i} className=\"h-[140px]\" />\n ))}\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"space-y-6 p-6 lg:p-8\">\n {/* Header */}\n <motion.div\n initial={{ opacity: 0, y: -8 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ duration: 0.3 }}\n >\n <h1 className=\"text-2xl font-bold tracking-tight\">Schedules</h1>\n <p className=\"text-sm text-muted-foreground\">\n Automated recurring tasks\n </p>\n </motion.div>\n\n {/* Feedback toast */}\n <AnimatePresence>\n {feedback && (\n <motion.div\n initial={{ opacity: 0, y: -8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n className={cn(\n \"rounded-lg border px-4 py-2.5 text-sm font-medium\",\n feedback.type === \"success\"\n ? \"border-emerald-500/30 bg-emerald-500/10 text-emerald-500\"\n : \"border-destructive/30 bg-destructive/10 text-destructive\"\n )}\n >\n {feedback.message}\n </motion.div>\n )}\n </AnimatePresence>\n\n {/* Empty state */}\n {schedules.length === 0 ? (\n <motion.div\n initial={{ opacity: 0, scale: 0.96 }}\n animate={{ opacity: 1, scale: 1 }}\n transition={{ duration: 0.3 }}\n >\n <Card>\n <CardContent className=\"flex flex-col items-center justify-center py-16 text-center\">\n <Clock className=\"mb-4 h-10 w-10 text-muted-foreground/50\" />\n <p className=\"text-lg font-medium text-muted-foreground\">\n No scheduled tasks\n </p>\n <p className=\"mt-1 text-sm text-muted-foreground/70\">\n Schedules will appear here once configured via the API or CLI.\n </p>\n </CardContent>\n </Card>\n </motion.div>\n ) : (\n <div className=\"flex flex-col gap-4\">\n {schedules.map((schedule, idx) => (\n <motion.div\n key={schedule.id}\n custom={idx}\n variants={fadeUp}\n initial=\"hidden\"\n animate=\"visible\"\n >\n <Card>\n <CardHeader className=\"flex flex-row items-start justify-between gap-4 pb-3\">\n <div className=\"min-w-0 flex-1 space-y-1\">\n <CardTitle className=\"text-base\">\n {schedule.description}\n </CardTitle>\n <div className=\"flex flex-wrap items-center gap-2\">\n {schedule.cron && (\n <Badge variant=\"secondary\" className=\"gap-1\">\n <Calendar className=\"h-3 w-3\" />\n {humanizeCron(schedule.cron)}\n </Badge>\n )}\n {schedule.delaySeconds != null && (\n <Badge variant=\"secondary\" className=\"gap-1\">\n <Timer className=\"h-3 w-3\" />\n {humanizeDelay(schedule.delaySeconds)}\n </Badge>\n )}\n {schedule.skillName && (\n <Badge variant=\"default\" className=\"gap-1\">\n <Sparkles className=\"h-3 w-3\" />\n {schedule.skillName}\n </Badge>\n )}\n </div>\n </div>\n <div className=\"flex shrink-0 gap-1\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => openEdit(schedule)}\n >\n <Pencil className=\"h-4 w-4\" />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => setDeleteId(schedule.id)}\n >\n <Trash2 className=\"h-4 w-4 text-destructive\" />\n </Button>\n </div>\n </CardHeader>\n <CardContent>\n <div className=\"flex flex-col gap-2 text-sm\">\n {schedule.prompt && (\n <p className=\"text-muted-foreground\">\n <span className=\"font-medium text-foreground\">Prompt: </span>\n {truncate(schedule.prompt, 100)}\n </p>\n )}\n <div className=\"flex flex-wrap gap-x-6 gap-y-1 text-xs text-muted-foreground\">\n {schedule.lastRun && (\n <span>\n Last run:{\" \"}\n <span className=\"font-medium tabular-nums text-foreground\">\n {formatDate(schedule.lastRun)}\n </span>\n </span>\n )}\n {schedule.nextRun && (\n <span>\n Next run:{\" \"}\n <span className=\"font-medium tabular-nums text-foreground\">\n {formatDate(schedule.nextRun)}\n </span>\n </span>\n )}\n </div>\n </div>\n </CardContent>\n </Card>\n </motion.div>\n ))}\n </div>\n )}\n\n {/* Edit Dialog */}\n <Dialog open={editOpen} onOpenChange={setEditOpen}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>Edit Schedule</DialogTitle>\n <DialogDescription>\n Update the schedule configuration.\n </DialogDescription>\n </DialogHeader>\n <div className=\"flex flex-col gap-4 py-2\">\n <div className=\"space-y-1.5\">\n <label className=\"text-sm font-medium\">Description</label>\n <Input\n value={editForm.description}\n onChange={(e) =>\n setEditForm((f) => ({ ...f, description: e.target.value }))\n }\n placeholder=\"Schedule description\"\n />\n </div>\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-1.5\">\n <label className=\"text-sm font-medium\">Cron Expression</label>\n <Input\n value={editForm.cron}\n onChange={(e) =>\n setEditForm((f) => ({ ...f, cron: e.target.value }))\n }\n placeholder=\"*/30 * * * *\"\n />\n </div>\n <div className=\"space-y-1.5\">\n <label className=\"text-sm font-medium\">Delay (seconds)</label>\n <Input\n type=\"number\"\n value={editForm.delaySeconds}\n onChange={(e) =>\n setEditForm((f) => ({ ...f, delaySeconds: e.target.value }))\n }\n placeholder=\"3600\"\n />\n </div>\n </div>\n <div className=\"space-y-1.5\">\n <label className=\"text-sm font-medium\">Prompt</label>\n <Input\n value={editForm.prompt}\n onChange={(e) =>\n setEditForm((f) => ({ ...f, prompt: e.target.value }))\n }\n placeholder=\"Optional prompt text\"\n />\n </div>\n <div className=\"space-y-1.5\">\n <label className=\"text-sm font-medium\">Skill Name</label>\n <Input\n value={editForm.skillName}\n onChange={(e) =>\n setEditForm((f) => ({ ...f, skillName: e.target.value }))\n }\n placeholder=\"Optional skill name\"\n />\n </div>\n </div>\n <DialogFooter>\n <Button variant=\"outline\" onClick={() => setEditOpen(false)}>\n Cancel\n </Button>\n <Button onClick={handleSave} disabled={saving || !editForm.description.trim()}>\n {saving ? \"Saving...\" : \"Save\"}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n\n {/* Delete Confirmation */}\n <AlertDialog open={!!deleteId} onOpenChange={(open) => !open && setDeleteId(null)}>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle className=\"flex items-center gap-2\">\n <AlertTriangle className=\"h-5 w-5 text-destructive\" />\n Delete Schedule\n </AlertDialogTitle>\n <AlertDialogDescription>\n This action cannot be undone. The scheduled task will be permanently removed.\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel disabled={deleting}>Cancel</AlertDialogCancel>\n <AlertDialogAction\n onClick={handleDelete}\n disabled={deleting}\n className=\"bg-destructive text-destructive-foreground hover:bg-destructive/90\"\n >\n {deleting ? \"Deleting...\" : \"Delete\"}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n </div>\n );\n}\n"],"names":["__iconNode","Calendar","createLucideIcon","Timer","TriangleAlert","fadeUp","i","Skeleton","className","cn","humanizeCron","cron","parts","min","hour","dom","dow","humanizeDelay","seconds","SchedulesPage","schedules","setSchedules","useState","loading","setLoading","error","setError","feedback","setFeedback","editOpen","setEditOpen","editId","setEditId","editForm","setEditForm","saving","setSaving","deleteId","setDeleteId","deleting","setDeleting","load","useCallback","api","res","err","useEffect","t","openEdit","schedule","_a","handleSave","payload","prev","s","handleDelete","jsx","jsxs","_","motion","AnimatePresence","Card","CardContent","Clock","idx","CardHeader","CardTitle","Badge","Sparkles","Button","Pencil","Trash2","truncate","formatDate","Dialog","DialogContent","DialogHeader","DialogTitle","DialogDescription","Input","e","f","DialogFooter","AlertDialog","open","AlertDialogContent","AlertDialogHeader","AlertDialogTitle","AlertTriangle","AlertDialogDescription","AlertDialogFooter","AlertDialogCancel","AlertDialogAction"],"mappings":"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","x_google_ignoreList":[0,1,2]}
|