diff --git a/CUSTOM_DISTROS.md b/CUSTOM_DISTROS.md index 1405a9119c..c9f08a2241 100644 --- a/CUSTOM_DISTROS.md +++ b/CUSTOM_DISTROS.md @@ -46,7 +46,7 @@ goose's architecture is designed for extensibility. Organizations can create "re |---------------|---------------|------------| | Preconfigure a model/provider | `config.yaml`, `init-config.yaml`, environment variables | Low | | Add custom AI providers | `crates/goose/src/providers/declarative/` | Low | -| Bundle custom MCP extensions | `config.yaml` extensions section, `ui/desktop/src/built-in-extensions.json` | Medium | +| Bundle custom MCP extensions | `config.yaml` extensions section, `ui/desktop/src/built-in-extensions.json`, `ui/desktop/src/components/settings/extensions/bundled-extensions.json` | Medium | | Modify system prompts | `crates/goose/src/prompts/` | Low | | Customize desktop branding | `ui/desktop/` (icons, names, colors) | Medium | | Build a new UI (web, mobile) | Integrate with `goose-server` REST API | High | @@ -191,7 +191,11 @@ async def query_data_lake(query: str) -> str: return results ``` -2. **Bundle as a built-in extension** by adding to `ui/desktop/src/built-in-extensions.json`: +2. **Bundle as a built-in extension** by adding to either: + - `ui/desktop/src/built-in-extensions.json` (core built-ins surfaced in extension UI) + - `ui/desktop/src/components/settings/extensions/bundled-extensions.json` (bundled extension catalog in Settings) + +Example: ```json { @@ -268,6 +272,26 @@ You are an AI assistant called [YourName], created by [YourCompany]. - Component text and labels - Feature visibility +5. **Align packaging and updater names** when rebranding: + - Update static branding metadata in `ui/desktop/package.json` (`productName`, description) and Linux desktop templates (`ui/desktop/forge.deb.desktop`, `ui/desktop/forge.rpm.desktop`) + + - Set build/release environment variables consistently: + - `GITHUB_OWNER` and `GITHUB_REPO` for publisher + updater repository lookup + - `GOOSE_BUNDLE_NAME` for bundle/debug scripts and updater asset naming (defaults to `Goose`) + +Example: + +```bash +export GITHUB_OWNER="your-org" +export GITHUB_REPO="your-goose-fork" +export GOOSE_BUNDLE_NAME="InsightStream-goose" +``` + +6. **Use this branding consistency checklist** before release: + - Application metadata (`forge.config.ts`, `package.json`, `index.html`) uses your distro name + - Release artifact names and updater lookup names are consistent + - Desktop launchers (Linux `.desktop` templates) point to the same executable name produced by packaging + ### Technical Details - Electron config: `ui/desktop/forge.config.ts` diff --git a/ui/desktop/package.json b/ui/desktop/package.json index 8364dccf18..6253c7bea4 100644 --- a/ui/desktop/package.json +++ b/ui/desktop/package.json @@ -17,10 +17,10 @@ "start:test-error": "GOOSE_TEST_ERROR=true electron-forge start", "package": "electron-forge package", "make": "electron-forge make", - "bundle:default": "node scripts/prepare-platform-binaries.js && npm run make && (cd out/Goose-darwin-arm64 && ditto -c -k --sequesterRsrc --keepParent Goose.app Goose.zip) || echo 'out/Goose-darwin-arm64 not found; either the binary is not built or you are not on macOS'", - "bundle:alpha": "ALPHA=true node scripts/prepare-platform-binaries.js && ALPHA=true npm run make && (cd out/Goose-darwin-arm64 && ditto -c -k --sequesterRsrc --keepParent Goose.app Goose_alpha.zip) || echo 'out/Goose-darwin-arm64 not found; either the binary is not built or you are not on macOS'", - "bundle:intel": "node scripts/prepare-platform-binaries.js && npm run make -- --arch=x64 && cd out/Goose-darwin-x64 && ditto -c -k --sequesterRsrc --keepParent Goose.app Goose_intel_mac.zip", - "debug": "echo 'run --remote-debugging-port=8315' && lldb out/Goose-darwin-arm64/Goose.app", + "bundle:default": "node scripts/prepare-platform-binaries.js && npm run make && BUNDLE_NAME=\"${GOOSE_BUNDLE_NAME:-Goose}\" && APP_DIR=\"out/${BUNDLE_NAME}-darwin-arm64\" && APP_BUNDLE=\"${APP_DIR}/${BUNDLE_NAME}.app\" && (cd \"$APP_DIR\" && ditto -c -k --sequesterRsrc --keepParent \"${BUNDLE_NAME}.app\" \"${BUNDLE_NAME}.zip\") || echo \"${APP_BUNDLE} not found; either the binary is not built or you are not on macOS\"", + "bundle:alpha": "ALPHA=true node scripts/prepare-platform-binaries.js && ALPHA=true npm run make && BUNDLE_NAME=\"${GOOSE_BUNDLE_NAME:-Goose}\" && APP_DIR=\"out/${BUNDLE_NAME}-darwin-arm64\" && APP_BUNDLE=\"${APP_DIR}/${BUNDLE_NAME}.app\" && (cd \"$APP_DIR\" && ditto -c -k --sequesterRsrc --keepParent \"${BUNDLE_NAME}.app\" \"${BUNDLE_NAME}_alpha.zip\") || echo \"${APP_BUNDLE} not found; either the binary is not built or you are not on macOS\"", + "bundle:intel": "node scripts/prepare-platform-binaries.js && npm run make -- --arch=x64 && BUNDLE_NAME=\"${GOOSE_BUNDLE_NAME:-Goose}\" && APP_DIR=\"out/${BUNDLE_NAME}-darwin-x64\" && APP_BUNDLE=\"${APP_DIR}/${BUNDLE_NAME}.app\" && (cd \"$APP_DIR\" && ditto -c -k --sequesterRsrc --keepParent \"${BUNDLE_NAME}.app\" \"${BUNDLE_NAME}_intel_mac.zip\")", + "debug": "echo 'run --remote-debugging-port=8315' && BUNDLE_NAME=\"${GOOSE_BUNDLE_NAME:-Goose}\" && lldb \"out/${BUNDLE_NAME}-darwin-arm64/${BUNDLE_NAME}.app\"", "test-e2e": "npm run generate-api && playwright test", "test-e2e:dev": "npm run generate-api && playwright test --reporter=list --retries=0 --max-failures=1", "test-e2e:ui": "npm run generate-api && playwright test --ui", diff --git a/ui/desktop/src/utils/githubUpdater.ts b/ui/desktop/src/utils/githubUpdater.ts index 2282e51cb7..a5d2ce3f92 100644 --- a/ui/desktop/src/utils/githubUpdater.ts +++ b/ui/desktop/src/utils/githubUpdater.ts @@ -29,6 +29,7 @@ interface UpdateCheckResult { export class GitHubUpdater { private readonly owner = process.env.GITHUB_OWNER || 'block'; private readonly repo = process.env.GITHUB_REPO || 'goose'; + private readonly bundleName = process.env.GOOSE_BUNDLE_NAME || 'Goose'; private readonly apiUrl = `https://api.github.com/repos/${this.owner}/${this.repo}/releases/latest`; async checkForUpdates(): Promise { @@ -103,16 +104,16 @@ export class GitHubUpdater { if (platform === 'darwin') { // macOS if (arch === 'arm64') { - assetName = 'Goose.zip'; + assetName = `${this.bundleName}.zip`; } else { - assetName = 'Goose_intel_mac.zip'; + assetName = `${this.bundleName}_intel_mac.zip`; } } else if (platform === 'win32') { // Windows - for future support - assetName = 'Goose-win32-x64.zip'; + assetName = `${this.bundleName}-win32-x64.zip`; } else { // Linux - for future support - assetName = `Goose-linux-${arch}.zip`; + assetName = `${this.bundleName}-linux-${arch}.zip`; } log.info(`GitHubUpdater: Looking for asset named: ${assetName}`); @@ -254,7 +255,7 @@ export class GitHubUpdater { // Save to Downloads directory const downloadsDir = path.join(os.homedir(), 'Downloads'); - const fileName = `goose-${latestVersion}.zip`; + const fileName = `${this.bundleName}-${latestVersion}.zip`; const downloadPath = path.join(downloadsDir, fileName); log.info(`GitHubUpdater: Writing file to ${downloadPath}...`); diff --git a/ui/desktop/vite.main.config.mts b/ui/desktop/vite.main.config.mts index 329f511cdd..7087ae8352 100644 --- a/ui/desktop/vite.main.config.mts +++ b/ui/desktop/vite.main.config.mts @@ -5,5 +5,6 @@ export default defineConfig({ define: { 'process.env.GITHUB_OWNER': JSON.stringify(process.env.GITHUB_OWNER || 'block'), 'process.env.GITHUB_REPO': JSON.stringify(process.env.GITHUB_REPO || 'goose'), + 'process.env.GOOSE_BUNDLE_NAME': JSON.stringify(process.env.GOOSE_BUNDLE_NAME || 'Goose'), }, });