kaizenai 0.2.1 → 0.2.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.
@@ -1,6 +1,6 @@
1
- import process from "node:process"
2
- import { spawnSync } from "node:child_process"
3
- import { hasCommand, spawnDetached } from "./process-utils"
1
+ import process from 'node:process';
2
+ import { spawnSync } from 'node:child_process';
3
+ import { hasCommand, spawnDetached } from './process-utils';
4
4
  import {
5
5
  APP_NAME,
6
6
  CLI_COMMAND,
@@ -8,71 +8,83 @@ import {
8
8
  getDataDirDisplay,
9
9
  LOG_PREFIX,
10
10
  PACKAGE_NAME,
11
- } from "../shared/branding"
12
- import type { UpdateInstallErrorCode } from "../shared/types"
13
- import { PROD_SERVER_PORT } from "../shared/ports"
14
- import { CLI_SUPPRESS_OPEN_ONCE_ENV_VAR } from "./restart"
11
+ } from '../shared/branding';
12
+ import type { UpdateInstallErrorCode } from '../shared/types';
13
+ import { PROD_SERVER_PORT } from '../shared/ports';
14
+ import {
15
+ CLI_SKIP_STARTUP_UPDATE_ONCE_ENV_VAR,
16
+ CLI_SUPPRESS_OPEN_ONCE_ENV_VAR,
17
+ shouldSkipStartupUpdateOnce,
18
+ } from './restart';
15
19
 
16
20
  export interface CliOptions {
17
- port: number
18
- host: string
19
- openBrowser: boolean
20
- strictPort: boolean
21
+ port: number;
22
+ host: string;
23
+ openBrowser: boolean;
24
+ strictPort: boolean;
21
25
  }
22
26
 
23
27
  export interface CliUpdateOptions {
24
- version: string
25
- fetchLatestVersion: (packageName: string) => Promise<string>
26
- installVersion: (packageName: string, version: string) => UpdateInstallAttemptResult
27
- argv: string[]
28
- command: string
28
+ version: string;
29
+ fetchLatestVersion: (packageName: string) => Promise<string>;
30
+ installVersion: (
31
+ packageName: string,
32
+ version: string
33
+ ) => UpdateInstallAttemptResult;
34
+ argv: string[];
35
+ command: string;
29
36
  }
30
37
 
31
38
  export interface StartedCli {
32
- kind: "started"
33
- stop: () => Promise<void>
39
+ kind: 'started';
40
+ stop: () => Promise<void>;
34
41
  }
35
42
 
36
43
  export interface RestartingCli {
37
- kind: "restarting"
38
- reason: "startup_update" | "ui_update"
44
+ kind: 'restarting';
45
+ reason: 'startup_update' | 'ui_update';
39
46
  }
40
47
 
41
48
  export interface ExitedCli {
42
- kind: "exited"
43
- code: number
49
+ kind: 'exited';
50
+ code: number;
44
51
  }
45
52
 
46
- export type CliRunResult = StartedCli | RestartingCli | ExitedCli
53
+ export type CliRunResult = StartedCli | RestartingCli | ExitedCli;
47
54
 
48
55
  export interface CliRuntimeDeps {
49
- version: string
50
- bunVersion: string
51
- allowSelfUpdate?: boolean
52
- startServer: (options: CliOptions & {
53
- update: CliUpdateOptions
54
- onMigrationProgress?: (message: string) => void
55
- }) => Promise<{ port: number; stop: () => Promise<void> }>
56
- fetchLatestVersion: (packageName: string) => Promise<string>
57
- installVersion: (packageName: string, version: string) => UpdateInstallAttemptResult
58
- openUrl: (url: string) => void
59
- log: (message: string) => void
60
- warn: (message: string) => void
56
+ version: string;
57
+ bunVersion: string;
58
+ allowSelfUpdate?: boolean;
59
+ startServer: (
60
+ options: CliOptions & {
61
+ update: CliUpdateOptions;
62
+ onMigrationProgress?: (message: string) => void;
63
+ }
64
+ ) => Promise<{ port: number; stop: () => Promise<void> }>;
65
+ fetchLatestVersion: (packageName: string) => Promise<string>;
66
+ installVersion: (
67
+ packageName: string,
68
+ version: string
69
+ ) => UpdateInstallAttemptResult;
70
+ openUrl: (url: string) => void;
71
+ log: (message: string) => void;
72
+ warn: (message: string) => void;
61
73
  }
