codee-agent 0.5.4__tar.gz → 0.5.6__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.
- {codee_agent-0.5.4 → codee_agent-0.5.6}/PKG-INFO +1 -1
- {codee_agent-0.5.4 → codee_agent-0.5.6}/pyproject.toml +1 -1
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/test_admin_service.py +1 -1
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee_agent_claude_code/provider.py +10 -6
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee_agent_claude_code/test.py +14 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee_agent_github_copilot/provider.py +12 -6
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee_agent_github_copilot/test.py +11 -1
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee_tasks_azure_devops/provider.py +4 -2
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee_tasks_azure_devops/test.py +1 -1
- {codee_agent-0.5.4 → codee_agent-0.5.6}/LICENSE +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/README.md +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/.gitignore +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/__init__.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/admin.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/admin_api.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/admin_cli.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/admin_service.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/agent_cli.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/coding_agents.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/executor.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/init_cli.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/lib/__init__.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/lib/cron_describe.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/lib/mcp_config.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/lib/runs_db.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/lib/test_mcp_config.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/lib/test_runs_db.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/lib/test_trigger_cron_skills.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/lib/test_trigger_issue_skills.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/lib/trigger_aws_sqs_skills.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/lib/trigger_cron_skills.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/lib/trigger_email_skills.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/lib/trigger_issue_skills.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/mail_server.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/setup_wizard.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/start_cli.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/tasks_providers.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/templates/AGENTS.md +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/templates/CLAUDE.md +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/templates/skills/aws-sqs-alarm-response/SKILL.md +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/templates/skills/cron-research-5xx-errors/SKILL.md +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/templates/skills/story-code-reviewer/SKILL.md +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/templates/skills/story-developer/SKILL.md +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/templates/skills/story-planner/SKILL.md +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/templates/skills/story-planner/assets/readme-template.md +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/templates/skills/story-qa/SKILL.md +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/templates/skills/story-security-reviewer/SKILL.md +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/templates/skills/task-code-reviewer/SKILL.md +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/templates/skills/task-developer/SKILL.md +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/templates/skills/task-qa/SKILL.md +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/templates/skills/task-security-reviewer/SKILL.md +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/test_admin_api.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/test_admin_cli.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/test_agent_cli.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/test_executor.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/test_init_cli.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/test_memory_index.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/test_setup_wizard.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/test_start_cli.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/workflow_graph.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee_admin/__init__.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee_admin/codee_admin.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee_agent_abstract/__init__.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee_agent_abstract/provider.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee_agent_claude_code/__init__.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee_agent_github_copilot/__init__.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee_database/__init__.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee_database/database.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee_database/oauth_tokens.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee_main_context/__init__.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee_main_context/context.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee_main_context/logging.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee_main_context/test_context.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee_main_context/test_logging.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee_tasks_abstract/__init__.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee_tasks_abstract/provider.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee_tasks_azure_devops/__init__.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee_tasks_azure_devops/oauth.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee_tasks_jira/__init__.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee_tasks_jira/provider.py +0 -0
- {codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee_tasks_jira/test.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codee-agent
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.6
|
|
4
4
|
Summary: A virtual co-worker that picks up Jira and Azure DevOps tasks and solves them with coding agents.
|
|
5
5
|
Keywords: ai,agent,jira,azure-devops,claude-code,github-copilot,automation
|
|
6
6
|
Author: Denis Kibalko
|
|
@@ -1719,7 +1719,7 @@ class SetupTasksMcpTest(unittest.TestCase):
|
|
|
1719
1719
|
config = self._config(root)
|
|
1720
1720
|
self.assertEqual(config["mcpServers"]["ado"], {
|
|
1721
1721
|
"command": "npx",
|
|
1722
|
-
"args": ["-y", "@azure-devops/mcp", "acme",
|
|
1722
|
+
"args": ["-y", "@azure-devops/mcp@2.8.0", "acme",
|
|
1723
1723
|
"--authentication", "azcli"],
|
|
1724
1724
|
})
|
|
1725
1725
|
self.assertEqual(config["servers"]["ado"]["type"], "stdio")
|
|
@@ -72,31 +72,35 @@ class ClaudeCodeAgent(AbstractCodingAgent):
|
|
|
72
72
|
cmd,
|
|
73
73
|
capture_output=True,
|
|
74
74
|
text=True,
|
|
75
|
+
encoding="utf-8",
|
|
76
|
+
errors="replace",
|
|
75
77
|
timeout=self.TIMEOUT_SECONDS,
|
|
76
78
|
cwd=self._cwd,
|
|
77
79
|
)
|
|
78
80
|
except subprocess.TimeoutExpired:
|
|
79
81
|
raise RuntimeError("Claude CLI timed out after 2 hours")
|
|
80
82
|
|
|
83
|
+
stdout = result.stdout or ""
|
|
84
|
+
stderr = result.stderr or ""
|
|
81
85
|
log.debug("claude exited %d (%d bytes stdout, %d bytes stderr)",
|
|
82
|
-
|
|
86
|
+
result.returncode, len(stdout), len(stderr))
|
|
83
87
|
|
|
84
88
|
# Raise on any non-success so callers retry. Over-limit exits non-zero;
|
|
85
89
|
# a completed-but-errored run sets is_error in the JSON.
|
|
86
90
|
if result.returncode != 0:
|
|
87
91
|
raise RuntimeError(
|
|
88
|
-
f"Claude CLI exited {result.returncode}: {
|
|
92
|
+
f"Claude CLI exited {result.returncode}: {stderr.strip()[:500]}"
|
|
89
93
|
)
|
|
90
94
|
|
|
91
95
|
try:
|
|
92
|
-
response = json.loads(
|
|
96
|
+
response = json.loads(stdout)
|
|
93
97
|
except json.JSONDecodeError:
|
|
94
|
-
return
|
|
98
|
+
return stdout
|
|
95
99
|
if isinstance(response, dict):
|
|
96
100
|
if response.get("is_error"):
|
|
97
101
|
raise RuntimeError(
|
|
98
102
|
f"Claude run errored ({response.get('subtype', 'unknown')}): "
|
|
99
103
|
f"{str(response.get('result', ''))[:500]}"
|
|
100
104
|
)
|
|
101
|
-
return response.get("result",
|
|
102
|
-
return
|
|
105
|
+
return response.get("result", stdout)
|
|
106
|
+
return stdout
|
|
@@ -34,6 +34,20 @@ class ClaudeCodeRunTest(unittest.TestCase):
|
|
|
34
34
|
|
|
35
35
|
self.assertEqual(cmd[cmd.index("--model") + 1], "opus")
|
|
36
36
|
|
|
37
|
+
def test_cli_output_is_decoded_as_utf8(self) -> None:
|
|
38
|
+
with patch("subprocess.run", return_value=_completed()) as run:
|
|
39
|
+
self.agent.run("/do-it CORE-1", SESSION)
|
|
40
|
+
|
|
41
|
+
self.assertEqual(run.call_args.kwargs["encoding"], "utf-8")
|
|
42
|
+
self.assertEqual(run.call_args.kwargs["errors"], "replace")
|
|
43
|
+
|
|
44
|
+
def test_missing_captured_streams_do_not_raise_type_error(self) -> None:
|
|
45
|
+
completed = subprocess.CompletedProcess(
|
|
46
|
+
args=["claude"], returncode=0, stdout=None, stderr=None)
|
|
47
|
+
|
|
48
|
+
with patch("subprocess.run", return_value=completed):
|
|
49
|
+
self.assertEqual(self.agent.run("/do-it CORE-1", SESSION), "")
|
|
50
|
+
|
|
37
51
|
def test_the_best_model_is_a_version_free_alias(self) -> None:
|
|
38
52
|
# The alias tracks the newest Opus, so no release needs an edit here.
|
|
39
53
|
self.assertEqual(ClaudeCodeAgent.best_model(), "opus")
|
|
@@ -102,16 +102,20 @@ class GitHubCopilotAgent(AbstractCodingAgent):
|
|
|
102
102
|
cmd,
|
|
103
103
|
capture_output=True,
|
|
104
104
|
text=True,
|
|
105
|
+
encoding="utf-8",
|
|
106
|
+
errors="replace",
|
|
105
107
|
timeout=self.TIMEOUT_SECONDS,
|
|
106
108
|
cwd=self._cwd,
|
|
107
109
|
)
|
|
108
110
|
except subprocess.TimeoutExpired:
|
|
109
111
|
raise RuntimeError("Copilot CLI timed out after 2 hours")
|
|
110
112
|
|
|
113
|
+
stdout = result.stdout or ""
|
|
114
|
+
stderr = result.stderr or ""
|
|
111
115
|
log.debug("copilot exited %d (%d bytes stdout, %d bytes stderr)",
|
|
112
|
-
result.returncode, len(
|
|
116
|
+
result.returncode, len(stdout), len(stderr))
|
|
113
117
|
|
|
114
|
-
reply, outcome, errors = _parse_events(
|
|
118
|
+
reply, outcome, errors = _parse_events(stdout)
|
|
115
119
|
|
|
116
120
|
# Raise on any non-success so callers retry. A run that fails before the
|
|
117
121
|
# session starts (bad model, no auth) exits non-zero with nothing on
|
|
@@ -119,22 +123,22 @@ class GitHubCopilotAgent(AbstractCodingAgent):
|
|
|
119
123
|
if result.returncode != 0:
|
|
120
124
|
raise RuntimeError(
|
|
121
125
|
f"Copilot CLI exited {result.returncode}: "
|
|
122
|
-
f"{_detail(errors,
|
|
126
|
+
f"{_detail(errors, stderr)}"
|
|
123
127
|
)
|
|
124
128
|
if outcome is None:
|
|
125
129
|
# Not the JSONL we know how to read — hand back whatever it printed
|
|
126
130
|
# rather than failing a run that the CLI itself called successful.
|
|
127
131
|
log.warning(
|
|
128
132
|
"copilot produced no result event; returning raw output")
|
|
129
|
-
return
|
|
133
|
+
return stdout
|
|
130
134
|
if outcome.get("exitCode"):
|
|
131
135
|
raise RuntimeError(
|
|
132
136
|
f"Copilot run errored (exit code {outcome['exitCode']}): "
|
|
133
|
-
f"{_detail(errors,
|
|
137
|
+
f"{_detail(errors, stderr)}"
|
|
134
138
|
)
|
|
135
139
|
if not reply:
|
|
136
140
|
raise RuntimeError(
|
|
137
|
-
f"Copilot run produced no response: {_detail(errors,
|
|
141
|
+
f"Copilot run produced no response: {_detail(errors, stderr)}"
|
|
138
142
|
)
|
|
139
143
|
return reply
|
|
140
144
|
|
|
@@ -152,6 +156,8 @@ def _fetch_acp_models() -> list[AgentModel]:
|
|
|
152
156
|
stdout=subprocess.PIPE,
|
|
153
157
|
stderr=subprocess.PIPE,
|
|
154
158
|
text=True,
|
|
159
|
+
encoding="utf-8",
|
|
160
|
+
errors="replace",
|
|
155
161
|
bufsize=1,
|
|
156
162
|
cwd=Path.cwd(),
|
|
157
163
|
)
|
|
@@ -71,6 +71,14 @@ class CopilotRunTest(unittest.TestCase):
|
|
|
71
71
|
for flag in ("--allow-all", "--no-ask-user", "--output-format"):
|
|
72
72
|
self.assertIn(flag, cmd)
|
|
73
73
|
self.assertEqual(self.captured.call_args.kwargs["cwd"], Path("/repo"))
|
|
74
|
+
self.assertEqual(self.captured.call_args.kwargs["encoding"], "utf-8")
|
|
75
|
+
self.assertEqual(self.captured.call_args.kwargs["errors"], "replace")
|
|
76
|
+
|
|
77
|
+
def test_missing_captured_streams_do_not_raise_type_error(self) -> None:
|
|
78
|
+
completed = subprocess.CompletedProcess(
|
|
79
|
+
args=["copilot"], returncode=0, stdout=None, stderr=None)
|
|
80
|
+
|
|
81
|
+
self.assertEqual(self._run(completed), "")
|
|
74
82
|
|
|
75
83
|
def test_the_skill_model_is_passed_on_the_command_line(self) -> None:
|
|
76
84
|
stdout = _stream(_event("assistant.message", {"content": "ok"}),
|
|
@@ -194,7 +202,7 @@ class CopilotModelCatalogTest(unittest.TestCase):
|
|
|
194
202
|
{"name": "nameless"}, # no id at all: unusable, skipped
|
|
195
203
|
]}}
|
|
196
204
|
|
|
197
|
-
with patch("codee_agent_github_copilot.provider.subprocess.Popen"), \
|
|
205
|
+
with patch("codee_agent_github_copilot.provider.subprocess.Popen") as popen, \
|
|
198
206
|
patch("codee_agent_github_copilot.provider._send"), \
|
|
199
207
|
patch("codee_agent_github_copilot.provider._await_result",
|
|
200
208
|
return_value=result):
|
|
@@ -202,6 +210,8 @@ class CopilotModelCatalogTest(unittest.TestCase):
|
|
|
202
210
|
|
|
203
211
|
self.assertEqual([(m.id, m.name) for m in models],
|
|
204
212
|
[("claude-opus-5", "Claude Opus 5"), ("gpt-5.4", "gpt-5.4")])
|
|
213
|
+
self.assertEqual(popen.call_args.kwargs["encoding"], "utf-8")
|
|
214
|
+
self.assertEqual(popen.call_args.kwargs["errors"], "replace")
|
|
205
215
|
|
|
206
216
|
def test_an_unavailable_cli_yields_no_models_rather_than_raising(self) -> None:
|
|
207
217
|
with patch("codee_agent_github_copilot.provider.subprocess.Popen",
|
|
@@ -44,8 +44,10 @@ _FIELDS = [
|
|
|
44
44
|
_PRIORITY_NAMES = {1: "Highest", 2: "High", 3: "Medium", 4: "Low"}
|
|
45
45
|
|
|
46
46
|
# Microsoft's own Azure DevOps MCP server, run from npm through `npx` so
|
|
47
|
-
# nothing has to be installed alongside it.
|
|
48
|
-
|
|
47
|
+
# nothing has to be installed alongside it. Version 2.8.0 keeps work item
|
|
48
|
+
# creation compatible with coding agents that stringify the consolidated
|
|
49
|
+
# write tool's fields parameter introduced in 2.9.0.
|
|
50
|
+
MCP_SERVER_PACKAGE = "@azure-devops/mcp@2.8.0"
|
|
49
51
|
|
|
50
52
|
# Ceiling the WIQL query is capped at, matching the JIRA provider's page size.
|
|
51
53
|
_MAX_TASKS = 50
|
|
@@ -629,7 +629,7 @@ class AzureDevOpsMcpTest(unittest.TestCase):
|
|
|
629
629
|
|
|
630
630
|
self.assertEqual(server.name, "ado")
|
|
631
631
|
self.assertEqual(server.command, "npx")
|
|
632
|
-
self.assertEqual(server.args, ["-y", "@azure-devops/mcp", "acme",
|
|
632
|
+
self.assertEqual(server.args, ["-y", "@azure-devops/mcp@2.8.0", "acme",
|
|
633
633
|
"--authentication", "azcli"])
|
|
634
634
|
# It signs in through `az login`, so it carries no credentials of ours.
|
|
635
635
|
self.assertEqual(server.env, {})
|
|
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
|
{codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/templates/skills/aws-sqs-alarm-response/SKILL.md
RENAMED
|
File without changes
|
{codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/templates/skills/cron-research-5xx-errors/SKILL.md
RENAMED
|
File without changes
|
{codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/templates/skills/story-code-reviewer/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/templates/skills/story-security-reviewer/SKILL.md
RENAMED
|
File without changes
|
{codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/templates/skills/task-code-reviewer/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{codee_agent-0.5.4 → codee_agent-0.5.6}/src/codee/templates/skills/task-security-reviewer/SKILL.md
RENAMED
|
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
|