@vm0/cli 9.208.1 → 9.209.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
@@ -74,7 +74,7 @@ import {
74
74
  uo,
75
75
  volumeConfigSchema,
76
76
  withErrorHandler
77
- } from "./chunk-HJC27CUJ.js";
77
+ } from "./chunk-QXLY7TX2.js";
78
78
  import {
79
79
  external_exports
80
80
  } from "./chunk-NUMM3WMG.js";
@@ -411,7 +411,7 @@ function getConfigPath() {
411
411
  return join(os.homedir(), ".vm0", "config.json");
412
412
  }
413
413
  var infoCommand = new Command().name("info").description("Display environment and debug information").action(async () => {
414
- console.log(source_default.bold(`VM0 CLI v${"9.208.1"}`));
414
+ console.log(source_default.bold(`VM0 CLI v${"9.209.0"}`));
415
415
  console.log();
416
416
  const config = await loadConfig();
417
417
  const hasEnvToken = !!process.env.VM0_TOKEN;
@@ -1113,7 +1113,7 @@ var composeCommand = new Command().name("compose").description("Create or update
1113
1113
  options.autoUpdate = false;
1114
1114
  }
1115
1115
  if (options.autoUpdate !== false) {
1116
- await startSilentUpgrade("9.208.1");
1116
+ await startSilentUpgrade("9.209.0");
1117
1117
  }
1118
1118
  try {
1119
1119
  const { config, agentName, agent, basePath } = await loadAndValidateConfig(resolvedConfigFile);
@@ -1210,7 +1210,7 @@ var mainRunCommand = new Command().name("run").description("Run an agent").argum
1210
1210
  withErrorHandler(
1211
1211
  async (identifier, prompt, options) => {
1212
1212
  if (options.autoUpdate !== false) {
1213
- await startSilentUpgrade("9.208.1");
1213
+ await startSilentUpgrade("9.209.0");
1214
1214
  }
1215
1215
  const { name, version } = parseIdentifier(identifier);
1216
1216
  let composeId;
@@ -3016,13 +3016,13 @@ var upgradeCommand = new Command().name("upgrade").description("Upgrade vm0 CLI
3016
3016
  if (latestVersion === null) {
3017
3017
  throw new Error("Could not check for updates. Please try again later.");
3018
3018
  }
3019
- if (latestVersion === "9.208.1") {
3020
- console.log(source_default.green(`\u2713 Already up to date (${"9.208.1"})`));
3019
+ if (latestVersion === "9.209.0") {
3020
+ console.log(source_default.green(`\u2713 Already up to date (${"9.209.0"})`));
3021
3021
  return;
3022
3022
  }
3023
3023
  console.log(
3024
3024
  source_default.yellow(
3025
- `Current version: ${"9.208.1"} -> Latest version: ${latestVersion}`
3025
+ `Current version: ${"9.209.0"} -> Latest version: ${latestVersion}`
3026
3026
  )
3027
3027
  );
3028
3028
  console.log();
@@ -3049,7 +3049,7 @@ var upgradeCommand = new Command().name("upgrade").description("Upgrade vm0 CLI
3049
3049
  const success = await performUpgrade(packageManager);
3050
3050
  if (success) {
3051
3051
  console.log(
3052
- source_default.green(`\u2713 Upgraded from ${"9.208.1"} to ${latestVersion}`)
3052
+ source_default.green(`\u2713 Upgraded from ${"9.209.0"} to ${latestVersion}`)
3053
3053
  );
3054
3054
  return;
3055
3055
  }
@@ -3116,7 +3116,7 @@ var whoamiCommand = new Command().name("whoami").description("Show current ident
3116
3116
 
3117
3117
  // src/index.ts
3118
3118
  var program = new Command();
3119
- program.name("vm0").description("VM0 CLI - Build and run agents with natural language").version("9.208.1");
3119
+ program.name("vm0").description("VM0 CLI - Build and run agents with natural language").version("9.209.0");
3120
3120
  program.addCommand(authCommand);
3121
3121
  program.addCommand(infoCommand);
3122
3122
  program.addCommand(composeCommand);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vm0/cli",
3
- "version": "9.208.1",
3
+ "version": "9.209.0",
4
4
  "description": "CLI application",
5
5
  "repository": {
6
6
  "type": "git",
package/zero.js CHANGED
@@ -178,7 +178,7 @@ import {
178
178
  uploadWebFile,
179
179
  upsertZeroOrgModelProvider,
180
180
  withErrorHandler
181
- } from "./chunk-HJC27CUJ.js";
181
+ } from "./chunk-QXLY7TX2.js";
182
182
  import {
183
183
  CONNECTOR_TYPES,
184
184
  CONNECTOR_TYPE_KEYS,
@@ -14962,9 +14962,13 @@ Notes:
14962
14962
 
14963
14963
  // src/commands/zero/maps/index.ts
14964
14964
  init_esm_shims();
14965
+ import { mkdir as mkdir3, writeFile as writeFile3 } from "fs/promises";
14966
+ import { dirname as dirname3 } from "path";
14965
14967
  var TRAVEL_MODES = ["driving", "walking", "bicycling", "transit"];
14966
14968
  var PLACE_SEARCH_FIELDSETS = ["pro", "enterprise"];
14967
14969
  var PLACE_DETAIL_FIELDSETS = ["essentials", "pro", "enterprise"];
14970
+ var OSM_LAYERS = ["roads", "buildings", "water", "parks"];
14971
+ var OSM_STYLES = ["standard", "guide"];
14968
14972
  function parseLatitude(value) {
14969
14973
  const latitude = Number(value);
14970
14974
  if (!Number.isFinite(latitude) || latitude < -90 || latitude > 90) {
@@ -14995,6 +14999,15 @@ function parseLimit4(value) {
14995
14999
  }
14996
15000
  return limit;
14997
15001
  }
15002
+ function parseIntegerInRange(value, min, max) {
15003
+ const parsed = Number(value);
15004
+ if (!Number.isInteger(parsed) || parsed < min || parsed > max) {
15005
+ throw new InvalidArgumentError(
15006
+ `value must be an integer from ${min} to ${max}`
15007
+ );
15008
+ }
15009
+ return parsed;
15010
+ }
14998
15011
  function parseTravelMode(value) {
14999
15012
  if (TRAVEL_MODES.includes(value)) {
15000
15013
  return value;
@@ -15019,8 +15032,142 @@ function parsePlaceDetailFields(value) {
15019
15032
  `fields must be one of: ${PLACE_DETAIL_FIELDSETS.join(", ")}`
15020
15033
  );
15021
15034
  }
15022
- function renderMapsResponse(label, response) {
15023
- console.log(source_default.green(`\u2713 ${label}`));
15035
+ function parseBBox(value) {
15036
+ const parts = value.split(",").map((part) => {
15037
+ return part.trim();
15038
+ });
15039
+ if (parts.length !== 4) {
15040
+ throw new InvalidArgumentError("bbox must be west,south,east,north");
15041
+ }
15042
+ const [westRaw, southRaw, eastRaw, northRaw] = parts;
15043
+ if (!westRaw || !southRaw || !eastRaw || !northRaw) {
15044
+ throw new InvalidArgumentError("bbox must be west,south,east,north");
15045
+ }
15046
+ const bbox = {
15047
+ west: parseLongitude(westRaw),
15048
+ south: parseLatitude(southRaw),
15049
+ east: parseLongitude(eastRaw),
15050
+ north: parseLatitude(northRaw)
15051
+ };
15052
+ if (bbox.east <= bbox.west || bbox.north <= bbox.south) {
15053
+ throw new InvalidArgumentError(
15054
+ "bbox east/north must be greater than west/south"
15055
+ );
15056
+ }
15057
+ return bbox;
15058
+ }
15059
+ function parseLatLng(value) {
15060
+ const parts = value.split(",").map((part) => {
15061
+ return part.trim();
15062
+ });
15063
+ if (parts.length !== 2 || !parts[0] || !parts[1]) {
15064
+ throw new InvalidArgumentError("coordinates must be lat,lng");
15065
+ }
15066
+ return {
15067
+ lat: parseLatitude(parts[0]),
15068
+ lng: parseLongitude(parts[1])
15069
+ };
15070
+ }
15071
+ function parseOsmLayers(value) {
15072
+ const layers = [
15073
+ ...new Set(
15074
+ value.split(",").map((layer) => {
15075
+ return layer.trim();
15076
+ }).filter(Boolean)
15077
+ )
15078
+ ];
15079
+ if (layers.length === 0) {
15080
+ throw new InvalidArgumentError("layers must include at least one value");
15081
+ }
15082
+ const invalid = layers.find((layer) => {
15083
+ return !OSM_LAYERS.includes(layer);
15084
+ });
15085
+ if (invalid) {
15086
+ throw new InvalidArgumentError(
15087
+ `layers must be drawn from: ${OSM_LAYERS.join(", ")}`
15088
+ );
15089
+ }
15090
+ return layers;
15091
+ }
15092
+ function parseOsmStyle(value) {
15093
+ if (OSM_STYLES.includes(value)) {
15094
+ return value;
15095
+ }
15096
+ throw new InvalidArgumentError(
15097
+ `style must be one of: ${OSM_STYLES.join(", ")}`
15098
+ );
15099
+ }
15100
+ function parseOsmMarker(value) {
15101
+ const [latRaw, lngRaw, ...labelParts] = value.split(",");
15102
+ if (!latRaw?.trim() || !lngRaw?.trim()) {
15103
+ throw new InvalidArgumentError("marker must be lat,lng or lat,lng,label");
15104
+ }
15105
+ const label = labelParts.join(",").trim();
15106
+ return {
15107
+ lat: parseLatitude(latRaw.trim()),
15108
+ lng: parseLongitude(lngRaw.trim()),
15109
+ ...label ? { label } : {}
15110
+ };
15111
+ }
15112
+ function collectOsmMarker(value, previous) {
15113
+ return [...previous, parseOsmMarker(value)];
15114
+ }
15115
+ function osmAreaPayload(options) {
15116
+ const hasBbox = options.bbox !== void 0;
15117
+ const hasCenterRadius = options.center !== void 0 && options.radius !== void 0;
15118
+ if (hasBbox === hasCenterRadius) {
15119
+ throw new Error("Provide either --bbox or --center with --radius");
15120
+ }
15121
+ return {
15122
+ ...options.bbox ? { bbox: options.bbox } : {},
15123
+ ...options.center ? { center: options.center } : {},
15124
+ ...options.radius !== void 0 ? { radiusMeters: options.radius } : {},
15125
+ layers: options.layers
15126
+ };
15127
+ }
15128
+ function isRecord3(value) {
15129
+ return typeof value === "object" && value !== null && !Array.isArray(value);
15130
+ }
15131
+ function resultRecord(response) {
15132
+ if (!isRecord3(response.result)) {
15133
+ throw new Error("Zero Maps response did not include an object result");
15134
+ }
15135
+ return response.result;
15136
+ }
15137
+ function stringField2(value, key) {
15138
+ const field = value[key];
15139
+ return typeof field === "string" ? field : void 0;
15140
+ }
15141
+ function numberField(value, key) {
15142
+ const field = value[key];
15143
+ return typeof field === "number" ? field : void 0;
15144
+ }
15145
+ async function writeOutputFile(outputPath, content) {
15146
+ await mkdir3(dirname3(outputPath), { recursive: true });
15147
+ await writeFile3(outputPath, content);
15148
+ }
15149
+ async function writeOsmGeoJson(outputPath, response) {
15150
+ const result = resultRecord(response);
15151
+ if (!("geojson" in result)) {
15152
+ throw new Error("Zero Maps OSM download response did not include geojson");
15153
+ }
15154
+ await writeOutputFile(
15155
+ outputPath,
15156
+ `${JSON.stringify(result.geojson, null, 2)}
15157
+ `
15158
+ );
15159
+ }
15160
+ async function writeOsmPng(outputPath, response) {
15161
+ const result = resultRecord(response);
15162
+ const image = result.image;
15163
+ if (!isRecord3(image) || typeof image.base64 !== "string") {
15164
+ throw new Error(
15165
+ "Zero Maps OSM render response did not include a PNG image"
15166
+ );
15167
+ }
15168
+ await writeOutputFile(outputPath, Buffer.from(image.base64, "base64"));
15169
+ }
15170
+ function renderMapsMetadata(response) {
15024
15171
  if (response.provider) {
15025
15172
  console.log(source_default.dim(` Provider: ${response.provider}`));
15026
15173
  }
@@ -15033,9 +15180,27 @@ function renderMapsResponse(label, response) {
15033
15180
  if (response.creditsCharged !== void 0) {
15034
15181
  console.log(source_default.dim(` Credits charged: ${response.creditsCharged}`));
15035
15182
  }
15183
+ }
15184
+ function renderMapsResponse(label, response) {
15185
+ console.log(source_default.green(`\u2713 ${label}`));
15186
+ renderMapsMetadata(response);
15036
15187
  const result = response.result ?? response;
15037
15188
  console.log(JSON.stringify(result, null, 2));
15038
15189
  }
15190
+ function renderOsmFileResponse(label, response, outputPath) {
15191
+ console.log(source_default.green(`\u2713 ${label}`));
15192
+ renderMapsMetadata(response);
15193
+ const result = isRecord3(response.result) ? response.result : {};
15194
+ const featureCount = numberField(result, "featureCount");
15195
+ const attribution = stringField2(result, "attribution");
15196
+ if (featureCount !== void 0) {
15197
+ console.log(source_default.dim(` Features: ${featureCount}`));
15198
+ }
15199
+ if (attribution) {
15200
+ console.log(source_default.dim(` Attribution: ${attribution}`));
15201
+ }
15202
+ console.log(source_default.dim(` Output: ${outputPath}`));
15203
+ }
15039
15204
  async function runMapsRequest(label, endpoint, payload, options) {
15040
15205
  const response = await callZeroMaps(endpoint, payload);
15041
15206
  if (options.json) {
@@ -15136,8 +15301,109 @@ var placesDetailsCommand = new Command().name("details").description("Get detail
15136
15301
  );
15137
15302
  })
15138
15303
  );
15304
+ var osmDownloadCommand = new Command().name("download").description("Download OpenStreetMap vector features as GeoJSON").option(
15305
+ "--bbox <west,south,east,north>",
15306
+ "Bounding box in WGS84 coordinates",
15307
+ parseBBox
15308
+ ).option(
15309
+ "--center <lat,lng>",
15310
+ "Center point in WGS84 coordinates",
15311
+ parseLatLng
15312
+ ).option(
15313
+ "--radius <meters>",
15314
+ "Radius in meters when using --center",
15315
+ parsePositiveInteger3
15316
+ ).option(
15317
+ "--layers <layers>",
15318
+ "Comma-separated layers: roads, buildings, water, parks",
15319
+ parseOsmLayers,
15320
+ OSM_LAYERS
15321
+ ).option("--output <path>", "Write GeoJSON to a file").option("--json", "Print the raw maps response as JSON").action(
15322
+ withErrorHandler(async (options) => {
15323
+ const response = await callZeroMaps(
15324
+ "osm/download",
15325
+ osmAreaPayload(options)
15326
+ );
15327
+ if (options.output) {
15328
+ await writeOsmGeoJson(options.output, response);
15329
+ }
15330
+ if (options.json) {
15331
+ console.log(JSON.stringify(response));
15332
+ return;
15333
+ }
15334
+ if (options.output) {
15335
+ renderOsmFileResponse(
15336
+ "OSM download completed",
15337
+ response,
15338
+ options.output
15339
+ );
15340
+ return;
15341
+ }
15342
+ renderMapsResponse("OSM download completed", response);
15343
+ })
15344
+ );
15345
+ var osmRenderCommand = new Command().name("render").description("Render OpenStreetMap vector features to PNG").option(
15346
+ "--bbox <west,south,east,north>",
15347
+ "Bounding box in WGS84 coordinates",
15348
+ parseBBox
15349
+ ).option(
15350
+ "--center <lat,lng>",
15351
+ "Center point in WGS84 coordinates",
15352
+ parseLatLng
15353
+ ).option(
15354
+ "--radius <meters>",
15355
+ "Radius in meters when using --center",
15356
+ parsePositiveInteger3
15357
+ ).option(
15358
+ "--layers <layers>",
15359
+ "Comma-separated layers: roads, buildings, water, parks",
15360
+ parseOsmLayers,
15361
+ OSM_LAYERS
15362
+ ).option(
15363
+ "--width <px>",
15364
+ "PNG width in pixels, from 320 to 2048",
15365
+ (value) => {
15366
+ return parseIntegerInRange(value, 320, 2048);
15367
+ },
15368
+ 1536
15369
+ ).option(
15370
+ "--height <px>",
15371
+ "PNG height in pixels, from 240 to 2048",
15372
+ (value) => {
15373
+ return parseIntegerInRange(value, 240, 2048);
15374
+ },
15375
+ 1024
15376
+ ).option(
15377
+ "--style <style>",
15378
+ "Render style: standard or guide",
15379
+ parseOsmStyle,
15380
+ "standard"
15381
+ ).option("--title <text>", "Optional title drawn onto the PNG").option(
15382
+ "--marker <lat,lng[,label]>",
15383
+ "Marker to draw; repeat for multiple markers",
15384
+ collectOsmMarker,
15385
+ []
15386
+ ).requiredOption("--output <path>", "Write PNG to a file").option("--json", "Print the raw maps response as JSON").action(
15387
+ withErrorHandler(async (options) => {
15388
+ const response = await callZeroMaps("osm/render", {
15389
+ ...osmAreaPayload(options),
15390
+ width: options.width,
15391
+ height: options.height,
15392
+ style: options.style,
15393
+ title: options.title,
15394
+ markers: options.marker
15395
+ });
15396
+ await writeOsmPng(options.output, response);
15397
+ if (options.json) {
15398
+ console.log(JSON.stringify(response));
15399
+ return;
15400
+ }
15401
+ renderOsmFileResponse("OSM render completed", response, options.output);
15402
+ })
15403
+ );
15404
+ var osmCommand = new Command().name("osm").description("Download and render OpenStreetMap data").addCommand(osmDownloadCommand).addCommand(osmRenderCommand);
15139
15405
  var placesCommand = new Command().name("places").description("Search places and fetch place details").addCommand(placesSearchCommand).addCommand(placesDetailsCommand);
15140
- var zeroMapsCommand = new Command().name("maps").description("Use managed zero maps services").addCommand(geocodeCommand).addCommand(reverseGeocodeCommand).addCommand(directionsCommand).addCommand(placesCommand).addHelpText(
15406
+ var zeroMapsCommand = new Command().name("maps").description("Use managed zero maps services").addCommand(geocodeCommand).addCommand(reverseGeocodeCommand).addCommand(directionsCommand).addCommand(placesCommand).addCommand(osmCommand).addHelpText(
15141
15407
  "after",
15142
15408
  `
15143
15409
  Examples:
@@ -15147,10 +15413,12 @@ Examples:
15147
15413
  Enterprise search: zero maps places search --query "restaurants in SoMa" --fields enterprise --json
15148
15414
  Place details: zero maps places details --place-id <id> --fields essentials --json
15149
15415
  Enterprise details: zero maps places details --place-id <id> --fields enterprise --json
15416
+ Download OSM data: zero maps osm download --bbox -122.43,37.76,-122.40,37.79 --output map.geojson
15417
+ Render OSM PNG: zero maps osm render --center 37.7749,-122.4194 --radius 1200 --output map.png
15150
15418
 
15151
15419
  Notes:
15152
15420
  - Authenticates via ZERO_TOKEN (requires maps:read capability) or a CLI token
15153
- - Google Maps calls and credit billing happen on the vm0 API server
15421
+ - Google Maps and OpenStreetMap calls and credit billing happen on the vm0 API server
15154
15422
  - Use --fields essentials for place details unless paid fields are required`
15155
15423
  );
15156
15424
 
@@ -15613,7 +15881,7 @@ Tip (video understanding):
15613
15881
  // src/commands/zero/resource/index.ts
15614
15882
  init_esm_shims();
15615
15883
  import { createHash as createHash3 } from "crypto";
15616
- import { mkdir as mkdir3, mkdtemp, rm, writeFile as writeFile3 } from "fs/promises";
15884
+ import { mkdir as mkdir4, mkdtemp, rm, writeFile as writeFile4 } from "fs/promises";
15617
15885
  import { tmpdir as tmpdir8 } from "os";
15618
15886
  import path from "path";
15619
15887
  function candidateIds(id) {
@@ -15691,8 +15959,8 @@ var zeroResourceCommand = new Command().name("resource").description("Pull regis
15691
15959
  const outputDir3 = path.resolve(options.dir);
15692
15960
  const tmpDir = await mkdtemp(path.join(tmpdir8(), "zero-resource-"));
15693
15961
  const archivePath = path.join(tmpDir, "resource.tar.gz");
15694
- await mkdir3(outputDir3, { recursive: true });
15695
- await writeFile3(archivePath, buffer);
15962
+ await mkdir4(outputDir3, { recursive: true });
15963
+ await writeFile4(archivePath, buffer);
15696
15964
  try {
15697
15965
  await uo({
15698
15966
  file: archivePath,
@@ -15837,7 +16105,7 @@ function registerZeroCommands(prog, commands) {
15837
16105
  var program = new Command();
15838
16106
  program.name("zero").description(
15839
16107
  "Zero CLI \u2014 interact with the zero platform from inside the sandbox"
15840
- ).version("9.208.1").addHelpText("after", () => {
16108
+ ).version("9.209.0").addHelpText("after", () => {
15841
16109
  return buildZeroHelpText();
15842
16110
  });
15843
16111
  if (process.argv[1]?.endsWith("zero.js") || process.argv[1]?.endsWith("zero.ts") || process.argv[1]?.endsWith("zero")) {