gemcode 0.3.54__tar.gz → 0.3.56__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.
Files changed (121) hide show
  1. {gemcode-0.3.54/src/gemcode.egg-info → gemcode-0.3.56}/PKG-INFO +1 -1
  2. {gemcode-0.3.54 → gemcode-0.3.56}/pyproject.toml +1 -1
  3. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/capability_routing.py +4 -0
  4. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/model_routing.py +4 -1
  5. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/repl_slash.py +15 -0
  6. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/session_runtime.py +76 -24
  7. {gemcode-0.3.54 → gemcode-0.3.56/src/gemcode.egg-info}/PKG-INFO +1 -1
  8. {gemcode-0.3.54 → gemcode-0.3.56}/LICENSE +0 -0
  9. {gemcode-0.3.54 → gemcode-0.3.56}/MANIFEST.in +0 -0
  10. {gemcode-0.3.54 → gemcode-0.3.56}/README.md +0 -0
  11. {gemcode-0.3.54 → gemcode-0.3.56}/setup.cfg +0 -0
  12. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/__init__.py +0 -0
  13. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/__main__.py +0 -0
  14. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/agent.py +0 -0
  15. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/audit.py +0 -0
  16. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/autocompact.py +0 -0
  17. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/callbacks.py +0 -0
  18. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/cli.py +0 -0
  19. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/compaction.py +0 -0
  20. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/computer_use/__init__.py +0 -0
  21. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/computer_use/browser_computer.py +0 -0
  22. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/config.py +0 -0
  23. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/context_budget.py +0 -0
  24. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/context_warning.py +0 -0
  25. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/credentials.py +0 -0
  26. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/hitl_session.py +0 -0
  27. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/hooks.py +0 -0
  28. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/intent_classifier.py +0 -0
  29. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/interactions.py +0 -0
  30. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/invoke.py +0 -0
  31. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/kairos_daemon.py +0 -0
  32. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/limits.py +0 -0
  33. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/live_audio_engine.py +0 -0
  34. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/logging_config.py +0 -0
  35. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/mcp_loader.py +0 -0
  36. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/memory/__init__.py +0 -0
  37. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/memory/embedding_memory_service.py +0 -0
  38. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/memory/file_memory_service.py +0 -0
  39. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/modality_tools.py +0 -0
  40. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/model_errors.py +0 -0
  41. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/openapi_loader.py +0 -0
  42. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/paths.py +0 -0
  43. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/permissions.py +0 -0
  44. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/plugins/__init__.py +0 -0
  45. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/plugins/terminal_hooks_plugin.py +0 -0
  46. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/plugins/tool_recovery_plugin.py +0 -0
  47. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/pricing.py +0 -0
  48. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/prompt_suggestions.py +0 -0
  49. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/query/__init__.py +0 -0
  50. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/query/config.py +0 -0
  51. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/query/deps.py +0 -0
  52. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/query/engine.py +0 -0
  53. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/query/stop_hooks.py +0 -0
  54. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/query/token_budget.py +0 -0
  55. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/query/transitions.py +0 -0
  56. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/refine.py +0 -0
  57. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/repl_commands.py +0 -0
  58. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/review_agent.py +0 -0
  59. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/session_store.py +0 -0
  60. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/slash_commands.py +0 -0
  61. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/thinking.py +0 -0
  62. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/tool_prompt_manifest.py +0 -0
  63. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/tool_registry.py +0 -0
  64. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/tools/__init__.py +0 -0
  65. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/tools/bash.py +0 -0
  66. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/tools/browser.py +0 -0
  67. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/tools/edit.py +0 -0
  68. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/tools/filesystem.py +0 -0
  69. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/tools/notes.py +0 -0
  70. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/tools/search.py +0 -0
  71. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/tools/shell.py +0 -0
  72. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/tools/shell_gate.py +0 -0
  73. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/tools/subtask.py +0 -0
  74. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/tools/think.py +0 -0
  75. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/tools/todo.py +0 -0
  76. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/tools/web.py +0 -0
  77. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/tools_inspector.py +0 -0
  78. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/trust.py +0 -0
  79. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/tui/input_handler.py +0 -0
  80. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/tui/scrollback.py +0 -0
  81. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/tui/spinner.py +0 -0
  82. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/tui/welcome_banner.py +0 -0
  83. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/tui/welcome_rich.py +0 -0
  84. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/version.py +0 -0
  85. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/vertex.py +0 -0
  86. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/web/__init__.py +0 -0
  87. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/web/claude_sse_adapter.py +0 -0
  88. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/web/terminal_repl.py +0 -0
  89. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode/workspace_hints.py +0 -0
  90. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode.egg-info/SOURCES.txt +0 -0
  91. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode.egg-info/dependency_links.txt +0 -0
  92. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode.egg-info/entry_points.txt +0 -0
  93. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode.egg-info/requires.txt +0 -0
  94. {gemcode-0.3.54 → gemcode-0.3.56}/src/gemcode.egg-info/top_level.txt +0 -0
  95. {gemcode-0.3.54 → gemcode-0.3.56}/tests/test_agent_instruction.py +0 -0
  96. {gemcode-0.3.54 → gemcode-0.3.56}/tests/test_autocompact.py +0 -0
  97. {gemcode-0.3.54 → gemcode-0.3.56}/tests/test_capability_routing.py +0 -0
  98. {gemcode-0.3.54 → gemcode-0.3.56}/tests/test_claude_web_adapter_sse.py +0 -0
  99. {gemcode-0.3.54 → gemcode-0.3.56}/tests/test_cli_init.py +0 -0
  100. {gemcode-0.3.54 → gemcode-0.3.56}/tests/test_computer_use_permissions.py +0 -0
  101. {gemcode-0.3.54 → gemcode-0.3.56}/tests/test_context_budget.py +0 -0
  102. {gemcode-0.3.54 → gemcode-0.3.56}/tests/test_context_warning.py +0 -0
  103. {gemcode-0.3.54 → gemcode-0.3.56}/tests/test_credentials.py +0 -0
  104. {gemcode-0.3.54 → gemcode-0.3.56}/tests/test_interactive_permission_ask.py +0 -0
  105. {gemcode-0.3.54 → gemcode-0.3.56}/tests/test_kairos_scheduler.py +0 -0
  106. {gemcode-0.3.54 → gemcode-0.3.56}/tests/test_modality_tools.py +0 -0
  107. {gemcode-0.3.54 → gemcode-0.3.56}/tests/test_model_error_retry.py +0 -0
  108. {gemcode-0.3.54 → gemcode-0.3.56}/tests/test_model_errors.py +0 -0
  109. {gemcode-0.3.54 → gemcode-0.3.56}/tests/test_model_routing.py +0 -0
  110. {gemcode-0.3.54 → gemcode-0.3.56}/tests/test_paths.py +0 -0
  111. {gemcode-0.3.54 → gemcode-0.3.56}/tests/test_permissions.py +0 -0
  112. {gemcode-0.3.54 → gemcode-0.3.56}/tests/test_prompt_suggestions.py +0 -0
  113. {gemcode-0.3.54 → gemcode-0.3.56}/tests/test_repl_commands.py +0 -0
  114. {gemcode-0.3.54 → gemcode-0.3.56}/tests/test_repl_slash.py +0 -0
  115. {gemcode-0.3.54 → gemcode-0.3.56}/tests/test_slash_commands.py +0 -0
  116. {gemcode-0.3.54 → gemcode-0.3.56}/tests/test_thinking_config.py +0 -0
  117. {gemcode-0.3.54 → gemcode-0.3.56}/tests/test_token_budget.py +0 -0
  118. {gemcode-0.3.54 → gemcode-0.3.56}/tests/test_tool_context_circulation.py +0 -0
  119. {gemcode-0.3.54 → gemcode-0.3.56}/tests/test_tools.py +0 -0
  120. {gemcode-0.3.54 → gemcode-0.3.56}/tests/test_tools_inspector.py +0 -0
  121. {gemcode-0.3.54 → gemcode-0.3.56}/tests/test_workspace_hints.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gemcode
