@vm0/cli 9.116.2 → 9.117.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
@@ -72,7 +72,7 @@ import {
72
72
  source_default,
73
73
  volumeConfigSchema,
74
74
  withErrorHandler
75
- } from "./chunk-DV6NKREP.js";
75
+ } from "./chunk-HVVPJHCH.js";
76
76
 
77
77
  // src/index.ts
78
78
  init_esm_shims();
@@ -465,7 +465,7 @@ function getConfigPath() {
465
465
  return join(homedir(), ".vm0", "config.json");
466
466
  }
467
467
  var infoCommand = new Command().name("info").description("Display environment and debug information").action(async () => {
468
- console.log(source_default.bold(`VM0 CLI v${"9.116.2"}`));
468
+ console.log(source_default.bold(`VM0 CLI v${"9.117.0"}`));
469
469
  console.log();
470
470
  const config = await loadConfig();
471
471
  const hasEnvToken = !!process.env.VM0_TOKEN;
@@ -4494,7 +4494,7 @@ var composeCommand = new Command().name("compose").description("Create or update
4494
4494
  options.autoUpdate = false;
4495
4495
  }
4496
4496
  if (options.autoUpdate !== false) {
4497
- await startSilentUpgrade("9.116.2");
4497
+ await startSilentUpgrade("9.117.0");
4498
4498
  }
4499
4499
  try {
4500
4500
  let result;
@@ -4579,7 +4579,7 @@ var mainRunCommand = new Command().name("run").description("Run an agent").argum
4579
4579
  withErrorHandler(
4580
4580
  async (identifier, prompt, options) => {
4581
4581
  if (options.autoUpdate !== false) {
4582
- await startSilentUpgrade("9.116.2");
4582
+ await startSilentUpgrade("9.117.0");
4583
4583
  }
4584
4584
  const { name, version } = parseIdentifier(identifier);
4585
4585
  let composeId;
@@ -6353,7 +6353,7 @@ var cookAction = new Command().name("cook").description("Quick start: prepare, c
6353
6353
  withErrorHandler(
6354
6354
  async (prompt, options) => {
6355
6355
  if (options.autoUpdate !== false) {
6356
- const shouldExit = await checkAndUpgrade("9.116.2", prompt);
6356
+ const shouldExit = await checkAndUpgrade("9.117.0", prompt);
6357
6357
  if (shouldExit) {
6358
6358
  process.exit(0);
6359
6359
  }
@@ -7120,13 +7120,13 @@ var upgradeCommand = new Command().name("upgrade").description("Upgrade vm0 CLI
7120
7120
  if (latestVersion === null) {
7121
7121
  throw new Error("Could not check for updates. Please try again later.");
7122
7122
  }
7123
- if (latestVersion === "9.116.2") {
7124
- console.log(source_default.green(`\u2713 Already up to date (${"9.116.2"})`));
7123
+ if (latestVersion === "9.117.0") {
7124
+ console.log(source_default.green(`\u2713 Already up to date (${"9.117.0"})`));
7125
7125
  return;
7126
7126
  }
7127
7127
  console.log(
7128
7128
  source_default.yellow(
7129
- `Current version: ${"9.116.2"} -> Latest version: ${latestVersion}`
7129
+ `Current version: ${"9.117.0"} -> Latest version: ${latestVersion}`
7130
7130
  )
7131
7131
  );
7132
7132
  console.log();
@@ -7153,7 +7153,7 @@ var upgradeCommand = new Command().name("upgrade").description("Upgrade vm0 CLI
7153
7153
  const success = await performUpgrade(packageManager);
7154
7154
  if (success) {
7155
7155
  console.log(
7156
- source_default.green(`\u2713 Upgraded from ${"9.116.2"} to ${latestVersion}`)
7156
+ source_default.green(`\u2713 Upgraded from ${"9.117.0"} to ${latestVersion}`)
7157
7157
  );
7158
7158
  return;
7159
7159
  }
@@ -7220,7 +7220,7 @@ var whoamiCommand = new Command().name("whoami").description("Show current ident
7220
7220
 
7221
7221
  // src/index.ts
7222
7222
  var program = new Command();
7223
- program.name("vm0").description("VM0 CLI - Build and run agents with natural language").version("9.116.2");
7223
+ program.name("vm0").description("VM0 CLI - Build and run agents with natural language").version("9.117.0");
7224
7224
  program.addCommand(authCommand);
7225
7225
  program.addCommand(infoCommand);
7226
7226
  program.addCommand(composeCommand);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vm0/cli",
3
- "version": "9.116.2",
3
+ "version": "9.117.0",
4
4
  "description": "CLI application",
5
5
  "repository": {
6
6
  "type": "git",
package/zero.js CHANGED
@@ -37,6 +37,7 @@ import {
37
37
  deleteZeroVariable,
38
38
  deployZeroSchedule,
39
39
  disableZeroSchedule,
40
+ downloadSlackFile,
40
41
  enableZeroSchedule,
41
42
  extractSecretNamesFromApis,
42
43
  findMatchingPermissions,
@@ -111,6 +112,7 @@ import {
111
112
  resolveZeroScheduleByAgent,
112
113
  saveConfig,
113
114
  searchZeroLogs,
115
+ sendChatMessage,
114
116
  sendSlackMessage,
115
117
  setZeroOrgModelProviderDefault,
116
118
  setZeroOrgSecret,
@@ -130,7 +132,7 @@ import {
130
132
  upsertZeroOrgModelProvider,
131
133
  withErrorHandler,
132
134
  zeroAgentCustomSkillNameSchema
133
- } from "./chunk-DV6NKREP.js";
135
+ } from "./chunk-HVVPJHCH.js";
134
136
 
135
137
  // src/zero.ts
136
138
  init_esm_shims();
@@ -3994,6 +3996,86 @@ var deleteCommand4 = new Command().name("delete").description("Delete a secret")
3994
3996
  // src/commands/zero/secret/index.ts
3995
3997
  var zeroSecretCommand = new Command().name("secret").description("Read or write secrets (API keys, tokens)").addCommand(listCommand8).addCommand(setCommand4).addCommand(deleteCommand4);
3996
3998
 
3999
+ // src/commands/zero/chat/index.ts
4000
+ init_esm_shims();
4001
+
4002
+ // src/commands/zero/chat/message/index.ts
4003
+ init_esm_shims();
4004
+
4005
+ // src/commands/zero/chat/message/send.ts
4006
+ init_esm_shims();
4007
+ import { readFileSync as readFileSync3 } from "fs";
4008
+ var sendCommand = new Command().name("send").description("Send a message to a web chat thread").option("-t, --thread <id>", "Existing chat thread ID").option("-a, --agent <agentId>", "Agent ID (creates a new thread)").option("--text <message>", "Message text").option("--title <title>", "Thread title (only with --agent)").addHelpText(
4009
+ "after",
4010
+ `
4011
+ Examples:
4012
+ Send to existing thread: zero chat message send -t <thread-id> --text "Hello!"
4013
+ Send to agent (new thread): zero chat message send -a <agent-id> --text "Hello!"
4014
+
4015
+ Notes:
4016
+ - Either --thread or --agent is required; they are mutually exclusive
4017
+ - --text is required (or pipe via stdin)`
4018
+ ).action(
4019
+ withErrorHandler(
4020
+ async (options) => {
4021
+ let text = options.text;
4022
+ const { thread, agent, title } = options;
4023
+ if (!thread && !agent) {
4024
+ throw new Error("Either --thread or --agent must be provided", {
4025
+ cause: new Error(
4026
+ 'Usage: zero chat message send -t THREAD_ID --text "your message"\n zero chat message send -a AGENT_ID --text "your message"'
4027
+ )
4028
+ });
4029
+ }
4030
+ if (thread && agent) {
4031
+ throw new Error("--thread and --agent are mutually exclusive", {
4032
+ cause: new Error(
4033
+ "Provide either --thread to send to an existing thread or --agent to create a new thread, not both"
4034
+ )
4035
+ });
4036
+ }
4037
+ if (!text && process.stdin.isTTY === false) {
4038
+ text = readFileSync3("/dev/stdin", "utf8").trim();
4039
+ }
4040
+ if (!text) {
4041
+ throw new Error("--text is required", {
4042
+ cause: new Error(
4043
+ 'Usage: zero chat message send -t THREAD_ID --text "your message"'
4044
+ )
4045
+ });
4046
+ }
4047
+ const result = await sendChatMessage({
4048
+ thread: thread || void 0,
4049
+ agent: agent || void 0,
4050
+ text,
4051
+ title: title || void 0
4052
+ });
4053
+ console.log(
4054
+ source_default.green(
4055
+ `\u2713 Message sent (id: ${result.messageId}, thread: ${result.threadId})`
4056
+ )
4057
+ );
4058
+ }
4059
+ )
4060
+ );
4061
+
4062
+ // src/commands/zero/chat/message/index.ts
4063
+ var zeroChatMessageCommand = new Command().name("message").description("Manage chat messages").addCommand(sendCommand).addHelpText(
4064
+ "after",
4065
+ `
4066
+ Examples:
4067
+ zero chat message send -t <thread-id> --text "Hello!"`
4068
+ );
4069
+
4070
+ // src/commands/zero/chat/index.ts
4071
+ var zeroChatCommand = new Command().name("chat").description("Send messages to web chat threads").addCommand(zeroChatMessageCommand).addHelpText(
4072
+ "after",
4073
+ `
4074
+ Examples:
4075
+ Send to thread: zero chat message send -t <thread-id> --text "Hello!"
4076
+ Send to agent: zero chat message send -a <agent-id> --text "Hello!"`
4077
+ );
4078
+
3997
4079
  // src/commands/zero/slack/index.ts
3998
4080
  init_esm_shims();
3999
4081
 
@@ -4002,8 +4084,8 @@ init_esm_shims();
4002
4084
 
4003
4085
  // src/commands/zero/slack/message/send.ts
4004
4086
  init_esm_shims();
4005
- import { readFileSync as readFileSync3 } from "fs";
4006
- var sendCommand = new Command().name("send").description("Send a message to a Slack channel or DM a user").option("-c, --channel <id>", "Channel ID").option("-u, --user <id>", "Slack user ID for DM").option("-t, --text <message>", "Message text").option("--thread <ts>", "Thread timestamp for replies").option("--blocks <json>", "Block Kit JSON string").addHelpText(
4087
+ import { readFileSync as readFileSync4 } from "fs";
4088
+ var sendCommand2 = new Command().name("send").description("Send a message to a Slack channel or DM a user").option("-c, --channel <id>", "Channel ID").option("-u, --user <id>", "Slack user ID for DM").option("-t, --text <message>", "Message text").option("--thread <ts>", "Thread timestamp for replies").option("--blocks <json>", "Block Kit JSON string").addHelpText(
4007
4089
  "after",
4008
4090
  `
4009
4091
  Examples:
@@ -4035,7 +4117,7 @@ Notes:
4035
4117
  });
4036
4118
  }
4037
4119
  if (!text && process.stdin.isTTY === false) {
4038
- text = readFileSync3("/dev/stdin", "utf8").trim();
4120
+ text = readFileSync4("/dev/stdin", "utf8").trim();
4039
4121
  }
4040
4122
  let blocks;
4041
4123
  if (blocksStr) {
@@ -4070,7 +4152,7 @@ Notes:
4070
4152
  );
4071
4153
 
4072
4154
  // src/commands/zero/slack/message/index.ts
4073
- var zeroSlackMessageCommand = new Command().name("message").description("Manage Slack messages").addCommand(sendCommand).addHelpText(
4155
+ var zeroSlackMessageCommand = new Command().name("message").description("Manage Slack messages").addCommand(sendCommand2).addHelpText(
4074
4156
  "after",
4075
4157
  `
4076
4158
  Examples:
@@ -4079,7 +4161,7 @@ Examples:
4079
4161
 
4080
4162
  // src/commands/zero/slack/upload-file.ts
4081
4163
  init_esm_shims();
4082
- import { statSync, readFileSync as readFileSync4 } from "fs";
4164
+ import { statSync, readFileSync as readFileSync5 } from "fs";
4083
4165
  import { basename } from "path";
4084
4166
  var uploadFileCommand = new Command().name("upload-file").description("Upload a file to a Slack channel as the bot").requiredOption("-f, --file <path>", "Local file path to upload").requiredOption("-c, --channel <id>", "Slack channel ID").option("--thread <ts>", "Thread timestamp to post as a reply").option("--title <title>", "Display title for the file").option("--comment <text>", "Initial comment to accompany the file").addHelpText(
4085
4167
  "after",
@@ -4110,7 +4192,7 @@ Notes:
4110
4192
  filename,
4111
4193
  length: fileSize
4112
4194
  });
4113
- const fileContent = readFileSync4(options.file);
4195
+ const fileContent = readFileSync5(options.file);
4114
4196
  const uploadResponse = await fetch(uploadUrl, {
4115
4197
  method: "POST",
4116
4198
  body: fileContent
@@ -4133,14 +4215,49 @@ Notes:
4133
4215
  )
4134
4216
  );
4135
4217
 
4218
+ // src/commands/zero/slack/download-file.ts
4219
+ init_esm_shims();
4220
+ import { join as join2 } from "path";
4221
+ import { tmpdir } from "os";
4222
+ function defaultOutPath(fileId) {
4223
+ return join2(tmpdir(), `slack-${fileId}`);
4224
+ }
4225
+ var downloadFileCommand = new Command().name("download-file").description("Download a Slack file by id using the bot token").argument("<file-id>", "Slack file id (e.g. F01234ABCD)").option(
4226
+ "-o, --out <path>",
4227
+ "Output path for the downloaded file (default: /tmp/slack-<file-id>)"
4228
+ ).addHelpText(
4229
+ "after",
4230
+ `
4231
+ Examples:
4232
+ Download to default temp path: zero slack download-file F01234ABCD
4233
+ Download to explicit path: zero slack download-file F01234ABCD -o /tmp/image.png
4234
+
4235
+ Output:
4236
+ Prints a JSON object to stdout on success:
4237
+ {"path":"/tmp/slack-F01234ABCD","mimetype":"image/png","size":12345}
4238
+
4239
+ Notes:
4240
+ - Uses the bot token on the server side; no user Slack token is needed
4241
+ - Streams the file bytes directly to disk`
4242
+ ).action(
4243
+ withErrorHandler(async (fileId, options) => {
4244
+ const outPath = options.out ?? defaultOutPath(fileId);
4245
+ const result = await downloadSlackFile(fileId, outPath);
4246
+ console.log(JSON.stringify(result));
4247
+ })
4248
+ );
4249
+
4136
4250
  // src/commands/zero/slack/index.ts
4137
- var zeroSlackCommand = new Command().name("slack").description("Send messages and upload files to Slack channels as the bot").addCommand(zeroSlackMessageCommand).addCommand(uploadFileCommand).addHelpText(
4251
+ var zeroSlackCommand = new Command().name("slack").description(
4252
+ "Send messages, upload files, and download files from Slack as the bot"
4253
+ ).addCommand(zeroSlackMessageCommand).addCommand(uploadFileCommand).addCommand(downloadFileCommand).addHelpText(
4138
4254
  "after",
4139
4255
  `
4140
4256
  Examples:
4141
4257
  Send a message: zero slack message send -c <channel-id> -t "Hello!"
4142
4258
  Reply in a thread: zero slack message send -c <channel-id> --thread <ts> -t "reply"
4143
- Upload a file: zero slack upload-file -f /tmp/report.pdf -c <channel-id>`
4259
+ Upload a file: zero slack upload-file -f /tmp/report.pdf -c <channel-id>
4260
+ Download a file: zero slack download-file <file-id> -o /tmp/out.png`
4144
4261
  );
4145
4262
 
4146
4263
  // src/commands/zero/variable/index.ts
@@ -4390,8 +4507,8 @@ init_esm_shims();
4390
4507
 
4391
4508
  // src/lib/skill-directory.ts
4392
4509
  init_esm_shims();
4393
- import { readFileSync as readFileSync5, readdirSync } from "fs";
4394
- import { join as join2 } from "path";
4510
+ import { readFileSync as readFileSync6, readdirSync } from "fs";
4511
+ import { join as join3 } from "path";
4395
4512
  var IGNORED_NAMES = /* @__PURE__ */ new Set(["node_modules", ".git", ".DS_Store"]);
4396
4513
  function readSkillDirectory(dirPath) {
4397
4514
  const files = [];
@@ -4401,11 +4518,11 @@ function readSkillDirectory(dirPath) {
4401
4518
  if (entry.name.startsWith(".") || IGNORED_NAMES.has(entry.name)) continue;
4402
4519
  const relPath = prefix ? `${prefix}/${entry.name}` : entry.name;
4403
4520
  if (entry.isDirectory()) {
4404
- walk(join2(dir, entry.name), relPath);
4521
+ walk(join3(dir, entry.name), relPath);
4405
4522
  } else {
4406
4523
  files.push({
4407
4524
  path: relPath,
4408
- content: readFileSync5(join2(dir, entry.name), "utf-8")
4525
+ content: readFileSync6(join3(dir, entry.name), "utf-8")
4409
4526
  });
4410
4527
  }
4411
4528
  }
@@ -4997,12 +5114,12 @@ init_esm_shims();
4997
5114
  import { execFile } from "child_process";
4998
5115
  import { readFile, unlink } from "fs/promises";
4999
5116
  import { randomUUID } from "crypto";
5000
- import { join as join3 } from "path";
5001
- import { tmpdir } from "os";
5117
+ import { join as join4 } from "path";
5118
+ import { tmpdir as tmpdir2 } from "os";
5002
5119
  import { promisify } from "util";
5003
5120
  var execFileAsync = promisify(execFile);
5004
5121
  async function captureScreenshot() {
5005
- const tmpPath = join3(tmpdir(), `vm0-screenshot-${randomUUID()}.jpg`);
5122
+ const tmpPath = join4(tmpdir2(), `vm0-screenshot-${randomUUID()}.jpg`);
5006
5123
  try {
5007
5124
  await execFileAsync("screencapture", ["-x", "-t", "jpg", tmpPath]);
5008
5125
  const info = await getScreenInfo();
@@ -5031,7 +5148,7 @@ async function captureScreenshot() {
5031
5148
  }
5032
5149
  }
5033
5150
  async function captureRegionScreenshot(region) {
5034
- const tmpPath = join3(tmpdir(), `vm0-zoom-${randomUUID()}.jpg`);
5151
+ const tmpPath = join4(tmpdir2(), `vm0-zoom-${randomUUID()}.jpg`);
5035
5152
  try {
5036
5153
  const regionArg = `${region.x},${region.y},${region.width},${region.height}`;
5037
5154
  await execFileAsync("screencapture", [
@@ -5723,7 +5840,7 @@ var hostStopCommand = new Command().name("stop").description("Stop and unregiste
5723
5840
  // src/commands/zero/computer-use/client.ts
5724
5841
  init_esm_shims();
5725
5842
  import { writeFile, mkdir } from "fs/promises";
5726
- import { join as join4 } from "path";
5843
+ import { join as join5 } from "path";
5727
5844
 
5728
5845
  // src/lib/computer-use/client.ts
5729
5846
  init_esm_shims();
@@ -5791,7 +5908,7 @@ var clientScreenshotCommand = new Command().name("screenshot").description("Capt
5791
5908
  const dir = "/tmp/computer-use";
5792
5909
  await mkdir(dir, { recursive: true });
5793
5910
  const timestamp = Date.now();
5794
- const filePath = join4(dir, `screenshot-${timestamp}.${data.format}`);
5911
+ const filePath = join5(dir, `screenshot-${timestamp}.${data.format}`);
5795
5912
  const buffer = Buffer.from(data.image, "base64");
5796
5913
  await writeFile(filePath, buffer);
5797
5914
  process.stdout.write(`${filePath}
@@ -5819,7 +5936,7 @@ var clientZoomCommand = new Command().name("zoom").description("Capture a region
5819
5936
  const dir = "/tmp/computer-use";
5820
5937
  await mkdir(dir, { recursive: true });
5821
5938
  const timestamp = Date.now();
5822
- const filePath = join4(dir, `zoom-${timestamp}.${data.format}`);
5939
+ const filePath = join5(dir, `zoom-${timestamp}.${data.format}`);
5823
5940
  const buffer = Buffer.from(data.image, "base64");
5824
5941
  await writeFile(filePath, buffer);
5825
5942
  process.stdout.write(`${filePath}
@@ -6217,7 +6334,7 @@ var voiceChatContextGetCommand = new Command().name("get").description("Read sha
6217
6334
 
6218
6335
  // src/commands/zero/voice-chat/context/append.ts
6219
6336
  init_esm_shims();
6220
- import { readFileSync as readFileSync7 } from "fs";
6337
+ import { readFileSync as readFileSync8 } from "fs";
6221
6338
  var voiceChatContextAppendCommand = new Command().name("append").description("Append an event to voice-chat shared context").argument("<session-id>", "Voice-chat session ID").requiredOption(
6222
6339
  "--source <source>",
6223
6340
  "Event source (system|user|fast-brain|slow-brain)"
@@ -6235,7 +6352,7 @@ Examples:
6235
6352
  async (sessionId, options) => {
6236
6353
  let content = options.content;
6237
6354
  if (!content && process.stdin.isTTY === false) {
6238
- content = readFileSync7("/dev/stdin", "utf8").trim();
6355
+ content = readFileSync8("/dev/stdin", "utf8").trim();
6239
6356
  }
6240
6357
  const data = await appendVoiceChatContextEvent(sessionId, {
6241
6358
  source: options.source,
@@ -6249,7 +6366,7 @@ Examples:
6249
6366
 
6250
6367
  // src/commands/zero/voice-chat/context/prepare.ts
6251
6368
  init_esm_shims();
6252
- import { readFileSync as readFileSync8 } from "fs";
6369
+ import { readFileSync as readFileSync9 } from "fs";
6253
6370
  var voiceChatContextPrepareCommand = new Command().name("prepare").description("Submit preparation directive content for a voice-chat run").option(
6254
6371
  "--content <content>",
6255
6372
  "Directive content (reads from stdin if not provided)"
@@ -6263,7 +6380,7 @@ Examples:
6263
6380
  withErrorHandler(async (options) => {
6264
6381
  let content = options.content;
6265
6382
  if (!content && process.stdin.isTTY === false) {
6266
- content = readFileSync8("/dev/stdin", "utf8").trim();
6383
+ content = readFileSync9("/dev/stdin", "utf8").trim();
6267
6384
  }
6268
6385
  if (!content) {
6269
6386
  throw new Error(
@@ -6297,6 +6414,7 @@ var COMMAND_CAPABILITY_MAP = {
6297
6414
  schedule: "schedule:read",
6298
6415
  doctor: null,
6299
6416
  logs: "agent-run:read",
6417
+ chat: "chat-message:write",
6300
6418
  slack: "slack:write",
6301
6419
  whoami: null,
6302
6420
  "developer-support": null,
@@ -6313,6 +6431,7 @@ var DEFAULT_COMMANDS = [
6313
6431
  zeroRunCommand,
6314
6432
  zeroScheduleCommand,
6315
6433
  zeroSecretCommand,
6434
+ zeroChatCommand,
6316
6435
  zeroSlackCommand,
6317
6436
  zeroVariableCommand,
6318
6437
  zeroLogsCommand,
@@ -6340,7 +6459,7 @@ function registerZeroCommands(prog, commands) {
6340
6459
  var program = new Command();
6341
6460
  program.name("zero").description(
6342
6461
  "Zero CLI \u2014 interact with the zero platform from inside the sandbox"
6343
- ).version("9.116.2").addHelpText(
6462
+ ).version("9.117.0").addHelpText(
6344
6463
  "after",
6345
6464
  `
6346
6465
  Examples: