klaude-code 2.4.2__tar.gz → 2.5.1__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.4.2 → klaude_code-2.5.1}/PKG-INFO +1 -1
- {klaude_code-2.4.2 → klaude_code-2.5.1}/pyproject.toml +1 -1
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/app/runtime.py +2 -6
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/cli/main.py +0 -1
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/config/assets/builtin_config.yaml +7 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/const.py +7 -4
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/agent.py +10 -1
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/agent_profile.py +47 -35
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/executor.py +6 -21
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/manager/sub_agent_manager.py +17 -1
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/prompts/prompt-sub-agent-web.md +4 -4
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/task.py +66 -4
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/tool/__init__.py +0 -5
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/tool/context.py +12 -1
- klaude_code-2.5.1/src/klaude_code/core/tool/offload.py +311 -0
- klaude_code-2.5.1/src/klaude_code/core/tool/shell/bash_tool.md +1 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/tool/sub_agent_tool.py +1 -0
- klaude_code-2.5.1/src/klaude_code/core/tool/todo/todo_write_tool.md +2 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/tool/tool_runner.py +14 -9
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/tool/web/web_fetch_tool.md +1 -1
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/tool/web/web_fetch_tool.py +14 -39
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/turn.py +127 -139
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/llm/anthropic/client.py +176 -82
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/llm/bedrock/client.py +8 -12
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/llm/claude/client.py +11 -15
- klaude_code-2.5.1/src/klaude_code/llm/client.py +63 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/llm/codex/client.py +7 -11
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/llm/google/client.py +150 -69
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/llm/openai_compatible/client.py +10 -15
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/llm/openai_compatible/stream.py +68 -6
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/llm/openrouter/client.py +9 -15
- klaude_code-2.5.1/src/klaude_code/llm/partial_message.py +35 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/llm/responses/client.py +134 -68
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/llm/usage.py +30 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/protocol/commands.py +0 -4
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/protocol/events/lifecycle.py +1 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/protocol/events/metadata.py +1 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/protocol/events/streaming.py +0 -1
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/protocol/events/system.py +0 -4
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/protocol/model.py +2 -15
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/protocol/sub_agent/explore.py +0 -10
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/protocol/sub_agent/image_gen.py +0 -7
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/protocol/sub_agent/task.py +0 -10
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/protocol/sub_agent/web.py +4 -12
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/session/templates/export_session.html +4 -4
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/skill/manager.py +2 -1
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/components/metadata.py +41 -49
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/components/rich/markdown.py +1 -3
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/components/rich/theme.py +2 -2
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/components/tools.py +0 -31
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/components/welcome.py +1 -32
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/input/prompt_toolkit.py +25 -9
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/machine.py +31 -19
- klaude_code-2.4.2/src/klaude_code/core/prompts/prompt-nano-banana.md +0 -1
- klaude_code-2.4.2/src/klaude_code/core/tool/shell/bash_tool.md +0 -43
- klaude_code-2.4.2/src/klaude_code/core/tool/todo/todo_write_tool.md +0 -25
- klaude_code-2.4.2/src/klaude_code/core/tool/truncation.py +0 -203
- klaude_code-2.4.2/src/klaude_code/llm/client.py +0 -36
- {klaude_code-2.4.2 → klaude_code-2.5.1}/README.md +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/app/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/auth/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/auth/base.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/auth/claude/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/auth/claude/exceptions.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/auth/claude/oauth.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/auth/claude/token_manager.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/auth/codex/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/auth/codex/exceptions.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/auth/codex/jwt_utils.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/auth/codex/oauth.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/auth/codex/token_manager.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/cli/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/cli/auth_cmd.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/cli/config_cmd.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/cli/cost_cmd.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/cli/debug.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/cli/list_model.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/cli/self_update.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/cli/session_cmd.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/config/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/config/assets/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/config/builtin_config.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/config/config.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/config/model_matcher.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/config/sub_agent_model_helper.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/config/thinking.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/manager/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/manager/llm_clients.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/manager/llm_clients_builder.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/prompts/prompt-claude-code.md +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/prompts/prompt-codex-gpt-5-1-codex-max.md +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/prompts/prompt-codex-gpt-5-2-codex.md +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/prompts/prompt-codex.md +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/prompts/prompt-gemini.md +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/prompts/prompt-minimal.md +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/prompts/prompt-sub-agent-explore.md +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/prompts/prompt-sub-agent-image-gen.md +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/prompts/prompt-sub-agent.md +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/reminders.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/tool/file/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/tool/file/_utils.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/tool/file/apply_patch.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/tool/file/apply_patch_tool.md +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/tool/file/apply_patch_tool.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/tool/file/diff_builder.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/tool/file/edit_tool.md +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/tool/file/edit_tool.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/tool/file/read_tool.md +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/tool/file/read_tool.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/tool/file/write_tool.md +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/tool/file/write_tool.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/tool/report_back_tool.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/tool/shell/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/tool/shell/bash_tool.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/tool/shell/command_safety.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/tool/todo/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/tool/todo/todo_write_tool.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/tool/todo/todo_write_tool_raw.md +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/tool/todo/update_plan_tool.md +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/tool/todo/update_plan_tool.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/tool/tool_abc.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/tool/tool_registry.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/tool/web/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/tool/web/mermaid_tool.md +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/tool/web/mermaid_tool.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/tool/web/web_search_tool.md +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/tool/web/web_search_tool.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/llm/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/llm/anthropic/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/llm/anthropic/input.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/llm/bedrock/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/llm/claude/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/llm/codex/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/llm/google/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/llm/google/input.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/llm/image.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/llm/input_common.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/llm/openai_compatible/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/llm/openai_compatible/input.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/llm/openai_compatible/tool_call_accumulator.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/llm/openrouter/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/llm/openrouter/input.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/llm/openrouter/reasoning.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/llm/registry.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/llm/responses/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/llm/responses/input.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/log.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/protocol/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/protocol/events/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/protocol/events/base.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/protocol/events/chat.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/protocol/events/tools.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/protocol/llm_param.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/protocol/message.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/protocol/op.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/protocol/op_handler.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/protocol/sub_agent/AGENTS.md +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/protocol/sub_agent/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/protocol/tools.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/session/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/session/codec.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/session/export.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/session/selector.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/session/session.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/session/store.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/session/templates/mermaid_viewer.html +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/skill/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/skill/assets/create-plan/SKILL.md +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/skill/assets/deslop/SKILL.md +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/skill/assets/handoff/SKILL.md +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/skill/assets/jj-workspace/SKILL.md +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/skill/assets/skill-creator/SKILL.md +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/skill/loader.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/skill/system_skills.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/command/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/command/clear_cmd.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/command/command_abc.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/command/copy_cmd.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/command/debug_cmd.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/command/export_cmd.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/command/export_online_cmd.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/command/fork_session_cmd.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/command/model_cmd.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/command/model_picker.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/command/prompt-init.md +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/command/prompt_command.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/command/refresh_cmd.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/command/registry.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/command/resume_cmd.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/command/status_cmd.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/command/sub_agent_model_cmd.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/command/terminal_setup_cmd.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/command/thinking_cmd.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/commands.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/components/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/components/assistant.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/components/bash_syntax.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/components/command_output.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/components/common.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/components/developer.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/components/diffs.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/components/errors.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/components/mermaid_viewer.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/components/rich/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/components/rich/cjk_wrap.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/components/rich/code_panel.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/components/rich/live.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/components/rich/quote.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/components/rich/searchable_text.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/components/rich/status.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/components/sub_agent.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/components/thinking.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/components/user_input.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/display.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/input/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/input/clipboard.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/input/completers.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/input/key_bindings.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/renderer.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/runner.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/terminal/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/terminal/color.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/terminal/control.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/terminal/image.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/terminal/notifier.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/terminal/progress_bar.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/tui/terminal/selector.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/ui/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/ui/common.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/ui/core/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/ui/core/display.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/ui/core/input.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/ui/debug_mode.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/ui/terminal/__init__.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/ui/terminal/title.py +0 -0
- {klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/update.py +0 -0
|
@@ -11,7 +11,6 @@ from klaude_code.config import Config, load_config
|
|
|
11
11
|
from klaude_code.core.agent import Agent
|
|
12
12
|
from klaude_code.core.agent_profile import (
|
|
13
13
|
DefaultModelProfileProvider,
|
|
14
|
-
NanoBananaModelProfileProvider,
|
|
15
14
|
VanillaModelProfileProvider,
|
|
16
15
|
)
|
|
17
16
|
from klaude_code.core.executor import Executor
|
|
@@ -28,7 +27,6 @@ class AppInitConfig:
|
|
|
28
27
|
model: str | None
|
|
29
28
|
debug: bool
|
|
30
29
|
vanilla: bool
|
|
31
|
-
banana: bool
|
|
32
30
|
debug_filters: set[DebugType] | None = None
|
|
33
31
|
|
|
34
32
|
|
|
@@ -59,7 +57,7 @@ async def initialize_app_components(
|
|
|
59
57
|
llm_clients = build_llm_clients(
|
|
60
58
|
config,
|
|
61
59
|
model_override=init_config.model,
|
|
62
|
-
skip_sub_agents=init_config.vanilla
|
|
60
|
+
skip_sub_agents=init_config.vanilla,
|
|
63
61
|
)
|
|
64
62
|
except ValueError as exc:
|
|
65
63
|
if init_config.model:
|
|
@@ -74,9 +72,7 @@ async def initialize_app_components(
|
|
|
74
72
|
log((f"Error: failed to load the default model configuration: {exc}", "red"))
|
|
75
73
|
raise typer.Exit(2) from None
|
|
76
74
|
|
|
77
|
-
if init_config.
|
|
78
|
-
model_profile_provider = NanoBananaModelProfileProvider()
|
|
79
|
-
elif init_config.vanilla:
|
|
75
|
+
if init_config.vanilla:
|
|
80
76
|
model_profile_provider = VanillaModelProfileProvider()
|
|
81
77
|
else:
|
|
82
78
|
model_profile_provider = DefaultModelProfileProvider(config=config)
|
|
@@ -152,6 +152,13 @@ provider_list:
|
|
|
152
152
|
modalities:
|
|
153
153
|
- image
|
|
154
154
|
- text
|
|
155
|
+
- model_name: flux
|
|
156
|
+
model_id: black-forest-labs/flux.2-max
|
|
157
|
+
context_limit: 47000
|
|
158
|
+
cost: {input: 7.32, output: 7.32, image: 7.32}
|
|
159
|
+
modalities:
|
|
160
|
+
- image
|
|
161
|
+
- text
|
|
155
162
|
- provider_name: google
|
|
156
163
|
protocol: google
|
|
157
164
|
api_key: ${GOOGLE_API_KEY}
|
|
@@ -47,7 +47,6 @@ THROUGHPUT_MIN_DURATION_SEC = 0.15 # Minimum duration (seconds) for throughput
|
|
|
47
47
|
INITIAL_RETRY_DELAY_S = 1.0 # Initial delay before retrying a failed turn (seconds)
|
|
48
48
|
MAX_RETRY_DELAY_S = 30.0 # Maximum delay between retries (seconds)
|
|
49
49
|
CANCEL_OUTPUT = "[Request interrupted by user for tool use]" # Message shown when tool call is cancelled
|
|
50
|
-
INTERRUPT_MARKER = " <system>interrupted by user</system>" # Marker appended when assistant is interrupted
|
|
51
50
|
EMPTY_TOOL_OUTPUT_MESSAGE = (
|
|
52
51
|
"<system-reminder>Tool ran without output or errors</system-reminder>" # Tool output placeholder
|
|
53
52
|
)
|
|
@@ -112,7 +111,10 @@ DIFF_DEFAULT_CONTEXT_LINES = 3 # Default number of context lines in diff output
|
|
|
112
111
|
TOOL_OUTPUT_MAX_LENGTH = 40000 # Maximum length for tool output before truncation
|
|
113
112
|
TOOL_OUTPUT_DISPLAY_HEAD = 10000 # Characters to show from the beginning of truncated output
|
|
114
113
|
TOOL_OUTPUT_DISPLAY_TAIL = 10000 # Characters to show from the end of truncated output
|
|
115
|
-
|
|
114
|
+
TOOL_OUTPUT_MAX_LINES = 2000 # Maximum lines for tool output before truncation
|
|
115
|
+
TOOL_OUTPUT_DISPLAY_HEAD_LINES = 1000 # Lines to show from the beginning of truncated output
|
|
116
|
+
TOOL_OUTPUT_DISPLAY_TAIL_LINES = 1000 # Lines to show from the end of truncated output
|
|
117
|
+
TOOL_OUTPUT_TRUNCATION_DIR = "/tmp" # Directory for saving full truncated output
|
|
116
118
|
|
|
117
119
|
|
|
118
120
|
# =============================================================================
|
|
@@ -156,8 +158,8 @@ STATUS_HINT_TEXT = " (esc to interrupt)" # Status hint text shown after spinner
|
|
|
156
158
|
|
|
157
159
|
# Spinner status texts
|
|
158
160
|
STATUS_WAITING_TEXT = "Connecting …"
|
|
159
|
-
STATUS_THINKING_TEXT = "
|
|
160
|
-
STATUS_COMPOSING_TEXT = "
|
|
161
|
+
STATUS_THINKING_TEXT = "Thinking …"
|
|
162
|
+
STATUS_COMPOSING_TEXT = "Composing"
|
|
161
163
|
|
|
162
164
|
# Backwards-compatible alias for the default spinner status text.
|
|
163
165
|
STATUS_DEFAULT_TEXT = STATUS_WAITING_TEXT
|
|
@@ -166,6 +168,7 @@ SPINNER_BREATH_PERIOD_SECONDS: float = 2.0 # Spinner breathing animation period
|
|
|
166
168
|
STATUS_SHIMMER_PADDING = 10 # Horizontal padding for shimmer band position
|
|
167
169
|
STATUS_SHIMMER_BAND_HALF_WIDTH = 5.0 # Half-width of shimmer band in characters
|
|
168
170
|
STATUS_SHIMMER_ALPHA_SCALE = 0.7 # Scale factor for shimmer intensity
|
|
171
|
+
STATUS_SHOW_BUFFER_LENGTH = False # Show character count (e.g., "(213)") during text generation
|
|
169
172
|
|
|
170
173
|
|
|
171
174
|
# =============================================================================
|
|
@@ -8,7 +8,7 @@ from klaude_code.core.tool import build_todo_context, get_registry
|
|
|
8
8
|
from klaude_code.core.tool.context import RunSubtask
|
|
9
9
|
from klaude_code.llm import LLMClientABC
|
|
10
10
|
from klaude_code.log import DebugType, log_debug
|
|
11
|
-
from klaude_code.protocol import events
|
|
11
|
+
from klaude_code.protocol import events, model
|
|
12
12
|
from klaude_code.protocol.message import UserInputPayload
|
|
13
13
|
from klaude_code.session import Session
|
|
14
14
|
|
|
@@ -93,3 +93,12 @@ class Agent:
|
|
|
93
93
|
|
|
94
94
|
def get_llm_client(self) -> LLMClientABC:
|
|
95
95
|
return self.profile.llm_client
|
|
96
|
+
|
|
97
|
+
def get_partial_metadata(self) -> model.TaskMetadata | None:
|
|
98
|
+
"""Get partial metadata from the currently running task.
|
|
99
|
+
|
|
100
|
+
Returns None if no task is running or no usage data has been accumulated.
|
|
101
|
+
"""
|
|
102
|
+
if self._current_task is None:
|
|
103
|
+
return None
|
|
104
|
+
return self._current_task.get_partial_metadata()
|
|
@@ -62,10 +62,7 @@ PROMPT_FILES: dict[str, str] = {
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
STRUCTURED_OUTPUT_PROMPT = """\
|
|
65
|
+
STRUCTURED_OUTPUT_PROMPT_FOR_SUB_AGENT = """\
|
|
69
66
|
|
|
70
67
|
# Structured Output
|
|
71
68
|
You have a `report_back` tool available. When you complete the task,\
|
|
@@ -74,6 +71,20 @@ Only the content passed to `report_back` will be returned to user.\
|
|
|
74
71
|
"""
|
|
75
72
|
|
|
76
73
|
|
|
74
|
+
SUB_AGENT_COMMON_PROMPT_FOR_MAIN_AGENT = """\
|
|
75
|
+
|
|
76
|
+
# Sub-agent capabilities
|
|
77
|
+
You have sub-agents (e.g. Task, Explore, WebAgent, ImageGen) with structured output and resume capabilites:
|
|
78
|
+
- Agents can be provided with an `output_format` (JSON Schema) parameter for structured output
|
|
79
|
+
- Example: `output_format={"type": "object", "properties": {"files": {"type": "array", "items": {"type": "string"}, "description": "List of file paths that match the search criteria, e.g. ['src/main.py', 'src/utils/helper.py']"}}, "required": ["files"]}`
|
|
80
|
+
- Agents can be resumed using the `resume` parameter by passing the agent ID from a previous invocation. \
|
|
81
|
+
When resumed, the agent continues with its full previous context preserved. \
|
|
82
|
+
When NOT resuming, each invocation starts fresh and you should provide a detailed task description with all necessary context.
|
|
83
|
+
- When the agent is done, it will return a single message back to you along with its agent ID. \
|
|
84
|
+
You can use this ID to resume the agent later if needed for follow-up work.
|
|
85
|
+
"""
|
|
86
|
+
|
|
87
|
+
|
|
77
88
|
@cache
|
|
78
89
|
def _load_prompt_by_path(prompt_path: str) -> str:
|
|
79
90
|
"""Load and cache prompt content from a file path relative to core package."""
|
|
@@ -142,10 +153,24 @@ def _build_env_info(model_name: str) -> str:
|
|
|
142
153
|
return "\n".join(env_lines)
|
|
143
154
|
|
|
144
155
|
|
|
156
|
+
def _has_sub_agents(config: Config | None) -> bool:
|
|
157
|
+
"""Check if there are any sub-agent tools available for the main agent."""
|
|
158
|
+
if config is not None:
|
|
159
|
+
from klaude_code.config.sub_agent_model_helper import SubAgentModelHelper
|
|
160
|
+
|
|
161
|
+
helper = SubAgentModelHelper(config)
|
|
162
|
+
return bool(helper.get_enabled_sub_agent_tool_names())
|
|
163
|
+
|
|
164
|
+
from klaude_code.protocol.sub_agent import sub_agent_tool_names
|
|
165
|
+
|
|
166
|
+
return bool(sub_agent_tool_names(enabled_only=True))
|
|
167
|
+
|
|
168
|
+
|
|
145
169
|
def load_system_prompt(
|
|
146
170
|
model_name: str,
|
|
147
171
|
protocol: llm_param.LLMClientProtocol,
|
|
148
172
|
sub_agent_type: str | None = None,
|
|
173
|
+
config: Config | None = None,
|
|
149
174
|
) -> str:
|
|
150
175
|
"""Get system prompt content for the given model and sub-agent type."""
|
|
151
176
|
|
|
@@ -161,13 +186,18 @@ def load_system_prompt(
|
|
|
161
186
|
return base_prompt
|
|
162
187
|
|
|
163
188
|
skills_prompt = ""
|
|
189
|
+
sub_agent_prompt = ""
|
|
164
190
|
if sub_agent_type is None:
|
|
165
191
|
# Skills are progressive-disclosure: keep only metadata in the system prompt.
|
|
166
192
|
from klaude_code.skill.manager import format_available_skills_for_system_prompt
|
|
167
193
|
|
|
168
194
|
skills_prompt = format_available_skills_for_system_prompt()
|
|
169
195
|
|
|
170
|
-
|
|
196
|
+
# Add sub-agent resume instructions if there are sub-agent tools available.
|
|
197
|
+
if _has_sub_agents(config):
|
|
198
|
+
sub_agent_prompt = "\n" + SUB_AGENT_COMMON_PROMPT_FOR_MAIN_AGENT
|
|
199
|
+
|
|
200
|
+
return base_prompt + _build_env_info(model_name) + skills_prompt + sub_agent_prompt
|
|
171
201
|
|
|
172
202
|
|
|
173
203
|
def load_agent_tools(
|
|
@@ -245,7 +275,7 @@ def with_structured_output(profile: AgentProfile, output_schema: dict[str, Any])
|
|
|
245
275
|
base_prompt = profile.system_prompt or ""
|
|
246
276
|
return AgentProfile(
|
|
247
277
|
llm_client=profile.llm_client,
|
|
248
|
-
system_prompt=base_prompt +
|
|
278
|
+
system_prompt=base_prompt + STRUCTURED_OUTPUT_PROMPT_FOR_SUB_AGENT,
|
|
249
279
|
tools=[*profile.tools, report_back_tool_class.schema()],
|
|
250
280
|
reminders=profile.reminders,
|
|
251
281
|
)
|
|
@@ -279,17 +309,24 @@ class DefaultModelProfileProvider(ModelProfileProvider):
|
|
|
279
309
|
model_name = llm_client.model_name
|
|
280
310
|
llm_config = llm_client.get_llm_config()
|
|
281
311
|
|
|
282
|
-
# Image generation models should not have tools
|
|
283
|
-
|
|
312
|
+
# Image generation models should not have system prompt, tools, or reminders
|
|
313
|
+
is_image_model = llm_config.modalities and "image" in llm_config.modalities
|
|
314
|
+
if is_image_model:
|
|
315
|
+
agent_system_prompt: str | None = None
|
|
284
316
|
agent_tools: list[llm_param.ToolSchema] = []
|
|
317
|
+
agent_reminders: list[Reminder] = []
|
|
285
318
|
else:
|
|
319
|
+
agent_system_prompt = load_system_prompt(
|
|
320
|
+
model_name, llm_client.protocol, sub_agent_type, config=self._config
|
|
321
|
+
)
|
|
286
322
|
agent_tools = load_agent_tools(model_name, sub_agent_type, config=self._config)
|
|
323
|
+
agent_reminders = load_agent_reminders(model_name, sub_agent_type)
|
|
287
324
|
|
|
288
325
|
profile = AgentProfile(
|
|
289
326
|
llm_client=llm_client,
|
|
290
|
-
system_prompt=
|
|
327
|
+
system_prompt=agent_system_prompt,
|
|
291
328
|
tools=agent_tools,
|
|
292
|
-
reminders=
|
|
329
|
+
reminders=agent_reminders,
|
|
293
330
|
)
|
|
294
331
|
if output_schema:
|
|
295
332
|
return with_structured_output(profile, output_schema)
|
|
@@ -316,28 +353,3 @@ class VanillaModelProfileProvider(ModelProfileProvider):
|
|
|
316
353
|
if output_schema:
|
|
317
354
|
return with_structured_output(profile, output_schema)
|
|
318
355
|
return profile
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
class NanoBananaModelProfileProvider(ModelProfileProvider):
|
|
322
|
-
"""Provider for the Nano Banana image generation model.
|
|
323
|
-
|
|
324
|
-
This mode uses a dedicated system prompt and strips all tools/reminders.
|
|
325
|
-
"""
|
|
326
|
-
|
|
327
|
-
def build_profile(
|
|
328
|
-
self,
|
|
329
|
-
llm_client: LLMClientABC,
|
|
330
|
-
sub_agent_type: tools.SubAgentType | None = None,
|
|
331
|
-
*,
|
|
332
|
-
output_schema: dict[str, Any] | None = None,
|
|
333
|
-
) -> AgentProfile:
|
|
334
|
-
del sub_agent_type
|
|
335
|
-
profile = AgentProfile(
|
|
336
|
-
llm_client=llm_client,
|
|
337
|
-
system_prompt=_load_prompt_by_path(NANO_BANANA_SYSTEM_PROMPT_PATH),
|
|
338
|
-
tools=[],
|
|
339
|
-
reminders=[],
|
|
340
|
-
)
|
|
341
|
-
if output_schema:
|
|
342
|
-
return with_structured_output(profile, output_schema)
|
|
343
|
-
return profile
|
|
@@ -17,14 +17,14 @@ from pathlib import Path
|
|
|
17
17
|
from klaude_code.config import load_config
|
|
18
18
|
from klaude_code.config.sub_agent_model_helper import SubAgentModelHelper
|
|
19
19
|
from klaude_code.core.agent import Agent
|
|
20
|
-
from klaude_code.core.agent_profile import
|
|
20
|
+
from klaude_code.core.agent_profile import DefaultModelProfileProvider, ModelProfileProvider
|
|
21
21
|
from klaude_code.core.manager import LLMClients, SubAgentManager
|
|
22
22
|
from klaude_code.llm.registry import create_llm_client
|
|
23
23
|
from klaude_code.log import DebugType, log_debug
|
|
24
24
|
from klaude_code.protocol import commands, events, message, model, op
|
|
25
25
|
from klaude_code.protocol.llm_param import LLMConfigParameter, Thinking
|
|
26
26
|
from klaude_code.protocol.op_handler import OperationHandler
|
|
27
|
-
from klaude_code.protocol.sub_agent import SubAgentResult
|
|
27
|
+
from klaude_code.protocol.sub_agent import SubAgentResult
|
|
28
28
|
from klaude_code.session.export import build_export_html, get_default_export_path
|
|
29
29
|
from klaude_code.session.session import Session
|
|
30
30
|
|
|
@@ -110,19 +110,6 @@ class AgentRuntime:
|
|
|
110
110
|
def current_agent(self) -> Agent | None:
|
|
111
111
|
return self._agent
|
|
112
112
|
|
|
113
|
-
def _get_sub_agent_models(self, profile: AgentProfile) -> dict[str, LLMConfigParameter]:
|
|
114
|
-
"""Build a dict of sub-agent type to LLMConfigParameter based on profile tools."""
|
|
115
|
-
enabled_types: set[str] = set()
|
|
116
|
-
for tool in profile.tools:
|
|
117
|
-
sub_profile = get_sub_agent_profile_by_tool(tool.name)
|
|
118
|
-
if sub_profile is not None:
|
|
119
|
-
enabled_types.add(sub_profile.name)
|
|
120
|
-
return {
|
|
121
|
-
sub_agent_type: client.get_llm_config()
|
|
122
|
-
for sub_agent_type, client in self._llm_clients.sub_clients.items()
|
|
123
|
-
if sub_agent_type in enabled_types
|
|
124
|
-
}
|
|
125
|
-
|
|
126
113
|
async def ensure_agent(self, session_id: str | None = None) -> Agent:
|
|
127
114
|
"""Return the active agent, creating or loading a session as needed."""
|
|
128
115
|
|
|
@@ -149,7 +136,6 @@ class AgentRuntime:
|
|
|
149
136
|
session_id=session.id,
|
|
150
137
|
work_dir=str(session.work_dir),
|
|
151
138
|
llm_config=self._llm_clients.main.get_llm_config(),
|
|
152
|
-
sub_agent_models=self._get_sub_agent_models(profile),
|
|
153
139
|
)
|
|
154
140
|
)
|
|
155
141
|
|
|
@@ -206,7 +192,6 @@ class AgentRuntime:
|
|
|
206
192
|
session_id=agent.session.id,
|
|
207
193
|
work_dir=str(agent.session.work_dir),
|
|
208
194
|
llm_config=self._llm_clients.main.get_llm_config(),
|
|
209
|
-
sub_agent_models=self._get_sub_agent_models(agent.profile),
|
|
210
195
|
)
|
|
211
196
|
)
|
|
212
197
|
|
|
@@ -230,7 +215,6 @@ class AgentRuntime:
|
|
|
230
215
|
session_id=target_session.id,
|
|
231
216
|
work_dir=str(target_session.work_dir),
|
|
232
217
|
llm_config=self._llm_clients.main.get_llm_config(),
|
|
233
|
-
sub_agent_models=self._get_sub_agent_models(profile),
|
|
234
218
|
)
|
|
235
219
|
)
|
|
236
220
|
|
|
@@ -291,8 +275,11 @@ class AgentRuntime:
|
|
|
291
275
|
async def _runner(
|
|
292
276
|
state: model.SubAgentState,
|
|
293
277
|
record_session_id: Callable[[str], None] | None,
|
|
278
|
+
register_metadata_getter: Callable[[Callable[[], model.TaskMetadata | None]], None] | None,
|
|
294
279
|
) -> SubAgentResult:
|
|
295
|
-
return await self._sub_agent_manager.run_sub_agent(
|
|
280
|
+
return await self._sub_agent_manager.run_sub_agent(
|
|
281
|
+
agent, state, record_session_id=record_session_id, register_metadata_getter=register_metadata_getter
|
|
282
|
+
)
|
|
296
283
|
|
|
297
284
|
async for event in agent.run_task(user_input, run_subtask=_runner):
|
|
298
285
|
await self._emit_event(event)
|
|
@@ -464,7 +451,6 @@ class ExecutorContext:
|
|
|
464
451
|
llm_config=llm_config,
|
|
465
452
|
work_dir=str(agent.session.work_dir),
|
|
466
453
|
show_klaude_code_info=False,
|
|
467
|
-
show_sub_agent_models=False,
|
|
468
454
|
)
|
|
469
455
|
)
|
|
470
456
|
|
|
@@ -512,7 +498,6 @@ class ExecutorContext:
|
|
|
512
498
|
work_dir=str(agent.session.work_dir),
|
|
513
499
|
llm_config=agent.profile.llm_client.get_llm_config(),
|
|
514
500
|
show_klaude_code_info=False,
|
|
515
|
-
show_sub_agent_models=False,
|
|
516
501
|
)
|
|
517
502
|
)
|
|
518
503
|
|
|
@@ -44,6 +44,7 @@ class SubAgentManager:
|
|
|
44
44
|
state: model.SubAgentState,
|
|
45
45
|
*,
|
|
46
46
|
record_session_id: Callable[[str], None] | None = None,
|
|
47
|
+
register_metadata_getter: Callable[[Callable[[], model.TaskMetadata | None]], None] | None = None,
|
|
47
48
|
) -> SubAgentResult:
|
|
48
49
|
"""Run a nested sub-agent task and return its result."""
|
|
49
50
|
|
|
@@ -114,6 +115,16 @@ class SubAgentManager:
|
|
|
114
115
|
debug_type=DebugType.EXECUTION,
|
|
115
116
|
)
|
|
116
117
|
|
|
118
|
+
# Register metadata getter so parent can retrieve partial metadata on cancel
|
|
119
|
+
def _get_partial_metadata() -> model.TaskMetadata | None:
|
|
120
|
+
metadata = child_agent.get_partial_metadata()
|
|
121
|
+
if metadata is not None:
|
|
122
|
+
metadata.description = state.sub_agent_desc or None
|
|
123
|
+
return metadata
|
|
124
|
+
|
|
125
|
+
if register_metadata_getter is not None:
|
|
126
|
+
register_metadata_getter(_get_partial_metadata)
|
|
127
|
+
|
|
117
128
|
try:
|
|
118
129
|
# Not emit the subtask's user input since task tool call is already rendered
|
|
119
130
|
result: str = ""
|
|
@@ -138,6 +149,7 @@ class SubAgentManager:
|
|
|
138
149
|
# Capture TaskMetadataEvent for metadata propagation
|
|
139
150
|
elif isinstance(event, events.TaskMetadataEvent):
|
|
140
151
|
task_metadata = event.metadata.main_agent
|
|
152
|
+
task_metadata.description = state.sub_agent_desc or None
|
|
141
153
|
await self.emit_event(event)
|
|
142
154
|
|
|
143
155
|
# Ensure the sub-agent session is persisted before returning its id for resume.
|
|
@@ -148,7 +160,11 @@ class SubAgentManager:
|
|
|
148
160
|
task_metadata=task_metadata,
|
|
149
161
|
)
|
|
150
162
|
except asyncio.CancelledError:
|
|
151
|
-
#
|
|
163
|
+
# Call cancel() on child agent to emit cleanup events
|
|
164
|
+
# Note: Parent retrieves partial metadata via registered getter before this runs
|
|
165
|
+
for evt in child_agent.cancel():
|
|
166
|
+
await self.emit_event(evt)
|
|
167
|
+
|
|
152
168
|
log_debug(
|
|
153
169
|
f"Sub-agent task for {state.sub_agent_type} was cancelled",
|
|
154
170
|
style="yellow",
|
{klaude_code-2.4.2 → klaude_code-2.5.1}/src/klaude_code/core/prompts/prompt-sub-agent-web.md
RENAMED
|
@@ -17,7 +17,7 @@ You are a web research subagent that searches and fetches web content to provide
|
|
|
17
17
|
- HTML pages are automatically converted to Markdown
|
|
18
18
|
- JSON responses are auto-formatted with indentation
|
|
19
19
|
- Other text content returned as-is
|
|
20
|
-
- **Content is always saved to a local file** -
|
|
20
|
+
- **Content is always saved to a local file** - path shown in `[Web content saved to ...]` at output start
|
|
21
21
|
|
|
22
22
|
## Tool Usage Strategy
|
|
23
23
|
|
|
@@ -54,9 +54,9 @@ Balance efficiency with thoroughness. For open-ended questions (e.g., "recommend
|
|
|
54
54
|
## Response Guidelines
|
|
55
55
|
|
|
56
56
|
- Only your last message is returned to the main agent
|
|
57
|
+
- Include the file path from `[Web content saved to ...]` so the main agent can access full content
|
|
57
58
|
- **DO NOT copy full web page content** - the main agent can read the saved files directly
|
|
58
59
|
- Provide a concise summary/analysis of key findings
|
|
59
|
-
- Include the file path from `<file_saved>` so the main agent can access full content if needed
|
|
60
60
|
- Lead with the most recent info for evolving topics
|
|
61
61
|
- Favor original sources (company blogs, papers, gov sites) over aggregators
|
|
62
62
|
- When sources conflict, explain the discrepancy and which source is more authoritative
|
|
@@ -73,5 +73,5 @@ Stop only when all are true:
|
|
|
73
73
|
You MUST end every response with a "Sources:" section listing all URLs with their saved file paths:
|
|
74
74
|
|
|
75
75
|
Sources:
|
|
76
|
-
- [Source Title](https://example.com) -> /tmp/klaude
|
|
77
|
-
- [Another Source](https://example.com/page) -> /tmp/klaude
|
|
76
|
+
- [Source Title](https://example.com) -> /tmp/klaude-webfetch-example_com.txt
|
|
77
|
+
- [Another Source](https://example.com/page) -> /tmp/klaude-webfetch-example_com_page.txt
|
|
@@ -66,6 +66,49 @@ class MetadataAccumulator:
|
|
|
66
66
|
"""Add sub-agent task metadata to the accumulated state."""
|
|
67
67
|
self._sub_agent_metadata.append(sub_agent_metadata)
|
|
68
68
|
|
|
69
|
+
def get_partial(self, task_duration_s: float) -> model.TaskMetadata | None:
|
|
70
|
+
"""Return a snapshot of main agent metadata without modifying accumulator state.
|
|
71
|
+
|
|
72
|
+
Returns None if no usage data has been accumulated yet.
|
|
73
|
+
"""
|
|
74
|
+
if self._main_agent.usage is None:
|
|
75
|
+
return None
|
|
76
|
+
|
|
77
|
+
# Create a copy to avoid modifying the original
|
|
78
|
+
usage_copy = self._main_agent.usage.model_copy(deep=True)
|
|
79
|
+
|
|
80
|
+
if self._throughput_tracked_tokens > 0:
|
|
81
|
+
usage_copy.throughput_tps = self._throughput_weighted_sum / self._throughput_tracked_tokens
|
|
82
|
+
else:
|
|
83
|
+
usage_copy.throughput_tps = None
|
|
84
|
+
|
|
85
|
+
if self._first_token_latency_count > 0:
|
|
86
|
+
usage_copy.first_token_latency_ms = self._first_token_latency_sum / self._first_token_latency_count
|
|
87
|
+
else:
|
|
88
|
+
usage_copy.first_token_latency_ms = None
|
|
89
|
+
|
|
90
|
+
return model.TaskMetadata(
|
|
91
|
+
model_name=self._main_agent.model_name,
|
|
92
|
+
provider=self._main_agent.provider,
|
|
93
|
+
usage=usage_copy,
|
|
94
|
+
task_duration_s=task_duration_s,
|
|
95
|
+
turn_count=self._turn_count,
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
def get_partial_item(self, task_duration_s: float) -> model.TaskMetadataItem | None:
|
|
99
|
+
"""Return a snapshot of full metadata (main + sub-agents) without modifying state.
|
|
100
|
+
|
|
101
|
+
Returns None if no usage data has been accumulated yet.
|
|
102
|
+
"""
|
|
103
|
+
main_agent = self.get_partial(task_duration_s)
|
|
104
|
+
if main_agent is None:
|
|
105
|
+
return None
|
|
106
|
+
|
|
107
|
+
return model.TaskMetadataItem(
|
|
108
|
+
main_agent=main_agent,
|
|
109
|
+
sub_agent_task_metadata=list(self._sub_agent_metadata),
|
|
110
|
+
)
|
|
111
|
+
|
|
69
112
|
def finalize(self, task_duration_s: float) -> model.TaskMetadataItem:
|
|
70
113
|
"""Return the final accumulated metadata with computed throughput and duration."""
|
|
71
114
|
if self._main_agent.usage is not None:
|
|
@@ -129,20 +172,38 @@ class TaskExecutor:
|
|
|
129
172
|
def current_turn(self) -> TurnExecutor | None:
|
|
130
173
|
return self._current_turn
|
|
131
174
|
|
|
175
|
+
def get_partial_metadata(self) -> model.TaskMetadata | None:
|
|
176
|
+
"""Get the currently accumulated metadata without finalizing.
|
|
177
|
+
|
|
178
|
+
Returns partial metadata that can be used if the task is interrupted.
|
|
179
|
+
"""
|
|
180
|
+
if self._metadata_accumulator is None or self._started_at <= 0:
|
|
181
|
+
return None
|
|
182
|
+
task_duration_s = time.perf_counter() - self._started_at
|
|
183
|
+
return self._metadata_accumulator.get_partial(task_duration_s)
|
|
184
|
+
|
|
132
185
|
def cancel(self) -> list[events.Event]:
|
|
133
186
|
"""Cancel the current turn and return any resulting events including metadata."""
|
|
134
187
|
ui_events: list[events.Event] = []
|
|
135
188
|
if self._current_turn is not None:
|
|
136
|
-
|
|
189
|
+
for evt in self._current_turn.cancel():
|
|
190
|
+
# Collect sub-agent task metadata from cancelled tool results
|
|
191
|
+
if (
|
|
192
|
+
isinstance(evt, events.ToolResultEvent)
|
|
193
|
+
and evt.task_metadata is not None
|
|
194
|
+
and self._metadata_accumulator is not None
|
|
195
|
+
):
|
|
196
|
+
self._metadata_accumulator.add_sub_agent_metadata(evt.task_metadata)
|
|
197
|
+
ui_events.append(evt)
|
|
137
198
|
self._current_turn = None
|
|
138
199
|
|
|
139
200
|
# Emit partial metadata on cancellation
|
|
140
201
|
if self._metadata_accumulator is not None and self._started_at > 0:
|
|
141
202
|
task_duration_s = time.perf_counter() - self._started_at
|
|
142
|
-
accumulated = self._metadata_accumulator.
|
|
143
|
-
if accumulated
|
|
203
|
+
accumulated = self._metadata_accumulator.get_partial_item(task_duration_s)
|
|
204
|
+
if accumulated is not None:
|
|
144
205
|
session_id = self._context.session_ctx.session_id
|
|
145
|
-
ui_events.append(events.TaskMetadataEvent(metadata=accumulated, session_id=session_id))
|
|
206
|
+
ui_events.append(events.TaskMetadataEvent(metadata=accumulated, session_id=session_id, cancelled=True))
|
|
146
207
|
self._context.session_ctx.append_history([accumulated])
|
|
147
208
|
|
|
148
209
|
return ui_events
|
|
@@ -156,6 +217,7 @@ class TaskExecutor:
|
|
|
156
217
|
yield events.TaskStartEvent(
|
|
157
218
|
session_id=session_ctx.session_id,
|
|
158
219
|
sub_agent_state=ctx.sub_agent_state,
|
|
220
|
+
model_id=ctx.profile.llm_client.get_llm_config().model_id,
|
|
159
221
|
)
|
|
160
222
|
del user_input # Persisted by the operation handler before launching the task.
|
|
161
223
|
|
|
@@ -13,7 +13,6 @@ from .todo.update_plan_tool import UpdatePlanTool
|
|
|
13
13
|
from .tool_abc import ToolABC
|
|
14
14
|
from .tool_registry import get_registry, get_tool_schemas
|
|
15
15
|
from .tool_runner import run_tool
|
|
16
|
-
from .truncation import SimpleTruncationStrategy, TruncationStrategy, get_truncation_strategy, set_truncation_strategy
|
|
17
16
|
from .web.mermaid_tool import MermaidTool
|
|
18
17
|
from .web.web_fetch_tool import WebFetchTool
|
|
19
18
|
from .web.web_search_tool import WebSearchTool
|
|
@@ -29,14 +28,12 @@ __all__ = [
|
|
|
29
28
|
"ReportBackTool",
|
|
30
29
|
"RunSubtask",
|
|
31
30
|
"SafetyCheckResult",
|
|
32
|
-
"SimpleTruncationStrategy",
|
|
33
31
|
"SubAgentResumeClaims",
|
|
34
32
|
"SubAgentTool",
|
|
35
33
|
"TodoContext",
|
|
36
34
|
"TodoWriteTool",
|
|
37
35
|
"ToolABC",
|
|
38
36
|
"ToolContext",
|
|
39
|
-
"TruncationStrategy",
|
|
40
37
|
"UpdatePlanTool",
|
|
41
38
|
"WebFetchTool",
|
|
42
39
|
"WebSearchTool",
|
|
@@ -44,9 +41,7 @@ __all__ = [
|
|
|
44
41
|
"build_todo_context",
|
|
45
42
|
"get_registry",
|
|
46
43
|
"get_tool_schemas",
|
|
47
|
-
"get_truncation_strategy",
|
|
48
44
|
"is_safe_command",
|
|
49
45
|
"process_patch",
|
|
50
46
|
"run_tool",
|
|
51
|
-
"set_truncation_strategy",
|
|
52
47
|
]
|
|
@@ -10,7 +10,12 @@ from klaude_code.session.session import Session
|
|
|
10
10
|
|
|
11
11
|
type FileTracker = MutableMapping[str, model.FileStatus]
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
GetMetadataFn = Callable[[], model.TaskMetadata | None]
|
|
14
|
+
|
|
15
|
+
RunSubtask = Callable[
|
|
16
|
+
[model.SubAgentState, Callable[[str], None] | None, Callable[[GetMetadataFn], None] | None],
|
|
17
|
+
Awaitable[SubAgentResult],
|
|
18
|
+
]
|
|
14
19
|
|
|
15
20
|
|
|
16
21
|
@dataclass
|
|
@@ -79,6 +84,12 @@ class ToolContext:
|
|
|
79
84
|
run_subtask: RunSubtask | None = None
|
|
80
85
|
sub_agent_resume_claims: SubAgentResumeClaims | None = None
|
|
81
86
|
record_sub_agent_session_id: Callable[[str], None] | None = None
|
|
87
|
+
register_sub_agent_metadata_getter: Callable[[GetMetadataFn], None] | None = None
|
|
82
88
|
|
|
83
89
|
def with_record_sub_agent_session_id(self, callback: Callable[[str], None] | None) -> ToolContext:
|
|
84
90
|
return replace(self, record_sub_agent_session_id=callback)
|
|
91
|
+
|
|
92
|
+
def with_register_sub_agent_metadata_getter(
|
|
93
|
+
self, callback: Callable[[GetMetadataFn], None] | None
|
|
94
|
+
) -> ToolContext:
|
|
95
|
+
return replace(self, register_sub_agent_metadata_getter=callback)
|