gemcode 0.3.0__tar.gz → 0.3.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.
Files changed (100) hide show
  1. {gemcode-0.3.0/src/gemcode.egg-info → gemcode-0.3.2}/PKG-INFO +1 -1
  2. {gemcode-0.3.0 → gemcode-0.3.2}/pyproject.toml +1 -1
  3. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/agent.py +1 -1
  4. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/cli.py +31 -1
  5. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/tool_prompt_manifest.py +1 -1
  6. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/tools/shell.py +20 -9
  7. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/tui/app.py +1 -1
  8. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/tui/scrollback.py +1 -1
  9. {gemcode-0.3.0 → gemcode-0.3.2/src/gemcode.egg-info}/PKG-INFO +1 -1
  10. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode.egg-info/SOURCES.txt +1 -0
  11. gemcode-0.3.2/tests/test_cli_init.py +22 -0
  12. {gemcode-0.3.0 → gemcode-0.3.2}/tests/test_tools.py +18 -0
  13. {gemcode-0.3.0 → gemcode-0.3.2}/LICENSE +0 -0
  14. {gemcode-0.3.0 → gemcode-0.3.2}/MANIFEST.in +0 -0
  15. {gemcode-0.3.0 → gemcode-0.3.2}/README.md +0 -0
  16. {gemcode-0.3.0 → gemcode-0.3.2}/setup.cfg +0 -0
  17. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/__init__.py +0 -0
  18. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/__main__.py +0 -0
  19. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/audit.py +0 -0
  20. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/autocompact.py +0 -0
  21. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/callbacks.py +0 -0
  22. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/capability_routing.py +0 -0
  23. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/compaction.py +0 -0
  24. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/computer_use/__init__.py +0 -0
  25. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/computer_use/browser_computer.py +0 -0
  26. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/config.py +0 -0
  27. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/context_budget.py +0 -0
  28. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/context_warning.py +0 -0
  29. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/credentials.py +0 -0
  30. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/hitl_session.py +0 -0
  31. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/interactions.py +0 -0
  32. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/invoke.py +0 -0
  33. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/kairos_daemon.py +0 -0
  34. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/limits.py +0 -0
  35. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/live_audio_engine.py +0 -0
  36. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/mcp_loader.py +0 -0
  37. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/memory/__init__.py +0 -0
  38. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/memory/embedding_memory_service.py +0 -0
  39. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/memory/file_memory_service.py +0 -0
  40. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/modality_tools.py +0 -0
  41. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/model_errors.py +0 -0
  42. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/model_routing.py +0 -0
  43. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/paths.py +0 -0
  44. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/permissions.py +0 -0
  45. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/plugins/__init__.py +0 -0
  46. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/plugins/terminal_hooks_plugin.py +0 -0
  47. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/plugins/tool_recovery_plugin.py +0 -0
  48. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/prompt_suggestions.py +0 -0
  49. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/query/__init__.py +0 -0
  50. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/query/config.py +0 -0
  51. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/query/deps.py +0 -0
  52. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/query/engine.py +0 -0
  53. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/query/stop_hooks.py +0 -0
  54. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/query/token_budget.py +0 -0
  55. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/query/transitions.py +0 -0
  56. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/repl_commands.py +0 -0
  57. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/repl_slash.py +0 -0
  58. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/session_runtime.py +0 -0
  59. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/slash_commands.py +0 -0
  60. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/thinking.py +0 -0
  61. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/tool_registry.py +0 -0
  62. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/tools/__init__.py +0 -0
  63. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/tools/edit.py +0 -0
  64. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/tools/filesystem.py +0 -0
  65. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/tools/search.py +0 -0
  66. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/tools/shell_gate.py +0 -0
  67. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/tools/todo.py +0 -0
  68. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/tools_inspector.py +0 -0
  69. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/trust.py +0 -0
  70. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/vertex.py +0 -0
  71. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/web/__init__.py +0 -0
  72. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/web/claude_sse_adapter.py +0 -0
  73. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode/web/terminal_repl.py +0 -0
  74. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode.egg-info/dependency_links.txt +0 -0
  75. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode.egg-info/entry_points.txt +0 -0
  76. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode.egg-info/requires.txt +0 -0
  77. {gemcode-0.3.0 → gemcode-0.3.2}/src/gemcode.egg-info/top_level.txt +0 -0
  78. {gemcode-0.3.0 → gemcode-0.3.2}/tests/test_autocompact.py +0 -0
  79. {gemcode-0.3.0 → gemcode-0.3.2}/tests/test_capability_routing.py +0 -0
  80. {gemcode-0.3.0 → gemcode-0.3.2}/tests/test_claude_web_adapter_sse.py +0 -0
  81. {gemcode-0.3.0 → gemcode-0.3.2}/tests/test_computer_use_permissions.py +0 -0
  82. {gemcode-0.3.0 → gemcode-0.3.2}/tests/test_context_budget.py +0 -0
  83. {gemcode-0.3.0 → gemcode-0.3.2}/tests/test_context_warning.py +0 -0
  84. {gemcode-0.3.0 → gemcode-0.3.2}/tests/test_credentials.py +0 -0
  85. {gemcode-0.3.0 → gemcode-0.3.2}/tests/test_interactive_permission_ask.py +0 -0
  86. {gemcode-0.3.0 → gemcode-0.3.2}/tests/test_kairos_scheduler.py +0 -0
  87. {gemcode-0.3.0 → gemcode-0.3.2}/tests/test_modality_tools.py +0 -0
  88. {gemcode-0.3.0 → gemcode-0.3.2}/tests/test_model_error_retry.py +0 -0
  89. {gemcode-0.3.0 → gemcode-0.3.2}/tests/test_model_errors.py +0 -0
  90. {gemcode-0.3.0 → gemcode-0.3.2}/tests/test_model_routing.py +0 -0
  91. {gemcode-0.3.0 → gemcode-0.3.2}/tests/test_paths.py +0 -0
  92. {gemcode-0.3.0 → gemcode-0.3.2}/tests/test_permissions.py +0 -0
  93. {gemcode-0.3.0 → gemcode-0.3.2}/tests/test_prompt_suggestions.py +0 -0
  94. {gemcode-0.3.0 → gemcode-0.3.2}/tests/test_repl_commands.py +0 -0
  95. {gemcode-0.3.0 → gemcode-0.3.2}/tests/test_repl_slash.py +0 -0
  96. {gemcode-0.3.0 → gemcode-0.3.2}/tests/test_slash_commands.py +0 -0
  97. {gemcode-0.3.0 → gemcode-0.3.2}/tests/test_thinking_config.py +0 -0
  98. {gemcode-0.3.0 → gemcode-0.3.2}/tests/test_token_budget.py +0 -0
  99. {gemcode-0.3.0 → gemcode-0.3.2}/tests/test_tool_context_circulation.py +0 -0
  100. {gemcode-0.3.0 → gemcode-0.3.2}/tests/test_tools_inspector.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gemcode