62
74
 
63
75
  export interface UpdateInstallAttemptResult {
64
- ok: boolean
65
- errorCode: UpdateInstallErrorCode | null
66
- userTitle: string | null
67
- userMessage: string | null
76
+ ok: boolean;
77
+ errorCode: UpdateInstallErrorCode | null;
78
+ userTitle: string | null;
79
+ userMessage: string | null;
68
80
  }
69
81
 
70
82
  type ParsedArgs =
71
- | { kind: "run"; options: CliOptions }
72
- | { kind: "help" }
73
- | { kind: "version" }
83
+ | { kind: 'run'; options: CliOptions }
84
+ | { kind: 'help' }
85
+ | { kind: 'version' };
74
86
 
75
- const MINIMUM_BUN_VERSION = "1.3.5"
87
+ const MINIMUM_BUN_VERSION = '1.3.5';
76
88
 
77
89
  function printHelp() {
78
90
  console.log(`${APP_NAME} — local-only project chat UI
@@ -87,144 +99,161 @@ Options:
87
99
  --strict-port Fail instead of trying another port
88
100
  --no-open Don't open browser automatically
89
101
  --version Print version and exit
90
- --help Show this help message`)
102
+ --help Show this help message`);
91
103
  }
92
104
 
93
105
  export function parseArgs(argv: string[]): ParsedArgs {
94
- let port = PROD_SERVER_PORT
95
- let host = "127.0.0.1"
96
- let openBrowser = true
97
- let strictPort = false
106
+ let port = PROD_SERVER_PORT;
107
+ let host = '127.0.0.1';
108
+ let openBrowser = true;
109
+ let strictPort = false;
98
110
 
99
111
  for (let index = 0; index < argv.length; index += 1) {
100
- const arg = argv[index]
101
- if (arg === "--version" || arg === "-v") {
102
- return { kind: "version" }
112
+ const arg = argv[index];
113
+ if (arg === '--version' || arg === '-v') {
114
+ return { kind: 'version' };
103
115
  }
104
- if (arg === "--help" || arg === "-h") {
105
- return { kind: "help" }
116
+ if (arg === '--help' || arg === '-h') {
117
+ return { kind: 'help' };
106
118
  }
107
- if (arg === "--port") {
108
- const next = argv[index + 1]
109
- if (!next) throw new Error("Missing value for --port")
110
- port = Number(next)
111
- index += 1
112
- continue
119
+ if (arg === '--port') {
120
+ const next = argv[index + 1];
121
+ if (!next) throw new Error('Missing value for --port');
122
+ port = Number(next);
123
+ index += 1;
124
+ continue;
113
125
  }
114
- if (arg === "--host") {
115
- const next = argv[index + 1]
116
- if (!next || next.startsWith("-")) throw new Error("Missing value for --host")
117
- host = next
118
- index += 1
119
- continue
126
+ if (arg === '--host') {
127
+ const next = argv[index + 1];
128
+ if (!next || next.startsWith('-'))
129
+ throw new Error('Missing value for --host');
130
+ host = next;
131
+ index += 1;
132
+ continue;
120
133
  }
121
- if (arg === "--remote") {
122
- host = "0.0.0.0"
123
- continue
134
+ if (arg === '--remote') {
135
+ host = '0.0.0.0';
136
+ continue;
124
137
  }
125
- if (arg === "--no-open") {
126
- openBrowser = false
127
- continue
138
+ if (arg === '--no-open') {
139
+ openBrowser = false;
140
+ continue;
128
141
  }
129
- if (arg === "--strict-port") {
130
- strictPort = true
131
- continue
142
+ if (arg === '--strict-port') {
143
+ strictPort = true;
144
+ continue;
132
145
  }
133
- if (!arg.startsWith("-")) throw new Error(`Unexpected positional argument: ${arg}`)
146
+ if (!arg.startsWith('-'))
147
+ throw new Error(`Unexpected positional argument: ${arg}`);
134
148
  }
135
149
 
136
150
  return {
137
- kind: "run",
151
+ kind: 'run',
138
152
  options: {
139
153
  port,
140
154
  host,
141
155
  openBrowser,
142
156
  strictPort,
143
157
  },
144
- }
158
+ };
145
159
  }
146
160
 
147
161
  export function compareVersions(currentVersion: string, latestVersion: string) {
148
- const currentParts = normalizeVersion(currentVersion)
149
- const latestParts = normalizeVersion(latestVersion)
150
- const length = Math.max(currentParts.length, latestParts.length)
162
+ const currentParts = normalizeVersion(currentVersion);
163
+ const latestParts = normalizeVersion(latestVersion);
164
+ const length = Math.max(currentParts.length, latestParts.length);
151
165
 
152
166
  for (let index = 0; index < length; index += 1) {
153
- const current = currentParts[index] ?? 0
154
- const latest = latestParts[index] ?? 0
155
- if (current === latest) continue
156
- return current < latest ? -1 : 1
167
+ const current = currentParts[index] ?? 0;
168
+ const latest = latestParts[index] ?? 0;
169
+ if (current === latest) continue;
170
+ return current < latest ? -1 : 1;
157
171
  }
158
172
 
159
- return 0
173
+ return 0;
160
174
  }
161
175
 
162
176
  function normalizeVersion(version: string) {
163
177
  return version
164
178
  .trim()
165
- .replace(/^v/i, "")
166
- .split("-")[0]
167
- .split(".")
179
+ .replace(/^v/i, '')
180
+ .split('-')[0]
181
+ .split('.')
168
182
  .map((part) => Number.parseInt(part, 10))
169
- .filter((part) => Number.isFinite(part))
183
+ .filter((part) => Number.isFinite(part));
170
184
  }
171
185
 
172
186
  async function maybeSelfUpdate(_argv: string[], deps: CliRuntimeDeps) {
173
- if (process.env[DISABLE_SELF_UPDATE_ENV_VAR] === "1") {
174
- return null
187
+ if (process.env[DISABLE_SELF_UPDATE_ENV_VAR] === '1') {
188
+ return null;
189
+ }
190
+
191
+ if (
192
+ shouldSkipStartupUpdateOnce(
193
+ process.env[CLI_SKIP_STARTUP_UPDATE_ONCE_ENV_VAR]
194
+ )
195
+ ) {
196
+ deps.warn(
197
+ `${LOG_PREFIX} skipping startup update after restart to avoid an update loop`
198
+ );
199
+ return null;
175
200
  }
176
201
 
177
- deps.log(`${LOG_PREFIX} checking for updates`)
202
+ deps.log(`${LOG_PREFIX} checking for updates`);
178
203
 
179
- let latestVersion: string
204
+ let latestVersion: string;
180
205
  try {
181
- latestVersion = await deps.fetchLatestVersion(PACKAGE_NAME)
182
- }
183
- catch (error) {
184
- deps.warn(`${LOG_PREFIX} update check failed, continuing current version`)
206
+ latestVersion = await deps.fetchLatestVersion(PACKAGE_NAME);
207
+ } catch (error) {
208
+ deps.warn(`${LOG_PREFIX} update check failed, continuing current version`);
185
209
  if (error instanceof Error && error.message) {
186
- deps.warn(`${LOG_PREFIX} ${error.message}`)
210
+ deps.warn(`${LOG_PREFIX} ${error.message}`);
187
211
  }
188
- return null
212
+ return null;
189
213
  }
190
214
 
191
215
  if (!latestVersion || compareVersions(deps.version, latestVersion) >= 0) {
192
- return null
216
+ return null;
193
217
  }
194
218
 
195
- deps.log(`${LOG_PREFIX} installing ${PACKAGE_NAME}@${latestVersion}`)
196
- const installResult = deps.installVersion(PACKAGE_NAME, latestVersion)
219
+ deps.log(`${LOG_PREFIX} installing ${PACKAGE_NAME}@${latestVersion}`);
220
+ const installResult = deps.installVersion(PACKAGE_NAME, latestVersion);
197
221
  if (!installResult.ok) {
198
- deps.warn(`${LOG_PREFIX} update failed, continuing current version`)
222
+ deps.warn(`${LOG_PREFIX} update failed, continuing current version`);
199
223
  if (installResult.userMessage) {
200
- deps.warn(`${LOG_PREFIX} ${installResult.userMessage}`)
224
+ deps.warn(`${LOG_PREFIX} ${installResult.userMessage}`);
201
225
  }
202
- return null
226
+ return null;
203
227
  }
204
228
 
205
- deps.log(`${LOG_PREFIX} restarting into updated version`)
206
- return "startup_update"
229
+ deps.log(`${LOG_PREFIX} restarting into updated version`);
230
+ return 'startup_update';
207
231
  }
208
232
 
209
- export async function runCli(argv: string[], deps: CliRuntimeDeps): Promise<CliRunResult> {
210
- const parsedArgs = parseArgs(argv)
211
- if (parsedArgs.kind === "version") {
212
- deps.log(deps.version)
213
- return { kind: "exited", code: 0 }
233
+ export async function runCli(
234
+ argv: string[],
235
+ deps: CliRuntimeDeps
236
+ ): Promise<CliRunResult> {
237
+ const parsedArgs = parseArgs(argv);
238
+ if (parsedArgs.kind === 'version') {
239
+ deps.log(deps.version);
240
+ return { kind: 'exited', code: 0 };
214
241
  }
215
- if (parsedArgs.kind === "help") {
216
- printHelp()
217
- return { kind: "exited", code: 0 }
242
+ if (parsedArgs.kind === 'help') {
243
+ printHelp();
244
+ return { kind: 'exited', code: 0 };
218
245
  }
219
246
  if (compareVersions(deps.bunVersion, MINIMUM_BUN_VERSION) < 0) {
220
- deps.warn(`${LOG_PREFIX} Bun ${MINIMUM_BUN_VERSION}+ is required for the embedded terminal. Current Bun: ${deps.bunVersion}`)
221
- return { kind: "exited", code: 1 }
247
+ deps.warn(
248
+ `${LOG_PREFIX} Bun ${MINIMUM_BUN_VERSION}+ is required for the embedded terminal. Current Bun: ${deps.bunVersion}`
249
+ );
250
+ return { kind: 'exited', code: 1 };
222
251
  }
223
252
 
224
253
  if (deps.allowSelfUpdate !== false) {
225
- const shouldRestart = await maybeSelfUpdate(argv, deps)
254
+ const shouldRestart = await maybeSelfUpdate(argv, deps);
226
255
  if (shouldRestart !== null) {
227
- return { kind: "restarting", reason: shouldRestart }
256
+ return { kind: 'restarting', reason: shouldRestart };
228
257
  }
229
258
  }
230
259
 
@@ -238,96 +267,109 @@ export async function runCli(argv: string[], deps: CliRuntimeDeps): Promise<CliR
238
267
  argv,
239
268
  command: CLI_COMMAND,
240
269
  },
241
- })
242
- const bindHost = parsedArgs.options.host
243
- const displayHost = bindHost === "127.0.0.1" || bindHost === "0.0.0.0" ? "localhost" : bindHost
244
- const launchUrl = `http://${displayHost}:${port}`
270
+ });
271
+ const bindHost = parsedArgs.options.host;
272
+ const displayHost =
273
+ bindHost === '127.0.0.1' || bindHost === '0.0.0.0' ? 'localhost' : bindHost;
274
+ const launchUrl = `http://${displayHost}:${port}`;
245
275
 
