@vm0/cli 9.249.1 → 9.249.2

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 (141) hide show
  1. package/{agent-PMWDKCSZ.js → agent-TOFXTWYP.js} +11 -10
  2. package/{agent-PMWDKCSZ.js.map → agent-TOFXTWYP.js.map} +1 -1
  3. package/{banking-S5RH46G5.js → banking-U7I6EJUO.js} +8 -7
  4. package/{banking-S5RH46G5.js.map → banking-U7I6EJUO.js.map} +1 -1
  5. package/{chat-2ZTZUIWC.js → chat-77EDGFMS.js} +9 -8
  6. package/{chat-2ZTZUIWC.js.map → chat-77EDGFMS.js.map} +1 -1
  7. package/{chunk-DIRAZ3YX.js → chunk-3VVCUQPB.js} +3 -3
  8. package/{chunk-DIRAZ3YX.js.map → chunk-3VVCUQPB.js.map} +1 -1
  9. package/{chunk-PLOJYRFL.js → chunk-4HN7U3JF.js} +40 -564
  10. package/chunk-4HN7U3JF.js.map +1 -0
  11. package/{chunk-FF5L22OE.js → chunk-5CZNUTFF.js} +3 -3
  12. package/chunk-A2NKQGRI.js +491 -0
  13. package/chunk-A2NKQGRI.js.map +1 -0
  14. package/{chunk-J2I5GYLR.js → chunk-AFNSFKAH.js} +5 -5
  15. package/{chunk-L63QVTYZ.js → chunk-BQOOTJNB.js} +27 -672
  16. package/chunk-BQOOTJNB.js.map +1 -0
  17. package/{chunk-KLIW3XK7.js → chunk-GPF7NSX7.js} +2 -2
  18. package/{chunk-HUMR2SA3.js → chunk-HSGQT7LT.js} +3 -3
  19. package/{chunk-SAW74AR6.js → chunk-JCLLQRCI.js} +3 -3
  20. package/{chunk-B3W2RUBP.js → chunk-LD4ZVU4O.js} +2 -2
  21. package/chunk-N6TDQYGF.js +678 -0
  22. package/chunk-N6TDQYGF.js.map +1 -0
  23. package/{chunk-KQN5YZZP.js → chunk-ROB3OE37.js} +10 -113
  24. package/chunk-ROB3OE37.js.map +1 -0
  25. package/{chunk-LTDQISD7.js → chunk-SB7EZ2ZO.js} +2 -2
  26. package/{chunk-RTYT3CSZ.js → chunk-UG5XA6KU.js} +2 -2
  27. package/{chunk-LKDE4AUC.js → chunk-UNQJRTJQ.js} +3 -3
  28. package/chunk-W75R7EZF.js +17 -0
  29. package/chunk-W75R7EZF.js.map +1 -0
  30. package/chunk-WDDZJGWL.js +32 -0
  31. package/chunk-WDDZJGWL.js.map +1 -0
  32. package/{chunk-JFY6GK7Y.js → chunk-X2545RBX.js} +2 -2
  33. package/{chunk-ZE2VIESK.js → chunk-X4DBCBU4.js} +2 -2
  34. package/{computer-use-GRK4TZYN.js → computer-use-BCGPVGWS.js} +7 -6
  35. package/{computer-use-GRK4TZYN.js.map → computer-use-BCGPVGWS.js.map} +1 -1
  36. package/{connector-2SVH4F2N.js → connector-CHZSI2LW.js} +14 -13
  37. package/{connector-2SVH4F2N.js.map → connector-CHZSI2LW.js.map} +1 -1
  38. package/credit-RWFBPKOS.js +166 -0
  39. package/credit-RWFBPKOS.js.map +1 -0
  40. package/{developer-support-RYTLIFUN.js → developer-support-IVR3HIP7.js} +8 -7
  41. package/{developer-support-RYTLIFUN.js.map → developer-support-IVR3HIP7.js.map} +1 -1
  42. package/{doctor-CS5TFE6A.js → doctor-KGWTXW2Q.js} +39 -13
  43. package/doctor-KGWTXW2Q.js.map +1 -0
  44. package/{esm-PZKPCIYJ.js → esm-GOCEMHJO.js} +3 -3
  45. package/{feishu-HFQIJDBU.js → feishu-PLF4P5OG.js} +8 -7
  46. package/{feishu-HFQIJDBU.js.map → feishu-PLF4P5OG.js.map} +1 -1
  47. package/{finance-56HIRALT.js → finance-LVFG3WWP.js} +8 -7
  48. package/{finance-56HIRALT.js.map → finance-LVFG3WWP.js.map} +1 -1
  49. package/{generate-4FEC4YVM.js → generate-4FIBMMJO.js} +77 -22
  50. package/generate-4FIBMMJO.js.map +1 -0
  51. package/{getMachineId-bsd-L73QENVB.js → getMachineId-bsd-SB7C44VX.js} +4 -4
  52. package/{getMachineId-darwin-TCCWKQ2S.js → getMachineId-darwin-R4BWY3CQ.js} +4 -4
  53. package/{getMachineId-linux-TJYYUZVM.js → getMachineId-linux-BR4HVNPW.js} +3 -3
  54. package/{getMachineId-unsupported-DPRVLH4Y.js → getMachineId-unsupported-FPGM635L.js} +3 -3
  55. package/{getMachineId-win-7EE436CJ.js → getMachineId-win-RB4JMF33.js} +4 -4
  56. package/{github-AALJ7IEM.js → github-WHNAVVG3.js} +8 -7
  57. package/{github-AALJ7IEM.js.map → github-WHNAVVG3.js.map} +1 -1
  58. package/{goal-CFSXEKHU.js → goal-G4J2BQ5Z.js} +8 -7
  59. package/{goal-CFSXEKHU.js.map → goal-G4J2BQ5Z.js.map} +1 -1
  60. package/{host-6NKXFQCO.js → host-3W6U2ZUP.js} +8 -7
  61. package/{host-6NKXFQCO.js.map → host-3W6U2ZUP.js.map} +1 -1
  62. package/{intro-MIVVJG7M.js → intro-PMHOBGDL.js} +3 -3
  63. package/{logs-F4KPELTF.js → logs-P7JLTGXY.js} +10 -9
  64. package/{logs-F4KPELTF.js.map → logs-P7JLTGXY.js.map} +1 -1
  65. package/{mail-RZTLZU3I.js → mail-LIAOXDD4.js} +12 -11
  66. package/{mail-RZTLZU3I.js.map → mail-LIAOXDD4.js.map} +1 -1
  67. package/{maps-QRHGR33R.js → maps-C4NOXSE7.js} +8 -7
  68. package/{maps-QRHGR33R.js.map → maps-C4NOXSE7.js.map} +1 -1
  69. package/{model-6N5VPIS5.js → model-I2MNQ5KC.js} +9 -8
  70. package/{model-6N5VPIS5.js.map → model-I2MNQ5KC.js.map} +1 -1
  71. package/{model-provider-UZO32ZTC.js → model-provider-AOCCHEMP.js} +9 -8
  72. package/{model-provider-UZO32ZTC.js.map → model-provider-AOCCHEMP.js.map} +1 -1
  73. package/{org-26ZL2W2U.js → org-MVBG3WXZ.js} +9 -8
  74. package/{org-26ZL2W2U.js.map → org-MVBG3WXZ.js.map} +1 -1
  75. package/package.json +1 -1
  76. package/{phone-QTRZLYIG.js → phone-4OZQFYHU.js} +8 -7
  77. package/{phone-QTRZLYIG.js.map → phone-4OZQFYHU.js.map} +1 -1
  78. package/{preference-JCFTTUBN.js → preference-H2A3WBGQ.js} +9 -8
  79. package/{preference-JCFTTUBN.js.map → preference-H2A3WBGQ.js.map} +1 -1
  80. package/{resource-64R7T4FF.js → resource-CPCQ6V6M.js} +9 -8
  81. package/{resource-64R7T4FF.js.map → resource-CPCQ6V6M.js.map} +1 -1
  82. package/{scrape-LVGJ56IS.js → scrape-6RMFDYAT.js} +8 -7
  83. package/{scrape-LVGJ56IS.js.map → scrape-6RMFDYAT.js.map} +1 -1
  84. package/{search-TRISF64L.js → search-HSQVSQZY.js} +10 -9
  85. package/{search-TRISF64L.js.map → search-HSQVSQZY.js.map} +1 -1
  86. package/{secret-UAJDU3SX.js → secret-S4D6CNOX.js} +9 -8
  87. package/{secret-UAJDU3SX.js.map → secret-S4D6CNOX.js.map} +1 -1
  88. package/{slack-PDOPNS5Z.js → slack-E3E2NIDZ.js} +50 -175
  89. package/slack-E3E2NIDZ.js.map +1 -0
  90. package/{teams-BL36IS5U.js → teams-CLEWT2LQ.js} +8 -7
  91. package/{teams-BL36IS5U.js.map → teams-CLEWT2LQ.js.map} +1 -1
  92. package/{telegram-X7YTUVNV.js → telegram-35FKKA4K.js} +8 -7
  93. package/{telegram-X7YTUVNV.js.map → telegram-35FKKA4K.js.map} +1 -1
  94. package/{undici-ZMFN7TNU.js → undici-YXSVPIYI.js} +2 -2
  95. package/upgrade-DNGUR42E.js +50 -0
  96. package/upgrade-DNGUR42E.js.map +1 -0
  97. package/{variable-EBCBNZSU.js → variable-C7RWUPV6.js} +9 -8
  98. package/{variable-EBCBNZSU.js.map → variable-C7RWUPV6.js.map} +1 -1
  99. package/{video-3HFJJJEE.js → video-JS5VOA2S.js} +9 -7
  100. package/{video-3HFJJJEE.js.map → video-JS5VOA2S.js.map} +1 -1
  101. package/{weather-Y37FKFKU.js → weather-5R2N5OX4.js} +8 -7
  102. package/{weather-Y37FKFKU.js.map → weather-5R2N5OX4.js.map} +1 -1
  103. package/{web-ZEWEVAI3.js → web-FXIIYCZ7.js} +10 -8
  104. package/{web-ZEWEVAI3.js.map → web-FXIIYCZ7.js.map} +1 -1
  105. package/{web-search-37SGCKB7.js → web-search-SZP7J4UM.js} +8 -7
  106. package/{web-search-37SGCKB7.js.map → web-search-SZP7J4UM.js.map} +1 -1
  107. package/{whoami-VZI6VS4C.js → whoami-J4FRN67A.js} +10 -9
  108. package/{whoami-VZI6VS4C.js.map → whoami-J4FRN67A.js.map} +1 -1
  109. package/{workflow-3WGBRMM5.js → workflow-HQHZKXB2.js} +9 -8
  110. package/{workflow-3WGBRMM5.js.map → workflow-HQHZKXB2.js.map} +1 -1
  111. package/zero.js +88 -61
  112. package/zero.js.map +1 -1
  113. package/chunk-KQN5YZZP.js.map +0 -1
  114. package/chunk-L63QVTYZ.js.map +0 -1
  115. package/chunk-LRHXR7JT.js +0 -33
  116. package/chunk-LRHXR7JT.js.map +0 -1
  117. package/chunk-PLOJYRFL.js.map +0 -1
  118. package/credit-LGMFDRFK.js +0 -128
  119. package/credit-LGMFDRFK.js.map +0 -1
  120. package/doctor-CS5TFE6A.js.map +0 -1
  121. package/generate-4FEC4YVM.js.map +0 -1
  122. package/slack-PDOPNS5Z.js.map +0 -1
  123. /package/{chunk-FF5L22OE.js.map → chunk-5CZNUTFF.js.map} +0 -0
  124. /package/{chunk-J2I5GYLR.js.map → chunk-AFNSFKAH.js.map} +0 -0
  125. /package/{chunk-KLIW3XK7.js.map → chunk-GPF7NSX7.js.map} +0 -0
  126. /package/{chunk-HUMR2SA3.js.map → chunk-HSGQT7LT.js.map} +0 -0
  127. /package/{chunk-SAW74AR6.js.map → chunk-JCLLQRCI.js.map} +0 -0
  128. /package/{chunk-B3W2RUBP.js.map → chunk-LD4ZVU4O.js.map} +0 -0
  129. /package/{chunk-LTDQISD7.js.map → chunk-SB7EZ2ZO.js.map} +0 -0
  130. /package/{chunk-RTYT3CSZ.js.map → chunk-UG5XA6KU.js.map} +0 -0
  131. /package/{chunk-LKDE4AUC.js.map → chunk-UNQJRTJQ.js.map} +0 -0
  132. /package/{chunk-JFY6GK7Y.js.map → chunk-X2545RBX.js.map} +0 -0
  133. /package/{chunk-ZE2VIESK.js.map → chunk-X4DBCBU4.js.map} +0 -0
  134. /package/{esm-PZKPCIYJ.js.map → esm-GOCEMHJO.js.map} +0 -0
  135. /package/{getMachineId-bsd-L73QENVB.js.map → getMachineId-bsd-SB7C44VX.js.map} +0 -0
  136. /package/{getMachineId-darwin-TCCWKQ2S.js.map → getMachineId-darwin-R4BWY3CQ.js.map} +0 -0
  137. /package/{getMachineId-linux-TJYYUZVM.js.map → getMachineId-linux-BR4HVNPW.js.map} +0 -0
  138. /package/{getMachineId-unsupported-DPRVLH4Y.js.map → getMachineId-unsupported-FPGM635L.js.map} +0 -0
  139. /package/{getMachineId-win-7EE436CJ.js.map → getMachineId-win-RB4JMF33.js.map} +0 -0
  140. /package/{intro-MIVVJG7M.js.map → intro-PMHOBGDL.js.map} +0 -0
  141. /package/{undici-ZMFN7TNU.js.map → undici-YXSVPIYI.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/zero/teams/index.ts","../src/commands/zero/teams/message/index.ts","../src/commands/zero/teams/message/send.ts","../src/commands/zero/teams/upload-file.ts","../src/commands/zero/teams/download-file.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { zeroTeamsMessageCommand } from \"./message\";\nimport { uploadFileCommand } from \"./upload-file\";\nimport { downloadFileCommand } from \"./download-file\";\n\nexport const zeroTeamsCommand = new Command()\n .name(\"teams\")\n .description(\n \"Send messages, upload files, and download files from Microsoft Teams as the bot\",\n )\n .addCommand(zeroTeamsMessageCommand)\n .addCommand(uploadFileCommand)\n .addCommand(downloadFileCommand)\n .addHelpText(\n \"after\",\n `\nExamples:\n Send a message: zero teams message send -c <conversation-id> -t \"Hello!\"\n DM a user: zero teams message send -u me -t \"Hello!\"\n Reply in a thread: zero teams message send -c <conversation-id> --thread <activity-id> -t \"reply\"\n Upload a file: zero teams upload-file -f /tmp/report.pdf -c <conversation-id>\n Download a file: zero teams download-file <file-id> -o /tmp/out.png`,\n );\n","import { Command } from \"commander\";\nimport { sendCommand } from \"./send\";\n\nexport const zeroTeamsMessageCommand = new Command()\n .name(\"message\")\n .description(\"Manage Microsoft Teams messages\")\n .addCommand(sendCommand)\n .addHelpText(\n \"after\",\n `\nExamples:\n zero teams message send -c <conversation-id> -t \"Hello!\"\n zero teams message send -u me -t \"Hello!\"`,\n );\n","import { readFileSync } from \"fs\";\nimport { Command } from \"commander\";\nimport type { SendTeamsMessageBody } from \"@vm0/api-contracts/contracts/integrations\";\nimport chalk from \"chalk\";\nimport { sendTeamsMessage } from \"../../../../lib/api\";\nimport { withErrorHandler } from \"../../../../lib/command\";\n\ntype TeamsCardInput = NonNullable<SendTeamsMessageBody[\"card\"]>;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction parseTeamsCard(value: string): TeamsCardInput {\n let parsed: unknown;\n try {\n parsed = JSON.parse(value);\n } catch {\n throw new Error(\"Invalid JSON for --card flag\", {\n cause: new Error(\"Provide a valid Adaptive Card JSON object\"),\n });\n }\n\n if (\n !isRecord(parsed) ||\n parsed.type !== \"AdaptiveCard\" ||\n typeof parsed.version !== \"string\"\n ) {\n throw new Error(\"Invalid Adaptive Card for --card flag\", {\n cause: new Error(\n 'Provide a JSON object with \"type\": \"AdaptiveCard\" and a version',\n ),\n });\n }\n\n return parsed as TeamsCardInput;\n}\n\nexport const sendCommand = new Command()\n .name(\"send\")\n .description(\"Send a message to a Microsoft Teams conversation or DM a user\")\n .option(\"-c, --conversation-id <id>\", \"Teams conversation ID\")\n .option(\"-u, --user <id>\", 'Teams user ID for DM (use \"me\" for yourself)')\n .option(\"-t, --text <message>\", \"Message text\")\n .option(\"--activity-id <id>\", \"Activity ID to reply to\")\n .option(\"--thread <id>\", \"Alias for --activity-id\")\n .option(\"--card <json>\", \"Adaptive Card JSON string\")\n .addHelpText(\n \"after\",\n `\nExamples:\n Simple message: zero teams message send -c 19:thread@thread.tacv2 -t \"Hello!\"\n DM a user: zero teams message send -u 29:user-id -t \"Hello!\"\n DM yourself: zero teams message send -u me -t \"Hello!\"\n Thread reply: zero teams message send -c 19:thread@thread.tacv2 --thread root-activity -t \"reply\"\n Adaptive Card: zero teams message send -c 19:thread@thread.tacv2 --card '{\"type\":\"AdaptiveCard\",\"version\":\"1.4\",\"body\":[{\"type\":\"TextBlock\",\"text\":\"Hello\",\"wrap\":true}]}'\n\nNotes:\n - Either --conversation-id or --user is required; they are mutually exclusive\n - Either --text or --card is required; text can be provided with --text or piped on stdin\n - Use the Conversation ID and Activity ID from the current Teams run prompt`,\n )\n .action(\n withErrorHandler(\n async (options: {\n conversationId?: string;\n user?: string;\n text?: string;\n activityId?: string;\n thread?: string;\n card?: string;\n }) => {\n let text = options.text;\n const { conversationId, user, card: cardJson } = options;\n\n if (!conversationId && !user) {\n throw new Error(\n \"Either --conversation-id or --user must be provided\",\n {\n cause: new Error(\n 'Usage: zero teams message send -c CONVERSATION_ID -t \"your message\"\\n zero teams message send -u USER_ID -t \"your message\"',\n ),\n },\n );\n }\n if (conversationId && user) {\n throw new Error(\n \"--conversation-id and --user are mutually exclusive\",\n {\n cause: new Error(\n \"Provide either --conversation-id to send to a conversation or --user to DM a user, not both\",\n ),\n },\n );\n }\n\n const activityId = options.activityId ?? options.thread;\n if (user && activityId) {\n throw new Error(\n \"--activity-id and --thread can only be used with --conversation-id\",\n {\n cause: new Error(\n \"Thread replies require an existing Teams conversation\",\n ),\n },\n );\n }\n\n if (!text && !process.stdin.isTTY) {\n try {\n text = readFileSync(\"/dev/stdin\", \"utf8\").trim();\n } catch {\n // stdin not readable; fall through to the missing-text validation.\n }\n }\n\n const card = cardJson ? parseTeamsCard(cardJson) : undefined;\n\n if (!text && !card) {\n throw new Error(\n \"Either --text, --card, or piped stdin must be provided\",\n {\n cause: new Error(\n 'Usage: zero teams message send -c CONVERSATION_ID -t \"your message\"',\n ),\n },\n );\n }\n\n const body: SendTeamsMessageBody = {\n ...(conversationId ? { conversationId } : { user }),\n ...(activityId ? { activityId } : {}),\n ...(text ? { text } : {}),\n ...(card ? { card } : {}),\n };\n const result = await sendTeamsMessage({\n ...body,\n });\n\n const activityInfo = result.activityId\n ? ` (activity_id: ${result.activityId})`\n : \"\";\n console.log(chalk.green(`✓ Message sent${activityInfo}`));\n },\n ),\n );\n","import { readFileSync, statSync } from \"fs\";\nimport { basename, extname } from \"path\";\nimport { Command } from \"commander\";\nimport { completeTeamsFileUpload, initTeamsFileUpload } from \"../../../lib/api\";\nimport { withErrorHandler } from \"../../../lib/command\";\n\nconst MIME_BY_EXTENSION: Record<string, string> = {\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".webp\": \"image/webp\",\n \".svg\": \"image/svg+xml\",\n \".mp4\": \"video/mp4\",\n \".webm\": \"video/webm\",\n \".mov\": \"video/quicktime\",\n \".pdf\": \"application/pdf\",\n \".txt\": \"text/plain\",\n \".csv\": \"text/csv\",\n \".md\": \"text/markdown\",\n \".json\": \"application/json\",\n};\n\nfunction inferContentType(localPath: string): string {\n const ext = extname(localPath).toLowerCase();\n return MIME_BY_EXTENSION[ext] ?? \"application/octet-stream\";\n}\n\nexport const uploadFileCommand = new Command()\n .name(\"upload-file\")\n .description(\n \"Upload a local file to a Microsoft Teams conversation as the bot\",\n )\n .requiredOption(\"-f, --file <path>\", \"Local file path to upload\")\n .requiredOption(\"-c, --conversation-id <id>\", \"Teams conversation ID\")\n .option(\"--activity-id <id>\", \"Activity ID to reply to\")\n .option(\"-t, --text <message>\", \"Message text to accompany the file\")\n .option(\"--content-type <mime>\", \"Override inferred content type\")\n .addHelpText(\n \"after\",\n `\nExamples:\n Upload a file: zero teams upload-file -f /tmp/report.pdf -c 19:thread@thread.tacv2\n Upload to thread: zero teams upload-file -f /tmp/log.txt -c 19:thread@thread.tacv2 --activity-id root-activity\n With message text: zero teams upload-file -f /tmp/data.csv -c 19:thread@thread.tacv2 -t \"Daily report\"\n\nOutput:\n Prints a JSON object to stdout on success:\n {\"activityId\":\"...\",\"conversationId\":\"19:...\",\"filename\":\"report.pdf\",\"mimetype\":\"application/pdf\",\"size\":12345,\"url\":\"https://...\"}\n\nNotes:\n - Uploads through VM0 storage first, then sends the Teams message with the file URL\n - Use the Conversation ID and Activity ID from the current Teams run prompt`,\n )\n .action(\n withErrorHandler(\n async (options: {\n file: string;\n conversationId: string;\n activityId?: string;\n text?: string;\n contentType?: string;\n }) => {\n let fileSize: number;\n try {\n const stat = statSync(options.file);\n if (!stat.isFile()) {\n throw new Error(`Not a regular file: ${options.file}`);\n }\n fileSize = stat.size;\n } catch (error) {\n if (error instanceof Error && error.message.startsWith(\"Not \")) {\n throw error;\n }\n throw new Error(`File not found: ${options.file}`);\n }\n\n if (fileSize === 0) {\n throw new Error(\"File is empty\");\n }\n\n const filename = basename(options.file);\n const contentType =\n options.contentType ?? inferContentType(options.file);\n const prepared = await initTeamsFileUpload({\n filename,\n contentType,\n length: fileSize,\n });\n\n const fileContent = readFileSync(options.file);\n const uploadResponse = await fetch(prepared.uploadUrl, {\n method: \"PUT\",\n headers: { \"Content-Type\": prepared.contentType },\n body: new Uint8Array(fileContent),\n });\n\n if (!uploadResponse.ok) {\n throw new Error(\n `File upload failed: ${uploadResponse.status} ${uploadResponse.statusText}`,\n );\n }\n\n const result = await completeTeamsFileUpload({\n uploadId: prepared.uploadId,\n conversationId: options.conversationId,\n activityId: options.activityId,\n contentType: prepared.contentType,\n text: options.text,\n });\n\n console.log(JSON.stringify(result));\n },\n ),\n );\n","import { basename, join } from \"path\";\nimport { tmpdir } from \"os\";\nimport { Command } from \"commander\";\nimport { downloadTeamsFile } from \"../../../lib/api\";\nimport { withErrorHandler } from \"../../../lib/command\";\n\nfunction defaultOutPath(fileId: string): string {\n return join(tmpdir(), `teams-${basename(fileId).slice(0, 48)}`);\n}\n\nexport const downloadFileCommand = new Command()\n .name(\"download-file\")\n .description(\"Download a Microsoft Teams file by signed file id\")\n .argument(\"<file-id>\", \"Microsoft Teams file id from a [Teams file] block\")\n .option(\n \"-o, --out <path>\",\n \"Output path for the downloaded file (default: /tmp/teams-<file-id>)\",\n )\n .addHelpText(\n \"after\",\n `\nExamples:\n Download to default temp path: zero teams download-file <file-id>\n Download to explicit path: zero teams download-file <file-id> -o /tmp/file.png\n\nOutput:\n Prints a JSON object to stdout on success:\n {\"path\":\"/tmp/teams-...\",\"mimetype\":\"image/png\",\"size\":12345}\n\nNotes:\n - Use the file id from a [Teams file] block in the prompt\n - Streams the file bytes directly to disk`,\n )\n .action(\n withErrorHandler(async (fileId: string, options: { out?: string }) => {\n const outPath = options.out ?? defaultOutPath(fileId);\n const result = await downloadTeamsFile(fileId, outPath);\n console.log(JSON.stringify(result));\n }),\n );\n"],"mappings":"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","names":["readFileSync","readFileSync","basename","basename"]}
