Skip to content

Commit 47744b3

Browse files
VladUZHclaude
andcommitted
style: clear 94 pre-existing ruff violations so CI can pass
python-sdk CI has never passed. Every run in its visible history back to 2026-03-25 is a failure, always at the same step: `ruff check src/`. Because it was never green, nothing in this repo has had automated enforcement — which is how a red test suite and this lint debt both accumulated unnoticed. These violations predate the previous commit: 94 errors at 31ea42e and 94 at 1476fcd, byte-identical. The fail-closed hardening did not introduce any of them (_base.py passes ruff cleanly on its own). All mechanical, against the declared target-version = "py310": UP045 (40) Optional[X] -> X | None UP006 (18) List/Dict/Tuple -> list/dict/tuple F401 (16) unused imports removed UP035 (12) deprecated typing imports I001 (5) import blocks sorted E501 (2) two long signatures in composio.py wrapped by hand UP007 (1) Union[X, Y] -> X | Y Public API verified unchanged by snapshotting dir() of sidclaw, sidclaw.middleware and all 11 middleware modules before and after. `sidclaw` and `sidclaw.middleware` are byte-identical. The only removals are incidental namespace pollution from the unused imports — typing constructs, stdlib modules, and ApprovalExpiredError / ApprovalTimeoutError, which remain exported from the canonical top level (`from sidclaw import ApprovalTimeoutError` still works). The undocumented `from sidclaw.middleware.composio import ApprovalTimeoutError` no longer resolves; it was never in an __all__ and nothing imports it. No behaviour change. 186 tests pass. `ruff check src/` now exits clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 1476fcd commit 47744b3

6 files changed

Lines changed: 95 additions & 89 deletions

File tree

src/sidclaw/middleware/__init__.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
11
"""Framework middleware for SidClaw governance."""
22