3
- Version: 0.3.0
3
+ Version: 0.3.2
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.0"
7
+ version = "0.3.2"
8
8
  description = "Local-first coding agent on Google Gemini + ADK"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -74,7 +74,7 @@ You operate only inside the user's project directory (current working directory)
74
74
  - **`run_command` rules (critical):**
75
75
  - `command` must be a **single executable basename** (e.g. `npm`, `npx`, `mkdir`) — **not** `bash`, `sh`, or `cd foo && ...`.
76
76
  - Pass argv as `args` (list). To run a command **inside** a subfolder (e.g. Next app in `testing/`), set **`cwd_subdir`** to that relative path (e.g. `"testing"`) and run `npm run dev` there — **never** simulate `cd` with `bash`.
77
- - **Scaffolding** (`create-next-app`, etc.): many CLIs require non-interactive mode — pass **`extra_env`** like `{"CI": "1"}` and/or flags supported by that tool (`--yes` where documented).
77
+ - **Scaffolding** (`create-next-app`, etc.): many CLIs require non-interactive mode — pass **`extra_env_keys`** / **`extra_env_values`** as parallel lists (e.g. `["CI"]` and `["1"]`) and/or flags supported by that tool (`--yes` where documented).
78
78
  - **Dev servers** (`npm run dev`, `vite`, etc.) run until stopped: use **`background=True`** so the process detaches; otherwise the tool may time out. You cannot open a *new OS terminal window* from here—background start is the supported way to keep running.