1
+ {"version":3,"sources":["../src/commands/zero/teams/index.ts","../src/commands/zero/teams/message/index.ts","../src/commands/zero/teams/message/send.ts","../src/commands/zero/teams/upload-file.ts","../src/commands/zero/teams/download-file.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { zeroTeamsMessageCommand } from \"./message\";\nimport { uploadFileCommand } from \"./upload-file\";\nimport { downloadFileCommand } from \"./download-file\";\n\nexport const zeroTeamsCommand = new Command()\n .name(\"teams\")\n .description(\n \"Send messages, upload files, and download files from Microsoft Teams as the bot\",\n )\n .addCommand(zeroTeamsMessageCommand)\n .addCommand(uploadFileCommand)\n .addCommand(downloadFileCommand)\n .addHelpText(\n \"after\",\n `\nExamples:\n Send a message: zero teams message send -c <conversation-id> -t \"Hello!\"\n DM a user: zero teams message send -u me -t \"Hello!\"\n Reply in a thread: zero teams message send -c <conversation-id> --thread <activity-id> -t \"reply\"\n Upload a file: zero teams upload-file -f /tmp/report.pdf -c <conversation-id>\n Download a file: zero teams download-file <file-id> -o /tmp/out.png`,\n );\n","import { Command } from \"commander\";\nimport { sendCommand } from \"./send\";\n\nexport const zeroTeamsMessageCommand = new Command()\n .name(\"message\")\n .description(\"Manage Microsoft Teams messages\")\n .addCommand(sendCommand)\n .addHelpText(\n \"after\",\n `\nExamples:\n zero teams message send -c <conversation-id> -t \"Hello!\"\n zero teams message send -u me -t \"Hello!\"`,\n );\n","import { readFileSync } from \"fs\";\nimport { Command } from \"commander\";\nimport type { SendTeamsMessageBody } from \"@vm0/api-contracts/contracts/integrations\";\nimport chalk from \"chalk\";\nimport { sendTeamsMessage } from \"../../../../lib/api\";\nimport { withErrorHandler } from \"../../../../lib/command\";\n\ntype TeamsCardInput = NonNullable<SendTeamsMessageBody[\"card\"]>;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction parseTeamsCard(value: string): TeamsCardInput {\n let parsed: unknown;\n try {\n parsed = JSON.parse(value);\n } catch {\n throw new Error(\"Invalid JSON for --card flag\", {\n cause: new Error(\"Provide a valid Adaptive Card JSON object\"),\n });\n }\n\n if (\n !isRecord(parsed) ||\n parsed.type !== \"AdaptiveCard\" ||\n typeof parsed.version !== \"string\"\n ) {\n throw new Error(\"Invalid Adaptive Card for --card flag\", {\n cause: new Error(\n 'Provide a JSON object with \"type\": \"AdaptiveCard\" and a version',\n ),\n });\n }\n\n return parsed as TeamsCardInput;\n}\n\nexport const sendCommand = new Command()\n .name(\"send\")\n .description(\"Send a message to a Microsoft Teams conversation or DM a user\")\n .option(\"-c, --conversation-id <id>\", \"Teams conversation ID\")\n .option(\"-u, --user <id>\", 'Teams user ID for DM (use \"me\" for yourself)')\n .option(\"-t, --text <message>\", \"Message text\")\n .option(\"--activity-id <id>\", \"Activity ID to reply to\")\n .option(\"--thread <id>\", \"Alias for --activity-id\")\n .option(\"--card <json>\", \"Adaptive Card JSON string\")\n .addHelpText(\n \"after\",\n `\nExamples:\n Simple message: zero teams message send -c 19:thread@thread.tacv2 -t \"Hello!\"\n DM a user: zero teams message send -u 29:user-id -t \"Hello!\"\n DM yourself: zero teams message send -u me -t \"Hello!\"\n Thread reply: zero teams message send -c 19:thread@thread.tacv2 --thread root-activity -t \"reply\"\n Adaptive Card: zero teams message send -c 19:thread@thread.tacv2 --card '{\"type\":\"AdaptiveCard\",\"version\":\"1.4\",\"body\":[{\"type\":\"TextBlock\",\"text\":\"Hello\",\"wrap\":true}]}'\n\nNotes:\n - Either --conversation-id or --user is required; they are mutually exclusive\n - Either --text or --card is required; text can be provided with --text or piped on stdin\n - Use the Conversation ID and Activity ID from the current Teams run prompt`,\n )\n .action(\n withErrorHandler(\n async (options: {\n conversationId?: string;\n user?: string;\n text?: string;\n activityId?: string;\n thread?: string;\n card?: string;\n }) => {\n let text = options.text;\n const { conversationId, user, card: cardJson } = options;\n\n if (!conversationId && !user) {\n throw new Error(\n \"Either --conversation-id or --user must be provided\",\n {\n cause: new Error(\n 'Usage: zero teams message send -c CONVERSATION_ID -t \"your message\"\\n zero teams message send -u USER_ID -t \"your message\"',\n ),\n },\n );\n }\n if (conversationId && user) {\n throw new Error(\n \"--conversation-id and --user are mutually exclusive\",\n {\n cause: new Error(\n \"Provide either --conversation-id to send to a conversation or --user to DM a user, not both\",\n ),\n },\n );\n }\n\n const activityId = options.activityId ?? options.thread;\n if (user && activityId) {\n throw new Error(\n \"--activity-id and --thread can only be used with --conversation-id\",\n {\n cause: new Error(\n \"Thread replies require an existing Teams conversation\",\n ),\n },\n );\n }\n\n if (!text && !process.stdin.isTTY) {\n try {\n text = readFileSync(\"/dev/stdin\", \"utf8\").trim();\n } catch {\n // stdin not readable; fall through to the missing-text validation.\n }\n }\n\n const card = cardJson ? parseTeamsCard(cardJson) : undefined;\n\n if (!text && !card) {\n throw new Error(\n \"Either --text, --card, or piped stdin must be provided\",\n {\n cause: new Error(\n 'Usage: zero teams message send -c CONVERSATION_ID -t \"your message\"',\n ),\n },\n );\n }\n\n const body: SendTeamsMessageBody = {\n ...(conversationId ? { conversationId } : { user }),\n ...(activityId ? { activityId } : {}),\n ...(text ? { text } : {}),\n ...(card ? { card } : {}),\n };\n const result = await sendTeamsMessage({\n ...body,\n });\n\n const activityInfo = result.activityId\n ? ` (activity_id: ${result.activityId})`\n : \"\";\n console.log(chalk.green(`✓ Message sent${activityInfo}`));\n },\n ),\n );\n","import { readFileSync, statSync } from \"fs\";\nimport { basename, extname } from \"path\";\nimport { Command } from \"commander\";\nimport { completeTeamsFileUpload, initTeamsFileUpload } from \"../../../lib/api\";\nimport { withErrorHandler } from \"../../../lib/command\";\n\nconst MIME_BY_EXTENSION: Record<string, string> = {\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".webp\": \"image/webp\",\n \".svg\": \"image/svg+xml\",\n \".mp4\": \"video/mp4\",\n \".webm\": \"video/webm\",\n \".mov\": \"video/quicktime\",\n \".pdf\": \"application/pdf\",\n \".txt\": \"text/plain\",\n \".csv\": \"text/csv\",\n \".md\": \"text/markdown\",\n \".json\": \"application/json\",\n};\n\nfunction inferContentType(localPath: string): string {\n const ext = extname(localPath).toLowerCase();\n return MIME_BY_EXTENSION[ext] ?? \"application/octet-stream\";\n}\n\nexport const uploadFileCommand = new Command()\n .name(\"upload-file\")\n .description(\n \"Upload a local file to a Microsoft Teams conversation as the bot\",\n )\n .requiredOption(\"-f, --file <path>\", \"Local file path to upload\")\n .requiredOption(\"-c, --conversation-id <id>\", \"Teams conversation ID\")\n .option(\"--activity-id <id>\", \"Activity ID to reply to\")\n .option(\"-t, --text <message>\", \"Message text to accompany the file\")\n .option(\"--content-type <mime>\", \"Override inferred content type\")\n .addHelpText(\n \"after\",\n `\nExamples:\n Upload a file: zero teams upload-file -f /tmp/report.pdf -c 19:thread@thread.tacv2\n Upload to thread: zero teams upload-file -f /tmp/log.txt -c 19:thread@thread.tacv2 --activity-id root-activity\n With message text: zero teams upload-file -f /tmp/data.csv -c 19:thread@thread.tacv2 -t \"Daily report\"\n\nOutput:\n Prints a JSON object to stdout on success:\n {\"activityId\":\"...\",\"conversationId\":\"19:...\",\"filename\":\"report.pdf\",\"mimetype\":\"application/pdf\",\"size\":12345,\"url\":\"https://...\"}\n\nNotes:\n - Uploads through VM0 storage first, then sends the Teams message with the file URL\n - Use the Conversation ID and Activity ID from the current Teams run prompt`,\n )\n .action(\n withErrorHandler(\n async (options: {\n file: string;\n conversationId: string;\n activityId?: string;\n text?: string;\n contentType?: string;\n }) => {\n let fileSize: number;\n try {\n const stat = statSync(options.file);\n if (!stat.isFile()) {\n throw new Error(`Not a regular file: ${options.file}`);\n }\n fileSize = stat.size;\n } catch (error) {\n if (error instanceof Error && error.message.startsWith(\"Not \")) {\n throw error;\n }\n throw new Error(`File not found: ${options.file}`);\n }\n\n if (fileSize === 0) {\n throw new Error(\"File is empty\");\n }\n\n const filename = basename(options.file);\n const contentType =\n options.contentType ?? inferContentType(options.file);\n const prepared = await initTeamsFileUpload({\n filename,\n contentType,\n length: fileSize,\n });\n\n const fileContent = readFileSync(options.file);\n const uploadResponse = await fetch(prepared.uploadUrl, {\n method: \"PUT\",\n headers: { \"Content-Type\": prepared.contentType },\n body: new Uint8Array(fileContent),\n });\n\n if (!uploadResponse.ok) {\n throw new Error(\n `File upload failed: ${uploadResponse.status} ${uploadResponse.statusText}`,\n );\n }\n\n const result = await completeTeamsFileUpload({\n uploadId: prepared.uploadId,\n conversationId: options.conversationId,\n activityId: options.activityId,\n contentType: prepared.contentType,\n text: options.text,\n });\n\n console.log(JSON.stringify(result));\n },\n ),\n );\n","import { basename, join } from \"path\";\nimport { tmpdir } from \"os\";\nimport { Command } from \"commander\";\nimport { downloadTeamsFile } from \"../../../lib/api\";\nimport { withErrorHandler } from \"../../../lib/command\";\n\nfunction defaultOutPath(fileId: string): string {\n return join(tmpdir(), `teams-${basename(fileId).slice(0, 48)}`);\n}\n\nexport const downloadFileCommand = new Command()\n .name(\"download-file\")\n .description(\"Download a Microsoft Teams file by signed file id\")\n .argument(\"<file-id>\", \"Microsoft Teams file id from a [Teams file] block\")\n .option(\n \"-o, --out <path>\",\n \"Output path for the downloaded file (default: /tmp/teams-<file-id>)\",\n )\n .addHelpText(\n \"after\",\n `\nExamples:\n Download to default temp path: zero teams download-file <file-id>\n Download to explicit path: zero teams download-file <file-id> -o /tmp/file.png\n\nOutput:\n Prints a JSON object to stdout on success:\n {\"path\":\"/tmp/teams-...\",\"mimetype\":\"image/png\",\"size\":12345}\n\nNotes:\n - Use the file id from a [Teams file] block in the prompt\n - Streams the file bytes directly to disk`,\n )\n .action(\n withErrorHandler(async (fileId: string, options: { out?: string }) => {\n const outPath = options.out ?? defaultOutPath(fileId);\n const result = await downloadTeamsFile(fileId, outPath);\n console.log(JSON.stringify(result));\n }),\n );\n"],"mappings":"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","names":["readFileSync","readFileSync","basename","basename"]}
@@ -7,19 +7,20 @@ import {
7
7
  initTelegramFileUpload,
8
8
  listTelegramBots,
9
9
  sendTelegramMessage
10
- } from "./chunk-KQN5YZZP.js";
11
- import "./chunk-LTDQISD7.js";
10
+ } from "./chunk-ROB3OE37.js";
11
+ import "./chunk-N6TDQYGF.js";
12
+ import "./chunk-SB7EZ2ZO.js";
12
13
  import {
13
14
  source_default,
14
15
  withErrorHandler
15
- } from "./chunk-L63QVTYZ.js";
16
- import "./chunk-LRHXR7JT.js";
16
+ } from "./chunk-BQOOTJNB.js";
17
+ import "./chunk-A2NKQGRI.js";
17
18
  import {
18
19
  Command
19
- } from "./chunk-B3W2RUBP.js";
20
+ } from "./chunk-LD4ZVU4O.js";
20
21
  import {
21
22
  init_esm_shims
22
- } from "./chunk-DIRAZ3YX.js";
23
+ } from "./chunk-3VVCUQPB.js";
23
24
 
