meshcode 2.11.117__tar.gz → 2.11.119__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 (93) hide show
  1. {meshcode-2.11.117 → meshcode-2.11.119}/PKG-INFO +1 -1
  2. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/__init__.py +1 -1
  3. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/meshcode_mcp/server.py +66 -0
  4. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/protocol_handler.py +7 -1
  5. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/upload.py +5 -0
  6. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode.egg-info/PKG-INFO +1 -1
  7. {meshcode-2.11.117 → meshcode-2.11.119}/pyproject.toml +1 -1
  8. {meshcode-2.11.117 → meshcode-2.11.119}/README.md +0 -0
  9. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/__main__.py +0 -0
  10. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/_session_handoff_template.py +0 -0
  11. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/_stop_hook_template.py +0 -0
  12. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/ascii_art.py +0 -0
  13. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/atomic_push.py +0 -0
  14. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/claude_update.py +0 -0
  15. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/cli.py +0 -0
  16. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/comms_v4.py +0 -0
  17. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/compat.py +0 -0
  18. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/daemon.py +0 -0
  19. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/date_parse.py +0 -0
  20. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/doctor.py +0 -0
  21. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/error_hints.py +0 -0
  22. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/exceptions.py +0 -0
  23. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/hooks/__init__.py +0 -0
  24. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/hooks/repo_path_lock.py +0 -0
  25. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/hostd.py +0 -0
  26. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/invites.py +0 -0
  27. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/launcher.py +0 -0
  28. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/launcher_install.py +0 -0
  29. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/meshcode_mcp/__init__.py +0 -0
  30. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/meshcode_mcp/__main__.py +0 -0
  31. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/meshcode_mcp/backend.py +0 -0
  32. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/meshcode_mcp/realtime.py +0 -0
  33. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/meshcode_mcp/sleep_signals.py +0 -0
  34. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/meshcode_mcp/test_backend.py +0 -0
  35. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/meshcode_mcp/test_boot_timing.py +0 -0
  36. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/meshcode_mcp/test_install_guard.py +0 -0
  37. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/meshcode_mcp/test_prefs_claude_version.py +0 -0
  38. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/meshcode_mcp/test_realtime.py +0 -0
  39. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  40. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/preferences.py +0 -0
  41. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/protocol_v2.py +0 -0
  42. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/quickstart.py +0 -0
  43. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/rpc_allowlist.py +0 -0
  44. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/run_agent.py +0 -0
  45. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/scripts/check_secrets.py +0 -0
  46. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/scripts/race_rate_harness.py +0 -0
  47. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/secrets.py +0 -0
  48. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/self_update.py +0 -0
  49. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/setup_clients.py +0 -0
  50. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/supervisor.py +0 -0
  51. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode/up.py +0 -0
  52. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode.egg-info/SOURCES.txt +0 -0
  53. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode.egg-info/dependency_links.txt +0 -0
  54. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode.egg-info/entry_points.txt +0 -0
  55. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode.egg-info/requires.txt +0 -0
  56. {meshcode-2.11.117 → meshcode-2.11.119}/meshcode.egg-info/top_level.txt +0 -0
  57. {meshcode-2.11.117 → meshcode-2.11.119}/setup.cfg +0 -0
  58. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_auto_update_hardening.py +0 -0
  59. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_autonomous_closegap_1.py +0 -0
  60. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_autonomous_closegap_2.py +0 -0
  61. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_autonomous_closegap_3.py +0 -0
  62. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_autonomous_prompt_inject.py +0 -0
  63. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_boot_bug_regression.py +0 -0
  64. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_color_truecolor.py +0 -0
  65. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_core.py +0 -0
  66. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_cross_agent_messaging.py +0 -0
  67. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_date_parse.py +0 -0
  68. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_doctor.py +0 -0
  69. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_epistemic_v1_python_sdk.py +0 -0
  70. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_epistemic_v1_stop_conditions.py +0 -0
  71. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_esc_deaf_state.py +0 -0
  72. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_exceptions.py +0 -0
  73. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_file_upload.py +0 -0
  74. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_init_device_code.py +0 -0
  75. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_install_guard.py +0 -0
  76. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_lease_sigterm_release.py +0 -0
  77. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_mark_read_batch.py +0 -0
  78. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_marketplace_ratings.py +0 -0
  79. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_migration_integrity.py +0 -0
  80. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_realtime_event_freshness.py +0 -0
  81. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_rls_cross_tenant.py +0 -0
  82. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_rpc_grants.py +0 -0
  83. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_rpc_migrations.py +0 -0
  84. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_run_agent_dry_run.py +0 -0
  85. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_run_agent_no_server_import.py +0 -0
  86. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_security_regressions.py +0 -0
  87. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_self_update_user_site.py +0 -0
  88. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_sentinel.py +0 -0
  89. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_setup_path.py +0 -0
  90. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_sleep_signals.py +0 -0
  91. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_status_enum_coverage.py +0 -0
  92. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_stay_on_loop_hook.py +0 -0
  93. {meshcode-2.11.117 → meshcode-2.11.119}/tests/test_wait_open_tasks_contradiction.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshcode
