gemcode 0.3.76__py3-none-any.whl → 0.3.77__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.
Files changed (60) hide show
  1. gemcode/agent.py +16 -16
  2. gemcode/autocompact.py +2 -2
  3. gemcode/callbacks.py +6 -6
  4. gemcode/capability_routing.py +2 -2
  5. gemcode/cli.py +28 -28
  6. gemcode/config.py +4 -4
  7. gemcode/context_budget.py +2 -2
  8. gemcode/context_warning.py +6 -6
  9. gemcode/credentials.py +1 -1
  10. gemcode/hooks.py +1 -1
  11. gemcode/invoke.py +1 -1
  12. gemcode/{kairos_daemon.py → kaira_daemon.py} +19 -19
  13. gemcode/limits.py +1 -1
  14. gemcode/mcp_loader.py +1 -1
  15. gemcode/modality_tools.py +1 -1
  16. gemcode/model_routing.py +1 -1
  17. gemcode/permissions.py +2 -2
  18. gemcode/plugins/terminal_hooks_plugin.py +1 -1
  19. gemcode/plugins/tool_recovery_plugin.py +2 -2
  20. gemcode/prompt_suggestions.py +2 -2
  21. gemcode/query/__init__.py +1 -1
  22. gemcode/query/config.py +1 -1
  23. gemcode/query/deps.py +1 -1
  24. gemcode/query/engine.py +1 -1
  25. gemcode/query/stop_hooks.py +1 -1
  26. gemcode/query/token_budget.py +2 -2
  27. gemcode/query/transitions.py +1 -1
  28. gemcode/repl_commands.py +3 -3
  29. gemcode/repl_slash.py +9 -9
  30. gemcode/session_runtime.py +1 -1
  31. gemcode/skills.py +1 -1
  32. gemcode/slash_commands.py +1 -1
  33. gemcode/thinking.py +4 -4
  34. gemcode/tool_prompt_manifest.py +1 -1
  35. gemcode/tool_registry.py +2 -2
  36. gemcode/tool_result_store.py +1 -1
  37. gemcode/tools/bash.py +1 -1
  38. gemcode/tools/edit.py +3 -2
  39. gemcode/tools/notebook.py +2 -2
  40. gemcode/tools/notes.py +2 -3
  41. gemcode/tools/subtask.py +1 -1
  42. gemcode/tools/tasks.py +2 -2
  43. gemcode/tools/think.py +1 -2
  44. gemcode/tools/todo.py +1 -1
  45. gemcode/tools/web.py +1 -1
  46. gemcode/tools/web_search.py +1 -1
  47. gemcode/tools_inspector.py +1 -1
  48. gemcode/tui/input_handler.py +1 -1
  49. gemcode/tui/scrollback.py +3 -3
  50. gemcode/tui/spinner.py +8 -8
  51. gemcode/tui/welcome_rich.py +1 -1
  52. gemcode/web/{claude_sse_adapter.py → web_sse_compat.py} +2 -5
  53. gemcode-0.3.77.dist-info/METADATA +689 -0
  54. gemcode-0.3.77.dist-info/RECORD +108 -0
  55. gemcode-0.3.76.dist-info/METADATA +0 -523
  56. gemcode-0.3.76.dist-info/RECORD +0 -108
  57. {gemcode-0.3.76.dist-info → gemcode-0.3.77.dist-info}/WHEEL +0 -0
  58. {gemcode-0.3.76.dist-info → gemcode-0.3.77.dist-info}/entry_points.txt +0 -0
  59. {gemcode-0.3.76.dist-info → gemcode-0.3.77.dist-info}/licenses/LICENSE +0 -0
  60. {gemcode-0.3.76.dist-info → gemcode-0.3.77.dist-info}/top_level.txt +0 -0
gemcode/agent.py CHANGED
@@ -1,5 +1,5 @@
1
1
  """
2
- Root LlmAgent definition (Claude Code: agent config + tool list, analogous to tools.ts + prompts).
2
+ Root LlmAgent definition (agent config + tool list, analogous to a tools registry + prompts).
3
3
 
4
4
  See `session_runtime.py` for Runner/session wiring (outer layer).
5
5
  See `tool_registry.py` for tool categories (read vs mutating vs shell).
@@ -64,7 +64,7 @@ def _chain_before_model_callbacks(*callbacks):
64
64
 
65
65
  def _load_gemini_md(project_root: Path) -> str:
66
66
  """
67
- Load GEMINI.md / .gemcode/NOTES.md from a Claude Code–style hierarchy.
67
+ Load GEMINI.md / .gemcode/NOTES.md from a interactive CLI–style hierarchy.
68
68
 
69
69
  Priority (later entries override earlier ones, all are concatenated):
70
70
  1. ~/.gemcode/GEMINI.md — user-global instructions (all projects)
@@ -89,7 +89,7 @@ def _load_gemini_md(project_root: Path) -> str:
89
89
  return ""
