klaude-code 1.2.21__py3-none-any.whl → 1.2.23__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.
Files changed (65) hide show
  1. klaude_code/cli/debug.py +8 -10
  2. klaude_code/command/__init__.py +0 -3
  3. klaude_code/command/status_cmd.py +1 -1
  4. klaude_code/const/__init__.py +10 -7
  5. klaude_code/core/manager/sub_agent_manager.py +1 -1
  6. klaude_code/core/prompt.py +5 -2
  7. klaude_code/core/prompts/prompt-codex-gpt-5-2-codex.md +117 -0
  8. klaude_code/core/prompts/{prompt-codex-gpt-5-1.md → prompt-codex.md} +9 -42
  9. klaude_code/core/reminders.py +87 -2
  10. klaude_code/core/task.py +37 -18
  11. klaude_code/core/tool/__init__.py +1 -9
  12. klaude_code/core/tool/file/_utils.py +6 -0
  13. klaude_code/core/tool/file/apply_patch_tool.py +30 -72
  14. klaude_code/core/tool/file/diff_builder.py +151 -0
  15. klaude_code/core/tool/file/edit_tool.py +35 -18
  16. klaude_code/core/tool/file/read_tool.py +45 -86
  17. klaude_code/core/tool/file/write_tool.py +40 -30
  18. klaude_code/core/tool/shell/bash_tool.py +147 -0
  19. klaude_code/core/tool/skill/__init__.py +0 -0
  20. klaude_code/core/tool/{memory → skill}/skill_tool.py +16 -39
  21. klaude_code/protocol/commands.py +0 -1
  22. klaude_code/protocol/model.py +31 -11
  23. klaude_code/protocol/tools.py +1 -2
  24. klaude_code/session/export.py +76 -21
  25. klaude_code/session/store.py +4 -2
  26. klaude_code/session/templates/export_session.html +28 -0
  27. klaude_code/skill/__init__.py +27 -0
  28. klaude_code/skill/assets/deslop/SKILL.md +17 -0
  29. klaude_code/skill/assets/dev-docs/SKILL.md +108 -0
  30. klaude_code/skill/assets/handoff/SKILL.md +39 -0
  31. klaude_code/skill/assets/jj-workspace/SKILL.md +20 -0
  32. klaude_code/skill/assets/skill-creator/SKILL.md +139 -0
  33. klaude_code/{core/tool/memory/skill_loader.py → skill/loader.py} +60 -24
  34. klaude_code/skill/manager.py +70 -0
  35. klaude_code/skill/system_skills.py +192 -0
  36. klaude_code/ui/modes/repl/completers.py +103 -3
  37. klaude_code/ui/modes/repl/event_handler.py +7 -3
  38. klaude_code/ui/modes/repl/input_prompt_toolkit.py +42 -3
  39. klaude_code/ui/renderers/assistant.py +7 -2
  40. klaude_code/ui/renderers/common.py +26 -11
  41. klaude_code/ui/renderers/developer.py +12 -5
  42. klaude_code/ui/renderers/diffs.py +85 -1
  43. klaude_code/ui/renderers/metadata.py +4 -2
  44. klaude_code/ui/renderers/thinking.py +1 -1
  45. klaude_code/ui/renderers/tools.py +75 -129
  46. klaude_code/ui/renderers/user_input.py +32 -2
  47. klaude_code/ui/rich/markdown.py +27 -12
  48. klaude_code/ui/rich/status.py +9 -24
  49. klaude_code/ui/rich/theme.py +17 -5
  50. {klaude_code-1.2.21.dist-info → klaude_code-1.2.23.dist-info}/METADATA +19 -13
  51. {klaude_code-1.2.21.dist-info → klaude_code-1.2.23.dist-info}/RECORD +54 -54
  52. klaude_code/command/diff_cmd.py +0 -136
  53. klaude_code/command/prompt-deslop.md +0 -14
  54. klaude_code/command/prompt-dev-docs-update.md +0 -56
  55. klaude_code/command/prompt-dev-docs.md +0 -46
  56. klaude_code/command/prompt-handoff.md +0 -33
  57. klaude_code/command/prompt-jj-workspace.md +0 -18
  58. klaude_code/core/tool/file/multi_edit_tool.md +0 -42
  59. klaude_code/core/tool/file/multi_edit_tool.py +0 -175
  60. klaude_code/core/tool/memory/__init__.py +0 -5
  61. klaude_code/core/tool/memory/memory_tool.md +0 -20
  62. klaude_code/core/tool/memory/memory_tool.py +0 -456
  63. /klaude_code/core/tool/{memory → skill}/skill_tool.md +0 -0
  64. {klaude_code-1.2.21.dist-info → klaude_code-1.2.23.dist-info}/WHEEL +0 -0
  65. {klaude_code-1.2.21.dist-info → klaude_code-1.2.23.dist-info}/entry_points.txt +0 -0
