klaude-code 1.2.6__py3-none-any.whl → 1.8.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- klaude_code/auth/__init__.py +24 -0
- klaude_code/auth/codex/__init__.py +20 -0
- klaude_code/auth/codex/exceptions.py +17 -0
- klaude_code/auth/codex/jwt_utils.py +45 -0
- klaude_code/auth/codex/oauth.py +229 -0
- klaude_code/auth/codex/token_manager.py +84 -0
- klaude_code/cli/auth_cmd.py +73 -0
- klaude_code/cli/config_cmd.py +91 -0
- klaude_code/cli/cost_cmd.py +338 -0
- klaude_code/cli/debug.py +78 -0
- klaude_code/cli/list_model.py +307 -0
- klaude_code/cli/main.py +233 -134
- klaude_code/cli/runtime.py +309 -117
- klaude_code/{version.py → cli/self_update.py} +114 -5
- klaude_code/cli/session_cmd.py +37 -21
- klaude_code/command/__init__.py +88 -27
- klaude_code/command/clear_cmd.py +8 -7
- klaude_code/command/command_abc.py +31 -31
- klaude_code/command/debug_cmd.py +79 -0
- klaude_code/command/export_cmd.py +19 -53
- klaude_code/command/export_online_cmd.py +154 -0
- klaude_code/command/fork_session_cmd.py +267 -0
- klaude_code/command/help_cmd.py +7 -8
- klaude_code/command/model_cmd.py +60 -10
- klaude_code/command/model_select.py +84 -0
- klaude_code/command/prompt-jj-describe.md +32 -0
- klaude_code/command/prompt_command.py +19 -11
- klaude_code/command/refresh_cmd.py +8 -10
- klaude_code/command/registry.py +139 -40
- klaude_code/command/release_notes_cmd.py +84 -0
- klaude_code/command/resume_cmd.py +111 -0
- klaude_code/command/status_cmd.py +104 -60
- klaude_code/command/terminal_setup_cmd.py +7 -9
- klaude_code/command/thinking_cmd.py +98 -0
- klaude_code/config/__init__.py +14 -6
- klaude_code/config/assets/__init__.py +1 -0
- klaude_code/config/assets/builtin_config.yaml +303 -0
- klaude_code/config/builtin_config.py +38 -0
- klaude_code/config/config.py +378 -109
- klaude_code/config/select_model.py +117 -53
- klaude_code/config/thinking.py +269 -0
- klaude_code/{const/__init__.py → const.py} +50 -19
- klaude_code/core/agent.py +20 -28
- klaude_code/core/executor.py +327 -112
- klaude_code/core/manager/__init__.py +2 -4
- klaude_code/core/manager/llm_clients.py +1 -15
- klaude_code/core/manager/llm_clients_builder.py +10 -11
- klaude_code/core/manager/sub_agent_manager.py +37 -6
- klaude_code/core/prompt.py +63 -44
- klaude_code/core/prompts/prompt-claude-code.md +2 -13
- klaude_code/core/prompts/prompt-codex-gpt-5-1-codex-max.md +117 -0
- klaude_code/core/prompts/prompt-codex-gpt-5-2-codex.md +117 -0
- klaude_code/core/prompts/prompt-codex.md +9 -42
- klaude_code/core/prompts/prompt-minimal.md +12 -0
- klaude_code/core/prompts/{prompt-subagent-explore.md → prompt-sub-agent-explore.md} +16 -3
- klaude_code/core/prompts/{prompt-subagent-oracle.md → prompt-sub-agent-oracle.md} +1 -2
- klaude_code/core/prompts/prompt-sub-agent-web.md +51 -0
- klaude_code/core/reminders.py +283 -95
- klaude_code/core/task.py +113 -75
- klaude_code/core/tool/__init__.py +24 -31
- klaude_code/core/tool/file/_utils.py +36 -0
- klaude_code/core/tool/file/apply_patch.py +17 -25
- klaude_code/core/tool/file/apply_patch_tool.py +57 -77
- klaude_code/core/tool/file/diff_builder.py +151 -0
- klaude_code/core/tool/file/edit_tool.py +50 -63
- klaude_code/core/tool/file/move_tool.md +41 -0
- klaude_code/core/tool/file/move_tool.py +435 -0
- klaude_code/core/tool/file/read_tool.md +1 -1
- klaude_code/core/tool/file/read_tool.py +86 -86
- klaude_code/core/tool/file/write_tool.py +59 -69
- klaude_code/core/tool/report_back_tool.py +84 -0
- klaude_code/core/tool/shell/bash_tool.py +265 -22
- klaude_code/core/tool/shell/command_safety.py +3 -6
- klaude_code/core/tool/{memory → skill}/skill_tool.py +16 -26
- klaude_code/core/tool/sub_agent_tool.py +13 -2
- klaude_code/core/tool/todo/todo_write_tool.md +0 -157
- klaude_code/core/tool/todo/todo_write_tool.py +1 -1
- klaude_code/core/tool/todo/todo_write_tool_raw.md +182 -0
- klaude_code/core/tool/todo/update_plan_tool.py +1 -1
- klaude_code/core/tool/tool_abc.py +18 -0
- klaude_code/core/tool/tool_context.py +27 -12
- klaude_code/core/tool/tool_registry.py +7 -7
- klaude_code/core/tool/tool_runner.py +44 -36
- klaude_code/core/tool/truncation.py +29 -14
- klaude_code/core/tool/web/mermaid_tool.md +43 -0
- klaude_code/core/tool/web/mermaid_tool.py +2 -5
- klaude_code/core/tool/web/web_fetch_tool.md +1 -1
- klaude_code/core/tool/web/web_fetch_tool.py +112 -22
- klaude_code/core/tool/web/web_search_tool.md +23 -0
- klaude_code/core/tool/web/web_search_tool.py +130 -0
- klaude_code/core/turn.py +168 -66
- klaude_code/llm/__init__.py +2 -10
- klaude_code/llm/anthropic/client.py +190 -178
- klaude_code/llm/anthropic/input.py +39 -15
- klaude_code/llm/bedrock/__init__.py +3 -0
- klaude_code/llm/bedrock/client.py +60 -0
- klaude_code/llm/client.py +7 -21
- klaude_code/llm/codex/__init__.py +5 -0
- klaude_code/llm/codex/client.py +149 -0
- klaude_code/llm/google/__init__.py +3 -0
- klaude_code/llm/google/client.py +309 -0
- klaude_code/llm/google/input.py +215 -0
- klaude_code/llm/input_common.py +3 -9
- klaude_code/llm/openai_compatible/client.py +72 -164
- klaude_code/llm/openai_compatible/input.py +6 -4
- klaude_code/llm/openai_compatible/stream.py +273 -0
- klaude_code/llm/openai_compatible/tool_call_accumulator.py +17 -1
- klaude_code/llm/openrouter/client.py +89 -160
- klaude_code/llm/openrouter/input.py +18 -30
- klaude_code/llm/openrouter/reasoning.py +118 -0
- klaude_code/llm/registry.py +39 -7
- klaude_code/llm/responses/client.py +184 -171
- klaude_code/llm/responses/input.py +20 -1
- klaude_code/llm/usage.py +17 -12
- klaude_code/protocol/commands.py +17 -1
- klaude_code/protocol/events.py +31 -4
- klaude_code/protocol/llm_param.py +13 -10
- klaude_code/protocol/model.py +232 -29
- klaude_code/protocol/op.py +90 -1
- klaude_code/protocol/op_handler.py +35 -1
- klaude_code/protocol/sub_agent/__init__.py +117 -0
- klaude_code/protocol/sub_agent/explore.py +63 -0
- klaude_code/protocol/sub_agent/oracle.py +91 -0
- klaude_code/protocol/sub_agent/task.py +61 -0
- klaude_code/protocol/sub_agent/web.py +79 -0
- klaude_code/protocol/tools.py +4 -2
- klaude_code/session/__init__.py +2 -2
- klaude_code/session/codec.py +71 -0
- klaude_code/session/export.py +293 -86
- klaude_code/session/selector.py +89 -67
- klaude_code/session/session.py +320 -309
- klaude_code/session/store.py +220 -0
- klaude_code/session/templates/export_session.html +595 -83
- klaude_code/session/templates/mermaid_viewer.html +926 -0
- klaude_code/skill/__init__.py +27 -0
- klaude_code/skill/assets/deslop/SKILL.md +17 -0
- klaude_code/skill/assets/dev-docs/SKILL.md +108 -0
- klaude_code/skill/assets/handoff/SKILL.md +39 -0
- klaude_code/skill/assets/jj-workspace/SKILL.md +20 -0
- klaude_code/skill/assets/skill-creator/SKILL.md +139 -0
- klaude_code/{core/tool/memory/skill_loader.py → skill/loader.py} +55 -15
- klaude_code/skill/manager.py +70 -0
- klaude_code/skill/system_skills.py +192 -0
- klaude_code/trace/__init__.py +20 -2
- klaude_code/trace/log.py +150 -5
- klaude_code/ui/__init__.py +4 -9
- klaude_code/ui/core/input.py +1 -1
- klaude_code/ui/core/stage_manager.py +7 -7
- klaude_code/ui/modes/debug/display.py +2 -1
- klaude_code/ui/modes/repl/__init__.py +3 -48
- klaude_code/ui/modes/repl/clipboard.py +5 -5
- klaude_code/ui/modes/repl/completers.py +487 -123
- klaude_code/ui/modes/repl/display.py +5 -4
- klaude_code/ui/modes/repl/event_handler.py +370 -117
- klaude_code/ui/modes/repl/input_prompt_toolkit.py +552 -105
- klaude_code/ui/modes/repl/key_bindings.py +146 -23
- klaude_code/ui/modes/repl/renderer.py +189 -99
- klaude_code/ui/renderers/assistant.py +9 -2
- klaude_code/ui/renderers/bash_syntax.py +178 -0
- klaude_code/ui/renderers/common.py +78 -0
- klaude_code/ui/renderers/developer.py +104 -48
- klaude_code/ui/renderers/diffs.py +87 -6
- klaude_code/ui/renderers/errors.py +11 -6
- klaude_code/ui/renderers/mermaid_viewer.py +57 -0
- klaude_code/ui/renderers/metadata.py +112 -76
- klaude_code/ui/renderers/sub_agent.py +92 -7
- klaude_code/ui/renderers/thinking.py +40 -18
- klaude_code/ui/renderers/tools.py +405 -227
- klaude_code/ui/renderers/user_input.py +73 -13
- klaude_code/ui/rich/__init__.py +10 -1
- klaude_code/ui/rich/cjk_wrap.py +228 -0
- klaude_code/ui/rich/code_panel.py +131 -0
- klaude_code/ui/rich/live.py +17 -0
- klaude_code/ui/rich/markdown.py +305 -170
- klaude_code/ui/rich/searchable_text.py +10 -13
- klaude_code/ui/rich/status.py +190 -49
- klaude_code/ui/rich/theme.py +135 -39
- klaude_code/ui/terminal/__init__.py +55 -0
- klaude_code/ui/terminal/color.py +1 -1
- klaude_code/ui/terminal/control.py +13 -22
- klaude_code/ui/terminal/notifier.py +44 -4
- klaude_code/ui/terminal/selector.py +658 -0
- klaude_code/ui/utils/common.py +0 -18
- klaude_code-1.8.0.dist-info/METADATA +377 -0
- klaude_code-1.8.0.dist-info/RECORD +219 -0
- {klaude_code-1.2.6.dist-info → klaude_code-1.8.0.dist-info}/entry_points.txt +1 -0
- klaude_code/command/diff_cmd.py +0 -138
- klaude_code/command/prompt-dev-docs-update.md +0 -56
- klaude_code/command/prompt-dev-docs.md +0 -46
- klaude_code/config/list_model.py +0 -162
- klaude_code/core/manager/agent_manager.py +0 -127
- klaude_code/core/prompts/prompt-subagent-webfetch.md +0 -46
- klaude_code/core/tool/file/multi_edit_tool.md +0 -42
- klaude_code/core/tool/file/multi_edit_tool.py +0 -199
- klaude_code/core/tool/memory/memory_tool.md +0 -16
- klaude_code/core/tool/memory/memory_tool.py +0 -462
- klaude_code/llm/openrouter/reasoning_handler.py +0 -209
- klaude_code/protocol/sub_agent.py +0 -348
- klaude_code/ui/utils/debouncer.py +0 -42
- klaude_code-1.2.6.dist-info/METADATA +0 -178
- klaude_code-1.2.6.dist-info/RECORD +0 -167
- /klaude_code/core/prompts/{prompt-subagent.md → prompt-sub-agent.md} +0 -0
- /klaude_code/core/tool/{memory → skill}/__init__.py +0 -0
- /klaude_code/core/tool/{memory → skill}/skill_tool.md +0 -0
- {klaude_code-1.2.6.dist-info → klaude_code-1.8.0.dist-info}/WHEEL +0 -0
klaude_code/command/diff_cmd.py
DELETED
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
import subprocess
|
|
2
|
-
from pathlib import Path
|
|
3
|
-
|
|
4
|
-
from klaude_code.command.command_abc import CommandABC, CommandResult
|
|
5
|
-
from klaude_code.command.registry import register_command
|
|
6
|
-
from klaude_code.core.agent import Agent
|
|
7
|
-
from klaude_code.protocol import commands, events, model
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
@register_command
|
|
11
|
-
class DiffCommand(CommandABC):
|
|
12
|
-
"""Show git diff for the current repository."""
|
|
13
|
-
|
|
14
|
-
@property
|
|
15
|
-
def name(self) -> commands.CommandName:
|
|
16
|
-
return commands.CommandName.DIFF
|
|
17
|
-
|
|
18
|
-
@property
|
|
19
|
-
def summary(self) -> str:
|
|
20
|
-
return "Show git diff"
|
|
21
|
-
|
|
22
|
-
async def run(self, raw: str, agent: Agent) -> CommandResult:
|
|
23
|
-
try:
|
|
24
|
-
# Check if current directory is in a git repository
|
|
25
|
-
git_check = subprocess.run(
|
|
26
|
-
["git", "rev-parse", "--is-inside-work-tree"],
|
|
27
|
-
cwd=Path.cwd(),
|
|
28
|
-
capture_output=True,
|
|
29
|
-
text=True,
|
|
30
|
-
timeout=5.0,
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
if git_check.returncode != 0:
|
|
34
|
-
# Not in a git repository
|
|
35
|
-
event = events.DeveloperMessageEvent(
|
|
36
|
-
session_id=agent.session.id,
|
|
37
|
-
item=model.DeveloperMessageItem(
|
|
38
|
-
content="No in a git repo",
|
|
39
|
-
command_output=model.CommandOutput(command_name=self.name, is_error=True),
|
|
40
|
-
),
|
|
41
|
-
)
|
|
42
|
-
return CommandResult(events=[event])
|
|
43
|
-
|
|
44
|
-
# Run git diff in current directory
|
|
45
|
-
result = subprocess.run(
|
|
46
|
-
["git", "diff", "HEAD"],
|
|
47
|
-
cwd=Path.cwd(),
|
|
48
|
-
capture_output=True,
|
|
49
|
-
text=True,
|
|
50
|
-
timeout=10.0,
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
if result.returncode != 0:
|
|
54
|
-
# Git command failed
|
|
55
|
-
error_msg = result.stderr.strip() or "git diff command failed"
|
|
56
|
-
event = events.DeveloperMessageEvent(
|
|
57
|
-
session_id=agent.session.id,
|
|
58
|
-
item=model.DeveloperMessageItem(
|
|
59
|
-
content=f"Error: {error_msg}",
|
|
60
|
-
command_output=model.CommandOutput(command_name=self.name, is_error=True),
|
|
61
|
-
),
|
|
62
|
-
)
|
|
63
|
-
return CommandResult(events=[event])
|
|
64
|
-
|
|
65
|
-
diff_output = result.stdout.strip()
|
|
66
|
-
|
|
67
|
-
# Get untracked files
|
|
68
|
-
untracked_result = subprocess.run(
|
|
69
|
-
["git", "ls-files", "--others", "--exclude-standard"],
|
|
70
|
-
cwd=Path.cwd(),
|
|
71
|
-
capture_output=True,
|
|
72
|
-
text=True,
|
|
73
|
-
timeout=10.0,
|
|
74
|
-
)
|
|
75
|
-
|
|
76
|
-
untracked_files = untracked_result.stdout.strip()
|
|
77
|
-
|
|
78
|
-
# Combine diff output and untracked files
|
|
79
|
-
output_parts: list[str] = []
|
|
80
|
-
|
|
81
|
-
if diff_output:
|
|
82
|
-
output_parts.append(diff_output)
|
|
83
|
-
|
|
84
|
-
if untracked_files:
|
|
85
|
-
untracked_lines = untracked_files.split("\n")
|
|
86
|
-
untracked_section = "git ls-files --others --exclude-standard\n" + "\n".join(
|
|
87
|
-
f"{file}" for file in untracked_lines
|
|
88
|
-
)
|
|
89
|
-
output_parts.append(untracked_section)
|
|
90
|
-
|
|
91
|
-
if not output_parts:
|
|
92
|
-
# No changes and no untracked files
|
|
93
|
-
event = events.DeveloperMessageEvent(
|
|
94
|
-
session_id=agent.session.id,
|
|
95
|
-
item=model.DeveloperMessageItem(
|
|
96
|
-
content="", command_output=model.CommandOutput(command_name=self.name)
|
|
97
|
-
),
|
|
98
|
-
)
|
|
99
|
-
return CommandResult(events=[event])
|
|
100
|
-
|
|
101
|
-
# Has changes or untracked files
|
|
102
|
-
combined_output = "\n\n".join(output_parts)
|
|
103
|
-
event = events.DeveloperMessageEvent(
|
|
104
|
-
session_id=agent.session.id,
|
|
105
|
-
item=model.DeveloperMessageItem(
|
|
106
|
-
content=combined_output,
|
|
107
|
-
command_output=model.CommandOutput(command_name=self.name),
|
|
108
|
-
),
|
|
109
|
-
)
|
|
110
|
-
return CommandResult(events=[event])
|
|
111
|
-
|
|
112
|
-
except subprocess.TimeoutExpired:
|
|
113
|
-
event = events.DeveloperMessageEvent(
|
|
114
|
-
session_id=agent.session.id,
|
|
115
|
-
item=model.DeveloperMessageItem(
|
|
116
|
-
content="Error: git diff command timeout",
|
|
117
|
-
command_output=model.CommandOutput(command_name=self.name, is_error=True),
|
|
118
|
-
),
|
|
119
|
-
)
|
|
120
|
-
return CommandResult(events=[event])
|
|
121
|
-
except FileNotFoundError:
|
|
122
|
-
event = events.DeveloperMessageEvent(
|
|
123
|
-
session_id=agent.session.id,
|
|
124
|
-
item=model.DeveloperMessageItem(
|
|
125
|
-
content="Error: git command not found",
|
|
126
|
-
command_output=model.CommandOutput(command_name=self.name, is_error=True),
|
|
127
|
-
),
|
|
128
|
-
)
|
|
129
|
-
return CommandResult(events=[event])
|
|
130
|
-
except Exception as e:
|
|
131
|
-
event = events.DeveloperMessageEvent(
|
|
132
|
-
session_id=agent.session.id,
|
|
133
|
-
item=model.DeveloperMessageItem(
|
|
134
|
-
content=f"Error:{e}",
|
|
135
|
-
command_output=model.CommandOutput(command_name=self.name, is_error=True),
|
|
136
|
-
),
|
|
137
|
-
)
|
|
138
|
-
return CommandResult(events=[event])
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Update dev documentation before context compaction
|
|
3
|
-
from: https://github.com/diet103/claude-code-infrastructure-showcase/blob/main/.claude/commands/dev-docs-update.md
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
We're approaching context limits. Please update the development documentation to ensure seamless continuation after context reset.
|
|
7
|
-
|
|
8
|
-
## Required Updates
|
|
9
|
-
|
|
10
|
-
### 1. Update Active Task Documentation
|
|
11
|
-
For each task in `/dev/active/`:
|
|
12
|
-
- Update `[task-name]-context.md` with:
|
|
13
|
-
- Current implementation state
|
|
14
|
-
- Key decisions made this session
|
|
15
|
-
- Files modified and why
|
|
16
|
-
- Any blockers or issues discovered
|
|
17
|
-
- Next immediate steps
|
|
18
|
-
- Last Updated timestamp
|
|
19
|
-
|
|
20
|
-
- Update `[task-name]-tasks.md` with:
|
|
21
|
-
- Mark completed tasks as ✅
|
|
22
|
-
- Add any new tasks discovered
|
|
23
|
-
- Update in-progress tasks with current status
|
|
24
|
-
- Reorder priorities if needed
|
|
25
|
-
|
|
26
|
-
### 2. Capture Session Context
|
|
27
|
-
Include any relevant information about:
|
|
28
|
-
- Complex problems solved
|
|
29
|
-
- Architectural decisions made
|
|
30
|
-
- Tricky bugs found and fixed
|
|
31
|
-
- Integration points discovered
|
|
32
|
-
- Testing approaches used
|
|
33
|
-
- Performance optimizations made
|
|
34
|
-
|
|
35
|
-
### 3. Update Memory (if applicable)
|
|
36
|
-
- Store any new patterns or solutions in project memory/documentation
|
|
37
|
-
- Update entity relationships discovered
|
|
38
|
-
- Add observations about system behavior
|
|
39
|
-
|
|
40
|
-
### 4. Document Unfinished Work
|
|
41
|
-
- What was being worked on when context limit approached
|
|
42
|
-
- Exact state of any partially completed features
|
|
43
|
-
- Commands that need to be run on restart
|
|
44
|
-
- Any temporary workarounds that need permanent fixes
|
|
45
|
-
|
|
46
|
-
### 5. Create Handoff Notes
|
|
47
|
-
If switching to a new conversation:
|
|
48
|
-
- Exact file and line being edited
|
|
49
|
-
- The goal of current changes
|
|
50
|
-
- Any uncommitted changes that need attention
|
|
51
|
-
- Test commands to verify work
|
|
52
|
-
|
|
53
|
-
## Additional Context:
|
|
54
|
-
$ARGUMENTS
|
|
55
|
-
|
|
56
|
-
**Priority**: Focus on capturing information that would be hard to rediscover or reconstruct from code alone.
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Create a comprehensive strategic plan with structured task breakdown
|
|
3
|
-
from: https://github.com/diet103/claude-code-infrastructure-showcase/blob/main/.claude/commands/dev-docs.md
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
Create a comprehensive, actionable plan for:
|
|
7
|
-
$ARGUMENTS
|
|
8
|
-
|
|
9
|
-
## Instructions
|
|
10
|
-
|
|
11
|
-
1. **Analyze the request** and determine the scope of planning needed
|
|
12
|
-
2. **Examine relevant files** in the codebase to understand current state
|
|
13
|
-
3. **Create a structured plan** with:
|
|
14
|
-
- Executive Summary
|
|
15
|
-
- Current State Analysis
|
|
16
|
-
- Proposed Future State
|
|
17
|
-
- Implementation Phases (broken into sections)
|
|
18
|
-
- Detailed Tasks (actionable items with clear acceptance criteria)
|
|
19
|
-
- Risk Assessment and Mitigation Strategies
|
|
20
|
-
- Success Metrics
|
|
21
|
-
- Required Resources and Dependencies
|
|
22
|
-
- Timeline Estimates
|
|
23
|
-
|
|
24
|
-
4. **Task Breakdown Structure**:
|
|
25
|
-
- Each major section represents a phase or component
|
|
26
|
-
- Number and prioritize tasks within sections
|
|
27
|
-
- Include clear acceptance criteria for each task
|
|
28
|
-
- Specify dependencies between tasks
|
|
29
|
-
- Estimate effort levels (S/M/L/XL)
|
|
30
|
-
|
|
31
|
-
5. **Create task management structure**:
|
|
32
|
-
- Create directory: `dev/active/[task-name]/` (relative to project root)
|
|
33
|
-
- Generate three files:
|
|
34
|
-
- `[task-name]-plan.md` - The comprehensive plan
|
|
35
|
-
- `[task-name]-context.md` - Key files, decisions, dependencies
|
|
36
|
-
- `[task-name]-tasks.md` - Checklist format for tracking progress
|
|
37
|
-
- Include "Last Updated: YYYY-MM-DD" in each file
|
|
38
|
-
|
|
39
|
-
6. **Stop and Consult**: Pause and negotiate the plan with the user.
|
|
40
|
-
|
|
41
|
-
## Quality Standards
|
|
42
|
-
- Plans must be self-contained with all necessary context
|
|
43
|
-
- Use clear, actionable language
|
|
44
|
-
- Include specific technical details where relevant
|
|
45
|
-
- Consider both technical and business perspectives
|
|
46
|
-
- Account for potential risks and edge cases
|
klaude_code/config/list_model.py
DELETED
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
from rich.console import Console, Group
|
|
2
|
-
from rich.panel import Panel
|
|
3
|
-
from rich.table import Table
|
|
4
|
-
from rich.text import Text
|
|
5
|
-
|
|
6
|
-
from klaude_code.config import Config
|
|
7
|
-
from klaude_code.protocol.sub_agent import iter_sub_agent_profiles
|
|
8
|
-
from klaude_code.ui.rich.theme import ThemeKey, get_theme
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def mask_api_key(api_key: str | None) -> str:
|
|
12
|
-
"""Mask API key to show only first 6 and last 6 characters with *** in between"""
|
|
13
|
-
if not api_key or api_key == "N/A":
|
|
14
|
-
return "N/A"
|
|
15
|
-
|
|
16
|
-
if len(api_key) <= 12:
|
|
17
|
-
return api_key
|
|
18
|
-
|
|
19
|
-
return f"{api_key[:6]} … {api_key[-6:]}"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def display_models_and_providers(config: Config):
|
|
23
|
-
"""Display models and providers configuration using rich formatting"""
|
|
24
|
-
themes = get_theme(config.theme)
|
|
25
|
-
console = Console(theme=themes.app_theme)
|
|
26
|
-
|
|
27
|
-
# Display providers section
|
|
28
|
-
providers_table = Table.grid(padding=(0, 1), expand=True)
|
|
29
|
-
providers_table.add_column(width=2, no_wrap=True) # Status
|
|
30
|
-
providers_table.add_column(overflow="fold") # Name
|
|
31
|
-
providers_table.add_column(overflow="fold") # Protocol
|
|
32
|
-
providers_table.add_column(overflow="fold") # Base URL
|
|
33
|
-
providers_table.add_column(overflow="fold") # API Key
|
|
34
|
-
|
|
35
|
-
# Add header
|
|
36
|
-
providers_table.add_row(
|
|
37
|
-
Text("", style="bold"),
|
|
38
|
-
Text("Name", style=f"bold {ThemeKey.CONFIG_TABLE_HEADER}"),
|
|
39
|
-
Text("Protocol", style=f"bold {ThemeKey.CONFIG_TABLE_HEADER}"),
|
|
40
|
-
Text("Base URL", style=f"bold {ThemeKey.CONFIG_TABLE_HEADER}"),
|
|
41
|
-
Text("API Key", style=f"bold {ThemeKey.CONFIG_TABLE_HEADER}"),
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
# Add providers
|
|
45
|
-
for provider in config.provider_list:
|
|
46
|
-
status = Text("✔", style=f"bold {ThemeKey.CONFIG_STATUS_OK}")
|
|
47
|
-
name = Text(provider.provider_name, style=ThemeKey.CONFIG_ITEM_NAME)
|
|
48
|
-
protocol = Text(str(provider.protocol.value), style="")
|
|
49
|
-
base_url = Text(provider.base_url or "N/A", style="")
|
|
50
|
-
api_key = Text(mask_api_key(provider.api_key), style="")
|
|
51
|
-
|
|
52
|
-
providers_table.add_row(status, name, protocol, base_url, api_key)
|
|
53
|
-
|
|
54
|
-
# Display models section
|
|
55
|
-
models_table = Table.grid(padding=(0, 1), expand=True)
|
|
56
|
-
models_table.add_column(width=2, no_wrap=True) # Status
|
|
57
|
-
models_table.add_column(overflow="fold", ratio=1) # Name
|
|
58
|
-
models_table.add_column(overflow="fold", ratio=2) # Model
|
|
59
|
-
models_table.add_column(overflow="fold", ratio=2) # Provider
|
|
60
|
-
models_table.add_column(overflow="fold", ratio=3) # Params
|
|
61
|
-
|
|
62
|
-
# Add header
|
|
63
|
-
models_table.add_row(
|
|
64
|
-
Text("", style="bold"),
|
|
65
|
-
Text("Name", style=f"bold {ThemeKey.CONFIG_TABLE_HEADER}"),
|
|
66
|
-
Text("Model", style=f"bold {ThemeKey.CONFIG_TABLE_HEADER}"),
|
|
67
|
-
Text("Provider", style=f"bold {ThemeKey.CONFIG_TABLE_HEADER}"),
|
|
68
|
-
Text("Params", style=f"bold {ThemeKey.CONFIG_TABLE_HEADER}"),
|
|
69
|
-
)
|
|
70
|
-
|
|
71
|
-
# Add models
|
|
72
|
-
for model in config.model_list:
|
|
73
|
-
status = Text("✔", style=f"bold {ThemeKey.CONFIG_STATUS_OK}")
|
|
74
|
-
if model.model_name == config.main_model:
|
|
75
|
-
status = Text("★", style=f"bold {ThemeKey.CONFIG_STATUS_PRIMARY}") # Mark main model
|
|
76
|
-
|
|
77
|
-
name = Text(
|
|
78
|
-
model.model_name,
|
|
79
|
-
style=ThemeKey.CONFIG_STATUS_PRIMARY
|
|
80
|
-
if model.model_name == config.main_model
|
|
81
|
-
else ThemeKey.CONFIG_ITEM_NAME,
|
|
82
|
-
)
|
|
83
|
-
model_name = Text(model.model_params.model or "N/A", style="")
|
|
84
|
-
provider = Text(model.provider, style="")
|
|
85
|
-
params: list[Text] = []
|
|
86
|
-
if model.model_params.thinking:
|
|
87
|
-
if model.model_params.thinking.reasoning_effort is not None:
|
|
88
|
-
params.append(
|
|
89
|
-
Text.assemble(
|
|
90
|
-
("reason-effort", ThemeKey.CONFIG_PARAM_LABEL),
|
|
91
|
-
": ",
|
|
92
|
-
model.model_params.thinking.reasoning_effort,
|
|
93
|
-
)
|
|
94
|
-
)
|
|
95
|
-
if model.model_params.thinking.reasoning_summary is not None:
|
|
96
|
-
params.append(
|
|
97
|
-
Text.assemble(
|
|
98
|
-
("reason-summary", ThemeKey.CONFIG_PARAM_LABEL),
|
|
99
|
-
": ",
|
|
100
|
-
model.model_params.thinking.reasoning_summary,
|
|
101
|
-
)
|
|
102
|
-
)
|
|
103
|
-
if model.model_params.thinking.budget_tokens is not None:
|
|
104
|
-
params.append(
|
|
105
|
-
Text.assemble(
|
|
106
|
-
("thinking-budget-tokens", ThemeKey.CONFIG_PARAM_LABEL),
|
|
107
|
-
": ",
|
|
108
|
-
str(model.model_params.thinking.budget_tokens),
|
|
109
|
-
)
|
|
110
|
-
)
|
|
111
|
-
if model.model_params.provider_routing:
|
|
112
|
-
params.append(
|
|
113
|
-
Text.assemble(
|
|
114
|
-
("provider-routing", ThemeKey.CONFIG_PARAM_LABEL),
|
|
115
|
-
": ",
|
|
116
|
-
model.model_params.provider_routing.model_dump_json(exclude_none=True),
|
|
117
|
-
)
|
|
118
|
-
)
|
|
119
|
-
if len(params) == 0:
|
|
120
|
-
params.append(Text("N/A", style=ThemeKey.CONFIG_PARAM_LABEL))
|
|
121
|
-
models_table.add_row(status, name, model_name, provider, Group(*params))
|
|
122
|
-
|
|
123
|
-
# Create panels and display
|
|
124
|
-
providers_panel = Panel(
|
|
125
|
-
providers_table,
|
|
126
|
-
title=Text("Providers Configuration", style="white bold"),
|
|
127
|
-
border_style=ThemeKey.CONFIG_PANEL_BORDER,
|
|
128
|
-
padding=(0, 1),
|
|
129
|
-
title_align="left",
|
|
130
|
-
)
|
|
131
|
-
|
|
132
|
-
models_panel = Panel(
|
|
133
|
-
models_table,
|
|
134
|
-
title=Text("Models Configuration", style="white bold"),
|
|
135
|
-
border_style=ThemeKey.CONFIG_PANEL_BORDER,
|
|
136
|
-
padding=(0, 1),
|
|
137
|
-
title_align="left",
|
|
138
|
-
)
|
|
139
|
-
|
|
140
|
-
console.print(providers_panel)
|
|
141
|
-
console.print()
|
|
142
|
-
console.print(models_panel)
|
|
143
|
-
|
|
144
|
-
# Display main model info
|
|
145
|
-
console.print()
|
|
146
|
-
console.print(
|
|
147
|
-
Text.assemble(
|
|
148
|
-
("Default Model: ", "bold"),
|
|
149
|
-
(config.main_model, ThemeKey.CONFIG_STATUS_PRIMARY),
|
|
150
|
-
)
|
|
151
|
-
)
|
|
152
|
-
|
|
153
|
-
for profile in iter_sub_agent_profiles():
|
|
154
|
-
sub_model_name = config.subagent_models.get(profile.name)
|
|
155
|
-
if not sub_model_name:
|
|
156
|
-
continue
|
|
157
|
-
console.print(
|
|
158
|
-
Text.assemble(
|
|
159
|
-
(f"{profile.name} Model: ", "bold"),
|
|
160
|
-
(sub_model_name, ThemeKey.CONFIG_STATUS_PRIMARY),
|
|
161
|
-
)
|
|
162
|
-
)
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
"""Agent and session manager.
|
|
2
|
-
|
|
3
|
-
This module contains :class:`AgentManager`, a helper responsible for
|
|
4
|
-
creating and tracking agents per session, applying model changes, and
|
|
5
|
-
clearing conversations. It is used by the executor context to keep
|
|
6
|
-
agent-related responsibilities separate from operation dispatch.
|
|
7
|
-
"""
|
|
8
|
-
|
|
9
|
-
from __future__ import annotations
|
|
10
|
-
|
|
11
|
-
import asyncio
|
|
12
|
-
|
|
13
|
-
from klaude_code.config import load_config
|
|
14
|
-
from klaude_code.core.agent import Agent, DefaultModelProfileProvider, ModelProfileProvider
|
|
15
|
-
from klaude_code.core.manager.llm_clients import LLMClients
|
|
16
|
-
from klaude_code.llm.registry import create_llm_client
|
|
17
|
-
from klaude_code.protocol import commands, events, model
|
|
18
|
-
from klaude_code.session.session import Session
|
|
19
|
-
from klaude_code.trace import DebugType, log_debug
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
class AgentManager:
|
|
23
|
-
"""Manager component that tracks agents and their sessions."""
|
|
24
|
-
|
|
25
|
-
def __init__(
|
|
26
|
-
self,
|
|
27
|
-
event_queue: asyncio.Queue[events.Event],
|
|
28
|
-
llm_clients: LLMClients,
|
|
29
|
-
model_profile_provider: ModelProfileProvider | None = None,
|
|
30
|
-
) -> None:
|
|
31
|
-
self._event_queue: asyncio.Queue[events.Event] = event_queue
|
|
32
|
-
self._llm_clients: LLMClients = llm_clients
|
|
33
|
-
self._model_profile_provider: ModelProfileProvider = model_profile_provider or DefaultModelProfileProvider()
|
|
34
|
-
self._active_agents: dict[str, Agent] = {}
|
|
35
|
-
|
|
36
|
-
async def emit_event(self, event: events.Event) -> None:
|
|
37
|
-
"""Emit an event to the shared event queue."""
|
|
38
|
-
|
|
39
|
-
await self._event_queue.put(event)
|
|
40
|
-
|
|
41
|
-
async def ensure_agent(self, session_id: str) -> Agent:
|
|
42
|
-
"""Return an existing agent for the session or create a new one."""
|
|
43
|
-
|
|
44
|
-
agent = self._active_agents.get(session_id)
|
|
45
|
-
if agent is not None:
|
|
46
|
-
return agent
|
|
47
|
-
|
|
48
|
-
session = Session.load(session_id)
|
|
49
|
-
profile = self._model_profile_provider.build_profile(self._llm_clients.main)
|
|
50
|
-
agent = Agent(session=session, profile=profile)
|
|
51
|
-
|
|
52
|
-
async for evt in agent.replay_history():
|
|
53
|
-
await self.emit_event(evt)
|
|
54
|
-
|
|
55
|
-
await self.emit_event(
|
|
56
|
-
events.WelcomeEvent(
|
|
57
|
-
work_dir=str(session.work_dir),
|
|
58
|
-
llm_config=self._llm_clients.main.get_llm_config(),
|
|
59
|
-
)
|
|
60
|
-
)
|
|
61
|
-
|
|
62
|
-
self._active_agents[session_id] = agent
|
|
63
|
-
log_debug(
|
|
64
|
-
f"Initialized agent for session: {session_id}",
|
|
65
|
-
style="cyan",
|
|
66
|
-
debug_type=DebugType.EXECUTION,
|
|
67
|
-
)
|
|
68
|
-
return agent
|
|
69
|
-
|
|
70
|
-
async def apply_model_change(self, agent: Agent, model_name: str) -> None:
|
|
71
|
-
"""Change the model used by an agent and notify the UI."""
|
|
72
|
-
|
|
73
|
-
config = load_config()
|
|
74
|
-
if config is None:
|
|
75
|
-
raise ValueError("Configuration must be initialized before changing model")
|
|
76
|
-
|
|
77
|
-
llm_config = config.get_model_config(model_name)
|
|
78
|
-
llm_client = create_llm_client(llm_config)
|
|
79
|
-
agent.set_model_profile(self._model_profile_provider.build_profile(llm_client))
|
|
80
|
-
|
|
81
|
-
developer_item = model.DeveloperMessageItem(
|
|
82
|
-
content=f"switched to model: {model_name}",
|
|
83
|
-
command_output=model.CommandOutput(command_name=commands.CommandName.MODEL),
|
|
84
|
-
)
|
|
85
|
-
agent.session.append_history([developer_item])
|
|
86
|
-
|
|
87
|
-
await self.emit_event(events.DeveloperMessageEvent(session_id=agent.session.id, item=developer_item))
|
|
88
|
-
await self.emit_event(events.WelcomeEvent(llm_config=llm_config, work_dir=str(agent.session.work_dir)))
|
|
89
|
-
|
|
90
|
-
async def apply_clear(self, agent: Agent) -> None:
|
|
91
|
-
"""Start a new conversation for an agent and notify the UI."""
|
|
92
|
-
|
|
93
|
-
old_session_id = agent.session.id
|
|
94
|
-
|
|
95
|
-
# Create a new session instance to replace the current one
|
|
96
|
-
new_session = Session(work_dir=agent.session.work_dir)
|
|
97
|
-
new_session.model_name = agent.session.model_name
|
|
98
|
-
|
|
99
|
-
# Replace the agent's session with the new one
|
|
100
|
-
agent.session = new_session
|
|
101
|
-
agent.session.save()
|
|
102
|
-
|
|
103
|
-
# Update the active_agents mapping
|
|
104
|
-
self._active_agents.pop(old_session_id, None)
|
|
105
|
-
self._active_agents[new_session.id] = agent
|
|
106
|
-
|
|
107
|
-
developer_item = model.DeveloperMessageItem(
|
|
108
|
-
content="started new conversation",
|
|
109
|
-
command_output=model.CommandOutput(command_name=commands.CommandName.CLEAR),
|
|
110
|
-
)
|
|
111
|
-
|
|
112
|
-
await self.emit_event(events.DeveloperMessageEvent(session_id=agent.session.id, item=developer_item))
|
|
113
|
-
|
|
114
|
-
def get_active_agent(self, session_id: str) -> Agent | None:
|
|
115
|
-
"""Return the active agent for a session id if present."""
|
|
116
|
-
|
|
117
|
-
return self._active_agents.get(session_id)
|
|
118
|
-
|
|
119
|
-
def active_session_ids(self) -> list[str]:
|
|
120
|
-
"""Return a snapshot list of session ids that currently have agents."""
|
|
121
|
-
|
|
122
|
-
return list(self._active_agents.keys())
|
|
123
|
-
|
|
124
|
-
def all_active_agents(self) -> dict[str, Agent]:
|
|
125
|
-
"""Return a snapshot of all active agents keyed by session id."""
|
|
126
|
-
|
|
127
|
-
return dict(self._active_agents)
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
You are a web content fetching and analysis specialist. Your job is to retrieve content from URLs and extract or analyze information according to the user's instructions.
|
|
2
|
-
|
|
3
|
-
Your available tools:
|
|
4
|
-
- WebFetch: Fetch content from a URL. HTML pages are automatically converted to Markdown.
|
|
5
|
-
- Read: Read files from the filesystem (useful when WebFetch output is truncated and saved to a file)
|
|
6
|
-
- Bash: Run shell commands (use `rg` to search through large saved files)
|
|
7
|
-
|
|
8
|
-
Workflow:
|
|
9
|
-
1. Use WebFetch to retrieve the URL content
|
|
10
|
-
2. Analyze the content according to the user's prompt
|
|
11
|
-
3. If the output was truncated and saved to a file, use Read or `rg` to search through the full content
|
|
12
|
-
4. If you need information from a linked page, use WebFetch to follow that link
|
|
13
|
-
5. Return a clear, structured summary of your findings
|
|
14
|
-
|
|
15
|
-
Guidelines:
|
|
16
|
-
- Focus on extracting the specific information requested
|
|
17
|
-
- For large pages, prioritize the most relevant sections
|
|
18
|
-
- If content is truncated, look for the saved file path in the system reminder and use rg to search it
|
|
19
|
-
- Return structured data when appropriate (lists, tables, key-value pairs)
|
|
20
|
-
- Be concise but comprehensive in your final response
|
|
21
|
-
- Use absolute file paths when referencing saved files
|
|
22
|
-
- Avoid using emojis
|
|
23
|
-
|
|
24
|
-
Following links:
|
|
25
|
-
- If a link on the page seems relevant to answering the question, use WebFetch to follow it
|
|
26
|
-
- You can fetch multiple pages in sequence to gather all needed information
|
|
27
|
-
- After fetching a link, analyze the content yourself to extract what's needed
|
|
28
|
-
- Remember to include any fetched URLs in your Sources section if they were helpful
|
|
29
|
-
|
|
30
|
-
Handling truncated content:
|
|
31
|
-
When WebFetch output is too large, it will be truncated and the full content saved to a temporary file.
|
|
32
|
-
The file path will be shown in a system-reminder tag. Use these approaches to access the full content:
|
|
33
|
-
- `rg "pattern" /path/to/file` to search for specific content
|
|
34
|
-
- Read tool with offset/limit to read specific sections
|
|
35
|
-
|
|
36
|
-
Response format:
|
|
37
|
-
Your response should be structured as follows:
|
|
38
|
-
|
|
39
|
-
[Your answer to the user's question]
|
|
40
|
-
|
|
41
|
-
## Sources
|
|
42
|
-
- [URL 1] (saved to local: /path/to/file if saved)
|
|
43
|
-
- [URL 2]
|
|
44
|
-
...
|
|
45
|
-
|
|
46
|
-
Only include URLs that actually contributed information to your answer. The main URL is always included. Add any additional URLs you fetched that provided relevant information.
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
This is a tool for making multiple edits to a single file in one operation. It is built on top of the Edit tool and allows you to perform multiple find-and-replace operations efficiently. Prefer this tool over the Edit tool when you need to make multiple edits to the same file.
|
|
2
|
-
|
|
3
|
-
Before using this tool:
|
|
4
|
-
|
|
5
|
-
1. Use the Read tool to understand the file's contents and context
|
|
6
|
-
2. Verify the directory path is correct
|
|
7
|
-
|
|
8
|
-
To make multiple file edits, provide the following:
|
|
9
|
-
1. file_path: The absolute path to the file to modify (must be absolute, not relative)
|
|
10
|
-
2. edits: An array of edit operations to perform, where each edit contains:
|
|
11
|
-
- old_string: The text to replace (must match the file contents exactly, including all whitespace and indentation)
|
|
12
|
-
- new_string: The edited text to replace the old_string
|
|
13
|
-
- replace_all: Replace all occurences of old_string. This parameter is optional and defaults to false.
|
|
14
|
-
|
|
15
|
-
IMPORTANT:
|
|
16
|
-
- All edits are applied in sequence, in the order they are provided
|
|
17
|
-
- Each edit operates on the result of the previous edit
|
|
18
|
-
- All edits must be valid for the operation to succeed - if any edit fails, none will be applied
|
|
19
|
-
- This tool is ideal when you need to make several changes to different parts of the same file
|
|
20
|
-
- For Jupyter notebooks (.ipynb files), use the NotebookEdit instead
|
|
21
|
-
|
|
22
|
-
CRITICAL REQUIREMENTS:
|
|
23
|
-
1. All edits follow the same requirements as the single Edit tool
|
|
24
|
-
2. The edits are atomic - either all succeed or none are applied
|
|
25
|
-
3. Plan your edits carefully to avoid conflicts between sequential operations
|
|
26
|
-
|
|
27
|
-
WARNING:
|
|
28
|
-
- The tool will fail if edits.old_string doesn't match the file contents exactly (including whitespace)
|
|
29
|
-
- The tool will fail if edits.old_string and edits.new_string are the same
|
|
30
|
-
- Since edits are applied in sequence, ensure that earlier edits don't affect the text that later edits are trying to find
|
|
31
|
-
|
|
32
|
-
When making edits:
|
|
33
|
-
- Ensure all edits result in idiomatic, correct code
|
|
34
|
-
- Do not leave the code in a broken state
|
|
35
|
-
- Always use absolute file paths (starting with /)
|
|
36
|
-
- Only use emojis if the user explicitly requests it. Avoid adding emojis to files unless asked.
|
|
37
|
-
- Use replace_all for replacing and renaming strings across the file. This parameter is useful if you want to rename a variable for instance.
|
|
38
|
-
|
|
39
|
-
If you want to create a new file, use:
|
|
40
|
-
- A new file path, including dir name if needed
|
|
41
|
-
- First edit: empty old_string and the new file's contents as new_string
|
|
42
|
-
- Subsequent edits: normal edit operations on the created content
|