@vm0/cli 9.36.0 → 9.37.1

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.
Files changed (2) hide show
  1. package/index.js +210 -97
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -45,7 +45,7 @@ if (DSN) {
45
45
  Sentry.init({
46
46
  dsn: DSN,
47
47
  environment: process.env.SENTRY_ENVIRONMENT ?? "production",
48
- release: "9.36.0",
48
+ release: "9.37.1",
49
49
  sendDefaultPii: false,
50
50
  tracesSampleRate: 0,
51
51
  shutdownTimeout: 500,
@@ -64,7 +64,7 @@ if (DSN) {
64
64
  }
65
65
  });
66
66
  Sentry.setContext("cli", {
67
- version: "9.36.0",
67
+ version: "9.37.1",
68
68
  command: process.argv.slice(2).join(" ")
69
69
  });
70
70
  Sentry.setContext("runtime", {
@@ -605,7 +605,7 @@ async function waitForSilentUpgrade(timeout = TIMEOUT_MS) {
605
605
  // src/commands/info/index.ts
606
606
  var CONFIG_PATH = join2(homedir2(), ".vm0", "config.json");
607
607
  var infoCommand = new Command6().name("info").description("Display environment and debug information").action(async () => {
608
- console.log(chalk7.bold(`VM0 CLI v${"9.36.0"}`));
608
+ console.log(chalk7.bold(`VM0 CLI v${"9.37.1"}`));
609
609
  console.log();
610
610
  const config = await loadConfig();
611
611
  const hasEnvToken = !!process.env.VM0_TOKEN;
@@ -3613,9 +3613,44 @@ var CONNECTOR_TYPES = {
3613
3613
  tokenUrl: "https://api.notion.com/v1/oauth/token",
3614
3614
  scopes: []
3615
3615
  }
3616
+ },
3617
+ computer: {
3618
+ label: "Computer",
3619
+ helpText: "Expose local services to remote sandboxes via authenticated ngrok tunnels",
3620
+ authMethods: {
3621
+ api: {
3622
+ label: "API",
3623
+ helpText: "Server-provisioned ngrok tunnel credentials.",
3624
+ secrets: {
3625
+ COMPUTER_CONNECTOR_AUTHTOKEN: {
3626
+ label: "ngrok Authtoken",
3627
+ required: true
3628
+ },
3629
+ COMPUTER_CONNECTOR_TOKEN: {
3630
+ label: "Bridge Token",
3631
+ required: true
3632
+ },
3633
+ COMPUTER_CONNECTOR_ENDPOINT: {
3634
+ label: "Endpoint Prefix",
3635
+ required: true
3636
+ },
3637
+ COMPUTER_CONNECTOR_DOMAIN: {
3638
+ label: "Tunnel Domain",
3639
+ required: true
3640
+ }
3641
+ }
3642
+ }
3643
+ },
3644
+ defaultAuthMethod: "api",
3645
+ environmentMapping: {
3646
+ COMPUTER_CONNECTOR_AUTHTOKEN: "$secrets.COMPUTER_CONNECTOR_AUTHTOKEN",
3647
+ COMPUTER_CONNECTOR_TOKEN: "$secrets.COMPUTER_CONNECTOR_TOKEN",
3648
+ COMPUTER_CONNECTOR_ENDPOINT: "$secrets.COMPUTER_CONNECTOR_ENDPOINT",
3649
+ COMPUTER_CONNECTOR_DOMAIN: "$secrets.COMPUTER_CONNECTOR_DOMAIN"
3650
+ }
3616
3651
  }
3617
3652
  };
3618
- var connectorTypeSchema = z23.enum(["github", "notion"]);
3653
+ var connectorTypeSchema = z23.enum(["github", "notion", "computer"]);
3619
3654
  function getConnectorEnvironmentMapping(type2) {
3620
3655
  return CONNECTOR_TYPES[type2].environmentMapping;
3621
3656
  }
@@ -3780,19 +3815,67 @@ var connectorSessionByIdContract = c19.router({
3780
3815
  summary: "Get connector session status"
3781
3816
  }
3782
3817
  });
3818
+ var computerConnectorCreateResponseSchema = z23.object({
3819
+ id: z23.string().uuid(),
3820
+ authtoken: z23.string(),
3821
+ bridgeToken: z23.string(),
3822
+ endpointPrefix: z23.string(),
3823
+ domain: z23.string()
3824
+ });
3825
+ var computerConnectorContract = c19.router({
3826
+ create: {
3827
+ method: "POST",
3828
+ path: "/api/connectors/computer",
3829
+ headers: authHeadersSchema,
3830
+ body: z23.object({}).optional(),
3831
+ responses: {
3832
+ 200: computerConnectorCreateResponseSchema,
3833
+ 400: apiErrorSchema,
3834
+ 401: apiErrorSchema,
3835
+ 409: apiErrorSchema,
3836
+ 500: apiErrorSchema
3837
+ },
3838
+ summary: "Create computer connector with ngrok tunnel credentials"
3839
+ },
3840
+ get: {
3841
+ method: "GET",
3842
+ path: "/api/connectors/computer",
3843
+ headers: authHeadersSchema,
3844
+ responses: {
3845
+ 200: connectorResponseSchema,
3846
+ 401: apiErrorSchema,
3847
+ 404: apiErrorSchema
3848
+ },
3849
+ summary: "Get computer connector status"
3850
+ },
3851
+ delete: {
3852
+ method: "DELETE",
3853
+ path: "/api/connectors/computer",
3854
+ headers: authHeadersSchema,
3855
+ responses: {
3856
+ 204: c19.noBody(),
3857
+ 401: apiErrorSchema,
3858
+ 404: apiErrorSchema,
3859
+ 500: apiErrorSchema
3860
+ },
3861
+ summary: "Delete computer connector and revoke ngrok credentials"
3862
+ }
3863
+ });
3783
3864
 
3784
3865
  // ../../packages/core/src/contracts/user-preferences.ts
3785
3866
  import { z as z24 } from "zod";
3786
3867
  var c20 = initContract();
3787
3868
  var userPreferencesResponseSchema = z24.object({
3788
3869
  timezone: z24.string().nullable(),
3789
- notifyEmail: z24.boolean()
3870
+ notifyEmail: z24.boolean(),
3871
+ notifySlack: z24.boolean()
3790
3872
  });
3791
3873
  var updateUserPreferencesRequestSchema = z24.object({
3792
3874
  timezone: z24.string().min(1).optional(),
3793
- notifyEmail: z24.boolean().optional()
3875
+ notifyEmail: z24.boolean().optional(),
3876
+ notifySlack: z24.boolean().optional()
3794
3877
  }).refine(
3795
- (data) => data.timezone !== void 0 || data.notifyEmail !== void 0,
3878
+ (data) => data.timezone !== void 0 || data.notifyEmail !== void 0 || data.notifySlack !== void 0,
3796
3879
  {
3797
3880
  message: "At least one preference must be provided"
3798
3881
  }
@@ -4502,6 +4585,10 @@ var FEATURE_SWITCHES = {
4502
4585
  ["platformApiKeys" /* PlatformApiKeys */]: {
4503
4586
  maintainer: "ethan@vm0.ai",
4504
4587
  enabled: false
4588
+ },
4589
+ ["computerConnector" /* ComputerConnector */]: {
4590
+ maintainer: "ethan@vm0.ai",
4591
+ enabled: false
4505
4592
  }
4506
4593
  };
4507
4594
 
@@ -6343,7 +6430,7 @@ var composeCommand = new Command7().name("compose").description("Create or updat
6343
6430
  options.autoUpdate = false;
6344
6431
  }
6345
6432
  if (options.autoUpdate !== false) {
6346
- await startSilentUpgrade("9.36.0");
6433
+ await startSilentUpgrade("9.37.1");
6347
6434
  }
6348
6435
  try {
6349
6436
  let result;
@@ -8540,7 +8627,7 @@ var mainRunCommand = new Command8().name("run").description("Run an agent").argu
8540
8627
  async (identifier, prompt, options) => {
8541
8628
  try {
8542
8629
  if (options.autoUpdate !== false) {
8543
- await startSilentUpgrade("9.36.0");
8630
+ await startSilentUpgrade("9.37.1");
8544
8631
  }
8545
8632
  const { scope, name, version } = parseIdentifier(identifier);
8546
8633
  if (scope && !options.experimentalSharedAgent) {
@@ -10116,7 +10203,7 @@ var cookAction = new Command27().name("cook").description("Quick start: prepare,
10116
10203
  ).option("-y, --yes", "Skip confirmation prompts").option("-v, --verbose", "Show full tool inputs and outputs").addOption(new Option5("--debug-no-mock-claude").hideHelp()).addOption(new Option5("--no-auto-update").hideHelp()).action(
10117
10204
  async (prompt, options) => {
10118
10205
  if (options.autoUpdate !== false) {
10119
- const shouldExit = await checkAndUpgrade("9.36.0", prompt);
10206
+ const shouldExit = await checkAndUpgrade("9.37.1", prompt);
10120
10207
  if (shouldExit) {
10121
10208
  process.exit(0);
10122
10209
  }
@@ -14701,12 +14788,12 @@ function isValidTimezone(timezone) {
14701
14788
  return false;
14702
14789
  }
14703
14790
  }
14704
- function parseNotifyEmail(value) {
14791
+ function parseOnOff(flag, value) {
14705
14792
  const lower = value.toLowerCase();
14706
14793
  if (lower === "on" || lower === "true" || lower === "1") return true;
14707
14794
  if (lower === "off" || lower === "false" || lower === "0") return false;
14708
14795
  throw new Error(
14709
- `Invalid value for --notify-email: "${value}". Use "on" or "off".`
14796
+ `Invalid value for --${flag}: "${value}". Use "on" or "off".`
14710
14797
  );
14711
14798
  }
14712
14799
  function displayPreferences(prefs) {
@@ -14717,99 +14804,125 @@ function displayPreferences(prefs) {
14717
14804
  console.log(
14718
14805
  ` Email notify: ${prefs.notifyEmail ? chalk78.green("on") : chalk78.dim("off")}`
14719
14806
  );
14807
+ console.log(
14808
+ ` Slack notify: ${prefs.notifySlack ? chalk78.green("on") : chalk78.dim("off")}`
14809
+ );
14720
14810
  }
14721
- var preferenceCommand = new Command77().name("preference").description("View or update your preferences").option("--timezone <timezone>", "IANA timezone (e.g., America/New_York)").option("--notify-email <on|off>", "Enable or disable email notifications").action(
14722
- withErrorHandler(
14723
- async (opts) => {
14724
- const hasTimezone = opts.timezone !== void 0;
14725
- const hasNotifyEmail = opts.notifyEmail !== void 0;
14726
- if (hasTimezone || hasNotifyEmail) {
14727
- const updates = {};
14728
- if (hasTimezone) {
14729
- if (!isValidTimezone(opts.timezone)) {
14730
- console.error(chalk78.red(`Invalid timezone: ${opts.timezone}`));
14731
- console.error(
14732
- chalk78.dim(
14733
- " Use an IANA timezone identifier (e.g., America/New_York, Asia/Shanghai)"
14734
- )
14735
- );
14736
- process.exit(1);
14737
- }
14738
- updates.timezone = opts.timezone;
14739
- }
14740
- if (hasNotifyEmail) {
14741
- try {
14742
- updates.notifyEmail = parseNotifyEmail(opts.notifyEmail);
14743
- } catch (err) {
14744
- console.error(chalk78.red(err.message));
14745
- process.exit(1);
14746
- }
14747
- }
14748
- const result = await updateUserPreferences(updates);
14749
- if (updates.timezone !== void 0) {
14750
- console.log(
14751
- chalk78.green(
14752
- `Timezone set to ${chalk78.cyan(result.timezone ?? updates.timezone)}`
14753
- )
14754
- );
14755
- }
14756
- if (updates.notifyEmail !== void 0) {
14757
- console.log(
14758
- chalk78.green(
14759
- `Email notifications ${result.notifyEmail ? "enabled" : "disabled"}`
14760
- )
14761
- );
14762
- }
14763
- return;
14764
- }
14765
- const prefs = await getUserPreferences();
14766
- displayPreferences(prefs);
14767
- if (isInteractive()) {
14768
- if (!prefs.timezone) {
14769
- const detectedTz = detectTimezone2();
14770
- console.log(chalk78.dim(`
14811
+ function buildUpdates(opts) {
14812
+ const hasTimezone = opts.timezone !== void 0;
14813
+ const hasNotifyEmail = opts.notifyEmail !== void 0;
14814
+ const hasNotifySlack = opts.notifySlack !== void 0;
14815
+ if (!hasTimezone && !hasNotifyEmail && !hasNotifySlack) return null;
14816
+ const updates = {};
14817
+ if (hasTimezone) {
14818
+ if (!isValidTimezone(opts.timezone)) {
14819
+ console.error(chalk78.red(`Invalid timezone: ${opts.timezone}`));
14820
+ console.error(
14821
+ chalk78.dim(
14822
+ " Use an IANA timezone identifier (e.g., America/New_York, Asia/Shanghai)"
14823
+ )
14824
+ );
14825
+ process.exit(1);
14826
+ }
14827
+ updates.timezone = opts.timezone;
14828
+ }
14829
+ if (hasNotifyEmail) {
14830
+ try {
14831
+ updates.notifyEmail = parseOnOff("notify-email", opts.notifyEmail);
14832
+ } catch (err) {
14833
+ console.error(chalk78.red(err.message));
14834
+ process.exit(1);
14835
+ }
14836
+ }
14837
+ if (hasNotifySlack) {
14838
+ try {
14839
+ updates.notifySlack = parseOnOff("notify-slack", opts.notifySlack);
14840
+ } catch (err) {
14841
+ console.error(chalk78.red(err.message));
14842
+ process.exit(1);
14843
+ }
14844
+ }
14845
+ return updates;
14846
+ }
14847
+ function printUpdateResult(updates, result) {
14848
+ if (updates.timezone !== void 0) {
14849
+ console.log(
14850
+ chalk78.green(
14851
+ `Timezone set to ${chalk78.cyan(result.timezone ?? updates.timezone)}`
14852
+ )
14853
+ );
14854
+ }
14855
+ if (updates.notifyEmail !== void 0) {
14856
+ console.log(
14857
+ chalk78.green(
14858
+ `Email notifications ${result.notifyEmail ? "enabled" : "disabled"}`
14859
+ )
14860
+ );
14861
+ }
14862
+ if (updates.notifySlack !== void 0) {
14863
+ console.log(
14864
+ chalk78.green(
14865
+ `Slack notifications ${result.notifySlack ? "enabled" : "disabled"}`
14866
+ )
14867
+ );
14868
+ }
14869
+ }
14870
+ async function interactiveSetup(prefs) {
14871
+ if (!prefs.timezone) {
14872
+ const detectedTz = detectTimezone2();
14873
+ console.log(chalk78.dim(`
14771
14874
  System timezone detected: ${detectedTz}`));
14772
- const tz = await promptText(
14773
- "Set timezone? (enter timezone or leave empty to skip)",
14774
- detectedTz
14775
- );
14776
- if (tz?.trim()) {
14777
- if (!isValidTimezone(tz.trim())) {
14778
- console.error(chalk78.red(`Invalid timezone: ${tz.trim()}`));
14779
- process.exit(1);
14780
- }
14781
- await updateUserPreferences({ timezone: tz.trim() });
14782
- console.log(
14783
- chalk78.green(`Timezone set to ${chalk78.cyan(tz.trim())}`)
14784
- );
14785
- }
14786
- }
14787
- if (!prefs.notifyEmail) {
14788
- const enable = await promptConfirm(
14789
- "\nEnable email notifications for scheduled runs?",
14790
- false
14791
- );
14792
- if (enable) {
14793
- await updateUserPreferences({ notifyEmail: true });
14794
- console.log(chalk78.green("Email notifications enabled"));
14795
- }
14796
- }
14797
- } else if (!prefs.timezone) {
14798
- console.log();
14799
- console.log(
14800
- `To set timezone: ${chalk78.cyan("vm0 preference --timezone <timezone>")}`
14801
- );
14802
- console.log(
14803
- chalk78.dim("Example: vm0 preference --timezone America/New_York")
14804
- );
14875
+ const tz = await promptText(
14876
+ "Set timezone? (enter timezone or leave empty to skip)",
14877
+ detectedTz
14878
+ );
14879
+ if (tz?.trim()) {
14880
+ if (!isValidTimezone(tz.trim())) {
14881
+ console.error(chalk78.red(`Invalid timezone: ${tz.trim()}`));
14882
+ process.exit(1);
14805
14883
  }
14884
+ await updateUserPreferences({ timezone: tz.trim() });
14885
+ console.log(chalk78.green(`Timezone set to ${chalk78.cyan(tz.trim())}`));
14806
14886
  }
14807
- )
14887
+ }
14888
+ if (!prefs.notifyEmail) {
14889
+ const enable = await promptConfirm(
14890
+ "\nEnable email notifications for scheduled runs?",
14891
+ false
14892
+ );
14893
+ if (enable) {
14894
+ await updateUserPreferences({ notifyEmail: true });
14895
+ console.log(chalk78.green("Email notifications enabled"));
14896
+ }
14897
+ }
14898
+ }
14899
+ var preferenceCommand = new Command77().name("preference").description("View or update your preferences").option("--timezone <timezone>", "IANA timezone (e.g., America/New_York)").option("--notify-email <on|off>", "Enable or disable email notifications").option("--notify-slack <on|off>", "Enable or disable Slack notifications").action(
14900
+ withErrorHandler(async (opts) => {
14901
+ const updates = buildUpdates(opts);
14902
+ if (updates) {
14903
+ const result = await updateUserPreferences(updates);
14904
+ printUpdateResult(updates, result);
14905
+ return;
14906
+ }
14907
+ const prefs = await getUserPreferences();
14908
+ displayPreferences(prefs);
14909
+ if (isInteractive()) {
14910
+ await interactiveSetup(prefs);
14911
+ } else if (!prefs.timezone) {
14912
+ console.log();
14913
+ console.log(
14914
+ `To set timezone: ${chalk78.cyan("vm0 preference --timezone <timezone>")}`
14915
+ );
14916
+ console.log(
14917
+ chalk78.dim("Example: vm0 preference --timezone America/New_York")
14918
+ );
14919
+ }
14920
+ })
14808
14921
  );
14809
14922
 
14810
14923
  // src/index.ts
14811
14924
  var program = new Command78();
14812
- program.name("vm0").description("VM0 CLI - Build and run agents with natural language").version("9.36.0");
14925
+ program.name("vm0").description("VM0 CLI - Build and run agents with natural language").version("9.37.1");
14813
14926
  program.addCommand(authCommand);
14814
14927
  program.addCommand(infoCommand);
14815
14928
  program.addCommand(composeCommand);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vm0/cli",
3
- "version": "9.36.0",
3
+ "version": "9.37.1",
4
4
  "description": "CLI application",
5
5
  "repository": {
6
6
  "type": "git",