@@ -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
@@ -1,175 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import asyncio
4
- import contextlib
5
- import difflib
6
- import os
7
- from pathlib import Path
8
-
9
- from pydantic import BaseModel, Field
10
-
11
- from klaude_code.core.tool.file._utils import file_exists, is_directory, read_text, write_text
12
- from klaude_code.core.tool.file.edit_tool import EditTool
13
- from klaude_code.core.tool.tool_abc import ToolABC, load_desc
14
- from klaude_code.core.tool.tool_context import get_current_file_tracker
15
- from klaude_code.core.tool.tool_registry import register
16
- from klaude_code.protocol import llm_param, model, tools
17
-
18
-
19
- @register(tools.MULTI_EDIT)
20
- class MultiEditTool(ToolABC):
21
- class MultiEditEditItem(BaseModel):
22
- old_string: str
23
- new_string: str
24
- replace_all: bool = Field(default=False)
25
-
26
- class MultiEditArguments(BaseModel):
27
- file_path: str
28
- edits: list[MultiEditTool.MultiEditEditItem]
29
-
30
- @classmethod
31
- def schema(cls) -> llm_param.ToolSchema:
32
- return llm_param.ToolSchema(
33
- name=tools.MULTI_EDIT,
34
- type="function",
35
- description=load_desc(Path(__file__).parent / "multi_edit_tool.md"),
36
- parameters={
37
- "type": "object",
38
- "properties": {
39
- "file_path": {
40
- "type": "string",
41
- "description": "The absolute path to the file to modify",
42
- },
43
- "edits": {
44
- "type": "array",
45
- "items": {
46
- "type": "object",
47
- "properties": {
48
- "old_string": {
49
- "type": "string",
50
- "description": "The text to replace",
51
- },
52
- "new_string": {
53
- "type": "string",
54
- "description": "The text to replace it with",
55
- },
56
- "replace_all": {
57
- "type": "boolean",
58
- "default": False,
59
- "description": "Replace all occurences of old_string (default false).",
60
- },
61
- },
62
- "required": ["old_string", "new_string"],
63
- "additionalProperties": False,
64
- },
65
- "minItems": 1,
66
- "description": "Array of edit operations to perform sequentially on the file",
67
- },
68
- },
69
- "required": ["file_path", "edits"],
70
- "additionalProperties": False,
71
- },
72
- )
73
-
74
- @classmethod
75
- async def call(cls, arguments: str) -> model.ToolResultItem:
76
- try:
77
- args = MultiEditTool.MultiEditArguments.model_validate_json(arguments)
78
- except Exception as e: # pragma: no cover - defensive
79
- return model.ToolResultItem(status="error", output=f"Invalid arguments: {e}")
80
-
81
- file_path = os.path.abspath(args.file_path)
82
-
83
- # Directory error first
84
- if is_directory(file_path):
85
- return model.ToolResultItem(
86
- status="error",
87
- output="<tool_use_error>Illegal operation on a directory. multi_edit</tool_use_error>",
88
- )
89
-
90
- file_tracker = get_current_file_tracker()
91
-
92
- # FileTracker check:
93
- if file_exists(file_path):
94
- if file_tracker is not None:
95
- tracked_status = file_tracker.get(file_path)
96
- if tracked_status is None:
97
- return model.ToolResultItem(
98
- status="error",
99
- output=("File has not been read yet. Read it first before writing to it."),
100
- )
101
- try:
102
- current_mtime = Path(file_path).stat().st_mtime
103
- except Exception:
104
- current_mtime = tracked_status.mtime
105
- if current_mtime != tracked_status.mtime:
106
- return model.ToolResultItem(
107
- status="error",
108
- output=(
109
- "File has been modified externally. Either by user or a linter. Read it first before writing to it."
110
- ),
111
- )
112
- else:
113
- # Allow creation only if first edit is creating content (old_string == "")
114
- if not args.edits or args.edits[0].old_string != "":
115
- return model.ToolResultItem(
116
- status="error",
117
- output=("File has not been read yet. Read it first before writing to it."),
118
- )
119
-
120
- # Load initial content (empty for new file case)
121
- if file_exists(file_path):
122
- before = await asyncio.to_thread(read_text, file_path)
123
- else:
124
- before = ""
125
-
126
- # Validate all edits atomically against staged content
127
- staged = before
128
- for edit in args.edits:
129
- err = EditTool.valid(
130
- content=staged,
131
- old_string=edit.old_string,
132
- new_string=edit.new_string,
133
- replace_all=edit.replace_all,
134
- )
135
- if err is not None:
136
- return model.ToolResultItem(status="error", output=err)
137
- # Apply to staged content
138
- staged = EditTool.execute(
139
- content=staged,
140
- old_string=edit.old_string,
141
- new_string=edit.new_string,
142
- replace_all=edit.replace_all,
143
- )
144
-
145
- # All edits valid; write to disk
146
- try:
147
- await asyncio.to_thread(write_text, file_path, staged)
148
- except Exception as e: # pragma: no cover
149
- return model.ToolResultItem(status="error", output=f"<tool_use_error>{e}</tool_use_error>")
150
-
151
- # Prepare UI extra: unified diff
152
- diff_lines = list(
153
- difflib.unified_diff(
154
- before.splitlines(),
155
- staged.splitlines(),
156
- fromfile=file_path,
157
- tofile=file_path,
158
- n=3,
159
- )
160
- )
161
- diff_text = "\n".join(diff_lines)
162
- ui_extra = model.DiffTextUIExtra(diff_text=diff_text)
163
-
164
- # Update tracker
165
- if file_tracker is not None:
166
- with contextlib.suppress(Exception):
167
- existing = file_tracker.get(file_path)
168
- is_mem = existing.is_memory if existing else False
169
- file_tracker[file_path] = model.FileStatus(mtime=Path(file_path).stat().st_mtime, is_memory=is_mem)
170
-
171
- # Build output message
172
- lines = [f"Applied {len(args.edits)} edits to {file_path}:"]
173
- for i, edit in enumerate(args.edits, start=1):
174
- lines.append(f'{i}. Replaced "{edit.old_string}" with "{edit.new_string}"')
175
- return model.ToolResultItem(status="success", output="\n".join(lines), ui_extra=ui_extra)
@@ -1,5 +0,0 @@
1
- from .skill_loader import SkillLoader
2
- from .skill_tool import SkillTool
3
-
4
- skill_loader = SkillLoader()
5
- SkillTool.set_skill_loader(skill_loader)
@@ -1,20 +0,0 @@
1
- Stores and retrieves information across conversations through a memory file directory. Use this tool to persist knowledge, progress, and context that should survive between sessions.
2
-
3
- The memory directory is located at `.claude/memories/` in the current project root (git repository root if present, otherwise the current working directory). Memories are scoped to the current project/directory and are not shared globally. All paths must start with `/memories` (e.g., `/memories/notes.txt`).
4
-
5
- Commands:
6
- - `view`: Show directory contents or file contents with optional line range
7
- - `create`: Create or overwrite a file
8
- - `str_replace`: Replace text in a file
9
- - `insert`: Insert text at a specific line
10
- - `delete`: Delete a file or directory
11
- - `rename`: Rename or move a file/directory
12
-
13
- Usage tips:
14
- - Check your memory directory before starting tasks to recall previous context
15
- - Record important decisions, progress, and learnings as you work
16
- - Keep memory files organized and up-to-date; delete obsolete files
17
-
18
- Note: when editing your memory folder, always try to keep its content up-to-date, coherent and organized. You can rename or delete files that are no longer relevant. Do not create new files unless necessary.
19
-
20
- Only write down information relevant to current project in your memory system.