seif-cli 0.3.3__tar.gz → 0.3.5__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.
- {seif_cli-0.3.3/src/seif_cli.egg-info → seif_cli-0.3.5}/PKG-INFO +1 -1
- {seif_cli-0.3.3 → seif_cli-0.3.5}/pyproject.toml +1 -1
- seif_cli-0.3.5/src/seif/bridge/native_client.py +212 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5/src/seif_cli.egg-info}/PKG-INFO +1 -1
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif_cli.egg-info/SOURCES.txt +1 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/LICENSE +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/MANIFEST.in +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/README.md +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/setup.cfg +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/__init__.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/__main__.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/analysis/__init__.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/analysis/physical_constants.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/analysis/quality_gate.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/analysis/stance_detector.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/analysis/transcompiler.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/bridge/__init__.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/bridge/telegram_bot.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/cli/__init__.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/cli/__main__.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/cli/chat.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/cli/cli.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/cli/identity.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/cli/main.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/cli/resonance_display.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/cli/serve.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/cli/serve_v2.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/cli/wrapper.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/constants.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/context/__init__.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/context/advisor.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/context/code_compressor.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/context/context_bridge.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/context/context_importer.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/context/context_manager.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/context/context_qr.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/context/cycle.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/context/file_extractor.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/context/git_context.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/context/git_hooks.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/context/ingest.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/context/nucleus.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/context/ref.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/context/registry.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/context/seif_io.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/context/sessions.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/context/workspace.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/core/__init__.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/core/fingerprint.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/core/resonance_encoding.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/core/resonance_gate.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/core/resonance_signal.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/core/signing.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/core/timestamping.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/core/transfer_function.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/core/triple_gate.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/data/RESONANCE.json +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/data/__init__.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/data/defaults/__init__.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/data/paths.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/security/__init__.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif/security/mode.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif_cli.egg-info/dependency_links.txt +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif_cli.egg-info/entry_points.txt +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif_cli.egg-info/requires.txt +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/src/seif_cli.egg-info/top_level.txt +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/tests/test_advisor.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/tests/test_canonical_inputs.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/tests/test_code_compressor.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/tests/test_collaborative_seif.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/tests/test_context_qr.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/tests/test_context_repo.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/tests/test_git_context.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/tests/test_git_hooks.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/tests/test_init.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/tests/test_quality_gate.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/tests/test_ref.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/tests/test_registry.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/tests/test_resonance_gate.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/tests/test_seif_io.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/tests/test_stance_detector.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/tests/test_transcompiler.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/tests/test_transfer_function.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/tests/test_triple_gate.py +0 -0
- {seif_cli-0.3.3 → seif_cli-0.3.5}/tests/test_workspace.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: seif-cli
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.5
|
|
4
4
|
Summary: Measure AI output quality, protect sensitive data, watch your AI environment resonate. Quality Gate, Classification, Sentinel & Auto-Healing, SEIF OS.
|
|
5
5
|
Author: André Cunha Antero de Carvalho
|
|
6
6
|
License: CC-BY-NC-SA-4.0
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "seif-cli"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.5"
|
|
8
8
|
description = "Measure AI output quality, protect sensitive data, watch your AI environment resonate. Quality Gate, Classification, Sentinel & Auto-Healing, SEIF OS."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "CC-BY-NC-SA-4.0"}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Native AI Client — Direct SDK integration with Claude CLI fallback.
|
|
3
|
+
|
|
4
|
+
Supports streaming, multi-backend routing, and context injection from
|
|
5
|
+
the personal nucleus. When no ANTHROPIC_API_KEY is set, uses Claude CLI
|
|
6
|
+
(compatible with Max Plan via OAuth).
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from dataclasses import dataclass
|
|
10
|
+
from typing import Iterator, Optional
|
|
11
|
+
import os
|
|
12
|
+
import shutil
|
|
13
|
+
import subprocess
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass
|
|
17
|
+
class ChatConfig:
|
|
18
|
+
backend: str = "auto" # claude, claude-cli, gemini, local, auto
|
|
19
|
+
model: str = "" # model override (empty = use default)
|
|
20
|
+
stream: bool = True # streaming responses
|
|
21
|
+
quality_gate: bool = True # measure every response
|
|
22
|
+
max_tokens: int = 4096
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# Default models per backend
|
|
26
|
+
_DEFAULT_MODELS = {
|
|
27
|
+
"claude": "claude-sonnet-4-6",
|
|
28
|
+
"claude-cli": "claude-sonnet-4-6",
|
|
29
|
+
"gemini": "gemini-2.5-flash",
|
|
30
|
+
"grok": "grok-4-1-fast",
|
|
31
|
+
"local": "llama3",
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _has_claude_cli() -> bool:
|
|
36
|
+
return shutil.which("claude") is not None
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class NativeClient:
|
|
40
|
+
"""Multi-backend AI client with streaming support."""
|
|
41
|
+
|
|
42
|
+
def __init__(self, config: Optional[ChatConfig] = None,
|
|
43
|
+
profile: Optional[dict] = None):
|
|
44
|
+
self.config = config or ChatConfig()
|
|
45
|
+
self.profile = profile or {}
|
|
46
|
+
self._backend = self._resolve_backend()
|
|
47
|
+
self._model = self.config.model or _DEFAULT_MODELS.get(self._backend, "")
|
|
48
|
+
self._client = None
|
|
49
|
+
|
|
50
|
+
def _resolve_backend(self) -> str:
|
|
51
|
+
"""Resolve 'auto' to the best available backend."""
|
|
52
|
+
if self.config.backend != "auto":
|
|
53
|
+
return self.config.backend
|
|
54
|
+
|
|
55
|
+
profile_default = self.profile.get("default_backend", "")
|
|
56
|
+
if profile_default and profile_default != "auto":
|
|
57
|
+
return profile_default
|
|
58
|
+
|
|
59
|
+
# SDK requires API key with credits
|
|
60
|
+
if os.environ.get("ANTHROPIC_API_KEY"):
|
|
61
|
+
return "claude"
|
|
62
|
+
# No API key — prefer Claude CLI (Max Plan compatible)
|
|
63
|
+
if _has_claude_cli():
|
|
64
|
+
return "claude-cli"
|
|
65
|
+
if os.environ.get("GEMINI_API_KEY") or os.environ.get("GOOGLE_API_KEY"):
|
|
66
|
+
return "gemini"
|
|
67
|
+
return "claude"
|
|
68
|
+
|
|
69
|
+
def _get_anthropic_client(self):
|
|
70
|
+
"""Lazy-init Anthropic client."""
|
|
71
|
+
if self._client is None:
|
|
72
|
+
import anthropic
|
|
73
|
+
self._client = anthropic.Anthropic()
|
|
74
|
+
return self._client
|
|
75
|
+
|
|
76
|
+
def send(self, message: str, history: list[dict] = None,
|
|
77
|
+
system: str = "") -> str:
|
|
78
|
+
"""Send message and return complete response."""
|
|
79
|
+
if self._backend == "claude":
|
|
80
|
+
return self._send_claude(message, history or [], system)
|
|
81
|
+
elif self._backend == "claude-cli":
|
|
82
|
+
return self._send_claude_cli(message, history or [], system)
|
|
83
|
+
elif self._backend == "gemini":
|
|
84
|
+
return self._send_gemini(message, history or [], system)
|
|
85
|
+
elif self._backend == "local":
|
|
86
|
+
return self._send_local(message, history or [], system)
|
|
87
|
+
else:
|
|
88
|
+
return f"Backend '{self._backend}' not supported."
|
|
89
|
+
|
|
90
|
+
def stream(self, message: str, history: list[dict] = None,
|
|
91
|
+
system: str = "") -> Iterator[str]:
|
|
92
|
+
"""Stream response tokens."""
|
|
93
|
+
if self._backend == "claude":
|
|
94
|
+
yield from self._stream_claude(message, history or [], system)
|
|
95
|
+
elif self._backend == "claude-cli":
|
|
96
|
+
yield from self._stream_claude_cli(message, history or [], system)
|
|
97
|
+
else:
|
|
98
|
+
yield self.send(message, history, system)
|
|
99
|
+
|
|
100
|
+
# -- Claude SDK ------------------------------------------------
|
|
101
|
+
|
|
102
|
+
def _send_claude(self, message: str, history: list[dict],
|
|
103
|
+
system: str) -> str:
|
|
104
|
+
try:
|
|
105
|
+
client = self._get_anthropic_client()
|
|
106
|
+
messages = history + [{"role": "user", "content": message}]
|
|
107
|
+
response = client.messages.create(
|
|
108
|
+
model=self._model,
|
|
109
|
+
max_tokens=self.config.max_tokens,
|
|
110
|
+
system=system,
|
|
111
|
+
messages=messages,
|
|
112
|
+
)
|
|
113
|
+
return response.content[0].text
|
|
114
|
+
except ImportError:
|
|
115
|
+
return self._send_claude_cli(message, history, system)
|
|
116
|
+
except Exception as e:
|
|
117
|
+
return f"Error: {e}"
|
|
118
|
+
|
|
119
|
+
def _stream_claude(self, message: str, history: list[dict],
|
|
120
|
+
system: str) -> Iterator[str]:
|
|
121
|
+
try:
|
|
122
|
+
client = self._get_anthropic_client()
|
|
123
|
+
messages = history + [{"role": "user", "content": message}]
|
|
124
|
+
with client.messages.stream(
|
|
125
|
+
model=self._model,
|
|
126
|
+
max_tokens=self.config.max_tokens,
|
|
127
|
+
system=system,
|
|
128
|
+
messages=messages,
|
|
129
|
+
) as stream:
|
|
130
|
+
for text in stream.text_stream:
|
|
131
|
+
yield text
|
|
132
|
+
except ImportError:
|
|
133
|
+
yield from self._stream_claude_cli(message, history, system)
|
|
134
|
+
except Exception as e:
|
|
135
|
+
yield f"Error: {e}"
|
|
136
|
+
|
|
137
|
+
# -- Claude CLI (Max Plan) -------------------------------------
|
|
138
|
+
|
|
139
|
+
def _send_claude_cli(self, message: str, history: list[dict],
|
|
140
|
+
system: str) -> str:
|
|
141
|
+
try:
|
|
142
|
+
cmd = ["claude", "--print", "--output-format", "text",
|
|
143
|
+
"--no-session-persistence"]
|
|
144
|
+
if system:
|
|
145
|
+
cmd.extend(["--append-system-prompt", system])
|
|
146
|
+
cmd.append(message)
|
|
147
|
+
result = subprocess.run(cmd, capture_output=True, text=True, timeout=300)
|
|
148
|
+
return result.stdout.strip() if result.returncode == 0 else f"CLI error: {result.stderr.strip()}"
|
|
149
|
+
except FileNotFoundError:
|
|
150
|
+
return "Claude CLI not found. Install: https://docs.anthropic.com/claude-code"
|
|
151
|
+
except subprocess.TimeoutExpired:
|
|
152
|
+
return "Claude CLI timeout (300s)."
|
|
153
|
+
except Exception as e:
|
|
154
|
+
return f"CLI error: {e}"
|
|
155
|
+
|
|
156
|
+
def _stream_claude_cli(self, message: str, history: list[dict],
|
|
157
|
+
system: str) -> Iterator[str]:
|
|
158
|
+
"""Stream from Claude CLI via subprocess pipe."""
|
|
159
|
+
try:
|
|
160
|
+
cmd = ["claude", "--print", "--output-format", "text",
|
|
161
|
+
"--no-session-persistence"]
|
|
162
|
+
if system:
|
|
163
|
+
cmd.extend(["--append-system-prompt", system])
|
|
164
|
+
cmd.append(message)
|
|
165
|
+
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
|
|
166
|
+
stderr=subprocess.PIPE, text=True)
|
|
167
|
+
for line in proc.stdout:
|
|
168
|
+
yield line
|
|
169
|
+
proc.wait()
|
|
170
|
+
if proc.returncode != 0:
|
|
171
|
+
err = proc.stderr.read().strip()
|
|
172
|
+
if err:
|
|
173
|
+
yield f"\nCLI error: {err}"
|
|
174
|
+
except FileNotFoundError:
|
|
175
|
+
yield "Claude CLI not found. Install: https://docs.anthropic.com/claude-code"
|
|
176
|
+
except Exception as e:
|
|
177
|
+
yield f"CLI error: {e}"
|
|
178
|
+
|
|
179
|
+
# -- Gemini ----------------------------------------------------
|
|
180
|
+
|
|
181
|
+
def _send_gemini(self, message: str, history: list[dict],
|
|
182
|
+
system: str) -> str:
|
|
183
|
+
try:
|
|
184
|
+
import google.generativeai as genai
|
|
185
|
+
genai.configure()
|
|
186
|
+
model = genai.GenerativeModel(self._model,
|
|
187
|
+
system_instruction=system)
|
|
188
|
+
chat = model.start_chat(history=[
|
|
189
|
+
{"role": h["role"], "parts": [h["content"]]}
|
|
190
|
+
for h in history
|
|
191
|
+
] if history else [])
|
|
192
|
+
response = chat.send_message(message)
|
|
193
|
+
return response.text
|
|
194
|
+
except ImportError:
|
|
195
|
+
return "Gemini SDK not installed. pip install google-generativeai"
|
|
196
|
+
except Exception as e:
|
|
197
|
+
return f"Gemini error: {e}"
|
|
198
|
+
|
|
199
|
+
# -- Local (Ollama) --------------------------------------------
|
|
200
|
+
|
|
201
|
+
def _send_local(self, message: str, history: list[dict],
|
|
202
|
+
system: str) -> str:
|
|
203
|
+
try:
|
|
204
|
+
result = subprocess.run(
|
|
205
|
+
["ollama", "run", self._model, message],
|
|
206
|
+
capture_output=True, text=True, timeout=120,
|
|
207
|
+
)
|
|
208
|
+
return result.stdout.strip() if result.returncode == 0 else f"Error: {result.stderr}"
|
|
209
|
+
except FileNotFoundError:
|
|
210
|
+
return "Ollama not installed. https://ollama.ai"
|
|
211
|
+
except Exception as e:
|
|
212
|
+
return f"Local error: {e}"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: seif-cli
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.5
|
|
4
4
|
Summary: Measure AI output quality, protect sensitive data, watch your AI environment resonate. Quality Gate, Classification, Sentinel & Auto-Healing, SEIF OS.
|
|
5
5
|
Author: André Cunha Antero de Carvalho
|
|
6
6
|
License: CC-BY-NC-SA-4.0
|
|
@@ -11,6 +11,7 @@ src/seif/analysis/quality_gate.py
|
|
|
11
11
|
src/seif/analysis/stance_detector.py
|
|
12
12
|
src/seif/analysis/transcompiler.py
|
|
13
13
|
src/seif/bridge/__init__.py
|
|
14
|
+
src/seif/bridge/native_client.py
|
|
14
15
|
src/seif/bridge/telegram_bot.py
|
|
15
16
|
src/seif/cli/__init__.py
|
|
16
17
|
src/seif/cli/__main__.py
|
|
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
|