one resolver for where an email chat lives
the picker above an email composer listed conversations from the owner's home — a chat started somewhere else entirely, offered as if it belonged to the mailbox. the address had two resolvers. the chat socket knew `context: 'email'` and ran the turn in the account's directory; `GET /chat/sessions` did not, and fell through to `who.home`. so a message went into the mailbox and could not be found in the list directly above where it was typed. two answers to "where does this chat live" is one too many, and the one that was missing failed quietly. `resolveEmailAccountDir` in data-path.ts is now the only answer, and both call it. it verifies a client-named mailbox against disk rather than sanitising it into shape, which matters because the socket's caller ends in mkdirSync — an unrecognised value would not fail, it would CREATE a directory named after whatever arrived and run turns in it. `all`, the list's own sentinel for the unified view, is exactly the value most likely to arrive by accident. pure: no mkdir, no writes. the caller that needs the directory says so itself. tested, because a missing branch is what this was: the named mailbox wins, `all` never becomes a directory, a mailbox with no emails.db is not a mailbox, and no account at all resolves to the accounts root rather than to something invented. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Officer-Session: 656f5c85-e49a-4f1f-b9f3-042a04b4d043
This commit is contained in:
@@ -17,9 +17,8 @@ import * as sidecar from '@@/sidecar-registry';
|
||||
import { join } from 'path';
|
||||
import {
|
||||
getOwnerHomeDir,
|
||||
getEmailAccountsDir,
|
||||
getPluginChatsDir,
|
||||
findEmailAccountName,
|
||||
resolveEmailAccountDir,
|
||||
getCommanderDir,
|
||||
} from '../../../servers/data-path';
|
||||
import { attachedFilePaths } from './attached-files';
|
||||
@@ -197,24 +196,11 @@ export const resolveBaseCwd = (home: string, cwd?: string) => resolveCwd(home, c
|
||||
// `accountEmail` will come from the account selector (msg.contextId) later; for now default to the
|
||||
// owner's first enabled account. Falls back to the email_accounts root if there are no accounts.
|
||||
async function resolveEmailCwd(ownerEmail: string, accountEmail?: string): Promise<string> {
|
||||
// Found on disk, never queried. Email is a plugin and the platform may not import its queries; the
|
||||
// directory layout is already the platform's, so reading it answers the question with no coupling and
|
||||
// nothing to throw when the plugin is not installed.
|
||||
//
|
||||
// The named mailbox has to EXIST before it is joined. `accountEmail` reaches here from the client — it is
|
||||
// the mailbox picker's `?account=` — and this function ends in `mkdirSync`, so an unrecognised value does
|
||||
// not fail, it CREATES a directory named after whatever was sent and runs the turn in it. The list's
|
||||
// unified view uses the sentinel `all`, which is the value most likely to arrive by accident; the panel
|
||||
// drops it, and this is the half that does not depend on the panel remembering to.
|
||||
//
|
||||
// Falling back to the most recently synced account is the same answer the unified list is mostly showing.
|
||||
const requested = accountEmail?.trim();
|
||||
const known = requested && existsSync(join(getEmailAccountsDir(ownerEmail), requested, 'emails.db'));
|
||||
if (requested && !known) {
|
||||
console.warn(`[chat] email: no mailbox named ${requested} — using the most recently synced one instead`);
|
||||
}
|
||||
const account = (known ? requested : null) ?? findEmailAccountName(ownerEmail);
|
||||
const dir = account ? join(getEmailAccountsDir(ownerEmail), account) : getEmailAccountsDir(ownerEmail);
|
||||
// `resolveEmailAccountDir` is shared with `GET /chat/sessions`, deliberately: the turn and the list of
|
||||
// conversations must resolve the same directory, and they did not — the sessions route knew nothing about
|
||||
// `email` and fell through to the owner's home, so the picker above this composer offered chats from
|
||||
// somewhere else. See its own comment for why `accountEmail` is verified rather than sanitised.
|
||||
const dir = resolveEmailAccountDir(ownerEmail, accountEmail);
|
||||
mkdirSync(dir, { recursive: true });
|
||||
// The same brief a plugin's own chats get, written where an email chat actually runs.
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user