Download .opencode/plugins/opendesign.js from Urytorre1/OpenDesign: direct link, hf CLI and curl.
- Browser
- Download file 3.49 kB
-
https://huggingface.co/Urytorre1/OpenDesign/resolve/main/.opencode/plugins/opendesign.js
- Command line
-
hf download hf://Urytorre1/OpenDesign/.opencode/plugins/opendesign.js
-
curl -L -o opendesign.js https://huggingface.co/Urytorre1/OpenDesign/resolve/main/.opencode/plugins/opendesign.js
3.49 kB
| /** | |
| * OpenDesign plugin for OpenCode.ai | |
| * | |
| * Injects the opendesign bootstrap skill via chat transform, | |
| * and registers the skills directory via config hook (no symlinks needed). | |
| */ | |
| import path from 'path'; | |
| import fs from 'fs'; | |
| import os from 'os'; | |
| import { fileURLToPath } from 'url'; | |
| const __dirname = path.dirname(fileURLToPath(import.meta.url)); | |
| // Minimal frontmatter extractor (avoids external deps). | |
| const extractAndStripFrontmatter = (content) => { | |
| const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/); | |
| if (!match) return { frontmatter: {}, content }; | |
| const frontmatterStr = match[1]; | |
| const body = match[2]; | |
| const frontmatter = {}; | |
| for (const line of frontmatterStr.split('\n')) { | |
| const colonIdx = line.indexOf(':'); | |
| if (colonIdx > 0) { | |
| const key = line.slice(0, colonIdx).trim(); | |
| const value = line.slice(colonIdx + 1).trim().replace(/^["']|["']$/g, ''); | |
| frontmatter[key] = value; | |
| } | |
| } | |
| return { frontmatter, content: body }; | |
| }; | |
| const normalizePath = (p, homeDir) => { | |
| if (!p || typeof p !== 'string') return null; | |
| let normalized = p.trim(); | |
| if (!normalized) return null; | |
| if (normalized.startsWith('~/')) { | |
| normalized = path.join(homeDir, normalized.slice(2)); | |
| } else if (normalized === '~') { | |
| normalized = homeDir; | |
| } | |
| return path.resolve(normalized); | |
| }; | |
| export const OpenDesignPlugin = async ({ client, directory }) => { | |
| const homeDir = os.homedir(); | |
| const opendesignSkillsDir = path.resolve(__dirname, '../../skills'); | |
| const envConfigDir = normalizePath(process.env.OPENCODE_CONFIG_DIR, homeDir); | |
| const configDir = envConfigDir || path.join(homeDir, '.config/opencode'); | |
| const getBootstrapContent = () => { | |
| const skillPath = path.join(opendesignSkillsDir, 'opendesign', 'SKILL.md'); | |
| if (!fs.existsSync(skillPath)) return null; | |
| const fullContent = fs.readFileSync(skillPath, 'utf8'); | |
| const { content } = extractAndStripFrontmatter(fullContent); | |
| const toolMapping = `**Tool Mapping for OpenCode:** | |
| When OpenDesign skills reference tools you don't have, substitute OpenCode equivalents: | |
| - \`TodoWrite\` β \`todowrite\` | |
| - \`Task\` tool with subagents β OpenCode's subagent system (@mention) | |
| - \`Skill\` tool β OpenCode's native \`skill\` tool | |
| - \`Read\`, \`Write\`, \`Edit\`, \`Bash\` β your native tools | |
| Use OpenCode's native \`skill\` tool to list and load the other OpenDesign skills (wireframe, make-a-deck, interactive-prototype, etc.) on demand.`; | |
| return `<EXTREMELY_IMPORTANT> | |
| You have OpenDesign loaded. | |
| **The opendesign entry-point skill is included below. It is ALREADY LOADED β you are currently following it. Do NOT use the skill tool to load "opendesign" again.** | |
| ${content} | |
| ${toolMapping} | |
| </EXTREMELY_IMPORTANT>`; | |
| }; | |
| return { | |
| // Register the skills directory so OpenCode discovers every SKILL.md | |
| // without the user editing opencode.json or symlinking. | |
| config: async (config) => { | |
| config.skills = config.skills || {}; | |
| config.skills.paths = config.skills.paths || []; | |
| if (!config.skills.paths.includes(opendesignSkillsDir)) { | |
| config.skills.paths.push(opendesignSkillsDir); | |
| } | |
| }, | |
| // Use system prompt transform for compatibility with current OpenCode builds. | |
| 'experimental.chat.system.transform': async (_input, output) => { | |
| const bootstrap = getBootstrapContent(); | |
| if (bootstrap) { | |
| (output.system ||= []).push(bootstrap); | |
| } | |
| } | |
| }; | |
| }; | |