3
- Version: 0.3.54
3
+ Version: 0.3.56
4
4
  Summary: Local-first coding agent on Google Gemini + ADK
5
5
  Author: GemCode Contributors
6
6
  License: Apache License
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "gemcode"
7
- version = "0.3.54"
7
+ version = "0.3.56"
8
8
  description = "Local-first coding agent on Google Gemini + ADK"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -94,6 +94,10 @@ def apply_capability_routing(
94
94
  cfg.enable_embeddings = True
95
95
 
96
96
  def enable_computer() -> None:
97
+ # Respect session-level unavailability (e.g. Playwright not installed).
98
+ # When computer-use is known-broken, auto-routing must not re-enable it.
99
+ if getattr(cfg, "_computer_use_available", True) is False:
100
+ return
97
101
  cfg.enable_computer_use = True
98
102
 
99
103
  def enable_audio() -> None:
@@ -60,7 +60,10 @@ def pick_effective_model(cfg: GemCodeConfig, prompt: str) -> str:
60
60
  # (Deep research already handled above.)
61
61
  if getattr(cfg, "enable_audio", False):
62
62
  return getattr(cfg, "model_audio_live", None) or cfg.model
63
- if getattr(cfg, "enable_computer_use", False):
63
+ # Only switch to the computer-use model when Playwright is actually available.
64
+ # `_computer_use_available` is set False by session_runtime when the probe fails,
65
+ # preventing an HTTP 400 ("model requires Computer Use tool") from the API.
66
+ if getattr(cfg, "enable_computer_use", False) and getattr(cfg, "_computer_use_available", True):
64
67
  return getattr(cfg, "model_computer_use", None) or cfg.model
65
68
 
66
69
  primary_fast = cfg.model
@@ -696,6 +696,15 @@ async def process_repl_slash(
696
696
  return ReplSlashResult(skip_model_turn=True)
697
697
 
698
698
  if args_s == "on":
699
+ # If the session has already determined computer-use is unavailable
700
+ # (Playwright missing), do not allow re-enabling without installing it
701
+ # and restarting the process.
702
+ if getattr(cfg, "_computer_use_available", True) is False:
703
+ out("computer_use: unavailable — Playwright browsers are not installed")
704
+ out("Run: python3 -m playwright install chromium")
705
+ out("Then restart GemCode and run: /computer on")
706
+ out()
707
+ return ReplSlashResult(skip_model_turn=True)
699
708
  cfg.enable_computer_use = True
700
709
  out("computer_use: on — Playwright Chromium browser automation enabled")
701
710
  out(" Runner will rebuild on the next turn to inject browser tools.")
@@ -911,6 +920,12 @@ async def process_repl_slash(
911
920
  out()
912
921
  return ReplSlashResult(skip_model_turn=True, force_rebuild_runner=True)
913
922
  if args_s in ("computer", "browser"):
923
+ if getattr(cfg, "_computer_use_available", True) is False:
924
+ out("enable_computer_use: unavailable — Playwright browsers are not installed")
925
+ out("Run: python3 -m playwright install chromium")
926
+ out("Then restart GemCode and re-enable computer-use.")
927
+ out()
928
+ return ReplSlashResult(skip_model_turn=True)
914
929
  cfg.enable_computer_use = True
915
930
  out("enable_computer_use: on (runner rebuilding…)")
916
931
  out("Tip: set GEMCODE_COMPUTER_HEADLESS=0 before starting gemcode to see the browser window.")
@@ -12,8 +12,13 @@ token budget helpers, and `GemCodeQueryEngine`.
12
12
  from __future__ import annotations
13
13
 
14
14
  import os
15
+ import warnings
15
16
  from pathlib import Path
16
17
 
18
+ # Suppress ADK's noisy "EXPERIMENTAL feature" UserWarning globally.
19
+ # Users get enough context from gemcode's own messages; the warning is redundant.
20
+ warnings.filterwarnings("ignore", category=UserWarning, message=".*EXPERIMENTAL.*")
21
+
17
22
  from google.adk.runners import Runner
18
23
  from google.adk.sessions.sqlite_session_service import SqliteSessionService
19
24
 
@@ -30,6 +35,29 @@ def session_db_path(cfg: GemCodeConfig) -> Path:
30
35
  return cfg.project_root / ".gemcode" / "sessions.sqlite"
31
36
 
32
37
 
38
+ def _playwright_available() -> bool:
39
+ """
40
+ Quick synchronous check: does a usable Playwright browser executable exist?
41
+
42
+ Runs playwright.sync_api.sync_playwright() briefly to resolve the browser
43
+ path, without actually launching a browser. Falls back to a path probe if
44
+ playwright is not installed.
45
+
46
+ Returns True only when Playwright AND at least one browser binary are present.
47
+ This is called before building the runner so we can disable computer-use
48
+ early and prevent model routing from switching to gemini-2.5-computer-use-*.
49
+ """
50
+ try:
51
+ from playwright.sync_api import sync_playwright
52
+ with sync_playwright() as p:
53
+ exe = p.chromium.executable_path
54
+ return bool(exe) and Path(exe).exists()
55
+ except Exception:
56
+ pass
57
+ # playwright not installed at all
58
+ return False
59
+
60
+
33
61
  def _make_safe_computer_toolset(computer):
34
62
  """
35
63
  Build a BaseToolset-compatible wrapper around ComputerUseToolset that catches
@@ -183,31 +211,55 @@ def create_runner(cfg: GemCodeConfig, extra_tools: list | None = None) -> Runner
183
211
  pass # OpenAPIToolset not in this ADK version — continue without
184
212
 
185
213
  # Computer-use: ADK ComputerUseToolset backed by our Playwright BrowserComputer.
186
- # Also inject standalone browser inspection tools (screenshot, get_text, etc.)
187
- # so the agent can read page state without performing side-effecting actions.
214
+ # Probe Playwright BEFORE building the agent so model routing (which runs
215
+ # inside build_root_agent pick_effective_model) never switches to
216
+ # gemini-2.5-computer-use-* when the browser binary is missing.
188
217
  if getattr(cfg, "enable_computer_use", False):
189
- headless_env = os.environ.get("GEMCODE_COMPUTER_HEADLESS", "1").lower()
190
- headless = headless_env in ("1", "true", "yes", "on")
191
- viewport_w = int(os.environ.get("GEMCODE_BROWSER_WIDTH", "1280"))
192
- viewport_h = int(os.environ.get("GEMCODE_BROWSER_HEIGHT", "720"))
193
- from gemcode.computer_use.browser_computer import BrowserComputer
194
-
195
- computer = BrowserComputer(
196
- headless=headless,
197
- viewport_size=(viewport_w, viewport_h),
198
- )
199
- computer_toolset = _make_safe_computer_toolset(computer)
200
- merged_extra_tools = list(merged_extra_tools or [])
201
- if computer_toolset is not None:
202
- merged_extra_tools.append(computer_toolset)
203
-
204
- # Standalone read-only browser tools (browser_screenshot, browser_get_text, etc.)
205
- from gemcode.tools.browser import build_browser_inspection_tools
206
- browser_tools = build_browser_inspection_tools(cfg, computer)
207
- merged_extra_tools.extend(browser_tools)
208
-
209
- # Store reference on cfg so slash commands / TUI can check browser state.
210
- cfg._browser_computer = computer # type: ignore[attr-defined]
218
+ if not _playwright_available():
219
+ import sys
220
+ print(
221
+ "\n[gemcode] Browser (computer-use) is unavailable — Playwright browsers "
222
+ "are not installed.\n"
223
+ " Run: playwright install chromium\n"
224
+ " Then restart GemCode with /computer on (or --computer flag).\n"
225
+ " Disabling computer-use for this session.\n",
226
+ file=sys.stderr,
227
+ )
228
+ # Disable so model_routing stays on the normal model (not computer-use preview).
229
+ cfg.enable_computer_use = False
230
+ cfg._computer_use_available = False # type: ignore[attr-defined]
231
+ # If the TUI already routed the model to the computer-use preview model for
232
+ # this turn, reset back to the normal model so the next agent construction
233
+ # doesn't keep using a model that requires the missing tool.
234
+ try:
235
+ if not getattr(cfg, "model_overridden", False) and cfg.model == cfg.model_computer_use:
236
+ cfg.model = os.environ.get("GEMCODE_MODEL", "gemini-3.1-pro-preview")
237
+ except Exception:
238
+ pass
239
+ else:
240
+ cfg._computer_use_available = True # type: ignore[attr-defined]
241
+ headless_env = os.environ.get("GEMCODE_COMPUTER_HEADLESS", "1").lower()
242
+ headless = headless_env in ("1", "true", "yes", "on")
243
+ viewport_w = int(os.environ.get("GEMCODE_BROWSER_WIDTH", "1280"))
244
+ viewport_h = int(os.environ.get("GEMCODE_BROWSER_HEIGHT", "720"))
245
+ from gemcode.computer_use.browser_computer import BrowserComputer
246
+
247
+ computer = BrowserComputer(
248
+ headless=headless,
249
+ viewport_size=(viewport_w, viewport_h),
250
+ )
251
+ computer_toolset = _make_safe_computer_toolset(computer)
252
+ merged_extra_tools = list(merged_extra_tools or [])
253
+ if computer_toolset is not None:
254
+ merged_extra_tools.append(computer_toolset)
255
+
256
+ # Standalone read-only browser tools (browser_screenshot, browser_get_text, etc.)
257
+ from gemcode.tools.browser import build_browser_inspection_tools
258
+ browser_tools = build_browser_inspection_tools(cfg, computer)
259
+ merged_extra_tools.extend(browser_tools)
260
+
261
+ # Store reference on cfg so slash commands / TUI can check browser state.
262
+ cfg._browser_computer = computer # type: ignore[attr-defined]
211
263
 
212
264
  agent = build_root_agent(cfg, extra_tools=merged_extra_tools)
213
265
  db = session_db_path(cfg)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gemcode
3
- Version: 0.3.54
3
+ Version: 0.3.56
4
4
  Summary: Local-first coding agent on Google Gemini + ADK
5
5
  Author: GemCode Contributors
6
6
  License: Apache License
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes