@traits-dev/cli 0.5.0 → 0.7.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/README.md +1 -1
- package/dist/traits.js +99 -21
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ traits init --template resolve profiles/resolve.yaml
|
|
|
15
15
|
traits validate profiles/resolve.yaml
|
|
16
16
|
traits validate profiles/resolve.yaml --format sarif
|
|
17
17
|
traits compile profiles/resolve.yaml --model gpt-4o
|
|
18
|
-
traits migrate profiles/legacy-v1-
|
|
18
|
+
traits migrate profiles/legacy-v1-5.yaml --to v1.6 --normalize-extends
|
|
19
19
|
traits eval profiles/resolve.yaml --tier 1
|
|
20
20
|
```
|
|
21
21
|
|
package/dist/traits.js
CHANGED
|
@@ -267,7 +267,7 @@ function printEvalUsage(out = process.stderr) {
|
|
|
267
267
|
"Options:",
|
|
268
268
|
" --model <model> Model target (required)",
|
|
269
269
|
" --tier <1|2|3> Highest tier to run (default: highest available)",
|
|
270
|
-
" --suite <name> Built-in baseline suite: support|healthcare|developer",
|
|
270
|
+
" --suite <name> Built-in baseline suite: support|healthcare|developer|educator|advisor",
|
|
271
271
|
" --provider <name> Judge provider for Tier 3: auto|openai|anthropic",
|
|
272
272
|
" --embedding-model <name> Embedding model for Tier 2 (OpenAI)",
|
|
273
273
|
" --judge-model <name> Judge model for Tier 3 provider",
|
|
@@ -402,10 +402,12 @@ function parseEvalArgs(args) {
|
|
|
402
402
|
if (!["auto", "openai", "anthropic"].includes(result.provider)) {
|
|
403
403
|
return { error: 'Invalid "--provider" value. Expected auto, openai, or anthropic.' };
|
|
404
404
|
}
|
|
405
|
-
if (result.suite != null && !["support", "healthcare", "developer"].includes(
|
|
405
|
+
if (result.suite != null && !["support", "healthcare", "developer", "educator", "advisor"].includes(
|
|
406
406
|
result.suite
|
|
407
407
|
)) {
|
|
408
|
-
return {
|
|
408
|
+
return {
|
|
409
|
+
error: 'Invalid "--suite" value. Expected support, healthcare, developer, educator, or advisor.'
|
|
410
|
+
};
|
|
409
411
|
}
|
|
410
412
|
if (result.suite != null && result.samplesPath != null) {
|
|
411
413
|
return { error: 'Use either "--suite" or "--samples/--scenarios", not both.' };
|
|
@@ -443,7 +445,7 @@ function loadSamples(options, cwd) {
|
|
|
443
445
|
const suite = loadBuiltInEvalSuite(options.suite);
|
|
444
446
|
if (!suite) {
|
|
445
447
|
throw new Error(
|
|
446
|
-
`Unknown suite "${options.suite}". Expected support, healthcare, or
|
|
448
|
+
`Unknown suite "${options.suite}". Expected support, healthcare, developer, educator, or advisor.`
|
|
447
449
|
);
|
|
448
450
|
}
|
|
449
451
|
return suite.scenarios.map((scenario) => ({
|
|
@@ -1451,6 +1453,11 @@ import fs4 from "fs";
|
|
|
1451
1453
|
import path5 from "path";
|
|
1452
1454
|
import { loadProfileFile, validateResolvedProfile as validateResolvedProfile2 } from "@traits-dev/core";
|
|
1453
1455
|
import { renderImportedProfileYAML, toValidationResultObject as toValidationResultObject4 } from "@traits-dev/core/internal";
|
|
1456
|
+
var SCHEMA_ORDER = {
|
|
1457
|
+
"v1.4": 0,
|
|
1458
|
+
"v1.5": 1,
|
|
1459
|
+
"v1.6": 2
|
|
1460
|
+
};
|
|
1454
1461
|
function printMigrateUsage(out = process.stderr) {
|
|
1455
1462
|
out.write(
|
|
1456
1463
|
[
|
|
@@ -1458,10 +1465,11 @@ function printMigrateUsage(out = process.stderr) {
|
|
|
1458
1465
|
" traits migrate <profile-path> [options]",
|
|
1459
1466
|
"",
|
|
1460
1467
|
"Options:",
|
|
1461
|
-
" --to <version> Target schema version (default: v1.5)",
|
|
1462
|
-
" --output <path> Output file path (default: <name>.
|
|
1468
|
+
" --to <version> Target schema version (default: v1.6; supported: v1.5, v1.6)",
|
|
1469
|
+
" --output <path> Output file path (default: <name>.<target>.yaml)",
|
|
1463
1470
|
" --in-place Overwrite the source file (requires --force if file exists)",
|
|
1464
1471
|
" --force Overwrite existing destination file",
|
|
1472
|
+
" --normalize-extends Convert single-string extends to array form (v1.6 target only)",
|
|
1465
1473
|
" --json Output structured JSON summary",
|
|
1466
1474
|
" --verbose Include additional command metadata",
|
|
1467
1475
|
" --no-color Disable colorized output",
|
|
@@ -1472,10 +1480,11 @@ function printMigrateUsage(out = process.stderr) {
|
|
|
1472
1480
|
function parseMigrateArgs(args) {
|
|
1473
1481
|
const result = {
|
|
1474
1482
|
profilePath: null,
|
|
1475
|
-
to: "v1.
|
|
1483
|
+
to: "v1.6",
|
|
1476
1484
|
outputPath: null,
|
|
1477
1485
|
inPlace: false,
|
|
1478
1486
|
force: false,
|
|
1487
|
+
normalizeExtends: false,
|
|
1479
1488
|
json: false,
|
|
1480
1489
|
verbose: false,
|
|
1481
1490
|
noColor: false
|
|
@@ -1491,6 +1500,10 @@ function parseMigrateArgs(args) {
|
|
|
1491
1500
|
result.force = true;
|
|
1492
1501
|
continue;
|
|
1493
1502
|
}
|
|
1503
|
+
if (arg === "--normalize-extends") {
|
|
1504
|
+
result.normalizeExtends = true;
|
|
1505
|
+
continue;
|
|
1506
|
+
}
|
|
1494
1507
|
if (arg === "--json") {
|
|
1495
1508
|
result.json = true;
|
|
1496
1509
|
continue;
|
|
@@ -1507,12 +1520,12 @@ function parseMigrateArgs(args) {
|
|
|
1507
1520
|
const value = args[index + 1];
|
|
1508
1521
|
if (!value) return { error: `Missing value for "${arg}"` };
|
|
1509
1522
|
if (arg === "--to") {
|
|
1510
|
-
if (value !== "v1.5") {
|
|
1523
|
+
if (value !== "v1.5" && value !== "v1.6") {
|
|
1511
1524
|
return {
|
|
1512
|
-
error: `Unsupported "--to" value "${value}". Currently supported: v1.5`
|
|
1525
|
+
error: `Unsupported "--to" value "${value}". Currently supported: v1.5, v1.6`
|
|
1513
1526
|
};
|
|
1514
1527
|
}
|
|
1515
|
-
result.to =
|
|
1528
|
+
result.to = value;
|
|
1516
1529
|
} else {
|
|
1517
1530
|
result.outputPath = value;
|
|
1518
1531
|
}
|
|
@@ -1531,6 +1544,9 @@ function parseMigrateArgs(args) {
|
|
|
1531
1544
|
if (result.inPlace && result.outputPath) {
|
|
1532
1545
|
return { error: 'Use either "--in-place" or "--output", not both.' };
|
|
1533
1546
|
}
|
|
1547
|
+
if (result.normalizeExtends && result.to !== "v1.6") {
|
|
1548
|
+
return { error: '"--normalize-extends" requires "--to v1.6".' };
|
|
1549
|
+
}
|
|
1534
1550
|
return { value: result };
|
|
1535
1551
|
}
|
|
1536
1552
|
function resolveDefaultOutputPath(sourcePath, toVersion) {
|
|
@@ -1563,6 +1579,22 @@ function migrateV14ToV15(profile) {
|
|
|
1563
1579
|
}
|
|
1564
1580
|
return { migrated, capabilitiesAdded: false };
|
|
1565
1581
|
}
|
|
1582
|
+
function migrateV15ToV16(profile, options) {
|
|
1583
|
+
const migrated = JSON.parse(JSON.stringify(profile));
|
|
1584
|
+
migrated.schema = "v1.6";
|
|
1585
|
+
if (options.normalizeExtends && typeof migrated.extends === "string") {
|
|
1586
|
+
const normalized = migrated.extends.trim();
|
|
1587
|
+
if (normalized.length > 0) {
|
|
1588
|
+
migrated.extends = [normalized];
|
|
1589
|
+
return { migrated, extendsNormalized: true };
|
|
1590
|
+
}
|
|
1591
|
+
}
|
|
1592
|
+
return { migrated, extendsNormalized: false };
|
|
1593
|
+
}
|
|
1594
|
+
function asSupportedSourceSchema(value) {
|
|
1595
|
+
if (value === "v1.4" || value === "v1.5") return value;
|
|
1596
|
+
return null;
|
|
1597
|
+
}
|
|
1566
1598
|
function runMigrate(args, io = process) {
|
|
1567
1599
|
const parsed = parseMigrateArgs(args);
|
|
1568
1600
|
if ("error" in parsed) {
|
|
@@ -1602,15 +1634,58 @@ function runMigrate(args, io = process) {
|
|
|
1602
1634
|
);
|
|
1603
1635
|
return 1;
|
|
1604
1636
|
}
|
|
1605
|
-
if (loaded.schema
|
|
1637
|
+
if (loaded.schema === "v1.6") {
|
|
1638
|
+
io.stderr.write(
|
|
1639
|
+
'Error: Source profile is already at "v1.6". Nothing to migrate.\n'
|
|
1640
|
+
);
|
|
1641
|
+
return 1;
|
|
1642
|
+
}
|
|
1643
|
+
const sourceSchema = asSupportedSourceSchema(loaded.schema);
|
|
1644
|
+
if (!sourceSchema) {
|
|
1645
|
+
io.stderr.write(
|
|
1646
|
+
`Error: Migration source schema must be "v1.4" or "v1.5". Found "${loaded.schema ?? "unknown"}".
|
|
1647
|
+
`
|
|
1648
|
+
);
|
|
1649
|
+
return 1;
|
|
1650
|
+
}
|
|
1651
|
+
if (SCHEMA_ORDER[options.to] < SCHEMA_ORDER[sourceSchema]) {
|
|
1606
1652
|
io.stderr.write(
|
|
1607
|
-
`Error:
|
|
1653
|
+
`Error: Downgrade is not supported (source "${sourceSchema}" -> target "${options.to}").
|
|
1608
1654
|
`
|
|
1609
1655
|
);
|
|
1610
1656
|
return 1;
|
|
1611
1657
|
}
|
|
1612
|
-
|
|
1613
|
-
|
|
1658
|
+
if (SCHEMA_ORDER[options.to] === SCHEMA_ORDER[sourceSchema]) {
|
|
1659
|
+
io.stderr.write(`Error: Source profile already uses target schema "${options.to}".
|
|
1660
|
+
`);
|
|
1661
|
+
return 1;
|
|
1662
|
+
}
|
|
1663
|
+
let migrated = loaded;
|
|
1664
|
+
let capabilitiesAdded = false;
|
|
1665
|
+
let extendsNormalized = false;
|
|
1666
|
+
let currentSchema = sourceSchema;
|
|
1667
|
+
if (currentSchema === "v1.4") {
|
|
1668
|
+
const step = migrateV14ToV15(migrated);
|
|
1669
|
+
migrated = step.migrated;
|
|
1670
|
+
capabilitiesAdded = step.capabilitiesAdded;
|
|
1671
|
+
currentSchema = "v1.5";
|
|
1672
|
+
}
|
|
1673
|
+
if (options.to === "v1.6" && currentSchema === "v1.5") {
|
|
1674
|
+
const step = migrateV15ToV16(migrated, {
|
|
1675
|
+
normalizeExtends: options.normalizeExtends
|
|
1676
|
+
});
|
|
1677
|
+
migrated = step.migrated;
|
|
1678
|
+
extendsNormalized = step.extendsNormalized;
|
|
1679
|
+
currentSchema = "v1.6";
|
|
1680
|
+
}
|
|
1681
|
+
if (currentSchema !== options.to) {
|
|
1682
|
+
io.stderr.write(
|
|
1683
|
+
`Error: Failed to migrate profile to target schema "${options.to}". Final schema: "${currentSchema}".
|
|
1684
|
+
`
|
|
1685
|
+
);
|
|
1686
|
+
return 2;
|
|
1687
|
+
}
|
|
1688
|
+
const validation = validateResolvedProfile2(migrated, {
|
|
1614
1689
|
strict: false
|
|
1615
1690
|
});
|
|
1616
1691
|
if (validation.errors.length > 0) {
|
|
@@ -1620,7 +1695,7 @@ function runMigrate(args, io = process) {
|
|
|
1620
1695
|
);
|
|
1621
1696
|
return 2;
|
|
1622
1697
|
}
|
|
1623
|
-
const yaml = renderImportedProfileYAML(
|
|
1698
|
+
const yaml = renderImportedProfileYAML(migrated);
|
|
1624
1699
|
writeFileAtomic2(destinationPath, yaml);
|
|
1625
1700
|
if (options.json) {
|
|
1626
1701
|
io.stdout.write(
|
|
@@ -1629,9 +1704,10 @@ function runMigrate(args, io = process) {
|
|
|
1629
1704
|
migrated: true,
|
|
1630
1705
|
sourcePath,
|
|
1631
1706
|
outputPath: destinationPath,
|
|
1632
|
-
fromSchema:
|
|
1633
|
-
toSchema:
|
|
1634
|
-
capabilitiesAdded
|
|
1707
|
+
fromSchema: sourceSchema,
|
|
1708
|
+
toSchema: options.to,
|
|
1709
|
+
capabilitiesAdded,
|
|
1710
|
+
extendsNormalized,
|
|
1635
1711
|
validation: toValidationResultObject4(validation)
|
|
1636
1712
|
},
|
|
1637
1713
|
null,
|
|
@@ -1646,13 +1722,15 @@ function runMigrate(args, io = process) {
|
|
|
1646
1722
|
`);
|
|
1647
1723
|
io.stdout.write(`Output: ${destinationPath}
|
|
1648
1724
|
`);
|
|
1649
|
-
io.stdout.write(`Capabilities added: ${
|
|
1725
|
+
io.stdout.write(`Capabilities added: ${capabilitiesAdded ? "yes" : "no"}
|
|
1726
|
+
`);
|
|
1727
|
+
io.stdout.write(`Extends normalized: ${extendsNormalized ? "yes" : "no"}
|
|
1650
1728
|
`);
|
|
1651
1729
|
io.stdout.write(`Validation warnings: ${validation.warnings.length}
|
|
1652
1730
|
|
|
1653
1731
|
`);
|
|
1654
1732
|
}
|
|
1655
|
-
io.stdout.write(`Migrated profile schema
|
|
1733
|
+
io.stdout.write(`Migrated profile schema ${sourceSchema} -> ${options.to}
|
|
1656
1734
|
`);
|
|
1657
1735
|
io.stdout.write(`Wrote: ${destinationPath}
|
|
1658
1736
|
`);
|
|
@@ -1871,7 +1949,7 @@ function printRootUsage(out = process.stdout) {
|
|
|
1871
1949
|
" compile <profile-path> Compile a profile for a target model",
|
|
1872
1950
|
" eval <profile-path> Evaluate profile responses (Tier 1 scaffold)",
|
|
1873
1951
|
" import [prompt-path] Import a profile from an existing system prompt",
|
|
1874
|
-
" migrate <profile-path> Migrate profile schema (
|
|
1952
|
+
" migrate <profile-path> Migrate profile schema (up to v1.6)",
|
|
1875
1953
|
" validate <profile-path> Validate a voice profile",
|
|
1876
1954
|
"",
|
|
1877
1955
|
"Global flags:",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@traits-dev/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "traits.dev command-line interface for voice profile init, validate, compile, eval, and import workflows.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"traits-dev",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"provenance": true
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@traits-dev/core": "^0.
|
|
44
|
+
"@traits-dev/core": "^0.7.0"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@types/node": "^25.2.3",
|