@vellumai/cli 0.3.14 → 0.3.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bun.lock CHANGED
@@ -6,12 +6,17 @@
6
6
  "name": "@vellumai/cli",
7
7
  "dependencies": {
8
8
  "ink": "^6.7.0",
9
+ "jsqr": "^1.4.0",
10
+ "pngjs": "^7.0.0",
11
+ "qrcode": "^1.5.4",
9
12
  "qrcode-terminal": "^0.12.0",
10
13
  "react": "^19.2.4",
11
14
  "react-devtools-core": "^6.1.2",
12
15
  },
13
16
  "devDependencies": {
14
17
  "@types/bun": "^1.2.4",
18
+ "@types/pngjs": "^6.0.5",
19
+ "@types/qrcode": "^1.5.6",
15
20
  "@types/qrcode-terminal": "^0.12.2",
16
21
  "@types/react": "^19.2.14",
17
22
  "eslint": "^10.0.0",
@@ -55,6 +60,10 @@
55
60
 
56
61
  "@types/node": ["@types/node@25.2.3", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-m0jEgYlYz+mDJZ2+F4v8D1AyQb+QzsNqRuI7xg1VQX/KlKS0qT9r1Mo16yo5F/MtifXFgaofIFsdFMox2SxIbQ=="],
57
62
 
63
+ "@types/pngjs": ["@types/pngjs@6.0.5", "", { "dependencies": { "@types/node": "*" } }, "sha512-0k5eKfrA83JOZPppLtS2C7OUtyNAl2wKNxfyYl9Q5g9lPkgBl/9hNyAu6HuEH2J4XmIv2znEpkDd0SaZVxW6iQ=="],
64
+
65
+ "@types/qrcode": ["@types/qrcode@1.5.6", "", { "dependencies": { "@types/node": "*" } }, "sha512-te7NQcV2BOvdj2b1hCAHzAoMNuj65kNBMz0KBaxM6c3VGBOhU0dURQKOtH8CFNI/dsKkwlv32p26qYQTWoB5bw=="],
66
+
58
67
  "@types/qrcode-terminal": ["@types/qrcode-terminal@0.12.2", "", {}, "sha512-v+RcIEJ+Uhd6ygSQ0u5YYY7ZM+la7GgPbs0V/7l/kFs2uO4S8BcIUEMoP7za4DNIqNnUD5npf0A/7kBhrCKG5Q=="],
59
68
 
60
69
  "@types/react": ["@types/react@19.2.14", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="],
@@ -99,6 +108,8 @@
99
108
 
100
109
  "bun-types": ["bun-types@1.3.9", "", { "dependencies": { "@types/node": "*" } }, "sha512-+UBWWOakIP4Tswh0Bt0QD0alpTY8cb5hvgiYeWCMet9YukHbzuruIEeXC2D7nMJPB12kbh8C7XJykSexEqGKJg=="],
101
110
 
111
+ "camelcase": ["camelcase@5.3.1", "", {}, "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="],
112
+
102
113
  "chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="],
103
114
 
104
115
  "cli-boxes": ["cli-boxes@3.0.0", "", {}, "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g=="],
@@ -107,8 +118,14 @@
107
118
 
108
119
  "cli-truncate": ["cli-truncate@5.1.1", "", { "dependencies": { "slice-ansi": "^7.1.0", "string-width": "^8.0.0" } }, "sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A=="],
109
120
 
121
+ "cliui": ["cliui@6.0.0", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^6.2.0" } }, "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ=="],
122
+
110
123
  "code-excerpt": ["code-excerpt@4.0.0", "", { "dependencies": { "convert-to-spaces": "^2.0.1" } }, "sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA=="],
111
124
 
125
+ "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
126
+
127
+ "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
128
+
112
129
  "convert-to-spaces": ["convert-to-spaces@2.0.1", "", {}, "sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ=="],
113
130
 
114
131
  "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
@@ -117,8 +134,12 @@
117
134
 
118
135
  "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
119
136
 
137
+ "decamelize": ["decamelize@1.2.0", "", {}, "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA=="],
138
+
120
139
  "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="],
121
140
 
141
+ "dijkstrajs": ["dijkstrajs@1.0.3", "", {}, "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA=="],
142
+
122
143
  "emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="],
123
144
 
124
145
  "environment": ["environment@1.1.0", "", {}, "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q=="],
@@ -159,6 +180,8 @@
159
180
 
160
181
  "flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="],
