Files
Aperant/apps/desktop/electron.vite.config.ts
a5670a6912 fix(build): bundle @libsql native modules + rebrand to Aperant (#1946)
* fix(build): unpack @libsql/client native modules from asar

@libsql/client has platform-specific native bindings (@libsql/darwin-arm64,
@libsql/linux-x64, etc.) containing .node files that cannot be loaded from
inside app.asar. This causes ERR_MODULE_NOT_FOUND on app startup after
updating to 2.8.0-beta.4.

Add @libsql/client to rollupOptions.external so Vite keeps it as a runtime
require, and add node_modules/@libsql/** to asarUnpack so electron-builder
extracts the native modules to app.asar.unpacked/.

Follows the same pattern used for @lydell/node-pty.

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* fix bundled and update name + icon

* fix: complete Aperant rebrand and harden native module loading

- Add try/catch + type validation to loadCreateClient() in db.ts to
  prevent silent failures when @libsql/client native module is missing
  or exports are wrong (was a blocking issue)
- Add path.resolve() and JSON type guard to ensureOnboardingComplete()
  for safer config file handling
- Replace require('fs').cpSync with static import; fix console.log in
  production code (index.ts)
- Complete "Auto Claude" → "Aperant" brand rename across ~30 remaining
  source files: renderer components, GitHub/GitLab PR comment bodies,
  User-Agent headers, MCP registry, and test assertions

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* fix(deps): sync package-lock.json with aperant rename

package.json was renamed from auto-claude-ui to aperant but
package-lock.json wasn't regenerated, causing npm ci to fail
in all CI jobs with "Missing: [email protected] from lock file".

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* fix(security): resolve CodeQL file-system race in ensureOnboardingComplete

Replace existsSync + readFileSync pattern with direct readFileSync
wrapped in try/catch for ENOENT. Eliminates the TOCTOU race condition
flagged by CodeQL (js/file-system-race).

Co-Authored-By: Claude Opus 4.6 <[email protected]>

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
2026-03-13 21:16:30 +01:00

137 lines
4.4 KiB
TypeScript

import { defineConfig, externalizeDepsPlugin } from 'electron-vite';
import react from '@vitejs/plugin-react';
import { resolve } from 'path';
import { config as dotenvConfig } from 'dotenv';
// Load .env file for build-time constants (Sentry DSN, etc.)
dotenvConfig({ path: resolve(__dirname, '.env') });
/**
* Build-time constants embedded via Vite `define`.
*
* In CI builds, these come from GitHub secrets.
* In local development, these come from apps/desktop/.env (loaded by dotenv).
*
* The `define` option replaces these values at build time, so they're
* embedded in the bundle and available at runtime in packaged apps.
*/
const sentryDefines = {
'__SENTRY_DSN__': JSON.stringify(process.env.SENTRY_DSN || ''),
'__SENTRY_TRACES_SAMPLE_RATE__': JSON.stringify(process.env.SENTRY_TRACES_SAMPLE_RATE || '0.1'),
'__SENTRY_PROFILES_SAMPLE_RATE__': JSON.stringify(process.env.SENTRY_PROFILES_SAMPLE_RATE || '0.1'),
};
/** Embedded API keys — search works out of the box, no user config needed. */
const embeddedKeys = {
'__SERPER_API_KEY__': JSON.stringify(process.env.SERPER_API_KEY || ''),
};
export default defineConfig({
main: {
define: { ...sentryDefines, ...embeddedKeys },
plugins: [externalizeDepsPlugin({
// Bundle these packages into the main process (they won't be in node_modules in packaged app)
exclude: [
'uuid',
'chokidar',
'dotenv',
'electron-log',
'proper-lockfile',
'semver',
'zod',
'@anthropic-ai/sdk',
'kuzu',
'electron-updater',
'@electron-toolkit/utils',
// Sentry and its transitive dependencies (opentelemetry -> debug -> ms)
'@sentry/electron',
'@sentry/core',
'@sentry/node',
'@sentry/utils',
'@opentelemetry/instrumentation',
'debug',
'ms',
// Minimatch for glob pattern matching in worktree handlers
'minimatch',
// XState for task state machine
'xstate',
// Vercel AI SDK packages (needed by worker thread + main process)
'ai',
'@ai-sdk/anthropic',
'@ai-sdk/openai',
'@ai-sdk/google',
'@ai-sdk/amazon-bedrock',
'@ai-sdk/azure',
'@ai-sdk/mistral',
'@ai-sdk/groq',
'@ai-sdk/xai',
'@ai-sdk/openai-compatible',
'@ai-sdk/provider',
'@ai-sdk/provider-utils',
]
})],
build: {
rollupOptions: {
input: {
index: resolve(__dirname, 'src/main/index.ts'),
// Worker thread entry point — must be a separate chunk so it can be
// spawned via `new Worker(path)` from WorkerBridge
'ai/agent/worker': resolve(__dirname, 'src/main/ai/agent/worker.ts'),
},
// Native modules that must remain external (loaded from disk, not bundled).
// @libsql/client is loaded lazily via globalThis.require() and resolved
// from extraResources/node_modules via Module.globalPaths (see index.ts).
external: ['@lydell/node-pty']
}
}
},
preload: {
plugins: [externalizeDepsPlugin()],
build: {
rollupOptions: {
input: {
index: resolve(__dirname, 'src/preload/index.ts')
}
}
}
},
renderer: {
define: sentryDefines,
root: resolve(__dirname, 'src/renderer'),
build: {
rollupOptions: {
input: {
index: resolve(__dirname, 'src/renderer/index.html')
}
}
},
plugins: [react()],
resolve: {
alias: {
'@': resolve(__dirname, 'src/renderer'),
'@shared': resolve(__dirname, 'src/shared'),
'@features': resolve(__dirname, 'src/renderer/features'),
'@components': resolve(__dirname, 'src/renderer/shared/components'),
'@hooks': resolve(__dirname, 'src/renderer/shared/hooks'),
'@lib': resolve(__dirname, 'src/renderer/shared/lib')
}
},
server: {
watch: {
// Ignore directories to prevent HMR conflicts during merge operations
// Using absolute paths and broader patterns
ignored: [
'**/node_modules/**',
'**/.git/**',
'**/.worktrees/**',
'**/.auto-claude/**',
'**/out/**',
// Ignore the parent autonomous-coding directory's worktrees
resolve(__dirname, '../.worktrees/**'),
resolve(__dirname, '../.auto-claude/**'),
]
}
}
}
});