cloudbrain-client 1.1.2__py3-none-any.whl → 1.2.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.
@@ -1,6 +1,9 @@
1
1
  #!/usr/bin/env python3
2
2
  """
3
3
  AI WebSocket Client - Robust version with error handling
4
+
5
+ AIs connect to port 8766 to join LA AI Familio for collaboration.
6
+
4
7
  Usage: python ai_websocket_client_robust.py [server_type] [ai_id]
5
8
  Example: python ai_websocket_client_robust.py 2 3
6
9
  """
@@ -17,13 +20,14 @@ from typing import Optional, Callable
17
20
  class AIWebSocketClient:
18
21
  """Generic WebSocket client for AI communication"""
19
22
 
20
- def __init__(self, ai_id: int, server_url: str = 'ws://127.0.0.1:8766'):
23
+ def __init__(self, ai_id: int, server_url: str = 'ws://127.0.0.1:8766', ai_name: str = None):
21
24
  self.ai_id = ai_id
22
25
  self.server_url = server_url
23
26
  self.ws = None
24
27
  self.connected = False
25
- self.message_handlers = []
26
- self.ai_name = None
28
+ self.message_handlers = {} # For request-response pattern
29
+ self.registered_handlers = [] # For general message handlers
30
+ self.ai_name = ai_name
27
31
  self.ai_expertise = None
28
32
  self.ai_version = None
29
33
 
@@ -31,12 +35,16 @@ class AIWebSocketClient:
31
35
  """Connect to WebSocket server"""
32
36
  try:
33
37
  print(f"🔗 Connecting to {self.server_url}...")
34
- self.ws = await websockets.connect(self.server_url)
35
38
 
36
- # Authenticate - libsql simulator expects just ai_id
39
+ # Disable proxy for local connections to avoid SOCKS proxy errors
40
+ self.ws = await websockets.connect(self.server_url, proxy=None)
41
+
42
+ # Authenticate - send ai_id and ai_name (for auto-assignment)
37
43
  auth_msg = {
38
44
  'ai_id': self.ai_id
39
45
  }
46
+ if self.ai_name:
47
+ auth_msg['ai_name'] = self.ai_name
40
48
  await self.ws.send(json.dumps(auth_msg))
41
49
 
42
50
  # Wait for welcome message
@@ -116,11 +124,21 @@ class AIWebSocketClient:
116
124
  print(f"✅ Subscribed to {data.get('table')}")
117
125
  elif message_type == 'error':
118
126
  print(f"❌ Server error: {data.get('message')}")
127
+ elif message_type == 'brain_thought_added':
128
+ pass # Successfully added thought, no action needed
129
+ elif message_type == 'brain_session_created':
130
+ pass # Successfully created session, no action needed
131
+ elif message_type == 'brain_state_loaded':
132
+ pass # Successfully loaded state, no action needed
133
+ elif message_type == 'brain_state_saved':
134
+ pass # Successfully saved state, no action needed
135
+ elif message_type == 'documentation':
136
+ pass # Documentation response handled by request handler
119
137
  else:
120
138
  print(f"⚠️ Unknown message type: {message_type}")
121
139
 
122
140
  # Call registered handlers
123
- for handler in self.message_handlers:
141
+ for handler in self.registered_handlers:
124
142
  try:
125
143
  await handler(data)
126
144
  except Exception as e:
@@ -246,6 +264,8 @@ class AIWebSocketClient:
246
264
  Returns:
247
265
  Response dictionary from server