24
25
  // src/commands/zero/telegram/index.ts
25
26
  init_esm_shims();
@@ -333,4 +334,4 @@ Examples:
333
334
  export {
334
335
  zeroTelegramCommand
335
336
  };
336
- //# sourceMappingURL=telegram-X7YTUVNV.js.map
337
+ //# sourceMappingURL=telegram-35FKKA4K.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/zero/telegram/index.ts","../src/commands/zero/telegram/bot/index.ts","../src/commands/zero/telegram/bot/list.ts","../src/commands/zero/telegram/download-file.ts","../src/commands/zero/telegram/message/index.ts","../src/commands/zero/telegram/message/send.ts","../src/commands/zero/telegram/upload-file.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { zeroTelegramBotCommand } from \"./bot\";\nimport { downloadFileCommand } from \"./download-file\";\nimport { zeroTelegramMessageCommand } from \"./message\";\nimport { uploadFileCommand } from \"./upload-file\";\n\nexport const zeroTelegramCommand = new Command()\n .name(\"telegram\")\n .description(\n \"Inspect bots, send messages, upload files, and download files from Telegram\",\n )\n .addCommand(zeroTelegramBotCommand)\n .addCommand(zeroTelegramMessageCommand)\n .addCommand(downloadFileCommand)\n .addCommand(uploadFileCommand)\n .addHelpText(\n \"after\",\n `\nExamples:\n List bots: zero telegram bot list\n Send a message: zero telegram message send --bot-id <bot-id> -c <chat-id> -t \"Hello!\"\n Upload a file: zero telegram upload-file -f /tmp/report.pdf --bot-id <bot-id> -c <chat-id>\n Download a file: zero telegram download-file <file-id> --bot-id <bot-id> -o /tmp/out.jpg`,\n );\n","import { Command } from \"commander\";\nimport { listCommand } from \"./list\";\n\nexport const zeroTelegramBotCommand = new Command()\n .name(\"bot\")\n .description(\"Inspect Telegram bots\")\n .addCommand(listCommand)\n .addHelpText(\n \"after\",\n `\nExamples:\n zero telegram bot list`,\n );\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { listTelegramBots } from \"../../../../lib/api\";\nimport { withErrorHandler } from \"../../../../lib/command\";\nimport type { TelegramBotListItem } from \"@vm0/api-contracts/contracts/integrations\";\n\nfunction usernameLabel(bot: TelegramBotListItem): string {\n if (!bot.username) return \"-\";\n return bot.username.startsWith(\"@\") ? bot.username : `@${bot.username}`;\n}\n\nfunction statusLabel(bot: TelegramBotListItem): string {\n if (bot.tokenStatus === \"valid\") return chalk.green(\"valid\");\n if (bot.tokenStatus === \"invalid\") return chalk.red(\"invalid\");\n return chalk.yellow(\"unknown\");\n}\n\nexport const listCommand = new Command()\n .name(\"list\")\n .alias(\"ls\")\n .description(\"List Telegram bots available in the active organization\")\n .addHelpText(\n \"after\",\n `\nExamples:\n zero telegram bot list\n\nNotes:\n - Use this to find the --bot-id value before sending Telegram messages.`,\n )\n .action(\n withErrorHandler(async () => {\n const result = await listTelegramBots();\n const { bots } = result;\n\n if (bots.length === 0) {\n console.log(chalk.dim(\"No Telegram bots found\"));\n console.log(\n chalk.dim(\" Add one from Settings > Integrations > Telegram\"),\n );\n return;\n }\n\n const botIdWidth = Math.max(\n 6,\n ...bots.map((bot) => {\n return bot.id.length;\n }),\n );\n const usernameWidth = Math.max(\n 8,\n ...bots.map((bot) => {\n return usernameLabel(bot).length;\n }),\n );\n const agentWidth = Math.max(\n 5,\n ...bots.map((bot) => {\n return (bot.agent?.name ?? \"-\").length;\n }),\n );\n\n const header = [\n \"BOT ID\".padEnd(botIdWidth),\n \"USERNAME\".padEnd(usernameWidth),\n \"AGENT\".padEnd(agentWidth),\n \"CONNECTED\",\n \"TOKEN\",\n ].join(\" \");\n console.log(chalk.dim(header));\n\n for (const bot of bots) {\n const row = [\n bot.id.padEnd(botIdWidth),\n usernameLabel(bot).padEnd(usernameWidth),\n (bot.agent?.name ?? \"-\").padEnd(agentWidth),\n (bot.isConnected ? \"yes\" : \"no\").padEnd(9),\n statusLabel(bot),\n ].join(\" \");\n console.log(row);\n }\n }),\n );\n","import { basename, join } from \"path\";\nimport { tmpdir } from \"os\";\nimport { Command } from \"commander\";\nimport { downloadTelegramFile } from \"../../../lib/api\";\nimport { withErrorHandler } from \"../../../lib/command\";\n\n/**\n * Derive a local output path for a Telegram file id.\n * Uses the system temp directory.\n *\n * `basename` strips any path separators from `fileId` so a hostile id like\n * `../etc/passwd` cannot escape `tmpdir()`.\n */\nfunction defaultOutPath(fileId: string): string {\n return join(tmpdir(), `telegram-${basename(fileId)}`);\n}\n\nexport const downloadFileCommand = new Command()\n .name(\"download-file\")\n .description(\"Download a Telegram file by id using the bot token\")\n .argument(\"<file-id>\", \"Telegram file id from a [Telegram file] block\")\n .option(\n \"-o, --out <path>\",\n \"Output path for the downloaded file (default: /tmp/telegram-<file-id>)\",\n )\n .requiredOption(\n \"--bot-id <bot-id>\",\n \"Telegram bot id from the [Telegram file] block\",\n )\n .addHelpText(\n \"after\",\n `\nExamples:\n Download to default temp path: zero telegram download-file AgACAgUAAxkBAA --bot-id 123456789\n Download to explicit path: zero telegram download-file AgACAgUAAxkBAA --bot-id 123456789 -o /tmp/photo.jpg\n\nOutput:\n Prints a JSON object to stdout on success:\n {\"path\":\"/tmp/telegram-AgACAgUAAxkBAA\",\"mimetype\":\"image/jpeg\",\"size\":12345}\n\nHow to read the downloaded file:\n - Images (png/jpg/gif/webp/svg): open the file path with your image viewing tool\n - Videos (mp4/mov/webm): transcribe audio first with\n zero video transcribe --url <download-url>\n or extract frames with\n ffmpeg -i <path> -vf \"fps=1\" -q:v 2 /tmp/<file-id>_frame_%03d.jpg\n - PDF/text/csv/json/markdown: read the file directly\n\nNotes:\n - Uses the Telegram bot token on the server side\n - Streams the file bytes directly to disk`,\n )\n .action(\n withErrorHandler(\n async (fileId: string, options: { out?: string; botId: string }) => {\n const outPath = options.out ?? defaultOutPath(fileId);\n const result = await downloadTelegramFile(\n fileId,\n options.botId,\n outPath,\n );\n console.log(JSON.stringify(result));\n },\n ),\n );\n","import { Command } from \"commander\";\nimport { sendCommand } from \"./send\";\n\nexport const zeroTelegramMessageCommand = new Command()\n .name(\"message\")\n .description(\"Manage Telegram messages\")\n .addCommand(sendCommand)\n .addHelpText(\n \"after\",\n `\nExamples:\n zero telegram message send --bot-id <bot-id> -c <chat-id> -t \"Hello!\"`,\n );\n","import { readFileSync } from \"fs\";\nimport { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { sendTelegramMessage } from \"../../../../lib/api\";\nimport { withErrorHandler } from \"../../../../lib/command\";\n\nfunction parsePositiveInteger(value: string, flag: string): number {\n const parsed = Number(value);\n if (!Number.isInteger(parsed) || parsed <= 0) {\n throw new Error(`${flag} must be a positive integer`);\n }\n return parsed;\n}\n\nexport const sendCommand = new Command()\n .name(\"send\")\n .description(\"Send a message to a Telegram chat as the bot\")\n .requiredOption(\"--bot-id <id>\", \"Telegram bot ID\")\n .requiredOption(\"-c, --chat-id <id>\", \"Telegram chat ID\")\n .option(\"-t, --text <message>\", \"Message text\")\n .option(\"--reply-to-message-id <id>\", \"Message ID to reply to\")\n .option(\"--message-thread-id <id>\", \"Telegram forum topic thread ID\")\n .addHelpText(\n \"after\",\n `\nExamples:\n Simple message: zero telegram message send --bot-id 123456789 -c -1001234567890 -t \"Hello!\"\n Reply to message: zero telegram message send --bot-id 123456789 -c -1001234567890 --reply-to-message-id 42 -t \"reply\"\n Forum topic message: zero telegram message send --bot-id 123456789 -c -1001234567890 --message-thread-id 7 -t \"topic update\"\n\nNotes:\n - Message text can be provided with --text or piped on stdin\n - Choose an explicit --bot-id. Run \"zero telegram bot list\" to inspect available bots.`,\n )\n .action(\n withErrorHandler(\n async (options: {\n botId: string;\n chatId: string;\n text?: string;\n replyToMessageId?: string;\n messageThreadId?: string;\n }) => {\n let text = options.text;\n if (!text && !process.stdin.isTTY) {\n try {\n text = readFileSync(\"/dev/stdin\", \"utf8\").trim();\n } catch {\n // stdin not readable (e.g. test runner with no piped input);\n // fall through to the missing-text validation below.\n }\n }\n\n if (!text) {\n throw new Error(\"Either --text or piped stdin must be provided\", {\n cause: new Error(\n 'Usage: zero telegram message send --bot-id BOT_ID -c CHAT_ID -t \"your message\"',\n ),\n });\n }\n\n const result = await sendTelegramMessage({\n botId: options.botId,\n chatId: options.chatId,\n text,\n replyToMessageId: options.replyToMessageId\n ? parsePositiveInteger(\n options.replyToMessageId,\n \"reply-to-message-id\",\n )\n : undefined,\n messageThreadId: options.messageThreadId\n ? parsePositiveInteger(options.messageThreadId, \"message-thread-id\")\n : undefined,\n });\n\n console.log(\n chalk.green(`✓ Message sent (message_id: ${result.messageId})`),\n );\n },\n ),\n );\n","import { readFileSync, statSync } from \"fs\";\nimport { basename, extname } from \"path\";\nimport { Command } from \"commander\";\nimport {\n completeTelegramFileUpload,\n initTelegramFileUpload,\n} from \"../../../lib/api\";\nimport { withErrorHandler } from \"../../../lib/command\";\n\nconst MIME_BY_EXTENSION: Record<string, string> = {\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".webp\": \"image/webp\",\n \".svg\": \"image/svg+xml\",\n \".mp4\": \"video/mp4\",\n \".webm\": \"video/webm\",\n \".mov\": \"video/quicktime\",\n \".pdf\": \"application/pdf\",\n \".txt\": \"text/plain\",\n \".csv\": \"text/csv\",\n \".md\": \"text/markdown\",\n \".json\": \"application/json\",\n};\n\nfunction inferContentType(localPath: string): string {\n const ext = extname(localPath).toLowerCase();\n return MIME_BY_EXTENSION[ext] ?? \"application/octet-stream\";\n}\n\nfunction parseMessageThreadId(value: string | undefined): number | undefined {\n if (!value) return undefined;\n const parsed = Number(value);\n if (!Number.isSafeInteger(parsed) || parsed <= 0) {\n throw new Error(\"message-thread-id must be a positive integer\");\n }\n return parsed;\n}\n\nexport const uploadFileCommand = new Command()\n .name(\"upload-file\")\n .description(\"Upload a local file to a Telegram chat as the bot\")\n .requiredOption(\"-f, --file <path>\", \"Local file path to upload\")\n .requiredOption(\"--bot-id <bot-id>\", \"Telegram bot id to send through\")\n .requiredOption(\"-c, --chat-id <chat-id>\", \"Telegram chat id or @channel\")\n .option(\"--caption <text>\", \"Caption to accompany the file\")\n .option(\"--message-thread-id <id>\", \"Forum topic message thread id\")\n .option(\"--content-type <mime>\", \"Override inferred content type\")\n .addHelpText(\n \"after\",\n `\nExamples:\n Upload a file: zero telegram upload-file -f /tmp/report.pdf --bot-id 123456789 -c -1001234567890\n Upload to a topic: zero telegram upload-file -f /tmp/log.txt --bot-id 123456789 -c -1001234567890 --message-thread-id 42\n With a caption: zero telegram upload-file -f /tmp/data.csv --bot-id 123456789 -c @channel --caption \"Daily report\"\n\nOutput:\n Prints a JSON object to stdout on success:\n {\"messageId\":123,\"chatId\":\"-1001234567890\",\"fileId\":\"...\",\"filename\":\"report.pdf\",\"mimetype\":\"application/pdf\",\"size\":12345,\"url\":\"https://...\"}\n\nNotes:\n - Uses the Telegram bot token on the server side\n - Uploads through VM0 storage first, then asks Telegram to fetch the file URL\n - VM0 does not apply file type or size restrictions before calling Telegram`,\n )\n .action(\n withErrorHandler(\n async (options: {\n file: string;\n botId: string;\n chatId: string;\n caption?: string;\n messageThreadId?: string;\n contentType?: string;\n }) => {\n let fileSize: number;\n try {\n const stat = statSync(options.file);\n if (!stat.isFile()) {\n throw new Error(`Not a regular file: ${options.file}`);\n }\n fileSize = stat.size;\n } catch (error) {\n if (error instanceof Error && error.message.startsWith(\"Not \")) {\n throw error;\n }\n throw new Error(`File not found: ${options.file}`);\n }\n\n if (fileSize === 0) {\n throw new Error(\"File is empty\");\n }\n const filename = basename(options.file);\n const contentType =\n options.contentType ?? inferContentType(options.file);\n const messageThreadId = parseMessageThreadId(options.messageThreadId);\n\n const prepared = await initTelegramFileUpload({\n filename,\n contentType,\n length: fileSize,\n });\n\n const fileContent = readFileSync(options.file);\n const uploadResponse = await fetch(prepared.uploadUrl, {\n method: \"PUT\",\n headers: { \"Content-Type\": prepared.contentType },\n body: new Uint8Array(fileContent),\n });\n\n if (!uploadResponse.ok) {\n throw new Error(\n `File upload failed: ${uploadResponse.status} ${uploadResponse.statusText}`,\n );\n }\n\n const result = await completeTelegramFileUpload({\n uploadId: prepared.uploadId,\n botId: options.botId,\n chatId: options.chatId,\n contentType: prepared.contentType,\n caption: options.caption,\n messageThreadId,\n });\n\n console.log(JSON.stringify(result));\n },\n ),\n );\n"],"mappings":"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","names":["readFileSync","basename","basename","readFileSync"]}
1
+ {"version":3,"sources":["../src/commands/zero/telegram/index.ts","../src/commands/zero/telegram/bot/index.ts","../src/commands/zero/telegram/bot/list.ts","../src/commands/zero/telegram/download-file.ts","../src/commands/zero/telegram/message/index.ts","../src/commands/zero/telegram/message/send.ts","../src/commands/zero/telegram/upload-file.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { zeroTelegramBotCommand } from \"./bot\";\nimport { downloadFileCommand } from \"./download-file\";\nimport { zeroTelegramMessageCommand } from \"./message\";\nimport { uploadFileCommand } from \"./upload-file\";\n\nexport const zeroTelegramCommand = new Command()\n .name(\"telegram\")\n .description(\n \"Inspect bots, send messages, upload files, and download files from Telegram\",\n )\n .addCommand(zeroTelegramBotCommand)\n .addCommand(zeroTelegramMessageCommand)\n .addCommand(downloadFileCommand)\n .addCommand(uploadFileCommand)\n .addHelpText(\n \"after\",\n `\nExamples:\n List bots: zero telegram bot list\n Send a message: zero telegram message send --bot-id <bot-id> -c <chat-id> -t \"Hello!\"\n Upload a file: zero telegram upload-file -f /tmp/report.pdf --bot-id <bot-id> -c <chat-id>\n Download a file: zero telegram download-file <file-id> --bot-id <bot-id> -o /tmp/out.jpg`,\n );\n","import { Command } from \"commander\";\nimport { listCommand } from \"./list\";\n\nexport const zeroTelegramBotCommand = new Command()\n .name(\"bot\")\n .description(\"Inspect Telegram bots\")\n .addCommand(listCommand)\n .addHelpText(\n \"after\",\n `\nExamples:\n zero telegram bot list`,\n );\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { listTelegramBots } from \"../../../../lib/api\";\nimport { withErrorHandler } from \"../../../../lib/command\";\nimport type { TelegramBotListItem } from \"@vm0/api-contracts/contracts/integrations\";\n\nfunction usernameLabel(bot: TelegramBotListItem): string {\n if (!bot.username) return \"-\";\n return bot.username.startsWith(\"@\") ? bot.username : `@${bot.username}`;\n}\n\nfunction statusLabel(bot: TelegramBotListItem): string {\n if (bot.tokenStatus === \"valid\") return chalk.green(\"valid\");\n if (bot.tokenStatus === \"invalid\") return chalk.red(\"invalid\");\n return chalk.yellow(\"unknown\");\n}\n\nexport const listCommand = new Command()\n .name(\"list\")\n .alias(\"ls\")\n .description(\"List Telegram bots available in the active organization\")\n .addHelpText(\n \"after\",\n `\nExamples:\n zero telegram bot list\n\nNotes:\n - Use this to find the --bot-id value before sending Telegram messages.`,\n )\n .action(\n withErrorHandler(async () => {\n const result = await listTelegramBots();\n const { bots } = result;\n\n if (bots.length === 0) {\n console.log(chalk.dim(\"No Telegram bots found\"));\n console.log(\n chalk.dim(\" Add one from Settings > Integrations > Telegram\"),\n );\n return;\n }\n\n const botIdWidth = Math.max(\n 6,\n ...bots.map((bot) => {\n return bot.id.length;\n }),\n );\n const usernameWidth = Math.max(\n 8,\n ...bots.map((bot) => {\n return usernameLabel(bot).length;\n }),\n );\n const agentWidth = Math.max(\n 5,\n ...bots.map((bot) => {\n return (bot.agent?.name ?? \"-\").length;\n }),\n );\n\n const header = [\n \"BOT ID\".padEnd(botIdWidth),\n \"USERNAME\".padEnd(usernameWidth),\n \"AGENT\".padEnd(agentWidth),\n \"CONNECTED\",\n \"TOKEN\",\n ].join(\" \");\n console.log(chalk.dim(header));\n\n for (const bot of bots) {\n const row = [\n bot.id.padEnd(botIdWidth),\n usernameLabel(bot).padEnd(usernameWidth),\n (bot.agent?.name ?? \"-\").padEnd(agentWidth),\n (bot.isConnected ? \"yes\" : \"no\").padEnd(9),\n statusLabel(bot),\n ].join(\" \");\n console.log(row);\n }\n }),\n );\n","import { basename, join } from \"path\";\nimport { tmpdir } from \"os\";\nimport { Command } from \"commander\";\nimport { downloadTelegramFile } from \"../../../lib/api\";\nimport { withErrorHandler } from \"../../../lib/command\";\n\n/**\n * Derive a local output path for a Telegram file id.\n * Uses the system temp directory.\n *\n * `basename` strips any path separators from `fileId` so a hostile id like\n * `../etc/passwd` cannot escape `tmpdir()`.\n */\nfunction defaultOutPath(fileId: string): string {\n return join(tmpdir(), `telegram-${basename(fileId)}`);\n}\n\nexport const downloadFileCommand = new Command()\n .name(\"download-file\")\n .description(\"Download a Telegram file by id using the bot token\")\n .argument(\"<file-id>\", \"Telegram file id from a [Telegram file] block\")\n .option(\n \"-o, --out <path>\",\n \"Output path for the downloaded file (default: /tmp/telegram-<file-id>)\",\n )\n .requiredOption(\n \"--bot-id <bot-id>\",\n \"Telegram bot id from the [Telegram file] block\",\n )\n .addHelpText(\n \"after\",\n `\nExamples:\n Download to default temp path: zero telegram download-file AgACAgUAAxkBAA --bot-id 123456789\n Download to explicit path: zero telegram download-file AgACAgUAAxkBAA --bot-id 123456789 -o /tmp/photo.jpg\n\nOutput:\n Prints a JSON object to stdout on success:\n {\"path\":\"/tmp/telegram-AgACAgUAAxkBAA\",\"mimetype\":\"image/jpeg\",\"size\":12345}\n\nHow to read the downloaded file:\n - Images (png/jpg/gif/webp/svg): open the file path with your image viewing tool\n - Videos (mp4/mov/webm): transcribe audio first with\n zero video transcribe --url <download-url>\n or extract frames with\n ffmpeg -i <path> -vf \"fps=1\" -q:v 2 /tmp/<file-id>_frame_%03d.jpg\n - PDF/text/csv/json/markdown: read the file directly\n\nNotes:\n - Uses the Telegram bot token on the server side\n - Streams the file bytes directly to disk`,\n )\n .action(\n withErrorHandler(\n async (fileId: string, options: { out?: string; botId: string }) => {\n const outPath = options.out ?? defaultOutPath(fileId);\n const result = await downloadTelegramFile(\n fileId,\n options.botId,\n outPath,\n );\n console.log(JSON.stringify(result));\n },\n ),\n );\n","import { Command } from \"commander\";\nimport { sendCommand } from \"./send\";\n\nexport const zeroTelegramMessageCommand = new Command()\n .name(\"message\")\n .description(\"Manage Telegram messages\")\n .addCommand(sendCommand)\n .addHelpText(\n \"after\",\n `\nExamples:\n zero telegram message send --bot-id <bot-id> -c <chat-id> -t \"Hello!\"`,\n );\n","import { readFileSync } from \"fs\";\nimport { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { sendTelegramMessage } from \"../../../../lib/api\";\nimport { withErrorHandler } from \"../../../../lib/command\";\n\nfunction parsePositiveInteger(value: string, flag: string): number {\n const parsed = Number(value);\n if (!Number.isInteger(parsed) || parsed <= 0) {\n throw new Error(`${flag} must be a positive integer`);\n }\n return parsed;\n}\n\nexport const sendCommand = new Command()\n .name(\"send\")\n .description(\"Send a message to a Telegram chat as the bot\")\n .requiredOption(\"--bot-id <id>\", \"Telegram bot ID\")\n .requiredOption(\"-c, --chat-id <id>\", \"Telegram chat ID\")\n .option(\"-t, --text <message>\", \"Message text\")\n .option(\"--reply-to-message-id <id>\", \"Message ID to reply to\")\n .option(\"--message-thread-id <id>\", \"Telegram forum topic thread ID\")\n .addHelpText(\n \"after\",\n `\nExamples:\n Simple message: zero telegram message send --bot-id 123456789 -c -1001234567890 -t \"Hello!\"\n Reply to message: zero telegram message send --bot-id 123456789 -c -1001234567890 --reply-to-message-id 42 -t \"reply\"\n Forum topic message: zero telegram message send --bot-id 123456789 -c -1001234567890 --message-thread-id 7 -t \"topic update\"\n\nNotes:\n - Message text can be provided with --text or piped on stdin\n - Choose an explicit --bot-id. Run \"zero telegram bot list\" to inspect available bots.`,\n )\n .action(\n withErrorHandler(\n async (options: {\n botId: string;\n chatId: string;\n text?: string;\n replyToMessageId?: string;\n messageThreadId?: string;\n }) => {\n let text = options.text;\n if (!text && !process.stdin.isTTY) {\n try {\n text = readFileSync(\"/dev/stdin\", \"utf8\").trim();\n } catch {\n // stdin not readable (e.g. test runner with no piped input);\n // fall through to the missing-text validation below.\n }\n }\n\n if (!text) {\n throw new Error(\"Either --text or piped stdin must be provided\", {\n cause: new Error(\n 'Usage: zero telegram message send --bot-id BOT_ID -c CHAT_ID -t \"your message\"',\n ),\n });\n }\n\n const result = await sendTelegramMessage({\n botId: options.botId,\n chatId: options.chatId,\n text,\n replyToMessageId: options.replyToMessageId\n ? parsePositiveInteger(\n options.replyToMessageId,\n \"reply-to-message-id\",\n )\n : undefined,\n messageThreadId: options.messageThreadId\n ? parsePositiveInteger(options.messageThreadId, \"message-thread-id\")\n : undefined,\n });\n\n console.log(\n chalk.green(`✓ Message sent (message_id: ${result.messageId})`),\n );\n },\n ),\n );\n","import { readFileSync, statSync } from \"fs\";\nimport { basename, extname } from \"path\";\nimport { Command } from \"commander\";\nimport {\n completeTelegramFileUpload,\n initTelegramFileUpload,\n} from \"../../../lib/api\";\nimport { withErrorHandler } from \"../../../lib/command\";\n\nconst MIME_BY_EXTENSION: Record<string, string> = {\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".webp\": \"image/webp\",\n \".svg\": \"image/svg+xml\",\n \".mp4\": \"video/mp4\",\n \".webm\": \"video/webm\",\n \".mov\": \"video/quicktime\",\n \".pdf\": \"application/pdf\",\n \".txt\": \"text/plain\",\n \".csv\": \"text/csv\",\n \".md\": \"text/markdown\",\n \".json\": \"application/json\",\n};\n\nfunction inferContentType(localPath: string): string {\n const ext = extname(localPath).toLowerCase();\n return MIME_BY_EXTENSION[ext] ?? \"application/octet-stream\";\n}\n\nfunction parseMessageThreadId(value: string | undefined): number | undefined {\n if (!value) return undefined;\n const parsed = Number(value);\n if (!Number.isSafeInteger(parsed) || parsed <= 0) {\n throw new Error(\"message-thread-id must be a positive integer\");\n }\n return parsed;\n}\n\nexport const uploadFileCommand = new Command()\n .name(\"upload-file\")\n .description(\"Upload a local file to a Telegram chat as the bot\")\n .requiredOption(\"-f, --file <path>\", \"Local file path to upload\")\n .requiredOption(\"--bot-id <bot-id>\", \"Telegram bot id to send through\")\n .requiredOption(\"-c, --chat-id <chat-id>\", \"Telegram chat id or @channel\")\n .option(\"--caption <text>\", \"Caption to accompany the file\")\n .option(\"--message-thread-id <id>\", \"Forum topic message thread id\")\n .option(\"--content-type <mime>\", \"Override inferred content type\")\n .addHelpText(\n \"after\",\n `\nExamples:\n Upload a file: zero telegram upload-file -f /tmp/report.pdf --bot-id 123456789 -c -1001234567890\n Upload to a topic: zero telegram upload-file -f /tmp/log.txt --bot-id 123456789 -c -1001234567890 --message-thread-id 42\n With a caption: zero telegram upload-file -f /tmp/data.csv --bot-id 123456789 -c @channel --caption \"Daily report\"\n\nOutput:\n Prints a JSON object to stdout on success:\n {\"messageId\":123,\"chatId\":\"-1001234567890\",\"fileId\":\"...\",\"filename\":\"report.pdf\",\"mimetype\":\"application/pdf\",\"size\":12345,\"url\":\"https://...\"}\n\nNotes:\n - Uses the Telegram bot token on the server side\n - Uploads through VM0 storage first, then asks Telegram to fetch the file URL\n - VM0 does not apply file type or size restrictions before calling Telegram`,\n )\n .action(\n withErrorHandler(\n async (options: {\n file: string;\n botId: string;\n chatId: string;\n caption?: string;\n messageThreadId?: string;\n contentType?: string;\n }) => {\n let fileSize: number;\n try {\n const stat = statSync(options.file);\n if (!stat.isFile()) {\n throw new Error(`Not a regular file: ${options.file}`);\n }\n fileSize = stat.size;\n } catch (error) {\n if (error instanceof Error && error.message.startsWith(\"Not \")) {\n throw error;\n }\n throw new Error(`File not found: ${options.file}`);\n }\n\n if (fileSize === 0) {\n throw new Error(\"File is empty\");\n }\n const filename = basename(options.file);\n const contentType =\n options.contentType ?? inferContentType(options.file);\n const messageThreadId = parseMessageThreadId(options.messageThreadId);\n\n const prepared = await initTelegramFileUpload({\n filename,\n contentType,\n length: fileSize,\n });\n\n const fileContent = readFileSync(options.file);\n const uploadResponse = await fetch(prepared.uploadUrl, {\n method: \"PUT\",\n headers: { \"Content-Type\": prepared.contentType },\n body: new Uint8Array(fileContent),\n });\n\n if (!uploadResponse.ok) {\n throw new Error(\n `File upload failed: ${uploadResponse.status} ${uploadResponse.statusText}`,\n );\n }\n\n const result = await completeTelegramFileUpload({\n uploadId: prepared.uploadId,\n botId: options.botId,\n chatId: options.chatId,\n contentType: prepared.contentType,\n caption: options.caption,\n messageThreadId,\n });\n\n console.log(JSON.stringify(result));\n },\n ),\n );\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;ACAA;;;ACAA;AAMA,SAAS,cAAc,KAAkC;AACvD,MAAI,CAAC,IAAI,SAAU,QAAO;AAC1B,SAAO,IAAI,SAAS,WAAW,GAAG,IAAI,IAAI,WAAW,IAAI,IAAI,QAAQ;AACvE;AAEA,SAAS,YAAY,KAAkC;AACrD,MAAI,IAAI,gBAAgB,QAAS,QAAO,eAAM,MAAM,OAAO;AAC3D,MAAI,IAAI,gBAAgB,UAAW,QAAO,eAAM,IAAI,SAAS;AAC7D,SAAO,eAAM,OAAO,SAAS;AAC/B;AAEO,IAAM,cAAc,IAAI,QAAQ,EACpC,KAAK,MAAM,EACX,MAAM,IAAI,EACV,YAAY,yDAAyD,EACrE;AAAA,EACC;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAMF,EACC;AAAA,EACC,iBAAiB,YAAY;AAC3B,UAAM,SAAS,MAAM,iBAAiB;AACtC,UAAM,EAAE,KAAK,IAAI;AAEjB,QAAI,KAAK,WAAW,GAAG;AACrB,cAAQ,IAAI,eAAM,IAAI,wBAAwB,CAAC;AAC/C,cAAQ;AAAA,QACN,eAAM,IAAI,mDAAmD;AAAA,MAC/D;AACA;AAAA,IACF;AAEA,UAAM,aAAa,KAAK;AAAA,MACtB;AAAA,MACA,GAAG,KAAK,IAAI,CAAC,QAAQ;AACnB,eAAO,IAAI,GAAG;AAAA,MAChB,CAAC;AAAA,IACH;AACA,UAAM,gBAAgB,KAAK;AAAA,MACzB;AAAA,MACA,GAAG,KAAK,IAAI,CAAC,QAAQ;AACnB,eAAO,cAAc,GAAG,EAAE;AAAA,MAC5B,CAAC;AAAA,IACH;AACA,UAAM,aAAa,KAAK;AAAA,MACtB;AAAA,MACA,GAAG,KAAK,IAAI,CAAC,QAAQ;AACnB,gBAAQ,IAAI,OAAO,QAAQ,KAAK;AAAA,MAClC,CAAC;AAAA,IACH;AAEA,UAAM,SAAS;AAAA,MACb,SAAS,OAAO,UAAU;AAAA,MAC1B,WAAW,OAAO,aAAa;AAAA,MAC/B,QAAQ,OAAO,UAAU;AAAA,MACzB;AAAA,MACA;AAAA,IACF,EAAE,KAAK,IAAI;AACX,YAAQ,IAAI,eAAM,IAAI,MAAM,CAAC;AAE7B,eAAW,OAAO,MAAM;AACtB,YAAM,MAAM;AAAA,QACV,IAAI,GAAG,OAAO,UAAU;AAAA,QACxB,cAAc,GAAG,EAAE,OAAO,aAAa;AAAA,SACtC,IAAI,OAAO,QAAQ,KAAK,OAAO,UAAU;AAAA,SACzC,IAAI,cAAc,QAAQ,MAAM,OAAO,CAAC;AAAA,QACzC,YAAY,GAAG;AAAA,MACjB,EAAE,KAAK,IAAI;AACX,cAAQ,IAAI,GAAG;AAAA,IACjB;AAAA,EACF,CAAC;AACH;;;AD/EK,IAAM,yBAAyB,IAAI,QAAQ,EAC/C,KAAK,KAAK,EACV,YAAY,uBAAuB,EACnC,WAAW,WAAW,EACtB;AAAA,EACC;AAAA,EACA;AAAA;AAAA;AAGF;;;AEZF;AAAA,SAAS,UAAU,YAAY;AAC/B,SAAS,cAAc;AAYvB,SAAS,eAAe,QAAwB;AAC9C,SAAO,KAAK,OAAO,GAAG,YAAY,SAAS,MAAM,CAAC,EAAE;AACtD;AAEO,IAAM,sBAAsB,IAAI,QAAQ,EAC5C,KAAK,eAAe,EACpB,YAAY,oDAAoD,EAChE,SAAS,aAAa,+CAA+C,EACrE;AAAA,EACC;AAAA,EACA;AACF,EACC;AAAA,EACC;AAAA,EACA;AACF,EACC;AAAA,EACC;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAoBF,EACC;AAAA,EACC;AAAA,IACE,OAAO,QAAgB,YAA6C;AAClE,YAAM,UAAU,QAAQ,OAAO,eAAe,MAAM;AACpD,YAAM,SAAS,MAAM;AAAA,QACnB;AAAA,QACA,QAAQ;AAAA,QACR;AAAA,MACF;AACA,cAAQ,IAAI,KAAK,UAAU,MAAM,CAAC;AAAA,IACpC;AAAA,EACF;AACF;;;AChEF;;;ACAA;AAAA,SAAS,oBAAoB;AAM7B,SAAS,qBAAqB,OAAe,MAAsB;AACjE,QAAM,SAAS,OAAO,KAAK;AAC3B,MAAI,CAAC,OAAO,UAAU,MAAM,KAAK,UAAU,GAAG;AAC5C,UAAM,IAAI,MAAM,GAAG,IAAI,6BAA6B;AAAA,EACtD;AACA,SAAO;AACT;AAEO,IAAM,cAAc,IAAI,QAAQ,EACpC,KAAK,MAAM,EACX,YAAY,8CAA8C,EAC1D,eAAe,iBAAiB,iBAAiB,EACjD,eAAe,sBAAsB,kBAAkB,EACvD,OAAO,wBAAwB,cAAc,EAC7C,OAAO,8BAA8B,wBAAwB,EAC7D,OAAO,4BAA4B,gCAAgC,EACnE;AAAA,EACC;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASF,EACC;AAAA,EACC;AAAA,IACE,OAAO,YAMD;AACJ,UAAI,OAAO,QAAQ;AACnB,UAAI,CAAC,QAAQ,CAAC,QAAQ,MAAM,OAAO;AACjC,YAAI;AACF,iBAAO,aAAa,cAAc,MAAM,EAAE,KAAK;AAAA,QACjD,QAAQ;AAAA,QAGR;AAAA,MACF;AAEA,UAAI,CAAC,MAAM;AACT,cAAM,IAAI,MAAM,iDAAiD;AAAA,UAC/D,OAAO,IAAI;AAAA,YACT;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH;AAEA,YAAM,SAAS,MAAM,oBAAoB;AAAA,QACvC,OAAO,QAAQ;AAAA,QACf,QAAQ,QAAQ;AAAA,QAChB;AAAA,QACA,kBAAkB,QAAQ,mBACtB;AAAA,UACE,QAAQ;AAAA,UACR;AAAA,QACF,IACA;AAAA,QACJ,iBAAiB,QAAQ,kBACrB,qBAAqB,QAAQ,iBAAiB,mBAAmB,IACjE;AAAA,MACN,CAAC;AAED,cAAQ;AAAA,QACN,eAAM,MAAM,oCAA+B,OAAO,SAAS,GAAG;AAAA,MAChE;AAAA,IACF;AAAA,EACF;AACF;;;AD9EK,IAAM,6BAA6B,IAAI,QAAQ,EACnD,KAAK,SAAS,EACd,YAAY,0BAA0B,EACtC,WAAW,WAAW,EACtB;AAAA,EACC;AAAA,EACA;AAAA;AAAA;AAGF;;;AEZF;AAAA,SAAS,gBAAAA,eAAc,gBAAgB;AACvC,SAAS,YAAAC,WAAU,eAAe;AAQlC,IAAM,oBAA4C;AAAA,EAChD,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,SAAS;AACX;AAEA,SAAS,iBAAiB,WAA2B;AACnD,QAAM,MAAM,QAAQ,SAAS,EAAE,YAAY;AAC3C,SAAO,kBAAkB,GAAG,KAAK;AACnC;AAEA,SAAS,qBAAqB,OAA+C;AAC3E,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,SAAS,OAAO,KAAK;AAC3B,MAAI,CAAC,OAAO,cAAc,MAAM,KAAK,UAAU,GAAG;AAChD,UAAM,IAAI,MAAM,8CAA8C;AAAA,EAChE;AACA,SAAO;AACT;AAEO,IAAM,oBAAoB,IAAI,QAAQ,EAC1C,KAAK,aAAa,EAClB,YAAY,mDAAmD,EAC/D,eAAe,qBAAqB,2BAA2B,EAC/D,eAAe,qBAAqB,iCAAiC,EACrE,eAAe,2BAA2B,8BAA8B,EACxE,OAAO,oBAAoB,+BAA+B,EAC1D,OAAO,4BAA4B,+BAA+B,EAClE,OAAO,yBAAyB,gCAAgC,EAChE;AAAA,EACC;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAcF,EACC;AAAA,EACC;AAAA,IACE,OAAO,YAOD;AACJ,UAAI;AACJ,UAAI;AACF,cAAM,OAAO,SAAS,QAAQ,IAAI;AAClC,YAAI,CAAC,KAAK,OAAO,GAAG;AAClB,gBAAM,IAAI,MAAM,uBAAuB,QAAQ,IAAI,EAAE;AAAA,QACvD;AACA,mBAAW,KAAK;AAAA,MAClB,SAAS,OAAO;AACd,YAAI,iBAAiB,SAAS,MAAM,QAAQ,WAAW,MAAM,GAAG;AAC9D,gBAAM;AAAA,QACR;AACA,cAAM,IAAI,MAAM,mBAAmB,QAAQ,IAAI,EAAE;AAAA,MACnD;AAEA,UAAI,aAAa,GAAG;AAClB,cAAM,IAAI,MAAM,eAAe;AAAA,MACjC;AACA,YAAM,WAAWC,UAAS,QAAQ,IAAI;AACtC,YAAM,cACJ,QAAQ,eAAe,iBAAiB,QAAQ,IAAI;AACtD,YAAM,kBAAkB,qBAAqB,QAAQ,eAAe;AAEpE,YAAM,WAAW,MAAM,uBAAuB;AAAA,QAC5C;AAAA,QACA;AAAA,QACA,QAAQ;AAAA,MACV,CAAC;AAED,YAAM,cAAcC,cAAa,QAAQ,IAAI;AAC7C,YAAM,iBAAiB,MAAM,MAAM,SAAS,WAAW;AAAA,QACrD,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,SAAS,YAAY;AAAA,QAChD,MAAM,IAAI,WAAW,WAAW;AAAA,MAClC,CAAC;AAED,UAAI,CAAC,eAAe,IAAI;AACtB,cAAM,IAAI;AAAA,UACR,uBAAuB,eAAe,MAAM,IAAI,eAAe,UAAU;AAAA,QAC3E;AAAA,MACF;AAEA,YAAM,SAAS,MAAM,2BAA2B;AAAA,QAC9C,UAAU,SAAS;AAAA,QACnB,OAAO,QAAQ;AAAA,QACf,QAAQ,QAAQ;AAAA,QAChB,aAAa,SAAS;AAAA,QACtB,SAAS,QAAQ;AAAA,QACjB;AAAA,MACF,CAAC;AAED,cAAQ,IAAI,KAAK,UAAU,MAAM,CAAC;AAAA,IACpC;AAAA,EACF;AACF;;;AN3HK,IAAM,sBAAsB,IAAI,QAAQ,EAC5C,KAAK,UAAU,EACf;AAAA,EACC;AACF,EACC,WAAW,sBAAsB,EACjC,WAAW,0BAA0B,EACrC,WAAW,mBAAmB,EAC9B,WAAW,iBAAiB,EAC5B;AAAA,EACC;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAMF;","names":["readFileSync","basename","basename","readFileSync"]}
@@ -6,7 +6,7 @@ import {
6
6
  __filename,
7
7
  __require,
8
8
  init_esm_shims
9
- } from "./chunk-DIRAZ3YX.js";
9
+ } from "./chunk-3VVCUQPB.js";
10
10
 
