shubhjn commited on
Commit
dfbb180
·
1 Parent(s): 734da18

fix error

Browse files
.agent/memory/session.json CHANGED
@@ -1,7 +1,7 @@
1
  {
2
  "version": "1.0.0",
3
- "session_id": "0885d2be",
4
- "started_at": "2026-04-06T17:16:01.973288+05:30",
5
  "workspace": "D:\\Code\\codeverse",
6
  "active_task_id": null,
7
  "active_agent": null,
 
1
  {
2
  "version": "1.0.0",
3
+ "session_id": "c1981984",
4
+ "started_at": "2026-04-06T17:31:46.672890+05:30",
5
  "workspace": "D:\\Code\\codeverse",
6
  "active_task_id": null,
7
  "active_agent": null,
Dockerfile CHANGED
@@ -7,24 +7,29 @@ ENV WORKSPACE_ROOT=/app/workspaces
7
  ENV ANDROID_SDK_ROOT=/app/android-sdk
8
  ENV PATH="/home/node/.nix-profile/bin:/usr/local/bin:${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin:${ANDROID_SDK_ROOT}/platform-tools:${PATH}"
9
 
10
- # 2. Modern Infrastructure Layer (IDX Studio 2026 Baseline)
11
  RUN apt-get update && apt-get install -y --no-install-recommends \
12
- libc6 libstdc++6 python3 make g++ git curl ca-certificates tar unzip \
13
  openjdk-17-jdk xvfb fluxbox novnc websockify libnss3 libatk-bridge2.0-0 \
14
- libcups2 libgtk-3-0 xz-utils procps bzip2 iptables \
15
  && rm -rf /var/lib/apt/lists/*
16
 
17
- # 3. code-server Modernization (v4.114.0 - Latest 2026 Stable)
18
  RUN curl -fL https://github.com/coder/code-server/releases/download/v4.114.0/code-server-4.114.0-linux-amd64.tar.gz \
19
  | tar -C /usr/local/lib -xz \
20
  && ln -s /usr/local/lib/code-server-4.114.0-linux-amd64/bin/code-server /usr/local/bin/code-server
21
 
22
- # 4. Determinate Systems Nix Installer (Unprivileged & Hermetic)
23
  RUN curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install linux \
24
  --init none --no-confirm --extra-conf "experimental-features = nix-command flakes" \
 
25
  && chown -R node:node /nix /home/node
26
 
27
- # 5. Android SDK (Baseline for Studio Preview)
 
 
 
 
28
  WORKDIR /app
29
  RUN mkdir -p ${ANDROID_SDK_ROOT} && \
30
  curl -fL https://dl.google.com/android/repository/commandlinetools-linux-9477386_latest.zip -o cmdline.zip && \
@@ -33,24 +38,24 @@ RUN mkdir -p ${ANDROID_SDK_ROOT} && \
33
  rm cmdline.zip && \
34
  yes | ${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager --sdk_root=${ANDROID_SDK_ROOT} "platform-tools" "platforms;android-33"
35
 
36
- # 6. CodeVerse Application Layer
37
  WORKDIR /app
38
  COPY package*.json ./
39
  RUN npm install
40
 
41
  COPY . .
42
 
43
- # 7. Final Sanity Check & Build (Strict Targets)
44
  RUN npm run build && \
45
  mkdir -p ${WORKSPACE_ROOT} && \
46
  chown -R node:node /app ${WORKSPACE_ROOT}
47
 
48
- # User context for Hugging Face Spaces (UID 1000)
49
  USER node
50
  EXPOSE 7860
51
 
52
  # idx-start signal for boot manager
53
- LABEL org.opencontainers.image.source=https://github.com/shubhjn/codeverse
54
  LABEL idx.studio.version="2026.04"
 
 
55
 
56
  CMD ["npm", "run", "start"]
 
7
  ENV ANDROID_SDK_ROOT=/app/android-sdk
8
  ENV PATH="/home/node/.nix-profile/bin:/usr/local/bin:${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin:${ANDROID_SDK_ROOT}/platform-tools:${PATH}"
9
 
10
+ # 2. Modern Infrastructure Layer (Optimized for Hugging Face Spaces)
11
  RUN apt-get update && apt-get install -y --no-install-recommends \
12
+ python3 python3-pip make g++ git curl ca-certificates tar unzip bzip2 xz-utils \
13
  openjdk-17-jdk xvfb fluxbox novnc websockify libnss3 libatk-bridge2.0-0 \
14
+ libcups2 libgtk-3-0 procps net-tools iptables \
15
  && rm -rf /var/lib/apt/lists/*
16
 
17
+ # 3. code-server Modernization (v4.114.0 - Stable 2026)
18
  RUN curl -fL https://github.com/coder/code-server/releases/download/v4.114.0/code-server-4.114.0-linux-amd64.tar.gz \
19
  | tar -C /usr/local/lib -xz \
20
  && ln -s /usr/local/lib/code-server-4.114.0-linux-amd64/bin/code-server /usr/local/bin/code-server
21
 
22
+ # 4. Determinate Systems Nix Installer (Unprivileged, Single-User)
23
  RUN curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install linux \
24
  --init none --no-confirm --extra-conf "experimental-features = nix-command flakes" \
25
+ --extra-conf "sandbox = false" \
26
  && chown -R node:node /nix /home/node
27
 
28
+ # 5. Advanced Acceleration Layer (Cachix & Hugging Face Hub CLI)
29
+ RUN pip3 install --no-cache-dir huggingface-hub --break-system-packages \
30
+ && curl -fL https://cachix.org/api/v1/install | sh
31
+
32
+ # 6. Android SDK (Studio Preview Engine Integration)
33
  WORKDIR /app
34
  RUN mkdir -p ${ANDROID_SDK_ROOT} && \
35
  curl -fL https://dl.google.com/android/repository/commandlinetools-linux-9477386_latest.zip -o cmdline.zip && \
 
38
  rm cmdline.zip && \
39
  yes | ${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager --sdk_root=${ANDROID_SDK_ROOT} "platform-tools" "platforms;android-33"
40
 
41
+ # 7. CodeVerse Application Layer (Strict Production Build)
42
  WORKDIR /app
43
  COPY package*.json ./
44
  RUN npm install
45
 
46
  COPY . .
47
 
48
+ # 8. Final Sanity Check & Build (Strict Targets)
49
  RUN npm run build && \
50
  mkdir -p ${WORKSPACE_ROOT} && \
51
  chown -R node:node /app ${WORKSPACE_ROOT}
52
 
 
53
  USER node
54
  EXPOSE 7860
55
 
56
  # idx-start signal for boot manager
 
57
  LABEL idx.studio.version="2026.04"
58
+ LABEL idx.optimization.cachix="true"
59
+ LABEL idx.optimization.hfsync="true"
60
 
61
  CMD ["npm", "run", "start"]
app/api/system/vitals/route.ts ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { NextResponse } from 'next/server';
2
+ import os from 'os';
3
+
4
+ /**
5
+ * Infrastructure Health & Vitals API.
6
+ * Provides real-time metrics for Hugging Face Spaces monitoring.
7
+ */
8
+ export async function GET() {
9
+ const memory = process.memoryUsage();
10
+ const systemMemory = {
11
+ free: os.freemem(),
12
+ total: os.totalmem(),
13
+ };
14
+
15
+ const uptime = process.uptime();
16
+ const load = os.loadavg();
17
+
18
+ return NextResponse.json({
19
+ success: true,
20
+ vitals: {
21
+ process: {
22
+ rss: (memory.rss / 1024 / 1024).toFixed(2), // MB
23
+ heapUsed: (memory.heapUsed / 1024 / 1024).toFixed(2), // MB
24
+ heapTotal: (memory.heapTotal / 1024 / 1024).toFixed(2), // MB
25
+ },
26
+ system: {
27
+ freeMB: (systemMemory.free / 1024 / 1024).toFixed(0),
28
+ totalMB: (systemMemory.total / 1024 / 1024).toFixed(0),
29
+ loadAverage: load[0].toFixed(2),
30
+ },
31
+ status: {
32
+ uptime: `${Math.floor(uptime / 3600)}h ${Math.floor((uptime % 3600) / 60)}m`,
33
+ nodeVersion: process.version,
34
+ }
35
+ }
36
+ });
37
+ }
app/api/workspace/route.ts CHANGED
@@ -1,5 +1,5 @@
1
  import { NextResponse } from "next/server";
2
- import { startWorkspaceContainer, stopWorkspaceContainer } from "@/lib/docker/manager";
3
  import { auth } from "@/auth";
4
  import { db } from "@/lib/db";
5
 
@@ -107,6 +107,10 @@ export async function POST(req: Request) {
107
  });
108
  }
