gemcode 0.3.46__py3-none-any.whl → 0.3.48__py3-none-any.whl
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/agent.py +19 -25
- gemcode/cli.py +0 -11
- gemcode/config.py +1 -1
- gemcode/pricing.py +4 -1
- gemcode/tools/__init__.py +1 -3
- gemcode/tui/scrollback.py +0 -55
- {gemcode-0.3.46.dist-info → gemcode-0.3.48.dist-info}/METADATA +1 -1
- {gemcode-0.3.46.dist-info → gemcode-0.3.48.dist-info}/RECORD +12 -12
- {gemcode-0.3.46.dist-info → gemcode-0.3.48.dist-info}/WHEEL +0 -0
- {gemcode-0.3.46.dist-info → gemcode-0.3.48.dist-info}/entry_points.txt +0 -0
- {gemcode-0.3.46.dist-info → gemcode-0.3.48.dist-info}/licenses/LICENSE +0 -0
- {gemcode-0.3.46.dist-info → gemcode-0.3.48.dist-info}/top_level.txt +0 -0
gemcode/agent.py
CHANGED
|
@@ -398,27 +398,19 @@ You run locally via the GemCode CLI. You are the same agent the user launched
|
|
|
398
398
|
|
|
399
399
|
## Core identity and approach
|
|
400
400
|
|
|
401
|
-
|
|
401
|
+
Use your built-in thinking to read the user's intent before acting. Match the response style to what was actually asked:
|
|
402
402
|
|
|
403
|
-
|
|
404
|
-
and stored it in session state as `_gemcode_intent`. Read it and adapt your behaviour:
|
|
405
|
-
|
|
406
|
-
| `_gemcode_intent` | Meaning | What to do |
|
|
403
|
+
| Message type | Examples | Right action |
|
|
407
404
|
|---|---|---|
|
|
408
|
-
|
|
|
409
|
-
|
|
|
410
|
-
|
|
|
411
|
-
|
|
|
412
|
-
|
|
|
413
|
-
|
|
414
|
-
If `_gemcode_intent` is not set (first turn or classifier unavailable), infer the intent yourself
|
|
415
|
-
from the message before acting — the categories above still apply.
|
|
405
|
+
| **Greeting / chitchat** | "hi", "thanks", "cool" | Reply warmly in one sentence. No tools. |
|
|
406
|
+
| **General knowledge** | "what is a closure?", "explain OAuth" | Answer from knowledge. No tools unless this specific repo is needed. |
|
|
407
|
+
| **Project question** | "how does auth work here?", "what's in this folder?" | 1–2 read-only tools, then a focused answer. |
|
|
408
|
+
| **Engineering task** | "fix the bug", "add pagination", "refactor X" | Orient → Plan → Execute → Verify. |
|
|
409
|
+
| **Analysis / audit** | "analyse the whole backend", "summarise all endpoints" | Thorough tool sweep, then synthesise. |
|
|
416
410
|
|
|
417
|
-
**
|
|
418
|
-
response to a greeting or a simple general question that requires no project context.**
|
|
411
|
+
**Never call `list_directory`, `read_project_notes`, or any tool in response to a greeting or a general knowledge question that needs no project context.**
|
|
419
412
|
|
|
420
413
|
### Engineering task workflow
|
|
421
|
-
When the intent is `ENGINEERING_TASK`:
|
|
422
414
|
1. **Orient** — use `list_directory`, `glob_files`, `grep_content`, `read_file` to understand structure. These tools need **no permission** and are instant.
|
|
423
415
|
2. **Plan** — for complex tasks, call `todo_write` upfront to map out the work.
|
|
424
416
|
3. **Execute** — make the changes, run the checks, iterate.
|
|
@@ -447,7 +439,7 @@ You have native deep thinking capability — use it actively:
|
|
|
447
439
|
- **For trade-off decisions** (which library, which pattern, which approach): reason through the pros/cons given this specific codebase.
|
|
448
440
|
|
|
449
441
|
## Interpreting requests
|
|
450
|
-
- **
|
|
442
|
+
- **Think first.** Read the message intent before touching any tool. The intent table above is your guide.
|
|
451
443
|
- **Engineering tasks** ("fix", "add", "refactor", "analyse", "debug"): infer from the repo — search, read, then act. Do not give abstract advice when concrete files exist.
|
|
452
444
|
- If the user refers to symbols or behaviors, **find them** with `glob_files`/`grep_content`/`list_directory` — never ask them to paste paths you can discover yourself.
|
|
453
445
|
- **Never propose edits to files you haven't read.** Read first, then edit.
|
|
@@ -470,12 +462,12 @@ You have native deep thinking capability — use it actively:
|
|
|
470
462
|
- For **dev servers**: `bash("npm run dev", background=True, cwd_subdir="frontend")`
|
|
471
463
|
- For **subfolders**: `bash("cargo build --release", cwd_subdir="backend")`
|
|
472
464
|
|
|
473
|
-
-
|
|
474
|
-
- `
|
|
475
|
-
- `
|
|
476
|
-
- `
|
|
477
|
-
- `
|
|
478
|
-
-
|
|
465
|
+
- **Long-running servers / watchers** — use `bash` with `background=True`:
|
|
466
|
+
- `bash("npm run dev", background=True)` — start the dev server in background
|
|
467
|
+
- `bash("python manage.py runserver", background=True)` — Django server
|
|
468
|
+
- `bash("tail -f logs/app.log", background=True)` — background log watcher
|
|
469
|
+
- NEVER call `bash("npm run dev")` without `background=True` — it blocks forever and crashes the turn
|
|
470
|
+
- After starting a background process, confirm the port is ready with `bash("sleep 2 && curl -s http://localhost:3000 -o /dev/null && echo ready")`
|
|
479
471
|
|
|
480
472
|
- **`run_command`** — simple single-executable calls without shell features:
|
|
481
473
|
- `run_command("npm", args=["install", "--legacy-peer-deps"])` — clean npm install
|
|
@@ -769,8 +761,10 @@ def build_root_agent(
|
|
|
769
761
|
# prepended to every agent's effective instruction.
|
|
770
762
|
global_instr = (
|
|
771
763
|
"You are GemCode, an expert software engineering agent powered by Google Gemini. "
|
|
772
|
-
"
|
|
773
|
-
"
|
|
764
|
+
"Think through the user's intent before acting. "
|
|
765
|
+
"For greetings or general questions, reply directly without calling tools. "
|
|
766
|
+
"For engineering tasks, act fully and autonomously — orient, plan, execute, verify. "
|
|
767
|
+
"Use read-only tools before shell/write tools."
|
|
774
768
|
)
|
|
775
769
|
|
|
776
770
|
agent_kwargs: dict = dict(
|
gemcode/cli.py
CHANGED
|
@@ -154,17 +154,6 @@ async def _run_prompt(
|
|
|
154
154
|
# MCP and OpenAPI toolsets are now loaded inside create_runner() directly.
|
|
155
155
|
runner = create_runner(cfg, extra_tools=None)
|
|
156
156
|
try:
|
|
157
|
-
# LLM intent pre-classifier: greetings bypass the main agent entirely.
|
|
158
|
-
try:
|
|
159
|
-
from gemcode.intent_classifier import (
|
|
160
|
-
classify_intent, generate_greeting_reply, INTENT_GREETING
|
|
161
|
-
)
|
|
162
|
-
_intent = await classify_intent(prompt)
|
|
163
|
-
if _intent == INTENT_GREETING:
|
|
164
|
-
return await generate_greeting_reply(prompt)
|
|
165
|
-
except Exception:
|
|
166
|
-
pass
|
|
167
|
-
|
|
168
157
|
collected = await run_turn(
|
|
169
158
|
runner,
|
|
170
159
|
user_id="local",
|
gemcode/config.py
CHANGED
|
@@ -68,7 +68,7 @@ class GemCodeConfig:
|
|
|
68
68
|
"""Runtime options (CLI + env)."""
|
|
69
69
|
|
|
70
70
|
project_root: Path
|
|
71
|
-
model: str = field(default_factory=lambda: os.environ.get("GEMCODE_MODEL", "gemini-
|
|
71
|
+
model: str = field(default_factory=lambda: os.environ.get("GEMCODE_MODEL", "gemini-3.1-pro-preview"))
|
|
72
72
|
# Model mode: fast|balanced|quality|auto
|
|
73
73
|
model_mode: str = field(
|
|
74
74
|
default_factory=lambda: os.environ.get("GEMCODE_MODEL_MODE", "fast")
|
gemcode/pricing.py
CHANGED
|
@@ -14,6 +14,10 @@ from __future__ import annotations
|
|
|
14
14
|
# Format: model_prefix → (input_$/M, output_$/M)
|
|
15
15
|
# Matches are done by checking if the model id STARTS WITH any key (longest first).
|
|
16
16
|
_PRICING_TABLE: dict[str, tuple[float, float]] = {
|
|
17
|
+
# ── Gemini 3 ────────────────────────────────────────────────────────────
|
|
18
|
+
"gemini-3.1-pro": (0.30, 1.20), # preview pricing (approximate)
|
|
19
|
+
"gemini-3.0-pro": (0.30, 1.20),
|
|
20
|
+
"gemini-3": (0.30, 1.20),
|
|
17
21
|
# ── Gemini 2.5 ──────────────────────────────────────────────────────────
|
|
18
22
|
"gemini-2.5-pro": (3.50, 10.50), # standard context ≤200k
|
|
19
23
|
"gemini-2.5-flash-lite": (0.10, 0.40), # lowest-cost 2.5 (must precede flash)
|
|
@@ -28,7 +32,6 @@ _PRICING_TABLE: dict[str, tuple[float, float]] = {
|
|
|
28
32
|
"gemini-1.5-pro": (1.25, 5.00),
|
|
29
33
|
# ── Gemini experimental / preview ───────────────────────────────────────
|
|
30
34
|
"gemini-exp": (0.00, 0.00), # free during preview
|
|
31
|
-
"gemini-3": (0.30, 1.20), # approximate future pricing
|
|
32
35
|
}
|
|
33
36
|
|
|
34
37
|
|
gemcode/tools/__init__.py
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
from gemcode.config import GemCodeConfig
|
|
6
|
-
from gemcode.tools.bash import make_bash_tool
|
|
6
|
+
from gemcode.tools.bash import make_bash_tool
|
|
7
7
|
from gemcode.tools.edit import make_edit_tools
|
|
8
8
|
from gemcode.tools.filesystem import make_filesystem_tools
|
|
9
9
|
from gemcode.tools.search import make_grep_tool
|
|
@@ -35,7 +35,6 @@ def build_function_tools(cfg: GemCodeConfig, *, include_subtask: bool = True) ->
|
|
|
35
35
|
grep_content = make_grep_tool(cfg)
|
|
36
36
|
run_command = make_run_command(cfg)
|
|
37
37
|
bash = make_bash_tool(cfg)
|
|
38
|
-
bash_stream = make_bash_stream_tool(cfg)
|
|
39
38
|
write_file, search_replace = make_edit_tools(cfg)
|
|
40
39
|
todo_write = make_todo_tool(cfg)
|
|
41
40
|
think = make_think_tool()
|
|
@@ -55,7 +54,6 @@ def build_function_tools(cfg: GemCodeConfig, *, include_subtask: bool = True) ->
|
|
|
55
54
|
glob_files,
|
|
56
55
|
grep_content,
|
|
57
56
|
bash_tool,
|
|
58
|
-
bash_stream,
|
|
59
57
|
run_command_tool,
|
|
60
58
|
write_file,
|
|
61
59
|
search_replace,
|
gemcode/tui/scrollback.py
CHANGED
|
@@ -582,61 +582,6 @@ async def run_gemcode_scrollback_tui(
|
|
|
582
582
|
except Exception:
|
|
583
583
|
pass
|
|
584
584
|
|
|
585
|
-
# ── LLM intent pre-classifier ────────────────────────────────────────────
|
|
586
|
-
# gemini-2.5-flash-lite classifies the message (same lane as Thinking)
|
|
587
|
-
try:
|
|
588
|
-
from gemcode.intent_classifier import (
|
|
589
|
-
classify_intent_with_source,
|
|
590
|
-
generate_greeting_reply,
|
|
591
|
-
show_intentifying_line,
|
|
592
|
-
INTENT_GREETING,
|
|
593
|
-
INTENT_DESCRIPTIONS,
|
|
594
|
-
)
|
|
595
|
-
# Show as a transient spinner status (do not print a permanent line).
|
|
596
|
-
_start_anim("Intentifying\u2026")
|
|
597
|
-
try:
|
|
598
|
-
_intent, _intent_src = await classify_intent_with_source(prompt)
|
|
599
|
-
finally:
|
|
600
|
-
_stop_anim()
|
|
601
|
-
# If disabled, show nothing; otherwise the spinner already conveyed it.
|
|
602
|
-
_ = show_intentifying_line(_intent_src)
|
|
603
|
-
|
|
604
|
-
if _intent == INTENT_GREETING:
|
|
605
|
-
_start_anim("Replying\u2026")
|
|
606
|
-
try:
|
|
607
|
-
_reply = await generate_greeting_reply(prompt)
|
|
608
|
-
finally:
|
|
609
|
-
_stop_anim()
|
|
610
|
-
print(f" \u23bf {ansi.bold}GemCode{ansi.reset}:")
|
|
611
|
-
console.print(_RichPadding(_RichMarkdown(_reply), (0, 0, 0, 4)))
|
|
612
|
-
print("")
|
|
613
|
-
if os.environ.get("GEMCODE_TUI_TURN_RULE", "1").lower() in (
|
|
614
|
-
"1", "true", "yes", "on"
|
|
615
|
-
):
|
|
616
|
-
print(f"{ansi.dim}{_hr(ch='─')}{ansi.reset}")
|
|
617
|
-
print("")
|
|
618
|
-
continue
|
|
619
|
-
|
|
620
|
-
# Non-greeting: store classified intent in session state so the main
|
|
621
|
-
# agent can read it and adapt its tool-use strategy accordingly.
|
|
622
|
-
try:
|
|
623
|
-
ss = runner.session_service
|
|
624
|
-
app = getattr(runner, "app_name", None) or getattr(cfg, "app_name", "gemcode")
|
|
625
|
-
sess = await ss.get_session(
|
|
626
|
-
app_name=app, user_id="local", session_id=current_session_id
|
|
627
|
-
)
|
|
628
|
-
if sess is not None:
|
|
629
|
-
_desc = INTENT_DESCRIPTIONS.get(_intent, _intent)
|
|
630
|
-
sess.state["_gemcode_intent"] = _intent
|
|
631
|
-
sess.state["_gemcode_intent_desc"] = _desc
|
|
632
|
-
await ss.update_session(sess)
|
|
633
|
-
except Exception:
|
|
634
|
-
pass # State injection is best-effort
|
|
635
|
-
|
|
636
|
-
except Exception:
|
|
637
|
-
pass # Classifier unavailable — fall through to main agent unchanged
|
|
638
|
-
# ─────────────────────────────────────────────────────────────────────────
|
|
639
|
-
|
|
640
585
|
# Snapshot pre-turn capability state so we can detect routing-triggered changes.
|
|
641
586
|
_pre_dr = cfg.enable_deep_research
|
|
642
587
|
_pre_emb = cfg.enable_embeddings
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
gemcode/__init__.py,sha256=l0DCRYqK7KM7Fb7u49fqh-5_SlpeIL7r3LjMeJWMgSg,112
|
|
2
2
|
gemcode/__main__.py,sha256=EX2s1hxq2Yvli_-tnBN3w5Qv4bOjsBBbjyISF0pDIQw,37
|
|
3
|
-
gemcode/agent.py,sha256=
|
|
3
|
+
gemcode/agent.py,sha256=2PVjjSiI4siJFrqkP6Ca6v7ecHrJywZOHs3PG_wSwgk,41884
|
|
4
4
|
gemcode/audit.py,sha256=bh9uhXaeh8wqxqoZtz3ZAowd8Ndk1ss-mw9993Vlrgo,469
|
|
5
5
|
gemcode/autocompact.py,sha256=77h5tgFzJ2rjrhlCL2oIc28IHwLbP4Pqlo7cSNgDwiA,6727
|
|
6
6
|
gemcode/callbacks.py,sha256=qgbxyBMOlgzVkJr9lI55En4EpJOwjo83U3dvNrl5I4s,24229
|
|
7
7
|
gemcode/capability_routing.py,sha256=D8tvawmf_MSL94GVXgG9QhDvNaQVGqzA8tUFQ8XlftY,2894
|
|
8
|
-
gemcode/cli.py,sha256=
|
|
8
|
+
gemcode/cli.py,sha256=kBXb4b4JCG3u0XewCJn8lCyOT62Y8bOvlVoDc2R-GKQ,25320
|
|
9
9
|
gemcode/compaction.py,sha256=9YtA_qa23_8dHWVHx7AJwUduuI7jJQtq-m6sT8jgPWI,1186
|
|
10
|
-
gemcode/config.py,sha256=
|
|
10
|
+
gemcode/config.py,sha256=Ngwbp96FzplhA_F5XPW_VvCmAekConR2OG6GBGDjJew,14087
|
|
11
11
|
gemcode/context_budget.py,sha256=Nhox9vFBtLbb7jtO7cyGW1MxtN7SVjlIeQ7d-cgGyKM,10544
|
|
12
12
|
gemcode/context_warning.py,sha256=Q8mg5Vojj7EglPhsGAVL7vb8ROLuHVPgdzw25yw-Q2c,4263
|
|
13
13
|
gemcode/credentials.py,sha256=04v-rLD8_Ams69FQdof2FwcL3ZgsroGUnMcHNQFuBZo,1296
|
|
@@ -27,7 +27,7 @@ gemcode/model_routing.py,sha256=Q42HZtXQa6rao2O2vYMHxohrTgD-wq4t7qGxU4_38Jg,4881
|
|
|
27
27
|
gemcode/openapi_loader.py,sha256=g_NZD8YL9_9iIJJ9qykhdbBrylJ1195A4FyHGC0mroc,4157
|
|
28
28
|
gemcode/paths.py,sha256=U6cEH9jfIcSc4NO8Ke0jniZSiJTfCIJPvSMue3hR0ZU,768
|
|
29
29
|
gemcode/permissions.py,sha256=0gQ63Ll-KPlZVU6KigIpwSwKL5-OWqYMB6a0x2wpc28,6766
|
|
30
|
-
gemcode/pricing.py,sha256=
|
|
30
|
+
gemcode/pricing.py,sha256=lftp0SwyDqOzHqC2-6XzgZZhjif5PLdCe1Q3wY-p6kQ,3558
|
|
31
31
|
gemcode/prompt_suggestions.py,sha256=h-W_9LlfagS91PyoMEjEjsCqoG4XmIh3QBypA59HyGw,2553
|
|
32
32
|
gemcode/refine.py,sha256=BijEZ4Z32wGa9aK_WottyAhZF-j0xEqRg5UpjedNv2A,7653
|
|
33
33
|
gemcode/repl_commands.py,sha256=qPUVSjNLR0QnABmURoYP58quu2pAcz3F0wUvDd_1v3o,11340
|
|
@@ -59,7 +59,7 @@ gemcode/query/engine.py,sha256=GPuvUgTRpWmyA39I_3ayVEADlHVFhPrC2FGW_yKs2yw,1420
|
|
|
59
59
|
gemcode/query/stop_hooks.py,sha256=jaXMN2OptwHeGXF8o630zIVr62T8jVg-eIyREG0GyxA,1847
|
|
60
60
|
gemcode/query/token_budget.py,sha256=JTq2TrGkFY5t5KOs-P9XQPqahyjcdTzN3wctZ1JxFV0,2973
|
|
61
61
|
gemcode/query/transitions.py,sha256=vJ77cv4cFwdvsxyGr7MxXz6uGVB5IDqOClqR1MkWvqw,933
|
|
62
|
-
gemcode/tools/__init__.py,sha256=
|
|
62
|
+
gemcode/tools/__init__.py,sha256=jea95Ds3BwUaiDNVGesBXDKvveIHbdTNpk4yKVWcPVA,2226
|
|
63
63
|
gemcode/tools/bash.py,sha256=1Nv1UmnWhc1Y-9gZyYUQEcAE43K8V2bakj27ULcvjR8,9075
|
|
64
64
|
gemcode/tools/browser.py,sha256=StWRttiyGkR4qaG5urRviJgdoj2hiFB2OuHPItaVzJY,7250
|
|
65
65
|
gemcode/tools/edit.py,sha256=Q6ALUCHQV37n0j6XQd2luCaDm0fIavho3faDisOqtuU,1716
|
|
@@ -73,16 +73,16 @@ gemcode/tools/think.py,sha256=WrNATR-bi97aLkbSsOFOYYAGxbzihe9AnPDZfw3z5-Q,1704
|
|
|
73
73
|
gemcode/tools/todo.py,sha256=d9aXiyT04r1RFZIk6qdVif17-_Oc3oi4ymDnsPBRg68,3143
|
|
74
74
|
gemcode/tools/web.py,sha256=ULg1e3inG4FjPSUCYI8dVBzTrcCHINNRo76SIU9qw-A,4489
|
|
75
75
|
gemcode/tui/input_handler.py,sha256=VWF92Fe3WkD3QP9kBDY5zrx333Vj2eShO3UO0x2n6eo,10079
|
|
76
|
-
gemcode/tui/scrollback.py,sha256=
|
|
76
|
+
gemcode/tui/scrollback.py,sha256=RxwS0DsjkkX_jHvnlF2XMi9z69yGfCiwPuFIHCnb8VU,32535
|
|
77
77
|
gemcode/tui/spinner.py,sha256=AJrApG5od-Sh40-5uWcNM9RHb5ax7gr-NbgAZmTbIYY,4848
|
|
78
78
|
gemcode/tui/welcome_banner.py,sha256=aocl1lnoyLIM6RN4f65g3i0wRA71RqUlgPrGsXeVLW4,4387
|
|
79
79
|
gemcode/tui/welcome_rich.py,sha256=8FEZzLXrzqly5JWiDgV9ooRV1LNXDk-CXV1a7K6ua-U,4048
|
|
80
80
|
gemcode/web/__init__.py,sha256=EysmUAWs6g-lmMk4VFljKfaHVrEgb_FiIzwQmBdORJc,40
|
|
81
81
|
gemcode/web/claude_sse_adapter.py,sha256=HcNp0Lh4DdBZBLOpstsqa-VzfqAUrRngZ6FSuJ-mIMg,8609
|
|
82
82
|
gemcode/web/terminal_repl.py,sha256=k2irvFGbCY8gDm_pbirR7b_cakaeafcctoTIvnJkVXk,3902
|
|
83
|
-
gemcode-0.3.
|
|
84
|
-
gemcode-0.3.
|
|
85
|
-
gemcode-0.3.
|
|
86
|
-
gemcode-0.3.
|
|
87
|
-
gemcode-0.3.
|
|
88
|
-
gemcode-0.3.
|
|
83
|
+
gemcode-0.3.48.dist-info/licenses/LICENSE,sha256=TD4524qn-W8Z07GTDnag-9jJPFutFZNB0a1WbMHPC54,8388
|
|
84
|
+
gemcode-0.3.48.dist-info/METADATA,sha256=gqGKCCsfE6Ppuf1x0ZlJR-qzsi38hWkPJmMB_H2NA8E,23695
|
|
85
|
+
gemcode-0.3.48.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
86
|
+
gemcode-0.3.48.dist-info/entry_points.txt,sha256=cZdLTLDiHbks7OSUCuxCh66dCWeQdpLR8BozoqfEjV4,45
|
|
87
|
+
gemcode-0.3.48.dist-info/top_level.txt,sha256=UYrjULLBY2bcgK6KI6flomJWmsbDXu7n0rvW2SWFrbo,8
|
|
88
|
+
gemcode-0.3.48.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|