cowork-os 0.4.2 → 0.4.3
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/CHANGELOG.md +7 -0
- package/README.md +1 -1
- package/docs/troubleshooting.md +33 -0
- package/package.json +1 -1
- package/scripts/setup_native.mjs +178 -29
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.4.3] - 2026-02-26
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- **Windows ARM64 first-run native setup**: when `better-sqlite3` cannot be rebuilt for `arm64`, setup now automatically falls back to `x64` Electron emulation and validates module loading before launch.
|
|
14
|
+
- **Windows ARM64 fallback robustness**: if npm-based x64 rebuild is insufficient, setup now runs an explicit `@electron/rebuild` pass with `--arch x64 --version <electron>` to avoid npm 11 runtime/target env ambiguity.
|
|
15
|
+
- **Windows node-gyp instructions**: replaced invalid npm config guidance with environment-variable-based setup (`GYP_MSVS_VERSION` / `npm_config_msvs_version`) for MSVC detection compatibility.
|
|
16
|
+
|
|
10
17
|
## [0.4.0] - 2026-02-26
|
|
11
18
|
|
|
12
19
|
### Added
|
package/README.md
CHANGED
|
@@ -97,7 +97,7 @@ npm install && npm run setup
|
|
|
97
97
|
npm run build && npm run package
|
|
98
98
|
```
|
|
99
99
|
|
|
100
|
-
> **Windows prerequisites:** Native module
|
|
100
|
+
> **Windows prerequisites:** Native module setup may require [Visual Studio Build Tools 2022 (C++)](https://visualstudio.microsoft.com/visual-cpp-build-tools/) and Python 3. On Windows ARM64, setup automatically falls back to x64 Electron emulation when ARM64 native prebuilds are unavailable.
|
|
101
101
|
|
|
102
102
|
See the [Development Guide](docs/development.md) for prerequisites and details.
|
|
103
103
|
|
package/docs/troubleshooting.md
CHANGED
|
@@ -44,6 +44,39 @@ If you see `Killed: 9` during `npm run setup`, macOS terminated a native build d
|
|
|
44
44
|
npm run setup
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
+
## Windows native setup fails (`better-sqlite3`)
|
|
48
|
+
|
|
49
|
+
If first launch exits after:
|
|
50
|
+
|
|
51
|
+
```text
|
|
52
|
+
[cowork] $ npm.cmd rebuild --ignore-scripts=false better-sqlite3
|
|
53
|
+
[cowork] Native setup failed.
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
install native build prerequisites, then retry:
|
|
57
|
+
|
|
58
|
+
1. Install [Visual Studio Build Tools 2022](https://visualstudio.microsoft.com/visual-cpp-build-tools/) with:
|
|
59
|
+
- Desktop development with C++
|
|
60
|
+
- MSVC v143 build tools
|
|
61
|
+
- Windows 10/11 SDK
|
|
62
|
+
2. Install Python 3 and verify:
|
|
63
|
+
|
|
64
|
+
```powershell
|
|
65
|
+
py -3 --version
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
3. Set node-gyp MSVC env vars, then retry from a new terminal:
|
|
69
|
+
|
|
70
|
+
```powershell
|
|
71
|
+
setx GYP_MSVS_VERSION 2022
|
|
72
|
+
setx npm_config_msvs_version 2022
|
|
73
|
+
cowork-os
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Windows ARM64 note:
|
|
77
|
+
- Setup now auto-tries x64 Electron emulation if ARM64 native rebuild fails.
|
|
78
|
+
- To disable that fallback and force native ARM64 only, set `COWORK_SETUP_SKIP_X64_FALLBACK=1`.
|
|
79
|
+
|
|
47
80
|
## App shows "vUnknown" or remote method error
|
|
48
81
|
|
|
49
82
|
If the app opens but shows `vUnknown` or `Error invoking remote method 'app:getVersion'`, you likely connected to an older already-running instance.
|
package/package.json
CHANGED
package/scripts/setup_native.mjs
CHANGED
|
@@ -102,6 +102,11 @@ function computeJobs() {
|
|
|
102
102
|
return Math.min(2, cpuCount);
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
+
function nodeMajorVersion() {
|
|
106
|
+
const major = Number.parseInt(String(process.versions.node || "").split(".")[0], 10);
|
|
107
|
+
return Number.isFinite(major) ? major : null;
|
|
108
|
+
}
|
|
109
|
+
|
|
105
110
|
function baseEnvWithJobs(jobs) {
|
|
106
111
|
// These influence node-gyp/make parallelism on macOS/Linux.
|
|
107
112
|
// Always set safe values so global MAKEFLAGS doesn't accidentally cause OOM.
|
|
@@ -120,6 +125,25 @@ function readJson(filePath) {
|
|
|
120
125
|
return JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
121
126
|
}
|
|
122
127
|
|
|
128
|
+
function makeElectronTargetEnv(env, electronVersion, arch = process.arch) {
|
|
129
|
+
return {
|
|
130
|
+
...env,
|
|
131
|
+
npm_config_runtime: "electron",
|
|
132
|
+
npm_config_target: electronVersion,
|
|
133
|
+
npm_config_disturl: "https://electronjs.org/headers",
|
|
134
|
+
npm_config_arch: arch,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function resolveElectronRebuildCli() {
|
|
139
|
+
return resolvePackageFile("@electron/rebuild", "cli.js")
|
|
140
|
+
|| (() => {
|
|
141
|
+
// Fallback: try resolving the main entry and deriving cli.js
|
|
142
|
+
const entry = resolveFromCwd("@electron/rebuild");
|
|
143
|
+
return entry ? path.join(path.dirname(entry), "cli.js") : null;
|
|
144
|
+
})();
|
|
145
|
+
}
|
|
146
|
+
|
|
123
147
|
function getElectronVersion() {
|
|
124
148
|
try {
|
|
125
149
|
const pkgPath = resolveFromCwd("electron/package.json");
|
|
@@ -160,6 +184,97 @@ function testBetterSqlite3InElectron(env) {
|
|
|
160
184
|
return res;
|
|
161
185
|
}
|
|
162
186
|
|
|
187
|
+
function shouldTryWindowsArm64X64Fallback() {
|
|
188
|
+
if (!(process.platform === "win32" && process.arch === "arm64")) return false;
|
|
189
|
+
const raw = String(process.env.COWORK_SETUP_SKIP_X64_FALLBACK || "")
|
|
190
|
+
.trim()
|
|
191
|
+
.toLowerCase();
|
|
192
|
+
return raw !== "1" && raw !== "true" && raw !== "yes";
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function tryWindowsArm64X64Fallback(
|
|
196
|
+
env,
|
|
197
|
+
installRootDir,
|
|
198
|
+
electronInstallScript,
|
|
199
|
+
electronVersion,
|
|
200
|
+
electronRebuildCli
|
|
201
|
+
) {
|
|
202
|
+
if (!shouldTryWindowsArm64X64Fallback()) return null;
|
|
203
|
+
if (!electronInstallScript || !electronVersion) return null;
|
|
204
|
+
|
|
205
|
+
console.log(
|
|
206
|
+
"[cowork] Windows ARM64 detected; trying x64 Electron + native module fallback (emulation mode)."
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
// Force Electron's installer to fetch x64 binaries, then rebuild better-sqlite3 for x64 Electron ABI.
|
|
210
|
+
const installRes = run(process.execPath, [electronInstallScript], {
|
|
211
|
+
env: { ...env, npm_config_arch: "x64" },
|
|
212
|
+
cwd: installRootDir,
|
|
213
|
+
});
|
|
214
|
+
if (installRes.status !== 0) return installRes;
|
|
215
|
+
|
|
216
|
+
const x64ElectronEnv = makeElectronTargetEnv(env, electronVersion, "x64");
|
|
217
|
+
const rebuildRes = run(
|
|
218
|
+
NPM_CMD,
|
|
219
|
+
["rebuild", "--ignore-scripts=false", "better-sqlite3"],
|
|
220
|
+
{ env: x64ElectronEnv, cwd: installRootDir }
|
|
221
|
+
);
|
|
222
|
+
if (rebuildRes.status !== 0) {
|
|
223
|
+
console.log(
|
|
224
|
+
"[cowork] x64 npm rebuild failed; trying electron-rebuild x64 fallback."
|
|
225
|
+
);
|
|
226
|
+
} else {
|
|
227
|
+
const testRes = testBetterSqlite3InElectron(x64ElectronEnv);
|
|
228
|
+
if (testRes.status === 0) {
|
|
229
|
+
console.log("[cowork] better-sqlite3 loads in Electron (x64 emulation mode).");
|
|
230
|
+
return testRes;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
console.log(
|
|
234
|
+
"[cowork] x64 npm rebuild completed, but better-sqlite3 still did not load in Electron."
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (!electronRebuildCli || !fs.existsSync(electronRebuildCli)) {
|
|
239
|
+
console.log(
|
|
240
|
+
"[cowork] @electron/rebuild is not installed; cannot run x64 fallback rebuild."
|
|
241
|
+
);
|
|
242
|
+
return { status: 1, signal: null };
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const rebuildX64Res = run(
|
|
246
|
+
process.execPath,
|
|
247
|
+
[
|
|
248
|
+
electronRebuildCli,
|
|
249
|
+
"-f",
|
|
250
|
+
"--only",
|
|
251
|
+
"better-sqlite3",
|
|
252
|
+
"--sequential",
|
|
253
|
+
"--arch",
|
|
254
|
+
"x64",
|
|
255
|
+
"--version",
|
|
256
|
+
electronVersion,
|
|
257
|
+
"--module-dir",
|
|
258
|
+
installRootDir,
|
|
259
|
+
],
|
|
260
|
+
{ env, cwd: installRootDir }
|
|
261
|
+
);
|
|
262
|
+
if (rebuildX64Res.status !== 0) return rebuildX64Res;
|
|
263
|
+
|
|
264
|
+
const testRes = testBetterSqlite3InElectron(x64ElectronEnv);
|
|
265
|
+
if (testRes.status === 0) {
|
|
266
|
+
console.log(
|
|
267
|
+
"[cowork] better-sqlite3 loads in Electron after x64 electron-rebuild fallback."
|
|
268
|
+
);
|
|
269
|
+
} else {
|
|
270
|
+
console.log(
|
|
271
|
+
"[cowork] x64 electron-rebuild fallback completed, but better-sqlite3 still did not load."
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return testRes;
|
|
276
|
+
}
|
|
277
|
+
|
|
163
278
|
function ensureBetterSqlite3(env, installRootDir) {
|
|
164
279
|
const pkgPath = resolveFromCwd("better-sqlite3/package.json");
|
|
165
280
|
|
|
@@ -203,6 +318,11 @@ function fail(res, context) {
|
|
|
203
318
|
"close other apps and re-run `npm run setup`."
|
|
204
319
|
);
|
|
205
320
|
}
|
|
321
|
+
if (process.platform === "win32") {
|
|
322
|
+
console.error(
|
|
323
|
+
"[cowork] On Windows, inspect npm logs in %LocalAppData%\\npm-cache\\_logs\\ for detailed native build errors."
|
|
324
|
+
);
|
|
325
|
+
}
|
|
206
326
|
// If a child process was SIGKILL'd, `spawnSync` will surface it as `signal`
|
|
207
327
|
// with `status === null`. Exit 137 (128 + 9) so shell-level retries can
|
|
208
328
|
// reliably detect and retry.
|
|
@@ -224,7 +344,7 @@ function checkPrereqs() {
|
|
|
224
344
|
// Check for Visual C++ build tools (required by node-gyp for native modules)
|
|
225
345
|
const res = spawnSync("where", ["cl.exe"], { encoding: "utf8" });
|
|
226
346
|
if (res.status !== 0) {
|
|
227
|
-
// Also check via npm config for
|
|
347
|
+
// Also check via npm config for an explicit MSVC version.
|
|
228
348
|
const npmRes = spawnSync(NPM_CMD, ["config", "get", "msvs_version"], {
|
|
229
349
|
encoding: "utf8",
|
|
230
350
|
});
|
|
@@ -234,16 +354,38 @@ function checkPrereqs() {
|
|
|
234
354
|
npmRes.stdout.trim() !== "undefined";
|
|
235
355
|
if (!hasMsvs) {
|
|
236
356
|
console.warn(
|
|
237
|
-
"\n[cowork] Warning: Visual C++ Build Tools
|
|
238
|
-
"Native module compilation (better-sqlite3)
|
|
239
|
-
"Install with:\n" +
|
|
240
|
-
"
|
|
241
|
-
"
|
|
242
|
-
"
|
|
357
|
+
"\n[cowork] Warning: Visual Studio C++ Build Tools were not detected.\n" +
|
|
358
|
+
"Native module compilation (better-sqlite3) may fail without them.\n" +
|
|
359
|
+
"Install Visual Studio Build Tools 2022 with:\n" +
|
|
360
|
+
" - Desktop development with C++\n" +
|
|
361
|
+
" - MSVC v143 build tools\n" +
|
|
362
|
+
" - Windows 10/11 SDK\n" +
|
|
363
|
+
"Then set node-gyp MSVC env vars (in cmd):\n" +
|
|
364
|
+
" setx GYP_MSVS_VERSION 2022\n" +
|
|
365
|
+
" setx npm_config_msvs_version 2022\n" +
|
|
366
|
+
"Download: https://visualstudio.microsoft.com/visual-cpp-build-tools/\n"
|
|
243
367
|
);
|
|
244
368
|
// Don't exit — prebuilt binaries may work without compilation
|
|
245
369
|
}
|
|
246
370
|
}
|
|
371
|
+
|
|
372
|
+
const pyRes = spawnSync("py", ["-3", "--version"], { encoding: "utf8" });
|
|
373
|
+
const pythonRes = pyRes.status === 0
|
|
374
|
+
? pyRes
|
|
375
|
+
: spawnSync("python", ["--version"], { encoding: "utf8" });
|
|
376
|
+
if (pythonRes.status !== 0) {
|
|
377
|
+
console.warn(
|
|
378
|
+
"\n[cowork] Warning: Python 3 was not detected (`py -3` / `python`).\n" +
|
|
379
|
+
"node-gyp requires Python 3 for native module builds.\n"
|
|
380
|
+
);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
if (process.arch === "arm64" && (nodeMajorVersion() ?? 0) >= 24) {
|
|
384
|
+
console.log(
|
|
385
|
+
"[cowork] Windows ARM64 + Node 24 detected. If native ARM64 rebuild fails,\n" +
|
|
386
|
+
"setup will auto-try x64 Electron emulation for better compatibility."
|
|
387
|
+
);
|
|
388
|
+
}
|
|
247
389
|
}
|
|
248
390
|
}
|
|
249
391
|
|
|
@@ -267,6 +409,7 @@ function main() {
|
|
|
267
409
|
const env = baseEnvWithJobs(attemptJobs);
|
|
268
410
|
const installRootDir = getInstallRootDir();
|
|
269
411
|
const electronInstallScript = resolvePackageFile("electron", "install.js");
|
|
412
|
+
const electronRebuildCli = resolveElectronRebuildCli();
|
|
270
413
|
const electronBinary = getElectronBinaryPath();
|
|
271
414
|
|
|
272
415
|
if (!electronInstallScript) {
|
|
@@ -300,30 +443,42 @@ function main() {
|
|
|
300
443
|
// 2) electron-rebuild for the one module (keeps rebuild surface small).
|
|
301
444
|
// 2) Prefer an Electron-targeted rebuild for better-sqlite3 (often prebuilt, lighter).
|
|
302
445
|
if (electronVersion) {
|
|
303
|
-
const electronEnv =
|
|
304
|
-
...env,
|
|
305
|
-
npm_config_runtime: "electron",
|
|
306
|
-
npm_config_target: electronVersion,
|
|
307
|
-
npm_config_disturl: "https://electronjs.org/headers",
|
|
308
|
-
npm_config_arch: process.arch,
|
|
309
|
-
};
|
|
446
|
+
const electronEnv = makeElectronTargetEnv(env, electronVersion, process.arch);
|
|
310
447
|
const rebuildElectronRes = run(
|
|
311
448
|
NPM_CMD,
|
|
312
449
|
["rebuild", "--ignore-scripts=false", "better-sqlite3"],
|
|
313
450
|
{ env: electronEnv, cwd: installRootDir }
|
|
314
451
|
);
|
|
315
|
-
if (rebuildElectronRes.status !== 0)
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
452
|
+
if (rebuildElectronRes.status !== 0) {
|
|
453
|
+
console.log(
|
|
454
|
+
"[cowork] Electron-targeted npm rebuild failed; trying fallback paths."
|
|
455
|
+
);
|
|
456
|
+
} else {
|
|
457
|
+
const testRes = testBetterSqlite3InElectron(electronEnv);
|
|
458
|
+
if (testRes.status === 0) {
|
|
459
|
+
console.log("[cowork] better-sqlite3 loads in Electron.");
|
|
460
|
+
return testRes;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
console.log(
|
|
464
|
+
"[cowork] better-sqlite3 did not load after Electron-targeted rebuild; " +
|
|
465
|
+
"trying fallback paths."
|
|
466
|
+
);
|
|
321
467
|
}
|
|
322
468
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
469
|
+
const winArmFallbackRes = tryWindowsArm64X64Fallback(
|
|
470
|
+
env,
|
|
471
|
+
installRootDir,
|
|
472
|
+
electronInstallScript,
|
|
473
|
+
electronVersion,
|
|
474
|
+
electronRebuildCli
|
|
326
475
|
);
|
|
476
|
+
if (winArmFallbackRes) {
|
|
477
|
+
if (winArmFallbackRes.status === 0) return winArmFallbackRes;
|
|
478
|
+
console.log(
|
|
479
|
+
"[cowork] Windows ARM64 x64 fallback did not fully recover; trying current-arch electron-rebuild fallback."
|
|
480
|
+
);
|
|
481
|
+
}
|
|
327
482
|
} else {
|
|
328
483
|
console.log(
|
|
329
484
|
"[cowork] Could not determine Electron version; falling back to electron-rebuild."
|
|
@@ -331,12 +486,6 @@ function main() {
|
|
|
331
486
|
}
|
|
332
487
|
|
|
333
488
|
// 3) Fallback: electron-rebuild.
|
|
334
|
-
const electronRebuildCli = resolvePackageFile("@electron/rebuild", "cli.js")
|
|
335
|
-
|| (() => {
|
|
336
|
-
// Fallback: try resolving the main entry and deriving cli.js
|
|
337
|
-
const entry = resolveFromCwd("@electron/rebuild");
|
|
338
|
-
return entry ? path.join(path.dirname(entry), "cli.js") : null;
|
|
339
|
-
})();
|
|
340
489
|
if (!electronRebuildCli || !fs.existsSync(electronRebuildCli)) {
|
|
341
490
|
console.log(
|
|
342
491
|
"[cowork] @electron/rebuild is not installed; skipping fallback rebuild."
|