clawpowers 2.2.5 → 2.2.7
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.
- package/CHANGELOG.md +186 -160
- package/COMPATIBILITY.md +48 -13
- package/KNOWN_LIMITATIONS.md +20 -19
- package/LICENSE +44 -44
- package/LICENSING.md +10 -10
- package/README.md +486 -462
- package/SECURITY.md +52 -52
- package/dist/index.d.ts +17 -5
- package/dist/index.js +187 -92
- package/dist/index.js.map +1 -1
- package/native/Cargo.lock +4927 -4927
- package/native/Cargo.toml +73 -73
- package/native/crates/canonical/Cargo.toml +24 -24
- package/native/crates/canonical/src/lib.rs +677 -673
- package/native/crates/compression/Cargo.toml +20 -20
- package/native/crates/compression/benches/compression_bench.rs +42 -42
- package/native/crates/compression/src/lib.rs +393 -393
- package/native/crates/evm-eth/Cargo.toml +13 -13
- package/native/crates/evm-eth/src/lib.rs +105 -105
- package/native/crates/fee/Cargo.toml +15 -15
- package/native/crates/fee/src/lib.rs +281 -281
- package/native/crates/index/Cargo.toml +16 -16
- package/native/crates/index/src/lib.rs +277 -277
- package/native/crates/policy/Cargo.toml +17 -17
- package/native/crates/policy/src/lib.rs +614 -614
- package/native/crates/security/Cargo.toml +22 -22
- package/native/crates/security/src/lib.rs +478 -478
- package/native/crates/tokens/Cargo.toml +13 -13
- package/native/crates/tokens/src/lib.rs +534 -534
- package/native/crates/verification/Cargo.toml +23 -23
- package/native/crates/verification/src/lib.rs +333 -333
- package/native/crates/wallet/Cargo.toml +20 -20
- package/native/crates/wallet/src/lib.rs +261 -261
- package/native/crates/x402/Cargo.toml +30 -30
- package/native/crates/x402/src/lib.rs +423 -423
- package/native/ffi/Cargo.toml +34 -34
- package/native/ffi/build.rs +4 -4
- package/native/ffi/src/lib.rs +352 -352
- package/native/ffi/tests/integration.rs +354 -354
- package/native/pyo3/Cargo.toml +26 -26
- package/native/pyo3/pyproject.toml +16 -16
- package/native/pyo3/src/lib.rs +407 -407
- package/native/pyo3/tests/test_smoke.py +180 -180
- package/native/wasm/Cargo.toml +47 -44
- package/native/wasm/pkg/.gitignore +6 -6
- package/native/wasm/pkg/clawpowers_wasm.d.ts +208 -208
- package/native/wasm/pkg/clawpowers_wasm.js +872 -872
- package/native/wasm/pkg/clawpowers_wasm_bg.wasm.d.ts +40 -40
- package/native/wasm/pkg/package.json +16 -16
- package/native/wasm/pkg-node/clawpowers_wasm.d.ts +143 -143
- package/native/wasm/pkg-node/clawpowers_wasm.js +798 -798
- package/native/wasm/pkg-node/clawpowers_wasm_bg.wasm.d.ts +40 -40
- package/native/wasm/pkg-node/package.json +12 -12
- package/native/wasm/src/lib.rs +433 -433
- package/package.json +13 -8
- package/scripts/build-wasm.mjs +59 -0
- package/scripts/generate_hermes_wrappers.py +211 -0
- package/scripts/hermes_wrapper_overrides.json +184 -0
- package/scripts/run-python-script.mjs +48 -0
- package/scripts/verify-consumer-install.mjs +109 -0
- package/scripts/verify-wasm-artifacts.mjs +26 -3
- package/scripts/verify_hermes_wrappers.py +154 -0
- package/skill.json +20 -0
- package/skills/1password/SKILL.md +34 -0
- package/skills/README.md +44 -0
- package/skills/agent-nexus-2/SKILL.md +34 -0
- package/skills/apple-notes/SKILL.md +34 -0
- package/skills/apple-reminders/SKILL.md +34 -0
- package/skills/autoresearch/SKILL.md +43 -0
- package/skills/bear-notes/SKILL.md +34 -0
- package/skills/blogwatcher/SKILL.md +34 -0
- package/skills/blucli/SKILL.md +34 -0
- package/skills/bluebubbles/SKILL.md +34 -0
- package/skills/business-strategy/SKILL.md +41 -0
- package/skills/camsnap/SKILL.md +34 -0
- package/skills/canvas/SKILL.md +34 -0
- package/skills/clawhub/SKILL.md +34 -0
- package/skills/coding-agent/SKILL.md +34 -0
- package/skills/coding-discipline.skill/SKILL.md +34 -0
- package/skills/content-writer/SKILL.md +41 -0
- package/skills/discord/SKILL.md +34 -0
- package/skills/eightctl/SKILL.md +34 -0
- package/skills/execution-validation.skill/SKILL.md +34 -0
- package/skills/gemini/SKILL.md +34 -0
- package/skills/gh-issues/SKILL.md +34 -0
- package/skills/gifgrep/SKILL.md +34 -0
- package/skills/github/SKILL.md +41 -0
- package/skills/gog/SKILL.md +34 -0
- package/skills/goplaces/SKILL.md +34 -0
- package/skills/healthcheck/SKILL.md +34 -0
- package/skills/himalaya/SKILL.md +34 -0
- package/skills/humanize/SKILL.md +41 -0
- package/skills/imsg/SKILL.md +34 -0
- package/skills/itp/SKILL.md +112 -0
- package/skills/mcporter/SKILL.md +34 -0
- package/skills/model-usage/SKILL.md +34 -0
- package/skills/nano-pdf/SKILL.md +34 -0
- package/skills/node-connect/SKILL.md +34 -0
- package/skills/notion/SKILL.md +34 -0
- package/skills/obsidian/SKILL.md +34 -0
- package/skills/openai-whisper/SKILL.md +34 -0
- package/skills/openai-whisper-api/SKILL.md +34 -0
- package/skills/openhue/SKILL.md +34 -0
- package/skills/oracle/SKILL.md +34 -0
- package/skills/ordercli/SKILL.md +34 -0
- package/skills/peekaboo/SKILL.md +34 -0
- package/skills/polyclaw/SKILL.md +34 -0
- package/skills/prospector/SKILL.md +41 -0
- package/skills/rsi.skill/SKILL.md +34 -0
- package/skills/sag/SKILL.md +34 -0
- package/skills/security/SKILL.md +41 -0
- package/skills/session-logs/SKILL.md +34 -0
- package/skills/sherpa-onnx-tts/SKILL.md +34 -0
- package/skills/skill-creator/SKILL.md +34 -0
- package/skills/slack/SKILL.md +34 -0
- package/skills/songsee/SKILL.md +34 -0
- package/skills/sonoscli/SKILL.md +34 -0
- package/skills/spotify-player/SKILL.md +34 -0
- package/skills/strykr-prism/SKILL.md +41 -0
- package/skills/summarize/SKILL.md +34 -0
- package/skills/taskbridge/SKILL.md +34 -0
- package/skills/things-mac/SKILL.md +34 -0
- package/skills/tmux/SKILL.md +34 -0
- package/skills/trello/SKILL.md +34 -0
- package/skills/validator-agent/SKILL.md +41 -0
- package/skills/video-frames/SKILL.md +34 -0
- package/skills/voice-call/SKILL.md +34 -0
- package/skills/wacli/SKILL.md +34 -0
- package/skills/weather/SKILL.md +34 -0
- package/skills/webmcp-payments/SKILL.md +41 -0
- package/skills/xurl/SKILL.md +34 -0
- package/src/skills/catalog.ts +435 -435
- package/src/skills/executor.ts +56 -56
- package/src/skills/index.ts +3 -3
- package/src/skills/itp/SKILL.md +112 -112
- package/src/skills/loader.ts +262 -193
- package/native/ffi/index.node +0 -0
- package/native/wasm/pkg-node/.gitignore +0 -6
|
@@ -1,180 +1,180 @@
|
|
|
1
|
-
"""Smoke test for clawpowers_core PyO3 bindings.
|
|
2
|
-
|
|
3
|
-
Exercises at least one function from: wallet, tokens, fee, x402, canonical,
|
|
4
|
-
compression, security, and policy (8 crates).
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
import json
|
|
8
|
-
import sys
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def main():
|
|
12
|
-
import clawpowers_core as cc
|
|
13
|
-
|
|
14
|
-
passed = 0
|
|
15
|
-
total = 0
|
|
16
|
-
|
|
17
|
-
# ── 1. Wallet ──────────────────────────────────────────────────────────
|
|
18
|
-
total += 1
|
|
19
|
-
w = cc.AgentWallet.generate()
|
|
20
|
-
addr = w.address()
|
|
21
|
-
assert addr.startswith("0x"), f"address should start with 0x, got {addr}"
|
|
22
|
-
assert len(addr) == 42, f"address should be 42 chars, got {len(addr)}"
|
|
23
|
-
wid = w.wallet_id()
|
|
24
|
-
assert len(wid) == 36, f"wallet_id should be UUID, got {wid}"
|
|
25
|
-
sig = w.sign_message(b"hello clawpowers")
|
|
26
|
-
assert len(sig) > 0, "signature should not be empty"
|
|
27
|
-
passed += 1
|
|
28
|
-
print(f" ✅ wallet: address={addr[:10]}…")
|
|
29
|
-
|
|
30
|
-
# ── 2. Wallet from private key ─────────────────────────────────────────
|
|
31
|
-
total += 1
|
|
32
|
-
w2 = cc.AgentWallet.from_private_key(
|
|
33
|
-
"0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
|
|
34
|
-
)
|
|
35
|
-
assert w2.address() == "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266"
|
|
36
|
-
passed += 1
|
|
37
|
-
print(f" ✅ wallet from_private_key: {w2.address()[:10]}…")
|
|
38
|
-
|
|
39
|
-
# ── 3. Tokens ──────────────────────────────────────────────────────────
|
|
40
|
-
total += 1
|
|
41
|
-
t = cc.TokenAmount.from_human(123.456, 6)
|
|
42
|
-
assert abs(t.to_human() - 123.456) < 0.001
|
|
43
|
-
assert not t.is_zero()
|
|
44
|
-
j = t.to_json()
|
|
45
|
-
assert "raw" in j
|
|
46
|
-
passed += 1
|
|
47
|
-
print(f" ✅ tokens: {t}")
|
|
48
|
-
|
|
49
|
-
# ── 4. Token registry ──────────────────────────────────────────────────
|
|
50
|
-
total += 1
|
|
51
|
-
reg = json.loads(cc.default_token_registry())
|
|
52
|
-
symbols = {t["symbol"] for t in reg}
|
|
53
|
-
assert "USDC" in symbols
|
|
54
|
-
assert "ETH" in symbols
|
|
55
|
-
passed += 1
|
|
56
|
-
print(f" ✅ token registry: {len(reg)} tokens")
|
|
57
|
-
|
|
58
|
-
# ── 5. Fee ─────────────────────────────────────────────────────────────
|
|
59
|
-
total += 1
|
|
60
|
-
fs = cc.FeeSchedule.with_defaults()
|
|
61
|
-
calc = json.loads(fs.calculate(1000.0, 6, "transaction"))
|
|
62
|
-
assert abs(calc["fee"] - 7.7) < 0.001, f"fee should be 7.7, got {calc['fee']}"
|
|
63
|
-
assert abs(calc["net"] - 992.3) < 0.001
|
|
64
|
-
passed += 1
|
|
65
|
-
print(f" ✅ fee: gross={calc['gross']} fee={calc['fee']} net={calc['net']}")
|
|
66
|
-
|
|
67
|
-
# ── 6. X402 ────────────────────────────────────────────────────────────
|
|
68
|
-
total += 1
|
|
69
|
-
x = cc.X402Client()
|
|
70
|
-
payment_json = json.dumps({
|
|
71
|
-
"payment_url": "https://pay.example.com/pay",
|
|
72
|
-
"amount": "1.00",
|
|
73
|
-
"token": "USDC",
|
|
74
|
-
"chain_id": 8453,
|
|
75
|
-
"recipient": "0xrecipient",
|
|
76
|
-
"memo": None,
|
|
77
|
-
})
|
|
78
|
-
header = x.create_payment_header(payment_json, "0xsig")
|
|
79
|
-
assert "0xrecipient" in header
|
|
80
|
-
assert "0xsig" in header
|
|
81
|
-
passed += 1
|
|
82
|
-
print(f" ✅ x402: header={header[:40]}…")
|
|
83
|
-
|
|
84
|
-
# ── 7. Canonical store ─────────────────────────────────────────────────
|
|
85
|
-
total += 1
|
|
86
|
-
store = cc.CanonicalStore.in_memory()
|
|
87
|
-
record = json.dumps({
|
|
88
|
-
"id": "00000000-0000-0000-0000-000000000001",
|
|
89
|
-
"namespace": "test",
|
|
90
|
-
"content": "hello world",
|
|
91
|
-
"content_hash": cc.compute_sha256("hello world"),
|
|
92
|
-
"embedding": None,
|
|
93
|
-
"metadata": {},
|
|
94
|
-
"created_at": "2026-03-31T00:00:00Z",
|
|
95
|
-
"provenance": "smoke-test",
|
|
96
|
-
})
|
|
97
|
-
rid = store.insert(record)
|
|
98
|
-
assert len(rid) == 36, f"insert should return UUID, got {rid}"
|
|
99
|
-
fetched = store.get(rid)
|
|
100
|
-
assert fetched is not None
|
|
101
|
-
assert json.loads(fetched)["content"] == "hello world"
|
|
102
|
-
assert store.verify_integrity(rid) is True
|
|
103
|
-
passed += 1
|
|
104
|
-
print(f" ✅ canonical: inserted and verified id={rid[:8]}…")
|
|
105
|
-
|
|
106
|
-
# ── 8. Compression ─────────────────────────────────────────────────────
|
|
107
|
-
total += 1
|
|
108
|
-
comp = cc.TurboCompressor(64, 8)
|
|
109
|
-
vec = [float(i) / 64.0 for i in range(64)]
|
|
110
|
-
compressed = comp.compress(vec)
|
|
111
|
-
cdata = json.loads(compressed)
|
|
112
|
-
assert len(cdata["quantized"]) == 64
|
|
113
|
-
decompressed = comp.decompress(compressed)
|
|
114
|
-
assert len(decompressed) == 64
|
|
115
|
-
# Check roundtrip fidelity
|
|
116
|
-
err = sum((a - b) ** 2 for a, b in zip(vec, decompressed)) ** 0.5
|
|
117
|
-
assert err < 1.0, f"roundtrip error too high: {err}"
|
|
118
|
-
passed += 1
|
|
119
|
-
print(f" ✅ compression: {len(vec)} dims → {len(cdata['quantized'])} quantized, err={err:.4f}")
|
|
120
|
-
|
|
121
|
-
# ── 9. Security (WriteFirewall) ────────────────────────────────────────
|
|
122
|
-
total += 1
|
|
123
|
-
fw = cc.WriteFirewall('{"allowed_namespaces": ["agents", "test"]}')
|
|
124
|
-
decision = json.loads(fw.evaluate(json.dumps({
|
|
125
|
-
"namespace": "agents",
|
|
126
|
-
"content": "normal content",
|
|
127
|
-
"trust_level": "Agent",
|
|
128
|
-
"source": "test-agent",
|
|
129
|
-
})))
|
|
130
|
-
assert decision == "Allow", f"expected Allow, got {decision}"
|
|
131
|
-
# Test deny for unlisted namespace
|
|
132
|
-
deny = json.loads(fw.evaluate(json.dumps({
|
|
133
|
-
"namespace": "forbidden",
|
|
134
|
-
"content": "bad",
|
|
135
|
-
"trust_level": "Agent",
|
|
136
|
-
"source": "test",
|
|
137
|
-
})))
|
|
138
|
-
assert "Deny" in str(deny), f"expected Deny, got {deny}"
|
|
139
|
-
passed += 1
|
|
140
|
-
print(f" ✅ security: allow={decision}, deny works")
|
|
141
|
-
|
|
142
|
-
# ── 10. Policy ─────────────────────────────────────────────────────────
|
|
143
|
-
total += 1
|
|
144
|
-
result = cc.evaluate_spending_policy(
|
|
145
|
-
100.0, 6, True, 50.0,
|
|
146
|
-
"0x0000000000000000000000000000000000000000"
|
|
147
|
-
)
|
|
148
|
-
assert result == "approve", f"expected approve, got {result}"
|
|
149
|
-
# Test deny
|
|
150
|
-
result2 = cc.evaluate_spending_policy(
|
|
151
|
-
100.0, 6, True, 200.0,
|
|
152
|
-
"0x0000000000000000000000000000000000000000"
|
|
153
|
-
)
|
|
154
|
-
assert result2.startswith("deny"), f"expected deny, got {result2}"
|
|
155
|
-
passed += 1
|
|
156
|
-
print(f" ✅ policy: approve ok, deny ok")
|
|
157
|
-
|
|
158
|
-
# ── 11. Utility functions ──────────────────────────────────────────────
|
|
159
|
-
total += 1
|
|
160
|
-
h = cc.compute_sha256("test")
|
|
161
|
-
assert len(h) == 64, f"sha256 should be 64 hex chars, got {len(h)}"
|
|
162
|
-
sim = cc.cosine_similarity([1.0, 0.0], [1.0, 0.0])
|
|
163
|
-
assert abs(sim - 1.0) < 0.001
|
|
164
|
-
dist = cc.l2_distance([0.0, 0.0], [3.0, 4.0])
|
|
165
|
-
assert abs(dist - 5.0) < 0.001
|
|
166
|
-
passed += 1
|
|
167
|
-
print(f" ✅ utilities: sha256, cosine_similarity, l2_distance")
|
|
168
|
-
|
|
169
|
-
print(f"\n{'='*60}")
|
|
170
|
-
print(f" SMOKE TEST: {passed}/{total} passed")
|
|
171
|
-
print(f" Crates exercised: wallet, tokens, fee, x402, canonical,")
|
|
172
|
-
print(f" compression, security, policy (8 crates)")
|
|
173
|
-
print(f"{'='*60}")
|
|
174
|
-
|
|
175
|
-
if passed < total:
|
|
176
|
-
sys.exit(1)
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
if __name__ == "__main__":
|
|
180
|
-
main()
|
|
1
|
+
"""Smoke test for clawpowers_core PyO3 bindings.
|
|
2
|
+
|
|
3
|
+
Exercises at least one function from: wallet, tokens, fee, x402, canonical,
|
|
4
|
+
compression, security, and policy (8 crates).
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import json
|
|
8
|
+
import sys
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def main():
|
|
12
|
+
import clawpowers_core as cc
|
|
13
|
+
|
|
14
|
+
passed = 0
|
|
15
|
+
total = 0
|
|
16
|
+
|
|
17
|
+
# ── 1. Wallet ──────────────────────────────────────────────────────────
|
|
18
|
+
total += 1
|
|
19
|
+
w = cc.AgentWallet.generate()
|
|
20
|
+
addr = w.address()
|
|
21
|
+
assert addr.startswith("0x"), f"address should start with 0x, got {addr}"
|
|
22
|
+
assert len(addr) == 42, f"address should be 42 chars, got {len(addr)}"
|
|
23
|
+
wid = w.wallet_id()
|
|
24
|
+
assert len(wid) == 36, f"wallet_id should be UUID, got {wid}"
|
|
25
|
+
sig = w.sign_message(b"hello clawpowers")
|
|
26
|
+
assert len(sig) > 0, "signature should not be empty"
|
|
27
|
+
passed += 1
|
|
28
|
+
print(f" ✅ wallet: address={addr[:10]}…")
|
|
29
|
+
|
|
30
|
+
# ── 2. Wallet from private key ─────────────────────────────────────────
|
|
31
|
+
total += 1
|
|
32
|
+
w2 = cc.AgentWallet.from_private_key(
|
|
33
|
+
"0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
|
|
34
|
+
)
|
|
35
|
+
assert w2.address() == "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266"
|
|
36
|
+
passed += 1
|
|
37
|
+
print(f" ✅ wallet from_private_key: {w2.address()[:10]}…")
|
|
38
|
+
|
|
39
|
+
# ── 3. Tokens ──────────────────────────────────────────────────────────
|
|
40
|
+
total += 1
|
|
41
|
+
t = cc.TokenAmount.from_human(123.456, 6)
|
|
42
|
+
assert abs(t.to_human() - 123.456) < 0.001
|
|
43
|
+
assert not t.is_zero()
|
|
44
|
+
j = t.to_json()
|
|
45
|
+
assert "raw" in j
|
|
46
|
+
passed += 1
|
|
47
|
+
print(f" ✅ tokens: {t}")
|
|
48
|
+
|
|
49
|
+
# ── 4. Token registry ──────────────────────────────────────────────────
|
|
50
|
+
total += 1
|
|
51
|
+
reg = json.loads(cc.default_token_registry())
|
|
52
|
+
symbols = {t["symbol"] for t in reg}
|
|
53
|
+
assert "USDC" in symbols
|
|
54
|
+
assert "ETH" in symbols
|
|
55
|
+
passed += 1
|
|
56
|
+
print(f" ✅ token registry: {len(reg)} tokens")
|
|
57
|
+
|
|
58
|
+
# ── 5. Fee ─────────────────────────────────────────────────────────────
|
|
59
|
+
total += 1
|
|
60
|
+
fs = cc.FeeSchedule.with_defaults()
|
|
61
|
+
calc = json.loads(fs.calculate(1000.0, 6, "transaction"))
|
|
62
|
+
assert abs(calc["fee"] - 7.7) < 0.001, f"fee should be 7.7, got {calc['fee']}"
|
|
63
|
+
assert abs(calc["net"] - 992.3) < 0.001
|
|
64
|
+
passed += 1
|
|
65
|
+
print(f" ✅ fee: gross={calc['gross']} fee={calc['fee']} net={calc['net']}")
|
|
66
|
+
|
|
67
|
+
# ── 6. X402 ────────────────────────────────────────────────────────────
|
|
68
|
+
total += 1
|
|
69
|
+
x = cc.X402Client()
|
|
70
|
+
payment_json = json.dumps({
|
|
71
|
+
"payment_url": "https://pay.example.com/pay",
|
|
72
|
+
"amount": "1.00",
|
|
73
|
+
"token": "USDC",
|
|
74
|
+
"chain_id": 8453,
|
|
75
|
+
"recipient": "0xrecipient",
|
|
76
|
+
"memo": None,
|
|
77
|
+
})
|
|
78
|
+
header = x.create_payment_header(payment_json, "0xsig")
|
|
79
|
+
assert "0xrecipient" in header
|
|
80
|
+
assert "0xsig" in header
|
|
81
|
+
passed += 1
|
|
82
|
+
print(f" ✅ x402: header={header[:40]}…")
|
|
83
|
+
|
|
84
|
+
# ── 7. Canonical store ─────────────────────────────────────────────────
|
|
85
|
+
total += 1
|
|
86
|
+
store = cc.CanonicalStore.in_memory()
|
|
87
|
+
record = json.dumps({
|
|
88
|
+
"id": "00000000-0000-0000-0000-000000000001",
|
|
89
|
+
"namespace": "test",
|
|
90
|
+
"content": "hello world",
|
|
91
|
+
"content_hash": cc.compute_sha256("hello world"),
|
|
92
|
+
"embedding": None,
|
|
93
|
+
"metadata": {},
|
|
94
|
+
"created_at": "2026-03-31T00:00:00Z",
|
|
95
|
+
"provenance": "smoke-test",
|
|
96
|
+
})
|
|
97
|
+
rid = store.insert(record)
|
|
98
|
+
assert len(rid) == 36, f"insert should return UUID, got {rid}"
|
|
99
|
+
fetched = store.get(rid)
|
|
100
|
+
assert fetched is not None
|
|
101
|
+
assert json.loads(fetched)["content"] == "hello world"
|
|
102
|
+
assert store.verify_integrity(rid) is True
|
|
103
|
+
passed += 1
|
|
104
|
+
print(f" ✅ canonical: inserted and verified id={rid[:8]}…")
|
|
105
|
+
|
|
106
|
+
# ── 8. Compression ─────────────────────────────────────────────────────
|
|
107
|
+
total += 1
|
|
108
|
+
comp = cc.TurboCompressor(64, 8)
|
|
109
|
+
vec = [float(i) / 64.0 for i in range(64)]
|
|
110
|
+
compressed = comp.compress(vec)
|
|
111
|
+
cdata = json.loads(compressed)
|
|
112
|
+
assert len(cdata["quantized"]) == 64
|
|
113
|
+
decompressed = comp.decompress(compressed)
|
|
114
|
+
assert len(decompressed) == 64
|
|
115
|
+
# Check roundtrip fidelity
|
|
116
|
+
err = sum((a - b) ** 2 for a, b in zip(vec, decompressed)) ** 0.5
|
|
117
|
+
assert err < 1.0, f"roundtrip error too high: {err}"
|
|
118
|
+
passed += 1
|
|
119
|
+
print(f" ✅ compression: {len(vec)} dims → {len(cdata['quantized'])} quantized, err={err:.4f}")
|
|
120
|
+
|
|
121
|
+
# ── 9. Security (WriteFirewall) ────────────────────────────────────────
|
|
122
|
+
total += 1
|
|
123
|
+
fw = cc.WriteFirewall('{"allowed_namespaces": ["agents", "test"]}')
|
|
124
|
+
decision = json.loads(fw.evaluate(json.dumps({
|
|
125
|
+
"namespace": "agents",
|
|
126
|
+
"content": "normal content",
|
|
127
|
+
"trust_level": "Agent",
|
|
128
|
+
"source": "test-agent",
|
|
129
|
+
})))
|
|
130
|
+
assert decision == "Allow", f"expected Allow, got {decision}"
|
|
131
|
+
# Test deny for unlisted namespace
|
|
132
|
+
deny = json.loads(fw.evaluate(json.dumps({
|
|
133
|
+
"namespace": "forbidden",
|
|
134
|
+
"content": "bad",
|
|
135
|
+
"trust_level": "Agent",
|
|
136
|
+
"source": "test",
|
|
137
|
+
})))
|
|
138
|
+
assert "Deny" in str(deny), f"expected Deny, got {deny}"
|
|
139
|
+
passed += 1
|
|
140
|
+
print(f" ✅ security: allow={decision}, deny works")
|
|
141
|
+
|
|
142
|
+
# ── 10. Policy ─────────────────────────────────────────────────────────
|
|
143
|
+
total += 1
|
|
144
|
+
result = cc.evaluate_spending_policy(
|
|
145
|
+
100.0, 6, True, 50.0,
|
|
146
|
+
"0x0000000000000000000000000000000000000000"
|
|
147
|
+
)
|
|
148
|
+
assert result == "approve", f"expected approve, got {result}"
|
|
149
|
+
# Test deny
|
|
150
|
+
result2 = cc.evaluate_spending_policy(
|
|
151
|
+
100.0, 6, True, 200.0,
|
|
152
|
+
"0x0000000000000000000000000000000000000000"
|
|
153
|
+
)
|
|
154
|
+
assert result2.startswith("deny"), f"expected deny, got {result2}"
|
|
155
|
+
passed += 1
|
|
156
|
+
print(f" ✅ policy: approve ok, deny ok")
|
|
157
|
+
|
|
158
|
+
# ── 11. Utility functions ──────────────────────────────────────────────
|
|
159
|
+
total += 1
|
|
160
|
+
h = cc.compute_sha256("test")
|
|
161
|
+
assert len(h) == 64, f"sha256 should be 64 hex chars, got {len(h)}"
|
|
162
|
+
sim = cc.cosine_similarity([1.0, 0.0], [1.0, 0.0])
|
|
163
|
+
assert abs(sim - 1.0) < 0.001
|
|
164
|
+
dist = cc.l2_distance([0.0, 0.0], [3.0, 4.0])
|
|
165
|
+
assert abs(dist - 5.0) < 0.001
|
|
166
|
+
passed += 1
|
|
167
|
+
print(f" ✅ utilities: sha256, cosine_similarity, l2_distance")
|
|
168
|
+
|
|
169
|
+
print(f"\n{'='*60}")
|
|
170
|
+
print(f" SMOKE TEST: {passed}/{total} passed")
|
|
171
|
+
print(f" Crates exercised: wallet, tokens, fee, x402, canonical,")
|
|
172
|
+
print(f" compression, security, policy (8 crates)")
|
|
173
|
+
print(f"{'='*60}")
|
|
174
|
+
|
|
175
|
+
if passed < total:
|
|
176
|
+
sys.exit(1)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
if __name__ == "__main__":
|
|
180
|
+
main()
|
package/native/wasm/Cargo.toml
CHANGED
|
@@ -1,44 +1,47 @@
|
|
|
1
|
-
[package]
|
|
2
|
-
name = "clawpowers-wasm"
|
|
3
|
-
version.workspace = true
|
|
4
|
-
edition.workspace = true
|
|
5
|
-
license.workspace = true
|
|
6
|
-
description = "WASM bindings for ClawPowers core — tokens, fees, policy, compression, index, canonical, verification, security"
|
|
7
|
-
|
|
8
|
-
[lib]
|
|
9
|
-
crate-type = ["cdylib", "rlib"]
|
|
10
|
-
|
|
11
|
-
[dependencies]
|
|
12
|
-
wasm-bindgen = { workspace = true }
|
|
13
|
-
serde = { workspace = true }
|
|
14
|
-
serde_json = { workspace = true }
|
|
15
|
-
serde-wasm-bindgen = "0.6"
|
|
16
|
-
|
|
17
|
-
# Crates that compile cleanly to WASM
|
|
18
|
-
clawpowers-tokens = { path = "../crates/tokens" }
|
|
19
|
-
clawpowers-fee = { path = "../crates/fee" }
|
|
20
|
-
clawpowers-policy = { path = "../crates/policy" }
|
|
21
|
-
clawpowers-compression = { path = "../crates/compression" }
|
|
22
|
-
clawpowers-index = { path = "../crates/index" }
|
|
23
|
-
|
|
24
|
-
# Crates that need WASM feature flag
|
|
25
|
-
clawpowers-canonical = { path = "../crates/canonical", default-features = false, features = ["wasm"] }
|
|
26
|
-
clawpowers-verification = { path = "../crates/verification", default-features = false, features = ["wasm"] }
|
|
27
|
-
clawpowers-security = { path = "../crates/security", default-features = false, features = ["wasm"] }
|
|
28
|
-
|
|
29
|
-
# alloy-primitives needed for Address type
|
|
30
|
-
alloy-primitives = { workspace = true }
|
|
31
|
-
k256 = { version = "0.13", features = ["ecdsa", "sha2"] }
|
|
32
|
-
clawpowers-evm-eth = { path = "../crates/evm-eth" }
|
|
33
|
-
uuid = { version = "1", features = ["v4", "serde", "js"] }
|
|
34
|
-
chrono = { workspace = true }
|
|
35
|
-
|
|
36
|
-
# WASM-compatible random number generation
|
|
37
|
-
getrandom = { version = "0.3", features = ["wasm_js"] }
|
|
38
|
-
|
|
39
|
-
# k256 → rand_core pulls getrandom 0.2; enable `js` for wasm32-unknown-unknown
|
|
40
|
-
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
|
41
|
-
getrandom = { version = "0.2", features = ["js"] }
|
|
42
|
-
|
|
43
|
-
[dev-dependencies]
|
|
44
|
-
wasm-bindgen-test = "0.3"
|
|
1
|
+
[package]
|
|
2
|
+
name = "clawpowers-wasm"
|
|
3
|
+
version.workspace = true
|
|
4
|
+
edition.workspace = true
|
|
5
|
+
license.workspace = true
|
|
6
|
+
description = "WASM bindings for ClawPowers core — tokens, fees, policy, compression, index, canonical, verification, security"
|
|
7
|
+
|
|
8
|
+
[lib]
|
|
9
|
+
crate-type = ["cdylib", "rlib"]
|
|
10
|
+
|
|
11
|
+
[dependencies]
|
|
12
|
+
wasm-bindgen = { workspace = true }
|
|
13
|
+
serde = { workspace = true }
|
|
14
|
+
serde_json = { workspace = true }
|
|
15
|
+
serde-wasm-bindgen = "0.6"
|
|
16
|
+
|
|
17
|
+
# Crates that compile cleanly to WASM
|
|
18
|
+
clawpowers-tokens = { path = "../crates/tokens" }
|
|
19
|
+
clawpowers-fee = { path = "../crates/fee" }
|
|
20
|
+
clawpowers-policy = { path = "../crates/policy" }
|
|
21
|
+
clawpowers-compression = { path = "../crates/compression" }
|
|
22
|
+
clawpowers-index = { path = "../crates/index" }
|
|
23
|
+
|
|
24
|
+
# Crates that need WASM feature flag
|
|
25
|
+
clawpowers-canonical = { path = "../crates/canonical", default-features = false, features = ["wasm"] }
|
|
26
|
+
clawpowers-verification = { path = "../crates/verification", default-features = false, features = ["wasm"] }
|
|
27
|
+
clawpowers-security = { path = "../crates/security", default-features = false, features = ["wasm"] }
|
|
28
|
+
|
|
29
|
+
# alloy-primitives needed for Address type
|
|
30
|
+
alloy-primitives = { workspace = true }
|
|
31
|
+
k256 = { version = "0.13", features = ["ecdsa", "sha2"] }
|
|
32
|
+
clawpowers-evm-eth = { path = "../crates/evm-eth" }
|
|
33
|
+
uuid = { version = "1", features = ["v4", "serde", "js"] }
|
|
34
|
+
chrono = { workspace = true }
|
|
35
|
+
|
|
36
|
+
# WASM-compatible random number generation
|
|
37
|
+
getrandom = { version = "0.3", features = ["wasm_js"] }
|
|
38
|
+
|
|
39
|
+
# k256 → rand_core pulls getrandom 0.2; enable `js` for wasm32-unknown-unknown
|
|
40
|
+
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
|
41
|
+
getrandom = { version = "0.2", features = ["js"] }
|
|
42
|
+
|
|
43
|
+
[dev-dependencies]
|
|
44
|
+
wasm-bindgen-test = "0.3"
|
|
45
|
+
|
|
46
|
+
[package.metadata.wasm-pack.profile.release]
|
|
47
|
+
wasm-opt = false
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
*
|
|
2
|
-
!.gitignore
|
|
3
|
-
!*.js
|
|
4
|
-
!*.d.ts
|
|
5
|
-
!*.wasm
|
|
6
|
-
!package.json
|
|
1
|
+
*
|
|
2
|
+
!.gitignore
|
|
3
|
+
!*.js
|
|
4
|
+
!*.d.ts
|
|
5
|
+
!*.wasm
|
|
6
|
+
!package.json
|