3-
from .generic import GovernanceConfig, async_with_governance, with_governance
3+
from .claude_agent_sdk import (
4+
ClaudeAgentGovernanceConfig,
5+
govern_claude_agent_tool,
6+
govern_claude_agent_tool_async,
7+
govern_claude_agent_tools,
8+
govern_claude_agent_tools_async,
9+
)
410
from .composio import (
511
ComposioGovernanceConfig,
6-
govern_composio_execution,
7-
govern_composio_execution_async,
812
create_composio_governance_modifiers,
913
create_composio_governance_modifiers_async,
14+
govern_composio_execution,
15+
govern_composio_execution_async,
1016
map_composio_slug,
1117
)
18+
from .generic import GovernanceConfig, async_with_governance, with_governance
1219
from .google_adk import (
1320
GoogleADKGovernanceConfig,
1421
govern_google_adk_tool,
@@ -22,13 +29,6 @@
2229
govern_llamaindex_tools,
2330
govern_llamaindex_tools_async,
2431
)
25-
from .claude_agent_sdk import (
26-
ClaudeAgentGovernanceConfig,
27-
govern_claude_agent_tool,
28-
govern_claude_agent_tool_async,
29-
govern_claude_agent_tools,
30-
govern_claude_agent_tools_async,
31-
)
3232
from .nemoclaw import (
3333
NemoClawGovernanceConfig,
3434
create_nemoclaw_proxy,

src/sidclaw/middleware/claude_agent_sdk.py

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,15 @@
2121
"""
2222
from __future__ import annotations
2323

24-
import copy
25-
import functools
26-
from dataclasses import dataclass, field
27-
from typing import Any, Callable, Dict, List, Optional, Sequence
24+
from collections.abc import Sequence
25+
from dataclasses import dataclass
26+
from typing import Any
2827

2928
from .._client import AsyncSidClaw, SidClaw
30-
from .._errors import ActionDeniedError, ApprovalExpiredError, ApprovalTimeoutError
29+
from .._errors import ActionDeniedError
3130
from .._types import DataClassification, EvaluateParams, EvaluateResponse
3231
from ._base import record_outcome_async, record_outcome_sync
3332

34-
3533
# ---------------------------------------------------------------------------
3634
# Config
3735
# ---------------------------------------------------------------------------
@@ -47,7 +45,7 @@ class ClaudeAgentGovernanceConfig:
4745
resource_scope: str = "claude_agent"
4846
"""Resource scope sent to the policy engine."""
4947

50-
target_integration: Optional[str] = None
48+
target_integration: str | None = None
5149
"""Target integration name override. Defaults to the tool name."""
5250

5351
wait_for_approval: bool = True
@@ -69,7 +67,7 @@ def _evaluate_sync(
6967
client: SidClaw,
7068
tool_name: str,
7169
args: Any,
72-
config: Optional[ClaudeAgentGovernanceConfig],
70+
config: ClaudeAgentGovernanceConfig | None,
7371
) -> EvaluateResponse:
7472
"""Evaluate governance synchronously. Handles allow/deny/approval_required."""
7573
cfg = config or ClaudeAgentGovernanceConfig()
@@ -126,7 +124,7 @@ async def _evaluate_async(
126124
client: AsyncSidClaw,
127125
tool_name: str,
128126
args: Any,
129-
config: Optional[ClaudeAgentGovernanceConfig],
127+
config: ClaudeAgentGovernanceConfig | None,
130128
) -> EvaluateResponse:
131129
"""Evaluate governance asynchronously. Handles allow/deny/approval_required."""
132130
cfg = config or ClaudeAgentGovernanceConfig()
@@ -195,14 +193,14 @@ def __init__(
195193
self,
196194
client: SidClaw,
197195
tool: Any,
198-
config: Optional[ClaudeAgentGovernanceConfig] = None,
196+
config: ClaudeAgentGovernanceConfig | None = None,
199197
) -> None:
200198
self._client = client
201199
self._tool = tool
202200
self._config = config
203201
# Preserve duck-typed attributes
204202
self.name: str = getattr(tool, "name", "unknown")
205-
self.description: Optional[str] = getattr(tool, "description", None)
203+
self.description: str | None = getattr(tool, "description", None)
206204
self.parameters: Any = getattr(tool, "parameters", None)
207205

208206
def execute(self, *args: Any, **kwargs: Any) -> Any:
@@ -232,14 +230,14 @@ def __init__(
232230
self,
233231
client: AsyncSidClaw,
234232
tool: Any,
235-
config: Optional[ClaudeAgentGovernanceConfig] = None,
233+
config: ClaudeAgentGovernanceConfig | None = None,
236234
) -> None:
237235
self._client = client
238236
self._tool = tool
239237
self._config = config
240238
# Preserve duck-typed attributes
241239
self.name: str = getattr(tool, "name", "unknown")
242-
self.description: Optional[str] = getattr(tool, "description", None)
240+
self.description: str | None = getattr(tool, "description", None)
243241
self.parameters: Any = getattr(tool, "parameters", None)
244242

245243
async def execute(self, *args: Any, **kwargs: Any) -> Any:
@@ -269,7 +267,7 @@ async def execute(self, *args: Any, **kwargs: Any) -> Any:
269267
def govern_claude_agent_tool(
270268
client: SidClaw,
271269
tool: Any,
272-
config: Optional[ClaudeAgentGovernanceConfig] = None,
270+
config: ClaudeAgentGovernanceConfig | None = None,
273271
) -> GovernedClaudeAgentTool:
274272
"""Wrap a Claude Agent SDK tool with SidClaw governance (sync).
275273
@@ -301,7 +299,7 @@ def govern_claude_agent_tool(
301299
def govern_claude_agent_tool_async(
302300
client: AsyncSidClaw,
303301
tool: Any,
304-
config: Optional[ClaudeAgentGovernanceConfig] = None,
302+
config: ClaudeAgentGovernanceConfig | None = None,
305303
) -> GovernedClaudeAgentToolAsync:
306304
"""Wrap a Claude Agent SDK tool with SidClaw governance (async).
307305
@@ -336,13 +334,13 @@ def govern_claude_agent_tool_async(
336334
def govern_claude_agent_tools(
337335
client: SidClaw,
338336
tools: Sequence[Any],
339-
config: Optional[ClaudeAgentGovernanceConfig] = None,
340-
) -> List[GovernedClaudeAgentTool]:
337+
config: ClaudeAgentGovernanceConfig | None = None,
338+
) -> list[GovernedClaudeAgentTool]:
341339
"""Wrap all tools in a sequence with SidClaw governance (sync).
342340
343341
Uses each tool's name as the target integration unless overridden in config.
344342
"""
345-
results: List[GovernedClaudeAgentTool] = []
343+
results: list[GovernedClaudeAgentTool] = []
346344
for tool in tools:
347345
tool_config = ClaudeAgentGovernanceConfig(
348346
data_classification=config.data_classification if config else "internal",
@@ -359,13 +357,13 @@ def govern_claude_agent_tools(
359357
def govern_claude_agent_tools_async(
360358
client: AsyncSidClaw,
361359
tools: Sequence[Any],
362-
config: Optional[ClaudeAgentGovernanceConfig] = None,
363-
) -> List[GovernedClaudeAgentToolAsync]:
360+
config: ClaudeAgentGovernanceConfig | None = None,
361+
) -> list[GovernedClaudeAgentToolAsync]:
364362
"""Wrap all tools in a sequence with SidClaw governance (async).
365363
366364
Uses each tool's name as the target integration unless overridden in config.
367365
"""
368-
results: List[GovernedClaudeAgentToolAsync] = []
366+
results: list[GovernedClaudeAgentToolAsync] = []
369367
for tool in tools:
370368
tool_config = ClaudeAgentGovernanceConfig(
371369
data_classification=config.data_classification if config else "internal",

src/sidclaw/middleware/composio.py

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,15 @@
2323
"""
2424
from __future__ import annotations
2525

26-
import time
26+
from collections.abc import Callable
2727
from dataclasses import dataclass, field
28-
from typing import Any, Callable, Dict, Optional, Tuple
29-
30-
import anyio
28+
from typing import Any
3129

3230
from .._client import AsyncSidClaw, SidClaw
33-
from .._errors import ActionDeniedError, ApprovalExpiredError, ApprovalTimeoutError
31+
from .._errors import ActionDeniedError
3432
from .._types import DataClassification, EvaluateParams, EvaluateResponse
3533
from ._base import record_outcome_async, record_outcome_sync
3634

37-
3835
# ---------------------------------------------------------------------------
3936
# Config
4037
# ---------------------------------------------------------------------------
@@ -44,7 +41,7 @@
4441
class ComposioGovernanceConfig:
4542
"""Configuration for Composio governance middleware."""
4643

47-
data_classification: Dict[str, str] = field(default_factory=dict)
44+
data_classification: dict[str, str] = field(default_factory=dict)
4845
"""Override data classification per Composio toolkit slug (e.g. {"SALESFORCE": "confidential"})."""
4946

5047
default_classification: DataClassification = "internal"
@@ -68,7 +65,7 @@ class ComposioGovernanceConfig:
6865
# ---------------------------------------------------------------------------
6966

7067

71-
def map_composio_slug(slug: str) -> Tuple[str, str]:
68+
def map_composio_slug(slug: str) -> tuple[str, str]:
7269
"""Map a Composio tool slug to ``(operation, target_integration)``.
7370
7471
Convention:
@@ -97,7 +94,7 @@ def map_composio_slug(slug: str) -> Tuple[str, str]:
9794

9895
def _resolve_classification(
9996
toolkit_slug: str,
100-
config: Optional[ComposioGovernanceConfig],
97+
config: ComposioGovernanceConfig | None,
10198
) -> DataClassification:
10299
upper = toolkit_slug.upper()
103100
if config and upper in config.data_classification:
@@ -111,7 +108,7 @@ def _evaluate_sync(
111108
client: SidClaw,
112109
slug: str,
113110
params: Any,
114-
config: Optional[ComposioGovernanceConfig],
111+
config: ComposioGovernanceConfig | None,
115112
) -> EvaluateResponse:
116113
"""Evaluate governance synchronously. Handles allow/deny/approval_required."""
117114
operation, target_integration = map_composio_slug(slug)
@@ -172,7 +169,7 @@ async def _evaluate_async(
172169
client: AsyncSidClaw,
173170
slug: str,
174171
params: Any,
175-
config: Optional[ComposioGovernanceConfig],
172+
config: ComposioGovernanceConfig | None,
176173
) -> EvaluateResponse:
177174
"""Evaluate governance asynchronously. Handles allow/deny/approval_required."""
178175
operation, target_integration = map_composio_slug(slug)
@@ -237,7 +234,7 @@ async def _evaluate_async(
237234
def govern_composio_execution(
238235
client: SidClaw,
239236
composio_client: Any,
240-
config: Optional[ComposioGovernanceConfig] = None,
237+
config: ComposioGovernanceConfig | None = None,
241238
) -> Callable[..., Any]:
242239
"""Return a governed wrapper around ``composio.tools.execute()``.
243240
@@ -248,7 +245,13 @@ def govern_composio_execution(
248245
It evaluates governance before execution and records the outcome after.
249246
"""
250247

251-
def execute(slug: str, *, user_id: str | None = None, arguments: dict[str, Any] | None = None, **kwargs: Any) -> Any:
248+
def execute(
249+
slug: str,
250+
*,
251+
user_id: str | None = None,
252+
arguments: dict[str, Any] | None = None,
253+
**kwargs: Any,
254+
) -> Any:
252255
params = {"user_id": user_id, "arguments": arguments or {}, **kwargs}
253256
decision = _evaluate_sync(client, slug, params, config)
254257

@@ -271,7 +274,7 @@ def execute(slug: str, *, user_id: str | None = None, arguments: dict[str, Any]
271274
def govern_composio_execution_async(
272275
client: AsyncSidClaw,
273276
composio_client: Any,
274-
config: Optional[ComposioGovernanceConfig] = None,
277+
config: ComposioGovernanceConfig | None = None,
275278
) -> Callable[..., Any]:
276279
"""Return an async governed wrapper around ``composio.tools.execute()``.
277280
@@ -280,7 +283,13 @@ def govern_composio_execution_async(
280283
await execute(slug: str, *, user_id: str, arguments: dict, **kwargs) -> dict
281284
"""
282285

283-
async def execute(slug: str, *, user_id: str | None = None, arguments: dict[str, Any] | None = None, **kwargs: Any) -> Any:
286+
async def execute(
287+
slug: str,
288+
*,
289+
user_id: str | None = None,
290+
arguments: dict[str, Any] | None = None,
291+
**kwargs: Any,
292+
) -> Any:
284293
params = {"user_id": user_id, "arguments": arguments or {}, **kwargs}
285294
decision = await _evaluate_async(client, slug, params, config)
286295

@@ -307,16 +316,16 @@ async def execute(slug: str, *, user_id: str | None = None, arguments: dict[str,
307316

308317
def create_composio_governance_modifiers(
309318
client: SidClaw,
310-
config: Optional[ComposioGovernanceConfig] = None,
311-
) -> Dict[str, Any]:
319+
config: ComposioGovernanceConfig | None = None,
320+
) -> dict[str, Any]:
312321
"""Create ``before_execute`` and ``after_execute`` modifier functions.
313322
314323
These can be used with Composio's modifier/interceptor system::
315324
316325
modifiers = create_composio_governance_modifiers(client)
317326
result = composio.tools.execute("GITHUB_CREATE_ISSUE", ..., **modifiers)
318327
"""
319-
inflight: Dict[str, str] = {} # toolSlug -> trace_id
328+
inflight: dict[str, str] = {} # toolSlug -> trace_id
320329

321330
def before_execute(tool: str, toolkit: str, params: Any) -> Any:
322331
decision = _evaluate_sync(client, tool, params, config)
@@ -334,10 +343,10 @@ def after_execute(tool: str, toolkit: str, response: Any) -> Any:
334343

335344
def create_composio_governance_modifiers_async(
336345
client: AsyncSidClaw,
337-
config: Optional[ComposioGovernanceConfig] = None,
338-
) -> Dict[str, Any]:
346+
config: ComposioGovernanceConfig | None = None,
347+
) -> dict[str, Any]:
339348
"""Create async ``before_execute`` and ``after_execute`` modifier functions."""
340-
inflight: Dict[str, str] = {}
349+
inflight: dict[str, str] = {}
341350

342351
async def before_execute(tool: str, toolkit: str, params: Any) -> Any:
343352
decision = await _evaluate_async(client, tool, params, config)

0 commit comments

Comments
 (0)