90
90
  try:
91
91
  raw = p.read_text(encoding="utf-8", errors="replace")[:_FILE_CAP]
92
- # Strip HTML comments (like Claude Code does — saves tokens)
92
+ # Strip HTML comments (saves tokens)
93
93
  return _COMMENT_RE.sub("", raw).strip()
94
94
  except OSError:
95
95
  return ""
@@ -140,7 +140,7 @@ def _get_git_context(root) -> str:
140
140
  """
141
141
  Run a quick git snapshot at session start — branch, recent commits, diff-stat.
142
142
  Returns a formatted string or empty string if not a git repo.
143
- Mirrors OpenClaude's getGitStatus() pattern.
143
+ Mirrors Reference UI getGitStatus() pattern.
144
144
  """
145
145
  import subprocess
146
146
  import shutil
@@ -232,18 +232,18 @@ def _build_runtime_facts(cfg: GemCodeConfig) -> str:
232
232
  if max_session_tokens:
233
233
  budget_line += f" · max_session_tokens={max_session_tokens:,}"
234
234
 
235
- # ── Kairos ────────────────────────────────────────────────────────────────
236
- # The user can run `gemcode kairos -C <project>` in a separate terminal to
235
+ # ── Kaira ────────────────────────────────────────────────────────────────
236
+ # The user can run `gemcode kaira -C <project>` in a separate terminal to
237
237
  # launch a long-lived scheduler. Jobs submitted to it run concurrently with
238
238
  # the current session. This is useful for background / parallel heavy work.
239
- kairos_section = (
240
- "- **Kairos background scheduler** — `gemcode kairos -C <project>` launches a "
239
+ kaira_section = (
240
+ "- **Kaira background scheduler** — `gemcode kaira -C <project>` launches a "
241
241
  "long-lived daemon that reads prompts from stdin and runs each as an isolated job "
242
- "(up to N concurrently). Each job gets `kairos_sleep_ms(ms)` and "
243
- "`kairos_enqueue_prompt(prompt, priority, session_id)` tools so the model can "
242
+ "(up to N concurrently). Each job gets `kaira_sleep_ms(ms)` and "
243
+ "`kaira_enqueue_prompt(prompt, priority, session_id)` tools so the model can "
244
244
  "schedule follow-up work itself. Useful for: bulk file processing, repeated "
245
245
  "polling loops, parallelising large independent tasks. "
246
- "Tell the user to open a second terminal and run `gemcode kairos` if a task "
246
+ "Tell the user to open a second terminal and run `gemcode kaira` if a task "
247
247
  "would benefit from background parallelism."
248
248
  )
249
249
 
@@ -274,7 +274,7 @@ def _build_runtime_facts(cfg: GemCodeConfig) -> str:
274
274
  - **Capability routing** (`capability_mode={getattr(cfg, 'capability_mode', 'auto')}`): in `auto` mode, GemCode automatically enables deep_research when it detects research-intent keywords in your prompt each turn. You can also type `/research on`, `/embeddings on`, `/memory on`, `/computer on` at the prompt.
275
275
  - **Your tool palette can grow mid-session:** if the user enables a capability via a slash command, the runner rebuilds and you get new tools on the next turn.
276
276
  - **Memory system:** when `memory ON`, ADK automatically searches `.gemcode/memories.jsonl` and injects relevant past context before each turn. Facts the user tells you in one session can appear in future sessions. You do not need to manage memory explicitly — it is loaded automatically.
277
- {kairos_section}
277
+ {kaira_section}
278
278
  - **UI banner** phrases like "GemCode Pro" are terminal marketing, not a separate API tier.
279
279
  - **Env toggles** (`GEMCODE_ENABLE_COMPUTER_USE`, `GEMCODE_MODEL`, etc.) affect only the OS process that launched gemcode. Pasting `VAR=1` in chat does NOT reconfigure a running session—tell the user to export in their shell, use project `.env`, or restart the CLI.
280
280
  - **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}"""
@@ -680,7 +680,7 @@ Concrete patterns:
680
680
  - Grepping different patterns → multiple `grep_content` in one response
681
681
  - `list_directory` + `glob_files` → both at once
682
682
 
683
- **Parallel sub-agent exploration (OpenClaude pattern):**
683
+ **Parallel sub-agent exploration (reference terminal UI pattern):**
684
684
  When a task requires understanding several subsystems before acting:
685
685
  1. Spawn parallel `run_subtask` workers, one per subsystem
686
686
  2. Wait for all results to return in the same turn
@@ -844,7 +844,7 @@ Use `gh pr create` via `bash`. When asked to create a PR:
844
844
  All file tools use paths **relative to the project root** (where GemCode was started). The root may be the home folder — subfolders like `Desktop`, `Desktop/code`, `Documents` are inside the sandbox. Call `list_directory("Desktop")` or `glob_files("**/*name*.ts")` instead of assuming access is blocked. Only treat access as denied when a tool returns an explicit `error`.
845
845
 
846
846
  ## Agent notes (.gemcode/notes.md)
847
- You have two tools to persist project insights across sessions, like Claude Code's auto-memory:
847
+ You have two tools to persist project insights across sessions (auto-memory style):
848
848
 
849
849
  - **`append_project_note(note)`** — write a note to `.gemcode/notes.md`. Use this proactively when you discover something worth remembering:
850
850
  - Build/test/lint commands you discover ("Build: `npm run build` — requires Node 20")
@@ -936,7 +936,7 @@ def build_root_agent(
936
936
  except Exception:
937
937
  pass
938
938
 
939
- # Agent auto-notes: write project insights to .gemcode/notes.md (Claude Code MEMORY.md equivalent)
939
+ # Agent auto-notes: write project insights to .gemcode/notes.md (project notes file)
940
940
  try:
941
941
  from gemcode.tools.notes import build_notes_tools
942
942
  notes_tools = build_notes_tools(cfg.project_root)
@@ -964,7 +964,7 @@ def build_root_agent(
964
964
  if before_model is not None:
965
965
  cb_kwargs["before_model_callback"] = before_model
966
966
 
967
- # Claude-like thinking: enabled by default (Gemini dynamic), but allow
967
+ # familiar thinking: enabled by default (Gemini dynamic), but allow
968
968
  # explicit overrides for disable/budgets/levels.
969
969
  gen_cfg = None
970
970
  thinking_cfg = build_thinking_config(cfg)
gemcode/autocompact.py CHANGED
@@ -1,5 +1,5 @@
1
1
  """
