copilot-hub 0.1.35 → 0.1.38

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/README.md CHANGED
@@ -168,7 +168,7 @@ Default values are already applied, and actions start from that agent workspace
168
168
  - If `npm run start` fails, first read the error and follow the suggested action.
169
169
  - `npm run start` now checks that Codex CLI is inside the supported range and can install the validated version automatically if missing or outside that range.
170
170
  - For Codex login issues, run `codex login` (or the configured `CODEX_BIN`) and retry `npm run start`.
171
- - If auto-install is skipped or unavailable, install Codex CLI with `npm install -g @openai/codex@0.117.0` or set `CODEX_BIN` in your Copilot Hub config to a binary in the supported `0.113.x` to `0.117.x` range.
171
+ - If auto-install is skipped or unavailable, install Codex CLI with `npm install -g @openai/codex@0.118.0` or set `CODEX_BIN` in your Copilot Hub config to a binary in the supported `0.113.x` to `0.118.x` range.
172
172
  - If you are still stuck, ask your favorite LLM with the exact error output.
173
173
 
174
174
  ## Upgrades
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "copilot-hub",
3
- "version": "0.1.35",
3
+ "version": "0.1.38",
4
4
  "description": "Copilot Hub CLI and runtime bundle",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -1,7 +1,7 @@
1
1
  export const codexNpmPackage = "@openai/codex";
2
2
  export const minimumCodexVersion = "0.113.0";
3
- export const preferredCodexVersion = "0.117.0";
4
- export const maximumCodexVersionExclusive = "0.118.0";
3
+ export const preferredCodexVersion = "0.118.0";
4
+ export const maximumCodexVersionExclusive = "0.119.0";
5
5
  export const codexInstallPackageSpec = `${codexNpmPackage}@${preferredCodexVersion}`;
6
6
  export const codexVersionRequirementLabel = `>= ${minimumCodexVersion} < ${maximumCodexVersionExclusive}`;
