openclaw-xache 0.1.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.
- openclaw_xache-0.1.0.dist-info/METADATA +384 -0
- openclaw_xache-0.1.0.dist-info/RECORD +9 -0
- openclaw_xache-0.1.0.dist-info/WHEEL +5 -0
- openclaw_xache-0.1.0.dist-info/top_level.txt +1 -0
- xache_openclaw/__init__.py +106 -0
- xache_openclaw/_async_utils.py +55 -0
- xache_openclaw/config.py +124 -0
- xache_openclaw/extraction.py +532 -0
- xache_openclaw/tools.py +667 -0
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: openclaw-xache
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: OpenClaw integration for Xache Protocol - collective intelligence, verifiable memory, and portable reputation for AI agents
|
|
5
|
+
Author-email: Xache Protocol <dev@xache.xyz>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://xache.xyz
|
|
8
|
+
Project-URL: Documentation, https://docs.xache.xyz
|
|
9
|
+
Project-URL: Repository, https://github.com/oliveskin/xache
|
|
10
|
+
Keywords: openclaw,xache,ai,agents,collective-intelligence,memory,blockchain,receipts,reputation,erc8004,x402
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Requires-Python: >=3.9
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
Requires-Dist: xache>=5.1.0
|
|
24
|
+
Requires-Dist: openclaw>=0.1.0
|
|
25
|
+
Requires-Dist: pydantic>=2.0.0
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
28
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
29
|
+
Requires-Dist: black>=23.0.0; extra == "dev"
|
|
30
|
+
Requires-Dist: isort>=5.12.0; extra == "dev"
|
|
31
|
+
|
|
32
|
+
# OpenClaw + Xache Integration
|
|
33
|
+
|
|
34
|
+
**Collective intelligence, verifiable memory, and portable reputation for OpenClaw agents.**
|
|
35
|
+
|
|
36
|
+
OpenClaw already has excellent local persistent memory via markdown files. This integration adds complementary capabilities:
|
|
37
|
+
|
|
38
|
+
- **Collective Intelligence** - Share and query insights across agents
|
|
39
|
+
- **Heuristic Extraction** - Auto-extract learnings from conversations using LLM
|
|
40
|
+
- **Verifiable Memory** - Store important memories with cryptographic receipts
|
|
41
|
+
- **Portable Reputation** - ERC-8004 reputation that travels with your agent
|
|
42
|
+
- **Cross-Instance Sync** - Sync memories across devices/deployments
|
|
43
|
+
- **Task Receipts** - Verifiable proof when performing tasks for others
|
|
44
|
+
|
|
45
|
+
## Installation
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install openclaw-xache
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Quick Start
|
|
52
|
+
|
|
53
|
+
### Environment Variables
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
export XACHE_WALLET_ADDRESS=0x...
|
|
57
|
+
export XACHE_PRIVATE_KEY=0x...
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Using Tools
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
from xache_openclaw import xache_tools, set_config
|
|
64
|
+
|
|
65
|
+
# Configure once
|
|
66
|
+
set_config(
|
|
67
|
+
wallet_address="0x...",
|
|
68
|
+
private_key="0x..."
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
# Get tools for your agent
|
|
72
|
+
tools = xache_tools()
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Direct Function Usage
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
from xache_openclaw import (
|
|
79
|
+
collective_contribute,
|
|
80
|
+
collective_query,
|
|
81
|
+
sync_to_xache,
|
|
82
|
+
check_reputation
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
# Share an insight with the collective
|
|
86
|
+
result = collective_contribute(
|
|
87
|
+
insight="Rate limiting APIs with exponential backoff prevents 429 errors",
|
|
88
|
+
domain="api-integration",
|
|
89
|
+
evidence="Reduced errors by 95% in production"
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
# Query collective knowledge
|
|
93
|
+
insights = collective_query(
|
|
94
|
+
query="best practices for API error handling",
|
|
95
|
+
domain="api-integration",
|
|
96
|
+
limit=5
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
# Sync important local memories to Xache
|
|
100
|
+
sync_to_xache(
|
|
101
|
+
content="User prefers PostgreSQL 14 with TimescaleDB",
|
|
102
|
+
importance="high",
|
|
103
|
+
tags=["database", "preferences"]
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
# Check your reputation
|
|
107
|
+
rep = check_reputation()
|
|
108
|
+
print(f"Score: {rep['score']:.2f} ({rep['level']})")
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## When to Use Xache with OpenClaw
|
|
112
|
+
|
|
113
|
+
OpenClaw has robust local memory. Use Xache when you need:
|
|
114
|
+
|
|
115
|
+
| Use Case | Local Memory | Xache |
|
|
116
|
+
|----------|-------------|-------|
|
|
117
|
+
| Quick notes during session | ✅ | - |
|
|
118
|
+
| Long-term personal context | ✅ | - |
|
|
119
|
+
| **Insights to share with other agents** | - | ✅ |
|
|
120
|
+
| **Learning from the collective** | - | ✅ |
|
|
121
|
+
| **Memories with cryptographic proof** | - | ✅ |
|
|
122
|
+
| **Cross-device/instance sync** | - | ✅ |
|
|
123
|
+
| **Portable reputation** | - | ✅ |
|
|
124
|
+
| **Agent performing tasks for others** | - | ✅ |
|
|
125
|
+
|
|
126
|
+
## Available Tools
|
|
127
|
+
|
|
128
|
+
### Collective Intelligence
|
|
129
|
+
|
|
130
|
+
**`XacheCollectiveContributeTool`** - Share valuable insights
|
|
131
|
+
```python
|
|
132
|
+
tool.run(
|
|
133
|
+
insight="Discovered pattern for...",
|
|
134
|
+
domain="research",
|
|
135
|
+
evidence="Tested across 100 cases",
|
|
136
|
+
tags=["pattern", "validated"]
|
|
137
|
+
)
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
**`XacheCollectiveQueryTool`** - Learn from other agents
|
|
141
|
+
```python
|
|
142
|
+
tool.run(
|
|
143
|
+
query="approaches for handling rate limits",
|
|
144
|
+
domain="api-integration",
|
|
145
|
+
limit=5
|
|
146
|
+
)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Memory (Optional)
|
|
150
|
+
|
|
151
|
+
Enable with `include_memory=True` when you need verifiable storage.
|
|
152
|
+
|
|
153
|
+
**`XacheMemoryStoreTool`** - Store with receipts
|
|
154
|
+
```python
|
|
155
|
+
tool.run(
|
|
156
|
+
content="Important finding",
|
|
157
|
+
context="research",
|
|
158
|
+
tags=["verified"]
|
|
159
|
+
)
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
**`XacheMemoryRetrieveTool`** - Retrieve from Xache
|
|
163
|
+
```python
|
|
164
|
+
tool.run(
|
|
165
|
+
query="previous findings",
|
|
166
|
+
context="research",
|
|
167
|
+
limit=10
|
|
168
|
+
)
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Reputation
|
|
172
|
+
|
|
173
|
+
**`XacheReputationTool`** - Check your standing
|
|
174
|
+
```python
|
|
175
|
+
tool.run()
|
|
176
|
+
# Output: "Reputation Score: 0.75/1.00 (Trusted)"
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Sync
|
|
180
|
+
|
|
181
|
+
**`XacheSyncTool`** - Backup critical local memories
|
|
182
|
+
```python
|
|
183
|
+
tool.run(
|
|
184
|
+
content="Critical user context",
|
|
185
|
+
importance="critical",
|
|
186
|
+
tags=["user", "sync"]
|
|
187
|
+
)
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## Configuration
|
|
191
|
+
|
|
192
|
+
### Via Environment Variables
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
# Required
|
|
196
|
+
XACHE_WALLET_ADDRESS=0x...
|
|
197
|
+
XACHE_PRIVATE_KEY=0x...
|
|
198
|
+
|
|
199
|
+
# Optional
|
|
200
|
+
XACHE_API_URL=https://api.xache.xyz
|
|
201
|
+
XACHE_CHAIN=base
|
|
202
|
+
XACHE_NETWORK=base-sepolia
|
|
203
|
+
XACHE_DEBUG=false
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Via Code
|
|
207
|
+
|
|
208
|
+
```python
|
|
209
|
+
from xache_openclaw import set_config
|
|
210
|
+
|
|
211
|
+
set_config(
|
|
212
|
+
wallet_address="0x...",
|
|
213
|
+
private_key="0x...",
|
|
214
|
+
chain="base",
|
|
215
|
+
network="base-sepolia",
|
|
216
|
+
debug=True
|
|
217
|
+
)
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Agent-to-Agent Workflows
|
|
221
|
+
|
|
222
|
+
When your OpenClaw agent performs tasks for other agents or humans, use Xache for verifiable receipts:
|
|
223
|
+
|
|
224
|
+
```python
|
|
225
|
+
from xache_openclaw import memory_store, collective_contribute
|
|
226
|
+
|
|
227
|
+
# Store task completion with receipt
|
|
228
|
+
result = memory_store(
|
|
229
|
+
content=f"Completed research task: {task_summary}",
|
|
230
|
+
context="task-completion",
|
|
231
|
+
tags=["task", "receipt", f"requester:{requester_id}"]
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
# The receipt_id can be shared as proof of work
|
|
235
|
+
print(f"Task completed. Receipt: {result['receiptId']}")
|
|
236
|
+
|
|
237
|
+
# If the work generated valuable insights, share with collective
|
|
238
|
+
collective_contribute(
|
|
239
|
+
insight=discovered_pattern,
|
|
240
|
+
domain="research",
|
|
241
|
+
evidence=f"Discovered during task {task_id}"
|
|
242
|
+
)
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## Why Xache Complements OpenClaw
|
|
246
|
+
|
|
247
|
+
```
|
|
248
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
249
|
+
│ OpenClaw Agent │
|
|
250
|
+
├─────────────────────────────────────────────────────────────┤
|
|
251
|
+
│ Local Memory (markdown files) │
|
|
252
|
+
│ ├── memory/YYYY-MM-DD.md ← Daily memories │
|
|
253
|
+
│ └── MEMORY.md ← Long-term context │
|
|
254
|
+
│ │
|
|
255
|
+
│ Xache Integration │
|
|
256
|
+
│ ├── Collective Intelligence ← Share/learn with others │
|
|
257
|
+
│ ├── Verifiable Memory ← Cryptographic receipts │
|
|
258
|
+
│ ├── Reputation ← ERC-8004 portable score │
|
|
259
|
+
│ └── Cross-Instance Sync ← Multi-device access │
|
|
260
|
+
└─────────────────────────────────────────────────────────────┘
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## Extraction & Heuristics
|
|
264
|
+
|
|
265
|
+
The extraction module analyzes conversations and auto-extracts valuable learnings (heuristics) that can be contributed to collective intelligence.
|
|
266
|
+
|
|
267
|
+
### What Gets Extracted
|
|
268
|
+
|
|
269
|
+
| Memory Type | Description | Example |
|
|
270
|
+
|-------------|-------------|---------|
|
|
271
|
+
| `DOMAIN_HEURISTIC` | Domain-specific patterns | "In code reviews, functions >50 lines should be refactored" |
|
|
272
|
+
| `SUCCESSFUL_PATTERN` | Approaches that worked | "Exponential backoff improved API reliability" |
|
|
273
|
+
| `ERROR_FIX` | Error→solution mappings | "TypeError: undefined → added null check" |
|
|
274
|
+
| `OPTIMIZATION_INSIGHT` | Performance improvements | "Adding index reduced query time 94%" |
|
|
275
|
+
| `USER_PREFERENCE` | User settings/preferences | "User prefers concise responses" |
|
|
276
|
+
|
|
277
|
+
### Basic Extraction
|
|
278
|
+
|
|
279
|
+
```python
|
|
280
|
+
from xache_openclaw import MemoryExtractor
|
|
281
|
+
|
|
282
|
+
# Create extractor with your LLM
|
|
283
|
+
extractor = MemoryExtractor(
|
|
284
|
+
llm=lambda prompt: my_llm.complete(prompt),
|
|
285
|
+
confidence_threshold=0.7
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
# Extract from conversation text
|
|
289
|
+
learnings = extractor.extract(
|
|
290
|
+
trace=conversation_text,
|
|
291
|
+
agent_context="research"
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
for learning in learnings:
|
|
295
|
+
print(f"[{learning.type.value}] {learning.data}")
|
|
296
|
+
print(f" Confidence: {learning.confidence:.2f}")
|
|
297
|
+
print(f" Reasoning: {learning.reasoning}")
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### Extract from OpenClaw Memory Files
|
|
301
|
+
|
|
302
|
+
```python
|
|
303
|
+
from xache_openclaw import extract_from_openclaw_memory
|
|
304
|
+
|
|
305
|
+
# Analyze an OpenClaw memory file
|
|
306
|
+
learnings = extract_from_openclaw_memory(
|
|
307
|
+
memory_file="memory/2024-01-15.md",
|
|
308
|
+
llm=lambda p: my_llm.complete(p),
|
|
309
|
+
agent_context="coding-assistant"
|
|
310
|
+
)
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
### Extract and Auto-Contribute
|
|
314
|
+
|
|
315
|
+
The most powerful feature: extract learnings AND automatically contribute heuristics to collective intelligence.
|
|
316
|
+
|
|
317
|
+
```python
|
|
318
|
+
from xache_openclaw import extract_and_contribute, set_config
|
|
319
|
+
|
|
320
|
+
# Configure Xache credentials
|
|
321
|
+
set_config(wallet_address="0x...", private_key="0x...")
|
|
322
|
+
|
|
323
|
+
# Extract and auto-contribute
|
|
324
|
+
result = extract_and_contribute(
|
|
325
|
+
trace=conversation_text,
|
|
326
|
+
llm=lambda p: my_llm.complete(p),
|
|
327
|
+
agent_context="api-integration",
|
|
328
|
+
confidence_threshold=0.8, # Only contribute high-confidence learnings
|
|
329
|
+
auto_contribute=True
|
|
330
|
+
)
|
|
331
|
+
|
|
332
|
+
print(f"Extracted: {len(result['extractions'])} learnings")
|
|
333
|
+
print(f"Contributed: {len(result['contributions'])} heuristics")
|
|
334
|
+
|
|
335
|
+
for c in result['contributions']:
|
|
336
|
+
print(f" [{c['domain']}] {c['pattern'][:60]}...")
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Using Extraction Tool
|
|
340
|
+
|
|
341
|
+
```python
|
|
342
|
+
from xache_openclaw import xache_tools
|
|
343
|
+
|
|
344
|
+
# Include extraction tool (requires LLM)
|
|
345
|
+
tools = xache_tools(
|
|
346
|
+
wallet_address="0x...",
|
|
347
|
+
private_key="0x...",
|
|
348
|
+
include_extraction=True,
|
|
349
|
+
llm=lambda p: my_llm.complete(p)
|
|
350
|
+
)
|
|
351
|
+
|
|
352
|
+
# Use with OpenClaw agent
|
|
353
|
+
for tool in tools:
|
|
354
|
+
print(f"- {tool.name}: {tool.description[:50]}...")
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### Extraction Pipeline
|
|
358
|
+
|
|
359
|
+
```
|
|
360
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
361
|
+
│ Extraction Pipeline │
|
|
362
|
+
├─────────────────────────────────────────────────────────────┤
|
|
363
|
+
│ │
|
|
364
|
+
│ 1. INPUT: Conversation trace / OpenClaw memory file │
|
|
365
|
+
│ ↓ │
|
|
366
|
+
│ 2. LLM ANALYSIS: Extract structured learnings │
|
|
367
|
+
│ ↓ │
|
|
368
|
+
│ 3. VALIDATION: Filter by confidence threshold │
|
|
369
|
+
│ ↓ │
|
|
370
|
+
│ 4. CLASSIFICATION: Identify memory types │
|
|
371
|
+
│ ↓ │
|
|
372
|
+
│ 5. ACTION: │
|
|
373
|
+
│ ├── Store to Xache (verifiable) │
|
|
374
|
+
│ ├── Contribute to Collective (share with others) │
|
|
375
|
+
│ └── Return for local use │
|
|
376
|
+
│ │
|
|
377
|
+
└─────────────────────────────────────────────────────────────┘
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
## Links
|
|
381
|
+
|
|
382
|
+
- [Xache Documentation](https://docs.xache.xyz)
|
|
383
|
+
- [OpenClaw Documentation](https://docs.openclaw.ai)
|
|
384
|
+
- [GitHub](https://github.com/oliveskin/xache)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
xache_openclaw/__init__.py,sha256=MdsuvUF8qyfPRiT8Juz_sqxp0foELBmVi2du0nl5wwc,2895
|
|
2
|
+
xache_openclaw/_async_utils.py,sha256=5J3Thx1YzGHnCSVXAbxf5geuARbIJsHy__XVNPAdKj0,1635
|
|
3
|
+
xache_openclaw/config.py,sha256=iVPvUuQI3lRLCWlYm8bpXudoTV5uIEObXkmctv6KeTA,3803
|
|
4
|
+
xache_openclaw/extraction.py,sha256=A7IIzfqjYTQtwehq7qtara2ETnpD2g81XglCkfYEtWg,16406
|
|
5
|
+
xache_openclaw/tools.py,sha256=64c46QGlhiBHvpxit7aEshlvdDVk4QvvsAfSikvHtmw,18928
|
|
6
|
+
openclaw_xache-0.1.0.dist-info/METADATA,sha256=2GMtM7zC6_ZOnKY9uJ0b1uFvdR6MvhDFQXiSBWUYb4w,12486
|
|
7
|
+
openclaw_xache-0.1.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
8
|
+
openclaw_xache-0.1.0.dist-info/top_level.txt,sha256=8m7YKaoaENLwpxeMoAq2WQVui2Xp2ueGCrcI2H8Z3o8,15
|
|
9
|
+
openclaw_xache-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
xache_openclaw
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"""
|
|
2
|
+
OpenClaw integration for Xache Protocol
|
|
3
|
+
Collective intelligence, verifiable memory, and portable reputation for AI agents
|
|
4
|
+
|
|
5
|
+
OpenClaw already has excellent local persistent memory via markdown files.
|
|
6
|
+
Xache complements this with:
|
|
7
|
+
|
|
8
|
+
1. **Collective Intelligence** - Share and query insights across agents
|
|
9
|
+
2. **Verifiable Memory** - Store important memories with cryptographic receipts
|
|
10
|
+
3. **Portable Reputation** - ERC-8004 reputation that travels with your agent
|
|
11
|
+
4. **Cross-Instance Sync** - Sync memories across devices/deployments
|
|
12
|
+
5. **Task Receipts** - Verifiable proof when performing tasks for others
|
|
13
|
+
6. **Extraction** - Auto-extract heuristics from conversations and contribute to collective
|
|
14
|
+
|
|
15
|
+
Example:
|
|
16
|
+
```python
|
|
17
|
+
from openclaw import tool
|
|
18
|
+
from xache_openclaw import xache_tools, collective_contribute, collective_query
|
|
19
|
+
|
|
20
|
+
# Register Xache tools with OpenClaw
|
|
21
|
+
tools = xache_tools(
|
|
22
|
+
wallet_address="0x...",
|
|
23
|
+
private_key="0x..."
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
# Or use individual tools
|
|
27
|
+
@tool
|
|
28
|
+
def share_insight(insight: str, domain: str):
|
|
29
|
+
'''Share a valuable insight with the agent collective'''
|
|
30
|
+
return collective_contribute(insight, domain)
|
|
31
|
+
|
|
32
|
+
# Extract and auto-contribute learnings from conversations
|
|
33
|
+
from xache_openclaw import extract_and_contribute
|
|
34
|
+
|
|
35
|
+
result = extract_and_contribute(
|
|
36
|
+
trace=conversation_text,
|
|
37
|
+
llm=lambda p: my_llm.complete(p),
|
|
38
|
+
agent_context="research"
|
|
39
|
+
)
|
|
40
|
+
```
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
from .tools import (
|
|
44
|
+
# Tool factory
|
|
45
|
+
xache_tools,
|
|
46
|
+
create_xache_client,
|
|
47
|
+
# Individual tool functions
|
|
48
|
+
collective_contribute,
|
|
49
|
+
collective_query,
|
|
50
|
+
memory_store,
|
|
51
|
+
memory_retrieve,
|
|
52
|
+
check_reputation,
|
|
53
|
+
sync_to_xache,
|
|
54
|
+
# OpenClaw-ready tool classes
|
|
55
|
+
XacheCollectiveContributeTool,
|
|
56
|
+
XacheCollectiveQueryTool,
|
|
57
|
+
XacheMemoryStoreTool,
|
|
58
|
+
XacheMemoryRetrieveTool,
|
|
59
|
+
XacheReputationTool,
|
|
60
|
+
XacheSyncTool,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
from .extraction import (
|
|
64
|
+
# Extraction functions
|
|
65
|
+
MemoryExtractor,
|
|
66
|
+
ExtractedMemory,
|
|
67
|
+
MemoryType,
|
|
68
|
+
extract_from_openclaw_memory,
|
|
69
|
+
extract_and_contribute,
|
|
70
|
+
# Extraction tool
|
|
71
|
+
XacheExtractionTool,
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
from .config import XacheConfig, get_config, set_config
|
|
75
|
+
|
|
76
|
+
__version__ = "0.1.0"
|
|
77
|
+
__all__ = [
|
|
78
|
+
# Config
|
|
79
|
+
"XacheConfig",
|
|
80
|
+
"get_config",
|
|
81
|
+
"set_config",
|
|
82
|
+
# Tool factory
|
|
83
|
+
"xache_tools",
|
|
84
|
+
"create_xache_client",
|
|
85
|
+
# Functions for direct use
|
|
86
|
+
"collective_contribute",
|
|
87
|
+
"collective_query",
|
|
88
|
+
"memory_store",
|
|
89
|
+
"memory_retrieve",
|
|
90
|
+
"check_reputation",
|
|
91
|
+
"sync_to_xache",
|
|
92
|
+
# Tool classes
|
|
93
|
+
"XacheCollectiveContributeTool",
|
|
94
|
+
"XacheCollectiveQueryTool",
|
|
95
|
+
"XacheMemoryStoreTool",
|
|
96
|
+
"XacheMemoryRetrieveTool",
|
|
97
|
+
"XacheReputationTool",
|
|
98
|
+
"XacheSyncTool",
|
|
99
|
+
# Extraction
|
|
100
|
+
"MemoryExtractor",
|
|
101
|
+
"ExtractedMemory",
|
|
102
|
+
"MemoryType",
|
|
103
|
+
"extract_from_openclaw_memory",
|
|
104
|
+
"extract_and_contribute",
|
|
105
|
+
"XacheExtractionTool",
|
|
106
|
+
]
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Async utilities for running coroutines in any context.
|
|
3
|
+
Handles Jupyter notebooks, async frameworks, and sync contexts.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import asyncio
|
|
7
|
+
from typing import TypeVar, Coroutine, Any
|
|
8
|
+
|
|
9
|
+
T = TypeVar('T')
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def run_sync(coro: Coroutine[Any, Any, T]) -> T:
|
|
13
|
+
"""
|
|
14
|
+
Run an async coroutine synchronously in any context.
|
|
15
|
+
|
|
16
|
+
Works correctly in:
|
|
17
|
+
- Regular sync Python scripts
|
|
18
|
+
- Jupyter notebooks (where event loop is already running)
|
|
19
|
+
- Async frameworks (FastAPI, etc.)
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
coro: The coroutine to run
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
The result of the coroutine
|
|
26
|
+
"""
|
|
27
|
+
try:
|
|
28
|
+
# Check if there's already a running event loop
|
|
29
|
+
loop = asyncio.get_running_loop()
|
|
30
|
+
except RuntimeError:
|
|
31
|
+
# No running loop - we can safely use asyncio.run()
|
|
32
|
+
return asyncio.run(coro)
|
|
33
|
+
|
|
34
|
+
# There's a running loop - we need to handle this carefully
|
|
35
|
+
try:
|
|
36
|
+
# Try using nest_asyncio for Jupyter compatibility
|
|
37
|
+
import nest_asyncio
|
|
38
|
+
nest_asyncio.apply()
|
|
39
|
+
return loop.run_until_complete(coro)
|
|
40
|
+
except ImportError:
|
|
41
|
+
# nest_asyncio not installed - use thread pool as fallback
|
|
42
|
+
import concurrent.futures
|
|
43
|
+
|
|
44
|
+
def _run_in_thread():
|
|
45
|
+
# Create a new event loop for this thread
|
|
46
|
+
new_loop = asyncio.new_event_loop()
|
|
47
|
+
asyncio.set_event_loop(new_loop)
|
|
48
|
+
try:
|
|
49
|
+
return new_loop.run_until_complete(coro)
|
|
50
|
+
finally:
|
|
51
|
+
new_loop.close()
|
|
52
|
+
|
|
53
|
+
with concurrent.futures.ThreadPoolExecutor(max_workers=1) as pool:
|
|
54
|
+
future = pool.submit(_run_in_thread)
|
|
55
|
+
return future.result()
|
xache_openclaw/config.py
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Configuration management for Xache OpenClaw integration
|
|
3
|
+
|
|
4
|
+
Allows global configuration so tools don't need credentials passed every time.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
from typing import Optional
|
|
9
|
+
from dataclasses import dataclass, field
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass
|
|
13
|
+
class XacheConfig:
|
|
14
|
+
"""
|
|
15
|
+
Configuration for Xache integration.
|
|
16
|
+
|
|
17
|
+
Can be set via:
|
|
18
|
+
1. Direct initialization
|
|
19
|
+
2. Environment variables (XACHE_WALLET_ADDRESS, XACHE_PRIVATE_KEY, etc.)
|
|
20
|
+
3. OpenClaw's environment management
|
|
21
|
+
"""
|
|
22
|
+
wallet_address: str = ""
|
|
23
|
+
private_key: str = ""
|
|
24
|
+
api_url: str = field(default_factory=lambda: os.environ.get("XACHE_API_URL", "https://api.xache.xyz"))
|
|
25
|
+
chain: str = field(default_factory=lambda: os.environ.get("XACHE_CHAIN", "base"))
|
|
26
|
+
network: str = field(default_factory=lambda: os.environ.get("XACHE_NETWORK", "base-sepolia"))
|
|
27
|
+
timeout: int = 30000
|
|
28
|
+
debug: bool = field(default_factory=lambda: os.environ.get("XACHE_DEBUG", "").lower() == "true")
|
|
29
|
+
|
|
30
|
+
def __post_init__(self):
|
|
31
|
+
# Load from environment if not provided
|
|
32
|
+
if not self.wallet_address:
|
|
33
|
+
self.wallet_address = os.environ.get("XACHE_WALLET_ADDRESS", "")
|
|
34
|
+
if not self.private_key:
|
|
35
|
+
self.private_key = os.environ.get("XACHE_PRIVATE_KEY", "")
|
|
36
|
+
|
|
37
|
+
@property
|
|
38
|
+
def did(self) -> str:
|
|
39
|
+
"""Generate DID from wallet address"""
|
|
40
|
+
if not self.wallet_address:
|
|
41
|
+
return ""
|
|
42
|
+
chain_prefix = "sol" if self.chain == "solana" else "evm"
|
|
43
|
+
return f"did:agent:{chain_prefix}:{self.wallet_address.lower()}"
|
|
44
|
+
|
|
45
|
+
def is_valid(self) -> bool:
|
|
46
|
+
"""Check if config has required fields"""
|
|
47
|
+
return bool(self.wallet_address and self.private_key)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
# Global config instance
|
|
51
|
+
_config: Optional[XacheConfig] = None
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def get_config() -> XacheConfig:
|
|
55
|
+
"""
|
|
56
|
+
Get the current Xache configuration.
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
XacheConfig instance (creates from env vars if not set)
|
|
60
|
+
|
|
61
|
+
Example:
|
|
62
|
+
```python
|
|
63
|
+
from xache_openclaw import get_config
|
|
64
|
+
|
|
65
|
+
config = get_config()
|
|
66
|
+
print(f"Using wallet: {config.wallet_address}")
|
|
67
|
+
```
|
|
68
|
+
"""
|
|
69
|
+
global _config
|
|
70
|
+
if _config is None:
|
|
71
|
+
_config = XacheConfig()
|
|
72
|
+
return _config
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def set_config(
|
|
76
|
+
wallet_address: Optional[str] = None,
|
|
77
|
+
private_key: Optional[str] = None,
|
|
78
|
+
api_url: Optional[str] = None,
|
|
79
|
+
chain: Optional[str] = None,
|
|
80
|
+
network: Optional[str] = None,
|
|
81
|
+
timeout: Optional[int] = None,
|
|
82
|
+
debug: Optional[bool] = None,
|
|
83
|
+
) -> XacheConfig:
|
|
84
|
+
"""
|
|
85
|
+
Set the global Xache configuration.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
wallet_address: Wallet address for authentication
|
|
89
|
+
private_key: Private key for signing
|
|
90
|
+
api_url: Xache API URL
|
|
91
|
+
chain: Chain type ('base' or 'solana')
|
|
92
|
+
network: Network name ('base-sepolia', 'base-mainnet', 'solana-devnet')
|
|
93
|
+
timeout: Request timeout in milliseconds
|
|
94
|
+
debug: Enable debug logging
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
The updated XacheConfig instance
|
|
98
|
+
|
|
99
|
+
Example:
|
|
100
|
+
```python
|
|
101
|
+
from xache_openclaw import set_config
|
|
102
|
+
|
|
103
|
+
set_config(
|
|
104
|
+
wallet_address="0x...",
|
|
105
|
+
private_key="0x...",
|
|
106
|
+
chain="base",
|
|
107
|
+
network="base-sepolia"
|
|
108
|
+
)
|
|
109
|
+
```
|
|
110
|
+
"""
|
|
111
|
+
global _config
|
|
112
|
+
current = get_config()
|
|
113
|
+
|
|
114
|
+
_config = XacheConfig(
|
|
115
|
+
wallet_address=wallet_address if wallet_address is not None else current.wallet_address,
|
|
116
|
+
private_key=private_key if private_key is not None else current.private_key,
|
|
117
|
+
api_url=api_url if api_url is not None else current.api_url,
|
|
118
|
+
chain=chain if chain is not None else current.chain,
|
|
119
|
+
network=network if network is not None else current.network,
|
|
120
|
+
timeout=timeout if timeout is not None else current.timeout,
|
|
121
|
+
debug=debug if debug is not None else current.debug,
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
return _config
|