fix(a2a): handle string-form errors in delegate_task
The A2A proxy can return three error shapes:
{"error": "plain string"}
{"error": {"message": "...", "code": ...}}
{"error": {"message": {"nested": "object"}}} ← value at .message is a string
builtin_tools/a2a_tools.py:72 called data["error"].get("message")
without guarding against error being a string, which raised:
AttributeError: 'str' object has no attribute 'get'
This broke every delegation attempt through the legacy a2a_tools path
(the LangChain-wrapped version used by adapter templates). The
SSOT parser a2a_response.py already handled string errors; the
legacy inline sniffer in a2a_tools.py did not.
Fix: branch on isinstance(err, dict/str/other) before calling .get().
Also update both publish-workflow files to remove the dead
`staging` branch trigger — trunk-based migration (PR #109,
2026-05-08) removed the staging branch.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
cd73b38c7b
commit
67b2e48824
@ -23,7 +23,7 @@ name: publish-workspace-server-image
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [staging, main]
|
branches: [main]
|
||||||
paths:
|
paths:
|
||||||
- 'workspace-server/**'
|
- 'workspace-server/**'
|
||||||
- 'canvas/**'
|
- 'canvas/**'
|
||||||
@ -32,11 +32,9 @@ on:
|
|||||||
- '.gitea/workflows/publish-workspace-server-image.yml'
|
- '.gitea/workflows/publish-workspace-server-image.yml'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
# Serialize per-branch so two rapid staging pushes don't race the same
|
# Serialize per-branch so two rapid main pushes don't race the same
|
||||||
# :staging-latest tag retag. Allow staging and main to run in parallel
|
# :staging-latest tag retag. Allow parallel runs as they produce
|
||||||
# (different GITHUB_REF → different concurrency group) since they
|
# different :staging-<sha> tags and last-write-wins on :staging-latest.
|
||||||
# produce different :staging-<sha> tags and last-write-wins on
|
|
||||||
# :staging-latest is acceptable across branches.
|
|
||||||
#
|
#
|
||||||
# cancel-in-progress: false → in-flight builds finish; the next push's
|
# cancel-in-progress: false → in-flight builds finish; the next push's
|
||||||
# build queues. This avoids a partially-pushed image.
|
# build queues. This avoids a partially-pushed image.
|
||||||
|
|||||||
@ -32,7 +32,7 @@ name: publish-workspace-server-image
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [staging, main]
|
branches: [main]
|
||||||
paths:
|
paths:
|
||||||
- 'workspace-server/**'
|
- 'workspace-server/**'
|
||||||
- 'canvas/**'
|
- 'canvas/**'
|
||||||
|
|||||||
@ -66,10 +66,23 @@ async def delegate_task(workspace_id: str, task: str) -> str:
|
|||||||
)
|
)
|
||||||
data = a2a_resp.json()
|
data = a2a_resp.json()
|
||||||
if "result" in data:
|
if "result" in data:
|
||||||
parts = data["result"].get("parts", [])
|
result = data["result"]
|
||||||
return parts[0].get("text", "(no text)") if parts else str(data["result"])
|
parts = result.get("parts", []) if isinstance(result, dict) else []
|
||||||
|
if parts and isinstance(parts[0], dict):
|
||||||
|
return parts[0].get("text", "(no text)")
|
||||||
|
return str(result) if isinstance(result, str) else "(no text)"
|
||||||
elif "error" in data:
|
elif "error" in data:
|
||||||
return f"Error: {data['error'].get('message', str(data['error']))}"
|
err = data["error"]
|
||||||
|
# Handle both string-form errors ("error": "some string")
|
||||||
|
# and object-form errors ("error": {"message": "...", "code": ...}).
|
||||||
|
msg = ""
|
||||||
|
if isinstance(err, dict):
|
||||||
|
msg = err.get("message", "")
|
||||||
|
elif isinstance(err, str):
|
||||||
|
msg = err
|
||||||
|
else:
|
||||||
|
msg = str(err)
|
||||||
|
return f"Error: {msg}"
|
||||||
return str(data)
|
return str(data)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return f"Error sending A2A message: {e}"
|
return f"Error sending A2A message: {e}"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user