gemcode 0.3.22__py3-none-any.whl → 0.3.23__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/config.py +7 -0
- gemcode/repl_commands.py +30 -6
- gemcode/repl_slash.py +266 -25
- gemcode/tui/input_handler.py +9 -3
- gemcode/tui/scrollback.py +28 -1
- {gemcode-0.3.22.dist-info → gemcode-0.3.23.dist-info}/METADATA +1 -1
- {gemcode-0.3.22.dist-info → gemcode-0.3.23.dist-info}/RECORD +11 -11
- {gemcode-0.3.22.dist-info → gemcode-0.3.23.dist-info}/WHEEL +0 -0
- {gemcode-0.3.22.dist-info → gemcode-0.3.23.dist-info}/entry_points.txt +0 -0
- {gemcode-0.3.22.dist-info → gemcode-0.3.23.dist-info}/licenses/LICENSE +0 -0
- {gemcode-0.3.22.dist-info → gemcode-0.3.23.dist-info}/top_level.txt +0 -0
gemcode/config.py
CHANGED
|
@@ -244,6 +244,13 @@ class GemCodeConfig:
|
|
|
244
244
|
default_factory=lambda: _opt_int("GEMCODE_THINKING_BUDGET")
|
|
245
245
|
)
|
|
246
246
|
|
|
247
|
+
# Controls how the TUI renders model thinking: True = full Rich Markdown,
|
|
248
|
+
# False = collapsed one-line excerpt (default, like OpenClaude).
|
|
249
|
+
# Toggled at runtime via /thinking verbose|brief.
|
|
250
|
+
show_full_thinking: bool = field(
|
|
251
|
+
default_factory=lambda: _truthy_env("GEMCODE_SHOW_FULL_THINKING", default=False)
|
|
252
|
+
)
|
|
253
|
+
|
|
247
254
|
def __post_init__(self) -> None:
|
|
248
255
|
self.project_root = self.project_root.resolve()
|
|
249
256
|
# Default agentic depth when env omits GEMCODE_MAX_LLM_CALLS (was: None → SDK default).
|
gemcode/repl_commands.py
CHANGED
|
@@ -162,9 +162,11 @@ def slash_help_lines() -> list[str]:
|
|
|
162
162
|
"Slash commands:",
|
|
163
163
|
" (CLI) gemcode -C DIR Use a project folder as root (recommended vs. ~ )",
|
|
164
164
|
" (CLI) gemcode login Save or change API key (~/.gemcode/credentials.json)",
|
|
165
|
+
"",
|
|
166
|
+
" Session:",
|
|
165
167
|
" /help Show this help",
|
|
166
|
-
" /status
|
|
167
|
-
" /config
|
|
168
|
+
" /status Full status: model, capabilities, thinking, limits",
|
|
169
|
+
" /config All active config fields (model, caps, context, thinking)",
|
|
168
170
|
" /session Print current session id",
|
|
169
171
|
" /session new Start a new session id (history reset)",
|
|
170
172
|
" /clear Alias for /session new",
|
|
@@ -173,9 +175,26 @@ def slash_help_lines() -> list[str]:
|
|
|
173
175
|
" /audit [N] Tail of .gemcode/audit.log (default 40 lines)",
|
|
174
176
|
" /tools List tool inventory for this config",
|
|
175
177
|
" /doctor Environment sanity check",
|
|
178
|
+
" /version Print GemCode version hint",
|
|
179
|
+
" /exit Exit the REPL",
|
|
180
|
+
"",
|
|
181
|
+
" Model:",
|
|
176
182
|
" /model Show model routing info",
|
|
177
183
|
" /model use <id> Override model for this REPL session",
|
|
178
|
-
" /model list
|
|
184
|
+
" /model list List available Gemini model IDs",
|
|
185
|
+
" /mode Show current model_mode",
|
|
186
|
+
" /mode <fast|balanced|quality|auto> Set model selection strategy",
|
|
187
|
+
"",
|
|
188
|
+
" Capabilities (all require runner rebuild — shown automatically):",
|
|
189
|
+
" /research Show deep-research status",
|
|
190
|
+
" /research on|off Enable/disable Google Search + URL Context tools",
|
|
191
|
+
" /embeddings on|off Enable/disable semantic file search (Embeddings API)",
|
|
192
|
+
" /caps View all capability flags",
|
|
193
|
+
" /caps <research|embeddings|all|reset> Bulk capability control",
|
|
194
|
+
" /memory Show persistent memory status",
|
|
195
|
+
" /memory on|off Enable/disable session memory",
|
|
196
|
+
"",
|
|
197
|
+
" Thinking:",
|
|
179
198
|
" /thinking Show current thinking config",
|
|
180
199
|
" /thinking verbose Show full thinking text each turn",
|
|
181
200
|
" /thinking brief Show collapsed one-line excerpt (default)",
|
|
@@ -183,9 +202,14 @@ def slash_help_lines() -> list[str]:
|
|
|
183
202
|
" /thinking on Re-enable thinking (auto budget/level)",
|
|
184
203
|
" /thinking budget <N> Set thinking token budget (Gemini 2.5, 0=off, -1=dynamic)",
|
|
185
204
|
" /thinking level <L> Set thinking level: minimal|low|medium|high (Gemini 3.x)",
|
|
205
|
+
"",
|
|
206
|
+
" Limits:",
|
|
207
|
+
" /limits Show all execution limits",
|
|
208
|
+
" /limits calls <N> Set max LLM calls per turn",
|
|
209
|
+
" /budget Show per-turn token budget",
|
|
210
|
+
" /budget <N>|off Set or clear per-turn token budget",
|
|
211
|
+
"",
|
|
212
|
+
" Other:",
|
|
186
213
|
" /permissions Show permission / HITL settings",
|
|
187
|
-
" /memory Show persistent memory settings",
|
|
188
214
|
" /hooks Show post-turn hook configuration",
|
|
189
|
-
" /version Print GemCode version hint",
|
|
190
|
-
" /exit Exit the REPL",
|
|
191
215
|
]
|
gemcode/repl_slash.py
CHANGED
|
@@ -181,29 +181,73 @@ async def process_repl_slash(
|
|
|
181
181
|
return ReplSlashResult(skip_model_turn=True)
|
|
182
182
|
|
|
183
183
|
if name == "status":
|
|
184
|
-
out(f"model:
|
|
185
|
-
out(f"
|
|
186
|
-
out(f"session_id:
|
|
187
|
-
out(f"
|
|
188
|
-
out(
|
|
184
|
+
out(f"model: {cfg.model}")
|
|
185
|
+
out(f"model_mode: {cfg.model_mode}")
|
|
186
|
+
out(f"session_id: {session_id}")
|
|
187
|
+
out(f"project_root: {cfg.project_root}")
|
|
188
|
+
out()
|
|
189
|
+
out("Capabilities:")
|
|
190
|
+
out(f" deep_research: {'on ✓' if cfg.enable_deep_research else 'off'}")
|
|
191
|
+
out(f" embeddings: {'on ✓' if cfg.enable_embeddings else 'off'}")
|
|
192
|
+
out(f" memory: {'on ✓' if cfg.enable_memory else 'off'}")
|
|
193
|
+
out(f" computer_use: {'on ✓' if cfg.enable_computer_use else 'off'}")
|
|
194
|
+
out(f" maps_grounding: {'on ✓' if cfg.enable_maps_grounding else 'off'}")
|
|
195
|
+
out(f" auto_routing: {cfg.capability_mode}")
|
|
196
|
+
out()
|
|
197
|
+
out("Thinking:")
|
|
198
|
+
out(f" disabled: {cfg.disable_thinking}")
|
|
199
|
+
if cfg.thinking_level:
|
|
200
|
+
out(f" level: {cfg.thinking_level}")
|
|
201
|
+
if cfg.thinking_budget is not None:
|
|
202
|
+
out(f" budget: {cfg.thinking_budget:,} tokens")
|
|
203
|
+
out(f" display: {'verbose (full)' if cfg.show_full_thinking else 'brief (collapsed)'}")
|
|
204
|
+
out()
|
|
205
|
+
out("Permissions / limits:")
|
|
206
|
+
out(f" permission_mode: {cfg.permission_mode}")
|
|
207
|
+
out(f" yes_to_all: {cfg.yes_to_all}")
|
|
208
|
+
out(f" max_llm_calls: {cfg.max_llm_calls or '(SDK default)'}")
|
|
209
|
+
out(f" token_budget: {f'{cfg.token_budget:,}' if cfg.token_budget else '(none)'}")
|
|
189
210
|
out()
|
|
190
211
|
return ReplSlashResult(skip_model_turn=True)
|
|
191
212
|
|
|
192
213
|
if name == "config":
|
|
193
|
-
out("
|
|
194
|
-
out(
|
|
195
|
-
out(
|
|
196
|
-
|
|
197
|
-
)
|
|
198
|
-
out(f"
|
|
199
|
-
out(f"
|
|
200
|
-
out(f"
|
|
201
|
-
out(
|
|
202
|
-
|
|
203
|
-
)
|
|
204
|
-
out(
|
|
205
|
-
|
|
206
|
-
)
|
|
214
|
+
out("Active configuration:")
|
|
215
|
+
out()
|
|
216
|
+
out(" Model:")
|
|
217
|
+
out(f" model: {cfg.model}")
|
|
218
|
+
out(f" model_mode: {cfg.model_mode} (fast|balanced|quality|auto — /mode)")
|
|
219
|
+
out(f" model_family_mode: {cfg.model_family_mode}")
|
|
220
|
+
out(f" model_overridden: {cfg.model_overridden}")
|
|
221
|
+
out(f" model_deep_research: {cfg.model_deep_research}")
|
|
222
|
+
out()
|
|
223
|
+
out(" Capabilities (/research, /embeddings, /caps, /memory):")
|
|
224
|
+
out(f" enable_deep_research: {cfg.enable_deep_research}")
|
|
225
|
+
out(f" enable_embeddings: {cfg.enable_embeddings}")
|
|
226
|
+
out(f" enable_memory: {cfg.enable_memory}")
|
|
227
|
+
out(f" enable_computer_use: {cfg.enable_computer_use}")
|
|
228
|
+
out(f" enable_maps_grounding: {cfg.enable_maps_grounding}")
|
|
229
|
+
out(f" capability_mode: {cfg.capability_mode} (auto-routing)")
|
|
230
|
+
out(f" tool_combination_mode: {cfg.tool_combination_mode}")
|
|
231
|
+
out()
|
|
232
|
+
out(" Context / limits (/limits, /budget):")
|
|
233
|
+
out(f" max_llm_calls: {cfg.max_llm_calls or '(SDK default)'}")
|
|
234
|
+
out(f" max_context_chars: {cfg.max_context_chars:,}")
|
|
235
|
+
out(f" tool_result_max_chars: {cfg.tool_result_max_chars:,}")
|
|
236
|
+
out(f" max_content_items: {cfg.max_content_items}")
|
|
237
|
+
out(f" context_shrink: {cfg.context_shrink_enabled}")
|
|
238
|
+
out(f" token_budget: {f'{cfg.token_budget:,}' if cfg.token_budget else '(none)'}")
|
|
239
|
+
out(f" max_session_tokens: {f'{cfg.max_session_tokens:,}' if cfg.max_session_tokens else '(none)'}")
|
|
240
|
+
out()
|
|
241
|
+
out(" Thinking (/thinking):")
|
|
242
|
+
out(f" disable_thinking: {cfg.disable_thinking}")
|
|
243
|
+
out(f" thinking_level: {cfg.thinking_level or '(auto)'}")
|
|
244
|
+
out(f" thinking_budget: {cfg.thinking_budget if cfg.thinking_budget is not None else '(auto)'}")
|
|
245
|
+
out(f" show_full_thinking: {cfg.show_full_thinking}")
|
|
246
|
+
out()
|
|
247
|
+
out(" Autocompact:")
|
|
248
|
+
out(f" GEMCODE_AUTOCOMPACT: {os.environ.get('GEMCODE_AUTOCOMPACT', '1')}")
|
|
249
|
+
out(f" GEMCODE_AUTOCOMPACT_BUFFER_CHARS: {os.environ.get('GEMCODE_AUTOCOMPACT_BUFFER_CHARS', '60000')}")
|
|
250
|
+
out(f" GEMCODE_AUTOCOMPACT_KEEP_CONTENT_ITEMS: {os.environ.get('GEMCODE_AUTOCOMPACT_KEEP_CONTENT_ITEMS', '18')}")
|
|
207
251
|
out()
|
|
208
252
|
return ReplSlashResult(skip_model_turn=True)
|
|
209
253
|
|
|
@@ -271,6 +315,203 @@ async def process_repl_slash(
|
|
|
271
315
|
if name in ("exit", "quit"):
|
|
272
316
|
return ReplSlashResult(exit_repl=True)
|
|
273
317
|
|
|
318
|
+
# ── /research ────────────────────────────────────────────────────────────
|
|
319
|
+
if name == "research":
|
|
320
|
+
args_s = (sc.args or "").strip().lower()
|
|
321
|
+
if not args_s or args_s in ("status", "show"):
|
|
322
|
+
status = "on ✓" if cfg.enable_deep_research else "off"
|
|
323
|
+
out(f"deep_research: {status}")
|
|
324
|
+
if cfg.enable_deep_research:
|
|
325
|
+
out(f" model_deep_research: {cfg.model_deep_research}")
|
|
326
|
+
out(f" enable_maps_grounding:{cfg.enable_maps_grounding}")
|
|
327
|
+
out(" tools: google_search, url_context")
|
|
328
|
+
out()
|
|
329
|
+
out("Commands: /research on · /research off")
|
|
330
|
+
out("When on: Google Search + URL Context are injected as tools.")
|
|
331
|
+
out(" Model switches to the deep-research routing model.")
|
|
332
|
+
out()
|
|
333
|
+
return ReplSlashResult(skip_model_turn=True)
|
|
334
|
+
if args_s == "on":
|
|
335
|
+
cfg.enable_deep_research = True
|
|
336
|
+
out("research: on — Google Search + URL Context enabled")
|
|
337
|
+
out(" Runner will rebuild on next turn to inject the new tools.")
|
|
338
|
+
out()
|
|
339
|
+
return ReplSlashResult(skip_model_turn=True, force_rebuild_runner=True)
|
|
340
|
+
if args_s == "off":
|
|
341
|
+
cfg.enable_deep_research = False
|
|
342
|
+
out("research: off")
|
|
343
|
+
out()
|
|
344
|
+
return ReplSlashResult(skip_model_turn=True, force_rebuild_runner=True)
|
|
345
|
+
out(f"Unknown /research subcommand: '{args_s}'")
|
|
346
|
+
out("Usage: /research [on|off]")
|
|
347
|
+
out()
|
|
348
|
+
return ReplSlashResult(skip_model_turn=True)
|
|
349
|
+
|
|
350
|
+
# ── /embeddings ──────────────────────────────────────────────────────────
|
|
351
|
+
if name in ("embeddings", "embed"):
|
|
352
|
+
args_s = (sc.args or "").strip().lower()
|
|
353
|
+
if not args_s or args_s in ("status", "show"):
|
|
354
|
+
status = "on ✓" if cfg.enable_embeddings else "off"
|
|
355
|
+
out(f"embeddings: {status}")
|
|
356
|
+
if cfg.enable_embeddings:
|
|
357
|
+
out(f" embeddings_model: {cfg.embeddings_model}")
|
|
358
|
+
out(" tools: semantic_search_files")
|
|
359
|
+
out()
|
|
360
|
+
out("Commands: /embeddings on · /embeddings off")
|
|
361
|
+
out("When on: semantic (meaning-based) file search via Google Embeddings API.")
|
|
362
|
+
out()
|
|
363
|
+
return ReplSlashResult(skip_model_turn=True)
|
|
364
|
+
if args_s == "on":
|
|
365
|
+
cfg.enable_embeddings = True
|
|
366
|
+
out("embeddings: on — semantic_search_files tool injected")
|
|
367
|
+
out(" Runner will rebuild on next turn.")
|
|
368
|
+
out()
|
|
369
|
+
return ReplSlashResult(skip_model_turn=True, force_rebuild_runner=True)
|
|
370
|
+
if args_s == "off":
|
|
371
|
+
cfg.enable_embeddings = False
|
|
372
|
+
out("embeddings: off")
|
|
373
|
+
out()
|
|
374
|
+
return ReplSlashResult(skip_model_turn=True, force_rebuild_runner=True)
|
|
375
|
+
out(f"Unknown /embeddings subcommand: '{args_s}'")
|
|
376
|
+
out("Usage: /embeddings [on|off]")
|
|
377
|
+
out()
|
|
378
|
+
return ReplSlashResult(skip_model_turn=True)
|
|
379
|
+
|
|
380
|
+
# ── /mode ─────────────────────────────────────────────────────────────────
|
|
381
|
+
if name == "mode":
|
|
382
|
+
args_s = (sc.args or "").strip().lower()
|
|
383
|
+
valid_modes = ("fast", "balanced", "quality", "auto")
|
|
384
|
+
if not args_s:
|
|
385
|
+
out(f"model_mode: {cfg.model_mode}")
|
|
386
|
+
out()
|
|
387
|
+
out(" fast — use the fastest model for edits and tool-heavy tasks")
|
|
388
|
+
out(" balanced — moderate speed/quality (default)")
|
|
389
|
+
out(" quality — highest-quality model for architecture and complex reasoning")
|
|
390
|
+
out(" auto — GemCode picks based on prompt complexity each turn")
|
|
391
|
+
out()
|
|
392
|
+
out("Usage: /mode <fast|balanced|quality|auto>")
|
|
393
|
+
out()
|
|
394
|
+
return ReplSlashResult(skip_model_turn=True)
|
|
395
|
+
if args_s in valid_modes:
|
|
396
|
+
cfg.model_mode = args_s
|
|
397
|
+
# Clear model_overridden so the new mode takes effect through routing
|
|
398
|
+
if not getattr(cfg, "_model_explicitly_set", False):
|
|
399
|
+
cfg.model_overridden = False
|
|
400
|
+
out(f"model_mode: {args_s}")
|
|
401
|
+
out()
|
|
402
|
+
return ReplSlashResult(skip_model_turn=True)
|
|
403
|
+
out(f"Unknown mode '{args_s}'. Choose from: {', '.join(valid_modes)}")
|
|
404
|
+
out()
|
|
405
|
+
return ReplSlashResult(skip_model_turn=True)
|
|
406
|
+
|
|
407
|
+
# ── /budget ───────────────────────────────────────────────────────────────
|
|
408
|
+
if name in ("budget", "token-budget"):
|
|
409
|
+
args_s = (sc.args or "").strip().lower()
|
|
410
|
+
if not args_s:
|
|
411
|
+
tb = cfg.token_budget
|
|
412
|
+
out(f"token_budget: {f'{tb:,} tokens/turn' if tb is not None else '(none — unlimited)'}")
|
|
413
|
+
out()
|
|
414
|
+
out("Usage: /budget <N> Set per-turn token budget (e.g. /budget 50000)")
|
|
415
|
+
out(" /budget off Remove budget limit")
|
|
416
|
+
out()
|
|
417
|
+
return ReplSlashResult(skip_model_turn=True)
|
|
418
|
+
if args_s == "off":
|
|
419
|
+
cfg.token_budget = None
|
|
420
|
+
out("token_budget: (none — unlimited)")
|
|
421
|
+
out()
|
|
422
|
+
return ReplSlashResult(skip_model_turn=True)
|
|
423
|
+
try:
|
|
424
|
+
n = int(args_s)
|
|
425
|
+
if n <= 0:
|
|
426
|
+
out("Token budget must be a positive integer (or 'off').")
|
|
427
|
+
out()
|
|
428
|
+
return ReplSlashResult(skip_model_turn=True)
|
|
429
|
+
cfg.token_budget = n
|
|
430
|
+
out(f"token_budget: {n:,} tokens per turn")
|
|
431
|
+
out()
|
|
432
|
+
return ReplSlashResult(skip_model_turn=True)
|
|
433
|
+
except ValueError:
|
|
434
|
+
out(f"Invalid budget '{args_s}' — use a number or 'off'.")
|
|
435
|
+
out()
|
|
436
|
+
return ReplSlashResult(skip_model_turn=True)
|
|
437
|
+
|
|
438
|
+
# ── /caps ─────────────────────────────────────────────────────────────────
|
|
439
|
+
if name in ("caps", "capabilities", "capability"):
|
|
440
|
+
args_s = (sc.args or "").strip().lower()
|
|
441
|
+
valid_caps = ("auto", "research", "embeddings", "computer", "all", "none", "reset")
|
|
442
|
+
out("Active capabilities:")
|
|
443
|
+
out(f" deep_research: {'on' if cfg.enable_deep_research else 'off'}")
|
|
444
|
+
out(f" embeddings: {'on' if cfg.enable_embeddings else 'off'}")
|
|
445
|
+
out(f" memory: {'on' if cfg.enable_memory else 'off'}")
|
|
446
|
+
out(f" computer_use: {'on' if cfg.enable_computer_use else 'off'}")
|
|
447
|
+
out(f" maps_grounding: {'on' if cfg.enable_maps_grounding else 'off'}")
|
|
448
|
+
out(f" capability_mode (auto-routing): {cfg.capability_mode}")
|
|
449
|
+
out()
|
|
450
|
+
if not args_s:
|
|
451
|
+
out("Commands:")
|
|
452
|
+
out(" /caps none — turn all off, capability_mode=auto")
|
|
453
|
+
out(" /caps research — enable_deep_research on")
|
|
454
|
+
out(" /caps embeddings — enable_embeddings on")
|
|
455
|
+
out(" /caps all — all modalities on")
|
|
456
|
+
out(" /caps reset — reset to startup defaults (all off, auto mode)")
|
|
457
|
+
out()
|
|
458
|
+
return ReplSlashResult(skip_model_turn=True)
|
|
459
|
+
if args_s in ("none", "reset"):
|
|
460
|
+
cfg.enable_deep_research = False
|
|
461
|
+
cfg.enable_embeddings = False
|
|
462
|
+
cfg.enable_computer_use = False
|
|
463
|
+
cfg.enable_maps_grounding = False
|
|
464
|
+
cfg.capability_mode = "auto"
|
|
465
|
+
out("capabilities: reset to defaults (all off, auto mode)")
|
|
466
|
+
out()
|
|
467
|
+
return ReplSlashResult(skip_model_turn=True, force_rebuild_runner=True)
|
|
468
|
+
if args_s == "research":
|
|
469
|
+
cfg.enable_deep_research = True
|
|
470
|
+
out("enable_deep_research: on (runner rebuilding…)")
|
|
471
|
+
out()
|
|
472
|
+
return ReplSlashResult(skip_model_turn=True, force_rebuild_runner=True)
|
|
473
|
+
if args_s == "embeddings":
|
|
474
|
+
cfg.enable_embeddings = True
|
|
475
|
+
out("enable_embeddings: on (runner rebuilding…)")
|
|
476
|
+
out()
|
|
477
|
+
return ReplSlashResult(skip_model_turn=True, force_rebuild_runner=True)
|
|
478
|
+
if args_s == "all":
|
|
479
|
+
cfg.enable_deep_research = True
|
|
480
|
+
cfg.enable_embeddings = True
|
|
481
|
+
cfg.enable_computer_use = True
|
|
482
|
+
out("capabilities: all on (runner rebuilding…)")
|
|
483
|
+
out()
|
|
484
|
+
return ReplSlashResult(skip_model_turn=True, force_rebuild_runner=True)
|
|
485
|
+
out(f"Unknown /caps value '{args_s}'. Choose from: {', '.join(valid_caps)}")
|
|
486
|
+
out()
|
|
487
|
+
return ReplSlashResult(skip_model_turn=True)
|
|
488
|
+
|
|
489
|
+
# ── /limits ───────────────────────────────────────────────────────────────
|
|
490
|
+
if name == "limits":
|
|
491
|
+
args_s = (sc.args or "").strip()
|
|
492
|
+
out("Current limits:")
|
|
493
|
+
out(f" max_llm_calls: {cfg.max_llm_calls or '(SDK default)'}")
|
|
494
|
+
out(f" max_context_chars: {cfg.max_context_chars:,}")
|
|
495
|
+
out(f" tool_result_max_chars: {cfg.tool_result_max_chars:,}")
|
|
496
|
+
out(f" max_content_items: {cfg.max_content_items}")
|
|
497
|
+
out(f" context_shrink: {cfg.context_shrink_enabled}")
|
|
498
|
+
out(f" token_budget: {f'{cfg.token_budget:,}' if cfg.token_budget else '(none)'}")
|
|
499
|
+
out(f" max_session_tokens: {f'{cfg.max_session_tokens:,}' if cfg.max_session_tokens else '(none)'}")
|
|
500
|
+
out()
|
|
501
|
+
if args_s:
|
|
502
|
+
parts = args_s.split()
|
|
503
|
+
if parts[0] == "calls" and len(parts) >= 2:
|
|
504
|
+
try:
|
|
505
|
+
n = int(parts[1])
|
|
506
|
+
if n > 0:
|
|
507
|
+
cfg.max_llm_calls = n
|
|
508
|
+
out(f"max_llm_calls: {n}")
|
|
509
|
+
out()
|
|
510
|
+
except ValueError:
|
|
511
|
+
out(f"Invalid value '{parts[1]}'")
|
|
512
|
+
out()
|
|
513
|
+
return ReplSlashResult(skip_model_turn=True)
|
|
514
|
+
|
|
274
515
|
if name == "thinking":
|
|
275
516
|
model_id = getattr(cfg, "model", "") or ""
|
|
276
517
|
is_25 = "2.5" in model_id
|
|
@@ -278,10 +519,10 @@ async def process_repl_slash(
|
|
|
278
519
|
|
|
279
520
|
if not args:
|
|
280
521
|
# Show current thinking config.
|
|
281
|
-
disable = bool(
|
|
282
|
-
level =
|
|
283
|
-
budget =
|
|
284
|
-
verbose = bool(
|
|
522
|
+
disable = bool(cfg.disable_thinking)
|
|
523
|
+
level = cfg.thinking_level
|
|
524
|
+
budget = cfg.thinking_budget
|
|
525
|
+
verbose = bool(cfg.show_full_thinking)
|
|
285
526
|
out("Thinking config:")
|
|
286
527
|
out(f" model: {model_id or '(default)'}")
|
|
287
528
|
out(f" disable_thinking: {disable}")
|
|
@@ -310,13 +551,13 @@ async def process_repl_slash(
|
|
|
310
551
|
sub = parts[0].lower()
|
|
311
552
|
|
|
312
553
|
if sub in ("verbose", "full"):
|
|
313
|
-
|
|
554
|
+
cfg.show_full_thinking = True
|
|
314
555
|
out("thinking display: verbose — full thinking shown each turn")
|
|
315
556
|
out()
|
|
316
557
|
return ReplSlashResult(skip_model_turn=True)
|
|
317
558
|
|
|
318
559
|
if sub in ("brief", "short", "collapsed"):
|
|
319
|
-
|
|
560
|
+
cfg.show_full_thinking = False
|
|
320
561
|
out("thinking display: brief — collapsed one-line excerpt (default)")
|
|
321
562
|
out()
|
|
322
563
|
return ReplSlashResult(skip_model_turn=True)
|
gemcode/tui/input_handler.py
CHANGED
|
@@ -43,16 +43,22 @@ SLASH_COMMANDS: list[tuple[str, str]] = [
|
|
|
43
43
|
("help", "List all available commands"),
|
|
44
44
|
("clear", "Start a fresh session (clears history) · alias: /session new"),
|
|
45
45
|
("model", "View or switch model · /model use <id> · /model list"),
|
|
46
|
+
("mode", "Set model mode · /mode fast|balanced|quality|auto"),
|
|
46
47
|
("thinking", "Thinking config · /thinking verbose · /thinking brief · /thinking budget <N>"),
|
|
47
|
-
("status", "Show session
|
|
48
|
+
("status", "Show full session status: model, capabilities, thinking, limits"),
|
|
48
49
|
("context", "Show context window usage and token counts"),
|
|
49
50
|
("compact", "Summarise conversation history to reclaim context space"),
|
|
51
|
+
("research", "Toggle Google Search + URL Context · /research on|off"),
|
|
52
|
+
("embeddings", "Toggle semantic file search via Embeddings API · /embeddings on|off"),
|
|
53
|
+
("caps", "View/toggle all capabilities · /caps · /caps all · /caps reset"),
|
|
54
|
+
("memory", "Toggle persistent memory · /memory on|off"),
|
|
55
|
+
("budget", "Set per-turn token budget · /budget <N> · /budget off"),
|
|
56
|
+
("limits", "Show/set execution limits (max_llm_calls, context, etc.)"),
|
|
50
57
|
("tools", "List all tools and their permission categories"),
|
|
51
|
-
("config", "Show active configuration
|
|
58
|
+
("config", "Show full active configuration (all fields)"),
|
|
52
59
|
("permissions", "Show current permission mode (default / strict / yes)"),
|
|
53
60
|
("session", "Show current session ID · /session new to reset"),
|
|
54
61
|
("audit", "Show recent audit log · /audit [N lines]"),
|
|
55
|
-
("memory", "Show memory / storage settings"),
|
|
56
62
|
("doctor", "Run diagnostics and validate the environment"),
|
|
57
63
|
("hooks", "Show post-turn hook configuration"),
|
|
58
64
|
("version", "Show installed GemCode version"),
|
gemcode/tui/scrollback.py
CHANGED
|
@@ -436,9 +436,36 @@ async def run_gemcode_scrollback_tui(
|
|
|
436
436
|
continue
|
|
437
437
|
prompt = slash.model_prompt or prompt
|
|
438
438
|
|
|
439
|
+
# Snapshot pre-turn capability state so we can detect routing-triggered changes.
|
|
440
|
+
_pre_dr = cfg.enable_deep_research
|
|
441
|
+
_pre_emb = cfg.enable_embeddings
|
|
442
|
+
_pre_cu = cfg.enable_computer_use
|
|
443
|
+
_pre_model = cfg.model
|
|
444
|
+
|
|
439
445
|
apply_capability_routing(cfg, prompt, context="prompt")
|
|
440
446
|
cfg.model = pick_effective_model(cfg, prompt)
|
|
441
447
|
|
|
448
|
+
# Capabilities and model are baked into the Runner at construction time.
|
|
449
|
+
# If routing changed any of them we must rebuild the runner so the new
|
|
450
|
+
# tools/model are actually used for this turn.
|
|
451
|
+
_routing_changed = (
|
|
452
|
+
cfg.enable_deep_research != _pre_dr
|
|
453
|
+
or cfg.enable_embeddings != _pre_emb
|
|
454
|
+
or cfg.enable_computer_use != _pre_cu
|
|
455
|
+
or cfg.model != _pre_model
|
|
456
|
+
)
|
|
457
|
+
if _routing_changed:
|
|
458
|
+
try:
|
|
459
|
+
close_fn = getattr(runner, "close", None)
|
|
460
|
+
if close_fn:
|
|
461
|
+
maybe = close_fn()
|
|
462
|
+
if asyncio.iscoroutine(maybe):
|
|
463
|
+
await maybe
|
|
464
|
+
except Exception:
|
|
465
|
+
pass
|
|
466
|
+
from gemcode.session_runtime import create_runner as _create_runner_rt
|
|
467
|
+
runner = _create_runner_rt(cfg, extra_tools=extra_tools)
|
|
468
|
+
|
|
442
469
|
current_message = types.Content(role="user", parts=[types.Part(text=prompt)])
|
|
443
470
|
do_reset = True
|
|
444
471
|
def _normalize_ws(s: str) -> str:
|
|
@@ -501,7 +528,7 @@ async def run_gemcode_scrollback_tui(
|
|
|
501
528
|
if thought_text and not (
|
|
502
529
|
buffered_final and _normalize_ws(thought_text) == _normalize_ws(final_text)
|
|
503
530
|
):
|
|
504
|
-
show_full = bool(
|
|
531
|
+
show_full = bool(cfg.show_full_thinking)
|
|
505
532
|
if show_full:
|
|
506
533
|
# Verbose mode: full thinking rendered as Markdown, like transcript mode.
|
|
507
534
|
print(f" \u23bf {ansi.dim}\u2234 Thinking{ansi.reset}")
|
|
@@ -7,7 +7,7 @@ gemcode/callbacks.py,sha256=dxZhHsJDE-16nJ0OGe4udPkWRTOCVfSi2gBSR7MUWOM,20465
|
|
|
7
7
|
gemcode/capability_routing.py,sha256=D8tvawmf_MSL94GVXgG9QhDvNaQVGqzA8tUFQ8XlftY,2894
|
|
8
8
|
gemcode/cli.py,sha256=0b9hO86EILJ5xRg8fb1Sfmwh6vYi9Bp6tkOvsxOSIEU,25447
|
|
9
9
|
gemcode/compaction.py,sha256=9YtA_qa23_8dHWVHx7AJwUduuI7jJQtq-m6sT8jgPWI,1186
|
|
10
|
-
gemcode/config.py,sha256=
|
|
10
|
+
gemcode/config.py,sha256=xvvhJbMEBPjIotwnxoggTdXpfYaDPjVi5PCIy489610,12540
|
|
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
|
|
@@ -25,8 +25,8 @@ gemcode/model_routing.py,sha256=Q42HZtXQa6rao2O2vYMHxohrTgD-wq4t7qGxU4_38Jg,4881
|
|
|
25
25
|
gemcode/paths.py,sha256=U6cEH9jfIcSc4NO8Ke0jniZSiJTfCIJPvSMue3hR0ZU,768
|
|
26
26
|
gemcode/permissions.py,sha256=9FmwTP_LLflahxS9KXvY3VPSra4e-h3OariOqnWIKDI,177
|
|
27
27
|
gemcode/prompt_suggestions.py,sha256=h-W_9LlfagS91PyoMEjEjsCqoG4XmIh3QBypA59HyGw,2553
|
|
28
|
-
gemcode/repl_commands.py,sha256=
|
|
29
|
-
gemcode/repl_slash.py,sha256=
|
|
28
|
+
gemcode/repl_commands.py,sha256=nnJSibPKCR2unmcRf1pjQKHu8uirHHah-9pFN3Hw9js,7972
|
|
29
|
+
gemcode/repl_slash.py,sha256=AUw5JfQWRZJWSoJKXNunhS0dWTgGRgiSPjcXxNkZpjM,24900
|
|
30
30
|
gemcode/session_runtime.py,sha256=Evqr6YNqB_O0V3omGjqD1ve_6kdpgwe7KFev9-WE_nA,3308
|
|
31
31
|
gemcode/slash_commands.py,sha256=Qylzsj1notk0xN_hvd3CR4HD8g-l99UENDMcg1pKeBA,794
|
|
32
32
|
gemcode/thinking.py,sha256=RanBf_x9fKv1o4DNyNXPLfOdn2xT0KybJb65nYgmMEE,4885
|
|
@@ -63,17 +63,17 @@ gemcode/tools/subtask.py,sha256=ur_6jnwnNzHSBtW96mB2N2A6zmALpydSV24Nkx0T6UQ,5683
|
|
|
63
63
|
gemcode/tools/think.py,sha256=WrNATR-bi97aLkbSsOFOYYAGxbzihe9AnPDZfw3z5-Q,1704
|
|
64
64
|
gemcode/tools/todo.py,sha256=d9aXiyT04r1RFZIk6qdVif17-_Oc3oi4ymDnsPBRg68,3143
|
|
65
65
|
gemcode/tools/web.py,sha256=ULg1e3inG4FjPSUCYI8dVBzTrcCHINNRo76SIU9qw-A,4489
|
|
66
|
-
gemcode/tui/input_handler.py,sha256=
|
|
67
|
-
gemcode/tui/scrollback.py,sha256=
|
|
66
|
+
gemcode/tui/input_handler.py,sha256=kYlESEQpdeoaBZEUwWrackSw_fzwShxiAH_7A_RNz8w,8056
|
|
67
|
+
gemcode/tui/scrollback.py,sha256=ujdYDfyVAofmPDlxpClJ4vFwgMphqricNJDxQlVbkCM,20396
|
|
68
68
|
gemcode/tui/spinner.py,sha256=AJrApG5od-Sh40-5uWcNM9RHb5ax7gr-NbgAZmTbIYY,4848
|
|
69
69
|
gemcode/tui/welcome_banner.py,sha256=aocl1lnoyLIM6RN4f65g3i0wRA71RqUlgPrGsXeVLW4,4387
|
|
70
70
|
gemcode/tui/welcome_rich.py,sha256=8FEZzLXrzqly5JWiDgV9ooRV1LNXDk-CXV1a7K6ua-U,4048
|
|
71
71
|
gemcode/web/__init__.py,sha256=EysmUAWs6g-lmMk4VFljKfaHVrEgb_FiIzwQmBdORJc,40
|
|
72
72
|
gemcode/web/claude_sse_adapter.py,sha256=HcNp0Lh4DdBZBLOpstsqa-VzfqAUrRngZ6FSuJ-mIMg,8609
|
|
73
73
|
gemcode/web/terminal_repl.py,sha256=k2irvFGbCY8gDm_pbirR7b_cakaeafcctoTIvnJkVXk,3902
|
|
74
|
-
gemcode-0.3.
|
|
75
|
-
gemcode-0.3.
|
|
76
|
-
gemcode-0.3.
|
|
77
|
-
gemcode-0.3.
|
|
78
|
-
gemcode-0.3.
|
|
79
|
-
gemcode-0.3.
|
|
74
|
+
gemcode-0.3.23.dist-info/licenses/LICENSE,sha256=TD4524qn-W8Z07GTDnag-9jJPFutFZNB0a1WbMHPC54,8388
|
|
75
|
+
gemcode-0.3.23.dist-info/METADATA,sha256=ZxsvHPJbnkeLZxuaAnsbQIbz8JjsZHuGplk6u4J15uc,23695
|
|
76
|
+
gemcode-0.3.23.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
77
|
+
gemcode-0.3.23.dist-info/entry_points.txt,sha256=cZdLTLDiHbks7OSUCuxCh66dCWeQdpLR8BozoqfEjV4,45
|
|
78
|
+
gemcode-0.3.23.dist-info/top_level.txt,sha256=UYrjULLBY2bcgK6KI6flomJWmsbDXu7n0rvW2SWFrbo,8
|
|
79
|
+
gemcode-0.3.23.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|