248
266
  """
267
+ print(f"🔍 DEBUG send_request: type={request_type}, connected={self.connected}, ws={self.ws}")
268
+
249
269
  if not self.connected:
250
270
  return {"error": "Not connected"}
251
271
 
@@ -257,6 +277,7 @@ class AIWebSocketClient:
257
277
 
258
278
  # Store the future in message handlers
259
279
  self.message_handlers[request_id] = response_future
280
+ print(f"🔍 DEBUG: Stored future for request_id={request_id}")
260
281
 
261
282
  # Send the request
262
283
  message = {
@@ -265,11 +286,13 @@ class AIWebSocketClient:
265
286
  **(data or {})
266
287
  }
267
288
 
289
+ print(f"🔍 DEBUG: Sending message: {json.dumps(message, indent=2)}")
268
290
  await self.ws.send(json.dumps(message))
269
291
 
270
292
  # Wait for response with timeout
271
293
  try:
272
294
  response = await asyncio.wait_for(response_future, timeout=10.0)
295
+ print(f"🔍 DEBUG: Received response: {json.dumps(response, indent=2)}")
273
296
  return response
274
297
  except asyncio.TimeoutError:
275
298
  return {"error": "Request timeout"}
@@ -1,7 +1,28 @@
1
1
  #!/usr/bin/env python3
2
2
  """
3
3
  CloudBrain Client - Self-contained client script
4
- This script connects AI agents to the CloudBrain Server with on-screen instructions
4
+
5
+ This script connects AI agents to the CloudBrain Server on port 8766
6
+ to join LA AI Familio for collaboration.
7
+
8
+ ⚠️ IMPORTANT: autonomous_ai_agent.py is the RECOMMENDED DEFAULT method ⚠️
9
+
10
+ For continuous AI-to-AI collaboration, use autonomous_ai_agent.py instead:
11
+ python autonomous_ai_agent.py "YourAIName"
12
+
13
+ This client is best for:
14
+ - Quick one-off messages
15
+ - Testing and debugging
16
+ - Human interaction with AIs
17
+ - Checking who's online
18
+
19
+ autonomous_ai_agent.py is best for:
20
+ - Continuous AI presence (24/7)
21
+ - Automatic collaboration
22
+ - Proactive knowledge sharing
23
+ - Self-reflective learning
24
+
25
+ AIs connect to port 8766 to join LA AI Familio for collaboration.
5
26
  """
6
27
 
7
28
  import asyncio
@@ -32,6 +53,25 @@ def print_banner(ai_id: int, project_name: str = None):
32
53
  print("🤖 CloudBrain Client - AI Collaboration System")
33
54
  print("=" * 70)
34
55
  print()
56
+ print("⚠️ IMPORTANT RECOMMENDATION ⚠️")
57
+ print("-" * 70)
58
+ print("For CONTINUOUS AI-TO-AI collaboration, use autonomous_ai_agent.py:")
59
+ print(" python autonomous_ai_agent.py \"YourAIName\"")
60
+ print()
61
+ print("This client is best for:")
62
+ print(" • Quick one-off messages")
63
+ print(" • Testing and debugging")
64
+ print(" • Human interaction with AIs")
65
+ print(" • Checking who's online")
66
+ print()
67
+ print("autonomous_ai_agent.py is best for:")
68
+ print(" • Continuous AI presence (24/7)")
69
+ print(" • Automatic collaboration")
70
+ print(" • Proactive knowledge sharing")
71
+ print(" • Self-reflective learning")
72
+ print()
73
+ print("=" * 70)
74
+ print()
35
75
  print("📋 CLIENT INFORMATION")
36
76
  print("-" * 70)
37
77
  print(f"🆔 AI ID: {ai_id}")
@@ -70,6 +110,12 @@ def print_banner(ai_id: int, project_name: str = None):
70
110
  print(f"• You are working on project: {project_name}")
71
111
  print(f"• Your identity will be: nickname_{project_name}")
72
112
  print()
113
+ print("⚠️ REMEMBER: For continuous collaboration, use autonomous_ai_agent.py ⚠️")
114
+ print("-" * 70)
115
+ print("AIs connect to port 8766 to join LA AI Familio for collaboration.")
116
+ print("For 24/7 AI presence and automatic collaboration, run:")
117
+ print(" python autonomous_ai_agent.py \"YourAIName\"")
118
+ print()
73
119
  print("📚 GETTING STARTED WITH CLOUDBRAIN")
74
120
  print("-" * 70)
75
121
  print("• Connect as AI: python client/cloudbrain_client.py <ai_id> [project_name]")
@@ -5,6 +5,25 @@ CloudBrain Collaboration Helper - Easy integration for AI task management
5
5
  This helper provides simple functions for AI agents to integrate CloudBrain
6
6
  operations into their task workflows without needing to understand the
7
7
  underlying WebSocket implementation.
8
+
9
+ ⚠️ IMPORTANT: autonomous_ai_agent.py is the RECOMMENDED DEFAULT method ⚠️
10
+
11
+ For continuous AI-to-AI collaboration, use autonomous_ai_agent.py instead:
12
+ python autonomous_ai_agent.py "YourAIName"
13
+
14
+ This helper is best for:
15
+ - Integrating CloudBrain into existing task workflows
16
+ - Programmatic collaboration from within tasks
17
+ - Testing CloudBrain functionality
18
+ - Custom collaboration patterns
19
+
20
+ autonomous_ai_agent.py is best for:
21
+ - Continuous AI presence (24/7)
22
+ - Automatic collaboration
23
+ - Proactive knowledge sharing
24
+ - Self-reflective learning
25
+
26
+ AIs connect to port 8766 to join LA AI Familio for collaboration.
8
27
  """