2
- Claude Code–style autocompact for ADK/Gemini.
2
+ interactive CLI–style autocompact for ADK/Gemini.
3
3
 
4
4
  GemCode already has:
5
5
  - bounded tool output (after_tool truncation)
@@ -41,7 +41,7 @@ def _autocompact_enabled(cfg: GemCodeConfig) -> bool:
41
41
 
42
42
 
43
43
  def _autocompact_threshold_chars(cfg: GemCodeConfig) -> int:
44
- # Claude Code uses token windows; we use a character proxy budget since
44
+ # uses token windows; we use a character proxy budget since
45
45
  # Gemini tokenizers vary and ADK does not expose a cheap exact counter.
46
46
  max_chars = int(getattr(cfg, "max_context_chars", 0) or 0)
47
47
  if max_chars <= 0:
gemcode/callbacks.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """
2
2
  ADK callbacks: permissions, audit, tool failure circuit breaker, usage logging.
3
3
 
4
- Maps to Claude Code patterns:
4
+ Maps to patterns:
5
5
  - before_tool / after_tool ≈ permission gates + telemetry around tool execution
6
6
  - after_model ≈ cost / usage hooks (see cost-tracker.ts role)
7
7
  - Session state for streak counters ≈ autoCompact failure tracking (MVP: tool errors)
@@ -60,7 +60,7 @@ def _truthy_env(name: str, *, default: bool = False) -> bool:
60
60
 
61
61
 
62
62
  def _maybe_tool_summary_enabled() -> bool:
63
- # Mirrors Claude's "emit tool use summaries" gate conceptually.
63
+ # Mirrors optional "emit tool use summaries" gating.
64
64
  return _truthy_env("GEMCODE_EMIT_TOOL_USE_SUMMARIES", default=False)
65
65
 
66
66
 
@@ -344,7 +344,7 @@ def make_before_tool_callback(cfg: GemCodeConfig):
344
344
 
345
345
 
346
346
  def make_after_tool_callback(cfg: GemCodeConfig):
347
- """Track consecutive tool failures in session state (Claude-style circuit breaker)."""
347
+ """Track consecutive tool failures in session state (conventional circuit breaker)."""
348
348
 
349
349
  def after_tool(
350
350
  tool: BaseTool,
@@ -548,7 +548,7 @@ def make_after_tool_callback(cfg: GemCodeConfig):
548
548
  summary[k] = v
549
549
  append_audit(cfg.project_root, summary)
550
550
  # Also print a concise, user-visible summary in CLI contexts.
551
- # (Claude Code renders tool cards; this is the lightweight equivalent.)
551
+ # (renders tool cards; this is the lightweight equivalent.)
552
552
  try:
553
553
  # Full-screen TUIs get corrupted by stray stderr prints.
554
554
  if _truthy_env("GEMCODE_TUI_ACTIVE", default=False):
@@ -621,7 +621,7 @@ def make_after_model_callback(cfg: GemCodeConfig):
621
621
 
622
622
  # ── Expose live token stats to the TUI ───────────────────────────────────
623
623
  # The TUI reads cfg._last_turn_stats after each turn to display token counts
624
- # and estimated cost in the footer (like OpenClaude's spinner token display).
624
+ # and estimated cost in the footer (like Reference UI spinner token display).
625
625
  try:
626
626
  in_tok = d.get("prompt_token_count", 0) or 0
627
627
  out_tok = d.get("candidates_token_count", 0) or 0
@@ -762,7 +762,7 @@ def make_after_model_callback(cfg: GemCodeConfig):
762
762
 
763
763
 
764
764
  def make_on_tool_error_callback(cfg: GemCodeConfig):
765
- """Turn tool exceptions into structured tool results (Claude-like is_error)."""
765
+ """Turn tool exceptions into structured tool results (familiar is_error)."""
766
766
 
767
767
  async def on_tool_error(
768
768
  *, tool: BaseTool, args: dict[str, Any], tool_context, error: Exception
@@ -1,8 +1,8 @@
1
1
  """
