import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'; import { join } from 'node:path'; import { DATA_PATH } from './data-path'; import { parseSeedVersion } from './sync-version'; const MARKETPLACE_URL = process.env.MARKETPLACE_URL ?? 'https://marketplace.officer.dev'; const GLOBAL_TOOLS_DIR = join(DATA_PATH, 'tools'); type ToolInput = { type: string; description: string; values?: string; }; type MarketplaceTool = { dirName: string; name: string; label: string; description: string; body: string; version: number; language: string; inputs: Record; implementation: string; }; type MarketplaceResponse = { categories: Array<{ name: string; tools: MarketplaceTool[] }>; uncategorized: MarketplaceTool[]; }; function buildToolMd(tool: MarketplaceTool): string { const lines = ['---']; lines.push(`name: ${tool.name}`); lines.push(`label: ${tool.label}`); lines.push(`description: ${tool.description}`); lines.push(`version: ${tool.version}`); lines.push(`language: ${tool.language}`); if (tool.inputs && Object.keys(tool.inputs).length > 0) { lines.push('inputs:'); for (const [key, input] of Object.entries(tool.inputs)) { lines.push(` ${key}:`); lines.push(` type: ${input.type}`); if (input.values) { lines.push(` values: ${input.values}`); } lines.push(` description: "${input.description}"`); } } lines.push('---'); lines.push(''); lines.push(tool.body); return lines.join('\n'); } export async function syncMarketplaceTools(): Promise { try { const res = await fetch(`${MARKETPLACE_URL}/api/tools/native`); if (!res.ok) { console.error(`[marketplace] Failed to fetch tools: ${res.status} ${res.statusText}`); return; } const data = (await res.json()) as MarketplaceResponse; mkdirSync(GLOBAL_TOOLS_DIR, { recursive: true }); const allTools: MarketplaceTool[] = []; for (const category of data.categories) { allTools.push(...category.tools); } if (data.uncategorized) { allTools.push(...data.uncategorized); } for (const tool of allTools) { const targetDir = join(GLOBAL_TOOLS_DIR, tool.dirName); const targetToolMd = join(targetDir, 'TOOL.md'); if (existsSync(targetToolMd)) { const existingVersion = parseSeedVersion(readFileSync(targetToolMd, 'utf-8')); if (tool.version <= existingVersion) continue; } mkdirSync(targetDir, { recursive: true }); writeFileSync(targetToolMd, buildToolMd(tool), 'utf-8'); writeFileSync(join(targetDir, 'index.ts'), tool.implementation, 'utf-8'); console.log(`[marketplace] Synced tool: ${tool.dirName} (v${tool.version})`); } } catch (err) { console.error('[marketplace] Failed to sync tools:', err instanceof Error ? err.message : err); } }