@traits-dev/cli 0.4.0 → 0.5.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/LICENSE +1 -1
- package/README.md +3 -1
- package/dist/traits.js +308 -15
- package/package.json +2 -2
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @traits-dev/cli
|
|
2
2
|
|
|
3
|
-
CLI for traits.dev voice profile workflows: init, validate, compile, eval, and
|
|
3
|
+
CLI for traits.dev voice profile workflows: init, validate, compile, eval, import, and migrate.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -13,7 +13,9 @@ pnpm add -D @traits-dev/cli
|
|
|
13
13
|
```bash
|
|
14
14
|
traits init --template resolve profiles/resolve.yaml
|
|
15
15
|
traits validate profiles/resolve.yaml
|
|
16
|
+
traits validate profiles/resolve.yaml --format sarif
|
|
16
17
|
traits compile profiles/resolve.yaml --model gpt-4o
|
|
18
|
+
traits migrate profiles/legacy-v1-4.yaml
|
|
17
19
|
traits eval profiles/resolve.yaml --tier 1
|
|
18
20
|
```
|
|
19
21
|
|
package/dist/traits.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/bin/traits.ts
|
|
4
|
-
import
|
|
5
|
-
import
|
|
4
|
+
import fs5 from "fs";
|
|
5
|
+
import path7 from "path";
|
|
6
6
|
import { fileURLToPath } from "url";
|
|
7
7
|
|
|
8
8
|
// src/commands/compile.ts
|
|
@@ -1446,21 +1446,238 @@ function importHelp(out = process.stdout) {
|
|
|
1446
1446
|
printImportUsage(out);
|
|
1447
1447
|
}
|
|
1448
1448
|
|
|
1449
|
-
// src/commands/
|
|
1449
|
+
// src/commands/migrate.ts
|
|
1450
|
+
import fs4 from "fs";
|
|
1450
1451
|
import path5 from "path";
|
|
1452
|
+
import { loadProfileFile, validateResolvedProfile as validateResolvedProfile2 } from "@traits-dev/core";
|
|
1453
|
+
import { renderImportedProfileYAML, toValidationResultObject as toValidationResultObject4 } from "@traits-dev/core/internal";
|
|
1454
|
+
function printMigrateUsage(out = process.stderr) {
|
|
1455
|
+
out.write(
|
|
1456
|
+
[
|
|
1457
|
+
"Usage:",
|
|
1458
|
+
" traits migrate <profile-path> [options]",
|
|
1459
|
+
"",
|
|
1460
|
+
"Options:",
|
|
1461
|
+
" --to <version> Target schema version (default: v1.5)",
|
|
1462
|
+
" --output <path> Output file path (default: <name>.v1.5.yaml)",
|
|
1463
|
+
" --in-place Overwrite the source file (requires --force if file exists)",
|
|
1464
|
+
" --force Overwrite existing destination file",
|
|
1465
|
+
" --json Output structured JSON summary",
|
|
1466
|
+
" --verbose Include additional command metadata",
|
|
1467
|
+
" --no-color Disable colorized output",
|
|
1468
|
+
""
|
|
1469
|
+
].join("\n")
|
|
1470
|
+
);
|
|
1471
|
+
}
|
|
1472
|
+
function parseMigrateArgs(args) {
|
|
1473
|
+
const result = {
|
|
1474
|
+
profilePath: null,
|
|
1475
|
+
to: "v1.5",
|
|
1476
|
+
outputPath: null,
|
|
1477
|
+
inPlace: false,
|
|
1478
|
+
force: false,
|
|
1479
|
+
json: false,
|
|
1480
|
+
verbose: false,
|
|
1481
|
+
noColor: false
|
|
1482
|
+
};
|
|
1483
|
+
const positionals = [];
|
|
1484
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
1485
|
+
const arg = args[index];
|
|
1486
|
+
if (arg === "--in-place") {
|
|
1487
|
+
result.inPlace = true;
|
|
1488
|
+
continue;
|
|
1489
|
+
}
|
|
1490
|
+
if (arg === "--force") {
|
|
1491
|
+
result.force = true;
|
|
1492
|
+
continue;
|
|
1493
|
+
}
|
|
1494
|
+
if (arg === "--json") {
|
|
1495
|
+
result.json = true;
|
|
1496
|
+
continue;
|
|
1497
|
+
}
|
|
1498
|
+
if (arg === "--verbose") {
|
|
1499
|
+
result.verbose = true;
|
|
1500
|
+
continue;
|
|
1501
|
+
}
|
|
1502
|
+
if (arg === "--no-color") {
|
|
1503
|
+
result.noColor = true;
|
|
1504
|
+
continue;
|
|
1505
|
+
}
|
|
1506
|
+
if (arg === "--to" || arg === "--output") {
|
|
1507
|
+
const value = args[index + 1];
|
|
1508
|
+
if (!value) return { error: `Missing value for "${arg}"` };
|
|
1509
|
+
if (arg === "--to") {
|
|
1510
|
+
if (value !== "v1.5") {
|
|
1511
|
+
return {
|
|
1512
|
+
error: `Unsupported "--to" value "${value}". Currently supported: v1.5`
|
|
1513
|
+
};
|
|
1514
|
+
}
|
|
1515
|
+
result.to = "v1.5";
|
|
1516
|
+
} else {
|
|
1517
|
+
result.outputPath = value;
|
|
1518
|
+
}
|
|
1519
|
+
index += 1;
|
|
1520
|
+
continue;
|
|
1521
|
+
}
|
|
1522
|
+
if (arg.startsWith("--")) {
|
|
1523
|
+
return { error: `Unknown option "${arg}"` };
|
|
1524
|
+
}
|
|
1525
|
+
positionals.push(arg);
|
|
1526
|
+
}
|
|
1527
|
+
if (positionals.length !== 1) {
|
|
1528
|
+
return { error: "Expected exactly one profile path argument" };
|
|
1529
|
+
}
|
|
1530
|
+
result.profilePath = positionals[0];
|
|
1531
|
+
if (result.inPlace && result.outputPath) {
|
|
1532
|
+
return { error: 'Use either "--in-place" or "--output", not both.' };
|
|
1533
|
+
}
|
|
1534
|
+
return { value: result };
|
|
1535
|
+
}
|
|
1536
|
+
function resolveDefaultOutputPath(sourcePath, toVersion) {
|
|
1537
|
+
const ext = path5.extname(sourcePath) || ".yaml";
|
|
1538
|
+
const base = sourcePath.slice(0, sourcePath.length - ext.length);
|
|
1539
|
+
return `${base}.${toVersion}${ext}`;
|
|
1540
|
+
}
|
|
1541
|
+
function writeFileAtomic2(filePath, contents) {
|
|
1542
|
+
fs4.mkdirSync(path5.dirname(filePath), { recursive: true });
|
|
1543
|
+
const tempFile = path5.join(
|
|
1544
|
+
path5.dirname(filePath),
|
|
1545
|
+
`.${path5.basename(filePath)}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`
|
|
1546
|
+
);
|
|
1547
|
+
fs4.writeFileSync(tempFile, contents, "utf8");
|
|
1548
|
+
fs4.renameSync(tempFile, filePath);
|
|
1549
|
+
}
|
|
1550
|
+
function migrateV14ToV15(profile) {
|
|
1551
|
+
const migrated = JSON.parse(JSON.stringify(profile));
|
|
1552
|
+
migrated.schema = "v1.5";
|
|
1553
|
+
if (!migrated.capabilities) {
|
|
1554
|
+
migrated.capabilities = {
|
|
1555
|
+
tools: [],
|
|
1556
|
+
constraints: [],
|
|
1557
|
+
handoff: {
|
|
1558
|
+
trigger: "Request requires unavailable operations.",
|
|
1559
|
+
action: "Offer handoff to a human operator."
|
|
1560
|
+
}
|
|
1561
|
+
};
|
|
1562
|
+
return { migrated, capabilitiesAdded: true };
|
|
1563
|
+
}
|
|
1564
|
+
return { migrated, capabilitiesAdded: false };
|
|
1565
|
+
}
|
|
1566
|
+
function runMigrate(args, io = process) {
|
|
1567
|
+
const parsed = parseMigrateArgs(args);
|
|
1568
|
+
if ("error" in parsed) {
|
|
1569
|
+
io.stderr.write(`Error: ${parsed.error}
|
|
1570
|
+
|
|
1571
|
+
`);
|
|
1572
|
+
printMigrateUsage(io.stderr);
|
|
1573
|
+
return 1;
|
|
1574
|
+
}
|
|
1575
|
+
const options = parsed.value;
|
|
1576
|
+
if (!options.profilePath) {
|
|
1577
|
+
io.stderr.write("Error: Missing profile path\n\n");
|
|
1578
|
+
printMigrateUsage(io.stderr);
|
|
1579
|
+
return 1;
|
|
1580
|
+
}
|
|
1581
|
+
const sourcePath = path5.resolve(io.cwd(), options.profilePath);
|
|
1582
|
+
const destinationPath = options.inPlace ? sourcePath : options.outputPath ? path5.resolve(io.cwd(), options.outputPath) : resolveDefaultOutputPath(sourcePath, options.to);
|
|
1583
|
+
if (!fs4.existsSync(sourcePath)) {
|
|
1584
|
+
io.stderr.write(`Error: Source profile does not exist: ${sourcePath}
|
|
1585
|
+
`);
|
|
1586
|
+
return 1;
|
|
1587
|
+
}
|
|
1588
|
+
if (fs4.existsSync(destinationPath) && !options.force) {
|
|
1589
|
+
io.stderr.write(
|
|
1590
|
+
`Error: Destination file already exists: ${destinationPath}. Use --force to overwrite.
|
|
1591
|
+
`
|
|
1592
|
+
);
|
|
1593
|
+
return 1;
|
|
1594
|
+
}
|
|
1595
|
+
let loaded;
|
|
1596
|
+
try {
|
|
1597
|
+
loaded = loadProfileFile(sourcePath);
|
|
1598
|
+
} catch (error) {
|
|
1599
|
+
io.stderr.write(
|
|
1600
|
+
`Error: Failed to read profile: ${error instanceof Error ? error.message : String(error)}
|
|
1601
|
+
`
|
|
1602
|
+
);
|
|
1603
|
+
return 1;
|
|
1604
|
+
}
|
|
1605
|
+
if (loaded.schema !== "v1.4") {
|
|
1606
|
+
io.stderr.write(
|
|
1607
|
+
`Error: Migration source schema must be "v1.4". Found "${loaded.schema ?? "unknown"}".
|
|
1608
|
+
`
|
|
1609
|
+
);
|
|
1610
|
+
return 1;
|
|
1611
|
+
}
|
|
1612
|
+
const migration = migrateV14ToV15(loaded);
|
|
1613
|
+
const validation = validateResolvedProfile2(migration.migrated, {
|
|
1614
|
+
strict: false
|
|
1615
|
+
});
|
|
1616
|
+
if (validation.errors.length > 0) {
|
|
1617
|
+
io.stderr.write(
|
|
1618
|
+
`Error: Migrated profile is invalid and was not written (${validation.errors.length} error(s)).
|
|
1619
|
+
`
|
|
1620
|
+
);
|
|
1621
|
+
return 2;
|
|
1622
|
+
}
|
|
1623
|
+
const yaml = renderImportedProfileYAML(migration.migrated);
|
|
1624
|
+
writeFileAtomic2(destinationPath, yaml);
|
|
1625
|
+
if (options.json) {
|
|
1626
|
+
io.stdout.write(
|
|
1627
|
+
`${JSON.stringify(
|
|
1628
|
+
{
|
|
1629
|
+
migrated: true,
|
|
1630
|
+
sourcePath,
|
|
1631
|
+
outputPath: destinationPath,
|
|
1632
|
+
fromSchema: "v1.4",
|
|
1633
|
+
toSchema: "v1.5",
|
|
1634
|
+
capabilitiesAdded: migration.capabilitiesAdded,
|
|
1635
|
+
validation: toValidationResultObject4(validation)
|
|
1636
|
+
},
|
|
1637
|
+
null,
|
|
1638
|
+
2
|
|
1639
|
+
)}
|
|
1640
|
+
`
|
|
1641
|
+
);
|
|
1642
|
+
return 0;
|
|
1643
|
+
}
|
|
1644
|
+
if (options.verbose) {
|
|
1645
|
+
io.stdout.write(`Source: ${sourcePath}
|
|
1646
|
+
`);
|
|
1647
|
+
io.stdout.write(`Output: ${destinationPath}
|
|
1648
|
+
`);
|
|
1649
|
+
io.stdout.write(`Capabilities added: ${migration.capabilitiesAdded ? "yes" : "no"}
|
|
1650
|
+
`);
|
|
1651
|
+
io.stdout.write(`Validation warnings: ${validation.warnings.length}
|
|
1652
|
+
|
|
1653
|
+
`);
|
|
1654
|
+
}
|
|
1655
|
+
io.stdout.write(`Migrated profile schema v1.4 -> v1.5
|
|
1656
|
+
`);
|
|
1657
|
+
io.stdout.write(`Wrote: ${destinationPath}
|
|
1658
|
+
`);
|
|
1659
|
+
return 0;
|
|
1660
|
+
}
|
|
1661
|
+
function migrateHelp(out = process.stdout) {
|
|
1662
|
+
printMigrateUsage(out);
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1665
|
+
// src/commands/validate.ts
|
|
1666
|
+
import path6 from "path";
|
|
1451
1667
|
import { validateProfile as validateProfile2 } from "@traits-dev/core";
|
|
1452
1668
|
import {
|
|
1453
1669
|
formatValidationResult as formatValidationResult4,
|
|
1454
|
-
toValidationResultObject as
|
|
1670
|
+
toValidationResultObject as toValidationResultObject5
|
|
1455
1671
|
} from "@traits-dev/core/internal";
|
|
1456
1672
|
function printValidateUsage(out = process.stderr) {
|
|
1457
1673
|
out.write(
|
|
1458
1674
|
[
|
|
1459
1675
|
"Usage:",
|
|
1460
|
-
" traits validate <profile-path> [
|
|
1676
|
+
" traits validate <profile-path> [options]",
|
|
1461
1677
|
"",
|
|
1462
1678
|
"Options:",
|
|
1463
1679
|
" --json Output structured JSON",
|
|
1680
|
+
" --format <text|json|sarif> Output format (default: text)",
|
|
1464
1681
|
" --strict Promote warnings to errors",
|
|
1465
1682
|
" --verbose Include additional command metadata",
|
|
1466
1683
|
" --no-color Disable colorized output",
|
|
@@ -1474,6 +1691,7 @@ function parseValidateArgs(args) {
|
|
|
1474
1691
|
profilePath: null,
|
|
1475
1692
|
strict: false,
|
|
1476
1693
|
json: false,
|
|
1694
|
+
format: "text",
|
|
1477
1695
|
verbose: false,
|
|
1478
1696
|
noColor: false,
|
|
1479
1697
|
bundledProfilesDir: null
|
|
@@ -1487,6 +1705,7 @@ function parseValidateArgs(args) {
|
|
|
1487
1705
|
}
|
|
1488
1706
|
if (arg === "--json") {
|
|
1489
1707
|
result.json = true;
|
|
1708
|
+
result.format = "json";
|
|
1490
1709
|
continue;
|
|
1491
1710
|
}
|
|
1492
1711
|
if (arg === "--verbose") {
|
|
@@ -1506,6 +1725,20 @@ function parseValidateArgs(args) {
|
|
|
1506
1725
|
index += 1;
|
|
1507
1726
|
continue;
|
|
1508
1727
|
}
|
|
1728
|
+
if (arg === "--format") {
|
|
1729
|
+
const nextValue = args[index + 1];
|
|
1730
|
+
if (!nextValue) {
|
|
1731
|
+
return { error: 'Missing value for "--format"' };
|
|
1732
|
+
}
|
|
1733
|
+
const normalized = String(nextValue).toLowerCase();
|
|
1734
|
+
if (normalized !== "text" && normalized !== "json" && normalized !== "sarif") {
|
|
1735
|
+
return { error: 'Invalid "--format" value. Expected text, json, or sarif.' };
|
|
1736
|
+
}
|
|
1737
|
+
result.format = normalized;
|
|
1738
|
+
result.json = normalized === "json";
|
|
1739
|
+
index += 1;
|
|
1740
|
+
continue;
|
|
1741
|
+
}
|
|
1509
1742
|
if (arg.startsWith("--")) {
|
|
1510
1743
|
return { error: `Unknown option "${arg}"` };
|
|
1511
1744
|
}
|
|
@@ -1517,6 +1750,54 @@ function parseValidateArgs(args) {
|
|
|
1517
1750
|
result.profilePath = positionals[0];
|
|
1518
1751
|
return { value: result };
|
|
1519
1752
|
}
|
|
1753
|
+
function toRelativePath(cwd, filePath) {
|
|
1754
|
+
const relative = path6.relative(cwd, filePath);
|
|
1755
|
+
if (relative && !relative.startsWith("..")) return relative;
|
|
1756
|
+
return filePath;
|
|
1757
|
+
}
|
|
1758
|
+
function buildSarifReport(validation, profilePath, cwd) {
|
|
1759
|
+
const diagnostics = [...validation.errors, ...validation.warnings];
|
|
1760
|
+
const uniqueRuleIds = [...new Set(diagnostics.map((diagnostic) => diagnostic.code))];
|
|
1761
|
+
const artifactUri = toRelativePath(cwd, profilePath);
|
|
1762
|
+
const rules = uniqueRuleIds.map((ruleId) => ({
|
|
1763
|
+
id: ruleId,
|
|
1764
|
+
shortDescription: {
|
|
1765
|
+
text: `traits.dev ${ruleId}`
|
|
1766
|
+
}
|
|
1767
|
+
}));
|
|
1768
|
+
const results = diagnostics.map((diagnostic) => ({
|
|
1769
|
+
ruleId: diagnostic.code,
|
|
1770
|
+
level: diagnostic.severity === "error" ? "error" : "warning",
|
|
1771
|
+
message: {
|
|
1772
|
+
text: diagnostic.message
|
|
1773
|
+
},
|
|
1774
|
+
locations: [
|
|
1775
|
+
{
|
|
1776
|
+
physicalLocation: {
|
|
1777
|
+
artifactLocation: {
|
|
1778
|
+
uri: artifactUri
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1781
|
+
}
|
|
1782
|
+
]
|
|
1783
|
+
}));
|
|
1784
|
+
return {
|
|
1785
|
+
version: "2.1.0",
|
|
1786
|
+
$schema: "https://json.schemastore.org/sarif-2.1.0.json",
|
|
1787
|
+
runs: [
|
|
1788
|
+
{
|
|
1789
|
+
tool: {
|
|
1790
|
+
driver: {
|
|
1791
|
+
name: "traits.dev",
|
|
1792
|
+
informationUri: "https://github.com/justinhambleton/traits",
|
|
1793
|
+
rules
|
|
1794
|
+
}
|
|
1795
|
+
},
|
|
1796
|
+
results
|
|
1797
|
+
}
|
|
1798
|
+
]
|
|
1799
|
+
};
|
|
1800
|
+
}
|
|
1520
1801
|
function runValidate(args, io = process) {
|
|
1521
1802
|
const parsed = parseValidateArgs(args);
|
|
1522
1803
|
if ("error" in parsed) {
|
|
@@ -1532,14 +1813,18 @@ function runValidate(args, io = process) {
|
|
|
1532
1813
|
printValidateUsage(io.stderr);
|
|
1533
1814
|
return 1;
|
|
1534
1815
|
}
|
|
1535
|
-
const bundledProfilesDir = options.bundledProfilesDir ?
|
|
1536
|
-
const profilePath =
|
|
1816
|
+
const bundledProfilesDir = options.bundledProfilesDir ? path6.resolve(io.cwd(), options.bundledProfilesDir) : path6.resolve(io.cwd(), "profiles");
|
|
1817
|
+
const profilePath = path6.resolve(io.cwd(), options.profilePath);
|
|
1537
1818
|
const result = validateProfile2(profilePath, {
|
|
1538
1819
|
strict: options.strict,
|
|
1539
1820
|
bundledProfilesDir
|
|
1540
1821
|
});
|
|
1541
|
-
if (options.json) {
|
|
1542
|
-
io.stdout.write(`${JSON.stringify(
|
|
1822
|
+
if (options.format === "json") {
|
|
1823
|
+
io.stdout.write(`${JSON.stringify(toValidationResultObject5(result), null, 2)}
|
|
1824
|
+
`);
|
|
1825
|
+
} else if (options.format === "sarif") {
|
|
1826
|
+
const sarif = buildSarifReport(result, profilePath, io.cwd());
|
|
1827
|
+
io.stdout.write(`${JSON.stringify(sarif, null, 2)}
|
|
1543
1828
|
`);
|
|
1544
1829
|
} else {
|
|
1545
1830
|
if (options.verbose) {
|
|
@@ -1561,14 +1846,14 @@ function validateHelp(out = process.stdout) {
|
|
|
1561
1846
|
}
|
|
1562
1847
|
|
|
1563
1848
|
// src/bin/traits.ts
|
|
1564
|
-
var CLI_DIR =
|
|
1849
|
+
var CLI_DIR = path7.dirname(fileURLToPath(import.meta.url));
|
|
1565
1850
|
var PACKAGE_JSON_CANDIDATES = [
|
|
1566
|
-
|
|
1567
|
-
|
|
1851
|
+
path7.resolve(CLI_DIR, "../package.json"),
|
|
1852
|
+
path7.resolve(CLI_DIR, "../../package.json")
|
|
1568
1853
|
];
|
|
1569
1854
|
function resolvePackageJsonPath() {
|
|
1570
1855
|
for (const candidate of PACKAGE_JSON_CANDIDATES) {
|
|
1571
|
-
if (
|
|
1856
|
+
if (fs5.existsSync(candidate)) return candidate;
|
|
1572
1857
|
}
|
|
1573
1858
|
return PACKAGE_JSON_CANDIDATES[0];
|
|
1574
1859
|
}
|
|
@@ -1586,6 +1871,7 @@ function printRootUsage(out = process.stdout) {
|
|
|
1586
1871
|
" compile <profile-path> Compile a profile for a target model",
|
|
1587
1872
|
" eval <profile-path> Evaluate profile responses (Tier 1 scaffold)",
|
|
1588
1873
|
" import [prompt-path] Import a profile from an existing system prompt",
|
|
1874
|
+
" migrate <profile-path> Migrate profile schema (v1.4 -> v1.5)",
|
|
1589
1875
|
" validate <profile-path> Validate a voice profile",
|
|
1590
1876
|
"",
|
|
1591
1877
|
"Global flags:",
|
|
@@ -1605,7 +1891,7 @@ function printRootUsage(out = process.stdout) {
|
|
|
1605
1891
|
}
|
|
1606
1892
|
function readCliVersion() {
|
|
1607
1893
|
try {
|
|
1608
|
-
const raw =
|
|
1894
|
+
const raw = fs5.readFileSync(PACKAGE_JSON_PATH, "utf8");
|
|
1609
1895
|
const pkg = JSON.parse(raw);
|
|
1610
1896
|
return String(pkg.version ?? "0.0.0");
|
|
1611
1897
|
} catch {
|
|
@@ -1651,7 +1937,7 @@ function withGlobalFlags(command, commandArgs, flags) {
|
|
|
1651
1937
|
if (flags.noColor && !args.includes("--no-color")) {
|
|
1652
1938
|
args.push("--no-color");
|
|
1653
1939
|
}
|
|
1654
|
-
if ((command === "validate" || command === "compile" || command === "eval" || command === "import") && flags.json && !args.includes("--json")) {
|
|
1940
|
+
if ((command === "validate" || command === "compile" || command === "eval" || command === "import" || command === "migrate") && flags.json && !args.includes("--json")) {
|
|
1655
1941
|
args.push("--json");
|
|
1656
1942
|
}
|
|
1657
1943
|
return args;
|
|
@@ -1717,6 +2003,13 @@ async function run(argv, io = process) {
|
|
|
1717
2003
|
}
|
|
1718
2004
|
return runImport(commandArgs, io);
|
|
1719
2005
|
}
|
|
2006
|
+
if (command === "migrate") {
|
|
2007
|
+
if (commandArgs.includes("--help") || commandArgs.includes("-h")) {
|
|
2008
|
+
migrateHelp(io.stdout);
|
|
2009
|
+
return 0;
|
|
2010
|
+
}
|
|
2011
|
+
return runMigrate(commandArgs, io);
|
|
2012
|
+
}
|
|
1720
2013
|
io.stderr.write(`Error: Unknown command "${command}"
|
|
1721
2014
|
|
|
1722
2015
|
`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@traits-dev/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.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.5.0"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@types/node": "^25.2.3",
|