| ... | ... | @@ -579,7 +579,20 @@ interface StagePackageJson { |
| 579 | 579 | } |
| 580 | 580 | |
| 581 | 581 | export const STAGE_INSTALL_ARGS = ["install", "--prod"] as const; |
| 582 | | export const DESKTOP_ASAR_UNPACK = ["node_modules/@ff-labs/fff-bin-*/**/*"] as const; |
| 582 | export const DESKTOP_ELECTRON_LANGUAGES = ["en-US"] as const; |
| 583 | export const DESKTOP_FILE_EXCLUSIONS = [ |
| 584 | // T3 Code always passes the user's installed Claude executable to the SDK, |
| 585 | // so the SDK's optional platform packages (each a ~200MB bundled executable) |
| 586 | // are dead weight. The trailing dash keeps the SDK's own JS package. |
| 587 | "!**/node_modules/@anthropic-ai/claude-agent-sdk-*/**/*", |
| 588 | ] as const; |
| 589 | // The WSL backend launches the server with plain `wsl.exe -- node`, which |
| 590 | // cannot read inside an asar archive — and the server bundle externalizes its |
| 591 | // runtime deps, so the whole node_modules tree must be unpacked, not just the |
| 592 | // bundle (otherwise ERR_MODULE_NOT_FOUND: "Cannot find package 'effect'"). |
| 593 | // The Windows primary backend reads the same files through the asar redirect, |
| 594 | // so nothing is duplicated. |
| 595 | export const WINDOWS_ASAR_UNPACK = ["apps/server/dist/**", "**/node_modules/**"] as const; |
| 583 | 596 | |
| 584 | 597 | export interface MacPasskeySigningConfiguration { |
| 585 | 598 | readonly appId: string; |
| ... | ... | @@ -1390,23 +1403,15 @@ export const createBuildConfig = Effect.fn("createBuildConfig")(function* ( |
| 1390 | 1403 | appId: DESKTOP_APP_ID, |
| 1391 | 1404 | productName: resolveDesktopProductName(version), |
| 1392 | 1405 | artifactName: "T3-Code-${version}-${arch}.${ext}", |
| 1406 | electronLanguages: [...DESKTOP_ELECTRON_LANGUAGES], |
| 1407 | files: [...DESKTOP_FILE_EXCLUSIONS], |
| 1393 | 1408 | directories: { |
| 1394 | 1409 | buildResources: "apps/desktop/resources", |
| 1395 | 1410 | }, |
| 1396 | | // The Windows primary backend runs the server bundle through |
| 1397 | | // ELECTRON_RUN_AS_NODE (asar-aware), so it reads bin.mjs straight out of |
| 1398 | | // app.asar. The WSL backend instead launches plain `wsl.exe -- node`, which |
| 1399 | | // cannot read inside an asar archive, so everything it loads must be on the |
| 1400 | | // real filesystem. The server bundle externalizes its runtime dependencies |
| 1401 | | // (effect, @effect/*, node-pty, ...) to node_modules rather than inlining |
| 1402 | | // them, so unpacking just the bundle + node-pty isn't enough — the Linux Node |
| 1403 | | // fails with ERR_MODULE_NOT_FOUND (e.g. "Cannot find package 'effect'") before |
| 1404 | | // it even reaches node-pty. Unpack the server bundle AND the whole |
| 1405 | | // node_modules tree so every import resolves (this also covers the fff native |
| 1406 | | // binaries in DESKTOP_ASAR_UNPACK). The Windows primary keeps reading the same |
| 1407 | | // files through the asar (transparently redirected to the unpacked copy), so |
| 1408 | | // there's no duplication. |
| 1409 | | asarUnpack: [...DESKTOP_ASAR_UNPACK, "apps/server/dist/**", "**/node_modules/**"], |
| 1411 | // Only the Windows WSL backend needs files outside the asar (see |
| 1412 | // WINDOWS_ASAR_UNPACK); macOS and Linux stay packed — smart unpack |
| 1413 | // extracts native libraries, which fff-node finds in app.asar.unpacked. |
| 1414 | ...(platform === "win" ? { asarUnpack: [...WINDOWS_ASAR_UNPACK] } : {}), |
| 1410 | 1415 | }; |
| 1411 | 1416 | const updateChannel = resolveDesktopUpdateChannel(version); |
| 1412 | 1417 | const publishConfig = yield* resolveGitHubPublishConfig(updateChannel); |