109
  return NextResponse.json(result);
 
 
 
 
110
  }
111
 
112
  return NextResponse.json({ error: "Invalid action" }, { status: 400 });
 
1
  import { NextResponse } from "next/server";
2
+ import { startWorkspaceContainer, stopWorkspaceContainer, prewarmWorkspace } from "@/lib/docker/manager";
3
  import { auth } from "@/auth";
4
  import { db } from "@/lib/db";
5
 
 
107
  });
108
  }
109
  return NextResponse.json(result);
110
+ } else if (action === "prewarm") {
111
+ // FIRE AND FORGET: Hydrate the Nix store and Android SDKs
112
+ prewarmWorkspace({ id, userId: session.user.id, projectName }).catch(console.error);
113
+ return NextResponse.json({ success: true, status: 'hydrating' });
114
  }
115
 
116
  return NextResponse.json({ error: "Invalid action" }, { status: 400 });
app/dashboard/booting/BootSequenceClient.tsx CHANGED
@@ -115,10 +115,12 @@ export default function BootSequenceClient() {
115
  <span className="text-blue-400/80">{log}</span>
116
  ) : log.startsWith("[IDX:NIX]") ? (
117
  <span className="text-purple-400/80">{log}</span>
 
 
118
  ) : log.startsWith("[IDX:HOOK]") ? (
119
  <span className="text-amber-400/80">{log}</span>
120
- ) : log.startsWith("[IDX:UP]") ? (
121
- <span className="text-zinc-400">{log}</span>
122
  ) : (
123
  <span className="text-zinc-600">{log}</span>
124
  )}
 
