| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- import path from "path"
- import { mkdir } from "fs/promises"
- import { Log } from "../util/log"
- import { Global } from "../global"
- export namespace Discovery {
- const log = Log.create({ service: "skill-discovery" })
- type Index = {
- skills: Array<{
- name: string
- description: string
- files: string[]
- }>
- }
- export function dir() {
- return path.join(Global.Path.cache, "skills")
- }
- async function get(url: string, dest: string): Promise<boolean> {
- if (await Bun.file(dest).exists()) return true
- return fetch(url)
- .then(async (response) => {
- if (!response.ok) {
- log.error("failed to download", { url, status: response.status })
- return false
- }
- await Bun.write(dest, await response.text())
- return true
- })
- .catch((err) => {
- log.error("failed to download", { url, err })
- return false
- })
- }
- export async function pull(url: string): Promise<string[]> {
- const result: string[] = []
- const base = url.endsWith("/") ? url : `${url}/`
- const index = new URL("index.json", base).href
- const cache = dir()
- const host = base.slice(0, -1)
- log.info("fetching index", { url: index })
- const data = await fetch(index)
- .then(async (response) => {
- if (!response.ok) {
- log.error("failed to fetch index", { url: index, status: response.status })
- return undefined
- }
- return response
- .json()
- .then((json) => json as Index)
- .catch((err) => {
- log.error("failed to parse index", { url: index, err })
- return undefined
- })
- })
- .catch((err) => {
- log.error("failed to fetch index", { url: index, err })
- return undefined
- })
- if (!data?.skills || !Array.isArray(data.skills)) {
- log.warn("invalid index format", { url: index })
- return result
- }
- const list = data.skills.filter((skill) => {
- if (!skill?.name || !Array.isArray(skill.files)) {
- log.warn("invalid skill entry", { url: index, skill })
- return false
- }
- return true
- })
- await Promise.all(
- list.map(async (skill) => {
- const root = path.join(cache, skill.name)
- await Promise.all(
- skill.files.map(async (file) => {
- const link = new URL(file, `${host}/${skill.name}/`).href
- const dest = path.join(root, file)
- await mkdir(path.dirname(dest), { recursive: true })
- await get(link, dest)
- }),
- )
- const md = path.join(root, "SKILL.md")
- if (await Bun.file(md).exists()) result.push(root)
- }),
- )
- return result
- }
- }
|