@whoz-oss/coday-web 0.0.0-workstream-forge.205 → 0.0.0-workstream-forge.207

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/index.js +50 -1
  2. package/launcher.js +37 -2
  3. package/package.json +7 -4
package/index.js CHANGED
@@ -4,7 +4,17 @@ import { dirname, resolve } from 'path';
4
4
  import { existsSync } from 'fs';
5
5
  import { spawn, spawnSync } from 'child_process';
6
6
  import { createRequire } from 'module';
7
- import { chooseMode, nxArgs, nxEnv, parseWorkspaceDir, resolveConfigDir, serverArgs } from './launcher.js';
7
+ import {
8
+ chooseMode,
9
+ nxArgs,
10
+ nxEnv,
11
+ parseWorkspaceDir,
12
+ resolveConfigDir,
13
+ serverArgs,
14
+ shouldRunDoctor,
15
+ wantsDoctorOnly,
16
+ withoutCommand,
17
+ } from './launcher.js';
8
18
 
9
19
  const __filename = fileURLToPath(import.meta.url);
10
20
  const __dirname = dirname(__filename);
@@ -17,6 +27,9 @@ const __dirname = dirname(__filename);
17
27
  * bundled `nx` on it, so the server, AgentOS and the Factory each get their own pane and log file.
18
28
  * 3. No TTY (desktop apps), --managed or CODAY_NO_NX=1: runs everything inside the server process,
19
29
  * exactly like before (it still prints `Server is running on http://localhost:PORT`).
30
+ *
31
+ * Before 2, it runs the `doctor` preflight (implemented in the bundled server, nothing duplicated here) so that a
32
+ * missing Java or an unwritable config directory is said in plain scrollback, not inside an Nx pane that scrolls away.
20
33
  */
21
34
 
22
35
  // Create require function for resolving packages
@@ -151,7 +164,43 @@ function runNx() {
151
164
  return undefined;
152
165
  }
153
166
 
167
+ /**
168
+ * The exit code `doctor` uses for "a check blocks the start" (DOCTOR_BLOCKED_EXIT in
169
+ * apps/server/src/lib/runtime/doctor.ts). It is deliberately not 1: that is what the server exits with on any
170
+ * unhandled error, and a preflight that merely crashed must never be what stops Coday.
171
+ */
172
+ const DOCTOR_BLOCKED_EXIT = 2;
173
+
174
+ /** Run the bundled server's `doctor`, inheriting the terminal so it prints its own report. */
175
+ function runDoctor(argv) {
176
+ return spawnSync(process.execPath, [serverMainPath, 'doctor', ...serverArgs(argv)], {
177
+ stdio: 'inherit',
178
+ env: process.env,
179
+ });
180
+ }
181
+
182
+ /**
183
+ * Preflight before the Nx TUI takes the terminal. Only a genuine blocker stops the start; anything else (a spawn
184
+ * error, a signal, a crash of the preflight itself) warns and carries on, like `runNx` falls back when the
185
+ * `workspace` command fails.
186
+ */
187
+ function preflight() {
188
+ if (!shouldRunDoctor({ mode, argv: rawArgs, env: process.env })) return;
189
+ const result = runDoctor(rawArgs);
190
+ if (result.status === 0) return;
191
+ if (result.status === DOCTOR_BLOCKED_EXIT) process.exit(result.status);
192
+ const why = result.error?.message ?? (result.signal ? `killed by ${result.signal}` : `exit code ${result.status}`);
193
+ console.warn(`Preflight could not run (${why}): starting anyway.`);
194
+ }
195
+
196
+ // `coday-web doctor`: the report is the whole job, whatever the terminal is.
197
+ if (wantsDoctorOnly(rawArgs)) {
198
+ const result = runDoctor(withoutCommand(rawArgs));
199
+ process.exit(result.error ? 1 : (result.status ?? 1));
200
+ }
201
+
154
202
  console.log(`Coday Web: ${mode} mode (${reason})`);
