zambo-haystack 0.1.2__tar.gz → 0.1.3__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.
- {zambo_haystack-0.1.2/src/zambo_haystack.egg-info → zambo_haystack-0.1.3}/PKG-INFO +14 -1
- {zambo_haystack-0.1.2 → zambo_haystack-0.1.3}/README.md +13 -0
- {zambo_haystack-0.1.2 → zambo_haystack-0.1.3}/pyproject.toml +1 -1
- {zambo_haystack-0.1.2 → zambo_haystack-0.1.3}/src/zambo_haystack/__init__.py +4 -1
- zambo_haystack-0.1.3/src/zambo_haystack/aer1.py +71 -0
- {zambo_haystack-0.1.2 → zambo_haystack-0.1.3}/src/zambo_haystack/client.py +13 -2
- {zambo_haystack-0.1.2 → zambo_haystack-0.1.3/src/zambo_haystack.egg-info}/PKG-INFO +14 -1
- {zambo_haystack-0.1.2 → zambo_haystack-0.1.3}/src/zambo_haystack.egg-info/SOURCES.txt +2 -0
- {zambo_haystack-0.1.2 → zambo_haystack-0.1.3}/LICENSE +0 -0
- {zambo_haystack-0.1.2 → zambo_haystack-0.1.3}/setup.cfg +0 -0
- {zambo_haystack-0.1.2 → zambo_haystack-0.1.3}/src/zambo_haystack/tools.py +0 -0
- {zambo_haystack-0.1.2 → zambo_haystack-0.1.3}/src/zambo_haystack.egg-info/dependency_links.txt +0 -0
- {zambo_haystack-0.1.2 → zambo_haystack-0.1.3}/src/zambo_haystack.egg-info/requires.txt +0 -0
- {zambo_haystack-0.1.2 → zambo_haystack-0.1.3}/src/zambo_haystack.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: zambo-haystack
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: Verifiable execution receipts for Haystack agents. Every tool call mints a verifiable AER-1 receipt at zambo.dev.
|
|
5
5
|
Author-email: Zambo <brennanzambo@zambo.dev>
|
|
6
6
|
License: MIT
|
|
@@ -102,3 +102,16 @@ Browse the full catalog any time with `zambo_haystack.list_tools()`, or pick too
|
|
|
102
102
|
- What is an AI agent execution receipt?: https://zambo.dev/guides/ai-agent-execution-receipt/
|
|
103
103
|
|
|
104
104
|
MIT License.
|
|
105
|
+
|
|
106
|
+
## Local AER-1 receipts (no network needed)
|
|
107
|
+
|
|
108
|
+
The package also mints AER-1 execution receipts locally, with no API calls:
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
from zambo_haystack import mint_receipt, verify_receipt
|
|
112
|
+
|
|
113
|
+
receipt = mint_receipt("my_tool", {"query": "hello"}, {"answer": "hi"}, ms=42)
|
|
114
|
+
assert verify_receipt(receipt) # recomputes the SHA-256 locally
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Local receipts follow the AER-1 core members (`id`, `created_at`, `tool`, `provenance_class`, `canonical_bytes`, `output_hash`) and use the provenance class `EXECUTED BY ZAMBO-HAYSTACK`, naming this package as the recording system. They pass the same hash-recomputation check as any AER-1 receipt.
|
|
@@ -78,3 +78,16 @@ Browse the full catalog any time with `zambo_haystack.list_tools()`, or pick too
|
|
|
78
78
|
- What is an AI agent execution receipt?: https://zambo.dev/guides/ai-agent-execution-receipt/
|
|
79
79
|
|
|
80
80
|
MIT License.
|
|
81
|
+
|
|
82
|
+
## Local AER-1 receipts (no network needed)
|
|
83
|
+
|
|
84
|
+
The package also mints AER-1 execution receipts locally, with no API calls:
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
from zambo_haystack import mint_receipt, verify_receipt
|
|
88
|
+
|
|
89
|
+
receipt = mint_receipt("my_tool", {"query": "hello"}, {"answer": "hi"}, ms=42)
|
|
90
|
+
assert verify_receipt(receipt) # recomputes the SHA-256 locally
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Local receipts follow the AER-1 core members (`id`, `created_at`, `tool`, `provenance_class`, `canonical_bytes`, `output_hash`) and use the provenance class `EXECUTED BY ZAMBO-HAYSTACK`, naming this package as the recording system. They pass the same hash-recomputation check as any AER-1 receipt.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "zambo-haystack"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.3"
|
|
8
8
|
description = "Verifiable execution receipts for Haystack agents. Every tool call mints a verifiable AER-1 receipt at zambo.dev."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -7,8 +7,9 @@ tier: 20 calls per tool per day.
|
|
|
7
7
|
|
|
8
8
|
from .client import call_tool, list_tools, ZamboReceipt, ZamboResult
|
|
9
9
|
from .tools import lookup_receipt, zambo_tool, zambo_tools
|
|
10
|
+
from .aer1 import mint_receipt, verify_receipt
|
|
10
11
|
|
|
11
|
-
__version__ = "0.1.
|
|
12
|
+
__version__ = "0.1.3"
|
|
12
13
|
|
|
13
14
|
__all__ = [
|
|
14
15
|
"call_tool",
|
|
@@ -18,4 +19,6 @@ __all__ = [
|
|
|
18
19
|
"zambo_tools",
|
|
19
20
|
"ZamboReceipt",
|
|
20
21
|
"ZamboResult",
|
|
22
|
+
"mint_receipt",
|
|
23
|
+
"verify_receipt",
|
|
21
24
|
]
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"""Local AER-1 execution receipt emitter.
|
|
2
|
+
|
|
3
|
+
Mints verifiable AER-1 execution receipts locally, with no network calls and
|
|
4
|
+
no dependencies beyond the Python standard library.
|
|
5
|
+
|
|
6
|
+
AER-1 (AI Agent Execution Receipt) is the verifiable execution receipt
|
|
7
|
+
standard created by Brennan Zambo (IETF draft-zambo-aer1-02). A receipt is a
|
|
8
|
+
small JSON record describing one tool call: what ran, what it was given, what
|
|
9
|
+
it returned, and when. The receipt carries a SHA-256 hash over its canonical
|
|
10
|
+
bytes, so anyone can recompute the hash and confirm the record is intact.
|
|
11
|
+
|
|
12
|
+
Receipts minted here use the provenance class ``EXECUTED BY ZAMBO-HAYSTACK``,
|
|
13
|
+
naming this package as the recording system, per Section 5 of the draft
|
|
14
|
+
("another implementation substitutes its own system name").
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
import base64
|
|
20
|
+
import hashlib
|
|
21
|
+
import json
|
|
22
|
+
import uuid
|
|
23
|
+
from datetime import datetime, timezone
|
|
24
|
+
from typing import Any
|
|
25
|
+
|
|
26
|
+
SCHEMA_VERSION = "0.3"
|
|
27
|
+
PROVENANCE_CLASS = "EXECUTED BY ZAMBO-HAYSTACK"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _utc_now_rfc3339() -> str:
|
|
31
|
+
now = datetime.now(timezone.utc)
|
|
32
|
+
return now.strftime("%Y-%m-%dT%H:%M:%S.") + "%03dZ" % (now.microsecond // 1000)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _canonical_bytes(tool_name: str, inputs: dict, outputs: dict, ms: int) -> bytes:
|
|
36
|
+
payload = {"tool": tool_name, "inputs": inputs, "outputs": outputs, "ms": ms}
|
|
37
|
+
return json.dumps(payload, separators=(",", ":"), ensure_ascii=True).encode("utf-8")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def mint_receipt(
|
|
41
|
+
tool_name: str,
|
|
42
|
+
inputs: Any = None,
|
|
43
|
+
outputs: Any = None,
|
|
44
|
+
ms: int = 0,
|
|
45
|
+
tool_version: str = "0.1.3",
|
|
46
|
+
scope: str = "local",
|
|
47
|
+
) -> dict:
|
|
48
|
+
"""Mint a verifiable AER-1 execution receipt for one tool call."""
|
|
49
|
+
inputs_obj = inputs if isinstance(inputs, dict) else {"value": inputs}
|
|
50
|
+
outputs_obj = outputs if isinstance(outputs, dict) else {"value": outputs}
|
|
51
|
+
raw = _canonical_bytes(tool_name, inputs_obj, outputs_obj, int(ms))
|
|
52
|
+
return {
|
|
53
|
+
"id": str(uuid.uuid4()),
|
|
54
|
+
"receipt_schema_version": SCHEMA_VERSION,
|
|
55
|
+
"created_at": _utc_now_rfc3339(),
|
|
56
|
+
"tool": {"name": tool_name, "version": tool_version, "scope": scope},
|
|
57
|
+
"provenance_class": PROVENANCE_CLASS,
|
|
58
|
+
"canonical_bytes": base64.b64encode(raw).decode("ascii"),
|
|
59
|
+
"output_hash": "sha256:" + hashlib.sha256(raw).hexdigest(),
|
|
60
|
+
"verification_status": "verified",
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def verify_receipt(receipt: dict) -> bool:
|
|
65
|
+
"""Check a receipt's integrity by recomputing its hash locally."""
|
|
66
|
+
try:
|
|
67
|
+
raw = base64.b64decode(receipt["canonical_bytes"])
|
|
68
|
+
digest = "sha256:" + hashlib.sha256(raw).hexdigest()
|
|
69
|
+
return digest == receipt["output_hash"]
|
|
70
|
+
except Exception:
|
|
71
|
+
return False
|
|
@@ -13,6 +13,8 @@ import urllib.error
|
|
|
13
13
|
import urllib.request
|
|
14
14
|
from dataclasses import dataclass, field
|
|
15
15
|
|
|
16
|
+
from .aer1 import mint_receipt, verify_receipt
|
|
17
|
+
|
|
16
18
|
MCP_URL = "https://zambo.dev/api/mcp"
|
|
17
19
|
_TIMEOUT = 60
|
|
18
20
|
_MAX_ATTEMPTS = 6
|
|
@@ -33,6 +35,7 @@ class ZamboResult:
|
|
|
33
35
|
text: str
|
|
34
36
|
receipt: ZamboReceipt | None = None
|
|
35
37
|
raw: dict = field(default_factory=dict)
|
|
38
|
+
local_receipt: dict | None = None
|
|
36
39
|
|
|
37
40
|
|
|
38
41
|
def _post(payload: dict) -> dict:
|
|
@@ -62,7 +65,7 @@ def _post(payload: dict) -> dict:
|
|
|
62
65
|
raise RuntimeError(f"Zambo API call failed after {_MAX_ATTEMPTS} attempts: {last_error}")
|
|
63
66
|
|
|
64
67
|
|
|
65
|
-
def call_tool(tool_name: str, arguments: dict) -> ZamboResult:
|
|
68
|
+
def call_tool(tool_name: str, arguments: dict, emit_aer1: bool = False) -> ZamboResult:
|
|
66
69
|
"""Call a Zambo MCP tool and return its result plus the receipt.
|
|
67
70
|
|
|
68
71
|
Every call mints a verifiable AER-1 receipt: a public URL carrying the
|
|
@@ -98,7 +101,15 @@ def call_tool(tool_name: str, arguments: dict) -> ZamboResult:
|
|
|
98
101
|
text_parts.append(str(item["text"]))
|
|
99
102
|
text = "\n".join(text_parts).strip()
|
|
100
103
|
|
|
101
|
-
|
|
104
|
+
local_receipt = None
|
|
105
|
+
if emit_aer1:
|
|
106
|
+
local_receipt = mint_receipt(
|
|
107
|
+
tool_name=tool_name,
|
|
108
|
+
inputs={"arguments": arguments},
|
|
109
|
+
outputs={"text": text},
|
|
110
|
+
scope="local",
|
|
111
|
+
)
|
|
112
|
+
return ZamboResult(text=text, receipt=receipt, raw=result, local_receipt=local_receipt)
|
|
102
113
|
|
|
103
114
|
|
|
104
115
|
def list_tools() -> list[dict]:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: zambo-haystack
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: Verifiable execution receipts for Haystack agents. Every tool call mints a verifiable AER-1 receipt at zambo.dev.
|
|
5
5
|
Author-email: Zambo <brennanzambo@zambo.dev>
|
|
6
6
|
License: MIT
|
|
@@ -102,3 +102,16 @@ Browse the full catalog any time with `zambo_haystack.list_tools()`, or pick too
|
|
|
102
102
|
- What is an AI agent execution receipt?: https://zambo.dev/guides/ai-agent-execution-receipt/
|
|
103
103
|
|
|
104
104
|
MIT License.
|
|
105
|
+
|
|
106
|
+
## Local AER-1 receipts (no network needed)
|
|
107
|
+
|
|
108
|
+
The package also mints AER-1 execution receipts locally, with no API calls:
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
from zambo_haystack import mint_receipt, verify_receipt
|
|
112
|
+
|
|
113
|
+
receipt = mint_receipt("my_tool", {"query": "hello"}, {"answer": "hi"}, ms=42)
|
|
114
|
+
assert verify_receipt(receipt) # recomputes the SHA-256 locally
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Local receipts follow the AER-1 core members (`id`, `created_at`, `tool`, `provenance_class`, `canonical_bytes`, `output_hash`) and use the provenance class `EXECUTED BY ZAMBO-HAYSTACK`, naming this package as the recording system. They pass the same hash-recomputation check as any AER-1 receipt.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{zambo_haystack-0.1.2 → zambo_haystack-0.1.3}/src/zambo_haystack.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|