kimi-cli 0.44__tar.gz → 0.45__tar.gz
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.
Potentially problematic release.
This version of kimi-cli might be problematic. Click here for more details.
- {kimi_cli-0.44 → kimi_cli-0.45}/PKG-INFO +2 -2
- {kimi_cli-0.44 → kimi_cli-0.45}/pyproject.toml +2 -2
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/CHANGELOG.md +12 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/app.py +2 -2
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/cli.py +8 -1
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/config.py +1 -1
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/llm.py +21 -4
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/ui/shell/__init__.py +11 -2
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/ui/shell/liveview.py +36 -5
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/ui/shell/visualize.py +7 -3
- {kimi_cli-0.44 → kimi_cli-0.45}/README.md +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/__init__.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/agents/default/agent.yaml +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/agents/default/sub.yaml +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/agents/default/system.md +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/agentspec.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/constant.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/exception.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/metadata.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/prompts/__init__.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/prompts/compact.md +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/prompts/init.md +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/py.typed +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/session.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/share.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/soul/__init__.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/soul/agent.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/soul/approval.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/soul/compaction.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/soul/context.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/soul/denwarenji.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/soul/kimisoul.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/soul/message.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/soul/runtime.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/soul/toolset.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/tools/__init__.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/tools/bash/__init__.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/tools/bash/bash.md +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/tools/dmail/__init__.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/tools/dmail/dmail.md +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/tools/file/__init__.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/tools/file/glob.md +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/tools/file/glob.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/tools/file/grep.md +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/tools/file/grep.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/tools/file/patch.md +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/tools/file/patch.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/tools/file/read.md +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/tools/file/read.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/tools/file/replace.md +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/tools/file/replace.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/tools/file/write.md +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/tools/file/write.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/tools/mcp.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/tools/task/__init__.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/tools/task/task.md +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/tools/test.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/tools/think/__init__.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/tools/think/think.md +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/tools/todo/__init__.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/tools/todo/set_todo_list.md +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/tools/utils.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/tools/web/__init__.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/tools/web/fetch.md +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/tools/web/fetch.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/tools/web/search.md +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/tools/web/search.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/ui/__init__.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/ui/acp/__init__.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/ui/print/__init__.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/ui/shell/console.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/ui/shell/debug.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/ui/shell/keyboard.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/ui/shell/metacmd.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/ui/shell/prompt.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/ui/shell/replay.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/ui/shell/setup.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/ui/shell/update.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/utils/aiohttp.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/utils/changelog.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/utils/logging.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/utils/message.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/utils/path.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/utils/pyinstaller.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/utils/signals.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/utils/string.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/wire/__init__.py +0 -0
- {kimi_cli-0.44 → kimi_cli-0.45}/src/kimi_cli/wire/message.py +0 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: kimi-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.45
|
|
4
4
|
Summary: Kimi CLI is your next CLI agent.
|
|
5
5
|
Requires-Dist: agent-client-protocol==0.6.2
|
|
6
6
|
Requires-Dist: aiofiles==25.1.0
|
|
7
7
|
Requires-Dist: aiohttp==3.13.2
|
|
8
8
|
Requires-Dist: click==8.3.0
|
|
9
|
-
Requires-Dist: kosong==0.16.
|
|
9
|
+
Requires-Dist: kosong==0.16.2
|
|
10
10
|
Requires-Dist: loguru==0.7.3
|
|
11
11
|
Requires-Dist: patch-ng==1.19.0
|
|
12
12
|
Requires-Dist: prompt-toolkit==3.0.52
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "kimi-cli"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.45"
|
|
4
4
|
description = "Kimi CLI is your next CLI agent."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.13"
|
|
@@ -9,7 +9,7 @@ dependencies = [
|
|
|
9
9
|
"aiofiles==25.1.0",
|
|
10
10
|
"aiohttp==3.13.2",
|
|
11
11
|
"click==8.3.0",
|
|
12
|
-
"kosong==0.16.
|
|
12
|
+
"kosong==0.16.2",
|
|
13
13
|
"loguru==0.7.3",
|
|
14
14
|
"patch-ng==1.19.0",
|
|
15
15
|
"prompt-toolkit==3.0.52",
|
|
@@ -9,6 +9,18 @@ Internal builds may append content to the Unreleased section.
|
|
|
9
9
|
Only write entries that are worth mentioning to users.
|
|
10
10
|
-->
|
|
11
11
|
|
|
12
|
+
## [0.45] - 2025-10-31
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- Allow `KIMI_MODEL_CAPABILITIES` environment variable to override model capabilities
|
|
17
|
+
- Add `--no-markdown` option to disable markdown rendering
|
|
18
|
+
- Support `openai_responses` LLM provider type
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- Fix crash when continuing a session
|
|
23
|
+
|
|
12
24
|
## [0.44] - 2025-10-30
|
|
13
25
|
|
|
14
26
|
### Changed
|
|
@@ -127,7 +127,7 @@ class KimiCLI:
|
|
|
127
127
|
finally:
|
|
128
128
|
os.chdir(original_cwd)
|
|
129
129
|
|
|
130
|
-
async def run_shell_mode(self, command: str | None = None) -> bool:
|
|
130
|
+
async def run_shell_mode(self, command: str | None = None, markdown: bool = True) -> bool:
|
|
131
131
|
from kimi_cli.ui.shell import ShellApp, WelcomeInfoItem
|
|
132
132
|
|
|
133
133
|
welcome_info = [
|
|
@@ -167,7 +167,7 @@ class KimiCLI:
|
|
|
167
167
|
)
|
|
168
168
|
)
|
|
169
169
|
with self._app_env():
|
|
170
|
-
app = ShellApp(self._soul, welcome_info=welcome_info)
|
|
170
|
+
app = ShellApp(self._soul, welcome_info=welcome_info, markdown=markdown)
|
|
171
171
|
return await app.run(command)
|
|
172
172
|
|
|
173
173
|
async def run_print_mode(
|
|
@@ -137,6 +137,12 @@ OutputFormat = Literal["text", "stream-json"]
|
|
|
137
137
|
default=False,
|
|
138
138
|
help="Automatically approve all actions. Default: no.",
|
|
139
139
|
)
|
|
140
|
+
@click.option(
|
|
141
|
+
"--markdown/--no-markdown",
|
|
142
|
+
is_flag=True,
|
|
143
|
+
default=True,
|
|
144
|
+
help="Enable/disable markdown rendering in shell UI. Default: yes.",
|
|
145
|
+
)
|
|
140
146
|
def kimi(
|
|
141
147
|
verbose: bool,
|
|
142
148
|
debug: bool,
|
|
@@ -151,6 +157,7 @@ def kimi(
|
|
|
151
157
|
mcp_config_file: list[Path],
|
|
152
158
|
mcp_config: list[str],
|
|
153
159
|
yolo: bool,
|
|
160
|
+
markdown: bool,
|
|
154
161
|
):
|
|
155
162
|
"""Kimi, your next CLI agent."""
|
|
156
163
|
from kimi_cli.app import KimiCLI
|
|
@@ -220,7 +227,7 @@ def kimi(
|
|
|
220
227
|
)
|
|
221
228
|
match ui:
|
|
222
229
|
case "shell":
|
|
223
|
-
return await instance.run_shell_mode(command)
|
|
230
|
+
return await instance.run_shell_mode(command, markdown=markdown)
|
|
224
231
|
case "print":
|
|
225
232
|
return await instance.run_print_mode(
|
|
226
233
|
input_format or "text",
|
|
@@ -12,7 +12,7 @@ from kimi_cli.utils.logging import logger
|
|
|
12
12
|
class LLMProvider(BaseModel):
|
|
13
13
|
"""LLM provider configuration."""
|
|
14
14
|
|
|
15
|
-
type: Literal["kimi", "openai_legacy", "_chaos"]
|
|
15
|
+
type: Literal["kimi", "openai_legacy", "openai_responses", "_chaos"]
|
|
16
16
|
"""Provider type"""
|
|
17
17
|
base_url: str
|
|
18
18
|
"""API base URL"""
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import os
|
|
2
|
-
from typing import NamedTuple
|
|
2
|
+
from typing import NamedTuple, cast, get_args
|
|
3
3
|
|
|
4
4
|
from kosong.base.chat_provider import ChatProvider
|
|
5
5
|
from pydantic import SecretStr
|
|
@@ -41,11 +41,19 @@ def augment_provider_with_env_vars(provider: LLMProvider, model: LLMModel) -> di
|
|
|
41
41
|
applied["KIMI_API_KEY"] = "******"
|
|
42
42
|
if model_name := os.getenv("KIMI_MODEL_NAME"):
|
|
43
43
|
model.model = model_name
|
|
44
|
-
applied["KIMI_MODEL_NAME"] =
|
|
44
|
+
applied["KIMI_MODEL_NAME"] = model_name
|
|
45
45
|
if max_context_size := os.getenv("KIMI_MODEL_MAX_CONTEXT_SIZE"):
|
|
46
46
|
model.max_context_size = int(max_context_size)
|
|
47
|
-
applied["KIMI_MODEL_MAX_CONTEXT_SIZE"] =
|
|
48
|
-
|
|
47
|
+
applied["KIMI_MODEL_MAX_CONTEXT_SIZE"] = max_context_size
|
|
48
|
+
if capabilities := os.getenv("KIMI_MODEL_CAPABILITIES"):
|
|
49
|
+
caps_lower = (cap.strip().lower() for cap in capabilities.split(",") if cap.strip())
|
|
50
|
+
model.capabilities = set(
|
|
51
|
+
cast(LLMModelCapability, cap)
|
|
52
|
+
for cap in caps_lower
|
|
53
|
+
if cap in get_args(LLMModelCapability)
|
|
54
|
+
)
|
|
55
|
+
applied["KIMI_MODEL_CAPABILITIES"] = capabilities
|
|
56
|
+
case "openai_legacy" | "openai_responses":
|
|
49
57
|
if base_url := os.getenv("OPENAI_BASE_URL"):
|
|
50
58
|
provider.base_url = base_url
|
|
51
59
|
if api_key := os.getenv("OPENAI_API_KEY"):
|
|
@@ -88,6 +96,15 @@ def create_llm(
|
|
|
88
96
|
api_key=provider.api_key.get_secret_value(),
|
|
89
97
|
stream=stream,
|
|
90
98
|
)
|
|
99
|
+
case "openai_responses":
|
|
100
|
+
from kosong.chat_provider.openai_responses import OpenAIResponses
|
|
101
|
+
|
|
102
|
+
chat_provider = OpenAIResponses(
|
|
103
|
+
model=model.model,
|
|
104
|
+
base_url=provider.base_url,
|
|
105
|
+
api_key=provider.api_key.get_secret_value(),
|
|
106
|
+
stream=stream,
|
|
107
|
+
)
|
|
91
108
|
case "_chaos":
|
|
92
109
|
from kosong.chat_provider.chaos import ChaosChatProvider, ChaosConfig
|
|
93
110
|
|
|
@@ -24,10 +24,16 @@ from kimi_cli.utils.signals import install_sigint_handler
|
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
class ShellApp:
|
|
27
|
-
def __init__(
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
soul: Soul,
|
|
30
|
+
welcome_info: list["WelcomeInfoItem"] | None = None,
|
|
31
|
+
markdown: bool = True,
|
|
32
|
+
):
|
|
28
33
|
self.soul = soul
|
|
29
34
|
self._welcome_info = list(welcome_info or [])
|
|
30
35
|
self._background_tasks: set[asyncio.Task[Any]] = set()
|
|
36
|
+
self._markdown = markdown
|
|
31
37
|
|
|
32
38
|
async def run(self, command: str | None = None) -> bool:
|
|
33
39
|
if command is not None:
|
|
@@ -168,7 +174,10 @@ class ShellApp:
|
|
|
168
174
|
self.soul,
|
|
169
175
|
user_input,
|
|
170
176
|
lambda wire: visualize(
|
|
171
|
-
wire,
|
|
177
|
+
wire,
|
|
178
|
+
initial_status=self.soul.status,
|
|
179
|
+
cancel_event=cancel_event,
|
|
180
|
+
markdown=self._markdown,
|
|
172
181
|
),
|
|
173
182
|
cancel_event,
|
|
174
183
|
)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
from collections import deque
|
|
3
|
+
from typing import Literal
|
|
3
4
|
|
|
4
5
|
import streamingjson
|
|
5
6
|
from kosong.base.message import ToolCall, ToolCallPart
|
|
@@ -129,6 +130,7 @@ class StepLiveView:
|
|
|
129
130
|
def __init__(self, status: StatusSnapshot, cancel_event: asyncio.Event | None = None):
|
|
130
131
|
# message content
|
|
131
132
|
self._line_buffer = Text("")
|
|
133
|
+
self._last_text_mode: Literal["text", "think", ""] = ""
|
|
132
134
|
|
|
133
135
|
# tool call
|
|
134
136
|
self._tool_calls: dict[str, _ToolCallDisplay] = {}
|
|
@@ -187,7 +189,21 @@ class StepLiveView:
|
|
|
187
189
|
"""
|
|
188
190
|
console.print(renderable)
|
|
189
191
|
|
|
190
|
-
def append_text(self, text: str):
|
|
192
|
+
def append_text(self, text: str, mode: Literal["text", "think"] = "text"):
|
|
193
|
+
if not text:
|
|
194
|
+
# Ignore empty message
|
|
195
|
+
return
|
|
196
|
+
if self._last_text_mode != mode:
|
|
197
|
+
if self._line_buffer:
|
|
198
|
+
self._push_out(self._line_buffer)
|
|
199
|
+
self._push_out("") # Add extra line between different modes
|
|
200
|
+
self._line_buffer.plain = ""
|
|
201
|
+
self._last_text_mode = mode
|
|
202
|
+
match mode:
|
|
203
|
+
case "text":
|
|
204
|
+
self._line_buffer.style = ""
|
|
205
|
+
case "think":
|
|
206
|
+
self._line_buffer.style = "grey50 italic"
|
|
191
207
|
lines = text.split("\n")
|
|
192
208
|
prev_is_empty = not self._line_buffer
|
|
193
209
|
for line in lines[:-1]:
|
|
@@ -313,7 +329,14 @@ class StepLiveViewWithMarkdown(StepLiveView):
|
|
|
313
329
|
self._buffer_status_active = False
|
|
314
330
|
self._buffer_status_obj: Status | None = None
|
|
315
331
|
|
|
316
|
-
def append_text(self, text: str):
|
|
332
|
+
def append_text(self, text: str, mode: Literal["text", "think"] = "text"):
|
|
333
|
+
if not text:
|
|
334
|
+
# Ignore empty message
|
|
335
|
+
return
|
|
336
|
+
if self._last_text_mode != mode:
|
|
337
|
+
if self._flush_markdown():
|
|
338
|
+
self._push_out("") # Add extra line between different modes
|
|
339
|
+
self._last_text_mode = mode
|
|
317
340
|
if not self._pending_markdown_parts:
|
|
318
341
|
self._show_thinking_status()
|
|
319
342
|
self._pending_markdown_parts.append(text)
|
|
@@ -334,14 +357,22 @@ class StepLiveViewWithMarkdown(StepLiveView):
|
|
|
334
357
|
self._flush_markdown()
|
|
335
358
|
return super().__exit__(exc_type, exc_value, traceback)
|
|
336
359
|
|
|
337
|
-
def _flush_markdown(self):
|
|
360
|
+
def _flush_markdown(self) -> bool:
|
|
338
361
|
self._hide_thinking_status()
|
|
339
362
|
if not self._pending_markdown_parts:
|
|
340
|
-
return
|
|
363
|
+
return False
|
|
341
364
|
markdown_text = "".join(self._pending_markdown_parts)
|
|
342
365
|
self._pending_markdown_parts.clear()
|
|
343
366
|
if markdown_text.strip():
|
|
344
|
-
self._push_out(
|
|
367
|
+
self._push_out(
|
|
368
|
+
_LeftAlignedMarkdown(
|
|
369
|
+
markdown_text,
|
|
370
|
+
justify="left",
|
|
371
|
+
style="grey50 italic" if self._last_text_mode == "think" else "none",
|
|
372
|
+
)
|
|
373
|
+
)
|
|
374
|
+
return True
|
|
375
|
+
return False
|
|
345
376
|
|
|
346
377
|
def _show_thinking_status(self):
|
|
347
378
|
if self._buffer_status_active:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
from contextlib import asynccontextmanager, suppress
|
|
3
3
|
|
|
4
|
-
from kosong.base.message import ContentPart, TextPart, ToolCall, ToolCallPart
|
|
4
|
+
from kosong.base.message import ContentPart, TextPart, ThinkPart, ToolCall, ToolCallPart
|
|
5
5
|
from kosong.tooling import ToolResult
|
|
6
6
|
|
|
7
7
|
from kimi_cli.soul import StatusSnapshot
|
|
@@ -42,6 +42,7 @@ async def visualize(
|
|
|
42
42
|
*,
|
|
43
43
|
initial_status: StatusSnapshot,
|
|
44
44
|
cancel_event: asyncio.Event | None = None,
|
|
45
|
+
markdown: bool = True,
|
|
45
46
|
):
|
|
46
47
|
"""
|
|
47
48
|
A loop to consume agent events and visualize the agent behavior.
|
|
@@ -60,7 +61,8 @@ async def visualize(
|
|
|
60
61
|
while True:
|
|
61
62
|
# TODO: Maybe we can always have a StepLiveView here.
|
|
62
63
|
# No need to recreate for each step.
|
|
63
|
-
|
|
64
|
+
LiveView = StepLiveViewWithMarkdown if markdown else StepLiveView
|
|
65
|
+
with LiveView(latest_status, cancel_event) as step:
|
|
64
66
|
async with _keyboard_listener(step):
|
|
65
67
|
# spin the moon at the beginning of each step
|
|
66
68
|
with console.status("", spinner="moon"):
|
|
@@ -78,7 +80,9 @@ async def visualize(
|
|
|
78
80
|
while True:
|
|
79
81
|
match msg:
|
|
80
82
|
case TextPart(text=text):
|
|
81
|
-
step.append_text(text)
|
|
83
|
+
step.append_text(text, mode="text")
|
|
84
|
+
case ThinkPart(think=think):
|
|
85
|
+
step.append_text(think, mode="think")
|
|
82
86
|
case ContentPart():
|
|
83
87
|
# TODO: support more content parts
|
|
84
88
|
step.append_text(f"[{msg.__class__.__name__}]")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|