gemcode 0.3.71__py3-none-any.whl → 0.3.72__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 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/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}%")
@@ -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.71
3
+ Version: 0.3.72
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=yft-8lLJbX4abM_bUW156JWfVT3b4OHO-_hIoKdVaOs,52032
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=APBKPIpGvKd46Xt0ZGOZfVr8Tl6EAPbwqDsuM45jc1U,15609
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
@@ -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=4YZ4ZsPoWWQ6oV6WKxkXS7C6R55On0E4H1SH0oxqB88,48778
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=o65TYRkCiNKDk2o7CiTs7Trpm41RLI2g0HiK1QyvqQc,19216
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.71.dist-info/licenses/LICENSE,sha256=TD4524qn-W8Z07GTDnag-9jJPFutFZNB0a1WbMHPC54,8388
91
- gemcode-0.3.71.dist-info/METADATA,sha256=OkyL8aZtBhHoGZhMZslyEHdaEeMQf8uwUAU75YTXHYY,25852
92
- gemcode-0.3.71.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
93
- gemcode-0.3.71.dist-info/entry_points.txt,sha256=cZdLTLDiHbks7OSUCuxCh66dCWeQdpLR8BozoqfEjV4,45
94
- gemcode-0.3.71.dist-info/top_level.txt,sha256=UYrjULLBY2bcgK6KI6flomJWmsbDXu7n0rvW2SWFrbo,8
95
- gemcode-0.3.71.dist-info/RECORD,,
90
+ gemcode-0.3.72.dist-info/licenses/LICENSE,sha256=TD4524qn-W8Z07GTDnag-9jJPFutFZNB0a1WbMHPC54,8388
91
+ gemcode-0.3.72.dist-info/METADATA,sha256=Gc52r_EC_JeO0CEkJZN-zdfxrRkUWDHCToG4wHt5xmA,26402
92
+ gemcode-0.3.72.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
93
+ gemcode-0.3.72.dist-info/entry_points.txt,sha256=cZdLTLDiHbks7OSUCuxCh66dCWeQdpLR8BozoqfEjV4,45
94
+ gemcode-0.3.72.dist-info/top_level.txt,sha256=UYrjULLBY2bcgK6KI6flomJWmsbDXu7n0rvW2SWFrbo,8
95
+ gemcode-0.3.72.dist-info/RECORD,,