run402 1.53.0 → 1.53.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/lib/apps.mjs +1 -1
  2. package/lib/domains.mjs +13 -4
  3. package/lib/email.mjs +5 -10
  4. package/lib/projects.mjs +14 -4
  5. package/lib/sites.mjs +84 -1
  6. package/lib/subdomains.mjs +23 -7
  7. package/package.json +1 -1
  8. package/sdk/dist/errors.d.ts +73 -0
  9. package/sdk/dist/errors.d.ts.map +1 -1
  10. package/sdk/dist/errors.js +128 -0
  11. package/sdk/dist/errors.js.map +1 -1
  12. package/sdk/dist/index.d.ts +4 -2
  13. package/sdk/dist/index.d.ts.map +1 -1
  14. package/sdk/dist/index.js +2 -1
  15. package/sdk/dist/index.js.map +1 -1
  16. package/sdk/dist/namespaces/admin.d.ts +4 -1
  17. package/sdk/dist/namespaces/admin.d.ts.map +1 -1
  18. package/sdk/dist/namespaces/admin.js +1 -1
  19. package/sdk/dist/namespaces/admin.js.map +1 -1
  20. package/sdk/dist/namespaces/apps.d.ts +27 -30
  21. package/sdk/dist/namespaces/apps.d.ts.map +1 -1
  22. package/sdk/dist/namespaces/apps.js.map +1 -1
  23. package/sdk/dist/namespaces/billing.d.ts +15 -6
  24. package/sdk/dist/namespaces/billing.d.ts.map +1 -1
  25. package/sdk/dist/namespaces/billing.js.map +1 -1
  26. package/sdk/dist/namespaces/contracts.d.ts +67 -15
  27. package/sdk/dist/namespaces/contracts.d.ts.map +1 -1
  28. package/sdk/dist/namespaces/contracts.js +32 -8
  29. package/sdk/dist/namespaces/contracts.js.map +1 -1
  30. package/sdk/dist/namespaces/domains.d.ts +5 -1
  31. package/sdk/dist/namespaces/domains.d.ts.map +1 -1
  32. package/sdk/dist/namespaces/domains.js +1 -1
  33. package/sdk/dist/namespaces/domains.js.map +1 -1
  34. package/sdk/dist/namespaces/email.d.ts +21 -13
  35. package/sdk/dist/namespaces/email.d.ts.map +1 -1
  36. package/sdk/dist/namespaces/email.js +5 -4
  37. package/sdk/dist/namespaces/email.js.map +1 -1
  38. package/sdk/dist/namespaces/functions.d.ts +2 -2
  39. package/sdk/dist/namespaces/functions.d.ts.map +1 -1
  40. package/sdk/dist/namespaces/functions.js +1 -1
  41. package/sdk/dist/namespaces/functions.js.map +1 -1
  42. package/sdk/dist/namespaces/functions.types.d.ts +4 -0
  43. package/sdk/dist/namespaces/functions.types.d.ts.map +1 -1
  44. package/sdk/dist/namespaces/projects.d.ts.map +1 -1
  45. package/sdk/dist/namespaces/projects.js +3 -5
  46. package/sdk/dist/namespaces/projects.js.map +1 -1
  47. package/sdk/dist/namespaces/projects.types.d.ts +9 -1
  48. package/sdk/dist/namespaces/projects.types.d.ts.map +1 -1
  49. package/sdk/dist/namespaces/secrets.d.ts +5 -1
  50. package/sdk/dist/namespaces/secrets.d.ts.map +1 -1
  51. package/sdk/dist/namespaces/secrets.js +1 -1
  52. package/sdk/dist/namespaces/secrets.js.map +1 -1
  53. package/sdk/dist/namespaces/sender-domain.d.ts +4 -1
  54. package/sdk/dist/namespaces/sender-domain.d.ts.map +1 -1
  55. package/sdk/dist/namespaces/sender-domain.js +1 -1
  56. package/sdk/dist/namespaces/sender-domain.js.map +1 -1
  57. package/sdk/dist/namespaces/service.d.ts +11 -31
  58. package/sdk/dist/namespaces/service.d.ts.map +1 -1
  59. package/sdk/dist/namespaces/service.js.map +1 -1
  60. package/sdk/dist/namespaces/subdomains.d.ts +10 -1
  61. package/sdk/dist/namespaces/subdomains.d.ts.map +1 -1
  62. package/sdk/dist/namespaces/subdomains.js +1 -1
  63. package/sdk/dist/namespaces/subdomains.js.map +1 -1
  64. package/sdk/dist/namespaces/tier.d.ts +9 -1
  65. package/sdk/dist/namespaces/tier.d.ts.map +1 -1
  66. package/sdk/dist/namespaces/tier.js.map +1 -1
  67. package/sdk/dist/node/index.d.ts +2 -2
  68. package/sdk/dist/node/index.d.ts.map +1 -1
  69. package/sdk/dist/node/index.js +1 -1
  70. package/sdk/dist/node/index.js.map +1 -1
  71. package/sdk/dist/retry.d.ts +50 -0
  72. package/sdk/dist/retry.d.ts.map +1 -0
  73. package/sdk/dist/retry.js +61 -0
  74. package/sdk/dist/retry.js.map +1 -0
  75. package/sdk/dist/scoped.d.ts +13 -13
  76. package/sdk/dist/scoped.d.ts.map +1 -1
  77. package/sdk/dist/scoped.js.map +1 -1