246
- deps.log(`${LOG_PREFIX} listening on http://${bindHost}:${port}`)
247
- deps.log(`${LOG_PREFIX} data dir: ${getDataDirDisplay()}`)
276
+ deps.log(`${LOG_PREFIX} listening on http://${bindHost}:${port}`);
277
+ deps.log(`${LOG_PREFIX} data dir: ${getDataDirDisplay()}`);
248
278
 
249
- const suppressOpenBrowser = process.env[CLI_SUPPRESS_OPEN_ONCE_ENV_VAR] === "1"
279
+ const suppressOpenBrowser =
280
+ process.env[CLI_SUPPRESS_OPEN_ONCE_ENV_VAR] === '1';
250
281
  if (parsedArgs.options.openBrowser && !suppressOpenBrowser) {
251
- deps.openUrl(launchUrl)
282
+ deps.openUrl(launchUrl);
252
283
  }
253
284
 
254
285
  return {
255
- kind: "started",
286
+ kind: 'started',
256
287
  stop,
257
- }
288
+ };
258
289
  }
259
290
 
260
291
  export function openUrl(url: string) {
261
- const platform = process.platform
262
- if (platform === "darwin") {
263
- spawnDetached("open", [url])
264
- } else if (platform === "win32") {
265
- spawnDetached("cmd", ["/c", "start", "", url])
292
+ const platform = process.platform;
293
+ if (platform === 'darwin') {
294
+ spawnDetached('open', [url]);
295
+ } else if (platform === 'win32') {
296
+ spawnDetached('cmd', ['/c', 'start', '', url]);
266
297
  } else {
267
- spawnDetached("xdg-open", [url])
298
+ spawnDetached('xdg-open', [url]);
268
299
  }
269
- console.log(`${LOG_PREFIX} opened in default browser`)
300
+ console.log(`${LOG_PREFIX} opened in default browser`);
270
301
  }
271
302
 
272
303
  export async function fetchLatestPackageVersion(packageName: string) {
273
- const response = await fetch(`https://registry.npmjs.org/${encodeURIComponent(packageName)}/latest`)
304
+ const response = await fetch(
305
+ `https://registry.npmjs.org/${encodeURIComponent(packageName)}/latest`
306
+ );
274
307
  if (!response.ok) {
275
- throw new Error(`registry returned ${response.status}`)
308
+ throw new Error(`registry returned ${response.status}`);
276
309
  }
277
310
 
278
- const payload = await response.json() as { version?: unknown }
279
- if (typeof payload.version !== "string" || !payload.version.trim()) {
280
- throw new Error("registry response did not include a version")
311
+ const payload = (await response.json()) as { version?: unknown };
312
+ if (typeof payload.version !== 'string' || !payload.version.trim()) {
313
+ throw new Error('registry response did not include a version');
281
314
  }
282
315
 
283
- return payload.version
316
+ return payload.version;
284
317
  }
285
318
 
286
- export function classifyInstallVersionFailure(output: string): UpdateInstallAttemptResult {
287
- const normalizedOutput = output.trim()
288
- if (/No version matching .* found|failed to resolve/i.test(normalizedOutput)) {
319
+ export function classifyInstallVersionFailure(
320
+ output: string
321
+ ): UpdateInstallAttemptResult {
322
+ const normalizedOutput = output.trim();
323
+ if (
324
+ /No version matching .* found|failed to resolve/i.test(normalizedOutput)
325
+ ) {
289
326
  return {
290
327
  ok: false,
291
- errorCode: "version_not_live_yet",
292
- userTitle: "Update not live yet",
293
- userMessage: "This update is still propagating. Try again in a few minutes.",
294
- }
328
+ errorCode: 'version_not_live_yet',
329
+ userTitle: 'Update not live yet',
330
+ userMessage:
331
+ 'This update is still propagating. Try again in a few minutes.',
332
+ };
295
333
  }
296
334
 
297
335
  return {
298
336
  ok: false,
299
- errorCode: "install_failed",
300
- userTitle: "Update failed",
301
- userMessage: "Kaizen could not install the update. Try again later.",
302
- }
337
+ errorCode: 'install_failed',
338
+ userTitle: 'Update failed',
339
+ userMessage: 'Kaizen could not install the update. Try again later.',
340
+ };
303
341
  }
304
342
 
305
343
  export function installPackageVersion(packageName: string, version: string) {
306
- if (!hasCommand("bun")) {
344
+ if (!hasCommand('bun')) {
307
345
  return {
308
346
  ok: false,
309
- errorCode: "command_missing",
310
- userTitle: "Bun not found",
311
- userMessage: "Kaizen could not find Bun to install the update.",
312
- } satisfies UpdateInstallAttemptResult
347
+ errorCode: 'command_missing',
348
+ userTitle: 'Bun not found',
349
+ userMessage: 'Kaizen could not find Bun to install the update.',
350
+ } satisfies UpdateInstallAttemptResult;
313
351
  }
314
352
 
315
- const result = spawnSync("bun", ["install", "-g", `${packageName}@${version}`], {
316
- stdio: ["ignore", "pipe", "pipe"],
317
- encoding: "utf8",
318
- })
319
- const stdout = result.stdout ?? ""
320
- const stderr = result.stderr ?? ""
321
- if (stdout) process.stdout.write(stdout)
322
- if (stderr) process.stderr.write(stderr)
353
+ const result = spawnSync(
354
+ 'bun',
355
+ ['install', '-g', `${packageName}@${version}`],
356
+ {
357
+ stdio: ['ignore', 'pipe', 'pipe'],
358
+ encoding: 'utf8',
359
+ }
360
+ );
361
+ const stdout = result.stdout ?? '';
362
+ const stderr = result.stderr ?? '';
363
+ if (stdout) process.stdout.write(stdout);
364
+ if (stderr) process.stderr.write(stderr);
323
365
  if (result.status === 0) {
324
366
  return {
325
367
  ok: true,
326
368
  errorCode: null,
327
369
  userTitle: null,
328
370
  userMessage: null,
329
- } satisfies UpdateInstallAttemptResult
371
+ } satisfies UpdateInstallAttemptResult;
330
372
  }
331
373
 
332
- return classifyInstallVersionFailure(`${stdout}\n${stderr}`)
374
+ return classifyInstallVersionFailure(`${stdout}\n${stderr}`);
333
375
  }
@@ -1,81 +1,97 @@
1
- import process from "node:process"
2
- import { spawn } from "node:child_process"
3
- import { CLI_COMMAND, LOG_PREFIX } from "../shared/branding"
1
+ import process from 'node:process';
2
+ import { spawn } from 'node:child_process';
3
+ import { CLI_COMMAND, LOG_PREFIX } from '../shared/branding';
4
4
  import {
5
5
  CLI_CHILD_ARGS_ENV_VAR,
6
6
  CLI_CHILD_COMMAND_ENV_VAR,
7
7
  CLI_CHILD_MODE,
8
8
  CLI_CHILD_MODE_ENV_VAR,
9
+ CLI_SKIP_STARTUP_UPDATE_ONCE_ENV_VAR,
9
10
  CLI_SUPPRESS_OPEN_ONCE_ENV_VAR,
11
+ isStartupUpdateRestart,
10
12
  isUiUpdateRestart,
11
13
  parseChildArgsEnv,
12
14
  shouldRestartCliProcess,
13
- } from "./restart"
15
+ } from './restart';
14
16
 
