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.
- {meshcode-2.9.0 → meshcode-2.9.2}/PKG-INFO +1 -1
- {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/__init__.py +1 -1
- {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/ascii_art.py +49 -7
- {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/run_agent.py +13 -13
- {meshcode-2.9.0 → meshcode-2.9.2}/meshcode.egg-info/PKG-INFO +1 -1
- {meshcode-2.9.0 → meshcode-2.9.2}/pyproject.toml +1 -1
- {meshcode-2.9.0 → meshcode-2.9.2}/README.md +0 -0
- {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/cli.py +0 -0
- {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/comms_v4.py +0 -0
- {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/invites.py +0 -0
- {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/launcher.py +0 -0
- {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/launcher_install.py +0 -0
- {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/meshcode_mcp/__init__.py +0 -0
- {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/meshcode_mcp/__main__.py +0 -0
- {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/meshcode_mcp/backend.py +0 -0
- {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/meshcode_mcp/realtime.py +0 -0
- {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/meshcode_mcp/server.py +0 -0
- {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/meshcode_mcp/test_backend.py +0 -0
- {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/meshcode_mcp/test_realtime.py +0 -0
- {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
- {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/preferences.py +0 -0
- {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/protocol_v2.py +0 -0
- {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/secrets.py +0 -0
- {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/self_update.py +0 -0
- {meshcode-2.9.0 → meshcode-2.9.2}/meshcode/setup_clients.py +0 -0
- {meshcode-2.9.0 → meshcode-2.9.2}/meshcode.egg-info/SOURCES.txt +0 -0
- {meshcode-2.9.0 → meshcode-2.9.2}/meshcode.egg-info/dependency_links.txt +0 -0
- {meshcode-2.9.0 → meshcode-2.9.2}/meshcode.egg-info/entry_points.txt +0 -0
- {meshcode-2.9.0 → meshcode-2.9.2}/meshcode.egg-info/requires.txt +0 -0
- {meshcode-2.9.0 → meshcode-2.9.2}/meshcode.egg-info/top_level.txt +0 -0
- {meshcode-2.9.0 → meshcode-2.9.2}/setup.cfg +0 -0
- {meshcode-2.9.0 → meshcode-2.9.2}/tests/test_status_enum_coverage.py +0 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""MeshCode — Real-time communication between AI agents."""
|
|
2
|
-
__version__ = "2.9.
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
199
|
-
|
|
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(
|
|
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) ->
|
|
36
|
-
"""Fetch ASCII art from server. If not stored yet, generate and save
|
|
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=
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|