From bc226b03c8a8e585808ade907b6ed9345f549cf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CBeeRad=E2=80=9D?= Date: Sat, 7 Mar 2026 12:00:52 +1100 Subject: [PATCH] cleanup(skills): remove legacy guide bundle and harden skill migration/pruning --- app/api/skills/[name]/route.ts | 49 ++++++++- apps/mcp-server-standalone/index.js | 4 +- src/components/settings/GuidesViewer.tsx | 53 +++++----- src/components/settings/SettingsModal.tsx | 8 +- src/config/guides/connect.md | 42 -------- src/config/guides/integrate.md | 71 ------------- src/config/guides/preferences.md | 14 --- src/config/guides/prep.md | 39 -------- src/config/guides/research.md | 48 --------- src/config/guides/survey.md | 53 ---------- src/config/guides/system/creating-nodes.md | 48 --------- src/config/guides/system/dimensions.md | 38 ------- src/config/guides/system/edges.md | 51 ---------- src/config/guides/system/extract.md | 33 ------ src/config/guides/system/schema.md | 111 --------------------- src/services/skills/skillService.ts | 53 ++++++++++ 16 files changed, 134 insertions(+), 581 deletions(-) delete mode 100644 src/config/guides/connect.md delete mode 100644 src/config/guides/integrate.md delete mode 100644 src/config/guides/preferences.md delete mode 100644 src/config/guides/prep.md delete mode 100644 src/config/guides/research.md delete mode 100644 src/config/guides/survey.md delete mode 100644 src/config/guides/system/creating-nodes.md delete mode 100644 src/config/guides/system/dimensions.md delete mode 100644 src/config/guides/system/edges.md delete mode 100644 src/config/guides/system/extract.md delete mode 100644 src/config/guides/system/schema.md diff --git a/app/api/skills/[name]/route.ts b/app/api/skills/[name]/route.ts index 5a5d05e..f84b958 100644 --- a/app/api/skills/[name]/route.ts +++ b/app/api/skills/[name]/route.ts @@ -1,5 +1,5 @@ import { NextRequest, NextResponse } from 'next/server'; -import { readSkill, deleteSkill } from '@/services/skills/skillService'; +import { readSkill, writeSkill, deleteSkill } from '@/services/skills/skillService'; export const runtime = 'nodejs'; @@ -50,3 +50,50 @@ export async function DELETE( ); } } + +export async function PUT( + request: NextRequest, + { params }: { params: Promise<{ name: string }> } +) { + try { + const { name } = await params; + const body = await request.json(); + const description = typeof body?.description === 'string' ? body.description.trim() : ''; + const content = typeof body?.content === 'string' ? body.content : ''; + + const safeName = name.trim(); + if (!safeName) { + return NextResponse.json( + { success: false, error: 'Skill name is required' }, + { status: 400 } + ); + } + + const safeDescription = description.replace(/\r?\n/g, ' ').trim(); + const frontmatter = [ + '---', + `name: ${safeName}`, + `description: ${safeDescription}`, + '---', + '', + content.trim(), + '', + ].join('\n'); + + const result = writeSkill(safeName, frontmatter); + if (!result.success) { + return NextResponse.json( + { success: false, error: result.error }, + { status: 400 } + ); + } + + return NextResponse.json({ success: true, message: `Skill "${safeName}" saved` }); + } catch (error) { + console.error('[API /skills/[name] PUT] error:', error); + return NextResponse.json( + { success: false, error: error instanceof Error ? error.message : 'Failed to save skill' }, + { status: 500 } + ); + } +} diff --git a/apps/mcp-server-standalone/index.js b/apps/mcp-server-standalone/index.js index d213ae5..04a05c7 100644 --- a/apps/mcp-server-standalone/index.js +++ b/apps/mcp-server-standalone/index.js @@ -37,7 +37,7 @@ const skillService = require('./services/skillService'); // Server info const serverInfo = { name: 'ra-h-standalone', - version: '1.7.0' + version: '1.8.0' }; function buildInstructions() { @@ -1012,7 +1012,7 @@ async function main() { 'sqliteQuery', { title: 'Execute read-only SQL', - description: 'Execute read-only SQL queries against the knowledge graph database. Tables: nodes, edges, dimensions, node_dimensions, chunks. Use PRAGMA table_info(tablename) for schema. Only SELECT/WITH/PRAGMA allowed. Use when structured tools are insufficient — e.g., complex JOINs, aggregations, or custom filtering. Read readSkill("schema") for table definitions and query patterns.', + description: 'Execute read-only SQL queries against the knowledge graph database. Tables: nodes, edges, dimensions, node_dimensions, chunks. Use PRAGMA table_info(tablename) for schema. Only SELECT/WITH/PRAGMA allowed. Use when structured tools are insufficient — e.g., complex JOINs, aggregations, or custom filtering. Read readSkill("db-operations") for table definitions and query patterns.', inputSchema: sqliteQueryInputSchema }, async ({ sql: userSql, format = 'json' }) => { diff --git a/src/components/settings/GuidesViewer.tsx b/src/components/settings/GuidesViewer.tsx index 3567fad..360accb 100644 --- a/src/components/settings/GuidesViewer.tsx +++ b/src/components/settings/GuidesViewer.tsx @@ -3,19 +3,19 @@ import { useState, useEffect } from 'react'; import { Plus, Pencil, Trash2, Save, X, FileText } from 'lucide-react'; -interface GuideMeta { +interface SkillMeta { name: string; description: string; } -interface Guide extends GuideMeta { +interface Skill extends SkillMeta { content: string; } export default function GuidesViewer() { - const [guides, setGuides] = useState([]); + const [guides, setGuides] = useState([]); const [loading, setLoading] = useState(true); - const [editing, setEditing] = useState(null); + const [editing, setEditing] = useState(null); const [isNew, setIsNew] = useState(false); const [error, setError] = useState(null); @@ -25,13 +25,13 @@ export default function GuidesViewer() { const fetchGuides = async () => { try { - const res = await fetch('/api/guides'); + const res = await fetch('/api/skills'); const data = await res.json(); if (data.success) { setGuides(data.data); } } catch (err) { - console.error('Failed to fetch guides:', err); + console.error('Failed to fetch skills:', err); } finally { setLoading(false); } @@ -39,7 +39,7 @@ export default function GuidesViewer() { const handleEdit = async (name: string) => { try { - const res = await fetch(`/api/guides/${encodeURIComponent(name)}`); + const res = await fetch(`/api/skills/${encodeURIComponent(name)}`); const data = await res.json(); if (data.success) { setEditing(data.data); @@ -47,16 +47,16 @@ export default function GuidesViewer() { setError(null); } } catch (err) { - console.error('Failed to fetch guide:', err); + console.error('Failed to fetch skill:', err); } }; const handleNew = () => { - setEditing({ - name: '', - description: '', - content: '# New Guide\n\nWrite your guide content here...', - }); + setEditing({ + name: '', + description: '', + content: '# New Skill\n\nWrite your skill content here...', + }); setIsNew(true); setError(null); }; @@ -69,7 +69,7 @@ export default function GuidesViewer() { } try { - const res = await fetch(`/api/guides/${encodeURIComponent(editing.name)}`, { + const res = await fetch(`/api/skills/${encodeURIComponent(editing.name)}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ @@ -81,20 +81,21 @@ export default function GuidesViewer() { if (data.success) { setEditing(null); fetchGuides(); + window.dispatchEvent(new Event('skills:updated')); window.dispatchEvent(new Event('guides:updated')); } else { setError(data.error || 'Failed to save'); } } catch (err) { - setError('Failed to save guide'); + setError('Failed to save skill'); } }; const handleDelete = async (name: string) => { - if (!confirm(`Delete guide "${name}"?`)) return; + if (!confirm(`Delete skill "${name}"?`)) return; try { - const res = await fetch(`/api/guides/${encodeURIComponent(name)}`, { + const res = await fetch(`/api/skills/${encodeURIComponent(name)}`, { method: 'DELETE', }); const data = await res.json(); @@ -103,13 +104,13 @@ export default function GuidesViewer() { window.dispatchEvent(new Event('guides:updated')); } } catch (err) { - console.error('Failed to delete guide:', err); + console.error('Failed to delete skill:', err); } }; if (loading) { return ( -
Loading guides...
+
Loading skills...
); } @@ -121,7 +122,7 @@ export default function GuidesViewer() { type="text" value={editing.name} onChange={(e) => setEditing({ ...editing, name: e.target.value })} - placeholder="Guide name" + placeholder="Skill name" disabled={!isNew} style={{ flex: 1, @@ -193,7 +194,7 @@ export default function GuidesViewer() {