diff --git a/agent.py b/agent.py index bd678cb..2da9ed2 100644 --- a/agent.py +++ b/agent.py @@ -409,7 +409,11 @@ def _read_uploaded_workspace_file(ctx: RunContext[PlatformUserAuth], path: str) async def _write_workspace_output(ctx: RunContext[PlatformUserAuth], path: str, payload: dict[str, Any], warnings: list[str]) -> None: data = json.dumps(payload, indent=2, sort_keys=True).encode("utf-8") - workspace = ctx.workspace + try: + workspace = ctx.workspace + except PermissionError as exc: + warnings.append(f"workspace write skipped: {str(exc)[:160]}") + return writer = getattr(workspace, "write_bytes", None) if callable(writer): writer(path, data) diff --git a/tests/test_full_stack_contract.py b/tests/test_full_stack_contract.py index 79ec763..cc28363 100644 --- a/tests/test_full_stack_contract.py +++ b/tests/test_full_stack_contract.py @@ -115,6 +115,25 @@ def test_invalid_schema_returns_structured_validation_error(): assert "type='object'" in " ".join(result.warnings) +def test_optional_workspace_write_is_skipped_without_a_workspace(): + class NoWorkspaceContext: + @property + def workspace(self): + raise PermissionError("no workspace bound") + + warnings = [] + asyncio.run( + agent_module._write_workspace_output( + NoWorkspaceContext(), + "outputs/data-workflows/test.workflow.json", + {"ok": True}, + warnings, + ) + ) + + assert warnings == ["workspace write skipped: no workspace bound"] + + def test_workflow_spec_has_no_secret_fields(): schema = {"type": "object", "properties": {"Name": {"type": "string"}}, "required": ["Name"]} profile = agent_module._profile_source_data("x.csv", "text/csv", b"Name\nAda\n")