7
7
  export function extractSemver(value) {
@@ -9,6 +9,7 @@ import { codexInstallPackageSpec } from "./codex-version.mjs";
9
9
  import { initializeCopilotHubLayout, resolveCopilotHubLayout } from "./install-layout.mjs";
10
10
  import { isManagedProcessRunning, isProcessRunning, normalizePid } from "./process-identity.mjs";
11
11
  import { buildCodexCompatibilityError, probeCodexVersion, resolveCodexBinForStart, resolveCompatibleInstalledCodexBin, } from "./codex-runtime.mjs";
12
+ import { getWindowsHiddenLauncherHaltSignalPath } from "./windows-hidden-launcher.mjs";
12
13
  const __filename = fileURLToPath(import.meta.url);
13
14
  const __dirname = path.dirname(__filename);
14
15
  const repoRoot = path.resolve(__dirname, "..", "..");
@@ -22,6 +23,7 @@ const lastStartupErrorPath = path.join(runtimeDir, "last-startup-error.json");
22
23
  const daemonLogPath = path.join(logsDir, "service-daemon.log");
23
24
  const controlPlaneLogPath = path.join(logsDir, "control-plane.log");
24
25
  const agentEngineLogPath = path.join(logsDir, "agent-engine.log");
26
+ const windowsLauncherHaltSignalPath = getWindowsHiddenLauncherHaltSignalPath(runtimeDir);
25
27
  const daemonScriptPath = path.join(repoRoot, "scripts", "dist", "daemon.mjs");
26
28
  const supervisorScriptPath = path.join(repoRoot, "scripts", "dist", "supervisor.mjs");
27
29
  const nodeBin = process.execPath;
@@ -135,6 +137,7 @@ async function runDaemonLoop() {
135
137
  clearLastStartupError();
136
138
  }
137
139
  catch (error) {
140
+ requestWindowsLauncherHalt();
138
141
  writeLastStartupError({
139
142
  detectedAt: new Date().toISOString(),
140
143
  reason: getErrorMessage(error),
@@ -165,6 +168,7 @@ async function runDaemonLoop() {
165
168
  }
166
169
  const fatal = detectFatalStartupError(ensureResult);
167
170
  if (fatal) {
171
+ requestWindowsLauncherHalt();
168
172
  writeLastStartupError(fatal);
169
173
  console.error(`[daemon] fatal startup error: ${fatal.reason}`);
170
174
  console.error(`[daemon] action required: ${fatal.action}`);
@@ -559,6 +563,18 @@ function writeLastStartupError(value) {
559
563
  // Best effort only.
560
564
  }
561
565
  }
566
+ function requestWindowsLauncherHalt() {
567
+ if (process.platform !== "win32") {
568
+ return;
569
+ }
570
+ try {
571
+ fs.mkdirSync(path.dirname(windowsLauncherHaltSignalPath), { recursive: true });
572
+ fs.writeFileSync(windowsLauncherHaltSignalPath, `${new Date().toISOString()}\n`, "utf8");
573
+ }
574
+ catch {
575
+ // Best effort only.
576
+ }
577
+ }
562
578
  function readLastStartupError() {
563
579
  if (!fs.existsSync(lastStartupErrorPath)) {
564
580
  return null;
@@ -8,7 +8,7 @@ import { spawn, spawnSync } from "node:child_process";
8
8
  import { fileURLToPath } from "node:url";
9
9
  import { initializeCopilotHubLayout, resolveCopilotHubLayout } from "./install-layout.mjs";
10
10
  import { isManagedProcessRunning, normalizePid } from "./process-identity.mjs";
11
- import { buildWindowsHiddenLauncherCommand, ensureWindowsHiddenLauncher, getWindowsHiddenLauncherScriptPath, getWindowsHiddenLauncherStopSignalPath, resolveWindowsScriptHost, } from "./windows-hidden-launcher.mjs";
11
+ import { getWindowsHiddenLauncherHaltSignalPath, buildWindowsHiddenLauncherCommand, ensureWindowsHiddenLauncher, getWindowsHiddenLauncherScriptPath, getWindowsHiddenLauncherStopSignalPath, resolveWindowsScriptHost, } from "./windows-hidden-launcher.mjs";
12
12
  const __filename = fileURLToPath(import.meta.url);
13
13
  const __dirname = path.dirname(__filename);
14
14
  const repoRoot = path.resolve(__dirname, "..", "..");
@@ -19,6 +19,7 @@ const daemonScriptPath = path.join(repoRoot, "scripts", "dist", "daemon.mjs");
19
19
  const daemonStatePath = path.join(layout.runtimeDir, "pids", "daemon.json");
20
20
  const windowsLauncherScriptPath = getWindowsHiddenLauncherScriptPath(layout.runtimeDir);
21
21
  const windowsLauncherStopSignalPath = getWindowsHiddenLauncherStopSignalPath(layout.runtimeDir);
22
+ const windowsLauncherHaltSignalPath = getWindowsHiddenLauncherHaltSignalPath(layout.runtimeDir);
22
23
  const WINDOWS_TASK_NAME = "CopilotHub";
23
24
  const WINDOWS_RUN_KEY_PATH = "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run";
24
25
  const WINDOWS_RUN_VALUE_NAME = "CopilotHub";
@@ -166,6 +167,7 @@ async function installWindowsAutoStart() {
166
167
  const command = buildWindowsLaunchCommand();
167
168
  const taskCreate = runChecked("schtasks", ["/Create", "/TN", WINDOWS_TASK_NAME, "/SC", "ONLOGON", "/RL", "LIMITED", "/F", "/TR", command], { allowFailure: true });
168
169
  if (taskCreate.ok) {
170
+ clearWindowsLauncherHaltRequest();
169
171
  clearWindowsLauncherStopRequest();
170
172
  await ensureWindowsSessionRunning("task");
171
173
  return "task";
@@ -174,6 +176,7 @@ async function installWindowsAutoStart() {
174
176
  throw new Error(taskCreate.combinedOutput || "Failed to create Windows auto-start task.");
175
177
  }
176
178
  installWindowsRunKey(command);
179
+ clearWindowsLauncherHaltRequest();
177
180
  clearWindowsLauncherStopRequest();
178
181
  await ensureWindowsSessionRunning("run-key");
179
182
  return "run-key";
@@ -210,6 +213,7 @@ async function uninstallWindowsAutoStart() {
210
213
  if (fs.existsSync(windowsLauncherScriptPath)) {
211
214
  fs.rmSync(windowsLauncherScriptPath, { force: true });
212
215
  }
216
+ clearWindowsLauncherHaltRequest();
213
217
  return removed;
214
218
  }
215
219
  function showWindowsAutoStartStatus() {
@@ -248,6 +252,7 @@ async function startWindowsAutoStart() {
248
252
  const runKey = queryWindowsRunKey();
249
253
  if (runKey.installed) {
250
254
  installWindowsRunKey(command);
255
+ clearWindowsLauncherHaltRequest();
251
256
  clearWindowsLauncherStopRequest();
252
257
  await ensureWindowsSessionRunning("run-key");
253
258
  return "run-key";
@@ -257,6 +262,7 @@ async function startWindowsAutoStart() {
257
262
  throw new Error("Service is not installed. Run 'copilot-hub service install' first.");
258
263
  }
259
264
  ensureTaskSchedulerAutoStart(command);
265
+ clearWindowsLauncherHaltRequest();
260
266
  clearWindowsLauncherStopRequest();
261
267
  await ensureWindowsSessionRunning("task");
262
268
  return "task";
@@ -665,6 +671,12 @@ function clearWindowsLauncherStopRequest() {
665
671
  }
666
672
  fs.rmSync(windowsLauncherStopSignalPath, { force: true });
667
673
  }
674
+ function clearWindowsLauncherHaltRequest() {
675
+ if (!fs.existsSync(windowsLauncherHaltSignalPath)) {
676
+ return;
677
+ }
678
+ fs.rmSync(windowsLauncherHaltSignalPath, { force: true });
679
+ }
668
680
  function getRunningDaemonPid() {
669
681
  const state = readManagedState(daemonStatePath);
670
682
  const pid = normalizePid(state?.pid);
@@ -12,6 +12,9 @@ export function getWindowsHiddenLauncherScriptPath(runtimeDir) {
12
12
  export function getWindowsHiddenLauncherStopSignalPath(runtimeDir) {
13
13
  return path.win32.join(runtimeDir, "windows-daemon-launcher.stop");
14
14
  }
15
+ export function getWindowsHiddenLauncherHaltSignalPath(runtimeDir) {
16
+ return path.win32.join(runtimeDir, "windows-daemon-launcher.halt");
17
+ }
15
18
  export function ensureWindowsHiddenLauncher({ scriptPath, nodeBin, daemonScriptPath, runtimeDir, }) {
16
19
  const content = buildWindowsHiddenLauncherContent({
17
20
  nodeBin,
@@ -38,14 +41,16 @@ export function buildWindowsHiddenLauncherCommand(scriptPath, env = process.env)
38
41
  export function buildWindowsHiddenLauncherContent({ nodeBin, daemonScriptPath, runtimeDir, }) {
39
42
  const command = buildWindowsCommandLine([nodeBin, daemonScriptPath, "run"]);
40
43
  const stopSignalPath = getWindowsHiddenLauncherStopSignalPath(runtimeDir);
44
+ const haltSignalPath = getWindowsHiddenLauncherHaltSignalPath(runtimeDir);
41
45
  return [
42
46
  "Option Explicit",
43
- "Dim shell, fso, command, stopSignalPath, restartDelayMs",
47
+ "Dim shell, fso, command, stopSignalPath, haltSignalPath, restartDelayMs",
44
48
  'Set shell = CreateObject("WScript.Shell")',
45
49
  'Set fso = CreateObject("Scripting.FileSystemObject")',
46
50
  `shell.CurrentDirectory = "${escapeVbsString(runtimeDir)}"`,
47
51
  `command = "${escapeVbsString(command)}"`,
48
52
  `stopSignalPath = "${escapeVbsString(stopSignalPath)}"`,
53
+ `haltSignalPath = "${escapeVbsString(haltSignalPath)}"`,
49
54
  `restartDelayMs = ${String(WINDOWS_HIDDEN_LAUNCHER_RESTART_DELAY_MS)}`,
50
55
  "Do",
51
56
  " If fso.FileExists(stopSignalPath) Then",
@@ -54,6 +59,9 @@ export function buildWindowsHiddenLauncherContent({ nodeBin, daemonScriptPath, r
54
59
  " On Error GoTo 0",
55
60
  " Exit Do",
56
61
  " End If",
62
+ " If fso.FileExists(haltSignalPath) Then",
63
+ " Exit Do",
64
+ " End If",
57
65
  " shell.Run command, 0, True",
58
66
  " If fso.FileExists(stopSignalPath) Then",
59
67
  " On Error Resume Next",
@@ -61,6 +69,9 @@ export function buildWindowsHiddenLauncherContent({ nodeBin, daemonScriptPath, r
61
69
  " On Error GoTo 0",
62
70
  " Exit Do",
63
71
  " End If",
72
+ " If fso.FileExists(haltSignalPath) Then",
73
+ " Exit Do",
74
+ " End If",
64
75
  " WScript.Sleep restartDelayMs",
65
76
  "Loop",
66
77
  "Set fso = Nothing",
@@ -1,7 +1,7 @@
1
1
  export const codexNpmPackage = "@openai/codex";
2
2
  export const minimumCodexVersion = "0.113.0";
3
- export const preferredCodexVersion = "0.117.0";
4
- export const maximumCodexVersionExclusive = "0.118.0";
3
+ export const preferredCodexVersion = "0.118.0";
4
+ export const maximumCodexVersionExclusive = "0.119.0";
5
5
  export const codexInstallPackageSpec = `${codexNpmPackage}@${preferredCodexVersion}`;
6
6
  export const codexVersionRequirementLabel = `>= ${minimumCodexVersion} < ${maximumCodexVersionExclusive}`;
7
7
 
@@ -14,6 +14,7 @@ import {
14
14
  resolveCodexBinForStart,
15
15
  resolveCompatibleInstalledCodexBin,
16
16
  } from "./codex-runtime.mjs";
17
+ import { getWindowsHiddenLauncherHaltSignalPath } from "./windows-hidden-launcher.mjs";
17
18
 
18
19
  const __filename = fileURLToPath(import.meta.url);
19
20
  const __dirname = path.dirname(__filename);
@@ -30,6 +31,7 @@ const lastStartupErrorPath = path.join(runtimeDir, "last-startup-error.json");
30
31
  const daemonLogPath = path.join(logsDir, "service-daemon.log");
31
32
  const controlPlaneLogPath = path.join(logsDir, "control-plane.log");
32
33
  const agentEngineLogPath = path.join(logsDir, "agent-engine.log");
34
+ const windowsLauncherHaltSignalPath = getWindowsHiddenLauncherHaltSignalPath(runtimeDir);
33
35
  const daemonScriptPath = path.join(repoRoot, "scripts", "dist", "daemon.mjs");
34
36
  const supervisorScriptPath = path.join(repoRoot, "scripts", "dist", "supervisor.mjs");
35
37
  const nodeBin = process.execPath;
@@ -159,6 +161,7 @@ async function runDaemonLoop() {
159
161
  ensureCompatibleCodexForDaemon();
160
162
  clearLastStartupError();
161
163
  } catch (error) {
164
+ requestWindowsLauncherHalt();
162
165
  writeLastStartupError({
163
166
  detectedAt: new Date().toISOString(),
164
167
  reason: getErrorMessage(error),
@@ -193,6 +196,7 @@ async function runDaemonLoop() {
193
196
 
194
197
  const fatal = detectFatalStartupError(ensureResult);
195
198
  if (fatal) {
199
+ requestWindowsLauncherHalt();
196
200
  writeLastStartupError(fatal);
197
201
  console.error(`[daemon] fatal startup error: ${fatal.reason}`);
198
202
  console.error(`[daemon] action required: ${fatal.action}`);
@@ -667,6 +671,18 @@ function writeLastStartupError(value) {
667
671
  }
668
672
  }
669
673
 
674
+ function requestWindowsLauncherHalt() {
675
+ if (process.platform !== "win32") {
676
+ return;
677
+ }
678
+ try {
679
+ fs.mkdirSync(path.dirname(windowsLauncherHaltSignalPath), { recursive: true });
680
+ fs.writeFileSync(windowsLauncherHaltSignalPath, `${new Date().toISOString()}\n`, "utf8");
681
+ } catch {
682
+ // Best effort only.
683
+ }
684
+ }
685
+
670
686
  function readLastStartupError() {
671
687
  if (!fs.existsSync(lastStartupErrorPath)) {
672
688
  return null;
@@ -9,6 +9,7 @@ import { fileURLToPath } from "node:url";
9
9
  import { initializeCopilotHubLayout, resolveCopilotHubLayout } from "./install-layout.mjs";
10
10
  import { isManagedProcessRunning, normalizePid } from "./process-identity.mjs";
11
11
  import {
12
+ getWindowsHiddenLauncherHaltSignalPath,
12
13
  buildWindowsHiddenLauncherCommand,
13
14
  ensureWindowsHiddenLauncher,
14
15
  getWindowsHiddenLauncherScriptPath,
@@ -26,6 +27,7 @@ const daemonScriptPath = path.join(repoRoot, "scripts", "dist", "daemon.mjs");
26
27
  const daemonStatePath = path.join(layout.runtimeDir, "pids", "daemon.json");
27
28
  const windowsLauncherScriptPath = getWindowsHiddenLauncherScriptPath(layout.runtimeDir);
28
29
  const windowsLauncherStopSignalPath = getWindowsHiddenLauncherStopSignalPath(layout.runtimeDir);
30
+ const windowsLauncherHaltSignalPath = getWindowsHiddenLauncherHaltSignalPath(layout.runtimeDir);
29
31
 
30
32
  const WINDOWS_TASK_NAME = "CopilotHub";
31
33
  const WINDOWS_RUN_KEY_PATH = "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run";
@@ -205,6 +207,7 @@ async function installWindowsAutoStart() {
205
207
  { allowFailure: true },
206
208
  );
207
209
  if (taskCreate.ok) {
210
+ clearWindowsLauncherHaltRequest();
208
211
  clearWindowsLauncherStopRequest();
209
212
  await ensureWindowsSessionRunning("task");
210
213
  return "task";
@@ -215,6 +218,7 @@ async function installWindowsAutoStart() {
215
218
  }
216
219
 
217
220
  installWindowsRunKey(command);
221
+ clearWindowsLauncherHaltRequest();
218
222
  clearWindowsLauncherStopRequest();
219
223
  await ensureWindowsSessionRunning("run-key");
220
224
  return "run-key";
@@ -265,6 +269,7 @@ async function uninstallWindowsAutoStart() {
265
269
  if (fs.existsSync(windowsLauncherScriptPath)) {
266
270
  fs.rmSync(windowsLauncherScriptPath, { force: true });
267
271
  }
272
+ clearWindowsLauncherHaltRequest();
268
273
 
269
274
  return removed;
270
275
  }
@@ -315,6 +320,7 @@ async function startWindowsAutoStart() {
315
320
  const runKey = queryWindowsRunKey();
316
321
  if (runKey.installed) {
317
322
  installWindowsRunKey(command);
323
+ clearWindowsLauncherHaltRequest();
318
324
  clearWindowsLauncherStopRequest();
319
325
  await ensureWindowsSessionRunning("run-key");
320
326
  return "run-key";
@@ -324,6 +330,7 @@ async function startWindowsAutoStart() {
324
330
  throw new Error("Service is not installed. Run 'copilot-hub service install' first.");
325
331
  }
326
332
  ensureTaskSchedulerAutoStart(command);
333
+ clearWindowsLauncherHaltRequest();
327
334
  clearWindowsLauncherStopRequest();
328
335
  await ensureWindowsSessionRunning("task");
329
336
  return "task";
@@ -797,6 +804,13 @@ function clearWindowsLauncherStopRequest() {
797
804
  fs.rmSync(windowsLauncherStopSignalPath, { force: true });
798
805
  }
799
806
 
807
+ function clearWindowsLauncherHaltRequest() {
808
+ if (!fs.existsSync(windowsLauncherHaltSignalPath)) {
809
+ return;
810
+ }
811
+ fs.rmSync(windowsLauncherHaltSignalPath, { force: true });
812
+ }
813
+
800
814
  function getRunningDaemonPid() {
801
815
  const state = readManagedState(daemonStatePath);
802
816
  const pid = normalizePid(state?.pid);
@@ -17,6 +17,10 @@ export function getWindowsHiddenLauncherStopSignalPath(runtimeDir: string): stri
17
17
  return path.win32.join(runtimeDir, "windows-daemon-launcher.stop");
18
18
  }
19
19
 
20
+ export function getWindowsHiddenLauncherHaltSignalPath(runtimeDir: string): string {
21
+ return path.win32.join(runtimeDir, "windows-daemon-launcher.halt");
22
+ }
23
+
20
24
  export function ensureWindowsHiddenLauncher({
21
25
  scriptPath,
22
26
  nodeBin,
@@ -68,14 +72,16 @@ export function buildWindowsHiddenLauncherContent({
68
72
  }): string {
69
73
  const command = buildWindowsCommandLine([nodeBin, daemonScriptPath, "run"]);
70
74
  const stopSignalPath = getWindowsHiddenLauncherStopSignalPath(runtimeDir);
75
+ const haltSignalPath = getWindowsHiddenLauncherHaltSignalPath(runtimeDir);
71
76
  return [
72
77
  "Option Explicit",
73
- "Dim shell, fso, command, stopSignalPath, restartDelayMs",
78
+ "Dim shell, fso, command, stopSignalPath, haltSignalPath, restartDelayMs",
74
79
  'Set shell = CreateObject("WScript.Shell")',
75
80
  'Set fso = CreateObject("Scripting.FileSystemObject")',
76
81
  `shell.CurrentDirectory = "${escapeVbsString(runtimeDir)}"`,
77
82
  `command = "${escapeVbsString(command)}"`,
78
83
  `stopSignalPath = "${escapeVbsString(stopSignalPath)}"`,
84
+ `haltSignalPath = "${escapeVbsString(haltSignalPath)}"`,
79
85
  `restartDelayMs = ${String(WINDOWS_HIDDEN_LAUNCHER_RESTART_DELAY_MS)}`,
80
86
  "Do",
81
87
  " If fso.FileExists(stopSignalPath) Then",
@@ -84,6 +90,9 @@ export function buildWindowsHiddenLauncherContent({
84
90
  " On Error GoTo 0",
85
91
  " Exit Do",
86
92
  " End If",
93
+ " If fso.FileExists(haltSignalPath) Then",
94
+ " Exit Do",
95
+ " End If",
87
96
  " shell.Run command, 0, True",
88
97
  " If fso.FileExists(stopSignalPath) Then",
89
98
  " On Error Resume Next",
@@ -91,6 +100,9 @@ export function buildWindowsHiddenLauncherContent({
91
100
  " On Error GoTo 0",
92
101
  " Exit Do",
93
102
  " End If",
103
+ " If fso.FileExists(haltSignalPath) Then",
104
+ " Exit Do",
105
+ " End If",
94
106
  " WScript.Sleep restartDelayMs",
95
107
  "Loop",
96
108
  "Set fso = Nothing",
@@ -7,14 +7,15 @@ import {
7
7
  preferredCodexVersion,
8
8
  } from "../dist/codex-version.mjs";
9
9
 
10
- test("isCodexVersionCompatible accepts validated stable 0.113.x through 0.117.x releases", () => {
10
+ test("isCodexVersionCompatible accepts validated stable 0.113.x through 0.118.x releases", () => {
11
11
  assert.equal(isCodexVersionCompatible("0.113.0"), true);
12
12
  assert.equal(isCodexVersionCompatible("0.114.0"), true);
13
13
  assert.equal(isCodexVersionCompatible("0.115.3"), true);
14
14
  assert.equal(isCodexVersionCompatible("0.116.9"), true);
15
15
  assert.equal(isCodexVersionCompatible("0.117.0"), true);
16
+ assert.equal(isCodexVersionCompatible("0.118.0"), true);
16
17
  assert.equal(isCodexVersionCompatible("0.112.9"), false);
17
- assert.equal(isCodexVersionCompatible("0.118.0"), false);
18
+ assert.equal(isCodexVersionCompatible("0.119.0"), false);
18
19
  });
19
20
 
20
21
  test("isCodexVersionCompatible rejects prerelease builds outside the validated lane", () => {
@@ -22,11 +23,12 @@ test("isCodexVersionCompatible rejects prerelease builds outside the validated l
22
23
  assert.equal(isCodexVersionCompatible("0.116.0-alpha.1"), false);
23
24
  assert.equal(isCodexVersionCompatible("0.117.0-alpha.1"), false);
24
25
  assert.equal(isCodexVersionCompatible("0.118.0-alpha.1"), false);
26
+ assert.equal(isCodexVersionCompatible("0.119.0-alpha.1"), false);
25
27
  });
26
28
 
27
29
  test("preferred install target stays inside the validated compatibility lane", () => {
28
- assert.equal(preferredCodexVersion, "0.117.0");
29
- assert.equal(codexInstallPackageSpec, "@openai/codex@0.117.0");
30
+ assert.equal(preferredCodexVersion, "0.118.0");
31
+ assert.equal(codexInstallPackageSpec, "@openai/codex@0.118.0");
30
32
  assert.equal(isCodexVersionCompatible(preferredCodexVersion), true);
31
33
  });
32
34
 
@@ -7,6 +7,7 @@ import {
7
7
  buildWindowsHiddenLauncherCommand,
8
8
  buildWindowsHiddenLauncherContent,
9
9
  ensureWindowsHiddenLauncher,
10
+ getWindowsHiddenLauncherHaltSignalPath,
10
11
  getWindowsHiddenLauncherStopSignalPath,
11
12
  resolveWindowsScriptHost,
12
13
  } from "../dist/windows-hidden-launcher.mjs";
@@ -41,6 +42,7 @@ test("buildWindowsHiddenLauncherContent starts daemon in hidden mode", () => {
41
42
  assert.match(content, /WScript\.Sleep restartDelayMs/);
42
43
  assert.match(content, /"run"/);
43
44
  assert.match(content, /windows-daemon-launcher\.stop/);
45
+ assert.match(content, /windows-daemon-launcher\.halt/);
44
46
  });
45
47
 
46
48
  test("ensureWindowsHiddenLauncher writes and preserves launcher content", () => {
@@ -79,3 +81,13 @@ test("getWindowsHiddenLauncherStopSignalPath uses the runtime directory", () =>
79
81
  "C:\\Users\\amine\\AppData\\Roaming\\copilot-hub\\runtime\\windows-daemon-launcher.stop",
80
82
  );
81
83
  });
84
+
85
+ test("getWindowsHiddenLauncherHaltSignalPath uses the runtime directory", () => {
86
+ const actual = getWindowsHiddenLauncherHaltSignalPath(
87
+ "C:\\Users\\amine\\AppData\\Roaming\\copilot-hub\\runtime",
88
+ );
89
+ assert.equal(
90
+ actual,
91
+ "C:\\Users\\amine\\AppData\\Roaming\\copilot-hub\\runtime\\windows-daemon-launcher.halt",
92
+ );
93
+ });