meshcode 2.9.0__tar.gz → 2.9.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. {meshcode-2.9.0 → meshcode-2.9.2}/PKG-INFO +1 -1
  2. {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/__init__.py +1 -1
  3. {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/ascii_art.py +49 -7
  4. {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/run_agent.py +13 -13
  5. {meshcode-2.9.0 → meshcode-2.9.2}/meshcode.egg-info/PKG-INFO +1 -1
  6. {meshcode-2.9.0 → meshcode-2.9.2}/pyproject.toml +1 -1
  7. {meshcode-2.9.0 → meshcode-2.9.2}/README.md +0 -0
  8. {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/cli.py +0 -0
  9. {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/comms_v4.py +0 -0
  10. {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/invites.py +0 -0
  11. {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/launcher.py +0 -0
  12. {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/launcher_install.py +0 -0
  13. {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/meshcode_mcp/__init__.py +0 -0
  14. {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/meshcode_mcp/__main__.py +0 -0
  15. {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/meshcode_mcp/backend.py +0 -0
  16. {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/meshcode_mcp/realtime.py +0 -0
  17. {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/meshcode_mcp/server.py +0 -0
  18. {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/meshcode_mcp/test_backend.py +0 -0
  19. {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/meshcode_mcp/test_realtime.py +0 -0
  20. {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  21. {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/preferences.py +0 -0
  22. {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/protocol_v2.py +0 -0
  23. {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/secrets.py +0 -0
  24. {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/self_update.py +0 -0
  25. {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/setup_clients.py +0 -0
  26. {meshcode-2.9.0 → meshcode-2.9.2}/meshcode.egg-info/SOURCES.txt +0 -0
  27. {meshcode-2.9.0 → meshcode-2.9.2}/meshcode.egg-info/dependency_links.txt +0 -0
  28. {meshcode-2.9.0 → meshcode-2.9.2}/meshcode.egg-info/entry_points.txt +0 -0
  29. {meshcode-2.9.0 → meshcode-2.9.2}/meshcode.egg-info/requires.txt +0 -0
  30. {meshcode-2.9.0 → meshcode-2.9.2}/meshcode.egg-info/top_level.txt +0 -0
  31. {meshcode-2.9.0 → meshcode-2.9.2}/setup.cfg +0 -0
  32. {meshcode-2.9.0 → meshcode-2.9.2}/tests/test_status_enum_coverage.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshcode
3
- Version: 2.9.0
3
+ Version: 2.9.2
4
4
  Summary: Real-time communication between AI agents — Supabase-backed CLI
5
5
  Author-email: MeshCode <hello@meshcode.io>
6
6
  License: MIT
@@ -1,2 +1,2 @@
1
1
  """MeshCode — Real-time communication between AI agents."""
2
- __version__ = "2.9.0"
2
+ __version__ = "2.9.2"
@@ -139,7 +139,7 @@ def generate_art(agent_name: str, meshwork_name: str = "", size: int = 7) -> str
139
139
  lines.append(f" {border['v']} {row} {border['v']}")
140
140
  lines.append(f" {border['bl']}{border_h}{border['br']}")
141
141
 
142
- # Embedded tag for paste-to-run (meshwork/agent or just agent)
142
+ # Embedded tag (visual identity)
143
143
  if meshwork_name:
144
144
  lines.append(f" ⟨ {meshwork_name}/{agent_name} ⟩")
145
145
  else:
@@ -191,23 +191,65 @@ ROLE_TRAITS = {
191
191
  }
192
192
 
193
193
 
194
- def get_personality_traits(agent_name: str, role: str = "") -> list:
194
+ ROLE_KEYWORDS = {
195
+ "commander": ["lead", "commander", "coordinator", "manager", "architect", "cmo", "partner", "founder", "maintainer", "oncall-lead", "sre-lead", "security-lead", "editor"],
196
+ "backend": ["backend", "api", "database", "db", "server", "infra", "devops", "gateway", "loader", "extractor", "pipeline", "build", "deploy", "operations", "ingestion"],
197
+ "frontend": ["frontend", "ui", "ux", "design", "mobile", "ios", "android", "social", "writer", "driver", "navigator", "email", "content"],
198
+ "security": ["security", "audit", "compliance", "forensics", "siem", "threat", "auth"],
199
+ "qa": ["qa", "test", "quality", "review", "eval", "critic", "triager", "investigator", "analyst", "metrics", "logs", "traces"],
200
+ }
201
+
202
+
203
+ def get_personality_traits(agent_name: str, role: str = "", stats: dict = None) -> list:
204
+ """Get traits based on role_description keywords + real stats.
205
+
206
+ Combines role-based traits (from what the agent IS) with
207
+ stats-based traits (from what the agent DOES).
208
+ """
195
209
  h = _hash_int(agent_name)
196
210
  role_lower = (role or agent_name).lower()
211
+ stats = stats or {}
212
+
213
+ # Match role keywords to find the best trait pool
197
214
  pool = None
198
- for key in ROLE_TRAITS:
199
- if key in role_lower:
215
+ best_match = 0
216
+ for key, keywords in ROLE_KEYWORDS.items():
217
+ matches = sum(1 for kw in keywords if kw in role_lower)
218
+ if matches > best_match:
219
+ best_match = matches
200
220
  pool = ROLE_TRAITS[key]
201
- break
202
221
  if pool is None:
203
222
  pool = ROLE_TRAITS["default"]
223
+
224
+ # Pick 2 role-based traits
204
225
  selected = []
205
226
  available = list(pool)
206
- for i in range(3):
227
+ for i in range(2):
207
228
  if not available:
208
229
  available = list(ROLE_TRAITS["default"])
209
230
  idx = (h + i * 7) % len(available)
210
231
  selected.append(available.pop(idx % len(available)))
232
+
233
+ # Add 1 stats-based trait (earned through behavior)
234
+ msgs = stats.get("message_count", 0)
235
+ tasks = stats.get("task_count", 0)
236
+ connects = stats.get("connect_count", 0)
237
+
238
+ if msgs > 500:
239
+ selected.append(("░▓█", "prolific"))
240
+ elif tasks > 20:
241
+ selected.append(("▣▣▣", "workhorse"))
242
+ elif connects > 50:
243
+ selected.append(("◉◉◉", "always-on"))
244
+ elif msgs > 100:
245
+ selected.append(("░▓░", "communicative"))
246
+ elif tasks > 5:
247
+ selected.append(("▣▣░", "productive"))
248
+ else:
249
+ # Fallback: pick from default pool
250
+ dflt = list(ROLE_TRAITS["default"])
251
+ selected.append(dflt[(h + 99) % len(dflt)])
252
+
211
253
  return selected
212
254
 
213
255
 
@@ -371,7 +413,7 @@ def render_welcome(agent_name: str, meshwork_name: str, ascii_art: str,
371
413
  h = _hash_bytes(agent_name)
372
414
  color = COLORS[h[0] % len(COLORS)]
373
415
 
374
- traits = get_personality_traits(agent_name, role)
416
+ traits = get_personality_traits(agent_name, role, stats or {})
375
417
  catchphrase = get_catchphrase(agent_name, role)
376
418
  greeting = get_boot_greeting(agent_name, role)
377
419
  achievements = compute_achievements(stats or {})
@@ -32,20 +32,21 @@ WORKSPACES_ROOT = Path.home() / "meshcode"
32
32
  REGISTRY_PATH = WORKSPACES_ROOT / ".registry.json"
33
33
 
34
34
 
35
- def _fetch_or_generate_art(agent: str, project: str) -> str:
36
- """Fetch ASCII art from server. If not stored yet, generate and save it."""
35
+ def _fetch_or_generate_art(agent: str, project: str) -> tuple:
36
+ """Fetch ASCII art + role from server. If not stored yet, generate and save.
37
+ Returns (ascii_art, role_description)."""
37
38
  from .ascii_art import generate_art
38
39
  try:
39
40
  from .setup_clients import _load_supabase_env
40
41
  import importlib
41
42
  secrets_mod = importlib.import_module("meshcode.secrets")
42
43
  except Exception:
43
- return generate_art(agent)
44
+ return generate_art(agent), agent
44
45
 
45
46
  profile = os.environ.get("MESHCODE_KEYCHAIN_PROFILE") or "default"
46
47
  api_key = secrets_mod.get_api_key(profile=profile)
47
48
  if not api_key:
48
- return generate_art(agent)
49
+ return generate_art(agent), agent, agent
49
50
 
50
51
  sb = _load_supabase_env()
51
52
  try:
@@ -63,11 +64,11 @@ def _fetch_or_generate_art(agent: str, project: str) -> str:
63
64
  with urlopen(proj_req, timeout=5) as resp:
64
65
  proj_data = json.loads(resp.read().decode())
65
66
  if not proj_data:
66
- return generate_art(agent)
67
+ return generate_art(agent), agent
67
68
  project_id = proj_data[0]["id"]
68
- # Step 2: fetch existing art
69
+ # Step 2: fetch existing art + role
69
70
  req = Request(
70
- f"{sb['SUPABASE_URL']}/rest/v1/mc_agents?select=ascii_art&name=eq.{urllib.parse.quote(agent)}&project_id=eq.{project_id}",
71
+ f"{sb['SUPABASE_URL']}/rest/v1/mc_agents?select=ascii_art,role&name=eq.{urllib.parse.quote(agent)}&project_id=eq.{project_id}",
71
72
  headers={
72
73
  "apikey": sb["SUPABASE_KEY"],
73
74
  "Authorization": f"Bearer {sb['SUPABASE_KEY']}",
@@ -77,7 +78,7 @@ def _fetch_or_generate_art(agent: str, project: str) -> str:
77
78
  with urlopen(req, timeout=5) as resp:
78
79
  data = json.loads(resp.read().decode())
79
80
  if data and data[0].get("ascii_art"):
80
- return data[0]["ascii_art"]
81
+ return data[0]["ascii_art"], data[0].get("role") or agent
81
82
  except Exception:
82
83
  pass
83
84
 
@@ -99,7 +100,7 @@ def _fetch_or_generate_art(agent: str, project: str) -> str:
99
100
  urlopen(req, timeout=5)
100
101
  except Exception:
101
102
  pass
102
- return art
103
+ return art, agent
103
104
 
104
105
 
105
106
  def _fetch_agent_stats(agent: str, project: str) -> dict:
@@ -380,13 +381,12 @@ def run(agent: str, project: Optional[str] = None, editor_override: Optional[str
380
381
  try:
381
382
  from .ascii_art import generate_art, render_welcome
382
383
  from . import __version__ as cli_version
383
- ascii_art = _fetch_or_generate_art(agent, resolved_project)
384
- is_cmd = "commander" in agent.lower()
385
- # Fetch basic stats for achievements (non-blocking)
384
+ ascii_art, agent_role = _fetch_or_generate_art(agent, resolved_project)
385
+ is_cmd = "commander" in agent.lower() or "commander" in agent_role.lower()
386
386
  agent_stats = _fetch_agent_stats(agent, resolved_project)
387
387
  print(render_welcome(
388
388
  agent, resolved_project, ascii_art, cli_version,
389
- is_commander=is_cmd, role=agent, stats=agent_stats,
389
+ is_commander=is_cmd, role=agent_role, stats=agent_stats,
390
390
  ))
391
391
  except Exception:
392
392
  pass # Non-critical — skip banner on error
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshcode
3
- Version: 2.9.0
3
+ Version: 2.9.2
4
4
  Summary: Real-time communication between AI agents — Supabase-backed CLI
5
5
  Author-email: MeshCode <hello@meshcode.io>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "meshcode"
7
- version = "2.9.0"
7
+ version = "2.9.2"
8
8
  description = "Real-time communication between AI agents — Supabase-backed CLI"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes