klaude-code 2.1.0__tar.gz → 2.1.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.1.0 → klaude_code-2.1.1}/PKG-INFO +1 -1
- {klaude_code-2.1.0 → klaude_code-2.1.1}/pyproject.toml +1 -1
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/agent_profile.py +10 -3
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/reminders.py +20 -4
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/tool/__init__.py +0 -2
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/turn.py +1 -4
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/protocol/commands.py +1 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/protocol/events/tools.py +5 -1
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/protocol/tools.py +0 -1
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/session/session.py +0 -2
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/skill/loader.py +31 -87
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/skill/manager.py +38 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/command/__init__.py +3 -0
- klaude_code-2.1.1/src/klaude_code/tui/command/copy_cmd.py +53 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/components/tools.py +4 -8
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/machine.py +3 -1
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/renderer.py +1 -1
- klaude_code-2.1.0/src/klaude_code/core/tool/skill/skill_tool.md +0 -24
- klaude_code-2.1.0/src/klaude_code/core/tool/skill/skill_tool.py +0 -89
- klaude_code-2.1.0/src/klaude_code/tui/components/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/README.md +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/app/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/app/runtime.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/auth/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/auth/base.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/auth/claude/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/auth/claude/exceptions.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/auth/claude/oauth.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/auth/claude/token_manager.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/auth/codex/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/auth/codex/exceptions.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/auth/codex/jwt_utils.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/auth/codex/oauth.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/auth/codex/token_manager.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/cli/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/cli/auth_cmd.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/cli/config_cmd.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/cli/cost_cmd.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/cli/debug.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/cli/list_model.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/cli/main.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/cli/self_update.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/cli/session_cmd.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/config/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/config/assets/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/config/assets/builtin_config.yaml +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/config/builtin_config.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/config/config.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/config/select_model.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/config/thinking.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/const.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/agent.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/executor.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/manager/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/manager/llm_clients.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/manager/llm_clients_builder.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/manager/sub_agent_manager.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/prompts/prompt-claude-code.md +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/prompts/prompt-codex-gpt-5-1-codex-max.md +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/prompts/prompt-codex-gpt-5-2-codex.md +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/prompts/prompt-codex.md +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/prompts/prompt-gemini.md +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/prompts/prompt-minimal.md +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/prompts/prompt-sub-agent-explore.md +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/prompts/prompt-sub-agent-image-gen.md +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/prompts/prompt-sub-agent-web.md +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/prompts/prompt-sub-agent.md +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/task.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/tool/context.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/tool/file/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/tool/file/_utils.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/tool/file/apply_patch.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/tool/file/apply_patch_tool.md +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/tool/file/apply_patch_tool.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/tool/file/diff_builder.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/tool/file/edit_tool.md +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/tool/file/edit_tool.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/tool/file/read_tool.md +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/tool/file/read_tool.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/tool/file/write_tool.md +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/tool/file/write_tool.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/tool/report_back_tool.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/tool/shell/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/tool/shell/bash_tool.md +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/tool/shell/bash_tool.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/tool/shell/command_safety.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/tool/sub_agent_tool.py +0 -0
- {klaude_code-2.1.0/src/klaude_code/core/tool/skill → klaude_code-2.1.1/src/klaude_code/core/tool/todo}/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/tool/todo/todo_write_tool.md +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/tool/todo/todo_write_tool.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/tool/todo/todo_write_tool_raw.md +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/tool/todo/update_plan_tool.md +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/tool/todo/update_plan_tool.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/tool/tool_abc.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/tool/tool_registry.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/tool/tool_runner.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/tool/truncation.py +0 -0
- {klaude_code-2.1.0/src/klaude_code/core/tool/todo → klaude_code-2.1.1/src/klaude_code/core/tool/web}/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/tool/web/mermaid_tool.md +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/tool/web/mermaid_tool.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/tool/web/web_fetch_tool.md +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/tool/web/web_fetch_tool.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/tool/web/web_search_tool.md +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/core/tool/web/web_search_tool.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/llm/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/llm/anthropic/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/llm/anthropic/client.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/llm/anthropic/input.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/llm/bedrock/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/llm/bedrock/client.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/llm/claude/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/llm/claude/client.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/llm/client.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/llm/codex/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/llm/codex/client.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/llm/google/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/llm/google/client.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/llm/google/input.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/llm/image.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/llm/input_common.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/llm/openai_compatible/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/llm/openai_compatible/client.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/llm/openai_compatible/input.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/llm/openai_compatible/stream.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/llm/openai_compatible/tool_call_accumulator.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/llm/openrouter/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/llm/openrouter/client.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/llm/openrouter/input.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/llm/openrouter/reasoning.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/llm/registry.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/llm/responses/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/llm/responses/client.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/llm/responses/input.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/llm/usage.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/log.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/protocol/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/protocol/events/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/protocol/events/base.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/protocol/events/chat.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/protocol/events/lifecycle.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/protocol/events/metadata.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/protocol/events/streaming.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/protocol/events/system.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/protocol/llm_param.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/protocol/message.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/protocol/model.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/protocol/op.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/protocol/op_handler.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/protocol/sub_agent/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/protocol/sub_agent/explore.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/protocol/sub_agent/image_gen.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/protocol/sub_agent/task.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/protocol/sub_agent/web.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/session/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/session/codec.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/session/export.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/session/selector.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/session/store.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/session/templates/export_session.html +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/session/templates/mermaid_viewer.html +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/skill/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/skill/assets/create-plan/SKILL.md +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/skill/assets/deslop/SKILL.md +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/skill/assets/handoff/SKILL.md +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/skill/assets/jj-workspace/SKILL.md +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/skill/assets/skill-creator/SKILL.md +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/skill/system_skills.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/command/clear_cmd.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/command/command_abc.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/command/debug_cmd.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/command/export_cmd.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/command/export_online_cmd.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/command/fork_session_cmd.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/command/help_cmd.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/command/model_cmd.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/command/model_select.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/command/prompt-commit.md +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/command/prompt-init.md +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/command/prompt_command.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/command/refresh_cmd.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/command/registry.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/command/release_notes_cmd.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/command/resume_cmd.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/command/status_cmd.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/command/terminal_setup_cmd.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/command/thinking_cmd.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/commands.py +0 -0
- {klaude_code-2.1.0/src/klaude_code/core/tool/web → klaude_code-2.1.1/src/klaude_code/tui/components}/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/components/assistant.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/components/bash_syntax.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/components/common.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/components/developer.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/components/diffs.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/components/errors.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/components/mermaid_viewer.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/components/metadata.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/components/rich/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/components/rich/cjk_wrap.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/components/rich/code_panel.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/components/rich/live.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/components/rich/markdown.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/components/rich/quote.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/components/rich/searchable_text.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/components/rich/status.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/components/rich/theme.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/components/sub_agent.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/components/thinking.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/components/user_input.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/display.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/input/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/input/clipboard.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/input/completers.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/input/key_bindings.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/input/prompt_toolkit.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/runner.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/terminal/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/terminal/color.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/terminal/control.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/terminal/image.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/terminal/notifier.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/terminal/progress_bar.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/tui/terminal/selector.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/ui/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/ui/common.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/ui/core/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/ui/core/display.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/ui/core/input.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/ui/debug_mode.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/ui/exec_mode.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/ui/terminal/__init__.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/ui/terminal/title.py +0 -0
- {klaude_code-2.1.0 → klaude_code-2.1.1}/src/klaude_code/update.py +0 -0
|
@@ -150,10 +150,17 @@ def load_system_prompt(
|
|
|
150
150
|
base_prompt = _load_base_prompt(file_key)
|
|
151
151
|
|
|
152
152
|
if protocol == llm_param.LLMClientProtocol.CODEX_OAUTH:
|
|
153
|
-
# Do not append environment info for Codex protocol
|
|
153
|
+
# Do not append environment info or skills info for Codex protocol.
|
|
154
154
|
return base_prompt
|
|
155
155
|
|
|
156
|
-
|
|
156
|
+
skills_prompt = ""
|
|
157
|
+
if sub_agent_type is None:
|
|
158
|
+
# Skills are progressive-disclosure: keep only metadata in the system prompt.
|
|
159
|
+
from klaude_code.skill.manager import format_available_skills_for_system_prompt
|
|
160
|
+
|
|
161
|
+
skills_prompt = format_available_skills_for_system_prompt()
|
|
162
|
+
|
|
163
|
+
return base_prompt + _build_env_info(model_name) + skills_prompt
|
|
157
164
|
|
|
158
165
|
|
|
159
166
|
def load_agent_tools(
|
|
@@ -180,7 +187,7 @@ def load_agent_tools(
|
|
|
180
187
|
tool_names = [tools.BASH, tools.READ, tools.EDIT, tools.WRITE, tools.TODO_WRITE]
|
|
181
188
|
|
|
182
189
|
tool_names.extend(sub_agent_tool_names(enabled_only=True, model_name=model_name))
|
|
183
|
-
tool_names.extend([tools.
|
|
190
|
+
tool_names.extend([tools.MERMAID])
|
|
184
191
|
# tool_names.extend([tools.MEMORY])
|
|
185
192
|
return get_tool_schemas(tool_names)
|
|
186
193
|
|
|
@@ -444,16 +444,32 @@ async def skill_reminder(session: Session) -> message.DeveloperMessage | None:
|
|
|
444
444
|
if not skill:
|
|
445
445
|
return None
|
|
446
446
|
|
|
447
|
-
|
|
448
|
-
|
|
447
|
+
if not skill.skill_path.exists() or not skill.skill_path.is_file():
|
|
448
|
+
return None
|
|
449
|
+
|
|
450
|
+
tool_context = ToolContext(
|
|
451
|
+
file_tracker=session.file_tracker,
|
|
452
|
+
todo_context=build_todo_context(session),
|
|
453
|
+
session_id=session.id,
|
|
454
|
+
)
|
|
455
|
+
args = ReadTool.ReadArguments(file_path=str(skill.skill_path))
|
|
456
|
+
tool_result = await ReadTool.call_with_args(args, tool_context)
|
|
457
|
+
|
|
458
|
+
tool_args = args.model_dump_json(exclude_none=True)
|
|
459
|
+
skill_file_str = f"""Called the {tools.READ} tool with the following input: {tool_args}
|
|
460
|
+
Result of calling the {tools.READ} tool:
|
|
461
|
+
{tool_result.output_text}
|
|
462
|
+
"""
|
|
449
463
|
|
|
450
|
-
|
|
464
|
+
base_dir = str(skill.base_dir)
|
|
465
|
+
content = f"""<system-reminder>The user activated the "{skill.name}" skill.
|
|
451
466
|
|
|
452
467
|
<skill>
|
|
453
468
|
<name>{skill.name}</name>
|
|
454
469
|
<base_dir>{base_dir}</base_dir>
|
|
470
|
+
<location>{skill.skill_path}</location>
|
|
455
471
|
|
|
456
|
-
{
|
|
472
|
+
{skill_file_str}
|
|
457
473
|
</skill>
|
|
458
474
|
</system-reminder>"""
|
|
459
475
|
|
|
@@ -7,7 +7,6 @@ from .file.write_tool import WriteTool
|
|
|
7
7
|
from .report_back_tool import ReportBackTool
|
|
8
8
|
from .shell.bash_tool import BashTool
|
|
9
9
|
from .shell.command_safety import SafetyCheckResult, is_safe_command
|
|
10
|
-
from .skill.skill_tool import SkillTool
|
|
11
10
|
from .sub_agent_tool import SubAgentTool
|
|
12
11
|
from .todo.todo_write_tool import TodoWriteTool
|
|
13
12
|
from .todo.update_plan_tool import UpdatePlanTool
|
|
@@ -31,7 +30,6 @@ __all__ = [
|
|
|
31
30
|
"RunSubtask",
|
|
32
31
|
"SafetyCheckResult",
|
|
33
32
|
"SimpleTruncationStrategy",
|
|
34
|
-
"SkillTool",
|
|
35
33
|
"SubAgentResumeClaims",
|
|
36
34
|
"SubAgentTool",
|
|
37
35
|
"TodoContext",
|
|
@@ -69,7 +69,6 @@ def build_events_from_tool_executor_event(session_id: str, event: ToolExecutorEv
|
|
|
69
69
|
)
|
|
70
70
|
)
|
|
71
71
|
case ToolExecutionResult(tool_call=tool_call, tool_result=tool_result, is_last_in_turn=is_last_in_turn):
|
|
72
|
-
status = "success" if tool_result.status == "success" else "error"
|
|
73
72
|
ui_events.append(
|
|
74
73
|
events.ToolResultEvent(
|
|
75
74
|
session_id=session_id,
|
|
@@ -78,13 +77,11 @@ def build_events_from_tool_executor_event(session_id: str, event: ToolExecutorEv
|
|
|
78
77
|
tool_name=tool_call.tool_name,
|
|
79
78
|
result=tool_result.output_text,
|
|
80
79
|
ui_extra=tool_result.ui_extra,
|
|
81
|
-
status=status,
|
|
80
|
+
status=tool_result.status,
|
|
82
81
|
task_metadata=tool_result.task_metadata,
|
|
83
82
|
is_last_in_turn=is_last_in_turn,
|
|
84
83
|
)
|
|
85
84
|
)
|
|
86
|
-
if tool_result.status == "aborted":
|
|
87
|
-
ui_events.append(events.InterruptEvent(session_id=session_id))
|
|
88
85
|
case ToolExecutionTodoChange(todos=todos):
|
|
89
86
|
ui_events.append(
|
|
90
87
|
events.TodoChangeEvent(
|
|
@@ -28,6 +28,7 @@ class CommandName(str, Enum):
|
|
|
28
28
|
THINKING = "thinking"
|
|
29
29
|
FORK_SESSION = "fork-session"
|
|
30
30
|
RESUME = "resume"
|
|
31
|
+
COPY = "copy"
|
|
31
32
|
# PLAN and DOC are dynamically registered now, but kept here if needed for reference
|
|
32
33
|
# or we can remove them if no code explicitly imports them.
|
|
33
34
|
# PLAN = "plan"
|
|
@@ -18,6 +18,10 @@ class ToolResultEvent(ResponseEvent):
|
|
|
18
18
|
tool_name: str
|
|
19
19
|
result: str
|
|
20
20
|
ui_extra: model.ToolResultUIExtra | None = None
|
|
21
|
-
status: Literal["success", "error"]
|
|
21
|
+
status: Literal["success", "error", "aborted"]
|
|
22
22
|
task_metadata: model.TaskMetadata | None = None
|
|
23
23
|
is_last_in_turn: bool = True
|
|
24
|
+
|
|
25
|
+
@property
|
|
26
|
+
def is_error(self) -> bool:
|
|
27
|
+
return self.status in ("error", "aborted")
|
|
@@ -350,8 +350,6 @@ class Session(BaseModel):
|
|
|
350
350
|
is_last_in_turn=is_last_in_turn,
|
|
351
351
|
)
|
|
352
352
|
yield from self._iter_sub_agent_history(tr, seen_sub_agent_sessions)
|
|
353
|
-
if tr.status == "aborted":
|
|
354
|
-
yield events.InterruptEvent(session_id=self.id)
|
|
355
353
|
case message.UserMessage() as um:
|
|
356
354
|
images = [part for part in um.parts if isinstance(part, message.ImageURLPart)]
|
|
357
355
|
yield events.UserMessageEvent(
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import re
|
|
2
1
|
from dataclasses import dataclass
|
|
3
2
|
from pathlib import Path
|
|
4
3
|
from typing import ClassVar
|
|
@@ -14,12 +13,12 @@ class Skill:
|
|
|
14
13
|
|
|
15
14
|
name: str # Skill identifier (lowercase-hyphen)
|
|
16
15
|
description: str # What the skill does and when to use it
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
location: str # Skill source: 'system', 'user', or 'project'
|
|
17
|
+
skill_path: Path
|
|
18
|
+
base_dir: Path
|
|
19
19
|
license: str | None = None
|
|
20
20
|
allowed_tools: list[str] | None = None
|
|
21
21
|
metadata: dict[str, str] | None = None
|
|
22
|
-
skill_path: Path | None = None
|
|
23
22
|
|
|
24
23
|
@property
|
|
25
24
|
def short_description(self) -> str:
|
|
@@ -31,17 +30,6 @@ class Skill:
|
|
|
31
30
|
return self.metadata["short-description"]
|
|
32
31
|
return self.description
|
|
33
32
|
|
|
34
|
-
def to_prompt(self) -> str:
|
|
35
|
-
"""Convert skill to prompt format for agent consumption"""
|
|
36
|
-
return f"""# Skill: {self.name}
|
|
37
|
-
|
|
38
|
-
{self.description}
|
|
39
|
-
|
|
40
|
-
---
|
|
41
|
-
|
|
42
|
-
{self.content}
|
|
43
|
-
"""
|
|
44
|
-
|
|
45
33
|
|
|
46
34
|
class SkillLoader:
|
|
47
35
|
"""Load and manage Claude Skills from SKILL.md files"""
|
|
@@ -79,7 +67,6 @@ class SkillLoader:
|
|
|
79
67
|
|
|
80
68
|
# Parse YAML frontmatter
|
|
81
69
|
frontmatter: dict[str, object] = {}
|
|
82
|
-
markdown_content = content
|
|
83
70
|
|
|
84
71
|
if content.startswith("---"):
|
|
85
72
|
parts = content.split("---", 2)
|
|
@@ -87,7 +74,6 @@ class SkillLoader:
|
|
|
87
74
|
loaded: object = yaml.safe_load(parts[1])
|
|
88
75
|
if isinstance(loaded, dict):
|
|
89
76
|
frontmatter = dict(loaded) # type: ignore[arg-type]
|
|
90
|
-
markdown_content = parts[2].strip()
|
|
91
77
|
|
|
92
78
|
# Extract skill metadata
|
|
93
79
|
name = str(frontmatter.get("name", ""))
|
|
@@ -96,10 +82,6 @@ class SkillLoader:
|
|
|
96
82
|
if not name or not description:
|
|
97
83
|
return None
|
|
98
84
|
|
|
99
|
-
# Process relative paths in content
|
|
100
|
-
skill_dir = skill_path.parent
|
|
101
|
-
processed_content = self._process_skill_paths(markdown_content, skill_dir)
|
|
102
|
-
|
|
103
85
|
# Create Skill object
|
|
104
86
|
license_val = frontmatter.get("license")
|
|
105
87
|
allowed_tools_val = frontmatter.get("allowed-tools")
|
|
@@ -118,12 +100,12 @@ class SkillLoader:
|
|
|
118
100
|
skill = Skill(
|
|
119
101
|
name=name,
|
|
120
102
|
description=description,
|
|
121
|
-
content=processed_content,
|
|
122
103
|
location=location,
|
|
123
104
|
license=str(license_val) if license_val is not None else None,
|
|
124
105
|
allowed_tools=allowed_tools,
|
|
125
106
|
metadata=metadata,
|
|
126
|
-
skill_path=skill_path,
|
|
107
|
+
skill_path=skill_path.resolve(),
|
|
108
|
+
base_dir=skill_path.parent.resolve(),
|
|
127
109
|
)
|
|
128
110
|
|
|
129
111
|
return skill
|
|
@@ -144,6 +126,15 @@ class SkillLoader:
|
|
|
144
126
|
List of successfully loaded Skill objects
|
|
145
127
|
"""
|
|
146
128
|
skills: list[Skill] = []
|
|
129
|
+
priority = {"system": 0, "user": 1, "project": 2}
|
|
130
|
+
|
|
131
|
+
def register(skill: Skill) -> None:
|
|
132
|
+
existing = self.loaded_skills.get(skill.name)
|
|
133
|
+
if existing is None:
|
|
134
|
+
self.loaded_skills[skill.name] = skill
|
|
135
|
+
return
|
|
136
|
+
if priority.get(skill.location, -1) >= priority.get(existing.location, -1):
|
|
137
|
+
self.loaded_skills[skill.name] = skill
|
|
147
138
|
|
|
148
139
|
# Load system-level skills first (lowest priority, can be overridden)
|
|
149
140
|
system_dir = self.SYSTEM_SKILLS_DIR.expanduser()
|
|
@@ -152,7 +143,7 @@ class SkillLoader:
|
|
|
152
143
|
skill = self.load_skill(skill_file, location="system")
|
|
153
144
|
if skill:
|
|
154
145
|
skills.append(skill)
|
|
155
|
-
|
|
146
|
+
register(skill)
|
|
156
147
|
|
|
157
148
|
# Load user-level skills (override system skills if same name)
|
|
158
149
|
for user_dir in self.USER_SKILLS_DIRS:
|
|
@@ -165,7 +156,7 @@ class SkillLoader:
|
|
|
165
156
|
skill = self.load_skill(skill_file, location="user")
|
|
166
157
|
if skill:
|
|
167
158
|
skills.append(skill)
|
|
168
|
-
|
|
159
|
+
register(skill)
|
|
169
160
|
|
|
170
161
|
# Load project-level skills (override user skills if same name)
|
|
171
162
|
project_dir = self.PROJECT_SKILLS_DIR.resolve()
|
|
@@ -174,13 +165,14 @@ class SkillLoader:
|
|
|
174
165
|
skill = self.load_skill(skill_file, location="project")
|
|
175
166
|
if skill:
|
|
176
167
|
skills.append(skill)
|
|
177
|
-
|
|
168
|
+
register(skill)
|
|
178
169
|
|
|
179
170
|
# Log discovery summary
|
|
180
|
-
if
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
171
|
+
if self.loaded_skills:
|
|
172
|
+
selected = list(self.loaded_skills.values())
|
|
173
|
+
system_count = sum(1 for s in selected if s.location == "system")
|
|
174
|
+
user_count = sum(1 for s in selected if s.location == "user")
|
|
175
|
+
project_count = sum(1 for s in selected if s.location == "project")
|
|
184
176
|
parts: list[str] = []
|
|
185
177
|
if system_count > 0:
|
|
186
178
|
parts.append(f"{system_count} system")
|
|
@@ -188,7 +180,7 @@ class SkillLoader:
|
|
|
188
180
|
parts.append(f"{user_count} user")
|
|
189
181
|
if project_count > 0:
|
|
190
182
|
parts.append(f"{project_count} project")
|
|
191
|
-
log_debug(f"
|
|
183
|
+
log_debug(f"Loaded {len(self.loaded_skills)} Claude Skills ({', '.join(parts)})")
|
|
192
184
|
|
|
193
185
|
return skills
|
|
194
186
|
|
|
@@ -224,62 +216,14 @@ class SkillLoader:
|
|
|
224
216
|
XML string with all skill metadata
|
|
225
217
|
"""
|
|
226
218
|
xml_parts: list[str] = []
|
|
227
|
-
|
|
228
|
-
|
|
219
|
+
# Prefer showing higher-priority skills first (project > user > system).
|
|
220
|
+
location_order = {"project": 0, "user": 1, "system": 2}
|
|
221
|
+
for skill in sorted(self.loaded_skills.values(), key=lambda s: location_order.get(s.location, 3)):
|
|
222
|
+
xml_parts.append(
|
|
223
|
+
f"""<skill>
|
|
229
224
|
<name>{skill.name}</name>
|
|
230
225
|
<description>{skill.description}</description>
|
|
231
|
-
<location>{skill.
|
|
232
|
-
</skill>"""
|
|
226
|
+
<location>{skill.skill_path}</location>
|
|
227
|
+
</skill>"""
|
|
228
|
+
)
|
|
233
229
|
return "\n".join(xml_parts)
|
|
234
|
-
|
|
235
|
-
def _process_skill_paths(self, content: str, skill_dir: Path) -> str:
|
|
236
|
-
"""Convert relative paths to absolute paths for Level 3+
|
|
237
|
-
|
|
238
|
-
Supports:
|
|
239
|
-
- scripts/, examples/, templates/, reference/ directories
|
|
240
|
-
- Markdown document references
|
|
241
|
-
- Markdown links [text](path)
|
|
242
|
-
|
|
243
|
-
Args:
|
|
244
|
-
content: Original skill content
|
|
245
|
-
skill_dir: Directory containing the SKILL.md file
|
|
246
|
-
|
|
247
|
-
Returns:
|
|
248
|
-
Content with absolute paths
|
|
249
|
-
"""
|
|
250
|
-
# Pattern 1: Directory-based paths (scripts/, examples/, etc.)
|
|
251
|
-
# e.g., "python scripts/generate.py" -> "python /abs/path/to/scripts/generate.py"
|
|
252
|
-
dir_pattern = r"\b(scripts|examples|templates|reference)/([^\s\)]+)"
|
|
253
|
-
|
|
254
|
-
def replace_dir_path(match: re.Match[str]) -> str:
|
|
255
|
-
directory = match.group(1)
|
|
256
|
-
filename = match.group(2)
|
|
257
|
-
abs_path = skill_dir / directory / filename
|
|
258
|
-
return str(abs_path)
|
|
259
|
-
|
|
260
|
-
content = re.sub(dir_pattern, replace_dir_path, content)
|
|
261
|
-
|
|
262
|
-
# Pattern 2: Markdown links [text](./path or path)
|
|
263
|
-
# e.g., "[Guide](./docs/guide.md)" -> "[Guide](`/abs/path/to/docs/guide.md`) (use the Read tool to access)"
|
|
264
|
-
link_pattern = r"\[([^\]]+)\]\((\./)?([^\)]+\.md)\)"
|
|
265
|
-
|
|
266
|
-
def replace_link(match: re.Match[str]) -> str:
|
|
267
|
-
text = match.group(1)
|
|
268
|
-
filename = match.group(3)
|
|
269
|
-
abs_path = skill_dir / filename
|
|
270
|
-
return f"[{text}](`{abs_path}`) (use the Read tool to access)"
|
|
271
|
-
|
|
272
|
-
content = re.sub(link_pattern, replace_link, content)
|
|
273
|
-
|
|
274
|
-
# Pattern 3: Standalone markdown references
|
|
275
|
-
# e.g., "see reference.md" -> "see `/abs/path/to/reference.md` (use the Read tool to access)"
|
|
276
|
-
standalone_pattern = r"(?<!\])\b(\w+\.md)\b(?!\))"
|
|
277
|
-
|
|
278
|
-
def replace_standalone(match: re.Match[str]) -> str:
|
|
279
|
-
filename = match.group(1)
|
|
280
|
-
abs_path = skill_dir / filename
|
|
281
|
-
return f"`{abs_path}` (use the Read tool to access)"
|
|
282
|
-
|
|
283
|
-
content = re.sub(standalone_pattern, replace_standalone, content)
|
|
284
|
-
|
|
285
|
-
return content
|
|
@@ -68,3 +68,41 @@ def list_skill_names() -> list[str]:
|
|
|
68
68
|
List of skill names
|
|
69
69
|
"""
|
|
70
70
|
return _ensure_initialized().list_skills()
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def format_available_skills_for_system_prompt() -> str:
|
|
74
|
+
"""Format skills metadata for inclusion in the system prompt.
|
|
75
|
+
|
|
76
|
+
This follows the progressive-disclosure approach:
|
|
77
|
+
- Keep only name/description + file location in the always-on system prompt
|
|
78
|
+
- Load the full SKILL.md content on demand via the Read tool when needed
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
try:
|
|
82
|
+
loader = _ensure_initialized()
|
|
83
|
+
skills_xml = loader.get_skills_xml().strip()
|
|
84
|
+
if not skills_xml:
|
|
85
|
+
return ""
|
|
86
|
+
|
|
87
|
+
return f"""\
|
|
88
|
+
# Skills
|
|
89
|
+
|
|
90
|
+
Skills are optional task-specific instructions stored as `SKILL.md` files.
|
|
91
|
+
|
|
92
|
+
How to use skills:
|
|
93
|
+
- Use the metadata in <available_skills> to decide whether a skill applies.
|
|
94
|
+
- When the task matches a skill's description, use the `Read` tool to load the `SKILL.md` at the given <location>.
|
|
95
|
+
- If the user explicitly activates a skill by starting their message with `$skill-name`, prioritize that skill.
|
|
96
|
+
|
|
97
|
+
Important:
|
|
98
|
+
- Only use skills listed in <available_skills> below.
|
|
99
|
+
- Keep context small: do NOT load skill files unless needed.
|
|
100
|
+
|
|
101
|
+
The list below is metadata only (name/description/location). The full instructions live in the referenced file.
|
|
102
|
+
|
|
103
|
+
<available_skills>
|
|
104
|
+
{skills_xml}
|
|
105
|
+
</available_skills>"""
|
|
106
|
+
except Exception:
|
|
107
|
+
# Skills are an optional enhancement; do not fail prompt construction if discovery breaks.
|
|
108
|
+
return ""
|
|
@@ -30,6 +30,7 @@ def ensure_commands_loaded() -> None:
|
|
|
30
30
|
|
|
31
31
|
# Import and register commands in display order
|
|
32
32
|
from .clear_cmd import ClearCommand
|
|
33
|
+
from .copy_cmd import CopyCommand
|
|
33
34
|
from .debug_cmd import DebugCommand
|
|
34
35
|
from .export_cmd import ExportCommand
|
|
35
36
|
from .export_online_cmd import ExportOnlineCommand
|
|
@@ -49,6 +50,7 @@ def ensure_commands_loaded() -> None:
|
|
|
49
50
|
register(RefreshTerminalCommand())
|
|
50
51
|
register(ThinkingCommand())
|
|
51
52
|
register(ModelCommand())
|
|
53
|
+
register(CopyCommand())
|
|
52
54
|
register(ForkSessionCommand())
|
|
53
55
|
register(ResumeCommand())
|
|
54
56
|
load_prompt_commands()
|
|
@@ -66,6 +68,7 @@ def ensure_commands_loaded() -> None:
|
|
|
66
68
|
def __getattr__(name: str) -> object:
|
|
67
69
|
_commands_map = {
|
|
68
70
|
"ClearCommand": "clear_cmd",
|
|
71
|
+
"CopyCommand": "copy_cmd",
|
|
69
72
|
"DebugCommand": "debug_cmd",
|
|
70
73
|
"ExportCommand": "export_cmd",
|
|
71
74
|
"ExportOnlineCommand": "export_online_cmd",
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
from klaude_code.protocol import commands, events, message, model
|
|
2
|
+
from klaude_code.tui.input.clipboard import copy_to_clipboard
|
|
3
|
+
|
|
4
|
+
from .command_abc import Agent, CommandABC, CommandResult
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class CopyCommand(CommandABC):
|
|
8
|
+
"""Copy the last assistant message to system clipboard."""
|
|
9
|
+
|
|
10
|
+
@property
|
|
11
|
+
def name(self) -> commands.CommandName:
|
|
12
|
+
return commands.CommandName.COPY
|
|
13
|
+
|
|
14
|
+
@property
|
|
15
|
+
def summary(self) -> str:
|
|
16
|
+
return "Copy last assistant message to clipboard"
|
|
17
|
+
|
|
18
|
+
async def run(self, agent: Agent, user_input: message.UserInputPayload) -> CommandResult:
|
|
19
|
+
del user_input # unused
|
|
20
|
+
|
|
21
|
+
last = _get_last_assistant_text(agent.session.conversation_history)
|
|
22
|
+
if not last:
|
|
23
|
+
return _developer_message(agent, "(no assistant message to copy)", self.name)
|
|
24
|
+
|
|
25
|
+
copy_to_clipboard(last)
|
|
26
|
+
return _developer_message(agent, "Copied last assistant message to clipboard.", self.name)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _get_last_assistant_text(history: list[message.HistoryEvent]) -> str:
|
|
30
|
+
for item in reversed(history):
|
|
31
|
+
if not isinstance(item, message.AssistantMessage):
|
|
32
|
+
continue
|
|
33
|
+
content = message.join_text_parts(item.parts)
|
|
34
|
+
images = [part for part in item.parts if isinstance(part, message.ImageFilePart)]
|
|
35
|
+
formatted = message.format_saved_images(images, content)
|
|
36
|
+
return formatted.strip()
|
|
37
|
+
return ""
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _developer_message(agent: Agent, content: str, command_name: commands.CommandName) -> CommandResult:
|
|
41
|
+
return CommandResult(
|
|
42
|
+
events=[
|
|
43
|
+
events.DeveloperMessageEvent(
|
|
44
|
+
session_id=agent.session.id,
|
|
45
|
+
item=message.DeveloperMessage(
|
|
46
|
+
parts=message.text_parts_from_str(content),
|
|
47
|
+
ui_extra=model.build_command_output_extra(command_name),
|
|
48
|
+
),
|
|
49
|
+
)
|
|
50
|
+
],
|
|
51
|
+
persist_user_input=False,
|
|
52
|
+
persist_events=False,
|
|
53
|
+
)
|
|
@@ -37,7 +37,6 @@ MARK_MERMAID = "⧉"
|
|
|
37
37
|
MARK_WEB_FETCH = "→"
|
|
38
38
|
MARK_WEB_SEARCH = "✱"
|
|
39
39
|
MARK_DONE = "✔"
|
|
40
|
-
MARK_SKILL = "✪"
|
|
41
40
|
|
|
42
41
|
# Todo status markers
|
|
43
42
|
MARK_TODO_PENDING = "▢"
|
|
@@ -491,7 +490,7 @@ def render_mermaid_tool_result(
|
|
|
491
490
|
|
|
492
491
|
link_info = _extract_mermaid_link(tr.ui_extra)
|
|
493
492
|
if link_info is None:
|
|
494
|
-
return render_generic_tool_result(tr.result, is_error=tr.
|
|
493
|
+
return render_generic_tool_result(tr.result, is_error=tr.is_error)
|
|
495
494
|
|
|
496
495
|
use_osc8 = supports_osc8_hyperlinks()
|
|
497
496
|
viewer = _render_mermaid_viewer_link(tr, link_info, use_osc8=use_osc8)
|
|
@@ -537,7 +536,6 @@ _TOOL_ACTIVE_FORM: dict[str, str] = {
|
|
|
537
536
|
tools.WRITE: "Writing",
|
|
538
537
|
tools.TODO_WRITE: "Planning",
|
|
539
538
|
tools.UPDATE_PLAN: "Planning",
|
|
540
|
-
tools.SKILL: "Skilling",
|
|
541
539
|
tools.MERMAID: "Diagramming",
|
|
542
540
|
tools.WEB_FETCH: "Fetching Web",
|
|
543
541
|
tools.WEB_SEARCH: "Searching Web",
|
|
@@ -589,8 +587,6 @@ def render_tool_call(e: events.ToolCallEvent) -> RenderableType | None:
|
|
|
589
587
|
return render_update_plan_tool_call(e.arguments)
|
|
590
588
|
case tools.MERMAID:
|
|
591
589
|
return render_mermaid_tool_call(e.arguments)
|
|
592
|
-
case tools.SKILL:
|
|
593
|
-
return render_generic_tool_call(e.tool_name, e.arguments, MARK_SKILL)
|
|
594
590
|
case tools.REPORT_BACK:
|
|
595
591
|
return render_report_back_tool_call()
|
|
596
592
|
case tools.WEB_FETCH:
|
|
@@ -649,7 +645,7 @@ def render_tool_result(
|
|
|
649
645
|
return TreeQuote.for_tool_result(content, is_last=e.is_last_in_turn)
|
|
650
646
|
|
|
651
647
|
# Handle error case
|
|
652
|
-
if e.
|
|
648
|
+
if e.is_error and e.ui_extra is None:
|
|
653
649
|
return wrap(render_generic_tool_result(e.result, is_error=True))
|
|
654
650
|
|
|
655
651
|
# Render multiple ui blocks if present
|
|
@@ -666,7 +662,7 @@ def render_tool_result(
|
|
|
666
662
|
# Show truncation info if output was truncated and saved to file
|
|
667
663
|
truncation_info = get_truncation_info(e)
|
|
668
664
|
if truncation_info:
|
|
669
|
-
result = render_generic_tool_result(e.result, is_error=e.
|
|
665
|
+
result = render_generic_tool_result(e.result, is_error=e.is_error)
|
|
670
666
|
return wrap(Group(render_truncation_info(truncation_info), result))
|
|
671
667
|
|
|
672
668
|
diff_ui = _extract_diff(e.ui_extra)
|
|
@@ -675,7 +671,7 @@ def render_tool_result(
|
|
|
675
671
|
def _render_fallback() -> TreeQuote:
|
|
676
672
|
if len(e.result.strip()) == 0:
|
|
677
673
|
return wrap(render_generic_tool_result("(no content)"))
|
|
678
|
-
return wrap(render_generic_tool_result(e.result, is_error=e.
|
|
674
|
+
return wrap(render_generic_tool_result(e.result, is_error=e.is_error))
|
|
679
675
|
|
|
680
676
|
match e.tool_name:
|
|
681
677
|
case tools.READ:
|
|
@@ -521,13 +521,15 @@ class DisplayStateMachine:
|
|
|
521
521
|
self._spinner.finish_sub_agent_tool_call(e.tool_call_id, get_tool_active_form(e.tool_name))
|
|
522
522
|
cmds.extend(self._spinner_update_commands())
|
|
523
523
|
|
|
524
|
-
if s.is_sub_agent and e.
|
|
524
|
+
if s.is_sub_agent and not e.is_error:
|
|
525
525
|
return cmds
|
|
526
526
|
|
|
527
527
|
cmds.append(RenderToolResult(event=e, is_sub_agent_session=s.is_sub_agent))
|
|
528
528
|
return cmds
|
|
529
529
|
|
|
530
530
|
case events.TaskMetadataEvent() as e:
|
|
531
|
+
cmds.append(EndThinkingStream(e.session_id))
|
|
532
|
+
cmds.append(EndAssistantStream(e.session_id))
|
|
531
533
|
cmds.append(RenderTaskMetadata(e))
|
|
532
534
|
return cmds
|
|
533
535
|
|
|
@@ -396,7 +396,7 @@ class TUICommandRenderer:
|
|
|
396
396
|
if c_tools.is_sub_agent_tool(e.tool_name):
|
|
397
397
|
return
|
|
398
398
|
|
|
399
|
-
if is_sub_agent and e.
|
|
399
|
+
if is_sub_agent and e.is_error:
|
|
400
400
|
error_msg = truncate_head(e.result)
|
|
401
401
|
self.print(c_errors.render_tool_error(error_msg))
|
|
402
402
|
return
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
Execute a skill within the main conversation
|
|
2
|
-
|
|
3
|
-
<skills_instructions>
|
|
4
|
-
When users ask you to perform tasks, check if any of the available skills below can help complete the task more effectively. Skills provide specialized capabilities and domain knowledge.
|
|
5
|
-
|
|
6
|
-
How to use skills:
|
|
7
|
-
- Invoke skills using this tool with the skill name only (no arguments)
|
|
8
|
-
- When you invoke a skill, you will see <command-message>The "{name}" skill is loading</command-message>
|
|
9
|
-
- The skill's prompt will expand and provide detailed instructions on how to complete the task
|
|
10
|
-
|
|
11
|
-
Examples:
|
|
12
|
-
- command: "pdf" - invoke the pdf skill
|
|
13
|
-
- command: "xlsx" - invoke the xlsx skill
|
|
14
|
-
- command: "document-skills:pdf" - invoke using fully qualified name
|
|
15
|
-
|
|
16
|
-
Important:
|
|
17
|
-
- Only use skills listed in <available_skills> below
|
|
18
|
-
- Do not invoke a skill that is already running
|
|
19
|
-
- Do not use this tool for built-in CLI commands (like /help, /clear, etc.)
|
|
20
|
-
</skills_instructions>
|
|
21
|
-
|
|
22
|
-
<available_skills>
|
|
23
|
-
$skills_xml
|
|
24
|
-
</available_skills>
|