@vm0/cli 4.14.0 → 4.15.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.
Files changed (2) hide show
  1. package/index.js +279 -28
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -6,8 +6,8 @@ var __export = (target, all) => {
6
6
  };
7
7
 
8
8
  // src/index.ts
9
- import { Command as Command19 } from "commander";
10
- import chalk20 from "chalk";
9
+ import { Command as Command22 } from "commander";
10
+ import chalk22 from "chalk";
11
11
 
12
12
  // src/lib/auth.ts
13
13
  import chalk from "chalk";
@@ -451,6 +451,56 @@ var ApiClient = class {
451
451
  }
452
452
  return await response.json();
453
453
  }
454
+ /**
455
+ * Get current user's scope
456
+ */
457
+ async getScope() {
458
+ const baseUrl = await this.getBaseUrl();
459
+ const headers = await this.getHeaders();
460
+ const response = await fetch(`${baseUrl}/api/scope`, {
461
+ method: "GET",
462
+ headers
463
+ });
464
+ if (!response.ok) {
465
+ const error43 = await response.json();
466
+ throw new Error(error43.error?.message || "Failed to get scope");
467
+ }
468
+ return await response.json();
469
+ }
470
+ /**
471
+ * Create user's scope
472
+ */
473
+ async createScope(body) {
474
+ const baseUrl = await this.getBaseUrl();
475
+ const headers = await this.getHeaders();
476
+ const response = await fetch(`${baseUrl}/api/scope`, {
477
+ method: "POST",
478
+ headers,
479
+ body: JSON.stringify(body)
480
+ });
481
+ if (!response.ok) {
482
+ const error43 = await response.json();
483
+ throw new Error(error43.error?.message || "Failed to create scope");
484
+ }
485
+ return await response.json();
486
+ }
487
+ /**
488
+ * Update user's scope slug
489
+ */
490
+ async updateScope(body) {
491
+ const baseUrl = await this.getBaseUrl();
492
+ const headers = await this.getHeaders();
493
+ const response = await fetch(`${baseUrl}/api/scope`, {
494
+ method: "PUT",
495
+ headers,
496
+ body: JSON.stringify(body)
497
+ });
498
+ if (!response.ok) {
499
+ const error43 = await response.json();
500
+ throw new Error(error43.error?.message || "Failed to update scope");
501
+ }
502
+ return await response.json();
503
+ }
454
504
  /**
455
505
  * Generic GET request
456
506
  */
