Skip to content

Conversation

@vanpelt
Copy link
Collaborator

@vanpelt vanpelt commented Nov 28, 2025

Use the /v1/sessions/workspace/{path} endpoint for active session polling instead of fetching all workspaces. This significantly reduces backend load during active Claude sessions.

  • Add latestUserPrompt, latestMessage, latestThought, stats to FullSessionData
  • Always populate session data fields (not just when full=true)
  • Update WorkspacePoller to use session endpoint for active sessions
  • Add effectiveLatestUserPrompt/Message computed properties in views
  • Fix "You asked" section disappearing during active sessions

🤖 Generated with Claude Code

Use the /v1/sessions/workspace/{path} endpoint for active session polling
instead of fetching all workspaces. This significantly reduces backend load
during active Claude sessions.

- Add latestUserPrompt, latestMessage, latestThought, stats to FullSessionData
- Always populate session data fields (not just when full=true)
- Update WorkspacePoller to use session endpoint for active sessions
- Add effectiveLatestUserPrompt/Message computed properties in views
- Fix "You asked" section disappearing during active sessions

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@codecov
Copy link

codecov bot commented Nov 28, 2025

Claude and others added 11 commits November 28, 2025 15:29
Show the "Start Working" button instead of an empty gray box when a
workspace is in completed phase but has no session content (no user
prompt, no Claude message, no session title, no todos).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
…ding

Two issues fixed:
1. Backend: Return full FullSessionData object (not just SessionInfo) when
   full=false, so latestUserPrompt, latestMessage, latestThought, and stats
   are included in the response
2. Swift: Send full workspace path (e.g., "/worktrees/catnip/ruby") instead
   of just the last component, so backend can match against config

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
The workspace path (e.g., /worktrees/catnip/ruby) contains slashes which
break URL routing when used as a path parameter. Changed to use query
parameter instead:

- Backend: Accept workspace via ?workspace= query param (with path param
  fallback for backward compatibility)
- Swift: Use URLComponents with query items to properly encode the path
- Added route without path param that must come before parameterized route

Now the URL is: /v1/sessions/workspace?workspace=/worktrees/catnip/ruby

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Much simpler approach - the Swift app already has the workspace ID from
the worktrees list. Using the ID in the URL path is cleaner than trying
to encode paths with slashes.

- Backend: Accept workspace ID or path in the path param, resolve ID to
  path using GitService.GetWorktree()
- Swift: Use workspaceId directly in URL path
- Remove unused workspacePath from WorkspacePoller

URL is now: /v1/sessions/workspace/{workspace-uuid}

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Use paths.FindBestSessionFile in ClaudeService instead of SessionService
- This filters out agent-*.jsonl subagent sessions via UUID validation
- Checks for conversation content (not just snapshots)
- Filters out forked sessions (queue-operation)
- Prioritizes most recently modified, then largest size

Also adds latestClaudeMessage field to Swift WorkspaceInfo model
for fallback display when session endpoint returns empty.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
populateLatestDataFromParser was returning cached/stale session data
because it didn't call ReadIncremental() to refresh the parser.

The user prompt was correct because it reads from ~/.claude/history.jsonl
fresh each time, but latestMessage/thought/stats came from cached parser
state.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
ParserService had its own findBestSessionInDir() that did NOT filter
by UUID format, so it was selecting agent-*.jsonl files when they were
larger than the main session file.

Now uses paths.FindBestSessionFile which properly:
- Validates UUID format (filters out agent-*.jsonl)
- Checks for conversation content (not just snapshots)
- Filters out forked sessions (queue-operation)
- Prioritizes most recently modified, then largest size

This ensures the session endpoint returns data from the same session file
as `catnip reflect`.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This fixes a bug where the PTY terminal was resuming a different session
than what the parser was reading. All session file selection logic now
uses the centralized paths.FindBestSessionFile which properly:
- Validates UUID format (filters out agent-*.jsonl files)
- Checks for conversation content (user/assistant messages)
- Filters out forked sessions (queue-operation)
- Prioritizes most recently modified, with size as tie-breaker

Updated:
- SessionService.findNewestClaudeSessionFile
- SessionService.FindBestSessionFile
- PTYHandler.findNewestClaudeSession
- ClaudeSessionDetector.findClaudeSessionFromFiles

Also added comprehensive tests for paths.FindBestSessionFile.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add Todos and LatestSessionTitle fields to FullSessionData model
- Populate fields in populateLatestDataFromParser from parser cache
  and session service
- Update Swift SessionData model to include the new fields
- Add effectiveSessionTitle and effectiveTodos computed properties
  in WorkspaceDetailView to prefer session data over workspace data
- Wrap session token logging in #if DEBUG directive
- Update UITestingHelper with mock todos and session title

This enables the iOS app to display session title and todos during
active polling without needing to fetch from the heavier /git/worktrees
endpoint.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Remove duplicate GetAllSessionsForWorkspace call (was called twice per request)
- Only populate allSessions when full=true is requested
- Always clear sessionInfo.allSessions to avoid duplication in response

This reduces polling response size from ~5.7KB to ~1.2KB (79% smaller)
for the iOS app which never uses allSessions data.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Shows Claude's token consumption as a circular progress indicator around
the terminal/dashboard toggle button. Ring color changes based on usage:
- Gray: < 40K tokens
- Green: 40K - 80K tokens
- Orange: 80K - 120K tokens
- Red: > 120K tokens (approaching 155K compaction limit)

Also removes verbose session data logging.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants