diff --git a/.gitea/workflows/publish-workspace-server-image.yml b/.gitea/workflows/publish-workspace-server-image.yml index 96a03b7e..08a65d14 100644 --- a/.gitea/workflows/publish-workspace-server-image.yml +++ b/.gitea/workflows/publish-workspace-server-image.yml @@ -23,7 +23,7 @@ name: publish-workspace-server-image on: push: - branches: [staging, main] + branches: [main] paths: - 'workspace-server/**' - 'canvas/**' @@ -32,11 +32,9 @@ on: - '.gitea/workflows/publish-workspace-server-image.yml' workflow_dispatch: -# Serialize per-branch so two rapid staging pushes don't race the same -# :staging-latest tag retag. Allow staging and main to run in parallel -# (different GITHUB_REF → different concurrency group) since they -# produce different :staging- tags and last-write-wins on -# :staging-latest is acceptable across branches. +# Serialize per-branch so two rapid main pushes don't race the same +# :staging-latest tag retag. Allow parallel runs as they produce +# different :staging- tags and last-write-wins on :staging-latest. # # cancel-in-progress: false → in-flight builds finish; the next push's # build queues. This avoids a partially-pushed image. diff --git a/.github/workflows/publish-workspace-server-image.yml b/.github/workflows/publish-workspace-server-image.yml index be88f2cc..2a1b8b17 100644 --- a/.github/workflows/publish-workspace-server-image.yml +++ b/.github/workflows/publish-workspace-server-image.yml @@ -32,7 +32,7 @@ name: publish-workspace-server-image on: push: - branches: [staging, main] + branches: [main] paths: - 'workspace-server/**' - 'canvas/**' diff --git a/workspace/builtin_tools/a2a_tools.py b/workspace/builtin_tools/a2a_tools.py index df4f9d78..d9c48598 100644 --- a/workspace/builtin_tools/a2a_tools.py +++ b/workspace/builtin_tools/a2a_tools.py @@ -66,10 +66,23 @@ async def delegate_task(workspace_id: str, task: str) -> str: ) data = a2a_resp.json() if "result" in data: - parts = data["result"].get("parts", []) - return parts[0].get("text", "(no text)") if parts else str(data["result"]) + result = 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: - 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) except Exception as e: return f"Error sending A2A message: {e}"