meshcode 2.11.162__tar.gz → 2.11.164__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.11.162 → meshcode-2.11.164}/PKG-INFO +1 -1
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/__init__.py +1 -1
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/meshcode_mcp/server.py +113 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/protocol_handler.py +8 -5
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode.egg-info/PKG-INFO +1 -1
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode.egg-info/SOURCES.txt +1 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/pyproject.toml +1 -1
- {meshcode-2.11.162 → meshcode-2.11.164}/README.md +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/__main__.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/_launch_smoke.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/_session_handoff_template.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/_stop_hook_template.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/_update_guard.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/ascii_art.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/atomic_push.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/claude_update.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/cli.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/comms_v4.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/compat.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/daemon.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/date_parse.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/doctor.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/error_hints.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/exceptions.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/hooks/__init__.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/hooks/push_guard.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/hooks/repo_path_lock.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/hostd.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/invites.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/launcher.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/launcher_install.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/meshcode_mcp/__init__.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/meshcode_mcp/__main__.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/meshcode_mcp/backend.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/meshcode_mcp/realtime.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/meshcode_mcp/sleep_signals.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/meshcode_mcp/test_backend.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/meshcode_mcp/test_boot_timing.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/meshcode_mcp/test_install_guard.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/meshcode_mcp/test_prefs_claude_version.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/meshcode_mcp/test_realtime.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/preferences.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/protocol_v2.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/quickstart.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/rpc_allowlist.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/run_agent.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/scripts/check_secrets.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/scripts/race_rate_harness.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/secrets.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/self_update.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/setup_clients.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/supervisor.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/up.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode/upload.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode.egg-info/dependency_links.txt +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode.egg-info/entry_points.txt +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode.egg-info/requires.txt +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/meshcode.egg-info/top_level.txt +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/setup.cfg +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_auto_update_hardening.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_autonomous_closegap_1.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_autonomous_closegap_2.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_autonomous_closegap_3.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_autonomous_prompt_inject.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_boot_bug_regression.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_color_truecolor.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_core.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_cross_agent_messaging.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_date_parse.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_doctor.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_ensure_boot_env_urgent_wake.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_epistemic_v1_python_sdk.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_epistemic_v1_stop_conditions.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_esc_deaf_state.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_exceptions.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_file_upload.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_fleet_reaper.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_hostd_launch_pinned_env.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_hostd_serve_discovery_split.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_hostd_zombie_sessions.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_init_device_code.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_install_guard.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_launch_smoke.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_lease_sigterm_release.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_live_mesh_guard.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_mark_read_batch.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_marketplace_ratings.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_migration_integrity.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_no_appleevents_on_sweep.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_preflight_hb_gate.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_pretrust_claude.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_prompt_dedup_budget.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_push_guard.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_realtime_event_freshness.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_replica_base_workspace_fallback.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_replica_boot_protocol_unconditional.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_rls_cross_tenant.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_rm_guard.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_rpc_grants.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_rpc_migrations.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_run_agent_dry_run.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_run_agent_no_server_import.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_security_regressions.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_self_update_user_site.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_sentinel.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_session_replay_gate.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_setup_path.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_sleep_signals.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_status_enum_coverage.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_stay_on_loop_hook.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_stop_ghost_terminal.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_task_progress.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_terminal_lifecycle.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_up_launch_cmd.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_update_guard.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_urgent_wake_tmux.py +0 -0
- {meshcode-2.11.162 → meshcode-2.11.164}/tests/test_wait_open_tasks_contradiction.py +0 -0
|
@@ -7789,6 +7789,119 @@ def meshcode_mesh_keep_alive(enabled: bool) -> Dict[str, Any]:
|
|
|
7789
7789
|
return res if isinstance(res, dict) else {"error": str(res)}
|
|
7790
7790
|
|
|
7791
7791
|
|
|
7792
|
+
@mcp.tool()
|
|
7793
|
+
def meshcode_gmail(
|
|
7794
|
+
action: str,
|
|
7795
|
+
to: str = "",
|
|
7796
|
+
subject: str = "",
|
|
7797
|
+
body: str = "",
|
|
7798
|
+
cc: str = "",
|
|
7799
|
+
bcc: str = "",
|
|
7800
|
+
message_id: str = "",
|
|
7801
|
+
q: str = "",
|
|
7802
|
+
max_results: int = 10,
|
|
7803
|
+
) -> Dict[str, Any]:
|
|
7804
|
+
"""Act on the meshwork owner's connected Gmail account (task fb654587).
|
|
7805
|
+
|
|
7806
|
+
OWNER-SCOPED: this agent can only reach the Gmail account connected to
|
|
7807
|
+
ITS OWN meshwork/project. Auth flows through the agent's api_key →
|
|
7808
|
+
mc_gmail_resolve_for_agent (SECURITY DEFINER), which verifies the key,
|
|
7809
|
+
confirms owner/member access to the project, resolves the single active
|
|
7810
|
+
gmail binding, and writes a MANDATORY audit row. Agents NEVER receive the
|
|
7811
|
+
OAuth token or binding_id — the trusted gmail-action edge fn holds the
|
|
7812
|
+
token and performs the Google API call. Every action is audited
|
|
7813
|
+
(meshcode.mc_connector_audit). Scope = readonly + compose + modify
|
|
7814
|
+
(NOT full mail.google.com).
|
|
7815
|
+
|
|
7816
|
+
Actions:
|
|
7817
|
+
- "send": send a new email. Needs: to, subject, body. Optional: cc, bcc.
|
|
7818
|
+
- "reply": reply in a thread. Needs: message_id (msg replied to), body.
|
|
7819
|
+
- "draft": create a draft. Needs: to, subject, body. Optional: cc, bcc.
|
|
7820
|
+
- "search": search messages. Needs: q. Optional: max_results.
|
|
7821
|
+
- "list": list recent msgs. Optional: q, max_results.
|
|
7822
|
+
- "get"/"read": fetch one msg. Needs: message_id.
|
|
7823
|
+
- "list_labels": list mailbox labels.
|
|
7824
|
+
|
|
7825
|
+
Args:
|
|
7826
|
+
action: one of send|reply|draft|search|list|get|read|list_labels.
|
|
7827
|
+
to: recipient email(s), comma-separated (send/draft).
|
|
7828
|
+
subject: subject line (send/draft).
|
|
7829
|
+
body: message body, plain text (send/reply/draft).
|
|
7830
|
+
cc, bcc: optional carbon-copy recipients (send/draft).
|
|
7831
|
+
message_id: Gmail message id (reply/get/read).
|
|
7832
|
+
q: Gmail search query, e.g. "from:boss is:unread" (search/list).
|
|
7833
|
+
max_results: cap results for search/list (default 10).
|
|
7834
|
+
|
|
7835
|
+
Returns the edge fn JSON ({ok, ...} or {ok:false, error/error_code}).
|
|
7836
|
+
"""
|
|
7837
|
+
import urllib.request as _req
|
|
7838
|
+
import urllib.error as _uerr
|
|
7839
|
+
|
|
7840
|
+
api_key = _get_api_key()
|
|
7841
|
+
if not api_key:
|
|
7842
|
+
return {"ok": False, "error": "no api key", "error_code": "auth_failed"}
|
|
7843
|
+
if not _PROJECT_ID:
|
|
7844
|
+
return {"ok": False, "error": "project not resolved", "error_code": "config_error"}
|
|
7845
|
+
|
|
7846
|
+
act = (action or "").strip().lower()
|
|
7847
|
+
valid = {"send", "reply", "draft", "search", "list", "get", "read", "list_labels"}
|
|
7848
|
+
if act not in valid:
|
|
7849
|
+
return {"ok": False, "error": f"unknown action '{action}'",
|
|
7850
|
+
"error_code": "bad_action", "valid_actions": sorted(valid)}
|
|
7851
|
+
|
|
7852
|
+
# Action-specific fields go in a NESTED `params` object — the gmail-action
|
|
7853
|
+
# edge fn reads them from b.params (b.params.to, b.params.message_id, …).
|
|
7854
|
+
params: Dict[str, Any] = {}
|
|
7855
|
+
if to:
|
|
7856
|
+
params["to"] = to
|
|
7857
|
+
if subject:
|
|
7858
|
+
params["subject"] = subject
|
|
7859
|
+
if body:
|
|
7860
|
+
params["body"] = body
|
|
7861
|
+
if cc:
|
|
7862
|
+
params["cc"] = cc
|
|
7863
|
+
if bcc:
|
|
7864
|
+
params["bcc"] = bcc
|
|
7865
|
+
if message_id:
|
|
7866
|
+
params["message_id"] = message_id
|
|
7867
|
+
if q:
|
|
7868
|
+
params["q"] = q
|
|
7869
|
+
if max_results:
|
|
7870
|
+
params["max"] = int(max_results)
|
|
7871
|
+
|
|
7872
|
+
payload = {
|
|
7873
|
+
"agent_api_key": api_key,
|
|
7874
|
+
"project_id": _PROJECT_ID,
|
|
7875
|
+
"agent_name": AGENT_NAME,
|
|
7876
|
+
"action": act,
|
|
7877
|
+
"params": params,
|
|
7878
|
+
}
|
|
7879
|
+
|
|
7880
|
+
url = f"{be.SUPABASE_URL}/functions/v1/gmail-action"
|
|
7881
|
+
data = json.dumps(payload).encode("utf-8")
|
|
7882
|
+
req = _req.Request(url, data=data, method="POST", headers={
|
|
7883
|
+
"Content-Type": "application/json",
|
|
7884
|
+
"apikey": be.SUPABASE_KEY,
|
|
7885
|
+
"Authorization": f"Bearer {be.SUPABASE_KEY}",
|
|
7886
|
+
})
|
|
7887
|
+
try:
|
|
7888
|
+
with _req.urlopen(req, timeout=30) as resp:
|
|
7889
|
+
raw = resp.read().decode("utf-8")
|
|
7890
|
+
return json.loads(raw) if raw else {"ok": True}
|
|
7891
|
+
except _uerr.HTTPError as e:
|
|
7892
|
+
try:
|
|
7893
|
+
parsed = json.loads(e.read().decode("utf-8"))
|
|
7894
|
+
if isinstance(parsed, dict):
|
|
7895
|
+
return parsed
|
|
7896
|
+
except Exception:
|
|
7897
|
+
pass
|
|
7898
|
+
return {"ok": False, "error": f"HTTP {e.code}: {e.reason}",
|
|
7899
|
+
"error_code": "edge_http_error"}
|
|
7900
|
+
except Exception as e:
|
|
7901
|
+
return {"ok": False, "error": f"{type(e).__name__}: {e}",
|
|
7902
|
+
"error_code": "request_failed"}
|
|
7903
|
+
|
|
7904
|
+
|
|
7792
7905
|
def inbox_resource() -> str:
|
|
7793
7906
|
"""Current pending messages for this agent. Read-only — does NOT mark as read."""
|
|
7794
7907
|
pending = be.sb_select(
|
|
@@ -1268,13 +1268,16 @@ def _spawn_terminal_windows(cmd: str) -> tuple[bool, str]:
|
|
|
1268
1268
|
def _spawn_terminal(cmd: str) -> tuple[bool, str]:
|
|
1269
1269
|
p = platform.system()
|
|
1270
1270
|
if p == "Darwin":
|
|
1271
|
-
#
|
|
1272
|
-
#
|
|
1273
|
-
|
|
1271
|
+
# tmux leads (reliable, ONE window, no AppleScript/TCC focus-steal);
|
|
1272
|
+
# native-tabs is prettier but AppleScript-flaky and can leak loose
|
|
1273
|
+
# windows ALONGSIDE the fleet (Samuel's "terminals everywhere") -> 2nd;
|
|
1274
|
+
# legacy one-window-per-agent backstop (task 678851c8 window-clutter).
|
|
1275
|
+
# 1) tmux fleet bar (task 2ac3f111) — shared window, styled tab bar.
|
|
1276
|
+
ok, info = _spawn_fleet_tab(cmd)
|
|
1274
1277
|
if ok:
|
|
1275
1278
|
return True, info
|
|
1276
|
-
# 2)
|
|
1277
|
-
ok, info =
|
|
1279
|
+
# 2) NATIVE Terminal tabs (task 4df5a126, Samuel GO) — prettier, flaky.
|
|
1280
|
+
ok, info = _spawn_fleet_native_macos(cmd)
|
|
1278
1281
|
if ok:
|
|
1279
1282
|
return True, info
|
|
1280
1283
|
# 3) legacy one-window-per-agent — never worse than before.
|
|
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
|
|
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
|
|
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
|