run402 4.9.0 → 4.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli.mjs +14 -2
- package/lib/admin.mjs +2 -2
- package/lib/agent.mjs +2 -2
- package/lib/ai.mjs +2 -2
- package/lib/allowance.mjs +2 -2
- package/lib/apps.mjs +2 -2
- package/lib/archives.mjs +2 -7
- package/lib/argparse.mjs +63 -2
- package/lib/asset-wire.mjs +59 -0
- package/lib/assets.mjs +8 -4
- package/lib/auth.mjs +2 -2
- package/lib/billing.mjs +2 -2
- package/lib/branches.mjs +2 -6
- package/lib/cache.mjs +2 -6
- package/lib/cdn.mjs +2 -2
- package/lib/ci.mjs +2 -1
- package/lib/cloud.mjs +3 -11
- package/lib/contracts.mjs +2 -1
- package/lib/core.mjs +3 -13
- package/lib/credentials.mjs +3 -13
- package/lib/deploy.mjs +2 -5
- package/lib/doctor.mjs +32 -4
- package/lib/domains.mjs +2 -2
- package/lib/email.mjs +2 -2
- package/lib/functions.mjs +2 -2
- package/lib/grants.mjs +3 -2
- package/lib/image.mjs +2 -2
- package/lib/jobs.mjs +3 -2
- package/lib/message.mjs +2 -2
- package/lib/notifications.mjs +6 -12
- package/lib/operator.mjs +2 -7
- package/lib/org.mjs +2 -1
- package/lib/projects.mjs +2 -2
- package/lib/secrets.mjs +3 -3
- package/lib/service.mjs +3 -2
- package/lib/sites.mjs +2 -2
- package/lib/snapshots.mjs +2 -6
- package/lib/subdomains.mjs +2 -2
- package/lib/tier.mjs +2 -2
- package/lib/transfer.mjs +2 -1
- package/lib/up.mjs +12 -6
- package/lib/wallets.mjs +2 -6
- package/lib/webhook-secret.mjs +3 -8
- package/lib/webhooks.mjs +2 -2
- package/package.json +1 -1
- package/sdk/dist/actions.d.ts +20 -1
- package/sdk/dist/actions.d.ts.map +1 -1
- package/sdk/dist/actions.js.map +1 -1
- package/sdk/dist/node/actions-node.d.ts.map +1 -1
- package/sdk/dist/node/actions-node.js +114 -8
- package/sdk/dist/node/actions-node.js.map +1 -1
- package/sdk/dist/node/deploy-manifest.d.ts +36 -0
- package/sdk/dist/node/deploy-manifest.d.ts.map +1 -1
- package/sdk/dist/node/deploy-manifest.js +112 -3
- package/sdk/dist/node/deploy-manifest.js.map +1 -1
- package/sdk/dist/node/index.d.ts +1 -1
- package/sdk/dist/node/index.d.ts.map +1 -1
- package/sdk/dist/node/index.js.map +1 -1
package/cli.mjs
CHANGED
|
@@ -385,11 +385,23 @@ switch (cmd) {
|
|
|
385
385
|
}
|
|
386
386
|
default: {
|
|
387
387
|
const { fail } = await import("./lib/sdk-errors.mjs");
|
|
388
|
+
// Did-you-mean candidates: manifest families ∪ the allowlisted skipped
|
|
389
|
+
// families — together these cover every case in this switch (the
|
|
390
|
+
// cli-conventions gate keeps them in lockstep), so no second list.
|
|
391
|
+
const { COMMAND_MANIFEST, SKIPPED_FAMILIES } = await import("./lib/command-manifest.mjs");
|
|
392
|
+
const { closestWord } = await import("./lib/argparse.mjs");
|
|
393
|
+
const families = new Set([
|
|
394
|
+
...COMMAND_MANIFEST.map((entry) => entry.path[0]),
|
|
395
|
+
...Object.keys(SKIPPED_FAMILIES),
|
|
396
|
+
]);
|
|
397
|
+
const closest = typeof cmd === "string" ? closestWord(cmd, [...families]) : null;
|
|
388
398
|
fail({
|
|
389
399
|
code: "UNKNOWN_COMMAND",
|
|
390
|
-
message:
|
|
400
|
+
message: closest
|
|
401
|
+
? `Unknown command: ${cmd}. Did you mean ${closest}?`
|
|
402
|
+
: `Unknown command: ${cmd}`,
|
|
391
403
|
hint: "Run `run402 --help` for the command list.",
|
|
392
|
-
details: { command: cmd },
|
|
404
|
+
details: { command: cmd, closest: closest ? [closest] : [] },
|
|
393
405
|
});
|
|
394
406
|
}
|
|
395
407
|
}
|
package/lib/admin.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getSdk } from "./sdk.mjs";
|
|
2
2
|
import { reportSdkError, fail } from "./sdk-errors.mjs";
|
|
3
|
-
import { assertKnownFlags, hasHelp, normalizeArgv, resolveProjectSelector } from "./argparse.mjs";
|
|
3
|
+
import { assertKnownFlags, hasHelp, normalizeArgv, resolveProjectSelector, failUnknownSubcommand } from "./argparse.mjs";
|
|
4
4
|
|
|
5
5
|
const HELP = `run402 admin — Platform-admin operations (v1.57+)
|
|
6
6
|
|
|
@@ -185,6 +185,6 @@ export async function run(sub, args) {
|
|
|
185
185
|
case "archive": await archive(args); break;
|
|
186
186
|
case "reactivate": await reactivate(args); break;
|
|
187
187
|
default:
|
|
188
|
-
|
|
188
|
+
failUnknownSubcommand("admin", sub);
|
|
189
189
|
}
|
|
190
190
|
}
|
package/lib/agent.mjs
CHANGED
|
@@ -1,7 +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, flagValue, normalizeArgv, positionalArgs, validateWebhookUrl } from "./argparse.mjs";
|
|
4
|
+
import { assertKnownFlags, flagValue, normalizeArgv, positionalArgs, validateWebhookUrl, failUnknownSubcommand } from "./argparse.mjs";
|
|
5
5
|
|
|
6
6
|
const HELP = `run402 agent — Manage agent identity
|
|
7
7
|
|
|
@@ -201,6 +201,6 @@ export async function run(sub, args) {
|
|
|
201
201
|
await passkey(args);
|
|
202
202
|
return;
|
|
203
203
|
default:
|
|
204
|
-
|
|
204
|
+
failUnknownSubcommand("agent", sub);
|
|
205
205
|
}
|
|
206
206
|
}
|
package/lib/ai.mjs
CHANGED
|
@@ -1,7 +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, resolvePositionalProject } from "./argparse.mjs";
|
|
4
|
+
import { assertKnownFlags, flagValue, normalizeArgv, resolvePositionalProject, failUnknownSubcommand } from "./argparse.mjs";
|
|
5
5
|
|
|
6
6
|
const HELP = `run402 ai — AI translation and moderation tools
|
|
7
7
|
|
|
@@ -230,6 +230,6 @@ export async function run(sub, args) {
|
|
|
230
230
|
case "moderate": await moderate(args); break;
|
|
231
231
|
case "usage": await usage(args); break;
|
|
232
232
|
default:
|
|
233
|
-
|
|
233
|
+
failUnknownSubcommand("ai", sub);
|
|
234
234
|
}
|
|
235
235
|
}
|
package/lib/allowance.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readAllowance, saveAllowance, allowanceFile } from "./config.mjs";
|
|
2
2
|
import { getSdk } from "./sdk.mjs";
|
|
3
3
|
import { reportSdkError, fail } from "./sdk-errors.mjs";
|
|
4
|
-
import { assertKnownFlags, flagValue, normalizeArgv, parseIntegerFlag, positionalArgs } from "./argparse.mjs";
|
|
4
|
+
import { assertKnownFlags, flagValue, normalizeArgv, parseIntegerFlag, positionalArgs, failUnknownSubcommand } from "./argparse.mjs";
|
|
5
5
|
|
|
6
6
|
const HELP = `run402 allowance — Manage your agent allowance
|
|
7
7
|
|
|
@@ -347,6 +347,6 @@ export async function run(sub, args) {
|
|
|
347
347
|
case "checkout": await checkout(args); break;
|
|
348
348
|
case "history": await history(args); break;
|
|
349
349
|
default:
|
|
350
|
-
|
|
350
|
+
failUnknownSubcommand("allowance", sub);
|
|
351
351
|
}
|
|
352
352
|
}
|
package/lib/apps.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { allowanceAuthHeaders, saveProject } from "./config.mjs";
|
|
2
2
|
import { getSdk } from "./sdk.mjs";
|
|
3
3
|
import { reportSdkError, fail } from "./sdk-errors.mjs";
|
|
4
|
-
import { assertAllowedValue, assertKnownFlags, flagValue, normalizeArgv, positionalArgs, resolveProjectSelector } from "./argparse.mjs";
|
|
4
|
+
import { assertAllowedValue, assertKnownFlags, flagValue, normalizeArgv, positionalArgs, resolveProjectSelector, failUnknownSubcommand } from "./argparse.mjs";
|
|
5
5
|
|
|
6
6
|
const HELP = `run402 apps — Browse and manage the app marketplace
|
|
7
7
|
|
|
@@ -330,6 +330,6 @@ export async function run(sub, args) {
|
|
|
330
330
|
case "update": await update(args[0], args[1], args.slice(2)); break;
|
|
331
331
|
case "delete": await deleteVersion(args[0], args[1], args.slice(2)); break;
|
|
332
332
|
default:
|
|
333
|
-
|
|
333
|
+
failUnknownSubcommand("apps", sub);
|
|
334
334
|
}
|
|
335
335
|
}
|
package/lib/archives.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { inspectArchive, verifyArchive } from "#sdk/node";
|
|
2
2
|
import { reportSdkError, fail } from "./sdk-errors.mjs";
|
|
3
|
-
import { assertKnownFlags, hasHelp, normalizeArgv, positionalArgs } from "./argparse.mjs";
|
|
3
|
+
import { assertKnownFlags, hasHelp, normalizeArgv, positionalArgs, failUnknownSubcommand } from "./argparse.mjs";
|
|
4
4
|
|
|
5
5
|
const HELP = `run402 archives — Inspect and verify portable Run402 project archives
|
|
6
6
|
|
|
@@ -23,12 +23,7 @@ export async function run(sub, rawArgs = []) {
|
|
|
23
23
|
case "inspect": return inspect(rawArgs);
|
|
24
24
|
case "verify": return verify(rawArgs);
|
|
25
25
|
default:
|
|
26
|
-
|
|
27
|
-
code: "UNKNOWN_SUBCOMMAND",
|
|
28
|
-
message: `Unknown archives subcommand: ${sub}`,
|
|
29
|
-
hint: "Run `run402 archives --help` for usage.",
|
|
30
|
-
details: { command: "archives", subcommand: sub },
|
|
31
|
-
});
|
|
26
|
+
failUnknownSubcommand("archives", sub);
|
|
32
27
|
}
|
|
33
28
|
}
|
|
34
29
|
|
package/lib/argparse.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { existsSync, statSync } from "node:fs";
|
|
2
2
|
import { fail } from "./sdk-errors.mjs";
|
|
3
3
|
import { resolveProjectId } from "./config.mjs";
|
|
4
|
+
import { COMMAND_MANIFEST } from "./command-manifest.mjs";
|
|
4
5
|
|
|
5
6
|
export function normalizeArgv(argv = []) {
|
|
6
7
|
const out = [];
|
|
@@ -368,11 +369,17 @@ export function resolveProjectSelector(args, opts = {}) {
|
|
|
368
369
|
return resolvePositionalProject(list, opts);
|
|
369
370
|
}
|
|
370
371
|
|
|
371
|
-
|
|
372
|
+
/**
|
|
373
|
+
* Reusable did-you-mean helper: the closest candidate within Levenshtein
|
|
374
|
+
* distance ≤ 3, or null when nothing is close enough. Used for flags
|
|
375
|
+
* (`closestFlag`), top-level commands (cli.mjs's dispatch default), and
|
|
376
|
+
* subcommands (`failUnknownSubcommand`).
|
|
377
|
+
*/
|
|
378
|
+
export function closestWord(word, candidates) {
|
|
372
379
|
let best = null;
|
|
373
380
|
let bestDistance = Number.POSITIVE_INFINITY;
|
|
374
381
|
for (const candidate of candidates) {
|
|
375
|
-
const d = levenshtein(
|
|
382
|
+
const d = levenshtein(word, candidate);
|
|
376
383
|
if (d < bestDistance) {
|
|
377
384
|
best = candidate;
|
|
378
385
|
bestDistance = d;
|
|
@@ -382,6 +389,60 @@ function closestFlag(flag, candidates) {
|
|
|
382
389
|
return bestDistance <= 3 ? best : null;
|
|
383
390
|
}
|
|
384
391
|
|
|
392
|
+
function closestFlag(flag, candidates) {
|
|
393
|
+
return closestWord(flag, candidates);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Known subcommands of a command family, derived from COMMAND_MANIFEST
|
|
398
|
+
* (never hand-maintained). `family` may be multi-word for nested groups
|
|
399
|
+
* (e.g. "cloud archives", "email webhooks").
|
|
400
|
+
*/
|
|
401
|
+
export function knownSubcommands(family) {
|
|
402
|
+
const familyWords = String(family).split(" ").filter(Boolean);
|
|
403
|
+
const subs = new Set();
|
|
404
|
+
for (const entry of COMMAND_MANIFEST) {
|
|
405
|
+
if (entry.path.length <= familyWords.length) continue;
|
|
406
|
+
if (!familyWords.every((word, i) => entry.path[i] === word)) continue;
|
|
407
|
+
subs.add(entry.path[familyWords.length]);
|
|
408
|
+
}
|
|
409
|
+
return [...subs].sort();
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Shared unknown-subcommand failure: derives the family's known
|
|
414
|
+
* subcommands from COMMAND_MANIFEST and adds a `Did you mean <sub>?`
|
|
415
|
+
* suggestion plus `details.closest` / `details.known_subcommands`.
|
|
416
|
+
*
|
|
417
|
+
* Options:
|
|
418
|
+
* hint override the default `Run \`run402 <family> --help\`…` line
|
|
419
|
+
* label display label when it differs from the manifest family
|
|
420
|
+
* (e.g. the email-webhooks group is dispatched as
|
|
421
|
+
* `run402 webhooks …` but lives at ["email","webhooks",…])
|
|
422
|
+
* extraSubcommands candidates handled by the module but absent from the
|
|
423
|
+
* manifest (nested group heads, aliases)
|
|
424
|
+
* next_actions forwarded to the error envelope
|
|
425
|
+
*/
|
|
426
|
+
export function failUnknownSubcommand(family, sub, { hint, label, extraSubcommands = [], next_actions } = {}) {
|
|
427
|
+
const displayLabel = label ?? family;
|
|
428
|
+
const known = [...new Set([...knownSubcommands(family), ...extraSubcommands])].sort();
|
|
429
|
+
const closest = typeof sub === "string" ? closestWord(sub, known) : null;
|
|
430
|
+
fail({
|
|
431
|
+
code: "UNKNOWN_SUBCOMMAND",
|
|
432
|
+
message: closest
|
|
433
|
+
? `Unknown ${displayLabel} subcommand: ${sub}. Did you mean ${closest}?`
|
|
434
|
+
: `Unknown ${displayLabel} subcommand: ${sub}`,
|
|
435
|
+
hint: hint ?? `Run \`run402 ${displayLabel} --help\` for usage.`,
|
|
436
|
+
details: {
|
|
437
|
+
command: displayLabel,
|
|
438
|
+
subcommand: sub,
|
|
439
|
+
closest: closest ? [closest] : [],
|
|
440
|
+
known_subcommands: known,
|
|
441
|
+
},
|
|
442
|
+
...(next_actions ? { next_actions } : {}),
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
|
|
385
446
|
function levenshtein(a, b) {
|
|
386
447
|
const prev = Array.from({ length: b.length + 1 }, (_, i) => i);
|
|
387
448
|
const curr = Array.from({ length: b.length + 1 }, () => 0);
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* toWireAssetRef — project an SDK AssetRef (which carries camelCase TS
|
|
3
|
+
* conveniences like `cdnUrl`, `immutableUrl`, `contentSha256`, `size`) onto
|
|
4
|
+
* the CANONICAL gateway wire shape: snake_case keys only, no duplicate
|
|
5
|
+
* values under two casings.
|
|
6
|
+
*
|
|
7
|
+
* Canonical key set (gateway asset envelope):
|
|
8
|
+
* key, sha256, size_bytes, content_type, visibility, immutable,
|
|
9
|
+
* url, immutable_url, cdn_url, cdn_immutable_url, sri, etag,
|
|
10
|
+
* content_digest, + the v1.49/v1.50/v1.54 image fields
|
|
11
|
+
* (width_px, height_px, blurhash, variant_spec_version, display_url,
|
|
12
|
+
* display_immutable_url, variants, metadata, image_format, image_info,
|
|
13
|
+
* image_exif, image_exif_policy, blurhash_data_url, asset_schema).
|
|
14
|
+
*
|
|
15
|
+
* Unknown snake_case keys from newer gateways are preserved as-is; every
|
|
16
|
+
* camelCase key (the documented SDK aliases and any future ones) is dropped,
|
|
17
|
+
* with the aliases mapped back to their canonical snake twin when the snake
|
|
18
|
+
* form is missing from the input.
|
|
19
|
+
*
|
|
20
|
+
* The SDK keeps its camelCase conveniences for typed consumers (e.g.
|
|
21
|
+
* @run402/astro reads `cdnUrl`); this projector is the CLI/MCP output
|
|
22
|
+
* boundary only.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
// SDK-only convenience keys that must never appear in wire output. `size`
|
|
26
|
+
// and `cdn` are lowercase but still SDK-only: `size` duplicates
|
|
27
|
+
// `size_bytes`, `cdn` is the SDK's invalidation envelope (camelCase inner
|
|
28
|
+
// keys, locally synthesized).
|
|
29
|
+
const SDK_ONLY_KEYS = new Set(["size", "cdn"]);
|
|
30
|
+
|
|
31
|
+
export function toWireAssetRef(ref) {
|
|
32
|
+
if (!ref || typeof ref !== "object" || Array.isArray(ref)) return ref;
|
|
33
|
+
const out = {};
|
|
34
|
+
for (const [key, value] of Object.entries(ref)) {
|
|
35
|
+
if (typeof value === "function") continue; // tag emitters (scriptTag, …)
|
|
36
|
+
if (SDK_ONLY_KEYS.has(key)) continue;
|
|
37
|
+
if (/[A-Z]/.test(key)) continue; // camelCase SDK aliases/conveniences
|
|
38
|
+
out[key] = value;
|
|
39
|
+
}
|
|
40
|
+
// Canonical fields whose only SDK source is a camelCase convenience.
|
|
41
|
+
if (out.content_type === undefined && typeof ref.contentType === "string") {
|
|
42
|
+
out.content_type = ref.contentType;
|
|
43
|
+
}
|
|
44
|
+
// SDK naming vs wire naming: `cdnUrl` is the IMMUTABLE cdn url,
|
|
45
|
+
// `cdnMutableUrl` the mutable one.
|
|
46
|
+
if (out.cdn_url === undefined && ref.cdnMutableUrl !== undefined) {
|
|
47
|
+
out.cdn_url = ref.cdnMutableUrl;
|
|
48
|
+
}
|
|
49
|
+
if (out.cdn_immutable_url === undefined && ref.cdnUrl !== undefined) {
|
|
50
|
+
out.cdn_immutable_url = ref.cdnUrl;
|
|
51
|
+
}
|
|
52
|
+
if (out.content_digest === undefined && ref.contentDigest !== undefined) {
|
|
53
|
+
out.content_digest = ref.contentDigest;
|
|
54
|
+
}
|
|
55
|
+
if (out.immutable === undefined) {
|
|
56
|
+
out.immutable = ref.immutable_url !== null && ref.immutable_url !== undefined;
|
|
57
|
+
}
|
|
58
|
+
return out;
|
|
59
|
+
}
|
package/lib/assets.mjs
CHANGED
|
@@ -31,7 +31,8 @@ import { pipeline } from "node:stream/promises";
|
|
|
31
31
|
import { resolveProjectId } from "./config.mjs";
|
|
32
32
|
import { getSdk } from "./sdk.mjs";
|
|
33
33
|
import { reportSdkError, fail } from "./sdk-errors.mjs";
|
|
34
|
-
import { assertKnownFlags, hasHelp, normalizeArgv, parseIntegerFlag } from "./argparse.mjs";
|
|
34
|
+
import { assertKnownFlags, hasHelp, normalizeArgv, parseIntegerFlag, failUnknownSubcommand } from "./argparse.mjs";
|
|
35
|
+
import { toWireAssetRef } from "./asset-wire.mjs";
|
|
35
36
|
|
|
36
37
|
const HELP = `run402 blob — Direct-to-S3 blob storage
|
|
37
38
|
|
|
@@ -458,8 +459,11 @@ async function putOne(projectId, filePath, opts) {
|
|
|
458
459
|
...(opts.metadata ? { metadata: opts.metadata } : {}),
|
|
459
460
|
...(opts.exifPolicy ? { exifPolicy: opts.exifPolicy } : {}),
|
|
460
461
|
});
|
|
461
|
-
|
|
462
|
-
|
|
462
|
+
// Canonical wire shape only on stdout: snake_case keys, no camelCase
|
|
463
|
+
// duplicates (the SDK's AssetRef carries both; toWireAssetRef projects).
|
|
464
|
+
const wire = toWireAssetRef(result);
|
|
465
|
+
log(opts, { event: "done", ...wire });
|
|
466
|
+
return wire;
|
|
463
467
|
}
|
|
464
468
|
|
|
465
469
|
function computeDestKey(filePath, keyOpt) {
|
|
@@ -681,6 +685,6 @@ export async function run(sub, args) {
|
|
|
681
685
|
case "sign": await sign(defaultProject, args); break;
|
|
682
686
|
case "diagnose": await diagnose(defaultProject, args); break;
|
|
683
687
|
default:
|
|
684
|
-
|
|
688
|
+
failUnknownSubcommand("assets", sub);
|
|
685
689
|
}
|
|
686
690
|
}
|
package/lib/auth.mjs
CHANGED
|
@@ -1,7 +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, hasHelp, normalizeArgv } from "./argparse.mjs";
|
|
4
|
+
import { assertKnownFlags, hasHelp, normalizeArgv, failUnknownSubcommand } from "./argparse.mjs";
|
|
5
5
|
|
|
6
6
|
const HELP = `run402 auth — Manage project user authentication
|
|
7
7
|
|
|
@@ -757,6 +757,6 @@ export async function run(sub, args) {
|
|
|
757
757
|
case "providers": await providers(args); break;
|
|
758
758
|
case "scaffold-roles": scaffoldRoles(args); break;
|
|
759
759
|
default:
|
|
760
|
-
|
|
760
|
+
failUnknownSubcommand("auth", sub);
|
|
761
761
|
}
|
|
762
762
|
}
|
package/lib/billing.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getSdk } from "./sdk.mjs";
|
|
2
2
|
import { reportSdkError, fail } from "./sdk-errors.mjs";
|
|
3
|
-
import { assertKnownFlags, flagValue, normalizeArgv, parseIntegerFlag, positionalArgs } from "./argparse.mjs";
|
|
3
|
+
import { assertKnownFlags, flagValue, normalizeArgv, parseIntegerFlag, positionalArgs, failUnknownSubcommand } from "./argparse.mjs";
|
|
4
4
|
|
|
5
5
|
const HELP = `run402 billing — Email organizations and org checkouts
|
|
6
6
|
|
|
@@ -359,6 +359,6 @@ export async function run(sub, args) {
|
|
|
359
359
|
case "balance": await balance(args); break;
|
|
360
360
|
case "history": await history(args); break;
|
|
361
361
|
default:
|
|
362
|
-
|
|
362
|
+
failUnknownSubcommand("billing", sub);
|
|
363
363
|
}
|
|
364
364
|
}
|
package/lib/branches.mjs
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
parseIntegerFlag,
|
|
10
10
|
positionalArgs,
|
|
11
11
|
resolveProjectSelector,
|
|
12
|
+
failUnknownSubcommand,
|
|
12
13
|
} from "./argparse.mjs";
|
|
13
14
|
|
|
14
15
|
const HELP = `run402 branches — Contained project data branches
|
|
@@ -41,12 +42,7 @@ export async function run(sub, args = []) {
|
|
|
41
42
|
case "renew": return renew(rest);
|
|
42
43
|
case "delete": return deleteBranch(rest);
|
|
43
44
|
default:
|
|
44
|
-
|
|
45
|
-
code: "UNKNOWN_SUBCOMMAND",
|
|
46
|
-
message: `Unknown branches subcommand: ${sub}`,
|
|
47
|
-
hint: "Run `run402 branches --help` for usage.",
|
|
48
|
-
details: { command: "branches", subcommand: sub },
|
|
49
|
-
});
|
|
45
|
+
failUnknownSubcommand("branches", sub);
|
|
50
46
|
}
|
|
51
47
|
}
|
|
52
48
|
|
package/lib/cache.mjs
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
import { getSdk } from "./sdk.mjs";
|
|
20
20
|
import { reportSdkError, fail } from "./sdk-errors.mjs";
|
|
21
|
-
import { assertKnownFlags, flagValue, normalizeArgv } from "./argparse.mjs";
|
|
21
|
+
import { assertKnownFlags, flagValue, normalizeArgv, failUnknownSubcommand } from "./argparse.mjs";
|
|
22
22
|
import { editRequestAction } from "./next-actions.mjs";
|
|
23
23
|
|
|
24
24
|
// Locally-defined helpers — argparse.mjs's normalized form is a flat
|
|
@@ -99,11 +99,7 @@ export async function run(sub, args) {
|
|
|
99
99
|
await invalidate(args);
|
|
100
100
|
break;
|
|
101
101
|
default:
|
|
102
|
-
|
|
103
|
-
code: "UNKNOWN_SUBCOMMAND",
|
|
104
|
-
message: `Unknown cache subcommand: ${sub}`,
|
|
105
|
-
hint: "Run `run402 cache --help` for usage.",
|
|
106
|
-
details: { command: "cache", subcommand: sub },
|
|
102
|
+
failUnknownSubcommand("cache", sub, {
|
|
107
103
|
next_actions: [editRequestAction("run402 cache --help", "Choose a supported cache subcommand.")],
|
|
108
104
|
});
|
|
109
105
|
}
|
package/lib/cdn.mjs
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
import { resolveProjectId } from "./config.mjs";
|
|
17
17
|
import { getSdk } from "./sdk.mjs";
|
|
18
18
|
import { reportSdkError, fail } from "./sdk-errors.mjs";
|
|
19
|
-
import { assertKnownFlags, flagValue, normalizeArgv, parseIntegerFlag, positionalArgs } from "./argparse.mjs";
|
|
19
|
+
import { assertKnownFlags, flagValue, normalizeArgv, parseIntegerFlag, positionalArgs, failUnknownSubcommand } from "./argparse.mjs";
|
|
20
20
|
|
|
21
21
|
const HELP = `run402 cdn — CloudFront CDN diagnostics for public blob URLs
|
|
22
22
|
|
|
@@ -135,6 +135,6 @@ export async function run(sub, args) {
|
|
|
135
135
|
await waitFresh(defaultProject, args);
|
|
136
136
|
break;
|
|
137
137
|
default:
|
|
138
|
-
|
|
138
|
+
failUnknownSubcommand("cdn", sub);
|
|
139
139
|
}
|
|
140
140
|
}
|
package/lib/ci.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { execFileSync } from "node:child_process";
|
|
2
|
+
import { failUnknownSubcommand } from "./argparse.mjs";
|
|
2
3
|
import { randomBytes } from "node:crypto";
|
|
3
4
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
4
5
|
import { dirname, resolve } from "node:path";
|
|
@@ -459,6 +460,6 @@ export async function run(sub, args) {
|
|
|
459
460
|
case "revoke": await revoke(args); break;
|
|
460
461
|
case "set-asset-scopes": await setAssetScopes(args); break;
|
|
461
462
|
default:
|
|
462
|
-
|
|
463
|
+
failUnknownSubcommand("ci", sub);
|
|
463
464
|
}
|
|
464
465
|
}
|
package/lib/cloud.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import { dirname, resolve } from "node:path";
|
|
|
3
3
|
|
|
4
4
|
import { getSdk } from "./sdk.mjs";
|
|
5
5
|
import { fail, reportSdkError } from "./sdk-errors.mjs";
|
|
6
|
-
import { assertAllowedValue, assertKnownFlags, flagValue, hasHelp, normalizeArgv, parseIntegerFlag, positionalArgs, resolveProjectSelector } from "./argparse.mjs";
|
|
6
|
+
import { assertAllowedValue, assertKnownFlags, flagValue, hasHelp, normalizeArgv, parseIntegerFlag, positionalArgs, resolveProjectSelector, failUnknownSubcommand } from "./argparse.mjs";
|
|
7
7
|
|
|
8
8
|
const HELP = `run402 cloud — Run402 Cloud portability commands
|
|
9
9
|
|
|
@@ -60,11 +60,7 @@ export async function run(sub, args = []) {
|
|
|
60
60
|
return;
|
|
61
61
|
}
|
|
62
62
|
if (sub !== "archives") {
|
|
63
|
-
|
|
64
|
-
code: "UNKNOWN_SUBCOMMAND",
|
|
65
|
-
message: `Unknown cloud subcommand: ${sub}`,
|
|
66
|
-
hint: "Run `run402 cloud --help` for usage.",
|
|
67
|
-
details: { command: "cloud", subcommand: sub },
|
|
63
|
+
failUnknownSubcommand("cloud", sub, {
|
|
68
64
|
next_actions: [{ type: "run_command", command: "run402 cloud archives --help" }],
|
|
69
65
|
});
|
|
70
66
|
}
|
|
@@ -73,11 +69,7 @@ export async function run(sub, args = []) {
|
|
|
73
69
|
if (action === "create") return create(rest);
|
|
74
70
|
if (action === "download") return download(rest);
|
|
75
71
|
if (action === "status") return status(rest);
|
|
76
|
-
|
|
77
|
-
code: "UNKNOWN_SUBCOMMAND",
|
|
78
|
-
message: `Unknown cloud archives subcommand: ${action}`,
|
|
79
|
-
hint: "Run `run402 cloud archives --help` for usage.",
|
|
80
|
-
details: { command: "cloud archives", subcommand: action },
|
|
72
|
+
failUnknownSubcommand("cloud archives", action, {
|
|
81
73
|
next_actions: [{ type: "run_command", command: "run402 cloud archives --help" }],
|
|
82
74
|
});
|
|
83
75
|
}
|
package/lib/contracts.mjs
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
positionalArgs,
|
|
9
9
|
resolveProjectSelector,
|
|
10
10
|
validateEvmAddress,
|
|
11
|
+
failUnknownSubcommand,
|
|
11
12
|
} from "./argparse.mjs";
|
|
12
13
|
|
|
13
14
|
const HELP = `run402 contracts — KMS-backed Ethereum signers for smart-contract calls
|
|
@@ -520,6 +521,6 @@ export async function run(sub, args) {
|
|
|
520
521
|
case "drain": { const { projectId, rest } = select(); await drain(projectId, rest[0], rest.slice(1)); break; }
|
|
521
522
|
case "delete": { const { projectId, rest } = select(); await deleteSigner(projectId, rest[0], rest.slice(1)); break; }
|
|
522
523
|
default:
|
|
523
|
-
|
|
524
|
+
failUnknownSubcommand("contracts", sub);
|
|
524
525
|
}
|
|
525
526
|
}
|
package/lib/core.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { importArchiveToCore } from "#sdk/node";
|
|
2
2
|
import { fail, reportSdkError } from "./sdk-errors.mjs";
|
|
3
|
-
import { assertKnownFlags, flagValue, hasHelp, normalizeArgv, positionalArgs } from "./argparse.mjs";
|
|
3
|
+
import { assertKnownFlags, flagValue, hasHelp, normalizeArgv, positionalArgs, failUnknownSubcommand } from "./argparse.mjs";
|
|
4
4
|
|
|
5
5
|
const HELP = `run402 core — Local Run402 Core commands
|
|
6
6
|
|
|
@@ -29,21 +29,11 @@ export async function run(sub, args = []) {
|
|
|
29
29
|
return;
|
|
30
30
|
}
|
|
31
31
|
if (sub !== "projects") {
|
|
32
|
-
|
|
33
|
-
code: "UNKNOWN_SUBCOMMAND",
|
|
34
|
-
message: `Unknown core subcommand: ${sub}`,
|
|
35
|
-
hint: "Run `run402 core --help` for usage.",
|
|
36
|
-
details: { command: "core", subcommand: sub },
|
|
37
|
-
});
|
|
32
|
+
failUnknownSubcommand("core", sub);
|
|
38
33
|
}
|
|
39
34
|
const action = args[0];
|
|
40
35
|
if (action === "import" || action === "apply") return importProject(args.slice(1));
|
|
41
|
-
|
|
42
|
-
code: "UNKNOWN_SUBCOMMAND",
|
|
43
|
-
message: `Unknown core projects subcommand: ${action}`,
|
|
44
|
-
hint: "Run `run402 core projects --help` for usage.",
|
|
45
|
-
details: { command: "core projects", subcommand: action },
|
|
46
|
-
});
|
|
36
|
+
failUnknownSubcommand("core projects", action, { extraSubcommands: ["apply"] });
|
|
47
37
|
}
|
|
48
38
|
|
|
49
39
|
async function importProject(rawArgs) {
|
package/lib/credentials.mjs
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
removeProject,
|
|
9
9
|
saveProject,
|
|
10
10
|
} from "./config.mjs";
|
|
11
|
-
import { assertKnownFlags, flagValue, normalizeArgv, positionalArgs } from "./argparse.mjs";
|
|
11
|
+
import { assertKnownFlags, flagValue, normalizeArgv, positionalArgs, failUnknownSubcommand } from "./argparse.mjs";
|
|
12
12
|
import { fail } from "./sdk-errors.mjs";
|
|
13
13
|
|
|
14
14
|
const HELP = `run402 credentials — Manage local credential material
|
|
@@ -245,12 +245,7 @@ async function runProjectKeys(sub, args) {
|
|
|
245
245
|
case "export": await exportKey(args); break;
|
|
246
246
|
case "remove": await remove(args); break;
|
|
247
247
|
default:
|
|
248
|
-
|
|
249
|
-
code: "UNKNOWN_SUBCOMMAND",
|
|
250
|
-
message: `Unknown credentials project-keys subcommand: ${sub}`,
|
|
251
|
-
hint: "Run `run402 credentials project-keys --help` for usage.",
|
|
252
|
-
details: { command: "credentials project-keys", subcommand: sub },
|
|
253
|
-
});
|
|
248
|
+
failUnknownSubcommand("credentials project-keys", sub);
|
|
254
249
|
}
|
|
255
250
|
}
|
|
256
251
|
|
|
@@ -264,10 +259,5 @@ export async function run(sub, args = []) {
|
|
|
264
259
|
await runProjectKeys(projectKeySub, rest);
|
|
265
260
|
return;
|
|
266
261
|
}
|
|
267
|
-
|
|
268
|
-
code: "UNKNOWN_SUBCOMMAND",
|
|
269
|
-
message: `Unknown credentials subcommand: ${sub}`,
|
|
270
|
-
hint: "Run `run402 credentials --help` for usage.",
|
|
271
|
-
details: { command: "credentials", subcommand: sub },
|
|
272
|
-
});
|
|
262
|
+
failUnknownSubcommand("credentials", sub);
|
|
273
263
|
}
|
package/lib/deploy.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { failUnknownSubcommand } from "./argparse.mjs";
|
|
2
2
|
|
|
3
3
|
const HELP = `run402 deploy — Unified deploy operations
|
|
4
4
|
|
|
@@ -65,11 +65,8 @@ export async function run(args) {
|
|
|
65
65
|
return;
|
|
66
66
|
}
|
|
67
67
|
default:
|
|
68
|
-
|
|
69
|
-
code: "BAD_USAGE",
|
|
70
|
-
message: `Unknown deploy subcommand: ${sub}`,
|
|
68
|
+
failUnknownSubcommand("deploy", sub, {
|
|
71
69
|
hint: "Use `run402 deploy apply --manifest <file>` for deployments.",
|
|
72
|
-
details: { subcommand: sub },
|
|
73
70
|
});
|
|
74
71
|
}
|
|
75
72
|
}
|
package/lib/doctor.mjs
CHANGED
|
@@ -63,6 +63,27 @@ function redactAllowanceForDiagnostics(allowance) {
|
|
|
63
63
|
return safe;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
/**
|
|
67
|
+
* Compose a check-failure message context-first.
|
|
68
|
+
*
|
|
69
|
+
* The SDK kernel composes thrown messages as `<envelope message> while
|
|
70
|
+
* <context>`, which reads as two jammed fragments when the envelope message
|
|
71
|
+
* ends with a period ("…header. while checking tier status"). Strip the
|
|
72
|
+
* SDK's trailing ` while <context>` segment (using the error's own
|
|
73
|
+
* `context` field) and lead with the check label instead.
|
|
74
|
+
*/
|
|
75
|
+
function describeCheckFailure(label, err) {
|
|
76
|
+
const raw = err instanceof Error ? err.message : String(err);
|
|
77
|
+
const context = typeof err?.context === "string" && err.context.length > 0 ? err.context : null;
|
|
78
|
+
let reason = raw;
|
|
79
|
+
if (context) {
|
|
80
|
+
const marker = ` while ${context}`;
|
|
81
|
+
const idx = raw.indexOf(marker);
|
|
82
|
+
if (idx !== -1) reason = (raw.slice(0, idx) + raw.slice(idx + marker.length)).trim();
|
|
83
|
+
}
|
|
84
|
+
return `${label} failed: ${reason}`;
|
|
85
|
+
}
|
|
86
|
+
|
|
66
87
|
export async function run(sub, args = []) {
|
|
67
88
|
const all = [sub, ...args].filter(Boolean);
|
|
68
89
|
if (all.includes("--help") || all.includes("-h")) {
|
|
@@ -111,9 +132,11 @@ export async function run(sub, args = []) {
|
|
|
111
132
|
}
|
|
112
133
|
|
|
113
134
|
// 2. Allowance.
|
|
135
|
+
let allowanceConfigured = false;
|
|
114
136
|
try {
|
|
115
137
|
const allowance = readAllowance();
|
|
116
138
|
if (allowance) {
|
|
139
|
+
allowanceConfigured = true;
|
|
117
140
|
checks.push({
|
|
118
141
|
name: "allowance",
|
|
119
142
|
status: "ok",
|
|
@@ -152,8 +175,13 @@ export async function run(sub, args = []) {
|
|
|
152
175
|
name: "projects",
|
|
153
176
|
status: "ok",
|
|
154
177
|
value: { project_count: projectCount },
|
|
178
|
+
// State-aware parenthetical: only claim the wallet is set up when the
|
|
179
|
+
// allowance check above actually passed; pre-init installs are pointed
|
|
180
|
+
// at `run402 init` first.
|
|
155
181
|
...(projectCount === 0 && {
|
|
156
|
-
hint:
|
|
182
|
+
hint: allowanceConfigured
|
|
183
|
+
? "No projects yet — run 'run402 projects provision' to create one (wallet is already set up)."
|
|
184
|
+
: "No projects yet — run 'run402 init' to set up the wallet first, then 'run402 projects provision'.",
|
|
157
185
|
}),
|
|
158
186
|
});
|
|
159
187
|
} catch (err) {
|
|
@@ -224,7 +252,7 @@ export async function run(sub, args = []) {
|
|
|
224
252
|
checks.push({
|
|
225
253
|
name: "tier",
|
|
226
254
|
status: "error",
|
|
227
|
-
message:
|
|
255
|
+
message: describeCheckFailure("tier status check", err),
|
|
228
256
|
});
|
|
229
257
|
}
|
|
230
258
|
|
|
@@ -324,13 +352,13 @@ export async function run(sub, args = []) {
|
|
|
324
352
|
checks.push({
|
|
325
353
|
name: "operator_health",
|
|
326
354
|
status: "skipped",
|
|
327
|
-
message:
|
|
355
|
+
message: describeCheckFailure("operator status check", err),
|
|
328
356
|
...(verbose && { hint: "GET /agent/v1/operator/status not reachable; requires v1.55+ gateway." }),
|
|
329
357
|
});
|
|
330
358
|
checks.push({
|
|
331
359
|
name: "runtime_staleness",
|
|
332
360
|
status: "skipped",
|
|
333
|
-
message:
|
|
361
|
+
message: describeCheckFailure("operator status check", err),
|
|
334
362
|
});
|
|
335
363
|
}
|
|
336
364
|
|