forked from BasedHardware/omi
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathelectron-builder.config.mjs
More file actions
191 lines (188 loc) · 10.3 KB
/
Copy pathelectron-builder.config.mjs
File metadata and controls
191 lines (188 loc) · 10.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
// electron-builder configuration (was electron-builder.yml — converted to a JS
// config in PR-D2 so the pi-mono asarUnpack closure can be spread in
// programmatically).
//
// WHY JS, not YAML: pi-mono (@earendil-works/pi-coding-agent) is spawned as a
// plain-Node child (ELECTRON_RUN_AS_NODE) by src/main/codingAgent/piMono.ts, so
// every package in its ~128-package runtime closure must be asarUnpacked (a
// plain-Node child cannot read from asar). Hand-listing that many globs in YAML
// silently drifts on a pi-mono version bump. Instead we compute the closure by
// walking pi's dependency graph at pack time (computeUnpackGlobs, drift-proof by
// construction — it reads the ACTUAL installed tree every build) and spread it
// into asarUnpack. See scripts/gen-pimono-unpack.mjs and verify-pimono-unpack.mjs.
//
// electron-builder v26 supports .mjs config files (do NOT name it
// electron-builder.js — that name conflicts with the package itself).
// IMPORTANT: electron-builder only AUTO-detects electron-builder.<ext> (yml/json/
// js/cjs/mjs/ts), NOT the electron-builder.config.* name, so every build:* script
// in package.json MUST pass `--config electron-builder.config.mjs` explicitly.
// Removing that flag silently drops this whole config (and the pi-mono closure).
import { computeUnpackGlobs } from './scripts/gen-pimono-unpack.mjs'
import { KGWORKER_NATIVE_UNPACK_GLOBS } from './scripts/kgworker-native-closure.mjs'
import fixPimonoChalkUnpack from './scripts/fix-pimono-chalk-unpack.mjs'
// Fresh at every pack: the closure is recomputed from the installed node_modules,
// so it can never be stale relative to what is actually on disk.
const { globs: pimonoUnpackGlobs } = computeUnpackGlobs()
export default {
appId: 'com.omiwindows.app',
productName: 'Omi for Windows',
directories: {
buildResources: 'build'
},
files: [
// Explicit default; positive patterns below would otherwise replace it.
'**/*',
'!**/.vscode/*',
'!src/*',
'!electron.vite.config.{js,ts,mjs,cjs}',
'!{.eslintcache,eslint.config.mjs,.prettierignore,.prettierrc.yaml,dev-app-update.yml,CHANGELOG.md,README.md}',
'!{.env,.env.*,.npmrc,pnpm-lock.yaml}',
'!{tsconfig.json,tsconfig.node.json,tsconfig.web.json}',
'!{tailwind.config.ts,postcss.config.js}',
'!resources/win-ocr-helper/*.pdb',
'!resources/win-automation-helper/*.pdb',
'!resources/win-audio-helper/*.pdb'
],
asarUnpack: [
'resources/**',
// koffi loads its native .node at runtime, resolved relative to its own package
// dir — it must live outside the asar archive or the foreground monitor fails.
'node_modules/koffi/**',
// kgWorker.js is loaded via new Worker(path) which bypasses Electron's asar
// virtual-fs patch — it must be a real file on disk.
'out/main/kgWorker.js',
// ...and so must its native-module runtime closure: the worker's module
// resolution is plain real-fs anchored at app.asar.unpacked and never crosses
// back into app.asar, so better-sqlite3 + its pure-JS deps (bindings,
// file-uri-to-path) must all be unpacked or the worker dies with
// "Cannot find module 'bindings'". See scripts/kgworker-native-closure.mjs.
...KGWORKER_NATIVE_UNPACK_GLOBS,
// The coding-agent ACP entry is spawned as a plain Node child process
// (ELECTRON_RUN_AS_NODE), which cannot read scripts out of the asar archive —
// both the entry (emitted under out/main/chunks by the ?asset import) and the
// packages it needs at runtime must be real files on disk. The transitive
// entries are claude-agent-acp's own runtime imports (electron-builder
// flattens resolved deps into the package's node_modules).
'out/main/chunks/*.mjs',
'node_modules/@agentclientprotocol/claude-agent-acp/**',
'node_modules/@agentclientprotocol/sdk/**',
'node_modules/@anthropic-ai/claude-agent-sdk/**',
'node_modules/@anthropic-ai/claude-agent-sdk-win32-x64/**',
// zod is the only remaining runtime import of the closure above (verified by
// spawning the entry from a packaged build; the sdk resolves it hoisted).
'node_modules/zod/**',
// pi-mono (@earendil-works/pi-coding-agent) is spawned as a plain-Node child
// (ELECTRON_RUN_AS_NODE) by src/main/codingAgent/piMono.ts, so — like the ACP
// entry above — every file it require()s at runtime must live outside the asar
// archive. The four @earendil-works packages are its core; jiti (in the closure
// below) is what loads the .ts provider extension on the fly.
'node_modules/@earendil-works/**',
// The omi-provider extension is a raw .ts source dir copied next to the main
// bundle by scripts/copy-pimono-extension.mjs (resolveBundledExtension() looks
// there). pi loads it via jiti, so it too must be on disk, not in asar.
'out/main/pi-mono-extension/**',
// pi's FULL transitive runtime closure (dependencies + optionalDependencies),
// computed at pack time by walking its dependency graph — AWS SDK,
// google-auth-library, protobufjs, openai, @mistralai/mistralai, @google/genai,
// jiti, undici, the native @mariozechner/clipboard-* addon, the
// @silvia-odwyer/photon-node WASM, etc. This replaces the hand-maintained list
// the old ⚠️ INCOMPLETE comment warned about.
...pimonoUnpackGlobs
],
win: {
executableName: 'omi-windows',
// Committed multi-size icon (generated by `pnpm gen:app-icon`). Set explicitly
// because it lives in resources/, not the default buildResources dir (build/,
// which is gitignored). NSIS installer/uninstaller/shortcut icons inherit this.
icon: 'resources/icon.ico',
target: [{ target: 'nsis', arch: ['x64'] }]
// --- CODE SIGNING (unsigned today → Windows SmartScreen warns "unknown publisher") ---
// Signing requires a certificate that must be procured separately; until one is
// wired in, leave this out so unsigned builds still succeed. Recommended: Azure
// Trusted Signing (no hardware token, CI-friendly). Once you have an account,
// add azureSignOptions (publisherName / endpoint / certificateProfileName /
// codeSigningAccountName), storing secrets in CI, never here. Traditional OV/EV
// cert alternative: signtoolOptions with certificateSubjectName, or
// certificateFile / certificatePassword via CSC_LINK / CSC_KEY_PASSWORD env.
},
nsis: {
oneClick: false,
perMachine: false,
allowToChangeInstallationDirectory: true,
// No spaces in the artifact name: electron-updater downloads the installer by
// the exact url recorded in latest.yml, and a spaced productName ("Omi for
// Windows") url-encodes to a path that no longer matches the uploaded asset —
// every auto-update would 404. Keep this literal and space-free.
artifactName: 'Omi-for-Windows-Setup-${version}.${ext}',
shortcutName: '${productName}',
uninstallDisplayName: '${productName}',
createDesktopShortcut: 'always'
},
mac: {
entitlementsInherit: 'build/entitlements.mac.plist',
extendInfo: [
{ NSCameraUsageDescription: "Application requests access to the device's camera." },
{ NSMicrophoneUsageDescription: "Application requests access to the device's microphone." },
{
NSDocumentsFolderUsageDescription:
"Application requests access to the user's Documents folder."
},
{
NSDownloadsFolderUsageDescription:
"Application requests access to the user's Downloads folder."
}
],
notarize: false
},
dmg: {
artifactName: '${name}-${version}.${ext}'
},
linux: {
// AppImage + deb only — snap omitted: strict confinement blocks
// xprop/tesseract/proc used by Linux active-window and OCR seams.
target: ['AppImage', 'deb'],
maintainer: 'Based Hardware <team@basedhardware.com>',
category: 'Utility',
synopsis: 'AI that sees your screen, listens, and remembers'
},
appImage: {
artifactName: '${name}-${version}.${ext}'
},
deb: {
// Runtime tools/libs the Linux platform seams call out of process. Missing
// ones degrade gracefully (OCR/active-window return empty), but packaging the
// depends keeps the shipped App experience complete on Debian/Ubuntu.
depends: ['tesseract-ocr', 'tesseract-ocr-eng', 'libnotify4', 'libxss1', 'x11-utils'],
// A soft dependency, not `depends`: xdg-desktop-portal is the universal
// front-end virtually every desktop already has, but the BACKEND that
// actually answers ScreenCast (xdg-desktop-portal-gnome/-kde/-wlr/…) is
// compositor-specific and can't be a single correct hard dependency —
// forcing e.g. -gnome onto a KDE or wlroots-compositor user would be
// wrong. Rewind's screen recording surfaces a real in-app error (see
// RewindCaptureNotice.tsx) when no backend answers; this Recommends just
// narrows the common "portal front-end isn't even installed" case.
// electron-builder's `recommends` REPLACES its own default
// (["libappindicator3-1"], needed for the tray icon) rather than
// appending, so it must be listed explicitly here too.
recommends: ['libappindicator3-1', 'xdg-desktop-portal']
},
npmRebuild: false,
// See scripts/fix-pimono-chalk-unpack.mjs: corrects chalk's packaged version for
// pi-coding-agent's plain-Node child process — can't be fixed via a pnpm
// override like this repo's other pimono version collisions because chalk 5 is
// ESM-only and would break electron-builder's own CJS `require('chalk')`.
afterPack: fixPimonoChalkUnpack,
// --- AUTO-UPDATE ---
// electron-updater is wired in src/main/updater.ts (packaged builds only; silent
// download + install-on-next-quit; NSIS differential updates stay default-on).
// This GitHub config makes electron-builder emit latest.yml and app-update.yml.
// Before every production check, updater.ts replaces the repository-wide GitHub
// provider with the backend-selected immutable Windows release directory. Local
// testing keeps dev-app-update.yml + OMI_UPDATER_DEV=1 (forceDevUpdateConfig).
//
// NOTE: this block is the UPDATE FEED only — it must never be used as an upload
// target. electron-builder auto-publishes to it when CI + a git tag are detected,
// so every build command must pass `--publish never` (build:win does; the release
// workflow uploads explicitly via `gh release` instead).
publish: [{ provider: 'github', owner: 'BasedHardware', repo: 'omi', releaseType: 'release' }]
}