11
11
  // ../../node_modules/.pnpm/undici@8.5.0/node_modules/undici/lib/core/symbols.js
12
12
  var require_symbols = __commonJS({
@@ -25902,4 +25902,4 @@ undici/lib/web/fetch/body.js:
25902
25902
  undici/lib/web/websocket/frame.js:
25903
25903
  (*! ws. MIT License. Einar Otto Stangvik <einaros@gmail.com> *)
25904
25904
  */
25905
- //# sourceMappingURL=undici-ZMFN7TNU.js.map
25905
+ //# sourceMappingURL=undici-YXSVPIYI.js.map
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire as __createRequire } from "node:module";
3
+ const require = __createRequire(import.meta.url);
4
+ import {
5
+ planUpgradeUrl
6
+ } from "./chunk-W75R7EZF.js";
7
+ import {
8
+ getPlatformOrigin
9
+ } from "./chunk-JCLLQRCI.js";
10
+ import "./chunk-SB7EZ2ZO.js";
11
+ import {
12
+ source_default,
13
+ withErrorHandler
14
+ } from "./chunk-BQOOTJNB.js";
15
+ import "./chunk-A2NKQGRI.js";
16
+ import {
17
+ Command,
18
+ InvalidArgumentError
19
+ } from "./chunk-LD4ZVU4O.js";
20
+ import {
21
+ init_esm_shims
22
+ } from "./chunk-3VVCUQPB.js";
23
+
24
+ // src/commands/zero/upgrade.ts
25
+ init_esm_shims();
26
+ function parseUpgradePlan(value) {
27
+ if (value !== "pro") {
28
+ throw new InvalidArgumentError("plan must be pro");
29
+ }
30
+ return value;
31
+ }
32
+ var zeroUpgradeCommand = new Command().name("upgrade").description("Create a link to compare and upgrade workspace plans").argument("[plan]", "Plan to upgrade to: pro", parseUpgradePlan, "pro").addHelpText(
33
+ "after",
34
+ `
35
+ Examples:
36
+ Upgrade to Pro: zero upgrade pro
37
+
38
+ Output:
39
+ Prints a platform link that chat can render as an upgrade card`
40
+ ).action(
41
+ withErrorHandler(async (plan) => {
42
+ const platformOrigin = await getPlatformOrigin();
43
+ console.log(source_default.bold(`Upgrade to ${plan === "pro" ? "Pro" : plan}:`));
44
+ console.log(planUpgradeUrl(platformOrigin));
45
+ })
46
+ );
47
+ export {
48
+ zeroUpgradeCommand
49
+ };
50
+ //# sourceMappingURL=upgrade-DNGUR42E.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/zero/upgrade.ts"],"sourcesContent":["import { Command, InvalidArgumentError } from \"commander\";\nimport chalk from \"chalk\";\n\nimport { withErrorHandler } from \"../../lib/command\";\nimport { getPlatformOrigin } from \"./doctor/platform-url\";\nimport { planUpgradeUrl } from \"./shared/billing-links\";\n\ntype UpgradePlan = \"pro\";\n\nfunction parseUpgradePlan(value: string): UpgradePlan {\n if (value !== \"pro\") {\n throw new InvalidArgumentError(\"plan must be pro\");\n }\n return value;\n}\n\nexport const zeroUpgradeCommand = new Command()\n .name(\"upgrade\")\n .description(\"Create a link to compare and upgrade workspace plans\")\n .argument(\"[plan]\", \"Plan to upgrade to: pro\", parseUpgradePlan, \"pro\")\n .addHelpText(\n \"after\",\n `\nExamples:\n Upgrade to Pro: zero upgrade pro\n\nOutput:\n Prints a platform link that chat can render as an upgrade card`,\n )\n .action(\n withErrorHandler(async (plan: UpgradePlan) => {\n const platformOrigin = await getPlatformOrigin();\n console.log(chalk.bold(`Upgrade to ${plan === \"pro\" ? \"Pro\" : plan}:`));\n console.log(planUpgradeUrl(platformOrigin));\n }),\n );\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAAA;AASA,SAAS,iBAAiB,OAA4B;AACpD,MAAI,UAAU,OAAO;AACnB,UAAM,IAAI,qBAAqB,kBAAkB;AAAA,EACnD;AACA,SAAO;AACT;AAEO,IAAM,qBAAqB,IAAI,QAAQ,EAC3C,KAAK,SAAS,EACd,YAAY,sDAAsD,EAClE,SAAS,UAAU,2BAA2B,kBAAkB,KAAK,EACrE;AAAA,EACC;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAMF,EACC;AAAA,EACC,iBAAiB,OAAO,SAAsB;AAC5C,UAAM,iBAAiB,MAAM,kBAAkB;AAC/C,YAAQ,IAAI,eAAM,KAAK,cAAc,SAAS,QAAQ,QAAQ,IAAI,GAAG,CAAC;AACtE,YAAQ,IAAI,eAAe,cAAc,CAAC;AAAA,EAC5C,CAAC;AACH;","names":[]}
@@ -4,24 +4,25 @@ const require = __createRequire(import.meta.url);
4
4
  import {
5
5
  isInteractive,
6
6
  promptConfirm
7
- } from "./chunk-JFY6GK7Y.js";
7
+ } from "./chunk-X2545RBX.js";
8
8
  import {
9
9
  deleteZeroVariable,
10
10
  listZeroVariables,
11
11
  setZeroVariable
12
- } from "./chunk-KQN5YZZP.js";
13
- import "./chunk-LTDQISD7.js";
12
+ } from "./chunk-ROB3OE37.js";
13
+ import "./chunk-N6TDQYGF.js";
14
+ import "./chunk-SB7EZ2ZO.js";
14
15
  import {
15
16
  source_default,
16
17
  withErrorHandler
17
- } from "./chunk-L63QVTYZ.js";
18
- import "./chunk-LRHXR7JT.js";
18
+ } from "./chunk-BQOOTJNB.js";
19
+ import "./chunk-A2NKQGRI.js";
19
20
  import {
20
21
  Command
21
- } from "./chunk-B3W2RUBP.js";
22
+ } from "./chunk-LD4ZVU4O.js";
22
23
  import {
23
24
  init_esm_shims
24
- } from "./chunk-DIRAZ3YX.js";
25
+ } from "./chunk-3VVCUQPB.js";
25
26
 