2
- Capability-based routing (Claude Code style conceptually).
2
+ Capability-based routing (style conceptually).
3
3
 
4
4
  This layer decides which *capabilities* to enable (deep research tools,
5
- embeddings retrieval, computer-use tools) and leaves the existing Claude-like
5
+ embeddings retrieval, computer-use tools) and leaves the existing familiar
6
6
  outer/inner loops intact.
7
7
 
8
8
  It is intentionally conservative:
gemcode/cli.py CHANGED
@@ -37,7 +37,7 @@ def _events_to_text(events) -> str:
37
37
 
38
38
  def _maybe_prompt_trust(cfg: GemCodeConfig) -> None:
39
39
  """
40
- Claude Code–style workspace trust prompt.
40
+ interactive CLI–style workspace trust prompt.
41
41
 
42
42
  On first use in a project root, ask the user to trust the folder so file,
43
43
  shell, and git tools can run. If not trusted, we exit before any tool runs.
@@ -70,7 +70,7 @@ def _maybe_prompt_trust(cfg: GemCodeConfig) -> None:
70
70
 
71
71
  def _maybe_prompt_google_api_key() -> None:
72
72
  """
73
- One-time interactive prompt for ``GOOGLE_API_KEY`` (like ``claude login`` / first-run).
73
+ One-time interactive prompt for ``GOOGLE_API_KEY`` (like ``gemcode login`` / first-run).
74
74
 
75
75
  Skipped when the key is already set, stdin is not a TTY, or
76
76
  ``GEMCODE_NO_LOGIN_PROMPT=1``.
@@ -125,7 +125,7 @@ def _initialize_gemcode_project(cfg: GemCodeConfig) -> None:
125
125
  Create ``<project>/.gemcode/`` and print a short banner the first time it appears.
126
126
 
127
127
  Runs after workspace trust + API key are satisfied so a bare ``gemcode`` REPL
128
- feels like a guided first-run (Claude Code–style).
128
+ feels like a guided first-run (interactive CLI–style).
129
129
  """
130
130
  root = cfg.project_root.resolve()
131
131
  gem_dir = root / ".gemcode"
@@ -174,7 +174,7 @@ async def _run_prompt(
174
174
 
175
175
  async def _run_repl(cfg: GemCodeConfig, session_id: str, *, use_mcp: bool) -> None:
176
176
  """
