@program-video/cli 0.1.10 → 0.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -872,6 +872,16 @@ function inferMimeType(fileName) {
872
872
  const extension = path2.extname(fileName).toLowerCase();
873
873
  return MIME_TYPES_BY_EXTENSION[extension] ?? null;
874
874
  }
875
+ function normalizeToolParams(toolName, params) {
876
+ if (toolName !== "addScene") {
877
+ return params;
878
+ }
879
+ const next = { ...params };
880
+ if (typeof next.name === "string" && next.name.length > 0 && (typeof next.title !== "string" || next.title.length === 0)) {
881
+ next.title = next.name;
882
+ }
883
+ return next;
884
+ }
875
885
  async function uploadFileFromPath(params, projectId, accessToken, source) {
876
886
  const filePath = params.path;
877
887
  if (typeof filePath !== "string" || filePath.length === 0) {
@@ -988,6 +998,7 @@ async function executeCommand(toolName, options) {
988
998
  if (options.params) {
989
999
  try {
990
1000
  params = JSON.parse(options.params);
1001
+ params = normalizeToolParams(toolName, params);
991
1002
  } catch {
992
1003
  spinner?.stop();
993
1004
  spinner?.clear();
@@ -1417,40 +1428,1058 @@ For agent integration, always use the --json flag.
1417
1428
  `);
1418
1429
  }
1419
1430
 
1420
- // src/index.ts
1421
- var program = new Command();
1422
- var require2 = createRequire(import.meta.url);
1423
- var packageJson = require2("../package.json");
1424
- program.name("program").description("CLI for the Program video creation platform").version(packageJson.version);
1425
- var auth = program.command("auth").description("Authentication commands");
1426
- auth.command("login").description("Authenticate with the Program platform").option("--json", "Output as JSON").action(async (options) => {
1427
- await loginCommand(options);
1428
- });
1429
- auth.command("logout").description("Log out from the Program platform").option("--json", "Output as JSON").action((options) => {
1430
- logoutCommand(options);
1431
- });
1432
- auth.command("status").description("Check authentication status").option("--json", "Output as JSON").action((options) => {
1433
- statusCommand(options);
1434
- });
1435
- var project = program.command("project").description("Project management commands");
1436
- project.command("create").description("Create a new project").option("--title <title>", "Project title").option("--description <description>", "Project description").option("--json", "Output as JSON").action(async (options) => {
1437
- await createCommand(options);
1438
- });
1439
- project.command("list").description("List projects").option("--limit <limit>", "Maximum number of projects to return", parseInt).option("--json", "Output as JSON").action(async (options) => {
1440
- await listCommand(options);
1441
- });
1442
- project.command("get <id>").description("Get project details including composition").option("--json", "Output as JSON").action(async (id, options) => {
1443
- await getCommand(id, options);
1444
- });
1445
- var workflow = program.command("workflow").description("Workflow template commands");
1446
- workflow.command("list").description("List available workflow templates").option("--limit <limit>", "Maximum number of templates to return", parseInt).option("--public-only", "Only show public templates").option("--json", "Output as JSON").action(async (options) => {
1447
- await listCommand2(options);
1448
- });
1449
- workflow.command("run <templateId>").description("Execute a workflow template").option("--project <projectId>", "Project ID to associate with execution").option("--input <json>", "JSON input for the workflow").option("--json", "Output as JSON").action(async (templateId, options) => {
1450
- await runCommand(templateId, options);
1431
+ // src/commands/template/list.ts
1432
+ import chalk14 from "chalk";
1433
+ import ora12 from "ora";
1434
+ async function listCommand5(options) {
1435
+ const showSpinner = !options.json && process.stdout.isTTY;
1436
+ const spinner = showSpinner ? ora12("Fetching templates...").start() : null;
1437
+ const client = createConvexClient(convexConfig);
1438
+ const result = await client.query("templates.list", {
1439
+ category: options.publicOnly ? "public" : void 0
1440
+ });
1441
+ spinner?.stop();
1442
+ spinner?.clear();
1443
+ if (!result.success || !result.data) {
1444
+ outputError(result.error ?? "Failed to list templates", options);
1445
+ process.exit(1);
1446
+ }
1447
+ const templates = result.data;
1448
+ if (options.json) {
1449
+ outputSuccess(
1450
+ templates.map((t) => ({
1451
+ id: t._id,
1452
+ name: t.name,
1453
+ description: t.description,
1454
+ public: t.public,
1455
+ stepCount: Array.isArray(t.steps) ? t.steps.length : 0
1456
+ })),
1457
+ options
1458
+ );
1459
+ } else {
1460
+ if (templates.length === 0) {
1461
+ console.log(chalk14.dim("No templates found."));
1462
+ return;
1463
+ }
1464
+ console.log(
1465
+ `Found ${chalk14.cyan(templates.length)} template${templates.length === 1 ? "" : "s"}:
1466
+ `
1467
+ );
1468
+ const rows = templates.map((t) => [
1469
+ t._id,
1470
+ t.name,
1471
+ t.description?.substring(0, 40) ?? chalk14.dim("No description"),
1472
+ String(Array.isArray(t.steps) ? t.steps.length : 0),
1473
+ t.public ? chalk14.green("public") : chalk14.dim("private")
1474
+ ]);
1475
+ console.log(
1476
+ formatTable(["ID", "Name", "Description", "Steps", "Visibility"], rows)
1477
+ );
1478
+ }
1479
+ }
1480
+
1481
+ // src/commands/template/get.ts
1482
+ import chalk15 from "chalk";
1483
+ import ora13 from "ora";
1484
+
1485
+ // src/lib/context.ts
1486
+ import Conf2 from "conf";
1487
+ import * as fs3 from "fs";
1488
+ import * as path3 from "path";
1489
+ import * as os2 from "os";
1490
+ var CONTEXT_DIR = path3.join(os2.homedir(), ".program");
1491
+ function ensureContextDir() {
1492
+ if (!fs3.existsSync(CONTEXT_DIR)) {
1493
+ fs3.mkdirSync(CONTEXT_DIR, { mode: 448, recursive: true });
1494
+ }
1495
+ }
1496
+ var store2 = new Conf2({
1497
+ projectName: "program-cli",
1498
+ cwd: CONTEXT_DIR,
1499
+ configName: "context",
1500
+ fileExtension: "json",
1501
+ defaults: {
1502
+ activeTemplateId: null
1503
+ }
1451
1504
  });
1452
- workflow.command("status <executionId>").description("Check workflow execution status").option("--watch", "Continuously poll for status updates").option("--interval <ms>", "Poll interval in milliseconds", parseInt).option("--json", "Output as JSON").action(async (executionId, options) => {
1453
- await statusCommand2(executionId, options);
1505
+ function setActiveTemplate(id) {
1506
+ ensureContextDir();
1507
+ store2.set("activeTemplateId", id);
1508
+ }
1509
+ function getActiveTemplate() {
1510
+ return store2.get("activeTemplateId");
1511
+ }
1512
+ function clearActiveTemplate() {
1513
+ store2.set("activeTemplateId", null);
1514
+ }
1515
+
1516
+ // src/commands/template/get.ts
1517
+ async function getCommand2(id, options) {
1518
+ const templateId = id ?? getActiveTemplate();
1519
+ if (!templateId) {
1520
+ outputError(
1521
+ "No template ID provided and no active template set. Use 'template use <id>' to set one.",
1522
+ options
1523
+ );
1524
+ process.exit(1);
1525
+ }
1526
+ const showSpinner = !options.json && process.stdout.isTTY;
1527
+ const spinner = showSpinner ? ora13("Fetching template...").start() : null;
1528
+ const client = createConvexClient(convexConfig);
1529
+ const result = await client.query("templates.byId", {
1530
+ id: templateId
1531
+ });
1532
+ spinner?.stop();
1533
+ spinner?.clear();
1534
+ if (!result.success || !result.data) {
1535
+ outputError(result.error ?? "Template not found", options);
1536
+ process.exit(1);
1537
+ }
1538
+ const template2 = result.data;
1539
+ if (options.json) {
1540
+ outputSuccess(template2, options);
1541
+ } else {
1542
+ console.log(
1543
+ formatKeyValue([
1544
+ { key: "ID", value: template2._id },
1545
+ { key: "Name", value: template2.name },
1546
+ {
1547
+ key: "Description",
1548
+ value: template2.description ?? chalk15.dim("None")
1549
+ },
1550
+ {
1551
+ key: "Visibility",
1552
+ value: template2.public ? chalk15.green("public") : chalk15.dim("private")
1553
+ },
1554
+ {
1555
+ key: "Created",
1556
+ value: new Date(template2.createdAt).toLocaleString()
1557
+ },
1558
+ {
1559
+ key: "Updated",
1560
+ value: new Date(template2.updatedAt).toLocaleString()
1561
+ }
1562
+ ])
1563
+ );
1564
+ const steps = template2.steps ?? [];
1565
+ if (steps.length === 0) {
1566
+ console.log(chalk15.dim("\nNo steps configured."));
1567
+ } else {
1568
+ console.log(`
1569
+ ${chalk15.bold("Steps")} (${steps.length}):
1570
+ `);
1571
+ const rows = steps.map((s, i) => [
1572
+ String(i),
1573
+ s.id ?? chalk15.dim("\u2014"),
1574
+ s.stepId,
1575
+ summarizeConfig(s.config)
1576
+ ]);
1577
+ console.log(formatTable(["#", "ID", "Type", "Config"], rows));
1578
+ }
1579
+ }
1580
+ }
1581
+ function summarizeConfig(config) {
1582
+ const keys = Object.keys(config);
1583
+ if (keys.length === 0) return chalk15.dim("{}");
1584
+ const summary = keys.slice(0, 3).map((k) => {
1585
+ const v = config[k];
1586
+ const vs = typeof v === "string" ? v.length > 20 ? v.substring(0, 20) + "..." : v : JSON.stringify(v);
1587
+ return `${k}=${vs}`;
1588
+ }).join(", ");
1589
+ return keys.length > 3 ? summary + `, +${keys.length - 3} more` : summary;
1590
+ }
1591
+
1592
+ // src/commands/template/create.ts
1593
+ import chalk16 from "chalk";
1594
+ import ora14 from "ora";
1595
+ async function createCommand2(options) {
1596
+ if (!options.name) {
1597
+ outputError("--name is required", options);
1598
+ process.exit(1);
1599
+ }
1600
+ const showSpinner = !options.json && process.stdout.isTTY;
1601
+ const spinner = showSpinner ? ora14("Creating template...").start() : null;
1602
+ const client = createConvexClient(convexConfig);
1603
+ const result = await client.mutation("templates.create", {
1604
+ name: options.name,
1605
+ description: options.description,
1606
+ public: options.public ?? false
1607
+ });
1608
+ spinner?.stop();
1609
+ spinner?.clear();
1610
+ if (!result.success || !result.data) {
1611
+ outputError(result.error ?? "Failed to create template", options);
1612
+ process.exit(1);
1613
+ }
1614
+ const templateId = result.data;
1615
+ setActiveTemplate(templateId);
1616
+ if (options.json) {
1617
+ outputSuccess({ id: templateId, active: true }, options);
1618
+ } else {
1619
+ console.log(formatSuccess("Template created (now active)"));
1620
+ console.log(chalk16.dim(` ID: ${templateId}`));
1621
+ }
1622
+ }
1623
+
1624
+ // src/commands/template/update.ts
1625
+ import ora15 from "ora";
1626
+ async function updateCommand(id, options) {
1627
+ const templateId = id ?? getActiveTemplate();
1628
+ if (!templateId) {
1629
+ outputError(
1630
+ "No template ID provided and no active template set. Use 'template use <id>' to set one.",
1631
+ options
1632
+ );
1633
+ process.exit(1);
1634
+ }
1635
+ const showSpinner = !options.json && process.stdout.isTTY;
1636
+ const spinner = showSpinner ? ora15("Updating template...").start() : null;
1637
+ const client = createConvexClient(convexConfig);
1638
+ const params = { id: templateId };
1639
+ if (options.name !== void 0) params.name = options.name;
1640
+ if (options.description !== void 0) params.description = options.description;
1641
+ if (options.public !== void 0) params.public = options.public;
1642
+ if (options.steps !== void 0) {
1643
+ try {
1644
+ params.steps = JSON.parse(options.steps);
1645
+ } catch {
1646
+ spinner?.stop();
1647
+ spinner?.clear();
1648
+ outputError("Invalid JSON in --steps parameter", options);
1649
+ process.exit(1);
1650
+ }
1651
+ }
1652
+ const result = await client.mutation("templates.update", params);
1653
+ spinner?.stop();
1654
+ spinner?.clear();
1655
+ if (!result.success) {
1656
+ outputError(result.error ?? "Failed to update template", options);
1657
+ process.exit(1);
1658
+ }
1659
+ if (options.json) {
1660
+ outputSuccess({ id: templateId, updated: true }, options);
1661
+ } else {
1662
+ console.log(formatSuccess("Template updated"));
1663
+ }
1664
+ }
1665
+
1666
+ // src/commands/template/remove.ts
1667
+ import chalk17 from "chalk";
1668
+ import ora16 from "ora";
1669
+ async function removeCommand(id, options) {
1670
+ const templateId = id ?? getActiveTemplate();
1671
+ if (!templateId) {
1672
+ outputError(
1673
+ "No template ID provided and no active template set. Use 'template use <id>' to set one.",
1674
+ options
1675
+ );
1676
+ process.exit(1);
1677
+ }
1678
+ if (!options.force && !options.json) {
1679
+ const readline = await import("readline");
1680
+ const rl = readline.createInterface({
1681
+ input: process.stdin,
1682
+ output: process.stdout
1683
+ });
1684
+ const answer = await new Promise((resolve) => {
1685
+ rl.question(
1686
+ chalk17.yellow(`Are you sure you want to delete template ${templateId}? (y/N) `),
1687
+ resolve
1688
+ );
1689
+ });
1690
+ rl.close();
1691
+ if (answer.toLowerCase() !== "y") {
1692
+ console.log(chalk17.dim("Cancelled."));
1693
+ return;
1694
+ }
1695
+ }
1696
+ const showSpinner = !options.json && process.stdout.isTTY;
1697
+ const spinner = showSpinner ? ora16("Deleting template...").start() : null;
1698
+ const client = createConvexClient(convexConfig);
1699
+ const result = await client.mutation("templates.remove", {
1700
+ id: templateId
1701
+ });
1702
+ spinner?.stop();
1703
+ spinner?.clear();
1704
+ if (!result.success) {
1705
+ outputError(result.error ?? "Failed to delete template", options);
1706
+ process.exit(1);
1707
+ }
1708
+ if (getActiveTemplate() === templateId) {
1709
+ clearActiveTemplate();
1710
+ }
1711
+ if (options.json) {
1712
+ outputSuccess({ id: templateId, deleted: true }, options);
1713
+ } else {
1714
+ console.log(formatSuccess("Template deleted"));
1715
+ }
1716
+ }
1717
+
1718
+ // src/commands/template/run.ts
1719
+ import chalk18 from "chalk";
1720
+ import ora17 from "ora";
1721
+ async function runCommand2(id, options) {
1722
+ const templateId = id ?? getActiveTemplate();
1723
+ if (!templateId) {
1724
+ outputError(
1725
+ "No template ID provided and no active template set. Use 'template use <id>' to set one.",
1726
+ options
1727
+ );
1728
+ process.exit(1);
1729
+ }
1730
+ const showSpinner = !options.json && process.stdout.isTTY;
1731
+ const spinner = showSpinner ? ora17("Starting workflow execution...").start() : null;
1732
+ let input;
1733
+ if (options.input) {
1734
+ try {
1735
+ input = JSON.parse(options.input);
1736
+ } catch {
1737
+ spinner?.stop();
1738
+ spinner?.clear();
1739
+ outputError("Invalid JSON in --input parameter", options);
1740
+ process.exit(1);
1741
+ }
1742
+ }
1743
+ const client = createConvexClient(convexConfig);
1744
+ const result = await client.mutation("workflows.run", {
1745
+ templateId,
1746
+ projectId: options.project,
1747
+ input
1748
+ });
1749
+ spinner?.stop();
1750
+ spinner?.clear();
1751
+ if (!result.success || !result.data) {
1752
+ outputError(result.error ?? "Failed to start workflow", options);
1753
+ process.exit(1);
1754
+ }
1755
+ const executionId = result.data;
1756
+ if (options.json) {
1757
+ outputSuccess({ executionId }, options);
1758
+ } else {
1759
+ console.log(formatSuccess("Workflow started"));
1760
+ console.log(chalk18.dim(` Execution ID: ${executionId}`));
1761
+ console.log(
1762
+ chalk18.dim(` Check status with: program template status ${executionId}`)
1763
+ );
1764
+ }
1765
+ }
1766
+
1767
+ // src/commands/template/status.ts
1768
+ import chalk19 from "chalk";
1769
+ import ora18 from "ora";
1770
+ async function statusCommand3(executionId, options) {
1771
+ const client = createConvexClient(convexConfig);
1772
+ const pollInterval = options.interval ?? 2e3;
1773
+ if (options.watch) {
1774
+ await watchStatus2(client, executionId, pollInterval, options);
1775
+ } else {
1776
+ await getStatusOnce2(client, executionId, options);
1777
+ }
1778
+ }
1779
+ async function getStatusOnce2(client, executionId, options) {
1780
+ const showSpinner = !options.json && process.stdout.isTTY;
1781
+ const spinner = showSpinner ? ora18("Fetching execution status...").start() : null;
1782
+ const result = await client.query("workflows.status", {
1783
+ executionId
1784
+ });
1785
+ spinner?.stop();
1786
+ spinner?.clear();
1787
+ if (!result.success) {
1788
+ outputError(result.error ?? "Failed to get status", options);
1789
+ process.exit(1);
1790
+ }
1791
+ const status = result.data;
1792
+ if (!status) {
1793
+ outputError("Execution not found", options);
1794
+ process.exit(1);
1795
+ }
1796
+ if (options.json) {
1797
+ outputSuccess(status, options);
1798
+ } else {
1799
+ printStatus2(status);
1800
+ }
1801
+ }
1802
+ async function watchStatus2(client, executionId, pollInterval, options) {
1803
+ let lastStatus = null;
1804
+ const poll = async () => {
1805
+ const result = await client.query("workflows.status", {
1806
+ executionId
1807
+ });
1808
+ if (!result.success) {
1809
+ outputError(result.error ?? "Failed to get status", options);
1810
+ return true;
1811
+ }
1812
+ const status = result.data;
1813
+ if (!status) {
1814
+ outputError("Execution not found", options);
1815
+ return true;
1816
+ }
1817
+ if (options.json) {
1818
+ if (status.status !== lastStatus) {
1819
+ console.log(JSON.stringify(status));
1820
+ lastStatus = status.status;
1821
+ }
1822
+ } else {
1823
+ if (status.status !== lastStatus) {
1824
+ console.clear();
1825
+ console.log(chalk19.dim(`Watching execution ${executionId}...
1826
+ `));
1827
+ printStatus2(status);
1828
+ lastStatus = status.status;
1829
+ }
1830
+ }
1831
+ if (["success", "error", "cancelled"].includes(status.status)) {
1832
+ return true;
1833
+ }
1834
+ return false;
1835
+ };
1836
+ let done = await poll();
1837
+ while (!done) {
1838
+ await new Promise((resolve) => setTimeout(resolve, pollInterval));
1839
+ done = await poll();
1840
+ }
1841
+ }
1842
+ function printStatus2(status) {
1843
+ const statusColor = getStatusColor2(status.status);
1844
+ console.log(
1845
+ formatKeyValue([
1846
+ { key: "Status", value: statusColor(status.status) },
1847
+ ...status.completedAt ? [
1848
+ {
1849
+ key: "Completed",
1850
+ value: new Date(status.completedAt).toLocaleString()
1851
+ }
1852
+ ] : []
1853
+ ])
1854
+ );
1855
+ if (status.nodeStatuses && status.nodeStatuses.length > 0) {
1856
+ console.log(chalk19.dim("\nStep progress:"));
1857
+ for (const node of status.nodeStatuses) {
1858
+ const nodeColor = getStatusColor2(node.status);
1859
+ console.log(` ${nodeColor(getStatusIcon2(node.status))} ${node.nodeId}`);
1860
+ }
1861
+ }
1862
+ if (status.error) {
1863
+ console.log(formatWarning(`
1864
+ Error: ${status.error}`));
1865
+ }
1866
+ if (status.status === "success" && status.output) {
1867
+ console.log(formatSuccess("\nOutput:"));
1868
+ console.log(JSON.stringify(status.output, null, 2));
1869
+ }
1870
+ }
1871
+ function getStatusColor2(status) {
1872
+ switch (status) {
1873
+ case "success":
1874
+ return chalk19.green;
1875
+ case "error":
1876
+ return chalk19.red;
1877
+ case "cancelled":
1878
+ return chalk19.yellow;
1879
+ case "running":
1880
+ return chalk19.blue;
1881
+ case "pending":
1882
+ default:
1883
+ return chalk19.dim;
1884
+ }
1885
+ }
1886
+ function getStatusIcon2(status) {
1887
+ switch (status) {
1888
+ case "success":
1889
+ return "\u2713";
1890
+ case "error":
1891
+ return "\u2715";
1892
+ case "running":
1893
+ return "\u25CF";
1894
+ case "pending":
1895
+ default:
1896
+ return "\u25CB";
1897
+ }
1898
+ }
1899
+
1900
+ // src/commands/template/use.ts
1901
+ import chalk20 from "chalk";
1902
+ import ora19 from "ora";
1903
+ async function useCommand(id, options) {
1904
+ const showSpinner = !options.json && process.stdout.isTTY;
1905
+ const spinner = showSpinner ? ora19("Verifying template...").start() : null;
1906
+ const client = createConvexClient(convexConfig);
1907
+ const result = await client.query("templates.byId", { id });
1908
+ spinner?.stop();
1909
+ spinner?.clear();
1910
+ if (!result.success || !result.data) {
1911
+ outputError(result.error ?? "Template not found or not accessible", options);
1912
+ process.exit(1);
1913
+ }
1914
+ setActiveTemplate(id);
1915
+ if (options.json) {
1916
+ outputSuccess({ id, name: result.data.name, active: true }, options);
1917
+ } else {
1918
+ console.log(formatSuccess(`Active template set to "${result.data.name}"`));
1919
+ console.log(chalk20.dim(` ID: ${id}`));
1920
+ }
1921
+ }
1922
+
1923
+ // src/commands/template/step/list.ts
1924
+ import chalk21 from "chalk";
1925
+ import ora20 from "ora";
1926
+ async function stepListCommand(options) {
1927
+ const showSpinner = !options.json && process.stdout.isTTY;
1928
+ const spinner = showSpinner ? ora20("Fetching step types...").start() : null;
1929
+ const client = createConvexClient(convexConfig);
1930
+ const result = await client.query("templates.steps", {
1931
+ category: options.category
1932
+ });
1933
+ spinner?.stop();
1934
+ spinner?.clear();
1935
+ if (!result.success || !result.data) {
1936
+ outputError(result.error ?? "Failed to list step types", options);
1937
+ process.exit(1);
1938
+ }
1939
+ const steps = result.data;
1940
+ if (options.json) {
1941
+ outputSuccess(steps, options);
1942
+ } else {
1943
+ if (steps.length === 0) {
1944
+ console.log(chalk21.dim("No step types found."));
1945
+ return;
1946
+ }
1947
+ console.log(
1948
+ `Found ${chalk21.cyan(steps.length)} step type${steps.length === 1 ? "" : "s"}:
1949
+ `
1950
+ );
1951
+ const rows = steps.map((s) => [
1952
+ s.id,
1953
+ s.name,
1954
+ s.category,
1955
+ s.isPrimitive ? chalk21.yellow("primitive") : ""
1956
+ ]);
1957
+ console.log(formatTable(["Type", "Name", "Category", ""], rows));
1958
+ }
1959
+ }
1960
+
1961
+ // src/commands/template/step/info.ts
1962
+ import chalk22 from "chalk";
1963
+ import ora21 from "ora";
1964
+ async function stepInfoCommand(stepType, options) {
1965
+ const showSpinner = !options.json && process.stdout.isTTY;
1966
+ const spinner = showSpinner ? ora21("Fetching step info...").start() : null;
1967
+ const client = createConvexClient(convexConfig);
1968
+ const result = await client.query("templates.stepInfo", {
1969
+ stepId: stepType
1970
+ });
1971
+ spinner?.stop();
1972
+ spinner?.clear();
1973
+ if (!result.success) {
1974
+ outputError(result.error ?? "Failed to get step info", options);
1975
+ process.exit(1);
1976
+ }
1977
+ if (!result.data) {
1978
+ outputError(`Step type "${stepType}" not found`, options);
1979
+ process.exit(1);
1980
+ }
1981
+ const step2 = result.data;
1982
+ if (options.json) {
1983
+ outputSuccess(step2, options);
1984
+ } else {
1985
+ console.log(
1986
+ formatKeyValue([
1987
+ { key: "Type", value: step2.id },
1988
+ { key: "Name", value: step2.name },
1989
+ { key: "Category", value: step2.category },
1990
+ { key: "Description", value: step2.description },
1991
+ {
1992
+ key: "Primitive",
1993
+ value: step2.isPrimitive ? chalk22.yellow("yes") : "no"
1994
+ }
1995
+ ])
1996
+ );
1997
+ const visibleInputs = step2.inputs.filter((i) => !i.hidden);
1998
+ if (visibleInputs.length > 0) {
1999
+ console.log(`
2000
+ ${chalk22.bold("Inputs")}:
2001
+ `);
2002
+ const inputRows = visibleInputs.map((i) => [
2003
+ i.key,
2004
+ i.type,
2005
+ i.required ? chalk22.green("yes") : chalk22.dim("no"),
2006
+ i.description
2007
+ ]);
2008
+ console.log(
2009
+ formatTable(["Key", "Type", "Required", "Description"], inputRows)
2010
+ );
2011
+ }
2012
+ if (step2.outputs.length > 0) {
2013
+ console.log(`
2014
+ ${chalk22.bold("Outputs")}:
2015
+ `);
2016
+ const outputRows = step2.outputs.map((o) => [
2017
+ o.key,
2018
+ o.type,
2019
+ o.description
2020
+ ]);
2021
+ console.log(formatTable(["Key", "Type", "Description"], outputRows));
2022
+ }
2023
+ }
2024
+ }
2025
+
2026
+ // src/commands/template/step/add.ts
2027
+ import chalk23 from "chalk";
2028
+ import ora22 from "ora";
2029
+ import crypto from "crypto";
2030
+ async function stepAddCommand(stepType, options) {
2031
+ const templateId = options.template ?? getActiveTemplate();
2032
+ if (!templateId) {
2033
+ outputError(
2034
+ "No template ID. Use --template <id> or set active template with 'template use <id>'.",
2035
+ options
2036
+ );
2037
+ process.exit(1);
2038
+ }
2039
+ let config = {};
2040
+ if (options.config) {
2041
+ try {
2042
+ config = JSON.parse(options.config);
2043
+ } catch {
2044
+ outputError("Invalid JSON in --config parameter", options);
2045
+ process.exit(1);
2046
+ }
2047
+ }
2048
+ const showSpinner = !options.json && process.stdout.isTTY;
2049
+ const spinner = showSpinner ? ora22("Adding step...").start() : null;
2050
+ const client = createConvexClient(convexConfig);
2051
+ const getResult = await client.query("templates.byId", {
2052
+ id: templateId
2053
+ });
2054
+ if (!getResult.success || !getResult.data) {
2055
+ spinner?.stop();
2056
+ spinner?.clear();
2057
+ outputError(getResult.error ?? "Template not found", options);
2058
+ process.exit(1);
2059
+ }
2060
+ const steps = (getResult.data.steps ?? []).map((s) => ({ ...s }));
2061
+ const newId = crypto.randomUUID().slice(0, 8);
2062
+ let insertAt;
2063
+ if (options.at !== void 0) {
2064
+ insertAt = Math.max(0, Math.min(options.at, steps.length));
2065
+ } else if (options.after) {
2066
+ const afterIndex = steps.findIndex((s) => s.id === options.after);
2067
+ if (afterIndex === -1) {
2068
+ spinner?.stop();
2069
+ spinner?.clear();
2070
+ outputError(`Step with id "${options.after}" not found`, options);
2071
+ process.exit(1);
2072
+ }
2073
+ insertAt = afterIndex + 1;
2074
+ } else {
2075
+ insertAt = steps.length;
2076
+ }
2077
+ const newStep = {
2078
+ id: newId,
2079
+ stepId: stepType,
2080
+ config,
2081
+ order: insertAt
2082
+ };
2083
+ steps.splice(insertAt, 0, newStep);
2084
+ for (let i = 0; i < steps.length; i++) {
2085
+ const s = steps[i];
2086
+ if (s) s.order = i;
2087
+ }
2088
+ const updateResult = await client.mutation("templates.update", {
2089
+ id: templateId,
2090
+ steps
2091
+ });
2092
+ spinner?.stop();
2093
+ spinner?.clear();
2094
+ if (!updateResult.success) {
2095
+ outputError(updateResult.error ?? "Failed to update template", options);
2096
+ process.exit(1);
2097
+ }
2098
+ if (options.json) {
2099
+ outputSuccess(
2100
+ { id: newId, stepId: stepType, order: insertAt, templateId },
2101
+ options
2102
+ );
2103
+ } else {
2104
+ console.log(formatSuccess(`Step added: ${stepType}`));
2105
+ console.log(chalk23.dim(` Step ID: ${newId}`));
2106
+ console.log(chalk23.dim(` Position: ${insertAt}`));
2107
+ }
2108
+ }
2109
+
2110
+ // src/commands/template/step/remove.ts
2111
+ import ora23 from "ora";
2112
+ async function stepRemoveCommand(stepInstanceId, options) {
2113
+ const templateId = options.template ?? getActiveTemplate();
2114
+ if (!templateId) {
2115
+ outputError(
2116
+ "No template ID. Use --template <id> or set active template with 'template use <id>'.",
2117
+ options
2118
+ );
2119
+ process.exit(1);
2120
+ }
2121
+ const showSpinner = !options.json && process.stdout.isTTY;
2122
+ const spinner = showSpinner ? ora23("Removing step...").start() : null;
2123
+ const client = createConvexClient(convexConfig);
2124
+ const getResult = await client.query("templates.byId", {
2125
+ id: templateId
2126
+ });
2127
+ if (!getResult.success || !getResult.data) {
2128
+ spinner?.stop();
2129
+ spinner?.clear();
2130
+ outputError(getResult.error ?? "Template not found", options);
2131
+ process.exit(1);
2132
+ }
2133
+ const steps = getResult.data.steps ?? [];
2134
+ const removeIndex = steps.findIndex((s) => s.id === stepInstanceId);
2135
+ if (removeIndex === -1) {
2136
+ spinner?.stop();
2137
+ spinner?.clear();
2138
+ outputError(`Step with id "${stepInstanceId}" not found in template`, options);
2139
+ process.exit(1);
2140
+ }
2141
+ const removed = steps[removeIndex];
2142
+ if (!removed) {
2143
+ spinner?.stop();
2144
+ spinner?.clear();
2145
+ outputError(`Step at index ${removeIndex} not found`, options);
2146
+ process.exit(1);
2147
+ }
2148
+ const newSteps = steps.filter((_, i) => i !== removeIndex);
2149
+ for (let i = 0; i < newSteps.length; i++) {
2150
+ const s = newSteps[i];
2151
+ if (s) s.order = i;
2152
+ }
2153
+ const updateResult = await client.mutation("templates.update", {
2154
+ id: templateId,
2155
+ steps: newSteps
2156
+ });
2157
+ spinner?.stop();
2158
+ spinner?.clear();
2159
+ if (!updateResult.success) {
2160
+ outputError(updateResult.error ?? "Failed to update template", options);
2161
+ process.exit(1);
2162
+ }
2163
+ if (options.json) {
2164
+ outputSuccess(
2165
+ { removed: stepInstanceId, stepId: removed.stepId, templateId },
2166
+ options
2167
+ );
2168
+ } else {
2169
+ console.log(formatSuccess(`Removed step: ${removed.stepId} (${stepInstanceId})`));
2170
+ }
2171
+ }
2172
+
2173
+ // src/commands/template/step/update.ts
2174
+ import ora24 from "ora";
2175
+ async function stepUpdateCommand(stepInstanceId, options) {
2176
+ const templateId = options.template ?? getActiveTemplate();
2177
+ if (!templateId) {
2178
+ outputError(
2179
+ "No template ID. Use --template <id> or set active template with 'template use <id>'.",
2180
+ options
2181
+ );
2182
+ process.exit(1);
2183
+ }
2184
+ if (!options.config) {
2185
+ outputError("--config is required", options);
2186
+ process.exit(1);
2187
+ }
2188
+ let configPatch;
2189
+ try {
2190
+ configPatch = JSON.parse(options.config);
2191
+ } catch {
2192
+ outputError("Invalid JSON in --config parameter", options);
2193
+ process.exit(1);
2194
+ }
2195
+ const showSpinner = !options.json && process.stdout.isTTY;
2196
+ const spinner = showSpinner ? ora24("Updating step...").start() : null;
2197
+ const client = createConvexClient(convexConfig);
2198
+ const getResult = await client.query("templates.byId", {
2199
+ id: templateId
2200
+ });
2201
+ if (!getResult.success || !getResult.data) {
2202
+ spinner?.stop();
2203
+ spinner?.clear();
2204
+ outputError(getResult.error ?? "Template not found", options);
2205
+ process.exit(1);
2206
+ }
2207
+ const steps = (getResult.data.steps ?? []).map((s) => ({ ...s }));
2208
+ const stepIndex = steps.findIndex((s) => s.id === stepInstanceId);
2209
+ if (stepIndex === -1) {
2210
+ spinner?.stop();
2211
+ spinner?.clear();
2212
+ outputError(`Step with id "${stepInstanceId}" not found in template`, options);
2213
+ process.exit(1);
2214
+ }
2215
+ const targetStep = steps[stepIndex];
2216
+ if (!targetStep) {
2217
+ spinner?.stop();
2218
+ spinner?.clear();
2219
+ outputError(`Step at index ${stepIndex} not found`, options);
2220
+ process.exit(1);
2221
+ }
2222
+ targetStep.config = {
2223
+ ...targetStep.config,
2224
+ ...configPatch
2225
+ };
2226
+ const updateResult = await client.mutation("templates.update", {
2227
+ id: templateId,
2228
+ steps
2229
+ });
2230
+ spinner?.stop();
2231
+ spinner?.clear();
2232
+ if (!updateResult.success) {
2233
+ outputError(updateResult.error ?? "Failed to update template", options);
2234
+ process.exit(1);
2235
+ }
2236
+ if (options.json) {
2237
+ outputSuccess(
2238
+ {
2239
+ id: stepInstanceId,
2240
+ stepId: targetStep.stepId,
2241
+ config: targetStep.config,
2242
+ templateId
2243
+ },
2244
+ options
2245
+ );
2246
+ } else {
2247
+ console.log(
2248
+ formatSuccess(
2249
+ `Updated step: ${targetStep.stepId} (${stepInstanceId})`
2250
+ )
2251
+ );
2252
+ }
2253
+ }
2254
+
2255
+ // src/commands/template/model/list.ts
2256
+ import chalk24 from "chalk";
2257
+ import ora25 from "ora";
2258
+ async function modelListCommand(category, options) {
2259
+ const showSpinner = !options.json && process.stdout.isTTY;
2260
+ const spinner = showSpinner ? ora25("Fetching models...").start() : null;
2261
+ const client = createConvexClient(convexConfig);
2262
+ const result = await client.query("models.list", { category });
2263
+ spinner?.stop();
2264
+ spinner?.clear();
2265
+ if (!result.success || !result.data) {
2266
+ outputError(result.error ?? "Failed to list models", options);
2267
+ process.exit(1);
2268
+ }
2269
+ const models = result.data;
2270
+ if (options.json) {
2271
+ outputSuccess(
2272
+ models.map((m) => ({
2273
+ modelId: m.modelId,
2274
+ name: m.displayName ?? m.modelName,
2275
+ provider: m.provider,
2276
+ description: m.description
2277
+ })),
2278
+ options
2279
+ );
2280
+ } else {
2281
+ if (models.length === 0) {
2282
+ console.log(chalk24.dim(`No ${category} models found.`));
2283
+ return;
2284
+ }
2285
+ console.log(
2286
+ `Found ${chalk24.cyan(models.length)} ${category} model${models.length === 1 ? "" : "s"}:
2287
+ `
2288
+ );
2289
+ const rows = models.map((m) => [
2290
+ m.modelId,
2291
+ m.displayName ?? m.modelName,
2292
+ m.provider
2293
+ ]);
2294
+ console.log(formatTable(["Model ID", "Name", "Provider"], rows));
2295
+ }
2296
+ }
2297
+
2298
+ // src/commands/template/model/schema.ts
2299
+ import chalk25 from "chalk";
2300
+ import ora26 from "ora";
2301
+ async function modelSchemaCommand(modelId, options) {
2302
+ const showSpinner = !options.json && process.stdout.isTTY;
2303
+ const spinner = showSpinner ? ora26("Fetching model schema...").start() : null;
2304
+ const client = createConvexClient(convexConfig);
2305
+ const result = await client.query("models.byModelId", {
2306
+ modelId
2307
+ });
2308
+ spinner?.stop();
2309
+ spinner?.clear();
2310
+ if (!result.success) {
2311
+ outputError(result.error ?? "Failed to get model", options);
2312
+ process.exit(1);
2313
+ }
2314
+ if (!result.data) {
2315
+ outputError(`Model "${modelId}" not found`, options);
2316
+ process.exit(1);
2317
+ }
2318
+ const model2 = result.data;
2319
+ if (options.json) {
2320
+ outputSuccess(
2321
+ {
2322
+ modelId: model2.modelId,
2323
+ name: model2.displayName ?? model2.modelName,
2324
+ provider: model2.provider,
2325
+ category: model2.category,
2326
+ description: model2.description,
2327
+ inputSchema: model2.inputSchema
2328
+ },
2329
+ options
2330
+ );
2331
+ } else {
2332
+ console.log(
2333
+ formatKeyValue([
2334
+ { key: "Model ID", value: model2.modelId },
2335
+ { key: "Name", value: model2.displayName ?? model2.modelName },
2336
+ { key: "Provider", value: model2.provider },
2337
+ { key: "Category", value: model2.category },
2338
+ {
2339
+ key: "Description",
2340
+ value: model2.description ?? chalk25.dim("None")
2341
+ }
2342
+ ])
2343
+ );
2344
+ const schema = model2.inputSchema;
2345
+ if (!schema?.properties) {
2346
+ console.log(chalk25.dim("\nNo input schema available."));
2347
+ return;
2348
+ }
2349
+ const required = new Set(schema.required ?? []);
2350
+ const props = schema.properties;
2351
+ console.log(`
2352
+ ${chalk25.bold("Input Parameters")}:
2353
+ `);
2354
+ const rows = Object.entries(props).map(([key, prop]) => [
2355
+ key,
2356
+ prop.type ?? "unknown",
2357
+ required.has(key) ? chalk25.green("yes") : chalk25.dim("no"),
2358
+ formatDefault(prop.default),
2359
+ formatConstraints(prop)
2360
+ ]);
2361
+ console.log(
2362
+ formatTable(
2363
+ ["Parameter", "Type", "Required", "Default", "Constraints"],
2364
+ rows
2365
+ )
2366
+ );
2367
+ const withDescriptions = Object.entries(props).filter(
2368
+ ([, p]) => p.description
2369
+ );
2370
+ if (withDescriptions.length > 0) {
2371
+ console.log(`
2372
+ ${chalk25.bold("Parameter Details")}:
2373
+ `);
2374
+ for (const [key, prop] of withDescriptions) {
2375
+ console.log(` ${chalk25.cyan(key)}: ${prop.description}`);
2376
+ if (prop.enum) {
2377
+ console.log(
2378
+ ` Values: ${prop.enum.map((v) => chalk25.green(String(v))).join(", ")}`
2379
+ );
2380
+ }
2381
+ }
2382
+ }
2383
+ }
2384
+ }
2385
+ function formatDefault(value) {
2386
+ if (value === void 0 || value === null) return chalk25.dim("\u2014");
2387
+ if (typeof value === "object") return JSON.stringify(value);
2388
+ return String(value);
2389
+ }
2390
+ function formatConstraints(prop) {
2391
+ const parts = [];
2392
+ if (prop.enum) {
2393
+ const enumStr = prop.enum.map(String).join("|");
2394
+ parts.push(enumStr.length > 40 ? enumStr.substring(0, 37) + "..." : enumStr);
2395
+ }
2396
+ if (prop.minimum !== void 0) parts.push(`min:${prop.minimum}`);
2397
+ if (prop.maximum !== void 0) parts.push(`max:${prop.maximum}`);
2398
+ return parts.length > 0 ? parts.join(", ") : chalk25.dim("\u2014");
2399
+ }
2400
+
2401
+ // src/index.ts
2402
+ var program = new Command();
2403
+ var require2 = createRequire(import.meta.url);
2404
+ var packageJson = require2("../package.json");
2405
+ program.name("program").description("CLI for the Program video creation platform").version(packageJson.version);
2406
+ var auth = program.command("auth").description("Authentication commands");
2407
+ auth.command("login").description("Authenticate with the Program platform").option("--json", "Output as JSON").action(async (options) => {
2408
+ await loginCommand(options);
2409
+ });
2410
+ auth.command("logout").description("Log out from the Program platform").option("--json", "Output as JSON").action((options) => {
2411
+ logoutCommand(options);
2412
+ });
2413
+ auth.command("status").description("Check authentication status").option("--json", "Output as JSON").action((options) => {
2414
+ statusCommand(options);
2415
+ });
2416
+ var project = program.command("project").description("Project management commands");
2417
+ project.command("create").description("Create a new project").option("--title <title>", "Project title").option("--description <description>", "Project description").option("--json", "Output as JSON").action(async (options) => {
2418
+ await createCommand(options);
2419
+ });
2420
+ project.command("list").description("List projects").option("--limit <limit>", "Maximum number of projects to return", parseInt).option("--json", "Output as JSON").action(async (options) => {
2421
+ await listCommand(options);
2422
+ });
2423
+ project.command("get <id>").description("Get project details including composition").option("--json", "Output as JSON").action(async (id, options) => {
2424
+ await getCommand(id, options);
2425
+ });
2426
+ var workflow = program.command("workflow").description("Workflow template commands (use 'template' for full management)");
2427
+ workflow.command("list").description("List available workflow templates").option("--limit <limit>", "Maximum number of templates to return", parseInt).option("--public-only", "Only show public templates").option("--json", "Output as JSON").action(async (options) => {
2428
+ await listCommand2(options);
2429
+ });
2430
+ workflow.command("run <templateId>").description("Execute a workflow template").option("--project <projectId>", "Project ID to associate with execution").option("--input <json>", "JSON input for the workflow").option("--json", "Output as JSON").action(async (templateId, options) => {
2431
+ await runCommand(templateId, options);
2432
+ });
2433
+ workflow.command("status <executionId>").description("Check workflow execution status").option("--watch", "Continuously poll for status updates").option("--interval <ms>", "Poll interval in milliseconds", parseInt).option("--json", "Output as JSON").action(async (executionId, options) => {
2434
+ await statusCommand2(executionId, options);
2435
+ });
2436
+ var template = program.command("template").description("Template management commands");
2437
+ template.command("list").description("List templates").option("--public-only", "Only show public templates").option("--json", "Output as JSON").action(async (options) => {
2438
+ await listCommand5(options);
2439
+ });
2440
+ template.command("get [id]").description("Get template details (uses active template if no ID)").option("--json", "Output as JSON").action(async (id, options) => {
2441
+ await getCommand2(id, options);
2442
+ });
2443
+ template.command("create").description("Create a new template (auto-sets as active)").requiredOption("--name <name>", "Template name").option("--description <description>", "Template description").option("--public", "Make template public").option("--json", "Output as JSON").action(async (options) => {
2444
+ await createCommand2(options);
2445
+ });
2446
+ template.command("update [id]").description("Update template metadata (uses active template if no ID)").option("--name <name>", "New template name").option("--description <description>", "New template description").option("--public", "Make template public").option("--steps <json>", "Replace steps array with JSON").option("--json", "Output as JSON").action(async (id, options) => {
2447
+ await updateCommand(id, options);
2448
+ });
2449
+ template.command("remove [id]").description("Delete a template (uses active template if no ID)").option("--force", "Skip confirmation prompt").option("--json", "Output as JSON").action(async (id, options) => {
2450
+ await removeCommand(id, options);
2451
+ });
2452
+ template.command("run [id]").description("Execute a template (uses active template if no ID)").option("--project <projectId>", "Project ID to associate with execution").option("--input <json>", "JSON input for the workflow").option("--json", "Output as JSON").action(async (id, options) => {
2453
+ await runCommand2(id, options);
2454
+ });
2455
+ template.command("status <executionId>").description("Check execution status").option("--watch", "Continuously poll for status updates").option("--interval <ms>", "Poll interval in milliseconds", parseInt).option("--json", "Output as JSON").action(async (executionId, options) => {
2456
+ await statusCommand3(executionId, options);
2457
+ });
2458
+ template.command("use <id>").description("Set the active template context").option("--json", "Output as JSON").action(async (id, options) => {
2459
+ await useCommand(id, options);
2460
+ });
2461
+ var step = template.command("step").description("Manage template steps and discover step types");
2462
+ step.command("list").description("List available step types").option("--category <category>", "Filter by category").option("--json", "Output as JSON").action(async (options) => {
2463
+ await stepListCommand(options);
2464
+ });
2465
+ step.command("info <stepType>").description("Show step type details (inputs, outputs)").option("--json", "Output as JSON").action(async (stepType, options) => {
2466
+ await stepInfoCommand(stepType, options);
2467
+ });
2468
+ step.command("add <stepType>").description("Add a step to the active template").option("--config <json>", "Step configuration as JSON").option("--at <position>", "Insert at position (0-indexed)", parseInt).option("--after <id>", "Insert after step with this ID").option("--template <id>", "Template ID (overrides active template)").option("--json", "Output as JSON").action(async (stepType, options) => {
2469
+ await stepAddCommand(stepType, options);
2470
+ });
2471
+ step.command("remove <id>").description("Remove a step by its instance ID").option("--template <id>", "Template ID (overrides active template)").option("--json", "Output as JSON").action(async (id, options) => {
2472
+ await stepRemoveCommand(id, options);
2473
+ });
2474
+ step.command("update <id>").description("Update a step's config by its instance ID").option("--config <json>", "Config to merge as JSON").option("--template <id>", "Template ID (overrides active template)").option("--json", "Output as JSON").action(async (id, options) => {
2475
+ await stepUpdateCommand(id, options);
2476
+ });
2477
+ var model = template.command("model").description("Browse models and schemas");
2478
+ model.command("list <category>").description("List models for a category (image, video, speech, text)").option("--json", "Output as JSON").action(async (category, options) => {
2479
+ await modelListCommand(category, options);
2480
+ });
2481
+ model.command("schema <modelId>").description("Show full input schema for a model").option("--json", "Output as JSON").action(async (modelId, options) => {
2482
+ await modelSchemaCommand(modelId, options);
1454
2483
  });
1455
2484
  var tool = program.command("tool").description("Execute agent tools directly");
1456
2485
  tool.addHelpText(