feat(desktop): add protected-build Bestie experiment (#6902)

## Summary

Introduces a protected-build boundary for the default-off Bestie
experiment without adding any Bestie product surface.

- Official OSS builds select an empty protected-feature module and emit
no Bestie/Chief metadata or implementation content.
- Protected internal builds select a separate module graph containing
the Bestie experiment definition.
- Within an internal build, Bestie remains disabled until the user opts
in under Settings → Experiments.
- The production build runs an artifact matrix and fails if OSS output
contains protected content or internal output lacks the Bestie manifest.

## Build contract

| Build variant | User opt-in | Result |
| --- | --- | --- |
| Official OSS | Any/forged | Bestie absent from the compiled artifact |
| Protected internal | Off | Bestie available but disabled |
| Protected internal | On | Bestie enabled |

The companion protected-release change is squareup/buzz-releases#91. It
sets `VITE_BUZZ_BESTIE=1`, requires that exact value, forwards it into
the signed macOS build, and asserts the contract in release validation.

## Why this is separate

This gives later Bestie PRs one build-selected import seam. Protected
implementations must be reachable only from the internal module so they
never enter the official OSS module graph.

## Non-goals

- No Bestie persona or provisioning
- No sidebar, app-chrome, or message-toolbar UI
- No entitlement or secrecy claim: the source is public; this boundary
controls official Block artifacts

## Verification

- Exact commit `523cf49ced03cba9be43836a54d6aa5d6923cc82`
- Full `just ci`: 5,673 Desktop tests, 2,773 Tauri tests, 1,860 mobile
tests, Rust/Tauri/web/mobile static checks and builds
- OSS production artifact: scanner confirms no `Bestie`, `Chief of
Staff`, or `builtin:bestie` content
- Internal production artifact: scanner confirms the protected Bestie
manifest is emitted
- Both build orders verified; `dist` retains the requested variant for
Vite/Tauri packaging

---------

Signed-off-by: Arjun Mahanti <arjun@squareup.com>
Signed-off-by: Fizz <fizz@buzz.local>
Signed-off-by: Fizz <dae5f6af70b8695a8b83c8deae555f63be41630ec2b8cd493e41a439c9527dd8@buzz.block.builderlab.xyz>
Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: Fizz <fizz@buzz.local>
Co-authored-by: Fizz <dae5f6af70b8695a8b83c8deae555f63be41630ec2b8cd493e41a439c9527dd8@buzz.block.builderlab.xyz>
This commit is contained in:
Arjun Mahanti
2026-08-31 17:03:35 -04:00
committed by GitHub
parent 2f3dd850db
commit 5673c3307e
16 changed files with 570 additions and 57 deletions

View File

@@ -274,6 +274,10 @@ RUST_LOG=buzz_relay=debug,buzz_datastore=info,buzz_db=debug,buzz_auth=debug,buzz
# app launch while keeping the current identity and relay data.
# VITE_BUZZ_FORCE_FRESH_ONBOARDING=true
# Protected internal builds only: selects the module graph that contains the
# default-off Bestie experiment. Official OSS builds must leave this unset.
# VITE_BUZZ_BESTIE=1
# ── Subscription & filtering ─────────────────────────────────────────────────
# Subscribe mode: "mentions" (default), "all", or "config" (rule-based).
# BUZZ_ACP_SUBSCRIBE=mentions

View File

@@ -304,7 +304,7 @@ jobs:
name: Desktop
runs-on: ubuntu-latest
timeout-minutes: 5
needs: [changes, desktop-core, desktop-smoke-e2e]
needs: [changes, desktop-core, desktop-smoke-e2e, desktop-windows-build]
if: always() && (github.event_name == 'push' || needs.changes.outputs.desktop == 'true' || needs.changes.outputs.desktop-rust == 'true' || needs.changes.outputs.rust == 'true')
permissions:
contents: read
@@ -319,6 +319,10 @@ jobs:
echo "Desktop Smoke E2E shards finished with: ${{ needs.desktop-smoke-e2e.result }}"
exit 1
fi
if [ "${{ needs.desktop-windows-build.result }}" != "success" ]; then
echo "Desktop Windows Build finished with: ${{ needs.desktop-windows-build.result }}"
exit 1
fi
echo "Desktop jobs passed"
desktop-e2e-relay:
@@ -1133,6 +1137,36 @@ jobs:
-p git-credential-nostr \
-p git-sign-nostr
desktop-windows-build:
name: Desktop Windows Build
runs-on: windows-latest
timeout-minutes: 20
needs: [changes]
if: github.event_name == 'push' || needs.changes.outputs.desktop == 'true' || needs.changes.outputs.desktop-rust == 'true' || needs.changes.outputs.rust == 'true'
permissions:
contents: read
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 24.14.1
package-manager-cache: false
- uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4.3.0
with:
version: 11.4.0
- name: Install desktop dependencies
shell: bash
run: pnpm install --frozen-lockfile
- name: Build both protected-feature selections
shell: pwsh
run: |
Remove-Item Env:VITE_BUZZ_BESTIE -ErrorAction SilentlyContinue
pnpm -C desktop build
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
$env:VITE_BUZZ_BESTIE = "1"
pnpm -C desktop build
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
windows-rust:
name: Windows Rust (x86_64-pc-windows-msvc)
runs-on: windows-latest

View File

@@ -5,7 +5,7 @@
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"build": "tsc && node ./scripts/build-protected-feature-artifacts.mjs",
"build:e2e": "tsc && vite build --mode e2e",
"typecheck": "tsc --noEmit",
"check:file-sizes": "node ./scripts/check-file-sizes.mjs",
@@ -16,13 +16,13 @@
"format": "biome format --write .",
"test": "node --import ./test-loader.mjs --experimental-strip-types --test \"src/**/*.test.mjs\"",
"preview": "vite preview",
"tauri": "tauri",
"tauri": "node ./scripts/tauri-command.mjs",
"test:e2e": "pnpm build:e2e && playwright test",
"test:e2e:smoke": "pnpm build:e2e && playwright test --project=smoke",
"test:e2e:integration": "pnpm build:e2e && playwright test --project=integration",
"test:e2e:release-smoke": "pnpm build:e2e && playwright test --config=playwright.release-smoke.config.ts",
"test:e2e:report": "playwright show-report",
"tauri:build": "tauri build"
"tauri:build": "node ./scripts/tauri-command.mjs build"
},
"dependencies": {
"@dnd-kit/core": "^6.3.1",

View File

@@ -0,0 +1,151 @@
import { spawnSync } from "node:child_process";
import {
mkdtempSync,
readFileSync,
readdirSync,
rmSync,
statSync,
} from "node:fs";
import { tmpdir } from "node:os";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { loadEnv } from "vite";
const desktopRoot = path.resolve(
path.dirname(fileURLToPath(import.meta.url)),
"..",
);
const vitePackageJsonPath = fileURLToPath(
import.meta.resolve("vite/package.json"),
);
const vitePackage = JSON.parse(readFileSync(vitePackageJsonPath, "utf8"));
const viteEntrypoint = path.resolve(
path.dirname(vitePackageJsonPath),
vitePackage.bin.vite,
);
function buildVariant({ internal, output }) {
const env = {
...process.env,
// Pin both children explicitly. Deleting the OSS value lets Vite reload
// `=1` from .env.local or a mode-specific env file.
VITE_BUZZ_BESTIE: internal ? "1" : "0",
};
const result = spawnSync(
process.execPath,
[viteEntrypoint, "build", "--outDir", output, "--emptyOutDir"],
{
cwd: desktopRoot,
env,
stdio: "inherit",
},
);
if (result.error) throw result.error;
if (result.status !== 0) {
throw new Error(
`${internal ? "internal" : "OSS"} desktop build failed with status ${result.status}`,
);
}
}
function emittedText(root) {
const chunks = [];
const visit = (candidate) => {
const stat = statSync(candidate);
if (stat.isDirectory()) {
for (const child of readdirSync(candidate)) {
visit(path.join(candidate, child));
}
return;
}
if (/\.(?:css|html|js|json)$/u.test(candidate)) {
chunks.push(readFileSync(candidate, "utf8"));
}
};
visit(root);
return chunks.join("\n");
}
export function assertArtifactContract({ ossOutput, internalOutput }) {
const ossText = emittedText(ossOutput);
const internalText = emittedText(internalOutput);
const protectedContent = /\bbestie\b|chief of staff|builtin:bestie/iu;
const internalManifestMarker =
"Try a personal agent that is always close at hand";
if (protectedContent.test(ossText)) {
throw new Error(
"Official OSS desktop artifact contains protected Bestie/Chief content",
);
}
if (!internalText.includes(internalManifestMarker)) {
throw new Error(
"Protected internal desktop artifact is missing the Bestie manifest",
);
}
}
/** Resolve the requested output with the same precedence used by Vite config. */
export function selectInternalVariant({ processEnv, modeEnv }) {
return (processEnv.VITE_BUZZ_BESTIE ?? modeEnv.VITE_BUZZ_BESTIE) === "1";
}
/** Build and inspect both graphs, leaving the requested variant in dist. */
export function buildArtifactMatrix({
selectedInternalVariant,
selectedOutput,
alternateOutput,
build = buildVariant,
}) {
// Build the unselected variant outside dist first, then leave the requested
// variant in dist for Vite/Tauri's ordinary packaging contract.
build({
internal: !selectedInternalVariant,
output: alternateOutput,
});
build({
internal: selectedInternalVariant,
output: selectedOutput,
});
assertArtifactContract({
ossOutput: selectedInternalVariant ? alternateOutput : selectedOutput,
internalOutput: selectedInternalVariant ? selectedOutput : alternateOutput,
});
}
function main() {
const selectedInternalVariant = selectInternalVariant({
processEnv: process.env,
modeEnv: loadEnv("production", desktopRoot, ""),
});
const scratchRoot = mkdtempSync(
path.join(tmpdir(), "buzz-protected-feature-artifacts-"),
);
const selectedOutput = process.env.BUZZ_PROTECTED_BUILD_OUTPUT
? path.resolve(process.env.BUZZ_PROTECTED_BUILD_OUTPUT)
: path.join(desktopRoot, "dist");
const alternateOutput = path.join(scratchRoot, "alternate");
try {
buildArtifactMatrix({
selectedInternalVariant,
selectedOutput,
alternateOutput,
});
} finally {
rmSync(scratchRoot, { recursive: true, force: true });
}
console.log(
`Protected feature artifact matrix passed; dist contains the ${selectedInternalVariant ? "internal" : "OSS"} variant.`,
);
}
if (
process.argv[1] &&
path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)
) {
main();
}