177
- Interactive REPL mode (Claude Code-like): keep the session open for multiple turns.
177
+ Interactive REPL mode (multi-turn REPL): keep the session open for multiple turns.
178
178
  """
179
179
  load_cli_environment()
180
180
  _maybe_prompt_trust(cfg)
@@ -356,7 +356,7 @@ def main() -> None:
356
356
  return
357
357
  raise SystemExit("Usage: gemcode ide --stdio")
358
358
 
359
- # Persist or rotate API key (Claude Code–style `claude login`).
359
+ # Persist or rotate API key (interactive CLI–style `gemcode login`).
360
360
  if len(sys.argv) > 1 and sys.argv[1] == "login":
361
361
  load_cli_environment()
362
362
  if not (hasattr(sys.stdin, "isatty") and sys.stdin.isatty()):
@@ -598,78 +598,78 @@ def main() -> None:
598
598
  print(f"\n[gemcode live-audio] session_id={session_id}", file=sys.stderr)
599
599
  return
600
600
 
601
- # Kairos proactive scheduler daemon.
602
- if len(sys.argv) > 1 and sys.argv[1] == "kairos":
603
- kairos_parser = argparse.ArgumentParser(
604
- prog="gemcode kairos",
605
- description="Kairos-like proactive scheduler daemon (stdin -> queued jobs).",
601
+ # Kaira proactive scheduler daemon.
602
+ if len(sys.argv) > 1 and sys.argv[1] == "kaira":
603
+ kaira_parser = argparse.ArgumentParser(
604
+ prog="gemcode kaira",
605
+ description="Background proactive scheduler daemon (stdin -> queued jobs).",
606
606
  )
607
- kairos_parser.add_argument(
607
+ kaira_parser.add_argument(
608
608
  "-C",
609
609
  "--directory",
610
610
  type=Path,
611
611
  default=Path.cwd(),
612
612
  help="Project root",
613
613
  )
614
- kairos_parser.add_argument(
614
+ kaira_parser.add_argument(
615
615
  "--session",
616
616
  default=None,
617
617
  help="Session id for SQLite-backed history (optional; defaults to a new uuid).",
618
618
  )
619
- kairos_parser.add_argument(
619
+ kaira_parser.add_argument(
620
620
  "--concurrency",
621
621
  type=int,
622
622
  default=2,
623
623
  help="Max number of concurrent queued jobs.",
624
624
  )
625
- kairos_parser.add_argument(
625
+ kaira_parser.add_argument(
626
626
  "--default-priority",
627
627
  type=int,
628
628
  default=0,
629
629
  help="Priority used for stdin-enqueued jobs.",
630
630
  )
631
- kairos_parser.add_argument(
631
+ kaira_parser.add_argument(
632
632
  "--yes",
633
633
  action="store_true",
634
634
  help="Allow write_file / search_replace (disables interactive HITL prompts).",
635
635
  )
636
- kairos_parser.add_argument(
636
+ kaira_parser.add_argument(
637
637
  "--interactive-ask",
638
638
  action="store_true",
639
639
  help="Prompt in-run for mutating tool confirmations (HITL).",
640
640
  )
641
- kairos_parser.add_argument("--model", default=None, help="Override GEMCODE_MODEL")
642
- kairos_parser.add_argument(
641
+ kaira_parser.add_argument("--model", default=None, help="Override GEMCODE_MODEL")
642
+ kaira_parser.add_argument(
643
643
  "--model-mode",
644
644
  default=None,
645
645
  help="Model mode: auto|fast|balanced|quality (overrides GEMCODE_MODEL_MODE).",
646
646
  )
647
- kairos_parser.add_argument(
647
+ kaira_parser.add_argument(
648
648
  "--deep-research",
649
649
  action="store_true",
650
650
  help="Enable deep research tools + routing.",
651
651
  )
652
- kairos_parser.add_argument(
652
+ kaira_parser.add_argument(
653
653
  "--maps-grounding",
654
654
  action="store_true",
655
655
  help="Opt-in to Google Maps grounding tool inside deep-research.",
656
656
  )
657
- kairos_parser.add_argument(
657
+ kaira_parser.add_argument(
658
658
  "--embeddings",
659
659
  action="store_true",
660
660
  help="Enable embeddings-based semantic retrieval.",
661
661
  )
662
- kairos_parser.add_argument(
662
+ kaira_parser.add_argument(
663
663
  "--capability-mode",
664
664
  default=None,
665
665
  help="Capability routing: auto|research|embeddings|computer|audio|all (enables tools and routes models).",
666
666
  )
667
- kairos_parser.add_argument(
667
+ kaira_parser.add_argument(
668
668
  "--tool-combination-mode",
669
669
  default=None,
670
670
  help="Gemini 3 tool context circulation: deep_research|always|never|auto",
671
671
  )
672
- kairos_parser.add_argument(
672
+ kaira_parser.add_argument(
673
673
  "--max-llm-calls",
674
674
  type=int,
675
675
  default=None,
@@ -677,7 +677,7 @@ def main() -> None:
677
677
  help="Cap model↔tool iterations for each job message (ADK RunConfig.max_llm_calls).",
678
678
  )
679
679
 
680
- args = kairos_parser.parse_args(sys.argv[2:])
680
+ args = kaira_parser.parse_args(sys.argv[2:])
681
681
  load_cli_environment()
682
682
 
683
683
  cfg = GemCodeConfig(project_root=args.directory)
@@ -713,15 +713,15 @@ def main() -> None:
713
713
  require_google_api_key()
714
714
 
715
715
  session_id = args.session or str(uuid.uuid4())
716
- from gemcode.kairos_daemon import KairosDaemon
716
+ from gemcode.kaira_daemon import KairaDaemon
717
717
 
718
- daemon = KairosDaemon(
718
+ daemon = KairaDaemon(
719
719
  cfg=cfg,
720
720
  concurrency=args.concurrency,
721
721
  default_priority=args.default_priority,
722
722
  )
723
723
  asyncio.run(daemon.run_forever(session_id=session_id))
724
- print(f"\n[gemcode kairos] session_id={session_id}", file=sys.stderr)
724
+ print(f"\n[gemcode kaira] session_id={session_id}", file=sys.stderr)
725
725
  return
726
726
 
727
727
  parser = argparse.ArgumentParser(prog="gemcode", description="Gemini + ADK coding agent")
gemcode/config.py CHANGED
@@ -49,7 +49,7 @@ def _truthy_env(name: str, *, default: bool = False) -> bool:
49
49
 
50
50
 
51
51
  def token_budget_invocation_reset() -> dict:
52
- """Reset per-user-message token budget tracker (matches new `query()` in Claude)."""
52
+ """Reset per-user-message token budget tracker when starting a new user turn."""
53
53
  import time
54
54
 
55
55
  t = int(time.time() * 1000)
@@ -285,9 +285,9 @@ class GemCodeConfig:
285
285
  # role-based routing from overriding their selection.
286
286
  model_overridden: bool = False
287
287
 
288
- # Gemini thinking controls (Claude-like intent, Gemini-specific knobs).
288
+ # Gemini thinking controls (familiar intent, Gemini-specific knobs).
289
289
  #
290
- # Claude Code enables thinking by default and only forces disable/budgets
290
+ # enables thinking by default and only forces disable/budgets
291
291
  # when explicitly configured. We match that by returning "None" unless the
292
292
  # user asks for explicit overrides below.
293
293
  #
@@ -333,7 +333,7 @@ class GemCodeConfig:
333
333
 
334
334
  # Plan mode: when ON, the agent explicitly writes out a numbered plan
335
335
  # BEFORE executing any tools, then checks the plan before reporting done.
336
- # Like OpenClaude's EnterPlanMode — great for complex, multi-file tasks.
336
+ # Like Reference UI EnterPlanMode — great for complex, multi-file tasks.
337
337
  # Toggle at runtime with /plan on|off.
338
338
  plan_mode: bool = field(
339
339
  default_factory=lambda: _truthy_env("GEMCODE_PLAN_MODE", default=False)
gemcode/context_budget.py CHANGED
@@ -1,5 +1,5 @@
1
1
  """
