blocklog 0.2.0__tar.gz → 0.2.2__tar.gz
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.
- {blocklog-0.2.0/src/blocklog.egg-info → blocklog-0.2.2}/PKG-INFO +3 -2
- {blocklog-0.2.0 → blocklog-0.2.2}/pyproject.toml +2 -2
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/__init__.py +1 -1
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/context/managers.py +5 -7
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/decorators/agent.py +9 -1
- blocklog-0.2.2/src/blocklog/signing/ed25519.py +18 -0
- {blocklog-0.2.0 → blocklog-0.2.2/src/blocklog.egg-info}/PKG-INFO +3 -2
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog.egg-info/requires.txt +3 -1
- {blocklog-0.2.0 → blocklog-0.2.2}/tests/test_client.py +5 -4
- {blocklog-0.2.0 → blocklog-0.2.2}/tests/test_public_api.py +7 -3
- blocklog-0.2.0/src/blocklog/signing/ed25519.py +0 -25
- {blocklog-0.2.0 → blocklog-0.2.2}/LICENSE +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/MANIFEST.in +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/README.md +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/docs/api-reference.md +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/docs/async.md +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/docs/changelog.md +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/docs/concepts.md +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/docs/configuration.md +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/docs/decisions.md +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/docs/decorators.md +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/docs/error-handling.md +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/docs/examples.md +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/docs/index.md +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/docs/installation.md +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/docs/integrations.md +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/docs/migration.md +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/docs/performance.md +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/docs/production.md +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/docs/quickstart.md +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/docs/tracing.md +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/docs/troubleshooting.md +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/examples/01_quickstart.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/examples/02_stock_trading_agent.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/examples/03_multi_agent_workflow.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/examples/advanced/01_human_approval_workflow.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/examples/advanced/02_incident_investigation.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/examples/advanced/03_decision_comparison.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/examples/advanced/langchain_alert_demo.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/setup.cfg +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/_global.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/_init_fn.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/api/approval.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/api/compliance.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/api/decisions.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/api/incidents.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/api/replay.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/api/traces.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/api/verify.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/approval.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/async_client.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/batching/buffer.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/client.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/compliance.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/config.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/context/vars.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/decorators/__init__.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/decorators/tool.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/incident.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/integrations/langchain.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/integrations/langgraph.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/integrations/openai_agents.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/managers/__init__.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/managers/decision.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/middleware/hooks.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/models/events.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/models/responses.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/replay.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/signing/canonical.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/transport/auth.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/transport/httpx_async.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/transport/httpx_sync.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/transport/retry.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/verify.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog.egg-info/SOURCES.txt +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog.egg-info/dependency_links.txt +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog.egg-info/top_level.txt +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/tests/test_config.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/tests/test_context.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/tests/test_decorators.py +0 -0
- {blocklog-0.2.0 → blocklog-0.2.2}/tests/test_transport.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: blocklog
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Infrastructure for AI Decision-Making — record, replay, verify, and govern AI agent decisions
|
|
5
5
|
Author-email: Blocklog <contact@blockloghq.com>
|
|
6
6
|
Maintainer-email: Blocklog <contact@blockloghq.com>
|
|
@@ -25,7 +25,8 @@ Description-Content-Type: text/markdown
|
|
|
25
25
|
License-File: LICENSE
|
|
26
26
|
Requires-Dist: httpx<1.0,>=0.27
|
|
27
27
|
Requires-Dist: pydantic<3.0,>=2.8
|
|
28
|
-
|
|
28
|
+
Provides-Extra: requests
|
|
29
|
+
Requires-Dist: requests>=2.32.0; extra == "requests"
|
|
29
30
|
Provides-Extra: dev
|
|
30
31
|
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
31
32
|
Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "blocklog"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.2"
|
|
4
4
|
description = "Infrastructure for AI Decision-Making — record, replay, verify, and govern AI agent decisions"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.10"
|
|
@@ -27,10 +27,10 @@ classifiers = [
|
|
|
27
27
|
dependencies = [
|
|
28
28
|
"httpx>=0.27,<1.0",
|
|
29
29
|
"pydantic>=2.8,<3.0",
|
|
30
|
-
"requests>=2.32.0",
|
|
31
30
|
]
|
|
32
31
|
|
|
33
32
|
[project.optional-dependencies]
|
|
33
|
+
requests = ["requests>=2.32.0"]
|
|
34
34
|
dev = [
|
|
35
35
|
"pytest>=8.0.0",
|
|
36
36
|
"pytest-asyncio>=0.23.0",
|
|
@@ -38,7 +38,7 @@ from blocklog.managers.decision import decision, DecisionContext
|
|
|
38
38
|
from blocklog import approval # noqa: E402
|
|
39
39
|
from blocklog.replay import replay # noqa: E402
|
|
40
40
|
|
|
41
|
-
__version__ = "0.2.
|
|
41
|
+
__version__ = "0.2.2"
|
|
42
42
|
|
|
43
43
|
# Expose only the minimum concepts required to understand Blocklog.
|
|
44
44
|
# Advanced features (incident, verify, compliance, clients) are hidden
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
from contextlib import contextmanager
|
|
2
|
-
|
|
3
2
|
from blocklog.models.events import SessionContext
|
|
4
|
-
|
|
5
|
-
from .vars import set_context
|
|
6
|
-
|
|
3
|
+
from .vars import set_context, get_context
|
|
7
4
|
|
|
8
5
|
@contextmanager
|
|
9
|
-
def agent_session(*, agent_id
|
|
6
|
+
def agent_session(*, agent_id=None, source="python-sdk", workflow_id=None):
|
|
7
|
+
previous = get_context()
|
|
10
8
|
context = SessionContext(agent_id=agent_id, source=source, workflow_id=workflow_id)
|
|
11
|
-
|
|
9
|
+
set_context(context)
|
|
12
10
|
try:
|
|
13
11
|
yield context
|
|
14
12
|
finally:
|
|
15
|
-
set_context(
|
|
13
|
+
set_context(previous)
|
|
@@ -65,6 +65,11 @@ def agent(
|
|
|
65
65
|
@blocklog.agent(name="my-agent", version="2.0")
|
|
66
66
|
def my_agent(): ...
|
|
67
67
|
|
|
68
|
+
.. warning::
|
|
69
|
+
Class decoration only emits ``AGENT_START``. Full lifecycle tracing
|
|
70
|
+
requires decorating the specific method (e.g. ``run``, ``execute``)
|
|
71
|
+
rather than the class itself.
|
|
72
|
+
|
|
68
73
|
Parameters
|
|
69
74
|
----------
|
|
70
75
|
func:
|
|
@@ -177,11 +182,14 @@ async def _run_async(fn: Callable, args: tuple, kwargs: dict, agent_name: str, m
|
|
|
177
182
|
|
|
178
183
|
def _wrap_class(cls: type, agent_name: str, meta: dict) -> type:
|
|
179
184
|
"""Wrap the ``__init__`` of a class to open an agent session."""
|
|
185
|
+
logger.warning(
|
|
186
|
+
"blocklog: @agent on a class only emits AGENT_START. "
|
|
187
|
+
"For full tracing, use @blocklog.agent on the method that runs the agent."
|
|
188
|
+
)
|
|
180
189
|
original_init = cls.__init__
|
|
181
190
|
|
|
182
191
|
@functools.wraps(original_init)
|
|
183
192
|
def new_init(self: Any, *args: Any, **kwargs: Any) -> None:
|
|
184
|
-
from blocklog.context.managers import agent_session
|
|
185
193
|
from blocklog.context.vars import set_context
|
|
186
194
|
from blocklog.models.events import SessionContext
|
|
187
195
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import hmac
|
|
2
|
+
from hashlib import sha256
|
|
3
|
+
|
|
4
|
+
from .canonical import canonical_json
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def hash_sign(payload: dict, private_key: str | None = None) -> str:
|
|
8
|
+
"""Generate an HMAC-SHA256 signature for a payload.
|
|
9
|
+
|
|
10
|
+
Uses HMAC-SHA256 for tamper-evidence — the signing_key is required
|
|
11
|
+
to reproduce the signature. Not Ed25519; for asymmetric signing use
|
|
12
|
+
the cryptography library.
|
|
13
|
+
"""
|
|
14
|
+
key = (private_key or "blocklog").encode("utf-8")
|
|
15
|
+
return hmac.new(key, canonical_json(payload), sha256).hexdigest()
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
pseudo_sign = hash_sign # backward compat
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: blocklog
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Infrastructure for AI Decision-Making — record, replay, verify, and govern AI agent decisions
|
|
5
5
|
Author-email: Blocklog <contact@blockloghq.com>
|
|
6
6
|
Maintainer-email: Blocklog <contact@blockloghq.com>
|
|
@@ -25,7 +25,8 @@ Description-Content-Type: text/markdown
|
|
|
25
25
|
License-File: LICENSE
|
|
26
26
|
Requires-Dist: httpx<1.0,>=0.27
|
|
27
27
|
Requires-Dist: pydantic<3.0,>=2.8
|
|
28
|
-
|
|
28
|
+
Provides-Extra: requests
|
|
29
|
+
Requires-Dist: requests>=2.32.0; extra == "requests"
|
|
29
30
|
Provides-Extra: dev
|
|
30
31
|
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
31
32
|
Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
|
|
@@ -163,15 +163,16 @@ def test_client_serialization_with_signing():
|
|
|
163
163
|
|
|
164
164
|
|
|
165
165
|
def test_client_instrumentation_methods():
|
|
166
|
-
"""Test that instrumentation methods return
|
|
166
|
+
"""Test that instrumentation methods return callback handlers."""
|
|
167
167
|
config = BlocklogConfig(api_key="blk_test")
|
|
168
168
|
client = BlocklogClient(config)
|
|
169
169
|
|
|
170
170
|
result = client.instrument_langchain()
|
|
171
|
-
assert result is
|
|
171
|
+
assert result is not None
|
|
172
|
+
assert hasattr(result, "on_chain_start")
|
|
172
173
|
|
|
173
174
|
result = client.instrument_langgraph()
|
|
174
|
-
assert result is client
|
|
175
|
+
assert result is client # langgraph returns client
|
|
175
176
|
|
|
176
177
|
result = client.instrument_openai_agents()
|
|
177
|
-
assert result is client
|
|
178
|
+
assert result is client # openai_agents returns client
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""Tests for public API imports and exports."""
|
|
2
|
-
|
|
2
|
+
from importlib.metadata import version
|
|
3
3
|
import pytest
|
|
4
4
|
|
|
5
5
|
# Test that the main package can be imported
|
|
@@ -9,11 +9,14 @@ def test_import_blocklog():
|
|
|
9
9
|
assert blocklog is not None
|
|
10
10
|
|
|
11
11
|
|
|
12
|
+
from importlib.metadata import version
|
|
13
|
+
|
|
12
14
|
def test_blocklog_version():
|
|
13
15
|
"""Test that blocklog has a version attribute."""
|
|
14
16
|
import blocklog
|
|
17
|
+
|
|
15
18
|
assert hasattr(blocklog, "__version__")
|
|
16
|
-
assert blocklog.__version__ == "
|
|
19
|
+
assert blocklog.__version__ == version("blocklog")
|
|
17
20
|
|
|
18
21
|
|
|
19
22
|
def test_public_api_exports():
|
|
@@ -81,7 +84,8 @@ def test_replay_module():
|
|
|
81
84
|
"""Test that replay module has expected functions."""
|
|
82
85
|
import blocklog.replay as replay
|
|
83
86
|
|
|
84
|
-
|
|
87
|
+
# replay is a function, not an attribute
|
|
88
|
+
assert callable(replay)
|
|
85
89
|
|
|
86
90
|
|
|
87
91
|
def test_compliance_module():
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
from hashlib import sha256
|
|
2
|
-
|
|
3
|
-
from .canonical import canonical_json
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def hash_sign(payload: dict, private_key: str | None = None) -> str:
|
|
7
|
-
"""Generate a deterministic hash signature for a payload.
|
|
8
|
-
|
|
9
|
-
This is NOT cryptographic Ed25519 signing. It generates a deterministic
|
|
10
|
-
SHA256 hash of the payload combined with a seed/key for tamper-evidence
|
|
11
|
-
purposes. For true cryptographic signing, use the cryptography library.
|
|
12
|
-
|
|
13
|
-
Args:
|
|
14
|
-
payload: The payload to hash
|
|
15
|
-
private_key: Optional seed/key for the hash (defaults to "blocklog")
|
|
16
|
-
|
|
17
|
-
Returns:
|
|
18
|
-
Hexadecimal SHA256 hash string
|
|
19
|
-
"""
|
|
20
|
-
seed = private_key or "blocklog"
|
|
21
|
-
return sha256(seed.encode("utf-8") + canonical_json(payload)).hexdigest()
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
# Backward compatibility alias
|
|
25
|
-
pseudo_sign = hash_sign
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|