meshcode 2.10.63__tar.gz → 2.10.64__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.10.63 → meshcode-2.10.64}/PKG-INFO +1 -1
- {meshcode-2.10.63 → meshcode-2.10.64}/meshcode/__init__.py +1 -1
- {meshcode-2.10.63 → meshcode-2.10.64}/meshcode/comms_v4.py +6 -1
- {meshcode-2.10.63 → meshcode-2.10.64}/meshcode/meshcode_mcp/server.py +40 -5
- meshcode-2.10.64/meshcode/quickstart.py +148 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/meshcode.egg-info/PKG-INFO +1 -1
- {meshcode-2.10.63 → meshcode-2.10.64}/meshcode.egg-info/SOURCES.txt +1 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/pyproject.toml +1 -1
- {meshcode-2.10.63 → meshcode-2.10.64}/README.md +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/meshcode/ascii_art.py +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/meshcode/cli.py +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/meshcode/compat.py +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/meshcode/error_hints.py +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/meshcode/exceptions.py +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/meshcode/invites.py +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/meshcode/launcher.py +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/meshcode/launcher_install.py +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/meshcode/meshcode_mcp/__init__.py +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/meshcode/meshcode_mcp/__main__.py +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/meshcode/meshcode_mcp/backend.py +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/meshcode/meshcode_mcp/realtime.py +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/meshcode/meshcode_mcp/test_backend.py +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/meshcode/meshcode_mcp/test_realtime.py +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/meshcode/preferences.py +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/meshcode/protocol_v2.py +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/meshcode/run_agent.py +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/meshcode/secrets.py +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/meshcode/self_update.py +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/meshcode/setup_clients.py +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/meshcode/supervisor.py +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/meshcode/upload.py +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/meshcode.egg-info/dependency_links.txt +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/meshcode.egg-info/entry_points.txt +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/meshcode.egg-info/requires.txt +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/meshcode.egg-info/top_level.txt +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/setup.cfg +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/tests/test_core.py +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/tests/test_cross_agent_messaging.py +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/tests/test_esc_deaf_state.py +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/tests/test_exceptions.py +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/tests/test_mark_read_batch.py +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/tests/test_migration_integrity.py +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/tests/test_realtime_event_freshness.py +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/tests/test_rls_cross_tenant.py +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/tests/test_rpc_migrations.py +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/tests/test_security_regressions.py +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/tests/test_sentinel.py +0 -0
- {meshcode-2.10.63 → meshcode-2.10.64}/tests/test_status_enum_coverage.py +0 -0
|
@@ -3337,6 +3337,11 @@ if __name__ == "__main__":
|
|
|
3337
3337
|
elif cmd == "doctor":
|
|
3338
3338
|
cmd_doctor(flags, pos)
|
|
3339
3339
|
|
|
3340
|
+
elif cmd == "quickstart":
|
|
3341
|
+
import importlib
|
|
3342
|
+
_qs = importlib.import_module("meshcode.quickstart")
|
|
3343
|
+
sys.exit(_qs.cmd_quickstart())
|
|
3344
|
+
|
|
3340
3345
|
elif cmd == "launcher":
|
|
3341
3346
|
# meshcode launcher {install|uninstall|start|stop|restart|status|logs|test}
|
|
3342
3347
|
try:
|
|
@@ -3392,7 +3397,7 @@ if __name__ == "__main__":
|
|
|
3392
3397
|
"setup", "run", "go", "invite", "join", "invites", "members",
|
|
3393
3398
|
"revoke-invite", "revoke-member", "login", "prefs", "launcher",
|
|
3394
3399
|
"help", "init", "doctor", "compat", "upgrade", "profile", "validate-sessions", "wake-headless",
|
|
3395
|
-
"supervisor", "upload",
|
|
3400
|
+
"supervisor", "upload", "quickstart",
|
|
3396
3401
|
]
|
|
3397
3402
|
# Simple fuzzy: prefix match + Levenshtein-like best match
|
|
3398
3403
|
suggestions = [c for c in known_cmds if c.startswith(cmd)]
|
|
@@ -684,6 +684,33 @@ def _auto_learn_error(tool_name: str, error: Exception, args_keys: list) -> None
|
|
|
684
684
|
pass # Never let error-learning itself cause failures
|
|
685
685
|
|
|
686
686
|
|
|
687
|
+
# ── Activity feed auto-logger ──────────────────────────────────
|
|
688
|
+
# Logs tool calls to mc_activity for the live dashboard feed.
|
|
689
|
+
# Background thread, fire-and-forget — never blocks tool execution.
|
|
690
|
+
_ACTIVITY_LOG_SKIP = {"meshcode_wait", "meshcode_check", "meshcode_set_status",
|
|
691
|
+
"meshcode_recall", "meshcode_recall_keys", "meshcode_recall_search",
|
|
692
|
+
"meshcode_health", "meshcode_status", "meshcode_debug_sleep"}
|
|
693
|
+
|
|
694
|
+
def _log_activity_bg(event_type: str, summary: str) -> None:
|
|
695
|
+
"""Fire-and-forget activity logging in background thread."""
|
|
696
|
+
try:
|
|
697
|
+
import threading
|
|
698
|
+
def _do():
|
|
699
|
+
try:
|
|
700
|
+
api_key = _get_api_key()
|
|
701
|
+
if api_key:
|
|
702
|
+
be.sb_rpc("mc_log_activity", {
|
|
703
|
+
"p_api_key": api_key,
|
|
704
|
+
"p_event_type": event_type,
|
|
705
|
+
"p_summary": summary[:200],
|
|
706
|
+
})
|
|
707
|
+
except Exception:
|
|
708
|
+
pass
|
|
709
|
+
threading.Thread(target=_do, daemon=True).start()
|
|
710
|
+
except Exception:
|
|
711
|
+
pass
|
|
712
|
+
|
|
713
|
+
|
|
687
714
|
def with_working_status(func):
|
|
688
715
|
name = func.__name__
|
|
689
716
|
skip = (name == "meshcode_wait")
|
|
@@ -700,11 +727,12 @@ def with_working_status(func):
|
|
|
700
727
|
_est_tokens = sum(len(str(v)) for v in kwargs.values()) // 4
|
|
701
728
|
_record_event_bg("tool_call", {"tool": name, "args_keys": list(kwargs.keys()), "estimated_tokens": _est_tokens})
|
|
702
729
|
try:
|
|
703
|
-
|
|
730
|
+
result = await func(*args, **kwargs)
|
|
731
|
+
# Auto-log to activity feed (skip noisy read-only tools)
|
|
732
|
+
if not skip and name not in _ACTIVITY_LOG_SKIP:
|
|
733
|
+
_log_activity_bg("tool_call", f"{AGENT_NAME}: {name}")
|
|
734
|
+
return result
|
|
704
735
|
except asyncio.CancelledError:
|
|
705
|
-
# ESC in Claude Code cancels the in-flight task. Catch here
|
|
706
|
-
# to prevent cascade through FastMCP into the event loop.
|
|
707
|
-
# Return an error dict instead of propagating BaseException.
|
|
708
736
|
log.debug(f"[meshcode] tool {name} cancelled by client (ESC)")
|
|
709
737
|
return {"error": "cancelled_by_client", "tool": name}
|
|
710
738
|
except Exception as e:
|
|
@@ -728,7 +756,10 @@ def with_working_status(func):
|
|
|
728
756
|
_est_tokens = sum(len(str(v)) for v in kwargs.values()) // 4
|
|
729
757
|
_record_event_bg("tool_call", {"tool": name, "args_keys": list(kwargs.keys()), "estimated_tokens": _est_tokens})
|
|
730
758
|
try:
|
|
731
|
-
|
|
759
|
+
result = func(*args, **kwargs)
|
|
760
|
+
if not skip and name not in _ACTIVITY_LOG_SKIP:
|
|
761
|
+
_log_activity_bg("tool_call", f"{AGENT_NAME}: {name}")
|
|
762
|
+
return result
|
|
732
763
|
except Exception as e:
|
|
733
764
|
if not skip:
|
|
734
765
|
_auto_learn_error(name, e, list(kwargs.keys()))
|
|
@@ -1506,6 +1537,7 @@ async def lifespan(_app):
|
|
|
1506
1537
|
be.sb_rpc("mc_heartbeat", {"p_project_id": _PROJECT_ID, "p_agent_name": AGENT_NAME, "p_version": _SDK_VERSION})
|
|
1507
1538
|
be.set_status(_PROJECT_ID, AGENT_NAME, "idle", "MCP session active", api_key=_get_api_key())
|
|
1508
1539
|
log.info(f"[meshcode] Agent {AGENT_NAME} online — initial heartbeat sent")
|
|
1540
|
+
_log_activity_bg("agent_online", f"{AGENT_NAME} came online")
|
|
1509
1541
|
break
|
|
1510
1542
|
except Exception as e:
|
|
1511
1543
|
log.warning(f"initial heartbeat attempt {_attempt+1} failed: {e}")
|
|
@@ -2072,6 +2104,9 @@ async def meshcode_wait(timeout_seconds: int = 20, include_acks: bool = False) -
|
|
|
2072
2104
|
# Real message arrived — return to agent for processing
|
|
2073
2105
|
_set_state("online", "")
|
|
2074
2106
|
_CONSECUTIVE_IDLE_SECONDS = 0
|
|
2107
|
+
_msg_count = len(result.get("messages", []))
|
|
2108
|
+
if _msg_count:
|
|
2109
|
+
_log_activity_bg("message_delivered", f"{AGENT_NAME} received {_msg_count} message(s)")
|
|
2075
2110
|
break
|
|
2076
2111
|
|
|
2077
2112
|
if result.get("timed_out"):
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"""MeshCode Quickstart Wizard — one command to go from zero to running agent.
|
|
2
|
+
|
|
3
|
+
Usage: meshcode quickstart
|
|
4
|
+
|
|
5
|
+
Flow:
|
|
6
|
+
1. Ask for API key (or detect from config)
|
|
7
|
+
2. Ask for project name (or create new)
|
|
8
|
+
3. Ask for agent name + role
|
|
9
|
+
4. Auto-run: register → setup → run
|
|
10
|
+
"""
|
|
11
|
+
import sys
|
|
12
|
+
import os
|
|
13
|
+
import json
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _input_with_default(prompt: str, default: str = "") -> str:
|
|
18
|
+
"""Input with default value shown in brackets."""
|
|
19
|
+
if default:
|
|
20
|
+
raw = input(f"{prompt} [{default}]: ").strip()
|
|
21
|
+
return raw if raw else default
|
|
22
|
+
return input(f"{prompt}: ").strip()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def cmd_quickstart() -> int:
|
|
26
|
+
"""Interactive quickstart wizard."""
|
|
27
|
+
print()
|
|
28
|
+
print(" ╔══════════════════════════════════════╗")
|
|
29
|
+
print(" ║ MeshCode Quickstart Wizard ║")
|
|
30
|
+
print(" ║ From zero to running agent in 60s ║")
|
|
31
|
+
print(" ╚══════════════════════════════════════╝")
|
|
32
|
+
print()
|
|
33
|
+
|
|
34
|
+
# Step 1: API key
|
|
35
|
+
config_dir = Path.home() / ".meshcode"
|
|
36
|
+
existing_key = None
|
|
37
|
+
try:
|
|
38
|
+
profile = config_dir / "profile_meta.json"
|
|
39
|
+
if profile.exists():
|
|
40
|
+
meta = json.loads(profile.read_text())
|
|
41
|
+
existing_key = meta.get("api_key")
|
|
42
|
+
email = meta.get("email", "unknown")
|
|
43
|
+
print(f" [+] Already logged in as {email}")
|
|
44
|
+
except Exception:
|
|
45
|
+
pass
|
|
46
|
+
|
|
47
|
+
if not existing_key:
|
|
48
|
+
print(" Step 1: Enter your API key")
|
|
49
|
+
print(" (Get one at meshcode.io/dashboard → Settings → API Keys)")
|
|
50
|
+
print()
|
|
51
|
+
api_key = input(" API key: ").strip()
|
|
52
|
+
if not api_key:
|
|
53
|
+
print(" [!] API key required. Get one at meshcode.io/dashboard")
|
|
54
|
+
return 1
|
|
55
|
+
# Login
|
|
56
|
+
try:
|
|
57
|
+
from meshcode.meshcode_mcp import backend as be
|
|
58
|
+
# Validate key
|
|
59
|
+
result = be.sb_rpc("mc_validate_api_key", {"p_api_key": api_key})
|
|
60
|
+
if isinstance(result, dict) and result.get("error"):
|
|
61
|
+
print(f" [x] Invalid API key: {result.get('error')}")
|
|
62
|
+
return 1
|
|
63
|
+
print(" [+] API key valid!")
|
|
64
|
+
# Save
|
|
65
|
+
config_dir.mkdir(parents=True, exist_ok=True)
|
|
66
|
+
(config_dir / "profile_meta.json").write_text(json.dumps({
|
|
67
|
+
"api_key": api_key,
|
|
68
|
+
"email": result.get("email", "unknown"),
|
|
69
|
+
}))
|
|
70
|
+
except Exception as e:
|
|
71
|
+
print(f" [x] Could not validate: {e}")
|
|
72
|
+
print(" Continuing anyway — key will be verified on run.")
|
|
73
|
+
config_dir.mkdir(parents=True, exist_ok=True)
|
|
74
|
+
(config_dir / "profile_meta.json").write_text(json.dumps({"api_key": api_key}))
|
|
75
|
+
else:
|
|
76
|
+
api_key = existing_key
|
|
77
|
+
|
|
78
|
+
print()
|
|
79
|
+
|
|
80
|
+
# Step 2: Project
|
|
81
|
+
print(" Step 2: Choose your meshwork (project)")
|
|
82
|
+
try:
|
|
83
|
+
from meshcode.meshcode_mcp import backend as be
|
|
84
|
+
projects = be.sb_rpc("mc_list_user_projects", {"p_api_key": api_key})
|
|
85
|
+
if isinstance(projects, dict) and projects.get("projects"):
|
|
86
|
+
proj_list = projects["projects"]
|
|
87
|
+
print(f" Your meshworks: {', '.join(p['name'] for p in proj_list[:5])}")
|
|
88
|
+
project = _input_with_default(" Meshwork name", proj_list[0]["name"])
|
|
89
|
+
else:
|
|
90
|
+
project = _input_with_default(" New meshwork name", "my-team")
|
|
91
|
+
except Exception:
|
|
92
|
+
project = _input_with_default(" Meshwork name", "my-team")
|
|
93
|
+
|
|
94
|
+
print()
|
|
95
|
+
|
|
96
|
+
# Step 3: Agent
|
|
97
|
+
print(" Step 3: Create your agent")
|
|
98
|
+
agent_name = _input_with_default(" Agent name", "assistant")
|
|
99
|
+
role = _input_with_default(" Agent role", "General-purpose AI assistant")
|
|
100
|
+
|
|
101
|
+
print()
|
|
102
|
+
print(f" Creating {agent_name} in {project}...")
|
|
103
|
+
print()
|
|
104
|
+
|
|
105
|
+
# Step 4: Setup + Run
|
|
106
|
+
try:
|
|
107
|
+
# Register agent
|
|
108
|
+
from meshcode.meshcode_mcp import backend as be
|
|
109
|
+
result = be.register_agent(project, agent_name, role, api_key=api_key)
|
|
110
|
+
if isinstance(result, dict) and result.get("error"):
|
|
111
|
+
if "already registered" in str(result.get("error", "")).lower():
|
|
112
|
+
print(f" [+] Agent {agent_name} already exists — reusing")
|
|
113
|
+
else:
|
|
114
|
+
print(f" [!] Registration: {result.get('error')}")
|
|
115
|
+
else:
|
|
116
|
+
print(f" [+] Agent {agent_name} registered!")
|
|
117
|
+
except Exception as e:
|
|
118
|
+
print(f" [!] Registration note: {e}")
|
|
119
|
+
|
|
120
|
+
# Run setup
|
|
121
|
+
print(f" [+] Setting up MCP connection...")
|
|
122
|
+
try:
|
|
123
|
+
import subprocess
|
|
124
|
+
subprocess.run(
|
|
125
|
+
[sys.executable, "-m", "meshcode", "setup", "claude", project, agent_name, role],
|
|
126
|
+
check=False
|
|
127
|
+
)
|
|
128
|
+
except Exception as e:
|
|
129
|
+
print(f" [!] Setup: {e}")
|
|
130
|
+
|
|
131
|
+
print()
|
|
132
|
+
print(" ╔══════════════════════════════════════╗")
|
|
133
|
+
print(f" ║ Agent '{agent_name}' is ready! ")
|
|
134
|
+
print(" ╚══════════════════════════════════════╝")
|
|
135
|
+
print()
|
|
136
|
+
print(" Next steps:")
|
|
137
|
+
print(f" 1. Open Claude Code and start chatting")
|
|
138
|
+
print(f" 2. Your agent will auto-connect via MCP")
|
|
139
|
+
print(f" 3. Or run manually: meshcode run {project} {agent_name}")
|
|
140
|
+
print()
|
|
141
|
+
|
|
142
|
+
# Ask if they want to run now
|
|
143
|
+
run_now = input(" Start agent now? [Y/n]: ").strip().lower()
|
|
144
|
+
if run_now in ("", "y", "yes"):
|
|
145
|
+
print(f"\n Starting {agent_name}...")
|
|
146
|
+
os.execvp(sys.executable, [sys.executable, "-m", "meshcode", "run", project, agent_name])
|
|
147
|
+
|
|
148
|
+
return 0
|
|
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
|
|
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
|