View File

@@ -0,0 +1,63 @@
import { spawnSync } from "node:child_process";
import { readFileSync } from "node:fs";
import { mkdtempSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import path from "node:path";
import { fileURLToPath } from "node:url";
const desktopRoot = path.resolve(
path.dirname(fileURLToPath(import.meta.url)),
"..",
);
const tauriPackageJsonPath = fileURLToPath(
import.meta.resolve("@tauri-apps/cli/package.json"),
);
const tauriPackage = JSON.parse(readFileSync(tauriPackageJsonPath, "utf8"));
const defaultTauriEntrypoint = path.resolve(
path.dirname(tauriPackageJsonPath),
tauriPackage.bin.tauri,
);
function runTauri(args, options = {}) {
const entrypoint =
process.env.BUZZ_TAURI_CLI_ENTRYPOINT ?? defaultTauriEntrypoint;
const result = spawnSync(process.execPath, [entrypoint, ...args], {
cwd: desktopRoot,
env: { ...process.env, ...options.env },
stdio: "inherit",
});
if (result.error) throw result.error;
return result.status ?? 1;
}
export function runTauriCommand(args) {
if (args[0] !== "build") return runTauri(args);
// Tauri runs beforeBuildCommand and then consumes frontendDist. Give the
// entire invocation a private directory so concurrent OSS/internal packages
// cannot replace one another's assets between those two operations.
const invocationRoot = mkdtempSync(
path.join(tmpdir(), "buzz-tauri-package-assets-"),
);
const frontendDist = path.join(invocationRoot, "dist");
const outputOverride = JSON.stringify({ build: { frontendDist } });
try {
const delimiterIndex = args.indexOf("--");
const configIndex = delimiterIndex === -1 ? args.length : delimiterIndex;
const tauriArgs = [...args];
tauriArgs.splice(configIndex, 0, "--config", outputOverride);
return runTauri(tauriArgs, {
env: { BUZZ_PROTECTED_BUILD_OUTPUT: frontendDist },
});
} finally {
rmSync(invocationRoot, { recursive: true, force: true });
}
}
if (
process.argv[1] &&
path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)
) {
process.exitCode = runTauriCommand(process.argv.slice(2));
}

