gemcode 0.3.107__tar.gz → 0.3.108__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.107/src/gemcode.egg-info → gemcode-0.3.108}/PKG-INFO +1 -1
- {gemcode-0.3.107 → gemcode-0.3.108}/pyproject.toml +1 -1
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/agent.py +83 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/invoke.py +4 -9
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/model_errors.py +18 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/tool_prompt_manifest.py +26 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/tool_registry.py +3 -1
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/tui/scrollback.py +59 -28
- {gemcode-0.3.107 → gemcode-0.3.108/src/gemcode.egg-info}/PKG-INFO +1 -1
- gemcode-0.3.108/tests/test_agent_instruction.py +76 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/tests/test_model_errors.py +17 -1
- gemcode-0.3.107/tests/test_agent_instruction.py +0 -22
- {gemcode-0.3.107 → gemcode-0.3.108}/LICENSE +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/MANIFEST.in +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/README.md +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/setup.cfg +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/__init__.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/__main__.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/audit.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/autocompact.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/autotune.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/callbacks.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/capability_routing.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/checkpoints.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/cli.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/compaction.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/computer_use/__init__.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/computer_use/browser_computer.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/config.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/context_budget.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/context_warning.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/credentials.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/curated_memory.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/dynamic_policy.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/evals/harness.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/hitl_session.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/hooks.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/ide_protocol.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/ide_stdio.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/intent_classifier.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/interactions.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/kaira_client.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/kaira_daemon.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/kaira_ipc.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/kaira_job_store.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/learning.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/limits.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/live_audio_engine.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/logging_config.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/mcp_loader.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/memory/__init__.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/memory/embedding_memory_service.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/memory/file_memory_service.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/modality_tools.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/model_routing.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/multimodal_input.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/openapi_loader.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/org.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/output_styles.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/paths.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/permissions.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/plugins/__init__.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/plugins/terminal_hooks_plugin.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/plugins/tool_recovery_plugin.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/policy_profile.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/pricing.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/prompt_suggestions.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/query/__init__.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/query/config.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/query/deps.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/query/engine.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/query/stop_hooks.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/query/token_budget.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/query/transitions.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/query_sanitizer.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/refine.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/repl_commands.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/repl_slash.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/review_agent.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/rules.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/session_runtime.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/session_store.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/session_summariser.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/skills.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/slash_commands.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/thinking.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/tool_result_store.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/tools/__init__.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/tools/bash.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/tools/browser.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/tools/compress_memory.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/tools/curated_memory.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/tools/edit.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/tools/filesystem.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/tools/notebook.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/tools/notes.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/tools/org_tools.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/tools/repo_map.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/tools/search.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/tools/shell.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/tools/shell_gate.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/tools/skills.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/tools/subtask.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/tools/tasks.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/tools/think.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/tools/todo.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/tools/user_choice.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/tools/veomem_tools.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/tools/web.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/tools/web_search.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/tools_inspector.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/trust.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/tui/input_handler.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/tui/spinner.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/tui/welcome_banner.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/tui/welcome_rich.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/veomem_bridge.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/version.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/vertex.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/wal.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/web/__init__.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/web/sse_adapter.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/web/terminal_repl.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/web/web_sse_compat.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode/workspace_hints.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode.egg-info/SOURCES.txt +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode.egg-info/dependency_links.txt +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode.egg-info/entry_points.txt +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode.egg-info/requires.txt +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/src/gemcode.egg-info/top_level.txt +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/tests/test_add_dir.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/tests/test_autocompact.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/tests/test_capability_routing.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/tests/test_checkpoint_diff_command.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/tests/test_cli_init.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/tests/test_compress_memory_tool.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/tests/test_computer_use_permissions.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/tests/test_context_budget.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/tests/test_context_warning.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/tests/test_credentials.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/tests/test_eval_harness_layout.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/tests/test_ide_stdio_attachments.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/tests/test_interactive_permission_ask.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/tests/test_kaira_scheduler.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/tests/test_modality_tools.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/tests/test_model_error_retry.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/tests/test_model_routing.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/tests/test_multimodal_input.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/tests/test_output_styles_and_rules.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/tests/test_paths.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/tests/test_permissions.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/tests/test_prompt_suggestions.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/tests/test_repl_commands.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/tests/test_repl_slash.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/tests/test_skills.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/tests/test_slash_commands.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/tests/test_slash_completion_registry.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/tests/test_thinking_config.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/tests/test_token_budget.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/tests/test_tool_context_circulation.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/tests/test_tools.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/tests/test_tools_inspector.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/tests/test_web_sse_adapter.py +0 -0
- {gemcode-0.3.107 → gemcode-0.3.108}/tests/test_workspace_hints.py +0 -0
|
@@ -76,6 +76,8 @@ def build_global_instruction() -> str:
|
|
|
76
76
|
"You are GemCode, an expert software engineering agent powered by Google Gemini. "
|
|
77
77
|
"Think deeply about what the person actually wants before you do anything. "
|
|
78
78
|
"Use exactly as many tools as the task genuinely requires — no more. "
|
|
79
|
+
"When routing or capabilities change between turns, still prefer minimal tools, "
|
|
80
|
+
"repo-grounded evidence, and verification before claiming done. "
|
|
79
81
|
"Act fully and autonomously when action is needed. "
|
|
80
82
|
"Always use read-only tools before shell or write tools. "
|
|
81
83
|
"Never create CLAUDE.md or AGENTS.md; use GEMINI.md for project instructions."
|
|
@@ -353,6 +355,79 @@ def _build_runtime_facts(cfg: GemCodeConfig) -> str:
|
|
|
353
355
|
- **Working in subfolders** — call `list_directory(\"Desktop\")`, `glob_files(\"**/query.ts\")`, `read_file(\"testing/ai-edtech-app/src/app/page.tsx\")` directly. Never claim access is blocked unless a tool returned an explicit error.{git_section}{curated_section}{veomem_section}"""
|
|
354
356
|
|
|
355
357
|
|
|
358
|
+
def _build_calibration_section(cfg: GemCodeConfig) -> str:
|
|
359
|
+
"""
|
|
360
|
+
Meta-instruction for "smart" behavior under dynamic routing (auto model/capability mode,
|
|
361
|
+
orchestration tools, etc.). Kept compact to limit prompt bloat.
|
|
362
|
+
"""
|
|
363
|
+
mm = (getattr(cfg, "model_mode", "") or "").strip().lower()
|
|
364
|
+
cm = (getattr(cfg, "capability_mode", "") or "").strip().lower()
|
|
365
|
+
bits: list[str] = []
|
|
366
|
+
if mm == "auto":
|
|
367
|
+
bits.append("`model_mode=auto` (model may shift per turn for speed vs depth)")
|
|
368
|
+
if cm == "auto":
|
|
369
|
+
bits.append("`capability_mode=auto` (deep research / extras may attach per turn)")
|
|
370
|
+
session_note = ""
|
|
371
|
+
if bits:
|
|
372
|
+
session_note = (
|
|
373
|
+
"\n**This session uses dynamic routing:** "
|
|
374
|
+
+ " · ".join(bits)
|
|
375
|
+
+ ". Defaults are **hints** — override with judgment when the task clearly needs more or less depth.\n"
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
return f"""## Calibration and dynamic routing (all modes)
|
|
379
|
+
|
|
380
|
+
Infer **intent → depth → tools** without fixed buckets (requests vary):
|
|
381
|
+
|
|
382
|
+
| Stance | Move |
|
|
383
|
+
| --- | --- |
|
|
384
|
+
| **Explain / review** | Read-only recon first; cite **paths**; avoid unrelated edits. |
|
|
385
|
+
| **Implement / fix** | Recon → plan (`todo_write` when 3+ steps) → smallest change → **verify** (tests, lint, build slice, or read-back). |
|
|
386
|
+
| **Debug** | One hypothesis per iteration; change one variable between tries; never repeat the same failing command verbatim. |
|
|
387
|
+
| **External facts** | Use web/research tools when the answer is outside the repo (docs, APIs, CVEs). Prefer **repo files** for how *this* codebase behaves. |
|
|
388
|
+
|
|
389
|
+
**Evidence:** tie non-obvious claims about this workspace to **files or command output** you actually saw.
|
|
390
|
+
|
|
391
|
+
**Orchestration:** use `spawn_subtasks`, org delegation, or background jobs only when work is **parallel** or **role-split**. Merge into **one** answer with a single recommendation; skip fan-out for small linear tasks.
|
|
392
|
+
|
|
393
|
+
**Anti-patterns:** tool spam; “done” without verification on risky edits; searching the web when the source file is already in-tree; repeating identical failures.{session_note}"""
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
def _engineering_discipline_instruction_enabled() -> bool:
|
|
397
|
+
"""Extra prompt section: cautious change quality. Opt out with GEMCODE_ENGINEERING_DISCIPLINE=0."""
|
|
398
|
+
import os
|
|
399
|
+
|
|
400
|
+
v = os.environ.get("GEMCODE_ENGINEERING_DISCIPLINE", "1").strip().lower()
|
|
401
|
+
return v not in ("0", "false", "no", "off")
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
def _build_engineering_discipline_section(cfg: GemCodeConfig) -> str:
|
|
405
|
+
"""Prompt block for minimal, evidence-grounded edits; trivial fixes need not dwell on it."""
|
|
406
|
+
_ = cfg # reserved for future project-scoped tuning
|
|
407
|
+
return """## Engineering discipline (change quality)
|
|
408
|
+
|
|
409
|
+
**Tradeoff:** biases toward careful, minimal diffs over speed. For trivial edits, use judgment.
|
|
410
|
+
|
|
411
|
+
### Ambiguity
|
|
412
|
+
- Briefly state **what you understood** before substantial implementation. If several readings fit, outline them or ask **one** precise question — do not silently pick and run.
|
|
413
|
+
- Prefer **evidence from this repo** (reads, grep, tests) over guessed APIs, paths, or behaviour.
|
|
414
|
+
|
|
415
|
+
### Scope and simplicity
|
|
416
|
+
- Deliver **what was asked**, not a roadmap of extras. Avoid speculative features, abstraction layers, or configurability “for later” unless the user requested flexibility.
|
|
417
|
+
- Prefer the **smallest** correct change. Expand structure only when complexity is already present or clearly required.
|
|
418
|
+
|
|
419
|
+
### Surgical edits
|
|
420
|
+
- Change **only** what is necessary for the outcome; match surrounding **style and patterns** unless project docs say otherwise.
|
|
421
|
+
- Do not refactor, rename, or reformat unrelated code in the same pass. Note worthwhile cleanups separately if helpful.
|
|
422
|
+
- Remove **orphans your edit introduced** (e.g. unused imports from your change). Leave pre-existing dead code unless the user asks to remove it.
|
|
423
|
+
|
|
424
|
+
### When to call it done
|
|
425
|
+
- Turn fuzzy requests into **checkable** outcomes where it matters (e.g. bug → reproduce → fix → same checks green).
|
|
426
|
+
- After material edits, run the **cheapest** falsifying step you can: targeted test, lint, build, or re-read the critical path — not guess-and-hope.
|
|
427
|
+
|
|
428
|
+
"""
|
|
429
|
+
|
|
430
|
+
|
|
356
431
|
def _build_memory_section(cfg: GemCodeConfig) -> str:
|
|
357
432
|
"""Injected when enable_memory=True so the agent understands and uses memory."""
|
|
358
433
|
mem_path = cfg.project_root / ".gemcode" / "memories.jsonl"
|
|
@@ -559,6 +634,12 @@ def build_instruction(cfg: GemCodeConfig) -> str:
|
|
|
559
634
|
"on",
|
|
560
635
|
)
|
|
561
636
|
|
|
637
|
+
discipline_block = (
|
|
638
|
+
_build_engineering_discipline_section(cfg)
|
|
639
|
+
if _engineering_discipline_instruction_enabled()
|
|
640
|
+
else ""
|
|
641
|
+
)
|
|
642
|
+
|
|
562
643
|
base = f"""You are GemCode, an expert software engineering agent powered by Google Gemini.
|
|
563
644
|
You run locally via the GemCode CLI. You are the same agent the user launched — not a hosted portal.
|
|
564
645
|
|
|
@@ -610,6 +691,8 @@ You have native deep thinking capability — use it actively:
|
|
|
610
691
|
- Prefer **small, targeted tool outputs** by default (saves context, improves accuracy).
|
|
611
692
|
- If a tool output was **offloaded** (you see a `tool_result:<sha>` reference), and you need details, call `load_tool_result(ref)` and extract only the relevant slice.
|
|
612
693
|
|
|
694
|
+
{_build_calibration_section(cfg)}
|
|
695
|
+
{discipline_block}
|
|
613
696
|
## Tool selection guide (only when needed)
|
|
614
697
|
|
|
615
698
|
Keep tool usage minimal. Prefer short, targeted calls and keep tool outputs small.
|
|
@@ -18,11 +18,6 @@ from google.adk.runners import Runner
|
|
|
18
18
|
from google.genai import types
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
# Delays (seconds) between successive transient-error retries: 2s, 5s, 12s.
|
|
22
|
-
# Three retries = up to ~19 seconds of total wait before giving up.
|
|
23
|
-
_TRANSIENT_RETRY_DELAYS = [2.0, 5.0, 12.0]
|
|
24
|
-
|
|
25
|
-
|
|
26
21
|
_HITL_PROMPT_LOCK = Lock()
|
|
27
22
|
|
|
28
23
|
async def _maybe_enqueue_kaira_autopilot(*, cfg: "GemCodeConfig", session_id: str) -> None:
|
|
@@ -423,14 +418,14 @@ async def run_turn(
|
|
|
423
418
|
next_message=current_message, do_reset=do_reset
|
|
424
419
|
)
|
|
425
420
|
except Exception as _exc:
|
|
426
|
-
from gemcode.model_errors import is_transient_error
|
|
427
|
-
if is_transient_error(_exc) and transient_attempts < len(
|
|
428
|
-
delay =
|
|
421
|
+
from gemcode.model_errors import API_TRANSIENT_RETRY_DELAYS_SEC, is_transient_error
|
|
422
|
+
if is_transient_error(_exc) and transient_attempts < len(API_TRANSIENT_RETRY_DELAYS_SEC):
|
|
423
|
+
delay = API_TRANSIENT_RETRY_DELAYS_SEC[transient_attempts]
|
|
429
424
|
transient_attempts += 1
|
|
430
425
|
_tui_active = os.environ.get("GEMCODE_TUI_ACTIVE", "0").lower() in ("1", "true", "yes", "on")
|
|
431
426
|
_msg = (
|
|
432
427
|
f"\n[gemcode] Transient API error ({type(_exc).__name__}). "
|
|
433
|
-
f"Retrying in {delay:.0f}s (attempt {transient_attempts}/{len(
|
|
428
|
+
f"Retrying in {delay:.0f}s (attempt {transient_attempts}/{len(API_TRANSIENT_RETRY_DELAYS_SEC)})...\n"
|
|
434
429
|
)
|
|
435
430
|
print(_msg, file=sys.stderr)
|
|
436
431
|
# Surface retry notice in TUI if available.
|
|
@@ -4,6 +4,9 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import re
|
|
6
6
|
|
|
7
|
+
# Seconds between retries for transient API failures (shared by invoke.py and TUI).
|
|
8
|
+
API_TRANSIENT_RETRY_DELAYS_SEC: tuple[float, ...] = (2.0, 5.0, 12.0)
|
|
9
|
+
|
|
7
10
|
|
|
8
11
|
def is_transient_error(error: Exception) -> bool:
|
|
9
12
|
"""Return True for HTTP 503 / 429 and similar transient API errors that are safe to retry.
|
|
@@ -29,6 +32,21 @@ def is_transient_error(error: Exception) -> bool:
|
|
|
29
32
|
return True
|
|
30
33
|
|
|
31
34
|
msg = str(error)
|
|
35
|
+
ml = msg.lower()
|
|
36
|
+
|
|
37
|
+
# httpx / google-genai often raise ``ServerError`` for HTTP 500 without ``APIError.code``.
|
|
38
|
+
if et == "ServerError" or "ServerError" in et:
|
|
39
|
+
if any(code in msg for code in ("500", "502", "503", "504")):
|
|
40
|
+
return True
|
|
41
|
+
|
|
42
|
+
# Gemini REST body shape: ``'code': 500`` / ``"INTERNAL"`` / "Internal error encountered."
|
|
43
|
+
if ("'code': 500" in msg or '"code": 500' in msg or re.search(r"\b500\b", msg)) and any(
|
|
44
|
+
p in ml for p in ("internal", "unavailable", "try again", "deadline", "timeout", "backend")
|
|
45
|
+
):
|
|
46
|
+
return True
|
|
47
|
+
if "internal error encountered" in ml:
|
|
48
|
+
return True
|
|
49
|
+
|
|
32
50
|
# Match the specific phrases Gemini uses in 503 responses
|
|
33
51
|
if "503" in msg and any(p in msg for p in ("high demand", "service unavailable", "overloaded")):
|
|
34
52
|
return True
|
|
@@ -105,6 +105,30 @@ def build_tool_manifest(cfg: GemCodeConfig) -> str | None:
|
|
|
105
105
|
|
|
106
106
|
memory_on = bool(getattr(cfg, "enable_memory", False))
|
|
107
107
|
|
|
108
|
+
mm = (getattr(cfg, "model_mode", "") or "").strip().lower()
|
|
109
|
+
cm = (getattr(cfg, "capability_mode", "") or "").strip().lower()
|
|
110
|
+
auto_routing_note = ""
|
|
111
|
+
if mm == "auto" or cm == "auto":
|
|
112
|
+
auto_routing_note = (
|
|
113
|
+
f"\n- **Dynamic routing:** `model_mode={mm}`, `capability_mode={cm}` — per-turn defaults are **hints**; "
|
|
114
|
+
"still pick the smallest depth/toolset that fits the ask.\n"
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
calibration_manifest = f"""### Calibration (aligned with main instruction)
|
|
118
|
+
- **Repo vs external:** ground claims about *this repo* with reads/grep/tests; use research/web for **external** docs, APIs, or facts outside the tree.
|
|
119
|
+
- **Orchestration:** use `run_subtask` / `spawn_subtasks` only for **parallel independent** work or explicit verification; merge into **one** answer; skip fan-out for trivial linear tasks.
|
|
120
|
+
- **Finish line:** verify risky edits (test/lint/read-back) before declaring done.{auto_routing_note}"""
|
|
121
|
+
|
|
122
|
+
_disc = os.environ.get("GEMCODE_ENGINEERING_DISCIPLINE", "1").strip().lower()
|
|
123
|
+
discipline_manifest = ""
|
|
124
|
+
if _disc not in ("0", "false", "no", "off"):
|
|
125
|
+
discipline_manifest = """
|
|
126
|
+
|
|
127
|
+
### Engineering discipline (aligned with main instruction)
|
|
128
|
+
- **Ambiguity:** state what you understood or ask **one** precise question; prefer repo evidence over guesses.
|
|
129
|
+
- **Scope:** deliver the ask with the **smallest** adequate change; skip speculative extras.
|
|
130
|
+
- **Surgical:** touch only what you must; match local style; clean up orphans **your** edit introduced."""
|
|
131
|
+
|
|
108
132
|
manifest = f"""## Tool system (GemCode)
|
|
109
133
|
|
|
110
134
|
### Execution model
|
|
@@ -112,6 +136,8 @@ def build_tool_manifest(cfg: GemCodeConfig) -> str | None:
|
|
|
112
136
|
- **Reason end-to-end autonomously.** The user expects complete tasks, not a questionnaire. Use `think` before complex actions, `todo_write` to track multi-step work.
|
|
113
137
|
- **Never stop after the first tool call succeeds.** Keep going until the full task is done or you hit a genuine blocker.
|
|
114
138
|
|
|
139
|
+
{calibration_manifest}{discipline_manifest}
|
|
140
|
+
|
|
115
141
|
### Permission policy
|
|
116
142
|
| Setting | Value |
|
|
117
143
|
|---------|-------|
|
|
@@ -38,7 +38,9 @@ SHELL_TOOLS: frozenset[str] = frozenset({"run_command", "bash"})
|
|
|
38
38
|
# Session planning only (no disk / shell; no extra permission)
|
|
39
39
|
# think — in-context reasoning scratchpad (no-op, no side effects)
|
|
40
40
|
# run_subtask — spawns a sub-agent; inherits parent permission settings
|
|
41
|
-
PLANNING_TOOLS: frozenset[str] = frozenset(
|
|
41
|
+
PLANNING_TOOLS: frozenset[str] = frozenset(
|
|
42
|
+
{"todo_write", "think", "run_subtask", "spawn_subtasks"}
|
|
43
|
+
)
|
|
42
44
|
|
|
43
45
|
ToolConcurrency = Literal["parallel_safe", "serial_mutating", "shell"]
|
|
44
46
|
|
|
@@ -16,6 +16,7 @@ from gemcode.multimodal_input import build_user_content
|
|
|
16
16
|
|
|
17
17
|
from gemcode.capability_routing import apply_capability_routing
|
|
18
18
|
from gemcode.config import load_cli_environment
|
|
19
|
+
from gemcode.model_errors import API_TRANSIENT_RETRY_DELAYS_SEC, format_model_error_for_user, is_transient_error
|
|
19
20
|
from gemcode.model_routing import pick_effective_model
|
|
20
21
|
from gemcode.repl_slash import process_repl_slash
|
|
21
22
|
from gemcode.tui.input_handler import GemCodeInputHandler
|
|
@@ -915,40 +916,70 @@ async def run_gemcode_scrollback_tui(
|
|
|
915
916
|
# as different phases of the turn complete.
|
|
916
917
|
_start_anim("Thinking\u2026")
|
|
917
918
|
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
continue
|
|
930
|
-
for part in ev.content.parts:
|
|
931
|
-
delta = getattr(part, "text", None)
|
|
932
|
-
if not delta:
|
|
919
|
+
transient_attempts = 0
|
|
920
|
+
stream_exc: Exception | None = None
|
|
921
|
+
while True:
|
|
922
|
+
stream_exc = None
|
|
923
|
+
try:
|
|
924
|
+
async for ev in runner.run_async(**kwargs):
|
|
925
|
+
events.append(ev)
|
|
926
|
+
_render_tool_calls(ev)
|
|
927
|
+
_render_tool_results(ev)
|
|
928
|
+
try:
|
|
929
|
+
if not ev.content or not ev.content.parts:
|
|
933
930
|
continue
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
931
|
+
# Only skip user turns. ADK often omits `author` on model events — do NOT
|
|
932
|
+
# skip those or the assistant text never renders (blank reply, ↓0 tokens).
|
|
933
|
+
if getattr(ev, "author", None) == "user":
|
|
934
|
+
continue
|
|
935
|
+
for part in ev.content.parts:
|
|
936
|
+
delta = getattr(part, "text", None)
|
|
937
|
+
if not delta:
|
|
938
|
+
continue
|
|
939
|
+
assistant_wrote_text = True
|
|
940
|
+
if getattr(part, "thought", None):
|
|
941
|
+
buffered_thought.append(delta)
|
|
942
|
+
else:
|
|
943
|
+
buffered_final.append(delta)
|
|
944
|
+
except Exception:
|
|
945
|
+
continue
|
|
946
|
+
break
|
|
947
|
+
except Exception as _turn_err:
|
|
948
|
+
if is_transient_error(_turn_err) and transient_attempts < len(
|
|
949
|
+
API_TRANSIENT_RETRY_DELAYS_SEC
|
|
950
|
+
):
|
|
951
|
+
_stop_anim()
|
|
952
|
+
delay = API_TRANSIENT_RETRY_DELAYS_SEC[transient_attempts]
|
|
953
|
+
transient_attempts += 1
|
|
954
|
+
print(
|
|
955
|
+
f"\n {ansi.dim}[gemcode] Transient API error ({type(_turn_err).__name__}). "
|
|
956
|
+
f"Retrying in {delay:.0f}s ({transient_attempts}/"
|
|
957
|
+
f"{len(API_TRANSIENT_RETRY_DELAYS_SEC)})…{ansi.reset}\n",
|
|
958
|
+
flush=True,
|
|
959
|
+
)
|
|
960
|
+
await asyncio.sleep(delay)
|
|
961
|
+
events.clear()
|
|
962
|
+
assistant_wrote_text = False
|
|
963
|
+
buffered_thought.clear()
|
|
964
|
+
buffered_final.clear()
|
|
965
|
+
last_tool_error = None
|
|
966
|
+
_start_anim("Retrying\u2026")
|
|
940
967
|
continue
|
|
941
|
-
|
|
968
|
+
stream_exc = _turn_err
|
|
969
|
+
break
|
|
970
|
+
|
|
971
|
+
if stream_exc is not None:
|
|
942
972
|
# Catch runner errors (e.g. ADK ValueError from mismatched function
|
|
943
973
|
# response IDs) so a single bad turn doesn't crash the whole TUI.
|
|
944
974
|
_stop_anim()
|
|
975
|
+
try:
|
|
976
|
+
hint = format_model_error_for_user(stream_exc)
|
|
977
|
+
except Exception:
|
|
978
|
+
hint = f"{type(stream_exc).__name__}: {stream_exc}"
|
|
979
|
+
print(f"\n {ansi.blue_warn}[gemcode] turn error: {hint}{ansi.reset}")
|
|
945
980
|
print(
|
|
946
|
-
f"
|
|
947
|
-
f"
|
|
948
|
-
)
|
|
949
|
-
print(
|
|
950
|
-
f" {ansi.dim}The agent encountered an internal error on this turn. "
|
|
951
|
-
f"Please send your message again.{ansi.reset}\n"
|
|
981
|
+
f" {ansi.dim}If this was a temporary Google API issue, send your message again. "
|
|
982
|
+
f"Otherwise try /compact, a shorter prompt, or /model to switch model.{ansi.reset}\n"
|
|
952
983
|
)
|
|
953
984
|
break
|
|
954
985
|
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from gemcode.agent import build_instruction
|
|
4
|
+
from gemcode.config import GemCodeConfig
|
|
5
|
+
from gemcode.tool_prompt_manifest import build_tool_manifest
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def test_instruction_includes_runtime_facts(tmp_path: Path) -> None:
|
|
9
|
+
cfg = GemCodeConfig(project_root=tmp_path, model="gemini-2.5-flash")
|
|
10
|
+
text = build_instruction(cfg)
|
|
11
|
+
assert str(tmp_path.resolve()) in text
|
|
12
|
+
assert "gemini-2.5-flash" in text
|
|
13
|
+
assert "GEMCODE_MODEL" in text
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def test_instruction_includes_calibration_section(tmp_path: Path) -> None:
|
|
17
|
+
cfg = GemCodeConfig(project_root=tmp_path, model="gemini-2.5-flash")
|
|
18
|
+
text = build_instruction(cfg)
|
|
19
|
+
assert "Calibration and dynamic routing" in text
|
|
20
|
+
assert "Orchestration" in text
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def test_instruction_includes_engineering_discipline_section(tmp_path: Path) -> None:
|
|
24
|
+
cfg = GemCodeConfig(project_root=tmp_path, model="gemini-2.5-flash")
|
|
25
|
+
text = build_instruction(cfg)
|
|
26
|
+
assert "Engineering discipline (change quality)" in text
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def test_instruction_omits_engineering_discipline_when_disabled(tmp_path: Path, monkeypatch) -> None:
|
|
30
|
+
monkeypatch.setenv("GEMCODE_ENGINEERING_DISCIPLINE", "0")
|
|
31
|
+
cfg = GemCodeConfig(project_root=tmp_path, model="gemini-2.5-flash")
|
|
32
|
+
text = build_instruction(cfg)
|
|
33
|
+
assert "Engineering discipline (change quality)" not in text
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_tool_manifest_includes_engineering_discipline_aligned_block(tmp_path: Path) -> None:
|
|
37
|
+
cfg = GemCodeConfig(project_root=tmp_path, model="gemini-2.5-flash")
|
|
38
|
+
m = build_tool_manifest(cfg)
|
|
39
|
+
assert m is not None
|
|
40
|
+
assert "Engineering discipline (aligned with main instruction)" in m
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def test_tool_manifest_omits_engineering_discipline_when_disabled(tmp_path: Path, monkeypatch) -> None:
|
|
44
|
+
monkeypatch.setenv("GEMCODE_ENGINEERING_DISCIPLINE", "0")
|
|
45
|
+
cfg = GemCodeConfig(project_root=tmp_path, model="gemini-2.5-flash")
|
|
46
|
+
m = build_tool_manifest(cfg)
|
|
47
|
+
assert m is not None
|
|
48
|
+
assert "Engineering discipline (aligned with main instruction)" not in m
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def test_tool_manifest_includes_calibration_aligned_block(tmp_path: Path) -> None:
|
|
52
|
+
cfg = GemCodeConfig(project_root=tmp_path, model="gemini-2.5-flash")
|
|
53
|
+
m = build_tool_manifest(cfg)
|
|
54
|
+
assert m is not None
|
|
55
|
+
assert "Calibration (aligned with main instruction)" in m
|
|
56
|
+
assert "spawn_subtasks" in m
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def test_instruction_notes_auto_routing_when_configured(tmp_path: Path) -> None:
|
|
60
|
+
cfg = GemCodeConfig(project_root=tmp_path, model="gemini-2.5-flash")
|
|
61
|
+
cfg.model_mode = "auto"
|
|
62
|
+
cfg.capability_mode = "auto"
|
|
63
|
+
text = build_instruction(cfg)
|
|
64
|
+
assert "dynamic routing" in text
|
|
65
|
+
assert "model_mode=auto" in text
|
|
66
|
+
assert "capability_mode=auto" in text
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def test_instruction_includes_veomem_tool_flow_when_recall_present(tmp_path: Path) -> None:
|
|
70
|
+
cfg = GemCodeConfig(project_root=tmp_path, model="gemini-2.5-flash")
|
|
71
|
+
object.__setattr__(cfg, "_veomem_wakeup_text", "<veomem-context>hello</veomem-context>")
|
|
72
|
+
text = build_instruction(cfg)
|
|
73
|
+
assert "VeoMem recall" in text
|
|
74
|
+
assert "veomem_search(query=...)" in text
|
|
75
|
+
assert "veomem_timeline(id=...)" in text
|
|
76
|
+
assert "veomem_get_observations(ids=...)" in text
|
|
@@ -4,7 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import pytest
|
|
6
6
|
|
|
7
|
-
from gemcode.model_errors import format_model_error_for_user
|
|
7
|
+
from gemcode.model_errors import format_model_error_for_user, is_transient_error
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
def test_format_generic_exception() -> None:
|
|
@@ -13,6 +13,22 @@ def test_format_generic_exception() -> None:
|
|
|
13
13
|
assert "something broke" in msg
|
|
14
14
|
|
|
15
15
|
|
|
16
|
+
def test_is_transient_server_error_500_internal() -> None:
|
|
17
|
+
"""Gemini often surfaces 500 INTERNAL as httpx ServerError, not genai APIError."""
|
|
18
|
+
msg = (
|
|
19
|
+
"ServerError: 500 INTERNAL. {'error': {'code': 500, 'message': "
|
|
20
|
+
"'Internal error encountered.', 'status': 'INTERNAL'}}"
|
|
21
|
+
)
|
|
22
|
+
assert is_transient_error(RuntimeError(msg))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def test_is_transient_server_error_classname() -> None:
|
|
26
|
+
class ServerError(Exception):
|
|
27
|
+
pass
|
|
28
|
+
|
|
29
|
+
assert is_transient_error(ServerError("500 something"))
|
|
30
|
+
|
|
31
|
+
|
|
16
32
|
def test_format_genai_client_error() -> None:
|
|
17
33
|
try:
|
|
18
34
|
from google.genai import errors as genai_errors
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
from pathlib import Path
|
|
2
|
-
|
|
3
|
-
from gemcode.agent import build_instruction
|
|
4
|
-
from gemcode.config import GemCodeConfig
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def test_instruction_includes_runtime_facts(tmp_path: Path) -> None:
|
|
8
|
-
cfg = GemCodeConfig(project_root=tmp_path, model="gemini-2.5-flash")
|
|
9
|
-
text = build_instruction(cfg)
|
|
10
|
-
assert str(tmp_path.resolve()) in text
|
|
11
|
-
assert "gemini-2.5-flash" in text
|
|
12
|
-
assert "GEMCODE_MODEL" in text
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def test_instruction_includes_veomem_tool_flow_when_recall_present(tmp_path: Path) -> None:
|
|
16
|
-
cfg = GemCodeConfig(project_root=tmp_path, model="gemini-2.5-flash")
|
|
17
|
-
object.__setattr__(cfg, "_veomem_wakeup_text", "<veomem-context>hello</veomem-context>")
|
|
18
|
-
text = build_instruction(cfg)
|
|
19
|
-
assert "VeoMem recall" in text
|
|
20
|
-
assert "veomem_search(query=...)" in text
|
|
21
|
-
assert "veomem_timeline(id=...)" in text
|
|
22
|
-
assert "veomem_get_observations(ids=...)" in text
|
|
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
|
|
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
|