diff --git a/.clawhub/lock.json b/.clawhub/lock.json index cd3e573..fe9380a 100644 --- a/.clawhub/lock.json +++ b/.clawhub/lock.json @@ -3,7 +3,19 @@ "skills": { "automation-workflows": { "version": "0.1.0", - "installedAt": 1774373495681 + "installedAt": 1774374565991 + }, + "competitive-intelligence-market-research": { + "version": "1.0.0", + "installedAt": 1774374441221 + }, + "cbo": { + "version": "1.0.0", + "installedAt": 1774374479849 + }, + "n8n-workflow-automation": { + "version": "1.0.0", + "installedAt": 1774374686820 } } } diff --git a/app/api/clawhub/route.ts b/app/api/clawhub/route.ts index 61cba84..0caac8b 100644 --- a/app/api/clawhub/route.ts +++ b/app/api/clawhub/route.ts @@ -113,10 +113,46 @@ export async function GET(req: NextRequest) { // Clean up await execAsync(`rm -rf ${tempPath} 2>/dev/null`); + // Now analyze project fit + const projectsDir = "/root/.openclaw/workspace/projects"; + const projectMatches: string[] = []; + + try { + const { readdirSync } = await import("fs"); + const { readFile: readFileAsync } = await import("fs/promises"); + + const entries = readdirSync(projectsDir, { withFileTypes: true }); + for (const entry of entries) { + if (entry.isFile() && (entry.name.endsWith(".md") || entry.name.endsWith(".json"))) { + const projectPath = path.join(projectsDir, entry.name); + const projectContent = await readFileAsync(projectPath, "utf-8"); + const projectName = entry.name.replace(/\.(md|json)$/, ""); + + // Simple keyword matching + const skillKeywords = (desc + " " + triggers).toLowerCase(); + const projectKeywords = projectContent.toLowerCase(); + + // Check for keyword overlaps + const overlaps: string[] = []; + const skillWords = skillKeywords.split(/\s+/).filter(w => w.length > 4); + for (const word of skillWords) { + if (projectKeywords.includes(word)) { + overlaps.push(word); + } + } + + if (overlaps.length >= 2) { + projectMatches.push(`${projectName}: ${overlaps.slice(0, 3).join(", ")}`); + } + } + } + } catch {} + return NextResponse.json({ description: desc, triggers: triggers, - raw: content.substring(0, 2000) + raw: content.substring(0, 2000), + projectMatches }); } catch (e: any) { return NextResponse.json({ error: e.message, description: "Could not analyze skill" }); diff --git a/app/mission-control/clawhub/page.tsx b/app/mission-control/clawhub/page.tsx index b628a4e..6f31693 100644 --- a/app/mission-control/clawhub/page.tsx +++ b/app/mission-control/clawhub/page.tsx @@ -215,10 +215,18 @@ export default function ClawHubMarketplace() { description: data.description, triggers: data.triggers }); - setOutput(`📋 ${selectedSkill.name}\n\n` + - `Description: ${data.description || "N/A"}\n\n` + - `Triggers: ${data.triggers || "N/A"}\n\n` + - (data.raw ? `📄 SKILL.md Preview:\n${data.raw.substring(0, 500)}...` : "")); + let output = `📋 ${selectedSkill.name}\n\n`; + output += `Description: ${data.description || "N/A"}\n\n`; + output += `Triggers: ${data.triggers || "N/A"}\n\n`; + if (data.projectMatches && data.projectMatches.length > 0) { + output += `🎯 Project Matches:\n`; + data.projectMatches.forEach((m: string) => { + output += ` • ${m}\n`; + }); + output += `\n`; + } + output += (data.raw ? `📄 SKILL.md Preview:\n${data.raw.substring(0, 500)}...` : ""); + setOutput(output); } catch (e) { setOutput("Error: " + String(e)); }