klaude-code 2.8.0__py3-none-any.whl → 2.8.1__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/cli/main.py +1 -1
- klaude_code/const.py +1 -1
- klaude_code/core/agent_profile.py +1 -1
- klaude_code/core/compaction/compaction.py +4 -6
- klaude_code/core/executor.py +18 -0
- klaude_code/core/tool/file/edit_tool.py +1 -2
- klaude_code/protocol/commands.py +1 -0
- klaude_code/protocol/op.py +14 -0
- klaude_code/protocol/op_handler.py +5 -0
- klaude_code/session/export.py +308 -299
- klaude_code/session/templates/export_session.html +430 -134
- klaude_code/tui/command/__init__.py +3 -0
- klaude_code/tui/command/continue_cmd.py +34 -0
- klaude_code/tui/components/rich/markdown.py +63 -12
- klaude_code/tui/renderer.py +1 -0
- {klaude_code-2.8.0.dist-info → klaude_code-2.8.1.dist-info}/METADATA +1 -1
- {klaude_code-2.8.0.dist-info → klaude_code-2.8.1.dist-info}/RECORD +19 -18
- {klaude_code-2.8.0.dist-info → klaude_code-2.8.1.dist-info}/WHEEL +0 -0
- {klaude_code-2.8.0.dist-info → klaude_code-2.8.1.dist-info}/entry_points.txt +0 -0
klaude_code/cli/main.py
CHANGED
|
@@ -34,7 +34,7 @@ def _build_env_help() -> str:
|
|
|
34
34
|
"Tool limits (Read):",
|
|
35
35
|
" KLAUDE_READ_GLOBAL_LINE_CAP Max lines to read (default: 2000)",
|
|
36
36
|
" KLAUDE_READ_MAX_CHARS Max total chars to read (default: 50000)",
|
|
37
|
-
" KLAUDE_READ_MAX_IMAGE_BYTES Max image bytes to read (default:
|
|
37
|
+
" KLAUDE_READ_MAX_IMAGE_BYTES Max image bytes to read (default: 64MB)",
|
|
38
38
|
" KLAUDE_IMAGE_OUTPUT_MAX_BYTES Max decoded image bytes (default: 64MB)",
|
|
39
39
|
]
|
|
40
40
|
)
|
klaude_code/const.py
CHANGED
|
@@ -81,7 +81,7 @@ MEMORY_FILE_NAMES = ["CLAUDE.md", "AGENTS.md", "AGENT.md"] # Memory file names
|
|
|
81
81
|
READ_CHAR_LIMIT_PER_LINE = 2000 # Maximum characters per line before truncation
|
|
82
82
|
READ_GLOBAL_LINE_CAP = _get_int_env("KLAUDE_READ_GLOBAL_LINE_CAP", 2000) # Maximum lines to read from a file
|
|
83
83
|
READ_MAX_CHARS = _get_int_env("KLAUDE_READ_MAX_CHARS", 50000) # Maximum total characters to read
|
|
84
|
-
READ_MAX_IMAGE_BYTES = _get_int_env("KLAUDE_READ_MAX_IMAGE_BYTES",
|
|
84
|
+
READ_MAX_IMAGE_BYTES = _get_int_env("KLAUDE_READ_MAX_IMAGE_BYTES", 64 * 1024 * 1024) # Max image size (64MB)
|
|
85
85
|
IMAGE_OUTPUT_MAX_BYTES = _get_int_env("KLAUDE_IMAGE_OUTPUT_MAX_BYTES", 64 * 1024 * 1024) # Max decoded image (64MB)
|
|
86
86
|
BINARY_CHECK_SIZE = 8192 # Bytes to check for binary file detection
|
|
87
87
|
|
|
@@ -311,7 +311,7 @@ class DefaultModelProfileProvider(ModelProfileProvider):
|
|
|
311
311
|
if is_image_model:
|
|
312
312
|
agent_system_prompt: str | None = None
|
|
313
313
|
agent_tools: list[llm_param.ToolSchema] = []
|
|
314
|
-
agent_reminders: list[Reminder] = []
|
|
314
|
+
agent_reminders: list[Reminder] = [at_file_reader_reminder, image_reminder]
|
|
315
315
|
else:
|
|
316
316
|
agent_system_prompt = load_system_prompt(
|
|
317
317
|
model_name, llm_client.protocol, sub_agent_type, config=self._config
|
|
@@ -268,9 +268,7 @@ def _call_args_probably_modify_file(args: dict[str, object]) -> bool:
|
|
|
268
268
|
return True
|
|
269
269
|
# Batch edits.
|
|
270
270
|
edits = args.get("edits")
|
|
271
|
-
|
|
272
|
-
return True
|
|
273
|
-
return False
|
|
271
|
+
return bool(isinstance(edits, list))
|
|
274
272
|
|
|
275
273
|
|
|
276
274
|
def _collect_file_operations(
|
|
@@ -478,12 +476,12 @@ async def _build_summary(
|
|
|
478
476
|
previous_summary,
|
|
479
477
|
cancel,
|
|
480
478
|
)
|
|
481
|
-
if messages_to_summarize
|
|
482
|
-
else asyncio.sleep(0, result=
|
|
479
|
+
if messages_to_summarize
|
|
480
|
+
else asyncio.sleep(0, result=previous_summary or "")
|
|
483
481
|
)
|
|
484
482
|
prefix_task = _generate_task_prefix_summary(task_prefix_messages, llm_client, config, cancel)
|
|
485
483
|
history_summary, task_prefix_summary = await asyncio.gather(history_task, prefix_task)
|
|
486
|
-
return f"{COMPACTION_SUMMARY_PREFIX}\n\n<summary>{history_summary}\n\n---\n\n**Task Context (
|
|
484
|
+
return f"{COMPACTION_SUMMARY_PREFIX}\n\n<summary>{history_summary}\n\n---\n\n**Task Context (current task):**\n\n{task_prefix_summary}\n\n</summary>"
|
|
487
485
|
|
|
488
486
|
return await _generate_summary(
|
|
489
487
|
messages_to_summarize,
|
klaude_code/core/executor.py
CHANGED
|
@@ -179,6 +179,21 @@ class AgentRuntime:
|
|
|
179
179
|
)
|
|
180
180
|
self._task_manager.register(operation.id, task, operation.session_id)
|
|
181
181
|
|
|
182
|
+
async def continue_agent(self, operation: op.ContinueAgentOperation) -> None:
|
|
183
|
+
"""Continue agent execution without adding a new user message."""
|
|
184
|
+
agent = await self.ensure_agent(operation.session_id)
|
|
185
|
+
|
|
186
|
+
existing_active = self._task_manager.get(operation.id)
|
|
187
|
+
if existing_active is not None and not existing_active.task.done():
|
|
188
|
+
raise RuntimeError(f"Active task already registered for operation {operation.id}")
|
|
189
|
+
|
|
190
|
+
# Use empty input since we're continuing from existing history
|
|
191
|
+
empty_input = message.UserInputPayload(text="")
|
|
192
|
+
task: asyncio.Task[None] = asyncio.create_task(
|
|
193
|
+
self._run_agent_task(agent, empty_input, operation.id, operation.session_id)
|
|
194
|
+
)
|
|
195
|
+
self._task_manager.register(operation.id, task, operation.session_id)
|
|
196
|
+
|
|
182
197
|
async def compact_session(self, operation: op.CompactSessionOperation) -> None:
|
|
183
198
|
agent = await self.ensure_agent(operation.session_id)
|
|
184
199
|
|
|
@@ -525,6 +540,9 @@ class ExecutorContext:
|
|
|
525
540
|
async def handle_run_agent(self, operation: op.RunAgentOperation) -> None:
|
|
526
541
|
await self._agent_runtime.run_agent(operation)
|
|
527
542
|
|
|
543
|
+
async def handle_continue_agent(self, operation: op.ContinueAgentOperation) -> None:
|
|
544
|
+
await self._agent_runtime.continue_agent(operation)
|
|
545
|
+
|
|
528
546
|
async def handle_compact_session(self, operation: op.CompactSessionOperation) -> None:
|
|
529
547
|
await self._agent_runtime.compact_session(operation)
|
|
530
548
|
|
|
@@ -114,10 +114,9 @@ class EditTool(ToolABC):
|
|
|
114
114
|
file_tracker = context.file_tracker
|
|
115
115
|
tracked_status: model.FileStatus | None = None
|
|
116
116
|
if not file_exists(file_path):
|
|
117
|
-
# We require reading before editing
|
|
118
117
|
return message.ToolResultMessage(
|
|
119
118
|
status="error",
|
|
120
|
-
output_text=("File
|
|
119
|
+
output_text=("File does not exist. If you want to create a file, use the Write tool instead."),
|
|
121
120
|
)
|
|
122
121
|
tracked_status = file_tracker.get(file_path)
|
|
123
122
|
if tracked_status is None:
|
klaude_code/protocol/commands.py
CHANGED
klaude_code/protocol/op.py
CHANGED
|
@@ -24,6 +24,7 @@ class OperationType(Enum):
|
|
|
24
24
|
"""Enumeration of supported operation types."""
|
|
25
25
|
|
|
26
26
|
RUN_AGENT = "run_agent"
|
|
27
|
+
CONTINUE_AGENT = "continue_agent"
|
|
27
28
|
COMPACT_SESSION = "compact_session"
|
|
28
29
|
CHANGE_MODEL = "change_model"
|
|
29
30
|
CHANGE_SUB_AGENT_MODEL = "change_sub_agent_model"
|
|
@@ -58,6 +59,19 @@ class RunAgentOperation(Operation):
|
|
|
58
59
|
await handler.handle_run_agent(self)
|
|
59
60
|
|
|
60
61
|
|
|
62
|
+
class ContinueAgentOperation(Operation):
|
|
63
|
+
"""Operation for continuing an agent task without adding a new user message.
|
|
64
|
+
|
|
65
|
+
Used for recovery after interruptions (network errors, API failures, etc.).
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
type: OperationType = OperationType.CONTINUE_AGENT
|
|
69
|
+
session_id: str
|
|
70
|
+
|
|
71
|
+
async def execute(self, handler: OperationHandler) -> None:
|
|
72
|
+
await handler.handle_continue_agent(self)
|
|
73
|
+
|
|
74
|
+
|
|
61
75
|
class CompactSessionOperation(Operation):
|
|
62
76
|
"""Operation for compacting a session's conversation history."""
|
|
63
77
|
|
|
@@ -15,6 +15,7 @@ if TYPE_CHECKING:
|
|
|
15
15
|
ChangeThinkingOperation,
|
|
16
16
|
ClearSessionOperation,
|
|
17
17
|
CompactSessionOperation,
|
|
18
|
+
ContinueAgentOperation,
|
|
18
19
|
ExportSessionOperation,
|
|
19
20
|
InitAgentOperation,
|
|
20
21
|
InterruptOperation,
|
|
@@ -30,6 +31,10 @@ class OperationHandler(Protocol):
|
|
|
30
31
|
"""Handle a run agent operation."""
|
|
31
32
|
...
|
|
32
33
|
|
|
34
|
+
async def handle_continue_agent(self, operation: ContinueAgentOperation) -> None:
|
|
35
|
+
"""Handle a continue agent operation (resume without adding user message)."""
|
|
36
|
+
...
|
|
37
|
+
|
|
33
38
|
async def handle_compact_session(self, operation: CompactSessionOperation) -> None:
|
|
34
39
|
"""Handle a compact session operation."""
|
|
35
40
|
...
|