@vm0/cli 9.119.3 → 9.121.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-3CRO7Q5L.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.121.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.121.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.121.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.121.0") {
6397
+ console.log(source_default.green(`\u2713 Already up to date (${"9.121.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.121.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.121.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.121.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.121.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-3CRO7Q5L.js";
129
130
  import {
130
131
  __toESM,
131
132
  init_esm_shims
@@ -1560,15 +1561,64 @@ 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/connected-as.ts
1582
+ init_esm_shims();
1583
+ function renderIdentity(connector) {
1584
+ if (connector.externalUsername) return `@${connector.externalUsername}`;
1585
+ if (connector.externalEmail) return connector.externalEmail;
1586
+ return "-";
1587
+ }
1588
+ function renderConnectedAsCell(connector) {
1589
+ if (!connector) return source_default.dim("(not connected)");
1590
+ const identity = renderIdentity(connector);
1591
+ if (connector.needsReconnect) {
1592
+ return source_default.yellow(`${identity} (reconnect needed)`);
1593
+ }
1594
+ const scopeMismatch = connector.authMethod === "oauth" && !hasRequiredScopes(connector.type, connector.oauthScopes);
1595
+ if (scopeMismatch) {
1596
+ return source_default.yellow(`${identity} (permissions update available)`);
1597
+ }
1598
+ return identity;
1599
+ }
1600
+ var ANSI_PATTERN = /\u001b\[[0-9;]*m/g;
1601
+ function stripAnsi(s) {
1602
+ return s.replace(ANSI_PATTERN, "");
1603
+ }
1604
+ function padEndAnsi(s, width) {
1605
+ const visible = stripAnsi(s).length;
1606
+ return s + " ".repeat(Math.max(0, width - visible));
1607
+ }
1608
+
1609
+ // src/commands/zero/connector/list.ts
1610
+ var listCommand6 = new Command().name("list").alias("ls").description("List all connectors and their status").option("--agent <id>", "Show per-agent authorization column").action(
1611
+ withErrorHandler(async (options) => {
1612
+ const [{ connectors }, orgId, agentCtx] = await Promise.all([
1613
+ listZeroConnectors(),
1614
+ getActiveOrg(),
1615
+ resolveAgentContext(options.agent)
1616
+ ]);
1566
1617
  const connectedMap = new Map(
1567
- result.connectors.map((c) => {
1618
+ connectors.map((c) => {
1568
1619
  return [c.type, c];
1569
1620
  })
1570
1621
  );
1571
- const orgId = await getActiveOrg();
1572
1622
  const allTypesRaw = Object.keys(CONNECTOR_TYPES);
1573
1623
  const allTypes = [];
1574
1624
  for (const type of allTypesRaw) {
@@ -1585,25 +1635,134 @@ var listCommand6 = new Command().name("list").alias("ls").description("List all
1585
1635
  return t.length;
1586
1636
  })
1587
1637
  );
1588
- const statusText = "STATUS";
1589
- const statusWidth = statusText.length;
1590
- const header = [
1638
+ const connectedAsHeader = "CONNECTED AS";
1639
+ const connectedCells = allTypes.map((type) => {
1640
+ return renderConnectedAsCell(connectedMap.get(type));
1641
+ });
1642
+ const connectedAsWidth = Math.max(
1643
+ connectedAsHeader.length,
1644
+ ...connectedCells.map((c) => {
1645
+ return stripAnsi(c).length;
1646
+ })
1647
+ );
1648
+ const authorizedHeader = agentCtx ? `AUTHORIZED FOR ${agentCtx.displayName}` : null;
1649
+ const headerParts = [
1591
1650
  "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);
1651
+ connectedAsHeader.padEnd(connectedAsWidth)
1652
+ ];
1653
+ if (authorizedHeader) headerParts.push(authorizedHeader);
1654
+ console.log(source_default.dim(headerParts.join(" ")));
1655
+ for (let i = 0; i < allTypes.length; i++) {
1656
+ const type = allTypes[i];
1657
+ const connectedCell = padEndAnsi(connectedCells[i], connectedAsWidth);
1658
+ const parts = [type.padEnd(typeWidth), connectedCell];
1659
+ if (agentCtx) {
1660
+ parts.push(
1661
+ agentCtx.authorizedTypes.has(type) ? source_default.green("\u2713") : source_default.dim("-")
1662
+ );
1663
+ }
1664
+ console.log(parts.join(" "));
1603
1665
  }
1604
1666
  })
1605
1667
  );
1606
1668
 
1669
+ // src/commands/zero/connector/search.ts
1670
+ init_esm_shims();
1671
+ var DEFAULT_LIMIT = 5;
1672
+ var EXACT_MATCH_THRESHOLD = 80;
1673
+ function parseLimit(raw) {
1674
+ const n = Number.parseInt(raw, 10);
1675
+ if (!Number.isFinite(n) || n <= 0) {
1676
+ throw new Error(`--limit must be a positive integer, got "${raw}".`);
1677
+ }
1678
+ return n;
1679
+ }
1680
+ 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(
1681
+ "--limit <n>",
1682
+ `Maximum number of results to display (default ${DEFAULT_LIMIT})`,
1683
+ parseLimit,
1684
+ DEFAULT_LIMIT
1685
+ ).action(
1686
+ withErrorHandler(
1687
+ async (keyword, options) => {
1688
+ const trimmed = keyword.trim();
1689
+ if (!trimmed) {
1690
+ throw new Error("Keyword cannot be empty.");
1691
+ }
1692
+ const [{ connectors }, orgId, agentCtx] = await Promise.all([
1693
+ listZeroConnectors(),
1694
+ getActiveOrg(),
1695
+ resolveAgentContext(options.agent)
1696
+ ]);
1697
+ const connectedMap = new Map(
1698
+ connectors.map((c) => {
1699
+ return [c.type, c];
1700
+ })
1701
+ );
1702
+ const isTypeAvailable = (type) => {
1703
+ const config = CONNECTOR_TYPES[type];
1704
+ const flag = config.featureFlag;
1705
+ const hasApiToken = "api-token" in config.authMethods;
1706
+ return !flag || isFeatureEnabled(flag, { orgId }) || hasApiToken;
1707
+ };
1708
+ const { results, total } = searchConnectors(
1709
+ trimmed,
1710
+ options.limit,
1711
+ isTypeAvailable
1712
+ );
1713
+ if (results.length === 0) {
1714
+ console.log("No matches found.");
1715
+ return;
1716
+ }
1717
+ const topScore = results[0].score;
1718
+ if (topScore < EXACT_MATCH_THRESHOLD) {
1719
+ console.log("No exact match. Showing closest:");
1720
+ }
1721
+ if (total > options.limit) {
1722
+ console.log(`Too many results (top ${options.limit} of ${total}):`);
1723
+ }
1724
+ const typeHeader = "TYPE";
1725
+ const connectedAsHeader = "CONNECTED AS";
1726
+ const connectedCells = results.map((r) => {
1727
+ return renderConnectedAsCell(connectedMap.get(r.type));
1728
+ });
1729
+ const typeWidth = Math.max(
1730
+ typeHeader.length,
1731
+ ...results.map((r) => {
1732
+ return r.type.length;
1733
+ })
1734
+ );
1735
+ const connectedAsWidth = Math.max(
1736
+ connectedAsHeader.length,
1737
+ ...connectedCells.map((c) => {
1738
+ return stripAnsi(c).length;
1739
+ })
1740
+ );
1741
+ const headerParts = [
1742
+ typeHeader.padEnd(typeWidth),
1743
+ connectedAsHeader.padEnd(connectedAsWidth)
1744
+ ];
1745
+ if (agentCtx) {
1746
+ headerParts.push(`AUTHORIZED FOR ${agentCtx.displayName}`);
1747
+ }
1748
+ console.log(source_default.dim(headerParts.join(" ")));
1749
+ for (let i = 0; i < results.length; i++) {
1750
+ const result = results[i];
1751
+ const parts = [
1752
+ result.type.padEnd(typeWidth),
1753
+ padEndAnsi(connectedCells[i], connectedAsWidth)
1754
+ ];
1755
+ if (agentCtx) {
1756
+ parts.push(
1757
+ agentCtx.authorizedTypes.has(result.type) ? source_default.green("\u2713") : source_default.dim("-")
1758
+ );
1759
+ }
1760
+ console.log(parts.join(" "));
1761
+ }
1762
+ }
1763
+ )
1764
+ );
1765
+
1607
1766
  // src/commands/zero/connector/status.ts
1608
1767
  init_esm_shims();
1609
1768
 
@@ -1721,10 +1880,30 @@ function toISODateTime(dateTimeStr) {
1721
1880
  return date.toISOString();
1722
1881
  }
1723
1882
 
1883
+ // src/commands/zero/doctor/platform-url.ts
1884
+ init_esm_shims();
1885
+ function toPlatformUrl(apiUrl) {
1886
+ const parsed = new URL(apiUrl);
1887
+ const parts = parsed.hostname.split(".");
1888
+ if (parts[0].endsWith("-www")) {
1889
+ parts[0] = parts[0].slice(0, -"-www".length) + "-app";
1890
+ } else if (parts[0] === "www" || parts[0] === "platform") {
1891
+ parts[0] = "app";
1892
+ } else if (parts[0] !== "app" && parts[0] !== "localhost") {
1893
+ parts.unshift("app");
1894
+ }
1895
+ parsed.hostname = parts.join(".");
1896
+ return parsed;
1897
+ }
1898
+ async function getPlatformOrigin() {
1899
+ const apiUrl = await getApiUrl();
1900
+ return toPlatformUrl(apiUrl).origin;
1901
+ }
1902
+
1724
1903
  // src/commands/zero/connector/status.ts
1725
1904
  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) => {
1905
+ 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(
1906
+ withErrorHandler(async (type, options) => {
1728
1907
  const parseResult = connectorTypeSchema.safeParse(type);
1729
1908
  if (!parseResult.success) {
1730
1909
  const available = Object.keys(CONNECTOR_TYPES).join(", ");
@@ -1732,7 +1911,10 @@ var statusCommand2 = new Command().name("status").description("Show detailed sta
1732
1911
  cause: new Error(`Available connectors: ${available}`)
1733
1912
  });
1734
1913
  }
1735
- const connector = await getZeroConnector(parseResult.data);
1914
+ const [connector, agentCtx] = await Promise.all([
1915
+ getZeroConnector(parseResult.data),
1916
+ resolveAgentContext(options.agent)
1917
+ ]);
1736
1918
  console.log(`Connector: ${source_default.cyan(type)}`);
1737
1919
  console.log();
1738
1920
  if (connector) {
@@ -1779,39 +1961,32 @@ var statusCommand2 = new Command().name("status").description("Show detailed sta
1779
1961
  `${"Status:".padEnd(LABEL_WIDTH)}${source_default.dim("not connected")}`
1780
1962
  );
1781
1963
  }
1964
+ if (agentCtx) {
1965
+ const authorized = agentCtx.authorizedTypes.has(parseResult.data);
1966
+ const glyph = authorized ? source_default.green("\u2713") : source_default.dim("-");
1967
+ console.log();
1968
+ console.log(
1969
+ `${"Authorized:".padEnd(LABEL_WIDTH)}${glyph} for agent ${agentCtx.displayName}`
1970
+ );
1971
+ if (!authorized) {
1972
+ const origin = await getPlatformOrigin();
1973
+ const url = `${origin}/connectors/${parseResult.data}/authorize?agentId=${agentCtx.agentId}`;
1974
+ console.log(
1975
+ `${"".padEnd(LABEL_WIDTH)}${source_default.dim("Authorize:")} ${url}`
1976
+ );
1977
+ }
1978
+ }
1782
1979
  })
1783
1980
  );
1784
1981
 
1785
1982
  // 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);
1983
+ var zeroConnectorCommand = new Command().name("connector").description("Check third-party service connections (GitHub, Slack, etc.)").addCommand(listCommand6).addCommand(searchCommand).addCommand(statusCommand2);
1787
1984
 
1788
1985
  // src/commands/zero/doctor/index.ts
1789
1986
  init_esm_shims();
1790
1987
 
1791
1988
  // src/commands/zero/doctor/check-connector.ts
1792
1989
  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
1990
  function resolveConnectorFromUrl(url) {
1816
1991
  const allTypes = Object.keys(CONNECTOR_TYPES);
1817
1992
  const normalized = url.endsWith("/") ? url.slice(0, -1) : url;
@@ -4454,7 +4629,7 @@ function parseContextOptions(options) {
4454
4629
  }
4455
4630
  return { before, after };
4456
4631
  }
4457
- function parseLimit(value) {
4632
+ function parseLimit2(value) {
4458
4633
  if (!value) return void 0;
4459
4634
  const limit = parseInt(value, 10);
4460
4635
  if (isNaN(limit) || limit < 1 || limit > 50) {
@@ -4509,7 +4684,7 @@ function renderResults(response) {
4509
4684
  );
4510
4685
  }
4511
4686
  }
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(
4687
+ 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
4688
  "after",
4514
4689
  `
4515
4690
  Examples:
@@ -4527,7 +4702,7 @@ Examples:
4527
4702
  process.exit(1);
4528
4703
  }
4529
4704
  const since = options.since ? parseTime(options.since) : Date.now() - SEVEN_DAYS_MS;
4530
- const limit = parseLimit(options.limit);
4705
+ const limit = parseLimit2(options.limit);
4531
4706
  const response = await searchZeroLogs({
4532
4707
  keyword,
4533
4708
  agent: options.agent,
@@ -4605,7 +4780,7 @@ async function showAgentEvents(runId, options) {
4605
4780
  renderAgentEvent(event, renderer);
4606
4781
  }
4607
4782
  }
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(
4783
+ 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
4784
  "--since <time>",
4610
4785
  "Show logs since timestamp (e.g., 5m, 2h, 1d, 2024-01-15T10:30:00Z)"
4611
4786
  ).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 +6295,7 @@ function registerZeroCommands(prog, commands) {
6120
6295
  var program = new Command();
6121
6296
  program.name("zero").description(
6122
6297
  "Zero CLI \u2014 interact with the zero platform from inside the sandbox"
6123
- ).version("9.119.3").addHelpText(
6298
+ ).version("9.121.0").addHelpText(
6124
6299
  "after",
6125
6300
  `
6126
6301
  Examples: