public-api-finder 0.2.0 → 0.2.2
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/README.md +4 -4
- package/package.json +1 -1
- package/skills/public-api-finder/SKILL.md +4 -4
- package/src/cli.js +52 -3
package/README.md
CHANGED
|
@@ -11,10 +11,10 @@ Powered by multiple sources:
|
|
|
11
11
|
## Quick start
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
-
npx public-api-finder "weather forecast" --no-auth --https
|
|
15
|
-
npx public-api-finder "crypto prices" --category Cryptocurrency --limit 5
|
|
16
|
-
npx public-api-finder "jobs" --json
|
|
17
|
-
npx public-api-finder "payments" --openapi
|
|
14
|
+
npx --package public-api-finder public-api-finder "weather forecast" --no-auth --https
|
|
15
|
+
npx --package public-api-finder public-api-finder "crypto prices" --category Cryptocurrency --limit 5
|
|
16
|
+
npx --package public-api-finder public-api-finder "jobs" --json
|
|
17
|
+
npx --package public-api-finder public-api-finder "payments" --openapi
|
|
18
18
|
```
|
|
19
19
|
|
|
20
20
|
## Why
|
package/package.json
CHANGED
|
@@ -10,10 +10,10 @@ Use this skill when a task needs a public API candidate. The CLI searches multip
|
|
|
10
10
|
## Quick command
|
|
11
11
|
|
|
12
12
|
```bash
|
|
13
|
-
npx public-api-finder "weather forecast" --no-auth --https
|
|
14
|
-
npx public-api-finder "crypto prices" --category Cryptocurrency --limit 5
|
|
15
|
-
npx public-api-finder "jobs" --json
|
|
16
|
-
npx public-api-finder "payments" --openapi
|
|
13
|
+
npx --package public-api-finder public-api-finder "weather forecast" --no-auth --https
|
|
14
|
+
npx --package public-api-finder public-api-finder "crypto prices" --category Cryptocurrency --limit 5
|
|
15
|
+
npx --package public-api-finder public-api-finder "jobs" --json
|
|
16
|
+
npx --package public-api-finder public-api-finder "payments" --openapi
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
If npm is unavailable, use the bundled fallback script:
|
package/src/cli.js
CHANGED
|
@@ -11,6 +11,54 @@ const SOURCES = {
|
|
|
11
11
|
const CACHE_PATH = process.env.PUBLIC_API_FINDER_CACHE || join(homedir(), '.cache', 'public-api-finder', 'all.json');
|
|
12
12
|
const CACHE_TTL_MS = 24 * 60 * 60 * 1000;
|
|
13
13
|
|
|
14
|
+
const DOMAIN_PROFILES = {
|
|
15
|
+
crypto: {
|
|
16
|
+
triggers: ['crypto', 'cryptocurrency', 'cryptocurrencies', 'bitcoin', 'ethereum', 'blockchain', 'defi', 'token', 'tokens', 'coin', 'coins', 'wallet'],
|
|
17
|
+
categories: ['cryptocurrency', 'currency exchange', 'finance', 'financial'],
|
|
18
|
+
categoryWeights: { cryptocurrency: 16, 'currency exchange': 5, finance: 3, financial: 3 },
|
|
19
|
+
boostTerms: ['crypto', 'cryptocurrency', 'bitcoin', 'ethereum', 'blockchain', 'defi', 'token', 'coin', 'exchange', 'price', 'market'],
|
|
20
|
+
weakTerms: ['price', 'prices'],
|
|
21
|
+
},
|
|
22
|
+
finance: {
|
|
23
|
+
triggers: ['stock', 'stocks', 'equity', 'equities', 'market', 'trading', 'ticker', 'tickers', 'quote', 'quotes', 'etf', 'forex', 'portfolio'],
|
|
24
|
+
categories: ['finance', 'financial', 'currency exchange'],
|
|
25
|
+
categoryWeights: { finance: 14, financial: 14, 'currency exchange': 5 },
|
|
26
|
+
boostTerms: ['stock', 'stocks', 'equity', 'market', 'trading', 'ticker', 'quote', 'quotes', 'forex', 'portfolio'],
|
|
27
|
+
weakTerms: ['quote', 'quotes', 'price', 'prices', 'market'],
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
function detectDomains(queryTokens) {
|
|
32
|
+
return Object.entries(DOMAIN_PROFILES)
|
|
33
|
+
.filter(([, profile]) => profile.triggers.some(t => queryTokens.has(t)))
|
|
34
|
+
.map(([name]) => name);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function domainAdjustment(entry, queryTokens) {
|
|
38
|
+
const domains = detectDomains(queryTokens);
|
|
39
|
+
if (!domains.length) return 0;
|
|
40
|
+
const cat = String(entry.category || '').toLowerCase();
|
|
41
|
+
const text = `${entry.name || ''} ${entry.description || ''} ${entry.provider || ''}`.toLowerCase();
|
|
42
|
+
let adjustment = 0;
|
|
43
|
+
for (const domain of domains) {
|
|
44
|
+
const profile = DOMAIN_PROFILES[domain];
|
|
45
|
+
let categoryBoost = 0;
|
|
46
|
+
for (const [category, weight] of Object.entries(profile.categoryWeights || {})) {
|
|
47
|
+
if (cat.includes(category)) categoryBoost = Math.max(categoryBoost, weight);
|
|
48
|
+
}
|
|
49
|
+
const categoryHit = categoryBoost > 0;
|
|
50
|
+
const textHit = profile.boostTerms.some(t => text.includes(t));
|
|
51
|
+
if (categoryHit) adjustment += categoryBoost;
|
|
52
|
+
else if (textHit) adjustment += 3;
|
|
53
|
+
else adjustment -= 10;
|
|
54
|
+
for (const weak of profile.weakTerms) {
|
|
55
|
+
if (queryTokens.has(weak) && text.includes(weak) && !categoryHit && !textHit) adjustment -= 4;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return adjustment;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
|
|
14
62
|
function usage() {
|
|
15
63
|
console.log(`public-api-finder — multi-source public API discovery for agents
|
|
16
64
|
|
|
@@ -84,7 +132,7 @@ function score(entry, queryTokens) {
|
|
|
84
132
|
if (entry.sources?.length > 1) base += 2;
|
|
85
133
|
if (entry.auth === 'No') base += 1;
|
|
86
134
|
if (entry.https) base += 1;
|
|
87
|
-
return base;
|
|
135
|
+
return base + domainAdjustment(entry, queryTokens);
|
|
88
136
|
}
|
|
89
137
|
|
|
90
138
|
async function cacheIsFresh() {
|
|
@@ -119,7 +167,7 @@ function cleanDescription(desc) {
|
|
|
119
167
|
.replace(/[#*_`>\[\]()]/g, '')
|
|
120
168
|
.replace(/\s+/g, ' ')
|
|
121
169
|
.trim()
|
|
122
|
-
.slice(0,
|
|
170
|
+
.slice(0, 260).replace(/\s+\S{0,20}$/, '');
|
|
123
171
|
}
|
|
124
172
|
|
|
125
173
|
function normalizeAuth(auth) {
|
|
@@ -167,7 +215,7 @@ function parseApisGuru(data) {
|
|
|
167
215
|
const origin = info['x-origin']?.[0]?.url;
|
|
168
216
|
entries.push({
|
|
169
217
|
name: info.title || providerName,
|
|
170
|
-
url: (info.contact?.url && !String(info.contact.url).startsWith('file:')) ? info.contact.url : ((origin && !String(origin).startsWith('file:')) ? origin : `https
|
|
218
|
+
url: (info.contact?.url && !String(info.contact.url).startsWith('file:')) ? info.contact.url : ((origin && !String(origin).startsWith('file:')) ? origin : (version?.swaggerUrl || version?.openapiUrl || `https://api.apis.guru/v2/specs/${providerName}/${item.preferred || 'latest'}/openapi.json`)),
|
|
171
219
|
description: cleanDescription(info.description || `OpenAPI definition for ${providerName}`),
|
|
172
220
|
auth: 'Unknown',
|
|
173
221
|
https: true,
|
|
@@ -279,6 +327,7 @@ function filterEntries(entries, args) {
|
|
|
279
327
|
const matched = q.size ? textScore(e, q) : 1;
|
|
280
328
|
if (q.size && matched === 0) return [];
|
|
281
329
|
const s = q.size ? score(e, q) : 1;
|
|
330
|
+
if (q.size && s <= 0) return [];
|
|
282
331
|
return [{ ...e, score: s + (e.sourceWeight || 0) }];
|
|
283
332
|
}).sort((a, b) => b.score - a.score || String(a.category).localeCompare(String(b.category)) || String(a.name).localeCompare(String(b.name))).slice(0, args.limit);
|
|
284
333
|
}
|