cinna-cli 0.2.4__tar.gz → 0.2.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.
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/PKG-INFO +1 -1
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/pyproject.toml +1 -1
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/src/cinna/chat.py +51 -1
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/tests/test_chat.py +106 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/uv.lock +1 -1
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/.claude/commands/cinna-cli.feature.doc.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/.github/workflows/publish.yml +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/.gitignore +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/LICENSE.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/README.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/README.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/account_workspace/account_workspace.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/account_workspace/account_workspace_acceptance.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/account_workspace/account_workspace_tech.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/agent_api/agent_api.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/agent_api/agent_api_acceptance.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/agent_api/agent_api_tech.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/agent_management/agent_management.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/agent_management/agent_management_acceptance.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/agent_management/agent_management_tech.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/agent_schedules/agent_schedules.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/agent_schedules/agent_schedules_acceptance.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/agent_schedules/agent_schedules_tech.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/bootstrap_onboarding/bootstrap_onboarding.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/bootstrap_onboarding/bootstrap_onboarding_acceptance.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/bootstrap_onboarding/bootstrap_onboarding_tech.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/doctor/doctor.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/doctor/doctor_acceptance.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/doctor/doctor_tech.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/git_versioning/git_versioning.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/git_versioning/git_versioning_acceptance.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/git_versioning/git_versioning_tech.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/live_sync/live_sync.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/live_sync/live_sync_acceptance.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/live_sync/live_sync_tech.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/mcp_integration/mcp_integration.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/mcp_integration/mcp_integration_acceptance.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/mcp_integration/mcp_integration_tech.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/remote_chat/remote_chat.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/remote_chat/remote_chat_acceptance.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/remote_chat/remote_chat_tech.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/remote_exec/remote_exec.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/remote_exec/remote_exec_acceptance.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/remote_exec/remote_exec_tech.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/interface.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/mutagen_capabilities.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/scripts/check_docs_references.py +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/src/cinna/__init__.py +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/src/cinna/account.py +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/src/cinna/auth.py +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/src/cinna/bootstrap.py +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/src/cinna/client.py +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/src/cinna/config.py +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/src/cinna/console.py +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/src/cinna/context.py +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/src/cinna/doctor.py +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/src/cinna/errors.py +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/src/cinna/git_versioning.py +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/src/cinna/logging.py +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/src/cinna/main.py +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/src/cinna/mcp_proxy.py +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/src/cinna/mutagen_runtime.py +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/src/cinna/sync.py +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/src/cinna/sync_session.py +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/src/cinna/sync_ssh_shim.py +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/src/cinna/sync_tui.py +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/src/cinna/templates/ACCOUNT_CLAUDE.md.template +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/src/cinna/templates/CHAT_TESTING.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/src/cinna/templates/CLAUDE.md.template +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/src/cinna/templates/GIT_VERSIONING.md +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/src/cinna/templates/__init__.py +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/tests/__init__.py +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/tests/conftest.py +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/tests/test_account.py +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/tests/test_auth.py +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/tests/test_bootstrap.py +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/tests/test_client.py +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/tests/test_config.py +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/tests/test_context.py +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/tests/test_doctor.py +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/tests/test_git_versioning.py +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/tests/test_main.py +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/tests/test_mutagen_runtime.py +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/tests/test_sync.py +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/tests/test_sync_session.py +0 -0
- {cinna_cli-0.2.4 → cinna_cli-0.2.5}/tests/test_sync_ssh_shim.py +0 -0
|
@@ -104,6 +104,24 @@ class _Emitter:
|
|
|
104
104
|
console.console.print(f" [dim]📎 {att.get('filename')} → {loc}[/dim]")
|
|
105
105
|
elif kind == "status":
|
|
106
106
|
console.console.print(f"[dim]· {event.get('state')}…[/dim]")
|
|
107
|
+
elif kind == "delta":
|
|
108
|
+
for ev in event.get("events", []):
|
|
109
|
+
etype = ev.get("type")
|
|
110
|
+
if etype == "assistant":
|
|
111
|
+
if ev.get("content"):
|
|
112
|
+
console.console.print(ev["content"], end="")
|
|
113
|
+
elif etype == "thinking":
|
|
114
|
+
console.console.print(
|
|
115
|
+
f" [magenta]🧠 thinking:[/magenta] {ev.get('content', '')}"
|
|
116
|
+
)
|
|
117
|
+
elif etype in ("tool", "tool_use"):
|
|
118
|
+
payload = ev.get("tool_input")
|
|
119
|
+
console.console.print(
|
|
120
|
+
f" [cyan]🔧 {ev.get('tool_name', 'tool')}[/cyan] "
|
|
121
|
+
f"[dim]{json.dumps(payload, ensure_ascii=False) if payload is not None else ''}[/dim]"
|
|
122
|
+
)
|
|
123
|
+
elif ev.get("content"):
|
|
124
|
+
console.console.print(f" [dim]{etype}: {ev['content']}[/dim]")
|
|
107
125
|
elif kind == "done":
|
|
108
126
|
console.console.print(
|
|
109
127
|
f"[dim]done — result: {event.get('result_state')}[/dim]"
|
|
@@ -274,6 +292,12 @@ def _poll_turn(
|
|
|
274
292
|
start_deadline = started + START_GRACE_SECONDS
|
|
275
293
|
turn_started = not expect_turn
|
|
276
294
|
flagged_in_progress: set[str] = set()
|
|
295
|
+
# How much of an in-progress message's trace we've already surfaced —
|
|
296
|
+
# the row is periodically re-flushed server-side with its *full*
|
|
297
|
+
# accumulated ``streaming_events`` so far, so this is what lets us emit
|
|
298
|
+
# only what's new since the last poll instead of going silent until the
|
|
299
|
+
# whole (possibly many-minutes-long) message finalizes.
|
|
300
|
+
shown_event_count: dict[str, int] = {}
|
|
277
301
|
|
|
278
302
|
while True:
|
|
279
303
|
# Drain newly-finalized messages; stop at the first in-progress one
|
|
@@ -285,16 +309,19 @@ def _poll_turn(
|
|
|
285
309
|
advanced = False
|
|
286
310
|
for m in batch:
|
|
287
311
|
meta = m.get("message_metadata") or {}
|
|
312
|
+
mid = m.get("id")
|
|
288
313
|
if meta.get("streaming_in_progress"):
|
|
289
314
|
in_progress = True
|
|
290
|
-
mid = m.get("id")
|
|
291
315
|
if mid not in flagged_in_progress:
|
|
292
316
|
flagged_in_progress.add(mid)
|
|
293
317
|
emit.emit(
|
|
294
318
|
{"event": "status", "state": "working", "message_id": mid}
|
|
295
319
|
)
|
|
320
|
+
if include_events:
|
|
321
|
+
_emit_delta(emit, m, shown_event_count)
|
|
296
322
|
break
|
|
297
323
|
_emit_message(client, emit, m, dl_dir, include_events)
|
|
324
|
+
shown_event_count.pop(mid, None)
|
|
298
325
|
consumed += 1
|
|
299
326
|
advanced = True
|
|
300
327
|
if m.get("role") and m["role"] != "user":
|
|
@@ -328,6 +355,29 @@ def _poll_turn(
|
|
|
328
355
|
_emit_done(client, emit, session_id)
|
|
329
356
|
|
|
330
357
|
|
|
358
|
+
def _emit_delta(
|
|
359
|
+
emit: _Emitter,
|
|
360
|
+
m: dict,
|
|
361
|
+
shown_event_count: dict[str, int],
|
|
362
|
+
) -> None:
|
|
363
|
+
"""Emit trace events newly appended to a still-in-progress message.
|
|
364
|
+
|
|
365
|
+
``streaming_events`` (thinking blocks, tool calls, tool results, and
|
|
366
|
+
individual assistant-text chunks) accumulates on the row as the turn
|
|
367
|
+
progresses and is what the server periodically flushes; this diffs
|
|
368
|
+
against what's already been shown for this message id so a long-running
|
|
369
|
+
turn surfaces gradual output instead of nothing until it finalizes.
|
|
370
|
+
"""
|
|
371
|
+
mid = m.get("id")
|
|
372
|
+
events = _extract_events(m)
|
|
373
|
+
prev_count = shown_event_count.get(mid, 0)
|
|
374
|
+
new_events = events[prev_count:]
|
|
375
|
+
if not new_events:
|
|
376
|
+
return
|
|
377
|
+
emit.emit({"event": "delta", "message_id": mid, "role": m.get("role"), "events": new_events})
|
|
378
|
+
shown_event_count[mid] = len(events)
|
|
379
|
+
|
|
380
|
+
|
|
331
381
|
def _emit_message(
|
|
332
382
|
client: AccountClient,
|
|
333
383
|
emit: _Emitter,
|
|
@@ -165,6 +165,81 @@ class FakeClient:
|
|
|
165
165
|
return {}
|
|
166
166
|
|
|
167
167
|
|
|
168
|
+
class FakeStreamingClient(FakeClient):
|
|
169
|
+
"""Scripts a turn whose agent message streams in two chunks before it
|
|
170
|
+
finalizes — models a long-running turn so progressive delta emission can
|
|
171
|
+
be exercised (see test_chat_streams_progressive_deltas_while_in_progress)."""
|
|
172
|
+
|
|
173
|
+
def __init__(self):
|
|
174
|
+
super().__init__()
|
|
175
|
+
self.poll_count = 0
|
|
176
|
+
|
|
177
|
+
def _user_msg(self):
|
|
178
|
+
return {
|
|
179
|
+
"id": "m1",
|
|
180
|
+
"role": "user",
|
|
181
|
+
"sequence_number": 1,
|
|
182
|
+
"timestamp": "2026-06-22T00:00:00Z",
|
|
183
|
+
"content": self.last_content,
|
|
184
|
+
"message_metadata": {},
|
|
185
|
+
"files": [],
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
def _agent_msg(self):
|
|
189
|
+
thinking = {"type": "thinking", "event_seq": 1, "content": "Step one."}
|
|
190
|
+
tool = {
|
|
191
|
+
"type": "tool",
|
|
192
|
+
"event_seq": 2,
|
|
193
|
+
"tool_name": "calculator",
|
|
194
|
+
"content": "calculator",
|
|
195
|
+
"metadata": {"tool_id": "tool-1", "tool_input": {"expression": "2+2"}},
|
|
196
|
+
}
|
|
197
|
+
assistant = {"type": "assistant", "event_seq": 3, "content": "Here you go"}
|
|
198
|
+
base = {
|
|
199
|
+
"id": "m2",
|
|
200
|
+
"role": "agent",
|
|
201
|
+
"sequence_number": 2,
|
|
202
|
+
"timestamp": "2026-06-22T00:00:01Z",
|
|
203
|
+
"files": [],
|
|
204
|
+
}
|
|
205
|
+
if self.poll_count == 1:
|
|
206
|
+
return {
|
|
207
|
+
**base,
|
|
208
|
+
"content": "Agent is responding...",
|
|
209
|
+
"message_metadata": {
|
|
210
|
+
"streaming_in_progress": True,
|
|
211
|
+
"streaming_events": [thinking],
|
|
212
|
+
},
|
|
213
|
+
}
|
|
214
|
+
if self.poll_count == 2:
|
|
215
|
+
return {
|
|
216
|
+
**base,
|
|
217
|
+
"content": "Agent is responding...",
|
|
218
|
+
"message_metadata": {
|
|
219
|
+
"streaming_in_progress": True,
|
|
220
|
+
"streaming_events": [thinking, tool],
|
|
221
|
+
},
|
|
222
|
+
}
|
|
223
|
+
return {
|
|
224
|
+
**base,
|
|
225
|
+
"content": "Here you go",
|
|
226
|
+
"message_metadata": {"streaming_events": [thinking, tool, assistant]},
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
def get_messages(self, session_id, limit=100, offset=0):
|
|
230
|
+
if not self.sent:
|
|
231
|
+
return {"data": [], "count": 0}
|
|
232
|
+
self.poll_count += 1
|
|
233
|
+
if offset == 0:
|
|
234
|
+
return {"data": [self._user_msg(), self._agent_msg()], "count": 2}
|
|
235
|
+
if offset == 1:
|
|
236
|
+
return {"data": [self._agent_msg()], "count": 1}
|
|
237
|
+
return {"data": [], "count": 0}
|
|
238
|
+
|
|
239
|
+
def get_streaming_status(self, session_id):
|
|
240
|
+
return {"is_streaming": self.poll_count < 3}
|
|
241
|
+
|
|
242
|
+
|
|
168
243
|
def _ndjson(output: str) -> list[dict]:
|
|
169
244
|
return [json.loads(line) for line in output.splitlines() if line.strip()]
|
|
170
245
|
|
|
@@ -247,6 +322,37 @@ def test_chat_no_events_flag_omits_trace(runner, account_root, monkeypatch):
|
|
|
247
322
|
assert agent_msg["content"] == "Here you go"
|
|
248
323
|
|
|
249
324
|
|
|
325
|
+
def test_chat_streams_progressive_deltas_while_in_progress(
|
|
326
|
+
runner, account_root, monkeypatch
|
|
327
|
+
):
|
|
328
|
+
"""A long-running turn (agent message stays `streaming_in_progress` across
|
|
329
|
+
several polls) surfaces its trace incrementally via `delta` events instead
|
|
330
|
+
of going silent until the whole message finalizes."""
|
|
331
|
+
monkeypatch.chdir(account_root)
|
|
332
|
+
fake = FakeStreamingClient()
|
|
333
|
+
monkeypatch.setattr("cinna.chat.AccountClient", lambda cfg: fake)
|
|
334
|
+
|
|
335
|
+
result = runner.invoke(
|
|
336
|
+
cli, ["chat", "--agent", "CRM Agent", "--interval", "0", "2+2"]
|
|
337
|
+
)
|
|
338
|
+
assert result.exit_code == 0, result.output
|
|
339
|
+
|
|
340
|
+
events = _ndjson(result.output)
|
|
341
|
+
deltas = [e for e in events if e["event"] == "delta"]
|
|
342
|
+
assert len(deltas) == 2
|
|
343
|
+
assert [ev["type"] for ev in deltas[0]["events"]] == ["thinking"]
|
|
344
|
+
# Second delta carries only the newly-appended event, not a repeat of
|
|
345
|
+
# what was already shown.
|
|
346
|
+
assert [ev["type"] for ev in deltas[1]["events"]] == ["tool"]
|
|
347
|
+
|
|
348
|
+
agent_msg = [
|
|
349
|
+
e
|
|
350
|
+
for e in events
|
|
351
|
+
if e["event"] == "message" and e["role"] == "agent"
|
|
352
|
+
][0]
|
|
353
|
+
assert agent_msg["content"] == "Here you go"
|
|
354
|
+
|
|
355
|
+
|
|
250
356
|
def test_chat_downloads_agent_attachment(runner, account_root, monkeypatch):
|
|
251
357
|
monkeypatch.chdir(account_root)
|
|
252
358
|
fake = FakeClient()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/account_workspace/account_workspace_acceptance.md
RENAMED
|
File without changes
|
{cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/account_workspace/account_workspace_tech.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/agent_management/agent_management_acceptance.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/agent_schedules/agent_schedules_acceptance.md
RENAMED
|
File without changes
|
|
File without changes
|
{cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/bootstrap_onboarding/bootstrap_onboarding.md
RENAMED
|
File without changes
|
|
File without changes
|
{cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/bootstrap_onboarding/bootstrap_onboarding_tech.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/git_versioning/git_versioning_acceptance.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cinna_cli-0.2.4 → cinna_cli-0.2.5}/docs/features/mcp_integration/mcp_integration_acceptance.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
|
|
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
|