@skillkit/api 1.12.0 → 1.14.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/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/server.ts
4
- import { Hono as Hono6 } from "hono";
4
+ import { Hono as Hono7 } from "hono";
5
5
  import { cors } from "hono/cors";
6
6
  import { MemoryCache } from "@skillkit/core";
7
7
 
@@ -246,6 +246,295 @@ function categoryRoutes(skills) {
246
246
  return app;
247
247
  }
248
248
 
249
+ // src/routes/docs.ts
250
+ import { Hono as Hono6 } from "hono";
251
+ var OPENAPI_SPEC = {
252
+ openapi: "3.1.0",
253
+ info: {
254
+ title: "SkillKit",
255
+ version: "1.12.0",
256
+ description: "Skill Discovery API for AI coding agents. Search, browse, and retrieve skills from the SkillKit marketplace (15,000+ skills across 32 agents).",
257
+ license: { name: "Apache-2.0", url: "https://opensource.org/licenses/Apache-2.0" },
258
+ contact: { name: "SkillKit", url: "https://github.com/rohitg00/skillkit" }
259
+ },
260
+ servers: [
261
+ { url: "http://localhost:3737", description: "Local development" }
262
+ ],
263
+ paths: {
264
+ "/search": {
265
+ get: {
266
+ summary: "Search skills",
267
+ description: "Locate agent skills matching a query, ranked by multi-signal relevance (content, query match, popularity, references).",
268
+ operationId: "searchSkillsGet",
269
+ tags: ["Search"],
270
+ parameters: [
271
+ { name: "q", in: "query", required: true, schema: { type: "string", minLength: 1, maxLength: 200 }, description: "Search query" },
272
+ { name: "limit", in: "query", schema: { type: "integer", default: 20, minimum: 1, maximum: 100 }, description: "Max results to return" },
273
+ { name: "include_content", in: "query", schema: { type: "boolean", default: false }, description: "Include full skill content in response" }
274
+ ],
275
+ responses: {
276
+ "200": { description: "Search results", content: { "application/json": { schema: { $ref: "#/components/schemas/SearchResponse" } } } },
277
+ "400": { description: "Missing query parameter", content: { "application/json": { schema: { $ref: "#/components/schemas/ErrorResponse" } } } },
278
+ "429": { description: "Rate limit exceeded", content: { "application/json": { schema: { $ref: "#/components/schemas/RateLimitResponse" } } } }
279
+ }
280
+ },
281
+ post: {
282
+ summary: "Search skills with filters",
283
+ description: "Search with advanced filters including tags, category, and source.",
284
+ operationId: "searchSkillsPost",
285
+ tags: ["Search"],
286
+ requestBody: {
287
+ required: true,
288
+ content: {
289
+ "application/json": {
290
+ schema: {
291
+ type: "object",
292
+ required: ["query"],
293
+ properties: {
294
+ query: { type: "string", description: "Search query" },
295
+ limit: { type: "integer", default: 20, minimum: 1, maximum: 100, description: "Max results" },
296
+ include_content: { type: "boolean", default: false, description: "Include full content" },
297
+ filters: {
298
+ type: "object",
299
+ properties: {
300
+ tags: { type: "array", items: { type: "string" }, description: "Filter by tags" },
301
+ category: { type: "string", description: "Filter by category" },
302
+ source: { type: "string", description: "Filter by source repo" }
303
+ }
304
+ }
305
+ }
306
+ }
307
+ }
308
+ }
309
+ },
310
+ responses: {
311
+ "200": { description: "Filtered search results", content: { "application/json": { schema: { $ref: "#/components/schemas/SearchResponse" } } } },
312
+ "400": { description: "Invalid request", content: { "application/json": { schema: { $ref: "#/components/schemas/ErrorResponse" } } } }
313
+ }
314
+ }
315
+ },
316
+ "/skills/{owner}/{repo}/{id}": {
317
+ get: {
318
+ summary: "Get skill by ID",
319
+ description: "Retrieve a specific skill by its source repository and name.",
320
+ operationId: "getSkill",
321
+ tags: ["Skills"],
322
+ parameters: [
323
+ { name: "owner", in: "path", required: true, schema: { type: "string" }, description: "Repository owner" },
324
+ { name: "repo", in: "path", required: true, schema: { type: "string" }, description: "Repository name" },
325
+ { name: "id", in: "path", required: true, schema: { type: "string" }, description: "Skill name" }
326
+ ],
327
+ responses: {
328
+ "200": { description: "Skill details", content: { "application/json": { schema: { $ref: "#/components/schemas/Skill" } } } },
329
+ "404": { description: "Skill not found", content: { "application/json": { schema: { $ref: "#/components/schemas/ErrorResponse" } } } }
330
+ }
331
+ }
332
+ },
333
+ "/trending": {
334
+ get: {
335
+ summary: "Trending skills",
336
+ description: "Get top skills ranked by multi-signal relevance score (content availability, popularity, references).",
337
+ operationId: "getTrending",
338
+ tags: ["Discovery"],
339
+ parameters: [
340
+ { name: "limit", in: "query", schema: { type: "integer", default: 20, minimum: 1, maximum: 100 }, description: "Max results" }
341
+ ],
342
+ responses: {
343
+ "200": { description: "Trending skills", content: { "application/json": { schema: { $ref: "#/components/schemas/TrendingResponse" } } } }
344
+ }
345
+ }
346
+ },
347
+ "/categories": {
348
+ get: {
349
+ summary: "Skill categories",
350
+ description: "List all skill categories and tags with their counts, sorted by popularity.",
351
+ operationId: "getCategories",
352
+ tags: ["Discovery"],
353
+ responses: {
354
+ "200": { description: "Category list", content: { "application/json": { schema: { $ref: "#/components/schemas/CategoriesResponse" } } } }
355
+ }
356
+ }
357
+ },
358
+ "/health": {
359
+ get: {
360
+ summary: "Health check",
361
+ description: "Server health status including version, skill count, and uptime.",
362
+ operationId: "getHealth",
363
+ tags: ["System"],
364
+ responses: {
365
+ "200": { description: "Server health", content: { "application/json": { schema: { $ref: "#/components/schemas/HealthResponse" } } } }
366
+ }
367
+ }
368
+ },
369
+ "/cache/stats": {
370
+ get: {
371
+ summary: "Cache statistics",
372
+ description: "Cache hit/miss rates and current size.",
373
+ operationId: "getCacheStats",
374
+ tags: ["System"],
375
+ responses: {
376
+ "200": { description: "Cache stats", content: { "application/json": { schema: { $ref: "#/components/schemas/CacheStatsResponse" } } } }
377
+ }
378
+ }
379
+ }
380
+ },
381
+ components: {
382
+ schemas: {
383
+ Skill: {
384
+ type: "object",
385
+ properties: {
386
+ name: { type: "string", description: "Skill name" },
387
+ description: { type: "string", description: "Skill description" },
388
+ source: { type: "string", description: "Source repository (owner/repo)" },
389
+ repo: { type: "string", description: "Repository URL" },
390
+ tags: { type: "array", items: { type: "string" }, description: "Skill tags" },
391
+ category: { type: "string", description: "Skill category" },
392
+ content: { type: "string", description: "Full SKILL.md content (when requested)" },
393
+ stars: { type: "integer", description: "GitHub stars" },
394
+ installs: { type: "integer", description: "Install count" }
395
+ },
396
+ required: ["name", "source"]
397
+ },
398
+ SearchResponse: {
399
+ type: "object",
400
+ properties: {
401
+ skills: { type: "array", items: { $ref: "#/components/schemas/Skill" } },
402
+ total: { type: "integer", description: "Total matching skills" },
403
+ query: { type: "string", description: "Original query" },
404
+ limit: { type: "integer", description: "Applied limit" }
405
+ },
406
+ required: ["skills", "total", "query", "limit"]
407
+ },
408
+ TrendingResponse: {
409
+ type: "object",
410
+ properties: {
411
+ skills: { type: "array", items: { $ref: "#/components/schemas/Skill" } },
412
+ limit: { type: "integer" }
413
+ },
414
+ required: ["skills", "limit"]
415
+ },
416
+ CategoriesResponse: {
417
+ type: "object",
418
+ properties: {
419
+ categories: { type: "array", items: { $ref: "#/components/schemas/CategoryCount" } },
420
+ total: { type: "integer" }
421
+ },
422
+ required: ["categories", "total"]
423
+ },
424
+ CategoryCount: {
425
+ type: "object",
426
+ properties: {
427
+ name: { type: "string" },
428
+ count: { type: "integer" }
429
+ },
430
+ required: ["name", "count"]
431
+ },
432
+ HealthResponse: {
433
+ type: "object",
434
+ properties: {
435
+ status: { type: "string", enum: ["ok"] },
436
+ version: { type: "string" },
437
+ skillCount: { type: "integer" },
438
+ uptime: { type: "number", description: "Uptime in seconds" }
439
+ },
440
+ required: ["status", "version", "skillCount", "uptime"]
441
+ },
442
+ CacheStatsResponse: {
443
+ type: "object",
444
+ properties: {
445
+ hits: { type: "integer" },
446
+ misses: { type: "integer" },
447
+ size: { type: "integer" },
448
+ maxSize: { type: "integer" },
449
+ hitRate: { type: "number" }
450
+ },
451
+ required: ["hits", "misses", "size", "maxSize", "hitRate"]
452
+ },
453
+ ErrorResponse: {
454
+ type: "object",
455
+ properties: {
456
+ error: { type: "string" }
457
+ },
458
+ required: ["error"]
459
+ },
460
+ RateLimitResponse: {
461
+ type: "object",
462
+ properties: {
463
+ error: { type: "string" },
464
+ retryAfter: { type: "integer", description: "Seconds until rate limit resets" }
465
+ },
466
+ required: ["error", "retryAfter"]
467
+ }
468
+ }
469
+ },
470
+ tags: [
471
+ { name: "Search", description: "Skill search and filtering" },
472
+ { name: "Skills", description: "Individual skill retrieval" },
473
+ { name: "Discovery", description: "Trending skills and categories" },
474
+ { name: "System", description: "Health checks and diagnostics" }
475
+ ]
476
+ };
477
+ var SWAGGER_HTML = `<!DOCTYPE html>
478
+ <html lang="en">
479
+ <head>
480
+ <meta charset="UTF-8">
481
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
482
+ <title>SkillKit API Documentation</title>
483
+ <link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css">
484
+ <style>
485
+ body { margin: 0; background: #1a1a2e; }
486
+ .swagger-ui .topbar { display: none; }
487
+ .swagger-ui { max-width: 1200px; margin: 0 auto; }
488
+ .swagger-ui .info .title { font-family: monospace; }
489
+ </style>
490
+ </head>
491
+ <body>
492
+ <div id="swagger-ui"></div>
493
+ <script src="https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js"></script>
494
+ <script>
495
+ SwaggerUIBundle({
496
+ url: '/openapi.json',
497
+ dom_id: '#swagger-ui',
498
+ deepLinking: true,
499
+ showExtensions: true,
500
+ showCommonExtensions: true,
501
+ defaultModelsExpandDepth: 2,
502
+ defaultModelExpandDepth: 2,
503
+ docExpansion: 'list',
504
+ filter: true,
505
+ tryItOutEnabled: true,
506
+ });
507
+ </script>
508
+ </body>
509
+ </html>`;
510
+ function docsRoutes() {
511
+ const app = new Hono6();
512
+ app.get("/openapi.json", (c) => {
513
+ return c.json(OPENAPI_SPEC);
514
+ });
515
+ app.get("/docs", (c) => {
516
+ return c.html(SWAGGER_HTML);
517
+ });
518
+ app.get("/", (c) => {
519
+ return c.json({
520
+ name: "SkillKit API",
521
+ version: "1.12.0",
522
+ docs: "/docs",
523
+ openapi: "/openapi.json",
524
+ endpoints: {
525
+ search: "GET /search?q=...",
526
+ searchFiltered: "POST /search",
527
+ skill: "GET /skills/:owner/:repo/:id",
528
+ trending: "GET /trending",
529
+ categories: "GET /categories",
530
+ health: "GET /health",
531
+ cache: "GET /cache/stats"
532
+ }
533
+ });
534
+ });
535
+ return app;
536
+ }
537
+
249
538
  // src/server.ts
