osborn 0.9.2 → 0.9.4

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.
Files changed (2) hide show
  1. package/dist/index.js +13 -22
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -300,41 +300,31 @@ function startApiServer(workingDir, port) {
300
300
  // GET /sessions/export — stream a gzipped tar of ~/.claude/projects/ to the client
301
301
  // Optional ?workDir= query param: if present, export only that project's slug folder.
302
302
  if (req.method === 'GET' && url.pathname === '/sessions/export') {
303
- const projectsDir = join(homedir(), '.claude', 'projects');
304
- const workDir = url.searchParams.get('workDir');
305
- if (workDir) {
306
- const slug = workDir.replace(/\//g, '-');
307
- const slugDir = join(projectsDir, slug);
308
- if (!existsSync(slugDir)) {
309
- res.writeHead(404, { 'Content-Type': 'application/json' });
310
- res.end(JSON.stringify({ error: 'Project not found', slug }));
303
+ if (syncToken) {
304
+ const authHeader = req.headers['authorization'] ?? '';
305
+ if (authHeader !== `Bearer ${syncToken}`) {
306
+ res.writeHead(401, { 'Content-Type': 'application/json' });
307
+ res.end(JSON.stringify({ error: 'Unauthorized' }));
311
308
  return;
312
309
  }
313
- res.writeHead(200, {
314
- 'Content-Type': 'application/gzip',
315
- 'Content-Disposition': `attachment; filename="claude-sessions-${slug}.tar.gz"`,
316
- 'Access-Control-Allow-Origin': '*',
317
- });
318
- // Use '--' to prevent tar from interpreting the leading-hyphen slug as flags
319
- const tar = spawn('tar', ['-czf', '-', '-C', projectsDir, '--', slug]);
320
- tar.stdout.pipe(res);
321
- tar.stderr.on('data', (d) => console.error('[export]', d.toString()));
322
- tar.on('close', (code) => { if (code !== 0)
323
- res.destroy(); });
324
- return;
325
310
  }
311
+ const claudeDir = join(homedir(), '.claude');
312
+ const projectsDir = join(claudeDir, 'projects');
313
+ const workDir = url.searchParams.get('workDir');
326
314
  if (!existsSync(projectsDir)) {
327
315
  res.writeHead(404, { 'Content-Type': 'application/json' });
328
316
  res.end(JSON.stringify({ error: 'No sessions found' }));
329
317
  return;
330
318
  }
319
+ const tarArgs = ['-czf', '-', '-C', claudeDir, 'projects'];
320
+ void workDir; // workDir param accepted but full projects/ export is returned
331
321
  res.writeHead(200, {
332
322
  'Content-Type': 'application/gzip',
333
323
  'Content-Disposition': 'attachment; filename="claude-sessions.tar.gz"',
334
324
  'Access-Control-Allow-Origin': '*',
335
325
  });
336
326
  // Stream tar output directly to response
337
- const tar = spawn('tar', ['-czf', '-', '-C', join(homedir(), '.claude'), 'projects']);
327
+ const tar = spawn('tar', tarArgs);
338
328
  tar.stdout.pipe(res);
339
329
  tar.stderr.on('data', (d) => console.error('[export]', d.toString()));
340
330
  tar.on('close', (code) => { if (code !== 0)
@@ -370,7 +360,8 @@ function startApiServer(workingDir, port) {
370
360
  return;
371
361
  }
372
362
  try {
373
- const projectsDir = join(homedir(), '.claude', 'projects');
363
+ const claudeDir = join(homedir(), '.claude');
364
+ const projectsDir = join(claudeDir, 'projects');
374
365
  mkdirSync(projectsDir, { recursive: true });
375
366
  // The archive should contain a 'projects' subdirectory
376
367
  const extractedProjects = join(tmpDir, 'projects');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "osborn",
3
- "version": "0.9.2",
3
+ "version": "0.9.4",
4
4
  "description": "Voice AI coding assistant - local agent that connects to Osborn frontend",
5
5
  "type": "module",
6
6
  "bin": {