MCPcopy Create free account
hub / github.com/MiniMax-AI/OpenRoom / sessionDataPlugin

Function sessionDataPlugin

apps/webuiapps/vite.config.ts:77–235  ·  view source on GitHub ↗

* Session data plugin — reads/writes files under ~/.openroom/sessions/ * API: /api/session-data?path={charId}/{modId}/chat/history.json * Supports GET, POST, DELETE.

()

Source from the content-addressed store, hash-verified

75 * Supports GET, POST, DELETE.
76 */
77function sessionDataPlugin(): Plugin {
78 return {
79 name: 'session-data',
80 configureServer(server) {
81 server.middlewares.use('/api/session-data', (req, res) => {
82 res.setHeader('Content-Type', 'application/json');
83
84 const url = new URL(req.url || '', 'http://localhost');
85 const relPath = url.searchParams.get('path') || '';
86 const action = url.searchParams.get('action') || '';
87
88 if (!relPath) {
89 res.writeHead(400);
90 res.end(JSON.stringify({ error: 'Missing path parameter' }));
91 return;
92 }
93
94 // Sanitize: only allow alphanumeric, underscore, hyphen, dot, forward slash
95 const safePath = relPath.replace(/[^a-zA-Z0-9_\-./]/g, '_').replace(/\.\./g, '');
96 const filePath = join(SESSIONS_DIR, safePath);
97
98 // Directory listing: ?action=list&path=...
99 if (action === 'list' && req.method === 'GET') {
100 try {
101 if (!fs.existsSync(filePath) || !fs.statSync(filePath).isDirectory()) {
102 res.writeHead(200);
103 res.end(JSON.stringify({ files: [], not_exists: !fs.existsSync(filePath) }));
104 return;
105 }
106 const entries = fs.readdirSync(filePath, { withFileTypes: true });
107 const files = entries.map((e) => ({
108 path: safePath === '' || safePath === '/' ? e.name : `${safePath}/${e.name}`,
109 type: e.isDirectory() ? 1 : 0,
110 size: e.isDirectory() ? 0 : fs.statSync(join(filePath, e.name)).size,
111 }));
112 res.writeHead(200);
113 res.end(JSON.stringify({ files, not_exists: false }));
114 } catch (err) {
115 res.writeHead(500);
116 res.end(JSON.stringify({ error: String(err) }));
117 }
118 return;
119 }
120
121 if (req.method === 'GET') {
122 try {
123 if (fs.existsSync(filePath)) {
124 const ext = filePath.split('.').pop()?.toLowerCase() || '';
125 const binaryMimes: Record<string, string> = {
126 png: 'image/png',
127 jpg: 'image/jpeg',
128 jpeg: 'image/jpeg',
129 gif: 'image/gif',
130 webp: 'image/webp',
131 svg: 'image/svg+xml',
132 mp4: 'video/mp4',
133 webm: 'video/webm',
134 };

Callers 1

configFunction · 0.85

Calls

no outgoing calls

Tested by

no test coverage detected