mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-11-15 02:49:33 +01:00
fix(files): list the git worktree an agent moved into (#765)
Claude Code's EnterWorktree moves the running process into <repo>/.claude/worktrees/<name>, while Session.workingDir stays on the main checkout. The Files panel kept walking workingDir, so it listed a tree the agent had left. paneCwd already follows the move, measured on Claude Code 2.1.318 in both directions, so nothing new has to track the agent. It also follows every cd in a shell, so a new SessionState.liveWorktree narrows it to a linked worktree, read from the .git file without starting git. Only a folder strictly below workingDir is ever an answer, and the listing only starts there: returned paths stay relative to workingDir, so the preview, raw and edit routes are unchanged and confinement does not widen. A worktree outside the session folder stays unfollowed. The panel asks with root=live, shows a strip naming the worktree with a switch to the session folder, and follows the agent in and out while open. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
46b85fa6d0
commit
89a93c871f
19 files changed
+853
-32
No files matched your search
@@ -35,6 +35,7 @@ import fastifyWebsocket from '@fastify/websocket';
|
||||
import fastifyMultipart from '@fastify/multipart';
|
||||
import { pasteImageDirInUseByOtherSession, startPasteImageGc, uploadDirs } from './paste-image-gc.js';
|
||||
import { CLEAN_EXIT_CLOSE_REASON, shouldCloseCleanlyExitedSession } from '../pane-exit-sweep.js';
|
||||
import { findLiveWorktree } from '../live-worktree.js';
|
||||
import { join, dirname } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { existsSync, mkdirSync, readFileSync, chmodSync, statSync } from 'node:fs';
|
||||
@@ -2967,6 +2968,7 @@ export class WebServer extends EventEmitter {
|
||||
// `undefined` here means an authoritative read listed no single directory
|
||||
// for the session (split into several panes, or gone from the socket).
|
||||
const paneCwdChanged = getPaneCurrentPath ? session.setPaneCwd(getPaneCurrentPath(muxName)) : false;
|
||||
if (paneCwdChanged) void this.refreshLiveWorktree(session);
|
||||
if (session.setPaneExit(getPaneExit(muxName))) {
|
||||
this.persistSessionState(session);
|
||||
} else if (!paneCwdChanged) {
|
||||
@@ -2977,6 +2979,18 @@ export class WebServer extends EventEmitter {
|
||||
this.closeCleanlyExitedSessions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Work out which linked worktree a session's pane moved into (#765). In the background, since
|
||||
* it reads the folder, and only after the directory changed, so an idle pane costs nothing.
|
||||
* A reading newer than the one this lookup started from owns the answer.
|
||||
*/
|
||||
private async refreshLiveWorktree(session: Session): Promise<void> {
|
||||
const cwd = session.paneCwd;
|
||||
const worktree = await findLiveWorktree(session.workingDir, cwd);
|
||||
if (session.paneCwd !== cwd) return;
|
||||
if (session.setLiveWorktree(worktree)) this.broadcastSessionStateDebounced(session.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close every session whose agent exited cleanly, through the same
|
||||
* `cleanupSession()` the X button uses (Ark0N/Codeman#446). A pinned session
|
||||
|
||||
Reference in new issue
Block a user