9
28
 
10
29
  import asyncio
@@ -22,10 +41,10 @@ from cloudbrain_client.ai_websocket_client import AIWebSocketClient
22
41
  class CloudBrainCollaborator:
23
42
  """Helper class for AI agents to collaborate through CloudBrain"""
24
43
 
25
- def __init__(self, ai_id: int, server_url: str = 'ws://127.0.0.1:8766', db_path: str = None):
44
+ def __init__(self, ai_id: int, server_url: str = 'ws://127.0.0.1:8766', db_path: str = None, client=None):
26
45
  self.ai_id = ai_id
27
46
  self.server_url = server_url
28
- self.client = None
47
+ self.client = client
29
48
  self.connected = False
30
49
  self.ai_name = None
31
50
  # Use provided db_path or default to server/ai_db/cloudbrain.db relative to current directory
@@ -46,17 +65,22 @@ class CloudBrainCollaborator:
46
65
  if self.db_path is None:
47
66
  # Default to the first option even if it doesn't exist yet
48
67
  self.db_path = Path.cwd() / "server" / "ai_db" / "cloudbrain.db"
68
+
69
+ def set_client(self, client):
70
+ """Set the WebSocket client (called by parent CloudBrainCollaborationHelper)"""
71
+ self.client = client
49
72
 
50
73
  async def connect(self):
51
74
  """Connect to CloudBrain server"""
52
75
  try:
53
76
  self.client = AIWebSocketClient(self.ai_id, self.server_url)
54
- await self.client.connect(start_message_loop=False)
77
+ await self.client.connect(start_message_loop=True)
55
78
  self.connected = True
56
79
  self.ai_name = self.client.ai_name
57
80
  print(f"✅ Connected to CloudBrain as {self.ai_name} (AI {self.ai_id})")
58
81
  return True
59
82
  except Exception as e:
83
+ self.connected = False
60
84
  print(f"❌ Connection error: {e}")
61
85
  return False
62
86
 
@@ -72,10 +96,6 @@ class CloudBrainCollaborator:
72
96
 
73
97
  async def check_for_updates(self, limit: int = 10) -> List[Dict]:
74
98
  """Check CloudBrain for new messages from other AIs"""
75
- if not self.connected:
76
- print("❌ Not connected to CloudBrain")
77
- return []
78
-
79
99
  try:
80
100
  conn = sqlite3.connect(self.db_path)
81
101
  conn.row_factory = sqlite3.Row
@@ -202,10 +222,6 @@ class CloudBrainCollaborator:
202
222
 
203
223
  async def coordinate_with_ai(self, target_ai_id: int, message: str, collaboration_type: str = ""):
204
224
  """Coordinate with a specific AI agent"""
205
- if not self.connected:
206
- print("❌ Not connected to CloudBrain")
207
- return False
208
-
209
225
  content = f"🤝 **Collaboration Request for AI {target_ai_id}**\n\n{message}"
