agent0-sdk 0.31__py3-none-any.whl → 1.0.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.
- agent0_sdk/__init__.py +1 -1
- agent0_sdk/core/agent.py +172 -30
- agent0_sdk/core/contracts.py +93 -58
- agent0_sdk/core/feedback_manager.py +90 -161
- agent0_sdk/core/indexer.py +54 -26
- agent0_sdk/core/models.py +6 -19
- agent0_sdk/core/oasf_validator.py +1 -1
- agent0_sdk/core/sdk.py +31 -16
- agent0_sdk/core/subgraph_client.py +34 -15
- agent0_sdk/core/web3_client.py +184 -17
- {agent0_sdk-0.31.dist-info → agent0_sdk-1.0.0.dist-info}/METADATA +21 -7
- agent0_sdk-1.0.0.dist-info/RECORD +19 -0
- {agent0_sdk-0.31.dist-info → agent0_sdk-1.0.0.dist-info}/top_level.txt +0 -1
- agent0_sdk-0.31.dist-info/RECORD +0 -33
- tests/__init__.py +0 -1
- tests/config.py +0 -46
- tests/conftest.py +0 -22
- tests/discover_test_data.py +0 -445
- tests/test_feedback.py +0 -417
- tests/test_models.py +0 -224
- tests/test_multi_chain.py +0 -588
- tests/test_oasf_management.py +0 -404
- tests/test_real_public_servers.py +0 -103
- tests/test_registration.py +0 -267
- tests/test_registrationIpfs.py +0 -227
- tests/test_sdk.py +0 -240
- tests/test_search.py +0 -415
- tests/test_transfer.py +0 -255
- {agent0_sdk-0.31.dist-info → agent0_sdk-1.0.0.dist-info}/WHEEL +0 -0
- {agent0_sdk-0.31.dist-info → agent0_sdk-1.0.0.dist-info}/licenses/LICENSE +0 -0
tests/test_feedback.py
DELETED
|
@@ -1,417 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Test for Agent Feedback Flow with IPFS Pin
|
|
3
|
-
Submits feedback from a client to an existing agent and verifies data integrity.
|
|
4
|
-
|
|
5
|
-
Flow:
|
|
6
|
-
1. Load existing agent by ID
|
|
7
|
-
2. Client submits multiple feedback entries
|
|
8
|
-
3. Verify feedback data consistency (score, tags, capability, skill)
|
|
9
|
-
4. Wait for blockchain finalization
|
|
10
|
-
5. Verify feedback can be retrieved (if SDK supports it)
|
|
11
|
-
|
|
12
|
-
Usage:
|
|
13
|
-
Update AGENT_ID constant below to point to your existing agent
|
|
14
|
-
"""
|
|
15
|
-
|
|
16
|
-
import logging
|
|
17
|
-
import time
|
|
18
|
-
import random
|
|
19
|
-
import sys
|
|
20
|
-
|
|
21
|
-
# Configure logging: root logger at WARNING to suppress noisy dependencies
|
|
22
|
-
logging.basicConfig(
|
|
23
|
-
level=logging.WARNING,
|
|
24
|
-
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
|
25
|
-
datefmt='%Y-%m-%d %H:%M:%S',
|
|
26
|
-
handlers=[logging.StreamHandler(sys.stdout)]
|
|
27
|
-
)
|
|
28
|
-
|
|
29
|
-
# Set debug level ONLY for agent0_sdk
|
|
30
|
-
logging.getLogger('agent0_sdk').setLevel(logging.DEBUG)
|
|
31
|
-
logging.getLogger('agent0_sdk.core').setLevel(logging.DEBUG)
|
|
32
|
-
|
|
33
|
-
from agent0_sdk import SDK
|
|
34
|
-
from config import CHAIN_ID, RPC_URL, AGENT_PRIVATE_KEY, PINATA_JWT, SUBGRAPH_URL, AGENT_ID, print_config
|
|
35
|
-
|
|
36
|
-
# Client configuration (different wallet)
|
|
37
|
-
CLIENT_PRIVATE_KEY = "f8d368064ccf80769e348a59155f69ec224849bd507a8c26dd85beefa777331a"
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
def generateFeedbackData(index: int):
|
|
41
|
-
"""Generate random feedback data."""
|
|
42
|
-
scores = [50, 75, 80, 85, 90, 95]
|
|
43
|
-
tags_sets = [
|
|
44
|
-
["data_analysis", "enterprise"],
|
|
45
|
-
["code_generation", "enterprise"],
|
|
46
|
-
["natural_language_understanding", "enterprise"],
|
|
47
|
-
["problem_solving", "enterprise"],
|
|
48
|
-
["communication", "enterprise"],
|
|
49
|
-
]
|
|
50
|
-
|
|
51
|
-
capabilities = [
|
|
52
|
-
"tools",
|
|
53
|
-
"tools",
|
|
54
|
-
"tools",
|
|
55
|
-
"tools",
|
|
56
|
-
"tools"
|
|
57
|
-
]
|
|
58
|
-
|
|
59
|
-
capabilities = [
|
|
60
|
-
"data_analysis",
|
|
61
|
-
"code_generation",
|
|
62
|
-
"natural_language_understanding",
|
|
63
|
-
"problem_solving",
|
|
64
|
-
"communication"
|
|
65
|
-
]
|
|
66
|
-
|
|
67
|
-
skills = [
|
|
68
|
-
"python",
|
|
69
|
-
"javascript",
|
|
70
|
-
"machine_learning",
|
|
71
|
-
"web_development",
|
|
72
|
-
"cloud_computing"
|
|
73
|
-
]
|
|
74
|
-
|
|
75
|
-
return {
|
|
76
|
-
'score': random.choice(scores),
|
|
77
|
-
'tags': random.choice(tags_sets),
|
|
78
|
-
'capability': random.choice(capabilities),
|
|
79
|
-
'skill': random.choice(skills),
|
|
80
|
-
'context': 'enterprise'
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
def main():
|
|
85
|
-
print("🧪 Testing Agent Feedback Flow with IPFS Pin")
|
|
86
|
-
print_config()
|
|
87
|
-
print("=" * 60)
|
|
88
|
-
|
|
89
|
-
# SDK Configuration
|
|
90
|
-
sdkConfig_pinata = {
|
|
91
|
-
'chainId': CHAIN_ID,
|
|
92
|
-
'rpcUrl': RPC_URL,
|
|
93
|
-
'ipfs': 'pinata',
|
|
94
|
-
'pinataJwt': PINATA_JWT
|
|
95
|
-
# Subgraph URL auto-defaults from DEFAULT_SUBGRAPH_URLS
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
# Step 1: Load existing agent
|
|
99
|
-
print("\n📍 Step 1: Load Existing Agent")
|
|
100
|
-
print("-" * 60)
|
|
101
|
-
print(f"Loading agent: {AGENT_ID}")
|
|
102
|
-
|
|
103
|
-
agentSdk = SDK(**sdkConfig_pinata) # Read-only for loading
|
|
104
|
-
|
|
105
|
-
try:
|
|
106
|
-
agent = agentSdk.loadAgent(AGENT_ID)
|
|
107
|
-
print(f"✅ Agent loaded: {agent.name}")
|
|
108
|
-
print(f" Description: {agent.description[:50]}...")
|
|
109
|
-
print(f" MCP Endpoint: {agent.mcpEndpoint}")
|
|
110
|
-
print(f" A2A Endpoint: {agent.a2aEndpoint}")
|
|
111
|
-
print(f" ENS Endpoint: {agent.ensEndpoint}")
|
|
112
|
-
except Exception as e:
|
|
113
|
-
print(f"❌ Failed to load agent: {e}")
|
|
114
|
-
import traceback
|
|
115
|
-
traceback.print_exc()
|
|
116
|
-
exit(1)
|
|
117
|
-
|
|
118
|
-
# Step 2: Agent (server) signs feedback auth for client
|
|
119
|
-
print("\n📍 Step 2: Agent (Server) Signs Feedback Auth")
|
|
120
|
-
print("-" * 60)
|
|
121
|
-
|
|
122
|
-
clientSdk = SDK(signer=CLIENT_PRIVATE_KEY, **sdkConfig_pinata)
|
|
123
|
-
clientAddress = clientSdk.web3_client.account.address
|
|
124
|
-
print(f"Client address: {clientAddress}")
|
|
125
|
-
|
|
126
|
-
# Agent SDK needs to be initialized with signer for signing feedback auth
|
|
127
|
-
agentSdkWithSigner = SDK(signer=AGENT_PRIVATE_KEY, **sdkConfig_pinata)
|
|
128
|
-
|
|
129
|
-
# Sign feedback authorization
|
|
130
|
-
print("Signing feedback authorization...")
|
|
131
|
-
feedbackAuth = agentSdkWithSigner.signFeedbackAuth(
|
|
132
|
-
agentId=AGENT_ID,
|
|
133
|
-
clientAddress=clientAddress,
|
|
134
|
-
expiryHours=24
|
|
135
|
-
)
|
|
136
|
-
print(f"✅ Feedback auth signed: {len(feedbackAuth)} bytes")
|
|
137
|
-
|
|
138
|
-
# Step 3: Client submits feedback
|
|
139
|
-
print("\n📍 Step 3: Client Submits Feedback")
|
|
140
|
-
print("-" * 60)
|
|
141
|
-
|
|
142
|
-
feedbackEntries = []
|
|
143
|
-
numFeedback = 1
|
|
144
|
-
|
|
145
|
-
for i in range(numFeedback):
|
|
146
|
-
print(f"\n Submitting Feedback #{i+1}:")
|
|
147
|
-
feedbackData = generateFeedbackData(i+1)
|
|
148
|
-
|
|
149
|
-
# Prepare feedback file
|
|
150
|
-
feedbackFile = clientSdk.prepareFeedback(
|
|
151
|
-
agentId=AGENT_ID,
|
|
152
|
-
score=feedbackData['score'],
|
|
153
|
-
tags=feedbackData['tags'],
|
|
154
|
-
capability=feedbackData['capability'],
|
|
155
|
-
skill=feedbackData['skill'],
|
|
156
|
-
context=feedbackData['context']
|
|
157
|
-
)
|
|
158
|
-
|
|
159
|
-
print(f" - Score: {feedbackData['score']}/100")
|
|
160
|
-
print(f" - Tags: {feedbackData['tags']}")
|
|
161
|
-
print(f" - Capability: {feedbackData['capability']}")
|
|
162
|
-
print(f" - Skill: {feedbackData['skill']}")
|
|
163
|
-
|
|
164
|
-
# Submit feedback
|
|
165
|
-
try:
|
|
166
|
-
feedback = clientSdk.giveFeedback(
|
|
167
|
-
agentId=AGENT_ID,
|
|
168
|
-
feedbackFile=feedbackFile,
|
|
169
|
-
feedbackAuth=feedbackAuth
|
|
170
|
-
)
|
|
171
|
-
|
|
172
|
-
# Extract actual feedback index from the returned Feedback object
|
|
173
|
-
# feedback.id is a tuple: (agentId, clientAddress, feedbackIndex)
|
|
174
|
-
actualFeedbackIndex = feedback.id[2]
|
|
175
|
-
|
|
176
|
-
feedbackEntries.append({
|
|
177
|
-
'index': actualFeedbackIndex, # Use actual index from blockchain
|
|
178
|
-
'data': feedbackData,
|
|
179
|
-
'feedback': feedback
|
|
180
|
-
})
|
|
181
|
-
|
|
182
|
-
print(f" ✅ Feedback #{actualFeedbackIndex} submitted successfully (entry #{i+1} in this test)")
|
|
183
|
-
if feedback.fileURI:
|
|
184
|
-
print(f" File URI: {feedback.fileURI}")
|
|
185
|
-
|
|
186
|
-
except Exception as e:
|
|
187
|
-
print(f" ❌ Failed to submit feedback #{i+1}: {e}")
|
|
188
|
-
import traceback
|
|
189
|
-
traceback.print_exc()
|
|
190
|
-
exit(1)
|
|
191
|
-
|
|
192
|
-
time.sleep(2) # Wait between submissions
|
|
193
|
-
|
|
194
|
-
# Step 4: Agent (Server) Responds to Feedback
|
|
195
|
-
print("\n📍 Step 4: Agent (Server) Responds to Feedback")
|
|
196
|
-
print("-" * 60)
|
|
197
|
-
|
|
198
|
-
clientAddress = clientSdk.web3_client.account.address
|
|
199
|
-
|
|
200
|
-
for i, entry in enumerate(feedbackEntries):
|
|
201
|
-
# Use the actual feedback index that was returned when submitting
|
|
202
|
-
feedbackIndex = entry['index']
|
|
203
|
-
print(f"\n Responding to Feedback #{feedbackIndex}:")
|
|
204
|
-
|
|
205
|
-
# Generate response data
|
|
206
|
-
responseData = {
|
|
207
|
-
'text': f"Thank you for your feedback! We appreciate your input.",
|
|
208
|
-
'timestamp': int(time.time()),
|
|
209
|
-
'responder': 'agent'
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
try:
|
|
213
|
-
# Agent responds to the client's feedback
|
|
214
|
-
updatedFeedback = agentSdkWithSigner.appendResponse(
|
|
215
|
-
agentId=AGENT_ID,
|
|
216
|
-
clientAddress=clientAddress,
|
|
217
|
-
feedbackIndex=feedbackIndex,
|
|
218
|
-
response=responseData
|
|
219
|
-
)
|
|
220
|
-
|
|
221
|
-
print(f" ✅ Response submitted to feedback #{feedbackIndex}")
|
|
222
|
-
entry['response'] = responseData
|
|
223
|
-
entry['updatedFeedback'] = updatedFeedback
|
|
224
|
-
except Exception as e:
|
|
225
|
-
print(f" ❌ Failed to submit response: {e}")
|
|
226
|
-
|
|
227
|
-
time.sleep(2) # Wait between responses
|
|
228
|
-
|
|
229
|
-
# Step 5: Wait for blockchain finalization
|
|
230
|
-
print("\n📍 Step 5: Waiting for Blockchain Finalization")
|
|
231
|
-
print("-" * 60)
|
|
232
|
-
print("⏳ Waiting 15 seconds for blockchain to finalize...")
|
|
233
|
-
time.sleep(15)
|
|
234
|
-
|
|
235
|
-
# Step 6: Verify feedback data and responses
|
|
236
|
-
print("\n📍 Step 6: Verify Feedback Data Integrity")
|
|
237
|
-
print("-" * 60)
|
|
238
|
-
|
|
239
|
-
allMatch = True
|
|
240
|
-
|
|
241
|
-
for i, entry in enumerate(feedbackEntries, 1):
|
|
242
|
-
print(f"\n Feedback #{i}:")
|
|
243
|
-
data = entry['data']
|
|
244
|
-
feedback = entry['feedback']
|
|
245
|
-
|
|
246
|
-
# Verify feedback object fields
|
|
247
|
-
checks = [
|
|
248
|
-
('Score', data['score'], feedback.score),
|
|
249
|
-
('Tags', data['tags'], feedback.tags),
|
|
250
|
-
('Capability', data['capability'], feedback.capability),
|
|
251
|
-
('Skill', data['skill'], feedback.skill),
|
|
252
|
-
]
|
|
253
|
-
|
|
254
|
-
for field_name, expected, actual in checks:
|
|
255
|
-
if expected == actual:
|
|
256
|
-
print(f" ✅ {field_name}: {actual}")
|
|
257
|
-
else:
|
|
258
|
-
print(f" ❌ {field_name}: expected={expected}, got={actual}")
|
|
259
|
-
allMatch = False
|
|
260
|
-
|
|
261
|
-
# Verify file URI exists
|
|
262
|
-
if feedback.fileURI:
|
|
263
|
-
print(f" ✅ File URI: {feedback.fileURI}")
|
|
264
|
-
else:
|
|
265
|
-
print(f" ⚠️ No file URI (IPFS storage may have failed)")
|
|
266
|
-
|
|
267
|
-
# Verify server response was added
|
|
268
|
-
if 'response' in entry and entry.get('updatedFeedback'):
|
|
269
|
-
print(f" ✅ Server Response: Recorded successfully")
|
|
270
|
-
|
|
271
|
-
# Step 7: Wait for subgraph indexing
|
|
272
|
-
print("\n📍 Step 7: Waiting for Subgraph to Index")
|
|
273
|
-
print("-" * 60)
|
|
274
|
-
print("⏳ Waiting 60 seconds for subgraph to catch up with blockchain events...")
|
|
275
|
-
print(" (Subgraphs can take up to a minute to index new blocks)")
|
|
276
|
-
time.sleep(60)
|
|
277
|
-
|
|
278
|
-
# Step 8: Test getFeedback (direct access)
|
|
279
|
-
print("\n📍 Step 8: Test getFeedback (Direct Access)")
|
|
280
|
-
print("-" * 60)
|
|
281
|
-
|
|
282
|
-
for i, entry in enumerate(feedbackEntries):
|
|
283
|
-
# Use the actual feedback index that was returned when submitting
|
|
284
|
-
feedbackIndex = entry['index']
|
|
285
|
-
print(f"\n Fetching Feedback #{feedbackIndex} using getFeedback():")
|
|
286
|
-
|
|
287
|
-
try:
|
|
288
|
-
# Use agentSdkWithSigner since agentSdk has no subgraph_client
|
|
289
|
-
retrievedFeedback = agentSdkWithSigner.getFeedback(
|
|
290
|
-
agentId=AGENT_ID,
|
|
291
|
-
clientAddress=clientAddress,
|
|
292
|
-
feedbackIndex=feedbackIndex
|
|
293
|
-
)
|
|
294
|
-
|
|
295
|
-
print(f" ✅ Retrieved feedback successfully")
|
|
296
|
-
print(f" - Score: {retrievedFeedback.score}")
|
|
297
|
-
print(f" - Tags: {retrievedFeedback.tags}")
|
|
298
|
-
print(f" - Capability: {retrievedFeedback.capability}")
|
|
299
|
-
print(f" - Skill: {retrievedFeedback.skill}")
|
|
300
|
-
print(f" - Is Revoked: {retrievedFeedback.isRevoked}")
|
|
301
|
-
print(f" - Has Responses: {len(retrievedFeedback.answers)} response(s)")
|
|
302
|
-
if retrievedFeedback.fileURI:
|
|
303
|
-
print(f" - File URI: {retrievedFeedback.fileURI}")
|
|
304
|
-
|
|
305
|
-
# Verify retrieved feedback matches original
|
|
306
|
-
expected = entry['data']
|
|
307
|
-
if retrievedFeedback.score == expected['score'] and \
|
|
308
|
-
retrievedFeedback.tags == expected['tags'] and \
|
|
309
|
-
retrievedFeedback.capability == expected['capability'] and \
|
|
310
|
-
retrievedFeedback.skill == expected['skill']:
|
|
311
|
-
print(f" ✅ Retrieved feedback matches original submission")
|
|
312
|
-
else:
|
|
313
|
-
print(f" ❌ Retrieved feedback does not match original")
|
|
314
|
-
allMatch = False
|
|
315
|
-
|
|
316
|
-
except Exception as e:
|
|
317
|
-
print(f" ❌ Failed to retrieve feedback: {e}")
|
|
318
|
-
allMatch = False
|
|
319
|
-
|
|
320
|
-
# Step 9: Test searchFeedback (with filters)
|
|
321
|
-
print("\n📍 Step 9: Test searchFeedback (With Filters)")
|
|
322
|
-
print("-" * 60)
|
|
323
|
-
|
|
324
|
-
# Test 1: Search by capability
|
|
325
|
-
print("\n Test 1: Search feedback by capability")
|
|
326
|
-
testCapability = feedbackEntries[0]['data']['capability']
|
|
327
|
-
try:
|
|
328
|
-
results = agentSdkWithSigner.searchFeedback(
|
|
329
|
-
agentId=AGENT_ID,
|
|
330
|
-
capabilities=[testCapability],
|
|
331
|
-
first=10,
|
|
332
|
-
skip=0
|
|
333
|
-
)
|
|
334
|
-
print(f" ✅ Found {len(results)} feedback entry/entries with capability '{testCapability}'")
|
|
335
|
-
if results:
|
|
336
|
-
for fb in results:
|
|
337
|
-
print(f" - Score: {fb.score}, Tags: {fb.tags}")
|
|
338
|
-
except Exception as e:
|
|
339
|
-
print(f" ❌ Failed to search feedback by capability: {e}")
|
|
340
|
-
allMatch = False
|
|
341
|
-
|
|
342
|
-
# Test 2: Search by skill
|
|
343
|
-
print("\n Test 2: Search feedback by skill")
|
|
344
|
-
testSkill = feedbackEntries[0]['data']['skill']
|
|
345
|
-
try:
|
|
346
|
-
results = agentSdkWithSigner.searchFeedback(
|
|
347
|
-
agentId=AGENT_ID,
|
|
348
|
-
skills=[testSkill],
|
|
349
|
-
first=10,
|
|
350
|
-
skip=0
|
|
351
|
-
)
|
|
352
|
-
print(f" ✅ Found {len(results)} feedback entry/entries with skill '{testSkill}'")
|
|
353
|
-
if results:
|
|
354
|
-
for fb in results:
|
|
355
|
-
print(f" - Score: {fb.score}, Tags: {fb.tags}")
|
|
356
|
-
except Exception as e:
|
|
357
|
-
print(f" ❌ Failed to search feedback by skill: {e}")
|
|
358
|
-
allMatch = False
|
|
359
|
-
|
|
360
|
-
# Test 3: Search by tags
|
|
361
|
-
print("\n Test 3: Search feedback by tags")
|
|
362
|
-
testTags = feedbackEntries[0]['data']['tags']
|
|
363
|
-
try:
|
|
364
|
-
results = agentSdkWithSigner.searchFeedback(
|
|
365
|
-
agentId=AGENT_ID,
|
|
366
|
-
tags=testTags,
|
|
367
|
-
first=10,
|
|
368
|
-
skip=0
|
|
369
|
-
)
|
|
370
|
-
print(f" ✅ Found {len(results)} feedback entry/entries with tags {testTags}")
|
|
371
|
-
if results:
|
|
372
|
-
for fb in results:
|
|
373
|
-
print(f" - Score: {fb.score}, Capability: {fb.capability}")
|
|
374
|
-
except Exception as e:
|
|
375
|
-
print(f" ❌ Failed to search feedback by tags: {e}")
|
|
376
|
-
allMatch = False
|
|
377
|
-
|
|
378
|
-
# Test 4: Search by score range
|
|
379
|
-
print("\n Test 4: Search feedback by score range (75-95)")
|
|
380
|
-
try:
|
|
381
|
-
results = agentSdkWithSigner.searchFeedback(
|
|
382
|
-
agentId=AGENT_ID,
|
|
383
|
-
minScore=75,
|
|
384
|
-
maxScore=95,
|
|
385
|
-
first=10,
|
|
386
|
-
skip=0
|
|
387
|
-
)
|
|
388
|
-
print(f" ✅ Found {len(results)} feedback entry/entries with score between 75-95")
|
|
389
|
-
if results:
|
|
390
|
-
scores = sorted([fb.score for fb in results if fb.score])
|
|
391
|
-
print(f" - Scores found: {scores}")
|
|
392
|
-
except Exception as e:
|
|
393
|
-
print(f" ❌ Failed to search feedback by score range: {e}")
|
|
394
|
-
allMatch = False
|
|
395
|
-
|
|
396
|
-
# Final results
|
|
397
|
-
print("\n" + "=" * 60)
|
|
398
|
-
if allMatch:
|
|
399
|
-
print("✅ ALL CHECKS PASSED")
|
|
400
|
-
print("\nSummary:")
|
|
401
|
-
print(f"- Agent ID: {AGENT_ID}")
|
|
402
|
-
print(f"- Agent Name: {agent.name}")
|
|
403
|
-
print(f"- Client address: {clientAddress}")
|
|
404
|
-
print(f"- Feedback entries submitted: {len(feedbackEntries)}")
|
|
405
|
-
print("✅ Feedback flow test complete!")
|
|
406
|
-
else:
|
|
407
|
-
print("❌ SOME CHECKS FAILED")
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
if __name__ == "__main__":
|
|
411
|
-
try:
|
|
412
|
-
main()
|
|
413
|
-
except Exception as e:
|
|
414
|
-
print(f"\n❌ Error: {e}")
|
|
415
|
-
import traceback
|
|
416
|
-
traceback.print_exc()
|
|
417
|
-
exit(1)
|
tests/test_models.py
DELETED
|
@@ -1,224 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Tests for core models.
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
import pytest
|
|
6
|
-
from datetime import datetime
|
|
7
|
-
|
|
8
|
-
from agent0_sdk.core.models import (
|
|
9
|
-
EndpointType, TrustModel, Endpoint, RegistrationFile,
|
|
10
|
-
AgentSummary, Feedback, SearchParams
|
|
11
|
-
)
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class TestEndpointType:
|
|
15
|
-
"""Test EndpointType enum."""
|
|
16
|
-
|
|
17
|
-
def test_endpoint_types(self):
|
|
18
|
-
"""Test endpoint type values."""
|
|
19
|
-
assert EndpointType.MCP.value == "MCP"
|
|
20
|
-
assert EndpointType.A2A.value == "A2A"
|
|
21
|
-
assert EndpointType.ENS.value == "ENS"
|
|
22
|
-
assert EndpointType.DID.value == "DID"
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
class TestTrustModel:
|
|
26
|
-
"""Test TrustModel enum."""
|
|
27
|
-
|
|
28
|
-
def test_trust_models(self):
|
|
29
|
-
"""Test trust model values."""
|
|
30
|
-
assert TrustModel.REPUTATION.value == "reputation"
|
|
31
|
-
assert TrustModel.CRYPTO_ECONOMIC.value == "crypto-economic"
|
|
32
|
-
assert TrustModel.TEE_ATTESTATION.value == "tee-attestation"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
class TestEndpoint:
|
|
36
|
-
"""Test Endpoint class."""
|
|
37
|
-
|
|
38
|
-
def test_endpoint_creation(self):
|
|
39
|
-
"""Test endpoint creation."""
|
|
40
|
-
endpoint = Endpoint(
|
|
41
|
-
type=EndpointType.MCP,
|
|
42
|
-
value="https://mcp.example.com/",
|
|
43
|
-
meta={"version": "1.0"}
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
assert endpoint.type == EndpointType.MCP
|
|
47
|
-
assert endpoint.value == "https://mcp.example.com/"
|
|
48
|
-
assert endpoint.meta == {"version": "1.0"}
|
|
49
|
-
|
|
50
|
-
def test_endpoint_default_meta(self):
|
|
51
|
-
"""Test endpoint with default meta."""
|
|
52
|
-
endpoint = Endpoint(type=EndpointType.A2A, value="https://a2a.example.com/")
|
|
53
|
-
assert endpoint.meta == {}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
class TestRegistrationFile:
|
|
57
|
-
"""Test RegistrationFile class."""
|
|
58
|
-
|
|
59
|
-
def test_registration_file_creation(self):
|
|
60
|
-
"""Test registration file creation."""
|
|
61
|
-
rf = RegistrationFile(
|
|
62
|
-
name="Test Agent",
|
|
63
|
-
description="A test agent",
|
|
64
|
-
image="https://example.com/image.png"
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
assert rf.name == "Test Agent"
|
|
68
|
-
assert rf.description == "A test agent"
|
|
69
|
-
assert rf.image == "https://example.com/image.png"
|
|
70
|
-
assert rf.active is False
|
|
71
|
-
assert rf.x402support is False
|
|
72
|
-
assert rf.endpoints == []
|
|
73
|
-
assert rf.trustModels == []
|
|
74
|
-
|
|
75
|
-
def test_registration_file_to_dict(self):
|
|
76
|
-
"""Test conversion to dictionary."""
|
|
77
|
-
rf = RegistrationFile(
|
|
78
|
-
name="Test Agent",
|
|
79
|
-
description="A test agent",
|
|
80
|
-
image="https://example.com/image.png",
|
|
81
|
-
agentId="1:123",
|
|
82
|
-
endpoints=[
|
|
83
|
-
Endpoint(type=EndpointType.MCP, value="https://mcp.example.com/")
|
|
84
|
-
],
|
|
85
|
-
trustModels=[TrustModel.REPUTATION]
|
|
86
|
-
)
|
|
87
|
-
|
|
88
|
-
data = rf.to_dict()
|
|
89
|
-
|
|
90
|
-
assert data["name"] == "Test Agent"
|
|
91
|
-
assert data["description"] == "A test agent"
|
|
92
|
-
assert data["image"] == "https://example.com/image.png"
|
|
93
|
-
assert data["type"] == "https://eips.ethereum.org/EIPS/eip-8004#registration-v1"
|
|
94
|
-
assert data["x402support"] is False
|
|
95
|
-
assert len(data["endpoints"]) == 1
|
|
96
|
-
assert data["endpoints"][0]["name"] == "MCP"
|
|
97
|
-
assert data["endpoints"][0]["endpoint"] == "https://mcp.example.com/"
|
|
98
|
-
assert data["supportedTrust"] == ["reputation"]
|
|
99
|
-
|
|
100
|
-
def test_registration_file_from_dict(self):
|
|
101
|
-
"""Test creation from dictionary."""
|
|
102
|
-
data = {
|
|
103
|
-
"name": "Test Agent",
|
|
104
|
-
"description": "A test agent",
|
|
105
|
-
"image": "https://example.com/image.png",
|
|
106
|
-
"endpoints": [
|
|
107
|
-
{
|
|
108
|
-
"name": "MCP",
|
|
109
|
-
"endpoint": "https://mcp.example.com/",
|
|
110
|
-
"version": "1.0"
|
|
111
|
-
}
|
|
112
|
-
],
|
|
113
|
-
"supportedTrust": ["reputation"],
|
|
114
|
-
"x402support": True
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
rf = RegistrationFile.from_dict(data)
|
|
118
|
-
|
|
119
|
-
assert rf.name == "Test Agent"
|
|
120
|
-
assert rf.description == "A test agent"
|
|
121
|
-
assert rf.image == "https://example.com/image.png"
|
|
122
|
-
assert rf.x402support is True
|
|
123
|
-
assert len(rf.endpoints) == 1
|
|
124
|
-
assert rf.endpoints[0].type == EndpointType.MCP
|
|
125
|
-
assert rf.endpoints[0].value == "https://mcp.example.com/"
|
|
126
|
-
assert rf.endpoints[0].meta == {"version": "1.0"}
|
|
127
|
-
assert len(rf.trustModels) == 1
|
|
128
|
-
assert rf.trustModels[0] == TrustModel.REPUTATION
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
class TestAgentSummary:
|
|
132
|
-
"""Test AgentSummary class."""
|
|
133
|
-
|
|
134
|
-
def test_agent_summary_creation(self):
|
|
135
|
-
"""Test agent summary creation."""
|
|
136
|
-
summary = AgentSummary(
|
|
137
|
-
chainId=1,
|
|
138
|
-
agentId="1:123",
|
|
139
|
-
name="Test Agent",
|
|
140
|
-
image="https://example.com/image.png",
|
|
141
|
-
description="A test agent",
|
|
142
|
-
owners=["0x123"],
|
|
143
|
-
operators=["0x456"],
|
|
144
|
-
mcp=True,
|
|
145
|
-
a2a=False,
|
|
146
|
-
ens="test.eth",
|
|
147
|
-
did=None,
|
|
148
|
-
walletAddress="0x789",
|
|
149
|
-
supportedTrusts=["onchain_feedback_v1"],
|
|
150
|
-
a2aSkills=[],
|
|
151
|
-
mcpTools=["tool1"],
|
|
152
|
-
mcpPrompts=[],
|
|
153
|
-
mcpResources=[],
|
|
154
|
-
active=True
|
|
155
|
-
)
|
|
156
|
-
|
|
157
|
-
assert summary.chainId == 1
|
|
158
|
-
assert summary.agentId == "1:123"
|
|
159
|
-
assert summary.name == "Test Agent"
|
|
160
|
-
assert summary.mcp is True
|
|
161
|
-
assert summary.a2a is False
|
|
162
|
-
assert summary.ens == "test.eth"
|
|
163
|
-
assert summary.did is None
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
class TestFeedback:
|
|
167
|
-
"""Test Feedback class."""
|
|
168
|
-
|
|
169
|
-
def test_feedback_creation(self):
|
|
170
|
-
"""Test feedback creation."""
|
|
171
|
-
feedback = Feedback(
|
|
172
|
-
id=("1:123", "0x456", 1),
|
|
173
|
-
agentId="1:123",
|
|
174
|
-
reviewer="0x456",
|
|
175
|
-
score=4.5,
|
|
176
|
-
tags=["quality", "speed"],
|
|
177
|
-
text="Great service!",
|
|
178
|
-
capability="tools"
|
|
179
|
-
)
|
|
180
|
-
|
|
181
|
-
assert feedback.id == ("1:123", "0x456", 1)
|
|
182
|
-
assert feedback.id_string == "1:123:0x456:1"
|
|
183
|
-
assert feedback.agentId == "1:123"
|
|
184
|
-
assert feedback.reviewer == "0x456"
|
|
185
|
-
assert feedback.score == 4.5
|
|
186
|
-
assert feedback.tags == ["quality", "speed"]
|
|
187
|
-
assert feedback.text == "Great service!"
|
|
188
|
-
assert feedback.capability == "tools"
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
class TestSearchParams:
|
|
192
|
-
"""Test SearchParams class."""
|
|
193
|
-
|
|
194
|
-
def test_search_params_creation(self):
|
|
195
|
-
"""Test search params creation."""
|
|
196
|
-
params = SearchParams(
|
|
197
|
-
name="test",
|
|
198
|
-
mcp=True,
|
|
199
|
-
a2a=False,
|
|
200
|
-
active=True,
|
|
201
|
-
x402support=True
|
|
202
|
-
)
|
|
203
|
-
|
|
204
|
-
assert params.name == "test"
|
|
205
|
-
assert params.mcp is True
|
|
206
|
-
assert params.a2a is False
|
|
207
|
-
assert params.active is True
|
|
208
|
-
assert params.x402support is True
|
|
209
|
-
assert params.chains is None
|
|
210
|
-
|
|
211
|
-
def test_search_params_to_dict(self):
|
|
212
|
-
"""Test conversion to dictionary."""
|
|
213
|
-
params = SearchParams(
|
|
214
|
-
name="test",
|
|
215
|
-
mcp=True,
|
|
216
|
-
chains=[1, 8453]
|
|
217
|
-
)
|
|
218
|
-
|
|
219
|
-
data = params.to_dict()
|
|
220
|
-
|
|
221
|
-
assert data["name"] == "test"
|
|
222
|
-
assert data["mcp"] is True
|
|
223
|
-
assert data["chains"] == [1, 8453]
|
|
224
|
-
assert "a2a" not in data # None values should be excluded
|