26
27
  // src/commands/zero/variable/index.ts
27
28
  init_esm_shims();
@@ -115,4 +116,4 @@ var zeroVariableCommand = new Command().name("variable").description("Read or wr
115
116
  export {
116
117
  zeroVariableCommand
117
118
  };
118
- //# sourceMappingURL=variable-EBCBNZSU.js.map
119
+ //# sourceMappingURL=variable-C7RWUPV6.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/zero/variable/index.ts","../src/commands/zero/variable/list.ts","../src/commands/zero/variable/set.ts","../src/commands/zero/variable/delete.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { listCommand } from \"./list\";\nimport { setCommand } from \"./set\";\nimport { deleteCommand } from \"./delete\";\n\nexport const zeroVariableCommand = new Command()\n .name(\"variable\")\n .description(\"Read or write non-sensitive configuration values\")\n .addCommand(listCommand)\n .addCommand(setCommand)\n .addCommand(deleteCommand);\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { listZeroVariables } from \"../../../lib/api\";\nimport { withErrorHandler } from \"../../../lib/command\";\n\n/**\n * Truncate value for display if too long\n */\nfunction truncateValue(value: string, maxLength: number = 60): string {\n if (value.length <= maxLength) {\n return value;\n }\n return value.slice(0, maxLength - 15) + \"... [truncated]\";\n}\n\nexport const listCommand = new Command()\n .name(\"list\")\n .alias(\"ls\")\n .description(\"List all variables\")\n .action(\n withErrorHandler(async () => {\n const result = await listZeroVariables();\n\n if (result.variables.length === 0) {\n console.log(chalk.dim(\"No variables found\"));\n console.log();\n console.log(\"To add a variable:\");\n console.log(chalk.cyan(\" zero variable set MY_VAR <value>\"));\n return;\n }\n\n console.log(chalk.bold(\"Variables:\"));\n console.log();\n\n for (const variable of result.variables) {\n const displayValue = truncateValue(variable.value);\n console.log(` ${chalk.cyan(variable.name)} = ${displayValue}`);\n if (variable.description) {\n console.log(` ${chalk.dim(variable.description)}`);\n }\n console.log(\n ` ${chalk.dim(`Updated: ${new Date(variable.updatedAt).toLocaleString()}`)}`,\n );\n console.log();\n }\n\n console.log(chalk.dim(`Total: ${result.variables.length} variable(s)`));\n }),\n );\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { setZeroVariable } from \"../../../lib/api\";\nimport { withErrorHandler } from \"../../../lib/command\";\n\nexport const setCommand = new Command()\n .name(\"set\")\n .description(\"Create or update a variable\")\n .argument(\"<name>\", \"Variable name (uppercase, e.g., MY_VAR)\")\n .argument(\"<value>\", \"Variable value\")\n .option(\"-d, --description <description>\", \"Optional description\")\n .action(\n withErrorHandler(\n async (\n name: string,\n value: string,\n options: { description?: string },\n ) => {\n let variable;\n try {\n variable = await setZeroVariable({\n name,\n value,\n description: options.description,\n });\n } catch (error) {\n if (\n error instanceof Error &&\n error.message.includes(\"must contain only uppercase\")\n ) {\n throw new Error(error.message, {\n cause: new Error(\n \"Examples of valid variable names: MY_VAR, API_URL, DEBUG_MODE\",\n ),\n });\n }\n throw error;\n }\n\n console.log(chalk.green(`✓ Variable \"${variable.name}\" saved`));\n },\n ),\n );\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { deleteZeroVariable } from \"../../../lib/api\";\nimport { isInteractive, promptConfirm } from \"../../../lib/utils/prompt-utils\";\nimport { withErrorHandler } from \"../../../lib/command\";\n\nexport const deleteCommand = new Command()\n .name(\"delete\")\n .description(\"Delete a variable\")\n .argument(\"<name>\", \"Variable name to delete\")\n .option(\"-y, --yes\", \"Skip confirmation prompt\")\n .action(\n withErrorHandler(async (name: string, options: { yes?: boolean }) => {\n if (!options.yes) {\n if (!isInteractive()) {\n throw new Error(\"--yes flag is required in non-interactive mode\");\n }\n\n const confirmed = await promptConfirm(\n `Are you sure you want to delete variable \"${name}\"?`,\n false,\n );\n\n if (!confirmed) {\n console.log(chalk.dim(\"Cancelled\"));\n return;\n }\n }\n\n await deleteZeroVariable(name);\n console.log(chalk.green(`✓ Variable \"${name}\" deleted`));\n }),\n );\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;ACAA;AAQA,SAAS,cAAc,OAAe,YAAoB,IAAY;AACpE,MAAI,MAAM,UAAU,WAAW;AAC7B,WAAO;AAAA,EACT;AACA,SAAO,MAAM,MAAM,GAAG,YAAY,EAAE,IAAI;AAC1C;AAEO,IAAM,cAAc,IAAI,QAAQ,EACpC,KAAK,MAAM,EACX,MAAM,IAAI,EACV,YAAY,oBAAoB,EAChC;AAAA,EACC,iBAAiB,YAAY;AAC3B,UAAM,SAAS,MAAM,kBAAkB;AAEvC,QAAI,OAAO,UAAU,WAAW,GAAG;AACjC,cAAQ,IAAI,eAAM,IAAI,oBAAoB,CAAC;AAC3C,cAAQ,IAAI;AACZ,cAAQ,IAAI,oBAAoB;AAChC,cAAQ,IAAI,eAAM,KAAK,oCAAoC,CAAC;AAC5D;AAAA,IACF;AAEA,YAAQ,IAAI,eAAM,KAAK,YAAY,CAAC;AACpC,YAAQ,IAAI;AAEZ,eAAW,YAAY,OAAO,WAAW;AACvC,YAAM,eAAe,cAAc,SAAS,KAAK;AACjD,cAAQ,IAAI,KAAK,eAAM,KAAK,SAAS,IAAI,CAAC,MAAM,YAAY,EAAE;AAC9D,UAAI,SAAS,aAAa;AACxB,gBAAQ,IAAI,OAAO,eAAM,IAAI,SAAS,WAAW,CAAC,EAAE;AAAA,MACtD;AACA,cAAQ;AAAA,QACN,OAAO,eAAM,IAAI,YAAY,IAAI,KAAK,SAAS,SAAS,EAAE,eAAe,CAAC,EAAE,CAAC;AAAA,MAC/E;AACA,cAAQ,IAAI;AAAA,IACd;AAEA,YAAQ,IAAI,eAAM,IAAI,UAAU,OAAO,UAAU,MAAM,cAAc,CAAC;AAAA,EACxE,CAAC;AACH;;;AChDF;AAKO,IAAM,aAAa,IAAI,QAAQ,EACnC,KAAK,KAAK,EACV,YAAY,6BAA6B,EACzC,SAAS,UAAU,yCAAyC,EAC5D,SAAS,WAAW,gBAAgB,EACpC,OAAO,mCAAmC,sBAAsB,EAChE;AAAA,EACC;AAAA,IACE,OACE,MACA,OACA,YACG;AACH,UAAI;AACJ,UAAI;AACF,mBAAW,MAAM,gBAAgB;AAAA,UAC/B;AAAA,UACA;AAAA,UACA,aAAa,QAAQ;AAAA,QACvB,CAAC;AAAA,MACH,SAAS,OAAO;AACd,YACE,iBAAiB,SACjB,MAAM,QAAQ,SAAS,6BAA6B,GACpD;AACA,gBAAM,IAAI,MAAM,MAAM,SAAS;AAAA,YAC7B,OAAO,IAAI;AAAA,cACT;AAAA,YACF;AAAA,UACF,CAAC;AAAA,QACH;AACA,cAAM;AAAA,MACR;AAEA,cAAQ,IAAI,eAAM,MAAM,oBAAe,SAAS,IAAI,SAAS,CAAC;AAAA,IAChE;AAAA,EACF;AACF;;;AC1CF;AAMO,IAAM,gBAAgB,IAAI,QAAQ,EACtC,KAAK,QAAQ,EACb,YAAY,mBAAmB,EAC/B,SAAS,UAAU,yBAAyB,EAC5C,OAAO,aAAa,0BAA0B,EAC9C;AAAA,EACC,iBAAiB,OAAO,MAAc,YAA+B;AACnE,QAAI,CAAC,QAAQ,KAAK;AAChB,UAAI,CAAC,cAAc,GAAG;AACpB,cAAM,IAAI,MAAM,gDAAgD;AAAA,MAClE;AAEA,YAAM,YAAY,MAAM;AAAA,QACtB,6CAA6C,IAAI;AAAA,QACjD;AAAA,MACF;AAEA,UAAI,CAAC,WAAW;AACd,gBAAQ,IAAI,eAAM,IAAI,WAAW,CAAC;AAClC;AAAA,MACF;AAAA,IACF;AAEA,UAAM,mBAAmB,IAAI;AAC7B,YAAQ,IAAI,eAAM,MAAM,oBAAe,IAAI,WAAW,CAAC;AAAA,EACzD,CAAC;AACH;;;AH3BK,IAAM,sBAAsB,IAAI,QAAQ,EAC5C,KAAK,UAAU,EACf,YAAY,kDAAkD,EAC9D,WAAW,WAAW,EACtB,WAAW,UAAU,EACrB,WAAW,aAAa;","names":[]}
1
+ {"version":3,"sources":["../src/commands/zero/variable/index.ts","../src/commands/zero/variable/list.ts","../src/commands/zero/variable/set.ts","../src/commands/zero/variable/delete.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { listCommand } from \"./list\";\nimport { setCommand } from \"./set\";\nimport { deleteCommand } from \"./delete\";\n\nexport const zeroVariableCommand = new Command()\n .name(\"variable\")\n .description(\"Read or write non-sensitive configuration values\")\n .addCommand(listCommand)\n .addCommand(setCommand)\n .addCommand(deleteCommand);\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { listZeroVariables } from \"../../../lib/api\";\nimport { withErrorHandler } from \"../../../lib/command\";\n\n/**\n * Truncate value for display if too long\n */\nfunction truncateValue(value: string, maxLength: number = 60): string {\n if (value.length <= maxLength) {\n return value;\n }\n return value.slice(0, maxLength - 15) + \"... [truncated]\";\n}\n\nexport const listCommand = new Command()\n .name(\"list\")\n .alias(\"ls\")\n .description(\"List all variables\")\n .action(\n withErrorHandler(async () => {\n const result = await listZeroVariables();\n\n if (result.variables.length === 0) {\n console.log(chalk.dim(\"No variables found\"));\n console.log();\n console.log(\"To add a variable:\");\n console.log(chalk.cyan(\" zero variable set MY_VAR <value>\"));\n return;\n }\n\n console.log(chalk.bold(\"Variables:\"));\n console.log();\n\n for (const variable of result.variables) {\n const displayValue = truncateValue(variable.value);\n console.log(` ${chalk.cyan(variable.name)} = ${displayValue}`);\n if (variable.description) {\n console.log(` ${chalk.dim(variable.description)}`);\n }\n console.log(\n ` ${chalk.dim(`Updated: ${new Date(variable.updatedAt).toLocaleString()}`)}`,\n );\n console.log();\n }\n\n console.log(chalk.dim(`Total: ${result.variables.length} variable(s)`));\n }),\n );\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { setZeroVariable } from \"../../../lib/api\";\nimport { withErrorHandler } from \"../../../lib/command\";\n\nexport const setCommand = new Command()\n .name(\"set\")\n .description(\"Create or update a variable\")\n .argument(\"<name>\", \"Variable name (uppercase, e.g., MY_VAR)\")\n .argument(\"<value>\", \"Variable value\")\n .option(\"-d, --description <description>\", \"Optional description\")\n .action(\n withErrorHandler(\n async (\n name: string,\n value: string,\n options: { description?: string },\n ) => {\n let variable;\n try {\n variable = await setZeroVariable({\n name,\n value,\n description: options.description,\n });\n } catch (error) {\n if (\n error instanceof Error &&\n error.message.includes(\"must contain only uppercase\")\n ) {\n throw new Error(error.message, {\n cause: new Error(\n \"Examples of valid variable names: MY_VAR, API_URL, DEBUG_MODE\",\n ),\n });\n }\n throw error;\n }\n\n console.log(chalk.green(`✓ Variable \"${variable.name}\" saved`));\n },\n ),\n );\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { deleteZeroVariable } from \"../../../lib/api\";\nimport { isInteractive, promptConfirm } from \"../../../lib/utils/prompt-utils\";\nimport { withErrorHandler } from \"../../../lib/command\";\n\nexport const deleteCommand = new Command()\n .name(\"delete\")\n .description(\"Delete a variable\")\n .argument(\"<name>\", \"Variable name to delete\")\n .option(\"-y, --yes\", \"Skip confirmation prompt\")\n .action(\n withErrorHandler(async (name: string, options: { yes?: boolean }) => {\n if (!options.yes) {\n if (!isInteractive()) {\n throw new Error(\"--yes flag is required in non-interactive mode\");\n }\n\n const confirmed = await promptConfirm(\n `Are you sure you want to delete variable \"${name}\"?`,\n false,\n );\n\n if (!confirmed) {\n console.log(chalk.dim(\"Cancelled\"));\n return;\n }\n }\n\n await deleteZeroVariable(name);\n console.log(chalk.green(`✓ Variable \"${name}\" deleted`));\n }),\n );\n"],"mappings":"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","names":[]}
@@ -1,19 +1,21 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire as __createRequire } from "node:module";
3
3
  const require = __createRequire(import.meta.url);
