aamp-openclaw-plugin 0.1.37 → 0.1.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/aamp-openclaw-plugin.mjs +7 -41
- package/dist/index.js +51 -77
- package/dist/index.js.map +3 -3
- package/package.json +2 -1
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../sdk/src/jmap-push.ts", "../../sdk/src/types.ts", "../../sdk/src/parser.ts", "../../sdk/src/tiny-emitter.ts", "../../sdk/src/smtp-sender.ts", "../../sdk/src/thread.
|
|
4
|
-
"sourcesContent": ["/**\n * JMAP WebSocket Push Client\n *\n * Connects to Stalwart's JMAP WebSocket endpoint and subscribes to\n * Email StateChange events. When a new email arrives in the agent's\n * mailbox, fetches it via JMAP and emits the parsed AAMP headers.\n *\n * Protocol: RFC 8887 (JMAP over WebSocket)\n * Ref: https://www.rfc-editor.org/rfc/rfc8887\n */\n\nimport WebSocket from 'ws'\nimport { parseAampHeaders } from './parser.js'\nimport type {\n AampMessage,\n CardQuery,\n CardResponse,\n HumanReply,\n TaskAck,\n TaskCancel,\n TaskDispatch,\n TaskHelp,\n TaskResult,\n TaskStreamOpened,\n} from './types.js'\nimport { TinyEmitter } from './tiny-emitter.js'\n\ninterface JmapSession {\n capabilities: Record<string, unknown>\n accounts: Record<string, { name: string; isPrimary: boolean; accountCapabilities: Record<string, unknown> }>\n primaryAccounts: Record<string, string>\n username: string\n apiUrl: string\n downloadUrl: string\n uploadUrl: string\n eventSourceUrl: string\n state: string\n}\n\ninterface JmapStateChange {\n '@type': 'StateChange'\n changed: Record<string, Record<string, string>>\n pushState?: string\n}\n\ninterface JmapEmail {\n id: string\n blobId: string\n threadId: string\n mailboxIds: Record<string, boolean>\n subject: string\n from: Array<{ email: string; name?: string }>\n to: Array<{ email: string; name?: string }>\n replyTo?: Array<{ email: string; name?: string }>\n messageId?: string[]\n headers: Array<{ name: string; value: string }>\n receivedAt: string\n size: number\n /** Plain-text body parts (JMAP bodyStructure) */\n textBody?: Array<{ partId: string; type: string }>\n /** Decoded body values keyed by partId */\n bodyValues?: Record<string, { value: string; isEncodingProblem?: boolean; isTruncated?: boolean }>\n /** JMAP attachments (non-inline parts) */\n attachments?: Array<{\n blobId: string\n type: string\n name: string | null\n size: number\n }>\n}\n\ninterface JmapMethodResponse {\n methodResponses: Array<[string, Record<string, unknown>, string]>\n}\n\nfunction describeError(err: unknown): string {\n if (!(err instanceof Error)) return String(err)\n\n const parts = [err.message]\n const details = err as Error & {\n code?: string\n errno?: number | string\n syscall?: string\n address?: string\n port?: number\n cause?: unknown\n }\n\n if (details.code) parts.push(`code=${details.code}`)\n if (details.errno !== undefined) parts.push(`errno=${details.errno}`)\n if (details.syscall) parts.push(`syscall=${details.syscall}`)\n if (details.address) parts.push(`address=${details.address}`)\n if (details.port !== undefined) parts.push(`port=${details.port}`)\n\n if (details.cause instanceof Error) {\n parts.push(`cause=${describeError(details.cause)}`)\n } else if (details.cause !== undefined) {\n parts.push(`cause=${String(details.cause)}`)\n }\n\n return parts.join(' | ')\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nfunction shouldRetrySessionFetch(status: number): boolean {\n return status === 429 || status >= 500\n}\n\nfunction shouldRetryBlobDownload(status: number): boolean {\n return status === 404 || status === 429 || status === 503\n}\n\nfunction rewriteUrlToConfiguredOrigin(rawUrl: string, configuredBaseUrl: string): string {\n const parsed = new URL(rawUrl)\n const configured = new URL(configuredBaseUrl)\n parsed.protocol = configured.protocol\n parsed.username = configured.username\n parsed.password = configured.password\n parsed.hostname = configured.hostname\n parsed.port = configured.port\n return parsed.toString()\n}\n\nconst SESSION_FETCH_MAX_ATTEMPTS = 3\nconst SESSION_FETCH_RETRY_BASE_DELAY_MS = 250\n\ntype JmapPushEvents = {\n 'task.dispatch': (task: TaskDispatch) => void\n 'task.cancel': (task: TaskCancel) => void\n 'task.result': (result: TaskResult) => void\n 'task.help_needed': (help: TaskHelp) => void\n 'task.ack': (ack: TaskAck) => void\n 'task.stream.opened': (stream: TaskStreamOpened) => void\n 'card.query': (query: CardQuery) => void\n 'card.response': (response: CardResponse) => void\n reply: (reply: HumanReply) => void\n connected: () => void\n disconnected: (reason: string) => void\n error: (err: Error) => void\n _autoAck: (payload: { to: string; taskId: string; messageId: string }) => void\n}\n\nexport class JmapPushClient extends TinyEmitter<JmapPushEvents> {\n private ws: WebSocket | null = null\n private session: JmapSession | null = null\n private reconnectTimer: NodeJS.Timeout | null = null\n private pollTimer: NodeJS.Timeout | null = null\n private pingTimer: NodeJS.Timeout | null = null\n private safetySyncTimer: NodeJS.Timeout | null = null\n private readonly seenMessageIds = new Set<string>()\n private connected = false\n private pollingActive = false\n private running = false\n private connecting = false\n /** JMAP Email state \u2014 tracks processed position; null = not yet initialized */\n private emailState: string | null = null\n private readonly startedAtMs = Date.now()\n\n private readonly email: string\n private readonly password: string\n private readonly jmapUrl: string\n private readonly reconnectInterval: number\n private readonly rejectUnauthorized: boolean\n private readonly pingIntervalMs = 5000\n private readonly safetySyncIntervalMs = 5000\n\n constructor(opts: {\n email: string\n password: string\n jmapUrl: string\n reconnectInterval?: number\n /** Whether to reject unauthorized TLS certificates (default: true) */\n rejectUnauthorized?: boolean\n }) {\n super()\n this.email = opts.email\n this.password = opts.password\n this.jmapUrl = opts.jmapUrl.replace(/\\/$/, '')\n this.reconnectInterval = opts.reconnectInterval ?? 5000\n this.rejectUnauthorized = opts.rejectUnauthorized ?? true\n }\n\n /**\n * Start the JMAP Push listener\n */\n async start(): Promise<void> {\n this.running = true\n this.startSafetySync()\n await this.connect()\n }\n\n /**\n * Stop the JMAP Push listener\n */\n stop(): void {\n this.running = false\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer)\n this.reconnectTimer = null\n }\n if (this.pollTimer) {\n clearTimeout(this.pollTimer)\n this.pollTimer = null\n }\n if (this.pingTimer) {\n clearInterval(this.pingTimer)\n this.pingTimer = null\n }\n if (this.safetySyncTimer) {\n clearInterval(this.safetySyncTimer)\n this.safetySyncTimer = null\n }\n if (this.ws) {\n this.ws.close()\n this.ws = null\n }\n this.connected = false\n this.pollingActive = false\n this.connecting = false\n }\n\n private getAuthHeader(): string {\n const creds = `${this.email}:${this.password}`\n return `Basic ${Buffer.from(creds).toString('base64')}`\n }\n\n /**\n * Fetch the JMAP session object\n */\n private async fetchSession(): Promise<JmapSession> {\n const url = `${this.jmapUrl}/.well-known/jmap`\n let lastError: Error | null = null\n\n for (let attempt = 1; attempt <= SESSION_FETCH_MAX_ATTEMPTS; attempt += 1) {\n let res: Response\n try {\n res = await fetch(url, {\n headers: { Authorization: this.getAuthHeader() },\n })\n } catch (err) {\n lastError = new Error(`fetchSession ${url} failed: ${describeError(err)}`)\n if (attempt >= SESSION_FETCH_MAX_ATTEMPTS) throw lastError\n await sleep(SESSION_FETCH_RETRY_BASE_DELAY_MS * attempt)\n continue\n }\n\n if (res.ok) {\n return res.json() as Promise<JmapSession>\n }\n\n lastError = new Error(\n attempt >= SESSION_FETCH_MAX_ATTEMPTS || !shouldRetrySessionFetch(res.status)\n ? `Failed to fetch JMAP session: ${res.status} ${res.statusText}`\n : `Failed to fetch JMAP session after ${attempt} attempt(s): ${res.status} ${res.statusText}`,\n )\n if (attempt >= SESSION_FETCH_MAX_ATTEMPTS || !shouldRetrySessionFetch(res.status)) {\n throw lastError\n }\n\n await sleep(SESSION_FETCH_RETRY_BASE_DELAY_MS * attempt)\n }\n\n throw lastError ?? new Error('Failed to fetch JMAP session')\n }\n\n /**\n * Perform a JMAP API call\n */\n private async jmapCall(\n methods: Array<[string, Record<string, unknown>, string]>,\n ): Promise<JmapMethodResponse> {\n if (!this.session) throw new Error('No JMAP session')\n\n // Use the configured jmapUrl (external hostname) rather than session.apiUrl\n // which Stalwart populates with its own internal URL (e.g. http://aamp.local:8080/jmap)\n // and is unreachable when running behind a proxy.\n const apiUrl = `${this.jmapUrl}/jmap/`\n let res: Response\n try {\n res = await fetch(apiUrl, {\n method: 'POST',\n headers: {\n Authorization: this.getAuthHeader(),\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n using: [\n 'urn:ietf:params:jmap:core',\n 'urn:ietf:params:jmap:mail',\n ],\n methodCalls: methods,\n }),\n })\n } catch (err) {\n throw new Error(`jmapCall ${apiUrl} failed: ${describeError(err)}`)\n }\n\n if (!res.ok) {\n throw new Error(`JMAP API call failed: ${res.status}`)\n }\n\n return res.json() as Promise<JmapMethodResponse>\n }\n\n /**\n * Initialize emailState by fetching the current state without loading any emails.\n * Called on first connect so we only process emails that arrive AFTER this point.\n */\n private async initEmailState(accountId: string): Promise<void> {\n const response = await this.jmapCall([\n ['Email/get', { accountId, ids: [] }, 'g0'],\n ])\n const getResp = response.methodResponses.find(([name]) => name === 'Email/get')\n if (getResp) {\n this.emailState = (getResp[1] as { state?: string }).state ?? null\n }\n }\n\n /**\n * Fetch only emails created since `sinceState` using Email/changes.\n * Updates `this.emailState` to the new state after fetching.\n * Returns [] and resets state if the server cannot calculate changes (state too old).\n */\n private async fetchEmailsSince(accountId: string, sinceState: string): Promise<JmapEmail[]> {\n const changesResp = await this.jmapCall([\n ['Email/changes', { accountId, sinceState, maxChanges: 50 }, 'c1'],\n ])\n\n const changesResult = changesResp.methodResponses.find(([name]) => name === 'Email/changes')\n\n // Handle server error \u2014 e.g. \"cannotCalculateChanges\" when state is too old\n if (!changesResult || changesResult[0] === 'error') {\n await this.initEmailState(accountId)\n return []\n }\n\n const changes = changesResult[1] as {\n created?: string[]\n newState?: string\n hasMoreChanges?: boolean\n }\n\n if (changes.newState) {\n this.emailState = changes.newState\n }\n\n const newIds = changes.created ?? []\n if (newIds.length === 0) return []\n\n const emailResp = await this.jmapCall([\n [\n 'Email/get',\n {\n accountId,\n ids: newIds,\n properties: ['id', 'subject', 'from', 'to', 'headers', 'messageId', 'receivedAt', 'textBody', 'bodyValues', 'attachments'],\n fetchTextBodyValues: true,\n maxBodyValueBytes: 262144,\n },\n 'g1',\n ],\n ])\n\n const getResult = emailResp.methodResponses.find(([name]) => name === 'Email/get')\n if (!getResult) return []\n\n const data = getResult[1] as { list?: JmapEmail[] }\n return data.list ?? []\n }\n\n /**\n * Process a received email.\n *\n * Priority:\n * 1. If X-AAMP-Intent is present \u2192 emit typed AAMP event (task.dispatch / task.cancel / task.result / task.help_needed)\n * 2. If In-Reply-To is present \u2192 emit 'reply' event so the application layer can\n * resolve the thread (inReplyTo \u2192 taskId via Redis/DB) and handle human replies.\n * 3. Otherwise \u2192 ignore (not an AAMP-related email)\n */\n private processEmail(email: JmapEmail): void {\n // Build lowercase header map from JMAP header array\n const headerMap: Record<string, string> = {}\n for (const h of email.headers ?? []) {\n headerMap[h.name.toLowerCase()] = h.value.trim()\n }\n\n const fromAddr = email.from?.[0]?.email ?? ''\n const toAddr = email.to?.[0]?.email ?? ''\n const messageId = email.messageId?.[0] ?? email.id\n\n if (this.seenMessageIds.has(messageId)) return\n this.seenMessageIds.add(messageId)\n\n // \u2500\u2500 Path 1: AAMP-tagged email \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const aampTextPartId = email.textBody?.[0]?.partId\n const aampBodyText = aampTextPartId ? (email.bodyValues?.[aampTextPartId]?.value ?? '').trim() : ''\n\n const msg: AampMessage | null = parseAampHeaders({\n from: fromAddr,\n to: toAddr,\n messageId,\n subject: email.subject ?? '',\n headers: headerMap,\n bodyText: aampBodyText,\n })\n\n if (msg && 'intent' in msg) {\n // Attach email body text (task description) to all AAMP messages\n ;(msg as unknown as Record<string, unknown>).bodyText = aampBodyText\n\n // Attach received attachment metadata (blobId-based, downloadable via downloadBlob)\n const receivedAttachments = (email.attachments ?? []).map(a => ({\n filename: a.name ?? 'attachment',\n contentType: a.type,\n size: a.size,\n blobId: a.blobId,\n }))\n if (receivedAttachments.length > 0) {\n ;(msg as unknown as Record<string, unknown>).attachments = receivedAttachments\n }\n\n // Auto-ACK for dispatches \u2014 AampClient handles the actual sending\n if ((msg as { intent: string }).intent === 'task.dispatch') {\n this.emit('_autoAck', { to: fromAddr, taskId: (msg as { taskId: string }).taskId, messageId })\n }\n\n const aampMsg = msg as Exclude<AampMessage, HumanReply>\n switch (aampMsg.intent) {\n case 'task.dispatch':\n this.emit('task.dispatch', aampMsg)\n break\n case 'task.cancel':\n this.emit('task.cancel', aampMsg)\n break\n case 'task.result':\n this.emit('task.result', aampMsg)\n break\n case 'task.help_needed':\n this.emit('task.help_needed', aampMsg)\n break\n case 'task.ack':\n this.emit('task.ack', aampMsg)\n break\n case 'task.stream.opened':\n this.emit('task.stream.opened', aampMsg)\n break\n case 'card.query':\n this.emit('card.query', aampMsg)\n break\n case 'card.response':\n this.emit('card.response', aampMsg)\n break\n }\n return\n }\n\n // \u2500\u2500 Path 2: standard email reply \u2014 In-Reply-To fallback \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Standard email clients automatically set In-Reply-To when replying.\n // We strip angle brackets (<msgid@host>) to get the bare Message-ID.\n const rawInReplyTo = headerMap['in-reply-to'] ?? ''\n if (!rawInReplyTo) return // unrelated email, ignore\n\n // Handle \"References\" chain: prefer the last (most recent) Message-ID\n // so multi-turn threads still resolve to the correct task.\n const rawReferences = headerMap['references'] ?? ''\n const referencesIds = rawReferences\n .split(/\\s+/)\n .map((s) => s.replace(/[<>]/g, '').trim())\n .filter(Boolean)\n\n const inReplyTo = rawInReplyTo.replace(/[<>]/g, '').trim()\n\n // Extract plain-text body if available (fetched via fetchTextBodyValues)\n const textPartId = email.textBody?.[0]?.partId\n const bodyText = textPartId ? (email.bodyValues?.[textPartId]?.value ?? '').trim() : ''\n\n const reply: HumanReply = {\n inReplyTo,\n messageId,\n from: fromAddr,\n to: toAddr,\n subject: email.subject ?? '',\n bodyText,\n }\n\n // Also expose the full References chain so callers can walk the thread if needed\n if (referencesIds.length > 0) {\n Object.assign(reply, { references: referencesIds })\n }\n\n this.emit('reply', reply)\n }\n\n private async fetchRecentEmails(accountId: string): Promise<JmapEmail[]> {\n const queryResp = await this.jmapCall([\n [\n 'Email/query',\n {\n accountId,\n sort: [{ property: 'receivedAt', isAscending: false }],\n limit: 20,\n },\n 'q1',\n ],\n ])\n\n const queryResult = queryResp.methodResponses.find(([name]) => name === 'Email/query')\n if (!queryResult) return []\n\n const ids = ((queryResult[1] as { ids?: string[] }).ids ?? []).slice(0, 20)\n if (ids.length === 0) return []\n\n const emailResp = await this.jmapCall([\n [\n 'Email/get',\n {\n accountId,\n ids,\n properties: ['id', 'subject', 'from', 'to', 'headers', 'messageId', 'receivedAt', 'textBody', 'bodyValues', 'attachments'],\n fetchTextBodyValues: true,\n maxBodyValueBytes: 262144,\n },\n 'gRecent',\n ],\n ])\n\n const getResult = emailResp.methodResponses.find(([name]) => name === 'Email/get')\n if (!getResult) return []\n\n return (getResult[1] as { list?: JmapEmail[] }).list ?? []\n }\n\n private shouldProcessBootstrapEmail(email: JmapEmail): boolean {\n const receivedAtMs = new Date(email.receivedAt).getTime()\n // Keep a small grace window for mail that arrived during startup / reconnect races,\n // but do not replay older historical mailbox contents as fresh tasks.\n return Number.isFinite(receivedAtMs) && receivedAtMs >= this.startedAtMs - 15_000\n }\n\n /**\n * Connect to JMAP WebSocket\n */\n private async connect(): Promise<void> {\n if (this.connecting || !this.running) return\n this.connecting = true\n\n try {\n this.session = await this.fetchSession()\n } catch (err) {\n this.connecting = false\n this.emit('error', new Error(`Failed to get JMAP session: ${(err as Error).message}`))\n this.startPolling('session fetch failed')\n this.scheduleReconnect()\n return\n }\n\n // Build WebSocket URL from the configured jmapUrl (the management-service proxy).\n // The management service exposes the standard external WebSocket path /jmap/ws\n // and proxies upgrades to Stalwart. We never use the session capability URL\n // directly because Stalwart populates it with its own internal hostname\n // (e.g. ws://aamp.local:8080/jmap/ws), which is unreachable from outside\n // the Docker / cluster network.\n const stalwartWsUrl = `${this.jmapUrl}/jmap/ws`\n .replace(/^https:\\/\\//, 'wss://')\n .replace(/^http:\\/\\//, 'ws://')\n\n this.ws = new WebSocket(stalwartWsUrl, 'jmap', {\n headers: {\n Authorization: this.getAuthHeader(),\n },\n perMessageDeflate: false,\n rejectUnauthorized: this.rejectUnauthorized,\n })\n\n this.ws.on('unexpected-response', (_req, res) => {\n this.connecting = false\n const headerSummary = Object.entries(res.headers)\n .map(([key, value]) => `${key}: ${Array.isArray(value) ? value.join(', ') : (value ?? '')}`)\n .join('; ')\n this.startPolling(`websocket handshake failed: ${res.statusCode ?? 'unknown'}`)\n this.emit(\n 'error',\n new Error(\n `JMAP WebSocket handshake failed: ${res.statusCode ?? 'unknown'} ${res.statusMessage ?? ''}${headerSummary ? ` | headers: ${headerSummary}` : ''}`,\n ),\n )\n this.scheduleReconnect()\n })\n\n this.ws.on('open', async () => {\n this.connecting = false\n this.connected = true\n this.stopPolling()\n this.startPingHeartbeat()\n\n // On first connect (emailState is null), initialize state so we only\n // process emails arriving AFTER this point.\n // On reconnect, emailState is already set \u2014 Email/changes will catch up.\n const accountId = this.session?.primaryAccounts['urn:ietf:params:jmap:mail']\n if (accountId && this.emailState === null) {\n await this.initEmailState(accountId)\n }\n\n // Subscribe to Email state changes AFTER state is initialized\n this.ws!.send(\n JSON.stringify({\n '@type': 'WebSocketPushEnable',\n dataTypes: ['Email'],\n pushState: null,\n }),\n )\n\n this.emit('connected')\n })\n\n this.ws.on('pong', () => {\n // Receiving pong confirms the upstream and LB path are still alive.\n })\n\n this.ws.on('message', async (rawData: WebSocket.RawData) => {\n try {\n const msg = JSON.parse(rawData.toString()) as {\n '@type': string\n } & JmapStateChange\n\n if (msg['@type'] === 'StateChange') {\n await this.handleStateChange(msg)\n }\n } catch (err) {\n this.emit('error', new Error(`Failed to process JMAP push message: ${(err as Error).message}`))\n }\n })\n\n this.ws.on('close', (code, reason) => {\n this.connecting = false\n this.connected = false\n this.stopPingHeartbeat()\n const reasonStr = reason?.toString() ?? 'connection closed'\n this.startPolling(reasonStr)\n this.emit('disconnected', reasonStr)\n\n if (this.running) {\n this.scheduleReconnect()\n }\n })\n\n this.ws.on('error', (err) => {\n this.connecting = false\n this.stopPingHeartbeat()\n this.startPolling(err.message)\n this.emit('error', err)\n })\n }\n\n private startPingHeartbeat(): void {\n if (this.pingTimer) {\n clearInterval(this.pingTimer)\n this.pingTimer = null\n }\n\n this.pingTimer = setInterval(() => {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return\n try {\n this.ws.ping()\n } catch (err) {\n this.emit('error', new Error(`Failed to send WebSocket ping: ${(err as Error).message}`))\n }\n }, this.pingIntervalMs)\n }\n\n private stopPingHeartbeat(): void {\n if (this.pingTimer) {\n clearInterval(this.pingTimer)\n this.pingTimer = null\n }\n }\n\n private startSafetySync(): void {\n if (this.safetySyncTimer) return\n\n this.safetySyncTimer = setInterval(() => {\n if (!this.running) return\n\n void this.reconcileRecentEmails(20).catch((err) => {\n this.emit('error', new Error(`Safety reconcile failed: ${(err as Error).message}`))\n })\n }, this.safetySyncIntervalMs)\n }\n\n private async handleStateChange(stateChange: JmapStateChange): Promise<void> {\n if (!this.session) return\n\n const accountId = this.session.primaryAccounts['urn:ietf:params:jmap:mail']\n if (!accountId) return\n\n const changedAccount = stateChange.changed[accountId]\n if (!changedAccount?.Email) return\n\n try {\n if (this.emailState === null) {\n // State not yet initialized (race between open handler and first StateChange)\n // Just initialize and skip \u2014 next StateChange will use Email/changes properly\n await this.initEmailState(accountId)\n return\n }\n\n const emails = await this.fetchEmailsSince(accountId, this.emailState)\n for (const email of emails) {\n this.processEmail(email)\n }\n } catch (err) {\n this.emit('error', new Error(`Failed to fetch emails: ${(err as Error).message}`))\n }\n }\n\n private scheduleReconnect(): void {\n if (this.reconnectTimer) return\n\n this.reconnectTimer = setTimeout(async () => {\n this.reconnectTimer = null\n if (this.running) {\n await this.connect()\n }\n }, this.reconnectInterval)\n }\n\n isConnected(): boolean {\n return this.connected || this.pollingActive\n }\n\n isUsingPollingFallback(): boolean {\n return this.pollingActive && !this.connected\n }\n\n private stopPolling(): void {\n if (this.pollTimer) {\n clearTimeout(this.pollTimer)\n this.pollTimer = null\n }\n this.pollingActive = false\n }\n\n private startPolling(reason: string): void {\n if (!this.running || this.pollingActive) return\n\n this.pollingActive = true\n this.emit('error', new Error(`JMAP WebSocket unavailable, falling back to polling: ${reason}`))\n this.emit('connected')\n\n const poll = async () => {\n if (!this.running || this.connected) {\n this.stopPolling()\n return\n }\n\n try {\n if (!this.session) {\n this.session = await this.fetchSession()\n }\n\n const accountId = this.session.primaryAccounts['urn:ietf:params:jmap:mail']\n ?? Object.keys(this.session.accounts)[0]\n\n if (!accountId) {\n throw new Error('No mail account available in JMAP session')\n }\n\n if (this.emailState === null) {\n const recentEmails = await this.fetchRecentEmails(accountId)\n for (const email of recentEmails.sort((a, b) => {\n const aTs = new Date(a.receivedAt).getTime()\n const bTs = new Date(b.receivedAt).getTime()\n return aTs - bTs\n })) {\n if (!this.shouldProcessBootstrapEmail(email)) continue\n this.processEmail(email)\n }\n await this.initEmailState(accountId)\n } else {\n const emails = await this.fetchEmailsSince(accountId, this.emailState)\n for (const email of emails) {\n this.processEmail(email)\n }\n }\n } catch (err) {\n this.emit('error', new Error(`Polling fallback failed: ${(err as Error).message}`))\n } finally {\n if (this.running && !this.connected) {\n this.pollTimer = setTimeout(poll, this.reconnectInterval)\n }\n }\n }\n\n this.pollTimer = setTimeout(poll, 0)\n }\n\n /**\n * Download a blob (attachment) by its JMAP blobId.\n * Returns the raw binary content as a Buffer.\n */\n async downloadBlob(blobId: string, filename?: string): Promise<Buffer> {\n if (!this.session) {\n // Fetch session on demand if not yet connected\n this.session = await this.fetchSession()\n }\n\n const accountId = this.session.primaryAccounts['urn:ietf:params:jmap:mail']\n ?? Object.keys(this.session.accounts)[0]\n\n // Build download URL from session template or fall back to standard JMAP path\n let downloadUrl = this.session.downloadUrl\n ?? `${this.jmapUrl}/jmap/download/{accountId}/{blobId}/{name}`\n\n // Replace session.downloadUrl host with our configured jmapUrl\n // (Stalwart may report an internal hostname unreachable from outside Docker)\n try {\n downloadUrl = rewriteUrlToConfiguredOrigin(downloadUrl, this.jmapUrl)\n } catch {\n // If URL parsing fails, use the template as-is\n }\n\n const safeFilename = filename ?? 'attachment'\n downloadUrl = downloadUrl\n .replace(/\\{accountId\\}|%7BaccountId%7D/gi, encodeURIComponent(accountId))\n .replace(/\\{blobId\\}|%7BblobId%7D/gi, encodeURIComponent(blobId))\n .replace(/\\{name\\}|%7Bname%7D/gi, encodeURIComponent(safeFilename))\n .replace(/\\{type\\}|%7Btype%7D/gi, 'application/octet-stream')\n\n // Retry with exponential backoff \u2014 the blob may not be immediately available\n // after the result email is observed (store/index write delay).\n const maxAttempts = 8\n let lastStatus: number | null = null\n let lastError: Error | null = null\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n let res: Response\n try {\n res = await fetch(downloadUrl, {\n headers: { Authorization: this.getAuthHeader() },\n })\n } catch (err) {\n lastError = new Error(\n `Blob download fetch failed: attempt=${attempt}/${maxAttempts} blobId=${blobId} filename=${filename ?? 'attachment'} url=${downloadUrl} error=${describeError(err)}`,\n )\n if (attempt < maxAttempts) {\n console.warn(\n `[AAMP-SDK] blob download retry fetch-error attempt=${attempt}/${maxAttempts} url=${downloadUrl} error=${describeError(err)}`,\n )\n const delay = Math.min(1000 * Math.pow(2, attempt - 1), 15000)\n await new Promise(r => setTimeout(r, delay))\n continue\n }\n console.error(\n `[AAMP-SDK] blob download fetch-error attempt=${attempt}/${maxAttempts} url=${downloadUrl} error=${describeError(err)}`,\n )\n throw lastError\n }\n\n lastStatus = res.status\n if (res.ok) {\n const arrayBuffer = await res.arrayBuffer()\n return Buffer.from(arrayBuffer)\n }\n if (attempt < maxAttempts && shouldRetryBlobDownload(res.status)) {\n console.warn(\n `[AAMP-SDK] blob download retry status=${res.status} attempt=${attempt}/${maxAttempts} url=${downloadUrl}`,\n )\n const delay = Math.min(1000 * Math.pow(2, attempt - 1), 15000) // 1s, 2s, 4s, 8s, 15s...\n await new Promise(r => setTimeout(r, delay))\n continue\n }\n console.error(\n `[AAMP-SDK] blob download failed status=${res.status} attempt=${attempt}/${maxAttempts} url=${downloadUrl}`,\n )\n throw new Error(\n `Blob download failed: status=${res.status} attempt=${attempt}/${maxAttempts} blobId=${blobId} filename=${filename ?? 'attachment'} url=${downloadUrl}`,\n )\n }\n if (lastError) throw lastError\n throw new Error(\n `Blob download failed after retries: status=${lastStatus ?? 'unknown'} attempt=${maxAttempts}/${maxAttempts} blobId=${blobId} filename=${filename ?? 'attachment'} url=${downloadUrl}`,\n )\n }\n\n /**\n * Actively reconcile recent mailbox contents via JMAP HTTP.\n * Useful as a safety net when the WebSocket stays \"connected\"\n * but a notification is missed by an intermediate layer.\n */\n async reconcileRecentEmails(limit = 20, opts?: { includeHistorical?: boolean }): Promise<number> {\n if (!this.session) {\n this.session = await this.fetchSession()\n }\n\n const accountId = this.session.primaryAccounts['urn:ietf:params:jmap:mail']\n ?? Object.keys(this.session.accounts)[0]\n\n if (!accountId) {\n throw new Error('No mail account available in JMAP session')\n }\n\n const queryResp = await this.jmapCall([\n [\n 'Email/query',\n {\n accountId,\n sort: [{ property: 'receivedAt', isAscending: false }],\n limit,\n },\n 'qReconcile',\n ],\n ])\n\n const queryResult = queryResp.methodResponses.find(([name]) => name === 'Email/query')\n if (!queryResult) return 0\n\n const ids = ((queryResult[1] as { ids?: string[] }).ids ?? []).slice(0, limit)\n if (ids.length === 0) return 0\n\n const emailResp = await this.jmapCall([\n [\n 'Email/get',\n {\n accountId,\n ids,\n properties: ['id', 'subject', 'from', 'to', 'headers', 'messageId', 'receivedAt', 'textBody', 'bodyValues', 'attachments'],\n fetchTextBodyValues: true,\n maxBodyValueBytes: 262144,\n },\n 'gReconcile',\n ],\n ])\n\n const getResult = emailResp.methodResponses.find(([name]) => name === 'Email/get')\n if (!getResult) return 0\n\n const emails = (getResult[1] as { list?: JmapEmail[] }).list ?? []\n for (const email of emails.sort((a, b) => {\n const aTs = new Date(a.receivedAt).getTime()\n const bTs = new Date(b.receivedAt).getTime()\n return aTs - bTs\n })) {\n if (!opts?.includeHistorical && !this.shouldProcessBootstrapEmail(email)) continue\n this.processEmail(email)\n }\n\n return emails.length\n }\n}\n", "/**\n * AAMP SDK Type Definitions\n */\n\nexport const AAMP_PROTOCOL_VERSION = '1.1'\n\nexport type AampIntent =\n | 'task.dispatch'\n | 'task.cancel'\n | 'task.result'\n | 'task.help_needed'\n | 'task.ack'\n | 'task.stream.opened'\n | 'card.query'\n | 'card.response'\n\nexport type TaskPriority = 'urgent' | 'high' | 'normal'\n\nexport type TaskStatus =\n | 'pending'\n | 'running'\n | 'completed'\n | 'rejected'\n | 'failed'\n | 'help_needed'\n | 'cancelled'\n | 'expired'\n\n// =====================================================\n// AAMP Header constants\n// =====================================================\nexport const AAMP_HEADER = {\n VERSION: 'X-AAMP-Version',\n INTENT: 'X-AAMP-Intent',\n TASK_ID: 'X-AAMP-TaskId',\n CONTEXT_LINKS: 'X-AAMP-ContextLinks',\n DISPATCH_CONTEXT: 'X-AAMP-Dispatch-Context',\n PRIORITY: 'X-AAMP-Priority',\n EXPIRES_AT: 'X-AAMP-Expires-At',\n STATUS: 'X-AAMP-Status',\n OUTPUT: 'X-AAMP-Output',\n ERROR_MSG: 'X-AAMP-ErrorMsg',\n STRUCTURED_RESULT: 'X-AAMP-StructuredResult',\n QUESTION: 'X-AAMP-Question',\n BLOCKED_REASON: 'X-AAMP-BlockedReason',\n SUGGESTED_OPTIONS: 'X-AAMP-SuggestedOptions',\n STREAM_ID: 'X-AAMP-Stream-Id',\n PARENT_TASK_ID: 'X-AAMP-ParentTaskId',\n CARD_SUMMARY: 'X-AAMP-Card-Summary',\n} as const\n\nexport interface StructuredResultField {\n fieldKey: string\n fieldTypeKey: string\n value?: unknown\n fieldAlias?: string\n index?: string\n attachmentFilenames?: string[]\n}\n\n// =====================================================\n// Parsed AAMP headers for task.dispatch\n// =====================================================\nexport interface TaskDispatch {\n protocolVersion: string\n intent: 'task.dispatch'\n taskId: string\n title: string\n priority: TaskPriority\n expiresAt?: string\n contextLinks: string[]\n dispatchContext?: Record<string, string>\n parentTaskId?: string\n // Email metadata\n from: string\n to: string\n messageId: string\n subject: string\n /** Plain-text body of the email (task description) */\n bodyText: string\n /** Attachments received with this dispatch (use blobId to download) */\n attachments?: ReceivedAttachment[]\n}\n\nexport interface TaskCancel {\n protocolVersion: string\n intent: 'task.cancel'\n taskId: string\n from: string\n to: string\n messageId?: string\n subject: string\n bodyText: string\n}\n\n// =====================================================\n// Parsed AAMP headers for task.result\n// =====================================================\nexport interface TaskResult {\n protocolVersion: string\n intent: 'task.result'\n taskId: string\n status: 'completed' | 'rejected'\n output: string\n errorMsg?: string\n structuredResult?: StructuredResultField[]\n from: string\n to: string\n messageId?: string\n /** True when the reply came from a standard email client (no X-AAMP-Intent header).\n * taskId was resolved via In-Reply-To \u2192 Message-ID reverse lookup. */\n isHumanReply?: boolean\n /** Attachments received with this result (use blobId to download) */\n attachments?: ReceivedAttachment[]\n}\n\n// =====================================================\n// Human reply via standard email client (no AAMP headers)\n// Emitted as 'reply' event when an email has In-Reply-To but no X-AAMP-Intent.\n// The application layer is responsible for resolving inReplyTo \u2192 taskId\n// (e.g. via Redis reverse index) and deciding how to handle it.\n// =====================================================\nexport interface HumanReply {\n /** Message-ID of the email being replied to \u2014 use this to look up the taskId */\n inReplyTo: string\n /** This reply email's own Message-ID */\n messageId: string\n from: string\n to: string\n subject: string\n /** Plain-text body of the reply */\n bodyText: string\n}\n\n// =====================================================\n// Parsed AAMP headers for task.help_needed\n// =====================================================\nexport interface TaskHelp {\n protocolVersion: string\n intent: 'task.help_needed'\n taskId: string\n question: string\n blockedReason: string\n suggestedOptions: string[]\n from: string\n to: string\n messageId?: string\n}\n\n// =====================================================\n// Parsed AAMP headers for task.ack\n// =====================================================\nexport interface TaskAck {\n protocolVersion: string\n intent: 'task.ack'\n taskId: string\n from: string\n to: string\n messageId?: string\n}\n\nexport interface TaskStreamOpened {\n protocolVersion: string\n intent: 'task.stream.opened'\n taskId: string\n streamId: string\n from: string\n to: string\n messageId?: string\n}\n\nexport interface CardQuery {\n protocolVersion: string\n intent: 'card.query'\n taskId: string\n from: string\n to: string\n messageId?: string\n subject: string\n bodyText: string\n}\n\nexport interface CardResponse {\n protocolVersion: string\n intent: 'card.response'\n taskId: string\n summary: string\n from: string\n to: string\n messageId?: string\n subject: string\n bodyText: string\n}\n\n// =====================================================\n// Attachment types\n// =====================================================\n\n/** Attachment for sending (binary content) */\nexport interface AampAttachment {\n filename: string\n contentType: string\n content: Buffer | string // Buffer for binary, base64 string for REST API\n size?: number\n}\n\n/** Attachment metadata received via JMAP (use blobId to download) */\nexport interface ReceivedAttachment {\n filename: string\n contentType: string\n size: number\n blobId: string\n}\n\nexport type AampMessage =\n | TaskDispatch\n | TaskCancel\n | TaskResult\n | TaskHelp\n | TaskAck\n | TaskStreamOpened\n | CardQuery\n | CardResponse\n | HumanReply\n\n// =====================================================\n// SDK Configuration\n// =====================================================\nexport interface AampClientConfig {\n /** Node email address, e.g. codereviewer-abc123@aamp.yourdomain.com */\n email: string\n\n /** Mailbox token for HTTP Basic Auth. Equivalent to base64(email:smtpPassword). */\n mailboxToken: string\n\n /** Base URL for this mailbox service, e.g. https://meshmail.ai */\n baseUrl: string\n\n /** Optional AAMP discovery base URL. Defaults to baseUrl and is used for same-domain send fallback via /.well-known/aamp + aamp.mailbox.send. */\n httpSendBaseUrl?: string\n\n /** SMTP submission host. If omitted, derived from baseUrl. */\n smtpHost?: string\n\n /** SMTP submission port (default: 587) */\n smtpPort?: number\n\n /** SMTP password (returned by management service on agent creation) */\n smtpPassword: string\n\n /** How often to retry failed JMAP connection (ms, default: 5000) */\n reconnectInterval?: number\n\n /** Maximum number of task.dispatch handlers running concurrently (default: 10). */\n taskDispatchConcurrency?: number\n\n /** Whether to reject unauthorized TLS certificates (default: true).\n * Set to false only for development with self-signed certificates. */\n rejectUnauthorized?: boolean\n}\n\nexport interface AampMailboxIdentityConfig {\n /** Mailbox email address, e.g. agent@meshmail.ai */\n email: string\n\n /** Mailbox SMTP/JMAP password */\n smtpPassword: string\n\n /** Optional base URL for JMAP and same-domain AAMP HTTP send fallback.\n * Defaults to https://<email-domain>. */\n baseUrl?: string\n\n /** SMTP submission port (default: 587) */\n smtpPort?: number\n\n /** How often to retry failed JMAP connection (ms, default: 5000) */\n reconnectInterval?: number\n\n /** Maximum number of task.dispatch handlers running concurrently (default: 10). */\n taskDispatchConcurrency?: number\n\n /** Whether to reject unauthorized TLS certificates (default: true). */\n rejectUnauthorized?: boolean\n}\n\nexport interface AampDiscoveryDocument {\n protocol: 'aamp'\n version: string\n intents?: AampIntent[]\n api?: {\n url?: string\n actions?: string[]\n }\n endpoints?: Record<string, string>\n capabilities?: {\n stream?: {\n transport: 'sse'\n createAction?: string\n appendAction?: string\n closeAction?: string\n getAction?: string\n subscribeUrlTemplate?: string\n }\n }\n}\n\nexport interface RegisterMailboxOptions {\n /** AAMP service root, e.g. https://meshmail.ai */\n aampHost: string\n slug: string\n description?: string\n}\n\nexport interface RegisteredMailboxIdentity {\n email: string\n mailboxToken: string\n smtpPassword: string\n baseUrl: string\n}\n\nexport interface AgentDirectoryEntry {\n email: string\n summary: string | null\n}\n\nexport interface AgentDirectorySearchEntry extends AgentDirectoryEntry {\n score: number\n}\n\nexport interface AgentDirectoryProfile extends AgentDirectoryEntry {\n cardText: string | null\n}\n\nexport interface AampThreadEvent {\n intent: AampIntent\n from: string\n to: string\n title?: string | null\n bodyText?: string | null\n output?: string | null\n question?: string | null\n blockedReason?: string | null\n messageId?: string | null\n createdAt: string\n}\n\nexport interface GetThreadHistoryOptions {\n includeStreamOpened?: boolean\n}\n\nexport interface TaskThreadHistory {\n taskId: string\n events: AampThreadEvent[]\n}\n\nexport interface HydratedTaskDispatch extends TaskDispatch {\n threadHistory: AampThreadEvent[]\n threadContextText: string\n}\n\n// =====================================================\n// Options for sending emails\n// =====================================================\nexport interface SendTaskOptions {\n /** Target node email */\n to: string\n taskId?: string\n title: string\n bodyText?: string\n /** When set, send the body exactly as provided instead of wrapping it in the default task template. */\n rawBodyText?: string\n priority?: TaskPriority\n /** Absolute expiry timestamp. */\n expiresAt?: string\n contextLinks?: string[]\n dispatchContext?: Record<string, string>\n parentTaskId?: string\n /** Attachments to include with the dispatch email */\n attachments?: AampAttachment[]\n}\n\nexport type RegisteredCommandStreamMode = 'none' | 'status-only' | 'full'\n\nexport interface RegisteredCommandInputRef {\n slot: string\n attachmentName: string\n}\n\nexport interface RegisteredCommandDispatchPayload {\n kind: 'registered-command/v1'\n command: string\n args?: Record<string, unknown>\n inputs?: RegisteredCommandInputRef[]\n stream?: {\n mode?: RegisteredCommandStreamMode\n }\n}\n\nexport interface SendRegisteredCommandOptions {\n to: string\n taskId?: string\n title?: string\n command: string\n args?: Record<string, unknown>\n inputs?: RegisteredCommandInputRef[]\n streamMode?: RegisteredCommandStreamMode\n priority?: TaskPriority\n expiresAt?: string\n contextLinks?: string[]\n dispatchContext?: Record<string, string>\n parentTaskId?: string\n attachments?: AampAttachment[]\n}\n\nexport interface SendCancelOptions {\n to: string\n taskId: string\n bodyText?: string\n inReplyTo?: string\n}\n\nexport interface SendResultOptions {\n /** Send to: the original from address of the dispatch email */\n to: string\n taskId: string\n status: 'completed' | 'rejected'\n output: string\n errorMsg?: string\n structuredResult?: StructuredResultField[]\n /** When set, send the body exactly as provided instead of wrapping it in the default result template. */\n rawBodyText?: string\n /** Message-ID of the dispatch email, for In-Reply-To threading */\n inReplyTo?: string\n /** Attachments to include with the result email */\n attachments?: AampAttachment[]\n}\n\nexport interface SendHelpOptions {\n /** Send to: the original from address of the dispatch email */\n to: string\n taskId: string\n question: string\n blockedReason: string\n suggestedOptions: string[]\n /** When set, send the body exactly as provided instead of wrapping it in the default help template. */\n rawBodyText?: string\n /** Message-ID of the dispatch email, for In-Reply-To threading */\n inReplyTo?: string\n /** Attachments to include with the help email */\n attachments?: AampAttachment[]\n}\n\nexport interface SendCardQueryOptions {\n to: string\n taskId?: string\n bodyText?: string\n inReplyTo?: string\n}\n\nexport interface SendCardResponseOptions {\n to: string\n taskId: string\n summary: string\n bodyText: string\n inReplyTo?: string\n}\n\nexport interface CreateStreamOptions {\n taskId: string\n peerEmail: string\n}\n\nexport interface CreateStreamResult {\n streamId: string\n taskId: string\n status: 'created' | 'opened' | 'closed'\n ownerEmail: string\n peerEmail: string\n createdAt: string\n openedAt?: string\n closedAt?: string\n}\n\nexport type AampStreamEventType =\n | 'text.delta'\n | 'progress'\n | 'status'\n | 'artifact'\n | 'error'\n | 'done'\n\nexport interface AampStreamEvent {\n id?: string\n streamId: string\n taskId: string\n seq: number\n timestamp: string\n type: AampStreamEventType\n payload: Record<string, unknown>\n}\n\nexport interface AppendStreamEventOptions {\n streamId: string\n type: AampStreamEventType\n payload: Record<string, unknown>\n}\n\nexport interface CloseStreamOptions {\n streamId: string\n payload?: Record<string, unknown>\n}\n\nexport interface GetTaskStreamOptions {\n taskId?: string\n streamId?: string\n}\n\nexport interface TaskStreamState extends CreateStreamResult {\n latestEvent?: AampStreamEvent\n}\n\nexport interface StreamSubscription {\n close(): void\n}\n\nexport interface DirectoryListOptions {\n scope?: string\n includeSelf?: boolean\n limit?: number\n}\n\nexport interface DirectorySearchOptions extends DirectoryListOptions {\n query: string\n}\n\nexport interface UpdateDirectoryProfileOptions {\n summary?: string | null\n cardText?: string | null\n}\n\n// =====================================================\n// Event emitter types\n// =====================================================\nexport interface AampClientEvents {\n 'task.dispatch': (task: TaskDispatch) => void | Promise<void>\n 'task.cancel': (task: TaskCancel) => void\n 'task.result': (result: TaskResult) => void\n 'task.help_needed': (help: TaskHelp) => void\n 'task.ack': (ack: TaskAck) => void\n 'task.stream.opened': (stream: TaskStreamOpened) => void\n 'card.query': (query: CardQuery) => void\n 'card.response': (response: CardResponse) => void\n /** Emitted when a standard email reply (no X-AAMP headers) is received for a known thread.\n * Use inReplyTo to look up the taskId in your own store (Redis / DB). */\n 'reply': (reply: HumanReply) => void\n connected: () => void\n disconnected: (reason: string) => void\n error: (err: Error) => void\n}\n", "/**\n * AAMP Header Parser\n *\n * Parses AAMP protocol headers from email messages.\n * Works with both raw header objects and JMAP Email objects.\n *\n * Headers are case-insensitive; we normalize to lowercase for lookup.\n */\n\nimport {\n AAMP_HEADER,\n AAMP_PROTOCOL_VERSION,\n type AampMessage,\n type TaskDispatch,\n type TaskCancel,\n type TaskResult,\n type TaskHelp,\n type TaskAck,\n type TaskStreamOpened,\n type CardQuery,\n type CardResponse,\n} from './types.js'\n\ntype RawHeaders = Record<string, string | string[]>\n\nfunction normalizeBodyText(value?: string): string {\n return value?.replace(/\\r\\n/g, '\\n').trim() ?? ''\n}\n\nfunction escapeRegex(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\nfunction extractBodySection(bodyText: string, label: string, nextLabels: string[]): string {\n if (!bodyText) return ''\n const nextPattern = nextLabels.length\n ? `(?=\\\\n(?:${nextLabels.map(escapeRegex).join('|')}):|$)`\n : '$'\n const pattern = new RegExp(\n `(?:^|\\\\n)${escapeRegex(label)}:\\\\s*([\\\\s\\\\S]*?)${nextPattern}`,\n 'i',\n )\n const match = pattern.exec(bodyText)\n return match?.[1]?.trim() ?? ''\n}\n\nfunction parseSuggestedOptionsBlock(block: string): string[] {\n if (!block.trim()) return []\n return block\n .split('\\n')\n .map((line) => line.replace(/^\\s*(?:[-*]|\\d+\\.)\\s*/, '').trim())\n .filter(Boolean)\n}\n\nfunction parseTaskResultBody(bodyText?: string): { output: string; errorMsg?: string } {\n const normalized = normalizeBodyText(bodyText)\n if (!normalized) return { output: '' }\n\n const output = extractBodySection(normalized, 'Output', ['Error'])\n const errorMsg = extractBodySection(normalized, 'Error', [])\n\n if (output || errorMsg) {\n return { output, ...(errorMsg ? { errorMsg } : {}) }\n }\n\n return { output: normalized }\n}\n\nfunction parseTaskHelpBody(bodyText?: string): {\n question: string\n blockedReason: string\n suggestedOptions: string[]\n} {\n const normalized = normalizeBodyText(bodyText)\n if (!normalized) {\n return { question: '', blockedReason: '', suggestedOptions: [] }\n }\n\n const question = extractBodySection(normalized, 'Question', ['Blocked reason', 'Suggested options'])\n const blockedReason = extractBodySection(normalized, 'Blocked reason', ['Suggested options'])\n const suggestedOptions = parseSuggestedOptionsBlock(\n extractBodySection(normalized, 'Suggested options', []),\n )\n\n if (question || blockedReason || suggestedOptions.length) {\n return { question, blockedReason, suggestedOptions }\n }\n\n return { question: normalized, blockedReason: '', suggestedOptions: [] }\n}\n\nfunction decodeMimeEncodedWordSegment(segment: string): string {\n const match = /^=\\?([^?]+)\\?([bBqQ])\\?([^?]*)\\?=$/.exec(segment)\n if (!match) return segment\n\n const [, charsetRaw, encodingRaw, body] = match\n const charset = charsetRaw.toLowerCase()\n const encoding = encodingRaw.toUpperCase()\n\n try {\n if (encoding === 'B') {\n const buf = Buffer.from(body, 'base64')\n return buf.toString(charset === 'utf-8' || charset === 'utf8' ? 'utf8' : 'utf8')\n }\n\n const normalized = body\n .replace(/_/g, ' ')\n .replace(/=([0-9A-Fa-f]{2})/g, (_, hex: string) =>\n String.fromCharCode(parseInt(hex, 16)),\n )\n const bytes = Buffer.from(normalized, 'binary')\n return bytes.toString(charset === 'utf-8' || charset === 'utf8' ? 'utf8' : 'utf8')\n } catch {\n return segment\n }\n}\n\nfunction decodeMimeEncodedWords(value?: string): string {\n if (!value || !value.includes('=?')) return value ?? ''\n const collapsed = value.replace(/\\r?\\n[ \\t]+/g, ' ')\n const decoded = collapsed.replace(/=\\?[^?]+\\?[bBqQ]\\?[^?]*\\?=/g, (segment) =>\n decodeMimeEncodedWordSegment(segment),\n )\n return decoded.replace(/\\s{2,}/g, ' ').trim()\n}\n\n/**\n * Normalize a header map to lowercase keys with string values\n */\nexport function normalizeHeaders(headers: RawHeaders): Record<string, string> {\n return Object.fromEntries(\n Object.entries(headers).map(([k, v]) => [\n k.toLowerCase(),\n Array.isArray(v) ? v[0] : v,\n ]),\n )\n}\n\n/**\n * Get a header value by its X-AAMP-* name (case-insensitive)\n */\nfunction getAampHeader(\n headers: Record<string, string>,\n headerName: string,\n): string | undefined {\n return headers[headerName.toLowerCase()]\n}\n\nconst DISPATCH_CONTEXT_KEY_RE = /^[a-z0-9_-]+$/\n\nexport function parseDispatchContextHeader(value?: string): Record<string, string> | undefined {\n if (!value) return undefined\n const context: Record<string, string> = {}\n\n for (const part of value.split(';')) {\n const segment = part.trim()\n if (!segment) continue\n const eqIdx = segment.indexOf('=')\n if (eqIdx <= 0) continue\n const rawKey = segment.slice(0, eqIdx).trim()\n const rawValue = segment.slice(eqIdx + 1).trim()\n if (!DISPATCH_CONTEXT_KEY_RE.test(rawKey)) continue\n try {\n context[rawKey] = decodeURIComponent(rawValue)\n } catch {\n context[rawKey] = rawValue\n }\n }\n\n return Object.keys(context).length ? context : undefined\n}\n\nexport function serializeDispatchContextHeader(context?: Record<string, string>): string | undefined {\n if (!context) return undefined\n const parts = Object.entries(context)\n .flatMap(([key, value]) => {\n const normalizedKey = key.trim().toLowerCase()\n if (!DISPATCH_CONTEXT_KEY_RE.test(normalizedKey)) return []\n const normalizedValue = String(value ?? '').trim()\n if (!normalizedValue) return []\n return `${normalizedKey}=${encodeURIComponent(normalizedValue)}`\n })\n return parts.length ? parts.join('; ') : undefined\n}\n\nfunction decodeStructuredResult(value?: string): TaskResult['structuredResult'] | undefined {\n if (!value) return undefined\n try {\n const normalized = value.replace(/-/g, '+').replace(/_/g, '/')\n const padding = normalized.length % 4 === 0 ? '' : '='.repeat(4 - (normalized.length % 4))\n const decoded = Buffer.from(normalized + padding, 'base64').toString('utf-8')\n return JSON.parse(decoded) as TaskResult['structuredResult']\n } catch {\n return undefined\n }\n}\n\nfunction encodeStructuredResult(value?: TaskResult['structuredResult']): string | undefined {\n if (!value) return undefined\n const json = JSON.stringify(value)\n return Buffer.from(json, 'utf-8')\n .toString('base64')\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/g, '')\n}\n\nexport interface EmailMetadata {\n from: string\n to: string\n messageId: string\n subject: string\n headers: RawHeaders\n bodyText?: string\n}\n\n/**\n * Parse AAMP headers from an email's header map.\n * Returns null if this email is not an AAMP message.\n *\n * @param meta - Email metadata (from, to, messageId, subject, headers)\n */\nexport function parseAampHeaders(meta: EmailMetadata): AampMessage | null {\n const headers = normalizeHeaders(meta.headers)\n\n const intent = getAampHeader(headers, AAMP_HEADER.INTENT)\n const taskId = getAampHeader(headers, AAMP_HEADER.TASK_ID)\n const protocolVersion = getAampHeader(headers, AAMP_HEADER.VERSION) ?? AAMP_PROTOCOL_VERSION\n\n if (!intent || !taskId) return null\n\n const from = meta.from.replace(/^<|>$/g, '')\n const to = meta.to.replace(/^<|>$/g, '')\n const decodedSubject = decodeMimeEncodedWords(meta.subject)\n\n if (intent === 'task.dispatch') {\n const contextLinksStr = getAampHeader(headers, AAMP_HEADER.CONTEXT_LINKS) ?? ''\n const dispatchContext = parseDispatchContextHeader(\n getAampHeader(headers, AAMP_HEADER.DISPATCH_CONTEXT),\n )\n\n const parentTaskId = getAampHeader(headers, AAMP_HEADER.PARENT_TASK_ID)\n const priority = (getAampHeader(headers, AAMP_HEADER.PRIORITY) ?? 'normal') as TaskDispatch['priority']\n const expiresAt = getAampHeader(headers, AAMP_HEADER.EXPIRES_AT)\n\n const dispatch: TaskDispatch = {\n protocolVersion,\n intent: 'task.dispatch',\n taskId,\n title: decodedSubject.replace(/^\\[AAMP Task\\]\\s*/, '').trim() || 'Untitled Task',\n priority: priority === 'urgent' || priority === 'high' ? priority : 'normal',\n ...(expiresAt ? { expiresAt } : {}),\n contextLinks: contextLinksStr\n ? contextLinksStr.split(',').map((s) => s.trim()).filter(Boolean)\n : [],\n ...(dispatchContext ? { dispatchContext } : {}),\n ...(parentTaskId ? { parentTaskId } : {}),\n from,\n to,\n messageId: meta.messageId,\n subject: meta.subject,\n bodyText: '', // filled in by jmap-push.ts after parsing\n }\n return dispatch\n }\n\n if (intent === 'task.cancel') {\n const cancel: TaskCancel = {\n protocolVersion,\n intent: 'task.cancel',\n taskId,\n from,\n to,\n messageId: meta.messageId,\n subject: meta.subject,\n bodyText: '',\n }\n return cancel\n }\n\n if (intent === 'task.result') {\n const parsedBody = parseTaskResultBody(meta.bodyText)\n const status = (getAampHeader(headers, AAMP_HEADER.STATUS) ?? 'completed') as\n | 'completed'\n | 'rejected'\n const output = getAampHeader(headers, AAMP_HEADER.OUTPUT) ?? parsedBody.output\n const errorMsg = getAampHeader(headers, AAMP_HEADER.ERROR_MSG) ?? parsedBody.errorMsg\n const structuredResult = decodeStructuredResult(\n getAampHeader(headers, AAMP_HEADER.STRUCTURED_RESULT),\n )\n\n const result: TaskResult = {\n protocolVersion,\n intent: 'task.result',\n taskId,\n status,\n output: decodeMimeEncodedWords(output),\n errorMsg: errorMsg ? decodeMimeEncodedWords(errorMsg) : errorMsg,\n structuredResult,\n from,\n to,\n messageId: meta.messageId,\n }\n return result\n }\n\n if (intent === 'task.help_needed') {\n const parsedBody = parseTaskHelpBody(meta.bodyText)\n const question = getAampHeader(headers, AAMP_HEADER.QUESTION) ?? parsedBody.question\n const blockedReason = getAampHeader(headers, AAMP_HEADER.BLOCKED_REASON) ?? parsedBody.blockedReason\n const suggestedOptionsStr = getAampHeader(headers, AAMP_HEADER.SUGGESTED_OPTIONS) ?? ''\n\n const help: TaskHelp = {\n protocolVersion,\n intent: 'task.help_needed',\n taskId,\n question: decodeMimeEncodedWords(question),\n blockedReason: decodeMimeEncodedWords(blockedReason),\n suggestedOptions: suggestedOptionsStr\n ? suggestedOptionsStr.split('|').map((s) => decodeMimeEncodedWords(s.trim())).filter(Boolean)\n : parsedBody.suggestedOptions,\n from,\n to,\n messageId: meta.messageId,\n }\n return help\n }\n\n if (intent === 'task.ack') {\n const ack: TaskAck = {\n protocolVersion,\n intent: 'task.ack',\n taskId,\n from,\n to,\n messageId: meta.messageId,\n }\n return ack\n }\n\n if (intent === 'task.stream.opened') {\n const streamId = getAampHeader(headers, AAMP_HEADER.STREAM_ID) ?? ''\n if (!streamId) return null\n\n const streamOpened: TaskStreamOpened = {\n protocolVersion,\n intent: 'task.stream.opened',\n taskId,\n streamId,\n from,\n to,\n messageId: meta.messageId,\n }\n return streamOpened\n }\n\n if (intent === 'card.query') {\n const cardQuery: CardQuery = {\n protocolVersion,\n intent: 'card.query',\n taskId,\n from,\n to,\n messageId: meta.messageId,\n subject: meta.subject,\n bodyText: '',\n }\n return cardQuery\n }\n\n if (intent === 'card.response') {\n const summary = getAampHeader(headers, AAMP_HEADER.CARD_SUMMARY) ?? ''\n const cardResponse: CardResponse = {\n protocolVersion,\n intent: 'card.response',\n taskId,\n summary: decodeMimeEncodedWords(summary) || decodedSubject.replace(/^\\[AAMP Card\\]\\s*/i, '').trim(),\n from,\n to,\n messageId: meta.messageId,\n subject: meta.subject,\n bodyText: '',\n }\n return cardResponse\n }\n\n return null\n}\n\n/**\n * Build AAMP headers for a task.dispatch email\n */\nexport function buildDispatchHeaders(params: {\n taskId: string\n priority?: TaskDispatch['priority']\n expiresAt?: string\n contextLinks: string[]\n dispatchContext?: Record<string, string>\n parentTaskId?: string\n}): Record<string, string> {\n const headers: Record<string, string> = {\n [AAMP_HEADER.VERSION]: AAMP_PROTOCOL_VERSION,\n [AAMP_HEADER.INTENT]: 'task.dispatch',\n [AAMP_HEADER.TASK_ID]: params.taskId,\n [AAMP_HEADER.PRIORITY]: params.priority ?? 'normal',\n }\n if (params.expiresAt) {\n headers[AAMP_HEADER.EXPIRES_AT] = params.expiresAt\n }\n if (params.contextLinks.length > 0) {\n headers[AAMP_HEADER.CONTEXT_LINKS] = params.contextLinks.join(',')\n }\n const dispatchContext = serializeDispatchContextHeader(params.dispatchContext)\n if (dispatchContext) {\n headers[AAMP_HEADER.DISPATCH_CONTEXT] = dispatchContext\n }\n if (params.parentTaskId) {\n headers[AAMP_HEADER.PARENT_TASK_ID] = params.parentTaskId\n }\n return headers\n}\n\nexport function buildCancelHeaders(params: { taskId: string }): Record<string, string> {\n return {\n [AAMP_HEADER.VERSION]: AAMP_PROTOCOL_VERSION,\n [AAMP_HEADER.INTENT]: 'task.cancel',\n [AAMP_HEADER.TASK_ID]: params.taskId,\n }\n}\n\n/**\n * Build AAMP headers for a task.ack email\n */\nexport function buildAckHeaders(opts: { taskId: string }): Record<string, string> {\n return {\n [AAMP_HEADER.VERSION]: AAMP_PROTOCOL_VERSION,\n [AAMP_HEADER.INTENT]: 'task.ack',\n [AAMP_HEADER.TASK_ID]: opts.taskId,\n }\n}\n\nexport function buildStreamOpenedHeaders(opts: {\n taskId: string\n streamId: string\n}): Record<string, string> {\n return {\n [AAMP_HEADER.VERSION]: AAMP_PROTOCOL_VERSION,\n [AAMP_HEADER.INTENT]: 'task.stream.opened',\n [AAMP_HEADER.TASK_ID]: opts.taskId,\n [AAMP_HEADER.STREAM_ID]: opts.streamId,\n }\n}\n\n/**\n * Build AAMP headers for a task.result email\n */\nexport function buildResultHeaders(params: {\n taskId: string\n status: 'completed' | 'rejected'\n output: string\n errorMsg?: string\n structuredResult?: TaskResult['structuredResult']\n}): Record<string, string> {\n const headers: Record<string, string> = {\n [AAMP_HEADER.VERSION]: AAMP_PROTOCOL_VERSION,\n [AAMP_HEADER.INTENT]: 'task.result',\n [AAMP_HEADER.TASK_ID]: params.taskId,\n [AAMP_HEADER.STATUS]: params.status,\n }\n const structuredResult = encodeStructuredResult(params.structuredResult)\n if (structuredResult) {\n headers[AAMP_HEADER.STRUCTURED_RESULT] = structuredResult\n }\n return headers\n}\n\n/**\n * Build AAMP headers for a task.help_needed email\n */\nexport function buildHelpHeaders(params: {\n taskId: string\n question: string\n blockedReason: string\n suggestedOptions: string[]\n}): Record<string, string> {\n return {\n [AAMP_HEADER.VERSION]: AAMP_PROTOCOL_VERSION,\n [AAMP_HEADER.INTENT]: 'task.help_needed',\n [AAMP_HEADER.TASK_ID]: params.taskId,\n [AAMP_HEADER.SUGGESTED_OPTIONS]: params.suggestedOptions.join('|'),\n }\n}\n\nexport function buildCardQueryHeaders(params: {\n taskId: string\n}): Record<string, string> {\n return {\n [AAMP_HEADER.VERSION]: AAMP_PROTOCOL_VERSION,\n [AAMP_HEADER.INTENT]: 'card.query',\n [AAMP_HEADER.TASK_ID]: params.taskId,\n }\n}\n\nexport function buildCardResponseHeaders(params: {\n taskId: string\n summary: string\n}): Record<string, string> {\n return {\n [AAMP_HEADER.VERSION]: AAMP_PROTOCOL_VERSION,\n [AAMP_HEADER.INTENT]: 'card.response',\n [AAMP_HEADER.TASK_ID]: params.taskId,\n [AAMP_HEADER.CARD_SUMMARY]: params.summary,\n }\n}\n", "type Listener = (...args: unknown[]) => unknown\ntype EventListener<Events, K extends keyof Events> =\n Extract<Events[K], (...args: any[]) => void>\ntype EventArgs<Events, K extends keyof Events> =\n EventListener<Events, K> extends (...args: infer A) => void ? A : never\n\nexport class TinyEmitter<Events extends object> {\n private readonly listeners = new Map<keyof Events, Set<Listener>>()\n private readonly onceWrappers = new WeakMap<Listener, Listener>()\n\n on<K extends keyof Events>(event: K, listener: EventListener<Events, K>): this {\n const bucket = this.listeners.get(event) ?? new Set<Listener>()\n bucket.add(listener as Listener)\n this.listeners.set(event, bucket)\n return this\n }\n\n once<K extends keyof Events>(event: K, listener: EventListener<Events, K>): this {\n const wrapped: Listener = (...args: unknown[]) => {\n this.off(event, listener)\n ;(listener as Listener)(...args)\n }\n this.onceWrappers.set(listener as Listener, wrapped)\n return this.on(event, wrapped as EventListener<Events, K>)\n }\n\n off<K extends keyof Events>(event: K, listener: EventListener<Events, K>): this {\n const bucket = this.listeners.get(event)\n if (!bucket) return this\n\n const original = listener as Listener\n const wrapped = this.onceWrappers.get(original)\n bucket.delete(wrapped ?? original)\n if (wrapped) this.onceWrappers.delete(original)\n if (bucket.size === 0) this.listeners.delete(event)\n return this\n }\n\n protected emit<K extends keyof Events>(event: K, ...args: EventArgs<Events, K>): boolean {\n const bucket = this.listeners.get(event)\n if (!bucket || bucket.size === 0) return false\n\n for (const listener of [...bucket]) {\n listener(...args)\n }\n return true\n }\n\n protected async emitAsync<K extends keyof Events>(event: K, ...args: EventArgs<Events, K>): Promise<boolean> {\n const bucket = this.listeners.get(event)\n if (!bucket || bucket.size === 0) return false\n\n const settled = await Promise.allSettled(\n [...bucket].map((listener) => Promise.resolve(listener(...args))),\n )\n const rejected = settled.find(\n (result): result is PromiseRejectedResult => result.status === 'rejected',\n )\n if (rejected) {\n throw rejected.reason\n }\n return true\n }\n}\n", "/**\n * SMTP Sender\n *\n * Sends AAMP protocol emails via SMTP (Stalwart submission port 587).\n */\n\nimport { createTransport, type Transporter } from 'nodemailer'\nimport { randomUUID } from 'crypto'\n\n/** Strip CR/LF to prevent email header injection */\nconst sanitize = (s: string) => s.replace(/[\\r\\n]/g, ' ').trim()\nimport {\n buildDispatchHeaders,\n buildCancelHeaders,\n buildResultHeaders,\n buildHelpHeaders,\n buildAckHeaders,\n buildStreamOpenedHeaders,\n buildCardQueryHeaders,\n buildCardResponseHeaders,\n} from './parser.js'\nimport type {\n SendTaskOptions,\n SendResultOptions,\n SendHelpOptions,\n SendCardQueryOptions,\n SendCardResponseOptions,\n SendCancelOptions,\n} from './types.js'\n\nexport interface SmtpConfig {\n host: string\n port: number\n user: string\n password: string\n httpBaseUrl?: string\n authToken?: string\n secure?: boolean\n /** Whether to reject unauthorized TLS certificates (default: true) */\n rejectUnauthorized?: boolean\n}\n\nexport interface MailboxIdentityConfig {\n email: string\n password: string\n baseUrl?: string\n smtpPort?: number\n secure?: boolean\n rejectUnauthorized?: boolean\n}\n\nexport function deriveMailboxServiceDefaults(email: string, baseUrl?: string): {\n smtpHost: string\n httpBaseUrl?: string\n} {\n const domain = email.split('@')[1]?.trim()\n const resolvedBaseUrl = baseUrl?.trim() || (domain ? `https://${domain}` : undefined)\n const smtpHost = domain || (resolvedBaseUrl ? new URL(resolvedBaseUrl).hostname : 'localhost')\n return {\n smtpHost,\n httpBaseUrl: resolvedBaseUrl,\n }\n}\n\nexport class SmtpSender {\n private transport: Transporter\n private discoveredApiUrlPromise: Promise<string> | null = null\n private jmapSessionPromise: Promise<{\n accountId: string\n apiUrl: string\n }> | null = null\n private sentMailboxIdPromise: Promise<string | null> | null = null\n\n static fromMailboxIdentity(config: MailboxIdentityConfig): SmtpSender {\n const derived = deriveMailboxServiceDefaults(config.email, config.baseUrl)\n return new SmtpSender({\n host: derived.smtpHost,\n port: config.smtpPort ?? 587,\n user: config.email,\n password: config.password,\n httpBaseUrl: derived.httpBaseUrl,\n authToken: Buffer.from(`${config.email}:${config.password}`).toString('base64'),\n secure: config.secure,\n rejectUnauthorized: config.rejectUnauthorized,\n })\n }\n\n constructor(private readonly config: SmtpConfig) {\n this.transport = createTransport({\n host: config.host,\n port: config.port,\n secure: config.secure ?? false,\n auth: {\n user: config.user,\n pass: config.password,\n },\n tls: {\n rejectUnauthorized: config.rejectUnauthorized ?? true,\n },\n })\n }\n\n private senderDomain(): string {\n return this.config.user.split('@')[1]?.toLowerCase() ?? ''\n }\n\n private recipientDomain(email: string): string {\n return email.split('@')[1]?.toLowerCase() ?? ''\n }\n\n private shouldUseHttpFallback(to: string): boolean {\n return Boolean(\n this.config.httpBaseUrl\n && this.config.authToken\n && this.senderDomain()\n && this.senderDomain() === this.recipientDomain(to),\n )\n }\n\n private async resolveAampApiUrl(): Promise<string> {\n const base = this.config.httpBaseUrl?.replace(/\\/$/, '')\n if (!base) {\n throw new Error('HTTP send fallback is not configured')\n }\n\n if (!this.discoveredApiUrlPromise) {\n this.discoveredApiUrlPromise = (async () => {\n const discoveryRes = await fetch(`${base}/.well-known/aamp`)\n if (!discoveryRes.ok) {\n throw new Error(`AAMP discovery failed: ${discoveryRes.status}`)\n }\n const discovery = await discoveryRes.json() as { api?: { url?: string } }\n if (!discovery.api?.url) {\n throw new Error('AAMP discovery did not return api.url')\n }\n return new URL(discovery.api.url, `${base}/`).toString()\n })()\n }\n\n try {\n return await this.discoveredApiUrlPromise\n } catch (err) {\n this.discoveredApiUrlPromise = null\n throw err\n }\n }\n\n private async sendViaHttp(opts: {\n to: string\n subject: string\n text: string\n aampHeaders: Record<string, string>\n attachments?: Array<{ filename: string; contentType: string; content: Buffer | string }>\n }): Promise<{ messageId?: string }> {\n if (!this.config.authToken) {\n throw new Error('HTTP send fallback is not configured')\n }\n const apiUrl = new URL(await this.resolveAampApiUrl())\n apiUrl.searchParams.set('action', 'aamp.mailbox.send')\n\n const res = await fetch(apiUrl, {\n method: 'POST',\n headers: {\n Authorization: `Basic ${this.config.authToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n to: opts.to,\n subject: opts.subject,\n text: opts.text,\n aampHeaders: opts.aampHeaders,\n attachments: opts.attachments?.map((a) => ({\n filename: a.filename,\n contentType: a.contentType,\n content: typeof a.content === 'string' ? a.content : a.content.toString('base64'),\n })),\n }),\n })\n\n const data = await res.json().catch(() => ({})) as { details?: string; messageId?: string }\n if (!res.ok) {\n throw new Error(data.details || `HTTP send failed: ${res.status}`)\n }\n return { messageId: data.messageId }\n }\n\n private canPersistSentCopy(): boolean {\n return Boolean(this.config.httpBaseUrl && this.config.authToken)\n }\n\n private getJmapAuthHeader(): string {\n if (!this.config.authToken) {\n throw new Error('JMAP auth token is not configured')\n }\n return `Basic ${this.config.authToken}`\n }\n\n private async resolveJmapSession(): Promise<{ accountId: string; apiUrl: string }> {\n const base = this.config.httpBaseUrl?.replace(/\\/$/, '')\n if (!base) {\n throw new Error('JMAP base URL is not configured')\n }\n\n if (!this.jmapSessionPromise) {\n this.jmapSessionPromise = (async () => {\n const res = await fetch(`${base}/.well-known/jmap`, {\n headers: { Authorization: this.getJmapAuthHeader() },\n })\n if (!res.ok) {\n throw new Error(`JMAP session failed: ${res.status} ${res.statusText}`)\n }\n\n const session = await res.json() as {\n accounts?: Record<string, unknown>\n primaryAccounts?: Record<string, string>\n }\n const accountId =\n session.primaryAccounts?.['urn:ietf:params:jmap:mail']\n ?? Object.keys(session.accounts ?? {})[0]\n\n if (!accountId) {\n throw new Error('No JMAP mail account available')\n }\n\n return {\n accountId,\n apiUrl: `${base}/jmap/`,\n }\n })()\n }\n\n try {\n return await this.jmapSessionPromise\n } catch (err) {\n this.jmapSessionPromise = null\n throw err\n }\n }\n\n private async jmapCall(\n methodCalls: Array<[string, Record<string, unknown>, string]>,\n ): Promise<Array<[string, Record<string, unknown>, string]>> {\n const session = await this.resolveJmapSession()\n const res = await fetch(session.apiUrl, {\n method: 'POST',\n headers: {\n Authorization: this.getJmapAuthHeader(),\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n using: [\n 'urn:ietf:params:jmap:core',\n 'urn:ietf:params:jmap:mail',\n ],\n methodCalls: methodCalls.map(([name, args, tag]) => [\n name,\n { accountId: session.accountId, ...args },\n tag,\n ]),\n }),\n })\n\n if (!res.ok) {\n throw new Error(`JMAP API call failed: ${res.status}`)\n }\n\n const data = await res.json() as {\n methodResponses?: Array<[string, Record<string, unknown>, string]>\n }\n return data.methodResponses ?? []\n }\n\n private async getSentMailboxId(): Promise<string | null> {\n if (!this.sentMailboxIdPromise) {\n this.sentMailboxIdPromise = (async () => {\n const responses = await this.jmapCall([\n ['Mailbox/get', { ids: null }, 'mb1'],\n ])\n const result = responses.find(([name]) => name === 'Mailbox/get')?.[1] as\n | { list?: Array<{ id: string; role: string | null }> }\n | undefined\n const mailboxes = result?.list ?? []\n return mailboxes.find((mailbox) => mailbox.role === 'sent')?.id ?? mailboxes[0]?.id ?? null\n })()\n }\n\n try {\n return await this.sentMailboxIdPromise\n } catch (err) {\n this.sentMailboxIdPromise = null\n throw err\n }\n }\n\n private async saveToSent(params: {\n from: string\n to: string\n subject: string\n text: string\n aampHeaders: Record<string, string>\n messageId?: string\n inReplyTo?: string\n references?: string\n }): Promise<void> {\n if (!this.canPersistSentCopy()) return\n\n const sentMailboxId = await this.getSentMailboxId()\n if (!sentMailboxId) return\n\n const emailCreate: Record<string, unknown> = {\n mailboxIds: { [sentMailboxId]: true },\n from: [{ email: params.from }],\n to: [{ email: params.to }],\n subject: params.subject,\n bodyValues: {\n body: {\n value: params.text,\n charset: 'utf-8',\n },\n },\n textBody: [{ partId: 'body', type: 'text/plain' }],\n keywords: { '$seen': true },\n }\n\n if (params.inReplyTo) {\n emailCreate['header:In-Reply-To:asText'] = ` ${sanitize(params.inReplyTo)}`\n }\n if (params.messageId) {\n emailCreate['header:Message-ID:asText'] = ` ${sanitize(params.messageId)}`\n }\n if (params.references) {\n emailCreate['header:References:asText'] = ` ${sanitize(params.references)}`\n }\n for (const [name, value] of Object.entries(params.aampHeaders)) {\n emailCreate[`header:${name}:asText`] = ` ${value}`\n }\n\n await this.jmapCall([\n ['Email/set', { create: { sent1: emailCreate } }, 'sent1'],\n ])\n }\n\n private async saveToSentBestEffort(params: {\n from: string\n to: string\n subject: string\n text: string\n aampHeaders: Record<string, string>\n messageId?: string\n inReplyTo?: string\n references?: string\n }): Promise<void> {\n if (!this.canPersistSentCopy()) return\n try {\n await this.saveToSent(params)\n } catch {\n // Non-fatal: mail delivery already succeeded, Sent copy is only for visibility/debugging.\n }\n }\n\n /**\n * Send a task.dispatch email.\n * Returns both the generated taskId and the SMTP Message-ID so callers can\n * store a reverse-index (messageId \u2192 taskId) for In-Reply-To thread routing.\n */\n async sendTask(opts: SendTaskOptions): Promise<{ taskId: string; messageId: string }> {\n const taskId = opts.taskId ?? randomUUID()\n const aampHeaders = buildDispatchHeaders({\n taskId,\n priority: opts.priority,\n expiresAt: opts.expiresAt,\n contextLinks: opts.contextLinks ?? [],\n dispatchContext: opts.dispatchContext,\n parentTaskId: opts.parentTaskId,\n })\n\n const sendMailOpts: Record<string, unknown> = {\n from: this.config.user,\n to: opts.to,\n subject: `[AAMP Task] ${sanitize(opts.title)}`,\n text: opts.rawBodyText ?? [\n `Task: ${opts.title}`,\n `Task ID: ${taskId}`,\n `Priority: ${opts.priority ?? 'normal'}`,\n opts.expiresAt ? `Expires At: ${opts.expiresAt}` : `Expires At: none`,\n opts.contextLinks?.length\n ? `Context:\\n${opts.contextLinks.map((l) => ` ${l}`).join('\\n')}`\n : '',\n opts.bodyText ?? '',\n ``,\n `--- This email was sent by AAMP. Reply directly to submit your result. ---`,\n ]\n .filter(Boolean)\n .join('\\n'),\n headers: aampHeaders,\n }\n\n if (opts.attachments?.length) {\n sendMailOpts.attachments = opts.attachments.map(a => ({\n filename: a.filename,\n content: typeof a.content === 'string' ? Buffer.from(a.content, 'base64') : a.content,\n contentType: a.contentType,\n }))\n }\n\n if (this.shouldUseHttpFallback(opts.to)) {\n const info = await this.sendViaHttp({\n to: opts.to,\n subject: sendMailOpts.subject as string,\n text: sendMailOpts.text as string,\n aampHeaders,\n attachments: opts.attachments?.map(a => ({\n filename: a.filename,\n contentType: a.contentType,\n content: typeof a.content === 'string' ? Buffer.from(a.content, 'base64') : a.content,\n })),\n })\n await this.saveToSentBestEffort({\n from: this.config.user,\n to: opts.to,\n subject: sendMailOpts.subject as string,\n text: sendMailOpts.text as string,\n aampHeaders,\n messageId: info.messageId,\n })\n return { taskId, messageId: info.messageId ?? '' }\n }\n\n const info = await this.transport.sendMail(sendMailOpts)\n await this.saveToSentBestEffort({\n from: this.config.user,\n to: opts.to,\n subject: sendMailOpts.subject as string,\n text: sendMailOpts.text as string,\n aampHeaders,\n messageId: info.messageId,\n })\n\n return { taskId, messageId: info.messageId ?? '' }\n }\n\n /**\n * Send a task.result email back to the dispatcher\n */\n async sendResult(opts: SendResultOptions): Promise<void> {\n const aampHeaders = buildResultHeaders({\n taskId: opts.taskId,\n status: opts.status,\n output: opts.output,\n errorMsg: opts.errorMsg,\n structuredResult: opts.structuredResult,\n })\n\n const mailOpts: Record<string, unknown> = {\n from: this.config.user,\n to: opts.to,\n subject: `[AAMP Result] Task ${opts.taskId} \u2014 ${opts.status}`,\n text: opts.rawBodyText ?? [\n `AAMP Task Result`,\n ``,\n `Task ID: ${opts.taskId}`,\n `Status: ${opts.status}`,\n ``,\n `Output:`,\n opts.output,\n opts.errorMsg ? `\\nError: ${opts.errorMsg}` : '',\n ]\n .filter((s) => s !== '')\n .join('\\n'),\n headers: aampHeaders,\n }\n if (opts.inReplyTo) {\n mailOpts.inReplyTo = opts.inReplyTo\n mailOpts.references = opts.inReplyTo\n }\n if (opts.attachments?.length) {\n mailOpts.attachments = opts.attachments.map(a => ({\n filename: a.filename,\n content: typeof a.content === 'string' ? Buffer.from(a.content, 'base64') : a.content,\n contentType: a.contentType,\n }))\n }\n\n if (this.shouldUseHttpFallback(opts.to)) {\n const info = await this.sendViaHttp({\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n attachments: opts.attachments?.map(a => ({\n filename: a.filename,\n contentType: a.contentType,\n content: typeof a.content === 'string' ? Buffer.from(a.content, 'base64') : a.content,\n })),\n })\n await this.saveToSentBestEffort({\n from: this.config.user,\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n messageId: info.messageId,\n inReplyTo: opts.inReplyTo,\n references: opts.inReplyTo,\n })\n return\n }\n const info = await this.transport.sendMail(mailOpts)\n await this.saveToSentBestEffort({\n from: this.config.user,\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n messageId: info.messageId,\n inReplyTo: opts.inReplyTo,\n references: opts.inReplyTo,\n })\n }\n\n /**\n * Send a task.help_needed email when the agent is blocked\n */\n async sendHelp(opts: SendHelpOptions): Promise<void> {\n const aampHeaders = buildHelpHeaders({\n taskId: opts.taskId,\n question: opts.question,\n blockedReason: opts.blockedReason,\n suggestedOptions: opts.suggestedOptions,\n })\n\n const helpMailOpts: Record<string, unknown> = {\n from: this.config.user,\n to: opts.to,\n subject: `[AAMP Help] Task ${opts.taskId} needs assistance`,\n text: opts.rawBodyText ?? [\n `AAMP Task Help Request`,\n ``,\n `Task ID: ${opts.taskId}`,\n ``,\n `Question: ${opts.question}`,\n ``,\n `Blocked reason: ${opts.blockedReason}`,\n ``,\n opts.suggestedOptions.length\n ? `Suggested options:\\n${opts.suggestedOptions.map((o, i) => ` ${i + 1}. ${o}`).join('\\n')}`\n : '',\n ]\n .filter(Boolean)\n .join('\\n'),\n headers: aampHeaders,\n }\n if (opts.inReplyTo) {\n helpMailOpts.inReplyTo = opts.inReplyTo\n helpMailOpts.references = opts.inReplyTo\n }\n if (opts.attachments?.length) {\n helpMailOpts.attachments = opts.attachments.map(a => ({\n filename: a.filename,\n content: typeof a.content === 'string' ? Buffer.from(a.content, 'base64') : a.content,\n contentType: a.contentType,\n }))\n }\n\n if (this.shouldUseHttpFallback(opts.to)) {\n const info = await this.sendViaHttp({\n to: opts.to,\n subject: helpMailOpts.subject as string,\n text: helpMailOpts.text as string,\n aampHeaders,\n attachments: opts.attachments?.map(a => ({\n filename: a.filename,\n contentType: a.contentType,\n content: typeof a.content === 'string' ? Buffer.from(a.content, 'base64') : a.content,\n })),\n })\n await this.saveToSentBestEffort({\n from: this.config.user,\n to: opts.to,\n subject: helpMailOpts.subject as string,\n text: helpMailOpts.text as string,\n aampHeaders,\n messageId: info.messageId,\n inReplyTo: opts.inReplyTo,\n references: opts.inReplyTo,\n })\n return\n }\n const info = await this.transport.sendMail(helpMailOpts)\n await this.saveToSentBestEffort({\n from: this.config.user,\n to: opts.to,\n subject: helpMailOpts.subject as string,\n text: helpMailOpts.text as string,\n aampHeaders,\n messageId: info.messageId,\n inReplyTo: opts.inReplyTo,\n references: opts.inReplyTo,\n })\n }\n\n /**\n * Send a task.cancel email to stop a previously dispatched task.\n */\n async sendCancel(opts: SendCancelOptions): Promise<void> {\n const aampHeaders = buildCancelHeaders({\n taskId: opts.taskId,\n })\n\n const mailOpts: Record<string, unknown> = {\n from: this.config.user,\n to: opts.to,\n subject: `[AAMP Cancel] Task ${opts.taskId}`,\n text: opts.bodyText ?? 'The dispatcher cancelled this task.',\n headers: aampHeaders,\n }\n if (opts.inReplyTo) {\n mailOpts.inReplyTo = opts.inReplyTo\n mailOpts.references = opts.inReplyTo\n }\n\n if (this.shouldUseHttpFallback(opts.to)) {\n const info = await this.sendViaHttp({\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n })\n await this.saveToSentBestEffort({\n from: this.config.user,\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n messageId: info.messageId,\n inReplyTo: opts.inReplyTo,\n references: opts.inReplyTo,\n })\n return\n }\n const info = await this.transport.sendMail(mailOpts)\n await this.saveToSentBestEffort({\n from: this.config.user,\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n messageId: info.messageId,\n inReplyTo: opts.inReplyTo,\n references: opts.inReplyTo,\n })\n }\n\n /**\n * Send a task.ack email to confirm receipt of a dispatch\n */\n async sendAck(opts: { to: string; taskId: string; inReplyTo?: string }): Promise<void> {\n const aampHeaders = buildAckHeaders({ taskId: opts.taskId })\n const mailOpts: Record<string, unknown> = {\n from: this.config.user,\n to: opts.to,\n subject: `[AAMP ACK] Task ${opts.taskId}`,\n text: '',\n headers: aampHeaders,\n }\n if (opts.inReplyTo) {\n mailOpts.inReplyTo = opts.inReplyTo\n mailOpts.references = opts.inReplyTo\n }\n\n if (this.shouldUseHttpFallback(opts.to)) {\n const info = await this.sendViaHttp({\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n })\n await this.saveToSentBestEffort({\n from: this.config.user,\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n messageId: info.messageId,\n inReplyTo: opts.inReplyTo,\n references: opts.inReplyTo,\n })\n return\n }\n const info = await this.transport.sendMail(mailOpts)\n await this.saveToSentBestEffort({\n from: this.config.user,\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n messageId: info.messageId,\n inReplyTo: opts.inReplyTo,\n references: opts.inReplyTo,\n })\n }\n\n async sendStreamOpened(opts: {\n to: string\n taskId: string\n streamId: string\n inReplyTo?: string\n }): Promise<void> {\n const aampHeaders = buildStreamOpenedHeaders({\n taskId: opts.taskId,\n streamId: opts.streamId,\n })\n const mailOpts: Record<string, unknown> = {\n from: this.config.user,\n to: opts.to,\n subject: `[AAMP Stream] Task ${opts.taskId}`,\n text: `AAMP task stream is ready.\\n\\nTask ID: ${opts.taskId}\\nStream ID: ${opts.streamId}`,\n headers: aampHeaders,\n }\n if (opts.inReplyTo) {\n mailOpts.inReplyTo = opts.inReplyTo\n mailOpts.references = opts.inReplyTo\n }\n\n if (this.shouldUseHttpFallback(opts.to)) {\n const info = await this.sendViaHttp({\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n })\n await this.saveToSentBestEffort({\n from: this.config.user,\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n messageId: info.messageId,\n inReplyTo: opts.inReplyTo,\n references: opts.inReplyTo,\n })\n return\n }\n\n const info = await this.transport.sendMail(mailOpts)\n await this.saveToSentBestEffort({\n from: this.config.user,\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n messageId: info.messageId,\n inReplyTo: opts.inReplyTo,\n references: opts.inReplyTo,\n })\n }\n\n async sendCardQuery(opts: SendCardQueryOptions): Promise<{ taskId: string; messageId: string }> {\n const taskId = opts.taskId ?? randomUUID()\n const aampHeaders = buildCardQueryHeaders({ taskId })\n const mailOpts: Record<string, unknown> = {\n from: this.config.user,\n to: opts.to,\n subject: `[AAMP Card Query] ${taskId}`,\n text: opts.bodyText?.trim() || 'Please share your agent card and capability details.',\n headers: aampHeaders,\n }\n if (opts.inReplyTo) {\n mailOpts.inReplyTo = opts.inReplyTo\n mailOpts.references = opts.inReplyTo\n }\n\n if (this.shouldUseHttpFallback(opts.to)) {\n const info = await this.sendViaHttp({\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n })\n await this.saveToSentBestEffort({\n from: this.config.user,\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n messageId: info.messageId,\n inReplyTo: opts.inReplyTo,\n references: opts.inReplyTo,\n })\n return { taskId, messageId: info.messageId ?? '' }\n }\n\n const info = await this.transport.sendMail(mailOpts)\n await this.saveToSentBestEffort({\n from: this.config.user,\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n messageId: info.messageId,\n inReplyTo: opts.inReplyTo,\n references: opts.inReplyTo,\n })\n return { taskId, messageId: info.messageId ?? '' }\n }\n\n async sendCardResponse(opts: SendCardResponseOptions): Promise<void> {\n const aampHeaders = buildCardResponseHeaders({\n taskId: opts.taskId,\n summary: opts.summary,\n })\n const mailOpts: Record<string, unknown> = {\n from: this.config.user,\n to: opts.to,\n subject: `[AAMP Card] ${sanitize(opts.summary)}`,\n text: opts.bodyText,\n headers: aampHeaders,\n }\n if (opts.inReplyTo) {\n mailOpts.inReplyTo = opts.inReplyTo\n mailOpts.references = opts.inReplyTo\n }\n\n if (this.shouldUseHttpFallback(opts.to)) {\n const info = await this.sendViaHttp({\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n })\n await this.saveToSentBestEffort({\n from: this.config.user,\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n messageId: info.messageId,\n inReplyTo: opts.inReplyTo,\n references: opts.inReplyTo,\n })\n return\n }\n\n const info = await this.transport.sendMail(mailOpts)\n await this.saveToSentBestEffort({\n from: this.config.user,\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n messageId: info.messageId,\n inReplyTo: opts.inReplyTo,\n references: opts.inReplyTo,\n })\n }\n\n /**\n * Verify SMTP connection\n */\n async verify(): Promise<boolean> {\n try {\n await this.transport.verify()\n return true\n } catch {\n return false\n }\n }\n\n close(): void {\n this.transport.close()\n }\n}\n", "function singleLine(value, maxLength = 220) {\n const normalized = (value ?? '').replace(/\\s+/g, ' ').trim();\n if (!normalized)\n return '';\n if (normalized.length <= maxLength)\n return normalized;\n return `${normalized.slice(0, maxLength - 1)}\u2026`;\n}\nfunction formatTimestamp(value) {\n const date = new Date(value);\n if (Number.isNaN(date.getTime()))\n return value;\n return date.toISOString().slice(0, 16).replace('T', ' ');\n}\nfunction renderEventLine(event) {\n const from = event.from.split('@')[0] || event.from;\n const timestamp = formatTimestamp(event.createdAt);\n if (event.intent === 'task.dispatch') {\n const summary = singleLine(event.bodyText) || singleLine(event.title) || 'Task dispatched';\n return `[${timestamp}] ${from} dispatched: ${summary}`;\n }\n if (event.intent === 'task.help_needed') {\n const question = singleLine(event.question) || 'Asked for help';\n const reason = singleLine(event.blockedReason);\n return `[${timestamp}] ${from} asked for help: ${question}${reason ? ` (reason: ${reason})` : ''}`;\n }\n if (event.intent === 'task.result') {\n const output = singleLine(event.output) || singleLine(event.bodyText) || 'Sent a result';\n return `[${timestamp}] ${from} replied: ${output}`;\n }\n if (event.intent === 'task.cancel') {\n const body = singleLine(event.bodyText) || 'Cancelled the task';\n return `[${timestamp}] ${from} cancelled the task: ${body}`;\n }\n if (event.intent === 'task.ack') {\n return `[${timestamp}] ${from} acknowledged the task`;\n }\n return `[${timestamp}] ${from}: ${singleLine(event.bodyText) || event.intent}`;\n}\nexport function renderThreadHistoryForAgent(events, options = {}) {\n const filtered = events.filter((event) => event.intent !== 'task.stream.opened');\n if (filtered.length === 0)\n return '';\n const maxEvents = Math.max(1, options.maxEvents ?? 8);\n const visible = filtered.slice(-maxEvents);\n const omitted = filtered.length - visible.length;\n return [\n 'Prior thread context:',\n ...(omitted > 0 ? [`(${omitted} earlier event(s) omitted)`] : []),\n ...visible.map((event) => `- ${renderEventLine(event)}`),\n ].join('\\n');\n}\n//# sourceMappingURL=thread.js.map", "/**\n * AampClient \u2014 Main SDK entry point\n *\n * Combines JMAP WebSocket Push (receive) + SMTP (send) into a single client.\n *\n * Usage:\n *\n * ```typescript\n * const client = new AampClient({\n * email: 'codereviewer-abc@aamp.example.com',\n * mailboxToken: '<base64(email:password)>',\n * baseUrl: 'https://meshmail.ai',\n * smtpPort: 587,\n * smtpPassword: 'agent-smtp-password',\n * })\n *\n * // Listen for incoming tasks\n * client.on('task.dispatch', async (task) => {\n * const result = await doWork(task)\n * await client.sendResult({\n * to: task.from,\n * taskId: task.taskId,\n * status: 'completed',\n * output: result,\n * })\n * })\n *\n * await client.connect()\n * ```\n */\n\nimport { JmapPushClient } from './jmap-push.js'\nimport { SmtpSender, deriveMailboxServiceDefaults } from './smtp-sender.js'\nimport { TinyEmitter } from './tiny-emitter.js'\nimport { renderThreadHistoryForAgent } from './thread.js'\nimport type {\n AampClientConfig,\n AampClientEvents,\n AampDiscoveryDocument,\n AgentDirectoryEntry,\n AgentDirectoryProfile,\n AgentDirectorySearchEntry,\n AampThreadEvent,\n AampMailboxIdentityConfig,\n AampStreamEvent,\n CardQuery,\n CardResponse,\n CloseStreamOptions,\n CreateStreamOptions,\n CreateStreamResult,\n DirectoryListOptions,\n DirectorySearchOptions,\n GetTaskStreamOptions,\n GetThreadHistoryOptions,\n HydratedTaskDispatch,\n RegisterMailboxOptions,\n RegisteredMailboxIdentity,\n RegisteredCommandDispatchPayload,\n SendCardQueryOptions,\n SendCardResponseOptions,\n SendCancelOptions,\n SendRegisteredCommandOptions,\n StreamSubscription,\n TaskCancel,\n TaskDispatch,\n TaskThreadHistory,\n TaskResult,\n TaskHelp,\n TaskAck,\n TaskStreamOpened,\n TaskStreamState,\n HumanReply,\n SendTaskOptions,\n SendResultOptions,\n SendHelpOptions,\n UpdateDirectoryProfileOptions,\n} from './types.js'\n\nfunction buildRegisteredCommandDispatchPayload(\n opts: Pick<SendRegisteredCommandOptions, 'command' | 'args' | 'inputs' | 'streamMode'>,\n): RegisteredCommandDispatchPayload {\n const command = opts.command.trim()\n if (!command) {\n throw new Error('Registered command name cannot be empty.')\n }\n\n if (opts.args != null && (typeof opts.args !== 'object' || Array.isArray(opts.args))) {\n throw new Error('Registered command args must be an object when provided.')\n }\n\n if (opts.inputs) {\n for (const input of opts.inputs) {\n if (!input.slot?.trim() || !input.attachmentName?.trim()) {\n throw new Error('Each registered command input must include slot and attachmentName.')\n }\n }\n }\n\n return {\n kind: 'registered-command/v1',\n command,\n ...(opts.args && Object.keys(opts.args).length > 0 ? { args: opts.args } : {}),\n ...(opts.inputs?.length ? { inputs: opts.inputs } : {}),\n stream: { mode: opts.streamMode ?? 'full' },\n }\n}\n\nconst DEFAULT_TASK_DISPATCH_CONCURRENCY = 10\n\nfunction normalizeTaskDispatchConcurrency(value: number | undefined): number {\n if (value == null) return DEFAULT_TASK_DISPATCH_CONCURRENCY\n\n if (!Number.isFinite(value) || !Number.isInteger(value) || value < 1) {\n throw new Error('taskDispatchConcurrency must be a positive integer')\n }\n\n return value\n}\n\ntype StreamAppendOperation =\n | {\n kind: 'text-delta-batch'\n text: string\n payload: Record<string, unknown>\n resolvers: Array<(event: AampStreamEvent) => void>\n rejecters: Array<(error: unknown) => void>\n }\n | {\n kind: 'single-event'\n opts: {\n streamId: string\n type: AampStreamEvent['type']\n payload: Record<string, unknown>\n }\n resolve: (event: AampStreamEvent) => void\n reject: (error: unknown) => void\n }\n\nexport class AampClient extends TinyEmitter<AampClientEvents> {\n private jmapClient: JmapPushClient\n private smtpSender: SmtpSender\n private readonly config: AampClientConfig\n private readonly taskDispatchConcurrency: number\n private readonly pendingTaskDispatches: TaskDispatch[] = []\n private activeTaskDispatchCount = 0\n private readonly streamAppendQueues = new Map<string, {\n running: boolean\n operations: StreamAppendOperation[]\n }>()\n\n constructor(config: AampClientConfig) {\n super()\n this.config = config\n this.taskDispatchConcurrency = normalizeTaskDispatchConcurrency(config.taskDispatchConcurrency)\n\n const mailboxToken = config.mailboxToken\n const resolvedBaseUrl = config.baseUrl\n const derived = deriveMailboxServiceDefaults(config.email, resolvedBaseUrl)\n const smtpHost = config.smtpHost ?? derived.smtpHost\n\n // Decode mailbox token (format: base64(email:password))\n let password: string\n try {\n const decoded = Buffer.from(mailboxToken, 'base64').toString('utf-8')\n const colonIdx = decoded.indexOf(':')\n if (colonIdx < 0) throw new Error('Invalid mailboxToken format: expected base64(email:password)')\n password = decoded.slice(colonIdx + 1)\n if (!password) throw new Error('Invalid mailboxToken: empty password')\n } catch (err) {\n if (err instanceof Error && err.message.startsWith('Invalid mailboxToken')) throw err\n throw new Error(`Failed to decode mailboxToken: ${(err as Error).message}`)\n }\n\n this.jmapClient = new JmapPushClient({\n email: config.email,\n password: password ?? config.smtpPassword,\n jmapUrl: resolvedBaseUrl,\n reconnectInterval: config.reconnectInterval ?? 5000,\n rejectUnauthorized: config.rejectUnauthorized,\n })\n\n this.smtpSender = new SmtpSender({\n host: smtpHost,\n port: config.smtpPort ?? 587,\n user: config.email,\n password: config.smtpPassword,\n httpBaseUrl: config.httpSendBaseUrl ?? resolvedBaseUrl,\n authToken: mailboxToken,\n rejectUnauthorized: config.rejectUnauthorized,\n })\n\n // Forward JMAP events to this emitter\n this.jmapClient.on('task.dispatch', (task: TaskDispatch) => {\n this.enqueueTaskDispatch(task)\n })\n\n this.jmapClient.on('task.cancel', (task: TaskCancel) => {\n this.emit('task.cancel', task)\n })\n\n this.jmapClient.on('task.result', (result: TaskResult) => {\n this.emit('task.result', result)\n })\n\n this.jmapClient.on('task.help_needed', (help: TaskHelp) => {\n this.emit('task.help_needed', help)\n })\n\n this.jmapClient.on('task.ack', (ack: TaskAck) => {\n this.emit('task.ack', ack)\n })\n\n this.jmapClient.on('task.stream.opened', (stream: TaskStreamOpened) => {\n this.emit('task.stream.opened', stream)\n })\n\n this.jmapClient.on('card.query', (query: CardQuery) => {\n this.emit('card.query', query)\n })\n\n this.jmapClient.on('card.response', (response: CardResponse) => {\n this.emit('card.response', response)\n })\n\n // Auto-ACK: when a task.dispatch is received, automatically send an ACK back\n this.jmapClient.on('_autoAck', async ({ to, taskId, messageId }: { to: string; taskId: string; messageId: string }) => {\n try {\n await this.smtpSender.sendAck({ to, taskId, inReplyTo: messageId })\n } catch (err) {\n console.warn(`[AAMP] Failed to send ACK for task ${taskId}: ${(err as Error).message}`)\n }\n })\n\n this.jmapClient.on('reply', (reply: HumanReply) => {\n this.emit('reply', reply)\n })\n\n this.jmapClient.on('connected', () => {\n this.emit('connected')\n })\n\n this.jmapClient.on('disconnected', (reason: string) => {\n this.emit('disconnected', reason)\n })\n\n this.jmapClient.on('error', (err: Error) => {\n this.emit('error', err)\n })\n }\n\n static fromMailboxIdentity(config: AampMailboxIdentityConfig): AampClient {\n const derived = deriveMailboxServiceDefaults(config.email, config.baseUrl)\n return new AampClient({\n email: config.email,\n mailboxToken: Buffer.from(`${config.email}:${config.smtpPassword}`).toString('base64'),\n baseUrl: derived.httpBaseUrl ?? `https://${config.email.split('@')[1] ?? 'localhost'}`,\n smtpHost: derived.smtpHost,\n smtpPort: config.smtpPort ?? 587,\n smtpPassword: config.smtpPassword,\n reconnectInterval: config.reconnectInterval,\n taskDispatchConcurrency: config.taskDispatchConcurrency,\n rejectUnauthorized: config.rejectUnauthorized,\n })\n }\n\n static async discoverAampService(aampHost: string): Promise<AampDiscoveryDocument> {\n const base = aampHost.replace(/\\/$/, '')\n const res = await fetch(`${base}/.well-known/aamp`)\n if (!res.ok) {\n throw new Error(`AAMP discovery failed: ${res.status} ${res.statusText}`)\n }\n const discovery = await res.json() as AampDiscoveryDocument\n if (!discovery.api?.url) {\n throw new Error('AAMP discovery did not return api.url')\n }\n return discovery\n }\n\n private static async callDiscoveredApi(\n base: string,\n opts: {\n action: string\n method?: 'GET' | 'POST'\n query?: Record<string, string | number | boolean | undefined>\n body?: unknown\n authToken?: string\n },\n ): Promise<Response> {\n const discovery = await AampClient.discoverAampService(base)\n const apiUrl = new URL(discovery.api!.url!, `${base}/`)\n apiUrl.searchParams.set('action', opts.action)\n for (const [key, value] of Object.entries(opts.query ?? {})) {\n if (value == null) continue\n apiUrl.searchParams.set(key, String(value))\n }\n return fetch(apiUrl, {\n method: opts.method ?? 'GET',\n headers: {\n ...(opts.authToken ? { Authorization: `Basic ${opts.authToken}` } : {}),\n ...(opts.body ? { 'Content-Type': 'application/json' } : {}),\n },\n ...(opts.body ? { body: JSON.stringify(opts.body) } : {}),\n })\n }\n\n static async registerMailbox(opts: RegisterMailboxOptions): Promise<RegisteredMailboxIdentity> {\n const base = opts.aampHost.replace(/\\/$/, '')\n const registerRes = await AampClient.callDiscoveredApi(base, {\n action: 'aamp.mailbox.register',\n method: 'POST',\n body: {\n slug: opts.slug,\n description: opts.description,\n },\n })\n if (!registerRes.ok) {\n const body = await registerRes.text().catch(() => '')\n throw new Error(`Mailbox registration failed: ${registerRes.status} ${body || registerRes.statusText}`)\n }\n const registerData = await registerRes.json() as { registrationCode?: string }\n if (!registerData.registrationCode) {\n throw new Error('Mailbox registration succeeded but no registrationCode was returned')\n }\n\n const credsRes = await AampClient.callDiscoveredApi(base, {\n action: 'aamp.mailbox.credentials',\n query: { code: registerData.registrationCode },\n })\n if (!credsRes.ok) {\n const body = await credsRes.text().catch(() => '')\n throw new Error(`Mailbox credential exchange failed: ${credsRes.status} ${body || credsRes.statusText}`)\n }\n const creds = await credsRes.json() as {\n email?: string\n mailbox?: { token?: string }\n smtp?: { password?: string }\n }\n if (!creds.email || !creds.mailbox?.token || !creds.smtp?.password) {\n throw new Error('Mailbox credential exchange returned an incomplete identity payload')\n }\n\n return {\n email: creds.email,\n mailboxToken: creds.mailbox.token,\n smtpPassword: creds.smtp.password,\n baseUrl: base,\n }\n }\n\n // =====================================================\n // Lifecycle\n // =====================================================\n\n /**\n * Connect to JMAP and start listening for tasks\n */\n async connect(): Promise<void> {\n await this.jmapClient.start()\n }\n\n /**\n * Disconnect and clean up\n */\n disconnect(): void {\n this.jmapClient.stop()\n this.smtpSender.close()\n }\n\n /**\n * Returns true if the JMAP connection is active\n */\n isConnected(): boolean {\n return this.jmapClient.isConnected()\n }\n\n isUsingPollingFallback(): boolean {\n return this.jmapClient.isUsingPollingFallback()\n }\n\n // =====================================================\n // Sending\n // =====================================================\n\n /**\n * Send a task.dispatch email to an agent.\n * Returns the generated taskId and the SMTP Message-ID.\n * Store messageId \u2192 taskId in Redis/DB to support In-Reply-To thread routing\n * for human replies that arrive without X-AAMP headers.\n */\n async sendTask(opts: SendTaskOptions): Promise<{ taskId: string; messageId: string }> {\n return this.smtpSender.sendTask(opts)\n }\n\n async sendRegisteredCommand(opts: SendRegisteredCommandOptions): Promise<{ taskId: string; messageId: string }> {\n const payload = buildRegisteredCommandDispatchPayload(opts)\n return this.smtpSender.sendTask({\n to: opts.to,\n taskId: opts.taskId,\n title: opts.title?.trim() || `Registered command: ${payload.command}`,\n rawBodyText: JSON.stringify(payload, null, 2),\n priority: opts.priority,\n expiresAt: opts.expiresAt,\n contextLinks: opts.contextLinks,\n dispatchContext: opts.dispatchContext,\n parentTaskId: opts.parentTaskId,\n attachments: opts.attachments,\n })\n }\n\n async sendCancel(opts: SendCancelOptions): Promise<void> {\n return this.smtpSender.sendCancel(opts)\n }\n\n /**\n * Send a task.result email (agent \u2192 system/dispatcher)\n */\n async sendResult(opts: SendResultOptions): Promise<void> {\n return this.smtpSender.sendResult(opts)\n }\n\n /**\n * Send a task.help_needed email when the agent needs human assistance\n */\n async sendHelp(opts: SendHelpOptions): Promise<void> {\n return this.smtpSender.sendHelp(opts)\n }\n\n async sendStreamOpened(opts: {\n to: string\n taskId: string\n streamId: string\n inReplyTo?: string\n }): Promise<void> {\n return this.smtpSender.sendStreamOpened(opts)\n }\n\n async sendCardQuery(opts: SendCardQueryOptions): Promise<{ taskId: string; messageId: string }> {\n return this.smtpSender.sendCardQuery(opts)\n }\n\n async sendCardResponse(opts: SendCardResponseOptions): Promise<void> {\n return this.smtpSender.sendCardResponse(opts)\n }\n\n async updateDirectoryProfile(opts: UpdateDirectoryProfileOptions): Promise<AgentDirectoryProfile> {\n const base = this.config.baseUrl\n const mailboxToken = this.config.mailboxToken\n const res = await AampClient.callDiscoveredApi(base, {\n action: 'aamp.directory.upsert',\n method: 'POST',\n authToken: mailboxToken,\n body: opts,\n })\n if (!res.ok) {\n const body = await res.text().catch(() => '')\n throw new Error(`Directory profile update failed: ${res.status} ${body || res.statusText}`)\n }\n const data = await res.json() as { profile: AgentDirectoryProfile }\n return data.profile\n }\n\n async listDirectory(opts: DirectoryListOptions = {}): Promise<AgentDirectoryEntry[]> {\n const base = this.config.baseUrl\n const mailboxToken = this.config.mailboxToken\n const res = await AampClient.callDiscoveredApi(base, {\n action: 'aamp.directory.list',\n authToken: mailboxToken,\n query: {\n scope: opts.scope,\n includeSelf: opts.includeSelf,\n limit: opts.limit,\n },\n })\n if (!res.ok) {\n const body = await res.text().catch(() => '')\n throw new Error(`Directory list failed: ${res.status} ${body || res.statusText}`)\n }\n const data = await res.json() as { agents: AgentDirectoryEntry[] }\n return data.agents\n }\n\n async searchDirectory(opts: DirectorySearchOptions): Promise<AgentDirectorySearchEntry[]> {\n const base = this.config.baseUrl\n const mailboxToken = this.config.mailboxToken\n const res = await AampClient.callDiscoveredApi(base, {\n action: 'aamp.directory.search',\n authToken: mailboxToken,\n query: {\n q: opts.query,\n scope: opts.scope,\n includeSelf: opts.includeSelf,\n limit: opts.limit,\n },\n })\n if (!res.ok) {\n const body = await res.text().catch(() => '')\n throw new Error(`Directory search failed: ${res.status} ${body || res.statusText}`)\n }\n const data = await res.json() as { agents: AgentDirectorySearchEntry[] }\n return data.agents\n }\n\n async getThreadHistory(taskId: string, opts: GetThreadHistoryOptions = {}): Promise<TaskThreadHistory> {\n const base = this.config.baseUrl\n const mailboxToken = this.config.mailboxToken\n const res = await AampClient.callDiscoveredApi(base, {\n action: 'aamp.mailbox.thread',\n authToken: mailboxToken,\n query: {\n taskId,\n includeStreamOpened: opts.includeStreamOpened,\n },\n })\n if (!res.ok) {\n const body = await res.text().catch(() => '')\n throw new Error(`Thread history fetch failed: ${res.status} ${body || res.statusText}`)\n }\n const data = await res.json() as TaskThreadHistory\n return {\n taskId: data.taskId,\n events: Array.isArray(data.events) ? data.events : [],\n }\n }\n\n async hydrateTaskDispatch(task: TaskDispatch): Promise<HydratedTaskDispatch> {\n const history = await this.getThreadHistory(task.taskId)\n const priorEvents = history.events.filter((event: AampThreadEvent) => event.messageId !== task.messageId)\n return {\n ...task,\n threadHistory: priorEvents,\n threadContextText: renderThreadHistoryForAgent(priorEvents),\n }\n }\n\n private async resolveStreamCapability(): Promise<NonNullable<NonNullable<AampDiscoveryDocument['capabilities']>['stream']>> {\n const discovery = await AampClient.discoverAampService(this.config.baseUrl)\n const stream = discovery.capabilities?.stream\n if (!stream?.transport) {\n throw new Error('AAMP stream capability is not available on this service')\n }\n return stream\n }\n\n async createStream(opts: CreateStreamOptions): Promise<CreateStreamResult> {\n const stream = await this.resolveStreamCapability()\n const res = await AampClient.callDiscoveredApi(this.config.baseUrl, {\n action: stream.createAction ?? 'aamp.stream.create',\n method: 'POST',\n authToken: this.config.mailboxToken,\n body: opts,\n })\n if (!res.ok) {\n const body = await res.text().catch(() => '')\n throw new Error(`AAMP stream create failed: ${res.status} ${body || res.statusText}`)\n }\n return res.json() as Promise<CreateStreamResult>\n }\n\n private enqueueTaskDispatch(task: TaskDispatch): void {\n this.pendingTaskDispatches.push(task)\n this.drainTaskDispatchQueue()\n }\n\n private drainTaskDispatchQueue(): void {\n while (\n this.activeTaskDispatchCount < this.taskDispatchConcurrency\n && this.pendingTaskDispatches.length > 0\n ) {\n const nextTask = this.pendingTaskDispatches.shift()\n if (!nextTask) return\n\n this.activeTaskDispatchCount += 1\n void this.runTaskDispatch(nextTask)\n }\n }\n\n private async runTaskDispatch(task: TaskDispatch): Promise<void> {\n try {\n await this.emitAsync('task.dispatch', task)\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n this.emit('error', error)\n } finally {\n this.activeTaskDispatchCount = Math.max(0, this.activeTaskDispatchCount - 1)\n this.drainTaskDispatchQueue()\n }\n }\n\n private getStreamAppendQueue(streamId: string): {\n running: boolean\n operations: StreamAppendOperation[]\n } {\n let queue = this.streamAppendQueues.get(streamId)\n if (!queue) {\n queue = { running: false, operations: [] }\n this.streamAppendQueues.set(streamId, queue)\n }\n return queue\n }\n\n private async dispatchStreamAppend(opts: {\n streamId: string\n type: AampStreamEvent['type']\n payload: Record<string, unknown>\n }): Promise<AampStreamEvent> {\n const stream = await this.resolveStreamCapability()\n const res = await AampClient.callDiscoveredApi(this.config.baseUrl, {\n action: stream.appendAction ?? 'aamp.stream.append',\n method: 'POST',\n authToken: this.config.mailboxToken,\n body: opts,\n })\n if (!res.ok) {\n const body = await res.text().catch(() => '')\n throw new Error(`AAMP stream append failed: ${res.status} ${body || res.statusText}`)\n }\n return res.json() as Promise<AampStreamEvent>\n }\n\n private enqueueStreamAppend(\n streamId: string,\n operation: StreamAppendOperation,\n ): void {\n const queue = this.getStreamAppendQueue(streamId)\n queue.operations.push(operation)\n void this.drainStreamAppendQueue(streamId)\n }\n\n private async drainStreamAppendQueue(streamId: string): Promise<void> {\n const queue = this.streamAppendQueues.get(streamId)\n if (!queue || queue.running) return\n\n queue.running = true\n try {\n while (queue.operations.length) {\n const operation = queue.operations.shift()\n if (!operation) continue\n\n if (operation.kind === 'text-delta-batch') {\n try {\n const event = await this.dispatchStreamAppend({\n streamId,\n type: 'text.delta',\n payload: {\n ...operation.payload,\n text: operation.text,\n },\n })\n for (const resolve of operation.resolvers) resolve(event)\n } catch (error) {\n for (const reject of operation.rejecters) reject(error)\n }\n continue\n }\n\n try {\n const event = await this.dispatchStreamAppend(operation.opts)\n operation.resolve(event)\n } catch (error) {\n operation.reject(error)\n }\n }\n } finally {\n queue.running = false\n if (queue.operations.length === 0) {\n this.streamAppendQueues.delete(streamId)\n }\n }\n }\n\n private async flushStreamAppendQueue(streamId: string): Promise<void> {\n while (true) {\n const queue = this.streamAppendQueues.get(streamId)\n if (!queue) return\n if (!queue.running && queue.operations.length === 0) {\n this.streamAppendQueues.delete(streamId)\n return\n }\n await new Promise((resolve) => setTimeout(resolve, 0))\n }\n }\n\n async appendStreamEvent(opts: {\n streamId: string\n type: AampStreamEvent['type']\n payload: Record<string, unknown>\n }): Promise<AampStreamEvent> {\n if (opts.type === 'text.delta' && typeof opts.payload.text === 'string') {\n return await new Promise<AampStreamEvent>((resolve, reject) => {\n const queue = this.getStreamAppendQueue(opts.streamId)\n const lastOperation = queue.operations.at(-1)\n if (lastOperation?.kind === 'text-delta-batch') {\n lastOperation.text += String(opts.payload.text ?? '')\n lastOperation.resolvers.push(resolve)\n lastOperation.rejecters.push(reject)\n return\n }\n\n this.enqueueStreamAppend(opts.streamId, {\n kind: 'text-delta-batch',\n text: String(opts.payload.text ?? ''),\n payload: {\n ...opts.payload,\n },\n resolvers: [resolve],\n rejecters: [reject],\n })\n })\n }\n\n return await new Promise<AampStreamEvent>((resolve, reject) => {\n this.enqueueStreamAppend(opts.streamId, {\n kind: 'single-event',\n opts,\n resolve,\n reject,\n })\n })\n }\n\n async closeStream(opts: CloseStreamOptions): Promise<TaskStreamState> {\n await this.flushStreamAppendQueue(opts.streamId)\n const stream = await this.resolveStreamCapability()\n const res = await AampClient.callDiscoveredApi(this.config.baseUrl, {\n action: stream.closeAction ?? 'aamp.stream.close',\n method: 'POST',\n authToken: this.config.mailboxToken,\n body: opts,\n })\n if (!res.ok) {\n const body = await res.text().catch(() => '')\n throw new Error(`AAMP stream close failed: ${res.status} ${body || res.statusText}`)\n }\n return res.json() as Promise<TaskStreamState>\n }\n\n async getTaskStream(opts: GetTaskStreamOptions): Promise<TaskStreamState | null> {\n const stream = await this.resolveStreamCapability()\n const res = await AampClient.callDiscoveredApi(this.config.baseUrl, {\n action: stream.getAction ?? 'aamp.stream.get',\n authToken: this.config.mailboxToken,\n query: {\n ...(opts.taskId ? { taskId: opts.taskId } : {}),\n ...(opts.streamId ? { streamId: opts.streamId } : {}),\n },\n })\n if (res.status === 404) return null\n if (!res.ok) {\n const body = await res.text().catch(() => '')\n throw new Error(`AAMP stream get failed: ${res.status} ${body || res.statusText}`)\n }\n return res.json() as Promise<TaskStreamState>\n }\n\n async subscribeStream(\n streamId: string,\n handlers: {\n onEvent: (event: AampStreamEvent) => void\n onError?: (err: Error) => void\n onOpen?: () => void\n },\n opts: { lastEventId?: string; signal?: AbortSignal } = {},\n ): Promise<StreamSubscription> {\n const stream = await this.resolveStreamCapability()\n const template = stream.subscribeUrlTemplate\n if (!template) throw new Error('AAMP stream subscribeUrlTemplate is missing')\n\n const url = new URL(template.replace('{streamId}', encodeURIComponent(streamId)), this.config.baseUrl)\n if (opts.lastEventId) {\n url.searchParams.set('lastEventId', opts.lastEventId)\n }\n\n const controller = new AbortController()\n if (opts.signal) {\n opts.signal.addEventListener('abort', () => controller.abort(), { once: true })\n }\n\n const res = await fetch(url, {\n headers: {\n Authorization: `Basic ${this.config.mailboxToken}`,\n Accept: 'text/event-stream',\n },\n signal: controller.signal,\n })\n if (!res.ok || !res.body) {\n throw new Error(`AAMP stream subscribe failed: ${res.status} ${res.statusText}`)\n }\n\n handlers.onOpen?.()\n const reader = res.body.getReader()\n const decoder = new TextDecoder()\n let buffer = ''\n let currentEvent = 'message'\n let currentId = ''\n let currentData: string[] = []\n\n const flush = () => {\n if (!currentData.length) return\n try {\n const parsed = JSON.parse(currentData.join('\\n')) as AampStreamEvent\n handlers.onEvent({\n ...parsed,\n ...(currentId ? { id: currentId } : {}),\n type: parsed.type ?? currentEvent as AampStreamEvent['type'],\n })\n } catch (err) {\n handlers.onError?.(err as Error)\n } finally {\n currentEvent = 'message'\n currentId = ''\n currentData = []\n }\n }\n\n void (async () => {\n try {\n while (true) {\n const { value, done } = await reader.read()\n if (done) break\n buffer += decoder.decode(value, { stream: true })\n\n let index = buffer.indexOf('\\n\\n')\n while (index >= 0) {\n const frame = buffer.slice(0, index)\n buffer = buffer.slice(index + 2)\n for (const rawLine of frame.split('\\n')) {\n const line = rawLine.replace(/\\r$/, '')\n if (!line || line.startsWith(':')) continue\n if (line.startsWith('event:')) {\n currentEvent = line.slice(6).trim()\n } else if (line.startsWith('id:')) {\n currentId = line.slice(3).trim()\n } else if (line.startsWith('data:')) {\n currentData.push(line.slice(5).trimStart())\n }\n }\n flush()\n index = buffer.indexOf('\\n\\n')\n }\n }\n } catch (err) {\n if (!controller.signal.aborted) {\n handlers.onError?.(err as Error)\n }\n } finally {\n buffer += decoder.decode()\n controller.abort()\n }\n })()\n\n return {\n close() {\n controller.abort()\n },\n }\n }\n\n /**\n * Download a blob (attachment) by its JMAP blobId.\n * Use this to retrieve attachment content from received TaskDispatch or TaskResult messages.\n * Returns the raw binary content as a Buffer.\n */\n async downloadBlob(blobId: string, filename?: string): Promise<Buffer> {\n return this.jmapClient.downloadBlob(blobId, filename)\n }\n\n /**\n * Reconcile recent mailbox contents via JMAP HTTP to catch messages missed by\n * a flaky WebSocket path. Safe to call periodically; duplicate processing is\n * suppressed by the JMAP push client.\n */\n async reconcileRecentEmails(limit?: number, opts?: { includeHistorical?: boolean }): Promise<number> {\n return this.jmapClient.reconcileRecentEmails(limit, opts)\n }\n\n /**\n * Verify SMTP connectivity\n */\n async verifySmtp(): Promise<boolean> {\n return this.smtpSender.verify()\n }\n\n get email(): string {\n return this.config.email\n }\n}\n", "/**\n * @aamp/openclaw-plugin\n *\n * OpenClaw plugin that gives the agent an AAMP mailbox identity and lets it\n * receive, process, and reply to AAMP tasks \u2014 entirely through standard email.\n *\n * How it works:\n * 1. Plugin resolves or auto-registers an AAMP mailbox identity on startup.\n * 2. Credentials are cached to a local file so the same mailbox is reused\n * across gateway restarts (no re-registration needed).\n * 3. Background JMAP WebSocket Push receives incoming task.dispatch emails.\n * 4. Incoming tasks are stored in an in-memory pending-task queue.\n * 5. before_prompt_build injects the oldest pending task into the LLM's\n * system context so the agent sees it and acts without user prompting.\n * 6. The agent calls aamp_send_result or aamp_send_help to reply.\n *\n * OpenClaw config (openclaw.json):\n *\n * \"plugins\": {\n * \"entries\": {\n * \"aamp\": {\n * \"enabled\": true,\n * \"config\": {\n * \"aampHost\": \"https://meshmail.ai\",\n * \"slug\": \"openclaw-agent\",\n * \"credentialsFile\": \"/absolute/path/to/.aamp-credentials.json\"\n * }\n * }\n * }\n * }\n *\n * Install:\n * openclaw plugins install ./packages/openclaw-plugin\n */\n\nimport { AampClient } from '../../sdk/src/index.ts'\nimport type {\n AampThreadEvent,\n TaskDispatch,\n TaskCancel,\n TaskResult,\n TaskHelp,\n TaskPriority,\n AampAttachment,\n ReceivedAttachment,\n} from '../../sdk/src/types.ts'\nimport { readFileSync } from 'node:fs'\nimport {\n defaultCredentialsPath,\n defaultTaskStatePath,\n ensureDir,\n loadCachedIdentity,\n loadTaskState,\n readBinaryFile,\n saveCachedIdentity,\n saveTaskState,\n writeBinaryFile,\n type Identity,\n} from './file-store.js'\n\n// \u2500\u2500\u2500 Shared runtime state (single instance per plugin lifetime) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ninterface PendingTask {\n taskId: string\n from: string\n title: string\n bodyText: string\n dispatchContext?: Record<string, string>\n threadHistory: AampThreadEvent[]\n threadContextText: string\n priority: TaskPriority\n expiresAt?: string\n contextLinks: string[]\n messageId: string\n receivedAt: string // ISO-8601\n awaitingHelpReply?: boolean\n}\n\ninterface PluginConfig {\n /** e.g. \"meshmail.ai\" \u2014 all URLs are derived from this */\n aampHost: string\n taskDispatchConcurrency?: number\n slug?: string\n summary?: string\n cardText?: string\n cardFile?: string\n /** Absolute path to cache AAMP credentials. Default: ~/.openclaw/extensions/aamp-openclaw-plugin/.credentials.json */\n credentialsFile?: string\n senderPolicies?: SenderPolicy[]\n}\n\ninterface SenderPolicy {\n sender: string\n dispatchContextRules?: Record<string, string[]>\n}\n\nexport function matchSenderPolicy(\n task: TaskDispatch,\n senderPolicies: SenderPolicy[] | undefined,\n): { allowed: boolean; reason?: string } {\n if (!senderPolicies?.length) return { allowed: true }\n\n const sender = task.from.toLowerCase()\n const policy = senderPolicies.find((item) => item.sender.trim().toLowerCase() === sender)\n if (!policy) {\n return { allowed: false, reason: `sender ${task.from} is not allowed by senderPolicies` }\n }\n\n const rules = policy.dispatchContextRules\n if (!rules || Object.keys(rules).length === 0) {\n return { allowed: true }\n }\n\n const context = task.dispatchContext ?? {}\n const effectiveRules = Object.entries(rules)\n .map(([key, allowedValues]) => [\n key,\n (allowedValues ?? []).map((value) => value.trim()).filter(Boolean),\n ] as const)\n .filter(([, allowedValues]) => allowedValues.length > 0)\n\n if (effectiveRules.length === 0) {\n return { allowed: true }\n }\n\n for (const [key, allowedValues] of effectiveRules) {\n const contextValue = context[key]\n if (!contextValue) {\n return { allowed: false, reason: `dispatchContext missing required key \"${key}\"` }\n }\n if (!allowedValues.includes(contextValue)) {\n return { allowed: false, reason: `dispatchContext ${key}=${contextValue} is not allowed` }\n }\n }\n\n return { allowed: true }\n}\n\ntype StructuredResultFieldInput = {\n fieldKey: string\n fieldTypeKey: string\n fieldAlias?: string\n value?: unknown\n index?: string\n attachmentFilenames?: string[]\n}\n\n/** Normalise aampHost to a base URL with scheme and no trailing slash */\nexport function baseUrl(aampHost: string): string {\n if (aampHost.startsWith('http://') || aampHost.startsWith('https://')) {\n return aampHost.replace(/\\/$/, '')\n }\n return `https://${aampHost}`\n}\n\nconst pendingTasks = new Map<string, PendingTask>()\nconst activeTaskStreams = new Map<string, string>()\nconst terminalTaskIds = new Set<string>(loadTaskState(defaultTaskStatePath()).terminalTaskIds ?? [])\nconst AAMP_SESSION_PREFIX = 'aamp:'\nconst DEFAULT_OPENCLAW_AGENT_ID = 'main'\nconst OPENCLAW_AGENT_SESSION_PREFIX = 'agent:'\nconst VALID_OPENCLAW_AGENT_ID_RE = /^[a-z0-9][a-z0-9_-]{0,63}$/i\nconst INVALID_OPENCLAW_AGENT_ID_RE = /[^a-z0-9_-]+/g\nconst LEADING_DASH_RE = /^-+/\nconst TRAILING_DASH_RE = /-+$/\n// Tracks sub-tasks dispatched TO other agents \u2014 waiting for their result/help replies\nconst dispatchedSubtasks = new Map<string, { to: string; title: string; dispatchedAt: string; parentTaskId?: string }>()\n// Tracks notification keys that have been shown to LLM (auto-cleaned on next prompt build)\nconst shownNotifications = new Set<string>()\n// Pending synchronous dispatch waiters \u2014 resolve callback keyed by sub-task ID.\n// When aamp_dispatch_task sends a sub-task, it parks a Promise here and waits.\n// When task.result/help arrives for that sub-task ID, the waiter is resolved\n// directly, keeping the LLM awake with full context (no heartbeat needed).\nconst waitingDispatches = new Map<string, (reply: { type: 'result' | 'help'; data: unknown }) => void>()\nlet aampClient: AampClient | null = null\nlet agentEmail = ''\nlet lastConnectionError = ''\nlet lastDisconnectReason = ''\nlet lastTransportMode: 'disconnected' | 'websocket' | 'polling' = 'disconnected'\nlet lastLoggedTransportMode: 'disconnected' | 'websocket' | 'polling' = 'disconnected'\nlet reconcileTimer: NodeJS.Timeout | null = null\nlet transportMonitorTimer: NodeJS.Timeout | null = null\nlet historicalReconcileCompleted = false\n// Channel runtime \u2014 captured from channel adapter's startAccount for instant dispatch.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet channelRuntime: any = null\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet channelCfg: any = null\n\nasync function ensureTaskStream(task: PendingTask): Promise<string | null> {\n if (!aampClient?.isConnected()) return null\n const existing = activeTaskStreams.get(task.taskId)\n if (existing) return existing\n\n const created = await aampClient.createStream({\n taskId: task.taskId,\n peerEmail: task.from,\n })\n await aampClient.sendStreamOpened({\n to: task.from,\n taskId: task.taskId,\n streamId: created.streamId,\n inReplyTo: task.messageId || undefined,\n })\n await aampClient.appendStreamEvent({\n streamId: created.streamId,\n type: 'status',\n payload: { state: 'running', label: 'Task queued in OpenClaw' },\n })\n activeTaskStreams.set(task.taskId, created.streamId)\n return created.streamId\n}\n\nasync function appendTaskStream(taskId: string, type: 'text.delta' | 'progress' | 'status' | 'artifact' | 'error' | 'done', payload: Record<string, unknown>): Promise<void> {\n if (!aampClient?.isConnected()) return\n const streamId = activeTaskStreams.get(taskId)\n if (!streamId) return\n await aampClient.appendStreamEvent({\n streamId,\n type,\n payload,\n })\n}\n\nasync function closeTaskStream(taskId: string, payload?: Record<string, unknown>): Promise<void> {\n if (!aampClient?.isConnected()) return\n const streamId = activeTaskStreams.get(taskId)\n if (!streamId) return\n activeTaskStreams.delete(taskId)\n await aampClient.closeStream({\n streamId,\n payload,\n })\n}\n\nfunction logTransportState(\n api: { logger: { info: (msg: string) => void; warn: (msg: string) => void } },\n mode: 'websocket' | 'polling',\n email: string,\n previousMode: 'disconnected' | 'websocket' | 'polling',\n): void {\n if (mode === previousMode) return\n\n if (mode === 'polling') {\n api.logger.info(`[AAMP] Connected (polling fallback active) \u2014 listening as ${email}`)\n return\n }\n\n if (previousMode === 'polling') {\n api.logger.info(`[AAMP] WebSocket restored \u2014 listening as ${email}`)\n return\n }\n\n api.logger.info(`[AAMP] Connected \u2014 listening as ${email}`)\n}\n\nfunction isSyntheticPendingKey(taskKey: string): boolean {\n return taskKey.startsWith('result:') || taskKey.startsWith('help:')\n}\n\nfunction isTaskAwaitingHelpReply(task: PendingTask): boolean {\n return task.awaitingHelpReply === true\n}\n\nfunction isConversationalTask(task: PendingTask): boolean {\n return task.dispatchContext?.source === 'feishu'\n}\n\nfunction firstDispatchContextValue(\n context: Record<string, string> | undefined,\n keys: string[],\n): string | undefined {\n if (!context) return undefined\n for (const key of keys) {\n const value = context[key]?.trim()\n if (value) return value\n }\n return undefined\n}\n\nfunction threadAlreadyTerminal(events: AampThreadEvent[] | undefined): boolean {\n return (events ?? []).some((event) =>\n event.intent === 'task.result' || event.intent === 'task.cancel',\n )\n}\n\nfunction isActionablePendingTask(taskKey: string, task: PendingTask): boolean {\n return !isSyntheticPendingKey(taskKey) && !isTaskAwaitingHelpReply(task)\n}\n\nfunction normalizeOpenClawAgentId(value: unknown): string {\n const trimmed = typeof value === 'string' ? value.trim() : ''\n if (!trimmed) return DEFAULT_OPENCLAW_AGENT_ID\n if (VALID_OPENCLAW_AGENT_ID_RE.test(trimmed)) return trimmed.toLowerCase()\n return trimmed\n .toLowerCase()\n .replace(INVALID_OPENCLAW_AGENT_ID_RE, '-')\n .replace(LEADING_DASH_RE, '')\n .replace(TRAILING_DASH_RE, '')\n .slice(0, 64) || DEFAULT_OPENCLAW_AGENT_ID\n}\n\nfunction resolveDefaultOpenClawAgentId(config: unknown): string {\n const agents = (config as { agents?: { list?: Array<{ id?: unknown; default?: unknown }> } } | null | undefined)?.agents?.list\n if (!Array.isArray(agents) || agents.length === 0) return DEFAULT_OPENCLAW_AGENT_ID\n\n const defaults = agents.filter((agent) => agent?.default)\n return normalizeOpenClawAgentId((defaults[0] ?? agents[0])?.id)\n}\n\nfunction stripOpenClawAgentScope(sessionKey: string): string {\n const trimmed = sessionKey.trim()\n if (!trimmed.toLowerCase().startsWith(OPENCLAW_AGENT_SESSION_PREFIX)) return trimmed\n\n const parts = trimmed.split(':')\n if (parts.length < 3 || parts[0]?.toLowerCase() !== 'agent') return trimmed\n return parts.slice(2).join(':')\n}\n\nfunction isAampSessionKey(sessionKey: unknown): sessionKey is string {\n return typeof sessionKey === 'string'\n && stripOpenClawAgentScope(sessionKey).toLowerCase().startsWith(AAMP_SESSION_PREFIX)\n}\n\nfunction buildOpenClawMainSessionKey(mainKey: string, config: unknown): string {\n const trimmed = mainKey.trim()\n if (!trimmed) return `${OPENCLAW_AGENT_SESSION_PREFIX}${resolveDefaultOpenClawAgentId(config)}:main`\n if (trimmed.toLowerCase().startsWith(OPENCLAW_AGENT_SESSION_PREFIX)) return trimmed\n return `${OPENCLAW_AGENT_SESSION_PREFIX}${resolveDefaultOpenClawAgentId(config)}:${trimmed}`\n}\n\nfunction buildAampConversationSessionKey(value: string, config: unknown): string {\n return buildOpenClawMainSessionKey(`${AAMP_SESSION_PREFIX}default:${value}`, config)\n}\n\nfunction buildAampStickySessionKey(\n dispatchContext: Record<string, string> | undefined,\n config: unknown,\n): string | undefined {\n const stickyValue = firstDispatchContextValue(dispatchContext, ['session_key', 'conversation_key', 'thread_key'])\n if (!stickyValue) return undefined\n return buildAampConversationSessionKey(`session:${stickyValue}`, config)\n}\n\nfunction buildAampTaskSessionKey(taskId: string, config: unknown): string {\n return buildAampConversationSessionKey(`task:${taskId}`, config)\n}\n\nfunction buildAampWakeSessionKey(kind: string, id: string): string {\n return `${AAMP_SESSION_PREFIX}wake:${kind}:${id}`\n}\n\nfunction buildSessionKeyForPendingTask(task: PendingTask, config: unknown): string {\n return buildAampStickySessionKey(task.dispatchContext, config)\n ?? buildAampTaskSessionKey(task.taskId, config)\n}\n\nfunction buildWakeSessionKeyForPendingTask(task: PendingTask, config: unknown): string {\n return buildAampStickySessionKey(task.dispatchContext, config)\n ?? buildAampWakeSessionKey('task', task.taskId)\n}\n\nfunction findPendingEntryForSession(\n sessionKey: unknown,\n config: unknown,\n): [string, PendingTask] | undefined {\n if (typeof sessionKey !== 'string' || !isAampSessionKey(sessionKey)) return undefined\n\n const requested = buildOpenClawMainSessionKey(stripOpenClawAgentScope(sessionKey), config)\n const entries = [...pendingTasks.entries()]\n .filter(([key, task]) => isActionablePendingTask(key, task))\n .filter(([, task]) => buildSessionKeyForPendingTask(task, config) === requested)\n .sort((a, b) => {\n const rankDiff = priorityRank(a[1].priority) - priorityRank(b[1].priority)\n if (rankDiff !== 0) return rankDiff\n return new Date(a[1].receivedAt).getTime() - new Date(b[1].receivedAt).getTime()\n })\n\n return entries[0]\n}\n\nfunction resolvePendingKeyFromSessionKey(sessionKey: unknown): string | undefined {\n if (typeof sessionKey !== 'string') return undefined\n\n const normalized = stripOpenClawAgentScope(sessionKey).trim()\n if (!normalized) return undefined\n\n const parts = normalized.split(':')\n if (parts[0]?.toLowerCase() !== 'aamp') return undefined\n\n if (parts[1]?.toLowerCase() === 'wake') {\n const kind = parts[2]?.toLowerCase()\n const id = parts.slice(3).join(':').trim()\n if (!id) return undefined\n if (kind === 'task') return id\n if (kind === 'result' || kind === 'help') return `${kind}:${id}`\n return undefined\n }\n\n if (parts[1]?.toLowerCase() === 'default') {\n const kind = parts[2]?.toLowerCase()\n const id = parts.slice(3).join(':').trim()\n if (!id) return undefined\n if (kind === 'task') return id\n if (kind === 'result' || kind === 'help') return `${kind}:${id}`\n }\n\n return undefined\n}\n\nfunction saveTerminalTaskIds(): void {\n saveTaskState({ terminalTaskIds: [...terminalTaskIds] }, defaultTaskStatePath())\n}\n\nfunction rememberTerminalTask(taskId: string): void {\n terminalTaskIds.add(taskId)\n saveTerminalTaskIds()\n}\n\nfunction priorityRank(priority: TaskPriority): number {\n switch (priority) {\n case 'urgent':\n return 0\n case 'high':\n return 1\n default:\n return 2\n }\n}\n\nfunction hasExpired(task: Pick<PendingTask, 'expiresAt'>): boolean {\n if (task.expiresAt) {\n const expiresAtMs = new Date(task.expiresAt).getTime()\n if (Number.isFinite(expiresAtMs) && Date.now() >= expiresAtMs) return true\n }\n return false\n}\n\nfunction isTransientTransportError(message: string): boolean {\n return [\n 'ECONNRESET',\n 'ETIMEDOUT',\n 'ECONNREFUSED',\n 'EPIPE',\n 'UND_ERR_SOCKET',\n 'UND_ERR_CONNECT_TIMEOUT',\n 'fetch failed',\n ].some((needle) => message.includes(needle))\n}\n\nfunction nextPendingEntry(): [string, PendingTask] | undefined {\n const entries = [...pendingTasks.entries()]\n const notifications = entries.filter(([key]) => key.startsWith('result:') || key.startsWith('help:'))\n if (notifications.length > 0) {\n return notifications.sort((a, b) => new Date(a[1].receivedAt).getTime() - new Date(b[1].receivedAt).getTime())[0]\n }\n\n return entries\n .filter(([key, task]) => isActionablePendingTask(key, task))\n .sort((a, b) => {\n const rankDiff = priorityRank(a[1].priority) - priorityRank(b[1].priority)\n if (rankDiff !== 0) return rankDiff\n return new Date(a[1].receivedAt).getTime() - new Date(b[1].receivedAt).getTime()\n })[0]\n}\n\nexport function queuePendingTask(\n task: TaskDispatch & { threadHistory?: AampThreadEvent[]; threadContextText?: string },\n): boolean {\n if (terminalTaskIds.has(task.taskId)) {\n return false\n }\n\n pendingTasks.set(task.taskId, {\n taskId: task.taskId,\n from: task.from,\n title: task.title,\n bodyText: task.bodyText ?? '',\n dispatchContext: task.dispatchContext,\n threadHistory: task.threadHistory ?? [],\n threadContextText: task.threadContextText ?? '',\n priority: task.priority ?? 'normal',\n ...(task.expiresAt ? { expiresAt: task.expiresAt } : {}),\n contextLinks: task.contextLinks ?? [],\n messageId: task.messageId ?? '',\n receivedAt: new Date().toISOString(),\n })\n\n if (hasExpired(pendingTasks.get(task.taskId)!)) {\n pendingTasks.delete(task.taskId)\n rememberTerminalTask(task.taskId)\n return false\n }\n\n return true\n}\n\n// \u2500\u2500\u2500 Identity helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ninterface Identity {\n email: string\n mailboxToken?: string\n smtpPassword: string\n}\n\n/**\n * Register a new AAMP node via the management service.\n *\n * Always creates a NEW mailbox (always returns 201). The slug is just a\n * human-readable prefix; a random hex suffix makes the email unique.\n * Callers should only call this once and persist the returned credentials.\n */\nexport async function registerNode(cfg: PluginConfig): Promise<Identity> {\n const slug = (cfg.slug ?? 'openclaw-agent')\n .toLowerCase()\n .replace(/[\\s_]+/g, '-')\n .replace(/[^a-z0-9-]/g, '')\n\n const base = baseUrl(cfg.aampHost)\n const discoveryRes = await fetch(`${base}/.well-known/aamp`)\n if (!discoveryRes.ok) {\n throw new Error(`AAMP discovery failed (${discoveryRes.status}): ${discoveryRes.statusText}`)\n }\n const discovery = (await discoveryRes.json()) as { api?: { url?: string } }\n const apiUrl = discovery.api?.url\n if (!apiUrl) {\n throw new Error('AAMP discovery did not return api.url')\n }\n\n const apiBase = new URL(apiUrl, `${base}/`).toString()\n\n // Step 1: Self-register \u2192 get one-time registration code\n const res = await fetch(`${apiBase}?action=aamp.mailbox.register`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ slug, description: 'OpenClaw AAMP agent node' }),\n })\n\n if (!res.ok) {\n const err = (await res.json().catch(() => ({}))) as { error?: string }\n throw new Error(`AAMP registration failed (${res.status}): ${err.error ?? res.statusText}`)\n }\n\n const regData = (await res.json()) as {\n registrationCode: string\n email: string\n }\n\n // Step 2: Exchange registration code for credentials\n const credRes = await fetch(\n `${apiBase}?action=aamp.mailbox.credentials&code=${encodeURIComponent(regData.registrationCode)}`,\n )\n\n if (!credRes.ok) {\n const err = (await credRes.json().catch(() => ({}))) as { error?: string }\n throw new Error(`AAMP credential exchange failed (${credRes.status}): ${err.error ?? credRes.statusText}`)\n }\n\n const credData = (await credRes.json()) as {\n email: string\n mailbox: { token: string }\n smtp: { password: string }\n }\n\n return {\n email: credData.email,\n mailboxToken: credData.mailbox.token,\n smtpPassword: credData.smtp.password,\n }\n}\n\n/**\n * Resolve this agent's identity:\n * 1. Return cached credentials from disk if available.\n * 2. Otherwise register a new node and cache the result.\n */\nexport async function resolveIdentity(cfg: PluginConfig): Promise<Identity> {\n const cached = loadCachedIdentity(cfg.credentialsFile ?? defaultCredentialsPath())\n if (cached) return cached\n\n const identity = await registerNode(cfg)\n saveCachedIdentity(identity, cfg.credentialsFile ?? defaultCredentialsPath())\n return identity\n}\n\n// \u2500\u2500\u2500 Plugin definition \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport default {\n id: 'aamp-openclaw-plugin',\n name: 'AAMP Agent Mail Protocol',\n\n configSchema: {\n type: 'object',\n properties: {\n aampHost: {\n type: 'string',\n description: 'AAMP service host, e.g. https://meshmail.ai',\n },\n slug: {\n type: 'string',\n default: 'openclaw-agent',\n description: 'Agent name prefix used in the mailbox address',\n },\n summary: {\n type: 'string',\n description: 'Directory summary shown when other agents search for this agent.',\n },\n cardText: {\n type: 'string',\n description: 'Inline card text used for automatic card.response replies.',\n },\n cardFile: {\n type: 'string',\n description: 'Absolute path to a card text file. Used when cardText is not set.',\n },\n credentialsFile: {\n type: 'string',\n description:\n 'Absolute path to cache AAMP credentials between gateway restarts. ' +\n 'Default: ~/.openclaw/extensions/aamp-openclaw-plugin/.credentials.json. ' +\n 'Delete this file to force re-registration with a new mailbox.',\n },\n senderPolicies: {\n type: 'array',\n description:\n 'Per-sender authorization policies. Each sender can optionally require specific ' +\n 'X-AAMP-Dispatch-Context key/value pairs before a task is accepted.',\n items: {\n type: 'object',\n required: ['sender'],\n properties: {\n sender: {\n type: 'string',\n description: 'Dispatch sender email address (case-insensitive exact match).',\n },\n dispatchContextRules: {\n type: 'object',\n description:\n 'Optional exact-match rules over X-AAMP-Dispatch-Context. ' +\n 'All listed keys must be present and their values must match one of the configured entries.',\n additionalProperties: {\n type: 'array',\n items: { type: 'string' },\n },\n },\n },\n },\n },\n },\n },\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n register(api: any) {\n // OpenClaw channel plugins keep runtime config under channels.<channelId>.\n // Fall back to the legacy plugins.entries config so older installs still work.\n const cfg = ((api.config?.channels?.aamp ?? api.pluginConfig ?? {}) as PluginConfig)\n\n // \u2500\u2500 Register lightweight channel adapter to capture channelRuntime \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // We register as a channel SOLELY to get access to channelRuntime, which provides\n // dispatchReplyWithBufferedBlockDispatcher for instant LLM dispatch (bypassing\n // heartbeat's global running-mutex + requests-in-flight ~60s delay).\n // JMAP connection is managed by registerService, NOT startAccount.\n api.registerChannel({\n id: 'aamp',\n meta: {\n label: 'AAMP',\n selectionLabel: 'AAMP',\n docsPath: '/channels/aamp',\n blurb: 'AAMP mailbox channel for receiving and replying to tasks over email.',\n },\n capabilities: { chatTypes: ['dm'] },\n config: {\n listAccountIds: () => cfg.aampHost ? ['default'] : [],\n resolveAccount: () => ({ aampHost: cfg.aampHost }),\n isEnabled: () => !!cfg.aampHost,\n isConfigured: () => !!loadCachedIdentity(cfg.credentialsFile ?? defaultCredentialsPath()),\n },\n gateway: {\n startAccount: async (ctx: { channelRuntime?: unknown; cfg?: unknown; abortSignal?: AbortSignal }) => {\n // Capture channelRuntime for use by sub-task notification dispatch\n channelRuntime = ctx.channelRuntime ?? null\n channelCfg = ctx.cfg ?? null\n api.logger.info(`[AAMP] Channel adapter started \u2014 channelRuntime ${channelRuntime ? 'available' : 'NOT available'}`)\n\n // Keep alive until abort \u2014 JMAP connection is managed by registerService\n await new Promise<void>((resolve) => {\n ctx.abortSignal?.addEventListener('abort', () => resolve())\n })\n channelRuntime = null\n channelCfg = null\n },\n stopAccount: async () => {\n channelRuntime = null\n channelCfg = null\n },\n },\n })\n\n function triggerHeartbeatWake(sessionKey: string, label: string): void {\n try {\n api.runtime.system.requestHeartbeatNow({ reason: 'wake', sessionKey })\n api.logger.info(`[AAMP] Heartbeat triggered for ${label} via session ${sessionKey}`)\n } catch (err) {\n api.logger.warn(`[AAMP] Could not trigger heartbeat for ${label}: ${(err as Error).message}`)\n }\n }\n\n function getConfiguredCardText(): string | undefined {\n const inline = cfg.cardText?.trim()\n if (inline) return inline\n\n const file = cfg.cardFile?.trim()\n if (!file) return undefined\n\n const fromFile = readFileSync(file, 'utf-8').trim()\n return fromFile || undefined\n }\n\n async function syncDirectoryProfile(): Promise<void> {\n if (!aampClient) return\n\n const summary = cfg.summary?.trim()\n const cardText = getConfiguredCardText()\n if (!summary && !cardText) return\n\n await aampClient.updateDirectoryProfile({\n ...(summary ? { summary } : {}),\n ...(cardText ? { cardText } : {}),\n })\n\n api.logger.info(`[AAMP] Directory profile synced${cardText ? ' (card text registered)' : ''}`)\n }\n\n function wakeAgentForPendingTask(task: PendingTask): void {\n const fallbackSessionKey = buildWakeSessionKeyForPendingTask(task, api.config)\n const openClawSessionKey = buildSessionKeyForPendingTask(task, api.config)\n const fallback = () => triggerHeartbeatWake(fallbackSessionKey, `task ${task.taskId}`)\n const dispatcher = channelRuntime?.reply?.dispatchReplyWithBufferedBlockDispatcher\n\n api.logger.info(\n `[AAMP] Wake requested for task ${task.taskId} \u2014 channelRuntime=${channelRuntime ? 'yes' : 'no'} channelCfg=${channelCfg ? 'yes' : 'no'} dispatcher=${typeof dispatcher === 'function' ? 'yes' : 'no'} session=${openClawSessionKey} fallbackSession=${fallbackSessionKey}`,\n )\n\n if (!channelRuntime || !channelCfg || typeof dispatcher !== 'function') {\n fallback()\n return\n }\n\n const prompt = [\n '## New AAMP Task',\n '',\n 'A new AAMP task just arrived.',\n 'Use the pending AAMP task in system context as the source of truth and handle it now.',\n 'Reply with aamp_send_result or aamp_send_help before responding.',\n ].join('\\n')\n\n try {\n void Promise.resolve(dispatcher({\n ctx: {\n Body: task.bodyText || task.title,\n BodyForAgent: prompt,\n From: task.from,\n To: agentEmail,\n SessionKey: openClawSessionKey,\n AccountId: 'default',\n ChatType: 'dm',\n Provider: 'aamp',\n Surface: 'aamp',\n OriginatingChannel: 'aamp',\n OriginatingTo: task.from,\n MessageSid: task.messageId || task.taskId,\n Timestamp: Date.now(),\n SenderName: task.from,\n SenderId: task.from,\n CommandAuthorized: true,\n },\n cfg: channelCfg,\n dispatcherOptions: {\n deliver: async () => {},\n onError: (err: unknown) => {\n api.logger.error(`[AAMP] Channel dispatch error for task ${task.taskId}: ${err instanceof Error ? err.message : String(err)}`)\n },\n },\n })).then(() => {\n api.logger.info(`[AAMP] Channel dispatch triggered for task ${task.taskId}`)\n }).catch((err: Error) => {\n api.logger.error(`[AAMP] Channel dispatch failed for task ${task.taskId}: ${err.message}`)\n fallback()\n })\n } catch (err) {\n api.logger.error(`[AAMP] Channel dispatch threw synchronously for task ${task.taskId}: ${(err as Error).message}`)\n fallback()\n }\n }\n\n async function reconcileMailbox(includeHistorical: boolean): Promise<void> {\n if (!aampClient) return\n\n const opts = includeHistorical ? { includeHistorical: true } : undefined\n const count = await aampClient.reconcileRecentEmails(100, opts)\n\n if (includeHistorical && !historicalReconcileCompleted) {\n historicalReconcileCompleted = true\n api.logger.info(`[AAMP] Historical mailbox reconcile complete (${count} email(s) scanned)`)\n }\n }\n\n // \u2500\u2500 Shared connect logic (used by service auto-connect and startup recovery) \u2500\u2500\u2500\u2500\u2500\u2500\n async function doConnect(identity: { email: string; mailboxToken?: string; smtpPassword: string }) {\n if (reconcileTimer) {\n clearInterval(reconcileTimer)\n reconcileTimer = null\n }\n if (transportMonitorTimer) {\n clearInterval(transportMonitorTimer)\n transportMonitorTimer = null\n }\n\n agentEmail = identity.email\n lastConnectionError = ''\n lastDisconnectReason = ''\n lastTransportMode = 'disconnected'\n lastLoggedTransportMode = 'disconnected'\n api.logger.info(`[AAMP] Mailbox identity ready \u2014 ${agentEmail}`)\n\n // All traffic goes through aampHost (port 3000).\n // The management service proxies /jmap/* and /.well-known/jmap \u2192 Stalwart:8080.\n const base = baseUrl(cfg.aampHost)\n\n aampClient = AampClient.fromMailboxIdentity({\n email: identity.email,\n smtpPassword: identity.smtpPassword,\n baseUrl: base,\n taskDispatchConcurrency: cfg.taskDispatchConcurrency,\n // Local/dev: management-service proxy uses plain HTTP, no TLS cert to verify.\n // Production: set to true when using wss:// with valid certs.\n rejectUnauthorized: false,\n })\n\n aampClient.on('task.dispatch', (task: TaskDispatch) => {\n api.logger.info(`[AAMP] \u2190 task.dispatch ${task.taskId} \"${task.title}\" from=${task.from}`)\n\n return (async () => {\n try {\n if (terminalTaskIds.has(task.taskId)) {\n api.logger.info(`[AAMP] Skipping already-terminal task ${task.taskId}`)\n return\n }\n\n // \u2500\u2500 Sender policy / dispatch-context authorization \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const decision = matchSenderPolicy(task, cfg.senderPolicies)\n if (!decision.allowed) {\n api.logger.warn(`[AAMP] \u2717 rejected by senderPolicies: ${task.from} task=${task.taskId} reason=${decision.reason}`)\n void aampClient!.sendResult({\n to: task.from,\n taskId: task.taskId,\n status: 'rejected',\n output: '',\n errorMsg: decision.reason ?? `Sender ${task.from} is not allowed.`,\n }).catch((err: Error) => {\n api.logger.error(`[AAMP] Failed to send rejection for task ${task.taskId}: ${err.message}`)\n })\n return\n }\n\n const hydratedTask = await aampClient!.hydrateTaskDispatch(task).catch((err: Error) => {\n api.logger.warn(`[AAMP] Failed to load thread history for ${task.taskId}: ${err.message}`)\n return {\n ...task,\n threadHistory: [],\n threadContextText: '',\n }\n })\n\n if (threadAlreadyTerminal(hydratedTask.threadHistory)) {\n rememberTerminalTask(task.taskId)\n api.logger.info(`[AAMP] Skipping historical task ${task.taskId} because the thread already reached a terminal state`)\n return\n }\n\n if (!queuePendingTask(hydratedTask)) {\n api.logger.info(`[AAMP] Ignoring already-terminal or expired task ${task.taskId}`)\n return\n }\n\n void ensureTaskStream(pendingTasks.get(task.taskId)!).catch((err: Error) => {\n api.logger.warn(`[AAMP] Failed to open stream for task ${task.taskId}: ${err.message}`)\n })\n\n // Wake the agent immediately after enqueueing the task.\n // In polling fallback mode heartbeat wakes can be delayed, so prefer a direct\n // channel dispatch when channelRuntime is available and only fall back to heartbeat.\n wakeAgentForPendingTask(pendingTasks.get(task.taskId)!)\n } catch (err) {\n api.logger.error(`[AAMP] task.dispatch handler failed for ${task.taskId}: ${(err as Error).message}`)\n if (pendingTasks.has(task.taskId)) {\n triggerHeartbeatWake(buildWakeSessionKeyForPendingTask(pendingTasks.get(task.taskId)!, api.config), `task ${task.taskId}`)\n }\n }\n })()\n })\n\n aampClient.on('task.cancel', (cancel: TaskCancel) => {\n api.logger.info(`[AAMP] \u2190 task.cancel ${cancel.taskId} from=${cancel.from}`)\n const removed = pendingTasks.delete(cancel.taskId)\n pendingTasks.delete(`result:${cancel.taskId}`)\n pendingTasks.delete(`help:${cancel.taskId}`)\n dispatchedSubtasks.delete(cancel.taskId)\n waitingDispatches.delete(cancel.taskId)\n rememberTerminalTask(cancel.taskId)\n void closeTaskStream(cancel.taskId, { reason: 'task.cancel' }).catch(() => {})\n if (removed) {\n api.logger.info(`[AAMP] Cancelled task ${cancel.taskId} \u2014 removed from pending queue`)\n }\n })\n\n // \u2500\u2500 Sub-task result: another agent completed a task we dispatched \u2500\u2500\u2500\u2500\u2500\u2500\n aampClient.on('task.result', (result: TaskResult) => {\n if (result.from.toLowerCase() === agentEmail.toLowerCase()) return\n api.logger.info(`[AAMP] \u2190 task.result ${result.taskId} status=${result.status} from=${result.from}`)\n\n const sub = dispatchedSubtasks.get(result.taskId)\n dispatchedSubtasks.delete(result.taskId)\n\n // \u2500\u2500 Synchronous dispatch: if aamp_dispatch_task is waiting, resolve it directly \u2500\u2500\n const waiter = waitingDispatches.get(result.taskId)\n if (waiter) {\n waitingDispatches.delete(result.taskId)\n api.logger.info(`[AAMP] Resolving sync waiter for sub-task ${result.taskId}`)\n waiter({ type: 'result', data: result })\n return // Don't go through heartbeat/channel \u2014 the LLM is already awake\n }\n\n // Pre-download attachments to local disk so the LLM can reference them\n // by local file path (instead of requiring a separate download tool call).\n const downloadedFiles: Array<{ filename: string; path: string; size: number }> = []\n const downloadPromise = (async () => {\n if (!result.attachments?.length) return\n const dir = '/tmp/aamp-files'\n ensureDir(dir)\n for (const att of result.attachments) {\n try {\n const buffer = await aampClient!.downloadBlob(att.blobId, att.filename)\n const filepath = `${dir}/${att.filename}`\n writeBinaryFile(filepath, buffer)\n downloadedFiles.push({ filename: att.filename, path: filepath, size: buffer.length })\n api.logger.info(`[AAMP] Pre-downloaded: ${att.filename} (${(buffer.length / 1024).toFixed(1)} KB) \u2192 ${filepath}`)\n } catch (dlErr) {\n api.logger.warn(`[AAMP] Pre-download failed for ${att.filename}: ${(dlErr as Error).message}`)\n }\n }\n })()\n\n downloadPromise.then(() => {\n // Build notification with pre-downloaded file paths\n const MAX_OUTPUT_CHARS = 800\n const label = result.status === 'completed' ? 'Sub-task completed' : 'Sub-task rejected'\n const rawOutput = result.output ?? ''\n const truncatedOutput = rawOutput.length > MAX_OUTPUT_CHARS\n ? rawOutput.slice(0, MAX_OUTPUT_CHARS) + `\\n\\n... [truncated, ${rawOutput.length} chars total]`\n : rawOutput\n\n let attachmentInfo = ''\n if (downloadedFiles.length > 0) {\n attachmentInfo = `\\n\\nAttachments (pre-downloaded to local disk):\\n${downloadedFiles.map(f =>\n `- ${f.filename} (${(f.size / 1024).toFixed(1)} KB) \u2192 ${f.path}`\n ).join('\\n')}\\nUse aamp_send_result with attachments: [${downloadedFiles.map(f => `{ filename: \"${f.filename}\", path: \"${f.path}\" }`).join(', ')}] to forward them.`\n } else if (result.attachments?.length) {\n const files = result.attachments.map((a: ReceivedAttachment) =>\n `${a.filename} (${(a.size / 1024).toFixed(1)} KB, blobId: ${a.blobId})`,\n )\n attachmentInfo = `\\n\\nAttachments (download failed \u2014 use aamp_download_attachment manually):\\n${files.join('\\n')}`\n }\n\n pendingTasks.set(`result:${result.taskId}`, {\n taskId: result.taskId,\n from: result.from,\n title: `${label}: ${sub?.title ?? result.taskId}`,\n bodyText: result.status === 'completed'\n ? `Agent ${result.from} completed the sub-task.\\n\\nOutput:\\n${truncatedOutput}${attachmentInfo}`\n : `Agent ${result.from} rejected the sub-task.\\n\\nReason: ${result.errorMsg ?? 'unknown'}`,\n priority: 'urgent',\n contextLinks: [],\n messageId: '',\n receivedAt: new Date().toISOString(),\n })\n\n // Wake LLM via channel dispatch (instant) or heartbeat (fallback)\n if (channelRuntime && channelCfg) {\n const notifyBody = pendingTasks.get(`result:${result.taskId}`)\n const actionableTasks = [...pendingTasks.entries()]\n .filter(([key]) => !key.startsWith('result:') && !key.startsWith('help:'))\n .map(([, t]) => t)\n const actionSection = actionableTasks.length > 0\n ? `\\n\\n### Action Required\\nYou MUST call aamp_send_result to complete the pending task(s):\\n${actionableTasks.map(t => `- Task ID: ${t.taskId} | From: ${t.from} | Title: \"${t.title}\"`).join('\\n')}`\n : ''\n const prompt = `## Sub-task Update\\n\\n${notifyBody?.bodyText ?? 'Sub-task completed.'}${actionSection}`\n\n channelRuntime.reply.dispatchReplyWithBufferedBlockDispatcher({\n ctx: {\n Body: `Sub-task result: ${result.taskId}`,\n BodyForAgent: prompt,\n From: result.from,\n To: agentEmail,\n SessionKey: buildAampConversationSessionKey(result.from, api.config),\n AccountId: 'default',\n ChatType: 'dm',\n Provider: 'aamp',\n Surface: 'aamp',\n OriginatingChannel: 'aamp',\n OriginatingTo: result.from,\n MessageSid: result.taskId,\n Timestamp: Date.now(),\n SenderName: result.from,\n SenderId: result.from,\n CommandAuthorized: true,\n },\n cfg: channelCfg,\n dispatcherOptions: {\n deliver: async () => {},\n onError: (err: unknown) => {\n api.logger.error(`[AAMP] Channel dispatch error: ${err instanceof Error ? err.message : String(err)}`)\n },\n },\n }).then(() => {\n api.logger.info(`[AAMP] Channel dispatch completed for sub-task result ${result.taskId}`)\n pendingTasks.delete(`result:${result.taskId}`)\n }).catch((err: Error) => {\n api.logger.error(`[AAMP] Channel dispatch failed: ${err.message}`)\n })\n } else {\n const notifySessionKey = buildAampWakeSessionKey('result', result.taskId)\n try {\n api.runtime.system.requestHeartbeatNow({ reason: 'wake', sessionKey: notifySessionKey })\n api.logger.info(`[AAMP] Heartbeat for sub-task result ${result.taskId}`)\n } catch (err) {\n api.logger.warn(`[AAMP] Heartbeat for sub-task result failed: ${(err as Error).message}`)\n }\n }\n }).catch((err: Error) => {\n api.logger.error(`[AAMP] Sub-task result processing failed: ${err.message}`)\n })\n })\n\n // \u2500\u2500 Sub-task help_needed: another agent asks for clarification \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n aampClient.on('task.help_needed', (help: TaskHelp) => {\n if (help.from.toLowerCase() === agentEmail.toLowerCase()) return\n api.logger.info(`[AAMP] \u2190 task.help_needed ${help.taskId} question=\"${help.question}\" from=${help.from}`)\n\n // \u2500\u2500 Synchronous dispatch: if aamp_dispatch_task is waiting, resolve it directly \u2500\u2500\n const waiter = waitingDispatches.get(help.taskId)\n if (waiter) {\n waitingDispatches.delete(help.taskId)\n api.logger.info(`[AAMP] Resolving sync waiter for sub-task help ${help.taskId}`)\n waiter({ type: 'help', data: help })\n return\n }\n\n const sub = dispatchedSubtasks.get(help.taskId)\n\n pendingTasks.set(`help:${help.taskId}`, {\n taskId: help.taskId,\n from: help.from,\n title: `Sub-task needs help: ${sub?.title ?? help.taskId}`,\n bodyText: `Agent ${help.from} is asking for help on the sub-task.\\n\\nQuestion: ${help.question}\\nBlocked reason: ${help.blockedReason}${help.suggestedOptions?.length ? `\\nSuggested options: ${help.suggestedOptions.join(', ')}` : ''}`,\n priority: 'urgent',\n contextLinks: [],\n messageId: '',\n receivedAt: new Date().toISOString(),\n })\n\n if (channelRuntime && channelCfg) {\n const notifyBody = pendingTasks.get(`help:${help.taskId}`)\n const prompt = `## Sub-task Help Request\\n\\n${notifyBody?.bodyText ?? help.question}`\n\n channelRuntime.reply.dispatchReplyWithBufferedBlockDispatcher({\n ctx: {\n Body: `Sub-task help: ${help.taskId}`,\n BodyForAgent: prompt,\n From: help.from,\n To: agentEmail,\n SessionKey: buildAampConversationSessionKey(help.from, api.config),\n AccountId: 'default',\n ChatType: 'dm',\n Provider: 'aamp',\n Surface: 'aamp',\n OriginatingChannel: 'aamp',\n OriginatingTo: help.from,\n MessageSid: help.taskId,\n Timestamp: Date.now(),\n SenderName: help.from,\n SenderId: help.from,\n CommandAuthorized: true,\n },\n cfg: channelCfg,\n dispatcherOptions: {\n deliver: async () => {},\n onError: (err: unknown) => {\n api.logger.error(`[AAMP] Channel dispatch error (help): ${err instanceof Error ? err.message : String(err)}`)\n },\n },\n }).then(() => {\n pendingTasks.delete(`help:${help.taskId}`)\n }).catch((err: Error) => {\n api.logger.error(`[AAMP] Channel dispatch failed for help: ${err.message}`)\n })\n } else {\n const helpSessionKey = buildAampWakeSessionKey('help', help.taskId)\n try {\n api.runtime.system.requestHeartbeatNow({ reason: 'wake', sessionKey: helpSessionKey })\n api.logger.info(`[AAMP] Heartbeat fallback for sub-task help ${help.taskId}`)\n } catch (err) {\n api.logger.warn(`[AAMP] Heartbeat for sub-task help failed: ${(err as Error).message}`)\n }\n }\n })\n\n aampClient.on('connected', () => {\n lastConnectionError = ''\n lastDisconnectReason = ''\n const mode = aampClient?.isUsingPollingFallback() ? 'polling' : 'websocket'\n logTransportState(api, mode, agentEmail, lastLoggedTransportMode)\n lastTransportMode = mode\n lastLoggedTransportMode = mode\n })\n\n aampClient.on('disconnected', (reason: string) => {\n lastDisconnectReason = reason\n if (lastTransportMode !== 'disconnected') {\n api.logger.warn(`[AAMP] Disconnected: ${reason} (will auto-reconnect)`)\n lastTransportMode = 'disconnected'\n lastLoggedTransportMode = 'disconnected'\n }\n })\n\n aampClient.on('error', (err: Error) => {\n lastConnectionError = err.message\n if (err.message.startsWith('JMAP WebSocket unavailable, falling back to polling:')) {\n if (lastTransportMode !== 'polling') {\n logTransportState(api, 'polling', agentEmail, lastLoggedTransportMode)\n lastTransportMode = 'polling'\n lastLoggedTransportMode = 'polling'\n }\n return\n }\n if (err.message.startsWith('Safety reconcile failed:') && isTransientTransportError(err.message)) {\n api.logger.warn(`[AAMP] ${err.message}`)\n return\n }\n api.logger.error(`[AAMP] ${err.message}`)\n })\n\n await aampClient.connect()\n await syncDirectoryProfile().catch((err: Error) => {\n api.logger.warn(`[AAMP] Directory profile sync failed: ${err.message}`)\n })\n\n api.logger.info(\n `[AAMP] Transport after connect \u2014 ${aampClient.isUsingPollingFallback() ? 'polling fallback' : 'websocket'} as ${agentEmail}`,\n )\n\n if (aampClient.isConnected() && lastTransportMode === 'disconnected') {\n if (aampClient.isUsingPollingFallback()) {\n logTransportState(api, 'polling', agentEmail, lastLoggedTransportMode)\n lastTransportMode = 'polling'\n lastLoggedTransportMode = 'polling'\n } else {\n logTransportState(api, 'websocket', agentEmail, lastLoggedTransportMode)\n lastTransportMode = 'websocket'\n lastLoggedTransportMode = 'websocket'\n }\n }\n\n setTimeout(() => {\n if (!aampClient?.isConnected()) return\n const mode = aampClient.isUsingPollingFallback() ? 'polling' : 'websocket'\n logTransportState(api, mode, agentEmail, lastLoggedTransportMode)\n lastTransportMode = mode\n lastLoggedTransportMode = mode\n }, 1000)\n\n void reconcileMailbox(!historicalReconcileCompleted).catch((err: Error) => {\n lastConnectionError = err.message\n if (!historicalReconcileCompleted) {\n api.logger.warn(`[AAMP] Startup mailbox reconcile failed: ${err.message} (will retry historical tasks)`)\n } else {\n api.logger.warn(`[AAMP] Startup mailbox reconcile failed: ${err.message}`)\n }\n })\n\n transportMonitorTimer = setInterval(() => {\n if (!aampClient) return\n if (!aampClient.isConnected()) {\n if (lastTransportMode !== 'disconnected') {\n lastTransportMode = 'disconnected'\n }\n return\n }\n const mode = aampClient.isUsingPollingFallback() ? 'polling' : 'websocket'\n logTransportState(api, mode, agentEmail, lastLoggedTransportMode)\n lastTransportMode = mode\n lastLoggedTransportMode = mode\n }, 5000)\n\n reconcileTimer = setInterval(() => {\n if (!aampClient) return\n const includeHistorical = !historicalReconcileCompleted\n void reconcileMailbox(includeHistorical).catch((err: Error) => {\n lastConnectionError = err.message\n if (includeHistorical) {\n api.logger.warn(`[AAMP] Mailbox reconcile failed while retrying historical tasks: ${err.message}`)\n } else {\n api.logger.warn(`[AAMP] Mailbox reconcile failed: ${err.message}`)\n }\n })\n }, 15000)\n }\n\n // \u2500\u2500 Service: auto-connect at gateway startup, disconnect on shutdown \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // registerService causes this plugin to load eagerly (at gateway startup),\n // not lazily (on first agent run). start() is called once the gateway is up.\n api.registerService({\n id: 'aamp-service',\n start: async () => {\n if (!cfg.aampHost) {\n api.logger.info('[AAMP] aampHost not configured \u2014 skipping auto-connect')\n return\n }\n try {\n const identity = await resolveIdentity(cfg)\n await doConnect(identity)\n } catch (err) {\n api.logger.warn(`[AAMP] Service auto-connect failed: ${(err as Error).message}`)\n }\n },\n stop: () => {\n if (reconcileTimer) {\n clearInterval(reconcileTimer)\n reconcileTimer = null\n }\n if (transportMonitorTimer) {\n clearInterval(transportMonitorTimer)\n transportMonitorTimer = null\n }\n if (aampClient) {\n try {\n aampClient.disconnect()\n api.logger.info('[AAMP] Disconnected on gateway stop')\n } catch {\n // ignore disconnect errors on shutdown\n }\n }\n },\n })\n\n // \u2500\u2500 gateway_start hook: re-trigger heartbeat after runner is initialized \u2500\u2500\u2500\n // Service start() runs BEFORE the heartbeat runner is ready, so\n // requestHeartbeatNow() called during JMAP initial fetch is silently dropped\n // (handler == null). gateway_start fires AFTER the heartbeat runner starts,\n // so we re-trigger here to process any tasks queued during startup.\n api.on('gateway_start', () => {\n if (pendingTasks.size === 0) return\n api.logger.info(`[AAMP] gateway_start: re-triggering heartbeat for ${pendingTasks.size} pending task(s)`)\n try {\n api.runtime.system.requestHeartbeatNow({\n reason: 'wake',\n sessionKey: buildAampWakeSessionKey('queue', 'gateway-start'),\n })\n } catch (err) {\n api.logger.warn(`[AAMP] gateway_start heartbeat failed: ${(err as Error).message}`)\n }\n })\n\n // \u2500\u2500 2. Prompt injection: surface the oldest pending task to the LLM \u2500\u2500\u2500\u2500\u2500\u2500\n api.on(\n 'before_prompt_build',\n (_event, ctx) => {\n // Only AAMP-owned sessions should receive mailbox task context.\n // This prevents regular user chats from inheriting pending email instructions.\n if (!isAampSessionKey(ctx?.sessionKey)) {\n return {}\n }\n\n // Expire tasks that have exceeded their dispatch expiry window.\n for (const [id, t] of pendingTasks) {\n if (hasExpired(t)) {\n if (!isSyntheticPendingKey(id) && aampClient?.isConnected()) {\n void aampClient.sendResult({\n to: t.from,\n taskId: t.taskId,\n status: 'rejected',\n output: '',\n errorMsg: t.expiresAt\n ? 'Task expired before the agent could complete it.'\n : 'Task timed out while waiting for agent completion or follow-up input.',\n inReplyTo: t.messageId || undefined,\n }).then(() => {\n rememberTerminalTask(t.taskId)\n api.logger.warn(`[AAMP] Task ${id} expired \u2014 sent rejected result to dispatcher`)\n }).catch((err: Error) => {\n api.logger.error(`[AAMP] Task ${id} expired \u2014 failed to notify dispatcher: ${err.message}`)\n })\n } else {\n rememberTerminalTask(t.taskId)\n api.logger.warn(`[AAMP] Task ${id} expired \u2014 removing from queue`)\n }\n pendingTasks.delete(id)\n }\n }\n\n if (pendingTasks.size === 0) return {}\n\n const targetedPendingKey = resolvePendingKeyFromSessionKey(ctx?.sessionKey)\n const targetedEntry = targetedPendingKey\n ? (() => {\n const targetedTask = pendingTasks.get(targetedPendingKey)\n if (!targetedTask) return undefined\n if (!isSyntheticPendingKey(targetedPendingKey) && isTaskAwaitingHelpReply(targetedTask)) {\n return undefined\n }\n return [targetedPendingKey, targetedTask] as [string, PendingTask]\n })()\n : undefined\n\n // Prioritize notifications (sub-task results/help) over actionable tasks.\n // Without this, the oldest actionable task blocks notification delivery,\n // preventing the LLM from seeing sub-task results and completing the parent task.\n const sessionScopedEntry = targetedPendingKey ? undefined : findPendingEntryForSession(ctx?.sessionKey, api.config)\n const nextEntry = targetedPendingKey ? targetedEntry : sessionScopedEntry ?? nextPendingEntry()\n if (!nextEntry) return {}\n const [taskKey, task] = nextEntry\n\n const isNotification = taskKey.startsWith('result:') || taskKey.startsWith('help:')\n\n // Notifications are one-shot: remove immediately after injecting into prompt\n if (isNotification && taskKey) {\n pendingTasks.delete(taskKey)\n }\n\n // Find remaining actionable tasks (non-notification) that still need a response\n const actionableTasks = [...pendingTasks.entries()]\n .filter(([key, pendingTask]) => isActionablePendingTask(key, pendingTask))\n .map(([, t]) => t)\n .sort((a, b) => {\n const rankDiff = priorityRank(a.priority) - priorityRank(b.priority)\n if (rankDiff !== 0) return rankDiff\n return new Date(a.receivedAt).getTime() - new Date(b.receivedAt).getTime()\n })\n const otherActionableTasks = actionableTasks.filter((pendingTask) => pendingTask.taskId !== task.taskId)\n\n const hasAttachmentInfo = isNotification && (task.bodyText?.includes('aamp_download_attachment') ?? false)\n const actionRequiredSection = isNotification && actionableTasks.length > 0\n ? [\n ``,\n `### Action Required`,\n ``,\n `You still have ${actionableTasks.length} pending task(s) that need a response.`,\n `Use the sub-task result above to complete them by calling aamp_send_result.`,\n ``,\n ...actionableTasks.map((t) =>\n `- [${t.priority}] Task ID: ${t.taskId} | From: ${t.from} | Title: \"${t.title}\"`\n ),\n ...(hasAttachmentInfo ? [\n ``,\n `### Forwarding Attachments`,\n `The sub-task result includes file attachments. To forward them:`,\n `1. Call aamp_download_attachment for each blobId listed above`,\n `2. Include the downloaded files in aamp_send_result via the attachments parameter`,\n ` Example: attachments: [{ filename: \"file.html\", path: \"/tmp/aamp-files/file.html\" }]`,\n ] : []),\n ].join('\\n')\n : ''\n\n const dispatchContextLines = task.dispatchContext && Object.keys(task.dispatchContext).length > 0\n ? `Dispatch Context:\\n${Object.entries(task.dispatchContext).map(([key, value]) => ` - ${key}: ${value}`).join('\\n')}`\n : ''\n\n const taskPromptLines = isConversationalTask(task) ? [\n `## Pending AAMP Conversation Turn`,\n ``,\n `This AAMP task came from a chat surface (${task.dispatchContext?.source ?? 'unknown'}).`,\n `Treat it as an ongoing conversation turn, not a one-off work order.`,\n `Your job is to reply naturally to the user's latest message and keep the conversation moving.`,\n ``,\n `### Tool selection rules for chat turns:`,\n ``,\n `Use aamp_send_result for normal conversation replies, including:`,\n ` - greetings, acknowledgements, and small talk (\"hi\", \"hello\", \"thanks\", \"got it\")`,\n ` - short follow-up questions that help narrow the user's intent`,\n ` - direct answers, suggestions, or next-step guidance`,\n ``,\n `Use aamp_send_help ONLY when you are truly blocked and cannot produce a meaningful`,\n `reply without waiting for specific missing information from the human.`,\n `Do NOT use aamp_send_help just because the message is brief or casual.`,\n ``,\n `IMPORTANT: For conversational traffic, replying to \"hi\" with a natural greeting and an`,\n `offer to help is CORRECT. Do not reject greetings as invalid tasks.`,\n ``,\n `### Sub-task dispatch rules:`,\n `If you delegate work to another agent via aamp_dispatch_task, you MUST pass`,\n `parentTaskId: \"${task.taskId}\" to establish the parent-child relationship.`,\n `If you need to find a suitable agent first, call aamp_directory_search.`,\n ``,\n `Task ID: ${task.taskId}`,\n `From: ${task.from}`,\n `Title: ${task.title}`,\n dispatchContextLines,\n task.threadContextText ? `${task.threadContextText}` : '',\n task.bodyText ? `Latest user message:\\n${task.bodyText}` : '',\n task.contextLinks.length\n ? `Context Links:\\n${task.contextLinks.map((l) => ` - ${l}`).join('\\n')}`\n : '',\n task.expiresAt ? `Expires: ${task.expiresAt}` : `Expires: none`,\n `Received: ${task.receivedAt}`,\n otherActionableTasks.length > 0 ? `\\n(+${otherActionableTasks.length} more tasks queued)` : '',\n ] : [\n `## Pending AAMP Task (action required)`,\n ``,\n `You have received a task via AAMP email. You MUST call one of the two tools below`,\n `BEFORE responding to the user \u2014 do not skip this step.`,\n ``,\n `### Tool selection rules (follow strictly):`,\n ``,\n `Use aamp_send_result ONLY when ALL of the following are true:`,\n ` 1. The title contains a clear, specific action verb (e.g. \"summarise\", \"review\",`,\n ` \"translate\", \"generate\", \"fix\", \"search\", \"compare\", \"list\")`,\n ` 2. You know exactly what input/resource to act on`,\n ` 3. No ambiguity remains \u2014 you could start work immediately without asking anything`,\n ``,\n `Use aamp_send_help in ALL other cases, including:`,\n ` - Title is a greeting or salutation (\"hello\", \"hi\", \"hey\", \"test\", \"ping\", etc.)`,\n ` - Title is fewer than 4 words and contains no actionable verb`,\n ` - Title is too vague to act on without guessing (e.g. \"help\", \"task\", \"question\")`,\n ` - Required context is missing (which file? which URL? which criteria?)`,\n ` - Multiple interpretations are equally plausible`,\n ``,\n `IMPORTANT: Responding to a greeting with a greeting is WRONG. \"hello\" is not a`,\n `valid task description \u2014 ask what specific task the dispatcher needs done.`,\n ``,\n `### Sub-task dispatch rules:`,\n `If you delegate work to another agent via aamp_dispatch_task, you MUST pass`,\n `parentTaskId: \"${task.taskId}\" to establish the parent-child relationship.`,\n `If you need to find a suitable agent first, call aamp_directory_search.`,\n ``,\n `Task ID: ${task.taskId}`,\n `From: ${task.from}`,\n `Title: ${task.title}`,\n dispatchContextLines,\n task.threadContextText ? `${task.threadContextText}` : '',\n task.bodyText ? `Description:\\n${task.bodyText}` : '',\n task.contextLinks.length\n ? `Context Links:\\n${task.contextLinks.map((l) => ` - ${l}`).join('\\n')}`\n : '',\n task.expiresAt ? `Expires: ${task.expiresAt}` : `Expires: none`,\n `Received: ${task.receivedAt}`,\n otherActionableTasks.length > 0 ? `\\n(+${otherActionableTasks.length} more tasks queued)` : '',\n ]\n\n const lines = isNotification ? [\n `## Sub-task Update`,\n ``,\n `A sub-task you dispatched has returned a result. Review the information below.`,\n `If the sub-task included attachments, use aamp_download_attachment to fetch them.`,\n ``,\n `Task ID: ${task.taskId}`,\n `Priority: ${task.priority}`,\n `From: ${task.from}`,\n `Title: ${task.title}`,\n task.bodyText ? `\\n${task.bodyText}` : '',\n actionRequiredSection,\n otherActionableTasks.length > 0 ? `\\n(+${otherActionableTasks.length} more tasks queued)` : '',\n ] : taskPromptLines\n .filter(Boolean)\n .join('\\n')\n\n return { prependContext: lines }\n },\n { priority: 5 },\n )\n\n // \u2500\u2500 3. Tool: send task result \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n api.registerTool({\n name: 'aamp_directory_search',\n description:\n 'Search the AAMP directory for agents by capability summary, card text, or email address.',\n parameters: {\n type: 'object',\n required: ['query'],\n properties: {\n query: { type: 'string', description: 'Capability or keyword to search for' },\n limit: { type: 'number', description: 'Maximum number of matches to return (default: 10)' },\n includeSelf: { type: 'boolean', description: 'Whether to include the current agent in results' },\n },\n },\n execute: async (_id, params) => {\n if (!aampClient) {\n return { content: [{ type: 'text', text: 'Error: AAMP client is not connected.' }] }\n }\n\n const query = String((params as { query?: string }).query ?? '').trim()\n if (!query) {\n return { content: [{ type: 'text', text: 'Error: query is required.' }] }\n }\n\n const agents = await aampClient.searchDirectory({\n query,\n limit: Number((params as { limit?: number }).limit ?? 10),\n includeSelf: Boolean((params as { includeSelf?: boolean }).includeSelf),\n })\n\n if (!agents.length) {\n return { content: [{ type: 'text', text: `No agents matched \"${query}\".` }] }\n }\n\n return {\n content: [{\n type: 'text',\n text: agents\n .map((agent, index) =>\n `${index + 1}. ${agent.email}${agent.summary ? ` \u2014 ${agent.summary}` : ''}`,\n )\n .join('\\n'),\n }],\n }\n },\n }, { name: 'aamp_directory_search' })\n\n api.registerTool({\n name: 'aamp_send_result',\n description:\n 'Send the result of an AAMP task back to the dispatcher. ' +\n 'Call this after you have finished processing the task.',\n parameters: {\n type: 'object',\n required: ['taskId', 'status', 'output'],\n properties: {\n taskId: {\n type: 'string',\n description: 'The AAMP task ID to reply to (from the system context)',\n },\n status: {\n type: 'string',\n enum: ['completed', 'rejected'],\n description: '\"completed\" on success, \"rejected\" if the task cannot be done',\n },\n output: {\n type: 'string',\n description: 'Your result or explanation',\n },\n errorMsg: {\n type: 'string',\n description: 'Optional error details (use only when status = rejected)',\n },\n attachments: {\n type: 'array',\n description: 'File attachments. Each item: { filename, contentType, path (local file path) }',\n items: {\n type: 'object',\n properties: {\n filename: { type: 'string' },\n contentType: { type: 'string' },\n path: { type: 'string', description: 'Absolute path to the file on disk' },\n },\n required: ['filename', 'path'],\n },\n },\n structuredResult: {\n type: 'array',\n description: 'Optional structured Meego field values.',\n items: {\n type: 'object',\n required: ['fieldKey', 'fieldTypeKey'],\n properties: {\n fieldKey: { type: 'string' },\n fieldTypeKey: { type: 'string' },\n fieldAlias: { type: 'string' },\n value: {\n description: 'Field value in the exact format required by Meego for this field type.',\n },\n index: { type: 'string' },\n attachmentFilenames: {\n type: 'array',\n items: { type: 'string' },\n description: 'For attachment fields, filenames from attachments[] that should be uploaded into this field.',\n },\n },\n },\n },\n },\n },\n execute: async (_id, params) => {\n const p = params as {\n taskId: string\n status: 'completed' | 'rejected'\n output: string\n errorMsg?: string\n attachments?: Array<{ filename: string; contentType?: string; path: string }>\n structuredResult?: StructuredResultFieldInput[]\n }\n\n const task = pendingTasks.get(p.taskId)\n if (!task) {\n return {\n content: [{ type: 'text', text: `Error: task ${p.taskId} not found in pending queue.` }],\n }\n }\n\n if (!aampClient?.isConnected()) {\n return { content: [{ type: 'text', text: 'Error: AAMP client is not connected.' }] }\n }\n\n api.logger.info(`[AAMP] aamp_send_result params ${JSON.stringify({\n taskId: p.taskId,\n status: p.status,\n output: p.output,\n errorMsg: p.errorMsg,\n attachments: p.attachments?.map((a) => ({\n filename: a.filename,\n contentType: a.contentType ?? 'application/octet-stream',\n path: a.path,\n })) ?? [],\n structuredResult: p.structuredResult?.map((field) => ({\n fieldKey: field.fieldKey,\n fieldTypeKey: field.fieldTypeKey,\n fieldAlias: field.fieldAlias,\n value: field.value,\n index: field.index,\n attachmentFilenames: field.attachmentFilenames ?? [],\n })) ?? [],\n })}`)\n\n // Build attachments from file paths\n let attachments: AampAttachment[] | undefined\n if (p.attachments?.length) {\n attachments = p.attachments.map((a: { filename: string; contentType?: string; path: string }) => ({\n filename: a.filename,\n contentType: a.contentType ?? 'application/octet-stream',\n content: readBinaryFile(a.path),\n }))\n }\n\n await appendTaskStream(task.taskId, 'status', {\n state: 'completing',\n label: `Sending ${p.status} result`,\n })\n if (p.output) {\n await appendTaskStream(task.taskId, 'text.delta', { text: p.output })\n }\n await closeTaskStream(task.taskId, {\n reason: 'task.result',\n status: p.status,\n ...(p.errorMsg ? { error: p.errorMsg } : {}),\n })\n\n await aampClient.sendResult({\n to: task.from,\n taskId: task.taskId,\n status: p.status,\n output: p.output,\n errorMsg: p.errorMsg,\n structuredResult: p.structuredResult?.length ? p.structuredResult : undefined,\n inReplyTo: task.messageId || undefined,\n attachments,\n })\n\n pendingTasks.delete(task.taskId)\n rememberTerminalTask(task.taskId)\n api.logger.info(`[AAMP] \u2192 task.result ${task.taskId} ${p.status}`)\n\n // If more tasks remain, wake the agent to process them\n if (pendingTasks.size > 0) {\n try {\n api.runtime.system.requestHeartbeatNow({\n reason: 'wake',\n sessionKey: buildAampWakeSessionKey('queue', 'follow-up'),\n })\n } catch { /* ignore */ }\n }\n\n return {\n content: [\n {\n type: 'text',\n text: `Result sent for task ${task.taskId} (status: ${p.status}).`,\n },\n ],\n }\n },\n }, { name: 'aamp_send_result' })\n\n // \u2500\u2500 4. Tool: ask for help \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n api.registerTool({\n name: 'aamp_send_help',\n description:\n 'Send a help request for an AAMP task when you are blocked or need human clarification ' +\n 'before you can proceed.',\n parameters: {\n type: 'object',\n required: ['taskId', 'question', 'blockedReason'],\n properties: {\n taskId: {\n type: 'string',\n description: 'The AAMP task ID',\n },\n question: {\n type: 'string',\n description: 'Your question for the human dispatcher',\n },\n blockedReason: {\n type: 'string',\n description: 'Why you cannot proceed without their input',\n },\n suggestedOptions: {\n type: 'array',\n items: { type: 'string' },\n description: 'Optional list of choices for the dispatcher to pick from',\n },\n },\n },\n execute: async (_id, params) => {\n const p = params as {\n taskId: string\n question: string\n blockedReason: string\n suggestedOptions?: string[]\n }\n\n const task = pendingTasks.get(p.taskId)\n if (!task) {\n return {\n content: [{ type: 'text', text: `Error: task ${p.taskId} not found in pending queue.` }],\n }\n }\n\n if (!aampClient?.isConnected()) {\n return { content: [{ type: 'text', text: 'Error: AAMP client is not connected.' }] }\n }\n\n await appendTaskStream(task.taskId, 'status', {\n state: 'help_needed',\n label: p.blockedReason,\n })\n\n try {\n await aampClient.sendHelp({\n to: task.from,\n taskId: task.taskId,\n question: p.question,\n blockedReason: p.blockedReason,\n suggestedOptions: p.suggestedOptions ?? [],\n inReplyTo: task.messageId || undefined,\n })\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n await appendTaskStream(task.taskId, 'error', {\n message: `Failed to send help request: ${message}`,\n })\n await appendTaskStream(task.taskId, 'status', {\n state: 'running',\n label: 'Help request failed; task still needs a reply',\n })\n api.logger.error(`[AAMP] aamp_send_help failed for ${task.taskId}: ${message}`)\n\n return {\n content: [\n {\n type: 'text',\n text: `Error: failed to send help request for task ${task.taskId}: ${message}`,\n },\n ],\n }\n }\n\n await closeTaskStream(task.taskId, {\n reason: 'task.help_needed',\n })\n\n pendingTasks.set(task.taskId, {\n ...task,\n awaitingHelpReply: true,\n })\n api.logger.info(`[AAMP] \u2192 task.help_needed ${task.taskId}`)\n\n // Keep the task in pending, but suspend it from auto-dispatch until new input arrives.\n return {\n content: [\n {\n type: 'text',\n text: `Help request sent for task ${task.taskId}. The task is now suspended until the dispatcher replies.`,\n },\n ],\n }\n },\n }, { name: 'aamp_send_help' })\n\n // \u2500\u2500 5. Tool: inspect queue \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n api.registerTool({\n name: 'aamp_pending_tasks',\n description: 'List all AAMP tasks currently waiting to be processed.',\n parameters: { type: 'object', properties: {} },\n execute: async () => {\n if (pendingTasks.size === 0) {\n return { content: [{ type: 'text', text: 'No pending AAMP tasks.' }] }\n }\n\n const lines = [...pendingTasks.values()]\n .sort((a, b) => {\n const rankDiff = priorityRank(a.priority) - priorityRank(b.priority)\n if (rankDiff !== 0) return rankDiff\n return new Date(a.receivedAt).getTime() - new Date(b.receivedAt).getTime()\n })\n .map(\n (t, i) =>\n `${i + 1}. [${t.priority}] [${t.taskId}] \"${t.title}\"${isTaskAwaitingHelpReply(t) ? ' (waiting for dispatcher reply)' : ''}${t.bodyText ? `\\n Description: ${t.bodyText}` : ''} \u2014 from ${t.from} (received ${t.receivedAt})`,\n )\n\n return {\n content: [\n {\n type: 'text',\n text: `${pendingTasks.size} pending task(s):\\n${lines.join('\\n')}`,\n },\n ],\n }\n },\n }, { name: 'aamp_pending_tasks' })\n\n api.registerTool({\n name: 'aamp_cancel_task',\n description: 'Cancel a pending AAMP task and notify the dispatcher.',\n parameters: {\n type: 'object',\n required: ['taskId'],\n properties: {\n taskId: { type: 'string', description: 'The AAMP task ID to cancel.' },\n bodyText: { type: 'string', description: 'Optional cancellation note sent in the email body.' },\n },\n },\n execute: async (_id, params) => {\n const p = params as { taskId: string; bodyText?: string }\n const task = pendingTasks.get(p.taskId)\n if (!task) {\n return { content: [{ type: 'text', text: `Error: task ${p.taskId} not found in pending queue.` }] }\n }\n if (!aampClient?.isConnected()) {\n return { content: [{ type: 'text', text: 'Error: AAMP client is not connected.' }] }\n }\n\n await aampClient.sendCancel({\n to: task.from,\n taskId: task.taskId,\n bodyText: p.bodyText,\n inReplyTo: task.messageId || undefined,\n })\n\n pendingTasks.delete(task.taskId)\n rememberTerminalTask(task.taskId)\n api.logger.info(`[AAMP] \u2192 task.cancel ${task.taskId}`)\n return {\n content: [{ type: 'text', text: `Cancellation sent for task ${task.taskId}.` }],\n }\n },\n }, { name: 'aamp_cancel_task' })\n\n // \u2500\u2500 6. Tool: dispatch task to another agent (SYNCHRONOUS) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Sends the task and BLOCKS until the sub-agent replies with task.result or\n // task.help_needed. The reply is returned directly as the tool result, keeping the\n // LLM awake with full context \u2014 no heartbeat/channel dispatch needed.\n api.registerTool({\n name: 'aamp_dispatch_task',\n description:\n 'Send a task to another AAMP agent and WAIT for the result. ' +\n 'This tool blocks until the sub-agent replies (typically 5-60s). ' +\n 'The sub-agent\\'s output and any attachment file paths are returned directly.',\n parameters: {\n type: 'object',\n required: ['to', 'title'],\n properties: {\n to: { type: 'string', description: 'Target agent AAMP email address' },\n title: { type: 'string', description: 'Task title (concise summary)' },\n bodyText: { type: 'string', description: 'Detailed task description' },\n parentTaskId: { type: 'string', description: 'If you are processing a pending AAMP task, pass its Task ID here to establish parent-child nesting. Omit for top-level tasks.' },\n priority: { type: 'string', enum: ['urgent', 'high', 'normal'], description: 'Task priority (optional)' },\n expiresAt: { type: 'string', description: 'Absolute expiry time in ISO 8601 format (optional)' },\n contextLinks: {\n type: 'array', items: { type: 'string' },\n description: 'URLs providing context (optional)',\n },\n attachments: {\n type: 'array',\n description: 'File attachments. Each item: { filename, contentType, path (local file path) }',\n items: {\n type: 'object',\n properties: {\n filename: { type: 'string' },\n contentType: { type: 'string' },\n path: { type: 'string', description: 'Absolute path to the file on disk' },\n },\n required: ['filename', 'path'],\n },\n },\n },\n },\n execute: async (_id: unknown, params: {\n to: string; title: string; bodyText?: string;\n parentTaskId?: string; priority?: TaskPriority; expiresAt?: string; contextLinks?: string[];\n attachments?: Array<{ filename: string; contentType?: string; path: string }>\n }) => {\n if (!aampClient?.isConnected()) {\n return { content: [{ type: 'text', text: 'Error: AAMP client is not connected.' }] }\n }\n\n try {\n // Build attachments from file paths\n let attachments: AampAttachment[] | undefined\n if (params.attachments?.length) {\n attachments = params.attachments.map((a: { filename: string; contentType?: string; path: string }) => ({\n filename: a.filename,\n contentType: a.contentType ?? 'application/octet-stream',\n content: readBinaryFile(a.path),\n }))\n }\n\n const result = await aampClient.sendTask({\n to: params.to,\n title: params.title,\n parentTaskId: params.parentTaskId,\n priority: params.priority,\n expiresAt: params.expiresAt,\n contextLinks: params.contextLinks,\n attachments,\n })\n\n // Track as dispatched sub-task\n dispatchedSubtasks.set(result.taskId, {\n to: params.to,\n title: params.title,\n dispatchedAt: new Date().toISOString(),\n parentTaskId: params.parentTaskId,\n })\n\n api.logger.info(`[AAMP] \u2192 task.dispatch ${result.taskId} to=${params.to} parent=${params.parentTaskId ?? 'none'} (waiting for reply\u2026)`)\n\n // \u2500\u2500 SYNCHRONOUS WAIT: block until sub-agent replies \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const timeoutMs = params.expiresAt\n ? Math.max(new Date(params.expiresAt).getTime() - Date.now(), 1)\n : 300 * 1000\n const reply = await new Promise<{ type: 'result' | 'help'; data: unknown }>((resolve, reject) => {\n waitingDispatches.set(result.taskId, resolve)\n setTimeout(() => {\n if (waitingDispatches.delete(result.taskId)) {\n reject(new Error(\n params.expiresAt\n ? `Sub-task ${result.taskId} expired before a reply was received`\n : `Sub-task ${result.taskId} timed out after 300s`,\n ))\n }\n }, timeoutMs)\n })\n\n api.logger.info(`[AAMP] \u2190 sync reply for ${result.taskId}: type=${reply.type} attachments=${JSON.stringify((reply.data as any)?.attachments?.length ?? 0)}`)\n\n if (reply.type === 'result') {\n const r = reply.data as TaskResult\n\n // Pre-download attachments \u2014 use direct JMAP blob download (bypass SDK's downloadBlob\n // which was returning 404 due to URL construction issues in the esbuild bundle).\n let attachmentLines = ''\n if (r.attachments?.length) {\n api.logger.info(`[AAMP] Downloading ${r.attachments.length} attachment(s) from sync reply...`)\n const dir = '/tmp/aamp-files'\n ensureDir(dir)\n const downloaded: string[] = []\n const base = baseUrl(cfg.aampHost)\n const identity = loadCachedIdentity(cfg.credentialsFile ?? defaultCredentialsPath())\n const authHeader = identity ? `Basic ${Buffer.from(identity.email + ':' + identity.smtpPassword).toString('base64')}` : ''\n for (const att of r.attachments) {\n try {\n // Direct JMAP blob download \u2014 construct URL manually\n const dlUrl = `${base}/jmap/download/n/${encodeURIComponent(att.blobId)}/${encodeURIComponent(att.filename)}?accept=application/octet-stream`\n api.logger.info(`[AAMP] Fetching ${dlUrl}`)\n const dlRes = await fetch(dlUrl, { headers: { Authorization: authHeader } })\n if (!dlRes.ok) throw new Error(`HTTP ${dlRes.status}`)\n const buffer = Buffer.from(await dlRes.arrayBuffer())\n const filepath = `${dir}/${att.filename}`\n writeBinaryFile(filepath, buffer)\n downloaded.push(`${att.filename} (${(buffer.length / 1024).toFixed(1)} KB) \u2192 ${filepath}`)\n api.logger.info(`[AAMP] Downloaded: ${att.filename} (${(buffer.length / 1024).toFixed(1)} KB)`)\n } catch (dlErr) {\n api.logger.error(`[AAMP] Download failed for ${att.filename}: ${(dlErr as Error).message}`)\n }\n }\n if (downloaded.length) {\n attachmentLines = `\\n\\nAttachments downloaded:\\n${downloaded.join('\\n')}`\n }\n }\n\n return {\n content: [{\n type: 'text',\n text: [\n `Sub-task ${r.status}: ${params.title}`,\n `Agent: ${r.from}`,\n `Task ID: ${result.taskId}`,\n r.status === 'completed' ? `\\nOutput:\\n${r.output}` : `\\nError: ${r.errorMsg ?? 'rejected'}`,\n attachmentLines,\n ].filter(Boolean).join('\\n'),\n }],\n }\n } else {\n const h = reply.data as TaskHelp\n return {\n content: [{\n type: 'text',\n text: [\n `Sub-task needs help: ${params.title}`,\n `Agent: ${h.from}`,\n `Task ID: ${result.taskId}`,\n `\\nQuestion: ${h.question}`,\n `Blocked reason: ${h.blockedReason}`,\n h.suggestedOptions?.length ? `Options: ${h.suggestedOptions.join(' | ')}` : '',\n ].filter(Boolean).join('\\n'),\n }],\n }\n }\n } catch (err) {\n return {\n content: [{ type: 'text', text: `Error dispatching task: ${(err as Error).message}` }],\n }\n }\n },\n }, { name: 'aamp_dispatch_task' })\n\n // \u2500\u2500 7. Tool: check AAMP protocol support \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n api.registerTool({\n name: 'aamp_check_protocol',\n description:\n 'Check if an email address supports the AAMP protocol. ' +\n 'Returns { aamp: true/false } indicating whether the address is an AAMP agent.',\n parameters: {\n type: 'object',\n required: ['email'],\n properties: {\n email: { type: 'string', description: 'Email address to check' },\n },\n },\n execute: async (_id: unknown, params: { email: string }) => {\n const base = baseUrl(cfg.aampHost)\n const email = params?.email ?? ''\n if (!email) {\n return { content: [{ type: 'text', text: 'Error: email parameter is required' }] }\n }\n try {\n const discoveryRes = await fetch(`${base}/.well-known/aamp`)\n if (!discoveryRes.ok) throw new Error(`HTTP ${discoveryRes.status}`)\n const discovery = await discoveryRes.json() as { api?: { url?: string } }\n const apiUrl = discovery.api?.url\n if (!apiUrl) throw new Error('AAMP discovery did not return api.url')\n const apiBase = new URL(apiUrl, `${base}/`).toString()\n const res = await fetch(`${apiBase}?action=aamp.mailbox.check&email=${encodeURIComponent(email)}`)\n if (!res.ok) throw new Error(`HTTP ${res.status}`)\n const data = await res.json() as { aamp: boolean; domain?: string }\n return {\n content: [{\n type: 'text',\n text: data.aamp\n ? `${params.email} supports AAMP protocol (domain: ${data.domain ?? 'unknown'})`\n : `${params.email} does not support AAMP protocol`,\n }],\n }\n } catch (err) {\n return {\n content: [{ type: 'text', text: `Could not check ${params.email}: ${(err as Error).message}` }],\n }\n }\n },\n }, { name: 'aamp_check_protocol' })\n\n // \u2500\u2500 8. Tool: download attachment blob \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n api.registerTool({\n name: 'aamp_download_attachment',\n description:\n 'Download an AAMP email attachment to local disk by its blobId. ' +\n 'Use this to retrieve files received from sub-agent task results.',\n parameters: {\n type: 'object',\n required: ['blobId', 'filename'],\n properties: {\n blobId: { type: 'string', description: 'The JMAP blobId from the attachment metadata' },\n filename: { type: 'string', description: 'Filename to save as' },\n saveTo: { type: 'string', description: 'Directory to save to (default: /tmp/aamp-files)' },\n },\n },\n execute: async (_id: unknown, params: { blobId: string; filename: string; saveTo?: string }) => {\n if (!aampClient?.isConnected()) {\n return { content: [{ type: 'text', text: 'Error: AAMP client is not connected.' }] }\n }\n\n const dir = params.saveTo ?? '/tmp/aamp-files'\n ensureDir(dir)\n\n try {\n const buffer = await aampClient.downloadBlob(params.blobId, params.filename)\n const filepath = `${dir}/${params.filename}`\n writeBinaryFile(filepath, buffer)\n return {\n content: [{\n type: 'text',\n text: `Downloaded ${params.filename} (${(buffer.length / 1024).toFixed(1)} KB) to ${filepath}`,\n }],\n }\n } catch (err) {\n return {\n content: [{ type: 'text', text: `Download failed: ${(err as Error).message}` }],\n }\n }\n },\n }, { name: 'aamp_download_attachment' })\n\n // \u2500\u2500 9. Slash command: /aamp-status \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n api.registerCommand({\n name: 'aamp-status',\n description: 'Show AAMP connection status and pending task queue',\n acceptsArgs: false,\n requireAuth: false,\n handler: () => {\n const isPollingFallback = aampClient?.isUsingPollingFallback?.() ?? false\n const connectionLine = aampClient?.isConnected()\n ? (isPollingFallback ? '\uD83D\uDFE1 connected (polling fallback)' : '\u2705 connected')\n : '\u274C disconnected'\n\n return {\n text: [\n `**AAMP Plugin Status**`,\n `Host: ${cfg.aampHost || '(not configured)'}`,\n `Identity: ${agentEmail || '(not yet registered)'}`,\n `Connection: ${connectionLine}`,\n `Cached: ${loadCachedIdentity(cfg.credentialsFile ?? defaultCredentialsPath()) ? 'yes' : 'no'}`,\n lastConnectionError ? `Last error: ${lastConnectionError}` : '',\n lastDisconnectReason ? `Last disconnect: ${lastDisconnectReason}` : '',\n `Pending: ${pendingTasks.size} task(s)`,\n ...[...pendingTasks.values()].map(\n (t) => ` \u2022 ${t.taskId.slice(0, 8)}\u2026 \"${t.title}\" from ${t.from}`,\n ),\n ]\n .filter(Boolean)\n .join('\\n'),\n }\n },\n })\n },\n}\n", "import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { homedir } from 'node:os'\n\nexport interface Identity {\n email: string\n mailboxToken: string\n smtpPassword: string\n}\n\nexport interface CachedTaskState {\n terminalTaskIds?: string[]\n}\n\nexport function defaultCredentialsPath(): string {\n return join(homedir(), '.openclaw', 'extensions', 'aamp-openclaw-plugin', '.credentials.json')\n}\n\nexport function defaultTaskStatePath(): string {\n return join(homedir(), '.openclaw', 'extensions', 'aamp-openclaw-plugin', '.task-state.json')\n}\n\nexport function loadCachedIdentity(file?: string): Identity | null {\n const resolved = file ?? defaultCredentialsPath()\n if (!existsSync(resolved)) return null\n try {\n const parsed = JSON.parse(readFileSync(resolved, 'utf-8')) as Partial<Identity>\n if (!parsed.email || !parsed.mailboxToken || !parsed.smtpPassword) return null\n return {\n email: parsed.email,\n mailboxToken: parsed.mailboxToken,\n smtpPassword: parsed.smtpPassword,\n }\n } catch {\n return null\n }\n}\n\nexport function saveCachedIdentity(identity: Identity, file?: string): void {\n const resolved = file ?? defaultCredentialsPath()\n mkdirSync(dirname(resolved), { recursive: true })\n writeFileSync(resolved, JSON.stringify({\n email: identity.email,\n mailboxToken: identity.mailboxToken,\n smtpPassword: identity.smtpPassword,\n }, null, 2), 'utf-8')\n}\n\nexport function loadTaskState(file?: string): CachedTaskState {\n const resolved = file ?? defaultTaskStatePath()\n if (!existsSync(resolved)) return { terminalTaskIds: [] }\n try {\n const parsed = JSON.parse(readFileSync(resolved, 'utf-8')) as CachedTaskState\n return {\n terminalTaskIds: Array.isArray(parsed.terminalTaskIds) ? parsed.terminalTaskIds.filter(Boolean) : [],\n }\n } catch {\n return { terminalTaskIds: [] }\n }\n}\n\nexport function saveTaskState(state: CachedTaskState, file?: string): void {\n const resolved = file ?? defaultTaskStatePath()\n mkdirSync(dirname(resolved), { recursive: true })\n writeFileSync(resolved, JSON.stringify({\n terminalTaskIds: state.terminalTaskIds ?? [],\n }, null, 2), 'utf-8')\n}\n\nexport function ensureDir(dir: string): void {\n mkdirSync(dir, { recursive: true })\n}\n\nexport function readBinaryFile(path: string): Buffer {\n return readFileSync(path)\n}\n\nexport function writeBinaryFile(path: string, content: Uint8Array | Buffer): void {\n mkdirSync(dirname(path), { recursive: true })\n writeFileSync(path, content)\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
3
|
+
"sources": ["../../sdk/src/jmap-push.ts", "../../sdk/src/types.ts", "../../sdk/src/parser.ts", "../../sdk/src/tiny-emitter.ts", "../../sdk/src/smtp-sender.ts", "../../sdk/src/thread.ts", "../../sdk/src/client.ts", "../src/index.ts", "../src/file-store.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * JMAP WebSocket Push Client\n *\n * Connects to Stalwart's JMAP WebSocket endpoint and subscribes to\n * Email StateChange events. When a new email arrives in the agent's\n * mailbox, fetches it via JMAP and emits the parsed AAMP headers.\n *\n * Protocol: RFC 8887 (JMAP over WebSocket)\n * Ref: https://www.rfc-editor.org/rfc/rfc8887\n */\n\nimport WebSocket from 'ws'\nimport { parseAampHeaders } from './parser.js'\nimport type {\n AampMessage,\n CardQuery,\n CardResponse,\n HumanReply,\n TaskAck,\n TaskCancel,\n TaskDispatch,\n TaskHelp,\n TaskResult,\n TaskStreamOpened,\n} from './types.js'\nimport { TinyEmitter } from './tiny-emitter.js'\n\ninterface JmapSession {\n capabilities: Record<string, unknown>\n accounts: Record<string, { name: string; isPrimary: boolean; accountCapabilities: Record<string, unknown> }>\n primaryAccounts: Record<string, string>\n username: string\n apiUrl: string\n downloadUrl: string\n uploadUrl: string\n eventSourceUrl: string\n state: string\n}\n\ninterface JmapStateChange {\n '@type': 'StateChange'\n changed: Record<string, Record<string, string>>\n pushState?: string\n}\n\ninterface JmapEmail {\n id: string\n blobId: string\n threadId: string\n mailboxIds: Record<string, boolean>\n subject: string\n from: Array<{ email: string; name?: string }>\n to: Array<{ email: string; name?: string }>\n replyTo?: Array<{ email: string; name?: string }>\n messageId?: string[]\n headers: Array<{ name: string; value: string }>\n receivedAt: string\n size: number\n /** Plain-text body parts (JMAP bodyStructure) */\n textBody?: Array<{ partId: string; type: string }>\n /** Decoded body values keyed by partId */\n bodyValues?: Record<string, { value: string; isEncodingProblem?: boolean; isTruncated?: boolean }>\n /** JMAP attachments (non-inline parts) */\n attachments?: Array<{\n blobId: string\n type: string\n name: string | null\n size: number\n }>\n}\n\ninterface JmapMethodResponse {\n methodResponses: Array<[string, Record<string, unknown>, string]>\n}\n\nfunction describeError(err: unknown): string {\n if (!(err instanceof Error)) return String(err)\n\n const parts = [err.message]\n const details = err as Error & {\n code?: string\n errno?: number | string\n syscall?: string\n address?: string\n port?: number\n cause?: unknown\n }\n\n if (details.code) parts.push(`code=${details.code}`)\n if (details.errno !== undefined) parts.push(`errno=${details.errno}`)\n if (details.syscall) parts.push(`syscall=${details.syscall}`)\n if (details.address) parts.push(`address=${details.address}`)\n if (details.port !== undefined) parts.push(`port=${details.port}`)\n\n if (details.cause instanceof Error) {\n parts.push(`cause=${describeError(details.cause)}`)\n } else if (details.cause !== undefined) {\n parts.push(`cause=${String(details.cause)}`)\n }\n\n return parts.join(' | ')\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nfunction shouldRetrySessionFetch(status: number): boolean {\n return status === 429 || status >= 500\n}\n\nfunction shouldRetryBlobDownload(status: number): boolean {\n return status === 404 || status === 429 || status === 503\n}\n\nfunction rewriteUrlToConfiguredOrigin(rawUrl: string, configuredBaseUrl: string): string {\n const parsed = new URL(rawUrl)\n const configured = new URL(configuredBaseUrl)\n parsed.protocol = configured.protocol\n parsed.username = configured.username\n parsed.password = configured.password\n parsed.hostname = configured.hostname\n parsed.port = configured.port\n return parsed.toString()\n}\n\nconst SESSION_FETCH_MAX_ATTEMPTS = 3\nconst SESSION_FETCH_RETRY_BASE_DELAY_MS = 250\n\ntype JmapPushEvents = {\n 'task.dispatch': (task: TaskDispatch) => void\n 'task.cancel': (task: TaskCancel) => void\n 'task.result': (result: TaskResult) => void\n 'task.help_needed': (help: TaskHelp) => void\n 'task.ack': (ack: TaskAck) => void\n 'task.stream.opened': (stream: TaskStreamOpened) => void\n 'card.query': (query: CardQuery) => void\n 'card.response': (response: CardResponse) => void\n reply: (reply: HumanReply) => void\n connected: () => void\n disconnected: (reason: string) => void\n error: (err: Error) => void\n _autoAck: (payload: { to: string; taskId: string; messageId: string }) => void\n}\n\nexport class JmapPushClient extends TinyEmitter<JmapPushEvents> {\n private ws: WebSocket | null = null\n private session: JmapSession | null = null\n private reconnectTimer: NodeJS.Timeout | null = null\n private pollTimer: NodeJS.Timeout | null = null\n private pingTimer: NodeJS.Timeout | null = null\n private safetySyncTimer: NodeJS.Timeout | null = null\n private readonly seenMessageIds = new Set<string>()\n private connected = false\n private pollingActive = false\n private running = false\n private connecting = false\n /** JMAP Email state \u2014 tracks processed position; null = not yet initialized */\n private emailState: string | null = null\n private readonly startedAtMs = Date.now()\n\n private readonly email: string\n private readonly password: string\n private readonly jmapUrl: string\n private readonly reconnectInterval: number\n private readonly rejectUnauthorized: boolean\n private readonly pingIntervalMs = 5000\n private readonly safetySyncIntervalMs = 5000\n\n constructor(opts: {\n email: string\n password: string\n jmapUrl: string\n reconnectInterval?: number\n /** Whether to reject unauthorized TLS certificates (default: true) */\n rejectUnauthorized?: boolean\n }) {\n super()\n this.email = opts.email\n this.password = opts.password\n this.jmapUrl = opts.jmapUrl.replace(/\\/$/, '')\n this.reconnectInterval = opts.reconnectInterval ?? 5000\n this.rejectUnauthorized = opts.rejectUnauthorized ?? true\n }\n\n /**\n * Start the JMAP Push listener\n */\n async start(): Promise<void> {\n this.running = true\n this.startSafetySync()\n await this.connect()\n }\n\n /**\n * Stop the JMAP Push listener\n */\n stop(): void {\n this.running = false\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer)\n this.reconnectTimer = null\n }\n if (this.pollTimer) {\n clearTimeout(this.pollTimer)\n this.pollTimer = null\n }\n if (this.pingTimer) {\n clearInterval(this.pingTimer)\n this.pingTimer = null\n }\n if (this.safetySyncTimer) {\n clearInterval(this.safetySyncTimer)\n this.safetySyncTimer = null\n }\n if (this.ws) {\n this.ws.close()\n this.ws = null\n }\n this.connected = false\n this.pollingActive = false\n this.connecting = false\n }\n\n private getAuthHeader(): string {\n const creds = `${this.email}:${this.password}`\n return `Basic ${Buffer.from(creds).toString('base64')}`\n }\n\n /**\n * Fetch the JMAP session object\n */\n private async fetchSession(): Promise<JmapSession> {\n const url = `${this.jmapUrl}/.well-known/jmap`\n let lastError: Error | null = null\n\n for (let attempt = 1; attempt <= SESSION_FETCH_MAX_ATTEMPTS; attempt += 1) {\n let res: Response\n try {\n res = await fetch(url, {\n headers: { Authorization: this.getAuthHeader() },\n })\n } catch (err) {\n lastError = new Error(`fetchSession ${url} failed: ${describeError(err)}`)\n if (attempt >= SESSION_FETCH_MAX_ATTEMPTS) throw lastError\n await sleep(SESSION_FETCH_RETRY_BASE_DELAY_MS * attempt)\n continue\n }\n\n if (res.ok) {\n return res.json() as Promise<JmapSession>\n }\n\n lastError = new Error(\n attempt >= SESSION_FETCH_MAX_ATTEMPTS || !shouldRetrySessionFetch(res.status)\n ? `Failed to fetch JMAP session: ${res.status} ${res.statusText}`\n : `Failed to fetch JMAP session after ${attempt} attempt(s): ${res.status} ${res.statusText}`,\n )\n if (attempt >= SESSION_FETCH_MAX_ATTEMPTS || !shouldRetrySessionFetch(res.status)) {\n throw lastError\n }\n\n await sleep(SESSION_FETCH_RETRY_BASE_DELAY_MS * attempt)\n }\n\n throw lastError ?? new Error('Failed to fetch JMAP session')\n }\n\n /**\n * Perform a JMAP API call\n */\n private async jmapCall(\n methods: Array<[string, Record<string, unknown>, string]>,\n ): Promise<JmapMethodResponse> {\n if (!this.session) throw new Error('No JMAP session')\n\n // Use the configured jmapUrl (external hostname) rather than session.apiUrl\n // which Stalwart populates with its own internal URL (e.g. http://aamp.local:8080/jmap)\n // and is unreachable when running behind a proxy.\n const apiUrl = `${this.jmapUrl}/jmap/`\n let res: Response\n try {\n res = await fetch(apiUrl, {\n method: 'POST',\n headers: {\n Authorization: this.getAuthHeader(),\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n using: [\n 'urn:ietf:params:jmap:core',\n 'urn:ietf:params:jmap:mail',\n ],\n methodCalls: methods,\n }),\n })\n } catch (err) {\n throw new Error(`jmapCall ${apiUrl} failed: ${describeError(err)}`)\n }\n\n if (!res.ok) {\n throw new Error(`JMAP API call failed: ${res.status}`)\n }\n\n return res.json() as Promise<JmapMethodResponse>\n }\n\n /**\n * Initialize emailState by fetching the current state without loading any emails.\n * Called on first connect so we only process emails that arrive AFTER this point.\n */\n private async initEmailState(accountId: string): Promise<void> {\n const response = await this.jmapCall([\n ['Email/get', { accountId, ids: [] }, 'g0'],\n ])\n const getResp = response.methodResponses.find(([name]) => name === 'Email/get')\n if (getResp) {\n this.emailState = (getResp[1] as { state?: string }).state ?? null\n }\n }\n\n /**\n * Fetch only emails created since `sinceState` using Email/changes.\n * Updates `this.emailState` to the new state after fetching.\n * Returns [] and resets state if the server cannot calculate changes (state too old).\n */\n private async fetchEmailsSince(accountId: string, sinceState: string): Promise<JmapEmail[]> {\n const changesResp = await this.jmapCall([\n ['Email/changes', { accountId, sinceState, maxChanges: 50 }, 'c1'],\n ])\n\n const changesResult = changesResp.methodResponses.find(([name]) => name === 'Email/changes')\n\n // Handle server error \u2014 e.g. \"cannotCalculateChanges\" when state is too old\n if (!changesResult || changesResult[0] === 'error') {\n await this.initEmailState(accountId)\n return []\n }\n\n const changes = changesResult[1] as {\n created?: string[]\n newState?: string\n hasMoreChanges?: boolean\n }\n\n if (changes.newState) {\n this.emailState = changes.newState\n }\n\n const newIds = changes.created ?? []\n if (newIds.length === 0) return []\n\n const emailResp = await this.jmapCall([\n [\n 'Email/get',\n {\n accountId,\n ids: newIds,\n properties: ['id', 'subject', 'from', 'to', 'headers', 'messageId', 'receivedAt', 'textBody', 'bodyValues', 'attachments'],\n fetchTextBodyValues: true,\n maxBodyValueBytes: 262144,\n },\n 'g1',\n ],\n ])\n\n const getResult = emailResp.methodResponses.find(([name]) => name === 'Email/get')\n if (!getResult) return []\n\n const data = getResult[1] as { list?: JmapEmail[] }\n return data.list ?? []\n }\n\n /**\n * Process a received email.\n *\n * Priority:\n * 1. If X-AAMP-Intent is present \u2192 emit typed AAMP event (task.dispatch / task.cancel / task.result / task.help_needed)\n * 2. If In-Reply-To is present \u2192 emit 'reply' event so the application layer can\n * resolve the thread (inReplyTo \u2192 taskId via Redis/DB) and handle human replies.\n * 3. Otherwise \u2192 ignore (not an AAMP-related email)\n */\n private processEmail(email: JmapEmail): void {\n // Build lowercase header map from JMAP header array\n const headerMap: Record<string, string> = {}\n for (const h of email.headers ?? []) {\n headerMap[h.name.toLowerCase()] = h.value.trim()\n }\n\n const fromAddr = email.from?.[0]?.email ?? ''\n const toAddr = email.to?.[0]?.email ?? ''\n const messageId = email.messageId?.[0] ?? email.id\n\n if (this.seenMessageIds.has(messageId)) return\n this.seenMessageIds.add(messageId)\n\n // \u2500\u2500 Path 1: AAMP-tagged email \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const aampTextPartId = email.textBody?.[0]?.partId\n const aampBodyText = aampTextPartId ? (email.bodyValues?.[aampTextPartId]?.value ?? '').trim() : ''\n\n const msg: AampMessage | null = parseAampHeaders({\n from: fromAddr,\n to: toAddr,\n messageId,\n subject: email.subject ?? '',\n headers: headerMap,\n bodyText: aampBodyText,\n })\n\n if (msg && 'intent' in msg) {\n // Attach email body text (task description) to all AAMP messages\n ;(msg as unknown as Record<string, unknown>).bodyText = aampBodyText\n\n // Attach received attachment metadata (blobId-based, downloadable via downloadBlob)\n const receivedAttachments = (email.attachments ?? []).map(a => ({\n filename: a.name ?? 'attachment',\n contentType: a.type,\n size: a.size,\n blobId: a.blobId,\n }))\n if (receivedAttachments.length > 0) {\n ;(msg as unknown as Record<string, unknown>).attachments = receivedAttachments\n }\n\n // Auto-ACK for dispatches \u2014 AampClient handles the actual sending\n if ((msg as { intent: string }).intent === 'task.dispatch') {\n this.emit('_autoAck', { to: fromAddr, taskId: (msg as { taskId: string }).taskId, messageId })\n }\n\n const aampMsg = msg as Exclude<AampMessage, HumanReply>\n switch (aampMsg.intent) {\n case 'task.dispatch':\n this.emit('task.dispatch', aampMsg)\n break\n case 'task.cancel':\n this.emit('task.cancel', aampMsg)\n break\n case 'task.result':\n this.emit('task.result', aampMsg)\n break\n case 'task.help_needed':\n this.emit('task.help_needed', aampMsg)\n break\n case 'task.ack':\n this.emit('task.ack', aampMsg)\n break\n case 'task.stream.opened':\n this.emit('task.stream.opened', aampMsg)\n break\n case 'card.query':\n this.emit('card.query', aampMsg)\n break\n case 'card.response':\n this.emit('card.response', aampMsg)\n break\n }\n return\n }\n\n // \u2500\u2500 Path 2: standard email reply \u2014 In-Reply-To fallback \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Standard email clients automatically set In-Reply-To when replying.\n // We strip angle brackets (<msgid@host>) to get the bare Message-ID.\n const rawInReplyTo = headerMap['in-reply-to'] ?? ''\n if (!rawInReplyTo) return // unrelated email, ignore\n\n // Handle \"References\" chain: prefer the last (most recent) Message-ID\n // so multi-turn threads still resolve to the correct task.\n const rawReferences = headerMap['references'] ?? ''\n const referencesIds = rawReferences\n .split(/\\s+/)\n .map((s) => s.replace(/[<>]/g, '').trim())\n .filter(Boolean)\n\n const inReplyTo = rawInReplyTo.replace(/[<>]/g, '').trim()\n\n // Extract plain-text body if available (fetched via fetchTextBodyValues)\n const textPartId = email.textBody?.[0]?.partId\n const bodyText = textPartId ? (email.bodyValues?.[textPartId]?.value ?? '').trim() : ''\n\n const reply: HumanReply = {\n inReplyTo,\n messageId,\n from: fromAddr,\n to: toAddr,\n subject: email.subject ?? '',\n bodyText,\n }\n\n // Also expose the full References chain so callers can walk the thread if needed\n if (referencesIds.length > 0) {\n Object.assign(reply, { references: referencesIds })\n }\n\n this.emit('reply', reply)\n }\n\n private async fetchRecentEmails(accountId: string): Promise<JmapEmail[]> {\n const queryResp = await this.jmapCall([\n [\n 'Email/query',\n {\n accountId,\n sort: [{ property: 'receivedAt', isAscending: false }],\n limit: 20,\n },\n 'q1',\n ],\n ])\n\n const queryResult = queryResp.methodResponses.find(([name]) => name === 'Email/query')\n if (!queryResult) return []\n\n const ids = ((queryResult[1] as { ids?: string[] }).ids ?? []).slice(0, 20)\n if (ids.length === 0) return []\n\n const emailResp = await this.jmapCall([\n [\n 'Email/get',\n {\n accountId,\n ids,\n properties: ['id', 'subject', 'from', 'to', 'headers', 'messageId', 'receivedAt', 'textBody', 'bodyValues', 'attachments'],\n fetchTextBodyValues: true,\n maxBodyValueBytes: 262144,\n },\n 'gRecent',\n ],\n ])\n\n const getResult = emailResp.methodResponses.find(([name]) => name === 'Email/get')\n if (!getResult) return []\n\n return (getResult[1] as { list?: JmapEmail[] }).list ?? []\n }\n\n private shouldProcessBootstrapEmail(email: JmapEmail): boolean {\n const receivedAtMs = new Date(email.receivedAt).getTime()\n // Keep a small grace window for mail that arrived during startup / reconnect races,\n // but do not replay older historical mailbox contents as fresh tasks.\n return Number.isFinite(receivedAtMs) && receivedAtMs >= this.startedAtMs - 15_000\n }\n\n /**\n * Connect to JMAP WebSocket\n */\n private async connect(): Promise<void> {\n if (this.connecting || !this.running) return\n this.connecting = true\n\n try {\n this.session = await this.fetchSession()\n } catch (err) {\n this.connecting = false\n this.emit('error', new Error(`Failed to get JMAP session: ${(err as Error).message}`))\n this.startPolling('session fetch failed')\n this.scheduleReconnect()\n return\n }\n\n // Build WebSocket URL from the configured jmapUrl (the management-service proxy).\n // The management service exposes the standard external WebSocket path /jmap/ws\n // and proxies upgrades to Stalwart. We never use the session capability URL\n // directly because Stalwart populates it with its own internal hostname\n // (e.g. ws://aamp.local:8080/jmap/ws), which is unreachable from outside\n // the Docker / cluster network.\n const stalwartWsUrl = `${this.jmapUrl}/jmap/ws`\n .replace(/^https:\\/\\//, 'wss://')\n .replace(/^http:\\/\\//, 'ws://')\n\n this.ws = new WebSocket(stalwartWsUrl, 'jmap', {\n headers: {\n Authorization: this.getAuthHeader(),\n },\n perMessageDeflate: false,\n rejectUnauthorized: this.rejectUnauthorized,\n })\n\n this.ws.on('unexpected-response', (_req, res) => {\n this.connecting = false\n const headerSummary = Object.entries(res.headers)\n .map(([key, value]) => `${key}: ${Array.isArray(value) ? value.join(', ') : (value ?? '')}`)\n .join('; ')\n this.startPolling(`websocket handshake failed: ${res.statusCode ?? 'unknown'}`)\n this.emit(\n 'error',\n new Error(\n `JMAP WebSocket handshake failed: ${res.statusCode ?? 'unknown'} ${res.statusMessage ?? ''}${headerSummary ? ` | headers: ${headerSummary}` : ''}`,\n ),\n )\n this.scheduleReconnect()\n })\n\n this.ws.on('open', async () => {\n this.connecting = false\n this.connected = true\n this.stopPolling()\n this.startPingHeartbeat()\n\n // On first connect (emailState is null), initialize state so we only\n // process emails arriving AFTER this point.\n // On reconnect, emailState is already set \u2014 Email/changes will catch up.\n const accountId = this.session?.primaryAccounts['urn:ietf:params:jmap:mail']\n if (accountId && this.emailState === null) {\n await this.initEmailState(accountId)\n }\n\n // Subscribe to Email state changes AFTER state is initialized\n this.ws!.send(\n JSON.stringify({\n '@type': 'WebSocketPushEnable',\n dataTypes: ['Email'],\n pushState: null,\n }),\n )\n\n this.emit('connected')\n })\n\n this.ws.on('pong', () => {\n // Receiving pong confirms the upstream and LB path are still alive.\n })\n\n this.ws.on('message', async (rawData: WebSocket.RawData) => {\n try {\n const msg = JSON.parse(rawData.toString()) as {\n '@type': string\n } & JmapStateChange\n\n if (msg['@type'] === 'StateChange') {\n await this.handleStateChange(msg)\n }\n } catch (err) {\n this.emit('error', new Error(`Failed to process JMAP push message: ${(err as Error).message}`))\n }\n })\n\n this.ws.on('close', (code, reason) => {\n this.connecting = false\n this.connected = false\n this.stopPingHeartbeat()\n const reasonStr = reason?.toString() ?? 'connection closed'\n this.startPolling(reasonStr)\n this.emit('disconnected', reasonStr)\n\n if (this.running) {\n this.scheduleReconnect()\n }\n })\n\n this.ws.on('error', (err) => {\n this.connecting = false\n this.stopPingHeartbeat()\n this.startPolling(err.message)\n this.emit('error', err)\n })\n }\n\n private startPingHeartbeat(): void {\n if (this.pingTimer) {\n clearInterval(this.pingTimer)\n this.pingTimer = null\n }\n\n this.pingTimer = setInterval(() => {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return\n try {\n this.ws.ping()\n } catch (err) {\n this.emit('error', new Error(`Failed to send WebSocket ping: ${(err as Error).message}`))\n }\n }, this.pingIntervalMs)\n }\n\n private stopPingHeartbeat(): void {\n if (this.pingTimer) {\n clearInterval(this.pingTimer)\n this.pingTimer = null\n }\n }\n\n private startSafetySync(): void {\n if (this.safetySyncTimer) return\n\n this.safetySyncTimer = setInterval(() => {\n if (!this.running) return\n\n void this.reconcileRecentEmails(20).catch((err) => {\n this.emit('error', new Error(`Safety reconcile failed: ${(err as Error).message}`))\n })\n }, this.safetySyncIntervalMs)\n }\n\n private async handleStateChange(stateChange: JmapStateChange): Promise<void> {\n if (!this.session) return\n\n const accountId = this.session.primaryAccounts['urn:ietf:params:jmap:mail']\n if (!accountId) return\n\n const changedAccount = stateChange.changed[accountId]\n if (!changedAccount?.Email) return\n\n try {\n if (this.emailState === null) {\n // State not yet initialized (race between open handler and first StateChange)\n // Just initialize and skip \u2014 next StateChange will use Email/changes properly\n await this.initEmailState(accountId)\n return\n }\n\n const emails = await this.fetchEmailsSince(accountId, this.emailState)\n for (const email of emails) {\n this.processEmail(email)\n }\n } catch (err) {\n this.emit('error', new Error(`Failed to fetch emails: ${(err as Error).message}`))\n }\n }\n\n private scheduleReconnect(): void {\n if (this.reconnectTimer) return\n\n this.reconnectTimer = setTimeout(async () => {\n this.reconnectTimer = null\n if (this.running) {\n await this.connect()\n }\n }, this.reconnectInterval)\n }\n\n isConnected(): boolean {\n return this.connected || this.pollingActive\n }\n\n isUsingPollingFallback(): boolean {\n return this.pollingActive && !this.connected\n }\n\n private stopPolling(): void {\n if (this.pollTimer) {\n clearTimeout(this.pollTimer)\n this.pollTimer = null\n }\n this.pollingActive = false\n }\n\n private startPolling(reason: string): void {\n if (!this.running || this.pollingActive) return\n\n this.pollingActive = true\n this.emit('error', new Error(`JMAP WebSocket unavailable, falling back to polling: ${reason}`))\n this.emit('connected')\n\n const poll = async () => {\n if (!this.running || this.connected) {\n this.stopPolling()\n return\n }\n\n try {\n if (!this.session) {\n this.session = await this.fetchSession()\n }\n\n const accountId = this.session.primaryAccounts['urn:ietf:params:jmap:mail']\n ?? Object.keys(this.session.accounts)[0]\n\n if (!accountId) {\n throw new Error('No mail account available in JMAP session')\n }\n\n if (this.emailState === null) {\n const recentEmails = await this.fetchRecentEmails(accountId)\n for (const email of recentEmails.sort((a, b) => {\n const aTs = new Date(a.receivedAt).getTime()\n const bTs = new Date(b.receivedAt).getTime()\n return aTs - bTs\n })) {\n if (!this.shouldProcessBootstrapEmail(email)) continue\n this.processEmail(email)\n }\n await this.initEmailState(accountId)\n } else {\n const emails = await this.fetchEmailsSince(accountId, this.emailState)\n for (const email of emails) {\n this.processEmail(email)\n }\n }\n } catch (err) {\n this.emit('error', new Error(`Polling fallback failed: ${(err as Error).message}`))\n } finally {\n if (this.running && !this.connected) {\n this.pollTimer = setTimeout(poll, this.reconnectInterval)\n }\n }\n }\n\n this.pollTimer = setTimeout(poll, 0)\n }\n\n /**\n * Download a blob (attachment) by its JMAP blobId.\n * Returns the raw binary content as a Buffer.\n */\n async downloadBlob(blobId: string, filename?: string): Promise<Buffer> {\n if (!this.session) {\n // Fetch session on demand if not yet connected\n this.session = await this.fetchSession()\n }\n\n const accountId = this.session.primaryAccounts['urn:ietf:params:jmap:mail']\n ?? Object.keys(this.session.accounts)[0]\n\n // Build download URL from session template or fall back to standard JMAP path\n let downloadUrl = this.session.downloadUrl\n ?? `${this.jmapUrl}/jmap/download/{accountId}/{blobId}/{name}`\n\n // Replace session.downloadUrl host with our configured jmapUrl\n // (Stalwart may report an internal hostname unreachable from outside Docker)\n try {\n downloadUrl = rewriteUrlToConfiguredOrigin(downloadUrl, this.jmapUrl)\n } catch {\n // If URL parsing fails, use the template as-is\n }\n\n const safeFilename = filename ?? 'attachment'\n downloadUrl = downloadUrl\n .replace(/\\{accountId\\}|%7BaccountId%7D/gi, encodeURIComponent(accountId))\n .replace(/\\{blobId\\}|%7BblobId%7D/gi, encodeURIComponent(blobId))\n .replace(/\\{name\\}|%7Bname%7D/gi, encodeURIComponent(safeFilename))\n .replace(/\\{type\\}|%7Btype%7D/gi, 'application/octet-stream')\n\n // Retry with exponential backoff \u2014 the blob may not be immediately available\n // after the result email is observed (store/index write delay).\n const maxAttempts = 8\n let lastStatus: number | null = null\n let lastError: Error | null = null\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n let res: Response\n try {\n res = await fetch(downloadUrl, {\n headers: { Authorization: this.getAuthHeader() },\n })\n } catch (err) {\n lastError = new Error(\n `Blob download fetch failed: attempt=${attempt}/${maxAttempts} blobId=${blobId} filename=${filename ?? 'attachment'} url=${downloadUrl} error=${describeError(err)}`,\n )\n if (attempt < maxAttempts) {\n console.warn(\n `[AAMP-SDK] blob download retry fetch-error attempt=${attempt}/${maxAttempts} url=${downloadUrl} error=${describeError(err)}`,\n )\n const delay = Math.min(1000 * Math.pow(2, attempt - 1), 15000)\n await new Promise(r => setTimeout(r, delay))\n continue\n }\n console.error(\n `[AAMP-SDK] blob download fetch-error attempt=${attempt}/${maxAttempts} url=${downloadUrl} error=${describeError(err)}`,\n )\n throw lastError\n }\n\n lastStatus = res.status\n if (res.ok) {\n const arrayBuffer = await res.arrayBuffer()\n return Buffer.from(arrayBuffer)\n }\n if (attempt < maxAttempts && shouldRetryBlobDownload(res.status)) {\n console.warn(\n `[AAMP-SDK] blob download retry status=${res.status} attempt=${attempt}/${maxAttempts} url=${downloadUrl}`,\n )\n const delay = Math.min(1000 * Math.pow(2, attempt - 1), 15000) // 1s, 2s, 4s, 8s, 15s...\n await new Promise(r => setTimeout(r, delay))\n continue\n }\n console.error(\n `[AAMP-SDK] blob download failed status=${res.status} attempt=${attempt}/${maxAttempts} url=${downloadUrl}`,\n )\n throw new Error(\n `Blob download failed: status=${res.status} attempt=${attempt}/${maxAttempts} blobId=${blobId} filename=${filename ?? 'attachment'} url=${downloadUrl}`,\n )\n }\n if (lastError) throw lastError\n throw new Error(\n `Blob download failed after retries: status=${lastStatus ?? 'unknown'} attempt=${maxAttempts}/${maxAttempts} blobId=${blobId} filename=${filename ?? 'attachment'} url=${downloadUrl}`,\n )\n }\n\n /**\n * Actively reconcile recent mailbox contents via JMAP HTTP.\n * Useful as a safety net when the WebSocket stays \"connected\"\n * but a notification is missed by an intermediate layer.\n */\n async reconcileRecentEmails(limit = 20, opts?: { includeHistorical?: boolean }): Promise<number> {\n if (!this.session) {\n this.session = await this.fetchSession()\n }\n\n const accountId = this.session.primaryAccounts['urn:ietf:params:jmap:mail']\n ?? Object.keys(this.session.accounts)[0]\n\n if (!accountId) {\n throw new Error('No mail account available in JMAP session')\n }\n\n const queryResp = await this.jmapCall([\n [\n 'Email/query',\n {\n accountId,\n sort: [{ property: 'receivedAt', isAscending: false }],\n limit,\n },\n 'qReconcile',\n ],\n ])\n\n const queryResult = queryResp.methodResponses.find(([name]) => name === 'Email/query')\n if (!queryResult) return 0\n\n const ids = ((queryResult[1] as { ids?: string[] }).ids ?? []).slice(0, limit)\n if (ids.length === 0) return 0\n\n const emailResp = await this.jmapCall([\n [\n 'Email/get',\n {\n accountId,\n ids,\n properties: ['id', 'subject', 'from', 'to', 'headers', 'messageId', 'receivedAt', 'textBody', 'bodyValues', 'attachments'],\n fetchTextBodyValues: true,\n maxBodyValueBytes: 262144,\n },\n 'gReconcile',\n ],\n ])\n\n const getResult = emailResp.methodResponses.find(([name]) => name === 'Email/get')\n if (!getResult) return 0\n\n const emails = (getResult[1] as { list?: JmapEmail[] }).list ?? []\n for (const email of emails.sort((a, b) => {\n const aTs = new Date(a.receivedAt).getTime()\n const bTs = new Date(b.receivedAt).getTime()\n return aTs - bTs\n })) {\n if (!opts?.includeHistorical && !this.shouldProcessBootstrapEmail(email)) continue\n this.processEmail(email)\n }\n\n return emails.length\n }\n}\n", "/**\n * AAMP SDK Type Definitions\n */\n\nexport const AAMP_PROTOCOL_VERSION = '1.1'\n\nexport type AampIntent =\n | 'task.dispatch'\n | 'task.cancel'\n | 'task.result'\n | 'task.help_needed'\n | 'task.ack'\n | 'task.stream.opened'\n | 'card.query'\n | 'card.response'\n\nexport type TaskPriority = 'urgent' | 'high' | 'normal'\n\nexport type TaskStatus =\n | 'pending'\n | 'running'\n | 'completed'\n | 'rejected'\n | 'failed'\n | 'help_needed'\n | 'cancelled'\n | 'expired'\n\n// =====================================================\n// AAMP Header constants\n// =====================================================\nexport const AAMP_HEADER = {\n VERSION: 'X-AAMP-Version',\n INTENT: 'X-AAMP-Intent',\n TASK_ID: 'X-AAMP-TaskId',\n SESSION_KEY: 'X-AAMP-Session-Key',\n CONTEXT_LINKS: 'X-AAMP-ContextLinks',\n DISPATCH_CONTEXT: 'X-AAMP-Dispatch-Context',\n PRIORITY: 'X-AAMP-Priority',\n EXPIRES_AT: 'X-AAMP-Expires-At',\n STATUS: 'X-AAMP-Status',\n OUTPUT: 'X-AAMP-Output',\n ERROR_MSG: 'X-AAMP-ErrorMsg',\n STRUCTURED_RESULT: 'X-AAMP-StructuredResult',\n QUESTION: 'X-AAMP-Question',\n BLOCKED_REASON: 'X-AAMP-BlockedReason',\n SUGGESTED_OPTIONS: 'X-AAMP-SuggestedOptions',\n STREAM_ID: 'X-AAMP-Stream-Id',\n PARENT_TASK_ID: 'X-AAMP-ParentTaskId',\n CARD_SUMMARY: 'X-AAMP-Card-Summary',\n} as const\n\nexport interface StructuredResultField {\n fieldKey: string\n fieldTypeKey: string\n value?: unknown\n fieldAlias?: string\n index?: string\n attachmentFilenames?: string[]\n}\n\n// =====================================================\n// Parsed AAMP headers for task.dispatch\n// =====================================================\nexport interface TaskDispatch {\n protocolVersion: string\n intent: 'task.dispatch'\n taskId: string\n sessionKey?: string\n title: string\n priority: TaskPriority\n expiresAt?: string\n contextLinks: string[]\n dispatchContext?: Record<string, string>\n parentTaskId?: string\n // Email metadata\n from: string\n to: string\n messageId: string\n subject: string\n /** Plain-text body of the email (task description) */\n bodyText: string\n /** Attachments received with this dispatch (use blobId to download) */\n attachments?: ReceivedAttachment[]\n}\n\nexport interface TaskCancel {\n protocolVersion: string\n intent: 'task.cancel'\n taskId: string\n from: string\n to: string\n messageId?: string\n subject: string\n bodyText: string\n}\n\n// =====================================================\n// Parsed AAMP headers for task.result\n// =====================================================\nexport interface TaskResult {\n protocolVersion: string\n intent: 'task.result'\n taskId: string\n status: 'completed' | 'rejected'\n output: string\n errorMsg?: string\n structuredResult?: StructuredResultField[]\n from: string\n to: string\n messageId?: string\n /** True when the reply came from a standard email client (no X-AAMP-Intent header).\n * taskId was resolved via In-Reply-To \u2192 Message-ID reverse lookup. */\n isHumanReply?: boolean\n /** Attachments received with this result (use blobId to download) */\n attachments?: ReceivedAttachment[]\n}\n\n// =====================================================\n// Human reply via standard email client (no AAMP headers)\n// Emitted as 'reply' event when an email has In-Reply-To but no X-AAMP-Intent.\n// The application layer is responsible for resolving inReplyTo \u2192 taskId\n// (e.g. via Redis reverse index) and deciding how to handle it.\n// =====================================================\nexport interface HumanReply {\n /** Message-ID of the email being replied to \u2014 use this to look up the taskId */\n inReplyTo: string\n /** This reply email's own Message-ID */\n messageId: string\n from: string\n to: string\n subject: string\n /** Plain-text body of the reply */\n bodyText: string\n}\n\n// =====================================================\n// Parsed AAMP headers for task.help_needed\n// =====================================================\nexport interface TaskHelp {\n protocolVersion: string\n intent: 'task.help_needed'\n taskId: string\n question: string\n blockedReason: string\n suggestedOptions: string[]\n from: string\n to: string\n messageId?: string\n}\n\n// =====================================================\n// Parsed AAMP headers for task.ack\n// =====================================================\nexport interface TaskAck {\n protocolVersion: string\n intent: 'task.ack'\n taskId: string\n from: string\n to: string\n messageId?: string\n}\n\nexport interface TaskStreamOpened {\n protocolVersion: string\n intent: 'task.stream.opened'\n taskId: string\n streamId: string\n from: string\n to: string\n messageId?: string\n}\n\nexport interface CardQuery {\n protocolVersion: string\n intent: 'card.query'\n taskId: string\n from: string\n to: string\n messageId?: string\n subject: string\n bodyText: string\n}\n\nexport interface CardResponse {\n protocolVersion: string\n intent: 'card.response'\n taskId: string\n summary: string\n from: string\n to: string\n messageId?: string\n subject: string\n bodyText: string\n}\n\n// =====================================================\n// Attachment types\n// =====================================================\n\n/** Attachment for sending (binary content) */\nexport interface AampAttachment {\n filename: string\n contentType: string\n content: Buffer | string // Buffer for binary, base64 string for REST API\n size?: number\n}\n\n/** Attachment metadata received via JMAP (use blobId to download) */\nexport interface ReceivedAttachment {\n filename: string\n contentType: string\n size: number\n blobId: string\n}\n\nexport type AampMessage =\n | TaskDispatch\n | TaskCancel\n | TaskResult\n | TaskHelp\n | TaskAck\n | TaskStreamOpened\n | CardQuery\n | CardResponse\n | HumanReply\n\n// =====================================================\n// SDK Configuration\n// =====================================================\nexport interface AampClientConfig {\n /** Node email address, e.g. codereviewer-abc123@aamp.yourdomain.com */\n email: string\n\n /** Mailbox token for HTTP Basic Auth. Equivalent to base64(email:smtpPassword). */\n mailboxToken: string\n\n /** Base URL for this mailbox service, e.g. https://meshmail.ai */\n baseUrl: string\n\n /** Optional AAMP discovery base URL. Defaults to baseUrl and is used for same-domain send fallback via /.well-known/aamp + aamp.mailbox.send. */\n httpSendBaseUrl?: string\n\n /** SMTP submission host. If omitted, derived from baseUrl. */\n smtpHost?: string\n\n /** SMTP submission port (default: 587) */\n smtpPort?: number\n\n /** SMTP password (returned by management service on agent creation) */\n smtpPassword: string\n\n /** How often to retry failed JMAP connection (ms, default: 5000) */\n reconnectInterval?: number\n\n /** Maximum number of task.dispatch handlers running concurrently (default: 10). */\n taskDispatchConcurrency?: number\n\n /** Whether to reject unauthorized TLS certificates (default: true).\n * Set to false only for development with self-signed certificates. */\n rejectUnauthorized?: boolean\n}\n\nexport interface AampMailboxIdentityConfig {\n /** Mailbox email address, e.g. agent@meshmail.ai */\n email: string\n\n /** Mailbox SMTP/JMAP password */\n smtpPassword: string\n\n /** Optional base URL for JMAP and same-domain AAMP HTTP send fallback.\n * Defaults to https://<email-domain>. */\n baseUrl?: string\n\n /** SMTP submission port (default: 587) */\n smtpPort?: number\n\n /** How often to retry failed JMAP connection (ms, default: 5000) */\n reconnectInterval?: number\n\n /** Maximum number of task.dispatch handlers running concurrently (default: 10). */\n taskDispatchConcurrency?: number\n\n /** Whether to reject unauthorized TLS certificates (default: true). */\n rejectUnauthorized?: boolean\n}\n\nexport interface AampDiscoveryDocument {\n protocol: 'aamp'\n version: string\n intents?: AampIntent[]\n api?: {\n url?: string\n actions?: string[]\n }\n endpoints?: Record<string, string>\n capabilities?: {\n stream?: {\n transport: 'sse'\n createAction?: string\n appendAction?: string\n closeAction?: string\n getAction?: string\n subscribeUrlTemplate?: string\n }\n }\n}\n\nexport interface RegisterMailboxOptions {\n /** AAMP service root, e.g. https://meshmail.ai */\n aampHost: string\n slug: string\n description?: string\n}\n\nexport interface RegisteredMailboxIdentity {\n email: string\n mailboxToken: string\n smtpPassword: string\n baseUrl: string\n}\n\nexport interface AgentDirectoryEntry {\n email: string\n summary: string | null\n}\n\nexport interface AgentDirectorySearchEntry extends AgentDirectoryEntry {\n score: number\n}\n\nexport interface AgentDirectoryProfile extends AgentDirectoryEntry {\n cardText: string | null\n}\n\nexport interface AampThreadEvent {\n intent: AampIntent\n from: string\n to: string\n title?: string | null\n bodyText?: string | null\n output?: string | null\n question?: string | null\n blockedReason?: string | null\n messageId?: string | null\n createdAt: string\n}\n\nexport interface GetThreadHistoryOptions {\n includeStreamOpened?: boolean\n}\n\nexport interface TaskThreadHistory {\n taskId: string\n events: AampThreadEvent[]\n}\n\nexport interface HydratedTaskDispatch extends TaskDispatch {\n threadHistory: AampThreadEvent[]\n threadContextText: string\n}\n\n// =====================================================\n// Options for sending emails\n// =====================================================\nexport interface SendTaskOptions {\n /** Target node email */\n to: string\n taskId?: string\n title: string\n bodyText?: string\n /** When set, send the body exactly as provided instead of wrapping it in the default task template. */\n rawBodyText?: string\n priority?: TaskPriority\n /** Absolute expiry timestamp. */\n expiresAt?: string\n sessionKey?: string\n contextLinks?: string[]\n dispatchContext?: Record<string, string>\n parentTaskId?: string\n /** Attachments to include with the dispatch email */\n attachments?: AampAttachment[]\n}\n\nexport type RegisteredCommandStreamMode = 'none' | 'status-only' | 'full'\n\nexport interface RegisteredCommandInputRef {\n slot: string\n attachmentName: string\n}\n\nexport interface RegisteredCommandDispatchPayload {\n kind: 'registered-command/v1'\n command: string\n args?: Record<string, unknown>\n inputs?: RegisteredCommandInputRef[]\n stream?: {\n mode?: RegisteredCommandStreamMode\n }\n}\n\nexport interface SendRegisteredCommandOptions {\n to: string\n taskId?: string\n title?: string\n command: string\n args?: Record<string, unknown>\n inputs?: RegisteredCommandInputRef[]\n streamMode?: RegisteredCommandStreamMode\n priority?: TaskPriority\n expiresAt?: string\n sessionKey?: string\n contextLinks?: string[]\n dispatchContext?: Record<string, string>\n parentTaskId?: string\n attachments?: AampAttachment[]\n}\n\nexport interface SendCancelOptions {\n to: string\n taskId: string\n bodyText?: string\n inReplyTo?: string\n}\n\nexport interface SendResultOptions {\n /** Send to: the original from address of the dispatch email */\n to: string\n taskId: string\n status: 'completed' | 'rejected'\n output: string\n errorMsg?: string\n structuredResult?: StructuredResultField[]\n /** When set, send the body exactly as provided instead of wrapping it in the default result template. */\n rawBodyText?: string\n /** Message-ID of the dispatch email, for In-Reply-To threading */\n inReplyTo?: string\n /** Attachments to include with the result email */\n attachments?: AampAttachment[]\n}\n\nexport interface SendHelpOptions {\n /** Send to: the original from address of the dispatch email */\n to: string\n taskId: string\n question: string\n blockedReason: string\n suggestedOptions: string[]\n /** When set, send the body exactly as provided instead of wrapping it in the default help template. */\n rawBodyText?: string\n /** Message-ID of the dispatch email, for In-Reply-To threading */\n inReplyTo?: string\n /** Attachments to include with the help email */\n attachments?: AampAttachment[]\n}\n\nexport interface SendCardQueryOptions {\n to: string\n taskId?: string\n bodyText?: string\n inReplyTo?: string\n}\n\nexport interface SendCardResponseOptions {\n to: string\n taskId: string\n summary: string\n bodyText: string\n inReplyTo?: string\n}\n\nexport interface CreateStreamOptions {\n taskId: string\n peerEmail: string\n}\n\nexport interface CreateStreamResult {\n streamId: string\n taskId: string\n status: 'created' | 'opened' | 'closed'\n ownerEmail: string\n peerEmail: string\n createdAt: string\n openedAt?: string\n closedAt?: string\n}\n\nexport type AampStreamEventType =\n | 'text.delta'\n | 'progress'\n | 'status'\n | 'artifact'\n | 'error'\n | 'done'\n\nexport interface AampStreamEvent {\n id?: string\n streamId: string\n taskId: string\n seq: number\n timestamp: string\n type: AampStreamEventType\n payload: Record<string, unknown>\n}\n\nexport interface AppendStreamEventOptions {\n streamId: string\n type: AampStreamEventType\n payload: Record<string, unknown>\n}\n\nexport interface CloseStreamOptions {\n streamId: string\n payload?: Record<string, unknown>\n}\n\nexport interface GetTaskStreamOptions {\n taskId?: string\n streamId?: string\n}\n\nexport interface TaskStreamState extends CreateStreamResult {\n latestEvent?: AampStreamEvent\n}\n\nexport interface StreamSubscription {\n close(): void\n}\n\nexport interface DirectoryListOptions {\n scope?: string\n includeSelf?: boolean\n limit?: number\n}\n\nexport interface DirectorySearchOptions extends DirectoryListOptions {\n query: string\n}\n\nexport interface UpdateDirectoryProfileOptions {\n summary?: string | null\n cardText?: string | null\n}\n\n// =====================================================\n// Event emitter types\n// =====================================================\nexport interface AampClientEvents {\n 'task.dispatch': (task: TaskDispatch) => void | Promise<void>\n 'task.cancel': (task: TaskCancel) => void\n 'task.result': (result: TaskResult) => void\n 'task.help_needed': (help: TaskHelp) => void\n 'task.ack': (ack: TaskAck) => void\n 'task.stream.opened': (stream: TaskStreamOpened) => void\n 'card.query': (query: CardQuery) => void\n 'card.response': (response: CardResponse) => void\n /** Emitted when a standard email reply (no X-AAMP headers) is received for a known thread.\n * Use inReplyTo to look up the taskId in your own store (Redis / DB). */\n 'reply': (reply: HumanReply) => void\n connected: () => void\n disconnected: (reason: string) => void\n error: (err: Error) => void\n}\n", "/**\n * AAMP Header Parser\n *\n * Parses AAMP protocol headers from email messages.\n * Works with both raw header objects and JMAP Email objects.\n *\n * Headers are case-insensitive; we normalize to lowercase for lookup.\n */\n\nimport {\n AAMP_HEADER,\n AAMP_PROTOCOL_VERSION,\n type AampMessage,\n type TaskDispatch,\n type TaskCancel,\n type TaskResult,\n type TaskHelp,\n type TaskAck,\n type TaskStreamOpened,\n type CardQuery,\n type CardResponse,\n} from './types.js'\n\ntype RawHeaders = Record<string, string | string[]>\n\nfunction normalizeBodyText(value?: string): string {\n return value?.replace(/\\r\\n/g, '\\n').trim() ?? ''\n}\n\nfunction escapeRegex(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\nfunction extractBodySection(bodyText: string, label: string, nextLabels: string[]): string {\n if (!bodyText) return ''\n const nextPattern = nextLabels.length\n ? `(?=\\\\n(?:${nextLabels.map(escapeRegex).join('|')}):|$)`\n : '$'\n const pattern = new RegExp(\n `(?:^|\\\\n)${escapeRegex(label)}:\\\\s*([\\\\s\\\\S]*?)${nextPattern}`,\n 'i',\n )\n const match = pattern.exec(bodyText)\n return match?.[1]?.trim() ?? ''\n}\n\nfunction parseSuggestedOptionsBlock(block: string): string[] {\n if (!block.trim()) return []\n return block\n .split('\\n')\n .map((line) => line.replace(/^\\s*(?:[-*]|\\d+\\.)\\s*/, '').trim())\n .filter(Boolean)\n}\n\nfunction parseTaskResultBody(bodyText?: string): { output: string; errorMsg?: string } {\n const normalized = normalizeBodyText(bodyText)\n if (!normalized) return { output: '' }\n\n const output = extractBodySection(normalized, 'Output', ['Error'])\n const errorMsg = extractBodySection(normalized, 'Error', [])\n\n if (output || errorMsg) {\n return { output, ...(errorMsg ? { errorMsg } : {}) }\n }\n\n return { output: normalized }\n}\n\nfunction parseTaskHelpBody(bodyText?: string): {\n question: string\n blockedReason: string\n suggestedOptions: string[]\n} {\n const normalized = normalizeBodyText(bodyText)\n if (!normalized) {\n return { question: '', blockedReason: '', suggestedOptions: [] }\n }\n\n const question = extractBodySection(normalized, 'Question', ['Blocked reason', 'Suggested options'])\n const blockedReason = extractBodySection(normalized, 'Blocked reason', ['Suggested options'])\n const suggestedOptions = parseSuggestedOptionsBlock(\n extractBodySection(normalized, 'Suggested options', []),\n )\n\n if (question || blockedReason || suggestedOptions.length) {\n return { question, blockedReason, suggestedOptions }\n }\n\n return { question: normalized, blockedReason: '', suggestedOptions: [] }\n}\n\nfunction decodeMimeEncodedWordSegment(segment: string): string {\n const match = /^=\\?([^?]+)\\?([bBqQ])\\?([^?]*)\\?=$/.exec(segment)\n if (!match) return segment\n\n const [, charsetRaw, encodingRaw, body] = match\n const charset = charsetRaw.toLowerCase()\n const encoding = encodingRaw.toUpperCase()\n\n try {\n if (encoding === 'B') {\n const buf = Buffer.from(body, 'base64')\n return buf.toString(charset === 'utf-8' || charset === 'utf8' ? 'utf8' : 'utf8')\n }\n\n const normalized = body\n .replace(/_/g, ' ')\n .replace(/=([0-9A-Fa-f]{2})/g, (_, hex: string) =>\n String.fromCharCode(parseInt(hex, 16)),\n )\n const bytes = Buffer.from(normalized, 'binary')\n return bytes.toString(charset === 'utf-8' || charset === 'utf8' ? 'utf8' : 'utf8')\n } catch {\n return segment\n }\n}\n\nfunction decodeMimeEncodedWords(value?: string): string {\n if (!value || !value.includes('=?')) return value ?? ''\n const collapsed = value.replace(/\\r?\\n[ \\t]+/g, ' ')\n const decoded = collapsed.replace(/=\\?[^?]+\\?[bBqQ]\\?[^?]*\\?=/g, (segment) =>\n decodeMimeEncodedWordSegment(segment),\n )\n return decoded.replace(/\\s{2,}/g, ' ').trim()\n}\n\n/**\n * Normalize a header map to lowercase keys with string values\n */\nexport function normalizeHeaders(headers: RawHeaders): Record<string, string> {\n return Object.fromEntries(\n Object.entries(headers).map(([k, v]) => [\n k.toLowerCase(),\n Array.isArray(v) ? v[0] : v,\n ]),\n )\n}\n\n/**\n * Get a header value by its X-AAMP-* name (case-insensitive)\n */\nfunction getAampHeader(\n headers: Record<string, string>,\n headerName: string,\n): string | undefined {\n return headers[headerName.toLowerCase()]\n}\n\nconst DISPATCH_CONTEXT_KEY_RE = /^[a-z0-9_-]+$/\n\nexport function parseDispatchContextHeader(value?: string): Record<string, string> | undefined {\n if (!value) return undefined\n const context: Record<string, string> = {}\n\n for (const part of value.split(';')) {\n const segment = part.trim()\n if (!segment) continue\n const eqIdx = segment.indexOf('=')\n if (eqIdx <= 0) continue\n const rawKey = segment.slice(0, eqIdx).trim()\n const rawValue = segment.slice(eqIdx + 1).trim()\n if (!DISPATCH_CONTEXT_KEY_RE.test(rawKey)) continue\n try {\n context[rawKey] = decodeURIComponent(rawValue)\n } catch {\n context[rawKey] = rawValue\n }\n }\n\n return Object.keys(context).length ? context : undefined\n}\n\nexport function serializeDispatchContextHeader(context?: Record<string, string>): string | undefined {\n if (!context) return undefined\n const parts = Object.entries(context)\n .flatMap(([key, value]) => {\n const normalizedKey = key.trim().toLowerCase()\n if (!DISPATCH_CONTEXT_KEY_RE.test(normalizedKey)) return []\n const normalizedValue = String(value ?? '').trim()\n if (!normalizedValue) return []\n return `${normalizedKey}=${encodeURIComponent(normalizedValue)}`\n })\n return parts.length ? parts.join('; ') : undefined\n}\n\nfunction decodeStructuredResult(value?: string): TaskResult['structuredResult'] | undefined {\n if (!value) return undefined\n try {\n const normalized = value.replace(/-/g, '+').replace(/_/g, '/')\n const padding = normalized.length % 4 === 0 ? '' : '='.repeat(4 - (normalized.length % 4))\n const decoded = Buffer.from(normalized + padding, 'base64').toString('utf-8')\n return JSON.parse(decoded) as TaskResult['structuredResult']\n } catch {\n return undefined\n }\n}\n\nfunction encodeStructuredResult(value?: TaskResult['structuredResult']): string | undefined {\n if (!value) return undefined\n const json = JSON.stringify(value)\n return Buffer.from(json, 'utf-8')\n .toString('base64')\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/g, '')\n}\n\nexport interface EmailMetadata {\n from: string\n to: string\n messageId: string\n subject: string\n headers: RawHeaders\n bodyText?: string\n}\n\n/**\n * Parse AAMP headers from an email's header map.\n * Returns null if this email is not an AAMP message.\n *\n * @param meta - Email metadata (from, to, messageId, subject, headers)\n */\nexport function parseAampHeaders(meta: EmailMetadata): AampMessage | null {\n const headers = normalizeHeaders(meta.headers)\n\n const intent = getAampHeader(headers, AAMP_HEADER.INTENT)\n const taskId = getAampHeader(headers, AAMP_HEADER.TASK_ID)\n const protocolVersion = getAampHeader(headers, AAMP_HEADER.VERSION) ?? AAMP_PROTOCOL_VERSION\n\n if (!intent || !taskId) return null\n\n const from = meta.from.replace(/^<|>$/g, '')\n const to = meta.to.replace(/^<|>$/g, '')\n const decodedSubject = decodeMimeEncodedWords(meta.subject)\n\n if (intent === 'task.dispatch') {\n const contextLinksStr = getAampHeader(headers, AAMP_HEADER.CONTEXT_LINKS) ?? ''\n const dispatchContext = parseDispatchContextHeader(\n getAampHeader(headers, AAMP_HEADER.DISPATCH_CONTEXT),\n )\n const sessionKey = getAampHeader(headers, AAMP_HEADER.SESSION_KEY)\n\n const parentTaskId = getAampHeader(headers, AAMP_HEADER.PARENT_TASK_ID)\n const priority = (getAampHeader(headers, AAMP_HEADER.PRIORITY) ?? 'normal') as TaskDispatch['priority']\n const expiresAt = getAampHeader(headers, AAMP_HEADER.EXPIRES_AT)\n\n const dispatch: TaskDispatch = {\n protocolVersion,\n intent: 'task.dispatch',\n taskId,\n ...(sessionKey ? { sessionKey } : {}),\n title: decodedSubject.replace(/^\\[AAMP Task\\]\\s*/, '').trim() || 'Untitled Task',\n priority: priority === 'urgent' || priority === 'high' ? priority : 'normal',\n ...(expiresAt ? { expiresAt } : {}),\n contextLinks: contextLinksStr\n ? contextLinksStr.split(',').map((s) => s.trim()).filter(Boolean)\n : [],\n ...(dispatchContext ? { dispatchContext } : {}),\n ...(parentTaskId ? { parentTaskId } : {}),\n from,\n to,\n messageId: meta.messageId,\n subject: meta.subject,\n bodyText: '', // filled in by jmap-push.ts after parsing\n }\n return dispatch\n }\n\n if (intent === 'task.cancel') {\n const cancel: TaskCancel = {\n protocolVersion,\n intent: 'task.cancel',\n taskId,\n from,\n to,\n messageId: meta.messageId,\n subject: meta.subject,\n bodyText: '',\n }\n return cancel\n }\n\n if (intent === 'task.result') {\n const parsedBody = parseTaskResultBody(meta.bodyText)\n const status = (getAampHeader(headers, AAMP_HEADER.STATUS) ?? 'completed') as\n | 'completed'\n | 'rejected'\n const output = getAampHeader(headers, AAMP_HEADER.OUTPUT) ?? parsedBody.output\n const errorMsg = getAampHeader(headers, AAMP_HEADER.ERROR_MSG) ?? parsedBody.errorMsg\n const structuredResult = decodeStructuredResult(\n getAampHeader(headers, AAMP_HEADER.STRUCTURED_RESULT),\n )\n\n const result: TaskResult = {\n protocolVersion,\n intent: 'task.result',\n taskId,\n status,\n output: decodeMimeEncodedWords(output),\n errorMsg: errorMsg ? decodeMimeEncodedWords(errorMsg) : errorMsg,\n structuredResult,\n from,\n to,\n messageId: meta.messageId,\n }\n return result\n }\n\n if (intent === 'task.help_needed') {\n const parsedBody = parseTaskHelpBody(meta.bodyText)\n const question = getAampHeader(headers, AAMP_HEADER.QUESTION) ?? parsedBody.question\n const blockedReason = getAampHeader(headers, AAMP_HEADER.BLOCKED_REASON) ?? parsedBody.blockedReason\n const suggestedOptionsStr = getAampHeader(headers, AAMP_HEADER.SUGGESTED_OPTIONS) ?? ''\n\n const help: TaskHelp = {\n protocolVersion,\n intent: 'task.help_needed',\n taskId,\n question: decodeMimeEncodedWords(question),\n blockedReason: decodeMimeEncodedWords(blockedReason),\n suggestedOptions: suggestedOptionsStr\n ? suggestedOptionsStr.split('|').map((s) => decodeMimeEncodedWords(s.trim())).filter(Boolean)\n : parsedBody.suggestedOptions,\n from,\n to,\n messageId: meta.messageId,\n }\n return help\n }\n\n if (intent === 'task.ack') {\n const ack: TaskAck = {\n protocolVersion,\n intent: 'task.ack',\n taskId,\n from,\n to,\n messageId: meta.messageId,\n }\n return ack\n }\n\n if (intent === 'task.stream.opened') {\n const streamId = getAampHeader(headers, AAMP_HEADER.STREAM_ID) ?? ''\n if (!streamId) return null\n\n const streamOpened: TaskStreamOpened = {\n protocolVersion,\n intent: 'task.stream.opened',\n taskId,\n streamId,\n from,\n to,\n messageId: meta.messageId,\n }\n return streamOpened\n }\n\n if (intent === 'card.query') {\n const cardQuery: CardQuery = {\n protocolVersion,\n intent: 'card.query',\n taskId,\n from,\n to,\n messageId: meta.messageId,\n subject: meta.subject,\n bodyText: '',\n }\n return cardQuery\n }\n\n if (intent === 'card.response') {\n const summary = getAampHeader(headers, AAMP_HEADER.CARD_SUMMARY) ?? ''\n const cardResponse: CardResponse = {\n protocolVersion,\n intent: 'card.response',\n taskId,\n summary: decodeMimeEncodedWords(summary) || decodedSubject.replace(/^\\[AAMP Card\\]\\s*/i, '').trim(),\n from,\n to,\n messageId: meta.messageId,\n subject: meta.subject,\n bodyText: '',\n }\n return cardResponse\n }\n\n return null\n}\n\n/**\n * Build AAMP headers for a task.dispatch email\n */\nexport function buildDispatchHeaders(params: {\n taskId: string\n priority?: TaskDispatch['priority']\n expiresAt?: string\n sessionKey?: string\n contextLinks: string[]\n dispatchContext?: Record<string, string>\n parentTaskId?: string\n}): Record<string, string> {\n const headers: Record<string, string> = {\n [AAMP_HEADER.VERSION]: AAMP_PROTOCOL_VERSION,\n [AAMP_HEADER.INTENT]: 'task.dispatch',\n [AAMP_HEADER.TASK_ID]: params.taskId,\n [AAMP_HEADER.PRIORITY]: params.priority ?? 'normal',\n }\n if (params.expiresAt) {\n headers[AAMP_HEADER.EXPIRES_AT] = params.expiresAt\n }\n if (params.sessionKey?.trim()) {\n headers[AAMP_HEADER.SESSION_KEY] = params.sessionKey.trim()\n }\n if (params.contextLinks.length > 0) {\n headers[AAMP_HEADER.CONTEXT_LINKS] = params.contextLinks.join(',')\n }\n const dispatchContext = serializeDispatchContextHeader(params.dispatchContext)\n if (dispatchContext) {\n headers[AAMP_HEADER.DISPATCH_CONTEXT] = dispatchContext\n }\n if (params.parentTaskId) {\n headers[AAMP_HEADER.PARENT_TASK_ID] = params.parentTaskId\n }\n return headers\n}\n\nexport function buildCancelHeaders(params: { taskId: string }): Record<string, string> {\n return {\n [AAMP_HEADER.VERSION]: AAMP_PROTOCOL_VERSION,\n [AAMP_HEADER.INTENT]: 'task.cancel',\n [AAMP_HEADER.TASK_ID]: params.taskId,\n }\n}\n\n/**\n * Build AAMP headers for a task.ack email\n */\nexport function buildAckHeaders(opts: { taskId: string }): Record<string, string> {\n return {\n [AAMP_HEADER.VERSION]: AAMP_PROTOCOL_VERSION,\n [AAMP_HEADER.INTENT]: 'task.ack',\n [AAMP_HEADER.TASK_ID]: opts.taskId,\n }\n}\n\nexport function buildStreamOpenedHeaders(opts: {\n taskId: string\n streamId: string\n}): Record<string, string> {\n return {\n [AAMP_HEADER.VERSION]: AAMP_PROTOCOL_VERSION,\n [AAMP_HEADER.INTENT]: 'task.stream.opened',\n [AAMP_HEADER.TASK_ID]: opts.taskId,\n [AAMP_HEADER.STREAM_ID]: opts.streamId,\n }\n}\n\n/**\n * Build AAMP headers for a task.result email\n */\nexport function buildResultHeaders(params: {\n taskId: string\n status: 'completed' | 'rejected'\n output: string\n errorMsg?: string\n structuredResult?: TaskResult['structuredResult']\n}): Record<string, string> {\n const headers: Record<string, string> = {\n [AAMP_HEADER.VERSION]: AAMP_PROTOCOL_VERSION,\n [AAMP_HEADER.INTENT]: 'task.result',\n [AAMP_HEADER.TASK_ID]: params.taskId,\n [AAMP_HEADER.STATUS]: params.status,\n }\n const structuredResult = encodeStructuredResult(params.structuredResult)\n if (structuredResult) {\n headers[AAMP_HEADER.STRUCTURED_RESULT] = structuredResult\n }\n return headers\n}\n\n/**\n * Build AAMP headers for a task.help_needed email\n */\nexport function buildHelpHeaders(params: {\n taskId: string\n question: string\n blockedReason: string\n suggestedOptions: string[]\n}): Record<string, string> {\n return {\n [AAMP_HEADER.VERSION]: AAMP_PROTOCOL_VERSION,\n [AAMP_HEADER.INTENT]: 'task.help_needed',\n [AAMP_HEADER.TASK_ID]: params.taskId,\n [AAMP_HEADER.SUGGESTED_OPTIONS]: params.suggestedOptions.join('|'),\n }\n}\n\nexport function buildCardQueryHeaders(params: {\n taskId: string\n}): Record<string, string> {\n return {\n [AAMP_HEADER.VERSION]: AAMP_PROTOCOL_VERSION,\n [AAMP_HEADER.INTENT]: 'card.query',\n [AAMP_HEADER.TASK_ID]: params.taskId,\n }\n}\n\nexport function buildCardResponseHeaders(params: {\n taskId: string\n summary: string\n}): Record<string, string> {\n return {\n [AAMP_HEADER.VERSION]: AAMP_PROTOCOL_VERSION,\n [AAMP_HEADER.INTENT]: 'card.response',\n [AAMP_HEADER.TASK_ID]: params.taskId,\n [AAMP_HEADER.CARD_SUMMARY]: params.summary,\n }\n}\n", "type Listener = (...args: unknown[]) => unknown\ntype EventListener<Events, K extends keyof Events> =\n Extract<Events[K], (...args: any[]) => void>\ntype EventArgs<Events, K extends keyof Events> =\n EventListener<Events, K> extends (...args: infer A) => void ? A : never\n\nexport class TinyEmitter<Events extends object> {\n private readonly listeners = new Map<keyof Events, Set<Listener>>()\n private readonly onceWrappers = new WeakMap<Listener, Listener>()\n\n on<K extends keyof Events>(event: K, listener: EventListener<Events, K>): this {\n const bucket = this.listeners.get(event) ?? new Set<Listener>()\n bucket.add(listener as Listener)\n this.listeners.set(event, bucket)\n return this\n }\n\n once<K extends keyof Events>(event: K, listener: EventListener<Events, K>): this {\n const wrapped: Listener = (...args: unknown[]) => {\n this.off(event, listener)\n ;(listener as Listener)(...args)\n }\n this.onceWrappers.set(listener as Listener, wrapped)\n return this.on(event, wrapped as EventListener<Events, K>)\n }\n\n off<K extends keyof Events>(event: K, listener: EventListener<Events, K>): this {\n const bucket = this.listeners.get(event)\n if (!bucket) return this\n\n const original = listener as Listener\n const wrapped = this.onceWrappers.get(original)\n bucket.delete(wrapped ?? original)\n if (wrapped) this.onceWrappers.delete(original)\n if (bucket.size === 0) this.listeners.delete(event)\n return this\n }\n\n protected emit<K extends keyof Events>(event: K, ...args: EventArgs<Events, K>): boolean {\n const bucket = this.listeners.get(event)\n if (!bucket || bucket.size === 0) return false\n\n for (const listener of [...bucket]) {\n listener(...args)\n }\n return true\n }\n\n protected async emitAsync<K extends keyof Events>(event: K, ...args: EventArgs<Events, K>): Promise<boolean> {\n const bucket = this.listeners.get(event)\n if (!bucket || bucket.size === 0) return false\n\n const settled = await Promise.allSettled(\n [...bucket].map((listener) => Promise.resolve(listener(...args))),\n )\n const rejected = settled.find(\n (result): result is PromiseRejectedResult => result.status === 'rejected',\n )\n if (rejected) {\n throw rejected.reason\n }\n return true\n }\n}\n", "/**\n * SMTP Sender\n *\n * Sends AAMP protocol emails via SMTP (Stalwart submission port 587).\n */\n\nimport { createTransport, type Transporter } from 'nodemailer'\nimport { randomUUID } from 'crypto'\n\n/** Strip CR/LF to prevent email header injection */\nconst sanitize = (s: string) => s.replace(/[\\r\\n]/g, ' ').trim()\nimport {\n buildDispatchHeaders,\n buildCancelHeaders,\n buildResultHeaders,\n buildHelpHeaders,\n buildAckHeaders,\n buildStreamOpenedHeaders,\n buildCardQueryHeaders,\n buildCardResponseHeaders,\n} from './parser.js'\nimport type {\n SendTaskOptions,\n SendResultOptions,\n SendHelpOptions,\n SendCardQueryOptions,\n SendCardResponseOptions,\n SendCancelOptions,\n} from './types.js'\n\nexport interface SmtpConfig {\n host: string\n port: number\n user: string\n password: string\n httpBaseUrl?: string\n authToken?: string\n secure?: boolean\n /** Whether to reject unauthorized TLS certificates (default: true) */\n rejectUnauthorized?: boolean\n}\n\nexport interface MailboxIdentityConfig {\n email: string\n password: string\n baseUrl?: string\n smtpPort?: number\n secure?: boolean\n rejectUnauthorized?: boolean\n}\n\nexport function deriveMailboxServiceDefaults(email: string, baseUrl?: string): {\n smtpHost: string\n httpBaseUrl?: string\n} {\n const domain = email.split('@')[1]?.trim()\n const resolvedBaseUrl = baseUrl?.trim() || (domain ? `https://${domain}` : undefined)\n const smtpHost = domain || (resolvedBaseUrl ? new URL(resolvedBaseUrl).hostname : 'localhost')\n return {\n smtpHost,\n httpBaseUrl: resolvedBaseUrl,\n }\n}\n\nexport class SmtpSender {\n private transport: Transporter\n private discoveredApiUrlPromise: Promise<string> | null = null\n private jmapSessionPromise: Promise<{\n accountId: string\n apiUrl: string\n }> | null = null\n private sentMailboxIdPromise: Promise<string | null> | null = null\n\n static fromMailboxIdentity(config: MailboxIdentityConfig): SmtpSender {\n const derived = deriveMailboxServiceDefaults(config.email, config.baseUrl)\n return new SmtpSender({\n host: derived.smtpHost,\n port: config.smtpPort ?? 587,\n user: config.email,\n password: config.password,\n httpBaseUrl: derived.httpBaseUrl,\n authToken: Buffer.from(`${config.email}:${config.password}`).toString('base64'),\n secure: config.secure,\n rejectUnauthorized: config.rejectUnauthorized,\n })\n }\n\n constructor(private readonly config: SmtpConfig) {\n this.transport = createTransport({\n host: config.host,\n port: config.port,\n secure: config.secure ?? false,\n auth: {\n user: config.user,\n pass: config.password,\n },\n tls: {\n rejectUnauthorized: config.rejectUnauthorized ?? true,\n },\n })\n }\n\n private senderDomain(): string {\n return this.config.user.split('@')[1]?.toLowerCase() ?? ''\n }\n\n private recipientDomain(email: string): string {\n return email.split('@')[1]?.toLowerCase() ?? ''\n }\n\n private shouldUseHttpFallback(to: string): boolean {\n return Boolean(\n this.config.httpBaseUrl\n && this.config.authToken\n && this.senderDomain()\n && this.senderDomain() === this.recipientDomain(to),\n )\n }\n\n private async resolveAampApiUrl(): Promise<string> {\n const base = this.config.httpBaseUrl?.replace(/\\/$/, '')\n if (!base) {\n throw new Error('HTTP send fallback is not configured')\n }\n\n if (!this.discoveredApiUrlPromise) {\n this.discoveredApiUrlPromise = (async () => {\n const discoveryRes = await fetch(`${base}/.well-known/aamp`)\n if (!discoveryRes.ok) {\n throw new Error(`AAMP discovery failed: ${discoveryRes.status}`)\n }\n const discovery = await discoveryRes.json() as { api?: { url?: string } }\n if (!discovery.api?.url) {\n throw new Error('AAMP discovery did not return api.url')\n }\n return new URL(discovery.api.url, `${base}/`).toString()\n })()\n }\n\n try {\n return await this.discoveredApiUrlPromise\n } catch (err) {\n this.discoveredApiUrlPromise = null\n throw err\n }\n }\n\n private async sendViaHttp(opts: {\n to: string\n subject: string\n text: string\n aampHeaders: Record<string, string>\n attachments?: Array<{ filename: string; contentType: string; content: Buffer | string }>\n }): Promise<{ messageId?: string }> {\n if (!this.config.authToken) {\n throw new Error('HTTP send fallback is not configured')\n }\n const apiUrl = new URL(await this.resolveAampApiUrl())\n apiUrl.searchParams.set('action', 'aamp.mailbox.send')\n\n const res = await fetch(apiUrl, {\n method: 'POST',\n headers: {\n Authorization: `Basic ${this.config.authToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n to: opts.to,\n subject: opts.subject,\n text: opts.text,\n aampHeaders: opts.aampHeaders,\n attachments: opts.attachments?.map((a) => ({\n filename: a.filename,\n contentType: a.contentType,\n content: typeof a.content === 'string' ? a.content : a.content.toString('base64'),\n })),\n }),\n })\n\n const data = await res.json().catch(() => ({})) as { details?: string; messageId?: string }\n if (!res.ok) {\n throw new Error(data.details || `HTTP send failed: ${res.status}`)\n }\n return { messageId: data.messageId }\n }\n\n private canPersistSentCopy(): boolean {\n return Boolean(this.config.httpBaseUrl && this.config.authToken)\n }\n\n private getJmapAuthHeader(): string {\n if (!this.config.authToken) {\n throw new Error('JMAP auth token is not configured')\n }\n return `Basic ${this.config.authToken}`\n }\n\n private async resolveJmapSession(): Promise<{ accountId: string; apiUrl: string }> {\n const base = this.config.httpBaseUrl?.replace(/\\/$/, '')\n if (!base) {\n throw new Error('JMAP base URL is not configured')\n }\n\n if (!this.jmapSessionPromise) {\n this.jmapSessionPromise = (async () => {\n const res = await fetch(`${base}/.well-known/jmap`, {\n headers: { Authorization: this.getJmapAuthHeader() },\n })\n if (!res.ok) {\n throw new Error(`JMAP session failed: ${res.status} ${res.statusText}`)\n }\n\n const session = await res.json() as {\n accounts?: Record<string, unknown>\n primaryAccounts?: Record<string, string>\n }\n const accountId =\n session.primaryAccounts?.['urn:ietf:params:jmap:mail']\n ?? Object.keys(session.accounts ?? {})[0]\n\n if (!accountId) {\n throw new Error('No JMAP mail account available')\n }\n\n return {\n accountId,\n apiUrl: `${base}/jmap/`,\n }\n })()\n }\n\n try {\n return await this.jmapSessionPromise\n } catch (err) {\n this.jmapSessionPromise = null\n throw err\n }\n }\n\n private async jmapCall(\n methodCalls: Array<[string, Record<string, unknown>, string]>,\n ): Promise<Array<[string, Record<string, unknown>, string]>> {\n const session = await this.resolveJmapSession()\n const res = await fetch(session.apiUrl, {\n method: 'POST',\n headers: {\n Authorization: this.getJmapAuthHeader(),\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n using: [\n 'urn:ietf:params:jmap:core',\n 'urn:ietf:params:jmap:mail',\n ],\n methodCalls: methodCalls.map(([name, args, tag]) => [\n name,\n { accountId: session.accountId, ...args },\n tag,\n ]),\n }),\n })\n\n if (!res.ok) {\n throw new Error(`JMAP API call failed: ${res.status}`)\n }\n\n const data = await res.json() as {\n methodResponses?: Array<[string, Record<string, unknown>, string]>\n }\n return data.methodResponses ?? []\n }\n\n private async getSentMailboxId(): Promise<string | null> {\n if (!this.sentMailboxIdPromise) {\n this.sentMailboxIdPromise = (async () => {\n const responses = await this.jmapCall([\n ['Mailbox/get', { ids: null }, 'mb1'],\n ])\n const result = responses.find(([name]) => name === 'Mailbox/get')?.[1] as\n | { list?: Array<{ id: string; role: string | null }> }\n | undefined\n const mailboxes = result?.list ?? []\n return mailboxes.find((mailbox) => mailbox.role === 'sent')?.id ?? mailboxes[0]?.id ?? null\n })()\n }\n\n try {\n return await this.sentMailboxIdPromise\n } catch (err) {\n this.sentMailboxIdPromise = null\n throw err\n }\n }\n\n private async saveToSent(params: {\n from: string\n to: string\n subject: string\n text: string\n aampHeaders: Record<string, string>\n messageId?: string\n inReplyTo?: string\n references?: string\n }): Promise<void> {\n if (!this.canPersistSentCopy()) return\n\n const sentMailboxId = await this.getSentMailboxId()\n if (!sentMailboxId) return\n\n const emailCreate: Record<string, unknown> = {\n mailboxIds: { [sentMailboxId]: true },\n from: [{ email: params.from }],\n to: [{ email: params.to }],\n subject: params.subject,\n bodyValues: {\n body: {\n value: params.text,\n charset: 'utf-8',\n },\n },\n textBody: [{ partId: 'body', type: 'text/plain' }],\n keywords: { '$seen': true },\n }\n\n if (params.inReplyTo) {\n emailCreate['header:In-Reply-To:asText'] = ` ${sanitize(params.inReplyTo)}`\n }\n if (params.messageId) {\n emailCreate['header:Message-ID:asText'] = ` ${sanitize(params.messageId)}`\n }\n if (params.references) {\n emailCreate['header:References:asText'] = ` ${sanitize(params.references)}`\n }\n for (const [name, value] of Object.entries(params.aampHeaders)) {\n emailCreate[`header:${name}:asText`] = ` ${value}`\n }\n\n await this.jmapCall([\n ['Email/set', { create: { sent1: emailCreate } }, 'sent1'],\n ])\n }\n\n private async saveToSentBestEffort(params: {\n from: string\n to: string\n subject: string\n text: string\n aampHeaders: Record<string, string>\n messageId?: string\n inReplyTo?: string\n references?: string\n }): Promise<void> {\n if (!this.canPersistSentCopy()) return\n try {\n await this.saveToSent(params)\n } catch {\n // Non-fatal: mail delivery already succeeded, Sent copy is only for visibility/debugging.\n }\n }\n\n /**\n * Send a task.dispatch email.\n * Returns both the generated taskId and the SMTP Message-ID so callers can\n * store a reverse-index (messageId \u2192 taskId) for In-Reply-To thread routing.\n */\n async sendTask(opts: SendTaskOptions): Promise<{ taskId: string; messageId: string }> {\n const taskId = opts.taskId ?? randomUUID()\n const aampHeaders = buildDispatchHeaders({\n taskId,\n priority: opts.priority,\n expiresAt: opts.expiresAt,\n contextLinks: opts.contextLinks ?? [],\n dispatchContext: opts.dispatchContext,\n parentTaskId: opts.parentTaskId,\n })\n\n const sendMailOpts: Record<string, unknown> = {\n from: this.config.user,\n to: opts.to,\n subject: `[AAMP Task] ${sanitize(opts.title)}`,\n text: opts.rawBodyText ?? [\n `Task: ${opts.title}`,\n `Task ID: ${taskId}`,\n `Priority: ${opts.priority ?? 'normal'}`,\n opts.expiresAt ? `Expires At: ${opts.expiresAt}` : `Expires At: none`,\n opts.contextLinks?.length\n ? `Context:\\n${opts.contextLinks.map((l) => ` ${l}`).join('\\n')}`\n : '',\n opts.bodyText ?? '',\n ``,\n `--- This email was sent by AAMP. Reply directly to submit your result. ---`,\n ]\n .filter(Boolean)\n .join('\\n'),\n headers: aampHeaders,\n }\n\n if (opts.attachments?.length) {\n sendMailOpts.attachments = opts.attachments.map(a => ({\n filename: a.filename,\n content: typeof a.content === 'string' ? Buffer.from(a.content, 'base64') : a.content,\n contentType: a.contentType,\n }))\n }\n\n if (this.shouldUseHttpFallback(opts.to)) {\n const info = await this.sendViaHttp({\n to: opts.to,\n subject: sendMailOpts.subject as string,\n text: sendMailOpts.text as string,\n aampHeaders,\n attachments: opts.attachments?.map(a => ({\n filename: a.filename,\n contentType: a.contentType,\n content: typeof a.content === 'string' ? Buffer.from(a.content, 'base64') : a.content,\n })),\n })\n await this.saveToSentBestEffort({\n from: this.config.user,\n to: opts.to,\n subject: sendMailOpts.subject as string,\n text: sendMailOpts.text as string,\n aampHeaders,\n messageId: info.messageId,\n })\n return { taskId, messageId: info.messageId ?? '' }\n }\n\n const info = await this.transport.sendMail(sendMailOpts)\n await this.saveToSentBestEffort({\n from: this.config.user,\n to: opts.to,\n subject: sendMailOpts.subject as string,\n text: sendMailOpts.text as string,\n aampHeaders,\n messageId: info.messageId,\n })\n\n return { taskId, messageId: info.messageId ?? '' }\n }\n\n /**\n * Send a task.result email back to the dispatcher\n */\n async sendResult(opts: SendResultOptions): Promise<void> {\n const aampHeaders = buildResultHeaders({\n taskId: opts.taskId,\n status: opts.status,\n output: opts.output,\n errorMsg: opts.errorMsg,\n structuredResult: opts.structuredResult,\n })\n\n const mailOpts: Record<string, unknown> = {\n from: this.config.user,\n to: opts.to,\n subject: `[AAMP Result] Task ${opts.taskId} \u2014 ${opts.status}`,\n text: opts.rawBodyText ?? [\n `AAMP Task Result`,\n ``,\n `Task ID: ${opts.taskId}`,\n `Status: ${opts.status}`,\n ``,\n `Output:`,\n opts.output,\n opts.errorMsg ? `\\nError: ${opts.errorMsg}` : '',\n ]\n .filter((s) => s !== '')\n .join('\\n'),\n headers: aampHeaders,\n }\n if (opts.inReplyTo) {\n mailOpts.inReplyTo = opts.inReplyTo\n mailOpts.references = opts.inReplyTo\n }\n if (opts.attachments?.length) {\n mailOpts.attachments = opts.attachments.map(a => ({\n filename: a.filename,\n content: typeof a.content === 'string' ? Buffer.from(a.content, 'base64') : a.content,\n contentType: a.contentType,\n }))\n }\n\n if (this.shouldUseHttpFallback(opts.to)) {\n const info = await this.sendViaHttp({\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n attachments: opts.attachments?.map(a => ({\n filename: a.filename,\n contentType: a.contentType,\n content: typeof a.content === 'string' ? Buffer.from(a.content, 'base64') : a.content,\n })),\n })\n await this.saveToSentBestEffort({\n from: this.config.user,\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n messageId: info.messageId,\n inReplyTo: opts.inReplyTo,\n references: opts.inReplyTo,\n })\n return\n }\n const info = await this.transport.sendMail(mailOpts)\n await this.saveToSentBestEffort({\n from: this.config.user,\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n messageId: info.messageId,\n inReplyTo: opts.inReplyTo,\n references: opts.inReplyTo,\n })\n }\n\n /**\n * Send a task.help_needed email when the agent is blocked\n */\n async sendHelp(opts: SendHelpOptions): Promise<void> {\n const aampHeaders = buildHelpHeaders({\n taskId: opts.taskId,\n question: opts.question,\n blockedReason: opts.blockedReason,\n suggestedOptions: opts.suggestedOptions,\n })\n\n const helpMailOpts: Record<string, unknown> = {\n from: this.config.user,\n to: opts.to,\n subject: `[AAMP Help] Task ${opts.taskId} needs assistance`,\n text: opts.rawBodyText ?? [\n `AAMP Task Help Request`,\n ``,\n `Task ID: ${opts.taskId}`,\n ``,\n `Question: ${opts.question}`,\n ``,\n `Blocked reason: ${opts.blockedReason}`,\n ``,\n opts.suggestedOptions.length\n ? `Suggested options:\\n${opts.suggestedOptions.map((o, i) => ` ${i + 1}. ${o}`).join('\\n')}`\n : '',\n ]\n .filter(Boolean)\n .join('\\n'),\n headers: aampHeaders,\n }\n if (opts.inReplyTo) {\n helpMailOpts.inReplyTo = opts.inReplyTo\n helpMailOpts.references = opts.inReplyTo\n }\n if (opts.attachments?.length) {\n helpMailOpts.attachments = opts.attachments.map(a => ({\n filename: a.filename,\n content: typeof a.content === 'string' ? Buffer.from(a.content, 'base64') : a.content,\n contentType: a.contentType,\n }))\n }\n\n if (this.shouldUseHttpFallback(opts.to)) {\n const info = await this.sendViaHttp({\n to: opts.to,\n subject: helpMailOpts.subject as string,\n text: helpMailOpts.text as string,\n aampHeaders,\n attachments: opts.attachments?.map(a => ({\n filename: a.filename,\n contentType: a.contentType,\n content: typeof a.content === 'string' ? Buffer.from(a.content, 'base64') : a.content,\n })),\n })\n await this.saveToSentBestEffort({\n from: this.config.user,\n to: opts.to,\n subject: helpMailOpts.subject as string,\n text: helpMailOpts.text as string,\n aampHeaders,\n messageId: info.messageId,\n inReplyTo: opts.inReplyTo,\n references: opts.inReplyTo,\n })\n return\n }\n const info = await this.transport.sendMail(helpMailOpts)\n await this.saveToSentBestEffort({\n from: this.config.user,\n to: opts.to,\n subject: helpMailOpts.subject as string,\n text: helpMailOpts.text as string,\n aampHeaders,\n messageId: info.messageId,\n inReplyTo: opts.inReplyTo,\n references: opts.inReplyTo,\n })\n }\n\n /**\n * Send a task.cancel email to stop a previously dispatched task.\n */\n async sendCancel(opts: SendCancelOptions): Promise<void> {\n const aampHeaders = buildCancelHeaders({\n taskId: opts.taskId,\n })\n\n const mailOpts: Record<string, unknown> = {\n from: this.config.user,\n to: opts.to,\n subject: `[AAMP Cancel] Task ${opts.taskId}`,\n text: opts.bodyText ?? 'The dispatcher cancelled this task.',\n headers: aampHeaders,\n }\n if (opts.inReplyTo) {\n mailOpts.inReplyTo = opts.inReplyTo\n mailOpts.references = opts.inReplyTo\n }\n\n if (this.shouldUseHttpFallback(opts.to)) {\n const info = await this.sendViaHttp({\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n })\n await this.saveToSentBestEffort({\n from: this.config.user,\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n messageId: info.messageId,\n inReplyTo: opts.inReplyTo,\n references: opts.inReplyTo,\n })\n return\n }\n const info = await this.transport.sendMail(mailOpts)\n await this.saveToSentBestEffort({\n from: this.config.user,\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n messageId: info.messageId,\n inReplyTo: opts.inReplyTo,\n references: opts.inReplyTo,\n })\n }\n\n /**\n * Send a task.ack email to confirm receipt of a dispatch\n */\n async sendAck(opts: { to: string; taskId: string; inReplyTo?: string }): Promise<void> {\n const aampHeaders = buildAckHeaders({ taskId: opts.taskId })\n const mailOpts: Record<string, unknown> = {\n from: this.config.user,\n to: opts.to,\n subject: `[AAMP ACK] Task ${opts.taskId}`,\n text: '',\n headers: aampHeaders,\n }\n if (opts.inReplyTo) {\n mailOpts.inReplyTo = opts.inReplyTo\n mailOpts.references = opts.inReplyTo\n }\n\n if (this.shouldUseHttpFallback(opts.to)) {\n const info = await this.sendViaHttp({\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n })\n await this.saveToSentBestEffort({\n from: this.config.user,\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n messageId: info.messageId,\n inReplyTo: opts.inReplyTo,\n references: opts.inReplyTo,\n })\n return\n }\n const info = await this.transport.sendMail(mailOpts)\n await this.saveToSentBestEffort({\n from: this.config.user,\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n messageId: info.messageId,\n inReplyTo: opts.inReplyTo,\n references: opts.inReplyTo,\n })\n }\n\n async sendStreamOpened(opts: {\n to: string\n taskId: string\n streamId: string\n inReplyTo?: string\n }): Promise<void> {\n const aampHeaders = buildStreamOpenedHeaders({\n taskId: opts.taskId,\n streamId: opts.streamId,\n })\n const mailOpts: Record<string, unknown> = {\n from: this.config.user,\n to: opts.to,\n subject: `[AAMP Stream] Task ${opts.taskId}`,\n text: `AAMP task stream is ready.\\n\\nTask ID: ${opts.taskId}\\nStream ID: ${opts.streamId}`,\n headers: aampHeaders,\n }\n if (opts.inReplyTo) {\n mailOpts.inReplyTo = opts.inReplyTo\n mailOpts.references = opts.inReplyTo\n }\n\n if (this.shouldUseHttpFallback(opts.to)) {\n const info = await this.sendViaHttp({\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n })\n await this.saveToSentBestEffort({\n from: this.config.user,\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n messageId: info.messageId,\n inReplyTo: opts.inReplyTo,\n references: opts.inReplyTo,\n })\n return\n }\n\n const info = await this.transport.sendMail(mailOpts)\n await this.saveToSentBestEffort({\n from: this.config.user,\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n messageId: info.messageId,\n inReplyTo: opts.inReplyTo,\n references: opts.inReplyTo,\n })\n }\n\n async sendCardQuery(opts: SendCardQueryOptions): Promise<{ taskId: string; messageId: string }> {\n const taskId = opts.taskId ?? randomUUID()\n const aampHeaders = buildCardQueryHeaders({ taskId })\n const mailOpts: Record<string, unknown> = {\n from: this.config.user,\n to: opts.to,\n subject: `[AAMP Card Query] ${taskId}`,\n text: opts.bodyText?.trim() || 'Please share your agent card and capability details.',\n headers: aampHeaders,\n }\n if (opts.inReplyTo) {\n mailOpts.inReplyTo = opts.inReplyTo\n mailOpts.references = opts.inReplyTo\n }\n\n if (this.shouldUseHttpFallback(opts.to)) {\n const info = await this.sendViaHttp({\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n })\n await this.saveToSentBestEffort({\n from: this.config.user,\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n messageId: info.messageId,\n inReplyTo: opts.inReplyTo,\n references: opts.inReplyTo,\n })\n return { taskId, messageId: info.messageId ?? '' }\n }\n\n const info = await this.transport.sendMail(mailOpts)\n await this.saveToSentBestEffort({\n from: this.config.user,\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n messageId: info.messageId,\n inReplyTo: opts.inReplyTo,\n references: opts.inReplyTo,\n })\n return { taskId, messageId: info.messageId ?? '' }\n }\n\n async sendCardResponse(opts: SendCardResponseOptions): Promise<void> {\n const aampHeaders = buildCardResponseHeaders({\n taskId: opts.taskId,\n summary: opts.summary,\n })\n const mailOpts: Record<string, unknown> = {\n from: this.config.user,\n to: opts.to,\n subject: `[AAMP Card] ${sanitize(opts.summary)}`,\n text: opts.bodyText,\n headers: aampHeaders,\n }\n if (opts.inReplyTo) {\n mailOpts.inReplyTo = opts.inReplyTo\n mailOpts.references = opts.inReplyTo\n }\n\n if (this.shouldUseHttpFallback(opts.to)) {\n const info = await this.sendViaHttp({\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n })\n await this.saveToSentBestEffort({\n from: this.config.user,\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n messageId: info.messageId,\n inReplyTo: opts.inReplyTo,\n references: opts.inReplyTo,\n })\n return\n }\n\n const info = await this.transport.sendMail(mailOpts)\n await this.saveToSentBestEffort({\n from: this.config.user,\n to: opts.to,\n subject: mailOpts.subject as string,\n text: mailOpts.text as string,\n aampHeaders,\n messageId: info.messageId,\n inReplyTo: opts.inReplyTo,\n references: opts.inReplyTo,\n })\n }\n\n /**\n * Verify SMTP connection\n */\n async verify(): Promise<boolean> {\n try {\n await this.transport.verify()\n return true\n } catch {\n return false\n }\n }\n\n close(): void {\n this.transport.close()\n }\n}\n", "import type { AampThreadEvent } from './types.js'\n\nexport interface RenderThreadHistoryOptions {\n maxEvents?: number\n}\n\nfunction singleLine(value?: string | null, maxLength = 220): string {\n const normalized = (value ?? '').replace(/\\s+/g, ' ').trim()\n if (!normalized) return ''\n if (normalized.length <= maxLength) return normalized\n return `${normalized.slice(0, maxLength - 1)}\u2026`\n}\n\nfunction formatTimestamp(value: string): string {\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return value\n return date.toISOString().slice(0, 16).replace('T', ' ')\n}\n\nfunction renderEventLine(event: AampThreadEvent): string {\n const from = event.from.split('@')[0] || event.from\n const timestamp = formatTimestamp(event.createdAt)\n\n if (event.intent === 'task.dispatch') {\n const summary = singleLine(event.bodyText) || singleLine(event.title) || 'Task dispatched'\n return `[${timestamp}] ${from} dispatched: ${summary}`\n }\n\n if (event.intent === 'task.help_needed') {\n const question = singleLine(event.question) || 'Asked for help'\n const reason = singleLine(event.blockedReason)\n return `[${timestamp}] ${from} asked for help: ${question}${reason ? ` (reason: ${reason})` : ''}`\n }\n\n if (event.intent === 'task.result') {\n const output = singleLine(event.output) || singleLine(event.bodyText) || 'Sent a result'\n return `[${timestamp}] ${from} replied: ${output}`\n }\n\n if (event.intent === 'task.cancel') {\n const body = singleLine(event.bodyText) || 'Cancelled the task'\n return `[${timestamp}] ${from} cancelled the task: ${body}`\n }\n\n if (event.intent === 'task.ack') {\n return `[${timestamp}] ${from} acknowledged the task`\n }\n\n return `[${timestamp}] ${from}: ${singleLine(event.bodyText) || event.intent}`\n}\n\nexport function renderThreadHistoryForAgent(\n events: AampThreadEvent[],\n options: RenderThreadHistoryOptions = {},\n): string {\n const filtered = events.filter((event) => event.intent !== 'task.stream.opened')\n if (filtered.length === 0) return ''\n\n const maxEvents = Math.max(1, options.maxEvents ?? 8)\n const visible = filtered.slice(-maxEvents)\n const omitted = filtered.length - visible.length\n\n return [\n 'Prior thread context:',\n ...(omitted > 0 ? [`(${omitted} earlier event(s) omitted)`] : []),\n ...visible.map((event) => `- ${renderEventLine(event)}`),\n ].join('\\n')\n}\n", "/**\n * AampClient \u2014 Main SDK entry point\n *\n * Combines JMAP WebSocket Push (receive) + SMTP (send) into a single client.\n *\n * Usage:\n *\n * ```typescript\n * const client = new AampClient({\n * email: 'codereviewer-abc@aamp.example.com',\n * mailboxToken: '<base64(email:password)>',\n * baseUrl: 'https://meshmail.ai',\n * smtpPort: 587,\n * smtpPassword: 'agent-smtp-password',\n * })\n *\n * // Listen for incoming tasks\n * client.on('task.dispatch', async (task) => {\n * const result = await doWork(task)\n * await client.sendResult({\n * to: task.from,\n * taskId: task.taskId,\n * status: 'completed',\n * output: result,\n * })\n * })\n *\n * await client.connect()\n * ```\n */\n\nimport { JmapPushClient } from './jmap-push.js'\nimport { SmtpSender, deriveMailboxServiceDefaults } from './smtp-sender.js'\nimport { TinyEmitter } from './tiny-emitter.js'\nimport { renderThreadHistoryForAgent } from './thread.js'\nimport type {\n AampClientConfig,\n AampClientEvents,\n AampDiscoveryDocument,\n AgentDirectoryEntry,\n AgentDirectoryProfile,\n AgentDirectorySearchEntry,\n AampThreadEvent,\n AampMailboxIdentityConfig,\n AampStreamEvent,\n CardQuery,\n CardResponse,\n CloseStreamOptions,\n CreateStreamOptions,\n CreateStreamResult,\n DirectoryListOptions,\n DirectorySearchOptions,\n GetTaskStreamOptions,\n GetThreadHistoryOptions,\n HydratedTaskDispatch,\n RegisterMailboxOptions,\n RegisteredMailboxIdentity,\n RegisteredCommandDispatchPayload,\n SendCardQueryOptions,\n SendCardResponseOptions,\n SendCancelOptions,\n SendRegisteredCommandOptions,\n StreamSubscription,\n TaskCancel,\n TaskDispatch,\n TaskThreadHistory,\n TaskResult,\n TaskHelp,\n TaskAck,\n TaskStreamOpened,\n TaskStreamState,\n HumanReply,\n SendTaskOptions,\n SendResultOptions,\n SendHelpOptions,\n UpdateDirectoryProfileOptions,\n} from './types.js'\n\nfunction buildRegisteredCommandDispatchPayload(\n opts: Pick<SendRegisteredCommandOptions, 'command' | 'args' | 'inputs' | 'streamMode'>,\n): RegisteredCommandDispatchPayload {\n const command = opts.command.trim()\n if (!command) {\n throw new Error('Registered command name cannot be empty.')\n }\n\n if (opts.args != null && (typeof opts.args !== 'object' || Array.isArray(opts.args))) {\n throw new Error('Registered command args must be an object when provided.')\n }\n\n if (opts.inputs) {\n for (const input of opts.inputs) {\n if (!input.slot?.trim() || !input.attachmentName?.trim()) {\n throw new Error('Each registered command input must include slot and attachmentName.')\n }\n }\n }\n\n return {\n kind: 'registered-command/v1',\n command,\n ...(opts.args && Object.keys(opts.args).length > 0 ? { args: opts.args } : {}),\n ...(opts.inputs?.length ? { inputs: opts.inputs } : {}),\n stream: { mode: opts.streamMode ?? 'full' },\n }\n}\n\nconst DEFAULT_TASK_DISPATCH_CONCURRENCY = 10\n\nfunction normalizeTaskDispatchConcurrency(value: number | undefined): number {\n if (value == null) return DEFAULT_TASK_DISPATCH_CONCURRENCY\n\n if (!Number.isFinite(value) || !Number.isInteger(value) || value < 1) {\n throw new Error('taskDispatchConcurrency must be a positive integer')\n }\n\n return value\n}\n\ntype StreamAppendOperation =\n | {\n kind: 'text-delta-batch'\n text: string\n payload: Record<string, unknown>\n resolvers: Array<(event: AampStreamEvent) => void>\n rejecters: Array<(error: unknown) => void>\n }\n | {\n kind: 'single-event'\n opts: {\n streamId: string\n type: AampStreamEvent['type']\n payload: Record<string, unknown>\n }\n resolve: (event: AampStreamEvent) => void\n reject: (error: unknown) => void\n }\n\nexport class AampClient extends TinyEmitter<AampClientEvents> {\n private jmapClient: JmapPushClient\n private smtpSender: SmtpSender\n private readonly config: AampClientConfig\n private readonly taskDispatchConcurrency: number\n private readonly pendingTaskDispatches: TaskDispatch[] = []\n private activeTaskDispatchCount = 0\n private readonly streamAppendQueues = new Map<string, {\n running: boolean\n operations: StreamAppendOperation[]\n }>()\n\n constructor(config: AampClientConfig) {\n super()\n this.config = config\n this.taskDispatchConcurrency = normalizeTaskDispatchConcurrency(config.taskDispatchConcurrency)\n\n const mailboxToken = config.mailboxToken\n const resolvedBaseUrl = config.baseUrl\n const derived = deriveMailboxServiceDefaults(config.email, resolvedBaseUrl)\n const smtpHost = config.smtpHost ?? derived.smtpHost\n\n // Decode mailbox token (format: base64(email:password))\n let password: string\n try {\n const decoded = Buffer.from(mailboxToken, 'base64').toString('utf-8')\n const colonIdx = decoded.indexOf(':')\n if (colonIdx < 0) throw new Error('Invalid mailboxToken format: expected base64(email:password)')\n password = decoded.slice(colonIdx + 1)\n if (!password) throw new Error('Invalid mailboxToken: empty password')\n } catch (err) {\n if (err instanceof Error && err.message.startsWith('Invalid mailboxToken')) throw err\n throw new Error(`Failed to decode mailboxToken: ${(err as Error).message}`)\n }\n\n this.jmapClient = new JmapPushClient({\n email: config.email,\n password: password ?? config.smtpPassword,\n jmapUrl: resolvedBaseUrl,\n reconnectInterval: config.reconnectInterval ?? 5000,\n rejectUnauthorized: config.rejectUnauthorized,\n })\n\n this.smtpSender = new SmtpSender({\n host: smtpHost,\n port: config.smtpPort ?? 587,\n user: config.email,\n password: config.smtpPassword,\n httpBaseUrl: config.httpSendBaseUrl ?? resolvedBaseUrl,\n authToken: mailboxToken,\n rejectUnauthorized: config.rejectUnauthorized,\n })\n\n // Forward JMAP events to this emitter\n this.jmapClient.on('task.dispatch', (task: TaskDispatch) => {\n this.enqueueTaskDispatch(task)\n })\n\n this.jmapClient.on('task.cancel', (task: TaskCancel) => {\n this.emit('task.cancel', task)\n })\n\n this.jmapClient.on('task.result', (result: TaskResult) => {\n this.emit('task.result', result)\n })\n\n this.jmapClient.on('task.help_needed', (help: TaskHelp) => {\n this.emit('task.help_needed', help)\n })\n\n this.jmapClient.on('task.ack', (ack: TaskAck) => {\n this.emit('task.ack', ack)\n })\n\n this.jmapClient.on('task.stream.opened', (stream: TaskStreamOpened) => {\n this.emit('task.stream.opened', stream)\n })\n\n this.jmapClient.on('card.query', (query: CardQuery) => {\n this.emit('card.query', query)\n })\n\n this.jmapClient.on('card.response', (response: CardResponse) => {\n this.emit('card.response', response)\n })\n\n // Auto-ACK: when a task.dispatch is received, automatically send an ACK back\n this.jmapClient.on('_autoAck', async ({ to, taskId, messageId }: { to: string; taskId: string; messageId: string }) => {\n try {\n await this.smtpSender.sendAck({ to, taskId, inReplyTo: messageId })\n } catch (err) {\n console.warn(`[AAMP] Failed to send ACK for task ${taskId}: ${(err as Error).message}`)\n }\n })\n\n this.jmapClient.on('reply', (reply: HumanReply) => {\n this.emit('reply', reply)\n })\n\n this.jmapClient.on('connected', () => {\n this.emit('connected')\n })\n\n this.jmapClient.on('disconnected', (reason: string) => {\n this.emit('disconnected', reason)\n })\n\n this.jmapClient.on('error', (err: Error) => {\n this.emit('error', err)\n })\n }\n\n static fromMailboxIdentity(config: AampMailboxIdentityConfig): AampClient {\n const derived = deriveMailboxServiceDefaults(config.email, config.baseUrl)\n return new AampClient({\n email: config.email,\n mailboxToken: Buffer.from(`${config.email}:${config.smtpPassword}`).toString('base64'),\n baseUrl: derived.httpBaseUrl ?? `https://${config.email.split('@')[1] ?? 'localhost'}`,\n smtpHost: derived.smtpHost,\n smtpPort: config.smtpPort ?? 587,\n smtpPassword: config.smtpPassword,\n reconnectInterval: config.reconnectInterval,\n taskDispatchConcurrency: config.taskDispatchConcurrency,\n rejectUnauthorized: config.rejectUnauthorized,\n })\n }\n\n static async discoverAampService(aampHost: string): Promise<AampDiscoveryDocument> {\n const base = aampHost.replace(/\\/$/, '')\n const res = await fetch(`${base}/.well-known/aamp`)\n if (!res.ok) {\n throw new Error(`AAMP discovery failed: ${res.status} ${res.statusText}`)\n }\n const discovery = await res.json() as AampDiscoveryDocument\n if (!discovery.api?.url) {\n throw new Error('AAMP discovery did not return api.url')\n }\n return discovery\n }\n\n private static async callDiscoveredApi(\n base: string,\n opts: {\n action: string\n method?: 'GET' | 'POST'\n query?: Record<string, string | number | boolean | undefined>\n body?: unknown\n authToken?: string\n },\n ): Promise<Response> {\n const discovery = await AampClient.discoverAampService(base)\n const apiUrl = new URL(discovery.api!.url!, `${base}/`)\n apiUrl.searchParams.set('action', opts.action)\n for (const [key, value] of Object.entries(opts.query ?? {})) {\n if (value == null) continue\n apiUrl.searchParams.set(key, String(value))\n }\n return fetch(apiUrl, {\n method: opts.method ?? 'GET',\n headers: {\n ...(opts.authToken ? { Authorization: `Basic ${opts.authToken}` } : {}),\n ...(opts.body ? { 'Content-Type': 'application/json' } : {}),\n },\n ...(opts.body ? { body: JSON.stringify(opts.body) } : {}),\n })\n }\n\n static async registerMailbox(opts: RegisterMailboxOptions): Promise<RegisteredMailboxIdentity> {\n const base = opts.aampHost.replace(/\\/$/, '')\n const registerRes = await AampClient.callDiscoveredApi(base, {\n action: 'aamp.mailbox.register',\n method: 'POST',\n body: {\n slug: opts.slug,\n description: opts.description,\n },\n })\n if (!registerRes.ok) {\n const body = await registerRes.text().catch(() => '')\n throw new Error(`Mailbox registration failed: ${registerRes.status} ${body || registerRes.statusText}`)\n }\n const registerData = await registerRes.json() as { registrationCode?: string }\n if (!registerData.registrationCode) {\n throw new Error('Mailbox registration succeeded but no registrationCode was returned')\n }\n\n const credsRes = await AampClient.callDiscoveredApi(base, {\n action: 'aamp.mailbox.credentials',\n query: { code: registerData.registrationCode },\n })\n if (!credsRes.ok) {\n const body = await credsRes.text().catch(() => '')\n throw new Error(`Mailbox credential exchange failed: ${credsRes.status} ${body || credsRes.statusText}`)\n }\n const creds = await credsRes.json() as {\n email?: string\n mailbox?: { token?: string }\n smtp?: { password?: string }\n }\n if (!creds.email || !creds.mailbox?.token || !creds.smtp?.password) {\n throw new Error('Mailbox credential exchange returned an incomplete identity payload')\n }\n\n return {\n email: creds.email,\n mailboxToken: creds.mailbox.token,\n smtpPassword: creds.smtp.password,\n baseUrl: base,\n }\n }\n\n static async checkMailbox(opts: {\n aampHost: string\n email: string\n }): Promise<{ aamp: boolean; domain?: string }> {\n const base = opts.aampHost.replace(/\\/$/, '')\n const res = await AampClient.callDiscoveredApi(base, {\n action: 'aamp.mailbox.check',\n query: { email: opts.email },\n })\n if (!res.ok) {\n const body = await res.text().catch(() => '')\n throw new Error(`Mailbox check failed: ${res.status} ${body || res.statusText}`)\n }\n const payload = await res.json() as { aamp?: boolean; domain?: string }\n return {\n aamp: Boolean(payload.aamp),\n ...(payload.domain ? { domain: payload.domain } : {}),\n }\n }\n\n // =====================================================\n // Lifecycle\n // =====================================================\n\n /**\n * Connect to JMAP and start listening for tasks\n */\n async connect(): Promise<void> {\n await this.jmapClient.start()\n }\n\n /**\n * Disconnect and clean up\n */\n disconnect(): void {\n this.jmapClient.stop()\n this.smtpSender.close()\n }\n\n /**\n * Returns true if the JMAP connection is active\n */\n isConnected(): boolean {\n return this.jmapClient.isConnected()\n }\n\n isUsingPollingFallback(): boolean {\n return this.jmapClient.isUsingPollingFallback()\n }\n\n // =====================================================\n // Sending\n // =====================================================\n\n /**\n * Send a task.dispatch email to an agent.\n * Returns the generated taskId and the SMTP Message-ID.\n * Store messageId \u2192 taskId in Redis/DB to support In-Reply-To thread routing\n * for human replies that arrive without X-AAMP headers.\n */\n async sendTask(opts: SendTaskOptions): Promise<{ taskId: string; messageId: string }> {\n return this.smtpSender.sendTask(opts)\n }\n\n async sendRegisteredCommand(opts: SendRegisteredCommandOptions): Promise<{ taskId: string; messageId: string }> {\n const payload = buildRegisteredCommandDispatchPayload(opts)\n return this.smtpSender.sendTask({\n to: opts.to,\n taskId: opts.taskId,\n title: opts.title?.trim() || `Registered command: ${payload.command}`,\n rawBodyText: JSON.stringify(payload, null, 2),\n priority: opts.priority,\n expiresAt: opts.expiresAt,\n sessionKey: opts.sessionKey,\n contextLinks: opts.contextLinks,\n dispatchContext: opts.dispatchContext,\n parentTaskId: opts.parentTaskId,\n attachments: opts.attachments,\n })\n }\n\n async sendCancel(opts: SendCancelOptions): Promise<void> {\n return this.smtpSender.sendCancel(opts)\n }\n\n /**\n * Send a task.result email (agent \u2192 system/dispatcher)\n */\n async sendResult(opts: SendResultOptions): Promise<void> {\n return this.smtpSender.sendResult(opts)\n }\n\n /**\n * Send a task.help_needed email when the agent needs human assistance\n */\n async sendHelp(opts: SendHelpOptions): Promise<void> {\n return this.smtpSender.sendHelp(opts)\n }\n\n async sendStreamOpened(opts: {\n to: string\n taskId: string\n streamId: string\n inReplyTo?: string\n }): Promise<void> {\n return this.smtpSender.sendStreamOpened(opts)\n }\n\n async sendCardQuery(opts: SendCardQueryOptions): Promise<{ taskId: string; messageId: string }> {\n return this.smtpSender.sendCardQuery(opts)\n }\n\n async sendCardResponse(opts: SendCardResponseOptions): Promise<void> {\n return this.smtpSender.sendCardResponse(opts)\n }\n\n async updateDirectoryProfile(opts: UpdateDirectoryProfileOptions): Promise<AgentDirectoryProfile> {\n const base = this.config.baseUrl\n const mailboxToken = this.config.mailboxToken\n const res = await AampClient.callDiscoveredApi(base, {\n action: 'aamp.directory.upsert',\n method: 'POST',\n authToken: mailboxToken,\n body: opts,\n })\n if (!res.ok) {\n const body = await res.text().catch(() => '')\n throw new Error(`Directory profile update failed: ${res.status} ${body || res.statusText}`)\n }\n const data = await res.json() as { profile: AgentDirectoryProfile }\n return data.profile\n }\n\n async listDirectory(opts: DirectoryListOptions = {}): Promise<AgentDirectoryEntry[]> {\n const base = this.config.baseUrl\n const mailboxToken = this.config.mailboxToken\n const res = await AampClient.callDiscoveredApi(base, {\n action: 'aamp.directory.list',\n authToken: mailboxToken,\n query: {\n scope: opts.scope,\n includeSelf: opts.includeSelf,\n limit: opts.limit,\n },\n })\n if (!res.ok) {\n const body = await res.text().catch(() => '')\n throw new Error(`Directory list failed: ${res.status} ${body || res.statusText}`)\n }\n const data = await res.json() as { agents: AgentDirectoryEntry[] }\n return data.agents\n }\n\n async searchDirectory(opts: DirectorySearchOptions): Promise<AgentDirectorySearchEntry[]> {\n const base = this.config.baseUrl\n const mailboxToken = this.config.mailboxToken\n const res = await AampClient.callDiscoveredApi(base, {\n action: 'aamp.directory.search',\n authToken: mailboxToken,\n query: {\n q: opts.query,\n scope: opts.scope,\n includeSelf: opts.includeSelf,\n limit: opts.limit,\n },\n })\n if (!res.ok) {\n const body = await res.text().catch(() => '')\n throw new Error(`Directory search failed: ${res.status} ${body || res.statusText}`)\n }\n const data = await res.json() as { agents: AgentDirectorySearchEntry[] }\n return data.agents\n }\n\n async getThreadHistory(taskId: string, opts: GetThreadHistoryOptions = {}): Promise<TaskThreadHistory> {\n const base = this.config.baseUrl\n const mailboxToken = this.config.mailboxToken\n const res = await AampClient.callDiscoveredApi(base, {\n action: 'aamp.mailbox.thread',\n authToken: mailboxToken,\n query: {\n taskId,\n includeStreamOpened: opts.includeStreamOpened,\n },\n })\n if (!res.ok) {\n const body = await res.text().catch(() => '')\n throw new Error(`Thread history fetch failed: ${res.status} ${body || res.statusText}`)\n }\n const data = await res.json() as TaskThreadHistory\n return {\n taskId: data.taskId,\n events: Array.isArray(data.events) ? data.events : [],\n }\n }\n\n async hydrateTaskDispatch(task: TaskDispatch): Promise<HydratedTaskDispatch> {\n const history = await this.getThreadHistory(task.taskId)\n const priorEvents = history.events.filter((event: AampThreadEvent) => event.messageId !== task.messageId)\n return {\n ...task,\n threadHistory: priorEvents,\n threadContextText: renderThreadHistoryForAgent(priorEvents),\n }\n }\n\n private async resolveStreamCapability(): Promise<NonNullable<NonNullable<AampDiscoveryDocument['capabilities']>['stream']>> {\n const discovery = await AampClient.discoverAampService(this.config.baseUrl)\n const stream = discovery.capabilities?.stream\n if (!stream?.transport) {\n throw new Error('AAMP stream capability is not available on this service')\n }\n return stream\n }\n\n async createStream(opts: CreateStreamOptions): Promise<CreateStreamResult> {\n const stream = await this.resolveStreamCapability()\n const res = await AampClient.callDiscoveredApi(this.config.baseUrl, {\n action: stream.createAction ?? 'aamp.stream.create',\n method: 'POST',\n authToken: this.config.mailboxToken,\n body: opts,\n })\n if (!res.ok) {\n const body = await res.text().catch(() => '')\n throw new Error(`AAMP stream create failed: ${res.status} ${body || res.statusText}`)\n }\n return res.json() as Promise<CreateStreamResult>\n }\n\n private enqueueTaskDispatch(task: TaskDispatch): void {\n this.pendingTaskDispatches.push(task)\n this.drainTaskDispatchQueue()\n }\n\n private drainTaskDispatchQueue(): void {\n while (\n this.activeTaskDispatchCount < this.taskDispatchConcurrency\n && this.pendingTaskDispatches.length > 0\n ) {\n const nextTask = this.pendingTaskDispatches.shift()\n if (!nextTask) return\n\n this.activeTaskDispatchCount += 1\n void this.runTaskDispatch(nextTask)\n }\n }\n\n private async runTaskDispatch(task: TaskDispatch): Promise<void> {\n try {\n await this.emitAsync('task.dispatch', task)\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n this.emit('error', error)\n } finally {\n this.activeTaskDispatchCount = Math.max(0, this.activeTaskDispatchCount - 1)\n this.drainTaskDispatchQueue()\n }\n }\n\n private getStreamAppendQueue(streamId: string): {\n running: boolean\n operations: StreamAppendOperation[]\n } {\n let queue = this.streamAppendQueues.get(streamId)\n if (!queue) {\n queue = { running: false, operations: [] }\n this.streamAppendQueues.set(streamId, queue)\n }\n return queue\n }\n\n private async dispatchStreamAppend(opts: {\n streamId: string\n type: AampStreamEvent['type']\n payload: Record<string, unknown>\n }): Promise<AampStreamEvent> {\n const stream = await this.resolveStreamCapability()\n const res = await AampClient.callDiscoveredApi(this.config.baseUrl, {\n action: stream.appendAction ?? 'aamp.stream.append',\n method: 'POST',\n authToken: this.config.mailboxToken,\n body: opts,\n })\n if (!res.ok) {\n const body = await res.text().catch(() => '')\n throw new Error(`AAMP stream append failed: ${res.status} ${body || res.statusText}`)\n }\n return res.json() as Promise<AampStreamEvent>\n }\n\n private enqueueStreamAppend(\n streamId: string,\n operation: StreamAppendOperation,\n ): void {\n const queue = this.getStreamAppendQueue(streamId)\n queue.operations.push(operation)\n void this.drainStreamAppendQueue(streamId)\n }\n\n private async drainStreamAppendQueue(streamId: string): Promise<void> {\n const queue = this.streamAppendQueues.get(streamId)\n if (!queue || queue.running) return\n\n queue.running = true\n try {\n while (queue.operations.length) {\n const operation = queue.operations.shift()\n if (!operation) continue\n\n if (operation.kind === 'text-delta-batch') {\n try {\n const event = await this.dispatchStreamAppend({\n streamId,\n type: 'text.delta',\n payload: {\n ...operation.payload,\n text: operation.text,\n },\n })\n for (const resolve of operation.resolvers) resolve(event)\n } catch (error) {\n for (const reject of operation.rejecters) reject(error)\n }\n continue\n }\n\n try {\n const event = await this.dispatchStreamAppend(operation.opts)\n operation.resolve(event)\n } catch (error) {\n operation.reject(error)\n }\n }\n } finally {\n queue.running = false\n if (queue.operations.length === 0) {\n this.streamAppendQueues.delete(streamId)\n }\n }\n }\n\n private async flushStreamAppendQueue(streamId: string): Promise<void> {\n while (true) {\n const queue = this.streamAppendQueues.get(streamId)\n if (!queue) return\n if (!queue.running && queue.operations.length === 0) {\n this.streamAppendQueues.delete(streamId)\n return\n }\n await new Promise((resolve) => setTimeout(resolve, 0))\n }\n }\n\n async appendStreamEvent(opts: {\n streamId: string\n type: AampStreamEvent['type']\n payload: Record<string, unknown>\n }): Promise<AampStreamEvent> {\n if (opts.type === 'text.delta' && typeof opts.payload.text === 'string') {\n return await new Promise<AampStreamEvent>((resolve, reject) => {\n const queue = this.getStreamAppendQueue(opts.streamId)\n const lastOperation = queue.operations.at(-1)\n if (lastOperation?.kind === 'text-delta-batch') {\n lastOperation.text += String(opts.payload.text ?? '')\n lastOperation.resolvers.push(resolve)\n lastOperation.rejecters.push(reject)\n return\n }\n\n this.enqueueStreamAppend(opts.streamId, {\n kind: 'text-delta-batch',\n text: String(opts.payload.text ?? ''),\n payload: {\n ...opts.payload,\n },\n resolvers: [resolve],\n rejecters: [reject],\n })\n })\n }\n\n return await new Promise<AampStreamEvent>((resolve, reject) => {\n this.enqueueStreamAppend(opts.streamId, {\n kind: 'single-event',\n opts,\n resolve,\n reject,\n })\n })\n }\n\n async closeStream(opts: CloseStreamOptions): Promise<TaskStreamState> {\n await this.flushStreamAppendQueue(opts.streamId)\n const stream = await this.resolveStreamCapability()\n const res = await AampClient.callDiscoveredApi(this.config.baseUrl, {\n action: stream.closeAction ?? 'aamp.stream.close',\n method: 'POST',\n authToken: this.config.mailboxToken,\n body: opts,\n })\n if (!res.ok) {\n const body = await res.text().catch(() => '')\n throw new Error(`AAMP stream close failed: ${res.status} ${body || res.statusText}`)\n }\n return res.json() as Promise<TaskStreamState>\n }\n\n async getTaskStream(opts: GetTaskStreamOptions): Promise<TaskStreamState | null> {\n const stream = await this.resolveStreamCapability()\n const res = await AampClient.callDiscoveredApi(this.config.baseUrl, {\n action: stream.getAction ?? 'aamp.stream.get',\n authToken: this.config.mailboxToken,\n query: {\n ...(opts.taskId ? { taskId: opts.taskId } : {}),\n ...(opts.streamId ? { streamId: opts.streamId } : {}),\n },\n })\n if (res.status === 404) return null\n if (!res.ok) {\n const body = await res.text().catch(() => '')\n throw new Error(`AAMP stream get failed: ${res.status} ${body || res.statusText}`)\n }\n return res.json() as Promise<TaskStreamState>\n }\n\n async subscribeStream(\n streamId: string,\n handlers: {\n onEvent: (event: AampStreamEvent) => void\n onError?: (err: Error) => void\n onOpen?: () => void\n },\n opts: { lastEventId?: string; signal?: AbortSignal } = {},\n ): Promise<StreamSubscription> {\n const stream = await this.resolveStreamCapability()\n const template = stream.subscribeUrlTemplate\n if (!template) throw new Error('AAMP stream subscribeUrlTemplate is missing')\n\n const url = new URL(template.replace('{streamId}', encodeURIComponent(streamId)), this.config.baseUrl)\n if (opts.lastEventId) {\n url.searchParams.set('lastEventId', opts.lastEventId)\n }\n\n const controller = new AbortController()\n if (opts.signal) {\n opts.signal.addEventListener('abort', () => controller.abort(), { once: true })\n }\n\n const res = await fetch(url, {\n headers: {\n Authorization: `Basic ${this.config.mailboxToken}`,\n Accept: 'text/event-stream',\n },\n signal: controller.signal,\n })\n if (!res.ok || !res.body) {\n throw new Error(`AAMP stream subscribe failed: ${res.status} ${res.statusText}`)\n }\n\n handlers.onOpen?.()\n const reader = res.body.getReader()\n const decoder = new TextDecoder()\n let buffer = ''\n let currentEvent = 'message'\n let currentId = ''\n let currentData: string[] = []\n\n const flush = () => {\n if (!currentData.length) return\n try {\n const parsed = JSON.parse(currentData.join('\\n')) as AampStreamEvent\n handlers.onEvent({\n ...parsed,\n ...(currentId ? { id: currentId } : {}),\n type: parsed.type ?? currentEvent as AampStreamEvent['type'],\n })\n } catch (err) {\n handlers.onError?.(err as Error)\n } finally {\n currentEvent = 'message'\n currentId = ''\n currentData = []\n }\n }\n\n void (async () => {\n try {\n while (true) {\n const { value, done } = await reader.read()\n if (done) break\n buffer += decoder.decode(value, { stream: true })\n\n let index = buffer.indexOf('\\n\\n')\n while (index >= 0) {\n const frame = buffer.slice(0, index)\n buffer = buffer.slice(index + 2)\n for (const rawLine of frame.split('\\n')) {\n const line = rawLine.replace(/\\r$/, '')\n if (!line || line.startsWith(':')) continue\n if (line.startsWith('event:')) {\n currentEvent = line.slice(6).trim()\n } else if (line.startsWith('id:')) {\n currentId = line.slice(3).trim()\n } else if (line.startsWith('data:')) {\n currentData.push(line.slice(5).trimStart())\n }\n }\n flush()\n index = buffer.indexOf('\\n\\n')\n }\n }\n } catch (err) {\n if (!controller.signal.aborted) {\n handlers.onError?.(err as Error)\n }\n } finally {\n buffer += decoder.decode()\n controller.abort()\n }\n })()\n\n return {\n close() {\n controller.abort()\n },\n }\n }\n\n /**\n * Download a blob (attachment) by its JMAP blobId.\n * Use this to retrieve attachment content from received TaskDispatch or TaskResult messages.\n * Returns the raw binary content as a Buffer.\n */\n async downloadBlob(blobId: string, filename?: string): Promise<Buffer> {\n return this.jmapClient.downloadBlob(blobId, filename)\n }\n\n /**\n * Reconcile recent mailbox contents via JMAP HTTP to catch messages missed by\n * a flaky WebSocket path. Safe to call periodically; duplicate processing is\n * suppressed by the JMAP push client.\n */\n async reconcileRecentEmails(limit?: number, opts?: { includeHistorical?: boolean }): Promise<number> {\n return this.jmapClient.reconcileRecentEmails(limit, opts)\n }\n\n /**\n * Verify SMTP connectivity\n */\n async verifySmtp(): Promise<boolean> {\n return this.smtpSender.verify()\n }\n\n get email(): string {\n return this.config.email\n }\n}\n", "/**\n * @aamp/openclaw-plugin\n *\n * OpenClaw plugin that gives the agent an AAMP mailbox identity and lets it\n * receive, process, and reply to AAMP tasks \u2014 entirely through standard email.\n *\n * How it works:\n * 1. Plugin resolves or auto-registers an AAMP mailbox identity on startup.\n * 2. Credentials are cached to a local file so the same mailbox is reused\n * across gateway restarts (no re-registration needed).\n * 3. Background JMAP WebSocket Push receives incoming task.dispatch emails.\n * 4. Incoming tasks are stored in an in-memory pending-task queue.\n * 5. before_prompt_build injects the oldest pending task into the LLM's\n * system context so the agent sees it and acts without user prompting.\n * 6. The agent calls aamp_send_result or aamp_send_help to reply.\n *\n * OpenClaw config (openclaw.json):\n *\n * \"plugins\": {\n * \"entries\": {\n * \"aamp\": {\n * \"enabled\": true,\n * \"config\": {\n * \"aampHost\": \"https://meshmail.ai\",\n * \"slug\": \"openclaw-agent\",\n * \"credentialsFile\": \"/absolute/path/to/.aamp-credentials.json\"\n * }\n * }\n * }\n * }\n *\n * Install:\n * openclaw plugins install ./packages/openclaw-plugin\n */\n\nimport { AampClient } from 'aamp-sdk'\nimport type {\n AampThreadEvent,\n TaskDispatch,\n TaskCancel,\n TaskResult,\n TaskHelp,\n TaskPriority,\n AampAttachment,\n ReceivedAttachment,\n} from 'aamp-sdk'\nimport { readFileSync } from 'node:fs'\nimport {\n defaultCredentialsPath,\n defaultTaskStatePath,\n ensureDir,\n loadCachedIdentity,\n loadTaskState,\n readBinaryFile,\n saveCachedIdentity,\n saveTaskState,\n writeBinaryFile,\n type Identity,\n} from './file-store.js'\n\n// \u2500\u2500\u2500 Shared runtime state (single instance per plugin lifetime) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ninterface PendingTask {\n taskId: string\n from: string\n title: string\n bodyText: string\n dispatchContext?: Record<string, string>\n threadHistory: AampThreadEvent[]\n threadContextText: string\n priority: TaskPriority\n expiresAt?: string\n contextLinks: string[]\n messageId: string\n receivedAt: string // ISO-8601\n awaitingHelpReply?: boolean\n}\n\ninterface PluginConfig {\n /** e.g. \"meshmail.ai\" \u2014 all URLs are derived from this */\n aampHost: string\n taskDispatchConcurrency?: number\n slug?: string\n summary?: string\n cardText?: string\n cardFile?: string\n /** Absolute path to cache AAMP credentials. Default: ~/.openclaw/extensions/aamp-openclaw-plugin/.credentials.json */\n credentialsFile?: string\n senderPolicies?: SenderPolicy[]\n}\n\ninterface SenderPolicy {\n sender: string\n dispatchContextRules?: Record<string, string[]>\n}\n\nexport function matchSenderPolicy(\n task: TaskDispatch,\n senderPolicies: SenderPolicy[] | undefined,\n): { allowed: boolean; reason?: string } {\n if (!senderPolicies?.length) return { allowed: true }\n\n const sender = task.from.toLowerCase()\n const policy = senderPolicies.find((item) => item.sender.trim().toLowerCase() === sender)\n if (!policy) {\n return { allowed: false, reason: `sender ${task.from} is not allowed by senderPolicies` }\n }\n\n const rules = policy.dispatchContextRules\n if (!rules || Object.keys(rules).length === 0) {\n return { allowed: true }\n }\n\n const context = task.dispatchContext ?? {}\n const effectiveRules = Object.entries(rules)\n .map(([key, allowedValues]) => [\n key,\n (allowedValues ?? []).map((value) => value.trim()).filter(Boolean),\n ] as const)\n .filter(([, allowedValues]) => allowedValues.length > 0)\n\n if (effectiveRules.length === 0) {\n return { allowed: true }\n }\n\n for (const [key, allowedValues] of effectiveRules) {\n const contextValue = context[key]\n if (!contextValue) {\n return { allowed: false, reason: `dispatchContext missing required key \"${key}\"` }\n }\n if (!allowedValues.includes(contextValue)) {\n return { allowed: false, reason: `dispatchContext ${key}=${contextValue} is not allowed` }\n }\n }\n\n return { allowed: true }\n}\n\ntype StructuredResultFieldInput = {\n fieldKey: string\n fieldTypeKey: string\n fieldAlias?: string\n value?: unknown\n index?: string\n attachmentFilenames?: string[]\n}\n\n/** Normalise aampHost to a base URL with scheme and no trailing slash */\nexport function baseUrl(aampHost: string): string {\n if (aampHost.startsWith('http://') || aampHost.startsWith('https://')) {\n return aampHost.replace(/\\/$/, '')\n }\n return `https://${aampHost}`\n}\n\nconst pendingTasks = new Map<string, PendingTask>()\nconst activeTaskStreams = new Map<string, string>()\nconst terminalTaskIds = new Set<string>(loadTaskState(defaultTaskStatePath()).terminalTaskIds ?? [])\nconst AAMP_SESSION_PREFIX = 'aamp:'\nconst DEFAULT_OPENCLAW_AGENT_ID = 'main'\nconst OPENCLAW_AGENT_SESSION_PREFIX = 'agent:'\nconst VALID_OPENCLAW_AGENT_ID_RE = /^[a-z0-9][a-z0-9_-]{0,63}$/i\nconst INVALID_OPENCLAW_AGENT_ID_RE = /[^a-z0-9_-]+/g\nconst LEADING_DASH_RE = /^-+/\nconst TRAILING_DASH_RE = /-+$/\n// Tracks sub-tasks dispatched TO other agents \u2014 waiting for their result/help replies\nconst dispatchedSubtasks = new Map<string, { to: string; title: string; dispatchedAt: string; parentTaskId?: string }>()\n// Tracks notification keys that have been shown to LLM (auto-cleaned on next prompt build)\nconst shownNotifications = new Set<string>()\n// Pending synchronous dispatch waiters \u2014 resolve callback keyed by sub-task ID.\n// When aamp_dispatch_task sends a sub-task, it parks a Promise here and waits.\n// When task.result/help arrives for that sub-task ID, the waiter is resolved\n// directly, keeping the LLM awake with full context (no heartbeat needed).\nconst waitingDispatches = new Map<string, (reply: { type: 'result' | 'help'; data: unknown }) => void>()\nlet aampClient: AampClient | null = null\nlet agentEmail = ''\nlet lastConnectionError = ''\nlet lastDisconnectReason = ''\nlet lastTransportMode: 'disconnected' | 'websocket' | 'polling' = 'disconnected'\nlet lastLoggedTransportMode: 'disconnected' | 'websocket' | 'polling' = 'disconnected'\nlet reconcileTimer: NodeJS.Timeout | null = null\nlet transportMonitorTimer: NodeJS.Timeout | null = null\nlet historicalReconcileCompleted = false\n// Channel runtime \u2014 captured from channel adapter's startAccount for instant dispatch.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet channelRuntime: any = null\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet channelCfg: any = null\n\nasync function ensureTaskStream(task: PendingTask): Promise<string | null> {\n if (!aampClient?.isConnected()) return null\n const existing = activeTaskStreams.get(task.taskId)\n if (existing) return existing\n\n const created = await aampClient.createStream({\n taskId: task.taskId,\n peerEmail: task.from,\n })\n await aampClient.sendStreamOpened({\n to: task.from,\n taskId: task.taskId,\n streamId: created.streamId,\n inReplyTo: task.messageId || undefined,\n })\n await aampClient.appendStreamEvent({\n streamId: created.streamId,\n type: 'status',\n payload: { state: 'running', label: 'Task queued in OpenClaw' },\n })\n activeTaskStreams.set(task.taskId, created.streamId)\n return created.streamId\n}\n\nasync function appendTaskStream(taskId: string, type: 'text.delta' | 'progress' | 'status' | 'artifact' | 'error' | 'done', payload: Record<string, unknown>): Promise<void> {\n if (!aampClient?.isConnected()) return\n const streamId = activeTaskStreams.get(taskId)\n if (!streamId) return\n await aampClient.appendStreamEvent({\n streamId,\n type,\n payload,\n })\n}\n\nasync function closeTaskStream(taskId: string, payload?: Record<string, unknown>): Promise<void> {\n if (!aampClient?.isConnected()) return\n const streamId = activeTaskStreams.get(taskId)\n if (!streamId) return\n activeTaskStreams.delete(taskId)\n await aampClient.closeStream({\n streamId,\n payload,\n })\n}\n\nfunction logTransportState(\n api: { logger: { info: (msg: string) => void; warn: (msg: string) => void } },\n mode: 'websocket' | 'polling',\n email: string,\n previousMode: 'disconnected' | 'websocket' | 'polling',\n): void {\n if (mode === previousMode) return\n\n if (mode === 'polling') {\n api.logger.info(`[AAMP] Connected (polling fallback active) \u2014 listening as ${email}`)\n return\n }\n\n if (previousMode === 'polling') {\n api.logger.info(`[AAMP] WebSocket restored \u2014 listening as ${email}`)\n return\n }\n\n api.logger.info(`[AAMP] Connected \u2014 listening as ${email}`)\n}\n\nfunction isSyntheticPendingKey(taskKey: string): boolean {\n return taskKey.startsWith('result:') || taskKey.startsWith('help:')\n}\n\nfunction isTaskAwaitingHelpReply(task: PendingTask): boolean {\n return task.awaitingHelpReply === true\n}\n\nfunction isConversationalTask(task: PendingTask): boolean {\n const source = task.dispatchContext?.source?.trim().toLowerCase()\n return source === 'feishu' || source === 'wechat'\n}\n\nfunction firstDispatchContextValue(\n context: Record<string, string> | undefined,\n keys: string[],\n): string | undefined {\n if (!context) return undefined\n for (const key of keys) {\n const value = context[key]?.trim()\n if (value) return value\n }\n return undefined\n}\n\nfunction threadAlreadyTerminal(events: AampThreadEvent[] | undefined): boolean {\n return (events ?? []).some((event) =>\n event.intent === 'task.result' || event.intent === 'task.cancel',\n )\n}\n\nfunction isActionablePendingTask(taskKey: string, task: PendingTask): boolean {\n return !isSyntheticPendingKey(taskKey) && !isTaskAwaitingHelpReply(task)\n}\n\nfunction normalizeOpenClawAgentId(value: unknown): string {\n const trimmed = typeof value === 'string' ? value.trim() : ''\n if (!trimmed) return DEFAULT_OPENCLAW_AGENT_ID\n if (VALID_OPENCLAW_AGENT_ID_RE.test(trimmed)) return trimmed.toLowerCase()\n return trimmed\n .toLowerCase()\n .replace(INVALID_OPENCLAW_AGENT_ID_RE, '-')\n .replace(LEADING_DASH_RE, '')\n .replace(TRAILING_DASH_RE, '')\n .slice(0, 64) || DEFAULT_OPENCLAW_AGENT_ID\n}\n\nfunction resolveDefaultOpenClawAgentId(config: unknown): string {\n const agents = (config as { agents?: { list?: Array<{ id?: unknown; default?: unknown }> } } | null | undefined)?.agents?.list\n if (!Array.isArray(agents) || agents.length === 0) return DEFAULT_OPENCLAW_AGENT_ID\n\n const defaults = agents.filter((agent) => agent?.default)\n return normalizeOpenClawAgentId((defaults[0] ?? agents[0])?.id)\n}\n\nfunction stripOpenClawAgentScope(sessionKey: string): string {\n const trimmed = sessionKey.trim()\n if (!trimmed.toLowerCase().startsWith(OPENCLAW_AGENT_SESSION_PREFIX)) return trimmed\n\n const parts = trimmed.split(':')\n if (parts.length < 3 || parts[0]?.toLowerCase() !== 'agent') return trimmed\n return parts.slice(2).join(':')\n}\n\nfunction isAampSessionKey(sessionKey: unknown): sessionKey is string {\n return typeof sessionKey === 'string'\n && stripOpenClawAgentScope(sessionKey).toLowerCase().startsWith(AAMP_SESSION_PREFIX)\n}\n\nfunction buildOpenClawMainSessionKey(mainKey: string, config: unknown): string {\n const trimmed = mainKey.trim()\n if (!trimmed) return `${OPENCLAW_AGENT_SESSION_PREFIX}${resolveDefaultOpenClawAgentId(config)}:main`\n if (trimmed.toLowerCase().startsWith(OPENCLAW_AGENT_SESSION_PREFIX)) return trimmed\n return `${OPENCLAW_AGENT_SESSION_PREFIX}${resolveDefaultOpenClawAgentId(config)}:${trimmed}`\n}\n\nfunction buildAampConversationSessionKey(value: string, config: unknown): string {\n return buildOpenClawMainSessionKey(`${AAMP_SESSION_PREFIX}default:${value}`, config)\n}\n\nfunction buildAampStickySessionKey(\n sessionKey: string | undefined,\n config: unknown,\n): string | undefined {\n const stickyValue = sessionKey?.trim()\n if (!stickyValue) return undefined\n return buildAampConversationSessionKey(`session:${stickyValue}`, config)\n}\n\nfunction buildAampTaskSessionKey(taskId: string, config: unknown): string {\n return buildAampConversationSessionKey(`task:${taskId}`, config)\n}\n\nfunction buildAampWakeSessionKey(kind: string, id: string): string {\n return `${AAMP_SESSION_PREFIX}wake:${kind}:${id}`\n}\n\nfunction buildSessionKeyForPendingTask(task: PendingTask, config: unknown): string {\n return buildAampStickySessionKey(task.sessionKey, config)\n ?? buildAampTaskSessionKey(task.taskId, config)\n}\n\nfunction buildWakeSessionKeyForPendingTask(task: PendingTask, config: unknown): string {\n return buildAampStickySessionKey(task.sessionKey, config)\n ?? buildAampWakeSessionKey('task', task.taskId)\n}\n\nfunction findPendingEntryForSession(\n sessionKey: unknown,\n config: unknown,\n): [string, PendingTask] | undefined {\n if (typeof sessionKey !== 'string' || !isAampSessionKey(sessionKey)) return undefined\n\n const requested = buildOpenClawMainSessionKey(stripOpenClawAgentScope(sessionKey), config)\n const entries = [...pendingTasks.entries()]\n .filter(([key, task]) => isActionablePendingTask(key, task))\n .filter(([, task]) => buildSessionKeyForPendingTask(task, config) === requested)\n .sort((a, b) => {\n const rankDiff = priorityRank(a[1].priority) - priorityRank(b[1].priority)\n if (rankDiff !== 0) return rankDiff\n return new Date(a[1].receivedAt).getTime() - new Date(b[1].receivedAt).getTime()\n })\n\n return entries[0]\n}\n\nfunction resolvePendingKeyFromSessionKey(sessionKey: unknown): string | undefined {\n if (typeof sessionKey !== 'string') return undefined\n\n const normalized = stripOpenClawAgentScope(sessionKey).trim()\n if (!normalized) return undefined\n\n const parts = normalized.split(':')\n if (parts[0]?.toLowerCase() !== 'aamp') return undefined\n\n if (parts[1]?.toLowerCase() === 'wake') {\n const kind = parts[2]?.toLowerCase()\n const id = parts.slice(3).join(':').trim()\n if (!id) return undefined\n if (kind === 'task') return id\n if (kind === 'result' || kind === 'help') return `${kind}:${id}`\n return undefined\n }\n\n if (parts[1]?.toLowerCase() === 'default') {\n const kind = parts[2]?.toLowerCase()\n const id = parts.slice(3).join(':').trim()\n if (!id) return undefined\n if (kind === 'task') return id\n if (kind === 'result' || kind === 'help') return `${kind}:${id}`\n }\n\n return undefined\n}\n\nfunction saveTerminalTaskIds(): void {\n saveTaskState({ terminalTaskIds: [...terminalTaskIds] }, defaultTaskStatePath())\n}\n\nfunction rememberTerminalTask(taskId: string): void {\n terminalTaskIds.add(taskId)\n saveTerminalTaskIds()\n}\n\nfunction priorityRank(priority: TaskPriority): number {\n switch (priority) {\n case 'urgent':\n return 0\n case 'high':\n return 1\n default:\n return 2\n }\n}\n\nfunction hasExpired(task: Pick<PendingTask, 'expiresAt'>): boolean {\n if (task.expiresAt) {\n const expiresAtMs = new Date(task.expiresAt).getTime()\n if (Number.isFinite(expiresAtMs) && Date.now() >= expiresAtMs) return true\n }\n return false\n}\n\nfunction isTransientTransportError(message: string): boolean {\n return [\n 'ECONNRESET',\n 'ETIMEDOUT',\n 'ECONNREFUSED',\n 'EPIPE',\n 'UND_ERR_SOCKET',\n 'UND_ERR_CONNECT_TIMEOUT',\n 'fetch failed',\n ].some((needle) => message.includes(needle))\n}\n\nfunction nextPendingEntry(): [string, PendingTask] | undefined {\n const entries = [...pendingTasks.entries()]\n const notifications = entries.filter(([key]) => key.startsWith('result:') || key.startsWith('help:'))\n if (notifications.length > 0) {\n return notifications.sort((a, b) => new Date(a[1].receivedAt).getTime() - new Date(b[1].receivedAt).getTime())[0]\n }\n\n return entries\n .filter(([key, task]) => isActionablePendingTask(key, task))\n .sort((a, b) => {\n const rankDiff = priorityRank(a[1].priority) - priorityRank(b[1].priority)\n if (rankDiff !== 0) return rankDiff\n return new Date(a[1].receivedAt).getTime() - new Date(b[1].receivedAt).getTime()\n })[0]\n}\n\nexport function queuePendingTask(\n task: TaskDispatch & { threadHistory?: AampThreadEvent[]; threadContextText?: string },\n): boolean {\n if (terminalTaskIds.has(task.taskId)) {\n return false\n }\n\n pendingTasks.set(task.taskId, {\n taskId: task.taskId,\n from: task.from,\n title: task.title,\n bodyText: task.bodyText ?? '',\n dispatchContext: task.dispatchContext,\n threadHistory: task.threadHistory ?? [],\n threadContextText: task.threadContextText ?? '',\n priority: task.priority ?? 'normal',\n ...(task.expiresAt ? { expiresAt: task.expiresAt } : {}),\n contextLinks: task.contextLinks ?? [],\n messageId: task.messageId ?? '',\n receivedAt: new Date().toISOString(),\n })\n\n if (hasExpired(pendingTasks.get(task.taskId)!)) {\n pendingTasks.delete(task.taskId)\n rememberTerminalTask(task.taskId)\n return false\n }\n\n return true\n}\n\n// \u2500\u2500\u2500 Identity helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ninterface Identity {\n email: string\n mailboxToken?: string\n smtpPassword: string\n}\n\n/**\n * Register a new AAMP node via the management service.\n *\n * Always creates a NEW mailbox (always returns 201). The slug is just a\n * human-readable prefix; a random hex suffix makes the email unique.\n * Callers should only call this once and persist the returned credentials.\n */\nexport async function registerNode(cfg: PluginConfig): Promise<Identity> {\n const slug = (cfg.slug ?? 'openclaw-agent')\n .toLowerCase()\n .replace(/[\\s_]+/g, '-')\n .replace(/[^a-z0-9-]/g, '')\n const credData = await AampClient.registerMailbox({\n aampHost: cfg.aampHost,\n slug,\n description: 'OpenClaw AAMP agent node',\n })\n\n return {\n email: credData.email,\n mailboxToken: credData.mailboxToken,\n smtpPassword: credData.smtpPassword,\n }\n}\n\n/**\n * Resolve this agent's identity:\n * 1. Return cached credentials from disk if available.\n * 2. Otherwise register a new node and cache the result.\n */\nexport async function resolveIdentity(cfg: PluginConfig): Promise<Identity> {\n const cached = loadCachedIdentity(cfg.credentialsFile ?? defaultCredentialsPath())\n if (cached) return cached\n\n const identity = await registerNode(cfg)\n saveCachedIdentity(identity, cfg.credentialsFile ?? defaultCredentialsPath())\n return identity\n}\n\n// \u2500\u2500\u2500 Plugin definition \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport default {\n id: 'aamp-openclaw-plugin',\n name: 'AAMP Agent Mail Protocol',\n\n configSchema: {\n type: 'object',\n properties: {\n aampHost: {\n type: 'string',\n description: 'AAMP service host, e.g. https://meshmail.ai',\n },\n slug: {\n type: 'string',\n default: 'openclaw-agent',\n description: 'Agent name prefix used in the mailbox address',\n },\n summary: {\n type: 'string',\n description: 'Directory summary shown when other agents search for this agent.',\n },\n cardText: {\n type: 'string',\n description: 'Inline card text used for automatic card.response replies.',\n },\n cardFile: {\n type: 'string',\n description: 'Absolute path to a card text file. Used when cardText is not set.',\n },\n credentialsFile: {\n type: 'string',\n description:\n 'Absolute path to cache AAMP credentials between gateway restarts. ' +\n 'Default: ~/.openclaw/extensions/aamp-openclaw-plugin/.credentials.json. ' +\n 'Delete this file to force re-registration with a new mailbox.',\n },\n senderPolicies: {\n type: 'array',\n description:\n 'Per-sender authorization policies. Each sender can optionally require specific ' +\n 'X-AAMP-Dispatch-Context key/value pairs before a task is accepted.',\n items: {\n type: 'object',\n required: ['sender'],\n properties: {\n sender: {\n type: 'string',\n description: 'Dispatch sender email address (case-insensitive exact match).',\n },\n dispatchContextRules: {\n type: 'object',\n description:\n 'Optional exact-match rules over X-AAMP-Dispatch-Context. ' +\n 'All listed keys must be present and their values must match one of the configured entries.',\n additionalProperties: {\n type: 'array',\n items: { type: 'string' },\n },\n },\n },\n },\n },\n },\n },\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n register(api: any) {\n // OpenClaw channel plugins keep runtime config under channels.<channelId>.\n // Fall back to the legacy plugins.entries config so older installs still work.\n const cfg = ((api.config?.channels?.aamp ?? api.pluginConfig ?? {}) as PluginConfig)\n\n // \u2500\u2500 Register lightweight channel adapter to capture channelRuntime \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // We register as a channel SOLELY to get access to channelRuntime, which provides\n // dispatchReplyWithBufferedBlockDispatcher for instant LLM dispatch (bypassing\n // heartbeat's global running-mutex + requests-in-flight ~60s delay).\n // JMAP connection is managed by registerService, NOT startAccount.\n api.registerChannel({\n id: 'aamp',\n meta: {\n label: 'AAMP',\n selectionLabel: 'AAMP',\n docsPath: '/channels/aamp',\n blurb: 'AAMP mailbox channel for receiving and replying to tasks over email.',\n },\n capabilities: { chatTypes: ['dm'] },\n config: {\n listAccountIds: () => cfg.aampHost ? ['default'] : [],\n resolveAccount: () => ({ aampHost: cfg.aampHost }),\n isEnabled: () => !!cfg.aampHost,\n isConfigured: () => !!loadCachedIdentity(cfg.credentialsFile ?? defaultCredentialsPath()),\n },\n gateway: {\n startAccount: async (ctx: { channelRuntime?: unknown; cfg?: unknown; abortSignal?: AbortSignal }) => {\n // Capture channelRuntime for use by sub-task notification dispatch\n channelRuntime = ctx.channelRuntime ?? null\n channelCfg = ctx.cfg ?? null\n api.logger.info(`[AAMP] Channel adapter started \u2014 channelRuntime ${channelRuntime ? 'available' : 'NOT available'}`)\n\n // Keep alive until abort \u2014 JMAP connection is managed by registerService\n await new Promise<void>((resolve) => {\n ctx.abortSignal?.addEventListener('abort', () => resolve())\n })\n channelRuntime = null\n channelCfg = null\n },\n stopAccount: async () => {\n channelRuntime = null\n channelCfg = null\n },\n },\n })\n\n function triggerHeartbeatWake(sessionKey: string, label: string): void {\n try {\n api.runtime.system.requestHeartbeatNow({ reason: 'wake', sessionKey })\n api.logger.info(`[AAMP] Heartbeat triggered for ${label} via session ${sessionKey}`)\n } catch (err) {\n api.logger.warn(`[AAMP] Could not trigger heartbeat for ${label}: ${(err as Error).message}`)\n }\n }\n\n function getConfiguredCardText(): string | undefined {\n const inline = cfg.cardText?.trim()\n if (inline) return inline\n\n const file = cfg.cardFile?.trim()\n if (!file) return undefined\n\n const fromFile = readFileSync(file, 'utf-8').trim()\n return fromFile || undefined\n }\n\n async function syncDirectoryProfile(): Promise<void> {\n if (!aampClient) return\n\n const summary = cfg.summary?.trim()\n const cardText = getConfiguredCardText()\n if (!summary && !cardText) return\n\n await aampClient.updateDirectoryProfile({\n ...(summary ? { summary } : {}),\n ...(cardText ? { cardText } : {}),\n })\n\n api.logger.info(`[AAMP] Directory profile synced${cardText ? ' (card text registered)' : ''}`)\n }\n\n function wakeAgentForPendingTask(task: PendingTask): void {\n const fallbackSessionKey = buildWakeSessionKeyForPendingTask(task, api.config)\n const openClawSessionKey = buildSessionKeyForPendingTask(task, api.config)\n const fallback = () => triggerHeartbeatWake(fallbackSessionKey, `task ${task.taskId}`)\n const dispatcher = channelRuntime?.reply?.dispatchReplyWithBufferedBlockDispatcher\n\n api.logger.info(\n `[AAMP] Wake requested for task ${task.taskId} \u2014 channelRuntime=${channelRuntime ? 'yes' : 'no'} channelCfg=${channelCfg ? 'yes' : 'no'} dispatcher=${typeof dispatcher === 'function' ? 'yes' : 'no'} session=${openClawSessionKey} fallbackSession=${fallbackSessionKey}`,\n )\n\n if (!channelRuntime || !channelCfg || typeof dispatcher !== 'function') {\n fallback()\n return\n }\n\n const prompt = [\n '## New AAMP Task',\n '',\n 'A new AAMP task just arrived.',\n 'Use the pending AAMP task in system context as the source of truth and handle it now.',\n 'Reply with aamp_send_result or aamp_send_help before responding.',\n ].join('\\n')\n\n try {\n void Promise.resolve(dispatcher({\n ctx: {\n Body: task.bodyText || task.title,\n BodyForAgent: prompt,\n From: task.from,\n To: agentEmail,\n SessionKey: openClawSessionKey,\n AccountId: 'default',\n ChatType: 'dm',\n Provider: 'aamp',\n Surface: 'aamp',\n OriginatingChannel: 'aamp',\n OriginatingTo: task.from,\n MessageSid: task.messageId || task.taskId,\n Timestamp: Date.now(),\n SenderName: task.from,\n SenderId: task.from,\n CommandAuthorized: true,\n },\n cfg: channelCfg,\n dispatcherOptions: {\n deliver: async () => {},\n onError: (err: unknown) => {\n api.logger.error(`[AAMP] Channel dispatch error for task ${task.taskId}: ${err instanceof Error ? err.message : String(err)}`)\n },\n },\n })).then(() => {\n api.logger.info(`[AAMP] Channel dispatch triggered for task ${task.taskId}`)\n }).catch((err: Error) => {\n api.logger.error(`[AAMP] Channel dispatch failed for task ${task.taskId}: ${err.message}`)\n fallback()\n })\n } catch (err) {\n api.logger.error(`[AAMP] Channel dispatch threw synchronously for task ${task.taskId}: ${(err as Error).message}`)\n fallback()\n }\n }\n\n async function reconcileMailbox(includeHistorical: boolean): Promise<void> {\n if (!aampClient) return\n\n const opts = includeHistorical ? { includeHistorical: true } : undefined\n const count = await aampClient.reconcileRecentEmails(100, opts)\n\n if (includeHistorical && !historicalReconcileCompleted) {\n historicalReconcileCompleted = true\n api.logger.info(`[AAMP] Historical mailbox reconcile complete (${count} email(s) scanned)`)\n }\n }\n\n // \u2500\u2500 Shared connect logic (used by service auto-connect and startup recovery) \u2500\u2500\u2500\u2500\u2500\u2500\n async function doConnect(identity: { email: string; mailboxToken?: string; smtpPassword: string }) {\n if (reconcileTimer) {\n clearInterval(reconcileTimer)\n reconcileTimer = null\n }\n if (transportMonitorTimer) {\n clearInterval(transportMonitorTimer)\n transportMonitorTimer = null\n }\n\n agentEmail = identity.email\n lastConnectionError = ''\n lastDisconnectReason = ''\n lastTransportMode = 'disconnected'\n lastLoggedTransportMode = 'disconnected'\n api.logger.info(`[AAMP] Mailbox identity ready \u2014 ${agentEmail}`)\n\n // All traffic goes through aampHost (port 3000).\n // The management service proxies /jmap/* and /.well-known/jmap \u2192 Stalwart:8080.\n const base = baseUrl(cfg.aampHost)\n\n aampClient = AampClient.fromMailboxIdentity({\n email: identity.email,\n smtpPassword: identity.smtpPassword,\n baseUrl: base,\n taskDispatchConcurrency: cfg.taskDispatchConcurrency,\n // Local/dev: management-service proxy uses plain HTTP, no TLS cert to verify.\n // Production: set to true when using wss:// with valid certs.\n rejectUnauthorized: false,\n })\n\n aampClient.on('task.dispatch', (task: TaskDispatch) => {\n api.logger.info(`[AAMP] \u2190 task.dispatch ${task.taskId} \"${task.title}\" from=${task.from}`)\n\n return (async () => {\n try {\n if (terminalTaskIds.has(task.taskId)) {\n api.logger.info(`[AAMP] Skipping already-terminal task ${task.taskId}`)\n return\n }\n\n // \u2500\u2500 Sender policy / dispatch-context authorization \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const decision = matchSenderPolicy(task, cfg.senderPolicies)\n if (!decision.allowed) {\n api.logger.warn(`[AAMP] \u2717 rejected by senderPolicies: ${task.from} task=${task.taskId} reason=${decision.reason}`)\n void aampClient!.sendResult({\n to: task.from,\n taskId: task.taskId,\n status: 'rejected',\n output: '',\n errorMsg: decision.reason ?? `Sender ${task.from} is not allowed.`,\n }).catch((err: Error) => {\n api.logger.error(`[AAMP] Failed to send rejection for task ${task.taskId}: ${err.message}`)\n })\n return\n }\n\n const hydratedTask = await aampClient!.hydrateTaskDispatch(task).catch((err: Error) => {\n api.logger.warn(`[AAMP] Failed to load thread history for ${task.taskId}: ${err.message}`)\n return {\n ...task,\n threadHistory: [],\n threadContextText: '',\n }\n })\n\n if (threadAlreadyTerminal(hydratedTask.threadHistory)) {\n rememberTerminalTask(task.taskId)\n api.logger.info(`[AAMP] Skipping historical task ${task.taskId} because the thread already reached a terminal state`)\n return\n }\n\n if (!queuePendingTask(hydratedTask)) {\n api.logger.info(`[AAMP] Ignoring already-terminal or expired task ${task.taskId}`)\n return\n }\n\n void ensureTaskStream(pendingTasks.get(task.taskId)!).catch((err: Error) => {\n api.logger.warn(`[AAMP] Failed to open stream for task ${task.taskId}: ${err.message}`)\n })\n\n // Wake the agent immediately after enqueueing the task.\n // In polling fallback mode heartbeat wakes can be delayed, so prefer a direct\n // channel dispatch when channelRuntime is available and only fall back to heartbeat.\n wakeAgentForPendingTask(pendingTasks.get(task.taskId)!)\n } catch (err) {\n api.logger.error(`[AAMP] task.dispatch handler failed for ${task.taskId}: ${(err as Error).message}`)\n if (pendingTasks.has(task.taskId)) {\n triggerHeartbeatWake(buildWakeSessionKeyForPendingTask(pendingTasks.get(task.taskId)!, api.config), `task ${task.taskId}`)\n }\n }\n })()\n })\n\n aampClient.on('task.cancel', (cancel: TaskCancel) => {\n api.logger.info(`[AAMP] \u2190 task.cancel ${cancel.taskId} from=${cancel.from}`)\n const removed = pendingTasks.delete(cancel.taskId)\n pendingTasks.delete(`result:${cancel.taskId}`)\n pendingTasks.delete(`help:${cancel.taskId}`)\n dispatchedSubtasks.delete(cancel.taskId)\n waitingDispatches.delete(cancel.taskId)\n rememberTerminalTask(cancel.taskId)\n void closeTaskStream(cancel.taskId, { reason: 'task.cancel' }).catch(() => {})\n if (removed) {\n api.logger.info(`[AAMP] Cancelled task ${cancel.taskId} \u2014 removed from pending queue`)\n }\n })\n\n // \u2500\u2500 Sub-task result: another agent completed a task we dispatched \u2500\u2500\u2500\u2500\u2500\u2500\n aampClient.on('task.result', (result: TaskResult) => {\n if (result.from.toLowerCase() === agentEmail.toLowerCase()) return\n api.logger.info(`[AAMP] \u2190 task.result ${result.taskId} status=${result.status} from=${result.from}`)\n\n const sub = dispatchedSubtasks.get(result.taskId)\n dispatchedSubtasks.delete(result.taskId)\n\n // \u2500\u2500 Synchronous dispatch: if aamp_dispatch_task is waiting, resolve it directly \u2500\u2500\n const waiter = waitingDispatches.get(result.taskId)\n if (waiter) {\n waitingDispatches.delete(result.taskId)\n api.logger.info(`[AAMP] Resolving sync waiter for sub-task ${result.taskId}`)\n waiter({ type: 'result', data: result })\n return // Don't go through heartbeat/channel \u2014 the LLM is already awake\n }\n\n // Pre-download attachments to local disk so the LLM can reference them\n // by local file path (instead of requiring a separate download tool call).\n const downloadedFiles: Array<{ filename: string; path: string; size: number }> = []\n const downloadPromise = (async () => {\n if (!result.attachments?.length) return\n const dir = '/tmp/aamp-files'\n ensureDir(dir)\n for (const att of result.attachments) {\n try {\n const buffer = await aampClient!.downloadBlob(att.blobId, att.filename)\n const filepath = `${dir}/${att.filename}`\n writeBinaryFile(filepath, buffer)\n downloadedFiles.push({ filename: att.filename, path: filepath, size: buffer.length })\n api.logger.info(`[AAMP] Pre-downloaded: ${att.filename} (${(buffer.length / 1024).toFixed(1)} KB) \u2192 ${filepath}`)\n } catch (dlErr) {\n api.logger.warn(`[AAMP] Pre-download failed for ${att.filename}: ${(dlErr as Error).message}`)\n }\n }\n })()\n\n downloadPromise.then(() => {\n // Build notification with pre-downloaded file paths\n const MAX_OUTPUT_CHARS = 800\n const label = result.status === 'completed' ? 'Sub-task completed' : 'Sub-task rejected'\n const rawOutput = result.output ?? ''\n const truncatedOutput = rawOutput.length > MAX_OUTPUT_CHARS\n ? rawOutput.slice(0, MAX_OUTPUT_CHARS) + `\\n\\n... [truncated, ${rawOutput.length} chars total]`\n : rawOutput\n\n let attachmentInfo = ''\n if (downloadedFiles.length > 0) {\n attachmentInfo = `\\n\\nAttachments (pre-downloaded to local disk):\\n${downloadedFiles.map(f =>\n `- ${f.filename} (${(f.size / 1024).toFixed(1)} KB) \u2192 ${f.path}`\n ).join('\\n')}\\nUse aamp_send_result with attachments: [${downloadedFiles.map(f => `{ filename: \"${f.filename}\", path: \"${f.path}\" }`).join(', ')}] to forward them.`\n } else if (result.attachments?.length) {\n const files = result.attachments.map((a: ReceivedAttachment) =>\n `${a.filename} (${(a.size / 1024).toFixed(1)} KB, blobId: ${a.blobId})`,\n )\n attachmentInfo = `\\n\\nAttachments (download failed \u2014 use aamp_download_attachment manually):\\n${files.join('\\n')}`\n }\n\n pendingTasks.set(`result:${result.taskId}`, {\n taskId: result.taskId,\n from: result.from,\n title: `${label}: ${sub?.title ?? result.taskId}`,\n bodyText: result.status === 'completed'\n ? `Agent ${result.from} completed the sub-task.\\n\\nOutput:\\n${truncatedOutput}${attachmentInfo}`\n : `Agent ${result.from} rejected the sub-task.\\n\\nReason: ${result.errorMsg ?? 'unknown'}`,\n priority: 'urgent',\n contextLinks: [],\n messageId: '',\n receivedAt: new Date().toISOString(),\n })\n\n // Wake LLM via channel dispatch (instant) or heartbeat (fallback)\n if (channelRuntime && channelCfg) {\n const notifyBody = pendingTasks.get(`result:${result.taskId}`)\n const actionableTasks = [...pendingTasks.entries()]\n .filter(([key]) => !key.startsWith('result:') && !key.startsWith('help:'))\n .map(([, t]) => t)\n const actionSection = actionableTasks.length > 0\n ? `\\n\\n### Action Required\\nYou MUST call aamp_send_result to complete the pending task(s):\\n${actionableTasks.map(t => `- Task ID: ${t.taskId} | From: ${t.from} | Title: \"${t.title}\"`).join('\\n')}`\n : ''\n const prompt = `## Sub-task Update\\n\\n${notifyBody?.bodyText ?? 'Sub-task completed.'}${actionSection}`\n\n channelRuntime.reply.dispatchReplyWithBufferedBlockDispatcher({\n ctx: {\n Body: `Sub-task result: ${result.taskId}`,\n BodyForAgent: prompt,\n From: result.from,\n To: agentEmail,\n SessionKey: buildAampConversationSessionKey(result.from, api.config),\n AccountId: 'default',\n ChatType: 'dm',\n Provider: 'aamp',\n Surface: 'aamp',\n OriginatingChannel: 'aamp',\n OriginatingTo: result.from,\n MessageSid: result.taskId,\n Timestamp: Date.now(),\n SenderName: result.from,\n SenderId: result.from,\n CommandAuthorized: true,\n },\n cfg: channelCfg,\n dispatcherOptions: {\n deliver: async () => {},\n onError: (err: unknown) => {\n api.logger.error(`[AAMP] Channel dispatch error: ${err instanceof Error ? err.message : String(err)}`)\n },\n },\n }).then(() => {\n api.logger.info(`[AAMP] Channel dispatch completed for sub-task result ${result.taskId}`)\n pendingTasks.delete(`result:${result.taskId}`)\n }).catch((err: Error) => {\n api.logger.error(`[AAMP] Channel dispatch failed: ${err.message}`)\n })\n } else {\n const notifySessionKey = buildAampWakeSessionKey('result', result.taskId)\n try {\n api.runtime.system.requestHeartbeatNow({ reason: 'wake', sessionKey: notifySessionKey })\n api.logger.info(`[AAMP] Heartbeat for sub-task result ${result.taskId}`)\n } catch (err) {\n api.logger.warn(`[AAMP] Heartbeat for sub-task result failed: ${(err as Error).message}`)\n }\n }\n }).catch((err: Error) => {\n api.logger.error(`[AAMP] Sub-task result processing failed: ${err.message}`)\n })\n })\n\n // \u2500\u2500 Sub-task help_needed: another agent asks for clarification \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n aampClient.on('task.help_needed', (help: TaskHelp) => {\n if (help.from.toLowerCase() === agentEmail.toLowerCase()) return\n api.logger.info(`[AAMP] \u2190 task.help_needed ${help.taskId} question=\"${help.question}\" from=${help.from}`)\n\n // \u2500\u2500 Synchronous dispatch: if aamp_dispatch_task is waiting, resolve it directly \u2500\u2500\n const waiter = waitingDispatches.get(help.taskId)\n if (waiter) {\n waitingDispatches.delete(help.taskId)\n api.logger.info(`[AAMP] Resolving sync waiter for sub-task help ${help.taskId}`)\n waiter({ type: 'help', data: help })\n return\n }\n\n const sub = dispatchedSubtasks.get(help.taskId)\n\n pendingTasks.set(`help:${help.taskId}`, {\n taskId: help.taskId,\n from: help.from,\n title: `Sub-task needs help: ${sub?.title ?? help.taskId}`,\n bodyText: `Agent ${help.from} is asking for help on the sub-task.\\n\\nQuestion: ${help.question}\\nBlocked reason: ${help.blockedReason}${help.suggestedOptions?.length ? `\\nSuggested options: ${help.suggestedOptions.join(', ')}` : ''}`,\n priority: 'urgent',\n contextLinks: [],\n messageId: '',\n receivedAt: new Date().toISOString(),\n })\n\n if (channelRuntime && channelCfg) {\n const notifyBody = pendingTasks.get(`help:${help.taskId}`)\n const prompt = `## Sub-task Help Request\\n\\n${notifyBody?.bodyText ?? help.question}`\n\n channelRuntime.reply.dispatchReplyWithBufferedBlockDispatcher({\n ctx: {\n Body: `Sub-task help: ${help.taskId}`,\n BodyForAgent: prompt,\n From: help.from,\n To: agentEmail,\n SessionKey: buildAampConversationSessionKey(help.from, api.config),\n AccountId: 'default',\n ChatType: 'dm',\n Provider: 'aamp',\n Surface: 'aamp',\n OriginatingChannel: 'aamp',\n OriginatingTo: help.from,\n MessageSid: help.taskId,\n Timestamp: Date.now(),\n SenderName: help.from,\n SenderId: help.from,\n CommandAuthorized: true,\n },\n cfg: channelCfg,\n dispatcherOptions: {\n deliver: async () => {},\n onError: (err: unknown) => {\n api.logger.error(`[AAMP] Channel dispatch error (help): ${err instanceof Error ? err.message : String(err)}`)\n },\n },\n }).then(() => {\n pendingTasks.delete(`help:${help.taskId}`)\n }).catch((err: Error) => {\n api.logger.error(`[AAMP] Channel dispatch failed for help: ${err.message}`)\n })\n } else {\n const helpSessionKey = buildAampWakeSessionKey('help', help.taskId)\n try {\n api.runtime.system.requestHeartbeatNow({ reason: 'wake', sessionKey: helpSessionKey })\n api.logger.info(`[AAMP] Heartbeat fallback for sub-task help ${help.taskId}`)\n } catch (err) {\n api.logger.warn(`[AAMP] Heartbeat for sub-task help failed: ${(err as Error).message}`)\n }\n }\n })\n\n aampClient.on('connected', () => {\n lastConnectionError = ''\n lastDisconnectReason = ''\n const mode = aampClient?.isUsingPollingFallback() ? 'polling' : 'websocket'\n logTransportState(api, mode, agentEmail, lastLoggedTransportMode)\n lastTransportMode = mode\n lastLoggedTransportMode = mode\n })\n\n aampClient.on('disconnected', (reason: string) => {\n lastDisconnectReason = reason\n if (lastTransportMode !== 'disconnected') {\n api.logger.warn(`[AAMP] Disconnected: ${reason} (will auto-reconnect)`)\n lastTransportMode = 'disconnected'\n lastLoggedTransportMode = 'disconnected'\n }\n })\n\n aampClient.on('error', (err: Error) => {\n lastConnectionError = err.message\n if (err.message.startsWith('JMAP WebSocket unavailable, falling back to polling:')) {\n if (lastTransportMode !== 'polling') {\n logTransportState(api, 'polling', agentEmail, lastLoggedTransportMode)\n lastTransportMode = 'polling'\n lastLoggedTransportMode = 'polling'\n }\n return\n }\n if (err.message.startsWith('Safety reconcile failed:') && isTransientTransportError(err.message)) {\n api.logger.warn(`[AAMP] ${err.message}`)\n return\n }\n api.logger.error(`[AAMP] ${err.message}`)\n })\n\n await aampClient.connect()\n await syncDirectoryProfile().catch((err: Error) => {\n api.logger.warn(`[AAMP] Directory profile sync failed: ${err.message}`)\n })\n\n api.logger.info(\n `[AAMP] Transport after connect \u2014 ${aampClient.isUsingPollingFallback() ? 'polling fallback' : 'websocket'} as ${agentEmail}`,\n )\n\n if (aampClient.isConnected() && lastTransportMode === 'disconnected') {\n if (aampClient.isUsingPollingFallback()) {\n logTransportState(api, 'polling', agentEmail, lastLoggedTransportMode)\n lastTransportMode = 'polling'\n lastLoggedTransportMode = 'polling'\n } else {\n logTransportState(api, 'websocket', agentEmail, lastLoggedTransportMode)\n lastTransportMode = 'websocket'\n lastLoggedTransportMode = 'websocket'\n }\n }\n\n setTimeout(() => {\n if (!aampClient?.isConnected()) return\n const mode = aampClient.isUsingPollingFallback() ? 'polling' : 'websocket'\n logTransportState(api, mode, agentEmail, lastLoggedTransportMode)\n lastTransportMode = mode\n lastLoggedTransportMode = mode\n }, 1000)\n\n void reconcileMailbox(!historicalReconcileCompleted).catch((err: Error) => {\n lastConnectionError = err.message\n if (!historicalReconcileCompleted) {\n api.logger.warn(`[AAMP] Startup mailbox reconcile failed: ${err.message} (will retry historical tasks)`)\n } else {\n api.logger.warn(`[AAMP] Startup mailbox reconcile failed: ${err.message}`)\n }\n })\n\n transportMonitorTimer = setInterval(() => {\n if (!aampClient) return\n if (!aampClient.isConnected()) {\n if (lastTransportMode !== 'disconnected') {\n lastTransportMode = 'disconnected'\n }\n return\n }\n const mode = aampClient.isUsingPollingFallback() ? 'polling' : 'websocket'\n logTransportState(api, mode, agentEmail, lastLoggedTransportMode)\n lastTransportMode = mode\n lastLoggedTransportMode = mode\n }, 5000)\n\n reconcileTimer = setInterval(() => {\n if (!aampClient) return\n const includeHistorical = !historicalReconcileCompleted\n void reconcileMailbox(includeHistorical).catch((err: Error) => {\n lastConnectionError = err.message\n if (includeHistorical) {\n api.logger.warn(`[AAMP] Mailbox reconcile failed while retrying historical tasks: ${err.message}`)\n } else {\n api.logger.warn(`[AAMP] Mailbox reconcile failed: ${err.message}`)\n }\n })\n }, 15000)\n }\n\n // \u2500\u2500 Service: auto-connect at gateway startup, disconnect on shutdown \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // registerService causes this plugin to load eagerly (at gateway startup),\n // not lazily (on first agent run). start() is called once the gateway is up.\n api.registerService({\n id: 'aamp-service',\n start: async () => {\n if (!cfg.aampHost) {\n api.logger.info('[AAMP] aampHost not configured \u2014 skipping auto-connect')\n return\n }\n try {\n const identity = await resolveIdentity(cfg)\n await doConnect(identity)\n } catch (err) {\n api.logger.warn(`[AAMP] Service auto-connect failed: ${(err as Error).message}`)\n }\n },\n stop: () => {\n if (reconcileTimer) {\n clearInterval(reconcileTimer)\n reconcileTimer = null\n }\n if (transportMonitorTimer) {\n clearInterval(transportMonitorTimer)\n transportMonitorTimer = null\n }\n if (aampClient) {\n try {\n aampClient.disconnect()\n api.logger.info('[AAMP] Disconnected on gateway stop')\n } catch {\n // ignore disconnect errors on shutdown\n }\n }\n },\n })\n\n // \u2500\u2500 gateway_start hook: re-trigger heartbeat after runner is initialized \u2500\u2500\u2500\n // Service start() runs BEFORE the heartbeat runner is ready, so\n // requestHeartbeatNow() called during JMAP initial fetch is silently dropped\n // (handler == null). gateway_start fires AFTER the heartbeat runner starts,\n // so we re-trigger here to process any tasks queued during startup.\n api.on('gateway_start', () => {\n if (pendingTasks.size === 0) return\n api.logger.info(`[AAMP] gateway_start: re-triggering heartbeat for ${pendingTasks.size} pending task(s)`)\n try {\n api.runtime.system.requestHeartbeatNow({\n reason: 'wake',\n sessionKey: buildAampWakeSessionKey('queue', 'gateway-start'),\n })\n } catch (err) {\n api.logger.warn(`[AAMP] gateway_start heartbeat failed: ${(err as Error).message}`)\n }\n })\n\n // \u2500\u2500 2. Prompt injection: surface the oldest pending task to the LLM \u2500\u2500\u2500\u2500\u2500\u2500\n api.on(\n 'before_prompt_build',\n (_event, ctx) => {\n // Only AAMP-owned sessions should receive mailbox task context.\n // This prevents regular user chats from inheriting pending email instructions.\n if (!isAampSessionKey(ctx?.sessionKey)) {\n return {}\n }\n\n // Expire tasks that have exceeded their dispatch expiry window.\n for (const [id, t] of pendingTasks) {\n if (hasExpired(t)) {\n if (!isSyntheticPendingKey(id) && aampClient?.isConnected()) {\n void aampClient.sendResult({\n to: t.from,\n taskId: t.taskId,\n status: 'rejected',\n output: '',\n errorMsg: t.expiresAt\n ? 'Task expired before the agent could complete it.'\n : 'Task timed out while waiting for agent completion or follow-up input.',\n inReplyTo: t.messageId || undefined,\n }).then(() => {\n rememberTerminalTask(t.taskId)\n api.logger.warn(`[AAMP] Task ${id} expired \u2014 sent rejected result to dispatcher`)\n }).catch((err: Error) => {\n api.logger.error(`[AAMP] Task ${id} expired \u2014 failed to notify dispatcher: ${err.message}`)\n })\n } else {\n rememberTerminalTask(t.taskId)\n api.logger.warn(`[AAMP] Task ${id} expired \u2014 removing from queue`)\n }\n pendingTasks.delete(id)\n }\n }\n\n if (pendingTasks.size === 0) return {}\n\n const targetedPendingKey = resolvePendingKeyFromSessionKey(ctx?.sessionKey)\n const targetedEntry = targetedPendingKey\n ? (() => {\n const targetedTask = pendingTasks.get(targetedPendingKey)\n if (!targetedTask) return undefined\n if (!isSyntheticPendingKey(targetedPendingKey) && isTaskAwaitingHelpReply(targetedTask)) {\n return undefined\n }\n return [targetedPendingKey, targetedTask] as [string, PendingTask]\n })()\n : undefined\n\n // Prioritize notifications (sub-task results/help) over actionable tasks.\n // Without this, the oldest actionable task blocks notification delivery,\n // preventing the LLM from seeing sub-task results and completing the parent task.\n const sessionScopedEntry = targetedPendingKey ? undefined : findPendingEntryForSession(ctx?.sessionKey, api.config)\n const nextEntry = targetedPendingKey ? targetedEntry : sessionScopedEntry ?? nextPendingEntry()\n if (!nextEntry) return {}\n const [taskKey, task] = nextEntry\n\n const isNotification = taskKey.startsWith('result:') || taskKey.startsWith('help:')\n\n // Notifications are one-shot: remove immediately after injecting into prompt\n if (isNotification && taskKey) {\n pendingTasks.delete(taskKey)\n }\n\n // Find remaining actionable tasks (non-notification) that still need a response\n const actionableTasks = [...pendingTasks.entries()]\n .filter(([key, pendingTask]) => isActionablePendingTask(key, pendingTask))\n .map(([, t]) => t)\n .sort((a, b) => {\n const rankDiff = priorityRank(a.priority) - priorityRank(b.priority)\n if (rankDiff !== 0) return rankDiff\n return new Date(a.receivedAt).getTime() - new Date(b.receivedAt).getTime()\n })\n const otherActionableTasks = actionableTasks.filter((pendingTask) => pendingTask.taskId !== task.taskId)\n\n const hasAttachmentInfo = isNotification && (task.bodyText?.includes('aamp_download_attachment') ?? false)\n const actionRequiredSection = isNotification && actionableTasks.length > 0\n ? [\n ``,\n `### Action Required`,\n ``,\n `You still have ${actionableTasks.length} pending task(s) that need a response.`,\n `Use the sub-task result above to complete them by calling aamp_send_result.`,\n ``,\n ...actionableTasks.map((t) =>\n `- [${t.priority}] Task ID: ${t.taskId} | From: ${t.from} | Title: \"${t.title}\"`\n ),\n ...(hasAttachmentInfo ? [\n ``,\n `### Forwarding Attachments`,\n `The sub-task result includes file attachments. To forward them:`,\n `1. Call aamp_download_attachment for each blobId listed above`,\n `2. Include the downloaded files in aamp_send_result via the attachments parameter`,\n ` Example: attachments: [{ filename: \"file.html\", path: \"/tmp/aamp-files/file.html\" }]`,\n ] : []),\n ].join('\\n')\n : ''\n\n const dispatchContextLines = task.dispatchContext && Object.keys(task.dispatchContext).length > 0\n ? `Dispatch Context:\\n${Object.entries(task.dispatchContext).map(([key, value]) => ` - ${key}: ${value}`).join('\\n')}`\n : ''\n\n const taskPromptLines = isConversationalTask(task) ? [\n `## Pending AAMP Conversation Turn`,\n ``,\n `This AAMP task came from a chat surface (${task.dispatchContext?.source ?? 'unknown'}).`,\n `Treat it as an ongoing conversation turn, not a one-off work order.`,\n `Your job is to reply naturally to the user's latest message and keep the conversation moving.`,\n ``,\n `### Tool selection rules for chat turns:`,\n ``,\n `Use aamp_send_result for normal conversation replies, including:`,\n ` - greetings, acknowledgements, and small talk (\"hi\", \"hello\", \"thanks\", \"got it\")`,\n ` - short follow-up questions that help narrow the user's intent`,\n ` - direct answers, suggestions, or next-step guidance`,\n ``,\n `Use aamp_send_help ONLY when you are truly blocked and cannot produce a meaningful`,\n `reply without waiting for specific missing information from the human.`,\n `Do NOT use aamp_send_help just because the message is brief or casual.`,\n ``,\n `IMPORTANT: For conversational traffic, replying to \"hi\" with a natural greeting and an`,\n `offer to help is CORRECT. Do not reject greetings as invalid tasks.`,\n ``,\n `### Sub-task dispatch rules:`,\n `If you delegate work to another agent via aamp_dispatch_task, you MUST pass`,\n `parentTaskId: \"${task.taskId}\" to establish the parent-child relationship.`,\n `If you need to find a suitable agent first, call aamp_directory_search.`,\n ``,\n `Task ID: ${task.taskId}`,\n `From: ${task.from}`,\n `Title: ${task.title}`,\n dispatchContextLines,\n task.threadContextText ? `${task.threadContextText}` : '',\n task.bodyText ? `Latest user message:\\n${task.bodyText}` : '',\n task.contextLinks.length\n ? `Context Links:\\n${task.contextLinks.map((l) => ` - ${l}`).join('\\n')}`\n : '',\n task.expiresAt ? `Expires: ${task.expiresAt}` : `Expires: none`,\n `Received: ${task.receivedAt}`,\n otherActionableTasks.length > 0 ? `\\n(+${otherActionableTasks.length} more tasks queued)` : '',\n ] : [\n `## Pending AAMP Task (action required)`,\n ``,\n `You have received a task via AAMP email. You MUST call one of the two tools below`,\n `BEFORE responding to the user \u2014 do not skip this step.`,\n ``,\n `### Tool selection rules (follow strictly):`,\n ``,\n `Use aamp_send_result ONLY when ALL of the following are true:`,\n ` 1. The title contains a clear, specific action verb (e.g. \"summarise\", \"review\",`,\n ` \"translate\", \"generate\", \"fix\", \"search\", \"compare\", \"list\")`,\n ` 2. You know exactly what input/resource to act on`,\n ` 3. No ambiguity remains \u2014 you could start work immediately without asking anything`,\n ``,\n `Use aamp_send_help in ALL other cases, including:`,\n ` - Title is a greeting or salutation (\"hello\", \"hi\", \"hey\", \"test\", \"ping\", etc.)`,\n ` - Title is fewer than 4 words and contains no actionable verb`,\n ` - Title is too vague to act on without guessing (e.g. \"help\", \"task\", \"question\")`,\n ` - Required context is missing (which file? which URL? which criteria?)`,\n ` - Multiple interpretations are equally plausible`,\n ``,\n `IMPORTANT: Responding to a greeting with a greeting is WRONG. \"hello\" is not a`,\n `valid task description \u2014 ask what specific task the dispatcher needs done.`,\n ``,\n `### Sub-task dispatch rules:`,\n `If you delegate work to another agent via aamp_dispatch_task, you MUST pass`,\n `parentTaskId: \"${task.taskId}\" to establish the parent-child relationship.`,\n `If you need to find a suitable agent first, call aamp_directory_search.`,\n ``,\n `Task ID: ${task.taskId}`,\n `From: ${task.from}`,\n `Title: ${task.title}`,\n dispatchContextLines,\n task.threadContextText ? `${task.threadContextText}` : '',\n task.bodyText ? `Description:\\n${task.bodyText}` : '',\n task.contextLinks.length\n ? `Context Links:\\n${task.contextLinks.map((l) => ` - ${l}`).join('\\n')}`\n : '',\n task.expiresAt ? `Expires: ${task.expiresAt}` : `Expires: none`,\n `Received: ${task.receivedAt}`,\n otherActionableTasks.length > 0 ? `\\n(+${otherActionableTasks.length} more tasks queued)` : '',\n ]\n\n const lines = isNotification ? [\n `## Sub-task Update`,\n ``,\n `A sub-task you dispatched has returned a result. Review the information below.`,\n `If the sub-task included attachments, use aamp_download_attachment to fetch them.`,\n ``,\n `Task ID: ${task.taskId}`,\n `Priority: ${task.priority}`,\n `From: ${task.from}`,\n `Title: ${task.title}`,\n task.bodyText ? `\\n${task.bodyText}` : '',\n actionRequiredSection,\n otherActionableTasks.length > 0 ? `\\n(+${otherActionableTasks.length} more tasks queued)` : '',\n ] : taskPromptLines\n .filter(Boolean)\n .join('\\n')\n\n return { prependContext: lines }\n },\n { priority: 5 },\n )\n\n // \u2500\u2500 3. Tool: send task result \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n api.registerTool({\n name: 'aamp_directory_search',\n description:\n 'Search the AAMP directory for agents by capability summary, card text, or email address.',\n parameters: {\n type: 'object',\n required: ['query'],\n properties: {\n query: { type: 'string', description: 'Capability or keyword to search for' },\n limit: { type: 'number', description: 'Maximum number of matches to return (default: 10)' },\n includeSelf: { type: 'boolean', description: 'Whether to include the current agent in results' },\n },\n },\n execute: async (_id, params) => {\n if (!aampClient) {\n return { content: [{ type: 'text', text: 'Error: AAMP client is not connected.' }] }\n }\n\n const query = String((params as { query?: string }).query ?? '').trim()\n if (!query) {\n return { content: [{ type: 'text', text: 'Error: query is required.' }] }\n }\n\n const agents = await aampClient.searchDirectory({\n query,\n limit: Number((params as { limit?: number }).limit ?? 10),\n includeSelf: Boolean((params as { includeSelf?: boolean }).includeSelf),\n })\n\n if (!agents.length) {\n return { content: [{ type: 'text', text: `No agents matched \"${query}\".` }] }\n }\n\n return {\n content: [{\n type: 'text',\n text: agents\n .map((agent, index) =>\n `${index + 1}. ${agent.email}${agent.summary ? ` \u2014 ${agent.summary}` : ''}`,\n )\n .join('\\n'),\n }],\n }\n },\n }, { name: 'aamp_directory_search' })\n\n api.registerTool({\n name: 'aamp_send_result',\n description:\n 'Send the result of an AAMP task back to the dispatcher. ' +\n 'Call this after you have finished processing the task.',\n parameters: {\n type: 'object',\n required: ['taskId', 'status', 'output'],\n properties: {\n taskId: {\n type: 'string',\n description: 'The AAMP task ID to reply to (from the system context)',\n },\n status: {\n type: 'string',\n enum: ['completed', 'rejected'],\n description: '\"completed\" on success, \"rejected\" if the task cannot be done',\n },\n output: {\n type: 'string',\n description: 'Your result or explanation',\n },\n errorMsg: {\n type: 'string',\n description: 'Optional error details (use only when status = rejected)',\n },\n attachments: {\n type: 'array',\n description: 'File attachments. Each item: { filename, contentType, path (local file path) }',\n items: {\n type: 'object',\n properties: {\n filename: { type: 'string' },\n contentType: { type: 'string' },\n path: { type: 'string', description: 'Absolute path to the file on disk' },\n },\n required: ['filename', 'path'],\n },\n },\n structuredResult: {\n type: 'array',\n description: 'Optional structured Meego field values.',\n items: {\n type: 'object',\n required: ['fieldKey', 'fieldTypeKey'],\n properties: {\n fieldKey: { type: 'string' },\n fieldTypeKey: { type: 'string' },\n fieldAlias: { type: 'string' },\n value: {\n description: 'Field value in the exact format required by Meego for this field type.',\n },\n index: { type: 'string' },\n attachmentFilenames: {\n type: 'array',\n items: { type: 'string' },\n description: 'For attachment fields, filenames from attachments[] that should be uploaded into this field.',\n },\n },\n },\n },\n },\n },\n execute: async (_id, params) => {\n const p = params as {\n taskId: string\n status: 'completed' | 'rejected'\n output: string\n errorMsg?: string\n attachments?: Array<{ filename: string; contentType?: string; path: string }>\n structuredResult?: StructuredResultFieldInput[]\n }\n\n const task = pendingTasks.get(p.taskId)\n if (!task) {\n return {\n content: [{ type: 'text', text: `Error: task ${p.taskId} not found in pending queue.` }],\n }\n }\n\n if (!aampClient?.isConnected()) {\n return { content: [{ type: 'text', text: 'Error: AAMP client is not connected.' }] }\n }\n\n api.logger.info(`[AAMP] aamp_send_result params ${JSON.stringify({\n taskId: p.taskId,\n status: p.status,\n output: p.output,\n errorMsg: p.errorMsg,\n attachments: p.attachments?.map((a) => ({\n filename: a.filename,\n contentType: a.contentType ?? 'application/octet-stream',\n path: a.path,\n })) ?? [],\n structuredResult: p.structuredResult?.map((field) => ({\n fieldKey: field.fieldKey,\n fieldTypeKey: field.fieldTypeKey,\n fieldAlias: field.fieldAlias,\n value: field.value,\n index: field.index,\n attachmentFilenames: field.attachmentFilenames ?? [],\n })) ?? [],\n })}`)\n\n // Build attachments from file paths\n let attachments: AampAttachment[] | undefined\n if (p.attachments?.length) {\n attachments = p.attachments.map((a: { filename: string; contentType?: string; path: string }) => ({\n filename: a.filename,\n contentType: a.contentType ?? 'application/octet-stream',\n content: readBinaryFile(a.path),\n }))\n }\n\n await appendTaskStream(task.taskId, 'status', {\n state: 'completing',\n label: `Sending ${p.status} result`,\n })\n if (p.output) {\n await appendTaskStream(task.taskId, 'text.delta', { text: p.output })\n }\n await closeTaskStream(task.taskId, {\n reason: 'task.result',\n status: p.status,\n ...(p.errorMsg ? { error: p.errorMsg } : {}),\n })\n\n await aampClient.sendResult({\n to: task.from,\n taskId: task.taskId,\n status: p.status,\n output: p.output,\n errorMsg: p.errorMsg,\n structuredResult: p.structuredResult?.length ? p.structuredResult : undefined,\n inReplyTo: task.messageId || undefined,\n attachments,\n })\n\n pendingTasks.delete(task.taskId)\n rememberTerminalTask(task.taskId)\n api.logger.info(`[AAMP] \u2192 task.result ${task.taskId} ${p.status}`)\n\n // If more tasks remain, wake the agent to process them\n if (pendingTasks.size > 0) {\n try {\n api.runtime.system.requestHeartbeatNow({\n reason: 'wake',\n sessionKey: buildAampWakeSessionKey('queue', 'follow-up'),\n })\n } catch { /* ignore */ }\n }\n\n return {\n content: [\n {\n type: 'text',\n text: `Result sent for task ${task.taskId} (status: ${p.status}).`,\n },\n ],\n }\n },\n }, { name: 'aamp_send_result' })\n\n // \u2500\u2500 4. Tool: ask for help \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n api.registerTool({\n name: 'aamp_send_help',\n description:\n 'Send a help request for an AAMP task when you are blocked or need human clarification ' +\n 'before you can proceed.',\n parameters: {\n type: 'object',\n required: ['taskId', 'question', 'blockedReason'],\n properties: {\n taskId: {\n type: 'string',\n description: 'The AAMP task ID',\n },\n question: {\n type: 'string',\n description: 'Your question for the human dispatcher',\n },\n blockedReason: {\n type: 'string',\n description: 'Why you cannot proceed without their input',\n },\n suggestedOptions: {\n type: 'array',\n items: { type: 'string' },\n description: 'Optional list of choices for the dispatcher to pick from',\n },\n },\n },\n execute: async (_id, params) => {\n const p = params as {\n taskId: string\n question: string\n blockedReason: string\n suggestedOptions?: string[]\n }\n\n const task = pendingTasks.get(p.taskId)\n if (!task) {\n return {\n content: [{ type: 'text', text: `Error: task ${p.taskId} not found in pending queue.` }],\n }\n }\n\n if (!aampClient?.isConnected()) {\n return { content: [{ type: 'text', text: 'Error: AAMP client is not connected.' }] }\n }\n\n await appendTaskStream(task.taskId, 'status', {\n state: 'help_needed',\n label: p.blockedReason,\n })\n\n try {\n await aampClient.sendHelp({\n to: task.from,\n taskId: task.taskId,\n question: p.question,\n blockedReason: p.blockedReason,\n suggestedOptions: p.suggestedOptions ?? [],\n inReplyTo: task.messageId || undefined,\n })\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n await appendTaskStream(task.taskId, 'error', {\n message: `Failed to send help request: ${message}`,\n })\n await appendTaskStream(task.taskId, 'status', {\n state: 'running',\n label: 'Help request failed; task still needs a reply',\n })\n api.logger.error(`[AAMP] aamp_send_help failed for ${task.taskId}: ${message}`)\n\n return {\n content: [\n {\n type: 'text',\n text: `Error: failed to send help request for task ${task.taskId}: ${message}`,\n },\n ],\n }\n }\n\n await closeTaskStream(task.taskId, {\n reason: 'task.help_needed',\n })\n\n pendingTasks.set(task.taskId, {\n ...task,\n awaitingHelpReply: true,\n })\n api.logger.info(`[AAMP] \u2192 task.help_needed ${task.taskId}`)\n\n // Keep the task in pending, but suspend it from auto-dispatch until new input arrives.\n return {\n content: [\n {\n type: 'text',\n text: `Help request sent for task ${task.taskId}. The task is now suspended until the dispatcher replies.`,\n },\n ],\n }\n },\n }, { name: 'aamp_send_help' })\n\n // \u2500\u2500 5. Tool: inspect queue \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n api.registerTool({\n name: 'aamp_pending_tasks',\n description: 'List all AAMP tasks currently waiting to be processed.',\n parameters: { type: 'object', properties: {} },\n execute: async () => {\n if (pendingTasks.size === 0) {\n return { content: [{ type: 'text', text: 'No pending AAMP tasks.' }] }\n }\n\n const lines = [...pendingTasks.values()]\n .sort((a, b) => {\n const rankDiff = priorityRank(a.priority) - priorityRank(b.priority)\n if (rankDiff !== 0) return rankDiff\n return new Date(a.receivedAt).getTime() - new Date(b.receivedAt).getTime()\n })\n .map(\n (t, i) =>\n `${i + 1}. [${t.priority}] [${t.taskId}] \"${t.title}\"${isTaskAwaitingHelpReply(t) ? ' (waiting for dispatcher reply)' : ''}${t.bodyText ? `\\n Description: ${t.bodyText}` : ''} \u2014 from ${t.from} (received ${t.receivedAt})`,\n )\n\n return {\n content: [\n {\n type: 'text',\n text: `${pendingTasks.size} pending task(s):\\n${lines.join('\\n')}`,\n },\n ],\n }\n },\n }, { name: 'aamp_pending_tasks' })\n\n api.registerTool({\n name: 'aamp_cancel_task',\n description: 'Cancel a pending AAMP task and notify the dispatcher.',\n parameters: {\n type: 'object',\n required: ['taskId'],\n properties: {\n taskId: { type: 'string', description: 'The AAMP task ID to cancel.' },\n bodyText: { type: 'string', description: 'Optional cancellation note sent in the email body.' },\n },\n },\n execute: async (_id, params) => {\n const p = params as { taskId: string; bodyText?: string }\n const task = pendingTasks.get(p.taskId)\n if (!task) {\n return { content: [{ type: 'text', text: `Error: task ${p.taskId} not found in pending queue.` }] }\n }\n if (!aampClient?.isConnected()) {\n return { content: [{ type: 'text', text: 'Error: AAMP client is not connected.' }] }\n }\n\n await aampClient.sendCancel({\n to: task.from,\n taskId: task.taskId,\n bodyText: p.bodyText,\n inReplyTo: task.messageId || undefined,\n })\n\n pendingTasks.delete(task.taskId)\n rememberTerminalTask(task.taskId)\n api.logger.info(`[AAMP] \u2192 task.cancel ${task.taskId}`)\n return {\n content: [{ type: 'text', text: `Cancellation sent for task ${task.taskId}.` }],\n }\n },\n }, { name: 'aamp_cancel_task' })\n\n // \u2500\u2500 6. Tool: dispatch task to another agent (SYNCHRONOUS) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Sends the task and BLOCKS until the sub-agent replies with task.result or\n // task.help_needed. The reply is returned directly as the tool result, keeping the\n // LLM awake with full context \u2014 no heartbeat/channel dispatch needed.\n api.registerTool({\n name: 'aamp_dispatch_task',\n description:\n 'Send a task to another AAMP agent and WAIT for the result. ' +\n 'This tool blocks until the sub-agent replies (typically 5-60s). ' +\n 'The sub-agent\\'s output and any attachment file paths are returned directly.',\n parameters: {\n type: 'object',\n required: ['to', 'title'],\n properties: {\n to: { type: 'string', description: 'Target agent AAMP email address' },\n title: { type: 'string', description: 'Task title (concise summary)' },\n bodyText: { type: 'string', description: 'Detailed task description' },\n parentTaskId: { type: 'string', description: 'If you are processing a pending AAMP task, pass its Task ID here to establish parent-child nesting. Omit for top-level tasks.' },\n priority: { type: 'string', enum: ['urgent', 'high', 'normal'], description: 'Task priority (optional)' },\n expiresAt: { type: 'string', description: 'Absolute expiry time in ISO 8601 format (optional)' },\n contextLinks: {\n type: 'array', items: { type: 'string' },\n description: 'URLs providing context (optional)',\n },\n attachments: {\n type: 'array',\n description: 'File attachments. Each item: { filename, contentType, path (local file path) }',\n items: {\n type: 'object',\n properties: {\n filename: { type: 'string' },\n contentType: { type: 'string' },\n path: { type: 'string', description: 'Absolute path to the file on disk' },\n },\n required: ['filename', 'path'],\n },\n },\n },\n },\n execute: async (_id: unknown, params: {\n to: string; title: string; bodyText?: string;\n parentTaskId?: string; priority?: TaskPriority; expiresAt?: string; contextLinks?: string[];\n attachments?: Array<{ filename: string; contentType?: string; path: string }>\n }) => {\n if (!aampClient?.isConnected()) {\n return { content: [{ type: 'text', text: 'Error: AAMP client is not connected.' }] }\n }\n\n try {\n // Build attachments from file paths\n let attachments: AampAttachment[] | undefined\n if (params.attachments?.length) {\n attachments = params.attachments.map((a: { filename: string; contentType?: string; path: string }) => ({\n filename: a.filename,\n contentType: a.contentType ?? 'application/octet-stream',\n content: readBinaryFile(a.path),\n }))\n }\n\n const result = await aampClient.sendTask({\n to: params.to,\n title: params.title,\n parentTaskId: params.parentTaskId,\n priority: params.priority,\n expiresAt: params.expiresAt,\n contextLinks: params.contextLinks,\n attachments,\n })\n\n // Track as dispatched sub-task\n dispatchedSubtasks.set(result.taskId, {\n to: params.to,\n title: params.title,\n dispatchedAt: new Date().toISOString(),\n parentTaskId: params.parentTaskId,\n })\n\n api.logger.info(`[AAMP] \u2192 task.dispatch ${result.taskId} to=${params.to} parent=${params.parentTaskId ?? 'none'} (waiting for reply\u2026)`)\n\n // \u2500\u2500 SYNCHRONOUS WAIT: block until sub-agent replies \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const timeoutMs = params.expiresAt\n ? Math.max(new Date(params.expiresAt).getTime() - Date.now(), 1)\n : 300 * 1000\n const reply = await new Promise<{ type: 'result' | 'help'; data: unknown }>((resolve, reject) => {\n waitingDispatches.set(result.taskId, resolve)\n setTimeout(() => {\n if (waitingDispatches.delete(result.taskId)) {\n reject(new Error(\n params.expiresAt\n ? `Sub-task ${result.taskId} expired before a reply was received`\n : `Sub-task ${result.taskId} timed out after 300s`,\n ))\n }\n }, timeoutMs)\n })\n\n api.logger.info(`[AAMP] \u2190 sync reply for ${result.taskId}: type=${reply.type} attachments=${JSON.stringify((reply.data as any)?.attachments?.length ?? 0)}`)\n\n if (reply.type === 'result') {\n const r = reply.data as TaskResult\n\n // Pre-download attachments \u2014 use direct JMAP blob download (bypass SDK's downloadBlob\n // which was returning 404 due to URL construction issues in the esbuild bundle).\n let attachmentLines = ''\n if (r.attachments?.length) {\n api.logger.info(`[AAMP] Downloading ${r.attachments.length} attachment(s) from sync reply...`)\n const dir = '/tmp/aamp-files'\n ensureDir(dir)\n const downloaded: string[] = []\n for (const att of r.attachments) {\n try {\n const buffer = await aampClient!.downloadBlob(att.blobId, att.filename)\n const filepath = `${dir}/${att.filename}`\n writeBinaryFile(filepath, buffer)\n downloaded.push(`${att.filename} (${(buffer.length / 1024).toFixed(1)} KB) \u2192 ${filepath}`)\n api.logger.info(`[AAMP] Downloaded: ${att.filename} (${(buffer.length / 1024).toFixed(1)} KB)`)\n } catch (dlErr) {\n api.logger.error(`[AAMP] Download failed for ${att.filename}: ${(dlErr as Error).message}`)\n }\n }\n if (downloaded.length) {\n attachmentLines = `\\n\\nAttachments downloaded:\\n${downloaded.join('\\n')}`\n }\n }\n\n return {\n content: [{\n type: 'text',\n text: [\n `Sub-task ${r.status}: ${params.title}`,\n `Agent: ${r.from}`,\n `Task ID: ${result.taskId}`,\n r.status === 'completed' ? `\\nOutput:\\n${r.output}` : `\\nError: ${r.errorMsg ?? 'rejected'}`,\n attachmentLines,\n ].filter(Boolean).join('\\n'),\n }],\n }\n } else {\n const h = reply.data as TaskHelp\n return {\n content: [{\n type: 'text',\n text: [\n `Sub-task needs help: ${params.title}`,\n `Agent: ${h.from}`,\n `Task ID: ${result.taskId}`,\n `\\nQuestion: ${h.question}`,\n `Blocked reason: ${h.blockedReason}`,\n h.suggestedOptions?.length ? `Options: ${h.suggestedOptions.join(' | ')}` : '',\n ].filter(Boolean).join('\\n'),\n }],\n }\n }\n } catch (err) {\n return {\n content: [{ type: 'text', text: `Error dispatching task: ${(err as Error).message}` }],\n }\n }\n },\n }, { name: 'aamp_dispatch_task' })\n\n // \u2500\u2500 7. Tool: check AAMP protocol support \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n api.registerTool({\n name: 'aamp_check_protocol',\n description:\n 'Check if an email address supports the AAMP protocol. ' +\n 'Returns { aamp: true/false } indicating whether the address is an AAMP agent.',\n parameters: {\n type: 'object',\n required: ['email'],\n properties: {\n email: { type: 'string', description: 'Email address to check' },\n },\n },\n execute: async (_id: unknown, params: { email: string }) => {\n const base = baseUrl(cfg.aampHost)\n const email = params?.email ?? ''\n if (!email) {\n return { content: [{ type: 'text', text: 'Error: email parameter is required' }] }\n }\n try {\n const data = await AampClient.checkMailbox({\n aampHost: base,\n email,\n })\n return {\n content: [{\n type: 'text',\n text: data.aamp\n ? `${params.email} supports AAMP protocol (domain: ${data.domain ?? 'unknown'})`\n : `${params.email} does not support AAMP protocol`,\n }],\n }\n } catch (err) {\n return {\n content: [{ type: 'text', text: `Could not check ${params.email}: ${(err as Error).message}` }],\n }\n }\n },\n }, { name: 'aamp_check_protocol' })\n\n // \u2500\u2500 8. Tool: download attachment blob \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n api.registerTool({\n name: 'aamp_download_attachment',\n description:\n 'Download an AAMP email attachment to local disk by its blobId. ' +\n 'Use this to retrieve files received from sub-agent task results.',\n parameters: {\n type: 'object',\n required: ['blobId', 'filename'],\n properties: {\n blobId: { type: 'string', description: 'The JMAP blobId from the attachment metadata' },\n filename: { type: 'string', description: 'Filename to save as' },\n saveTo: { type: 'string', description: 'Directory to save to (default: /tmp/aamp-files)' },\n },\n },\n execute: async (_id: unknown, params: { blobId: string; filename: string; saveTo?: string }) => {\n if (!aampClient?.isConnected()) {\n return { content: [{ type: 'text', text: 'Error: AAMP client is not connected.' }] }\n }\n\n const dir = params.saveTo ?? '/tmp/aamp-files'\n ensureDir(dir)\n\n try {\n const buffer = await aampClient.downloadBlob(params.blobId, params.filename)\n const filepath = `${dir}/${params.filename}`\n writeBinaryFile(filepath, buffer)\n return {\n content: [{\n type: 'text',\n text: `Downloaded ${params.filename} (${(buffer.length / 1024).toFixed(1)} KB) to ${filepath}`,\n }],\n }\n } catch (err) {\n return {\n content: [{ type: 'text', text: `Download failed: ${(err as Error).message}` }],\n }\n }\n },\n }, { name: 'aamp_download_attachment' })\n\n // \u2500\u2500 9. Slash command: /aamp-status \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n api.registerCommand({\n name: 'aamp-status',\n description: 'Show AAMP connection status and pending task queue',\n acceptsArgs: false,\n requireAuth: false,\n handler: () => {\n const isPollingFallback = aampClient?.isUsingPollingFallback?.() ?? false\n const connectionLine = aampClient?.isConnected()\n ? (isPollingFallback ? '\uD83D\uDFE1 connected (polling fallback)' : '\u2705 connected')\n : '\u274C disconnected'\n\n return {\n text: [\n `**AAMP Plugin Status**`,\n `Host: ${cfg.aampHost || '(not configured)'}`,\n `Identity: ${agentEmail || '(not yet registered)'}`,\n `Connection: ${connectionLine}`,\n `Cached: ${loadCachedIdentity(cfg.credentialsFile ?? defaultCredentialsPath()) ? 'yes' : 'no'}`,\n lastConnectionError ? `Last error: ${lastConnectionError}` : '',\n lastDisconnectReason ? `Last disconnect: ${lastDisconnectReason}` : '',\n `Pending: ${pendingTasks.size} task(s)`,\n ...[...pendingTasks.values()].map(\n (t) => ` \u2022 ${t.taskId.slice(0, 8)}\u2026 \"${t.title}\" from ${t.from}`,\n ),\n ]\n .filter(Boolean)\n .join('\\n'),\n }\n },\n })\n },\n}\n", "import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { homedir } from 'node:os'\n\nexport interface Identity {\n email: string\n mailboxToken: string\n smtpPassword: string\n}\n\nexport interface CachedTaskState {\n terminalTaskIds?: string[]\n}\n\nexport function defaultCredentialsPath(): string {\n return join(homedir(), '.openclaw', 'extensions', 'aamp-openclaw-plugin', '.credentials.json')\n}\n\nexport function defaultTaskStatePath(): string {\n return join(homedir(), '.openclaw', 'extensions', 'aamp-openclaw-plugin', '.task-state.json')\n}\n\nexport function loadCachedIdentity(file?: string): Identity | null {\n const resolved = file ?? defaultCredentialsPath()\n if (!existsSync(resolved)) return null\n try {\n const parsed = JSON.parse(readFileSync(resolved, 'utf-8')) as Partial<Identity>\n if (!parsed.email || !parsed.mailboxToken || !parsed.smtpPassword) return null\n return {\n email: parsed.email,\n mailboxToken: parsed.mailboxToken,\n smtpPassword: parsed.smtpPassword,\n }\n } catch {\n return null\n }\n}\n\nexport function saveCachedIdentity(identity: Identity, file?: string): void {\n const resolved = file ?? defaultCredentialsPath()\n mkdirSync(dirname(resolved), { recursive: true })\n writeFileSync(resolved, JSON.stringify({\n email: identity.email,\n mailboxToken: identity.mailboxToken,\n smtpPassword: identity.smtpPassword,\n }, null, 2), 'utf-8')\n}\n\nexport function loadTaskState(file?: string): CachedTaskState {\n const resolved = file ?? defaultTaskStatePath()\n if (!existsSync(resolved)) return { terminalTaskIds: [] }\n try {\n const parsed = JSON.parse(readFileSync(resolved, 'utf-8')) as CachedTaskState\n return {\n terminalTaskIds: Array.isArray(parsed.terminalTaskIds) ? parsed.terminalTaskIds.filter(Boolean) : [],\n }\n } catch {\n return { terminalTaskIds: [] }\n }\n}\n\nexport function saveTaskState(state: CachedTaskState, file?: string): void {\n const resolved = file ?? defaultTaskStatePath()\n mkdirSync(dirname(resolved), { recursive: true })\n writeFileSync(resolved, JSON.stringify({\n terminalTaskIds: state.terminalTaskIds ?? [],\n }, null, 2), 'utf-8')\n}\n\nexport function ensureDir(dir: string): void {\n mkdirSync(dir, { recursive: true })\n}\n\nexport function readBinaryFile(path: string): Buffer {\n return readFileSync(path)\n}\n\nexport function writeBinaryFile(path: string, content: Uint8Array | Buffer): void {\n mkdirSync(dirname(path), { recursive: true })\n writeFileSync(path, content)\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["baseUrl", "info", "readFileSync", "readFileSync"]
|
|
7
7
|
}
|