View File

@@ -7,11 +7,11 @@ import {
canManageCommunityMembers,
shouldWarnMissingMembershipSnapshot,
} from "@/shared/api/relayMembers";
import { getFeature } from "@/shared/features/manifest";
import {
getFeature,
resolveEnabled,
useFeatureSnapshot,
} from "@/shared/features/useFeatureEnabled";
} from "@/shared/features";
import { topChromeBackdrop } from "@/shared/layout/chromeLayout";
import { cn } from "@/shared/lib/cn";
import {
@@ -137,7 +137,10 @@ export function SettingsView({
// stable and renders unconditionally (fail-open).
if (s.featureGate) {
const feature = getFeature(s.featureGate);
if (feature && !resolveEnabled(s.featureGate, featureState)) {
if (
feature &&
!resolveEnabled(s.featureGate, featureState, feature.defaultEnabled)
) {
return false;
}
}

View File

@@ -0,0 +1,95 @@
import assert from "node:assert/strict";
import {
mkdtempSync,
mkdirSync,
readFileSync,
rmSync,
writeFileSync,
} from "node:fs";
import { tmpdir } from "node:os";
import path from "node:path";
import { describe, it } from "node:test";
import { loadEnv } from "vite";
import {
buildArtifactMatrix,
selectInternalVariant,
} from "../../scripts/build-protected-feature-artifacts.mjs";
const INTERNAL_MARKER = "Try a personal agent that is always close at hand";
function fakeBuilder(calls) {
return ({ internal, output }) => {
calls.push(internal);
rmSync(output, { recursive: true, force: true });
mkdirSync(output, { recursive: true });
writeFileSync(
path.join(output, "index.js"),
internal ? INTERNAL_MARKER : "public desktop artifact",
);
};
}
describe("protected feature production artifact selection", () => {
it("honors env-file selection while process overrides retain the requested dist", () => {
const root = mkdtempSync(path.join(tmpdir(), "buzz-protected-build-test-"));
const envRoot = path.join(root, "env");
mkdirSync(envRoot);
writeFileSync(path.join(envRoot, ".env.local"), "VITE_BUZZ_BESTIE=1\n");
try {
const modeEnv = loadEnv("production", envRoot, "");
const internalOutput = path.join(root, "internal-dist");
const internalAlternate = path.join(root, "internal-alternate");
const internalCalls = [];
const fileSelectedInternal = selectInternalVariant({
processEnv: {},
modeEnv,
});
assert.equal(fileSelectedInternal, true);
buildArtifactMatrix({
selectedInternalVariant: fileSelectedInternal,
selectedOutput: internalOutput,
alternateOutput: internalAlternate,
build: fakeBuilder(internalCalls),
});
assert.deepEqual(internalCalls, [false, true]);
assert.match(
readFileSync(path.join(internalOutput, "index.js"), "utf8"),
/personal agent/u,
);
assert.doesNotMatch(
readFileSync(path.join(internalAlternate, "index.js"), "utf8"),
/personal agent/u,
);
const ossOutput = path.join(root, "oss-dist");
const ossAlternate = path.join(root, "oss-alternate");
const ossCalls = [];
const processSelectedOss = selectInternalVariant({
processEnv: { VITE_BUZZ_BESTIE: "0" },
modeEnv,
});
assert.equal(processSelectedOss, false);
buildArtifactMatrix({
selectedInternalVariant: processSelectedOss,
selectedOutput: ossOutput,
alternateOutput: ossAlternate,
build: fakeBuilder(ossCalls),
});
assert.deepEqual(ossCalls, [true, false]);
assert.doesNotMatch(
readFileSync(path.join(ossOutput, "index.js"), "utf8"),
/personal agent/u,
);
assert.match(
readFileSync(path.join(ossAlternate, "index.js"), "utf8"),
/personal agent/u,
);
} finally {
rmSync(root, { recursive: true, force: true });
}
});
});

View File

@@ -0,0 +1,11 @@
import type { FeatureDefinition } from "@/shared/features/types";
/** Definitions available only in the protected internal application build. */
export const protectedFeatureDefinitions: FeatureDefinition[] = [
{
id: "bestie",
name: "Bestie",
description: "Try a personal agent that is always close at hand",
platforms: ["desktop"],
},
];

View File

@@ -0,0 +1,22 @@
import assert from "node:assert/strict";
import { describe, it } from "node:test";
import { resolveEnabled } from "../shared/features/resolveEnabled.ts";
import { protectedFeatureDefinitions as internalDefinitions } from "./internal.ts";
import { protectedFeatureDefinitions as publicDefinitions } from "./public.ts";
describe("protected feature build variants", () => {
it("keeps protected definitions out of the OSS module", () => {
assert.deepEqual(publicDefinitions, []);
});
it("adds Bestie as a default-off experiment only through the internal module", () => {
assert.deepEqual(
internalDefinitions.map((feature) => feature.id),
["bestie"],
);
const bestie = internalDefinitions[0];
assert.ok(bestie);
assert.equal(resolveEnabled(bestie.id, {}, bestie.defaultEnabled), false);
});
});

View File

@@ -0,0 +1,7 @@
import type { FeatureDefinition } from "@/shared/features/types";
/**
* Protected feature definitions compiled into the official OSS application.
* Keep this module free of protected product names, metadata, and imports.
*/
export const protectedFeatureDefinitions: FeatureDefinition[] = [];

View File

@@ -0,0 +1,97 @@
import assert from "node:assert/strict";
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import path from "node:path";
import { test } from "node:test";
import { fileURLToPath } from "node:url";
import { spawn } from "node:child_process";
const desktopRoot = path.resolve(
path.dirname(fileURLToPath(import.meta.url)),
"../..",
);
const wrapper = path.join(desktopRoot, "scripts/tauri-command.mjs");
const fakeCli = path.join(tmpdir(), `buzz-fake-tauri-${process.pid}.mjs`);
writeFileSync(
fakeCli,
`import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
import path from "node:path";
const args = process.argv.slice(2);
const configIndex = args.lastIndexOf("--config");
const override = JSON.parse(args[configIndex + 1]);
const output = override.build.frontendDist;
mkdirSync(output, { recursive: true });
writeFileSync(path.join(output, "variant.txt"), process.env.VITE_BUZZ_BESTIE);
await new Promise((resolve) => setTimeout(resolve, 100));
const observed = readFileSync(path.join(output, "variant.txt"), "utf8");
writeFileSync(
process.env.BUZZ_TEST_RESULT,
JSON.stringify({ args, output, observed }),
);
`,
);
function packageVariant(variant, result, runnerArguments = []) {
return new Promise((resolve, reject) => {
const child = spawn(
process.execPath,
[wrapper, "build", ...runnerArguments],
{
cwd: desktopRoot,
env: {
...process.env,
BUZZ_TAURI_CLI_ENTRYPOINT: fakeCli,
BUZZ_TEST_RESULT: result,
VITE_BUZZ_BESTIE: variant,
},
stdio: "inherit",
},
);
child.once("error", reject);
child.once("exit", (code) =>
code === 0 ? resolve() : reject(new Error(`wrapper exited ${code}`)),
);
});
}
test("opposite Tauri package variants own private frontend artifacts", async () => {
const resultRoot = path.join(tmpdir(), `buzz-tauri-results-${process.pid}`);
mkdirSync(resultRoot, { recursive: true });
const ossResult = path.join(resultRoot, "oss.json");
const internalResult = path.join(resultRoot, "internal.json");
await Promise.all([
packageVariant("0", ossResult),
packageVariant("1", internalResult),
]);
const oss = JSON.parse(readFileSync(ossResult, "utf8"));
const internal = JSON.parse(readFileSync(internalResult, "utf8"));
assert.equal(oss.observed, "0");
assert.equal(internal.observed, "1");
assert.notEqual(oss.output, internal.output);
});
test("private config precedes Cargo runner arguments", async () => {
const result = path.join(
tmpdir(),
`buzz-tauri-runner-arguments-${process.pid}.json`,
);
await packageVariant("0", result, [
"--config",
'{"bundle":{"active":false}}',
"--",
"--locked",
]);
const invocation = JSON.parse(readFileSync(result, "utf8"));
const delimiterIndex = invocation.args.indexOf("--");
const privateConfigIndex = invocation.args.lastIndexOf("--config");
assert.ok(privateConfigIndex < delimiterIndex);
assert.equal(invocation.args[delimiterIndex + 1], "--locked");
assert.equal(
JSON.parse(invocation.args[privateConfigIndex + 1]).build.frontendDist,
invocation.output,
);
});

View File

@@ -1,4 +1,5 @@
import manifestJson from "@features-manifest";
import { protectedFeatureDefinitions } from "@protected-features";
import { z } from "zod";
import type { FeatureDefinition, FeaturesManifest } from "./types";
@@ -25,7 +26,10 @@ const FeaturesManifestSchema = z.object({
const EMPTY_MANIFEST: FeaturesManifest = { version: 1, features: [] };
function loadManifest(): FeaturesManifest {
const result = FeaturesManifestSchema.safeParse(manifestJson);
const result = FeaturesManifestSchema.safeParse({
...manifestJson,
features: [...manifestJson.features, ...protectedFeatureDefinitions],
});
if (!result.success) {
console.warn(
"[FeatureFlags] preview-features.json failed schema validation; falling back to empty manifest.",

View File

@@ -105,6 +105,8 @@ export function useFeatureEnabled(featureId: string): boolean {
return resolveEnabled(featureId, overrides, feature.defaultEnabled);
}
export { resolveEnabled } from "./resolveEnabled";
/**
* Hook to toggle a feature override. Returns [enabled, toggle].
*/
@@ -157,5 +159,3 @@ export function usePreviewFeatureWarning(featureId: string): void {
};
}, [feature, enabled]);
}
export { resolveEnabled } from "./resolveEnabled";

View File

@@ -89,6 +89,12 @@ export function resolve(specifier, context, nextResolve) {
const resolved = path.join(repoRoot, "preview-features.json");
return nextResolve(toFileSpecifier(resolved), context);
}
if (specifier === "@protected-features") {
const variant =
process.env.VITE_BUZZ_BESTIE === "1" ? "internal.ts" : "public.ts";
const resolved = path.join(srcRoot, "protectedFeatures", variant);
return nextResolve(toFileSpecifier(resolved), context);
}
if (specifier === "@model-capabilities-manifest") {
const resolved = path.join(repoRoot, "scripts", "model-capabilities.json");
return nextResolve(toFileSpecifier(resolved), context);

View File

@@ -8,6 +8,7 @@
"paths": {
"@/*": ["./src/*"],
"@features-manifest": ["../preview-features.json"],
"@protected-features": ["./src/protectedFeatures/public.ts"],
"@model-capabilities-manifest": ["../scripts/model-capabilities.json"]
},

View File

@@ -1,56 +1,71 @@
import path from "node:path";
import { defineConfig } from "vite";
import { defineConfig, loadEnv } from "vite";
import react from "@vitejs/plugin-react";
import { tanstackRouter } from "@tanstack/router-plugin/vite";
const host = process.env.TAURI_DEV_HOST;
// https://vite.dev/config/
export default defineConfig(async () => ({
plugins: [
tanstackRouter({
target: "react",
routesDirectory: "./src/app/routes",
generatedRouteTree: "./src/app/routeTree.gen.ts",
virtualRouteConfig: "./src/app/routes.ts",
quoteStyle: "double",
semicolons: true,
routeTreeFileHeader: [
"// biome-ignore-all lint: generated by TanStack Router",
],
}),
react(),
],
resolve: {
alias: {
"@": "/src",
"@features-manifest": path.resolve(__dirname, "../preview-features.json"),
"@model-capabilities-manifest": path.resolve(
__dirname,
"../scripts/model-capabilities.json",
),
},
},
export default defineConfig(async ({ mode }) => {
const modeEnv = loadEnv(mode, __dirname, "");
const protectedFeaturesEnabled =
(process.env.VITE_BUZZ_BESTIE ?? modeEnv.VITE_BUZZ_BESTIE) === "1";
// 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
server: {
port: parseInt(process.env.VITE_PORT || "1420", 10),
strictPort: true,
host: host || false,
hmr: host
? {
protocol: "ws",
host,
port: parseInt(process.env.VITE_HMR_PORT || "1421", 10),
}
: undefined,
watch: {
// 3. tell Vite to ignore watching `src-tauri`
ignored: ["**/src-tauri/**"],
return {
plugins: [
tanstackRouter({
target: "react",
routesDirectory: "./src/app/routes",
generatedRouteTree: "./src/app/routeTree.gen.ts",
virtualRouteConfig: "./src/app/routes.ts",
quoteStyle: "double",
semicolons: true,
routeTreeFileHeader: [
"// biome-ignore-all lint: generated by TanStack Router",
],
}),
react(),
],
resolve: {
alias: {
"@": "/src",
"@features-manifest": path.resolve(
__dirname,
"../preview-features.json",
),
"@protected-features": path.resolve(
__dirname,
protectedFeaturesEnabled
? "./src/protectedFeatures/internal.ts"
: "./src/protectedFeatures/public.ts",
),
"@model-capabilities-manifest": path.resolve(
__dirname,
"../scripts/model-capabilities.json",
),
},
},
},
}));
// 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
server: {
port: parseInt(process.env.VITE_PORT || "1420", 10),
strictPort: true,
host: host || false,
hmr: host
? {
protocol: "ws",
host,
port: parseInt(process.env.VITE_HMR_PORT || "1421", 10),
}
: undefined,
watch: {
// 3. tell Vite to ignore watching `src-tauri`
ignored: ["**/src-tauri/**"],
},
},
};
});