15
17
  interface ChildExit {
16
- code: number | null
17
- signal: NodeJS.Signals | null
18
+ code: number | null;
19
+ signal: NodeJS.Signals | null;
18
20
  }
19
21
 
20
22
  function getChildProcessSpec() {
21
- const command = process.env[CLI_CHILD_COMMAND_ENV_VAR] || CLI_COMMAND
22
- const args = parseChildArgsEnv(process.env[CLI_CHILD_ARGS_ENV_VAR])
23
- return { command, args }
23
+ const command = process.env[CLI_CHILD_COMMAND_ENV_VAR] || CLI_COMMAND;
24
+ const args = parseChildArgsEnv(process.env[CLI_CHILD_ARGS_ENV_VAR]);
25
+ return { command, args };
24
26
  }
25
27
 
26
28
  function spawnChild(argv: string[]) {
27
- const childProcess = getChildProcessSpec()
28
- const suppressOpenThisChild = suppressOpenOnNextChild
29
- suppressOpenOnNextChild = false
29
+ const childProcess = getChildProcessSpec();
30
+ const suppressOpenThisChild = suppressOpenOnNextChild;
31
+ const skipStartupUpdateThisChild = skipStartupUpdateOnNextChild;
32
+ suppressOpenOnNextChild = false;
33
+ skipStartupUpdateOnNextChild = false;
30
34
  return new Promise<ChildExit>((resolve, reject) => {
31
35
  const child = spawn(childProcess.command, [...childProcess.args, ...argv], {
32
- stdio: "inherit",
36
+ stdio: 'inherit',
33
37
  env: {
34
38
  ...process.env,
35
39
  [CLI_CHILD_MODE_ENV_VAR]: CLI_CHILD_MODE,
36
- ...(suppressOpenThisChild ? { [CLI_SUPPRESS_OPEN_ONCE_ENV_VAR]: "1" } : {}),
40
+ ...(suppressOpenThisChild
41
+ ? { [CLI_SUPPRESS_OPEN_ONCE_ENV_VAR]: '1' }
42
+ : {}),
43
+ ...(skipStartupUpdateThisChild
44
+ ? { [CLI_SKIP_STARTUP_UPDATE_ONCE_ENV_VAR]: '1' }
45
+ : {}),
37
46
  },
38
- })
47
+ });
39
48
 
40
49
  const forwardSignal = (signal: NodeJS.Signals) => {
41
- if (child.exitCode !== null) return
42
- child.kill(signal)
43
- }
50
+ if (child.exitCode !== null) return;
51
+ child.kill(signal);
52
+ };
44
53
 
