mrmd-server 0.1.22 → 0.1.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/cli.js CHANGED
@@ -23,7 +23,7 @@ function parseArgs(args) {
23
23
  const options = {
24
24
  port: 8080,
25
25
  host: '0.0.0.0',
26
- token: null,
26
+ token: undefined,
27
27
  noAuth: false,
28
28
  projectDir: '.',
29
29
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mrmd-server",
3
- "version": "0.1.22",
3
+ "version": "0.1.23",
4
4
  "description": "HTTP server for mrmd - run mrmd in any browser, access from anywhere",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
package/src/api/file.js CHANGED
@@ -58,10 +58,10 @@ export function createFileRoutes(ctx) {
58
58
  }
59
59
 
60
60
  const fullPath = resolvePath(ctx.projectDir, filePath);
61
- const result = await fileService.createFile(fullPath, content);
61
+ await fileService.createFile(fullPath, content);
62
62
 
63
63
  ctx.eventBus.projectChanged(ctx.projectDir);
64
- res.json({ success: true, path: result });
64
+ res.json({ success: true, path: fullPath });
65
65
  } catch (err) {
66
66
  if (err.message?.includes('already exists')) {
67
67
  return res.status(409).json({ error: 'File already exists' });
@@ -89,7 +89,7 @@ export function createFileRoutes(ctx) {
89
89
  ctx.eventBus.projectChanged(root);
90
90
  res.json({
91
91
  success: true,
92
- path: result.relativePath,
92
+ path: result,
93
93
  });
94
94
  } catch (err) {
95
95
  console.error('[file:createInProject]', err);
@@ -239,7 +239,7 @@ export function createFileRoutes(ctx) {
239
239
  const content = await fileService.read(fullPath);
240
240
  const previewLines = content.split('\n').slice(0, lines).join('\n');
241
241
 
242
- res.json({ success: true, content: previewLines });
242
+ res.json({ success: true, content: previewLines, preview: previewLines });
243
243
  } catch (err) {
244
244
  if (err.code === 'ENOENT') {
245
245
  return res.status(404).json({ success: false, error: 'File not found' });
package/src/server.js CHANGED
@@ -83,7 +83,7 @@ export async function createServer(config) {
83
83
  port = 8080,
84
84
  host = '0.0.0.0',
85
85
  projectDir,
86
- token = generateToken(),
86
+ token: configuredToken,
87
87
  noAuth = false,
88
88
  staticDir,
89
89
  electronDir,
@@ -91,6 +91,12 @@ export async function createServer(config) {
91
91
  pythonPort = 8000,
92
92
  aiPort = 51790,
93
93
  } = config;
94
+ const token = (
95
+ typeof configuredToken === 'string' &&
96
+ configuredToken.trim() !== '' &&
97
+ configuredToken !== 'null' &&
98
+ configuredToken !== 'undefined'
99
+ ) ? configuredToken : generateToken();
94
100
 
95
101
  // projectDir is optional now - dynamic project detection is supported
96
102
  if (!projectDir) {
@@ -112,6 +118,10 @@ export async function createServer(config) {
112
118
  const assetService = new AssetService();
113
119
  const settingsService = new SettingsService();
114
120
 
121
+ // Import API keys from environment variables into settings
122
+ // This lets users run: ANTHROPIC_API_KEY=sk-ant-... mrmd-server
123
+ importApiKeysFromEnv(settingsService);
124
+
115
125
  // Service context passed to all route handlers
116
126
  const context = {
117
127
  // Legacy: fixed project dir (for backwards compat, may be null)
@@ -542,6 +552,40 @@ function transformIndexHtml(html, host, port) {
542
552
  return html;
543
553
  }
544
554
 
555
+ /**
556
+ * Import API keys from environment variables into settings.
557
+ * Only imports if the env var is set and the settings key is empty.
558
+ * This allows: ANTHROPIC_API_KEY=sk-ant-... mrmd-server
559
+ */
560
+ function importApiKeysFromEnv(settingsService) {
561
+ const envMapping = {
562
+ anthropic: 'ANTHROPIC_API_KEY',
563
+ openai: 'OPENAI_API_KEY',
564
+ groq: 'GROQ_API_KEY',
565
+ gemini: 'GEMINI_API_KEY',
566
+ openrouter: 'OPENROUTER_API_KEY',
567
+ };
568
+
569
+ settingsService.load();
570
+ let imported = 0;
571
+
572
+ for (const [provider, envVar] of Object.entries(envMapping)) {
573
+ const envValue = process.env[envVar];
574
+ if (envValue) {
575
+ const existing = settingsService.getApiKey(provider);
576
+ if (!existing) {
577
+ settingsService.setApiKey(provider, envValue);
578
+ console.log(`[server] Imported ${envVar} from environment into settings`);
579
+ imported++;
580
+ }
581
+ }
582
+ }
583
+
584
+ if (imported > 0) {
585
+ console.log(`[server] Imported ${imported} API key(s) from environment`);
586
+ }
587
+ }
588
+
545
589
  /**
546
590
  * Convenience function to create and start server
547
591
  * @param {ServerConfig} config
@@ -260,7 +260,10 @@
260
260
 
261
261
  readPreview: (filePath, lines) =>
262
262
  GET(`/api/file/preview?path=${encodeURIComponent(filePath)}&lines=${lines || 40}`)
263
- .then(r => r.content),
263
+ .then((r) => ({
264
+ success: r?.success !== false,
265
+ preview: typeof r?.preview === 'string' ? r.preview : (r?.content || ''),
266
+ })),
264
267
 
265
268
  getFileInfo: (filePath) =>
266
269
  GET(`/api/file/info?path=${encodeURIComponent(filePath)}`),