kompass-sdk 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/sources/l402-directory.d.ts +3 -2
- package/dist/sources/l402-directory.d.ts.map +1 -1
- package/dist/sources/l402-directory.js +57 -32
- package/dist/sources/l402-directory.js.map +1 -1
- package/dist/sources/skills.d.ts +5 -2
- package/dist/sources/skills.d.ts.map +1 -1
- package/dist/sources/skills.js +82 -105
- package/dist/sources/skills.js.map +1 -1
- package/package.json +1 -1
- package/src/sources/l402-directory.ts +56 -36
- package/src/sources/skills.ts +82 -111
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* L402 Directory Source Adapter
|
|
3
|
-
*
|
|
2
|
+
* L402 Lightning Directory Source Adapter
|
|
3
|
+
* Searches 402index.io filtered to L402 (Lightning) protocol
|
|
4
|
+
* Real data — not hardcoded seed list
|
|
4
5
|
*/
|
|
5
6
|
import type { SourceAdapter } from "./types.js";
|
|
6
7
|
export declare const l402DirectoryAdapter: SourceAdapter;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"l402-directory.d.ts","sourceRoot":"","sources":["../../src/sources/l402-directory.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"l402-directory.d.ts","sourceRoot":"","sources":["../../src/sources/l402-directory.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAqC,MAAM,YAAY,CAAC;AAInF,eAAO,MAAM,oBAAoB,EAAE,aA4DlC,CAAC"}
|
|
@@ -1,42 +1,67 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* L402 Directory Source Adapter
|
|
3
|
-
*
|
|
2
|
+
* L402 Lightning Directory Source Adapter
|
|
3
|
+
* Searches 402index.io filtered to L402 (Lightning) protocol
|
|
4
|
+
* Real data — not hardcoded seed list
|
|
4
5
|
*/
|
|
5
|
-
|
|
6
|
-
const KNOWN_L402_SERVICES = [
|
|
7
|
-
{ name: "Satring", url: "https://satring.com", description: "Curated L402 + x402 API directory. 36 endpoints across 4 providers", categories: ["directory", "tools"] },
|
|
8
|
-
{ name: "Lightning Faucet L402", url: "https://lightningfaucet.com", description: "L402 API registry and testing tools", categories: ["tools", "testing"] },
|
|
9
|
-
{ name: "Nostr NIP-68 Bridge", url: "https://l402.nostr.com", description: "L402 payments over Nostr relay network", categories: ["social", "payments"] },
|
|
10
|
-
{ name: "Stacker News", url: "https://stacker.news", description: "Lightning-powered news with L402 API access", categories: ["content", "data"] },
|
|
11
|
-
{ name: "Nodana", url: "https://nodana.io", description: "L402 agentic access for Bitcoin app deployment", categories: ["development", "compute"] },
|
|
12
|
-
];
|
|
6
|
+
const INDEX_API = "https://402index.io/api/v1/services";
|
|
13
7
|
export const l402DirectoryAdapter = {
|
|
14
8
|
name: "l402-directory",
|
|
15
|
-
displayName: "L402 Lightning Directory",
|
|
9
|
+
displayName: "L402 Lightning Directory (402index)",
|
|
16
10
|
async search(query, options) {
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
11
|
+
const limit = options?.limit ?? 20;
|
|
12
|
+
const timeout = options?.timeout ?? 10000;
|
|
13
|
+
try {
|
|
14
|
+
const url = new URL(INDEX_API);
|
|
15
|
+
if (query)
|
|
16
|
+
url.searchParams.set("q", query);
|
|
17
|
+
url.searchParams.set("protocol", "L402");
|
|
18
|
+
url.searchParams.set("limit", String(limit));
|
|
19
|
+
url.searchParams.set("health", "healthy");
|
|
20
|
+
url.searchParams.set("sort", "reliability");
|
|
21
|
+
const res = await fetch(url.toString(), { signal: AbortSignal.timeout(timeout) });
|
|
22
|
+
if (!res.ok)
|
|
23
|
+
return [];
|
|
24
|
+
const data = await res.json();
|
|
25
|
+
const services = data.services ?? data.data ?? [];
|
|
26
|
+
if (!Array.isArray(services))
|
|
27
|
+
return [];
|
|
28
|
+
return services.slice(0, limit).map((s) => ({
|
|
29
|
+
id: `l402-directory:${s.id ?? s.url}`,
|
|
30
|
+
nativeId: s.id ?? s.name,
|
|
31
|
+
name: (s.name ?? "L402 Service").replace(/^\s+/g, "").split("\n")[0].trim().slice(0, 100),
|
|
32
|
+
description: (s.description ?? "").replace(/^\s+|\s+$/g, "").replace(/\s+/g, " ").slice(0, 300),
|
|
33
|
+
categories: s.category ? s.category.split("/").map((c) => c.trim()) : ["general"],
|
|
34
|
+
capabilities: [s.description ?? s.name ?? ""],
|
|
35
|
+
source: "l402-directory",
|
|
36
|
+
protocol: "l402",
|
|
37
|
+
endpoints: { l402: s.url, http: s.url },
|
|
38
|
+
pricing: {
|
|
39
|
+
model: "per-call",
|
|
40
|
+
amount: s.price_sats ? `${s.price_sats} sats` : s.price_usd ? String(s.price_usd) : undefined,
|
|
41
|
+
currency: "sats",
|
|
42
|
+
},
|
|
43
|
+
reputation: s.reliability_score ? {
|
|
44
|
+
score: s.reliability_score,
|
|
45
|
+
count: s.uptime_30d ? Math.round(s.uptime_30d * 100) : 0,
|
|
46
|
+
source: "402index",
|
|
47
|
+
} : undefined,
|
|
48
|
+
verified: s.health_status === "healthy",
|
|
49
|
+
lastSeen: s.last_checked ? new Date(s.last_checked).getTime() : undefined,
|
|
50
|
+
raw: s,
|
|
51
|
+
}));
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return [];
|
|
55
|
+
}
|
|
37
56
|
},
|
|
38
57
|
async ping() {
|
|
39
|
-
|
|
58
|
+
try {
|
|
59
|
+
const res = await fetch(`${INDEX_API}?protocol=L402&limit=1`, { signal: AbortSignal.timeout(5000) });
|
|
60
|
+
return res.ok;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
40
65
|
},
|
|
41
66
|
};
|
|
42
67
|
//# sourceMappingURL=l402-directory.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"l402-directory.js","sourceRoot":"","sources":["../../src/sources/l402-directory.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"l402-directory.js","sourceRoot":"","sources":["../../src/sources/l402-directory.ts"],"names":[],"mappings":"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"}
|
package/dist/sources/skills.d.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Skills Source Adapter
|
|
3
|
-
* Searches
|
|
4
|
-
*
|
|
3
|
+
* Searches REAL APIs:
|
|
4
|
+
* - skills.sh (Vercel) — /api/search?q=
|
|
5
|
+
* - ClawHub (OpenClaw) — /api/search?q= (vector search)
|
|
6
|
+
*
|
|
7
|
+
* No hardcoded seed lists. All real data.
|
|
5
8
|
*/
|
|
6
9
|
import type { SourceAdapter } from "./types.js";
|
|
7
10
|
export declare const skillsAdapter: SourceAdapter;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/sources/skills.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/sources/skills.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAqC,MAAM,YAAY,CAAC;AAKnF,eAAO,MAAM,aAAa,EAAE,aA6B3B,CAAC"}
|
package/dist/sources/skills.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Skills Source Adapter
|
|
3
|
-
* Searches
|
|
4
|
-
*
|
|
3
|
+
* Searches REAL APIs:
|
|
4
|
+
* - skills.sh (Vercel) — /api/search?q=
|
|
5
|
+
* - ClawHub (OpenClaw) — /api/search?q= (vector search)
|
|
6
|
+
*
|
|
7
|
+
* No hardcoded seed lists. All real data.
|
|
5
8
|
*/
|
|
6
|
-
const SKILLS_SH_API = "https://skills.sh";
|
|
7
|
-
const CLAWHUB_API = "https://clawhub.ai";
|
|
9
|
+
const SKILLS_SH_API = "https://skills.sh/api/search";
|
|
10
|
+
const CLAWHUB_API = "https://clawhub.ai/api/search";
|
|
8
11
|
export const skillsAdapter = {
|
|
9
12
|
name: "skills-registry",
|
|
10
13
|
displayName: "Skills Registry (skills.sh + ClawHub)",
|
|
@@ -13,134 +16,106 @@ export const skillsAdapter = {
|
|
|
13
16
|
const timeout = options?.timeout ?? 10000;
|
|
14
17
|
const results = [];
|
|
15
18
|
// Search skills.sh
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
try {
|
|
25
|
-
const clawHubResults = await searchClawHub(query, Math.ceil(limit / 2), timeout);
|
|
26
|
-
results.push(...clawHubResults);
|
|
27
|
-
}
|
|
28
|
-
catch {
|
|
29
|
-
// ClawHub might be rate-limited
|
|
30
|
-
}
|
|
31
|
-
// If both APIs fail, return from seed list
|
|
32
|
-
if (results.length === 0) {
|
|
33
|
-
return searchSeedList(query, limit);
|
|
34
|
-
}
|
|
19
|
+
const [skillsShResults, clawHubResults] = await Promise.allSettled([
|
|
20
|
+
searchSkillsSh(query, Math.ceil(limit / 2), timeout),
|
|
21
|
+
searchClawHub(query, Math.ceil(limit / 2), timeout),
|
|
22
|
+
]);
|
|
23
|
+
if (skillsShResults.status === "fulfilled")
|
|
24
|
+
results.push(...skillsShResults.value);
|
|
25
|
+
if (clawHubResults.status === "fulfilled")
|
|
26
|
+
results.push(...clawHubResults.value);
|
|
35
27
|
return results.slice(0, limit);
|
|
36
28
|
},
|
|
37
29
|
async ping() {
|
|
38
30
|
try {
|
|
39
|
-
const res = await fetch(SKILLS_SH_API
|
|
31
|
+
const res = await fetch(`${SKILLS_SH_API}?q=test`, { signal: AbortSignal.timeout(3000) });
|
|
40
32
|
return res.ok;
|
|
41
33
|
}
|
|
42
34
|
catch {
|
|
43
|
-
return
|
|
35
|
+
return false;
|
|
44
36
|
}
|
|
45
37
|
},
|
|
46
38
|
};
|
|
47
39
|
async function searchSkillsSh(query, limit, timeout) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
signal: AbortSignal.timeout(timeout),
|
|
51
|
-
});
|
|
52
|
-
if (!res.ok) {
|
|
53
|
-
// Try the leaderboard endpoint
|
|
54
|
-
const lbRes = await fetch(`${SKILLS_SH_API}/api/leaderboard?limit=${limit}`, {
|
|
40
|
+
try {
|
|
41
|
+
const res = await fetch(`${SKILLS_SH_API}?q=${encodeURIComponent(query)}`, {
|
|
55
42
|
signal: AbortSignal.timeout(timeout),
|
|
56
43
|
});
|
|
57
|
-
if (!
|
|
44
|
+
if (!res.ok)
|
|
58
45
|
return [];
|
|
59
|
-
const data = await
|
|
60
|
-
const skills =
|
|
61
|
-
return skills
|
|
62
|
-
.
|
|
63
|
-
.
|
|
46
|
+
const data = await res.json();
|
|
47
|
+
const skills = data.skills ?? [];
|
|
48
|
+
return skills.slice(0, limit).map((s) => ({
|
|
49
|
+
id: `skills-registry:skills-sh:${s.id ?? s.skillId}`,
|
|
50
|
+
nativeId: s.id ?? s.skillId,
|
|
51
|
+
name: s.name ?? s.skillId ?? "Unknown Skill",
|
|
52
|
+
description: s.description ?? "",
|
|
53
|
+
categories: extractSkillCategories(s.name ?? "", s.description ?? ""),
|
|
54
|
+
capabilities: [s.name, s.description].filter(Boolean),
|
|
55
|
+
source: "skills-registry",
|
|
56
|
+
protocol: "skill",
|
|
57
|
+
endpoints: {
|
|
58
|
+
http: `https://skills.sh/${s.source ?? s.id}`,
|
|
59
|
+
},
|
|
60
|
+
pricing: { model: "free" },
|
|
61
|
+
verified: (s.installs ?? 0) > 100,
|
|
62
|
+
reputation: s.installs ? {
|
|
63
|
+
score: Math.min(s.installs / 100, 100),
|
|
64
|
+
count: s.installs,
|
|
65
|
+
source: "skills-sh-installs",
|
|
66
|
+
} : undefined,
|
|
67
|
+
raw: { ...s, registry: "skills-sh" },
|
|
68
|
+
}));
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return [];
|
|
64
72
|
}
|
|
65
|
-
const data = await res.json();
|
|
66
|
-
const skills = Array.isArray(data) ? data : data.skills ?? data.results ?? [];
|
|
67
|
-
return skills.map((s) => mapSkill(s, "skills-sh"));
|
|
68
73
|
}
|
|
69
74
|
async function searchClawHub(query, limit, timeout) {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
75
|
+
try {
|
|
76
|
+
const res = await fetch(`${CLAWHUB_API}?q=${encodeURIComponent(query)}`, {
|
|
77
|
+
signal: AbortSignal.timeout(timeout),
|
|
78
|
+
});
|
|
79
|
+
if (!res.ok)
|
|
80
|
+
return [];
|
|
81
|
+
const data = await res.json();
|
|
82
|
+
const skills = data.results ?? [];
|
|
83
|
+
return skills.slice(0, limit).map((s) => ({
|
|
84
|
+
id: `skills-registry:clawhub:${s.slug}`,
|
|
85
|
+
nativeId: s.slug,
|
|
86
|
+
name: s.displayName ?? s.slug ?? "Unknown Skill",
|
|
87
|
+
description: s.summary ?? "",
|
|
88
|
+
categories: extractSkillCategories(s.displayName ?? "", s.summary ?? ""),
|
|
89
|
+
capabilities: [s.summary ?? s.displayName ?? ""],
|
|
90
|
+
source: "skills-registry",
|
|
91
|
+
protocol: "skill",
|
|
92
|
+
endpoints: {
|
|
93
|
+
http: `https://clawhub.ai/${s.slug}`,
|
|
94
|
+
},
|
|
95
|
+
pricing: { model: "free" },
|
|
96
|
+
verified: true,
|
|
97
|
+
reputation: s.score ? {
|
|
98
|
+
score: Math.round(s.score * 25),
|
|
99
|
+
count: 0,
|
|
100
|
+
source: "clawhub-relevance",
|
|
101
|
+
} : undefined,
|
|
102
|
+
raw: { ...s, registry: "clawhub" },
|
|
103
|
+
}));
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
74
106
|
return [];
|
|
75
|
-
|
|
76
|
-
const skills = Array.isArray(data) ? data : data.skills ?? data.results ?? [];
|
|
77
|
-
return skills.map((s) => mapSkill(s, "clawhub"));
|
|
78
|
-
}
|
|
79
|
-
function mapSkill(skill, registry) {
|
|
80
|
-
const name = skill.name ?? skill.slug ?? skill.title ?? "Unknown Skill";
|
|
81
|
-
const description = skill.description ?? "";
|
|
82
|
-
const repo = skill.repo ?? skill.repository ?? skill.url ?? "";
|
|
83
|
-
const installs = skill.installs ?? skill.downloads ?? 0;
|
|
84
|
-
return {
|
|
85
|
-
id: `skills-registry:${registry}:${name.toLowerCase().replace(/\s+/g, "-")}`,
|
|
86
|
-
nativeId: skill.id ?? name,
|
|
87
|
-
name,
|
|
88
|
-
description,
|
|
89
|
-
categories: extractSkillCategories(name, description),
|
|
90
|
-
capabilities: [description, ...(skill.tags ?? [])],
|
|
91
|
-
source: "skills-registry",
|
|
92
|
-
protocol: "skill",
|
|
93
|
-
endpoints: {
|
|
94
|
-
http: repo || `https://skills.sh/${name}`,
|
|
95
|
-
},
|
|
96
|
-
pricing: { model: "free" },
|
|
97
|
-
verified: installs > 100,
|
|
98
|
-
lastSeen: Date.now(),
|
|
99
|
-
raw: { ...skill, registry },
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
// Seed list of well-known skills for when APIs are unavailable
|
|
103
|
-
const KNOWN_SKILLS = [
|
|
104
|
-
{ name: "remotion-best-practices", description: "Video creation in React with Remotion", categories: ["media", "development"], registry: "skills-sh", installs: 145000 },
|
|
105
|
-
{ name: "web-design-guidelines", description: "UI/UX design best practices for web development", categories: ["design", "development"], registry: "skills-sh", installs: 89000 },
|
|
106
|
-
{ name: "react-best-practices", description: "React and Next.js performance optimization from Vercel", categories: ["development"], registry: "skills-sh", installs: 120000 },
|
|
107
|
-
{ name: "solana-dev", description: "End-to-end Solana development playbook", categories: ["development", "defi"], registry: "skills-sh", installs: 50000 },
|
|
108
|
-
{ name: "cairo-contracts", description: "Write Cairo smart contracts on Starknet", categories: ["development", "defi"], registry: "skills-sh", installs: 30000 },
|
|
109
|
-
{ name: "x402-skill", description: "x402 HTTP payment protocol for monetizing APIs", categories: ["payments", "development"], registry: "skills-sh", installs: 25000 },
|
|
110
|
-
{ name: "agent-browser", description: "Automate browser interactions, screenshots, form filling", categories: ["tools", "automation"], registry: "skills-sh", installs: 70000 },
|
|
111
|
-
{ name: "implement-design", description: "Translate Figma designs into production-ready code", categories: ["design", "development"], registry: "skills-sh", installs: 60000 },
|
|
112
|
-
{ name: "find-skills", description: "Discover and install new agent skills", categories: ["tools", "discovery"], registry: "skills-sh", installs: 200000 },
|
|
113
|
-
{ name: "tailwind-v4-shadcn", description: "Set up Tailwind v4 with shadcn/ui", categories: ["development", "design"], registry: "skills-sh", installs: 45000 },
|
|
114
|
-
{ name: "ethskills", description: "Learn Ethereum, Solidity, smart contracts, web3 development", categories: ["development", "defi"], registry: "skills-sh", installs: 8000 },
|
|
115
|
-
{ name: "soul-markets", description: "Agent skill marketplace — monetize agent capabilities", categories: ["marketplace", "commerce"], registry: "clawhub", installs: 5000 },
|
|
116
|
-
{ name: "a2a-market", description: "Buy and sell agent skills using USDC on Base via A2A", categories: ["marketplace", "commerce"], registry: "clawhub", installs: 3000 },
|
|
117
|
-
{ name: "skillzmarket", description: "Discover and install skills from community marketplace", categories: ["marketplace", "discovery"], registry: "clawhub", installs: 4000 },
|
|
118
|
-
{ name: "x402-agent-marketplace", description: "x402 agent marketplace for paid AI capabilities", categories: ["marketplace", "payments"], registry: "clawhub", installs: 2000 },
|
|
119
|
-
];
|
|
120
|
-
function searchSeedList(query, limit) {
|
|
121
|
-
const lower = query.toLowerCase();
|
|
122
|
-
return KNOWN_SKILLS
|
|
123
|
-
.filter((s) => matchesQuery(s, query))
|
|
124
|
-
.slice(0, limit)
|
|
125
|
-
.map((s) => mapSkill({ ...s, installs: s.installs }, s.registry));
|
|
126
|
-
}
|
|
127
|
-
function matchesQuery(skill, query) {
|
|
128
|
-
if (!query)
|
|
129
|
-
return true;
|
|
130
|
-
const lower = query.toLowerCase();
|
|
131
|
-
const text = `${skill.name ?? ""} ${skill.description ?? ""} ${(skill.tags ?? []).join(" ")} ${(skill.categories ?? []).join(" ")}`.toLowerCase();
|
|
132
|
-
return lower.split(/\s+/).some((term) => text.includes(term));
|
|
107
|
+
}
|
|
133
108
|
}
|
|
134
109
|
function extractSkillCategories(name, description) {
|
|
135
110
|
const text = `${name} ${description}`.toLowerCase();
|
|
136
111
|
const cats = [];
|
|
137
112
|
if (text.match(/react|next|vue|svelte|frontend|css|tailwind|design/))
|
|
138
113
|
cats.push("development");
|
|
139
|
-
if (text.match(/defi|yield|swap|solidity|ethereum|solana|contract/))
|
|
114
|
+
if (text.match(/defi|yield|swap|solidity|ethereum|solana|contract|crypto/))
|
|
140
115
|
cats.push("defi");
|
|
141
116
|
if (text.match(/image|video|audio|media|remotion|figma/))
|
|
142
117
|
cats.push("media");
|
|
143
|
-
if (text.match(/data|analytics|research|search/))
|
|
118
|
+
if (text.match(/data|analytics|research|search|scrape/))
|
|
144
119
|
cats.push("data");
|
|
145
120
|
if (text.match(/browser|automat|tool|file/))
|
|
146
121
|
cats.push("tools");
|
|
@@ -148,6 +123,8 @@ function extractSkillCategories(name, description) {
|
|
|
148
123
|
cats.push("commerce");
|
|
149
124
|
if (text.match(/security|audit|test/))
|
|
150
125
|
cats.push("security");
|
|
126
|
+
if (text.match(/ai|llm|model|agent/))
|
|
127
|
+
cats.push("ai");
|
|
151
128
|
return cats.length > 0 ? cats : ["general"];
|
|
152
129
|
}
|
|
153
130
|
//# sourceMappingURL=skills.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/sources/skills.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/sources/skills.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,MAAM,aAAa,GAAG,8BAA8B,CAAC;AACrD,MAAM,WAAW,GAAG,+BAA+B,CAAC;AAEpD,MAAM,CAAC,MAAM,aAAa,GAAkB;IAC1C,IAAI,EAAE,iBAAiB;IACvB,WAAW,EAAE,uCAAuC;IAEpD,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,OAA6B;QACvD,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC;QACnC,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,IAAI,KAAK,CAAC;QAC1C,MAAM,OAAO,GAAmB,EAAE,CAAC;QAEnC,mBAAmB;QACnB,MAAM,CAAC,eAAe,EAAE,cAAc,CAAC,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC;YACjE,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC;YACpD,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC;SACpD,CAAC,CAAC;QAEH,IAAI,eAAe,CAAC,MAAM,KAAK,WAAW;YAAE,OAAO,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;QACnF,IAAI,cAAc,CAAC,MAAM,KAAK,WAAW;YAAE,OAAO,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;QAEjF,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACjC,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,aAAa,SAAS,EAAE,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC1F,OAAO,GAAG,CAAC,EAAE,CAAC;QAChB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;CACF,CAAC;AAEF,KAAK,UAAU,cAAc,CAAC,KAAa,EAAE,KAAa,EAAE,OAAe;IACzE,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,aAAa,MAAM,kBAAkB,CAAC,KAAK,CAAC,EAAE,EAAE;YACzE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC;SACrC,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO,EAAE,CAAC;QAEvB,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC;QAEjC,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC;YAC7C,EAAE,EAAE,6BAA6B,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,OAAO,EAAE;YACpD,QAAQ,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,OAAO;YAC3B,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,OAAO,IAAI,eAAe;YAC5C,WAAW,EAAE,CAAC,CAAC,WAAW,IAAI,EAAE;YAChC,UAAU,EAAE,sBAAsB,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC,WAAW,IAAI,EAAE,CAAC;YACrE,YAAY,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC;YACrD,MAAM,EAAE,iBAA0B;YAClC,QAAQ,EAAE,OAAgB;YAC1B,SAAS,EAAE;gBACT,IAAI,EAAE,qBAAqB,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,EAAE,EAAE;aAC9C;YACD,OAAO,EAAE,EAAE,KAAK,EAAE,MAAe,EAAE;YACnC,QAAQ,EAAE,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,GAAG,GAAG;YACjC,UAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;gBACvB,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,GAAG,GAAG,EAAE,GAAG,CAAC;gBACtC,KAAK,EAAE,CAAC,CAAC,QAAQ;gBACjB,MAAM,EAAE,oBAAoB;aAC7B,CAAC,CAAC,CAAC,SAAS;YACb,GAAG,EAAE,EAAE,GAAG,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE;SACrC,CAAC,CAAC,CAAC;IACN,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,aAAa,CAAC,KAAa,EAAE,KAAa,EAAE,OAAe;IACxE,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,WAAW,MAAM,kBAAkB,CAAC,KAAK,CAAC,EAAE,EAAE;YACvE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC;SACrC,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO,EAAE,CAAC;QAEvB,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;QAElC,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC;YAC7C,EAAE,EAAE,2BAA2B,CAAC,CAAC,IAAI,EAAE;YACvC,QAAQ,EAAE,CAAC,CAAC,IAAI;YAChB,IAAI,EAAE,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,IAAI,IAAI,eAAe;YAChD,WAAW,EAAE,CAAC,CAAC,OAAO,IAAI,EAAE;YAC5B,UAAU,EAAE,sBAAsB,CAAC,CAAC,CAAC,WAAW,IAAI,EAAE,EAAE,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC;YACxE,YAAY,EAAE,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,WAAW,IAAI,EAAE,CAAC;YAChD,MAAM,EAAE,iBAA0B;YAClC,QAAQ,EAAE,OAAgB;YAC1B,SAAS,EAAE;gBACT,IAAI,EAAE,sBAAsB,CAAC,CAAC,IAAI,EAAE;aACrC;YACD,OAAO,EAAE,EAAE,KAAK,EAAE,MAAe,EAAE;YACnC,QAAQ,EAAE,IAAI;YACd,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;gBACpB,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;gBAC/B,KAAK,EAAE,CAAC;gBACR,MAAM,EAAE,mBAAmB;aAC5B,CAAC,CAAC,CAAC,SAAS;YACb,GAAG,EAAE,EAAE,GAAG,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE;SACnC,CAAC,CAAC,CAAC;IACN,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,SAAS,sBAAsB,CAAC,IAAY,EAAE,WAAmB;IAC/D,MAAM,IAAI,GAAG,GAAG,IAAI,IAAI,WAAW,EAAE,CAAC,WAAW,EAAE,CAAC;IACpD,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,IAAI,IAAI,CAAC,KAAK,CAAC,oDAAoD,CAAC;QAAE,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC/F,IAAI,IAAI,CAAC,KAAK,CAAC,0DAA0D,CAAC;QAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC9F,IAAI,IAAI,CAAC,KAAK,CAAC,wCAAwC,CAAC;QAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC7E,IAAI,IAAI,CAAC,KAAK,CAAC,uCAAuC,CAAC;QAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3E,IAAI,IAAI,CAAC,KAAK,CAAC,2BAA2B,CAAC;QAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAChE,IAAI,IAAI,CAAC,KAAK,CAAC,kCAAkC,CAAC;QAAE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC1E,IAAI,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC;QAAE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC7D,IAAI,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC;QAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtD,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;AAC9C,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kompass-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Get any job done. Universal agent capability discovery + coordination across ACP, MCP, x402, A2A, skills, L402, and ERC-8004.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -1,51 +1,71 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* L402 Directory Source Adapter
|
|
3
|
-
*
|
|
2
|
+
* L402 Lightning Directory Source Adapter
|
|
3
|
+
* Searches 402index.io filtered to L402 (Lightning) protocol
|
|
4
|
+
* Real data — not hardcoded seed list
|
|
4
5
|
*/
|
|
5
6
|
|
|
6
7
|
import type { SourceAdapter, UnifiedAgent, SourceSearchOptions } from "./types.js";
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
const KNOWN_L402_SERVICES = [
|
|
10
|
-
{ name: "Satring", url: "https://satring.com", description: "Curated L402 + x402 API directory. 36 endpoints across 4 providers", categories: ["directory", "tools"] },
|
|
11
|
-
{ name: "Lightning Faucet L402", url: "https://lightningfaucet.com", description: "L402 API registry and testing tools", categories: ["tools", "testing"] },
|
|
12
|
-
{ name: "Nostr NIP-68 Bridge", url: "https://l402.nostr.com", description: "L402 payments over Nostr relay network", categories: ["social", "payments"] },
|
|
13
|
-
{ name: "Stacker News", url: "https://stacker.news", description: "Lightning-powered news with L402 API access", categories: ["content", "data"] },
|
|
14
|
-
{ name: "Nodana", url: "https://nodana.io", description: "L402 agentic access for Bitcoin app deployment", categories: ["development", "compute"] },
|
|
15
|
-
];
|
|
9
|
+
const INDEX_API = "https://402index.io/api/v1/services";
|
|
16
10
|
|
|
17
11
|
export const l402DirectoryAdapter: SourceAdapter = {
|
|
18
12
|
name: "l402-directory",
|
|
19
|
-
displayName: "L402 Lightning Directory",
|
|
13
|
+
displayName: "L402 Lightning Directory (402index)",
|
|
20
14
|
|
|
21
15
|
async search(query: string, options?: SourceSearchOptions): Promise<UnifiedAgent[]> {
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
16
|
+
const limit = options?.limit ?? 20;
|
|
17
|
+
const timeout = options?.timeout ?? 10000;
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
const url = new URL(INDEX_API);
|
|
21
|
+
if (query) url.searchParams.set("q", query);
|
|
22
|
+
url.searchParams.set("protocol", "L402");
|
|
23
|
+
url.searchParams.set("limit", String(limit));
|
|
24
|
+
url.searchParams.set("health", "healthy");
|
|
25
|
+
url.searchParams.set("sort", "reliability");
|
|
26
|
+
|
|
27
|
+
const res = await fetch(url.toString(), { signal: AbortSignal.timeout(timeout) });
|
|
28
|
+
if (!res.ok) return [];
|
|
29
|
+
|
|
30
|
+
const data = await res.json();
|
|
31
|
+
const services = data.services ?? data.data ?? [];
|
|
32
|
+
if (!Array.isArray(services)) return [];
|
|
33
|
+
|
|
34
|
+
return services.slice(0, limit).map((s: any) => ({
|
|
35
|
+
id: `l402-directory:${s.id ?? s.url}`,
|
|
36
|
+
nativeId: s.id ?? s.name,
|
|
37
|
+
name: (s.name ?? "L402 Service").replace(/^\s+/g, "").split("\n")[0].trim().slice(0, 100),
|
|
38
|
+
description: (s.description ?? "").replace(/^\s+|\s+$/g, "").replace(/\s+/g, " ").slice(0, 300),
|
|
39
|
+
categories: s.category ? s.category.split("/").map((c: string) => c.trim()) : ["general"],
|
|
40
|
+
capabilities: [s.description ?? s.name ?? ""],
|
|
41
|
+
source: "l402-directory" as const,
|
|
42
|
+
protocol: "l402" as const,
|
|
43
|
+
endpoints: { l402: s.url, http: s.url },
|
|
44
|
+
pricing: {
|
|
45
|
+
model: "per-call" as const,
|
|
46
|
+
amount: s.price_sats ? `${s.price_sats} sats` : s.price_usd ? String(s.price_usd) : undefined,
|
|
47
|
+
currency: "sats",
|
|
48
|
+
},
|
|
49
|
+
reputation: s.reliability_score ? {
|
|
50
|
+
score: s.reliability_score,
|
|
51
|
+
count: s.uptime_30d ? Math.round(s.uptime_30d * 100) : 0,
|
|
52
|
+
source: "402index",
|
|
53
|
+
} : undefined,
|
|
54
|
+
verified: s.health_status === "healthy",
|
|
55
|
+
lastSeen: s.last_checked ? new Date(s.last_checked).getTime() : undefined,
|
|
56
|
+
raw: s,
|
|
57
|
+
}));
|
|
58
|
+
} catch {
|
|
59
|
+
return [];
|
|
60
|
+
}
|
|
46
61
|
},
|
|
47
62
|
|
|
48
63
|
async ping(): Promise<boolean> {
|
|
49
|
-
|
|
64
|
+
try {
|
|
65
|
+
const res = await fetch(`${INDEX_API}?protocol=L402&limit=1`, { signal: AbortSignal.timeout(5000) });
|
|
66
|
+
return res.ok;
|
|
67
|
+
} catch {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
50
70
|
},
|
|
51
71
|
};
|
package/src/sources/skills.ts
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Skills Source Adapter
|
|
3
|
-
* Searches
|
|
4
|
-
*
|
|
3
|
+
* Searches REAL APIs:
|
|
4
|
+
* - skills.sh (Vercel) — /api/search?q=
|
|
5
|
+
* - ClawHub (OpenClaw) — /api/search?q= (vector search)
|
|
6
|
+
*
|
|
7
|
+
* No hardcoded seed lists. All real data.
|
|
5
8
|
*/
|
|
6
9
|
|
|
7
10
|
import type { SourceAdapter, UnifiedAgent, SourceSearchOptions } from "./types.js";
|
|
8
11
|
|
|
9
|
-
const SKILLS_SH_API = "https://skills.sh";
|
|
10
|
-
const CLAWHUB_API = "https://clawhub.ai";
|
|
12
|
+
const SKILLS_SH_API = "https://skills.sh/api/search";
|
|
13
|
+
const CLAWHUB_API = "https://clawhub.ai/api/search";
|
|
11
14
|
|
|
12
15
|
export const skillsAdapter: SourceAdapter = {
|
|
13
16
|
name: "skills-registry",
|
|
@@ -19,143 +22,111 @@ export const skillsAdapter: SourceAdapter = {
|
|
|
19
22
|
const results: UnifiedAgent[] = [];
|
|
20
23
|
|
|
21
24
|
// Search skills.sh
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
// skills.sh might not have a public search API — fall back to known skills
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// Search ClawHub
|
|
30
|
-
try {
|
|
31
|
-
const clawHubResults = await searchClawHub(query, Math.ceil(limit / 2), timeout);
|
|
32
|
-
results.push(...clawHubResults);
|
|
33
|
-
} catch {
|
|
34
|
-
// ClawHub might be rate-limited
|
|
35
|
-
}
|
|
25
|
+
const [skillsShResults, clawHubResults] = await Promise.allSettled([
|
|
26
|
+
searchSkillsSh(query, Math.ceil(limit / 2), timeout),
|
|
27
|
+
searchClawHub(query, Math.ceil(limit / 2), timeout),
|
|
28
|
+
]);
|
|
36
29
|
|
|
37
|
-
|
|
38
|
-
if (
|
|
39
|
-
return searchSeedList(query, limit);
|
|
40
|
-
}
|
|
30
|
+
if (skillsShResults.status === "fulfilled") results.push(...skillsShResults.value);
|
|
31
|
+
if (clawHubResults.status === "fulfilled") results.push(...clawHubResults.value);
|
|
41
32
|
|
|
42
33
|
return results.slice(0, limit);
|
|
43
34
|
},
|
|
44
35
|
|
|
45
36
|
async ping(): Promise<boolean> {
|
|
46
37
|
try {
|
|
47
|
-
const res = await fetch(SKILLS_SH_API
|
|
38
|
+
const res = await fetch(`${SKILLS_SH_API}?q=test`, { signal: AbortSignal.timeout(3000) });
|
|
48
39
|
return res.ok;
|
|
49
40
|
} catch {
|
|
50
|
-
return
|
|
41
|
+
return false;
|
|
51
42
|
}
|
|
52
43
|
},
|
|
53
44
|
};
|
|
54
45
|
|
|
55
46
|
async function searchSkillsSh(query: string, limit: number, timeout: number): Promise<UnifiedAgent[]> {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
signal: AbortSignal.timeout(timeout),
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
if (!res.ok) {
|
|
62
|
-
// Try the leaderboard endpoint
|
|
63
|
-
const lbRes = await fetch(`${SKILLS_SH_API}/api/leaderboard?limit=${limit}`, {
|
|
47
|
+
try {
|
|
48
|
+
const res = await fetch(`${SKILLS_SH_API}?q=${encodeURIComponent(query)}`, {
|
|
64
49
|
signal: AbortSignal.timeout(timeout),
|
|
65
50
|
});
|
|
66
|
-
if (!lbRes.ok) return [];
|
|
67
|
-
const data = await lbRes.json();
|
|
68
|
-
const skills = Array.isArray(data) ? data : data.skills ?? data.data ?? [];
|
|
69
|
-
return skills
|
|
70
|
-
.filter((s: any) => matchesQuery(s, query))
|
|
71
|
-
.map((s: any) => mapSkill(s, "skills-sh"));
|
|
72
|
-
}
|
|
73
51
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
52
|
+
if (!res.ok) return [];
|
|
53
|
+
|
|
54
|
+
const data = await res.json();
|
|
55
|
+
const skills = data.skills ?? [];
|
|
56
|
+
|
|
57
|
+
return skills.slice(0, limit).map((s: any) => ({
|
|
58
|
+
id: `skills-registry:skills-sh:${s.id ?? s.skillId}`,
|
|
59
|
+
nativeId: s.id ?? s.skillId,
|
|
60
|
+
name: s.name ?? s.skillId ?? "Unknown Skill",
|
|
61
|
+
description: s.description ?? "",
|
|
62
|
+
categories: extractSkillCategories(s.name ?? "", s.description ?? ""),
|
|
63
|
+
capabilities: [s.name, s.description].filter(Boolean),
|
|
64
|
+
source: "skills-registry" as const,
|
|
65
|
+
protocol: "skill" as const,
|
|
66
|
+
endpoints: {
|
|
67
|
+
http: `https://skills.sh/${s.source ?? s.id}`,
|
|
68
|
+
},
|
|
69
|
+
pricing: { model: "free" as const },
|
|
70
|
+
verified: (s.installs ?? 0) > 100,
|
|
71
|
+
reputation: s.installs ? {
|
|
72
|
+
score: Math.min(s.installs / 100, 100),
|
|
73
|
+
count: s.installs,
|
|
74
|
+
source: "skills-sh-installs",
|
|
75
|
+
} : undefined,
|
|
76
|
+
raw: { ...s, registry: "skills-sh" },
|
|
77
|
+
}));
|
|
78
|
+
} catch {
|
|
79
|
+
return [];
|
|
80
|
+
}
|
|
77
81
|
}
|
|
78
82
|
|
|
79
83
|
async function searchClawHub(query: string, limit: number, timeout: number): Promise<UnifiedAgent[]> {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
if (!res.ok) return [];
|
|
85
|
-
|
|
86
|
-
const data = await res.json();
|
|
87
|
-
const skills = Array.isArray(data) ? data : data.skills ?? data.results ?? [];
|
|
88
|
-
return skills.map((s: any) => mapSkill(s, "clawhub"));
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function mapSkill(skill: any, registry: string): UnifiedAgent {
|
|
92
|
-
const name = skill.name ?? skill.slug ?? skill.title ?? "Unknown Skill";
|
|
93
|
-
const description = skill.description ?? "";
|
|
94
|
-
const repo = skill.repo ?? skill.repository ?? skill.url ?? "";
|
|
95
|
-
const installs = skill.installs ?? skill.downloads ?? 0;
|
|
96
|
-
|
|
97
|
-
return {
|
|
98
|
-
id: `skills-registry:${registry}:${name.toLowerCase().replace(/\s+/g, "-")}`,
|
|
99
|
-
nativeId: skill.id ?? name,
|
|
100
|
-
name,
|
|
101
|
-
description,
|
|
102
|
-
categories: extractSkillCategories(name, description),
|
|
103
|
-
capabilities: [description, ...(skill.tags ?? [])],
|
|
104
|
-
source: "skills-registry" as any,
|
|
105
|
-
protocol: "skill" as any,
|
|
106
|
-
endpoints: {
|
|
107
|
-
http: repo || `https://skills.sh/${name}`,
|
|
108
|
-
},
|
|
109
|
-
pricing: { model: "free" as const },
|
|
110
|
-
verified: installs > 100,
|
|
111
|
-
lastSeen: Date.now(),
|
|
112
|
-
raw: { ...skill, registry },
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// Seed list of well-known skills for when APIs are unavailable
|
|
117
|
-
const KNOWN_SKILLS = [
|
|
118
|
-
{ name: "remotion-best-practices", description: "Video creation in React with Remotion", categories: ["media", "development"], registry: "skills-sh", installs: 145000 },
|
|
119
|
-
{ name: "web-design-guidelines", description: "UI/UX design best practices for web development", categories: ["design", "development"], registry: "skills-sh", installs: 89000 },
|
|
120
|
-
{ name: "react-best-practices", description: "React and Next.js performance optimization from Vercel", categories: ["development"], registry: "skills-sh", installs: 120000 },
|
|
121
|
-
{ name: "solana-dev", description: "End-to-end Solana development playbook", categories: ["development", "defi"], registry: "skills-sh", installs: 50000 },
|
|
122
|
-
{ name: "cairo-contracts", description: "Write Cairo smart contracts on Starknet", categories: ["development", "defi"], registry: "skills-sh", installs: 30000 },
|
|
123
|
-
{ name: "x402-skill", description: "x402 HTTP payment protocol for monetizing APIs", categories: ["payments", "development"], registry: "skills-sh", installs: 25000 },
|
|
124
|
-
{ name: "agent-browser", description: "Automate browser interactions, screenshots, form filling", categories: ["tools", "automation"], registry: "skills-sh", installs: 70000 },
|
|
125
|
-
{ name: "implement-design", description: "Translate Figma designs into production-ready code", categories: ["design", "development"], registry: "skills-sh", installs: 60000 },
|
|
126
|
-
{ name: "find-skills", description: "Discover and install new agent skills", categories: ["tools", "discovery"], registry: "skills-sh", installs: 200000 },
|
|
127
|
-
{ name: "tailwind-v4-shadcn", description: "Set up Tailwind v4 with shadcn/ui", categories: ["development", "design"], registry: "skills-sh", installs: 45000 },
|
|
128
|
-
{ name: "ethskills", description: "Learn Ethereum, Solidity, smart contracts, web3 development", categories: ["development", "defi"], registry: "skills-sh", installs: 8000 },
|
|
129
|
-
{ name: "soul-markets", description: "Agent skill marketplace — monetize agent capabilities", categories: ["marketplace", "commerce"], registry: "clawhub", installs: 5000 },
|
|
130
|
-
{ name: "a2a-market", description: "Buy and sell agent skills using USDC on Base via A2A", categories: ["marketplace", "commerce"], registry: "clawhub", installs: 3000 },
|
|
131
|
-
{ name: "skillzmarket", description: "Discover and install skills from community marketplace", categories: ["marketplace", "discovery"], registry: "clawhub", installs: 4000 },
|
|
132
|
-
{ name: "x402-agent-marketplace", description: "x402 agent marketplace for paid AI capabilities", categories: ["marketplace", "payments"], registry: "clawhub", installs: 2000 },
|
|
133
|
-
];
|
|
134
|
-
|
|
135
|
-
function searchSeedList(query: string, limit: number): UnifiedAgent[] {
|
|
136
|
-
const lower = query.toLowerCase();
|
|
137
|
-
return KNOWN_SKILLS
|
|
138
|
-
.filter((s) => matchesQuery(s, query))
|
|
139
|
-
.slice(0, limit)
|
|
140
|
-
.map((s) => mapSkill({ ...s, installs: s.installs }, s.registry));
|
|
141
|
-
}
|
|
84
|
+
try {
|
|
85
|
+
const res = await fetch(`${CLAWHUB_API}?q=${encodeURIComponent(query)}`, {
|
|
86
|
+
signal: AbortSignal.timeout(timeout),
|
|
87
|
+
});
|
|
142
88
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
89
|
+
if (!res.ok) return [];
|
|
90
|
+
|
|
91
|
+
const data = await res.json();
|
|
92
|
+
const skills = data.results ?? [];
|
|
93
|
+
|
|
94
|
+
return skills.slice(0, limit).map((s: any) => ({
|
|
95
|
+
id: `skills-registry:clawhub:${s.slug}`,
|
|
96
|
+
nativeId: s.slug,
|
|
97
|
+
name: s.displayName ?? s.slug ?? "Unknown Skill",
|
|
98
|
+
description: s.summary ?? "",
|
|
99
|
+
categories: extractSkillCategories(s.displayName ?? "", s.summary ?? ""),
|
|
100
|
+
capabilities: [s.summary ?? s.displayName ?? ""],
|
|
101
|
+
source: "skills-registry" as const,
|
|
102
|
+
protocol: "skill" as const,
|
|
103
|
+
endpoints: {
|
|
104
|
+
http: `https://clawhub.ai/${s.slug}`,
|
|
105
|
+
},
|
|
106
|
+
pricing: { model: "free" as const },
|
|
107
|
+
verified: true,
|
|
108
|
+
reputation: s.score ? {
|
|
109
|
+
score: Math.round(s.score * 25),
|
|
110
|
+
count: 0,
|
|
111
|
+
source: "clawhub-relevance",
|
|
112
|
+
} : undefined,
|
|
113
|
+
raw: { ...s, registry: "clawhub" },
|
|
114
|
+
}));
|
|
115
|
+
} catch {
|
|
116
|
+
return [];
|
|
117
|
+
}
|
|
148
118
|
}
|
|
149
119
|
|
|
150
120
|
function extractSkillCategories(name: string, description: string): string[] {
|
|
151
121
|
const text = `${name} ${description}`.toLowerCase();
|
|
152
122
|
const cats: string[] = [];
|
|
153
123
|
if (text.match(/react|next|vue|svelte|frontend|css|tailwind|design/)) cats.push("development");
|
|
154
|
-
if (text.match(/defi|yield|swap|solidity|ethereum|solana|contract/)) cats.push("defi");
|
|
124
|
+
if (text.match(/defi|yield|swap|solidity|ethereum|solana|contract|crypto/)) cats.push("defi");
|
|
155
125
|
if (text.match(/image|video|audio|media|remotion|figma/)) cats.push("media");
|
|
156
|
-
if (text.match(/data|analytics|research|search/)) cats.push("data");
|
|
126
|
+
if (text.match(/data|analytics|research|search|scrape/)) cats.push("data");
|
|
157
127
|
if (text.match(/browser|automat|tool|file/)) cats.push("tools");
|
|
158
128
|
if (text.match(/market|commerce|pay|x402|monetiz/)) cats.push("commerce");
|
|
159
129
|
if (text.match(/security|audit|test/)) cats.push("security");
|
|
130
|
+
if (text.match(/ai|llm|model|agent/)) cats.push("ai");
|
|
160
131
|
return cats.length > 0 ? cats : ["general"];
|
|
161
132
|
}
|