kompass-sdk 0.5.0 → 0.7.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.
@@ -1,10 +1,13 @@
1
1
  /**
2
2
  * Skills Source Adapter
3
- * Searches skills.sh (Vercel) and ClawHub registries for agent skills
4
- * 13,700+ capabilities indexed across both registries
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
- try {
17
- const skillsShResults = await searchSkillsSh(query, Math.ceil(limit / 2), timeout);
18
- results.push(...skillsShResults);
19
- }
20
- catch {
21
- // skills.sh might not have a public search API — fall back to known skills
22
- }
23
- // Search ClawHub
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, { signal: AbortSignal.timeout(3000) });
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 true; // Seed list always available
35
+ return false;
44
36
  }
45
37
  },
46
38
  };
47
39
  async function searchSkillsSh(query, limit, timeout) {
48
- // skills.sh has a search page — try to query it
49
- const res = await fetch(`${SKILLS_SH_API}/api/search?q=${encodeURIComponent(query)}&limit=${limit}`, {
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 (!lbRes.ok)
44
+ if (!res.ok)
58
45
  return [];
59
- const data = await lbRes.json();
60
- const skills = Array.isArray(data) ? data : data.skills ?? data.data ?? [];
61
- return skills
62
- .filter((s) => matchesQuery(s, query))
63
- .map((s) => mapSkill(s, "skills-sh"));
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
- const res = await fetch(`${CLAWHUB_API}/api/skills/search?q=${encodeURIComponent(query)}&limit=${limit}`, {
71
- signal: AbortSignal.timeout(timeout),
72
- });
73
- if (!res.ok)
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
- const data = await res.json();
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;;;;GAIG;AAIH,MAAM,aAAa,GAAG,mBAAmB,CAAC;AAC1C,MAAM,WAAW,GAAG,oBAAoB,CAAC;AAEzC,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,IAAI,CAAC;YACH,MAAM,eAAe,GAAG,MAAM,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YACnF,OAAO,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,CAAC;QACnC,CAAC;QAAC,MAAM,CAAC;YACP,2EAA2E;QAC7E,CAAC;QAED,iBAAiB;QACjB,IAAI,CAAC;YACH,MAAM,cAAc,GAAG,MAAM,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YACjF,OAAO,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,CAAC;QAClC,CAAC;QAAC,MAAM,CAAC;YACP,gCAAgC;QAClC,CAAC;QAED,2CAA2C;QAC3C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QACtC,CAAC;QAED,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,aAAa,EAAE,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC9E,OAAO,GAAG,CAAC,EAAE,CAAC;QAChB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC,CAAC,6BAA6B;QAC5C,CAAC;IACH,CAAC;CACF,CAAC;AAEF,KAAK,UAAU,cAAc,CAAC,KAAa,EAAE,KAAa,EAAE,OAAe;IACzE,gDAAgD;IAChD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,aAAa,iBAAiB,kBAAkB,CAAC,KAAK,CAAC,UAAU,KAAK,EAAE,EAAE;QACnG,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC;KACrC,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,+BAA+B;QAC/B,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,GAAG,aAAa,0BAA0B,KAAK,EAAE,EAAE;YAC3E,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC;SACrC,CAAC,CAAC;QACH,IAAI,CAAC,KAAK,CAAC,EAAE;YAAE,OAAO,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;QAChC,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;QAC3E,OAAO,MAAM;aACV,MAAM,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;aAC1C,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC;IAC/C,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAC9B,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;IAC9E,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC;AAC1D,CAAC;AAED,KAAK,UAAU,aAAa,CAAC,KAAa,EAAE,KAAa,EAAE,OAAe;IACxE,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,WAAW,wBAAwB,kBAAkB,CAAC,KAAK,CAAC,UAAU,KAAK,EAAE,EAAE;QACxG,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC;KACrC,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,EAAE;QAAE,OAAO,EAAE,CAAC;IAEvB,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAC9B,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;IAC9E,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC;AACxD,CAAC;AAED,SAAS,QAAQ,CAAC,KAAU,EAAE,QAAgB;IAC5C,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,KAAK,IAAI,eAAe,CAAC;IACxE,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,IAAI,EAAE,CAAC;IAC5C,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,UAAU,IAAI,KAAK,CAAC,GAAG,IAAI,EAAE,CAAC;IAC/D,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,SAAS,IAAI,CAAC,CAAC;IAExD,OAAO;QACL,EAAE,EAAE,mBAAmB,QAAQ,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE;QAC5E,QAAQ,EAAE,KAAK,CAAC,EAAE,IAAI,IAAI;QAC1B,IAAI;QACJ,WAAW;QACX,UAAU,EAAE,sBAAsB,CAAC,IAAI,EAAE,WAAW,CAAC;QACrD,YAAY,EAAE,CAAC,WAAW,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;QAClD,MAAM,EAAE,iBAAwB;QAChC,QAAQ,EAAE,OAAc;QACxB,SAAS,EAAE;YACT,IAAI,EAAE,IAAI,IAAI,qBAAqB,IAAI,EAAE;SAC1C;QACD,OAAO,EAAE,EAAE,KAAK,EAAE,MAAe,EAAE;QACnC,QAAQ,EAAE,QAAQ,GAAG,GAAG;QACxB,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE;QACpB,GAAG,EAAE,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE;KAC5B,CAAC;AACJ,CAAC;AAED,+DAA+D;AAC/D,MAAM,YAAY,GAAG;IACnB,EAAE,IAAI,EAAE,yBAAyB,EAAE,WAAW,EAAE,uCAAuC,EAAE,UAAU,EAAE,CAAC,OAAO,EAAE,aAAa,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE;IACxK,EAAE,IAAI,EAAE,uBAAuB,EAAE,WAAW,EAAE,iDAAiD,EAAE,UAAU,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,KAAK,EAAE;IAChL,EAAE,IAAI,EAAE,sBAAsB,EAAE,WAAW,EAAE,wDAAwD,EAAE,UAAU,EAAE,CAAC,aAAa,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE;IAC7K,EAAE,IAAI,EAAE,YAAY,EAAE,WAAW,EAAE,wCAAwC,EAAE,UAAU,EAAE,CAAC,aAAa,EAAE,MAAM,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,KAAK,EAAE;IAC1J,EAAE,IAAI,EAAE,iBAAiB,EAAE,WAAW,EAAE,yCAAyC,EAAE,UAAU,EAAE,CAAC,aAAa,EAAE,MAAM,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,KAAK,EAAE;IAChK,EAAE,IAAI,EAAE,YAAY,EAAE,WAAW,EAAE,gDAAgD,EAAE,UAAU,EAAE,CAAC,UAAU,EAAE,aAAa,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,KAAK,EAAE;IACtK,EAAE,IAAI,EAAE,eAAe,EAAE,WAAW,EAAE,0DAA0D,EAAE,UAAU,EAAE,CAAC,OAAO,EAAE,YAAY,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,KAAK,EAAE;IAC/K,EAAE,IAAI,EAAE,kBAAkB,EAAE,WAAW,EAAE,oDAAoD,EAAE,UAAU,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,KAAK,EAAE;IAC9K,EAAE,IAAI,EAAE,aAAa,EAAE,WAAW,EAAE,uCAAuC,EAAE,UAAU,EAAE,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE;IAC1J,EAAE,IAAI,EAAE,oBAAoB,EAAE,WAAW,EAAE,mCAAmC,EAAE,UAAU,EAAE,CAAC,aAAa,EAAE,QAAQ,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,KAAK,EAAE;IAC/J,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,6DAA6D,EAAE,UAAU,EAAE,CAAC,aAAa,EAAE,MAAM,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE;IAC7K,EAAE,IAAI,EAAE,cAAc,EAAE,WAAW,EAAE,uDAAuD,EAAE,UAAU,EAAE,CAAC,aAAa,EAAE,UAAU,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE;IAC5K,EAAE,IAAI,EAAE,YAAY,EAAE,WAAW,EAAE,sDAAsD,EAAE,UAAU,EAAE,CAAC,aAAa,EAAE,UAAU,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE;IACzK,EAAE,IAAI,EAAE,cAAc,EAAE,WAAW,EAAE,wDAAwD,EAAE,UAAU,EAAE,CAAC,aAAa,EAAE,WAAW,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE;IAC9K,EAAE,IAAI,EAAE,wBAAwB,EAAE,WAAW,EAAE,iDAAiD,EAAE,UAAU,EAAE,CAAC,aAAa,EAAE,UAAU,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE;CACjL,CAAC;AAEF,SAAS,cAAc,CAAC,KAAa,EAAE,KAAa;IAClD,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IAClC,OAAO,YAAY;SAChB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;SACrC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC;SACf,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;AACtE,CAAC;AAED,SAAS,YAAY,CAAC,KAAU,EAAE,KAAa;IAC7C,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IAClC,MAAM,IAAI,GAAG,GAAG,KAAK,CAAC,IAAI,IAAI,EAAE,IAAI,KAAK,CAAC,WAAW,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC;IAClJ,OAAO,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;AAChE,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,mDAAmD,CAAC;QAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACvF,IAAI,IAAI,CAAC,KAAK,CAAC,wCAAwC,CAAC;QAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC7E,IAAI,IAAI,CAAC,KAAK,CAAC,gCAAgC,CAAC;QAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACpE,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,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;AAC9C,CAAC"}
1
+ {"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/sources/skills.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kompass-sdk",
3
- "version": "0.5.0",
3
+ "version": "0.7.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,107 +1,47 @@
1
1
  /**
2
- * ERC-8004 On-Chain Source Adapter
3
- * Indexes agent identities from the ERC-8004 Identity Registry on Base
2
+ * ERC-8004 Source Adapter
3
+ * Searches 8004scan.io API for registered AI agents
4
+ * Real data — agent identity, reputation, supported protocols
4
5
  */