package/lib/apps.mjs CHANGED
@@ -72,7 +72,7 @@ Arguments:
72
72
  Options:
73
73
  --description <d> Human-readable description of the app
74
74
  --tags <t1,t2> Comma-separated list of tags
75
- --visibility <v> Visibility: 'public' or 'private'
75
+ --visibility <v> Visibility: 'public', 'unlisted', or 'private'
76
76
  --fork-allowed Allow other users to fork this app
77
77
 
78
78
  Examples:
package/lib/domains.mjs CHANGED
@@ -11,14 +11,14 @@ Subcommands:
11
11
  add <domain> <subdomain_name> [--project <id>] Register a custom domain
12
12
  list [<id>] List custom domains for a project
13
13
  status <domain> [--project <id>] Check domain DNS/SSL status
14
- delete <domain> [--project <id>] Release a custom domain
14
+ delete <domain> --confirm [--project <id>] Release a custom domain. Requires --confirm.
15
15
 
16
16
  Examples:
17
17
  run402 domains add example.com myapp
18
18
  run402 domains add example.com myapp --project prj_123
19
19
  run402 domains list
20
20
  run402 domains status example.com
21
- run402 domains delete example.com
21
+ run402 domains delete example.com --confirm
22
22
 
23
23
  Notes:
24
24
  - After adding a domain, configure DNS as shown in the response