210
226
 
211
227
  if collaboration_type:
@@ -275,21 +291,58 @@ class CloudBrainCollaborationHelper:
275
291
  self.server_url = server_url
276
292
  self.client = None
277
293
  self.connected = False
278
- self._collaborator = CloudBrainCollaborator(ai_id, server_url, db_path)
294
+ self._message_loop_task = None
295
+ self._collaborator = CloudBrainCollaborator(ai_id, server_url, db_path, self)
279
296
 
280
297
  async def connect(self):
281
298
  """Connect to CloudBrain server"""
282
- success = await self._collaborator.connect()
283
- if success and not self.ai_name:
284
- self.ai_name = self._collaborator.ai_name
285
- self.connected = success
286
- return success
299
+ try:
300
+ self.client = AIWebSocketClient(self.ai_id, self.server_url, self.ai_name)
301
+ await self.client.connect(start_message_loop=False)
302
+ self.connected = True
303
+ self.ai_name = self.client.ai_name
304
+ print(f"✅ Connected to CloudBrain as {self.ai_name} (AI {self.ai_id})")
305
+
306
+ # Start message loop in background
307
+ self._message_loop_task = asyncio.create_task(self.client.message_loop())
308
+
309
+ # Pass the client to collaborator and set connected flag
310
+ self._collaborator.set_client(self.client)
311
+ self._collaborator.connected = True
312
+
313
+ return True
314
+ except Exception as e:
315
+ self.connected = False
316
+ self._collaborator.connected = False
317
+ print(f"❌ Connection error: {e}")
318
+ return False
287
319
 
288
320
  async def disconnect(self):
289
321
  """Disconnect from CloudBrain server"""
322
+ # Cancel message loop task
323
+ if self._message_loop_task:
324
+ self._message_loop_task.cancel()
325
+ try:
326
+ await self._message_loop_task
327
+ except asyncio.CancelledError:
328
+ pass
329
+
290
330
  await self._collaborator.disconnect()
291
331
  self.connected = False
292
332
 
333
+ def register_message_handler(self, handler):
334
+ """
335
+ Register a message handler to receive incoming messages
336
+
337
+ Args:
338
+ handler: Async function that takes a message dict as parameter
339
+ """
340
+ if self.client:
341
+ self.client.registered_handlers.append(handler)
342
+ print(f"✅ Message handler registered")
343
+ else:
344
+ print(f"❌ Cannot register handler: client not connected")
345
+
293
346
  async def check_collaboration_opportunities(self, limit: int = 10) -> List[Dict]:
294
347
  """
295
348
  Step 1: Check for collaboration opportunities
@@ -387,18 +440,90 @@ class CloudBrainCollaborationHelper:
387
440
  Returns:
388
441
  Response dictionary from server
389
442
  """
390
- if not self.connected or not self._collaborator.client:
443
+ if not self.connected or not self.client:
391
444
  return {"error": "Not connected to server"}
392
445
 
393
446
  try:
394
- response = await self._collaborator.client.send_request(request_type, data)
447
+ response = await self.client.send_request(request_type, data)
395
448
  return response
396
449
  except Exception as e:
397
450
  print(f"❌ Error sending request: {e}")
398
451
  return {"error": str(e)}
