Built-in design generation now runs as an agentic MCP tool-loop (reusing the agent-rs BuiltInProvider), gated behind OPENPENCIL_DESIGN_AGENT_LOOP / the Settings experimental toggle; the orchestrator stays the default. - design-agent system prompt + in-process design toolset (parity-locked with the MCP surface) + flag-gated Intent::Design routing - spawn_agents execution as sequential sub-loops + live creation-mode badges (per-agent glow + 'N/M designing...' header) - new MCP tools: get_guidelines, ToolSearch, get_screenshot, get_editor_state, export_nodes, spawn_agents; style-guide local audit - #27 AI panel restyle: rounded tool cards + green check-rings, gray user bubbles, model-pill bottom toolbar, header, empty-state pills, the PARALLEL AGENTS (agent_team_size) 1x-6x chip dropdown - multi-chat tabs: ChatSessions model (Deref-to-active) + tab row UI (switch / close / + / Cmd+T) with each run bound to its tab Large checkpoint commit spanning the working tree (Rust shell crates).
57 lines
1.9 KiB
TypeScript
57 lines
1.9 KiB
TypeScript
/**
|
|
* Pre-build script: reads ../openpencil-skill/ and generates a JSON bundle
|
|
* that gets embedded into the CLI binary by esbuild.
|
|
*
|
|
* Usage: bun scripts/bundle-skill.ts
|
|
* Output: apps/cli/src/commands/skill-bundle.json
|
|
*/
|
|
|
|
import { readFileSync, writeFileSync, existsSync } from 'node:fs';
|
|
import { dirname, join, resolve } from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
|
|
// Allow override via env (useful for CI where the skill repo is cloned separately)
|
|
const SKILL_ROOT = process.env.SKILL_ROOT
|
|
? resolve(process.env.SKILL_ROOT)
|
|
: resolve(__dirname, '../../openpencil-skill');
|
|
const OUT = resolve(__dirname, '../apps/cli/src/commands/skill-bundle.json');
|
|
|
|
// Files to embed (relative to openpencil-skill/)
|
|
const FILES = [
|
|
'skills/openpencil-design/SKILL.md',
|
|
'.claude-plugin/plugin.json',
|
|
'.claude-plugin/marketplace.json',
|
|
'.cursor-plugin/plugin.json',
|
|
'package.json',
|
|
'GEMINI.md',
|
|
'gemini-extension.json',
|
|
];
|
|
|
|
function main(): void {
|
|
if (!existsSync(SKILL_ROOT)) {
|
|
console.error(`Skill repo not found at ${SKILL_ROOT}`);
|
|
console.error('Skipping skill bundle — install command will use git clone fallback.');
|
|
// Write an empty bundle so the build doesn't break
|
|
writeFileSync(OUT, JSON.stringify({ version: '', files: {} }, null, 2) + '\n');
|
|
return;
|
|
}
|
|
|
|
const pkg = JSON.parse(readFileSync(join(SKILL_ROOT, 'package.json'), 'utf-8'));
|
|
const bundle: Record<string, string> = {};
|
|
|
|
for (const file of FILES) {
|
|
const fullPath = join(SKILL_ROOT, file);
|
|
if (existsSync(fullPath)) {
|
|
bundle[file] = readFileSync(fullPath, 'utf-8');
|
|
}
|
|
}
|
|
|
|
const output = { version: pkg.version as string, files: bundle };
|
|
writeFileSync(OUT, JSON.stringify(output, null, 2) + '\n');
|
|
console.log(`Bundled ${Object.keys(bundle).length} skill files (v${pkg.version}) → ${OUT}`);
|
|
}
|
|
|
|
main();
|