klaude-code 2.0.2__py3-none-any.whl → 2.1.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/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 +284 -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 +64 -99
- klaude_code/core/task.py +12 -20
- klaude_code/core/tool/__init__.py +5 -17
- 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/skill/skill_tool.py +3 -1
- 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 +86 -26
- 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/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 +23 -0
- klaude_code/protocol/op.py +5 -0
- klaude_code/session/session.py +6 -5
- klaude_code/skill/assets/create-plan/SKILL.md +76 -0
- klaude_code/skill/loader.py +1 -1
- klaude_code/skill/system_skills.py +1 -1
- klaude_code/tui/__init__.py +8 -0
- klaude_code/{command → tui/command}/clear_cmd.py +2 -1
- 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 +9 -9
- 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 +606 -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.0.dist-info}/METADATA +1 -1
- klaude_code-2.1.0.dist-info/RECORD +235 -0
- klaude_code/cli/runtime.py +0 -518
- klaude_code/core/prompt.py +0 -108
- 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/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}/__init__.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/{ui/renderers → 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.0.dist-info}/WHEEL +0 -0
- {klaude_code-2.0.2.dist-info → klaude_code-2.1.0.dist-info}/entry_points.txt +0 -0
|
@@ -16,6 +16,7 @@ from klaude_code.const import (
|
|
|
16
16
|
WEB_FETCH_DEFAULT_TIMEOUT_SEC,
|
|
17
17
|
WEB_FETCH_USER_AGENT,
|
|
18
18
|
)
|
|
19
|
+
from klaude_code.core.tool.context import ToolContext
|
|
19
20
|
from klaude_code.core.tool.tool_abc import ToolABC, ToolConcurrencyPolicy, ToolMetadata, load_desc
|
|
20
21
|
from klaude_code.core.tool.tool_registry import register
|
|
21
22
|
from klaude_code.protocol import llm_param, message, tools
|
|
@@ -213,7 +214,7 @@ class WebFetchTool(ToolABC):
|
|
|
213
214
|
url: str
|
|
214
215
|
|
|
215
216
|
@classmethod
|
|
216
|
-
async def call(cls, arguments: str) -> message.ToolResultMessage:
|
|
217
|
+
async def call(cls, arguments: str, context: ToolContext) -> message.ToolResultMessage:
|
|
217
218
|
try:
|
|
218
219
|
args = WebFetchTool.WebFetchArguments.model_validate_json(arguments)
|
|
219
220
|
except ValueError as e:
|
|
@@ -221,10 +222,11 @@ class WebFetchTool(ToolABC):
|
|
|
221
222
|
status="error",
|
|
222
223
|
output_text=f"Invalid arguments: {e}",
|
|
223
224
|
)
|
|
224
|
-
return await cls.call_with_args(args)
|
|
225
|
+
return await cls.call_with_args(args, context)
|
|
225
226
|
|
|
226
227
|
@classmethod
|
|
227
|
-
async def call_with_args(cls, args: WebFetchArguments) -> message.ToolResultMessage:
|
|
228
|
+
async def call_with_args(cls, args: WebFetchArguments, context: ToolContext) -> message.ToolResultMessage:
|
|
229
|
+
del context
|
|
228
230
|
url = args.url
|
|
229
231
|
|
|
230
232
|
# Basic URL validation
|
|
@@ -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):
|
|
@@ -206,6 +206,8 @@ class TurnExecutor:
|
|
|
206
206
|
|
|
207
207
|
ctx = self._context
|
|
208
208
|
session_ctx = ctx.session_ctx
|
|
209
|
+
thinking_active = False
|
|
210
|
+
assistant_text_active = False
|
|
209
211
|
message_types = (
|
|
210
212
|
message.SystemMessage,
|
|
211
213
|
message.DeveloperMessage,
|
|
@@ -247,12 +249,30 @@ class TurnExecutor:
|
|
|
247
249
|
)
|
|
248
250
|
match delta:
|
|
249
251
|
case message.ThinkingTextDelta() as delta:
|
|
252
|
+
if not thinking_active:
|
|
253
|
+
thinking_active = True
|
|
254
|
+
yield events.ThinkingStartEvent(
|
|
255
|
+
response_id=delta.response_id,
|
|
256
|
+
session_id=session_ctx.session_id,
|
|
257
|
+
)
|
|
250
258
|
yield events.ThinkingDeltaEvent(
|
|
251
259
|
content=delta.content,
|
|
252
260
|
response_id=delta.response_id,
|
|
253
261
|
session_id=session_ctx.session_id,
|
|
254
262
|
)
|
|
255
263
|
case message.AssistantTextDelta() as delta:
|
|
264
|
+
if thinking_active:
|
|
265
|
+
thinking_active = False
|
|
266
|
+
yield events.ThinkingEndEvent(
|
|
267
|
+
response_id=delta.response_id,
|
|
268
|
+
session_id=session_ctx.session_id,
|
|
269
|
+
)
|
|
270
|
+
if not assistant_text_active:
|
|
271
|
+
assistant_text_active = True
|
|
272
|
+
yield events.AssistantTextStartEvent(
|
|
273
|
+
response_id=delta.response_id,
|
|
274
|
+
session_id=session_ctx.session_id,
|
|
275
|
+
)
|
|
256
276
|
if delta.response_id:
|
|
257
277
|
self._assistant_response_id = delta.response_id
|
|
258
278
|
self._assistant_delta_buffer.append(delta.content)
|
|
@@ -262,6 +282,12 @@ class TurnExecutor:
|
|
|
262
282
|
session_id=session_ctx.session_id,
|
|
263
283
|
)
|
|
264
284
|
case message.AssistantImageDelta() as delta:
|
|
285
|
+
if thinking_active:
|
|
286
|
+
thinking_active = False
|
|
287
|
+
yield events.ThinkingEndEvent(
|
|
288
|
+
response_id=delta.response_id,
|
|
289
|
+
session_id=session_ctx.session_id,
|
|
290
|
+
)
|
|
265
291
|
yield events.AssistantImageDeltaEvent(
|
|
266
292
|
file_path=delta.file_path,
|
|
267
293
|
response_id=delta.response_id,
|
|
@@ -270,6 +296,18 @@ class TurnExecutor:
|
|
|
270
296
|
case message.AssistantMessage() as msg:
|
|
271
297
|
if msg.response_id is None and self._assistant_response_id:
|
|
272
298
|
msg.response_id = self._assistant_response_id
|
|
299
|
+
if thinking_active:
|
|
300
|
+
thinking_active = False
|
|
301
|
+
yield events.ThinkingEndEvent(
|
|
302
|
+
response_id=msg.response_id,
|
|
303
|
+
session_id=session_ctx.session_id,
|
|
304
|
+
)
|
|
305
|
+
if assistant_text_active:
|
|
306
|
+
assistant_text_active = False
|
|
307
|
+
yield events.AssistantTextEndEvent(
|
|
308
|
+
response_id=msg.response_id,
|
|
309
|
+
session_id=session_ctx.session_id,
|
|
310
|
+
)
|
|
273
311
|
turn_result.assistant_message = msg
|
|
274
312
|
for part in msg.parts:
|
|
275
313
|
if isinstance(part, message.ToolCallPart):
|
|
@@ -281,11 +319,16 @@ class TurnExecutor:
|
|
|
281
319
|
arguments_json=part.arguments_json,
|
|
282
320
|
)
|
|
283
321
|
)
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
322
|
+
if msg.stop_reason != "aborted":
|
|
323
|
+
thinking_text = "".join(
|
|
324
|
+
part.text for part in msg.parts if isinstance(part, message.ThinkingTextPart)
|
|
325
|
+
)
|
|
326
|
+
yield events.ResponseCompleteEvent(
|
|
327
|
+
content=message.join_text_parts(msg.parts),
|
|
328
|
+
response_id=msg.response_id,
|
|
329
|
+
session_id=session_ctx.session_id,
|
|
330
|
+
thinking_text=thinking_text or None,
|
|
331
|
+
)
|
|
289
332
|
if msg.stop_reason == "aborted":
|
|
290
333
|
yield events.InterruptEvent(session_id=session_ctx.session_id)
|
|
291
334
|
if msg.usage:
|
|
@@ -296,9 +339,9 @@ class TurnExecutor:
|
|
|
296
339
|
metadata.model_name = ctx.llm_client.model_name
|
|
297
340
|
if metadata.provider is None:
|
|
298
341
|
metadata.provider = ctx.llm_client.get_llm_config().provider_name or None
|
|
299
|
-
yield events.
|
|
342
|
+
yield events.UsageEvent(
|
|
300
343
|
session_id=session_ctx.session_id,
|
|
301
|
-
|
|
344
|
+
usage=metadata,
|
|
302
345
|
)
|
|
303
346
|
case message.StreamErrorItem() as msg:
|
|
304
347
|
turn_result.stream_error = msg
|
|
@@ -309,12 +352,23 @@ class TurnExecutor:
|
|
|
309
352
|
debug_type=DebugType.RESPONSE,
|
|
310
353
|
)
|
|
311
354
|
case message.ToolCallStartItem() as msg:
|
|
312
|
-
|
|
355
|
+
if thinking_active:
|
|
356
|
+
thinking_active = False
|
|
357
|
+
yield events.ThinkingEndEvent(
|
|
358
|
+
response_id=msg.response_id,
|
|
359
|
+
session_id=session_ctx.session_id,
|
|
360
|
+
)
|
|
361
|
+
if assistant_text_active:
|
|
362
|
+
assistant_text_active = False
|
|
363
|
+
yield events.AssistantTextEndEvent(
|
|
364
|
+
response_id=msg.response_id,
|
|
365
|
+
session_id=session_ctx.session_id,
|
|
366
|
+
)
|
|
367
|
+
yield events.ToolCallStartEvent(
|
|
313
368
|
session_id=session_ctx.session_id,
|
|
314
369
|
response_id=msg.response_id,
|
|
315
370
|
tool_call_id=msg.call_id,
|
|
316
371
|
tool_name=msg.name,
|
|
317
|
-
arguments="",
|
|
318
372
|
)
|
|
319
373
|
case _:
|
|
320
374
|
continue
|
|
@@ -332,20 +386,26 @@ class TurnExecutor:
|
|
|
332
386
|
|
|
333
387
|
ctx = self._context
|
|
334
388
|
session_ctx = ctx.session_ctx
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
)
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
389
|
+
tool_context = ToolContext(
|
|
390
|
+
file_tracker=session_ctx.file_tracker,
|
|
391
|
+
todo_context=session_ctx.todo_context,
|
|
392
|
+
session_id=session_ctx.session_id,
|
|
393
|
+
run_subtask=session_ctx.run_subtask,
|
|
394
|
+
sub_agent_resume_claims=SubAgentResumeClaims(),
|
|
395
|
+
)
|
|
396
|
+
|
|
397
|
+
executor = ToolExecutor(
|
|
398
|
+
context=tool_context,
|
|
399
|
+
registry=ctx.tool_registry,
|
|
400
|
+
append_history=session_ctx.append_history,
|
|
401
|
+
)
|
|
402
|
+
self._tool_executor = executor
|
|
403
|
+
try:
|
|
404
|
+
async for exec_event in executor.run_tools(tool_calls):
|
|
405
|
+
for ui_event in build_events_from_tool_executor_event(session_ctx.session_id, exec_event):
|
|
406
|
+
yield ui_event
|
|
407
|
+
finally:
|
|
408
|
+
self._tool_executor = None
|
|
349
409
|
|
|
350
410
|
def _persist_partial_assistant_on_cancel(self) -> None:
|
|
351
411
|
"""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
|
|
@@ -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,23 @@
|
|
|
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"]
|
|
22
|
+
task_metadata: model.TaskMetadata | None = None
|
|
23
|
+
is_last_in_turn: bool = True
|
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)
|