203
+ preflight();
155
204
  (mode === 'nx' ? Promise.resolve().then(runNx) : runManaged()).catch((error) => {
156
205
  console.error('Failed to start server:', error);
157
206
  process.exit(1);
package/launcher.js CHANGED
@@ -34,9 +34,44 @@ export function resolveConfigDir(argv, home = homedir()) {
34
34
  return join(home, '.coday');
35
35
  }
36
36
 
37
- /** The arguments the server must see: the launcher's own (`--managed`) are removed. */
37
+ /** Flags the launcher handles itself; the server never sees them. Both `--flag` and `--flag=value` forms. */
38
+ const LAUNCHER_FLAGS = ['--managed', '--skip-doctor'];
39
+
40
+ const hasFlag = (argv, flag) => argv.some((a) => a === flag || a.startsWith(`${flag}=`));
41
+
42
+ /** The arguments the server must see: the launcher's own are removed. */
38
43
  export function serverArgs(argv) {
39
- return argv.filter((a) => a !== '--managed');
44
+ return argv.filter((a) => !LAUNCHER_FLAGS.some((flag) => a === flag || a.startsWith(`${flag}=`)));
45
+ }
46
+
47
+ /**
48
+ * `coday-web doctor`: run the preflight and nothing else. Same rule as the bundled server's `parseCommand` (the
49
+ * first positional wins), so the command means the same thing with or without a terminal — without this the Nx
50
+ * branch would print the report and then start the whole stack, which is not what anyone typing `doctor` wants.
51
+ */
52
+ export function wantsDoctorOnly(argv) {
53
+ return argv.find((a) => !a.startsWith('-')) === 'doctor';
54
+ }
55
+
56
+ /** The same arguments without that leading command word, so it is not handed to the server twice. */
57
+ export function withoutCommand(argv) {
58
+ const at = argv.findIndex((a) => !a.startsWith('-'));
59
+ return at === -1 ? argv : [...argv.slice(0, at), ...argv.slice(at + 1)];
60
+ }
61
+
62
+ /**
63
+ * Whether to run the `doctor` preflight before starting.
64
+ *
65
+ * Only in `nx` mode, and for one reason: the Nx TUI is about to take the terminal, so a blocking problem must be said
66
+ * in plain scrollback first. The managed mode is the desktop apps, which have their own installer and show the same
67
+ * facts in the first-run wizard, so they are left alone (and spared the extra process).
68
+ *
69
+ * `--skip-doctor` / `CODAY_SKIP_DOCTOR=1` bypasses it, for anyone who knows better than the checks.
70
+ */
71
+ export function shouldRunDoctor({ mode, argv, env }) {
72
+ if (mode !== 'nx') return false;
73
+ if (hasFlag(argv, '--skip-doctor')) return false;
74
+ return !(env.CODAY_SKIP_DOCTOR === '1' || env.CODAY_SKIP_DOCTOR === 'true');
40
75
  }
41
76
 
42
77
  /** Marker the server's `workspace` command prints before the directory it generated. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@whoz-oss/coday-web",
3
- "version": "0.0.0-workstream-forge.205",
3
+ "version": "0.0.0-workstream-forge.207",
4
4
  "repository": "https://github.com/whoz-oss/coday",
5
5
  "type": "module",
6
6
  "bin": {
@@ -13,9 +13,12 @@
13
13
  ],
14
14
  "dependencies": {
15
15
  "nx": "23.1.1",
16
- "@whoz-oss/coday-client": "0.0.0-workstream-forge.205",
17
- "@whoz-oss/coday-factory-cockpit": "0.0.0-workstream-forge.205",
18
- "@whoz-oss/coday-server": "0.0.0-workstream-forge.205"
16
+ "@whoz-oss/coday-client": "0.0.0-workstream-forge.207",
17
+ "@whoz-oss/coday-factory-cockpit": "0.0.0-workstream-forge.207",
18
+ "@whoz-oss/coday-server": "0.0.0-workstream-forge.207"
19
+ },
20
+ "engines": {
21
+ "node": ">=22"
19
22
  },
20
23
  "publishConfig": {
21
24
  "access": "public"