diff --git a/apps/harness/src/lib/agents.ts b/apps/harness/src/lib/agents.ts index 0ebff72..acd95fc 100644 --- a/apps/harness/src/lib/agents.ts +++ b/apps/harness/src/lib/agents.ts @@ -58,7 +58,10 @@ export interface AgentConfig { env?: Record; // additional env vars for the agent process } -const configs: Map = new Map(); +// Shared via globalThis to survive Next.js module re-bundling. +const g = globalThis as unknown as { __harnessAgentConfigs?: Map }; +g.__harnessAgentConfigs ??= new Map(); +const configs = g.__harnessAgentConfigs; export function getAllAgentConfigs(): AgentConfig[] { return Array.from(configs.values()); diff --git a/apps/harness/src/lib/boot.ts b/apps/harness/src/lib/boot.ts index 3736a7e..84f525a 100644 --- a/apps/harness/src/lib/boot.ts +++ b/apps/harness/src/lib/boot.ts @@ -7,7 +7,8 @@ import { upsertCuratedModel, getCuratedModels } from "./model-store"; import { upsertAgentConfig, getAllAgentConfigs, type AgentRuntime } from "./agents"; import { fetchAllModels } from "./model-providers"; -let booted = false; +const gb = globalThis as unknown as { __harnessBooted?: boolean }; + // Well-known models with pricing (used as fallback when API discovery returns // models without pricing info, and to enable cost tracking from the start). @@ -179,8 +180,8 @@ async function discoverModelsAndAgents() { // ─── BOOT ─────────────────────────────────────────────────── export async function boot() { - if (booted) return; - booted = true; + if (gb.__harnessBooted) return; + gb.__harnessBooted = true; // 1. Load credentials from mounted secrets (files take priority) loadClaudeCredentials(); diff --git a/apps/harness/src/lib/credentials.ts b/apps/harness/src/lib/credentials.ts index 6bb7d02..6a071db 100644 --- a/apps/harness/src/lib/credentials.ts +++ b/apps/harness/src/lib/credentials.ts @@ -13,8 +13,10 @@ export interface Credential { baseUrl?: string; // for self-hosted GitLab or custom endpoints } -// In-memory store. Will be replaced with encrypted persistent storage. -const credentials: Map = new Map(); +// In-memory store shared via globalThis to survive Next.js module re-bundling. +const g = globalThis as unknown as { __harnessCredentials?: Map }; +g.__harnessCredentials ??= new Map(); +const credentials = g.__harnessCredentials; export function getAllCredentials(): Credential[] { return Array.from(credentials.values()).map(c => ({ diff --git a/apps/harness/src/lib/model-store.ts b/apps/harness/src/lib/model-store.ts index 80718e4..52ac317 100644 --- a/apps/harness/src/lib/model-store.ts +++ b/apps/harness/src/lib/model-store.ts @@ -32,9 +32,12 @@ export interface ModelUsageSummary { totalDurationMs: number; } -// In-memory stores -const curatedModels: Map = new Map(); -const usageLog: ModelUsageEntry[] = []; +// In-memory stores shared via globalThis to survive Next.js module re-bundling. +const g = globalThis as unknown as { __harnessCuratedModels?: Map; __harnessUsageLog?: ModelUsageEntry[] }; +g.__harnessCuratedModels ??= new Map(); +g.__harnessUsageLog ??= []; +const curatedModels = g.__harnessCuratedModels; +const usageLog = g.__harnessUsageLog; // ─── CURATED MODELS ───────────────────────────────────────── diff --git a/apps/harness/src/lib/store.ts b/apps/harness/src/lib/store.ts index f00903c..e4951ad 100644 --- a/apps/harness/src/lib/store.ts +++ b/apps/harness/src/lib/store.ts @@ -1,8 +1,9 @@ import { Task } from "./types"; -// In-memory task store. Will be replaced with persistent storage (CloudNativePG) -// once the orchestrator loop is wired up. -const tasks: Map = new Map(); +// In-memory task store shared via globalThis to survive Next.js module re-bundling. +const g = globalThis as unknown as { __harnessTasks?: Map }; +g.__harnessTasks ??= new Map(); +const tasks = g.__harnessTasks; export function getAllTasks(): Task[] { return Array.from(tasks.values());