feat: enhance ClawdHub integration with paging and retry
Add paging support when loading ClawdHub skills Retry on API errors and throttle for ClawdHub requests Load source content on source change and show loading indicators
This commit is contained in:
@@ -8,6 +8,36 @@
|
||||
import { fetchClawdHubSkills } from './api.js';
|
||||
|
||||
const MAX_PAGES = 20; // Safety limit to prevent infinite loops
|
||||
const CLAWDHUB_PAGE_LIMIT = 25;
|
||||
|
||||
const mapClawdHubItem = (item) => {
|
||||
const latestVersion = item.tags?.latest || item.latestVersion?.version || '1.0.0';
|
||||
|
||||
return {
|
||||
sourceId: 'clawdhub',
|
||||
repoSource: 'clawdhub:registry',
|
||||
repoSubpath: null,
|
||||
gitIdentityId: null,
|
||||
skillDir: item.slug,
|
||||
skillName: item.slug,
|
||||
frontmatterName: item.displayName || item.slug,
|
||||
description: item.summary || null,
|
||||
installable: true,
|
||||
warnings: [],
|
||||
// ClawdHub-specific metadata
|
||||
clawdhub: {
|
||||
slug: item.slug,
|
||||
version: latestVersion,
|
||||
displayName: item.displayName,
|
||||
owner: item.owner?.handle || null,
|
||||
downloads: item.stats?.downloads || 0,
|
||||
stars: item.stats?.stars || 0,
|
||||
versionsCount: item.stats?.versions || 1,
|
||||
createdAt: item.createdAt,
|
||||
updatedAt: item.updatedAt,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Scan ClawdHub registry for all available skills
|
||||
@@ -19,35 +49,23 @@ export async function scanClawdHub() {
|
||||
let cursor = null;
|
||||
|
||||
for (let page = 0; page < MAX_PAGES; page++) {
|
||||
const { items, nextCursor } = await fetchClawdHubSkills({ cursor });
|
||||
let items = [];
|
||||
let nextCursor = null;
|
||||
|
||||
try {
|
||||
const pageResult = await fetchClawdHubSkills({ cursor });
|
||||
items = pageResult.items || [];
|
||||
nextCursor = pageResult.nextCursor || null;
|
||||
} catch (error) {
|
||||
if (page > 0 && allItems.length > 0) {
|
||||
console.warn('ClawdHub pagination failed; returning partial results.');
|
||||
break;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
|
||||
for (const item of items) {
|
||||
const latestVersion = item.tags?.latest || item.latestVersion?.version || '1.0.0';
|
||||
|
||||
allItems.push({
|
||||
sourceId: 'clawdhub',
|
||||
repoSource: 'clawdhub:registry',
|
||||
repoSubpath: null,
|
||||
gitIdentityId: null,
|
||||
skillDir: item.slug,
|
||||
skillName: item.slug,
|
||||
frontmatterName: item.displayName || item.slug,
|
||||
description: item.summary || null,
|
||||
installable: true,
|
||||
warnings: [],
|
||||
// ClawdHub-specific metadata
|
||||
clawdhub: {
|
||||
slug: item.slug,
|
||||
version: latestVersion,
|
||||
displayName: item.displayName,
|
||||
owner: item.owner?.handle || null,
|
||||
downloads: item.stats?.downloads || 0,
|
||||
stars: item.stats?.stars || 0,
|
||||
versionsCount: item.stats?.versions || 1,
|
||||
createdAt: item.createdAt,
|
||||
updatedAt: item.updatedAt,
|
||||
},
|
||||
});
|
||||
allItems.push(mapClawdHubItem(item));
|
||||
}
|
||||
|
||||
if (!nextCursor) {
|
||||
@@ -71,3 +89,25 @@ export async function scanClawdHub() {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan a single ClawdHub page (cursor-based)
|
||||
* @returns {Promise<{ ok: boolean, items?: Array, nextCursor?: string | null, error?: Object }>}
|
||||
*/
|
||||
export async function scanClawdHubPage({ cursor } = {}) {
|
||||
try {
|
||||
const { items, nextCursor } = await fetchClawdHubSkills({ cursor });
|
||||
const mapped = (items || []).map(mapClawdHubItem).slice(0, CLAWDHUB_PAGE_LIMIT);
|
||||
mapped.sort((a, b) => (b.clawdhub?.downloads || 0) - (a.clawdhub?.downloads || 0));
|
||||
return { ok: true, items: mapped, nextCursor: nextCursor || null };
|
||||
} catch (error) {
|
||||
console.error('ClawdHub page scan error:', error);
|
||||
return {
|
||||
ok: false,
|
||||
error: {
|
||||
kind: 'networkError',
|
||||
message: error instanceof Error ? error.message : 'Failed to fetch skills from ClawdHub',
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user