gemcode 0.3.71__py3-none-any.whl → 0.3.73__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 +39 -1
- gemcode/config.py +25 -0
- gemcode/invoke.py +2 -2
- gemcode/repl_slash.py +8 -0
- gemcode/session_runtime.py +28 -0
- {gemcode-0.3.71.dist-info → gemcode-0.3.73.dist-info}/METADATA +6 -1
- {gemcode-0.3.71.dist-info → gemcode-0.3.73.dist-info}/RECORD +11 -11
- {gemcode-0.3.71.dist-info → gemcode-0.3.73.dist-info}/WHEEL +0 -0
- {gemcode-0.3.71.dist-info → gemcode-0.3.73.dist-info}/entry_points.txt +0 -0
- {gemcode-0.3.71.dist-info → gemcode-0.3.73.dist-info}/licenses/LICENSE +0 -0
- {gemcode-0.3.71.dist-info → gemcode-0.3.73.dist-info}/top_level.txt +0 -0
gemcode/agent.py
CHANGED
|
@@ -887,7 +887,6 @@ def build_root_agent(
|
|
|
887
887
|
pre-built list that excludes run_subtask itself, preventing recursion).
|
|
888
888
|
When set, build_function_tools() is NOT called.
|
|
889
889
|
"""
|
|
890
|
-
return (base + tool_guide).strip() + "\n"
|
|
891
890
|
if _tools is not None:
|
|
892
891
|
tools = list(_tools)
|
|
893
892
|
else:
|
|
@@ -966,12 +965,51 @@ def build_root_agent(
|
|
|
966
965
|
tool_config=tool_cfg,
|
|
967
966
|
)
|
|
968
967
|
|
|
968
|
+
# ── ADK multi-agent tree (LLM-controlled transfer) ───────────────────────
|
|
969
|
+
sub_agents = []
|
|
970
|
+
if getattr(cfg, "enable_adk_agent_transfer", True) and _tools is None:
|
|
971
|
+
try:
|
|
972
|
+
# Explorer: read-only, fast, low-risk. Keep instruction short.
|
|
973
|
+
explorer_tools = build_function_tools(cfg, include_subtask=False)
|
|
974
|
+
explorer_tools = [t for t in explorer_tools if getattr(t, "__name__", "") not in ("write_file", "search_replace", "delete_file", "move_file", "bash", "run_command")]
|
|
975
|
+
explorer = LlmAgent(
|
|
976
|
+
name="explorer",
|
|
977
|
+
model=getattr(cfg, "model_alt", None) or cfg.model,
|
|
978
|
+
instruction=(
|
|
979
|
+
"You are Explorer. Your job is to quickly map the codebase and answer: "
|
|
980
|
+
"what files/symbols matter and where to look next. Use read-only tools only. "
|
|
981
|
+
"Return concise findings with file paths and symbol names."
|
|
982
|
+
),
|
|
983
|
+
tools=explorer_tools,
|
|
984
|
+
generate_content_config=gen_cfg,
|
|
985
|
+
**cb_kwargs,
|
|
986
|
+
)
|
|
987
|
+
# Verifier: focuses on checking, tests, and consistency.
|
|
988
|
+
verifier_tools = build_function_tools(cfg, include_subtask=False)
|
|
989
|
+
verifier_tools = [t for t in verifier_tools if getattr(t, "__name__", "") not in ("write_file", "search_replace", "delete_file", "move_file")]
|
|
990
|
+
verifier = LlmAgent(
|
|
991
|
+
name="verifier",
|
|
992
|
+
model=getattr(cfg, "model_alt", None) or cfg.model,
|
|
993
|
+
instruction=(
|
|
994
|
+
"You are Verifier. Your job is to verify changes: run checks/tests when needed, "
|
|
995
|
+
"spot inconsistencies, and report PASS/FAIL with concrete evidence. "
|
|
996
|
+
"Prefer minimal commands and short outputs."
|
|
997
|
+
),
|
|
998
|
+
tools=verifier_tools,
|
|
999
|
+
generate_content_config=gen_cfg,
|
|
1000
|
+
**cb_kwargs,
|
|
1001
|
+
)
|
|
1002
|
+
sub_agents = [explorer, verifier]
|
|
1003
|
+
except Exception:
|
|
1004
|
+
sub_agents = []
|
|
1005
|
+
|
|
969
1006
|
agent_kwargs: dict = dict(
|
|
970
1007
|
model=cfg.model,
|
|
971
1008
|
name="gemcode",
|
|
972
1009
|
instruction=build_instruction(cfg),
|
|
973
1010
|
tools=tools,
|
|
974
1011
|
generate_content_config=gen_cfg,
|
|
1012
|
+
sub_agents=sub_agents or None,
|
|
975
1013
|
**cb_kwargs,
|
|
976
1014
|
)
|
|
977
1015
|
|
gemcode/config.py
CHANGED
|
@@ -141,6 +141,31 @@ class GemCodeConfig:
|
|
|
141
141
|
default_factory=lambda: int(os.environ.get("GEMCODE_TOOL_RESULT_GROUP_BUDGET_CHARS", "60000"))
|
|
142
142
|
)
|
|
143
143
|
|
|
144
|
+
# ADK App-level event compaction (sliding-window summarization).
|
|
145
|
+
enable_adk_events_compaction: bool = field(
|
|
146
|
+
default_factory=lambda: _truthy_env("GEMCODE_ADK_EVENTS_COMPACTION", default=False)
|
|
147
|
+
)
|
|
148
|
+
adk_compaction_interval: int = field(
|
|
149
|
+
default_factory=lambda: int(os.environ.get("GEMCODE_ADK_COMPACTION_INTERVAL", "6"))
|
|
150
|
+
)
|
|
151
|
+
adk_compaction_overlap: int = field(
|
|
152
|
+
default_factory=lambda: int(os.environ.get("GEMCODE_ADK_COMPACTION_OVERLAP", "1"))
|
|
153
|
+
)
|
|
154
|
+
adk_compaction_token_threshold: int | None = field(
|
|
155
|
+
default_factory=lambda: _opt_positive_int("GEMCODE_ADK_COMPACTION_TOKEN_THRESHOLD")
|
|
156
|
+
)
|
|
157
|
+
adk_compaction_event_retention_size: int | None = field(
|
|
158
|
+
default_factory=lambda: _opt_positive_int("GEMCODE_ADK_COMPACTION_EVENT_RETENTION")
|
|
159
|
+
)
|
|
160
|
+
adk_compaction_summarizer_model: str = field(
|
|
161
|
+
default_factory=lambda: os.environ.get("GEMCODE_ADK_COMPACTION_MODEL", "gemini-2.5-flash")
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
# ADK multi-agent transfer (Explorer/Implementer/Verifier sub-agents).
|
|
165
|
+
enable_adk_agent_transfer: bool = field(
|
|
166
|
+
default_factory=lambda: _truthy_env("GEMCODE_ADK_AGENT_TRANSFER", default=True)
|
|
167
|
+
)
|
|
168
|
+
|
|
144
169
|
# When enabled, oversized tool outputs are offloaded to disk under
|
|
145
170
|
# .gemcode/tool-results/ and replaced in history with stable refs + previews.
|
|
146
171
|
# This reduces context bloat and improves prompt-cache stability.
|
gemcode/invoke.py
CHANGED
|
@@ -87,11 +87,11 @@ async def run_turn(
|
|
|
87
87
|
if re.search(r"\\b(test|pytest|ci|build|deploy|release)\\b", p, re.I):
|
|
88
88
|
risk += 0.1
|
|
89
89
|
# Multi-file hints
|
|
90
|
-
if p.count(
|
|
90
|
+
if p.count("/") >= 6 or p.count(".py") + p.count(".ts") + p.count(".tsx") >= 3:
|
|
91
91
|
risk += 0.1
|
|
92
92
|
# Clamp 0..1
|
|
93
93
|
risk = max(0.0, min(1.0, float(risk)))
|
|
94
|
-
object.__setattr__(cfg,
|
|
94
|
+
object.__setattr__(cfg, "_risk_score", risk)
|
|
95
95
|
except Exception:
|
|
96
96
|
pass
|
|
97
97
|
run_config = (
|
gemcode/repl_slash.py
CHANGED
|
@@ -400,6 +400,14 @@ async def process_repl_slash(
|
|
|
400
400
|
out(f" dynamic_token_policy: {getattr(cfg, 'dynamic_token_policy', True)}")
|
|
401
401
|
out(f" dynamic_risk_policy: {getattr(cfg, 'dynamic_risk_policy', True)}")
|
|
402
402
|
out(f" dynamic_risk_boost: {getattr(cfg, 'dynamic_risk_boost', 0.6)}")
|
|
403
|
+
out()
|
|
404
|
+
out(" ADK advanced:")
|
|
405
|
+
out(f" adk_agent_transfer: {getattr(cfg, 'enable_adk_agent_transfer', True)}")
|
|
406
|
+
out(f" adk_events_compaction: {getattr(cfg, 'enable_adk_events_compaction', False)}")
|
|
407
|
+
if getattr(cfg, "enable_adk_events_compaction", False):
|
|
408
|
+
out(f" compaction_interval: {getattr(cfg, 'adk_compaction_interval', 6)}")
|
|
409
|
+
out(f" compaction_overlap: {getattr(cfg, 'adk_compaction_overlap', 1)}")
|
|
410
|
+
out(f" compaction_model: {getattr(cfg, 'adk_compaction_summarizer_model', 'gemini-2.5-flash')}")
|
|
403
411
|
out(f" risk_score: {risk:.2f}")
|
|
404
412
|
if isinstance(pct, int):
|
|
405
413
|
out(f" context_percent_left: {pct}%")
|
gemcode/session_runtime.py
CHANGED
|
@@ -66,11 +66,39 @@ def _build_app(agent, plugins, cfg: GemCodeConfig):
|
|
|
66
66
|
"""
|
|
67
67
|
try:
|
|
68
68
|
from google.adk.apps.app import App
|
|
69
|
+
events_compaction_config = None
|
|
70
|
+
if getattr(cfg, "enable_adk_events_compaction", False):
|
|
71
|
+
try:
|
|
72
|
+
from google.adk.apps.app import EventsCompactionConfig
|
|
73
|
+
summarizer = None
|
|
74
|
+
try:
|
|
75
|
+
from google.adk.apps.llm_event_summarizer import LlmEventSummarizer
|
|
76
|
+
from google.adk.models import Gemini
|
|
77
|
+
summarizer_llm = Gemini(model=getattr(cfg, "adk_compaction_summarizer_model", "gemini-2.5-flash"))
|
|
78
|
+
summarizer = LlmEventSummarizer(llm=summarizer_llm)
|
|
79
|
+
except Exception:
|
|
80
|
+
summarizer = None
|
|
81
|
+
|
|
82
|
+
kw = dict(
|
|
83
|
+
compaction_interval=max(2, int(getattr(cfg, "adk_compaction_interval", 6) or 6)),
|
|
84
|
+
overlap_size=max(0, int(getattr(cfg, "adk_compaction_overlap", 1) or 1)),
|
|
85
|
+
)
|
|
86
|
+
tt = getattr(cfg, "adk_compaction_token_threshold", None)
|
|
87
|
+
rs = getattr(cfg, "adk_compaction_event_retention_size", None)
|
|
88
|
+
if tt is not None and rs is not None:
|
|
89
|
+
kw["token_threshold"] = int(tt)
|
|
90
|
+
kw["event_retention_size"] = int(rs)
|
|
91
|
+
if summarizer is not None:
|
|
92
|
+
kw["summarizer"] = summarizer
|
|
93
|
+
events_compaction_config = EventsCompactionConfig(**kw)
|
|
94
|
+
except Exception:
|
|
95
|
+
events_compaction_config = None
|
|
69
96
|
return App(
|
|
70
97
|
name="gemcode",
|
|
71
98
|
root_agent=agent,
|
|
72
99
|
plugins=plugins,
|
|
73
100
|
context_cache_config=_build_context_cache_config(),
|
|
101
|
+
events_compaction_config=events_compaction_config,
|
|
74
102
|
)
|
|
75
103
|
except Exception:
|
|
76
104
|
# Fall back silently — Runner still accepts the legacy kwargs.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gemcode
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.73
|
|
4
4
|
Summary: Local-first coding agent on Google Gemini + ADK
|
|
5
5
|
Author: GemCode Contributors
|
|
6
6
|
License: Apache License
|
|
@@ -246,6 +246,11 @@ GemCode keeps project-local state under `.gemcode/`:
|
|
|
246
246
|
- `gemcode tools smoke` fails non-zero if any tool’s declaration compilation fails
|
|
247
247
|
- Optional inspection flags: `--deep-research`, `--maps-grounding`, `--embeddings`, `--memory`
|
|
248
248
|
- **Optional compaction**: set `GEMCODE_ENABLE_COMPACT=1` to trim old `Content` entries before each model call (MVP sliding window; can break complex tool chains if too aggressive—tune `GEMCODE_MAX_CONTENT_ITEMS`).
|
|
249
|
+
- **ADK multi-agent transfer (recommended)**: enabled by default; GemCode builds an ADK sub-agent tree (Explorer/Verifier) and allows the model to transfer with `transfer_to_agent` when specialization helps.
|
|
250
|
+
- Disable: `GEMCODE_ADK_AGENT_TRANSFER=0`
|
|
251
|
+
- **ADK event compaction (new)**: optional ADK-native summarization of older events to keep long sessions coherent without exploding context.
|
|
252
|
+
- Enable: `GEMCODE_ADK_EVENTS_COMPACTION=1`
|
|
253
|
+
- Tune: `GEMCODE_ADK_COMPACTION_INTERVAL`, `GEMCODE_ADK_COMPACTION_OVERLAP`, `GEMCODE_ADK_COMPACTION_MODEL`
|
|
249
254
|
- **Session token ceiling**: set `GEMCODE_MAX_SESSION_TOKENS` to stop the next LLM call when cumulative `usage_metadata.total_token_count` exceeds the limit.
|
|
250
255
|
- **Token budget tracking**: set `GEMCODE_TOKEN_BUDGET` to enforce continuation/stop decisions per user turn (token-budget audit in `.gemcode/audit.log`).
|
|
251
256
|
- **Stop-the-loop hooks**: set `GEMCODE_POST_TURN_HOOK=/path/to/hook.sh` (or place an executable at `.gemcode/hooks/post_turn`) to run after each user message.
|
|
@@ -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=EogvAa9qBHY_rYmC52wks8G4dTYrJK0li5_zHFF9yN8,53894
|
|
4
4
|
gemcode/audit.py,sha256=bh9uhXaeh8wqxqoZtz3ZAowd8Ndk1ss-mw9993Vlrgo,469
|
|
5
5
|
gemcode/autocompact.py,sha256=77h5tgFzJ2rjrhlCL2oIc28IHwLbP4Pqlo7cSNgDwiA,6727
|
|
6
6
|
gemcode/callbacks.py,sha256=EYkJTRcHjCeqTgVZGat2Y3BYWg4tNtHl-cgl5cdUxpo,31076
|
|
7
7
|
gemcode/capability_routing.py,sha256=yvQXwKtrfHXbgbNunU0Dxh9GCDN4cbySXIeccrdzr2o,3471
|
|
8
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=20OnbYjcvwTZ9qwKF5Ih-NfHxrpzctQ-bSXQtAZjYWI,16726
|
|
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
|
|
@@ -16,7 +16,7 @@ gemcode/hitl_session.py,sha256=oNiI7odFJGUcmqPavjKLJOEumZKrgklLvwjjrIG9GPg,281
|
|
|
16
16
|
gemcode/hooks.py,sha256=FHz175d_18j-4ByZZVdEIagmdOvLHcjDjo7HD2Cikf4,6339
|
|
17
17
|
gemcode/intent_classifier.py,sha256=YfRVEe8gHeKlRkjuSWef1bZ0MPBwyYMp5jymP5Vig5U,8507
|
|
18
18
|
gemcode/interactions.py,sha256=B0b3QNE_I2i5_HtiebX4ehhjlc4Nbqjf_XbvcTLyJT0,641
|
|
19
|
-
gemcode/invoke.py,sha256=
|
|
19
|
+
gemcode/invoke.py,sha256=rHxV0_uFTjwvu6oOIpzNK98su1l3V1kQkqCtefxqhyA,10275
|
|
20
20
|
gemcode/kairos_daemon.py,sha256=giINipslAIhBtdbqA0o4RYwt4fBsZjtkiKDjp4zSEvw,6980
|
|
21
21
|
gemcode/limits.py,sha256=1u7w3X13Uqw34ZOVYKa62pxfvlyLTY2Dne1kN8SKJlA,2524
|
|
22
22
|
gemcode/live_audio_engine.py,sha256=wxdGp5ciAgQ7WIeBpcW_hm8lbMDsh0KPJbqIS9uAGxA,3406
|
|
@@ -33,9 +33,9 @@ gemcode/pricing.py,sha256=lftp0SwyDqOzHqC2-6XzgZZhjif5PLdCe1Q3wY-p6kQ,3558
|
|
|
33
33
|
gemcode/prompt_suggestions.py,sha256=h-W_9LlfagS91PyoMEjEjsCqoG4XmIh3QBypA59HyGw,2553
|
|
34
34
|
gemcode/refine.py,sha256=BijEZ4Z32wGa9aK_WottyAhZF-j0xEqRg5UpjedNv2A,7653
|
|
35
35
|
gemcode/repl_commands.py,sha256=AHjDUhlq7IuSL6Fla17y0aeGZyp6snxwbMG7gz1PrRc,11330
|
|
36
|
-
gemcode/repl_slash.py,sha256=
|
|
36
|
+
gemcode/repl_slash.py,sha256=L5KFu4uriijEtxYgFJIpgiOrqk_F7aGnc7pJheYUDlM,49355
|
|
37
37
|
gemcode/review_agent.py,sha256=4t7_5-aE60b4-EheJ_eSB_H2eQYf9GppKoui6jw0TME,5264
|
|
38
|
-
gemcode/session_runtime.py,sha256=
|
|
38
|
+
gemcode/session_runtime.py,sha256=mHZooqGPjaLwUcLzkTaHQ_i13OiRqHlPPQ9PYFmtDfM,20513
|
|
39
39
|
gemcode/session_store.py,sha256=POUT_QQf715c74jbXj0s5vCd4dlAgJz_CLsIWuEUoO0,6051
|
|
40
40
|
gemcode/slash_commands.py,sha256=Qylzsj1notk0xN_hvd3CR4HD8g-l99UENDMcg1pKeBA,794
|
|
41
41
|
gemcode/thinking.py,sha256=RanBf_x9fKv1o4DNyNXPLfOdn2xT0KybJb65nYgmMEE,4885
|
|
@@ -87,9 +87,9 @@ gemcode/tui/welcome_rich.py,sha256=8FEZzLXrzqly5JWiDgV9ooRV1LNXDk-CXV1a7K6ua-U,4
|
|
|
87
87
|
gemcode/web/__init__.py,sha256=EysmUAWs6g-lmMk4VFljKfaHVrEgb_FiIzwQmBdORJc,40
|
|
88
88
|
gemcode/web/claude_sse_adapter.py,sha256=HcNp0Lh4DdBZBLOpstsqa-VzfqAUrRngZ6FSuJ-mIMg,8609
|
|
89
89
|
gemcode/web/terminal_repl.py,sha256=k2irvFGbCY8gDm_pbirR7b_cakaeafcctoTIvnJkVXk,3902
|
|
90
|
-
gemcode-0.3.
|
|
91
|
-
gemcode-0.3.
|
|
92
|
-
gemcode-0.3.
|
|
93
|
-
gemcode-0.3.
|
|
94
|
-
gemcode-0.3.
|
|
95
|
-
gemcode-0.3.
|
|
90
|
+
gemcode-0.3.73.dist-info/licenses/LICENSE,sha256=TD4524qn-W8Z07GTDnag-9jJPFutFZNB0a1WbMHPC54,8388
|
|
91
|
+
gemcode-0.3.73.dist-info/METADATA,sha256=plCNdUK4RChi2iiO_R1FV2JdKxlrFHaN9c_f9oU9HPg,26402
|
|
92
|
+
gemcode-0.3.73.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
93
|
+
gemcode-0.3.73.dist-info/entry_points.txt,sha256=cZdLTLDiHbks7OSUCuxCh66dCWeQdpLR8BozoqfEjV4,45
|
|
94
|
+
gemcode-0.3.73.dist-info/top_level.txt,sha256=UYrjULLBY2bcgK6KI6flomJWmsbDXu7n0rvW2SWFrbo,8
|
|
95
|
+
gemcode-0.3.73.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|