@t3lnet/sceneforge 1.0.9 → 1.0.10
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/README.md +57 -0
- package/cli/cli.js +6 -0
- package/cli/commands/context.js +791 -0
- package/context/context-builder.ts +318 -0
- package/context/index.ts +52 -0
- package/context/template-loader.ts +161 -0
- package/context/templates/base/actions-reference.md +299 -0
- package/context/templates/base/cli-reference.md +236 -0
- package/context/templates/base/project-overview.md +58 -0
- package/context/templates/base/selectors-guide.md +233 -0
- package/context/templates/base/yaml-schema.md +210 -0
- package/context/templates/skills/balance-timing.md +136 -0
- package/context/templates/skills/debug-selector.md +193 -0
- package/context/templates/skills/generate-actions.md +94 -0
- package/context/templates/skills/optimize-demo.md +218 -0
- package/context/templates/skills/review-demo-yaml.md +164 -0
- package/context/templates/skills/write-step-script.md +136 -0
- package/context/templates/stages/stage1-actions.md +236 -0
- package/context/templates/stages/stage2-scripts.md +197 -0
- package/context/templates/stages/stage3-balancing.md +229 -0
- package/context/templates/stages/stage4-rebalancing.md +228 -0
- package/context/tests/context-builder.test.ts +237 -0
- package/context/tests/template-loader.test.ts +181 -0
- package/context/tests/tool-formatter.test.ts +198 -0
- package/context/tool-formatter.ts +189 -0
- package/dist/index.cjs +416 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +182 -1
- package/dist/index.d.ts +182 -1
- package/dist/index.js +391 -11
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -180,8 +180,8 @@ function formatValidationError(error) {
|
|
|
180
180
|
}
|
|
181
181
|
const issues = error.issues;
|
|
182
182
|
return issues.map((issue) => {
|
|
183
|
-
const
|
|
184
|
-
return `${
|
|
183
|
+
const path7 = issue.path.length ? issue.path.join(".") : "root";
|
|
184
|
+
return `${path7}: ${issue.message}`;
|
|
185
185
|
}).join("; ");
|
|
186
186
|
}
|
|
187
187
|
function parseDemoDefinition(input) {
|
|
@@ -311,7 +311,7 @@ function createEmptyStep(id) {
|
|
|
311
311
|
};
|
|
312
312
|
}
|
|
313
313
|
var SECRET_PATTERN = /\$\{(ENV|SECRET):([A-Za-z0-9_]+)\}/g;
|
|
314
|
-
function resolveSecrets(value, resolver,
|
|
314
|
+
function resolveSecrets(value, resolver, path7 = "root") {
|
|
315
315
|
if (typeof value === "string") {
|
|
316
316
|
if (!SECRET_PATTERN.test(value)) {
|
|
317
317
|
return value;
|
|
@@ -320,20 +320,20 @@ function resolveSecrets(value, resolver, path5 = "root") {
|
|
|
320
320
|
return value.replace(SECRET_PATTERN, (_match, _type, key) => {
|
|
321
321
|
const resolved = resolver(key);
|
|
322
322
|
if (resolved === void 0) {
|
|
323
|
-
throw new Error(`Missing secret for ${key} at ${
|
|
323
|
+
throw new Error(`Missing secret for ${key} at ${path7}`);
|
|
324
324
|
}
|
|
325
325
|
return resolved;
|
|
326
326
|
});
|
|
327
327
|
}
|
|
328
328
|
if (Array.isArray(value)) {
|
|
329
329
|
return value.map(
|
|
330
|
-
(entry, index) => resolveSecrets(entry, resolver, `${
|
|
330
|
+
(entry, index) => resolveSecrets(entry, resolver, `${path7}[${index}]`)
|
|
331
331
|
);
|
|
332
332
|
}
|
|
333
333
|
if (value && typeof value === "object") {
|
|
334
334
|
const result = {};
|
|
335
335
|
for (const [key, entry] of Object.entries(value)) {
|
|
336
|
-
result[key] = resolveSecrets(entry, resolver, `${
|
|
336
|
+
result[key] = resolveSecrets(entry, resolver, `${path7}.${key}`);
|
|
337
337
|
}
|
|
338
338
|
return result;
|
|
339
339
|
}
|
|
@@ -412,10 +412,10 @@ function createTypeAction(selector, text) {
|
|
|
412
412
|
text
|
|
413
413
|
};
|
|
414
414
|
}
|
|
415
|
-
function createNavigateAction(
|
|
415
|
+
function createNavigateAction(path7) {
|
|
416
416
|
return {
|
|
417
417
|
action: "navigate",
|
|
418
|
-
path:
|
|
418
|
+
path: path7
|
|
419
419
|
};
|
|
420
420
|
}
|
|
421
421
|
function createWaitAction(duration) {
|
|
@@ -839,7 +839,7 @@ function runCommand(command, args, options = {}) {
|
|
|
839
839
|
cwd,
|
|
840
840
|
maxOutputBytes = DEFAULT_MAX_OUTPUT_BYTES
|
|
841
841
|
} = options;
|
|
842
|
-
return new Promise((
|
|
842
|
+
return new Promise((resolve3, reject) => {
|
|
843
843
|
const child = spawn(command, args, { stdio, cwd });
|
|
844
844
|
let stdout = "";
|
|
845
845
|
let stderr = "";
|
|
@@ -858,7 +858,7 @@ function runCommand(command, args, options = {}) {
|
|
|
858
858
|
});
|
|
859
859
|
child.on("close", (code) => {
|
|
860
860
|
if (code === 0) {
|
|
861
|
-
|
|
861
|
+
resolve3({ stdout, stderr });
|
|
862
862
|
return;
|
|
863
863
|
}
|
|
864
864
|
const error = new Error(`${command} exited with code ${code}`);
|
|
@@ -889,7 +889,7 @@ async function probeMediaDurationMs(filePath) {
|
|
|
889
889
|
return null;
|
|
890
890
|
}
|
|
891
891
|
function sleep(ms) {
|
|
892
|
-
return new Promise((
|
|
892
|
+
return new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
893
893
|
}
|
|
894
894
|
function getStatusCode(error) {
|
|
895
895
|
if (!error || typeof error !== "object") return void 0;
|
|
@@ -2385,10 +2385,369 @@ async function discoverDemos(demoDir) {
|
|
|
2385
2385
|
const files = await fs4.readdir(demoDir);
|
|
2386
2386
|
return files.filter((f) => f.endsWith(".yaml") || f.endsWith(".yml")).map((f) => path4.join(demoDir, f));
|
|
2387
2387
|
}
|
|
2388
|
+
|
|
2389
|
+
// context/template-loader.ts
|
|
2390
|
+
import * as fs5 from "fs/promises";
|
|
2391
|
+
import * as path5 from "path";
|
|
2392
|
+
import { fileURLToPath } from "url";
|
|
2393
|
+
var __filename = fileURLToPath(import.meta.url);
|
|
2394
|
+
var __dirname = path5.dirname(__filename);
|
|
2395
|
+
function getTemplatesDir() {
|
|
2396
|
+
return path5.join(__dirname, "templates");
|
|
2397
|
+
}
|
|
2398
|
+
async function loadTemplate(category, name) {
|
|
2399
|
+
const templatesDir = getTemplatesDir();
|
|
2400
|
+
const filePath = path5.join(templatesDir, category, `${name}.md`);
|
|
2401
|
+
try {
|
|
2402
|
+
const content = await fs5.readFile(filePath, "utf-8");
|
|
2403
|
+
return { name, content, category };
|
|
2404
|
+
} catch (error) {
|
|
2405
|
+
throw new Error(`Failed to load template ${category}/${name}: ${error}`);
|
|
2406
|
+
}
|
|
2407
|
+
}
|
|
2408
|
+
async function loadTemplatesByCategory(category) {
|
|
2409
|
+
const templatesDir = getTemplatesDir();
|
|
2410
|
+
const categoryDir = path5.join(templatesDir, category);
|
|
2411
|
+
try {
|
|
2412
|
+
const files = await fs5.readdir(categoryDir);
|
|
2413
|
+
const templates = [];
|
|
2414
|
+
for (const file of files) {
|
|
2415
|
+
if (file.endsWith(".md")) {
|
|
2416
|
+
const name = file.replace(/\.md$/, "");
|
|
2417
|
+
const template = await loadTemplate(category, name);
|
|
2418
|
+
templates.push(template);
|
|
2419
|
+
}
|
|
2420
|
+
}
|
|
2421
|
+
return templates;
|
|
2422
|
+
} catch (error) {
|
|
2423
|
+
throw new Error(`Failed to load templates from ${category}: ${error}`);
|
|
2424
|
+
}
|
|
2425
|
+
}
|
|
2426
|
+
function interpolateVariables(content, variables) {
|
|
2427
|
+
return content.replace(/\{\{(\w+)\}\}/g, (match, key) => {
|
|
2428
|
+
const value = variables[key];
|
|
2429
|
+
if (value === void 0) {
|
|
2430
|
+
return match;
|
|
2431
|
+
}
|
|
2432
|
+
return String(value);
|
|
2433
|
+
});
|
|
2434
|
+
}
|
|
2435
|
+
function composeTemplates(templates, options) {
|
|
2436
|
+
const { separator = "\n\n---\n\n", includeHeaders = false } = options ?? {};
|
|
2437
|
+
return templates.map((template) => {
|
|
2438
|
+
if (includeHeaders) {
|
|
2439
|
+
return `<!-- Template: ${template.category}/${template.name} -->
|
|
2440
|
+
|
|
2441
|
+
${template.content}`;
|
|
2442
|
+
}
|
|
2443
|
+
return template.content;
|
|
2444
|
+
}).join(separator);
|
|
2445
|
+
}
|
|
2446
|
+
async function listTemplates() {
|
|
2447
|
+
const templatesDir = getTemplatesDir();
|
|
2448
|
+
const result = {
|
|
2449
|
+
base: [],
|
|
2450
|
+
stages: [],
|
|
2451
|
+
skills: []
|
|
2452
|
+
};
|
|
2453
|
+
for (const category of ["base", "stages", "skills"]) {
|
|
2454
|
+
const categoryDir = path5.join(templatesDir, category);
|
|
2455
|
+
try {
|
|
2456
|
+
const files = await fs5.readdir(categoryDir);
|
|
2457
|
+
result[category] = files.filter((f) => f.endsWith(".md")).map((f) => f.replace(/\.md$/, ""));
|
|
2458
|
+
} catch {
|
|
2459
|
+
result[category] = [];
|
|
2460
|
+
}
|
|
2461
|
+
}
|
|
2462
|
+
return result;
|
|
2463
|
+
}
|
|
2464
|
+
async function templateExists(category, name) {
|
|
2465
|
+
const templatesDir = getTemplatesDir();
|
|
2466
|
+
const filePath = path5.join(templatesDir, category, `${name}.md`);
|
|
2467
|
+
try {
|
|
2468
|
+
await fs5.access(filePath);
|
|
2469
|
+
return true;
|
|
2470
|
+
} catch {
|
|
2471
|
+
return false;
|
|
2472
|
+
}
|
|
2473
|
+
}
|
|
2474
|
+
|
|
2475
|
+
// context/tool-formatter.ts
|
|
2476
|
+
var TOOL_CONFIGS = {
|
|
2477
|
+
cursor: {
|
|
2478
|
+
name: "Cursor",
|
|
2479
|
+
description: "Cursor AI IDE with .cursorrules support",
|
|
2480
|
+
combinedFile: ".cursorrules",
|
|
2481
|
+
splitDir: ".cursor/rules",
|
|
2482
|
+
splitFilePrefix: "",
|
|
2483
|
+
fileExtension: ".md",
|
|
2484
|
+
supportsSkills: true
|
|
2485
|
+
},
|
|
2486
|
+
copilot: {
|
|
2487
|
+
name: "GitHub Copilot",
|
|
2488
|
+
description: "GitHub Copilot with instructions file",
|
|
2489
|
+
combinedFile: ".github/copilot-instructions.md",
|
|
2490
|
+
splitDir: ".github/copilot",
|
|
2491
|
+
splitFilePrefix: "",
|
|
2492
|
+
fileExtension: ".md",
|
|
2493
|
+
supportsSkills: false
|
|
2494
|
+
},
|
|
2495
|
+
claude: {
|
|
2496
|
+
name: "Claude Code",
|
|
2497
|
+
description: "Claude Code CLI with CLAUDE.md support",
|
|
2498
|
+
combinedFile: "CLAUDE.md",
|
|
2499
|
+
splitDir: ".claude/rules",
|
|
2500
|
+
splitFilePrefix: "",
|
|
2501
|
+
fileExtension: ".md",
|
|
2502
|
+
supportsSkills: true
|
|
2503
|
+
},
|
|
2504
|
+
codex: {
|
|
2505
|
+
name: "Codex",
|
|
2506
|
+
description: "OpenAI Codex with AGENTS.md support",
|
|
2507
|
+
combinedFile: "AGENTS.md",
|
|
2508
|
+
splitDir: ".codex",
|
|
2509
|
+
splitFilePrefix: "",
|
|
2510
|
+
fileExtension: ".md",
|
|
2511
|
+
supportsSkills: false
|
|
2512
|
+
}
|
|
2513
|
+
};
|
|
2514
|
+
function getSupportedTools() {
|
|
2515
|
+
return Object.keys(TOOL_CONFIGS);
|
|
2516
|
+
}
|
|
2517
|
+
function getToolConfig(tool) {
|
|
2518
|
+
return TOOL_CONFIGS[tool];
|
|
2519
|
+
}
|
|
2520
|
+
function formatForTool(tool, content, options) {
|
|
2521
|
+
const config = TOOL_CONFIGS[tool];
|
|
2522
|
+
const { stage, includeToolHeader = true } = options ?? {};
|
|
2523
|
+
const lines = [];
|
|
2524
|
+
if (includeToolHeader) {
|
|
2525
|
+
lines.push(`# SceneForge LLM Context`);
|
|
2526
|
+
lines.push(``);
|
|
2527
|
+
lines.push(`> Generated for ${config.name}`);
|
|
2528
|
+
if (stage) {
|
|
2529
|
+
lines.push(`> Stage: ${stage}`);
|
|
2530
|
+
}
|
|
2531
|
+
lines.push(``);
|
|
2532
|
+
lines.push(`---`);
|
|
2533
|
+
lines.push(``);
|
|
2534
|
+
}
|
|
2535
|
+
lines.push(content);
|
|
2536
|
+
return lines.join("\n");
|
|
2537
|
+
}
|
|
2538
|
+
function getOutputPath(tool, format, outputDir, stageName) {
|
|
2539
|
+
const config = TOOL_CONFIGS[tool];
|
|
2540
|
+
if (format === "combined") {
|
|
2541
|
+
return `${outputDir}/${config.combinedFile}`;
|
|
2542
|
+
}
|
|
2543
|
+
const fileName = stageName ? `${config.splitFilePrefix}${stageName}${config.fileExtension}` : `${config.splitFilePrefix}main${config.fileExtension}`;
|
|
2544
|
+
return `${outputDir}/${config.splitDir}/${fileName}`;
|
|
2545
|
+
}
|
|
2546
|
+
function getSplitOutputPaths(tool, outputDir, stageNames) {
|
|
2547
|
+
return stageNames.map((stage) => getOutputPath(tool, "split", outputDir, stage));
|
|
2548
|
+
}
|
|
2549
|
+
function formatStageName(stage) {
|
|
2550
|
+
const stageMap = {
|
|
2551
|
+
actions: "Stage 1: Action Generation",
|
|
2552
|
+
scripts: "Stage 2: Script Writing",
|
|
2553
|
+
balance: "Stage 3: Step Balancing",
|
|
2554
|
+
rebalance: "Stage 4: Rebalancing"
|
|
2555
|
+
};
|
|
2556
|
+
return stageMap[stage] ?? stage;
|
|
2557
|
+
}
|
|
2558
|
+
function getStageFileName(stage) {
|
|
2559
|
+
const stageFileMap = {
|
|
2560
|
+
actions: "stage1-actions",
|
|
2561
|
+
scripts: "stage2-scripts",
|
|
2562
|
+
balance: "stage3-balancing",
|
|
2563
|
+
rebalance: "stage4-rebalancing"
|
|
2564
|
+
};
|
|
2565
|
+
return stageFileMap[stage] ?? stage;
|
|
2566
|
+
}
|
|
2567
|
+
function isValidTool(tool) {
|
|
2568
|
+
return tool in TOOL_CONFIGS;
|
|
2569
|
+
}
|
|
2570
|
+
function isValidFormat(format) {
|
|
2571
|
+
return format === "combined" || format === "split";
|
|
2572
|
+
}
|
|
2573
|
+
|
|
2574
|
+
// context/context-builder.ts
|
|
2575
|
+
import * as fs6 from "fs/promises";
|
|
2576
|
+
import * as path6 from "path";
|
|
2577
|
+
async function buildContext(tool, stage, variables) {
|
|
2578
|
+
const templates = [];
|
|
2579
|
+
const baseTemplates = await loadTemplatesByCategory("base");
|
|
2580
|
+
templates.push(...baseTemplates);
|
|
2581
|
+
if (stage === "all") {
|
|
2582
|
+
const stageTemplates = await loadTemplatesByCategory("stages");
|
|
2583
|
+
templates.push(...stageTemplates);
|
|
2584
|
+
} else {
|
|
2585
|
+
const stageFileName = getStageFileName(stage);
|
|
2586
|
+
try {
|
|
2587
|
+
const stageTemplate = await loadTemplate("stages", stageFileName);
|
|
2588
|
+
templates.push(stageTemplate);
|
|
2589
|
+
} catch {
|
|
2590
|
+
}
|
|
2591
|
+
}
|
|
2592
|
+
let content = composeTemplates(templates, {
|
|
2593
|
+
separator: "\n\n---\n\n",
|
|
2594
|
+
includeHeaders: false
|
|
2595
|
+
});
|
|
2596
|
+
if (variables) {
|
|
2597
|
+
content = interpolateVariables(content, variables);
|
|
2598
|
+
}
|
|
2599
|
+
const stageName = stage === "all" ? void 0 : formatStageName(stage);
|
|
2600
|
+
return formatForTool(tool, content, { stage: stageName });
|
|
2601
|
+
}
|
|
2602
|
+
async function deployContext(options) {
|
|
2603
|
+
const { target, stage, format, outputDir, variables } = options;
|
|
2604
|
+
const results = [];
|
|
2605
|
+
const tools = target === "all" ? getSupportedTools() : [target];
|
|
2606
|
+
const stages = stage === "all" ? ["actions", "scripts", "balance", "rebalance"] : [stage];
|
|
2607
|
+
for (const tool of tools) {
|
|
2608
|
+
if (format === "combined") {
|
|
2609
|
+
try {
|
|
2610
|
+
const content = await buildContext(tool, "all", variables);
|
|
2611
|
+
const filePath = getOutputPath(tool, format, outputDir);
|
|
2612
|
+
const absolutePath = path6.resolve(filePath);
|
|
2613
|
+
await fs6.mkdir(path6.dirname(absolutePath), { recursive: true });
|
|
2614
|
+
await fs6.writeFile(absolutePath, content, "utf-8");
|
|
2615
|
+
results.push({
|
|
2616
|
+
tool,
|
|
2617
|
+
filePath: absolutePath,
|
|
2618
|
+
created: true
|
|
2619
|
+
});
|
|
2620
|
+
} catch (error) {
|
|
2621
|
+
results.push({
|
|
2622
|
+
tool,
|
|
2623
|
+
filePath: getOutputPath(tool, format, outputDir),
|
|
2624
|
+
created: false,
|
|
2625
|
+
error: error instanceof Error ? error.message : String(error)
|
|
2626
|
+
});
|
|
2627
|
+
}
|
|
2628
|
+
} else {
|
|
2629
|
+
for (const stg of stages) {
|
|
2630
|
+
try {
|
|
2631
|
+
const content = await buildContext(tool, stg, variables);
|
|
2632
|
+
const stageName = getStageFileName(stg);
|
|
2633
|
+
const filePath = getOutputPath(tool, format, outputDir, stageName);
|
|
2634
|
+
const absolutePath = path6.resolve(filePath);
|
|
2635
|
+
await fs6.mkdir(path6.dirname(absolutePath), { recursive: true });
|
|
2636
|
+
await fs6.writeFile(absolutePath, content, "utf-8");
|
|
2637
|
+
results.push({
|
|
2638
|
+
tool,
|
|
2639
|
+
filePath: absolutePath,
|
|
2640
|
+
stage: stg,
|
|
2641
|
+
created: true
|
|
2642
|
+
});
|
|
2643
|
+
} catch (error) {
|
|
2644
|
+
results.push({
|
|
2645
|
+
tool,
|
|
2646
|
+
filePath: getOutputPath(tool, format, outputDir, stg),
|
|
2647
|
+
stage: stg,
|
|
2648
|
+
created: false,
|
|
2649
|
+
error: error instanceof Error ? error.message : String(error)
|
|
2650
|
+
});
|
|
2651
|
+
}
|
|
2652
|
+
}
|
|
2653
|
+
}
|
|
2654
|
+
}
|
|
2655
|
+
return results;
|
|
2656
|
+
}
|
|
2657
|
+
async function previewContext(tool, stage, variables) {
|
|
2658
|
+
const content = await buildContext(tool, stage, variables);
|
|
2659
|
+
return {
|
|
2660
|
+
tool,
|
|
2661
|
+
stage: stage === "all" ? void 0 : stage,
|
|
2662
|
+
content
|
|
2663
|
+
};
|
|
2664
|
+
}
|
|
2665
|
+
async function listDeployedContext(outputDir) {
|
|
2666
|
+
const tools = getSupportedTools();
|
|
2667
|
+
const files = [];
|
|
2668
|
+
for (const tool of tools) {
|
|
2669
|
+
const config = getToolConfig(tool);
|
|
2670
|
+
const combinedPath = path6.join(outputDir, config.combinedFile);
|
|
2671
|
+
try {
|
|
2672
|
+
await fs6.access(combinedPath);
|
|
2673
|
+
files.push({ tool, path: combinedPath, exists: true });
|
|
2674
|
+
} catch {
|
|
2675
|
+
files.push({ tool, path: combinedPath, exists: false });
|
|
2676
|
+
}
|
|
2677
|
+
const splitDir = path6.join(outputDir, config.splitDir);
|
|
2678
|
+
try {
|
|
2679
|
+
const splitFiles = await fs6.readdir(splitDir);
|
|
2680
|
+
for (const file of splitFiles) {
|
|
2681
|
+
if (file.endsWith(config.fileExtension)) {
|
|
2682
|
+
files.push({
|
|
2683
|
+
tool,
|
|
2684
|
+
path: path6.join(splitDir, file),
|
|
2685
|
+
exists: true
|
|
2686
|
+
});
|
|
2687
|
+
}
|
|
2688
|
+
}
|
|
2689
|
+
} catch {
|
|
2690
|
+
}
|
|
2691
|
+
}
|
|
2692
|
+
return { files };
|
|
2693
|
+
}
|
|
2694
|
+
async function removeContext(outputDir, target) {
|
|
2695
|
+
const tools = target === "all" ? getSupportedTools() : [target];
|
|
2696
|
+
const results = [];
|
|
2697
|
+
for (const tool of tools) {
|
|
2698
|
+
const config = getToolConfig(tool);
|
|
2699
|
+
const combinedPath = path6.join(outputDir, config.combinedFile);
|
|
2700
|
+
try {
|
|
2701
|
+
await fs6.unlink(combinedPath);
|
|
2702
|
+
results.push({ path: combinedPath, removed: true });
|
|
2703
|
+
} catch (error) {
|
|
2704
|
+
if (error.code !== "ENOENT") {
|
|
2705
|
+
results.push({
|
|
2706
|
+
path: combinedPath,
|
|
2707
|
+
removed: false,
|
|
2708
|
+
error: error instanceof Error ? error.message : String(error)
|
|
2709
|
+
});
|
|
2710
|
+
}
|
|
2711
|
+
}
|
|
2712
|
+
const splitDir = path6.join(outputDir, config.splitDir);
|
|
2713
|
+
try {
|
|
2714
|
+
await fs6.rm(splitDir, { recursive: true });
|
|
2715
|
+
results.push({ path: splitDir, removed: true });
|
|
2716
|
+
} catch (error) {
|
|
2717
|
+
if (error.code !== "ENOENT") {
|
|
2718
|
+
results.push({
|
|
2719
|
+
path: splitDir,
|
|
2720
|
+
removed: false,
|
|
2721
|
+
error: error instanceof Error ? error.message : String(error)
|
|
2722
|
+
});
|
|
2723
|
+
}
|
|
2724
|
+
}
|
|
2725
|
+
}
|
|
2726
|
+
return results;
|
|
2727
|
+
}
|
|
2728
|
+
async function getSkill(name) {
|
|
2729
|
+
try {
|
|
2730
|
+
const template = await loadTemplate("skills", name);
|
|
2731
|
+
return { name: template.name, content: template.content };
|
|
2732
|
+
} catch {
|
|
2733
|
+
return null;
|
|
2734
|
+
}
|
|
2735
|
+
}
|
|
2736
|
+
async function listSkills() {
|
|
2737
|
+
const templates = await listTemplates();
|
|
2738
|
+
return templates.skills;
|
|
2739
|
+
}
|
|
2740
|
+
async function hasTemplates() {
|
|
2741
|
+
const templates = await listTemplates();
|
|
2742
|
+
return templates.base.length > 0;
|
|
2743
|
+
}
|
|
2388
2744
|
export {
|
|
2389
2745
|
DEMO_SCHEMA_VERSION,
|
|
2390
2746
|
ScriptGenerator,
|
|
2747
|
+
TOOL_CONFIGS,
|
|
2391
2748
|
VoiceSynthesizer,
|
|
2749
|
+
buildContext,
|
|
2750
|
+
composeTemplates,
|
|
2392
2751
|
createClickAction,
|
|
2393
2752
|
createDragAction,
|
|
2394
2753
|
createEmptyDemo,
|
|
@@ -2407,15 +2766,35 @@ export {
|
|
|
2407
2766
|
demoDefinitionSchema,
|
|
2408
2767
|
demoHover,
|
|
2409
2768
|
demoType,
|
|
2769
|
+
deployContext,
|
|
2410
2770
|
discoverDemos,
|
|
2771
|
+
formatForTool,
|
|
2772
|
+
formatStageName,
|
|
2411
2773
|
formatValidationError,
|
|
2412
2774
|
generateTimingManifest,
|
|
2775
|
+
getOutputPath,
|
|
2776
|
+
getSkill,
|
|
2777
|
+
getSplitOutputPaths,
|
|
2778
|
+
getStageFileName,
|
|
2779
|
+
getSupportedTools,
|
|
2780
|
+
getToolConfig,
|
|
2781
|
+
hasTemplates,
|
|
2413
2782
|
highlightElement,
|
|
2414
2783
|
injectCursorOverlay,
|
|
2784
|
+
interpolateVariables,
|
|
2785
|
+
isValidFormat,
|
|
2786
|
+
isValidTool,
|
|
2787
|
+
listDeployedContext,
|
|
2788
|
+
listSkills,
|
|
2789
|
+
listTemplates,
|
|
2415
2790
|
loadDemoDefinition,
|
|
2791
|
+
loadTemplate,
|
|
2792
|
+
loadTemplatesByCategory,
|
|
2416
2793
|
moveCursorTo,
|
|
2417
2794
|
parseDemoDefinition,
|
|
2418
2795
|
parseFromYAML,
|
|
2796
|
+
previewContext,
|
|
2797
|
+
removeContext,
|
|
2419
2798
|
removeCursorOverlay,
|
|
2420
2799
|
resolvePath,
|
|
2421
2800
|
resolveTarget,
|
|
@@ -2423,6 +2802,7 @@ export {
|
|
|
2423
2802
|
runDemoFromFile,
|
|
2424
2803
|
safeParseDemoDefinition,
|
|
2425
2804
|
serializeToYAML,
|
|
2805
|
+
templateExists,
|
|
2426
2806
|
triggerClickRipple,
|
|
2427
2807
|
validateDemoDefinition
|
|
2428
2808
|
};
|