161
182
 
183
+ "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="],
184
+
162
185
  "get-east-asian-width": ["get-east-asian-width@1.5.0", "", {}, "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA=="],
163
186
 
164
187
  "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="],
@@ -187,6 +210,8 @@
187
210
 
188
211
  "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="],
189
212
 
213
+ "jsqr": ["jsqr@1.4.0", "", {}, "sha512-dxLob7q65Xg2DvstYkRpkYtmKm2sPJ9oFhrhmudT1dZvNFFTlroai3AWSpLey/w5vMcLBXRgOJsbXpdN9HzU/A=="],
214
+
190
215
  "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="],
191
216
 
192
217
  "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="],
@@ -209,6 +234,8 @@
209
234
 
210
235
  "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="],
211
236
 
237
+ "p-try": ["p-try@2.2.0", "", {}, "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="],
238
+
212
239
  "patch-console": ["patch-console@2.0.0", "", {}, "sha512-0YNdUceMdaQwoKce1gatDScmMo5pu/tfABfnzEqeG0gtTmd7mh/WcwgUjtAeOU7N8nFFlbQBnFK2gXW5fGvmMA=="],
213
240
 
214
241
  "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="],
@@ -217,10 +244,14 @@
217
244
 
218
245
  "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
219
246
 
247
+ "pngjs": ["pngjs@7.0.0", "", {}, "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow=="],
248
+
220
249
  "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
221
250
 
222
251
  "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
223
252
 
253
+ "qrcode": ["qrcode@1.5.4", "", { "dependencies": { "dijkstrajs": "^1.0.1", "pngjs": "^5.0.0", "yargs": "^15.3.1" }, "bin": { "qrcode": "bin/qrcode" } }, "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg=="],
254
+
224
255
  "qrcode-terminal": ["qrcode-terminal@0.12.0", "", { "bin": { "qrcode-terminal": "./bin/qrcode-terminal.js" } }, "sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ=="],
225
256
 
226
257
  "react": ["react@19.2.4", "", {}, "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ=="],
@@ -229,12 +260,18 @@
229
260
 
230
261
  "react-reconciler": ["react-reconciler@0.33.0", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.0" } }, "sha512-KetWRytFv1epdpJc3J4G75I4WrplZE5jOL7Yq0p34+OVOKF4Se7WrdIdVC45XsSSmUTlht2FM/fM1FZb1mfQeA=="],
231
262
 
263
+ "require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="],
264
+
265
+ "require-main-filename": ["require-main-filename@2.0.0", "", {}, "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="],
266
+
232
267
  "restore-cursor": ["restore-cursor@4.0.0", "", { "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" } }, "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg=="],
233
268
 
234
269
  "scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
235
270
 
236
271
  "semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
237
272
 
273
+ "set-blocking": ["set-blocking@2.0.0", "", {}, "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw=="],
274
+
238
275
  "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
239
276
 
240
277
  "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
@@ -273,6 +310,8 @@
273
310
 
274
311
  "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
275
312
 
313
+ "which-module": ["which-module@2.0.1", "", {}, "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ=="],
314
+
276
315
  "widest-line": ["widest-line@6.0.0", "", { "dependencies": { "string-width": "^8.1.0" } }, "sha512-U89AsyEeAsyoF0zVJBkG9zBgekjgjK7yk9sje3F4IQpXBJ10TF6ByLlIfjMhcmHMJgHZI4KHt4rdNfktzxIAMA=="],
277
316
 
278
317
  "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="],
@@ -281,6 +320,12 @@
281
320
 
282
321
  "ws": ["ws@8.19.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg=="],
283
322
 
