klaude-code 2.0.2__py3-none-any.whl → 2.1.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/app/__init__.py +12 -0
- klaude_code/app/runtime.py +215 -0
- klaude_code/cli/auth_cmd.py +2 -2
- klaude_code/cli/config_cmd.py +2 -2
- klaude_code/cli/cost_cmd.py +1 -1
- klaude_code/cli/debug.py +12 -36
- klaude_code/cli/list_model.py +3 -3
- klaude_code/cli/main.py +17 -60
- klaude_code/cli/self_update.py +2 -187
- klaude_code/cli/session_cmd.py +2 -2
- klaude_code/config/config.py +1 -1
- klaude_code/config/select_model.py +1 -1
- klaude_code/const.py +9 -1
- klaude_code/core/agent.py +9 -62
- klaude_code/core/agent_profile.py +291 -0
- klaude_code/core/executor.py +335 -230
- klaude_code/core/manager/llm_clients_builder.py +1 -1
- klaude_code/core/manager/sub_agent_manager.py +16 -29
- klaude_code/core/reminders.py +84 -103
- klaude_code/core/task.py +12 -20
- klaude_code/core/tool/__init__.py +5 -19
- klaude_code/core/tool/context.py +84 -0
- klaude_code/core/tool/file/apply_patch_tool.py +18 -21
- klaude_code/core/tool/file/edit_tool.py +39 -42
- klaude_code/core/tool/file/read_tool.py +14 -9
- klaude_code/core/tool/file/write_tool.py +12 -13
- klaude_code/core/tool/report_back_tool.py +4 -1
- klaude_code/core/tool/shell/bash_tool.py +6 -11
- klaude_code/core/tool/sub_agent_tool.py +8 -7
- klaude_code/core/tool/todo/todo_write_tool.py +3 -9
- klaude_code/core/tool/todo/update_plan_tool.py +3 -5
- klaude_code/core/tool/tool_abc.py +2 -1
- klaude_code/core/tool/tool_registry.py +2 -33
- klaude_code/core/tool/tool_runner.py +13 -10
- klaude_code/core/tool/web/mermaid_tool.py +3 -1
- klaude_code/core/tool/web/web_fetch_tool.py +5 -3
- klaude_code/core/tool/web/web_search_tool.py +5 -3
- klaude_code/core/turn.py +87 -30
- klaude_code/llm/anthropic/client.py +1 -1
- klaude_code/llm/bedrock/client.py +1 -1
- klaude_code/llm/claude/client.py +1 -1
- klaude_code/llm/codex/client.py +1 -1
- klaude_code/llm/google/client.py +1 -1
- klaude_code/llm/openai_compatible/client.py +1 -1
- klaude_code/llm/openai_compatible/tool_call_accumulator.py +1 -1
- klaude_code/llm/openrouter/client.py +1 -1
- klaude_code/llm/openrouter/reasoning.py +1 -1
- klaude_code/llm/responses/client.py +1 -1
- klaude_code/protocol/commands.py +1 -0
- klaude_code/protocol/events/__init__.py +57 -0
- klaude_code/protocol/events/base.py +18 -0
- klaude_code/protocol/events/chat.py +20 -0
- klaude_code/protocol/events/lifecycle.py +22 -0
- klaude_code/protocol/events/metadata.py +15 -0
- klaude_code/protocol/events/streaming.py +43 -0
- klaude_code/protocol/events/system.py +53 -0
- klaude_code/protocol/events/tools.py +27 -0
- klaude_code/protocol/op.py +5 -0
- klaude_code/protocol/tools.py +0 -1
- klaude_code/session/session.py +6 -7
- klaude_code/skill/assets/create-plan/SKILL.md +76 -0
- klaude_code/skill/loader.py +32 -88
- klaude_code/skill/manager.py +38 -0
- klaude_code/skill/system_skills.py +1 -1
- klaude_code/tui/__init__.py +8 -0
- klaude_code/{command → tui/command}/__init__.py +3 -0
- klaude_code/{command → tui/command}/clear_cmd.py +2 -1
- klaude_code/tui/command/copy_cmd.py +53 -0
- klaude_code/{command → tui/command}/debug_cmd.py +3 -2
- klaude_code/{command → tui/command}/export_cmd.py +2 -1
- klaude_code/{command → tui/command}/export_online_cmd.py +2 -1
- klaude_code/{command → tui/command}/fork_session_cmd.py +4 -3
- klaude_code/{command → tui/command}/help_cmd.py +2 -1
- klaude_code/{command → tui/command}/model_cmd.py +4 -3
- klaude_code/{command → tui/command}/model_select.py +2 -2
- klaude_code/{command → tui/command}/prompt_command.py +4 -3
- klaude_code/{command → tui/command}/refresh_cmd.py +3 -1
- klaude_code/{command → tui/command}/registry.py +6 -5
- klaude_code/{command → tui/command}/release_notes_cmd.py +2 -1
- klaude_code/{command → tui/command}/resume_cmd.py +4 -3
- klaude_code/{command → tui/command}/status_cmd.py +2 -1
- klaude_code/{command → tui/command}/terminal_setup_cmd.py +2 -1
- klaude_code/{command → tui/command}/thinking_cmd.py +3 -2
- klaude_code/tui/commands.py +164 -0
- klaude_code/{ui/renderers → tui/components}/assistant.py +3 -3
- klaude_code/{ui/renderers → tui/components}/bash_syntax.py +2 -2
- klaude_code/{ui/renderers → tui/components}/common.py +1 -1
- klaude_code/{ui/renderers → tui/components}/developer.py +4 -4
- klaude_code/{ui/renderers → tui/components}/diffs.py +2 -2
- klaude_code/{ui/renderers → tui/components}/errors.py +2 -2
- klaude_code/{ui/renderers → tui/components}/metadata.py +7 -7
- klaude_code/{ui → tui/components}/rich/markdown.py +9 -23
- klaude_code/{ui → tui/components}/rich/status.py +2 -2
- klaude_code/{ui → tui/components}/rich/theme.py +3 -1
- klaude_code/{ui/renderers → tui/components}/sub_agent.py +23 -43
- klaude_code/{ui/renderers → tui/components}/thinking.py +3 -3
- klaude_code/{ui/renderers → tui/components}/tools.py +13 -17
- klaude_code/{ui/renderers → tui/components}/user_input.py +3 -20
- klaude_code/tui/display.py +85 -0
- klaude_code/{ui/modes/repl → tui/input}/__init__.py +1 -1
- klaude_code/{ui/modes/repl → tui/input}/completers.py +1 -1
- klaude_code/{ui/modes/repl/input_prompt_toolkit.py → tui/input/prompt_toolkit.py} +6 -6
- klaude_code/tui/machine.py +608 -0
- klaude_code/tui/renderer.py +707 -0
- klaude_code/tui/runner.py +321 -0
- klaude_code/tui/terminal/__init__.py +56 -0
- klaude_code/{ui → tui}/terminal/color.py +1 -1
- klaude_code/{ui → tui}/terminal/control.py +1 -1
- klaude_code/{ui → tui}/terminal/notifier.py +1 -1
- klaude_code/ui/__init__.py +6 -50
- klaude_code/ui/core/display.py +3 -3
- klaude_code/ui/core/input.py +2 -1
- klaude_code/ui/{modes/debug/display.py → debug_mode.py} +1 -1
- klaude_code/ui/{modes/exec/display.py → exec_mode.py} +0 -2
- klaude_code/ui/terminal/__init__.py +6 -54
- klaude_code/ui/terminal/title.py +31 -0
- klaude_code/update.py +163 -0
- {klaude_code-2.0.2.dist-info → klaude_code-2.1.1.dist-info}/METADATA +1 -1
- klaude_code-2.1.1.dist-info/RECORD +233 -0
- klaude_code/cli/runtime.py +0 -518
- klaude_code/core/prompt.py +0 -108
- klaude_code/core/tool/skill/skill_tool.md +0 -24
- klaude_code/core/tool/skill/skill_tool.py +0 -87
- klaude_code/core/tool/tool_context.py +0 -148
- klaude_code/protocol/events.py +0 -195
- klaude_code/skill/assets/dev-docs/SKILL.md +0 -108
- klaude_code/trace/__init__.py +0 -21
- klaude_code/ui/core/stage_manager.py +0 -48
- klaude_code/ui/modes/__init__.py +0 -1
- klaude_code/ui/modes/debug/__init__.py +0 -1
- klaude_code/ui/modes/exec/__init__.py +0 -1
- klaude_code/ui/modes/repl/display.py +0 -61
- klaude_code/ui/modes/repl/event_handler.py +0 -629
- klaude_code/ui/modes/repl/renderer.py +0 -464
- klaude_code/ui/renderers/__init__.py +0 -0
- klaude_code/ui/utils/__init__.py +0 -1
- klaude_code-2.0.2.dist-info/RECORD +0 -227
- /klaude_code/{trace/log.py → log.py} +0 -0
- /klaude_code/{command → tui/command}/command_abc.py +0 -0
- /klaude_code/{command → tui/command}/prompt-commit.md +0 -0
- /klaude_code/{command → tui/command}/prompt-init.md +0 -0
- /klaude_code/{core/tool/skill → tui/components}/__init__.py +0 -0
- /klaude_code/{ui/renderers → tui/components}/mermaid_viewer.py +0 -0
- /klaude_code/{ui → tui/components}/rich/__init__.py +0 -0
- /klaude_code/{ui → tui/components}/rich/cjk_wrap.py +0 -0
- /klaude_code/{ui → tui/components}/rich/code_panel.py +0 -0
- /klaude_code/{ui → tui/components}/rich/live.py +0 -0
- /klaude_code/{ui → tui/components}/rich/quote.py +0 -0
- /klaude_code/{ui → tui/components}/rich/searchable_text.py +0 -0
- /klaude_code/{ui/modes/repl → tui/input}/clipboard.py +0 -0
- /klaude_code/{ui/modes/repl → tui/input}/key_bindings.py +0 -0
- /klaude_code/{ui → tui}/terminal/image.py +0 -0
- /klaude_code/{ui → tui}/terminal/progress_bar.py +0 -0
- /klaude_code/{ui → tui}/terminal/selector.py +0 -0
- /klaude_code/ui/{utils/common.py → common.py} +0 -0
- {klaude_code-2.0.2.dist-info → klaude_code-2.1.1.dist-info}/WHEEL +0 -0
- {klaude_code-2.0.2.dist-info → klaude_code-2.1.1.dist-info}/entry_points.txt +0 -0
|
@@ -5,6 +5,7 @@ from pathlib import Path
|
|
|
5
5
|
from pydantic import BaseModel
|
|
6
6
|
|
|
7
7
|
from klaude_code.const import WEB_SEARCH_DEFAULT_MAX_RESULTS, WEB_SEARCH_MAX_RESULTS_LIMIT
|
|
8
|
+
from klaude_code.core.tool.context import ToolContext
|
|
8
9
|
from klaude_code.core.tool.tool_abc import ToolABC, ToolConcurrencyPolicy, ToolMetadata, load_desc
|
|
9
10
|
from klaude_code.core.tool.tool_registry import register
|
|
10
11
|
from klaude_code.protocol import llm_param, message, tools
|
|
@@ -91,7 +92,7 @@ class WebSearchTool(ToolABC):
|
|
|
91
92
|
max_results: int = WEB_SEARCH_DEFAULT_MAX_RESULTS
|
|
92
93
|
|
|
93
94
|
@classmethod
|
|
94
|
-
async def call(cls, arguments: str) -> message.ToolResultMessage:
|
|
95
|
+
async def call(cls, arguments: str, context: ToolContext) -> message.ToolResultMessage:
|
|
95
96
|
try:
|
|
96
97
|
args = WebSearchTool.WebSearchArguments.model_validate_json(arguments)
|
|
97
98
|
except ValueError as e:
|
|
@@ -99,10 +100,11 @@ class WebSearchTool(ToolABC):
|
|
|
99
100
|
status="error",
|
|
100
101
|
output_text=f"Invalid arguments: {e}",
|
|
101
102
|
)
|
|
102
|
-
return await cls.call_with_args(args)
|
|
103
|
+
return await cls.call_with_args(args, context)
|
|
103
104
|
|
|
104
105
|
@classmethod
|
|
105
|
-
async def call_with_args(cls, args: WebSearchArguments) -> message.ToolResultMessage:
|
|
106
|
+
async def call_with_args(cls, args: WebSearchArguments, context: ToolContext) -> message.ToolResultMessage:
|
|
107
|
+
del context
|
|
106
108
|
query = args.query.strip()
|
|
107
109
|
if not query:
|
|
108
110
|
return message.ToolResultMessage(
|
klaude_code/core/turn.py
CHANGED
|
@@ -5,8 +5,8 @@ from dataclasses import dataclass, field
|
|
|
5
5
|
from typing import TYPE_CHECKING
|
|
6
6
|
|
|
7
7
|
from klaude_code.const import INTERRUPT_MARKER, SUPPORTED_IMAGE_SIZES
|
|
8
|
-
from klaude_code.core.tool import ToolABC
|
|
9
|
-
from klaude_code.core.tool.
|
|
8
|
+
from klaude_code.core.tool import ToolABC
|
|
9
|
+
from klaude_code.core.tool.context import SubAgentResumeClaims, ToolContext
|
|
10
10
|
|
|
11
11
|
if TYPE_CHECKING:
|
|
12
12
|
from klaude_code.core.task import SessionContext
|
|
@@ -20,8 +20,8 @@ from klaude_code.core.tool.tool_runner import (
|
|
|
20
20
|
ToolExecutorEvent,
|
|
21
21
|
)
|
|
22
22
|
from klaude_code.llm import LLMClientABC
|
|
23
|
+
from klaude_code.log import DebugType, log_debug
|
|
23
24
|
from klaude_code.protocol import events, llm_param, message, model, tools
|
|
24
|
-
from klaude_code.trace import DebugType, log_debug
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
class TurnError(Exception):
|
|
@@ -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(
|
|
@@ -206,6 +203,8 @@ class TurnExecutor:
|
|
|
206
203
|
|
|
207
204
|
ctx = self._context
|
|
208
205
|
session_ctx = ctx.session_ctx
|
|
206
|
+
thinking_active = False
|
|
207
|
+
assistant_text_active = False
|
|
209
208
|
message_types = (
|
|
210
209
|
message.SystemMessage,
|
|
211
210
|
message.DeveloperMessage,
|
|
@@ -247,12 +246,30 @@ class TurnExecutor:
|
|
|
247
246
|
)
|
|
248
247
|
match delta:
|
|
249
248
|
case message.ThinkingTextDelta() as delta:
|
|
249
|
+
if not thinking_active:
|
|
250
|
+
thinking_active = True
|
|
251
|
+
yield events.ThinkingStartEvent(
|
|
252
|
+
response_id=delta.response_id,
|
|
253
|
+
session_id=session_ctx.session_id,
|
|
254
|
+
)
|
|
250
255
|
yield events.ThinkingDeltaEvent(
|
|
251
256
|
content=delta.content,
|
|
252
257
|
response_id=delta.response_id,
|
|
253
258
|
session_id=session_ctx.session_id,
|
|
254
259
|
)
|
|
255
260
|
case message.AssistantTextDelta() as delta:
|
|
261
|
+
if thinking_active:
|
|
262
|
+
thinking_active = False
|
|
263
|
+
yield events.ThinkingEndEvent(
|
|
264
|
+
response_id=delta.response_id,
|
|
265
|
+
session_id=session_ctx.session_id,
|
|
266
|
+
)
|
|
267
|
+
if not assistant_text_active:
|
|
268
|
+
assistant_text_active = True
|
|
269
|
+
yield events.AssistantTextStartEvent(
|
|
270
|
+
response_id=delta.response_id,
|
|
271
|
+
session_id=session_ctx.session_id,
|
|
272
|
+
)
|
|
256
273
|
if delta.response_id:
|
|
257
274
|
self._assistant_response_id = delta.response_id
|
|
258
275
|
self._assistant_delta_buffer.append(delta.content)
|
|
@@ -262,6 +279,12 @@ class TurnExecutor:
|
|
|
262
279
|
session_id=session_ctx.session_id,
|
|
263
280
|
)
|
|
264
281
|
case message.AssistantImageDelta() as delta:
|
|
282
|
+
if thinking_active:
|
|
283
|
+
thinking_active = False
|
|
284
|
+
yield events.ThinkingEndEvent(
|
|
285
|
+
response_id=delta.response_id,
|
|
286
|
+
session_id=session_ctx.session_id,
|
|
287
|
+
)
|
|
265
288
|
yield events.AssistantImageDeltaEvent(
|
|
266
289
|
file_path=delta.file_path,
|
|
267
290
|
response_id=delta.response_id,
|
|
@@ -270,6 +293,18 @@ class TurnExecutor:
|
|
|
270
293
|
case message.AssistantMessage() as msg:
|
|
271
294
|
if msg.response_id is None and self._assistant_response_id:
|
|
272
295
|
msg.response_id = self._assistant_response_id
|
|
296
|
+
if thinking_active:
|
|
297
|
+
thinking_active = False
|
|
298
|
+
yield events.ThinkingEndEvent(
|
|
299
|
+
response_id=msg.response_id,
|
|
300
|
+
session_id=session_ctx.session_id,
|
|
301
|
+
)
|
|
302
|
+
if assistant_text_active:
|
|
303
|
+
assistant_text_active = False
|
|
304
|
+
yield events.AssistantTextEndEvent(
|
|
305
|
+
response_id=msg.response_id,
|
|
306
|
+
session_id=session_ctx.session_id,
|
|
307
|
+
)
|
|
273
308
|
turn_result.assistant_message = msg
|
|
274
309
|
for part in msg.parts:
|
|
275
310
|
if isinstance(part, message.ToolCallPart):
|
|
@@ -281,11 +316,16 @@ class TurnExecutor:
|
|
|
281
316
|
arguments_json=part.arguments_json,
|
|
282
317
|
)
|
|
283
318
|
)
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
319
|
+
if msg.stop_reason != "aborted":
|
|
320
|
+
thinking_text = "".join(
|
|
321
|
+
part.text for part in msg.parts if isinstance(part, message.ThinkingTextPart)
|
|
322
|
+
)
|
|
323
|
+
yield events.ResponseCompleteEvent(
|
|
324
|
+
content=message.join_text_parts(msg.parts),
|
|
325
|
+
response_id=msg.response_id,
|
|
326
|
+
session_id=session_ctx.session_id,
|
|
327
|
+
thinking_text=thinking_text or None,
|
|
328
|
+
)
|
|
289
329
|
if msg.stop_reason == "aborted":
|
|
290
330
|
yield events.InterruptEvent(session_id=session_ctx.session_id)
|
|
291
331
|
if msg.usage:
|
|
@@ -296,9 +336,9 @@ class TurnExecutor:
|
|
|
296
336
|
metadata.model_name = ctx.llm_client.model_name
|
|
297
337
|
if metadata.provider is None:
|
|
298
338
|
metadata.provider = ctx.llm_client.get_llm_config().provider_name or None
|
|
299
|
-
yield events.
|
|
339
|
+
yield events.UsageEvent(
|
|
300
340
|
session_id=session_ctx.session_id,
|
|
301
|
-
|
|
341
|
+
usage=metadata,
|
|
302
342
|
)
|
|
303
343
|
case message.StreamErrorItem() as msg:
|
|
304
344
|
turn_result.stream_error = msg
|
|
@@ -309,12 +349,23 @@ class TurnExecutor:
|
|
|
309
349
|
debug_type=DebugType.RESPONSE,
|
|
310
350
|
)
|
|
311
351
|
case message.ToolCallStartItem() as msg:
|
|
312
|
-
|
|
352
|
+
if thinking_active:
|
|
353
|
+
thinking_active = False
|
|
354
|
+
yield events.ThinkingEndEvent(
|
|
355
|
+
response_id=msg.response_id,
|
|
356
|
+
session_id=session_ctx.session_id,
|
|
357
|
+
)
|
|
358
|
+
if assistant_text_active:
|
|
359
|
+
assistant_text_active = False
|
|
360
|
+
yield events.AssistantTextEndEvent(
|
|
361
|
+
response_id=msg.response_id,
|
|
362
|
+
session_id=session_ctx.session_id,
|
|
363
|
+
)
|
|
364
|
+
yield events.ToolCallStartEvent(
|
|
313
365
|
session_id=session_ctx.session_id,
|
|
314
366
|
response_id=msg.response_id,
|
|
315
367
|
tool_call_id=msg.call_id,
|
|
316
368
|
tool_name=msg.name,
|
|
317
|
-
arguments="",
|
|
318
369
|
)
|
|
319
370
|
case _:
|
|
320
371
|
continue
|
|
@@ -332,20 +383,26 @@ class TurnExecutor:
|
|
|
332
383
|
|
|
333
384
|
ctx = self._context
|
|
334
385
|
session_ctx = ctx.session_ctx
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
)
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
386
|
+
tool_context = ToolContext(
|
|
387
|
+
file_tracker=session_ctx.file_tracker,
|
|
388
|
+
todo_context=session_ctx.todo_context,
|
|
389
|
+
session_id=session_ctx.session_id,
|
|
390
|
+
run_subtask=session_ctx.run_subtask,
|
|
391
|
+
sub_agent_resume_claims=SubAgentResumeClaims(),
|
|
392
|
+
)
|
|
393
|
+
|
|
394
|
+
executor = ToolExecutor(
|
|
395
|
+
context=tool_context,
|
|
396
|
+
registry=ctx.tool_registry,
|
|
397
|
+
append_history=session_ctx.append_history,
|
|
398
|
+
)
|
|
399
|
+
self._tool_executor = executor
|
|
400
|
+
try:
|
|
401
|
+
async for exec_event in executor.run_tools(tool_calls):
|
|
402
|
+
for ui_event in build_events_from_tool_executor_event(session_ctx.session_id, exec_event):
|
|
403
|
+
yield ui_event
|
|
404
|
+
finally:
|
|
405
|
+
self._tool_executor = None
|
|
349
406
|
|
|
350
407
|
def _persist_partial_assistant_on_cancel(self) -> None:
|
|
351
408
|
"""Persist streamed assistant text when a turn is interrupted.
|
|
@@ -34,8 +34,8 @@ from klaude_code.llm.client import LLMClientABC
|
|
|
34
34
|
from klaude_code.llm.input_common import apply_config_defaults
|
|
35
35
|
from klaude_code.llm.registry import register
|
|
36
36
|
from klaude_code.llm.usage import MetadataTracker, error_stream_items
|
|
37
|
+
from klaude_code.log import DebugType, log_debug
|
|
37
38
|
from klaude_code.protocol import llm_param, message, model
|
|
38
|
-
from klaude_code.trace import DebugType, log_debug
|
|
39
39
|
|
|
40
40
|
|
|
41
41
|
def _map_anthropic_stop_reason(reason: str) -> model.StopReason | None:
|
|
@@ -14,8 +14,8 @@ from klaude_code.llm.client import LLMClientABC
|
|
|
14
14
|
from klaude_code.llm.input_common import apply_config_defaults
|
|
15
15
|
from klaude_code.llm.registry import register
|
|
16
16
|
from klaude_code.llm.usage import MetadataTracker, error_stream_items
|
|
17
|
+
from klaude_code.log import DebugType, log_debug
|
|
17
18
|
from klaude_code.protocol import llm_param, message
|
|
18
|
-
from klaude_code.trace import DebugType, log_debug
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
@register(llm_param.LLMClientProtocol.BEDROCK)
|
klaude_code/llm/claude/client.py
CHANGED
|
@@ -22,8 +22,8 @@ from klaude_code.llm.client import LLMClientABC
|
|
|
22
22
|
from klaude_code.llm.input_common import apply_config_defaults
|
|
23
23
|
from klaude_code.llm.registry import register
|
|
24
24
|
from klaude_code.llm.usage import MetadataTracker, error_stream_items
|
|
25
|
+
from klaude_code.log import DebugType, log_debug
|
|
25
26
|
from klaude_code.protocol import llm_param, message
|
|
26
|
-
from klaude_code.trace import DebugType, log_debug
|
|
27
27
|
|
|
28
28
|
_CLAUDE_OAUTH_REQUIRED_BETAS: tuple[str, ...] = (
|
|
29
29
|
ANTHROPIC_BETA_OAUTH,
|
klaude_code/llm/codex/client.py
CHANGED
|
@@ -25,8 +25,8 @@ from klaude_code.llm.registry import register
|
|
|
25
25
|
from klaude_code.llm.responses.client import parse_responses_stream
|
|
26
26
|
from klaude_code.llm.responses.input import convert_history_to_input, convert_tool_schema
|
|
27
27
|
from klaude_code.llm.usage import MetadataTracker, error_stream_items
|
|
28
|
+
from klaude_code.log import DebugType, log_debug
|
|
28
29
|
from klaude_code.protocol import llm_param, message
|
|
29
|
-
from klaude_code.trace import DebugType, log_debug
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
def build_payload(param: llm_param.LLMCallParameter) -> ResponseCreateParamsStreaming:
|
klaude_code/llm/google/client.py
CHANGED
|
@@ -26,8 +26,8 @@ from klaude_code.llm.google.input import convert_history_to_contents, convert_to
|
|
|
26
26
|
from klaude_code.llm.input_common import apply_config_defaults
|
|
27
27
|
from klaude_code.llm.registry import register
|
|
28
28
|
from klaude_code.llm.usage import MetadataTracker
|
|
29
|
+
from klaude_code.log import DebugType, log_debug
|
|
29
30
|
from klaude_code.protocol import llm_param, message, model
|
|
30
|
-
from klaude_code.trace import DebugType, log_debug
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
def _build_config(param: llm_param.LLMCallParameter) -> GenerateContentConfig:
|
|
@@ -13,8 +13,8 @@ from klaude_code.llm.openai_compatible.input import convert_history_to_input, co
|
|
|
13
13
|
from klaude_code.llm.openai_compatible.stream import DefaultReasoningHandler, parse_chat_completions_stream
|
|
14
14
|
from klaude_code.llm.registry import register
|
|
15
15
|
from klaude_code.llm.usage import MetadataTracker
|
|
16
|
+
from klaude_code.log import DebugType, log_debug
|
|
16
17
|
from klaude_code.protocol import llm_param, message
|
|
17
|
-
from klaude_code.trace import DebugType, log_debug
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
def build_payload(param: llm_param.LLMCallParameter) -> tuple[CompletionCreateParamsStreaming, dict[str, object]]:
|
|
@@ -4,8 +4,8 @@ from abc import ABC, abstractmethod
|
|
|
4
4
|
from openai.types.chat.chat_completion_chunk import ChoiceDeltaToolCall
|
|
5
5
|
from pydantic import BaseModel, Field
|
|
6
6
|
|
|
7
|
+
from klaude_code.log import log_debug
|
|
7
8
|
from klaude_code.protocol import message
|
|
8
|
-
from klaude_code.trace.log import log_debug
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
def normalize_tool_name(name: str) -> str:
|
|
@@ -22,8 +22,8 @@ from klaude_code.llm.openrouter.input import convert_history_to_input, is_claude
|
|
|
22
22
|
from klaude_code.llm.openrouter.reasoning import ReasoningStreamHandler
|
|
23
23
|
from klaude_code.llm.registry import register
|
|
24
24
|
from klaude_code.llm.usage import MetadataTracker
|
|
25
|
+
from klaude_code.log import DebugType, is_debug_enabled, log_debug
|
|
25
26
|
from klaude_code.protocol import llm_param, message
|
|
26
|
-
from klaude_code.trace import DebugType, is_debug_enabled, log_debug
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
def build_payload(
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
from pydantic import BaseModel
|
|
2
2
|
|
|
3
3
|
from klaude_code.llm.openai_compatible.stream import ReasoningDeltaResult, ReasoningHandlerABC
|
|
4
|
+
from klaude_code.log import log
|
|
4
5
|
from klaude_code.protocol import message
|
|
5
|
-
from klaude_code.trace import log
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class ReasoningDetail(BaseModel):
|
|
@@ -14,8 +14,8 @@ from klaude_code.llm.input_common import apply_config_defaults
|
|
|
14
14
|
from klaude_code.llm.registry import register
|
|
15
15
|
from klaude_code.llm.responses.input import convert_history_to_input, convert_tool_schema
|
|
16
16
|
from klaude_code.llm.usage import MetadataTracker, error_stream_items
|
|
17
|
+
from klaude_code.log import DebugType, log_debug
|
|
17
18
|
from klaude_code.protocol import llm_param, message, model
|
|
18
|
-
from klaude_code.trace import DebugType, log_debug
|
|
19
19
|
|
|
20
20
|
if TYPE_CHECKING:
|
|
21
21
|
from openai import AsyncStream
|
klaude_code/protocol/commands.py
CHANGED
|
@@ -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"
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from klaude_code.protocol.events.base import Event, ResponseEvent
|
|
4
|
+
from klaude_code.protocol.events.chat import DeveloperMessageEvent, TodoChangeEvent, UserMessageEvent
|
|
5
|
+
from klaude_code.protocol.events.lifecycle import TaskFinishEvent, TaskStartEvent, TurnEndEvent, TurnStartEvent
|
|
6
|
+
from klaude_code.protocol.events.metadata import TaskMetadataEvent, UsageEvent
|
|
7
|
+
from klaude_code.protocol.events.streaming import (
|
|
8
|
+
AssistantImageDeltaEvent,
|
|
9
|
+
AssistantTextDeltaEvent,
|
|
10
|
+
AssistantTextEndEvent,
|
|
11
|
+
AssistantTextStartEvent,
|
|
12
|
+
ResponseCompleteEvent,
|
|
13
|
+
ThinkingDeltaEvent,
|
|
14
|
+
ThinkingEndEvent,
|
|
15
|
+
ThinkingStartEvent,
|
|
16
|
+
ToolCallStartEvent,
|
|
17
|
+
)
|
|
18
|
+
from klaude_code.protocol.events.system import (
|
|
19
|
+
EndEvent,
|
|
20
|
+
ErrorEvent,
|
|
21
|
+
InterruptEvent,
|
|
22
|
+
ReplayEventUnion,
|
|
23
|
+
ReplayHistoryEvent,
|
|
24
|
+
WelcomeEvent,
|
|
25
|
+
)
|
|
26
|
+
from klaude_code.protocol.events.tools import ToolCallEvent, ToolResultEvent
|
|
27
|
+
|
|
28
|
+
__all__ = [
|
|
29
|
+
"AssistantImageDeltaEvent",
|
|
30
|
+
"AssistantTextDeltaEvent",
|
|
31
|
+
"AssistantTextEndEvent",
|
|
32
|
+
"AssistantTextStartEvent",
|
|
33
|
+
"DeveloperMessageEvent",
|
|
34
|
+
"EndEvent",
|
|
35
|
+
"ErrorEvent",
|
|
36
|
+
"Event",
|
|
37
|
+
"InterruptEvent",
|
|
38
|
+
"ReplayEventUnion",
|
|
39
|
+
"ReplayHistoryEvent",
|
|
40
|
+
"ResponseCompleteEvent",
|
|
41
|
+
"ResponseEvent",
|
|
42
|
+
"TaskFinishEvent",
|
|
43
|
+
"TaskMetadataEvent",
|
|
44
|
+
"TaskStartEvent",
|
|
45
|
+
"ThinkingDeltaEvent",
|
|
46
|
+
"ThinkingEndEvent",
|
|
47
|
+
"ThinkingStartEvent",
|
|
48
|
+
"TodoChangeEvent",
|
|
49
|
+
"ToolCallEvent",
|
|
50
|
+
"ToolCallStartEvent",
|
|
51
|
+
"ToolResultEvent",
|
|
52
|
+
"TurnEndEvent",
|
|
53
|
+
"TurnStartEvent",
|
|
54
|
+
"UsageEvent",
|
|
55
|
+
"UserMessageEvent",
|
|
56
|
+
"WelcomeEvent",
|
|
57
|
+
]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import time
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, Field
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Event(BaseModel):
|
|
9
|
+
"""Base event."""
|
|
10
|
+
|
|
11
|
+
session_id: str
|
|
12
|
+
timestamp: float = Field(default_factory=time.time)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ResponseEvent(Event):
|
|
16
|
+
"""Event associated with a single model response."""
|
|
17
|
+
|
|
18
|
+
response_id: str | None = None
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from klaude_code.protocol import message, model
|
|
4
|
+
|
|
5
|
+
from .base import Event
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class UserMessageEvent(Event):
|
|
9
|
+
content: str
|
|
10
|
+
images: list[message.ImageURLPart] | None = None
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class DeveloperMessageEvent(Event):
|
|
14
|
+
"""DeveloperMessages are reminders in user messages or tool results."""
|
|
15
|
+
|
|
16
|
+
item: message.DeveloperMessage
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class TodoChangeEvent(Event):
|
|
20
|
+
todos: list[model.TodoItem]
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from klaude_code.protocol import model
|
|
4
|
+
|
|
5
|
+
from .base import Event
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TaskStartEvent(Event):
|
|
9
|
+
sub_agent_state: model.SubAgentState | None = None
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class TaskFinishEvent(Event):
|
|
13
|
+
task_result: str
|
|
14
|
+
has_structured_output: bool = False
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class TurnStartEvent(Event):
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class TurnEndEvent(Event):
|
|
22
|
+
pass
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""Metadata-related protocol events."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from klaude_code.protocol import model
|
|
6
|
+
|
|
7
|
+
from .base import Event, ResponseEvent
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class UsageEvent(ResponseEvent):
|
|
11
|
+
usage: model.Usage
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class TaskMetadataEvent(Event):
|
|
15
|
+
metadata: model.TaskMetadataItem
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from .base import ResponseEvent
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ThinkingStartEvent(ResponseEvent):
|
|
7
|
+
pass
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ThinkingDeltaEvent(ResponseEvent):
|
|
11
|
+
content: str
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ThinkingEndEvent(ResponseEvent):
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class AssistantTextStartEvent(ResponseEvent):
|
|
19
|
+
pass
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class AssistantTextDeltaEvent(ResponseEvent):
|
|
23
|
+
content: str
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class AssistantTextEndEvent(ResponseEvent):
|
|
27
|
+
pass
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class AssistantImageDeltaEvent(ResponseEvent):
|
|
31
|
+
file_path: str
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class ToolCallStartEvent(ResponseEvent):
|
|
35
|
+
tool_call_id: str
|
|
36
|
+
tool_name: str
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class ResponseCompleteEvent(ResponseEvent):
|
|
40
|
+
"""Final snapshot of the model response."""
|
|
41
|
+
|
|
42
|
+
content: str
|
|
43
|
+
thinking_text: str | None = None
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from klaude_code.protocol import llm_param
|
|
4
|
+
from klaude_code.protocol.events.chat import DeveloperMessageEvent, UserMessageEvent
|
|
5
|
+
from klaude_code.protocol.events.lifecycle import TaskFinishEvent, TaskStartEvent, TurnStartEvent
|
|
6
|
+
from klaude_code.protocol.events.metadata import TaskMetadataEvent
|
|
7
|
+
from klaude_code.protocol.events.streaming import AssistantImageDeltaEvent, ResponseCompleteEvent
|
|
8
|
+
from klaude_code.protocol.events.tools import ToolCallEvent, ToolResultEvent
|
|
9
|
+
|
|
10
|
+
from .base import Event
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class WelcomeEvent(Event):
|
|
14
|
+
work_dir: str
|
|
15
|
+
llm_config: llm_param.LLMConfigParameter
|
|
16
|
+
show_klaude_code_info: bool = True
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class ErrorEvent(Event):
|
|
20
|
+
error_message: str
|
|
21
|
+
can_retry: bool = False
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class InterruptEvent(Event):
|
|
25
|
+
pass
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class EndEvent(Event):
|
|
29
|
+
"""Global display shutdown."""
|
|
30
|
+
|
|
31
|
+
session_id: str = "__app__"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
type ReplayEventUnion = (
|
|
35
|
+
TaskStartEvent
|
|
36
|
+
| TaskFinishEvent
|
|
37
|
+
| TurnStartEvent
|
|
38
|
+
| AssistantImageDeltaEvent
|
|
39
|
+
| ResponseCompleteEvent
|
|
40
|
+
| ToolCallEvent
|
|
41
|
+
| ToolResultEvent
|
|
42
|
+
| UserMessageEvent
|
|
43
|
+
| TaskMetadataEvent
|
|
44
|
+
| InterruptEvent
|
|
45
|
+
| DeveloperMessageEvent
|
|
46
|
+
| ErrorEvent
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class ReplayHistoryEvent(Event):
|
|
51
|
+
events: list[ReplayEventUnion]
|
|
52
|
+
updated_at: float
|
|
53
|
+
is_load: bool = True
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Literal
|
|
4
|
+
|
|
5
|
+
from klaude_code.protocol import model
|
|
6
|
+
|
|
7
|
+
from .base import ResponseEvent
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ToolCallEvent(ResponseEvent):
|
|
11
|
+
tool_call_id: str
|
|
12
|
+
tool_name: str
|
|
13
|
+
arguments: str
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ToolResultEvent(ResponseEvent):
|
|
17
|
+
tool_call_id: str
|
|
18
|
+
tool_name: str
|
|
19
|
+
result: str
|
|
20
|
+
ui_extra: model.ToolResultUIExtra | None = None
|
|
21
|
+
status: Literal["success", "error", "aborted"]
|
|
22
|
+
task_metadata: model.TaskMetadata | None = None
|
|
23
|
+
is_last_in_turn: bool = True
|
|
24
|
+
|
|
25
|
+
@property
|
|
26
|
+
def is_error(self) -> bool:
|
|
27
|
+
return self.status in ("error", "aborted")
|
klaude_code/protocol/op.py
CHANGED
|
@@ -51,6 +51,11 @@ class RunAgentOperation(Operation):
|
|
|
51
51
|
type: OperationType = OperationType.RUN_AGENT
|
|
52
52
|
session_id: str
|
|
53
53
|
input: UserInputPayload
|
|
54
|
+
# Frontends may choose to render the user message themselves (e.g. TUI) to support
|
|
55
|
+
# event-only commands; in that case the core should skip emitting the UserMessageEvent.
|
|
56
|
+
emit_user_message_event: bool = True
|
|
57
|
+
# Frontends may choose to run without persisting input (e.g. some interactive commands).
|
|
58
|
+
persist_user_input: bool = True
|
|
54
59
|
|
|
55
60
|
async def execute(self, handler: OperationHandler) -> None:
|
|
56
61
|
await handler.handle_run_agent(self)
|