openadapt-verify 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- openadapt_verify/__init__.py +65 -0
- openadapt_verify/__main__.py +3 -0
- openadapt_verify/_ledger_config.py +21 -0
- openadapt_verify/adapters/__init__.py +1 -0
- openadapt_verify/adapters/browser_use.py +39 -0
- openadapt_verify/adapters/claude_sdk.py +5 -0
- openadapt_verify/adapters/openai_agents.py +5 -0
- openadapt_verify/adapters/stagehand.py +32 -0
- openadapt_verify/audit.py +742 -0
- openadapt_verify/audit_demo.py +106 -0
- openadapt_verify/cli.py +463 -0
- openadapt_verify/guard.py +130 -0
- openadapt_verify/mcp.py +24 -0
- openadapt_verify/quickstart.py +567 -0
- openadapt_verify/shadow.py +5 -0
- openadapt_verify-0.2.0.dist-info/METADATA +382 -0
- openadapt_verify-0.2.0.dist-info/RECORD +20 -0
- openadapt_verify-0.2.0.dist-info/WHEEL +4 -0
- openadapt_verify-0.2.0.dist-info/entry_points.txt +2 -0
- openadapt_verify-0.2.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""Public facade over OpenAdapt's canonical verifier and receipt formats.
|
|
2
|
+
|
|
3
|
+
WriteResult describes the store's outcome. LocalSealVerification and
|
|
4
|
+
PortableReceiptVerification describe different signature formats; neither
|
|
5
|
+
substitutes for the store result or a caller's pinned issuer trust.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import TYPE_CHECKING, Any
|
|
9
|
+
|
|
10
|
+
from openadapt_flow.offline_seal import LocalSealVerification, verify_local_seal
|
|
11
|
+
from openadapt_flow.verifier import (
|
|
12
|
+
Actor,
|
|
13
|
+
AlreadyWritten,
|
|
14
|
+
Contract,
|
|
15
|
+
Outcome,
|
|
16
|
+
Scope,
|
|
17
|
+
WriteBlocked,
|
|
18
|
+
WriteResult,
|
|
19
|
+
begin_write,
|
|
20
|
+
issue_write_receipt,
|
|
21
|
+
recheck,
|
|
22
|
+
verify_write,
|
|
23
|
+
)
|
|
24
|
+
from openadapt_flow.write_receipt import ReceiptError
|
|
25
|
+
from openadapt_flow.write_receipt import Verification as PortableReceiptVerification
|
|
26
|
+
from openadapt_flow.write_receipt import verify as verify_receipt
|
|
27
|
+
|
|
28
|
+
from openadapt_verify.guard import checked_write, verified
|
|
29
|
+
|
|
30
|
+
__version__ = "0.2.0"
|
|
31
|
+
|
|
32
|
+
__all__ = [
|
|
33
|
+
"Actor",
|
|
34
|
+
"AlreadyWritten",
|
|
35
|
+
"Contract",
|
|
36
|
+
"LocalSealVerification",
|
|
37
|
+
"Outcome",
|
|
38
|
+
"PortableReceiptVerification",
|
|
39
|
+
"ReceiptError",
|
|
40
|
+
"Scope",
|
|
41
|
+
"WriteBlocked",
|
|
42
|
+
"WriteGuard",
|
|
43
|
+
"WriteResult",
|
|
44
|
+
"begin_write",
|
|
45
|
+
"checked_write",
|
|
46
|
+
"issue_write_receipt",
|
|
47
|
+
"recheck",
|
|
48
|
+
"verify_local_seal",
|
|
49
|
+
"verified",
|
|
50
|
+
"verify_receipt",
|
|
51
|
+
"verify_write",
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
if TYPE_CHECKING:
|
|
56
|
+
from openadapt_flow.integrations.agents import WriteGuard
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def __getattr__(name: str) -> Any:
|
|
60
|
+
if name == "WriteGuard":
|
|
61
|
+
from openadapt_flow.integrations.agents import WriteGuard
|
|
62
|
+
|
|
63
|
+
globals()[name] = WriteGuard
|
|
64
|
+
return WriteGuard
|
|
65
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Refuse protected operation when the installed Flow cannot select it."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
_PROTECTED_CONFIG_ENV = "OPENADAPT_LEDGER_AUTHORITY_CONFIG"
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ProtectedLedgerUnsupported(RuntimeError):
|
|
9
|
+
"""The installed Flow lacks the configured protected default."""
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def require_protected_default_support() -> None:
|
|
13
|
+
if _PROTECTED_CONFIG_ENV not in os.environ:
|
|
14
|
+
return
|
|
15
|
+
from openadapt_flow import write_ledger
|
|
16
|
+
|
|
17
|
+
if (
|
|
18
|
+
getattr(write_ledger, "PROTECTED_LEDGER_CONFIG_ENV", None)
|
|
19
|
+
!= _PROTECTED_CONFIG_ENV
|
|
20
|
+
):
|
|
21
|
+
raise ProtectedLedgerUnsupported("ledger_authority_unsupported")
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Opt-in write wrappers. Calls outside a wrapper are not protected."""
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Wrap a typed async action before registering it with browser-use Tools."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import inspect
|
|
6
|
+
from functools import wraps
|
|
7
|
+
from typing import Any, Callable
|
|
8
|
+
|
|
9
|
+
from openadapt_flow.integrations.agents import WriteGuard, reply_text
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def verified(
|
|
13
|
+
action: Callable[..., Any], *, contract: Any, **options: Any
|
|
14
|
+
) -> Callable[..., Any]:
|
|
15
|
+
"""Return tool text from a guarded action; other browser actions stay outside.
|
|
16
|
+
|
|
17
|
+
Register the returned function with ``tools.action(...)``. Its parameter
|
|
18
|
+
names and evaluated annotations are preserved, including browser_session.
|
|
19
|
+
"""
|
|
20
|
+
if not inspect.iscoroutinefunction(action):
|
|
21
|
+
raise TypeError("browser-use verified actions must be async functions")
|
|
22
|
+
signature = inspect.signature(action, eval_str=True)
|
|
23
|
+
guard = WriteGuard(contract, **options)
|
|
24
|
+
|
|
25
|
+
@wraps(action)
|
|
26
|
+
async def checked(*args: Any, **kwargs: Any) -> str:
|
|
27
|
+
bound = signature.bind(*args, **kwargs)
|
|
28
|
+
bound.apply_defaults()
|
|
29
|
+
reply = await guard.arun(bound.arguments, lambda: action(*args, **kwargs))
|
|
30
|
+
return reply_text(reply)
|
|
31
|
+
|
|
32
|
+
checked.__signature__ = signature.replace(return_annotation=str) # type: ignore[attr-defined]
|
|
33
|
+
checked.__annotations__ = {
|
|
34
|
+
name: parameter.annotation
|
|
35
|
+
for name, parameter in signature.parameters.items()
|
|
36
|
+
if parameter.annotation is not inspect.Parameter.empty
|
|
37
|
+
}
|
|
38
|
+
checked.__annotations__["return"] = str
|
|
39
|
+
return checked
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""Explicit single-act guard for a caller-owned Stagehand Python session."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any, Mapping
|
|
6
|
+
|
|
7
|
+
from openadapt_flow.integrations.agents import WriteGuard
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class VerifiedSession:
|
|
11
|
+
"""Only this object's act call is checked; the original session is unchanged.
|
|
12
|
+
|
|
13
|
+
``values`` bind the operator's existing verification contract. Stagehand's
|
|
14
|
+
response is tool output, never evidence that the record was persisted.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
def __init__(self, session: Any, *, contract: Any, **options: Any) -> None:
|
|
18
|
+
if not callable(getattr(session, "act", None)):
|
|
19
|
+
raise TypeError("a Stagehand session with an async act method is required")
|
|
20
|
+
self._session = session
|
|
21
|
+
self._guard = WriteGuard(contract, **options)
|
|
22
|
+
|
|
23
|
+
async def act(
|
|
24
|
+
self, *, values: Mapping[str, Any], input: Any, **options: Any
|
|
25
|
+
) -> dict:
|
|
26
|
+
return await self._guard.arun(
|
|
27
|
+
values, lambda: self._session.act(input=input, **options)
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def verified(session: Any, *, contract: Any, **options: Any) -> VerifiedSession:
|
|
32
|
+
return VerifiedSession(session, contract=contract, **options)
|