support configurable binary paths for mbsync, notmuch env

Orchestrator reads MBSYNC_BIN and NOTMUCH_CONFIG from env vars so the
backend works on Uberspace where mbsync is built from source at a
custom path and notmuch needs an explicit config location.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-10 12:41:37 +01:00
parent 35f558b323
commit 5867799de4
2 changed files with 15 additions and 5 deletions

View File

@@ -70,8 +70,12 @@ function isMessageNode(item: unknown): item is Record<string, unknown> {
return typeof item === "object" && item !== null && "id" in item && "headers" in item;
}
const notmuchEnv = process.env.NOTMUCH_CONFIG
? { NOTMUCH_CONFIG: process.env.NOTMUCH_CONFIG }
: undefined;
export async function searchThreads(query: string): Promise<ThreadSummary[]> {
const result = await runCommand("notmuch", ["search", "--format=json", query]);
const result = await runCommand("notmuch", ["search", "--format=json", query], notmuchEnv);
if (result.exitCode !== 0) {
throw new Error(`notmuch search failed: ${result.stderr}`);
}
@@ -79,7 +83,7 @@ export async function searchThreads(query: string): Promise<ThreadSummary[]> {
}
export async function getThread(threadId: string): Promise<Message[]> {
const result = await runCommand("notmuch", ["show", "--format=json", `thread:${threadId}`]);
const result = await runCommand("notmuch", ["show", "--format=json", `thread:${threadId}`], notmuchEnv);
if (result.exitCode !== 0) {
throw new Error(`notmuch show failed: ${result.stderr}`);
}

View File

@@ -4,10 +4,11 @@ export interface CommandResult {
exitCode: number;
}
export async function runCommand(cmd: string, args: string[]): Promise<CommandResult> {
export async function runCommand(cmd: string, args: string[], env?: Record<string, string>): Promise<CommandResult> {
const proc = Bun.spawn([cmd, ...args], {
stdout: "pipe",
stderr: "pipe",
env: env ? { ...process.env, ...env } : undefined,
});
const stdout = await new Response(proc.stdout).text();
@@ -17,12 +18,17 @@ export async function runCommand(cmd: string, args: string[]): Promise<CommandRe
return { stdout, stderr, exitCode };
}
const mbsyncBin = process.env.MBSYNC_BIN ?? "mbsync";
const notmuchEnv = process.env.NOTMUCH_CONFIG
? { NOTMUCH_CONFIG: process.env.NOTMUCH_CONFIG }
: undefined;
export async function syncMail(channelName: string): Promise<CommandResult> {
return runCommand("mbsync", [channelName]);
return runCommand(mbsyncBin, [channelName]);
}
export async function indexMail(): Promise<CommandResult> {
return runCommand("notmuch", ["new"]);
return runCommand("notmuch", ["new"], notmuchEnv);
}
export async function syncAndIndex(channelName: string): Promise<CommandResult> {