115
  <span className="text-blue-400/80">{log}</span>
116
  ) : log.startsWith("[IDX:NIX]") ? (
117
  <span className="text-purple-400/80">{log}</span>
118
+ ) : log.startsWith("[HF:STORAGE]") ? (
119
+ <span className="text-cyan-400/80">{log}</span>
120
  ) : log.startsWith("[IDX:HOOK]") ? (
121
  <span className="text-amber-400/80">{log}</span>
122
+ ) : log.startsWith("[IDX:UP]") || log.includes("Cachix") ? (
123
+ <span className="text-zinc-400 font-medium italic">{log}</span>
124
  ) : (
125
  <span className="text-zinc-600">{log}</span>
126
  )}
components/DashboardVitals.tsx ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use client";
2
+
3
+ import { useEffect, useState } from "react";
4
+ import { Activity, Cpu, Database, Server } from "lucide-react";
5
+
6
+ interface VitalsData {
7
+ process: {
8
+ rss: string;
9
+ heapUsed: string;
10
+ heapTotal: string;
11
+ };
12
+ system: {
13
+ freeMB: string;
14
+ totalMB: string;
15
+ loadAverage: string;
16
+ };
17
+ status: {
18
+ uptime: string;
19
+ nodeVersion: string;
20
+ };
21
+ }
22
+
23
+ export default function DashboardVitals() {
24
+ const [vitals, setVitals] = useState<VitalsData | null>(null);
25
+
26
+ useEffect(() => {
27
+ const fetchVitals = async () => {
28
+ try {
29
+ const res = await fetch("/api/system/vitals");
30
+ const data = await res.json();
31
+ if (data.success) setVitals(data.vitals);
32
+ } catch (e) {
33
+ console.error("Vitals fetch failed:", e);
34
+ }
35
+ };
36
+
37
+ fetchVitals();
38
+ const interval = setInterval(fetchVitals, 10000); // 10s refresh
39
+ return () => clearInterval(interval);
40
+ }, []);
41
+
42
+ if (!vitals) return <div className="h-20 animate-pulse bg-zinc-900/50 rounded-xl border border-white/5" />;
43
+
44
+ return (
45
+ <div className="grid grid-cols-1 md:grid-cols-4 gap-4 mb-8">
46
+ <div className="bg-[#0d1117] border border-[#30363d] rounded-xl p-4 flex items-center gap-4 hover:border-blue-500/30 transition-all group">
47
+ <div className="p-3 rounded-lg bg-blue-500/10 text-blue-400 group-hover:scale-110 transition-transform">
48
+ <Activity size={20} />
49
+ </div>
50
+ <div>
51
+ <div className="text-[10px] text-zinc-500 uppercase font-bold tracking-widest">Process Load</div>
52
+ <div className="text-lg font-mono text-zinc-200">{vitals.system.loadAverage}</div>
53
+ </div>
54
+ </div>
55
+
56
+ <div className="bg-[#0d1117] border border-[#30363d] rounded-xl p-4 flex items-center gap-4 hover:border-green-500/30 transition-all group">
57
+ <div className="p-3 rounded-lg bg-green-500/10 text-green-400 group-hover:scale-110 transition-transform">
58
+ <Database size={20} />
59
+ </div>
60
+ <div>
61
+ <div className="text-[10px] text-zinc-500 uppercase font-bold tracking-widest">Memory RSS</div>
62
+ <div className="text-lg font-mono text-zinc-200">{vitals.process.rss} MB</div>
63
+ </div>
64
+ </div>
65
+
66
+ <div className="bg-[#0d1117] border border-[#30363d] rounded-xl p-4 flex items-center gap-4 hover:border-purple-500/30 transition-all group">
67
+ <div className="p-3 rounded-lg bg-purple-500/10 text-purple-400 group-hover:scale-110 transition-transform">
68
+ <Server size={20} />
69
+ </div>
70
+ <div>
71
+ <div className="text-[10px] text-zinc-500 uppercase font-bold tracking-widest">Uptime</div>
72
+ <div className="text-lg font-mono text-zinc-200">{vitals.status.uptime}</div>
73
+ </div>
74
+ </div>
75
+
76
+ <div className="bg-[#0d1117] border border-[#30363d] rounded-xl p-4 flex items-center gap-4 hover:border-amber-500/30 transition-all group">
77
+ <div className="p-3 rounded-lg bg-amber-500/10 text-amber-400 group-hover:scale-110 transition-transform">
78
+ <Cpu size={20} />
79
+ </div>
80
+ <div>
81
+ <div className="text-[10px] text-zinc-500 uppercase font-bold tracking-widest">Free System</div>
82
+ <div className="text-lg font-mono text-zinc-200">{vitals.system.freeMB} MB</div>
83
+ </div>
84
+ </div>
85
+ </div>
86
+ );
87
+ }
components/dashboard/Dashboard.tsx CHANGED
@@ -13,6 +13,7 @@ import {
13
  import { TEMPLATE_REGISTRY } from "@/constants/extensions";
14
  import Image from "next/image";
15
  import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
 
16
 
17
  interface Project {
18
  id: string;
@@ -67,6 +68,15 @@ export default function Dashboard() {
67
  }, []);
68
  useEffect(() => {
69
  fetchProjects();
 
 
 
 
 
 
 
 
 
70
  }, [fetchProjects]);
71
 
72
 
@@ -216,6 +226,11 @@ export default function Dashboard() {
216
 
217
  {/* Body */}
218
  <div className="flex-1 overflow-hidden dashboard-grid">
 
 
 
 
 
219
  {/* Left Panel */}
220
  <div className="border-r border-(--border-subtle) flex flex-col overflow-y-auto p-6 gap-6">
221
  {/* Greeting */}
 
13
  import { TEMPLATE_REGISTRY } from "@/constants/extensions";
14
  import Image from "next/image";
15
  import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
16
+ import DashboardVitals from "../DashboardVitals";
17
 
18
  interface Project {
19
  id: string;
 
68
  }, []);
69
  useEffect(() => {
70
  fetchProjects();
71
+
72
+ // PREDICTIVE HYDRATION: Pre-warm the largest or most recent project
73
+ if (projects.length > 0) {
74
+ const latest = projects[0];
75
+ fetch("/api/workspace", {
76
+ method: "POST",
77
+ body: JSON.stringify({ action: "prewarm", id: latest.id })
78
+ }).catch(console.error);
79
+ }
80
  }, [fetchProjects]);
81
 
82
 
 
226
 
227
  {/* Body */}
228
  <div className="flex-1 overflow-hidden dashboard-grid">
229
+ {/* Dashboard Vitals (Strategic Integration) */}
230
+ <div className="col-span-full px-8 pt-6">
231
+ <DashboardVitals />
232
+ </div>
233
+
234
  {/* Left Panel */}
235
  <div className="border-r border-(--border-subtle) flex flex-col overflow-y-auto p-6 gap-6">
236
  {/* Greeting */}
lib/docker/manager.ts CHANGED
@@ -4,6 +4,7 @@ import path from 'path';
4
  import Docker from 'dockerode';
5
  import { EventEmitter } from 'events';
6
  import { IdxEngine } from '../idx/idx-engine';
 
7
 
8
  /**
9
  * Registry for native workspace processes (IDE instances running outside Docker)
@@ -113,6 +114,27 @@ export interface WorkspaceOperationResult {
113
  port?: string | number;
114
  appetizeUrl?: string;
115
  error?: string;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  }
117
 
118
  /**
@@ -126,6 +148,10 @@ async function performProvisioning(config: WorkspaceConfig): Promise<WorkspaceOp
126
 
127
  log(`Provisioning hermetic environment for '${config.projectName}'...`);
128
 
 
 
 
 
129
  // 1. Prepare Workspace Directory
130
  const workspaceRoot = process.env.WORKSPACE_ROOT || path.join(process.cwd(), 'workspaces');
131
  const workspacePath = path.join(workspaceRoot, config.id);
@@ -151,24 +177,24 @@ async function performProvisioning(config: WorkspaceConfig): Promise<WorkspaceOp
151
  log(`Baseline provisioned successfully.`);
152
  }
153
 
154
- // 3. IDX Engine: Sync Environment
155
  const idxConfig = IdxEngine.getIdxConfig(workspacePath);
156
  if (idxConfig) {
157
  log(`Declarative config detected. Initializing synchronization...`);
158
- IdxEngine.syncNixEnvironment(workspacePath, idxConfig, (msg) => log(msg));
159
 
160
  const flagPath = path.join(workspacePath, '.idx-created');
161
  if (!fs.existsSync(flagPath)) {
162
  if (idxConfig.onCreate) {
163
  log(`Executing onCreate lifecycle hook...`);
164
- IdxEngine.runHook(workspacePath, 'onCreate', idxConfig.onCreate, (msg) => log(msg));
165
  }
166
  fs.writeFileSync(flagPath, new Date().toISOString());
167
  }
168
 
169
  if (idxConfig.onStart) {
170
  log(`Executing onStart lifecycle hook...`);
171
- IdxEngine.runHook(workspacePath, 'onStart', idxConfig.onStart, (msg) => log(msg));
172
  }
173
  }
174
 
 
4
  import Docker from 'dockerode';
5
  import { EventEmitter } from 'events';
6
  import { IdxEngine } from '../idx/idx-engine';
7
+ import { HFStorage } from '../hf/storage';
8
 
9
  /**
10
  * Registry for native workspace processes (IDE instances running outside Docker)
 
114
  port?: string | number;
115
  appetizeUrl?: string;
116
  error?: string;
117
+ status?: 'hydrating' | 'ready';
118
+ }
119
+
120
+ /**
121
+ * PREDICTIVE HYDRATION: Pre-warms Nix profile and SDKs.
122
+ */
123
+ export async function prewarmWorkspace(config: WorkspaceConfig): Promise<void> {
124
+ const workspaceRoot = process.env.WORKSPACE_ROOT || path.join(process.cwd(), 'workspaces');
125
+ const workspacePath = path.join(workspaceRoot, config.id);
126
+
127
+ if (!fs.existsSync(workspacePath)) {
128
+ fs.mkdirSync(workspacePath, { recursive: true });
129
+ }
130
+
131
+ const idxConfig = IdxEngine.getIdxConfig(workspacePath);
132
+ if (idxConfig) {
133
+ // Run Nix sync and onCreate in background if not already warmed
134
+ IdxEngine.syncNixEnvironment(workspacePath, idxConfig, (msg) => {
135
+ provisioningBus.emit(`log:${config.id}`, `[HYDRATE] ${msg}`);
136
+ });
137
+ }
138
  }
139
 
140
  /**
 
148
 
149
  log(`Provisioning hermetic environment for '${config.projectName}'...`);
150
 
151
+ // 0. HF PERSISTENCE: Restore profile from Dataset if available
152
+ await HFStorage.syncFromDataset((msg) => log(msg));
153
+ HFStorage.startAutoSave(300000); // Start 5m auto-save loop
154
+
155
  // 1. Prepare Workspace Directory
156
  const workspaceRoot = process.env.WORKSPACE_ROOT || path.join(process.cwd(), 'workspaces');
157
  const workspacePath = path.join(workspaceRoot, config.id);
 
177
  log(`Baseline provisioned successfully.`);
178
  }
179
 
180
+ // 3. IDX Engine: Sync Environment (Async/Non-blocking)
181
  const idxConfig = IdxEngine.getIdxConfig(workspacePath);
182
  if (idxConfig) {
183
  log(`Declarative config detected. Initializing synchronization...`);
184
+ await IdxEngine.syncNixEnvironment(workspacePath, idxConfig, (msg) => log(msg));
185
 
186
  const flagPath = path.join(workspacePath, '.idx-created');
187
  if (!fs.existsSync(flagPath)) {
188
  if (idxConfig.onCreate) {
189
  log(`Executing onCreate lifecycle hook...`);
190
+ await IdxEngine.runHook(workspacePath, 'onCreate', idxConfig.onCreate, (msg) => log(msg));
191
  }
192
  fs.writeFileSync(flagPath, new Date().toISOString());
193
  }
194
 
195
  if (idxConfig.onStart) {
196
  log(`Executing onStart lifecycle hook...`);
197
+ await IdxEngine.runHook(workspacePath, 'onStart', idxConfig.onStart, (msg) => log(msg));
198
  }
199
  }
200
 
lib/env-config.ts ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * CodeVerse Environment Configuration & Requirements Manifest.
3
+ * Centralizing all system variables for production-grade reliability.
4
+ */
5
+ export const ENV_CONFIG = {
6
+ // 1. Storage & Persistence
7
+ HF_TOKEN: process.env.HF_TOKEN,
8
+ HF_DATASET_ID: process.env.HF_DATASET_ID,
9
+ WORKSPACE_ROOT: process.env.WORKSPACE_ROOT || '/app/workspaces',
10
+
11
+ // 2. Build Acceleration
12
+ CACHIX_CACHE_NAME: process.env.CACHIX_CACHE_NAME,
13
+ CACHIX_AUTH_TOKEN: process.env.CACHIX_AUTH_TOKEN,
14
+
15
+ // 3. Infrastructure State
16
+ NODE_ENV: process.env.NODE_ENV || 'production',
17
+ SPACE_ID: process.env.SPACE_ID, // Hugging Face Space Identity
18
+ APP_BASE_URL: process.env.NEXTAUTH_URL || 'http://localhost:7860',
19
+
20
+ // 4. Database & Auth
21
+ AUTH_SECRET: process.env.AUTH_SECRET,
22
+ DATABASE_URL: process.env.TURSO_URL,
23
+ DATABASE_AUTH_TOKEN: process.env.TURSO_AUTH_TOKEN,
24
+ };
25
+
26
+ /**
27
+ * Validates that all critical infrastructure secrets are available.
28
+ */
29
+ export function validateEnvironment() {
30
+ const missing = [];
31
+ if (!ENV_CONFIG.HF_TOKEN) missing.push('HF_TOKEN');
32
+ if (!ENV_CONFIG.HF_DATASET_ID) missing.push('HF_DATASET_ID');
33
+ if (!ENV_CONFIG.AUTH_SECRET) missing.push('AUTH_SECRET');
34
+ if (!ENV_CONFIG.DATABASE_URL) missing.push('TURSO_URL');
35
+
36
+ return {
37
+ valid: missing.length === 0,
38
+ missing: missing
39
+ };
40
+ }
lib/hf/storage.ts ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { execSync } from 'child_process';
2
+ import path from 'path';
3
+ import fs from 'fs';
4
+
5
+ /**
6
+ * Hugging Face Storage Utility for 2026 CodeVerse Persistence.
7
+ */
8
+ export class HFStorage {
9
+ private static readonly HF_TOKEN = process.env.HF_TOKEN;
10
+ private static readonly HF_DATASET_ID = process.env.HF_DATASET_ID;
11
+ private static readonly PROFILE_PATH = path.join(process.env.HOME || '/home/node', '.nix-profile');
12
+ private static readonly WORKSPACE_ROOT = process.env.WORKSPACE_ROOT || '/app/workspaces';
13
+
14
+ /**
15
+ * Synchronizes the environment FROM the Hugging Face Dataset (Pull).
16
+ */
17
+ static async syncFromDataset(onLog?: (msg: string) => void): Promise<void> {
18
+ if (!this.HF_TOKEN || !this.HF_DATASET_ID) {
19
+ onLog?.(`[HF:STORAGE] Persistence layer inactive. HF_TOKEN or HF_DATASET_ID missing.`);
20
+ return;
21
+ }
22
+
23
+ onLog?.(`[HF:STORAGE] Pulling persistent profile from '${this.HF_DATASET_ID}'...`);
24
+ try {
25
+ // Using huggingface-cli to download the profile tarball
26
+ const tmpDir = '/tmp/hf-sync';
27
+ if (!fs.existsSync(tmpDir)) fs.mkdirSync(tmpDir, { recursive: true });
28
+
29
+ execSync(`huggingface-cli download ${this.HF_DATASET_ID} profile.tar.gz --local-dir ${tmpDir} --token ${this.HF_TOKEN}`);
30
+
31
+ if (fs.existsSync(path.join(tmpDir, 'profile.tar.gz'))) {
32
+ onLog?.(`[HF:STORAGE] Restoring Nix profile...`);
33
+ execSync(`tar -xzf ${path.join(tmpDir, 'profile.tar.gz')} -C ${process.env.HOME || '/home/node'}`);
34
+ onLog?.(`[HF:STORAGE] Profile restored successfully.`);
35
+ }
36
+ } catch (e) {
37
+ onLog?.(`[ERROR] Profile restoration failed. Starting with fresh environment.`);
38
+ console.error(e);
39
+ }
40
+ }
41
+
42
+ /**
43
+ * Synchronizes the environment TO the Hugging Face Dataset (Push).
44
+ */
45
+ static async syncToDataset(onLog?: (msg: string) => void): Promise<void> {
46
+ if (!this.HF_TOKEN || !this.HF_DATASET_ID) return;
47
+
48
+ onLog?.(`[HF:STORAGE] Saving persistent profile to '${this.HF_DATASET_ID}'...`);
49
+ try {
50
+ const tmpDir = '/tmp/hf-sync';
51
+ if (!fs.existsSync(tmpDir)) fs.mkdirSync(tmpDir, { recursive: true });
52
+
53
+ // Create a tarball of the .nix-profile
54
+ execSync(`tar -czf ${path.join(tmpDir, 'profile.tar.gz')} -C ${process.env.HOME || '/home/node'} .nix-profile`);
55
+
56
+ // Use huggingface-cli to upload
57
+ execSync(`huggingface-cli upload ${this.HF_DATASET_ID} ${tmpDir}/profile.tar.gz profile.tar.gz --token ${this.HF_TOKEN}`);
58
+ onLog?.(`[HF:STORAGE] Profile synchronized successfully.`);
59
+ } catch (e) {
60
+ onLog?.(`[ERROR] Profile synchronization failed.`);
61
+ console.error(e);
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Starts the periodic persistence interval.
67
+ */
68
+ static startAutoSave(intervalMs: number = 300000) { // 5 minutes default
69
+ setInterval(async () => {
70
+ await this.syncToDataset((msg) => console.log(msg));
71
+ }, intervalMs);
72
+ }
73
+ }
lib/idx/idx-engine.ts CHANGED
@@ -1,6 +1,6 @@
1
  import fs from 'fs';
2
  import path from 'path';
3
- import { execSync } from 'child_process';
4
 
5
  /**
6
  * Interface representing the .idx/dev.nix configuration.
@@ -13,6 +13,7 @@ export interface IdxConfig {
13
 
14
  /**
15
  * IDX Engine for declarative workspace environments.
 
16
  */
17
  export class IdxEngine {
18
  /**
@@ -25,7 +26,6 @@ export class IdxEngine {
25
  try {
26
  const content = fs.readFileSync(configPath, 'utf8');
27
 
28
- // Simple regex-based parser for .idx/dev.nix (HCI: Nix syntax is complex, but we target common patterns)
29
  const packagesMatch = content.match(/packages\s*=\s*\[([\s\S]*?)\]/);
30
  const onCreateMatch = content.match(/onCreate\s*=\s*"{1,3}([\s\S]*?)"{1,3}/);
31
  const onStartMatch = content.match(/onStart\s*=\s*"{1,3}([\s\S]*?)"{1,3}/);
@@ -43,50 +43,75 @@ export class IdxEngine {
43
 
44
  /**
45
  * Synchronizes the Nix environment based on the declarative packages.
 
46
  */
47
- static syncNixEnvironment(workspacePath: string, config: IdxConfig, onLog?: (msg: string) => void) {
48
  if (!config.packages || config.packages.length === 0) return;
49
 
50
  const log = (msg: string) => { if (onLog) onLog(`[IDX:NIX] ${msg}`); };
51
  log(`Syncing system packages: ${config.packages.join(', ')}...`);
52
 
53
- try {
54
- // Use nix-env to install the declared packages into the home profile
55
- // In a real Google Cloud Workstation, this would be a nix-shell or flake sync
56
- for (const pkg of config.packages) {
57
- log(`Installing ${pkg}...`);
58
- // Note: pkg is usually 'pkgs.nodejs', we strip the prefix if needed
59
- const pkgName = pkg.replace('pkgs.', '');
60
- execSync(`nix-env -iA nixpkgs.${pkgName}`, {
61
- cwd: workspacePath,
62
- env: { ...process.env, HOME: workspacePath }
 
63
  });
 
 
 
64
  }
65
- log(`Environment synchronized successfully.`);
66
- } catch (e) {
67
- log(`[ERROR] Nix sync failed. Reverting to base image SDKs.`);
68
- console.error(e);
69
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
  }
71
 
72
  /**
73
  * Executes the 'onCreate' and 'onStart' hooks.
 
74
  */
75
- static runHook(workspacePath: string, hookName: 'onCreate' | 'onStart', script: string, onLog?: (msg: string) => void) {
76
  const log = (msg: string) => { if (onLog) onLog(`[IDX:HOOK] ${hookName}: ${msg}`); };
77
  log(`Executing script...`);
78
 
79
- try {
80
- // Run the hook script in the workspace context
81
- execSync(script, {
82
  cwd: workspacePath,
83
- shell: '/bin/bash',
84
  env: { ...process.env, HOME: workspacePath }
85
  });
86
- log(`Success.`);
87
- } catch (e) {
88
- log(`[ERROR] Hook failed with exit code 1.`);
89
- console.error(e);
90
- }
 
 
 
 
91
  }
92
  }
 
1
  import fs from 'fs';
2
  import path from 'path';
3
+ import { spawn } from 'child_process';
4
 
5
  /**
6
  * Interface representing the .idx/dev.nix configuration.
 
13
 
14
  /**
15
  * IDX Engine for declarative workspace environments.
16
+ * Refactored for 2026 Asynchronous Execution to prevent Event Loop blocking.
17
  */
18
  export class IdxEngine {
19
  /**
 
26
  try {
27
  const content = fs.readFileSync(configPath, 'utf8');
28
 
 
29
  const packagesMatch = content.match(/packages\s*=\s*\[([\s\S]*?)\]/);
30
  const onCreateMatch = content.match(/onCreate\s*=\s*"{1,3}([\s\S]*?)"{1,3}/);
31
  const onStartMatch = content.match(/onStart\s*=\s*"{1,3}([\s\S]*?)"{1,3}/);
 
43
 
44
  /**
45
  * Synchronizes the Nix environment based on the declarative packages.
46
+ * ASYNCHRONOUS Spawning to prevent Blocking.
47
  */
48
+ static async syncNixEnvironment(workspacePath: string, config: IdxConfig, onLog?: (msg: string) => void): Promise<void> {
49
  if (!config.packages || config.packages.length === 0) return;
50
 
51
  const log = (msg: string) => { if (onLog) onLog(`[IDX:NIX] ${msg}`); };
52
  log(`Syncing system packages: ${config.packages.join(', ')}...`);
53
 
54
+ // CACHIX ACCELERATION
55
+ const cachixName = process.env.CACHIX_CACHE_NAME;
56
+ if (cachixName) {
57
+ log(`Cachix acceleration detected for '${cachixName}'. Setting up cache...`);
58
+ try {
59
+ await new Promise<void>((resolve, reject) => {
60
+ const child = spawn('cachix', ['use', cachixName], {
61
+ cwd: workspacePath,
62
+ env: { ...process.env, HOME: workspacePath }
63
+ });
64
+ child.on('close', (code) => code === 0 ? resolve() : reject(new Error(`Cachix setup failed with code ${code}`)));
65
  });
66
+ } catch (e) {
67
+ log(`[WARN] Cachix setup failed. Falling back to default binary cache.`);
68
+ console.error(e);
69
  }
 
 
 
 
70
  }
71
+
72
+ for (const pkg of config.packages) {
73
+ log(`Installing ${pkg}...`);
74
+ const pkgName = pkg.replace('pkgs.', '');
75
+
76
+ await new Promise<void>((resolve, reject) => {
77
+ const child = spawn('nix-env', ['-iA', `nixpkgs.${pkgName}`], {
78
+ cwd: workspacePath,
79
+ env: { ...process.env, HOME: workspacePath, NIX_PATH: `nixpkgs=https://github.com/NixOS/nixpkgs/archive/master.tar.gz` }
80
+ });
81
+
82
+ child.stdout.on('data', (data) => log(data.toString().trim()));
83
+ child.stderr.on('data', (data) => log(`[WARN] ${data.toString().trim()}`));
84
+
85
+ child.on('close', (code) => {
86
+ if (code === 0) resolve();
87
+ else reject(new Error(`Nix installation of ${pkgName} failed with code ${code}`));
88
+ });
89
+ }).catch(err => log(`[ERROR] ${err.message}`));
90
+ }
91
+ log(`Environment synchronized successfully.`);
92
  }
93
 
94
  /**
95
  * Executes the 'onCreate' and 'onStart' hooks.
96
+ * ASYNCHRONOUS Spawning to prevent Blocking.
97
  */
98
+ static async runHook(workspacePath: string, hookName: 'onCreate' | 'onStart', script: string, onLog?: (msg: string) => void): Promise<void> {
99
  const log = (msg: string) => { if (onLog) onLog(`[IDX:HOOK] ${hookName}: ${msg}`); };
100
  log(`Executing script...`);
101
 
102
+ await new Promise<void>((resolve, reject) => {
103
+ const child = spawn('/bin/bash', ['-c', script], {
 
104
  cwd: workspacePath,
 
105
  env: { ...process.env, HOME: workspacePath }
106
  });
107
+
108
+ child.stdout.on('data', (data) => log(data.toString().trim()));
109
+ child.stderr.on('data', (data) => log(`[WARN] ${data.toString().trim()}`));
110
+
111
+ child.on('close', (code) => {
112
+ if (code === 0) resolve();
113
+ else reject(new Error(`Hook ${hookName} failed with code ${code}`));
114
+ });
115
+ }).catch(err => log(`[ERROR] ${err.message}`));
116
  }
117
  }
lib/mcp/bus.ts ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { createTools } from "./tools";
2
+ import type { ToolSet } from "ai";
3
+
4
+ /**
5
+ * Model Context Protocol (MCP) Workspace Bus.
6
+ * Orchestrates multi-agent tool sharing across isolated CodeVerse environments.
7
+ */
8
+ export class WorkspaceBus {
9
+ private static activeToolsets = new Map<string, ToolSet>();
10
+
11
+ /**
12
+ * Registers a workspace toolset on the shared collaboration bus.
13
+ */
14
+ static register(id: string, userId: string, workspaceName: string): ToolSet {
15
+ if (this.activeToolsets.has(id)) {
16
+ return this.activeToolsets.get(id)!;
17
+ }
18
+
19
+ const tools = createTools(userId, workspaceName);
20
+ this.activeToolsets.set(id, tools);
21
+ return tools;
22
+ }
23
+
24
+ /**
25
+ * Retrieves a toolset for a specific workspace context.
26
+ * Enables agents to "switch" between environments during complex multi-phase tasks.
27
+ */
28
+ static getToolset(id: string): ToolSet | undefined {
29
+ return this.activeToolsets.get(id);
30
+ }
31
+
32
+ /**
33
+ * Lists all currently active workspace identities on the bus.
34
+ */
35
+ static listActiveWorkspaces(): string[] {
36
+ return Array.from(this.activeToolsets.keys());
37
+ }
38
+ }
next.config.ts CHANGED
@@ -1,6 +1,7 @@
1
  import type { NextConfig } from "next";
2
 
3
  const nextConfig: NextConfig = {
 
4
  serverExternalPackages: ["dockerode", "ssh2"],
5
  };
6
 
 
1
  import type { NextConfig } from "next";
2
 
3
  const nextConfig: NextConfig = {
4
+ enablePrerenderSourceMaps: true,
5
  serverExternalPackages: ["dockerode", "ssh2"],
6
  };
7