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 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 compilation (better-sqlite3) requires [Visual C++ Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/). The setup script will warn you if they're missing, but prebuilt binaries may work without them.
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
 
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cowork-os",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "description": "CoWork OS - The most complete open-source AI assistant platform",
5
5
  "overrides": {
6
6
  "@whiskeysockets/baileys": {
@@ -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 windows-build-tools
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 may not be installed.\n" +
238
- "Native module compilation (better-sqlite3) requires them.\n" +
239
- "Install with:\n" +
240
- " npm install -g windows-build-tools\n" +
241
- "Or install Visual Studio Build Tools from:\n" +
242
- " https://visualstudio.microsoft.com/visual-cpp-build-tools/\n"
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) return rebuildElectronRes;
316
-
317
- const testRes = testBetterSqlite3InElectron(electronEnv);
318
- if (testRes.status === 0) {
319
- console.log("[cowork] better-sqlite3 loads in Electron.");
320
- return testRes;
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
- console.log(
324
- "[cowork] better-sqlite3 did not load after Electron-targeted rebuild; " +
325
- "falling back to electron-rebuild."
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."