meshcode 1.7.0__tar.gz → 1.8.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-1.7.0 → meshcode-1.8.2}/PKG-INFO +1 -1
- {meshcode-1.7.0 → meshcode-1.8.2}/meshcode/__init__.py +1 -1
- {meshcode-1.7.0 → meshcode-1.8.2}/meshcode/comms_v4.py +36 -1
- {meshcode-1.7.0 → meshcode-1.8.2}/meshcode/meshcode_mcp/backend.py +3 -1
- {meshcode-1.7.0 → meshcode-1.8.2}/meshcode/meshcode_mcp/server.py +18 -2
- meshcode-1.8.2/meshcode/preferences.py +171 -0
- {meshcode-1.7.0 → meshcode-1.8.2}/meshcode/run_agent.py +10 -2
- {meshcode-1.7.0 → meshcode-1.8.2}/meshcode.egg-info/PKG-INFO +1 -1
- {meshcode-1.7.0 → meshcode-1.8.2}/meshcode.egg-info/SOURCES.txt +1 -0
- {meshcode-1.7.0 → meshcode-1.8.2}/pyproject.toml +1 -1
- {meshcode-1.7.0 → meshcode-1.8.2}/README.md +0 -0
- {meshcode-1.7.0 → meshcode-1.8.2}/meshcode/cli.py +0 -0
- {meshcode-1.7.0 → meshcode-1.8.2}/meshcode/invites.py +0 -0
- {meshcode-1.7.0 → meshcode-1.8.2}/meshcode/launcher.py +0 -0
- {meshcode-1.7.0 → meshcode-1.8.2}/meshcode/launcher_install.py +0 -0
- {meshcode-1.7.0 → meshcode-1.8.2}/meshcode/meshcode_mcp/__init__.py +0 -0
- {meshcode-1.7.0 → meshcode-1.8.2}/meshcode/meshcode_mcp/__main__.py +0 -0
- {meshcode-1.7.0 → meshcode-1.8.2}/meshcode/meshcode_mcp/realtime.py +0 -0
- {meshcode-1.7.0 → meshcode-1.8.2}/meshcode/meshcode_mcp/test_backend.py +0 -0
- {meshcode-1.7.0 → meshcode-1.8.2}/meshcode/meshcode_mcp/test_realtime.py +0 -0
- {meshcode-1.7.0 → meshcode-1.8.2}/meshcode/protocol_v2.py +0 -0
- {meshcode-1.7.0 → meshcode-1.8.2}/meshcode/secrets.py +0 -0
- {meshcode-1.7.0 → meshcode-1.8.2}/meshcode/setup_clients.py +0 -0
- {meshcode-1.7.0 → meshcode-1.8.2}/meshcode.egg-info/dependency_links.txt +0 -0
- {meshcode-1.7.0 → meshcode-1.8.2}/meshcode.egg-info/entry_points.txt +0 -0
- {meshcode-1.7.0 → meshcode-1.8.2}/meshcode.egg-info/requires.txt +0 -0
- {meshcode-1.7.0 → meshcode-1.8.2}/meshcode.egg-info/top_level.txt +0 -0
- {meshcode-1.7.0 → meshcode-1.8.2}/setup.cfg +0 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""MeshCode — Real-time communication between AI agents."""
|
|
2
|
-
__version__ = "1.
|
|
2
|
+
__version__ = "1.8.2"
|
|
@@ -1946,9 +1946,14 @@ if __name__ == "__main__":
|
|
|
1946
1946
|
agent = sys.argv[2]
|
|
1947
1947
|
proj_override = flags.get("project")
|
|
1948
1948
|
editor_override = flags.get("editor")
|
|
1949
|
+
perm_override = flags.get("permission") # bypass | safe | ask
|
|
1950
|
+
if "--bypass" in sys.argv:
|
|
1951
|
+
perm_override = "bypass"
|
|
1952
|
+
elif "--safe" in sys.argv:
|
|
1953
|
+
perm_override = "safe"
|
|
1949
1954
|
import importlib
|
|
1950
1955
|
_run = importlib.import_module("meshcode.run_agent").run
|
|
1951
|
-
sys.exit(_run(agent, project=proj_override, editor_override=editor_override))
|
|
1956
|
+
sys.exit(_run(agent, project=proj_override, editor_override=editor_override, permission_override=perm_override))
|
|
1952
1957
|
|
|
1953
1958
|
elif cmd == "invite":
|
|
1954
1959
|
# meshcode invite <project> <agent> [--role "..."] [--days N]
|
|
@@ -2017,6 +2022,36 @@ if __name__ == "__main__":
|
|
|
2017
2022
|
sys.exit(1)
|
|
2018
2023
|
login(key)
|
|
2019
2024
|
|
|
2025
|
+
elif cmd == "prefs":
|
|
2026
|
+
# meshcode prefs permission-mode [bypass|safe|ask] (no arg = show)
|
|
2027
|
+
# meshcode prefs reset
|
|
2028
|
+
from meshcode.preferences import (
|
|
2029
|
+
get_permission_mode, set_permission_mode, reset_permission_mode,
|
|
2030
|
+
VALID_PERMISSION_MODES,
|
|
2031
|
+
)
|
|
2032
|
+
sub = sys.argv[2] if len(sys.argv) > 2 else ""
|
|
2033
|
+
if sub == "permission-mode":
|
|
2034
|
+
if len(sys.argv) > 3:
|
|
2035
|
+
mode = sys.argv[3].lower()
|
|
2036
|
+
if mode not in VALID_PERMISSION_MODES:
|
|
2037
|
+
print(f"[ERROR] mode must be one of: {', '.join(sorted(VALID_PERMISSION_MODES))}")
|
|
2038
|
+
sys.exit(1)
|
|
2039
|
+
ok = set_permission_mode(mode)
|
|
2040
|
+
print(f"[meshcode] permission_mode = {mode}" if ok else "[ERROR] failed to save")
|
|
2041
|
+
sys.exit(0 if ok else 1)
|
|
2042
|
+
else:
|
|
2043
|
+
cur = get_permission_mode()
|
|
2044
|
+
print(f"permission_mode: {cur or '(unset — will prompt on next run)'}")
|
|
2045
|
+
sys.exit(0)
|
|
2046
|
+
elif sub == "reset":
|
|
2047
|
+
reset_permission_mode()
|
|
2048
|
+
print("[meshcode] preferences reset")
|
|
2049
|
+
sys.exit(0)
|
|
2050
|
+
else:
|
|
2051
|
+
print("Usage: meshcode prefs permission-mode [bypass|safe|ask]")
|
|
2052
|
+
print(" meshcode prefs reset")
|
|
2053
|
+
sys.exit(1)
|
|
2054
|
+
|
|
2020
2055
|
elif cmd == "launcher":
|
|
2021
2056
|
# meshcode launcher {install|uninstall|start|stop|restart|status|logs|test}
|
|
2022
2057
|
try:
|
|
@@ -164,7 +164,7 @@ def register_agent(project: str, name: str, role: str = "") -> Dict:
|
|
|
164
164
|
}
|
|
165
165
|
|
|
166
166
|
|
|
167
|
-
def send_message(project_id: str, from_agent: str, to_agent: str, payload: Any, msg_type: str = "msg", parent_msg_id: Optional[str] = None) -> Dict:
|
|
167
|
+
def send_message(project_id: str, from_agent: str, to_agent: str, payload: Any, msg_type: str = "msg", parent_msg_id: Optional[str] = None, sensitive: bool = False) -> Dict:
|
|
168
168
|
if not isinstance(payload, dict):
|
|
169
169
|
payload = {"text": str(payload)}
|
|
170
170
|
msg = {
|
|
@@ -177,6 +177,8 @@ def send_message(project_id: str, from_agent: str, to_agent: str, payload: Any,
|
|
|
177
177
|
}
|
|
178
178
|
if parent_msg_id:
|
|
179
179
|
msg["parent_msg_id"] = parent_msg_id
|
|
180
|
+
if sensitive:
|
|
181
|
+
msg["is_sensitive"] = True
|
|
180
182
|
result = sb_insert("mc_messages", msg)
|
|
181
183
|
if isinstance(result, dict) and result.get("_error"):
|
|
182
184
|
return {"error": result["_error"]}
|
|
@@ -363,6 +363,14 @@ meshcode_wait / meshcode_check / meshcode_read now includes an `id` field
|
|
|
363
363
|
(use it for in_reply_to) and a `parent_id` field (so you can see whether
|
|
364
364
|
the message you received is itself a reply to something).
|
|
365
365
|
|
|
366
|
+
SENSITIVE DATA: when sharing API keys, credentials, customer data, personal
|
|
367
|
+
information, secrets, or anything that should not be in a public log, set
|
|
368
|
+
sensitive=True in your meshcode_send call. Sensitive messages are NEVER
|
|
369
|
+
included in public meshwork exports, even if the meshwork owner publishes
|
|
370
|
+
the meshwork. The flag is enforced at the database level — there is no way
|
|
371
|
+
for a public viewer to read sensitive messages. Use this liberally — false
|
|
372
|
+
positives are harmless, false negatives are a privacy leak.
|
|
373
|
+
|
|
366
374
|
LOOP-SAFETY RULES (IMPORTANT — prevent token-burning ping-pong):
|
|
367
375
|
- Do NOT reply "Done" / "OK" / "Got it" to every message. If a message
|
|
368
376
|
is a status update or pure ack, just process it and call meshcode_wait
|
|
@@ -505,7 +513,8 @@ except Exception:
|
|
|
505
513
|
# ----------------- TOOLS -----------------
|
|
506
514
|
|
|
507
515
|
@mcp.tool()
|
|
508
|
-
def meshcode_send(to: str, message: Any, in_reply_to: Optional[str] = None
|
|
516
|
+
def meshcode_send(to: str, message: Any, in_reply_to: Optional[str] = None,
|
|
517
|
+
sensitive: bool = False) -> Dict[str, Any]:
|
|
509
518
|
"""Send a message to another agent in the meshwork.
|
|
510
519
|
|
|
511
520
|
If you only have plain text, just pass it as a string and it will be
|
|
@@ -520,6 +529,13 @@ def meshcode_send(to: str, message: Any, in_reply_to: Optional[str] = None) -> D
|
|
|
520
529
|
message is a threaded reply — the dashboard renders it under the
|
|
521
530
|
original. Use this especially when replying to one of several
|
|
522
531
|
outstanding broadcasts so humans can tell which is which.
|
|
532
|
+
sensitive: If True, this message will NEVER appear in a public meshwork
|
|
533
|
+
export, regardless of whether the meshwork is published. ALWAYS
|
|
534
|
+
set this to True when sharing API keys, credentials, customer
|
|
535
|
+
data, secrets, personal information, or anything that should not
|
|
536
|
+
be visible to anyone outside the meshwork. The owner can publish
|
|
537
|
+
the meshwork without leaking sensitive messages, because the
|
|
538
|
+
sensitive flag is enforced at the database level.
|
|
523
539
|
"""
|
|
524
540
|
if isinstance(message, str):
|
|
525
541
|
payload: Dict[str, Any] = {"text": message}
|
|
@@ -528,7 +544,7 @@ def meshcode_send(to: str, message: Any, in_reply_to: Optional[str] = None) -> D
|
|
|
528
544
|
else:
|
|
529
545
|
payload = {"text": str(message)}
|
|
530
546
|
return be.send_message(_PROJECT_ID, AGENT_NAME, to, payload, msg_type="msg",
|
|
531
|
-
parent_msg_id=in_reply_to)
|
|
547
|
+
parent_msg_id=in_reply_to, sensitive=sensitive)
|
|
532
548
|
|
|
533
549
|
|
|
534
550
|
@mcp.tool()
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"""Per-user CLI preferences for MeshCode.
|
|
2
|
+
|
|
3
|
+
Stores small non-secret settings (like permission_mode for `meshcode run`)
|
|
4
|
+
in ~/.meshcode/preferences.json with mode 600. Not the same as the API key
|
|
5
|
+
storage in secrets.py — that goes to the OS keychain. This file is for
|
|
6
|
+
opinion/UX preferences only, no credentials.
|
|
7
|
+
|
|
8
|
+
Currently tracked:
|
|
9
|
+
permission_mode one of "bypass" | "safe" | "ask" | None (unset)
|
|
10
|
+
- "bypass": meshcode run passes --dangerously-skip-permissions
|
|
11
|
+
to Claude Code so the autonomous loop runs without prompts.
|
|
12
|
+
- "safe": meshcode run does NOT pass that flag, so Claude
|
|
13
|
+
prompts the user to approve every tool call. Kills the
|
|
14
|
+
autonomous loop in practice — exists for paranoid users.
|
|
15
|
+
- "ask": prompt every launch.
|
|
16
|
+
- None: never set; meshcode run prompts on first use,
|
|
17
|
+
saves the choice, and uses it from then on.
|
|
18
|
+
"""
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import json
|
|
22
|
+
import os
|
|
23
|
+
import sys
|
|
24
|
+
import time
|
|
25
|
+
from pathlib import Path
|
|
26
|
+
from typing import Any, Dict, Optional
|
|
27
|
+
|
|
28
|
+
PREFS_PATH = Path.home() / ".meshcode" / "preferences.json"
|
|
29
|
+
|
|
30
|
+
VALID_PERMISSION_MODES = {"bypass", "safe", "ask"}
|
|
31
|
+
DEFAULT_PERMISSION_MODE_FOR_NON_TTY = "bypass"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def load_prefs() -> Dict[str, Any]:
|
|
35
|
+
"""Load the prefs file. Returns {} if missing or unparseable."""
|
|
36
|
+
if not PREFS_PATH.exists():
|
|
37
|
+
return {}
|
|
38
|
+
try:
|
|
39
|
+
return json.loads(PREFS_PATH.read_text())
|
|
40
|
+
except Exception:
|
|
41
|
+
return {}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def save_prefs(prefs: Dict[str, Any]) -> bool:
|
|
45
|
+
"""Atomic write of the prefs file with mode 600."""
|
|
46
|
+
try:
|
|
47
|
+
PREFS_PATH.parent.mkdir(parents=True, exist_ok=True)
|
|
48
|
+
tmp = PREFS_PATH.with_suffix(".tmp")
|
|
49
|
+
tmp.write_text(json.dumps(prefs, indent=2))
|
|
50
|
+
try:
|
|
51
|
+
os.chmod(tmp, 0o600)
|
|
52
|
+
except Exception:
|
|
53
|
+
pass
|
|
54
|
+
tmp.replace(PREFS_PATH)
|
|
55
|
+
return True
|
|
56
|
+
except Exception as e:
|
|
57
|
+
print(f"[meshcode] WARNING: could not save prefs: {e}", file=sys.stderr)
|
|
58
|
+
return False
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def get_permission_mode() -> Optional[str]:
|
|
62
|
+
"""Returns 'bypass' / 'safe' / 'ask' / None."""
|
|
63
|
+
val = load_prefs().get("permission_mode")
|
|
64
|
+
if isinstance(val, str) and val in VALID_PERMISSION_MODES:
|
|
65
|
+
return val
|
|
66
|
+
return None
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def set_permission_mode(mode: str) -> bool:
|
|
70
|
+
"""Persist a new permission mode. Returns True on success."""
|
|
71
|
+
if mode not in VALID_PERMISSION_MODES:
|
|
72
|
+
print(f"[meshcode] ERROR: invalid permission mode '{mode}'. Use: {', '.join(sorted(VALID_PERMISSION_MODES))}", file=sys.stderr)
|
|
73
|
+
return False
|
|
74
|
+
prefs = load_prefs()
|
|
75
|
+
prefs["permission_mode"] = mode
|
|
76
|
+
prefs["permission_mode_set_at"] = int(time.time())
|
|
77
|
+
return save_prefs(prefs)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def reset_permission_mode() -> bool:
|
|
81
|
+
"""Forget the permission mode so the next launch prompts again."""
|
|
82
|
+
prefs = load_prefs()
|
|
83
|
+
prefs.pop("permission_mode", None)
|
|
84
|
+
prefs.pop("permission_mode_set_at", None)
|
|
85
|
+
return save_prefs(prefs)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def prompt_permission_mode() -> str:
|
|
89
|
+
"""Interactive first-run prompt. Returns the chosen mode and saves it.
|
|
90
|
+
|
|
91
|
+
If stdin is not a TTY (CI, automation, no terminal), silently picks
|
|
92
|
+
DEFAULT_PERMISSION_MODE_FOR_NON_TTY ('bypass') and saves it. The user
|
|
93
|
+
can change it later with `meshcode prefs permission-mode <mode>`.
|
|
94
|
+
"""
|
|
95
|
+
if not sys.stdin.isatty():
|
|
96
|
+
set_permission_mode(DEFAULT_PERMISSION_MODE_FOR_NON_TTY)
|
|
97
|
+
return DEFAULT_PERMISSION_MODE_FOR_NON_TTY
|
|
98
|
+
|
|
99
|
+
print("", file=sys.stderr)
|
|
100
|
+
print("[meshcode] PERMISSION MODE — choose once (saved for future runs)", file=sys.stderr)
|
|
101
|
+
print("[meshcode]", file=sys.stderr)
|
|
102
|
+
print("[meshcode] Mesh agents work best with bypass mode: tools run without", file=sys.stderr)
|
|
103
|
+
print("[meshcode] confirmation prompts, so the autonomous loop is not interrupted.", file=sys.stderr)
|
|
104
|
+
print("[meshcode] Equivalent to running `claude --dangerously-skip-permissions`.", file=sys.stderr)
|
|
105
|
+
print("[meshcode]", file=sys.stderr)
|
|
106
|
+
print("[meshcode] In bypass mode, your agents can run shell commands, edit files,", file=sys.stderr)
|
|
107
|
+
print("[meshcode] and access the network without asking. Only use bypass in", file=sys.stderr)
|
|
108
|
+
print("[meshcode] directories where you're OK with the agent acting as you.", file=sys.stderr)
|
|
109
|
+
print("[meshcode]", file=sys.stderr)
|
|
110
|
+
print("[meshcode] [B] Bypass mode (recommended for autonomous mesh agents)", file=sys.stderr)
|
|
111
|
+
print("[meshcode] [s] Safe mode (you approve every tool call — kills the loop)", file=sys.stderr)
|
|
112
|
+
print("[meshcode] [a] Ask me each launch", file=sys.stderr)
|
|
113
|
+
print("[meshcode]", file=sys.stderr)
|
|
114
|
+
try:
|
|
115
|
+
ans = input("[meshcode] Pick [B/s/a] (default B): ").strip().lower()
|
|
116
|
+
except (EOFError, KeyboardInterrupt):
|
|
117
|
+
ans = ""
|
|
118
|
+
|
|
119
|
+
if ans in ("", "b", "bypass"):
|
|
120
|
+
chosen = "bypass"
|
|
121
|
+
elif ans in ("s", "safe"):
|
|
122
|
+
chosen = "safe"
|
|
123
|
+
elif ans in ("a", "ask"):
|
|
124
|
+
chosen = "ask"
|
|
125
|
+
else:
|
|
126
|
+
print(f"[meshcode] '{ans}' not recognized — defaulting to bypass.", file=sys.stderr)
|
|
127
|
+
chosen = "bypass"
|
|
128
|
+
|
|
129
|
+
set_permission_mode(chosen)
|
|
130
|
+
print(f"[meshcode] ✓ Saved as '{chosen}'. Change later with: meshcode prefs permission-mode <mode>", file=sys.stderr)
|
|
131
|
+
print("", file=sys.stderr)
|
|
132
|
+
return chosen
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def resolve_permission_mode(per_launch_override: Optional[str] = None) -> str:
|
|
136
|
+
"""Resolve the effective permission mode for a single launch.
|
|
137
|
+
|
|
138
|
+
Order:
|
|
139
|
+
1. per-launch override (--bypass / --safe flag) wins
|
|
140
|
+
2. saved preference
|
|
141
|
+
3. interactive prompt (saves choice if user is at a TTY)
|
|
142
|
+
4. fallback to 'bypass' for non-TTY environments
|
|
143
|
+
"""
|
|
144
|
+
if per_launch_override in VALID_PERMISSION_MODES:
|
|
145
|
+
return per_launch_override
|
|
146
|
+
|
|
147
|
+
saved = get_permission_mode()
|
|
148
|
+
if saved == "ask":
|
|
149
|
+
# The user opted into being prompted every launch
|
|
150
|
+
return prompt_permission_mode_quick()
|
|
151
|
+
if saved in ("bypass", "safe"):
|
|
152
|
+
return saved
|
|
153
|
+
|
|
154
|
+
# Unset → first-run prompt + save
|
|
155
|
+
return prompt_permission_mode()
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def prompt_permission_mode_quick() -> str:
|
|
159
|
+
"""One-line prompt for users who picked 'ask each launch'.
|
|
160
|
+
|
|
161
|
+
Does NOT save — the saved preference stays as 'ask'.
|
|
162
|
+
"""
|
|
163
|
+
if not sys.stdin.isatty():
|
|
164
|
+
return DEFAULT_PERMISSION_MODE_FOR_NON_TTY
|
|
165
|
+
try:
|
|
166
|
+
ans = input("[meshcode] Permission mode for this launch [B/s] (default B): ").strip().lower()
|
|
167
|
+
except (EOFError, KeyboardInterrupt):
|
|
168
|
+
ans = ""
|
|
169
|
+
if ans in ("s", "safe"):
|
|
170
|
+
return "safe"
|
|
171
|
+
return "bypass"
|
|
@@ -25,6 +25,8 @@ import sys
|
|
|
25
25
|
from pathlib import Path
|
|
26
26
|
from typing import Optional, Tuple
|
|
27
27
|
|
|
28
|
+
from .preferences import resolve_permission_mode
|
|
29
|
+
|
|
28
30
|
WORKSPACES_ROOT = Path.home() / "meshcode"
|
|
29
31
|
REGISTRY_PATH = WORKSPACES_ROOT / ".registry.json"
|
|
30
32
|
|
|
@@ -97,7 +99,7 @@ def _detect_editor() -> Optional[str]:
|
|
|
97
99
|
return None
|
|
98
100
|
|
|
99
101
|
|
|
100
|
-
def run(agent: str, project: Optional[str] = None, editor_override: Optional[str] = None) -> int:
|
|
102
|
+
def run(agent: str, project: Optional[str] = None, editor_override: Optional[str] = None, permission_override: Optional[str] = None) -> int:
|
|
101
103
|
"""Launch the user's editor with ONLY the named agent's MCP server loaded."""
|
|
102
104
|
found = _find_agent_workspace(agent, project)
|
|
103
105
|
if not found:
|
|
@@ -121,12 +123,18 @@ def run(agent: str, project: Optional[str] = None, editor_override: Optional[str
|
|
|
121
123
|
if editor == "claude":
|
|
122
124
|
# Claude Code: pass --mcp-config to point at the workspace's .mcp.json
|
|
123
125
|
# and --strict-mcp-config so it ignores ~/.claude.json's mcpServers.
|
|
126
|
+
mode = resolve_permission_mode(permission_override)
|
|
124
127
|
cmd = [
|
|
125
128
|
editor,
|
|
126
129
|
"--mcp-config", str(ws / ".mcp.json"),
|
|
127
130
|
"--strict-mcp-config",
|
|
128
|
-
"--dangerously-skip-permissions",
|
|
129
131
|
]
|
|
132
|
+
if mode == "bypass":
|
|
133
|
+
cmd.append("--dangerously-skip-permissions")
|
|
134
|
+
print(f"[meshcode] Permission mode: bypass (autonomous loop, no prompts)")
|
|
135
|
+
else:
|
|
136
|
+
print(f"[meshcode] Permission mode: safe (Claude will prompt for every tool call)")
|
|
137
|
+
print(f"[meshcode] Tip: change with `meshcode prefs permission-mode bypass`")
|
|
130
138
|
try:
|
|
131
139
|
os.chdir(ws)
|
|
132
140
|
except Exception:
|
|
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
|