3
- Version: 2.11.117
3
+ Version: 2.11.119
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,5 +1,5 @@
1
1
  """MeshCode — Real-time communication between AI agents."""
2
- __version__ = "2.11.117"
2
+ __version__ = "2.11.119"
3
3
 
4
4
  # Exception hierarchy — eagerly imported (lightweight, no deps)
5
5
  from meshcode.exceptions import ( # noqa: F401
@@ -3460,6 +3460,72 @@ def meshcode_download_file(file_id: str) -> Dict[str, Any]:
3460
3460
  return _consume(content, mime_type, file_name)
3461
3461
 
3462
3462
 
3463
+ @mcp.tool()
3464
+ @with_working_status
3465
+ def meshcode_send_file(to: Union[str, List[str]], file_path: str,
3466
+ caption: str = "", in_reply_to: Optional[str] = None,
3467
+ sensitive: bool = False) -> Dict[str, Any]:
3468
+ """Send a local file to other agent(s) as a mesh attachment — one call
3469
+ instead of the 3-call paste dance (chunked text sends).
3470
+
3471
+ Uploads file_path to mesh storage (mc_register_file + meshcode-files
3472
+ bucket, 50MB cap) and delivers a message whose payload carries the
3473
+ FE-standard attachment shape {file: {file_id, file_name, mime_type}}.
3474
+ The dashboard renders a file chip; agent recipients retrieve content via
3475
+ meshcode_download_file(file_id). `to` accepts the same forms as
3476
+ meshcode_send (agent / CSV / list / agent@meshwork).
3477
+
3478
+ Args:
3479
+ to: recipient(s), meshcode_send forms.
3480
+ file_path: local path of the file to attach.
3481
+ caption: optional message text shown with the chip (default:
3482
+ "file: <name> (<size> bytes)").
3483
+ in_reply_to: optional message UUID to thread under.
3484
+ sensitive: hide from exports (secret/PII payloads).
3485
+ """
3486
+ from pathlib import Path as _P
3487
+ api_key = _get_api_key()
3488
+ if not api_key:
3489
+ return {"error": "no api key", "error_code": "auth_failed"}
3490
+ p = _P(file_path).expanduser()
3491
+ if not p.is_file():
3492
+ return {"error": f"file not found: {file_path}", "error_code": "file_not_found"}
3493
+
3494
+ # Upload reuses the proven CLI path (meshcode/upload.py): mc_register_file
3495
+ # RPC (api_key-authorized, mints file_id + storage_path) then a storage
3496
+ # POST. The POST prefers this workspace's service key when present —
3497
+ # mirrors meshcode_download_file's fallback order; guest workspaces
3498
+ # without it fall back to the anon key (storage policy permitting).
3499
+ from meshcode.upload import upload_file as _upload_file
3500
+ _storage_key = os.environ.get("MESHCODE_SUPABASE_SERVICE_KEY", "") or be.SUPABASE_KEY
3501
+ up = _upload_file(str(p), api_key, be.SUPABASE_URL, _storage_key)
3502
+ if not up.get("ok"):
3503
+ out = {"error": up.get("error", "upload failed"), "error_code": "upload_failed"}
3504
+ if up.get("file_id"):
3505
+ # metadata row exists but the binary never landed — surface the id
3506
+ # so the caller doesn't re-register on retry confusion.
3507
+ out["file_id"] = up["file_id"]
3508
+ out["note"] = "metadata registered, binary upload failed — retry sends a fresh file_id"
3509
+ return out
3510
+
3511
+ payload = {
3512
+ "type": "file_attachment",
3513
+ "text": caption or f"file: {up['file_name']} ({up['size_bytes']} bytes)",
3514
+ "file": {"file_id": up["file_id"], "file_name": up["file_name"],
3515
+ "mime_type": up["mime_type"]},
3516
+ }
3517
+ # msg_type stays default 'msg' — mc_messages.type carries a DB CHECK
3518
+ # (chk_mc_messages_type) that REFUSES unknown tags (live-caught 2026-06-09;
3519
+ # the "soft-validate" is SDK-side only). The attachment semantic rides in
3520
+ # payload.type + payload.file, which is what the FE chip renderer keys on.
3521
+ res = meshcode_send(to, payload, in_reply_to=in_reply_to, sensitive=sensitive)
3522
+ if isinstance(res, dict) and not res.get("error"):
3523
+ res = dict(res)
3524
+ res.update({"file_id": up["file_id"], "file_name": up["file_name"],
3525
+ "size_bytes": up["size_bytes"], "mime_type": up["mime_type"]})
3526
+ return res
3527
+
3528
+
3463
3529
  def _detect_global_done(messages: List[Dict[str, Any]]) -> Optional[Dict[str, Any]]:
3464
3530
  """Return {reason, from} if the list contains a global_done signal, else None."""
3465
3531
  for m in messages:
@@ -298,7 +298,13 @@ def _spawn_terminal_windows(cmd: str) -> tuple[bool, str]:
298
298
  # is what Samuel wants ("ventana nueva ENFOCADA"). The old `-w 0 nt` opened a tab in
299
299
  # the most-recently-used window — frequently minimized/background, so the launch
300
300
  # looked like "nada pasó".
301
- subprocess.Popen([wt, "-w", "new", "nt", "cmd", "/k", cmd])
301
+ # mesh-core patch-wt-semicolon (e9786e2d, verified on Samuel's box
302
+ # 2026-06-07): wt treats an unescaped ';' as a pane/tab delimiter,
303
+ # and the hostd PATH-inject (`set "PATH={bindir};%PATH%"`) always
304
+ # carries one → the cmdline splits and wt fails with 0x80070002.
305
+ # Escape ONLY here; the cmd.exe fallback below stays unescaped
306
+ # (cmd.exe does not split on ';').
307
+ subprocess.Popen([wt, "-w", "new", "nt", "cmd", "/k", cmd.replace(";", "\\;")])
302
308
  return True, "wt"
303
309
  except Exception as e:
304
310
  return False, f"wt.exe: {e}"
@@ -4,6 +4,11 @@ import sys
4
4
  import json
5
5
  import mimetypes
6
6
  from pathlib import Path
7
+
8
+ # Python's mimetypes table lacks markdown — without this, .md uploads land as
9
+ # application/octet-stream and meshcode_download_file hands recipients a temp
10
+ # file instead of inline text (live-caught in the send_file E2E 2026-06-09).
11
+ mimetypes.add_type("text/markdown", ".md")
7
12
  from urllib.request import Request, urlopen
8
13
  from urllib.error import HTTPError
9
14
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshcode
3
- Version: 2.11.117
3
+ Version: 2.11.119
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.11.117"
7
+ version = "2.11.119"
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