run402 1.69.5 → 1.69.6
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/lib/agent.mjs +37 -11
- package/lib/apps.mjs +92 -40
- package/lib/argparse.mjs +53 -1
- package/lib/billing.mjs +65 -24
- package/lib/blob.mjs +2 -2
- package/lib/cdn.mjs +21 -8
- package/lib/contracts.mjs +112 -33
- package/lib/domains.mjs +22 -11
- package/lib/image.mjs +17 -8
- package/lib/message.mjs +4 -1
- package/lib/secrets.mjs +29 -12
- package/lib/sender-domain.mjs +32 -14
- package/lib/sites.mjs +39 -16
- package/lib/subdomains.mjs +31 -35
- package/lib/tier.mjs +26 -4
- package/package.json +1 -1
- package/sdk/dist/namespaces/ai.d.ts.map +1 -1
- package/sdk/dist/namespaces/ai.js +7 -2
- package/sdk/dist/namespaces/ai.js.map +1 -1
- package/sdk/dist/namespaces/contracts.d.ts.map +1 -1
- package/sdk/dist/namespaces/contracts.js +17 -4
- package/sdk/dist/namespaces/contracts.js.map +1 -1
- package/sdk/dist/validation.d.ts +2 -0
- package/sdk/dist/validation.d.ts.map +1 -1
- package/sdk/dist/validation.js +10 -0
- package/sdk/dist/validation.js.map +1 -1
package/lib/contracts.mjs
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { getSdk } from "./sdk.mjs";
|
|
2
2
|
import { reportSdkError, fail, parseFlagJson } from "./sdk-errors.mjs";
|
|
3
|
+
import {
|
|
4
|
+
assertAllowedValue,
|
|
5
|
+
assertKnownFlags,
|
|
6
|
+
flagValue,
|
|
7
|
+
normalizeArgv,
|
|
8
|
+
positionalArgs,
|
|
9
|
+
validateEvmAddress,
|
|
10
|
+
} from "./argparse.mjs";
|
|
3
11
|
|
|
4
12
|
const HELP = `run402 contracts — KMS-backed Ethereum wallets for smart-contract calls
|
|
5
13
|
|
|
@@ -126,12 +134,6 @@ Examples:
|
|
|
126
134
|
`,
|
|
127
135
|
};
|
|
128
136
|
|
|
129
|
-
function parseFlag(args, flag) {
|
|
130
|
-
for (let i = 0; i < args.length; i++) {
|
|
131
|
-
if (args[i] === flag && args[i + 1]) return args[i + 1];
|
|
132
|
-
}
|
|
133
|
-
return null;
|
|
134
|
-
}
|
|
135
137
|
function hasFlag(args, flag) {
|
|
136
138
|
return args.includes(flag);
|
|
137
139
|
}
|
|
@@ -146,21 +148,30 @@ function validateWeiFlag(flag, value) {
|
|
|
146
148
|
}
|
|
147
149
|
|
|
148
150
|
async function provisionWallet(projectId, args) {
|
|
149
|
-
const
|
|
151
|
+
const parsedArgs = normalizeArgv(args);
|
|
152
|
+
const valueFlags = ["--chain", "--recovery"];
|
|
153
|
+
assertKnownFlags(parsedArgs, [...valueFlags, "--yes", "--help", "-h"], valueFlags);
|
|
154
|
+
const extra = positionalArgs(parsedArgs, valueFlags);
|
|
155
|
+
if (extra.length > 0) {
|
|
156
|
+
fail({ code: "BAD_USAGE", message: `Unexpected argument for contracts provision-wallet: ${extra[0]}` });
|
|
157
|
+
}
|
|
158
|
+
const chain = flagValue(parsedArgs, "--chain");
|
|
150
159
|
if (!chain) {
|
|
151
160
|
fail({
|
|
152
161
|
code: "BAD_USAGE",
|
|
153
162
|
message: "Missing --chain (base-mainnet or base-sepolia)",
|
|
154
163
|
});
|
|
155
164
|
}
|
|
156
|
-
|
|
165
|
+
assertAllowedValue(chain, ["base-mainnet", "base-sepolia"], "--chain");
|
|
166
|
+
const recovery = flagValue(parsedArgs, "--recovery");
|
|
167
|
+
if (recovery) validateEvmAddress(recovery, "--recovery");
|
|
157
168
|
// Soft default of one wallet — confirm if project already has one.
|
|
158
169
|
let activeWallets = null;
|
|
159
170
|
try {
|
|
160
171
|
const list = await getSdk().contracts.listWallets(projectId);
|
|
161
172
|
activeWallets = (list.wallets || []).filter((w) => w.status === "active").length;
|
|
162
173
|
} catch { /* best-effort */ }
|
|
163
|
-
if (activeWallets !== null && activeWallets >= 1 && !hasFlag(
|
|
174
|
+
if (activeWallets !== null && activeWallets >= 1 && !hasFlag(parsedArgs, "--yes")) {
|
|
164
175
|
fail({
|
|
165
176
|
code: "CONFIRMATION_REQUIRED",
|
|
166
177
|
message: `This project already has ${activeWallets} active wallet(s). Adding another costs $0.04/day each ($1.20/month). Re-run with --yes to confirm.`,
|
|
@@ -179,7 +190,13 @@ async function provisionWallet(projectId, args) {
|
|
|
179
190
|
}
|
|
180
191
|
}
|
|
181
192
|
|
|
182
|
-
async function getWallet(projectId, walletId) {
|
|
193
|
+
async function getWallet(projectId, walletId, args = []) {
|
|
194
|
+
const parsedArgs = normalizeArgv(args);
|
|
195
|
+
assertKnownFlags(parsedArgs, ["--help", "-h"]);
|
|
196
|
+
const extra = positionalArgs(parsedArgs);
|
|
197
|
+
if (extra.length > 0) {
|
|
198
|
+
fail({ code: "BAD_USAGE", message: `Unexpected argument for contracts get-wallet: ${extra[0]}` });
|
|
199
|
+
}
|
|
183
200
|
try {
|
|
184
201
|
const data = await getSdk().contracts.getWallet(projectId, walletId);
|
|
185
202
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -188,7 +205,13 @@ async function getWallet(projectId, walletId) {
|
|
|
188
205
|
}
|
|
189
206
|
}
|
|
190
207
|
|
|
191
|
-
async function listWallets(projectId) {
|
|
208
|
+
async function listWallets(projectId, args = []) {
|
|
209
|
+
const parsedArgs = normalizeArgv(args);
|
|
210
|
+
assertKnownFlags(parsedArgs, ["--help", "-h"]);
|
|
211
|
+
const extra = positionalArgs(parsedArgs);
|
|
212
|
+
if (extra.length > 0) {
|
|
213
|
+
fail({ code: "BAD_USAGE", message: `Unexpected argument for contracts list-wallets: ${extra[0]}` });
|
|
214
|
+
}
|
|
192
215
|
try {
|
|
193
216
|
const data = await getSdk().contracts.listWallets(projectId);
|
|
194
217
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -198,14 +221,25 @@ async function listWallets(projectId) {
|
|
|
198
221
|
}
|
|
199
222
|
|
|
200
223
|
async function setRecovery(projectId, walletId, args) {
|
|
201
|
-
const
|
|
202
|
-
const
|
|
224
|
+
const parsedArgs = normalizeArgv(args);
|
|
225
|
+
const valueFlags = ["--address"];
|
|
226
|
+
assertKnownFlags(parsedArgs, [...valueFlags, "--clear", "--help", "-h"], valueFlags);
|
|
227
|
+
const extra = positionalArgs(parsedArgs, valueFlags);
|
|
228
|
+
if (extra.length > 0) {
|
|
229
|
+
fail({ code: "BAD_USAGE", message: `Unexpected argument for contracts set-recovery: ${extra[0]}` });
|
|
230
|
+
}
|
|
231
|
+
const clear = hasFlag(parsedArgs, "--clear");
|
|
232
|
+
const address = flagValue(parsedArgs, "--address");
|
|
233
|
+
if (clear && address) {
|
|
234
|
+
fail({ code: "BAD_USAGE", message: "Provide either --address or --clear, not both." });
|
|
235
|
+
}
|
|
203
236
|
if (!clear && !address) {
|
|
204
237
|
fail({
|
|
205
238
|
code: "BAD_USAGE",
|
|
206
239
|
message: "Provide --address 0x... or --clear",
|
|
207
240
|
});
|
|
208
241
|
}
|
|
242
|
+
if (address) validateEvmAddress(address, "--address");
|
|
209
243
|
try {
|
|
210
244
|
await getSdk().contracts.setRecovery(projectId, walletId, clear ? null : address);
|
|
211
245
|
console.log(JSON.stringify({ status: "ok", wallet_id: walletId, recovery_address: clear ? null : address }));
|
|
@@ -215,7 +249,14 @@ async function setRecovery(projectId, walletId, args) {
|
|
|
215
249
|
}
|
|
216
250
|
|
|
217
251
|
async function setAlert(projectId, walletId, args) {
|
|
218
|
-
const
|
|
252
|
+
const parsedArgs = normalizeArgv(args);
|
|
253
|
+
const valueFlags = ["--threshold-wei"];
|
|
254
|
+
assertKnownFlags(parsedArgs, [...valueFlags, "--help", "-h"], valueFlags);
|
|
255
|
+
const extra = positionalArgs(parsedArgs, valueFlags);
|
|
256
|
+
if (extra.length > 0) {
|
|
257
|
+
fail({ code: "BAD_USAGE", message: `Unexpected argument for contracts set-alert: ${extra[0]}` });
|
|
258
|
+
}
|
|
259
|
+
const threshold = flagValue(parsedArgs, "--threshold-wei");
|
|
219
260
|
if (!threshold) {
|
|
220
261
|
fail({ code: "BAD_USAGE", message: "Missing --threshold-wei <n>" });
|
|
221
262
|
}
|
|
@@ -229,13 +270,20 @@ async function setAlert(projectId, walletId, args) {
|
|
|
229
270
|
}
|
|
230
271
|
|
|
231
272
|
async function call(projectId, walletId, args) {
|
|
232
|
-
const
|
|
233
|
-
const
|
|
234
|
-
|
|
235
|
-
const
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
273
|
+
const parsedArgs = normalizeArgv(args);
|
|
274
|
+
const valueFlags = ["--to", "--abi", "--fn", "--args", "--value-wei", "--chain", "--idempotency-key"];
|
|
275
|
+
assertKnownFlags(parsedArgs, [...valueFlags, "--help", "-h"], valueFlags);
|
|
276
|
+
const extra = positionalArgs(parsedArgs, valueFlags);
|
|
277
|
+
if (extra.length > 0) {
|
|
278
|
+
fail({ code: "BAD_USAGE", message: `Unexpected argument for contracts call: ${extra[0]}` });
|
|
279
|
+
}
|
|
280
|
+
const to = flagValue(parsedArgs, "--to");
|
|
281
|
+
const abi = flagValue(parsedArgs, "--abi");
|
|
282
|
+
const fn = flagValue(parsedArgs, "--fn");
|
|
283
|
+
const argsJson = flagValue(parsedArgs, "--args");
|
|
284
|
+
const value = flagValue(parsedArgs, "--value-wei");
|
|
285
|
+
const chain = flagValue(parsedArgs, "--chain") || "base-mainnet";
|
|
286
|
+
const idempotency = flagValue(parsedArgs, "--idempotency-key");
|
|
239
287
|
if (!to || !abi || !fn || !argsJson) {
|
|
240
288
|
fail({
|
|
241
289
|
code: "BAD_USAGE",
|
|
@@ -243,9 +291,11 @@ async function call(projectId, walletId, args) {
|
|
|
243
291
|
hint: "Cost: chain gas + $0.000005 KMS sign fee.",
|
|
244
292
|
});
|
|
245
293
|
}
|
|
294
|
+
assertAllowedValue(chain, ["base-mainnet", "base-sepolia"], "--chain");
|
|
246
295
|
if (value !== null) validateWeiFlag("--value-wei", value);
|
|
247
296
|
const abiFragment = parseFlagJson("--abi", abi);
|
|
248
297
|
const callArgs = parseFlagJson("--args", argsJson);
|
|
298
|
+
validateEvmAddress(to, "--to");
|
|
249
299
|
try {
|
|
250
300
|
const data = await getSdk().contracts.call(projectId, {
|
|
251
301
|
walletId,
|
|
@@ -264,19 +314,28 @@ async function call(projectId, walletId, args) {
|
|
|
264
314
|
}
|
|
265
315
|
|
|
266
316
|
async function read(args) {
|
|
267
|
-
const
|
|
268
|
-
const
|
|
269
|
-
|
|
270
|
-
const
|
|
271
|
-
|
|
317
|
+
const parsedArgs = normalizeArgv(args);
|
|
318
|
+
const valueFlags = ["--chain", "--to", "--abi", "--fn", "--args"];
|
|
319
|
+
assertKnownFlags(parsedArgs, [...valueFlags, "--help", "-h"], valueFlags);
|
|
320
|
+
const extra = positionalArgs(parsedArgs, valueFlags);
|
|
321
|
+
if (extra.length > 0) {
|
|
322
|
+
fail({ code: "BAD_USAGE", message: `Unexpected argument for contracts read: ${extra[0]}` });
|
|
323
|
+
}
|
|
324
|
+
const chain = flagValue(parsedArgs, "--chain");
|
|
325
|
+
const to = flagValue(parsedArgs, "--to");
|
|
326
|
+
const abi = flagValue(parsedArgs, "--abi");
|
|
327
|
+
const fn = flagValue(parsedArgs, "--fn");
|
|
328
|
+
const argsJson = flagValue(parsedArgs, "--args");
|
|
272
329
|
if (!chain || !to || !abi || !fn || !argsJson) {
|
|
273
330
|
fail({
|
|
274
331
|
code: "BAD_USAGE",
|
|
275
332
|
message: "Required flags: --chain, --to, --abi, --fn, --args",
|
|
276
333
|
});
|
|
277
334
|
}
|
|
335
|
+
assertAllowedValue(chain, ["base-mainnet", "base-sepolia"], "--chain");
|
|
278
336
|
const abiFragment = parseFlagJson("--abi", abi);
|
|
279
337
|
const callArgs = parseFlagJson("--args", argsJson);
|
|
338
|
+
validateEvmAddress(to, "--to");
|
|
280
339
|
try {
|
|
281
340
|
const data = await getSdk().contracts.read({
|
|
282
341
|
chain,
|
|
@@ -291,7 +350,13 @@ async function read(args) {
|
|
|
291
350
|
}
|
|
292
351
|
}
|
|
293
352
|
|
|
294
|
-
async function status(projectId, callId) {
|
|
353
|
+
async function status(projectId, callId, args = []) {
|
|
354
|
+
const parsedArgs = normalizeArgv(args);
|
|
355
|
+
assertKnownFlags(parsedArgs, ["--help", "-h"]);
|
|
356
|
+
const extra = positionalArgs(parsedArgs);
|
|
357
|
+
if (extra.length > 0) {
|
|
358
|
+
fail({ code: "BAD_USAGE", message: `Unexpected argument for contracts status: ${extra[0]}` });
|
|
359
|
+
}
|
|
295
360
|
try {
|
|
296
361
|
const data = await getSdk().contracts.callStatus(projectId, callId);
|
|
297
362
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -301,14 +366,22 @@ async function status(projectId, callId) {
|
|
|
301
366
|
}
|
|
302
367
|
|
|
303
368
|
async function drain(projectId, walletId, args) {
|
|
304
|
-
const
|
|
305
|
-
|
|
369
|
+
const parsedArgs = normalizeArgv(args);
|
|
370
|
+
const valueFlags = ["--to"];
|
|
371
|
+
assertKnownFlags(parsedArgs, [...valueFlags, "--confirm", "--help", "-h"], valueFlags);
|
|
372
|
+
const extra = positionalArgs(parsedArgs, valueFlags);
|
|
373
|
+
if (extra.length > 0) {
|
|
374
|
+
fail({ code: "BAD_USAGE", message: `Unexpected argument for contracts drain: ${extra[0]}` });
|
|
375
|
+
}
|
|
376
|
+
const to = flagValue(parsedArgs, "--to");
|
|
377
|
+
if (!to || !hasFlag(parsedArgs, "--confirm")) {
|
|
306
378
|
fail({
|
|
307
379
|
code: "BAD_USAGE",
|
|
308
380
|
message: "Required: --to 0x... and --confirm.",
|
|
309
381
|
hint: "Cost: chain gas + $0.000005 KMS sign fee.",
|
|
310
382
|
});
|
|
311
383
|
}
|
|
384
|
+
validateEvmAddress(to, "--to");
|
|
312
385
|
try {
|
|
313
386
|
const data = await getSdk().contracts.drain(projectId, walletId, to);
|
|
314
387
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -318,7 +391,13 @@ async function drain(projectId, walletId, args) {
|
|
|
318
391
|
}
|
|
319
392
|
|
|
320
393
|
async function deleteWallet(projectId, walletId, args) {
|
|
321
|
-
|
|
394
|
+
const parsedArgs = normalizeArgv(args);
|
|
395
|
+
assertKnownFlags(parsedArgs, ["--confirm", "--help", "-h"]);
|
|
396
|
+
const extra = positionalArgs(parsedArgs);
|
|
397
|
+
if (extra.length > 0) {
|
|
398
|
+
fail({ code: "BAD_USAGE", message: `Unexpected argument for contracts delete: ${extra[0]}` });
|
|
399
|
+
}
|
|
400
|
+
if (!hasFlag(parsedArgs, "--confirm")) {
|
|
322
401
|
fail({ code: "BAD_USAGE", message: "Required: --confirm" });
|
|
323
402
|
}
|
|
324
403
|
try {
|
|
@@ -334,13 +413,13 @@ export async function run(sub, args) {
|
|
|
334
413
|
if (Array.isArray(args) && (args.includes("--help") || args.includes("-h"))) { console.log(SUB_HELP[sub] || HELP); process.exit(0); }
|
|
335
414
|
switch (sub) {
|
|
336
415
|
case "provision-wallet": await provisionWallet(args[0], args.slice(1)); break;
|
|
337
|
-
case "get-wallet": await getWallet(args[0], args[1]); break;
|
|
338
|
-
case "list-wallets": await listWallets(args[0]); break;
|
|
416
|
+
case "get-wallet": await getWallet(args[0], args[1], args.slice(2)); break;
|
|
417
|
+
case "list-wallets": await listWallets(args[0], args.slice(1)); break;
|
|
339
418
|
case "set-recovery": await setRecovery(args[0], args[1], args.slice(2)); break;
|
|
340
419
|
case "set-alert": await setAlert(args[0], args[1], args.slice(2)); break;
|
|
341
420
|
case "call": await call(args[0], args[1], args.slice(2)); break;
|
|
342
421
|
case "read": await read(args); break;
|
|
343
|
-
case "status": await status(args[0], args[1]); break;
|
|
422
|
+
case "status": await status(args[0], args[1], args.slice(2)); break;
|
|
344
423
|
case "drain": await drain(args[0], args[1], args.slice(2)); break;
|
|
345
424
|
case "delete": await deleteWallet(args[0], args[1], args.slice(2)); break;
|
|
346
425
|
default:
|
package/lib/domains.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { resolveProjectId } from "./config.mjs";
|
|
2
2
|
import { getSdk } from "./sdk.mjs";
|
|
3
3
|
import { reportSdkError, fail } from "./sdk-errors.mjs";
|
|
4
|
+
import { assertKnownFlags, flagValue, normalizeArgv, positionalArgs } from "./argparse.mjs";
|
|
4
5
|
|
|
5
6
|
const HELP = `run402 domains — Manage custom domains
|
|
6
7
|
|
|
@@ -94,14 +95,15 @@ Examples:
|
|
|
94
95
|
`,
|
|
95
96
|
};
|
|
96
97
|
|
|
97
|
-
function parseProjectFlag(args) {
|
|
98
|
-
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
98
|
+
function parseProjectFlag(args, extraKnown = []) {
|
|
99
|
+
const parsedArgs = normalizeArgv(args);
|
|
100
|
+
const valueFlags = ["--project"];
|
|
101
|
+
assertKnownFlags(parsedArgs, [...valueFlags, ...extraKnown, "--help", "-h"], valueFlags);
|
|
102
|
+
return {
|
|
103
|
+
project: flagValue(parsedArgs, "--project"),
|
|
104
|
+
rest: positionalArgs(parsedArgs, valueFlags),
|
|
105
|
+
args: parsedArgs,
|
|
106
|
+
};
|
|
105
107
|
}
|
|
106
108
|
|
|
107
109
|
async function add(args) {
|
|
@@ -115,6 +117,9 @@ async function add(args) {
|
|
|
115
117
|
hint: "run402 domains add <domain> <subdomain_name> [--project <id>]",
|
|
116
118
|
});
|
|
117
119
|
}
|
|
120
|
+
if (rest.length > 2) {
|
|
121
|
+
fail({ code: "BAD_USAGE", message: `Unexpected argument for domains add: ${rest[2]}` });
|
|
122
|
+
}
|
|
118
123
|
const projectId = resolveProjectId(project);
|
|
119
124
|
try {
|
|
120
125
|
const data = await getSdk().domains.add(projectId, domain, subdomainName);
|
|
@@ -153,6 +158,9 @@ async function status(args) {
|
|
|
153
158
|
hint: "run402 domains status <domain> [--project <id>]",
|
|
154
159
|
});
|
|
155
160
|
}
|
|
161
|
+
if (rest.length > 1) {
|
|
162
|
+
fail({ code: "BAD_USAGE", message: `Unexpected argument for domains status: ${rest[1]}` });
|
|
163
|
+
}
|
|
156
164
|
const projectId = resolveProjectId(project);
|
|
157
165
|
try {
|
|
158
166
|
const data = await getSdk().domains.status(projectId, domain);
|
|
@@ -163,8 +171,8 @@ async function status(args) {
|
|
|
163
171
|
}
|
|
164
172
|
|
|
165
173
|
async function deleteDomain(args) {
|
|
166
|
-
const { project, rest } = parseProjectFlag(args);
|
|
167
|
-
const domain = rest
|
|
174
|
+
const { project, rest, args: parsedArgs } = parseProjectFlag(args, ["--confirm"]);
|
|
175
|
+
const domain = rest[0];
|
|
168
176
|
if (!domain) {
|
|
169
177
|
fail({
|
|
170
178
|
code: "BAD_USAGE",
|
|
@@ -172,7 +180,10 @@ async function deleteDomain(args) {
|
|
|
172
180
|
hint: "run402 domains delete <domain> --confirm [--project <id>]",
|
|
173
181
|
});
|
|
174
182
|
}
|
|
175
|
-
if (
|
|
183
|
+
if (rest.length > 1) {
|
|
184
|
+
fail({ code: "BAD_USAGE", message: `Unexpected argument for domains delete: ${rest[1]}` });
|
|
185
|
+
}
|
|
186
|
+
if (!parsedArgs.includes("--confirm")) {
|
|
176
187
|
fail({
|
|
177
188
|
code: "CONFIRMATION_REQUIRED",
|
|
178
189
|
message: `Destructive: releasing custom domain '${domain}' detaches it from this project and clears its DNS/SSL configuration. This is irreversible. Re-run with --confirm to proceed.`,
|
package/lib/image.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { writeFileSync } from "fs";
|
|
2
2
|
import { getSdk } from "./sdk.mjs";
|
|
3
3
|
import { reportSdkError, fail } from "./sdk-errors.mjs";
|
|
4
|
+
import { assertAllowedValue, assertKnownFlags, flagValue, normalizeArgv, positionalArgs } from "./argparse.mjs";
|
|
4
5
|
|
|
5
6
|
const HELP = `run402 image — Generate AI images via x402 micropayments
|
|
6
7
|
|
|
@@ -71,15 +72,22 @@ export async function run(sub, args) {
|
|
|
71
72
|
process.exit(1);
|
|
72
73
|
}
|
|
73
74
|
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
75
|
+
const parsedArgs = normalizeArgv(args);
|
|
76
|
+
const valueFlags = ["--aspect", "--output"];
|
|
77
|
+
assertKnownFlags(parsedArgs, [...valueFlags, "--help", "-h"], valueFlags);
|
|
78
|
+
const positionals = positionalArgs(parsedArgs, valueFlags);
|
|
79
|
+
if (positionals.length > 1) {
|
|
80
|
+
fail({
|
|
81
|
+
code: "BAD_USAGE",
|
|
82
|
+
message: `Unexpected argument for image generate: ${positionals[1]}`,
|
|
83
|
+
hint: 'Quote multi-word prompts, e.g. run402 image generate "your prompt".',
|
|
84
|
+
});
|
|
82
85
|
}
|
|
86
|
+
const opts = {
|
|
87
|
+
prompt: positionals[0] ?? null,
|
|
88
|
+
aspect: flagValue(parsedArgs, "--aspect") ?? "square",
|
|
89
|
+
output: flagValue(parsedArgs, "--output"),
|
|
90
|
+
};
|
|
83
91
|
|
|
84
92
|
if (!opts.prompt) {
|
|
85
93
|
fail({
|
|
@@ -88,6 +96,7 @@ export async function run(sub, args) {
|
|
|
88
96
|
hint: 'run402 image generate "your prompt"',
|
|
89
97
|
});
|
|
90
98
|
}
|
|
99
|
+
assertAllowedValue(opts.aspect, ["square", "landscape", "portrait"], "--aspect");
|
|
91
100
|
|
|
92
101
|
try {
|
|
93
102
|
const data = await getSdk().ai.generateImage({ prompt: opts.prompt, aspect: opts.aspect });
|
package/lib/message.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { allowanceAuthHeaders } from "./config.mjs";
|
|
2
2
|
import { getSdk } from "./sdk.mjs";
|
|
3
3
|
import { reportSdkError, fail } from "./sdk-errors.mjs";
|
|
4
|
+
import { assertKnownFlags, normalizeArgv } from "./argparse.mjs";
|
|
4
5
|
|
|
5
6
|
const HELP = `run402 message — Send messages to Run402 developers
|
|
6
7
|
|
|
@@ -88,5 +89,7 @@ export async function run(sub, args) {
|
|
|
88
89
|
console.log(HELP);
|
|
89
90
|
process.exit(1);
|
|
90
91
|
}
|
|
91
|
-
|
|
92
|
+
const parsedArgs = normalizeArgv(args);
|
|
93
|
+
assertKnownFlags(parsedArgs, ["--help", "-h"]);
|
|
94
|
+
await send(parsedArgs.join(" "));
|
|
92
95
|
}
|
package/lib/secrets.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readFileSync } from "fs";
|
|
2
2
|
import { getSdk } from "./sdk.mjs";
|
|
3
3
|
import { reportSdkError, fail } from "./sdk-errors.mjs";
|
|
4
|
-
import { validateRegularFile } from "./argparse.mjs";
|
|
4
|
+
import { assertKnownFlags, flagValue, normalizeArgv, positionalArgs, validateRegularFile } from "./argparse.mjs";
|
|
5
5
|
|
|
6
6
|
const HELP = `run402 secrets — Manage project secrets
|
|
7
7
|
|
|
@@ -78,15 +78,20 @@ Examples:
|
|
|
78
78
|
};
|
|
79
79
|
|
|
80
80
|
async function set(projectId, key, args = []) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
81
|
+
const parsedArgs = normalizeArgv(args);
|
|
82
|
+
const valueFlags = ["--file"];
|
|
83
|
+
assertKnownFlags(parsedArgs, [...valueFlags, "--help", "-h"], valueFlags);
|
|
84
|
+
const values = positionalArgs(parsedArgs, valueFlags);
|
|
85
|
+
if (values.length > 1) {
|
|
86
|
+
fail({ code: "BAD_USAGE", message: `Unexpected argument for secrets set: ${values[1]}` });
|
|
87
|
+
}
|
|
88
|
+
const file = flagValue(parsedArgs, "--file");
|
|
89
|
+
if (file && values.length > 0) {
|
|
90
|
+
fail({ code: "BAD_USAGE", message: "Provide either an inline value or --file, not both." });
|
|
86
91
|
}
|
|
87
92
|
if (file) validateRegularFile(file, "--file");
|
|
88
|
-
const val = file ? readFileSync(file, "utf-8") :
|
|
89
|
-
if (
|
|
93
|
+
const val = file ? readFileSync(file, "utf-8") : values.length === 1 ? values[0] : undefined;
|
|
94
|
+
if (val === undefined) {
|
|
90
95
|
fail({
|
|
91
96
|
code: "BAD_USAGE",
|
|
92
97
|
message: "Missing secret value.",
|
|
@@ -101,7 +106,13 @@ async function set(projectId, key, args = []) {
|
|
|
101
106
|
}
|
|
102
107
|
}
|
|
103
108
|
|
|
104
|
-
async function list(projectId) {
|
|
109
|
+
async function list(projectId, args = []) {
|
|
110
|
+
const parsedArgs = normalizeArgv(args);
|
|
111
|
+
assertKnownFlags(parsedArgs, ["--help", "-h"]);
|
|
112
|
+
const extra = positionalArgs(parsedArgs);
|
|
113
|
+
if (extra.length > 0) {
|
|
114
|
+
fail({ code: "BAD_USAGE", message: `Unexpected argument for secrets list: ${extra[0]}` });
|
|
115
|
+
}
|
|
105
116
|
try {
|
|
106
117
|
const data = await getSdk().secrets.list(projectId);
|
|
107
118
|
const sanitized = {
|
|
@@ -117,7 +128,13 @@ async function list(projectId) {
|
|
|
117
128
|
}
|
|
118
129
|
}
|
|
119
130
|
|
|
120
|
-
async function deleteSecret(projectId, key) {
|
|
131
|
+
async function deleteSecret(projectId, key, args = []) {
|
|
132
|
+
const parsedArgs = normalizeArgv(args);
|
|
133
|
+
assertKnownFlags(parsedArgs, ["--help", "-h"]);
|
|
134
|
+
const extra = positionalArgs(parsedArgs);
|
|
135
|
+
if (extra.length > 0) {
|
|
136
|
+
fail({ code: "BAD_USAGE", message: `Unexpected argument for secrets delete: ${extra[0]}` });
|
|
137
|
+
}
|
|
121
138
|
try {
|
|
122
139
|
await getSdk().secrets.delete(projectId, key);
|
|
123
140
|
console.log(JSON.stringify({ status: "ok", message: `Secret '${key}' deleted.` }));
|
|
@@ -134,8 +151,8 @@ export async function run(sub, args) {
|
|
|
134
151
|
}
|
|
135
152
|
switch (sub) {
|
|
136
153
|
case "set": await set(args[0], args[1], args.slice(2)); break;
|
|
137
|
-
case "list": await list(args[0]); break;
|
|
138
|
-
case "delete": await deleteSecret(args[0], args[1]); break;
|
|
154
|
+
case "list": await list(args[0], args.slice(1)); break;
|
|
155
|
+
case "delete": await deleteSecret(args[0], args[1], args.slice(2)); break;
|
|
139
156
|
default:
|
|
140
157
|
console.error(`Unknown subcommand: ${sub}\n`);
|
|
141
158
|
console.log(HELP);
|
package/lib/sender-domain.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { resolveProjectId } from "./config.mjs";
|
|
2
2
|
import { getSdk } from "./sdk.mjs";
|
|
3
3
|
import { reportSdkError, fail } from "./sdk-errors.mjs";
|
|
4
|
+
import { assertKnownFlags, flagValue, normalizeArgv, positionalArgs } from "./argparse.mjs";
|
|
4
5
|
|
|
5
6
|
const HELP = `run402 sender-domain — Manage custom email sender domain
|
|
6
7
|
|
|
@@ -100,18 +101,18 @@ Examples:
|
|
|
100
101
|
};
|
|
101
102
|
|
|
102
103
|
function parseFlag(args, flag) {
|
|
103
|
-
|
|
104
|
-
if (args[i] === flag && args[i + 1]) return args[i + 1];
|
|
105
|
-
}
|
|
106
|
-
return null;
|
|
104
|
+
return flagValue(normalizeArgv(args), flag);
|
|
107
105
|
}
|
|
108
106
|
|
|
109
107
|
async function register(args) {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
108
|
+
const parsedArgs = normalizeArgv(args);
|
|
109
|
+
const valueFlags = ["--project"];
|
|
110
|
+
assertKnownFlags(parsedArgs, [...valueFlags, "--help", "-h"], valueFlags);
|
|
111
|
+
const positionals = positionalArgs(parsedArgs, valueFlags);
|
|
112
|
+
let domain = positionals[0] ?? null;
|
|
113
|
+
let projectOpt = flagValue(parsedArgs, "--project");
|
|
114
|
+
if (positionals.length > 1) {
|
|
115
|
+
fail({ code: "BAD_USAGE", message: `Unexpected argument for sender-domain register: ${positionals[1]}` });
|
|
115
116
|
}
|
|
116
117
|
const projectId = resolveProjectId(projectOpt);
|
|
117
118
|
|
|
@@ -132,6 +133,13 @@ async function register(args) {
|
|
|
132
133
|
}
|
|
133
134
|
|
|
134
135
|
async function status(args) {
|
|
136
|
+
const parsedArgs = normalizeArgv(args);
|
|
137
|
+
const valueFlags = ["--project"];
|
|
138
|
+
assertKnownFlags(parsedArgs, [...valueFlags, "--help", "-h"], valueFlags);
|
|
139
|
+
const extra = positionalArgs(parsedArgs, valueFlags);
|
|
140
|
+
if (extra.length > 0) {
|
|
141
|
+
fail({ code: "BAD_USAGE", message: `Unexpected argument for sender-domain status: ${extra[0]}` });
|
|
142
|
+
}
|
|
135
143
|
const projectId = resolveProjectId(parseFlag(args, "--project"));
|
|
136
144
|
try {
|
|
137
145
|
const data = await getSdk().senderDomain.status(projectId);
|
|
@@ -142,6 +150,13 @@ async function status(args) {
|
|
|
142
150
|
}
|
|
143
151
|
|
|
144
152
|
async function remove(args) {
|
|
153
|
+
const parsedArgs = normalizeArgv(args);
|
|
154
|
+
const valueFlags = ["--project"];
|
|
155
|
+
assertKnownFlags(parsedArgs, [...valueFlags, "--help", "-h"], valueFlags);
|
|
156
|
+
const extra = positionalArgs(parsedArgs, valueFlags);
|
|
157
|
+
if (extra.length > 0) {
|
|
158
|
+
fail({ code: "BAD_USAGE", message: `Unexpected argument for sender-domain remove: ${extra[0]}` });
|
|
159
|
+
}
|
|
145
160
|
const projectId = resolveProjectId(parseFlag(args, "--project"));
|
|
146
161
|
try {
|
|
147
162
|
await getSdk().senderDomain.remove(projectId);
|
|
@@ -152,11 +167,14 @@ async function remove(args) {
|
|
|
152
167
|
}
|
|
153
168
|
|
|
154
169
|
async function inboundToggle(action, args) {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
170
|
+
const parsedArgs = normalizeArgv(args);
|
|
171
|
+
const valueFlags = ["--project"];
|
|
172
|
+
assertKnownFlags(parsedArgs, [...valueFlags, "--help", "-h"], valueFlags);
|
|
173
|
+
const positionals = positionalArgs(parsedArgs, valueFlags);
|
|
174
|
+
let domain = positionals[0] ?? null;
|
|
175
|
+
let projectOpt = flagValue(parsedArgs, "--project");
|
|
176
|
+
if (positionals.length > 1) {
|
|
177
|
+
fail({ code: "BAD_USAGE", message: `Unexpected argument for sender-domain inbound-${action}: ${positionals[1]}` });
|
|
160
178
|
}
|
|
161
179
|
const projectId = resolveProjectId(projectOpt);
|
|
162
180
|
|