klaude-code 2.5.2__tar.gz → 2.5.3__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.
- {klaude_code-2.5.2 → klaude_code-2.5.3}/PKG-INFO +1 -1
- {klaude_code-2.5.2 → klaude_code-2.5.3}/pyproject.toml +1 -1
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/cli/auth_cmd.py +2 -13
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/cli/cost_cmd.py +10 -10
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/cli/main.py +40 -7
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/cli/session_cmd.py +2 -11
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/config/assets/builtin_config.yaml +45 -24
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/config/model_matcher.py +1 -1
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/const.py +2 -1
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/file/edit_tool.py +1 -1
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/file/read_tool.py +2 -2
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/file/write_tool.py +1 -1
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/turn.py +19 -1
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/llm/anthropic/client.py +75 -50
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/llm/anthropic/input.py +20 -9
- klaude_code-2.5.3/src/klaude_code/llm/google/client.py +527 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/llm/google/input.py +44 -36
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/llm/openai_compatible/stream.py +109 -99
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/llm/openrouter/reasoning.py +4 -29
- klaude_code-2.5.3/src/klaude_code/llm/partial_message.py +5 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/llm/responses/client.py +99 -81
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/llm/responses/input.py +11 -25
- klaude_code-2.5.3/src/klaude_code/llm/stream_parts.py +94 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/log.py +57 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/command/fork_session_cmd.py +14 -23
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/command/model_picker.py +2 -17
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/command/resume_cmd.py +2 -18
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/command/sub_agent_model_cmd.py +5 -19
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/command/thinking_cmd.py +2 -14
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/components/common.py +1 -1
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/components/metadata.py +17 -16
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/components/rich/quote.py +36 -8
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/components/rich/theme.py +2 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/input/prompt_toolkit.py +3 -1
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/machine.py +19 -1
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/renderer.py +3 -3
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/terminal/selector.py +174 -31
- klaude_code-2.5.2/src/klaude_code/llm/google/client.py +0 -452
- klaude_code-2.5.2/src/klaude_code/llm/partial_message.py +0 -35
- {klaude_code-2.5.2 → klaude_code-2.5.3}/README.md +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/.DS_Store +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/app/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/app/runtime.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/auth/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/auth/base.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/auth/claude/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/auth/claude/exceptions.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/auth/claude/oauth.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/auth/claude/token_manager.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/auth/codex/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/auth/codex/exceptions.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/auth/codex/jwt_utils.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/auth/codex/oauth.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/auth/codex/token_manager.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/cli/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/cli/config_cmd.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/cli/debug.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/cli/list_model.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/cli/self_update.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/config/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/config/assets/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/config/builtin_config.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/config/config.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/config/sub_agent_model_helper.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/config/thinking.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/agent.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/agent_profile.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/executor.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/loaded_skills.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/manager/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/manager/llm_clients.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/manager/llm_clients_builder.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/manager/sub_agent_manager.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/prompts/prompt-claude-code.md +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/prompts/prompt-codex-gpt-5-1-codex-max.md +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/prompts/prompt-codex-gpt-5-2-codex.md +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/prompts/prompt-codex.md +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/prompts/prompt-gemini.md +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/prompts/prompt-minimal.md +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/prompts/prompt-sub-agent-explore.md +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/prompts/prompt-sub-agent-image-gen.md +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/prompts/prompt-sub-agent-web.md +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/prompts/prompt-sub-agent.md +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/reminders.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/task.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/context.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/file/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/file/_utils.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/file/apply_patch.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/file/apply_patch_tool.md +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/file/apply_patch_tool.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/file/diff_builder.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/file/edit_tool.md +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/file/read_tool.md +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/file/write_tool.md +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/offload.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/report_back_tool.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/shell/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/shell/bash_tool.md +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/shell/bash_tool.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/shell/command_safety.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/sub_agent_tool.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/todo/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/todo/todo_write_tool.md +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/todo/todo_write_tool.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/todo/todo_write_tool_raw.md +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/todo/update_plan_tool.md +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/todo/update_plan_tool.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/tool_abc.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/tool_registry.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/tool_runner.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/web/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/web/mermaid_tool.md +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/web/mermaid_tool.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/web/web_fetch_tool.md +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/web/web_fetch_tool.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/web/web_search_tool.md +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/core/tool/web/web_search_tool.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/llm/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/llm/anthropic/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/llm/bedrock/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/llm/bedrock/client.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/llm/claude/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/llm/claude/client.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/llm/client.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/llm/codex/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/llm/codex/client.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/llm/google/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/llm/image.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/llm/input_common.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/llm/openai_compatible/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/llm/openai_compatible/client.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/llm/openai_compatible/input.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/llm/openai_compatible/tool_call_accumulator.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/llm/openrouter/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/llm/openrouter/client.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/llm/openrouter/input.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/llm/registry.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/llm/responses/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/llm/usage.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/protocol/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/protocol/commands.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/protocol/events/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/protocol/events/base.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/protocol/events/chat.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/protocol/events/lifecycle.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/protocol/events/metadata.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/protocol/events/streaming.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/protocol/events/system.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/protocol/events/tools.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/protocol/llm_param.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/protocol/message.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/protocol/model.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/protocol/op.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/protocol/op_handler.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/protocol/sub_agent/AGENTS.md +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/protocol/sub_agent/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/protocol/sub_agent/explore.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/protocol/sub_agent/image_gen.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/protocol/sub_agent/task.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/protocol/sub_agent/web.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/protocol/tools.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/session/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/session/codec.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/session/export.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/session/selector.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/session/session.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/session/store.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/session/templates/export_session.html +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/session/templates/mermaid_viewer.html +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/skill/.DS_Store +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/skill/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/skill/assets/.DS_Store +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/skill/assets/create-plan/SKILL.md +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/skill/assets/deslop/SKILL.md +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/skill/assets/handoff/SKILL.md +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/skill/assets/skill-creator/SKILL.md +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/skill/loader.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/skill/manager.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/skill/system_skills.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/command/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/command/clear_cmd.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/command/command_abc.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/command/copy_cmd.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/command/debug_cmd.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/command/export_cmd.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/command/export_online_cmd.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/command/model_cmd.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/command/prompt-init.md +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/command/prompt_command.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/command/refresh_cmd.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/command/registry.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/command/status_cmd.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/command/terminal_setup_cmd.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/commands.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/components/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/components/assistant.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/components/bash_syntax.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/components/command_output.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/components/developer.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/components/diffs.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/components/errors.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/components/mermaid_viewer.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/components/rich/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/components/rich/cjk_wrap.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/components/rich/code_panel.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/components/rich/live.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/components/rich/markdown.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/components/rich/searchable_text.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/components/rich/status.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/components/sub_agent.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/components/thinking.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/components/tools.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/components/user_input.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/components/welcome.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/display.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/input/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/input/clipboard.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/input/completers.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/input/key_bindings.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/runner.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/terminal/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/terminal/color.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/terminal/control.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/terminal/image.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/terminal/notifier.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/tui/terminal/progress_bar.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/ui/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/ui/common.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/ui/core/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/ui/core/display.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/ui/core/input.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/ui/debug_mode.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/ui/terminal/__init__.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/ui/terminal/title.py +0 -0
- {klaude_code-2.5.2 → klaude_code-2.5.3}/src/klaude_code/update.py +0 -0
|
@@ -4,20 +4,9 @@ import datetime
|
|
|
4
4
|
import webbrowser
|
|
5
5
|
|
|
6
6
|
import typer
|
|
7
|
-
from prompt_toolkit.styles import Style
|
|
8
7
|
|
|
9
8
|
from klaude_code.log import log
|
|
10
|
-
from klaude_code.tui.terminal.selector import SelectItem, select_one
|
|
11
|
-
|
|
12
|
-
_SELECT_STYLE = Style(
|
|
13
|
-
[
|
|
14
|
-
("instruction", "ansibrightblack"),
|
|
15
|
-
("pointer", "ansigreen"),
|
|
16
|
-
("highlighted", "ansigreen"),
|
|
17
|
-
("text", "ansibrightblack"),
|
|
18
|
-
("question", "bold"),
|
|
19
|
-
]
|
|
20
|
-
)
|
|
9
|
+
from klaude_code.tui.terminal.selector import DEFAULT_PICKER_STYLE, SelectItem, select_one
|
|
21
10
|
|
|
22
11
|
|
|
23
12
|
def _select_provider() -> str | None:
|
|
@@ -30,7 +19,7 @@ def _select_provider() -> str | None:
|
|
|
30
19
|
message="Select provider to login:",
|
|
31
20
|
items=items,
|
|
32
21
|
pointer="→",
|
|
33
|
-
style=
|
|
22
|
+
style=DEFAULT_PICKER_STYLE,
|
|
34
23
|
use_search_filter=False,
|
|
35
24
|
)
|
|
36
25
|
|
|
@@ -183,14 +183,14 @@ def render_cost_table(daily_stats: dict[str, DailyStats]) -> Table:
|
|
|
183
183
|
box=ASCII_HORIZONAL,
|
|
184
184
|
)
|
|
185
185
|
|
|
186
|
-
table.add_column("Date", style="cyan"
|
|
187
|
-
table.add_column("Model",
|
|
188
|
-
table.add_column("Input", justify="right"
|
|
189
|
-
table.add_column("Output", justify="right"
|
|
190
|
-
table.add_column("Cache", justify="right"
|
|
191
|
-
table.add_column("Total", justify="right"
|
|
192
|
-
table.add_column("USD", justify="right"
|
|
193
|
-
table.add_column("CNY", justify="right"
|
|
186
|
+
table.add_column("Date", style="cyan")
|
|
187
|
+
table.add_column("Model", overflow="ellipsis")
|
|
188
|
+
table.add_column("Input", justify="right")
|
|
189
|
+
table.add_column("Output", justify="right")
|
|
190
|
+
table.add_column("Cache", justify="right")
|
|
191
|
+
table.add_column("Total", justify="right")
|
|
192
|
+
table.add_column("USD", justify="right")
|
|
193
|
+
table.add_column("CNY", justify="right")
|
|
194
194
|
|
|
195
195
|
# Sort dates
|
|
196
196
|
sorted_dates = sorted(daily_stats.keys())
|
|
@@ -222,7 +222,7 @@ def render_cost_table(daily_stats: dict[str, DailyStats]) -> Table:
|
|
|
222
222
|
|
|
223
223
|
table.add_row(
|
|
224
224
|
format_date_display(date_str) if first_row else "",
|
|
225
|
-
f"
|
|
225
|
+
f"{model_name}",
|
|
226
226
|
format_tokens(stats.input_tokens),
|
|
227
227
|
format_tokens(stats.output_tokens),
|
|
228
228
|
format_tokens(stats.cached_tokens),
|
|
@@ -276,7 +276,7 @@ def render_cost_table(daily_stats: dict[str, DailyStats]) -> Table:
|
|
|
276
276
|
usd_str, cny_str = format_cost_dual(stats.cost_usd, stats.cost_cny)
|
|
277
277
|
table.add_row(
|
|
278
278
|
"",
|
|
279
|
-
f"
|
|
279
|
+
f"{model_name}",
|
|
280
280
|
format_tokens(stats.input_tokens),
|
|
281
281
|
format_tokens(stats.output_tokens),
|
|
282
282
|
format_tokens(stats.cached_tokens),
|
|
@@ -13,13 +13,46 @@ from klaude_code.session import Session
|
|
|
13
13
|
from klaude_code.tui.command.resume_cmd import select_session_sync
|
|
14
14
|
from klaude_code.ui.terminal.title import update_terminal_title
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
Environment Variables:
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
""
|
|
16
|
+
ENV_HELP_LINES = [
|
|
17
|
+
"Environment Variables:",
|
|
18
|
+
"",
|
|
19
|
+
"Provider API keys (built-in config):",
|
|
20
|
+
" ANTHROPIC_API_KEY Anthropic API key",
|
|
21
|
+
" OPENAI_API_KEY OpenAI API key",
|
|
22
|
+
" OPENROUTER_API_KEY OpenRouter API key",
|
|
23
|
+
" GOOGLE_API_KEY Google API key (Gemini)",
|
|
24
|
+
" DEEPSEEK_API_KEY DeepSeek API key",
|
|
25
|
+
" MOONSHOT_API_KEY Moonshot API key (Kimi)",
|
|
26
|
+
"",
|
|
27
|
+
"AWS credentials (Bedrock):",
|
|
28
|
+
" AWS_ACCESS_KEY_ID AWS access key id",
|
|
29
|
+
" AWS_SECRET_ACCESS_KEY AWS secret access key",
|
|
30
|
+
" AWS_REGION AWS region",
|
|
31
|
+
"",
|
|
32
|
+
"Tool limits (Read):",
|
|
33
|
+
" KLAUDE_READ_GLOBAL_LINE_CAP Max lines to read (default: 2000)",
|
|
34
|
+
" KLAUDE_READ_MAX_CHARS Max total chars to read (default: 50000)",
|
|
35
|
+
" KLAUDE_READ_MAX_IMAGE_BYTES Max image bytes to read (default: 4MB)",
|
|
36
|
+
" KLAUDE_IMAGE_OUTPUT_MAX_BYTES Max decoded image bytes (default: 64MB)",
|
|
37
|
+
"",
|
|
38
|
+
"Notifications / testing:",
|
|
39
|
+
" KLAUDE_NOTIFY Set to 0/off/false/disable(d) to disable task notifications",
|
|
40
|
+
" KLAUDE_TEST_SIGNAL In tmux, emit `tmux wait-for -S <channel>` on task completion",
|
|
41
|
+
" TMUX Auto-detected; required for KLAUDE_TEST_SIGNAL",
|
|
42
|
+
"",
|
|
43
|
+
"Editor / terminal integration:",
|
|
44
|
+
" EDITOR Preferred editor for `klaude config`",
|
|
45
|
+
" TERM Terminal identification (auto-detected)",
|
|
46
|
+
" TERM_PROGRAM Terminal identification (auto-detected)",
|
|
47
|
+
" WT_SESSION Terminal hint (auto-detected)",
|
|
48
|
+
" VTE_VERSION Terminal hint (auto-detected)",
|
|
49
|
+
" GHOSTTY_RESOURCES_DIR Ghostty detection (auto-detected)",
|
|
50
|
+
"",
|
|
51
|
+
"Compatibility:",
|
|
52
|
+
" ANTHROPIC_AUTH_TOKEN Reserved by anthropic SDK; temporarily unset during client init",
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
ENV_HELP = "\n\n".join(ENV_HELP_LINES)
|
|
23
56
|
|
|
24
57
|
app = typer.Typer(
|
|
25
58
|
add_completion=False,
|
|
@@ -9,9 +9,7 @@ from klaude_code.session import Session
|
|
|
9
9
|
def _session_confirm(sessions: list[Session.SessionMetaBrief], message: str) -> bool:
|
|
10
10
|
"""Show session list and confirm deletion using prompt_toolkit."""
|
|
11
11
|
|
|
12
|
-
from
|
|
13
|
-
|
|
14
|
-
from klaude_code.tui.terminal.selector import SelectItem, select_one
|
|
12
|
+
from klaude_code.tui.terminal.selector import DEFAULT_PICKER_STYLE, SelectItem, select_one
|
|
15
13
|
|
|
16
14
|
def _fmt(ts: float) -> str:
|
|
17
15
|
try:
|
|
@@ -37,14 +35,7 @@ def _session_confirm(sessions: list[Session.SessionMetaBrief], message: str) ->
|
|
|
37
35
|
message=message,
|
|
38
36
|
items=items,
|
|
39
37
|
pointer="→",
|
|
40
|
-
style=
|
|
41
|
-
[
|
|
42
|
-
("question", "bold"),
|
|
43
|
-
("pointer", "ansigreen"),
|
|
44
|
-
("highlighted", "ansigreen"),
|
|
45
|
-
("text", ""),
|
|
46
|
-
]
|
|
47
|
-
),
|
|
38
|
+
style=DEFAULT_PICKER_STYLE,
|
|
48
39
|
use_search_filter=False,
|
|
49
40
|
)
|
|
50
41
|
return bool(result)
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
---
|
|
2
1
|
# Built-in provider and model configurations
|
|
3
2
|
# Users can start using klaude by simply setting environment variables
|
|
4
3
|
# (ANTHROPIC_API_KEY, OPENAI_API_KEY, etc.) without manual configuration.
|
|
@@ -25,32 +24,58 @@ provider_list:
|
|
|
25
24
|
protocol: responses
|
|
26
25
|
api_key: ${OPENAI_API_KEY}
|
|
27
26
|
model_list:
|
|
28
|
-
- model_name: gpt-5.2
|
|
27
|
+
- model_name: gpt-5.2-high
|
|
29
28
|
model_id: gpt-5.2
|
|
30
29
|
max_tokens: 128000
|
|
31
30
|
context_limit: 400000
|
|
32
31
|
verbosity: high
|
|
33
32
|
thinking:
|
|
34
33
|
reasoning_effort: high
|
|
34
|
+
reasoning_summary: detailed
|
|
35
|
+
cost: {input: 1.75, output: 14, cache_read: 0.17}
|
|
36
|
+
- model_name: gpt-5.2-medium
|
|
37
|
+
model_id: gpt-5.2
|
|
38
|
+
context_limit: 400000
|
|
39
|
+
verbosity: high
|
|
40
|
+
thinking:
|
|
41
|
+
reasoning_effort: medium
|
|
42
|
+
reasoning_summary: concise
|
|
43
|
+
cost: {input: 1.75, output: 14, cache_read: 0.17}
|
|
44
|
+
- model_name: gpt-5.2-low
|
|
45
|
+
model_id: gpt-5.2
|
|
46
|
+
context_limit: 400000
|
|
47
|
+
verbosity: low
|
|
48
|
+
thinking:
|
|
49
|
+
reasoning_effort: low
|
|
50
|
+
reasoning_summary: concise
|
|
51
|
+
cost: {input: 1.75, output: 14, cache_read: 0.17}
|
|
52
|
+
- model_name: gpt-5.2-fast
|
|
53
|
+
model_id: gpt-5.2
|
|
54
|
+
context_limit: 400000
|
|
55
|
+
verbosity: low
|
|
56
|
+
thinking:
|
|
57
|
+
reasoning_effort: none
|
|
35
58
|
cost: {input: 1.75, output: 14, cache_read: 0.17}
|
|
36
|
-
- provider_name: openrouter
|
|
37
|
-
protocol: openrouter
|
|
38
|
-
api_key: ${OPENROUTER_API_KEY}
|
|
39
|
-
model_list:
|
|
40
59
|
- model_name: gpt-5.1-codex-max
|
|
41
|
-
model_id:
|
|
60
|
+
model_id: gpt-5.1-codex-max
|
|
42
61
|
max_tokens: 128000
|
|
43
62
|
context_limit: 400000
|
|
44
63
|
thinking:
|
|
45
64
|
reasoning_effort: medium
|
|
65
|
+
reasoning_summary: detailed
|
|
46
66
|
cost: {input: 1.25, output: 10, cache_read: 0.13}
|
|
47
|
-
|
|
67
|
+
- provider_name: openrouter
|
|
68
|
+
protocol: openrouter
|
|
69
|
+
api_key: ${OPENROUTER_API_KEY}
|
|
70
|
+
model_list:
|
|
71
|
+
- model_name: gpt-5.2-high
|
|
48
72
|
model_id: openai/gpt-5.2
|
|
49
73
|
max_tokens: 128000
|
|
50
74
|
context_limit: 400000
|
|
51
75
|
verbosity: high
|
|
52
76
|
thinking:
|
|
53
77
|
reasoning_effort: high
|
|
78
|
+
reasoning_summary: detailed
|
|
54
79
|
cost: {input: 1.75, output: 14, cache_read: 0.17}
|
|
55
80
|
- model_name: gpt-5.2-medium
|
|
56
81
|
model_id: openai/gpt-5.2
|
|
@@ -59,22 +84,7 @@ provider_list:
|
|
|
59
84
|
verbosity: high
|
|
60
85
|
thinking:
|
|
61
86
|
reasoning_effort: medium
|
|
62
|
-
|
|
63
|
-
- model_name: gpt-5.2-low
|
|
64
|
-
model_id: openai/gpt-5.2
|
|
65
|
-
max_tokens: 128000
|
|
66
|
-
context_limit: 400000
|
|
67
|
-
verbosity: low
|
|
68
|
-
thinking:
|
|
69
|
-
reasoning_effort: low
|
|
70
|
-
cost: {input: 1.75, output: 14, cache_read: 0.17}
|
|
71
|
-
- model_name: gpt-5.2-fast
|
|
72
|
-
model_id: openai/gpt-5.2
|
|
73
|
-
max_tokens: 128000
|
|
74
|
-
context_limit: 400000
|
|
75
|
-
verbosity: low
|
|
76
|
-
thinking:
|
|
77
|
-
reasoning_effort: none
|
|
87
|
+
reasoning_summary: concise
|
|
78
88
|
cost: {input: 1.75, output: 14, cache_read: 0.17}
|
|
79
89
|
- model_name: kimi
|
|
80
90
|
model_id: moonshotai/kimi-k2-thinking
|
|
@@ -165,10 +175,14 @@ provider_list:
|
|
|
165
175
|
- model_name: gemini-pro
|
|
166
176
|
model_id: gemini-3-pro-preview
|
|
167
177
|
context_limit: 1048576
|
|
178
|
+
thinking:
|
|
179
|
+
reasoning_effort: high
|
|
168
180
|
cost: {input: 2, output: 12, cache_read: 0.2}
|
|
169
181
|
- model_name: gemini-flash
|
|
170
182
|
model_id: gemini-3-flash-preview
|
|
171
183
|
context_limit: 1048576
|
|
184
|
+
thinking:
|
|
185
|
+
reasoning_effort: medium
|
|
172
186
|
cost: {input: 0.5, output: 3, cache_read: 0.05}
|
|
173
187
|
- model_name: nano-banana-pro
|
|
174
188
|
model_id: gemini-3-pro-image-preview
|
|
@@ -177,6 +191,13 @@ provider_list:
|
|
|
177
191
|
- image
|
|
178
192
|
- text
|
|
179
193
|
cost: {input: 2, output: 12, cache_read: 0.2, image: 120}
|
|
194
|
+
- model_name: nano-banana
|
|
195
|
+
model_id: gemini-2.5-flash-image
|
|
196
|
+
context_limit: 33000
|
|
197
|
+
modalities:
|
|
198
|
+
- image
|
|
199
|
+
- text
|
|
200
|
+
cost: {input: 0.3, output: 2.5, cache_read: 0.03, image: 30}
|
|
180
201
|
- provider_name: bedrock
|
|
181
202
|
protocol: bedrock
|
|
182
203
|
aws_access_key: ${AWS_ACCESS_KEY_ID}
|
|
@@ -102,6 +102,7 @@ def match_model_from_config(preferred: str | None = None) -> ModelMatchResult:
|
|
|
102
102
|
)
|
|
103
103
|
|
|
104
104
|
# Normalized matching (e.g. gpt52 == gpt-5.2, gpt52 in gpt-5.2-2025-...)
|
|
105
|
+
# Only match selector/model_name exactly; model_id is checked via substring match below
|
|
105
106
|
preferred_norm = _normalize_model_key(preferred)
|
|
106
107
|
normalized_matches: list[ModelEntry] = []
|
|
107
108
|
if preferred_norm:
|
|
@@ -110,7 +111,6 @@ def match_model_from_config(preferred: str | None = None) -> ModelMatchResult:
|
|
|
110
111
|
for m in models
|
|
111
112
|
if preferred_norm == _normalize_model_key(m.selector)
|
|
112
113
|
or preferred_norm == _normalize_model_key(m.model_name)
|
|
113
|
-
or preferred_norm == _normalize_model_key(m.model_id or "")
|
|
114
114
|
]
|
|
115
115
|
if len(normalized_matches) == 1:
|
|
116
116
|
return ModelMatchResult(
|
|
@@ -27,6 +27,7 @@ def _get_int_env(name: str, default: int) -> int:
|
|
|
27
27
|
# =============================================================================
|
|
28
28
|
|
|
29
29
|
MAX_FAILED_TURN_RETRIES = 10 # Maximum retry attempts for failed turns
|
|
30
|
+
RETRY_PRESERVE_PARTIAL_MESSAGE = True # Preserve partial message on stream error for retry prefill
|
|
30
31
|
LLM_HTTP_TIMEOUT_TOTAL = 300.0 # HTTP timeout for LLM API requests (seconds)
|
|
31
32
|
LLM_HTTP_TIMEOUT_CONNECT = 15.0 # HTTP connect timeout (seconds)
|
|
32
33
|
LLM_HTTP_TIMEOUT_READ = 285.0 # HTTP read timeout (seconds)
|
|
@@ -157,7 +158,7 @@ MARKDOWN_RIGHT_MARGIN = 2 # Right margin (columns) for markdown rendering
|
|
|
157
158
|
STATUS_HINT_TEXT = " (esc to interrupt)" # Status hint text shown after spinner
|
|
158
159
|
|
|
159
160
|
# Spinner status texts
|
|
160
|
-
STATUS_WAITING_TEXT = "
|
|
161
|
+
STATUS_WAITING_TEXT = "Loading …"
|
|
161
162
|
STATUS_THINKING_TEXT = "Thinking …"
|
|
162
163
|
STATUS_COMPOSING_TEXT = "Composing"
|
|
163
164
|
|
|
@@ -98,7 +98,7 @@ class EditTool(ToolABC):
|
|
|
98
98
|
if is_directory(file_path):
|
|
99
99
|
return message.ToolResultMessage(
|
|
100
100
|
status="error",
|
|
101
|
-
output_text="<tool_use_error>Illegal operation on a directory
|
|
101
|
+
output_text="<tool_use_error>Illegal operation on a directory: edit</tool_use_error>",
|
|
102
102
|
)
|
|
103
103
|
|
|
104
104
|
if args.old_string == "":
|
|
@@ -210,7 +210,7 @@ class ReadTool(ToolABC):
|
|
|
210
210
|
if is_directory(file_path):
|
|
211
211
|
return message.ToolResultMessage(
|
|
212
212
|
status="error",
|
|
213
|
-
output_text="<tool_use_error>Illegal operation on a directory
|
|
213
|
+
output_text="<tool_use_error>Illegal operation on a directory: read</tool_use_error>",
|
|
214
214
|
)
|
|
215
215
|
if not file_exists(file_path):
|
|
216
216
|
return message.ToolResultMessage(
|
|
@@ -308,7 +308,7 @@ class ReadTool(ToolABC):
|
|
|
308
308
|
except IsADirectoryError:
|
|
309
309
|
return message.ToolResultMessage(
|
|
310
310
|
status="error",
|
|
311
|
-
output_text="<tool_use_error>Illegal operation on a directory
|
|
311
|
+
output_text="<tool_use_error>Illegal operation on a directory: read</tool_use_error>",
|
|
312
312
|
)
|
|
313
313
|
|
|
314
314
|
if offset > max(read_result.total_lines, 0):
|
|
@@ -57,7 +57,7 @@ class WriteTool(ToolABC):
|
|
|
57
57
|
if is_directory(file_path):
|
|
58
58
|
return message.ToolResultMessage(
|
|
59
59
|
status="error",
|
|
60
|
-
output_text="<tool_use_error>Illegal operation on a directory
|
|
60
|
+
output_text="<tool_use_error>Illegal operation on a directory: write</tool_use_error>",
|
|
61
61
|
)
|
|
62
62
|
|
|
63
63
|
file_tracker = context.file_tracker
|
|
@@ -4,7 +4,7 @@ from collections.abc import AsyncGenerator
|
|
|
4
4
|
from dataclasses import dataclass, field
|
|
5
5
|
from typing import TYPE_CHECKING
|
|
6
6
|
|
|
7
|
-
from klaude_code.const import SUPPORTED_IMAGE_SIZES
|
|
7
|
+
from klaude_code.const import RETRY_PRESERVE_PARTIAL_MESSAGE, SUPPORTED_IMAGE_SIZES
|
|
8
8
|
from klaude_code.core.tool import ToolABC
|
|
9
9
|
from klaude_code.core.tool.context import SubAgentResumeClaims, ToolContext
|
|
10
10
|
|
|
@@ -24,6 +24,12 @@ from klaude_code.llm.client import LLMStreamABC
|
|
|
24
24
|
from klaude_code.log import DebugType, log_debug
|
|
25
25
|
from klaude_code.protocol import events, llm_param, message, model, tools
|
|
26
26
|
|
|
27
|
+
# Protocols that support prefill (continuing from partial assistant message)
|
|
28
|
+
_PREFILL_SUPPORTED_PROTOCOLS = frozenset({
|
|
29
|
+
"anthropic",
|
|
30
|
+
"claude_oauth",
|
|
31
|
+
})
|
|
32
|
+
|
|
27
33
|
|
|
28
34
|
class TurnError(Exception):
|
|
29
35
|
"""Raised when a turn fails and should be retried."""
|
|
@@ -176,6 +182,18 @@ class TurnExecutor:
|
|
|
176
182
|
yield event
|
|
177
183
|
|
|
178
184
|
if self._turn_result.stream_error is not None:
|
|
185
|
+
# Save accumulated content for potential prefill on retry (only for supported protocols)
|
|
186
|
+
protocol = ctx.llm_client.get_llm_config().protocol
|
|
187
|
+
supports_prefill = protocol.value in _PREFILL_SUPPORTED_PROTOCOLS
|
|
188
|
+
if (
|
|
189
|
+
RETRY_PRESERVE_PARTIAL_MESSAGE
|
|
190
|
+
and supports_prefill
|
|
191
|
+
and self._turn_result.assistant_message is not None
|
|
192
|
+
and self._turn_result.assistant_message.parts
|
|
193
|
+
):
|
|
194
|
+
session_ctx.append_history([self._turn_result.assistant_message])
|
|
195
|
+
# Add continuation prompt to avoid Anthropic thinking block requirement
|
|
196
|
+
session_ctx.append_history([message.UserMessage(parts=[message.TextPart(text="continue")])])
|
|
179
197
|
session_ctx.append_history([self._turn_result.stream_error])
|
|
180
198
|
yield events.TurnEndEvent(session_id=session_ctx.session_id)
|
|
181
199
|
raise TurnError(self._turn_result.stream_error.error)
|
|
@@ -33,8 +33,13 @@ from klaude_code.const import (
|
|
|
33
33
|
from klaude_code.llm.anthropic.input import convert_history_to_input, convert_system_to_input, convert_tool_schema
|
|
34
34
|
from klaude_code.llm.client import LLMClientABC, LLMStreamABC
|
|
35
35
|
from klaude_code.llm.input_common import apply_config_defaults
|
|
36
|
-
from klaude_code.llm.partial_message import degrade_thinking_to_text
|
|
37
36
|
from klaude_code.llm.registry import register
|
|
37
|
+
from klaude_code.llm.stream_parts import (
|
|
38
|
+
append_text_part,
|
|
39
|
+
append_thinking_text_part,
|
|
40
|
+
build_partial_message,
|
|
41
|
+
build_partial_parts,
|
|
42
|
+
)
|
|
38
43
|
from klaude_code.llm.usage import MetadataTracker, error_llm_stream
|
|
39
44
|
from klaude_code.log import DebugType, log_debug
|
|
40
45
|
from klaude_code.protocol import llm_param, message, model
|
|
@@ -64,11 +69,10 @@ class AnthropicStreamStateManager:
|
|
|
64
69
|
|
|
65
70
|
def __init__(self, model_id: str) -> None:
|
|
66
71
|
self.model_id = model_id
|
|
67
|
-
self.
|
|
68
|
-
self.accumulated_content: list[str] = []
|
|
69
|
-
self.parts: list[message.Part] = []
|
|
72
|
+
self.assistant_parts: list[message.Part] = []
|
|
70
73
|
self.response_id: str | None = None
|
|
71
|
-
self.
|
|
74
|
+
self._pending_signature: str | None = None
|
|
75
|
+
self._pending_signature_thinking_index: int | None = None
|
|
72
76
|
self.stop_reason: model.StopReason | None = None
|
|
73
77
|
|
|
74
78
|
# Tool call state
|
|
@@ -80,34 +84,59 @@ class AnthropicStreamStateManager:
|
|
|
80
84
|
self.input_token: int = 0
|
|
81
85
|
self.cached_token: int = 0
|
|
82
86
|
|
|
83
|
-
def
|
|
84
|
-
"""
|
|
85
|
-
|
|
87
|
+
def append_thinking_text(self, text: str) -> None:
|
|
88
|
+
"""Append thinking text, merging with the previous ThinkingTextPart when possible."""
|
|
89
|
+
index = append_thinking_text_part(self.assistant_parts, text, model_id=self.model_id)
|
|
90
|
+
if index is not None:
|
|
91
|
+
self._pending_signature_thinking_index = index
|
|
92
|
+
|
|
93
|
+
def append_text(self, text: str) -> None:
|
|
94
|
+
"""Append assistant text, merging with the previous TextPart when possible."""
|
|
95
|
+
append_text_part(self.assistant_parts, text)
|
|
96
|
+
|
|
97
|
+
def set_pending_signature(self, signature: str) -> None:
|
|
98
|
+
if signature:
|
|
99
|
+
self._pending_signature = signature
|
|
100
|
+
|
|
101
|
+
def flush_pending_signature(self) -> None:
|
|
102
|
+
"""Attach any pending signature to the most recent thinking segment.
|
|
103
|
+
|
|
104
|
+
Anthropic's signature is semantically tied to its thinking content. The
|
|
105
|
+
signature delta may arrive slightly after thinking text, so we insert the
|
|
106
|
+
signature part adjacent to the thinking part it signs.
|
|
107
|
+
"""
|
|
108
|
+
|
|
109
|
+
if not self._pending_signature:
|
|
110
|
+
return
|
|
111
|
+
if self._pending_signature_thinking_index is None:
|
|
112
|
+
# No thinking part seen for this signature; drop it.
|
|
113
|
+
self._pending_signature = None
|
|
86
114
|
return
|
|
87
|
-
full_thinking = "".join(self.accumulated_thinking)
|
|
88
|
-
self.parts.append(message.ThinkingTextPart(text=full_thinking, model_id=self.model_id))
|
|
89
|
-
if self.pending_signature:
|
|
90
|
-
self.parts.append(
|
|
91
|
-
message.ThinkingSignaturePart(
|
|
92
|
-
signature=self.pending_signature,
|
|
93
|
-
model_id=self.model_id,
|
|
94
|
-
format="anthropic",
|
|
95
|
-
)
|
|
96
|
-
)
|
|
97
|
-
self.accumulated_thinking.clear()
|
|
98
|
-
self.pending_signature = None
|
|
99
115
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
if
|
|
116
|
+
insert_at = self._pending_signature_thinking_index + 1
|
|
117
|
+
# Avoid inserting duplicates if flush is called multiple times.
|
|
118
|
+
if insert_at < len(self.assistant_parts) and isinstance(
|
|
119
|
+
self.assistant_parts[insert_at], message.ThinkingSignaturePart
|
|
120
|
+
):
|
|
121
|
+
self._pending_signature = None
|
|
103
122
|
return
|
|
104
|
-
|
|
105
|
-
self.
|
|
123
|
+
|
|
124
|
+
self.assistant_parts.insert(
|
|
125
|
+
insert_at,
|
|
126
|
+
message.ThinkingSignaturePart(
|
|
127
|
+
signature=self._pending_signature,
|
|
128
|
+
model_id=self.model_id,
|
|
129
|
+
format="anthropic",
|
|
130
|
+
),
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
self._pending_signature = None
|
|
134
|
+
self._pending_signature_thinking_index = None
|
|
106
135
|
|
|
107
136
|
def flush_tool_call(self) -> None:
|
|
108
137
|
"""Flush current tool call into parts."""
|
|
109
138
|
if self.current_tool_name and self.current_tool_call_id:
|
|
110
|
-
self.
|
|
139
|
+
self.assistant_parts.append(
|
|
111
140
|
message.ToolCallPart(
|
|
112
141
|
call_id=self.current_tool_call_id,
|
|
113
142
|
tool_name=self.current_tool_name,
|
|
@@ -119,11 +148,17 @@ class AnthropicStreamStateManager:
|
|
|
119
148
|
self.current_tool_inputs = None
|
|
120
149
|
|
|
121
150
|
def flush_all(self) -> list[message.Part]:
|
|
122
|
-
"""Flush all
|
|
123
|
-
self.
|
|
124
|
-
self.flush_content()
|
|
151
|
+
"""Flush all pending content in order and return parts."""
|
|
152
|
+
self.flush_pending_signature()
|
|
125
153
|
self.flush_tool_call()
|
|
126
|
-
return list(self.
|
|
154
|
+
return list(self.assistant_parts)
|
|
155
|
+
|
|
156
|
+
def get_partial_parts(self) -> list[message.Part]:
|
|
157
|
+
"""Get accumulated parts excluding tool calls, with thinking degraded.
|
|
158
|
+
|
|
159
|
+
Filters out ToolCallPart and applies degrade_thinking_to_text.
|
|
160
|
+
"""
|
|
161
|
+
return build_partial_parts(self.assistant_parts)
|
|
127
162
|
|
|
128
163
|
def get_partial_message(self) -> message.AssistantMessage | None:
|
|
129
164
|
"""Build a partial AssistantMessage from accumulated state.
|
|
@@ -131,16 +166,7 @@ class AnthropicStreamStateManager:
|
|
|
131
166
|
Flushes all accumulated content and returns the message with
|
|
132
167
|
stop_reason="aborted". Returns None if no content has been accumulated.
|
|
133
168
|
"""
|
|
134
|
-
self.
|
|
135
|
-
self.flush_content()
|
|
136
|
-
parts = degrade_thinking_to_text(list(self.parts))
|
|
137
|
-
if not parts:
|
|
138
|
-
return None
|
|
139
|
-
return message.AssistantMessage(
|
|
140
|
-
parts=parts,
|
|
141
|
-
response_id=self.response_id,
|
|
142
|
-
stop_reason="aborted",
|
|
143
|
-
)
|
|
169
|
+
return build_partial_message(self.assistant_parts, response_id=self.response_id)
|
|
144
170
|
|
|
145
171
|
|
|
146
172
|
def build_payload(
|
|
@@ -226,17 +252,18 @@ async def parse_anthropic_stream(
|
|
|
226
252
|
case BetaThinkingDelta() as delta:
|
|
227
253
|
if delta.thinking:
|
|
228
254
|
metadata_tracker.record_token()
|
|
229
|
-
state.
|
|
255
|
+
state.append_thinking_text(delta.thinking)
|
|
230
256
|
yield message.ThinkingTextDelta(
|
|
231
257
|
content=delta.thinking,
|
|
232
258
|
response_id=state.response_id,
|
|
233
259
|
)
|
|
234
260
|
case BetaSignatureDelta() as delta:
|
|
235
|
-
state.
|
|
261
|
+
state.set_pending_signature(delta.signature)
|
|
236
262
|
case BetaTextDelta() as delta:
|
|
237
263
|
if delta.text:
|
|
238
264
|
metadata_tracker.record_token()
|
|
239
|
-
state.
|
|
265
|
+
state.flush_pending_signature()
|
|
266
|
+
state.append_text(delta.text)
|
|
240
267
|
yield message.AssistantTextDelta(
|
|
241
268
|
content=delta.text,
|
|
242
269
|
response_id=state.response_id,
|
|
@@ -251,6 +278,7 @@ async def parse_anthropic_stream(
|
|
|
251
278
|
match event.content_block:
|
|
252
279
|
case BetaToolUseBlock() as block:
|
|
253
280
|
metadata_tracker.record_token()
|
|
281
|
+
state.flush_pending_signature()
|
|
254
282
|
yield message.ToolCallStartDelta(
|
|
255
283
|
response_id=state.response_id,
|
|
256
284
|
call_id=block.id,
|
|
@@ -262,12 +290,7 @@ async def parse_anthropic_stream(
|
|
|
262
290
|
case _:
|
|
263
291
|
pass
|
|
264
292
|
case BetaRawContentBlockStopEvent():
|
|
265
|
-
|
|
266
|
-
metadata_tracker.record_token()
|
|
267
|
-
state.flush_thinking()
|
|
268
|
-
if state.accumulated_content:
|
|
269
|
-
metadata_tracker.record_token()
|
|
270
|
-
state.flush_content()
|
|
293
|
+
state.flush_pending_signature()
|
|
271
294
|
if state.current_tool_name and state.current_tool_call_id:
|
|
272
295
|
metadata_tracker.record_token()
|
|
273
296
|
state.flush_tool_call()
|
|
@@ -337,8 +360,10 @@ class AnthropicLLMStream(LLMStreamABC):
|
|
|
337
360
|
self._metadata_tracker.set_model_name(str(self._param.model_id))
|
|
338
361
|
self._metadata_tracker.set_response_id(self._state.response_id)
|
|
339
362
|
metadata = self._metadata_tracker.finalize()
|
|
363
|
+
# Use accumulated parts for potential prefill on retry
|
|
364
|
+
self._state.flush_all()
|
|
340
365
|
yield message.AssistantMessage(
|
|
341
|
-
parts=
|
|
366
|
+
parts=self._state.get_partial_parts(),
|
|
342
367
|
response_id=self._state.response_id,
|
|
343
368
|
usage=metadata,
|
|
344
369
|
stop_reason="error",
|