45
54
  const onSigint = () => {
46
- forwardSignal("SIGINT")
47
- }
55
+ forwardSignal('SIGINT');
56
+ };
48
57
  const onSigterm = () => {
49
- forwardSignal("SIGTERM")
50
- }
58
+ forwardSignal('SIGTERM');
59
+ };
51
60
 
52
- process.on("SIGINT", onSigint)
53
- process.on("SIGTERM", onSigterm)
61
+ process.on('SIGINT', onSigint);
62
+ process.on('SIGTERM', onSigterm);
54
63
 
55
- child.once("error", (error) => {
56
- process.off("SIGINT", onSigint)
57
- process.off("SIGTERM", onSigterm)
58
- reject(error)
59
- })
64
+ child.once('error', (error) => {
65
+ process.off('SIGINT', onSigint);
66
+ process.off('SIGTERM', onSigterm);
67
+ reject(error);
68
+ });
60
69
 
61
- child.once("exit", (code, signal) => {
62
- process.off("SIGINT", onSigint)
63
- process.off("SIGTERM", onSigterm)
64
- resolve({ code, signal })
65
- })
66
- })
70
+ child.once('exit', (code, signal) => {
71
+ process.off('SIGINT', onSigint);
72
+ process.off('SIGTERM', onSigterm);
73
+ resolve({ code, signal });
74
+ });
75
+ });
67
76
  }
