omniagent 0.1.13 → 0.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -9
- package/dist/agy-Clt40QYQ.js +138 -0
- package/dist/{claude-DWeyS4fP.js → claude-BuXp9FHS.js} +1 -1
- package/dist/cli.js +869 -134
- package/dist/{codex-0b2YLh_8.js → codex-OCvtxDjw.js} +1 -1
- package/dist/{pty-CZBSAJzE.js → pty-CMd3Wxfe.js} +2 -2
- package/package.json +4 -1
- package/dist/gemini-BVRg6OMO.js +0 -437
package/dist/cli.js
CHANGED
|
@@ -3,7 +3,7 @@ import { constants, realpathSync, existsSync, readFileSync } from "node:fs";
|
|
|
3
3
|
import { pathToFileURL, fileURLToPath } from "node:url";
|
|
4
4
|
import yargs from "yargs";
|
|
5
5
|
import { hideBin } from "yargs/helpers";
|
|
6
|
-
import { stat, rm, readdir, access, readFile, mkdir, writeFile, rename } from "node:fs/promises";
|
|
6
|
+
import { stat, rm, readdir, access, readFile, mkdir, writeFile, rename, mkdtemp } from "node:fs/promises";
|
|
7
7
|
import path from "node:path";
|
|
8
8
|
import { createHash, randomUUID } from "node:crypto";
|
|
9
9
|
import os from "node:os";
|
|
@@ -11,6 +11,9 @@ import { Minimatch } from "minimatch";
|
|
|
11
11
|
import { createInterface } from "node:readline/promises";
|
|
12
12
|
import { TextDecoder } from "node:util";
|
|
13
13
|
import { spawn } from "node:child_process";
|
|
14
|
+
import Ajv from "ajv";
|
|
15
|
+
import Ajv2019 from "ajv/dist/2019.js";
|
|
16
|
+
import Ajv2020 from "ajv/dist/2020.js";
|
|
14
17
|
async function pathExists$2(candidate) {
|
|
15
18
|
try {
|
|
16
19
|
await stat(candidate);
|
|
@@ -475,14 +478,14 @@ const ALLOWED_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set([
|
|
|
475
478
|
]);
|
|
476
479
|
const ALLOWED_CATEGORY_KEYS = new Set(PROFILE_CATEGORIES);
|
|
477
480
|
const ALLOWED_TARGET_SETTING_KEYS = /* @__PURE__ */ new Set(["enabled"]);
|
|
478
|
-
function isPlainObject$
|
|
481
|
+
function isPlainObject$2(value) {
|
|
479
482
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
480
483
|
}
|
|
481
484
|
function pushError(errors, path2, message) {
|
|
482
485
|
errors.push({ path: path2, message });
|
|
483
486
|
}
|
|
484
487
|
function validatePatternMap(value, pathPrefix, errors) {
|
|
485
|
-
if (!isPlainObject$
|
|
488
|
+
if (!isPlainObject$2(value)) {
|
|
486
489
|
pushError(errors, pathPrefix, "must be an object.");
|
|
487
490
|
return;
|
|
488
491
|
}
|
|
@@ -507,7 +510,7 @@ function validatePatternMap(value, pathPrefix, errors) {
|
|
|
507
510
|
}
|
|
508
511
|
}
|
|
509
512
|
function validateTargets(value, errors) {
|
|
510
|
-
if (!isPlainObject$
|
|
513
|
+
if (!isPlainObject$2(value)) {
|
|
511
514
|
pushError(errors, "targets", "must be an object.");
|
|
512
515
|
return;
|
|
513
516
|
}
|
|
@@ -516,7 +519,7 @@ function validateTargets(value, errors) {
|
|
|
516
519
|
pushError(errors, "targets", `target keys must be non-empty strings (got "${targetName}").`);
|
|
517
520
|
continue;
|
|
518
521
|
}
|
|
519
|
-
if (!isPlainObject$
|
|
522
|
+
if (!isPlainObject$2(setting)) {
|
|
520
523
|
pushError(errors, `targets.${targetName}`, "must be an object.");
|
|
521
524
|
continue;
|
|
522
525
|
}
|
|
@@ -532,7 +535,7 @@ function validateTargets(value, errors) {
|
|
|
532
535
|
}
|
|
533
536
|
function validateProfile(value) {
|
|
534
537
|
const errors = [];
|
|
535
|
-
if (!isPlainObject$
|
|
538
|
+
if (!isPlainObject$2(value)) {
|
|
536
539
|
return {
|
|
537
540
|
valid: false,
|
|
538
541
|
errors: [{ path: "", message: "profile must be a JSON object." }]
|
|
@@ -578,7 +581,7 @@ function validateProfile(value) {
|
|
|
578
581
|
};
|
|
579
582
|
}
|
|
580
583
|
function validateVariables(value, errors) {
|
|
581
|
-
if (!isPlainObject$
|
|
584
|
+
if (!isPlainObject$2(value)) {
|
|
582
585
|
pushError(errors, "variables", "must be an object of string values.");
|
|
583
586
|
return;
|
|
584
587
|
}
|
|
@@ -1272,6 +1275,74 @@ function resolveEffectiveTargets(options) {
|
|
|
1272
1275
|
const skipSet = new Set(overrideSkip.map((target) => normalizeTargetName(target)));
|
|
1273
1276
|
return dedupeTargets(base.filter((target) => !skipSet.has(normalizeTargetName(target))));
|
|
1274
1277
|
}
|
|
1278
|
+
const agyTarget = {
|
|
1279
|
+
id: "agy",
|
|
1280
|
+
displayName: "Antigravity CLI",
|
|
1281
|
+
aliases: ["gemini"],
|
|
1282
|
+
cli: {
|
|
1283
|
+
modes: {
|
|
1284
|
+
interactive: { command: "agy" },
|
|
1285
|
+
oneShot: { command: "agy" }
|
|
1286
|
+
},
|
|
1287
|
+
// agy requires the prompt as -p's argument; the shim always passes the
|
|
1288
|
+
// (possibly stdin-derived) prompt inline, so piped stdin works.
|
|
1289
|
+
prompt: { type: "flag", flag: ["-p"] },
|
|
1290
|
+
flags: {
|
|
1291
|
+
approval: {
|
|
1292
|
+
values: {
|
|
1293
|
+
prompt: [],
|
|
1294
|
+
"auto-edit": null,
|
|
1295
|
+
yolo: ["--dangerously-skip-permissions"]
|
|
1296
|
+
}
|
|
1297
|
+
},
|
|
1298
|
+
sandbox: {
|
|
1299
|
+
values: {
|
|
1300
|
+
"workspace-write": ["--sandbox"],
|
|
1301
|
+
off: []
|
|
1302
|
+
}
|
|
1303
|
+
},
|
|
1304
|
+
output: {
|
|
1305
|
+
byMode: {
|
|
1306
|
+
"one-shot": {
|
|
1307
|
+
text: [],
|
|
1308
|
+
json: null,
|
|
1309
|
+
"stream-json": null
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
},
|
|
1313
|
+
// Model names are display strings, e.g. "Gemini 3.5 Flash (Low)"; list via `agy models`.
|
|
1314
|
+
model: { flag: ["--model"] },
|
|
1315
|
+
structuredOutputFallback: {
|
|
1316
|
+
extraction: { type: "text" }
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
},
|
|
1320
|
+
outputs: {
|
|
1321
|
+
skills: "{repoRoot}/.agents/skills/{itemName}",
|
|
1322
|
+
subagents: {
|
|
1323
|
+
path: "{repoRoot}/.agents/skills/{itemName}",
|
|
1324
|
+
fallback: { mode: "convert", targetType: "skills" }
|
|
1325
|
+
},
|
|
1326
|
+
commands: {
|
|
1327
|
+
fallback: { mode: "convert", targetType: "skills" }
|
|
1328
|
+
},
|
|
1329
|
+
instructions: {
|
|
1330
|
+
filename: "AGENTS.md",
|
|
1331
|
+
group: "agents"
|
|
1332
|
+
}
|
|
1333
|
+
},
|
|
1334
|
+
usage: {
|
|
1335
|
+
windows: ["credits"],
|
|
1336
|
+
launch: {
|
|
1337
|
+
command: "agy",
|
|
1338
|
+
timeoutMs: 7e4
|
|
1339
|
+
},
|
|
1340
|
+
extract: async (context) => {
|
|
1341
|
+
const { extractAgyUsage } = await import("./agy-Clt40QYQ.js");
|
|
1342
|
+
return extractAgyUsage(context);
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
};
|
|
1275
1346
|
const claudeTarget = {
|
|
1276
1347
|
id: "claude",
|
|
1277
1348
|
displayName: "Claude Code",
|
|
@@ -1298,7 +1369,13 @@ const claudeTarget = {
|
|
|
1298
1369
|
}
|
|
1299
1370
|
}
|
|
1300
1371
|
},
|
|
1301
|
-
model: { flag: ["--model"] }
|
|
1372
|
+
model: { flag: ["--model"] },
|
|
1373
|
+
structuredOutput: {
|
|
1374
|
+
delivery: "inline",
|
|
1375
|
+
flag: ["--json-schema"],
|
|
1376
|
+
companionArgs: ["--output-format", "json"],
|
|
1377
|
+
extraction: { type: "json-envelope", field: "structured_output" }
|
|
1378
|
+
}
|
|
1302
1379
|
}
|
|
1303
1380
|
},
|
|
1304
1381
|
outputs: {
|
|
@@ -1322,7 +1399,7 @@ const claudeTarget = {
|
|
|
1322
1399
|
timeoutMs: 6e4
|
|
1323
1400
|
},
|
|
1324
1401
|
extract: async (context) => {
|
|
1325
|
-
const { extractClaudeUsage } = await import("./claude-
|
|
1402
|
+
const { extractClaudeUsage } = await import("./claude-BuXp9FHS.js");
|
|
1326
1403
|
return extractClaudeUsage(context);
|
|
1327
1404
|
}
|
|
1328
1405
|
}
|
|
@@ -1368,7 +1445,12 @@ const codexTarget = {
|
|
|
1368
1445
|
}
|
|
1369
1446
|
},
|
|
1370
1447
|
model: { flag: ["-m"] },
|
|
1371
|
-
web: { on: ["--search"], off: ["--disable", "web_search_request"] }
|
|
1448
|
+
web: { on: ["--search"], off: ["--disable", "web_search_request"] },
|
|
1449
|
+
structuredOutput: {
|
|
1450
|
+
delivery: "file",
|
|
1451
|
+
flag: ["--output-schema"],
|
|
1452
|
+
extraction: { type: "last-message-file", flag: ["--output-last-message"] }
|
|
1453
|
+
}
|
|
1372
1454
|
}
|
|
1373
1455
|
},
|
|
1374
1456
|
outputs: {
|
|
@@ -1402,7 +1484,7 @@ const codexTarget = {
|
|
|
1402
1484
|
timeoutMs: 6e4
|
|
1403
1485
|
},
|
|
1404
1486
|
extract: async (context) => {
|
|
1405
|
-
const { extractCodexUsage } = await import("./codex-
|
|
1487
|
+
const { extractCodexUsage } = await import("./codex-OCvtxDjw.js");
|
|
1406
1488
|
return extractCodexUsage(context);
|
|
1407
1489
|
}
|
|
1408
1490
|
}
|
|
@@ -1500,7 +1582,11 @@ const copilotTarget = {
|
|
|
1500
1582
|
}
|
|
1501
1583
|
}
|
|
1502
1584
|
},
|
|
1503
|
-
model: { flag: ["--model"] }
|
|
1585
|
+
model: { flag: ["--model"] },
|
|
1586
|
+
structuredOutputFallback: {
|
|
1587
|
+
args: ["--silent"],
|
|
1588
|
+
extraction: { type: "text" }
|
|
1589
|
+
}
|
|
1504
1590
|
}
|
|
1505
1591
|
},
|
|
1506
1592
|
outputs: {
|
|
@@ -1547,74 +1633,10 @@ const copilotTarget = {
|
|
|
1547
1633
|
}
|
|
1548
1634
|
}
|
|
1549
1635
|
};
|
|
1550
|
-
const geminiTarget = {
|
|
1551
|
-
id: "gemini",
|
|
1552
|
-
displayName: "Gemini CLI",
|
|
1553
|
-
cli: {
|
|
1554
|
-
modes: {
|
|
1555
|
-
interactive: { command: "gemini" },
|
|
1556
|
-
oneShot: { command: "gemini" }
|
|
1557
|
-
},
|
|
1558
|
-
prompt: { type: "flag", flag: ["-p"] },
|
|
1559
|
-
flags: {
|
|
1560
|
-
approval: {
|
|
1561
|
-
values: {
|
|
1562
|
-
prompt: ["--approval-mode", "default"],
|
|
1563
|
-
"auto-edit": ["--approval-mode", "auto_edit"],
|
|
1564
|
-
yolo: ["--yolo"]
|
|
1565
|
-
}
|
|
1566
|
-
},
|
|
1567
|
-
sandbox: {
|
|
1568
|
-
values: {
|
|
1569
|
-
"workspace-write": ["--sandbox"],
|
|
1570
|
-
off: []
|
|
1571
|
-
}
|
|
1572
|
-
},
|
|
1573
|
-
output: {
|
|
1574
|
-
byMode: {
|
|
1575
|
-
"one-shot": {
|
|
1576
|
-
text: [],
|
|
1577
|
-
json: ["--output-format", "json"],
|
|
1578
|
-
"stream-json": ["--output-format", "stream-json"]
|
|
1579
|
-
}
|
|
1580
|
-
}
|
|
1581
|
-
},
|
|
1582
|
-
model: { flag: ["--model"] },
|
|
1583
|
-
web: { on: [], off: null }
|
|
1584
|
-
}
|
|
1585
|
-
},
|
|
1586
|
-
outputs: {
|
|
1587
|
-
skills: "{repoRoot}/.gemini/skills/{itemName}",
|
|
1588
|
-
subagents: {
|
|
1589
|
-
path: "{repoRoot}/.gemini/skills/{itemName}",
|
|
1590
|
-
fallback: { mode: "convert", targetType: "skills" }
|
|
1591
|
-
},
|
|
1592
|
-
commands: {
|
|
1593
|
-
projectPath: "{repoRoot}/.gemini/commands/{itemName}.toml",
|
|
1594
|
-
userPath: "{homeDir}/.gemini/commands/{itemName}.toml"
|
|
1595
|
-
},
|
|
1596
|
-
instructions: {
|
|
1597
|
-
filename: "GEMINI.md"
|
|
1598
|
-
}
|
|
1599
|
-
},
|
|
1600
|
-
usage: {
|
|
1601
|
-
windows: ["model"],
|
|
1602
|
-
launch: {
|
|
1603
|
-
command: "gemini",
|
|
1604
|
-
// /model inspection does not need a model override; Gemini requires session-scoped trust.
|
|
1605
|
-
args: ["--skip-trust"],
|
|
1606
|
-
timeoutMs: 7e4
|
|
1607
|
-
},
|
|
1608
|
-
extract: async (context) => {
|
|
1609
|
-
const { extractGeminiUsage } = await import("./gemini-BVRg6OMO.js");
|
|
1610
|
-
return extractGeminiUsage(context);
|
|
1611
|
-
}
|
|
1612
|
-
}
|
|
1613
|
-
};
|
|
1614
1636
|
const BUILTIN_TARGETS = [
|
|
1615
1637
|
codexTarget,
|
|
1616
1638
|
claudeTarget,
|
|
1617
|
-
|
|
1639
|
+
agyTarget,
|
|
1618
1640
|
copilotTarget
|
|
1619
1641
|
];
|
|
1620
1642
|
Object.freeze(BUILTIN_TARGETS.map((target) => target.id));
|
|
@@ -2386,7 +2408,7 @@ const COMMON_PLACEHOLDERS = /* @__PURE__ */ new Set([
|
|
|
2386
2408
|
"itemName"
|
|
2387
2409
|
]);
|
|
2388
2410
|
const COMMAND_PLACEHOLDERS = /* @__PURE__ */ new Set([...COMMON_PLACEHOLDERS, "commandLocation"]);
|
|
2389
|
-
function isPlainObject(value) {
|
|
2411
|
+
function isPlainObject$1(value) {
|
|
2390
2412
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
2391
2413
|
}
|
|
2392
2414
|
function normalizeString(value) {
|
|
@@ -2415,7 +2437,7 @@ function validateStringArray(value, label, errors, options = {}) {
|
|
|
2415
2437
|
}
|
|
2416
2438
|
}
|
|
2417
2439
|
function validateFlagMapValues(value, label, allowedValues, errors) {
|
|
2418
|
-
if (!isPlainObject(value)) {
|
|
2440
|
+
if (!isPlainObject$1(value)) {
|
|
2419
2441
|
errors.push(`${label} must be an object.`);
|
|
2420
2442
|
return;
|
|
2421
2443
|
}
|
|
@@ -2431,7 +2453,7 @@ function validateFlagMapValues(value, label, allowedValues, errors) {
|
|
|
2431
2453
|
}
|
|
2432
2454
|
}
|
|
2433
2455
|
function validateFlagMap(value, label, allowedValues, errors) {
|
|
2434
|
-
if (!isPlainObject(value)) {
|
|
2456
|
+
if (!isPlainObject$1(value)) {
|
|
2435
2457
|
errors.push(`${label} must be an object.`);
|
|
2436
2458
|
return;
|
|
2437
2459
|
}
|
|
@@ -2439,7 +2461,7 @@ function validateFlagMap(value, label, allowedValues, errors) {
|
|
|
2439
2461
|
validateFlagMapValues(value.values, `${label}.values`, allowedValues, errors);
|
|
2440
2462
|
}
|
|
2441
2463
|
if (value.byMode !== void 0) {
|
|
2442
|
-
if (!isPlainObject(value.byMode)) {
|
|
2464
|
+
if (!isPlainObject$1(value.byMode)) {
|
|
2443
2465
|
errors.push(`${label}.byMode must be an object.`);
|
|
2444
2466
|
} else {
|
|
2445
2467
|
for (const [mode, entries] of Object.entries(value.byMode)) {
|
|
@@ -2452,8 +2474,64 @@ function validateFlagMap(value, label, allowedValues, errors) {
|
|
|
2452
2474
|
}
|
|
2453
2475
|
}
|
|
2454
2476
|
}
|
|
2477
|
+
function validateStructuredOutputSpec(value, label, errors) {
|
|
2478
|
+
if (!isPlainObject$1(value)) {
|
|
2479
|
+
errors.push(`${label} must be an object.`);
|
|
2480
|
+
return;
|
|
2481
|
+
}
|
|
2482
|
+
if (value.delivery !== "inline" && value.delivery !== "file") {
|
|
2483
|
+
errors.push(`${label}.delivery must be "inline" or "file".`);
|
|
2484
|
+
}
|
|
2485
|
+
validateStringArray(value.flag, `${label}.flag`, errors);
|
|
2486
|
+
if (value.companionArgs !== void 0) {
|
|
2487
|
+
validateStringArray(value.companionArgs, `${label}.companionArgs`, errors, {
|
|
2488
|
+
allowEmpty: true
|
|
2489
|
+
});
|
|
2490
|
+
}
|
|
2491
|
+
if (!isPlainObject$1(value.extraction)) {
|
|
2492
|
+
errors.push(`${label}.extraction must be an object.`);
|
|
2493
|
+
return;
|
|
2494
|
+
}
|
|
2495
|
+
if (value.extraction.type === "json-envelope") {
|
|
2496
|
+
if (normalizeString(value.extraction.field) === null) {
|
|
2497
|
+
errors.push(`${label}.extraction.field must be a non-empty string.`);
|
|
2498
|
+
}
|
|
2499
|
+
return;
|
|
2500
|
+
}
|
|
2501
|
+
if (value.extraction.type === "last-message-file") {
|
|
2502
|
+
validateStringArray(value.extraction.flag, `${label}.extraction.flag`, errors);
|
|
2503
|
+
return;
|
|
2504
|
+
}
|
|
2505
|
+
errors.push(`${label}.extraction.type must be "json-envelope" or "last-message-file".`);
|
|
2506
|
+
}
|
|
2507
|
+
function validateStructuredOutputFallbackSpec(value, label, errors) {
|
|
2508
|
+
if (!isPlainObject$1(value)) {
|
|
2509
|
+
errors.push(`${label} must be an object.`);
|
|
2510
|
+
return;
|
|
2511
|
+
}
|
|
2512
|
+
if (value.args !== void 0) {
|
|
2513
|
+
validateStringArray(value.args, `${label}.args`, errors, { allowEmpty: true });
|
|
2514
|
+
}
|
|
2515
|
+
if (value.extraction === void 0) {
|
|
2516
|
+
return;
|
|
2517
|
+
}
|
|
2518
|
+
if (!isPlainObject$1(value.extraction)) {
|
|
2519
|
+
errors.push(`${label}.extraction must be an object.`);
|
|
2520
|
+
return;
|
|
2521
|
+
}
|
|
2522
|
+
if (value.extraction.type === "text") {
|
|
2523
|
+
return;
|
|
2524
|
+
}
|
|
2525
|
+
if (value.extraction.type === "json-envelope") {
|
|
2526
|
+
if (normalizeString(value.extraction.field) === null) {
|
|
2527
|
+
errors.push(`${label}.extraction.field must be a non-empty string.`);
|
|
2528
|
+
}
|
|
2529
|
+
return;
|
|
2530
|
+
}
|
|
2531
|
+
errors.push(`${label}.extraction.type must be "text" or "json-envelope".`);
|
|
2532
|
+
}
|
|
2455
2533
|
function validateModeCommand(value, label, errors) {
|
|
2456
|
-
if (!isPlainObject(value)) {
|
|
2534
|
+
if (!isPlainObject$1(value)) {
|
|
2457
2535
|
errors.push(`${label} must be an object.`);
|
|
2458
2536
|
return;
|
|
2459
2537
|
}
|
|
@@ -2466,7 +2544,7 @@ function validateModeCommand(value, label, errors) {
|
|
|
2466
2544
|
}
|
|
2467
2545
|
}
|
|
2468
2546
|
function validatePromptSpec(value, label, errors) {
|
|
2469
|
-
if (!isPlainObject(value)) {
|
|
2547
|
+
if (!isPlainObject$1(value)) {
|
|
2470
2548
|
errors.push(`${label} must be an object.`);
|
|
2471
2549
|
return;
|
|
2472
2550
|
}
|
|
@@ -2486,11 +2564,11 @@ function validateCliDefinition(cli, label, errors) {
|
|
|
2486
2564
|
if (!cli) {
|
|
2487
2565
|
return;
|
|
2488
2566
|
}
|
|
2489
|
-
if (!isPlainObject(cli)) {
|
|
2567
|
+
if (!isPlainObject$1(cli)) {
|
|
2490
2568
|
errors.push(`${label} must be an object.`);
|
|
2491
2569
|
return;
|
|
2492
2570
|
}
|
|
2493
|
-
if (!isPlainObject(cli.modes)) {
|
|
2571
|
+
if (!isPlainObject$1(cli.modes)) {
|
|
2494
2572
|
errors.push(`${label}.modes is required.`);
|
|
2495
2573
|
return;
|
|
2496
2574
|
}
|
|
@@ -2500,7 +2578,7 @@ function validateCliDefinition(cli, label, errors) {
|
|
|
2500
2578
|
validatePromptSpec(cli.prompt, `${label}.prompt`, errors);
|
|
2501
2579
|
}
|
|
2502
2580
|
if (cli.flags !== void 0) {
|
|
2503
|
-
if (!isPlainObject(cli.flags)) {
|
|
2581
|
+
if (!isPlainObject$1(cli.flags)) {
|
|
2504
2582
|
errors.push(`${label}.flags must be an object.`);
|
|
2505
2583
|
} else {
|
|
2506
2584
|
if (cli.flags.approval !== void 0) {
|
|
@@ -2513,7 +2591,7 @@ function validateCliDefinition(cli, label, errors) {
|
|
|
2513
2591
|
validateFlagMap(cli.flags.output, `${label}.flags.output`, OUTPUT_FORMATS, errors);
|
|
2514
2592
|
}
|
|
2515
2593
|
if (cli.flags.model !== void 0) {
|
|
2516
|
-
if (!isPlainObject(cli.flags.model)) {
|
|
2594
|
+
if (!isPlainObject$1(cli.flags.model)) {
|
|
2517
2595
|
errors.push(`${label}.flags.model must be an object.`);
|
|
2518
2596
|
} else {
|
|
2519
2597
|
validateStringArray(cli.flags.model.flag, `${label}.flags.model.flag`, errors);
|
|
@@ -2527,8 +2605,22 @@ function validateCliDefinition(cli, label, errors) {
|
|
|
2527
2605
|
}
|
|
2528
2606
|
}
|
|
2529
2607
|
}
|
|
2608
|
+
if (cli.flags.structuredOutput !== void 0) {
|
|
2609
|
+
validateStructuredOutputSpec(
|
|
2610
|
+
cli.flags.structuredOutput,
|
|
2611
|
+
`${label}.flags.structuredOutput`,
|
|
2612
|
+
errors
|
|
2613
|
+
);
|
|
2614
|
+
}
|
|
2615
|
+
if (cli.flags.structuredOutputFallback !== void 0) {
|
|
2616
|
+
validateStructuredOutputFallbackSpec(
|
|
2617
|
+
cli.flags.structuredOutputFallback,
|
|
2618
|
+
`${label}.flags.structuredOutputFallback`,
|
|
2619
|
+
errors
|
|
2620
|
+
);
|
|
2621
|
+
}
|
|
2530
2622
|
if (cli.flags.web !== void 0) {
|
|
2531
|
-
if (!isPlainObject(cli.flags.web)) {
|
|
2623
|
+
if (!isPlainObject$1(cli.flags.web)) {
|
|
2532
2624
|
errors.push(`${label}.flags.web must be an object.`);
|
|
2533
2625
|
} else {
|
|
2534
2626
|
if (cli.flags.web.on !== void 0 && cli.flags.web.on !== null) {
|
|
@@ -2554,7 +2646,7 @@ function validateCliDefinition(cli, label, errors) {
|
|
|
2554
2646
|
}
|
|
2555
2647
|
}
|
|
2556
2648
|
if (cli.passthrough !== void 0) {
|
|
2557
|
-
if (!isPlainObject(cli.passthrough)) {
|
|
2649
|
+
if (!isPlainObject$1(cli.passthrough)) {
|
|
2558
2650
|
errors.push(`${label}.passthrough must be an object.`);
|
|
2559
2651
|
} else if (cli.passthrough.position !== void 0 && cli.passthrough.position !== "after" && cli.passthrough.position !== "before-prompt") {
|
|
2560
2652
|
errors.push(`${label}.passthrough.position must be "after" or "before-prompt".`);
|
|
@@ -2568,13 +2660,13 @@ function validateUsageDefinition(usage, label, errors) {
|
|
|
2568
2660
|
if (usage === void 0) {
|
|
2569
2661
|
return;
|
|
2570
2662
|
}
|
|
2571
|
-
if (!isPlainObject(usage)) {
|
|
2663
|
+
if (!isPlainObject$1(usage)) {
|
|
2572
2664
|
errors.push(`${label} must be an object.`);
|
|
2573
2665
|
return;
|
|
2574
2666
|
}
|
|
2575
2667
|
validateStringArray(usage.windows, `${label}.windows`, errors);
|
|
2576
2668
|
if (usage.launch !== void 0) {
|
|
2577
|
-
if (!isPlainObject(usage.launch)) {
|
|
2669
|
+
if (!isPlainObject$1(usage.launch)) {
|
|
2578
2670
|
errors.push(`${label}.launch must be an object.`);
|
|
2579
2671
|
} else {
|
|
2580
2672
|
if (usage.launch.command !== void 0 && normalizeString(usage.launch.command) === null) {
|
|
@@ -2632,7 +2724,7 @@ function validateOutputDefinition(output, label, errors) {
|
|
|
2632
2724
|
validateTemplate(output, label, COMMON_PLACEHOLDERS, errors);
|
|
2633
2725
|
return;
|
|
2634
2726
|
}
|
|
2635
|
-
if (!isPlainObject(output)) {
|
|
2727
|
+
if (!isPlainObject$1(output)) {
|
|
2636
2728
|
errors.push(`${label} must be a string or an object.`);
|
|
2637
2729
|
return;
|
|
2638
2730
|
}
|
|
@@ -2647,7 +2739,7 @@ function validateCommandOutputDefinition(output, label, errors) {
|
|
|
2647
2739
|
validateTemplate(output, label, COMMAND_PLACEHOLDERS, errors);
|
|
2648
2740
|
return;
|
|
2649
2741
|
}
|
|
2650
|
-
if (!isPlainObject(output)) {
|
|
2742
|
+
if (!isPlainObject$1(output)) {
|
|
2651
2743
|
errors.push(`${label} must be a string or an object.`);
|
|
2652
2744
|
return;
|
|
2653
2745
|
}
|
|
@@ -2671,7 +2763,7 @@ function validateInstructionOutputDefinition(output, label, errors) {
|
|
|
2671
2763
|
validateTemplate(output, label, COMMON_PLACEHOLDERS, errors);
|
|
2672
2764
|
return;
|
|
2673
2765
|
}
|
|
2674
|
-
if (!isPlainObject(output)) {
|
|
2766
|
+
if (!isPlainObject$1(output)) {
|
|
2675
2767
|
errors.push(`${label} must be a string or an object.`);
|
|
2676
2768
|
return;
|
|
2677
2769
|
}
|
|
@@ -2684,7 +2776,7 @@ function validateOutputs(outputs, label, errors) {
|
|
|
2684
2776
|
if (!outputs) {
|
|
2685
2777
|
return;
|
|
2686
2778
|
}
|
|
2687
|
-
if (!isPlainObject(outputs)) {
|
|
2779
|
+
if (!isPlainObject$1(outputs)) {
|
|
2688
2780
|
errors.push(`${label} must be an object.`);
|
|
2689
2781
|
return;
|
|
2690
2782
|
}
|
|
@@ -2702,7 +2794,7 @@ function validateTargetConfig(options) {
|
|
|
2702
2794
|
if (config === null) {
|
|
2703
2795
|
return { valid: true, errors, config: null };
|
|
2704
2796
|
}
|
|
2705
|
-
if (!isPlainObject(config)) {
|
|
2797
|
+
if (!isPlainObject$1(config)) {
|
|
2706
2798
|
return {
|
|
2707
2799
|
valid: false,
|
|
2708
2800
|
errors: ["Config must export an object."],
|
|
@@ -2717,9 +2809,11 @@ function validateTargetConfig(options) {
|
|
|
2717
2809
|
}
|
|
2718
2810
|
const builtInIds = new Set(options.builtIns.map((target) => normalizeLower(target.id)));
|
|
2719
2811
|
const builtInAliasSet = /* @__PURE__ */ new Set();
|
|
2812
|
+
const builtInAliasToId = /* @__PURE__ */ new Map();
|
|
2720
2813
|
for (const target of options.builtIns) {
|
|
2721
2814
|
for (const alias of target.aliases ?? []) {
|
|
2722
2815
|
builtInAliasSet.add(normalizeLower(alias));
|
|
2816
|
+
builtInAliasToId.set(normalizeLower(alias), normalizeLower(target.id));
|
|
2723
2817
|
}
|
|
2724
2818
|
}
|
|
2725
2819
|
const seenIds = /* @__PURE__ */ new Set();
|
|
@@ -2736,7 +2830,8 @@ function validateTargetConfig(options) {
|
|
|
2736
2830
|
errors.push("disableTargets entries must be non-empty strings.");
|
|
2737
2831
|
continue;
|
|
2738
2832
|
}
|
|
2739
|
-
const
|
|
2833
|
+
const rawKey = normalizeLower(normalized);
|
|
2834
|
+
const key = builtInAliasToId.get(rawKey) ?? rawKey;
|
|
2740
2835
|
if (!builtInIds.has(key)) {
|
|
2741
2836
|
errors.push(`disableTargets includes unknown built-in: ${normalized}.`);
|
|
2742
2837
|
continue;
|
|
@@ -2755,7 +2850,7 @@ function validateTargetConfig(options) {
|
|
|
2755
2850
|
} else {
|
|
2756
2851
|
for (const [index, entry2] of config.targets.entries()) {
|
|
2757
2852
|
const label = `targets[${index}]`;
|
|
2758
|
-
if (!isPlainObject(entry2)) {
|
|
2853
|
+
if (!isPlainObject$1(entry2)) {
|
|
2759
2854
|
errors.push(`${label} must be an object.`);
|
|
2760
2855
|
continue;
|
|
2761
2856
|
}
|
|
@@ -2770,6 +2865,14 @@ function validateTargetConfig(options) {
|
|
|
2770
2865
|
} else {
|
|
2771
2866
|
seenIds.add(idKey);
|
|
2772
2867
|
}
|
|
2868
|
+
const aliasOwner = builtInAliasToId.get(idKey);
|
|
2869
|
+
if (aliasOwner) {
|
|
2870
|
+
errors.push(
|
|
2871
|
+
`${label}.id collides with built-in alias (${id}) of target ${aliasOwner}. Pick a distinct id.`
|
|
2872
|
+
);
|
|
2873
|
+
} else if (seenAliases.has(idKey)) {
|
|
2874
|
+
errors.push(`${label}.id collides with existing alias (${id}).`);
|
|
2875
|
+
}
|
|
2773
2876
|
if (entry2.displayName !== void 0 && normalizeString(entry2.displayName) === null) {
|
|
2774
2877
|
errors.push(`${label}.displayName must be a non-empty string when provided.`);
|
|
2775
2878
|
}
|
|
@@ -2779,7 +2882,8 @@ function validateTargetConfig(options) {
|
|
|
2779
2882
|
}
|
|
2780
2883
|
if (inherits) {
|
|
2781
2884
|
const inheritKey = normalizeLower(inherits);
|
|
2782
|
-
|
|
2885
|
+
const canonicalInherit = builtInAliasToId.get(inheritKey) ?? inheritKey;
|
|
2886
|
+
if (!builtInIds.has(canonicalInherit)) {
|
|
2783
2887
|
errors.push(`${label}.inherits references unknown built-in: ${inherits}.`);
|
|
2784
2888
|
}
|
|
2785
2889
|
}
|
|
@@ -2818,7 +2922,8 @@ function validateTargetConfig(options) {
|
|
|
2818
2922
|
errors.push(`${label}.aliases collides with existing target id (${aliasValue}).`);
|
|
2819
2923
|
continue;
|
|
2820
2924
|
}
|
|
2821
|
-
|
|
2925
|
+
const collidesWithOtherBuiltInAlias = builtInAliasSet.has(aliasKey) && builtInAliasToId.get(aliasKey) !== idKey;
|
|
2926
|
+
if (seenAliases.has(aliasKey) || collidesWithOtherBuiltInAlias) {
|
|
2822
2927
|
errors.push(`${label}.aliases collides with existing alias (${aliasValue}).`);
|
|
2823
2928
|
continue;
|
|
2824
2929
|
}
|
|
@@ -2835,7 +2940,8 @@ function validateTargetConfig(options) {
|
|
|
2835
2940
|
}
|
|
2836
2941
|
if (config.disableTargets && Array.isArray(config.disableTargets)) {
|
|
2837
2942
|
for (const targetId of config.disableTargets) {
|
|
2838
|
-
const
|
|
2943
|
+
const rawKey = normalizeLower(targetId);
|
|
2944
|
+
const normalized = builtInAliasToId.get(rawKey) ?? rawKey;
|
|
2839
2945
|
if (customBuiltInIds.has(normalized)) {
|
|
2840
2946
|
errors.push(`disableTargets cannot include overridden/inherited target (${targetId}).`);
|
|
2841
2947
|
}
|
|
@@ -2890,7 +2996,7 @@ function mergeOutputs(base, override) {
|
|
|
2890
2996
|
}
|
|
2891
2997
|
function resolveInheritTarget(builtIns, inherits) {
|
|
2892
2998
|
const key = normalizeKey$2(inherits);
|
|
2893
|
-
const found = builtIns.find((target) => normalizeKey$2(target.id) === key);
|
|
2999
|
+
const found = builtIns.find((target) => normalizeKey$2(target.id) === key) ?? builtIns.find((target) => (target.aliases ?? []).some((alias) => normalizeKey$2(alias) === key));
|
|
2894
3000
|
return found ?? null;
|
|
2895
3001
|
}
|
|
2896
3002
|
function resolveTargets(options) {
|
|
@@ -2899,12 +3005,18 @@ function resolveTargets(options) {
|
|
|
2899
3005
|
for (const target of builtIns) {
|
|
2900
3006
|
builtInMap.set(normalizeKey$2(target.id), target);
|
|
2901
3007
|
}
|
|
3008
|
+
const builtInAliasToId = /* @__PURE__ */ new Map();
|
|
3009
|
+
for (const target of builtIns) {
|
|
3010
|
+
for (const alias of target.aliases ?? []) {
|
|
3011
|
+
builtInAliasToId.set(normalizeKey$2(alias), normalizeKey$2(target.id));
|
|
3012
|
+
}
|
|
3013
|
+
}
|
|
2902
3014
|
const disabledTargets = [];
|
|
2903
3015
|
const disableSet = /* @__PURE__ */ new Set();
|
|
2904
3016
|
if (options.config?.disableTargets) {
|
|
2905
3017
|
for (const entry2 of options.config.disableTargets) {
|
|
2906
|
-
const
|
|
2907
|
-
disableSet.add(
|
|
3018
|
+
const rawKey = normalizeKey$2(entry2);
|
|
3019
|
+
disableSet.add(builtInAliasToId.get(rawKey) ?? rawKey);
|
|
2908
3020
|
disabledTargets.push(entry2);
|
|
2909
3021
|
}
|
|
2910
3022
|
}
|
|
@@ -2938,7 +3050,9 @@ function resolveTargets(options) {
|
|
|
2938
3050
|
resolvedTargets.push({
|
|
2939
3051
|
id: customTarget.id,
|
|
2940
3052
|
displayName: customTarget.displayName ?? inherited?.displayName ?? customTarget.id,
|
|
2941
|
-
|
|
3053
|
+
// Aliases follow the overridden built-in's identity, not the inherited
|
|
3054
|
+
// definition — inheriting them would move the alias between targets.
|
|
3055
|
+
aliases: customTarget.aliases ?? builtIn.aliases ?? [],
|
|
2942
3056
|
outputs: mergedOutputs,
|
|
2943
3057
|
cli: cloneCli(customTarget.cli ?? inherited?.cli),
|
|
2944
3058
|
usage: cloneUsage(customTarget.usage ?? inherited?.usage),
|
|
@@ -2951,7 +3065,7 @@ function resolveTargets(options) {
|
|
|
2951
3065
|
resolvedTargets.push({
|
|
2952
3066
|
id: customTarget.id,
|
|
2953
3067
|
displayName: customTarget.displayName ?? customTarget.id,
|
|
2954
|
-
aliases: customTarget.aliases ?? [],
|
|
3068
|
+
aliases: customTarget.aliases ?? builtIn.aliases ?? [],
|
|
2955
3069
|
outputs: cloneOutputs(customTarget.outputs),
|
|
2956
3070
|
cli: cloneCli(customTarget.cli),
|
|
2957
3071
|
usage: cloneUsage(customTarget.usage),
|
|
@@ -2972,7 +3086,9 @@ function resolveTargets(options) {
|
|
|
2972
3086
|
resolvedTargets.push({
|
|
2973
3087
|
id: target.id,
|
|
2974
3088
|
displayName: target.displayName ?? inherited?.displayName ?? target.id,
|
|
2975
|
-
|
|
3089
|
+
// Aliases name a specific target, so a new custom target never inherits
|
|
3090
|
+
// them — otherwise it would shadow the built-in's alias in aliasToId.
|
|
3091
|
+
aliases: target.aliases ?? [],
|
|
2976
3092
|
outputs: mergedOutputs,
|
|
2977
3093
|
cli: cloneCli(target.cli ?? inherited?.cli),
|
|
2978
3094
|
usage: cloneUsage(target.usage ?? inherited?.usage),
|
|
@@ -3144,7 +3260,7 @@ Profile files must be valid JSON. This commented version is just a guide:
|
|
|
3144
3260
|
|
|
3145
3261
|
"targets": {
|
|
3146
3262
|
"claude": { "enabled": true }, // includes Claude; overrides an earlier profile setting it false
|
|
3147
|
-
"
|
|
3263
|
+
"agy": { "enabled": false } // skips Antigravity for this profile
|
|
3148
3264
|
},
|
|
3149
3265
|
|
|
3150
3266
|
"enable": { // names/globs to include; also opts in items marked enabled:false
|
|
@@ -3578,6 +3694,18 @@ function processTemplating(content, options) {
|
|
|
3578
3694
|
const validSet = new Set(normalizedValid);
|
|
3579
3695
|
const context = { sourcePath: options.sourcePath, validAgents: normalizedValid };
|
|
3580
3696
|
const target = options.target ? options.target.toLowerCase() : null;
|
|
3697
|
+
const targetKeys = target ? /* @__PURE__ */ new Set([target, ...(options.targetAliases ?? []).map((alias) => alias.toLowerCase())]) : null;
|
|
3698
|
+
const intersects = (set) => {
|
|
3699
|
+
if (!targetKeys) {
|
|
3700
|
+
return false;
|
|
3701
|
+
}
|
|
3702
|
+
for (const key of targetKeys) {
|
|
3703
|
+
if (set.has(key)) {
|
|
3704
|
+
return true;
|
|
3705
|
+
}
|
|
3706
|
+
}
|
|
3707
|
+
return false;
|
|
3708
|
+
};
|
|
3581
3709
|
let output = "";
|
|
3582
3710
|
let index = 0;
|
|
3583
3711
|
while (index < content.length) {
|
|
@@ -3608,7 +3736,7 @@ function processTemplating(content, options) {
|
|
|
3608
3736
|
);
|
|
3609
3737
|
}
|
|
3610
3738
|
const { include, exclude } = parseSelectorList(selectorRaw, validSet, context);
|
|
3611
|
-
const shouldInclude = target === null ? false : include.size > 0 ? include
|
|
3739
|
+
const shouldInclude = target === null ? false : include.size > 0 ? intersects(include) && !intersects(exclude) : !intersects(exclude);
|
|
3612
3740
|
let cursor = contentStart;
|
|
3613
3741
|
let blockOutput = "";
|
|
3614
3742
|
while (cursor < content.length) {
|
|
@@ -3658,6 +3786,7 @@ function validateAgentTemplating(options) {
|
|
|
3658
3786
|
function applyAgentTemplating(options) {
|
|
3659
3787
|
return processTemplating(options.content, {
|
|
3660
3788
|
target: options.target,
|
|
3789
|
+
targetAliases: options.targetAliases,
|
|
3661
3790
|
validAgents: options.validAgents,
|
|
3662
3791
|
sourcePath: options.sourcePath
|
|
3663
3792
|
});
|
|
@@ -4030,6 +4159,7 @@ const DEFAULT_SKIP_DIRS = /* @__PURE__ */ new Set([
|
|
|
4030
4159
|
".git",
|
|
4031
4160
|
"node_modules",
|
|
4032
4161
|
"dist",
|
|
4162
|
+
".agents",
|
|
4033
4163
|
".claude",
|
|
4034
4164
|
".codex",
|
|
4035
4165
|
".gemini",
|
|
@@ -5167,6 +5297,7 @@ async function copySkillDirectory(options) {
|
|
|
5167
5297
|
const templated = applyAgentTemplating({
|
|
5168
5298
|
content: withScripts,
|
|
5169
5299
|
target: options.targetId,
|
|
5300
|
+
targetAliases: options.targetAliases,
|
|
5170
5301
|
validAgents: options.validAgents,
|
|
5171
5302
|
sourcePath: winner.sourcePath
|
|
5172
5303
|
});
|
|
@@ -5186,6 +5317,7 @@ const defaultSkillWriter = {
|
|
|
5186
5317
|
source: item.directoryPath,
|
|
5187
5318
|
destination: options.outputPath,
|
|
5188
5319
|
targetId: options.context.targetId,
|
|
5320
|
+
targetAliases: options.context.targetAliases,
|
|
5189
5321
|
validAgents: options.context.validAgents,
|
|
5190
5322
|
skillFileName: item.skillFileName,
|
|
5191
5323
|
outputFileName: item.outputFileName,
|
|
@@ -5211,6 +5343,7 @@ const defaultSubagentWriter = {
|
|
|
5211
5343
|
const templated = applyAgentTemplating({
|
|
5212
5344
|
content: withScripts,
|
|
5213
5345
|
target: options.context.targetId,
|
|
5346
|
+
targetAliases: options.context.targetAliases,
|
|
5214
5347
|
validAgents: options.context.validAgents,
|
|
5215
5348
|
sourcePath: item.sourcePath
|
|
5216
5349
|
});
|
|
@@ -5552,6 +5685,7 @@ async function syncInstructions(request) {
|
|
|
5552
5685
|
const content = applyAgentTemplating({
|
|
5553
5686
|
content: withScripts,
|
|
5554
5687
|
target: targetName,
|
|
5688
|
+
targetAliases: selection.target.aliases,
|
|
5555
5689
|
validAgents: request.validAgents,
|
|
5556
5690
|
sourcePath: template.sourcePath
|
|
5557
5691
|
});
|
|
@@ -5753,6 +5887,7 @@ async function syncInstructions(request) {
|
|
|
5753
5887
|
agentsDir: agentsRoot,
|
|
5754
5888
|
homeDir,
|
|
5755
5889
|
targetId: candidate.targetName,
|
|
5890
|
+
targetAliases: selectionById.get(candidate.targetName)?.target.aliases,
|
|
5756
5891
|
outputType: "instructions",
|
|
5757
5892
|
validAgents: request.validAgents
|
|
5758
5893
|
});
|
|
@@ -5805,6 +5940,7 @@ async function syncInstructions(request) {
|
|
|
5805
5940
|
agentsDir: agentsRoot,
|
|
5806
5941
|
homeDir,
|
|
5807
5942
|
targetId: candidate.targetName,
|
|
5943
|
+
targetAliases: selectionById.get(candidate.targetName)?.target.aliases,
|
|
5808
5944
|
outputType: "instructions",
|
|
5809
5945
|
validAgents: request.validAgents,
|
|
5810
5946
|
templateScriptRuntime
|
|
@@ -6301,6 +6437,7 @@ async function syncSkills(request) {
|
|
|
6301
6437
|
agentsDir: agentsDirPath,
|
|
6302
6438
|
homeDir,
|
|
6303
6439
|
targetId: target.id,
|
|
6440
|
+
targetAliases: target.aliases,
|
|
6304
6441
|
outputType: "skills",
|
|
6305
6442
|
validAgents: request.validAgents
|
|
6306
6443
|
});
|
|
@@ -6361,6 +6498,7 @@ async function syncSkills(request) {
|
|
|
6361
6498
|
agentsDir: agentsDirPath,
|
|
6362
6499
|
homeDir,
|
|
6363
6500
|
targetId: target.id,
|
|
6501
|
+
targetAliases: target.aliases,
|
|
6364
6502
|
outputType: "skills",
|
|
6365
6503
|
validAgents: request.validAgents,
|
|
6366
6504
|
templateScriptRuntime
|
|
@@ -6698,7 +6836,7 @@ function buildInvalidTargetWarnings$1(commands) {
|
|
|
6698
6836
|
}
|
|
6699
6837
|
return warnings;
|
|
6700
6838
|
}
|
|
6701
|
-
async function applyTemplatingToCommand(command, targetName, validAgents, runtime) {
|
|
6839
|
+
async function applyTemplatingToCommand(command, targetName, validAgents, runtime, targetAliases) {
|
|
6702
6840
|
const withScripts = runtime ? await evaluateTemplateScripts({
|
|
6703
6841
|
templatePath: command.sourcePath,
|
|
6704
6842
|
content: command.rawContents,
|
|
@@ -6707,6 +6845,7 @@ async function applyTemplatingToCommand(command, targetName, validAgents, runtim
|
|
|
6707
6845
|
const templatedContents = applyAgentTemplating({
|
|
6708
6846
|
content: withScripts,
|
|
6709
6847
|
target: targetName,
|
|
6848
|
+
targetAliases,
|
|
6710
6849
|
validAgents,
|
|
6711
6850
|
sourcePath: command.sourcePath
|
|
6712
6851
|
});
|
|
@@ -6974,7 +7113,8 @@ async function syncSlashCommands(request) {
|
|
|
6974
7113
|
command,
|
|
6975
7114
|
target.id,
|
|
6976
7115
|
validAgents,
|
|
6977
|
-
templateScriptRuntime
|
|
7116
|
+
templateScriptRuntime,
|
|
7117
|
+
target.aliases
|
|
6978
7118
|
);
|
|
6979
7119
|
const writer = resolveWriter(commandDef.writer, writerRegistry);
|
|
6980
7120
|
const converter = resolveConverter(commandDef.converter, converterRegistry);
|
|
@@ -7050,6 +7190,7 @@ async function syncSlashCommands(request) {
|
|
|
7050
7190
|
agentsDir: agentsDirPath,
|
|
7051
7191
|
homeDir,
|
|
7052
7192
|
targetId: target.id,
|
|
7193
|
+
targetAliases: target.aliases,
|
|
7053
7194
|
outputType: "commands",
|
|
7054
7195
|
commandLocation: selected.location,
|
|
7055
7196
|
validAgents
|
|
@@ -7111,6 +7252,7 @@ async function syncSlashCommands(request) {
|
|
|
7111
7252
|
agentsDir: agentsDirPath,
|
|
7112
7253
|
homeDir,
|
|
7113
7254
|
targetId: target.id,
|
|
7255
|
+
targetAliases: target.aliases,
|
|
7114
7256
|
outputType: "commands",
|
|
7115
7257
|
commandLocation: selected.location,
|
|
7116
7258
|
validAgents,
|
|
@@ -8027,6 +8169,7 @@ async function syncSubagents(request) {
|
|
|
8027
8169
|
agentsDir: agentsDirPath,
|
|
8028
8170
|
homeDir,
|
|
8029
8171
|
targetId: target.id,
|
|
8172
|
+
targetAliases: target.aliases,
|
|
8030
8173
|
outputType: "subagents",
|
|
8031
8174
|
validAgents
|
|
8032
8175
|
});
|
|
@@ -8087,6 +8230,7 @@ async function syncSubagents(request) {
|
|
|
8087
8230
|
agentsDir: agentsDirPath,
|
|
8088
8231
|
homeDir,
|
|
8089
8232
|
targetId: target.id,
|
|
8233
|
+
targetAliases: target.aliases,
|
|
8090
8234
|
outputType: "subagents",
|
|
8091
8235
|
validAgents,
|
|
8092
8236
|
templateScriptRuntime
|
|
@@ -8474,7 +8618,9 @@ async function checkTargetAvailability(target) {
|
|
|
8474
8618
|
checks
|
|
8475
8619
|
};
|
|
8476
8620
|
}
|
|
8477
|
-
const DEFAULT_SUPPORTED_TARGETS = BUILTIN_TARGETS.map(
|
|
8621
|
+
const DEFAULT_SUPPORTED_TARGETS = BUILTIN_TARGETS.map(
|
|
8622
|
+
(target) => target.aliases?.length ? `${target.id} (alias: ${target.aliases.join(", ")})` : target.id
|
|
8623
|
+
).join(", ");
|
|
8478
8624
|
const LOCAL_CATEGORIES = ["skills", "commands", "agents", "instructions"];
|
|
8479
8625
|
const LOCAL_CATEGORY_SET = new Set(LOCAL_CATEGORIES);
|
|
8480
8626
|
const utf8Decoder = new TextDecoder("utf-8", { fatal: true });
|
|
@@ -10377,6 +10523,7 @@ function makeUsageLimit(options) {
|
|
|
10377
10523
|
modelLabel: options.modelLabel,
|
|
10378
10524
|
percentUsed: options.percentUsed,
|
|
10379
10525
|
percentRemaining: options.percentRemaining,
|
|
10526
|
+
remainingText: emptyToNull(options.remainingText) ?? void 0,
|
|
10380
10527
|
resetAt: parseResetAt(resetText, {
|
|
10381
10528
|
now: options.now,
|
|
10382
10529
|
sourceTimeZone: options.resetSourceTimeZone ?? "local"
|
|
@@ -11142,6 +11289,9 @@ function leftCellText(row) {
|
|
|
11142
11289
|
if (row.status === "error") {
|
|
11143
11290
|
return "-";
|
|
11144
11291
|
}
|
|
11292
|
+
if (row.limit.percentRemaining == null && row.limit.remainingText) {
|
|
11293
|
+
return row.limit.remainingText;
|
|
11294
|
+
}
|
|
11145
11295
|
return percentText(row.limit.percentRemaining);
|
|
11146
11296
|
}
|
|
11147
11297
|
function resetCellText(row) {
|
|
@@ -11708,6 +11858,9 @@ function translateInvocation(invocation, cli, options = {}) {
|
|
|
11708
11858
|
args.push(...mapped);
|
|
11709
11859
|
}
|
|
11710
11860
|
}
|
|
11861
|
+
if (invocation.structuredOutput) {
|
|
11862
|
+
args.push(...invocation.structuredOutput.args);
|
|
11863
|
+
}
|
|
11711
11864
|
if (mode === "one-shot" && base.args?.includes("exec")) {
|
|
11712
11865
|
const searchIndex = args.indexOf("--search");
|
|
11713
11866
|
if (searchIndex > -1) {
|
|
@@ -11765,9 +11918,344 @@ function buildAgentArgs(invocation) {
|
|
|
11765
11918
|
warnings: translated.warnings
|
|
11766
11919
|
};
|
|
11767
11920
|
}
|
|
11921
|
+
const PREVIOUS_OUTPUT_LIMIT = 4e3;
|
|
11922
|
+
const RESPONSE_RULES = "Respond with only the JSON value - no explanations, no markdown code fences, no additional text.";
|
|
11923
|
+
function schemaBlock(schemaJson) {
|
|
11924
|
+
return `Your entire response must be a single JSON value that conforms to this JSON Schema:
|
|
11925
|
+
${schemaJson}`;
|
|
11926
|
+
}
|
|
11927
|
+
function truncate(text, limit) {
|
|
11928
|
+
if (text.length <= limit) {
|
|
11929
|
+
return text;
|
|
11930
|
+
}
|
|
11931
|
+
return `${text.slice(0, limit)}
|
|
11932
|
+
[truncated]`;
|
|
11933
|
+
}
|
|
11934
|
+
function buildFallbackPrompt(prompt, schemaJson) {
|
|
11935
|
+
const base = prompt.trim().length > 0 ? `${prompt}
|
|
11936
|
+
|
|
11937
|
+
` : "";
|
|
11938
|
+
return `${base}${schemaBlock(schemaJson)}
|
|
11939
|
+
|
|
11940
|
+
${RESPONSE_RULES}`;
|
|
11941
|
+
}
|
|
11942
|
+
function buildRetryPrompt(prompt, schemaJson, previousOutput, errors) {
|
|
11943
|
+
const base = prompt.trim().length > 0 ? `${prompt}
|
|
11944
|
+
|
|
11945
|
+
` : "";
|
|
11946
|
+
const previous = previousOutput.trim().length > 0 ? truncate(previousOutput.trim(), PREVIOUS_OUTPUT_LIMIT) : "(empty response)";
|
|
11947
|
+
const errorLines = errors.map((error) => `- ${error}`).join("\n");
|
|
11948
|
+
return [
|
|
11949
|
+
`${base}${schemaBlock(schemaJson)}`,
|
|
11950
|
+
`Your previous response failed validation.
|
|
11951
|
+
|
|
11952
|
+
Previous response:
|
|
11953
|
+
${previous}`,
|
|
11954
|
+
`Validation errors:
|
|
11955
|
+
${errorLines}`,
|
|
11956
|
+
`Respond again with only the corrected JSON value. ${RESPONSE_RULES}`
|
|
11957
|
+
].join("\n\n");
|
|
11958
|
+
}
|
|
11959
|
+
function tryParse(text) {
|
|
11960
|
+
try {
|
|
11961
|
+
return { ok: true, value: JSON.parse(text) };
|
|
11962
|
+
} catch {
|
|
11963
|
+
return null;
|
|
11964
|
+
}
|
|
11965
|
+
}
|
|
11966
|
+
function extractJsonPayload(text) {
|
|
11967
|
+
const trimmed = text.trim();
|
|
11968
|
+
if (trimmed.length === 0) {
|
|
11969
|
+
return { ok: false, error: "the response was empty" };
|
|
11970
|
+
}
|
|
11971
|
+
const whole = tryParse(trimmed);
|
|
11972
|
+
if (whole) {
|
|
11973
|
+
return whole;
|
|
11974
|
+
}
|
|
11975
|
+
const fenced = trimmed.match(/```(?:json)?\s*\n?([\s\S]*?)```/);
|
|
11976
|
+
if (fenced?.[1]) {
|
|
11977
|
+
const parsed = tryParse(fenced[1].trim());
|
|
11978
|
+
if (parsed) {
|
|
11979
|
+
return parsed;
|
|
11980
|
+
}
|
|
11981
|
+
}
|
|
11982
|
+
for (const [open, close] of [
|
|
11983
|
+
["{", "}"],
|
|
11984
|
+
["[", "]"]
|
|
11985
|
+
]) {
|
|
11986
|
+
const start = trimmed.indexOf(open);
|
|
11987
|
+
const end = trimmed.lastIndexOf(close);
|
|
11988
|
+
if (start !== -1 && end > start) {
|
|
11989
|
+
const parsed = tryParse(trimmed.slice(start, end + 1));
|
|
11990
|
+
if (parsed) {
|
|
11991
|
+
return parsed;
|
|
11992
|
+
}
|
|
11993
|
+
}
|
|
11994
|
+
}
|
|
11995
|
+
return { ok: false, error: "the response did not contain parseable JSON" };
|
|
11996
|
+
}
|
|
11997
|
+
function withPipedStdout(stdio) {
|
|
11998
|
+
if (Array.isArray(stdio)) {
|
|
11999
|
+
return [stdio[0] ?? "inherit", "pipe", stdio[2] ?? "inherit"];
|
|
12000
|
+
}
|
|
12001
|
+
return [stdio, "pipe", stdio];
|
|
12002
|
+
}
|
|
12003
|
+
function mapExitCode(code) {
|
|
12004
|
+
if (code === 0) {
|
|
12005
|
+
return { exitCode: 0, reason: "success" };
|
|
12006
|
+
}
|
|
12007
|
+
if (code === 2) {
|
|
12008
|
+
return { exitCode: 2, reason: "invalid-usage" };
|
|
12009
|
+
}
|
|
12010
|
+
if (code === 3) {
|
|
12011
|
+
return { exitCode: 3, reason: "blocked" };
|
|
12012
|
+
}
|
|
12013
|
+
return { exitCode: 1, reason: "execution-error" };
|
|
12014
|
+
}
|
|
12015
|
+
async function finalizeStructuredOutput(options) {
|
|
12016
|
+
const { plan, agentId, code, captured, stdout, stderr } = options;
|
|
12017
|
+
if (code !== 0) {
|
|
12018
|
+
if (plan.capture.type === "json-envelope" && captured.length > 0) {
|
|
12019
|
+
stderr.write(captured);
|
|
12020
|
+
}
|
|
12021
|
+
return mapExitCode(code);
|
|
12022
|
+
}
|
|
12023
|
+
if (plan.capture.type === "json-envelope") {
|
|
12024
|
+
let envelope;
|
|
12025
|
+
try {
|
|
12026
|
+
envelope = JSON.parse(captured);
|
|
12027
|
+
} catch {
|
|
12028
|
+
envelope = void 0;
|
|
12029
|
+
}
|
|
12030
|
+
if (typeof envelope !== "object" || envelope === null || Array.isArray(envelope)) {
|
|
12031
|
+
stderr.write(captured);
|
|
12032
|
+
stderr.write(`Error: ${agentId} did not return a JSON envelope.
|
|
12033
|
+
`);
|
|
12034
|
+
return { exitCode: 1, reason: "execution-error" };
|
|
12035
|
+
}
|
|
12036
|
+
const record = envelope;
|
|
12037
|
+
if (record.is_error === true) {
|
|
12038
|
+
stderr.write(captured);
|
|
12039
|
+
stderr.write(`Error: ${agentId} reported an error result.
|
|
12040
|
+
`);
|
|
12041
|
+
return { exitCode: 1, reason: "execution-error" };
|
|
12042
|
+
}
|
|
12043
|
+
const payload = record[plan.capture.field];
|
|
12044
|
+
if (payload === void 0 || payload === null) {
|
|
12045
|
+
stderr.write(captured);
|
|
12046
|
+
stderr.write(`Error: ${agentId} response is missing ${plan.capture.field}.
|
|
12047
|
+
`);
|
|
12048
|
+
return { exitCode: 1, reason: "execution-error" };
|
|
12049
|
+
}
|
|
12050
|
+
stdout.write(`${JSON.stringify(payload)}
|
|
12051
|
+
`);
|
|
12052
|
+
return { exitCode: 0, reason: "success" };
|
|
12053
|
+
}
|
|
12054
|
+
if (plan.capture.type === "fallback") {
|
|
12055
|
+
return { exitCode: 1, reason: "execution-error" };
|
|
12056
|
+
}
|
|
12057
|
+
let contents;
|
|
12058
|
+
try {
|
|
12059
|
+
contents = await readFile(plan.capture.path, "utf8");
|
|
12060
|
+
} catch {
|
|
12061
|
+
contents = "";
|
|
12062
|
+
}
|
|
12063
|
+
const trimmed = contents.trim();
|
|
12064
|
+
if (!trimmed) {
|
|
12065
|
+
stderr.write(`Error: ${agentId} did not produce a structured output message.
|
|
12066
|
+
`);
|
|
12067
|
+
return { exitCode: 1, reason: "execution-error" };
|
|
12068
|
+
}
|
|
12069
|
+
stdout.write(`${trimmed}
|
|
12070
|
+
`);
|
|
12071
|
+
return { exitCode: 0, reason: "success" };
|
|
12072
|
+
}
|
|
12073
|
+
function runCapturedAttempt(params) {
|
|
12074
|
+
return new Promise((resolve) => {
|
|
12075
|
+
let settled = false;
|
|
12076
|
+
const settle = (value) => {
|
|
12077
|
+
if (!settled) {
|
|
12078
|
+
settled = true;
|
|
12079
|
+
resolve(value);
|
|
12080
|
+
}
|
|
12081
|
+
};
|
|
12082
|
+
const child = params.spawn(params.command, params.args, { stdio: params.stdio });
|
|
12083
|
+
const chunks = [];
|
|
12084
|
+
const childStdout = child.stdout;
|
|
12085
|
+
if (childStdout) {
|
|
12086
|
+
childStdout.on("data", (chunk) => {
|
|
12087
|
+
chunks.push(Buffer.from(chunk));
|
|
12088
|
+
});
|
|
12089
|
+
}
|
|
12090
|
+
child.on("error", (error) => {
|
|
12091
|
+
params.stderr.write(`Error: ${error.message}
|
|
12092
|
+
`);
|
|
12093
|
+
settle({ kind: "spawn-error" });
|
|
12094
|
+
});
|
|
12095
|
+
child.on("close", (code) => {
|
|
12096
|
+
if (!childStdout) {
|
|
12097
|
+
params.stderr.write(`Error: ${params.agentId} stdout was not captured.
|
|
12098
|
+
`);
|
|
12099
|
+
settle({ kind: "spawn-error" });
|
|
12100
|
+
return;
|
|
12101
|
+
}
|
|
12102
|
+
settle({ kind: "closed", code, captured: Buffer.concat(chunks).toString("utf8") });
|
|
12103
|
+
});
|
|
12104
|
+
});
|
|
12105
|
+
}
|
|
12106
|
+
function extractEnvelopeText(params) {
|
|
12107
|
+
const { captured, field, agentId, stderr } = params;
|
|
12108
|
+
let envelope;
|
|
12109
|
+
try {
|
|
12110
|
+
envelope = JSON.parse(captured);
|
|
12111
|
+
} catch {
|
|
12112
|
+
envelope = void 0;
|
|
12113
|
+
}
|
|
12114
|
+
if (typeof envelope !== "object" || envelope === null || Array.isArray(envelope)) {
|
|
12115
|
+
if (captured.length > 0) {
|
|
12116
|
+
stderr.write(captured);
|
|
12117
|
+
}
|
|
12118
|
+
stderr.write(`Error: ${agentId} did not return a JSON envelope.
|
|
12119
|
+
`);
|
|
12120
|
+
return { ok: false };
|
|
12121
|
+
}
|
|
12122
|
+
const record = envelope;
|
|
12123
|
+
if (record.error !== void 0 && record.error !== null) {
|
|
12124
|
+
stderr.write(captured);
|
|
12125
|
+
stderr.write(`Error: ${agentId} reported an error result.
|
|
12126
|
+
`);
|
|
12127
|
+
return { ok: false };
|
|
12128
|
+
}
|
|
12129
|
+
const payload = record[field];
|
|
12130
|
+
if (payload === void 0 || payload === null) {
|
|
12131
|
+
stderr.write(captured);
|
|
12132
|
+
stderr.write(`Error: ${agentId} response is missing ${field}.
|
|
12133
|
+
`);
|
|
12134
|
+
return { ok: false };
|
|
12135
|
+
}
|
|
12136
|
+
return { ok: true, text: typeof payload === "string" ? payload : JSON.stringify(payload) };
|
|
12137
|
+
}
|
|
12138
|
+
async function runFallbackAttempts(params) {
|
|
12139
|
+
const { invocation, plan, capture, options, stdout, stderr } = params;
|
|
12140
|
+
const agentId = invocation.agent.id;
|
|
12141
|
+
const spawn$1 = options.spawn ?? spawn;
|
|
12142
|
+
const stdio = withPipedStdout(options.stdio ?? "inherit");
|
|
12143
|
+
const originalPrompt = invocation.prompt ?? "";
|
|
12144
|
+
const validate = plan.validate ?? (() => ({ valid: true, errors: [] }));
|
|
12145
|
+
let feedback = null;
|
|
12146
|
+
for (let attempt = 1; attempt <= capture.maxAttempts; attempt += 1) {
|
|
12147
|
+
const attemptPrompt = feedback ? buildRetryPrompt(originalPrompt, plan.schemaJson, feedback.output, feedback.errors) : buildFallbackPrompt(originalPrompt, plan.schemaJson);
|
|
12148
|
+
const built = buildAgentArgs({ ...invocation, prompt: attemptPrompt });
|
|
12149
|
+
if (attempt === 1) {
|
|
12150
|
+
if (options.traceTranslate) {
|
|
12151
|
+
const trace = {
|
|
12152
|
+
agent: agentId,
|
|
12153
|
+
mode: invocation.mode,
|
|
12154
|
+
command: built.command,
|
|
12155
|
+
args: built.args,
|
|
12156
|
+
shimArgs: built.shimArgs,
|
|
12157
|
+
passthroughArgs: built.passthroughArgs,
|
|
12158
|
+
warnings: built.warnings,
|
|
12159
|
+
requests: invocation.requests,
|
|
12160
|
+
structuredOutput: { capture: capture.type, maxAttempts: capture.maxAttempts }
|
|
12161
|
+
};
|
|
12162
|
+
stderr.write(`OA_TRANSLATION=${JSON.stringify(trace)}
|
|
12163
|
+
`);
|
|
12164
|
+
}
|
|
12165
|
+
for (const warning of built.warnings) {
|
|
12166
|
+
stderr.write(`${warning}
|
|
12167
|
+
`);
|
|
12168
|
+
}
|
|
12169
|
+
for (const notice of plan.notices ?? []) {
|
|
12170
|
+
stderr.write(`${notice}
|
|
12171
|
+
`);
|
|
12172
|
+
}
|
|
12173
|
+
}
|
|
12174
|
+
const attemptResult = await runCapturedAttempt({
|
|
12175
|
+
spawn: spawn$1,
|
|
12176
|
+
command: built.command,
|
|
12177
|
+
args: built.args,
|
|
12178
|
+
stdio,
|
|
12179
|
+
agentId,
|
|
12180
|
+
stderr
|
|
12181
|
+
});
|
|
12182
|
+
if (attemptResult.kind === "spawn-error") {
|
|
12183
|
+
return { exitCode: 1, reason: "execution-error" };
|
|
12184
|
+
}
|
|
12185
|
+
if (attemptResult.code !== 0) {
|
|
12186
|
+
if (attemptResult.captured.length > 0) {
|
|
12187
|
+
stderr.write(attemptResult.captured);
|
|
12188
|
+
}
|
|
12189
|
+
return mapExitCode(attemptResult.code);
|
|
12190
|
+
}
|
|
12191
|
+
let responseText = attemptResult.captured;
|
|
12192
|
+
if (capture.extraction.type === "json-envelope") {
|
|
12193
|
+
const outcome = extractEnvelopeText({
|
|
12194
|
+
captured: attemptResult.captured,
|
|
12195
|
+
field: capture.extraction.field,
|
|
12196
|
+
agentId,
|
|
12197
|
+
stderr
|
|
12198
|
+
});
|
|
12199
|
+
if (!outcome.ok) {
|
|
12200
|
+
return { exitCode: 1, reason: "execution-error" };
|
|
12201
|
+
}
|
|
12202
|
+
responseText = outcome.text;
|
|
12203
|
+
}
|
|
12204
|
+
const extracted = extractJsonPayload(responseText);
|
|
12205
|
+
if (extracted.ok) {
|
|
12206
|
+
const result = validate(extracted.value);
|
|
12207
|
+
if (result.valid) {
|
|
12208
|
+
stdout.write(`${JSON.stringify(extracted.value)}
|
|
12209
|
+
`);
|
|
12210
|
+
return { exitCode: 0, reason: "success" };
|
|
12211
|
+
}
|
|
12212
|
+
feedback = { output: responseText, errors: result.errors };
|
|
12213
|
+
} else {
|
|
12214
|
+
feedback = { output: responseText, errors: [extracted.error] };
|
|
12215
|
+
}
|
|
12216
|
+
if (attempt < capture.maxAttempts) {
|
|
12217
|
+
stderr.write(
|
|
12218
|
+
`Attempt ${attempt} failed schema validation; retrying (${attempt + 1}/${capture.maxAttempts}).
|
|
12219
|
+
`
|
|
12220
|
+
);
|
|
12221
|
+
for (const error of feedback.errors) {
|
|
12222
|
+
stderr.write(`- ${error}
|
|
12223
|
+
`);
|
|
12224
|
+
}
|
|
12225
|
+
}
|
|
12226
|
+
}
|
|
12227
|
+
if (feedback) {
|
|
12228
|
+
const lastOutput = feedback.output.trim();
|
|
12229
|
+
if (lastOutput.length > 0) {
|
|
12230
|
+
stderr.write(`${lastOutput}
|
|
12231
|
+
`);
|
|
12232
|
+
}
|
|
12233
|
+
for (const error of feedback.errors) {
|
|
12234
|
+
stderr.write(`- ${error}
|
|
12235
|
+
`);
|
|
12236
|
+
}
|
|
12237
|
+
}
|
|
12238
|
+
stderr.write(
|
|
12239
|
+
`Error: ${agentId} response failed schema validation after ${capture.maxAttempts} attempts.
|
|
12240
|
+
`
|
|
12241
|
+
);
|
|
12242
|
+
return { exitCode: 1, reason: "execution-error" };
|
|
12243
|
+
}
|
|
11768
12244
|
async function executeInvocation(invocation, options = {}) {
|
|
11769
|
-
const { command, args, warnings, shimArgs, passthroughArgs } = buildAgentArgs(invocation);
|
|
11770
12245
|
const stderr = options.stderr ?? process.stderr;
|
|
12246
|
+
const stdout = options.stdout ?? process.stdout;
|
|
12247
|
+
const plan = invocation.structuredOutput;
|
|
12248
|
+
if (plan && plan.capture.type === "fallback") {
|
|
12249
|
+
return runFallbackAttempts({
|
|
12250
|
+
invocation,
|
|
12251
|
+
plan,
|
|
12252
|
+
capture: plan.capture,
|
|
12253
|
+
options,
|
|
12254
|
+
stdout,
|
|
12255
|
+
stderr
|
|
12256
|
+
});
|
|
12257
|
+
}
|
|
12258
|
+
const { command, args, warnings, shimArgs, passthroughArgs } = buildAgentArgs(invocation);
|
|
11771
12259
|
if (options.traceTranslate) {
|
|
11772
12260
|
const trace = {
|
|
11773
12261
|
agent: invocation.agent.id,
|
|
@@ -11777,17 +12265,23 @@ async function executeInvocation(invocation, options = {}) {
|
|
|
11777
12265
|
shimArgs,
|
|
11778
12266
|
passthroughArgs,
|
|
11779
12267
|
warnings,
|
|
11780
|
-
requests: invocation.requests
|
|
12268
|
+
requests: invocation.requests,
|
|
12269
|
+
...plan ? { structuredOutput: { capture: plan.capture.type } } : {}
|
|
11781
12270
|
};
|
|
11782
12271
|
stderr.write(`OA_TRANSLATION=${JSON.stringify(trace)}
|
|
11783
12272
|
`);
|
|
11784
12273
|
}
|
|
11785
12274
|
for (const warning of warnings) {
|
|
11786
12275
|
stderr.write(`${warning}
|
|
12276
|
+
`);
|
|
12277
|
+
}
|
|
12278
|
+
for (const notice of plan?.notices ?? []) {
|
|
12279
|
+
stderr.write(`${notice}
|
|
11787
12280
|
`);
|
|
11788
12281
|
}
|
|
11789
12282
|
const spawn$1 = options.spawn ?? spawn;
|
|
11790
|
-
const
|
|
12283
|
+
const baseStdio = options.stdio ?? "inherit";
|
|
12284
|
+
const stdio = plan ? withPipedStdout(baseStdio) : baseStdio;
|
|
11791
12285
|
return await new Promise((resolve) => {
|
|
11792
12286
|
const child = spawn$1(command, args, { stdio });
|
|
11793
12287
|
child.on("error", (error) => {
|
|
@@ -11795,20 +12289,40 @@ async function executeInvocation(invocation, options = {}) {
|
|
|
11795
12289
|
`);
|
|
11796
12290
|
resolve({ exitCode: 1, reason: "execution-error" });
|
|
11797
12291
|
});
|
|
11798
|
-
|
|
11799
|
-
|
|
11800
|
-
resolve(
|
|
11801
|
-
|
|
11802
|
-
|
|
11803
|
-
|
|
11804
|
-
|
|
11805
|
-
|
|
12292
|
+
if (!plan) {
|
|
12293
|
+
child.on("exit", (code) => {
|
|
12294
|
+
resolve(mapExitCode(code));
|
|
12295
|
+
});
|
|
12296
|
+
return;
|
|
12297
|
+
}
|
|
12298
|
+
const chunks = [];
|
|
12299
|
+
const childStdout = child.stdout;
|
|
12300
|
+
if (childStdout) {
|
|
12301
|
+
if (plan.capture.type === "json-envelope") {
|
|
12302
|
+
childStdout.on("data", (chunk) => {
|
|
12303
|
+
chunks.push(Buffer.from(chunk));
|
|
12304
|
+
});
|
|
12305
|
+
} else {
|
|
12306
|
+
childStdout.on("data", (chunk) => {
|
|
12307
|
+
stderr.write(chunk);
|
|
12308
|
+
});
|
|
11806
12309
|
}
|
|
11807
|
-
|
|
11808
|
-
|
|
12310
|
+
}
|
|
12311
|
+
child.on("close", (code) => {
|
|
12312
|
+
if (!childStdout) {
|
|
12313
|
+
stderr.write(`Error: ${invocation.agent.id} stdout was not captured.
|
|
12314
|
+
`);
|
|
12315
|
+
resolve({ exitCode: 1, reason: "execution-error" });
|
|
11809
12316
|
return;
|
|
11810
12317
|
}
|
|
11811
|
-
|
|
12318
|
+
void finalizeStructuredOutput({
|
|
12319
|
+
plan,
|
|
12320
|
+
agentId: invocation.agent.id,
|
|
12321
|
+
code,
|
|
12322
|
+
captured: Buffer.concat(chunks).toString("utf8"),
|
|
12323
|
+
stdout,
|
|
12324
|
+
stderr
|
|
12325
|
+
}).then(resolve);
|
|
11812
12326
|
});
|
|
11813
12327
|
});
|
|
11814
12328
|
}
|
|
@@ -11846,6 +12360,16 @@ function readFlagValue(args, index, label) {
|
|
|
11846
12360
|
}
|
|
11847
12361
|
return [value, index + 1];
|
|
11848
12362
|
}
|
|
12363
|
+
function parseRetriesValue(value) {
|
|
12364
|
+
const normalized = normalizeValue(value, "--output-schema-retries");
|
|
12365
|
+
const parsed = Number(normalized);
|
|
12366
|
+
if (!Number.isInteger(parsed) || parsed < 0 || parsed > 10) {
|
|
12367
|
+
throw new InvalidUsageError(
|
|
12368
|
+
"Invalid value for --output-schema-retries. Provide an integer between 0 and 10."
|
|
12369
|
+
);
|
|
12370
|
+
}
|
|
12371
|
+
return parsed;
|
|
12372
|
+
}
|
|
11849
12373
|
function parseBooleanValue(label, value) {
|
|
11850
12374
|
const normalized = normalizeValue(value, label).toLowerCase();
|
|
11851
12375
|
if (["on", "true", "1"].includes(normalized)) {
|
|
@@ -11874,6 +12398,9 @@ function parseShimFlags(argv) {
|
|
|
11874
12398
|
let webExplicit = false;
|
|
11875
12399
|
let agent = null;
|
|
11876
12400
|
let agentExplicit = false;
|
|
12401
|
+
let outputSchema = null;
|
|
12402
|
+
let outputSchemaExplicit = false;
|
|
12403
|
+
let outputSchemaRetries = null;
|
|
11877
12404
|
let traceTranslate = false;
|
|
11878
12405
|
let help = false;
|
|
11879
12406
|
let version = false;
|
|
@@ -12011,6 +12538,28 @@ function parseShimFlags(argv) {
|
|
|
12011
12538
|
agentExplicit = true;
|
|
12012
12539
|
continue;
|
|
12013
12540
|
}
|
|
12541
|
+
if (arg === "--output-schema-retries") {
|
|
12542
|
+
const [value, nextIndex] = readFlagValue(preArgs, index, "--output-schema-retries");
|
|
12543
|
+
outputSchemaRetries = parseRetriesValue(value);
|
|
12544
|
+
index = nextIndex;
|
|
12545
|
+
continue;
|
|
12546
|
+
}
|
|
12547
|
+
if (arg.startsWith("--output-schema-retries=")) {
|
|
12548
|
+
outputSchemaRetries = parseRetriesValue(arg.slice("--output-schema-retries=".length));
|
|
12549
|
+
continue;
|
|
12550
|
+
}
|
|
12551
|
+
if (arg === "--output-schema") {
|
|
12552
|
+
const [value, nextIndex] = readFlagValue(preArgs, index, "--output-schema");
|
|
12553
|
+
outputSchema = normalizeValue(value, "--output-schema");
|
|
12554
|
+
outputSchemaExplicit = true;
|
|
12555
|
+
index = nextIndex;
|
|
12556
|
+
continue;
|
|
12557
|
+
}
|
|
12558
|
+
if (arg.startsWith("--output-schema=")) {
|
|
12559
|
+
outputSchema = normalizeValue(arg.slice("--output-schema=".length), "--output-schema");
|
|
12560
|
+
outputSchemaExplicit = true;
|
|
12561
|
+
continue;
|
|
12562
|
+
}
|
|
12014
12563
|
if (arg === "--trace-translate") {
|
|
12015
12564
|
traceTranslate = true;
|
|
12016
12565
|
continue;
|
|
@@ -12029,6 +12578,14 @@ function parseShimFlags(argv) {
|
|
|
12029
12578
|
if (outputSelections.length > 0) {
|
|
12030
12579
|
output = outputSelections[outputSelections.length - 1];
|
|
12031
12580
|
}
|
|
12581
|
+
if (outputSchema !== null && outputExplicit) {
|
|
12582
|
+
throw new InvalidUsageError(
|
|
12583
|
+
"--output-schema cannot be combined with --output, --json, or --stream-json."
|
|
12584
|
+
);
|
|
12585
|
+
}
|
|
12586
|
+
if (outputSchemaRetries !== null && outputSchema === null) {
|
|
12587
|
+
throw new InvalidUsageError("--output-schema-retries requires --output-schema.");
|
|
12588
|
+
}
|
|
12032
12589
|
if (approval === "yolo" && !sandboxExplicit) {
|
|
12033
12590
|
sandbox = "off";
|
|
12034
12591
|
}
|
|
@@ -12047,6 +12604,9 @@ function parseShimFlags(argv) {
|
|
|
12047
12604
|
webExplicit,
|
|
12048
12605
|
agent,
|
|
12049
12606
|
agentExplicit,
|
|
12607
|
+
outputSchema,
|
|
12608
|
+
outputSchemaExplicit,
|
|
12609
|
+
outputSchemaRetries,
|
|
12050
12610
|
traceTranslate,
|
|
12051
12611
|
help,
|
|
12052
12612
|
version,
|
|
@@ -12145,6 +12705,157 @@ async function resolveAgentSelection(flags, repoRoot, agentsDir) {
|
|
|
12145
12705
|
}
|
|
12146
12706
|
return { resolution: { selection, targetId: resolvedId }, targetMap };
|
|
12147
12707
|
}
|
|
12708
|
+
const AJV_OPTIONS = { allErrors: true, strict: false, validateFormats: false };
|
|
12709
|
+
const instances = /* @__PURE__ */ new Map();
|
|
12710
|
+
function resolveDialect(schema) {
|
|
12711
|
+
const declared = typeof schema.$schema === "string" ? schema.$schema : "";
|
|
12712
|
+
if (declared.includes("2020-12")) {
|
|
12713
|
+
return "2020-12";
|
|
12714
|
+
}
|
|
12715
|
+
if (declared.includes("2019-09")) {
|
|
12716
|
+
return "2019-09";
|
|
12717
|
+
}
|
|
12718
|
+
return "draft-07";
|
|
12719
|
+
}
|
|
12720
|
+
function ajvForDialect(dialect) {
|
|
12721
|
+
let instance = instances.get(dialect);
|
|
12722
|
+
if (!instance) {
|
|
12723
|
+
instance = dialect === "2020-12" ? new Ajv2020(AJV_OPTIONS) : dialect === "2019-09" ? new Ajv2019(AJV_OPTIONS) : new Ajv(AJV_OPTIONS);
|
|
12724
|
+
instances.set(dialect, instance);
|
|
12725
|
+
}
|
|
12726
|
+
return instance;
|
|
12727
|
+
}
|
|
12728
|
+
function compileSchemaValidator(schemaJson) {
|
|
12729
|
+
let compiled;
|
|
12730
|
+
try {
|
|
12731
|
+
const schema = JSON.parse(schemaJson);
|
|
12732
|
+
compiled = ajvForDialect(resolveDialect(schema)).compile(schema);
|
|
12733
|
+
} catch (error) {
|
|
12734
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
12735
|
+
throw new InvalidUsageError(`Invalid value for --output-schema: ${message}.`);
|
|
12736
|
+
}
|
|
12737
|
+
return (data) => {
|
|
12738
|
+
const valid = compiled(data) === true;
|
|
12739
|
+
const errors = (compiled.errors ?? []).map(
|
|
12740
|
+
(error) => `${error.instancePath || "/"}: ${error.message ?? "is invalid"}`
|
|
12741
|
+
);
|
|
12742
|
+
return { valid, errors };
|
|
12743
|
+
};
|
|
12744
|
+
}
|
|
12745
|
+
const SCHEMA_LABEL = "--output-schema";
|
|
12746
|
+
const DEFAULT_SCHEMA_RETRIES = 2;
|
|
12747
|
+
function isPlainObject(value) {
|
|
12748
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
12749
|
+
}
|
|
12750
|
+
function parseSchemaJson(text, sourceLabel) {
|
|
12751
|
+
let parsed;
|
|
12752
|
+
try {
|
|
12753
|
+
parsed = JSON.parse(text);
|
|
12754
|
+
} catch {
|
|
12755
|
+
throw new InvalidUsageError(`Invalid value for ${SCHEMA_LABEL}: ${sourceLabel}.`);
|
|
12756
|
+
}
|
|
12757
|
+
if (!isPlainObject(parsed)) {
|
|
12758
|
+
throw new InvalidUsageError(`Invalid value for ${SCHEMA_LABEL}: schema must be a JSON object.`);
|
|
12759
|
+
}
|
|
12760
|
+
return JSON.stringify(parsed);
|
|
12761
|
+
}
|
|
12762
|
+
async function resolveOutputSchema(raw) {
|
|
12763
|
+
const trimmed = raw.trim();
|
|
12764
|
+
if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
|
|
12765
|
+
return parseSchemaJson(trimmed, "schema is not valid JSON");
|
|
12766
|
+
}
|
|
12767
|
+
let contents;
|
|
12768
|
+
try {
|
|
12769
|
+
contents = await readFile(trimmed, "utf8");
|
|
12770
|
+
} catch {
|
|
12771
|
+
throw new InvalidUsageError(
|
|
12772
|
+
`Invalid value for ${SCHEMA_LABEL}: cannot read schema file ${trimmed}.`
|
|
12773
|
+
);
|
|
12774
|
+
}
|
|
12775
|
+
return parseSchemaJson(contents, `schema file ${trimmed} is not valid JSON`);
|
|
12776
|
+
}
|
|
12777
|
+
async function planStructuredOutput(options) {
|
|
12778
|
+
const { rawSchema, mode, agentId, spec } = options;
|
|
12779
|
+
if (rawSchema === null) {
|
|
12780
|
+
return null;
|
|
12781
|
+
}
|
|
12782
|
+
if (mode !== "one-shot") {
|
|
12783
|
+
throw new InvalidUsageError(
|
|
12784
|
+
`${SCHEMA_LABEL} requires one-shot mode; provide -p/--prompt or pipe stdin.`
|
|
12785
|
+
);
|
|
12786
|
+
}
|
|
12787
|
+
if (!spec) {
|
|
12788
|
+
return planFallback(options);
|
|
12789
|
+
}
|
|
12790
|
+
const notices = [];
|
|
12791
|
+
if (options.retries !== null && options.retries !== void 0) {
|
|
12792
|
+
notices.push(
|
|
12793
|
+
`Warning: ${agentId} uses native ${SCHEMA_LABEL} support; ignoring ${SCHEMA_LABEL}-retries.`
|
|
12794
|
+
);
|
|
12795
|
+
}
|
|
12796
|
+
const schemaJson = await resolveOutputSchema(rawSchema);
|
|
12797
|
+
const needsTempDir = spec.delivery === "file" || spec.extraction.type === "last-message-file";
|
|
12798
|
+
const tempPaths = [];
|
|
12799
|
+
let tempDirPath = null;
|
|
12800
|
+
if (needsTempDir) {
|
|
12801
|
+
tempDirPath = await mkdtemp(path.join(options.tempDir ?? os.tmpdir(), "omniagent-schema-"));
|
|
12802
|
+
tempPaths.push(tempDirPath);
|
|
12803
|
+
}
|
|
12804
|
+
let deliveryValue = schemaJson;
|
|
12805
|
+
if (spec.delivery === "file" && tempDirPath) {
|
|
12806
|
+
deliveryValue = path.join(tempDirPath, "schema.json");
|
|
12807
|
+
await writeFile(deliveryValue, schemaJson, "utf8");
|
|
12808
|
+
}
|
|
12809
|
+
const args = [...spec.flag, deliveryValue, ...spec.companionArgs ?? []];
|
|
12810
|
+
let capture;
|
|
12811
|
+
if (spec.extraction.type === "json-envelope") {
|
|
12812
|
+
capture = { type: "json-envelope", field: spec.extraction.field };
|
|
12813
|
+
} else {
|
|
12814
|
+
const lastMessagePath = path.join(tempDirPath ?? os.tmpdir(), "last-message.txt");
|
|
12815
|
+
args.push(...spec.extraction.flag, lastMessagePath);
|
|
12816
|
+
capture = { type: "last-message-file", path: lastMessagePath };
|
|
12817
|
+
}
|
|
12818
|
+
return { schemaJson, args, capture, tempPaths, notices };
|
|
12819
|
+
}
|
|
12820
|
+
async function planFallback(options) {
|
|
12821
|
+
const { rawSchema, agentId, fallbackSpec } = options;
|
|
12822
|
+
if (rawSchema === null) {
|
|
12823
|
+
return null;
|
|
12824
|
+
}
|
|
12825
|
+
if (options.promptDeliverable === false) {
|
|
12826
|
+
throw new InvalidUsageError(
|
|
12827
|
+
`${agentId} cannot use the ${SCHEMA_LABEL} fallback: target defines no prompt flag.`
|
|
12828
|
+
);
|
|
12829
|
+
}
|
|
12830
|
+
const schemaJson = await resolveOutputSchema(rawSchema);
|
|
12831
|
+
const validate = compileSchemaValidator(schemaJson);
|
|
12832
|
+
const maxAttempts = (options.retries ?? DEFAULT_SCHEMA_RETRIES) + 1;
|
|
12833
|
+
return {
|
|
12834
|
+
schemaJson,
|
|
12835
|
+
args: [...fallbackSpec?.args ?? []],
|
|
12836
|
+
capture: {
|
|
12837
|
+
type: "fallback",
|
|
12838
|
+
extraction: fallbackSpec?.extraction ?? { type: "text" },
|
|
12839
|
+
maxAttempts
|
|
12840
|
+
},
|
|
12841
|
+
tempPaths: [],
|
|
12842
|
+
validate,
|
|
12843
|
+
notices: [
|
|
12844
|
+
`Notice: ${agentId} lacks native ${SCHEMA_LABEL} support; using prompt-based fallback with client-side validation.`
|
|
12845
|
+
]
|
|
12846
|
+
};
|
|
12847
|
+
}
|
|
12848
|
+
async function cleanupStructuredOutput(plan) {
|
|
12849
|
+
if (!plan) {
|
|
12850
|
+
return;
|
|
12851
|
+
}
|
|
12852
|
+
for (const tempPath of plan.tempPaths) {
|
|
12853
|
+
try {
|
|
12854
|
+
await rm(tempPath, { recursive: true, force: true });
|
|
12855
|
+
} catch {
|
|
12856
|
+
}
|
|
12857
|
+
}
|
|
12858
|
+
}
|
|
12148
12859
|
function normalizeKey(value) {
|
|
12149
12860
|
return value.trim().toLowerCase();
|
|
12150
12861
|
}
|
|
@@ -12165,6 +12876,16 @@ async function resolveInvocationFromFlags(options) {
|
|
|
12165
12876
|
const agent = resolution.selection;
|
|
12166
12877
|
const session = buildSession(flags);
|
|
12167
12878
|
const requests = buildRequests(flags);
|
|
12879
|
+
const structuredOutput = await planStructuredOutput({
|
|
12880
|
+
rawSchema: flags.outputSchema,
|
|
12881
|
+
mode,
|
|
12882
|
+
agentId: agent.id,
|
|
12883
|
+
spec: target.cli?.flags?.structuredOutput,
|
|
12884
|
+
fallbackSpec: target.cli?.flags?.structuredOutputFallback,
|
|
12885
|
+
retries: flags.outputSchemaRetries,
|
|
12886
|
+
promptDeliverable: Boolean(target.cli?.prompt),
|
|
12887
|
+
tempDir: options.tempDir
|
|
12888
|
+
});
|
|
12168
12889
|
return {
|
|
12169
12890
|
mode,
|
|
12170
12891
|
prompt,
|
|
@@ -12176,7 +12897,8 @@ async function resolveInvocationFromFlags(options) {
|
|
|
12176
12897
|
passthrough: {
|
|
12177
12898
|
hasDelimiter: flags.hasDelimiter,
|
|
12178
12899
|
args: flags.passthroughArgs
|
|
12179
|
-
}
|
|
12900
|
+
},
|
|
12901
|
+
structuredOutput
|
|
12180
12902
|
};
|
|
12181
12903
|
}
|
|
12182
12904
|
async function readStreamText(stream) {
|
|
@@ -12195,6 +12917,7 @@ async function runShim(argv, runtime = {}) {
|
|
|
12195
12917
|
const stdin = runtime.stdin ?? process.stdin;
|
|
12196
12918
|
const repoRoot = runtime.repoRoot ?? await findRepoRoot(process.cwd()) ?? process.cwd();
|
|
12197
12919
|
const stdinIsTTY = runtime.stdinIsTTY ?? stdin.isTTY ?? false;
|
|
12920
|
+
let invocation = null;
|
|
12198
12921
|
try {
|
|
12199
12922
|
const flags = parseShimFlags(argv);
|
|
12200
12923
|
let stdinText = runtime.stdinText ?? null;
|
|
@@ -12210,16 +12933,18 @@ async function runShim(argv, runtime = {}) {
|
|
|
12210
12933
|
}
|
|
12211
12934
|
}
|
|
12212
12935
|
const stdio = !stdinIsTTY && flags.promptExplicit ? ["ignore", "inherit", "inherit"] : "inherit";
|
|
12213
|
-
|
|
12936
|
+
invocation = await resolveInvocationFromFlags({
|
|
12214
12937
|
flags,
|
|
12215
12938
|
stdinIsTTY,
|
|
12216
12939
|
stdinText,
|
|
12217
12940
|
repoRoot,
|
|
12218
|
-
agentsDir: runtime.agentsDir
|
|
12941
|
+
agentsDir: runtime.agentsDir,
|
|
12942
|
+
tempDir: runtime.tempDir
|
|
12219
12943
|
});
|
|
12220
12944
|
const result = await executeInvocation(invocation, {
|
|
12221
12945
|
spawn: runtime.spawn,
|
|
12222
12946
|
stderr,
|
|
12947
|
+
stdout: runtime.stdout,
|
|
12223
12948
|
stdio,
|
|
12224
12949
|
traceTranslate: flags.traceTranslate
|
|
12225
12950
|
});
|
|
@@ -12234,6 +12959,8 @@ async function runShim(argv, runtime = {}) {
|
|
|
12234
12959
|
stderr.write(`Error: ${message}
|
|
12235
12960
|
`);
|
|
12236
12961
|
return exitCodeFor("execution-error");
|
|
12962
|
+
} finally {
|
|
12963
|
+
await cleanupStructuredOutput(invocation?.structuredOutput);
|
|
12237
12964
|
}
|
|
12238
12965
|
}
|
|
12239
12966
|
function resolveVersion() {
|
|
@@ -12260,11 +12987,13 @@ const VERSION = resolveVersion();
|
|
|
12260
12987
|
const KNOWN_COMMANDS = /* @__PURE__ */ new Set(["hello", "greet", "echo", "sync", "dev", "profiles", "usage"]);
|
|
12261
12988
|
const SHIM_CAPABILITIES = [
|
|
12262
12989
|
"Capabilities by agent:",
|
|
12263
|
-
" codex: approval, sandbox, output, model, web",
|
|
12264
|
-
" claude: approval, output, model",
|
|
12265
|
-
"
|
|
12266
|
-
" copilot: approval, model",
|
|
12267
|
-
"Unsupported shared flags for a selected agent emit a warning and are ignored."
|
|
12990
|
+
" codex: approval, sandbox, output, model, web, output-schema",
|
|
12991
|
+
" claude: approval, output, model, output-schema",
|
|
12992
|
+
" agy: approval, sandbox, model, output-schema (fallback) (alias: gemini)",
|
|
12993
|
+
" copilot: approval, model, output-schema (fallback)",
|
|
12994
|
+
"Unsupported shared flags for a selected agent emit a warning and are ignored.",
|
|
12995
|
+
"--output-schema is one-shot only; agents without native support use a prompt-based",
|
|
12996
|
+
"fallback with client-side validation and retries (--output-schema-retries, default 2)."
|
|
12268
12997
|
].join("\n");
|
|
12269
12998
|
function formatError(message, args) {
|
|
12270
12999
|
if (message.startsWith("Unknown command:")) {
|
|
@@ -12345,6 +13074,12 @@ function runCli(argv = process.argv, options = {}) {
|
|
|
12345
13074
|
}).option("agent", {
|
|
12346
13075
|
type: "string",
|
|
12347
13076
|
describe: "Select the agent (built-in id or configured alias)."
|
|
13077
|
+
}).option("output-schema", {
|
|
13078
|
+
type: "string",
|
|
13079
|
+
describe: "JSON schema file path or inline JSON; emit the final response as schema-conforming JSON (one-shot only)."
|
|
13080
|
+
}).option("output-schema-retries", {
|
|
13081
|
+
type: "number",
|
|
13082
|
+
describe: "Max retries when a prompt-based --output-schema fallback response fails validation (0-10, default 2)."
|
|
12348
13083
|
}).option("trace-translate", {
|
|
12349
13084
|
type: "boolean",
|
|
12350
13085
|
describe: "Emit a JSON line to stderr with the translated agent command/args."
|