2
- Bounded tool output and soft prompt-size limits (Claude Code–style context hygiene).
2
+ Bounded tool output and soft prompt-size limits (interactive CLI–style context hygiene).
3
3
 
4
4
  - Truncate oversized tool result dicts before they enter history (`after_tool`).
5
5
  - Before each LLM call, trim oldest text parts until estimated char total is under
@@ -169,7 +169,7 @@ def shrink_contents_text_inplace(contents: Any, max_total_chars: int) -> bool:
169
169
  # Choose a max string size that should reduce at least some of the excess.
170
170
  if excess >= max_len:
171
171
  # Extreme overage: clearing oldest tool payload is closer to
172
- # Claude Code's microcompact behavior and guarantees progress.
172
+ # microcompact behavior and guarantees progress.
173
173
  cleared = {"[Old tool result content cleared]": True}
174
174
  if getattr(part, "tool_response", None) is not None:
175
175
  part.tool_response.response = cleared
@@ -1,8 +1,8 @@
1
1
  """
2
- Claude Code–style context pressure signals (cf. `autoCompact.ts` / `calculateTokenWarningState`).
2
+ Context pressure signals for autocompact and warnings (token-based thresholds).
3
3
 
4
4
  Uses API `prompt_token_count` when available; thresholds are token-based with
5
- env overrides. Mirrors Claude’s buffer constants where practical.
5
+ env overrides. Mirrors common buffer constants where practical.
6
6
  """
7
7
 
8
8
  from __future__ import annotations
@@ -11,7 +11,7 @@ import os
11
11
 
12
12
  from gemcode.config import GemCodeConfig
13
13
 
14
- # Claude `autoCompact.ts` defaults
14
+ # Reference auto-compact defaults
15
15
  AUTOCOMPACT_BUFFER_TOKENS = 13_000
16
16
  WARNING_THRESHOLD_BUFFER_TOKENS = 20_000
17
17
  ERROR_THRESHOLD_BUFFER_TOKENS = 20_000
@@ -40,12 +40,12 @@ def get_effective_context_window_tokens(model: str) -> int:
40
40
 
41
41
 
42
42
  def get_reserved_summary_tokens(model: str) -> int:
43
- """Claude reserves headroom for compaction summary output; we use a small cap."""
43
+ """Reserve headroom for compaction summary output; we use a small cap."""
44
44
  return min(_opt_int("GEMCODE_AUTOCOMPACT_RESERVED_OUTPUT_TOKENS", 20_000), 20_000)
45
45
 
46
46
 
47
47
  def get_effective_context_window_size_tokens(model: str) -> int:
48
- """`effectiveContextWindow` ≈ window minus reserved output (Claude `getEffectiveContextWindowSize`)."""
48
+ """`effectiveContextWindow` ≈ window minus reserved output for summaries."""
49
49
  w = get_effective_context_window_tokens(model)
50
50
  return max(10_000, w - get_reserved_summary_tokens(model))
51
51
 
@@ -70,7 +70,7 @@ def calculate_context_warning_state(
70
70
  cfg: GemCodeConfig | None = None,
71
71
  ) -> dict[str, object]:
72
72
  """
73
- Returns keys aligned with Claude’s `calculateTokenWarningState`:
73
+ Returns keys aligned with typical token-warning state helpers:
74
74
  - percent_left
75
75
  - is_above_warning_threshold
76
76
  - is_above_error_threshold
gemcode/credentials.py CHANGED
@@ -1,4 +1,4 @@
1
- """Persisted Google API credentials (Claude Code–style: save once, override via env)."""
1
+ """Persisted Google API credentials (interactive CLI–style: save once, override via env)."""
2
2
 
3
3
  from __future__ import annotations
4
4
 
gemcode/hooks.py CHANGED
@@ -1,5 +1,5 @@
1
1
  """
