@agent-native/core 0.7.27 → 0.7.28

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.
@@ -1 +1 @@
1
- {"version":3,"file":"a2a-continuation-processor.d.ts","sourceRoot":"","sources":["../../src/integrations/a2a-continuation-processor.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAgBlD,wBAAsB,uBAAuB,CAC3C,cAAc,EAAE,MAAM,EACtB,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,IAAI,CAAC,CA0Cf;AAED,wBAAsB,0BAA0B,CAC9C,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE;IAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;CAAE,GAClD,OAAO,CAAC,IAAI,CAAC,CAIf;AAED,wBAAsB,0BAA0B,CAAC,OAAO,EAAE;IACxD,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,IAAI,CAAC,CAUhB"}
1
+ {"version":3,"file":"a2a-continuation-processor.d.ts","sourceRoot":"","sources":["../../src/integrations/a2a-continuation-processor.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAiBlD,wBAAsB,uBAAuB,CAC3C,cAAc,EAAE,MAAM,EACtB,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,IAAI,CAAC,CAqDf;AAmBD,wBAAsB,0BAA0B,CAC9C,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE;IAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;CAAE,GAClD,OAAO,CAAC,IAAI,CAAC,CAIf;AAED,wBAAsB,0BAA0B,CAAC,OAAO,EAAE;IACxD,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,IAAI,CAAC,CAUhB"}
@@ -8,6 +8,7 @@ const TERMINAL_STATES = new Set(["completed", "failed", "canceled"]);
8
8
  const MAX_ATTEMPTS = 6;
9
9
  const POLL_INTERVAL_MS = 2_000;
10
10
  const PROCESSOR_WAIT_MS = 20_000;
11
+ const DISPATCH_SETTLE_WAIT_MS = 250;
11
12
  export async function dispatchA2AContinuation(continuationId, webhookBaseUrl) {
12
13
  const baseUrl = webhookBaseUrl ||
13
14
  process.env.WEBHOOK_BASE_URL ||
@@ -31,19 +32,34 @@ export async function dispatchA2AContinuation(continuationId, webhookBaseUrl) {
31
32
  console.error(`[integrations] signInternalToken failed unexpectedly for ${continuationId}:`, err);
32
33
  }
33
34
  }
34
- const controller = new AbortController();
35
- const timer = setTimeout(() => controller.abort(), 5_000);
35
+ const dispatchPromise = fetch(url, {
36
+ method: "POST",
37
+ headers,
38
+ body: JSON.stringify({ continuationId }),
39
+ })
40
+ .then(async (response) => {
41
+ if (!response.ok) {
42
+ await logFailedDispatchResponse(continuationId, response);
43
+ }
44
+ })
45
+ .catch((err) => {
46
+ console.error(`[integrations] Failed to dispatch A2A continuation ${continuationId}:`, err);
47
+ });
48
+ await Promise.race([
49
+ dispatchPromise,
50
+ new Promise((resolve) => setTimeout(resolve, DISPATCH_SETTLE_WAIT_MS)),
51
+ ]);
52
+ }
53
+ async function logFailedDispatchResponse(continuationId, response) {
54
+ let body = "";
36
55
  try {
37
- await fetch(url, {
38
- method: "POST",
39
- headers,
40
- body: JSON.stringify({ continuationId }),
41
- signal: controller.signal,
42
- });
43
- }
44
- finally {
45
- clearTimeout(timer);
56
+ body = await response.text();
46
57
  }
58
+ catch { }
59
+ const trimmedBody = body.trim();
60
+ console.error(`[integrations] A2A continuation ${continuationId} processor dispatch returned HTTP ` +
61
+ `${response.status}${response.statusText ? ` ${response.statusText}` : ""}` +
62
+ `${trimmedBody ? `: ${trimmedBody.slice(0, 500)}` : ""}`);
47
63
  }
48
64
  export async function processA2AContinuationById(continuationId, options) {
49
65
  const continuation = await claimA2AContinuation(continuationId);
@@ -76,7 +92,7 @@ async function processClaimedContinuation(continuation, options) {
76
92
  }
77
93
  catch (err) {
78
94
  if (continuation.attempts >= MAX_ATTEMPTS) {
79
- await failA2AContinuation(continuation.id, err instanceof Error ? err.message : String(err));
95
+ await notifyAndFailA2AContinuation(continuation, adapter, err instanceof Error ? err.message : String(err));
80
96
  return;
81
97
  }
82
98
  await rescheduleA2AContinuation(continuation.id, 30_000);
@@ -85,7 +101,7 @@ async function processClaimedContinuation(continuation, options) {
85
101
  }
86
102
  if (!task || !TERMINAL_STATES.has(task.status.state)) {
87
103
  if (continuation.attempts >= MAX_ATTEMPTS) {
88
- await failA2AContinuation(continuation.id, `Remote A2A task ${continuation.a2aTaskId} did not complete after ${MAX_ATTEMPTS} attempts`);
104
+ await notifyAndFailA2AContinuation(continuation, adapter, `Remote A2A task ${continuation.a2aTaskId} did not complete after ${MAX_ATTEMPTS} attempts`);
89
105
  return;
90
106
  }
91
107
  await rescheduleA2AContinuation(continuation.id, 30_000);
@@ -93,12 +109,14 @@ async function processClaimedContinuation(continuation, options) {
93
109
  return;
94
110
  }
95
111
  if (task.status.state !== "completed") {
96
- await failA2AContinuation(continuation.id, `Remote A2A task ${continuation.a2aTaskId} ended with state ${task.status.state}`);
112
+ const reason = extractTaskText(task) ||
113
+ `Remote A2A task ${continuation.a2aTaskId} ended with state ${task.status.state}`;
114
+ await notifyAndFailA2AContinuation(continuation, adapter, reason);
97
115
  return;
98
116
  }
99
117
  const text = expandRelativeUrls(extractTaskText(task), continuation.agentUrl);
100
118
  if (!text.trim()) {
101
- await failA2AContinuation(continuation.id, `Remote A2A task ${continuation.a2aTaskId} completed without text`);
119
+ await notifyAndFailA2AContinuation(continuation, adapter, `Remote A2A task ${continuation.a2aTaskId} completed without text`);
102
120
  return;
103
121
  }
104
122
  try {
@@ -114,6 +132,33 @@ async function processClaimedContinuation(continuation, options) {
114
132
  await redispatchContinuation(continuation.id);
115
133
  }
116
134
  }
135
+ async function notifyAndFailA2AContinuation(continuation, adapter, reason) {
136
+ const message = formatContinuationFailureMessage(continuation, reason);
137
+ try {
138
+ await adapter.sendResponse(adapter.formatAgentResponse(message), continuation.incoming, { placeholderRef: continuation.placeholderRef ?? undefined });
139
+ }
140
+ catch (err) {
141
+ console.error(`[integrations] Failed to notify ${continuation.platform} about failed A2A continuation ${continuation.id}:`, err);
142
+ }
143
+ await failA2AContinuation(continuation.id, reason);
144
+ }
145
+ function formatContinuationFailureMessage(continuation, reason) {
146
+ if (isLlmCredentialError(reason)) {
147
+ return `The ${continuation.agentName} agent could not finish this request because that app needs an LLM connection. Connect Builder.io or another LLM provider for the ${continuation.agentName} app, then try again.`;
148
+ }
149
+ return `The ${continuation.agentName} agent could not finish this request: ${sanitizeFailureReason(reason)}`;
150
+ }
151
+ function isLlmCredentialError(reason) {
152
+ return (/(?:ANTHROPIC|OPENAI|GOOGLE|GEMINI|MISTRAL|GROQ|TOGETHER|XAI|PERPLEXITY|FIREWORKS|DEEPSEEK)_[A-Z0-9_]*API_KEY/i.test(reason) ||
153
+ /(?:api key|llm|model provider).*(?:missing|not set|not configured|required)/i.test(reason) ||
154
+ /(?:missing|not set|not configured|required).*(?:api key|llm|model provider)/i.test(reason));
155
+ }
156
+ function sanitizeFailureReason(reason) {
157
+ const oneLine = reason.replace(/\s+/g, " ").trim();
158
+ const withoutEnvNames = oneLine.replace(/\b[A-Z][A-Z0-9_]*(?:API_KEY|PRIVATE_KEY|SECRET|TOKEN)\b/g, "a required credential");
159
+ return (withoutEnvNames.slice(0, 500) ||
160
+ "the downstream agent returned an empty error");
161
+ }
117
162
  async function redispatchContinuation(continuationId) {
118
163
  await dispatchA2AContinuation(continuationId).catch((err) => {
119
164
  console.error(`[integrations] Failed to redispatch A2A continuation ${continuationId}:`, err);
@@ -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 claimA2AContinuation,\n claimDueA2AContinuations,\n completeA2AContinuation,\n failA2AContinuation,\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 POLL_INTERVAL_MS = 2_000;\nconst PROCESSOR_WAIT_MS = 20_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 controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), 5_000);\n try {\n await fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ continuationId }),\n signal: controller.signal,\n });\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport async function processA2AContinuationById(\n continuationId: string,\n options: { adapters: Map<string, PlatformAdapter> },\n): Promise<void> {\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: 10_000 },\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 (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, 30_000);\n await redispatchContinuation(continuation.id);\n return;\n }\n\n if (!task || !TERMINAL_STATES.has(task.status.state)) {\n if (continuation.attempts >= MAX_ATTEMPTS) {\n await failA2AContinuation(\n continuation.id,\n `Remote A2A task ${continuation.a2aTaskId} did not complete after ${MAX_ATTEMPTS} attempts`,\n );\n return;\n }\n await rescheduleA2AContinuation(continuation.id, 30_000);\n await redispatchContinuation(continuation.id);\n return;\n }\n\n if (task.status.state !== \"completed\") {\n await failA2AContinuation(\n continuation.id,\n `Remote A2A task ${continuation.a2aTaskId} ended with state ${task.status.state}`,\n );\n return;\n }\n\n const text = expandRelativeUrls(extractTaskText(task), continuation.agentUrl);\n if (!text.trim()) {\n await failA2AContinuation(\n continuation.id,\n `Remote A2A task ${continuation.a2aTaskId} completed without text`,\n );\n return;\n }\n\n try {\n await adapter.sendResponse(\n adapter.formatAgentResponse(text),\n continuation.incoming,\n { placeholderRef: continuation.placeholderRef ?? undefined },\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, 30_000);\n await redispatchContinuation(continuation.id);\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 claimA2AContinuation,\n claimDueA2AContinuations,\n completeA2AContinuation,\n failA2AContinuation,\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 POLL_INTERVAL_MS = 2_000;\nconst PROCESSOR_WAIT_MS = 20_000;\nconst DISPATCH_SETTLE_WAIT_MS = 250;\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 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: 10_000 },\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 (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, 30_000);\n await redispatchContinuation(continuation.id);\n return;\n }\n\n if (!task || !TERMINAL_STATES.has(task.status.state)) {\n if (continuation.attempts >= MAX_ATTEMPTS) {\n await notifyAndFailA2AContinuation(\n continuation,\n adapter,\n `Remote A2A task ${continuation.a2aTaskId} did not complete after ${MAX_ATTEMPTS} attempts`,\n );\n return;\n }\n await rescheduleA2AContinuation(continuation.id, 30_000);\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 adapter.sendResponse(\n adapter.formatAgentResponse(text),\n continuation.incoming,\n { placeholderRef: continuation.placeholderRef ?? undefined },\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, 30_000);\n await redispatchContinuation(continuation.id);\n }\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 adapter.sendResponse(\n adapter.formatAgentResponse(message),\n continuation.incoming,\n { placeholderRef: continuation.placeholderRef ?? undefined },\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 `The ${continuation.agentName} agent could not finish this request because that app needs an LLM connection. Connect Builder.io or another LLM provider for the ${continuation.agentName} app, then try again.`;\n }\n\n return `The ${continuation.agentName} agent could not finish this request: ${sanitizeFailureReason(\n reason,\n )}`;\n}\n\nfunction isLlmCredentialError(reason: string): boolean {\n return (\n /(?:ANTHROPIC|OPENAI|GOOGLE|GEMINI|MISTRAL|GROQ|TOGETHER|XAI|PERPLEXITY|FIREWORKS|DEEPSEEK)_[A-Z0-9_]*API_KEY/i.test(\n reason,\n ) ||\n /(?:api key|llm|model provider).*(?:missing|not set|not configured|required)/i.test(\n reason,\n ) ||\n /(?:missing|not set|not configured|required).*(?:api key|llm|model provider)/i.test(\n reason,\n )\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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core",
3
- "version": "0.7.27",
3
+ "version": "0.7.28",
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",