osborn 0.9.155 → 0.9.156

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.
@@ -140,10 +140,17 @@ function ensureCompactionSettings() {
140
140
  else {
141
141
  mkdirSync(claudeDir, { recursive: true });
142
142
  }
143
+ let dirty = false;
143
144
  if (settings.autoCompactWindow !== 1_000_000) {
144
145
  settings.autoCompactWindow = 1_000_000;
146
+ dirty = true;
147
+ }
148
+ if (settings.cleanupPeriodDays !== 3650) {
149
+ settings.cleanupPeriodDays = 3650;
150
+ dirty = true;
151
+ }
152
+ if (dirty) {
145
153
  writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n');
146
- console.log('🪟 autoCompactWindow set to 1,000,000 in', settingsPath);
147
154
  }
148
155
  }
149
156
  catch (err) {
package/dist/index.js CHANGED
@@ -267,6 +267,7 @@ let codeServerStartHook = null;
267
267
  // code-server runs on 127.0.0.1:8300; the agent proxies it through its own
268
268
  // public HTTP server so no Cloudflare tunnel is needed.
269
269
  const IDE_TARGET = 'http://127.0.0.1:8300';
270
+ const OSBORN_API_PORT = parseInt(process.env.OSBORN_API_PORT || '8741', 10);
270
271
  // Route prefixes that belong to the agent itself. The proxy fall-through checks
271
272
  // this list FIRST so it never intercepts an agent API path.
272
273
  const AGENT_ROUTE_PREFIXES = [
@@ -1498,21 +1499,44 @@ function startApiServer(workingDir, port) {
1498
1499
  // 3 s until ready.
1499
1500
  if (url.pathname === '/editor' && req.method === 'GET') {
1500
1501
  // AUTH GATE (future): validate key / signed session before minting the cookie
1502
+ // Optional ?folder= param: must be an absolute path under /workspace with no
1503
+ // directory-traversal sequences. If absent or invalid, fall back to bare '/'.
1504
+ const rawFolder = url.searchParams.get('folder') ?? '';
1505
+ const folderParam = (() => {
1506
+ if (!rawFolder)
1507
+ return '';
1508
+ // Must be absolute, start with /workspace, no traversal sequences
1509
+ if (!rawFolder.startsWith('/workspace') ||
1510
+ rawFolder.includes('..') ||
1511
+ rawFolder.includes('\0'))
1512
+ return '';
1513
+ // Normalise and re-check (catches encoded or doubled slashes resolving outside /workspace)
1514
+ const normalised = rawFolder.replace(/\/+/g, '/');
1515
+ if (!normalised.startsWith('/workspace'))
1516
+ return '';
1517
+ return normalised;
1518
+ })();
1501
1519
  if (ideProxyEnabled && ideSessionToken) {
1502
- // code-server is up — set cookie and redirect to root (code-server's asset base)
1520
+ // code-server is up — set cookie and redirect into the requested folder (if valid)
1521
+ // or to root if no valid folder was supplied.
1522
+ const location = folderParam ? `/?folder=${encodeURIComponent(folderParam)}` : '/';
1503
1523
  res.writeHead(302, {
1504
1524
  'Set-Cookie': `osborn_ide=${ideSessionToken}; Path=/; HttpOnly; SameSite=Lax`,
1505
- 'Location': '/',
1525
+ 'Location': location,
1506
1526
  });
1507
1527
  res.end();
1508
1528
  }
1509
1529
  else {
1510
- // Not yet running — kick off start in the background, show "Starting…" page
1530
+ // Not yet running — kick off start in the background, show "Starting…" page.
1531
+ // Preserve ?folder= in the refresh URL so it survives the polling loop.
1511
1532
  if (codeServerStartHook) {
1512
1533
  codeServerStartHook().catch((err) => {
1513
1534
  console.error('❌ startCodeServer() from /editor failed:', err);
1514
1535
  });
1515
1536
  }
1537
+ const refreshTarget = folderParam
1538
+ ? `/editor?folder=${encodeURIComponent(folderParam)}`
1539
+ : '/editor';
1516
1540
  res.writeHead(200, {
1517
1541
  'Content-Type': 'text/html; charset=utf-8',
1518
1542
  'Cache-Control': 'no-store, must-revalidate',
@@ -1520,7 +1544,7 @@ function startApiServer(workingDir, port) {
1520
1544
  });
1521
1545
  res.end(`<!DOCTYPE html><html><head>
1522
1546
  <meta charset="utf-8">
1523
- <meta http-equiv="refresh" content="3;url=/editor">
1547
+ <meta http-equiv="refresh" content="3;url=${refreshTarget}">
1524
1548
  <title>Starting editor…</title>
1525
1549
  <style>body{font-family:sans-serif;display:flex;align-items:center;justify-content:center;height:100vh;margin:0;background:#1e1e1e;color:#ccc}</style>
1526
1550
  </head><body><p>Starting your editor…</p></body></html>`);
@@ -1536,7 +1560,7 @@ function startApiServer(workingDir, port) {
1536
1560
  const portProxyMatch = url.pathname.match(/^\/proxy\/(\d+)(\/.*)?$/);
1537
1561
  if (portProxyMatch) {
1538
1562
  const targetPort = parseInt(portProxyMatch[1]);
1539
- if (targetPort > 1024 && targetPort < 65536 && targetPort !== 8300 && targetPort !== parseInt(process.env.OSBORN_API_PORT || '8741', 10)) {
1563
+ if (targetPort > 1024 && targetPort < 65536 && targetPort !== 8300 && targetPort !== OSBORN_API_PORT) {
1540
1564
  const portProxyOptions = {
1541
1565
  hostname: '127.0.0.1',
1542
1566
  port: targetPort,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "osborn",
3
- "version": "0.9.155",
3
+ "version": "0.9.156",
4
4
  "description": "Voice AI coding assistant - local agent that connects to Osborn frontend",
5
5
  "type": "module",
6
6
  "bin": {