4
- import "./chunk-LTDQISD7.js";
5
4
  import {
6
5
  downloadWebFile,
7
- transcribeAudio,
6
+ transcribeAudio
7
+ } from "./chunk-N6TDQYGF.js";
8
+ import "./chunk-SB7EZ2ZO.js";
9
+ import {
8
10
  withErrorHandler
9
- } from "./chunk-L63QVTYZ.js";
10
- import "./chunk-LRHXR7JT.js";
11
+ } from "./chunk-BQOOTJNB.js";
12
+ import "./chunk-A2NKQGRI.js";
11
13
  import {
12
14
  Command
13
- } from "./chunk-B3W2RUBP.js";
15
+ } from "./chunk-LD4ZVU4O.js";
14
16
  import {
15
17
  init_esm_shims
16
- } from "./chunk-DIRAZ3YX.js";
18
+ } from "./chunk-3VVCUQPB.js";
17
19
 
18
20
  // src/commands/zero/video/index.ts
19
21
  init_esm_shims();
@@ -245,4 +247,4 @@ Tip (video understanding):
245
247
  export {
246
248
  zeroVideoCommand
247
249
  };
248
- //# sourceMappingURL=video-3HFJJJEE.js.map
250
+ //# sourceMappingURL=video-JS5VOA2S.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/zero/video/index.ts","../src/commands/zero/video/transcribe.ts","../src/commands/zero/video/frames.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { transcribeCommand } from \"./transcribe\";\nimport { framesCommand } from \"./frames\";\n\nexport const zeroVideoCommand = new Command()\n .name(\"video\")\n .description(\"Video processing utilities\")\n .addCommand(transcribeCommand)\n .addCommand(framesCommand)\n .addHelpText(\n \"after\",\n `\nExamples:\n Transcribe a video: zero video transcribe --url \"https://...\"\n Web file: zero video transcribe --file-id abc-123\n Extract frames: zero video frames --url \"https://...\" --at 00:21,01:40\n\nTip (video understanding):\n Transcribe first to get a timestamped index, then extract only the\n frames worth seeing instead of watching the whole video.`,\n );\n","import { execFileSync } from \"child_process\";\nimport { unlinkSync } from \"fs\";\nimport { tmpdir } from \"os\";\nimport { join } from \"path\";\nimport { Command } from \"commander\";\nimport { withErrorHandler } from \"../../../lib/command\";\nimport {\n downloadWebFile,\n transcribeAudio,\n type TranscribeAudioSegment,\n} from \"../../../lib/api/domains/web\";\n\nfunction formatTime(seconds: number): string {\n const m = Math.floor(seconds / 60)\n .toString()\n .padStart(2, \"0\");\n const s = Math.floor(seconds % 60)\n .toString()\n .padStart(2, \"0\");\n return `${m}:${s}`;\n}\n\nfunction formatTranscript(\n text: string,\n segments: readonly TranscribeAudioSegment[] | undefined,\n): string {\n if (!segments || segments.length === 0) {\n return `## Transcript\\n${text}`;\n }\n const lines = segments.map((s) => {\n const start = formatTime(s.start);\n const end = formatTime(s.end);\n return `[${start}-${end}] ${s.text.trim()}`;\n });\n return `## Transcript\\n${lines.join(\"\\n\")}`;\n}\n\nexport const transcribeCommand = new Command()\n .name(\"transcribe\")\n .description(\n \"Transcribe audio from a video file and output structured Markdown\",\n )\n .option(\"--url <presigned-url>\", \"Pre-signed or public URL of the video file\")\n .option(\"--file-id <id>\", \"Web file ID (alternative to --url)\")\n .option(\n \"--file <path>\",\n \"Local file path (alternative to --url or --file-id)\",\n )\n .option(\n \"--no-timestamps\",\n \"Output plain text only, without per-segment timestamps\",\n )\n .addHelpText(\n \"after\",\n `\nExamples:\n Transcribe from URL: zero video transcribe --url \"https://...\"\n Transcribe a web file: zero video transcribe --file-id abc-123-def\n Transcribe a local file: zero video transcribe --file /tmp/video.mp4\n Plain text only: zero video transcribe --url \"https://...\" --no-timestamps\n\nOutput:\n Structured Markdown printed to stdout:\n ## Transcript\n [00:02-00:05] First sentence here.\n [00:06-00:07] Second sentence here.\n\nNotes:\n - Requires ffmpeg on PATH for audio extraction\n - Authenticates via ZERO_TOKEN\n - Audio is extracted before upload to stay within the 25 MB size limit\n - Uses the /api/zero/voice-io/stt endpoint (quota applies)`,\n )\n .action(\n withErrorHandler(\n async (options: {\n url?: string;\n fileId?: string;\n file?: string;\n timestamps: boolean;\n }) => {\n if (!options.url && !options.fileId && !options.file) {\n process.stderr.write(\n \"Error: provide --url <presigned-url>, --file-id <id>, or --file <path>\\n\",\n );\n process.exit(1);\n }\n\n const tmpAudio = join(tmpdir(), `zero-audio-${Date.now()}.wav`);\n let tmpVideo: string | undefined;\n\n try {\n let videoPath: string;\n\n if (options.file) {\n videoPath = options.file;\n } else {\n tmpVideo = join(tmpdir(), `zero-video-${Date.now()}.mp4`);\n if (options.url) {\n execFileSync(\"curl\", [\"-sS\", \"-L\", \"-o\", tmpVideo, options.url], {\n stdio: [\"ignore\", \"ignore\", \"pipe\"],\n });\n } else {\n await downloadWebFile(options.fileId as string, tmpVideo);\n }\n videoPath = tmpVideo;\n }\n\n execFileSync(\n \"ffmpeg\",\n [\n \"-i\",\n videoPath,\n \"-vn\",\n \"-ar\",\n \"16000\",\n \"-ac\",\n \"1\",\n \"-c:a\",\n \"pcm_s16le\",\n \"-map_metadata\",\n \"-1\",\n tmpAudio,\n \"-y\",\n \"-loglevel\",\n \"error\",\n ],\n { stdio: [\"ignore\", \"ignore\", \"pipe\"] },\n );\n\n const result = await transcribeAudio(tmpAudio, {\n verbose: options.timestamps !== false,\n });\n\n process.stdout.write(\n formatTranscript(result.text, result.segments) + \"\\n\",\n );\n } finally {\n for (const path of [tmpAudio, tmpVideo]) {\n if (!path) continue;\n try {\n unlinkSync(path);\n } catch {\n // best-effort cleanup\n }\n }\n }\n },\n ),\n );\n","import { execFileSync } from \"child_process\";\nimport { mkdirSync, unlinkSync } from \"fs\";\nimport { tmpdir } from \"os\";\nimport { join } from \"path\";\nimport { Command } from \"commander\";\nimport { withErrorHandler } from \"../../../lib/command\";\nimport { downloadWebFile } from \"../../../lib/api/domains/web\";\n\ninterface ExtractedFrame {\n readonly at: string;\n readonly path: string;\n}\n\nexport const framesCommand = new Command()\n .name(\"frames\")\n .description(\"Extract still frames from a video at the given timestamps\")\n .option(\"--url <presigned-url>\", \"Pre-signed or public URL of the video file\")\n .option(\"--file-id <id>\", \"Web file ID (alternative to --url)\")\n .requiredOption(\n \"--at <timestamps>\",\n \"Comma-separated timestamps to capture (e.g. 00:21,01:40 or 12,95.5)\",\n )\n .addHelpText(\n \"after\",\n `\nExamples:\n Frames at two moments: zero video frames --url \"https://...\" --at 00:21,01:40\n From a web file: zero video frames --file-id abc-123 --at 12,95.5\n\nOutput:\n Prints a JSON object to stdout, one entry per timestamp:\n {\"frames\":[{\"at\":\"00:21\",\"path\":\"/tmp/zero-frames-.../frame-001.jpg\"}]}\n\nTip:\n Pair with \"zero video transcribe\": read the timestamped transcript to find the\n moments that matter, then extract just those frames here for a closer look.\n\nNotes:\n - Requires ffmpeg on PATH for frame extraction\n - Timestamps accept SS, MM:SS, or HH:MM:SS (fractions allowed, e.g. 95.5)\n - Extracted frames are kept on disk; only the downloaded video is cleaned up`,\n )\n .action(\n withErrorHandler(\n async (options: { url?: string; fileId?: string; at: string }) => {\n if (!options.url && !options.fileId) {\n process.stderr.write(\n \"Error: provide --url <presigned-url> or --file-id <id>\\n\",\n );\n process.exit(1);\n }\n\n const timestamps = options.at\n .split(\",\")\n .map((s) => {\n return s.trim();\n })\n .filter((s) => {\n return s.length > 0;\n });\n if (timestamps.length === 0) {\n process.stderr.write(\"Error: --at requires at least one timestamp\\n\");\n process.exit(1);\n }\n\n const outDir = join(tmpdir(), `zero-frames-${Date.now()}`);\n mkdirSync(outDir, { recursive: true });\n\n const tmpVideo = join(tmpdir(), `zero-video-${Date.now()}.mp4`);\n\n try {\n if (options.url) {\n execFileSync(\"curl\", [\"-sS\", \"-L\", \"-o\", tmpVideo, options.url], {\n stdio: [\"ignore\", \"ignore\", \"pipe\"],\n });\n } else {\n await downloadWebFile(options.fileId as string, tmpVideo);\n }\n\n const frames: ExtractedFrame[] = timestamps.map((at, index) => {\n const outPath = join(\n outDir,\n `frame-${String(index + 1).padStart(3, \"0\")}.jpg`,\n );\n execFileSync(\n \"ffmpeg\",\n [\n \"-ss\",\n at,\n \"-i\",\n tmpVideo,\n \"-frames:v\",\n \"1\",\n \"-q:v\",\n \"2\",\n outPath,\n \"-y\",\n \"-loglevel\",\n \"error\",\n ],\n { stdio: [\"ignore\", \"ignore\", \"pipe\"] },\n );\n return { at, path: outPath };\n });\n\n process.stdout.write(JSON.stringify({ frames }) + \"\\n\");\n } finally {\n try {\n unlinkSync(tmpVideo);\n } catch {\n // best-effort cleanup\n }\n }\n },\n ),\n );\n"],"mappings":"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","names":["execFileSync","unlinkSync","tmpdir","join","join","tmpdir","execFileSync","unlinkSync"]}
1
+ {"version":3,"sources":["../src/commands/zero/video/index.ts","../src/commands/zero/video/transcribe.ts","../src/commands/zero/video/frames.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { transcribeCommand } from \"./transcribe\";\nimport { framesCommand } from \"./frames\";\n\nexport const zeroVideoCommand = new Command()\n .name(\"video\")\n .description(\"Video processing utilities\")\n .addCommand(transcribeCommand)\n .addCommand(framesCommand)\n .addHelpText(\n \"after\",\n `\nExamples:\n Transcribe a video: zero video transcribe --url \"https://...\"\n Web file: zero video transcribe --file-id abc-123\n Extract frames: zero video frames --url \"https://...\" --at 00:21,01:40\n\nTip (video understanding):\n Transcribe first to get a timestamped index, then extract only the\n frames worth seeing instead of watching the whole video.`,\n );\n","import { execFileSync } from \"child_process\";\nimport { unlinkSync } from \"fs\";\nimport { tmpdir } from \"os\";\nimport { join } from \"path\";\nimport { Command } from \"commander\";\nimport { withErrorHandler } from \"../../../lib/command\";\nimport {\n downloadWebFile,\n transcribeAudio,\n type TranscribeAudioSegment,\n} from \"../../../lib/api/domains/web\";\n\nfunction formatTime(seconds: number): string {\n const m = Math.floor(seconds / 60)\n .toString()\n .padStart(2, \"0\");\n const s = Math.floor(seconds % 60)\n .toString()\n .padStart(2, \"0\");\n return `${m}:${s}`;\n}\n\nfunction formatTranscript(\n text: string,\n segments: readonly TranscribeAudioSegment[] | undefined,\n): string {\n if (!segments || segments.length === 0) {\n return `## Transcript\\n${text}`;\n }\n const lines = segments.map((s) => {\n const start = formatTime(s.start);\n const end = formatTime(s.end);\n return `[${start}-${end}] ${s.text.trim()}`;\n });\n return `## Transcript\\n${lines.join(\"\\n\")}`;\n}\n\nexport const transcribeCommand = new Command()\n .name(\"transcribe\")\n .description(\n \"Transcribe audio from a video file and output structured Markdown\",\n )\n .option(\"--url <presigned-url>\", \"Pre-signed or public URL of the video file\")\n .option(\"--file-id <id>\", \"Web file ID (alternative to --url)\")\n .option(\n \"--file <path>\",\n \"Local file path (alternative to --url or --file-id)\",\n )\n .option(\n \"--no-timestamps\",\n \"Output plain text only, without per-segment timestamps\",\n )\n .addHelpText(\n \"after\",\n `\nExamples:\n Transcribe from URL: zero video transcribe --url \"https://...\"\n Transcribe a web file: zero video transcribe --file-id abc-123-def\n Transcribe a local file: zero video transcribe --file /tmp/video.mp4\n Plain text only: zero video transcribe --url \"https://...\" --no-timestamps\n\nOutput:\n Structured Markdown printed to stdout:\n ## Transcript\n [00:02-00:05] First sentence here.\n [00:06-00:07] Second sentence here.\n\nNotes:\n - Requires ffmpeg on PATH for audio extraction\n - Authenticates via ZERO_TOKEN\n - Audio is extracted before upload to stay within the 25 MB size limit\n - Uses the /api/zero/voice-io/stt endpoint (quota applies)`,\n )\n .action(\n withErrorHandler(\n async (options: {\n url?: string;\n fileId?: string;\n file?: string;\n timestamps: boolean;\n }) => {\n if (!options.url && !options.fileId && !options.file) {\n process.stderr.write(\n \"Error: provide --url <presigned-url>, --file-id <id>, or --file <path>\\n\",\n );\n process.exit(1);\n }\n\n const tmpAudio = join(tmpdir(), `zero-audio-${Date.now()}.wav`);\n let tmpVideo: string | undefined;\n\n try {\n let videoPath: string;\n\n if (options.file) {\n videoPath = options.file;\n } else {\n tmpVideo = join(tmpdir(), `zero-video-${Date.now()}.mp4`);\n if (options.url) {\n execFileSync(\"curl\", [\"-sS\", \"-L\", \"-o\", tmpVideo, options.url], {\n stdio: [\"ignore\", \"ignore\", \"pipe\"],\n });\n } else {\n await downloadWebFile(options.fileId as string, tmpVideo);\n }\n videoPath = tmpVideo;\n }\n\n execFileSync(\n \"ffmpeg\",\n [\n \"-i\",\n videoPath,\n \"-vn\",\n \"-ar\",\n \"16000\",\n \"-ac\",\n \"1\",\n \"-c:a\",\n \"pcm_s16le\",\n \"-map_metadata\",\n \"-1\",\n tmpAudio,\n \"-y\",\n \"-loglevel\",\n \"error\",\n ],\n { stdio: [\"ignore\", \"ignore\", \"pipe\"] },\n );\n\n const result = await transcribeAudio(tmpAudio, {\n verbose: options.timestamps !== false,\n });\n\n process.stdout.write(\n formatTranscript(result.text, result.segments) + \"\\n\",\n );\n } finally {\n for (const path of [tmpAudio, tmpVideo]) {\n if (!path) continue;\n try {\n unlinkSync(path);\n } catch {\n // best-effort cleanup\n }\n }\n }\n },\n ),\n );\n","import { execFileSync } from \"child_process\";\nimport { mkdirSync, unlinkSync } from \"fs\";\nimport { tmpdir } from \"os\";\nimport { join } from \"path\";\nimport { Command } from \"commander\";\nimport { withErrorHandler } from \"../../../lib/command\";\nimport { downloadWebFile } from \"../../../lib/api/domains/web\";\n\ninterface ExtractedFrame {\n readonly at: string;\n readonly path: string;\n}\n\nexport const framesCommand = new Command()\n .name(\"frames\")\n .description(\"Extract still frames from a video at the given timestamps\")\n .option(\"--url <presigned-url>\", \"Pre-signed or public URL of the video file\")\n .option(\"--file-id <id>\", \"Web file ID (alternative to --url)\")\n .requiredOption(\n \"--at <timestamps>\",\n \"Comma-separated timestamps to capture (e.g. 00:21,01:40 or 12,95.5)\",\n )\n .addHelpText(\n \"after\",\n `\nExamples:\n Frames at two moments: zero video frames --url \"https://...\" --at 00:21,01:40\n From a web file: zero video frames --file-id abc-123 --at 12,95.5\n\nOutput:\n Prints a JSON object to stdout, one entry per timestamp:\n {\"frames\":[{\"at\":\"00:21\",\"path\":\"/tmp/zero-frames-.../frame-001.jpg\"}]}\n\nTip:\n Pair with \"zero video transcribe\": read the timestamped transcript to find the\n moments that matter, then extract just those frames here for a closer look.\n\nNotes:\n - Requires ffmpeg on PATH for frame extraction\n - Timestamps accept SS, MM:SS, or HH:MM:SS (fractions allowed, e.g. 95.5)\n - Extracted frames are kept on disk; only the downloaded video is cleaned up`,\n )\n .action(\n withErrorHandler(\n async (options: { url?: string; fileId?: string; at: string }) => {\n if (!options.url && !options.fileId) {\n process.stderr.write(\n \"Error: provide --url <presigned-url> or --file-id <id>\\n\",\n );\n process.exit(1);\n }\n\n const timestamps = options.at\n .split(\",\")\n .map((s) => {\n return s.trim();\n })\n .filter((s) => {\n return s.length > 0;\n });\n if (timestamps.length === 0) {\n process.stderr.write(\"Error: --at requires at least one timestamp\\n\");\n process.exit(1);\n }\n\n const outDir = join(tmpdir(), `zero-frames-${Date.now()}`);\n mkdirSync(outDir, { recursive: true });\n\n const tmpVideo = join(tmpdir(), `zero-video-${Date.now()}.mp4`);\n\n try {\n if (options.url) {\n execFileSync(\"curl\", [\"-sS\", \"-L\", \"-o\", tmpVideo, options.url], {\n stdio: [\"ignore\", \"ignore\", \"pipe\"],\n });\n } else {\n await downloadWebFile(options.fileId as string, tmpVideo);\n }\n\n const frames: ExtractedFrame[] = timestamps.map((at, index) => {\n const outPath = join(\n outDir,\n `frame-${String(index + 1).padStart(3, \"0\")}.jpg`,\n );\n execFileSync(\n \"ffmpeg\",\n [\n \"-ss\",\n at,\n \"-i\",\n tmpVideo,\n \"-frames:v\",\n \"1\",\n \"-q:v\",\n \"2\",\n outPath,\n \"-y\",\n \"-loglevel\",\n \"error\",\n ],\n { stdio: [\"ignore\", \"ignore\", \"pipe\"] },\n );\n return { at, path: outPath };\n });\n\n process.stdout.write(JSON.stringify({ frames }) + \"\\n\");\n } finally {\n try {\n unlinkSync(tmpVideo);\n } catch {\n // best-effort cleanup\n }\n }\n },\n ),\n );\n"],"mappings":"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","names":["execFileSync","unlinkSync","tmpdir","join","join","tmpdir","execFileSync","unlinkSync"]}
@@ -3,20 +3,21 @@ import { createRequire as __createRequire } from "node:module";
3
3
  const require = __createRequire(import.meta.url);
