Feat : Skills

This commit is contained in:
decolua
2026-05-04 11:29:02 +07:00
parent f08fa5f78d
commit 9c6be62a54
52 changed files with 2666 additions and 1581 deletions
+7
View File
@@ -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",
+10 -9
View File
@@ -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
+71
View File
@@ -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`;
}