@@ -75,8 +75,17 @@ async function status(args) {
75
75
 
76
76
  async function deleteDomain(args) {
77
77
  const { project, rest } = parseProjectFlag(args);
78
- const domain = rest[0];
79
- if (!domain) { console.error("Usage: run402 domains delete <domain> [--project <id>]"); process.exit(1); }
78
+ const domain = rest.find((a) => !a.startsWith("--"));
79
+ if (!domain) { console.error("Usage: run402 domains delete <domain> --confirm [--project <id>]"); process.exit(1); }
80
+ if (!Array.isArray(args) || !args.includes("--confirm")) {
81
+ console.error(JSON.stringify({
82
+ status: "error",
83
+ code: "CONFIRMATION_REQUIRED",
84
+ 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.`,
85
+ details: { domain },
86
+ }));
87
+ process.exit(1);
88
+ }
80
89
  const projectId = resolveProjectId(project);
81
90
  try {
82
91
  await getSdk().domains.remove(domain, { projectId });
package/lib/email.mjs CHANGED
@@ -167,12 +167,7 @@ async function create(args) {
167
167
 
168
168
  try {
169
169
  const data = await getSdk().email.createMailbox(projectId, slug);
170
- // SDK may return CreateMailboxResult (with slug) on success, or MailboxInfo on 409 idempotency.
171
- if (data.slug) {
172
- console.log(JSON.stringify({ status: "ok", mailbox_id: data.mailbox_id, address: data.address, slug: data.slug }));
173
- } else {
174
- console.log(JSON.stringify({ status: "ok", mailbox_id: data.mailbox_id, address: data.address, already_existed: true }));
175
- }
170
+ console.log(JSON.stringify({ status: "ok", mailbox_id: data.mailbox_id, address: data.address, slug: data.slug }));
176
171
  } catch (err) {
177
172
  reportSdkError(err);
178
173
  }
@@ -203,7 +198,7 @@ async function send(args) {
203
198
  text: text ?? undefined,
204
199
  from_name: fromName ?? undefined,
205
200
  });
206
- console.log(JSON.stringify({ status: "ok", message_id: data.id, to: data.to, template: data.template || null, subject: data.subject || null }));
201
+ console.log(JSON.stringify({ status: "ok", message_id: data.message_id, to: data.to, template: data.template, subject: data.subject }));
207
202
  } catch (err) {
208
203
  reportSdkError(err);
209
204
  }
@@ -325,7 +320,7 @@ async function reply(args) {
325
320
  from_name: fromName ?? undefined,
326
321
  in_reply_to: messageId,
327
322
  });
328
- console.log(JSON.stringify({ status: "ok", message_id: data.id, to: data.to, subject: replySubject, in_reply_to: messageId }));
323
+ console.log(JSON.stringify({ status: "ok", message_id: data.message_id, to: data.to, subject: replySubject, in_reply_to: messageId }));
329
324
  } catch (err) {
330
325
  reportSdkError(err);
331
326
  }
@@ -352,8 +347,8 @@ async function deleteMailbox(args) {
352
347
  }
353
348
 
354
349
  try {
355
- await getSdk().email.deleteMailbox(projectId, positional ?? undefined);
356
- console.log(JSON.stringify({ status: "ok", mailbox_id: positional ?? "(resolved)", deleted: true }));
350
+ const data = await getSdk().email.deleteMailbox(projectId, positional ?? undefined);
351
+ console.log(JSON.stringify({ status: "ok", mailbox_id: data.mailbox_id, address: data.address, deleted: true }));
357
352
  } catch (err) {
358
353
  reportSdkError(err);
359
354
  }
package/lib/projects.mjs CHANGED
@@ -22,7 +22,7 @@ Subcommands:
22
22
  apply-expose [id] <manifest_json> Apply a declarative authorization manifest
23
23
  apply-expose [id] --file <path> Apply a manifest from a JSON file
24
24
  get-expose [id] Get the current authorization manifest
25
- delete [id] Immediately and irreversibly delete a project (cascade purge) and remove from local state
25
+ delete [id] --confirm Immediately and irreversibly delete a project (cascade purge) and remove from local state. Requires --confirm.
26
26
  pin [id] Pin a project (admin only; project owners get 403 admin_required)
27
27
  promote-user [id] <email> Promote a user to project_admin role
28
28
  demote-user [id] <email> Demote a user from project_admin role
@@ -43,7 +43,7 @@ Examples:
43
43
  run402 projects apply-expose abc123 --file manifest.json
44
44
  run402 projects get-expose abc123
45
45
  run402 projects keys abc123
46
- run402 projects delete abc123
46
+ run402 projects delete abc123 --confirm
47
47
 
48
48
  Notes:
49
49
  - <id> is the project_id shown in 'run402 projects list' (prefix: 'prj_')
@@ -302,7 +302,17 @@ async function demoteUser(projectId, email) {
302
302
  console.log(JSON.stringify(data, null, 2));
303
303
  }
304
304
 
305
- async function deleteProject(projectId) {
305
+ async function deleteProject(projectId, args = []) {
306
+ const confirmed = Array.isArray(args) && args.includes("--confirm");
307
+ if (!confirmed) {
308
+ console.error(JSON.stringify({
309
+ status: "error",
310
+ code: "CONFIRMATION_REQUIRED",
311
+ message: `Destructive: deleting project ${projectId} drops all DB schemas, functions, subdomains, mailbox, blobs, and secrets. This is irreversible. Re-run with --confirm to proceed.`,
312
+ details: { project_id: projectId, destroys: ["schemas", "functions", "subdomains", "mailbox", "blobs", "secrets"] },
313
+ }));
314
+ process.exit(1);
315
+ }
306
316
  try {
307
317
  await getSdk().projects.delete(projectId);
308
318
  console.log(JSON.stringify({ status: "ok", message: `Project ${projectId} deleted.` }));
@@ -346,7 +356,7 @@ export async function run(sub, args) {
346
356
  case "schema": { const { projectId } = resolvePositionalProject(args); await schema(projectId); break; }
347
357
  case "apply-expose": { const { projectId, rest } = resolvePositionalProject(args); await applyExpose(projectId, rest); break; }
348
358
  case "get-expose": { const { projectId } = resolvePositionalProject(args); await getExpose(projectId); break; }
349
- case "delete": { const { projectId } = resolvePositionalProject(args); await deleteProject(projectId); break; }
359
+ case "delete": { const { projectId, rest } = resolvePositionalProject(args); await deleteProject(projectId, rest); break; }
350
360
  case "pin": { const { projectId } = resolvePositionalProject(args); await pin(projectId); break; }
351
361
  case "promote-user": { const { projectId, rest } = resolvePositionalProject(args); await promoteUser(projectId, rest[0]); break; }
352
362
  case "demote-user": { const { projectId, rest } = resolvePositionalProject(args); await demoteUser(projectId, rest[0]); break; }
package/lib/sites.mjs CHANGED
@@ -1,11 +1,14 @@
1
1
  import { mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "fs";
2
2
  import { tmpdir } from "os";
3
3
  import { dirname, join, resolve } from "path";
4
+ import { fileSetFromDir } from "#sdk/node";
4
5
  import { allowanceAuthHeaders, resolveProjectId, updateProject } from "./config.mjs";
5
6
  import { resolveFilePathsInManifest } from "./manifest.mjs";
6
7
  import { getSdk } from "./sdk.mjs";
7
8
  import { reportSdkError } from "./sdk-errors.mjs";
8
9
 
10
+ const SMALL_DIR_THRESHOLD = 5;
11
+
9
12
  const HELP = `run402 sites - Deploy and manage static sites
10
13
 
11
14
  Usage:
@@ -28,6 +31,9 @@ Options (deploy-dir):
28
31
  --project <id> Project ID (defaults to active project)
29
32
  --target <target> Deployment target (e.g. 'production')
30
33
  --quiet Suppress progress events on stderr
34
+ --dry-run Plan-only: print the diff envelope and exit
35
+ --confirm-prune Required when <path> has fewer files than the
36
+ small-dir guardrail threshold
31
37
 
32
38
  Manifest format (JSON):
33
39
  {
@@ -97,6 +103,7 @@ Examples:
97
103
 
98
104
  Usage:
99
105
  run402 sites deploy-dir <path> [--project <id>] [--target <target>] [--quiet]
106
+ [--dry-run] [--confirm-prune]
100
107
 
101
108
  Arguments:
102
109
  <path> Local directory to deploy (positional, required)
@@ -106,11 +113,23 @@ Options:
106
113
  --target <target> Deployment target (e.g. 'production')
107
114
  --quiet Suppress progress events on stderr (events are on by
108
115
  default — see Progress events below)
116
+ --dry-run Plan the deploy and print a JSON envelope describing
117
+ what would happen, then exit. Does NOT upload bytes
118
+ or commit a release.
119
+ --confirm-prune Acknowledge that deploying <path> may remove files
120
+ that exist in the current site but are absent from
121
+ <path>. Required when <path> contains fewer than
122
+ ${SMALL_DIR_THRESHOLD} files (the small-dir guardrail).
109
123
 
110
124
  Behavior:
111
125
  - Walks <path> recursively, skips .git / node_modules / .DS_Store
112
126
  - Computes per-file SHA-256 and uploads only bytes the gateway doesn't
113
127
  already have (CAS-backed unified deploy primitive)
128
+ - A static-site deploy REPLACES the live release: any path in the current
129
+ site that is absent from <path> is removed from the new release. To
130
+ avoid accidentally wiping a multi-page site by deploying a single-file
131
+ directory, a small <path> (fewer than ${SMALL_DIR_THRESHOLD} files) requires
132
+ --confirm-prune.
114
133
  - Symlinks are rejected (no following)
115
134
  - Paths in the manifest are POSIX-style relative to <path>
116
135
 
@@ -131,6 +150,8 @@ Examples:
131
150
  run402 sites deploy-dir ./dist --project prj_abc
132
151
  run402 sites deploy-dir ./my-site --project prj_abc --target production
133
152
  run402 sites deploy-dir ./dist --project prj_abc --quiet
153
+ run402 sites deploy-dir ./tiny-site --project prj_abc --confirm-prune
154
+ run402 sites deploy-dir ./dist --project prj_abc --dry-run
134
155
  `,
135
156
  };
136
157
 
@@ -207,12 +228,21 @@ async function deploy(args) {
207
228
  }
208
229
 
209
230
  async function deployDir(args) {
210
- const opts = { dir: null, project: undefined, target: undefined, quiet: false };
231
+ const opts = {
232
+ dir: null,
233
+ project: undefined,
234
+ target: undefined,
235
+ quiet: false,
236
+ dryRun: false,
237
+ confirmPrune: false,
238
+ };
211
239
  for (let i = 0; i < args.length; i++) {
212
240
  if (args[i] === "--help" || args[i] === "-h") { console.log(SUB_HELP["deploy-dir"]); process.exit(0); }
213
241
  if (args[i] === "--project" && args[i + 1]) { opts.project = args[++i]; continue; }
214
242
  if (args[i] === "--target" && args[i + 1]) { opts.target = args[++i]; continue; }
215
243
  if (args[i] === "--quiet") { opts.quiet = true; continue; }
244
+ if (args[i] === "--dry-run") { opts.dryRun = true; continue; }
245
+ if (args[i] === "--confirm-prune") { opts.confirmPrune = true; continue; }
216
246
  if (args[i] === "--inherit") {
217
247
  console.error(JSON.stringify({
218
248
  status: "error",
@@ -231,6 +261,59 @@ async function deployDir(args) {
231
261
  // Preserve the aggressive early exit when no allowance is configured.
232
262
  allowanceAuthHeaders("/deploy/v2/plans");
233
263
 
264
+ let fileSet;
265
+ try {
266
+ fileSet = await fileSetFromDir(opts.dir);
267
+ } catch (err) {
268
+ reportSdkError(err);
269
+ return;
270
+ }
271
+ const fileCount = Object.keys(fileSet).length;
272
+
273
+ if (
274
+ fileCount < SMALL_DIR_THRESHOLD &&
275
+ !opts.confirmPrune &&
276
+ !opts.dryRun
277
+ ) {
278
+ console.error(JSON.stringify({
279
+ status: "error",
280
+ code: "PRUNE_CONFIRMATION_REQUIRED",
281
+ message:
282
+ `sites deploy-dir would replace the entire site with ${fileCount} ` +
283
+ `file(s) from ${opts.dir}. Any files in the current release that ` +
284
+ `are absent from this directory will be removed. Pass ` +
285
+ `--confirm-prune to proceed, or --dry-run to preview the diff.`,
286
+ details: {
287
+ local_file_count: fileCount,
288
+ threshold: SMALL_DIR_THRESHOLD,
289
+ dir: opts.dir,
290
+ },
291
+ }));
292
+ process.exit(1);
293
+ }
294
+
295
+ if (opts.dryRun) {
296
+ try {
297
+ const { plan } = await getSdk().deploy.plan({
298
+ project: projectId,
299
+ site: { replace: fileSet },
300
+ });
301
+ console.log(JSON.stringify({
302
+ status: "ok",
303
+ dry_run: true,
304
+ local_file_count: fileCount,
305
+ plan_id: plan.plan_id,
306
+ operation_id: plan.operation_id,
307
+ manifest_digest: plan.manifest_digest,
308
+ diff: plan.diff,
309
+ missing_content_count: plan.missing_content.filter((p) => !p.present).length,
310
+ }, null, 2));
311
+ } catch (err) {
312
+ reportSdkError(err);
313
+ }
314
+ return;
315
+ }
316
+
234
317
  try {
235
318
  const data = await getSdk().sites.deployDir({
236
319
  project: projectId,
@@ -9,7 +9,7 @@ Usage:
9
9
 
10
10
  Subcommands:
11
11
  claim <name> [--project <id>] [--deployment <id>] Claim a subdomain
12
- delete <name> [--project <id>] Release a subdomain
12
+ delete <name> --confirm [--project <id>] Release a subdomain. Requires --confirm.
13
13
  list [<id>] List subdomains for a project
14
14
 
15
15
  Options default to the active project and its last deployment when omitted.
@@ -18,7 +18,7 @@ Legacy syntax 'claim <deployment_id> <name>' is still supported.
18
18
  Examples:
19
19
  run402 subdomains claim myapp
20
20
  run402 subdomains claim myapp --deployment dpl_abc123 --project proj123
21
- run402 subdomains delete myapp
21
+ run402 subdomains delete myapp --confirm
22
22
  run402 subdomains list
23
23
 
24
24
  Notes:
@@ -77,10 +77,26 @@ async function claim(positionalArgs, flagArgs) {
77
77
  }
78
78
  }
79
79
 
80
- async function deleteSubdomain(name, args) {
81
- const opts = { project: null };
82
- for (let i = 0; i < args.length; i++) {
83
- if (args[i] === "--project" && args[i + 1]) opts.project = args[++i];
80
+ async function deleteSubdomain(allArgs) {
81
+ const argList = Array.isArray(allArgs) ? allArgs : [];
82
+ let opts = { project: null };
83
+ let name = null;
84
+ for (let i = 0; i < argList.length; i++) {
85
+ if (argList[i] === "--project" && argList[i + 1]) { opts.project = argList[++i]; }
86
+ else if (!argList[i].startsWith("--") && !name) { name = argList[i]; }
87
+ }
88
+ if (!name) {
89
+ console.error(JSON.stringify({ status: "error", message: "Usage: run402 subdomains delete <name> --confirm [--project <id>]" }));
90
+ process.exit(1);
91
+ }
92
+ if (!argList.includes("--confirm")) {
93
+ console.error(JSON.stringify({
94
+ status: "error",
95
+ code: "CONFIRMATION_REQUIRED",
96
+ message: `Destructive: releasing subdomain '${name}' makes it available for any other project to claim. This is irreversible. Re-run with --confirm to proceed.`,
97
+ details: { name },
98
+ }));
99
+ process.exit(1);
84
100
  }
85
101
  const projectId = resolveProjectId(opts.project);
86
102
  try {
@@ -116,7 +132,7 @@ export async function run(sub, args) {
116
132
  await claim(positional, flags);
117
133
  break;
118
134
  }
119
- case "delete": await deleteSubdomain(args[0], args.slice(1)); break;
135
+ case "delete": await deleteSubdomain(args); break;
120
136
  case "list": await list(args[0]); break;
121
137
  default:
122
138
  console.error(`Unknown subcommand: ${sub}\n`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "run402",
3
- "version": "1.53.0",
3
+ "version": "1.53.1",
4
4
  "description": "CLI for Run402 — provision Postgres databases, deploy static sites, generate images, and manage wallets via x402 and MPP micropayments.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -2,8 +2,34 @@
2
2
  * Error hierarchy for the Run402 SDK. Every failure throws a subclass of
3
3
  * {@link Run402Error}. Consumers (MCP handlers, CLI commands, user functions)
4
4
  * translate these into their native error shapes at the edge.
5
+ *
6
+ * Branch on {@link Run402Error.kind} (or the exported `is*` type guards) rather
7
+ * than `instanceof`. Discriminator-based checks survive duplicate SDK installs,
8
+ * bundler chunk splits, ESM/CJS interop, and V8-isolate realm boundaries —
9
+ * any setting where a class object's identity might differ from the consumer's
10
+ * own class object reference. `instanceof X` continues to work for callers
11
+ * holding a single SDK copy (back-compat); the guards are the recommended path.
12
+ */
13
+ /**
14
+ * Stable string discriminator on every {@link Run402Error} subclass. Use this
15
+ * (or the exported `is*` guards) to branch on errors safely across SDK copies
16
+ * and realms — value comparison, no class-identity dependency.
5
17
  */
18
+ export type Run402ErrorKind = "payment_required" | "project_not_found" | "unauthorized" | "api_error" | "network_error" | "local_error" | "deploy_error";
6
19
  export declare abstract class Run402Error extends Error {
20
+ /**
21
+ * Structural brand. Always `true` on any {@link Run402Error} subclass
22
+ * instance, regardless of which SDK copy created it. The exported
23
+ * {@link isRun402Error} guard checks this field instead of `instanceof`,
24
+ * so cross-realm and cross-bundle errors still match.
25
+ */
26
+ readonly isRun402Error: true;
27
+ /**
28
+ * Stable string discriminator. Branch on `e.kind === "..."` (or the
29
+ * exported subclass guards) rather than `e instanceof X`. Equality on
30
+ * `kind` survives duplicate SDK copies and cross-realm errors.
31
+ */
32
+ abstract readonly kind: Run402ErrorKind;
7
33
  /** HTTP status, or null for local/network failures that produced no response. */
8
34
  readonly status: number | null;
9
35
  /** Parsed response body, or null when no body was received. */
@@ -27,28 +53,42 @@ export declare abstract class Run402Error extends Error {
27
53
  /** Advisory next actions from the gateway. Rendering them must not execute them. */
28
54
  readonly nextActions?: unknown[];
29
55
  constructor(message: string, status: number | null, body: unknown, context: string);
56
+ /**
57
+ * Canonical structured envelope for `JSON.stringify`. Without this, an
58
+ * `Error` instance serializes as `"{}"` (its built-in fields are
59
+ * non-enumerable), losing every structured detail an agent needs for
60
+ * triage. Subclasses with extra fields (e.g. {@link Run402DeployError})
61
+ * override and spread `super.toJSON()`.
62
+ */
63
+ toJSON(): Record<string, unknown>;
30
64
  }
31
65
  /** HTTP 402 — the gateway requires payment (lease expired, insufficient balance, or x402 quote). */
32
66
  export declare class PaymentRequired extends Run402Error {
67
+ readonly kind: "payment_required";
33
68
  }
34
69
  /** Project ID is not present in the credential provider (local miss) or the gateway returned 404. */
35
70
  export declare class ProjectNotFound extends Run402Error {
71
+ readonly kind: "project_not_found";
36
72
  readonly projectId: string;
37
73
  constructor(projectId: string, context: string, status?: number | null, body?: unknown);
38
74
  }
39
75
  /** HTTP 401 or 403 — authentication missing, invalid, or insufficient for the operation. */
40
76
  export declare class Unauthorized extends Run402Error {
77
+ readonly kind: "unauthorized";
41
78
  }
42
79
  /** Any other non-2xx HTTP response from the gateway. */
43
80
  export declare class ApiError extends Run402Error {
81
+ readonly kind: "api_error";
44
82
  }
45
83
  /** The underlying `fetch` threw before producing a response (DNS, connection reset, offline). */
46
84
  export declare class NetworkError extends Run402Error {
85
+ readonly kind: "network_error";
47
86
  readonly cause: unknown;
48
87
  constructor(message: string, cause: unknown, context: string);
49
88
  }
50
89
  /** Local/filesystem error — input validation, missing path, unreadable dir. No HTTP involved. */
51
90
  export declare class LocalError extends Run402Error {
91
+ readonly kind: "local_error";
52
92
  readonly cause?: unknown;
53
93
  constructor(message: string, context: string, cause?: unknown);
54
94
  }
@@ -69,6 +109,7 @@ export interface Run402DeployErrorFix {
69
109
  [key: string]: unknown;
70
110
  }
71
111
  export declare class Run402DeployError extends Run402Error {
112
+ readonly kind: "deploy_error";
72
113
  readonly code: Run402DeployErrorCode;
73
114
  readonly phase: string | null;
74
115
  readonly resource: string | null;
@@ -92,5 +133,37 @@ export declare class Run402DeployError extends Run402Error {
92
133
  body?: unknown;
93
134
  context: string;
94
135
  });
136
+ toJSON(): Record<string, unknown>;
95
137
  }
138
+ /** True if `e` is any {@link Run402Error} subclass instance, regardless of which SDK copy created it. */
139
+ export declare function isRun402Error(e: unknown): e is Run402Error;
140
+ /** True if `e` is a {@link PaymentRequired}. Survives duplicate SDK copies and realms. */
141
+ export declare function isPaymentRequired(e: unknown): e is PaymentRequired;
142
+ /** True if `e` is a {@link ProjectNotFound}. */
143
+ export declare function isProjectNotFound(e: unknown): e is ProjectNotFound;
144
+ /** True if `e` is an {@link Unauthorized}. */
145
+ export declare function isUnauthorized(e: unknown): e is Unauthorized;
146
+ /** True if `e` is an {@link ApiError}. */
147
+ export declare function isApiError(e: unknown): e is ApiError;
148
+ /** True if `e` is a {@link NetworkError}. */
149
+ export declare function isNetworkError(e: unknown): e is NetworkError;
150
+ /** True if `e` is a {@link LocalError}. */
151
+ export declare function isLocalError(e: unknown): e is LocalError;
152
+ /** True if `e` is a {@link Run402DeployError}. */
153
+ export declare function isDeployError(e: unknown): e is Run402DeployError;
154
+ /**
155
+ * Canonical "should I retry this?" policy. Returns true when `e` is a
156
+ * {@link Run402Error} AND any of:
157
+ * - `e.retryable === true` (gateway flagged it)
158
+ * - `e.safeToRetry === true` (gateway flagged it)
159
+ * - `e.kind === "network_error"` (fetch never produced a response)
160
+ * - `e.status` is 408 (Request Timeout), 425 (Too Early), or 429 (Too Many
161
+ * Requests)
162
+ * - `e.status` is a 5xx server error
163
+ *
164
+ * Returns false for non-Run402 errors so it can be safely called with
165
+ * `unknown` from a catch block. Used as the default `retryIf` in
166
+ * {@link withRetry}.
167
+ */
168
+ export declare function isRetryableRun402Error(e: unknown): boolean;
96
169
  //# sourceMappingURL=errors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,8BAAsB,WAAY,SAAQ,KAAK;IAC7C,iFAAiF;IACjF,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,+DAA+D;IAC/D,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,2FAA2F;IAC3F,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,mFAAmF;IACnF,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,+DAA+D;IAC/D,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,kDAAkD;IAClD,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B,yFAAyF;IACzF,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B,sEAAsE;IACtE,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,+CAA+C;IAC/C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,mFAAmF;IACnF,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,oFAAoF;IACpF,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,EAAE,CAAC;gBAErB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM;CAkBnF;AAQD,oGAAoG;AACpG,qBAAa,eAAgB,SAAQ,WAAW;CAAG;AAEnD,qGAAqG;AACrG,qBAAa,eAAgB,SAAQ,WAAW;IAC9C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;gBACf,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,GAAG,IAAW,EAAE,IAAI,GAAE,OAAc;CAInG;AAED,4FAA4F;AAC5F,qBAAa,YAAa,SAAQ,WAAW;CAAG;AAEhD,wDAAwD;AACxD,qBAAa,QAAS,SAAQ,WAAW;CAAG;AAE5C,iGAAiG;AACjG,qBAAa,YAAa,SAAQ,WAAW;IAC3C,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;gBACZ,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM;CAI7D;AAED,iGAAiG;AACjG,qBAAa,UAAW,SAAQ,WAAW;IACzC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;gBACb,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAI9D;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,qBAAqB,GAC7B,kBAAkB,GAClB,6BAA6B,GAC7B,yBAAyB,GACzB,uBAAuB,GACvB,kBAAkB,GAClB,+BAA+B,GAC/B,uBAAuB,GACvB,mBAAmB,GACnB,qBAAqB,GACrB,mBAAmB,GACnB,uBAAuB,GACvB,uBAAuB,GACvB,cAAc,GACd,qBAAqB,GACrB,gBAAgB,GAChB,qBAAqB,GACrB,eAAe,GACf,eAAe,GACf,eAAe,GACf,gBAAgB,GAChB,eAAe,GACf,mBAAmB,GACnB,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAElB,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,qBAAa,iBAAkB,SAAQ,WAAW;IAChD,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAC;IACrC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,GAAG,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAC1C,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;gBAG3B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE;QACJ,IAAI,EAAE,qBAAqB,CAAC;QAC5B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACtB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACvB,GAAG,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;QAClC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QACvB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC,EAAE,OAAO,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;KACjB;CAaJ"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}