@agent-native/core 0.7.46 → 0.7.47

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.
@@ -12,7 +12,9 @@ export declare class A2ATaskTimeoutError extends Error {
12
12
  * Uses A2A_SECRET as an HMAC key. The token contains the caller's email
13
13
  * as `sub`, so the receiving app can verify who's calling.
14
14
  */
15
- export declare function signA2AToken(email: string, orgDomain?: string, orgSecret?: string): Promise<string>;
15
+ export declare function signA2AToken(email: string, orgDomain?: string, orgSecret?: string, options?: {
16
+ expiresIn?: string | number;
17
+ }): Promise<string>;
16
18
  export declare class A2AClient {
17
19
  private baseUrl;
18
20
  private apiKey?;
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/a2a/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/a2a/client.ts"],"names":[],"mappings":"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"}
@@ -20,7 +20,7 @@ export class A2ATaskTimeoutError extends Error {
20
20
  * Uses A2A_SECRET as an HMAC key. The token contains the caller's email
21
21
  * as `sub`, so the receiving app can verify who's calling.
22
22
  */
23
- export async function signA2AToken(email, orgDomain, orgSecret) {
23
+ export async function signA2AToken(email, orgDomain, orgSecret, options) {
24
24
  const secret = orgSecret || process.env.A2A_SECRET;
25
25
  if (!secret) {
26
26
  throw new Error("No A2A secret available. Set an org-level A2A secret in Team settings, " +
@@ -36,7 +36,7 @@ export async function signA2AToken(email, orgDomain, orgSecret) {
36
36
  .setProtectedHeader({ alg: "HS256" })
37
37
  .setIssuer(appUrl)
38
38
  .setIssuedAt()
39
- .setExpirationTime("15m")
39
+ .setExpirationTime(options?.expiresIn ?? "15m")
40
40
  .sign(new TextEncoder().encode(secret));
41
41
  }
42
42
  export class A2AClient {
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/a2a/client.ts"],"names":[],"mappings":"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","sourcesContent":["import * as jose from \"jose\";\nimport type {\n AgentCard,\n JsonRpcRequest,\n JsonRpcResponse,\n Message,\n Task,\n} from \"./types.js\";\n\nexport class A2ATaskTimeoutError extends Error {\n readonly taskId: string;\n readonly lastTask: Task;\n readonly lastState: string;\n readonly timeoutMs: number;\n\n constructor(taskId: string, lastTask: Task, timeoutMs: number) {\n const lastState = lastTask.status.state;\n super(\n `A2A task ${taskId} did not complete within ${timeoutMs}ms (last state: ${lastState})`,\n );\n this.name = \"A2ATaskTimeoutError\";\n this.taskId = taskId;\n this.lastTask = lastTask;\n this.lastState = lastState;\n this.timeoutMs = timeoutMs;\n }\n}\n\n/**\n * Sign a JWT for A2A cross-app identity verification.\n *\n * Uses A2A_SECRET as an HMAC key. The token contains the caller's email\n * as `sub`, so the receiving app can verify who's calling.\n */\nexport async function signA2AToken(\n email: string,\n orgDomain?: string,\n orgSecret?: string,\n): Promise<string> {\n const secret = orgSecret || process.env.A2A_SECRET;\n if (!secret) {\n throw new Error(\n \"No A2A secret available. Set an org-level A2A secret in Team settings, \" +\n \"or set A2A_SECRET as an environment variable on all apps that need to verify identity.\",\n );\n }\n\n const appUrl =\n process.env.APP_URL ||\n process.env.BETTER_AUTH_URL ||\n \"http://localhost:3000\";\n\n return new jose.SignJWT({\n sub: email,\n ...(orgDomain ? { org_domain: orgDomain } : {}),\n })\n .setProtectedHeader({ alg: \"HS256\" })\n .setIssuer(appUrl)\n .setIssuedAt()\n .setExpirationTime(\"15m\")\n .sign(new TextEncoder().encode(secret));\n}\n\nexport class A2AClient {\n private baseUrl: string;\n private apiKey?: string;\n private endpointCandidates: string[] = [];\n private endpointResolved = false;\n private requestTimeoutMs?: number;\n\n constructor(\n baseUrl: string,\n apiKey?: string,\n options?: { requestTimeoutMs?: number },\n ) {\n const normalized = baseUrl.replace(/\\/$/, \"\");\n const explicitEndpoint = splitExplicitA2AEndpoint(normalized);\n this.baseUrl = explicitEndpoint?.baseUrl ?? normalized;\n if (explicitEndpoint) {\n this.endpointCandidates = [explicitEndpoint.endpointUrl];\n this.endpointResolved = true;\n }\n this.apiKey = apiKey;\n this.requestTimeoutMs = options?.requestTimeoutMs;\n }\n\n /**\n * Detect which A2A path the target agent uses.\n * Agent-native apps use /_agent-native/a2a, external agents may use /a2a.\n */\n async resolveEndpoint(): Promise<void> {\n await this.ensureEndpointCandidates();\n if (this.endpointCandidates.length <= 1) return;\n\n for (const endpoint of this.endpointCandidates) {\n try {\n const res = await fetch(endpoint, { method: \"OPTIONS\" });\n if (res.status !== 404 && res.status !== 405) {\n this.endpointCandidates = [endpoint];\n return;\n }\n if (res.status === 405) {\n this.endpointCandidates = [endpoint];\n return;\n }\n } catch {\n // Try the next candidate.\n }\n }\n }\n\n private headers(): Record<string, string> {\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (this.apiKey) {\n h[\"Authorization\"] = `Bearer ${this.apiKey}`;\n }\n return h;\n }\n\n private async rpc(\n method: string,\n params: Record<string, unknown>,\n ): Promise<JsonRpcResponse> {\n const body: JsonRpcRequest = {\n jsonrpc: \"2.0\",\n id: Date.now(),\n method,\n params,\n };\n\n await this.ensureEndpointCandidates();\n let lastError: Error | null = null;\n\n for (const url of this.endpointCandidates) {\n console.log(`[A2A Client] POST ${url} method=${method}`);\n const startTime = Date.now();\n const res = await this.postJson(url, body);\n console.log(\n `[A2A Client] Response: ${res.status} in ${Date.now() - startTime}ms`,\n );\n\n if (res.ok) {\n this.endpointCandidates = [url];\n return res.json() as Promise<JsonRpcResponse>;\n }\n\n const text = await res.text();\n lastError = new Error(`A2A request failed (${res.status}): ${text}`);\n if (!shouldTryNextEndpoint(res.status)) {\n throw lastError;\n }\n }\n\n throw lastError ?? new Error(\"No A2A endpoint candidates available\");\n }\n\n async getAgentCard(): Promise<AgentCard> {\n const res = await fetch(`${this.baseUrl}/.well-known/agent-card.json`);\n if (!res.ok) {\n throw new Error(`Failed to fetch agent card (${res.status})`);\n }\n return res.json() as Promise<AgentCard>;\n }\n\n async send(\n message: Message,\n opts?: {\n contextId?: string;\n metadata?: Record<string, unknown>;\n /**\n * If true, ask the server to return the task immediately in `working`\n * state and process the handler in the background. The caller should\n * then poll `getTask(taskId)` until `completed` / `failed` / `canceled`.\n *\n * Use this when you expect the handler may exceed a synchronous\n * serverless request budget.\n */\n async?: boolean;\n },\n ): Promise<Task> {\n const response = await this.rpc(\"message/send\", {\n message,\n contextId: opts?.contextId,\n metadata: opts?.metadata,\n ...(opts?.async ? { async: true } : {}),\n });\n\n if (response.error) {\n throw new Error(\n `A2A error (${response.error.code}): ${response.error.message}`,\n );\n }\n\n return response.result as Task;\n }\n\n /**\n * Poll for a task by id. Used in async mode after `send({ async: true })`.\n */\n async getTask(taskId: string): Promise<Task> {\n const response = await this.rpc(\"tasks/get\", { id: taskId });\n if (response.error) {\n throw new Error(\n `A2A error (${response.error.code}): ${response.error.message}`,\n );\n }\n return response.result as Task;\n }\n\n /**\n * Send a message in async mode and poll until the task reaches a terminal\n * state. This is the recommended path on serverless hosts with short\n * function timeouts (Netlify, Vercel) where a synchronous LLM-driven A2A\n * call can exceed the gateway limit.\n *\n * Each individual fetch returns quickly; long-running work happens on the\n * receiving side and is checked via `tasks/get`.\n */\n async sendAndWait(\n message: Message,\n opts?: {\n contextId?: string;\n metadata?: Record<string, unknown>;\n /** Total time to wait for completion. Default 5 min. */\n timeoutMs?: number;\n /** Poll interval. Default 2s. */\n pollIntervalMs?: number;\n /** Called with each polled task — useful for surfacing progress. */\n onUpdate?: (task: Task) => void;\n },\n ): Promise<Task> {\n const submitted = await this.send(message, {\n contextId: opts?.contextId,\n metadata: opts?.metadata,\n async: true,\n });\n\n const terminalStates = new Set([\"completed\", \"failed\", \"canceled\"]);\n if (terminalStates.has(submitted.status.state)) return submitted;\n\n const timeoutMs = opts?.timeoutMs ?? 5 * 60_000;\n const pollMs = opts?.pollIntervalMs ?? 2_000;\n const deadline = Date.now() + timeoutMs;\n\n let current = submitted;\n while (Date.now() < deadline) {\n await new Promise((r) => setTimeout(r, pollMs));\n try {\n current = await this.getTask(submitted.id);\n opts?.onUpdate?.(current);\n } catch (err) {\n // Transient fetch failure — keep polling until the deadline.\n continue;\n }\n if (terminalStates.has(current.status.state)) return current;\n }\n throw new A2ATaskTimeoutError(submitted.id, current, timeoutMs);\n }\n\n async *stream(\n message: Message,\n opts?: { contextId?: string; metadata?: Record<string, unknown> },\n ): AsyncGenerator<Task> {\n const body: JsonRpcRequest = {\n jsonrpc: \"2.0\",\n id: Date.now(),\n method: \"message/stream\",\n params: {\n message,\n contextId: opts?.contextId,\n metadata: opts?.metadata,\n },\n };\n\n await this.ensureEndpointCandidates();\n let res: Response | null = null;\n let lastError: Error | null = null;\n for (const candidate of this.endpointCandidates) {\n res = await this.postJson(candidate, body);\n if (res.ok) {\n this.endpointCandidates = [candidate];\n break;\n }\n const text = await res.text();\n lastError = new Error(`A2A stream failed (${res.status}): ${text}`);\n if (!shouldTryNextEndpoint(res.status)) throw lastError;\n }\n if (!res?.ok) {\n throw lastError ?? new Error(\"No A2A endpoint candidates available\");\n }\n\n const reader = res.body?.getReader();\n if (!reader) throw new Error(\"No response body\");\n\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n for (const line of lines) {\n if (!line.startsWith(\"data: \")) continue;\n const json = line.slice(6).trim();\n if (!json) continue;\n\n const response: JsonRpcResponse = JSON.parse(json);\n if (response.error) {\n throw new Error(\n `A2A error (${response.error.code}): ${response.error.message}`,\n );\n }\n if (response.result) {\n yield response.result as Task;\n }\n }\n }\n }\n\n private async ensureEndpointCandidates(): Promise<void> {\n if (this.endpointResolved) return;\n this.endpointResolved = true;\n\n const candidates: string[] = [];\n addDefaultEndpointCandidates(candidates, this.baseUrl);\n\n try {\n const card = await this.getAgentCard();\n const cardUrl = normalizeUrl(card.url, this.baseUrl);\n if (cardUrl) {\n const explicitEndpoint = splitExplicitA2AEndpoint(cardUrl);\n if (explicitEndpoint) {\n candidates.unshift(explicitEndpoint.endpointUrl);\n } else {\n addDefaultEndpointCandidates(candidates, cardUrl);\n }\n }\n } catch {\n // Agent cards are discovery hints. Fall back to conventional endpoints.\n }\n\n this.endpointCandidates = unique(candidates);\n }\n\n private async postJson(url: string, body: JsonRpcRequest): Promise<Response> {\n const controller = this.requestTimeoutMs\n ? new AbortController()\n : undefined;\n const timer =\n controller && this.requestTimeoutMs\n ? setTimeout(() => controller.abort(), this.requestTimeoutMs)\n : undefined;\n try {\n return await fetch(url, {\n method: \"POST\",\n headers: this.headers(),\n body: JSON.stringify(body),\n signal: controller?.signal,\n });\n } finally {\n if (timer) clearTimeout(timer);\n }\n }\n}\n\nfunction splitExplicitA2AEndpoint(\n url: string,\n): { baseUrl: string; endpointUrl: string } | null {\n try {\n const parsed = new URL(url);\n const pathname = parsed.pathname.replace(/\\/$/, \"\");\n if (pathname.endsWith(\"/_agent-native/a2a\")) {\n parsed.pathname = pathname.slice(0, -\"/_agent-native/a2a\".length) || \"/\";\n parsed.search = \"\";\n parsed.hash = \"\";\n return {\n baseUrl: parsed.toString().replace(/\\/$/, \"\"),\n endpointUrl: url,\n };\n }\n if (pathname.endsWith(\"/a2a\")) {\n parsed.pathname = pathname.slice(0, -\"/a2a\".length) || \"/\";\n parsed.search = \"\";\n parsed.hash = \"\";\n return {\n baseUrl: parsed.toString().replace(/\\/$/, \"\"),\n endpointUrl: url,\n };\n }\n } catch {\n // Relative or invalid URLs are handled by the caller's normal fetch path.\n }\n return null;\n}\n\nfunction addDefaultEndpointCandidates(candidates: string[], baseUrl: string) {\n const base = baseUrl.replace(/\\/$/, \"\");\n candidates.push(`${base}/_agent-native/a2a`, `${base}/a2a`);\n}\n\nfunction normalizeUrl(\n value: string | undefined,\n baseUrl: string,\n): string | null {\n if (!value) return null;\n try {\n return new URL(value, `${baseUrl.replace(/\\/$/, \"\")}/`)\n .toString()\n .replace(/\\/$/, \"\");\n } catch {\n return null;\n }\n}\n\nfunction shouldTryNextEndpoint(status: number): boolean {\n return status === 404 || status === 405;\n}\n\nfunction unique(values: string[]): string[] {\n return Array.from(new Set(values));\n}\n\n/**\n * One-shot convenience function: send a text message and get a text response.\n *\n * When A2A_SECRET is set and userEmail is provided, outbound calls are signed\n * with a JWT so the receiving app can cryptographically verify the caller's\n * identity (instead of blindly trusting metadata).\n */\nexport async function callAgent(\n url: string,\n text: string,\n opts?: {\n apiKey?: string;\n contextId?: string;\n userEmail?: string;\n orgDomain?: string;\n orgSecret?: string;\n /**\n * Use async/poll instead of a single blocking POST. Recommended for\n * cross-app calls that may exceed a synchronous serverless request budget.\n * Defaults to true so callers get safe behavior out of the box.\n */\n async?: boolean;\n /** Total time to wait for the polled task (default 5 min). */\n timeoutMs?: number;\n },\n): Promise<string> {\n let apiKey = opts?.apiKey;\n\n // Auto-sign with JWT when an A2A secret (org or global) is available and we have a user email\n if (\n !apiKey &&\n opts?.userEmail &&\n (opts?.orgSecret || process.env.A2A_SECRET)\n ) {\n try {\n apiKey = await signA2AToken(\n opts.userEmail,\n opts.orgDomain,\n opts.orgSecret,\n );\n } catch {\n // Fall back to unsigned call\n }\n }\n\n const client = new A2AClient(url, apiKey);\n const metadata: Record<string, unknown> = {};\n if (opts?.userEmail) metadata.userEmail = opts.userEmail;\n if (opts?.orgDomain) metadata.orgDomain = opts.orgDomain;\n\n // Default to async + poll. The receiving A2A server's `_process-task` route\n // runs the handler in a fresh function execution (cross-platform queue\n // pattern), so async mode now works on every host instead of relying on\n // detached promises that get killed on Netlify/Vercel. Callers that\n // explicitly want a single-shot blocking POST can pass `async: false`.\n const useAsync = opts?.async ?? true;\n const message: Message = {\n role: \"user\",\n parts: [{ type: \"text\", text }],\n };\n\n let task: Task;\n if (useAsync) {\n task = await client.sendAndWait(message, {\n contextId: opts?.contextId,\n metadata,\n timeoutMs: opts?.timeoutMs,\n });\n } else {\n task = await client.send(message, {\n contextId: opts?.contextId,\n metadata,\n });\n }\n\n // Extract text from the response\n const responseMessage = task.status.message;\n if (responseMessage) {\n const textParts = responseMessage.parts\n .filter((p): p is { type: \"text\"; text: string } => p.type === \"text\")\n .map((p) => p.text);\n return textParts.join(\"\\n\");\n }\n\n return \"\";\n}\n"]}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/a2a/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAS7B,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IACnC,MAAM,CAAS;IACf,QAAQ,CAAO;IACf,SAAS,CAAS;IAClB,SAAS,CAAS;IAE3B,YAAY,MAAc,EAAE,QAAc,EAAE,SAAiB;QAC3D,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC;QACxC,KAAK,CACH,YAAY,MAAM,4BAA4B,SAAS,mBAAmB,SAAS,GAAG,CACvF,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;QAClC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,KAAa,EACb,SAAkB,EAClB,SAAkB,EAClB,OAAyC;IAEzC,MAAM,MAAM,GAAG,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC;IACnD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,yEAAyE;YACvE,wFAAwF,CAC3F,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GACV,OAAO,CAAC,GAAG,CAAC,OAAO;QACnB,OAAO,CAAC,GAAG,CAAC,eAAe;QAC3B,uBAAuB,CAAC;IAE1B,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC;QACtB,GAAG,EAAE,KAAK;QACV,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAChD,CAAC;SACC,kBAAkB,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;SACpC,SAAS,CAAC,MAAM,CAAC;SACjB,WAAW,EAAE;SACb,iBAAiB,CAAC,OAAO,EAAE,SAAS,IAAI,KAAK,CAAC;SAC9C,IAAI,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,OAAO,SAAS;IACZ,OAAO,CAAS;IAChB,MAAM,CAAU;IAChB,kBAAkB,GAAa,EAAE,CAAC;IAClC,gBAAgB,GAAG,KAAK,CAAC;IACzB,gBAAgB,CAAU;IAElC,YACE,OAAe,EACf,MAAe,EACf,OAAuC;QAEvC,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC9C,MAAM,gBAAgB,GAAG,wBAAwB,CAAC,UAAU,CAAC,CAAC;QAC9D,IAAI,CAAC,OAAO,GAAG,gBAAgB,EAAE,OAAO,IAAI,UAAU,CAAC;QACvD,IAAI,gBAAgB,EAAE,CAAC;YACrB,IAAI,CAAC,kBAAkB,GAAG,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;YACzD,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAC/B,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,gBAAgB,GAAG,OAAO,EAAE,gBAAgB,CAAC;IACpD,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,eAAe;QACnB,MAAM,IAAI,CAAC,wBAAwB,EAAE,CAAC;QACtC,IAAI,IAAI,CAAC,kBAAkB,CAAC,MAAM,IAAI,CAAC;YAAE,OAAO;QAEhD,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC/C,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;gBACzD,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;oBAC7C,IAAI,CAAC,kBAAkB,GAAG,CAAC,QAAQ,CAAC,CAAC;oBACrC,OAAO;gBACT,CAAC;gBACD,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;oBACvB,IAAI,CAAC,kBAAkB,GAAG,CAAC,QAAQ,CAAC,CAAC;oBACrC,OAAO;gBACT,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,0BAA0B;YAC5B,CAAC;QACH,CAAC;IACH,CAAC;IAEO,OAAO;QACb,MAAM,CAAC,GAA2B,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC;QACzE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,CAAC,CAAC,eAAe,CAAC,GAAG,UAAU,IAAI,CAAC,MAAM,EAAE,CAAC;QAC/C,CAAC;QACD,OAAO,CAAC,CAAC;IACX,CAAC;IAEO,KAAK,CAAC,GAAG,CACf,MAAc,EACd,MAA+B;QAE/B,MAAM,IAAI,GAAmB;YAC3B,OAAO,EAAE,KAAK;YACd,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;YACd,MAAM;YACN,MAAM;SACP,CAAC;QAEF,MAAM,IAAI,CAAC,wBAAwB,EAAE,CAAC;QACtC,IAAI,SAAS,GAAiB,IAAI,CAAC;QAEnC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC1C,OAAO,CAAC,GAAG,CAAC,qBAAqB,GAAG,WAAW,MAAM,EAAE,CAAC,CAAC;YACzD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAC7B,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAC3C,OAAO,CAAC,GAAG,CACT,0BAA0B,GAAG,CAAC,MAAM,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,IAAI,CACtE,CAAC;YAEF,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC;gBACX,IAAI,CAAC,kBAAkB,GAAG,CAAC,GAAG,CAAC,CAAC;gBAChC,OAAO,GAAG,CAAC,IAAI,EAA8B,CAAC;YAChD,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YAC9B,SAAS,GAAG,IAAI,KAAK,CAAC,uBAAuB,GAAG,CAAC,MAAM,MAAM,IAAI,EAAE,CAAC,CAAC;YACrE,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBACvC,MAAM,SAAS,CAAC;YAClB,CAAC;QACH,CAAC;QAED,MAAM,SAAS,IAAI,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IACvE,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,8BAA8B,CAAC,CAAC;QACvE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,+BAA+B,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;QAChE,CAAC;QACD,OAAO,GAAG,CAAC,IAAI,EAAwB,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,IAAI,CACR,OAAgB,EAChB,IAYC;QAED,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE;YAC9C,OAAO;YACP,SAAS,EAAE,IAAI,EAAE,SAAS;YAC1B,QAAQ,EAAE,IAAI,EAAE,QAAQ;YACxB,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACxC,CAAC,CAAC;QAEH,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CACb,cAAc,QAAQ,CAAC,KAAK,CAAC,IAAI,MAAM,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,CAChE,CAAC;QACJ,CAAC;QAED,OAAO,QAAQ,CAAC,MAAc,CAAC;IACjC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO,CAAC,MAAc;QAC1B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QAC7D,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CACb,cAAc,QAAQ,CAAC,KAAK,CAAC,IAAI,MAAM,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,CAChE,CAAC;QACJ,CAAC;QACD,OAAO,QAAQ,CAAC,MAAc,CAAC;IACjC,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,WAAW,CACf,OAAgB,EAChB,IASC;QAED,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;YACzC,SAAS,EAAE,IAAI,EAAE,SAAS;YAC1B,QAAQ,EAAE,IAAI,EAAE,QAAQ;YACxB,KAAK,EAAE,IAAI;SACZ,CAAC,CAAC;QAEH,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC;QACpE,IAAI,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC;YAAE,OAAO,SAAS,CAAC;QAEjE,MAAM,SAAS,GAAG,IAAI,EAAE,SAAS,IAAI,CAAC,GAAG,MAAM,CAAC;QAChD,MAAM,MAAM,GAAG,IAAI,EAAE,cAAc,IAAI,KAAK,CAAC;QAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;QAExC,IAAI,OAAO,GAAG,SAAS,CAAC;QACxB,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;YAC7B,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;YAChD,IAAI,CAAC;gBACH,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;gBAC3C,IAAI,EAAE,QAAQ,EAAE,CAAC,OAAO,CAAC,CAAC;YAC5B,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,6DAA6D;gBAC7D,SAAS;YACX,CAAC;YACD,IAAI,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;gBAAE,OAAO,OAAO,CAAC;QAC/D,CAAC;QACD,MAAM,IAAI,mBAAmB,CAAC,SAAS,CAAC,EAAE,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;IAClE,CAAC;IAED,KAAK,CAAC,CAAC,MAAM,CACX,OAAgB,EAChB,IAAiE;QAEjE,MAAM,IAAI,GAAmB;YAC3B,OAAO,EAAE,KAAK;YACd,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;YACd,MAAM,EAAE,gBAAgB;YACxB,MAAM,EAAE;gBACN,OAAO;gBACP,SAAS,EAAE,IAAI,EAAE,SAAS;gBAC1B,QAAQ,EAAE,IAAI,EAAE,QAAQ;aACzB;SACF,CAAC;QAEF,MAAM,IAAI,CAAC,wBAAwB,EAAE,CAAC;QACtC,IAAI,GAAG,GAAoB,IAAI,CAAC;QAChC,IAAI,SAAS,GAAiB,IAAI,CAAC;QACnC,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAChD,GAAG,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;YAC3C,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC;gBACX,IAAI,CAAC,kBAAkB,GAAG,CAAC,SAAS,CAAC,CAAC;gBACtC,MAAM;YACR,CAAC;YACD,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YAC9B,SAAS,GAAG,IAAI,KAAK,CAAC,sBAAsB,GAAG,CAAC,MAAM,MAAM,IAAI,EAAE,CAAC,CAAC;YACpE,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,MAAM,CAAC;gBAAE,MAAM,SAAS,CAAC;QAC1D,CAAC;QACD,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE,CAAC;YACb,MAAM,SAAS,IAAI,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;QACvE,CAAC;QAED,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC;QACrC,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;QAEjD,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;QAClC,IAAI,MAAM,GAAG,EAAE,CAAC;QAEhB,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;YAC5C,IAAI,IAAI;gBAAE,MAAM;YAEhB,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;YAClD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACjC,MAAM,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;YAE3B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;oBAAE,SAAS;gBACzC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;gBAClC,IAAI,CAAC,IAAI;oBAAE,SAAS;gBAEpB,MAAM,QAAQ,GAAoB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBACnD,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;oBACnB,MAAM,IAAI,KAAK,CACb,cAAc,QAAQ,CAAC,KAAK,CAAC,IAAI,MAAM,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,CAChE,CAAC;gBACJ,CAAC;gBACD,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;oBACpB,MAAM,QAAQ,CAAC,MAAc,CAAC;gBAChC,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,wBAAwB;QACpC,IAAI,IAAI,CAAC,gBAAgB;YAAE,OAAO;QAClC,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAE7B,MAAM,UAAU,GAAa,EAAE,CAAC;QAChC,4BAA4B,CAAC,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAEvD,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;YACvC,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YACrD,IAAI,OAAO,EAAE,CAAC;gBACZ,MAAM,gBAAgB,GAAG,wBAAwB,CAAC,OAAO,CAAC,CAAC;gBAC3D,IAAI,gBAAgB,EAAE,CAAC;oBACrB,UAAU,CAAC,OAAO,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;gBACnD,CAAC;qBAAM,CAAC;oBACN,4BAA4B,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;gBACpD,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,wEAAwE;QAC1E,CAAC;QAED,IAAI,CAAC,kBAAkB,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;IAC/C,CAAC;IAEO,KAAK,CAAC,QAAQ,CAAC,GAAW,EAAE,IAAoB;QACtD,MAAM,UAAU,GAAG,IAAI,CAAC,gBAAgB;YACtC,CAAC,CAAC,IAAI,eAAe,EAAE;YACvB,CAAC,CAAC,SAAS,CAAC;QACd,MAAM,KAAK,GACT,UAAU,IAAI,IAAI,CAAC,gBAAgB;YACjC,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,gBAAgB,CAAC;YAC7D,CAAC,CAAC,SAAS,CAAC;QAChB,IAAI,CAAC;YACH,OAAO,MAAM,KAAK,CAAC,GAAG,EAAE;gBACtB,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE;gBACvB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;gBAC1B,MAAM,EAAE,UAAU,EAAE,MAAM;aAC3B,CAAC,CAAC;QACL,CAAC;gBAAS,CAAC;YACT,IAAI,KAAK;gBAAE,YAAY,CAAC,KAAK,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;CACF;AAED,SAAS,wBAAwB,CAC/B,GAAW;IAEX,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACpD,IAAI,QAAQ,CAAC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,CAAC;YAC5C,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,oBAAoB,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC;YACzE,MAAM,CAAC,MAAM,GAAG,EAAE,CAAC;YACnB,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;YACjB,OAAO;gBACL,OAAO,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;gBAC7C,WAAW,EAAE,GAAG;aACjB,CAAC;QACJ,CAAC;QACD,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC9B,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC;YAC3D,MAAM,CAAC,MAAM,GAAG,EAAE,CAAC;YACnB,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;YACjB,OAAO;gBACL,OAAO,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;gBAC7C,WAAW,EAAE,GAAG;aACjB,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,0EAA0E;IAC5E,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,4BAA4B,CAAC,UAAoB,EAAE,OAAe;IACzE,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACxC,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI,oBAAoB,EAAE,GAAG,IAAI,MAAM,CAAC,CAAC;AAC9D,CAAC;AAED,SAAS,YAAY,CACnB,KAAyB,EACzB,OAAe;IAEf,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CAAC,KAAK,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC;aACpD,QAAQ,EAAE;aACV,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,qBAAqB,CAAC,MAAc;IAC3C,OAAO,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG,CAAC;AAC1C,CAAC;AAED,SAAS,MAAM,CAAC,MAAgB;IAC9B,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;AACrC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,GAAW,EACX,IAAY,EACZ,IAcC;IAED,IAAI,MAAM,GAAG,IAAI,EAAE,MAAM,CAAC;IAE1B,8FAA8F;IAC9F,IACE,CAAC,MAAM;QACP,IAAI,EAAE,SAAS;QACf,CAAC,IAAI,EAAE,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,EAC3C,CAAC;QACD,IAAI,CAAC;YACH,MAAM,GAAG,MAAM,YAAY,CACzB,IAAI,CAAC,SAAS,EACd,IAAI,CAAC,SAAS,EACd,IAAI,CAAC,SAAS,CACf,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,6BAA6B;QAC/B,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAC1C,MAAM,QAAQ,GAA4B,EAAE,CAAC;IAC7C,IAAI,IAAI,EAAE,SAAS;QAAE,QAAQ,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;IACzD,IAAI,IAAI,EAAE,SAAS;QAAE,QAAQ,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;IAEzD,4EAA4E;IAC5E,uEAAuE;IACvE,wEAAwE;IACxE,oEAAoE;IACpE,uEAAuE;IACvE,MAAM,QAAQ,GAAG,IAAI,EAAE,KAAK,IAAI,IAAI,CAAC;IACrC,MAAM,OAAO,GAAY;QACvB,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;KAChC,CAAC;IAEF,IAAI,IAAU,CAAC;IACf,IAAI,QAAQ,EAAE,CAAC;QACb,IAAI,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE;YACvC,SAAS,EAAE,IAAI,EAAE,SAAS;YAC1B,QAAQ;YACR,SAAS,EAAE,IAAI,EAAE,SAAS;SAC3B,CAAC,CAAC;IACL,CAAC;SAAM,CAAC;QACN,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE;YAChC,SAAS,EAAE,IAAI,EAAE,SAAS;YAC1B,QAAQ;SACT,CAAC,CAAC;IACL,CAAC;IAED,iCAAiC;IACjC,MAAM,eAAe,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;IAC5C,IAAI,eAAe,EAAE,CAAC;QACpB,MAAM,SAAS,GAAG,eAAe,CAAC,KAAK;aACpC,MAAM,CAAC,CAAC,CAAC,EAAuC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC;aACrE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACtB,OAAO,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;IAED,OAAO,EAAE,CAAC;AACZ,CAAC","sourcesContent":["import * as jose from \"jose\";\nimport type {\n AgentCard,\n JsonRpcRequest,\n JsonRpcResponse,\n Message,\n Task,\n} from \"./types.js\";\n\nexport class A2ATaskTimeoutError extends Error {\n readonly taskId: string;\n readonly lastTask: Task;\n readonly lastState: string;\n readonly timeoutMs: number;\n\n constructor(taskId: string, lastTask: Task, timeoutMs: number) {\n const lastState = lastTask.status.state;\n super(\n `A2A task ${taskId} did not complete within ${timeoutMs}ms (last state: ${lastState})`,\n );\n this.name = \"A2ATaskTimeoutError\";\n this.taskId = taskId;\n this.lastTask = lastTask;\n this.lastState = lastState;\n this.timeoutMs = timeoutMs;\n }\n}\n\n/**\n * Sign a JWT for A2A cross-app identity verification.\n *\n * Uses A2A_SECRET as an HMAC key. The token contains the caller's email\n * as `sub`, so the receiving app can verify who's calling.\n */\nexport async function signA2AToken(\n email: string,\n orgDomain?: string,\n orgSecret?: string,\n options?: { expiresIn?: string | number },\n): Promise<string> {\n const secret = orgSecret || process.env.A2A_SECRET;\n if (!secret) {\n throw new Error(\n \"No A2A secret available. Set an org-level A2A secret in Team settings, \" +\n \"or set A2A_SECRET as an environment variable on all apps that need to verify identity.\",\n );\n }\n\n const appUrl =\n process.env.APP_URL ||\n process.env.BETTER_AUTH_URL ||\n \"http://localhost:3000\";\n\n return new jose.SignJWT({\n sub: email,\n ...(orgDomain ? { org_domain: orgDomain } : {}),\n })\n .setProtectedHeader({ alg: \"HS256\" })\n .setIssuer(appUrl)\n .setIssuedAt()\n .setExpirationTime(options?.expiresIn ?? \"15m\")\n .sign(new TextEncoder().encode(secret));\n}\n\nexport class A2AClient {\n private baseUrl: string;\n private apiKey?: string;\n private endpointCandidates: string[] = [];\n private endpointResolved = false;\n private requestTimeoutMs?: number;\n\n constructor(\n baseUrl: string,\n apiKey?: string,\n options?: { requestTimeoutMs?: number },\n ) {\n const normalized = baseUrl.replace(/\\/$/, \"\");\n const explicitEndpoint = splitExplicitA2AEndpoint(normalized);\n this.baseUrl = explicitEndpoint?.baseUrl ?? normalized;\n if (explicitEndpoint) {\n this.endpointCandidates = [explicitEndpoint.endpointUrl];\n this.endpointResolved = true;\n }\n this.apiKey = apiKey;\n this.requestTimeoutMs = options?.requestTimeoutMs;\n }\n\n /**\n * Detect which A2A path the target agent uses.\n * Agent-native apps use /_agent-native/a2a, external agents may use /a2a.\n */\n async resolveEndpoint(): Promise<void> {\n await this.ensureEndpointCandidates();\n if (this.endpointCandidates.length <= 1) return;\n\n for (const endpoint of this.endpointCandidates) {\n try {\n const res = await fetch(endpoint, { method: \"OPTIONS\" });\n if (res.status !== 404 && res.status !== 405) {\n this.endpointCandidates = [endpoint];\n return;\n }\n if (res.status === 405) {\n this.endpointCandidates = [endpoint];\n return;\n }\n } catch {\n // Try the next candidate.\n }\n }\n }\n\n private headers(): Record<string, string> {\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (this.apiKey) {\n h[\"Authorization\"] = `Bearer ${this.apiKey}`;\n }\n return h;\n }\n\n private async rpc(\n method: string,\n params: Record<string, unknown>,\n ): Promise<JsonRpcResponse> {\n const body: JsonRpcRequest = {\n jsonrpc: \"2.0\",\n id: Date.now(),\n method,\n params,\n };\n\n await this.ensureEndpointCandidates();\n let lastError: Error | null = null;\n\n for (const url of this.endpointCandidates) {\n console.log(`[A2A Client] POST ${url} method=${method}`);\n const startTime = Date.now();\n const res = await this.postJson(url, body);\n console.log(\n `[A2A Client] Response: ${res.status} in ${Date.now() - startTime}ms`,\n );\n\n if (res.ok) {\n this.endpointCandidates = [url];\n return res.json() as Promise<JsonRpcResponse>;\n }\n\n const text = await res.text();\n lastError = new Error(`A2A request failed (${res.status}): ${text}`);\n if (!shouldTryNextEndpoint(res.status)) {\n throw lastError;\n }\n }\n\n throw lastError ?? new Error(\"No A2A endpoint candidates available\");\n }\n\n async getAgentCard(): Promise<AgentCard> {\n const res = await fetch(`${this.baseUrl}/.well-known/agent-card.json`);\n if (!res.ok) {\n throw new Error(`Failed to fetch agent card (${res.status})`);\n }\n return res.json() as Promise<AgentCard>;\n }\n\n async send(\n message: Message,\n opts?: {\n contextId?: string;\n metadata?: Record<string, unknown>;\n /**\n * If true, ask the server to return the task immediately in `working`\n * state and process the handler in the background. The caller should\n * then poll `getTask(taskId)` until `completed` / `failed` / `canceled`.\n *\n * Use this when you expect the handler may exceed a synchronous\n * serverless request budget.\n */\n async?: boolean;\n },\n ): Promise<Task> {\n const response = await this.rpc(\"message/send\", {\n message,\n contextId: opts?.contextId,\n metadata: opts?.metadata,\n ...(opts?.async ? { async: true } : {}),\n });\n\n if (response.error) {\n throw new Error(\n `A2A error (${response.error.code}): ${response.error.message}`,\n );\n }\n\n return response.result as Task;\n }\n\n /**\n * Poll for a task by id. Used in async mode after `send({ async: true })`.\n */\n async getTask(taskId: string): Promise<Task> {\n const response = await this.rpc(\"tasks/get\", { id: taskId });\n if (response.error) {\n throw new Error(\n `A2A error (${response.error.code}): ${response.error.message}`,\n );\n }\n return response.result as Task;\n }\n\n /**\n * Send a message in async mode and poll until the task reaches a terminal\n * state. This is the recommended path on serverless hosts with short\n * function timeouts (Netlify, Vercel) where a synchronous LLM-driven A2A\n * call can exceed the gateway limit.\n *\n * Each individual fetch returns quickly; long-running work happens on the\n * receiving side and is checked via `tasks/get`.\n */\n async sendAndWait(\n message: Message,\n opts?: {\n contextId?: string;\n metadata?: Record<string, unknown>;\n /** Total time to wait for completion. Default 5 min. */\n timeoutMs?: number;\n /** Poll interval. Default 2s. */\n pollIntervalMs?: number;\n /** Called with each polled task — useful for surfacing progress. */\n onUpdate?: (task: Task) => void;\n },\n ): Promise<Task> {\n const submitted = await this.send(message, {\n contextId: opts?.contextId,\n metadata: opts?.metadata,\n async: true,\n });\n\n const terminalStates = new Set([\"completed\", \"failed\", \"canceled\"]);\n if (terminalStates.has(submitted.status.state)) return submitted;\n\n const timeoutMs = opts?.timeoutMs ?? 5 * 60_000;\n const pollMs = opts?.pollIntervalMs ?? 2_000;\n const deadline = Date.now() + timeoutMs;\n\n let current = submitted;\n while (Date.now() < deadline) {\n await new Promise((r) => setTimeout(r, pollMs));\n try {\n current = await this.getTask(submitted.id);\n opts?.onUpdate?.(current);\n } catch (err) {\n // Transient fetch failure — keep polling until the deadline.\n continue;\n }\n if (terminalStates.has(current.status.state)) return current;\n }\n throw new A2ATaskTimeoutError(submitted.id, current, timeoutMs);\n }\n\n async *stream(\n message: Message,\n opts?: { contextId?: string; metadata?: Record<string, unknown> },\n ): AsyncGenerator<Task> {\n const body: JsonRpcRequest = {\n jsonrpc: \"2.0\",\n id: Date.now(),\n method: \"message/stream\",\n params: {\n message,\n contextId: opts?.contextId,\n metadata: opts?.metadata,\n },\n };\n\n await this.ensureEndpointCandidates();\n let res: Response | null = null;\n let lastError: Error | null = null;\n for (const candidate of this.endpointCandidates) {\n res = await this.postJson(candidate, body);\n if (res.ok) {\n this.endpointCandidates = [candidate];\n break;\n }\n const text = await res.text();\n lastError = new Error(`A2A stream failed (${res.status}): ${text}`);\n if (!shouldTryNextEndpoint(res.status)) throw lastError;\n }\n if (!res?.ok) {\n throw lastError ?? new Error(\"No A2A endpoint candidates available\");\n }\n\n const reader = res.body?.getReader();\n if (!reader) throw new Error(\"No response body\");\n\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n for (const line of lines) {\n if (!line.startsWith(\"data: \")) continue;\n const json = line.slice(6).trim();\n if (!json) continue;\n\n const response: JsonRpcResponse = JSON.parse(json);\n if (response.error) {\n throw new Error(\n `A2A error (${response.error.code}): ${response.error.message}`,\n );\n }\n if (response.result) {\n yield response.result as Task;\n }\n }\n }\n }\n\n private async ensureEndpointCandidates(): Promise<void> {\n if (this.endpointResolved) return;\n this.endpointResolved = true;\n\n const candidates: string[] = [];\n addDefaultEndpointCandidates(candidates, this.baseUrl);\n\n try {\n const card = await this.getAgentCard();\n const cardUrl = normalizeUrl(card.url, this.baseUrl);\n if (cardUrl) {\n const explicitEndpoint = splitExplicitA2AEndpoint(cardUrl);\n if (explicitEndpoint) {\n candidates.unshift(explicitEndpoint.endpointUrl);\n } else {\n addDefaultEndpointCandidates(candidates, cardUrl);\n }\n }\n } catch {\n // Agent cards are discovery hints. Fall back to conventional endpoints.\n }\n\n this.endpointCandidates = unique(candidates);\n }\n\n private async postJson(url: string, body: JsonRpcRequest): Promise<Response> {\n const controller = this.requestTimeoutMs\n ? new AbortController()\n : undefined;\n const timer =\n controller && this.requestTimeoutMs\n ? setTimeout(() => controller.abort(), this.requestTimeoutMs)\n : undefined;\n try {\n return await fetch(url, {\n method: \"POST\",\n headers: this.headers(),\n body: JSON.stringify(body),\n signal: controller?.signal,\n });\n } finally {\n if (timer) clearTimeout(timer);\n }\n }\n}\n\nfunction splitExplicitA2AEndpoint(\n url: string,\n): { baseUrl: string; endpointUrl: string } | null {\n try {\n const parsed = new URL(url);\n const pathname = parsed.pathname.replace(/\\/$/, \"\");\n if (pathname.endsWith(\"/_agent-native/a2a\")) {\n parsed.pathname = pathname.slice(0, -\"/_agent-native/a2a\".length) || \"/\";\n parsed.search = \"\";\n parsed.hash = \"\";\n return {\n baseUrl: parsed.toString().replace(/\\/$/, \"\"),\n endpointUrl: url,\n };\n }\n if (pathname.endsWith(\"/a2a\")) {\n parsed.pathname = pathname.slice(0, -\"/a2a\".length) || \"/\";\n parsed.search = \"\";\n parsed.hash = \"\";\n return {\n baseUrl: parsed.toString().replace(/\\/$/, \"\"),\n endpointUrl: url,\n };\n }\n } catch {\n // Relative or invalid URLs are handled by the caller's normal fetch path.\n }\n return null;\n}\n\nfunction addDefaultEndpointCandidates(candidates: string[], baseUrl: string) {\n const base = baseUrl.replace(/\\/$/, \"\");\n candidates.push(`${base}/_agent-native/a2a`, `${base}/a2a`);\n}\n\nfunction normalizeUrl(\n value: string | undefined,\n baseUrl: string,\n): string | null {\n if (!value) return null;\n try {\n return new URL(value, `${baseUrl.replace(/\\/$/, \"\")}/`)\n .toString()\n .replace(/\\/$/, \"\");\n } catch {\n return null;\n }\n}\n\nfunction shouldTryNextEndpoint(status: number): boolean {\n return status === 404 || status === 405;\n}\n\nfunction unique(values: string[]): string[] {\n return Array.from(new Set(values));\n}\n\n/**\n * One-shot convenience function: send a text message and get a text response.\n *\n * When A2A_SECRET is set and userEmail is provided, outbound calls are signed\n * with a JWT so the receiving app can cryptographically verify the caller's\n * identity (instead of blindly trusting metadata).\n */\nexport async function callAgent(\n url: string,\n text: string,\n opts?: {\n apiKey?: string;\n contextId?: string;\n userEmail?: string;\n orgDomain?: string;\n orgSecret?: string;\n /**\n * Use async/poll instead of a single blocking POST. Recommended for\n * cross-app calls that may exceed a synchronous serverless request budget.\n * Defaults to true so callers get safe behavior out of the box.\n */\n async?: boolean;\n /** Total time to wait for the polled task (default 5 min). */\n timeoutMs?: number;\n },\n): Promise<string> {\n let apiKey = opts?.apiKey;\n\n // Auto-sign with JWT when an A2A secret (org or global) is available and we have a user email\n if (\n !apiKey &&\n opts?.userEmail &&\n (opts?.orgSecret || process.env.A2A_SECRET)\n ) {\n try {\n apiKey = await signA2AToken(\n opts.userEmail,\n opts.orgDomain,\n opts.orgSecret,\n );\n } catch {\n // Fall back to unsigned call\n }\n }\n\n const client = new A2AClient(url, apiKey);\n const metadata: Record<string, unknown> = {};\n if (opts?.userEmail) metadata.userEmail = opts.userEmail;\n if (opts?.orgDomain) metadata.orgDomain = opts.orgDomain;\n\n // Default to async + poll. The receiving A2A server's `_process-task` route\n // runs the handler in a fresh function execution (cross-platform queue\n // pattern), so async mode now works on every host instead of relying on\n // detached promises that get killed on Netlify/Vercel. Callers that\n // explicitly want a single-shot blocking POST can pass `async: false`.\n const useAsync = opts?.async ?? true;\n const message: Message = {\n role: \"user\",\n parts: [{ type: \"text\", text }],\n };\n\n let task: Task;\n if (useAsync) {\n task = await client.sendAndWait(message, {\n contextId: opts?.contextId,\n metadata,\n timeoutMs: opts?.timeoutMs,\n });\n } else {\n task = await client.send(message, {\n contextId: opts?.contextId,\n metadata,\n });\n }\n\n // Extract text from the response\n const responseMessage = task.status.message;\n if (responseMessage) {\n const textParts = responseMessage.parts\n .filter((p): p is { type: \"text\"; text: string } => p.type === \"text\")\n .map((p) => p.text);\n return textParts.join(\"\\n\");\n }\n\n return \"\";\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/a2a/server.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AA0I5C;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CACtB,QAAQ,EAAE,GAAG,EACb,MAAM,EAAE,SAAS,EACjB,WAAW,SAAmB,GAC7B,IAAI,CAyMN"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/a2a/server.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AA0I5C;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CACtB,QAAQ,EAAE,GAAG,EACb,MAAM,EAAE,SAAS,EACjB,WAAW,SAAmB,GAC7B,IAAI,CAkNN"}
@@ -233,6 +233,8 @@ export function mountA2A(nitroApp, config, routePrefix = "/_agent-native") {
233
233
  const authHeader = getRequestHeader(event, "authorization");
234
234
  let verifiedCallerEmail = null;
235
235
  let verifiedOrgDomain = null;
236
+ let legacyApiKeyAuthenticated = false;
237
+ let bearerTokenRejectedByJwt = false;
236
238
  // SECURITY: when neither A2A_SECRET nor an apiKeyEnv is configured,
237
239
  // there's no way to authenticate the caller. Default to "auth required"
238
240
  // in production — return 503 with a clear message instead of running
@@ -240,37 +242,12 @@ export function mountA2A(nitroApp, config, routePrefix = "/_agent-native") {
240
242
  // warning but allow so local templates work out of the box.
241
243
  const hasA2ASecret = !!process.env.A2A_SECRET;
242
244
  const hasApiKey = !!(config.apiKeyEnv && process.env[config.apiKeyEnv]);
243
- if (!hasA2ASecret && !hasApiKey) {
244
- if (process.env.NODE_ENV === "production") {
245
- setResponseStatus(event, 503);
246
- return {
247
- jsonrpc: "2.0",
248
- id: null,
249
- error: {
250
- code: -32001,
251
- message: "A2A authentication not configured. Set A2A_SECRET (preferred) or configure apiKeyEnv to accept inbound A2A traffic.",
252
- },
253
- };
254
- }
255
- warnA2AUnauthOnce();
256
- }
257
245
  // Try JWT verification first (org-level or global A2A_SECRET-based identity)
258
246
  if (authHeader?.startsWith("Bearer ")) {
259
247
  const tokenPayload = await verifyA2AToken(authHeader, event);
260
248
  verifiedCallerEmail = tokenPayload.email;
261
249
  verifiedOrgDomain = tokenPayload.orgDomain;
262
- // If a secret exists (org-level or global) and token fails verification, reject
263
- if (!verifiedCallerEmail && process.env.A2A_SECRET) {
264
- setResponseStatus(event, 401);
265
- return {
266
- jsonrpc: "2.0",
267
- id: null,
268
- error: {
269
- code: -32001,
270
- message: "Invalid or expired A2A token",
271
- },
272
- };
273
- }
250
+ bearerTokenRejectedByJwt = !verifiedCallerEmail;
274
251
  }
275
252
  // Fall back to legacy API key check (exact string match)
276
253
  if (!verifiedCallerEmail && config.apiKeyEnv) {
@@ -293,6 +270,36 @@ export function mountA2A(nitroApp, config, routePrefix = "/_agent-native") {
293
270
  error: { code: -32001, message: "Invalid API key" },
294
271
  };
295
272
  }
273
+ legacyApiKeyAuthenticated = true;
274
+ }
275
+ }
276
+ if (!verifiedCallerEmail && !legacyApiKeyAuthenticated) {
277
+ // If a global secret exists and JWT verification failed, reject after
278
+ // giving the legacy exact-match apiKeyEnv path a chance to succeed.
279
+ if (bearerTokenRejectedByJwt && process.env.A2A_SECRET) {
280
+ setResponseStatus(event, 401);
281
+ return {
282
+ jsonrpc: "2.0",
283
+ id: null,
284
+ error: {
285
+ code: -32001,
286
+ message: "Invalid or expired A2A token",
287
+ },
288
+ };
289
+ }
290
+ if (!hasA2ASecret && !hasApiKey) {
291
+ if (process.env.NODE_ENV === "production") {
292
+ setResponseStatus(event, 503);
293
+ return {
294
+ jsonrpc: "2.0",
295
+ id: null,
296
+ error: {
297
+ code: -32001,
298
+ message: "A2A authentication not configured. Set A2A_SECRET (preferred) or configure apiKeyEnv to accept inbound A2A traffic.",
299
+ },
300
+ };
301
+ }
302
+ warnA2AUnauthOnce();
296
303
  }
297
304
  }
298
305
  // Store verified caller identity on the event context so the handler
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/a2a/server.ts"],"names":[],"mappings":"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","sourcesContent":["import * as jose from \"jose\";\nimport { getH3App } from \"../server/framework-request-handler.js\";\nimport {\n defineEventHandler,\n setResponseHeader,\n setResponseStatus,\n getMethod,\n getRequestHeader,\n} from \"h3\";\nimport type { A2AConfig } from \"./types.js\";\nimport { generateAgentCard } from \"./agent-card.js\";\nimport { handleJsonRpcH3, processA2ATaskFromQueue } from \"./handlers.js\";\nimport { readBody } from \"../server/h3-helpers.js\";\nimport {\n extractBearerToken,\n verifyInternalToken,\n} from \"../integrations/internal-token.js\";\n\n/**\n * One-time warning when A2A is running unauthenticated in development. We\n * don't refuse the request (local templates need to work out of the box),\n * but we log a single noisy line so operators notice if they accidentally\n * deploy with no auth configured.\n */\nlet _warnedUnauthA2A = false;\nfunction warnA2AUnauthOnce(): void {\n if (_warnedUnauthA2A) return;\n _warnedUnauthA2A = true;\n // eslint-disable-next-line no-console\n console.warn(\n \"[a2a] No A2A_SECRET or apiKeyEnv configured — A2A endpoint runs unauthenticated. \" +\n \"This is allowed in development but blocked in production. Set A2A_SECRET before deploying.\",\n );\n}\n\n/**\n * Verify an inbound A2A JWT signed with the shared A2A_SECRET.\n * Returns the caller's email (from `sub` claim) if valid, null otherwise.\n */\ninterface A2ATokenPayload {\n email: string | null;\n orgDomain: string | null;\n}\n\n/**\n * Resolve the audience (`aud`) value to expect in an inbound JWT. We use the\n * receiver's app URL — it's the natural identifier of \"who this token was\n * minted for\". Falls back to undefined when no app URL is configured, in\n * which case the audience check is skipped (backward-compat with tokens\n * minted before the audience claim shipped).\n */\nfunction expectedJwtAudience(event: any | undefined): string | undefined {\n const fromEnv =\n process.env.APP_URL ||\n process.env.URL ||\n process.env.DEPLOY_URL ||\n process.env.BETTER_AUTH_URL;\n if (fromEnv) return String(fromEnv);\n // Best-effort: derive from the inbound request host. This is forgeable\n // (Host-header attack), but only useful as a hint when env-derived URL\n // is unset; the rest of the JWT verification still uses the secret.\n try {\n const proto = getRequestHeader(event, \"x-forwarded-proto\") || \"https\";\n const host = getRequestHeader(event, \"host\");\n if (host) return `${proto}://${host}`;\n } catch {}\n return undefined;\n}\n\nasync function verifyA2AToken(\n authHeader: string,\n event: any | undefined,\n): Promise<A2ATokenPayload> {\n const token = authHeader.replace(\"Bearer \", \"\");\n\n // Step 1: Peek at JWT claims WITHOUT verification to get org_domain.\n // This is safe because we only use org_domain to look up the secret,\n // then verify the full JWT with that secret. If someone forges a JWT\n // with a fake org_domain, verification will fail because they don't\n // have the real secret.\n let orgDomainHint: string | undefined;\n let unverifiedPayload: jose.JWTPayload | undefined;\n try {\n unverifiedPayload = jose.decodeJwt(token);\n orgDomainHint = unverifiedPayload.org_domain as string | undefined;\n } catch {\n // Malformed token — fall through to global secret attempt\n }\n\n // Step 2: Look up the org's A2A secret by domain\n let secret: string | undefined;\n if (orgDomainHint) {\n try {\n const { getA2ASecretByDomain } = await import(\"../org/context.js\");\n const orgSecret = await getA2ASecretByDomain(orgDomainHint);\n if (orgSecret) secret = orgSecret;\n } catch {\n // DB not ready or column doesn't exist yet — fall through\n }\n }\n\n // Step 3: Fall back to global A2A_SECRET\n if (!secret) secret = process.env.A2A_SECRET;\n if (!secret) return { email: null, orgDomain: null };\n\n // Step 4: Verify JWT with the resolved secret.\n //\n // - `audience`: passed only when the token carries an `aud` claim\n // (backward-compat: tokens minted by older `signA2AToken` versions\n // don't include one).\n // - `issuer`: enforced when the token carries an `iss` claim. The\n // sender's `signA2AToken` (`a2a/client.ts:42`) sets the issuer to its\n // own app URL, so a verified token must self-identify a non-empty\n // string issuer. We accept any string the token claims (we don't pin\n // a specific expected issuer because dispatchers may legitimately\n // mint tokens from many sender URLs — dev tunnels, multi-deploy\n // setups). The pin is \"issuer must match the value the token says\n // it was minted from\", which `jose.jwtVerify` validates exactly when\n // `issuer` is supplied as a string. Backward-compat: when the token\n // has no `iss`, we skip the check.\n try {\n const verifyOptions: jose.JWTVerifyOptions = {};\n if (unverifiedPayload && typeof unverifiedPayload.aud !== \"undefined\") {\n const aud = expectedJwtAudience(event);\n if (aud) verifyOptions.audience = aud;\n }\n if (\n unverifiedPayload &&\n typeof unverifiedPayload.iss === \"string\" &&\n unverifiedPayload.iss.length > 0\n ) {\n verifyOptions.issuer = unverifiedPayload.iss;\n }\n const { payload } = await jose.jwtVerify(\n token,\n new TextEncoder().encode(secret),\n verifyOptions,\n );\n return {\n email: (payload.sub as string) ?? null,\n orgDomain: (payload.org_domain as string) ?? null,\n };\n } catch {\n return { email: null, orgDomain: null };\n }\n}\n\n/**\n * Mount A2A protocol endpoints on an H3/Nitro app.\n *\n * - GET /.well-known/agent-card.json — public agent card (no auth)\n * - POST /_agent-native/a2a — JSON-RPC endpoint (with optional auth)\n *\n * When A2A_SECRET is set, inbound Bearer tokens are verified as JWTs\n * and the caller's email is extracted from the `sub` claim. This provides\n * cryptographic identity verification for cross-app A2A calls.\n */\nexport function mountA2A(\n nitroApp: any,\n config: A2AConfig,\n routePrefix = \"/_agent-native\",\n): void {\n // Public agent card endpoint (no auth required).\n //\n // SECURITY: per-user / per-org MCP tools are filtered out of the public\n // skills list. Their merged-key prefix (`mcp__user_<emailhash>_…` or\n // `mcp__org_<orgid>_…`) discloses (a) which users have integrations\n // attached, and (b) what those integrations are — fingerprinting the\n // tenant. Template- and framework-defined skills stay; only the dynamic\n // per-tenant MCP entries are dropped. See finding #7 in\n // /tmp/security-audit/12-mcp-a2a-agent.md.\n getH3App(nitroApp).use(\n \"/.well-known/agent-card.json\",\n defineEventHandler((event) => {\n if (getMethod(event) !== \"GET\") {\n setResponseStatus(event, 405);\n return { error: \"Method not allowed\" };\n }\n const protocol =\n getRequestHeader(event, \"x-forwarded-proto\") ||\n (event.url?.protocol?.replace(\":\", \"\") ?? \"http\");\n const host = getRequestHeader(event, \"host\") ?? \"localhost\";\n const baseUrl = `${protocol}://${host}`;\n\n // Filter out per-user/per-org MCP tools to avoid tenant disclosure.\n // Note: stdio MCP tools loaded from a file-based mcp.config.json are\n // process-wide and don't carry a per-user/per-org prefix, so they\n // remain visible. That's intentional — they're an operator-controlled\n // capability list.\n const filteredSkills = (config.skills ?? []).filter((skill) => {\n const id =\n (skill as { id?: string; name?: string }).id ??\n (skill as { name?: string }).name ??\n \"\";\n if (typeof id !== \"string\") return true;\n return !id.startsWith(\"mcp__user_\") && !id.startsWith(\"mcp__org_\");\n });\n\n return generateAgentCard({ ...config, skills: filteredSkills }, baseUrl);\n }),\n );\n\n // Async-mode processor route. MUST be mounted BEFORE the `/a2a` catch-all\n // below, since h3's `.use()` matches by prefix and `/a2a` would otherwise\n // swallow `/a2a/_process-task` and return a JSON-RPC \"Invalid token\" error\n // (the JSON-RPC handler doesn't know about taskId-only bodies).\n //\n // When `message/send` is called with `async: true`, the JSON-RPC handler\n // enqueues the task and self-fires a POST to this route on the same\n // deployment so the actual handler runs in a fresh function execution (its\n // own full timeout). Authenticated with an HMAC token bound to the task id\n // (5-minute lifetime, signed with A2A_SECRET — same scheme as the\n // integration webhook queue).\n getH3App(nitroApp).use(\n `${routePrefix}/a2a/_process-task`,\n defineEventHandler(async (event) => {\n if (getMethod(event) !== \"POST\") {\n setResponseStatus(event, 405);\n return { error: \"Method not allowed\" };\n }\n\n const body = (await readBody(event)) as { taskId?: unknown } | null;\n const taskId = body && typeof body.taskId === \"string\" ? body.taskId : \"\";\n if (!taskId) {\n setResponseStatus(event, 400);\n return { error: \"taskId required\" };\n }\n\n // When A2A_SECRET is set, require a valid HMAC token bound to this\n // taskId. In production, we REQUIRE A2A_SECRET to be set so unsigned\n // dispatches are never accepted (an attacker who fishes a taskId out\n // of logs / a share link could otherwise force-replay it). In\n // development, a missing secret is permitted so local templates work\n // out of the box, but we log a one-time warning so operators notice.\n if (process.env.A2A_SECRET) {\n const auth = getRequestHeader(event, \"authorization\");\n const tok = extractBearerToken(auth);\n if (!verifyInternalToken(taskId, tok)) {\n setResponseStatus(event, 401);\n return { error: \"Invalid or expired processor token\" };\n }\n } else if (process.env.NODE_ENV === \"production\") {\n setResponseStatus(event, 503);\n return {\n error:\n \"A2A processor not configured — set A2A_SECRET on this deployment to enable async A2A.\",\n };\n } else {\n warnA2AUnauthOnce();\n }\n\n try {\n await processA2ATaskFromQueue(taskId, config, event);\n return { ok: true };\n } catch (err: any) {\n console.error(\"[a2a] process-task failed:\", err);\n setResponseStatus(event, 500);\n return { error: err?.message ?? \"process-task failed\" };\n }\n }),\n );\n\n // JSON-RPC A2A endpoint (with optional auth)\n getH3App(nitroApp).use(\n `${routePrefix}/a2a`,\n defineEventHandler(async (event) => {\n if (getMethod(event) !== \"POST\") {\n setResponseStatus(event, 405);\n return { error: \"Method not allowed\" };\n }\n\n // h3 prefix-matches mounts, so a request to `/a2a/_process-task`\n // reaches this handler too. The dedicated mount above runs first and\n // takes the request, but if that returns `undefined` (or h3 ever\n // changes ordering semantics) defensively bail here. event.path is\n // stripped to the remainder after the mount prefix.\n const sub = (event.path || \"/\").split(\"?\")[0].replace(/^\\//, \"\");\n if (sub.startsWith(\"_process-task\")) return;\n\n const authHeader = getRequestHeader(event, \"authorization\");\n let verifiedCallerEmail: string | null = null;\n let verifiedOrgDomain: string | null = null;\n\n // SECURITY: when neither A2A_SECRET nor an apiKeyEnv is configured,\n // there's no way to authenticate the caller. Default to \"auth required\"\n // in production — return 503 with a clear message instead of running\n // the agent loop unauthenticated. In development, log a one-time\n // warning but allow so local templates work out of the box.\n const hasA2ASecret = !!process.env.A2A_SECRET;\n const hasApiKey = !!(config.apiKeyEnv && process.env[config.apiKeyEnv]);\n if (!hasA2ASecret && !hasApiKey) {\n if (process.env.NODE_ENV === \"production\") {\n setResponseStatus(event, 503);\n return {\n jsonrpc: \"2.0\",\n id: null,\n error: {\n code: -32001,\n message:\n \"A2A authentication not configured. Set A2A_SECRET (preferred) or configure apiKeyEnv to accept inbound A2A traffic.\",\n },\n };\n }\n warnA2AUnauthOnce();\n }\n\n // Try JWT verification first (org-level or global A2A_SECRET-based identity)\n if (authHeader?.startsWith(\"Bearer \")) {\n const tokenPayload = await verifyA2AToken(authHeader, event);\n verifiedCallerEmail = tokenPayload.email;\n verifiedOrgDomain = tokenPayload.orgDomain;\n // If a secret exists (org-level or global) and token fails verification, reject\n if (!verifiedCallerEmail && process.env.A2A_SECRET) {\n setResponseStatus(event, 401);\n return {\n jsonrpc: \"2.0\",\n id: null,\n error: {\n code: -32001,\n message: \"Invalid or expired A2A token\",\n },\n };\n }\n }\n\n // Fall back to legacy API key check (exact string match)\n if (!verifiedCallerEmail && config.apiKeyEnv) {\n const expectedKey = process.env[config.apiKeyEnv];\n if (expectedKey) {\n if (!authHeader || !authHeader.startsWith(\"Bearer \")) {\n setResponseStatus(event, 401);\n return {\n jsonrpc: \"2.0\",\n id: null,\n error: { code: -32001, message: \"Authentication required\" },\n };\n }\n const token = authHeader.slice(7);\n if (token !== expectedKey) {\n setResponseStatus(event, 401);\n return {\n jsonrpc: \"2.0\",\n id: null,\n error: { code: -32001, message: \"Invalid API key\" },\n };\n }\n }\n }\n\n // Store verified caller identity on the event context so the handler\n // can set request context from a trusted source instead of metadata\n if (verifiedCallerEmail) {\n event.context.__a2aVerifiedEmail = verifiedCallerEmail;\n }\n if (verifiedOrgDomain) {\n event.context.__a2aOrgDomain = verifiedOrgDomain;\n }\n\n const body = await readBody(event);\n return handleJsonRpcH3(body, event, config);\n }),\n );\n}\n"]}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/a2a/server.ts"],"names":[],"mappings":"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","sourcesContent":["import * as jose from \"jose\";\nimport { getH3App } from \"../server/framework-request-handler.js\";\nimport {\n defineEventHandler,\n setResponseHeader,\n setResponseStatus,\n getMethod,\n getRequestHeader,\n} from \"h3\";\nimport type { A2AConfig } from \"./types.js\";\nimport { generateAgentCard } from \"./agent-card.js\";\nimport { handleJsonRpcH3, processA2ATaskFromQueue } from \"./handlers.js\";\nimport { readBody } from \"../server/h3-helpers.js\";\nimport {\n extractBearerToken,\n verifyInternalToken,\n} from \"../integrations/internal-token.js\";\n\n/**\n * One-time warning when A2A is running unauthenticated in development. We\n * don't refuse the request (local templates need to work out of the box),\n * but we log a single noisy line so operators notice if they accidentally\n * deploy with no auth configured.\n */\nlet _warnedUnauthA2A = false;\nfunction warnA2AUnauthOnce(): void {\n if (_warnedUnauthA2A) return;\n _warnedUnauthA2A = true;\n // eslint-disable-next-line no-console\n console.warn(\n \"[a2a] No A2A_SECRET or apiKeyEnv configured — A2A endpoint runs unauthenticated. \" +\n \"This is allowed in development but blocked in production. Set A2A_SECRET before deploying.\",\n );\n}\n\n/**\n * Verify an inbound A2A JWT signed with the shared A2A_SECRET.\n * Returns the caller's email (from `sub` claim) if valid, null otherwise.\n */\ninterface A2ATokenPayload {\n email: string | null;\n orgDomain: string | null;\n}\n\n/**\n * Resolve the audience (`aud`) value to expect in an inbound JWT. We use the\n * receiver's app URL — it's the natural identifier of \"who this token was\n * minted for\". Falls back to undefined when no app URL is configured, in\n * which case the audience check is skipped (backward-compat with tokens\n * minted before the audience claim shipped).\n */\nfunction expectedJwtAudience(event: any | undefined): string | undefined {\n const fromEnv =\n process.env.APP_URL ||\n process.env.URL ||\n process.env.DEPLOY_URL ||\n process.env.BETTER_AUTH_URL;\n if (fromEnv) return String(fromEnv);\n // Best-effort: derive from the inbound request host. This is forgeable\n // (Host-header attack), but only useful as a hint when env-derived URL\n // is unset; the rest of the JWT verification still uses the secret.\n try {\n const proto = getRequestHeader(event, \"x-forwarded-proto\") || \"https\";\n const host = getRequestHeader(event, \"host\");\n if (host) return `${proto}://${host}`;\n } catch {}\n return undefined;\n}\n\nasync function verifyA2AToken(\n authHeader: string,\n event: any | undefined,\n): Promise<A2ATokenPayload> {\n const token = authHeader.replace(\"Bearer \", \"\");\n\n // Step 1: Peek at JWT claims WITHOUT verification to get org_domain.\n // This is safe because we only use org_domain to look up the secret,\n // then verify the full JWT with that secret. If someone forges a JWT\n // with a fake org_domain, verification will fail because they don't\n // have the real secret.\n let orgDomainHint: string | undefined;\n let unverifiedPayload: jose.JWTPayload | undefined;\n try {\n unverifiedPayload = jose.decodeJwt(token);\n orgDomainHint = unverifiedPayload.org_domain as string | undefined;\n } catch {\n // Malformed token — fall through to global secret attempt\n }\n\n // Step 2: Look up the org's A2A secret by domain\n let secret: string | undefined;\n if (orgDomainHint) {\n try {\n const { getA2ASecretByDomain } = await import(\"../org/context.js\");\n const orgSecret = await getA2ASecretByDomain(orgDomainHint);\n if (orgSecret) secret = orgSecret;\n } catch {\n // DB not ready or column doesn't exist yet — fall through\n }\n }\n\n // Step 3: Fall back to global A2A_SECRET\n if (!secret) secret = process.env.A2A_SECRET;\n if (!secret) return { email: null, orgDomain: null };\n\n // Step 4: Verify JWT with the resolved secret.\n //\n // - `audience`: passed only when the token carries an `aud` claim\n // (backward-compat: tokens minted by older `signA2AToken` versions\n // don't include one).\n // - `issuer`: enforced when the token carries an `iss` claim. The\n // sender's `signA2AToken` (`a2a/client.ts:42`) sets the issuer to its\n // own app URL, so a verified token must self-identify a non-empty\n // string issuer. We accept any string the token claims (we don't pin\n // a specific expected issuer because dispatchers may legitimately\n // mint tokens from many sender URLs — dev tunnels, multi-deploy\n // setups). The pin is \"issuer must match the value the token says\n // it was minted from\", which `jose.jwtVerify` validates exactly when\n // `issuer` is supplied as a string. Backward-compat: when the token\n // has no `iss`, we skip the check.\n try {\n const verifyOptions: jose.JWTVerifyOptions = {};\n if (unverifiedPayload && typeof unverifiedPayload.aud !== \"undefined\") {\n const aud = expectedJwtAudience(event);\n if (aud) verifyOptions.audience = aud;\n }\n if (\n unverifiedPayload &&\n typeof unverifiedPayload.iss === \"string\" &&\n unverifiedPayload.iss.length > 0\n ) {\n verifyOptions.issuer = unverifiedPayload.iss;\n }\n const { payload } = await jose.jwtVerify(\n token,\n new TextEncoder().encode(secret),\n verifyOptions,\n );\n return {\n email: (payload.sub as string) ?? null,\n orgDomain: (payload.org_domain as string) ?? null,\n };\n } catch {\n return { email: null, orgDomain: null };\n }\n}\n\n/**\n * Mount A2A protocol endpoints on an H3/Nitro app.\n *\n * - GET /.well-known/agent-card.json — public agent card (no auth)\n * - POST /_agent-native/a2a — JSON-RPC endpoint (with optional auth)\n *\n * When A2A_SECRET is set, inbound Bearer tokens are verified as JWTs\n * and the caller's email is extracted from the `sub` claim. This provides\n * cryptographic identity verification for cross-app A2A calls.\n */\nexport function mountA2A(\n nitroApp: any,\n config: A2AConfig,\n routePrefix = \"/_agent-native\",\n): void {\n // Public agent card endpoint (no auth required).\n //\n // SECURITY: per-user / per-org MCP tools are filtered out of the public\n // skills list. Their merged-key prefix (`mcp__user_<emailhash>_…` or\n // `mcp__org_<orgid>_…`) discloses (a) which users have integrations\n // attached, and (b) what those integrations are — fingerprinting the\n // tenant. Template- and framework-defined skills stay; only the dynamic\n // per-tenant MCP entries are dropped. See finding #7 in\n // /tmp/security-audit/12-mcp-a2a-agent.md.\n getH3App(nitroApp).use(\n \"/.well-known/agent-card.json\",\n defineEventHandler((event) => {\n if (getMethod(event) !== \"GET\") {\n setResponseStatus(event, 405);\n return { error: \"Method not allowed\" };\n }\n const protocol =\n getRequestHeader(event, \"x-forwarded-proto\") ||\n (event.url?.protocol?.replace(\":\", \"\") ?? \"http\");\n const host = getRequestHeader(event, \"host\") ?? \"localhost\";\n const baseUrl = `${protocol}://${host}`;\n\n // Filter out per-user/per-org MCP tools to avoid tenant disclosure.\n // Note: stdio MCP tools loaded from a file-based mcp.config.json are\n // process-wide and don't carry a per-user/per-org prefix, so they\n // remain visible. That's intentional — they're an operator-controlled\n // capability list.\n const filteredSkills = (config.skills ?? []).filter((skill) => {\n const id =\n (skill as { id?: string; name?: string }).id ??\n (skill as { name?: string }).name ??\n \"\";\n if (typeof id !== \"string\") return true;\n return !id.startsWith(\"mcp__user_\") && !id.startsWith(\"mcp__org_\");\n });\n\n return generateAgentCard({ ...config, skills: filteredSkills }, baseUrl);\n }),\n );\n\n // Async-mode processor route. MUST be mounted BEFORE the `/a2a` catch-all\n // below, since h3's `.use()` matches by prefix and `/a2a` would otherwise\n // swallow `/a2a/_process-task` and return a JSON-RPC \"Invalid token\" error\n // (the JSON-RPC handler doesn't know about taskId-only bodies).\n //\n // When `message/send` is called with `async: true`, the JSON-RPC handler\n // enqueues the task and self-fires a POST to this route on the same\n // deployment so the actual handler runs in a fresh function execution (its\n // own full timeout). Authenticated with an HMAC token bound to the task id\n // (5-minute lifetime, signed with A2A_SECRET — same scheme as the\n // integration webhook queue).\n getH3App(nitroApp).use(\n `${routePrefix}/a2a/_process-task`,\n defineEventHandler(async (event) => {\n if (getMethod(event) !== \"POST\") {\n setResponseStatus(event, 405);\n return { error: \"Method not allowed\" };\n }\n\n const body = (await readBody(event)) as { taskId?: unknown } | null;\n const taskId = body && typeof body.taskId === \"string\" ? body.taskId : \"\";\n if (!taskId) {\n setResponseStatus(event, 400);\n return { error: \"taskId required\" };\n }\n\n // When A2A_SECRET is set, require a valid HMAC token bound to this\n // taskId. In production, we REQUIRE A2A_SECRET to be set so unsigned\n // dispatches are never accepted (an attacker who fishes a taskId out\n // of logs / a share link could otherwise force-replay it). In\n // development, a missing secret is permitted so local templates work\n // out of the box, but we log a one-time warning so operators notice.\n if (process.env.A2A_SECRET) {\n const auth = getRequestHeader(event, \"authorization\");\n const tok = extractBearerToken(auth);\n if (!verifyInternalToken(taskId, tok)) {\n setResponseStatus(event, 401);\n return { error: \"Invalid or expired processor token\" };\n }\n } else if (process.env.NODE_ENV === \"production\") {\n setResponseStatus(event, 503);\n return {\n error:\n \"A2A processor not configured — set A2A_SECRET on this deployment to enable async A2A.\",\n };\n } else {\n warnA2AUnauthOnce();\n }\n\n try {\n await processA2ATaskFromQueue(taskId, config, event);\n return { ok: true };\n } catch (err: any) {\n console.error(\"[a2a] process-task failed:\", err);\n setResponseStatus(event, 500);\n return { error: err?.message ?? \"process-task failed\" };\n }\n }),\n );\n\n // JSON-RPC A2A endpoint (with optional auth)\n getH3App(nitroApp).use(\n `${routePrefix}/a2a`,\n defineEventHandler(async (event) => {\n if (getMethod(event) !== \"POST\") {\n setResponseStatus(event, 405);\n return { error: \"Method not allowed\" };\n }\n\n // h3 prefix-matches mounts, so a request to `/a2a/_process-task`\n // reaches this handler too. The dedicated mount above runs first and\n // takes the request, but if that returns `undefined` (or h3 ever\n // changes ordering semantics) defensively bail here. event.path is\n // stripped to the remainder after the mount prefix.\n const sub = (event.path || \"/\").split(\"?\")[0].replace(/^\\//, \"\");\n if (sub.startsWith(\"_process-task\")) return;\n\n const authHeader = getRequestHeader(event, \"authorization\");\n let verifiedCallerEmail: string | null = null;\n let verifiedOrgDomain: string | null = null;\n let legacyApiKeyAuthenticated = false;\n let bearerTokenRejectedByJwt = false;\n\n // SECURITY: when neither A2A_SECRET nor an apiKeyEnv is configured,\n // there's no way to authenticate the caller. Default to \"auth required\"\n // in production — return 503 with a clear message instead of running\n // the agent loop unauthenticated. In development, log a one-time\n // warning but allow so local templates work out of the box.\n const hasA2ASecret = !!process.env.A2A_SECRET;\n const hasApiKey = !!(config.apiKeyEnv && process.env[config.apiKeyEnv]);\n\n // Try JWT verification first (org-level or global A2A_SECRET-based identity)\n if (authHeader?.startsWith(\"Bearer \")) {\n const tokenPayload = await verifyA2AToken(authHeader, event);\n verifiedCallerEmail = tokenPayload.email;\n verifiedOrgDomain = tokenPayload.orgDomain;\n bearerTokenRejectedByJwt = !verifiedCallerEmail;\n }\n\n // Fall back to legacy API key check (exact string match)\n if (!verifiedCallerEmail && config.apiKeyEnv) {\n const expectedKey = process.env[config.apiKeyEnv];\n if (expectedKey) {\n if (!authHeader || !authHeader.startsWith(\"Bearer \")) {\n setResponseStatus(event, 401);\n return {\n jsonrpc: \"2.0\",\n id: null,\n error: { code: -32001, message: \"Authentication required\" },\n };\n }\n const token = authHeader.slice(7);\n if (token !== expectedKey) {\n setResponseStatus(event, 401);\n return {\n jsonrpc: \"2.0\",\n id: null,\n error: { code: -32001, message: \"Invalid API key\" },\n };\n }\n legacyApiKeyAuthenticated = true;\n }\n }\n\n if (!verifiedCallerEmail && !legacyApiKeyAuthenticated) {\n // If a global secret exists and JWT verification failed, reject after\n // giving the legacy exact-match apiKeyEnv path a chance to succeed.\n if (bearerTokenRejectedByJwt && process.env.A2A_SECRET) {\n setResponseStatus(event, 401);\n return {\n jsonrpc: \"2.0\",\n id: null,\n error: {\n code: -32001,\n message: \"Invalid or expired A2A token\",\n },\n };\n }\n\n if (!hasA2ASecret && !hasApiKey) {\n if (process.env.NODE_ENV === \"production\") {\n setResponseStatus(event, 503);\n return {\n jsonrpc: \"2.0\",\n id: null,\n error: {\n code: -32001,\n message:\n \"A2A authentication not configured. Set A2A_SECRET (preferred) or configure apiKeyEnv to accept inbound A2A traffic.\",\n },\n };\n }\n warnA2AUnauthOnce();\n }\n }\n\n // Store verified caller identity on the event context so the handler\n // can set request context from a trusted source instead of metadata\n if (verifiedCallerEmail) {\n event.context.__a2aVerifiedEmail = verifiedCallerEmail;\n }\n if (verifiedOrgDomain) {\n event.context.__a2aOrgDomain = verifiedOrgDomain;\n }\n\n const body = await readBody(event);\n return handleJsonRpcH3(body, event, config);\n }),\n );\n}\n"]}
@@ -191,7 +191,7 @@ function isTransientA2APollError(err) {
191
191
  return false;
192
192
  if (err.name === "AbortError")
193
193
  return true;
194
- return /operation was aborted|aborted|timed out|timeout/i.test(err.message);
194
+ return /operation was aborted|aborted|timed out|timeout|Invalid or expired A2A token|A2A request failed \(401\)/i.test(err.message);
195
195
  }
196
196
  function remotePollTimeoutReason(continuation) {
197
197
  return `Timed out polling the ${continuation.agentName} A2A task ${continuation.a2aTaskId} after ${Math.round(MAX_REMOTE_WORK_MS / 60_000)} minutes. The downstream agent did not return a final result.`;
@@ -226,6 +226,9 @@ async function redispatchContinuation(continuationId) {
226
226
  });
227
227
  }
228
228
  async function signContinuationToken(continuation) {
229
+ if (continuation.a2aAuthToken !== null) {
230
+ return continuation.a2aAuthToken || undefined;
231
+ }
229
232
  let orgDomain;
230
233
  let orgSecret;
231
234
  if (continuation.orgId) {
@@ -240,7 +243,9 @@ async function signContinuationToken(continuation) {
240
243
  return undefined;
241
244
  }
242
245
  try {
243
- return await signA2AToken(continuation.ownerEmail, orgDomain, orgSecret);
246
+ return await signA2AToken(continuation.ownerEmail, orgDomain, orgSecret, {
247
+ expiresIn: "30m",
248
+ });
244
249
  }
245
250
  catch {
246
251
  return undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"a2a-continuation-processor.js","sourceRoot":"","sources":["../../src/integrations/a2a-continuation-processor.ts"],"names":[],"mappings":"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","sourcesContent":["import { A2AClient, signA2AToken } from \"../a2a/client.js\";\nimport type { Task } from \"../a2a/types.js\";\nimport { withConfiguredAppBasePath } from \"../server/app-base-path.js\";\nimport { FRAMEWORK_ROUTE_PREFIX } from \"../server/core-routes-plugin.js\";\nimport { signInternalToken } from \"./internal-token.js\";\nimport type { PlatformAdapter } from \"./types.js\";\nimport {\n formatLlmCredentialErrorMessage,\n isLlmCredentialError,\n} from \"../agent/engine/credential-errors.js\";\nimport {\n claimA2AContinuation,\n claimDueA2AContinuations,\n completeA2AContinuation,\n failA2AContinuation,\n getA2AContinuation,\n rescheduleA2AContinuation,\n type A2AContinuation,\n} from \"./a2a-continuations-store.js\";\n\nconst PROCESSOR_PATH = `${FRAMEWORK_ROUTE_PREFIX}/integrations/process-a2a-continuation`;\nconst TERMINAL_STATES = new Set([\"completed\", \"failed\", \"canceled\"]);\nconst MAX_ATTEMPTS = 6;\nconst MAX_REMOTE_WORK_MS = 10 * 60_000;\nconst RESCHEDULE_DELAY_MS = 5_000;\nconst MAX_PRE_CLAIM_WAIT_MS = RESCHEDULE_DELAY_MS + 5_000;\nconst POLL_INTERVAL_MS = 2_000;\nconst PROCESSOR_WAIT_MS = 20_000;\nconst POLL_REQUEST_TIMEOUT_MS = 25_000;\nconst PLATFORM_SEND_TIMEOUT_MS = 12_000;\nconst DISPATCH_SETTLE_WAIT_MS = 2_000;\n\nexport async function dispatchA2AContinuation(\n continuationId: string,\n webhookBaseUrl?: string,\n): Promise<void> {\n const baseUrl =\n webhookBaseUrl ||\n process.env.WEBHOOK_BASE_URL ||\n process.env.APP_URL ||\n process.env.URL ||\n process.env.DEPLOY_URL ||\n `http://localhost:${process.env.PORT || 3000}`;\n\n const url = `${withConfiguredAppBasePath(baseUrl)}${PROCESSOR_PATH}`;\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n try {\n headers[\"Authorization\"] = `Bearer ${signInternalToken(continuationId)}`;\n } catch (err) {\n if (process.env.NODE_ENV === \"production\") {\n console.error(\n `[integrations] Refusing to dispatch A2A continuation ${continuationId} — A2A_SECRET not configured.`,\n );\n return;\n }\n if (err instanceof Error && !/A2A_SECRET/i.test(err.message)) {\n console.error(\n `[integrations] signInternalToken failed unexpectedly for ${continuationId}:`,\n err,\n );\n }\n }\n\n const dispatchPromise = fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ continuationId }),\n })\n .then(async (response) => {\n if (!response.ok) {\n await logFailedDispatchResponse(continuationId, response);\n }\n })\n .catch((err) => {\n console.error(\n `[integrations] Failed to dispatch A2A continuation ${continuationId}:`,\n err,\n );\n });\n\n await Promise.race([\n dispatchPromise,\n new Promise<void>((resolve) =>\n setTimeout(resolve, DISPATCH_SETTLE_WAIT_MS),\n ),\n ]);\n}\n\nasync function logFailedDispatchResponse(\n continuationId: string,\n response: Response,\n): Promise<void> {\n let body = \"\";\n try {\n body = await response.text();\n } catch {}\n\n const trimmedBody = body.trim();\n console.error(\n `[integrations] A2A continuation ${continuationId} processor dispatch returned HTTP ` +\n `${response.status}${response.statusText ? ` ${response.statusText}` : \"\"}` +\n `${trimmedBody ? `: ${trimmedBody.slice(0, 500)}` : \"\"}`,\n );\n}\n\nexport async function processA2AContinuationById(\n continuationId: string,\n options: { adapters: Map<string, PlatformAdapter> },\n): Promise<void> {\n const shouldClaim = await waitForContinuationDue(continuationId);\n if (!shouldClaim) return;\n const continuation = await claimA2AContinuation(continuationId);\n if (!continuation) return;\n await processClaimedContinuation(continuation, options);\n}\n\nexport async function processDueA2AContinuations(options: {\n adapters: Map<string, PlatformAdapter>;\n limit?: number;\n}): Promise<void> {\n const continuations = await claimDueA2AContinuations(options.limit ?? 5);\n for (const continuation of continuations) {\n await processClaimedContinuation(continuation, options).catch((err) =>\n console.error(\n `[integrations] A2A continuation ${continuation.id} failed:`,\n err,\n ),\n );\n }\n}\n\nasync function processClaimedContinuation(\n continuation: A2AContinuation,\n options: { adapters: Map<string, PlatformAdapter> },\n): Promise<void> {\n const adapter = options.adapters.get(continuation.platform);\n if (!adapter) {\n await failA2AContinuation(\n continuation.id,\n `Unknown platform: ${continuation.platform}`,\n );\n return;\n }\n\n const client = new A2AClient(\n continuation.agentUrl,\n await signContinuationToken(continuation),\n { requestTimeoutMs: POLL_REQUEST_TIMEOUT_MS },\n );\n const deadline = Date.now() + PROCESSOR_WAIT_MS;\n let task: Task | null = null;\n\n try {\n while (Date.now() < deadline) {\n task = await client.getTask(continuation.a2aTaskId);\n if (TERMINAL_STATES.has(task.status.state)) break;\n await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));\n }\n } catch (err) {\n if (isTransientA2APollError(err)) {\n if (isRemoteWorkExpired(continuation)) {\n await notifyAndFailA2AContinuation(\n continuation,\n adapter,\n remotePollTimeoutReason(continuation),\n );\n return;\n }\n await rescheduleA2AContinuation(continuation.id, RESCHEDULE_DELAY_MS);\n await redispatchContinuation(continuation.id);\n return;\n }\n if (continuation.attempts >= MAX_ATTEMPTS) {\n await notifyAndFailA2AContinuation(\n continuation,\n adapter,\n err instanceof Error ? err.message : String(err),\n );\n return;\n }\n await rescheduleA2AContinuation(continuation.id, RESCHEDULE_DELAY_MS);\n await redispatchContinuation(continuation.id);\n return;\n }\n\n if (!task || !TERMINAL_STATES.has(task.status.state)) {\n if (isRemoteWorkExpired(continuation)) {\n await notifyAndFailA2AContinuation(\n continuation,\n adapter,\n `Remote A2A task ${continuation.a2aTaskId} did not complete within ${Math.round(\n MAX_REMOTE_WORK_MS / 60_000,\n )} minutes`,\n );\n return;\n }\n await rescheduleA2AContinuation(continuation.id, RESCHEDULE_DELAY_MS);\n await redispatchContinuation(continuation.id);\n return;\n }\n\n if (task.status.state !== \"completed\") {\n const reason =\n extractTaskText(task) ||\n `Remote A2A task ${continuation.a2aTaskId} ended with state ${task.status.state}`;\n await notifyAndFailA2AContinuation(continuation, adapter, reason);\n return;\n }\n\n const text = expandRelativeUrls(extractTaskText(task), continuation.agentUrl);\n if (!text.trim()) {\n await notifyAndFailA2AContinuation(\n continuation,\n adapter,\n `Remote A2A task ${continuation.a2aTaskId} completed without text`,\n );\n return;\n }\n\n try {\n await withTimeout(\n adapter.sendResponse(\n adapter.formatAgentResponse(text),\n continuation.incoming,\n { placeholderRef: continuation.placeholderRef ?? undefined },\n ),\n PLATFORM_SEND_TIMEOUT_MS,\n `${continuation.platform} response delivery timed out`,\n );\n await completeA2AContinuation(continuation.id);\n } catch (err) {\n if (continuation.attempts >= MAX_ATTEMPTS) {\n await failA2AContinuation(\n continuation.id,\n err instanceof Error ? err.message : String(err),\n );\n return;\n }\n await rescheduleA2AContinuation(continuation.id, RESCHEDULE_DELAY_MS);\n await redispatchContinuation(continuation.id);\n }\n}\n\nasync function waitForContinuationDue(\n continuationId: string,\n): Promise<boolean> {\n const continuation = await getA2AContinuation(continuationId);\n if (!continuation) return false;\n if (continuation.status === \"completed\" || continuation.status === \"failed\") {\n return false;\n }\n if (continuation.status !== \"pending\") return true;\n\n const waitMs = continuation.nextCheckAt - Date.now();\n if (waitMs <= 0) return true;\n\n await sleep(Math.min(waitMs, MAX_PRE_CLAIM_WAIT_MS));\n return true;\n}\n\nasync function notifyAndFailA2AContinuation(\n continuation: A2AContinuation,\n adapter: PlatformAdapter,\n reason: string,\n): Promise<void> {\n const message = formatContinuationFailureMessage(continuation, reason);\n try {\n await withTimeout(\n adapter.sendResponse(\n adapter.formatAgentResponse(message),\n continuation.incoming,\n { placeholderRef: continuation.placeholderRef ?? undefined },\n ),\n PLATFORM_SEND_TIMEOUT_MS,\n `${continuation.platform} failure notification timed out`,\n );\n } catch (err) {\n console.error(\n `[integrations] Failed to notify ${continuation.platform} about failed A2A continuation ${continuation.id}:`,\n err,\n );\n }\n\n await failA2AContinuation(continuation.id, reason);\n}\n\nfunction formatContinuationFailureMessage(\n continuation: A2AContinuation,\n reason: string,\n): string {\n if (isLlmCredentialError(reason)) {\n return formatLlmCredentialErrorMessage({\n agentName: continuation.agentName,\n });\n }\n\n return `The ${continuation.agentName} agent could not finish this request: ${sanitizeFailureReason(\n reason,\n )}`;\n}\n\nfunction isRemoteWorkExpired(continuation: A2AContinuation): boolean {\n return Date.now() - continuation.createdAt >= MAX_REMOTE_WORK_MS;\n}\n\nfunction isTransientA2APollError(err: unknown): boolean {\n if (!(err instanceof Error)) return false;\n if (err.name === \"AbortError\") return true;\n return /operation was aborted|aborted|timed out|timeout/i.test(err.message);\n}\n\nfunction remotePollTimeoutReason(continuation: A2AContinuation): string {\n return `Timed out polling the ${continuation.agentName} A2A task ${continuation.a2aTaskId} after ${Math.round(\n MAX_REMOTE_WORK_MS / 60_000,\n )} minutes. The downstream agent did not return a final result.`;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nasync function withTimeout<T>(\n promise: Promise<T>,\n timeoutMs: number,\n message: string,\n): Promise<T> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n return await Promise.race([\n promise,\n new Promise<never>((_, reject) => {\n timer = setTimeout(() => reject(new Error(message)), timeoutMs);\n }),\n ]);\n } finally {\n if (timer) clearTimeout(timer);\n }\n}\n\nfunction sanitizeFailureReason(reason: string): string {\n const oneLine = reason.replace(/\\s+/g, \" \").trim();\n const withoutEnvNames = oneLine.replace(\n /\\b[A-Z][A-Z0-9_]*(?:API_KEY|PRIVATE_KEY|SECRET|TOKEN)\\b/g,\n \"a required credential\",\n );\n return (\n withoutEnvNames.slice(0, 500) ||\n \"the downstream agent returned an empty error\"\n );\n}\n\nasync function redispatchContinuation(continuationId: string): Promise<void> {\n await dispatchA2AContinuation(continuationId).catch((err) => {\n console.error(\n `[integrations] Failed to redispatch A2A continuation ${continuationId}:`,\n err,\n );\n });\n}\n\nasync function signContinuationToken(\n continuation: A2AContinuation,\n): Promise<string | undefined> {\n let orgDomain: string | undefined;\n let orgSecret: string | undefined;\n if (continuation.orgId) {\n try {\n const { getOrgDomain, getOrgA2ASecret } =\n await import(\"../org/context.js\");\n orgDomain = (await getOrgDomain(continuation.orgId)) ?? undefined;\n orgSecret = (await getOrgA2ASecret(continuation.orgId)) ?? undefined;\n } catch {}\n }\n\n if (!continuation.ownerEmail || !(orgSecret || process.env.A2A_SECRET)) {\n return undefined;\n }\n\n try {\n return await signA2AToken(continuation.ownerEmail, orgDomain, orgSecret);\n } catch {\n return undefined;\n }\n}\n\nfunction extractTaskText(task: Task): string {\n const parts = task.status.message?.parts ?? [];\n return parts\n .filter((part): part is { type: \"text\"; text: string } => {\n return part.type === \"text\" && typeof part.text === \"string\";\n })\n .map((part) => part.text)\n .join(\"\\n\");\n}\n\nfunction expandRelativeUrls(text: string, agentUrl: string): string {\n if (!text || !agentUrl) return text;\n const base = agentUrl.replace(/\\/$/, \"\");\n return text.replace(\n /(^|[\\s(\\[<\"'`])(\\/[a-z0-9_-][a-z0-9_/?&=%#.,:-]*)/gi,\n (_match, lead, path) => `${lead}${base}${path}`,\n );\n}\n"]}
1
+ {"version":3,"file":"a2a-continuation-processor.js","sourceRoot":"","sources":["../../src/integrations/a2a-continuation-processor.ts"],"names":[],"mappings":"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","sourcesContent":["import { A2AClient, signA2AToken } from \"../a2a/client.js\";\nimport type { Task } from \"../a2a/types.js\";\nimport { withConfiguredAppBasePath } from \"../server/app-base-path.js\";\nimport { FRAMEWORK_ROUTE_PREFIX } from \"../server/core-routes-plugin.js\";\nimport { signInternalToken } from \"./internal-token.js\";\nimport type { PlatformAdapter } from \"./types.js\";\nimport {\n formatLlmCredentialErrorMessage,\n isLlmCredentialError,\n} from \"../agent/engine/credential-errors.js\";\nimport {\n claimA2AContinuation,\n claimDueA2AContinuations,\n completeA2AContinuation,\n failA2AContinuation,\n getA2AContinuation,\n rescheduleA2AContinuation,\n type A2AContinuation,\n} from \"./a2a-continuations-store.js\";\n\nconst PROCESSOR_PATH = `${FRAMEWORK_ROUTE_PREFIX}/integrations/process-a2a-continuation`;\nconst TERMINAL_STATES = new Set([\"completed\", \"failed\", \"canceled\"]);\nconst MAX_ATTEMPTS = 6;\nconst MAX_REMOTE_WORK_MS = 10 * 60_000;\nconst RESCHEDULE_DELAY_MS = 5_000;\nconst MAX_PRE_CLAIM_WAIT_MS = RESCHEDULE_DELAY_MS + 5_000;\nconst POLL_INTERVAL_MS = 2_000;\nconst PROCESSOR_WAIT_MS = 20_000;\nconst POLL_REQUEST_TIMEOUT_MS = 25_000;\nconst PLATFORM_SEND_TIMEOUT_MS = 12_000;\nconst DISPATCH_SETTLE_WAIT_MS = 2_000;\n\nexport async function dispatchA2AContinuation(\n continuationId: string,\n webhookBaseUrl?: string,\n): Promise<void> {\n const baseUrl =\n webhookBaseUrl ||\n process.env.WEBHOOK_BASE_URL ||\n process.env.APP_URL ||\n process.env.URL ||\n process.env.DEPLOY_URL ||\n `http://localhost:${process.env.PORT || 3000}`;\n\n const url = `${withConfiguredAppBasePath(baseUrl)}${PROCESSOR_PATH}`;\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n try {\n headers[\"Authorization\"] = `Bearer ${signInternalToken(continuationId)}`;\n } catch (err) {\n if (process.env.NODE_ENV === \"production\") {\n console.error(\n `[integrations] Refusing to dispatch A2A continuation ${continuationId} — A2A_SECRET not configured.`,\n );\n return;\n }\n if (err instanceof Error && !/A2A_SECRET/i.test(err.message)) {\n console.error(\n `[integrations] signInternalToken failed unexpectedly for ${continuationId}:`,\n err,\n );\n }\n }\n\n const dispatchPromise = fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ continuationId }),\n })\n .then(async (response) => {\n if (!response.ok) {\n await logFailedDispatchResponse(continuationId, response);\n }\n })\n .catch((err) => {\n console.error(\n `[integrations] Failed to dispatch A2A continuation ${continuationId}:`,\n err,\n );\n });\n\n await Promise.race([\n dispatchPromise,\n new Promise<void>((resolve) =>\n setTimeout(resolve, DISPATCH_SETTLE_WAIT_MS),\n ),\n ]);\n}\n\nasync function logFailedDispatchResponse(\n continuationId: string,\n response: Response,\n): Promise<void> {\n let body = \"\";\n try {\n body = await response.text();\n } catch {}\n\n const trimmedBody = body.trim();\n console.error(\n `[integrations] A2A continuation ${continuationId} processor dispatch returned HTTP ` +\n `${response.status}${response.statusText ? ` ${response.statusText}` : \"\"}` +\n `${trimmedBody ? `: ${trimmedBody.slice(0, 500)}` : \"\"}`,\n );\n}\n\nexport async function processA2AContinuationById(\n continuationId: string,\n options: { adapters: Map<string, PlatformAdapter> },\n): Promise<void> {\n const shouldClaim = await waitForContinuationDue(continuationId);\n if (!shouldClaim) return;\n const continuation = await claimA2AContinuation(continuationId);\n if (!continuation) return;\n await processClaimedContinuation(continuation, options);\n}\n\nexport async function processDueA2AContinuations(options: {\n adapters: Map<string, PlatformAdapter>;\n limit?: number;\n}): Promise<void> {\n const continuations = await claimDueA2AContinuations(options.limit ?? 5);\n for (const continuation of continuations) {\n await processClaimedContinuation(continuation, options).catch((err) =>\n console.error(\n `[integrations] A2A continuation ${continuation.id} failed:`,\n err,\n ),\n );\n }\n}\n\nasync function processClaimedContinuation(\n continuation: A2AContinuation,\n options: { adapters: Map<string, PlatformAdapter> },\n): Promise<void> {\n const adapter = options.adapters.get(continuation.platform);\n if (!adapter) {\n await failA2AContinuation(\n continuation.id,\n `Unknown platform: ${continuation.platform}`,\n );\n return;\n }\n\n const client = new A2AClient(\n continuation.agentUrl,\n await signContinuationToken(continuation),\n { requestTimeoutMs: POLL_REQUEST_TIMEOUT_MS },\n );\n const deadline = Date.now() + PROCESSOR_WAIT_MS;\n let task: Task | null = null;\n\n try {\n while (Date.now() < deadline) {\n task = await client.getTask(continuation.a2aTaskId);\n if (TERMINAL_STATES.has(task.status.state)) break;\n await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));\n }\n } catch (err) {\n if (isTransientA2APollError(err)) {\n if (isRemoteWorkExpired(continuation)) {\n await notifyAndFailA2AContinuation(\n continuation,\n adapter,\n remotePollTimeoutReason(continuation),\n );\n return;\n }\n await rescheduleA2AContinuation(continuation.id, RESCHEDULE_DELAY_MS);\n await redispatchContinuation(continuation.id);\n return;\n }\n if (continuation.attempts >= MAX_ATTEMPTS) {\n await notifyAndFailA2AContinuation(\n continuation,\n adapter,\n err instanceof Error ? err.message : String(err),\n );\n return;\n }\n await rescheduleA2AContinuation(continuation.id, RESCHEDULE_DELAY_MS);\n await redispatchContinuation(continuation.id);\n return;\n }\n\n if (!task || !TERMINAL_STATES.has(task.status.state)) {\n if (isRemoteWorkExpired(continuation)) {\n await notifyAndFailA2AContinuation(\n continuation,\n adapter,\n `Remote A2A task ${continuation.a2aTaskId} did not complete within ${Math.round(\n MAX_REMOTE_WORK_MS / 60_000,\n )} minutes`,\n );\n return;\n }\n await rescheduleA2AContinuation(continuation.id, RESCHEDULE_DELAY_MS);\n await redispatchContinuation(continuation.id);\n return;\n }\n\n if (task.status.state !== \"completed\") {\n const reason =\n extractTaskText(task) ||\n `Remote A2A task ${continuation.a2aTaskId} ended with state ${task.status.state}`;\n await notifyAndFailA2AContinuation(continuation, adapter, reason);\n return;\n }\n\n const text = expandRelativeUrls(extractTaskText(task), continuation.agentUrl);\n if (!text.trim()) {\n await notifyAndFailA2AContinuation(\n continuation,\n adapter,\n `Remote A2A task ${continuation.a2aTaskId} completed without text`,\n );\n return;\n }\n\n try {\n await withTimeout(\n adapter.sendResponse(\n adapter.formatAgentResponse(text),\n continuation.incoming,\n { placeholderRef: continuation.placeholderRef ?? undefined },\n ),\n PLATFORM_SEND_TIMEOUT_MS,\n `${continuation.platform} response delivery timed out`,\n );\n await completeA2AContinuation(continuation.id);\n } catch (err) {\n if (continuation.attempts >= MAX_ATTEMPTS) {\n await failA2AContinuation(\n continuation.id,\n err instanceof Error ? err.message : String(err),\n );\n return;\n }\n await rescheduleA2AContinuation(continuation.id, RESCHEDULE_DELAY_MS);\n await redispatchContinuation(continuation.id);\n }\n}\n\nasync function waitForContinuationDue(\n continuationId: string,\n): Promise<boolean> {\n const continuation = await getA2AContinuation(continuationId);\n if (!continuation) return false;\n if (continuation.status === \"completed\" || continuation.status === \"failed\") {\n return false;\n }\n if (continuation.status !== \"pending\") return true;\n\n const waitMs = continuation.nextCheckAt - Date.now();\n if (waitMs <= 0) return true;\n\n await sleep(Math.min(waitMs, MAX_PRE_CLAIM_WAIT_MS));\n return true;\n}\n\nasync function notifyAndFailA2AContinuation(\n continuation: A2AContinuation,\n adapter: PlatformAdapter,\n reason: string,\n): Promise<void> {\n const message = formatContinuationFailureMessage(continuation, reason);\n try {\n await withTimeout(\n adapter.sendResponse(\n adapter.formatAgentResponse(message),\n continuation.incoming,\n { placeholderRef: continuation.placeholderRef ?? undefined },\n ),\n PLATFORM_SEND_TIMEOUT_MS,\n `${continuation.platform} failure notification timed out`,\n );\n } catch (err) {\n console.error(\n `[integrations] Failed to notify ${continuation.platform} about failed A2A continuation ${continuation.id}:`,\n err,\n );\n }\n\n await failA2AContinuation(continuation.id, reason);\n}\n\nfunction formatContinuationFailureMessage(\n continuation: A2AContinuation,\n reason: string,\n): string {\n if (isLlmCredentialError(reason)) {\n return formatLlmCredentialErrorMessage({\n agentName: continuation.agentName,\n });\n }\n\n return `The ${continuation.agentName} agent could not finish this request: ${sanitizeFailureReason(\n reason,\n )}`;\n}\n\nfunction isRemoteWorkExpired(continuation: A2AContinuation): boolean {\n return Date.now() - continuation.createdAt >= MAX_REMOTE_WORK_MS;\n}\n\nfunction isTransientA2APollError(err: unknown): boolean {\n if (!(err instanceof Error)) return false;\n if (err.name === \"AbortError\") return true;\n return /operation was aborted|aborted|timed out|timeout|Invalid or expired A2A token|A2A request failed \\(401\\)/i.test(\n err.message,\n );\n}\n\nfunction remotePollTimeoutReason(continuation: A2AContinuation): string {\n return `Timed out polling the ${continuation.agentName} A2A task ${continuation.a2aTaskId} after ${Math.round(\n MAX_REMOTE_WORK_MS / 60_000,\n )} minutes. The downstream agent did not return a final result.`;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nasync function withTimeout<T>(\n promise: Promise<T>,\n timeoutMs: number,\n message: string,\n): Promise<T> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n return await Promise.race([\n promise,\n new Promise<never>((_, reject) => {\n timer = setTimeout(() => reject(new Error(message)), timeoutMs);\n }),\n ]);\n } finally {\n if (timer) clearTimeout(timer);\n }\n}\n\nfunction sanitizeFailureReason(reason: string): string {\n const oneLine = reason.replace(/\\s+/g, \" \").trim();\n const withoutEnvNames = oneLine.replace(\n /\\b[A-Z][A-Z0-9_]*(?:API_KEY|PRIVATE_KEY|SECRET|TOKEN)\\b/g,\n \"a required credential\",\n );\n return (\n withoutEnvNames.slice(0, 500) ||\n \"the downstream agent returned an empty error\"\n );\n}\n\nasync function redispatchContinuation(continuationId: string): Promise<void> {\n await dispatchA2AContinuation(continuationId).catch((err) => {\n console.error(\n `[integrations] Failed to redispatch A2A continuation ${continuationId}:`,\n err,\n );\n });\n}\n\nasync function signContinuationToken(\n continuation: A2AContinuation,\n): Promise<string | undefined> {\n if (continuation.a2aAuthToken !== null) {\n return continuation.a2aAuthToken || undefined;\n }\n\n let orgDomain: string | undefined;\n let orgSecret: string | undefined;\n if (continuation.orgId) {\n try {\n const { getOrgDomain, getOrgA2ASecret } =\n await import(\"../org/context.js\");\n orgDomain = (await getOrgDomain(continuation.orgId)) ?? undefined;\n orgSecret = (await getOrgA2ASecret(continuation.orgId)) ?? undefined;\n } catch {}\n }\n\n if (!continuation.ownerEmail || !(orgSecret || process.env.A2A_SECRET)) {\n return undefined;\n }\n\n try {\n return await signA2AToken(continuation.ownerEmail, orgDomain, orgSecret, {\n expiresIn: \"30m\",\n });\n } catch {\n return undefined;\n }\n}\n\nfunction extractTaskText(task: Task): string {\n const parts = task.status.message?.parts ?? [];\n return parts\n .filter((part): part is { type: \"text\"; text: string } => {\n return part.type === \"text\" && typeof part.text === \"string\";\n })\n .map((part) => part.text)\n .join(\"\\n\");\n}\n\nfunction expandRelativeUrls(text: string, agentUrl: string): string {\n if (!text || !agentUrl) return text;\n const base = agentUrl.replace(/\\/$/, \"\");\n return text.replace(\n /(^|[\\s(\\[<\"'`])(\\/[a-z0-9_-][a-z0-9_/?&=%#.,:-]*)/gi,\n (_match, lead, path) => `${lead}${base}${path}`,\n );\n}\n"]}
@@ -12,6 +12,7 @@ export interface A2AContinuation {
12
12
  agentName: string;
13
13
  agentUrl: string;
14
14
  a2aTaskId: string;
15
+ a2aAuthToken: string | null;
15
16
  status: A2AContinuationStatus;
16
17
  attempts: number;
17
18
  nextCheckAt: number;
@@ -31,6 +32,7 @@ export declare function insertA2AContinuation(input: {
31
32
  agentName: string;
32
33
  agentUrl: string;
33
34
  a2aTaskId: string;
35
+ a2aAuthToken?: string | null;
34
36
  }): Promise<A2AContinuation>;
35
37
  export declare function getA2AContinuation(id: string): Promise<A2AContinuation | null>;
36
38
  export declare function claimA2AContinuation(id: string): Promise<A2AContinuation | null>;
@@ -1 +1 @@
1
- {"version":3,"file":"a2a-continuations-store.d.ts","sourceRoot":"","sources":["../../src/integrations/a2a-continuations-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AA0ClD,MAAM,MAAM,qBAAqB,GAC7B,SAAS,GACT,YAAY,GACZ,WAAW,GACX,QAAQ,CAAC;AAEb,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,eAAe,CAAC;IAC1B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,qBAAqB,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AA0BD,wBAAsB,qBAAqB,CAAC,KAAK,EAAE;IACjD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,eAAe,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,eAAe,CAAC,CA4C3B;AA8BD,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,MAAM,GACT,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAQjC;AAED,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,MAAM,GACT,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CA6BjC;AAED,wBAAsB,wBAAwB,CAC5C,KAAK,SAAI,GACR,OAAO,CAAC,eAAe,EAAE,CAAC,CAuB5B;AAED,wBAAsB,yBAAyB,CAC7C,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAUf;AAED,wBAAsB,uBAAuB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAUvE;AAED,wBAAsB,mBAAmB,CACvC,EAAE,EAAE,MAAM,EACV,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,CAUf"}
1
+ {"version":3,"file":"a2a-continuations-store.d.ts","sourceRoot":"","sources":["../../src/integrations/a2a-continuations-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAkDlD,MAAM,MAAM,qBAAqB,GAC7B,SAAS,GACT,YAAY,GACZ,WAAW,GACX,QAAQ,CAAC;AAEb,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,eAAe,CAAC;IAC1B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,EAAE,qBAAqB,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AA2BD,wBAAsB,qBAAqB,CAAC,KAAK,EAAE;IACjD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,eAAe,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B,GAAG,OAAO,CAAC,eAAe,CAAC,CA6C3B;AA8BD,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,MAAM,GACT,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAQjC;AAED,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,MAAM,GACT,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CA6BjC;AAED,wBAAsB,wBAAwB,CAC5C,KAAK,SAAI,GACR,OAAO,CAAC,eAAe,EAAE,CAAC,CAuB5B;AAED,wBAAsB,yBAAyB,CAC7C,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAUf;AAED,wBAAsB,uBAAuB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAUvE;AAED,wBAAsB,mBAAmB,CACvC,EAAE,EAAE,MAAM,EACV,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,CAUf"}
@@ -18,6 +18,7 @@ async function ensureTable() {
18
18
  agent_name TEXT NOT NULL,
19
19
  agent_url TEXT NOT NULL,
20
20
  a2a_task_id TEXT NOT NULL,
21
+ a2a_auth_token TEXT,
21
22
  status TEXT NOT NULL,
22
23
  attempts ${intType()} NOT NULL DEFAULT 0,
23
24
  next_check_at ${intType()} NOT NULL,
@@ -29,6 +30,12 @@ async function ensureTable() {
29
30
  `);
30
31
  await client.execute(`CREATE INDEX IF NOT EXISTS idx_a2a_continuations_status_next ON integration_a2a_continuations(status, next_check_at)`);
31
32
  await client.execute(`CREATE UNIQUE INDEX IF NOT EXISTS idx_a2a_continuations_remote_task ON integration_a2a_continuations(integration_task_id, agent_url, a2a_task_id)`);
33
+ try {
34
+ await client.execute(`ALTER TABLE integration_a2a_continuations ADD COLUMN a2a_auth_token TEXT`);
35
+ }
36
+ catch {
37
+ // Column already exists.
38
+ }
32
39
  })();
33
40
  }
34
41
  return _initPromise;
@@ -46,6 +53,7 @@ function rowToContinuation(row) {
46
53
  agentName: row.agent_name,
47
54
  agentUrl: row.agent_url,
48
55
  a2aTaskId: row.a2a_task_id,
56
+ a2aAuthToken: row.a2a_auth_token ?? null,
49
57
  status: row.status,
50
58
  attempts: Number(row.attempts ?? 0),
51
59
  nextCheckAt: Number(row.next_check_at ?? 0),
@@ -65,9 +73,9 @@ export async function insertA2AContinuation(input) {
65
73
  await client.execute({
66
74
  sql: `INSERT INTO integration_a2a_continuations
67
75
  (id, integration_task_id, platform, external_thread_id, incoming_payload,
68
- placeholder_ref, owner_email, org_id, agent_name, agent_url, a2a_task_id,
76
+ placeholder_ref, owner_email, org_id, agent_name, agent_url, a2a_task_id, a2a_auth_token,
69
77
  status, attempts, next_check_at, created_at, updated_at)
70
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
78
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
71
79
  args: [
72
80
  id,
73
81
  input.integrationTaskId,
@@ -80,6 +88,7 @@ export async function insertA2AContinuation(input) {
80
88
  input.agentName,
81
89
  input.agentUrl,
82
90
  input.a2aTaskId,
91
+ input.a2aAuthToken ?? null,
83
92
  "pending",
84
93
  0,
85
94
  now,
@@ -1 +1 @@
1
- {"version":3,"file":"a2a-continuations-store.js","sourceRoot":"","sources":["../../src/integrations/a2a-continuations-store.ts"],"names":[],"mappings":"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","sourcesContent":["import { getDbExec, isPostgres, intType } from \"../db/client.js\";\nimport type { IncomingMessage } from \"./types.js\";\n\nlet _initPromise: Promise<void> | undefined;\nconst PROCESSING_STUCK_AFTER_MS = 5 * 60 * 1000;\n\nasync function ensureTable(): Promise<void> {\n if (!_initPromise) {\n _initPromise = (async () => {\n const client = getDbExec();\n await client.execute(`\n CREATE TABLE IF NOT EXISTS integration_a2a_continuations (\n id TEXT PRIMARY KEY,\n integration_task_id TEXT NOT NULL,\n platform TEXT NOT NULL,\n external_thread_id TEXT NOT NULL,\n incoming_payload TEXT NOT NULL,\n placeholder_ref TEXT,\n owner_email TEXT NOT NULL,\n org_id TEXT,\n agent_name TEXT NOT NULL,\n agent_url TEXT NOT NULL,\n a2a_task_id TEXT NOT NULL,\n status TEXT NOT NULL,\n attempts ${intType()} NOT NULL DEFAULT 0,\n next_check_at ${intType()} NOT NULL,\n error_message TEXT,\n created_at ${intType()} NOT NULL,\n updated_at ${intType()} NOT NULL,\n completed_at ${intType()}\n )\n `);\n await client.execute(\n `CREATE INDEX IF NOT EXISTS idx_a2a_continuations_status_next ON integration_a2a_continuations(status, next_check_at)`,\n );\n await client.execute(\n `CREATE UNIQUE INDEX IF NOT EXISTS idx_a2a_continuations_remote_task ON integration_a2a_continuations(integration_task_id, agent_url, a2a_task_id)`,\n );\n })();\n }\n return _initPromise;\n}\n\nexport type A2AContinuationStatus =\n | \"pending\"\n | \"processing\"\n | \"completed\"\n | \"failed\";\n\nexport interface A2AContinuation {\n id: string;\n integrationTaskId: string;\n platform: string;\n externalThreadId: string;\n incoming: IncomingMessage;\n placeholderRef: string | null;\n ownerEmail: string;\n orgId: string | null;\n agentName: string;\n agentUrl: string;\n a2aTaskId: string;\n status: A2AContinuationStatus;\n attempts: number;\n nextCheckAt: number;\n errorMessage: string | null;\n createdAt: number;\n updatedAt: number;\n completedAt: number | null;\n}\n\nfunction rowToContinuation(row: Record<string, unknown>): A2AContinuation {\n return {\n id: row.id as string,\n integrationTaskId: row.integration_task_id as string,\n platform: row.platform as string,\n externalThreadId: row.external_thread_id as string,\n incoming: JSON.parse(row.incoming_payload as string) as IncomingMessage,\n placeholderRef: (row.placeholder_ref as string | null) ?? null,\n ownerEmail: row.owner_email as string,\n orgId: (row.org_id as string | null) ?? null,\n agentName: row.agent_name as string,\n agentUrl: row.agent_url as string,\n a2aTaskId: row.a2a_task_id as string,\n status: row.status as A2AContinuationStatus,\n attempts: Number(row.attempts ?? 0),\n nextCheckAt: Number(row.next_check_at ?? 0),\n errorMessage: (row.error_message as string | null) ?? null,\n createdAt: Number(row.created_at ?? 0),\n updatedAt: Number(row.updated_at ?? 0),\n completedAt:\n row.completed_at == null ? null : Number(row.completed_at as number),\n };\n}\n\nexport async function insertA2AContinuation(input: {\n integrationTaskId: string;\n platform: string;\n externalThreadId: string;\n incoming: IncomingMessage;\n placeholderRef?: string | null;\n ownerEmail: string;\n orgId?: string | null;\n agentName: string;\n agentUrl: string;\n a2aTaskId: string;\n}): Promise<A2AContinuation> {\n await ensureTable();\n const client = getDbExec();\n const now = Date.now();\n const id = `a2a-cont-${now}-${Math.random().toString(36).slice(2, 8)}`;\n const payload = JSON.stringify(input.incoming);\n\n try {\n await client.execute({\n sql: `INSERT INTO integration_a2a_continuations\n (id, integration_task_id, platform, external_thread_id, incoming_payload,\n placeholder_ref, owner_email, org_id, agent_name, agent_url, a2a_task_id,\n status, attempts, next_check_at, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n id,\n input.integrationTaskId,\n input.platform,\n input.externalThreadId,\n payload,\n input.placeholderRef ?? null,\n input.ownerEmail,\n input.orgId ?? null,\n input.agentName,\n input.agentUrl,\n input.a2aTaskId,\n \"pending\",\n 0,\n now,\n now,\n now,\n ],\n });\n return (await getA2AContinuation(id))!;\n } catch (err: any) {\n if (!isDuplicateContinuationError(err)) throw err;\n const existing = await findA2AContinuation(\n input.integrationTaskId,\n input.agentUrl,\n input.a2aTaskId,\n );\n if (existing) return existing;\n throw err;\n }\n}\n\nfunction isDuplicateContinuationError(err: unknown): boolean {\n const e = err as { code?: string; message?: string } | null;\n if (!e) return false;\n if (e.code === \"23505\") return true;\n const msg = String(e.message ?? \"\").toLowerCase();\n return (\n msg.includes(\"unique\") ||\n msg.includes(\"duplicate entry\") ||\n msg.includes(\"duplicate key\")\n );\n}\n\nasync function findA2AContinuation(\n integrationTaskId: string,\n agentUrl: string,\n a2aTaskId: string,\n): Promise<A2AContinuation | null> {\n await ensureTable();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT * FROM integration_a2a_continuations\n WHERE integration_task_id = ? AND agent_url = ? AND a2a_task_id = ?\n LIMIT 1`,\n args: [integrationTaskId, agentUrl, a2aTaskId],\n });\n return rows[0] ? rowToContinuation(rows[0] as Record<string, unknown>) : null;\n}\n\nexport async function getA2AContinuation(\n id: string,\n): Promise<A2AContinuation | null> {\n await ensureTable();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT * FROM integration_a2a_continuations WHERE id = ? LIMIT 1`,\n args: [id],\n });\n return rows[0] ? rowToContinuation(rows[0] as Record<string, unknown>) : null;\n}\n\nexport async function claimA2AContinuation(\n id: string,\n): Promise<A2AContinuation | null> {\n await ensureTable();\n const client = getDbExec();\n const now = Date.now();\n const processingCutoff = now - PROCESSING_STUCK_AFTER_MS;\n const result = await client.execute({\n sql: isPostgres()\n ? `UPDATE integration_a2a_continuations\n SET status = ?, attempts = attempts + 1, updated_at = ?\n WHERE id = ?\n AND (status = 'pending' OR (status = 'processing' AND updated_at <= ?))\n RETURNING *`\n : `UPDATE integration_a2a_continuations\n SET status = ?, attempts = attempts + 1, updated_at = ?\n WHERE id = ?\n AND (status = 'pending' OR (status = 'processing' AND updated_at <= ?))`,\n args: [\"processing\", now, id, processingCutoff],\n });\n const rows = result.rows ?? [];\n if (isPostgres()) {\n return rows[0]\n ? rowToContinuation(rows[0] as Record<string, unknown>)\n : null;\n }\n const affected = (result as any)?.rowsAffected ?? (result as any)?.rowCount;\n if (affected === 0) return null;\n const fetched = await getA2AContinuation(id);\n if (!fetched || fetched.status !== \"processing\") return null;\n return fetched;\n}\n\nexport async function claimDueA2AContinuations(\n limit = 5,\n): Promise<A2AContinuation[]> {\n await ensureTable();\n const client = getDbExec();\n const now = Date.now();\n await client.execute({\n sql: `UPDATE integration_a2a_continuations\n SET status = ?, next_check_at = ?, updated_at = ?\n WHERE status = 'processing' AND updated_at <= ?`,\n args: [\"pending\", now, now, now - 5 * 60 * 1000],\n });\n const { rows } = await client.execute({\n sql: `SELECT id FROM integration_a2a_continuations\n WHERE status = 'pending' AND next_check_at <= ?\n ORDER BY next_check_at ASC\n LIMIT ?`,\n args: [now, limit],\n });\n const claimed: A2AContinuation[] = [];\n for (const row of rows) {\n const continuation = await claimA2AContinuation(row.id as string);\n if (continuation) claimed.push(continuation);\n }\n return claimed;\n}\n\nexport async function rescheduleA2AContinuation(\n id: string,\n delayMs: number,\n): Promise<void> {\n await ensureTable();\n const client = getDbExec();\n const now = Date.now();\n await client.execute({\n sql: `UPDATE integration_a2a_continuations\n SET status = ?, next_check_at = ?, updated_at = ?\n WHERE id = ? AND status = 'processing'`,\n args: [\"pending\", now + delayMs, now, id],\n });\n}\n\nexport async function completeA2AContinuation(id: string): Promise<void> {\n await ensureTable();\n const client = getDbExec();\n const now = Date.now();\n await client.execute({\n sql: `UPDATE integration_a2a_continuations\n SET status = ?, updated_at = ?, completed_at = ?\n WHERE id = ?`,\n args: [\"completed\", now, now, id],\n });\n}\n\nexport async function failA2AContinuation(\n id: string,\n errorMessage: string,\n): Promise<void> {\n await ensureTable();\n const client = getDbExec();\n const now = Date.now();\n await client.execute({\n sql: `UPDATE integration_a2a_continuations\n SET status = ?, updated_at = ?, error_message = ?\n WHERE id = ?`,\n args: [\"failed\", now, errorMessage.slice(0, 2000), id],\n });\n}\n"]}
1
+ {"version":3,"file":"a2a-continuations-store.js","sourceRoot":"","sources":["../../src/integrations/a2a-continuations-store.ts"],"names":[],"mappings":"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","sourcesContent":["import { getDbExec, isPostgres, intType } from \"../db/client.js\";\nimport type { IncomingMessage } from \"./types.js\";\n\nlet _initPromise: Promise<void> | undefined;\nconst PROCESSING_STUCK_AFTER_MS = 5 * 60 * 1000;\n\nasync function ensureTable(): Promise<void> {\n if (!_initPromise) {\n _initPromise = (async () => {\n const client = getDbExec();\n await client.execute(`\n CREATE TABLE IF NOT EXISTS integration_a2a_continuations (\n id TEXT PRIMARY KEY,\n integration_task_id TEXT NOT NULL,\n platform TEXT NOT NULL,\n external_thread_id TEXT NOT NULL,\n incoming_payload TEXT NOT NULL,\n placeholder_ref TEXT,\n owner_email TEXT NOT NULL,\n org_id TEXT,\n agent_name TEXT NOT NULL,\n agent_url TEXT NOT NULL,\n a2a_task_id TEXT NOT NULL,\n a2a_auth_token TEXT,\n status TEXT NOT NULL,\n attempts ${intType()} NOT NULL DEFAULT 0,\n next_check_at ${intType()} NOT NULL,\n error_message TEXT,\n created_at ${intType()} NOT NULL,\n updated_at ${intType()} NOT NULL,\n completed_at ${intType()}\n )\n `);\n await client.execute(\n `CREATE INDEX IF NOT EXISTS idx_a2a_continuations_status_next ON integration_a2a_continuations(status, next_check_at)`,\n );\n await client.execute(\n `CREATE UNIQUE INDEX IF NOT EXISTS idx_a2a_continuations_remote_task ON integration_a2a_continuations(integration_task_id, agent_url, a2a_task_id)`,\n );\n try {\n await client.execute(\n `ALTER TABLE integration_a2a_continuations ADD COLUMN a2a_auth_token TEXT`,\n );\n } catch {\n // Column already exists.\n }\n })();\n }\n return _initPromise;\n}\n\nexport type A2AContinuationStatus =\n | \"pending\"\n | \"processing\"\n | \"completed\"\n | \"failed\";\n\nexport interface A2AContinuation {\n id: string;\n integrationTaskId: string;\n platform: string;\n externalThreadId: string;\n incoming: IncomingMessage;\n placeholderRef: string | null;\n ownerEmail: string;\n orgId: string | null;\n agentName: string;\n agentUrl: string;\n a2aTaskId: string;\n a2aAuthToken: string | null;\n status: A2AContinuationStatus;\n attempts: number;\n nextCheckAt: number;\n errorMessage: string | null;\n createdAt: number;\n updatedAt: number;\n completedAt: number | null;\n}\n\nfunction rowToContinuation(row: Record<string, unknown>): A2AContinuation {\n return {\n id: row.id as string,\n integrationTaskId: row.integration_task_id as string,\n platform: row.platform as string,\n externalThreadId: row.external_thread_id as string,\n incoming: JSON.parse(row.incoming_payload as string) as IncomingMessage,\n placeholderRef: (row.placeholder_ref as string | null) ?? null,\n ownerEmail: row.owner_email as string,\n orgId: (row.org_id as string | null) ?? null,\n agentName: row.agent_name as string,\n agentUrl: row.agent_url as string,\n a2aTaskId: row.a2a_task_id as string,\n a2aAuthToken: (row.a2a_auth_token as string | null) ?? null,\n status: row.status as A2AContinuationStatus,\n attempts: Number(row.attempts ?? 0),\n nextCheckAt: Number(row.next_check_at ?? 0),\n errorMessage: (row.error_message as string | null) ?? null,\n createdAt: Number(row.created_at ?? 0),\n updatedAt: Number(row.updated_at ?? 0),\n completedAt:\n row.completed_at == null ? null : Number(row.completed_at as number),\n };\n}\n\nexport async function insertA2AContinuation(input: {\n integrationTaskId: string;\n platform: string;\n externalThreadId: string;\n incoming: IncomingMessage;\n placeholderRef?: string | null;\n ownerEmail: string;\n orgId?: string | null;\n agentName: string;\n agentUrl: string;\n a2aTaskId: string;\n a2aAuthToken?: string | null;\n}): Promise<A2AContinuation> {\n await ensureTable();\n const client = getDbExec();\n const now = Date.now();\n const id = `a2a-cont-${now}-${Math.random().toString(36).slice(2, 8)}`;\n const payload = JSON.stringify(input.incoming);\n\n try {\n await client.execute({\n sql: `INSERT INTO integration_a2a_continuations\n (id, integration_task_id, platform, external_thread_id, incoming_payload,\n placeholder_ref, owner_email, org_id, agent_name, agent_url, a2a_task_id, a2a_auth_token,\n status, attempts, next_check_at, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n id,\n input.integrationTaskId,\n input.platform,\n input.externalThreadId,\n payload,\n input.placeholderRef ?? null,\n input.ownerEmail,\n input.orgId ?? null,\n input.agentName,\n input.agentUrl,\n input.a2aTaskId,\n input.a2aAuthToken ?? null,\n \"pending\",\n 0,\n now,\n now,\n now,\n ],\n });\n return (await getA2AContinuation(id))!;\n } catch (err: any) {\n if (!isDuplicateContinuationError(err)) throw err;\n const existing = await findA2AContinuation(\n input.integrationTaskId,\n input.agentUrl,\n input.a2aTaskId,\n );\n if (existing) return existing;\n throw err;\n }\n}\n\nfunction isDuplicateContinuationError(err: unknown): boolean {\n const e = err as { code?: string; message?: string } | null;\n if (!e) return false;\n if (e.code === \"23505\") return true;\n const msg = String(e.message ?? \"\").toLowerCase();\n return (\n msg.includes(\"unique\") ||\n msg.includes(\"duplicate entry\") ||\n msg.includes(\"duplicate key\")\n );\n}\n\nasync function findA2AContinuation(\n integrationTaskId: string,\n agentUrl: string,\n a2aTaskId: string,\n): Promise<A2AContinuation | null> {\n await ensureTable();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT * FROM integration_a2a_continuations\n WHERE integration_task_id = ? AND agent_url = ? AND a2a_task_id = ?\n LIMIT 1`,\n args: [integrationTaskId, agentUrl, a2aTaskId],\n });\n return rows[0] ? rowToContinuation(rows[0] as Record<string, unknown>) : null;\n}\n\nexport async function getA2AContinuation(\n id: string,\n): Promise<A2AContinuation | null> {\n await ensureTable();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT * FROM integration_a2a_continuations WHERE id = ? LIMIT 1`,\n args: [id],\n });\n return rows[0] ? rowToContinuation(rows[0] as Record<string, unknown>) : null;\n}\n\nexport async function claimA2AContinuation(\n id: string,\n): Promise<A2AContinuation | null> {\n await ensureTable();\n const client = getDbExec();\n const now = Date.now();\n const processingCutoff = now - PROCESSING_STUCK_AFTER_MS;\n const result = await client.execute({\n sql: isPostgres()\n ? `UPDATE integration_a2a_continuations\n SET status = ?, attempts = attempts + 1, updated_at = ?\n WHERE id = ?\n AND (status = 'pending' OR (status = 'processing' AND updated_at <= ?))\n RETURNING *`\n : `UPDATE integration_a2a_continuations\n SET status = ?, attempts = attempts + 1, updated_at = ?\n WHERE id = ?\n AND (status = 'pending' OR (status = 'processing' AND updated_at <= ?))`,\n args: [\"processing\", now, id, processingCutoff],\n });\n const rows = result.rows ?? [];\n if (isPostgres()) {\n return rows[0]\n ? rowToContinuation(rows[0] as Record<string, unknown>)\n : null;\n }\n const affected = (result as any)?.rowsAffected ?? (result as any)?.rowCount;\n if (affected === 0) return null;\n const fetched = await getA2AContinuation(id);\n if (!fetched || fetched.status !== \"processing\") return null;\n return fetched;\n}\n\nexport async function claimDueA2AContinuations(\n limit = 5,\n): Promise<A2AContinuation[]> {\n await ensureTable();\n const client = getDbExec();\n const now = Date.now();\n await client.execute({\n sql: `UPDATE integration_a2a_continuations\n SET status = ?, next_check_at = ?, updated_at = ?\n WHERE status = 'processing' AND updated_at <= ?`,\n args: [\"pending\", now, now, now - 5 * 60 * 1000],\n });\n const { rows } = await client.execute({\n sql: `SELECT id FROM integration_a2a_continuations\n WHERE status = 'pending' AND next_check_at <= ?\n ORDER BY next_check_at ASC\n LIMIT ?`,\n args: [now, limit],\n });\n const claimed: A2AContinuation[] = [];\n for (const row of rows) {\n const continuation = await claimA2AContinuation(row.id as string);\n if (continuation) claimed.push(continuation);\n }\n return claimed;\n}\n\nexport async function rescheduleA2AContinuation(\n id: string,\n delayMs: number,\n): Promise<void> {\n await ensureTable();\n const client = getDbExec();\n const now = Date.now();\n await client.execute({\n sql: `UPDATE integration_a2a_continuations\n SET status = ?, next_check_at = ?, updated_at = ?\n WHERE id = ? AND status = 'processing'`,\n args: [\"pending\", now + delayMs, now, id],\n });\n}\n\nexport async function completeA2AContinuation(id: string): Promise<void> {\n await ensureTable();\n const client = getDbExec();\n const now = Date.now();\n await client.execute({\n sql: `UPDATE integration_a2a_continuations\n SET status = ?, updated_at = ?, completed_at = ?\n WHERE id = ?`,\n args: [\"completed\", now, now, id],\n });\n}\n\nexport async function failA2AContinuation(\n id: string,\n errorMessage: string,\n): Promise<void> {\n await ensureTable();\n const client = getDbExec();\n const now = Date.now();\n await client.execute({\n sql: `UPDATE integration_a2a_continuations\n SET status = ?, updated_at = ?, error_message = ?\n WHERE id = ?`,\n args: [\"failed\", now, errorMessage.slice(0, 2000), id],\n });\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"call-agent.d.ts","sourceRoot":"","sources":["../../src/scripts/call-agent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAqDrE,eAAO,MAAM,IAAI,EAAE,UAqBlB,CAAC;AAEF,wBAAsB,GAAG,CACvB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,OAAO,CAAC,EAAE,gBAAgB,EAC1B,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CAoMjB;AA+CD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CASzE"}
1
+ {"version":3,"file":"call-agent.d.ts","sourceRoot":"","sources":["../../src/scripts/call-agent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAsDrE,eAAO,MAAM,IAAI,EAAE,UAqBlB,CAAC;AAEF,wBAAsB,GAAG,CACvB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,OAAO,CAAC,EAAE,gBAAgB,EAC1B,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CAuMjB;AAiDD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CASzE"}
@@ -4,6 +4,7 @@ import { getRequestUserEmail, getRequestOrgId, isIntegrationCallerRequest, getIn
4
4
  import { getOrgDomain, getOrgA2ASecret } from "../org/context.js";
5
5
  const DEFAULT_SERVERLESS_INTEGRATION_A2A_TIMEOUT_MS = 18_000;
6
6
  const NETLIFY_INTEGRATION_A2A_TIMEOUT_MS = 50_000;
7
+ const INTEGRATION_A2A_TOKEN_TTL = "30m";
7
8
  function parseTimeoutMs(value) {
8
9
  if (!value)
9
10
  return undefined;
@@ -111,7 +112,7 @@ export async function run(args, context, selfAppId) {
111
112
  let apiKey;
112
113
  if (callerEmail && (callerOrgSecret || process.env.A2A_SECRET)) {
113
114
  try {
114
- apiKey = await signA2AToken(callerEmail, callerOrgDomain, callerOrgSecret);
115
+ apiKey = await signA2AToken(callerEmail, callerOrgDomain, callerOrgSecret, { expiresIn: INTEGRATION_A2A_TOKEN_TTL });
115
116
  }
116
117
  catch { }
117
118
  }
@@ -164,6 +165,7 @@ export async function run(args, context, selfAppId) {
164
165
  // still need to finish before their current function execution dies.
165
166
  const callTimeoutMs = getIntegrationCallTimeoutMs();
166
167
  responseText = await callAgent(agent.url, messageWithHint, {
168
+ apiKey,
167
169
  userEmail: callerEmail,
168
170
  orgDomain: callerOrgDomain,
169
171
  orgSecret: callerOrgSecret,
@@ -180,7 +182,7 @@ export async function run(args, context, selfAppId) {
180
182
  }
181
183
  catch (pollErr) {
182
184
  if (pollErr instanceof A2ATaskTimeoutError) {
183
- const queued = await enqueueIntegrationContinuationIfPossible(pollErr, agent, callerEmail);
185
+ const queued = await enqueueIntegrationContinuationIfPossible(pollErr, agent, callerEmail, apiKey);
184
186
  if (queued) {
185
187
  responseText = `The ${agent.name} agent is still working. I will update this thread with the final result when it finishes.`;
186
188
  emitNewText(responseText);
@@ -235,7 +237,7 @@ export async function run(args, context, selfAppId) {
235
237
  return `Error calling ${agent.name}: ${msg}`;
236
238
  }
237
239
  }
238
- async function enqueueIntegrationContinuationIfPossible(error, agent, ownerEmail) {
240
+ async function enqueueIntegrationContinuationIfPossible(error, agent, ownerEmail, a2aAuthToken) {
239
241
  const integration = getIntegrationRequestContext();
240
242
  if (!integration || !ownerEmail)
241
243
  return false;
@@ -255,6 +257,7 @@ async function enqueueIntegrationContinuationIfPossible(error, agent, ownerEmail
255
257
  agentName: agent.name,
256
258
  agentUrl: agent.url,
257
259
  a2aTaskId: error.taskId,
260
+ a2aAuthToken: a2aAuthToken ?? "",
258
261
  });
259
262
  await dispatchA2AContinuation(continuation.id).catch((err) => {
260
263
  console.error(`[call-agent] Failed to dispatch A2A continuation ${continuation.id}:`, err);
@@ -1 +1 @@
1
- {"version":3,"file":"call-agent.js","sourceRoot":"","sources":["../../src/scripts/call-agent.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ActionTool } from \"../agent/types.js\";\nimport type { ActionRunContext } from \"../agent/production-agent.js\";\nimport { findAgent, discoverAgents } from \"../server/agent-discovery.js\";\nimport {\n A2AClient,\n A2ATaskTimeoutError,\n callAgent,\n signA2AToken,\n} from \"../a2a/client.js\";\nimport {\n getRequestUserEmail,\n getRequestOrgId,\n isIntegrationCallerRequest,\n getIntegrationRequestContext,\n} from \"../server/request-context.js\";\nimport { getOrgDomain, getOrgA2ASecret } from \"../org/context.js\";\n\nconst DEFAULT_SERVERLESS_INTEGRATION_A2A_TIMEOUT_MS = 18_000;\nconst NETLIFY_INTEGRATION_A2A_TIMEOUT_MS = 50_000;\n\nfunction parseTimeoutMs(value: string | undefined): number | undefined {\n if (!value) return undefined;\n const parsed = Number(value);\n if (!Number.isFinite(parsed) || parsed <= 0) return undefined;\n return Math.floor(parsed);\n}\n\nfunction isServerlessHost(): boolean {\n // Detection mirrors db/migrations.ts:297-301. On Cloudflare Workers/Pages,\n // `process.env` is shimmed and CF_PAGES isn't reliably populated at runtime —\n // the canonical signal is the `__cf_env` global injected by workerd.\n return (\n !!process.env.NETLIFY ||\n !!process.env.AWS_LAMBDA_FUNCTION_NAME ||\n !!process.env.VERCEL ||\n \"__cf_env\" in globalThis\n );\n}\n\nfunction getIntegrationCallTimeoutMs(): number | undefined {\n if (!isServerlessHost() || !isIntegrationCallerRequest()) return undefined;\n\n const configured = parseTimeoutMs(\n process.env.AGENT_NATIVE_INTEGRATION_A2A_TIMEOUT_MS,\n );\n if (configured !== undefined) return configured;\n\n // Netlify's current synchronous function budget is 60s, but leave room for\n // cold start, polling overhead, and the caller's final platform response.\n if (process.env.NETLIFY) return NETLIFY_INTEGRATION_A2A_TIMEOUT_MS;\n\n return DEFAULT_SERVERLESS_INTEGRATION_A2A_TIMEOUT_MS;\n}\n\nexport const tool: ActionTool = {\n description:\n \"Call a DIFFERENT, separately-deployed agent app to ask a question or delegate a task. This is strictly for cross-app A2A communication — for example, asking the mail agent to send an email while you are the calendar agent. NEVER use this to call your own app or perform actions you can do with your own tools. Using call-agent on yourself will fail and waste time. \" +\n \"IMPORTANT — handling the response: \" +\n \"(a) If it contains a URL or ID, copy it VERBATIM into your reply. Do not 'correct' or pluralize the path (e.g. /deck/ → /decks/), normalize casing, or change the slug — any edit breaks the link. \" +\n '(b) If it does NOT contain a URL/ID and the user asked for one, say so explicitly (e.g. \"the agent created the deck but didn\\'t return a link — open the app directly to view it\"). NEVER invent a URL, slug, or path — guessing produces broken links that look real.',\n parameters: {\n type: \"object\",\n properties: {\n agent: {\n type: \"string\",\n description:\n \"Name or URL of a DIFFERENT deployed agent app (e.g. 'mail', 'calendar', 'analytics'). Must not be the current app's own name.\",\n },\n message: {\n type: \"string\",\n description: \"The message/question to send to the other agent\",\n },\n },\n required: [\"agent\", \"message\"],\n },\n};\n\nexport async function run(\n args: Record<string, string>,\n context?: ActionRunContext,\n selfAppId?: string,\n): Promise<string> {\n const { agent: agentIdOrName, message } = args;\n\n if (!agentIdOrName) return \"Error: --agent is required\";\n if (!message) return \"Error: --message is required\";\n\n // Prevent self-calls — the agent must use its own registered tools instead\n if (selfAppId && agentIdOrName.toLowerCase() === selfAppId.toLowerCase()) {\n return `Error: You cannot use call-agent to call yourself (${selfAppId}). Use your own registered actions/tools instead. call-agent is only for communicating with OTHER separately-deployed apps.`;\n }\n\n const agent = await findAgent(agentIdOrName, selfAppId);\n if (!agent) {\n const available = (await discoverAgents(selfAppId))\n .map((a) => a.name)\n .join(\", \");\n return `Error: Agent \"${agentIdOrName}\" not found. Available agents: ${available || \"(none)\"}`;\n }\n\n // Append a small cross-app hint to the outgoing message so the receiving\n // agent (which may be on an older deploy without the receiver-side hint\n // in handlers.ts) still emits fully-qualified URLs. This is belt-and-\n // suspenders with the receiver hint — but it works against any current\n // deployment, no redeploy required.\n const messageWithHint =\n `${message}\\n\\n` +\n `[Note: this request comes from another app via A2A. The caller cannot see your local UI, deck list, or navigation — only the literal text you put in your reply. ` +\n `If you create or reference a deck/document/dashboard, include its FULLY-QUALIFIED URL (e.g. ${agent.url}/deck/<id>) in your reply, not a relative path. ` +\n `Use only IDs returned by your own actions — never invent slugs or hosts.]`;\n\n try {\n // If we have a send context, use streaming so the UI shows progressive text\n if (context?.send) {\n const callerEmail = getRequestUserEmail();\n\n // Build metadata with identity\n const a2aMetadata: Record<string, unknown> = {};\n if (callerEmail) a2aMetadata.userEmail = callerEmail;\n\n // Include org domain for cross-app org resolution\n let callerOrgDomain: string | undefined;\n let callerOrgSecret: string | undefined;\n const orgId = getRequestOrgId();\n if (orgId) {\n try {\n const domain = await getOrgDomain(orgId);\n if (domain) {\n callerOrgDomain = domain;\n a2aMetadata.orgDomain = domain;\n }\n } catch {}\n try {\n const secret = await getOrgA2ASecret(orgId);\n if (secret) callerOrgSecret = secret;\n } catch {}\n }\n\n // Sign JWT with identity + org domain for the streaming client\n let apiKey: string | undefined;\n if (callerEmail && (callerOrgSecret || process.env.A2A_SECRET)) {\n try {\n apiKey = await signA2AToken(\n callerEmail,\n callerOrgDomain,\n callerOrgSecret,\n );\n } catch {}\n }\n\n const client = new A2AClient(agent.url, apiKey);\n\n if (process.env.NODE_ENV === \"production\" && callerEmail) {\n try {\n const { listOAuthAccountsByOwner } =\n await import(\"../oauth-tokens/store.js\");\n const accounts = await listOAuthAccountsByOwner(\n \"google\",\n callerEmail,\n );\n const tokens = accounts[0]?.tokens;\n if (tokens?.access_token) {\n a2aMetadata.googleToken = tokens.access_token;\n }\n } catch {}\n }\n\n let responseText = \"\";\n let lastSentLength = 0;\n\n context.send({\n type: \"agent_call\",\n agent: agent.name,\n status: \"start\",\n });\n\n const emitNewText = (newText: string) => {\n if (newText.length > lastSentLength) {\n context.send!({\n type: \"agent_call_text\",\n agent: agent.name,\n text: newText.slice(lastSentLength),\n });\n lastSentLength = newText.length;\n }\n responseText = newText;\n };\n\n // Skip the SSE streaming attempt and go straight to async + poll.\n // Why: on Netlify (Lambda), the receiving server has no streaming\n // response support, so message/stream returns a single JSON-RPC error\n // body in a 200 response that our SSE parser silently consumes — the\n // `for await` loop yields nothing AND keeps the connection open until\n // the function timeout, eating the current serverless budget. By the\n // time we get to the sync fallback, Lambda is dead and the second fetch\n // errors out as \"fetch failed\". Async+poll has its own short fetches\n // with their own budgets, so it works reliably across hosts. The\n // trade-off is we lose progressive in-UI text streaming for cross-app\n // A2A calls, but the receiving agent's full response still surfaces via\n // the tool_result event below.\n try {\n // Apply a polling cap ONLY for integration-platform callers on\n // serverless hosts. Normal chat, local Node, self-hosted Node, and\n // Docker can wait for slow-but-valid answers; integration processors\n // still need to finish before their current function execution dies.\n const callTimeoutMs = getIntegrationCallTimeoutMs();\n responseText = await callAgent(agent.url, messageWithHint, {\n userEmail: callerEmail,\n orgDomain: callerOrgDomain,\n orgSecret: callerOrgSecret,\n ...(callTimeoutMs ? { timeoutMs: callTimeoutMs } : {}),\n });\n // Some agents reply with relative paths (e.g. slides emits\n // \"/deck/abc\"). Those resolve against the caller's host, not the\n // receiver's, so they're broken for the user. Expand any leading-slash\n // URL into a fully-qualified one rooted at the receiving agent's host.\n responseText = expandRelativeUrls(responseText, agent.url);\n // Mirror the response into the streaming UI so the user sees it.\n if (responseText) emitNewText(responseText);\n } catch (pollErr: any) {\n if (pollErr instanceof A2ATaskTimeoutError) {\n const queued = await enqueueIntegrationContinuationIfPossible(\n pollErr,\n agent,\n callerEmail,\n );\n if (queued) {\n responseText = `The ${agent.name} agent is still working. I will update this thread with the final result when it finishes.`;\n emitNewText(responseText);\n } else {\n const reason = pollErr?.message ?? \"unknown error\";\n responseText = `The ${agent.name} agent is taking longer than expected and didn't reply in time. (${reason})`;\n }\n } else {\n const reason = pollErr?.message ?? \"unknown error\";\n responseText = `The ${agent.name} agent is taking longer than expected and didn't reply in time. (${reason})`;\n }\n }\n\n context.send({\n type: \"agent_call\",\n agent: agent.name,\n status: \"done\",\n });\n\n return responseText || \"(empty response)\";\n }\n\n // No context — use the async + poll call so we don't get cut off at the\n // serverless gateway's ~30s timeout. callAgent defaults to async:true.\n const email = getRequestUserEmail();\n let domain: string | undefined;\n let orgSecret: string | undefined;\n const currentOrgId = getRequestOrgId();\n if (currentOrgId) {\n try {\n domain = (await getOrgDomain(currentOrgId)) ?? undefined;\n } catch {}\n try {\n orgSecret = (await getOrgA2ASecret(currentOrgId)) ?? undefined;\n } catch {}\n }\n const response = await callAgent(agent.url, messageWithHint, {\n userEmail: email,\n orgDomain: domain,\n orgSecret,\n });\n return expandRelativeUrls(response, agent.url) || \"(empty response)\";\n } catch (err: any) {\n const msg = err?.message ?? String(err);\n // Friendlier message for the common timeout case so the calling agent can\n // decide whether to give up or retry.\n if (/timeout|did not complete|Inactivity|504/i.test(msg)) {\n return `The ${agent.name} agent is taking longer than expected. Please try again, ask a simpler question, or open the ${agent.name} app directly.`;\n }\n return `Error calling ${agent.name}: ${msg}`;\n }\n}\n\nasync function enqueueIntegrationContinuationIfPossible(\n error: A2ATaskTimeoutError,\n agent: { name: string; url: string },\n ownerEmail: string | undefined,\n): Promise<boolean> {\n const integration = getIntegrationRequestContext();\n if (!integration || !ownerEmail) return false;\n\n try {\n const [{ insertA2AContinuation }, { dispatchA2AContinuation }] =\n await Promise.all([\n import(\"../integrations/a2a-continuations-store.js\"),\n import(\"../integrations/a2a-continuation-processor.js\"),\n ]);\n const continuation = await insertA2AContinuation({\n integrationTaskId: integration.taskId,\n platform: integration.incoming.platform,\n externalThreadId: integration.incoming.externalThreadId,\n incoming: integration.incoming,\n placeholderRef: integration.placeholderRef,\n ownerEmail,\n orgId: getRequestOrgId() ?? null,\n agentName: agent.name,\n agentUrl: agent.url,\n a2aTaskId: error.taskId,\n });\n await dispatchA2AContinuation(continuation.id).catch((err) => {\n console.error(\n `[call-agent] Failed to dispatch A2A continuation ${continuation.id}:`,\n err,\n );\n });\n return true;\n } catch (err) {\n console.error(\"[call-agent] Failed to enqueue A2A continuation:\", err);\n return false;\n }\n}\n\n// Expand bare leading-slash paths (e.g. \"/deck/abc\") into fully-qualified URLs\n// rooted at the receiving agent's host. The receiver doesn't always know it's\n// being called cross-app, so it may emit relative paths that resolve against\n// the caller's host (broken). Match a path that starts at a word boundary,\n// begins with `/`, and has at least one path segment after that. Skip if it\n// already looks like a fully-qualified URL.\nexport function expandRelativeUrls(text: string, agentUrl: string): string {\n if (!text || !agentUrl) return text;\n const base = agentUrl.replace(/\\/$/, \"\");\n // Path must start at boundary (start, whitespace, or punctuation that isn't\n // ':' — to avoid mangling `https://example.com/foo` or markdown link bodies).\n return text.replace(\n /(^|[\\s(\\[<\"'`])(\\/[a-z0-9_-][a-z0-9_/?&=%#.,:-]*)/gi,\n (_match, lead, path) => `${lead}${base}${path}`,\n );\n}\n"]}
1
+ {"version":3,"file":"call-agent.js","sourceRoot":"","sources":["../../src/scripts/call-agent.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ActionTool } from \"../agent/types.js\";\nimport type { ActionRunContext } from \"../agent/production-agent.js\";\nimport { findAgent, discoverAgents } from \"../server/agent-discovery.js\";\nimport {\n A2AClient,\n A2ATaskTimeoutError,\n callAgent,\n signA2AToken,\n} from \"../a2a/client.js\";\nimport {\n getRequestUserEmail,\n getRequestOrgId,\n isIntegrationCallerRequest,\n getIntegrationRequestContext,\n} from \"../server/request-context.js\";\nimport { getOrgDomain, getOrgA2ASecret } from \"../org/context.js\";\n\nconst DEFAULT_SERVERLESS_INTEGRATION_A2A_TIMEOUT_MS = 18_000;\nconst NETLIFY_INTEGRATION_A2A_TIMEOUT_MS = 50_000;\nconst INTEGRATION_A2A_TOKEN_TTL = \"30m\";\n\nfunction parseTimeoutMs(value: string | undefined): number | undefined {\n if (!value) return undefined;\n const parsed = Number(value);\n if (!Number.isFinite(parsed) || parsed <= 0) return undefined;\n return Math.floor(parsed);\n}\n\nfunction isServerlessHost(): boolean {\n // Detection mirrors db/migrations.ts:297-301. On Cloudflare Workers/Pages,\n // `process.env` is shimmed and CF_PAGES isn't reliably populated at runtime —\n // the canonical signal is the `__cf_env` global injected by workerd.\n return (\n !!process.env.NETLIFY ||\n !!process.env.AWS_LAMBDA_FUNCTION_NAME ||\n !!process.env.VERCEL ||\n \"__cf_env\" in globalThis\n );\n}\n\nfunction getIntegrationCallTimeoutMs(): number | undefined {\n if (!isServerlessHost() || !isIntegrationCallerRequest()) return undefined;\n\n const configured = parseTimeoutMs(\n process.env.AGENT_NATIVE_INTEGRATION_A2A_TIMEOUT_MS,\n );\n if (configured !== undefined) return configured;\n\n // Netlify's current synchronous function budget is 60s, but leave room for\n // cold start, polling overhead, and the caller's final platform response.\n if (process.env.NETLIFY) return NETLIFY_INTEGRATION_A2A_TIMEOUT_MS;\n\n return DEFAULT_SERVERLESS_INTEGRATION_A2A_TIMEOUT_MS;\n}\n\nexport const tool: ActionTool = {\n description:\n \"Call a DIFFERENT, separately-deployed agent app to ask a question or delegate a task. This is strictly for cross-app A2A communication — for example, asking the mail agent to send an email while you are the calendar agent. NEVER use this to call your own app or perform actions you can do with your own tools. Using call-agent on yourself will fail and waste time. \" +\n \"IMPORTANT — handling the response: \" +\n \"(a) If it contains a URL or ID, copy it VERBATIM into your reply. Do not 'correct' or pluralize the path (e.g. /deck/ → /decks/), normalize casing, or change the slug — any edit breaks the link. \" +\n '(b) If it does NOT contain a URL/ID and the user asked for one, say so explicitly (e.g. \"the agent created the deck but didn\\'t return a link — open the app directly to view it\"). NEVER invent a URL, slug, or path — guessing produces broken links that look real.',\n parameters: {\n type: \"object\",\n properties: {\n agent: {\n type: \"string\",\n description:\n \"Name or URL of a DIFFERENT deployed agent app (e.g. 'mail', 'calendar', 'analytics'). Must not be the current app's own name.\",\n },\n message: {\n type: \"string\",\n description: \"The message/question to send to the other agent\",\n },\n },\n required: [\"agent\", \"message\"],\n },\n};\n\nexport async function run(\n args: Record<string, string>,\n context?: ActionRunContext,\n selfAppId?: string,\n): Promise<string> {\n const { agent: agentIdOrName, message } = args;\n\n if (!agentIdOrName) return \"Error: --agent is required\";\n if (!message) return \"Error: --message is required\";\n\n // Prevent self-calls — the agent must use its own registered tools instead\n if (selfAppId && agentIdOrName.toLowerCase() === selfAppId.toLowerCase()) {\n return `Error: You cannot use call-agent to call yourself (${selfAppId}). Use your own registered actions/tools instead. call-agent is only for communicating with OTHER separately-deployed apps.`;\n }\n\n const agent = await findAgent(agentIdOrName, selfAppId);\n if (!agent) {\n const available = (await discoverAgents(selfAppId))\n .map((a) => a.name)\n .join(\", \");\n return `Error: Agent \"${agentIdOrName}\" not found. Available agents: ${available || \"(none)\"}`;\n }\n\n // Append a small cross-app hint to the outgoing message so the receiving\n // agent (which may be on an older deploy without the receiver-side hint\n // in handlers.ts) still emits fully-qualified URLs. This is belt-and-\n // suspenders with the receiver hint — but it works against any current\n // deployment, no redeploy required.\n const messageWithHint =\n `${message}\\n\\n` +\n `[Note: this request comes from another app via A2A. The caller cannot see your local UI, deck list, or navigation — only the literal text you put in your reply. ` +\n `If you create or reference a deck/document/dashboard, include its FULLY-QUALIFIED URL (e.g. ${agent.url}/deck/<id>) in your reply, not a relative path. ` +\n `Use only IDs returned by your own actions — never invent slugs or hosts.]`;\n\n try {\n // If we have a send context, use streaming so the UI shows progressive text\n if (context?.send) {\n const callerEmail = getRequestUserEmail();\n\n // Build metadata with identity\n const a2aMetadata: Record<string, unknown> = {};\n if (callerEmail) a2aMetadata.userEmail = callerEmail;\n\n // Include org domain for cross-app org resolution\n let callerOrgDomain: string | undefined;\n let callerOrgSecret: string | undefined;\n const orgId = getRequestOrgId();\n if (orgId) {\n try {\n const domain = await getOrgDomain(orgId);\n if (domain) {\n callerOrgDomain = domain;\n a2aMetadata.orgDomain = domain;\n }\n } catch {}\n try {\n const secret = await getOrgA2ASecret(orgId);\n if (secret) callerOrgSecret = secret;\n } catch {}\n }\n\n // Sign JWT with identity + org domain for the streaming client\n let apiKey: string | undefined;\n if (callerEmail && (callerOrgSecret || process.env.A2A_SECRET)) {\n try {\n apiKey = await signA2AToken(\n callerEmail,\n callerOrgDomain,\n callerOrgSecret,\n { expiresIn: INTEGRATION_A2A_TOKEN_TTL },\n );\n } catch {}\n }\n\n const client = new A2AClient(agent.url, apiKey);\n\n if (process.env.NODE_ENV === \"production\" && callerEmail) {\n try {\n const { listOAuthAccountsByOwner } =\n await import(\"../oauth-tokens/store.js\");\n const accounts = await listOAuthAccountsByOwner(\n \"google\",\n callerEmail,\n );\n const tokens = accounts[0]?.tokens;\n if (tokens?.access_token) {\n a2aMetadata.googleToken = tokens.access_token;\n }\n } catch {}\n }\n\n let responseText = \"\";\n let lastSentLength = 0;\n\n context.send({\n type: \"agent_call\",\n agent: agent.name,\n status: \"start\",\n });\n\n const emitNewText = (newText: string) => {\n if (newText.length > lastSentLength) {\n context.send!({\n type: \"agent_call_text\",\n agent: agent.name,\n text: newText.slice(lastSentLength),\n });\n lastSentLength = newText.length;\n }\n responseText = newText;\n };\n\n // Skip the SSE streaming attempt and go straight to async + poll.\n // Why: on Netlify (Lambda), the receiving server has no streaming\n // response support, so message/stream returns a single JSON-RPC error\n // body in a 200 response that our SSE parser silently consumes — the\n // `for await` loop yields nothing AND keeps the connection open until\n // the function timeout, eating the current serverless budget. By the\n // time we get to the sync fallback, Lambda is dead and the second fetch\n // errors out as \"fetch failed\". Async+poll has its own short fetches\n // with their own budgets, so it works reliably across hosts. The\n // trade-off is we lose progressive in-UI text streaming for cross-app\n // A2A calls, but the receiving agent's full response still surfaces via\n // the tool_result event below.\n try {\n // Apply a polling cap ONLY for integration-platform callers on\n // serverless hosts. Normal chat, local Node, self-hosted Node, and\n // Docker can wait for slow-but-valid answers; integration processors\n // still need to finish before their current function execution dies.\n const callTimeoutMs = getIntegrationCallTimeoutMs();\n responseText = await callAgent(agent.url, messageWithHint, {\n apiKey,\n userEmail: callerEmail,\n orgDomain: callerOrgDomain,\n orgSecret: callerOrgSecret,\n ...(callTimeoutMs ? { timeoutMs: callTimeoutMs } : {}),\n });\n // Some agents reply with relative paths (e.g. slides emits\n // \"/deck/abc\"). Those resolve against the caller's host, not the\n // receiver's, so they're broken for the user. Expand any leading-slash\n // URL into a fully-qualified one rooted at the receiving agent's host.\n responseText = expandRelativeUrls(responseText, agent.url);\n // Mirror the response into the streaming UI so the user sees it.\n if (responseText) emitNewText(responseText);\n } catch (pollErr: any) {\n if (pollErr instanceof A2ATaskTimeoutError) {\n const queued = await enqueueIntegrationContinuationIfPossible(\n pollErr,\n agent,\n callerEmail,\n apiKey,\n );\n if (queued) {\n responseText = `The ${agent.name} agent is still working. I will update this thread with the final result when it finishes.`;\n emitNewText(responseText);\n } else {\n const reason = pollErr?.message ?? \"unknown error\";\n responseText = `The ${agent.name} agent is taking longer than expected and didn't reply in time. (${reason})`;\n }\n } else {\n const reason = pollErr?.message ?? \"unknown error\";\n responseText = `The ${agent.name} agent is taking longer than expected and didn't reply in time. (${reason})`;\n }\n }\n\n context.send({\n type: \"agent_call\",\n agent: agent.name,\n status: \"done\",\n });\n\n return responseText || \"(empty response)\";\n }\n\n // No context — use the async + poll call so we don't get cut off at the\n // serverless gateway's ~30s timeout. callAgent defaults to async:true.\n const email = getRequestUserEmail();\n let domain: string | undefined;\n let orgSecret: string | undefined;\n const currentOrgId = getRequestOrgId();\n if (currentOrgId) {\n try {\n domain = (await getOrgDomain(currentOrgId)) ?? undefined;\n } catch {}\n try {\n orgSecret = (await getOrgA2ASecret(currentOrgId)) ?? undefined;\n } catch {}\n }\n const response = await callAgent(agent.url, messageWithHint, {\n userEmail: email,\n orgDomain: domain,\n orgSecret,\n });\n return expandRelativeUrls(response, agent.url) || \"(empty response)\";\n } catch (err: any) {\n const msg = err?.message ?? String(err);\n // Friendlier message for the common timeout case so the calling agent can\n // decide whether to give up or retry.\n if (/timeout|did not complete|Inactivity|504/i.test(msg)) {\n return `The ${agent.name} agent is taking longer than expected. Please try again, ask a simpler question, or open the ${agent.name} app directly.`;\n }\n return `Error calling ${agent.name}: ${msg}`;\n }\n}\n\nasync function enqueueIntegrationContinuationIfPossible(\n error: A2ATaskTimeoutError,\n agent: { name: string; url: string },\n ownerEmail: string | undefined,\n a2aAuthToken: string | undefined,\n): Promise<boolean> {\n const integration = getIntegrationRequestContext();\n if (!integration || !ownerEmail) return false;\n\n try {\n const [{ insertA2AContinuation }, { dispatchA2AContinuation }] =\n await Promise.all([\n import(\"../integrations/a2a-continuations-store.js\"),\n import(\"../integrations/a2a-continuation-processor.js\"),\n ]);\n const continuation = await insertA2AContinuation({\n integrationTaskId: integration.taskId,\n platform: integration.incoming.platform,\n externalThreadId: integration.incoming.externalThreadId,\n incoming: integration.incoming,\n placeholderRef: integration.placeholderRef,\n ownerEmail,\n orgId: getRequestOrgId() ?? null,\n agentName: agent.name,\n agentUrl: agent.url,\n a2aTaskId: error.taskId,\n a2aAuthToken: a2aAuthToken ?? \"\",\n });\n await dispatchA2AContinuation(continuation.id).catch((err) => {\n console.error(\n `[call-agent] Failed to dispatch A2A continuation ${continuation.id}:`,\n err,\n );\n });\n return true;\n } catch (err) {\n console.error(\"[call-agent] Failed to enqueue A2A continuation:\", err);\n return false;\n }\n}\n\n// Expand bare leading-slash paths (e.g. \"/deck/abc\") into fully-qualified URLs\n// rooted at the receiving agent's host. The receiver doesn't always know it's\n// being called cross-app, so it may emit relative paths that resolve against\n// the caller's host (broken). Match a path that starts at a word boundary,\n// begins with `/`, and has at least one path segment after that. Skip if it\n// already looks like a fully-qualified URL.\nexport function expandRelativeUrls(text: string, agentUrl: string): string {\n if (!text || !agentUrl) return text;\n const base = agentUrl.replace(/\\/$/, \"\");\n // Path must start at boundary (start, whitespace, or punctuation that isn't\n // ':' — to avoid mangling `https://example.com/foo` or markdown link bodies).\n return text.replace(\n /(^|[\\s(\\[<\"'`])(\\/[a-z0-9_-][a-z0-9_/?&=%#.,:-]*)/gi,\n (_match, lead, path) => `${lead}${base}${path}`,\n );\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core",
3
- "version": "0.7.46",
3
+ "version": "0.7.47",
4
4
  "type": "module",
5
5
  "description": "Framework for agent-native application development — where AI agents and UI share state via files",
6
6
  "license": "MIT",