323
+ "y18n": ["y18n@4.0.3", "", {}, "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ=="],
324
+
325
+ "yargs": ["yargs@15.4.1", "", { "dependencies": { "cliui": "^6.0.0", "decamelize": "^1.2.0", "find-up": "^4.1.0", "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", "string-width": "^4.2.0", "which-module": "^2.0.0", "y18n": "^4.0.0", "yargs-parser": "^18.1.2" } }, "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A=="],
326
+
327
+ "yargs-parser": ["yargs-parser@18.1.3", "", { "dependencies": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" } }, "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ=="],
328
+
284
329
  "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
285
330
 
286
331
  "yoga-layout": ["yoga-layout@3.2.1", "", {}, "sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ=="],
@@ -291,14 +336,48 @@
291
336
 
292
337
  "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
293
338
 
339
+ "cliui/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
340
+
341
+ "cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
342
+
343
+ "cliui/wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="],
344
+
345
+ "qrcode/pngjs": ["pngjs@5.0.0", "", {}, "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw=="],
346
+
294
347
  "react-devtools-core/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="],
295
348
 
296
349
  "stack-utils/escape-string-regexp": ["escape-string-regexp@2.0.0", "", {}, "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w=="],
297
350
 
298
351
  "wrap-ansi/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
299
352
 
353
+ "yargs/find-up": ["find-up@4.1.0", "", { "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw=="],
354
+
355
+ "yargs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
356
+
300
357
  "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
301
358
 
359
+ "cliui/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
360
+
361
+ "cliui/string-width/is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
362
+
363
+ "cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
364
+
365
+ "cliui/wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
366
+
367
+ "yargs/find-up/locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="],
368
+
369
+ "yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
370
+
371
+ "yargs/string-width/is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
372
+
373
+ "yargs/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
374
+
302
375
  "@typescript-eslint/typescript-estree/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
376
+
377
+ "yargs/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="],
378
+
379
+ "yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
380
+
381
+ "yargs/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="],
303
382
  }
304
383
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vellumai/cli",
3
- "version": "0.3.14",
3
+ "version": "0.3.16",
4
4
  "description": "CLI tools for vellum-assistant",
5
5
  "type": "module",