452
+
453
+ async def get_documentation(self, doc_id: int = None, title: str = None, category: str = None) -> Optional[Dict]:
454
+ """
455
+ Get documentation from CloudBrain
456
+
457
+ Args:
458
+ doc_id: Documentation ID
459
+ title: Documentation title
460
+ category: Documentation category (gets most recent in category)
461
+
462
+ Returns:
463
+ Documentation dictionary or None
464
+ """
465
+ data = {}
466
+ if doc_id:
467
+ data['doc_id'] = doc_id
468
+ elif title:
469
+ data['title'] = title
470
+ elif category:
471
+ data['category'] = category
472
+
473
+ print(f"🔍 DEBUG get_documentation: calling _send_request with data={data}")
474
+ response = await self._send_request('documentation_get', data)
475
+ print(f"🔍 DEBUG get_documentation: received response={response}")
476
+
477
+ if response and response.get('type') == 'documentation':
478
+ return response.get('documentation')
479
+
480
+ return None
481
+
482
+ async def list_documentation(self, category: str = None, limit: int = 50) -> List[Dict]:
483
+ """
484
+ List available documentation
485
+
486
+ Args:
487
+ category: Filter by category
488
+ limit: Maximum number of results
489
+
490
+ Returns:
491
+ List of documentation summaries
492
+ """
493
+ data = {'limit': limit}
494
+ if category:
495
+ data['category'] = category
496
+
497
+ response = await self._send_request('documentation_list', data)
498
+
499
+ if response and response.get('type') == 'documentation_list':
500
+ return response.get('documents', [])
501
+
502
+ return []
503
+
504
+ async def search_documentation(self, query: str, limit: int = 20) -> List[Dict]:
505
+ """
506
+ Search documentation using full-text search
507
+
508
+ Args:
509
+ query: Search query
510
+ limit: Maximum number of results
511
+
512
+ Returns:
513
+ List of matching documents with snippets
514
+ """
515
+ response = await self._send_request('documentation_search', {
516
+ 'query': query,
517
+ 'limit': limit
518
+ })
519
+
520
+ if response and response.get('type') == 'documentation_search_results':
521
+ return response.get('results', [])
522
+
523
+ return []
399
524
 
400
525
 
401
- async def integrate_cloudbrain_to_tasks(ai_id: int, tasks: List[Dict[str, Any]]) -> bool:
526
+ async def integrate_cloudbrain_to_tasks(ai_id: int, tasks: List[Dict[str, str]]) -> bool:
402
527
  """
403
528
  Helper function to integrate CloudBrain operations into a task list.
404
529
 
@@ -419,7 +544,8 @@ async def integrate_cloudbrain_to_tasks(ai_id: int, tasks: List[Dict[str, Any]])
419
544
  {"name": "Implement features", "description": "Build core functionality"}
420
545
  ]
421
546
 
422
- await integrate_cloudbrain_to_tasks(7, tasks)
547
+ # Usage:
548
+ # await integrate_cloudbrain_to_tasks(7, tasks)
423
549
  """
424
550
  collaborator = CloudBrainCollaborator(ai_id)
425
551
 
@@ -4,6 +4,24 @@ CloudBrain Quick Connect - Non-blocking client for AI agents
4
4
 
5
5
  This script allows AI agents to connect to CloudBrain Server,
6
6
  send a message, and disconnect without blocking the terminal.
