gemcode 0.3.0__tar.gz → 0.3.1__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.
- {gemcode-0.3.0/src/gemcode.egg-info → gemcode-0.3.1}/PKG-INFO +1 -1
- {gemcode-0.3.0 → gemcode-0.3.1}/pyproject.toml +1 -1
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/cli.py +31 -1
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/tui/app.py +1 -1
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/tui/scrollback.py +1 -1
- {gemcode-0.3.0 → gemcode-0.3.1/src/gemcode.egg-info}/PKG-INFO +1 -1
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode.egg-info/SOURCES.txt +1 -0
- gemcode-0.3.1/tests/test_cli_init.py +22 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/LICENSE +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/MANIFEST.in +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/README.md +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/setup.cfg +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/__init__.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/__main__.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/agent.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/audit.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/autocompact.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/callbacks.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/capability_routing.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/compaction.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/computer_use/__init__.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/computer_use/browser_computer.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/config.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/context_budget.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/context_warning.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/credentials.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/hitl_session.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/interactions.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/invoke.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/kairos_daemon.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/limits.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/live_audio_engine.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/mcp_loader.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/memory/__init__.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/memory/embedding_memory_service.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/memory/file_memory_service.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/modality_tools.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/model_errors.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/model_routing.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/paths.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/permissions.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/plugins/__init__.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/plugins/terminal_hooks_plugin.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/plugins/tool_recovery_plugin.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/prompt_suggestions.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/query/__init__.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/query/config.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/query/deps.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/query/engine.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/query/stop_hooks.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/query/token_budget.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/query/transitions.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/repl_commands.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/repl_slash.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/session_runtime.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/slash_commands.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/thinking.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/tool_prompt_manifest.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/tool_registry.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/tools/__init__.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/tools/edit.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/tools/filesystem.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/tools/search.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/tools/shell.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/tools/shell_gate.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/tools/todo.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/tools_inspector.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/trust.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/vertex.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/web/__init__.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/web/claude_sse_adapter.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode/web/terminal_repl.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode.egg-info/dependency_links.txt +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode.egg-info/entry_points.txt +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode.egg-info/requires.txt +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/src/gemcode.egg-info/top_level.txt +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/tests/test_autocompact.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/tests/test_capability_routing.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/tests/test_claude_web_adapter_sse.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/tests/test_computer_use_permissions.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/tests/test_context_budget.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/tests/test_context_warning.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/tests/test_credentials.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/tests/test_interactive_permission_ask.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/tests/test_kairos_scheduler.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/tests/test_modality_tools.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/tests/test_model_error_retry.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/tests/test_model_errors.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/tests/test_model_routing.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/tests/test_paths.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/tests/test_permissions.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/tests/test_prompt_suggestions.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/tests/test_repl_commands.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/tests/test_repl_slash.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/tests/test_slash_commands.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/tests/test_thinking_config.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/tests/test_token_budget.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/tests/test_tool_context_circulation.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/tests/test_tools.py +0 -0
- {gemcode-0.3.0 → gemcode-0.3.1}/tests/test_tools_inspector.py +0 -0
|
@@ -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
|
-
"\
|
|
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
|
|
@@ -303,7 +303,7 @@ async def run_gemcode_tui(
|
|
|
303
303
|
|
|
304
304
|
tips = [
|
|
305
305
|
"Tips for getting started",
|
|
306
|
-
"
|
|
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"]
|
|
@@ -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()
|
|
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
|
|
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
|