osborn 0.9.24 → 0.9.25

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/dist/config.js CHANGED
@@ -649,25 +649,24 @@ export async function listAllClaudeSessions(limit = 100) {
649
649
  ]);
650
650
  if (preview.messageCount < 2)
651
651
  continue;
652
- // SLUG-FIRST: prefer the slug-derived path over the content cwd.
652
+ // SLUG-FIRST for both `cwd` (routing) and `projectPath` (display).
653
653
  //
654
- // Claude Code's `--resume <id>` looks up sessions by file LOCATION
655
- // (slug folder under ~/.claude/projects/), not by the cwd field inside
656
- // the JSONL. The JSONL content cwd is immutable historical metadata —
657
- // it's where the session was ORIGINALLY recorded (e.g. sprite path
658
- // /home/sprite/workspace or /workspaces/codespaces-blank). On migration
659
- // (sprite fly), files were finalized into a new slug but their
660
- // content still records the original cwd.
654
+ // The workspace root (the agent's cwd, e.g. `/workspace` on fly) is
655
+ // the base layer. Projects are subdirectories beneath it a session
656
+ // started in `/workspace/instagram` gets slug `-workspace-instagram`,
657
+ // and slugToPath turns that back into `/workspace/instagram`. The
658
+ // dashboard groups by this path → "instagram" naturally becomes a
659
+ // project card. Sessions started at the workspace root collapse into
660
+ // one "General" / "Workspace" card.
661
661
  //
662
- // The dashboard forwards this field as `workingDirectory` to the
663
- // agent, which uses it as Claude Code's spawn cwd. If it doesn't
664
- // match the slug, the spawn lands in the wrong folder and resume
665
- // errors with "No conversation found". The slug is the source of
666
- // truth for where the file lives on disk; use it.
667
- //
668
- // Content cwd is kept as a last-resort fallback only when slug
669
- // reversal fails (slugToPath validates with existsSync and returns
670
- // '' on ambiguous encodings like dir names containing literal '-').
662
+ // Why NOT prefer the content cwd: the JSONL records whatever cwd
663
+ // existed when the session was recorded for migrated sessions that
664
+ // can be a path that no longer exists on this host (e.g.
665
+ // `/workspaces/codespaces-blank` from someone's Codespace). Using
666
+ // file LOCATION as the source of truth keeps grouping aligned with
667
+ // where the data actually lives and where Claude Code's --resume
668
+ // will look. Content cwd is kept as a last-resort fallback for the
669
+ // rare case where slugToPath reversal fails.
671
670
  const slugPath = slugToPath(c.slug);
672
671
  sessions.push({
673
672
  sessionId: c.sessionId,
package/dist/index.js CHANGED
@@ -164,6 +164,14 @@ function startApiServer(workingDir, port) {
164
164
  const limit = parseInt(url.searchParams.get('limit') || '100', 10);
165
165
  const sessions = await listAllClaudeSessions(limit);
166
166
  const payload = {
167
+ // The agent's working directory at launch — the BASE LAYER of all
168
+ // project organization. The dashboard groups sessions relative to
169
+ // this path: a session whose cwd === baseCwd is a "Workspace"
170
+ // session (the base); a session at `${baseCwd}/<name>` is a
171
+ // project called "<name>". Replaces the dashboard's previously-
172
+ // hardcoded base-path list — agent self-describes its base so
173
+ // the UI doesn't have to keep a sync'd copy.
174
+ baseCwd: workingDir,
167
175
  sessions: sessions.map(s => ({
168
176
  sessionId: s.sessionId,
169
177
  projectSlug: s.projectSlug,
@@ -3100,6 +3108,11 @@ async function main() {
3100
3108
  const sessions = await listAllClaudeSessions(100);
3101
3109
  await sendToFrontend({
3102
3110
  type: 'sessions_list',
3111
+ // See `/sessions` HTTP handler — baseCwd is the agent's
3112
+ // workingDir, the base layer the dashboard groups against.
3113
+ // Sent here too so the in-chat session list grouping stays
3114
+ // consistent with the dashboard's grouping.
3115
+ baseCwd: workingDir,
3103
3116
  sessions: sessions.map(s => ({
3104
3117
  sessionId: s.sessionId,
3105
3118
  projectSlug: s.projectSlug,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "osborn",
3
- "version": "0.9.24",
3
+ "version": "0.9.25",
4
4
  "description": "Voice AI coding assistant - local agent that connects to Osborn frontend",
5
5
  "type": "module",
6
6
  "bin": {