79
79
  - **Parallelize:** when you need several **independent** reads or searches (no output from one is required to form the next call), issue them together in one turn so the user gets answers faster. When step B depends on step A's result, run **sequentially**.
80
80
  - **Deletion:** use `delete_file` for a single file under the project root; reserve `rm` via `run_command` for unusual cases.
@@ -49,6 +49,7 @@ def _maybe_prompt_trust(cfg: GemCodeConfig) -> None:
49
49
  return
50
50
  try:
51
51
  print(
52
+ "\n── GemCode setup (1/3) · Workspace permission ──\n"
52
53
  "GemCode needs full access to this workspace folder (files, shell, git):\n"
53
54
  f" {root}\n\n"
54
55
  "Trust this folder? [y/N] ",
@@ -86,7 +87,8 @@ def _maybe_prompt_google_api_key() -> None:
86
87
  return
87
88
  try:
88
89
  print(
89
- "\nGemCode needs a Google Gemini API key (saved once under ~/.gemcode/).\n"
90
+ "\n── GemCode setup (2/3) · API key ──\n"
91
+ "GemCode needs a Google Gemini API key (saved once under ~/.gemcode/).\n"
90
92
  "Create one at https://aistudio.google.com/app/apikey\n"
91
93
  "Paste your key and press Enter (input is hidden).\n",
92
94
  file=sys.stderr,
@@ -115,6 +117,32 @@ def require_google_api_key() -> None:
115
117
  )
116
118
 
117
119
 
120
+ def _initialize_gemcode_project(cfg: GemCodeConfig) -> None:
121
+ """
122
+ Create ``<project>/.gemcode/`` and print a short banner the first time it appears.
123
+
124
+ Runs after workspace trust + API key are satisfied so a bare ``gemcode`` REPL
125
+ feels like a guided first-run (Claude Code–style).
126
+ """
127
+ root = cfg.project_root.resolve()
128
+ gem_dir = root / ".gemcode"
129
+ already_there = gem_dir.is_dir()
130
+ try:
131
+ gem_dir.mkdir(parents=True, exist_ok=True)
132
+ except OSError as e:
133
+ print(f"[gemcode] warning: could not create {gem_dir}: {e}", file=sys.stderr)
134
+ return
135
+ if not already_there:
136
+ print(
137
+ "\n── GemCode · Project folder ready ──\n"
138
+ f" Workspace: {root}\n"
139
+ f" Config & session data: {gem_dir}/\n"
140
+ " Optional: add GEMINI.md in the repo root for project context.\n"
141
+ "── Ready. ──\n",
142
+ file=sys.stderr,
143
+ )
144
+
145
+
118
146
  async def _run_prompt(
119
147
  cfg: GemCodeConfig, prompt: str, session_id: str, *, use_mcp: bool
120
148
  ) -> str:
@@ -122,6 +150,7 @@ async def _run_prompt(
122
150
  _maybe_prompt_trust(cfg)
123
151
  _maybe_prompt_google_api_key()
124
152
  require_google_api_key()
153
+ _initialize_gemcode_project(cfg)
125
154
  extra: list = []
126
155
  if use_mcp:
127
156
  from gemcode.mcp_loader import load_mcp_toolsets
@@ -153,6 +182,7 @@ async def _run_repl(cfg: GemCodeConfig, session_id: str, *, use_mcp: bool) -> No
153
182
  _maybe_prompt_trust(cfg)
154
183
  _maybe_prompt_google_api_key()
155
184
  require_google_api_key()
185
+ _initialize_gemcode_project(cfg)
156
186
  extra: list = []
157
187
  if use_mcp:
158
188
  from gemcode.mcp_loader import load_mcp_toolsets
@@ -120,7 +120,7 @@ You may call tools as follows:
120
120
  Notes:
121
121
  - Prefer `python -m pip ...` (or `python3 -m pip ...`) so installs stay in the active virtualenv.
122
122
  - Do not assume sudo/system package manager access.
123
- - `run_command` supports `cwd_subdir` (relative path under the project) instead of `cd`/`bash`; use `extra_env` (e.g. CI=1) for non-interactive installers; use `background=true` for long-running dev servers.
123
+ - `run_command` supports `cwd_subdir` (relative path under the project) instead of `cd`/`bash`; use parallel `extra_env_keys` / `extra_env_values` (e.g. ["CI"] and ["1"]) for non-interactive installers; use `background=true` for long-running dev servers.
124
124
 
125
125
  Optional capability tools:
126
126
  - Deep research built-ins are {'ON' if deep_research_on else 'OFF'}.
@@ -7,7 +7,6 @@ import re
7
7
  import shutil
8
8
  import subprocess
9
9
  from pathlib import Path
10
- from typing import Any
11
10
 
12
11
  from google.adk.tools.tool_context import ToolContext
13
12
 
@@ -18,12 +17,12 @@ from gemcode.tools.shell_gate import consume_confirmed_shell_if_matches
18
17
  from gemcode.trust import is_trusted_root
19
18
 
20
19
 
21
- def _merge_child_env(extra: dict[str, Any] | None) -> dict[str, str]:
22
- """Merge a small set of env vars into os.environ for the child (e.g. CI=1)."""
20
+ def _merge_child_env(keys: list[str], values: list[str]) -> dict[str, str]:
21
+ """Merge parallel key/value lists into os.environ (Gemini API rejects dict-typed tool params)."""
23
22
  out = {**os.environ}
24
- if not extra:
23
+ if not keys and not values:
25
24
  return out
26
- for k, v in extra.items():
25
+ for k, v in zip(keys, values):
27
26
  if not isinstance(k, str) or not isinstance(v, str):
28
27
  continue
29
28
  if not re.match(r"^[A-Za-z_][A-Za-z0-9_]*$", k):
@@ -45,7 +44,8 @@ def make_run_command(cfg: GemCodeConfig):
45
44
  tool_context: ToolContext | None = None,
46
45
  cwd_subdir: str = ".",
47
46
  background: bool = False,
48
- extra_env: dict[str, str] | None = None,
47
+ extra_env_keys: list[str] | None = None,
48
+ extra_env_values: list[str] | None = None,
49
49
  ) -> dict:
50
50
  """
51
51
  Run an allowlisted executable with arguments.
@@ -57,8 +57,9 @@ def make_run_command(cfg: GemCodeConfig):
57
57
  For long-running servers (e.g. `npm run dev`), set `background=True` to start
58
58
  a detached process and return its PID (non-interactive; no TTY for the child).
59
59
 
60
- Optional `extra_env` merges env vars for the child (e.g. {"CI": "1"} for
61
- non-interactive scaffolding tools).
60
+ Optional `extra_env_keys` / `extra_env_values` are parallel lists (same length)
61
+ merged into the child environment (e.g. keys ["CI"], values ["1"] for
62
+ non-interactive scaffolding tools). Omit both to use the default environment.
62
63
  """
63
64
  if not trusted:
64
65
  return {"error": "Project folder is not trusted. Re-run GemCode and approve folder trust."}
@@ -111,7 +112,17 @@ def make_run_command(cfg: GemCodeConfig):
111
112
  )