5
6
 
6
- import { createPublicClient, http, type Address, parseAbiItem } from "viem";
7
- import { base, baseSepolia } from "viem/chains";
8
7
  import type { SourceAdapter, UnifiedAgent, SourceSearchOptions } from "./types.js";
9
8
 
10
- // ERC-8004 Identity Registry addresses
11
- const REGISTRY_ADDRESSES: Record<string, Address> = {
12
- "base": "0x8004A818BFB912233c491871b3d84c89A494BD9e" as Address,
13
- "base-sepolia": "0x8004A818BFB912233c491871b3d84c89A494BD9e" as Address,
14
- };
15
-
16
- const TRANSFER_EVENT = parseAbiItem(
17
- "event Transfer(address indexed from, address indexed to, uint256 indexed tokenId)"
18
- );
19
-
20
- const TOKEN_URI_ABI = [
21
- {
22
- type: "function",
23
- name: "tokenURI",
24
- inputs: [{ name: "tokenId", type: "uint256" }],
25
- outputs: [{ name: "", type: "string" }],
26
- stateMutability: "view",
27
- },
28
- ] as const;
29
-
30
- export function createErc8004Adapter(network: "base" | "base-sepolia" = "base-sepolia"): SourceAdapter {
31
- const chain = network === "base" ? base : baseSepolia;
32
- const registryAddress = REGISTRY_ADDRESSES[network];
33
-
34
- const client = createPublicClient({
35
- chain,
36
- transport: http(),
37
- });
9
+ const SCAN_API = "https://www.8004scan.io/api/v1";
38
10
 
11
+ export function createErc8004Adapter(network: "base" | "base-sepolia" = "base"): SourceAdapter {
39
12
  return {
40
13
  name: "erc8004",
41
- displayName: "ERC-8004 Identity Registry",
14
+ displayName: "ERC-8004 Identity Registry (8004scan)",
42
15
 
43
16
  async search(query: string, options?: SourceSearchOptions): Promise<UnifiedAgent[]> {
44
17
  const limit = options?.limit ?? 20;
18
+ const timeout = options?.timeout ?? 10000;
45
19
 
46
20
  try {
47
- // Get recent Transfer events (minting = from 0x0)
48
- const logs = await client.getLogs({
49
- address: registryAddress,
50
- event: TRANSFER_EVENT,
51
- args: { from: "0x0000000000000000000000000000000000000000" as Address },
52
- fromBlock: "earliest",
53
- toBlock: "latest",
54
- });
55
-
56
- const agents: UnifiedAgent[] = [];
57
-
58
- // Process most recent first
59
- const recentLogs = logs.slice(-limit * 2).reverse();
21
+ // Search across all chains on 8004scan
22
+ const url = new URL(`${SCAN_API}/agents`);
23
+ if (query) url.searchParams.set("search", query);
24
+ url.searchParams.set("limit", String(limit));
60
25
 
61
- for (const log of recentLogs) {
62
- if (agents.length >= limit) break;
63
-
64
- const tokenId = log.args.tokenId!;
65
- const owner = log.args.to!;
66
-
67
- try {
68
- // Fetch tokenURI for agent metadata
69
- const uri = await client.readContract({
70
- address: registryAddress,
71
- abi: TOKEN_URI_ABI,
72
- functionName: "tokenURI",
73
- args: [tokenId],
74
- });
75
-
76
- // Resolve URI to JSON
77
- let metadata: any = {};
78
- if (uri.startsWith("http") || uri.startsWith("ipfs")) {
79
- const fetchUrl = uri.startsWith("ipfs://")
80
- ? `https://ipfs.io/ipfs/${uri.slice(7)}`
81
- : uri;
82
- const res = await fetch(fetchUrl, { signal: AbortSignal.timeout(3000) });
83
- if (res.ok) metadata = await res.json();
84
- } else if (uri.startsWith("data:")) {
85
- const json = uri.split(",")[1];
86
- metadata = JSON.parse(atob(json));
87
- }
26
+ const res = await fetch(url.toString(), {
27
+ signal: AbortSignal.timeout(timeout),
28
+ });
88
29
 
89
- const agent = mapErc8004Agent(tokenId, owner, metadata, network);
30
+ if (!res.ok) return [];
90
31
 
91
- // Filter by query
92
- if (query) {
93
- const searchText = `${agent.name} ${agent.description} ${agent.categories.join(" ")}`.toLowerCase();
94
- if (!searchText.includes(query.toLowerCase())) continue;
95
- }
32
+ const data = await res.json();
33
+ const agents = data.items ?? data.agents ?? data.data ?? [];
96
34
 
97
- agents.push(agent);
98
- } catch {
99
- // Skip agents with unresolvable metadata
100
- continue;
101
- }
102
- }
35
+ if (!Array.isArray(agents)) return [];
103
36
 
104
- return agents;
37
+ return agents
38
+ .filter((a: any) => {
39
+ if (!query) return true;
40
+ const text = `${a.name ?? ""} ${a.description ?? ""}`.toLowerCase();
41
+ return query.toLowerCase().split(/\s+/).some((t) => text.includes(t));
42
+ })
43
+ .slice(0, limit)
44
+ .map(mapErc8004Agent);
105
45
  } catch {
106
46
  return [];
107
47
  }
@@ -109,8 +49,10 @@ export function createErc8004Adapter(network: "base" | "base-sepolia" = "base-se
109
49
 
110
50
  async ping(): Promise<boolean> {
111
51
  try {
112
- await client.getBlockNumber();
113
- return true;
52
+ const res = await fetch(`${SCAN_API}/agents?limit=1`, {
53
+ signal: AbortSignal.timeout(5000),
54
+ });
55
+ return res.ok;
114
56
  } catch {
115
57
  return false;
116
58
  }
@@ -118,49 +60,46 @@ export function createErc8004Adapter(network: "base" | "base-sepolia" = "base-se
118
60
  };
119
61
  }
120
62
 
121
- function mapErc8004Agent(
122
- tokenId: bigint,
123
- owner: Address,
124
- metadata: any,
125
- network: string
126
- ): UnifiedAgent {
127
- const services = metadata.services ?? [];
128
- const endpoints: UnifiedAgent["endpoints"] = {};
63
+ function mapErc8004Agent(agent: any): UnifiedAgent {
64
+ const protocols = agent.supported_protocols ?? [];
65
+ const protocol = protocols.includes("A2A") ? "a2a" as const
66
+ : protocols.includes("MCP") ? "mcp" as const
67
+ : protocols.includes("x402") || agent.x402_supported ? "x402" as const
68
+ : "onchain" as const;
129
69
 
130
- for (const svc of services) {
131
- if (svc.protocol === "mcp") endpoints.mcp = svc.endpoint;
132
- if (svc.protocol === "a2a") endpoints.a2a = svc.endpoint;
133
- if (svc.protocol === "x402") endpoints.x402 = svc.endpoint;
134
- if (svc.protocol === "http") endpoints.http = svc.endpoint;
135
- }
70
+ const endpoints: UnifiedAgent["endpoints"] = {};
71
+ if (protocols.includes("MCP")) endpoints.mcp = agent.mcp_endpoint;
72
+ if (protocols.includes("A2A")) endpoints.a2a = agent.a2a_endpoint;
73
+ if (agent.x402_supported) endpoints.x402 = agent.x402_endpoint;
136
74
 
137
75
  return {
138
- id: `erc8004:${network}:${tokenId}`,
139
- nativeId: tokenId.toString(),
140
- name: metadata.name ?? `Agent #${tokenId}`,
141
- description: metadata.description ?? "",
142
- categories: metadata.categories ?? extractFromDescription(metadata.description ?? ""),
143
- capabilities: services.map((s: any) => `${s.protocol}: ${s.endpoint}`),
76
+ id: `erc8004:${agent.agent_id ?? agent.token_id}`,
77
+ nativeId: agent.token_id?.toString() ?? agent.agent_id ?? "",
78
+ name: agent.name ?? `Agent #${agent.token_id}`,
79
+ ensName: agent.owner_ens ?? undefined,
80
+ description: agent.description ?? "",
81
+ categories: extractCategories(agent.name ?? "", agent.description ?? ""),
82
+ capabilities: protocols.map((p: string) => `Supports ${p}`),
144
83
  source: "erc8004",
145
- protocol: endpoints.a2a ? "a2a" : endpoints.mcp ? "mcp" : endpoints.x402 ? "x402" : "onchain",
84
+ protocol,
146
85
  endpoints,
147
86
  reputation: {
148
- score: 0,
149
- count: 0,
150
- source: "erc8004",
87
+ score: agent.total_score ?? 0,
88
+ count: agent.star_count ?? 0,
89
+ source: "8004scan",
151
90
  },
152
- verified: true,
153
- lastSeen: Date.now(),
154
- raw: { tokenId: tokenId.toString(), owner, metadata, network },
91
+ verified: agent.is_verified ?? false,
92
+ raw: agent,
155
93
  };
156
94
  }
157
95
 
158
- function extractFromDescription(text: string): string[] {
159
- const lower = text.toLowerCase();
96
+ function extractCategories(name: string, description: string): string[] {
97
+ const text = `${name} ${description}`.toLowerCase();
160
98
  const cats: string[] = [];
161
- if (lower.match(/defi|yield|swap|pool/)) cats.push("defi");
162
- if (lower.match(/data|analyt/)) cats.push("data");
163
- if (lower.match(/trade|trading/)) cats.push("trading");
164
- if (lower.match(/research/)) cats.push("research");
99
+ if (text.match(/defi|yield|swap|pool|trading/)) cats.push("defi");
100
+ if (text.match(/data|analyt|research/)) cats.push("data");
101
+ if (text.match(/code|develop|build/)) cats.push("development");
102
+ if (text.match(/ai|model|inference/)) cats.push("ai");
103
+ if (text.match(/security|audit/)) cats.push("security");
165
104
  return cats.length > 0 ? cats : ["general"];
166
105
  }
@@ -1,51 +1,71 @@
1
1
  /**
2
- * L402 Directory Source Adapter
3
- * Indexes Lightning 402 endpoints from known directories
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
- // Known L402 services (from satring, l402.directory, and community)
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 lower = query.toLowerCase();
23
- const filtered = query
24
- ? KNOWN_L402_SERVICES.filter(
25
- (s) =>
26
- s.name.toLowerCase().includes(lower) ||
27
- s.description.toLowerCase().includes(lower) ||
28
- s.categories.some((c) => c.includes(lower))
29
- )
30
- : KNOWN_L402_SERVICES;
31
-
32
- return filtered.slice(0, options?.limit ?? 50).map((service) => ({
33
- id: `l402-directory:${service.name.toLowerCase().replace(/\s+/g, "-")}`,
34
- nativeId: service.name,
35
- name: service.name,
36
- description: service.description,
37
- categories: service.categories,
38
- capabilities: [service.description],
39
- source: "l402-directory" as const,
40
- protocol: "l402" as const,
41
- endpoints: { l402: service.url, http: service.url },
42
- pricing: { model: "per-call" as const, currency: "BTC/sats" },
43
- verified: true,
44
- raw: service,
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
- return true; // Seed list always available
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
  };