chat: tag OpenCode sessions with officer metadata (cwd) + filter lists by it

OpenCode has no per-session directory (every session runs in the fixed server's cwd),
so sessions from every context (/chat pwd, email account, project) all landed in one
list. Now each session is tagged on creation with its logical cwd via the free-form
session `metadata`: { officer: { cwd } } — API-settable, round-trips on list+detail,
never touched by opencode core (confirmed by source dive + live test).

- client.createSession(metadata?) sends `metadata`; adds OfficerSessionMeta + officerMeta() helper.
- send-opencode tags new sessions with { officer: { cwd } } (the resolved chat cwd).
- websocket: pass the full resolved cwd for every context (not just non-/chat).
- listOpenCodeSessions(cwd?) filters by metadata.officer.cwd; chat.ts passes the request cwd.

Verified live: sessions tagged with distinct cwds list only under their own cwd.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-25 10:50:48 +00:00
co-authored by Claude Opus 4.8
parent bab0d1b7f8
commit 7cd2be9fb9
5 changed files with 40 additions and 28 deletions
+3 -6
View File
@@ -85,7 +85,8 @@ async function resolveChatCwd(
userId: number,
): Promise<string> {
if (msg.context === 'email') return resolveEmailCwd(userId, email, msg.contextId);
if (msg.context === 'chat') return msg.cwd?.trim() ? resolveCwd(email, role, msg.cwd) : ensureClaudeSessionsCwd(email);
if (msg.context === 'chat')
return msg.cwd?.trim() ? resolveCwd(email, role, msg.cwd) : ensureClaudeSessionsCwd(email);
return resolveCwd(email, role, msg.cwd);
}
@@ -424,10 +425,6 @@ async function handleOpenCodeChat(
const cwd = await resolveChatCwd(msg, email, ws.data.role, userId);
// OpenCode's working directory: a context-scoped dir (email account, project, …) for OpenCode to
// operate in; the general /chat runs in the fixed server's default project (home), so pass none.
const openCodeDir = msg.context && msg.context !== 'chat' ? cwd : undefined;
const groupSlug = msg.groupSlug || null;
const session = sessionManager.getOrCreate(sessionId, email, cwd, model, groupSlug, msg.context, msg.contextId);
@@ -469,7 +466,7 @@ async function handleOpenCodeChat(
username,
prompt: effectivePrompt,
sessionKey: sessionId,
cwd: openCodeDir,
cwd,
model,
role: ws.data.role,
resumeSessionId: msg.resumeSessionId,