2
- GemCode shell hooks — scriptable lifecycle events inspired by OpenClaude.
2
+ GemCode shell hooks — scriptable lifecycle events inspired by reference terminal UI.
3
3
 
4
4
  Hooks are shell scripts stored under ``<project_root>/.gemcode/hooks/``.
5
5
  They receive a JSON payload on stdin and can:
gemcode/invoke.py CHANGED
@@ -1,5 +1,5 @@
1
1
  """
2
- Single user turn (Claude Code: inner path ≈ `query()` invocation per message).
2
+ Single user turn (inner path ≈ `query()` invocation per message).
3
3
 
4
4
  CLI and tests call `run_turn` with a Runner already bound to app + session service.
5
5
  """
@@ -30,15 +30,15 @@ def _events_to_text(events) -> str:
30
30
 
31
31
 
32
32
  @dataclass(frozen=True)
33
- class KairosJob:
33
+ class KairaJob:
34
34
  job_id: str
35
35
  prompt: str
36
36
  priority: int
37
37
  session_id: str
38
38
 
39
39
 
40
- class KairosDaemon:
41
- """Kairos-like proactive scheduler (stdin -> priority queue -> job runners)."""
40
+ class KairaDaemon:
41
+ """Background proactive scheduler (stdin -> priority queue -> job runners)."""
42
42
 
43
43
  def __init__(
44
44
  self,
@@ -47,16 +47,16 @@ class KairosDaemon:
47
47
  concurrency: int = 2,
48
48
  default_priority: int = 0,
49
49
  user_id: str = "local",
50
- job_runner: Callable[[KairosJob], Awaitable[None]] | None = None,
50
+ job_runner: Callable[[KairaJob], Awaitable[None]] | None = None,
51
51
  ) -> None:
52
52
  self.cfg = cfg
53
53
  self.concurrency = max(1, int(concurrency))
54
54
  self.default_priority = int(default_priority)
55
55
  self.user_id = user_id
56
56
 
57
- # Queue items are (sort_key, seq, KairosJob).
57
+ # Queue items are (sort_key, seq, KairaJob).
58
58
  self._queue: asyncio.PriorityQueue[
59
- tuple[int, int, KairosJob]
59
+ tuple[int, int, KairaJob]
60
60
  ] = asyncio.PriorityQueue()
61
61
  self._seq = 0
62
62
  self._sem = asyncio.Semaphore(self.concurrency)
@@ -75,7 +75,7 @@ class KairosDaemon:
75
75
  job_id = f"job_{uuid.uuid4().hex[:10]}"
76
76
  pr = self.default_priority if priority is None else int(priority)
77
77
  self._seq += 1