250
539
  function createApp(options = {}) {
251
540
  const skills = options.skills || [];
@@ -253,7 +542,7 @@ function createApp(options = {}) {
253
542
  maxSize: 500,
254
543
  ttlMs: options.cacheTtlMs ?? 864e5
255
544
  });
256
- const app = new Hono6();
545
+ const app = new Hono7();
257
546
  app.use("*", cors({ origin: options.corsOrigin || "*" }));
258
547
  app.use("*", rateLimiter(options.rateLimitMax ?? 60));
259
548
  app.route("/", healthRoutes(skills.length, cache));
@@ -261,6 +550,7 @@ function createApp(options = {}) {
261
550
  app.route("/", skillRoutes(skills));
262
551
  app.route("/", trendingRoutes(skills));
263
552
  app.route("/", categoryRoutes(skills));
553
+ app.route("/", docsRoutes());
264
554
  return { app, cache };
265
555
  }
266
556
  async function startServer(options = {}) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/server.ts","../src/middleware/rate-limit.ts","../src/routes/health.ts","../src/routes/search.ts","../src/routes/skills.ts","../src/routes/trending.ts","../src/routes/categories.ts"],"sourcesContent":["import { Hono } from 'hono';\nimport { cors } from 'hono/cors';\nimport { MemoryCache } from '@skillkit/core';\nimport { rateLimiter } from './middleware/rate-limit.js';\nimport { healthRoutes } from './routes/health.js';\nimport { searchRoutes } from './routes/search.js';\nimport { skillRoutes } from './routes/skills.js';\nimport { trendingRoutes } from './routes/trending.js';\nimport { categoryRoutes } from './routes/categories.js';\nimport type { ApiSkill, SearchResponse } from './types.js';\n\nexport interface ServerOptions {\n port?: number;\n host?: string;\n corsOrigin?: string;\n cacheTtlMs?: number;\n skills?: ApiSkill[];\n rateLimitMax?: number;\n}\n\nexport function createApp(options: ServerOptions = {}) {\n const skills = options.skills || [];\n const cache = new MemoryCache<SearchResponse>({\n maxSize: 500,\n ttlMs: options.cacheTtlMs ?? 86_400_000,\n });\n\n const app = new Hono();\n\n app.use('*', cors({ origin: options.corsOrigin || '*' }));\n app.use('*', rateLimiter(options.rateLimitMax ?? 60));\n\n app.route('/', healthRoutes(skills.length, cache));\n app.route('/', searchRoutes(skills, cache));\n app.route('/', skillRoutes(skills));\n app.route('/', trendingRoutes(skills));\n app.route('/', categoryRoutes(skills));\n\n return { app, cache };\n}\n\nexport async function startServer(options: ServerOptions = {}) {\n const port = options.port ?? 3737;\n const host = options.host ?? '0.0.0.0';\n const { app, cache } = createApp(options);\n\n const { serve } = await import('@hono/node-server');\n\n const server = serve({ fetch: app.fetch, port, hostname: host }, () => {\n console.log(`SkillKit API server running at http://${host}:${port}`);\n console.log(`Skills loaded: ${options.skills?.length ?? 0}`);\n });\n\n return { server, app, cache };\n}\n","import type { Context, Next } from 'hono';\n\ninterface RateLimitEntry {\n count: number;\n resetAt: number;\n}\n\nexport function rateLimiter(maxRequests = 60, windowMs = 60_000) {\n const windows = new Map<string, RateLimitEntry>();\n\n setInterval(() => {\n const now = Date.now();\n for (const [key, entry] of windows) {\n if (now > entry.resetAt) {\n windows.delete(key);\n }\n }\n }, windowMs).unref();\n\n return async (c: Context, next: Next): Promise<Response | void> => {\n const forwardedFor = c.req.header('x-forwarded-for');\n const ip = (forwardedFor?.split(',')[0]?.trim()) || c.req.header('x-real-ip') || 'unknown';\n const now = Date.now();\n\n let entry = windows.get(ip);\n if (!entry || now > entry.resetAt) {\n entry = { count: 0, resetAt: now + windowMs };\n windows.set(ip, entry);\n }\n\n entry.count++;\n\n c.header('X-RateLimit-Limit', String(maxRequests));\n c.header('X-RateLimit-Remaining', String(Math.max(0, maxRequests - entry.count)));\n c.header('X-RateLimit-Reset', String(Math.ceil(entry.resetAt / 1000)));\n\n if (entry.count > maxRequests) {\n return c.json({ error: 'Too many requests', retryAfter: Math.ceil((entry.resetAt - now) / 1000) }, 429);\n }\n\n await next();\n };\n}\n","import { Hono } from 'hono';\nimport type { HealthResponse, CacheStatsResponse } from '../types.js';\nimport type { CacheBackend } from '@skillkit/core';\n\nconst startTime = Date.now();\n\nexport function healthRoutes(skillCount: number, cache: CacheBackend) {\n const app = new Hono();\n\n app.get('/health', (c) => {\n const response: HealthResponse = {\n status: 'ok',\n version: '1.11.0',\n skillCount,\n uptime: Math.floor((Date.now() - startTime) / 1000),\n };\n return c.json(response);\n });\n\n app.get('/cache/stats', (c) => {\n const stats = cache.stats();\n const response: CacheStatsResponse = {\n hits: stats.hits,\n misses: stats.misses,\n size: stats.size,\n maxSize: stats.maxSize,\n hitRate: stats.hitRate,\n };\n return c.json(response);\n });\n\n return app;\n}\n","import { Hono } from 'hono';\nimport type { ApiSkill, SearchResponse } from '../types.js';\nimport { RelevanceRanker } from '@skillkit/core';\nimport type { MemoryCache } from '@skillkit/core';\n\nexport function searchRoutes(skills: ApiSkill[], cache: MemoryCache<SearchResponse>) {\n const app = new Hono();\n const ranker = new RelevanceRanker();\n\n app.get('/search', (c) => {\n const query = c.req.query('q') || '';\n const parsedLimit = parseInt(c.req.query('limit') || '20', 10);\n const limit = Math.min(Number.isNaN(parsedLimit) ? 20 : parsedLimit, 100);\n const includeContent = c.req.query('include_content') === 'true';\n\n if (!query) {\n return c.json({ error: 'Query parameter \"q\" is required' }, 400);\n }\n\n const cacheKey = `search:${query}:${limit}:${includeContent}`;\n const cached = cache.get(cacheKey);\n if (cached) return c.json(cached);\n\n const skillMap = new Map(skills.map((s) => [`${s.source}:${s.name}`, s]));\n\n const ranked = ranker.rank(\n skills.map((s) => ({\n name: s.name,\n description: s.description,\n content: s.content,\n stars: s.stars,\n installs: s.installs,\n source: s.source,\n })),\n query,\n );\n\n const results: ApiSkill[] = ranked.slice(0, limit).map((r) => {\n const key = `${(r.skill as Record<string, unknown>).source}:${r.skill.name}`;\n const original = skillMap.get(key) ?? skills.find((s) => s.name === r.skill.name)!;\n if (!includeContent) {\n const { content: _, ...rest } = original;\n return rest;\n }\n return original;\n });\n\n const response: SearchResponse = {\n skills: results,\n total: ranked.length,\n query,\n limit,\n };\n\n cache.set(cacheKey, response);\n return c.json(response);\n });\n\n app.post('/search', async (c) => {\n let body: {\n query: string;\n limit?: number;\n include_content?: boolean;\n filters?: { tags?: string[]; category?: string; source?: string };\n };\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n\n if (!body.query) {\n return c.json({ error: 'Field \"query\" is required' }, 400);\n }\n\n const limit = Math.min(body.limit ?? 20, 100);\n let filtered = skills;\n\n if (body.filters) {\n if (body.filters.tags?.length) {\n filtered = filtered.filter((s) =>\n body.filters!.tags!.some((t) => s.tags?.includes(t)),\n );\n }\n if (body.filters.category) {\n filtered = filtered.filter((s) => s.category === body.filters!.category);\n }\n if (body.filters.source) {\n filtered = filtered.filter((s) => s.source.includes(body.filters!.source!));\n }\n }\n\n const filteredMap = new Map(filtered.map((s) => [`${s.source}:${s.name}`, s]));\n\n const ranked = ranker.rank(\n filtered.map((s) => ({\n name: s.name,\n description: s.description,\n content: s.content,\n stars: s.stars,\n installs: s.installs,\n source: s.source,\n })),\n body.query,\n );\n\n const results: ApiSkill[] = ranked.slice(0, limit).map((r) => {\n const key = `${(r.skill as Record<string, unknown>).source}:${r.skill.name}`;\n const original = filteredMap.get(key) ?? filtered.find((s) => s.name === r.skill.name)!;\n if (!body.include_content) {\n const { content: _, ...rest } = original;\n return rest;\n }\n return original;\n });\n\n const response: SearchResponse = {\n skills: results,\n total: ranked.length,\n query: body.query,\n limit,\n };\n\n return c.json(response);\n });\n\n return app;\n}\n","import { Hono } from 'hono';\nimport type { ApiSkill } from '../types.js';\n\nexport function skillRoutes(skills: ApiSkill[]) {\n const app = new Hono();\n\n app.get('/skills/:owner/:repo/:id', (c) => {\n const source = `${c.req.param('owner')}/${c.req.param('repo')}`;\n const id = c.req.param('id');\n\n const skill = skills.find(\n (s) => s.source === source && s.name === id,\n );\n\n if (!skill) {\n return c.json({ error: `Skill not found: ${source}/${id}` }, 404);\n }\n\n return c.json(skill);\n });\n\n return app;\n}\n","import { Hono } from 'hono';\nimport type { ApiSkill, TrendingResponse } from '../types.js';\nimport { RelevanceRanker } from '@skillkit/core';\n\nexport function trendingRoutes(skills: ApiSkill[]) {\n const app = new Hono();\n const ranker = new RelevanceRanker();\n\n app.get('/trending', (c) => {\n const parsedLimit = parseInt(c.req.query('limit') || '20', 10);\n const limit = Math.min(Number.isNaN(parsedLimit) ? 20 : parsedLimit, 100);\n\n const skillMap = new Map(skills.map((s) => [`${s.source}:${s.name}`, s]));\n\n const ranked = ranker.rank(\n skills.map((s) => ({\n name: s.name,\n description: s.description,\n content: s.content,\n stars: s.stars,\n installs: s.installs,\n references: [],\n source: s.source,\n })),\n );\n\n const results = ranked.slice(0, limit).map((r) => {\n const key = `${(r.skill as Record<string, unknown>).source}:${r.skill.name}`;\n const original = skillMap.get(key) ?? skills.find((s) => s.name === r.skill.name)!;\n const { content: _, ...rest } = original;\n return rest;\n });\n\n const response: TrendingResponse = { skills: results, limit };\n return c.json(response);\n });\n\n return app;\n}\n","import { Hono } from 'hono';\nimport type { ApiSkill, CategoriesResponse } from '../types.js';\n\nexport function categoryRoutes(skills: ApiSkill[]) {\n const app = new Hono();\n\n app.get('/categories', (c) => {\n const tagCounts = new Map<string, number>();\n\n for (const skill of skills) {\n if (skill.tags) {\n for (const tag of skill.tags) {\n tagCounts.set(tag, (tagCounts.get(tag) || 0) + 1);\n }\n }\n if (skill.category) {\n const key = `category:${skill.category}`;\n tagCounts.set(key, (tagCounts.get(key) || 0) + 1);\n }\n }\n\n const categories = Array.from(tagCounts.entries())\n .map(([name, count]) => ({ name, count }))\n .sort((a, b) => b.count - a.count);\n\n const response: CategoriesResponse = {\n categories,\n total: categories.length,\n };\n return c.json(response);\n });\n\n return app;\n}\n"],"mappings":"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","names":["Hono","Hono","Hono","Hono","RelevanceRanker","Hono","Hono"]}
