@omnidev-ai/cli 0.17.0 → 0.18.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 +534 -307
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1287,85 +1287,6 @@ var init_dist = __esm(() => {
|
|
|
1287
1287
|
dist_default = { parse, stringify, TomlDate, TomlError };
|
|
1288
1288
|
});
|
|
1289
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
|
-
};
|
|
1324
|
-
});
|
|
1325
|
-
|
|
1326
|
-
// ../core/src/config/parser.ts
|
|
1327
|
-
function parseOmniConfig(tomlContent) {
|
|
1328
|
-
try {
|
|
1329
|
-
return parse(tomlContent);
|
|
1330
|
-
} catch (error) {
|
|
1331
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
1332
|
-
throw new Error(`Invalid TOML in config: ${message}`);
|
|
1333
|
-
}
|
|
1334
|
-
}
|
|
1335
|
-
function validateCapabilityConfig(parsed) {
|
|
1336
|
-
const cap = parsed["capability"];
|
|
1337
|
-
if (typeof cap !== "object" || cap === null) {
|
|
1338
|
-
throw new Error("capability.id is required in capability.toml");
|
|
1339
|
-
}
|
|
1340
|
-
const capability = cap;
|
|
1341
|
-
if (typeof capability["id"] !== "string") {
|
|
1342
|
-
throw new Error("capability.id is required in capability.toml");
|
|
1343
|
-
}
|
|
1344
|
-
if (typeof capability["name"] !== "string") {
|
|
1345
|
-
throw new Error("capability.name is required in capability.toml");
|
|
1346
|
-
}
|
|
1347
|
-
if (typeof capability["version"] !== "string") {
|
|
1348
|
-
throw new Error("capability.version is required in capability.toml");
|
|
1349
|
-
}
|
|
1350
|
-
if (capability["providers"] !== undefined) {
|
|
1351
|
-
capability["providers"] = normalizeProviderApplicability(capability["providers"], "capability.providers");
|
|
1352
|
-
}
|
|
1353
|
-
}
|
|
1354
|
-
function parseCapabilityConfig(tomlContent) {
|
|
1355
|
-
try {
|
|
1356
|
-
const parsed = parse(tomlContent);
|
|
1357
|
-
validateCapabilityConfig(parsed);
|
|
1358
|
-
return parsed;
|
|
1359
|
-
} catch (error) {
|
|
1360
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
1361
|
-
throw new Error(`Invalid capability.toml: ${message}`);
|
|
1362
|
-
}
|
|
1363
|
-
}
|
|
1364
|
-
var init_parser = __esm(() => {
|
|
1365
|
-
init_dist();
|
|
1366
|
-
init_providers();
|
|
1367
|
-
});
|
|
1368
|
-
|
|
1369
1290
|
// ../core/src/hooks/constants.ts
|
|
1370
1291
|
var HOOK_EVENTS, MATCHER_EVENTS, PROMPT_HOOK_EVENTS, HOOK_TYPES, COMMON_TOOL_MATCHERS, NOTIFICATION_MATCHERS, SESSION_START_MATCHERS, PRE_COMPACT_MATCHERS, DEFAULT_COMMAND_TIMEOUT = 60, DEFAULT_PROMPT_TIMEOUT = 30, VARIABLE_MAPPINGS, HOOKS_CONFIG_FILENAME = "hooks.toml", CLAUDE_HOOKS_CONFIG_FILENAME = "hooks.json", HOOKS_DIRECTORY = "hooks";
|
|
1371
1292
|
var init_constants = __esm(() => {
|
|
@@ -2451,14 +2372,90 @@ var init_loader = __esm(() => {
|
|
|
2451
2372
|
init_constants();
|
|
2452
2373
|
});
|
|
2453
2374
|
|
|
2454
|
-
// ../core/src/
|
|
2375
|
+
// ../core/src/providers.ts
|
|
2376
|
+
function normalizeProviderId(provider) {
|
|
2377
|
+
if (provider in PROVIDER_ALIAS_MAP) {
|
|
2378
|
+
return PROVIDER_ALIAS_MAP[provider];
|
|
2379
|
+
}
|
|
2380
|
+
throw new Error(`Unknown provider: ${provider}`);
|
|
2381
|
+
}
|
|
2382
|
+
function normalizeProviderApplicability(value, fieldName) {
|
|
2383
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
2384
|
+
throw new Error(`${fieldName} must be a table of provider = boolean entries`);
|
|
2385
|
+
}
|
|
2386
|
+
const normalized = {};
|
|
2387
|
+
for (const [rawProvider, rawEnabled] of Object.entries(value)) {
|
|
2388
|
+
if (typeof rawEnabled !== "boolean") {
|
|
2389
|
+
throw new Error(`${fieldName}.${rawProvider} must be a boolean`);
|
|
2390
|
+
}
|
|
2391
|
+
const canonicalProvider = normalizeProviderId(rawProvider);
|
|
2392
|
+
const existing = normalized[canonicalProvider];
|
|
2393
|
+
if (existing !== undefined && existing !== rawEnabled) {
|
|
2394
|
+
throw new Error(`Conflicting provider entries in ${fieldName}: ${rawProvider} maps to ${canonicalProvider}`);
|
|
2395
|
+
}
|
|
2396
|
+
normalized[canonicalProvider] = rawEnabled;
|
|
2397
|
+
}
|
|
2398
|
+
return normalized;
|
|
2399
|
+
}
|
|
2400
|
+
var PROVIDER_ALIAS_MAP;
|
|
2401
|
+
var init_providers = __esm(() => {
|
|
2402
|
+
PROVIDER_ALIAS_MAP = {
|
|
2403
|
+
claude: "claude-code",
|
|
2404
|
+
"claude-code": "claude-code",
|
|
2405
|
+
codex: "codex",
|
|
2406
|
+
cursor: "cursor",
|
|
2407
|
+
opencode: "opencode"
|
|
2408
|
+
};
|
|
2409
|
+
});
|
|
2410
|
+
|
|
2411
|
+
// ../core/src/config/parser.ts
|
|
2412
|
+
function parseOmniConfig(tomlContent) {
|
|
2413
|
+
try {
|
|
2414
|
+
return parse(tomlContent);
|
|
2415
|
+
} catch (error) {
|
|
2416
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2417
|
+
throw new Error(`Invalid TOML in config: ${message}`);
|
|
2418
|
+
}
|
|
2419
|
+
}
|
|
2420
|
+
function validateCapabilityConfig(parsed) {
|
|
2421
|
+
const cap = parsed["capability"];
|
|
2422
|
+
if (typeof cap !== "object" || cap === null) {
|
|
2423
|
+
throw new Error("capability.id is required in capability.toml");
|
|
2424
|
+
}
|
|
2425
|
+
const capability = cap;
|
|
2426
|
+
if (typeof capability["id"] !== "string") {
|
|
2427
|
+
throw new Error("capability.id is required in capability.toml");
|
|
2428
|
+
}
|
|
2429
|
+
if (typeof capability["name"] !== "string") {
|
|
2430
|
+
throw new Error("capability.name is required in capability.toml");
|
|
2431
|
+
}
|
|
2432
|
+
if (typeof capability["version"] !== "string") {
|
|
2433
|
+
throw new Error("capability.version is required in capability.toml");
|
|
2434
|
+
}
|
|
2435
|
+
if (capability["providers"] !== undefined) {
|
|
2436
|
+
capability["providers"] = normalizeProviderApplicability(capability["providers"], "capability.providers");
|
|
2437
|
+
}
|
|
2438
|
+
}
|
|
2439
|
+
function parseCapabilityConfig(tomlContent) {
|
|
2440
|
+
try {
|
|
2441
|
+
const parsed = parse(tomlContent);
|
|
2442
|
+
validateCapabilityConfig(parsed);
|
|
2443
|
+
return parsed;
|
|
2444
|
+
} catch (error) {
|
|
2445
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2446
|
+
throw new Error(`Invalid capability.toml: ${message}`);
|
|
2447
|
+
}
|
|
2448
|
+
}
|
|
2449
|
+
var init_parser = __esm(() => {
|
|
2450
|
+
init_dist();
|
|
2451
|
+
init_providers();
|
|
2452
|
+
});
|
|
2453
|
+
|
|
2454
|
+
// ../core/src/capability/env.ts
|
|
2455
2455
|
import { existsSync as existsSync6 } from "node:fs";
|
|
2456
2456
|
import { readFile as readFile3 } from "node:fs/promises";
|
|
2457
2457
|
import { join as join4 } from "node:path";
|
|
2458
2458
|
import { parseEnv } from "node:util";
|
|
2459
|
-
function hasEnvPlaceholder(value) {
|
|
2460
|
-
return ENV_PLACEHOLDER_DETECTOR.test(value);
|
|
2461
|
-
}
|
|
2462
2459
|
function mergeEnvSources(capabilityEnv) {
|
|
2463
2460
|
const merged = { ...capabilityEnv };
|
|
2464
2461
|
for (const [key, value] of Object.entries(process.env)) {
|
|
@@ -2468,13 +2465,21 @@ function mergeEnvSources(capabilityEnv) {
|
|
|
2468
2465
|
}
|
|
2469
2466
|
return merged;
|
|
2470
2467
|
}
|
|
2471
|
-
async function
|
|
2468
|
+
async function loadCapabilityEnvVariables(capabilityPath) {
|
|
2472
2469
|
const envPath = join4(capabilityPath, CAPABILITY_ENV_FILE);
|
|
2473
2470
|
if (!existsSync6(envPath)) {
|
|
2474
|
-
return {};
|
|
2471
|
+
return mergeEnvSources({});
|
|
2475
2472
|
}
|
|
2476
2473
|
const envContent = await readFile3(envPath, "utf-8");
|
|
2477
|
-
|
|
2474
|
+
const capabilityEnv = Object.fromEntries(Object.entries(parseEnv(envContent)).filter((entry) => typeof entry[1] === "string"));
|
|
2475
|
+
return mergeEnvSources(capabilityEnv);
|
|
2476
|
+
}
|
|
2477
|
+
var CAPABILITY_ENV_FILE = ".env";
|
|
2478
|
+
var init_env = () => {};
|
|
2479
|
+
|
|
2480
|
+
// ../core/src/capability/mcp-env.ts
|
|
2481
|
+
function hasEnvPlaceholder(value) {
|
|
2482
|
+
return ENV_PLACEHOLDER_DETECTOR.test(value);
|
|
2478
2483
|
}
|
|
2479
2484
|
function resolveString(value, variables, capabilityId, fieldPath) {
|
|
2480
2485
|
if (!hasEnvPlaceholder(value)) {
|
|
@@ -2510,35 +2515,35 @@ function mcpHasPlaceholders(mcp) {
|
|
|
2510
2515
|
}
|
|
2511
2516
|
return strings.some((value) => hasEnvPlaceholder(value));
|
|
2512
2517
|
}
|
|
2513
|
-
async function resolveCapabilityMcpEnv(config, capabilityPath) {
|
|
2518
|
+
async function resolveCapabilityMcpEnv(config, capabilityPath, variables) {
|
|
2514
2519
|
if (!config.mcp || !mcpHasPlaceholders(config.mcp)) {
|
|
2515
2520
|
return config;
|
|
2516
2521
|
}
|
|
2517
|
-
const
|
|
2522
|
+
const resolvedVariables = variables ?? await loadCapabilityEnvVariables(capabilityPath);
|
|
2518
2523
|
const resolvedMcp = { ...config.mcp };
|
|
2519
2524
|
const capabilityId = config.capability.id;
|
|
2520
2525
|
if (resolvedMcp.command) {
|
|
2521
|
-
resolvedMcp.command = resolveString(resolvedMcp.command,
|
|
2526
|
+
resolvedMcp.command = resolveString(resolvedMcp.command, resolvedVariables, capabilityId, "mcp.command");
|
|
2522
2527
|
}
|
|
2523
2528
|
if (resolvedMcp.cwd) {
|
|
2524
|
-
resolvedMcp.cwd = resolveString(resolvedMcp.cwd,
|
|
2529
|
+
resolvedMcp.cwd = resolveString(resolvedMcp.cwd, resolvedVariables, capabilityId, "mcp.cwd");
|
|
2525
2530
|
}
|
|
2526
2531
|
if (resolvedMcp.url) {
|
|
2527
|
-
resolvedMcp.url = resolveString(resolvedMcp.url,
|
|
2532
|
+
resolvedMcp.url = resolveString(resolvedMcp.url, resolvedVariables, capabilityId, "mcp.url");
|
|
2528
2533
|
}
|
|
2529
2534
|
if (resolvedMcp.args) {
|
|
2530
|
-
resolvedMcp.args = resolvedMcp.args.map((arg, index) => resolveString(arg,
|
|
2535
|
+
resolvedMcp.args = resolvedMcp.args.map((arg, index) => resolveString(arg, resolvedVariables, capabilityId, `mcp.args[${index}]`));
|
|
2531
2536
|
}
|
|
2532
2537
|
if (resolvedMcp.env) {
|
|
2533
2538
|
resolvedMcp.env = Object.fromEntries(Object.entries(resolvedMcp.env).map(([key, value]) => [
|
|
2534
2539
|
key,
|
|
2535
|
-
resolveString(value,
|
|
2540
|
+
resolveString(value, resolvedVariables, capabilityId, `mcp.env.${key}`)
|
|
2536
2541
|
]));
|
|
2537
2542
|
}
|
|
2538
2543
|
if (resolvedMcp.headers) {
|
|
2539
2544
|
resolvedMcp.headers = Object.fromEntries(Object.entries(resolvedMcp.headers).map(([key, value]) => [
|
|
2540
2545
|
key,
|
|
2541
|
-
resolveString(value,
|
|
2546
|
+
resolveString(value, resolvedVariables, capabilityId, `mcp.headers.${key}`)
|
|
2542
2547
|
]));
|
|
2543
2548
|
}
|
|
2544
2549
|
return {
|
|
@@ -2546,8 +2551,9 @@ async function resolveCapabilityMcpEnv(config, capabilityPath) {
|
|
|
2546
2551
|
mcp: resolvedMcp
|
|
2547
2552
|
};
|
|
2548
2553
|
}
|
|
2549
|
-
var
|
|
2554
|
+
var ENV_PLACEHOLDER, ENV_PLACEHOLDER_DETECTOR;
|
|
2550
2555
|
var init_mcp_env = __esm(() => {
|
|
2556
|
+
init_env();
|
|
2551
2557
|
ENV_PLACEHOLDER = /\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g;
|
|
2552
2558
|
ENV_PLACEHOLDER_DETECTOR = /\$\{([A-Za-z_][A-Za-z0-9_]*)\}/;
|
|
2553
2559
|
});
|
|
@@ -2582,9 +2588,45 @@ var init_rules = () => {};
|
|
|
2582
2588
|
import { existsSync as existsSync8, readdirSync as readdirSync4 } from "node:fs";
|
|
2583
2589
|
import { readFile as readFile5 } from "node:fs/promises";
|
|
2584
2590
|
import { join as join6 } from "node:path";
|
|
2585
|
-
|
|
2591
|
+
function hasSkillPlaceholder(value) {
|
|
2592
|
+
return SKILL_PLACEHOLDER_DETECTOR.test(value);
|
|
2593
|
+
}
|
|
2594
|
+
function resolveSkillPlaceholders(content, variables, capabilityId, sourceLabel) {
|
|
2595
|
+
if (!hasSkillPlaceholder(content)) {
|
|
2596
|
+
return content;
|
|
2597
|
+
}
|
|
2598
|
+
return content.replace(SKILL_PLACEHOLDER, (match, variableName) => {
|
|
2599
|
+
const resolved = variables[variableName];
|
|
2600
|
+
if (resolved === undefined) {
|
|
2601
|
+
throw new Error(`Missing environment variable "${variableName}" required by capability "${capabilityId}" in ${sourceLabel} (placeholder "${match}")`);
|
|
2602
|
+
}
|
|
2603
|
+
return resolved;
|
|
2604
|
+
});
|
|
2605
|
+
}
|
|
2606
|
+
function parseSkillMarkdown(content, capabilityId, options) {
|
|
2607
|
+
const resolvedContent = options?.variables && options.sourceLabel ? resolveSkillPlaceholders(content, options.variables, capabilityId, options.sourceLabel) : content;
|
|
2608
|
+
const parsed = parseFrontmatterWithMarkdown(resolvedContent);
|
|
2609
|
+
if (!parsed) {
|
|
2610
|
+
const sourceLabel = options?.sourceLabel ?? "skill content";
|
|
2611
|
+
throw new Error(`Invalid SKILL.md format at ${sourceLabel}: missing YAML frontmatter`);
|
|
2612
|
+
}
|
|
2613
|
+
const frontmatter = parsed.frontmatter;
|
|
2614
|
+
const instructions = parsed.markdown;
|
|
2615
|
+
if (!frontmatter.name || !frontmatter.description) {
|
|
2616
|
+
const sourceLabel = options?.sourceLabel ?? "skill content";
|
|
2617
|
+
throw new Error(`Invalid SKILL.md at ${sourceLabel}: name and description required in frontmatter`);
|
|
2618
|
+
}
|
|
2619
|
+
return {
|
|
2620
|
+
name: frontmatter.name,
|
|
2621
|
+
description: frontmatter.description,
|
|
2622
|
+
instructions: instructions.trim(),
|
|
2623
|
+
capabilityId
|
|
2624
|
+
};
|
|
2625
|
+
}
|
|
2626
|
+
async function loadSkills(capabilityPath, capabilityId, variables) {
|
|
2586
2627
|
const skills = [];
|
|
2587
2628
|
const possibleDirNames = ["skills", "skill"];
|
|
2629
|
+
const resolvedVariables = variables ?? await loadCapabilityEnvVariables(capabilityPath);
|
|
2588
2630
|
for (const dirName of possibleDirNames) {
|
|
2589
2631
|
const dir = join6(capabilityPath, dirName);
|
|
2590
2632
|
if (!existsSync8(dir)) {
|
|
@@ -2595,7 +2637,7 @@ async function loadSkills(capabilityPath, capabilityId) {
|
|
|
2595
2637
|
if (entry.isDirectory()) {
|
|
2596
2638
|
const skillPath = join6(dir, entry.name, "SKILL.md");
|
|
2597
2639
|
if (existsSync8(skillPath)) {
|
|
2598
|
-
const skill = await parseSkillFile(skillPath, capabilityId);
|
|
2640
|
+
const skill = await parseSkillFile(skillPath, capabilityId, resolvedVariables, `skill file ${skillPath}`);
|
|
2599
2641
|
skills.push(skill);
|
|
2600
2642
|
}
|
|
2601
2643
|
}
|
|
@@ -2603,25 +2645,19 @@ async function loadSkills(capabilityPath, capabilityId) {
|
|
|
2603
2645
|
}
|
|
2604
2646
|
return skills;
|
|
2605
2647
|
}
|
|
2606
|
-
async function parseSkillFile(filePath, capabilityId) {
|
|
2648
|
+
async function parseSkillFile(filePath, capabilityId, variables, sourceLabel) {
|
|
2607
2649
|
const content = await readFile5(filePath, "utf-8");
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
}
|
|
2612
|
-
const frontmatter = parsed.frontmatter;
|
|
2613
|
-
const instructions = parsed.markdown;
|
|
2614
|
-
if (!frontmatter.name || !frontmatter.description) {
|
|
2615
|
-
throw new Error(`Invalid SKILL.md at ${filePath}: name and description required in frontmatter`);
|
|
2616
|
-
}
|
|
2617
|
-
return {
|
|
2618
|
-
name: frontmatter.name,
|
|
2619
|
-
description: frontmatter.description,
|
|
2620
|
-
instructions: instructions.trim(),
|
|
2621
|
-
capabilityId
|
|
2622
|
-
};
|
|
2650
|
+
return parseSkillMarkdown(content, capabilityId, {
|
|
2651
|
+
variables,
|
|
2652
|
+
sourceLabel
|
|
2653
|
+
});
|
|
2623
2654
|
}
|
|
2624
|
-
var
|
|
2655
|
+
var SKILL_PLACEHOLDER, SKILL_PLACEHOLDER_DETECTOR;
|
|
2656
|
+
var init_skills = __esm(() => {
|
|
2657
|
+
init_env();
|
|
2658
|
+
SKILL_PLACEHOLDER = /\{OMNIDEV_([A-Za-z_][A-Za-z0-9_]*)\}/g;
|
|
2659
|
+
SKILL_PLACEHOLDER_DETECTOR = /\{OMNIDEV_([A-Za-z_][A-Za-z0-9_]*)\}/;
|
|
2660
|
+
});
|
|
2625
2661
|
|
|
2626
2662
|
// ../core/src/capability/subagents.ts
|
|
2627
2663
|
import { existsSync as existsSync9, readdirSync as readdirSync5 } from "node:fs";
|
|
@@ -2767,40 +2803,13 @@ async function loadTypeDefinitions(capabilityPath) {
|
|
|
2767
2803
|
}
|
|
2768
2804
|
return readFile7(typesPath, "utf-8");
|
|
2769
2805
|
}
|
|
2770
|
-
function convertSkillExports(skillExports, capabilityId) {
|
|
2771
|
-
return skillExports.map((skillExport) => {
|
|
2806
|
+
function convertSkillExports(skillExports, capabilityId, variables) {
|
|
2807
|
+
return skillExports.map((skillExport, index) => {
|
|
2772
2808
|
const exportObj = skillExport;
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
let instructions = exportObj.skillMd;
|
|
2778
|
-
if (lines[0]?.trim() === "---") {
|
|
2779
|
-
const endIndex = lines.findIndex((line, i) => i > 0 && line.trim() === "---");
|
|
2780
|
-
if (endIndex > 0) {
|
|
2781
|
-
const frontmatter = lines.slice(1, endIndex);
|
|
2782
|
-
instructions = lines.slice(endIndex + 1).join(`
|
|
2783
|
-
`).trim();
|
|
2784
|
-
for (const line of frontmatter) {
|
|
2785
|
-
const match = line.match(/^(\w+):\s*(.+)$/);
|
|
2786
|
-
if (match?.[1] && match[2]) {
|
|
2787
|
-
const key = match[1];
|
|
2788
|
-
const value = match[2];
|
|
2789
|
-
if (key === "name") {
|
|
2790
|
-
name = value.replace(/^["']|["']$/g, "");
|
|
2791
|
-
} else if (key === "description") {
|
|
2792
|
-
description = value.replace(/^["']|["']$/g, "");
|
|
2793
|
-
}
|
|
2794
|
-
}
|
|
2795
|
-
}
|
|
2796
|
-
}
|
|
2797
|
-
}
|
|
2798
|
-
return {
|
|
2799
|
-
name,
|
|
2800
|
-
description,
|
|
2801
|
-
instructions,
|
|
2802
|
-
capabilityId
|
|
2803
|
-
};
|
|
2809
|
+
return parseSkillMarkdown(exportObj.skillMd, capabilityId, {
|
|
2810
|
+
variables,
|
|
2811
|
+
sourceLabel: `programmatic skill export[${index}]`
|
|
2812
|
+
});
|
|
2804
2813
|
});
|
|
2805
2814
|
}
|
|
2806
2815
|
function convertRuleExports(ruleExports, capabilityId) {
|
|
@@ -2953,8 +2962,9 @@ function mergeByName(fileBased, programmatic) {
|
|
|
2953
2962
|
return Array.from(byName.values());
|
|
2954
2963
|
}
|
|
2955
2964
|
async function loadCapability(capabilityPath) {
|
|
2965
|
+
const capabilityEnvVariables = await loadCapabilityEnvVariables(capabilityPath);
|
|
2956
2966
|
const rawConfig = await loadCapabilityConfig(capabilityPath);
|
|
2957
|
-
const config = await resolveCapabilityMcpEnv(rawConfig, capabilityPath);
|
|
2967
|
+
const config = await resolveCapabilityMcpEnv(rawConfig, capabilityPath, capabilityEnvVariables);
|
|
2958
2968
|
const id = config.capability.id;
|
|
2959
2969
|
const exports = await importCapabilityExports(capabilityPath);
|
|
2960
2970
|
const exportsAny = exports;
|
|
@@ -2969,8 +2979,8 @@ async function loadCapability(capabilityPath) {
|
|
|
2969
2979
|
return;
|
|
2970
2980
|
};
|
|
2971
2981
|
const skillsExport = getExportValue("skills");
|
|
2972
|
-
const programmaticSkills = Array.isArray(skillsExport) ? convertSkillExports(skillsExport, id) : [];
|
|
2973
|
-
const fileSkills = await loadSkills(capabilityPath, id);
|
|
2982
|
+
const programmaticSkills = Array.isArray(skillsExport) ? convertSkillExports(skillsExport, id, capabilityEnvVariables) : [];
|
|
2983
|
+
const fileSkills = await loadSkills(capabilityPath, id, capabilityEnvVariables);
|
|
2974
2984
|
const skills = mergeByName(fileSkills, programmaticSkills);
|
|
2975
2985
|
const rulesExport = getExportValue("rules");
|
|
2976
2986
|
const programmaticRules = Array.isArray(rulesExport) ? convertRuleExports(rulesExport, id) : [];
|
|
@@ -3018,11 +3028,12 @@ async function loadCapability(capabilityPath) {
|
|
|
3018
3028
|
}
|
|
3019
3029
|
var CAPABILITIES_DIR = ".omni/capabilities";
|
|
3020
3030
|
var init_loader2 = __esm(() => {
|
|
3021
|
-
init_parser();
|
|
3022
3031
|
init_loader();
|
|
3023
|
-
|
|
3032
|
+
init_parser();
|
|
3024
3033
|
init_commands();
|
|
3025
3034
|
init_docs();
|
|
3035
|
+
init_env();
|
|
3036
|
+
init_mcp_env();
|
|
3026
3037
|
init_rules();
|
|
3027
3038
|
init_skills();
|
|
3028
3039
|
init_subagents();
|
|
@@ -5370,10 +5381,36 @@ var init_state = __esm(() => {
|
|
|
5370
5381
|
|
|
5371
5382
|
// ../core/src/sync.ts
|
|
5372
5383
|
import { spawn as spawn2 } from "node:child_process";
|
|
5373
|
-
import { mkdirSync as mkdirSync5 } from "node:fs";
|
|
5384
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync5, readFileSync as readFileSync3 } from "node:fs";
|
|
5385
|
+
import { join as join10 } from "node:path";
|
|
5386
|
+
function getDeclaredPackageManager(packageManager) {
|
|
5387
|
+
if (typeof packageManager !== "string" || packageManager.trim().length === 0) {
|
|
5388
|
+
return;
|
|
5389
|
+
}
|
|
5390
|
+
const atIndex = packageManager.indexOf("@");
|
|
5391
|
+
return atIndex === -1 ? packageManager : packageManager.slice(0, atIndex);
|
|
5392
|
+
}
|
|
5393
|
+
function resolveCapabilityInstallCommand(capabilityPath, options) {
|
|
5394
|
+
const packageJsonPath = join10(capabilityPath, "package.json");
|
|
5395
|
+
const packageLockPath = join10(capabilityPath, "package-lock.json");
|
|
5396
|
+
let packageManager;
|
|
5397
|
+
try {
|
|
5398
|
+
const pkgJson = JSON.parse(readFileSync3(packageJsonPath, "utf-8"));
|
|
5399
|
+
packageManager = getDeclaredPackageManager(pkgJson.packageManager);
|
|
5400
|
+
} catch {}
|
|
5401
|
+
if (!options.hasNpm) {
|
|
5402
|
+
throw new Error("npm is not installed. Install npm to install capability dependencies.");
|
|
5403
|
+
}
|
|
5404
|
+
if (packageManager && packageManager !== "npm") {
|
|
5405
|
+
throw new Error(`Capability at ${capabilityPath} declares packageManager=${packageManager}, but OmniDev only supports npm for capability dependencies.`);
|
|
5406
|
+
}
|
|
5407
|
+
return {
|
|
5408
|
+
cmd: "npm",
|
|
5409
|
+
args: [existsSync20(packageLockPath) ? "ci" : "install"]
|
|
5410
|
+
};
|
|
5411
|
+
}
|
|
5374
5412
|
async function installCapabilityDependencies(silent) {
|
|
5375
|
-
const {
|
|
5376
|
-
const { join: join10 } = await import("node:path");
|
|
5413
|
+
const { readdirSync: readdirSync7 } = await import("node:fs");
|
|
5377
5414
|
const { parse: parse2 } = await Promise.resolve().then(() => (init_dist(), exports_dist));
|
|
5378
5415
|
const capabilitiesDir = ".omni/capabilities";
|
|
5379
5416
|
if (!existsSync20(capabilitiesDir)) {
|
|
@@ -5387,10 +5424,9 @@ async function installCapabilityDependencies(silent) {
|
|
|
5387
5424
|
proc.on("close", (code) => resolve2(code === 0));
|
|
5388
5425
|
});
|
|
5389
5426
|
}
|
|
5390
|
-
const
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
throw new Error("Neither Bun nor npm is installed. Install one of them to install capability dependencies.");
|
|
5427
|
+
const hasNpm = await commandExists("npm");
|
|
5428
|
+
if (!hasNpm) {
|
|
5429
|
+
throw new Error("npm is not installed. Install npm to install capability dependencies.");
|
|
5394
5430
|
}
|
|
5395
5431
|
for (const entry of entries) {
|
|
5396
5432
|
if (!entry.isDirectory()) {
|
|
@@ -5413,9 +5449,9 @@ async function installCapabilityDependencies(silent) {
|
|
|
5413
5449
|
}
|
|
5414
5450
|
try {
|
|
5415
5451
|
await new Promise((resolve2, reject) => {
|
|
5416
|
-
const
|
|
5417
|
-
|
|
5418
|
-
|
|
5452
|
+
const { cmd, args } = resolveCapabilityInstallCommand(capabilityPath, {
|
|
5453
|
+
hasNpm
|
|
5454
|
+
});
|
|
5419
5455
|
const proc = spawn2(cmd, args, {
|
|
5420
5456
|
cwd: capabilityPath,
|
|
5421
5457
|
stdio: "pipe"
|
|
@@ -5444,9 +5480,7 @@ ${stderr}`));
|
|
|
5444
5480
|
} catch {}
|
|
5445
5481
|
if (hasBuildScript) {
|
|
5446
5482
|
await new Promise((resolve2, reject) => {
|
|
5447
|
-
const
|
|
5448
|
-
const args = ["run", "build"];
|
|
5449
|
-
const proc = spawn2(cmd, args, {
|
|
5483
|
+
const proc = spawn2("npm", ["run", "build"], {
|
|
5450
5484
|
cwd: capabilityPath,
|
|
5451
5485
|
stdio: "pipe"
|
|
5452
5486
|
});
|
|
@@ -5598,21 +5632,23 @@ var init_types3 = __esm(() => {
|
|
|
5598
5632
|
unicode: true,
|
|
5599
5633
|
symlinks: true,
|
|
5600
5634
|
scripts: true,
|
|
5601
|
-
binaries: false
|
|
5635
|
+
binaries: false,
|
|
5636
|
+
hiddenCommands: true
|
|
5602
5637
|
}
|
|
5603
5638
|
};
|
|
5604
5639
|
DEFAULT_SCAN_SETTINGS = {
|
|
5605
5640
|
unicode: true,
|
|
5606
5641
|
symlinks: true,
|
|
5607
5642
|
scripts: true,
|
|
5608
|
-
binaries: false
|
|
5643
|
+
binaries: false,
|
|
5644
|
+
hiddenCommands: true
|
|
5609
5645
|
};
|
|
5610
5646
|
});
|
|
5611
5647
|
|
|
5612
5648
|
// ../core/src/security/scanner.ts
|
|
5613
|
-
import { existsSync as
|
|
5649
|
+
import { existsSync as existsSync21 } from "node:fs";
|
|
5614
5650
|
import { lstat, readdir as readdir2, readFile as readFile17, readlink, realpath } from "node:fs/promises";
|
|
5615
|
-
import { join as
|
|
5651
|
+
import { join as join11, relative, resolve as resolve2 } from "node:path";
|
|
5616
5652
|
async function scanFileForUnicode(filePath, relativePath) {
|
|
5617
5653
|
const findings = [];
|
|
5618
5654
|
try {
|
|
@@ -5693,10 +5729,113 @@ async function scanFileForScripts(filePath, relativePath) {
|
|
|
5693
5729
|
} catch {}
|
|
5694
5730
|
return findings;
|
|
5695
5731
|
}
|
|
5732
|
+
function extractHiddenRegions(fileContent) {
|
|
5733
|
+
const regions = [];
|
|
5734
|
+
HTML_COMMENT_RE.lastIndex = 0;
|
|
5735
|
+
for (let match = HTML_COMMENT_RE.exec(fileContent);match !== null; match = HTML_COMMENT_RE.exec(fileContent)) {
|
|
5736
|
+
const captured = match[1];
|
|
5737
|
+
if (captured === undefined)
|
|
5738
|
+
continue;
|
|
5739
|
+
const beforeMatch = fileContent.substring(0, match.index);
|
|
5740
|
+
const startLine = beforeMatch.split(`
|
|
5741
|
+
`).length;
|
|
5742
|
+
regions.push({ content: captured, startLine });
|
|
5743
|
+
}
|
|
5744
|
+
HIDDEN_REFERENCE_RE.lastIndex = 0;
|
|
5745
|
+
for (let match = HIDDEN_REFERENCE_RE.exec(fileContent);match !== null; match = HIDDEN_REFERENCE_RE.exec(fileContent)) {
|
|
5746
|
+
const captured = match[1];
|
|
5747
|
+
if (captured === undefined)
|
|
5748
|
+
continue;
|
|
5749
|
+
const beforeMatch = fileContent.substring(0, match.index);
|
|
5750
|
+
const startLine = beforeMatch.split(`
|
|
5751
|
+
`).length;
|
|
5752
|
+
regions.push({ content: captured, startLine });
|
|
5753
|
+
}
|
|
5754
|
+
return regions;
|
|
5755
|
+
}
|
|
5756
|
+
async function scanFileForHiddenCommands(filePath, relativePath) {
|
|
5757
|
+
const findings = [];
|
|
5758
|
+
try {
|
|
5759
|
+
const content = await readFile17(filePath, "utf-8");
|
|
5760
|
+
const hiddenRegions = extractHiddenRegions(content);
|
|
5761
|
+
for (const region of hiddenRegions) {
|
|
5762
|
+
const regionLines = region.content.split(`
|
|
5763
|
+
`);
|
|
5764
|
+
for (let i = 0;i < regionLines.length; i++) {
|
|
5765
|
+
const line = regionLines[i] ?? "";
|
|
5766
|
+
if (!line.trim())
|
|
5767
|
+
continue;
|
|
5768
|
+
for (const { pattern, message, severity } of HIDDEN_COMMAND_PATTERNS) {
|
|
5769
|
+
if (pattern.test(line)) {
|
|
5770
|
+
findings.push({
|
|
5771
|
+
type: "hidden_command",
|
|
5772
|
+
severity,
|
|
5773
|
+
file: relativePath,
|
|
5774
|
+
line: region.startLine + i,
|
|
5775
|
+
message: `Hidden in comment: ${message}`,
|
|
5776
|
+
details: line.trim().substring(0, 100)
|
|
5777
|
+
});
|
|
5778
|
+
}
|
|
5779
|
+
}
|
|
5780
|
+
for (const { pattern, message, severity } of NETWORK_REQUEST_PATTERNS) {
|
|
5781
|
+
if (pattern.test(line)) {
|
|
5782
|
+
findings.push({
|
|
5783
|
+
type: "network_request",
|
|
5784
|
+
severity: severity === "medium" ? "high" : severity,
|
|
5785
|
+
file: relativePath,
|
|
5786
|
+
line: region.startLine + i,
|
|
5787
|
+
message: `Hidden in comment: ${message}`,
|
|
5788
|
+
details: line.trim().substring(0, 100)
|
|
5789
|
+
});
|
|
5790
|
+
}
|
|
5791
|
+
}
|
|
5792
|
+
for (const { pattern, message, severity } of SUSPICIOUS_SCRIPT_PATTERNS) {
|
|
5793
|
+
if (pattern.test(line)) {
|
|
5794
|
+
findings.push({
|
|
5795
|
+
type: "hidden_command",
|
|
5796
|
+
severity: severity === "medium" ? "high" : severity,
|
|
5797
|
+
file: relativePath,
|
|
5798
|
+
line: region.startLine + i,
|
|
5799
|
+
message: `Hidden in comment: ${message}`,
|
|
5800
|
+
details: line.trim().substring(0, 100)
|
|
5801
|
+
});
|
|
5802
|
+
}
|
|
5803
|
+
}
|
|
5804
|
+
}
|
|
5805
|
+
}
|
|
5806
|
+
} catch {}
|
|
5807
|
+
return findings;
|
|
5808
|
+
}
|
|
5809
|
+
async function scanFileForNetworkRequests(filePath, relativePath) {
|
|
5810
|
+
const findings = [];
|
|
5811
|
+
try {
|
|
5812
|
+
const content = await readFile17(filePath, "utf-8");
|
|
5813
|
+
const lines = content.split(`
|
|
5814
|
+
`);
|
|
5815
|
+
for (let lineNum = 0;lineNum < lines.length; lineNum++) {
|
|
5816
|
+
const line = lines[lineNum];
|
|
5817
|
+
if (!line)
|
|
5818
|
+
continue;
|
|
5819
|
+
for (const { pattern, message, severity } of NETWORK_REQUEST_PATTERNS) {
|
|
5820
|
+
if (pattern.test(line)) {
|
|
5821
|
+
findings.push({
|
|
5822
|
+
type: "network_request",
|
|
5823
|
+
severity,
|
|
5824
|
+
file: relativePath,
|
|
5825
|
+
line: lineNum + 1,
|
|
5826
|
+
message,
|
|
5827
|
+
details: line.trim().substring(0, 100)
|
|
5828
|
+
});
|
|
5829
|
+
}
|
|
5830
|
+
}
|
|
5831
|
+
}
|
|
5832
|
+
} catch {}
|
|
5833
|
+
return findings;
|
|
5834
|
+
}
|
|
5696
5835
|
async function checkSymlink(symlinkPath, relativePath, capabilityRoot) {
|
|
5697
5836
|
try {
|
|
5698
5837
|
const linkTarget = await readlink(symlinkPath);
|
|
5699
|
-
const resolvedTarget = resolve2(
|
|
5838
|
+
const resolvedTarget = resolve2(join11(symlinkPath, "..", linkTarget));
|
|
5700
5839
|
const normalizedRoot = await realpath(capabilityRoot);
|
|
5701
5840
|
if (linkTarget.startsWith("/")) {
|
|
5702
5841
|
return {
|
|
@@ -5731,7 +5870,7 @@ function isTextFile(filePath) {
|
|
|
5731
5870
|
async function scanCapability(capabilityId, capabilityPath, settings = DEFAULT_SCAN_SETTINGS) {
|
|
5732
5871
|
const startTime = Date.now();
|
|
5733
5872
|
const findings = [];
|
|
5734
|
-
if (!
|
|
5873
|
+
if (!existsSync21(capabilityPath)) {
|
|
5735
5874
|
return {
|
|
5736
5875
|
capabilityId,
|
|
5737
5876
|
path: capabilityPath,
|
|
@@ -5743,7 +5882,7 @@ async function scanCapability(capabilityId, capabilityPath, settings = DEFAULT_S
|
|
|
5743
5882
|
async function scanDirectory(dirPath) {
|
|
5744
5883
|
const entries = await readdir2(dirPath, { withFileTypes: true });
|
|
5745
5884
|
for (const entry of entries) {
|
|
5746
|
-
const fullPath =
|
|
5885
|
+
const fullPath = join11(dirPath, entry.name);
|
|
5747
5886
|
const relativePath = relative(capabilityPath, fullPath);
|
|
5748
5887
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "__pycache__") {
|
|
5749
5888
|
continue;
|
|
@@ -5770,17 +5909,27 @@ async function scanCapability(capabilityId, capabilityPath, settings = DEFAULT_S
|
|
|
5770
5909
|
});
|
|
5771
5910
|
}
|
|
5772
5911
|
if (isTextFile(fullPath)) {
|
|
5912
|
+
const ext = fullPath.toLowerCase().substring(fullPath.lastIndexOf("."));
|
|
5773
5913
|
if (settings.unicode) {
|
|
5774
5914
|
const unicodeFindings = await scanFileForUnicode(fullPath, relativePath);
|
|
5775
5915
|
findings.push(...unicodeFindings);
|
|
5776
5916
|
}
|
|
5777
5917
|
if (settings.scripts) {
|
|
5778
|
-
const ext = fullPath.toLowerCase().substring(fullPath.lastIndexOf("."));
|
|
5779
5918
|
if ([".sh", ".bash", ".zsh", ".fish", ".py", ".rb", ".js", ".ts"].includes(ext)) {
|
|
5780
5919
|
const scriptFindings = await scanFileForScripts(fullPath, relativePath);
|
|
5781
5920
|
findings.push(...scriptFindings);
|
|
5782
5921
|
}
|
|
5783
5922
|
}
|
|
5923
|
+
if (settings.hiddenCommands) {
|
|
5924
|
+
if ([".md", ".txt", ".yaml", ".yml", ".toml"].includes(ext)) {
|
|
5925
|
+
const hiddenFindings = await scanFileForHiddenCommands(fullPath, relativePath);
|
|
5926
|
+
findings.push(...hiddenFindings);
|
|
5927
|
+
}
|
|
5928
|
+
}
|
|
5929
|
+
if (settings.hiddenCommands) {
|
|
5930
|
+
const networkFindings = await scanFileForNetworkRequests(fullPath, relativePath);
|
|
5931
|
+
findings.push(...networkFindings);
|
|
5932
|
+
}
|
|
5784
5933
|
}
|
|
5785
5934
|
}
|
|
5786
5935
|
}
|
|
@@ -5812,7 +5961,9 @@ async function scanCapabilities(capabilities2, config2 = {}) {
|
|
|
5812
5961
|
symlink_escape: 0,
|
|
5813
5962
|
symlink_absolute: 0,
|
|
5814
5963
|
suspicious_script: 0,
|
|
5815
|
-
binary_file: 0
|
|
5964
|
+
binary_file: 0,
|
|
5965
|
+
hidden_command: 0,
|
|
5966
|
+
network_request: 0
|
|
5816
5967
|
};
|
|
5817
5968
|
const findingsBySeverity = {
|
|
5818
5969
|
low: 0,
|
|
@@ -5887,7 +6038,7 @@ function formatScanResults(summary, verbose = false) {
|
|
|
5887
6038
|
return lines.join(`
|
|
5888
6039
|
`);
|
|
5889
6040
|
}
|
|
5890
|
-
var UNICODE_PATTERNS, SUSPICIOUS_SCRIPT_PATTERNS, BINARY_EXTENSIONS, TEXT_EXTENSIONS;
|
|
6041
|
+
var UNICODE_PATTERNS, SUSPICIOUS_SCRIPT_PATTERNS, NETWORK_REQUEST_PATTERNS, HIDDEN_COMMAND_PATTERNS, BINARY_EXTENSIONS, TEXT_EXTENSIONS, HTML_COMMENT_RE, HIDDEN_REFERENCE_RE;
|
|
5891
6042
|
var init_scanner = __esm(() => {
|
|
5892
6043
|
init_types3();
|
|
5893
6044
|
UNICODE_PATTERNS = {
|
|
@@ -5979,6 +6130,75 @@ var init_scanner = __esm(() => {
|
|
|
5979
6130
|
severity: "high"
|
|
5980
6131
|
}
|
|
5981
6132
|
];
|
|
6133
|
+
NETWORK_REQUEST_PATTERNS = [
|
|
6134
|
+
{
|
|
6135
|
+
pattern: /\bcurl\s+.*https?:\/\//i,
|
|
6136
|
+
message: "Outbound curl request detected",
|
|
6137
|
+
severity: "medium"
|
|
6138
|
+
},
|
|
6139
|
+
{
|
|
6140
|
+
pattern: /\bwget\s+.*https?:\/\//i,
|
|
6141
|
+
message: "Outbound wget request detected",
|
|
6142
|
+
severity: "medium"
|
|
6143
|
+
},
|
|
6144
|
+
{
|
|
6145
|
+
pattern: /\bfetch\s*\(\s*["'`]https?:\/\//i,
|
|
6146
|
+
message: "Outbound fetch() request detected",
|
|
6147
|
+
severity: "medium"
|
|
6148
|
+
},
|
|
6149
|
+
{
|
|
6150
|
+
pattern: /\b(?:http|https)\.(?:get|request|post|put)\s*\(/i,
|
|
6151
|
+
message: "Outbound HTTP request via Node.js http module",
|
|
6152
|
+
severity: "medium"
|
|
6153
|
+
},
|
|
6154
|
+
{
|
|
6155
|
+
pattern: /\brequests\.(?:get|post|put|delete|patch)\s*\(/i,
|
|
6156
|
+
message: "Outbound HTTP request via Python requests",
|
|
6157
|
+
severity: "medium"
|
|
6158
|
+
},
|
|
6159
|
+
{
|
|
6160
|
+
pattern: /\bnc\b.*\s\d{2,5}\b/i,
|
|
6161
|
+
message: "Netcat connection detected",
|
|
6162
|
+
severity: "high"
|
|
6163
|
+
},
|
|
6164
|
+
{
|
|
6165
|
+
pattern: /\b(?:Invoke-WebRequest|Invoke-RestMethod|iwr|irm)\b/i,
|
|
6166
|
+
message: "Outbound PowerShell web request detected",
|
|
6167
|
+
severity: "medium"
|
|
6168
|
+
}
|
|
6169
|
+
];
|
|
6170
|
+
HIDDEN_COMMAND_PATTERNS = [
|
|
6171
|
+
{
|
|
6172
|
+
pattern: /`[^`]*(?:curl|wget|bash|sh|python|ruby|node|exec|eval|system)\s[^`]*`/i,
|
|
6173
|
+
message: "Executable command in backtick-wrapped code",
|
|
6174
|
+
severity: "critical"
|
|
6175
|
+
},
|
|
6176
|
+
{
|
|
6177
|
+
pattern: /\|\s*(?:ba)?sh\b/i,
|
|
6178
|
+
message: "Pipe to shell execution",
|
|
6179
|
+
severity: "critical"
|
|
6180
|
+
},
|
|
6181
|
+
{
|
|
6182
|
+
pattern: /(?:^|\s)(?:bash|sh|zsh)\s+-c\s+/i,
|
|
6183
|
+
message: "Shell invocation with -c flag",
|
|
6184
|
+
severity: "high"
|
|
6185
|
+
},
|
|
6186
|
+
{
|
|
6187
|
+
pattern: /\b(?:curl|wget)\s+.*https?:\/\//i,
|
|
6188
|
+
message: "Network fetch command detected",
|
|
6189
|
+
severity: "high"
|
|
6190
|
+
},
|
|
6191
|
+
{
|
|
6192
|
+
pattern: /\b(?:python|ruby|node)\s+-e\s+/i,
|
|
6193
|
+
message: "Inline script execution",
|
|
6194
|
+
severity: "high"
|
|
6195
|
+
},
|
|
6196
|
+
{
|
|
6197
|
+
pattern: /\beval\s*\(.*\)/i,
|
|
6198
|
+
message: "eval() call detected",
|
|
6199
|
+
severity: "high"
|
|
6200
|
+
}
|
|
6201
|
+
];
|
|
5982
6202
|
BINARY_EXTENSIONS = new Set([
|
|
5983
6203
|
".exe",
|
|
5984
6204
|
".dll",
|
|
@@ -6013,6 +6233,8 @@ var init_scanner = __esm(() => {
|
|
|
6013
6233
|
".py",
|
|
6014
6234
|
".rb"
|
|
6015
6235
|
]);
|
|
6236
|
+
HTML_COMMENT_RE = /<!--([\s\S]*?)-->/g;
|
|
6237
|
+
HIDDEN_REFERENCE_RE = /^\[.*?\]:\s*\S+\s+"(.+)"/gm;
|
|
6016
6238
|
});
|
|
6017
6239
|
|
|
6018
6240
|
// ../core/src/security/index.ts
|
|
@@ -6222,6 +6444,7 @@ __export(exports_src, {
|
|
|
6222
6444
|
resolveEnabledCapabilities: () => resolveEnabledCapabilities,
|
|
6223
6445
|
resolveCapabilityRootInConfig: () => resolveCapabilityRootInConfig,
|
|
6224
6446
|
resolveCapabilityRoot: () => resolveCapabilityRoot,
|
|
6447
|
+
resolveCapabilityInstallCommand: () => resolveCapabilityInstallCommand,
|
|
6225
6448
|
removeSecurityAllow: () => removeSecurityAllow,
|
|
6226
6449
|
readSecurityAllows: () => readSecurityAllows,
|
|
6227
6450
|
readMcpJson: () => readMcpJson,
|
|
@@ -6353,13 +6576,13 @@ var init_src = __esm(() => {
|
|
|
6353
6576
|
import { run } from "@stricli/core";
|
|
6354
6577
|
|
|
6355
6578
|
// src/lib/dynamic-app.ts
|
|
6356
|
-
import { existsSync as
|
|
6579
|
+
import { existsSync as existsSync31 } from "node:fs";
|
|
6357
6580
|
import { createRequire as createRequire2 } from "node:module";
|
|
6358
|
-
import { join as
|
|
6581
|
+
import { join as join28 } from "node:path";
|
|
6359
6582
|
import { buildApplication, buildRouteMap as buildRouteMap7 } from "@stricli/core";
|
|
6360
6583
|
|
|
6361
6584
|
// src/commands/add.ts
|
|
6362
|
-
import { existsSync as
|
|
6585
|
+
import { existsSync as existsSync24 } from "node:fs";
|
|
6363
6586
|
import { basename as basename5, resolve as resolve3 } from "node:path";
|
|
6364
6587
|
|
|
6365
6588
|
// ../adapters/src/writers/generic/executor.ts
|
|
@@ -6392,21 +6615,21 @@ async function executeWriters(writerConfigs, bundle, projectRoot, providerId) {
|
|
|
6392
6615
|
}
|
|
6393
6616
|
// ../adapters/src/writers/generic/hooks.ts
|
|
6394
6617
|
init_src();
|
|
6395
|
-
import { existsSync as
|
|
6618
|
+
import { existsSync as existsSync22 } from "node:fs";
|
|
6396
6619
|
import { mkdir as mkdir2, readFile as readFile18, writeFile as writeFile10 } from "node:fs/promises";
|
|
6397
|
-
import { dirname, join as
|
|
6620
|
+
import { dirname, join as join12 } from "node:path";
|
|
6398
6621
|
var HooksWriter = {
|
|
6399
6622
|
id: "hooks",
|
|
6400
6623
|
async write(bundle, ctx) {
|
|
6401
6624
|
if (!bundle.hooks) {
|
|
6402
6625
|
return { filesWritten: [] };
|
|
6403
6626
|
}
|
|
6404
|
-
const settingsPath =
|
|
6627
|
+
const settingsPath = join12(ctx.projectRoot, ctx.outputPath);
|
|
6405
6628
|
const parentDir = dirname(settingsPath);
|
|
6406
6629
|
await mkdir2(parentDir, { recursive: true });
|
|
6407
6630
|
const claudeHooks = transformHooksConfig(bundle.hooks, "toClaude");
|
|
6408
6631
|
let existingSettings = {};
|
|
6409
|
-
if (
|
|
6632
|
+
if (existsSync22(settingsPath)) {
|
|
6410
6633
|
try {
|
|
6411
6634
|
const content = await readFile18(settingsPath, "utf-8");
|
|
6412
6635
|
existingSettings = JSON.parse(content);
|
|
@@ -6426,9 +6649,9 @@ var HooksWriter = {
|
|
|
6426
6649
|
}
|
|
6427
6650
|
};
|
|
6428
6651
|
// ../adapters/src/writers/generic/instructions-md.ts
|
|
6429
|
-
import { existsSync as
|
|
6652
|
+
import { existsSync as existsSync23 } from "node:fs";
|
|
6430
6653
|
import { mkdir as mkdir3, readFile as readFile19, writeFile as writeFile11 } from "node:fs/promises";
|
|
6431
|
-
import { dirname as dirname2, join as
|
|
6654
|
+
import { dirname as dirname2, join as join13 } from "node:path";
|
|
6432
6655
|
|
|
6433
6656
|
// ../adapters/src/writers/generic/omni-md.ts
|
|
6434
6657
|
init_src();
|
|
@@ -6453,14 +6676,14 @@ function renderOmniMdForProvider(content, providerId) {
|
|
|
6453
6676
|
var InstructionsMdWriter = {
|
|
6454
6677
|
id: "instructions-md",
|
|
6455
6678
|
async write(bundle, ctx) {
|
|
6456
|
-
const outputFullPath =
|
|
6679
|
+
const outputFullPath = join13(ctx.projectRoot, ctx.outputPath);
|
|
6457
6680
|
const parentDir = dirname2(outputFullPath);
|
|
6458
6681
|
if (parentDir !== ctx.projectRoot) {
|
|
6459
6682
|
await mkdir3(parentDir, { recursive: true });
|
|
6460
6683
|
}
|
|
6461
|
-
const omniMdPath =
|
|
6684
|
+
const omniMdPath = join13(ctx.projectRoot, "OMNI.md");
|
|
6462
6685
|
let omniMdContent = "";
|
|
6463
|
-
if (
|
|
6686
|
+
if (existsSync23(omniMdPath)) {
|
|
6464
6687
|
omniMdContent = renderOmniMdForProvider(await readFile19(omniMdPath, "utf-8"), ctx.providerId);
|
|
6465
6688
|
}
|
|
6466
6689
|
let content = omniMdContent;
|
|
@@ -6478,17 +6701,17 @@ ${bundle.instructionsContent}
|
|
|
6478
6701
|
};
|
|
6479
6702
|
// ../adapters/src/writers/generic/skills.ts
|
|
6480
6703
|
import { mkdir as mkdir4, writeFile as writeFile12 } from "node:fs/promises";
|
|
6481
|
-
import { join as
|
|
6704
|
+
import { join as join14 } from "node:path";
|
|
6482
6705
|
var SkillsWriter = {
|
|
6483
6706
|
id: "skills",
|
|
6484
6707
|
async write(bundle, ctx) {
|
|
6485
|
-
const skillsDir =
|
|
6708
|
+
const skillsDir = join14(ctx.projectRoot, ctx.outputPath);
|
|
6486
6709
|
await mkdir4(skillsDir, { recursive: true });
|
|
6487
6710
|
const filesWritten = [];
|
|
6488
6711
|
for (const skill of bundle.skills) {
|
|
6489
|
-
const skillDir =
|
|
6712
|
+
const skillDir = join14(skillsDir, skill.name);
|
|
6490
6713
|
await mkdir4(skillDir, { recursive: true });
|
|
6491
|
-
const skillPath =
|
|
6714
|
+
const skillPath = join14(skillDir, "SKILL.md");
|
|
6492
6715
|
const content = `---
|
|
6493
6716
|
name: ${skill.name}
|
|
6494
6717
|
description: "${skill.description}"
|
|
@@ -6496,7 +6719,7 @@ description: "${skill.description}"
|
|
|
6496
6719
|
|
|
6497
6720
|
${skill.instructions}`;
|
|
6498
6721
|
await writeFile12(skillPath, content, "utf-8");
|
|
6499
|
-
filesWritten.push(
|
|
6722
|
+
filesWritten.push(join14(ctx.outputPath, skill.name, "SKILL.md"));
|
|
6500
6723
|
}
|
|
6501
6724
|
return {
|
|
6502
6725
|
filesWritten
|
|
@@ -6505,7 +6728,7 @@ ${skill.instructions}`;
|
|
|
6505
6728
|
};
|
|
6506
6729
|
// ../adapters/src/writers/generic/commands-as-skills.ts
|
|
6507
6730
|
import { mkdir as mkdir5, writeFile as writeFile13 } from "node:fs/promises";
|
|
6508
|
-
import { join as
|
|
6731
|
+
import { join as join15 } from "node:path";
|
|
6509
6732
|
function generateSkillFrontmatter(command) {
|
|
6510
6733
|
const lines = ["---"];
|
|
6511
6734
|
lines.push(`name: ${command.name}`);
|
|
@@ -6520,19 +6743,19 @@ function generateSkillFrontmatter(command) {
|
|
|
6520
6743
|
var CommandsAsSkillsWriter = {
|
|
6521
6744
|
id: "commands-as-skills",
|
|
6522
6745
|
async write(bundle, ctx) {
|
|
6523
|
-
const skillsDir =
|
|
6746
|
+
const skillsDir = join15(ctx.projectRoot, ctx.outputPath);
|
|
6524
6747
|
await mkdir5(skillsDir, { recursive: true });
|
|
6525
6748
|
const filesWritten = [];
|
|
6526
6749
|
for (const command of bundle.commands) {
|
|
6527
|
-
const commandSkillDir =
|
|
6750
|
+
const commandSkillDir = join15(skillsDir, command.name);
|
|
6528
6751
|
await mkdir5(commandSkillDir, { recursive: true });
|
|
6529
6752
|
const frontmatter = generateSkillFrontmatter(command);
|
|
6530
6753
|
const content = `${frontmatter}
|
|
6531
6754
|
|
|
6532
6755
|
${command.prompt}`;
|
|
6533
|
-
const skillPath =
|
|
6756
|
+
const skillPath = join15(commandSkillDir, "SKILL.md");
|
|
6534
6757
|
await writeFile13(skillPath, content, "utf-8");
|
|
6535
|
-
filesWritten.push(
|
|
6758
|
+
filesWritten.push(join15(ctx.outputPath, command.name, "SKILL.md"));
|
|
6536
6759
|
}
|
|
6537
6760
|
return {
|
|
6538
6761
|
filesWritten
|
|
@@ -6588,7 +6811,7 @@ function createProviderScopedBundle(bundle, providerId) {
|
|
|
6588
6811
|
|
|
6589
6812
|
// ../adapters/src/writers/claude/agents.ts
|
|
6590
6813
|
import { mkdir as mkdir6, writeFile as writeFile14 } from "node:fs/promises";
|
|
6591
|
-
import { join as
|
|
6814
|
+
import { join as join16 } from "node:path";
|
|
6592
6815
|
function generateFrontmatter(agent) {
|
|
6593
6816
|
const lines = ["---"];
|
|
6594
6817
|
lines.push(`name: ${agent.name}`);
|
|
@@ -6615,7 +6838,7 @@ function generateFrontmatter(agent) {
|
|
|
6615
6838
|
var ClaudeAgentsWriter = {
|
|
6616
6839
|
id: "claude-agents",
|
|
6617
6840
|
async write(bundle, ctx) {
|
|
6618
|
-
const agentsDir =
|
|
6841
|
+
const agentsDir = join16(ctx.projectRoot, ctx.outputPath);
|
|
6619
6842
|
await mkdir6(agentsDir, { recursive: true });
|
|
6620
6843
|
const filesWritten = [];
|
|
6621
6844
|
for (const agent of bundle.subagents) {
|
|
@@ -6623,9 +6846,9 @@ var ClaudeAgentsWriter = {
|
|
|
6623
6846
|
const content = `${frontmatter}
|
|
6624
6847
|
|
|
6625
6848
|
${agent.systemPrompt}`;
|
|
6626
|
-
const agentPath =
|
|
6849
|
+
const agentPath = join16(agentsDir, `${agent.name}.md`);
|
|
6627
6850
|
await writeFile14(agentPath, content, "utf-8");
|
|
6628
|
-
filesWritten.push(
|
|
6851
|
+
filesWritten.push(join16(ctx.outputPath, `${agent.name}.md`));
|
|
6629
6852
|
}
|
|
6630
6853
|
return {
|
|
6631
6854
|
filesWritten
|
|
@@ -6661,12 +6884,12 @@ var claudeCodeAdapter = {
|
|
|
6661
6884
|
};
|
|
6662
6885
|
// ../adapters/src/codex/index.ts
|
|
6663
6886
|
import { mkdirSync as mkdirSync6 } from "node:fs";
|
|
6664
|
-
import { join as
|
|
6887
|
+
import { join as join18 } from "node:path";
|
|
6665
6888
|
|
|
6666
6889
|
// ../adapters/src/writers/codex/toml.ts
|
|
6667
6890
|
init_dist();
|
|
6668
6891
|
import { mkdir as mkdir7, writeFile as writeFile15 } from "node:fs/promises";
|
|
6669
|
-
import { dirname as dirname3, join as
|
|
6892
|
+
import { dirname as dirname3, join as join17 } from "node:path";
|
|
6670
6893
|
var FILE_HEADER = `# Generated by OmniDev - DO NOT EDIT
|
|
6671
6894
|
# Run \`omnidev sync\` to regenerate
|
|
6672
6895
|
|
|
@@ -6717,7 +6940,7 @@ var CodexTomlWriter = {
|
|
|
6717
6940
|
if (mcps.size === 0) {
|
|
6718
6941
|
return { filesWritten: [] };
|
|
6719
6942
|
}
|
|
6720
|
-
const configPath =
|
|
6943
|
+
const configPath = join17(ctx.projectRoot, ctx.outputPath);
|
|
6721
6944
|
const parentDir = dirname3(configPath);
|
|
6722
6945
|
await mkdir7(parentDir, { recursive: true });
|
|
6723
6946
|
const mcpServers = {};
|
|
@@ -6751,7 +6974,7 @@ var codexAdapter = {
|
|
|
6751
6974
|
{ writer: CodexTomlWriter, outputPath: ".codex/config.toml" }
|
|
6752
6975
|
],
|
|
6753
6976
|
async init(ctx) {
|
|
6754
|
-
const codexDir =
|
|
6977
|
+
const codexDir = join18(ctx.projectRoot, ".codex");
|
|
6755
6978
|
mkdirSync6(codexDir, { recursive: true });
|
|
6756
6979
|
return {
|
|
6757
6980
|
filesCreated: [".codex/"],
|
|
@@ -6770,11 +6993,11 @@ var codexAdapter = {
|
|
|
6770
6993
|
};
|
|
6771
6994
|
// ../adapters/src/cursor/index.ts
|
|
6772
6995
|
import { mkdirSync as mkdirSync7 } from "node:fs";
|
|
6773
|
-
import { join as
|
|
6996
|
+
import { join as join23 } from "node:path";
|
|
6774
6997
|
|
|
6775
6998
|
// ../adapters/src/writers/cursor/agents.ts
|
|
6776
6999
|
import { mkdir as mkdir8, writeFile as writeFile16 } from "node:fs/promises";
|
|
6777
|
-
import { join as
|
|
7000
|
+
import { join as join19 } from "node:path";
|
|
6778
7001
|
function mapModelToCursor(model) {
|
|
6779
7002
|
if (!model || model === "inherit")
|
|
6780
7003
|
return "inherit";
|
|
@@ -6806,7 +7029,7 @@ function generateFrontmatter2(agent) {
|
|
|
6806
7029
|
var CursorAgentsWriter = {
|
|
6807
7030
|
id: "cursor-agents",
|
|
6808
7031
|
async write(bundle, ctx) {
|
|
6809
|
-
const agentsDir =
|
|
7032
|
+
const agentsDir = join19(ctx.projectRoot, ctx.outputPath);
|
|
6810
7033
|
await mkdir8(agentsDir, { recursive: true });
|
|
6811
7034
|
const filesWritten = [];
|
|
6812
7035
|
for (const agent of bundle.subagents) {
|
|
@@ -6814,9 +7037,9 @@ var CursorAgentsWriter = {
|
|
|
6814
7037
|
const content = `${frontmatter}
|
|
6815
7038
|
|
|
6816
7039
|
${agent.systemPrompt}`;
|
|
6817
|
-
const agentPath =
|
|
7040
|
+
const agentPath = join19(agentsDir, `${agent.name}.md`);
|
|
6818
7041
|
await writeFile16(agentPath, content, "utf-8");
|
|
6819
|
-
filesWritten.push(
|
|
7042
|
+
filesWritten.push(join19(ctx.outputPath, `${agent.name}.md`));
|
|
6820
7043
|
}
|
|
6821
7044
|
return {
|
|
6822
7045
|
filesWritten
|
|
@@ -6825,11 +7048,11 @@ ${agent.systemPrompt}`;
|
|
|
6825
7048
|
};
|
|
6826
7049
|
// ../adapters/src/writers/cursor/commands.ts
|
|
6827
7050
|
import { mkdir as mkdir9, writeFile as writeFile17 } from "node:fs/promises";
|
|
6828
|
-
import { join as
|
|
7051
|
+
import { join as join20 } from "node:path";
|
|
6829
7052
|
var CursorCommandsWriter = {
|
|
6830
7053
|
id: "cursor-commands",
|
|
6831
7054
|
async write(bundle, ctx) {
|
|
6832
|
-
const commandsDir =
|
|
7055
|
+
const commandsDir = join20(ctx.projectRoot, ctx.outputPath);
|
|
6833
7056
|
await mkdir9(commandsDir, { recursive: true });
|
|
6834
7057
|
const filesWritten = [];
|
|
6835
7058
|
for (const command of bundle.commands) {
|
|
@@ -6838,9 +7061,9 @@ var CursorCommandsWriter = {
|
|
|
6838
7061
|
${command.description}
|
|
6839
7062
|
|
|
6840
7063
|
${command.prompt}`;
|
|
6841
|
-
const commandPath =
|
|
7064
|
+
const commandPath = join20(commandsDir, `${command.name}.md`);
|
|
6842
7065
|
await writeFile17(commandPath, content, "utf-8");
|
|
6843
|
-
filesWritten.push(
|
|
7066
|
+
filesWritten.push(join20(ctx.outputPath, `${command.name}.md`));
|
|
6844
7067
|
}
|
|
6845
7068
|
return {
|
|
6846
7069
|
filesWritten
|
|
@@ -6849,7 +7072,7 @@ ${command.prompt}`;
|
|
|
6849
7072
|
};
|
|
6850
7073
|
// ../adapters/src/writers/cursor/mcp-json.ts
|
|
6851
7074
|
import { mkdir as mkdir10, writeFile as writeFile18 } from "node:fs/promises";
|
|
6852
|
-
import { dirname as dirname4, join as
|
|
7075
|
+
import { dirname as dirname4, join as join21 } from "node:path";
|
|
6853
7076
|
function buildCursorMcpConfig(mcp) {
|
|
6854
7077
|
const transport = mcp.transport ?? "stdio";
|
|
6855
7078
|
if (transport === "http" || transport === "sse") {
|
|
@@ -6894,7 +7117,7 @@ var CursorMcpJsonWriter = {
|
|
|
6894
7117
|
if (mcps.size === 0) {
|
|
6895
7118
|
return { filesWritten: [] };
|
|
6896
7119
|
}
|
|
6897
|
-
const configPath =
|
|
7120
|
+
const configPath = join21(ctx.projectRoot, ctx.outputPath);
|
|
6898
7121
|
const parentDir = dirname4(configPath);
|
|
6899
7122
|
await mkdir10(parentDir, { recursive: true });
|
|
6900
7123
|
const mcpServers = {};
|
|
@@ -6919,17 +7142,17 @@ var CursorMcpJsonWriter = {
|
|
|
6919
7142
|
};
|
|
6920
7143
|
// ../adapters/src/writers/cursor/rules.ts
|
|
6921
7144
|
import { mkdir as mkdir11, writeFile as writeFile19 } from "node:fs/promises";
|
|
6922
|
-
import { join as
|
|
7145
|
+
import { join as join22 } from "node:path";
|
|
6923
7146
|
var CursorRulesWriter = {
|
|
6924
7147
|
id: "cursor-rules",
|
|
6925
7148
|
async write(bundle, ctx) {
|
|
6926
|
-
const rulesDir =
|
|
7149
|
+
const rulesDir = join22(ctx.projectRoot, ctx.outputPath);
|
|
6927
7150
|
await mkdir11(rulesDir, { recursive: true });
|
|
6928
7151
|
const filesWritten = [];
|
|
6929
7152
|
for (const rule of bundle.rules) {
|
|
6930
|
-
const rulePath =
|
|
7153
|
+
const rulePath = join22(rulesDir, `omnidev-${rule.name}.mdc`);
|
|
6931
7154
|
await writeFile19(rulePath, rule.content, "utf-8");
|
|
6932
|
-
filesWritten.push(
|
|
7155
|
+
filesWritten.push(join22(ctx.outputPath, `omnidev-${rule.name}.mdc`));
|
|
6933
7156
|
}
|
|
6934
7157
|
return {
|
|
6935
7158
|
filesWritten
|
|
@@ -6949,7 +7172,7 @@ var cursorAdapter = {
|
|
|
6949
7172
|
{ writer: CursorMcpJsonWriter, outputPath: ".cursor/mcp.json" }
|
|
6950
7173
|
],
|
|
6951
7174
|
async init(ctx) {
|
|
6952
|
-
const rulesDir =
|
|
7175
|
+
const rulesDir = join23(ctx.projectRoot, ".cursor", "rules");
|
|
6953
7176
|
mkdirSync7(rulesDir, { recursive: true });
|
|
6954
7177
|
return {
|
|
6955
7178
|
filesCreated: [".cursor/rules/"],
|
|
@@ -6975,11 +7198,11 @@ var cursorAdapter = {
|
|
|
6975
7198
|
};
|
|
6976
7199
|
// ../adapters/src/opencode/index.ts
|
|
6977
7200
|
import { mkdirSync as mkdirSync8 } from "node:fs";
|
|
6978
|
-
import { join as
|
|
7201
|
+
import { join as join26 } from "node:path";
|
|
6979
7202
|
|
|
6980
7203
|
// ../adapters/src/writers/opencode/agents.ts
|
|
6981
7204
|
import { mkdir as mkdir12, writeFile as writeFile20 } from "node:fs/promises";
|
|
6982
|
-
import { join as
|
|
7205
|
+
import { join as join24 } from "node:path";
|
|
6983
7206
|
function mapModelToOpenCode(model) {
|
|
6984
7207
|
if (!model || model === "inherit")
|
|
6985
7208
|
return;
|
|
@@ -7057,7 +7280,7 @@ function generateFrontmatter3(agent) {
|
|
|
7057
7280
|
var OpenCodeAgentsWriter = {
|
|
7058
7281
|
id: "opencode-agents",
|
|
7059
7282
|
async write(bundle, ctx) {
|
|
7060
|
-
const agentsDir =
|
|
7283
|
+
const agentsDir = join24(ctx.projectRoot, ctx.outputPath);
|
|
7061
7284
|
await mkdir12(agentsDir, { recursive: true });
|
|
7062
7285
|
const filesWritten = [];
|
|
7063
7286
|
for (const agent of bundle.subagents) {
|
|
@@ -7065,9 +7288,9 @@ var OpenCodeAgentsWriter = {
|
|
|
7065
7288
|
const content = `${frontmatter}
|
|
7066
7289
|
|
|
7067
7290
|
${agent.systemPrompt}`;
|
|
7068
|
-
const agentPath =
|
|
7291
|
+
const agentPath = join24(agentsDir, `${agent.name}.md`);
|
|
7069
7292
|
await writeFile20(agentPath, content, "utf-8");
|
|
7070
|
-
filesWritten.push(
|
|
7293
|
+
filesWritten.push(join24(ctx.outputPath, `${agent.name}.md`));
|
|
7071
7294
|
}
|
|
7072
7295
|
return {
|
|
7073
7296
|
filesWritten
|
|
@@ -7076,7 +7299,7 @@ ${agent.systemPrompt}`;
|
|
|
7076
7299
|
};
|
|
7077
7300
|
// ../adapters/src/writers/opencode/commands.ts
|
|
7078
7301
|
import { mkdir as mkdir13, writeFile as writeFile21 } from "node:fs/promises";
|
|
7079
|
-
import { join as
|
|
7302
|
+
import { join as join25 } from "node:path";
|
|
7080
7303
|
function generateFrontmatter4(command) {
|
|
7081
7304
|
const lines = ["---"];
|
|
7082
7305
|
lines.push(`description: "${command.description.replace(/"/g, "\\\"")}"`);
|
|
@@ -7093,7 +7316,7 @@ function generateFrontmatter4(command) {
|
|
|
7093
7316
|
var OpenCodeCommandsWriter = {
|
|
7094
7317
|
id: "opencode-commands",
|
|
7095
7318
|
async write(bundle, ctx) {
|
|
7096
|
-
const commandsDir =
|
|
7319
|
+
const commandsDir = join25(ctx.projectRoot, ctx.outputPath);
|
|
7097
7320
|
await mkdir13(commandsDir, { recursive: true });
|
|
7098
7321
|
const filesWritten = [];
|
|
7099
7322
|
for (const command of bundle.commands) {
|
|
@@ -7101,9 +7324,9 @@ var OpenCodeCommandsWriter = {
|
|
|
7101
7324
|
const content = `${frontmatter}
|
|
7102
7325
|
|
|
7103
7326
|
${command.prompt}`;
|
|
7104
|
-
const commandPath =
|
|
7327
|
+
const commandPath = join25(commandsDir, `${command.name}.md`);
|
|
7105
7328
|
await writeFile21(commandPath, content, "utf-8");
|
|
7106
|
-
filesWritten.push(
|
|
7329
|
+
filesWritten.push(join25(ctx.outputPath, `${command.name}.md`));
|
|
7107
7330
|
}
|
|
7108
7331
|
return {
|
|
7109
7332
|
filesWritten
|
|
@@ -7121,7 +7344,7 @@ var opencodeAdapter = {
|
|
|
7121
7344
|
{ writer: OpenCodeCommandsWriter, outputPath: ".opencode/commands/" }
|
|
7122
7345
|
],
|
|
7123
7346
|
async init(ctx) {
|
|
7124
|
-
const opencodeDir =
|
|
7347
|
+
const opencodeDir = join26(ctx.projectRoot, ".opencode");
|
|
7125
7348
|
mkdirSync8(opencodeDir, { recursive: true });
|
|
7126
7349
|
return {
|
|
7127
7350
|
filesCreated: [".opencode/"],
|
|
@@ -7175,7 +7398,7 @@ async function inferCapabilityId(source, sourceType) {
|
|
|
7175
7398
|
}
|
|
7176
7399
|
async function runAddCap(flags, name) {
|
|
7177
7400
|
try {
|
|
7178
|
-
if (!
|
|
7401
|
+
if (!existsSync24("omni.toml")) {
|
|
7179
7402
|
console.log("✗ No config file found");
|
|
7180
7403
|
console.log(" Run: omnidev init");
|
|
7181
7404
|
process.exit(1);
|
|
@@ -7198,7 +7421,7 @@ async function runAddCap(flags, name) {
|
|
|
7198
7421
|
sourceType = "local";
|
|
7199
7422
|
const localPath = flags.local.startsWith("file://") ? flags.local.slice(7) : flags.local;
|
|
7200
7423
|
source = `file://${localPath}`;
|
|
7201
|
-
if (!
|
|
7424
|
+
if (!existsSync24(localPath)) {
|
|
7202
7425
|
console.error(`✗ Local path not found: ${localPath}`);
|
|
7203
7426
|
process.exit(1);
|
|
7204
7427
|
}
|
|
@@ -7290,7 +7513,7 @@ async function runAddCap(flags, name) {
|
|
|
7290
7513
|
}
|
|
7291
7514
|
async function runAddMcp(flags, name) {
|
|
7292
7515
|
try {
|
|
7293
|
-
if (!
|
|
7516
|
+
if (!existsSync24("omni.toml")) {
|
|
7294
7517
|
console.log("✗ No config file found");
|
|
7295
7518
|
console.log(" Run: omnidev init");
|
|
7296
7519
|
process.exit(1);
|
|
@@ -7577,9 +7800,9 @@ var addRoutes = buildRouteMap({
|
|
|
7577
7800
|
});
|
|
7578
7801
|
|
|
7579
7802
|
// src/commands/capability.ts
|
|
7580
|
-
import { existsSync as
|
|
7803
|
+
import { existsSync as existsSync25, mkdirSync as mkdirSync9 } from "node:fs";
|
|
7581
7804
|
import { writeFile as writeFile22 } from "node:fs/promises";
|
|
7582
|
-
import { join as
|
|
7805
|
+
import { join as join27 } from "node:path";
|
|
7583
7806
|
import { input } from "@inquirer/prompts";
|
|
7584
7807
|
init_src();
|
|
7585
7808
|
import { buildCommand as buildCommand2, buildRouteMap as buildRouteMap2 } from "@stricli/core";
|
|
@@ -7768,7 +7991,7 @@ function generateGitignore(programmatic) {
|
|
|
7768
7991
|
}
|
|
7769
7992
|
async function runCapabilityNew(flags, capabilityId) {
|
|
7770
7993
|
try {
|
|
7771
|
-
if (!
|
|
7994
|
+
if (!existsSync25(".omni")) {
|
|
7772
7995
|
console.error("✗ OmniDev is not initialized in this directory.");
|
|
7773
7996
|
console.log("");
|
|
7774
7997
|
console.log(" Run: omnidev init");
|
|
@@ -7792,28 +8015,28 @@ async function runCapabilityNew(flags, capabilityId) {
|
|
|
7792
8015
|
default: defaultPath
|
|
7793
8016
|
});
|
|
7794
8017
|
}
|
|
7795
|
-
if (
|
|
8018
|
+
if (existsSync25(capabilityDir)) {
|
|
7796
8019
|
console.error(`✗ Directory already exists at ${capabilityDir}`);
|
|
7797
8020
|
process.exit(1);
|
|
7798
8021
|
}
|
|
7799
8022
|
const name = toTitleCase(id);
|
|
7800
8023
|
mkdirSync9(capabilityDir, { recursive: true });
|
|
7801
8024
|
const capabilityToml = generateCapabilityToml2({ id, name });
|
|
7802
|
-
await writeFile22(
|
|
7803
|
-
const skillDir =
|
|
8025
|
+
await writeFile22(join27(capabilityDir, "capability.toml"), capabilityToml, "utf-8");
|
|
8026
|
+
const skillDir = join27(capabilityDir, "skills", "getting-started");
|
|
7804
8027
|
mkdirSync9(skillDir, { recursive: true });
|
|
7805
|
-
await writeFile22(
|
|
7806
|
-
const rulesDir =
|
|
8028
|
+
await writeFile22(join27(skillDir, "SKILL.md"), generateSkillTemplate("getting-started"), "utf-8");
|
|
8029
|
+
const rulesDir = join27(capabilityDir, "rules");
|
|
7807
8030
|
mkdirSync9(rulesDir, { recursive: true });
|
|
7808
|
-
await writeFile22(
|
|
7809
|
-
const hooksDir =
|
|
8031
|
+
await writeFile22(join27(rulesDir, "coding-standards.md"), generateRuleTemplate("coding-standards"), "utf-8");
|
|
8032
|
+
const hooksDir = join27(capabilityDir, "hooks");
|
|
7810
8033
|
mkdirSync9(hooksDir, { recursive: true });
|
|
7811
|
-
await writeFile22(
|
|
7812
|
-
await writeFile22(
|
|
7813
|
-
await writeFile22(
|
|
8034
|
+
await writeFile22(join27(hooksDir, "hooks.toml"), generateHooksTemplate(), "utf-8");
|
|
8035
|
+
await writeFile22(join27(hooksDir, "example-hook.sh"), generateHookScript(), "utf-8");
|
|
8036
|
+
await writeFile22(join27(capabilityDir, ".gitignore"), generateGitignore(Boolean(flags.programmatic)), "utf-8");
|
|
7814
8037
|
if (flags.programmatic) {
|
|
7815
|
-
await writeFile22(
|
|
7816
|
-
await writeFile22(
|
|
8038
|
+
await writeFile22(join27(capabilityDir, "package.json"), generatePackageJson(id), "utf-8");
|
|
8039
|
+
await writeFile22(join27(capabilityDir, "index.ts"), generateIndexTs(id, name), "utf-8");
|
|
7817
8040
|
}
|
|
7818
8041
|
console.log(`✓ Created capability: ${name}`);
|
|
7819
8042
|
console.log(` Location: ${capabilityDir}`);
|
|
@@ -7969,7 +8192,7 @@ var capabilityRoutes = buildRouteMap2({
|
|
|
7969
8192
|
});
|
|
7970
8193
|
|
|
7971
8194
|
// src/commands/doctor.ts
|
|
7972
|
-
import { existsSync as
|
|
8195
|
+
import { existsSync as existsSync26 } from "node:fs";
|
|
7973
8196
|
import { execFile } from "node:child_process";
|
|
7974
8197
|
import { readFile as readFile20 } from "node:fs/promises";
|
|
7975
8198
|
import { promisify } from "node:util";
|
|
@@ -8016,50 +8239,52 @@ async function runDoctor() {
|
|
|
8016
8239
|
async function checkPackageManager() {
|
|
8017
8240
|
const execFileAsync = promisify(execFile);
|
|
8018
8241
|
try {
|
|
8019
|
-
const { stdout } = await execFileAsync("
|
|
8020
|
-
const
|
|
8021
|
-
|
|
8022
|
-
|
|
8242
|
+
const { stdout: npmStdout } = await execFileAsync("npm", ["--version"]);
|
|
8243
|
+
const npmVersion = npmStdout.trim();
|
|
8244
|
+
try {
|
|
8245
|
+
const { stdout: bunStdout } = await execFileAsync("bun", ["--version"]);
|
|
8246
|
+
const bunVersion = bunStdout.trim();
|
|
8247
|
+
const firstPart = bunVersion.split(".")[0];
|
|
8248
|
+
if (!firstPart) {
|
|
8249
|
+
return {
|
|
8250
|
+
name: "Package Manager",
|
|
8251
|
+
passed: false,
|
|
8252
|
+
message: `Invalid Bun version format: ${bunVersion}`,
|
|
8253
|
+
fix: "Reinstall Bun: curl -fsSL https://bun.sh/install | bash"
|
|
8254
|
+
};
|
|
8255
|
+
}
|
|
8256
|
+
const major = Number.parseInt(firstPart, 10);
|
|
8257
|
+
if (major < 1) {
|
|
8258
|
+
return {
|
|
8259
|
+
name: "Package Manager",
|
|
8260
|
+
passed: false,
|
|
8261
|
+
message: `npm v${npmVersion}; bun v${bunVersion}`,
|
|
8262
|
+
fix: "Upgrade Bun: curl -fsSL https://bun.sh/install | bash"
|
|
8263
|
+
};
|
|
8264
|
+
}
|
|
8023
8265
|
return {
|
|
8024
8266
|
name: "Package Manager",
|
|
8025
|
-
passed:
|
|
8026
|
-
message: `
|
|
8027
|
-
fix: "Reinstall Bun: curl -fsSL https://bun.sh/install | bash"
|
|
8267
|
+
passed: true,
|
|
8268
|
+
message: `npm v${npmVersion}; bun v${bunVersion}`
|
|
8028
8269
|
};
|
|
8029
|
-
}
|
|
8030
|
-
const major = Number.parseInt(firstPart, 10);
|
|
8031
|
-
if (major < 1) {
|
|
8270
|
+
} catch {
|
|
8032
8271
|
return {
|
|
8033
8272
|
name: "Package Manager",
|
|
8034
|
-
passed:
|
|
8035
|
-
message: `
|
|
8036
|
-
fix: "Upgrade Bun: curl -fsSL https://bun.sh/install | bash"
|
|
8273
|
+
passed: true,
|
|
8274
|
+
message: `npm v${npmVersion}`
|
|
8037
8275
|
};
|
|
8038
8276
|
}
|
|
8039
|
-
return {
|
|
8040
|
-
name: "Package Manager",
|
|
8041
|
-
passed: true,
|
|
8042
|
-
message: `bun v${version2}`
|
|
8043
|
-
};
|
|
8044
|
-
} catch {}
|
|
8045
|
-
try {
|
|
8046
|
-
const { stdout } = await execFileAsync("npm", ["--version"]);
|
|
8047
|
-
return {
|
|
8048
|
-
name: "Package Manager",
|
|
8049
|
-
passed: true,
|
|
8050
|
-
message: `npm v${stdout.trim()}`
|
|
8051
|
-
};
|
|
8052
8277
|
} catch {
|
|
8053
8278
|
return {
|
|
8054
8279
|
name: "Package Manager",
|
|
8055
8280
|
passed: false,
|
|
8056
|
-
message: "
|
|
8057
|
-
fix: "Install
|
|
8281
|
+
message: "npm is not installed",
|
|
8282
|
+
fix: "Install Node.js and npm: https://nodejs.org/"
|
|
8058
8283
|
};
|
|
8059
8284
|
}
|
|
8060
8285
|
}
|
|
8061
8286
|
async function checkOmniLocalDir() {
|
|
8062
|
-
const exists =
|
|
8287
|
+
const exists = existsSync26(".omni");
|
|
8063
8288
|
if (!exists) {
|
|
8064
8289
|
return {
|
|
8065
8290
|
name: ".omni/ directory",
|
|
@@ -8076,7 +8301,7 @@ async function checkOmniLocalDir() {
|
|
|
8076
8301
|
}
|
|
8077
8302
|
async function checkConfig() {
|
|
8078
8303
|
const configPath = "omni.toml";
|
|
8079
|
-
if (!
|
|
8304
|
+
if (!existsSync26(configPath)) {
|
|
8080
8305
|
return {
|
|
8081
8306
|
name: "Configuration",
|
|
8082
8307
|
passed: false,
|
|
@@ -8103,7 +8328,7 @@ async function checkConfig() {
|
|
|
8103
8328
|
}
|
|
8104
8329
|
async function checkRootGitignore() {
|
|
8105
8330
|
const gitignorePath = ".gitignore";
|
|
8106
|
-
if (!
|
|
8331
|
+
if (!existsSync26(gitignorePath)) {
|
|
8107
8332
|
return {
|
|
8108
8333
|
name: "Root .gitignore",
|
|
8109
8334
|
passed: false,
|
|
@@ -8137,7 +8362,7 @@ async function checkRootGitignore() {
|
|
|
8137
8362
|
}
|
|
8138
8363
|
async function checkCapabilitiesDir() {
|
|
8139
8364
|
const capabilitiesDirPath = ".omni/capabilities";
|
|
8140
|
-
if (!
|
|
8365
|
+
if (!existsSync26(capabilitiesDirPath)) {
|
|
8141
8366
|
return {
|
|
8142
8367
|
name: "Capabilities Directory",
|
|
8143
8368
|
passed: true,
|
|
@@ -8153,7 +8378,7 @@ async function checkCapabilitiesDir() {
|
|
|
8153
8378
|
|
|
8154
8379
|
// src/commands/init.ts
|
|
8155
8380
|
import { exec } from "node:child_process";
|
|
8156
|
-
import { existsSync as
|
|
8381
|
+
import { existsSync as existsSync27, mkdirSync as mkdirSync10 } from "node:fs";
|
|
8157
8382
|
import { readFile as readFile21, writeFile as writeFile23 } from "node:fs/promises";
|
|
8158
8383
|
import { promisify as promisify2 } from "node:util";
|
|
8159
8384
|
init_src();
|
|
@@ -8223,7 +8448,7 @@ async function runInit(_flags, providerArg) {
|
|
|
8223
8448
|
}
|
|
8224
8449
|
}
|
|
8225
8450
|
await writeEnabledProviders(providerIds);
|
|
8226
|
-
if (!
|
|
8451
|
+
if (!existsSync27("omni.toml")) {
|
|
8227
8452
|
await writeConfig({
|
|
8228
8453
|
profiles: {
|
|
8229
8454
|
default: {
|
|
@@ -8239,7 +8464,7 @@ async function runInit(_flags, providerArg) {
|
|
|
8239
8464
|
});
|
|
8240
8465
|
await setActiveProfile("default");
|
|
8241
8466
|
}
|
|
8242
|
-
if (!
|
|
8467
|
+
if (!existsSync27("OMNI.md")) {
|
|
8243
8468
|
await writeFile23("OMNI.md", generateOmniMdTemplate(), "utf-8");
|
|
8244
8469
|
}
|
|
8245
8470
|
const config3 = await loadConfig();
|
|
@@ -8317,7 +8542,7 @@ async function addProviderFilesToGitignore(entries) {
|
|
|
8317
8542
|
async function addToGitignore(entriesToAdd, sectionHeader) {
|
|
8318
8543
|
const gitignorePath = ".gitignore";
|
|
8319
8544
|
let content = "";
|
|
8320
|
-
if (
|
|
8545
|
+
if (existsSync27(gitignorePath)) {
|
|
8321
8546
|
content = await readFile21(gitignorePath, "utf-8");
|
|
8322
8547
|
}
|
|
8323
8548
|
const lines = content.split(`
|
|
@@ -8349,7 +8574,7 @@ async function getTrackedProviderFiles(files) {
|
|
|
8349
8574
|
}
|
|
8350
8575
|
|
|
8351
8576
|
// src/commands/profile.ts
|
|
8352
|
-
import { existsSync as
|
|
8577
|
+
import { existsSync as existsSync28 } from "node:fs";
|
|
8353
8578
|
init_src();
|
|
8354
8579
|
import { buildCommand as buildCommand5, buildRouteMap as buildRouteMap3 } from "@stricli/core";
|
|
8355
8580
|
var listCommand2 = buildCommand5({
|
|
@@ -8393,7 +8618,7 @@ var profileRoutes = buildRouteMap3({
|
|
|
8393
8618
|
});
|
|
8394
8619
|
async function runProfileList() {
|
|
8395
8620
|
try {
|
|
8396
|
-
if (!
|
|
8621
|
+
if (!existsSync28("omni.toml")) {
|
|
8397
8622
|
console.log("✗ No config file found");
|
|
8398
8623
|
console.log(" Run: omnidev init");
|
|
8399
8624
|
process.exit(1);
|
|
@@ -8433,7 +8658,7 @@ async function runProfileList() {
|
|
|
8433
8658
|
}
|
|
8434
8659
|
async function runProfileSet(profileName) {
|
|
8435
8660
|
try {
|
|
8436
|
-
if (!
|
|
8661
|
+
if (!existsSync28("omni.toml")) {
|
|
8437
8662
|
console.log("✗ No config file found");
|
|
8438
8663
|
console.log(" Run: omnidev init");
|
|
8439
8664
|
process.exit(1);
|
|
@@ -8582,7 +8807,7 @@ var providerRoutes = buildRouteMap4({
|
|
|
8582
8807
|
|
|
8583
8808
|
// src/commands/security.ts
|
|
8584
8809
|
init_src();
|
|
8585
|
-
import { existsSync as
|
|
8810
|
+
import { existsSync as existsSync29 } from "node:fs";
|
|
8586
8811
|
import { buildCommand as buildCommand7, buildRouteMap as buildRouteMap5 } from "@stricli/core";
|
|
8587
8812
|
var VALID_FINDING_TYPES = [
|
|
8588
8813
|
"unicode_bidi",
|
|
@@ -8621,7 +8846,9 @@ async function filterAllowedFindings(summary, options = {}) {
|
|
|
8621
8846
|
symlink_escape: 0,
|
|
8622
8847
|
symlink_absolute: 0,
|
|
8623
8848
|
suspicious_script: 0,
|
|
8624
|
-
binary_file: 0
|
|
8849
|
+
binary_file: 0,
|
|
8850
|
+
hidden_command: 0,
|
|
8851
|
+
network_request: 0
|
|
8625
8852
|
};
|
|
8626
8853
|
const findingsBySeverity = {
|
|
8627
8854
|
low: 0,
|
|
@@ -8699,7 +8926,7 @@ function formatFindingsWithHints(summary) {
|
|
|
8699
8926
|
}
|
|
8700
8927
|
async function runSecurityIssues(flags = {}) {
|
|
8701
8928
|
try {
|
|
8702
|
-
if (!
|
|
8929
|
+
if (!existsSync29("omni.toml")) {
|
|
8703
8930
|
console.log("No config file found");
|
|
8704
8931
|
console.log(" Run: omnidev init");
|
|
8705
8932
|
process.exit(1);
|
|
@@ -8954,7 +9181,7 @@ var securityRoutes = buildRouteMap5({
|
|
|
8954
9181
|
});
|
|
8955
9182
|
|
|
8956
9183
|
// src/commands/sync.ts
|
|
8957
|
-
import { existsSync as
|
|
9184
|
+
import { existsSync as existsSync30 } from "node:fs";
|
|
8958
9185
|
init_src();
|
|
8959
9186
|
import { buildCommand as buildCommand8 } from "@stricli/core";
|
|
8960
9187
|
var PROVIDERS_STATE_PATH = ".omni/state/providers.json";
|
|
@@ -8972,7 +9199,7 @@ async function runSync() {
|
|
|
8972
9199
|
const config3 = await loadConfig();
|
|
8973
9200
|
const activeProfile = await getActiveProfile() ?? "default";
|
|
8974
9201
|
let adapters = await getEnabledAdapters();
|
|
8975
|
-
if (!
|
|
9202
|
+
if (!existsSync30(PROVIDERS_STATE_PATH) || adapters.length === 0) {
|
|
8976
9203
|
console.log("No providers configured yet. Select your provider(s):");
|
|
8977
9204
|
const providerIds = await promptForProviders();
|
|
8978
9205
|
await writeEnabledProviders(providerIds);
|
|
@@ -9182,9 +9409,9 @@ async function buildDynamicApp() {
|
|
|
9182
9409
|
security: securityRoutes
|
|
9183
9410
|
};
|
|
9184
9411
|
debug("Core routes registered", Object.keys(routes));
|
|
9185
|
-
const configPath =
|
|
9186
|
-
debug("Checking for config", { configPath, exists:
|
|
9187
|
-
if (
|
|
9412
|
+
const configPath = join28(process.cwd(), "omni.toml");
|
|
9413
|
+
debug("Checking for config", { configPath, exists: existsSync31(configPath), cwd: process.cwd() });
|
|
9414
|
+
if (existsSync31(configPath)) {
|
|
9188
9415
|
try {
|
|
9189
9416
|
debug("Loading capability commands...");
|
|
9190
9417
|
const capabilityCommands = await loadCapabilityCommands();
|
|
@@ -9259,25 +9486,25 @@ async function loadCapabilityCommands() {
|
|
|
9259
9486
|
return commands;
|
|
9260
9487
|
}
|
|
9261
9488
|
async function loadCapabilityExport(capability3) {
|
|
9262
|
-
const capabilityPath =
|
|
9263
|
-
const builtIndexPath =
|
|
9264
|
-
const jsIndexPath =
|
|
9265
|
-
const tsIndexPath =
|
|
9489
|
+
const capabilityPath = join28(process.cwd(), capability3.path);
|
|
9490
|
+
const builtIndexPath = join28(capabilityPath, "dist", "index.js");
|
|
9491
|
+
const jsIndexPath = join28(capabilityPath, "index.js");
|
|
9492
|
+
const tsIndexPath = join28(capabilityPath, "index.ts");
|
|
9266
9493
|
debug(`Checking entry points for '${capability3.id}'`, {
|
|
9267
9494
|
capabilityPath,
|
|
9268
9495
|
builtIndexPath,
|
|
9269
|
-
builtExists:
|
|
9496
|
+
builtExists: existsSync31(builtIndexPath),
|
|
9270
9497
|
jsIndexPath,
|
|
9271
|
-
jsExists:
|
|
9498
|
+
jsExists: existsSync31(jsIndexPath),
|
|
9272
9499
|
tsIndexPath,
|
|
9273
|
-
tsExists:
|
|
9500
|
+
tsExists: existsSync31(tsIndexPath)
|
|
9274
9501
|
});
|
|
9275
9502
|
let indexPath = null;
|
|
9276
|
-
if (
|
|
9503
|
+
if (existsSync31(builtIndexPath)) {
|
|
9277
9504
|
indexPath = builtIndexPath;
|
|
9278
|
-
} else if (
|
|
9505
|
+
} else if (existsSync31(jsIndexPath)) {
|
|
9279
9506
|
indexPath = jsIndexPath;
|
|
9280
|
-
} else if (
|
|
9507
|
+
} else if (existsSync31(tsIndexPath)) {
|
|
9281
9508
|
indexPath = tsIndexPath;
|
|
9282
9509
|
}
|
|
9283
9510
|
if (!indexPath) {
|