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.
Files changed (81) hide show
  1. {blocklog-0.2.0/src/blocklog.egg-info → blocklog-0.2.2}/PKG-INFO +3 -2
  2. {blocklog-0.2.0 → blocklog-0.2.2}/pyproject.toml +2 -2
  3. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/__init__.py +1 -1
  4. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/context/managers.py +5 -7
  5. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/decorators/agent.py +9 -1
  6. blocklog-0.2.2/src/blocklog/signing/ed25519.py +18 -0
  7. {blocklog-0.2.0 → blocklog-0.2.2/src/blocklog.egg-info}/PKG-INFO +3 -2
  8. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog.egg-info/requires.txt +3 -1
  9. {blocklog-0.2.0 → blocklog-0.2.2}/tests/test_client.py +5 -4
  10. {blocklog-0.2.0 → blocklog-0.2.2}/tests/test_public_api.py +7 -3
  11. blocklog-0.2.0/src/blocklog/signing/ed25519.py +0 -25
  12. {blocklog-0.2.0 → blocklog-0.2.2}/LICENSE +0 -0
  13. {blocklog-0.2.0 → blocklog-0.2.2}/MANIFEST.in +0 -0
  14. {blocklog-0.2.0 → blocklog-0.2.2}/README.md +0 -0
  15. {blocklog-0.2.0 → blocklog-0.2.2}/docs/api-reference.md +0 -0
  16. {blocklog-0.2.0 → blocklog-0.2.2}/docs/async.md +0 -0
  17. {blocklog-0.2.0 → blocklog-0.2.2}/docs/changelog.md +0 -0
  18. {blocklog-0.2.0 → blocklog-0.2.2}/docs/concepts.md +0 -0
  19. {blocklog-0.2.0 → blocklog-0.2.2}/docs/configuration.md +0 -0
  20. {blocklog-0.2.0 → blocklog-0.2.2}/docs/decisions.md +0 -0
  21. {blocklog-0.2.0 → blocklog-0.2.2}/docs/decorators.md +0 -0
  22. {blocklog-0.2.0 → blocklog-0.2.2}/docs/error-handling.md +0 -0
  23. {blocklog-0.2.0 → blocklog-0.2.2}/docs/examples.md +0 -0
  24. {blocklog-0.2.0 → blocklog-0.2.2}/docs/index.md +0 -0
  25. {blocklog-0.2.0 → blocklog-0.2.2}/docs/installation.md +0 -0
  26. {blocklog-0.2.0 → blocklog-0.2.2}/docs/integrations.md +0 -0
  27. {blocklog-0.2.0 → blocklog-0.2.2}/docs/migration.md +0 -0
  28. {blocklog-0.2.0 → blocklog-0.2.2}/docs/performance.md +0 -0
  29. {blocklog-0.2.0 → blocklog-0.2.2}/docs/production.md +0 -0
  30. {blocklog-0.2.0 → blocklog-0.2.2}/docs/quickstart.md +0 -0
  31. {blocklog-0.2.0 → blocklog-0.2.2}/docs/tracing.md +0 -0
  32. {blocklog-0.2.0 → blocklog-0.2.2}/docs/troubleshooting.md +0 -0
  33. {blocklog-0.2.0 → blocklog-0.2.2}/examples/01_quickstart.py +0 -0
  34. {blocklog-0.2.0 → blocklog-0.2.2}/examples/02_stock_trading_agent.py +0 -0
  35. {blocklog-0.2.0 → blocklog-0.2.2}/examples/03_multi_agent_workflow.py +0 -0
  36. {blocklog-0.2.0 → blocklog-0.2.2}/examples/advanced/01_human_approval_workflow.py +0 -0
  37. {blocklog-0.2.0 → blocklog-0.2.2}/examples/advanced/02_incident_investigation.py +0 -0
  38. {blocklog-0.2.0 → blocklog-0.2.2}/examples/advanced/03_decision_comparison.py +0 -0
  39. {blocklog-0.2.0 → blocklog-0.2.2}/examples/advanced/langchain_alert_demo.py +0 -0
  40. {blocklog-0.2.0 → blocklog-0.2.2}/setup.cfg +0 -0
  41. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/_global.py +0 -0
  42. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/_init_fn.py +0 -0
  43. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/api/approval.py +0 -0
  44. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/api/compliance.py +0 -0
  45. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/api/decisions.py +0 -0
  46. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/api/incidents.py +0 -0
  47. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/api/replay.py +0 -0
  48. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/api/traces.py +0 -0
  49. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/api/verify.py +0 -0
  50. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/approval.py +0 -0
  51. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/async_client.py +0 -0
  52. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/batching/buffer.py +0 -0
  53. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/client.py +0 -0
  54. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/compliance.py +0 -0
  55. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/config.py +0 -0
  56. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/context/vars.py +0 -0
  57. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/decorators/__init__.py +0 -0
  58. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/decorators/tool.py +0 -0
  59. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/incident.py +0 -0
  60. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/integrations/langchain.py +0 -0
  61. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/integrations/langgraph.py +0 -0
  62. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/integrations/openai_agents.py +0 -0
  63. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/managers/__init__.py +0 -0
  64. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/managers/decision.py +0 -0
  65. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/middleware/hooks.py +0 -0
  66. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/models/events.py +0 -0
  67. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/models/responses.py +0 -0
  68. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/replay.py +0 -0
  69. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/signing/canonical.py +0 -0
  70. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/transport/auth.py +0 -0
  71. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/transport/httpx_async.py +0 -0
  72. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/transport/httpx_sync.py +0 -0
  73. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/transport/retry.py +0 -0
  74. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog/verify.py +0 -0
  75. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog.egg-info/SOURCES.txt +0 -0
  76. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog.egg-info/dependency_links.txt +0 -0
  77. {blocklog-0.2.0 → blocklog-0.2.2}/src/blocklog.egg-info/top_level.txt +0 -0
  78. {blocklog-0.2.0 → blocklog-0.2.2}/tests/test_config.py +0 -0
  79. {blocklog-0.2.0 → blocklog-0.2.2}/tests/test_context.py +0 -0
  80. {blocklog-0.2.0 → blocklog-0.2.2}/tests/test_decorators.py +0 -0
  81. {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.0
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
- Requires-Dist: requests>=2.32.0
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.0"
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.0"
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: str | None = None, source: str = "python-sdk", workflow_id=None):
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
- token = set_context(context)
9
+ set_context(context)
12
10
  try:
13
11
  yield context
14
12
  finally:
15
- set_context(None)
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.0
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
- Requires-Dist: requests>=2.32.0
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,9 +1,11 @@
1
1
  httpx<1.0,>=0.27
2
2
  pydantic<3.0,>=2.8
3
- requests>=2.32.0
4
3
 
5
4
  [dev]
6
5
  pytest>=8.0.0
7
6
  pytest-asyncio>=0.23.0
8
7
  build>=1.0.0
9
8
  twine>=5.0.0
9
+
10
+ [requests]
11
+ requests>=2.32.0
@@ -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 client for chaining."""
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 client
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__ == "0.2.0"
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
- assert hasattr(replay, "replay")
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