klaude-code 2.0.1__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 +10 -1
- klaude_code/core/agent.py +9 -62
- klaude_code/core/agent_profile.py +284 -0
- klaude_code/core/executor.py +343 -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 +107 -155
- 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 +42 -44
- 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/message.py +3 -11
- klaude_code/protocol/model.py +78 -9
- klaude_code/protocol/op.py +5 -0
- klaude_code/protocol/sub_agent/explore.py +0 -15
- klaude_code/protocol/sub_agent/task.py +1 -1
- klaude_code/protocol/sub_agent/web.py +1 -17
- klaude_code/protocol/tools.py +0 -1
- 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 +4 -3
- klaude_code/{command → tui/command}/export_cmd.py +2 -1
- klaude_code/{command → tui/command}/export_online_cmd.py +6 -5
- klaude_code/{command → tui/command}/fork_session_cmd.py +10 -9
- klaude_code/{command → tui/command}/help_cmd.py +3 -2
- klaude_code/{command → tui/command}/model_cmd.py +5 -4
- 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 +16 -6
- klaude_code/{command → tui/command}/release_notes_cmd.py +3 -2
- klaude_code/{command → tui/command}/resume_cmd.py +6 -5
- klaude_code/{command → tui/command}/status_cmd.py +4 -3
- klaude_code/{command → tui/command}/terminal_setup_cmd.py +4 -3
- klaude_code/{command → tui/command}/thinking_cmd.py +4 -3
- 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/tui/components/developer.py +231 -0
- 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 +34 -21
- klaude_code/{ui → tui/components}/rich/markdown.py +78 -34
- klaude_code/{ui → tui/components}/rich/status.py +2 -2
- klaude_code/{ui → tui/components}/rich/theme.py +12 -5
- 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 +11 -48
- 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} +11 -7
- 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 → tui}/terminal/selector.py +36 -17
- 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} +1 -4
- 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.1.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 -525
- klaude_code/core/prompt.py +0 -108
- klaude_code/core/tool/file/move_tool.md +0 -41
- klaude_code/core/tool/file/move_tool.py +0 -435
- klaude_code/core/tool/tool_context.py +0 -148
- klaude_code/protocol/events.py +0 -194
- 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 -634
- klaude_code/ui/modes/repl/renderer.py +0 -463
- klaude_code/ui/renderers/developer.py +0 -215
- klaude_code/ui/utils/__init__.py +0 -1
- klaude_code-2.0.1.dist-info/RECORD +0 -229
- /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/{utils/common.py → common.py} +0 -0
- {klaude_code-2.0.1.dist-info → klaude_code-2.1.0.dist-info}/WHEEL +0 -0
- {klaude_code-2.0.1.dist-info → klaude_code-2.1.0.dist-info}/entry_points.txt +0 -0
|
@@ -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/message.py
CHANGED
|
@@ -12,8 +12,7 @@ from typing import Annotated, Literal
|
|
|
12
12
|
from pydantic import BaseModel, Field, field_validator
|
|
13
13
|
|
|
14
14
|
from klaude_code.protocol.model import (
|
|
15
|
-
|
|
16
|
-
CommandOutput,
|
|
15
|
+
DeveloperUIExtra,
|
|
17
16
|
StopReason,
|
|
18
17
|
TaskMetadata,
|
|
19
18
|
TaskMetadataItem,
|
|
@@ -137,15 +136,8 @@ class DeveloperMessage(MessageBase):
|
|
|
137
136
|
role: Literal["developer"] = "developer"
|
|
138
137
|
parts: list[Part]
|
|
139
138
|
|
|
140
|
-
#
|
|
141
|
-
|
|
142
|
-
memory_mentioned: dict[str, list[str]] | None = None # memory_path -> list of @ patterns mentioned in it
|
|
143
|
-
external_file_changes: list[str] | None = None
|
|
144
|
-
todo_use: bool | None = None
|
|
145
|
-
at_files: list[AtPatternParseResult] | None = None
|
|
146
|
-
command_output: CommandOutput | None = None
|
|
147
|
-
user_image_count: int | None = None
|
|
148
|
-
skill_name: str | None = None # Skill name activated via $skill syntax
|
|
139
|
+
# Structured UI-only metadata (never sent to the LLM).
|
|
140
|
+
ui_extra: DeveloperUIExtra | None = None
|
|
149
141
|
|
|
150
142
|
|
|
151
143
|
class UserMessage(MessageBase):
|
klaude_code/protocol/model.py
CHANGED
|
@@ -272,21 +272,90 @@ ToolResultUIExtra = Annotated[
|
|
|
272
272
|
]
|
|
273
273
|
|
|
274
274
|
|
|
275
|
-
class AtPatternParseResult(BaseModel):
|
|
276
|
-
path: str
|
|
277
|
-
tool_name: str
|
|
278
|
-
result: str
|
|
279
|
-
tool_args: str
|
|
280
|
-
operation: Literal["Read", "List"]
|
|
281
|
-
mentioned_in: str | None = None # Parent file that referenced this file
|
|
282
|
-
|
|
283
|
-
|
|
284
275
|
class CommandOutput(BaseModel):
|
|
285
276
|
command_name: CommandName
|
|
286
277
|
ui_extra: ToolResultUIExtra | None = None
|
|
287
278
|
is_error: bool = False
|
|
288
279
|
|
|
289
280
|
|
|
281
|
+
class MemoryFileLoaded(BaseModel):
|
|
282
|
+
path: str
|
|
283
|
+
mentioned_patterns: list[str] = Field(default_factory=list)
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
class MemoryLoadedUIItem(BaseModel):
|
|
287
|
+
type: Literal["memory_loaded"] = "memory_loaded"
|
|
288
|
+
files: list[MemoryFileLoaded]
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
class ExternalFileChangesUIItem(BaseModel):
|
|
292
|
+
type: Literal["external_file_changes"] = "external_file_changes"
|
|
293
|
+
paths: list[str]
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
class TodoReminderUIItem(BaseModel):
|
|
297
|
+
type: Literal["todo_reminder"] = "todo_reminder"
|
|
298
|
+
reason: Literal["empty", "not_used_recently"]
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
class AtFileOp(BaseModel):
|
|
302
|
+
operation: Literal["Read", "List"]
|
|
303
|
+
path: str
|
|
304
|
+
mentioned_in: str | None = None
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
class AtFileOpsUIItem(BaseModel):
|
|
308
|
+
type: Literal["at_file_ops"] = "at_file_ops"
|
|
309
|
+
ops: list[AtFileOp]
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
class UserImagesUIItem(BaseModel):
|
|
313
|
+
type: Literal["user_images"] = "user_images"
|
|
314
|
+
count: int
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
class SkillActivatedUIItem(BaseModel):
|
|
318
|
+
type: Literal["skill_activated"] = "skill_activated"
|
|
319
|
+
name: str
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
class CommandOutputUIItem(BaseModel):
|
|
323
|
+
type: Literal["command_output"] = "command_output"
|
|
324
|
+
output: CommandOutput
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
type DeveloperUIItem = (
|
|
328
|
+
MemoryLoadedUIItem
|
|
329
|
+
| ExternalFileChangesUIItem
|
|
330
|
+
| TodoReminderUIItem
|
|
331
|
+
| AtFileOpsUIItem
|
|
332
|
+
| UserImagesUIItem
|
|
333
|
+
| SkillActivatedUIItem
|
|
334
|
+
| CommandOutputUIItem
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
def _empty_developer_ui_items() -> list[DeveloperUIItem]:
|
|
339
|
+
return []
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
class DeveloperUIExtra(BaseModel):
|
|
343
|
+
items: list[DeveloperUIItem] = Field(default_factory=_empty_developer_ui_items)
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
def build_command_output_extra(
|
|
347
|
+
command_name: CommandName,
|
|
348
|
+
*,
|
|
349
|
+
ui_extra: ToolResultUIExtra | None = None,
|
|
350
|
+
is_error: bool = False,
|
|
351
|
+
) -> DeveloperUIExtra:
|
|
352
|
+
return DeveloperUIExtra(
|
|
353
|
+
items=[
|
|
354
|
+
CommandOutputUIItem(output=CommandOutput(command_name=command_name, ui_extra=ui_extra, is_error=is_error))
|
|
355
|
+
]
|
|
356
|
+
)
|
|
357
|
+
|
|
358
|
+
|
|
290
359
|
class SubAgentState(BaseModel):
|
|
291
360
|
sub_agent_type: SubAgentType
|
|
292
361
|
sub_agent_desc: str
|
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)
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import Any
|
|
4
|
-
|
|
5
3
|
from klaude_code.protocol import tools
|
|
6
4
|
from klaude_code.protocol.sub_agent import SubAgentProfile, register_sub_agent
|
|
7
5
|
|
|
@@ -37,11 +35,6 @@ EXPLORE_PARAMETERS = {
|
|
|
37
35
|
"type": "string",
|
|
38
36
|
"description": "The task for the agent to perform",
|
|
39
37
|
},
|
|
40
|
-
"thoroughness": {
|
|
41
|
-
"type": "string",
|
|
42
|
-
"enum": ["quick", "medium", "very thorough"],
|
|
43
|
-
"description": "Controls how deep the sub-agent should search the repo",
|
|
44
|
-
},
|
|
45
38
|
"output_format": {
|
|
46
39
|
"type": "object",
|
|
47
40
|
"description": "Optional JSON Schema for sub-agent structured output",
|
|
@@ -52,13 +45,6 @@ EXPLORE_PARAMETERS = {
|
|
|
52
45
|
}
|
|
53
46
|
|
|
54
47
|
|
|
55
|
-
def _explore_prompt_builder(args: dict[str, Any]) -> str:
|
|
56
|
-
"""Build the Explore prompt from tool arguments."""
|
|
57
|
-
prompt = args.get("prompt", "").strip()
|
|
58
|
-
thoroughness = args.get("thoroughness", "medium")
|
|
59
|
-
return f"{prompt}\nthoroughness: {thoroughness}"
|
|
60
|
-
|
|
61
|
-
|
|
62
48
|
register_sub_agent(
|
|
63
49
|
SubAgentProfile(
|
|
64
50
|
name="Explore",
|
|
@@ -66,7 +52,6 @@ register_sub_agent(
|
|
|
66
52
|
parameters=EXPLORE_PARAMETERS,
|
|
67
53
|
prompt_file="prompts/prompt-sub-agent-explore.md",
|
|
68
54
|
tool_set=(tools.BASH, tools.READ),
|
|
69
|
-
prompt_builder=_explore_prompt_builder,
|
|
70
55
|
active_form="Exploring",
|
|
71
56
|
output_schema_arg="output_format",
|
|
72
57
|
)
|
|
@@ -64,7 +64,7 @@ register_sub_agent(
|
|
|
64
64
|
description=TASK_DESCRIPTION,
|
|
65
65
|
parameters=TASK_PARAMETERS,
|
|
66
66
|
prompt_file="prompts/prompt-sub-agent.md",
|
|
67
|
-
tool_set=(tools.BASH, tools.READ, tools.EDIT, tools.WRITE
|
|
67
|
+
tool_set=(tools.BASH, tools.READ, tools.EDIT, tools.WRITE),
|
|
68
68
|
active_form="Tasking",
|
|
69
69
|
output_schema_arg="output_format",
|
|
70
70
|
)
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import Any
|
|
4
|
-
|
|
5
3
|
from klaude_code.protocol import tools
|
|
6
4
|
from klaude_code.protocol.sub_agent import SubAgentProfile, register_sub_agent
|
|
7
5
|
|
|
@@ -21,7 +19,7 @@ Capabilities:
|
|
|
21
19
|
How to use:
|
|
22
20
|
- Write a clear prompt describing what information you need - the agent will search and fetch as needed
|
|
23
21
|
- Account for "Today's date" in <env>. For example, if <env> says "Today's date: 2025-07-01", and the user wants the latest docs, do not use 2024 in the search query. Use 2025.
|
|
24
|
-
-
|
|
22
|
+
- Provide the url if you already know the target page
|
|
25
23
|
- Use `output_format` (JSON Schema) to get structured data back from the agent
|
|
26
24
|
|
|
27
25
|
What you receive:
|
|
@@ -48,10 +46,6 @@ WEB_AGENT_PARAMETERS = {
|
|
|
48
46
|
"type": "string",
|
|
49
47
|
"description": "A short (3-5 word) description of the task",
|
|
50
48
|
},
|
|
51
|
-
"url": {
|
|
52
|
-
"type": "string",
|
|
53
|
-
"description": "The URL to fetch and analyze. If not provided, the agent will search the web first",
|
|
54
|
-
},
|
|
55
49
|
"prompt": {
|
|
56
50
|
"type": "string",
|
|
57
51
|
"description": "Instructions for searching, analyzing, or extracting content from the web page",
|
|
@@ -66,15 +60,6 @@ WEB_AGENT_PARAMETERS = {
|
|
|
66
60
|
}
|
|
67
61
|
|
|
68
62
|
|
|
69
|
-
def _web_agent_prompt_builder(args: dict[str, Any]) -> str:
|
|
70
|
-
"""Build the WebAgent prompt from tool arguments."""
|
|
71
|
-
url = args.get("url", "")
|
|
72
|
-
prompt = args.get("prompt", "")
|
|
73
|
-
if url:
|
|
74
|
-
return f"URL to fetch: {url}\nTask: {prompt}"
|
|
75
|
-
return prompt
|
|
76
|
-
|
|
77
|
-
|
|
78
63
|
register_sub_agent(
|
|
79
64
|
SubAgentProfile(
|
|
80
65
|
name="WebAgent",
|
|
@@ -82,7 +67,6 @@ register_sub_agent(
|
|
|
82
67
|
parameters=WEB_AGENT_PARAMETERS,
|
|
83
68
|
prompt_file="prompts/prompt-sub-agent-web.md",
|
|
84
69
|
tool_set=(tools.BASH, tools.READ, tools.WEB_FETCH, tools.WEB_SEARCH, tools.WRITE),
|
|
85
|
-
prompt_builder=_web_agent_prompt_builder,
|
|
86
70
|
active_form="Surfing",
|
|
87
71
|
output_schema_arg="output_format",
|
|
88
72
|
)
|
klaude_code/protocol/tools.py
CHANGED
klaude_code/session/session.py
CHANGED
|
@@ -289,7 +289,7 @@ class Session(BaseModel):
|
|
|
289
289
|
return True
|
|
290
290
|
return isinstance(prev_item, (message.UserMessage, message.ToolResultMessage, message.DeveloperMessage))
|
|
291
291
|
|
|
292
|
-
def get_history_item(self) -> Iterable[events.
|
|
292
|
+
def get_history_item(self) -> Iterable[events.ReplayEventUnion]:
|
|
293
293
|
seen_sub_agent_sessions: set[str] = set()
|
|
294
294
|
prev_item: message.HistoryEvent | None = None
|
|
295
295
|
last_assistant_content: str = ""
|
|
@@ -314,8 +314,8 @@ class Session(BaseModel):
|
|
|
314
314
|
response_id=am.response_id,
|
|
315
315
|
session_id=self.id,
|
|
316
316
|
)
|
|
317
|
-
yield events.
|
|
318
|
-
thinking_text=thinking_text,
|
|
317
|
+
yield events.ResponseCompleteEvent(
|
|
318
|
+
thinking_text=thinking_text or None,
|
|
319
319
|
content=content,
|
|
320
320
|
response_id=am.response_id,
|
|
321
321
|
session_id=self.id,
|
|
@@ -360,7 +360,8 @@ class Session(BaseModel):
|
|
|
360
360
|
images=images or None,
|
|
361
361
|
)
|
|
362
362
|
case model.TaskMetadataItem() as mt:
|
|
363
|
-
|
|
363
|
+
if self.sub_agent_state is None:
|
|
364
|
+
yield events.TaskMetadataEvent(session_id=self.id, metadata=mt)
|
|
364
365
|
case message.DeveloperMessage() as dm:
|
|
365
366
|
yield events.DeveloperMessageEvent(session_id=self.id, item=dm)
|
|
366
367
|
case message.StreamErrorItem() as se:
|
|
@@ -377,7 +378,7 @@ class Session(BaseModel):
|
|
|
377
378
|
|
|
378
379
|
def _iter_sub_agent_history(
|
|
379
380
|
self, tool_result: message.ToolResultMessage, seen_sub_agent_sessions: set[str]
|
|
380
|
-
) -> Iterable[events.
|
|
381
|
+
) -> Iterable[events.ReplayEventUnion]:
|
|
381
382
|
ui_extra = tool_result.ui_extra
|
|
382
383
|
if not isinstance(ui_extra, model.SessionIdUIExtra):
|
|
383
384
|
return
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: create-plan
|
|
3
|
+
description: Create a concise plan. Use when a user explicitly asks for a plan related to a coding task.
|
|
4
|
+
metadata:
|
|
5
|
+
short-description: Create a plan
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Create Plan
|
|
9
|
+
|
|
10
|
+
## Goal
|
|
11
|
+
|
|
12
|
+
Turn a user prompt into a **single, actionable plan** delivered in the final assistant message.
|
|
13
|
+
|
|
14
|
+
## Minimal workflow
|
|
15
|
+
|
|
16
|
+
1. **Scan context quickly**
|
|
17
|
+
- Read `README.md` and any obvious docs (`docs/`, `CONTRIBUTING.md`, `ARCHITECTURE.md`).
|
|
18
|
+
- Skim relevant files (the ones most likely touched).
|
|
19
|
+
- Identify constraints (language, frameworks, CI/test commands, deployment shape).
|
|
20
|
+
|
|
21
|
+
2. **Ask follow-ups only if blocking**
|
|
22
|
+
- Ask **at most 1–2 questions**.
|
|
23
|
+
- Only ask if you cannot responsibly plan without the answer; prefer multiple-choice.
|
|
24
|
+
- If unsure but not blocked, make a reasonable assumption and proceed.
|
|
25
|
+
|
|
26
|
+
3. **Create a plan using the template below**
|
|
27
|
+
- Start with **1 short paragraph** describing the intent and approach.
|
|
28
|
+
- Clearly call out what is **in scope** and what is **not in scope** in short.
|
|
29
|
+
- Then provide a **small checklist** of action items (default 6–10 items).
|
|
30
|
+
- Each checklist item should be a concrete action and, when helpful, mention files/commands.
|
|
31
|
+
- **Make items atomic and ordered**: discovery → changes → tests → rollout.
|
|
32
|
+
- **Verb-first**: “Add…”, “Refactor…”, “Verify…”, “Ship…”.
|
|
33
|
+
- Include at least one item for **tests/validation** and one for **edge cases/risk** when applicable.
|
|
34
|
+
- If there are unknowns, include a tiny **Open questions** section (max 3).
|
|
35
|
+
|
|
36
|
+
4. **Write the plan to `plan.md` in the current working directory**
|
|
37
|
+
- Use the Write tool to save the plan to `./plan.md`
|
|
38
|
+
- If `plan.md` already exists, overwrite it with the new plan
|
|
39
|
+
|
|
40
|
+
5. **Do not preface the plan with meta explanations; output only the plan as per template**
|
|
41
|
+
|
|
42
|
+
## Plan template (follow exactly)
|
|
43
|
+
|
|
44
|
+
```markdown
|
|
45
|
+
# Plan
|
|
46
|
+
|
|
47
|
+
<1–3 sentences: what we’re doing, why, and the high-level approach.>
|
|
48
|
+
|
|
49
|
+
## Scope
|
|
50
|
+
- In:
|
|
51
|
+
- Out:
|
|
52
|
+
|
|
53
|
+
## Action items
|
|
54
|
+
[ ] <Step 1>
|
|
55
|
+
[ ] <Step 2>
|
|
56
|
+
[ ] <Step 3>
|
|
57
|
+
[ ] <Step 4>
|
|
58
|
+
[ ] <Step 5>
|
|
59
|
+
[ ] <Step 6>
|
|
60
|
+
|
|
61
|
+
## Open questions
|
|
62
|
+
- <Question 1>
|
|
63
|
+
- <Question 2>
|
|
64
|
+
- <Question 3>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Checklist item guidance
|
|
68
|
+
Good checklist items:
|
|
69
|
+
- Point to likely files/modules: src/..., app/..., services/...
|
|
70
|
+
- Name concrete validation: “Run npm test”, “Add unit tests for X”
|
|
71
|
+
- Include safe rollout when relevant: feature flag, migration plan, rollback note
|
|
72
|
+
|
|
73
|
+
Avoid:
|
|
74
|
+
- Vague steps (“handle backend”, “do auth”)
|
|
75
|
+
- Too many micro-steps
|
|
76
|
+
- Writing code snippets (keep the plan implementation-agnostic)
|
klaude_code/skill/loader.py
CHANGED
|
@@ -11,7 +11,7 @@ from contextlib import contextmanager
|
|
|
11
11
|
from importlib import resources
|
|
12
12
|
from pathlib import Path
|
|
13
13
|
|
|
14
|
-
from klaude_code.
|
|
14
|
+
from klaude_code.log import log_debug
|
|
15
15
|
|
|
16
16
|
# Marker file name for tracking installed skills version
|
|
17
17
|
SYSTEM_SKILLS_MARKER_FILENAME = ".klaude-system-skills.marker"
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"""Terminal (TUI) frontend for klaude-code.
|
|
2
|
+
|
|
3
|
+
This package contains all terminal-specific UI code (Rich rendering,
|
|
4
|
+
prompt-toolkit input, and terminal integrations).
|
|
5
|
+
|
|
6
|
+
The tui layer may depend on `klaude_code.ui`, but `klaude_code.ui` must not
|
|
7
|
+
depend on `klaude_code.tui`.
|
|
8
|
+
"""
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
from klaude_code.command.command_abc import Agent, CommandABC, CommandResult
|
|
2
1
|
from klaude_code.protocol import commands, message, op
|
|
3
2
|
|
|
3
|
+
from .command_abc import Agent, CommandABC, CommandResult
|
|
4
|
+
|
|
4
5
|
|
|
5
6
|
class ClearCommand(CommandABC):
|
|
6
7
|
"""Clear current session and start a new conversation"""
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
from klaude_code.
|
|
1
|
+
from klaude_code.log import DebugType, get_current_log_file, is_debug_enabled, set_debug_logging
|
|
2
2
|
from klaude_code.protocol import commands, events, message, model
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
from .command_abc import Agent, CommandABC, CommandResult
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
def _format_status() -> str:
|
|
@@ -72,7 +73,7 @@ class DebugCommand(CommandABC):
|
|
|
72
73
|
session_id=agent.session.id,
|
|
73
74
|
item=message.DeveloperMessage(
|
|
74
75
|
parts=message.text_parts_from_str(content),
|
|
75
|
-
|
|
76
|
+
ui_extra=model.build_command_output_extra(self.name),
|
|
76
77
|
),
|
|
77
78
|
)
|
|
78
79
|
]
|
|
@@ -2,9 +2,10 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
|
|
5
|
-
from klaude_code.command.command_abc import Agent, CommandABC, CommandResult
|
|
6
5
|
from klaude_code.protocol import commands, message, op
|
|
7
6
|
|
|
7
|
+
from .command_abc import Agent, CommandABC, CommandResult
|
|
8
|
+
|
|
8
9
|
|
|
9
10
|
class ExportCommand(CommandABC):
|
|
10
11
|
"""Export the current session into a standalone HTML transcript."""
|
|
@@ -9,10 +9,11 @@ from pathlib import Path
|
|
|
9
9
|
from rich.console import Console
|
|
10
10
|
from rich.text import Text
|
|
11
11
|
|
|
12
|
-
from klaude_code.command.command_abc import Agent, CommandABC, CommandResult
|
|
13
12
|
from klaude_code.protocol import commands, events, message, model
|
|
14
13
|
from klaude_code.session.export import build_export_html
|
|
15
14
|
|
|
15
|
+
from .command_abc import Agent, CommandABC, CommandResult
|
|
16
|
+
|
|
16
17
|
|
|
17
18
|
class ExportOnlineCommand(CommandABC):
|
|
18
19
|
"""Export and deploy the current session to surge.sh as a static webpage."""
|
|
@@ -42,7 +43,7 @@ class ExportOnlineCommand(CommandABC):
|
|
|
42
43
|
session_id=agent.session.id,
|
|
43
44
|
item=message.DeveloperMessage(
|
|
44
45
|
parts=message.text_parts_from_str("surge.sh CLI not found. Install with: npm install -g surge"),
|
|
45
|
-
|
|
46
|
+
ui_extra=model.build_command_output_extra(self.name, is_error=True),
|
|
46
47
|
),
|
|
47
48
|
)
|
|
48
49
|
return CommandResult(events=[event])
|
|
@@ -59,7 +60,7 @@ class ExportOnlineCommand(CommandABC):
|
|
|
59
60
|
session_id=agent.session.id,
|
|
60
61
|
item=message.DeveloperMessage(
|
|
61
62
|
parts=message.text_parts_from_str(f"Not logged in to surge.sh. Please run: {login_cmd}"),
|
|
62
|
-
|
|
63
|
+
ui_extra=model.build_command_output_extra(self.name, is_error=True),
|
|
63
64
|
),
|
|
64
65
|
)
|
|
65
66
|
return CommandResult(events=[event])
|
|
@@ -73,7 +74,7 @@ class ExportOnlineCommand(CommandABC):
|
|
|
73
74
|
session_id=agent.session.id,
|
|
74
75
|
item=message.DeveloperMessage(
|
|
75
76
|
parts=message.text_parts_from_str(f"Session deployed to: {url}"),
|
|
76
|
-
|
|
77
|
+
ui_extra=model.build_command_output_extra(self.name),
|
|
77
78
|
),
|
|
78
79
|
)
|
|
79
80
|
return CommandResult(events=[event])
|
|
@@ -84,7 +85,7 @@ class ExportOnlineCommand(CommandABC):
|
|
|
84
85
|
session_id=agent.session.id,
|
|
85
86
|
item=message.DeveloperMessage(
|
|
86
87
|
parts=message.text_parts_from_str(f"Failed to deploy session: {exc}\n{traceback.format_exc()}"),
|
|
87
|
-
|
|
88
|
+
ui_extra=model.build_command_output_extra(self.name, is_error=True),
|
|
88
89
|
),
|
|
89
90
|
)
|
|
90
91
|
return CommandResult(events=[event])
|