gemcode 0.3.53__tar.gz → 0.3.54__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.53/src/gemcode.egg-info → gemcode-0.3.54}/PKG-INFO +1 -1
- {gemcode-0.3.53 → gemcode-0.3.54}/pyproject.toml +1 -1
- gemcode-0.3.54/src/gemcode/tui/welcome_banner.py +127 -0
- {gemcode-0.3.53 → gemcode-0.3.54/src/gemcode.egg-info}/PKG-INFO +1 -1
- gemcode-0.3.53/src/gemcode/tui/welcome_banner.py +0 -137
- {gemcode-0.3.53 → gemcode-0.3.54}/LICENSE +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/MANIFEST.in +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/README.md +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/setup.cfg +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/__init__.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/__main__.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/agent.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/audit.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/autocompact.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/callbacks.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/capability_routing.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/cli.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/compaction.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/computer_use/__init__.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/computer_use/browser_computer.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/config.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/context_budget.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/context_warning.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/credentials.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/hitl_session.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/hooks.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/intent_classifier.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/interactions.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/invoke.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/kairos_daemon.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/limits.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/live_audio_engine.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/logging_config.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/mcp_loader.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/memory/__init__.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/memory/embedding_memory_service.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/memory/file_memory_service.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/modality_tools.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/model_errors.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/model_routing.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/openapi_loader.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/paths.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/permissions.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/plugins/__init__.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/plugins/terminal_hooks_plugin.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/plugins/tool_recovery_plugin.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/pricing.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/prompt_suggestions.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/query/__init__.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/query/config.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/query/deps.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/query/engine.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/query/stop_hooks.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/query/token_budget.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/query/transitions.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/refine.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/repl_commands.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/repl_slash.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/review_agent.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/session_runtime.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/session_store.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/slash_commands.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/thinking.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/tool_prompt_manifest.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/tool_registry.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/tools/__init__.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/tools/bash.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/tools/browser.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/tools/edit.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/tools/filesystem.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/tools/notes.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/tools/search.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/tools/shell.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/tools/shell_gate.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/tools/subtask.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/tools/think.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/tools/todo.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/tools/web.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/tools_inspector.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/trust.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/tui/input_handler.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/tui/scrollback.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/tui/spinner.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/tui/welcome_rich.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/version.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/vertex.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/web/__init__.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/web/claude_sse_adapter.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/web/terminal_repl.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode/workspace_hints.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode.egg-info/SOURCES.txt +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode.egg-info/dependency_links.txt +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode.egg-info/entry_points.txt +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode.egg-info/requires.txt +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/src/gemcode.egg-info/top_level.txt +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/tests/test_agent_instruction.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/tests/test_autocompact.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/tests/test_capability_routing.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/tests/test_claude_web_adapter_sse.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/tests/test_cli_init.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/tests/test_computer_use_permissions.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/tests/test_context_budget.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/tests/test_context_warning.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/tests/test_credentials.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/tests/test_interactive_permission_ask.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/tests/test_kairos_scheduler.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/tests/test_modality_tools.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/tests/test_model_error_retry.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/tests/test_model_errors.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/tests/test_model_routing.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/tests/test_paths.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/tests/test_permissions.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/tests/test_prompt_suggestions.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/tests/test_repl_commands.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/tests/test_repl_slash.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/tests/test_slash_commands.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/tests/test_thinking_config.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/tests/test_token_budget.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/tests/test_tool_context_circulation.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/tests/test_tools.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/tests/test_tools_inspector.py +0 -0
- {gemcode-0.3.53 → gemcode-0.3.54}/tests/test_workspace_hints.py +0 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"""ASCII welcome banner + provider box (scrollback + full-screen TUI)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from gemcode.version import get_version
|
|
9
|
+
from gemcode.vertex import vertex_env_active
|
|
10
|
+
from gemcode.workspace_hints import narrow_workspace_tip
|
|
11
|
+
|
|
12
|
+
_GEM_LINES = (
|
|
13
|
+
r" ██████╗ ███████╗███╗ ███╗",
|
|
14
|
+
r" ██╔════╝ ██╔════╝████╗ ████║",
|
|
15
|
+
r" ██║ ███╗█████╗ ██╔████╔██║",
|
|
16
|
+
r" ██║ ██║██╔══╝ ██║╚██╔╝██║",
|
|
17
|
+
r" ╚██████╔╝███████╗██║ ╚═╝ ██║",
|
|
18
|
+
r" ╚═════╝ ╚══════╝╚═╝ ╚═╝",
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
_CODE_LINES = (
|
|
22
|
+
r" ██████╗ ██████╗ ██████╗ ███████╗",
|
|
23
|
+
r" ██╔════╝██╔═══██╗██╔══██╗██╔════╝",
|
|
24
|
+
r" ██║ ██║ ██║██║ ██║█████╗ ",
|
|
25
|
+
r" ██║ ██║ ██║██║ ██║██╔══╝ ",
|
|
26
|
+
r" ╚██████╗╚██████╔╝██████╔╝███████╗",
|
|
27
|
+
r" ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝",
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
_TAGLINE = "✦ Gemini-powered coding agent. Fast. Capable. Local. ✦"
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _banner_width() -> int:
|
|
34
|
+
return max(len(x) for x in _GEM_LINES + _CODE_LINES)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _center(line: str, width: int) -> str:
|
|
38
|
+
if len(line) >= width:
|
|
39
|
+
return line
|
|
40
|
+
pad = width - len(line)
|
|
41
|
+
left = pad // 2
|
|
42
|
+
return " " * left + line + " " * (pad - left)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _provider_model_endpoint(cfg) -> tuple[str, str, str]:
|
|
46
|
+
model = (getattr(cfg, "model", None) or "").strip() or "gemini-2.5-flash"
|
|
47
|
+
if vertex_env_active():
|
|
48
|
+
provider = "Vertex AI"
|
|
49
|
+
loc = (os.environ.get("GOOGLE_CLOUD_LOCATION") or "us-central1").strip()
|
|
50
|
+
proj = (os.environ.get("GOOGLE_CLOUD_PROJECT") or "").strip()
|
|
51
|
+
end = f"vertex://{loc}"
|
|
52
|
+
if proj:
|
|
53
|
+
end = f"{end} · {proj}"
|
|
54
|
+
else:
|
|
55
|
+
provider = "Google Gemini"
|
|
56
|
+
end = "https://generativelanguage.googleapis.com/"
|
|
57
|
+
return provider, model, end
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _kv_line(inner: int, label: str, value: str) -> str:
|
|
61
|
+
"""One row inside the box: leading space + label column + value (total width ``inner``)."""
|
|
62
|
+
lead = " "
|
|
63
|
+
prefix = f"{label:<10}"
|
|
64
|
+
room = inner - len(lead) - len(prefix)
|
|
65
|
+
if room < 4:
|
|
66
|
+
raw = (lead + prefix + value)[:inner]
|
|
67
|
+
return raw.ljust(inner)
|
|
68
|
+
v = value
|
|
69
|
+
if len(v) > room:
|
|
70
|
+
v = v[: max(0, room - 3)] + "..."
|
|
71
|
+
return (lead + prefix + v).ljust(inner)[:inner]
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def format_welcome_banner(cfg, *, term_width: int = 100) -> str:
|
|
75
|
+
inner = min(60, max(48, term_width - 4))
|
|
76
|
+
top = "╔" + ("═" * inner) + "╗"
|
|
77
|
+
mid = "╠" + ("═" * inner) + "╣"
|
|
78
|
+
bot = "╚" + ("═" * inner) + "╝"
|
|
79
|
+
|
|
80
|
+
provider, model, endpoint = _provider_model_endpoint(cfg)
|
|
81
|
+
row_p = _kv_line(inner, "Provider", provider)
|
|
82
|
+
row_m = _kv_line(inner, "Model", model)
|
|
83
|
+
row_e = _kv_line(inner, "Endpoint", endpoint)
|
|
84
|
+
|
|
85
|
+
mode = "vertex" if vertex_env_active() else "cloud"
|
|
86
|
+
status_raw = f" ● {mode} Ready — type /help to begin"
|
|
87
|
+
if len(status_raw) > inner:
|
|
88
|
+
status_raw = status_raw[: max(0, inner - 3)] + "..."
|
|
89
|
+
row_s = status_raw.ljust(inner)[:inner]
|
|
90
|
+
|
|
91
|
+
bw = max(_banner_width(), inner + 2)
|
|
92
|
+
lines: list[str] = []
|
|
93
|
+
for row in _GEM_LINES:
|
|
94
|
+
lines.append(_center(row, bw))
|
|
95
|
+
lines.append("")
|
|
96
|
+
for row in _CODE_LINES:
|
|
97
|
+
lines.append(_center(row, bw))
|
|
98
|
+
lines.append("")
|
|
99
|
+
lines.append(_center(f" {_TAGLINE} ", bw))
|
|
100
|
+
lines.append("")
|
|
101
|
+
|
|
102
|
+
box_w = inner + 2
|
|
103
|
+
pad_b = max(0, (bw - box_w) // 2)
|
|
104
|
+
bp = " " * pad_b
|
|
105
|
+
|
|
106
|
+
def box_row(body: str) -> str:
|
|
107
|
+
b = body[:inner].ljust(inner)
|
|
108
|
+
return bp + "│" + b + "│"
|
|
109
|
+
|
|
110
|
+
lines.append(bp + top)
|
|
111
|
+
lines.append(box_row(row_p))
|
|
112
|
+
lines.append(box_row(row_m))
|
|
113
|
+
lines.append(box_row(row_e))
|
|
114
|
+
lines.append(bp + mid)
|
|
115
|
+
lines.append(box_row(row_s))
|
|
116
|
+
lines.append(bp + bot)
|
|
117
|
+
|
|
118
|
+
ver = os.environ.get("GEMCODE_VERSION", get_version())
|
|
119
|
+
lines.append(_center(f" gemcode v{ver} ", bw))
|
|
120
|
+
|
|
121
|
+
root = getattr(cfg, "project_root", None)
|
|
122
|
+
if isinstance(root, Path):
|
|
123
|
+
nt = narrow_workspace_tip(root)
|
|
124
|
+
if nt:
|
|
125
|
+
lines.append(_center(nt, bw))
|
|
126
|
+
lines.append("")
|
|
127
|
+
return "\n".join(lines)
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
"""ASCII welcome banner + provider box (scrollback + full-screen TUI)."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
import os
|
|
6
|
-
from pathlib import Path
|
|
7
|
-
|
|
8
|
-
from gemcode.version import get_version
|
|
9
|
-
from gemcode.vertex import vertex_env_active
|
|
10
|
-
from gemcode.workspace_hints import narrow_workspace_tip
|
|
11
|
-
|
|
12
|
-
_GEM_LINES = (
|
|
13
|
-
r"██████╗ ███████╗███╗ ███╗",
|
|
14
|
-
r"██╔════╝ ██╔════╝████╗ ████║",
|
|
15
|
-
r"██║ ███╗█████╗ ██╔████╔██║",
|
|
16
|
-
r"██║ ██║██╔══╝ ██║╚██╔╝██║",
|
|
17
|
-
r"╚██████╔╝███████╗██║ ╚═╝ ██║",
|
|
18
|
-
r" ╚═════╝ ╚══════╝╚═╝ ╚═╝",
|
|
19
|
-
)
|
|
20
|
-
|
|
21
|
-
_CODE_LINES = (
|
|
22
|
-
r"██████╗ ██████╗ ██████╗ ███████╗",
|
|
23
|
-
r"██╔════╝██╔═══██╗██╔══██╗██╔════╝",
|
|
24
|
-
r"██║ ██║ ██║██║ ██║█████╗ ",
|
|
25
|
-
r"██║ ██║ ██║██║ ██║██╔══╝ ",
|
|
26
|
-
r"╚██████╗╚██████╔╝██████╔╝███████╗",
|
|
27
|
-
r" ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝",
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
_TAGLINE = "✦ Gemini-powered coding agent. Fast. Capable. Local. ✦"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
def _banner_width() -> int:
|
|
34
|
-
return max(len(x) for x in _GEM_LINES + _CODE_LINES)
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
def _center(line: str, width: int) -> str:
|
|
38
|
-
if len(line) >= width:
|
|
39
|
-
return line
|
|
40
|
-
pad = width - len(line)
|
|
41
|
-
left = pad // 2
|
|
42
|
-
return " " * left + line + " " * (pad - left)
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
def _provider_model_endpoint(cfg) -> tuple[str, str, str]:
|
|
46
|
-
model = (getattr(cfg, "model", None) or "").strip() or "gemini-2.5-flash"
|
|
47
|
-
if vertex_env_active():
|
|
48
|
-
provider = "Vertex AI"
|
|
49
|
-
loc = (os.environ.get("GOOGLE_CLOUD_LOCATION") or "us-central1").strip()
|
|
50
|
-
proj = (os.environ.get("GOOGLE_CLOUD_PROJECT") or "").strip()
|
|
51
|
-
end = f"vertex://{loc}"
|
|
52
|
-
if proj:
|
|
53
|
-
end = f"{end} · {proj}"
|
|
54
|
-
else:
|
|
55
|
-
provider = "Google Gemini"
|
|
56
|
-
end = "https://generativelanguage.googleapis.com/"
|
|
57
|
-
return provider, model, end
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
def _kv_line(inner: int, label: str, value: str) -> str:
|
|
61
|
-
"""One row inside the box: leading space + label column + value (total width ``inner``)."""
|
|
62
|
-
lead = " "
|
|
63
|
-
prefix = f"{label:<10}"
|
|
64
|
-
room = inner - len(lead) - len(prefix)
|
|
65
|
-
if room < 4:
|
|
66
|
-
raw = (lead + prefix + value)[:inner]
|
|
67
|
-
return raw.ljust(inner)
|
|
68
|
-
v = value
|
|
69
|
-
if len(v) > room:
|
|
70
|
-
v = v[: max(0, room - 3)] + "..."
|
|
71
|
-
return (lead + prefix + v).ljust(inner)[:inner]
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
def format_welcome_banner(cfg, *, term_width: int = 100) -> str:
|
|
75
|
-
provider, model, endpoint = _provider_model_endpoint(cfg)
|
|
76
|
-
# Banner style: "solid" removes the boxed provider block and blank spacer
|
|
77
|
-
# lines for a single rigid header (OpenClaude-like).
|
|
78
|
-
style = (os.environ.get("GEMCODE_TUI_BANNER_STYLE", "solid") or "solid").strip().lower()
|
|
79
|
-
|
|
80
|
-
bw = max(_banner_width(), min(80, max(48, term_width)))
|
|
81
|
-
lines: list[str] = []
|
|
82
|
-
for row in _GEM_LINES:
|
|
83
|
-
lines.append(_center(row, bw))
|
|
84
|
-
for row in _CODE_LINES:
|
|
85
|
-
lines.append(_center(row, bw))
|
|
86
|
-
lines.append(_center(_TAGLINE, bw))
|
|
87
|
-
|
|
88
|
-
if style not in ("solid", "rigid", "compact"):
|
|
89
|
-
# Backward-compat: unknown values fall back to the old boxed layout.
|
|
90
|
-
style = "boxed"
|
|
91
|
-
|
|
92
|
-
if style == "boxed":
|
|
93
|
-
inner = min(60, max(48, term_width - 4))
|
|
94
|
-
top = "╔" + ("═" * inner) + "╗"
|
|
95
|
-
mid = "╠" + ("═" * inner) + "╣"
|
|
96
|
-
bot = "╚" + ("═" * inner) + "╝"
|
|
97
|
-
|
|
98
|
-
row_p = _kv_line(inner, "Provider", provider)
|
|
99
|
-
row_m = _kv_line(inner, "Model", model)
|
|
100
|
-
row_e = _kv_line(inner, "Endpoint", endpoint)
|
|
101
|
-
|
|
102
|
-
mode = "vertex" if vertex_env_active() else "cloud"
|
|
103
|
-
status_raw = f" ● {mode} Ready — type /help to begin"
|
|
104
|
-
if len(status_raw) > inner:
|
|
105
|
-
status_raw = status_raw[: max(0, inner - 3)] + "..."
|
|
106
|
-
row_s = status_raw.ljust(inner)[:inner]
|
|
107
|
-
|
|
108
|
-
box_w = inner + 2
|
|
109
|
-
pad_b = max(0, (bw - box_w) // 2)
|
|
110
|
-
bp = " " * pad_b
|
|
111
|
-
|
|
112
|
-
def box_row(body: str) -> str:
|
|
113
|
-
b = body[:inner].ljust(inner)
|
|
114
|
-
return bp + "│" + b + "│"
|
|
115
|
-
|
|
116
|
-
lines.append(bp + top)
|
|
117
|
-
lines.append(box_row(row_p))
|
|
118
|
-
lines.append(box_row(row_m))
|
|
119
|
-
lines.append(box_row(row_e))
|
|
120
|
-
lines.append(bp + mid)
|
|
121
|
-
lines.append(box_row(row_s))
|
|
122
|
-
lines.append(bp + bot)
|
|
123
|
-
else:
|
|
124
|
-
# Solid header: one rigid info line, no extra blocks.
|
|
125
|
-
mode = "vertex" if vertex_env_active() else "cloud"
|
|
126
|
-
info = f"{provider} · {model} · {endpoint} · {mode} ready — type /help"
|
|
127
|
-
lines.append(_center(info, bw))
|
|
128
|
-
|
|
129
|
-
ver = os.environ.get("GEMCODE_VERSION", get_version())
|
|
130
|
-
lines.append(_center(f"gemcode v{ver}", bw))
|
|
131
|
-
|
|
132
|
-
root = getattr(cfg, "project_root", None)
|
|
133
|
-
if isinstance(root, Path):
|
|
134
|
-
nt = narrow_workspace_tip(root)
|
|
135
|
-
if nt:
|
|
136
|
-
lines.append(_center(nt, bw))
|
|
137
|
-
return "\n".join(lines)
|
|
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
|