apiblaze 0.17.12 → 0.17.15

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 (2) hide show
  1. package/dist/index.js +630 -509
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -137,9 +137,9 @@ async function createProxyAnonymous(body) {
137
137
  }
138
138
  return res.json();
139
139
  }
140
- async function apiFetch(path7, options = {}) {
140
+ async function apiFetch(path8, options = {}) {
141
141
  const token = getAccessToken();
142
- const url = `${DASHBOARD_BASE}${path7}`;
142
+ const url = `${DASHBOARD_BASE}${path8}`;
143
143
  const res = await fetch(url, {
144
144
  ...options,
145
145
  headers: {
@@ -165,12 +165,12 @@ async function apiFetch(path7, options = {}) {
165
165
  }
166
166
  return res.json();
167
167
  }
168
- async function agentCall(path7, method, body) {
168
+ async function agentCall(path8, method, body) {
169
169
  const token = getAccessToken();
170
170
  const res = await fetch(`${DASHBOARD_BASE}/api/cli/agents`, {
171
171
  method: "POST",
172
172
  headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` },
173
- body: JSON.stringify({ path: path7, method, body })
173
+ body: JSON.stringify({ path: path8, method, body })
174
174
  });
175
175
  let data = null;
176
176
  try {
@@ -389,32 +389,32 @@ function maskBody(body) {
389
389
  }
390
390
  function renderTrace() {
391
391
  if (!verbose || entries.length === 0) return;
392
- console.log(import_chalk11.default.dim("\n" + "\u2500".repeat(64)));
393
- console.log(import_chalk11.default.bold(`--verbose: ${entries.length} API call${entries.length === 1 ? "" : "s"} this command made`));
392
+ console.log(import_chalk12.default.dim("\n" + "\u2500".repeat(64)));
393
+ console.log(import_chalk12.default.bold(`--verbose: ${entries.length} API call${entries.length === 1 ? "" : "s"} this command made`));
394
394
  console.log(
395
- import_chalk11.default.dim("The same thing on the official API \u2014 copy/paste with your control-plane key\n(get one from the Developers section of dashboard.apiblaze.com, then\n`export APIBLAZE_CONTROLPLANE_APIKEY=sk_...`).\nFull API reference: https://api.apiblaze.com/openapi.json\n")
395
+ import_chalk12.default.dim("The same thing on the official API \u2014 copy/paste with your control-plane key\n(get one from the Developers section of dashboard.apiblaze.com, then\n`export APIBLAZE_CONTROLPLANE_APIKEY=sk_...`).\nFull API reference: https://api.apiblaze.com/openapi.json\n")
396
396
  );
397
397
  entries.forEach((e, i) => {
398
- const n = entries.length > 1 ? import_chalk11.default.bold(`${i + 1}. `) : "";
399
- if (e.summary) console.log(`${n}${import_chalk11.default.cyan(e.summary)}${e.status ? import_chalk11.default.dim(` (HTTP ${e.status})`) : ""}`);
398
+ const n = entries.length > 1 ? import_chalk12.default.bold(`${i + 1}. `) : "";
399
+ if (e.summary) console.log(`${n}${import_chalk12.default.cyan(e.summary)}${e.status ? import_chalk12.default.dim(` (HTTP ${e.status})`) : ""}`);
400
400
  const url = `https://api.apiblaze.com/${CONTROL_API_VERSION}/prod${e.path}`;
401
401
  const masked = maskBody(e.body);
402
402
  const hasBody = e.method !== "GET" && masked !== void 0;
403
- console.log(import_chalk11.default.green(` curl -sS -X ${e.method} ${url}` + (hasBody ? " \\" : "")));
404
- console.log(import_chalk11.default.green(' -H "X-API-Key: $APIBLAZE_CONTROLPLANE_APIKEY"' + (hasBody ? " \\" : "")));
403
+ console.log(import_chalk12.default.green(` curl -sS -X ${e.method} ${url}` + (hasBody ? " \\" : "")));
404
+ console.log(import_chalk12.default.green(' -H "X-API-Key: $APIBLAZE_CONTROLPLANE_APIKEY"' + (hasBody ? " \\" : "")));
405
405
  if (hasBody) {
406
- console.log(import_chalk11.default.green(" -H 'Content-Type: application/json' \\"));
407
- console.log(import_chalk11.default.green(` -d '${masked}'`));
406
+ console.log(import_chalk12.default.green(" -H 'Content-Type: application/json' \\"));
407
+ console.log(import_chalk12.default.green(` -d '${masked}'`));
408
408
  }
409
409
  if (i < entries.length - 1) console.log();
410
410
  });
411
411
  entries.length = 0;
412
412
  }
413
- var import_chalk11, CONTROL_API_VERSION, verbose, entries, SECRET_KEY;
413
+ var import_chalk12, CONTROL_API_VERSION, verbose, entries, SECRET_KEY;
414
414
  var init_trace = __esm({
415
415
  "src/lib/trace.ts"() {
416
416
  "use strict";
417
- import_chalk11 = __toESM(require("chalk"));
417
+ import_chalk12 = __toESM(require("chalk"));
418
418
  CONTROL_API_VERSION = "1.0.0";
419
419
  verbose = false;
420
420
  entries = [];
@@ -455,13 +455,13 @@ function formatBilling(billing) {
455
455
  }
456
456
  function maybePrintBilling(data) {
457
457
  const line = formatBilling(data?.billing);
458
- if (line) console.log(import_chalk12.default.magenta(` ${line}`));
458
+ if (line) console.log(import_chalk13.default.magenta(` ${line}`));
459
459
  }
460
- var import_chalk12, DASHBOARD_BASE3;
460
+ var import_chalk13, DASHBOARD_BASE3;
461
461
  var init_admin = __esm({
462
462
  "src/lib/admin.ts"() {
463
463
  "use strict";
464
- import_chalk12 = __toESM(require("chalk"));
464
+ import_chalk13 = __toESM(require("chalk"));
465
465
  init_auth();
466
466
  init_trace();
467
467
  init_types();
@@ -481,7 +481,7 @@ async function createTenantRow(teamId) {
481
481
  const { name } = await inquirer3.prompt([{
482
482
  type: "input",
483
483
  name: "name",
484
- message: `Tenant name ${import_chalk22.default.dim("(lowercase letters/numbers; globally unique \u2014 becomes {name}.portal.apiblaze.com)")}:`,
484
+ message: `Tenant name ${import_chalk23.default.dim("(lowercase letters/numbers; globally unique \u2014 becomes {name}.portal.apiblaze.com)")}:`,
485
485
  validate: (s) => /^[a-z0-9]+$/.test(s.trim()) ? true : "lowercase letters and numbers only"
486
486
  }]);
487
487
  const slug = name.trim();
@@ -496,7 +496,7 @@ async function createTenantRow(teamId) {
496
496
  } catch (err) {
497
497
  const msg = err instanceof Error ? err.message : String(err);
498
498
  if (/taken|unique|exists|reserved|conflict/i.test(msg)) {
499
- console.log(import_chalk22.default.yellow(` "${slug}" is not available (tenant names are global): ${msg}`));
499
+ console.log(import_chalk23.default.yellow(` "${slug}" is not available (tenant names are global): ${msg}`));
500
500
  continue;
501
501
  }
502
502
  throw err;
@@ -513,11 +513,11 @@ async function addApiblazeHostedLogin(teamId, tenant2, opts = {}) {
513
513
  pageSize: 10,
514
514
  choices: [
515
515
  ...PROVIDERS.map((p) => ({ name: p.label, value: p.id })),
516
- ...opts.allowSkip ? [new inquirer3.Separator(), { name: import_chalk22.default.dim("Skip for now \u2014 set up a login method later"), value: null }] : []
516
+ ...opts.allowSkip ? [new inquirer3.Separator(), { name: import_chalk23.default.dim("Skip for now \u2014 set up a login method later"), value: null }] : []
517
517
  ]
518
518
  }]);
519
519
  if (!provider) {
520
- console.log(import_chalk22.default.dim(" No login method yet \u2014 add one later under Login methods."));
520
+ console.log(import_chalk23.default.dim(" No login method yet \u2014 add one later under Login methods."));
521
521
  return false;
522
522
  }
523
523
  const opt = PROVIDERS.find((p) => p.id === provider);
@@ -563,26 +563,26 @@ async function addApiblazeHostedLogin(teamId, tenant2, opts = {}) {
563
563
  async function createTenantInteractive(teamId) {
564
564
  const { default: inquirer3 } = await import("inquirer");
565
565
  const tenant2 = await createTenantRow(teamId);
566
- console.log(import_chalk22.default.green(` Tenant ${import_chalk22.default.bold(tenant2)} created.`));
566
+ console.log(import_chalk23.default.green(` Tenant ${import_chalk23.default.bold(tenant2)} created.`));
567
567
  const { users } = await inquirer3.prompt([{
568
568
  type: "confirm",
569
569
  name: "users",
570
570
  default: false,
571
- message: `Enable Users & groups? ${import_chalk22.default.dim(`(identity/key management at ${tenant2}.iam.apiblaze.com)`)}`
571
+ message: `Enable Users & groups? ${import_chalk23.default.dim(`(identity/key management at ${tenant2}.iam.apiblaze.com)`)}`
572
572
  }]);
573
573
  if (users) {
574
574
  await admin({ method: "PATCH", path: `/teams/${encodeURIComponent(teamId)}/tenants/${encodeURIComponent(tenant2)}/iam`, body: { enabled: true }, summary: "Enable Users & groups" }).catch(() => {
575
575
  });
576
- console.log(import_chalk22.default.green(" Users & groups enabled."));
576
+ console.log(import_chalk23.default.green(" Users & groups enabled."));
577
577
  }
578
578
  await addApiblazeHostedLogin(teamId, tenant2, { allowSkip: true });
579
579
  return tenant2;
580
580
  }
581
- var import_chalk22, import_ora8, PROVIDERS, DEFAULT_SCOPES;
581
+ var import_chalk23, import_ora8, PROVIDERS, DEFAULT_SCOPES;
582
582
  var init_tenant_create = __esm({
583
583
  "src/lib/tenant-create.ts"() {
584
584
  "use strict";
585
- import_chalk22 = __toESM(require("chalk"));
585
+ import_chalk23 = __toESM(require("chalk"));
586
586
  import_ora8 = __toESM(require("ora"));
587
587
  init_admin();
588
588
  PROVIDERS = [
@@ -621,10 +621,10 @@ async function fetchPage(teamId, q) {
621
621
  }
622
622
  function label(t, defaultTenant, active) {
623
623
  const tags = [
624
- t.tenant_name === active ? import_chalk23.default.cyan("active scope") : "",
625
- t.tenant_name === defaultTenant ? import_chalk23.default.dim("team default") : ""
624
+ t.tenant_name === active ? import_chalk24.default.cyan("active scope") : "",
625
+ t.tenant_name === defaultTenant ? import_chalk24.default.dim("team default") : ""
626
626
  ].filter(Boolean).join(", ");
627
- const disp = t.display_name && t.display_name !== t.tenant_name ? import_chalk23.default.dim(` ${t.display_name}`) : "";
627
+ const disp = t.display_name && t.display_name !== t.tenant_name ? import_chalk24.default.dim(` ${t.display_name}`) : "";
628
628
  return `${t.tenant_name}${disp}${tags ? ` (${tags})` : ""}`;
629
629
  }
630
630
  async function pickTenant(teamId, opts = {}) {
@@ -639,7 +639,7 @@ async function pickTenant(teamId, opts = {}) {
639
639
  const { make } = await inquirer3.prompt([{ type: "confirm", name: "make", message: "No tenants yet \u2014 create one?", default: true }]);
640
640
  if (make) return await createTenantInline(teamId);
641
641
  }
642
- console.error(import_chalk23.default.red("This team has no tenants. Create one with `apiblaze tenant create`."));
642
+ console.error(import_chalk24.default.red("This team has no tenants. Create one with `apiblaze tenant create`."));
643
643
  return null;
644
644
  }
645
645
  const truncated = page.total > page.rows.length;
@@ -648,7 +648,7 @@ async function pickTenant(teamId, opts = {}) {
648
648
  value: t.tenant_name
649
649
  }));
650
650
  if (truncated || q) {
651
- choices.push(new inquirer3.Separator(import_chalk23.default.dim(
651
+ choices.push(new inquirer3.Separator(import_chalk24.default.dim(
652
652
  truncated ? `showing ${page.rows.length} of ${page.total}${q ? ` matching "${q}"` : ""} \u2014 search to narrow` : `matches for "${q}"`
653
653
  )));
654
654
  choices.push({ name: `\u{1F50D} Search${q ? " again" : ""}\u2026`, value: "\0search" });
@@ -682,11 +682,11 @@ async function createTenantInline(teamId) {
682
682
  const { createTenantInteractive: createTenantInteractive2 } = await Promise.resolve().then(() => (init_tenant_create(), tenant_create_exports));
683
683
  return createTenantInteractive2(teamId);
684
684
  }
685
- var import_chalk23, import_ora9, PAGE;
685
+ var import_chalk24, import_ora9, PAGE;
686
686
  var init_tenant_pick = __esm({
687
687
  "src/lib/tenant-pick.ts"() {
688
688
  "use strict";
689
- import_chalk23 = __toESM(require("chalk"));
689
+ import_chalk24 = __toESM(require("chalk"));
690
690
  import_ora9 = __toESM(require("ora"));
691
691
  init_admin();
692
692
  init_auth();
@@ -696,10 +696,10 @@ var init_tenant_pick = __esm({
696
696
 
697
697
  // src/index.ts
698
698
  var import_commander = require("commander");
699
- var import_chalk37 = __toESM(require("chalk"));
699
+ var import_chalk38 = __toESM(require("chalk"));
700
700
 
701
701
  // package.json
702
- var version = "0.17.12";
702
+ var version = "0.17.15";
703
703
 
704
704
  // src/index.ts
705
705
  init_types();
@@ -949,11 +949,11 @@ function decodeJwt(token) {
949
949
  return null;
950
950
  }
951
951
  }
952
- function maskPath(path7) {
953
- const q = path7.indexOf("?");
954
- if (q < 0) return path7;
955
- const base = path7.slice(0, q);
956
- const query = path7.slice(q + 1);
952
+ function maskPath(path8) {
953
+ const q = path8.indexOf("?");
954
+ if (q < 0) return path8;
955
+ const base = path8.slice(0, q);
956
+ const query = path8.slice(q + 1);
957
957
  const masked = query.split("&").map((pair) => {
958
958
  const eq = pair.indexOf("=");
959
959
  if (eq < 0) return pair;
@@ -2185,8 +2185,48 @@ async function runLogout(opts = {}) {
2185
2185
  }
2186
2186
  }
2187
2187
 
2188
- // src/commands/whoami.ts
2188
+ // src/commands/flush.ts
2189
2189
  var import_chalk9 = __toESM(require("chalk"));
2190
+ var fs6 = __toESM(require("fs"));
2191
+ var path4 = __toESM(require("path"));
2192
+ init_auth();
2193
+ async function runFlush(opts) {
2194
+ const dir = getApiblazeDir();
2195
+ const entries2 = fs6.existsSync(dir) ? fs6.readdirSync(dir) : [];
2196
+ if (!entries2.length) {
2197
+ console.log(import_chalk9.default.dim("Nothing to flush \u2014 no local apiblaze config found."));
2198
+ return;
2199
+ }
2200
+ console.log(import_chalk9.default.yellow("This removes ALL local apiblaze state from this machine:"));
2201
+ console.log(import_chalk9.default.dim(" \u2022 login credentials & anonymous-workspace keys"));
2202
+ console.log(import_chalk9.default.dim(" \u2022 saved apichats \u2014 their DP API keys and transcripts"));
2203
+ console.log(import_chalk9.default.dim(" \u2022 your BYO LLM key and any cached secrets"));
2204
+ console.log(import_chalk9.default.dim(` (${entries2.length} item(s) in ${dir})`));
2205
+ console.log(import_chalk9.default.dim(" It does NOT delete server-side proxies/keys \u2014 those GC or are revoked separately."));
2206
+ if (!opts.yes) {
2207
+ const { default: inquirer3 } = await import("inquirer");
2208
+ const { ok } = await inquirer3.prompt([
2209
+ { type: "confirm", name: "ok", message: "Delete all local state?", default: false }
2210
+ ]);
2211
+ if (!ok) {
2212
+ console.log(import_chalk9.default.dim("Cancelled \u2014 nothing removed."));
2213
+ return;
2214
+ }
2215
+ }
2216
+ let removed = 0;
2217
+ for (const e of entries2) {
2218
+ try {
2219
+ fs6.rmSync(path4.join(dir, e), { recursive: true, force: true });
2220
+ removed++;
2221
+ } catch (err) {
2222
+ console.log(import_chalk9.default.red(` \u2717 could not remove ${e}: ${err instanceof Error ? err.message : "error"}`));
2223
+ }
2224
+ }
2225
+ console.log(`${import_chalk9.default.green("\u2714")} Flushed \u2014 removed ${removed} item(s). You're fully logged out and clean.`);
2226
+ }
2227
+
2228
+ // src/commands/whoami.ts
2229
+ var import_chalk10 = __toESM(require("chalk"));
2190
2230
  init_auth();
2191
2231
  init_anon_cred();
2192
2232
  async function runWhoami(opts = {}) {
@@ -2209,43 +2249,43 @@ async function runWhoami(opts = {}) {
2209
2249
  }, null, 2));
2210
2250
  return;
2211
2251
  }
2212
- console.log(import_chalk9.default.bold("API Producer"));
2252
+ console.log(import_chalk10.default.bold("API Producer"));
2213
2253
  if (!creds) {
2214
- console.log(import_chalk9.default.dim(" Not logged in. Run `apiblaze login`."));
2254
+ console.log(import_chalk10.default.dim(" Not logged in. Run `apiblaze login`."));
2215
2255
  } else {
2216
2256
  const who = creds.githubHandle ?? creds.email ?? creds.apiblazeUserId ?? "unknown";
2217
- console.log(` ${import_chalk9.default.cyan("Signed in as")} ${import_chalk9.default.bold(who)}`);
2257
+ console.log(` ${import_chalk10.default.cyan("Signed in as")} ${import_chalk10.default.bold(who)}`);
2218
2258
  if (creds.email && creds.email !== who) console.log(` Email: ${creds.email}`);
2219
- if (creds.teamName || creds.teamId) console.log(` Team: ${import_chalk9.default.bold(creds.teamName ?? creds.teamId)}`);
2220
- if (creds.activeTenant) console.log(` Tenant scope: ${import_chalk9.default.bold(creds.activeTenant)} ${import_chalk9.default.dim("(clear: `apiblaze tenant use --clear`)")}`);
2221
- if (Date.now() >= creds.expiresAt) console.log(import_chalk9.default.yellow(" \u26A0 Session expired \u2014 run `apiblaze login`."));
2259
+ if (creds.teamName || creds.teamId) console.log(` Team: ${import_chalk10.default.bold(creds.teamName ?? creds.teamId)}`);
2260
+ if (creds.activeTenant) console.log(` Tenant scope: ${import_chalk10.default.bold(creds.activeTenant)} ${import_chalk10.default.dim("(clear: `apiblaze tenant use --clear`)")}`);
2261
+ if (Date.now() >= creds.expiresAt) console.log(import_chalk10.default.yellow(" \u26A0 Session expired \u2014 run `apiblaze login`."));
2222
2262
  }
2223
2263
  if (anon) {
2224
2264
  const masked = `${anon.cp_key.slice(0, 11)}\u2026${anon.cp_key.slice(-4)}`;
2225
- console.log(import_chalk9.default.bold("\nAnonymous workspace") + import_chalk9.default.dim(" (created without an account \u2014 unclaimed)"));
2226
- console.log(` Team: ${import_chalk9.default.bold(anon.team_id)}`);
2227
- console.log(` CP key: ${import_chalk9.default.bold(masked)} ${import_chalk9.default.dim("controls the proxies you created anonymously")}`);
2265
+ console.log(import_chalk10.default.bold("\nAnonymous workspace") + import_chalk10.default.dim(" (created without an account \u2014 unclaimed)"));
2266
+ console.log(` Team: ${import_chalk10.default.bold(anon.team_id)}`);
2267
+ console.log(` CP key: ${import_chalk10.default.bold(masked)} ${import_chalk10.default.dim("controls the proxies you created anonymously")}`);
2228
2268
  console.log(
2229
- import_chalk9.default.dim(` Keep it: ${import_chalk9.default.cyan("apiblaze login")} then ${import_chalk9.default.cyan("apiblaze claim")}`) + (anon.claim_code ? import_chalk9.default.dim(` \xB7 from another machine: ${import_chalk9.default.cyan(`apiblaze claim ${anon.claim_code}`)}`) : "")
2269
+ import_chalk10.default.dim(` Keep it: ${import_chalk10.default.cyan("apiblaze login")} then ${import_chalk10.default.cyan("apiblaze claim")}`) + (anon.claim_code ? import_chalk10.default.dim(` \xB7 from another machine: ${import_chalk10.default.cyan(`apiblaze claim ${anon.claim_code}`)}`) : "")
2230
2270
  );
2231
- if (creds) console.log(import_chalk9.default.dim(" (you're logged in \u2014 `apiblaze claim` folds this workspace into your account)"));
2271
+ if (creds) console.log(import_chalk10.default.dim(" (you're logged in \u2014 `apiblaze claim` folds this workspace into your account)"));
2232
2272
  }
2233
- console.log(import_chalk9.default.bold("\nAPI Consumer"));
2273
+ console.log(import_chalk10.default.bold("\nAPI Consumer"));
2234
2274
  if (!consumer2) {
2235
- console.log(import_chalk9.default.dim(" Not logged in. Run `apiblaze consumer login`."));
2275
+ console.log(import_chalk10.default.dim(" Not logged in. Run `apiblaze consumer login`."));
2236
2276
  } else {
2237
- console.log(` ${import_chalk9.default.cyan("Signed in as")} ${import_chalk9.default.bold(consumer2.email ?? consumer2.tenant)}`);
2238
- console.log(` Tenant: ${import_chalk9.default.bold(consumer2.tenant)}`);
2239
- if (Date.now() >= consumer2.expiresAt) console.log(import_chalk9.default.yellow(" \u26A0 Token expired \u2014 it will refresh on next use, or re-run `apiblaze consumer login`."));
2277
+ console.log(` ${import_chalk10.default.cyan("Signed in as")} ${import_chalk10.default.bold(consumer2.email ?? consumer2.tenant)}`);
2278
+ console.log(` Tenant: ${import_chalk10.default.bold(consumer2.tenant)}`);
2279
+ if (Date.now() >= consumer2.expiresAt) console.log(import_chalk10.default.yellow(" \u26A0 Token expired \u2014 it will refresh on next use, or re-run `apiblaze consumer login`."));
2240
2280
  }
2241
2281
  }
2242
2282
 
2243
2283
  // src/commands/team.ts
2244
- var import_chalk10 = __toESM(require("chalk"));
2284
+ var import_chalk11 = __toESM(require("chalk"));
2245
2285
  init_auth();
2246
2286
  init_api();
2247
2287
  function fail3(message) {
2248
- console.error(import_chalk10.default.red(`Error: ${message}`));
2288
+ console.error(import_chalk11.default.red(`Error: ${message}`));
2249
2289
  process.exit(1);
2250
2290
  }
2251
2291
  async function runTeam(arg) {
@@ -2267,7 +2307,7 @@ async function runTeam(arg) {
2267
2307
  }
2268
2308
  } else if (teams.length === 1) {
2269
2309
  chosen = teams[0];
2270
- console.log(`${import_chalk10.default.cyan("\u2192")} You only have one team: ${import_chalk10.default.bold(chosen.name)}`);
2310
+ console.log(`${import_chalk11.default.cyan("\u2192")} You only have one team: ${import_chalk11.default.bold(chosen.name)}`);
2271
2311
  } else if (process.stdin.isTTY) {
2272
2312
  const { default: inquirer3 } = await import("inquirer");
2273
2313
  const { picked } = await inquirer3.prompt([{
@@ -2282,47 +2322,47 @@ async function runTeam(arg) {
2282
2322
  fail3(`Specify a team: \`apiblaze team <name|id>\`. Available: ${teams.map((t) => t.name).join(", ")}.`);
2283
2323
  }
2284
2324
  saveCredentials({ ...creds, teamId: chosen.teamId, teamName: chosen.name });
2285
- console.log(import_chalk10.default.green(`
2286
- \u2714 Active team: ${import_chalk10.default.bold(chosen.name)}`));
2325
+ console.log(import_chalk11.default.green(`
2326
+ \u2714 Active team: ${import_chalk11.default.bold(chosen.name)}`));
2287
2327
  }
2288
2328
 
2289
2329
  // src/commands/authz.ts
2290
- var import_chalk14 = __toESM(require("chalk"));
2330
+ var import_chalk15 = __toESM(require("chalk"));
2291
2331
  init_auth();
2292
2332
  init_api();
2293
2333
 
2294
2334
  // src/lib/agent-chat.ts
2295
2335
  var import_readline = __toESM(require("readline"));
2296
- var import_chalk13 = __toESM(require("chalk"));
2336
+ var import_chalk14 = __toESM(require("chalk"));
2297
2337
  init_api();
2298
2338
  init_admin();
2299
2339
  async function runAgentChatRepl(opts) {
2300
2340
  const { title, subtitle, endpoint, buildBody, seedPrompt, summarizeProposal, commands } = opts;
2301
- console.log("\n" + import_chalk13.default.cyan.bold(title));
2302
- if (subtitle) console.log(import_chalk13.default.dim(subtitle));
2341
+ console.log("\n" + import_chalk14.default.cyan.bold(title));
2342
+ if (subtitle) console.log(import_chalk14.default.dim(subtitle));
2303
2343
  const messages = [];
2304
2344
  const ctx = { proposal: null, lastData: null, log: (s) => console.log(s) };
2305
2345
  const cmdByName = new Map(commands.map((c) => [c.name, c]));
2306
2346
  const footer = () => {
2307
2347
  const parts = [
2308
- import_chalk13.default.dim("type to chat/refine"),
2309
- ...commands.map((c) => import_chalk13.default.dim(`/${c.name} ${c.describe}`)),
2310
- import_chalk13.default.dim("/show"),
2311
- import_chalk13.default.dim("/drop discard & exit")
2348
+ import_chalk14.default.dim("type to chat/refine"),
2349
+ ...commands.map((c) => import_chalk14.default.dim(`/${c.name} ${c.describe}`)),
2350
+ import_chalk14.default.dim("/show"),
2351
+ import_chalk14.default.dim("/drop discard & exit")
2312
2352
  ];
2313
- return " " + import_chalk13.default.dim("[ ") + parts.join(import_chalk13.default.dim(" \xB7 ")) + import_chalk13.default.dim(" ]");
2353
+ return " " + import_chalk14.default.dim("[ ") + parts.join(import_chalk14.default.dim(" \xB7 ")) + import_chalk14.default.dim(" ]");
2314
2354
  };
2315
2355
  async function turn(content) {
2316
2356
  messages.push({ role: "user", content });
2317
- process.stdout.write(import_chalk13.default.dim(" \u2026thinking\n"));
2357
+ process.stdout.write(import_chalk14.default.dim(" \u2026thinking\n"));
2318
2358
  const { status, data } = await agentCall(endpoint, "POST", { messages, ...buildBody(messages) });
2319
2359
  if (status === 402) {
2320
- console.log(import_chalk13.default.red(" Insufficient credits \u2014 top up to keep using the agents.\n"));
2360
+ console.log(import_chalk14.default.red(" Insufficient credits \u2014 top up to keep using the agents.\n"));
2321
2361
  messages.pop();
2322
2362
  return;
2323
2363
  }
2324
2364
  if (status >= 400 || !data) {
2325
- console.log(import_chalk13.default.red(` Error (${status}): ${(data && data.error) ?? "request failed"}
2365
+ console.log(import_chalk14.default.red(` Error (${status}): ${(data && data.error) ?? "request failed"}
2326
2366
  `));
2327
2367
  messages.pop();
2328
2368
  return;
@@ -2330,19 +2370,19 @@ async function runAgentChatRepl(opts) {
2330
2370
  ctx.lastData = data;
2331
2371
  const reply = data.reply ?? data.message ?? "(no reply)";
2332
2372
  messages.push({ role: "assistant", content: reply });
2333
- console.log("\n" + import_chalk13.default.cyan("agent \u203A ") + reply + "\n");
2373
+ console.log("\n" + import_chalk14.default.cyan("agent \u203A ") + reply + "\n");
2334
2374
  if (data.proposal) {
2335
2375
  ctx.proposal = data.proposal;
2336
2376
  const summary = summarizeProposal?.(data);
2337
- if (summary) console.log(import_chalk13.default.yellow(" " + summary));
2377
+ if (summary) console.log(import_chalk14.default.yellow(" " + summary));
2338
2378
  const ready = commands.filter((c) => c.needsProposal).map((c) => `/${c.name}`).join(" or ");
2339
- if (ready) console.log(import_chalk13.default.dim(` Ready \u2014 ${ready} to make it official, or keep refining.`));
2379
+ if (ready) console.log(import_chalk14.default.dim(` Ready \u2014 ${ready} to make it official, or keep refining.`));
2340
2380
  console.log();
2341
2381
  }
2342
2382
  const line = formatBilling(data.billing);
2343
2383
  if (line) {
2344
2384
  const llm2 = data.llm;
2345
- console.log(import_chalk13.default.dim(` ${line}${llm2?.model ? ` \xB7 ${llm2.model}` : ""}`));
2385
+ console.log(import_chalk14.default.dim(` ${line}${llm2?.model ? ` \xB7 ${llm2.model}` : ""}`));
2346
2386
  }
2347
2387
  }
2348
2388
  const rl = import_readline.default.createInterface({ input: process.stdin, output: process.stdout });
@@ -2350,26 +2390,26 @@ async function runAgentChatRepl(opts) {
2350
2390
  await turn(seedPrompt);
2351
2391
  for (; ; ) {
2352
2392
  console.log(footer());
2353
- const line = (await ask(import_chalk13.default.green("you \u203A "))).trim();
2393
+ const line = (await ask(import_chalk14.default.green("you \u203A "))).trim();
2354
2394
  if (!line) continue;
2355
2395
  if (line === "/drop" || line === "/exit" || line === "/quit") {
2356
- console.log(import_chalk13.default.dim(" Dropped \u2014 nothing applied.\n"));
2396
+ console.log(import_chalk14.default.dim(" Dropped \u2014 nothing applied.\n"));
2357
2397
  break;
2358
2398
  }
2359
2399
  if (line === "/show") {
2360
- if (!ctx.proposal) console.log(import_chalk13.default.dim(" No proposal yet \u2014 keep chatting until the agent proposes one.\n"));
2400
+ if (!ctx.proposal) console.log(import_chalk14.default.dim(" No proposal yet \u2014 keep chatting until the agent proposes one.\n"));
2361
2401
  else console.log("\n" + JSON.stringify(ctx.proposal, null, 2) + "\n");
2362
2402
  continue;
2363
2403
  }
2364
2404
  if (line.startsWith("/")) {
2365
2405
  const cmd = cmdByName.get(line.slice(1));
2366
2406
  if (!cmd) {
2367
- console.log(import_chalk13.default.red(` Unknown command "${line}". Try one of: ${commands.map((c) => "/" + c.name).join(", ")}, /show, /drop
2407
+ console.log(import_chalk14.default.red(` Unknown command "${line}". Try one of: ${commands.map((c) => "/" + c.name).join(", ")}, /show, /drop
2368
2408
  `));
2369
2409
  continue;
2370
2410
  }
2371
2411
  if (cmd.needsProposal && !ctx.proposal) {
2372
- console.log(import_chalk13.default.yellow(" No proposal yet \u2014 keep chatting until the agent generates one, then try again.\n"));
2412
+ console.log(import_chalk14.default.yellow(" No proposal yet \u2014 keep chatting until the agent generates one, then try again.\n"));
2373
2413
  continue;
2374
2414
  }
2375
2415
  await cmd.run(ctx);
@@ -2398,11 +2438,11 @@ async function runAuthz(projectArg, apiVersionArg) {
2398
2438
  if (!enable) {
2399
2439
  const m = await agentCall(`/projects/${projectId}/${apiVersion}/policies/model?tenantId=${encodeURIComponent(tenant2)}`, "POST", proposal.model);
2400
2440
  if (m.status === 404) {
2401
- ctx.log(import_chalk14.default.red(" Authorization store not provisioned yet. Open the dashboard Authorization tab for this project once (it auto-provisions the store), then re-run.\n"));
2441
+ ctx.log(import_chalk15.default.red(" Authorization store not provisioned yet. Open the dashboard Authorization tab for this project once (it auto-provisions the store), then re-run.\n"));
2402
2442
  return;
2403
2443
  }
2404
2444
  if (m.status >= 400) {
2405
- ctx.log(import_chalk14.default.red(` Model save failed (${m.status}): ${m.data?.error ?? ""}
2445
+ ctx.log(import_chalk15.default.red(` Model save failed (${m.status}): ${m.data?.error ?? ""}
2406
2446
  `));
2407
2447
  return;
2408
2448
  }
@@ -2431,14 +2471,14 @@ async function runAuthz(projectArg, apiVersionArg) {
2431
2471
  if (enable) {
2432
2472
  const e = await agentCall(`/${projectId}/${apiVersion}/config`, "PATCH", { authorization: { enforce_authorization: true }, tenant: tenant2 });
2433
2473
  if (e.status >= 400) {
2434
- ctx.log(import_chalk14.default.red(` Enforced ${ok} route(s) but turning on the project-level switch failed (${e.status}). Toggle "Enforce Authorization" on in the dashboard.
2474
+ ctx.log(import_chalk15.default.red(` Enforced ${ok} route(s) but turning on the project-level switch failed (${e.status}). Toggle "Enforce Authorization" on in the dashboard.
2435
2475
  `));
2436
2476
  return;
2437
2477
  }
2438
- ctx.log(import_chalk14.default.green(` \u2713 Enforcement ON \u2014 ${ok} route(s) + project switch on${fail5 ? `, ${fail5} failed` : ""}.
2478
+ ctx.log(import_chalk15.default.green(` \u2713 Enforcement ON \u2014 ${ok} route(s) + project switch on${fail5 ? `, ${fail5} failed` : ""}.
2439
2479
  `));
2440
2480
  } else {
2441
- ctx.log(import_chalk14.default.green(` \u2713 Published (shadow): model + ${ok} route(s)${fail5 ? `, ${fail5} failed` : ""}. Review, then /enable.
2481
+ ctx.log(import_chalk15.default.green(` \u2713 Published (shadow): model + ${ok} route(s)${fail5 ? `, ${fail5} failed` : ""}. Review, then /enable.
2442
2482
  `));
2443
2483
  }
2444
2484
  }
@@ -2463,7 +2503,7 @@ async function runAuthz(projectArg, apiVersionArg) {
2463
2503
  }
2464
2504
 
2465
2505
  // src/commands/openapi.ts
2466
- var import_chalk15 = __toESM(require("chalk"));
2506
+ var import_chalk16 = __toESM(require("chalk"));
2467
2507
  init_auth();
2468
2508
  init_api();
2469
2509
  async function runOpenapi(projectArg, apiVersionArg) {
@@ -2474,10 +2514,10 @@ async function runOpenapi(projectArg, apiVersionArg) {
2474
2514
  if (!match) throw new Error(`Project "${projectArg}" not found in your active team. Run \`apiblaze projects\`.`);
2475
2515
  const projectId = match.projectId;
2476
2516
  const apiVersion = apiVersionArg || match.apiVersion;
2477
- console.log(import_chalk15.default.dim("Gathering captured traffic samples\u2026"));
2517
+ console.log(import_chalk16.default.dim("Gathering captured traffic samples\u2026"));
2478
2518
  const routesRes = await agentCall(`/projects/${projectId}/${apiVersion}/samples/routes`, "GET");
2479
2519
  if (routesRes.status >= 400) {
2480
- console.log(import_chalk15.default.red(`Could not list traffic (${routesRes.status}): ${routesRes.data?.error ?? ""}`));
2520
+ console.log(import_chalk16.default.red(`Could not list traffic (${routesRes.status}): ${routesRes.data?.error ?? ""}`));
2481
2521
  return;
2482
2522
  }
2483
2523
  const routes = routesRes.data?.routes ?? (Array.isArray(routesRes.data) ? routesRes.data : []);
@@ -2490,25 +2530,25 @@ async function runOpenapi(projectArg, apiVersionArg) {
2490
2530
  }
2491
2531
  const sampleIds = [...ids];
2492
2532
  if (sampleIds.length === 0) {
2493
- console.log(import_chalk15.default.yellow("No captured traffic samples found. Hit the dev environment of this proxy to capture some traces, then retry."));
2533
+ console.log(import_chalk16.default.yellow("No captured traffic samples found. Hit the dev environment of this proxy to capture some traces, then retry."));
2494
2534
  return;
2495
2535
  }
2496
2536
  async function publish(ctx) {
2497
2537
  const patch = ctx.proposal.patch;
2498
2538
  if (!Array.isArray(patch) || patch.length === 0) {
2499
- ctx.log(import_chalk15.default.green(" Nothing to publish \u2014 the spec already covers the observed traffic.\n"));
2539
+ ctx.log(import_chalk16.default.green(" Nothing to publish \u2014 the spec already covers the observed traffic.\n"));
2500
2540
  return;
2501
2541
  }
2502
2542
  const specSource = ctx.lastData?.spec_source ?? "unknown";
2503
2543
  const endpoint = specSource === "github" ? "open-pr" : "publish-openapi";
2504
2544
  const pub = await agentCall(`/projects/${projectId}/${apiVersion}/samples/${endpoint}`, "POST", { patch, sample_ids_used: sampleIds });
2505
2545
  if (pub.status >= 400) {
2506
- ctx.log(import_chalk15.default.red(` Publish failed (${pub.status}): ${pub.data?.error ?? ""}
2546
+ ctx.log(import_chalk16.default.red(` Publish failed (${pub.status}): ${pub.data?.error ?? ""}
2507
2547
  `));
2508
2548
  return;
2509
2549
  }
2510
2550
  const prUrl = pub.data?.pr_url;
2511
- ctx.log(import_chalk15.default.green(prUrl ? ` \u2713 Pull request opened: ${prUrl}
2551
+ ctx.log(import_chalk16.default.green(prUrl ? ` \u2713 Pull request opened: ${prUrl}
2512
2552
  ` : " \u2713 Published updated OpenAPI spec.\n"));
2513
2553
  }
2514
2554
  await runAgentChatRepl({
@@ -2529,7 +2569,7 @@ async function runOpenapi(projectArg, apiVersionArg) {
2529
2569
  }
2530
2570
 
2531
2571
  // src/commands/mcp.ts
2532
- var import_chalk16 = __toESM(require("chalk"));
2572
+ var import_chalk17 = __toESM(require("chalk"));
2533
2573
  init_auth();
2534
2574
  init_api();
2535
2575
  async function runMcp(projectArg, apiVersionArg, opts) {
@@ -2546,11 +2586,11 @@ async function runMcp(projectArg, apiVersionArg, opts) {
2546
2586
  const spec2 = ctx.proposal;
2547
2587
  const pub = await agentCall(`/projects/${projectId}/${apiVersion}/mcp/spec`, "PUT", { environment, spec: spec2 });
2548
2588
  if (pub.status >= 400) {
2549
- ctx.log(import_chalk16.default.red(` Publish failed (${pub.status}): ${pub.data?.error ?? ""}
2589
+ ctx.log(import_chalk17.default.red(` Publish failed (${pub.status}): ${pub.data?.error ?? ""}
2550
2590
  `));
2551
2591
  return;
2552
2592
  }
2553
- ctx.log(import_chalk16.default.green(` \u2713 Published MCP server \u2014 ${mcpHost}.mcp.apiblaze.com/${apiVersion}/${environment}.
2593
+ ctx.log(import_chalk17.default.green(` \u2713 Published MCP server \u2014 ${mcpHost}.mcp.apiblaze.com/${apiVersion}/${environment}.
2554
2594
  `));
2555
2595
  }
2556
2596
  await runAgentChatRepl({
@@ -2572,18 +2612,18 @@ async function runMcp(projectArg, apiVersionArg, opts) {
2572
2612
  }
2573
2613
 
2574
2614
  // src/commands/delete.ts
2575
- var import_chalk18 = __toESM(require("chalk"));
2615
+ var import_chalk19 = __toESM(require("chalk"));
2576
2616
  var import_ora5 = __toESM(require("ora"));
2577
2617
  init_admin();
2578
2618
 
2579
2619
  // src/lib/resolve.ts
2580
- var import_chalk17 = __toESM(require("chalk"));
2620
+ var import_chalk18 = __toESM(require("chalk"));
2581
2621
  init_auth();
2582
2622
  init_api();
2583
2623
  function requireAuth() {
2584
2624
  const creds = loadCredentials();
2585
2625
  if (!creds) {
2586
- console.error(import_chalk17.default.red("Not logged in. Run `apiblaze login` first."));
2626
+ console.error(import_chalk18.default.red("Not logged in. Run `apiblaze login` first."));
2587
2627
  process.exit(1);
2588
2628
  }
2589
2629
  return creds;
@@ -2592,7 +2632,7 @@ async function resolveTeam(opt) {
2592
2632
  const creds = requireAuth();
2593
2633
  if (!opt) {
2594
2634
  if (!creds.teamId) {
2595
- console.error(import_chalk17.default.red("No active team. Run `apiblaze login` or pass --team."));
2635
+ console.error(import_chalk18.default.red("No active team. Run `apiblaze login` or pass --team."));
2596
2636
  process.exit(1);
2597
2637
  }
2598
2638
  return { teamId: creds.teamId, teamName: creds.teamName };
@@ -2601,7 +2641,7 @@ async function resolveTeam(opt) {
2601
2641
  const teams = await getTeams().catch(() => []);
2602
2642
  const match = teams.find((t) => t.name === opt || t.teamId === opt);
2603
2643
  if (!match) {
2604
- console.error(import_chalk17.default.red(`Team "${opt}" not found.${teams.length ? " Available: " + teams.map((t) => t.name).join(", ") : ""}`));
2644
+ console.error(import_chalk18.default.red(`Team "${opt}" not found.${teams.length ? " Available: " + teams.map((t) => t.name).join(", ") : ""}`));
2605
2645
  process.exit(1);
2606
2646
  }
2607
2647
  return { teamId: match.teamId, teamName: match.name };
@@ -2612,13 +2652,13 @@ async function resolveProject(teamId, nameOrId, version2) {
2612
2652
  (p) => p.projectId === nameOrId || p.projectName === nameOrId
2613
2653
  );
2614
2654
  if (candidates.length === 0) {
2615
- console.error(import_chalk17.default.red(`Project "${nameOrId}" not found in this team.`));
2616
- if (projects.length) console.error(import_chalk17.default.dim(" Known: " + projects.map((p) => p.projectName).join(", ")));
2655
+ console.error(import_chalk18.default.red(`Project "${nameOrId}" not found in this team.`));
2656
+ if (projects.length) console.error(import_chalk18.default.dim(" Known: " + projects.map((p) => p.projectName).join(", ")));
2617
2657
  process.exit(1);
2618
2658
  }
2619
2659
  const chosen = version2 ? candidates.find((p) => p.apiVersion === version2) : candidates[0];
2620
2660
  if (!chosen) {
2621
- console.error(import_chalk17.default.red(`Project "${nameOrId}" has no version ${version2}. Versions: ${candidates.map((p) => p.apiVersion).join(", ")}`));
2661
+ console.error(import_chalk18.default.red(`Project "${nameOrId}" has no version ${version2}. Versions: ${candidates.map((p) => p.apiVersion).join(", ")}`));
2622
2662
  process.exit(1);
2623
2663
  }
2624
2664
  return {
@@ -2653,10 +2693,10 @@ async function runDelete(project, version2, opts) {
2653
2693
  return;
2654
2694
  }
2655
2695
  } else {
2656
- console.log(`${import_chalk18.default.red.bold("Delete")} ${import_chalk18.default.bold(proj2.projectName)} ${import_chalk18.default.dim("v" + proj2.apiVersion)} ${import_chalk18.default.dim("(" + proj2.projectId + ")")}`);
2696
+ console.log(`${import_chalk19.default.red.bold("Delete")} ${import_chalk19.default.bold(proj2.projectName)} ${import_chalk19.default.dim("v" + proj2.apiVersion)} ${import_chalk19.default.dim("(" + proj2.projectId + ")")}`);
2657
2697
  if (impact && typeof impact === "object") {
2658
2698
  const counts = impact.counts ?? impact.impact ?? impact;
2659
- console.log(import_chalk18.default.dim(" This removes (cascade): ") + import_chalk18.default.yellow(JSON.stringify(counts)));
2699
+ console.log(import_chalk19.default.dim(" This removes (cascade): ") + import_chalk19.default.yellow(JSON.stringify(counts)));
2660
2700
  }
2661
2701
  if (!opts.yes) {
2662
2702
  const { default: inquirer3 } = await import("inquirer");
@@ -2664,7 +2704,7 @@ async function runDelete(project, version2, opts) {
2664
2704
  { type: "confirm", name: "confirm", message: `Permanently delete ${proj2.projectName} v${proj2.apiVersion}? This cannot be undone.`, default: false }
2665
2705
  ]);
2666
2706
  if (!confirm) {
2667
- console.log(import_chalk18.default.dim("Aborted."));
2707
+ console.log(import_chalk19.default.dim("Aborted."));
2668
2708
  return;
2669
2709
  }
2670
2710
  }
@@ -2685,7 +2725,7 @@ async function runDelete(project, version2, opts) {
2685
2725
  }
2686
2726
 
2687
2727
  // src/commands/export.ts
2688
- var import_chalk19 = __toESM(require("chalk"));
2728
+ var import_chalk20 = __toESM(require("chalk"));
2689
2729
  var import_fs3 = require("fs");
2690
2730
  init_admin();
2691
2731
  init_auth();
@@ -2703,7 +2743,7 @@ async function runExport(projectArg, versionArg, opts) {
2703
2743
  if (opts.noConsumers) q.set("include_consumers", "0");
2704
2744
  if (opts.keys) q.set("keys", opts.keys);
2705
2745
  const qs = q.toString() ? `?${q.toString()}` : "";
2706
- console.log(import_chalk19.default.dim(`Queuing ${target} export of ${projectId}@${version2}\u2026`));
2746
+ console.log(import_chalk20.default.dim(`Queuing ${target} export of ${projectId}@${version2}\u2026`));
2707
2747
  const job = await admin({
2708
2748
  path: `/projects/${projectId}/${version2}/export/${target}${qs}`,
2709
2749
  method: "GET",
@@ -2713,11 +2753,11 @@ async function runExport(projectArg, versionArg, opts) {
2713
2753
  const statusPath = `/projects/${projectId}/${version2}/export/jobs/${job.job_id}`;
2714
2754
  let status = "queued";
2715
2755
  const started = Date.now();
2716
- process.stdout.write(import_chalk19.default.dim("Building bundle"));
2756
+ process.stdout.write(import_chalk20.default.dim("Building bundle"));
2717
2757
  while (status !== "ready" && status !== "failed") {
2718
2758
  if (Date.now() - started > 10 * 6e4) throw new Error("Export timed out after 10 minutes.");
2719
2759
  await new Promise((r) => setTimeout(r, 3e3));
2720
- process.stdout.write(import_chalk19.default.dim("."));
2760
+ process.stdout.write(import_chalk20.default.dim("."));
2721
2761
  const st = await admin({ path: statusPath, method: "GET", summary: "poll export" });
2722
2762
  status = st?.status ?? "queued";
2723
2763
  if (status === "failed") {
@@ -2735,14 +2775,14 @@ async function runExport(projectArg, versionArg, opts) {
2735
2775
  if (!res.ok) throw new Error(`Download failed (${res.status}): ${await res.text().catch(() => "")}`);
2736
2776
  const buf = Buffer.from(await res.arrayBuffer());
2737
2777
  (0, import_fs3.writeFileSync)(outFile, buf);
2738
- console.log(import_chalk19.default.green(`\u2713 Saved ${outFile} (${(buf.length / 1024).toFixed(0)} KB)`));
2739
- if (job.decryption_key) console.log(import_chalk19.default.yellow(`Decryption key (shown once): ${job.decryption_key}`));
2740
- console.log(import_chalk19.default.dim("Read MIGRATION-REPORT.json inside the zip for the full fidelity ledger."));
2741
- if (target === "kong") console.log(import_chalk19.default.dim("Kong: unzip, then `cd kong && docker compose up` (see kong/README.md)."));
2778
+ console.log(import_chalk20.default.green(`\u2713 Saved ${outFile} (${(buf.length / 1024).toFixed(0)} KB)`));
2779
+ if (job.decryption_key) console.log(import_chalk20.default.yellow(`Decryption key (shown once): ${job.decryption_key}`));
2780
+ console.log(import_chalk20.default.dim("Read MIGRATION-REPORT.json inside the zip for the full fidelity ledger."));
2781
+ if (target === "kong") console.log(import_chalk20.default.dim("Kong: unzip, then `cd kong && docker compose up` (see kong/README.md)."));
2742
2782
  }
2743
2783
 
2744
2784
  // src/commands/config.ts
2745
- var import_chalk20 = __toESM(require("chalk"));
2785
+ var import_chalk21 = __toESM(require("chalk"));
2746
2786
  var import_ora6 = __toESM(require("ora"));
2747
2787
  init_admin();
2748
2788
  async function patchConfig(project, opts, body, summary) {
@@ -2765,7 +2805,7 @@ async function patchConfig(project, opts, body, summary) {
2765
2805
  }
2766
2806
  async function runTargetSet(project, opts) {
2767
2807
  if (!opts.url) {
2768
- console.error(import_chalk20.default.red("--url is required."));
2808
+ console.error(import_chalk21.default.red("--url is required."));
2769
2809
  process.exit(1);
2770
2810
  }
2771
2811
  const body = opts.env ? { environments: { [opts.env]: { target: opts.url } } } : { target_url: opts.url };
@@ -2778,38 +2818,38 @@ async function runThrottleSet(project, opts) {
2778
2818
  if (opts.quota !== void 0) throttling.proxyQuota = Number(opts.quota);
2779
2819
  if (opts.period !== void 0) {
2780
2820
  if (!["daily", "weekly", "monthly"].includes(opts.period)) {
2781
- console.error(import_chalk20.default.red("--period must be daily, weekly, or monthly."));
2821
+ console.error(import_chalk21.default.red("--period must be daily, weekly, or monthly."));
2782
2822
  process.exit(1);
2783
2823
  }
2784
2824
  throttling.quotaPeriod = opts.period;
2785
2825
  }
2786
2826
  if (Object.keys(throttling).length === 0) {
2787
- console.error(import_chalk20.default.red("Nothing to set. Pass at least one of --rate, --end-user-rate, --quota, --period."));
2827
+ console.error(import_chalk21.default.red("Nothing to set. Pass at least one of --rate, --end-user-rate, --quota, --period."));
2788
2828
  process.exit(1);
2789
2829
  }
2790
2830
  await patchConfig(project, opts, { throttling }, `Update throttling ${JSON.stringify(throttling)}`);
2791
2831
  }
2792
2832
  async function runRename(project, opts) {
2793
2833
  if (!opts.displayName) {
2794
- console.error(import_chalk20.default.red("--display-name is required."));
2834
+ console.error(import_chalk21.default.red("--display-name is required."));
2795
2835
  process.exit(1);
2796
2836
  }
2797
2837
  await patchConfig(project, opts, { display_name: opts.displayName }, `Rename \u2192 "${opts.displayName}"`);
2798
2838
  }
2799
2839
 
2800
2840
  // src/commands/config-browse.ts
2801
- var import_chalk29 = __toESM(require("chalk"));
2841
+ var import_chalk30 = __toESM(require("chalk"));
2802
2842
  var import_ora14 = __toESM(require("ora"));
2803
2843
  init_admin();
2804
2844
  init_auth();
2805
2845
 
2806
2846
  // src/commands/domain.ts
2807
- var import_chalk21 = __toESM(require("chalk"));
2847
+ var import_chalk22 = __toESM(require("chalk"));
2808
2848
  var import_ora7 = __toESM(require("ora"));
2809
2849
  init_admin();
2810
2850
  async function runDomainAdd(project, opts) {
2811
2851
  if (!opts.domain) {
2812
- console.error(import_chalk21.default.red("--domain is required."));
2852
+ console.error(import_chalk22.default.red("--domain is required."));
2813
2853
  process.exit(1);
2814
2854
  }
2815
2855
  const { teamId } = await resolveTeam(opts.team);
@@ -2828,9 +2868,9 @@ async function runDomainAdd(project, opts) {
2828
2868
  console.log(JSON.stringify(out));
2829
2869
  return;
2830
2870
  }
2831
- if (out?.cnameRecord) console.log(` ${import_chalk21.default.cyan("CNAME")} ${out.cnameRecord.name ?? opts.domain} \u2192 ${out.cnameRecord.value ?? out.cnameRecord.target}`);
2832
- if (out?.dcv) console.log(` ${import_chalk21.default.cyan("TXT")} ${out.dcv.name} = ${out.dcv.value}`);
2833
- if (out?.id) console.log(import_chalk21.default.dim(` domain id: ${out.id}`));
2871
+ if (out?.cnameRecord) console.log(` ${import_chalk22.default.cyan("CNAME")} ${out.cnameRecord.name ?? opts.domain} \u2192 ${out.cnameRecord.value ?? out.cnameRecord.target}`);
2872
+ if (out?.dcv) console.log(` ${import_chalk22.default.cyan("TXT")} ${out.dcv.name} = ${out.dcv.value}`);
2873
+ if (out?.id) console.log(import_chalk22.default.dim(` domain id: ${out.id}`));
2834
2874
  } catch (err) {
2835
2875
  spinner.fail("Domain registration failed.");
2836
2876
  throw err;
@@ -2850,14 +2890,14 @@ async function runDomainList(project, opts) {
2850
2890
  return;
2851
2891
  }
2852
2892
  if (!domains.length) {
2853
- console.log(import_chalk21.default.yellow("No custom domains."));
2893
+ console.log(import_chalk22.default.yellow("No custom domains."));
2854
2894
  return;
2855
2895
  }
2856
- for (const d of domains) console.log(` ${import_chalk21.default.bold(d.hostname)} ${import_chalk21.default.dim(d.status ?? "")} ${import_chalk21.default.dim(d.id ?? "")}`);
2896
+ for (const d of domains) console.log(` ${import_chalk22.default.bold(d.hostname)} ${import_chalk22.default.dim(d.status ?? "")} ${import_chalk22.default.dim(d.id ?? "")}`);
2857
2897
  }
2858
2898
  async function runDomainStatus(project, opts) {
2859
2899
  if (!opts.id) {
2860
- console.error(import_chalk21.default.red("--id <domainId> is required (see `apiblaze domain list`)."));
2900
+ console.error(import_chalk22.default.red("--id <domainId> is required (see `apiblaze domain list`)."));
2861
2901
  process.exit(1);
2862
2902
  }
2863
2903
  const { teamId } = await resolveTeam(opts.team);
@@ -2867,11 +2907,11 @@ async function runDomainStatus(project, opts) {
2867
2907
  path: `/projects/${proj2.projectId}/domains/${encodeURIComponent(opts.id)}/status`,
2868
2908
  summary: `Check custom-domain status`
2869
2909
  });
2870
- console.log(opts.json ? JSON.stringify(out) : ` ${import_chalk21.default.bold(out?.hostname ?? opts.id)}: ${import_chalk21.default.cyan(out?.status ?? "unknown")}`);
2910
+ console.log(opts.json ? JSON.stringify(out) : ` ${import_chalk22.default.bold(out?.hostname ?? opts.id)}: ${import_chalk22.default.cyan(out?.status ?? "unknown")}`);
2871
2911
  }
2872
2912
  async function runDomainRemove(project, opts) {
2873
2913
  if (!opts.id) {
2874
- console.error(import_chalk21.default.red("--id <domainId> is required (see `apiblaze domain list`)."));
2914
+ console.error(import_chalk22.default.red("--id <domainId> is required (see `apiblaze domain list`)."));
2875
2915
  process.exit(1);
2876
2916
  }
2877
2917
  const { teamId } = await resolveTeam(opts.team);
@@ -2909,7 +2949,7 @@ async function runDomainSetBase(project, opts) {
2909
2949
  }
2910
2950
 
2911
2951
  // src/commands/tenant.ts
2912
- var import_chalk24 = __toESM(require("chalk"));
2952
+ var import_chalk25 = __toESM(require("chalk"));
2913
2953
  var import_ora10 = __toESM(require("ora"));
2914
2954
  init_admin();
2915
2955
  init_auth();
@@ -2917,20 +2957,20 @@ init_tenant_pick();
2917
2957
  async function runTenantUse(query, opts) {
2918
2958
  const creds = loadCredentials();
2919
2959
  if (!creds) {
2920
- console.error(import_chalk24.default.red("Not logged in. Run `apiblaze login` first."));
2960
+ console.error(import_chalk25.default.red("Not logged in. Run `apiblaze login` first."));
2921
2961
  process.exit(1);
2922
2962
  }
2923
2963
  if (opts.clear) {
2924
2964
  delete creds.activeTenant;
2925
2965
  saveCredentials(creds);
2926
- console.log(import_chalk24.default.green("Tenant scope cleared."));
2966
+ console.log(import_chalk25.default.green("Tenant scope cleared."));
2927
2967
  return;
2928
2968
  }
2929
2969
  const { teamId } = await resolveTeam(opts.team);
2930
2970
  const slug = await pickTenant(teamId, { message: "Scope future commands to which tenant?", initialQuery: query });
2931
2971
  if (!slug) process.exit(1);
2932
2972
  saveCredentials({ ...creds, activeTenant: slug });
2933
- console.log(import_chalk24.default.green(`Tenant scope set to ${import_chalk24.default.bold(slug)}.`) + import_chalk24.default.dim(" (clear with `apiblaze tenant use --clear`)"));
2973
+ console.log(import_chalk25.default.green(`Tenant scope set to ${import_chalk25.default.bold(slug)}.`) + import_chalk25.default.dim(" (clear with `apiblaze tenant use --clear`)"));
2934
2974
  }
2935
2975
  async function runTenantList(opts) {
2936
2976
  const { teamId, teamName } = await resolveTeam(opts.team);
@@ -2947,22 +2987,22 @@ async function runTenantList(opts) {
2947
2987
  return;
2948
2988
  }
2949
2989
  if (!tenants.length) {
2950
- console.log(import_chalk24.default.yellow(opts.q ? `No tenants matching "${opts.q}".` : "No tenants."));
2990
+ console.log(import_chalk25.default.yellow(opts.q ? `No tenants matching "${opts.q}".` : "No tenants."));
2951
2991
  return;
2952
2992
  }
2953
2993
  for (const t of tenants) {
2954
2994
  const name = typeof t === "string" ? t : t.tenant_name;
2955
- const display = typeof t === "string" ? "" : import_chalk24.default.dim(` ${t.display_name ?? ""}`);
2956
- console.log(` ${import_chalk24.default.bold(name)}${display}`);
2995
+ const display = typeof t === "string" ? "" : import_chalk25.default.dim(` ${t.display_name ?? ""}`);
2996
+ console.log(` ${import_chalk25.default.bold(name)}${display}`);
2957
2997
  }
2958
2998
  const total = out?.total ?? tenants.length;
2959
2999
  if (total > tenants.length) {
2960
- console.log(import_chalk24.default.dim(` \u2026 showing ${tenants.length} of ${total} \u2014 narrow with --q <search>`));
3000
+ console.log(import_chalk25.default.dim(` \u2026 showing ${tenants.length} of ${total} \u2014 narrow with --q <search>`));
2961
3001
  }
2962
3002
  }
2963
3003
  async function runTenantCreate(opts) {
2964
3004
  if (!opts.name) {
2965
- console.error(import_chalk24.default.red("--name (display name) is required."));
3005
+ console.error(import_chalk25.default.red("--name (display name) is required."));
2966
3006
  process.exit(1);
2967
3007
  }
2968
3008
  const { teamId } = await resolveTeam(opts.team);
@@ -2974,7 +3014,7 @@ async function runTenantCreate(opts) {
2974
3014
  body: { display_name: opts.name, ...opts.slug ? { tenant_name: opts.slug } : {} },
2975
3015
  summary: `Create tenant "${opts.name}"`
2976
3016
  });
2977
- spinner.succeed(`Created tenant ${import_chalk24.default.bold(out?.tenant_name ?? opts.name)}.`);
3017
+ spinner.succeed(`Created tenant ${import_chalk25.default.bold(out?.tenant_name ?? opts.name)}.`);
2978
3018
  if (opts.json) console.log(JSON.stringify(out));
2979
3019
  } catch (err) {
2980
3020
  spinner.fail("Tenant create failed.");
@@ -2983,7 +3023,7 @@ async function runTenantCreate(opts) {
2983
3023
  }
2984
3024
  async function runTenantAttach(project, opts) {
2985
3025
  if (!opts.tenant) {
2986
- console.error(import_chalk24.default.red("--tenant <slug> is required."));
3026
+ console.error(import_chalk25.default.red("--tenant <slug> is required."));
2987
3027
  process.exit(1);
2988
3028
  }
2989
3029
  const { teamId } = await resolveTeam(opts.team);
@@ -3011,7 +3051,7 @@ async function runTenantDelete(slug, opts) {
3011
3051
  { type: "confirm", name: "confirm", message: `Permanently delete tenant "${slug}" and everything under it? This cannot be undone.`, default: false }
3012
3052
  ]);
3013
3053
  if (!confirm) {
3014
- console.log(import_chalk24.default.dim("Aborted."));
3054
+ console.log(import_chalk25.default.dim("Aborted."));
3015
3055
  return;
3016
3056
  }
3017
3057
  }
@@ -3030,7 +3070,7 @@ async function runTenantDelete(slug, opts) {
3030
3070
  }
3031
3071
  async function runTenantCors(opts) {
3032
3072
  if (!opts.tenant) {
3033
- console.error(import_chalk24.default.red("--tenant <slug> is required."));
3073
+ console.error(import_chalk25.default.red("--tenant <slug> is required."));
3034
3074
  process.exit(1);
3035
3075
  }
3036
3076
  const { teamId } = await resolveTeam(opts.team);
@@ -3052,7 +3092,7 @@ async function runTenantCors(opts) {
3052
3092
  }
3053
3093
 
3054
3094
  // src/commands/tenant-drill.ts
3055
- var import_chalk25 = __toESM(require("chalk"));
3095
+ var import_chalk26 = __toESM(require("chalk"));
3056
3096
  var import_ora11 = __toESM(require("ora"));
3057
3097
  var import_crypto = require("crypto");
3058
3098
  init_admin();
@@ -3082,15 +3122,15 @@ async function validScopedTenant(teamId, query) {
3082
3122
  const next = { ...creds };
3083
3123
  delete next.activeTenant;
3084
3124
  saveCredentials2(next);
3085
- console.log(import_chalk25.default.yellow(`Tenant scope "${scoped}" no longer exists in this team \u2014 cleared.`));
3125
+ console.log(import_chalk26.default.yellow(`Tenant scope "${scoped}" no longer exists in this team \u2014 cleared.`));
3086
3126
  return void 0;
3087
3127
  }
3088
3128
  async function tenantHome(teamId, tenant2) {
3089
3129
  const { default: inquirer3 } = await import("inquirer");
3090
3130
  const base = `/teams/${encodeURIComponent(teamId)}/tenants/${encodeURIComponent(tenant2)}`;
3091
- console.log(import_chalk25.default.bold(`
3131
+ console.log(import_chalk26.default.bold(`
3092
3132
  Tenant ${tenant2}`));
3093
- console.log(import_chalk25.default.dim("Tenant auth/settings are SHARED: changes apply to every proxy this tenant serves.\n"));
3133
+ console.log(import_chalk26.default.dim("Tenant auth/settings are SHARED: changes apply to every proxy this tenant serves.\n"));
3094
3134
  for (; ; ) {
3095
3135
  const spinner = (0, import_ora11.default)("Reading tenant state...").start();
3096
3136
  const [iam, cors, emails, issuers, opaque, clients] = await Promise.all([
@@ -3106,18 +3146,18 @@ Tenant ${tenant2}`));
3106
3146
  const nClients = Array.isArray(clients) ? clients.length : 0;
3107
3147
  const nOpaque = opaque?.opaque?.endpoint ? 1 : 0;
3108
3148
  const nLogin = nClients + nIssuers + nOpaque;
3109
- const onOff = (b) => b ? import_chalk25.default.green("on") : import_chalk25.default.dim("off");
3149
+ const onOff = (b) => b ? import_chalk26.default.green("on") : import_chalk26.default.dim("off");
3110
3150
  const { pick: pick2 } = await inquirer3.prompt([{
3111
3151
  type: "list",
3112
3152
  name: "pick",
3113
3153
  message: `Tenant ${tenant2}:`,
3114
3154
  pageSize: 12,
3115
3155
  choices: [
3116
- { name: `Login methods (${nLogin}) ${import_chalk25.default.dim("how your consumers sign in")}`, value: "login" },
3117
- { name: `Users & groups: ${onOff(iam?.iam_enabled)} ${import_chalk25.default.dim(`identity & key management (${tenant2}.iam.apiblaze.com)`)}`, value: "iam" },
3118
- { name: `Portal admins (${nEmails}) ${import_chalk25.default.dim("emails allowed to administer this tenant's portal")}`, value: "emails" },
3119
- new inquirer3.Separator(import_chalk25.default.dim(" Settings")),
3120
- { name: `CORS: ${cors?.cors ? import_chalk25.default.cyan(JSON.stringify(cors.cors)) : import_chalk25.default.dim("(unset)")} ${import_chalk25.default.dim("browser origins allowed to call this tenant")}`, value: "cors" },
3156
+ { name: `Login methods (${nLogin}) ${import_chalk26.default.dim("how your consumers sign in")}`, value: "login" },
3157
+ { name: `Users & groups: ${onOff(iam?.iam_enabled)} ${import_chalk26.default.dim(`identity & key management (${tenant2}.iam.apiblaze.com)`)}`, value: "iam" },
3158
+ { name: `Portal admins (${nEmails}) ${import_chalk26.default.dim("emails allowed to administer this tenant's portal")}`, value: "emails" },
3159
+ new inquirer3.Separator(import_chalk26.default.dim(" Settings")),
3160
+ { name: `CORS: ${cors?.cors ? import_chalk26.default.cyan(JSON.stringify(cors.cors)) : import_chalk26.default.dim("(unset)")} ${import_chalk26.default.dim("browser origins allowed to call this tenant")}`, value: "cors" },
3121
3161
  { name: "\u2190 Back", value: "back" }
3122
3162
  ]
3123
3163
  }]);
@@ -3130,7 +3170,7 @@ Tenant ${tenant2}`));
3130
3170
  case "iam": {
3131
3171
  const { v } = await inquirer3.prompt([{ type: "confirm", name: "v", message: "Enable Users & groups?", default: !!iam?.iam_enabled }]);
3132
3172
  await admin({ method: "PATCH", path: `${base}/iam`, body: { enabled: v }, summary: `IAM enforcement \u2192 ${v ? "on" : "off"}` });
3133
- console.log(import_chalk25.default.green(` Users & groups ${v ? "enabled" : "disabled"}.`));
3173
+ console.log(import_chalk26.default.green(` Users & groups ${v ? "enabled" : "disabled"}.`));
3134
3174
  break;
3135
3175
  }
3136
3176
  case "cors": {
@@ -3143,11 +3183,11 @@ Tenant ${tenant2}`));
3143
3183
  if (v === "") break;
3144
3184
  const parsed = v === "null" ? null : safeJson(v);
3145
3185
  if (parsed === void 0) {
3146
- console.log(import_chalk25.default.yellow(" Not valid JSON \u2014 unchanged."));
3186
+ console.log(import_chalk26.default.yellow(" Not valid JSON \u2014 unchanged."));
3147
3187
  break;
3148
3188
  }
3149
3189
  await admin({ method: "PUT", path: `${base}/cors`, body: { cors: parsed }, summary: "Set tenant CORS" });
3150
- console.log(import_chalk25.default.green(" CORS updated."));
3190
+ console.log(import_chalk26.default.green(" CORS updated."));
3151
3191
  break;
3152
3192
  }
3153
3193
  case "emails":
@@ -3171,15 +3211,15 @@ async function loginMethodsMenu(teamId, tenant2, base) {
3171
3211
  const choices = [];
3172
3212
  for (const c of appClients) {
3173
3213
  const nP = (c.providers ?? []).length || c.providers_count || 0;
3174
- choices.push({ name: `${import_chalk25.default.cyan("APIblaze-hosted")} ${import_chalk25.default.bold(c.name ?? c.clientId)} ${import_chalk25.default.dim(`${c.clientId}${nP ? ` \xB7 ${nP} provider${nP === 1 ? "" : "s"}` : import_chalk25.default.yellow(" \xB7 needs a provider")}`)}`, value: { kind: "client", item: c } });
3214
+ choices.push({ name: `${import_chalk26.default.cyan("APIblaze-hosted")} ${import_chalk26.default.bold(c.name ?? c.clientId)} ${import_chalk26.default.dim(`${c.clientId}${nP ? ` \xB7 ${nP} provider${nP === 1 ? "" : "s"}` : import_chalk26.default.yellow(" \xB7 needs a provider")}`)}`, value: { kind: "client", item: c } });
3175
3215
  }
3176
3216
  for (const i of issuers) {
3177
- choices.push({ name: `${import_chalk25.default.cyan("Your own \u2014 JWT ")} ${import_chalk25.default.bold(i.iss)} ${import_chalk25.default.dim(`aud=${i.aud}`)}`, value: { kind: "issuer", item: i } });
3217
+ choices.push({ name: `${import_chalk26.default.cyan("Your own \u2014 JWT ")} ${import_chalk26.default.bold(i.iss)} ${import_chalk26.default.dim(`aud=${i.aud}`)}`, value: { kind: "issuer", item: i } });
3178
3218
  }
3179
3219
  if (opaque?.endpoint) {
3180
- choices.push({ name: `${import_chalk25.default.cyan("Your own \u2014 opaque")} ${import_chalk25.default.bold(opaque.endpoint)}`, value: { kind: "opaque", item: opaque } });
3220
+ choices.push({ name: `${import_chalk26.default.cyan("Your own \u2014 opaque")} ${import_chalk26.default.bold(opaque.endpoint)}`, value: { kind: "opaque", item: opaque } });
3181
3221
  }
3182
- if (!choices.length) console.log(import_chalk25.default.dim("\n No login methods yet \u2014 consumers cannot sign in until you add one."));
3222
+ if (!choices.length) console.log(import_chalk26.default.dim("\n No login methods yet \u2014 consumers cannot sign in until you add one."));
3183
3223
  const { pick: pick2 } = await inquirer3.prompt([{
3184
3224
  type: "list",
3185
3225
  name: "pick",
@@ -3219,9 +3259,9 @@ async function addLoginMethod(teamId, tenant2, base) {
3219
3259
  message: "How do people log in?",
3220
3260
  pageSize: 8,
3221
3261
  choices: [
3222
- { name: `APIblaze hosted login page ${import_chalk25.default.dim("we host login; pick a provider (GitHub/Google/\u2026) \u2014 easiest")}`, value: "apiblaze" },
3223
- { name: `Your own hosted login \u2014 JWT ${import_chalk25.default.dim("your identity provider issues JWTs; we trust them")}`, value: "jwt" },
3224
- { name: `Your own login \u2014 opaque token ${import_chalk25.default.dim("we validate your opaque tokens via an introspection endpoint")}`, value: "opaque" },
3262
+ { name: `APIblaze hosted login page ${import_chalk26.default.dim("we host login; pick a provider (GitHub/Google/\u2026) \u2014 easiest")}`, value: "apiblaze" },
3263
+ { name: `Your own hosted login \u2014 JWT ${import_chalk26.default.dim("your identity provider issues JWTs; we trust them")}`, value: "jwt" },
3264
+ { name: `Your own login \u2014 opaque token ${import_chalk26.default.dim("we validate your opaque tokens via an introspection endpoint")}`, value: "opaque" },
3225
3265
  { name: "\u2190 Back", value: null }
3226
3266
  ]
3227
3267
  }]);
@@ -3245,8 +3285,8 @@ function safeJson(s) {
3245
3285
  async function emailsMenu(base, emails) {
3246
3286
  const { default: inquirer3 } = await import("inquirer");
3247
3287
  console.log();
3248
- if (!emails.length) console.log(import_chalk25.default.dim(" No consumer-admin emails."));
3249
- for (const e of emails) console.log(` ${import_chalk25.default.bold(e.email ?? e)} ${import_chalk25.default.dim(e.status ?? "")}`);
3288
+ if (!emails.length) console.log(import_chalk26.default.dim(" No consumer-admin emails."));
3289
+ for (const e of emails) console.log(` ${import_chalk26.default.bold(e.email ?? e)} ${import_chalk26.default.dim(e.status ?? "")}`);
3250
3290
  const { act } = await inquirer3.prompt([{
3251
3291
  type: "list",
3252
3292
  name: "act",
@@ -3261,7 +3301,7 @@ async function emailsMenu(base, emails) {
3261
3301
  if (act === "add") {
3262
3302
  const { email } = await inquirer3.prompt([{ type: "input", name: "email", message: "Email:", validate: (s) => /.+@.+\..+/.test(s) || "not an email" }]);
3263
3303
  await admin({ method: "POST", path: `${base}/admin-emails`, body: { email }, summary: `Add consumer-admin ${email}` });
3264
- console.log(import_chalk25.default.green(` ${email} added.`));
3304
+ console.log(import_chalk26.default.green(` ${email} added.`));
3265
3305
  } else {
3266
3306
  const { e } = await inquirer3.prompt([{
3267
3307
  type: "list",
@@ -3271,7 +3311,7 @@ async function emailsMenu(base, emails) {
3271
3311
  }]);
3272
3312
  if (!e) return;
3273
3313
  await admin({ method: "DELETE", path: `${base}/admin-emails/${encodeURIComponent(e)}`, summary: `Remove consumer-admin ${e}` });
3274
- console.log(import_chalk25.default.green(` ${e} removed.`));
3314
+ console.log(import_chalk26.default.green(` ${e} removed.`));
3275
3315
  }
3276
3316
  }
3277
3317
  async function addIssuer(base) {
@@ -3292,19 +3332,19 @@ async function addIssuer(base) {
3292
3332
  body: { iss: a.iss.trim(), aud: a.aud.trim(), jwks_url: a.jwks.trim() || null, sub_semantics: a.sem, ...claim ? { claim_name: claim } : {} },
3293
3333
  summary: `Add external issuer ${a.iss.trim()}`
3294
3334
  });
3295
- console.log(import_chalk25.default.green(" JWT login method saved."));
3335
+ console.log(import_chalk26.default.green(" JWT login method saved."));
3296
3336
  }
3297
3337
  async function issuerHome(base, issuer) {
3298
3338
  const { default: inquirer3 } = await import("inquirer");
3299
3339
  console.log(`
3300
- ${import_chalk25.default.bold(issuer.iss)} ${import_chalk25.default.dim(`aud=${issuer.aud} \xB7 ${issuer.sub_semantics ?? ""}`)}`);
3340
+ ${import_chalk26.default.bold(issuer.iss)} ${import_chalk26.default.dim(`aud=${issuer.aud} \xB7 ${issuer.sub_semantics ?? ""}`)}`);
3301
3341
  const { act } = await inquirer3.prompt([{
3302
3342
  type: "list",
3303
3343
  name: "act",
3304
3344
  message: "This JWT login method:",
3305
3345
  choices: [
3306
3346
  { name: "Replace it (re-enter details)", value: "edit" },
3307
- { name: import_chalk25.default.red("Delete it"), value: "rm" },
3347
+ { name: import_chalk26.default.red("Delete it"), value: "rm" },
3308
3348
  { name: "\u2190 Back", value: "back" }
3309
3349
  ]
3310
3350
  }]);
@@ -3320,7 +3360,7 @@ async function issuerHome(base, issuer) {
3320
3360
  path: `${base}/external-issuers?iss=${encodeURIComponent(issuer.iss)}&aud=${encodeURIComponent(issuer.aud)}`,
3321
3361
  summary: `Delete issuer ${issuer.iss}`
3322
3362
  });
3323
- console.log(import_chalk25.default.green(" Deleted."));
3363
+ console.log(import_chalk26.default.green(" Deleted."));
3324
3364
  }
3325
3365
  async function setOpaque(base, cur) {
3326
3366
  const { default: inquirer3 } = await import("inquirer");
@@ -3329,19 +3369,19 @@ async function setOpaque(base, cur) {
3329
3369
  { type: "list", name: "method", message: "HTTP method:", choices: ["GET", "POST"], default: cur?.method ?? "GET" }
3330
3370
  ]);
3331
3371
  await admin({ method: "PUT", path: `${base}/opaque`, body: { opaque: { endpoint: a.endpoint, method: a.method } }, summary: "Set opaque validator" });
3332
- console.log(import_chalk25.default.green(" Opaque login method set."));
3372
+ console.log(import_chalk26.default.green(" Opaque login method set."));
3333
3373
  }
3334
3374
  async function opaqueHome(base, cur) {
3335
3375
  const { default: inquirer3 } = await import("inquirer");
3336
3376
  console.log(`
3337
- ${import_chalk25.default.bold(cur.endpoint)} ${import_chalk25.default.dim(cur.method ?? "GET")}`);
3377
+ ${import_chalk26.default.bold(cur.endpoint)} ${import_chalk26.default.dim(cur.method ?? "GET")}`);
3338
3378
  const { act } = await inquirer3.prompt([{
3339
3379
  type: "list",
3340
3380
  name: "act",
3341
3381
  message: "This opaque login method:",
3342
3382
  choices: [
3343
3383
  { name: "Replace it", value: "edit" },
3344
- { name: import_chalk25.default.red("Delete it"), value: "rm" },
3384
+ { name: import_chalk26.default.red("Delete it"), value: "rm" },
3345
3385
  { name: "\u2190 Back", value: "back" }
3346
3386
  ]
3347
3387
  }]);
@@ -3351,7 +3391,7 @@ async function opaqueHome(base, cur) {
3351
3391
  return;
3352
3392
  }
3353
3393
  await admin({ method: "PUT", path: `${base}/opaque`, body: { opaque: null }, summary: "Clear opaque validator" });
3354
- console.log(import_chalk25.default.green(" Deleted."));
3394
+ console.log(import_chalk26.default.green(" Deleted."));
3355
3395
  }
3356
3396
  async function clientHome(base, summary) {
3357
3397
  const { default: inquirer3 } = await import("inquirer");
@@ -3370,13 +3410,13 @@ async function clientHome(base, summary) {
3370
3410
  message: `${c.name ?? id}:`,
3371
3411
  pageSize: 12,
3372
3412
  choices: [
3373
- { name: `Login providers${nProviders ? ` (${nProviders})` : ""} ${import_chalk25.default.dim("google/github/microsoft/\u2026 \u2014 how consumers sign in")}`, value: "providers" },
3374
- { name: `Callback URLs: ${cb.length ? import_chalk25.default.cyan(cb.join(", ")) : import_chalk25.default.dim("(none)")}`, value: "callbacks" },
3375
- { name: `Scopes: ${scopes.length ? import_chalk25.default.cyan(scopes.join(" ")) : import_chalk25.default.dim("(defaults)")}`, value: "scopes" },
3413
+ { name: `Login providers${nProviders ? ` (${nProviders})` : ""} ${import_chalk26.default.dim("google/github/microsoft/\u2026 \u2014 how consumers sign in")}`, value: "providers" },
3414
+ { name: `Callback URLs: ${cb.length ? import_chalk26.default.cyan(cb.join(", ")) : import_chalk26.default.dim("(none)")}`, value: "callbacks" },
3415
+ { name: `Scopes: ${scopes.length ? import_chalk26.default.cyan(scopes.join(" ")) : import_chalk26.default.dim("(defaults)")}`, value: "scopes" },
3376
3416
  { name: `Token expiries: access ${c.accessTokenExpiry ?? 3600}s \xB7 id ${c.idTokenExpiry ?? 3600}s \xB7 refresh ${c.refreshTokenExpiry ?? 2592e3}s`, value: "expiries" },
3377
3417
  { name: "Reveal client secret", value: "secret" },
3378
3418
  { name: "Rotate client secret", value: "rotate" },
3379
- { name: import_chalk25.default.red("Delete this app client"), value: "delete" },
3419
+ { name: import_chalk26.default.red("Delete this app client"), value: "delete" },
3380
3420
  { name: "\u2190 Back", value: "back" }
3381
3421
  ]
3382
3422
  }]);
@@ -3389,13 +3429,13 @@ async function clientHome(base, summary) {
3389
3429
  case "callbacks": {
3390
3430
  const { v } = await inquirer3.prompt([{ type: "input", name: "v", message: "Callback URLs (comma-separated):", default: cb.join(", ") }]);
3391
3431
  await admin({ method: "PATCH", path: cBase, body: { authorizedCallbackUrls: parseList(v) }, summary: "Update callback URLs" });
3392
- console.log(import_chalk25.default.green(" Callbacks updated."));
3432
+ console.log(import_chalk26.default.green(" Callbacks updated."));
3393
3433
  break;
3394
3434
  }
3395
3435
  case "scopes": {
3396
3436
  const { v } = await inquirer3.prompt([{ type: "input", name: "v", message: "Scopes (space/comma-separated):", default: scopes.join(" ") }]);
3397
3437
  await admin({ method: "PATCH", path: cBase, body: { scopes: v.split(/[\s,]+/).filter(Boolean) }, summary: "Update scopes" });
3398
- console.log(import_chalk25.default.green(" Scopes updated."));
3438
+ console.log(import_chalk26.default.green(" Scopes updated."));
3399
3439
  break;
3400
3440
  }
3401
3441
  case "expiries": {
@@ -3410,14 +3450,14 @@ async function clientHome(base, summary) {
3410
3450
  body: { accessTokenExpiry: Number(a.access), idTokenExpiry: Number(a.id), refreshTokenExpiry: Number(a.refresh) },
3411
3451
  summary: "Update token expiries"
3412
3452
  });
3413
- console.log(import_chalk25.default.green(" Expiries updated."));
3453
+ console.log(import_chalk26.default.green(" Expiries updated."));
3414
3454
  break;
3415
3455
  }
3416
3456
  case "secret": {
3417
3457
  const { sure } = await inquirer3.prompt([{ type: "confirm", name: "sure", message: "Print the client secret to this terminal?", default: false }]);
3418
3458
  if (!sure) break;
3419
3459
  const s = await admin({ method: "GET", path: `${cBase}/secret`, summary: "Reveal client secret" });
3420
- console.log(` ${import_chalk25.default.bold("client_secret")}: ${import_chalk25.default.green(s?.clientSecret ?? s?.client_secret ?? JSON.stringify(s))}`);
3460
+ console.log(` ${import_chalk26.default.bold("client_secret")}: ${import_chalk26.default.green(s?.clientSecret ?? s?.client_secret ?? JSON.stringify(s))}`);
3421
3461
  break;
3422
3462
  }
3423
3463
  case "rotate": {
@@ -3425,14 +3465,14 @@ async function clientHome(base, summary) {
3425
3465
  if (!sure) break;
3426
3466
  const fresh = randomSecret();
3427
3467
  await admin({ method: "PATCH", path: cBase, body: { clientSecret: fresh }, summary: "Rotate client secret" });
3428
- console.log(` New ${import_chalk25.default.bold("client_secret")}: ${import_chalk25.default.green(fresh)} ${import_chalk25.default.dim("(store it now)")}`);
3468
+ console.log(` New ${import_chalk26.default.bold("client_secret")}: ${import_chalk26.default.green(fresh)} ${import_chalk26.default.dim("(store it now)")}`);
3429
3469
  break;
3430
3470
  }
3431
3471
  case "delete": {
3432
3472
  const { sure } = await inquirer3.prompt([{ type: "confirm", name: "sure", message: `Delete app client "${c.name ?? id}"? Consumers logged in through it will lose access.`, default: false }]);
3433
3473
  if (!sure) break;
3434
3474
  await admin({ method: "DELETE", path: cBase, summary: `Delete app client ${id}` });
3435
- console.log(import_chalk25.default.green(" App client deleted."));
3475
+ console.log(import_chalk26.default.green(" App client deleted."));
3436
3476
  return;
3437
3477
  }
3438
3478
  }
@@ -3459,9 +3499,9 @@ async function providersMenu(cBase, clientLabel) {
3459
3499
  const providers = Array.isArray(raw) ? raw : [];
3460
3500
  console.log();
3461
3501
  for (const p of providers) {
3462
- console.log(` ${import_chalk25.default.bold(p.type)} ${import_chalk25.default.dim(`${p.clientId || "(managed)"} \xB7 identity=${p.tokenType ?? "apiblaze"} \xB7 to-upstream=${p.targetServerToken ?? "apiblaze"}${p.isApiblazeDefault ? " \xB7 apiblaze-managed" : ""}`)}`);
3502
+ console.log(` ${import_chalk26.default.bold(p.type)} ${import_chalk26.default.dim(`${p.clientId || "(managed)"} \xB7 identity=${p.tokenType ?? "apiblaze"} \xB7 to-upstream=${p.targetServerToken ?? "apiblaze"}${p.isApiblazeDefault ? " \xB7 apiblaze-managed" : ""}`)}`);
3463
3503
  }
3464
- if (!providers.length) console.log(import_chalk25.default.dim(" No login providers \u2014 consumers cannot sign in to this client yet."));
3504
+ if (!providers.length) console.log(import_chalk26.default.dim(" No login providers \u2014 consumers cannot sign in to this client yet."));
3465
3505
  const { act } = await inquirer3.prompt([{
3466
3506
  type: "list",
3467
3507
  name: "act",
@@ -3519,31 +3559,31 @@ async function providersMenu(cBase, clientLabel) {
3519
3559
  body.targetServerToken = routing;
3520
3560
  }
3521
3561
  await admin({ method: "POST", path: `${cBase}/providers`, body, summary: `Add ${type} login provider` });
3522
- console.log(import_chalk25.default.green(` ${type} provider added.`));
3562
+ console.log(import_chalk26.default.green(` ${type} provider added.`));
3523
3563
  } else {
3524
3564
  const { p } = await inquirer3.prompt([{
3525
3565
  type: "list",
3526
3566
  name: "p",
3527
3567
  message: act === "rm" ? "Remove which provider?" : "Reveal which secret?",
3528
- choices: [...providers.map((x) => ({ name: `${x.type} ${import_chalk25.default.dim(x.clientId || "(managed)")}`, value: x })), { name: "\u2190 Back", value: null }]
3568
+ choices: [...providers.map((x) => ({ name: `${x.type} ${import_chalk26.default.dim(x.clientId || "(managed)")}`, value: x })), { name: "\u2190 Back", value: null }]
3529
3569
  }]);
3530
3570
  if (!p) continue;
3531
3571
  if (act === "rm") {
3532
3572
  const { sure } = await inquirer3.prompt([{ type: "confirm", name: "sure", message: `Remove the ${p.type} provider? Consumers using it can no longer sign in.`, default: false }]);
3533
3573
  if (!sure) continue;
3534
3574
  await admin({ method: "DELETE", path: `${cBase}/providers/${encodeURIComponent(p.id)}`, summary: `Remove ${p.type} provider` });
3535
- console.log(import_chalk25.default.green(` ${p.type} removed.`));
3575
+ console.log(import_chalk26.default.green(` ${p.type} removed.`));
3536
3576
  } else {
3537
3577
  const s = await admin({ method: "GET", path: `${cBase}/providers/${encodeURIComponent(p.id)}/secret`, summary: `Reveal ${p.type} provider secret` });
3538
- console.log(` ${import_chalk25.default.bold("client_secret")}: ${import_chalk25.default.green(s?.clientSecret ?? s?.client_secret ?? JSON.stringify(s))}`);
3578
+ console.log(` ${import_chalk26.default.bold("client_secret")}: ${import_chalk26.default.green(s?.clientSecret ?? s?.client_secret ?? JSON.stringify(s))}`);
3539
3579
  }
3540
3580
  }
3541
3581
  }
3542
3582
  }
3543
3583
 
3544
3584
  // src/commands/spec.ts
3545
- var fs6 = __toESM(require("fs"));
3546
- var import_chalk26 = __toESM(require("chalk"));
3585
+ var fs7 = __toESM(require("fs"));
3586
+ var import_chalk27 = __toESM(require("chalk"));
3547
3587
  var import_ora12 = __toESM(require("ora"));
3548
3588
  init_admin();
3549
3589
  async function runSpecGet(project, opts) {
@@ -3558,14 +3598,14 @@ async function runSpecGet(project, opts) {
3558
3598
  }
3559
3599
  async function runSpecSet(project, opts) {
3560
3600
  if (!opts.file) {
3561
- console.error(import_chalk26.default.red("--file <path> is required (OpenAPI JSON or YAML)."));
3601
+ console.error(import_chalk27.default.red("--file <path> is required (OpenAPI JSON or YAML)."));
3562
3602
  process.exit(1);
3563
3603
  }
3564
3604
  let specContent;
3565
3605
  try {
3566
- specContent = fs6.readFileSync(opts.file, "utf-8");
3606
+ specContent = fs7.readFileSync(opts.file, "utf-8");
3567
3607
  } catch {
3568
- console.error(import_chalk26.default.red(`Cannot read file: ${opts.file}`));
3608
+ console.error(import_chalk27.default.red(`Cannot read file: ${opts.file}`));
3569
3609
  process.exit(1);
3570
3610
  }
3571
3611
  const { teamId } = await resolveTeam(opts.team);
@@ -3587,13 +3627,13 @@ async function runSpecSet(project, opts) {
3587
3627
  }
3588
3628
 
3589
3629
  // src/commands/agent.ts
3590
- var import_chalk28 = __toESM(require("chalk"));
3630
+ var import_chalk29 = __toESM(require("chalk"));
3591
3631
  var import_ora13 = __toESM(require("ora"));
3592
3632
  init_auth();
3593
3633
  init_admin();
3594
3634
 
3595
3635
  // src/lib/tools.ts
3596
- var import_chalk27 = __toESM(require("chalk"));
3636
+ var import_chalk28 = __toESM(require("chalk"));
3597
3637
  init_admin();
3598
3638
  init_api();
3599
3639
  async function proj(teamId, name, version2) {
@@ -3612,15 +3652,15 @@ var TOOLS = [
3612
3652
  const key = keys.dev ?? Object.values(keys)[0];
3613
3653
  const url = `https://${a.name}.abz.run/${version2}/dev`;
3614
3654
  const tryIt = buildTryItCurl(url, auth, key);
3615
- const lines = [` ${import_chalk27.default.dim("Proxy URL:")} ${import_chalk27.default.bold(url)}`];
3616
- if (res.devPortal) lines.push(` ${import_chalk27.default.dim("Dev portal:")} ${res.devPortal}`);
3655
+ const lines = [` ${import_chalk28.default.dim("Proxy URL:")} ${import_chalk28.default.bold(url)}`];
3656
+ if (res.devPortal) lines.push(` ${import_chalk28.default.dim("Dev portal:")} ${res.devPortal}`);
3617
3657
  const envs = Object.keys(keys);
3618
3658
  if (envs.length) {
3619
- lines.push("", ` ${import_chalk27.default.bold("API keys")} ${import_chalk27.default.dim("(bootstrapped \u2014 send as the X-API-Key header; shown once):")}`);
3659
+ lines.push("", ` ${import_chalk28.default.bold("API keys")} ${import_chalk28.default.dim("(bootstrapped \u2014 send as the X-API-Key header; shown once):")}`);
3620
3660
  const w = Math.max(...envs.map((e) => e.length));
3621
- for (const env of envs) lines.push(` ${import_chalk27.default.cyan(env.padEnd(w))} ${import_chalk27.default.green(keys[env])}`);
3661
+ for (const env of envs) lines.push(` ${import_chalk28.default.cyan(env.padEnd(w))} ${import_chalk28.default.green(keys[env])}`);
3622
3662
  }
3623
- if (tryIt) lines.push("", ` ${import_chalk27.default.dim("Try it:")}`, ` ${import_chalk27.default.cyan(tryIt)}`);
3663
+ if (tryIt) lines.push("", ` ${import_chalk28.default.dim("Try it:")}`, ` ${import_chalk28.default.cyan(tryIt)}`);
3624
3664
  return { ...res, proxy_url: url, keys, ...tryIt ? { try_it: tryIt } : {}, display: lines.join("\n") };
3625
3665
  }
3626
3666
  },
@@ -3776,17 +3816,17 @@ function truncate(value, max = 1500) {
3776
3816
  }
3777
3817
  function printCost(resp) {
3778
3818
  const line = formatBilling(resp.billing);
3779
- if (line) console.log(import_chalk28.default.magenta(` ${line}`) + import_chalk28.default.dim(` (${resp.llm.model}, ${resp.llm.total_tokens} tok)`));
3819
+ if (line) console.log(import_chalk29.default.magenta(` ${line}`) + import_chalk29.default.dim(` (${resp.llm.model}, ${resp.llm.total_tokens} tok)`));
3780
3820
  }
3781
3821
  async function runAgent(opts) {
3782
3822
  requireAuth();
3783
3823
  const { teamId, teamName } = await resolveTeam(opts.team);
3784
3824
  const { default: inquirer3 } = await import("inquirer");
3785
- console.log(import_chalk28.default.bold("APIblaze agent") + import_chalk28.default.dim(` \xB7 team ${teamName ?? teamId}`));
3786
- console.log(import_chalk28.default.dim('Ask me to create/delete/configure proxies, tenants, keys, domains, specs. Type "exit" to quit.\n'));
3825
+ console.log(import_chalk29.default.bold("APIblaze agent") + import_chalk29.default.dim(` \xB7 team ${teamName ?? teamId}`));
3826
+ console.log(import_chalk29.default.dim('Ask me to create/delete/configure proxies, tenants, keys, domains, specs. Type "exit" to quit.\n'));
3787
3827
  const history = [];
3788
3828
  while (true) {
3789
- const { input } = await inquirer3.prompt([{ type: "input", name: "input", message: import_chalk28.default.cyan("you") + " \u203A" }]);
3829
+ const { input } = await inquirer3.prompt([{ type: "input", name: "input", message: import_chalk29.default.cyan("you") + " \u203A" }]);
3790
3830
  const text = (input ?? "").trim();
3791
3831
  if (!text) continue;
3792
3832
  if (["exit", "quit", ":q"].includes(text.toLowerCase())) break;
@@ -3800,14 +3840,14 @@ async function runAgent(opts) {
3800
3840
  } catch (err) {
3801
3841
  spinner.stop();
3802
3842
  if (err instanceof ApiError && err.status === 402) {
3803
- console.log(import_chalk28.default.yellow(" Insufficient credits \u2014 top up to keep using the agent."));
3843
+ console.log(import_chalk29.default.yellow(" Insufficient credits \u2014 top up to keep using the agent."));
3804
3844
  break;
3805
3845
  }
3806
3846
  throw err;
3807
3847
  }
3808
3848
  history.push({ role: "assistant", content: resp.raw });
3809
3849
  printCost(resp);
3810
- if (resp.reply) console.log(import_chalk28.default.green("agent") + " \u203A " + resp.reply);
3850
+ if (resp.reply) console.log(import_chalk29.default.green("agent") + " \u203A " + resp.reply);
3811
3851
  if (!resp.action) break;
3812
3852
  const tool = findTool(resp.action.tool);
3813
3853
  if (!tool) {
@@ -3832,11 +3872,11 @@ async function runAgent(opts) {
3832
3872
  }
3833
3873
  renderTrace();
3834
3874
  if (step === MAX_TOOL_STEPS - 1) {
3835
- console.log(import_chalk28.default.dim(" (paused after several steps \u2014 tell me how to continue)"));
3875
+ console.log(import_chalk29.default.dim(" (paused after several steps \u2014 tell me how to continue)"));
3836
3876
  }
3837
3877
  }
3838
3878
  }
3839
- console.log(import_chalk28.default.dim("\nBye."));
3879
+ console.log(import_chalk29.default.dim("\nBye."));
3840
3880
  }
3841
3881
 
3842
3882
  // src/commands/config-browse.ts
@@ -3999,11 +4039,11 @@ function dig(blob, dotted) {
3999
4039
  }
4000
4040
  var readSetting = (s, cfg) => s.read ? s.read(cfg) : dig(cfg, s.key);
4001
4041
  function show(v) {
4002
- if (v === void 0) return import_chalk29.default.dim("(unset)");
4003
- if (v === null) return import_chalk29.default.dim("null");
4004
- if (typeof v === "object") return import_chalk29.default.cyan(JSON.stringify(v));
4005
- if (typeof v === "boolean") return v ? import_chalk29.default.green("on") : import_chalk29.default.red("off");
4006
- return import_chalk29.default.cyan(String(v));
4042
+ if (v === void 0) return import_chalk30.default.dim("(unset)");
4043
+ if (v === null) return import_chalk30.default.dim("null");
4044
+ if (typeof v === "object") return import_chalk30.default.cyan(JSON.stringify(v));
4045
+ if (typeof v === "boolean") return v ? import_chalk30.default.green("on") : import_chalk30.default.red("off");
4046
+ return import_chalk30.default.cyan(String(v));
4007
4047
  }
4008
4048
  function parseValue(raw) {
4009
4049
  if (raw === "true") return true;
@@ -4045,10 +4085,10 @@ async function patchSetting(proj2, s, value, cfg) {
4045
4085
  }
4046
4086
  }
4047
4087
  var loginFirst = (what) => {
4048
- console.log(import_chalk29.default.yellow(`
4088
+ console.log(import_chalk30.default.yellow(`
4049
4089
  Log in first to ${what}.`));
4050
- console.log(import_chalk29.default.dim(" Run `npx apiblaze login` \u2014 or `npx apiblaze claim` if you created this proxy"));
4051
- console.log(import_chalk29.default.dim(" anonymously and want to bring it into your account.\n"));
4090
+ console.log(import_chalk30.default.dim(" Run `npx apiblaze login` \u2014 or `npx apiblaze claim` if you created this proxy"));
4091
+ console.log(import_chalk30.default.dim(" anonymously and want to bring it into your account.\n"));
4052
4092
  };
4053
4093
  async function runConfig(project, key, value, opts) {
4054
4094
  const creds = loadCredentials();
@@ -4065,9 +4105,9 @@ async function runConfig(project, key, value, opts) {
4065
4105
  }
4066
4106
  const setting = SETTINGS.find((s) => s.key === key);
4067
4107
  if (!setting) {
4068
- console.error(import_chalk29.default.red(`Unknown setting "${key}".`));
4069
- console.error(import_chalk29.default.dim(" Known: " + SETTINGS.map((s) => s.key).join(", ")));
4070
- console.error(import_chalk29.default.dim(" (Features like transforms/domains/tenants live in the menu: `apiblaze config <project>`.)"));
4108
+ console.error(import_chalk30.default.red(`Unknown setting "${key}".`));
4109
+ console.error(import_chalk30.default.dim(" Known: " + SETTINGS.map((s) => s.key).join(", ")));
4110
+ console.error(import_chalk30.default.dim(" (Features like transforms/domains/tenants live in the menu: `apiblaze config <project>`.)"));
4071
4111
  process.exit(1);
4072
4112
  }
4073
4113
  if (value === void 0) {
@@ -4082,7 +4122,7 @@ async function pickProject(teamId) {
4082
4122
  const { getProjects: getProjects2 } = await Promise.resolve().then(() => (init_api(), api_exports));
4083
4123
  const projects = await getProjects2(teamId).catch(() => []);
4084
4124
  if (!projects.length) {
4085
- console.error(import_chalk29.default.red("No projects in this team. Create one: `npx apiblaze create`."));
4125
+ console.error(import_chalk30.default.red("No projects in this team. Create one: `npx apiblaze create`."));
4086
4126
  process.exit(1);
4087
4127
  }
4088
4128
  const { default: inquirer3 } = await import("inquirer");
@@ -4090,7 +4130,7 @@ async function pickProject(teamId) {
4090
4130
  type: "list",
4091
4131
  name: "picked",
4092
4132
  message: "Which project?",
4093
- choices: projects.map((p) => ({ name: `${p.projectName} ${import_chalk29.default.dim("v" + p.apiVersion)}`, value: p }))
4133
+ choices: projects.map((p) => ({ name: `${p.projectName} ${import_chalk30.default.dim("v" + p.apiVersion)}`, value: p }))
4094
4134
  }]);
4095
4135
  return { projectId: picked.projectId, projectName: picked.projectName, apiVersion: picked.apiVersion, teamId, tenant: picked.tenant };
4096
4136
  }
@@ -4101,25 +4141,25 @@ function printAll(proj2, cfg, json) {
4101
4141
  console.log(JSON.stringify(out, null, 2));
4102
4142
  return;
4103
4143
  }
4104
- console.log(import_chalk29.default.bold(`
4144
+ console.log(import_chalk30.default.bold(`
4105
4145
  ${proj2.projectName} v${proj2.apiVersion} \u2014 settings
4106
4146
  `));
4107
4147
  for (const group of SETTING_GROUPS) {
4108
- console.log(import_chalk29.default.bold(group));
4148
+ console.log(import_chalk30.default.bold(group));
4109
4149
  for (const s of SETTINGS.filter((x) => x.group === group)) {
4110
- console.log(` ${s.key.padEnd(32)} ${show(readSetting(s, cfg))} ${import_chalk29.default.dim(s.desc)}`);
4150
+ console.log(` ${s.key.padEnd(32)} ${show(readSetting(s, cfg))} ${import_chalk30.default.dim(s.desc)}`);
4111
4151
  }
4112
4152
  console.log();
4113
4153
  }
4114
- console.log(import_chalk29.default.dim("Change one: apiblaze config " + proj2.projectName + " <key> <value> (add --verbose for the API call)"));
4154
+ console.log(import_chalk30.default.dim("Change one: apiblaze config " + proj2.projectName + " <key> <value> (add --verbose for the API call)"));
4115
4155
  }
4116
4156
  async function discoveryMenu(project) {
4117
4157
  const { default: inquirer3 } = await import("inquirer");
4118
- console.log(import_chalk29.default.bold(`
4158
+ console.log(import_chalk30.default.bold(`
4119
4159
  APIblaze proxy configuration${project ? ` \u2014 ${project}` : ""}
4120
4160
  `));
4121
- console.log(import_chalk29.default.dim("You are not logged in \u2014 browsing what's configurable. Everything below works"));
4122
- console.log(import_chalk29.default.dim("from this menu once you log in (`npx apiblaze login`).\n"));
4161
+ console.log(import_chalk30.default.dim("You are not logged in \u2014 browsing what's configurable. Everything below works"));
4162
+ console.log(import_chalk30.default.dim("from this menu once you log in (`npx apiblaze login`).\n"));
4123
4163
  for (; ; ) {
4124
4164
  const { pick: pick2 } = await inquirer3.prompt([{
4125
4165
  type: "list",
@@ -4127,13 +4167,13 @@ APIblaze proxy configuration${project ? ` \u2014 ${project}` : ""}
4127
4167
  message: "Explore:",
4128
4168
  pageSize: 20,
4129
4169
  choices: [
4130
- new inquirer3.Separator(import_chalk29.default.bold("\u2014 Settings \u2014")),
4170
+ new inquirer3.Separator(import_chalk30.default.bold("\u2014 Settings \u2014")),
4131
4171
  ...SETTING_GROUPS.map((g) => ({
4132
- name: `${g} ${import_chalk29.default.dim(SETTINGS.filter((s) => s.group === g).map((s) => s.label).join(", "))}`,
4172
+ name: `${g} ${import_chalk30.default.dim(SETTINGS.filter((s) => s.group === g).map((s) => s.label).join(", "))}`,
4133
4173
  value: { kind: "settings", g }
4134
4174
  })),
4135
- new inquirer3.Separator(import_chalk29.default.bold("\u2014 Features \u2014")),
4136
- ...FEATURES.map((f) => ({ name: `${f.label} ${import_chalk29.default.dim(f.desc)}`, value: { kind: "feature", f } })),
4175
+ new inquirer3.Separator(import_chalk30.default.bold("\u2014 Features \u2014")),
4176
+ ...FEATURES.map((f) => ({ name: `${f.label} ${import_chalk30.default.dim(f.desc)}`, value: { kind: "feature", f } })),
4137
4177
  new inquirer3.Separator(),
4138
4178
  { name: "Exit", value: { kind: "exit" } }
4139
4179
  ]
@@ -4142,24 +4182,24 @@ APIblaze proxy configuration${project ? ` \u2014 ${project}` : ""}
4142
4182
  if (pick2.kind === "settings") {
4143
4183
  console.log();
4144
4184
  for (const s of SETTINGS.filter((x) => x.group === pick2.g)) {
4145
- console.log(` ${import_chalk29.default.bold(s.label.padEnd(28))} ${import_chalk29.default.dim(s.desc)}`);
4146
- console.log(` ${import_chalk29.default.dim(" key: " + s.key)}`);
4185
+ console.log(` ${import_chalk30.default.bold(s.label.padEnd(28))} ${import_chalk30.default.dim(s.desc)}`);
4186
+ console.log(` ${import_chalk30.default.dim(" key: " + s.key)}`);
4147
4187
  }
4148
4188
  loginFirst("view or change these settings");
4149
4189
  } else {
4150
4190
  const f = pick2.f;
4151
4191
  console.log(`
4152
- ${import_chalk29.default.bold(f.label)} \u2014 ${f.desc}`);
4192
+ ${import_chalk30.default.bold(f.label)} \u2014 ${f.desc}`);
4153
4193
  loginFirst(`use ${f.label.toLowerCase()}`);
4154
4194
  }
4155
4195
  }
4156
4196
  }
4157
4197
  async function navigator(proj2, cfg, opts) {
4158
4198
  const { default: inquirer3 } = await import("inquirer");
4159
- console.log(import_chalk29.default.bold(`
4199
+ console.log(import_chalk30.default.bold(`
4160
4200
  ${proj2.projectName} v${proj2.apiVersion} \u2014 configuration
4161
4201
  `));
4162
- console.log(import_chalk29.default.dim("Tip: every change is one API call \u2014 add --verbose to see the curl equivalent.\n"));
4202
+ console.log(import_chalk30.default.dim("Tip: every change is one API call \u2014 add --verbose to see the curl equivalent.\n"));
4163
4203
  let blob = cfg;
4164
4204
  for (; ; ) {
4165
4205
  const { pick: pick2 } = await inquirer3.prompt([{
@@ -4168,10 +4208,10 @@ ${proj2.projectName} v${proj2.apiVersion} \u2014 configuration
4168
4208
  message: "Where to?",
4169
4209
  pageSize: 20,
4170
4210
  choices: [
4171
- new inquirer3.Separator(import_chalk29.default.bold("\u2014 Settings \u2014")),
4211
+ new inquirer3.Separator(import_chalk30.default.bold("\u2014 Settings \u2014")),
4172
4212
  ...SETTING_GROUPS.map((g) => ({ name: g, value: { kind: "settings", g } })),
4173
- new inquirer3.Separator(import_chalk29.default.bold("\u2014 Features \u2014")),
4174
- ...FEATURES.map((f) => ({ name: `${f.label} ${import_chalk29.default.dim(f.desc)}`, value: { kind: f.go } })),
4213
+ new inquirer3.Separator(import_chalk30.default.bold("\u2014 Features \u2014")),
4214
+ ...FEATURES.map((f) => ({ name: `${f.label} ${import_chalk30.default.dim(f.desc)}`, value: { kind: f.go } })),
4175
4215
  new inquirer3.Separator(),
4176
4216
  { name: "Show all settings", value: { kind: "list" } },
4177
4217
  { name: "Exit", value: { kind: "exit" } }
@@ -4211,7 +4251,7 @@ ${proj2.projectName} v${proj2.apiVersion} \u2014 configuration
4211
4251
  }
4212
4252
  }
4213
4253
  } catch (err) {
4214
- console.error(import_chalk29.default.red(` ${err instanceof Error ? err.message : String(err)}`));
4254
+ console.error(import_chalk30.default.red(` ${err instanceof Error ? err.message : String(err)}`));
4215
4255
  }
4216
4256
  }
4217
4257
  }
@@ -4225,7 +4265,7 @@ async function settingsGroup(proj2, cfg, group) {
4225
4265
  message: group + ":",
4226
4266
  pageSize: 16,
4227
4267
  choices: [
4228
- ...items.map((s2) => ({ name: `${s2.label.padEnd(30)} ${show(readSetting(s2, cfg))} ${import_chalk29.default.dim(s2.desc)}`, value: s2 })),
4268
+ ...items.map((s2) => ({ name: `${s2.label.padEnd(30)} ${show(readSetting(s2, cfg))} ${import_chalk30.default.dim(s2.desc)}`, value: s2 })),
4229
4269
  new inquirer3.Separator(),
4230
4270
  { name: "\u2190 Back", value: null }
4231
4271
  ]
@@ -4243,7 +4283,7 @@ async function settingsGroup(proj2, cfg, group) {
4243
4283
  } else if (s.type === "number") {
4244
4284
  const { v } = await inquirer3.prompt([{ type: "input", name: "v", message: `${s.label} (number):`, default: readSetting(s, cfg) }]);
4245
4285
  if (v === "" || Number.isNaN(Number(v))) {
4246
- console.log(import_chalk29.default.yellow(" Not a number \u2014 unchanged."));
4286
+ console.log(import_chalk30.default.yellow(" Not a number \u2014 unchanged."));
4247
4287
  continue;
4248
4288
  }
4249
4289
  value = Number(v);
@@ -4324,7 +4364,7 @@ async function buildCondition(phase) {
4324
4364
  const items = [];
4325
4365
  for (; ; ) {
4326
4366
  const a = await inquirer3.prompt([
4327
- { type: "input", name: "source", message: `Condition field ${import_chalk29.default.dim(srcHint)}:`, validate: (s) => !!s || "required" },
4367
+ { type: "input", name: "source", message: `Condition field ${import_chalk30.default.dim(srcHint)}:`, validate: (s) => !!s || "required" },
4328
4368
  { type: "list", name: "operator", message: "Operator:", choices: [
4329
4369
  "eq",
4330
4370
  "neq",
@@ -4355,7 +4395,7 @@ async function buildCondition(phase) {
4355
4395
  function showCondition(cond) {
4356
4396
  if (!Array.isArray(cond) || !cond.length) return "";
4357
4397
  const s = cond.map((c) => `${c.source} ${c.operator}${c.value !== void 0 ? ` "${c.value}"` : ""}${c.logicOp ? ` ${c.logicOp}` : ""}`).join(" ");
4358
- return import_chalk29.default.dim(` when ${s}`);
4398
+ return import_chalk30.default.dim(` when ${s}`);
4359
4399
  }
4360
4400
  async function transformsMenu(proj2) {
4361
4401
  const { default: inquirer3 } = await import("inquirer");
@@ -4364,12 +4404,12 @@ async function transformsMenu(proj2) {
4364
4404
  const out = await admin({ method: "GET", path: base, summary: "List transform rules" });
4365
4405
  const rules = out?.rules ?? [];
4366
4406
  console.log();
4367
- if (!rules.length) console.log(import_chalk29.default.dim(" No transform rules yet."));
4407
+ if (!rules.length) console.log(import_chalk30.default.dim(" No transform rules yet."));
4368
4408
  for (const r of rules) {
4369
4409
  const a = r.action ?? {};
4370
4410
  const fns = [...a.source_fns ?? [], ...a.dest_fns ?? []].map((f) => f.fn);
4371
- const what = a.type === "hardcode" ? `${a.destination} = "${a.value}"` : a.type === "remove" ? `remove ${a.field}` : `${a.source} \u2192 ${a.destination}${a.lookup ? " (mapped)" : ""}${fns.length ? import_chalk29.default.dim(` via ${fns.join("\u2192")}`) : ""}`;
4372
- console.log(` ${r.enabled ? import_chalk29.default.green("\u25CF") : import_chalk29.default.dim("\u25CB")} ${import_chalk29.default.bold(r.name)} ${import_chalk29.default.dim(`[${r.phase ?? "request"}]`)} ${what}${showCondition(r.condition)}`);
4411
+ const what = a.type === "hardcode" ? `${a.destination} = "${a.value}"` : a.type === "remove" ? `remove ${a.field}` : `${a.source} \u2192 ${a.destination}${a.lookup ? " (mapped)" : ""}${fns.length ? import_chalk30.default.dim(` via ${fns.join("\u2192")}`) : ""}`;
4412
+ console.log(` ${r.enabled ? import_chalk30.default.green("\u25CF") : import_chalk30.default.dim("\u25CB")} ${import_chalk30.default.bold(r.name)} ${import_chalk30.default.dim(`[${r.phase ?? "request"}]`)} ${what}${showCondition(r.condition)}`);
4373
4413
  }
4374
4414
  const { act } = await inquirer3.prompt([{
4375
4415
  type: "list",
@@ -4381,7 +4421,7 @@ async function transformsMenu(proj2) {
4381
4421
  { name: "Enable/disable a rule", value: "toggle" },
4382
4422
  { name: "Delete a rule", value: "delete" }
4383
4423
  ] : [],
4384
- { name: import_chalk29.default.dim("Add from raw JSON (grouped conditions, lookup tables, \u2026)"), value: "raw" },
4424
+ { name: import_chalk30.default.dim("Add from raw JSON (grouped conditions, lookup tables, \u2026)"), value: "raw" },
4385
4425
  { name: "\u2190 Back", value: "back" }
4386
4426
  ]
4387
4427
  }]);
@@ -4394,11 +4434,11 @@ async function transformsMenu(proj2) {
4394
4434
  }]);
4395
4435
  const body = parseValue(raw);
4396
4436
  if (!body || typeof body !== "object" || Array.isArray(body)) {
4397
- console.log(import_chalk29.default.yellow(" Not a JSON object \u2014 skipped."));
4437
+ console.log(import_chalk30.default.yellow(" Not a JSON object \u2014 skipped."));
4398
4438
  continue;
4399
4439
  }
4400
4440
  await admin({ method: "POST", path: base, body, summary: "Create transform rule (raw JSON)" });
4401
- console.log(import_chalk29.default.green(" Rule created."));
4441
+ console.log(import_chalk30.default.green(" Rule created."));
4402
4442
  continue;
4403
4443
  }
4404
4444
  if (act === "add") {
@@ -4414,7 +4454,7 @@ async function transformsMenu(proj2) {
4414
4454
  { name: "Remove a field", value: "remove" }
4415
4455
  ] }
4416
4456
  ]);
4417
- const fieldHint = import_chalk29.default.dim("(e.g. header:x-api-version, param:limit, bodyvar:user.id)");
4457
+ const fieldHint = import_chalk30.default.dim("(e.g. header:x-api-version, param:limit, bodyvar:user.id)");
4418
4458
  let action2;
4419
4459
  if (ans.kind === "hardcode") {
4420
4460
  const a = await inquirer3.prompt([
@@ -4461,16 +4501,16 @@ async function transformsMenu(proj2) {
4461
4501
  type: "list",
4462
4502
  name: "rule",
4463
4503
  message: act === "toggle" ? "Which rule?" : "Delete which rule?",
4464
- choices: [...rules.map((r) => ({ name: `${r.name} ${import_chalk29.default.dim(`[${r.phase ?? "request"}]`)}`, value: r })), { name: "\u2190 Back", value: null }]
4504
+ choices: [...rules.map((r) => ({ name: `${r.name} ${import_chalk30.default.dim(`[${r.phase ?? "request"}]`)}`, value: r })), { name: "\u2190 Back", value: null }]
4465
4505
  }]);
4466
4506
  if (!rule) continue;
4467
4507
  if (act === "toggle") {
4468
4508
  const flipped = { ...rule, enabled: rule.enabled === false };
4469
4509
  await admin({ method: "PUT", path: `${base}/${rule.id}`, body: flipped, summary: `${flipped.enabled ? "Enable" : "Disable"} transform "${rule.name}"` });
4470
- console.log(import_chalk29.default.green(` ${rule.name} \u2192 ${flipped.enabled ? "enabled" : "disabled"}`));
4510
+ console.log(import_chalk30.default.green(` ${rule.name} \u2192 ${flipped.enabled ? "enabled" : "disabled"}`));
4471
4511
  } else {
4472
4512
  await admin({ method: "DELETE", path: `${base}/${rule.id}`, summary: `Delete transform "${rule.name}"` });
4473
- console.log(import_chalk29.default.green(` ${rule.name} deleted.`));
4513
+ console.log(import_chalk30.default.green(` ${rule.name} deleted.`));
4474
4514
  }
4475
4515
  }
4476
4516
  }
@@ -4482,9 +4522,9 @@ async function mappingsMenu(proj2) {
4482
4522
  const out = await admin({ method: "GET", path: base, summary: "List mapping tables" });
4483
4523
  const tables = out?.mappings ?? out?.tables ?? [];
4484
4524
  console.log();
4485
- if (!tables.length) console.log(import_chalk29.default.dim(" No mapping tables yet."));
4525
+ if (!tables.length) console.log(import_chalk30.default.dim(" No mapping tables yet."));
4486
4526
  for (const t of tables) {
4487
- console.log(` ${import_chalk29.default.bold(t.name)} ${import_chalk29.default.dim(`${t.entries?.length ?? "?"} entries${t.hide_map_values ? ", hidden" : ""}${t.encrypt_values ? ", encrypted" : ""}`)}`);
4527
+ console.log(` ${import_chalk30.default.bold(t.name)} ${import_chalk30.default.dim(`${t.entries?.length ?? "?"} entries${t.hide_map_values ? ", hidden" : ""}${t.encrypt_values ? ", encrypted" : ""}`)}`);
4488
4528
  }
4489
4529
  const { act } = await inquirer3.prompt([{
4490
4530
  type: "list",
@@ -4504,11 +4544,11 @@ async function mappingsMenu(proj2) {
4504
4544
  ]);
4505
4545
  const entries2 = parseValue(a.entries);
4506
4546
  if (!Array.isArray(entries2)) {
4507
- console.log(import_chalk29.default.yellow(" Entries must be a JSON array \u2014 not created."));
4547
+ console.log(import_chalk30.default.yellow(" Entries must be a JSON array \u2014 not created."));
4508
4548
  continue;
4509
4549
  }
4510
4550
  await admin({ method: "POST", path: base, body: { name: a.name, entries: entries2 }, summary: `Create mapping table "${a.name}"` });
4511
- console.log(import_chalk29.default.green(` Table "${a.name}" created.`));
4551
+ console.log(import_chalk30.default.green(` Table "${a.name}" created.`));
4512
4552
  } else {
4513
4553
  const { table } = await inquirer3.prompt([{
4514
4554
  type: "list",
@@ -4518,7 +4558,7 @@ async function mappingsMenu(proj2) {
4518
4558
  }]);
4519
4559
  if (!table) continue;
4520
4560
  await admin({ method: "DELETE", path: `${base}/${table.id}`, summary: `Delete mapping table "${table.name}"` });
4521
- console.log(import_chalk29.default.green(` ${table.name} deleted.`));
4561
+ console.log(import_chalk30.default.green(` ${table.name} deleted.`));
4522
4562
  }
4523
4563
  }
4524
4564
  }
@@ -4529,14 +4569,14 @@ async function tenantsMenu(proj2, opts) {
4529
4569
  const out = await admin({ method: "GET", path: base, summary: "List attached tenants" });
4530
4570
  const tenants = out?.tenants ?? [];
4531
4571
  console.log();
4532
- if (!tenants.length) console.log(import_chalk29.default.dim(" No tenants attached (consumers use the default tenant)."));
4533
- for (const t of tenants) console.log(` ${import_chalk29.default.bold(t.tenant_name ?? t.name)} ${import_chalk29.default.dim(t.display_name ?? "")}`);
4572
+ if (!tenants.length) console.log(import_chalk30.default.dim(" No tenants attached (consumers use the default tenant)."));
4573
+ for (const t of tenants) console.log(` ${import_chalk30.default.bold(t.tenant_name ?? t.name)} ${import_chalk30.default.dim(t.display_name ?? "")}`);
4534
4574
  const { act } = await inquirer3.prompt([{
4535
4575
  type: "list",
4536
4576
  name: "act",
4537
4577
  message: "Tenants:",
4538
4578
  choices: [
4539
- { name: `Manage a tenant\u2026 ${import_chalk29.default.dim("settings, login app clients, providers, issuers \u2014 affects EVERY proxy the tenant serves")}`, value: "manage" },
4579
+ { name: `Manage a tenant\u2026 ${import_chalk30.default.dim("settings, login app clients, providers, issuers \u2014 affects EVERY proxy the tenant serves")}`, value: "manage" },
4540
4580
  { name: "Attach a tenant to this project", value: "attach" },
4541
4581
  ...tenants.length ? [{ name: "Detach a tenant from this project", value: "detach" }] : [],
4542
4582
  { name: "\u2190 Back", value: "back" }
@@ -4559,7 +4599,7 @@ async function tenantsMenu(proj2, opts) {
4559
4599
  }]);
4560
4600
  if (!t) continue;
4561
4601
  await admin({ method: "DELETE", path: `${base}/${encodeURIComponent(t.tenant_name ?? t.name)}`, summary: `Detach tenant ${t.tenant_name ?? t.name}` });
4562
- console.log(import_chalk29.default.green(` Detached ${t.tenant_name ?? t.name}.`));
4602
+ console.log(import_chalk30.default.green(` Detached ${t.tenant_name ?? t.name}.`));
4563
4603
  }
4564
4604
  }
4565
4605
  }
@@ -4602,7 +4642,7 @@ async function specMenu(proj2, opts) {
4602
4642
  choices: [
4603
4643
  { name: "Print the stored spec", value: "get" },
4604
4644
  { name: "Refresh the spec from its source", value: "refresh" },
4605
- { name: import_chalk29.default.dim("Build the spec by chatting over real traffic \u2192 agent"), value: "agent" },
4645
+ { name: import_chalk30.default.dim("Build the spec by chatting over real traffic \u2192 agent"), value: "agent" },
4606
4646
  { name: "\u2190 Back", value: "back" }
4607
4647
  ]
4608
4648
  }]);
@@ -4610,7 +4650,7 @@ async function specMenu(proj2, opts) {
4610
4650
  if (act === "get") await runSpecGet(proj2.projectName, { team: opts.team, apiversion: proj2.apiVersion });
4611
4651
  else if (act === "refresh") {
4612
4652
  await admin({ method: "POST", path: `/projects/${proj2.projectId}/${proj2.apiVersion}/refresh-spec`, summary: "Refresh spec from source" });
4613
- console.log(import_chalk29.default.green(" Spec refresh triggered."));
4653
+ console.log(import_chalk30.default.green(" Spec refresh triggered."));
4614
4654
  } else await runOpenapi(proj2.projectName, proj2.apiVersion);
4615
4655
  }
4616
4656
  async function agentsMenu(proj2, opts) {
@@ -4635,7 +4675,7 @@ async function agentsMenu(proj2, opts) {
4635
4675
  }
4636
4676
 
4637
4677
  // src/commands/key.ts
4638
- var import_chalk30 = __toESM(require("chalk"));
4678
+ var import_chalk31 = __toESM(require("chalk"));
4639
4679
  var import_ora15 = __toESM(require("ora"));
4640
4680
  init_admin();
4641
4681
  async function runApikeysMenu(opts) {
@@ -4664,11 +4704,11 @@ async function runKeyList(opts) {
4664
4704
  return;
4665
4705
  }
4666
4706
  if (!keys.length) {
4667
- console.log(import_chalk30.default.yellow("No developer keys."));
4707
+ console.log(import_chalk31.default.yellow("No developer keys."));
4668
4708
  return;
4669
4709
  }
4670
4710
  for (const k of keys) {
4671
- console.log(` ${import_chalk30.default.bold(k.key_id ?? k.id)} ${import_chalk30.default.dim(k.description ?? "")} ${import_chalk30.default.dim(k.expires_at ?? "no expiry")}`);
4711
+ console.log(` ${import_chalk31.default.bold(k.key_id ?? k.id)} ${import_chalk31.default.dim(k.description ?? "")} ${import_chalk31.default.dim(k.expires_at ?? "no expiry")}`);
4672
4712
  }
4673
4713
  }
4674
4714
  async function runKeyMint(opts) {
@@ -4689,9 +4729,9 @@ async function runKeyMint(opts) {
4689
4729
  console.log(JSON.stringify(out));
4690
4730
  return;
4691
4731
  }
4692
- console.log(` ${import_chalk30.default.bold("key_id")}: ${out?.key_id}`);
4693
- console.log(` ${import_chalk30.default.bold("key")}: ${import_chalk30.default.green(out?.key)} ${import_chalk30.default.dim("(shown once \u2014 store it now)")}`);
4694
- if (out?.expires_at) console.log(` ${import_chalk30.default.dim("expires:")} ${out.expires_at}`);
4732
+ console.log(` ${import_chalk31.default.bold("key_id")}: ${out?.key_id}`);
4733
+ console.log(` ${import_chalk31.default.bold("key")}: ${import_chalk31.default.green(out?.key)} ${import_chalk31.default.dim("(shown once \u2014 store it now)")}`);
4734
+ if (out?.expires_at) console.log(` ${import_chalk31.default.dim("expires:")} ${out.expires_at}`);
4695
4735
  } catch (err) {
4696
4736
  spinner.fail("Mint failed.");
4697
4737
  throw err;
@@ -4714,10 +4754,10 @@ async function runKeyRevoke(keyId, opts) {
4714
4754
  }
4715
4755
 
4716
4756
  // src/commands/apichat.ts
4717
- var fs8 = __toESM(require("fs"));
4718
- var path5 = __toESM(require("path"));
4757
+ var fs9 = __toESM(require("fs"));
4758
+ var path6 = __toESM(require("path"));
4719
4759
  var crypto2 = __toESM(require("crypto"));
4720
- var import_chalk32 = __toESM(require("chalk"));
4760
+ var import_chalk33 = __toESM(require("chalk"));
4721
4761
  var import_ora16 = __toESM(require("ora"));
4722
4762
  var import_yaml = require("yaml");
4723
4763
  init_auth();
@@ -4726,12 +4766,12 @@ init_api();
4726
4766
  init_admin();
4727
4767
 
4728
4768
  // src/commands/llm.ts
4729
- var fs7 = __toESM(require("fs"));
4730
- var path4 = __toESM(require("path"));
4731
- var import_chalk31 = __toESM(require("chalk"));
4769
+ var fs8 = __toESM(require("fs"));
4770
+ var path5 = __toESM(require("path"));
4771
+ var import_chalk32 = __toESM(require("chalk"));
4732
4772
  var import_inquirer2 = __toESM(require("inquirer"));
4733
4773
  init_auth();
4734
- var LLM_PATH = path4.join(getApiblazeDir(), "llm.json");
4774
+ var LLM_PATH = path5.join(getApiblazeDir(), "llm.json");
4735
4775
  function detectProvider(key) {
4736
4776
  const k = key.trim();
4737
4777
  if (k.startsWith("sk-or-")) return "openrouter";
@@ -4742,15 +4782,15 @@ function detectProvider(key) {
4742
4782
  }
4743
4783
  function loadLlmConfig() {
4744
4784
  try {
4745
- return JSON.parse(fs7.readFileSync(LLM_PATH, "utf-8"));
4785
+ return JSON.parse(fs8.readFileSync(LLM_PATH, "utf-8"));
4746
4786
  } catch {
4747
4787
  return null;
4748
4788
  }
4749
4789
  }
4750
4790
  function saveLlmConfig(cfg) {
4751
- fs7.mkdirSync(getApiblazeDir(), { recursive: true });
4752
- fs7.writeFileSync(LLM_PATH, JSON.stringify(cfg, null, 2), "utf-8");
4753
- fs7.chmodSync(LLM_PATH, 384);
4791
+ fs8.mkdirSync(getApiblazeDir(), { recursive: true });
4792
+ fs8.writeFileSync(LLM_PATH, JSON.stringify(cfg, null, 2), "utf-8");
4793
+ fs8.chmodSync(LLM_PATH, 384);
4754
4794
  }
4755
4795
  async function runLlmSetKey(keyArg, opts) {
4756
4796
  let key = keyArg?.trim();
@@ -4772,27 +4812,27 @@ async function runLlmSetKey(keyArg, opts) {
4772
4812
  }
4773
4813
  const existing = loadLlmConfig();
4774
4814
  saveLlmConfig({ key, provider, model: opts.model ?? existing?.model });
4775
- console.log(`${import_chalk31.default.green("\u2713")} Saved ${import_chalk31.default.bold(provider)} key ${maskSecret(key)}`);
4776
- console.log(import_chalk31.default.gray(` Stored locally at ${LLM_PATH} (0600) \u2014 never sent to APIblaze except per chat turn.`));
4777
- if (opts.model) console.log(import_chalk31.default.gray(` Model: ${opts.model}`));
4815
+ console.log(`${import_chalk32.default.green("\u2713")} Saved ${import_chalk32.default.bold(provider)} key ${maskSecret(key)}`);
4816
+ console.log(import_chalk32.default.gray(` Stored locally at ${LLM_PATH} (0600) \u2014 never sent to APIblaze except per chat turn.`));
4817
+ if (opts.model) console.log(import_chalk32.default.gray(` Model: ${opts.model}`));
4778
4818
  }
4779
4819
  async function runLlmShow() {
4780
4820
  const cfg = loadLlmConfig();
4781
4821
  if (!cfg) {
4782
- console.log(import_chalk31.default.gray("No LLM key set. `apiblaze llm set-key sk-...` to add one (optional \u2014 chat works without it)."));
4822
+ console.log(import_chalk32.default.gray("No LLM key set. `apiblaze llm set-key sk-...` to add one (optional \u2014 chat works without it)."));
4783
4823
  return;
4784
4824
  }
4785
- console.log(`Provider: ${import_chalk31.default.bold(cfg.provider)}`);
4825
+ console.log(`Provider: ${import_chalk32.default.bold(cfg.provider)}`);
4786
4826
  console.log(`Key: ${maskSecret(cfg.key)}`);
4787
4827
  if (cfg.model) console.log(`Model: ${cfg.model}`);
4788
- console.log(import_chalk31.default.gray(`Stored at ${LLM_PATH}`));
4828
+ console.log(import_chalk32.default.gray(`Stored at ${LLM_PATH}`));
4789
4829
  }
4790
4830
  async function runLlmClearKey() {
4791
4831
  try {
4792
- fs7.unlinkSync(LLM_PATH);
4793
- console.log(`${import_chalk31.default.green("\u2713")} Removed local LLM key.`);
4832
+ fs8.unlinkSync(LLM_PATH);
4833
+ console.log(`${import_chalk32.default.green("\u2713")} Removed local LLM key.`);
4794
4834
  } catch {
4795
- console.log(import_chalk31.default.gray("No LLM key was set."));
4835
+ console.log(import_chalk32.default.gray("No LLM key was set."));
4796
4836
  }
4797
4837
  }
4798
4838
 
@@ -4800,9 +4840,9 @@ async function runLlmClearKey() {
4800
4840
  init_trace();
4801
4841
  init_types();
4802
4842
  function fail4(message, hint) {
4803
- console.error(import_chalk32.default.red(`
4843
+ console.error(import_chalk33.default.red(`
4804
4844
  Error: ${message}`));
4805
- if (hint) console.error(import_chalk32.default.dim(hint));
4845
+ if (hint) console.error(import_chalk33.default.dim(hint));
4806
4846
  process.exit(1);
4807
4847
  }
4808
4848
  function normalizeName2(raw) {
@@ -4866,7 +4906,7 @@ async function loadSpec(opts) {
4866
4906
  }
4867
4907
  let text;
4868
4908
  try {
4869
- text = fs8.readFileSync(opts.openapispec, "utf-8");
4909
+ text = fs9.readFileSync(opts.openapispec, "utf-8");
4870
4910
  } catch {
4871
4911
  fail4(`Cannot read spec file: ${opts.openapispec}`);
4872
4912
  }
@@ -4950,7 +4990,7 @@ async function resolveTargetAuth(spec2, opts) {
4950
4990
  "Re-run with --force to provision anyway (configure target auth later with `apiblaze config`),\nor use an api_key / bearer / basic scheme."
4951
4991
  );
4952
4992
  }
4953
- if (sawOAuth) console.log(import_chalk32.default.yellow(" --force: skipping OAuth target auth \u2014 configure it later with `apiblaze config`."));
4993
+ if (sawOAuth) console.log(import_chalk33.default.yellow(" --force: skipping OAuth target auth \u2014 configure it later with `apiblaze config`."));
4954
4994
  return null;
4955
4995
  }
4956
4996
  if (candidates.length === 1 && !noneAllowed) return candidates[0];
@@ -5003,13 +5043,13 @@ async function captureTargetSecret(auth, opts) {
5003
5043
  if (!secret) fail4("No credential entered.");
5004
5044
  return secret;
5005
5045
  }
5006
- async function cpPost(anon, path7, body, summary) {
5046
+ async function cpPost(anon, path8, body, summary) {
5007
5047
  if (anon) {
5008
5048
  const cred = loadAnonCred();
5009
5049
  if (!cred) throw new Error("Anonymous workspace credential missing.");
5010
- return cpFetch(cred.cp_key, path7, { method: "POST", body: JSON.stringify(body) });
5050
+ return cpFetch(cred.cp_key, path8, { method: "POST", body: JSON.stringify(body) });
5011
5051
  }
5012
- return admin({ method: "POST", path: path7, body, summary });
5052
+ return admin({ method: "POST", path: path8, body, summary });
5013
5053
  }
5014
5054
  async function provision(spec2, target, opts) {
5015
5055
  const loggedIn = !!loadCredentials();
@@ -5144,7 +5184,7 @@ async function uploadSpec(p, specText, opts) {
5144
5184
  throw err;
5145
5185
  }
5146
5186
  if (out && out.reused === true) {
5147
- console.log(import_chalk32.default.dim(" Spec unchanged since the last provision \u2014 reusing the existing configuration."));
5187
+ console.log(import_chalk33.default.dim(" Spec unchanged since the last provision \u2014 reusing the existing configuration."));
5148
5188
  } else if (out && out.changed === true && out.previous_spec_hash) {
5149
5189
  const interactive = !!process.stdin.isTTY && !opts.yes;
5150
5190
  if (interactive) {
@@ -5152,7 +5192,7 @@ async function uploadSpec(p, specText, opts) {
5152
5192
  const { go } = await inquirer3.prompt([
5153
5193
  { type: "confirm", name: "go", message: "The spec changed since the last provision \u2014 re-publish the MCP catalogue?", default: true }
5154
5194
  ]);
5155
- if (!go) console.log(import_chalk32.default.dim(" Keeping the existing MCP catalogue."));
5195
+ if (!go) console.log(import_chalk33.default.dim(" Keeping the existing MCP catalogue."));
5156
5196
  }
5157
5197
  }
5158
5198
  }
@@ -5186,19 +5226,24 @@ var CLIENT_ROUND_CAP = 12;
5186
5226
  function chatUrl(p) {
5187
5227
  return `https://${p.mcpHost}/${p.version}/${p.environment}/runtime-chat`;
5188
5228
  }
5189
- function renderToolEvents(events) {
5229
+ function renderToolEvents(events, dpKey) {
5190
5230
  for (const e of events ?? []) {
5191
5231
  const ok = typeof e.status === "number" ? e.status < 400 : String(e.status).toLowerCase() === "ok";
5192
- const mark = ok ? import_chalk32.default.green("\u2713") : import_chalk32.default.red("\u2717");
5193
- console.log(` ${mark} ${import_chalk32.default.cyan(e.name)} ${import_chalk32.default.dim(`(${e.status}, ${e.ms}ms)`)}`);
5232
+ const mark = ok ? import_chalk33.default.green("\u2713") : import_chalk33.default.red("\u2717");
5233
+ console.log(` ${mark} ${import_chalk33.default.cyan(e.name)} ${import_chalk33.default.dim(`(${e.status}, ${e.ms}ms)`)}`);
5234
+ if (isVerbose() && e.method && e.url) {
5235
+ const auth = dpKey ? ` \\
5236
+ -H 'X-API-Key: ${maskSecret(dpKey)}'` : "";
5237
+ console.log(import_chalk33.default.dim(` curl -sS -X ${e.method} '${e.url}'${auth}`));
5238
+ }
5194
5239
  }
5195
5240
  }
5196
5241
  function billingLine(billing) {
5197
5242
  if (!billing || typeof billing.cents !== "number") return null;
5198
5243
  const usd = (billing.cents / 100).toFixed(Math.abs(billing.cents - Math.round(billing.cents)) < 1e-9 ? 2 : 4);
5199
- let line = import_chalk32.default.magenta(` \u{1F4B3} $${usd}`) + import_chalk32.default.dim(billing.model ? ` \xB7 ${billing.model}` : "");
5244
+ let line = import_chalk33.default.magenta(` \u{1F4B3} $${usd}`) + import_chalk33.default.dim(billing.model ? ` \xB7 ${billing.model}` : "");
5200
5245
  if (typeof billing.credits_remaining === "number") {
5201
- line += import_chalk32.default.dim(` \xB7 balance $${(billing.credits_remaining / 100).toFixed(2)}`);
5246
+ line += import_chalk33.default.dim(` \xB7 balance $${(billing.credits_remaining / 100).toFixed(2)}`);
5202
5247
  }
5203
5248
  return line;
5204
5249
  }
@@ -5207,27 +5252,18 @@ function freeBudgetWarning(billing, anon) {
5207
5252
  const perTurn = Math.max(billing.cents || 0, 0.02);
5208
5253
  const left = Math.floor(billing.free_remaining_cents / perTurn);
5209
5254
  if (left > 8) return null;
5210
- if (left <= 0) return import_chalk32.default.yellow(" Free messages used up \u2014 `npx apiblaze login` (free) to keep chatting.");
5211
- return import_chalk32.default.yellow(` \u26A0 About ${left} free message${left === 1 ? "" : "s"} left \u2014 \`npx apiblaze login\` (free) for more.`);
5255
+ if (left <= 0) return import_chalk33.default.yellow(" Free messages used up \u2014 `npx apiblaze login` (free) to keep chatting.");
5256
+ return import_chalk33.default.yellow(` \u26A0 About ${left} free message${left === 1 ? "" : "s"} left \u2014 \`npx apiblaze login\` (free) for more.`);
5212
5257
  }
5213
5258
  function printAssistant(delta) {
5214
5259
  for (let i = delta.length - 1; i >= 0; i--) {
5215
5260
  const m = delta[i];
5216
5261
  if (m && m.role === "assistant" && typeof m.content === "string" && m.content.trim()) {
5217
- console.log("\n" + import_chalk32.default.green("assistant \u203A ") + m.content + "\n");
5262
+ console.log("\n" + import_chalk33.default.green("assistant \u203A ") + m.content + "\n");
5218
5263
  return;
5219
5264
  }
5220
5265
  }
5221
5266
  }
5222
- function verboseTrace(p, hasByo) {
5223
- if (!isVerbose()) return;
5224
- console.log(import_chalk32.default.dim("\n" + "\u2500".repeat(64)));
5225
- console.log(import_chalk32.default.bold("--verbose: this turn POSTed to the data-plane MCP host"));
5226
- console.log(import_chalk32.default.green(` curl -sS -X POST ${chatUrl(p)} \\`));
5227
- console.log(import_chalk32.default.green(` -H "X-API-Key: ${maskSecret(p.dpKey)}" \\`));
5228
- console.log(import_chalk32.default.green(" -H 'Content-Type: application/json' \\"));
5229
- console.log(import_chalk32.default.green(` -d '{"turn_id":"\u2026","messages":[\u2026],"environment":"${p.environment}"${hasByo ? ',"llm_api_key":"***","llm_provider":"\u2026"' : ""}}'`));
5230
- }
5231
5267
  async function replTurn(p, messages, userText) {
5232
5268
  messages.push({ role: "user", content: userText });
5233
5269
  const llm2 = loadLlmConfig();
@@ -5249,7 +5285,7 @@ async function replTurn(p, messages, userText) {
5249
5285
  });
5250
5286
  } catch (err) {
5251
5287
  spinner.fail("Network error.");
5252
- console.log(import_chalk32.default.red(` Could not reach ${p.mcpHost}: ${err instanceof Error ? err.message : String(err)}`));
5288
+ console.log(import_chalk33.default.red(` Could not reach ${p.mcpHost}: ${err instanceof Error ? err.message : String(err)}`));
5253
5289
  return;
5254
5290
  }
5255
5291
  let data = null;
@@ -5267,16 +5303,16 @@ async function replTurn(p, messages, userText) {
5267
5303
  return;
5268
5304
  }
5269
5305
  if (res.status === 401) {
5270
- console.log(import_chalk32.default.red(" The proxy rejected the API key (401). The key may have been revoked; re-run `apiblaze apichat` to re-provision."));
5306
+ console.log(import_chalk33.default.red(" The proxy rejected the API key (401). The key may have been revoked; re-run `apiblaze apichat` to re-provision."));
5271
5307
  return;
5272
5308
  }
5273
5309
  if (!res.ok || !data) {
5274
5310
  const err = data && data.error || `HTTP ${res.status}`;
5275
- console.log(import_chalk32.default.red(` Chat error: ${err}`));
5311
+ console.log(import_chalk33.default.red(` Chat error: ${err}`));
5276
5312
  return;
5277
5313
  }
5278
5314
  if (Array.isArray(data.delta)) {
5279
- renderToolEvents(data.tool_events);
5315
+ renderToolEvents(data.tool_events, p.dpKey);
5280
5316
  for (const m of data.delta) messages.push(m);
5281
5317
  printAssistant(data.delta);
5282
5318
  }
@@ -5284,39 +5320,38 @@ async function replTurn(p, messages, userText) {
5284
5320
  if (bl) console.log(bl);
5285
5321
  const warn = freeBudgetWarning(data.billing, p.anon);
5286
5322
  if (warn) console.log(warn);
5287
- verboseTrace(p, !!llm2);
5288
5323
  if (!data.continue) return;
5289
5324
  }
5290
- console.log(import_chalk32.default.dim(" (stopped after several tool rounds \u2014 ask again to continue)"));
5325
+ console.log(import_chalk33.default.dim(" (stopped after several tool rounds \u2014 ask again to continue)"));
5291
5326
  }
5292
5327
  function renderUpsell(p, upsell) {
5293
5328
  const loggedIn = !!loadCredentials();
5294
- console.log("\n" + import_chalk32.default.yellow(` ${upsell.message || "This turn is not available right now."}`));
5329
+ console.log("\n" + import_chalk33.default.yellow(` ${upsell.message || "This turn is not available right now."}`));
5295
5330
  if (upsell.reason === "INSUFFICIENT" || upsell.reason === "BREAKER" || upsell.reason === "CAPPED" || upsell.reason === "PAUSED") {
5296
5331
  if (!loggedIn) {
5297
- console.log(import_chalk32.default.dim(" Options: `/login` for free login credit and higher limits, or `apiblaze llm set-key` to bring your own model key."));
5332
+ console.log(import_chalk33.default.dim(" Options: `/login` for free login credit and higher limits, or `apiblaze llm set-key` to bring your own model key."));
5298
5333
  } else {
5299
- console.log(import_chalk32.default.dim(" Options: top up your wallet, or `apiblaze llm set-key` to bring your own model key (bypasses platform limits)."));
5334
+ console.log(import_chalk33.default.dim(" Options: top up your wallet, or `apiblaze llm set-key` to bring your own model key (bypasses platform limits)."));
5300
5335
  }
5301
5336
  } else if (upsell.reason === "INFLIGHT") {
5302
- console.log(import_chalk32.default.dim(" Another turn is still in flight \u2014 wait a moment and try again."));
5337
+ console.log(import_chalk33.default.dim(" Another turn is still in flight \u2014 wait a moment and try again."));
5303
5338
  }
5304
5339
  console.log();
5305
5340
  }
5306
- var apichatsPath = () => path5.join(getApiblazeDir(), "apichats.json");
5341
+ var apichatsPath = () => path6.join(getApiblazeDir(), "apichats.json");
5307
5342
  function loadApichats() {
5308
5343
  try {
5309
- const list = JSON.parse(fs8.readFileSync(apichatsPath(), "utf-8"));
5344
+ const list = JSON.parse(fs9.readFileSync(apichatsPath(), "utf-8"));
5310
5345
  return Array.isArray(list) ? list : [];
5311
5346
  } catch {
5312
5347
  return [];
5313
5348
  }
5314
5349
  }
5315
5350
  function writeApichats(list) {
5316
- fs8.mkdirSync(getApiblazeDir(), { recursive: true });
5317
- fs8.writeFileSync(apichatsPath(), JSON.stringify(list, null, 2), "utf-8");
5351
+ fs9.mkdirSync(getApiblazeDir(), { recursive: true });
5352
+ fs9.writeFileSync(apichatsPath(), JSON.stringify(list, null, 2), "utf-8");
5318
5353
  try {
5319
- fs8.chmodSync(apichatsPath(), 384);
5354
+ fs9.chmodSync(apichatsPath(), 384);
5320
5355
  } catch {
5321
5356
  }
5322
5357
  }
@@ -5348,21 +5383,89 @@ function claimApichat(p, ownerUserId) {
5348
5383
  list[i].updatedAt = (/* @__PURE__ */ new Date()).toISOString();
5349
5384
  writeApichats(list);
5350
5385
  }
5386
+ async function mintDurableProxyKey(teamId, tenant2) {
5387
+ const out = await admin({
5388
+ method: "POST",
5389
+ path: `/teams/${encodeURIComponent(teamId)}/tenants/${encodeURIComponent(tenant2)}/admin/keys`,
5390
+ body: { key_type: "apiblaze-consumer-admin", environment: "prod" },
5391
+ // no expiry → durable
5392
+ summary: "Mint a durable data-plane key for apichat"
5393
+ });
5394
+ if (!out?.key) throw new Error("key mint returned no key");
5395
+ return out.key;
5396
+ }
5397
+ async function openServerProxy(project) {
5398
+ const version2 = project.apiVersion || "1.0.0";
5399
+ const environment = "prod";
5400
+ const mcpHost = `${project.projectId}.mcp.abz.run`;
5401
+ const tenant2 = project.tenant || project.projectId;
5402
+ const me = loadCredentials()?.apiblazeUserId;
5403
+ const prior = loadApichats().find((a) => a.projectId === project.projectId && a.dpKey);
5404
+ let dpKey = prior?.dpKey;
5405
+ if (!dpKey) {
5406
+ console.log(import_chalk33.default.dim(` Minting an API key for tenant ${import_chalk33.default.bold(tenant2)} to query project ${import_chalk33.default.bold(project.projectName)}\u2026`));
5407
+ dpKey = await mintDurableProxyKey(project.teamId, tenant2);
5408
+ console.log(` ${import_chalk33.default.green("\u2714")} API key: ${import_chalk33.default.dim(maskSecret(dpKey))}`);
5409
+ }
5410
+ const p = {
5411
+ projectId: project.projectId,
5412
+ version: version2,
5413
+ environment,
5414
+ dpKey,
5415
+ mcpHost,
5416
+ proxyUrl: `https://${project.projectId}.abz.run/${version2}/${environment}`,
5417
+ anon: false
5418
+ };
5419
+ const spinner = (0, import_ora16.default)("Preparing the chat\u2026").start();
5420
+ try {
5421
+ const raw = await admin({
5422
+ method: "GET",
5423
+ path: `/projects/${project.projectId}/${version2}/openapi`,
5424
+ summary: "Fetch OpenAPI spec"
5425
+ }).catch(() => null);
5426
+ const spec2 = raw && (raw.spec ?? raw);
5427
+ spinner.stop();
5428
+ if (spec2 && (spec2.paths || spec2.openapi)) {
5429
+ await publishMcp(p, spec2);
5430
+ } else {
5431
+ console.log(import_chalk33.default.yellow(" This proxy has no OpenAPI spec yet \u2014 chat will have no tools. Build one with `apiblaze agent openapi`."));
5432
+ }
5433
+ } catch (err) {
5434
+ spinner.fail("Could not open the proxy.");
5435
+ throw err;
5436
+ }
5437
+ upsertApichat({
5438
+ name: project.projectId,
5439
+ target: project.projectName,
5440
+ projectId: project.projectId,
5441
+ version: version2,
5442
+ environment,
5443
+ mcpHost,
5444
+ dpKey,
5445
+ anon: false,
5446
+ ownerUserId: me,
5447
+ createdAt: prior?.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
5448
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
5449
+ messages: prior?.messages
5450
+ // preserve any earlier transcript; this session starts fresh
5451
+ });
5452
+ return { p, messages: [] };
5453
+ }
5351
5454
  function discoverLocalSpecs() {
5352
5455
  const cwd = process.cwd();
5353
5456
  const known = ["openapi.yaml", "openapi.yml", "openapi.json", "swagger.yaml", "swagger.yml", "swagger.json", "api.yaml", "api.yml", "api.json"];
5354
5457
  const found = [];
5355
5458
  for (const n of known) {
5356
5459
  try {
5357
- if (fs8.statSync(path5.join(cwd, n)).isFile()) found.push(n);
5460
+ if (fs9.statSync(path6.join(cwd, n)).isFile()) found.push(n);
5358
5461
  } catch {
5359
5462
  }
5360
5463
  }
5361
5464
  try {
5362
- const files = fs8.readdirSync(cwd).filter((f) => /\.(ya?ml|json)$/i.test(f) && !found.includes(f));
5465
+ const files = fs9.readdirSync(cwd).filter((f) => /\.(ya?ml|json)$/i.test(f) && !found.includes(f));
5363
5466
  for (const f of files.slice(0, 60)) {
5364
5467
  try {
5365
- const head = fs8.readFileSync(path5.join(cwd, f), "utf-8").slice(0, 4e3);
5468
+ const head = fs9.readFileSync(path6.join(cwd, f), "utf-8").slice(0, 4e3);
5366
5469
  if (/["']?openapi["']?\s*:/i.test(head) || /["']?swagger["']?\s*:/i.test(head) || /^\s*paths\s*:/im.test(head) || /"paths"\s*:/.test(head)) {
5367
5470
  found.push(f);
5368
5471
  }
@@ -5378,10 +5481,24 @@ async function noArgsMenu(opts) {
5378
5481
  const me = loadCredentials()?.apiblazeUserId;
5379
5482
  const saved = loadApichats().filter((a) => a.anon ? true : a.ownerUserId !== void 0 && a.ownerUserId === me);
5380
5483
  const choices = saved.map((a) => ({
5381
- name: `Chat with ${import_chalk32.default.bold(a.name)} ${import_chalk32.default.dim(`(${a.target})${a.messages && a.messages.length ? ` \xB7 ${a.messages.length} msgs` : ""}`)}`,
5484
+ name: `Chat with ${import_chalk33.default.bold(a.name)} ${import_chalk33.default.dim(`(${a.target})${a.messages && a.messages.length ? ` \xB7 ${a.messages.length} msgs` : ""}`)}`,
5382
5485
  value: { type: "existing", a }
5383
5486
  }));
5384
- choices.push({ name: import_chalk32.default.green("\uFF0B Create a new apichat"), value: { type: "new" } });
5487
+ const creds = loadCredentials();
5488
+ if (creds?.teamId) {
5489
+ const savedIds = new Set(saved.map((a) => a.projectId));
5490
+ try {
5491
+ const proxies = (await getProjects(creds.teamId)).filter((pr) => !savedIds.has(pr.projectId));
5492
+ for (const pr of proxies) {
5493
+ choices.push({
5494
+ name: `Chat with ${import_chalk33.default.bold(pr.projectName)} ${import_chalk33.default.dim(`(v${pr.apiVersion}) \xB7 your proxy`)}`,
5495
+ value: { type: "server", project: pr }
5496
+ });
5497
+ }
5498
+ } catch {
5499
+ }
5500
+ }
5501
+ choices.push({ name: import_chalk33.default.green("\uFF0B Create a new apichat"), value: { type: "new" } });
5385
5502
  const { pick: pick2 } = await inquirer3.prompt([
5386
5503
  { type: "list", name: "pick", message: "What would you like to do?", choices }
5387
5504
  ]);
@@ -5413,6 +5530,9 @@ async function noArgsMenu(opts) {
5413
5530
  };
5414
5531
  return { p, messages };
5415
5532
  }
5533
+ if (pick2.type === "server") {
5534
+ return await openServerProxy(pick2.project);
5535
+ }
5416
5536
  const { source } = await inquirer3.prompt([
5417
5537
  {
5418
5538
  type: "list",
@@ -5450,31 +5570,31 @@ async function noArgsMenu(opts) {
5450
5570
  async function runRepl(p, initialMessages) {
5451
5571
  const { default: inquirer3 } = await import("inquirer");
5452
5572
  const messages = initialMessages && initialMessages.length ? initialMessages.slice() : [];
5453
- console.log("\n" + import_chalk32.default.cyan.bold("Chat with your API") + import_chalk32.default.dim(` \xB7 ${p.mcpHost}`));
5454
- if (messages.length) console.log(import_chalk32.default.dim(` Resumed \u2014 ${messages.length} prior messages.`));
5573
+ console.log("\n" + import_chalk33.default.cyan.bold("Chat with your API") + import_chalk33.default.dim(` \xB7 ${p.mcpHost}`));
5574
+ if (messages.length) console.log(import_chalk33.default.dim(` Resumed \u2014 ${messages.length} prior messages.`));
5455
5575
  const llm2 = loadLlmConfig();
5456
5576
  console.log(
5457
- import_chalk32.default.dim(
5577
+ import_chalk33.default.dim(
5458
5578
  llm2 ? `Using your local ${llm2.provider} key for the model. Type a question, or /exit. /login /claim manage your workspace.` : "Ask a question in plain English. /exit to quit \xB7 /login for credit \xB7 /claim to keep this workspace \xB7 `apiblaze llm set-key` for BYO models."
5459
5579
  )
5460
5580
  );
5461
5581
  for (; ; ) {
5462
- const { input } = await inquirer3.prompt([{ type: "input", name: "input", message: import_chalk32.default.green("you \u203A") }]);
5582
+ const { input } = await inquirer3.prompt([{ type: "input", name: "input", message: import_chalk33.default.green("you \u203A") }]);
5463
5583
  const text = (input ?? "").trim();
5464
5584
  if (!text) continue;
5465
5585
  if (["/exit", "/quit", "exit", "quit", ":q"].includes(text.toLowerCase())) break;
5466
5586
  if (text === "/login") {
5467
5587
  try {
5468
5588
  await runLogin();
5469
- console.log(import_chalk32.default.dim(" Logged in \u2014 history preserved. Keep chatting."));
5589
+ console.log(import_chalk33.default.dim(" Logged in \u2014 history preserved. Keep chatting."));
5470
5590
  } catch (err) {
5471
- console.log(import_chalk32.default.red(` Login failed: ${err instanceof Error ? err.message : String(err)}`));
5591
+ console.log(import_chalk33.default.red(` Login failed: ${err instanceof Error ? err.message : String(err)}`));
5472
5592
  }
5473
5593
  continue;
5474
5594
  }
5475
5595
  if (text === "/claim") {
5476
5596
  if (!loadCredentials()) {
5477
- console.log(import_chalk32.default.yellow(" Log in first: `/login`, then `/claim`."));
5597
+ console.log(import_chalk33.default.yellow(" Log in first: `/login`, then `/claim`."));
5478
5598
  continue;
5479
5599
  }
5480
5600
  try {
@@ -5483,24 +5603,24 @@ async function runRepl(p, initialMessages) {
5483
5603
  p.mcpHost = p.mcpHost.replace(".mcp.tryabz.run", ".mcp.abz.run");
5484
5604
  p.anon = false;
5485
5605
  claimApichat(p, loadCredentials()?.apiblazeUserId);
5486
- console.log(import_chalk32.default.dim(` Workspace claimed \u2014 chat now routes on ${p.mcpHost}. History preserved.`));
5606
+ console.log(import_chalk33.default.dim(` Workspace claimed \u2014 chat now routes on ${p.mcpHost}. History preserved.`));
5487
5607
  }
5488
5608
  } catch (err) {
5489
- console.log(import_chalk32.default.red(` Claim failed: ${err instanceof Error ? err.message : String(err)}`));
5609
+ console.log(import_chalk33.default.red(` Claim failed: ${err instanceof Error ? err.message : String(err)}`));
5490
5610
  }
5491
5611
  continue;
5492
5612
  }
5493
5613
  if (text.startsWith("/")) {
5494
- console.log(import_chalk32.default.dim(" Commands: /login /claim /exit"));
5614
+ console.log(import_chalk33.default.dim(" Commands: /login /claim /exit"));
5495
5615
  continue;
5496
5616
  }
5497
5617
  await replTurn(p, messages, text);
5498
5618
  saveTranscript(p, messages);
5499
5619
  }
5500
- console.log(import_chalk32.default.dim("\nBye."));
5620
+ console.log(import_chalk33.default.dim("\nBye."));
5501
5621
  }
5502
5622
  async function runApichat(opts) {
5503
- console.log(import_chalk32.default.bold("\napichat \u2014 turn any API into a chat\n"));
5623
+ console.log(import_chalk33.default.bold("\napichat \u2014 turn any API into a chat\n"));
5504
5624
  if (!opts.openapispec && !opts.target) {
5505
5625
  if (!process.stdin.isTTY) {
5506
5626
  fail4("No spec source. Pass --openapispec <file|url> or --target <url>.", GENERATOR_HINT);
@@ -5513,7 +5633,7 @@ async function runApichat(opts) {
5513
5633
  }
5514
5634
  const { spec: spec2, sourceUrl } = await loadSpec(opts);
5515
5635
  const target = resolveTarget(spec2, opts, sourceUrl);
5516
- console.log(` ${import_chalk32.default.dim("Target:")} ${import_chalk32.default.bold(target)}`);
5636
+ console.log(` ${import_chalk33.default.dim("Target:")} ${import_chalk33.default.bold(target)}`);
5517
5637
  const auth = await resolveTargetAuth(spec2, opts);
5518
5638
  if (auth && !process.stdin.isTTY && !opts.targetAuthEnv) {
5519
5639
  fail4(
@@ -5522,7 +5642,7 @@ async function runApichat(opts) {
5522
5642
  );
5523
5643
  }
5524
5644
  const p = await provision(spec2, target, opts);
5525
- console.log(` ${import_chalk32.default.dim("Proxy: ")} ${import_chalk32.default.bold(p.proxyUrl || `${p.projectId} v${p.version}`)}`);
5645
+ console.log(` ${import_chalk33.default.dim("Proxy: ")} ${import_chalk33.default.bold(p.proxyUrl || `${p.projectId} v${p.version}`)}`);
5526
5646
  upsertApichat({
5527
5647
  name: p.projectId,
5528
5648
  target,
@@ -5541,22 +5661,22 @@ async function runApichat(opts) {
5541
5661
  const secret = await captureTargetSecret(auth, opts);
5542
5662
  if (secret) await writeTargetAuth(p, auth, secret);
5543
5663
  } else {
5544
- console.log(import_chalk32.default.dim(" Target auth: none required."));
5664
+ console.log(import_chalk33.default.dim(" Target auth: none required."));
5545
5665
  }
5546
5666
  const specText = JSON.stringify(spec2);
5547
5667
  await uploadSpec(p, specText, opts);
5548
5668
  const mcpUrl = await publishMcp(p, spec2);
5549
5669
  console.log();
5550
- if (p.proxyUrl) console.log(` ${import_chalk32.default.green("\u2713")} proxy ${import_chalk32.default.bold(p.proxyUrl)}`);
5551
- if (mcpUrl) console.log(` ${import_chalk32.default.green("\u2713")} mcp ${import_chalk32.default.bold(mcpUrl)}`);
5670
+ if (p.proxyUrl) console.log(` ${import_chalk33.default.green("\u2713")} proxy ${import_chalk33.default.bold(p.proxyUrl)}`);
5671
+ if (mcpUrl) console.log(` ${import_chalk33.default.green("\u2713")} mcp ${import_chalk33.default.bold(mcpUrl)}`);
5552
5672
  if (p.anon) {
5553
- console.log(import_chalk32.default.dim("\n Anonymous workspace \u2014 /claim inside the chat (after /login) to keep it beyond 30 days."));
5673
+ console.log(import_chalk33.default.dim("\n Anonymous workspace \u2014 /claim inside the chat (after /login) to keep it beyond 30 days."));
5554
5674
  }
5555
5675
  await runRepl(p);
5556
5676
  }
5557
5677
 
5558
5678
  // src/commands/consumer.ts
5559
- var import_chalk33 = __toESM(require("chalk"));
5679
+ var import_chalk34 = __toESM(require("chalk"));
5560
5680
  var import_ora17 = __toESM(require("ora"));
5561
5681
  init_admin();
5562
5682
  var DEFAULT_SCOPE = "openid email profile offline_access";
@@ -5577,7 +5697,7 @@ async function consumerFetch(creds, suffix, init) {
5577
5697
  function requireConsumer() {
5578
5698
  const c = loadConsumer();
5579
5699
  if (!c) {
5580
- console.error(import_chalk33.default.red("Not logged in as a consumer. Run `apiblaze consumer login` first."));
5700
+ console.error(import_chalk34.default.red("Not logged in as a consumer. Run `apiblaze consumer login` first."));
5581
5701
  process.exit(1);
5582
5702
  }
5583
5703
  return c;
@@ -5588,7 +5708,7 @@ async function runConsumerLogin(opts) {
5588
5708
  let clientId = opts.client;
5589
5709
  if (clientId) {
5590
5710
  if (!tenant2) {
5591
- console.error(import_chalk33.default.red("When using --client, also pass --tenant <slug> (it sets which portal/keys host to use)."));
5711
+ console.error(import_chalk34.default.red("When using --client, also pass --tenant <slug> (it sets which portal/keys host to use)."));
5592
5712
  process.exit(1);
5593
5713
  }
5594
5714
  } else {
@@ -5606,19 +5726,19 @@ async function runConsumerLogin(opts) {
5606
5726
  const usable = (Array.isArray(clients) ? clients : []).filter((c) => c && (c.client_id || c.clientId));
5607
5727
  const pick2 = usable.find((c) => c.is_default || c.default) ?? usable.find((c) => c.verified !== false) ?? usable[0];
5608
5728
  if (!pick2) {
5609
- console.error(import_chalk33.default.red(`Tenant "${tenant2}" has no login app configured. Set one up in the dashboard (or \`apiblaze create\` with auth).`));
5729
+ console.error(import_chalk34.default.red(`Tenant "${tenant2}" has no login app configured. Set one up in the dashboard (or \`apiblaze create\` with auth).`));
5610
5730
  process.exit(1);
5611
5731
  }
5612
5732
  clientId = pick2.client_id ?? pick2.clientId;
5613
5733
  }
5614
5734
  const portalResource = `https://${tenant2}.portal.apiblaze.com/1.0.0`;
5615
- console.log(`${import_chalk33.default.cyan("\u2192")} Logging in to ${import_chalk33.default.bold(tenant2)} as a consumer...`);
5735
+ console.log(`${import_chalk34.default.cyan("\u2192")} Logging in to ${import_chalk34.default.bold(tenant2)} as a consumer...`);
5616
5736
  const result = await deviceLogin(clientId, DEFAULT_SCOPE, ({ verificationUri, userCode }) => {
5617
5737
  console.log(`
5618
- Open: ${import_chalk33.default.underline(verificationUri)}`);
5619
- console.log(` Code: ${import_chalk33.default.bold(userCode)}
5738
+ Open: ${import_chalk34.default.underline(verificationUri)}`);
5739
+ console.log(` Code: ${import_chalk34.default.bold(userCode)}
5620
5740
  `);
5621
- console.log(import_chalk33.default.dim(" (opening your browser\u2026 waiting for you to finish)"));
5741
+ console.log(import_chalk34.default.dim(" (opening your browser\u2026 waiting for you to finish)"));
5622
5742
  }, portalResource);
5623
5743
  const claims = result.idToken && decodeJwt2(result.idToken) || (decodeJwt2(result.accessToken) ?? {});
5624
5744
  const creds = {
@@ -5633,7 +5753,7 @@ async function runConsumerLogin(opts) {
5633
5753
  obtainedAt: Date.now()
5634
5754
  };
5635
5755
  saveConsumer(creds);
5636
- console.log(import_chalk33.default.green(`\u2714 Logged in as consumer${creds.email ? ` ${creds.email}` : ""} on ${tenant2}.`));
5756
+ console.log(import_chalk34.default.green(`\u2714 Logged in as consumer${creds.email ? ` ${creds.email}` : ""} on ${tenant2}.`));
5637
5757
  }
5638
5758
  async function runConsumerTokens(opts) {
5639
5759
  const creds = requireConsumer();
@@ -5646,18 +5766,18 @@ async function runConsumerTokens(opts) {
5646
5766
  console.log(JSON.stringify({ tenant: fresh.tenant, access_token: fresh.accessToken, refresh_token: fresh.refreshToken, id_token: fresh.idToken, expires_at: new Date(fresh.expiresAt).toISOString() }, null, 2));
5647
5767
  return;
5648
5768
  }
5649
- console.log(`${import_chalk33.default.cyan("Consumer")} ${import_chalk33.default.bold(fresh.email ?? fresh.tenant)} on ${import_chalk33.default.bold(fresh.tenant)}
5769
+ console.log(`${import_chalk34.default.cyan("Consumer")} ${import_chalk34.default.bold(fresh.email ?? fresh.tenant)} on ${import_chalk34.default.bold(fresh.tenant)}
5650
5770
  `);
5651
- console.log(`${import_chalk33.default.bold("access_token")} ${import_chalk33.default.dim("exp " + (exp(fresh.accessToken) ?? "?"))}
5771
+ console.log(`${import_chalk34.default.bold("access_token")} ${import_chalk34.default.dim("exp " + (exp(fresh.accessToken) ?? "?"))}
5652
5772
  ${fresh.accessToken}
5653
5773
  `);
5654
- if (fresh.idToken) console.log(`${import_chalk33.default.bold("id_token")} ${import_chalk33.default.dim("exp " + (exp(fresh.idToken) ?? "?"))}
5774
+ if (fresh.idToken) console.log(`${import_chalk34.default.bold("id_token")} ${import_chalk34.default.dim("exp " + (exp(fresh.idToken) ?? "?"))}
5655
5775
  ${fresh.idToken}
5656
5776
  `);
5657
- if (fresh.refreshToken) console.log(`${import_chalk33.default.bold("refresh_token")}
5777
+ if (fresh.refreshToken) console.log(`${import_chalk34.default.bold("refresh_token")}
5658
5778
  ${fresh.refreshToken}
5659
5779
  `);
5660
- console.log(import_chalk33.default.dim("These are your own tokens \u2014 keep them secret."));
5780
+ console.log(import_chalk34.default.dim("These are your own tokens \u2014 keep them secret."));
5661
5781
  }
5662
5782
  async function runConsumerApikeys(opts) {
5663
5783
  const creds = requireConsumer();
@@ -5667,8 +5787,8 @@ async function runConsumerApikeys(opts) {
5667
5787
  const revealed = await consumerFetch(list.creds, "/apikeys/reveal").catch(() => ({ status: 0, data: null, creds: list.creds }));
5668
5788
  spinner.stop();
5669
5789
  if (list.status >= 400) {
5670
- console.error(import_chalk33.default.red(`Failed to list keys (${list.status}): ${list.data?.error ?? ""}`));
5671
- if (list.status === 401) console.error(import_chalk33.default.dim("Your consumer session may have expired \u2014 run `apiblaze consumer login` again."));
5790
+ console.error(import_chalk34.default.red(`Failed to list keys (${list.status}): ${list.data?.error ?? ""}`));
5791
+ if (list.status === 401) console.error(import_chalk34.default.dim("Your consumer session may have expired \u2014 run `apiblaze consumer login` again."));
5672
5792
  process.exit(1);
5673
5793
  }
5674
5794
  const keys = list.data?.keys ?? [];
@@ -5676,16 +5796,16 @@ async function runConsumerApikeys(opts) {
5676
5796
  if (opts.json) {
5677
5797
  console.log(JSON.stringify({ keys, revealed: revealMap }, null, 2));
5678
5798
  } else if (!keys.length) {
5679
- console.log(import_chalk33.default.yellow("No API keys yet."));
5799
+ console.log(import_chalk34.default.yellow("No API keys yet."));
5680
5800
  } else {
5681
5801
  for (const k of keys) {
5682
5802
  const clear = revealMap[k.environment]?.key;
5683
- const shown = clear ? import_chalk33.default.green(clear) : import_chalk33.default.dim(`${k.key_prefix ?? ""}\u2026${k.key_suffix ?? ""}`);
5684
- const exp = k.expires_at ? import_chalk33.default.dim(`exp ${k.expires_at}`) : import_chalk33.default.dim("no expiry");
5685
- console.log(` ${import_chalk33.default.bold(k.environment ?? "")} ${shown} ${exp} ${import_chalk33.default.dim(k.description ?? "")}`);
5803
+ const shown = clear ? import_chalk34.default.green(clear) : import_chalk34.default.dim(`${k.key_prefix ?? ""}\u2026${k.key_suffix ?? ""}`);
5804
+ const exp = k.expires_at ? import_chalk34.default.dim(`exp ${k.expires_at}`) : import_chalk34.default.dim("no expiry");
5805
+ console.log(` ${import_chalk34.default.bold(k.environment ?? "")} ${shown} ${exp} ${import_chalk34.default.dim(k.description ?? "")}`);
5686
5806
  }
5687
5807
  if (Object.keys(revealMap).length === 0 && keys.some((k) => !k.expires_at)) {
5688
- console.log(import_chalk33.default.dim("\n(Only expiring keys can be shown in clear; non-expiring keys show a prefix only.)"));
5808
+ console.log(import_chalk34.default.dim("\n(Only expiring keys can be shown in clear; non-expiring keys show a prefix only.)"));
5689
5809
  }
5690
5810
  }
5691
5811
  if (opts.json) return;
@@ -5707,34 +5827,34 @@ async function runConsumerApikeys(opts) {
5707
5827
  }
5708
5828
  s2.succeed("Key created.");
5709
5829
  const key = created.data?.key ?? created.data?.fullKey;
5710
- if (key) console.log(` ${import_chalk33.default.green(key)} ${import_chalk33.default.dim("(shown once \u2014 store it now)")}`);
5711
- else console.log(import_chalk33.default.dim(" Key created; run `apiblaze consumer apikeys` to reveal it if it expires."));
5830
+ if (key) console.log(` ${import_chalk34.default.green(key)} ${import_chalk34.default.dim("(shown once \u2014 store it now)")}`);
5831
+ else console.log(import_chalk34.default.dim(" Key created; run `apiblaze consumer apikeys` to reveal it if it expires."));
5712
5832
  }
5713
5833
 
5714
5834
  // src/commands/sidecar.ts
5715
- var import_chalk34 = __toESM(require("chalk"));
5835
+ var import_chalk35 = __toESM(require("chalk"));
5716
5836
  var import_ora18 = __toESM(require("ora"));
5717
- var fs9 = __toESM(require("fs"));
5718
- var path6 = __toESM(require("path"));
5837
+ var fs10 = __toESM(require("fs"));
5838
+ var path7 = __toESM(require("path"));
5719
5839
  init_admin();
5720
5840
  init_auth();
5721
5841
  function detectNextProject(root) {
5722
- const hasConfig = ["next.config.js", "next.config.mjs", "next.config.ts"].some((f) => fs9.existsSync(path6.join(root, f)));
5842
+ const hasConfig = ["next.config.js", "next.config.mjs", "next.config.ts"].some((f) => fs10.existsSync(path7.join(root, f)));
5723
5843
  let hasDep = false;
5724
5844
  try {
5725
- const pkg = JSON.parse(fs9.readFileSync(path6.join(root, "package.json"), "utf8"));
5845
+ const pkg = JSON.parse(fs10.readFileSync(path7.join(root, "package.json"), "utf8"));
5726
5846
  hasDep = !!(pkg.dependencies?.next || pkg.devDependencies?.next);
5727
5847
  } catch {
5728
5848
  }
5729
- const appDir = fs9.existsSync(path6.join(root, "app")) || fs9.existsSync(path6.join(root, "src", "app"));
5730
- const pagesDir = fs9.existsSync(path6.join(root, "pages")) || fs9.existsSync(path6.join(root, "src", "pages"));
5849
+ const appDir = fs10.existsSync(path7.join(root, "app")) || fs10.existsSync(path7.join(root, "src", "app"));
5850
+ const pagesDir = fs10.existsSync(path7.join(root, "pages")) || fs10.existsSync(path7.join(root, "src", "pages"));
5731
5851
  return { found: hasConfig || hasDep || appDir || pagesDir, router: appDir ? "app" : pagesDir ? "pages" : null };
5732
5852
  }
5733
5853
  function upsertEnvLocal(root, token) {
5734
- const p = path6.join(root, ".env.local");
5854
+ const p = path7.join(root, ".env.local");
5735
5855
  let existing = "";
5736
5856
  try {
5737
- existing = fs9.readFileSync(p, "utf8");
5857
+ existing = fs10.readFileSync(p, "utf8");
5738
5858
  } catch {
5739
5859
  }
5740
5860
  const had = /^APIBLAZE_API_KEY=/m.test(existing) || /^APIBLAZE_TOKEN=/m.test(existing);
@@ -5749,15 +5869,15 @@ function upsertEnvLocal(root, token) {
5749
5869
  next = (next.endsWith("\n") ? next : next + "\n") + `APIBLAZE_SIDECAR_VERBOSE=true
5750
5870
  `;
5751
5871
  }
5752
- fs9.writeFileSync(p, next);
5872
+ fs10.writeFileSync(p, next);
5753
5873
  return had ? "rotated" : "created";
5754
5874
  }
5755
5875
  function installSidecarPackage(root) {
5756
- if (fs9.existsSync(path6.join(root, "node_modules", "apiblaze", "package.json"))) {
5757
- console.log(` ${import_chalk34.default.green("\u2713")} apiblaze package already installed`);
5876
+ if (fs10.existsSync(path7.join(root, "node_modules", "apiblaze", "package.json"))) {
5877
+ console.log(` ${import_chalk35.default.green("\u2713")} apiblaze package already installed`);
5758
5878
  return;
5759
5879
  }
5760
- const has = (f) => fs9.existsSync(path6.join(root, f));
5880
+ const has = (f) => fs10.existsSync(path7.join(root, f));
5761
5881
  const pm = has("bun.lockb") || has("bun.lock") ? { cmd: "bun", add: "add" } : has("pnpm-lock.yaml") ? { cmd: "pnpm", add: "add" } : has("yarn.lock") ? { cmd: "yarn", add: "add" } : { cmd: "npm", add: "install" };
5762
5882
  const spinner = (0, import_ora18.default)(`Installing the apiblaze package (${pm.cmd})\u2026`).start();
5763
5883
  try {
@@ -5765,12 +5885,12 @@ function installSidecarPackage(root) {
5765
5885
  execSync(`${pm.cmd} ${pm.add} apiblaze`, { cwd: root, stdio: "ignore" });
5766
5886
  spinner.succeed("Installed apiblaze (the sidecar runtime).");
5767
5887
  } catch {
5768
- spinner.warn(`Couldn't auto-install \u2014 run ${import_chalk34.default.cyan(`${pm.cmd} ${pm.add} apiblaze`)} yourself before ${import_chalk34.default.cyan("npm run dev")}.`);
5888
+ spinner.warn(`Couldn't auto-install \u2014 run ${import_chalk35.default.cyan(`${pm.cmd} ${pm.add} apiblaze`)} yourself before ${import_chalk35.default.cyan("npm run dev")}.`);
5769
5889
  }
5770
5890
  }
5771
5891
  function readEnvKey(root) {
5772
5892
  try {
5773
- const s = fs9.readFileSync(path6.join(root, ".env.local"), "utf8");
5893
+ const s = fs10.readFileSync(path7.join(root, ".env.local"), "utf8");
5774
5894
  const m = s.match(/^APIBLAZE_API_KEY=(.+)$/m) ?? s.match(/^APIBLAZE_TOKEN=(.+)$/m);
5775
5895
  return m ? m[1].trim() : null;
5776
5896
  } catch {
@@ -5778,16 +5898,16 @@ function readEnvKey(root) {
5778
5898
  }
5779
5899
  }
5780
5900
  function ensureGitignored(root) {
5781
- const p = path6.join(root, ".gitignore");
5901
+ const p = path7.join(root, ".gitignore");
5782
5902
  let c = "";
5783
5903
  try {
5784
- c = fs9.readFileSync(p, "utf8");
5904
+ c = fs10.readFileSync(p, "utf8");
5785
5905
  } catch {
5786
5906
  }
5787
- if (!/^\.env\.local$/m.test(c) && !/^\.env\*/m.test(c)) fs9.writeFileSync(p, (c && !c.endsWith("\n") ? c + "\n" : c) + ".env.local\n");
5907
+ if (!/^\.env\.local$/m.test(c) && !/^\.env\*/m.test(c)) fs10.writeFileSync(p, (c && !c.endsWith("\n") ? c + "\n" : c) + ".env.local\n");
5788
5908
  }
5789
5909
  function wireInstrumentation(root) {
5790
- const existing = ["instrumentation.ts", "instrumentation.js", path6.join("src", "instrumentation.ts")].map((c) => path6.join(root, c)).find((f) => fs9.existsSync(f));
5910
+ const existing = ["instrumentation.ts", "instrumentation.js", path7.join("src", "instrumentation.ts")].map((c) => path7.join(root, c)).find((f) => fs10.existsSync(f));
5791
5911
  const body = `import { register as apiblaze } from "apiblaze/sidecar";
5792
5912
 
5793
5913
  export function register() {
@@ -5795,18 +5915,18 @@ export function register() {
5795
5915
  }
5796
5916
  `;
5797
5917
  if (!existing) {
5798
- fs9.writeFileSync(path6.join(root, "instrumentation.ts"), body);
5918
+ fs10.writeFileSync(path7.join(root, "instrumentation.ts"), body);
5799
5919
  return "created";
5800
5920
  }
5801
- const cur = fs9.readFileSync(existing, "utf8");
5921
+ const cur = fs10.readFileSync(existing, "utf8");
5802
5922
  if (cur.includes("apiblaze/sidecar")) return "present";
5803
5923
  if (/export\s+function\s+register\s*\(/.test(cur)) {
5804
- fs9.writeFileSync(existing, `import { register as apiblaze } from "apiblaze/sidecar";
5924
+ fs10.writeFileSync(existing, `import { register as apiblaze } from "apiblaze/sidecar";
5805
5925
  ` + cur.replace(/export\s+function\s+register\s*\(\s*\)\s*\{/, (m) => `${m}
5806
5926
  apiblaze();`));
5807
5927
  return "patched";
5808
5928
  }
5809
- fs9.writeFileSync(existing, `import { register as apiblaze } from "apiblaze/sidecar";
5929
+ fs10.writeFileSync(existing, `import { register as apiblaze } from "apiblaze/sidecar";
5810
5930
  ${cur}
5811
5931
  // call apiblaze() inside your register() export.
5812
5932
  `);
@@ -5885,17 +6005,17 @@ export default async function Page() {
5885
6005
  function generateInspector(root, router) {
5886
6006
  try {
5887
6007
  if (router === "pages") {
5888
- const dir2 = fs9.existsSync(path6.join(root, "src", "pages")) ? path6.join(root, "src", "pages") : path6.join(root, "pages");
5889
- const f2 = path6.join(dir2, "abz-inspector.tsx");
5890
- fs9.writeFileSync(f2, INSPECTOR_PAGE);
5891
- return path6.relative(root, f2);
5892
- }
5893
- const base = fs9.existsSync(path6.join(root, "src", "app")) ? path6.join(root, "src", "app") : path6.join(root, "app");
5894
- const dir = path6.join(base, "abz-inspector");
5895
- fs9.mkdirSync(dir, { recursive: true });
5896
- const f = path6.join(dir, "page.tsx");
5897
- fs9.writeFileSync(f, INSPECTOR_PAGE);
5898
- return path6.relative(root, f);
6008
+ const dir2 = fs10.existsSync(path7.join(root, "src", "pages")) ? path7.join(root, "src", "pages") : path7.join(root, "pages");
6009
+ const f2 = path7.join(dir2, "abz-inspector.tsx");
6010
+ fs10.writeFileSync(f2, INSPECTOR_PAGE);
6011
+ return path7.relative(root, f2);
6012
+ }
6013
+ const base = fs10.existsSync(path7.join(root, "src", "app")) ? path7.join(root, "src", "app") : path7.join(root, "app");
6014
+ const dir = path7.join(base, "abz-inspector");
6015
+ fs10.mkdirSync(dir, { recursive: true });
6016
+ const f = path7.join(dir, "page.tsx");
6017
+ fs10.writeFileSync(f, INSPECTOR_PAGE);
6018
+ return path7.relative(root, f);
5899
6019
  } catch {
5900
6020
  return null;
5901
6021
  }
@@ -5916,29 +6036,29 @@ async function runAnonymousInit(root, router, opts) {
5916
6036
  if (out.cp_key && out.team_id) saveAnonCred2(out.cp_key, out.team_id, out.claim_code);
5917
6037
  const envState = upsertEnvLocal(root, out.token);
5918
6038
  ensureGitignored(root);
5919
- console.log(` ${import_chalk34.default.green("\u2713")} .env.local ${envState} (APIBLAZE_API_KEY) \u2014 gitignored`);
5920
- console.log(` ${import_chalk34.default.green("\u2713")} instrumentation.ts ${wireInstrumentation(root)}`);
6039
+ console.log(` ${import_chalk35.default.green("\u2713")} .env.local ${envState} (APIBLAZE_API_KEY) \u2014 gitignored`);
6040
+ console.log(` ${import_chalk35.default.green("\u2713")} instrumentation.ts ${wireInstrumentation(root)}`);
5921
6041
  installSidecarPackage(root);
5922
6042
  let inspectorPath = null;
5923
6043
  if (!opts.noInspector) {
5924
6044
  inspectorPath = generateInspector(root, router);
5925
- if (inspectorPath) console.log(` ${import_chalk34.default.green("\u2713")} inspector at ${inspectorPath}`);
6045
+ if (inspectorPath) console.log(` ${import_chalk35.default.green("\u2713")} inspector at ${inspectorPath}`);
5926
6046
  }
5927
6047
  console.log("");
5928
- console.log(import_chalk34.default.bold("Done (no account needed). What happens next:"));
5929
- console.log(` 1. ${import_chalk34.default.cyan("npm run dev")} and use your app.`);
6048
+ console.log(import_chalk35.default.bold("Done (no account needed). What happens next:"));
6049
+ console.log(` 1. ${import_chalk35.default.cyan("npm run dev")} and use your app.`);
5930
6050
  console.log(` 2. Each external origin your app calls is logged in the console \u2014 approve one with:`);
5931
- console.log(` ${import_chalk34.default.cyan("apiblaze sidecar approve api.stripe.com")} (no login needed)`);
6051
+ console.log(` ${import_chalk35.default.cyan("apiblaze sidecar approve api.stripe.com")} (no login needed)`);
5932
6052
  console.log("");
5933
- console.log(import_chalk34.default.bold(" \u{1F511} Keep your setup \u2014 claim it into an account:"));
5934
- console.log(` ${import_chalk34.default.cyan("apiblaze login")} then ${import_chalk34.default.cyan("apiblaze claim")} ${import_chalk34.default.dim("(no code needed here)")}`);
5935
- console.log(import_chalk34.default.dim(` From another machine: apiblaze claim ${out.claim_code} \xB7 expires in 30 days`));
6053
+ console.log(import_chalk35.default.bold(" \u{1F511} Keep your setup \u2014 claim it into an account:"));
6054
+ console.log(` ${import_chalk35.default.cyan("apiblaze login")} then ${import_chalk35.default.cyan("apiblaze claim")} ${import_chalk35.default.dim("(no code needed here)")}`);
6055
+ console.log(import_chalk35.default.dim(` From another machine: apiblaze claim ${out.claim_code} \xB7 expires in 30 days`));
5936
6056
  }
5937
6057
  async function runSidecar(opts) {
5938
- const root = path6.resolve(opts.dir ?? process.cwd());
6058
+ const root = path7.resolve(opts.dir ?? process.cwd());
5939
6059
  const detected = detectNextProject(root);
5940
6060
  if (!detected.found) {
5941
- console.log(import_chalk34.default.yellow(`No Next.js project detected in ${root}.`));
6061
+ console.log(import_chalk35.default.yellow(`No Next.js project detected in ${root}.`));
5942
6062
  console.log("Create one (e.g. `npx create-next-app`) and re-run `apiblaze init` inside it.");
5943
6063
  return;
5944
6064
  }
@@ -5949,10 +6069,10 @@ async function runSidecar(opts) {
5949
6069
  if (!loadCredentials()) {
5950
6070
  upsertEnvLocal(root, readEnvKey(root));
5951
6071
  ensureGitignored(root);
5952
- console.log(` ${import_chalk34.default.green("\u2713")} .env.local present (APIBLAZE_API_KEY) \u2014 reusing`);
5953
- console.log(` ${import_chalk34.default.green("\u2713")} instrumentation.ts ${wireInstrumentation(root)}`);
6072
+ console.log(` ${import_chalk35.default.green("\u2713")} .env.local present (APIBLAZE_API_KEY) \u2014 reusing`);
6073
+ console.log(` ${import_chalk35.default.green("\u2713")} instrumentation.ts ${wireInstrumentation(root)}`);
5954
6074
  installSidecarPackage(root);
5955
- console.log(import_chalk34.default.dim(" Log in and run `apiblaze claim <code>` to keep this setup, or `apiblaze login` to manage it."));
6075
+ console.log(import_chalk35.default.dim(" Log in and run `apiblaze claim <code>` to keep this setup, or `apiblaze login` to manage it."));
5956
6076
  return;
5957
6077
  }
5958
6078
  const { teamId, teamName } = await resolveTeam(opts.team);
@@ -5975,38 +6095,38 @@ async function runSidecar(opts) {
5975
6095
  throw err;
5976
6096
  }
5977
6097
  } else {
5978
- console.log(import_chalk34.default.dim(` Reusing the existing APIBLAZE_API_KEY (run with --rotate to mint a fresh one, or --team <name> to switch teams).`));
6098
+ console.log(import_chalk35.default.dim(` Reusing the existing APIBLAZE_API_KEY (run with --rotate to mint a fresh one, or --team <name> to switch teams).`));
5979
6099
  }
5980
6100
  const envState = upsertEnvLocal(root, token);
5981
6101
  ensureGitignored(root);
5982
- console.log(` ${import_chalk34.default.green("\u2713")} .env.local ${envState} (APIBLAZE_API_KEY) \u2014 gitignored`);
6102
+ console.log(` ${import_chalk35.default.green("\u2713")} .env.local ${envState} (APIBLAZE_API_KEY) \u2014 gitignored`);
5983
6103
  const wireState = wireInstrumentation(root);
5984
- console.log(` ${import_chalk34.default.green("\u2713")} instrumentation.ts ${wireState}`);
6104
+ console.log(` ${import_chalk35.default.green("\u2713")} instrumentation.ts ${wireState}`);
5985
6105
  installSidecarPackage(root);
5986
6106
  let inspectorPath = null;
5987
6107
  if (!opts.noInspector) {
5988
6108
  inspectorPath = generateInspector(root, detected.router);
5989
- if (inspectorPath) console.log(` ${import_chalk34.default.green("\u2713")} inspector at ${inspectorPath}`);
6109
+ if (inspectorPath) console.log(` ${import_chalk35.default.green("\u2713")} inspector at ${inspectorPath}`);
5990
6110
  }
5991
6111
  console.log("");
5992
- console.log(import_chalk34.default.bold("Done. What happens next:"));
5993
- console.log(` 1. ${import_chalk34.default.cyan("npm run dev")} and use your app \u2014 it works exactly as before (all calls go direct).`);
5994
- console.log(` 2. The origins your app calls appear as ${import_chalk34.default.bold("candidates")} \u2014 list them: ${import_chalk34.default.cyan("apiblaze sidecar")}`);
5995
- console.log(` 3. Approve the ones to route: ${import_chalk34.default.cyan("apiblaze sidecar approve api.stripe.com")} (or in the dashboard)`);
6112
+ console.log(import_chalk35.default.bold("Done. What happens next:"));
6113
+ console.log(` 1. ${import_chalk35.default.cyan("npm run dev")} and use your app \u2014 it works exactly as before (all calls go direct).`);
6114
+ console.log(` 2. The origins your app calls appear as ${import_chalk35.default.bold("candidates")} \u2014 list them: ${import_chalk35.default.cyan("apiblaze sidecar")}`);
6115
+ console.log(` 3. Approve the ones to route: ${import_chalk35.default.cyan("apiblaze sidecar approve api.stripe.com")} (or in the dashboard)`);
5996
6116
  console.log(` \u2026within ~5 min your app starts routing that origin through APIblaze.`);
5997
- if (inspectorPath) console.log(` \u2022 Try it now: open ${import_chalk34.default.underline("http://localhost:3000/abz-inspector")} (dev only; rm ${path6.dirname(inspectorPath)} before shipping)`);
5998
- if (switchingTeam) console.log(import_chalk34.default.dim(` \u2022 Approved origins are per-team \u2014 re-approve them on ${teamName ?? teamId} with \`apiblaze sidecar approve <origin>\`.`));
6117
+ if (inspectorPath) console.log(` \u2022 Try it now: open ${import_chalk35.default.underline("http://localhost:3000/abz-inspector")} (dev only; rm ${path7.dirname(inspectorPath)} before shipping)`);
6118
+ if (switchingTeam) console.log(import_chalk35.default.dim(` \u2022 Approved origins are per-team \u2014 re-approve them on ${teamName ?? teamId} with \`apiblaze sidecar approve <origin>\`.`));
5999
6119
  console.log("");
6000
- console.log(import_chalk34.default.dim(" Manage: apiblaze sidecar (list/approve/deny/remove)"));
6001
- console.log(import_chalk34.default.dim(" Rotate: apiblaze init --rotate \xB7 Switch team: apiblaze init --team <name>"));
6002
- console.log(import_chalk34.default.dim(" Turn off: set APIBLAZE_SIDECAR=off in .env.local (flip back to on anytime; key stays put)."));
6120
+ console.log(import_chalk35.default.dim(" Manage: apiblaze sidecar (list/approve/deny/remove)"));
6121
+ console.log(import_chalk35.default.dim(" Rotate: apiblaze init --rotate \xB7 Switch team: apiblaze init --team <name>"));
6122
+ console.log(import_chalk35.default.dim(" Turn off: set APIBLAZE_SIDECAR=off in .env.local (flip back to on anytime; key stays put)."));
6003
6123
  console.log("");
6004
- console.log(import_chalk34.default.yellow(" \u26A0 APIBLAZE_API_KEY is long-lived and lets a holder call your team's proxies. Never commit it."));
6005
- console.log(import_chalk34.default.dim(" Your control-plane login stays in ~/.apiblaze \u2014 it never entered this project."));
6124
+ console.log(import_chalk35.default.yellow(" \u26A0 APIBLAZE_API_KEY is long-lived and lets a holder call your team's proxies. Never commit it."));
6125
+ console.log(import_chalk35.default.dim(" Your control-plane login stays in ~/.apiblaze \u2014 it never entered this project."));
6006
6126
  }
6007
6127
 
6008
6128
  // src/commands/origins.ts
6009
- var import_chalk35 = __toESM(require("chalk"));
6129
+ var import_chalk36 = __toESM(require("chalk"));
6010
6130
  var import_ora19 = __toESM(require("ora"));
6011
6131
  init_admin();
6012
6132
  init_auth();
@@ -6016,7 +6136,7 @@ async function runOriginsList(opts) {
6016
6136
  if (!loadCredentials()) {
6017
6137
  const cred = loadAnonCred();
6018
6138
  if (!cred) {
6019
- console.log(import_chalk35.default.yellow("No anonymous workspace here. Run `apiblaze init` first."));
6139
+ console.log(import_chalk36.default.yellow("No anonymous workspace here. Run `apiblaze init` first."));
6020
6140
  return;
6021
6141
  }
6022
6142
  out = await cpFetch(cred.cp_key, `/teams/${encodeURIComponent(cred.team_id)}/sidecar/candidates`, { method: "GET" });
@@ -6034,27 +6154,27 @@ async function runOriginsList(opts) {
6034
6154
  }
6035
6155
  const routed = out.routed ?? [];
6036
6156
  const candidates = out.candidates ?? [];
6037
- console.log(import_chalk35.default.bold(`
6157
+ console.log(import_chalk36.default.bold(`
6038
6158
  Routed through APIblaze (${routed.length})`));
6039
- if (!routed.length) console.log(import_chalk35.default.dim(" none yet"));
6040
- for (const r of routed) console.log(` ${import_chalk35.default.green("\u25CF")} ${r.sidecar_origin} ${import_chalk35.default.dim(`\u2192 ${r.project_id}`)}`);
6041
- console.log(import_chalk35.default.bold(`
6159
+ if (!routed.length) console.log(import_chalk36.default.dim(" none yet"));
6160
+ for (const r of routed) console.log(` ${import_chalk36.default.green("\u25CF")} ${r.sidecar_origin} ${import_chalk36.default.dim(`\u2192 ${r.project_id}`)}`);
6161
+ console.log(import_chalk36.default.bold(`
6042
6162
  Candidates \u2014 going direct, not yet approved (${candidates.length})`));
6043
- if (!candidates.length) console.log(import_chalk35.default.dim(" none \u2014 run your app to discover the origins it calls"));
6163
+ if (!candidates.length) console.log(import_chalk36.default.dim(" none \u2014 run your app to discover the origins it calls"));
6044
6164
  for (const c of candidates) {
6045
- console.log(` ${import_chalk35.default.yellow("\u25CB")} ${c.origin} ${import_chalk35.default.dim(`seen ${c.request_count}\xD7, last ${c.last_seen}`)}`);
6165
+ console.log(` ${import_chalk36.default.yellow("\u25CB")} ${c.origin} ${import_chalk36.default.dim(`seen ${c.request_count}\xD7, last ${c.last_seen}`)}`);
6046
6166
  }
6047
6167
  if (candidates.length) {
6048
- console.log(import_chalk35.default.dim(`
6168
+ console.log(import_chalk36.default.dim(`
6049
6169
  Approve: apiblaze sidecar approve ${candidates[0].origin.replace("https://", "")}`));
6050
- console.log(import_chalk35.default.dim(` Dismiss: apiblaze sidecar deny ${candidates[0].origin.replace("https://", "")}`));
6170
+ console.log(import_chalk36.default.dim(` Dismiss: apiblaze sidecar deny ${candidates[0].origin.replace("https://", "")}`));
6051
6171
  }
6052
6172
  }
6053
6173
  async function runOriginsApprove(origin, opts) {
6054
6174
  if (!loadCredentials()) {
6055
6175
  const cred = loadAnonCred();
6056
6176
  if (!cred) {
6057
- console.error(import_chalk35.default.red("Not logged in and no anonymous workspace. Run `apiblaze init` first."));
6177
+ console.error(import_chalk36.default.red("Not logged in and no anonymous workspace. Run `apiblaze init` first."));
6058
6178
  process.exit(1);
6059
6179
  }
6060
6180
  const spinner2 = (0, import_ora19.default)(`Approving ${origin} (anonymous)...`).start();
@@ -6107,7 +6227,7 @@ async function runOriginsRemove(origin, opts) {
6107
6227
  }
6108
6228
 
6109
6229
  // src/commands/op.ts
6110
- var import_chalk36 = __toESM(require("chalk"));
6230
+ var import_chalk37 = __toESM(require("chalk"));
6111
6231
  init_auth();
6112
6232
  init_trace();
6113
6233
  init_types();
@@ -6140,82 +6260,82 @@ function printResidue(report, applied) {
6140
6260
  const up = report?.upstash ?? {};
6141
6261
  const fga = report?.fga ?? {};
6142
6262
  const ghosts = report?.ghosts ?? {};
6143
- console.log(import_chalk36.default.bold(applied ? "\nExternal-residue sweep" : "\nExternal residue (dry-run \u2014 nothing deleted)"));
6144
- console.log(import_chalk36.default.bold("\n Upstash"));
6263
+ console.log(import_chalk37.default.bold(applied ? "\nExternal-residue sweep" : "\nExternal residue (dry-run \u2014 nothing deleted)"));
6264
+ console.log(import_chalk37.default.bold("\n Upstash"));
6145
6265
  const orphans = up.orphans ?? [];
6146
- if (orphans.length === 0) console.log(import_chalk36.default.green(" no orphaned keys"));
6147
- for (const o of orphans) console.log(` ${import_chalk36.default.yellow(o.key)} ${import_chalk36.default.dim(`\u2014 ${o.reason}`)}`);
6148
- console.log(import_chalk36.default.dim(` kept (live principals): ${up.kept ?? 0} \xB7 anon wallets (untouched): ${up.anon_wallets ?? 0}`));
6266
+ if (orphans.length === 0) console.log(import_chalk37.default.green(" no orphaned keys"));
6267
+ for (const o of orphans) console.log(` ${import_chalk37.default.yellow(o.key)} ${import_chalk37.default.dim(`\u2014 ${o.reason}`)}`);
6268
+ console.log(import_chalk37.default.dim(` kept (live principals): ${up.kept ?? 0} \xB7 anon wallets (untouched): ${up.anon_wallets ?? 0}`));
6149
6269
  if (up.anon_wallet_detail) {
6150
6270
  const d = up.anon_wallet_detail;
6151
- console.log(import_chalk36.default.dim(` anon wallets: ${d.count} ($${(d.total_cents / 100).toFixed(2)}), ${d.no_ttl} with NO TTL${d.no_ttl ? " \u26A0" : " (all self-expire)"}`));
6271
+ console.log(import_chalk37.default.dim(` anon wallets: ${d.count} ($${(d.total_cents / 100).toFixed(2)}), ${d.no_ttl} with NO TTL${d.no_ttl ? " \u26A0" : " (all self-expire)"}`));
6152
6272
  }
6153
6273
  if (up.keyspace_census) {
6154
6274
  const census = Object.entries(up.keyspace_census).map(([k, v]) => `${k}=${v}`).join(" \xB7 ");
6155
- console.log(import_chalk36.default.dim(` keyspace: ${census}`));
6275
+ console.log(import_chalk37.default.dim(` keyspace: ${census}`));
6156
6276
  }
6157
- if (up.unknown?.length) console.log(import_chalk36.default.dim(` unknown (never deleted): ${up.unknown.join(", ")}`));
6158
- if (applied) console.log(` ${import_chalk36.default.bold(String(up.deleted ?? 0))} key(s) deleted`);
6159
- for (const e of up.errors ?? []) console.log(import_chalk36.default.red(` error: ${e}`));
6160
- console.log(import_chalk36.default.bold("\n OpenFGA / Neon \u2014 orphan stores"));
6277
+ if (up.unknown?.length) console.log(import_chalk37.default.dim(` unknown (never deleted): ${up.unknown.join(", ")}`));
6278
+ if (applied) console.log(` ${import_chalk37.default.bold(String(up.deleted ?? 0))} key(s) deleted`);
6279
+ for (const e of up.errors ?? []) console.log(import_chalk37.default.red(` error: ${e}`));
6280
+ console.log(import_chalk37.default.bold("\n OpenFGA / Neon \u2014 orphan stores"));
6161
6281
  if (applied) {
6162
6282
  const swept = fga?.swept ?? [];
6163
- if (swept.length === 0) console.log(import_chalk36.default.green(" no orphaned stores"));
6283
+ if (swept.length === 0) console.log(import_chalk37.default.green(" no orphaned stores"));
6164
6284
  for (const s of swept) {
6165
6285
  console.log(
6166
- ` ${import_chalk36.default.yellow(s.store_id)} ${import_chalk36.default.dim(`\u2014 store ${s.openfga_deleted ? "deleted" : "DEFERRED"}, ${s.neon_deleted} Neon tuple(s) purged`)}`
6286
+ ` ${import_chalk37.default.yellow(s.store_id)} ${import_chalk37.default.dim(`\u2014 store ${s.openfga_deleted ? "deleted" : "DEFERRED"}, ${s.neon_deleted} Neon tuple(s) purged`)}`
6167
6287
  );
6168
6288
  }
6169
- if (fga?.remaining) console.log(import_chalk36.default.yellow(` ${fga.remaining} more orphan store(s) \u2014 re-run to drain`));
6289
+ if (fga?.remaining) console.log(import_chalk37.default.yellow(` ${fga.remaining} more orphan store(s) \u2014 re-run to drain`));
6170
6290
  const st = fga?.side_tables;
6171
- if (st) console.log(import_chalk36.default.dim(` Neon side-tables purged: ${st.soft_deleted_stores} store records, ${st.orphan_models} models, ${st.orphan_changelog} changelog rows${st.error ? ` (${st.error})` : ""}`));
6291
+ if (st) console.log(import_chalk37.default.dim(` Neon side-tables purged: ${st.soft_deleted_stores} store records, ${st.orphan_models} models, ${st.orphan_changelog} changelog rows${st.error ? ` (${st.error})` : ""}`));
6172
6292
  } else {
6173
6293
  const fgaOrphans = fga?.orphans ?? [];
6174
- if (fgaOrphans.length === 0) console.log(import_chalk36.default.green(" no orphaned stores"));
6294
+ if (fgaOrphans.length === 0) console.log(import_chalk37.default.green(" no orphaned stores"));
6175
6295
  for (const s of fgaOrphans) {
6176
6296
  const src = s.in_openfga ? "live in OpenFGA" : "Neon tuples only";
6177
- console.log(` ${import_chalk36.default.yellow(s.store_id)} ${import_chalk36.default.dim(`\u2014 ${src}${s.name ? ` (${s.name})` : ""}, ${s.neon_tuples} Neon tuple(s)`)}`);
6297
+ console.log(` ${import_chalk37.default.yellow(s.store_id)} ${import_chalk37.default.dim(`\u2014 ${src}${s.name ? ` (${s.name})` : ""}, ${s.neon_tuples} Neon tuple(s)`)}`);
6178
6298
  }
6179
- console.log(import_chalk36.default.dim(` kept stores: ${(fga?.kept_store_ids ?? []).length}`));
6299
+ console.log(import_chalk37.default.dim(` kept stores: ${(fga?.kept_store_ids ?? []).length}`));
6180
6300
  const st = fga?.side_tables;
6181
- if (st) console.log(import_chalk36.default.dim(` Neon side-table residue: ${st.soft_deleted_stores} soft-deleted store records, ${st.orphan_models} orphan models, ${st.orphan_changelog} orphan changelog rows`));
6301
+ if (st) console.log(import_chalk37.default.dim(` Neon side-table residue: ${st.soft_deleted_stores} soft-deleted store records, ${st.orphan_models} orphan models, ${st.orphan_changelog} orphan changelog rows`));
6182
6302
  }
6183
- for (const e of fga?.errors ?? []) console.log(import_chalk36.default.red(` error: ${e}`));
6184
- console.log(import_chalk36.default.bold("\n OpenFGA \u2014 ghost tuples in surviving stores"));
6303
+ for (const e of fga?.errors ?? []) console.log(import_chalk37.default.red(` error: ${e}`));
6304
+ console.log(import_chalk37.default.bold("\n OpenFGA \u2014 ghost tuples in surviving stores"));
6185
6305
  if (applied) {
6186
- if ((ghosts?.ghost_count ?? 0) === 0) console.log(import_chalk36.default.green(" no ghost tuples"));
6187
- else console.log(` ${import_chalk36.default.bold(String(ghosts.deleted ?? 0))} ghost tuple(s) deleted ${import_chalk36.default.dim(`(of ${ghosts.ghost_count} found, ${ghosts.scanned_tuples} scanned across ${ghosts.live_stores} live stores)`)}`);
6306
+ if ((ghosts?.ghost_count ?? 0) === 0) console.log(import_chalk37.default.green(" no ghost tuples"));
6307
+ else console.log(` ${import_chalk37.default.bold(String(ghosts.deleted ?? 0))} ghost tuple(s) deleted ${import_chalk37.default.dim(`(of ${ghosts.ghost_count} found, ${ghosts.scanned_tuples} scanned across ${ghosts.live_stores} live stores)`)}`);
6188
6308
  } else {
6189
6309
  const n = ghosts?.ghost_count ?? 0;
6190
- if (n === 0) console.log(import_chalk36.default.green(` no ghost tuples ${import_chalk36.default.dim(`(${ghosts.scanned_tuples ?? 0} scanned across ${ghosts.live_stores ?? 0} live stores)`)}`));
6310
+ if (n === 0) console.log(import_chalk37.default.green(` no ghost tuples ${import_chalk37.default.dim(`(${ghosts.scanned_tuples ?? 0} scanned across ${ghosts.live_stores ?? 0} live stores)`)}`));
6191
6311
  else {
6192
- console.log(import_chalk36.default.yellow(` ${n} ghost tuple(s) referencing entities absent from D1:`));
6312
+ console.log(import_chalk37.default.yellow(` ${n} ghost tuple(s) referencing entities absent from D1:`));
6193
6313
  for (const g of (ghosts.ghosts ?? []).slice(0, 20)) {
6194
- console.log(import_chalk36.default.dim(` ${g.object_type}:${g.object_id} ${g.relation} ${g._user}`));
6314
+ console.log(import_chalk37.default.dim(` ${g.object_type}:${g.object_id} ${g.relation} ${g._user}`));
6195
6315
  }
6196
- if (n > 20) console.log(import_chalk36.default.dim(` \u2026 and ${n - 20} more`));
6316
+ if (n > 20) console.log(import_chalk37.default.dim(` \u2026 and ${n - 20} more`));
6197
6317
  }
6198
6318
  }
6199
- for (const e of ghosts?.errors ?? []) console.log(import_chalk36.default.red(` error: ${e}`));
6319
+ for (const e of ghosts?.errors ?? []) console.log(import_chalk37.default.red(` error: ${e}`));
6200
6320
  console.log();
6201
6321
  }
6202
6322
  async function runOp(sub, opts = {}) {
6203
6323
  if (!loadCredentials()) {
6204
- console.log(import_chalk36.default.dim("Not logged in. Run `apiblaze login`."));
6324
+ console.log(import_chalk37.default.dim("Not logged in. Run `apiblaze login`."));
6205
6325
  return;
6206
6326
  }
6207
6327
  if (!isOperatorLogin()) {
6208
- console.log(import_chalk36.default.dim("`apiblaze op` is only available to platform operators."));
6328
+ console.log(import_chalk37.default.dim("`apiblaze op` is only available to platform operators."));
6209
6329
  return;
6210
6330
  }
6211
6331
  switch (sub) {
6212
6332
  case void 0:
6213
6333
  case "menu": {
6214
- console.log(import_chalk36.default.bold("\nOperator menu"));
6215
- console.log(` ${import_chalk36.default.cyan("apiblaze op residue")} external-store residue report (Upstash + Neon/OpenFGA, dry-run)`);
6216
- console.log(` ${import_chalk36.default.cyan("apiblaze op sweep")} delete the orphans the report shows (asks first; ${import_chalk36.default.dim("-y to skip")})`);
6217
- console.log(` ${import_chalk36.default.cyan("apiblaze op credits")} list credit wallets`);
6218
- console.log(import_chalk36.default.dim(` (to prune all non-CP data: run scripts/nuke-but-cp.sh --apply --sweep in the repo)
6334
+ console.log(import_chalk37.default.bold("\nOperator menu"));
6335
+ console.log(` ${import_chalk37.default.cyan("apiblaze op residue")} external-store residue report (Upstash + Neon/OpenFGA, dry-run)`);
6336
+ console.log(` ${import_chalk37.default.cyan("apiblaze op sweep")} delete the orphans the report shows (asks first; ${import_chalk37.default.dim("-y to skip")})`);
6337
+ console.log(` ${import_chalk37.default.cyan("apiblaze op credits")} list credit wallets`);
6338
+ console.log(import_chalk37.default.dim(` (to prune all non-CP data: run scripts/nuke-but-cp.sh --apply --sweep in the repo)
6219
6339
  `));
6220
6340
  return;
6221
6341
  }
@@ -6234,17 +6354,17 @@ async function runOp(sub, opts = {}) {
6234
6354
  const nSide = (st.soft_deleted_stores ?? 0) + (st.orphan_models ?? 0) + (st.orphan_changelog ?? 0);
6235
6355
  printResidue(report, false);
6236
6356
  if (nUp + nFga + nGhost + nSide === 0) {
6237
- console.log(import_chalk36.default.green("Nothing to sweep."));
6357
+ console.log(import_chalk37.default.green("Nothing to sweep."));
6238
6358
  return;
6239
6359
  }
6240
6360
  if (!opts.yes) {
6241
6361
  const readline2 = await import("readline/promises");
6242
6362
  const rl = readline2.createInterface({ input: process.stdin, output: process.stdout });
6243
6363
  const answer = await rl.question(
6244
- import_chalk36.default.red(`Delete ${nUp} Upstash key(s) + ${nFga} OpenFGA store(s) + ${nGhost} ghost tuple(s) + ${nSide} Neon side-table row(s)? Type 'sweep' to confirm: `)
6364
+ import_chalk37.default.red(`Delete ${nUp} Upstash key(s) + ${nFga} OpenFGA store(s) + ${nGhost} ghost tuple(s) + ${nSide} Neon side-table row(s)? Type 'sweep' to confirm: `)
6245
6365
  );
6246
6366
  rl.close();
6247
- if (answer.trim() !== "sweep") return void console.log(import_chalk36.default.dim("Aborted."));
6367
+ if (answer.trim() !== "sweep") return void console.log(import_chalk37.default.dim("Aborted."));
6248
6368
  }
6249
6369
  const result = await opCall({ method: "POST", path: "/operator/external-residue/sweep", summary: "external residue sweep" });
6250
6370
  if (opts.json) return void console.log(JSON.stringify(result, null, 2));
@@ -6255,15 +6375,15 @@ async function runOp(sub, opts = {}) {
6255
6375
  const data = await opCall({ method: "GET", path: "/operator/credits", summary: "list credit wallets" });
6256
6376
  if (opts.json) return void console.log(JSON.stringify(data, null, 2));
6257
6377
  const accounts = data?.accounts ?? [];
6258
- if (accounts.length === 0) return void console.log(import_chalk36.default.dim("No credit wallets."));
6378
+ if (accounts.length === 0) return void console.log(import_chalk37.default.dim("No credit wallets."));
6259
6379
  for (const a of accounts) {
6260
6380
  const bal = typeof a.balance_cents === "number" ? `$${(a.balance_cents / 100).toFixed(2)}` : "?";
6261
- console.log(` ${import_chalk36.default.bold(bal.padStart(9))} ${a.walletId}${a.owner_email ? import_chalk36.default.dim(` \u2014 ${a.owner_email}`) : a.anon ? import_chalk36.default.dim(" \u2014 anon") : ""}`);
6381
+ console.log(` ${import_chalk37.default.bold(bal.padStart(9))} ${a.walletId}${a.owner_email ? import_chalk37.default.dim(` \u2014 ${a.owner_email}`) : a.anon ? import_chalk37.default.dim(" \u2014 anon") : ""}`);
6262
6382
  }
6263
6383
  return;
6264
6384
  }
6265
6385
  default:
6266
- console.log(import_chalk36.default.red(`Unknown op subcommand '${sub}'. Run \`apiblaze op\` for the menu.`));
6386
+ console.log(import_chalk37.default.red(`Unknown op subcommand '${sub}'. Run \`apiblaze op\` for the menu.`));
6267
6387
  }
6268
6388
  }
6269
6389
 
@@ -6325,7 +6445,7 @@ program.command("dev").description("Put your localhost behind a public URL (dev
6325
6445
  try {
6326
6446
  const resolved = parseInt(port ?? opts.port, 10);
6327
6447
  if (Number.isNaN(resolved)) {
6328
- console.error(import_chalk37.default.red(`Invalid port: ${port ?? opts.port}`));
6448
+ console.error(import_chalk38.default.red(`Invalid port: ${port ?? opts.port}`));
6329
6449
  process.exit(1);
6330
6450
  }
6331
6451
  await runDev({ port: resolved, captureFile: opts.captureFile });
@@ -6338,6 +6458,7 @@ var consumer = program.command("consumer").description("Act as a consumer of you
6338
6458
  consumer.command("login").description("Log in to a tenant's portal as a consumer (device flow)").option("--team <id|name>", "Team whose tenants to choose from (producer mode)").option("--tenant <slug>", "Tenant to log in to (skips the picker)").option("--client <clientId>", "App client id \u2014 for standalone login without a producer session").action(action((opts) => runConsumerLogin(opts)));
6339
6459
  consumer.command("tokens").description("Show the logged-in consumer access / refresh / id tokens").option("--json", "Output machine-readable JSON").action(action((opts) => runConsumerTokens(opts)));
6340
6460
  consumer.command("apikeys").description("List your consumer API keys (reveals expiring ones), then offer to create one").option("--json", "Output machine-readable JSON").action(action((opts) => runConsumerApikeys(opts)));
6461
+ program.command("flush").description("Wipe ALL local state (login, workspace keys, apichats, DP keys, secrets)").option("-y, --yes", "Skip the confirmation prompt").action(runFlush);
6341
6462
  program.command("logout").description("Sign out (asks whether to drop the Producer or Consumer login)").option("--producer", "Log out of the API Producer identity").option("--consumer", "Log out of the API Consumer identity").option("--all", "Log out of both").action(action((opts) => runLogout(opts)));
6342
6463
  program.command("whoami").description("Show who you are \u2014 both API Producer and API Consumer").option("--json", "Output machine-readable JSON").action(async (opts) => {
6343
6464
  try {
@@ -6423,7 +6544,7 @@ function groupedCommandHelp() {
6423
6544
  const sub = byName.get(e.parent)?.commands.find((s) => s.name() === e.sub);
6424
6545
  return sub ? ` ${helpLabel(e).padEnd(width)}${sub.description()}` : "";
6425
6546
  }).filter(Boolean).join("\n");
6426
- return `${import_chalk37.default.bold(g.title)}
6547
+ return `${import_chalk38.default.bold(g.title)}
6427
6548
  ${rows}`;
6428
6549
  }).join("\n\n");
6429
6550
  }
@@ -6457,14 +6578,14 @@ async function recoverStaleTeam() {
6457
6578
  const { resolveLinkedTeam: resolveLinkedTeam2 } = await Promise.resolve().then(() => (init_team(), team_exports));
6458
6579
  const linked = await resolveLinkedTeam2({ preferredId: creds.teamId, interactive: !!process.stdin.isTTY });
6459
6580
  if (!linked) {
6460
- console.error(import_chalk37.default.yellow("Your account has no teams anymore (deleted?). Run `apiblaze login` or `apiblaze create` to get a workspace."));
6581
+ console.error(import_chalk38.default.yellow("Your account has no teams anymore (deleted?). Run `apiblaze login` or `apiblaze create` to get a workspace."));
6461
6582
  return;
6462
6583
  }
6463
6584
  if (linked.teamId === creds.teamId) return;
6464
6585
  const next = { ...creds, teamId: linked.teamId, teamName: linked.teamName };
6465
6586
  delete next.activeTenant;
6466
6587
  saveCredentials(next);
6467
- console.error(import_chalk37.default.yellow(`Your previous team no longer exists \u2014 relinked to ${import_chalk37.default.bold(linked.teamName ?? linked.teamId)}. Re-run your command.`));
6588
+ console.error(import_chalk38.default.yellow(`Your previous team no longer exists \u2014 relinked to ${import_chalk38.default.bold(linked.teamName ?? linked.teamId)}. Re-run your command.`));
6468
6589
  } catch {
6469
6590
  }
6470
6591
  }
@@ -6472,16 +6593,16 @@ async function printError(err) {
6472
6593
  if (err instanceof ApiError) {
6473
6594
  const data = err.body;
6474
6595
  const extra = [data?.body?.reason, data?.body?.details, data?.details, data?.body?.error].find((x) => typeof x === "string" && x && x !== err.message);
6475
- console.error(import_chalk37.default.red(`
6596
+ console.error(import_chalk38.default.red(`
6476
6597
  API error (${err.status}): ${err.message}${extra ? ` \u2014 ${extra}` : ""}`));
6477
6598
  if (err.status === 403 || err.status === 404) {
6478
6599
  await recoverStaleTeam();
6479
6600
  }
6480
6601
  } else if (err instanceof Error) {
6481
- console.error(import_chalk37.default.red(`
6602
+ console.error(import_chalk38.default.red(`
6482
6603
  Error: ${err.message}`));
6483
6604
  } else {
6484
- console.error(import_chalk37.default.red("\nUnknown error"));
6605
+ console.error(import_chalk38.default.red("\nUnknown error"));
6485
6606
  }
6486
6607
  }
6487
6608
  program.parse(process.argv);