deepspace 0.10.2 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli/cli.ts
4
- import { defineCommand as defineCommand14, runMain, runCommand } from "citty";
4
+ import { defineCommand as defineCommand13, runMain, runCommand } from "citty";
5
5
  import { sync as spawnSync8 } from "cross-spawn";
6
- import { readFileSync as readFileSync28, existsSync as existsSync26 } from "fs";
7
- import { dirname as dirname10, join as join25 } from "path";
6
+ import { readFileSync as readFileSync28, existsSync as existsSync25 } from "fs";
7
+ import { dirname as dirname10, join as join24 } from "path";
8
8
  import { fileURLToPath as fileURLToPath3 } from "url";
9
9
 
10
10
  // src/cli/lib/spinner.ts
@@ -709,7 +709,7 @@ async function provisionProfile(jwt) {
709
709
  }
710
710
  }
711
711
  function sleep(ms) {
712
- return new Promise((resolve19) => setTimeout(resolve19, ms));
712
+ return new Promise((resolve18) => setTimeout(resolve18, ms));
713
713
  }
714
714
  function base64url(bytes) {
715
715
  return bytes.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
@@ -1267,7 +1267,7 @@ function upsertWorktreeLaunchConfig(mainRepoRoot, worktreeName, appDir, opts) {
1267
1267
  let port = opts.port;
1268
1268
  if (opts.probePort) {
1269
1269
  const taken = new Set(
1270
- config.configurations.map((c) => Number(c?.port)).filter((p35) => Number.isInteger(p35) && p35 > 0)
1270
+ config.configurations.map((c) => Number(c?.port)).filter((p34) => Number.isInteger(p34) && p34 > 0)
1271
1271
  );
1272
1272
  for (let i = 0; i < WORKTREE_PORT_RANGE && taken.has(port); i++) {
1273
1273
  port = WORKTREE_PORT_MIN + (port - WORKTREE_PORT_MIN + 1) % WORKTREE_PORT_RANGE;
@@ -1838,7 +1838,8 @@ async function refreshSecretsCache(deployUrl, token, appId, wranglerEnv) {
1838
1838
  return {
1839
1839
  pulled,
1840
1840
  rendered: renderSecretsCache(pulled.values, pulled),
1841
- summary: `Secrets: ${pulled.configName} (${count} secret${count === 1 ? "" : "s"})`
1841
+ // An empty store is the common case and not worth a status line.
1842
+ summary: count ? `Secrets: ${pulled.configName} (${count} secret${count === 1 ? "" : "s"})` : null
1842
1843
  };
1843
1844
  }
1844
1845
 
@@ -2289,18 +2290,18 @@ function ensureInstallReady(appDir) {
2289
2290
  const logPath = join9(sentinelDir, "install.log");
2290
2291
  if (existsSync9(errPath)) {
2291
2292
  const detail = readFileSync11(errPath, "utf-8").trimEnd();
2292
- const log29 = existsSync9(logPath) ? ` Full log: ${logPath}.` : "";
2293
+ const log28 = existsSync9(logPath) ? ` Full log: ${logPath}.` : "";
2293
2294
  throw new Refusal(
2294
- `Dependency install failed: ${detail}.${log29} Run \`npm install\` (or \`bun install\`) manually, then retry.`,
2295
+ `Dependency install failed: ${detail}.${log28} Run \`npm install\` (or \`bun install\`) manually, then retry.`,
2295
2296
  "install_failed",
2296
2297
  { action: { cwd: appDir, argv: [detectPackageManager(appDir), "install"] } }
2297
2298
  );
2298
2299
  }
2299
2300
  if (existsSync9(startedPath) && !existsSync9(donePath)) {
2300
2301
  if (!installWorkerAlive(sentinelDir)) {
2301
- const log29 = existsSync9(logPath) ? ` See what happened: ${logPath}.` : "";
2302
+ const log28 = existsSync9(logPath) ? ` See what happened: ${logPath}.` : "";
2302
2303
  throw new Refusal(
2303
- `The dependency install is no longer running and never finished.${log29} Run \`npm install\` (or \`bun install\`) manually, then retry.`,
2304
+ `The dependency install is no longer running and never finished.${log28} Run \`npm install\` (or \`bun install\`) manually, then retry.`,
2304
2305
  "install_failed",
2305
2306
  { action: { cwd: appDir, argv: [detectPackageManager(appDir), "install"] } }
2306
2307
  );
@@ -2449,7 +2450,7 @@ function lintSchema(schema) {
2449
2450
  const offendingRoles = Object.entries(schema.permissions).filter(([, perms]) => perms.read === true).map(([role]) => role);
2450
2451
  if (offendingRoles.length > 0) {
2451
2452
  const usesAware = Object.values(schema.permissions).some(
2452
- (p35) => typeof p35.read === "string" && VISIBILITY_AWARE.includes(p35.read)
2453
+ (p34) => typeof p34.read === "string" && VISIBILITY_AWARE.includes(p34.read)
2453
2454
  );
2454
2455
  if (!usesAware) {
2455
2456
  warnings.push(
@@ -2533,10 +2534,10 @@ function formatSchemaLintFindings(findings) {
2533
2534
  import { createServer } from "net";
2534
2535
  var DEFAULT_PORT = 5173;
2535
2536
  function checkPortAvailable(port, host = "0.0.0.0") {
2536
- return new Promise((resolve19) => {
2537
+ return new Promise((resolve18) => {
2537
2538
  const srv = createServer();
2538
- srv.once("error", () => resolve19(false));
2539
- srv.once("listening", () => srv.close(() => resolve19(true)));
2539
+ srv.once("error", () => resolve18(false));
2540
+ srv.once("listening", () => srv.close(() => resolve18(true)));
2540
2541
  srv.listen(port, host);
2541
2542
  });
2542
2543
  }
@@ -2664,7 +2665,7 @@ var dev_default = defineDeepspaceCommand({
2664
2665
  const refreshed = await refreshSecretsCache(DEPLOY_URL, token, appIdForSecrets, wranglerEnv);
2665
2666
  if (refreshed) {
2666
2667
  generatedSecretsCache = refreshed.rendered;
2667
- say(refreshed.summary);
2668
+ if (refreshed.summary) say(refreshed.summary);
2668
2669
  }
2669
2670
  } catch (err) {
2670
2671
  throw new Refusal(
@@ -3261,7 +3262,7 @@ var test_default = defineDeepspaceCommand({
3261
3262
  const refreshed = await refreshSecretsCache(DEPLOY_URL2, token, appIdForSecrets, wranglerEnv);
3262
3263
  if (refreshed) {
3263
3264
  generatedSecretsCache = refreshed.rendered;
3264
- say(refreshed.summary);
3265
+ if (refreshed.summary) say(refreshed.summary);
3265
3266
  }
3266
3267
  } catch (err) {
3267
3268
  throw new Refusal(
@@ -3714,6 +3715,7 @@ import { resolve as resolve12 } from "path";
3714
3715
  // src/cli/commands/deploy/build.ts
3715
3716
  import * as p6 from "@clack/prompts";
3716
3717
  import { execSync as execSync2 } from "child_process";
3718
+ import { createHash as createHash2 } from "crypto";
3717
3719
  import { existsSync as existsSync15, readFileSync as readFileSync17, readdirSync as readdirSync4 } from "fs";
3718
3720
  import { dirname as dirname5, join as join16, resolve as resolve10 } from "path";
3719
3721
 
@@ -4173,9 +4175,12 @@ function collectAssets(dir) {
4173
4175
  if (entry.isDirectory()) {
4174
4176
  walk(fullPath, relativePath);
4175
4177
  } else {
4178
+ const bytes = readFileSync17(fullPath);
4176
4179
  assets.push({
4177
4180
  path: `/${relativePath}`,
4178
- contentBase64: readFileSync17(fullPath).toString("base64")
4181
+ hash: createHash2("sha256").update(bytes).digest("hex"),
4182
+ size: bytes.byteLength,
4183
+ sourcePath: fullPath
4179
4184
  });
4180
4185
  }
4181
4186
  }
@@ -4462,7 +4467,7 @@ function createDeployOutput(json) {
4462
4467
 
4463
4468
  // src/cli/commands/deploy/request.ts
4464
4469
  import * as p10 from "@clack/prompts";
4465
- import { randomUUID as randomUUID2 } from "crypto";
4470
+ import { readFileSync as readFileSync18 } from "fs";
4466
4471
 
4467
4472
  // src/cli/commands/deploy/repository.ts
4468
4473
  import * as p9 from "@clack/prompts";
@@ -5172,7 +5177,7 @@ async function pushWithTransientRetry(push) {
5172
5177
  } catch (error) {
5173
5178
  const message = errorMessage3(error);
5174
5179
  if (/(?:HTTP |error: )(?:429|503)\b/i.test(message) && attempt < backoffMs.length) {
5175
- await new Promise((resolve19) => setTimeout(resolve19, backoffMs[attempt]));
5180
+ await new Promise((resolve18) => setTimeout(resolve18, backoffMs[attempt]));
5176
5181
  continue;
5177
5182
  }
5178
5183
  throw error;
@@ -5202,12 +5207,9 @@ function detachedHeadRefusal() {
5202
5207
 
5203
5208
  // src/cli/commands/deploy/request.ts
5204
5209
  var CLOUDFLARE_DEPLOY_ERROR_HINT = "Deployment reached the DeepSpace deploy worker, but Cloudflare's deployment control-plane API failed. This is often caused by a Cloudflare Dashboard/API incident or Workers for Platforms entitlement outage. Already deployed apps should keep serving; wait for Cloudflare to recover and retry.";
5205
- var MAX_GROUP_BYTES = 40 * 1024 * 1024;
5206
- var GROUP_BYTES = (() => {
5207
- const configured = Number(process.env.DEEPSPACE_DEPLOY_GROUP_BYTES);
5208
- const bytes = Number.isInteger(configured) && configured > 0 ? configured : 3 * 1024 * 1024;
5209
- return Math.min(bytes, MAX_GROUP_BYTES);
5210
- })();
5210
+ var DEPLOY_SERVICE_LIMIT_HINT = "The DeepSpace deploy service hit a resource limit processing this deploy (the deploy worker was terminated before it could answer). This is a DeepSpace-side failure, not a Cloudflare incident \u2014 your app was not changed. Retry; if it keeps happening, report the app id and asset count.";
5211
+ var REQUIRED_ASSET_TRANSPORT = "content-addressed-v1";
5212
+ var UPLOAD_CONCURRENCY = 4;
5211
5213
  async function deployBuiltBundle(options) {
5212
5214
  const {
5213
5215
  deployUrl,
@@ -5228,44 +5230,11 @@ async function deployBuiltBundle(options) {
5228
5230
  } else if (bundle.extraRoutes.length) {
5229
5231
  p10.log.info(`Custom worker-first routes: ${bundle.extraRoutes.join(", ")}`);
5230
5232
  }
5231
- const assetGroups = packAssetGroups(bundle.assets, GROUP_BYTES);
5232
- if (assetGroups.length === 0) assetGroups.push([]);
5233
- const uploadId = randomUUID2();
5234
- const totalGroups = assetGroups.length;
5235
- try {
5236
- for (let index = 0; index < totalGroups; index++) {
5237
- const groupJson = JSON.stringify(assetGroups[index]);
5238
- spinner2.message(`Uploading assets \u2014 group ${index + 1}/${totalGroups}...`);
5239
- const groupResponse = await postWithRetry(
5240
- `${deployUrl}/api/deploy/${appId}/assets?uploadId=${uploadId}&groupIndex=${index}&totalGroups=${totalGroups}`,
5241
- () => ({
5242
- method: "POST",
5243
- headers: {
5244
- Authorization: `Bearer ${token}`,
5245
- "Content-Type": "application/json"
5246
- },
5247
- body: groupJson
5248
- })
5249
- );
5250
- if (!groupResponse.ok) {
5251
- const errorBody = await groupResponse.json().catch(() => ({}));
5252
- await abortStagedUpload(deployUrl, appId, uploadId, totalGroups, token);
5253
- spinner2.stop("Deploy failed");
5254
- output.die(
5255
- `Asset upload failed on group ${index + 1}/${totalGroups}: ${errorBody.error ?? `HTTP ${groupResponse.status}`}`,
5256
- "upload_failed"
5257
- );
5258
- }
5259
- }
5260
- } catch (error) {
5261
- await abortStagedUpload(deployUrl, appId, uploadId, totalGroups, token);
5262
- spinner2.stop("Deploy failed");
5263
- output.die(`Asset upload failed (network): ${errorMessage4(error)}`, "upload_failed");
5264
- }
5233
+ await requireAssetTransport(deployUrl, spinner2, output);
5234
+ await uploadDeployAssets({ deployUrl, appId, token, assets: bundle.assets, output, spinner: spinner2 });
5265
5235
  spinner2.message(`Deploying ${appName}...`);
5266
5236
  let confirmRename = options.rename;
5267
5237
  const bail = async (message, stopLabel = "Deploy failed", code, actionRequired = false, action) => {
5268
- await abortStagedUpload(deployUrl, appId, uploadId, totalGroups, token);
5269
5238
  if (stopLabel !== null) spinner2.stop(stopLabel);
5270
5239
  p10.cancel(code ? withSlug(message, code) : message);
5271
5240
  if (action) printAction(action);
@@ -5287,8 +5256,7 @@ async function deployBuiltBundle(options) {
5287
5256
  new Blob([bundle.workerJs], { type: "application/javascript" }),
5288
5257
  "worker.js"
5289
5258
  );
5290
- form.append("uploadId", uploadId);
5291
- form.append("totalGroups", String(totalGroups));
5259
+ form.append("assetManifest", JSON.stringify(assetManifest(bundle.assets)));
5292
5260
  form.append("appMigrations", JSON.stringify(bundle.appMigrations));
5293
5261
  if (bundle.doManifest) form.append("doManifest", JSON.stringify(bundle.doManifest));
5294
5262
  if (bundle.customBindings.length) {
@@ -5367,7 +5335,11 @@ async function deployBuiltBundle(options) {
5367
5335
  );
5368
5336
  }
5369
5337
  if (!response.ok || !body.success) {
5370
- await bail(formatDeployWorkerError(response.status, body.error), "Deploy failed", body.code);
5338
+ await bail(
5339
+ formatDeployWorkerError(response.status, body.error, body.code),
5340
+ "Deploy failed",
5341
+ body.code
5342
+ );
5371
5343
  }
5372
5344
  if (body.onBehalfOfOwner) {
5373
5345
  p10.log.warn(`Deployed on behalf of owner ${body.onBehalfOfOwner}`);
@@ -5384,17 +5356,139 @@ async function deployBuiltBundle(options) {
5384
5356
  }
5385
5357
  return body;
5386
5358
  }
5387
- async function abortStagedUpload(deployUrl, appId, uploadId, totalGroups, token) {
5359
+ function assetManifest(assets) {
5360
+ return assets.map((asset) => ({ path: asset.path, hash: asset.hash, size: asset.size }));
5361
+ }
5362
+ async function requireAssetTransport(deployUrl, spinner2, output) {
5363
+ let advertised;
5388
5364
  try {
5389
- await fetch(
5390
- `${deployUrl}/api/deploy/${appId}/assets?uploadId=${uploadId}&totalGroups=${totalGroups}`,
5391
- { method: "DELETE", headers: { Authorization: `Bearer ${token}` } }
5365
+ const response = await fetch(`${deployUrl}/api/health`);
5366
+ if (!response.ok) throw new Error(`HTTP ${response.status}`);
5367
+ const body = await response.json();
5368
+ advertised = body.capabilities?.assetTransport;
5369
+ } catch (error) {
5370
+ spinner2.stop("Deploy failed");
5371
+ output.die(
5372
+ `Could not reach the DeepSpace deploy service at ${deployUrl} to check its capabilities: ${errorMessage4(error)}`,
5373
+ "deploy_service_unreachable"
5374
+ );
5375
+ }
5376
+ if (advertised !== REQUIRED_ASSET_TRANSPORT) {
5377
+ spinner2.stop("Deploy failed");
5378
+ output.die(
5379
+ `The DeepSpace deploy service at ${deployUrl} does not support this CLI's asset transport (needs "${REQUIRED_ASSET_TRANSPORT}", found ${advertised === void 0 ? "none" : `"${String(advertised)}"`}). Wait for the platform to finish updating, or pin an older deepspace CLI.`,
5380
+ "asset_transport_unsupported"
5392
5381
  );
5393
- } catch {
5394
5382
  }
5395
5383
  }
5396
- function formatDeployWorkerError(status3, error) {
5384
+ async function uploadDeployAssets(options) {
5385
+ const { deployUrl, appId, token, assets, spinner: spinner2 } = options;
5386
+ const output = options.output;
5387
+ const byHash = new Map(assets.map((asset) => [asset.hash, asset]));
5388
+ spinner2.message("Checking which assets are already uploaded...");
5389
+ let planResponse;
5390
+ try {
5391
+ planResponse = await postWithRetry(`${deployUrl}/api/deploy/${appId}/asset-plan`, () => ({
5392
+ method: "POST",
5393
+ headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
5394
+ body: JSON.stringify({
5395
+ assets: [...byHash.values()].map((asset) => ({ hash: asset.hash, size: asset.size }))
5396
+ })
5397
+ }));
5398
+ } catch (error) {
5399
+ spinner2.stop("Deploy failed");
5400
+ output.die(`Asset plan failed (network): ${errorMessage4(error)}`, "upload_failed");
5401
+ }
5402
+ const planBody = await planResponse.json().catch(() => ({}));
5403
+ if (!planResponse.ok) {
5404
+ spinner2.stop("Deploy failed");
5405
+ output.die(
5406
+ formatDeployWorkerError(planResponse.status, planBody.error, planBody.code),
5407
+ planBody.code ?? "upload_failed"
5408
+ );
5409
+ }
5410
+ const missing = [];
5411
+ for (const hash of planBody.missing ?? []) {
5412
+ const asset = byHash.get(hash);
5413
+ if (!asset) {
5414
+ spinner2.stop("Deploy failed");
5415
+ output.die(
5416
+ `The deploy service asked for asset ${hash}, which is not part of this build. Re-run the deploy; if it persists, report the app id.`,
5417
+ "upload_failed"
5418
+ );
5419
+ }
5420
+ missing.push(asset);
5421
+ }
5422
+ if (missing.length === 0) {
5423
+ p10.log.info(`Assets: ${byHash.size} file(s), all already uploaded`);
5424
+ return;
5425
+ }
5426
+ const missingBytes = missing.reduce((total, asset) => total + asset.size, 0);
5427
+ p10.log.info(
5428
+ `Assets: ${byHash.size} file(s), uploading ${missing.length} (${Math.ceil(missingBytes / 1024)} KiB); the rest are already stored`
5429
+ );
5430
+ let uploaded = 0;
5431
+ const next = () => missing.pop();
5432
+ const worker = async () => {
5433
+ for (let asset = next(); asset; asset = next()) {
5434
+ const response = await postWithRetry(
5435
+ `${deployUrl}/api/deploy/${appId}/assets/${asset.hash}`,
5436
+ () => ({
5437
+ method: "PUT",
5438
+ headers: {
5439
+ Authorization: `Bearer ${token}`,
5440
+ "Content-Type": "application/octet-stream"
5441
+ },
5442
+ // Read whole, per attempt. The platform matches Content-Length
5443
+ // against the plan before it touches storage, and a stream body
5444
+ // would be sent chunked with no length at all; a retry also needs a
5445
+ // body it can send again.
5446
+ body: readFileSync18(asset.sourcePath)
5447
+ })
5448
+ );
5449
+ if (!response.ok) {
5450
+ const body = await response.json().catch(() => ({}));
5451
+ throw new AssetUploadError(
5452
+ body.error ?? `Upload of ${asset.path} failed: HTTP ${response.status}`,
5453
+ body.code ?? "upload_failed",
5454
+ response.status
5455
+ );
5456
+ }
5457
+ uploaded++;
5458
+ spinner2.message(`Uploading assets \u2014 ${uploaded}/${uploaded + missing.length}...`);
5459
+ }
5460
+ };
5461
+ try {
5462
+ await Promise.all(
5463
+ Array.from({ length: Math.min(UPLOAD_CONCURRENCY, missing.length) }, worker)
5464
+ );
5465
+ } catch (error) {
5466
+ spinner2.stop("Deploy failed");
5467
+ if (error instanceof AssetUploadError) {
5468
+ output.die(formatDeployWorkerError(error.status, error.message, error.code), error.code);
5469
+ }
5470
+ output.die(`Asset upload failed (network): ${errorMessage4(error)}`, "upload_failed");
5471
+ }
5472
+ }
5473
+ var AssetUploadError = class extends Error {
5474
+ constructor(message, code, status3) {
5475
+ super(message);
5476
+ this.code = code;
5477
+ this.status = status3;
5478
+ }
5479
+ };
5480
+ function isDeployServiceResourceLimit(status3, error) {
5481
+ if (!error) return status3 === 500 || status3 === 502;
5482
+ return /\b110[12]\b/.test(error) && /worker|error code/i.test(error);
5483
+ }
5484
+ function formatDeployWorkerError(status3, error, code) {
5397
5485
  const detail = error ?? `Deployment error (${status3})`;
5486
+ if (code === "cli_outdated") return detail;
5487
+ if (isDeployServiceResourceLimit(status3, error)) {
5488
+ return `${DEPLOY_SERVICE_LIMIT_HINT}
5489
+
5490
+ Underlying error: ${detail}`;
5491
+ }
5398
5492
  if (status3 < 500 && ![
5399
5493
  "Upload session failed",
5400
5494
  "Asset upload failed",
@@ -5411,23 +5505,6 @@ Underlying error: ${detail}`;
5411
5505
  function errorMessage4(error) {
5412
5506
  return error instanceof Error ? error.message : String(error);
5413
5507
  }
5414
- function packAssetGroups(assets, maxBytes) {
5415
- const groups = [];
5416
- let current = [];
5417
- let currentBytes = 2;
5418
- for (const asset of assets) {
5419
- const entryBytes = Buffer.byteLength(JSON.stringify(asset), "utf-8") + 1;
5420
- if (current.length > 0 && currentBytes + entryBytes > maxBytes) {
5421
- groups.push(current);
5422
- current = [];
5423
- currentBytes = 2;
5424
- }
5425
- current.push(asset);
5426
- currentBytes += entryBytes;
5427
- }
5428
- if (current.length > 0) groups.push(current);
5429
- return groups;
5430
- }
5431
5508
  async function postWithRetry(url, makeInit, {
5432
5509
  attempts = 4,
5433
5510
  retryServerErrors = true
@@ -5444,7 +5521,7 @@ async function postWithRetry(url, makeInit, {
5444
5521
  lastError = error;
5445
5522
  }
5446
5523
  if (attempt < attempts) {
5447
- await new Promise((resolve19) => setTimeout(resolve19, Math.min(8e3, 500 * 2 ** (attempt - 1))));
5524
+ await new Promise((resolve18) => setTimeout(resolve18, Math.min(8e3, 500 * 2 ** (attempt - 1))));
5448
5525
  }
5449
5526
  }
5450
5527
  if (lastResponse) return lastResponse;
@@ -5453,7 +5530,7 @@ async function postWithRetry(url, makeInit, {
5453
5530
 
5454
5531
  // src/cli/commands/deploy/secrets.ts
5455
5532
  import * as p11 from "@clack/prompts";
5456
- import { existsSync as existsSync18, readFileSync as readFileSync18 } from "fs";
5533
+ import { existsSync as existsSync18, readFileSync as readFileSync19 } from "fs";
5457
5534
  function classifyDevVarsSecrets(options) {
5458
5535
  const store = new Set(options.storeSecretNames);
5459
5536
  const strayKeys = options.handEditedDevVarKeys.filter((key) => !store.has(key));
@@ -5480,7 +5557,7 @@ async function loadDeploySecrets(options) {
5480
5557
  generatedSecretsCache: refreshed.rendered,
5481
5558
  sharedDevVarsCache: true
5482
5559
  });
5483
- p11.log.info(refreshed.summary);
5560
+ if (refreshed.summary) p11.log.info(refreshed.summary);
5484
5561
  }
5485
5562
  } catch (error) {
5486
5563
  if (error?.status === 403) {
@@ -5552,7 +5629,7 @@ function prepareDeploySecrets(options) {
5552
5629
  }
5553
5630
  function readCustomDevVars(path, output) {
5554
5631
  if (!existsSync18(path)) return {};
5555
- const section = extractCustomDevVars(stripGeneratedSecretsCache(readFileSync18(path, "utf-8")));
5632
+ const section = extractCustomDevVars(stripGeneratedSecretsCache(readFileSync19(path, "utf-8")));
5556
5633
  if (!section) return {};
5557
5634
  try {
5558
5635
  return parseDevVars(section);
@@ -5826,7 +5903,7 @@ async function waitForAssetsReady(url, timeoutMs) {
5826
5903
  if (!body.includes("Assets have not yet deployed") && !body.includes("No app configured")) {
5827
5904
  streak++;
5828
5905
  if (streak >= 3) return true;
5829
- await new Promise((resolve19) => setTimeout(resolve19, 1500));
5906
+ await new Promise((resolve18) => setTimeout(resolve18, 1500));
5830
5907
  continue;
5831
5908
  }
5832
5909
  streak = 0;
@@ -5834,7 +5911,7 @@ async function waitForAssetsReady(url, timeoutMs) {
5834
5911
  streak = 0;
5835
5912
  }
5836
5913
  const waitMs = Math.min(8e3, 1e3 * 2 ** (attempt - 1));
5837
- await new Promise((resolve19) => setTimeout(resolve19, waitMs));
5914
+ await new Promise((resolve18) => setTimeout(resolve18, waitMs));
5838
5915
  }
5839
5916
  return false;
5840
5917
  }
@@ -6127,12 +6204,20 @@ var apps_default = defineDeepspaceCommand({
6127
6204
  if (!apps.length) {
6128
6205
  console.log("No apps yet. Create one with `npx create-deepspace <name>` and `deepspace deploy`.");
6129
6206
  } else {
6130
- const nameWidth = Math.max(4, ...apps.map((a) => (a.name ?? "\u2014").length));
6131
- const idWidth = Math.max(6, ...apps.map((a) => a.appId.length));
6132
- console.log(`${"NAME".padEnd(nameWidth)} ${"APP ID".padEnd(idWidth)} URL`);
6133
- for (const a of apps) {
6207
+ const rows = [...apps].sort(
6208
+ (left, right) => Number(right.status !== "undeployed") - Number(left.status !== "undeployed")
6209
+ );
6210
+ const nameWidth = Math.max(4, ...rows.map((a) => (a.name ?? "\u2014").length));
6211
+ const statusWidth = Math.max(6, ...rows.map((a) => a.status.length));
6212
+ const idWidth = Math.max(6, ...rows.map((a) => a.appId.length));
6213
+ console.log(
6214
+ `${"NAME".padEnd(nameWidth)} ${"STATUS".padEnd(statusWidth)} ${"APP ID".padEnd(idWidth)} URL`
6215
+ );
6216
+ for (const a of rows) {
6134
6217
  const url = a.url ?? "(not deployed)";
6135
- console.log(`${(a.name ?? "\u2014").padEnd(nameWidth)} ${a.appId.padEnd(idWidth)} ${url}`);
6218
+ console.log(
6219
+ `${(a.name ?? "\u2014").padEnd(nameWidth)} ${a.status.padEnd(statusWidth)} ${a.appId.padEnd(idWidth)} ${url}`
6220
+ );
6136
6221
  }
6137
6222
  }
6138
6223
  }
@@ -6470,7 +6555,7 @@ var usage_default = defineDeepspaceCommand({
6470
6555
  });
6471
6556
 
6472
6557
  // src/cli/commands/add.ts
6473
- import { existsSync as existsSync20, readFileSync as readFileSync20, realpathSync as realpathSync3 } from "fs";
6558
+ import { existsSync as existsSync20, readFileSync as readFileSync21, realpathSync as realpathSync3 } from "fs";
6474
6559
  import { dirname as dirname7, join as join19, resolve as resolve14 } from "path";
6475
6560
  import { pathToFileURL as pathToFileURL3 } from "url";
6476
6561
 
@@ -6483,7 +6568,7 @@ import {
6483
6568
  mkdirSync as mkdirSync6,
6484
6569
  mkdtempSync,
6485
6570
  openSync as openSync2,
6486
- readFileSync as readFileSync19,
6571
+ readFileSync as readFileSync20,
6487
6572
  readSync,
6488
6573
  readdirSync as readdirSync5,
6489
6574
  rmSync as rmSync4,
@@ -6500,7 +6585,7 @@ function featurePackageRoot(moduleUrl = import.meta.url) {
6500
6585
  const packagePath = join18(dir, "package.json");
6501
6586
  if (existsSync19(packagePath)) {
6502
6587
  try {
6503
- const pkg2 = JSON.parse(readFileSync19(packagePath, "utf-8"));
6588
+ const pkg2 = JSON.parse(readFileSync20(packagePath, "utf-8"));
6504
6589
  if (pkg2.name === "deepspace") return dir;
6505
6590
  } catch {
6506
6591
  }
@@ -6517,7 +6602,7 @@ function readFeatureConfig(id, packageRoot = featurePackageRoot()) {
6517
6602
  const configPath = join18(packageRoot, "features", id, "feature.json");
6518
6603
  if (!existsSync19(configPath)) return null;
6519
6604
  try {
6520
- const config = JSON.parse(readFileSync19(configPath, "utf-8"));
6605
+ const config = JSON.parse(readFileSync20(configPath, "utf-8"));
6521
6606
  if (typeof config.id !== "string" || typeof config.name !== "string" || !Array.isArray(config.files)) {
6522
6607
  return null;
6523
6608
  }
@@ -6582,7 +6667,7 @@ function copyFile(src, dest) {
6582
6667
  function copyFileWithImportShift(src, dest, levels) {
6583
6668
  mkdirSync6(dirname6(dest), { recursive: true });
6584
6669
  const prefix = "../".repeat(levels);
6585
- const shifted = readFileSync19(src, "utf-8").replace(
6670
+ const shifted = readFileSync20(src, "utf-8").replace(
6586
6671
  /(from\s+|import\s+|import\()(['"])(\.\.\/)/g,
6587
6672
  `$1$2${prefix}$3`
6588
6673
  );
@@ -6641,7 +6726,7 @@ function integrateSchema(config, targetDir, emit) {
6641
6726
  if (!existsSync19(schemasPath)) {
6642
6727
  return [unresolvedSchema(config.schema, "src/schemas.ts was not found.", emit)];
6643
6728
  }
6644
- let content = readFileSync19(schemasPath, "utf-8");
6729
+ let content = readFileSync20(schemasPath, "utf-8");
6645
6730
  const { exportName, importPath, spreadOperator } = config.schema;
6646
6731
  const importPattern = new RegExp(`^import\\s+\\{[^}]*\\b${exportName}\\b`, "m");
6647
6732
  if (importPattern.test(content)) {
@@ -6698,7 +6783,7 @@ function integrateActions(config, targetDir, emit) {
6698
6783
  if (!existsSync19(actionsPath)) {
6699
6784
  return [unresolvedActions(config.actions, "src/actions/index.ts was not found.", emit)];
6700
6785
  }
6701
- let content = readFileSync19(actionsPath, "utf-8");
6786
+ let content = readFileSync20(actionsPath, "utf-8");
6702
6787
  const registryPattern = /export const actions:\s*Record<string,\s*ActionHandler(?:<[^>]*>)?>\s*=\s*\{/;
6703
6788
  if (!registryPattern.test(content)) {
6704
6789
  const reason = "src/actions/index.ts has an unexpected structure.";
@@ -6753,7 +6838,7 @@ function integrateCode(config, targetDir, emit) {
6753
6838
  });
6754
6839
  continue;
6755
6840
  }
6756
- const original = readFileSync19(targetPath, "utf-8");
6841
+ const original = readFileSync20(targetPath, "utf-8");
6757
6842
  if (original.includes(insertion.insert.trim())) {
6758
6843
  emit(` Integration already present: ${insertion.file}`);
6759
6844
  continue;
@@ -6789,7 +6874,7 @@ ${content.slice(importIndex < 0 ? 0 : importIndex)}`;
6789
6874
  function integrateIgnore(config, targetDir) {
6790
6875
  if (!config.ignore?.length) return;
6791
6876
  const targetPath = join18(targetDir, ".gitignore");
6792
- const current = existsSync19(targetPath) ? readFileSync19(targetPath, "utf-8") : "";
6877
+ const current = existsSync19(targetPath) ? readFileSync20(targetPath, "utf-8") : "";
6793
6878
  const present = new Set(current.split(/\r?\n/).map((line) => line.trim()));
6794
6879
  const missing = config.ignore.filter((pattern) => !present.has(pattern));
6795
6880
  if (missing.length === 0) return;
@@ -6809,7 +6894,7 @@ function integrateWrangler(config, targetDir, emit) {
6809
6894
  if (!existsSync19(targetPath)) {
6810
6895
  return [{ area: "wrangler", reason: "wrangler.toml was not found.", steps }];
6811
6896
  }
6812
- let source = readFileSync19(targetPath, "utf-8");
6897
+ let source = readFileSync20(targetPath, "utf-8");
6813
6898
  if (runWorkerFirst && !/^\[assets\]\s*$/m.test(source)) {
6814
6899
  return [{ area: "wrangler", reason: "wrangler.toml has no [assets] section.", steps }];
6815
6900
  }
@@ -6898,7 +6983,7 @@ function integrateCss(packageRoot, config, targetDir, emit) {
6898
6983
  }
6899
6984
  ];
6900
6985
  }
6901
- let styles = readFileSync19(stylesPath, "utf-8");
6986
+ let styles = readFileSync20(stylesPath, "utf-8");
6902
6987
  let integrated = 0;
6903
6988
  const unresolved = [];
6904
6989
  for (const cssFile of config.css) {
@@ -6912,7 +6997,7 @@ function integrateCss(packageRoot, config, targetDir, emit) {
6912
6997
  });
6913
6998
  continue;
6914
6999
  }
6915
- const css = readFileSync19(srcPath, "utf-8");
7000
+ const css = readFileSync20(srcPath, "utf-8");
6916
7001
  const fingerprint = css.match(/\.([\w-]+)\s*\{|@keyframes\s+([\w-]+)/);
6917
7002
  const marker = fingerprint?.[1] ?? fingerprint?.[2];
6918
7003
  if (marker && styles.includes(marker)) {
@@ -6943,7 +7028,7 @@ function integrateRoute(config, targetDir, emit) {
6943
7028
  if (!existsSync19(navPath)) {
6944
7029
  return [unresolvedRoute(config.route, config, "src/nav.ts was not found.", emit)];
6945
7030
  }
6946
- let content = readFileSync19(navPath, "utf-8");
7031
+ let content = readFileSync20(navPath, "utf-8");
6947
7032
  const routePath = config.route.path;
6948
7033
  if (content.includes(`'${routePath}'`)) {
6949
7034
  emit(` Nav already present: ${routePath}`);
@@ -7024,7 +7109,7 @@ function integrateDependencies(config, targetDir, runInstall, outputVisible, emi
7024
7109
  }
7025
7110
  let pkg2;
7026
7111
  try {
7027
- pkg2 = JSON.parse(readFileSync19(packagePath, "utf-8"));
7112
+ pkg2 = JSON.parse(readFileSync20(packagePath, "utf-8"));
7028
7113
  } catch (error) {
7029
7114
  emit(
7030
7115
  ` Could not patch package.json (parse error: ${error instanceof Error ? error.message : String(error)})`
@@ -7084,7 +7169,7 @@ ${child.diagnosticTail}` : "";
7084
7169
  }
7085
7170
  function dependencySnapshot(targetDir) {
7086
7171
  try {
7087
- const pkg2 = JSON.parse(readFileSync19(join18(targetDir, "package.json"), "utf-8"));
7172
+ const pkg2 = JSON.parse(readFileSync20(join18(targetDir, "package.json"), "utf-8"));
7088
7173
  return {
7089
7174
  dependencies: pkg2.dependencies ?? {},
7090
7175
  devDependencies: pkg2.devDependencies ?? {}
@@ -7333,7 +7418,7 @@ function isDeepSpaceApp(dir) {
7333
7418
  const packagePath = join19(dir, "package.json");
7334
7419
  if (!existsSync20(packagePath)) return false;
7335
7420
  try {
7336
- const pkg2 = JSON.parse(readFileSync20(packagePath, "utf-8"));
7421
+ const pkg2 = JSON.parse(readFileSync21(packagePath, "utf-8"));
7337
7422
  return Boolean(pkg2.dependencies?.deepspace || pkg2.devDependencies?.deepspace);
7338
7423
  } catch {
7339
7424
  return false;
@@ -7536,11 +7621,11 @@ function fmtDate(iso) {
7536
7621
  }
7537
7622
  async function confirm4(message) {
7538
7623
  process.stdout.write(`${message} [y/N] `);
7539
- return new Promise((resolve19) => {
7624
+ return new Promise((resolve18) => {
7540
7625
  process.stdin.setEncoding("utf-8");
7541
7626
  process.stdin.once("data", (data) => {
7542
7627
  const answer = data.toString().trim().toLowerCase();
7543
- resolve19(answer === "y" || answer === "yes");
7628
+ resolve18(answer === "y" || answer === "yes");
7544
7629
  });
7545
7630
  });
7546
7631
  }
@@ -7867,8 +7952,8 @@ var list3 = defineDeepspaceCommand({
7867
7952
  }
7868
7953
  if (pending.length) {
7869
7954
  console.log(`PENDING INVITES ON ${app2}`);
7870
- for (const p35 of pending) {
7871
- console.log(` ${p35.email} (expires ${new Date(p35.expiresAt).toLocaleDateString()})`);
7955
+ for (const p34 of pending) {
7956
+ console.log(` ${p34.email} (expires ${new Date(p34.expiresAt).toLocaleDateString()})`);
7872
7957
  }
7873
7958
  }
7874
7959
  }
@@ -7966,7 +8051,7 @@ var cancel3 = defineDeepspaceCommand({
7966
8051
  `/api/app-collaborators/${encodeURIComponent(app2)}`
7967
8052
  );
7968
8053
  const target = email.trim().toLowerCase();
7969
- const found = pending.find((p35) => p35.email.toLowerCase() === target);
8054
+ const found = pending.find((p34) => p34.email.toLowerCase() === target);
7970
8055
  if (!found) {
7971
8056
  throw new Refusal(`${email} has no pending invite on ${app2}`, "no_pending_invite", {
7972
8057
  action: cliAction("deepspace", "app", "collaborators", "list", "--app", app2)
@@ -8116,7 +8201,7 @@ var transfer_default = defineCommand7({
8116
8201
  import { defineCommand as defineCommand8 } from "citty";
8117
8202
 
8118
8203
  // src/cli/commands/_invoke-impl.ts
8119
- import { readFileSync as readFileSync21 } from "fs";
8204
+ import { readFileSync as readFileSync22 } from "fs";
8120
8205
  import * as p15 from "@clack/prompts";
8121
8206
  var API_URL7 = process.env.DEEPSPACE_API_URL ?? PLATFORM_URLS.api;
8122
8207
  var DEFAULT_TIMEOUT_MS = 12e4;
@@ -8157,7 +8242,7 @@ function resolveBody(opts) {
8157
8242
  if (opts.body != null) {
8158
8243
  raw = opts.body;
8159
8244
  } else if (opts.bodyFile != null) {
8160
- raw = opts.bodyFile === "-" ? readFileSync21(0, "utf-8") : readFileSync21(opts.bodyFile, "utf-8");
8245
+ raw = opts.bodyFile === "-" ? readFileSync22(0, "utf-8") : readFileSync22(opts.bodyFile, "utf-8");
8161
8246
  } else {
8162
8247
  return "{}";
8163
8248
  }
@@ -8434,227 +8519,10 @@ var integrations_default = defineCommand8({
8434
8519
  }
8435
8520
  });
8436
8521
 
8437
- // src/cli/commands/library.ts
8438
- import { defineCommand as defineCommand9 } from "citty";
8439
- import { existsSync as existsSync21, readFileSync as readFileSync22 } from "fs";
8440
- import { join as join20, resolve as resolve15 } from "path";
8441
- import { parse as parseToml4 } from "smol-toml";
8442
- import * as p16 from "@clack/prompts";
8443
- var DEFAULT_LIBRARY_APP = "deepdotspace-site";
8444
- var str = (v) => typeof v === "string" && v ? v : void 0;
8445
- var publish = defineDeepspaceCommand({
8446
- meta: {
8447
- name: "publish",
8448
- description: "Publish the current app to the DeepSpace library"
8449
- },
8450
- args: {
8451
- dir: {
8452
- type: "string",
8453
- description: "App directory (default: current directory)",
8454
- required: false
8455
- },
8456
- app: {
8457
- type: "string",
8458
- description: "App name (default: read from wrangler.toml)",
8459
- required: false
8460
- },
8461
- name: {
8462
- type: "string",
8463
- description: "Display name (default: app name)",
8464
- required: false
8465
- },
8466
- description: {
8467
- type: "string",
8468
- description: "Short description",
8469
- required: false
8470
- },
8471
- category: {
8472
- type: "string",
8473
- description: "Category (e.g. Productivity, Finance, AI). Default: General",
8474
- required: false
8475
- },
8476
- tags: {
8477
- type: "string",
8478
- description: "Comma-separated tags",
8479
- required: false
8480
- },
8481
- visibility: {
8482
- type: "string",
8483
- description: "'public' (default), 'unlisted', or 'private'",
8484
- required: false
8485
- },
8486
- screenshot: {
8487
- type: "string",
8488
- description: "Override the auto-captured preview with a public PNG URL",
8489
- required: false
8490
- },
8491
- "library-app": {
8492
- type: "string",
8493
- description: `Target library app subdomain (default: ${DEFAULT_LIBRARY_APP})`,
8494
- required: false
8495
- }
8496
- },
8497
- async run({ args }) {
8498
- const json = args.json;
8499
- const intro6 = (s) => {
8500
- if (!json) p16.intro(s);
8501
- };
8502
- const info2 = (s) => {
8503
- if (!json) p16.log.info(s);
8504
- };
8505
- intro6("Publishing to the DeepSpace library");
8506
- const appErr = parseAppArg(str(args.app)).error;
8507
- if (appErr) throw new Refusal(appErr, "invalid_app");
8508
- let appName = str(args.app)?.trim();
8509
- if (!appName) {
8510
- const appDir = resolve15(str(args.dir) ?? ".");
8511
- const wranglerPath = join20(appDir, "wrangler.toml");
8512
- if (!existsSync21(wranglerPath)) {
8513
- throw new Refusal(
8514
- "No --app provided and no wrangler.toml found. Either pass --app <name> or run from your app's directory.",
8515
- "not_in_app_repo"
8516
- );
8517
- }
8518
- const cfg = parseToml4(readFileSync22(wranglerPath, "utf-8"));
8519
- const nameRes = resolveAppName(cfg.name);
8520
- if (!nameRes.ok) throw new Refusal(`wrangler.toml: ${nameRes.reason}`, "invalid_config");
8521
- appName = nameRes.name;
8522
- }
8523
- info2(`App: ${appName}`);
8524
- const visibility = str(args.visibility) ?? "public";
8525
- if (!["public", "private", "unlisted"].includes(visibility)) {
8526
- throw new Refusal("--visibility must be 'public', 'unlisted', or 'private'.", "invalid_visibility");
8527
- }
8528
- const tags = str(args.tags) ? String(args.tags).split(",").map((t) => t.trim()).filter(Boolean) : void 0;
8529
- const libraryApp = str(args["library-app"]) ?? DEFAULT_LIBRARY_APP;
8530
- const libraryHost = process.env.DEEPSPACE_LIBRARY_HOST ?? `https://${libraryApp}.app.space`;
8531
- let token;
8532
- try {
8533
- token = await ensureToken();
8534
- } catch (err) {
8535
- throw new Refusal(err instanceof Error ? err.message : String(err), "not_authenticated", {
8536
- action: cliAction("deepspace", "auth", "login")
8537
- });
8538
- }
8539
- const payload = {
8540
- appName,
8541
- ...args.name ? { name: args.name } : {},
8542
- ...args.description ? { description: args.description } : {},
8543
- ...args.category ? { category: args.category } : {},
8544
- ...tags ? { tags } : {},
8545
- visibility,
8546
- ...args.screenshot ? { screenshotUrl: args.screenshot } : {}
8547
- };
8548
- const url = `${libraryHost}/api/actions/library.publish`;
8549
- let res;
8550
- try {
8551
- res = await fetch(url, {
8552
- method: "POST",
8553
- headers: {
8554
- "Content-Type": "application/json",
8555
- Authorization: `Bearer ${token}`
8556
- },
8557
- body: JSON.stringify(payload)
8558
- });
8559
- } catch (err) {
8560
- throw new Refusal(
8561
- `Network error reaching ${url}: ${err instanceof Error ? err.message : String(err)}`,
8562
- "network_error"
8563
- );
8564
- }
8565
- const body = await res.text();
8566
- let parsed;
8567
- try {
8568
- parsed = JSON.parse(body);
8569
- } catch {
8570
- throw new Refusal(`Server returned non-JSON (${res.status}): ${body.slice(0, 400)}`, "invalid_response");
8571
- }
8572
- if (!parsed.success) {
8573
- throw new Refusal(parsed.error ?? `Publish failed (HTTP ${res.status}).`, "publish_failed");
8574
- }
8575
- if (!json) {
8576
- p16.log.success(`Published ${appName} as ${parsed.data?.templateHandle} (v${parsed.data?.version})`);
8577
- if (parsed.data?.url) p16.log.message(parsed.data.url);
8578
- p16.outro("Done");
8579
- }
8580
- return {
8581
- data: {
8582
- appName,
8583
- templateHandle: parsed.data?.templateHandle ?? null,
8584
- url: parsed.data?.url ?? null,
8585
- version: parsed.data?.version ?? null,
8586
- visibility
8587
- }
8588
- };
8589
- }
8590
- });
8591
- var unpublish = defineDeepspaceCommand({
8592
- meta: {
8593
- name: "unpublish",
8594
- description: "Remove a library entry (owner or admin only)"
8595
- },
8596
- args: {
8597
- handle: {
8598
- type: "positional",
8599
- description: "templateHandle to remove (usually your app name)",
8600
- required: true
8601
- },
8602
- "library-app": {
8603
- type: "string",
8604
- description: `Target library app subdomain (default: ${DEFAULT_LIBRARY_APP})`,
8605
- required: false
8606
- }
8607
- },
8608
- async run({ args }) {
8609
- const json = args.json;
8610
- if (!json) p16.intro("Unpublishing library entry");
8611
- let token;
8612
- try {
8613
- token = await ensureToken();
8614
- } catch (err) {
8615
- throw new Refusal(err instanceof Error ? err.message : String(err), "not_authenticated", {
8616
- action: cliAction("deepspace", "auth", "login")
8617
- });
8618
- }
8619
- const libraryApp = str(args["library-app"]) ?? DEFAULT_LIBRARY_APP;
8620
- const libraryHost = process.env.DEEPSPACE_LIBRARY_HOST ?? `https://${libraryApp}.app.space`;
8621
- const res = await fetch(`${libraryHost}/api/actions/library.unpublish`, {
8622
- method: "POST",
8623
- headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` },
8624
- body: JSON.stringify({ templateHandle: String(args.handle) })
8625
- });
8626
- const body = await res.text();
8627
- let parsed;
8628
- try {
8629
- parsed = JSON.parse(body);
8630
- } catch {
8631
- throw new Refusal(`Server returned non-JSON (${res.status}): ${body.slice(0, 400)}`, "invalid_response");
8632
- }
8633
- if (!parsed.success) {
8634
- throw new Refusal(parsed.error ?? `HTTP ${res.status}`, "unpublish_failed");
8635
- }
8636
- if (!json) {
8637
- p16.log.success(`Unpublished ${parsed.data?.templateHandle}`);
8638
- p16.outro("Done");
8639
- }
8640
- return { data: { templateHandle: parsed.data?.templateHandle ?? String(args.handle) } };
8641
- }
8642
- });
8643
- var library_default = defineCommand9({
8644
- meta: {
8645
- name: "library",
8646
- description: "Manage your DeepSpace library entries"
8647
- },
8648
- subCommands: {
8649
- publish,
8650
- unpublish
8651
- }
8652
- });
8653
-
8654
8522
  // src/cli/commands/feedback.ts
8655
- import * as p17 from "@clack/prompts";
8656
- import { existsSync as existsSync22, readFileSync as readFileSync23 } from "fs";
8657
- import { dirname as dirname8, join as join21 } from "path";
8523
+ import * as p16 from "@clack/prompts";
8524
+ import { existsSync as existsSync21, readFileSync as readFileSync23 } from "fs";
8525
+ import { dirname as dirname8, join as join20 } from "path";
8658
8526
  import { fileURLToPath as fileURLToPath2 } from "url";
8659
8527
  import { release } from "os";
8660
8528
  var API_URL8 = process.env.DEEPSPACE_API_URL ?? PLATFORM_URLS.api;
@@ -8677,11 +8545,11 @@ function readCliVersion() {
8677
8545
  try {
8678
8546
  const here = dirname8(fileURLToPath2(import.meta.url));
8679
8547
  const candidates = [
8680
- join21(here, "..", "package.json"),
8681
- join21(here, "..", "..", "..", "package.json")
8548
+ join20(here, "..", "package.json"),
8549
+ join20(here, "..", "..", "..", "package.json")
8682
8550
  ];
8683
8551
  for (const path of candidates) {
8684
- if (!existsSync22(path)) continue;
8552
+ if (!existsSync21(path)) continue;
8685
8553
  const pkg2 = JSON.parse(readFileSync23(path, "utf-8"));
8686
8554
  if (pkg2.name === "deepspace" && pkg2.version) return pkg2.version;
8687
8555
  }
@@ -8775,21 +8643,21 @@ var feedback_default = defineDeepspaceCommand({
8775
8643
  );
8776
8644
  }
8777
8645
  if (interactive && (!args.type || !title || !body)) {
8778
- p17.intro("DeepSpace Feedback");
8646
+ p16.intro("DeepSpace Feedback");
8779
8647
  if (!args.type) {
8780
- const picked = await p17.select({
8648
+ const picked = await p16.select({
8781
8649
  message: "What kind of feedback is this?",
8782
8650
  options: TYPES.map((t) => ({ value: t, label: TYPE_LABELS[t] })),
8783
8651
  initialValue: type
8784
8652
  });
8785
- if (p17.isCancel(picked)) {
8786
- p17.cancel("Cancelled.");
8653
+ if (p16.isCancel(picked)) {
8654
+ p16.cancel("Cancelled.");
8787
8655
  return { data: { submitted: false, cancelled: true } };
8788
8656
  }
8789
8657
  type = picked;
8790
8658
  }
8791
8659
  if (!title) {
8792
- const t = await p17.text({
8660
+ const t = await p16.text({
8793
8661
  message: "Title",
8794
8662
  placeholder: "Short summary of the issue",
8795
8663
  validate: (v) => {
@@ -8799,14 +8667,14 @@ var feedback_default = defineDeepspaceCommand({
8799
8667
  return void 0;
8800
8668
  }
8801
8669
  });
8802
- if (p17.isCancel(t)) {
8803
- p17.cancel("Cancelled.");
8670
+ if (p16.isCancel(t)) {
8671
+ p16.cancel("Cancelled.");
8804
8672
  return { data: { submitted: false, cancelled: true } };
8805
8673
  }
8806
8674
  title = String(t);
8807
8675
  }
8808
8676
  if (!body) {
8809
- const m = await p17.text({
8677
+ const m = await p16.text({
8810
8678
  message: "Details",
8811
8679
  placeholder: "What happened? Steps to reproduce, what you expected\u2026",
8812
8680
  validate: (v) => {
@@ -8816,8 +8684,8 @@ var feedback_default = defineDeepspaceCommand({
8816
8684
  return void 0;
8817
8685
  }
8818
8686
  });
8819
- if (p17.isCancel(m)) {
8820
- p17.cancel("Cancelled.");
8687
+ if (p16.isCancel(m)) {
8688
+ p16.cancel("Cancelled.");
8821
8689
  return { data: { submitted: false, cancelled: true } };
8822
8690
  }
8823
8691
  body = String(m);
@@ -8835,7 +8703,7 @@ var feedback_default = defineDeepspaceCommand({
8835
8703
  throw new Refusal(err.message, "invalid_input");
8836
8704
  }
8837
8705
  if (interactive && !args.yes) {
8838
- p17.note(
8706
+ p16.note(
8839
8707
  `${TYPE_LABELS[payload.type]}
8840
8708
  ${payload.title}
8841
8709
 
@@ -8844,9 +8712,9 @@ ${payload.body}
8844
8712
  Context: deepspace ${payload.cliVersion} \xB7 ${payload.nodeVersion} \xB7 ${payload.platform}` + (payload.appName ? ` \xB7 app ${payload.appName}` : ""),
8845
8713
  "Review"
8846
8714
  );
8847
- const ok2 = await p17.confirm({ message: "Send this to the DeepSpace team?" });
8848
- if (p17.isCancel(ok2) || !ok2) {
8849
- p17.cancel("Not sent.");
8715
+ const ok2 = await p16.confirm({ message: "Send this to the DeepSpace team?" });
8716
+ if (p16.isCancel(ok2) || !ok2) {
8717
+ p16.cancel("Not sent.");
8850
8718
  return { data: { submitted: false, cancelled: true } };
8851
8719
  }
8852
8720
  }
@@ -8866,7 +8734,7 @@ Context: deepspace ${payload.cliVersion} \xB7 ${payload.nodeVersion} \xB7 ${payl
8866
8734
  });
8867
8735
  if (!args.json) {
8868
8736
  if (interactive) {
8869
- p17.outro(`Thanks! Submitted as ${result.report.id}.`);
8737
+ p16.outro(`Thanks! Submitted as ${result.report.id}.`);
8870
8738
  } else {
8871
8739
  console.log(`Submitted feedback ${result.report.id} (${result.report.type}).`);
8872
8740
  }
@@ -8877,7 +8745,7 @@ Context: deepspace ${payload.cliVersion} \xB7 ${payload.nodeVersion} \xB7 ${payl
8877
8745
  });
8878
8746
 
8879
8747
  // src/cli/commands/secrets.ts
8880
- import { defineCommand as defineCommand10 } from "citty";
8748
+ import { defineCommand as defineCommand9 } from "citty";
8881
8749
  import { readFileSync as readFileSync24 } from "fs";
8882
8750
 
8883
8751
  // src/cli/lib/citty-args.ts
@@ -8981,7 +8849,7 @@ function warnIfDebugRoutesEnabled(secrets) {
8981
8849
  }
8982
8850
  var APPLY_HINT = "Run `deepspace deploy` to apply \u2014 secrets take effect at deploy time.";
8983
8851
  var LOCAL_DEV_HINT = "Running `deepspace dev start`? Restart it to load the change locally.";
8984
- var list5 = defineCommand10({
8852
+ var list5 = defineCommand9({
8985
8853
  meta: { name: "list", description: "List masked secrets in a config" },
8986
8854
  args: {
8987
8855
  ...COMMON_ARGS,
@@ -9011,7 +8879,7 @@ var list5 = defineCommand10({
9011
8879
  }
9012
8880
  }
9013
8881
  });
9014
- var set = defineCommand10({
8882
+ var set = defineCommand9({
9015
8883
  meta: { name: "set", description: "Set secrets from KEY=value pairs" },
9016
8884
  args: {
9017
8885
  ...COMMON_ARGS,
@@ -9060,7 +8928,7 @@ var set = defineCommand10({
9060
8928
  }
9061
8929
  }
9062
8930
  });
9063
- var get = defineCommand10({
8931
+ var get = defineCommand9({
9064
8932
  meta: { name: "get", description: "Get a secret; pass --plain to print the value" },
9065
8933
  args: {
9066
8934
  ...COMMON_ARGS,
@@ -9096,7 +8964,7 @@ var get = defineCommand10({
9096
8964
  }
9097
8965
  }
9098
8966
  });
9099
- var del2 = defineCommand10({
8967
+ var del2 = defineCommand9({
9100
8968
  meta: { name: "delete", description: "Delete one or more secrets" },
9101
8969
  args: {
9102
8970
  ...COMMON_ARGS,
@@ -9130,7 +8998,7 @@ var del2 = defineCommand10({
9130
8998
  }
9131
8999
  }
9132
9000
  });
9133
- var upload = defineCommand10({
9001
+ var upload = defineCommand9({
9134
9002
  meta: { name: "upload", description: "Upload secrets from a dotenv or JSON file" },
9135
9003
  args: {
9136
9004
  ...COMMON_ARGS,
@@ -9167,7 +9035,7 @@ var upload = defineCommand10({
9167
9035
  }
9168
9036
  }
9169
9037
  });
9170
- var download = defineCommand10({
9038
+ var download = defineCommand9({
9171
9039
  meta: { name: "download", description: "Download a config\u2019s secrets (dotenv/json/shell)" },
9172
9040
  args: {
9173
9041
  ...COMMON_ARGS,
@@ -9196,7 +9064,7 @@ var download = defineCommand10({
9196
9064
  }
9197
9065
  }
9198
9066
  });
9199
- var pull = defineCommand10({
9067
+ var pull = defineCommand9({
9200
9068
  meta: { name: "pull", description: "Refresh the .dev.vars cache from the app store" },
9201
9069
  args: { ...COMMON_ARGS },
9202
9070
  async run({ args }) {
@@ -9239,7 +9107,7 @@ var pull = defineCommand10({
9239
9107
  }
9240
9108
  }
9241
9109
  });
9242
- var configsList = defineCommand10({
9110
+ var configsList = defineCommand9({
9243
9111
  meta: { name: "list", description: "List the app\u2019s configs" },
9244
9112
  args: { ...COMMON_ARGS },
9245
9113
  async run({ args }) {
@@ -9260,7 +9128,7 @@ var configsList = defineCommand10({
9260
9128
  }
9261
9129
  }
9262
9130
  });
9263
- var configsCreate = defineCommand10({
9131
+ var configsCreate = defineCommand9({
9264
9132
  meta: { name: "create", description: "Create a config (optionally copying another)" },
9265
9133
  args: {
9266
9134
  ...COMMON_ARGS,
@@ -9300,7 +9168,7 @@ var configsCreate = defineCommand10({
9300
9168
  }
9301
9169
  }
9302
9170
  });
9303
- var configsDelete = defineCommand10({
9171
+ var configsDelete = defineCommand9({
9304
9172
  meta: { name: "delete", description: "Delete a config and all of its secrets" },
9305
9173
  args: {
9306
9174
  ...COMMON_ARGS,
@@ -9321,11 +9189,11 @@ var configsDelete = defineCommand10({
9321
9189
  }
9322
9190
  }
9323
9191
  });
9324
- var configs = defineCommand10({
9192
+ var configs = defineCommand9({
9325
9193
  meta: { name: "configs", description: "Manage the app\u2019s secrets configs" },
9326
9194
  subCommands: { list: configsList, create: configsCreate, delete: configsDelete }
9327
9195
  });
9328
- var secrets_default = defineCommand10({
9196
+ var secrets_default = defineCommand9({
9329
9197
  meta: { name: "secrets", description: "Manage the app\u2019s secrets store" },
9330
9198
  subCommands: {
9331
9199
  list: list5,
@@ -9402,9 +9270,9 @@ var init_default = defineDeepspaceCommand({
9402
9270
  });
9403
9271
 
9404
9272
  // src/cli/commands/status.ts
9405
- import { defineCommand as defineCommand11 } from "citty";
9406
- import * as p18 from "@clack/prompts";
9407
- import { existsSync as existsSync23, readFileSync as readFileSync25 } from "fs";
9273
+ import { defineCommand as defineCommand10 } from "citty";
9274
+ import * as p17 from "@clack/prompts";
9275
+ import { existsSync as existsSync22, readFileSync as readFileSync25 } from "fs";
9408
9276
  function timeAgo(iso) {
9409
9277
  const ms = Date.now() - Date.parse(iso);
9410
9278
  if (!Number.isFinite(ms) || ms < 0) return iso;
@@ -9437,7 +9305,7 @@ function resolveStatusApp(appDir, wranglerEnv) {
9437
9305
  if (!resolved.ok) throw new InputError(resolved.reason, "invalid_env");
9438
9306
  return { appName: resolved.name, appId: readAppId(appDir, wranglerEnv) };
9439
9307
  }
9440
- var status_default = defineCommand11({
9308
+ var status_default = defineCommand10({
9441
9309
  meta: {
9442
9310
  name: "status",
9443
9311
  description: "One screenful of current state: session, app, workspace, and live release"
@@ -9489,7 +9357,7 @@ var status_default = defineCommand11({
9489
9357
  json.services = urls;
9490
9358
  if (urlOverrides.length > 0) json.urlOverrides = urlOverrides;
9491
9359
  }
9492
- facts.loggedIn = existsSync23(SESSION_PATH);
9360
+ facts.loggedIn = existsSync22(SESSION_PATH);
9493
9361
  let userId = null;
9494
9362
  if (!facts.loggedIn) {
9495
9363
  lines.push(["Session", "not logged in"]);
@@ -9670,12 +9538,12 @@ var status_default = defineCommand11({
9670
9538
  return;
9671
9539
  }
9672
9540
  const width = Math.max(...lines.map(([k]) => k.length));
9673
- for (const [k, v] of lines) p18.log.message(`${k.padEnd(width)} ${v}`);
9541
+ for (const [k, v] of lines) p17.log.message(`${k.padEnd(width)} ${v}`);
9674
9542
  }
9675
9543
  });
9676
9544
 
9677
9545
  // src/cli/commands/push.ts
9678
- import * as p19 from "@clack/prompts";
9546
+ import * as p18 from "@clack/prompts";
9679
9547
  function pullRecoveryAction(cwd, appId, branch) {
9680
9548
  return {
9681
9549
  cwd,
@@ -9859,7 +9727,7 @@ var push_default = defineDeepspaceCommand({
9859
9727
  const recoverable = isRecoverablePushFailure(result.status);
9860
9728
  const rejectReason = result.reason ?? result.summary;
9861
9729
  const errorMsg = ok2 ? null : result.status === "ref_conflict" ? `The cloud repo's ${branch} moved while you worked (${rejectReason}). Run \`deepspace pull --app ${shQuote(appId)} --branch ${shQuote(branch)}\` to integrate, then push again.` : result.status === "rejected" ? `The cloud repo rejected ${branch}: ${rejectReason}.` + (OVERSIZED_PUSH_RE.test(rejectReason) ? ` ${oversizedPushFix(appDir)}` : "") : `The cloud repo's ${branch} has commit(s) your local ${branch} doesn't. Run \`deepspace pull --app ${shQuote(appId)} --branch ${shQuote(branch)}\` and merge (or rebase), then push. Avoid --force here \u2014 it's guarded and will refuse rather than silently drop a peer's commits.`;
9862
- if (!args.json && ok2) p19.log.info(`App: ${appId}`);
9730
+ if (!args.json && ok2) p18.log.info(`App: ${appId}`);
9863
9731
  const action = recoverable ? pullRecoveryAction(pullRecoveryCwd, appId, branch) : void 0;
9864
9732
  if (!ok2) {
9865
9733
  throw new Refusal(errorMsg ?? `Push did not complete.`, result.status, {
@@ -9881,7 +9749,7 @@ var push_default = defineDeepspaceCommand({
9881
9749
  });
9882
9750
 
9883
9751
  // src/cli/commands/pull.ts
9884
- import * as p20 from "@clack/prompts";
9752
+ import * as p19 from "@clack/prompts";
9885
9753
  import { realpathSync as realpathSync4 } from "fs";
9886
9754
  function targetedVcAction(command, cwd, appId, branch) {
9887
9755
  return {
@@ -10143,7 +10011,7 @@ var pull_default = defineDeepspaceCommand({
10143
10011
  }
10144
10012
  const actionRequired = recoveryAction !== void 0;
10145
10013
  spinner2?.stop(codeForState ? `Fetched ${SPACE_REMOTE}/${branch}.` : line);
10146
- if (!args.json) p20.log.info(`App: ${appId} \xB7 ${SPACE_REMOTE}/${branch} at ${remoteOid.slice(0, 10)}`);
10014
+ if (!args.json) p19.log.info(`App: ${appId} \xB7 ${SPACE_REMOTE}/${branch} at ${remoteOid.slice(0, 10)}`);
10147
10015
  if (codeForState) {
10148
10016
  throw new Refusal(line, codeForState, {
10149
10017
  actionRequired,
@@ -10162,19 +10030,19 @@ var pull_default = defineDeepspaceCommand({
10162
10030
  });
10163
10031
 
10164
10032
  // src/cli/commands/clone.ts
10165
- import * as p21 from "@clack/prompts";
10166
- import { existsSync as existsSync24, readdirSync as readdirSync6, rmSync as rmSync5 } from "fs";
10167
- import { resolve as resolve16, basename as basename3, join as join22 } from "path";
10033
+ import * as p20 from "@clack/prompts";
10034
+ import { existsSync as existsSync23, readdirSync as readdirSync6, rmSync as rmSync5 } from "fs";
10035
+ import { resolve as resolve15, basename as basename3, join as join21 } from "path";
10168
10036
  function cleanFailedCloneDir(dir) {
10169
10037
  let entries;
10170
10038
  try {
10171
10039
  entries = readdirSync6(dir);
10172
10040
  } catch {
10173
- return existsSync24(dir) ? ["<unreadable>"] : [];
10041
+ return existsSync23(dir) ? ["<unreadable>"] : [];
10174
10042
  }
10175
10043
  if (entries.length === 1 && entries[0] === ".git") {
10176
10044
  try {
10177
- rmSync5(join22(dir, ".git"), { recursive: true, force: true });
10045
+ rmSync5(join21(dir, ".git"), { recursive: true, force: true });
10178
10046
  return [];
10179
10047
  } catch {
10180
10048
  return entries;
@@ -10183,7 +10051,7 @@ function cleanFailedCloneDir(dir) {
10183
10051
  return entries;
10184
10052
  }
10185
10053
  function validateCloneTarget(dir) {
10186
- if (!existsSync24(dir)) return false;
10054
+ if (!existsSync23(dir)) return false;
10187
10055
  let entries;
10188
10056
  try {
10189
10057
  entries = readdirSync6(dir);
@@ -10218,7 +10086,7 @@ var clone_default = defineDeepspaceCommand({
10218
10086
  async run({ args }) {
10219
10087
  assertAppTargetResolvable(String(args.app));
10220
10088
  const selector = String(args.app).trim();
10221
- const dir = resolve16(String(args.dir ?? selector));
10089
+ const dir = resolve15(String(args.dir ?? selector));
10222
10090
  const dirPreexisted = validateCloneTarget(dir);
10223
10091
  const spinner2 = args.json ? null : createSpinner();
10224
10092
  spinner2?.start(`Resolving ${selector}\u2026`);
@@ -10264,7 +10132,7 @@ var clone_default = defineDeepspaceCommand({
10264
10132
  `Cloned ${selector} (${branches.length} ${branches.length === 1 ? "branch" : "branches"}) into ${basename3(dir)}/ at ${head?.slice(0, 10) ?? "(unborn)"}.`
10265
10133
  );
10266
10134
  if (!args.json && !branch) {
10267
- p21.log.warn("HEAD is detached \u2014 check `git branch -a`.");
10135
+ p20.log.warn("HEAD is detached \u2014 check `git branch -a`.");
10268
10136
  }
10269
10137
  return {
10270
10138
  data: {
@@ -10283,7 +10151,7 @@ var clone_default = defineDeepspaceCommand({
10283
10151
  });
10284
10152
 
10285
10153
  // src/cli/commands/releases.ts
10286
- import * as p22 from "@clack/prompts";
10154
+ import * as p21 from "@clack/prompts";
10287
10155
  var DEPLOY_URL11 = process.env.DEEPSPACE_DEPLOY_URL ?? PLATFORM_URLS.deploy;
10288
10156
  var releases_default = defineDeepspaceCommand({
10289
10157
  meta: {
@@ -10324,7 +10192,7 @@ var releases_default = defineDeepspaceCommand({
10324
10192
  spinner2?.stop(`Loaded ${releases.length} ${releases.length === 1 ? "release" : "releases"}.`);
10325
10193
  if (!args.json) {
10326
10194
  if (releases.length === 0) {
10327
- p22.log.info("No releases yet \u2014 the history starts with the next `deepspace deploy`.");
10195
+ p21.log.info("No releases yet \u2014 the history starts with the next `deepspace deploy`.");
10328
10196
  } else {
10329
10197
  for (const r of releases) {
10330
10198
  const source = r.commitOid ? `commit ${r.commitOid.slice(0, 10)}` : "(no source recorded)";
@@ -10333,7 +10201,7 @@ var releases_default = defineDeepspaceCommand({
10333
10201
  `#${r.seq} ${r.id} ${r.kind.padEnd(8)} ${r.createdAt} ${r.actor} ${source} ${rollback}`
10334
10202
  );
10335
10203
  }
10336
- p22.log.info(
10204
+ p21.log.info(
10337
10205
  `Roll back an available release with: deepspace rollback <release-id>${wranglerEnv ? ` --env ${wranglerEnv}` : ""}`
10338
10206
  );
10339
10207
  }
@@ -10343,7 +10211,7 @@ var releases_default = defineDeepspaceCommand({
10343
10211
  });
10344
10212
 
10345
10213
  // src/cli/commands/rollback.ts
10346
- import * as p23 from "@clack/prompts";
10214
+ import * as p22 from "@clack/prompts";
10347
10215
  var REL_ID_RE = /^rel_[0-9A-HJKMNP-TV-Z]{26}$/;
10348
10216
  function unavailableDoGuardRefusal(message) {
10349
10217
  return new Refusal(
@@ -10456,18 +10324,18 @@ Re-run with --allow-do-deletion to accept the data loss.`,
10456
10324
  spinner2?.stop(`Rolled back to ${result.rolledBackTo ?? releaseId}.`);
10457
10325
  const doClassGuard = result.doClassGuard === "unverified" ? "unverified" : void 0;
10458
10326
  if (!args.json) {
10459
- if (result.url) p23.log.success(`Live at: ${result.url}`);
10327
+ if (result.url) p22.log.success(`Live at: ${result.url}`);
10460
10328
  if (result.bundleRetained === false) {
10461
- p23.log.warn(
10329
+ p22.log.warn(
10462
10330
  "The rollback is live, but its bundle was concurrently retired and is not available for a future rollback."
10463
10331
  );
10464
10332
  }
10465
10333
  if (doClassGuard === "unverified") {
10466
- p23.log.warn(
10334
+ p22.log.warn(
10467
10335
  "DO-class guard bypassed (--allow-do-deletion): this rollback was NOT checked against the live Durable Object classes \u2014 any class the target doesn't declare has been deleted with its data."
10468
10336
  );
10469
10337
  }
10470
- p23.log.info(
10338
+ p22.log.info(
10471
10339
  "This rollback is itself the newest release \u2014 `deepspace releases` shows the full history."
10472
10340
  );
10473
10341
  }
@@ -10487,14 +10355,14 @@ Re-run with --allow-do-deletion to accept the data loss.`,
10487
10355
  });
10488
10356
 
10489
10357
  // src/cli/commands/workspace.ts
10490
- import { defineCommand as defineCommand12 } from "citty";
10358
+ import { defineCommand as defineCommand11 } from "citty";
10491
10359
 
10492
10360
  // src/cli/commands/workspace/new.ts
10493
- import * as p26 from "@clack/prompts";
10494
- import { isAbsolute as isAbsolute6, resolve as resolve17 } from "path";
10361
+ import * as p25 from "@clack/prompts";
10362
+ import { isAbsolute as isAbsolute6, resolve as resolve16 } from "path";
10495
10363
 
10496
10364
  // src/cli/commands/workspace/analysis.ts
10497
- import * as p24 from "@clack/prompts";
10365
+ import * as p23 from "@clack/prompts";
10498
10366
  var MAX_OVERLAP_PATHS = 20;
10499
10367
  var PEER_REF_PREFIX = `${spacePrivateRef("peers")}/`;
10500
10368
  function peerWorkspaceRef(workspaceId) {
@@ -10608,16 +10476,16 @@ function printOverlaps(overlaps, json) {
10608
10476
  for (const overlap of overlaps) {
10609
10477
  const sample = overlap.paths.slice(0, 5).join(", ");
10610
10478
  const more = overlap.paths.length - 5 + overlap.morePaths;
10611
- p24.log.warn(
10479
+ p23.log.warn(
10612
10480
  `Overlap: ${overlap.workspaceId} ("${overlap.task}") also modified ${sample}${more > 0 ? ` (+${more} more)` : ""} \u2014 coordinate before landing.`
10613
10481
  );
10614
10482
  }
10615
10483
  }
10616
10484
 
10617
10485
  // src/cli/commands/workspace/local.ts
10618
- import * as p25 from "@clack/prompts";
10486
+ import * as p24 from "@clack/prompts";
10619
10487
  import { mkdirSync as mkdirSync7, readFileSync as readFileSync26, realpathSync as realpathSync5, renameSync as renameSync2, statSync, writeFileSync as writeFileSync9 } from "fs";
10620
- import { dirname as dirname9, isAbsolute as isAbsolute5, join as join23, relative as relative2, sep as sep2 } from "path";
10488
+ import { dirname as dirname9, isAbsolute as isAbsolute5, join as join22, relative as relative2, sep as sep2 } from "path";
10621
10489
  var WORKSPACE_MARKER = "deepspace-workspace.json";
10622
10490
  function excludeWorktreeDir(appDir, dir) {
10623
10491
  try {
@@ -10638,7 +10506,7 @@ function worktreeMarkerPath(worktreeRoot) {
10638
10506
  const result = runGit(worktreeRoot, ["rev-parse", "--absolute-git-dir"], { allowFail: true });
10639
10507
  if (result.status !== 0) return null;
10640
10508
  const gitDir = result.stdout.toString("utf-8").trim();
10641
- return isAbsolute5(gitDir) ? join23(gitDir, WORKSPACE_MARKER) : null;
10509
+ return isAbsolute5(gitDir) ? join22(gitDir, WORKSPACE_MARKER) : null;
10642
10510
  } catch {
10643
10511
  return null;
10644
10512
  }
@@ -10683,11 +10551,11 @@ function isManagedWorkspaceWorktree(worktreeRoot, workspaceId) {
10683
10551
  function defaultWorkspaceRoot(appDir, workspaceId) {
10684
10552
  const primary = listWorktrees(appDir)[0];
10685
10553
  if (!primary) throw new Error("Git did not report a primary worktree");
10686
- return join23(primary.path, ".deepspace", "ws", workspaceId.slice(3).toLowerCase());
10554
+ return join22(primary.path, ".deepspace", "ws", workspaceId.slice(3).toLowerCase());
10687
10555
  }
10688
10556
  function appDirInWorktree(appDir, worktreeRoot) {
10689
10557
  const appRelative = relative2(realpathSync5(repoToplevel(appDir)), realpathSync5(appDir));
10690
- return appRelative ? join23(worktreeRoot, appRelative) : worktreeRoot;
10558
+ return appRelative ? join22(worktreeRoot, appRelative) : worktreeRoot;
10691
10559
  }
10692
10560
  function materializeWorkspaceWorktree(appDir, worktreeRoot, branch, startPoint, workspaceId, options = {}) {
10693
10561
  const createdOid = resolveCommit(appDir, startPoint);
@@ -10705,7 +10573,7 @@ function materializeWorkspaceWorktree(appDir, worktreeRoot, branch, startPoint,
10705
10573
  function inOwnLinkedWorktree(appDir, id) {
10706
10574
  if (workspaceIdFromBranch(currentBranch(appDir)) !== id) return false;
10707
10575
  try {
10708
- return statSync(join23(repoToplevel(appDir), ".git")).isFile();
10576
+ return statSync(join22(repoToplevel(appDir), ".git")).isFile();
10709
10577
  } catch {
10710
10578
  return false;
10711
10579
  }
@@ -10851,7 +10719,7 @@ function cleanupAction(outcome) {
10851
10719
  }
10852
10720
  function reportCleanupHuman(outcome) {
10853
10721
  if (outcome.error) {
10854
- p25.log.warn(
10722
+ p24.log.warn(
10855
10723
  cleanupRefusalMessage({
10856
10724
  error: outcome.error,
10857
10725
  worktreeDir: outcome.worktreeDir,
@@ -10864,12 +10732,12 @@ function reportCleanupHuman(outcome) {
10864
10732
  outcome.worktreeRemoved ? "worktree" : null,
10865
10733
  outcome.branchDeleted ? `branch ${outcome.branch}` : null
10866
10734
  ].filter(Boolean);
10867
- if (parts.length) p25.log.success(`Removed ${parts.join(" + ")}.`);
10735
+ if (parts.length) p24.log.success(`Removed ${parts.join(" + ")}.`);
10868
10736
  if (outcome.worktreeRetained) {
10869
- p25.log.info(`Retained externally managed worktree: ${outcome.worktreeRetained}`);
10737
+ p24.log.info(`Retained externally managed worktree: ${outcome.worktreeRetained}`);
10870
10738
  }
10871
10739
  if (outcome.worktreeRemoved && outcome.mainDir) {
10872
- p25.log.info(`This directory was removed \u2014 run: cd ${shQuote(outcome.mainDir)}`);
10740
+ p24.log.info(`This directory was removed \u2014 run: cd ${shQuote(outcome.mainDir)}`);
10873
10741
  }
10874
10742
  }
10875
10743
 
@@ -11051,7 +10919,7 @@ var newWorkspaceCommand = defineDeepspaceCommand({
11051
10919
  idempotencyKey: mintIdempotencyKey()
11052
10920
  });
11053
10921
  const dirInput = typeof args.dir === "string" ? args.dir.trim() : "";
11054
- const worktreeRoot = dirInput ? isAbsolute6(dirInput) ? dirInput : resolve17(appDir, dirInput) : defaultWorkspaceRoot(appDir, id);
10922
+ const worktreeRoot = dirInput ? isAbsolute6(dirInput) ? dirInput : resolve16(appDir, dirInput) : defaultWorkspaceRoot(appDir, id);
11055
10923
  const dir = appDirInWorktree(appDir, worktreeRoot);
11056
10924
  try {
11057
10925
  materializeWorkspaceWorktree(appDir, worktreeRoot, branch, baseOid, id);
@@ -11066,8 +10934,8 @@ var newWorkspaceCommand = defineDeepspaceCommand({
11066
10934
  }
11067
10935
  spinner2?.stop(`Workspace ${id} created.`);
11068
10936
  if (!args.json) {
11069
- p26.log.info(`Work in: cd ${dir}`);
11070
- p26.log.info(
10937
+ p25.log.info(`Work in: cd ${dir}`);
10938
+ p25.log.info(
11071
10939
  `Then: commit as usual, \`deepspace workspace sync\` to publish, \`deepspace workspace land\` when done.`
11072
10940
  );
11073
10941
  }
@@ -11088,9 +10956,9 @@ var newWorkspaceCommand = defineDeepspaceCommand({
11088
10956
  });
11089
10957
 
11090
10958
  // src/cli/commands/workspace/attach.ts
11091
- import * as p27 from "@clack/prompts";
11092
- import { existsSync as existsSync25, readdirSync as readdirSync7, rmSync as rmSync6 } from "fs";
11093
- import { isAbsolute as isAbsolute7, resolve as resolve18 } from "path";
10959
+ import * as p26 from "@clack/prompts";
10960
+ import { existsSync as existsSync24, readdirSync as readdirSync7, rmSync as rmSync6 } from "fs";
10961
+ import { isAbsolute as isAbsolute7, resolve as resolve17 } from "path";
11094
10962
  function finishedWorkspaceMessage(id, view) {
11095
10963
  const workspace = view.workspace;
11096
10964
  if (workspace.status === "landed") {
@@ -11099,7 +10967,7 @@ function finishedWorkspaceMessage(id, view) {
11099
10967
  return `Workspace ${id} is ${workspace.status} \u2014 its ref is retained briefly (fetch ${workspace.ref} to inspect), but attach only works on active workspaces.`;
11100
10968
  }
11101
10969
  function cleanFailedFreshAttachDir(dir) {
11102
- if (!existsSync25(dir)) return [];
10970
+ if (!existsSync24(dir)) return [];
11103
10971
  let entries;
11104
10972
  try {
11105
10973
  entries = readdirSync7(dir);
@@ -11175,7 +11043,7 @@ var attachWorkspaceCommand = defineDeepspaceCommand({
11175
11043
  );
11176
11044
  }
11177
11045
  const requestedDir = typeof args.dir === "string" ? args.dir.trim() : "";
11178
- const worktreeRoot = requestedDir ? isAbsolute7(requestedDir) ? requestedDir : resolve18(appDir, requestedDir) : defaultWorkspaceRoot(appDir, id);
11046
+ const worktreeRoot = requestedDir ? isAbsolute7(requestedDir) ? requestedDir : resolve17(appDir, requestedDir) : defaultWorkspaceRoot(appDir, id);
11179
11047
  const dir2 = appDirInWorktree(appDir, worktreeRoot);
11180
11048
  if (resolveCommit(appDir, `refs/heads/${branch}`)) {
11181
11049
  throw new Refusal(
@@ -11186,8 +11054,8 @@ var attachWorkspaceCommand = defineDeepspaceCommand({
11186
11054
  materializeWorkspaceWorktree(appDir, worktreeRoot, branch, tip2, id);
11187
11055
  spinner2?.stop(`Attached ${id}.`);
11188
11056
  if (!args.json) {
11189
- p27.log.info(`Task: ${view2.workspace.task}`);
11190
- p27.log.info(`Work in: cd ${dir2}`);
11057
+ p26.log.info(`Task: ${view2.workspace.task}`);
11058
+ p26.log.info(`Work in: cd ${dir2}`);
11191
11059
  }
11192
11060
  const action2 = { cwd: dir2, argv: [detectPackageManager(dir2), "install"] };
11193
11061
  return {
@@ -11214,11 +11082,11 @@ var attachWorkspaceCommand = defineDeepspaceCommand({
11214
11082
  extra: { status: view.workspace.status }
11215
11083
  });
11216
11084
  }
11217
- const dir = resolve18(
11085
+ const dir = resolve17(
11218
11086
  process.cwd(),
11219
11087
  (typeof args.dir === "string" ? args.dir.trim() : "") || `ws-${id.slice(3).toLowerCase()}`
11220
11088
  );
11221
- if (existsSync25(dir)) {
11089
+ if (existsSync24(dir)) {
11222
11090
  spinner2?.stop("Target exists.");
11223
11091
  throw new Refusal(`${dir} already exists \u2014 pass a different directory.`, "dir_exists");
11224
11092
  }
@@ -11259,8 +11127,8 @@ var attachWorkspaceCommand = defineDeepspaceCommand({
11259
11127
  spinner2?.stop(`Attached ${id}.`);
11260
11128
  const action = { cwd: dir, argv: [detectPackageManager(dir), "install"] };
11261
11129
  if (!args.json) {
11262
- p27.log.info(`Task: ${view.workspace.task}`);
11263
- p27.log.info("Pull app secrets after install if this workspace needs them.");
11130
+ p26.log.info(`Task: ${view.workspace.task}`);
11131
+ p26.log.info("Pull app secrets after install if this workspace needs them.");
11264
11132
  }
11265
11133
  return {
11266
11134
  data: {
@@ -11277,7 +11145,7 @@ var attachWorkspaceCommand = defineDeepspaceCommand({
11277
11145
  });
11278
11146
 
11279
11147
  // src/cli/commands/workspace/sync.ts
11280
- import * as p28 from "@clack/prompts";
11148
+ import * as p27 from "@clack/prompts";
11281
11149
  var syncWorkspaceCommand = defineDeepspaceCommand({
11282
11150
  meta: {
11283
11151
  name: "sync",
@@ -11338,12 +11206,12 @@ var syncWorkspaceCommand = defineDeepspaceCommand({
11338
11206
  );
11339
11207
  printOverlaps(overlaps, args.json);
11340
11208
  if (!args.json && trunkOverlap.length > 0) {
11341
- p28.log.warn(
11209
+ p27.log.warn(
11342
11210
  `Trunk already changed ${trunkOverlap.length} file(s) you also touch \u2014 landed work you haven't merged: ${trunkOverlap.slice(0, 5).join(", ")}${trunkOverlap.length > 5 ? ` (+${trunkOverlap.length - 5} more)` : ""}. Merge trunk before landing (\`deepspace workspace status\` shows the full picture).`
11343
11211
  );
11344
11212
  }
11345
11213
  if (!args.json && dirty.length > 0) {
11346
- p28.log.warn(
11214
+ p27.log.warn(
11347
11215
  `${dirty.length} uncommitted ${dirty.length === 1 ? "file" : "files"} NOT synced \u2014 commit them to this workspace branch (WIP commits are fine \u2014 they land with the merge).`
11348
11216
  );
11349
11217
  }
@@ -11363,7 +11231,7 @@ var syncWorkspaceCommand = defineDeepspaceCommand({
11363
11231
  });
11364
11232
 
11365
11233
  // src/cli/commands/workspace/list.ts
11366
- import * as p29 from "@clack/prompts";
11234
+ import * as p28 from "@clack/prompts";
11367
11235
 
11368
11236
  // src/cli/lib/actor-labels.ts
11369
11237
  var API_URL9 = process.env.DEEPSPACE_API_URL ?? PLATFORM_URLS.api;
@@ -11411,7 +11279,7 @@ var listWorkspacesCommand = defineDeepspaceCommand({
11411
11279
  if (views.length === 0) {
11412
11280
  spinner2?.stop("No workspaces found.");
11413
11281
  if (!args.json) {
11414
- p29.log.info(
11282
+ p28.log.info(
11415
11283
  all ? "No workspaces." : 'No active workspaces. Create one with `deepspace workspace new -t "\u2026"`.'
11416
11284
  );
11417
11285
  }
@@ -11440,13 +11308,13 @@ var listWorkspacesCommand = defineDeepspaceCommand({
11440
11308
  );
11441
11309
  }
11442
11310
  }
11443
- p29.log.info("\u2191 commits ahead of base \xB7 \u2193 trunk commits since base (staleness)");
11311
+ p28.log.info("\u2191 commits ahead of base \xB7 \u2193 trunk commits since base (staleness)");
11444
11312
  return { data: { workspaces } };
11445
11313
  }
11446
11314
  });
11447
11315
 
11448
11316
  // src/cli/commands/workspace/status.ts
11449
- import * as p30 from "@clack/prompts";
11317
+ import * as p29 from "@clack/prompts";
11450
11318
  var workspaceStatusCommand = defineDeepspaceCommand({
11451
11319
  meta: { name: "status", description: "This workspace: base staleness, overlaps, sync state" },
11452
11320
  args: {
@@ -11506,22 +11374,22 @@ var workspaceStatusCommand = defineDeepspaceCommand({
11506
11374
  overlaps
11507
11375
  };
11508
11376
  if (!args.json) {
11509
- p30.log.info(`Task: ${workspace.task}`);
11510
- p30.log.info(
11377
+ p29.log.info(`Task: ${workspace.task}`);
11378
+ p29.log.info(
11511
11379
  `Base: ${workspace.baseOid.slice(0, 10)} \xB7 ahead ${aheadExact ?? "?"} commit(s) \xB7 trunk moved ${behindExact ?? "?"} commit(s) since your base`
11512
11380
  );
11513
11381
  if (!attached) {
11514
- p30.log.info(
11382
+ p29.log.info(
11515
11383
  `Not checked out in this clone \u2014 showing the published state (local HEAD/uncommitted unavailable). Attach it with \`deepspace workspace attach ${id} <dir>\`.`
11516
11384
  );
11517
11385
  }
11518
11386
  if (unsynced)
11519
- p30.log.warn(
11387
+ p29.log.warn(
11520
11388
  `Local HEAD ${headOid?.slice(0, 10)} is not synced (server has ${view.tipOid?.slice(0, 10) ?? "nothing"}) \u2014 run \`deepspace workspace sync\`.`
11521
11389
  );
11522
- if (dirty.length > 0) p30.log.warn(`${dirty.length} uncommitted file(s) in the worktree.`);
11390
+ if (dirty.length > 0) p29.log.warn(`${dirty.length} uncommitted file(s) in the worktree.`);
11523
11391
  if (trunkOverlap.length > 0) {
11524
- p30.log.warn(
11392
+ p29.log.warn(
11525
11393
  `Trunk also modified: ${trunkOverlap.slice(0, 5).join(", ")}${trunkOverlap.length > 5 ? ` (+${trunkOverlap.length - 5} more)` : ""} \u2014 expect merge attention at land time.`
11526
11394
  );
11527
11395
  }
@@ -11532,17 +11400,17 @@ var workspaceStatusCommand = defineDeepspaceCommand({
11532
11400
  });
11533
11401
 
11534
11402
  // src/cli/commands/workspace/land.ts
11535
- import * as p31 from "@clack/prompts";
11403
+ import * as p30 from "@clack/prompts";
11536
11404
 
11537
11405
  // src/cli/lib/validation.ts
11538
11406
  import { sync as spawnSync7 } from "cross-spawn";
11539
11407
  import { readFileSync as readFileSync27 } from "fs";
11540
- import { join as join24 } from "path";
11408
+ import { join as join23 } from "path";
11541
11409
  var MAX_SUMMARY_CHARS = 4e3;
11542
11410
  var MAX_OUTPUT_BUFFER = 64 * 1024 * 1024;
11543
11411
  function configuredCommand(appDir) {
11544
11412
  try {
11545
- const pkg2 = JSON.parse(readFileSync27(join24(appDir, "package.json"), "utf-8"));
11413
+ const pkg2 = JSON.parse(readFileSync27(join23(appDir, "package.json"), "utf-8"));
11546
11414
  if (pkg2.scripts?.validate) return `${detectPackageManager(appDir)} run --silent validate`;
11547
11415
  } catch {
11548
11416
  }
@@ -11818,7 +11686,7 @@ var landWorkspaceCommand = defineDeepspaceCommand({
11818
11686
  if (!args.json && cleanup && !cleanup.error) {
11819
11687
  reportCleanupHuman(cleanup);
11820
11688
  } else if (!args.json && retainedWorktree) {
11821
- p31.log.info(`Retained checkout: ${retainedWorktree}`);
11689
+ p30.log.info(`Retained checkout: ${retainedWorktree}`);
11822
11690
  }
11823
11691
  if (cleanup?.error) {
11824
11692
  const action = cleanupAction({
@@ -11840,7 +11708,7 @@ var landWorkspaceCommand = defineDeepspaceCommand({
11840
11708
  });
11841
11709
 
11842
11710
  // src/cli/commands/workspace/drop.ts
11843
- import * as p32 from "@clack/prompts";
11711
+ import * as p31 from "@clack/prompts";
11844
11712
  function isWorkspaceTipPublished(appDir, localTip, publishedOids) {
11845
11713
  return publishedOids.some(
11846
11714
  (publishedOid) => publishedOid === localTip || isAncestor(appDir, localTip, publishedOid)
@@ -11849,9 +11717,9 @@ function isWorkspaceTipPublished(appDir, localTip, publishedOids) {
11849
11717
  function workspaceUnsyncedRefusal(args) {
11850
11718
  const syncArgv = ["deepspace", "workspace", "sync", "--app", args.appId, "--workspace", args.id];
11851
11719
  const dropArgv = ["deepspace", "workspace", "drop", args.id, "--app", args.appId];
11852
- const publish2 = args.workspaceDir ? `Publish them first with \`${humanCommand(syncArgv)}\`, then re-run \`${humanCommand(dropArgv)}\`.` : `Recreate a worktree from the branch (\`git worktree add <dir> ${args.branch}\`), publish from there with \`${humanCommand(syncArgv)}\`, then re-run \`${humanCommand(dropArgv)}\`.`;
11720
+ const publish = args.workspaceDir ? `Publish them first with \`${humanCommand(syncArgv)}\`, then re-run \`${humanCommand(dropArgv)}\`.` : `Recreate a worktree from the branch (\`git worktree add <dir> ${args.branch}\`), publish from there with \`${humanCommand(syncArgv)}\`, then re-run \`${humanCommand(dropArgv)}\`.`;
11853
11721
  return new Refusal(
11854
- `${args.id} has committed work that isn't published yet. ${publish2} Alternatively, pass \`--keep-worktree\` to drop the cloud workspace while retaining the local branch/worktree for manual disposal. Nothing was dropped.`,
11722
+ `${args.id} has committed work that isn't published yet. ${publish} Alternatively, pass \`--keep-worktree\` to drop the cloud workspace while retaining the local branch/worktree for manual disposal. Nothing was dropped.`,
11855
11723
  "workspace_unsynced",
11856
11724
  {
11857
11725
  ...args.workspaceDir ? { action: { cwd: args.workspaceDir, argv: syncArgv } } : {},
@@ -11886,7 +11754,7 @@ var dropWorkspaceCommand = defineDeepspaceCommand({
11886
11754
  const { view: view2 } = await api5.dropWorkspace(explicitId);
11887
11755
  spinner2?.stop();
11888
11756
  if (!args.json) {
11889
- p32.log.success(
11757
+ p31.log.success(
11890
11758
  `Dropped ${explicitId}. Its ref sticks around briefly for undo, then is reaped.`
11891
11759
  );
11892
11760
  }
@@ -11938,9 +11806,9 @@ var dropWorkspaceCommand = defineDeepspaceCommand({
11938
11806
  };
11939
11807
  spinner2?.stop();
11940
11808
  if (!args.json) {
11941
- p32.log.success(`Dropped ${id}. Its ref sticks around briefly for undo, then is reaped.`);
11809
+ p31.log.success(`Dropped ${id}. Its ref sticks around briefly for undo, then is reaped.`);
11942
11810
  if (cleanup && !cleanup.error) reportCleanupHuman(cleanup);
11943
- else if (retainedWorktree) p32.log.info(`Retained checkout: ${retainedWorktree}`);
11811
+ else if (retainedWorktree) p31.log.info(`Retained checkout: ${retainedWorktree}`);
11944
11812
  }
11945
11813
  if (cleanup?.error) {
11946
11814
  const action = cleanupAction({
@@ -11962,7 +11830,7 @@ var dropWorkspaceCommand = defineDeepspaceCommand({
11962
11830
  });
11963
11831
 
11964
11832
  // src/cli/commands/workspace.ts
11965
- var workspace_default = defineCommand12({
11833
+ var workspace_default = defineCommand11({
11966
11834
  meta: {
11967
11835
  name: "workspace",
11968
11836
  description: "Durable parallel-agent workspaces (new/attach/sync/list/status/land/drop)"
@@ -11979,7 +11847,7 @@ var workspace_default = defineCommand12({
11979
11847
  });
11980
11848
 
11981
11849
  // src/cli/commands/activity.ts
11982
- import * as p33 from "@clack/prompts";
11850
+ import * as p32 from "@clack/prompts";
11983
11851
  var FOLLOW_INTERVAL_MS = 5e3;
11984
11852
  function landIndex(events) {
11985
11853
  const m = /* @__PURE__ */ new Map();
@@ -12092,7 +11960,7 @@ var activity_default = defineDeepspaceCommand({
12092
11960
  const lands = landIndex(page.events);
12093
11961
  for (const e of page.events) console.log(formatEvent2(e, lands, actors));
12094
11962
  if (page.events.length === 0 && !args.follow) {
12095
- p33.log.info(cursor > 0 ? `No activity after #${cursor}.` : "No activity yet.");
11963
+ p32.log.info(cursor > 0 ? `No activity after #${cursor}.` : "No activity yet.");
12096
11964
  }
12097
11965
  }
12098
11966
  cursor = page.cursor;
@@ -12102,7 +11970,7 @@ var activity_default = defineDeepspaceCommand({
12102
11970
  }
12103
11971
  if (!args.follow) {
12104
11972
  if (page.events.length > 0) {
12105
- p33.log.info(
11973
+ p32.log.info(
12106
11974
  `Cursor: ${cursor}` + (page.hasMore ? ` \xB7 more available (next page: --since ${cursor})` : ` (resume later with --since ${cursor})`)
12107
11975
  );
12108
11976
  }
@@ -12124,7 +11992,7 @@ var activity_default = defineDeepspaceCommand({
12124
11992
  })
12125
11993
  );
12126
11994
  } else {
12127
- p33.log.warn(`Activity feed interrupted (${code}); retrying in 5s.`);
11995
+ p32.log.warn(`Activity feed interrupted (${code}); retrying in 5s.`);
12128
11996
  }
12129
11997
  }
12130
11998
  await new Promise((resolveSleep) => setTimeout(resolveSleep, FOLLOW_INTERVAL_MS));
@@ -12133,7 +12001,7 @@ var activity_default = defineDeepspaceCommand({
12133
12001
  });
12134
12002
 
12135
12003
  // src/cli/commands/git-credential.ts
12136
- import { defineCommand as defineCommand13 } from "citty";
12004
+ import { defineCommand as defineCommand12 } from "citty";
12137
12005
  function parseFields(input) {
12138
12006
  const fields = /* @__PURE__ */ new Map();
12139
12007
  for (const line of input.split("\n")) {
@@ -12182,7 +12050,7 @@ async function readStdin() {
12182
12050
  for await (const chunk of process.stdin) data += chunk;
12183
12051
  return data;
12184
12052
  }
12185
- var git_credential_default = defineCommand13({
12053
+ var git_credential_default = defineCommand12({
12186
12054
  meta: {
12187
12055
  name: "git-credential",
12188
12056
  description: "Git credential helper (installed automatically; not for direct use)"
@@ -12217,7 +12085,7 @@ var git_credential_default = defineCommand13({
12217
12085
  });
12218
12086
 
12219
12087
  // src/cli/commands/source.ts
12220
- import * as p34 from "@clack/prompts";
12088
+ import * as p33 from "@clack/prompts";
12221
12089
  var TRANSFER_PREFIX = spacePrivateRef("source-transfer");
12222
12090
  var source_default = defineDeepspaceCommand({
12223
12091
  meta: {
@@ -12270,7 +12138,7 @@ var source_default = defineDeepspaceCommand({
12270
12138
  const remoteArg = typeof args.remote === "string" ? args.remote.trim() : void 0;
12271
12139
  const result = requested === "github" ? await moveToGitHub({ appDir, appId, token, deployUrl, state, remoteArg }) : await moveToDeepSpace({ appDir, appId, token, deployUrl, state, remoteArg });
12272
12140
  if (!args.json) {
12273
- p34.log.success(
12141
+ p33.log.success(
12274
12142
  result.source.provider === "github" ? `Source: GitHub \xB7 ${result.source.repository} (revision ${result.revision})` : `Source: DeepSpace (revision ${result.revision})`
12275
12143
  );
12276
12144
  }
@@ -13036,11 +12904,11 @@ function reportMigration(migration, json) {
13036
12904
 
13037
12905
  // src/cli/cli.ts
13038
12906
  var __dirname = dirname10(fileURLToPath3(import.meta.url));
13039
- var pkg = JSON.parse(readFileSync28(join25(__dirname, "..", "package.json"), "utf-8"));
13040
- if (process.platform === "linux" && !process.env.SSL_CERT_FILE && existsSync26("/etc/ssl/certs/ca-certificates.crt")) {
12907
+ var pkg = JSON.parse(readFileSync28(join24(__dirname, "..", "package.json"), "utf-8"));
12908
+ if (process.platform === "linux" && !process.env.SSL_CERT_FILE && existsSync25("/etc/ssl/certs/ca-certificates.crt")) {
13041
12909
  process.env.SSL_CERT_FILE = "/etc/ssl/certs/ca-certificates.crt";
13042
12910
  }
13043
- var create2 = defineCommand14({
12911
+ var create2 = defineCommand13({
13044
12912
  meta: {
13045
12913
  name: "create",
13046
12914
  description: "Create a new DeepSpace app (runs create-deepspace; all flags are forwarded)"
@@ -13079,14 +12947,14 @@ var create2 = defineCommand14({
13079
12947
  }
13080
12948
  });
13081
12949
  var rename = (cmd, name) => ({ ...cmd, meta: { ...cmd.meta ?? {}, name } });
13082
- var auth = defineCommand14({
12950
+ var auth = defineCommand13({
13083
12951
  meta: { name: "auth", description: "Session: login, logout, whoami" },
13084
12952
  subCommands: { login: login_default, logout: logout_default, whoami: whoami_default }
13085
12953
  });
13086
- var app = defineCommand14({
12954
+ var app = defineCommand13({
13087
12955
  meta: {
13088
12956
  name: "app",
13089
- description: "The app itself: create, init, list, source, migrate, undeploy, transfer, collaborators, domain, library, usage"
12957
+ description: "The app itself: create, init, list, source, migrate, undeploy, transfer, collaborators, domain, usage"
13090
12958
  },
13091
12959
  subCommands: {
13092
12960
  create: create2,
@@ -13096,17 +12964,16 @@ var app = defineCommand14({
13096
12964
  transfer: transfer_default,
13097
12965
  collaborators: collaborators_default,
13098
12966
  domain: domain_default,
13099
- library: library_default,
13100
12967
  usage: usage_default,
13101
12968
  source: source_default,
13102
12969
  migrate: migrate_default
13103
12970
  }
13104
12971
  });
13105
- var devGroup = defineCommand14({
12972
+ var devGroup = defineCommand13({
13106
12973
  meta: { name: "dev", description: "Local development" },
13107
12974
  subCommands: { start: rename(dev_default, "start"), kill: kill_default }
13108
12975
  });
13109
- var testGroup = defineCommand14({
12976
+ var testGroup = defineCommand13({
13110
12977
  meta: { name: "test", description: "App tests and test tooling" },
13111
12978
  subCommands: {
13112
12979
  run: rename(test_default, "run"),
@@ -13114,7 +12981,7 @@ var testGroup = defineCommand14({
13114
12981
  accounts: rename(test_accounts_default, "accounts")
13115
12982
  }
13116
12983
  });
13117
- var main = defineCommand14({
12984
+ var main = defineCommand13({
13118
12985
  meta: {
13119
12986
  name: "deepspace",
13120
12987
  version: pkg.version,