aamp-wechat-bridge 0.1.0

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.
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/index.ts", "../src/config.ts", "../../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/wechat-api.ts", "../src/runtime.ts"],
4
+ "sourcesContent": ["import readline from 'node:readline/promises'\nimport { stdin as input, stdout as output, argv, exit } from 'node:process'\nimport qrcodeTerminal from 'qrcode-terminal'\nimport {\n getBridgeHomeDir,\n initializeBridgeConfig,\n loadBridgeConfig,\n loadBridgeState,\n saveBridgeState,\n} from './config.js'\nimport {\n pollQrStatus,\n startQrLogin,\n type WechatQrStatus,\n} from './wechat-api.js'\nimport { WechatBridgeRuntime } from './runtime.js'\nimport type { BridgeConfig, BridgeState } from './types.js'\n\ninterface ParsedCliArgs {\n command: string\n configDir?: string\n options: Record<string, string | boolean>\n}\n\nfunction printUsage(): void {\n console.log([\n 'Usage: aamp-wechat-bridge <command> [options]',\n '',\n 'Commands:',\n ' init Create or update local bridge config and AAMP mailbox credentials',\n ' login Start QR login and persist the WeChat bot token locally',\n ' run Start the local WeChat bridge daemon',\n ' status Show local config, login state, and target agent information',\n '',\n 'Options:',\n ' --config-dir <path> Override bridge config directory',\n '',\n 'Examples:',\n ' aamp-wechat-bridge init',\n ' aamp-wechat-bridge login',\n ' aamp-wechat-bridge run',\n ].join('\\n'))\n}\n\nfunction parseCliArgs(rawArgs: string[]): ParsedCliArgs {\n let command = 'run'\n let commandAssigned = false\n let configDir: string | undefined\n const options: Record<string, string | boolean> = {}\n\n for (let index = 0; index < rawArgs.length; index += 1) {\n const token = rawArgs[index]\n if (!commandAssigned && !token.startsWith('-')) {\n command = token\n commandAssigned = true\n continue\n }\n\n if (token === '--config-dir') {\n const value = rawArgs[index + 1]\n if (!value) throw new Error('--config-dir requires a value')\n configDir = value\n index += 1\n continue\n }\n\n if (token.startsWith('--')) {\n const key = token.slice(2)\n const next = rawArgs[index + 1]\n if (!next || next.startsWith('--')) {\n options[key] = true\n continue\n }\n options[key] = next\n index += 1\n continue\n }\n }\n\n return { command, configDir, options }\n}\n\nasync function requireConfig(configDir?: string): Promise<BridgeConfig> {\n const config = await loadBridgeConfig(configDir)\n if (!config) {\n throw new Error(`Bridge config not found at ${getBridgeHomeDir(configDir)}/config.json. Run \\`aamp-wechat-bridge init\\` first.`)\n }\n return config\n}\n\nfunction printQrCode(url: string): void {\n qrcodeTerminal.generate(url, { small: true })\n console.log(`\u626B\u7801\u94FE\u63A5: ${url}`)\n}\n\nasync function promptVerifyCode(): Promise<string> {\n const rl = readline.createInterface({ input, output })\n try {\n const value = await rl.question('\u8BF7\u8F93\u5165\u5FAE\u4FE1\u8FD4\u56DE\u7684\u9A8C\u8BC1\u7801: ')\n return value.trim()\n } finally {\n rl.close()\n }\n}\n\nasync function waitForQrLogin(config: BridgeConfig, state: BridgeState): Promise<BridgeState> {\n const started = await startQrLogin({\n apiBaseUrl: config.wechat.apiBaseUrl,\n botType: config.wechat.botType,\n botAgent: config.wechat.botAgent,\n })\n\n console.log('\u8BF7\u4F7F\u7528\u5FAE\u4FE1\u626B\u7801\u767B\u5F55\u3002')\n printQrCode(started.qrCodeUrl)\n\n let currentBaseUrl = config.wechat.apiBaseUrl\n let pendingVerifyCode: string | undefined\n\n for (;;) {\n const status = await pollQrStatus({\n apiBaseUrl: currentBaseUrl,\n qrCode: started.qrCode,\n botAgent: config.wechat.botAgent,\n ...(pendingVerifyCode ? { verifyCode: pendingVerifyCode } : {}),\n })\n pendingVerifyCode = undefined\n\n if (status.status === 'wait') {\n continue\n }\n\n if (status.status === 'scaned') {\n console.log('\u4E8C\u7EF4\u7801\u5DF2\u626B\u63CF\uFF0C\u8BF7\u5728\u624B\u673A\u4E0A\u786E\u8BA4\u767B\u5F55\u3002')\n continue\n }\n\n if (status.status === 'scaned_but_redirect') {\n if (status.redirectHost) {\n currentBaseUrl = `https://${status.redirectHost.replace(/^https?:\\/\\//, '').replace(/\\/$/, '')}`\n }\n continue\n }\n\n if (status.status === 'need_verifycode') {\n pendingVerifyCode = await promptVerifyCode()\n continue\n }\n\n if (status.status === 'verify_code_blocked') {\n throw new Error('\u5FAE\u4FE1\u767B\u5F55\u9A8C\u8BC1\u5931\u8D25\u6B21\u6570\u8FC7\u591A\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C `aamp-wechat-bridge login`\u3002')\n }\n\n if (status.status === 'expired') {\n throw new Error('\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C `aamp-wechat-bridge login`\u3002')\n }\n\n if (status.status === 'binded_redirect') {\n console.log('\u8BE5\u5FAE\u4FE1\u8D26\u53F7\u5DF2\u7ECF\u7ED1\u5B9A\u5230\u5F53\u524D\u672C\u5730 bridge\uFF0C\u7EE7\u7EED\u590D\u7528\u73B0\u6709\u767B\u5F55\u6001\u3002')\n return state\n }\n\n if (status.status === 'confirmed') {\n if (!status.botToken) {\n throw new Error('\u5FAE\u4FE1\u767B\u5F55\u5DF2\u786E\u8BA4\uFF0C\u4F46\u6CA1\u6709\u8FD4\u56DE bot token\u3002')\n }\n const accountId = status.ilinkUserId?.trim() || 'default'\n state.account = {\n accountId,\n token: status.botToken,\n baseUrl: status.baseUrl?.trim() || currentBaseUrl,\n ilinkUserId: status.ilinkUserId?.trim() || undefined,\n connectedAt: new Date().toISOString(),\n }\n state.lastLoginAt = new Date().toISOString()\n return state\n }\n\n const exhaustive: never = status.status\n throw new Error(`Unexpected QR login state: ${exhaustive}`)\n }\n}\n\nasync function handleInit(configDir?: string, options: Record<string, string | boolean> = {}): Promise<void> {\n const config = await initializeBridgeConfig({\n configDir,\n aampHost: typeof options.aampHost === 'string' ? options.aampHost : undefined,\n targetAgentEmail: typeof options.targetAgentEmail === 'string' ? options.targetAgentEmail : undefined,\n slug: typeof options.slug === 'string' ? options.slug : undefined,\n summary: typeof options.summary === 'string' ? options.summary : undefined,\n botAgent: typeof options.botAgent === 'string' ? options.botAgent : undefined,\n dispatchTimeoutMs: typeof options.dispatchTimeoutMs === 'string' ? Number(options.dispatchTimeoutMs) : undefined,\n pollTimeoutMs: typeof options.pollTimeoutMs === 'string' ? Number(options.pollTimeoutMs) : undefined,\n })\n\n console.log(`Bridge config saved to ${getBridgeHomeDir(configDir)}/config.json`)\n console.log(`Mailbox: ${config.mailbox.email}`)\n console.log(`Target agent: ${config.targetAgentEmail}`)\n}\n\nasync function handleLogin(configDir?: string): Promise<void> {\n const config = await requireConfig(configDir)\n const state = await loadBridgeState(configDir)\n const nextState = await waitForQrLogin(config, state)\n await saveBridgeState(nextState, configDir)\n console.log(`\u5FAE\u4FE1\u767B\u5F55\u6210\u529F\uFF0C\u8D26\u53F7\u6807\u8BC6: ${nextState.account?.accountId ?? 'default'}`)\n}\n\nasync function handleRun(configDir?: string): Promise<void> {\n const config = await requireConfig(configDir)\n const state = await loadBridgeState(configDir)\n if (!state.account?.token) {\n throw new Error('\u5C1A\u672A\u767B\u5F55\u5FAE\u4FE1\uFF0C\u8BF7\u5148\u6267\u884C `aamp-wechat-bridge login`\u3002')\n }\n\n const runtime = new WechatBridgeRuntime(config, {\n configDir,\n logger: console,\n })\n\n const shutdown = async () => {\n await runtime.stop().catch(() => {})\n exit(0)\n }\n process.once('SIGINT', () => { void shutdown() })\n process.once('SIGTERM', () => { void shutdown() })\n\n console.log(`WeChat bridge is running for ${config.targetAgentEmail}`)\n console.log(`Mailbox: ${config.mailbox.email}`)\n await runtime.start()\n}\n\nasync function handleStatus(configDir?: string): Promise<void> {\n const config = await requireConfig(configDir)\n const state = await loadBridgeState(configDir)\n console.log([\n `Bridge home: ${getBridgeHomeDir(configDir)}`,\n `AAMP host: ${config.aampHost}`,\n `Target agent: ${config.targetAgentEmail}`,\n `Mailbox: ${config.mailbox.email}`,\n `WeChat API base: ${config.wechat.apiBaseUrl}`,\n `Bot agent: ${config.wechat.botAgent}`,\n `Logged in: ${state.account?.token ? 'yes' : 'no'}`,\n ...(state.account?.token ? [\n `WeChat account: ${state.account.accountId}`,\n `Login base URL: ${state.account.baseUrl}`,\n `Last login: ${state.lastLoginAt ?? state.account.connectedAt}`,\n ] : []),\n ].join('\\n'))\n}\n\nasync function main(): Promise<void> {\n const parsed = parseCliArgs(argv.slice(2))\n switch (parsed.command) {\n case 'help':\n case '--help':\n case '-h':\n printUsage()\n return\n case 'init':\n await handleInit(parsed.configDir, parsed.options)\n return\n case 'login':\n await handleLogin(parsed.configDir)\n return\n case 'run':\n await handleRun(parsed.configDir)\n return\n case 'status':\n await handleStatus(parsed.configDir)\n return\n default:\n throw new Error(`Unknown command: ${parsed.command}`)\n }\n}\n\nmain().catch((error: Error) => {\n console.error(error.message)\n exit(1)\n})\n", "import { existsSync } from 'node:fs'\nimport { mkdir, readFile, rename, writeFile } from 'node:fs/promises'\nimport os from 'node:os'\nimport path from 'node:path'\nimport readline from 'node:readline/promises'\nimport { randomUUID } from 'node:crypto'\nimport { stdin as input, stdout as output } from 'node:process'\nimport { AampClient } from 'aamp-sdk'\nimport type { BridgeConfig, BridgeMailboxIdentity, BridgeState } from './types.js'\n\nconst CONFIG_FILENAME = 'config.json'\nconst STATE_FILENAME = 'state.json'\n\nexport interface InitBridgeOptions {\n configDir?: string\n aampHost?: string\n targetAgentEmail?: string\n slug?: string\n summary?: string\n botAgent?: string\n dispatchTimeoutMs?: number\n pollTimeoutMs?: number\n}\n\nexport function getBridgeHomeDir(customDir?: string): string {\n return customDir\n ? path.resolve(customDir)\n : path.join(os.homedir(), '.aamp', 'wechat-bridge')\n}\n\nexport function getConfigPath(customDir?: string): string {\n return path.join(getBridgeHomeDir(customDir), CONFIG_FILENAME)\n}\n\nexport function getStatePath(customDir?: string): string {\n return path.join(getBridgeHomeDir(customDir), STATE_FILENAME)\n}\n\nexport async function ensureBridgeHomeDir(customDir?: string): Promise<string> {\n const dir = getBridgeHomeDir(customDir)\n await mkdir(dir, { recursive: true })\n return dir\n}\n\nasync function writeJsonAtomic(filePath: string, value: unknown): Promise<void> {\n const parentDir = path.dirname(filePath)\n await mkdir(parentDir, { recursive: true })\n const tempPath = path.join(parentDir, `.${path.basename(filePath)}.${randomUUID()}.tmp`)\n await writeFile(tempPath, `${JSON.stringify(value, null, 2)}\\n`, 'utf8')\n await rename(tempPath, filePath)\n}\n\nexport function createDefaultBridgeState(): BridgeState {\n return {\n version: 1,\n processedMessageIds: [],\n contextTokens: {},\n conversations: {},\n tasks: {},\n }\n}\n\nexport async function loadBridgeConfig(customDir?: string): Promise<BridgeConfig | null> {\n const filePath = getConfigPath(customDir)\n if (!existsSync(filePath)) return null\n const raw = await readFile(filePath, 'utf8')\n return JSON.parse(raw) as BridgeConfig\n}\n\nexport async function saveBridgeConfig(config: BridgeConfig, customDir?: string): Promise<void> {\n await writeJsonAtomic(getConfigPath(customDir), config)\n}\n\nexport async function loadBridgeState(customDir?: string): Promise<BridgeState> {\n const filePath = getStatePath(customDir)\n if (!existsSync(filePath)) return createDefaultBridgeState()\n const raw = await readFile(filePath, 'utf8')\n const parsed = JSON.parse(raw) as Partial<BridgeState>\n return {\n ...createDefaultBridgeState(),\n ...parsed,\n processedMessageIds: Array.isArray(parsed.processedMessageIds) ? parsed.processedMessageIds : [],\n contextTokens: parsed.contextTokens ?? {},\n conversations: parsed.conversations ?? {},\n tasks: parsed.tasks ?? {},\n }\n}\n\nexport async function saveBridgeState(state: BridgeState, customDir?: string): Promise<void> {\n await writeJsonAtomic(getStatePath(customDir), state)\n}\n\nfunction normalizeBaseUrl(url: string): string {\n if (url.startsWith('http://') || url.startsWith('https://')) return url.replace(/\\/$/, '')\n return `https://${url.replace(/\\/$/, '')}`\n}\n\nfunction normalizeSlug(rawValue: string): string {\n return rawValue\n .toLowerCase()\n .replace(/[\\s_]+/g, '-')\n .replace(/[^a-z0-9-]/g, '')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '')\n .slice(0, 32) || 'wechat-bridge'\n}\n\nasync function prompt(question: string, defaultValue = ''): Promise<string> {\n const rl = readline.createInterface({ input, output })\n try {\n const suffix = defaultValue ? ` (${defaultValue})` : ''\n const answer = await rl.question(`${question}${suffix}: `)\n return answer.trim() || defaultValue\n } finally {\n rl.close()\n }\n}\n\nfunction toMailboxIdentity(mailbox: BridgeMailboxIdentity | Awaited<ReturnType<typeof AampClient.registerMailbox>>): BridgeMailboxIdentity {\n return {\n email: mailbox.email,\n mailboxToken: mailbox.mailboxToken,\n smtpPassword: mailbox.smtpPassword,\n baseUrl: mailbox.baseUrl,\n }\n}\n\nexport async function initializeBridgeConfig(options: InitBridgeOptions): Promise<BridgeConfig> {\n const existing = await loadBridgeConfig(options.configDir)\n\n const aampHost = (options.aampHost ?? existing?.aampHost ?? await prompt('AAMP host', 'https://meshmail.ai')).trim()\n const targetAgentEmail = (options.targetAgentEmail ?? existing?.targetAgentEmail ?? await prompt('Target AAMP agent email')).trim()\n const slug = normalizeSlug(options.slug ?? existing?.slug ?? await prompt('Bridge mailbox slug', 'wechat-bridge'))\n const summary = (options.summary ?? existing?.summary ?? '').trim() || undefined\n const botAgent = (options.botAgent ?? existing?.wechat.botAgent ?? await prompt('WeChat bot agent', 'AAMP-WeChat-Bridge/0.1.0')).trim()\n const dispatchTimeoutMs = Math.max(1000, Math.trunc(options.dispatchTimeoutMs ?? existing?.behavior.dispatchTimeoutMs ?? 180000))\n const pollTimeoutMs = Math.max(5000, Math.trunc(options.pollTimeoutMs ?? existing?.behavior.pollTimeoutMs ?? 35000))\n\n if (!aampHost) throw new Error('AAMP host is required.')\n if (!targetAgentEmail) throw new Error('Target AAMP agent email is required.')\n\n const mailbox = existing?.mailbox ?? toMailboxIdentity(await AampClient.registerMailbox({\n aampHost,\n slug,\n description: `WeChat bridge for ${targetAgentEmail}`,\n }))\n\n const config: BridgeConfig = {\n version: 1,\n aampHost: normalizeBaseUrl(aampHost),\n targetAgentEmail,\n slug,\n ...(summary ? { summary } : {}),\n mailbox: toMailboxIdentity(mailbox),\n wechat: {\n apiBaseUrl: existing?.wechat.apiBaseUrl ?? 'https://ilinkai.weixin.qq.com',\n botType: existing?.wechat.botType ?? '3',\n botAgent: botAgent || 'AAMP-WeChat-Bridge/0.1.0',\n },\n behavior: {\n dispatchTimeoutMs,\n pollTimeoutMs,\n },\n }\n\n await ensureBridgeHomeDir(options.configDir)\n await saveBridgeConfig(config, options.configDir)\n return config\n}\n", "/**\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", "import crypto from 'node:crypto'\n\nconst DEFAULT_APP_ID = 'bot'\nconst DEFAULT_CHANNEL_VERSION = '0.1.0'\n\nexport interface WechatMessageItem {\n type?: number\n text_item?: {\n text?: string\n }\n voice_item?: {\n text?: string\n }\n file_item?: {\n file_name?: string\n }\n}\n\nexport interface WechatMessage {\n message_id?: number\n message_type?: number\n from_user_id?: string\n to_user_id?: string\n create_time_ms?: number\n session_id?: string\n group_id?: string\n item_list?: WechatMessageItem[]\n context_token?: string\n}\n\nexport interface WechatGetUpdatesResponse {\n ret?: number\n errcode?: number\n errmsg?: string\n msgs?: WechatMessage[]\n get_updates_buf?: string\n longpolling_timeout_ms?: number\n}\n\nexport type WechatQrStatus =\n | 'wait'\n | 'scaned'\n | 'confirmed'\n | 'expired'\n | 'scaned_but_redirect'\n | 'need_verifycode'\n | 'verify_code_blocked'\n | 'binded_redirect'\n\nexport interface WechatQrStartResult {\n qrCode: string\n qrCodeUrl: string\n}\n\nexport interface WechatQrStatusResult {\n status: WechatQrStatus\n botToken?: string\n ilinkUserId?: string\n baseUrl?: string\n redirectHost?: string\n}\n\nexport interface WechatApiCommonOptions {\n apiBaseUrl: string\n botAgent: string\n token?: string\n timeoutMs?: number\n}\n\nexport function normalizeWechatApiBaseUrl(url: string): string {\n if (url.startsWith('http://') || url.startsWith('https://')) return url.replace(/\\/$/, '')\n return `https://${url.replace(/\\/$/, '')}`\n}\n\nfunction buildClientVersion(version: string): number {\n const parts = version.split('.').map((part) => Number.parseInt(part, 10))\n const major = parts[0] ?? 0\n const minor = parts[1] ?? 0\n const patch = parts[2] ?? 0\n return ((major & 0xff) << 16) | ((minor & 0xff) << 8) | (patch & 0xff)\n}\n\nfunction sanitizeBotAgent(raw: string): string {\n const trimmed = raw.trim()\n if (!trimmed) return 'AAMP-WeChat-Bridge/0.1.0'\n return trimmed.slice(0, 256)\n}\n\nfunction buildBaseInfo(botAgent: string): Record<string, string> {\n return {\n channel_version: DEFAULT_CHANNEL_VERSION,\n bot_agent: sanitizeBotAgent(botAgent),\n }\n}\n\nfunction buildHeaders(token?: string): Record<string, string> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n AuthorizationType: 'ilink_bot_token',\n 'X-WECHAT-UIN': Buffer.from(String(crypto.randomBytes(4).readUInt32BE(0)), 'utf8').toString('base64'),\n 'iLink-App-Id': DEFAULT_APP_ID,\n 'iLink-App-ClientVersion': String(buildClientVersion(DEFAULT_CHANNEL_VERSION)),\n }\n if (token?.trim()) {\n headers.Authorization = `Bearer ${token.trim()}`\n }\n return headers\n}\n\nasync function postJson<T>(\n endpoint: string,\n body: unknown,\n opts: WechatApiCommonOptions,\n): Promise<T> {\n const controller = opts.timeoutMs ? new AbortController() : undefined\n const timeout = opts.timeoutMs\n ? setTimeout(() => controller?.abort(), opts.timeoutMs)\n : undefined\n try {\n const response = await fetch(`${normalizeWechatApiBaseUrl(opts.apiBaseUrl)}/${endpoint}`, {\n method: 'POST',\n headers: buildHeaders(opts.token),\n body: JSON.stringify(body),\n ...(controller ? { signal: controller.signal } : {}),\n })\n const text = await response.text()\n if (!response.ok) {\n throw new Error(`${endpoint} ${response.status}: ${text || response.statusText}`)\n }\n return JSON.parse(text) as T\n } finally {\n if (timeout) clearTimeout(timeout)\n }\n}\n\nasync function getJson<T>(\n endpoint: string,\n opts: WechatApiCommonOptions,\n): Promise<T> {\n const controller = opts.timeoutMs ? new AbortController() : undefined\n const timeout = opts.timeoutMs\n ? setTimeout(() => controller?.abort(), opts.timeoutMs)\n : undefined\n try {\n const response = await fetch(`${normalizeWechatApiBaseUrl(opts.apiBaseUrl)}/${endpoint}`, {\n method: 'GET',\n headers: buildHeaders(opts.token),\n ...(controller ? { signal: controller.signal } : {}),\n })\n const text = await response.text()\n if (!response.ok) {\n throw new Error(`${endpoint} ${response.status}: ${text || response.statusText}`)\n }\n return JSON.parse(text) as T\n } finally {\n if (timeout) clearTimeout(timeout)\n }\n}\n\nexport async function startQrLogin(opts: {\n apiBaseUrl: string\n botType: string\n botAgent: string\n}): Promise<WechatQrStartResult> {\n const response = await postJson<{\n qrcode?: string\n qrcode_img_content?: string\n }>(\n `ilink/bot/get_bot_qrcode?bot_type=${encodeURIComponent(opts.botType)}`,\n {\n local_token_list: [],\n base_info: buildBaseInfo(opts.botAgent),\n },\n { apiBaseUrl: opts.apiBaseUrl, botAgent: opts.botAgent, timeoutMs: 15000 },\n )\n\n if (!response.qrcode || !response.qrcode_img_content) {\n throw new Error('\u5FAE\u4FE1\u767B\u5F55\u4E8C\u7EF4\u7801\u83B7\u53D6\u5931\u8D25\u3002')\n }\n\n return {\n qrCode: response.qrcode,\n qrCodeUrl: response.qrcode_img_content,\n }\n}\n\nexport async function pollQrStatus(opts: {\n apiBaseUrl: string\n qrCode: string\n botAgent: string\n verifyCode?: string\n}): Promise<WechatQrStatusResult> {\n const query = new URLSearchParams({ qrcode: opts.qrCode })\n if (opts.verifyCode) query.set('verify_code', opts.verifyCode)\n const response = await getJson<{\n status?: WechatQrStatus\n bot_token?: string\n ilink_user_id?: string\n baseurl?: string\n redirect_host?: string\n }>(`ilink/bot/get_qrcode_status?${query.toString()}`, {\n apiBaseUrl: opts.apiBaseUrl,\n botAgent: opts.botAgent,\n timeoutMs: 35000,\n })\n\n return {\n status: response.status ?? 'wait',\n botToken: response.bot_token,\n ilinkUserId: response.ilink_user_id,\n baseUrl: response.baseurl ? normalizeWechatApiBaseUrl(response.baseurl) : undefined,\n redirectHost: response.redirect_host,\n }\n}\n\nexport async function getUpdates(opts: WechatApiCommonOptions & {\n syncCursor?: string\n}): Promise<WechatGetUpdatesResponse> {\n try {\n return await postJson<WechatGetUpdatesResponse>(\n 'ilink/bot/getupdates',\n {\n get_updates_buf: opts.syncCursor ?? '',\n base_info: buildBaseInfo(opts.botAgent),\n },\n opts,\n )\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n return {\n ret: 0,\n msgs: [],\n get_updates_buf: opts.syncCursor,\n }\n }\n throw error\n }\n}\n\nexport async function sendTextMessage(opts: WechatApiCommonOptions & {\n toUserId: string\n text: string\n contextToken?: string\n}): Promise<void> {\n await postJson(\n 'ilink/bot/sendmessage',\n {\n msg: {\n from_user_id: '',\n to_user_id: opts.toUserId,\n client_id: crypto.randomUUID(),\n message_type: 2,\n message_state: 2,\n item_list: opts.text\n ? [{ type: 1, text_item: { text: opts.text } }]\n : undefined,\n context_token: opts.contextToken ?? undefined,\n },\n base_info: buildBaseInfo(opts.botAgent),\n },\n opts,\n )\n}\n\nexport async function getTypingTicket(opts: WechatApiCommonOptions & {\n ilinkUserId: string\n contextToken?: string\n}): Promise<string | undefined> {\n const response = await postJson<{\n ret?: number\n errmsg?: string\n typing_ticket?: string\n }>(\n 'ilink/bot/getconfig',\n {\n ilink_user_id: opts.ilinkUserId,\n context_token: opts.contextToken ?? undefined,\n base_info: buildBaseInfo(opts.botAgent),\n },\n opts,\n )\n if (response.ret && response.ret !== 0) return undefined\n return response.typing_ticket\n}\n\nexport async function sendTypingStatus(opts: WechatApiCommonOptions & {\n ilinkUserId: string\n typingTicket: string\n status: 'typing' | 'cancel'\n}): Promise<void> {\n await postJson(\n 'ilink/bot/sendtyping',\n {\n ilink_user_id: opts.ilinkUserId,\n typing_ticket: opts.typingTicket,\n status: opts.status === 'typing' ? 1 : 2,\n base_info: buildBaseInfo(opts.botAgent),\n },\n opts,\n )\n}\n\nexport async function notifyStart(opts: WechatApiCommonOptions): Promise<void> {\n await postJson(\n 'ilink/bot/msg/notifystart',\n { base_info: buildBaseInfo(opts.botAgent) },\n opts,\n )\n}\n\nexport async function notifyStop(opts: WechatApiCommonOptions): Promise<void> {\n await postJson(\n 'ilink/bot/msg/notifystop',\n { base_info: buildBaseInfo(opts.botAgent) },\n opts,\n )\n}\n", "import { randomUUID } from 'node:crypto'\nimport {\n AampClient,\n type AampAttachment,\n type AampStreamEvent,\n type StreamSubscription,\n type TaskAck,\n type TaskHelp,\n type TaskResult,\n type TaskStreamOpened,\n} from 'aamp-sdk'\nimport {\n createDefaultBridgeState,\n loadBridgeState,\n saveBridgeState,\n} from './config.js'\nimport {\n getTypingTicket,\n getUpdates,\n notifyStart,\n notifyStop,\n sendTextMessage,\n sendTypingStatus,\n type WechatMessage,\n type WechatMessageItem,\n} from './wechat-api.js'\nimport type {\n BridgeConfig,\n BridgeState,\n BridgeTaskState,\n} from './types.js'\n\ninterface WechatBridgeRuntimeOptions {\n configDir?: string\n logger?: Pick<Console, 'log' | 'error'>\n}\n\nconst MAX_PROCESSED_MESSAGE_IDS = 200\n\nexport class WechatBridgeRuntime {\n private readonly aamp: AampClient\n private readonly config: BridgeConfig\n private readonly configDir?: string\n private readonly logger: Pick<Console, 'log' | 'error'>\n private readonly activeStreamSubscriptions = new Map<string, StreamSubscription>()\n private readonly liveTaskIds = new Set<string>()\n private readonly typingTickets = new Map<string, string>()\n private state: BridgeState = createDefaultBridgeState()\n private stopping = false\n private pollLoopPromise?: Promise<void>\n\n constructor(config: BridgeConfig, options: WechatBridgeRuntimeOptions = {}) {\n this.config = config\n this.configDir = options.configDir\n this.logger = options.logger ?? console\n this.aamp = new AampClient({\n email: config.mailbox.email,\n mailboxToken: config.mailbox.mailboxToken,\n smtpPassword: config.mailbox.smtpPassword,\n baseUrl: config.mailbox.baseUrl,\n })\n }\n\n async start(): Promise<void> {\n this.state = await loadBridgeState(this.configDir)\n if (!this.state.account?.token) {\n throw new Error('\u5C1A\u672A\u767B\u5F55\u5FAE\u4FE1\uFF0C\u8BF7\u5148\u6267\u884C `aamp-wechat-bridge login`\u3002')\n }\n this.state.tasks = {}\n this.state.lastStartedAt = new Date().toISOString()\n this.state.lastError = undefined\n await this.persistState()\n\n this.registerAampHandlers()\n await this.aamp.connect()\n await notifyStart({\n apiBaseUrl: this.state.account.baseUrl,\n token: this.state.account.token,\n botAgent: this.config.wechat.botAgent,\n timeoutMs: 10000,\n }).catch(() => {})\n\n this.pollLoopPromise = this.pollLoop()\n await this.pollLoopPromise\n }\n\n async stop(): Promise<void> {\n if (this.stopping) return\n this.stopping = true\n\n for (const subscription of this.activeStreamSubscriptions.values()) {\n subscription.close()\n }\n this.activeStreamSubscriptions.clear()\n this.liveTaskIds.clear()\n\n if (this.state.account?.token) {\n await notifyStop({\n apiBaseUrl: this.state.account.baseUrl,\n token: this.state.account.token,\n botAgent: this.config.wechat.botAgent,\n timeoutMs: 10000,\n }).catch(() => {})\n }\n\n this.aamp.disconnect()\n this.state.lastStoppedAt = new Date().toISOString()\n await this.persistState()\n }\n\n private registerAampHandlers(): void {\n this.aamp.on('task.ack', (task) => {\n void this.handleTaskAck(task)\n })\n this.aamp.on('task.stream.opened', (task) => {\n void this.handleTaskStreamOpened(task)\n })\n this.aamp.on('task.result', (task) => {\n void this.handleTaskResult(task)\n })\n this.aamp.on('task.help_needed', (task) => {\n void this.handleTaskHelp(task)\n })\n this.aamp.on('error', (error) => {\n this.state.lastError = error.message\n this.logger.error(`[aamp] ${error.message}`)\n void this.persistState()\n })\n }\n\n private async pollLoop(): Promise<void> {\n while (!this.stopping) {\n try {\n await this.pollOnce()\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n this.state.lastError = message\n this.logger.error(`[wechat] ${message}`)\n await this.persistState()\n if (message.includes('session timeout') || message.includes('errcode=-14')) {\n throw error\n }\n await new Promise((resolve) => setTimeout(resolve, 3000))\n }\n }\n }\n\n private async pollOnce(): Promise<void> {\n if (!this.state.account?.token) return\n const response = await getUpdates({\n apiBaseUrl: this.state.account.baseUrl,\n token: this.state.account.token,\n botAgent: this.config.wechat.botAgent,\n timeoutMs: this.config.behavior.pollTimeoutMs,\n syncCursor: this.state.syncCursor,\n })\n\n if (response.errcode === -14) {\n throw new Error('WeChat session timeout (errcode=-14). Please run `aamp-wechat-bridge login` again.')\n }\n if (response.ret && response.ret !== 0) {\n throw new Error(`WeChat getupdates failed: errcode=${response.errcode ?? response.ret} ${response.errmsg ?? ''}`.trim())\n }\n\n if (response.get_updates_buf && response.get_updates_buf !== this.state.syncCursor) {\n this.state.syncCursor = response.get_updates_buf\n await this.persistState()\n }\n\n for (const message of response.msgs ?? []) {\n await this.handleInboundWechatMessage(message)\n }\n }\n\n private async handleInboundWechatMessage(message: WechatMessage): Promise<void> {\n if (message.group_id) return\n if (message.message_type === 2) return\n const senderId = message.from_user_id?.trim()\n if (!senderId) return\n\n const messageKey = String(message.message_id ?? '')\n if (messageKey && this.state.processedMessageIds.includes(messageKey)) {\n return\n }\n\n const text = this.extractMessageText(message.item_list ?? [])\n const mediaNote = this.extractMediaNote(message.item_list ?? [])\n const body = [text, mediaNote].filter(Boolean).join('\\n\\n').trim()\n if (!body) return\n\n const taskId = randomUUID()\n const sessionKey = this.buildSessionKey(senderId)\n const contextToken = message.context_token?.trim() || undefined\n const now = new Date().toISOString()\n\n this.liveTaskIds.add(taskId)\n this.state.tasks[taskId] = {\n taskId,\n senderId,\n sessionKey,\n ...(contextToken ? { contextToken } : {}),\n status: 'received',\n createdAt: now,\n updatedAt: now,\n }\n this.state.conversations[sessionKey] = {\n senderId,\n sessionKey,\n lastTaskId: taskId,\n ...(contextToken ? { lastContextToken: contextToken } : {}),\n updatedAt: now,\n }\n if (contextToken) {\n this.state.contextTokens[senderId] = contextToken\n }\n if (messageKey) {\n this.rememberProcessedMessageId(messageKey)\n }\n await this.persistState()\n\n await this.aamp.sendTask({\n to: this.config.targetAgentEmail,\n taskId,\n sessionKey,\n title: `WeChat DM from ${senderId}`,\n bodyText: body,\n dispatchContext: {\n source: 'wechat',\n wechat_account_id: this.state.account?.accountId ?? 'default',\n wechat_sender_id: senderId,\n ...(contextToken ? { wechat_context_token: contextToken } : {}),\n ...(message.session_id ? { wechat_session_id: message.session_id } : {}),\n ...(message.message_id != null ? { wechat_message_id: String(message.message_id) } : {}),\n },\n })\n }\n\n private extractMessageText(items: WechatMessageItem[]): string {\n const parts: string[] = []\n for (const item of items) {\n const text = item.text_item?.text?.trim()\n if (text) parts.push(text)\n const voiceText = item.voice_item?.text?.trim()\n if (voiceText) parts.push(voiceText)\n }\n return parts.join('\\n').trim()\n }\n\n private extractMediaNote(items: WechatMessageItem[]): string {\n const labels: string[] = []\n for (const item of items) {\n if (item.type === 2) labels.push('image')\n if (item.type === 3) labels.push('voice')\n if (item.type === 4) labels.push(`file${item.file_item?.file_name ? ` (${item.file_item.file_name})` : ''}`)\n if (item.type === 5) labels.push('video')\n }\n if (labels.length === 0) return ''\n return `User also sent WeChat media: ${labels.join(', ')}. Native media relay is not implemented yet, so please answer based on the textual context only.`\n }\n\n private buildSessionKey(senderId: string): string {\n return `wechat:${this.state.account?.accountId ?? 'default'}:${senderId}`\n }\n\n private rememberProcessedMessageId(messageId: string): void {\n this.state.processedMessageIds.push(messageId)\n if (this.state.processedMessageIds.length > MAX_PROCESSED_MESSAGE_IDS) {\n this.state.processedMessageIds.splice(0, this.state.processedMessageIds.length - MAX_PROCESSED_MESSAGE_IDS)\n }\n }\n\n private async handleTaskAck(task: TaskAck): Promise<void> {\n const state = this.state.tasks[task.taskId]\n if (!state || !this.liveTaskIds.has(task.taskId)) return\n state.status = 'pending'\n state.updatedAt = new Date().toISOString()\n await this.ensureTyping(state, 'typing')\n await this.persistState()\n }\n\n private async handleTaskStreamOpened(task: TaskStreamOpened): Promise<void> {\n const state = this.state.tasks[task.taskId]\n if (!state || !this.liveTaskIds.has(task.taskId)) return\n state.status = 'streaming'\n state.streamId = task.streamId\n state.updatedAt = new Date().toISOString()\n await this.subscribeToTaskStream(state)\n await this.persistState()\n }\n\n private async subscribeToTaskStream(task: BridgeTaskState): Promise<void> {\n if (!task.streamId || this.activeStreamSubscriptions.has(task.taskId)) return\n const subscription = await this.aamp.subscribeStream(\n task.streamId,\n {\n onEvent: (event) => {\n void this.handleStreamEvent(task.taskId, event)\n },\n onError: (error) => {\n this.logger.error(`[stream ${task.taskId}] ${error.message}`)\n },\n },\n )\n this.activeStreamSubscriptions.set(task.taskId, subscription)\n }\n\n private async handleStreamEvent(taskId: string, event: AampStreamEvent): Promise<void> {\n const state = this.state.tasks[taskId]\n if (!state || !this.liveTaskIds.has(taskId)) return\n if (event.type === 'text.delta') {\n state.streamText = (state.streamText ?? '') + String(event.payload.text ?? '')\n state.status = 'streaming'\n state.updatedAt = new Date().toISOString()\n await this.persistState()\n return\n }\n if (event.type === 'error') {\n state.resultError = String(event.payload.message ?? event.payload.error ?? 'Unknown stream error')\n state.updatedAt = new Date().toISOString()\n await this.persistState()\n }\n }\n\n private async handleTaskResult(task: TaskResult): Promise<void> {\n const state = this.state.tasks[task.taskId]\n if (!state || !this.liveTaskIds.has(task.taskId)) return\n state.status = task.status === 'completed' ? 'completed' : 'rejected'\n state.outputText = task.output || state.streamText || state.outputText\n state.resultError = task.errorMsg\n state.updatedAt = new Date().toISOString()\n this.closeActiveStream(task.taskId)\n await this.ensureTyping(state, 'cancel')\n await this.replyToWechat(state, this.buildReplyTextFromResult(task, state))\n this.finishTask(task.taskId)\n }\n\n private async handleTaskHelp(task: TaskHelp): Promise<void> {\n const state = this.state.tasks[task.taskId]\n if (!state || !this.liveTaskIds.has(task.taskId)) return\n state.status = 'help_needed'\n state.updatedAt = new Date().toISOString()\n this.closeActiveStream(task.taskId)\n await this.ensureTyping(state, 'cancel')\n await this.replyToWechat(state, this.buildReplyTextFromHelp(task))\n this.finishTask(task.taskId)\n }\n\n private buildReplyTextFromResult(task: TaskResult, state: BridgeTaskState): string {\n const body = (task.output || state.streamText || '').trim()\n const base = body\n || (task.status === 'rejected' ? '\u5F53\u524D\u8BF7\u6C42\u88AB\u76EE\u6807 Agent \u62D2\u7EDD\u4E86\u3002' : '\u5DF2\u7ECF\u5904\u7406\u5B8C\u6210\u3002')\n const attachmentLines = (task.attachments ?? []).map((attachment: AampAttachment) => `- ${attachment.filename} (${attachment.size} bytes)`)\n const senderPolicyHint = this.buildSenderPolicyHint(task.errorMsg, state)\n return [\n base,\n ...(attachmentLines.length ? ['', '\u8FD4\u56DE\u4E2D\u8FD8\u5305\u542B\u9644\u4EF6\uFF0C\u76EE\u524D\u5FAE\u4FE1 bridge \u5148\u53EA\u63D0\u793A\u6587\u4EF6\u540D\uFF1A', ...attachmentLines] : []),\n ...(senderPolicyHint ? ['', senderPolicyHint] : []),\n ].join('\\n')\n }\n\n private buildReplyTextFromHelp(task: TaskHelp): string {\n return [\n task.question.trim() || '\u6211\u8FD8\u9700\u8981\u4E00\u4E9B\u4FE1\u606F\u624D\u80FD\u7EE7\u7EED\u3002',\n ...(task.blockedReason?.trim() ? ['', `\u539F\u56E0\uFF1A${task.blockedReason.trim()}`] : []),\n ...(task.suggestedOptions?.length ? ['', '\u4F60\u53EF\u4EE5\u8FD9\u6837\u8865\u5145\uFF1A', ...task.suggestedOptions.map((item) => `- ${item}`)] : []),\n ].join('\\n')\n }\n\n private buildSenderPolicyHint(errorMsg: string | undefined, state: BridgeTaskState): string {\n if (!errorMsg?.includes('senderPolicies')) return ''\n return [\n '\u76EE\u6807 Agent \u5F53\u524D\u6CA1\u6709\u653E\u884C\u8FD9\u4E2A\u5FAE\u4FE1\u6865\u3002',\n '\u8BF7\u5728 target agent \u7684 senderPolicies \u4E2D\u5141\u8BB8\u5F53\u524D bridge \u90AE\u7BB1\uFF0C\u5E76\u628A `wechat_sender_id` \u4F5C\u4E3A dispatchContext \u767D\u540D\u5355\u6761\u4EF6\u3002',\n '',\n '\u793A\u4F8B\uFF1A',\n '[',\n ` {\"sender\":\"${this.config.mailbox.email}\",\"dispatchContextRules\":{\"wechat_sender_id\":[\"${state.senderId}\"]}}`,\n ']',\n ].join('\\n')\n }\n\n private async replyToWechat(task: BridgeTaskState, text: string): Promise<void> {\n if (!this.state.account?.token) return\n await sendTextMessage({\n apiBaseUrl: this.state.account.baseUrl,\n token: this.state.account.token,\n botAgent: this.config.wechat.botAgent,\n timeoutMs: 15000,\n toUserId: task.senderId,\n text,\n contextToken: task.contextToken ?? this.state.contextTokens[task.senderId],\n })\n }\n\n private async ensureTyping(task: BridgeTaskState, status: 'typing' | 'cancel'): Promise<void> {\n if (!this.state.account?.token) return\n const cachedTicket = this.typingTickets.get(task.senderId)\n const ticket = cachedTicket || await getTypingTicket({\n apiBaseUrl: this.state.account.baseUrl,\n token: this.state.account.token,\n botAgent: this.config.wechat.botAgent,\n timeoutMs: 10000,\n ilinkUserId: task.senderId,\n contextToken: task.contextToken ?? this.state.contextTokens[task.senderId],\n }).catch(() => undefined)\n if (!ticket) return\n this.typingTickets.set(task.senderId, ticket)\n await sendTypingStatus({\n apiBaseUrl: this.state.account.baseUrl,\n token: this.state.account.token,\n botAgent: this.config.wechat.botAgent,\n timeoutMs: 10000,\n ilinkUserId: task.senderId,\n typingTicket: ticket,\n status,\n }).catch(() => {})\n task.typingActive = status === 'typing'\n }\n\n private closeActiveStream(taskId: string): void {\n const subscription = this.activeStreamSubscriptions.get(taskId)\n if (!subscription) return\n subscription.close()\n this.activeStreamSubscriptions.delete(taskId)\n }\n\n private finishTask(taskId: string): void {\n this.liveTaskIds.delete(taskId)\n delete this.state.tasks[taskId]\n void this.persistState()\n }\n\n private async persistState(): Promise<void> {\n await saveBridgeState(this.state, this.configDir)\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["readline", "input", "output", "randomUUID", "output", "info", "output", "input", "randomUUID", "randomUUID", "randomUUID", "readline", "input", "output"]
7
+ }