@vm0/cli 4.14.1 → 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 +261 -23
  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
  */
@@ -4119,7 +4169,7 @@ var $ZodBase64 = /* @__PURE__ */ $constructor("$ZodBase64", (inst, def) => {
4119
4169
  function isValidBase64URL(data) {
4120
4170
  if (!base64url.test(data))
4121
4171
  return false;
4122
- const base643 = data.replace(/[-_]/g, (c11) => c11 === "-" ? "+" : "/");
4172
+ const base643 = data.replace(/[-_]/g, (c12) => c12 === "-" ? "+" : "/");
4123
4173
  const padded = base643.padEnd(Math.ceil(base643.length / 4) * 4, "=");
4124
4174
  return isValidBase64(padded);
4125
4175
  }
@@ -13031,9 +13081,9 @@ var ZodDate = /* @__PURE__ */ $constructor("ZodDate", (inst, def) => {
13031
13081
  ZodType.init(inst, def);
13032
13082
  inst.min = (value, params) => inst.check(_gte(value, params));
13033
13083
  inst.max = (value, params) => inst.check(_lte(value, params));
13034
- const c11 = inst._zod.bag;
13035
- inst.minDate = c11.minimum ? new Date(c11.minimum) : null;
13036
- 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;
13037
13087
  });
13038
13088
  function date3(params) {
13039
13089
  return _date(ZodDate, params);
@@ -13905,7 +13955,8 @@ var runResultSchema = external_exports.object({
13905
13955
  checkpointId: external_exports.string(),
13906
13956
  agentSessionId: external_exports.string(),
13907
13957
  conversationId: external_exports.string(),
13908
- 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
13909
13960
  volumes: external_exports.record(external_exports.string(), external_exports.string()).optional()
13910
13961
  });
13911
13962
  var runStateSchema = external_exports.object({
@@ -14136,7 +14187,8 @@ var agentSessionSchema = external_exports.object({
14136
14187
  userId: external_exports.string(),
14137
14188
  agentComposeId: external_exports.string(),
14138
14189
  conversationId: external_exports.string().nullable(),
14139
- artifactName: external_exports.string(),
14190
+ artifactName: external_exports.string().nullable(),
14191
+ // nullable when session has no artifact
14140
14192
  vars: external_exports.record(external_exports.string(), external_exports.string()).nullable(),
14141
14193
  createdAt: external_exports.string(),
14142
14194
  updatedAt: external_exports.string()
@@ -14356,7 +14408,7 @@ var webhookCheckpointsContract = c6.router({
14356
14408
  cliAgentType: external_exports.string().min(1, "cliAgentType is required"),
14357
14409
  cliAgentSessionId: external_exports.string().min(1, "cliAgentSessionId is required"),
14358
14410
  cliAgentSessionHistory: external_exports.string().min(1, "cliAgentSessionHistory is required"),
14359
- artifactSnapshot: artifactSnapshotSchema,
14411
+ artifactSnapshot: artifactSnapshotSchema.optional(),
14360
14412
  volumeVersionsSnapshot: volumeVersionsSnapshotSchema.optional()
14361
14413
  }),
14362
14414
  responses: {
@@ -14364,7 +14416,7 @@ var webhookCheckpointsContract = c6.router({
14364
14416
  checkpointId: external_exports.string(),
14365
14417
  agentSessionId: external_exports.string(),
14366
14418
  conversationId: external_exports.string(),
14367
- artifact: artifactSnapshotSchema,
14419
+ artifact: artifactSnapshotSchema.optional(),
14368
14420
  volumes: external_exports.record(external_exports.string(), external_exports.string()).optional()
14369
14421
  }),
14370
14422
  400: apiErrorSchema,
@@ -14755,6 +14807,86 @@ var proxyErrorSchema = external_exports.object({
14755
14807
  })
14756
14808
  });
14757
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
+
14758
14890
  // src/commands/run.ts
14759
14891
  function collectKeyValue(value, previous) {
14760
14892
  const [key, ...valueParts] = value.split("=");
@@ -14943,15 +15075,6 @@ var runCmd = new Command2().name("run").description("Execute an agent").argument
14943
15075
  ).option("-v, --verbose", "Show verbose output with timing information").action(
14944
15076
  async (identifier, prompt, options) => {
14945
15077
  const startTimestamp = /* @__PURE__ */ new Date();
14946
- if (!options.artifactName) {
14947
- console.error(
14948
- chalk4.red("\u2717 Missing required option: --artifact-name <name>")
14949
- );
14950
- console.error(
14951
- chalk4.gray(" The artifact-name is required for new agent runs.")
14952
- );
14953
- process.exit(1);
14954
- }
14955
15078
  const verbose = options.verbose;
14956
15079
  try {
14957
15080
  const { name, version: version2 } = parseIdentifier(identifier);
@@ -16131,7 +16254,7 @@ async function generateEnvPlaceholders(missingVars, envFilePath) {
16131
16254
  }
16132
16255
  }
16133
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) => {
16134
- const shouldExit = await checkAndUpgrade("4.14.1", prompt);
16257
+ const shouldExit = await checkAndUpgrade("4.15.0", prompt);
16135
16258
  if (shouldExit) {
16136
16259
  process.exit(0);
16137
16260
  }
@@ -16766,11 +16889,125 @@ function handleError(error43, runId) {
16766
16889
  }
16767
16890
  }
16768
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
+
16769
17006
  // src/index.ts
16770
- var program = new Command19();
16771
- program.name("vm0").description("VM0 CLI - A modern build tool").version("4.14.1");
17007
+ var program = new Command22();
17008
+ program.name("vm0").description("VM0 CLI - A modern build tool").version("4.15.0");
16772
17009
  program.command("info").description("Display environment information").action(async () => {
16773
- console.log(chalk20.cyan("System Information:"));
17010
+ console.log(chalk22.cyan("System Information:"));
16774
17011
  console.log(`Node Version: ${process.version}`);
16775
17012
  console.log(`Platform: ${process.platform}`);
16776
17013
  console.log(`Architecture: ${process.arch}`);
@@ -16797,6 +17034,7 @@ program.addCommand(artifactCommand);
16797
17034
  program.addCommand(cookCommand);
16798
17035
  program.addCommand(imageCommand);
16799
17036
  program.addCommand(logsCommand);
17037
+ program.addCommand(scopeCommand);
16800
17038
  if (process.argv[1]?.endsWith("index.js") || process.argv[1]?.endsWith("index.ts") || process.argv[1]?.endsWith("vm0")) {
16801
17039
  program.parse();
16802
17040
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vm0/cli",
3
- "version": "4.14.1",
3
+ "version": "4.15.0",
4
4
  "description": "CLI application",
5
5
  "repository": {
6
6
  "type": "git",