68
77
 
69
- const argv = process.argv.slice(2)
70
- let suppressOpenOnNextChild = false
78
+ const argv = process.argv.slice(2);
79
+ let suppressOpenOnNextChild = false;
80
+ let skipStartupUpdateOnNextChild = false;
71
81
 
72
82
  while (true) {
73
- const result = await spawnChild(argv)
83
+ const result = await spawnChild(argv);
74
84
  if (shouldRestartCliProcess(result.code, result.signal)) {
75
- suppressOpenOnNextChild = isUiUpdateRestart(result.code, result.signal)
76
- console.log(`${LOG_PREFIX} supervisor restarting ${CLI_COMMAND} in the same terminal session`)
77
- continue
85
+ suppressOpenOnNextChild = isUiUpdateRestart(result.code, result.signal);
86
+ skipStartupUpdateOnNextChild = isStartupUpdateRestart(
87
+ result.code,
88
+ result.signal
89
+ );
90
+ console.log(
91
+ `${LOG_PREFIX} supervisor restarting ${CLI_COMMAND} in the same terminal session`
92
+ );
93
+ continue;
78
94
  }
79
95
 
80
- process.exit(result.code ?? (result.signal ? 1 : 0))
96
+ process.exit(result.code ?? (result.signal ? 1 : 0));
81
97
  }