@michaelfromyeg/loom-adapter-opencode 0.1.0 → 0.2.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
@@ -16,11 +16,11 @@ function readJson(path) {
16
16
  }
17
17
  }
18
18
  function subdirsWith(dir, marker) {
19
- if (!existsSync(dir) || !statSync(dir).isDirectory()) return [];
19
+ if (!(existsSync(dir) && statSync(dir).isDirectory())) return [];
20
20
  return readdirSync(dir).filter((n) => statSync(join(dir, n)).isDirectory() && existsSync(join(dir, n, marker))).sort();
21
21
  }
22
22
  function filesWithExt(dir, ext) {
23
- if (!existsSync(dir) || !statSync(dir).isDirectory()) return [];
23
+ if (!(existsSync(dir) && statSync(dir).isDirectory())) return [];
24
24
  return readdirSync(dir).filter((n) => n.endsWith(ext) && statSync(join(dir, n)).isFile()).sort();
25
25
  }
26
26
  function copyTree(srcDir, destPrefix, kind) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/import.ts","../src/mcp.ts","../src/index.ts"],"names":["config","json","basename","artifact","join"],"mappings":"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","file":"index.js","sourcesContent":["import { existsSync, readdirSync, readFileSync, statSync } from \"node:fs\";\nimport { basename, join, relative } from \"node:path\";\nimport {\n artifact,\n type CompiledArtifact,\n type ImportedMarketplace,\n type ImportedPlugin,\n type ImportOptions,\n type ImportResult,\n} from \"@michaelfromyeg/loom-adapter-kit\";\nimport type { Component, Marketplace, Plugin } from \"@michaelfromyeg/loom-schema\";\nimport type { OpencodeMcpServer } from \"./mcp\";\n\nconst MCP_SCHEMA = \"https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json\";\nconst json = (o: unknown): string => `${JSON.stringify(o, null, 2)}\\n`;\n\nfunction readJson(path: string): Record<string, unknown> | null {\n try {\n return JSON.parse(readFileSync(path, \"utf8\"));\n } catch {\n return null;\n }\n}\n\n/** Subdirectories of `dir` that contain `marker`. */\nfunction subdirsWith(dir: string, marker: string): string[] {\n if (!existsSync(dir) || !statSync(dir).isDirectory()) return [];\n return readdirSync(dir)\n .filter((n) => statSync(join(dir, n)).isDirectory() && existsSync(join(dir, n, marker)))\n .sort();\n}\n\nfunction filesWithExt(dir: string, ext: string): string[] {\n if (!existsSync(dir) || !statSync(dir).isDirectory()) return [];\n return readdirSync(dir)\n .filter((n) => n.endsWith(ext) && statSync(join(dir, n)).isFile())\n .sort();\n}\n\nfunction copyTree(\n srcDir: string,\n destPrefix: string,\n kind: CompiledArtifact[\"kind\"],\n): CompiledArtifact[] {\n const out: CompiledArtifact[] = [];\n const walk = (d: string) => {\n for (const n of readdirSync(d).sort()) {\n const abs = join(d, n);\n if (statSync(abs).isDirectory()) walk(abs);\n else\n out.push(artifact(`${destPrefix}/${relative(srcDir, abs)}`, readFileSync(abs), { kind }));\n }\n };\n walk(srcDir);\n return out;\n}\n\n/** A Loom source string from a Loom-marketplace `source` (string or object). */\nfunction sourceToString(source: unknown): string {\n if (typeof source === \"string\") return source;\n const s = source as Record<string, unknown>;\n switch (s?.source) {\n case \"github\":\n return `github:${s.repo}${s.ref ? `#${s.ref}` : \"\"}`;\n case \"url\":\n case \"git-subdir\":\n return String(s.url);\n case \"npm\":\n return `npm:${s.package}${s.version ? `@${s.version}` : \"\"}`;\n default:\n return String(source);\n }\n}\n\n/**\n * Reconstruct an MCP-standard server.json from OpenCode's runnable `mcp` entry\n * (lossy but functional). OpenCode's local `command` is a STRING ARRAY (argv)\n * and the env key is `environment`, not `env`.\n */\nfunction synthesizeServerJson(namespace: string, name: string, cfg: OpencodeMcpServer): unknown {\n const base = {\n $schema: MCP_SCHEMA,\n name: `${namespace}/${name}`,\n description: `Imported ${name} MCP server.`,\n version: \"0.0.0\",\n };\n if (cfg.type === \"remote\") {\n const headers = cfg.headers\n ? Object.entries(cfg.headers).map(([n, value]) => ({ name: n, value }))\n : undefined;\n return {\n ...base,\n remotes: [{ type: \"streamable-http\", url: cfg.url, ...(headers?.length ? { headers } : {}) }],\n };\n }\n const command = cfg.command ?? [];\n // npm-style: [\"npx\",\"-y\",\"<ident>\"] -> npm package (parse the ident after -y).\n if (command[0] === \"npx\") {\n const ident = command.slice(1).find((a) => a !== \"-y\" && !a.startsWith(\"-\"));\n if (ident) {\n const at = ident.lastIndexOf(\"@\");\n const id = at > 0 ? ident.slice(0, at) : ident;\n const version = at > 0 ? ident.slice(at + 1) : undefined;\n return {\n ...base,\n packages: [\n {\n registryType: \"npm\",\n identifier: id,\n ...(version ? { version } : {}),\n transport: { type: \"stdio\" },\n },\n ],\n };\n }\n }\n // Bare command: first element is the executable, the rest are args.\n return {\n ...base,\n ...(command.length ? { command: command[0], args: command.slice(1) } : {}),\n ...(cfg.environment ? { env: cfg.environment } : {}),\n };\n}\n\nfunction importPlugin(dir: string, namespace: string): ImportedPlugin {\n const components: Component[] = [];\n const files: CompiledArtifact[] = [];\n\n for (const sk of subdirsWith(join(dir, \"skills\"), \"SKILL.md\")) {\n components.push({ skill: `skills/${sk}` });\n files.push(...copyTree(join(dir, \"skills\", sk), `skills/${sk}`, \"skill\"));\n }\n for (const f of filesWithExt(join(dir, \"agents\"), \".md\")) {\n components.push({ agent: `agents/${f}` });\n files.push(artifact(`agents/${f}`, readFileSync(join(dir, \"agents\", f)), { kind: \"agent\" }));\n }\n for (const f of filesWithExt(join(dir, \"commands\"), \".md\")) {\n components.push({ command: `commands/${f}` });\n files.push(\n artifact(`commands/${f}`, readFileSync(join(dir, \"commands\", f)), { kind: \"command\" }),\n );\n }\n\n // Prefer verbatim mcp/<leaf>/server.json copies the adapter wrote; only if there\n // is NO mcp/ dir do we reconstruct server.json from opencode.json's mcp block.\n const mcpDir = join(dir, \"mcp\");\n const verbatim = subdirsWith(mcpDir, \"server.json\");\n if (verbatim.length > 0) {\n for (const leaf of verbatim) {\n components.push({ mcp: `mcp/${leaf}` });\n files.push(\n artifact(`mcp/${leaf}/server.json`, readFileSync(join(mcpDir, leaf, \"server.json\")), {\n kind: \"mcp\",\n }),\n );\n }\n } else {\n const config = readJson(join(dir, \"opencode.json\"));\n const servers = (config?.mcp as Record<string, OpencodeMcpServer> | undefined) ?? {};\n for (const [serverName, cfg] of Object.entries(servers)) {\n components.push({ mcp: `mcp/${serverName}` });\n files.push(\n artifact(\n `mcp/${serverName}/server.json`,\n json(synthesizeServerJson(namespace, serverName, cfg)),\n { kind: \"mcp\" },\n ),\n );\n }\n }\n\n // OpenCode has no plugin manifest; the name is the directory basename, with the\n // opencode.json \"name\" (if any) preferred.\n const config = readJson(join(dir, \"opencode.json\"));\n const name = config?.name ? String(config.name) : basename(dir);\n const plugin: Plugin = {\n name,\n version: \"0.1.0\",\n owner: { name, namespace },\n components,\n };\n return { kind: \"plugin\", plugin, files };\n}\n\nfunction importMarketplace(\n manifest: Record<string, unknown>,\n namespace: string,\n): ImportedMarketplace {\n const owner = manifest.owner as { name?: string; email?: string } | undefined;\n const plugins = ((manifest.plugins as Array<Record<string, unknown>>) ?? []).map((p) => ({\n plugin: sourceToString(p.source),\n ...(p.version ? { version: String(p.version) } : {}),\n ...(p.category ? { category: String(p.category) } : {}),\n ...(Array.isArray(p.tags) ? { tags: p.tags as string[] } : {}),\n }));\n const marketplace: Marketplace = {\n name: String(manifest.name),\n owner: {\n name: owner?.name ?? String(manifest.name),\n namespace,\n ...(owner?.email ? { email: owner.email } : {}),\n },\n ...(manifest.description ? { description: String(manifest.description) } : {}),\n plugins,\n };\n return { kind: \"marketplace\", marketplace };\n}\n\n/** Reverse-compile an OpenCode plugin or Loom-marketplace dir into the Loom model. */\nexport function importOpencode(dir: string, opts?: ImportOptions): ImportResult | null {\n const namespace = opts?.namespace ?? \"com.imported\";\n\n // OpenCode has no native marketplace; the adapter emits a Loom-only catalog.\n const marketplace = readJson(join(dir, \"loom-marketplace.json\"));\n if (marketplace) return importMarketplace(marketplace, namespace);\n\n // Directory convention: any plural component dir makes this an importable plugin.\n if (\n existsSync(join(dir, \"skills\")) ||\n existsSync(join(dir, \"agents\")) ||\n existsSync(join(dir, \"commands\")) ||\n existsSync(join(dir, \"mcp\")) ||\n existsSync(join(dir, \"opencode.json\"))\n ) {\n return importPlugin(dir, namespace);\n }\n return null;\n}\n","/**\n * Derives a runnable OpenCode `mcp` entry from an MCP-standard `server.json`\n * (the registry's ServerJSON shape: packages[] / remotes[] / a bare command).\n * Stored standards stay verbatim in the plugin; this is the tool-specific view.\n *\n * OpenCode's mcp shape differs from most harnesses (see docs/harness-research.md):\n * local -> { type: \"local\", command: [ ...string ARRAY... ], environment: {…}, enabled: true }\n * remote -> { type: \"remote\", url, headers: {…}, enabled: true }\n * Note the local invocation is a single `command` STRING ARRAY (argv) and the\n * env key is `environment`, NOT `env`.\n */\n\nexport interface OpencodeLocalServer {\n type: \"local\";\n command: string[];\n environment?: Record<string, string>;\n enabled: boolean;\n}\nexport interface OpencodeRemoteServer {\n type: \"remote\";\n url: string;\n headers?: Record<string, string>;\n enabled: boolean;\n}\nexport type OpencodeMcpServer = OpencodeLocalServer | OpencodeRemoteServer;\n\ninterface McpPackage {\n registryType?: string;\n identifier?: string;\n version?: string;\n transport?: { type?: string };\n}\ninterface McpRemote {\n type?: string;\n url?: string;\n headers?: Array<{ name: string; value: string }>;\n}\ninterface ServerJson {\n name?: string;\n packages?: McpPackage[];\n remotes?: McpRemote[];\n command?: string;\n args?: string[];\n env?: Record<string, string>;\n}\n\n/** The short server key OpenCode uses (the part after the reverse-DNS namespace). */\nexport function mcpServerName(server: ServerJson): string {\n const raw = server.name ?? \"server\";\n const afterSlash = raw.includes(\"/\") ? raw.slice(raw.lastIndexOf(\"/\") + 1) : raw;\n return afterSlash || \"server\";\n}\n\n// TODO(verify): the research doc only documents npx/local examples for OpenCode's\n// command array. pypi/oci runner choice (uvx/docker) is a best-effort mirror of\n// the other adapters and not confirmed against OpenCode docs.\nconst RUNNERS: Record<string, string> = { npm: \"npx\", pypi: \"uvx\" };\n\nexport function mcpRunConfig(server: ServerJson): OpencodeMcpServer {\n const pkg = server.packages?.[0];\n if (pkg?.identifier) {\n if (pkg.registryType === \"oci\") {\n return {\n type: \"local\",\n command: [\"docker\", \"run\", \"-i\", \"--rm\", pkg.identifier],\n enabled: true,\n };\n }\n const runner = RUNNERS[pkg.registryType ?? \"npm\"] ?? \"npx\";\n const ident = pkg.version ? `${pkg.identifier}@${pkg.version}` : pkg.identifier;\n const command = runner === \"npx\" ? [\"npx\", \"-y\", ident] : [runner, ident];\n return { type: \"local\", command, enabled: true };\n }\n\n const remote = server.remotes?.[0];\n if (remote?.url) {\n const config: OpencodeRemoteServer = { type: \"remote\", url: remote.url, enabled: true };\n if (remote.headers?.length) {\n config.headers = Object.fromEntries(remote.headers.map((h) => [h.name, h.value]));\n }\n return config;\n }\n\n if (server.command) {\n const config: OpencodeLocalServer = {\n type: \"local\",\n command: [server.command, ...(server.args ?? [])],\n enabled: true,\n };\n if (server.env) config.environment = server.env;\n return config;\n }\n\n return {\n type: \"local\",\n command: [\"echo\", \"server.json declares no runnable transport\"],\n enabled: true,\n };\n}\n","import { homedir } from \"node:os\";\nimport { basename, extname, join } from \"node:path\";\nimport {\n artifact,\n type CompiledArtifact,\n type HarnessAdapter,\n type InstallPaths,\n type PluginCtx,\n type ResolvedMarketplace,\n} from \"@michaelfromyeg/loom-adapter-kit\";\nimport {\n type Component,\n kindOf,\n leafNameOf,\n type Plugin,\n refOf,\n type Scope,\n} from \"@michaelfromyeg/loom-schema\";\nimport { importOpencode } from \"./import\";\nimport { mcpRunConfig, mcpServerName, type OpencodeMcpServer } from \"./mcp\";\n\n/** Bump on any change to OpenCode's directory-convention / opencode.json shape (spec §5). */\nconst TARGET_SCHEMA = \"opencode/1\";\n\ninterface OpencodeManifest {\n mcp: Record<string, OpencodeMcpServer>;\n}\ninterface LoomMarketplacePlugin {\n name: string;\n source: string;\n description?: string;\n version?: string;\n category?: string;\n tags?: string[];\n}\ninterface LoomMarketplace {\n name: string;\n owner: { name: string; namespace: string; email?: string };\n description?: string;\n plugins: LoomMarketplacePlugin[];\n}\n\nconst json = (o: unknown): string => `${JSON.stringify(o, null, 2)}\\n`;\n\n/** Copy every file under a plugin dir into `destPrefix/`, preserving structure. */\nfunction copyDir(\n ctx: PluginCtx,\n ref: string,\n destPrefix: string,\n kind: CompiledArtifact[\"kind\"],\n): CompiledArtifact[] {\n return ctx.list(ref).map((file) => {\n const within = file.startsWith(`${ref}/`) ? file.slice(ref.length + 1) : basename(file);\n return artifact(`${destPrefix}/${within}`, ctx.read(file), { kind });\n });\n}\n\n/**\n * Place a component that may be a single Markdown file or a directory. OpenCode\n * wants agents/commands as a flat `<leaf>.md`; a bare-file source falls back to\n * `.md`, while a directory source is copied verbatim under `destPrefix/`.\n */\nfunction copyFileOrDir(\n ctx: PluginCtx,\n ref: string,\n destPrefix: string,\n kind: CompiledArtifact[\"kind\"],\n): CompiledArtifact[] {\n const files = ctx.list(ref);\n if (files.length === 0) {\n // ref is a single file (e.g. agents/code-review.md).\n return [artifact(`${destPrefix}${extname(ref) || \".md\"}`, ctx.read(ref), { kind })];\n }\n return copyDir(ctx, ref, destPrefix, kind);\n}\n\nexport const opencodeAdapter: HarnessAdapter = {\n target: \"opencode\",\n version: \"0.1.0\",\n targetSchema: TARGET_SCHEMA,\n\n detect(scope: Scope, cwd: string): InstallPaths {\n // User config lives under XDG `~/.config/opencode`; project under `<cwd>/.opencode`.\n const root = scope === \"user\" ? join(homedir(), \".config\", \"opencode\") : join(cwd, \".opencode\");\n return {\n root,\n // Executable plugins (.ts) live in plugins/; that is also where passthrough lands.\n plugins: join(root, \"plugins\"),\n skills: join(root, \"skills\"),\n // opencode.json (with the mcp block) lives at the config root.\n mcp: root,\n agents: join(root, \"agents\"),\n commands: join(root, \"commands\"),\n hooks: join(root, \"plugins\"),\n catalog: root,\n };\n },\n\n transform(component: Component, ctx: PluginCtx): CompiledArtifact[] {\n const ref = refOf(component);\n const leaf = leafNameOf(component);\n switch (kindOf(component)) {\n case \"skill\":\n return copyDir(ctx, ref, `skills/${leaf}`, \"skill\");\n case \"agent\":\n return copyFileOrDir(ctx, ref, `agents/${leaf}`, \"agent\");\n case \"command\":\n return copyFileOrDir(ctx, ref, `commands/${leaf}`, \"command\");\n case \"hook\":\n // OpenCode has no standalone hooks dir; hooks are executable plugins.\n return [\n artifact(`plugins/${basename(ref)}`, ctx.read(ref), { kind: \"hook\", executable: true }),\n ];\n case \"mcp\":\n // Verbatim provenance copy; the runnable config goes into opencode.json's mcp block.\n return copyDir(ctx, ref, `mcp/${leaf}`, \"mcp\");\n case \"passthrough\":\n // Executable plugins/scripts land in plugins/, placed DISABLED (spec §11).\n return [\n artifact(`plugins/${basename(ref)}`, ctx.read(ref), { kind: \"hook\", executable: true }),\n ];\n default:\n return [];\n }\n },\n\n emitManifest(plugin: Plugin, ctx: PluginCtx): CompiledArtifact[] {\n // OpenCode has NO central plugin manifest. The only thing to emit is the\n // aggregated `mcp` block; on install this block is MERGED into the user's\n // existing opencode.json rather than replacing it.\n const mcp: Record<string, OpencodeMcpServer> = {};\n for (const c of plugin.components) {\n if (kindOf(c) !== \"mcp\") continue;\n try {\n const server = JSON.parse(ctx.read(`${refOf(c)}/server.json`).toString(\"utf8\"));\n mcp[mcpServerName(server)] = mcpRunConfig(server);\n } catch {\n // validate.ts already surfaced an error for an unparsable server.json.\n }\n }\n if (Object.keys(mcp).length === 0) return [];\n\n const manifest: OpencodeManifest = { mcp };\n return [artifact(\"opencode.json\", json(manifest), { kind: \"manifest\" })];\n },\n\n emitCatalog(marketplace: ResolvedMarketplace): CompiledArtifact[] {\n // OpenCode reads no marketplace catalog -- do NOT synthesize a manifest it\n // ignores. Emit a Loom-only index so the build output is inspectable; OpenCode\n // does not consume this file.\n const plugins: LoomMarketplacePlugin[] = marketplace.entries.map((entry) => {\n const entryPlugin: LoomMarketplacePlugin = {\n name: entry.name,\n source: entry.source.startsWith(\"./\") ? entry.source : `./${entry.source}`,\n };\n if (entry.description) entryPlugin.description = entry.description;\n if (entry.version) entryPlugin.version = entry.version;\n if (entry.category) entryPlugin.category = entry.category;\n if (entry.tags) entryPlugin.tags = entry.tags;\n return entryPlugin;\n });\n\n const catalog: LoomMarketplace = {\n name: marketplace.name,\n owner: marketplace.owner,\n plugins,\n };\n if (marketplace.description) catalog.description = marketplace.description;\n\n return [artifact(\"loom-marketplace.json\", json(catalog), { kind: \"catalog\" })];\n },\n\n importNative: importOpencode,\n};\n\nexport default opencodeAdapter;\n"]}
