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 +1 -1
- package/package.json +1 -1
- package/scripts/dist/codex-version.mjs +2 -2
- package/scripts/dist/daemon.mjs +16 -0
- package/scripts/dist/service.mjs +13 -1
- package/scripts/dist/windows-hidden-launcher.mjs +12 -1
- package/scripts/src/codex-version.mts +2 -2
- package/scripts/src/daemon.mts +16 -0
- package/scripts/src/service.mts +14 -0
- package/scripts/src/windows-hidden-launcher.mts +13 -1
- package/scripts/test/codex-version.test.mjs +6 -4
- package/scripts/test/windows-hidden-launcher.test.mjs +12 -0
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.
|
|
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,7 +1,7 @@
|
|
|
1
1
|
export const codexNpmPackage = "@openai/codex";
|
|
2
2
|
export const minimumCodexVersion = "0.113.0";
|
|
3
|
-
export const preferredCodexVersion = "0.
|
|
4
|
-
export const maximumCodexVersionExclusive = "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) {
|
package/scripts/dist/daemon.mjs
CHANGED
|
@@ -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;
|
package/scripts/dist/service.mjs
CHANGED
|
@@ -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.
|
|
4
|
-
export const maximumCodexVersionExclusive = "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
|
|
package/scripts/src/daemon.mts
CHANGED
|
@@ -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;
|
package/scripts/src/service.mts
CHANGED
|
@@ -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.
|
|
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.
|
|
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.
|
|
29
|
-
assert.equal(codexInstallPackageSpec, "@openai/codex@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
|
+
});
|