flowviant 0.101.0 → 0.101.2

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/bin/cli.mjs CHANGED
@@ -70,6 +70,11 @@
70
70
  * env (the box keypair, the uplink scrubber, the env-comparison scan) + vault
71
71
  * (the knowledge wiki, not secrets), resources, deploy, shot.
72
72
  */
73
+ // The tray app reads `login --json` through a pipe (wsl.exe). A line written
74
+ // just before process.exit() can be dropped there, and then all the tray knows
75
+ // is that the login ended; wait for stdout to drain before exiting.
76
+ const flushStdout = () => new Promise((resolve) => process.stdout.write('', resolve));
77
+
73
78
  // Resolve --dir before config reads the project bound to cwd. A tray process
74
79
  // starts outside the checkout; its explicit folder is the daemon's checkout.
75
80
  const dirAt = process.argv.indexOf('--dir');
@@ -83,6 +88,7 @@ if (dirAt >= 0 && !noCheckoutCommand.has(process.argv[2])) {
83
88
  if (process.argv.includes('--json') && process.argv[2] === 'login')
84
89
  process.stdout.write(`${JSON.stringify({ event: 'error', message: `Cannot use directory ${dir ?? ''}: ${e.message}` })}\n`);
85
90
  else console.error(`error: cannot use directory ${dir ?? ''}: ${e.message}`);
91
+ await flushStdout();
86
92
  process.exit(1);
87
93
  }
88
94
  }
@@ -122,6 +128,7 @@ if (process.argv[2] === 'login') {
122
128
  // A login the person CANCELLED at the second-project question saved nothing,
123
129
  // so there is no credential for the child to serve — starting it would end
124
130
  // in "no credential found" over a choice they just made on purpose.
131
+ if (json) await flushStdout();
125
132
  if (!login?.saved) process.exit(1); // refused: the directory already serves another project
126
133
  if (noStart) process.exit(0);
127
134
  // Re-exec as a plain `flowviant` rather than falling through. config.mjs reads
package/bin/lib/login.mjs CHANGED
@@ -51,10 +51,14 @@ export async function runLogin({ thenStart = false, json = false, dir = process.
51
51
  // section deleted 2026-08-17; connecting a machine is offered on the surface
52
52
  // you are on when it matters, and for a new operator that is the Workbench —
53
53
  // the project's empty state says so before it can show you any sessions.
54
- if (json) event({ event: 'open_url', url: APP_URL, code: pretty });
54
+ // `/connect?code=` (2026-09-25) takes the code, asks which project, and
55
+ // approves: the code no longer has to be carried by hand into a project's
56
+ // Connect a machine panel, which is where people got lost.
57
+ const approveUrl = `${APP_URL}/connect?code=${encodeURIComponent(pretty)}`;
58
+ if (json) event({ event: 'open_url', url: approveUrl, code: pretty });
55
59
  else {
56
- console.log(` 1. Open ${c.cyan(APP_URL)} → your project → the ${c.bold('Workbench')} → ${c.bold('Connect a machine')}.`);
57
- console.log(` 2. Enter this code: ${c.bold(c.green(pretty))}\n`);
60
+ console.log(` Open ${c.cyan(approveUrl)}`);
61
+ console.log(` and approve this computer for your project. Check the code there is ${c.bold(c.green(pretty))}.\n`);
58
62
  info('waiting for you to approve…');
59
63
  }
60
64
 
@@ -259,7 +259,8 @@ export async function runUninstall(options = {}) {
259
259
  if (others && c.kind === 'path-line' && plan.copies.some((copy) => copy.kind === 'binary' && copy.current && c.block === exactBlock(dirname(copy.path), c.path))) reason = 'needed by the running binary';
260
260
  if (reason) {
261
261
  result.skipped.push({ ...item, reason });
262
- if (!json) line(`skipped ${c.path}: ${reason}`);
262
+ // The copy doing the work is not news; every other skip is.
263
+ if (!json && reason !== 'running copy') line(`skipped ${c.path}: ${reason}`);
263
264
  continue;
264
265
  }
265
266
  try {
@@ -269,7 +270,7 @@ export async function runUninstall(options = {}) {
269
270
  else if (c.kind === 'path-line') removePathBlock(o, c.path, c.block);
270
271
  else o.fs.rmSync(c.removal, { recursive: c.kind === 'npx-cache', force: true });
271
272
  result.removed.push(item);
272
- if (!json) line(`removed ${c.path}`);
273
+ if (!json) line(c.kind === 'path-line' ? `removed the flowviant PATH line from ${c.path}` : `removed ${c.path}`);
273
274
  } catch (e) { result.errors.push(`${c.path}: ${errorWords(e)}`); }
274
275
  }
275
276
  if (purge && !others) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flowviant",
3
- "version": "0.101.0",
3
+ "version": "0.101.2",
4
4
  "description": "Run your own coding CLIs as build agents for Flowviant — Claude Code, Codex or Antigravity, on your own credentials. Holds your sessions, keeps a worktree per tab, and ships branches on your word.",
5
5
  "type": "module",
6
6
  "bin": {