1
+ {"version":3,"sources":["../src/import.ts","../src/mcp.ts","../src/index.ts"],"names":["config","json","basename","artifact","join"],"mappings":"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","file":"index.js","sourcesContent":["import { existsSync, readdirSync, readFileSync, statSync } from \"node:fs\";\nimport { basename, join, relative } from \"node:path\";\nimport {\n artifact,\n type CompiledArtifact,\n type ImportedMarketplace,\n type ImportedPlugin,\n type ImportOptions,\n type ImportResult,\n} from \"@michaelfromyeg/loom-adapter-kit\";\nimport type { Component, Marketplace, Plugin } from \"@michaelfromyeg/loom-schema\";\nimport type { OpencodeMcpServer } from \"./mcp\";\n\nconst MCP_SCHEMA = \"https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json\";\nconst json = (o: unknown): string => `${JSON.stringify(o, null, 2)}\\n`;\n\nfunction readJson(path: string): Record<string, unknown> | null {\n try {\n return JSON.parse(readFileSync(path, \"utf8\"));\n } catch {\n return null;\n }\n}\n\n/** Subdirectories of `dir` that contain `marker`. */\nfunction subdirsWith(dir: string, marker: string): string[] {\n if (!(existsSync(dir) && statSync(dir).isDirectory())) return [];\n return readdirSync(dir)\n .filter((n) => statSync(join(dir, n)).isDirectory() && existsSync(join(dir, n, marker)))\n .sort();\n}\n\nfunction filesWithExt(dir: string, ext: string): string[] {\n if (!(existsSync(dir) && statSync(dir).isDirectory())) return [];\n return readdirSync(dir)\n .filter((n) => n.endsWith(ext) && statSync(join(dir, n)).isFile())\n .sort();\n}\n\nfunction copyTree(\n srcDir: string,\n destPrefix: string,\n kind: CompiledArtifact[\"kind\"],\n): CompiledArtifact[] {\n const out: CompiledArtifact[] = [];\n const walk = (d: string) => {\n for (const n of readdirSync(d).sort()) {\n const abs = join(d, n);\n if (statSync(abs).isDirectory()) walk(abs);\n else\n out.push(artifact(`${destPrefix}/${relative(srcDir, abs)}`, readFileSync(abs), { kind }));\n }\n };\n walk(srcDir);\n return out;\n}\n\n/** A Loom source string from a Loom-marketplace `source` (string or object). */\nfunction sourceToString(source: unknown): string {\n if (typeof source === \"string\") return source;\n const s = source as Record<string, unknown>;\n switch (s?.source) {\n case \"github\":\n return `github:${s.repo}${s.ref ? `#${s.ref}` : \"\"}`;\n case \"url\":\n case \"git-subdir\":\n return String(s.url);\n case \"npm\":\n return `npm:${s.package}${s.version ? `@${s.version}` : \"\"}`;\n default:\n return String(source);\n }\n}\n\n/**\n * Reconstruct an MCP-standard server.json from OpenCode's runnable `mcp` entry\n * (lossy but functional). OpenCode's local `command` is a STRING ARRAY (argv)\n * and the env key is `environment`, not `env`.\n */\nfunction synthesizeServerJson(namespace: string, name: string, cfg: OpencodeMcpServer): unknown {\n const base = {\n $schema: MCP_SCHEMA,\n name: `${namespace}/${name}`,\n description: `Imported ${name} MCP server.`,\n version: \"0.0.0\",\n };\n if (cfg.type === \"remote\") {\n const headers = cfg.headers\n ? Object.entries(cfg.headers).map(([n, value]) => ({ name: n, value }))\n : undefined;\n return {\n ...base,\n remotes: [{ type: \"streamable-http\", url: cfg.url, ...(headers?.length ? { headers } : {}) }],\n };\n }\n const command = cfg.command ?? [];\n // npm-style: [\"npx\",\"-y\",\"<ident>\"] -> npm package (parse the ident after -y).\n if (command[0] === \"npx\") {\n const ident = command.slice(1).find((a) => a !== \"-y\" && !a.startsWith(\"-\"));\n if (ident) {\n const at = ident.lastIndexOf(\"@\");\n const id = at > 0 ? ident.slice(0, at) : ident;\n const version = at > 0 ? ident.slice(at + 1) : undefined;\n return {\n ...base,\n packages: [\n {\n registryType: \"npm\",\n identifier: id,\n ...(version ? { version } : {}),\n transport: { type: \"stdio\" },\n },\n ],\n };\n }\n }\n // Bare command: first element is the executable, the rest are args.\n return {\n ...base,\n ...(command.length ? { command: command[0], args: command.slice(1) } : {}),\n ...(cfg.environment ? { env: cfg.environment } : {}),\n };\n}\n\nfunction importPlugin(dir: string, namespace: string): ImportedPlugin {\n const components: Component[] = [];\n const files: CompiledArtifact[] = [];\n\n for (const sk of subdirsWith(join(dir, \"skills\"), \"SKILL.md\")) {\n components.push({ skill: `skills/${sk}` });\n files.push(...copyTree(join(dir, \"skills\", sk), `skills/${sk}`, \"skill\"));\n }\n for (const f of filesWithExt(join(dir, \"agents\"), \".md\")) {\n components.push({ agent: `agents/${f}` });\n files.push(artifact(`agents/${f}`, readFileSync(join(dir, \"agents\", f)), { kind: \"agent\" }));\n }\n for (const f of filesWithExt(join(dir, \"commands\"), \".md\")) {\n components.push({ command: `commands/${f}` });\n files.push(\n artifact(`commands/${f}`, readFileSync(join(dir, \"commands\", f)), { kind: \"command\" }),\n );\n }\n\n // Prefer verbatim mcp/<leaf>/server.json copies the adapter wrote; only if there\n // is NO mcp/ dir do we reconstruct server.json from opencode.json's mcp block.\n const mcpDir = join(dir, \"mcp\");\n const verbatim = subdirsWith(mcpDir, \"server.json\");\n if (verbatim.length > 0) {\n for (const leaf of verbatim) {\n components.push({ mcp: `mcp/${leaf}` });\n files.push(\n artifact(`mcp/${leaf}/server.json`, readFileSync(join(mcpDir, leaf, \"server.json\")), {\n kind: \"mcp\",\n }),\n );\n }\n } else {\n const config = readJson(join(dir, \"opencode.json\"));\n const servers = (config?.mcp as Record<string, OpencodeMcpServer> | undefined) ?? {};\n for (const [serverName, cfg] of Object.entries(servers)) {\n components.push({ mcp: `mcp/${serverName}` });\n files.push(\n artifact(\n `mcp/${serverName}/server.json`,\n json(synthesizeServerJson(namespace, serverName, cfg)),\n { kind: \"mcp\" },\n ),\n );\n }\n }\n\n // OpenCode has no plugin manifest; the name is the directory basename, with the\n // opencode.json \"name\" (if any) preferred.\n const config = readJson(join(dir, \"opencode.json\"));\n const name = config?.name ? String(config.name) : basename(dir);\n const plugin: Plugin = {\n name,\n version: \"0.1.0\",\n owner: { name, namespace },\n components,\n };\n return { kind: \"plugin\", plugin, files };\n}\n\nfunction importMarketplace(\n manifest: Record<string, unknown>,\n namespace: string,\n): ImportedMarketplace {\n const owner = manifest.owner as { name?: string; email?: string } | undefined;\n const plugins = ((manifest.plugins as Record<string, unknown>[]) ?? []).map((p) => ({\n plugin: sourceToString(p.source),\n ...(p.version ? { version: String(p.version) } : {}),\n ...(p.category ? { category: String(p.category) } : {}),\n ...(Array.isArray(p.tags) ? { tags: p.tags as string[] } : {}),\n }));\n const marketplace: Marketplace = {\n name: String(manifest.name),\n owner: {\n name: owner?.name ?? String(manifest.name),\n namespace,\n ...(owner?.email ? { email: owner.email } : {}),\n },\n ...(manifest.description ? { description: String(manifest.description) } : {}),\n plugins,\n };\n return { kind: \"marketplace\", marketplace };\n}\n\n/** Reverse-compile an OpenCode plugin or Loom-marketplace dir into the Loom model. */\nexport function importOpencode(dir: string, opts?: ImportOptions): ImportResult | null {\n const namespace = opts?.namespace ?? \"com.imported\";\n\n // OpenCode has no native marketplace; the adapter emits a Loom-only catalog.\n const marketplace = readJson(join(dir, \"loom-marketplace.json\"));\n if (marketplace) return importMarketplace(marketplace, namespace);\n\n // Directory convention: any plural component dir makes this an importable plugin.\n if (\n existsSync(join(dir, \"skills\")) ||\n existsSync(join(dir, \"agents\")) ||\n existsSync(join(dir, \"commands\")) ||\n existsSync(join(dir, \"mcp\")) ||\n existsSync(join(dir, \"opencode.json\"))\n ) {\n return importPlugin(dir, namespace);\n }\n return null;\n}\n","/**\n * Derives a runnable OpenCode `mcp` entry from an MCP-standard `server.json`\n * (the registry's ServerJSON shape: packages[] / remotes[] / a bare command).\n * Stored standards stay verbatim in the plugin; this is the tool-specific view.\n *\n * OpenCode's mcp shape differs from most harnesses (see docs/harness-research.md):\n * local -> { type: \"local\", command: [ ...string ARRAY... ], environment: {…}, enabled: true }\n * remote -> { type: \"remote\", url, headers: {…}, enabled: true }\n * Note the local invocation is a single `command` STRING ARRAY (argv) and the\n * env key is `environment`, NOT `env`.\n */\n\nexport interface OpencodeLocalServer {\n type: \"local\";\n command: string[];\n environment?: Record<string, string>;\n enabled: boolean;\n}\nexport interface OpencodeRemoteServer {\n type: \"remote\";\n url: string;\n headers?: Record<string, string>;\n enabled: boolean;\n}\nexport type OpencodeMcpServer = OpencodeLocalServer | OpencodeRemoteServer;\n\ninterface McpPackage {\n registryType?: string;\n identifier?: string;\n version?: string;\n transport?: { type?: string };\n}\ninterface McpRemote {\n type?: string;\n url?: string;\n headers?: Array<{ name: string; value: string }>;\n}\ninterface ServerJson {\n name?: string;\n packages?: McpPackage[];\n remotes?: McpRemote[];\n command?: string;\n args?: string[];\n env?: Record<string, string>;\n}\n\n/** The short server key OpenCode uses (the part after the reverse-DNS namespace). */\nexport function mcpServerName(server: ServerJson): string {\n const raw = server.name ?? \"server\";\n const afterSlash = raw.includes(\"/\") ? raw.slice(raw.lastIndexOf(\"/\") + 1) : raw;\n return afterSlash || \"server\";\n}\n\n// TODO(verify): the research doc only documents npx/local examples for OpenCode's\n// command array. pypi/oci runner choice (uvx/docker) is a best-effort mirror of\n// the other adapters and not confirmed against OpenCode docs.\nconst RUNNERS: Record<string, string> = { npm: \"npx\", pypi: \"uvx\" };\n\nexport function mcpRunConfig(server: ServerJson): OpencodeMcpServer {\n const pkg = server.packages?.[0];\n if (pkg?.identifier) {\n if (pkg.registryType === \"oci\") {\n return {\n type: \"local\",\n command: [\"docker\", \"run\", \"-i\", \"--rm\", pkg.identifier],\n enabled: true,\n };\n }\n const runner = RUNNERS[pkg.registryType ?? \"npm\"] ?? \"npx\";\n const ident = pkg.version ? `${pkg.identifier}@${pkg.version}` : pkg.identifier;\n const command = runner === \"npx\" ? [\"npx\", \"-y\", ident] : [runner, ident];\n return { type: \"local\", command, enabled: true };\n }\n\n const remote = server.remotes?.[0];\n if (remote?.url) {\n const config: OpencodeRemoteServer = { type: \"remote\", url: remote.url, enabled: true };\n if (remote.headers?.length) {\n config.headers = Object.fromEntries(remote.headers.map((h) => [h.name, h.value]));\n }\n return config;\n }\n\n if (server.command) {\n const config: OpencodeLocalServer = {\n type: \"local\",\n command: [server.command, ...(server.args ?? [])],\n enabled: true,\n };\n if (server.env) config.environment = server.env;\n return config;\n }\n\n return {\n type: \"local\",\n command: [\"echo\", \"server.json declares no runnable transport\"],\n enabled: true,\n };\n}\n","import { homedir } from \"node:os\";\nimport { basename, extname, join } from \"node:path\";\nimport {\n artifact,\n type CompiledArtifact,\n type HarnessAdapter,\n type InstallPaths,\n type PluginCtx,\n type ResolvedMarketplace,\n} from \"@michaelfromyeg/loom-adapter-kit\";\nimport {\n type Component,\n kindOf,\n leafNameOf,\n type Plugin,\n refOf,\n type Scope,\n} from \"@michaelfromyeg/loom-schema\";\nimport { importOpencode } from \"./import\";\nimport { mcpRunConfig, mcpServerName, type OpencodeMcpServer } from \"./mcp\";\n\n/** Bump on any change to OpenCode's directory-convention / opencode.json shape (spec §5). */\nconst TARGET_SCHEMA = \"opencode/1\";\n\ninterface OpencodeManifest {\n mcp: Record<string, OpencodeMcpServer>;\n}\ninterface LoomMarketplacePlugin {\n name: string;\n source: string;\n description?: string;\n version?: string;\n category?: string;\n tags?: string[];\n}\ninterface LoomMarketplace {\n name: string;\n owner: { name: string; namespace: string; email?: string };\n description?: string;\n plugins: LoomMarketplacePlugin[];\n}\n\nconst json = (o: unknown): string => `${JSON.stringify(o, null, 2)}\\n`;\n\n/** Copy every file under a plugin dir into `destPrefix/`, preserving structure. */\nfunction copyDir(\n ctx: PluginCtx,\n ref: string,\n destPrefix: string,\n kind: CompiledArtifact[\"kind\"],\n): CompiledArtifact[] {\n return ctx.list(ref).map((file) => {\n const within = file.startsWith(`${ref}/`) ? file.slice(ref.length + 1) : basename(file);\n return artifact(`${destPrefix}/${within}`, ctx.read(file), { kind });\n });\n}\n\n/**\n * Place a component that may be a single Markdown file or a directory. OpenCode\n * wants agents/commands as a flat `<leaf>.md`; a bare-file source falls back to\n * `.md`, while a directory source is copied verbatim under `destPrefix/`.\n */\nfunction copyFileOrDir(\n ctx: PluginCtx,\n ref: string,\n destPrefix: string,\n kind: CompiledArtifact[\"kind\"],\n): CompiledArtifact[] {\n const files = ctx.list(ref);\n if (files.length === 0) {\n // ref is a single file (e.g. agents/code-review.md).\n return [artifact(`${destPrefix}${extname(ref) || \".md\"}`, ctx.read(ref), { kind })];\n }\n return copyDir(ctx, ref, destPrefix, kind);\n}\n\nexport const opencodeAdapter: HarnessAdapter = {\n target: \"opencode\",\n version: \"0.1.0\",\n targetSchema: TARGET_SCHEMA,\n\n detect(scope: Scope, cwd: string): InstallPaths {\n // User config lives under XDG `~/.config/opencode`; project under `<cwd>/.opencode`.\n const root = scope === \"user\" ? join(homedir(), \".config\", \"opencode\") : join(cwd, \".opencode\");\n return {\n root,\n // Executable plugins (.ts) live in plugins/; that is also where passthrough lands.\n plugins: join(root, \"plugins\"),\n skills: join(root, \"skills\"),\n // opencode.json (with the mcp block) lives at the config root.\n mcp: root,\n agents: join(root, \"agents\"),\n commands: join(root, \"commands\"),\n hooks: join(root, \"plugins\"),\n catalog: root,\n };\n },\n\n transform(component: Component, ctx: PluginCtx): CompiledArtifact[] {\n const ref = refOf(component);\n const leaf = leafNameOf(component);\n switch (kindOf(component)) {\n case \"skill\":\n return copyDir(ctx, ref, `skills/${leaf}`, \"skill\");\n case \"agent\":\n return copyFileOrDir(ctx, ref, `agents/${leaf}`, \"agent\");\n case \"command\":\n return copyFileOrDir(ctx, ref, `commands/${leaf}`, \"command\");\n case \"hook\":\n // OpenCode has no standalone hooks dir; hooks are executable plugins.\n return [\n artifact(`plugins/${basename(ref)}`, ctx.read(ref), { kind: \"hook\", executable: true }),\n ];\n case \"mcp\":\n // Verbatim provenance copy; the runnable config goes into opencode.json's mcp block.\n return copyDir(ctx, ref, `mcp/${leaf}`, \"mcp\");\n case \"passthrough\":\n // Executable plugins/scripts land in plugins/, placed DISABLED (spec §11).\n return [\n artifact(`plugins/${basename(ref)}`, ctx.read(ref), { kind: \"hook\", executable: true }),\n ];\n default:\n return [];\n }\n },\n\n emitManifest(plugin: Plugin, ctx: PluginCtx): CompiledArtifact[] {\n // OpenCode has NO central plugin manifest. The only thing to emit is the\n // aggregated `mcp` block; on install this block is MERGED into the user's\n // existing opencode.json rather than replacing it.\n const mcp: Record<string, OpencodeMcpServer> = {};\n for (const c of plugin.components) {\n if (kindOf(c) !== \"mcp\") continue;\n try {\n const server = JSON.parse(ctx.read(`${refOf(c)}/server.json`).toString(\"utf8\"));\n mcp[mcpServerName(server)] = mcpRunConfig(server);\n } catch {\n // validate.ts already surfaced an error for an unparsable server.json.\n }\n }\n if (Object.keys(mcp).length === 0) return [];\n\n const manifest: OpencodeManifest = { mcp };\n return [artifact(\"opencode.json\", json(manifest), { kind: \"manifest\" })];\n },\n\n emitCatalog(marketplace: ResolvedMarketplace): CompiledArtifact[] {\n // OpenCode reads no marketplace catalog -- do NOT synthesize a manifest it\n // ignores. Emit a Loom-only index so the build output is inspectable; OpenCode\n // does not consume this file.\n const plugins: LoomMarketplacePlugin[] = marketplace.entries.map((entry) => {\n const entryPlugin: LoomMarketplacePlugin = {\n name: entry.name,\n source: entry.source.startsWith(\"./\") ? entry.source : `./${entry.source}`,\n };\n if (entry.description) entryPlugin.description = entry.description;\n if (entry.version) entryPlugin.version = entry.version;\n if (entry.category) entryPlugin.category = entry.category;\n if (entry.tags) entryPlugin.tags = entry.tags;\n return entryPlugin;\n });\n\n const catalog: LoomMarketplace = {\n name: marketplace.name,\n owner: marketplace.owner,\n plugins,\n };\n if (marketplace.description) catalog.description = marketplace.description;\n\n return [artifact(\"loom-marketplace.json\", json(catalog), { kind: \"catalog\" })];\n },\n\n importNative: importOpencode,\n};\n\nexport default opencodeAdapter;\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@michaelfromyeg/loom-adapter-opencode",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Loom adapter for OpenCode: directory-convention placement + opencode.json mcp block.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -16,11 +16,11 @@
16
16
  "dist"
17
17
  ],
18
18
  "dependencies": {
19
- "@michaelfromyeg/loom-adapter-kit": "0.1.0",
20
- "@michaelfromyeg/loom-schema": "0.1.0"
19
+ "@michaelfromyeg/loom-adapter-kit": "0.2.0",
20
+ "@michaelfromyeg/loom-schema": "0.2.0"
21
21
  },
22
22
  "devDependencies": {
23
- "@michaelfromyeg/loom-core": "0.1.0"
23
+ "@michaelfromyeg/loom-core": "0.2.0"
24
24
  },
25
25
  "license": "MIT",
26
26
  "author": "Michael DeMarco",