@vm0/cli 9.134.1 → 9.136.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vm0/cli",
3
- "version": "9.134.1",
3
+ "version": "9.136.0",
4
4
  "description": "CLI application",
5
5
  "repository": {
6
6
  "type": "git",
package/zero.js CHANGED
@@ -11,6 +11,7 @@ import {
11
11
  Option,
12
12
  allowsCustomModel,
13
13
  completeSlackFileUpload,
14
+ completeTelegramFileUpload,
14
15
  configureGlobalProxyFromEnv,
15
16
  connectorTypeSchema,
16
17
  createSkill,
@@ -59,6 +60,7 @@ import {
59
60
  hasAuthMethods,
60
61
  hasModelSelection,
61
62
  initSlackFileUpload,
63
+ initTelegramFileUpload,
62
64
  inviteZeroOrgMember,
63
65
  isInteractive,
64
66
  isUUID,
@@ -113,7 +115,7 @@ import {
113
115
  upsertZeroOrgModelProvider,
114
116
  withErrorHandler,
115
117
  zeroAgentCustomSkillNameSchema
116
- } from "./chunk-2MZO4LKL.js";
118
+ } from "./chunk-5F6QHYHS.js";
117
119
  import {
118
120
  __toESM,
119
121
  init_esm_shims
@@ -16787,11 +16789,111 @@ Notes:
16787
16789
  )
16788
16790
  );
16789
16791
 
16792
+ // src/commands/zero/telegram/upload-file.ts
16793
+ init_esm_shims();
16794
+ import { readFileSync as readFileSync7, statSync as statSync2 } from "fs";
16795
+ import { basename as basename2, extname } from "path";
16796
+ var MIME_BY_EXTENSION = {
16797
+ ".png": "image/png",
16798
+ ".jpg": "image/jpeg",
16799
+ ".jpeg": "image/jpeg",
16800
+ ".gif": "image/gif",
16801
+ ".webp": "image/webp",
16802
+ ".svg": "image/svg+xml",
16803
+ ".mp4": "video/mp4",
16804
+ ".webm": "video/webm",
16805
+ ".mov": "video/quicktime",
16806
+ ".pdf": "application/pdf",
16807
+ ".txt": "text/plain",
16808
+ ".csv": "text/csv",
16809
+ ".md": "text/markdown",
16810
+ ".json": "application/json"
16811
+ };
16812
+ function inferContentType(localPath) {
16813
+ const ext = extname(localPath).toLowerCase();
16814
+ return MIME_BY_EXTENSION[ext] ?? "application/octet-stream";
16815
+ }
16816
+ function parseMessageThreadId(value) {
16817
+ if (!value) return void 0;
16818
+ const parsed = Number(value);
16819
+ if (!Number.isSafeInteger(parsed) || parsed <= 0) {
16820
+ throw new Error("message-thread-id must be a positive integer");
16821
+ }
16822
+ return parsed;
16823
+ }
16824
+ var uploadFileCommand2 = new Command().name("upload-file").description("Upload a local file to a Telegram chat as the bot").requiredOption("-f, --file <path>", "Local file path to upload").requiredOption("--bot-id <bot-id>", "Telegram bot id to send through").requiredOption("-c, --chat-id <chat-id>", "Telegram chat id or @channel").option("--caption <text>", "Caption to accompany the file").option("--message-thread-id <id>", "Forum topic message thread id").option("--content-type <mime>", "Override inferred content type").addHelpText(
16825
+ "after",
16826
+ `
16827
+ Examples:
16828
+ Upload a file: zero telegram upload-file -f /tmp/report.pdf --bot-id 123456789 -c -1001234567890
16829
+ Upload to a topic: zero telegram upload-file -f /tmp/log.txt --bot-id 123456789 -c -1001234567890 --message-thread-id 42
16830
+ With a caption: zero telegram upload-file -f /tmp/data.csv --bot-id 123456789 -c @channel --caption "Daily report"
16831
+
16832
+ Output:
16833
+ Prints a JSON object to stdout on success:
16834
+ {"messageId":123,"chatId":"-1001234567890","fileId":"...","filename":"report.pdf","mimetype":"application/pdf","size":12345,"url":"https://..."}
16835
+
16836
+ Notes:
16837
+ - Uses the Telegram bot token on the server side
16838
+ - Uploads through VM0 storage first, then asks Telegram to fetch the file URL
16839
+ - VM0 does not apply file type or size restrictions before calling Telegram`
16840
+ ).action(
16841
+ withErrorHandler(
16842
+ async (options) => {
16843
+ let fileSize;
16844
+ try {
16845
+ const stat = statSync2(options.file);
16846
+ if (!stat.isFile()) {
16847
+ throw new Error(`Not a regular file: ${options.file}`);
16848
+ }
16849
+ fileSize = stat.size;
16850
+ } catch (error) {
16851
+ if (error instanceof Error && error.message.startsWith("Not ")) {
16852
+ throw error;
16853
+ }
16854
+ throw new Error(`File not found: ${options.file}`);
16855
+ }
16856
+ if (fileSize === 0) {
16857
+ throw new Error("File is empty");
16858
+ }
16859
+ const filename = basename2(options.file);
16860
+ const contentType = options.contentType ?? inferContentType(options.file);
16861
+ const messageThreadId = parseMessageThreadId(options.messageThreadId);
16862
+ const prepared = await initTelegramFileUpload({
16863
+ filename,
16864
+ contentType,
16865
+ length: fileSize
16866
+ });
16867
+ const fileContent = readFileSync7(options.file);
16868
+ const uploadResponse = await fetch(prepared.uploadUrl, {
16869
+ method: "PUT",
16870
+ headers: { "Content-Type": prepared.contentType },
16871
+ body: new Uint8Array(fileContent)
16872
+ });
16873
+ if (!uploadResponse.ok) {
16874
+ throw new Error(
16875
+ `File upload failed: ${uploadResponse.status} ${uploadResponse.statusText}`
16876
+ );
16877
+ }
16878
+ const result = await completeTelegramFileUpload({
16879
+ uploadId: prepared.uploadId,
16880
+ botId: options.botId,
16881
+ chatId: options.chatId,
16882
+ contentType: prepared.contentType,
16883
+ caption: options.caption,
16884
+ messageThreadId
16885
+ });
16886
+ console.log(JSON.stringify(result));
16887
+ }
16888
+ )
16889
+ );
16890
+
16790
16891
  // src/commands/zero/telegram/index.ts
16791
- var zeroTelegramCommand = new Command().name("telegram").description("Download files from Telegram as the bot").addCommand(downloadFileCommand2).addHelpText(
16892
+ var zeroTelegramCommand = new Command().name("telegram").description("Upload and download files from Telegram as the bot").addCommand(downloadFileCommand2).addCommand(uploadFileCommand2).addHelpText(
16792
16893
  "after",
16793
16894
  `
16794
16895
  Examples:
16896
+ Upload a file: zero telegram upload-file -f /tmp/report.pdf --bot-id <bot-id> -c <chat-id>
16795
16897
  Download a file: zero telegram download-file <file-id> --bot-id <bot-id> -o /tmp/out.jpg`
16796
16898
  );
16797
16899
 
@@ -17042,7 +17144,7 @@ init_esm_shims();
17042
17144
 
17043
17145
  // src/lib/skill-directory.ts
17044
17146
  init_esm_shims();
17045
- import { readFileSync as readFileSync7, readdirSync } from "fs";
17147
+ import { readFileSync as readFileSync8, readdirSync } from "fs";
17046
17148
  import { join as join3 } from "path";
17047
17149
  var IGNORED_NAMES = /* @__PURE__ */ new Set(["node_modules", ".git", ".DS_Store"]);
17048
17150
  function readSkillDirectory(dirPath) {
@@ -17057,7 +17159,7 @@ function readSkillDirectory(dirPath) {
17057
17159
  } else {
17058
17160
  files.push({
17059
17161
  path: relPath,
17060
- content: readFileSync7(join3(dir, entry.name), "utf-8")
17162
+ content: readFileSync8(join3(dir, entry.name), "utf-8")
17061
17163
  });
17062
17164
  }
17063
17165
  }
@@ -18877,7 +18979,7 @@ Notes:
18877
18979
 
18878
18980
  // src/commands/zero/web/upload-file.ts
18879
18981
  init_esm_shims();
18880
- var uploadFileCommand2 = new Command().name("upload-file").description("Upload a local file and print a permanent URL").requiredOption("-f, --file <path>", "Local file path to upload").option("--content-type <mime>", "Override inferred content type").addHelpText(
18982
+ var uploadFileCommand3 = new Command().name("upload-file").description("Upload a local file and print a permanent URL").requiredOption("-f, --file <path>", "Local file path to upload").option("--content-type <mime>", "Override inferred content type").addHelpText(
18881
18983
  "after",
18882
18984
  `
18883
18985
  Examples:
@@ -18906,7 +19008,7 @@ Notes:
18906
19008
  );
18907
19009
 
18908
19010
  // src/commands/zero/web/index.ts
18909
- var zeroWebCommand = new Command().name("web").description("Upload and download files via the web chat endpoint").addCommand(downloadFileCommand3).addCommand(uploadFileCommand2).addHelpText(
19011
+ var zeroWebCommand = new Command().name("web").description("Upload and download files via the web chat endpoint").addCommand(downloadFileCommand3).addCommand(uploadFileCommand3).addHelpText(
18910
19012
  "after",
18911
19013
  `
18912
19014
  Examples:
@@ -18926,7 +19028,7 @@ var COMMAND_CAPABILITY_MAP = {
18926
19028
  search: "chat-message:read",
18927
19029
  chat: "chat-message:write",
18928
19030
  slack: "slack:write",
18929
- telegram: "file:read",
19031
+ telegram: ["telegram:read", "telegram:write"],
18930
19032
  whoami: null,
18931
19033
  "developer-support": null,
18932
19034
  "computer-use": "computer-use:write",
@@ -18957,7 +19059,13 @@ function shouldHideCommand(name, payload) {
18957
19059
  if (!payload) return false;
18958
19060
  const requiredCap = COMMAND_CAPABILITY_MAP[name];
18959
19061
  if (requiredCap === void 0) return true;
18960
- return requiredCap !== null && !payload.capabilities.includes(requiredCap);
19062
+ if (requiredCap === null) return false;
19063
+ if (typeof requiredCap !== "string") {
19064
+ return !requiredCap.some((capability) => {
19065
+ return payload.capabilities.includes(capability);
19066
+ });
19067
+ }
19068
+ return !payload.capabilities.includes(requiredCap);
18961
19069
  }
18962
19070
  function registerZeroCommands(prog, commands) {
18963
19071
  const token = process.env.ZERO_TOKEN;
@@ -18970,12 +19078,13 @@ function registerZeroCommands(prog, commands) {
18970
19078
  var program = new Command();
18971
19079
  program.name("zero").description(
18972
19080
  "Zero CLI \u2014 interact with the zero platform from inside the sandbox"
18973
- ).version("9.134.1").addHelpText(
19081
+ ).version("9.136.0").addHelpText(
18974
19082
  "after",
18975
19083
  `
18976
19084
  Examples:
18977
19085
  Check a connector? zero doctor check-connector --env-name <ENV_NAME>
18978
19086
  Send a Slack message? zero slack message send --help
19087
+ Upload Telegram? zero telegram upload-file --help
18979
19088
  Download Telegram? zero telegram download-file --help
18980
19089
  Set up a schedule? zero schedule setup --help
18981
19090
  Update yourself? zero agent --help