Skip to content

Commit 15d2a07

Browse files
committed
deploy: 101713c
1 parent 4a3e0a1 commit 15d2a07

7 files changed

Lines changed: 2790 additions & 6 deletions

File tree

server/a2a_server.html

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,16 @@ <h2 class="section-title" id="header-classes">Classes</h2>
204204
try:
205205
result = await self._tool_callers[skill_name](params)
206206
await self._send_result(event_queue, context, skill_name, result)
207+
except ADCPError as exc:
208+
# Application-layer AdCP error (IdempotencyConflictError etc.).
209+
# Emit a failed task with the adcp_error in a DataPart per
210+
# transport-errors.mdx §A2A Binding, plus a human-readable text
211+
# part. The JSON-RPC channel is reserved for transport-level
212+
# errors (auth rejected, rate-limited pre-dispatch).
213+
logger.info(
214+
&#34;AdCP application error for skill %s: %s&#34;, skill_name, exc
215+
)
216+
await self._send_adcp_error(event_queue, context, exc)
207217
except Exception:
208218
logger.exception(&#34;Error executing skill %s&#34;, skill_name)
209219
await self._send_error(
@@ -310,6 +320,44 @@ <h2 class="section-title" id="header-classes">Classes</h2>
310320
state=TaskState.failed,
311321
message=error_msg,
312322
)
323+
await event_queue.enqueue_event(task)
324+
325+
async def _send_adcp_error(
326+
self,
327+
event_queue: EventQueue,
328+
context: RequestContext,
329+
exc: ADCPError,
330+
) -&gt; None:
331+
&#34;&#34;&#34;Publish a failed task carrying an AdCP ``adcp_error`` payload.
332+
333+
Follows transport-errors.mdx §A2A Binding: failed task with artifact
334+
containing a ``DataPart`` keyed under ``adcp_error`` plus a terse
335+
``TextPart`` for human/LLM consumption.
336+
&#34;&#34;&#34;
337+
# Derive the spec error code. ADCPTaskError carries a list of codes
338+
# (e.g. IdempotencyConflictError → IDEMPOTENCY_CONFLICT); fall back
339+
# to a generic INTERNAL_ERROR when the exception doesn&#39;t supply one.
340+
code = &#34;INTERNAL_ERROR&#34;
341+
if isinstance(exc, ADCPTaskError) and exc.error_codes:
342+
code = str(exc.error_codes[0])
343+
344+
adcp_error: dict[str, Any] = {
345+
&#34;code&#34;: code,
346+
&#34;message&#34;: exc.message,
347+
}
348+
recovery = STANDARD_ERROR_CODES.get(code, {}).get(&#34;recovery&#34;)
349+
if recovery:
350+
adcp_error[&#34;recovery&#34;] = recovery
351+
suggestion = getattr(exc, &#34;suggestion&#34;, None)
352+
if suggestion:
353+
adcp_error[&#34;suggestion&#34;] = suggestion
354+
355+
task = _make_task(
356+
context,
357+
state=TaskState.failed,
358+
data={&#34;adcp_error&#34;: adcp_error},
359+
message=exc.message,
360+
)
313361
await event_queue.enqueue_event(task)</code></pre>
314362
</details>
315363
<div class="desc"><p>Bridges ADCPHandler methods to the a2a-sdk AgentExecutor interface.</p>
@@ -391,6 +439,16 @@ <h3>Methods</h3>
391439
try:
392440
result = await self._tool_callers[skill_name](params)
393441
await self._send_result(event_queue, context, skill_name, result)
442+
except ADCPError as exc:
443+
# Application-layer AdCP error (IdempotencyConflictError etc.).
444+
# Emit a failed task with the adcp_error in a DataPart per
445+
# transport-errors.mdx §A2A Binding, plus a human-readable text
446+
# part. The JSON-RPC channel is reserved for transport-level
447+
# errors (auth rejected, rate-limited pre-dispatch).
448+
logger.info(
449+
&#34;AdCP application error for skill %s: %s&#34;, skill_name, exc
450+
)
451+
await self._send_adcp_error(event_queue, context, exc)
394452
except Exception:
395453
logger.exception(&#34;Error executing skill %s&#34;, skill_name)
396454
await self._send_error(

0 commit comments

Comments
 (0)