112
113
  }
113
114
 
114
- child_env = _merge_child_env(extra_env)
115
+ ek = list(extra_env_keys or [])
116
+ ev = list(extra_env_values or [])
117
+ if len(ek) != len(ev):
118
+ return {
119
+ "error": (
120
+ "extra_env_keys and extra_env_values must be parallel lists of the same length "
121
+ "(one value per key)."
122
+ ),
123
+ }
124
+
125
+ child_env = _merge_child_env(ek, ev)
115
126
 
116
127
  if background:
117
128
  try:
@@ -303,7 +303,7 @@ async def run_gemcode_tui(
303
303
 
304
304
  tips = [
305
305
  "Tips for getting started",
306
- "Run /init to create a .gemcode config",
306
+ "First run: trust folder, API key, then .gemcode/",
307
307
  "Note: Use perm=ask to approve tools",
308
308
  ]
309
309
  activity = ["Recent activity", "No recent activity"]
@@ -104,7 +104,7 @@ def _dashboard(cfg) -> str:
104
104
  ]
105
105
  right = [
106
106
  "Tips for getting started",
107
- "Run /init to create a .gemcode file",
107
+ "First run creates .gemcode/ (trust + API key)",
108
108
  "",
109
109
  "Recent activity",
110
110
  "No recent activity",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gemcode
3
- Version: 0.3.0
3
+ Version: 0.3.2
4
4
  Summary: Local-first coding agent on Google Gemini + ADK
5
5
  Author: GemCode Contributors
6
6
  License: Apache License
@@ -74,6 +74,7 @@ src/gemcode/web/terminal_repl.py
74
74
  tests/test_autocompact.py
75
75
  tests/test_capability_routing.py
76
76
  tests/test_claude_web_adapter_sse.py
77
+ tests/test_cli_init.py
77
78
  tests/test_computer_use_permissions.py
78
79
  tests/test_context_budget.py
79
80
  tests/test_context_warning.py
@@ -0,0 +1,22 @@
1
+ """First-run project initialization (.gemcode/)."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pathlib import Path
6
+
7
+ from gemcode.cli import _initialize_gemcode_project
8
+ from gemcode.config import GemCodeConfig
9
+
10
+
11
+ def test_initialize_gemcode_project_creates_dot_gemcode(tmp_path: Path) -> None:
12
+ cfg = GemCodeConfig(project_root=tmp_path)
13
+ assert not (tmp_path / ".gemcode").exists()
14
+ _initialize_gemcode_project(cfg)
15
+ assert (tmp_path / ".gemcode").is_dir()
16
+
17
+
18
+ def test_initialize_gemcode_project_idempotent(tmp_path: Path) -> None:
19
+ cfg = GemCodeConfig(project_root=tmp_path)
20
+ _initialize_gemcode_project(cfg)
21
+ _initialize_gemcode_project(cfg)
22
+ assert (tmp_path / ".gemcode").is_dir()
@@ -118,6 +118,24 @@ def test_run_command_background_returns_pid(tmp_path: Path, monkeypatch) -> None
118
118
  assert isinstance(out.get("pid"), int)
119
119
 
120
120
 
121
+ def test_run_command_extra_env_merges(tmp_path: Path, monkeypatch) -> None:
122
+ monkeypatch.setenv("GEMCODE_HOME", str(tmp_path / ".gemstate"))
123
+ trust_root(tmp_path, trusted=True)
124
+ cfg = GemCodeConfig(project_root=tmp_path)
125
+ run_command = make_run_command(cfg)
126
+ ctx = MagicMock()
127
+ ctx.state = {HITL_STICKY_SESSION_KEY: True}
128
+ out = run_command(
129
+ "python3",
130
+ ["-c", "import os; print(os.environ.get('GEMCODE_TEST_EXTRA', ''))"],
131
+ extra_env_keys=["GEMCODE_TEST_EXTRA"],
132
+ extra_env_values=["ok"],
133
+ tool_context=ctx,
134
+ )
135
+ assert out.get("exit_code") == 0
136
+ assert "ok" in (out.get("stdout") or "")
137
+
138
+
121
139
  def test_delete_file(tmp_path: Path, monkeypatch) -> None:
122
140
  monkeypatch.setenv("GEMCODE_HOME", str(tmp_path / ".gemstate"))
123
141
  trust_root(tmp_path, trusted=True)
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