klaude-code 1.2.6__py3-none-any.whl → 1.8.0__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.
- klaude_code/auth/__init__.py +24 -0
- klaude_code/auth/codex/__init__.py +20 -0
- klaude_code/auth/codex/exceptions.py +17 -0
- klaude_code/auth/codex/jwt_utils.py +45 -0
- klaude_code/auth/codex/oauth.py +229 -0
- klaude_code/auth/codex/token_manager.py +84 -0
- klaude_code/cli/auth_cmd.py +73 -0
- klaude_code/cli/config_cmd.py +91 -0
- klaude_code/cli/cost_cmd.py +338 -0
- klaude_code/cli/debug.py +78 -0
- klaude_code/cli/list_model.py +307 -0
- klaude_code/cli/main.py +233 -134
- klaude_code/cli/runtime.py +309 -117
- klaude_code/{version.py → cli/self_update.py} +114 -5
- klaude_code/cli/session_cmd.py +37 -21
- klaude_code/command/__init__.py +88 -27
- klaude_code/command/clear_cmd.py +8 -7
- klaude_code/command/command_abc.py +31 -31
- klaude_code/command/debug_cmd.py +79 -0
- klaude_code/command/export_cmd.py +19 -53
- klaude_code/command/export_online_cmd.py +154 -0
- klaude_code/command/fork_session_cmd.py +267 -0
- klaude_code/command/help_cmd.py +7 -8
- klaude_code/command/model_cmd.py +60 -10
- klaude_code/command/model_select.py +84 -0
- klaude_code/command/prompt-jj-describe.md +32 -0
- klaude_code/command/prompt_command.py +19 -11
- klaude_code/command/refresh_cmd.py +8 -10
- klaude_code/command/registry.py +139 -40
- klaude_code/command/release_notes_cmd.py +84 -0
- klaude_code/command/resume_cmd.py +111 -0
- klaude_code/command/status_cmd.py +104 -60
- klaude_code/command/terminal_setup_cmd.py +7 -9
- klaude_code/command/thinking_cmd.py +98 -0
- klaude_code/config/__init__.py +14 -6
- klaude_code/config/assets/__init__.py +1 -0
- klaude_code/config/assets/builtin_config.yaml +303 -0
- klaude_code/config/builtin_config.py +38 -0
- klaude_code/config/config.py +378 -109
- klaude_code/config/select_model.py +117 -53
- klaude_code/config/thinking.py +269 -0
- klaude_code/{const/__init__.py → const.py} +50 -19
- klaude_code/core/agent.py +20 -28
- klaude_code/core/executor.py +327 -112
- klaude_code/core/manager/__init__.py +2 -4
- klaude_code/core/manager/llm_clients.py +1 -15
- klaude_code/core/manager/llm_clients_builder.py +10 -11
- klaude_code/core/manager/sub_agent_manager.py +37 -6
- klaude_code/core/prompt.py +63 -44
- klaude_code/core/prompts/prompt-claude-code.md +2 -13
- klaude_code/core/prompts/prompt-codex-gpt-5-1-codex-max.md +117 -0
- klaude_code/core/prompts/prompt-codex-gpt-5-2-codex.md +117 -0
- klaude_code/core/prompts/prompt-codex.md +9 -42
- klaude_code/core/prompts/prompt-minimal.md +12 -0
- klaude_code/core/prompts/{prompt-subagent-explore.md → prompt-sub-agent-explore.md} +16 -3
- klaude_code/core/prompts/{prompt-subagent-oracle.md → prompt-sub-agent-oracle.md} +1 -2
- klaude_code/core/prompts/prompt-sub-agent-web.md +51 -0
- klaude_code/core/reminders.py +283 -95
- klaude_code/core/task.py +113 -75
- klaude_code/core/tool/__init__.py +24 -31
- klaude_code/core/tool/file/_utils.py +36 -0
- klaude_code/core/tool/file/apply_patch.py +17 -25
- klaude_code/core/tool/file/apply_patch_tool.py +57 -77
- klaude_code/core/tool/file/diff_builder.py +151 -0
- klaude_code/core/tool/file/edit_tool.py +50 -63
- klaude_code/core/tool/file/move_tool.md +41 -0
- klaude_code/core/tool/file/move_tool.py +435 -0
- klaude_code/core/tool/file/read_tool.md +1 -1
- klaude_code/core/tool/file/read_tool.py +86 -86
- klaude_code/core/tool/file/write_tool.py +59 -69
- klaude_code/core/tool/report_back_tool.py +84 -0
- klaude_code/core/tool/shell/bash_tool.py +265 -22
- klaude_code/core/tool/shell/command_safety.py +3 -6
- klaude_code/core/tool/{memory → skill}/skill_tool.py +16 -26
- klaude_code/core/tool/sub_agent_tool.py +13 -2
- klaude_code/core/tool/todo/todo_write_tool.md +0 -157
- klaude_code/core/tool/todo/todo_write_tool.py +1 -1
- klaude_code/core/tool/todo/todo_write_tool_raw.md +182 -0
- klaude_code/core/tool/todo/update_plan_tool.py +1 -1
- klaude_code/core/tool/tool_abc.py +18 -0
- klaude_code/core/tool/tool_context.py +27 -12
- klaude_code/core/tool/tool_registry.py +7 -7
- klaude_code/core/tool/tool_runner.py +44 -36
- klaude_code/core/tool/truncation.py +29 -14
- klaude_code/core/tool/web/mermaid_tool.md +43 -0
- klaude_code/core/tool/web/mermaid_tool.py +2 -5
- klaude_code/core/tool/web/web_fetch_tool.md +1 -1
- klaude_code/core/tool/web/web_fetch_tool.py +112 -22
- klaude_code/core/tool/web/web_search_tool.md +23 -0
- klaude_code/core/tool/web/web_search_tool.py +130 -0
- klaude_code/core/turn.py +168 -66
- klaude_code/llm/__init__.py +2 -10
- klaude_code/llm/anthropic/client.py +190 -178
- klaude_code/llm/anthropic/input.py +39 -15
- klaude_code/llm/bedrock/__init__.py +3 -0
- klaude_code/llm/bedrock/client.py +60 -0
- klaude_code/llm/client.py +7 -21
- klaude_code/llm/codex/__init__.py +5 -0
- klaude_code/llm/codex/client.py +149 -0
- klaude_code/llm/google/__init__.py +3 -0
- klaude_code/llm/google/client.py +309 -0
- klaude_code/llm/google/input.py +215 -0
- klaude_code/llm/input_common.py +3 -9
- klaude_code/llm/openai_compatible/client.py +72 -164
- klaude_code/llm/openai_compatible/input.py +6 -4
- klaude_code/llm/openai_compatible/stream.py +273 -0
- klaude_code/llm/openai_compatible/tool_call_accumulator.py +17 -1
- klaude_code/llm/openrouter/client.py +89 -160
- klaude_code/llm/openrouter/input.py +18 -30
- klaude_code/llm/openrouter/reasoning.py +118 -0
- klaude_code/llm/registry.py +39 -7
- klaude_code/llm/responses/client.py +184 -171
- klaude_code/llm/responses/input.py +20 -1
- klaude_code/llm/usage.py +17 -12
- klaude_code/protocol/commands.py +17 -1
- klaude_code/protocol/events.py +31 -4
- klaude_code/protocol/llm_param.py +13 -10
- klaude_code/protocol/model.py +232 -29
- klaude_code/protocol/op.py +90 -1
- klaude_code/protocol/op_handler.py +35 -1
- klaude_code/protocol/sub_agent/__init__.py +117 -0
- klaude_code/protocol/sub_agent/explore.py +63 -0
- klaude_code/protocol/sub_agent/oracle.py +91 -0
- klaude_code/protocol/sub_agent/task.py +61 -0
- klaude_code/protocol/sub_agent/web.py +79 -0
- klaude_code/protocol/tools.py +4 -2
- klaude_code/session/__init__.py +2 -2
- klaude_code/session/codec.py +71 -0
- klaude_code/session/export.py +293 -86
- klaude_code/session/selector.py +89 -67
- klaude_code/session/session.py +320 -309
- klaude_code/session/store.py +220 -0
- klaude_code/session/templates/export_session.html +595 -83
- klaude_code/session/templates/mermaid_viewer.html +926 -0
- klaude_code/skill/__init__.py +27 -0
- klaude_code/skill/assets/deslop/SKILL.md +17 -0
- klaude_code/skill/assets/dev-docs/SKILL.md +108 -0
- klaude_code/skill/assets/handoff/SKILL.md +39 -0
- klaude_code/skill/assets/jj-workspace/SKILL.md +20 -0
- klaude_code/skill/assets/skill-creator/SKILL.md +139 -0
- klaude_code/{core/tool/memory/skill_loader.py → skill/loader.py} +55 -15
- klaude_code/skill/manager.py +70 -0
- klaude_code/skill/system_skills.py +192 -0
- klaude_code/trace/__init__.py +20 -2
- klaude_code/trace/log.py +150 -5
- klaude_code/ui/__init__.py +4 -9
- klaude_code/ui/core/input.py +1 -1
- klaude_code/ui/core/stage_manager.py +7 -7
- klaude_code/ui/modes/debug/display.py +2 -1
- klaude_code/ui/modes/repl/__init__.py +3 -48
- klaude_code/ui/modes/repl/clipboard.py +5 -5
- klaude_code/ui/modes/repl/completers.py +487 -123
- klaude_code/ui/modes/repl/display.py +5 -4
- klaude_code/ui/modes/repl/event_handler.py +370 -117
- klaude_code/ui/modes/repl/input_prompt_toolkit.py +552 -105
- klaude_code/ui/modes/repl/key_bindings.py +146 -23
- klaude_code/ui/modes/repl/renderer.py +189 -99
- klaude_code/ui/renderers/assistant.py +9 -2
- klaude_code/ui/renderers/bash_syntax.py +178 -0
- klaude_code/ui/renderers/common.py +78 -0
- klaude_code/ui/renderers/developer.py +104 -48
- klaude_code/ui/renderers/diffs.py +87 -6
- klaude_code/ui/renderers/errors.py +11 -6
- klaude_code/ui/renderers/mermaid_viewer.py +57 -0
- klaude_code/ui/renderers/metadata.py +112 -76
- klaude_code/ui/renderers/sub_agent.py +92 -7
- klaude_code/ui/renderers/thinking.py +40 -18
- klaude_code/ui/renderers/tools.py +405 -227
- klaude_code/ui/renderers/user_input.py +73 -13
- klaude_code/ui/rich/__init__.py +10 -1
- klaude_code/ui/rich/cjk_wrap.py +228 -0
- klaude_code/ui/rich/code_panel.py +131 -0
- klaude_code/ui/rich/live.py +17 -0
- klaude_code/ui/rich/markdown.py +305 -170
- klaude_code/ui/rich/searchable_text.py +10 -13
- klaude_code/ui/rich/status.py +190 -49
- klaude_code/ui/rich/theme.py +135 -39
- klaude_code/ui/terminal/__init__.py +55 -0
- klaude_code/ui/terminal/color.py +1 -1
- klaude_code/ui/terminal/control.py +13 -22
- klaude_code/ui/terminal/notifier.py +44 -4
- klaude_code/ui/terminal/selector.py +658 -0
- klaude_code/ui/utils/common.py +0 -18
- klaude_code-1.8.0.dist-info/METADATA +377 -0
- klaude_code-1.8.0.dist-info/RECORD +219 -0
- {klaude_code-1.2.6.dist-info → klaude_code-1.8.0.dist-info}/entry_points.txt +1 -0
- klaude_code/command/diff_cmd.py +0 -138
- klaude_code/command/prompt-dev-docs-update.md +0 -56
- klaude_code/command/prompt-dev-docs.md +0 -46
- klaude_code/config/list_model.py +0 -162
- klaude_code/core/manager/agent_manager.py +0 -127
- klaude_code/core/prompts/prompt-subagent-webfetch.md +0 -46
- klaude_code/core/tool/file/multi_edit_tool.md +0 -42
- klaude_code/core/tool/file/multi_edit_tool.py +0 -199
- klaude_code/core/tool/memory/memory_tool.md +0 -16
- klaude_code/core/tool/memory/memory_tool.py +0 -462
- klaude_code/llm/openrouter/reasoning_handler.py +0 -209
- klaude_code/protocol/sub_agent.py +0 -348
- klaude_code/ui/utils/debouncer.py +0 -42
- klaude_code-1.2.6.dist-info/METADATA +0 -178
- klaude_code-1.2.6.dist-info/RECORD +0 -167
- /klaude_code/core/prompts/{prompt-subagent.md → prompt-sub-agent.md} +0 -0
- /klaude_code/core/tool/{memory → skill}/__init__.py +0 -0
- /klaude_code/core/tool/{memory → skill}/skill_tool.md +0 -0
- {klaude_code-1.2.6.dist-info → klaude_code-1.8.0.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
|
|
3
|
+
from rich.console import Console, Group
|
|
4
|
+
from rich.panel import Panel
|
|
5
|
+
from rich.table import Table
|
|
6
|
+
from rich.text import Text
|
|
7
|
+
|
|
8
|
+
from klaude_code.config import Config
|
|
9
|
+
from klaude_code.config.config import ModelConfig, ProviderConfig, parse_env_var_syntax
|
|
10
|
+
from klaude_code.protocol.llm_param import LLMClientProtocol
|
|
11
|
+
from klaude_code.protocol.sub_agent import iter_sub_agent_profiles
|
|
12
|
+
from klaude_code.ui.rich.theme import ThemeKey, get_theme
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _get_codex_status_elements() -> list[Text]:
|
|
16
|
+
"""Get Codex OAuth login status as Text elements for panel display."""
|
|
17
|
+
from klaude_code.auth.codex.token_manager import CodexTokenManager
|
|
18
|
+
|
|
19
|
+
elements: list[Text] = []
|
|
20
|
+
token_manager = CodexTokenManager()
|
|
21
|
+
state = token_manager.get_state()
|
|
22
|
+
|
|
23
|
+
if state is None:
|
|
24
|
+
elements.append(
|
|
25
|
+
Text.assemble(
|
|
26
|
+
("Status: ", "bold"),
|
|
27
|
+
("Not logged in", ThemeKey.CONFIG_STATUS_ERROR),
|
|
28
|
+
(" (run 'klaude login codex' to authenticate)", "dim"),
|
|
29
|
+
)
|
|
30
|
+
)
|
|
31
|
+
elif state.is_expired():
|
|
32
|
+
elements.append(
|
|
33
|
+
Text.assemble(
|
|
34
|
+
("Status: ", "bold"),
|
|
35
|
+
("Token expired", ThemeKey.CONFIG_STATUS_ERROR),
|
|
36
|
+
(" (run 'klaude login codex' to re-authenticate)", "dim"),
|
|
37
|
+
)
|
|
38
|
+
)
|
|
39
|
+
else:
|
|
40
|
+
expires_dt = datetime.datetime.fromtimestamp(state.expires_at, tz=datetime.UTC)
|
|
41
|
+
elements.append(
|
|
42
|
+
Text.assemble(
|
|
43
|
+
("Status: ", "bold"),
|
|
44
|
+
("Logged in", ThemeKey.CONFIG_STATUS_OK),
|
|
45
|
+
(f" (account: {state.account_id[:8]}..., expires: {expires_dt.strftime('%Y-%m-%d %H:%M UTC')})", "dim"),
|
|
46
|
+
)
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
elements.append(
|
|
50
|
+
Text.assemble(
|
|
51
|
+
("Visit ", "dim"),
|
|
52
|
+
(
|
|
53
|
+
"https://chatgpt.com/codex/settings/usage",
|
|
54
|
+
"blue underline link https://chatgpt.com/codex/settings/usage",
|
|
55
|
+
),
|
|
56
|
+
(" for up-to-date information on rate limits and credits", "dim"),
|
|
57
|
+
)
|
|
58
|
+
)
|
|
59
|
+
return elements
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def mask_api_key(api_key: str | None) -> str:
|
|
63
|
+
"""Mask API key to show only first 6 and last 6 characters with *** in between"""
|
|
64
|
+
if not api_key or api_key == "N/A":
|
|
65
|
+
return "N/A"
|
|
66
|
+
|
|
67
|
+
if len(api_key) <= 12:
|
|
68
|
+
return api_key
|
|
69
|
+
|
|
70
|
+
return f"{api_key[:6]} … {api_key[-6:]}"
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def format_api_key_display(provider: ProviderConfig) -> Text:
|
|
74
|
+
"""Format API key display with warning if env var is not set."""
|
|
75
|
+
env_var = provider.get_api_key_env_var()
|
|
76
|
+
resolved_key = provider.get_resolved_api_key()
|
|
77
|
+
|
|
78
|
+
if env_var:
|
|
79
|
+
# Using ${ENV_VAR} syntax
|
|
80
|
+
if resolved_key:
|
|
81
|
+
return Text.assemble(
|
|
82
|
+
(f"${{{env_var}}} = ", "dim"),
|
|
83
|
+
(mask_api_key(resolved_key), ""),
|
|
84
|
+
)
|
|
85
|
+
else:
|
|
86
|
+
return Text.assemble(
|
|
87
|
+
(f"${{{env_var}}} ", ""),
|
|
88
|
+
("(not set)", ThemeKey.CONFIG_STATUS_ERROR),
|
|
89
|
+
)
|
|
90
|
+
elif provider.api_key:
|
|
91
|
+
# Plain API key
|
|
92
|
+
return Text(mask_api_key(provider.api_key))
|
|
93
|
+
else:
|
|
94
|
+
return Text("N/A")
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def format_env_var_display(value: str | None) -> Text:
|
|
98
|
+
"""Format environment variable display with warning if not set."""
|
|
99
|
+
env_var, resolved = parse_env_var_syntax(value)
|
|
100
|
+
|
|
101
|
+
if env_var:
|
|
102
|
+
# Using ${ENV_VAR} syntax
|
|
103
|
+
if resolved:
|
|
104
|
+
return Text.assemble(
|
|
105
|
+
(f"${{{env_var}}} = ", "dim"),
|
|
106
|
+
(mask_api_key(resolved), ""),
|
|
107
|
+
)
|
|
108
|
+
else:
|
|
109
|
+
return Text.assemble(
|
|
110
|
+
(f"${{{env_var}}} ", ""),
|
|
111
|
+
("(not set)", ThemeKey.CONFIG_STATUS_ERROR),
|
|
112
|
+
)
|
|
113
|
+
elif value:
|
|
114
|
+
# Plain value
|
|
115
|
+
return Text(mask_api_key(value))
|
|
116
|
+
else:
|
|
117
|
+
return Text("N/A")
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def _get_model_params_display(model: ModelConfig) -> list[Text]:
|
|
121
|
+
"""Get display elements for model parameters."""
|
|
122
|
+
params: list[Text] = []
|
|
123
|
+
if model.model_params.thinking:
|
|
124
|
+
if model.model_params.thinking.reasoning_effort is not None:
|
|
125
|
+
params.append(
|
|
126
|
+
Text.assemble(
|
|
127
|
+
("reason-effort", ThemeKey.CONFIG_PARAM_LABEL),
|
|
128
|
+
": ",
|
|
129
|
+
model.model_params.thinking.reasoning_effort,
|
|
130
|
+
)
|
|
131
|
+
)
|
|
132
|
+
if model.model_params.thinking.reasoning_summary is not None:
|
|
133
|
+
params.append(
|
|
134
|
+
Text.assemble(
|
|
135
|
+
("reason-summary", ThemeKey.CONFIG_PARAM_LABEL),
|
|
136
|
+
": ",
|
|
137
|
+
model.model_params.thinking.reasoning_summary,
|
|
138
|
+
)
|
|
139
|
+
)
|
|
140
|
+
if model.model_params.thinking.budget_tokens is not None:
|
|
141
|
+
params.append(
|
|
142
|
+
Text.assemble(
|
|
143
|
+
("thinking-budget-tokens", ThemeKey.CONFIG_PARAM_LABEL),
|
|
144
|
+
": ",
|
|
145
|
+
str(model.model_params.thinking.budget_tokens),
|
|
146
|
+
)
|
|
147
|
+
)
|
|
148
|
+
if model.model_params.provider_routing:
|
|
149
|
+
params.append(
|
|
150
|
+
Text.assemble(
|
|
151
|
+
("provider-routing", ThemeKey.CONFIG_PARAM_LABEL),
|
|
152
|
+
": ",
|
|
153
|
+
model.model_params.provider_routing.model_dump_json(exclude_none=True),
|
|
154
|
+
)
|
|
155
|
+
)
|
|
156
|
+
if len(params) == 0:
|
|
157
|
+
params.append(Text("N/A", style=ThemeKey.CONFIG_PARAM_LABEL))
|
|
158
|
+
return params
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def display_models_and_providers(config: Config):
|
|
162
|
+
"""Display models and providers configuration using rich formatting"""
|
|
163
|
+
themes = get_theme(config.theme)
|
|
164
|
+
console = Console(theme=themes.app_theme)
|
|
165
|
+
|
|
166
|
+
# Display each provider as a separate panel
|
|
167
|
+
for provider in config.provider_list:
|
|
168
|
+
# Provider info section
|
|
169
|
+
provider_info = Table.grid(padding=(0, 1))
|
|
170
|
+
provider_info.add_column(width=12)
|
|
171
|
+
provider_info.add_column()
|
|
172
|
+
|
|
173
|
+
provider_info.add_row(
|
|
174
|
+
Text("Protocol:", style=ThemeKey.CONFIG_PARAM_LABEL),
|
|
175
|
+
Text(provider.protocol.value),
|
|
176
|
+
)
|
|
177
|
+
if provider.base_url:
|
|
178
|
+
provider_info.add_row(
|
|
179
|
+
Text("Base URL:", style=ThemeKey.CONFIG_PARAM_LABEL),
|
|
180
|
+
Text(provider.base_url or "N/A"),
|
|
181
|
+
)
|
|
182
|
+
if provider.api_key:
|
|
183
|
+
provider_info.add_row(
|
|
184
|
+
Text("API Key:", style=ThemeKey.CONFIG_PARAM_LABEL),
|
|
185
|
+
format_api_key_display(provider),
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
# AWS Bedrock parameters
|
|
189
|
+
if provider.protocol == LLMClientProtocol.BEDROCK:
|
|
190
|
+
if provider.aws_access_key:
|
|
191
|
+
provider_info.add_row(
|
|
192
|
+
Text("AWS Key:", style=ThemeKey.CONFIG_PARAM_LABEL),
|
|
193
|
+
format_env_var_display(provider.aws_access_key),
|
|
194
|
+
)
|
|
195
|
+
if provider.aws_secret_key:
|
|
196
|
+
provider_info.add_row(
|
|
197
|
+
Text("AWS Secret:", style=ThemeKey.CONFIG_PARAM_LABEL),
|
|
198
|
+
format_env_var_display(provider.aws_secret_key),
|
|
199
|
+
)
|
|
200
|
+
if provider.aws_region:
|
|
201
|
+
provider_info.add_row(
|
|
202
|
+
Text("AWS Region:", style=ThemeKey.CONFIG_PARAM_LABEL),
|
|
203
|
+
format_env_var_display(provider.aws_region),
|
|
204
|
+
)
|
|
205
|
+
if provider.aws_session_token:
|
|
206
|
+
provider_info.add_row(
|
|
207
|
+
Text("AWS Token:", style=ThemeKey.CONFIG_PARAM_LABEL),
|
|
208
|
+
format_env_var_display(provider.aws_session_token),
|
|
209
|
+
)
|
|
210
|
+
if provider.aws_profile:
|
|
211
|
+
provider_info.add_row(
|
|
212
|
+
Text("AWS Profile:", style=ThemeKey.CONFIG_PARAM_LABEL),
|
|
213
|
+
format_env_var_display(provider.aws_profile),
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
# Check if provider has valid API key
|
|
217
|
+
provider_available = not provider.is_api_key_missing()
|
|
218
|
+
|
|
219
|
+
# Models table for this provider
|
|
220
|
+
models_table = Table.grid(padding=(0, 1), expand=True)
|
|
221
|
+
models_table.add_column(width=2, no_wrap=True) # Status
|
|
222
|
+
models_table.add_column(overflow="fold", ratio=2) # Name
|
|
223
|
+
models_table.add_column(overflow="fold", ratio=3) # Model
|
|
224
|
+
models_table.add_column(overflow="fold", ratio=4) # Params
|
|
225
|
+
|
|
226
|
+
# Add header
|
|
227
|
+
models_table.add_row(
|
|
228
|
+
Text("", style="bold"),
|
|
229
|
+
Text("Name", style=ThemeKey.CONFIG_TABLE_HEADER),
|
|
230
|
+
Text("Model", style=ThemeKey.CONFIG_TABLE_HEADER),
|
|
231
|
+
Text("Params", style=ThemeKey.CONFIG_TABLE_HEADER),
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
# Add models for this provider
|
|
235
|
+
for model in provider.model_list:
|
|
236
|
+
if not provider_available:
|
|
237
|
+
# Provider API key not set - show as unavailable
|
|
238
|
+
status = Text("-", style="dim")
|
|
239
|
+
name = Text(model.model_name, style="dim")
|
|
240
|
+
model_id = Text(model.model_params.model or "N/A", style="dim")
|
|
241
|
+
params = [Text("(unavailable)", style="dim")]
|
|
242
|
+
elif model.model_name == config.main_model:
|
|
243
|
+
status = Text("★", style=ThemeKey.CONFIG_STATUS_PRIMARY)
|
|
244
|
+
name = Text(model.model_name, style=ThemeKey.CONFIG_STATUS_PRIMARY)
|
|
245
|
+
model_id = Text(model.model_params.model or "N/A", style="")
|
|
246
|
+
params = _get_model_params_display(model)
|
|
247
|
+
else:
|
|
248
|
+
status = Text("✔", style=ThemeKey.CONFIG_STATUS_OK)
|
|
249
|
+
name = Text(model.model_name, style=ThemeKey.CONFIG_ITEM_NAME)
|
|
250
|
+
model_id = Text(model.model_params.model or "N/A", style="")
|
|
251
|
+
params = _get_model_params_display(model)
|
|
252
|
+
|
|
253
|
+
models_table.add_row(status, name, model_id, Group(*params))
|
|
254
|
+
|
|
255
|
+
# Create panel content with provider info and models
|
|
256
|
+
panel_elements = [
|
|
257
|
+
provider_info,
|
|
258
|
+
Text(""), # Spacer
|
|
259
|
+
Text("Models:", style=ThemeKey.CONFIG_TABLE_HEADER),
|
|
260
|
+
models_table,
|
|
261
|
+
]
|
|
262
|
+
|
|
263
|
+
# Add Codex status if this is a codex provider
|
|
264
|
+
if provider.protocol == LLMClientProtocol.CODEX:
|
|
265
|
+
panel_elements.append(Text("")) # Spacer
|
|
266
|
+
panel_elements.extend(_get_codex_status_elements())
|
|
267
|
+
|
|
268
|
+
panel_content = Group(*panel_elements)
|
|
269
|
+
|
|
270
|
+
panel = Panel(
|
|
271
|
+
panel_content,
|
|
272
|
+
title=Text(f"Provider: {provider.provider_name}", style=ThemeKey.CONFIG_PROVIDER),
|
|
273
|
+
border_style=ThemeKey.CONFIG_PANEL_BORDER,
|
|
274
|
+
padding=(0, 1),
|
|
275
|
+
title_align="left",
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
console.print(panel)
|
|
279
|
+
console.print()
|
|
280
|
+
|
|
281
|
+
# Display main model info
|
|
282
|
+
console.print()
|
|
283
|
+
if config.main_model:
|
|
284
|
+
console.print(
|
|
285
|
+
Text.assemble(
|
|
286
|
+
("Default Model: ", "bold"),
|
|
287
|
+
(config.main_model, ThemeKey.CONFIG_STATUS_PRIMARY),
|
|
288
|
+
)
|
|
289
|
+
)
|
|
290
|
+
else:
|
|
291
|
+
console.print(
|
|
292
|
+
Text.assemble(
|
|
293
|
+
("Default Model: ", "bold"),
|
|
294
|
+
("(not set)", ThemeKey.CONFIG_STATUS_ERROR),
|
|
295
|
+
)
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
for profile in iter_sub_agent_profiles():
|
|
299
|
+
sub_model_name = config.sub_agent_models.get(profile.name)
|
|
300
|
+
if not sub_model_name:
|
|
301
|
+
continue
|
|
302
|
+
console.print(
|
|
303
|
+
Text.assemble(
|
|
304
|
+
(f"{profile.name} Model: ", "bold"),
|
|
305
|
+
(sub_model_name, ThemeKey.CONFIG_STATUS_PRIMARY),
|
|
306
|
+
)
|
|
307
|
+
)
|