78
- job = KairosJob(
78
+ job = KairaJob(
79
79
  job_id=job_id,
80
80
  prompt=prompt,
81
81
  priority=pr,
@@ -85,7 +85,7 @@ class KairosDaemon:
85
85
  self._queue.put_nowait((-pr, self._seq, job))
86
86
  return job_id
87
87
 
88
- async def _default_job_runner(self, job: KairosJob) -> None:
88
+ async def _default_job_runner(self, job: KairaJob) -> None:
89
89
  runner: Runner | None = None
90
90
  try:
91
91
  # Route model/capabilities based on this job's prompt, without mutating
@@ -94,7 +94,7 @@ class KairosDaemon:
94
94
  apply_capability_routing(job_cfg, job.prompt, context="prompt")
95
95
  job_cfg.model = pick_effective_model(job_cfg, job.prompt)
96
96
 
97
- # For the initial MVP, we inject Kairos tools via `_build_extra_tools_for_job()`;
97
+ # For the initial MVP, we inject Kaira tools via `_build_extra_tools_for_job()`;
98
98
  # this keeps scheduling logic independent from tool declarations.
99
99
  extra_tools = self._build_extra_tools_for_job(job)
100
100
  runner = create_runner(job_cfg, extra_tools=extra_tools or None)
@@ -108,28 +108,28 @@ class KairosDaemon:
108
108
  )
109
109
  text = _events_to_text(events).strip()
110
110
  if text:
111
- print(f"\n[kairos {job.job_id}] {text}\n", flush=True)
111
+ print(f"\n[kaira {job.job_id}] {text}\n", flush=True)
112
112
  else:
113
- print(f"\n[kairos {job.job_id}] (no text output)\n", flush=True)
113
+ print(f"\n[kaira {job.job_id}] (no text output)\n", flush=True)
114
114
  finally:
115
115
  if runner is not None:
116
116
  await runner.close()
117
117
 
118
- def _build_extra_tools_for_job(self, job: KairosJob) -> list | None:
118
+ def _build_extra_tools_for_job(self, job: KairaJob) -> list | None:
119
119
  """Inject per-job tools for the model to call."""
120
120
 
121
- async def kairos_sleep_ms(duration_ms: int) -> dict:
121
+ async def kaira_sleep_ms(duration_ms: int) -> dict:
122
122
  """Pause this job for `duration_ms` (does not block other jobs)."""
123
123
  duration_ms = max(0, int(duration_ms))
124
124
  await asyncio.sleep(duration_ms / 1000.0)
125
125
  return {"slept_ms": duration_ms}
126
126
 
127
- def kairos_enqueue_prompt(
127
+ def kaira_enqueue_prompt(
128
128
  prompt: str,
129
129
  priority: int = 0,
130
130
  session_id: str | None = None,
131
131
  ) -> dict:
132
- """Enqueue a new Kairos job from the model.
132
+ """Enqueue a new Kaira job from the model.
133
133
 
134
134
  If `session_id` is not provided, it defaults to the current job's
135
135
  session_id.
@@ -142,13 +142,13 @@ class KairosDaemon:
142
142
  )
143
143
  return {"enqueued_job_id": enqueued_id}
144
144
 
145
- return [kairos_sleep_ms, kairos_enqueue_prompt]
145
+ return [kaira_sleep_ms, kaira_enqueue_prompt]
146
146
 
147
- async def _run_job_with_semaphore(self, job: KairosJob) -> None:
147
+ async def _run_job_with_semaphore(self, job: KairaJob) -> None:
148
148
  async with self._sem:
149
149
  await self._job_runner(job)
150
150
 
151
- async def _run_job_and_release(self, job: KairosJob) -> None:
151
+ async def _run_job_and_release(self, job: KairaJob) -> None:
152
152
  try:
153
153
  await self._job_runner(job)
154
154
  finally:
@@ -166,7 +166,7 @@ class KairosDaemon:
166
166
  async def _stdin_loop(self, *, session_id: str) -> None:
167
167
  """Read stdin lines and enqueue each as a new job."""
168
168
  # Use a background thread so the asyncio loop stays responsive.
169
- prompt_prefix = "kairos> "
169
+ prompt_prefix = "kaira> "
170
170
  while not self._stop_event.is_set():
171
171
  try:
172
172
  # Print prompt only in interactive terminals.
gemcode/limits.py CHANGED
@@ -1,5 +1,5 @@
1
1
  """
2
- Pre-model limits (cf. Claude `calculateTokenWarningState` / blocking limit checks).
2
+ Pre-model limits (token warning state / blocking limit checks).
3
3
 
4
4
  Uses session state updated in `callbacks.make_after_model_callback`.
5
5
  """
gemcode/mcp_loader.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """
2
2
  Optional MCP toolsets from `.gemcode/mcp.json`.
3
3
 
4
- Now supports all three ADK connection types — like Claude Code's MCP integration:
4
+ Now supports all three ADK connection types — like MCP integration:
5
5
 
6
6
  Schema (example):
7
7
  {
gemcode/modality_tools.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """
2
2
  Modality tool injection for GemCode.
3
3
 
4
- Claude Code–style: outer loop + inner tool orchestration remains ADK-driven,
4
+ interactive CLI–style: outer loop + inner tool orchestration remains ADK-driven,
5
5
  but we choose which tools to expose based on user flags / prompt heuristics.
6
6
  """
7
7
 
gemcode/model_routing.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """
2
2
  Model routing for GemCode.
3
3
 
4
- Goal: match Claude-style "multi modes" where users can select a model mode
4
+ Goal: match conventional "multi modes" where users can select a model mode
5
5
  explicitly, or GemCode can choose a best-fit model automatically (no extra
6
6
  model call; heuristic only).
7
7
  """
gemcode/permissions.py CHANGED
@@ -1,5 +1,5 @@
1
1
  """
2
- Permission rules engine — inspired by Claude Code's allow/deny pattern system.
2
+ Permission rules engine — inspired by allow/deny pattern system.
3
3
 
4
4
  Users define rules in `.gemcode/settings.json` (project) or `~/.gemcode/settings.json` (global).
5
5
  Rules are evaluated for every tool call: deny first, then allow, then default.
@@ -25,7 +25,7 @@ Schema:
25
25
  }
26
26
  }
27
27
 
28
- Pattern syntax (same as Claude Code's permission rules):
28
+ Pattern syntax (same as permission rules):
29
29
  - "bash" — matches ALL bash calls
30
30
  - "bash(*)" — same as above
31
31
  - "bash(git *)" — bash calls whose command starts with "git "
@@ -1,5 +1,5 @@
1
1
  """
2
- ADK plugin: complements Claude-like stopHooks with GemCode terminal reasons,
2
+ ADK plugin: complements familiar stopHooks with GemCode terminal reasons,
3
3
  optional memory ingestion, and post-turn hook execution.
4
4
  """
5
5