@@ -1011,7 +1061,6 @@ async function directUpload(storageName, storageType, cwd, options) {
1011
1061
  const files = await getAllFiles(cwd);
1012
1062
  onProgress?.("Computing file hashes...");
1013
1063
  const fileEntries = await collectFileMetadata(cwd, files, onProgress);
1014
- const totalSize = fileEntries.reduce((sum, f) => sum + f.size, 0);
1015
1064
  onProgress?.("Preparing upload...");
1016
1065
  const prepareResponse = await apiClient.post("/api/storages/prepare", {
1017
1066
  body: JSON.stringify({
@@ -1027,12 +1076,26 @@ async function directUpload(storageName, storageType, cwd, options) {
1027
1076
  }
1028
1077
  const prepareResult = await prepareResponse.json();
1029
1078
  if (prepareResult.existing) {
1079
+ onProgress?.("Version exists, updating HEAD...");
1080
+ const commitResponse2 = await apiClient.post("/api/storages/commit", {
1081
+ body: JSON.stringify({
1082
+ storageName,
1083
+ storageType,
1084
+ versionId: prepareResult.versionId,
1085
+ files: fileEntries
1086
+ })
1087
+ });
1088
+ if (!commitResponse2.ok) {
1089
+ const error43 = await commitResponse2.json();
1090
+ throw new Error(error43.error?.message || "Commit failed");
1091
+ }
1092
+ const commitResult2 = await commitResponse2.json();
1030
1093
  return {
1031
- versionId: prepareResult.versionId,
1032
- size: totalSize,
1033
- fileCount: fileEntries.length,
1094
+ versionId: commitResult2.versionId,
1095
+ size: commitResult2.size,
1096
+ fileCount: commitResult2.fileCount,
1034
1097
  deduplicated: true,
1035
- empty: fileEntries.length === 0
1098
+ empty: commitResult2.fileCount === 0
1036
1099
  };
1037
1100
  }
1038
1101
  if (files.length > 0) {
@@ -4106,7 +4169,7 @@ var $ZodBase64 = /* @__PURE__ */ $constructor("$ZodBase64", (inst, def) => {
4106
4169
  function isValidBase64URL(data) {
4107
4170
  if (!base64url.test(data))
4108
4171
  return false;
4109
- const base643 = data.replace(/[-_]/g, (c11) => c11 === "-" ? "+" : "/");
4172
+ const base643 = data.replace(/[-_]/g, (c12) => c12 === "-" ? "+" : "/");
4110
4173
  const padded = base643.padEnd(Math.ceil(base643.length / 4) * 4, "=");
4111
4174
  return isValidBase64(padded);
4112
4175
  }
@@ -13018,9 +13081,9 @@ var ZodDate = /* @__PURE__ */ $constructor("ZodDate", (inst, def) => {
13018
13081
  ZodType.init(inst, def);
13019
13082
  inst.min = (value, params) => inst.check(_gte(value, params));
13020
13083
  inst.max = (value, params) => inst.check(_lte(value, params));
13021
- const c11 = inst._zod.bag;
13022
- inst.minDate = c11.minimum ? new Date(c11.minimum) : null;
13023
- inst.maxDate = c11.maximum ? new Date(c11.maximum) : null;
13084
+ const c12 = inst._zod.bag;
13085
+ inst.minDate = c12.minimum ? new Date(c12.minimum) : null;
13086
+ inst.maxDate = c12.maximum ? new Date(c12.maximum) : null;
13024
13087
  });
13025
13088
  function date3(params) {
13026
13089
  return _date(ZodDate, params);
@@ -13892,7 +13955,8 @@ var runResultSchema = external_exports.object({
13892
13955
  checkpointId: external_exports.string(),
13893
13956
  agentSessionId: external_exports.string(),
13894
13957
  conversationId: external_exports.string(),
13895
- artifact: external_exports.record(external_exports.string(), external_exports.string()),
13958
+ artifact: external_exports.record(external_exports.string(), external_exports.string()).optional(),
13959
+ // optional when run has no artifact
13896
13960
  volumes: external_exports.record(external_exports.string(), external_exports.string()).optional()
13897
13961
  });
13898
13962
  var runStateSchema = external_exports.object({
@@ -14123,7 +14187,8 @@ var agentSessionSchema = external_exports.object({
14123
14187
  userId: external_exports.string(),
14124
14188
  agentComposeId: external_exports.string(),
14125
14189
  conversationId: external_exports.string().nullable(),
14126
- artifactName: external_exports.string(),
14190
+ artifactName: external_exports.string().nullable(),
14191
+ // nullable when session has no artifact
14127
14192
  vars: external_exports.record(external_exports.string(), external_exports.string()).nullable(),
14128
14193
  createdAt: external_exports.string(),
14129
14194
  updatedAt: external_exports.string()
@@ -14343,7 +14408,7 @@ var webhookCheckpointsContract = c6.router({
14343
14408
  cliAgentType: external_exports.string().min(1, "cliAgentType is required"),
14344
14409
  cliAgentSessionId: external_exports.string().min(1, "cliAgentSessionId is required"),
14345
14410
  cliAgentSessionHistory: external_exports.string().min(1, "cliAgentSessionHistory is required"),
14346
- artifactSnapshot: artifactSnapshotSchema,
14411
+ artifactSnapshot: artifactSnapshotSchema.optional(),
14347
14412
  volumeVersionsSnapshot: volumeVersionsSnapshotSchema.optional()
14348
14413
  }),
14349
14414
  responses: {
@@ -14351,7 +14416,7 @@ var webhookCheckpointsContract = c6.router({
14351
14416
  checkpointId: external_exports.string(),
14352
14417
  agentSessionId: external_exports.string(),
14353
14418
  conversationId: external_exports.string(),
14354
- artifact: artifactSnapshotSchema,
14419
+ artifact: artifactSnapshotSchema.optional(),
14355
14420
  volumes: external_exports.record(external_exports.string(), external_exports.string()).optional()
14356
14421
  }),
14357
14422
  400: apiErrorSchema,
@@ -14742,6 +14807,86 @@ var proxyErrorSchema = external_exports.object({
14742
14807
  })
14743
14808
  });
14744
14809
 
14810
+ // ../../packages/core/src/contracts/scopes.ts
14811
+ var c11 = initContract();
14812
+ var scopeTypeSchema = external_exports.enum(["personal", "organization", "system"]);
14813
+ var scopeSlugSchema = external_exports.string().min(3, "Scope slug must be at least 3 characters").max(64, "Scope slug must be at most 64 characters").regex(
14814
+ /^[a-z0-9][a-z0-9-]*[a-z0-9]$|^[a-z0-9]{1,2}$/,
14815
+ "Scope slug must contain only lowercase letters, numbers, and hyphens, and must start and end with an alphanumeric character"
14816
+ ).refine(
14817
+ (slug) => !slug.startsWith("vm0"),
14818
+ "Scope slug cannot start with 'vm0' (reserved)"
14819
+ ).transform((s) => s.toLowerCase());
14820
+ var scopeResponseSchema = external_exports.object({
14821
+ id: external_exports.string().uuid(),
14822
+ slug: external_exports.string(),
14823
+ type: scopeTypeSchema,
14824
+ displayName: external_exports.string().nullable(),
14825
+ createdAt: external_exports.string(),
14826
+ updatedAt: external_exports.string()
14827
+ });
14828
+ var createScopeRequestSchema = external_exports.object({
14829
+ slug: scopeSlugSchema,
14830
+ displayName: external_exports.string().max(128).optional()
14831
+ });
14832
+ var updateScopeRequestSchema = external_exports.object({
14833
+ slug: scopeSlugSchema,
14834
+ force: external_exports.boolean().optional().default(false)
14835
+ });
14836
+ var scopeContract = c11.router({
14837
+ /**
14838
+ * GET /api/scope
14839
+ * Get current user's scope
14840
+ */
14841
+ get: {
14842
+ method: "GET",
14843
+ path: "/api/scope",
14844
+ responses: {
14845
+ 200: scopeResponseSchema,
14846
+ 401: apiErrorSchema,
14847
+ 404: apiErrorSchema,
14848
+ 500: apiErrorSchema
14849
+ },
14850
+ summary: "Get current user's scope"
14851
+ },
14852
+ /**
14853
+ * POST /api/scope
14854
+ * Create user's scope
14855
+ */
14856
+ create: {
14857
+ method: "POST",
14858
+ path: "/api/scope",
14859
+ body: createScopeRequestSchema,
14860
+ responses: {
14861
+ 201: scopeResponseSchema,
14862
+ 400: apiErrorSchema,
14863
+ 401: apiErrorSchema,
14864
+ 409: apiErrorSchema,
14865
+ 500: apiErrorSchema
14866
+ },
14867
+ summary: "Create user's scope"
14868
+ },
14869
+ /**
14870
+ * PUT /api/scope
14871
+ * Update user's scope slug
14872
+ */
14873
+ update: {
14874
+ method: "PUT",
14875
+ path: "/api/scope",
14876
+ body: updateScopeRequestSchema,
14877
+ responses: {
14878
+ 200: scopeResponseSchema,
14879
+ 400: apiErrorSchema,
14880
+ 401: apiErrorSchema,
14881
+ 403: apiErrorSchema,
14882
+ 404: apiErrorSchema,
14883
+ 409: apiErrorSchema,
14884
+ 500: apiErrorSchema
14885
+ },
14886
+ summary: "Update user's scope slug"
14887
+ }
14888
+ });
14889
+
14745
14890
  // src/commands/run.ts
14746
14891
  function collectKeyValue(value, previous) {
14747
14892
  const [key, ...valueParts] = value.split("=");
@@ -14930,15 +15075,6 @@ var runCmd = new Command2().name("run").description("Execute an agent").argument
14930
15075
  ).option("-v, --verbose", "Show verbose output with timing information").action(
14931
15076
  async (identifier, prompt, options) => {
14932
15077
  const startTimestamp = /* @__PURE__ */ new Date();
14933
- if (!options.artifactName) {
14934
- console.error(
14935
- chalk4.red("\u2717 Missing required option: --artifact-name <name>")
14936
- );
14937
- console.error(
14938
- chalk4.gray(" The artifact-name is required for new agent runs.")
14939
- );
14940
- process.exit(1);
14941
- }
14942
15078
  const verbose = options.verbose;
14943
15079
  try {
14944
15080
  const { name, version: version2 } = parseIdentifier(identifier);
@@ -16118,7 +16254,7 @@ async function generateEnvPlaceholders(missingVars, envFilePath) {
16118
16254
  }
16119
16255
  }
16120
16256
  var cookCommand = new Command13().name("cook").description("One-click agent preparation and execution from vm0.yaml").argument("[prompt]", "Prompt for the agent").action(async (prompt) => {
16121
- const shouldExit = await checkAndUpgrade("4.14.0", prompt);
16257
+ const shouldExit = await checkAndUpgrade("4.15.0", prompt);
16122
16258
  if (shouldExit) {
16123
16259
  process.exit(0);
16124
16260
  }
@@ -16753,11 +16889,125 @@ function handleError(error43, runId) {
16753
16889
  }
16754
16890
  }
16755
16891
 
16892
+ // src/commands/scope/index.ts
16893
+ import { Command as Command21 } from "commander";
16894
+
16895
+ // src/commands/scope/status.ts
16896
+ import { Command as Command19 } from "commander";
16897
+ import chalk20 from "chalk";
16898
+ var statusCommand3 = new Command19().name("status").description("View current scope status").action(async () => {
16899
+ try {
16900
+ const scope = await apiClient.getScope();
16901
+ console.log(chalk20.cyan("Scope Information:"));
16902
+ console.log(` Slug: ${chalk20.green("@" + scope.slug)}`);
16903
+ console.log(` Type: ${scope.type}`);
16904
+ if (scope.displayName) {
16905
+ console.log(` Display Name: ${scope.displayName}`);
16906
+ }
16907
+ console.log(
16908
+ ` Created: ${new Date(scope.createdAt).toLocaleDateString()}`
16909
+ );
16910
+ } catch (error43) {
16911
+ if (error43 instanceof Error) {
16912
+ if (error43.message.includes("Not authenticated")) {
16913
+ console.error(chalk20.red("\u2717 Not authenticated. Run: vm0 auth login"));
16914
+ } else if (error43.message.includes("No scope configured")) {
16915
+ console.log(chalk20.yellow("No scope configured."));
16916
+ console.log();
16917
+ console.log("Set your scope with:");
16918
+ console.log(chalk20.cyan(" vm0 scope set <slug>"));
16919
+ console.log();
16920
+ console.log("Example:");
16921
+ console.log(chalk20.gray(" vm0 scope set myusername"));
16922
+ } else {
16923
+ console.error(chalk20.red(`\u2717 ${error43.message}`));
16924
+ }
16925
+ } else {
16926
+ console.error(chalk20.red("\u2717 An unexpected error occurred"));
16927
+ }
16928
+ process.exit(1);
16929
+ }
16930
+ });
16931
+
16932
+ // src/commands/scope/set.ts
16933
+ import { Command as Command20 } from "commander";
16934
+ import chalk21 from "chalk";
16935
+ var setCommand = new Command20().name("set").description("Set your scope slug").argument("<slug>", "The scope slug (e.g., your username)").option("--force", "Force change existing scope (may break references)").option("--display-name <name>", "Display name for the scope").action(
16936
+ async (slug, options) => {
16937
+ try {
16938
+ let existingScope;
16939
+ try {
16940
+ existingScope = await apiClient.getScope();
16941
+ } catch {
16942
+ }
16943
+ let scope;
16944
+ if (existingScope) {
16945
+ if (!options.force) {
16946
+ console.error(
16947
+ chalk21.yellow(`You already have a scope: @${existingScope.slug}`)
16948
+ );
16949
+ console.error();
16950
+ console.error("To change your scope, use --force:");
16951
+ console.error(chalk21.cyan(` vm0 scope set ${slug} --force`));
16952
+ console.error();
16953
+ console.error(
16954
+ chalk21.yellow(
16955
+ "Warning: Changing your scope may break existing image references."
16956
+ )
16957
+ );
16958
+ process.exit(1);
16959
+ }
16960
+ scope = await apiClient.updateScope({ slug, force: true });
16961
+ console.log(chalk21.green(`\u2713 Scope updated to @${scope.slug}`));
16962
+ } else {
16963
+ scope = await apiClient.createScope({
16964
+ slug,
16965
+ displayName: options.displayName
16966
+ });
16967
+ console.log(chalk21.green(`\u2713 Scope created: @${scope.slug}`));
16968
+ }
16969
+ console.log();
16970
+ console.log("Your images will now be namespaced as:");
16971
+ console.log(chalk21.cyan(` @${scope.slug}/<image-name>`));
16972
+ } catch (error43) {
16973
+ if (error43 instanceof Error) {
16974
+ if (error43.message.includes("Not authenticated")) {
16975
+ console.error(
16976
+ chalk21.red("\u2717 Not authenticated. Run: vm0 auth login")
16977
+ );
16978
+ } else if (error43.message.includes("already exists")) {
16979
+ console.error(
16980
+ chalk21.red(
16981
+ `\u2717 Scope "${slug}" is already taken. Please choose a different slug.`
16982
+ )
16983
+ );
16984
+ } else if (error43.message.includes("reserved")) {
16985
+ console.error(chalk21.red(`\u2717 ${error43.message}`));
16986
+ } else if (error43.message.includes("vm0")) {
16987
+ console.error(
16988
+ chalk21.red(
16989
+ "\u2717 Scope slugs cannot start with 'vm0' (reserved for system use)"
16990
+ )
16991
+ );
16992
+ } else {
16993
+ console.error(chalk21.red(`\u2717 ${error43.message}`));
16994
+ }
16995
+ } else {
16996
+ console.error(chalk21.red("\u2717 An unexpected error occurred"));
16997
+ }
16998
+ process.exit(1);
16999
+ }
17000
+ }
17001
+ );
17002
+
17003
+ // src/commands/scope/index.ts
17004
+ var scopeCommand = new Command21().name("scope").description("Manage your scope (namespace for images)").addCommand(statusCommand3).addCommand(setCommand);
17005
+
16756
17006
  // src/index.ts
16757
- var program = new Command19();
16758
- program.name("vm0").description("VM0 CLI - A modern build tool").version("4.14.0");
17007
+ var program = new Command22();
17008
+ program.name("vm0").description("VM0 CLI - A modern build tool").version("4.15.0");
16759
17009
  program.command("info").description("Display environment information").action(async () => {
16760
- console.log(chalk20.cyan("System Information:"));
17010
+ console.log(chalk22.cyan("System Information:"));
16761
17011
  console.log(`Node Version: ${process.version}`);
16762
17012
  console.log(`Platform: ${process.platform}`);
16763
17013
  console.log(`Architecture: ${process.arch}`);
@@ -16784,6 +17034,7 @@ program.addCommand(artifactCommand);
16784
17034
  program.addCommand(cookCommand);
16785
17035
  program.addCommand(imageCommand);
16786
17036
  program.addCommand(logsCommand);
17037
+ program.addCommand(scopeCommand);
16787
17038
  if (process.argv[1]?.endsWith("index.js") || process.argv[1]?.endsWith("index.ts") || process.argv[1]?.endsWith("vm0")) {
16788
17039
  program.parse();
16789
17040
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vm0/cli",
3
- "version": "4.14.0",
3
+ "version": "4.15.0",
4
4
  "description": "CLI application",
5
5
  "repository": {
6
6
  "type": "git",