summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorKit Langton <[email protected]>2026-04-16 16:59:30 -0400
committerGitHub <[email protected]>2026-04-16 16:59:30 -0400
commit0e86466f990edd046867820b9fac97766d11db3f (patch)
treed03d2e4cd4f381ebac6ee8515b7b589dfc45881d
parent32548bcb4af7db393d91f315ec2222954326e766 (diff)
downloadopencode-0e86466f990edd046867820b9fac97766d11db3f.tar.gz
opencode-0e86466f990edd046867820b9fac97766d11db3f.zip
refactor: unwrap Discovery namespace to flat exports + self-reexport (#22878)
-rw-r--r--packages/opencode/src/skill/discovery.ts206
1 files changed, 103 insertions, 103 deletions
diff --git a/packages/opencode/src/skill/discovery.ts b/packages/opencode/src/skill/discovery.ts
index eff64ed2b..debd68dd3 100644
--- a/packages/opencode/src/skill/discovery.ts
+++ b/packages/opencode/src/skill/discovery.ts
@@ -6,111 +6,111 @@ import { AppFileSystem } from "@opencode-ai/shared/filesystem"
import { Global } from "../global"
import { Log } from "../util"
-export namespace Discovery {
- const skillConcurrency = 4
- const fileConcurrency = 8
-
- class IndexSkill extends Schema.Class<IndexSkill>("IndexSkill")({
- name: Schema.String,
- files: Schema.Array(Schema.String),
- }) {}
-
- class Index extends Schema.Class<Index>("Index")({
- skills: Schema.Array(IndexSkill),
- }) {}
-
- export interface Interface {
- readonly pull: (url: string) => Effect.Effect<string[]>
- }
-
- export class Service extends Context.Service<Service, Interface>()("@opencode/SkillDiscovery") {}
-
- export const layer: Layer.Layer<Service, never, AppFileSystem.Service | Path.Path | HttpClient.HttpClient> =
- Layer.effect(
- Service,
- Effect.gen(function* () {
- const log = Log.create({ service: "skill-discovery" })
- const fs = yield* AppFileSystem.Service
- const path = yield* Path.Path
- const http = HttpClient.filterStatusOk(withTransientReadRetry(yield* HttpClient.HttpClient))
- const cache = path.join(Global.Path.cache, "skills")
-
- const download = Effect.fn("Discovery.download")(function* (url: string, dest: string) {
- if (yield* fs.exists(dest).pipe(Effect.orDie)) return true
-
- return yield* HttpClientRequest.get(url).pipe(
- http.execute,
- Effect.flatMap((res) => res.arrayBuffer),
- Effect.flatMap((body) => fs.writeWithDirs(dest, new Uint8Array(body))),
- Effect.as(true),
- Effect.catch((err) =>
- Effect.sync(() => {
- log.error("failed to download", { url, err })
- return false
- }),
- ),
- )
- })
+const skillConcurrency = 4
+const fileConcurrency = 8
+
+class IndexSkill extends Schema.Class<IndexSkill>("IndexSkill")({
+ name: Schema.String,
+ files: Schema.Array(Schema.String),
+}) {}
+
+class Index extends Schema.Class<Index>("Index")({
+ skills: Schema.Array(IndexSkill),
+}) {}
+
+export interface Interface {
+ readonly pull: (url: string) => Effect.Effect<string[]>
+}
- const pull = Effect.fn("Discovery.pull")(function* (url: string) {
- const base = url.endsWith("/") ? url : `${url}/`
- const index = new URL("index.json", base).href
- const host = base.slice(0, -1)
-
- log.info("fetching index", { url: index })
-
- const data = yield* HttpClientRequest.get(index).pipe(
- HttpClientRequest.acceptJson,
- http.execute,
- Effect.flatMap(HttpClientResponse.schemaBodyJson(Index)),
- Effect.catch((err) =>
- Effect.sync(() => {
- log.error("failed to fetch index", { url: index, err })
- return null
- }),
- ),
- )
-
- if (!data) return []
-
- const list = data.skills.filter((skill) => {
- if (!skill.files.includes("SKILL.md")) {
- log.warn("skill entry missing SKILL.md", { url: index, skill: skill.name })
+export class Service extends Context.Service<Service, Interface>()("@opencode/SkillDiscovery") {}
+
+export const layer: Layer.Layer<Service, never, AppFileSystem.Service | Path.Path | HttpClient.HttpClient> =
+ Layer.effect(
+ Service,
+ Effect.gen(function* () {
+ const log = Log.create({ service: "skill-discovery" })
+ const fs = yield* AppFileSystem.Service
+ const path = yield* Path.Path
+ const http = HttpClient.filterStatusOk(withTransientReadRetry(yield* HttpClient.HttpClient))
+ const cache = path.join(Global.Path.cache, "skills")
+
+ const download = Effect.fn("Discovery.download")(function* (url: string, dest: string) {
+ if (yield* fs.exists(dest).pipe(Effect.orDie)) return true
+
+ return yield* HttpClientRequest.get(url).pipe(
+ http.execute,
+ Effect.flatMap((res) => res.arrayBuffer),
+ Effect.flatMap((body) => fs.writeWithDirs(dest, new Uint8Array(body))),
+ Effect.as(true),
+ Effect.catch((err) =>
+ Effect.sync(() => {
+ log.error("failed to download", { url, err })
return false
- }
- return true
- })
-
- const dirs = yield* Effect.forEach(
- list,
- (skill) =>
- Effect.gen(function* () {
- const root = path.join(cache, skill.name)
-
- yield* Effect.forEach(
- skill.files,
- (file) => download(new URL(file, `${host}/${skill.name}/`).href, path.join(root, file)),
- {
- concurrency: fileConcurrency,
- },
- )
-
- const md = path.join(root, "SKILL.md")
- return (yield* fs.exists(md).pipe(Effect.orDie)) ? root : null
- }),
- { concurrency: skillConcurrency },
- )
-
- return dirs.filter((dir): dir is string => dir !== null)
+ }),
+ ),
+ )
+ })
+
+ const pull = Effect.fn("Discovery.pull")(function* (url: string) {
+ const base = url.endsWith("/") ? url : `${url}/`
+ const index = new URL("index.json", base).href
+ const host = base.slice(0, -1)
+
+ log.info("fetching index", { url: index })
+
+ const data = yield* HttpClientRequest.get(index).pipe(
+ HttpClientRequest.acceptJson,
+ http.execute,
+ Effect.flatMap(HttpClientResponse.schemaBodyJson(Index)),
+ Effect.catch((err) =>
+ Effect.sync(() => {
+ log.error("failed to fetch index", { url: index, err })
+ return null
+ }),
+ ),
+ )
+
+ if (!data) return []
+
+ const list = data.skills.filter((skill) => {
+ if (!skill.files.includes("SKILL.md")) {
+ log.warn("skill entry missing SKILL.md", { url: index, skill: skill.name })
+ return false
+ }
+ return true
})
- return Service.of({ pull })
- }),
- )
-
- export const defaultLayer: Layer.Layer<Service> = layer.pipe(
- Layer.provide(FetchHttpClient.layer),
- Layer.provide(AppFileSystem.defaultLayer),
- Layer.provide(NodePath.layer),
+ const dirs = yield* Effect.forEach(
+ list,
+ (skill) =>
+ Effect.gen(function* () {
+ const root = path.join(cache, skill.name)
+
+ yield* Effect.forEach(
+ skill.files,
+ (file) => download(new URL(file, `${host}/${skill.name}/`).href, path.join(root, file)),
+ {
+ concurrency: fileConcurrency,
+ },
+ )
+
+ const md = path.join(root, "SKILL.md")
+ return (yield* fs.exists(md).pipe(Effect.orDie)) ? root : null
+ }),
+ { concurrency: skillConcurrency },
+ )
+
+ return dirs.filter((dir): dir is string => dir !== null)
+ })
+
+ return Service.of({ pull })
+ }),
)
-}
+
+export const defaultLayer: Layer.Layer<Service> = layer.pipe(
+ Layer.provide(FetchHttpClient.layer),
+ Layer.provide(AppFileSystem.defaultLayer),
+ Layer.provide(NodePath.layer),
+)
+
+export * as Discovery from "./discovery"