mirror of
https://github.com/hanzoai/desktop.git
synced 2026-10-30 14:58:42 +00:00
The main window mounts @hanzo/app's Host (was Rooms) and types its window bar as Titlebar (was Bar). The window's own component in host.tsx is now Main, so it no longer shares a name with the SDK's Host. Catalog: @hanzo/app 0.3.0 and @hanzo/ai 0.7.0, excluded from the release-age hold; app 0.3.0's peers raise @hanzo/appearance to 0.2.12, @hanzo/build to 0.2.86 and @hanzo/ui to 8.29.26. ui 8.29.26 asks @hanzo/event >= 0.3.63, and build 0.2.86 no longer exports `prompt`, which @hanzo/studio 0.1.3 imports, so event moves to 0.3.63 and studio to 0.1.8 (the versions hanzo-inc/app pins). public/memoji, a new asset tree 0.3.0 ships, is ignored like the rest. Comments and LLM.md say @hanzo/app instead of @hanzo/rooms. Claude-Session: https://claude.ai/code/session_015XYKLjZtDTJEnMo4eK3AFH
214 lines
8.4 KiB
TypeScript
214 lines
8.4 KiB
TypeScript
import { cpSync } from 'fs';
|
|
import { createRequire } from 'module';
|
|
import { dirname, resolve as pathResolve } from 'path';
|
|
import react from '@vitejs/plugin-react';
|
|
import { defineConfig, type Plugin } from 'vite';
|
|
import wasm from 'vite-plugin-wasm';
|
|
import tsconfigPaths from 'vite-tsconfig-paths';
|
|
import tailwindcss from '@tailwindcss/vite';
|
|
|
|
// react-native → web resolution. @hanzo/gui + @hanzogui/lucide-icons-2 pull the
|
|
// upstream react-native / react-native-svg, whose Flow syntax crashes esbuild &
|
|
// rollup (and Vite's own optimizer manages `alias`, so a plain resolve.alias can't
|
|
// reach it). This is the canonical gui-monorepo web alias map (guiAliases({ svg,
|
|
// rnwLite }) from @hanzogui/vite-plugin) — react-native-svg → the web-safe
|
|
// @hanzogui fork, and react-native[-web][/subpaths] → @hanzogui/react-native-web-
|
|
// lite via absolute paths so every layer (scan, optimize, rollup) resolves it. No
|
|
// Tamagui compiler plugin: the runtime GuiProvider config is enough.
|
|
const req = createRequire(import.meta.url);
|
|
|
|
// @hanzo/app names its portraits by path (`/agents/<id>.png`, `/bots/<name>.png`)
|
|
// and ships them in its `assets/`. hanzo.ai copies that tree into the
|
|
// root it serves (its scripts/rooms-assets.mjs), and so does this window: into
|
|
// public/ before every serve and build, so a new portrait arrives with the next
|
|
// @hanzo/app release and the copy is never committed.
|
|
function rooms(): Plugin {
|
|
return {
|
|
name: 'rooms-assets',
|
|
buildStart() {
|
|
const from = pathResolve(dirname(req.resolve('@hanzo/app')), '..', 'assets');
|
|
cpSync(from, pathResolve(import.meta.dirname, 'public'), { recursive: true });
|
|
},
|
|
};
|
|
}
|
|
const rnwlBase = dirname(
|
|
req.resolve('@hanzogui/react-native-web-lite/package.json'),
|
|
);
|
|
// The ESM entry, NOT req.resolve('.') — require.resolve picks the "require"
|
|
// condition (dist/cjs/index.js), whose CJS shape breaks named imports
|
|
// (ActivityIndicator et al) when Vite's dev server serves it as ESM. 8.3.5
|
|
// ships `.js` (8.3.1 shipped `.mjs`), and a module is a file or a directory
|
|
// with an index, so the per-module alias names no extension and Vite finds it.
|
|
const rnwl = `${rnwlBase}/dist/esm/index.js`;
|
|
const guiAliases = [
|
|
{
|
|
find: 'react-native-svg',
|
|
replacement: `${dirname(req.resolve('@hanzogui/react-native-svg/package.json'))}/dist/esm/index.js`,
|
|
},
|
|
{
|
|
find: /^react-native(?:-web)?\/dist\/(?:exports|modules)\/.*\/([^/]+)$/,
|
|
replacement: `${rnwlBase}/dist/esm/$1`,
|
|
},
|
|
{ find: /^react-native$/, replacement: rnwl },
|
|
{
|
|
find: /^react-native\/(Libraries\/Utilities\/codegenNativeComponent|Libraries\/Utilities\/codegenNativeCommand)$/,
|
|
replacement: `${rnwlBase}/$1`,
|
|
},
|
|
{
|
|
find: 'react-native/package.json',
|
|
replacement: req.resolve('@hanzogui/react-native-web-lite/package.json'),
|
|
},
|
|
{ find: /^react-native-web$/, replacement: rnwl },
|
|
];
|
|
|
|
// https://vitejs.dev/config/
|
|
export default defineConfig(() => ({
|
|
resolve: {
|
|
// @hanzo/usage ships its own react devDep; force a single React instance
|
|
// so its useUsage hook shares the app's React runtime. Dedupe the wallet
|
|
// store's peer deps (zustand/ethers) + @luxfi/crypto to the app's copy so
|
|
// the wallet store is one instance, not two.
|
|
dedupe: ['react', 'react-dom', 'zustand', 'ethers', '@luxfi/crypto'],
|
|
alias: [
|
|
// react-native / react-native-svg → web (see guiAliases above).
|
|
...guiAliases,
|
|
// libsodium-wrappers-sumo ESM entry imports ./libsodium-sumo.mjs which
|
|
// lives in the separate libsodium-sumo package.
|
|
{
|
|
find: './libsodium-sumo.mjs',
|
|
replacement: pathResolve(
|
|
import.meta.dirname,
|
|
'../../node_modules/libsodium-sumo/dist/modules-sumo-esm/libsodium-sumo.mjs',
|
|
),
|
|
},
|
|
],
|
|
},
|
|
plugins: [rooms(), react(), tailwindcss(), tsconfigPaths({ root: '../..' }), wasm()],
|
|
esbuild: {
|
|
// Important for wasm plugin
|
|
supported: {
|
|
'top-level-await': true,
|
|
bigint: true,
|
|
},
|
|
},
|
|
|
|
define: {
|
|
// Tamagui (@hanzo/gui) reads this to pick the web output at bundle time.
|
|
'process.env.TAMAGUI_TARGET': JSON.stringify('web'),
|
|
},
|
|
|
|
optimizeDeps: {
|
|
// Upstream react-native-web must not be pre-bundled when it is aliased to the
|
|
// lite fork (same as @hanzogui/vite-plugin). react-native itself is aliased
|
|
// away by guiAliases, so it never reaches the optimizer.
|
|
exclude: ['react-native-web'],
|
|
// CJS-only dep of the aliased react-native-web-lite ESM build; the /@fs
|
|
// alias path bypasses the dep scanner, so without prebundling the dev
|
|
// server ships raw CJS ("module is not defined") and the webview dies.
|
|
// @hanzogui/normalize-css-color pulls the CJS-only @react-native/normalize-
|
|
// color. Under pnpm neither is resolvable from the app, so naming either one
|
|
// directly matches nothing and the dev server ships raw `module.exports` —
|
|
// the webview dies on "module is not defined" before React mounts. Name the
|
|
// path from a package that IS resolvable and let Vite walk it.
|
|
include: [
|
|
'@hanzogui/react-native-web-lite > @hanzogui/normalize-css-color > @react-native/normalize-color',
|
|
],
|
|
},
|
|
|
|
// Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
|
|
//
|
|
// 1. prevent vite from obscuring rust errors
|
|
clearScreen: false,
|
|
// 2. tauri expects a fixed port, fail if that port is not available.
|
|
// 1420 is the port `tauri.conf.json` `devUrl` and the Playwright smoke
|
|
// `baseURL` both point at; serving 1421 meant `tauri:dev` and `test:smoke`
|
|
// were aimed at a dead port. One value, three consumers.
|
|
server: {
|
|
port: 1420,
|
|
strictPort: true,
|
|
watch: {
|
|
ignored: [
|
|
// Exclude output.wav from being watched
|
|
'**/output.wav',
|
|
// The cargo build directory is hundreds of thousands of files and no
|
|
// part of it is a frontend input. Watching it exhausts the inotify
|
|
// limit and `vite` dies at startup with ENOSPC the moment a debug
|
|
// build exists — which is exactly when you want `tauri:dev`.
|
|
'**/src-tauri/target',
|
|
'**/src-tauri/target/**',
|
|
],
|
|
},
|
|
// headers: {
|
|
// 'Cross-Origin-Embedder-Policy': 'require-corp',
|
|
// 'Cross-Origin-Opener-Policy': 'cross-origin',
|
|
// },
|
|
},
|
|
// 3. to make use of `TAURI_DEBUG` and other env variables
|
|
// https://tauri.studio/v1/api/config#buildconfig.beforedevcommand
|
|
// to access the Tauri environment variables set by the CLI with information about the current target
|
|
envPrefix: [
|
|
'VITE_',
|
|
'TAURI_PLATFORM',
|
|
'TAURI_ARCH',
|
|
'TAURI_FAMILY',
|
|
'TAURI_PLATFORM_VERSION',
|
|
'TAURI_PLATFORM_TYPE',
|
|
'TAURI_DEBUG',
|
|
],
|
|
|
|
build: {
|
|
// @hanzo/gui / react-native-web ship ES2022 syntax esbuild won't downlevel
|
|
// to vite's legacy baseline; the Tauri webview is modern.
|
|
target: 'es2022',
|
|
rollupOptions: {
|
|
input: {
|
|
index: pathResolve(import.meta.dirname, 'index.html'),
|
|
hanzo_node_manager: pathResolve(
|
|
import.meta.dirname,
|
|
'src/windows/hanzo-node-manager/index.html',
|
|
),
|
|
spotlight: pathResolve(
|
|
import.meta.dirname,
|
|
'src/windows/spotlight/index.html',
|
|
),
|
|
coordinator: pathResolve(
|
|
import.meta.dirname,
|
|
'src/windows/coordinator/index.html',
|
|
),
|
|
hanzo_artifacts: pathResolve(
|
|
import.meta.dirname,
|
|
'src/windows/hanzo-artifacts/index.html',
|
|
),
|
|
},
|
|
},
|
|
},
|
|
test: {
|
|
watch: false,
|
|
setupFiles: './src/test-setup.ts',
|
|
globals: true,
|
|
cache: { dir: '../../node_modules/.vitest/apps/hanzo-desktop' },
|
|
environment: 'jsdom',
|
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
|
reporters: ['default'],
|
|
// @hanzo/gui and the @hanzogui/* packages must go through Vite's transform
|
|
// pipeline, not Node's CJS loader. Externalized, `resolve.alias` never
|
|
// applies, so `react-native-svg` resolves to the UPSTREAM package whose
|
|
// published "commonjs" build still contains TypeScript source
|
|
// (`SvgTouchableMixin.ts`) — Node hits `Unexpected token 'typeof'` and every
|
|
// gui-backed component test fails to even collect. Inlining routes them
|
|
// through the same alias map the browser build uses.
|
|
server: {
|
|
deps: {
|
|
inline: [/@hanzogui\//, /@hanzo\/gui/, /@hanzo\/ui/, /react-native/],
|
|
},
|
|
},
|
|
coverage: {
|
|
reportsDirectory: '../../coverage/libs/hanzo-message-ts',
|
|
provider: 'v8',
|
|
},
|
|
},
|
|
worker: {
|
|
format: 'es' as const,
|
|
},
|
|
}));
|