1
+ {"version":3,"sources":["../src/server.ts","../src/middleware/rate-limit.ts","../src/routes/health.ts","../src/routes/search.ts","../src/routes/skills.ts","../src/routes/trending.ts","../src/routes/categories.ts","../src/routes/docs.ts"],"sourcesContent":["import { Hono } from 'hono';\nimport { cors } from 'hono/cors';\nimport { MemoryCache } from '@skillkit/core';\nimport { rateLimiter } from './middleware/rate-limit.js';\nimport { healthRoutes } from './routes/health.js';\nimport { searchRoutes } from './routes/search.js';\nimport { skillRoutes } from './routes/skills.js';\nimport { trendingRoutes } from './routes/trending.js';\nimport { categoryRoutes } from './routes/categories.js';\nimport { docsRoutes } from './routes/docs.js';\nimport type { ApiSkill, SearchResponse } from './types.js';\n\nexport interface ServerOptions {\n port?: number;\n host?: string;\n corsOrigin?: string;\n cacheTtlMs?: number;\n skills?: ApiSkill[];\n rateLimitMax?: number;\n}\n\nexport function createApp(options: ServerOptions = {}) {\n const skills = options.skills || [];\n const cache = new MemoryCache<SearchResponse>({\n maxSize: 500,\n ttlMs: options.cacheTtlMs ?? 86_400_000,\n });\n\n const app = new Hono();\n\n app.use('*', cors({ origin: options.corsOrigin || '*' }));\n app.use('*', rateLimiter(options.rateLimitMax ?? 60));\n\n app.route('/', healthRoutes(skills.length, cache));\n app.route('/', searchRoutes(skills, cache));\n app.route('/', skillRoutes(skills));\n app.route('/', trendingRoutes(skills));\n app.route('/', categoryRoutes(skills));\n app.route('/', docsRoutes());\n\n return { app, cache };\n}\n\nexport async function startServer(options: ServerOptions = {}) {\n const port = options.port ?? 3737;\n const host = options.host ?? '0.0.0.0';\n const { app, cache } = createApp(options);\n\n const { serve } = await import('@hono/node-server');\n\n const server = serve({ fetch: app.fetch, port, hostname: host }, () => {\n console.log(`SkillKit API server running at http://${host}:${port}`);\n console.log(`Skills loaded: ${options.skills?.length ?? 0}`);\n });\n\n return { server, app, cache };\n}\n","import type { Context, Next } from 'hono';\n\ninterface RateLimitEntry {\n count: number;\n resetAt: number;\n}\n\nexport function rateLimiter(maxRequests = 60, windowMs = 60_000) {\n const windows = new Map<string, RateLimitEntry>();\n\n setInterval(() => {\n const now = Date.now();\n for (const [key, entry] of windows) {\n if (now > entry.resetAt) {\n windows.delete(key);\n }\n }\n }, windowMs).unref();\n\n return async (c: Context, next: Next): Promise<Response | void> => {\n const forwardedFor = c.req.header('x-forwarded-for');\n const ip = (forwardedFor?.split(',')[0]?.trim()) || c.req.header('x-real-ip') || 'unknown';\n const now = Date.now();\n\n let entry = windows.get(ip);\n if (!entry || now > entry.resetAt) {\n entry = { count: 0, resetAt: now + windowMs };\n windows.set(ip, entry);\n }\n\n entry.count++;\n\n c.header('X-RateLimit-Limit', String(maxRequests));\n c.header('X-RateLimit-Remaining', String(Math.max(0, maxRequests - entry.count)));\n c.header('X-RateLimit-Reset', String(Math.ceil(entry.resetAt / 1000)));\n\n if (entry.count > maxRequests) {\n return c.json({ error: 'Too many requests', retryAfter: Math.ceil((entry.resetAt - now) / 1000) }, 429);\n }\n\n await next();\n };\n}\n","import { Hono } from 'hono';\nimport type { HealthResponse, CacheStatsResponse } from '../types.js';\nimport type { CacheBackend } from '@skillkit/core';\n\nconst startTime = Date.now();\n\nexport function healthRoutes(skillCount: number, cache: CacheBackend) {\n const app = new Hono();\n\n app.get('/health', (c) => {\n const response: HealthResponse = {\n status: 'ok',\n version: '1.11.0',\n skillCount,\n uptime: Math.floor((Date.now() - startTime) / 1000),\n };\n return c.json(response);\n });\n\n app.get('/cache/stats', (c) => {\n const stats = cache.stats();\n const response: CacheStatsResponse = {\n hits: stats.hits,\n misses: stats.misses,\n size: stats.size,\n maxSize: stats.maxSize,\n hitRate: stats.hitRate,\n };\n return c.json(response);\n });\n\n return app;\n}\n","import { Hono } from 'hono';\nimport type { ApiSkill, SearchResponse } from '../types.js';\nimport { RelevanceRanker } from '@skillkit/core';\nimport type { MemoryCache } from '@skillkit/core';\n\nexport function searchRoutes(skills: ApiSkill[], cache: MemoryCache<SearchResponse>) {\n const app = new Hono();\n const ranker = new RelevanceRanker();\n\n app.get('/search', (c) => {\n const query = c.req.query('q') || '';\n const parsedLimit = parseInt(c.req.query('limit') || '20', 10);\n const limit = Math.min(Number.isNaN(parsedLimit) ? 20 : parsedLimit, 100);\n const includeContent = c.req.query('include_content') === 'true';\n\n if (!query) {\n return c.json({ error: 'Query parameter \"q\" is required' }, 400);\n }\n\n const cacheKey = `search:${query}:${limit}:${includeContent}`;\n const cached = cache.get(cacheKey);\n if (cached) return c.json(cached);\n\n const skillMap = new Map(skills.map((s) => [`${s.source}:${s.name}`, s]));\n\n const ranked = ranker.rank(\n skills.map((s) => ({\n name: s.name,\n description: s.description,\n content: s.content,\n stars: s.stars,\n installs: s.installs,\n source: s.source,\n })),\n query,\n );\n\n const results: ApiSkill[] = ranked.slice(0, limit).map((r) => {\n const key = `${(r.skill as Record<string, unknown>).source}:${r.skill.name}`;\n const original = skillMap.get(key) ?? skills.find((s) => s.name === r.skill.name)!;\n if (!includeContent) {\n const { content: _, ...rest } = original;\n return rest;\n }\n return original;\n });\n\n const response: SearchResponse = {\n skills: results,\n total: ranked.length,\n query,\n limit,\n };\n\n cache.set(cacheKey, response);\n return c.json(response);\n });\n\n app.post('/search', async (c) => {\n let body: {\n query: string;\n limit?: number;\n include_content?: boolean;\n filters?: { tags?: string[]; category?: string; source?: string };\n };\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n\n if (!body.query) {\n return c.json({ error: 'Field \"query\" is required' }, 400);\n }\n\n const limit = Math.min(body.limit ?? 20, 100);\n let filtered = skills;\n\n if (body.filters) {\n if (body.filters.tags?.length) {\n filtered = filtered.filter((s) =>\n body.filters!.tags!.some((t) => s.tags?.includes(t)),\n );\n }\n if (body.filters.category) {\n filtered = filtered.filter((s) => s.category === body.filters!.category);\n }\n if (body.filters.source) {\n filtered = filtered.filter((s) => s.source.includes(body.filters!.source!));\n }\n }\n\n const filteredMap = new Map(filtered.map((s) => [`${s.source}:${s.name}`, s]));\n\n const ranked = ranker.rank(\n filtered.map((s) => ({\n name: s.name,\n description: s.description,\n content: s.content,\n stars: s.stars,\n installs: s.installs,\n source: s.source,\n })),\n body.query,\n );\n\n const results: ApiSkill[] = ranked.slice(0, limit).map((r) => {\n const key = `${(r.skill as Record<string, unknown>).source}:${r.skill.name}`;\n const original = filteredMap.get(key) ?? filtered.find((s) => s.name === r.skill.name)!;\n if (!body.include_content) {\n const { content: _, ...rest } = original;\n return rest;\n }\n return original;\n });\n\n const response: SearchResponse = {\n skills: results,\n total: ranked.length,\n query: body.query,\n limit,\n };\n\n return c.json(response);\n });\n\n return app;\n}\n","import { Hono } from 'hono';\nimport type { ApiSkill } from '../types.js';\n\nexport function skillRoutes(skills: ApiSkill[]) {\n const app = new Hono();\n\n app.get('/skills/:owner/:repo/:id', (c) => {\n const source = `${c.req.param('owner')}/${c.req.param('repo')}`;\n const id = c.req.param('id');\n\n const skill = skills.find(\n (s) => s.source === source && s.name === id,\n );\n\n if (!skill) {\n return c.json({ error: `Skill not found: ${source}/${id}` }, 404);\n }\n\n return c.json(skill);\n });\n\n return app;\n}\n","import { Hono } from 'hono';\nimport type { ApiSkill, TrendingResponse } from '../types.js';\nimport { RelevanceRanker } from '@skillkit/core';\n\nexport function trendingRoutes(skills: ApiSkill[]) {\n const app = new Hono();\n const ranker = new RelevanceRanker();\n\n app.get('/trending', (c) => {\n const parsedLimit = parseInt(c.req.query('limit') || '20', 10);\n const limit = Math.min(Number.isNaN(parsedLimit) ? 20 : parsedLimit, 100);\n\n const skillMap = new Map(skills.map((s) => [`${s.source}:${s.name}`, s]));\n\n const ranked = ranker.rank(\n skills.map((s) => ({\n name: s.name,\n description: s.description,\n content: s.content,\n stars: s.stars,\n installs: s.installs,\n references: [],\n source: s.source,\n })),\n );\n\n const results = ranked.slice(0, limit).map((r) => {\n const key = `${(r.skill as Record<string, unknown>).source}:${r.skill.name}`;\n const original = skillMap.get(key) ?? skills.find((s) => s.name === r.skill.name)!;\n const { content: _, ...rest } = original;\n return rest;\n });\n\n const response: TrendingResponse = { skills: results, limit };\n return c.json(response);\n });\n\n return app;\n}\n","import { Hono } from 'hono';\nimport type { ApiSkill, CategoriesResponse } from '../types.js';\n\nexport function categoryRoutes(skills: ApiSkill[]) {\n const app = new Hono();\n\n app.get('/categories', (c) => {\n const tagCounts = new Map<string, number>();\n\n for (const skill of skills) {\n if (skill.tags) {\n for (const tag of skill.tags) {\n tagCounts.set(tag, (tagCounts.get(tag) || 0) + 1);\n }\n }\n if (skill.category) {\n const key = `category:${skill.category}`;\n tagCounts.set(key, (tagCounts.get(key) || 0) + 1);\n }\n }\n\n const categories = Array.from(tagCounts.entries())\n .map(([name, count]) => ({ name, count }))\n .sort((a, b) => b.count - a.count);\n\n const response: CategoriesResponse = {\n categories,\n total: categories.length,\n };\n return c.json(response);\n });\n\n return app;\n}\n","import { Hono } from 'hono';\n\nconst OPENAPI_SPEC = {\n openapi: '3.1.0',\n info: {\n title: 'SkillKit',\n version: '1.12.0',\n description: 'Skill Discovery API for AI coding agents. Search, browse, and retrieve skills from the SkillKit marketplace (15,000+ skills across 32 agents).',\n license: { name: 'Apache-2.0', url: 'https://opensource.org/licenses/Apache-2.0' },\n contact: { name: 'SkillKit', url: 'https://github.com/rohitg00/skillkit' },\n },\n servers: [\n { url: 'http://localhost:3737', description: 'Local development' },\n ],\n paths: {\n '/search': {\n get: {\n summary: 'Search skills',\n description: 'Locate agent skills matching a query, ranked by multi-signal relevance (content, query match, popularity, references).',\n operationId: 'searchSkillsGet',\n tags: ['Search'],\n parameters: [\n { name: 'q', in: 'query', required: true, schema: { type: 'string', minLength: 1, maxLength: 200 }, description: 'Search query' },\n { name: 'limit', in: 'query', schema: { type: 'integer', default: 20, minimum: 1, maximum: 100 }, description: 'Max results to return' },\n { name: 'include_content', in: 'query', schema: { type: 'boolean', default: false }, description: 'Include full skill content in response' },\n ],\n responses: {\n '200': { description: 'Search results', content: { 'application/json': { schema: { $ref: '#/components/schemas/SearchResponse' } } } },\n '400': { description: 'Missing query parameter', content: { 'application/json': { schema: { $ref: '#/components/schemas/ErrorResponse' } } } },\n '429': { description: 'Rate limit exceeded', content: { 'application/json': { schema: { $ref: '#/components/schemas/RateLimitResponse' } } } },\n },\n },\n post: {\n summary: 'Search skills with filters',\n description: 'Search with advanced filters including tags, category, and source.',\n operationId: 'searchSkillsPost',\n tags: ['Search'],\n requestBody: {\n required: true,\n content: {\n 'application/json': {\n schema: {\n type: 'object',\n required: ['query'],\n properties: {\n query: { type: 'string', description: 'Search query' },\n limit: { type: 'integer', default: 20, minimum: 1, maximum: 100, description: 'Max results' },\n include_content: { type: 'boolean', default: false, description: 'Include full content' },\n filters: {\n type: 'object',\n properties: {\n tags: { type: 'array', items: { type: 'string' }, description: 'Filter by tags' },\n category: { type: 'string', description: 'Filter by category' },\n source: { type: 'string', description: 'Filter by source repo' },\n },\n },\n },\n },\n },\n },\n },\n responses: {\n '200': { description: 'Filtered search results', content: { 'application/json': { schema: { $ref: '#/components/schemas/SearchResponse' } } } },\n '400': { description: 'Invalid request', content: { 'application/json': { schema: { $ref: '#/components/schemas/ErrorResponse' } } } },\n },\n },\n },\n '/skills/{owner}/{repo}/{id}': {\n get: {\n summary: 'Get skill by ID',\n description: 'Retrieve a specific skill by its source repository and name.',\n operationId: 'getSkill',\n tags: ['Skills'],\n parameters: [\n { name: 'owner', in: 'path', required: true, schema: { type: 'string' }, description: 'Repository owner' },\n { name: 'repo', in: 'path', required: true, schema: { type: 'string' }, description: 'Repository name' },\n { name: 'id', in: 'path', required: true, schema: { type: 'string' }, description: 'Skill name' },\n ],\n responses: {\n '200': { description: 'Skill details', content: { 'application/json': { schema: { $ref: '#/components/schemas/Skill' } } } },\n '404': { description: 'Skill not found', content: { 'application/json': { schema: { $ref: '#/components/schemas/ErrorResponse' } } } },\n },\n },\n },\n '/trending': {\n get: {\n summary: 'Trending skills',\n description: 'Get top skills ranked by multi-signal relevance score (content availability, popularity, references).',\n operationId: 'getTrending',\n tags: ['Discovery'],\n parameters: [\n { name: 'limit', in: 'query', schema: { type: 'integer', default: 20, minimum: 1, maximum: 100 }, description: 'Max results' },\n ],\n responses: {\n '200': { description: 'Trending skills', content: { 'application/json': { schema: { $ref: '#/components/schemas/TrendingResponse' } } } },\n },\n },\n },\n '/categories': {\n get: {\n summary: 'Skill categories',\n description: 'List all skill categories and tags with their counts, sorted by popularity.',\n operationId: 'getCategories',\n tags: ['Discovery'],\n responses: {\n '200': { description: 'Category list', content: { 'application/json': { schema: { $ref: '#/components/schemas/CategoriesResponse' } } } },\n },\n },\n },\n '/health': {\n get: {\n summary: 'Health check',\n description: 'Server health status including version, skill count, and uptime.',\n operationId: 'getHealth',\n tags: ['System'],\n responses: {\n '200': { description: 'Server health', content: { 'application/json': { schema: { $ref: '#/components/schemas/HealthResponse' } } } },\n },\n },\n },\n '/cache/stats': {\n get: {\n summary: 'Cache statistics',\n description: 'Cache hit/miss rates and current size.',\n operationId: 'getCacheStats',\n tags: ['System'],\n responses: {\n '200': { description: 'Cache stats', content: { 'application/json': { schema: { $ref: '#/components/schemas/CacheStatsResponse' } } } },\n },\n },\n },\n },\n components: {\n schemas: {\n Skill: {\n type: 'object',\n properties: {\n name: { type: 'string', description: 'Skill name' },\n description: { type: 'string', description: 'Skill description' },\n source: { type: 'string', description: 'Source repository (owner/repo)' },\n repo: { type: 'string', description: 'Repository URL' },\n tags: { type: 'array', items: { type: 'string' }, description: 'Skill tags' },\n category: { type: 'string', description: 'Skill category' },\n content: { type: 'string', description: 'Full SKILL.md content (when requested)' },\n stars: { type: 'integer', description: 'GitHub stars' },\n installs: { type: 'integer', description: 'Install count' },\n },\n required: ['name', 'source'],\n },\n SearchResponse: {\n type: 'object',\n properties: {\n skills: { type: 'array', items: { $ref: '#/components/schemas/Skill' } },\n total: { type: 'integer', description: 'Total matching skills' },\n query: { type: 'string', description: 'Original query' },\n limit: { type: 'integer', description: 'Applied limit' },\n },\n required: ['skills', 'total', 'query', 'limit'],\n },\n TrendingResponse: {\n type: 'object',\n properties: {\n skills: { type: 'array', items: { $ref: '#/components/schemas/Skill' } },\n limit: { type: 'integer' },\n },\n required: ['skills', 'limit'],\n },\n CategoriesResponse: {\n type: 'object',\n properties: {\n categories: { type: 'array', items: { $ref: '#/components/schemas/CategoryCount' } },\n total: { type: 'integer' },\n },\n required: ['categories', 'total'],\n },\n CategoryCount: {\n type: 'object',\n properties: {\n name: { type: 'string' },\n count: { type: 'integer' },\n },\n required: ['name', 'count'],\n },\n HealthResponse: {\n type: 'object',\n properties: {\n status: { type: 'string', enum: ['ok'] },\n version: { type: 'string' },\n skillCount: { type: 'integer' },\n uptime: { type: 'number', description: 'Uptime in seconds' },\n },\n required: ['status', 'version', 'skillCount', 'uptime'],\n },\n CacheStatsResponse: {\n type: 'object',\n properties: {\n hits: { type: 'integer' },\n misses: { type: 'integer' },\n size: { type: 'integer' },\n maxSize: { type: 'integer' },\n hitRate: { type: 'number' },\n },\n required: ['hits', 'misses', 'size', 'maxSize', 'hitRate'],\n },\n ErrorResponse: {\n type: 'object',\n properties: {\n error: { type: 'string' },\n },\n required: ['error'],\n },\n RateLimitResponse: {\n type: 'object',\n properties: {\n error: { type: 'string' },\n retryAfter: { type: 'integer', description: 'Seconds until rate limit resets' },\n },\n required: ['error', 'retryAfter'],\n },\n },\n },\n tags: [\n { name: 'Search', description: 'Skill search and filtering' },\n { name: 'Skills', description: 'Individual skill retrieval' },\n { name: 'Discovery', description: 'Trending skills and categories' },\n { name: 'System', description: 'Health checks and diagnostics' },\n ],\n};\n\nconst SWAGGER_HTML = `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>SkillKit API Documentation</title>\n <link rel=\"stylesheet\" href=\"https://unpkg.com/swagger-ui-dist@5/swagger-ui.css\">\n <style>\n body { margin: 0; background: #1a1a2e; }\n .swagger-ui .topbar { display: none; }\n .swagger-ui { max-width: 1200px; margin: 0 auto; }\n .swagger-ui .info .title { font-family: monospace; }\n </style>\n</head>\n<body>\n <div id=\"swagger-ui\"></div>\n <script src=\"https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js\"></script>\n <script>\n SwaggerUIBundle({\n url: '/openapi.json',\n dom_id: '#swagger-ui',\n deepLinking: true,\n showExtensions: true,\n showCommonExtensions: true,\n defaultModelsExpandDepth: 2,\n defaultModelExpandDepth: 2,\n docExpansion: 'list',\n filter: true,\n tryItOutEnabled: true,\n });\n </script>\n</body>\n</html>`;\n\nexport function docsRoutes() {\n const app = new Hono();\n\n app.get('/openapi.json', (c) => {\n return c.json(OPENAPI_SPEC);\n });\n\n app.get('/docs', (c) => {\n return c.html(SWAGGER_HTML);\n });\n\n app.get('/', (c) => {\n return c.json({\n name: 'SkillKit API',\n version: '1.12.0',\n docs: '/docs',\n openapi: '/openapi.json',\n endpoints: {\n search: 'GET /search?q=...',\n searchFiltered: 'POST /search',\n skill: 'GET /skills/:owner/:repo/:id',\n trending: 'GET /trending',\n categories: 'GET /categories',\n health: 'GET /health',\n cache: 'GET /cache/stats',\n },\n });\n });\n\n return app;\n}\n"],"mappings":"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","names":["Hono","Hono","Hono","Hono","RelevanceRanker","Hono","Hono","Hono"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skillkit/api",
3
- "version": "1.12.0",
3
+ "version": "1.14.0",
4
4
  "description": "REST API server for SkillKit skill discovery",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -21,7 +21,7 @@
21
21
  "hono": "^4.0.0",
22
22
  "@hono/node-server": "^1.0.0",
23
23
  "zod": "^3.24.0",
24
- "@skillkit/core": "1.12.0"
24
+ "@skillkit/core": "1.14.0"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@types/node": "^22.10.5",