feat(KB-335): rename environment variables from KB_* to FUSION_*
- Rename all KB_* environment variables to FUSION_* prefix across CLI and dashboard - Update CLI runtime files (native-patch.ts) and build configuration - Update dashboard server, badge-pubsub, GitHub webhooks, and terminal service - Update test files to use new FUSION_API_KEY and related env vars - Update documentation in README, AGENTS.md, STANDALONE.md, and dashboard README - Update changeset files with new environment variable names
This commit is contained in:
@@ -14,9 +14,9 @@ Replace GitHub badge polling with GitHub App webhook ingestion
|
||||
- Removed live `/api/ws` dependency on `GitHubPollingService` lifecycle
|
||||
|
||||
**Configuration:**
|
||||
- `KB_GITHUB_APP_ID` - GitHub App ID
|
||||
- `KB_GITHUB_APP_PRIVATE_KEY` or `KB_GITHUB_APP_PRIVATE_KEY_PATH` - PEM private key
|
||||
- `KB_GITHUB_WEBHOOK_SECRET` - Webhook secret for signature verification
|
||||
- `FUSION_GITHUB_APP_ID` - GitHub App ID
|
||||
- `FUSION_GITHUB_APP_PRIVATE_KEY` or `FUSION_GITHUB_APP_PRIVATE_KEY_PATH` - PEM private key
|
||||
- `FUSION_GITHUB_WEBHOOK_SECRET` - Webhook secret for signature verification
|
||||
|
||||
**Required GitHub App Permissions:**
|
||||
- Metadata: Read
|
||||
|
||||
19
.changeset/rename-environment-variables.md
Normal file
19
.changeset/rename-environment-variables.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
"@gsxdsm/fusion": minor
|
||||
"@fusion/dashboard": patch
|
||||
---
|
||||
|
||||
Rename environment variables from KB_* to FUSION_* prefix
|
||||
|
||||
BREAKING CHANGE: All environment variables have been renamed:
|
||||
- KB_GITHUB_APP_ID → FUSION_GITHUB_APP_ID
|
||||
- KB_GITHUB_APP_PRIVATE_KEY → FUSION_GITHUB_APP_PRIVATE_KEY
|
||||
- KB_GITHUB_APP_PRIVATE_KEY_PATH → FUSION_GITHUB_APP_PRIVATE_KEY_PATH
|
||||
- KB_GITHUB_WEBHOOK_SECRET → FUSION_GITHUB_WEBHOOK_SECRET
|
||||
- KB_BADGE_PUBSUB_REDIS_URL → FUSION_BADGE_PUBSUB_REDIS_URL
|
||||
- KB_BADGE_PUBSUB_CHANNEL → FUSION_BADGE_PUBSUB_CHANNEL
|
||||
- KB_DEBUG_PLANNING_ROUTES → FUSION_DEBUG_PLANNING_ROUTES
|
||||
- KB_RUNTIME_DIR → FUSION_RUNTIME_DIR
|
||||
- KB_NATIVE_ASSETS_PATH → FUSION_NATIVE_ASSETS_PATH
|
||||
- KB_FAKE_BUNFS_ROOT → FUSION_FAKE_BUNFS_ROOT
|
||||
- KB_CLIENT_DIR → FUSION_CLIENT_DIR
|
||||
@@ -7,8 +7,8 @@ Add shared badge pub/sub support for multi-instance dashboard deployments
|
||||
The dashboard now supports cross-instance badge update delivery via Redis pub/sub. When running multiple dashboard instances behind a load balancer, badge updates detected on one instance are now delivered to subscribed WebSocket clients on other instances.
|
||||
|
||||
**Configuration:**
|
||||
- `KB_BADGE_PUBSUB_REDIS_URL` - Redis connection URL (enables multi-instance mode)
|
||||
- `KB_BADGE_PUBSUB_CHANNEL` - Pub/sub channel name (default: `kb:badge-updates`)
|
||||
- `FUSION_BADGE_PUBSUB_REDIS_URL` - Redis connection URL (enables multi-instance mode)
|
||||
- `FUSION_BADGE_PUBSUB_CHANNEL` - Pub/sub channel name (default: `fusion:badge-updates`)
|
||||
|
||||
**Features:**
|
||||
- Badge snapshots are fanned out across instances while preserving per-instance focused polling
|
||||
|
||||
@@ -162,7 +162,7 @@ Use `useBadgeWebSocket()` when a UI surface needs live badge snapshots for speci
|
||||
- `/api/ws` is badge-specific; do **not** reuse it for general task updates.
|
||||
- Badge broadcasts should contain only `prInfo` / `issueInfo` snapshot data, never full task objects.
|
||||
- Badge updates are now **push-based via GitHub App webhooks** at `POST /api/github/webhooks`.
|
||||
- The server verifies webhook signatures using `KB_GITHUB_WEBHOOK_SECRET`, fetches canonical badge state with GitHub App installation tokens, and broadcasts updates via the existing `task:updated` → `/api/ws` bridge.
|
||||
- The server verifies webhook signatures using `FUSION_GITHUB_WEBHOOK_SECRET`, fetches canonical badge state with GitHub App installation tokens, and broadcasts updates via the existing `task:updated` → `/api/ws` bridge.
|
||||
- Keep the existing 5-minute refresh endpoints (`/api/tasks/:id/pr/status`, `/api/tasks/:id/issue/status`) as a fallback path when webhook delivery is unavailable.
|
||||
|
||||
## Git
|
||||
|
||||
@@ -413,10 +413,10 @@ pnpm --filter kb build:exe -- --target bun-linux-x64
|
||||
|
||||
The `client/` directory is shared across all binaries (platform-independent assets).
|
||||
|
||||
You can override the dashboard asset path via the `KB_CLIENT_DIR` environment variable:
|
||||
You can override the dashboard asset path via the `FUSION_CLIENT_DIR` environment variable:
|
||||
|
||||
```bash
|
||||
KB_CLIENT_DIR=/path/to/client ./fn dashboard
|
||||
FUSION_CLIENT_DIR=/path/to/client ./fn dashboard
|
||||
```
|
||||
|
||||
**Prerequisites:** Bun ≥ 1.0 (`bun --version`)
|
||||
@@ -432,7 +432,7 @@ Tasks with linked GitHub PRs or imported issues display real-time status badges
|
||||
- **PR badges** — Shows open/closed/merged state with check status
|
||||
- **Issue badges** — Shows open/closed state
|
||||
- **WebSocket updates** — Badge status updates instantly via WebSocket when changes occur on GitHub
|
||||
- **Multi-instance support** — Redis pub/sub enables badge updates across load-balanced dashboard instances (configure via `KB_BADGE_PUBSUB_REDIS_URL`)
|
||||
- **Multi-instance support** — Redis pub/sub enables badge updates across load-balanced dashboard instances (configure via `FUSION_BADGE_PUBSUB_REDIS_URL`)
|
||||
|
||||
### PR Creation
|
||||
|
||||
|
||||
@@ -34,10 +34,10 @@ When deploying the dashboard behind a load balancer with multiple instances, con
|
||||
|
||||
```bash
|
||||
# Set Redis URL for cross-instance badge synchronization
|
||||
export KB_BADGE_PUBSUB_REDIS_URL="redis://redis.example.com:6379"
|
||||
export FUSION_BADGE_PUBSUB_REDIS_URL="redis://redis.example.com:6379"
|
||||
|
||||
# Optional: customize the pub/sub channel (default: kb:badge-updates)
|
||||
export KB_BADGE_PUBSUB_CHANNEL="my-app-badge-updates"
|
||||
# Optional: customize the pub/sub channel (default: fusion:badge-updates)
|
||||
export FUSION_BADGE_PUBSUB_CHANNEL="my-app-badge-updates"
|
||||
|
||||
fn dashboard
|
||||
```
|
||||
@@ -50,10 +50,10 @@ For real-time PR/issue badge updates, configure a GitHub App to push updates to
|
||||
|
||||
**Required Environment Variables:**
|
||||
```bash
|
||||
export KB_GITHUB_APP_ID="123456"
|
||||
export KB_GITHUB_APP_PRIVATE_KEY_PATH="/path/to/private-key.pem"
|
||||
# Or: export KB_GITHUB_APP_PRIVATE_KEY="$(cat /path/to/private-key.pem)"
|
||||
export KB_GITHUB_WEBHOOK_SECRET="your-webhook-secret"
|
||||
export FUSION_GITHUB_APP_ID="123456"
|
||||
export FUSION_GITHUB_APP_PRIVATE_KEY_PATH="/path/to/private-key.pem"
|
||||
# Or: export FUSION_GITHUB_APP_PRIVATE_KEY="$(cat /path/to/private-key.pem)"
|
||||
export FUSION_GITHUB_WEBHOOK_SECRET="your-webhook-secret"
|
||||
```
|
||||
|
||||
**GitHub App Configuration:**
|
||||
|
||||
@@ -230,7 +230,7 @@ function compileBinary(outFile: string, target: string, isCrossCompile: boolean)
|
||||
...process.env,
|
||||
NODE_PATH: join(workspaceRoot, "node_modules"),
|
||||
// Tell the runtime where to find native assets
|
||||
KB_RUNTIME_DIR: join(outDir, "runtime"),
|
||||
FUSION_RUNTIME_DIR: join(outDir, "runtime"),
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -39,9 +39,9 @@ function findStagedNativeDir(): string | null {
|
||||
return nextToBinary;
|
||||
}
|
||||
|
||||
// Check KB_RUNTIME_DIR env var
|
||||
if (process.env.KB_RUNTIME_DIR) {
|
||||
const envPath = join(process.env.KB_RUNTIME_DIR, prebuildName);
|
||||
// Check FUSION_RUNTIME_DIR env var
|
||||
if (process.env.FUSION_RUNTIME_DIR) {
|
||||
const envPath = join(process.env.FUSION_RUNTIME_DIR, prebuildName);
|
||||
if (existsSync(join(envPath, "pty.node"))) {
|
||||
return envPath;
|
||||
}
|
||||
@@ -99,7 +99,7 @@ export function setupNativeResolution(): { success: boolean; nativeDir: string |
|
||||
}
|
||||
|
||||
// Store reference for other code to use
|
||||
process.env.KB_NATIVE_ASSETS_PATH = nativeDir;
|
||||
process.env.FUSION_NATIVE_ASSETS_PATH = nativeDir;
|
||||
|
||||
// Create the fake bunfs structure
|
||||
const tmpRoot = join(tmpdir(), `kb-bunfs-${process.pid}`);
|
||||
@@ -123,7 +123,7 @@ export function setupNativeResolution(): { success: boolean; nativeDir: string |
|
||||
}
|
||||
|
||||
// Store the path for potential use
|
||||
process.env.KB_FAKE_BUNFS_ROOT = tmpRoot;
|
||||
process.env.FUSION_FAKE_BUNFS_ROOT = tmpRoot;
|
||||
|
||||
// Try to create symlink from /$bunfs/root to our temp directory
|
||||
// This allows node-pty's relative require() to find the native module
|
||||
@@ -184,7 +184,7 @@ export function cleanupNativeResolution(): void {
|
||||
*/
|
||||
export function initNativePatch(): { success: boolean; nativeDir: string | null } {
|
||||
if (initialized || !isBunBinary) {
|
||||
return { success: true, nativeDir: process.env.KB_NATIVE_ASSETS_PATH || null };
|
||||
return { success: true, nativeDir: process.env.FUSION_NATIVE_ASSETS_PATH || null };
|
||||
}
|
||||
|
||||
const result = setupNativeResolution();
|
||||
|
||||
@@ -346,10 +346,10 @@ The dashboard server exposes a REST API at `/api`:
|
||||
For real-time PR/issue badge updates, configure a GitHub App instead of relying on polling:
|
||||
|
||||
**Environment Variables:**
|
||||
- `KB_GITHUB_APP_ID` - Your GitHub App ID
|
||||
- `KB_GITHUB_APP_PRIVATE_KEY` - PEM private key content (or use `KB_GITHUB_APP_PRIVATE_KEY_PATH`)
|
||||
- `KB_GITHUB_APP_PRIVATE_KEY_PATH` - Path to PEM private key file (alternative to direct key)
|
||||
- `KB_GITHUB_WEBHOOK_SECRET` - Webhook secret for signature verification
|
||||
- `FUSION_GITHUB_APP_ID` - Your GitHub App ID
|
||||
- `FUSION_GITHUB_APP_PRIVATE_KEY` - PEM private key content (or use `FUSION_GITHUB_APP_PRIVATE_KEY_PATH`)
|
||||
- `FUSION_GITHUB_APP_PRIVATE_KEY_PATH` - Path to PEM private key file (alternative to direct key)
|
||||
- `FUSION_GITHUB_WEBHOOK_SECRET` - Webhook secret for signature verification
|
||||
|
||||
**GitHub App Configuration:**
|
||||
- **Permissions Required:**
|
||||
@@ -361,7 +361,7 @@ For real-time PR/issue badge updates, configure a GitHub App instead of relying
|
||||
|
||||
**How it Works:**
|
||||
1. GitHub sends signed webhook events when PR/issue state changes
|
||||
2. Server verifies `X-Hub-Signature-256` using `KB_GITHUB_WEBHOOK_SECRET`
|
||||
2. Server verifies `X-Hub-Signature-256` using `FUSION_GITHUB_WEBHOOK_SECRET`
|
||||
3. Server fetches canonical badge data using GitHub App installation token
|
||||
4. Matching tasks (by parsed badge URL) are updated via `store.updatePrInfo()` / `store.updateIssueInfo()`
|
||||
5. `task:updated` event triggers `/api/ws` broadcast to subscribed clients
|
||||
@@ -375,10 +375,10 @@ When webhook delivery is unavailable, the 5-minute refresh endpoints (`/api/task
|
||||
When running the dashboard on multiple instances behind a load balancer, badge updates can be shared across instances using Redis pub/sub. This ensures that a PR/issue badge change detected on instance A is delivered to subscribed WebSocket clients on instance B.
|
||||
|
||||
**Configuration:**
|
||||
- `KB_BADGE_PUBSUB_REDIS_URL` - Redis connection URL (e.g., `redis://localhost:6379`)
|
||||
- `KB_BADGE_PUBSUB_CHANNEL` - Pub/sub channel name (default: `kb:badge-updates`)
|
||||
- `FUSION_BADGE_PUBSUB_REDIS_URL` - Redis connection URL (e.g., `redis://localhost:6379`)
|
||||
- `FUSION_BADGE_PUBSUB_CHANNEL` - Pub/sub channel name (default: `fusion:badge-updates`)
|
||||
|
||||
When `KB_BADGE_PUBSUB_REDIS_URL` is not set, the dashboard uses an in-memory adapter for single-instance deployments.
|
||||
When `FUSION_BADGE_PUBSUB_REDIS_URL` is not set, the dashboard uses an in-memory adapter for single-instance deployments.
|
||||
|
||||
**Design Notes:**
|
||||
- Webhook deliveries to any instance are broadcast to all instances via pub/sub
|
||||
|
||||
@@ -98,8 +98,8 @@ describe("createBadgePubSub", () => {
|
||||
|
||||
beforeEach(() => {
|
||||
process.env = { ...originalEnv };
|
||||
delete process.env.KB_BADGE_PUBSUB_REDIS_URL;
|
||||
delete process.env.KB_BADGE_PUBSUB_CHANNEL;
|
||||
delete process.env.FUSION_BADGE_PUBSUB_REDIS_URL;
|
||||
delete process.env.FUSION_BADGE_PUBSUB_CHANNEL;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -111,24 +111,24 @@ describe("createBadgePubSub", () => {
|
||||
expect(pubsub).toBeInstanceOf(InMemoryBadgePubSub);
|
||||
});
|
||||
|
||||
it("returns RedisBadgePubSub when KB_BADGE_PUBSUB_REDIS_URL is set", () => {
|
||||
process.env.KB_BADGE_PUBSUB_REDIS_URL = "redis://localhost:6379";
|
||||
it("returns RedisBadgePubSub when FUSION_BADGE_PUBSUB_REDIS_URL is set", () => {
|
||||
process.env.FUSION_BADGE_PUBSUB_REDIS_URL = "redis://localhost:6379";
|
||||
const pubsub = createBadgePubSub({ sourceId: "server-1" });
|
||||
expect(pubsub).toBeInstanceOf(RedisBadgePubSub);
|
||||
});
|
||||
|
||||
it("uses default channel kb:badge-updates when KB_BADGE_PUBSUB_CHANNEL is unset", () => {
|
||||
process.env.KB_BADGE_PUBSUB_REDIS_URL = "redis://localhost:6379";
|
||||
delete process.env.KB_BADGE_PUBSUB_CHANNEL;
|
||||
it("uses default channel fusion:badge-updates when FUSION_BADGE_PUBSUB_CHANNEL is unset", () => {
|
||||
process.env.FUSION_BADGE_PUBSUB_REDIS_URL = "redis://localhost:6379";
|
||||
delete process.env.FUSION_BADGE_PUBSUB_CHANNEL;
|
||||
|
||||
const pubsub = createBadgePubSub({ sourceId: "server-1" });
|
||||
expect(pubsub).toBeInstanceOf(RedisBadgePubSub);
|
||||
// The channel is internal to the adapter; we verify by creating it without error
|
||||
});
|
||||
|
||||
it("uses custom channel when KB_BADGE_PUBSUB_CHANNEL is set", () => {
|
||||
process.env.KB_BADGE_PUBSUB_REDIS_URL = "redis://localhost:6379";
|
||||
process.env.KB_BADGE_PUBSUB_CHANNEL = "custom-channel";
|
||||
it("uses custom channel when FUSION_BADGE_PUBSUB_CHANNEL is set", () => {
|
||||
process.env.FUSION_BADGE_PUBSUB_REDIS_URL = "redis://localhost:6379";
|
||||
process.env.FUSION_BADGE_PUBSUB_CHANNEL = "custom-channel";
|
||||
|
||||
const pubsub = createBadgePubSub({ sourceId: "server-1" });
|
||||
expect(pubsub).toBeInstanceOf(RedisBadgePubSub);
|
||||
@@ -401,8 +401,8 @@ describe("RedisBadgePubSub (integration)", () => {
|
||||
});
|
||||
|
||||
it("reads configuration from environment variables", () => {
|
||||
process.env.KB_BADGE_PUBSUB_REDIS_URL = "redis://redis.example.com:6380";
|
||||
process.env.KB_BADGE_PUBSUB_CHANNEL = "prod-badges";
|
||||
process.env.FUSION_BADGE_PUBSUB_REDIS_URL = "redis://redis.example.com:6380";
|
||||
process.env.FUSION_BADGE_PUBSUB_CHANNEL = "prod-badges";
|
||||
|
||||
const pubsub = createBadgePubSub({ sourceId: "server-1" });
|
||||
expect(pubsub).toBeInstanceOf(RedisBadgePubSub);
|
||||
|
||||
@@ -20,10 +20,10 @@ describe("GitHub Webhooks Module", () => {
|
||||
beforeEach(() => {
|
||||
vi.resetModules();
|
||||
process.env = { ...originalEnv };
|
||||
delete process.env.KB_GITHUB_APP_ID;
|
||||
delete process.env.KB_GITHUB_APP_PRIVATE_KEY;
|
||||
delete process.env.KB_GITHUB_APP_PRIVATE_KEY_PATH;
|
||||
delete process.env.KB_GITHUB_WEBHOOK_SECRET;
|
||||
delete process.env.FUSION_GITHUB_APP_ID;
|
||||
delete process.env.FUSION_GITHUB_APP_PRIVATE_KEY;
|
||||
delete process.env.FUSION_GITHUB_APP_PRIVATE_KEY_PATH;
|
||||
delete process.env.FUSION_GITHUB_WEBHOOK_SECRET;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -37,14 +37,14 @@ describe("GitHub Webhooks Module", () => {
|
||||
});
|
||||
|
||||
it("returns null when only appId is set", () => {
|
||||
process.env.KB_GITHUB_APP_ID = "12345";
|
||||
process.env.FUSION_GITHUB_APP_ID = "12345";
|
||||
expect(getGitHubAppConfig()).toBeNull();
|
||||
});
|
||||
|
||||
it("returns config when all required vars are set via direct key", () => {
|
||||
process.env.KB_GITHUB_APP_ID = "12345";
|
||||
process.env.KB_GITHUB_APP_PRIVATE_KEY = "-----BEGIN RSA PRIVATE KEY-----\ntest\n-----END RSA PRIVATE KEY-----";
|
||||
process.env.KB_GITHUB_WEBHOOK_SECRET = "webhook-secret";
|
||||
process.env.FUSION_GITHUB_APP_ID = "12345";
|
||||
process.env.FUSION_GITHUB_APP_PRIVATE_KEY = "-----BEGIN RSA PRIVATE KEY-----\ntest\n-----END RSA PRIVATE KEY-----";
|
||||
process.env.FUSION_GITHUB_WEBHOOK_SECRET = "webhook-secret";
|
||||
|
||||
const config = getGitHubAppConfig();
|
||||
expect(config).not.toBeNull();
|
||||
@@ -54,18 +54,18 @@ describe("GitHub Webhooks Module", () => {
|
||||
});
|
||||
|
||||
it("returns null when key file cannot be read", () => {
|
||||
process.env.KB_GITHUB_APP_ID = "12345";
|
||||
process.env.KB_GITHUB_APP_PRIVATE_KEY_PATH = "/nonexistent/path/key.pem";
|
||||
process.env.KB_GITHUB_WEBHOOK_SECRET = "webhook-secret";
|
||||
process.env.FUSION_GITHUB_APP_ID = "12345";
|
||||
process.env.FUSION_GITHUB_APP_PRIVATE_KEY_PATH = "/nonexistent/path/key.pem";
|
||||
process.env.FUSION_GITHUB_WEBHOOK_SECRET = "webhook-secret";
|
||||
|
||||
expect(getGitHubAppConfig()).toBeNull();
|
||||
});
|
||||
|
||||
it("prefers direct key over file path when both are set", () => {
|
||||
process.env.KB_GITHUB_APP_ID = "12345";
|
||||
process.env.KB_GITHUB_APP_PRIVATE_KEY = "direct-key-content";
|
||||
process.env.KB_GITHUB_APP_PRIVATE_KEY_PATH = "/nonexistent/path/key.pem";
|
||||
process.env.KB_GITHUB_WEBHOOK_SECRET = "webhook-secret";
|
||||
process.env.FUSION_GITHUB_APP_ID = "12345";
|
||||
process.env.FUSION_GITHUB_APP_PRIVATE_KEY = "direct-key-content";
|
||||
process.env.FUSION_GITHUB_APP_PRIVATE_KEY_PATH = "/nonexistent/path/key.pem";
|
||||
process.env.FUSION_GITHUB_WEBHOOK_SECRET = "webhook-secret";
|
||||
|
||||
const config = getGitHubAppConfig();
|
||||
expect(config?.privateKey).toBe("direct-key-content");
|
||||
@@ -78,9 +78,9 @@ describe("GitHub Webhooks Module", () => {
|
||||
});
|
||||
|
||||
it("returns true when fully configured", () => {
|
||||
process.env.KB_GITHUB_APP_ID = "12345";
|
||||
process.env.KB_GITHUB_APP_PRIVATE_KEY = "private-key";
|
||||
process.env.KB_GITHUB_WEBHOOK_SECRET = "webhook-secret";
|
||||
process.env.FUSION_GITHUB_APP_ID = "12345";
|
||||
process.env.FUSION_GITHUB_APP_PRIVATE_KEY = "private-key";
|
||||
process.env.FUSION_GITHUB_WEBHOOK_SECRET = "webhook-secret";
|
||||
|
||||
expect(isGitHubAppConfigured()).toBe(true);
|
||||
});
|
||||
|
||||
@@ -103,8 +103,8 @@ export class InMemoryBadgePubSub extends EventEmitter<BadgePubSubEvents> impleme
|
||||
* Uses Redis pub/sub for cross-instance message delivery.
|
||||
*
|
||||
* Environment variables:
|
||||
* - KB_BADGE_PUBSUB_REDIS_URL: Redis connection URL
|
||||
* - KB_BADGE_PUBSUB_CHANNEL: Channel name (default: "kb:badge-updates")
|
||||
* - FUSION_BADGE_PUBSUB_REDIS_URL: Redis connection URL
|
||||
* - FUSION_BADGE_PUBSUB_CHANNEL: Channel name (default: "fusion:badge-updates")
|
||||
*/
|
||||
export class RedisBadgePubSub extends EventEmitter<BadgePubSubEvents> implements BadgePubSub {
|
||||
private subscriber: import("ioredis").Redis | null = null;
|
||||
@@ -280,7 +280,7 @@ export function parseBadgePubSubMessage(
|
||||
/**
|
||||
* Create a BadgePubSub adapter based on environment configuration.
|
||||
*
|
||||
* If KB_BADGE_PUBSUB_REDIS_URL is set, returns a RedisBadgePubSub.
|
||||
* If FUSION_BADGE_PUBSUB_REDIS_URL is set, returns a RedisBadgePubSub.
|
||||
* Otherwise, returns an InMemoryBadgePubSub for local-only operation.
|
||||
*/
|
||||
export function createBadgePubSub(options: { sourceId: string }): BadgePubSub {
|
||||
@@ -298,11 +298,11 @@ export function createBadgePubSub(options: { sourceId: string }): BadgePubSub {
|
||||
}
|
||||
|
||||
function getRedisUrlFromEnv(): string | undefined {
|
||||
return process.env.KB_BADGE_PUBSUB_REDIS_URL;
|
||||
return process.env.FUSION_BADGE_PUBSUB_REDIS_URL;
|
||||
}
|
||||
|
||||
function getChannelFromEnv(): string {
|
||||
return process.env.KB_BADGE_PUBSUB_CHANNEL ?? "kb:badge-updates";
|
||||
return process.env.FUSION_BADGE_PUBSUB_CHANNEL ?? "fusion:badge-updates";
|
||||
}
|
||||
|
||||
export { getRedisUrlFromEnv, getChannelFromEnv };
|
||||
|
||||
@@ -57,19 +57,19 @@ export interface VerificationResult {
|
||||
|
||||
/**
|
||||
* Read GitHub App configuration from environment variables.
|
||||
* Supports KB_GITHUB_APP_PRIVATE_KEY or KB_GITHUB_APP_PRIVATE_KEY_PATH.
|
||||
* Supports FUSION_GITHUB_APP_PRIVATE_KEY or FUSION_GITHUB_APP_PRIVATE_KEY_PATH.
|
||||
*/
|
||||
export function getGitHubAppConfig(): GitHubAppConfig | null {
|
||||
const appId = process.env.KB_GITHUB_APP_ID;
|
||||
const webhookSecret = process.env.KB_GITHUB_WEBHOOK_SECRET;
|
||||
const appId = process.env.FUSION_GITHUB_APP_ID;
|
||||
const webhookSecret = process.env.FUSION_GITHUB_WEBHOOK_SECRET;
|
||||
|
||||
let privateKey: string | undefined;
|
||||
|
||||
if (process.env.KB_GITHUB_APP_PRIVATE_KEY) {
|
||||
privateKey = process.env.KB_GITHUB_APP_PRIVATE_KEY;
|
||||
} else if (process.env.KB_GITHUB_APP_PRIVATE_KEY_PATH) {
|
||||
if (process.env.FUSION_GITHUB_APP_PRIVATE_KEY) {
|
||||
privateKey = process.env.FUSION_GITHUB_APP_PRIVATE_KEY;
|
||||
} else if (process.env.FUSION_GITHUB_APP_PRIVATE_KEY_PATH) {
|
||||
try {
|
||||
privateKey = readFileSync(process.env.KB_GITHUB_APP_PRIVATE_KEY_PATH, "utf-8");
|
||||
privateKey = readFileSync(process.env.FUSION_GITHUB_APP_PRIVATE_KEY_PATH, "utf-8");
|
||||
} catch {
|
||||
// Failed to read key file
|
||||
return null;
|
||||
|
||||
@@ -1049,7 +1049,7 @@ function discardGitChanges(files: string[], cwd?: string): string[] {
|
||||
export function createApiRoutes(store: TaskStore, options?: ServerOptions): Router {
|
||||
const router = Router();
|
||||
|
||||
if (process.env.KB_DEBUG_PLANNING_ROUTES === "1") {
|
||||
if (process.env.FUSION_DEBUG_PLANNING_ROUTES === "1") {
|
||||
const planningRoutes = [
|
||||
"POST /planning/start",
|
||||
"POST /planning/start-streaming",
|
||||
|
||||
@@ -57,13 +57,13 @@ export function createServer(store: TaskStore, options?: ServerOptions): ReturnT
|
||||
|
||||
// Serve built React app
|
||||
// Resolution order:
|
||||
// 1. KB_CLIENT_DIR env override (explicit)
|
||||
// 1. FUSION_CLIENT_DIR env override (explicit)
|
||||
// 2. Next to process.execPath (bun-compiled binary: dist/kb + dist/client/)
|
||||
// 3. __dirname/../dist/client (running from src/ via tsx/ts-node)
|
||||
// 4. __dirname/../client (running from dist/ after tsc)
|
||||
const execDir = dirname(process.execPath);
|
||||
const clientDir = process.env.KB_CLIENT_DIR
|
||||
? process.env.KB_CLIENT_DIR
|
||||
const clientDir = process.env.FUSION_CLIENT_DIR
|
||||
? process.env.FUSION_CLIENT_DIR
|
||||
: existsSync(join(execDir, "client", "index.html"))
|
||||
? join(execDir, "client")
|
||||
: existsSync(join(__dirname, "..", "dist", "client"))
|
||||
@@ -167,7 +167,7 @@ export function createServer(store: TaskStore, options?: ServerOptions): ReturnT
|
||||
app.use("/api", rateLimit(RATE_LIMITS.api));
|
||||
|
||||
// Planning route diagnostics for production/runtime debugging. Disabled by default.
|
||||
if (process.env.KB_DEBUG_PLANNING_ROUTES === "1") {
|
||||
if (process.env.FUSION_DEBUG_PLANNING_ROUTES === "1") {
|
||||
app.use("/api/planning", (req, _res, next) => {
|
||||
console.debug("[planning:request]", {
|
||||
method: req.method,
|
||||
|
||||
@@ -33,9 +33,9 @@ function findStagedNativeDir(): string | null {
|
||||
process.arch === "x64" ? "x64" : "unknown";
|
||||
const prebuildName = `${platform}-${arch}`;
|
||||
|
||||
// Check KB_RUNTIME_DIR env var first
|
||||
if (process.env.KB_RUNTIME_DIR) {
|
||||
const envPath = join(process.env.KB_RUNTIME_DIR, prebuildName);
|
||||
// Check FUSION_RUNTIME_DIR env var first
|
||||
if (process.env.FUSION_RUNTIME_DIR) {
|
||||
const envPath = join(process.env.FUSION_RUNTIME_DIR, prebuildName);
|
||||
if (existsSync(join(envPath, "pty.node"))) {
|
||||
return envPath;
|
||||
}
|
||||
@@ -69,7 +69,7 @@ async function loadPtyModule(): Promise<typeof import("node-pty")> {
|
||||
process.env.NODE_PTY_SPAWN_HELPER_DIR = nativeDir;
|
||||
}
|
||||
// Store reference for debugging
|
||||
process.env.KB_NATIVE_ASSETS_PATH = nativeDir;
|
||||
process.env.FUSION_NATIVE_ASSETS_PATH = nativeDir;
|
||||
|
||||
// Try to pre-load the native module using process.dlopen
|
||||
// This can help when the normal require() path fails
|
||||
@@ -137,7 +137,7 @@ const STRIP_ENV_VARS = [
|
||||
"AUTOMAKER_API_KEY",
|
||||
"NODE_PATH",
|
||||
"GITHUB_TOKEN",
|
||||
"KB_API_KEY",
|
||||
"FUSION_API_KEY",
|
||||
];
|
||||
|
||||
export interface TerminalSession {
|
||||
|
||||
Reference in New Issue
Block a user