klaude-code 2.10.3__tar.gz → 2.10.4__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.10.3 → klaude_code-2.10.4}/PKG-INFO +1 -1
- {klaude_code-2.10.3 → klaude_code-2.10.4}/pyproject.toml +1 -1
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/auth/AGENTS.md +4 -24
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/auth/__init__.py +1 -17
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/cli/auth_cmd.py +3 -53
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/cli/list_model.py +0 -50
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/config/assets/builtin_config.yaml +0 -28
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/config/config.py +5 -42
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/const.py +5 -2
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/agent_profile.py +2 -10
- klaude_code-2.10.4/src/klaude_code/core/backtrack/__init__.py +3 -0
- klaude_code-2.10.4/src/klaude_code/core/backtrack/manager.py +48 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/memory.py +25 -9
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/task.py +53 -7
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/__init__.py +2 -0
- klaude_code-2.10.4/src/klaude_code/core/tool/backtrack/__init__.py +3 -0
- klaude_code-2.10.4/src/klaude_code/core/tool/backtrack/backtrack_tool.md +17 -0
- klaude_code-2.10.4/src/klaude_code/core/tool/backtrack/backtrack_tool.py +65 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/context.py +5 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/turn.py +3 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/llm/input_common.py +70 -1
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/llm/openai_compatible/input.py +5 -2
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/llm/openrouter/input.py +5 -2
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/llm/registry.py +0 -1
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/protocol/events.py +10 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/protocol/llm_param.py +0 -1
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/protocol/message.py +10 -1
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/protocol/tools.py +1 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/session/session.py +111 -2
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/session/store.py +2 -0
- klaude_code-2.10.4/src/klaude_code/skill/assets/executing-plans/SKILL.md +84 -0
- klaude_code-2.10.4/src/klaude_code/skill/assets/writing-plans/SKILL.md +116 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/commands.py +15 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/components/developer.py +1 -1
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/components/rich/status.py +7 -76
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/components/rich/theme.py +10 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/components/tools.py +31 -18
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/display.py +4 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/input/prompt_toolkit.py +15 -1
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/machine.py +26 -8
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/renderer.py +97 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/runner.py +7 -2
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/terminal/image.py +28 -12
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/ui/terminal/title.py +8 -3
- klaude_code-2.10.3/src/klaude_code/auth/antigravity/__init__.py +0 -20
- klaude_code-2.10.3/src/klaude_code/auth/antigravity/exceptions.py +0 -17
- klaude_code-2.10.3/src/klaude_code/auth/antigravity/oauth.py +0 -315
- klaude_code-2.10.3/src/klaude_code/auth/antigravity/pkce.py +0 -25
- klaude_code-2.10.3/src/klaude_code/auth/antigravity/token_manager.py +0 -27
- klaude_code-2.10.3/src/klaude_code/core/prompts/prompt-antigravity.md +0 -80
- klaude_code-2.10.3/src/klaude_code/llm/antigravity/__init__.py +0 -3
- klaude_code-2.10.3/src/klaude_code/llm/antigravity/client.py +0 -558
- klaude_code-2.10.3/src/klaude_code/llm/antigravity/input.py +0 -268
- klaude_code-2.10.3/src/klaude_code/skill/assets/create-plan/SKILL.md +0 -74
- {klaude_code-2.10.3 → klaude_code-2.10.4}/README.md +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/.DS_Store +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/app/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/app/runtime.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/auth/base.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/auth/claude/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/auth/claude/exceptions.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/auth/claude/oauth.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/auth/claude/token_manager.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/auth/codex/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/auth/codex/exceptions.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/auth/codex/jwt_utils.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/auth/codex/oauth.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/auth/codex/token_manager.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/auth/env.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/cli/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/cli/config_cmd.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/cli/cost_cmd.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/cli/debug.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/cli/main.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/cli/self_update.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/config/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/config/assets/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/config/builtin_config.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/config/model_matcher.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/config/sub_agent_model_helper.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/config/thinking.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/agent.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/bash_mode.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/compaction/AGENTS.md +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/compaction/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/compaction/compaction.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/compaction/overflow.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/compaction/prompts.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/executor.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/loaded_skills.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/manager/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/manager/llm_clients.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/manager/llm_clients_builder.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/manager/sub_agent_manager.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/prompts/prompt-claude-code.md +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/prompts/prompt-codex-gpt-5-2-codex.md +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/prompts/prompt-codex-gpt-5-2.md +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/prompts/prompt-codex.md +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/prompts/prompt-gemini.md +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/prompts/prompt-minimal.md +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/prompts/prompt-sub-agent-explore.md +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/prompts/prompt-sub-agent-image-gen.md +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/prompts/prompt-sub-agent-web.md +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/prompts/prompt-sub-agent.md +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/reminders.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/file/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/file/_utils.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/file/apply_patch.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/file/apply_patch_tool.md +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/file/apply_patch_tool.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/file/diff_builder.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/file/edit_tool.md +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/file/edit_tool.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/file/read_tool.md +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/file/read_tool.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/file/write_tool.md +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/file/write_tool.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/offload.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/report_back_tool.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/shell/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/shell/bash_tool.md +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/shell/bash_tool.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/shell/command_safety.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/sub_agent/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/sub_agent/image_gen.md +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/sub_agent/image_gen.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/sub_agent/task.md +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/sub_agent/task.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/todo/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/todo/todo_write_tool.md +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/todo/todo_write_tool.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/todo/todo_write_tool_raw.md +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/todo/update_plan_tool.md +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/todo/update_plan_tool.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/tool_abc.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/tool_registry.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/tool_runner.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/web/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/web/mermaid_tool.md +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/web/mermaid_tool.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/web/web_fetch_tool.md +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/web/web_fetch_tool.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/web/web_search_tool.md +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/core/tool/web/web_search_tool.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/llm/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/llm/anthropic/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/llm/anthropic/client.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/llm/anthropic/input.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/llm/bedrock_anthropic/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/llm/bedrock_anthropic/client.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/llm/claude/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/llm/claude/client.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/llm/client.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/llm/google/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/llm/google/client.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/llm/google/input.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/llm/image.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/llm/json_stable.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/llm/openai_codex/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/llm/openai_codex/client.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/llm/openai_compatible/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/llm/openai_compatible/client.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/llm/openai_compatible/stream.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/llm/openai_responses/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/llm/openai_responses/client.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/llm/openai_responses/input.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/llm/openrouter/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/llm/openrouter/client.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/llm/openrouter/reasoning.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/llm/partial_message.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/llm/stream_parts.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/llm/usage.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/log.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/protocol/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/protocol/commands.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/protocol/model.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/protocol/op.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/protocol/op_handler.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/protocol/sub_agent/AGENTS.md +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/protocol/sub_agent/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/protocol/sub_agent/explore.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/protocol/sub_agent/image_gen.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/protocol/sub_agent/task.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/protocol/sub_agent/web.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/session/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/session/codec.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/session/export.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/session/selector.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/session/templates/export_session.html +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/session/templates/mermaid_viewer.html +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/skill/.DS_Store +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/skill/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/skill/assets/.DS_Store +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/skill/assets/deslop/SKILL.md +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/skill/assets/handoff/SKILL.md +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/skill/assets/skill-creator/SKILL.md +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/skill/loader.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/skill/manager.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/skill/system_skills.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/command/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/command/clear_cmd.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/command/command_abc.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/command/compact_cmd.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/command/continue_cmd.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/command/copy_cmd.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/command/debug_cmd.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/command/export_cmd.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/command/export_online_cmd.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/command/fork_session_cmd.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/command/model_cmd.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/command/model_picker.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/command/prompt-init.md +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/command/prompt_command.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/command/refresh_cmd.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/command/registry.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/command/resume_cmd.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/command/status_cmd.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/command/sub_agent_model_cmd.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/command/thinking_cmd.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/components/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/components/bash_syntax.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/components/command_output.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/components/common.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/components/diffs.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/components/errors.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/components/mermaid_viewer.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/components/metadata.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/components/rich/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/components/rich/cjk_wrap.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/components/rich/code_panel.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/components/rich/live.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/components/rich/markdown.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/components/rich/quote.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/components/sub_agent.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/components/thinking.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/components/user_input.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/components/welcome.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/input/AGENTS.md +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/input/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/input/completers.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/input/drag_drop.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/input/images.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/input/key_bindings.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/input/paste.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/terminal/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/terminal/color.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/terminal/control.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/terminal/notifier.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/terminal/progress_bar.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/tui/terminal/selector.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/ui/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/ui/common.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/ui/core/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/ui/core/display.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/ui/core/input.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/ui/debug_mode.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/ui/terminal/__init__.py +0 -0
- {klaude_code-2.10.3 → klaude_code-2.10.4}/src/klaude_code/update.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Adding a New OAuth Provider
|
|
2
2
|
|
|
3
|
-
This document describes all the files and changes required to add a new OAuth-based authentication provider (like `
|
|
3
|
+
This document describes all the files and changes required to add a new OAuth-based authentication provider (like `codex` or `claude`).
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
@@ -25,7 +25,7 @@ Add the new protocol to the `LLMClientProtocol` enum:
|
|
|
25
25
|
```python
|
|
26
26
|
class LLMClientProtocol(Enum):
|
|
27
27
|
# ... existing protocols ...
|
|
28
|
-
|
|
28
|
+
NEW_PROVIDER = "new_provider" # Add new protocol
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
---
|
|
@@ -171,26 +171,8 @@ def is_api_key_missing(self) -> bool:
|
|
|
171
171
|
return state is None
|
|
172
172
|
```
|
|
173
173
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
Add the protocol to the "no API key required" set:
|
|
177
|
-
|
|
178
|
-
```python
|
|
179
|
-
if (
|
|
180
|
-
provider.protocol
|
|
181
|
-
not in {
|
|
182
|
-
llm_param.LLMClientProtocol.CODEX_OAUTH,
|
|
183
|
-
llm_param.LLMClientProtocol.CLAUDE_OAUTH,
|
|
184
|
-
llm_param.LLMClientProtocol.<PROVIDER>, # Add here
|
|
185
|
-
llm_param.LLMClientProtocol.BEDROCK,
|
|
186
|
-
}
|
|
187
|
-
and not api_key
|
|
188
|
-
):
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
#### `Config.get_model_config()`
|
|
192
|
-
|
|
193
|
-
Same change as above - add protocol to the set.
|
|
174
|
+
Note: `resolve_model_location_prefer_available()` and `get_model_config()` both use
|
|
175
|
+
`is_api_key_missing()` internally, so no additional changes are needed in those methods.
|
|
194
176
|
|
|
195
177
|
---
|
|
196
178
|
|
|
@@ -317,8 +299,6 @@ When adding a new OAuth provider, ensure you've completed:
|
|
|
317
299
|
- [ ] Create `llm/<provider>/` module (input, client, __init__)
|
|
318
300
|
- [ ] Register protocol in `llm/registry.py`
|
|
319
301
|
- [ ] Update `config.py` - `is_api_key_missing()` method
|
|
320
|
-
- [ ] Update `config.py` - `resolve_model_location_prefer_available()` method
|
|
321
|
-
- [ ] Update `config.py` - `get_model_config()` method
|
|
322
302
|
- [ ] Update `auth_cmd.py` - provider selection, login, logout
|
|
323
303
|
- [ ] Update `list_model.py` - status display function and panel
|
|
324
304
|
- [ ] Add provider/models to `builtin_config.yaml`
|
|
@@ -1,17 +1,8 @@
|
|
|
1
1
|
"""Authentication module.
|
|
2
2
|
|
|
3
|
-
Includes
|
|
3
|
+
Includes OAuth helpers for various providers.
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
-
from klaude_code.auth.antigravity import (
|
|
7
|
-
AntigravityAuthError,
|
|
8
|
-
AntigravityAuthState,
|
|
9
|
-
AntigravityNotLoggedInError,
|
|
10
|
-
AntigravityOAuth,
|
|
11
|
-
AntigravityOAuthError,
|
|
12
|
-
AntigravityTokenExpiredError,
|
|
13
|
-
AntigravityTokenManager,
|
|
14
|
-
)
|
|
15
6
|
from klaude_code.auth.codex import (
|
|
16
7
|
CodexAuthError,
|
|
17
8
|
CodexAuthState,
|
|
@@ -29,13 +20,6 @@ from klaude_code.auth.env import (
|
|
|
29
20
|
)
|
|
30
21
|
|
|
31
22
|
__all__ = [
|
|
32
|
-
"AntigravityAuthError",
|
|
33
|
-
"AntigravityAuthState",
|
|
34
|
-
"AntigravityNotLoggedInError",
|
|
35
|
-
"AntigravityOAuth",
|
|
36
|
-
"AntigravityOAuthError",
|
|
37
|
-
"AntigravityTokenExpiredError",
|
|
38
|
-
"AntigravityTokenManager",
|
|
39
23
|
"CodexAuthError",
|
|
40
24
|
"CodexAuthState",
|
|
41
25
|
"CodexNotLoggedInError",
|
|
@@ -24,11 +24,6 @@ def _select_provider() -> str | None:
|
|
|
24
24
|
value="codex",
|
|
25
25
|
search_text="codex",
|
|
26
26
|
),
|
|
27
|
-
SelectItem(
|
|
28
|
-
title=[("", "Google Antigravity "), ("ansibrightblack", "[OAuth]\n")],
|
|
29
|
-
value="antigravity",
|
|
30
|
-
search_text="antigravity",
|
|
31
|
-
),
|
|
32
27
|
]
|
|
33
28
|
# Add API key options
|
|
34
29
|
for key_info in SUPPORTED_API_KEYS:
|
|
@@ -76,7 +71,7 @@ def _build_provider_help() -> str:
|
|
|
76
71
|
from klaude_code.config.builtin_config import SUPPORTED_API_KEYS
|
|
77
72
|
|
|
78
73
|
# Use first word of name for brevity (e.g., "google" instead of "google gemini")
|
|
79
|
-
names = ["codex", "claude"
|
|
74
|
+
names = ["codex", "claude"] + [k.name.split()[0].lower() for k in SUPPORTED_API_KEYS]
|
|
80
75
|
return f"Provider name ({', '.join(names)})"
|
|
81
76
|
|
|
82
77
|
|
|
@@ -154,39 +149,6 @@ def login_command(
|
|
|
154
149
|
except Exception as e:
|
|
155
150
|
log((f"Login failed: {e}", "red"))
|
|
156
151
|
raise typer.Exit(1) from None
|
|
157
|
-
case "antigravity":
|
|
158
|
-
from klaude_code.auth.antigravity.oauth import AntigravityOAuth
|
|
159
|
-
from klaude_code.auth.antigravity.token_manager import AntigravityTokenManager
|
|
160
|
-
|
|
161
|
-
token_manager = AntigravityTokenManager()
|
|
162
|
-
|
|
163
|
-
if token_manager.is_logged_in():
|
|
164
|
-
state = token_manager.get_state()
|
|
165
|
-
if state and not state.is_expired():
|
|
166
|
-
log(("You are already logged in to Antigravity.", "green"))
|
|
167
|
-
if state.email:
|
|
168
|
-
log(f" Email: {state.email}")
|
|
169
|
-
log(f" Project ID: {state.project_id}")
|
|
170
|
-
expires_dt = datetime.datetime.fromtimestamp(state.expires_at, tz=datetime.UTC)
|
|
171
|
-
log(f" Expires: {expires_dt.strftime('%Y-%m-%d %H:%M:%S UTC')}")
|
|
172
|
-
if not typer.confirm("Do you want to re-login?"):
|
|
173
|
-
return
|
|
174
|
-
|
|
175
|
-
log("Starting Antigravity OAuth login flow...")
|
|
176
|
-
log("A browser window will open for authentication.")
|
|
177
|
-
|
|
178
|
-
try:
|
|
179
|
-
oauth = AntigravityOAuth(token_manager)
|
|
180
|
-
state = oauth.login()
|
|
181
|
-
log(("Login successful!", "green"))
|
|
182
|
-
if state.email:
|
|
183
|
-
log(f" Email: {state.email}")
|
|
184
|
-
log(f" Project ID: {state.project_id}")
|
|
185
|
-
expires_dt = datetime.datetime.fromtimestamp(state.expires_at, tz=datetime.UTC)
|
|
186
|
-
log(f" Expires: {expires_dt.strftime('%Y-%m-%d %H:%M:%S UTC')}")
|
|
187
|
-
except Exception as e:
|
|
188
|
-
log((f"Login failed: {e}", "red"))
|
|
189
|
-
raise typer.Exit(1) from None
|
|
190
152
|
case _:
|
|
191
153
|
from klaude_code.config.builtin_config import SUPPORTED_API_KEYS
|
|
192
154
|
|
|
@@ -212,7 +174,7 @@ def login_command(
|
|
|
212
174
|
|
|
213
175
|
|
|
214
176
|
def logout_command(
|
|
215
|
-
provider: str = typer.Argument("codex", help="Provider to logout (codex|claude
|
|
177
|
+
provider: str = typer.Argument("codex", help="Provider to logout (codex|claude)"),
|
|
216
178
|
) -> None:
|
|
217
179
|
"""Logout from a provider."""
|
|
218
180
|
match provider.lower():
|
|
@@ -240,20 +202,8 @@ def logout_command(
|
|
|
240
202
|
if typer.confirm("Are you sure you want to logout from Claude?"):
|
|
241
203
|
token_manager.delete()
|
|
242
204
|
log(("Logged out from Claude.", "green"))
|
|
243
|
-
case "antigravity":
|
|
244
|
-
from klaude_code.auth.antigravity.token_manager import AntigravityTokenManager
|
|
245
|
-
|
|
246
|
-
token_manager = AntigravityTokenManager()
|
|
247
|
-
|
|
248
|
-
if not token_manager.is_logged_in():
|
|
249
|
-
log("You are not logged in to Antigravity.")
|
|
250
|
-
return
|
|
251
|
-
|
|
252
|
-
if typer.confirm("Are you sure you want to logout from Antigravity?"):
|
|
253
|
-
token_manager.delete()
|
|
254
|
-
log(("Logged out from Antigravity.", "green"))
|
|
255
205
|
case _:
|
|
256
|
-
log((f"Error: Unknown provider '{provider}'. Supported: codex, claude
|
|
206
|
+
log((f"Error: Unknown provider '{provider}'. Supported: codex, claude", "red"))
|
|
257
207
|
raise typer.Exit(1)
|
|
258
208
|
|
|
259
209
|
|
|
@@ -121,53 +121,6 @@ def _get_claude_status_rows() -> list[tuple[Text, Text]]:
|
|
|
121
121
|
return rows
|
|
122
122
|
|
|
123
123
|
|
|
124
|
-
def _get_antigravity_status_rows() -> list[tuple[Text, Text]]:
|
|
125
|
-
"""Get Antigravity OAuth login status as (label, value) tuples for table display."""
|
|
126
|
-
from klaude_code.auth.antigravity.token_manager import AntigravityTokenManager
|
|
127
|
-
|
|
128
|
-
rows: list[tuple[Text, Text]] = []
|
|
129
|
-
token_manager = AntigravityTokenManager()
|
|
130
|
-
state = token_manager.get_state()
|
|
131
|
-
|
|
132
|
-
if state is None:
|
|
133
|
-
rows.append(
|
|
134
|
-
(
|
|
135
|
-
Text("Status", style=ThemeKey.CONFIG_PARAM_LABEL),
|
|
136
|
-
Text.assemble(
|
|
137
|
-
("Not logged in", ThemeKey.CONFIG_STATUS_ERROR),
|
|
138
|
-
(" (run 'klaude login antigravity' to authenticate)", "dim"),
|
|
139
|
-
),
|
|
140
|
-
)
|
|
141
|
-
)
|
|
142
|
-
elif state.is_expired():
|
|
143
|
-
rows.append(
|
|
144
|
-
(
|
|
145
|
-
Text("Status", style=ThemeKey.CONFIG_PARAM_LABEL),
|
|
146
|
-
Text.assemble(
|
|
147
|
-
("Token expired", ThemeKey.CONFIG_STATUS_ERROR),
|
|
148
|
-
(" (will refresh automatically on use; run 'klaude login antigravity' if refresh fails)", "dim"),
|
|
149
|
-
),
|
|
150
|
-
)
|
|
151
|
-
)
|
|
152
|
-
else:
|
|
153
|
-
expires_dt = datetime.datetime.fromtimestamp(state.expires_at, tz=datetime.UTC)
|
|
154
|
-
email_info = f", email: {state.email}" if state.email else ""
|
|
155
|
-
rows.append(
|
|
156
|
-
(
|
|
157
|
-
Text("Status", style=ThemeKey.CONFIG_PARAM_LABEL),
|
|
158
|
-
Text.assemble(
|
|
159
|
-
("Logged in", ThemeKey.CONFIG_STATUS_OK),
|
|
160
|
-
(
|
|
161
|
-
f" (project: {state.project_id}{email_info}, expires: {expires_dt.strftime('%Y-%m-%d %H:%M UTC')})",
|
|
162
|
-
"dim",
|
|
163
|
-
),
|
|
164
|
-
),
|
|
165
|
-
)
|
|
166
|
-
)
|
|
167
|
-
|
|
168
|
-
return rows
|
|
169
|
-
|
|
170
|
-
|
|
171
124
|
def mask_api_key(api_key: str | None) -> str:
|
|
172
125
|
"""Mask API key to show only first 6 and last 6 characters with *** in between"""
|
|
173
126
|
if not api_key:
|
|
@@ -286,9 +239,6 @@ def _build_provider_info_panel(provider: ProviderConfig, available: bool, *, dis
|
|
|
286
239
|
if provider.protocol == LLMClientProtocol.CLAUDE_OAUTH:
|
|
287
240
|
for label, value in _get_claude_status_rows():
|
|
288
241
|
info_table.add_row(label, value)
|
|
289
|
-
if provider.protocol == LLMClientProtocol.ANTIGRAVITY:
|
|
290
|
-
for label, value in _get_antigravity_status_rows():
|
|
291
|
-
info_table.add_row(label, value)
|
|
292
242
|
|
|
293
243
|
return Quote(
|
|
294
244
|
Group(title, info_table),
|
|
@@ -341,32 +341,4 @@ provider_list:
|
|
|
341
341
|
cost: {input: 1.75, output: 14, cache_read: 0.17}
|
|
342
342
|
|
|
343
343
|
|
|
344
|
-
- provider_name: antigravity
|
|
345
|
-
protocol: antigravity
|
|
346
|
-
model_list:
|
|
347
|
-
- model_name: opus
|
|
348
|
-
model_id: claude-opus-4-5-thinking
|
|
349
|
-
context_limit: 200000
|
|
350
|
-
max_tokens: 64000
|
|
351
|
-
|
|
352
|
-
- model_name: sonnet
|
|
353
|
-
model_id: claude-sonnet-4-5
|
|
354
|
-
context_limit: 200000
|
|
355
|
-
max_tokens: 64000
|
|
356
|
-
|
|
357
|
-
- model_name: gemini-pro-high
|
|
358
|
-
model_id: gemini-3-pro-high
|
|
359
|
-
context_limit: 1048576
|
|
360
|
-
max_tokens: 65535
|
|
361
|
-
thinking:
|
|
362
|
-
reasoning_effort: high
|
|
363
|
-
|
|
364
|
-
- model_name: gemini-flash
|
|
365
|
-
model_id: gemini-3-flash
|
|
366
|
-
context_limit: 1048576
|
|
367
|
-
max_tokens: 65535
|
|
368
|
-
thinking:
|
|
369
|
-
reasoning_effort: medium
|
|
370
|
-
|
|
371
|
-
|
|
372
344
|
compact_model: gemini-flash
|
|
@@ -101,15 +101,6 @@ class ProviderConfig(llm_param.LLMConfigProviderParameter):
|
|
|
101
101
|
# Consider available if logged in. Token refresh happens on-demand.
|
|
102
102
|
return state is None
|
|
103
103
|
|
|
104
|
-
if self.protocol == LLMClientProtocol.ANTIGRAVITY:
|
|
105
|
-
# Antigravity uses OAuth authentication, not API key
|
|
106
|
-
from klaude_code.auth.antigravity.token_manager import AntigravityTokenManager
|
|
107
|
-
|
|
108
|
-
token_manager = AntigravityTokenManager()
|
|
109
|
-
state = token_manager.get_state()
|
|
110
|
-
# Consider available if logged in. Token refresh happens on-demand.
|
|
111
|
-
return state is None
|
|
112
|
-
|
|
113
104
|
if self.protocol == LLMClientProtocol.BEDROCK:
|
|
114
105
|
# Bedrock uses AWS credentials, not API key. Region is always required.
|
|
115
106
|
_, resolved_profile = parse_env_var_syntax(self.aws_profile)
|
|
@@ -275,8 +266,7 @@ class Config(BaseModel):
|
|
|
275
266
|
def resolve_model_location_prefer_available(self, model_selector: str) -> tuple[str, str] | None:
|
|
276
267
|
"""Resolve a selector to (model_name, provider_name), preferring usable providers.
|
|
277
268
|
|
|
278
|
-
This uses the same availability logic as :meth:`get_model_config
|
|
279
|
-
presence for non-OAuth protocols).
|
|
269
|
+
This uses the same availability logic as :meth:`get_model_config`.
|
|
280
270
|
"""
|
|
281
271
|
|
|
282
272
|
requested_model, requested_provider = self._split_model_selector(model_selector)
|
|
@@ -285,20 +275,7 @@ class Config(BaseModel):
|
|
|
285
275
|
if requested_provider is not None and provider.provider_name.casefold() != requested_provider.casefold():
|
|
286
276
|
continue
|
|
287
277
|
|
|
288
|
-
if provider.disabled:
|
|
289
|
-
continue
|
|
290
|
-
|
|
291
|
-
api_key = provider.get_resolved_api_key()
|
|
292
|
-
if (
|
|
293
|
-
provider.protocol
|
|
294
|
-
not in {
|
|
295
|
-
llm_param.LLMClientProtocol.CODEX_OAUTH,
|
|
296
|
-
llm_param.LLMClientProtocol.CLAUDE_OAUTH,
|
|
297
|
-
llm_param.LLMClientProtocol.ANTIGRAVITY,
|
|
298
|
-
llm_param.LLMClientProtocol.BEDROCK,
|
|
299
|
-
}
|
|
300
|
-
and not api_key
|
|
301
|
-
):
|
|
278
|
+
if provider.disabled or provider.is_api_key_missing():
|
|
302
279
|
continue
|
|
303
280
|
|
|
304
281
|
for model in provider.model_list:
|
|
@@ -322,24 +299,10 @@ class Config(BaseModel):
|
|
|
322
299
|
raise ValueError(f"Provider '{provider.provider_name}' is disabled for: {model_name}")
|
|
323
300
|
continue
|
|
324
301
|
|
|
325
|
-
|
|
326
|
-
api_key = provider.get_resolved_api_key()
|
|
327
|
-
|
|
328
|
-
# Some protocols do not use API keys for authentication.
|
|
329
|
-
if (
|
|
330
|
-
provider.protocol
|
|
331
|
-
not in {
|
|
332
|
-
llm_param.LLMClientProtocol.CODEX_OAUTH,
|
|
333
|
-
llm_param.LLMClientProtocol.CLAUDE_OAUTH,
|
|
334
|
-
llm_param.LLMClientProtocol.ANTIGRAVITY,
|
|
335
|
-
llm_param.LLMClientProtocol.BEDROCK,
|
|
336
|
-
}
|
|
337
|
-
and not api_key
|
|
338
|
-
):
|
|
339
|
-
# When provider is explicitly requested, fail fast with a clearer error.
|
|
302
|
+
if provider.is_api_key_missing():
|
|
340
303
|
if requested_provider is not None:
|
|
341
304
|
raise ValueError(
|
|
342
|
-
f"Provider '{provider.provider_name}' is not available (missing
|
|
305
|
+
f"Provider '{provider.provider_name}' is not available (missing credentials) for: {model_name}"
|
|
343
306
|
)
|
|
344
307
|
continue
|
|
345
308
|
|
|
@@ -355,7 +318,7 @@ class Config(BaseModel):
|
|
|
355
318
|
break
|
|
356
319
|
|
|
357
320
|
provider_dump = provider.model_dump(exclude={"model_list", "disabled"})
|
|
358
|
-
provider_dump["api_key"] =
|
|
321
|
+
provider_dump["api_key"] = provider.get_resolved_api_key()
|
|
359
322
|
return llm_param.LLMConfigParameter(
|
|
360
323
|
**provider_dump,
|
|
361
324
|
**model.model_dump(exclude={"model_name"}),
|
|
@@ -141,7 +141,9 @@ MIN_HIDDEN_LINES_FOR_INDICATOR = 5 # Minimum hidden lines before showing trunca
|
|
|
141
141
|
SUB_AGENT_RESULT_MAX_LINES = 10 # Maximum lines for sub-agent result display
|
|
142
142
|
TRUNCATE_HEAD_MAX_LINES = 2 # Maximum lines for sub-agent error display
|
|
143
143
|
BASH_OUTPUT_PANEL_THRESHOLD = 10 # Bash output line threshold for CodePanel display
|
|
144
|
-
BASH_MULTILINE_STRING_TRUNCATE_MAX_LINES =
|
|
144
|
+
BASH_MULTILINE_STRING_TRUNCATE_MAX_LINES = (
|
|
145
|
+
20 # Max lines shown for heredoc / multiline string tokens in bash tool calls
|
|
146
|
+
)
|
|
145
147
|
URL_TRUNCATE_MAX_LENGTH = 400 # Maximum length for URL truncation in display
|
|
146
148
|
QUERY_DISPLAY_TRUNCATE_LENGTH = 80 # Maximum length for search query display
|
|
147
149
|
NOTIFY_COMPACT_LIMIT = 160 # Maximum length for notification body text
|
|
@@ -169,7 +171,7 @@ STATUS_HINT_TEXT = " (esc to interrupt)" # Status hint text shown after spinner
|
|
|
169
171
|
# Spinner status texts
|
|
170
172
|
STATUS_WAITING_TEXT = "Loading …"
|
|
171
173
|
STATUS_THINKING_TEXT = "Thinking …"
|
|
172
|
-
STATUS_COMPOSING_TEXT = "
|
|
174
|
+
STATUS_COMPOSING_TEXT = "Typing"
|
|
173
175
|
STATUS_COMPACTING_TEXT = "Compacting"
|
|
174
176
|
STATUS_RUNNING_TEXT = "Running …"
|
|
175
177
|
|
|
@@ -177,6 +179,7 @@ STATUS_RUNNING_TEXT = "Running …"
|
|
|
177
179
|
STATUS_DEFAULT_TEXT = STATUS_WAITING_TEXT
|
|
178
180
|
SIGINT_DOUBLE_PRESS_EXIT_TEXT = "Press ctrl+c again to exit" # Toast shown on first Ctrl+C during task waits
|
|
179
181
|
SPINNER_BREATH_PERIOD_SECONDS: float = 2.0 # Spinner breathing animation period (seconds)
|
|
182
|
+
STATUS_SHIMMER_ENABLED = True # Enable shimmer effect on status text
|
|
180
183
|
STATUS_SHIMMER_PADDING = 10 # Horizontal padding for shimmer band position
|
|
181
184
|
STATUS_SHIMMER_BAND_HALF_WIDTH = 5.0 # Half-width of shimmer band in characters
|
|
182
185
|
STATUS_SHIMMER_ALPHA_SCALE = 0.7 # Scale factor for shimmer intensity
|
|
@@ -52,10 +52,6 @@ COMMAND_DESCRIPTIONS: dict[str, str] = {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
|
|
55
|
-
# Prompt for antigravity protocol - used exactly as-is without any additions.
|
|
56
|
-
ANTIGRAVITY_PROMPT_PATH = "prompts/prompt-antigravity.md"
|
|
57
|
-
|
|
58
|
-
|
|
59
55
|
STRUCTURED_OUTPUT_PROMPT_FOR_SUB_AGENT = """\
|
|
60
56
|
|
|
61
57
|
# Structured Output
|
|
@@ -130,10 +126,6 @@ def load_system_prompt(
|
|
|
130
126
|
) -> str:
|
|
131
127
|
"""Get system prompt content for the given model and sub-agent type."""
|
|
132
128
|
|
|
133
|
-
# For antigravity protocol, use exact prompt without any additions.
|
|
134
|
-
if protocol == llm_param.LLMClientProtocol.ANTIGRAVITY:
|
|
135
|
-
return _load_prompt_by_path(ANTIGRAVITY_PROMPT_PATH)
|
|
136
|
-
|
|
137
129
|
if sub_agent_type is not None:
|
|
138
130
|
profile = get_sub_agent_profile(sub_agent_type)
|
|
139
131
|
base_prompt = _load_prompt_by_path(profile.prompt_file)
|
|
@@ -169,9 +161,9 @@ def load_agent_tools(
|
|
|
169
161
|
|
|
170
162
|
# Main agent tools
|
|
171
163
|
if "gpt-5" in model_name:
|
|
172
|
-
tool_names: list[str] = [tools.BASH, tools.READ, tools.APPLY_PATCH, tools.UPDATE_PLAN]
|
|
164
|
+
tool_names: list[str] = [tools.BASH, tools.READ, tools.APPLY_PATCH, tools.UPDATE_PLAN, tools.BACKTRACK]
|
|
173
165
|
else:
|
|
174
|
-
tool_names = [tools.BASH, tools.READ, tools.EDIT, tools.WRITE, tools.TODO_WRITE]
|
|
166
|
+
tool_names = [tools.BASH, tools.READ, tools.EDIT, tools.WRITE, tools.TODO_WRITE, tools.BACKTRACK]
|
|
175
167
|
|
|
176
168
|
tool_names.append(tools.TASK)
|
|
177
169
|
if config is not None:
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
@dataclass
|
|
5
|
+
class BacktrackRequest:
|
|
6
|
+
checkpoint_id: int
|
|
7
|
+
note: str
|
|
8
|
+
rationale: str
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class BacktrackManager:
|
|
12
|
+
"""Manage backtrack requests and checkpoint metadata for a task run."""
|
|
13
|
+
|
|
14
|
+
def __init__(self) -> None:
|
|
15
|
+
self._pending: BacktrackRequest | None = None
|
|
16
|
+
self._n_checkpoints: int = 0
|
|
17
|
+
self._checkpoint_user_messages: dict[int, str] = {}
|
|
18
|
+
|
|
19
|
+
def set_n_checkpoints(self, n: int) -> None:
|
|
20
|
+
self._n_checkpoints = n
|
|
21
|
+
|
|
22
|
+
@property
|
|
23
|
+
def n_checkpoints(self) -> int:
|
|
24
|
+
return self._n_checkpoints
|
|
25
|
+
|
|
26
|
+
def sync_checkpoints(self, checkpoints: dict[int, str]) -> None:
|
|
27
|
+
self._checkpoint_user_messages = dict(checkpoints)
|
|
28
|
+
|
|
29
|
+
def register_checkpoint(self, checkpoint_id: int, user_message: str) -> None:
|
|
30
|
+
self._checkpoint_user_messages[checkpoint_id] = user_message
|
|
31
|
+
|
|
32
|
+
def get_checkpoint_user_message(self, checkpoint_id: int) -> str | None:
|
|
33
|
+
return self._checkpoint_user_messages.get(checkpoint_id)
|
|
34
|
+
|
|
35
|
+
def send_backtrack(self, checkpoint_id: int, note: str, rationale: str) -> str:
|
|
36
|
+
if self._pending is not None:
|
|
37
|
+
raise ValueError("Only one backtrack can be pending at a time")
|
|
38
|
+
if checkpoint_id < 0 or checkpoint_id >= self._n_checkpoints:
|
|
39
|
+
raise ValueError(f"Invalid checkpoint {checkpoint_id}, available: 0-{self._n_checkpoints - 1}")
|
|
40
|
+
if checkpoint_id not in self._checkpoint_user_messages:
|
|
41
|
+
raise ValueError("Checkpoint is no longer available")
|
|
42
|
+
self._pending = BacktrackRequest(checkpoint_id=checkpoint_id, note=note, rationale=rationale)
|
|
43
|
+
return "Backtrack scheduled"
|
|
44
|
+
|
|
45
|
+
def fetch_pending(self) -> BacktrackRequest | None:
|
|
46
|
+
pending = self._pending
|
|
47
|
+
self._pending = None
|
|
48
|
+
return pending
|
|
@@ -9,7 +9,7 @@ from pathlib import Path
|
|
|
9
9
|
|
|
10
10
|
from pydantic import BaseModel
|
|
11
11
|
|
|
12
|
-
MEMORY_FILE_NAMES = ["
|
|
12
|
+
MEMORY_FILE_NAMES = ["AGENTS.md", "CLAUDE.md", "AGENT.md"]
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
class Memory(BaseModel):
|
|
@@ -36,12 +36,20 @@ def get_memory_paths(*, work_dir: Path) -> list[tuple[Path, str]]:
|
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
def get_existing_memory_files(*, work_dir: Path) -> dict[str, list[str]]:
|
|
39
|
-
"""Return existing memory file paths grouped by location (user/project).
|
|
39
|
+
"""Return existing memory file paths grouped by location (user/project).
|
|
40
|
+
|
|
41
|
+
Only one memory file per directory is loaded, with priority: AGENTS.md > CLAUDE.md > AGENT.md
|
|
42
|
+
"""
|
|
40
43
|
result: dict[str, list[str]] = {"user": [], "project": []}
|
|
41
44
|
work_dir = work_dir.resolve()
|
|
45
|
+
seen_dirs: set[Path] = set()
|
|
42
46
|
|
|
43
47
|
for memory_path, _instruction in get_memory_paths(work_dir=work_dir):
|
|
48
|
+
parent = memory_path.parent.resolve()
|
|
49
|
+
if parent in seen_dirs:
|
|
50
|
+
continue
|
|
44
51
|
if memory_path.exists() and memory_path.is_file():
|
|
52
|
+
seen_dirs.add(parent)
|
|
45
53
|
path_str = str(memory_path)
|
|
46
54
|
resolved = memory_path.resolve()
|
|
47
55
|
try:
|
|
@@ -87,6 +95,8 @@ def discover_memory_files_near_paths(
|
|
|
87
95
|
) -> list[Memory]:
|
|
88
96
|
"""Discover and load CLAUDE.md/AGENTS.md from directories containing accessed files.
|
|
89
97
|
|
|
98
|
+
Only one memory file per directory is loaded, with priority: AGENTS.md > CLAUDE.md > AGENT.md
|
|
99
|
+
|
|
90
100
|
Args:
|
|
91
101
|
paths: List of file paths that have been accessed.
|
|
92
102
|
is_memory_loaded: Callback to check if a memory file is already loaded.
|
|
@@ -97,7 +107,7 @@ def discover_memory_files_near_paths(
|
|
|
97
107
|
"""
|
|
98
108
|
memories: list[Memory] = []
|
|
99
109
|
work_dir = work_dir.resolve()
|
|
100
|
-
|
|
110
|
+
seen_dirs: set[Path] = set()
|
|
101
111
|
|
|
102
112
|
for p_str in paths:
|
|
103
113
|
p = Path(p_str)
|
|
@@ -117,24 +127,30 @@ def discover_memory_files_near_paths(
|
|
|
117
127
|
current_dir = work_dir
|
|
118
128
|
for part in rel_parts:
|
|
119
129
|
current_dir = current_dir / part
|
|
130
|
+
if current_dir in seen_dirs:
|
|
131
|
+
continue
|
|
132
|
+
# Check if any memory file in this directory was already loaded
|
|
133
|
+
dir_already_loaded = any(is_memory_loaded(str(current_dir / fname)) for fname in MEMORY_FILE_NAMES)
|
|
134
|
+
if dir_already_loaded:
|
|
135
|
+
seen_dirs.add(current_dir)
|
|
136
|
+
continue
|
|
137
|
+
# Load first existing memory file in priority order
|
|
120
138
|
for fname in MEMORY_FILE_NAMES:
|
|
121
139
|
mem_path = current_dir / fname
|
|
122
|
-
mem_path_str = str(mem_path)
|
|
123
|
-
if mem_path_str in seen_memory_files or is_memory_loaded(mem_path_str):
|
|
124
|
-
continue
|
|
125
140
|
if mem_path.exists() and mem_path.is_file():
|
|
126
141
|
try:
|
|
127
142
|
text = mem_path.read_text(encoding="utf-8", errors="replace")
|
|
128
143
|
except (PermissionError, UnicodeDecodeError, OSError):
|
|
129
144
|
continue
|
|
130
|
-
mark_memory_loaded(
|
|
131
|
-
|
|
145
|
+
mark_memory_loaded(str(mem_path))
|
|
146
|
+
seen_dirs.add(current_dir)
|
|
132
147
|
memories.append(
|
|
133
148
|
Memory(
|
|
134
|
-
path=
|
|
149
|
+
path=str(mem_path),
|
|
135
150
|
instruction="project instructions, discovered near last accessed path",
|
|
136
151
|
content=text,
|
|
137
152
|
)
|
|
138
153
|
)
|
|
154
|
+
break
|
|
139
155
|
|
|
140
156
|
return memories
|