Feat : Skills
This commit is contained in:
@@ -123,6 +123,13 @@ const getPageInfo = (pathname) => {
|
||||
icon: "lan",
|
||||
breadcrumbs: [],
|
||||
};
|
||||
if (pathname.includes("/skills"))
|
||||
return {
|
||||
title: "Agent Skills",
|
||||
description: "Copy a link and paste to your AI to use 9Router — no install needed",
|
||||
icon: "extension",
|
||||
breadcrumbs: [],
|
||||
};
|
||||
if (pathname.includes("/endpoint"))
|
||||
return {
|
||||
title: "Endpoint",
|
||||
|
||||
@@ -34,6 +34,7 @@ const debugItems = [
|
||||
|
||||
const systemItems = [
|
||||
{ href: "/dashboard/proxy-pools", label: "Proxy Pools", icon: "lan" },
|
||||
{ href: "/dashboard/skills", label: "Skills", icon: "extension" },
|
||||
];
|
||||
|
||||
export default function Sidebar({ onClose }) {
|
||||
@@ -171,14 +172,14 @@ export default function Sidebar({ onClose }) {
|
||||
</div>
|
||||
|
||||
{/* Navigation */}
|
||||
<nav className="flex-1 px-4 py-2 space-y-1 overflow-y-auto custom-scrollbar">
|
||||
<nav className="flex-1 px-4 py-2 space-y-0.5 overflow-y-auto custom-scrollbar">
|
||||
{navItems.map((item) => (
|
||||
<Link
|
||||
key={item.href}
|
||||
href={item.href}
|
||||
onClick={onClose}
|
||||
className={cn(
|
||||
"flex items-center gap-3 px-3 py-1.5 rounded-lg transition-all group",
|
||||
"flex items-center gap-3 px-3 py-1 rounded-lg transition-all group",
|
||||
isActive(item.href)
|
||||
? "bg-primary/10 text-primary"
|
||||
: "text-text-muted hover:bg-surface-2 hover:text-text-main"
|
||||
@@ -197,7 +198,7 @@ export default function Sidebar({ onClose }) {
|
||||
))}
|
||||
|
||||
{/* System section */}
|
||||
<div className="pt-4 mt-2 space-y-1">
|
||||
<div className="pt-3 mt-2 space-y-0.5">
|
||||
<p className="px-4 text-xs font-semibold text-text-muted/60 uppercase tracking-wider mb-2">
|
||||
System
|
||||
</p>
|
||||
@@ -206,7 +207,7 @@ export default function Sidebar({ onClose }) {
|
||||
<button
|
||||
onClick={() => setMediaOpen((v) => !v)}
|
||||
className={cn(
|
||||
"w-full flex items-center gap-3 px-3 py-1.5 rounded-lg transition-all group",
|
||||
"w-full flex items-center gap-3 px-3 py-1 rounded-lg transition-all group",
|
||||
pathname.startsWith("/dashboard/media-providers")
|
||||
? "bg-primary/10 text-primary"
|
||||
: "text-text-muted hover:bg-surface-2 hover:text-text-main"
|
||||
@@ -226,7 +227,7 @@ export default function Sidebar({ onClose }) {
|
||||
href={`/dashboard/media-providers/${kind.id}`}
|
||||
onClick={onClose}
|
||||
className={cn(
|
||||
"flex items-center gap-3 px-4 py-1.5 rounded-lg transition-all group",
|
||||
"flex items-center gap-3 px-4 py-1 rounded-lg transition-all group",
|
||||
pathname.startsWith(`/dashboard/media-providers/${kind.id}`)
|
||||
? "bg-primary/10 text-primary"
|
||||
: "text-text-muted hover:bg-surface-2 hover:text-text-main"
|
||||
@@ -241,7 +242,7 @@ export default function Sidebar({ onClose }) {
|
||||
href={COMBINED_WEB_ITEM.href}
|
||||
onClick={onClose}
|
||||
className={cn(
|
||||
"flex items-center gap-3 px-4 py-1.5 rounded-lg transition-all group",
|
||||
"flex items-center gap-3 px-4 py-1 rounded-lg transition-all group",
|
||||
pathname.startsWith(COMBINED_WEB_ITEM.href)
|
||||
? "bg-primary/10 text-primary"
|
||||
: "text-text-muted hover:bg-surface-2 hover:text-text-main"
|
||||
@@ -259,7 +260,7 @@ export default function Sidebar({ onClose }) {
|
||||
href={item.href}
|
||||
onClick={onClose}
|
||||
className={cn(
|
||||
"flex items-center gap-3 px-3 py-1.5 rounded-lg transition-all group",
|
||||
"flex items-center gap-3 px-3 py-1 rounded-lg transition-all group",
|
||||
isActive(item.href)
|
||||
? "bg-primary/10 text-primary"
|
||||
: "text-text-muted hover:bg-surface-2 hover:text-text-main"
|
||||
@@ -286,7 +287,7 @@ export default function Sidebar({ onClose }) {
|
||||
href={item.href}
|
||||
onClick={onClose}
|
||||
className={cn(
|
||||
"flex items-center gap-3 px-3 py-1.5 rounded-lg transition-all group",
|
||||
"flex items-center gap-3 px-3 py-1 rounded-lg transition-all group",
|
||||
isActive(item.href)
|
||||
? "bg-primary/10 text-primary"
|
||||
: "text-text-muted hover:bg-surface-2 hover:text-text-main"
|
||||
@@ -310,7 +311,7 @@ export default function Sidebar({ onClose }) {
|
||||
href="/dashboard/profile"
|
||||
onClick={onClose}
|
||||
className={cn(
|
||||
"flex items-center gap-3 px-3 py-1.5 rounded-lg transition-all group",
|
||||
"flex items-center gap-3 px-3 py-1 rounded-lg transition-all group",
|
||||
isActive("/dashboard/profile")
|
||||
? "bg-primary/10 text-primary"
|
||||
: "text-text-muted hover:bg-surface-2 hover:text-text-main"
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,71 @@
|
||||
// Agent Skills metadata — single source of truth for /dashboard/skills page.
|
||||
// Each skill = 1 raw GitHub URL the user copies and pastes to any AI agent.
|
||||
|
||||
const REPO = "decolua/9router";
|
||||
const BRANCH = "main";
|
||||
const SKILL_PATH = "app/skills";
|
||||
|
||||
export const SKILLS_REPO_URL = `https://github.com/${REPO}`;
|
||||
export const SKILLS_RAW_BASE = `https://raw.githubusercontent.com/${REPO}/${BRANCH}/${SKILL_PATH}`;
|
||||
export const SKILLS_BLOB_BASE = `https://github.com/${REPO}/blob/${BRANCH}/${SKILL_PATH}`;
|
||||
|
||||
export const SKILLS = [
|
||||
{
|
||||
id: "9router",
|
||||
name: "9Router (Entry)",
|
||||
description: "Setup + index of all capabilities. Start here — covers base URL, auth, model discovery, and links to every capability skill.",
|
||||
endpoint: null,
|
||||
icon: "hub",
|
||||
isEntry: true,
|
||||
},
|
||||
{
|
||||
id: "9router-chat",
|
||||
name: "Chat",
|
||||
description: "Chat / code-gen via OpenAI or Anthropic format with streaming.",
|
||||
endpoint: "/v1/chat/completions",
|
||||
icon: "chat",
|
||||
},
|
||||
{
|
||||
id: "9router-image",
|
||||
name: "Image Generation",
|
||||
description: "Text-to-image via DALL-E, Imagen, FLUX, MiniMax, SDWebUI…",
|
||||
endpoint: "/v1/images/generations",
|
||||
icon: "image",
|
||||
},
|
||||
{
|
||||
id: "9router-tts",
|
||||
name: "Text-to-Speech",
|
||||
description: "OpenAI / ElevenLabs / Edge / Google / Deepgram voices.",
|
||||
endpoint: "/v1/audio/speech",
|
||||
icon: "record_voice_over",
|
||||
},
|
||||
{
|
||||
id: "9router-embeddings",
|
||||
name: "Embeddings",
|
||||
description: "Vectors for RAG / semantic search via OpenAI, Gemini, Mistral…",
|
||||
endpoint: "/v1/embeddings",
|
||||
icon: "scatter_plot",
|
||||
},
|
||||
{
|
||||
id: "9router-web-search",
|
||||
name: "Web Search",
|
||||
description: "Tavily / Exa / Brave / Serper / SearXNG / Google PSE / You.com.",
|
||||
endpoint: "/v1/search",
|
||||
icon: "search",
|
||||
},
|
||||
{
|
||||
id: "9router-web-fetch",
|
||||
name: "Web Fetch",
|
||||
description: "URL → markdown / text / HTML via Firecrawl, Jina, Tavily, Exa.",
|
||||
endpoint: "/v1/web/fetch",
|
||||
icon: "language",
|
||||
},
|
||||
];
|
||||
|
||||
export function getSkillRawUrl(id) {
|
||||
return `${SKILLS_RAW_BASE}/${id}/SKILL.md`;
|
||||
}
|
||||
|
||||
export function getSkillBlobUrl(id) {
|
||||
return `${SKILLS_BLOB_BASE}/${id}/SKILL.md`;
|
||||
}
|
||||
Reference in New Issue
Block a user