mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-07 07:42:13 +03:00
Release v3.8.42 — full CHANGELOG in CHANGELOG.md. CI: 103 checks green incl. CodeQL (all languages), Semgrep, all 8 unit shards, coverage, Node 24 compat, and integration tests. Full unit suite validated locally: 19437 pass / 0 fail. The 3 red checks are advisory and do not gate main (no required status checks): SonarCloud/SonarQube new-code coverage gate, and PR Test Policy (test-masking detector flagging the legitimate dead-Phind provider removal in #5530 — reviewed, correct). Includes cycle-close reconciliation + repair of inherited base-red tests from #5480/#5527/#5427/#5521 that the PR->release fast-path did not exercise.
74 lines
2.3 KiB
TypeScript
74 lines
2.3 KiB
TypeScript
import { z } from "zod";
|
|
|
|
// ─── skills.sh API response schemas ───
|
|
|
|
export const SkillsShSkillSchema = z.object({
|
|
id: z.string(),
|
|
skillId: z.string(),
|
|
name: z.string(),
|
|
installs: z.number().optional().default(0),
|
|
source: z.string(),
|
|
});
|
|
|
|
export const SkillsShSearchResponseSchema = z.object({
|
|
query: z.string().optional(),
|
|
searchType: z.string().optional(),
|
|
skills: z.array(SkillsShSkillSchema).default([]),
|
|
count: z.number().optional(),
|
|
duration_ms: z.number().optional(),
|
|
});
|
|
|
|
export type SkillsShSearchResponse = z.infer<typeof SkillsShSearchResponseSchema>;
|
|
|
|
const SKILLSSH_BASE_URL = "https://skills.sh/api";
|
|
const GITHUB_RAW_BASE = "https://raw.githubusercontent.com";
|
|
const DEFAULT_SEARCH_LIMIT = 20;
|
|
const REQUEST_TIMEOUT_MS = 15_000;
|
|
|
|
/**
|
|
* Search the skills.sh public directory.
|
|
* No authentication required.
|
|
*/
|
|
export async function searchSkillsSh(
|
|
query: string,
|
|
limit: number = DEFAULT_SEARCH_LIMIT
|
|
): Promise<SkillsShSearchResponse> {
|
|
const url = `${SKILLSSH_BASE_URL}/search?q=${encodeURIComponent(query)}&limit=${limit}`;
|
|
const controller = new AbortController();
|
|
const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
|
|
try {
|
|
const res = await fetch(url, { signal: controller.signal });
|
|
if (!res.ok) {
|
|
const body = await res.text();
|
|
throw new Error(`skills.sh API error: ${res.status} ${body}`);
|
|
}
|
|
const data = await res.json();
|
|
return SkillsShSearchResponseSchema.parse(data);
|
|
} finally {
|
|
clearTimeout(timeout);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fetch SKILL.md content from GitHub for a skills.sh skill.
|
|
*
|
|
* @param source - GitHub "owner/repo" (e.g. "supabase/agent-skills")
|
|
* @param skillId - Skill name (last segment of the full id, e.g. "supabase-postgres-best-practices")
|
|
*/
|
|
export async function fetchSkillMd(source: string, skillId: string): Promise<string> {
|
|
const url = `${GITHUB_RAW_BASE}/${source}/main/skills/${skillId}/SKILL.md`;
|
|
const controller = new AbortController();
|
|
const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
|
|
try {
|
|
const res = await fetch(url, { signal: controller.signal });
|
|
if (!res.ok) {
|
|
throw new Error(`Failed to fetch SKILL.md: ${res.status} (${url})`);
|
|
}
|
|
return await res.text();
|
|
} finally {
|
|
clearTimeout(timeout);
|
|
}
|
|
}
|