deepspace 0.4.3 → 0.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli/cli.ts
4
- import { defineCommand as defineCommand19, runMain } from "citty";
4
+ import { defineCommand as defineCommand18, runMain } from "citty";
5
5
  import { execSync as execSync5 } from "child_process";
6
- import { readFileSync as readFileSync11, existsSync as existsSync12 } from "fs";
7
- import { dirname as dirname3, join as join14 } from "path";
8
- import { fileURLToPath } from "url";
6
+ import { readFileSync as readFileSync12, existsSync as existsSync13 } from "fs";
7
+ import { dirname as dirname4, join as join14 } from "path";
8
+ import { fileURLToPath as fileURLToPath2 } from "url";
9
9
 
10
10
  // src/cli/commands/login.ts
11
11
  import { defineCommand } from "citty";
@@ -581,8 +581,8 @@ import { join as join5 } from "path";
581
581
  import { homedir as homedir3 } from "os";
582
582
 
583
583
  // src/cli/jwt.ts
584
- function decodeJwtPayload(token2) {
585
- const payloadSegment = token2.split(".")[1];
584
+ function decodeJwtPayload(token) {
585
+ const payloadSegment = token.split(".")[1];
586
586
  if (!payloadSegment) {
587
587
  throw new Error("JWT payload is missing");
588
588
  }
@@ -605,13 +605,13 @@ async function ensureToken() {
605
605
  throw new Error("Not logged in. Run `deepspace login` first.");
606
606
  }
607
607
  const sessionToken = readFileSync4(SESSION_PATH2, "utf-8").trim();
608
- const token2 = await exchangeSession(AUTH_URL3, sessionToken);
609
- if (!token2) {
608
+ const token = await exchangeSession(AUTH_URL3, sessionToken);
609
+ if (!token) {
610
610
  throw new Error("Session expired. Run `deepspace login` to re-authenticate.");
611
611
  }
612
612
  mkdirSync2(DIR2, { recursive: true, mode: 448 });
613
- writeFileSync3(TOKEN_PATH2, token2, { mode: 384 });
614
- return token2;
613
+ writeFileSync3(TOKEN_PATH2, token, { mode: 384 });
614
+ return token;
615
615
  }
616
616
  function isTokenValid(jwt) {
617
617
  try {
@@ -794,16 +794,16 @@ var dev_default = defineCommand3({
794
794
  }
795
795
  writeLaunchConfigIfMissing(appDir, detectAppName(appDir) ?? basename(appDir), port);
796
796
  ensureInstallReady(appDir);
797
- let token2;
797
+ let token;
798
798
  try {
799
- token2 = await ensureToken();
799
+ token = await ensureToken();
800
800
  } catch (err) {
801
801
  console.error(err.message);
802
802
  process.exit(1);
803
803
  }
804
804
  let payload;
805
805
  try {
806
- payload = decodeJwtPayload(token2);
806
+ payload = decodeJwtPayload(token);
807
807
  } catch {
808
808
  console.error("Malformed session token. Run `npx deepspace login`.");
809
809
  process.exit(1);
@@ -812,7 +812,7 @@ var dev_default = defineCommand3({
812
812
  console.log(`Platform: ${env}`);
813
813
  if (wranglerEnv) console.log(`Wrangler env: ${wranglerEnv}`);
814
814
  console.log(`Port: ${port}`);
815
- await writeDevVars(appDir, env, payload.sub, token2, wranglerEnv);
815
+ await writeDevVars(appDir, env, payload.sub, token, wranglerEnv);
816
816
  preflightWindowsWorkerd(appDir);
817
817
  console.log("Starting dev server...\n");
818
818
  const vite = spawn(
@@ -1074,17 +1074,17 @@ var test_default = defineCommand5({
1074
1074
  process.exit(1);
1075
1075
  }
1076
1076
  ensureInstallReady(appDir);
1077
- let token2;
1077
+ let token;
1078
1078
  let ownerId;
1079
1079
  try {
1080
- token2 = await ensureToken();
1081
- const payload = decodeJwtPayload(token2);
1080
+ token = await ensureToken();
1081
+ const payload = decodeJwtPayload(token);
1082
1082
  ownerId = payload.sub;
1083
1083
  } catch (err) {
1084
1084
  console.error("`deepspace test` requires you to be logged in. Run `deepspace login` first.");
1085
1085
  process.exit(1);
1086
1086
  }
1087
- await writeDevVars(appDir, "dev", ownerId, token2);
1087
+ await writeDevVars(appDir, "dev", ownerId, token);
1088
1088
  if (suite !== "unit") {
1089
1089
  preflightWindowsWorkerd(appDir);
1090
1090
  ensurePlaywright(appDir);
@@ -1224,8 +1224,8 @@ function saveAccounts(accounts) {
1224
1224
  writeFileSync5(ACCOUNTS_PATH, JSON.stringify(accounts, null, 2), { mode: 384 });
1225
1225
  }
1226
1226
  function sessionCookie() {
1227
- const token2 = readFileSync7(SESSION_PATH2, "utf-8").trim();
1228
- return `${SESSION_COOKIE2}=${encodeURIComponent(token2)}`;
1227
+ const token = readFileSync7(SESSION_PATH2, "utf-8").trim();
1228
+ return `${SESSION_COOKIE2}=${encodeURIComponent(token)}`;
1229
1229
  }
1230
1230
  async function fetchRemoteAccounts() {
1231
1231
  const res = await fetch(`${AUTH_URL4}/api/auth/test-accounts`, {
@@ -1788,11 +1788,11 @@ async function postWithRetry(url, makeInit, { attempts = 4, retryServerErrors =
1788
1788
  if (lastRes) return lastRes;
1789
1789
  throw lastErr instanceof Error ? lastErr : new Error(String(lastErr));
1790
1790
  }
1791
- async function abortStagedUpload(appName, uploadId, totalGroups, token2) {
1791
+ async function abortStagedUpload(appName, uploadId, totalGroups, token) {
1792
1792
  try {
1793
1793
  await fetch(
1794
1794
  `${DEPLOY_URL}/api/deploy/${appName}/assets?uploadId=${uploadId}&totalGroups=${totalGroups}`,
1795
- { method: "DELETE", headers: { Authorization: `Bearer ${token2}` } }
1795
+ { method: "DELETE", headers: { Authorization: `Bearer ${token}` } }
1796
1796
  );
1797
1797
  } catch {
1798
1798
  }
@@ -1839,9 +1839,9 @@ var deploy_default = defineCommand8({
1839
1839
  }
1840
1840
  const appName = nameRes.name;
1841
1841
  p4.log.info(envName ? `App: ${appName} (env: ${envName})` : `App: ${appName}`);
1842
- let token2;
1842
+ let token;
1843
1843
  try {
1844
- token2 = await ensureToken();
1844
+ token = await ensureToken();
1845
1845
  } catch (err) {
1846
1846
  p4.cancel(err.message);
1847
1847
  process.exit(1);
@@ -1979,7 +1979,7 @@ var deploy_default = defineCommand8({
1979
1979
  () => ({
1980
1980
  method: "POST",
1981
1981
  headers: {
1982
- Authorization: `Bearer ${token2}`,
1982
+ Authorization: `Bearer ${token}`,
1983
1983
  "Content-Type": "application/json"
1984
1984
  },
1985
1985
  body: groupJson
@@ -1987,7 +1987,7 @@ var deploy_default = defineCommand8({
1987
1987
  );
1988
1988
  if (!groupRes.ok) {
1989
1989
  const errBody = await groupRes.json().catch(() => ({}));
1990
- await abortStagedUpload(appName, uploadId, totalGroups, token2);
1990
+ await abortStagedUpload(appName, uploadId, totalGroups, token);
1991
1991
  s.stop("Deploy failed");
1992
1992
  p4.cancel(
1993
1993
  `Asset upload failed on group ${i + 1}/${totalGroups}: ${errBody.error ?? `HTTP ${groupRes.status}`}`
@@ -1996,7 +1996,7 @@ var deploy_default = defineCommand8({
1996
1996
  }
1997
1997
  }
1998
1998
  } catch (err) {
1999
- await abortStagedUpload(appName, uploadId, totalGroups, token2);
1999
+ await abortStagedUpload(appName, uploadId, totalGroups, token);
2000
2000
  s.stop("Deploy failed");
2001
2001
  p4.cancel(`Asset upload failed (network): ${err?.message ?? err}`);
2002
2002
  process.exit(1);
@@ -2032,7 +2032,7 @@ var deploy_default = defineCommand8({
2032
2032
  `${DEPLOY_URL}/api/deploy/${appName}`,
2033
2033
  () => ({
2034
2034
  method: "POST",
2035
- headers: { Authorization: `Bearer ${token2}` },
2035
+ headers: { Authorization: `Bearer ${token}` },
2036
2036
  body: makeForm()
2037
2037
  }),
2038
2038
  // Commit runs a real deploy — don't retry its 5xx (could double-deploy);
@@ -2041,14 +2041,14 @@ var deploy_default = defineCommand8({
2041
2041
  { retryServerErrors: false }
2042
2042
  );
2043
2043
  } catch (err) {
2044
- if (uploadId) await abortStagedUpload(appName, uploadId, totalGroups, token2);
2044
+ if (uploadId) await abortStagedUpload(appName, uploadId, totalGroups, token);
2045
2045
  s.stop("Deploy failed");
2046
2046
  p4.cancel(`Deploy request failed: ${err?.message ?? err}`);
2047
2047
  process.exit(1);
2048
2048
  }
2049
2049
  const body = await res.json().catch(() => ({}));
2050
2050
  if (!res.ok || !body.success) {
2051
- if (uploadId) await abortStagedUpload(appName, uploadId, totalGroups, token2);
2051
+ if (uploadId) await abortStagedUpload(appName, uploadId, totalGroups, token);
2052
2052
  s.stop("Deploy failed");
2053
2053
  p4.cancel(formatDeployWorkerError(res.status, body.error));
2054
2054
  process.exit(1);
@@ -2060,20 +2060,20 @@ var deploy_default = defineCommand8({
2060
2060
  s.stop("Deployed (edge propagation still in progress after 90s)");
2061
2061
  p4.log.warn("First requests may briefly hit the assets transitional page; retry in a minute.");
2062
2062
  p4.log.success(`Live at: ${body.url}`);
2063
- await syncSubscriptionPlans(appDir, appName, token2);
2064
- await syncOneTimeProducts(appDir, appName, token2);
2063
+ await syncSubscriptionPlans(appDir, appName, token);
2064
+ await syncOneTimeProducts(appDir, appName, token);
2065
2065
  p4.outro("Done");
2066
2066
  return;
2067
2067
  }
2068
2068
  }
2069
2069
  s.stop("Deployed!");
2070
2070
  p4.log.success(`Live at: ${body.url}`);
2071
- await syncSubscriptionPlans(appDir, appName, token2);
2072
- await syncOneTimeProducts(appDir, appName, token2);
2071
+ await syncSubscriptionPlans(appDir, appName, token);
2072
+ await syncOneTimeProducts(appDir, appName, token);
2073
2073
  p4.outro("Done");
2074
2074
  }
2075
2075
  });
2076
- async function syncSubscriptionPlans(appDir, appName, token2) {
2076
+ async function syncSubscriptionPlans(appDir, appName, token) {
2077
2077
  const subsPath = join9(appDir, "src", "subscriptions.ts");
2078
2078
  if (!existsSync9(subsPath)) return;
2079
2079
  const s = createSpinner();
@@ -2112,7 +2112,7 @@ async function syncSubscriptionPlans(appDir, appName, token2) {
2112
2112
  res = await fetch(`${API_URL}/api/subscriptions/sync`, {
2113
2113
  method: "POST",
2114
2114
  headers: {
2115
- Authorization: `Bearer ${token2}`,
2115
+ Authorization: `Bearer ${token}`,
2116
2116
  "Content-Type": "application/json"
2117
2117
  },
2118
2118
  body: JSON.stringify({ appName, plans })
@@ -2132,7 +2132,7 @@ async function syncSubscriptionPlans(appDir, appName, token2) {
2132
2132
  }
2133
2133
  const changes = (body.planChanges ?? []).filter((c) => c.affectedSubscribers > 0);
2134
2134
  if (changes.length > 0) {
2135
- await promptAndCancelChangedPlans(appName, token2, changes);
2135
+ await promptAndCancelChangedPlans(appName, token, changes);
2136
2136
  }
2137
2137
  return;
2138
2138
  }
@@ -2153,7 +2153,7 @@ function summaryLine(c) {
2153
2153
  const diffs = (c.intervals ?? []).map((i) => `${i.interval}: ${formatCents(i.oldCents)} \u2192 ${formatCents(i.newCents)}`).join("; ");
2154
2154
  return ` \u2022 ${c.slug} \u2014 repriced (${diffs}; ${suffix} grandfathered on old price)`;
2155
2155
  }
2156
- async function promptAndCancelChangedPlans(appName, token2, changes) {
2156
+ async function promptAndCancelChangedPlans(appName, token, changes) {
2157
2157
  const summary = changes.map(summaryLine).join("\n");
2158
2158
  p4.log.warn(
2159
2159
  `Plan change${changes.length === 1 ? "" : "s"} from this deploy left subscribers stranded:
@@ -2184,7 +2184,7 @@ current billing period? (Skip to leave them grandfathered.)`
2184
2184
  const res = await fetch(`${API_URL}/api/subscriptions/admin-cancel`, {
2185
2185
  method: "POST",
2186
2186
  headers: {
2187
- Authorization: `Bearer ${token2}`,
2187
+ Authorization: `Bearer ${token}`,
2188
2188
  "Content-Type": "application/json"
2189
2189
  },
2190
2190
  body: JSON.stringify({
@@ -2222,7 +2222,7 @@ current billing period? (Skip to leave them grandfathered.)`
2222
2222
  }
2223
2223
  }
2224
2224
  }
2225
- async function syncOneTimeProducts(appDir, appName, token2) {
2225
+ async function syncOneTimeProducts(appDir, appName, token) {
2226
2226
  const productsPath = join9(appDir, "src", "products.ts");
2227
2227
  if (!existsSync9(productsPath)) return;
2228
2228
  const s = createSpinner();
@@ -2261,7 +2261,7 @@ async function syncOneTimeProducts(appDir, appName, token2) {
2261
2261
  res = await fetch(`${API_URL}/api/charges/products/sync`, {
2262
2262
  method: "POST",
2263
2263
  headers: {
2264
- Authorization: `Bearer ${token2}`,
2264
+ Authorization: `Bearer ${token}`,
2265
2265
  "Content-Type": "application/json"
2266
2266
  },
2267
2267
  body: JSON.stringify({ appName, products })
@@ -2360,9 +2360,9 @@ var undeploy_default = defineCommand9({
2360
2360
  p5.cancel("Provide an app name or run from a DeepSpace app directory.");
2361
2361
  process.exit(1);
2362
2362
  }
2363
- let token2;
2363
+ let token;
2364
2364
  try {
2365
- token2 = await ensureToken();
2365
+ token = await ensureToken();
2366
2366
  } catch (err) {
2367
2367
  p5.cancel(err.message);
2368
2368
  process.exit(1);
@@ -2372,7 +2372,7 @@ var undeploy_default = defineCommand9({
2372
2372
  s.start("Removing...");
2373
2373
  const res = await fetch(`${DEPLOY_URL2}/api/deploy/${appName}`, {
2374
2374
  method: "DELETE",
2375
- headers: { Authorization: `Bearer ${token2}` }
2375
+ headers: { Authorization: `Bearer ${token}` }
2376
2376
  });
2377
2377
  const body = await res.json().catch(() => ({}));
2378
2378
  if (!res.ok || !body.success) {
@@ -2591,25 +2591,25 @@ var skills_default = defineCommand12({
2591
2591
  import { defineCommand as defineCommand13 } from "citty";
2592
2592
  import { execSync as execSync4 } from "child_process";
2593
2593
  var API_URL2 = process.env.DEEPSPACE_API_URL ?? ENVS.prod.api;
2594
- async function api(token2, path, init) {
2594
+ async function api(token, path, init) {
2595
2595
  const res = await fetch(`${API_URL2}${path}`, {
2596
2596
  ...init,
2597
2597
  headers: {
2598
- Authorization: `Bearer ${token2}`,
2598
+ Authorization: `Bearer ${token}`,
2599
2599
  "Content-Type": "application/json",
2600
2600
  ...init?.headers ?? {}
2601
2601
  }
2602
2602
  });
2603
- const text = await res.text();
2603
+ const text2 = await res.text();
2604
2604
  if (!res.ok) {
2605
- let msg = text;
2605
+ let msg = text2;
2606
2606
  try {
2607
- msg = JSON.parse(text).error ?? text;
2607
+ msg = JSON.parse(text2).error ?? text2;
2608
2608
  } catch {
2609
2609
  }
2610
2610
  throw new Error(`API ${path} (${res.status}): ${msg}`);
2611
2611
  }
2612
- return JSON.parse(text);
2612
+ return JSON.parse(text2);
2613
2613
  }
2614
2614
  function scrubInternal(value) {
2615
2615
  if (Array.isArray(value)) return value.map(scrubInternal);
@@ -2652,10 +2652,10 @@ var search = defineCommand13({
2652
2652
  json: { type: "boolean", description: "Emit JSON instead of a table" }
2653
2653
  },
2654
2654
  async run({ args }) {
2655
- const token2 = await ensureToken();
2655
+ const token = await ensureToken();
2656
2656
  const limit = parseInt(args.limit ?? "10", 10) || 10;
2657
2657
  const result = await api(
2658
- token2,
2658
+ token,
2659
2659
  `/api/domains/search?q=${encodeURIComponent(args.query)}&limit=${limit}`
2660
2660
  );
2661
2661
  if (args.json) {
@@ -2685,9 +2685,9 @@ var buy = defineCommand13({
2685
2685
  json: { type: "boolean", description: "Emit JSON to stdout", default: false }
2686
2686
  },
2687
2687
  async run({ args }) {
2688
- const token2 = await ensureToken();
2688
+ const token = await ensureToken();
2689
2689
  const appName = requireAppName(args.app);
2690
- const priceCheck = await api(token2, "/api/domains/check", {
2690
+ const priceCheck = await api(token, "/api/domains/check", {
2691
2691
  method: "POST",
2692
2692
  body: JSON.stringify({ domains: [args.domain] })
2693
2693
  });
@@ -2708,7 +2708,7 @@ var buy = defineCommand13({
2708
2708
  }
2709
2709
  }
2710
2710
  const checkout = await api(
2711
- token2,
2711
+ token,
2712
2712
  "/api/domains/checkout",
2713
2713
  {
2714
2714
  method: "POST",
@@ -2735,7 +2735,7 @@ var buy = defineCommand13({
2735
2735
  await new Promise((r) => setTimeout(r, 5e3));
2736
2736
  try {
2737
2737
  const detail = await api(
2738
- token2,
2738
+ token,
2739
2739
  `/api/domains/${checkout.purchaseId}`
2740
2740
  );
2741
2741
  if (detail.domain.status !== lastStatus) {
@@ -2769,8 +2769,8 @@ var list2 = defineCommand13({
2769
2769
  json: { type: "boolean", description: "Emit JSON" }
2770
2770
  },
2771
2771
  async run({ args }) {
2772
- const token2 = await ensureToken();
2773
- const result = await api(token2, "/api/domains");
2772
+ const token = await ensureToken();
2773
+ const result = await api(token, "/api/domains");
2774
2774
  if (args.json) {
2775
2775
  process.stdout.write(JSON.stringify(scrubInternal(result), null, 2) + "\n");
2776
2776
  return;
@@ -2794,8 +2794,8 @@ var status = defineCommand13({
2794
2794
  json: { type: "boolean" }
2795
2795
  },
2796
2796
  async run({ args }) {
2797
- const token2 = await ensureToken();
2798
- const all = await api(token2, "/api/domains");
2797
+ const token = await ensureToken();
2798
+ const all = await api(token, "/api/domains");
2799
2799
  const found = all.domains.find((d) => d.domain === args.domain);
2800
2800
  if (!found) {
2801
2801
  console.error(`No domain ${args.domain} in your account`);
@@ -2823,16 +2823,16 @@ var attach = defineCommand13({
2823
2823
  json: { type: "boolean" }
2824
2824
  },
2825
2825
  async run({ args }) {
2826
- const token2 = await ensureToken();
2826
+ const token = await ensureToken();
2827
2827
  const targetApp = requireAppName(args.app);
2828
- const all = await api(token2, "/api/domains");
2828
+ const all = await api(token, "/api/domains");
2829
2829
  const found = all.domains.find((d) => d.domain === args.domain);
2830
2830
  if (!found) {
2831
2831
  console.error(`No domain ${args.domain} in your account`);
2832
2832
  process.exit(1);
2833
2833
  }
2834
2834
  const result = await api(
2835
- token2,
2835
+ token,
2836
2836
  `/api/domains/${found.id}/reattach`,
2837
2837
  {
2838
2838
  method: "POST",
@@ -2856,8 +2856,8 @@ var detach = defineCommand13({
2856
2856
  yes: { type: "boolean", description: "Skip the confirmation prompt" }
2857
2857
  },
2858
2858
  async run({ args }) {
2859
- const token2 = await ensureToken();
2860
- const all = await api(token2, "/api/domains");
2859
+ const token = await ensureToken();
2860
+ const all = await api(token, "/api/domains");
2861
2861
  const found = all.domains.find((d) => d.domain === args.domain);
2862
2862
  if (!found) {
2863
2863
  console.error(`No domain ${args.domain} in your account`);
@@ -2872,7 +2872,7 @@ var detach = defineCommand13({
2872
2872
  return;
2873
2873
  }
2874
2874
  }
2875
- await api(token2, `/api/domains/${found.id}`, { method: "DELETE" });
2875
+ await api(token, `/api/domains/${found.id}`, { method: "DELETE" });
2876
2876
  console.log(`\u2713 ${args.domain} detached. Use \`deepspace domain attach\` to re-route, or \`renew --auto off\` to stop auto-renewal.`);
2877
2877
  }
2878
2878
  });
@@ -2887,15 +2887,15 @@ var renew = defineCommand13({
2887
2887
  console.error('--auto must be "on" or "off"');
2888
2888
  process.exit(1);
2889
2889
  }
2890
- const token2 = await ensureToken();
2891
- const all = await api(token2, "/api/domains");
2890
+ const token = await ensureToken();
2891
+ const all = await api(token, "/api/domains");
2892
2892
  const found = all.domains.find((d) => d.domain === args.domain);
2893
2893
  if (!found) {
2894
2894
  console.error(`No domain ${args.domain} in your account`);
2895
2895
  process.exit(1);
2896
2896
  }
2897
2897
  const enabled = args.auto === "on";
2898
- await api(token2, `/api/domains/${found.id}/auto-renew`, {
2898
+ await api(token, `/api/domains/${found.id}/auto-renew`, {
2899
2899
  method: "POST",
2900
2900
  body: JSON.stringify({ autoRenew: enabled })
2901
2901
  });
@@ -3277,257 +3277,14 @@ var invoke_default = defineCommand15({
3277
3277
  }
3278
3278
  });
3279
3279
 
3280
- // src/cli/commands/managed-repos.ts
3281
- import { defineCommand as defineCommand16 } from "citty";
3282
- var API_URL4 = process.env.DEEPSPACE_API_URL ?? ENVS.prod.api;
3283
- var SIMPLE_APP_ID = /^[a-z0-9][a-z0-9_.:-]{0,119}$/i;
3284
- var SIMPLE_APP_NAME = /^[a-z0-9][a-z0-9_-]{0,119}$/i;
3285
- async function api2(token2, path, init) {
3286
- const res = await fetch(`${API_URL4}${path}`, {
3287
- ...init,
3288
- headers: {
3289
- Authorization: `Bearer ${token2}`,
3290
- "Content-Type": "application/json",
3291
- ...init?.headers ?? {}
3292
- }
3293
- });
3294
- const text = await res.text();
3295
- if (!res.ok) {
3296
- let msg = text;
3297
- try {
3298
- msg = JSON.parse(text).error ?? text;
3299
- } catch {
3300
- }
3301
- throw new Error(`API ${path} (${res.status}): ${msg}`);
3302
- }
3303
- return JSON.parse(text);
3304
- }
3305
- function defaultAppId(appName) {
3306
- return `cli-${slugId(appName)}`;
3307
- }
3308
- function slugId(raw) {
3309
- return raw.toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "") || "app";
3310
- }
3311
- function assertSimple(value, pattern, label) {
3312
- if (!pattern.test(value)) {
3313
- throw new Error(`${label} must start with a letter or number and contain only simple identifier characters.`);
3314
- }
3315
- }
3316
- function printQuota(quota) {
3317
- console.log(`Repo quota: ${quota.activeCount} / ${quota.limit} active (${quota.remaining} remaining)`);
3318
- }
3319
- function printRepo(repo) {
3320
- console.log(`${repo.fullName}`);
3321
- console.log(` ID: ${repo.id}`);
3322
- console.log(` App: ${repo.appName}`);
3323
- console.log(` App ID: ${repo.appId}`);
3324
- console.log(` URL: ${repo.htmlUrl}`);
3325
- console.log(` Clone: ${repo.cloneUrl}`);
3326
- }
3327
- async function confirm4(message) {
3328
- if (!process.stdin.isTTY) {
3329
- throw new Error(`${message} \u2014 pass --yes to confirm non-interactively`);
3330
- }
3331
- process.stdout.write(`${message} [y/N] `);
3332
- return new Promise((resolve9) => {
3333
- process.stdin.setEncoding("utf-8");
3334
- process.stdin.once("data", (data) => {
3335
- const answer = data.toString().trim().toLowerCase();
3336
- resolve9(answer === "y" || answer === "yes");
3337
- });
3338
- });
3339
- }
3340
- var list4 = defineCommand16({
3341
- meta: {
3342
- name: "list",
3343
- description: "List your DeepSpace-managed repos and quota"
3344
- },
3345
- args: {
3346
- json: {
3347
- type: "boolean",
3348
- description: "Emit JSON instead of human output",
3349
- default: false
3350
- }
3351
- },
3352
- async run({ args }) {
3353
- const token2 = await ensureToken();
3354
- const result = await api2(token2, "/api/github/repos");
3355
- if (args.json) {
3356
- process.stdout.write(JSON.stringify(result, null, 2) + "\n");
3357
- return;
3358
- }
3359
- printQuota(result.quota);
3360
- if (result.repos.length === 0) {
3361
- console.log("No DeepSpace-managed repos. Create one with `deepspace managed-repos create <app-name>`.");
3362
- return;
3363
- }
3364
- console.log("");
3365
- for (const repo of result.repos) {
3366
- printRepo(repo);
3367
- }
3368
- }
3369
- });
3370
- var create2 = defineCommand16({
3371
- meta: {
3372
- name: "create",
3373
- description: "Create a private DeepSpace-managed GitHub repo"
3374
- },
3375
- args: {
3376
- appName: {
3377
- type: "positional",
3378
- description: "Working app name for this repo",
3379
- required: true
3380
- },
3381
- appId: {
3382
- type: "string",
3383
- description: "Stable DeepSpace repo app id (defaults to cli-<app-name>)",
3384
- required: false
3385
- },
3386
- nameHint: {
3387
- type: "string",
3388
- description: "Repo-name hint (defaults to app name)",
3389
- required: false
3390
- },
3391
- json: {
3392
- type: "boolean",
3393
- description: "Emit JSON instead of human output",
3394
- default: false
3395
- }
3396
- },
3397
- async run({ args }) {
3398
- const appName = String(args.appName);
3399
- const appId = args.appId ? String(args.appId) : defaultAppId(appName);
3400
- const nameHint = args.nameHint ? String(args.nameHint) : void 0;
3401
- try {
3402
- assertSimple(appName, SIMPLE_APP_NAME, "appName");
3403
- assertSimple(appId, SIMPLE_APP_ID, "appId");
3404
- if (nameHint) assertSimple(nameHint, SIMPLE_APP_NAME, "nameHint");
3405
- } catch (err) {
3406
- console.error(err.message);
3407
- process.exit(1);
3408
- }
3409
- const token2 = await ensureToken();
3410
- const result = await api2(token2, "/api/github/repos", {
3411
- method: "POST",
3412
- body: JSON.stringify({ appName, appId, ...nameHint ? { nameHint } : {} })
3413
- });
3414
- if (args.json) {
3415
- process.stdout.write(JSON.stringify(result, null, 2) + "\n");
3416
- return;
3417
- }
3418
- console.log(result.alreadyExists ? "Existing DeepSpace-managed repo:" : "Created DeepSpace-managed repo:");
3419
- printRepo(result.repo);
3420
- }
3421
- });
3422
- var token = defineCommand16({
3423
- meta: {
3424
- name: "token",
3425
- description: "Mint a short-lived GitHub token for a DeepSpace-managed repo"
3426
- },
3427
- args: {
3428
- repoId: {
3429
- type: "positional",
3430
- description: "Repo id from `deepspace managed-repos list`",
3431
- required: true
3432
- },
3433
- json: {
3434
- type: "boolean",
3435
- description: "Emit JSON instead of human output",
3436
- default: false
3437
- }
3438
- },
3439
- async run({ args }) {
3440
- const jwt = await ensureToken();
3441
- const result = await api2(
3442
- jwt,
3443
- `/api/github/repos/${encodeURIComponent(String(args.repoId))}/agent-token`,
3444
- { method: "POST" }
3445
- );
3446
- if (args.json) {
3447
- process.stdout.write(JSON.stringify(result, null, 2) + "\n");
3448
- return;
3449
- }
3450
- console.log(`Repo: ${result.repo.fullName}`);
3451
- console.log(`Expires: ${result.token.expiresAt}`);
3452
- console.log(`Token: ${result.token.token}`);
3453
- console.log("");
3454
- console.log(`Clone: git clone https://x-access-token:${encodeURIComponent(result.token.token)}@github.com/${result.repo.fullName}.git`);
3455
- }
3456
- });
3457
- var remove = defineCommand16({
3458
- meta: {
3459
- name: "delete",
3460
- description: "Delete a DeepSpace-managed GitHub repo"
3461
- },
3462
- args: {
3463
- repoId: {
3464
- type: "positional",
3465
- description: "Repo id from `deepspace managed-repos list`",
3466
- required: true
3467
- },
3468
- yes: {
3469
- type: "boolean",
3470
- description: "Skip the confirmation prompt",
3471
- default: false
3472
- },
3473
- json: {
3474
- type: "boolean",
3475
- description: "Emit JSON instead of human output",
3476
- default: false
3477
- }
3478
- },
3479
- async run({ args }) {
3480
- if (!args.yes) {
3481
- try {
3482
- const ok = await confirm4(
3483
- "Delete this DeepSpace-managed GitHub repo? This removes the GitHub repository and counts against your daily delete quota."
3484
- );
3485
- if (!ok) {
3486
- console.log("Cancelled.");
3487
- return;
3488
- }
3489
- } catch (err) {
3490
- console.error(err.message);
3491
- process.exit(1);
3492
- }
3493
- }
3494
- const jwt = await ensureToken();
3495
- const result = await api2(
3496
- jwt,
3497
- `/api/github/repos/${encodeURIComponent(String(args.repoId))}`,
3498
- { method: "DELETE" }
3499
- );
3500
- if (args.json) {
3501
- process.stdout.write(JSON.stringify(result, null, 2) + "\n");
3502
- return;
3503
- }
3504
- console.log(`Deleted ${result.repo.fullName}`);
3505
- console.log(
3506
- `Delete quota: ${result.deletionQuota.deletedCount} / ${result.deletionQuota.limit} used today (${result.deletionQuota.remaining} remaining)`
3507
- );
3508
- }
3509
- });
3510
- var managed_repos_default = defineCommand16({
3511
- meta: {
3512
- name: "managed-repos",
3513
- description: "Create and manage DeepSpace-owned GitHub repos"
3514
- },
3515
- subCommands: {
3516
- list: list4,
3517
- create: create2,
3518
- token,
3519
- delete: remove
3520
- }
3521
- });
3522
-
3523
3280
  // src/cli/commands/library.ts
3524
- import { defineCommand as defineCommand17 } from "citty";
3281
+ import { defineCommand as defineCommand16 } from "citty";
3525
3282
  import { existsSync as existsSync11, readFileSync as readFileSync10 } from "fs";
3526
3283
  import { join as join12, resolve as resolve8 } from "path";
3527
3284
  import { parse as parseToml3 } from "smol-toml";
3528
3285
  import * as p6 from "@clack/prompts";
3529
3286
  var DEFAULT_LIBRARY_APP = "deepdotspace-site";
3530
- var publish = defineCommand17({
3287
+ var publish = defineCommand16({
3531
3288
  meta: {
3532
3289
  name: "publish",
3533
3290
  description: "Publish the current app to the DeepSpace library"
@@ -3586,7 +3343,7 @@ var publish = defineCommand17({
3586
3343
  },
3587
3344
  async run({ args }) {
3588
3345
  const json = !!args.json;
3589
- const intro5 = (s) => {
3346
+ const intro6 = (s) => {
3590
3347
  if (!json) p6.intro(s);
3591
3348
  };
3592
3349
  const info2 = (s) => {
@@ -3597,7 +3354,7 @@ var publish = defineCommand17({
3597
3354
  else p6.cancel(msg);
3598
3355
  process.exit(1);
3599
3356
  };
3600
- intro5("Publishing to the DeepSpace library");
3357
+ intro6("Publishing to the DeepSpace library");
3601
3358
  let appName = typeof args.app === "string" && args.app.trim() ? args.app.trim() : void 0;
3602
3359
  if (!appName) {
3603
3360
  const appDir = resolve8(typeof args.dir === "string" && args.dir ? args.dir : ".");
@@ -3618,9 +3375,9 @@ var publish = defineCommand17({
3618
3375
  const tags = typeof args.tags === "string" && args.tags ? args.tags.split(",").map((t) => t.trim()).filter(Boolean) : void 0;
3619
3376
  const libraryApp = typeof args["library-app"] === "string" && args["library-app"] ? args["library-app"] : DEFAULT_LIBRARY_APP;
3620
3377
  const libraryHost = process.env.DEEPSPACE_LIBRARY_HOST ?? `https://${libraryApp}.app.space`;
3621
- let token2;
3378
+ let token;
3622
3379
  try {
3623
- token2 = await ensureToken();
3380
+ token = await ensureToken();
3624
3381
  } catch (err) {
3625
3382
  return die(err instanceof Error ? err.message : String(err));
3626
3383
  }
@@ -3640,7 +3397,7 @@ var publish = defineCommand17({
3640
3397
  method: "POST",
3641
3398
  headers: {
3642
3399
  "Content-Type": "application/json",
3643
- Authorization: `Bearer ${token2}`
3400
+ Authorization: `Bearer ${token}`
3644
3401
  },
3645
3402
  body: JSON.stringify(payload)
3646
3403
  });
@@ -3666,7 +3423,7 @@ var publish = defineCommand17({
3666
3423
  p6.outro("Done");
3667
3424
  }
3668
3425
  });
3669
- var unpublish = defineCommand17({
3426
+ var unpublish = defineCommand16({
3670
3427
  meta: {
3671
3428
  name: "unpublish",
3672
3429
  description: "Remove a library entry (owner or admin only)"
@@ -3696,9 +3453,9 @@ var unpublish = defineCommand17({
3696
3453
  process.exit(1);
3697
3454
  };
3698
3455
  if (!json) p6.intro("Unpublishing library entry");
3699
- let token2;
3456
+ let token;
3700
3457
  try {
3701
- token2 = await ensureToken();
3458
+ token = await ensureToken();
3702
3459
  } catch (err) {
3703
3460
  return die(err instanceof Error ? err.message : String(err));
3704
3461
  }
@@ -3706,7 +3463,7 @@ var unpublish = defineCommand17({
3706
3463
  const libraryHost = process.env.DEEPSPACE_LIBRARY_HOST ?? `https://${libraryApp}.app.space`;
3707
3464
  const res = await fetch(`${libraryHost}/api/actions/library.unpublish`, {
3708
3465
  method: "POST",
3709
- headers: { "Content-Type": "application/json", Authorization: `Bearer ${token2}` },
3466
+ headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` },
3710
3467
  body: JSON.stringify({ templateHandle: String(args.handle) })
3711
3468
  });
3712
3469
  const body = await res.text();
@@ -3725,7 +3482,7 @@ var unpublish = defineCommand17({
3725
3482
  p6.outro("Done");
3726
3483
  }
3727
3484
  });
3728
- var library_default = defineCommand17({
3485
+ var library_default = defineCommand16({
3729
3486
  meta: {
3730
3487
  name: "library",
3731
3488
  description: "Manage your DeepSpace library entries"
@@ -3736,85 +3493,276 @@ var library_default = defineCommand17({
3736
3493
  }
3737
3494
  });
3738
3495
 
3739
- // src/cli/commands/admin.ts
3740
- import { defineCommand as defineCommand18 } from "citty";
3741
- import { mkdirSync as mkdirSync6, writeFileSync as writeFileSync6 } from "fs";
3742
- import { homedir as homedir6 } from "os";
3743
- import { join as join13 } from "path";
3744
- var AUTH_URL5 = process.env.DEEPSPACE_AUTH_URL ?? ENVS.prod.auth;
3745
- var impersonate = defineCommand18({
3496
+ // src/cli/commands/feedback.ts
3497
+ import { defineCommand as defineCommand17 } from "citty";
3498
+ import * as p7 from "@clack/prompts";
3499
+ import { existsSync as existsSync12, readFileSync as readFileSync11 } from "fs";
3500
+ import { dirname as dirname3, join as join13 } from "path";
3501
+ import { fileURLToPath } from "url";
3502
+ import { release } from "os";
3503
+ var API_URL4 = process.env.DEEPSPACE_API_URL ?? ENVS.prod.api;
3504
+ var TYPES = ["bug", "feature", "other"];
3505
+ var TYPE_LABELS = {
3506
+ bug: "Bug report",
3507
+ feature: "Feature request",
3508
+ other: "Other feedback"
3509
+ };
3510
+ var MAX_TITLE_LEN = 200;
3511
+ var MAX_BODY_LEN = 1e4;
3512
+ var MAX_CONTEXT_LEN = 200;
3513
+ async function api2(token, path, init) {
3514
+ const res = await fetch(`${API_URL4}${path}`, {
3515
+ ...init,
3516
+ headers: {
3517
+ Authorization: `Bearer ${token}`,
3518
+ "Content-Type": "application/json",
3519
+ ...init?.headers ?? {}
3520
+ }
3521
+ });
3522
+ const text2 = await res.text();
3523
+ if (!res.ok) {
3524
+ let msg = text2;
3525
+ try {
3526
+ msg = JSON.parse(text2).error ?? text2;
3527
+ } catch {
3528
+ }
3529
+ throw new Error(`API ${path} (${res.status}): ${msg}`);
3530
+ }
3531
+ return JSON.parse(text2);
3532
+ }
3533
+ function normalizeType(raw) {
3534
+ const value = (raw ?? "bug").toLowerCase();
3535
+ if (TYPES.includes(value)) return value;
3536
+ throw new Error(`Invalid --type "${raw}". Use one of: ${TYPES.join(", ")}.`);
3537
+ }
3538
+ function readCliVersion() {
3539
+ try {
3540
+ const here = dirname3(fileURLToPath(import.meta.url));
3541
+ const candidates = [
3542
+ join13(here, "..", "package.json"),
3543
+ join13(here, "..", "..", "..", "package.json")
3544
+ ];
3545
+ for (const path of candidates) {
3546
+ if (!existsSync12(path)) continue;
3547
+ const pkg2 = JSON.parse(readFileSync11(path, "utf-8"));
3548
+ if (pkg2.name === "deepspace" && pkg2.version) return pkg2.version;
3549
+ }
3550
+ } catch {
3551
+ }
3552
+ return "unknown";
3553
+ }
3554
+ function detectAppName2() {
3555
+ try {
3556
+ const cwd = process.cwd();
3557
+ if (!hasWranglerConfig(cwd)) return void 0;
3558
+ const config = readWranglerConfig(cwd);
3559
+ return typeof config.name === "string" ? config.name : void 0;
3560
+ } catch {
3561
+ return void 0;
3562
+ }
3563
+ }
3564
+ function clampContext(value) {
3565
+ return value.length > MAX_CONTEXT_LEN ? value.slice(0, MAX_CONTEXT_LEN) : value;
3566
+ }
3567
+ function collectContext() {
3568
+ const appName = detectAppName2();
3569
+ return {
3570
+ cliVersion: clampContext(readCliVersion()),
3571
+ nodeVersion: clampContext(process.version),
3572
+ platform: clampContext(`${process.platform} ${release()}`),
3573
+ ...appName ? { appName: clampContext(appName) } : {}
3574
+ };
3575
+ }
3576
+ function buildFeedbackPayload(input) {
3577
+ const title = input.title.trim();
3578
+ const body = input.body.trim();
3579
+ if (!title) throw new Error("A title is required.");
3580
+ if (!body) throw new Error("A message/description is required.");
3581
+ if (title.length > MAX_TITLE_LEN) {
3582
+ throw new Error(
3583
+ `Title must be ${MAX_TITLE_LEN} characters or fewer (got ${title.length}).`
3584
+ );
3585
+ }
3586
+ if (body.length > MAX_BODY_LEN) {
3587
+ throw new Error(
3588
+ `Description must be ${MAX_BODY_LEN} characters or fewer (got ${body.length}).`
3589
+ );
3590
+ }
3591
+ return {
3592
+ type: normalizeType(input.type),
3593
+ title,
3594
+ body,
3595
+ ...input.context
3596
+ };
3597
+ }
3598
+ var feedback_default = defineCommand17({
3746
3599
  meta: {
3747
- name: "impersonate",
3748
- description: "Store a short-lived CLI token for another user"
3600
+ name: "feedback",
3601
+ description: "Submit a bug report, feature request, or feedback to DeepSpace"
3749
3602
  },
3750
3603
  args: {
3751
- email: {
3752
- type: "string",
3753
- description: "Target user email",
3604
+ title: {
3605
+ type: "positional",
3606
+ description: "Short summary (prompted if omitted in a terminal)",
3754
3607
  required: false
3755
3608
  },
3756
- userId: {
3609
+ type: {
3757
3610
  type: "string",
3758
- description: "Target user id",
3611
+ alias: "t",
3612
+ description: `Report type: ${TYPES.join(" | ")} (default: bug)`,
3759
3613
  required: false
3760
3614
  },
3761
- secret: {
3615
+ message: {
3762
3616
  type: "string",
3763
- description: "Admin secret; defaults to DEEPSPACE_ADMIN_SECRET",
3617
+ alias: "m",
3618
+ description: "Details / description (prompted if omitted in a terminal)",
3764
3619
  required: false
3620
+ },
3621
+ yes: {
3622
+ type: "boolean",
3623
+ description: "Skip the confirmation prompt",
3624
+ default: false
3625
+ },
3626
+ json: {
3627
+ type: "boolean",
3628
+ description: "Emit JSON instead of human output",
3629
+ default: false
3765
3630
  }
3766
3631
  },
3767
3632
  async run({ args }) {
3768
- const secret = args.secret ?? process.env.DEEPSPACE_ADMIN_SECRET;
3769
- if (!secret) {
3770
- console.error("Missing admin secret. Set DEEPSPACE_ADMIN_SECRET or pass --secret.");
3633
+ const interactive = process.stdin.isTTY && !args.json;
3634
+ const fail = (message) => {
3635
+ if (args.json) {
3636
+ process.stdout.write(JSON.stringify({ ok: false, error: message }) + "\n");
3637
+ } else {
3638
+ console.error(message);
3639
+ }
3771
3640
  process.exit(1);
3641
+ };
3642
+ let type;
3643
+ try {
3644
+ type = normalizeType(args.type ? String(args.type) : void 0);
3645
+ } catch (err) {
3646
+ return fail(err.message);
3772
3647
  }
3773
- if (!args.email && !args.userId) {
3774
- console.error("Pass --email or --userId.");
3775
- process.exit(1);
3648
+ let title = args.title ? String(args.title) : "";
3649
+ let body = args.message ? String(args.message) : "";
3650
+ if ((!title || !body) && !interactive) {
3651
+ return fail(
3652
+ 'Provide a title and --message to submit non-interactively, e.g. `deepspace feedback "Title" --message "Details"`.'
3653
+ );
3776
3654
  }
3777
- const res = await fetch(`${AUTH_URL5}/api/auth/admin/impersonate`, {
3778
- method: "POST",
3779
- headers: {
3780
- "Content-Type": "application/json",
3781
- Authorization: `Bearer ${secret}`
3782
- },
3783
- body: JSON.stringify({
3784
- email: args.email,
3785
- userId: args.userId
3786
- })
3787
- });
3788
- const data = await res.json().catch(() => ({}));
3789
- if (!res.ok || !data.token || !data.user) {
3790
- console.error(`Failed: ${data.error ?? `HTTP ${res.status}`}`);
3791
- process.exit(1);
3655
+ if (interactive && (!args.type || !title || !body)) {
3656
+ p7.intro("DeepSpace Feedback");
3657
+ if (!args.type) {
3658
+ const picked = await p7.select({
3659
+ message: "What kind of feedback is this?",
3660
+ options: TYPES.map((t) => ({ value: t, label: TYPE_LABELS[t] })),
3661
+ initialValue: type
3662
+ });
3663
+ if (p7.isCancel(picked)) {
3664
+ p7.cancel("Cancelled.");
3665
+ process.exit(0);
3666
+ }
3667
+ type = picked;
3668
+ }
3669
+ if (!title) {
3670
+ const t = await p7.text({
3671
+ message: "Title",
3672
+ placeholder: "Short summary of the issue",
3673
+ validate: (v) => {
3674
+ if (!v?.trim()) return "Title is required";
3675
+ if (v.length > MAX_TITLE_LEN)
3676
+ return `Title must be ${MAX_TITLE_LEN} characters or fewer`;
3677
+ return void 0;
3678
+ }
3679
+ });
3680
+ if (p7.isCancel(t)) {
3681
+ p7.cancel("Cancelled.");
3682
+ process.exit(0);
3683
+ }
3684
+ title = String(t);
3685
+ }
3686
+ if (!body) {
3687
+ const m = await p7.text({
3688
+ message: "Details",
3689
+ placeholder: "What happened? Steps to reproduce, what you expected\u2026",
3690
+ validate: (v) => {
3691
+ if (!v?.trim()) return "A description is required";
3692
+ if (v.length > MAX_BODY_LEN)
3693
+ return `Description must be ${MAX_BODY_LEN} characters or fewer`;
3694
+ return void 0;
3695
+ }
3696
+ });
3697
+ if (p7.isCancel(m)) {
3698
+ p7.cancel("Cancelled.");
3699
+ process.exit(0);
3700
+ }
3701
+ body = String(m);
3702
+ }
3792
3703
  }
3793
- const dir = join13(homedir6(), ".deepspace");
3794
- mkdirSync6(dir, { recursive: true });
3795
- writeFileSync6(TOKEN_PATH2, data.token, { mode: 384 });
3796
- console.log(`Impersonating ${data.user.name ?? data.user.email ?? data.user.id}`);
3797
- console.log(`Email: ${data.user.email ?? "(none)"}`);
3798
- console.log(`UserID: ${data.user.id}`);
3799
- }
3800
- });
3801
- var admin_default = defineCommand18({
3802
- meta: {
3803
- name: "admin",
3804
- description: "Maintainer-only admin commands"
3805
- },
3806
- subCommands: {
3807
- impersonate
3704
+ let payload;
3705
+ try {
3706
+ payload = buildFeedbackPayload({
3707
+ type,
3708
+ title,
3709
+ body,
3710
+ context: collectContext()
3711
+ });
3712
+ } catch (err) {
3713
+ return fail(err.message);
3714
+ }
3715
+ if (interactive && !args.yes) {
3716
+ p7.note(
3717
+ `${TYPE_LABELS[payload.type]}
3718
+ ${payload.title}
3719
+
3720
+ ${payload.body}
3721
+
3722
+ Context: deepspace ${payload.cliVersion} \xB7 ${payload.nodeVersion} \xB7 ${payload.platform}` + (payload.appName ? ` \xB7 app ${payload.appName}` : ""),
3723
+ "Review"
3724
+ );
3725
+ const ok = await p7.confirm({ message: "Send this to the DeepSpace team?" });
3726
+ if (p7.isCancel(ok) || !ok) {
3727
+ p7.cancel("Not sent.");
3728
+ process.exit(0);
3729
+ }
3730
+ }
3731
+ let token;
3732
+ try {
3733
+ token = await ensureToken();
3734
+ } catch (err) {
3735
+ return fail(err.message ?? "Not signed in. Run `deepspace login`.");
3736
+ }
3737
+ let result;
3738
+ try {
3739
+ result = await api2(token, "/api/feedback", {
3740
+ method: "POST",
3741
+ body: JSON.stringify(payload)
3742
+ });
3743
+ } catch (err) {
3744
+ return fail(err.message);
3745
+ }
3746
+ if (args.json) {
3747
+ process.stdout.write(JSON.stringify({ ok: true, report: result.report }) + "\n");
3748
+ return;
3749
+ }
3750
+ if (interactive) {
3751
+ p7.outro(`Thanks! Submitted as ${result.report.id}.`);
3752
+ } else {
3753
+ console.log(`Submitted feedback ${result.report.id} (${result.report.type}).`);
3754
+ }
3755
+ console.log(`Track triage status at ${DASHBOARD_URL}.`);
3808
3756
  }
3809
3757
  });
3810
3758
 
3811
3759
  // src/cli/cli.ts
3812
- var __dirname = dirname3(fileURLToPath(import.meta.url));
3813
- var pkg = JSON.parse(readFileSync11(join14(__dirname, "..", "package.json"), "utf-8"));
3814
- if (process.platform === "linux" && !process.env.SSL_CERT_FILE && existsSync12("/etc/ssl/certs/ca-certificates.crt")) {
3760
+ var __dirname = dirname4(fileURLToPath2(import.meta.url));
3761
+ var pkg = JSON.parse(readFileSync12(join14(__dirname, "..", "package.json"), "utf-8"));
3762
+ if (process.platform === "linux" && !process.env.SSL_CERT_FILE && existsSync13("/etc/ssl/certs/ca-certificates.crt")) {
3815
3763
  process.env.SSL_CERT_FILE = "/etc/ssl/certs/ca-certificates.crt";
3816
3764
  }
3817
- var create3 = defineCommand19({
3765
+ var create2 = defineCommand18({
3818
3766
  meta: {
3819
3767
  name: "create",
3820
3768
  description: "Create a new DeepSpace app"
@@ -3833,14 +3781,14 @@ var create3 = defineCommand19({
3833
3781
  execSync5(`npm create deepspace@latest${name}`, { stdio: "inherit" });
3834
3782
  }
3835
3783
  });
3836
- var main = defineCommand19({
3784
+ var main = defineCommand18({
3837
3785
  meta: {
3838
3786
  name: "deepspace",
3839
3787
  version: pkg.version,
3840
3788
  description: "DeepSpace SDK CLI"
3841
3789
  },
3842
3790
  subCommands: {
3843
- create: create3,
3791
+ create: create2,
3844
3792
  login: login_default,
3845
3793
  logout: logout_default,
3846
3794
  whoami: whoami_default,
@@ -3852,13 +3800,12 @@ var main = defineCommand19({
3852
3800
  add: add_default,
3853
3801
  skills: skills_default,
3854
3802
  integrations: integrations_default,
3855
- "managed-repos": managed_repos_default,
3856
3803
  invoke: invoke_default,
3857
3804
  deploy: deploy_default,
3858
3805
  undeploy: undeploy_default,
3859
3806
  domain: domain_default,
3860
3807
  library: library_default,
3861
- admin: admin_default
3808
+ feedback: feedback_default
3862
3809
  }
3863
3810
  // No `run()` here — citty cascades parent run() AFTER subcommand finishes,
3864
3811
  // which corrupts agent-friendly output (`--json`) and prints noise on every