@omnidev-ai/cli 0.14.0 → 0.17.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 +791 -383
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1243,6 +1243,15 @@ var init_stringify = __esm(() => {
|
|
|
1243
1243
|
});
|
|
1244
1244
|
|
|
1245
1245
|
// ../../node_modules/.bun/smol-toml@1.6.0/node_modules/smol-toml/dist/index.js
|
|
1246
|
+
var exports_dist = {};
|
|
1247
|
+
__export(exports_dist, {
|
|
1248
|
+
stringify: () => stringify,
|
|
1249
|
+
parse: () => parse,
|
|
1250
|
+
default: () => dist_default,
|
|
1251
|
+
TomlError: () => TomlError,
|
|
1252
|
+
TomlDate: () => TomlDate
|
|
1253
|
+
});
|
|
1254
|
+
var dist_default;
|
|
1246
1255
|
var init_dist = __esm(() => {
|
|
1247
1256
|
init_parse();
|
|
1248
1257
|
init_stringify();
|
|
@@ -1275,6 +1284,43 @@ var init_dist = __esm(() => {
|
|
|
1275
1284
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
1276
1285
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
1277
1286
|
*/
|
|
1287
|
+
dist_default = { parse, stringify, TomlDate, TomlError };
|
|
1288
|
+
});
|
|
1289
|
+
|
|
1290
|
+
// ../core/src/providers.ts
|
|
1291
|
+
function normalizeProviderId(provider) {
|
|
1292
|
+
if (provider in PROVIDER_ALIAS_MAP) {
|
|
1293
|
+
return PROVIDER_ALIAS_MAP[provider];
|
|
1294
|
+
}
|
|
1295
|
+
throw new Error(`Unknown provider: ${provider}`);
|
|
1296
|
+
}
|
|
1297
|
+
function normalizeProviderApplicability(value, fieldName) {
|
|
1298
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
1299
|
+
throw new Error(`${fieldName} must be a table of provider = boolean entries`);
|
|
1300
|
+
}
|
|
1301
|
+
const normalized = {};
|
|
1302
|
+
for (const [rawProvider, rawEnabled] of Object.entries(value)) {
|
|
1303
|
+
if (typeof rawEnabled !== "boolean") {
|
|
1304
|
+
throw new Error(`${fieldName}.${rawProvider} must be a boolean`);
|
|
1305
|
+
}
|
|
1306
|
+
const canonicalProvider = normalizeProviderId(rawProvider);
|
|
1307
|
+
const existing = normalized[canonicalProvider];
|
|
1308
|
+
if (existing !== undefined && existing !== rawEnabled) {
|
|
1309
|
+
throw new Error(`Conflicting provider entries in ${fieldName}: ${rawProvider} maps to ${canonicalProvider}`);
|
|
1310
|
+
}
|
|
1311
|
+
normalized[canonicalProvider] = rawEnabled;
|
|
1312
|
+
}
|
|
1313
|
+
return normalized;
|
|
1314
|
+
}
|
|
1315
|
+
var PROVIDER_ALIAS_MAP;
|
|
1316
|
+
var init_providers = __esm(() => {
|
|
1317
|
+
PROVIDER_ALIAS_MAP = {
|
|
1318
|
+
claude: "claude-code",
|
|
1319
|
+
"claude-code": "claude-code",
|
|
1320
|
+
codex: "codex",
|
|
1321
|
+
cursor: "cursor",
|
|
1322
|
+
opencode: "opencode"
|
|
1323
|
+
};
|
|
1278
1324
|
});
|
|
1279
1325
|
|
|
1280
1326
|
// ../core/src/config/parser.ts
|
|
@@ -1301,6 +1347,9 @@ function validateCapabilityConfig(parsed) {
|
|
|
1301
1347
|
if (typeof capability["version"] !== "string") {
|
|
1302
1348
|
throw new Error("capability.version is required in capability.toml");
|
|
1303
1349
|
}
|
|
1350
|
+
if (capability["providers"] !== undefined) {
|
|
1351
|
+
capability["providers"] = normalizeProviderApplicability(capability["providers"], "capability.providers");
|
|
1352
|
+
}
|
|
1304
1353
|
}
|
|
1305
1354
|
function parseCapabilityConfig(tomlContent) {
|
|
1306
1355
|
try {
|
|
@@ -1314,6 +1363,7 @@ function parseCapabilityConfig(tomlContent) {
|
|
|
1314
1363
|
}
|
|
1315
1364
|
var init_parser = __esm(() => {
|
|
1316
1365
|
init_dist();
|
|
1366
|
+
init_providers();
|
|
1317
1367
|
});
|
|
1318
1368
|
|
|
1319
1369
|
// ../core/src/hooks/constants.ts
|
|
@@ -2401,21 +2451,122 @@ var init_loader = __esm(() => {
|
|
|
2401
2451
|
init_constants();
|
|
2402
2452
|
});
|
|
2403
2453
|
|
|
2404
|
-
// ../core/src/capability/
|
|
2405
|
-
import { existsSync as existsSync6
|
|
2454
|
+
// ../core/src/capability/mcp-env.ts
|
|
2455
|
+
import { existsSync as existsSync6 } from "node:fs";
|
|
2406
2456
|
import { readFile as readFile3 } from "node:fs/promises";
|
|
2407
|
-
import {
|
|
2457
|
+
import { join as join4 } from "node:path";
|
|
2458
|
+
import { parseEnv } from "node:util";
|
|
2459
|
+
function hasEnvPlaceholder(value) {
|
|
2460
|
+
return ENV_PLACEHOLDER_DETECTOR.test(value);
|
|
2461
|
+
}
|
|
2462
|
+
function mergeEnvSources(capabilityEnv) {
|
|
2463
|
+
const merged = { ...capabilityEnv };
|
|
2464
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
2465
|
+
if (typeof value === "string") {
|
|
2466
|
+
merged[key] = value;
|
|
2467
|
+
}
|
|
2468
|
+
}
|
|
2469
|
+
return merged;
|
|
2470
|
+
}
|
|
2471
|
+
async function loadCapabilityEnv(capabilityPath) {
|
|
2472
|
+
const envPath = join4(capabilityPath, CAPABILITY_ENV_FILE);
|
|
2473
|
+
if (!existsSync6(envPath)) {
|
|
2474
|
+
return {};
|
|
2475
|
+
}
|
|
2476
|
+
const envContent = await readFile3(envPath, "utf-8");
|
|
2477
|
+
return Object.fromEntries(Object.entries(parseEnv(envContent)).filter((entry) => typeof entry[1] === "string"));
|
|
2478
|
+
}
|
|
2479
|
+
function resolveString(value, variables, capabilityId, fieldPath) {
|
|
2480
|
+
if (!hasEnvPlaceholder(value)) {
|
|
2481
|
+
return value;
|
|
2482
|
+
}
|
|
2483
|
+
return value.replace(ENV_PLACEHOLDER, (_match, variableName) => {
|
|
2484
|
+
const resolved = variables[variableName];
|
|
2485
|
+
if (resolved === undefined) {
|
|
2486
|
+
throw new Error(`Missing environment variable "${variableName}" required by capability "${capabilityId}" in ${fieldPath}`);
|
|
2487
|
+
}
|
|
2488
|
+
return resolved;
|
|
2489
|
+
});
|
|
2490
|
+
}
|
|
2491
|
+
function mcpHasPlaceholders(mcp) {
|
|
2492
|
+
const strings = [];
|
|
2493
|
+
if (mcp.command) {
|
|
2494
|
+
strings.push(mcp.command);
|
|
2495
|
+
}
|
|
2496
|
+
if (mcp.cwd) {
|
|
2497
|
+
strings.push(mcp.cwd);
|
|
2498
|
+
}
|
|
2499
|
+
if (mcp.url) {
|
|
2500
|
+
strings.push(mcp.url);
|
|
2501
|
+
}
|
|
2502
|
+
if (mcp.args) {
|
|
2503
|
+
strings.push(...mcp.args);
|
|
2504
|
+
}
|
|
2505
|
+
if (mcp.env) {
|
|
2506
|
+
strings.push(...Object.values(mcp.env));
|
|
2507
|
+
}
|
|
2508
|
+
if (mcp.headers) {
|
|
2509
|
+
strings.push(...Object.values(mcp.headers));
|
|
2510
|
+
}
|
|
2511
|
+
return strings.some((value) => hasEnvPlaceholder(value));
|
|
2512
|
+
}
|
|
2513
|
+
async function resolveCapabilityMcpEnv(config, capabilityPath) {
|
|
2514
|
+
if (!config.mcp || !mcpHasPlaceholders(config.mcp)) {
|
|
2515
|
+
return config;
|
|
2516
|
+
}
|
|
2517
|
+
const variables = mergeEnvSources(await loadCapabilityEnv(capabilityPath));
|
|
2518
|
+
const resolvedMcp = { ...config.mcp };
|
|
2519
|
+
const capabilityId = config.capability.id;
|
|
2520
|
+
if (resolvedMcp.command) {
|
|
2521
|
+
resolvedMcp.command = resolveString(resolvedMcp.command, variables, capabilityId, "mcp.command");
|
|
2522
|
+
}
|
|
2523
|
+
if (resolvedMcp.cwd) {
|
|
2524
|
+
resolvedMcp.cwd = resolveString(resolvedMcp.cwd, variables, capabilityId, "mcp.cwd");
|
|
2525
|
+
}
|
|
2526
|
+
if (resolvedMcp.url) {
|
|
2527
|
+
resolvedMcp.url = resolveString(resolvedMcp.url, variables, capabilityId, "mcp.url");
|
|
2528
|
+
}
|
|
2529
|
+
if (resolvedMcp.args) {
|
|
2530
|
+
resolvedMcp.args = resolvedMcp.args.map((arg, index) => resolveString(arg, variables, capabilityId, `mcp.args[${index}]`));
|
|
2531
|
+
}
|
|
2532
|
+
if (resolvedMcp.env) {
|
|
2533
|
+
resolvedMcp.env = Object.fromEntries(Object.entries(resolvedMcp.env).map(([key, value]) => [
|
|
2534
|
+
key,
|
|
2535
|
+
resolveString(value, variables, capabilityId, `mcp.env.${key}`)
|
|
2536
|
+
]));
|
|
2537
|
+
}
|
|
2538
|
+
if (resolvedMcp.headers) {
|
|
2539
|
+
resolvedMcp.headers = Object.fromEntries(Object.entries(resolvedMcp.headers).map(([key, value]) => [
|
|
2540
|
+
key,
|
|
2541
|
+
resolveString(value, variables, capabilityId, `mcp.headers.${key}`)
|
|
2542
|
+
]));
|
|
2543
|
+
}
|
|
2544
|
+
return {
|
|
2545
|
+
...config,
|
|
2546
|
+
mcp: resolvedMcp
|
|
2547
|
+
};
|
|
2548
|
+
}
|
|
2549
|
+
var CAPABILITY_ENV_FILE = ".env", ENV_PLACEHOLDER, ENV_PLACEHOLDER_DETECTOR;
|
|
2550
|
+
var init_mcp_env = __esm(() => {
|
|
2551
|
+
ENV_PLACEHOLDER = /\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g;
|
|
2552
|
+
ENV_PLACEHOLDER_DETECTOR = /\$\{([A-Za-z_][A-Za-z0-9_]*)\}/;
|
|
2553
|
+
});
|
|
2554
|
+
|
|
2555
|
+
// ../core/src/capability/rules.ts
|
|
2556
|
+
import { existsSync as existsSync7, readdirSync as readdirSync3 } from "node:fs";
|
|
2557
|
+
import { readFile as readFile4 } from "node:fs/promises";
|
|
2558
|
+
import { basename as basename3, join as join5 } from "node:path";
|
|
2408
2559
|
async function loadRules(capabilityPath, capabilityId) {
|
|
2409
|
-
const rulesDir =
|
|
2410
|
-
if (!
|
|
2560
|
+
const rulesDir = join5(capabilityPath, "rules");
|
|
2561
|
+
if (!existsSync7(rulesDir)) {
|
|
2411
2562
|
return [];
|
|
2412
2563
|
}
|
|
2413
2564
|
const rules = [];
|
|
2414
2565
|
const entries = readdirSync3(rulesDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
2415
2566
|
for (const entry of entries) {
|
|
2416
2567
|
if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
2417
|
-
const rulePath =
|
|
2418
|
-
const content = await
|
|
2568
|
+
const rulePath = join5(rulesDir, entry.name);
|
|
2569
|
+
const content = await readFile4(rulePath, "utf-8");
|
|
2419
2570
|
rules.push({
|
|
2420
2571
|
name: basename3(entry.name, ".md"),
|
|
2421
2572
|
content: content.trim(),
|
|
@@ -2428,22 +2579,22 @@ async function loadRules(capabilityPath, capabilityId) {
|
|
|
2428
2579
|
var init_rules = () => {};
|
|
2429
2580
|
|
|
2430
2581
|
// ../core/src/capability/skills.ts
|
|
2431
|
-
import { existsSync as
|
|
2432
|
-
import { readFile as
|
|
2433
|
-
import { join as
|
|
2582
|
+
import { existsSync as existsSync8, readdirSync as readdirSync4 } from "node:fs";
|
|
2583
|
+
import { readFile as readFile5 } from "node:fs/promises";
|
|
2584
|
+
import { join as join6 } from "node:path";
|
|
2434
2585
|
async function loadSkills(capabilityPath, capabilityId) {
|
|
2435
2586
|
const skills = [];
|
|
2436
2587
|
const possibleDirNames = ["skills", "skill"];
|
|
2437
2588
|
for (const dirName of possibleDirNames) {
|
|
2438
|
-
const dir =
|
|
2439
|
-
if (!
|
|
2589
|
+
const dir = join6(capabilityPath, dirName);
|
|
2590
|
+
if (!existsSync8(dir)) {
|
|
2440
2591
|
continue;
|
|
2441
2592
|
}
|
|
2442
2593
|
const entries = readdirSync4(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
2443
2594
|
for (const entry of entries) {
|
|
2444
2595
|
if (entry.isDirectory()) {
|
|
2445
|
-
const skillPath =
|
|
2446
|
-
if (
|
|
2596
|
+
const skillPath = join6(dir, entry.name, "SKILL.md");
|
|
2597
|
+
if (existsSync8(skillPath)) {
|
|
2447
2598
|
const skill = await parseSkillFile(skillPath, capabilityId);
|
|
2448
2599
|
skills.push(skill);
|
|
2449
2600
|
}
|
|
@@ -2453,7 +2604,7 @@ async function loadSkills(capabilityPath, capabilityId) {
|
|
|
2453
2604
|
return skills;
|
|
2454
2605
|
}
|
|
2455
2606
|
async function parseSkillFile(filePath, capabilityId) {
|
|
2456
|
-
const content = await
|
|
2607
|
+
const content = await readFile5(filePath, "utf-8");
|
|
2457
2608
|
const parsed = parseFrontmatterWithMarkdown(content);
|
|
2458
2609
|
if (!parsed) {
|
|
2459
2610
|
throw new Error(`Invalid SKILL.md format at ${filePath}: missing YAML frontmatter`);
|
|
@@ -2473,30 +2624,30 @@ async function parseSkillFile(filePath, capabilityId) {
|
|
|
2473
2624
|
var init_skills = () => {};
|
|
2474
2625
|
|
|
2475
2626
|
// ../core/src/capability/subagents.ts
|
|
2476
|
-
import { existsSync as
|
|
2477
|
-
import { readFile as
|
|
2478
|
-
import { basename as basename4, join as
|
|
2627
|
+
import { existsSync as existsSync9, readdirSync as readdirSync5 } from "node:fs";
|
|
2628
|
+
import { readFile as readFile6 } from "node:fs/promises";
|
|
2629
|
+
import { basename as basename4, join as join7 } from "node:path";
|
|
2479
2630
|
async function loadSubagents(capabilityPath, capabilityId) {
|
|
2480
2631
|
const subagents = [];
|
|
2481
2632
|
const possibleDirNames = ["subagents", "agents", "agent", "subagent"];
|
|
2482
2633
|
for (const dirName of possibleDirNames) {
|
|
2483
|
-
const dir =
|
|
2484
|
-
if (!
|
|
2634
|
+
const dir = join7(capabilityPath, dirName);
|
|
2635
|
+
if (!existsSync9(dir)) {
|
|
2485
2636
|
continue;
|
|
2486
2637
|
}
|
|
2487
2638
|
const entries = readdirSync5(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
2488
2639
|
for (const entry of entries) {
|
|
2489
2640
|
if (entry.isDirectory()) {
|
|
2490
|
-
let subagentPath =
|
|
2491
|
-
if (!
|
|
2492
|
-
subagentPath =
|
|
2641
|
+
let subagentPath = join7(dir, entry.name, "SUBAGENT.md");
|
|
2642
|
+
if (!existsSync9(subagentPath)) {
|
|
2643
|
+
subagentPath = join7(dir, entry.name, "AGENT.md");
|
|
2493
2644
|
}
|
|
2494
|
-
if (
|
|
2645
|
+
if (existsSync9(subagentPath)) {
|
|
2495
2646
|
const subagent = await parseSubagentFile(subagentPath, capabilityId);
|
|
2496
2647
|
subagents.push(subagent);
|
|
2497
2648
|
}
|
|
2498
2649
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
2499
|
-
const subagentPath =
|
|
2650
|
+
const subagentPath = join7(dir, entry.name);
|
|
2500
2651
|
const subagent = await parseSubagentFile(subagentPath, capabilityId);
|
|
2501
2652
|
subagents.push(subagent);
|
|
2502
2653
|
}
|
|
@@ -2505,7 +2656,7 @@ async function loadSubagents(capabilityPath, capabilityId) {
|
|
|
2505
2656
|
return subagents;
|
|
2506
2657
|
}
|
|
2507
2658
|
async function parseSubagentFile(filePath, capabilityId) {
|
|
2508
|
-
const content = await
|
|
2659
|
+
const content = await readFile6(filePath, "utf-8");
|
|
2509
2660
|
const parsed = parseFrontmatterWithMarkdown(content);
|
|
2510
2661
|
if (!parsed) {
|
|
2511
2662
|
throw new Error(`Invalid SUBAGENT.md format at ${filePath}: missing YAML frontmatter`);
|
|
@@ -2549,18 +2700,18 @@ function parseCommaSeparatedList(value) {
|
|
|
2549
2700
|
var init_subagents = () => {};
|
|
2550
2701
|
|
|
2551
2702
|
// ../core/src/capability/loader.ts
|
|
2552
|
-
import { existsSync as
|
|
2553
|
-
import { readFile as
|
|
2554
|
-
import { join as
|
|
2703
|
+
import { existsSync as existsSync10, readdirSync as readdirSync6 } from "node:fs";
|
|
2704
|
+
import { readFile as readFile7 } from "node:fs/promises";
|
|
2705
|
+
import { join as join8 } from "node:path";
|
|
2555
2706
|
async function discoverCapabilities() {
|
|
2556
2707
|
const capabilities = [];
|
|
2557
|
-
if (
|
|
2708
|
+
if (existsSync10(CAPABILITIES_DIR)) {
|
|
2558
2709
|
const entries = readdirSync6(CAPABILITIES_DIR, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
2559
2710
|
for (const entry of entries) {
|
|
2560
2711
|
if (entry.isDirectory()) {
|
|
2561
|
-
const entryPath =
|
|
2562
|
-
const configPath =
|
|
2563
|
-
if (
|
|
2712
|
+
const entryPath = join8(CAPABILITIES_DIR, entry.name);
|
|
2713
|
+
const configPath = join8(entryPath, "capability.toml");
|
|
2714
|
+
if (existsSync10(configPath)) {
|
|
2564
2715
|
capabilities.push(entryPath);
|
|
2565
2716
|
}
|
|
2566
2717
|
}
|
|
@@ -2569,28 +2720,28 @@ async function discoverCapabilities() {
|
|
|
2569
2720
|
return capabilities;
|
|
2570
2721
|
}
|
|
2571
2722
|
async function loadCapabilityConfig(capabilityPath) {
|
|
2572
|
-
const configPath =
|
|
2573
|
-
const content = await
|
|
2723
|
+
const configPath = join8(capabilityPath, "capability.toml");
|
|
2724
|
+
const content = await readFile7(configPath, "utf-8");
|
|
2574
2725
|
const config = parseCapabilityConfig(content);
|
|
2575
2726
|
return config;
|
|
2576
2727
|
}
|
|
2577
2728
|
async function importCapabilityExports(capabilityPath) {
|
|
2578
|
-
const builtIndexPath =
|
|
2579
|
-
const jsIndexPath =
|
|
2580
|
-
const tsIndexPath =
|
|
2729
|
+
const builtIndexPath = join8(capabilityPath, "dist", "index.js");
|
|
2730
|
+
const jsIndexPath = join8(capabilityPath, "index.js");
|
|
2731
|
+
const tsIndexPath = join8(capabilityPath, "index.ts");
|
|
2581
2732
|
let indexPath = null;
|
|
2582
|
-
if (
|
|
2733
|
+
if (existsSync10(builtIndexPath)) {
|
|
2583
2734
|
indexPath = builtIndexPath;
|
|
2584
|
-
} else if (
|
|
2735
|
+
} else if (existsSync10(jsIndexPath)) {
|
|
2585
2736
|
indexPath = jsIndexPath;
|
|
2586
|
-
} else if (
|
|
2737
|
+
} else if (existsSync10(tsIndexPath)) {
|
|
2587
2738
|
indexPath = tsIndexPath;
|
|
2588
2739
|
}
|
|
2589
2740
|
if (!indexPath) {
|
|
2590
2741
|
return {};
|
|
2591
2742
|
}
|
|
2592
2743
|
try {
|
|
2593
|
-
const absolutePath =
|
|
2744
|
+
const absolutePath = join8(process.cwd(), indexPath);
|
|
2594
2745
|
const module = await import(absolutePath);
|
|
2595
2746
|
return module;
|
|
2596
2747
|
} catch (error) {
|
|
@@ -2610,11 +2761,11 @@ If this is a project-specific capability, install dependencies or remove it from
|
|
|
2610
2761
|
}
|
|
2611
2762
|
}
|
|
2612
2763
|
async function loadTypeDefinitions(capabilityPath) {
|
|
2613
|
-
const typesPath =
|
|
2614
|
-
if (!
|
|
2764
|
+
const typesPath = join8(capabilityPath, "types.d.ts");
|
|
2765
|
+
if (!existsSync10(typesPath)) {
|
|
2615
2766
|
return;
|
|
2616
2767
|
}
|
|
2617
|
-
return
|
|
2768
|
+
return readFile7(typesPath, "utf-8");
|
|
2618
2769
|
}
|
|
2619
2770
|
function convertSkillExports(skillExports, capabilityId) {
|
|
2620
2771
|
return skillExports.map((skillExport) => {
|
|
@@ -2791,19 +2942,57 @@ function convertCommandExports(commandExports, capabilityId) {
|
|
|
2791
2942
|
return result;
|
|
2792
2943
|
});
|
|
2793
2944
|
}
|
|
2945
|
+
function mergeByName(fileBased, programmatic) {
|
|
2946
|
+
const byName = new Map;
|
|
2947
|
+
for (const item of fileBased) {
|
|
2948
|
+
byName.set(item.name, item);
|
|
2949
|
+
}
|
|
2950
|
+
for (const item of programmatic) {
|
|
2951
|
+
byName.set(item.name, item);
|
|
2952
|
+
}
|
|
2953
|
+
return Array.from(byName.values());
|
|
2954
|
+
}
|
|
2794
2955
|
async function loadCapability(capabilityPath) {
|
|
2795
|
-
const
|
|
2956
|
+
const rawConfig = await loadCapabilityConfig(capabilityPath);
|
|
2957
|
+
const config = await resolveCapabilityMcpEnv(rawConfig, capabilityPath);
|
|
2796
2958
|
const id = config.capability.id;
|
|
2797
2959
|
const exports = await importCapabilityExports(capabilityPath);
|
|
2798
2960
|
const exportsAny = exports;
|
|
2799
|
-
const
|
|
2800
|
-
const
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2961
|
+
const defaultExport = exportsAny.default ?? {};
|
|
2962
|
+
const getExportValue = (key) => {
|
|
2963
|
+
if (key in exports && exports[key] !== undefined) {
|
|
2964
|
+
return exportsAny[key];
|
|
2965
|
+
}
|
|
2966
|
+
if (key in defaultExport && defaultExport[key] !== undefined) {
|
|
2967
|
+
return defaultExport[key];
|
|
2968
|
+
}
|
|
2969
|
+
return;
|
|
2970
|
+
};
|
|
2971
|
+
const skillsExport = getExportValue("skills");
|
|
2972
|
+
const programmaticSkills = Array.isArray(skillsExport) ? convertSkillExports(skillsExport, id) : [];
|
|
2973
|
+
const fileSkills = await loadSkills(capabilityPath, id);
|
|
2974
|
+
const skills = mergeByName(fileSkills, programmaticSkills);
|
|
2975
|
+
const rulesExport = getExportValue("rules");
|
|
2976
|
+
const programmaticRules = Array.isArray(rulesExport) ? convertRuleExports(rulesExport, id) : [];
|
|
2977
|
+
const fileRules = await loadRules(capabilityPath, id);
|
|
2978
|
+
const rules = mergeByName(fileRules, programmaticRules);
|
|
2979
|
+
const docsExport = getExportValue("docs");
|
|
2980
|
+
const programmaticDocs = Array.isArray(docsExport) ? convertDocExports(docsExport, id) : [];
|
|
2981
|
+
const fileDocs = await loadDocs(capabilityPath, id);
|
|
2982
|
+
const docs = mergeByName(fileDocs, programmaticDocs);
|
|
2983
|
+
const subagentsExport = getExportValue("subagents");
|
|
2984
|
+
const programmaticSubagents = Array.isArray(subagentsExport) ? convertSubagentExports(subagentsExport, id) : [];
|
|
2985
|
+
const fileSubagents = await loadSubagents(capabilityPath, id);
|
|
2986
|
+
const subagents = mergeByName(fileSubagents, programmaticSubagents);
|
|
2987
|
+
const commandsExport = getExportValue("commands");
|
|
2988
|
+
const programmaticCommands = Array.isArray(commandsExport) ? convertCommandExports(commandsExport, id) : [];
|
|
2989
|
+
const fileCommands = await loadCommands(capabilityPath, id);
|
|
2990
|
+
const commands = mergeByName(fileCommands, programmaticCommands);
|
|
2991
|
+
const typeDefinitionsExport = getExportValue("typeDefinitions");
|
|
2992
|
+
const typeDefinitionsFromExports = typeof typeDefinitionsExport === "string" ? typeDefinitionsExport : undefined;
|
|
2805
2993
|
const typeDefinitions = typeDefinitionsFromExports !== undefined ? typeDefinitionsFromExports : await loadTypeDefinitions(capabilityPath);
|
|
2806
|
-
const
|
|
2994
|
+
const gitignoreExport = getExportValue("gitignore");
|
|
2995
|
+
const gitignore = Array.isArray(gitignoreExport) ? gitignoreExport : undefined;
|
|
2807
2996
|
const hooks = loadCapabilityHooks(id, capabilityPath, { resolveCapabilityRoot: true });
|
|
2808
2997
|
const result = {
|
|
2809
2998
|
id,
|
|
@@ -2831,6 +3020,7 @@ var CAPABILITIES_DIR = ".omni/capabilities";
|
|
|
2831
3020
|
var init_loader2 = __esm(() => {
|
|
2832
3021
|
init_parser();
|
|
2833
3022
|
init_loader();
|
|
3023
|
+
init_mcp_env();
|
|
2834
3024
|
init_commands();
|
|
2835
3025
|
init_docs();
|
|
2836
3026
|
init_rules();
|
|
@@ -2839,8 +3029,8 @@ var init_loader2 = __esm(() => {
|
|
|
2839
3029
|
});
|
|
2840
3030
|
|
|
2841
3031
|
// ../core/src/config/config.ts
|
|
2842
|
-
import { existsSync as
|
|
2843
|
-
import { readFile as
|
|
3032
|
+
import { existsSync as existsSync11 } from "node:fs";
|
|
3033
|
+
import { readFile as readFile8, writeFile } from "node:fs/promises";
|
|
2844
3034
|
function mergeConfigs(base, override) {
|
|
2845
3035
|
const merged = { ...base, ...override };
|
|
2846
3036
|
merged.profiles = { ...base.profiles };
|
|
@@ -2882,8 +3072,8 @@ function mergeConfigs(base, override) {
|
|
|
2882
3072
|
return merged;
|
|
2883
3073
|
}
|
|
2884
3074
|
async function loadBaseConfig() {
|
|
2885
|
-
if (
|
|
2886
|
-
const content = await
|
|
3075
|
+
if (existsSync11(CONFIG_PATH)) {
|
|
3076
|
+
const content = await readFile8(CONFIG_PATH, "utf-8");
|
|
2887
3077
|
return parseOmniConfig(content);
|
|
2888
3078
|
}
|
|
2889
3079
|
return {};
|
|
@@ -2891,8 +3081,8 @@ async function loadBaseConfig() {
|
|
|
2891
3081
|
async function loadConfig() {
|
|
2892
3082
|
const baseConfig = await loadBaseConfig();
|
|
2893
3083
|
let localConfig = {};
|
|
2894
|
-
if (
|
|
2895
|
-
const content = await
|
|
3084
|
+
if (existsSync11(LOCAL_CONFIG)) {
|
|
3085
|
+
const content = await readFile8(LOCAL_CONFIG, "utf-8");
|
|
2896
3086
|
localConfig = parseOmniConfig(content);
|
|
2897
3087
|
}
|
|
2898
3088
|
return mergeConfigs(baseConfig, localConfig);
|
|
@@ -3056,14 +3246,14 @@ var init_config = __esm(() => {
|
|
|
3056
3246
|
});
|
|
3057
3247
|
|
|
3058
3248
|
// ../core/src/state/active-profile.ts
|
|
3059
|
-
import { existsSync as
|
|
3060
|
-
import { readFile as
|
|
3249
|
+
import { existsSync as existsSync12, mkdirSync } from "node:fs";
|
|
3250
|
+
import { readFile as readFile9, unlink, writeFile as writeFile2 } from "node:fs/promises";
|
|
3061
3251
|
async function readActiveProfileState() {
|
|
3062
|
-
if (!
|
|
3252
|
+
if (!existsSync12(ACTIVE_PROFILE_PATH)) {
|
|
3063
3253
|
return null;
|
|
3064
3254
|
}
|
|
3065
3255
|
try {
|
|
3066
|
-
const content = await
|
|
3256
|
+
const content = await readFile9(ACTIVE_PROFILE_PATH, "utf-8");
|
|
3067
3257
|
const trimmed = content.trim();
|
|
3068
3258
|
return trimmed || null;
|
|
3069
3259
|
} catch {
|
|
@@ -3075,7 +3265,7 @@ async function writeActiveProfileState(profileName) {
|
|
|
3075
3265
|
await writeFile2(ACTIVE_PROFILE_PATH, profileName, "utf-8");
|
|
3076
3266
|
}
|
|
3077
3267
|
async function clearActiveProfileState() {
|
|
3078
|
-
if (
|
|
3268
|
+
if (existsSync12(ACTIVE_PROFILE_PATH)) {
|
|
3079
3269
|
await unlink(ACTIVE_PROFILE_PATH);
|
|
3080
3270
|
}
|
|
3081
3271
|
}
|
|
@@ -3319,10 +3509,10 @@ function getActiveProviders(config) {
|
|
|
3319
3509
|
var init_types2 = () => {};
|
|
3320
3510
|
|
|
3321
3511
|
// ../core/src/capability/sources.ts
|
|
3322
|
-
import { existsSync as
|
|
3512
|
+
import { existsSync as existsSync13 } from "node:fs";
|
|
3323
3513
|
import { spawn } from "node:child_process";
|
|
3324
|
-
import { cp, mkdir, readdir, readFile as
|
|
3325
|
-
import { join as
|
|
3514
|
+
import { cp, mkdir, readdir, readFile as readFile10, rename, rm, stat, writeFile as writeFile3 } from "node:fs/promises";
|
|
3515
|
+
import { join as join9 } from "node:path";
|
|
3326
3516
|
import { createHash } from "node:crypto";
|
|
3327
3517
|
async function spawnCapture(command, args, options) {
|
|
3328
3518
|
const timeout = options?.timeout ?? 60000;
|
|
@@ -3379,10 +3569,10 @@ function parseFileSourcePath(source) {
|
|
|
3379
3569
|
return source.slice(7);
|
|
3380
3570
|
}
|
|
3381
3571
|
async function readCapabilityIdFromPath(capabilityPath) {
|
|
3382
|
-
const tomlPath =
|
|
3383
|
-
if (
|
|
3572
|
+
const tomlPath = join9(capabilityPath, "capability.toml");
|
|
3573
|
+
if (existsSync13(tomlPath)) {
|
|
3384
3574
|
try {
|
|
3385
|
-
const content = await
|
|
3575
|
+
const content = await readFile10(tomlPath, "utf-8");
|
|
3386
3576
|
const parsed = parse(content);
|
|
3387
3577
|
const capability = parsed["capability"];
|
|
3388
3578
|
if (capability?.["id"] && typeof capability["id"] === "string") {
|
|
@@ -3435,18 +3625,18 @@ function sourceToGitUrl(source) {
|
|
|
3435
3625
|
return source;
|
|
3436
3626
|
}
|
|
3437
3627
|
function getSourceCapabilityPath(id) {
|
|
3438
|
-
return
|
|
3628
|
+
return join9(OMNI_LOCAL, "capabilities", id);
|
|
3439
3629
|
}
|
|
3440
3630
|
function getLockFilePath() {
|
|
3441
3631
|
return "omni.lock.toml";
|
|
3442
3632
|
}
|
|
3443
3633
|
async function loadLockFile() {
|
|
3444
3634
|
const lockPath = getLockFilePath();
|
|
3445
|
-
if (!
|
|
3635
|
+
if (!existsSync13(lockPath)) {
|
|
3446
3636
|
return { capabilities: {} };
|
|
3447
3637
|
}
|
|
3448
3638
|
try {
|
|
3449
|
-
const content = await
|
|
3639
|
+
const content = await readFile10(lockPath, "utf-8");
|
|
3450
3640
|
const parsed = parse(content);
|
|
3451
3641
|
const rawCapabilities = parsed["capabilities"];
|
|
3452
3642
|
if (!rawCapabilities) {
|
|
@@ -3504,7 +3694,7 @@ function stringifyLockFile(lockFile) {
|
|
|
3504
3694
|
}
|
|
3505
3695
|
async function saveLockFile(lockFile) {
|
|
3506
3696
|
const lockPath = getLockFilePath();
|
|
3507
|
-
await mkdir(
|
|
3697
|
+
await mkdir(join9(OMNI_LOCAL, "capabilities"), { recursive: true });
|
|
3508
3698
|
const header = `# Auto-generated by OmniDev - DO NOT EDIT
|
|
3509
3699
|
# Records installed capability versions for reproducibility
|
|
3510
3700
|
# Last updated: ${new Date().toISOString()}
|
|
@@ -3528,6 +3718,9 @@ function shortCommit(commit) {
|
|
|
3528
3718
|
function shortContentHash(hash) {
|
|
3529
3719
|
return hash.substring(0, 12);
|
|
3530
3720
|
}
|
|
3721
|
+
function escapeTomlString(value) {
|
|
3722
|
+
return value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
|
|
3723
|
+
}
|
|
3531
3724
|
async function computeContentHash(dirPath, excludePatterns = CONTENT_HASH_EXCLUDES) {
|
|
3532
3725
|
const hash = createHash("sha256");
|
|
3533
3726
|
const files = [];
|
|
@@ -3535,7 +3728,7 @@ async function computeContentHash(dirPath, excludePatterns = CONTENT_HASH_EXCLUD
|
|
|
3535
3728
|
const entries = await readdir(currentPath, { withFileTypes: true });
|
|
3536
3729
|
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
3537
3730
|
for (const entry of entries) {
|
|
3538
|
-
const fullPath =
|
|
3731
|
+
const fullPath = join9(currentPath, entry.name);
|
|
3539
3732
|
const relativePath = fullPath.slice(relativeTo.length + 1);
|
|
3540
3733
|
if (excludePatterns.some((pattern) => entry.name === pattern || relativePath.startsWith(`${pattern}/`))) {
|
|
3541
3734
|
continue;
|
|
@@ -3543,7 +3736,7 @@ async function computeContentHash(dirPath, excludePatterns = CONTENT_HASH_EXCLUD
|
|
|
3543
3736
|
if (entry.isDirectory()) {
|
|
3544
3737
|
await collectFiles(fullPath, relativeTo);
|
|
3545
3738
|
} else if (entry.isFile()) {
|
|
3546
|
-
const content = await
|
|
3739
|
+
const content = await readFile10(fullPath);
|
|
3547
3740
|
files.push({ relativePath, content });
|
|
3548
3741
|
}
|
|
3549
3742
|
}
|
|
@@ -3557,10 +3750,10 @@ async function computeContentHash(dirPath, excludePatterns = CONTENT_HASH_EXCLUD
|
|
|
3557
3750
|
return hash.digest("hex");
|
|
3558
3751
|
}
|
|
3559
3752
|
async function detectDisplayVersion(dirPath, fallback, fallbackSource) {
|
|
3560
|
-
const capTomlPath =
|
|
3561
|
-
if (
|
|
3753
|
+
const capTomlPath = join9(dirPath, "capability.toml");
|
|
3754
|
+
if (existsSync13(capTomlPath)) {
|
|
3562
3755
|
try {
|
|
3563
|
-
const content = await
|
|
3756
|
+
const content = await readFile10(capTomlPath, "utf-8");
|
|
3564
3757
|
const parsed = parse(content);
|
|
3565
3758
|
const capability = parsed["capability"];
|
|
3566
3759
|
if (capability?.["version"] && typeof capability["version"] === "string") {
|
|
@@ -3568,20 +3761,20 @@ async function detectDisplayVersion(dirPath, fallback, fallbackSource) {
|
|
|
3568
3761
|
}
|
|
3569
3762
|
} catch {}
|
|
3570
3763
|
}
|
|
3571
|
-
const pluginJsonPath =
|
|
3572
|
-
if (
|
|
3764
|
+
const pluginJsonPath = join9(dirPath, ".claude-plugin", "plugin.json");
|
|
3765
|
+
if (existsSync13(pluginJsonPath)) {
|
|
3573
3766
|
try {
|
|
3574
|
-
const content = await
|
|
3767
|
+
const content = await readFile10(pluginJsonPath, "utf-8");
|
|
3575
3768
|
const parsed = JSON.parse(content);
|
|
3576
3769
|
if (parsed.version && typeof parsed.version === "string") {
|
|
3577
3770
|
return { version: parsed.version, source: "plugin.json" };
|
|
3578
3771
|
}
|
|
3579
3772
|
} catch {}
|
|
3580
3773
|
}
|
|
3581
|
-
const pkgJsonPath =
|
|
3582
|
-
if (
|
|
3774
|
+
const pkgJsonPath = join9(dirPath, "package.json");
|
|
3775
|
+
if (existsSync13(pkgJsonPath)) {
|
|
3583
3776
|
try {
|
|
3584
|
-
const content = await
|
|
3777
|
+
const content = await readFile10(pkgJsonPath, "utf-8");
|
|
3585
3778
|
const parsed = JSON.parse(content);
|
|
3586
3779
|
if (parsed.version && typeof parsed.version === "string") {
|
|
3587
3780
|
return { version: parsed.version, source: "package.json" };
|
|
@@ -3592,9 +3785,9 @@ async function detectDisplayVersion(dirPath, fallback, fallbackSource) {
|
|
|
3592
3785
|
}
|
|
3593
3786
|
async function validateGitCapability(sourceUrl, subPath) {
|
|
3594
3787
|
const gitUrl = sourceToGitUrl(sourceUrl);
|
|
3595
|
-
const tempPath =
|
|
3788
|
+
const tempPath = join9(OMNI_LOCAL, "_temp", `_validate-${Date.now()}`);
|
|
3596
3789
|
try {
|
|
3597
|
-
await mkdir(
|
|
3790
|
+
await mkdir(join9(tempPath, ".."), { recursive: true });
|
|
3598
3791
|
const args = ["clone", "--depth", "1", gitUrl, tempPath];
|
|
3599
3792
|
const { exitCode, stderr } = await spawnCapture("git", args, { timeout: 30000 });
|
|
3600
3793
|
if (exitCode !== 0) {
|
|
@@ -3630,8 +3823,8 @@ async function validateGitCapability(sourceUrl, subPath) {
|
|
|
3630
3823
|
error: `Failed to clone repository: ${stderr.trim()}`
|
|
3631
3824
|
};
|
|
3632
3825
|
}
|
|
3633
|
-
const checkPath = subPath ?
|
|
3634
|
-
if (subPath && !
|
|
3826
|
+
const checkPath = subPath ? join9(tempPath, subPath) : tempPath;
|
|
3827
|
+
if (subPath && !existsSync13(checkPath)) {
|
|
3635
3828
|
return {
|
|
3636
3829
|
valid: false,
|
|
3637
3830
|
hasCapabilityToml: false,
|
|
@@ -3642,9 +3835,9 @@ async function validateGitCapability(sourceUrl, subPath) {
|
|
|
3642
3835
|
const hasCapToml = hasCapabilityToml(checkPath);
|
|
3643
3836
|
let capabilityId;
|
|
3644
3837
|
if (hasCapToml) {
|
|
3645
|
-
const tomlPath =
|
|
3838
|
+
const tomlPath = join9(checkPath, "capability.toml");
|
|
3646
3839
|
try {
|
|
3647
|
-
const content = await
|
|
3840
|
+
const content = await readFile10(tomlPath, "utf-8");
|
|
3648
3841
|
const parsed = parse(content);
|
|
3649
3842
|
const capability = parsed["capability"];
|
|
3650
3843
|
if (capability?.["id"] && typeof capability["id"] === "string") {
|
|
@@ -3676,27 +3869,27 @@ async function validateGitCapability(sourceUrl, subPath) {
|
|
|
3676
3869
|
canBeWrapped: true
|
|
3677
3870
|
};
|
|
3678
3871
|
} finally {
|
|
3679
|
-
if (
|
|
3872
|
+
if (existsSync13(tempPath)) {
|
|
3680
3873
|
await rm(tempPath, { recursive: true });
|
|
3681
3874
|
}
|
|
3682
3875
|
}
|
|
3683
3876
|
}
|
|
3684
3877
|
async function detectPinVersion(sourceUrl, subPath) {
|
|
3685
3878
|
const gitUrl = sourceToGitUrl(sourceUrl);
|
|
3686
|
-
const tempPath =
|
|
3879
|
+
const tempPath = join9(OMNI_LOCAL, "_temp", `_pin-detect-${Date.now()}`);
|
|
3687
3880
|
try {
|
|
3688
|
-
await mkdir(
|
|
3881
|
+
await mkdir(join9(tempPath, ".."), { recursive: true });
|
|
3689
3882
|
const args = ["clone", "--depth", "1", gitUrl, tempPath];
|
|
3690
3883
|
const { exitCode, stderr } = await spawnCapture("git", args);
|
|
3691
3884
|
if (exitCode !== 0) {
|
|
3692
3885
|
throw new Error(`Failed to clone ${gitUrl}: ${stderr.trim()}`);
|
|
3693
3886
|
}
|
|
3694
3887
|
const commit = await getRepoCommit(tempPath);
|
|
3695
|
-
const checkPath = subPath ?
|
|
3696
|
-
const capTomlPath =
|
|
3697
|
-
if (
|
|
3888
|
+
const checkPath = subPath ? join9(tempPath, subPath) : tempPath;
|
|
3889
|
+
const capTomlPath = join9(checkPath, "capability.toml");
|
|
3890
|
+
if (existsSync13(capTomlPath)) {
|
|
3698
3891
|
try {
|
|
3699
|
-
const content = await
|
|
3892
|
+
const content = await readFile10(capTomlPath, "utf-8");
|
|
3700
3893
|
const parsed = parse(content);
|
|
3701
3894
|
const capability = parsed["capability"];
|
|
3702
3895
|
if (capability?.["version"] && typeof capability["version"] === "string") {
|
|
@@ -3704,10 +3897,10 @@ async function detectPinVersion(sourceUrl, subPath) {
|
|
|
3704
3897
|
}
|
|
3705
3898
|
} catch {}
|
|
3706
3899
|
}
|
|
3707
|
-
const pluginJsonPath =
|
|
3708
|
-
if (
|
|
3900
|
+
const pluginJsonPath = join9(checkPath, ".claude-plugin", "plugin.json");
|
|
3901
|
+
if (existsSync13(pluginJsonPath)) {
|
|
3709
3902
|
try {
|
|
3710
|
-
const content = await
|
|
3903
|
+
const content = await readFile10(pluginJsonPath, "utf-8");
|
|
3711
3904
|
const parsed = JSON.parse(content);
|
|
3712
3905
|
if (parsed.version && typeof parsed.version === "string") {
|
|
3713
3906
|
return parsed.version;
|
|
@@ -3716,13 +3909,13 @@ async function detectPinVersion(sourceUrl, subPath) {
|
|
|
3716
3909
|
}
|
|
3717
3910
|
return commit;
|
|
3718
3911
|
} finally {
|
|
3719
|
-
if (
|
|
3912
|
+
if (existsSync13(tempPath)) {
|
|
3720
3913
|
await rm(tempPath, { recursive: true });
|
|
3721
3914
|
}
|
|
3722
3915
|
}
|
|
3723
3916
|
}
|
|
3724
3917
|
async function cloneRepo(gitUrl, targetPath, ref) {
|
|
3725
|
-
await mkdir(
|
|
3918
|
+
await mkdir(join9(targetPath, ".."), { recursive: true });
|
|
3726
3919
|
const args = ["clone", "--depth", "1"];
|
|
3727
3920
|
if (ref) {
|
|
3728
3921
|
args.push("--branch", ref);
|
|
@@ -3734,41 +3927,62 @@ async function cloneRepo(gitUrl, targetPath, ref) {
|
|
|
3734
3927
|
}
|
|
3735
3928
|
}
|
|
3736
3929
|
async function fetchRepo(repoPath, ref) {
|
|
3737
|
-
const
|
|
3930
|
+
const fetchArgs = ["fetch", "--depth", "1", "origin"];
|
|
3931
|
+
if (ref) {
|
|
3932
|
+
fetchArgs.push(ref);
|
|
3933
|
+
}
|
|
3934
|
+
const fetchResult = await spawnCapture("git", fetchArgs, {
|
|
3738
3935
|
cwd: repoPath
|
|
3739
3936
|
});
|
|
3740
3937
|
if (fetchResult.exitCode !== 0) {
|
|
3741
3938
|
throw new Error(`Failed to fetch in ${repoPath}: ${fetchResult.stderr.trim()}`);
|
|
3742
3939
|
}
|
|
3743
3940
|
const currentCommit = await getRepoCommit(repoPath);
|
|
3744
|
-
|
|
3745
|
-
|
|
3941
|
+
let resetTarget;
|
|
3942
|
+
if (ref) {
|
|
3943
|
+
resetTarget = "FETCH_HEAD";
|
|
3944
|
+
} else {
|
|
3945
|
+
const remoteShowResult = await spawnCapture("git", ["remote", "show", "origin"], {
|
|
3946
|
+
cwd: repoPath
|
|
3947
|
+
});
|
|
3948
|
+
let defaultBranch = "main";
|
|
3949
|
+
if (remoteShowResult.exitCode === 0) {
|
|
3950
|
+
const match = remoteShowResult.stdout.match(/HEAD branch:\s*(\S+)/);
|
|
3951
|
+
if (match?.[1]) {
|
|
3952
|
+
defaultBranch = match[1];
|
|
3953
|
+
}
|
|
3954
|
+
}
|
|
3955
|
+
resetTarget = `origin/${defaultBranch}`;
|
|
3956
|
+
}
|
|
3957
|
+
const revParseResult = await spawnCapture("git", ["rev-parse", resetTarget], {
|
|
3746
3958
|
cwd: repoPath
|
|
3747
3959
|
});
|
|
3748
|
-
if (
|
|
3749
|
-
throw new Error(`Failed to
|
|
3960
|
+
if (revParseResult.exitCode !== 0) {
|
|
3961
|
+
throw new Error(`Failed to resolve ${resetTarget} in ${repoPath}: ${revParseResult.stderr.trim()}`);
|
|
3750
3962
|
}
|
|
3751
|
-
const
|
|
3752
|
-
if (currentCommit ===
|
|
3963
|
+
const targetCommit = revParseResult.stdout.trim();
|
|
3964
|
+
if (currentCommit === targetCommit) {
|
|
3753
3965
|
return false;
|
|
3754
3966
|
}
|
|
3755
|
-
const
|
|
3756
|
-
|
|
3757
|
-
|
|
3967
|
+
const resetResult = await spawnCapture("git", ["reset", "--hard", resetTarget], {
|
|
3968
|
+
cwd: repoPath
|
|
3969
|
+
});
|
|
3970
|
+
if (resetResult.exitCode !== 0) {
|
|
3971
|
+
throw new Error(`Failed to reset in ${repoPath}: ${resetResult.stderr.trim()}`);
|
|
3758
3972
|
}
|
|
3759
3973
|
return true;
|
|
3760
3974
|
}
|
|
3761
3975
|
function hasCapabilityToml(dirPath) {
|
|
3762
|
-
return
|
|
3976
|
+
return existsSync13(join9(dirPath, "capability.toml"));
|
|
3763
3977
|
}
|
|
3764
3978
|
async function shouldWrapDirectory(dirPath) {
|
|
3765
|
-
if (
|
|
3979
|
+
if (existsSync13(join9(dirPath, ".claude-plugin", "plugin.json"))) {
|
|
3766
3980
|
return true;
|
|
3767
3981
|
}
|
|
3768
3982
|
const allDirs = [...SKILL_DIRS, ...AGENT_DIRS, ...COMMAND_DIRS, ...RULE_DIRS, ...DOC_DIRS];
|
|
3769
3983
|
for (const dirName of allDirs) {
|
|
3770
|
-
const checkPath =
|
|
3771
|
-
if (
|
|
3984
|
+
const checkPath = join9(dirPath, dirName);
|
|
3985
|
+
if (existsSync13(checkPath)) {
|
|
3772
3986
|
const stats = await stat(checkPath);
|
|
3773
3987
|
if (stats.isDirectory()) {
|
|
3774
3988
|
return true;
|
|
@@ -3777,10 +3991,64 @@ async function shouldWrapDirectory(dirPath) {
|
|
|
3777
3991
|
}
|
|
3778
3992
|
return false;
|
|
3779
3993
|
}
|
|
3994
|
+
function isRecognizedWrappedDirectory(dirName, keepGitDir = false) {
|
|
3995
|
+
if (keepGitDir && dirName === ".git") {
|
|
3996
|
+
return true;
|
|
3997
|
+
}
|
|
3998
|
+
return WRAPPED_CONTENT_DIRS.has(dirName);
|
|
3999
|
+
}
|
|
4000
|
+
function isMandatoryWrappedRootFile(fileName) {
|
|
4001
|
+
if (WRAPPED_ROOT_FILES_EXACT.has(fileName)) {
|
|
4002
|
+
return true;
|
|
4003
|
+
}
|
|
4004
|
+
return WRAPPED_ROOT_FILE_PATTERNS.some((pattern) => pattern.test(fileName));
|
|
4005
|
+
}
|
|
4006
|
+
async function copyWrappedContentOnly(sourcePath, targetPath) {
|
|
4007
|
+
await mkdir(targetPath, { recursive: true });
|
|
4008
|
+
const entries = await readdir(sourcePath, { withFileTypes: true });
|
|
4009
|
+
for (const entry of entries) {
|
|
4010
|
+
if (entry.isDirectory() && !isRecognizedWrappedDirectory(entry.name)) {
|
|
4011
|
+
continue;
|
|
4012
|
+
}
|
|
4013
|
+
if (entry.isFile() && !isMandatoryWrappedRootFile(entry.name)) {
|
|
4014
|
+
continue;
|
|
4015
|
+
}
|
|
4016
|
+
if (!entry.isDirectory() && !entry.isFile()) {
|
|
4017
|
+
continue;
|
|
4018
|
+
}
|
|
4019
|
+
const sourceEntryPath = join9(sourcePath, entry.name);
|
|
4020
|
+
const targetEntryPath = join9(targetPath, entry.name);
|
|
4021
|
+
if (entry.isDirectory()) {
|
|
4022
|
+
await cp(sourceEntryPath, targetEntryPath, { recursive: true });
|
|
4023
|
+
} else {
|
|
4024
|
+
await cp(sourceEntryPath, targetEntryPath);
|
|
4025
|
+
}
|
|
4026
|
+
}
|
|
4027
|
+
}
|
|
4028
|
+
async function pruneUnknownWrappedEntries(repoPath, keepGitDir = false) {
|
|
4029
|
+
const entries = await readdir(repoPath, { withFileTypes: true });
|
|
4030
|
+
for (const entry of entries) {
|
|
4031
|
+
if (entry.isDirectory()) {
|
|
4032
|
+
if (isRecognizedWrappedDirectory(entry.name, keepGitDir)) {
|
|
4033
|
+
continue;
|
|
4034
|
+
}
|
|
4035
|
+
await rm(join9(repoPath, entry.name), { recursive: true, force: true });
|
|
4036
|
+
continue;
|
|
4037
|
+
}
|
|
4038
|
+
if (entry.isFile()) {
|
|
4039
|
+
if (isMandatoryWrappedRootFile(entry.name)) {
|
|
4040
|
+
continue;
|
|
4041
|
+
}
|
|
4042
|
+
await rm(join9(repoPath, entry.name), { force: true });
|
|
4043
|
+
continue;
|
|
4044
|
+
}
|
|
4045
|
+
await rm(join9(repoPath, entry.name), { recursive: true, force: true });
|
|
4046
|
+
}
|
|
4047
|
+
}
|
|
3780
4048
|
async function findMatchingDirs(basePath, names) {
|
|
3781
4049
|
for (const name of names) {
|
|
3782
|
-
const dirPath =
|
|
3783
|
-
if (
|
|
4050
|
+
const dirPath = join9(basePath, name);
|
|
4051
|
+
if (existsSync13(dirPath)) {
|
|
3784
4052
|
const stats = await stat(dirPath);
|
|
3785
4053
|
if (stats.isDirectory()) {
|
|
3786
4054
|
return dirPath;
|
|
@@ -3791,15 +4059,15 @@ async function findMatchingDirs(basePath, names) {
|
|
|
3791
4059
|
}
|
|
3792
4060
|
async function findContentItems(dirPath, filePatterns) {
|
|
3793
4061
|
const items = [];
|
|
3794
|
-
if (!
|
|
4062
|
+
if (!existsSync13(dirPath)) {
|
|
3795
4063
|
return items;
|
|
3796
4064
|
}
|
|
3797
4065
|
const entries = (await readdir(dirPath, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name));
|
|
3798
4066
|
for (const entry of entries) {
|
|
3799
|
-
const entryPath =
|
|
4067
|
+
const entryPath = join9(dirPath, entry.name);
|
|
3800
4068
|
if (entry.isDirectory()) {
|
|
3801
4069
|
for (const pattern of filePatterns) {
|
|
3802
|
-
if (
|
|
4070
|
+
if (existsSync13(join9(entryPath, pattern))) {
|
|
3803
4071
|
items.push({
|
|
3804
4072
|
name: entry.name,
|
|
3805
4073
|
path: entryPath,
|
|
@@ -3820,12 +4088,12 @@ async function findContentItems(dirPath, filePatterns) {
|
|
|
3820
4088
|
return items;
|
|
3821
4089
|
}
|
|
3822
4090
|
async function parsePluginJson(dirPath) {
|
|
3823
|
-
const pluginJsonPath =
|
|
3824
|
-
if (!
|
|
4091
|
+
const pluginJsonPath = join9(dirPath, ".claude-plugin", "plugin.json");
|
|
4092
|
+
if (!existsSync13(pluginJsonPath)) {
|
|
3825
4093
|
return null;
|
|
3826
4094
|
}
|
|
3827
4095
|
try {
|
|
3828
|
-
const content = await
|
|
4096
|
+
const content = await readFile10(pluginJsonPath, "utf-8");
|
|
3829
4097
|
const data = JSON.parse(content);
|
|
3830
4098
|
const result = {
|
|
3831
4099
|
name: data.name,
|
|
@@ -3845,12 +4113,12 @@ async function parsePluginJson(dirPath) {
|
|
|
3845
4113
|
}
|
|
3846
4114
|
}
|
|
3847
4115
|
async function readReadmeDescription(dirPath) {
|
|
3848
|
-
const readmePath =
|
|
3849
|
-
if (!
|
|
4116
|
+
const readmePath = join9(dirPath, "README.md");
|
|
4117
|
+
if (!existsSync13(readmePath)) {
|
|
3850
4118
|
return null;
|
|
3851
4119
|
}
|
|
3852
4120
|
try {
|
|
3853
|
-
const content = await
|
|
4121
|
+
const content = await readFile10(readmePath, "utf-8");
|
|
3854
4122
|
const lines = content.split(`
|
|
3855
4123
|
`);
|
|
3856
4124
|
let description = "";
|
|
@@ -3885,9 +4153,9 @@ async function normalizeFolderNames(repoPath) {
|
|
|
3885
4153
|
{ from: "rule", to: "rules" }
|
|
3886
4154
|
];
|
|
3887
4155
|
for (const { from, to } of renameMappings) {
|
|
3888
|
-
const fromPath =
|
|
3889
|
-
const toPath =
|
|
3890
|
-
if (
|
|
4156
|
+
const fromPath = join9(repoPath, from);
|
|
4157
|
+
const toPath = join9(repoPath, to);
|
|
4158
|
+
if (existsSync13(fromPath) && !existsSync13(toPath)) {
|
|
3891
4159
|
try {
|
|
3892
4160
|
const stats = await stat(fromPath);
|
|
3893
4161
|
if (stats.isDirectory()) {
|
|
@@ -3952,31 +4220,31 @@ async function generateCapabilityToml(id, repoPath, source, commit, content) {
|
|
|
3952
4220
|
# This capability was wrapped from an external repository
|
|
3953
4221
|
|
|
3954
4222
|
[capability]
|
|
3955
|
-
id = "${id}"
|
|
3956
|
-
name = "${name}"
|
|
3957
|
-
version = "${version}"
|
|
3958
|
-
description = "${description}"
|
|
4223
|
+
id = "${escapeTomlString(id)}"
|
|
4224
|
+
name = "${escapeTomlString(name)}"
|
|
4225
|
+
version = "${escapeTomlString(version)}"
|
|
4226
|
+
description = "${escapeTomlString(description)}"
|
|
3959
4227
|
`;
|
|
3960
4228
|
if (pluginMeta?.author?.name || pluginMeta?.author?.email) {
|
|
3961
4229
|
tomlContent += `
|
|
3962
4230
|
[capability.author]
|
|
3963
4231
|
`;
|
|
3964
4232
|
if (pluginMeta.author.name) {
|
|
3965
|
-
tomlContent += `name = "${pluginMeta.author.name}"
|
|
4233
|
+
tomlContent += `name = "${escapeTomlString(pluginMeta.author.name)}"
|
|
3966
4234
|
`;
|
|
3967
4235
|
}
|
|
3968
4236
|
if (pluginMeta.author.email) {
|
|
3969
|
-
tomlContent += `email = "${pluginMeta.author.email}"
|
|
4237
|
+
tomlContent += `email = "${escapeTomlString(pluginMeta.author.email)}"
|
|
3970
4238
|
`;
|
|
3971
4239
|
}
|
|
3972
4240
|
}
|
|
3973
4241
|
tomlContent += `
|
|
3974
4242
|
[capability.metadata]
|
|
3975
|
-
repository = "${repoUrl}"
|
|
4243
|
+
repository = "${escapeTomlString(repoUrl)}"
|
|
3976
4244
|
wrapped = true
|
|
3977
4245
|
commit = "${commit}"
|
|
3978
4246
|
`;
|
|
3979
|
-
await writeFile3(
|
|
4247
|
+
await writeFile3(join9(repoPath, "capability.toml"), tomlContent, "utf-8");
|
|
3980
4248
|
}
|
|
3981
4249
|
async function fetchGitCapabilitySource(id, config, options) {
|
|
3982
4250
|
const gitUrl = sourceToGitUrl(config.source);
|
|
@@ -3984,31 +4252,40 @@ async function fetchGitCapabilitySource(id, config, options) {
|
|
|
3984
4252
|
let updated = false;
|
|
3985
4253
|
let commit;
|
|
3986
4254
|
let repoPath;
|
|
4255
|
+
let needsWrap = false;
|
|
3987
4256
|
const gitRef = config.version && config.version !== "latest" ? config.version : undefined;
|
|
3988
4257
|
if (config.path) {
|
|
3989
|
-
const tempPath =
|
|
3990
|
-
if (
|
|
4258
|
+
const tempPath = join9(OMNI_LOCAL, "_temp", `${id}-repo`);
|
|
4259
|
+
if (existsSync13(join9(tempPath, ".git"))) {
|
|
3991
4260
|
updated = await fetchRepo(tempPath, gitRef);
|
|
3992
4261
|
commit = await getRepoCommit(tempPath);
|
|
3993
4262
|
} else {
|
|
3994
|
-
await mkdir(
|
|
4263
|
+
await mkdir(join9(tempPath, ".."), { recursive: true });
|
|
3995
4264
|
await cloneRepo(gitUrl, tempPath, gitRef);
|
|
3996
4265
|
commit = await getRepoCommit(tempPath);
|
|
3997
4266
|
updated = true;
|
|
3998
4267
|
}
|
|
3999
|
-
const sourcePath =
|
|
4000
|
-
if (!
|
|
4268
|
+
const sourcePath = join9(tempPath, config.path);
|
|
4269
|
+
if (!existsSync13(sourcePath)) {
|
|
4001
4270
|
throw new Error(`Path not found in repository: ${config.path}`);
|
|
4002
4271
|
}
|
|
4003
|
-
|
|
4272
|
+
const sourceHasCapabilityToml = hasCapabilityToml(sourcePath);
|
|
4273
|
+
if (!sourceHasCapabilityToml) {
|
|
4274
|
+
needsWrap = await shouldWrapDirectory(sourcePath);
|
|
4275
|
+
}
|
|
4276
|
+
if (existsSync13(targetPath)) {
|
|
4004
4277
|
await rm(targetPath, { recursive: true });
|
|
4005
4278
|
}
|
|
4006
|
-
await mkdir(
|
|
4007
|
-
|
|
4279
|
+
await mkdir(join9(targetPath, ".."), { recursive: true });
|
|
4280
|
+
if (needsWrap) {
|
|
4281
|
+
await copyWrappedContentOnly(sourcePath, targetPath);
|
|
4282
|
+
} else {
|
|
4283
|
+
await cp(sourcePath, targetPath, { recursive: true });
|
|
4284
|
+
}
|
|
4008
4285
|
await rm(tempPath, { recursive: true });
|
|
4009
4286
|
repoPath = targetPath;
|
|
4010
4287
|
} else {
|
|
4011
|
-
if (
|
|
4288
|
+
if (existsSync13(join9(targetPath, ".git"))) {
|
|
4012
4289
|
if (!options?.silent) {
|
|
4013
4290
|
console.log(` Checking ${id}...`);
|
|
4014
4291
|
}
|
|
@@ -4024,11 +4301,11 @@ async function fetchGitCapabilitySource(id, config, options) {
|
|
|
4024
4301
|
}
|
|
4025
4302
|
repoPath = targetPath;
|
|
4026
4303
|
}
|
|
4027
|
-
|
|
4028
|
-
if (!hasCapabilityToml(repoPath)) {
|
|
4304
|
+
if (!config.path && !hasCapabilityToml(repoPath)) {
|
|
4029
4305
|
needsWrap = await shouldWrapDirectory(repoPath);
|
|
4030
4306
|
}
|
|
4031
4307
|
if (needsWrap) {
|
|
4308
|
+
await pruneUnknownWrappedEntries(repoPath, true);
|
|
4032
4309
|
await normalizeFolderNames(repoPath);
|
|
4033
4310
|
const content = await discoverContent(repoPath);
|
|
4034
4311
|
await generateCapabilityToml(id, repoPath, config.source, commit, content);
|
|
@@ -4059,7 +4336,7 @@ async function fetchGitCapabilitySource(id, config, options) {
|
|
|
4059
4336
|
async function fetchFileCapabilitySource(id, config, options) {
|
|
4060
4337
|
const sourcePath = parseFileSourcePath(config.source);
|
|
4061
4338
|
const targetPath = getSourceCapabilityPath(id);
|
|
4062
|
-
if (!
|
|
4339
|
+
if (!existsSync13(sourcePath)) {
|
|
4063
4340
|
throw new Error(`File source not found: ${sourcePath}`);
|
|
4064
4341
|
}
|
|
4065
4342
|
const sourceStats = await stat(sourcePath);
|
|
@@ -4067,7 +4344,7 @@ async function fetchFileCapabilitySource(id, config, options) {
|
|
|
4067
4344
|
throw new Error(`File source must be a directory: ${sourcePath}`);
|
|
4068
4345
|
}
|
|
4069
4346
|
const contentHash = await computeContentHash(sourcePath);
|
|
4070
|
-
const hasCapToml =
|
|
4347
|
+
const hasCapToml = existsSync13(join9(sourcePath, "capability.toml"));
|
|
4071
4348
|
let needsWrap = false;
|
|
4072
4349
|
if (!hasCapToml) {
|
|
4073
4350
|
needsWrap = await shouldWrapDirectory(sourcePath);
|
|
@@ -4078,11 +4355,15 @@ async function fetchFileCapabilitySource(id, config, options) {
|
|
|
4078
4355
|
if (!options?.silent) {
|
|
4079
4356
|
console.log(` Copying ${id} from ${sourcePath}...`);
|
|
4080
4357
|
}
|
|
4081
|
-
if (
|
|
4358
|
+
if (existsSync13(targetPath)) {
|
|
4082
4359
|
await rm(targetPath, { recursive: true });
|
|
4083
4360
|
}
|
|
4084
|
-
await mkdir(
|
|
4085
|
-
|
|
4361
|
+
await mkdir(join9(targetPath, ".."), { recursive: true });
|
|
4362
|
+
if (needsWrap) {
|
|
4363
|
+
await copyWrappedContentOnly(sourcePath, targetPath);
|
|
4364
|
+
} else {
|
|
4365
|
+
await cp(sourcePath, targetPath, { recursive: true });
|
|
4366
|
+
}
|
|
4086
4367
|
if (needsWrap) {
|
|
4087
4368
|
await normalizeFolderNames(targetPath);
|
|
4088
4369
|
const content = await discoverContent(targetPath);
|
|
@@ -4138,30 +4419,30 @@ async function generateFileSourceCapabilityToml(id, source, hashVersion, content
|
|
|
4138
4419
|
# This capability was wrapped from a local directory
|
|
4139
4420
|
|
|
4140
4421
|
[capability]
|
|
4141
|
-
id = "${id}"
|
|
4142
|
-
name = "${name}"
|
|
4143
|
-
version = "${version}"
|
|
4144
|
-
description = "${description}"
|
|
4422
|
+
id = "${escapeTomlString(id)}"
|
|
4423
|
+
name = "${escapeTomlString(name)}"
|
|
4424
|
+
version = "${escapeTomlString(version)}"
|
|
4425
|
+
description = "${escapeTomlString(description)}"
|
|
4145
4426
|
`;
|
|
4146
4427
|
if (pluginMeta?.author?.name || pluginMeta?.author?.email) {
|
|
4147
4428
|
tomlContent += `
|
|
4148
4429
|
[capability.author]
|
|
4149
4430
|
`;
|
|
4150
4431
|
if (pluginMeta.author.name) {
|
|
4151
|
-
tomlContent += `name = "${pluginMeta.author.name}"
|
|
4432
|
+
tomlContent += `name = "${escapeTomlString(pluginMeta.author.name)}"
|
|
4152
4433
|
`;
|
|
4153
4434
|
}
|
|
4154
4435
|
if (pluginMeta.author.email) {
|
|
4155
|
-
tomlContent += `email = "${pluginMeta.author.email}"
|
|
4436
|
+
tomlContent += `email = "${escapeTomlString(pluginMeta.author.email)}"
|
|
4156
4437
|
`;
|
|
4157
4438
|
}
|
|
4158
4439
|
}
|
|
4159
4440
|
tomlContent += `
|
|
4160
4441
|
[capability.metadata]
|
|
4161
4442
|
wrapped = true
|
|
4162
|
-
source = "${source}"
|
|
4443
|
+
source = "${escapeTomlString(source)}"
|
|
4163
4444
|
`;
|
|
4164
|
-
await writeFile3(
|
|
4445
|
+
await writeFile3(join9(targetPath, "capability.toml"), tomlContent, "utf-8");
|
|
4165
4446
|
}
|
|
4166
4447
|
async function fetchCapabilitySource(id, sourceConfig, options) {
|
|
4167
4448
|
const config = parseSourceConfig(sourceConfig);
|
|
@@ -4234,16 +4515,16 @@ generated_from_omni_toml = true
|
|
|
4234
4515
|
}
|
|
4235
4516
|
async function generateMcpCapabilityToml(id, mcpConfig, targetPath) {
|
|
4236
4517
|
const tomlContent = generateMcpCapabilityTomlContent(id, mcpConfig);
|
|
4237
|
-
await writeFile3(
|
|
4518
|
+
await writeFile3(join9(targetPath, "capability.toml"), tomlContent, "utf-8");
|
|
4238
4519
|
}
|
|
4239
4520
|
async function isGeneratedMcpCapability(capabilityDir) {
|
|
4240
|
-
const tomlPath =
|
|
4241
|
-
if (!
|
|
4521
|
+
const tomlPath = join9(capabilityDir, "capability.toml");
|
|
4522
|
+
if (!existsSync13(tomlPath)) {
|
|
4242
4523
|
console.warn("no capability.toml found in", capabilityDir);
|
|
4243
4524
|
return false;
|
|
4244
4525
|
}
|
|
4245
4526
|
try {
|
|
4246
|
-
const content = await
|
|
4527
|
+
const content = await readFile10(tomlPath, "utf-8");
|
|
4247
4528
|
const parsed = parse(content);
|
|
4248
4529
|
const capability = parsed["capability"];
|
|
4249
4530
|
const metadata = capability?.["metadata"];
|
|
@@ -4253,14 +4534,14 @@ async function isGeneratedMcpCapability(capabilityDir) {
|
|
|
4253
4534
|
}
|
|
4254
4535
|
}
|
|
4255
4536
|
async function cleanupStaleMcpCapabilities(currentMcpIds) {
|
|
4256
|
-
const capabilitiesDir =
|
|
4257
|
-
if (!
|
|
4537
|
+
const capabilitiesDir = join9(OMNI_LOCAL, "capabilities");
|
|
4538
|
+
if (!existsSync13(capabilitiesDir)) {
|
|
4258
4539
|
return;
|
|
4259
4540
|
}
|
|
4260
4541
|
const entries = await readdir(capabilitiesDir, { withFileTypes: true });
|
|
4261
4542
|
for (const entry of entries) {
|
|
4262
4543
|
if (entry.isDirectory()) {
|
|
4263
|
-
const capDir =
|
|
4544
|
+
const capDir = join9(capabilitiesDir, entry.name);
|
|
4264
4545
|
const isGenerated = await isGeneratedMcpCapability(capDir);
|
|
4265
4546
|
if (isGenerated && !currentMcpIds.has(entry.name)) {
|
|
4266
4547
|
await rm(capDir, { recursive: true });
|
|
@@ -4273,10 +4554,10 @@ async function generateMcpCapabilities(config) {
|
|
|
4273
4554
|
await cleanupStaleMcpCapabilities(new Set);
|
|
4274
4555
|
return;
|
|
4275
4556
|
}
|
|
4276
|
-
const mcpCapabilitiesDir =
|
|
4557
|
+
const mcpCapabilitiesDir = join9(OMNI_LOCAL, "capabilities");
|
|
4277
4558
|
const currentMcpIds = new Set;
|
|
4278
4559
|
for (const [id, mcpConfig] of Object.entries(config.mcps)) {
|
|
4279
|
-
const targetPath =
|
|
4560
|
+
const targetPath = join9(mcpCapabilitiesDir, id);
|
|
4280
4561
|
currentMcpIds.add(id);
|
|
4281
4562
|
await mkdir(targetPath, { recursive: true });
|
|
4282
4563
|
await generateMcpCapabilityToml(id, mcpConfig, targetPath);
|
|
@@ -4285,8 +4566,8 @@ async function generateMcpCapabilities(config) {
|
|
|
4285
4566
|
}
|
|
4286
4567
|
async function fetchAllCapabilitySources(config, options) {
|
|
4287
4568
|
await generateMcpCapabilities(config);
|
|
4288
|
-
const tempDir =
|
|
4289
|
-
if (
|
|
4569
|
+
const tempDir = join9(OMNI_LOCAL, "_temp");
|
|
4570
|
+
if (existsSync13(tempDir)) {
|
|
4290
4571
|
await rm(tempDir, { recursive: true });
|
|
4291
4572
|
}
|
|
4292
4573
|
const sources = config.capabilities?.sources;
|
|
@@ -4372,7 +4653,7 @@ async function checkForUpdates(config) {
|
|
|
4372
4653
|
continue;
|
|
4373
4654
|
}
|
|
4374
4655
|
const gitConfig = sourceConfig;
|
|
4375
|
-
if (!
|
|
4656
|
+
if (!existsSync13(join9(targetPath, ".git"))) {
|
|
4376
4657
|
updates.push({
|
|
4377
4658
|
id,
|
|
4378
4659
|
source: gitConfig.source,
|
|
@@ -4415,12 +4696,12 @@ function checkVersionMismatch(lockEntry, currentCommit, currentVersion) {
|
|
|
4415
4696
|
}
|
|
4416
4697
|
async function verifyIntegrity(id, lockEntry) {
|
|
4417
4698
|
const capabilityPath = getSourceCapabilityPath(id);
|
|
4418
|
-
if (!
|
|
4699
|
+
if (!existsSync13(capabilityPath)) {
|
|
4419
4700
|
return "capability directory missing";
|
|
4420
4701
|
}
|
|
4421
4702
|
if (lockEntry.commit) {
|
|
4422
|
-
const gitDir =
|
|
4423
|
-
if (
|
|
4703
|
+
const gitDir = join9(capabilityPath, ".git");
|
|
4704
|
+
if (existsSync13(gitDir)) {
|
|
4424
4705
|
try {
|
|
4425
4706
|
const currentCommit = await getRepoCommit(capabilityPath);
|
|
4426
4707
|
if (currentCommit !== lockEntry.commit) {
|
|
@@ -4439,7 +4720,7 @@ async function verifyIntegrity(id, lockEntry) {
|
|
|
4439
4720
|
}
|
|
4440
4721
|
return null;
|
|
4441
4722
|
}
|
|
4442
|
-
var OMNI_LOCAL = ".omni", SKILL_DIRS, AGENT_DIRS, COMMAND_DIRS, RULE_DIRS, DOC_DIRS, SKILL_FILES, AGENT_FILES, COMMAND_FILES, CONTENT_HASH_EXCLUDES;
|
|
4723
|
+
var OMNI_LOCAL = ".omni", SKILL_DIRS, AGENT_DIRS, COMMAND_DIRS, RULE_DIRS, DOC_DIRS, WRAPPED_CONTENT_DIRS, WRAPPED_ROOT_FILES_EXACT, WRAPPED_ROOT_FILE_PATTERNS, SKILL_FILES, AGENT_FILES, COMMAND_FILES, CONTENT_HASH_EXCLUDES;
|
|
4443
4724
|
var init_sources = __esm(() => {
|
|
4444
4725
|
init_dist();
|
|
4445
4726
|
init_types2();
|
|
@@ -4448,6 +4729,23 @@ var init_sources = __esm(() => {
|
|
|
4448
4729
|
COMMAND_DIRS = ["commands", "command"];
|
|
4449
4730
|
RULE_DIRS = ["rules", "rule"];
|
|
4450
4731
|
DOC_DIRS = ["docs", "doc", "documentation"];
|
|
4732
|
+
WRAPPED_CONTENT_DIRS = new Set([
|
|
4733
|
+
...SKILL_DIRS,
|
|
4734
|
+
...AGENT_DIRS,
|
|
4735
|
+
...COMMAND_DIRS,
|
|
4736
|
+
...RULE_DIRS,
|
|
4737
|
+
...DOC_DIRS,
|
|
4738
|
+
"hooks",
|
|
4739
|
+
".claude-plugin"
|
|
4740
|
+
]);
|
|
4741
|
+
WRAPPED_ROOT_FILES_EXACT = new Set([".gitignore", "hooks.json"]);
|
|
4742
|
+
WRAPPED_ROOT_FILE_PATTERNS = [
|
|
4743
|
+
/^readme(?:\..+)?$/i,
|
|
4744
|
+
/^license(?:\..+)?$/i,
|
|
4745
|
+
/^licence(?:\..+)?$/i,
|
|
4746
|
+
/^notice(?:\..+)?$/i,
|
|
4747
|
+
/^copying(?:\..+)?$/i
|
|
4748
|
+
];
|
|
4451
4749
|
SKILL_FILES = ["SKILL.md", "skill.md", "Skill.md"];
|
|
4452
4750
|
AGENT_FILES = ["AGENT.md", "agent.md", "Agent.md", "SUBAGENT.md", "subagent.md"];
|
|
4453
4751
|
COMMAND_FILES = ["COMMAND.md", "command.md", "Command.md"];
|
|
@@ -4489,13 +4787,13 @@ var init_hooks = __esm(() => {
|
|
|
4489
4787
|
});
|
|
4490
4788
|
|
|
4491
4789
|
// ../core/src/config/provider.ts
|
|
4492
|
-
import { existsSync as
|
|
4493
|
-
import { readFile as
|
|
4790
|
+
import { existsSync as existsSync14 } from "node:fs";
|
|
4791
|
+
import { readFile as readFile11, writeFile as writeFile4 } from "node:fs/promises";
|
|
4494
4792
|
async function loadProviderConfig() {
|
|
4495
|
-
if (!
|
|
4793
|
+
if (!existsSync14(PROVIDER_CONFIG_PATH)) {
|
|
4496
4794
|
return { provider: "claude" };
|
|
4497
4795
|
}
|
|
4498
|
-
const content = await
|
|
4796
|
+
const content = await readFile11(PROVIDER_CONFIG_PATH, "utf-8");
|
|
4499
4797
|
const parsed = parse(content);
|
|
4500
4798
|
return parsed;
|
|
4501
4799
|
}
|
|
@@ -4542,13 +4840,13 @@ var init_provider = __esm(() => {
|
|
|
4542
4840
|
});
|
|
4543
4841
|
|
|
4544
4842
|
// ../core/src/config/toml-patcher.ts
|
|
4545
|
-
import { existsSync as
|
|
4546
|
-
import { readFile as
|
|
4843
|
+
import { existsSync as existsSync15 } from "node:fs";
|
|
4844
|
+
import { readFile as readFile12, writeFile as writeFile5 } from "node:fs/promises";
|
|
4547
4845
|
async function readConfigFile() {
|
|
4548
|
-
if (!
|
|
4846
|
+
if (!existsSync15(CONFIG_PATH2)) {
|
|
4549
4847
|
return "";
|
|
4550
4848
|
}
|
|
4551
|
-
return
|
|
4849
|
+
return readFile12(CONFIG_PATH2, "utf-8");
|
|
4552
4850
|
}
|
|
4553
4851
|
async function writeConfigFile(content) {
|
|
4554
4852
|
await writeFile5(CONFIG_PATH2, content, "utf-8");
|
|
@@ -4770,14 +5068,14 @@ var init_config2 = __esm(() => {
|
|
|
4770
5068
|
});
|
|
4771
5069
|
|
|
4772
5070
|
// ../core/src/mcp-json/manager.ts
|
|
4773
|
-
import { existsSync as
|
|
4774
|
-
import { readFile as
|
|
5071
|
+
import { existsSync as existsSync16 } from "node:fs";
|
|
5072
|
+
import { readFile as readFile13, writeFile as writeFile6 } from "node:fs/promises";
|
|
4775
5073
|
async function readMcpJson() {
|
|
4776
|
-
if (!
|
|
5074
|
+
if (!existsSync16(MCP_JSON_PATH)) {
|
|
4777
5075
|
return { mcpServers: {} };
|
|
4778
5076
|
}
|
|
4779
5077
|
try {
|
|
4780
|
-
const content = await
|
|
5078
|
+
const content = await readFile13(MCP_JSON_PATH, "utf-8");
|
|
4781
5079
|
const parsed = JSON.parse(content);
|
|
4782
5080
|
return {
|
|
4783
5081
|
mcpServers: parsed.mcpServers || {}
|
|
@@ -4859,17 +5157,17 @@ var init_mcp_json = __esm(() => {
|
|
|
4859
5157
|
});
|
|
4860
5158
|
|
|
4861
5159
|
// ../core/src/state/manifest.ts
|
|
4862
|
-
import { existsSync as
|
|
4863
|
-
import { readFile as
|
|
5160
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync2, rmSync } from "node:fs";
|
|
5161
|
+
import { readFile as readFile14, writeFile as writeFile7 } from "node:fs/promises";
|
|
4864
5162
|
async function loadManifest() {
|
|
4865
|
-
if (!
|
|
5163
|
+
if (!existsSync17(MANIFEST_PATH)) {
|
|
4866
5164
|
return {
|
|
4867
5165
|
version: CURRENT_VERSION,
|
|
4868
5166
|
syncedAt: new Date().toISOString(),
|
|
4869
5167
|
capabilities: {}
|
|
4870
5168
|
};
|
|
4871
5169
|
}
|
|
4872
|
-
const content = await
|
|
5170
|
+
const content = await readFile14(MANIFEST_PATH, "utf-8");
|
|
4873
5171
|
return JSON.parse(content);
|
|
4874
5172
|
}
|
|
4875
5173
|
async function saveManifest(manifest) {
|
|
@@ -4909,14 +5207,14 @@ async function cleanupStaleResources(previousManifest, currentCapabilityIds) {
|
|
|
4909
5207
|
}
|
|
4910
5208
|
for (const skillName of resources.skills) {
|
|
4911
5209
|
const skillDir = `.claude/skills/${skillName}`;
|
|
4912
|
-
if (
|
|
5210
|
+
if (existsSync17(skillDir)) {
|
|
4913
5211
|
rmSync(skillDir, { recursive: true });
|
|
4914
5212
|
result.deletedSkills.push(skillName);
|
|
4915
5213
|
}
|
|
4916
5214
|
}
|
|
4917
5215
|
for (const ruleName of resources.rules) {
|
|
4918
5216
|
const rulePath = `.cursor/rules/omnidev-${ruleName}.mdc`;
|
|
4919
|
-
if (
|
|
5217
|
+
if (existsSync17(rulePath)) {
|
|
4920
5218
|
rmSync(rulePath);
|
|
4921
5219
|
result.deletedRules.push(ruleName);
|
|
4922
5220
|
}
|
|
@@ -4928,14 +5226,14 @@ var MANIFEST_PATH = ".omni/state/manifest.json", CURRENT_VERSION = 1;
|
|
|
4928
5226
|
var init_manifest = () => {};
|
|
4929
5227
|
|
|
4930
5228
|
// ../core/src/state/providers.ts
|
|
4931
|
-
import { existsSync as
|
|
4932
|
-
import { readFile as
|
|
5229
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync3 } from "node:fs";
|
|
5230
|
+
import { readFile as readFile15, writeFile as writeFile8 } from "node:fs/promises";
|
|
4933
5231
|
async function readEnabledProviders() {
|
|
4934
|
-
if (!
|
|
5232
|
+
if (!existsSync18(PROVIDERS_PATH)) {
|
|
4935
5233
|
return DEFAULT_PROVIDERS;
|
|
4936
5234
|
}
|
|
4937
5235
|
try {
|
|
4938
|
-
const content = await
|
|
5236
|
+
const content = await readFile15(PROVIDERS_PATH, "utf-8");
|
|
4939
5237
|
const state = JSON.parse(content);
|
|
4940
5238
|
return state.enabled.length > 0 ? state.enabled : DEFAULT_PROVIDERS;
|
|
4941
5239
|
} catch {
|
|
@@ -4964,20 +5262,20 @@ async function isProviderEnabled(providerId) {
|
|
|
4964
5262
|
return current.includes(providerId);
|
|
4965
5263
|
}
|
|
4966
5264
|
var STATE_DIR2 = ".omni/state", PROVIDERS_PATH, DEFAULT_PROVIDERS;
|
|
4967
|
-
var
|
|
5265
|
+
var init_providers2 = __esm(() => {
|
|
4968
5266
|
PROVIDERS_PATH = `${STATE_DIR2}/providers.json`;
|
|
4969
5267
|
DEFAULT_PROVIDERS = ["claude-code"];
|
|
4970
5268
|
});
|
|
4971
5269
|
|
|
4972
5270
|
// ../core/src/state/security-allows.ts
|
|
4973
|
-
import { existsSync as
|
|
4974
|
-
import { readFile as
|
|
5271
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync4 } from "node:fs";
|
|
5272
|
+
import { readFile as readFile16, writeFile as writeFile9 } from "node:fs/promises";
|
|
4975
5273
|
async function readSecurityAllows() {
|
|
4976
|
-
if (!
|
|
5274
|
+
if (!existsSync19(SECURITY_PATH)) {
|
|
4977
5275
|
return { ...DEFAULT_STATE };
|
|
4978
5276
|
}
|
|
4979
5277
|
try {
|
|
4980
|
-
const content = await
|
|
5278
|
+
const content = await readFile16(SECURITY_PATH, "utf-8");
|
|
4981
5279
|
const state = JSON.parse(content);
|
|
4982
5280
|
return state;
|
|
4983
5281
|
} catch {
|
|
@@ -5066,7 +5364,7 @@ var init_security_allows = __esm(() => {
|
|
|
5066
5364
|
var init_state = __esm(() => {
|
|
5067
5365
|
init_active_profile();
|
|
5068
5366
|
init_manifest();
|
|
5069
|
-
|
|
5367
|
+
init_providers2();
|
|
5070
5368
|
init_security_allows();
|
|
5071
5369
|
});
|
|
5072
5370
|
|
|
@@ -5074,10 +5372,11 @@ var init_state = __esm(() => {
|
|
|
5074
5372
|
import { spawn as spawn2 } from "node:child_process";
|
|
5075
5373
|
import { mkdirSync as mkdirSync5 } from "node:fs";
|
|
5076
5374
|
async function installCapabilityDependencies(silent) {
|
|
5077
|
-
const { existsSync:
|
|
5078
|
-
const { join:
|
|
5375
|
+
const { existsSync: existsSync20, readdirSync: readdirSync7, readFileSync: readFileSync3 } = await import("node:fs");
|
|
5376
|
+
const { join: join10 } = await import("node:path");
|
|
5377
|
+
const { parse: parse2 } = await Promise.resolve().then(() => (init_dist(), exports_dist));
|
|
5079
5378
|
const capabilitiesDir = ".omni/capabilities";
|
|
5080
|
-
if (!
|
|
5379
|
+
if (!existsSync20(capabilitiesDir)) {
|
|
5081
5380
|
return;
|
|
5082
5381
|
}
|
|
5083
5382
|
const entries = readdirSync7(capabilitiesDir, { withFileTypes: true });
|
|
@@ -5097,45 +5396,26 @@ async function installCapabilityDependencies(silent) {
|
|
|
5097
5396
|
if (!entry.isDirectory()) {
|
|
5098
5397
|
continue;
|
|
5099
5398
|
}
|
|
5100
|
-
const capabilityPath =
|
|
5101
|
-
const packageJsonPath =
|
|
5102
|
-
|
|
5399
|
+
const capabilityPath = join10(capabilitiesDir, entry.name);
|
|
5400
|
+
const packageJsonPath = join10(capabilityPath, "package.json");
|
|
5401
|
+
const capabilityTomlPath = join10(capabilityPath, "capability.toml");
|
|
5402
|
+
if (!existsSync20(packageJsonPath)) {
|
|
5103
5403
|
continue;
|
|
5104
5404
|
}
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
|
|
5111
|
-
stdio: "pipe"
|
|
5112
|
-
});
|
|
5113
|
-
let stderr = "";
|
|
5114
|
-
proc.stderr?.on("data", (data) => {
|
|
5115
|
-
stderr += data.toString();
|
|
5116
|
-
});
|
|
5117
|
-
proc.on("close", (code) => {
|
|
5118
|
-
if (code === 0) {
|
|
5119
|
-
resolve2();
|
|
5120
|
-
} else {
|
|
5121
|
-
reject(new Error(`Failed to install dependencies for ${capabilityPath}:
|
|
5122
|
-
${stderr}`));
|
|
5405
|
+
if (existsSync20(capabilityTomlPath)) {
|
|
5406
|
+
try {
|
|
5407
|
+
const tomlContent = readFileSync3(capabilityTomlPath, "utf-8");
|
|
5408
|
+
const parsed = parse2(tomlContent);
|
|
5409
|
+
if (parsed.capability?.metadata?.wrapped === true) {
|
|
5410
|
+
continue;
|
|
5123
5411
|
}
|
|
5124
|
-
}
|
|
5125
|
-
|
|
5126
|
-
reject(error);
|
|
5127
|
-
});
|
|
5128
|
-
});
|
|
5129
|
-
const hasIndexTs = existsSync19(join9(capabilityPath, "index.ts"));
|
|
5130
|
-
let hasBuildScript = false;
|
|
5412
|
+
} catch {}
|
|
5413
|
+
}
|
|
5131
5414
|
try {
|
|
5132
|
-
const pkgJson = JSON.parse(readFileSync3(packageJsonPath, "utf-8"));
|
|
5133
|
-
hasBuildScript = Boolean(pkgJson.scripts?.build);
|
|
5134
|
-
} catch {}
|
|
5135
|
-
if (hasBuildScript) {
|
|
5136
5415
|
await new Promise((resolve2, reject) => {
|
|
5416
|
+
const useNpmCi = hasNpm && existsSync20(join10(capabilityPath, "package-lock.json"));
|
|
5137
5417
|
const cmd = hasBun ? "bun" : "npm";
|
|
5138
|
-
const args = ["
|
|
5418
|
+
const args = hasBun ? ["install"] : useNpmCi ? ["ci"] : ["install"];
|
|
5139
5419
|
const proc = spawn2(cmd, args, {
|
|
5140
5420
|
cwd: capabilityPath,
|
|
5141
5421
|
stdio: "pipe"
|
|
@@ -5148,7 +5428,7 @@ ${stderr}`));
|
|
|
5148
5428
|
if (code === 0) {
|
|
5149
5429
|
resolve2();
|
|
5150
5430
|
} else {
|
|
5151
|
-
reject(new Error(`Failed to
|
|
5431
|
+
reject(new Error(`Failed to install dependencies for ${capabilityPath}:
|
|
5152
5432
|
${stderr}`));
|
|
5153
5433
|
}
|
|
5154
5434
|
});
|
|
@@ -5156,12 +5436,46 @@ ${stderr}`));
|
|
|
5156
5436
|
reject(error);
|
|
5157
5437
|
});
|
|
5158
5438
|
});
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5439
|
+
const hasIndexTs = existsSync20(join10(capabilityPath, "index.ts"));
|
|
5440
|
+
let hasBuildScript = false;
|
|
5441
|
+
try {
|
|
5442
|
+
const pkgJson = JSON.parse(readFileSync3(packageJsonPath, "utf-8"));
|
|
5443
|
+
hasBuildScript = Boolean(pkgJson.scripts?.build);
|
|
5444
|
+
} catch {}
|
|
5445
|
+
if (hasBuildScript) {
|
|
5446
|
+
await new Promise((resolve2, reject) => {
|
|
5447
|
+
const cmd = hasBun ? "bun" : "npm";
|
|
5448
|
+
const args = ["run", "build"];
|
|
5449
|
+
const proc = spawn2(cmd, args, {
|
|
5450
|
+
cwd: capabilityPath,
|
|
5451
|
+
stdio: "pipe"
|
|
5452
|
+
});
|
|
5453
|
+
let stderr = "";
|
|
5454
|
+
proc.stderr?.on("data", (data) => {
|
|
5455
|
+
stderr += data.toString();
|
|
5456
|
+
});
|
|
5457
|
+
proc.on("close", (code) => {
|
|
5458
|
+
if (code === 0) {
|
|
5459
|
+
resolve2();
|
|
5460
|
+
} else {
|
|
5461
|
+
reject(new Error(`Failed to build capability ${capabilityPath}:
|
|
5462
|
+
${stderr}`));
|
|
5463
|
+
}
|
|
5464
|
+
});
|
|
5465
|
+
proc.on("error", (error) => {
|
|
5466
|
+
reject(error);
|
|
5467
|
+
});
|
|
5468
|
+
});
|
|
5469
|
+
} else if (hasIndexTs && !silent) {
|
|
5470
|
+
const hasBuiltIndex = existsSync20(join10(capabilityPath, "dist", "index.js"));
|
|
5471
|
+
if (!hasBuiltIndex) {
|
|
5472
|
+
console.warn(`Warning: Capability at ${capabilityPath} has index.ts but no build script.
|
|
5163
5473
|
Add a "build" script to package.json (e.g., "build": "tsc") to compile TypeScript.`);
|
|
5474
|
+
}
|
|
5164
5475
|
}
|
|
5476
|
+
} catch (error) {
|
|
5477
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
5478
|
+
console.warn(`Warning: ${errorMessage}`);
|
|
5165
5479
|
}
|
|
5166
5480
|
}
|
|
5167
5481
|
}
|
|
@@ -5296,13 +5610,13 @@ var init_types3 = __esm(() => {
|
|
|
5296
5610
|
});
|
|
5297
5611
|
|
|
5298
5612
|
// ../core/src/security/scanner.ts
|
|
5299
|
-
import { existsSync as
|
|
5300
|
-
import { lstat, readdir as readdir2, readFile as
|
|
5301
|
-
import { join as
|
|
5613
|
+
import { existsSync as existsSync20 } from "node:fs";
|
|
5614
|
+
import { lstat, readdir as readdir2, readFile as readFile17, readlink, realpath } from "node:fs/promises";
|
|
5615
|
+
import { join as join10, relative, resolve as resolve2 } from "node:path";
|
|
5302
5616
|
async function scanFileForUnicode(filePath, relativePath) {
|
|
5303
5617
|
const findings = [];
|
|
5304
5618
|
try {
|
|
5305
|
-
const content = await
|
|
5619
|
+
const content = await readFile17(filePath, "utf-8");
|
|
5306
5620
|
const lines = content.split(`
|
|
5307
5621
|
`);
|
|
5308
5622
|
for (let lineNum = 0;lineNum < lines.length; lineNum++) {
|
|
@@ -5356,7 +5670,7 @@ async function scanFileForUnicode(filePath, relativePath) {
|
|
|
5356
5670
|
async function scanFileForScripts(filePath, relativePath) {
|
|
5357
5671
|
const findings = [];
|
|
5358
5672
|
try {
|
|
5359
|
-
const content = await
|
|
5673
|
+
const content = await readFile17(filePath, "utf-8");
|
|
5360
5674
|
const lines = content.split(`
|
|
5361
5675
|
`);
|
|
5362
5676
|
for (let lineNum = 0;lineNum < lines.length; lineNum++) {
|
|
@@ -5382,7 +5696,7 @@ async function scanFileForScripts(filePath, relativePath) {
|
|
|
5382
5696
|
async function checkSymlink(symlinkPath, relativePath, capabilityRoot) {
|
|
5383
5697
|
try {
|
|
5384
5698
|
const linkTarget = await readlink(symlinkPath);
|
|
5385
|
-
const resolvedTarget = resolve2(
|
|
5699
|
+
const resolvedTarget = resolve2(join10(symlinkPath, "..", linkTarget));
|
|
5386
5700
|
const normalizedRoot = await realpath(capabilityRoot);
|
|
5387
5701
|
if (linkTarget.startsWith("/")) {
|
|
5388
5702
|
return {
|
|
@@ -5417,7 +5731,7 @@ function isTextFile(filePath) {
|
|
|
5417
5731
|
async function scanCapability(capabilityId, capabilityPath, settings = DEFAULT_SCAN_SETTINGS) {
|
|
5418
5732
|
const startTime = Date.now();
|
|
5419
5733
|
const findings = [];
|
|
5420
|
-
if (!
|
|
5734
|
+
if (!existsSync20(capabilityPath)) {
|
|
5421
5735
|
return {
|
|
5422
5736
|
capabilityId,
|
|
5423
5737
|
path: capabilityPath,
|
|
@@ -5429,7 +5743,7 @@ async function scanCapability(capabilityId, capabilityPath, settings = DEFAULT_S
|
|
|
5429
5743
|
async function scanDirectory(dirPath) {
|
|
5430
5744
|
const entries = await readdir2(dirPath, { withFileTypes: true });
|
|
5431
5745
|
for (const entry of entries) {
|
|
5432
|
-
const fullPath =
|
|
5746
|
+
const fullPath = join10(dirPath, entry.name);
|
|
5433
5747
|
const relativePath = relative(capabilityPath, fullPath);
|
|
5434
5748
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "__pycache__") {
|
|
5435
5749
|
continue;
|
|
@@ -5720,13 +6034,16 @@ function generateAgentsTemplate() {
|
|
|
5720
6034
|
}
|
|
5721
6035
|
|
|
5722
6036
|
// ../core/src/templates/capability.ts
|
|
6037
|
+
function escapeTomlString2(value) {
|
|
6038
|
+
return value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
|
|
6039
|
+
}
|
|
5723
6040
|
function generateCapabilityToml2(options) {
|
|
5724
6041
|
const description = options.description || "TODO: Add a description for your capability";
|
|
5725
6042
|
return `[capability]
|
|
5726
|
-
id = "${options.id}"
|
|
5727
|
-
name = "${options.name}"
|
|
6043
|
+
id = "${escapeTomlString2(options.id)}"
|
|
6044
|
+
name = "${escapeTomlString2(options.name)}"
|
|
5728
6045
|
version = "0.1.0"
|
|
5729
|
-
description = "${description}"
|
|
6046
|
+
description = "${escapeTomlString2(description)}"
|
|
5730
6047
|
|
|
5731
6048
|
# Optional author information
|
|
5732
6049
|
# [capability.author]
|
|
@@ -5919,6 +6236,8 @@ __export(exports_src, {
|
|
|
5919
6236
|
parseOmniConfig: () => parseOmniConfig,
|
|
5920
6237
|
parseFileSourcePath: () => parseFileSourcePath,
|
|
5921
6238
|
parseCapabilityConfig: () => parseCapabilityConfig,
|
|
6239
|
+
normalizeProviderId: () => normalizeProviderId,
|
|
6240
|
+
normalizeProviderApplicability: () => normalizeProviderApplicability,
|
|
5922
6241
|
mergeHooksConfigs: () => mergeHooksConfigs,
|
|
5923
6242
|
mergeAndDeduplicateHooks: () => mergeAndDeduplicateHooks,
|
|
5924
6243
|
loadSubagents: () => loadSubagents,
|
|
@@ -6026,6 +6345,7 @@ var init_src = __esm(() => {
|
|
|
6026
6345
|
init_state();
|
|
6027
6346
|
init_sync();
|
|
6028
6347
|
init_security();
|
|
6348
|
+
init_providers();
|
|
6029
6349
|
init_types2();
|
|
6030
6350
|
});
|
|
6031
6351
|
|
|
@@ -6033,17 +6353,17 @@ var init_src = __esm(() => {
|
|
|
6033
6353
|
import { run } from "@stricli/core";
|
|
6034
6354
|
|
|
6035
6355
|
// src/lib/dynamic-app.ts
|
|
6036
|
-
import { existsSync as
|
|
6356
|
+
import { existsSync as existsSync30 } from "node:fs";
|
|
6037
6357
|
import { createRequire as createRequire2 } from "node:module";
|
|
6038
|
-
import { join as
|
|
6358
|
+
import { join as join27 } from "node:path";
|
|
6039
6359
|
import { buildApplication, buildRouteMap as buildRouteMap7 } from "@stricli/core";
|
|
6040
6360
|
|
|
6041
6361
|
// src/commands/add.ts
|
|
6042
|
-
import { existsSync as
|
|
6362
|
+
import { existsSync as existsSync23 } from "node:fs";
|
|
6043
6363
|
import { basename as basename5, resolve as resolve3 } from "node:path";
|
|
6044
6364
|
|
|
6045
6365
|
// ../adapters/src/writers/generic/executor.ts
|
|
6046
|
-
async function executeWriters(writerConfigs, bundle, projectRoot) {
|
|
6366
|
+
async function executeWriters(writerConfigs, bundle, projectRoot, providerId) {
|
|
6047
6367
|
const seen = new Set;
|
|
6048
6368
|
const uniqueConfigs = [];
|
|
6049
6369
|
let deduplicatedCount = 0;
|
|
@@ -6060,7 +6380,8 @@ async function executeWriters(writerConfigs, bundle, projectRoot) {
|
|
|
6060
6380
|
for (const config of uniqueConfigs) {
|
|
6061
6381
|
const result = await config.writer.write(bundle, {
|
|
6062
6382
|
outputPath: config.outputPath,
|
|
6063
|
-
projectRoot
|
|
6383
|
+
projectRoot,
|
|
6384
|
+
...providerId ? { providerId } : {}
|
|
6064
6385
|
});
|
|
6065
6386
|
allFilesWritten.push(...result.filesWritten);
|
|
6066
6387
|
}
|
|
@@ -6071,23 +6392,23 @@ async function executeWriters(writerConfigs, bundle, projectRoot) {
|
|
|
6071
6392
|
}
|
|
6072
6393
|
// ../adapters/src/writers/generic/hooks.ts
|
|
6073
6394
|
init_src();
|
|
6074
|
-
import { existsSync as
|
|
6075
|
-
import { mkdir as mkdir2, readFile as
|
|
6076
|
-
import { dirname, join as
|
|
6395
|
+
import { existsSync as existsSync21 } from "node:fs";
|
|
6396
|
+
import { mkdir as mkdir2, readFile as readFile18, writeFile as writeFile10 } from "node:fs/promises";
|
|
6397
|
+
import { dirname, join as join11 } from "node:path";
|
|
6077
6398
|
var HooksWriter = {
|
|
6078
6399
|
id: "hooks",
|
|
6079
6400
|
async write(bundle, ctx) {
|
|
6080
6401
|
if (!bundle.hooks) {
|
|
6081
6402
|
return { filesWritten: [] };
|
|
6082
6403
|
}
|
|
6083
|
-
const settingsPath =
|
|
6404
|
+
const settingsPath = join11(ctx.projectRoot, ctx.outputPath);
|
|
6084
6405
|
const parentDir = dirname(settingsPath);
|
|
6085
6406
|
await mkdir2(parentDir, { recursive: true });
|
|
6086
6407
|
const claudeHooks = transformHooksConfig(bundle.hooks, "toClaude");
|
|
6087
6408
|
let existingSettings = {};
|
|
6088
|
-
if (
|
|
6409
|
+
if (existsSync21(settingsPath)) {
|
|
6089
6410
|
try {
|
|
6090
|
-
const content = await
|
|
6411
|
+
const content = await readFile18(settingsPath, "utf-8");
|
|
6091
6412
|
existingSettings = JSON.parse(content);
|
|
6092
6413
|
} catch {
|
|
6093
6414
|
existingSettings = {};
|
|
@@ -6105,21 +6426,42 @@ var HooksWriter = {
|
|
|
6105
6426
|
}
|
|
6106
6427
|
};
|
|
6107
6428
|
// ../adapters/src/writers/generic/instructions-md.ts
|
|
6108
|
-
import { existsSync as
|
|
6109
|
-
import { mkdir as mkdir3, readFile as
|
|
6110
|
-
import { dirname as dirname2, join as
|
|
6429
|
+
import { existsSync as existsSync22 } from "node:fs";
|
|
6430
|
+
import { mkdir as mkdir3, readFile as readFile19, writeFile as writeFile11 } from "node:fs/promises";
|
|
6431
|
+
import { dirname as dirname2, join as join12 } from "node:path";
|
|
6432
|
+
|
|
6433
|
+
// ../adapters/src/writers/generic/omni-md.ts
|
|
6434
|
+
init_src();
|
|
6435
|
+
var PROVIDER_BLOCK_REGEX = /<provider\.([a-z-]+)>([\s\S]*?)<\/provider\.\1>/g;
|
|
6436
|
+
var PROVIDER_TAG_REGEX = /<\/?provider\.[a-z-]+>/;
|
|
6437
|
+
function renderOmniMdForProvider(content, providerId) {
|
|
6438
|
+
if (!providerId) {
|
|
6439
|
+
return content;
|
|
6440
|
+
}
|
|
6441
|
+
const rendered = content.replace(PROVIDER_BLOCK_REGEX, (_match, rawProvider, providerContent) => {
|
|
6442
|
+
const canonicalProvider = normalizeProviderId(rawProvider);
|
|
6443
|
+
return canonicalProvider === providerId ? providerContent : "";
|
|
6444
|
+
});
|
|
6445
|
+
const strayTag = rendered.match(PROVIDER_TAG_REGEX);
|
|
6446
|
+
if (strayTag) {
|
|
6447
|
+
throw new Error(`Invalid provider block syntax in OMNI.md near ${strayTag[0]}`);
|
|
6448
|
+
}
|
|
6449
|
+
return rendered;
|
|
6450
|
+
}
|
|
6451
|
+
|
|
6452
|
+
// ../adapters/src/writers/generic/instructions-md.ts
|
|
6111
6453
|
var InstructionsMdWriter = {
|
|
6112
6454
|
id: "instructions-md",
|
|
6113
6455
|
async write(bundle, ctx) {
|
|
6114
|
-
const outputFullPath =
|
|
6456
|
+
const outputFullPath = join12(ctx.projectRoot, ctx.outputPath);
|
|
6115
6457
|
const parentDir = dirname2(outputFullPath);
|
|
6116
6458
|
if (parentDir !== ctx.projectRoot) {
|
|
6117
6459
|
await mkdir3(parentDir, { recursive: true });
|
|
6118
6460
|
}
|
|
6119
|
-
const omniMdPath =
|
|
6461
|
+
const omniMdPath = join12(ctx.projectRoot, "OMNI.md");
|
|
6120
6462
|
let omniMdContent = "";
|
|
6121
|
-
if (
|
|
6122
|
-
omniMdContent = await
|
|
6463
|
+
if (existsSync22(omniMdPath)) {
|
|
6464
|
+
omniMdContent = renderOmniMdForProvider(await readFile19(omniMdPath, "utf-8"), ctx.providerId);
|
|
6123
6465
|
}
|
|
6124
6466
|
let content = omniMdContent;
|
|
6125
6467
|
if (bundle.instructionsContent) {
|
|
@@ -6136,17 +6478,17 @@ ${bundle.instructionsContent}
|
|
|
6136
6478
|
};
|
|
6137
6479
|
// ../adapters/src/writers/generic/skills.ts
|
|
6138
6480
|
import { mkdir as mkdir4, writeFile as writeFile12 } from "node:fs/promises";
|
|
6139
|
-
import { join as
|
|
6481
|
+
import { join as join13 } from "node:path";
|
|
6140
6482
|
var SkillsWriter = {
|
|
6141
6483
|
id: "skills",
|
|
6142
6484
|
async write(bundle, ctx) {
|
|
6143
|
-
const skillsDir =
|
|
6485
|
+
const skillsDir = join13(ctx.projectRoot, ctx.outputPath);
|
|
6144
6486
|
await mkdir4(skillsDir, { recursive: true });
|
|
6145
6487
|
const filesWritten = [];
|
|
6146
6488
|
for (const skill of bundle.skills) {
|
|
6147
|
-
const skillDir =
|
|
6489
|
+
const skillDir = join13(skillsDir, skill.name);
|
|
6148
6490
|
await mkdir4(skillDir, { recursive: true });
|
|
6149
|
-
const skillPath =
|
|
6491
|
+
const skillPath = join13(skillDir, "SKILL.md");
|
|
6150
6492
|
const content = `---
|
|
6151
6493
|
name: ${skill.name}
|
|
6152
6494
|
description: "${skill.description}"
|
|
@@ -6154,7 +6496,7 @@ description: "${skill.description}"
|
|
|
6154
6496
|
|
|
6155
6497
|
${skill.instructions}`;
|
|
6156
6498
|
await writeFile12(skillPath, content, "utf-8");
|
|
6157
|
-
filesWritten.push(
|
|
6499
|
+
filesWritten.push(join13(ctx.outputPath, skill.name, "SKILL.md"));
|
|
6158
6500
|
}
|
|
6159
6501
|
return {
|
|
6160
6502
|
filesWritten
|
|
@@ -6163,7 +6505,7 @@ ${skill.instructions}`;
|
|
|
6163
6505
|
};
|
|
6164
6506
|
// ../adapters/src/writers/generic/commands-as-skills.ts
|
|
6165
6507
|
import { mkdir as mkdir5, writeFile as writeFile13 } from "node:fs/promises";
|
|
6166
|
-
import { join as
|
|
6508
|
+
import { join as join14 } from "node:path";
|
|
6167
6509
|
function generateSkillFrontmatter(command) {
|
|
6168
6510
|
const lines = ["---"];
|
|
6169
6511
|
lines.push(`name: ${command.name}`);
|
|
@@ -6178,28 +6520,75 @@ function generateSkillFrontmatter(command) {
|
|
|
6178
6520
|
var CommandsAsSkillsWriter = {
|
|
6179
6521
|
id: "commands-as-skills",
|
|
6180
6522
|
async write(bundle, ctx) {
|
|
6181
|
-
const skillsDir =
|
|
6523
|
+
const skillsDir = join14(ctx.projectRoot, ctx.outputPath);
|
|
6182
6524
|
await mkdir5(skillsDir, { recursive: true });
|
|
6183
6525
|
const filesWritten = [];
|
|
6184
6526
|
for (const command of bundle.commands) {
|
|
6185
|
-
const commandSkillDir =
|
|
6527
|
+
const commandSkillDir = join14(skillsDir, command.name);
|
|
6186
6528
|
await mkdir5(commandSkillDir, { recursive: true });
|
|
6187
6529
|
const frontmatter = generateSkillFrontmatter(command);
|
|
6188
6530
|
const content = `${frontmatter}
|
|
6189
6531
|
|
|
6190
6532
|
${command.prompt}`;
|
|
6191
|
-
const skillPath =
|
|
6533
|
+
const skillPath = join14(commandSkillDir, "SKILL.md");
|
|
6192
6534
|
await writeFile13(skillPath, content, "utf-8");
|
|
6193
|
-
filesWritten.push(
|
|
6535
|
+
filesWritten.push(join14(ctx.outputPath, command.name, "SKILL.md"));
|
|
6194
6536
|
}
|
|
6195
6537
|
return {
|
|
6196
6538
|
filesWritten
|
|
6197
6539
|
};
|
|
6198
6540
|
}
|
|
6199
6541
|
};
|
|
6542
|
+
// ../adapters/src/provider-bundle.ts
|
|
6543
|
+
init_src();
|
|
6544
|
+
function capabilityAppliesToProvider(capability3, providerId) {
|
|
6545
|
+
const providers3 = capability3.config.capability.providers;
|
|
6546
|
+
if (!providers3) {
|
|
6547
|
+
return true;
|
|
6548
|
+
}
|
|
6549
|
+
return providers3[providerId] === true;
|
|
6550
|
+
}
|
|
6551
|
+
function generateInstructionsContent2(rules, _docs) {
|
|
6552
|
+
if (rules.length === 0) {
|
|
6553
|
+
return "";
|
|
6554
|
+
}
|
|
6555
|
+
let content = `## Rules
|
|
6556
|
+
|
|
6557
|
+
`;
|
|
6558
|
+
for (const rule of rules) {
|
|
6559
|
+
content += `${rule.content}
|
|
6560
|
+
|
|
6561
|
+
`;
|
|
6562
|
+
}
|
|
6563
|
+
return content.trimEnd();
|
|
6564
|
+
}
|
|
6565
|
+
function createProviderScopedBundle(bundle, providerId) {
|
|
6566
|
+
const capabilities2 = bundle.capabilities.filter((capability3) => capabilityAppliesToProvider(capability3, providerId));
|
|
6567
|
+
const capabilityIds = new Set(capabilities2.map((capability3) => capability3.id));
|
|
6568
|
+
const skills = bundle.skills.filter((skill) => capabilityIds.has(skill.capabilityId));
|
|
6569
|
+
const rules = bundle.rules.filter((rule) => capabilityIds.has(rule.capabilityId));
|
|
6570
|
+
const docs = bundle.docs.filter((doc) => capabilityIds.has(doc.capabilityId));
|
|
6571
|
+
const commands = bundle.commands.filter((command) => capabilityIds.has(command.capabilityId));
|
|
6572
|
+
const subagents = bundle.subagents.filter((subagent) => capabilityIds.has(subagent.capabilityId));
|
|
6573
|
+
const scopedBundle = {
|
|
6574
|
+
capabilities: capabilities2,
|
|
6575
|
+
skills,
|
|
6576
|
+
rules,
|
|
6577
|
+
docs,
|
|
6578
|
+
commands,
|
|
6579
|
+
subagents,
|
|
6580
|
+
instructionsContent: generateInstructionsContent2(rules, docs)
|
|
6581
|
+
};
|
|
6582
|
+
const mergedHooks = mergeHooksConfigs(capabilities2.flatMap((capability3) => capability3.hooks ? [capability3.hooks] : []));
|
|
6583
|
+
if (hasAnyHooks(mergedHooks)) {
|
|
6584
|
+
scopedBundle.hooks = mergedHooks;
|
|
6585
|
+
}
|
|
6586
|
+
return scopedBundle;
|
|
6587
|
+
}
|
|
6588
|
+
|
|
6200
6589
|
// ../adapters/src/writers/claude/agents.ts
|
|
6201
6590
|
import { mkdir as mkdir6, writeFile as writeFile14 } from "node:fs/promises";
|
|
6202
|
-
import { join as
|
|
6591
|
+
import { join as join15 } from "node:path";
|
|
6203
6592
|
function generateFrontmatter(agent) {
|
|
6204
6593
|
const lines = ["---"];
|
|
6205
6594
|
lines.push(`name: ${agent.name}`);
|
|
@@ -6226,7 +6615,7 @@ function generateFrontmatter(agent) {
|
|
|
6226
6615
|
var ClaudeAgentsWriter = {
|
|
6227
6616
|
id: "claude-agents",
|
|
6228
6617
|
async write(bundle, ctx) {
|
|
6229
|
-
const agentsDir =
|
|
6618
|
+
const agentsDir = join15(ctx.projectRoot, ctx.outputPath);
|
|
6230
6619
|
await mkdir6(agentsDir, { recursive: true });
|
|
6231
6620
|
const filesWritten = [];
|
|
6232
6621
|
for (const agent of bundle.subagents) {
|
|
@@ -6234,9 +6623,9 @@ var ClaudeAgentsWriter = {
|
|
|
6234
6623
|
const content = `${frontmatter}
|
|
6235
6624
|
|
|
6236
6625
|
${agent.systemPrompt}`;
|
|
6237
|
-
const agentPath =
|
|
6626
|
+
const agentPath = join15(agentsDir, `${agent.name}.md`);
|
|
6238
6627
|
await writeFile14(agentPath, content, "utf-8");
|
|
6239
|
-
filesWritten.push(
|
|
6628
|
+
filesWritten.push(join15(ctx.outputPath, `${agent.name}.md`));
|
|
6240
6629
|
}
|
|
6241
6630
|
return {
|
|
6242
6631
|
filesWritten
|
|
@@ -6261,7 +6650,9 @@ var claudeCodeAdapter = {
|
|
|
6261
6650
|
};
|
|
6262
6651
|
},
|
|
6263
6652
|
async sync(bundle, ctx) {
|
|
6264
|
-
const
|
|
6653
|
+
const providerId = "claude-code";
|
|
6654
|
+
const providerBundle = createProviderScopedBundle(bundle, providerId);
|
|
6655
|
+
const result = await executeWriters(this.writers, providerBundle, ctx.projectRoot, providerId);
|
|
6265
6656
|
return {
|
|
6266
6657
|
filesWritten: result.filesWritten,
|
|
6267
6658
|
filesDeleted: []
|
|
@@ -6270,12 +6661,12 @@ var claudeCodeAdapter = {
|
|
|
6270
6661
|
};
|
|
6271
6662
|
// ../adapters/src/codex/index.ts
|
|
6272
6663
|
import { mkdirSync as mkdirSync6 } from "node:fs";
|
|
6273
|
-
import { join as
|
|
6664
|
+
import { join as join17 } from "node:path";
|
|
6274
6665
|
|
|
6275
6666
|
// ../adapters/src/writers/codex/toml.ts
|
|
6276
6667
|
init_dist();
|
|
6277
6668
|
import { mkdir as mkdir7, writeFile as writeFile15 } from "node:fs/promises";
|
|
6278
|
-
import { dirname as dirname3, join as
|
|
6669
|
+
import { dirname as dirname3, join as join16 } from "node:path";
|
|
6279
6670
|
var FILE_HEADER = `# Generated by OmniDev - DO NOT EDIT
|
|
6280
6671
|
# Run \`omnidev sync\` to regenerate
|
|
6281
6672
|
|
|
@@ -6326,7 +6717,7 @@ var CodexTomlWriter = {
|
|
|
6326
6717
|
if (mcps.size === 0) {
|
|
6327
6718
|
return { filesWritten: [] };
|
|
6328
6719
|
}
|
|
6329
|
-
const configPath =
|
|
6720
|
+
const configPath = join16(ctx.projectRoot, ctx.outputPath);
|
|
6330
6721
|
const parentDir = dirname3(configPath);
|
|
6331
6722
|
await mkdir7(parentDir, { recursive: true });
|
|
6332
6723
|
const mcpServers = {};
|
|
@@ -6360,7 +6751,7 @@ var codexAdapter = {
|
|
|
6360
6751
|
{ writer: CodexTomlWriter, outputPath: ".codex/config.toml" }
|
|
6361
6752
|
],
|
|
6362
6753
|
async init(ctx) {
|
|
6363
|
-
const codexDir =
|
|
6754
|
+
const codexDir = join17(ctx.projectRoot, ".codex");
|
|
6364
6755
|
mkdirSync6(codexDir, { recursive: true });
|
|
6365
6756
|
return {
|
|
6366
6757
|
filesCreated: [".codex/"],
|
|
@@ -6368,7 +6759,9 @@ var codexAdapter = {
|
|
|
6368
6759
|
};
|
|
6369
6760
|
},
|
|
6370
6761
|
async sync(bundle, ctx) {
|
|
6371
|
-
const
|
|
6762
|
+
const providerId = "codex";
|
|
6763
|
+
const providerBundle = createProviderScopedBundle(bundle, providerId);
|
|
6764
|
+
const result = await executeWriters(this.writers, providerBundle, ctx.projectRoot, providerId);
|
|
6372
6765
|
return {
|
|
6373
6766
|
filesWritten: result.filesWritten,
|
|
6374
6767
|
filesDeleted: []
|
|
@@ -6377,11 +6770,11 @@ var codexAdapter = {
|
|
|
6377
6770
|
};
|
|
6378
6771
|
// ../adapters/src/cursor/index.ts
|
|
6379
6772
|
import { mkdirSync as mkdirSync7 } from "node:fs";
|
|
6380
|
-
import { join as
|
|
6773
|
+
import { join as join22 } from "node:path";
|
|
6381
6774
|
|
|
6382
6775
|
// ../adapters/src/writers/cursor/agents.ts
|
|
6383
6776
|
import { mkdir as mkdir8, writeFile as writeFile16 } from "node:fs/promises";
|
|
6384
|
-
import { join as
|
|
6777
|
+
import { join as join18 } from "node:path";
|
|
6385
6778
|
function mapModelToCursor(model) {
|
|
6386
6779
|
if (!model || model === "inherit")
|
|
6387
6780
|
return "inherit";
|
|
@@ -6413,7 +6806,7 @@ function generateFrontmatter2(agent) {
|
|
|
6413
6806
|
var CursorAgentsWriter = {
|
|
6414
6807
|
id: "cursor-agents",
|
|
6415
6808
|
async write(bundle, ctx) {
|
|
6416
|
-
const agentsDir =
|
|
6809
|
+
const agentsDir = join18(ctx.projectRoot, ctx.outputPath);
|
|
6417
6810
|
await mkdir8(agentsDir, { recursive: true });
|
|
6418
6811
|
const filesWritten = [];
|
|
6419
6812
|
for (const agent of bundle.subagents) {
|
|
@@ -6421,9 +6814,9 @@ var CursorAgentsWriter = {
|
|
|
6421
6814
|
const content = `${frontmatter}
|
|
6422
6815
|
|
|
6423
6816
|
${agent.systemPrompt}`;
|
|
6424
|
-
const agentPath =
|
|
6817
|
+
const agentPath = join18(agentsDir, `${agent.name}.md`);
|
|
6425
6818
|
await writeFile16(agentPath, content, "utf-8");
|
|
6426
|
-
filesWritten.push(
|
|
6819
|
+
filesWritten.push(join18(ctx.outputPath, `${agent.name}.md`));
|
|
6427
6820
|
}
|
|
6428
6821
|
return {
|
|
6429
6822
|
filesWritten
|
|
@@ -6432,11 +6825,11 @@ ${agent.systemPrompt}`;
|
|
|
6432
6825
|
};
|
|
6433
6826
|
// ../adapters/src/writers/cursor/commands.ts
|
|
6434
6827
|
import { mkdir as mkdir9, writeFile as writeFile17 } from "node:fs/promises";
|
|
6435
|
-
import { join as
|
|
6828
|
+
import { join as join19 } from "node:path";
|
|
6436
6829
|
var CursorCommandsWriter = {
|
|
6437
6830
|
id: "cursor-commands",
|
|
6438
6831
|
async write(bundle, ctx) {
|
|
6439
|
-
const commandsDir =
|
|
6832
|
+
const commandsDir = join19(ctx.projectRoot, ctx.outputPath);
|
|
6440
6833
|
await mkdir9(commandsDir, { recursive: true });
|
|
6441
6834
|
const filesWritten = [];
|
|
6442
6835
|
for (const command of bundle.commands) {
|
|
@@ -6445,9 +6838,9 @@ var CursorCommandsWriter = {
|
|
|
6445
6838
|
${command.description}
|
|
6446
6839
|
|
|
6447
6840
|
${command.prompt}`;
|
|
6448
|
-
const commandPath =
|
|
6841
|
+
const commandPath = join19(commandsDir, `${command.name}.md`);
|
|
6449
6842
|
await writeFile17(commandPath, content, "utf-8");
|
|
6450
|
-
filesWritten.push(
|
|
6843
|
+
filesWritten.push(join19(ctx.outputPath, `${command.name}.md`));
|
|
6451
6844
|
}
|
|
6452
6845
|
return {
|
|
6453
6846
|
filesWritten
|
|
@@ -6456,7 +6849,7 @@ ${command.prompt}`;
|
|
|
6456
6849
|
};
|
|
6457
6850
|
// ../adapters/src/writers/cursor/mcp-json.ts
|
|
6458
6851
|
import { mkdir as mkdir10, writeFile as writeFile18 } from "node:fs/promises";
|
|
6459
|
-
import { dirname as dirname4, join as
|
|
6852
|
+
import { dirname as dirname4, join as join20 } from "node:path";
|
|
6460
6853
|
function buildCursorMcpConfig(mcp) {
|
|
6461
6854
|
const transport = mcp.transport ?? "stdio";
|
|
6462
6855
|
if (transport === "http" || transport === "sse") {
|
|
@@ -6501,7 +6894,7 @@ var CursorMcpJsonWriter = {
|
|
|
6501
6894
|
if (mcps.size === 0) {
|
|
6502
6895
|
return { filesWritten: [] };
|
|
6503
6896
|
}
|
|
6504
|
-
const configPath =
|
|
6897
|
+
const configPath = join20(ctx.projectRoot, ctx.outputPath);
|
|
6505
6898
|
const parentDir = dirname4(configPath);
|
|
6506
6899
|
await mkdir10(parentDir, { recursive: true });
|
|
6507
6900
|
const mcpServers = {};
|
|
@@ -6526,17 +6919,17 @@ var CursorMcpJsonWriter = {
|
|
|
6526
6919
|
};
|
|
6527
6920
|
// ../adapters/src/writers/cursor/rules.ts
|
|
6528
6921
|
import { mkdir as mkdir11, writeFile as writeFile19 } from "node:fs/promises";
|
|
6529
|
-
import { join as
|
|
6922
|
+
import { join as join21 } from "node:path";
|
|
6530
6923
|
var CursorRulesWriter = {
|
|
6531
6924
|
id: "cursor-rules",
|
|
6532
6925
|
async write(bundle, ctx) {
|
|
6533
|
-
const rulesDir =
|
|
6926
|
+
const rulesDir = join21(ctx.projectRoot, ctx.outputPath);
|
|
6534
6927
|
await mkdir11(rulesDir, { recursive: true });
|
|
6535
6928
|
const filesWritten = [];
|
|
6536
6929
|
for (const rule of bundle.rules) {
|
|
6537
|
-
const rulePath =
|
|
6930
|
+
const rulePath = join21(rulesDir, `omnidev-${rule.name}.mdc`);
|
|
6538
6931
|
await writeFile19(rulePath, rule.content, "utf-8");
|
|
6539
|
-
filesWritten.push(
|
|
6932
|
+
filesWritten.push(join21(ctx.outputPath, `omnidev-${rule.name}.mdc`));
|
|
6540
6933
|
}
|
|
6541
6934
|
return {
|
|
6542
6935
|
filesWritten
|
|
@@ -6556,7 +6949,7 @@ var cursorAdapter = {
|
|
|
6556
6949
|
{ writer: CursorMcpJsonWriter, outputPath: ".cursor/mcp.json" }
|
|
6557
6950
|
],
|
|
6558
6951
|
async init(ctx) {
|
|
6559
|
-
const rulesDir =
|
|
6952
|
+
const rulesDir = join22(ctx.projectRoot, ".cursor", "rules");
|
|
6560
6953
|
mkdirSync7(rulesDir, { recursive: true });
|
|
6561
6954
|
return {
|
|
6562
6955
|
filesCreated: [".cursor/rules/"],
|
|
@@ -6564,20 +6957,29 @@ var cursorAdapter = {
|
|
|
6564
6957
|
};
|
|
6565
6958
|
},
|
|
6566
6959
|
async sync(bundle, ctx) {
|
|
6567
|
-
const
|
|
6960
|
+
const cursorProviderId = "cursor";
|
|
6961
|
+
const instructionsProviderId = "claude-code";
|
|
6962
|
+
const instructionsWriters = this.writers.filter((config3) => config3.writer.id === "instructions-md");
|
|
6963
|
+
const cursorWriters = this.writers.filter((config3) => config3.writer.id !== "instructions-md");
|
|
6964
|
+
const instructionsBundle = createProviderScopedBundle(bundle, instructionsProviderId);
|
|
6965
|
+
const cursorBundle = createProviderScopedBundle(bundle, cursorProviderId);
|
|
6966
|
+
const instructionsResult = await executeWriters(instructionsWriters, instructionsBundle, ctx.projectRoot, instructionsProviderId);
|
|
6967
|
+
const cursorResult = await executeWriters(cursorWriters, cursorBundle, ctx.projectRoot, cursorProviderId);
|
|
6568
6968
|
return {
|
|
6569
|
-
filesWritten:
|
|
6969
|
+
filesWritten: [
|
|
6970
|
+
...new Set([...instructionsResult.filesWritten, ...cursorResult.filesWritten])
|
|
6971
|
+
],
|
|
6570
6972
|
filesDeleted: []
|
|
6571
6973
|
};
|
|
6572
6974
|
}
|
|
6573
6975
|
};
|
|
6574
6976
|
// ../adapters/src/opencode/index.ts
|
|
6575
6977
|
import { mkdirSync as mkdirSync8 } from "node:fs";
|
|
6576
|
-
import { join as
|
|
6978
|
+
import { join as join25 } from "node:path";
|
|
6577
6979
|
|
|
6578
6980
|
// ../adapters/src/writers/opencode/agents.ts
|
|
6579
6981
|
import { mkdir as mkdir12, writeFile as writeFile20 } from "node:fs/promises";
|
|
6580
|
-
import { join as
|
|
6982
|
+
import { join as join23 } from "node:path";
|
|
6581
6983
|
function mapModelToOpenCode(model) {
|
|
6582
6984
|
if (!model || model === "inherit")
|
|
6583
6985
|
return;
|
|
@@ -6655,7 +7057,7 @@ function generateFrontmatter3(agent) {
|
|
|
6655
7057
|
var OpenCodeAgentsWriter = {
|
|
6656
7058
|
id: "opencode-agents",
|
|
6657
7059
|
async write(bundle, ctx) {
|
|
6658
|
-
const agentsDir =
|
|
7060
|
+
const agentsDir = join23(ctx.projectRoot, ctx.outputPath);
|
|
6659
7061
|
await mkdir12(agentsDir, { recursive: true });
|
|
6660
7062
|
const filesWritten = [];
|
|
6661
7063
|
for (const agent of bundle.subagents) {
|
|
@@ -6663,9 +7065,9 @@ var OpenCodeAgentsWriter = {
|
|
|
6663
7065
|
const content = `${frontmatter}
|
|
6664
7066
|
|
|
6665
7067
|
${agent.systemPrompt}`;
|
|
6666
|
-
const agentPath =
|
|
7068
|
+
const agentPath = join23(agentsDir, `${agent.name}.md`);
|
|
6667
7069
|
await writeFile20(agentPath, content, "utf-8");
|
|
6668
|
-
filesWritten.push(
|
|
7070
|
+
filesWritten.push(join23(ctx.outputPath, `${agent.name}.md`));
|
|
6669
7071
|
}
|
|
6670
7072
|
return {
|
|
6671
7073
|
filesWritten
|
|
@@ -6674,7 +7076,7 @@ ${agent.systemPrompt}`;
|
|
|
6674
7076
|
};
|
|
6675
7077
|
// ../adapters/src/writers/opencode/commands.ts
|
|
6676
7078
|
import { mkdir as mkdir13, writeFile as writeFile21 } from "node:fs/promises";
|
|
6677
|
-
import { join as
|
|
7079
|
+
import { join as join24 } from "node:path";
|
|
6678
7080
|
function generateFrontmatter4(command) {
|
|
6679
7081
|
const lines = ["---"];
|
|
6680
7082
|
lines.push(`description: "${command.description.replace(/"/g, "\\\"")}"`);
|
|
@@ -6691,7 +7093,7 @@ function generateFrontmatter4(command) {
|
|
|
6691
7093
|
var OpenCodeCommandsWriter = {
|
|
6692
7094
|
id: "opencode-commands",
|
|
6693
7095
|
async write(bundle, ctx) {
|
|
6694
|
-
const commandsDir =
|
|
7096
|
+
const commandsDir = join24(ctx.projectRoot, ctx.outputPath);
|
|
6695
7097
|
await mkdir13(commandsDir, { recursive: true });
|
|
6696
7098
|
const filesWritten = [];
|
|
6697
7099
|
for (const command of bundle.commands) {
|
|
@@ -6699,9 +7101,9 @@ var OpenCodeCommandsWriter = {
|
|
|
6699
7101
|
const content = `${frontmatter}
|
|
6700
7102
|
|
|
6701
7103
|
${command.prompt}`;
|
|
6702
|
-
const commandPath =
|
|
7104
|
+
const commandPath = join24(commandsDir, `${command.name}.md`);
|
|
6703
7105
|
await writeFile21(commandPath, content, "utf-8");
|
|
6704
|
-
filesWritten.push(
|
|
7106
|
+
filesWritten.push(join24(ctx.outputPath, `${command.name}.md`));
|
|
6705
7107
|
}
|
|
6706
7108
|
return {
|
|
6707
7109
|
filesWritten
|
|
@@ -6719,7 +7121,7 @@ var opencodeAdapter = {
|
|
|
6719
7121
|
{ writer: OpenCodeCommandsWriter, outputPath: ".opencode/commands/" }
|
|
6720
7122
|
],
|
|
6721
7123
|
async init(ctx) {
|
|
6722
|
-
const opencodeDir =
|
|
7124
|
+
const opencodeDir = join25(ctx.projectRoot, ".opencode");
|
|
6723
7125
|
mkdirSync8(opencodeDir, { recursive: true });
|
|
6724
7126
|
return {
|
|
6725
7127
|
filesCreated: [".opencode/"],
|
|
@@ -6727,7 +7129,9 @@ var opencodeAdapter = {
|
|
|
6727
7129
|
};
|
|
6728
7130
|
},
|
|
6729
7131
|
async sync(bundle, ctx) {
|
|
6730
|
-
const
|
|
7132
|
+
const providerId = "opencode";
|
|
7133
|
+
const providerBundle = createProviderScopedBundle(bundle, providerId);
|
|
7134
|
+
const result = await executeWriters(this.writers, providerBundle, ctx.projectRoot, providerId);
|
|
6731
7135
|
return {
|
|
6732
7136
|
filesWritten: result.filesWritten,
|
|
6733
7137
|
filesDeleted: []
|
|
@@ -6771,7 +7175,7 @@ async function inferCapabilityId(source, sourceType) {
|
|
|
6771
7175
|
}
|
|
6772
7176
|
async function runAddCap(flags, name) {
|
|
6773
7177
|
try {
|
|
6774
|
-
if (!
|
|
7178
|
+
if (!existsSync23("omni.toml")) {
|
|
6775
7179
|
console.log("✗ No config file found");
|
|
6776
7180
|
console.log(" Run: omnidev init");
|
|
6777
7181
|
process.exit(1);
|
|
@@ -6794,7 +7198,7 @@ async function runAddCap(flags, name) {
|
|
|
6794
7198
|
sourceType = "local";
|
|
6795
7199
|
const localPath = flags.local.startsWith("file://") ? flags.local.slice(7) : flags.local;
|
|
6796
7200
|
source = `file://${localPath}`;
|
|
6797
|
-
if (!
|
|
7201
|
+
if (!existsSync23(localPath)) {
|
|
6798
7202
|
console.error(`✗ Local path not found: ${localPath}`);
|
|
6799
7203
|
process.exit(1);
|
|
6800
7204
|
}
|
|
@@ -6886,7 +7290,7 @@ async function runAddCap(flags, name) {
|
|
|
6886
7290
|
}
|
|
6887
7291
|
async function runAddMcp(flags, name) {
|
|
6888
7292
|
try {
|
|
6889
|
-
if (!
|
|
7293
|
+
if (!existsSync23("omni.toml")) {
|
|
6890
7294
|
console.log("✗ No config file found");
|
|
6891
7295
|
console.log(" Run: omnidev init");
|
|
6892
7296
|
process.exit(1);
|
|
@@ -7173,9 +7577,9 @@ var addRoutes = buildRouteMap({
|
|
|
7173
7577
|
});
|
|
7174
7578
|
|
|
7175
7579
|
// src/commands/capability.ts
|
|
7176
|
-
import { existsSync as
|
|
7580
|
+
import { existsSync as existsSync24, mkdirSync as mkdirSync9 } from "node:fs";
|
|
7177
7581
|
import { writeFile as writeFile22 } from "node:fs/promises";
|
|
7178
|
-
import { join as
|
|
7582
|
+
import { join as join26 } from "node:path";
|
|
7179
7583
|
import { input } from "@inquirer/prompts";
|
|
7180
7584
|
init_src();
|
|
7181
7585
|
import { buildCommand as buildCommand2, buildRouteMap as buildRouteMap2 } from "@stricli/core";
|
|
@@ -7353,14 +7757,18 @@ export default {
|
|
|
7353
7757
|
} satisfies CapabilityExport;
|
|
7354
7758
|
`;
|
|
7355
7759
|
}
|
|
7356
|
-
function generateGitignore() {
|
|
7357
|
-
|
|
7358
|
-
|
|
7760
|
+
function generateGitignore(programmatic) {
|
|
7761
|
+
const lines = [".env"];
|
|
7762
|
+
if (programmatic) {
|
|
7763
|
+
lines.push("dist/", "node_modules/");
|
|
7764
|
+
}
|
|
7765
|
+
return `${lines.join(`
|
|
7766
|
+
`)}
|
|
7359
7767
|
`;
|
|
7360
7768
|
}
|
|
7361
7769
|
async function runCapabilityNew(flags, capabilityId) {
|
|
7362
7770
|
try {
|
|
7363
|
-
if (!
|
|
7771
|
+
if (!existsSync24(".omni")) {
|
|
7364
7772
|
console.error("✗ OmniDev is not initialized in this directory.");
|
|
7365
7773
|
console.log("");
|
|
7366
7774
|
console.log(" Run: omnidev init");
|
|
@@ -7384,28 +7792,28 @@ async function runCapabilityNew(flags, capabilityId) {
|
|
|
7384
7792
|
default: defaultPath
|
|
7385
7793
|
});
|
|
7386
7794
|
}
|
|
7387
|
-
if (
|
|
7795
|
+
if (existsSync24(capabilityDir)) {
|
|
7388
7796
|
console.error(`✗ Directory already exists at ${capabilityDir}`);
|
|
7389
7797
|
process.exit(1);
|
|
7390
7798
|
}
|
|
7391
7799
|
const name = toTitleCase(id);
|
|
7392
7800
|
mkdirSync9(capabilityDir, { recursive: true });
|
|
7393
7801
|
const capabilityToml = generateCapabilityToml2({ id, name });
|
|
7394
|
-
await writeFile22(
|
|
7395
|
-
const skillDir =
|
|
7802
|
+
await writeFile22(join26(capabilityDir, "capability.toml"), capabilityToml, "utf-8");
|
|
7803
|
+
const skillDir = join26(capabilityDir, "skills", "getting-started");
|
|
7396
7804
|
mkdirSync9(skillDir, { recursive: true });
|
|
7397
|
-
await writeFile22(
|
|
7398
|
-
const rulesDir =
|
|
7805
|
+
await writeFile22(join26(skillDir, "SKILL.md"), generateSkillTemplate("getting-started"), "utf-8");
|
|
7806
|
+
const rulesDir = join26(capabilityDir, "rules");
|
|
7399
7807
|
mkdirSync9(rulesDir, { recursive: true });
|
|
7400
|
-
await writeFile22(
|
|
7401
|
-
const hooksDir =
|
|
7808
|
+
await writeFile22(join26(rulesDir, "coding-standards.md"), generateRuleTemplate("coding-standards"), "utf-8");
|
|
7809
|
+
const hooksDir = join26(capabilityDir, "hooks");
|
|
7402
7810
|
mkdirSync9(hooksDir, { recursive: true });
|
|
7403
|
-
await writeFile22(
|
|
7404
|
-
await writeFile22(
|
|
7811
|
+
await writeFile22(join26(hooksDir, "hooks.toml"), generateHooksTemplate(), "utf-8");
|
|
7812
|
+
await writeFile22(join26(hooksDir, "example-hook.sh"), generateHookScript(), "utf-8");
|
|
7813
|
+
await writeFile22(join26(capabilityDir, ".gitignore"), generateGitignore(Boolean(flags.programmatic)), "utf-8");
|
|
7405
7814
|
if (flags.programmatic) {
|
|
7406
|
-
await writeFile22(
|
|
7407
|
-
await writeFile22(
|
|
7408
|
-
await writeFile22(join25(capabilityDir, ".gitignore"), generateGitignore(), "utf-8");
|
|
7815
|
+
await writeFile22(join26(capabilityDir, "package.json"), generatePackageJson(id), "utf-8");
|
|
7816
|
+
await writeFile22(join26(capabilityDir, "index.ts"), generateIndexTs(id, name), "utf-8");
|
|
7409
7817
|
}
|
|
7410
7818
|
console.log(`✓ Created capability: ${name}`);
|
|
7411
7819
|
console.log(` Location: ${capabilityDir}`);
|
|
@@ -7416,10 +7824,10 @@ async function runCapabilityNew(flags, capabilityId) {
|
|
|
7416
7824
|
console.log(" - rules/coding-standards.md");
|
|
7417
7825
|
console.log(" - hooks/hooks.toml");
|
|
7418
7826
|
console.log(" - hooks/example-hook.sh");
|
|
7827
|
+
console.log(" - .gitignore");
|
|
7419
7828
|
if (flags.programmatic) {
|
|
7420
7829
|
console.log(" - package.json");
|
|
7421
7830
|
console.log(" - index.ts");
|
|
7422
|
-
console.log(" - .gitignore");
|
|
7423
7831
|
}
|
|
7424
7832
|
console.log("");
|
|
7425
7833
|
if (flags.programmatic) {
|
|
@@ -7561,9 +7969,9 @@ var capabilityRoutes = buildRouteMap2({
|
|
|
7561
7969
|
});
|
|
7562
7970
|
|
|
7563
7971
|
// src/commands/doctor.ts
|
|
7564
|
-
import { existsSync as
|
|
7972
|
+
import { existsSync as existsSync25 } from "node:fs";
|
|
7565
7973
|
import { execFile } from "node:child_process";
|
|
7566
|
-
import { readFile as
|
|
7974
|
+
import { readFile as readFile20 } from "node:fs/promises";
|
|
7567
7975
|
import { promisify } from "node:util";
|
|
7568
7976
|
import { buildCommand as buildCommand3 } from "@stricli/core";
|
|
7569
7977
|
var doctorCommand = buildCommand3({
|
|
@@ -7651,7 +8059,7 @@ async function checkPackageManager() {
|
|
|
7651
8059
|
}
|
|
7652
8060
|
}
|
|
7653
8061
|
async function checkOmniLocalDir() {
|
|
7654
|
-
const exists =
|
|
8062
|
+
const exists = existsSync25(".omni");
|
|
7655
8063
|
if (!exists) {
|
|
7656
8064
|
return {
|
|
7657
8065
|
name: ".omni/ directory",
|
|
@@ -7668,7 +8076,7 @@ async function checkOmniLocalDir() {
|
|
|
7668
8076
|
}
|
|
7669
8077
|
async function checkConfig() {
|
|
7670
8078
|
const configPath = "omni.toml";
|
|
7671
|
-
if (!
|
|
8079
|
+
if (!existsSync25(configPath)) {
|
|
7672
8080
|
return {
|
|
7673
8081
|
name: "Configuration",
|
|
7674
8082
|
passed: false,
|
|
@@ -7695,7 +8103,7 @@ async function checkConfig() {
|
|
|
7695
8103
|
}
|
|
7696
8104
|
async function checkRootGitignore() {
|
|
7697
8105
|
const gitignorePath = ".gitignore";
|
|
7698
|
-
if (!
|
|
8106
|
+
if (!existsSync25(gitignorePath)) {
|
|
7699
8107
|
return {
|
|
7700
8108
|
name: "Root .gitignore",
|
|
7701
8109
|
passed: false,
|
|
@@ -7703,7 +8111,7 @@ async function checkRootGitignore() {
|
|
|
7703
8111
|
fix: "Run: omnidev init"
|
|
7704
8112
|
};
|
|
7705
8113
|
}
|
|
7706
|
-
const content = await
|
|
8114
|
+
const content = await readFile20(gitignorePath, "utf-8");
|
|
7707
8115
|
const lines = content.split(`
|
|
7708
8116
|
`).map((line) => line.trim());
|
|
7709
8117
|
const hasOmniDir = lines.includes(".omni/");
|
|
@@ -7729,7 +8137,7 @@ async function checkRootGitignore() {
|
|
|
7729
8137
|
}
|
|
7730
8138
|
async function checkCapabilitiesDir() {
|
|
7731
8139
|
const capabilitiesDirPath = ".omni/capabilities";
|
|
7732
|
-
if (!
|
|
8140
|
+
if (!existsSync25(capabilitiesDirPath)) {
|
|
7733
8141
|
return {
|
|
7734
8142
|
name: "Capabilities Directory",
|
|
7735
8143
|
passed: true,
|
|
@@ -7745,8 +8153,8 @@ async function checkCapabilitiesDir() {
|
|
|
7745
8153
|
|
|
7746
8154
|
// src/commands/init.ts
|
|
7747
8155
|
import { exec } from "node:child_process";
|
|
7748
|
-
import { existsSync as
|
|
7749
|
-
import { readFile as
|
|
8156
|
+
import { existsSync as existsSync26, mkdirSync as mkdirSync10 } from "node:fs";
|
|
8157
|
+
import { readFile as readFile21, writeFile as writeFile23 } from "node:fs/promises";
|
|
7750
8158
|
import { promisify as promisify2 } from "node:util";
|
|
7751
8159
|
init_src();
|
|
7752
8160
|
import { buildCommand as buildCommand4 } from "@stricli/core";
|
|
@@ -7759,8 +8167,8 @@ var PROVIDER_GITIGNORE_FILES = {
|
|
|
7759
8167
|
codex: ["AGENTS.md", ".codex/"],
|
|
7760
8168
|
opencode: [".opencode/"]
|
|
7761
8169
|
};
|
|
7762
|
-
function getProviderGitignoreFiles(
|
|
7763
|
-
return
|
|
8170
|
+
function getProviderGitignoreFiles(providers3) {
|
|
8171
|
+
return providers3.flatMap((p) => PROVIDER_GITIGNORE_FILES[p] ?? []);
|
|
7764
8172
|
}
|
|
7765
8173
|
async function promptForProviders() {
|
|
7766
8174
|
const answers = await checkbox({
|
|
@@ -7815,7 +8223,7 @@ async function runInit(_flags, providerArg) {
|
|
|
7815
8223
|
}
|
|
7816
8224
|
}
|
|
7817
8225
|
await writeEnabledProviders(providerIds);
|
|
7818
|
-
if (!
|
|
8226
|
+
if (!existsSync26("omni.toml")) {
|
|
7819
8227
|
await writeConfig({
|
|
7820
8228
|
profiles: {
|
|
7821
8229
|
default: {
|
|
@@ -7831,7 +8239,7 @@ async function runInit(_flags, providerArg) {
|
|
|
7831
8239
|
});
|
|
7832
8240
|
await setActiveProfile("default");
|
|
7833
8241
|
}
|
|
7834
|
-
if (!
|
|
8242
|
+
if (!existsSync26("OMNI.md")) {
|
|
7835
8243
|
await writeFile23("OMNI.md", generateOmniMdTemplate(), "utf-8");
|
|
7836
8244
|
}
|
|
7837
8245
|
const config3 = await loadConfig();
|
|
@@ -7909,8 +8317,8 @@ async function addProviderFilesToGitignore(entries) {
|
|
|
7909
8317
|
async function addToGitignore(entriesToAdd, sectionHeader) {
|
|
7910
8318
|
const gitignorePath = ".gitignore";
|
|
7911
8319
|
let content = "";
|
|
7912
|
-
if (
|
|
7913
|
-
content = await
|
|
8320
|
+
if (existsSync26(gitignorePath)) {
|
|
8321
|
+
content = await readFile21(gitignorePath, "utf-8");
|
|
7914
8322
|
}
|
|
7915
8323
|
const lines = content.split(`
|
|
7916
8324
|
`);
|
|
@@ -7941,7 +8349,7 @@ async function getTrackedProviderFiles(files) {
|
|
|
7941
8349
|
}
|
|
7942
8350
|
|
|
7943
8351
|
// src/commands/profile.ts
|
|
7944
|
-
import { existsSync as
|
|
8352
|
+
import { existsSync as existsSync27 } from "node:fs";
|
|
7945
8353
|
init_src();
|
|
7946
8354
|
import { buildCommand as buildCommand5, buildRouteMap as buildRouteMap3 } from "@stricli/core";
|
|
7947
8355
|
var listCommand2 = buildCommand5({
|
|
@@ -7985,7 +8393,7 @@ var profileRoutes = buildRouteMap3({
|
|
|
7985
8393
|
});
|
|
7986
8394
|
async function runProfileList() {
|
|
7987
8395
|
try {
|
|
7988
|
-
if (!
|
|
8396
|
+
if (!existsSync27("omni.toml")) {
|
|
7989
8397
|
console.log("✗ No config file found");
|
|
7990
8398
|
console.log(" Run: omnidev init");
|
|
7991
8399
|
process.exit(1);
|
|
@@ -8025,7 +8433,7 @@ async function runProfileList() {
|
|
|
8025
8433
|
}
|
|
8026
8434
|
async function runProfileSet(profileName) {
|
|
8027
8435
|
try {
|
|
8028
|
-
if (!
|
|
8436
|
+
if (!existsSync27("omni.toml")) {
|
|
8029
8437
|
console.log("✗ No config file found");
|
|
8030
8438
|
console.log(" Run: omnidev init");
|
|
8031
8439
|
process.exit(1);
|
|
@@ -8174,7 +8582,7 @@ var providerRoutes = buildRouteMap4({
|
|
|
8174
8582
|
|
|
8175
8583
|
// src/commands/security.ts
|
|
8176
8584
|
init_src();
|
|
8177
|
-
import { existsSync as
|
|
8585
|
+
import { existsSync as existsSync28 } from "node:fs";
|
|
8178
8586
|
import { buildCommand as buildCommand7, buildRouteMap as buildRouteMap5 } from "@stricli/core";
|
|
8179
8587
|
var VALID_FINDING_TYPES = [
|
|
8180
8588
|
"unicode_bidi",
|
|
@@ -8291,7 +8699,7 @@ function formatFindingsWithHints(summary) {
|
|
|
8291
8699
|
}
|
|
8292
8700
|
async function runSecurityIssues(flags = {}) {
|
|
8293
8701
|
try {
|
|
8294
|
-
if (!
|
|
8702
|
+
if (!existsSync28("omni.toml")) {
|
|
8295
8703
|
console.log("No config file found");
|
|
8296
8704
|
console.log(" Run: omnidev init");
|
|
8297
8705
|
process.exit(1);
|
|
@@ -8546,7 +8954,7 @@ var securityRoutes = buildRouteMap5({
|
|
|
8546
8954
|
});
|
|
8547
8955
|
|
|
8548
8956
|
// src/commands/sync.ts
|
|
8549
|
-
import { existsSync as
|
|
8957
|
+
import { existsSync as existsSync29 } from "node:fs";
|
|
8550
8958
|
init_src();
|
|
8551
8959
|
import { buildCommand as buildCommand8 } from "@stricli/core";
|
|
8552
8960
|
var PROVIDERS_STATE_PATH = ".omni/state/providers.json";
|
|
@@ -8564,7 +8972,7 @@ async function runSync() {
|
|
|
8564
8972
|
const config3 = await loadConfig();
|
|
8565
8973
|
const activeProfile = await getActiveProfile() ?? "default";
|
|
8566
8974
|
let adapters = await getEnabledAdapters();
|
|
8567
|
-
if (!
|
|
8975
|
+
if (!existsSync29(PROVIDERS_STATE_PATH) || adapters.length === 0) {
|
|
8568
8976
|
console.log("No providers configured yet. Select your provider(s):");
|
|
8569
8977
|
const providerIds = await promptForProviders();
|
|
8570
8978
|
await writeEnabledProviders(providerIds);
|
|
@@ -8774,9 +9182,9 @@ async function buildDynamicApp() {
|
|
|
8774
9182
|
security: securityRoutes
|
|
8775
9183
|
};
|
|
8776
9184
|
debug("Core routes registered", Object.keys(routes));
|
|
8777
|
-
const configPath =
|
|
8778
|
-
debug("Checking for config", { configPath, exists:
|
|
8779
|
-
if (
|
|
9185
|
+
const configPath = join27(process.cwd(), "omni.toml");
|
|
9186
|
+
debug("Checking for config", { configPath, exists: existsSync30(configPath), cwd: process.cwd() });
|
|
9187
|
+
if (existsSync30(configPath)) {
|
|
8780
9188
|
try {
|
|
8781
9189
|
debug("Loading capability commands...");
|
|
8782
9190
|
const capabilityCommands = await loadCapabilityCommands();
|
|
@@ -8851,25 +9259,25 @@ async function loadCapabilityCommands() {
|
|
|
8851
9259
|
return commands;
|
|
8852
9260
|
}
|
|
8853
9261
|
async function loadCapabilityExport(capability3) {
|
|
8854
|
-
const capabilityPath =
|
|
8855
|
-
const builtIndexPath =
|
|
8856
|
-
const jsIndexPath =
|
|
8857
|
-
const tsIndexPath =
|
|
9262
|
+
const capabilityPath = join27(process.cwd(), capability3.path);
|
|
9263
|
+
const builtIndexPath = join27(capabilityPath, "dist", "index.js");
|
|
9264
|
+
const jsIndexPath = join27(capabilityPath, "index.js");
|
|
9265
|
+
const tsIndexPath = join27(capabilityPath, "index.ts");
|
|
8858
9266
|
debug(`Checking entry points for '${capability3.id}'`, {
|
|
8859
9267
|
capabilityPath,
|
|
8860
9268
|
builtIndexPath,
|
|
8861
|
-
builtExists:
|
|
9269
|
+
builtExists: existsSync30(builtIndexPath),
|
|
8862
9270
|
jsIndexPath,
|
|
8863
|
-
jsExists:
|
|
9271
|
+
jsExists: existsSync30(jsIndexPath),
|
|
8864
9272
|
tsIndexPath,
|
|
8865
|
-
tsExists:
|
|
9273
|
+
tsExists: existsSync30(tsIndexPath)
|
|
8866
9274
|
});
|
|
8867
9275
|
let indexPath = null;
|
|
8868
|
-
if (
|
|
9276
|
+
if (existsSync30(builtIndexPath)) {
|
|
8869
9277
|
indexPath = builtIndexPath;
|
|
8870
|
-
} else if (
|
|
9278
|
+
} else if (existsSync30(jsIndexPath)) {
|
|
8871
9279
|
indexPath = jsIndexPath;
|
|
8872
|
-
} else if (
|
|
9280
|
+
} else if (existsSync30(tsIndexPath)) {
|
|
8873
9281
|
indexPath = tsIndexPath;
|
|
8874
9282
|
}
|
|
8875
9283
|
if (!indexPath) {
|