4
4
  import {
5
5
  callZeroWeather
6
- } from "./chunk-KQN5YZZP.js";
7
- import "./chunk-LTDQISD7.js";
6
+ } from "./chunk-ROB3OE37.js";
7
+ import "./chunk-N6TDQYGF.js";
8
+ import "./chunk-SB7EZ2ZO.js";
8
9
  import {
9
10
  source_default,
10
11
  withErrorHandler
11
- } from "./chunk-L63QVTYZ.js";
12
- import "./chunk-LRHXR7JT.js";
12
+ } from "./chunk-BQOOTJNB.js";
13
+ import "./chunk-A2NKQGRI.js";
13
14
  import {
14
15
  Command,
15
16
  InvalidArgumentError
16
- } from "./chunk-B3W2RUBP.js";
17
+ } from "./chunk-LD4ZVU4O.js";
17
18
  import {
18
19
  init_esm_shims
19
- } from "./chunk-DIRAZ3YX.js";
20
+ } from "./chunk-3VVCUQPB.js";
20
21
 
21
22
  // src/commands/zero/weather/index.ts
22
23
  init_esm_shims();
@@ -587,4 +588,4 @@ Notes:
587
588
  export {
588
589
  zeroWeatherCommand
589
590
  };
590
- //# sourceMappingURL=weather-Y37FKFKU.js.map
591
+ //# sourceMappingURL=weather-5R2N5OX4.js.map