@vodmal/vdx-cli 0.20.0 → 0.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vodmal/vdx-cli",
3
- "version": "0.20.0",
3
+ "version": "0.20.1",
4
4
  "description": "vdx — unified lifecycle interface (up/down/build/test/check/fix) + versioned maturity audit with drift detection. Pairs with the vdx Claude Code plugin.",
5
5
  "keywords": [
6
6
  "vdx",
package/src/ai.ts CHANGED
@@ -957,6 +957,8 @@ export interface ConversationChoice {
957
957
  remote?: { host: string; id: string; reachable: boolean };
958
958
  /** Continue it here only after a yes: another machine's that cannot be asked, or one running here already. */
959
959
  askHere?: { id: string; why: string };
960
+ /** The person ended the question (Ctrl-D): start nothing. */
961
+ abort?: boolean;
960
962
  /** For the person: what was found and what is taken. */
961
963
  lines: string[];
962
964
  }
@@ -1047,7 +1049,8 @@ export function chooseConversation(plan: LaunchPlan, deps: AiDeps, canAsk: boole
1047
1049
  deps.log(' n) a new conversation');
1048
1050
  for (let tries = 0; tries < 2; tries++) {
1049
1051
  const answer = deps.ask(`Which one to continue? [1]: `);
1050
- if (answer === null) break;
1052
+ // Ctrl-D at the question is a cancel, not "no terminal": start nothing.
1053
+ if (answer === null) return { args: [], abort: true, lines: ['no answer — nothing started'] };
1051
1054
  const a = answer.trim();
1052
1055
  if (/^n(ew)?$/i.test(a)) return { args: [], lines: ['a new conversation'] };
1053
1056
  const c = a === '' ? found[0] : /^\d+$/.test(a) ? found[Number(a) - 1] : undefined;
@@ -1244,6 +1247,7 @@ export function runAi(opts: AiOptions, deps: AiDeps): number {
1244
1247
  return EXIT_OK;
1245
1248
  }
1246
1249
  for (const l of choice?.lines ?? []) log(l);
1250
+ if (choice?.abort) return EXIT_LAUNCH_FAILED;
1247
1251
 
1248
1252
  let askHere = choice?.askHere;
1249
1253
  if (choice?.remote) {
package/src/publish.ts CHANGED
@@ -392,6 +392,8 @@ export interface PublishDeps {
392
392
  sleep: (ms: number) => void;
393
393
  /** How long to wait for the registry to show the new version. */
394
394
  registryWaitMs: number;
395
+ /** Rewrites one status line in place (a terminal); without it the wait logs a line now and then. */
396
+ progress?: (text: string) => void;
395
397
  }
396
398
 
397
399
  function sleepSync(ms: number): void {
@@ -407,6 +409,7 @@ export function defaultPublishDeps(): PublishDeps {
407
409
  log: (line) => process.stderr.write(line + '\n'),
408
410
  sleep: sleepSync,
409
411
  registryWaitMs: 180_000,
412
+ progress: process.stderr.isTTY ? (text) => process.stderr.write(`\r${text}\x1b[K`) : undefined,
410
413
  };
411
414
  }
412
415
 
@@ -427,19 +430,38 @@ export function bumpLockText(text: string, version: string): string {
427
430
  export function waitForRegistry(name: string, version: string, deps: PublishDeps): boolean {
428
431
  const started = Date.now();
429
432
  const deadline = started + deps.registryWaitMs;
430
- deps.log(`→ waiting for the registry to show ${name}@${version}...`);
431
- for (;;) {
433
+ const limit = Math.round(deps.registryWaitMs / 1000);
434
+ const seconds = () => Math.round((Date.now() - started) / 1000);
435
+ deps.log(
436
+ `→ waiting for the registry to show ${name}@${version} — npm has taken it; ` +
437
+ `the registry usually shows it within ~2 min (giving it ${limit} s)`,
438
+ );
439
+ const shown = () => {
432
440
  try {
433
- if (deps.npm(['view', `${name}@${version}`, 'version', '--prefer-online']).trim() === version) {
434
- deps.log(`✓ ${name}@${version} is on the registry (${Math.round((Date.now() - started) / 1000)} s after publish)`);
435
- return true;
436
- }
441
+ return deps.npm(['view', `${name}@${version}`, 'version', '--prefer-online']).trim() === version;
437
442
  } catch {
438
- /* E404 until it is processed */
443
+ return false; // E404 until it is processed
444
+ }
445
+ };
446
+ // Ask npm every 10 s; between the asks, count the seconds on one line.
447
+ let lastLogged = 0;
448
+ for (let found = shown(); ; found = shown()) {
449
+ if (found) {
450
+ deps.progress?.('');
451
+ deps.log(`✓ ${name}@${version} is on the registry (${seconds()} s after publish)`);
452
+ return true;
439
453
  }
440
454
  if (Date.now() >= deadline) break;
441
- deps.sleep(10_000);
455
+ for (let i = 0; i < 10 && Date.now() < deadline; i++) {
456
+ if (deps.progress) deps.progress(` … ${seconds()} s of ${limit} s`);
457
+ else if (seconds() - lastLogged >= 30) {
458
+ lastLogged = seconds();
459
+ deps.log(` … ${lastLogged} s`);
460
+ }
461
+ deps.sleep(1_000);
462
+ }
442
463
  }
464
+ deps.progress?.('');
443
465
  deps.log(
444
466
  `! ${name}@${version} not visible on the registry after ${Math.round(deps.registryWaitMs / 60_000)} min — ` +
445
467
  `npm accepted it; check later: npm view ${name}@${version} version`,