6
6
  "exports": {
@@ -22,12 +22,17 @@
22
22
  "license": "MIT",
23
23
  "dependencies": {
24
24
  "ink": "^6.7.0",
25
+ "jsqr": "^1.4.0",
26
+ "pngjs": "^7.0.0",
27
+ "qrcode": "^1.5.4",
25
28
  "qrcode-terminal": "^0.12.0",
26
29
  "react": "^19.2.4",
27
30
  "react-devtools-core": "^6.1.2"
28
31
  },
29
32
  "devDependencies": {
30
33
  "@types/bun": "^1.2.4",
34
+ "@types/pngjs": "^6.0.5",
35
+ "@types/qrcode": "^1.5.6",
31
36
  "@types/qrcode-terminal": "^0.12.2",
32
37
  "@types/react": "^19.2.14",
33
38
  "eslint": "^10.0.0",
@@ -3,15 +3,16 @@ import { homedir } from "node:os";
3
3
  import { join } from "node:path";
4
4
 
5
5
  import { loadLatestAssistant } from "../lib/assistant-config";
6
+ import { GATEWAY_PORT } from "../lib/constants.js";
6
7
 
7
8
  // ---------------------------------------------------------------------------
8
- // Runtime API client
9
+ // Gateway API client
9
10
  // ---------------------------------------------------------------------------
10
11
 
11
- function getRuntimeUrl(): string {
12
+ function getGatewayUrl(): string {
12
13
  const entry = loadLatestAssistant();
13
14
  if (entry?.runtimeUrl) return entry.runtimeUrl;
14
- return "http://localhost:7821";
15
+ return `http://localhost:${GATEWAY_PORT}`;
15
16
  }
16
17
 
17
18
  function getBearerToken(): string | undefined {
@@ -45,7 +46,7 @@ function buildHeaders(): Record<string, string> {
45
46
  }
46
47
 
47
48
  async function apiGet(path: string): Promise<unknown> {
48
- const url = `${getRuntimeUrl()}/v1/${path}`;
49
+ const url = `${getGatewayUrl()}/v1/${path}`;
49
50
  const response = await fetch(url, { headers: buildHeaders() });
50
51
  if (!response.ok) {
51
52
  const text = await response.text();
@@ -58,7 +59,7 @@ async function apiPost(
58
59
  path: string,
59
60
  body: unknown,
60
61
  ): Promise<unknown> {
61
- const url = `${getRuntimeUrl()}/v1/${path}`;
62
+ const url = `${getGatewayUrl()}/v1/${path}`;
62
63
  const response = await fetch(url, {
63
64
  method: "POST",
64
65
  headers: buildHeaders(),
@@ -1,6 +1,5 @@
1
- import { randomBytes } from "crypto";
2
- import { existsSync, lstatSync, mkdirSync, readFileSync, readlinkSync, symlinkSync, unlinkSync, writeFileSync } from "fs";
3
- import { homedir, tmpdir, userInfo } from "os";
1
+ import { existsSync, lstatSync, mkdirSync, readFileSync, readlinkSync, symlinkSync, unlinkSync } from "fs";
2
+ import { homedir, userInfo } from "os";
4
3
  import { join } from "path";
5
4
 
6
5
  // Direct import — bun embeds this at compile time so it works in compiled binaries.
@@ -11,7 +10,6 @@ import { loadAllAssistants, saveAssistantEntry } from "../lib/assistant-config";
11
10
  import type { AssistantEntry } from "../lib/assistant-config";
12
11
  import { hatchAws } from "../lib/aws";
13
12
  import {
14
- GATEWAY_PORT,
15
13
  SPECIES_CONFIG,
16
14
  VALID_REMOTE_HOSTS,
17
15
  VALID_SPECIES,
@@ -23,21 +21,12 @@ import { startLocalDaemon, startGateway, stopLocalProcesses } from "../lib/local
23
21
  import { isProcessAlive } from "../lib/process";
24
22
  import { generateRandomSuffix } from "../lib/random-name";
25
23
  import { validateAssistantName } from "../lib/retire-archive";
26
- import { exec } from "../lib/step-runner";
27
24
 
28
25
  export type { PollResult, WatchHatchingResult } from "../lib/gcp";
29
26
 
30
27
  const INSTALL_SCRIPT_REMOTE_PATH = "/tmp/vellum-install.sh";
31
28
 
32
- // Embedded install script — bun --compile doesn't bundle non-JS assets,
33
- // so we inline it to ensure it's available in the compiled binary.
34
- import INSTALL_SCRIPT_CONTENT from "../adapters/install.sh" with { type: "text" };
35
29
 
36
- function resolveInstallScriptPath(): string {
37
- const tmpPath = join(tmpdir(), `vellum-install-${process.pid}.sh`);
38
- writeFileSync(tmpPath, INSTALL_SCRIPT_CONTENT, { mode: 0o755 });
39
- return tmpPath;
40
- }
41
30
  const HATCH_TIMEOUT_MS: Record<Species, number> = {
42
31
  vellum: 2 * 60 * 1000,
43
32
  openclaw: 10 * 60 * 1000,
@@ -403,138 +392,6 @@ function watchHatchingDesktop(
403
392
  });
404
393
  }
405
394
 
406
- function buildSshArgs(host: string): string[] {
407
- const args: string[] = [host];
408
- const keyPath = process.env.VELLUM_SSH_KEY_PATH;
409
- if (keyPath) {
410
- args.push("-i", keyPath);
411
- }
412
- args.push(
413
- "-o", "StrictHostKeyChecking=no",
414
- "-o", "UserKnownHostsFile=/dev/null",
415
- "-o", "ConnectTimeout=10",
416
- "-o", "LogLevel=ERROR",
417
- );
418
- return args;
419
- }
420
-
421
- function buildScpArgs(keyPath?: string): string[] {
422
- const args: string[] = [];
423
- if (keyPath) {
424
- args.push("-i", keyPath);
425
- }
426
- args.push(
427
- "-o", "StrictHostKeyChecking=no",
428
- "-o", "UserKnownHostsFile=/dev/null",
429
- "-o", "LogLevel=ERROR",
430
- );
431
- return args;
432
- }
433
-
434
- function extractHostname(host: string): string {
435
- return host.includes("@") ? host.split("@")[1] : host;
436
- }
437
-
438
- async function hatchCustom(
439
- species: Species,
440
- detached: boolean,
441
- name: string | null,
442
- ): Promise<void> {
443
- const host = process.env.VELLUM_CUSTOM_HOST;
444
- if (!host) {
445
- console.error("Error: VELLUM_CUSTOM_HOST environment variable is required when using --remote custom (e.g., user@hostname)");
446
- process.exit(1);
447
- }
448
-
449
- try {
450
- const hostname = extractHostname(host);
451
- const instanceName = name ?? `${species}-${generateRandomSuffix()}`;
452
-
453
- console.log(`🥚 Creating new assistant: ${instanceName}`);
454
- console.log(` Species: ${species}`);
455
- console.log(` Cloud: Custom`);
456
- console.log(` Host: ${host}`);
457
- console.log("");
458
-
459
- const sshUser = host.includes("@") ? host.split("@")[0] : userInfo().username;
460
- const bearerToken = randomBytes(32).toString("hex");
461
- const anthropicApiKey = process.env.ANTHROPIC_API_KEY;
462
- if (!anthropicApiKey) {
463
- console.error("Error: ANTHROPIC_API_KEY environment variable is not set.");
464
- process.exit(1);
465
- }
466
-
467
- const startupScript = await buildStartupScript(
468
- species,
469
- bearerToken,
470
- sshUser,
471
- anthropicApiKey,
472
- instanceName,
473
- "custom",
474
- );
475
- const startupScriptPath = join(tmpdir(), `${instanceName}-startup.sh`);
476
- writeFileSync(startupScriptPath, startupScript);
477
-
478
- const sshKeyPath = process.env.VELLUM_SSH_KEY_PATH;
479
-
480
- const installScriptPath = resolveInstallScriptPath();
481
-
482
- try {
483
- console.log("📋 Uploading install script to instance...");
484
- await exec("scp", [
485
- ...buildScpArgs(sshKeyPath),
486
- installScriptPath,
487
- `${host}:${INSTALL_SCRIPT_REMOTE_PATH}`,
488
- ]);
489
-
490
- console.log("📋 Uploading startup script to instance...");
491
- const remoteStartupPath = `/tmp/${instanceName}-startup.sh`;
492
- await exec("scp", [
493
- ...buildScpArgs(sshKeyPath),
494
- startupScriptPath,
495
- `${host}:${remoteStartupPath}`,
496
- ]);
497
-
498
- console.log("🔨 Running startup script on instance...");
499
- await exec("ssh", [
500
- ...buildSshArgs(host),
501
- `chmod +x ${remoteStartupPath} ${INSTALL_SCRIPT_REMOTE_PATH} && bash ${remoteStartupPath}`,
502
- ]);
503
- } finally {
504
- try { unlinkSync(startupScriptPath); } catch {}
505
- try { unlinkSync(installScriptPath); } catch {}
506
- }
507
-
508
- const runtimeUrl = `http://${hostname}:${GATEWAY_PORT}`;
509
- const customEntry: AssistantEntry = {
510
- assistantId: instanceName,
511
- runtimeUrl,
512
- bearerToken,
513
- cloud: "custom",
514
- species,
515
- sshUser,
516
- hatchedAt: new Date().toISOString(),
517
- };
518
- saveAssistantEntry(customEntry);
519
-
520
- if (detached) {
521
- console.log("");
522
- console.log("✅ Assistant is hatching!\n");
523
- } else {
524
- console.log("");
525
- console.log("✅ Assistant has been set up!");
526
- }
527
- console.log("Instance details:");
528
- console.log(` Name: ${instanceName}`);
529
- console.log(` Host: ${host}`);
530
- console.log(` Runtime URL: ${runtimeUrl}`);
531
- console.log("");
532
- } catch (error) {
533
- console.error("❌ Error:", error instanceof Error ? error.message : error);
534
- process.exit(1);
535
- }
536
- }
537
-
538
395
  function installCLISymlink(): void {
539
396
  const cliBinary = process.execPath;
540
397
  if (!cliBinary || !existsSync(cliBinary)) return;
@@ -665,11 +522,6 @@ export async function hatch(): Promise<void> {
665
522
  return;
666
523
  }
667
524
 
668
- if (remote === "custom") {
669
- await hatchCustom(species, detached, name);
670
- return;
671
- }
672
-
673
525
  if (remote === "aws") {
674
526
  await hatchAws(species, detached, name);
675
527
  return;
@@ -0,0 +1,163 @@
1
+ import { createHash } from "crypto";
2
+ import { readFileSync } from "fs";
3
+ import jsQR from "jsqr";
4
+ import { hostname, userInfo } from "os";
5
+ import { PNG } from "pngjs";
6
+
7
+ import { saveAssistantEntry } from "../lib/assistant-config";
8
+ import type { AssistantEntry } from "../lib/assistant-config";
9
+ import type { Species } from "../lib/constants";
10
+ import { generateRandomSuffix } from "../lib/random-name";
11
+
12
+ interface QRPairingPayload {
13
+ type: string;
14
+ v: number;
15
+ id?: string;
16
+ g: string;
17
+ pairingRequestId: string;
18
+ pairingSecret: string;
19
+ }
20
+
21
+ interface PairingResponse {
22
+ status: "approved" | "pending";
23
+ bearerToken?: string;
24
+ gatewayUrl?: string;
25
+ }
26
+
27
+ function decodeQRCodeFromPng(pngPath: string): string {
28
+ const fileData = readFileSync(pngPath);
29
+ const png = PNG.sync.read(fileData);
30
+ const code = jsQR(new Uint8ClampedArray(png.data), png.width, png.height);
31
+ if (!code) {
32
+ throw new Error("Could not decode QR code from the provided PNG image.");
33
+ }
34
+ return code.data;
35
+ }
36
+
37
+ function getDeviceId(): string {
38
+ const raw = hostname() + userInfo().username;
39
+ return createHash("sha256").update(raw).digest("hex");
40
+ }
41
+
42
+ const PAIRING_POLL_INTERVAL_MS = 2000;
43
+ const PAIRING_POLL_TIMEOUT_MS = 120_000;
44
+
45
+ async function pollForApproval(
46
+ gatewayUrl: string,
47
+ pairingRequestId: string,
48
+ pairingSecret: string,
49
+ ): Promise<PairingResponse> {
50
+ const startTime = Date.now();
51
+
52
+ while (Date.now() - startTime < PAIRING_POLL_TIMEOUT_MS) {
53
+ const statusUrl = `${gatewayUrl}/pairing/status?id=${encodeURIComponent(pairingRequestId)}&secret=${encodeURIComponent(pairingSecret)}`;
54
+ const statusRes = await fetch(statusUrl);
55
+
56
+ if (!statusRes.ok) {
57
+ const body = await statusRes.text().catch(() => "");
58
+ throw new Error(`Failed to check pairing status: HTTP ${statusRes.status}: ${body || statusRes.statusText}`);
59
+ }
60
+
61
+ const statusBody = await statusRes.json() as PairingResponse;
62
+
63
+ if (statusBody.status === "approved") {
64
+ return statusBody;
65
+ }
66
+
67
+ await new Promise((resolve) => setTimeout(resolve, PAIRING_POLL_INTERVAL_MS));
68
+ }
69
+
70
+ throw new Error("Pairing timed out waiting for approval.");
71
+ }
72
+
73
+ export async function pair(): Promise<void> {
74
+ const args = process.argv.slice(3);
75
+ const qrCodePath = args[0] || process.env.VELLUM_CUSTOM_QR_CODE_PATH;
76
+
77
+ if (!qrCodePath) {
78
+ console.error("Usage: vellum pair <path-to-qrcode.png>");
79
+ console.error("");
80
+ console.error("Pair with a remote assistant by scanning the QR code PNG generated during setup.");
81
+ process.exit(1);
82
+ }
83
+
84
+ const species: Species = "vellum";
85
+
86
+ try {
87
+ console.log("Reading QR code from provided image...");
88
+ const qrData = decodeQRCodeFromPng(qrCodePath);
89
+
90
+ let payload: QRPairingPayload;
91
+ try {
92
+ payload = JSON.parse(qrData) as QRPairingPayload;
93
+ } catch {
94
+ throw new Error("QR code does not contain valid pairing data.");
95
+ }
96
+
97
+ if (payload.type !== "vellum-daemon" || !payload.g || !payload.pairingRequestId || !payload.pairingSecret) {
98
+ throw new Error("QR code does not contain valid Vellum pairing data.");
99
+ }
100
+
101
+ const instanceName = `${species}-${generateRandomSuffix()}`;
102
+ const runtimeUrl = payload.g;
103
+ const deviceId = getDeviceId();
104
+ const deviceName = hostname();
105
+
106
+ console.log(`Pairing with remote assistant at ${runtimeUrl}...`);
107
+
108
+ const requestUrl = `${runtimeUrl}/pairing/request`;
109
+ const requestRes = await fetch(requestUrl, {
110
+ method: "POST",
111
+ headers: { "Content-Type": "application/json" },
112
+ body: JSON.stringify({
113
+ pairingRequestId: payload.pairingRequestId,
114
+ pairingSecret: payload.pairingSecret,
115
+ deviceId,
116
+ deviceName,
117
+ }),
118
+ });
119
+
120
+ if (!requestRes.ok) {
121
+ const body = await requestRes.text().catch(() => "");
122
+ throw new Error(`Failed to initiate pairing: HTTP ${requestRes.status}: ${body || requestRes.statusText}`);
123
+ }
124
+
125
+ const requestBody = await requestRes.json() as PairingResponse;
126
+
127
+ let bearerToken: string | undefined;
128
+
129
+ if (requestBody.status === "approved") {
130
+ bearerToken = requestBody.bearerToken;
131
+ } else if (requestBody.status === "pending") {
132
+ console.log("Waiting for pairing approval...");
133
+ const approvedResponse = await pollForApproval(
134
+ runtimeUrl,
135
+ payload.pairingRequestId,
136
+ payload.pairingSecret,
137
+ );
138
+ bearerToken = approvedResponse.bearerToken;
139
+ } else {
140
+ throw new Error(`Unexpected pairing response status: ${requestBody.status}`);
141
+ }
142
+
143
+ const customEntry: AssistantEntry = {
144
+ assistantId: instanceName,
145
+ runtimeUrl,
146
+ bearerToken,
147
+ cloud: "custom",
148
+ species,
149
+ hatchedAt: new Date().toISOString(),
150
+ };
151
+ saveAssistantEntry(customEntry);
152
+
153
+ console.log("");
154
+ console.log("Successfully paired with remote assistant!");
155
+ console.log("Instance details:");
156
+ console.log(` Name: ${instanceName}`);
157
+ console.log(` Runtime URL: ${runtimeUrl}`);
158
+ console.log("");
159
+ } catch (error) {
160
+ console.error("Error:", error instanceof Error ? error.message : error);
161
+ process.exit(1);
162
+ }
163
+ }
package/src/index.ts CHANGED
@@ -14,6 +14,7 @@ import { contacts } from "./commands/contacts";
14
14
  import { email } from "./commands/email";
15
15
  import { hatch } from "./commands/hatch";
16
16
  import { login, logout, whoami } from "./commands/login";
17
+ import { pair } from "./commands/pair";
17
18
  import { ps } from "./commands/ps";
18
19
  import { recover } from "./commands/recover";
19
20
  import { retire } from "./commands/retire";
@@ -30,6 +31,7 @@ const commands = {
30
31
  email,
31
32
  hatch,
32
33
  login,
34
+ pair,
33
35
  logout,
34
36
  ps,
35
37
  recover,
@@ -88,6 +90,7 @@ async function main() {
88
90
  console.log(" contacts Manage the contact graph");
89
91
  console.log(" email Email operations (status, create inbox)");
90
92
  console.log(" hatch Create a new assistant instance");
93
+ console.log(" pair Pair with a remote assistant via QR code");
91
94
  console.log(" login Log in to the Vellum platform");
92
95
  console.log(" logout Log out of the Vellum platform");
93
96
  console.log(" ps List assistants (or processes for a specific assistant)");