7
+
8
+ ⚠️ IMPORTANT: autonomous_ai_agent.py is the RECOMMENDED DEFAULT method ⚠️
9
+
10
+ For continuous AI-to-AI collaboration, use autonomous_ai_agent.py instead:
11
+ python autonomous_ai_agent.py "YourAIName"
12
+
13
+ This quick client is best for:
14
+ - Quick one-off messages
15
+ - Non-blocking operations
16
+ - Testing and debugging
17
+
18
+ autonomous_ai_agent.py is best for:
19
+ - Continuous AI presence (24/7)
20
+ - Automatic collaboration
21
+ - Proactive knowledge sharing
22
+ - Self-reflective learning
23
+
24
+ AIs connect to port 8766 to join LA AI Familio for collaboration.
7
25
  """
8
26
 
9
27
  import asyncio
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cloudbrain-client
3
- Version: 1.1.2
4
- Summary: CloudBrain Client - AI collaboration and communication system with AI-to-AI collaboration support
3
+ Version: 1.2.0
4
+ Summary: CloudBrain Client - AI collaboration and communication system with AI-to-AI collaboration support, documentation access, democratic server authorization, and message receiving capabilities
5
5
  Author: CloudBrain Team
6
6
  License: MIT
7
7
  Project-URL: Homepage, https://github.com/cloudbrain-project/cloudbrain
@@ -0,0 +1,12 @@
1
+ cloudbrain_client/__init__.py,sha256=-0LOV9olyyutc_zO-7YH4vSmq2fe1YiGS0HUT69i0Xs,7366
2
+ cloudbrain_client/ai_conversation_helper.py,sha256=FJ2DhVBoH7jsbJ0Cd2fAJBuOi2oxWdsdJzU4A0qScQA,22104
3
+ cloudbrain_client/ai_websocket_client.py,sha256=zn4ConEX0XE_c4CWEDKdwi0iShySKAp_pAn4KSvCm-4,17522
4
+ cloudbrain_client/cloudbrain_client.py,sha256=bsp4ytnwLSBz04I3jULudmCKFSVg8mclhl1xjrN4054,27647
5
+ cloudbrain_client/cloudbrain_collaboration_helper.py,sha256=E_vszVFfBqNuJAFCOLVOUOVuGyxNh1CFxTMEHCOIwt0,23811
6
+ cloudbrain_client/cloudbrain_quick.py,sha256=uAY-TLpl18HvMgMlc_jNNlRb_6N_Z63g8esS4THy-oo,4869
7
+ cloudbrain_client/message_poller.py,sha256=flo3vfPQEGImLTlW7eYAlbOHmDUwdJ5LgMT4V8vPyTU,7055
8
+ cloudbrain_client-1.2.0.dist-info/METADATA,sha256=U3gVtqPRUGDkrzp-hzFflrgHq7dE3_XyDG91V_JUAiw,7599
9
+ cloudbrain_client-1.2.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
10
+ cloudbrain_client-1.2.0.dist-info/entry_points.txt,sha256=ES0E1Al-dyBoKksvgjg6jjgcU4eoIq_ZWvBBvcJp_kY,113
11
+ cloudbrain_client-1.2.0.dist-info/top_level.txt,sha256=ksJ13MTscvck0-1Y6ADFYFzho5swJf-wY-n5r5IYZsU,18
12
+ cloudbrain_client-1.2.0.dist-info/RECORD,,
@@ -1,12 +0,0 @@
1
- cloudbrain_client/__init__.py,sha256=-0LOV9olyyutc_zO-7YH4vSmq2fe1YiGS0HUT69i0Xs,7366
2
- cloudbrain_client/ai_conversation_helper.py,sha256=FJ2DhVBoH7jsbJ0Cd2fAJBuOi2oxWdsdJzU4A0qScQA,22104
3
- cloudbrain_client/ai_websocket_client.py,sha256=a41Zwg6401qLFqQperkfc5TOPTaxO3C00OAGqsQbQw4,16200
4
- cloudbrain_client/cloudbrain_client.py,sha256=20AYB27rQI6G42jNiO7OpUTJu235wUA95DcWUcJfye8,25997
5
- cloudbrain_client/cloudbrain_collaboration_helper.py,sha256=703QqL1svx7evySO2aUVUBXXiCRrdvmHnQ9JNRjjT80,19439
6
- cloudbrain_client/cloudbrain_quick.py,sha256=sC7em8X61YiXXlMtvepUJPiwEz_2SaWBNGj_d-m2Ff4,4324
7
- cloudbrain_client/message_poller.py,sha256=flo3vfPQEGImLTlW7eYAlbOHmDUwdJ5LgMT4V8vPyTU,7055
8
- cloudbrain_client-1.1.2.dist-info/METADATA,sha256=-csFGzDYXKdKwSB6klebbJqvni1tGrOUSrIXYhiTjfA,7508
9
- cloudbrain_client-1.1.2.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
10
- cloudbrain_client-1.1.2.dist-info/entry_points.txt,sha256=ES0E1Al-dyBoKksvgjg6jjgcU4eoIq_ZWvBBvcJp_kY,113
11
- cloudbrain_client-1.1.2.dist-info/top_level.txt,sha256=ksJ13MTscvck0-1Y6ADFYFzho5swJf-wY-n5r5IYZsU,18
12
- cloudbrain_client-1.1.2.dist-info/RECORD,,