Spaces:
Running
Running
Fix: Use Hugging Face persistent /data directory for file storage
Browse files- Updated Dockerfile to create directories in /data (persistent in HF Spaces)
- Modified API routes to use /data in production, fallback to local in dev
- Fixed sessionManager to use persistent storage
- Added MCP server icon and description
- This fixes the 'file not found' error after container restarts
- Dockerfile +4 -3
- app/api/download/route.ts +4 -1
- app/api/files/route.ts +4 -1
- app/api/upload/route.ts +4 -1
- lib/sessionManager.ts +8 -2
- mcp-server.js +2 -0
Dockerfile
CHANGED
|
@@ -38,9 +38,10 @@ COPY --from=builder /app/public ./public
|
|
| 38 |
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
| 39 |
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
| 40 |
|
| 41 |
-
# Create data directory for file uploads
|
| 42 |
-
|
| 43 |
-
RUN
|
|
|
|
| 44 |
|
| 45 |
# Install Python for MCP backend
|
| 46 |
RUN apk add --no-cache python3 py3-pip
|
|
|
|
| 38 |
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
| 39 |
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
| 40 |
|
| 41 |
+
# Create data directory for file uploads (Hugging Face persistent storage)
|
| 42 |
+
# Note: /data is persistent in Hugging Face Spaces
|
| 43 |
+
RUN mkdir -p /data/documents /data/public /data/exams /data/files
|
| 44 |
+
RUN chown -R nextjs:nodejs /data
|
| 45 |
|
| 46 |
# Install Python for MCP backend
|
| 47 |
RUN apk add --no-cache python3 py3-pip
|
app/api/download/route.ts
CHANGED
|
@@ -2,7 +2,10 @@ import { NextRequest, NextResponse } from 'next/server'
|
|
| 2 |
import fs from 'fs'
|
| 3 |
import path from 'path'
|
| 4 |
|
| 5 |
-
|
|
|
|
|
|
|
|
|
|
| 6 |
const DOCS_DIR = path.join(DATA_DIR, 'documents')
|
| 7 |
|
| 8 |
export async function GET(request: NextRequest) {
|
|
|
|
| 2 |
import fs from 'fs'
|
| 3 |
import path from 'path'
|
| 4 |
|
| 5 |
+
// Use /data for Hugging Face persistent storage, fallback to local for development
|
| 6 |
+
const DATA_DIR = process.env.NODE_ENV === 'production' && fs.existsSync('/data')
|
| 7 |
+
? '/data'
|
| 8 |
+
: path.join(process.cwd(), 'data')
|
| 9 |
const DOCS_DIR = path.join(DATA_DIR, 'documents')
|
| 10 |
|
| 11 |
export async function GET(request: NextRequest) {
|
app/api/files/route.ts
CHANGED
|
@@ -2,7 +2,10 @@ import { NextRequest, NextResponse } from 'next/server'
|
|
| 2 |
import fs from 'fs'
|
| 3 |
import path from 'path'
|
| 4 |
|
| 5 |
-
|
|
|
|
|
|
|
|
|
|
| 6 |
const DOCS_DIR = path.join(DATA_DIR, 'documents')
|
| 7 |
|
| 8 |
// Ensure directories exist
|
|
|
|
| 2 |
import fs from 'fs'
|
| 3 |
import path from 'path'
|
| 4 |
|
| 5 |
+
// Use /data for Hugging Face persistent storage, fallback to local for development
|
| 6 |
+
const DATA_DIR = process.env.NODE_ENV === 'production' && fs.existsSync('/data')
|
| 7 |
+
? '/data'
|
| 8 |
+
: path.join(process.cwd(), 'data')
|
| 9 |
const DOCS_DIR = path.join(DATA_DIR, 'documents')
|
| 10 |
|
| 11 |
// Ensure directories exist
|
app/api/upload/route.ts
CHANGED
|
@@ -2,7 +2,10 @@ import { NextRequest, NextResponse } from 'next/server'
|
|
| 2 |
import fs from 'fs'
|
| 3 |
import path from 'path'
|
| 4 |
|
| 5 |
-
|
|
|
|
|
|
|
|
|
|
| 6 |
const DOCS_DIR = path.join(DATA_DIR, 'documents')
|
| 7 |
const MAX_FILE_SIZE = 50 * 1024 * 1024 // 50MB
|
| 8 |
|
|
|
|
| 2 |
import fs from 'fs'
|
| 3 |
import path from 'path'
|
| 4 |
|
| 5 |
+
// Use /data for Hugging Face persistent storage, fallback to local for development
|
| 6 |
+
const DATA_DIR = process.env.NODE_ENV === 'production' && fs.existsSync('/data')
|
| 7 |
+
? '/data'
|
| 8 |
+
: path.join(process.cwd(), 'data')
|
| 9 |
const DOCS_DIR = path.join(DATA_DIR, 'documents')
|
| 10 |
const MAX_FILE_SIZE = 50 * 1024 * 1024 // 50MB
|
| 11 |
|
lib/sessionManager.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
| 1 |
import crypto from 'crypto';
|
| 2 |
import fs from 'fs/promises';
|
|
|
|
| 3 |
import path from 'path';
|
| 4 |
|
| 5 |
export interface Session {
|
|
@@ -17,8 +18,13 @@ export class SessionManager {
|
|
| 17 |
private publicDir: string;
|
| 18 |
|
| 19 |
private constructor() {
|
| 20 |
-
|
| 21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
this.initializeDirectories();
|
| 23 |
}
|
| 24 |
|
|
|
|
| 1 |
import crypto from 'crypto';
|
| 2 |
import fs from 'fs/promises';
|
| 3 |
+
import fsSync from 'fs';
|
| 4 |
import path from 'path';
|
| 5 |
|
| 6 |
export interface Session {
|
|
|
|
| 18 |
private publicDir: string;
|
| 19 |
|
| 20 |
private constructor() {
|
| 21 |
+
// Use /data for Hugging Face persistent storage, fallback to local for development
|
| 22 |
+
const baseDataDir = process.env.NODE_ENV === 'production' && fsSync.existsSync('/data')
|
| 23 |
+
? '/data'
|
| 24 |
+
: path.join(process.cwd(), 'data');
|
| 25 |
+
|
| 26 |
+
this.sessionDir = path.join(baseDataDir, 'files');
|
| 27 |
+
this.publicDir = path.join(baseDataDir, 'public');
|
| 28 |
this.initializeDirectories();
|
| 29 |
}
|
| 30 |
|
mcp-server.js
CHANGED
|
@@ -17,6 +17,8 @@ class ReubenOSMCPServer {
|
|
| 17 |
{
|
| 18 |
name: 'reubenos-file-manager',
|
| 19 |
version: '1.0.0',
|
|
|
|
|
|
|
| 20 |
},
|
| 21 |
{
|
| 22 |
capabilities: {
|
|
|
|
| 17 |
{
|
| 18 |
name: 'reubenos-file-manager',
|
| 19 |
version: '1.0.0',
|
| 20 |
+
description: 'AI-powered desktop environment with file management and document generation',
|
| 21 |
+
icon: '🖥️',
|
| 22 |
},
|
| 23 |
{
|
| 24 |
capabilities: {
|