More fixes

This commit is contained in:
Haakam Aujla 2026-01-27 14:42:37 -08:00
parent 0d73dea914
commit a1182ccd04
8 changed files with 52 additions and 21 deletions

View File

@ -13,8 +13,7 @@
"selectionLabel": "AgentMail (Email Inbox API)",
"docsPath": "/channels/agentmail",
"docsLabel": "agentmail",
"blurb": "Email channel via AgentMail; configure API key and inbox.",
"order": 0,
"blurb": "email channel via AgentMail; dedicated agent inbox API.",
"quickstartAllowFrom": true
},
"install": {

View File

@ -16,11 +16,10 @@ export function listAgentMailAccountIds(_cfg: CoreConfig): string[] {
/**
* Returns the default AgentMail account ID.
* Currently only supports a single default account.
*/
export function resolveDefaultAgentMailAccountId(cfg: CoreConfig): string {
const ids = listAgentMailAccountIds(cfg);
if (ids.includes(DEFAULT_ACCOUNT_ID)) return DEFAULT_ACCOUNT_ID;
return ids[0] ?? DEFAULT_ACCOUNT_ID;
export function resolveDefaultAgentMailAccountId(_cfg: CoreConfig): string {
return DEFAULT_ACCOUNT_ID;
}
/** Resolved AgentMail credentials and paths. */

View File

@ -23,12 +23,13 @@ import type { CoreConfig, ResolvedAgentMailAccount } from "./utils.js";
const meta = {
id: "agentmail",
label: "AgentMail (Email Inbox API)",
label: "AgentMail",
selectionLabel: "AgentMail (Email Inbox API)",
detailLabel: "AgentMail",
docsPath: "/channels/agentmail",
docsLabel: "agentmail",
blurb: "Email channel via AgentMail; configure token and email address.",
order: 80,
blurb: "email channel via AgentMail; dedicated agent inbox API.",
systemImage: "envelope",
quickstartAllowFrom: true,
};

View File

@ -5,15 +5,21 @@ import { getAgentMailRuntime } from "./runtime.js";
import type { CoreConfig } from "./utils.js";
let sharedClient: AgentMailClient | null = null;
let sharedClientKey: string | null = null;
/** Creates or returns a shared AgentMailClient instance. */
/** Creates or returns a shared AgentMailClient instance. Recreates if key changed. */
export function getAgentMailClient(apiKey?: string): AgentMailClient {
if (sharedClient) return sharedClient;
const key = apiKey ?? getResolvedCredentials().apiKey;
if (!key) throw new Error("AgentMail token is required");
// Return cached client if key matches
if (sharedClient && sharedClientKey === key) {
return sharedClient;
}
// Create new client (key changed or first call)
sharedClient = new AgentMailClient({ apiKey: key });
sharedClientKey = key;
return sharedClient;
}

View File

@ -14,11 +14,8 @@ export function matchesList(senderEmail: string, list: string[]): boolean {
return list.some((entry) => {
const normalizedEntry = entry.toLowerCase().trim();
return (
normalizedEntry === normalizedSender || // exact email match
normalizedEntry === domain || // exact domain match
normalizedSender.endsWith(`@${normalizedEntry}`) // domain suffix match
);
// Match exact email or domain
return normalizedEntry === normalizedSender || normalizedEntry === domain;
});
}

View File

@ -44,6 +44,7 @@ function recordState(
});
}
/** Returns runtime state for status checks. */
export function getAgentMailRuntimeState(accountId: string) {
return runtimeState.get(`agentmail:${accountId}`);
}
@ -158,8 +159,12 @@ export async function monitorAgentMailProvider(
return sendJson(res, 200, { ok: true, filtered: true });
}
// Label message as allowed
await labelMessageAllowed(client, inboxId, message.messageId);
// Label message as allowed (best effort - don't fail if labeling fails)
try {
await labelMessageAllowed(client, inboxId, message.messageId);
} catch (labelErr) {
logVerbose(`agentmail: failed to label message: ${String(labelErr)}`);
}
recordState(accountId, { lastInboundAt: Date.now() });

View File

@ -94,8 +94,8 @@ export async function fetchFormattedThread(
const messages = thread.messages.map(formatMessage).join("\n\n");
return `${header}\n\n${messages}`;
} catch (err) {
console.error(`Failed to fetch thread: ${String(err)}`);
} catch {
// Caller handles fallback to webhook payload
return "";
}
}

View File

@ -213,6 +213,30 @@ const DOCKS: Record<ChatChannelId, ChannelDock> = {
}),
},
},
agentmail: {
id: "agentmail",
capabilities: {
chatTypes: ["direct"],
media: true,
threads: true,
},
outbound: { textChunkLimit: 4000 },
config: {
resolveAllowFrom: ({ cfg }) =>
((cfg.channels?.agentmail as { allowFrom?: string[] } | undefined)?.allowFrom ?? []).map(
(entry) => String(entry),
),
formatAllowFrom: ({ allowFrom }) => formatLower(allowFrom),
},
threading: {
buildToolContext: ({ context, hasRepliedRef }) => ({
currentChannelId: context.To?.trim() || undefined,
currentThreadTs:
context.MessageThreadId != null ? String(context.MessageThreadId) : undefined,
hasRepliedRef,
}),
},
},
googlechat: {
id: "googlechat",
capabilities: {