Conversation
|
@claude review this, propose change of skills routes from FastAPI to TanStack server funcs |
|
Claude finished @DIodide's task in 2m 17s —— View job PR Review + TanStack Migration Proposal
Code ReviewOverall this is a solid integration. The pattern of storing Bugs / Correctness
Architecture
Minor
Proposed Migration: Skills Routes → TanStack Server FunctionsWhy migrate?
What stays in FastAPI: The Step 1 — Create import { createServerFn } from "@tanstack/react-start";
const HF_BASE = "https://datasets-server.huggingface.co";
const HF_COMMON = "dataset=tickleliu/all-skills-from-skills-sh&config=default&split=train";
function stripDetail(entry: Record<string, unknown>) {
const r = (entry.row ?? entry) as Record<string, unknown>;
return {
name: (r.name as string) ?? "",
skill_name: (r.skill_name as string) ?? "",
description: (r.description as string) ?? "",
code: (r.code as string) ?? "",
};
}
export const listSkillsFn = createServerFn({ method: "GET" })
.validator((data: { offset: number; limit: number }) => data)
.handler(async ({ data }) => {
const { offset, limit } = data;
const resp = await fetch(
`${HF_BASE}/rows?${HF_COMMON}&offset=${offset}&length=${limit}`,
);
if (!resp.ok) throw new Error("Failed to fetch skills from catalog");
const json = await resp.json();
return {
rows: (json.rows as Record<string, unknown>[]).map(stripDetail),
total: (json.num_rows_total as number) ?? 0,
offset,
limit,
};
});
export const searchSkillsFn = createServerFn({ method: "GET" })
.validator((data: { q: string; offset: number; limit: number }) => data)
.handler(async ({ data }) => {
const { q, offset, limit } = data;
const encoded = encodeURIComponent(q);
const resp = await fetch(
`${HF_BASE}/search?${HF_COMMON}&query=${encoded}&offset=${offset}&length=${limit}`,
);
if (!resp.ok) throw new Error("Failed to search skills catalog");
const json = await resp.json();
return {
rows: (json.rows as Record<string, unknown>[]).map(stripDetail),
total: (json.num_rows_total as number) ?? 0,
offset,
limit,
};
});Step 2 — Update Replace the direct // Before (skills-browser.tsx:57-63)
queryFn: async () => {
const endpoint = debouncedSearch
? `${API_URL}/api/skills/search?q=${encodeURIComponent(debouncedSearch)}&offset=${offset}&limit=${PAGE_SIZE}`
: `${API_URL}/api/skills?offset=${offset}&limit=${PAGE_SIZE}`;
const res = await fetch(endpoint);
if (!res.ok) throw new Error("Failed to fetch skills");
return res.json();
},
// After
queryFn: () =>
debouncedSearch
? searchSkillsFn({ data: { q: debouncedSearch, offset, limit: PAGE_SIZE } })
: listSkillsFn({ data: { offset, limit: PAGE_SIZE } }),Then remove the Step 3 — Remove the FastAPI skills route # packages/fastapi/app/main.py
-from app.routes import chat, health, mcp_health, mcp_oauth, skills
+from app.routes import chat, health, mcp_health, mcp_oauth
-app.include_router(skills.router, prefix="/api/skills", tags=["skills"])Delete Trade-off to consider: TanStack server functions run on the Node.js SSR server, so catalog fetches will originate from your server IP rather than the browser. If HuggingFace has per-IP rate limits this concentrates requests. At 50k skills with pagination this is unlikely to be an issue in practice, but worth keeping in mind. If rate limiting becomes a concern, a light caching layer (e.g. a 60-second in-memory cache keyed on |
|
@claude review this |
|
Claude finished @DIodide's task in 2m 46s —— View job PR Review: skills.sh Catalog Integration
Note: The TanStack migration proposed in the previous review is already applied in commit Bugs / Correctness1. When the HuggingFace top-5 search doesn't contain an exact name match, Fix: either skip insertion when 2. Chat-time HuggingFace fallback has the same exact-match fragility (
3. Hardcoded ngrok URL committed in "https://aab7-140-180-240-231.ngrok-free.app",This URL will expire and is a dev artifact. It should either be in env config or removed. Also Architecture4. if (existing) return existing._id; // always skips if any record existsIf a skill's 5. A custom 6. skills: Array<{ name: string; description: string }>;The shared Minor7. 8. What's Good
|
PR: Skills.sh Catalog Integration
Branch:
feak/skills.sh→stagingSummary
Integrates the full skills.sh catalog (~50,000 skills) into the platform. Users can browse, search, and add skills to their harnesses. Selected skills are passed to the LLM during chat as a manifest, and a custom
get_skill_contenttool lets the model retrieve full skill markdown on demand.What Changed
New: Skills Catalog Proxy (FastAPI)
packages/fastapi/app/routes/skills.py— Three new endpoints (/api/skills,/api/skills/search,/api/skills/detail) that proxy the HuggingFace Dataset Server API. List and search responses strip thedetailfield to keep payloads small for the browser.main.pyunder/api/skills.New: Convex Skills Backend
packages/convex-backend/convex/skills.ts— Queries (getByName,getByNames) and anensureSkillDetailsaction that lazily fetches and stores full skill markdown from HuggingFace into a newskillDetailstable. Skill detail is only persisted when a harness containing that skill is saved, avoiding unnecessary storage.packages/convex-backend/convex/schema.ts— AddedskillDetailstable (name, skillName, description, detail, code) with aby_nameindex. Changedharnesses.skillsfromv.array(v.string())tov.array(v.object({ name, description }))so descriptions travel with the harness and don't require extra queries at chat time.Updated: Harness Mutations
packages/convex-backend/convex/harnesses.ts—create,update, andduplicatemutations updated for the new skills shape. Includes a one-timemigrateSkillsToObjectsinternal mutation that was used to migrate existing documents from the oldstring[]format.packages/convex-backend/convex/seed.ts— Seed data updated to use{ name, description }skill objects.New: Frontend Skills Components
apps/web/src/components/skills-browser.tsx— Paginated, searchable skill catalog browser using TanStack Query. Checkbox-style selection matching the MCP preset grid pattern.apps/web/src/components/recommended-skills-grid.tsx— Curated grid of 9 recommended skills (vercel-react-best-practices, brainstorming, browser-automation, pdf-vision-reader, systematic-debugging, xlsx, code-review, database-schema-design, git-best-practices).apps/web/src/lib/skills.ts— SharedSkillEntrytype andRECOMMENDED_SKILLSdata.0xbigboss/claude-code), and description.Updated: Harness Editor (
$harnessId.tsx)ensureSkillDetailsfires in the background to cache markdown for newly added skills.skillDetailsConvex query for display — descriptions now come directly from the stored skill objects, eliminating flicker.Updated: Onboarding (
onboarding.tsx){ name, description }objects on harness creation.ensureSkillDetailscalled after harness creation to backfill markdown.Updated: Chat Page (
chat/index.tsx)SkillsStatuscomponent in the chat header showing "X Skills" next to the MCP status indicator. Clicking it reveals a dropdown listing all skills in the active harness with their display name and description.skills: Array<{ name, description }>to FastAPI.Updated: Chat Loop (FastAPI
chat.py)get_skill_contenttool definition is added to the tools list sent to the LLM.get_skill_contentare intercepted and handled locally — the backend queries Convex for the cached markdown, falling back to HuggingFace if not yet cached.Updated: FastAPI Models (
models.py)SkillRefmodel (name + description).HarnessConfig.skillschanged fromlist[str]tolist[SkillRef].Updated: Convex Service (
services/convex.py)query_convexhelper to execute Convex queries via the HTTP API using the deploy key. Used by the chat route to fetch skill detail markdown.Minor Fixes
message-attachments.tsx— Replaced ESLint ignore comment with biome-ignore foruseMediaCaption.chat/index.tsx— FixedforEachreturn value lint (useIterableCallbackReturn) by switching tofor...of. Added biome-ignore fornoStaticElementInteractionson the drag-and-drop zone.organizeImportsrule.Files Changed (22 files, +1204 / -136)
routes/skills.py(new),routes/chat.py,models.py,services/convex.py,main.pyschema.ts,harnesses.ts,skills.ts(new),seed.tsskills-browser.tsx(new),recommended-skills-grid.tsx(new)skills.ts(new),use-chat-stream.ts,models.ts,multimodal.tschat/index.tsx,harnesses/$harnessId.tsx,onboarding.tsxattachment-chip.tsx,message-attachments.tsx,use-file-attachments.ts