@vm0/cli 9.119.3 → 9.120.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/index.js CHANGED
@@ -65,7 +65,7 @@ import {
65
65
  source_default,
66
66
  volumeConfigSchema,
67
67
  withErrorHandler
68
- } from "./chunk-6UFVJSUZ.js";
68
+ } from "./chunk-CVXG5BRK.js";
69
69
  import {
70
70
  __toESM,
71
71
  init_esm_shims
@@ -398,7 +398,7 @@ function getConfigPath() {
398
398
  return join(homedir(), ".vm0", "config.json");
399
399
  }
400
400
  var infoCommand = new Command().name("info").description("Display environment and debug information").action(async () => {
401
- console.log(source_default.bold(`VM0 CLI v${"9.119.3"}`));
401
+ console.log(source_default.bold(`VM0 CLI v${"9.120.0"}`));
402
402
  console.log();
403
403
  const config = await loadConfig();
404
404
  const hasEnvToken = !!process.env.VM0_TOKEN;
@@ -4291,7 +4291,7 @@ var composeCommand = new Command().name("compose").description("Create or update
4291
4291
  options.autoUpdate = false;
4292
4292
  }
4293
4293
  if (options.autoUpdate !== false) {
4294
- await startSilentUpgrade("9.119.3");
4294
+ await startSilentUpgrade("9.120.0");
4295
4295
  }
4296
4296
  try {
4297
4297
  let result;
@@ -4381,7 +4381,7 @@ var mainRunCommand = new Command().name("run").description("Run an agent").argum
4381
4381
  withErrorHandler(
4382
4382
  async (identifier, prompt, options) => {
4383
4383
  if (options.autoUpdate !== false) {
4384
- await startSilentUpgrade("9.119.3");
4384
+ await startSilentUpgrade("9.120.0");
4385
4385
  }
4386
4386
  const { name, version } = parseIdentifier(identifier);
4387
4387
  let composeId;
@@ -6393,13 +6393,13 @@ var upgradeCommand = new Command().name("upgrade").description("Upgrade vm0 CLI
6393
6393
  if (latestVersion === null) {
6394
6394
  throw new Error("Could not check for updates. Please try again later.");
6395
6395
  }
6396
- if (latestVersion === "9.119.3") {
6397
- console.log(source_default.green(`\u2713 Already up to date (${"9.119.3"})`));
6396
+ if (latestVersion === "9.120.0") {
6397
+ console.log(source_default.green(`\u2713 Already up to date (${"9.120.0"})`));
6398
6398
  return;
6399
6399
  }
6400
6400
  console.log(
6401
6401
  source_default.yellow(
6402
- `Current version: ${"9.119.3"} -> Latest version: ${latestVersion}`
6402
+ `Current version: ${"9.120.0"} -> Latest version: ${latestVersion}`
6403
6403
  )
6404
6404
  );
6405
6405
  console.log();
@@ -6426,7 +6426,7 @@ var upgradeCommand = new Command().name("upgrade").description("Upgrade vm0 CLI
6426
6426
  const success = await performUpgrade(packageManager);
6427
6427
  if (success) {
6428
6428
  console.log(
6429
- source_default.green(`\u2713 Upgraded from ${"9.119.3"} to ${latestVersion}`)
6429
+ source_default.green(`\u2713 Upgraded from ${"9.120.0"} to ${latestVersion}`)
6430
6430
  );
6431
6431
  return;
6432
6432
  }
@@ -6493,7 +6493,7 @@ var whoamiCommand = new Command().name("whoami").description("Show current ident
6493
6493
 
6494
6494
  // src/index.ts
6495
6495
  var program = new Command();
6496
- program.name("vm0").description("VM0 CLI - Build and run agents with natural language").version("9.119.3");
6496
+ program.name("vm0").description("VM0 CLI - Build and run agents with natural language").version("9.120.0");
6497
6497
  program.addCommand(authCommand);
6498
6498
  program.addCommand(infoCommand);
6499
6499
  program.addCommand(composeCommand);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vm0/cli",
3
- "version": "9.119.3",
3
+ "version": "9.120.0",
4
4
  "description": "CLI application",
5
5
  "repository": {
6
6
  "type": "git",
package/zero.js CHANGED
@@ -104,6 +104,7 @@ import {
104
104
  resolveFirewallPolicies,
105
105
  resolveZeroScheduleByAgent,
106
106
  saveConfig,
107
+ searchConnectors,
107
108
  searchZeroLogs,
108
109
  sendChatMessage,
109
110
  sendSlackMessage,
@@ -125,7 +126,7 @@ import {
125
126
  upsertZeroOrgModelProvider,
126
127
  withErrorHandler,
127
128
  zeroAgentCustomSkillNameSchema
128
- } from "./chunk-6UFVJSUZ.js";
129
+ } from "./chunk-CVXG5BRK.js";
129
130
  import {
130
131
  __toESM,
131
132
  init_esm_shims
@@ -1560,15 +1561,61 @@ init_esm_shims();
1560
1561
 
1561
1562
  // src/commands/zero/connector/list.ts
1562
1563
  init_esm_shims();
1563
- var listCommand6 = new Command().name("list").alias("ls").description("List all connectors and their status").action(
1564
- withErrorHandler(async () => {
1565
- const result = await listZeroConnectors();
1564
+
1565
+ // src/commands/zero/connector/agent-context.ts
1566
+ init_esm_shims();
1567
+ async function resolveAgentContext(flagAgentId) {
1568
+ const agentId = flagAgentId ?? process.env.ZERO_AGENT_ID;
1569
+ if (!agentId) return null;
1570
+ const [agent, enabledTypes] = await Promise.all([
1571
+ getZeroAgent(agentId),
1572
+ getZeroAgentUserConnectors(agentId)
1573
+ ]);
1574
+ return {
1575
+ agentId: agent.agentId,
1576
+ displayName: agent.displayName ?? agent.agentId,
1577
+ authorizedTypes: new Set(enabledTypes)
1578
+ };
1579
+ }
1580
+
1581
+ // src/commands/zero/connector/list.ts
1582
+ function renderIdentity(connector) {
1583
+ if (connector.externalUsername) return `@${connector.externalUsername}`;
1584
+ if (connector.externalEmail) return connector.externalEmail;
1585
+ return "-";
1586
+ }
1587
+ function renderConnectedAsCell(connector) {
1588
+ if (!connector) return source_default.dim("(not connected)");
1589
+ const identity = renderIdentity(connector);
1590
+ if (connector.needsReconnect) {
1591
+ return source_default.yellow(`${identity} (reconnect needed)`);
1592
+ }
1593
+ const scopeMismatch = connector.authMethod === "oauth" && !hasRequiredScopes(connector.type, connector.oauthScopes);
1594
+ if (scopeMismatch) {
1595
+ return source_default.yellow(`${identity} (permissions update available)`);
1596
+ }
1597
+ return identity;
1598
+ }
1599
+ var ANSI_PATTERN = /\u001b\[[0-9;]*m/g;
1600
+ function stripAnsi(s) {
1601
+ return s.replace(ANSI_PATTERN, "");
1602
+ }
1603
+ function padEndAnsi(s, width) {
1604
+ const visible = stripAnsi(s).length;
1605
+ return s + " ".repeat(Math.max(0, width - visible));
1606
+ }
1607
+ var listCommand6 = new Command().name("list").alias("ls").description("List all connectors and their status").option("--agent <id>", "Show per-agent authorization column").action(
1608
+ withErrorHandler(async (options) => {
1609
+ const [{ connectors }, orgId, agentCtx] = await Promise.all([
1610
+ listZeroConnectors(),
1611
+ getActiveOrg(),
1612
+ resolveAgentContext(options.agent)
1613
+ ]);
1566
1614
  const connectedMap = new Map(
1567
- result.connectors.map((c) => {
1615
+ connectors.map((c) => {
1568
1616
  return [c.type, c];
1569
1617
  })
1570
1618
  );
1571
- const orgId = await getActiveOrg();
1572
1619
  const allTypesRaw = Object.keys(CONNECTOR_TYPES);
1573
1620
  const allTypes = [];
1574
1621
  for (const type of allTypesRaw) {
@@ -1585,25 +1632,133 @@ var listCommand6 = new Command().name("list").alias("ls").description("List all
1585
1632
  return t.length;
1586
1633
  })
1587
1634
  );
1588
- const statusText = "STATUS";
1589
- const statusWidth = statusText.length;
1590
- const header = [
1635
+ const connectedAsHeader = "CONNECTED AS";
1636
+ const connectedCells = allTypes.map((type) => {
1637
+ return renderConnectedAsCell(connectedMap.get(type));
1638
+ });
1639
+ const connectedAsWidth = Math.max(
1640
+ connectedAsHeader.length,
1641
+ ...connectedCells.map((c) => {
1642
+ return stripAnsi(c).length;
1643
+ })
1644
+ );
1645
+ const authorizedHeader = agentCtx ? `AUTHORIZED FOR ${agentCtx.displayName}` : null;
1646
+ const headerParts = [
1591
1647
  "TYPE".padEnd(typeWidth),
1592
- statusText.padEnd(statusWidth),
1593
- "ACCOUNT"
1594
- ].join(" ");
1595
- console.log(source_default.dim(header));
1596
- for (const type of allTypes) {
1597
- const connector = connectedMap.get(type);
1598
- const scopeMismatch = connector !== void 0 && connector.authMethod === "oauth" && !hasRequiredScopes(type, connector.oauthScopes);
1599
- const status = connector ? connector.needsReconnect ? source_default.yellow("!".padEnd(statusWidth)) : scopeMismatch ? source_default.yellow("!".padEnd(statusWidth)) : source_default.green("\u2713".padEnd(statusWidth)) : source_default.dim("-".padEnd(statusWidth));
1600
- const account = connector?.needsReconnect ? source_default.yellow("(reconnect needed)") : scopeMismatch ? source_default.yellow("(permissions update available)") : connector?.externalUsername ? `@${connector.externalUsername}` : source_default.dim("-");
1601
- const row = [type.padEnd(typeWidth), status, account].join(" ");
1602
- console.log(row);
1648
+ connectedAsHeader.padEnd(connectedAsWidth)
1649
+ ];
1650
+ if (authorizedHeader) headerParts.push(authorizedHeader);
1651
+ console.log(source_default.dim(headerParts.join(" ")));
1652
+ for (let i = 0; i < allTypes.length; i++) {
1653
+ const type = allTypes[i];
1654
+ const connectedCell = padEndAnsi(connectedCells[i], connectedAsWidth);
1655
+ const parts = [type.padEnd(typeWidth), connectedCell];
1656
+ if (agentCtx) {
1657
+ parts.push(
1658
+ agentCtx.authorizedTypes.has(type) ? source_default.green("\u2713") : source_default.dim("-")
1659
+ );
1660
+ }
1661
+ console.log(parts.join(" "));
1603
1662
  }
1604
1663
  })
1605
1664
  );
1606
1665
 
1666
+ // src/commands/zero/connector/search.ts
1667
+ init_esm_shims();
1668
+ var DEFAULT_LIMIT = 5;
1669
+ var EXACT_MATCH_THRESHOLD = 80;
1670
+ var ANSI_PATTERN2 = /\u001b\[[0-9;]*m/g;
1671
+ function stripAnsi2(s) {
1672
+ return s.replace(ANSI_PATTERN2, "");
1673
+ }
1674
+ function padEndAnsi2(s, width) {
1675
+ const visible = stripAnsi2(s).length;
1676
+ return s + " ".repeat(Math.max(0, width - visible));
1677
+ }
1678
+ function parseLimit(raw) {
1679
+ const n = Number.parseInt(raw, 10);
1680
+ if (!Number.isFinite(n) || n <= 0) {
1681
+ throw new Error(`--limit must be a positive integer, got "${raw}".`);
1682
+ }
1683
+ return n;
1684
+ }
1685
+ var searchCommand = new Command().name("search").description("Search connectors by type, label, env var, secret, or tag").argument("<keyword>", "Search keyword (case-insensitive)").option("--agent <id>", "Show per-agent authorization column").option(
1686
+ "--limit <n>",
1687
+ `Maximum number of results to display (default ${DEFAULT_LIMIT})`,
1688
+ parseLimit,
1689
+ DEFAULT_LIMIT
1690
+ ).action(
1691
+ withErrorHandler(
1692
+ async (keyword, options) => {
1693
+ const trimmed = keyword.trim();
1694
+ if (!trimmed) {
1695
+ throw new Error("Keyword cannot be empty.");
1696
+ }
1697
+ const [orgId, agentCtx] = await Promise.all([
1698
+ getActiveOrg(),
1699
+ resolveAgentContext(options.agent)
1700
+ ]);
1701
+ const isTypeAvailable = (type) => {
1702
+ const config = CONNECTOR_TYPES[type];
1703
+ const flag = config.featureFlag;
1704
+ const hasApiToken = "api-token" in config.authMethods;
1705
+ return !flag || isFeatureEnabled(flag, { orgId }) || hasApiToken;
1706
+ };
1707
+ const { results, total } = searchConnectors(
1708
+ trimmed,
1709
+ options.limit,
1710
+ isTypeAvailable
1711
+ );
1712
+ if (results.length === 0) {
1713
+ console.log("No matches found.");
1714
+ return;
1715
+ }
1716
+ const topScore = results[0].score;
1717
+ if (topScore < EXACT_MATCH_THRESHOLD) {
1718
+ console.log("No exact match. Showing closest:");
1719
+ }
1720
+ if (total > options.limit) {
1721
+ console.log(`Too many results (top ${options.limit} of ${total}):`);
1722
+ }
1723
+ const typeHeader = "TYPE";
1724
+ const labelHeader = "LABEL";
1725
+ const typeWidth = Math.max(
1726
+ typeHeader.length,
1727
+ ...results.map((r) => {
1728
+ return r.type.length;
1729
+ })
1730
+ );
1731
+ const labelWidth = Math.max(
1732
+ labelHeader.length,
1733
+ ...results.map((r) => {
1734
+ return CONNECTOR_TYPES[r.type].label.length;
1735
+ })
1736
+ );
1737
+ const headerParts = [
1738
+ typeHeader.padEnd(typeWidth),
1739
+ labelHeader.padEnd(labelWidth)
1740
+ ];
1741
+ if (agentCtx) {
1742
+ headerParts.push(`AUTHORIZED FOR ${agentCtx.displayName}`);
1743
+ }
1744
+ console.log(source_default.dim(headerParts.join(" ")));
1745
+ for (const result of results) {
1746
+ const config = CONNECTOR_TYPES[result.type];
1747
+ const parts = [
1748
+ result.type.padEnd(typeWidth),
1749
+ padEndAnsi2(config.label, labelWidth)
1750
+ ];
1751
+ if (agentCtx) {
1752
+ parts.push(
1753
+ agentCtx.authorizedTypes.has(result.type) ? source_default.green("\u2713") : source_default.dim("-")
1754
+ );
1755
+ }
1756
+ console.log(parts.join(" "));
1757
+ }
1758
+ }
1759
+ )
1760
+ );
1761
+
1607
1762
  // src/commands/zero/connector/status.ts
1608
1763
  init_esm_shims();
1609
1764
 
@@ -1721,10 +1876,30 @@ function toISODateTime(dateTimeStr) {
1721
1876
  return date.toISOString();
1722
1877
  }
1723
1878
 
1879
+ // src/commands/zero/doctor/platform-url.ts
1880
+ init_esm_shims();
1881
+ function toPlatformUrl(apiUrl) {
1882
+ const parsed = new URL(apiUrl);
1883
+ const parts = parsed.hostname.split(".");
1884
+ if (parts[0].endsWith("-www")) {
1885
+ parts[0] = parts[0].slice(0, -"-www".length) + "-app";
1886
+ } else if (parts[0] === "www" || parts[0] === "platform") {
1887
+ parts[0] = "app";
1888
+ } else if (parts[0] !== "app" && parts[0] !== "localhost") {
1889
+ parts.unshift("app");
1890
+ }
1891
+ parsed.hostname = parts.join(".");
1892
+ return parsed;
1893
+ }
1894
+ async function getPlatformOrigin() {
1895
+ const apiUrl = await getApiUrl();
1896
+ return toPlatformUrl(apiUrl).origin;
1897
+ }
1898
+
1724
1899
  // src/commands/zero/connector/status.ts
1725
1900
  var LABEL_WIDTH = 16;
1726
- var statusCommand2 = new Command().name("status").description("Show detailed status of a connector").argument("<type>", "Connector type (e.g., github)").action(
1727
- withErrorHandler(async (type) => {
1901
+ var statusCommand2 = new Command().name("status").description("Show detailed status of a connector").argument("<type>", "Connector type (e.g., github)").option("--agent <id>", "Show authorization state for the given agent").action(
1902
+ withErrorHandler(async (type, options) => {
1728
1903
  const parseResult = connectorTypeSchema.safeParse(type);
1729
1904
  if (!parseResult.success) {
1730
1905
  const available = Object.keys(CONNECTOR_TYPES).join(", ");
@@ -1732,7 +1907,10 @@ var statusCommand2 = new Command().name("status").description("Show detailed sta
1732
1907
  cause: new Error(`Available connectors: ${available}`)
1733
1908
  });
1734
1909
  }
1735
- const connector = await getZeroConnector(parseResult.data);
1910
+ const [connector, agentCtx] = await Promise.all([
1911
+ getZeroConnector(parseResult.data),
1912
+ resolveAgentContext(options.agent)
1913
+ ]);
1736
1914
  console.log(`Connector: ${source_default.cyan(type)}`);
1737
1915
  console.log();
1738
1916
  if (connector) {
@@ -1779,39 +1957,32 @@ var statusCommand2 = new Command().name("status").description("Show detailed sta
1779
1957
  `${"Status:".padEnd(LABEL_WIDTH)}${source_default.dim("not connected")}`
1780
1958
  );
1781
1959
  }
1960
+ if (agentCtx) {
1961
+ const authorized = agentCtx.authorizedTypes.has(parseResult.data);
1962
+ const glyph = authorized ? source_default.green("\u2713") : source_default.dim("-");
1963
+ console.log();
1964
+ console.log(
1965
+ `${"Authorized:".padEnd(LABEL_WIDTH)}${glyph} for agent ${agentCtx.displayName}`
1966
+ );
1967
+ if (!authorized) {
1968
+ const origin = await getPlatformOrigin();
1969
+ const url = `${origin}/connectors/${parseResult.data}/authorize?agentId=${agentCtx.agentId}`;
1970
+ console.log(
1971
+ `${"".padEnd(LABEL_WIDTH)}${source_default.dim("Authorize:")} ${url}`
1972
+ );
1973
+ }
1974
+ }
1782
1975
  })
1783
1976
  );
1784
1977
 
1785
1978
  // src/commands/zero/connector/index.ts
1786
- var zeroConnectorCommand = new Command().name("connector").description("Check third-party service connections (GitHub, Slack, etc.)").addCommand(listCommand6).addCommand(statusCommand2);
1979
+ var zeroConnectorCommand = new Command().name("connector").description("Check third-party service connections (GitHub, Slack, etc.)").addCommand(listCommand6).addCommand(searchCommand).addCommand(statusCommand2);
1787
1980
 
1788
1981
  // src/commands/zero/doctor/index.ts
1789
1982
  init_esm_shims();
1790
1983
 
1791
1984
  // src/commands/zero/doctor/check-connector.ts
1792
1985
  init_esm_shims();
1793
-
1794
- // src/commands/zero/doctor/platform-url.ts
1795
- init_esm_shims();
1796
- function toPlatformUrl(apiUrl) {
1797
- const parsed = new URL(apiUrl);
1798
- const parts = parsed.hostname.split(".");
1799
- if (parts[0].endsWith("-www")) {
1800
- parts[0] = parts[0].slice(0, -"-www".length) + "-app";
1801
- } else if (parts[0] === "www" || parts[0] === "platform") {
1802
- parts[0] = "app";
1803
- } else if (parts[0] !== "app" && parts[0] !== "localhost") {
1804
- parts.unshift("app");
1805
- }
1806
- parsed.hostname = parts.join(".");
1807
- return parsed;
1808
- }
1809
- async function getPlatformOrigin() {
1810
- const apiUrl = await getApiUrl();
1811
- return toPlatformUrl(apiUrl).origin;
1812
- }
1813
-
1814
- // src/commands/zero/doctor/check-connector.ts
1815
1986
  function resolveConnectorFromUrl(url) {
1816
1987
  const allTypes = Object.keys(CONNECTOR_TYPES);
1817
1988
  const normalized = url.endsWith("/") ? url.slice(0, -1) : url;
@@ -4454,7 +4625,7 @@ function parseContextOptions(options) {
4454
4625
  }
4455
4626
  return { before, after };
4456
4627
  }
4457
- function parseLimit(value) {
4628
+ function parseLimit2(value) {
4458
4629
  if (!value) return void 0;
4459
4630
  const limit = parseInt(value, 10);
4460
4631
  if (isNaN(limit) || limit < 1 || limit > 50) {
@@ -4509,7 +4680,7 @@ function renderResults(response) {
4509
4680
  );
4510
4681
  }
4511
4682
  }
4512
- var searchCommand = new Command().name("search").description("Search agent events across runs").argument("<keyword>", "Search keyword").option("-A, --after-context <n>", "Show n events after each match").option("-B, --before-context <n>", "Show n events before each match").option("-C, --context <n>", "Show n events before and after each match").option("--agent <name>", "Filter by agent name").option("--run <id>", "Filter by specific run ID").option("--since <time>", "Search logs since (default: 7d)").option("--limit <n>", "Maximum number of matches (default: 20)").addHelpText(
4683
+ var searchCommand2 = new Command().name("search").description("Search agent events across runs").argument("<keyword>", "Search keyword").option("-A, --after-context <n>", "Show n events after each match").option("-B, --before-context <n>", "Show n events before each match").option("-C, --context <n>", "Show n events before and after each match").option("--agent <name>", "Filter by agent name").option("--run <id>", "Filter by specific run ID").option("--since <time>", "Search logs since (default: 7d)").option("--limit <n>", "Maximum number of matches (default: 20)").addHelpText(
4513
4684
  "after",
4514
4685
  `
4515
4686
  Examples:
@@ -4527,7 +4698,7 @@ Examples:
4527
4698
  process.exit(1);
4528
4699
  }
4529
4700
  const since = options.since ? parseTime(options.since) : Date.now() - SEVEN_DAYS_MS;
4530
- const limit = parseLimit(options.limit);
4701
+ const limit = parseLimit2(options.limit);
4531
4702
  const response = await searchZeroLogs({
4532
4703
  keyword,
4533
4704
  agent: options.agent,
@@ -4605,7 +4776,7 @@ async function showAgentEvents(runId, options) {
4605
4776
  renderAgentEvent(event, renderer);
4606
4777
  }
4607
4778
  }
4608
- var zeroLogsCommand = new Command().name("logs").description("View and search agent run logs").argument("[runId]", "Run ID to view agent events for").addCommand(listCommand11).addCommand(searchCommand).option(
4779
+ var zeroLogsCommand = new Command().name("logs").description("View and search agent run logs").argument("[runId]", "Run ID to view agent events for").addCommand(listCommand11).addCommand(searchCommand2).option(
4609
4780
  "--since <time>",
4610
4781
  "Show logs since timestamp (e.g., 5m, 2h, 1d, 2024-01-15T10:30:00Z)"
4611
4782
  ).option("--tail <n>", "Show last N entries (default: 5)").option("--head <n>", "Show first N entries").option("--all", "Fetch all log entries").addHelpText(
@@ -6120,7 +6291,7 @@ function registerZeroCommands(prog, commands) {
6120
6291
  var program = new Command();
6121
6292
  program.name("zero").description(
6122
6293
  "Zero CLI \u2014 interact with the zero platform from inside the sandbox"
6123
- ).version("9.119.3").addHelpText(
6294
+ ).version("9.120.0").addHelpText(
6124
6295
  "after",
6125
6296
  `
6126
6297
  Examples: