kimi-cli 0.35__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.
Potentially problematic release.
This version of kimi-cli might be problematic. Click here for more details.
- kimi_cli/CHANGELOG.md +304 -0
- kimi_cli/__init__.py +374 -0
- kimi_cli/agent.py +261 -0
- kimi_cli/agents/koder/README.md +3 -0
- kimi_cli/agents/koder/agent.yaml +24 -0
- kimi_cli/agents/koder/sub.yaml +11 -0
- kimi_cli/agents/koder/system.md +72 -0
- kimi_cli/config.py +138 -0
- kimi_cli/llm.py +8 -0
- kimi_cli/metadata.py +117 -0
- kimi_cli/prompts/metacmds/__init__.py +4 -0
- kimi_cli/prompts/metacmds/compact.md +74 -0
- kimi_cli/prompts/metacmds/init.md +21 -0
- kimi_cli/py.typed +0 -0
- kimi_cli/share.py +8 -0
- kimi_cli/soul/__init__.py +59 -0
- kimi_cli/soul/approval.py +69 -0
- kimi_cli/soul/context.py +142 -0
- kimi_cli/soul/denwarenji.py +37 -0
- kimi_cli/soul/kimisoul.py +248 -0
- kimi_cli/soul/message.py +76 -0
- kimi_cli/soul/toolset.py +25 -0
- kimi_cli/soul/wire.py +101 -0
- kimi_cli/tools/__init__.py +85 -0
- kimi_cli/tools/bash/__init__.py +97 -0
- kimi_cli/tools/bash/bash.md +31 -0
- kimi_cli/tools/dmail/__init__.py +38 -0
- kimi_cli/tools/dmail/dmail.md +15 -0
- kimi_cli/tools/file/__init__.py +21 -0
- kimi_cli/tools/file/glob.md +17 -0
- kimi_cli/tools/file/glob.py +149 -0
- kimi_cli/tools/file/grep.md +5 -0
- kimi_cli/tools/file/grep.py +285 -0
- kimi_cli/tools/file/patch.md +8 -0
- kimi_cli/tools/file/patch.py +131 -0
- kimi_cli/tools/file/read.md +14 -0
- kimi_cli/tools/file/read.py +139 -0
- kimi_cli/tools/file/replace.md +7 -0
- kimi_cli/tools/file/replace.py +132 -0
- kimi_cli/tools/file/write.md +5 -0
- kimi_cli/tools/file/write.py +107 -0
- kimi_cli/tools/mcp.py +85 -0
- kimi_cli/tools/task/__init__.py +156 -0
- kimi_cli/tools/task/task.md +26 -0
- kimi_cli/tools/test.py +55 -0
- kimi_cli/tools/think/__init__.py +21 -0
- kimi_cli/tools/think/think.md +1 -0
- kimi_cli/tools/todo/__init__.py +27 -0
- kimi_cli/tools/todo/set_todo_list.md +15 -0
- kimi_cli/tools/utils.py +150 -0
- kimi_cli/tools/web/__init__.py +4 -0
- kimi_cli/tools/web/fetch.md +1 -0
- kimi_cli/tools/web/fetch.py +94 -0
- kimi_cli/tools/web/search.md +1 -0
- kimi_cli/tools/web/search.py +126 -0
- kimi_cli/ui/__init__.py +68 -0
- kimi_cli/ui/acp/__init__.py +441 -0
- kimi_cli/ui/print/__init__.py +176 -0
- kimi_cli/ui/shell/__init__.py +326 -0
- kimi_cli/ui/shell/console.py +3 -0
- kimi_cli/ui/shell/liveview.py +158 -0
- kimi_cli/ui/shell/metacmd.py +309 -0
- kimi_cli/ui/shell/prompt.py +574 -0
- kimi_cli/ui/shell/setup.py +192 -0
- kimi_cli/ui/shell/update.py +204 -0
- kimi_cli/utils/changelog.py +101 -0
- kimi_cli/utils/logging.py +18 -0
- kimi_cli/utils/message.py +8 -0
- kimi_cli/utils/path.py +23 -0
- kimi_cli/utils/provider.py +64 -0
- kimi_cli/utils/pyinstaller.py +24 -0
- kimi_cli/utils/string.py +12 -0
- kimi_cli-0.35.dist-info/METADATA +24 -0
- kimi_cli-0.35.dist-info/RECORD +76 -0
- kimi_cli-0.35.dist-info/WHEEL +4 -0
- kimi_cli-0.35.dist-info/entry_points.txt +3 -0
kimi_cli/CHANGELOG.md
ADDED
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
<!--
|
|
4
|
+
Release notes will be parsed and available as /release-notes
|
|
5
|
+
The parser extracts for each version:
|
|
6
|
+
- a short description (first paragraph after the version header)
|
|
7
|
+
- bullet entries beginning with "- " under that version (across any subsections)
|
|
8
|
+
Internal builds may append content to the Unreleased section.
|
|
9
|
+
Only write entries that are worth mentioning to users.
|
|
10
|
+
-->
|
|
11
|
+
|
|
12
|
+
## [0.35] - 2025-10-22
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- Minor UI improvements
|
|
17
|
+
- Auto download ripgrep if not found in the system
|
|
18
|
+
- Always approve tool calls in `--print` mode
|
|
19
|
+
- Add `/feedback` meta command
|
|
20
|
+
|
|
21
|
+
## [0.34] - 2025-10-21
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- Add `/update` meta command to check for updates and auto-update in background
|
|
26
|
+
- Support running interactive shell commands in raw shell mode
|
|
27
|
+
- Add `/setup` meta command to setup LLM provider and model
|
|
28
|
+
- Add `/reload` meta command to reload configuration
|
|
29
|
+
|
|
30
|
+
## [0.33] - 2025-10-18
|
|
31
|
+
|
|
32
|
+
### Added
|
|
33
|
+
|
|
34
|
+
- Add `/version` meta command
|
|
35
|
+
- Add raw shell mode, which can be switched to by Ctrl-K
|
|
36
|
+
- Show shortcuts in bottom status line
|
|
37
|
+
|
|
38
|
+
### Fixed
|
|
39
|
+
|
|
40
|
+
- Fix logging redirection
|
|
41
|
+
- Merge duplicated input histories
|
|
42
|
+
|
|
43
|
+
## [0.32] - 2025-10-16
|
|
44
|
+
|
|
45
|
+
### Added
|
|
46
|
+
|
|
47
|
+
- Add bottom status line
|
|
48
|
+
- Support file path auto-completion (`@filepath`)
|
|
49
|
+
|
|
50
|
+
### Fixed
|
|
51
|
+
|
|
52
|
+
- Do not auto-complete meta command in the middle of user input
|
|
53
|
+
|
|
54
|
+
## [0.31] - 2025-10-14
|
|
55
|
+
|
|
56
|
+
### Fixed
|
|
57
|
+
|
|
58
|
+
- Fix step interrupting by Ctrl-C, for real
|
|
59
|
+
|
|
60
|
+
## [0.30] - 2025-10-14
|
|
61
|
+
|
|
62
|
+
### Added
|
|
63
|
+
|
|
64
|
+
- Add `/compact` meta command to allow manually compacting context
|
|
65
|
+
|
|
66
|
+
### Fixed
|
|
67
|
+
|
|
68
|
+
- Fix `/clear` meta command when context is empty
|
|
69
|
+
|
|
70
|
+
## [0.29] - 2025-10-14
|
|
71
|
+
|
|
72
|
+
### Added
|
|
73
|
+
|
|
74
|
+
- Support Enter key to accept completion in shell mode
|
|
75
|
+
- Remember user input history across sessions in shell mode
|
|
76
|
+
- Add `/reset` meta command as an alias for `/clear`
|
|
77
|
+
|
|
78
|
+
### Fixed
|
|
79
|
+
|
|
80
|
+
- Fix step interrupting by Ctrl-C
|
|
81
|
+
|
|
82
|
+
### Changed
|
|
83
|
+
|
|
84
|
+
- Disable `SendDMail` tool in Kimi Koder agent
|
|
85
|
+
|
|
86
|
+
## [0.28] - 2025-10-13
|
|
87
|
+
|
|
88
|
+
### Added
|
|
89
|
+
|
|
90
|
+
- Add `/init` meta command to analyze the codebase and generate an `AGENTS.md` file
|
|
91
|
+
- Add `/clear` meta command to clear the context
|
|
92
|
+
|
|
93
|
+
### Fixed
|
|
94
|
+
|
|
95
|
+
- Fix `ReadFile` output
|
|
96
|
+
|
|
97
|
+
## [0.27] - 2025-10-11
|
|
98
|
+
|
|
99
|
+
### Added
|
|
100
|
+
|
|
101
|
+
- Add `--mcp-config-file` and `--mcp-config` options to load MCP configs
|
|
102
|
+
|
|
103
|
+
### Changed
|
|
104
|
+
|
|
105
|
+
- Rename `--agent` option to `--agent-file`
|
|
106
|
+
|
|
107
|
+
## [0.26] - 2025-10-11
|
|
108
|
+
|
|
109
|
+
### Fixed
|
|
110
|
+
|
|
111
|
+
- Fix possible encoding error in `--output-format stream-json` mode
|
|
112
|
+
|
|
113
|
+
## [0.25] - 2025-10-11
|
|
114
|
+
|
|
115
|
+
### Changed
|
|
116
|
+
|
|
117
|
+
- Rename package name `ensoul` to `kimi-cli`
|
|
118
|
+
- Rename `ENSOUL_*` builtin system prompt arguments to `KIMI_*`
|
|
119
|
+
- Further decouple `App` with `Soul`
|
|
120
|
+
- Split `Soul` protocol and `KimiSoul` implementation for better modularity
|
|
121
|
+
|
|
122
|
+
## [0.24] - 2025-10-10
|
|
123
|
+
|
|
124
|
+
### Fixed
|
|
125
|
+
|
|
126
|
+
- Fix ACP `cancel` method
|
|
127
|
+
|
|
128
|
+
## [0.23] - 2025-10-09
|
|
129
|
+
|
|
130
|
+
### Added
|
|
131
|
+
|
|
132
|
+
- Add `extend` field to agent file to support agent file extension
|
|
133
|
+
- Add `exclude_tools` field to agent file to support excluding tools
|
|
134
|
+
- Add `subagents` field to agent file to support defining subagents
|
|
135
|
+
|
|
136
|
+
## [0.22] - 2025-10-09
|
|
137
|
+
|
|
138
|
+
### Changed
|
|
139
|
+
|
|
140
|
+
- Improve `SearchWeb` and `FetchURL` tool call visualization
|
|
141
|
+
- Improve search result output format
|
|
142
|
+
|
|
143
|
+
## [0.21] - 2025-10-09
|
|
144
|
+
|
|
145
|
+
### Added
|
|
146
|
+
|
|
147
|
+
- Add `--print` option as a shortcut for `--ui print`, `--acp` option as a shortcut for `--ui acp`
|
|
148
|
+
- Support `--output-format stream-json` to print output in JSON format
|
|
149
|
+
- Add `SearchWeb` tool with `services.moonshot_search` configuration. You need to configure it with `"services": {"moonshot_search": {"api_key": "your-search-api-key"}}` in your config file.
|
|
150
|
+
- Add `FetchURL` tool
|
|
151
|
+
- Add `Think` tool
|
|
152
|
+
- Add `PatchFile` tool, not enabled in Kimi Koder agent
|
|
153
|
+
- Enable `SendDMail` and `Task` tool in Kimi Koder agent with better tool prompts
|
|
154
|
+
- Add `ENSOUL_NOW` builtin system prompt argument
|
|
155
|
+
|
|
156
|
+
### Changed
|
|
157
|
+
|
|
158
|
+
- Better-looking `/release-notes`
|
|
159
|
+
- Improve tool descriptions
|
|
160
|
+
- Improve tool output truncation
|
|
161
|
+
|
|
162
|
+
## [0.20] - 2025-09-30
|
|
163
|
+
|
|
164
|
+
### Added
|
|
165
|
+
|
|
166
|
+
- Add `--ui acp` option to start Agent Client Protocol (ACP) server
|
|
167
|
+
|
|
168
|
+
## [0.19] - 2025-09-29
|
|
169
|
+
|
|
170
|
+
### Added
|
|
171
|
+
|
|
172
|
+
- Support piped stdin for print UI
|
|
173
|
+
- Support `--input-format=stream-json` for piped JSON input
|
|
174
|
+
|
|
175
|
+
### Fixed
|
|
176
|
+
|
|
177
|
+
- Do not include `CHECKPOINT` messages in the context when `SendDMail` is not enabled
|
|
178
|
+
|
|
179
|
+
## [0.18] - 2025-09-29
|
|
180
|
+
|
|
181
|
+
### Added
|
|
182
|
+
|
|
183
|
+
- Support `max_context_size` in LLM model configurations to configure the maximum context size (in tokens)
|
|
184
|
+
|
|
185
|
+
### Improved
|
|
186
|
+
|
|
187
|
+
- Improve `ReadFile` tool description
|
|
188
|
+
|
|
189
|
+
## [0.17] - 2025-09-29
|
|
190
|
+
|
|
191
|
+
### Fixed
|
|
192
|
+
|
|
193
|
+
- Fix step count in error message when exceeded max steps
|
|
194
|
+
- Fix history file assertion error in `kimi_run`
|
|
195
|
+
- Fix error handling in print mode and single command shell mode
|
|
196
|
+
- Add retry for LLM API connection errors and timeout errors
|
|
197
|
+
|
|
198
|
+
### Changed
|
|
199
|
+
|
|
200
|
+
- Increase default max-steps-per-run to 100
|
|
201
|
+
|
|
202
|
+
## [0.16.0] - 2025-09-26
|
|
203
|
+
|
|
204
|
+
### Tools
|
|
205
|
+
|
|
206
|
+
- Add `SendDMail` tool (disabled in Kimi Koder, can be enabled in custom agent)
|
|
207
|
+
|
|
208
|
+
### SDK
|
|
209
|
+
|
|
210
|
+
- Session history file can be specified via `_history_file` parameter when creating a new session
|
|
211
|
+
|
|
212
|
+
## [0.15.0] - 2025-09-26
|
|
213
|
+
|
|
214
|
+
- Improve tool robustness
|
|
215
|
+
|
|
216
|
+
## [0.14.0] - 2025-09-25
|
|
217
|
+
|
|
218
|
+
### Added
|
|
219
|
+
|
|
220
|
+
- Add `StrReplaceFile` tool
|
|
221
|
+
|
|
222
|
+
### Improved
|
|
223
|
+
|
|
224
|
+
- Emphasize the use of the same language as the user
|
|
225
|
+
|
|
226
|
+
## [0.13.0] - 2025-09-25
|
|
227
|
+
|
|
228
|
+
### Added
|
|
229
|
+
|
|
230
|
+
- Add `SetTodoList` tool
|
|
231
|
+
- Add `User-Agent` in LLM API calls
|
|
232
|
+
|
|
233
|
+
### Improved
|
|
234
|
+
|
|
235
|
+
- Better system prompt and tool description
|
|
236
|
+
- Better error messages for LLM
|
|
237
|
+
|
|
238
|
+
## [0.12.0] - 2025-09-24
|
|
239
|
+
|
|
240
|
+
### Added
|
|
241
|
+
|
|
242
|
+
- Add `print` UI mode, which can be used via `--ui print` option
|
|
243
|
+
- Add logging and `--debug` option
|
|
244
|
+
|
|
245
|
+
### Changed
|
|
246
|
+
|
|
247
|
+
- Catch EOF error for better experience
|
|
248
|
+
|
|
249
|
+
## [0.11.1] - 2025-09-22
|
|
250
|
+
|
|
251
|
+
### Changed
|
|
252
|
+
|
|
253
|
+
- Rename `max_retry_per_step` to `max_retries_per_step`
|
|
254
|
+
|
|
255
|
+
## [0.11.0] - 2025-09-22
|
|
256
|
+
|
|
257
|
+
### Added
|
|
258
|
+
|
|
259
|
+
- Add `/release-notes` command
|
|
260
|
+
- Add retry for LLM API errors
|
|
261
|
+
- Add loop control configuration, e.g. `{"loop_control": {"max_steps_per_run": 50, "max_retry_per_step": 3}}`
|
|
262
|
+
|
|
263
|
+
### Changed
|
|
264
|
+
|
|
265
|
+
- Better extreme cases handling in `read_file` tool
|
|
266
|
+
- Prevent Ctrl-C from exiting the CLI, force the use of Ctrl-D or `exit` instead
|
|
267
|
+
|
|
268
|
+
## [0.10.1] - 2025-09-18
|
|
269
|
+
|
|
270
|
+
- Make slash commands look slightly better
|
|
271
|
+
- Improve `glob` tool
|
|
272
|
+
|
|
273
|
+
## [0.10.0] - 2025-09-17
|
|
274
|
+
|
|
275
|
+
### Added
|
|
276
|
+
|
|
277
|
+
- Add `read_file` tool
|
|
278
|
+
- Add `write_file` tool
|
|
279
|
+
- Add `glob` tool
|
|
280
|
+
- Add `task` tool
|
|
281
|
+
|
|
282
|
+
### Changed
|
|
283
|
+
|
|
284
|
+
- Improve tool call visualization
|
|
285
|
+
- Improve session management
|
|
286
|
+
- Restore context usage when `--continue` a session
|
|
287
|
+
|
|
288
|
+
## [0.9.0] - 2025-09-15
|
|
289
|
+
|
|
290
|
+
- Remove `--session` and `--continue` options
|
|
291
|
+
|
|
292
|
+
## [0.8.1] - 2025-09-14
|
|
293
|
+
|
|
294
|
+
- Fix config model dumping
|
|
295
|
+
|
|
296
|
+
## [0.8.0] - 2025-09-14
|
|
297
|
+
|
|
298
|
+
- Add `shell` tool and basic system prompt
|
|
299
|
+
- Add tool call visualization
|
|
300
|
+
- Add context usage count
|
|
301
|
+
- Support interrupting the agent loop
|
|
302
|
+
- Support project-level `AGENTS.md`
|
|
303
|
+
- Support custom agent defined with YAML
|
|
304
|
+
- Support oneshot task via `kimi -c`
|
kimi_cli/__init__.py
ADDED
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import contextlib
|
|
3
|
+
import importlib.metadata
|
|
4
|
+
import json
|
|
5
|
+
import os
|
|
6
|
+
import subprocess
|
|
7
|
+
import sys
|
|
8
|
+
import textwrap
|
|
9
|
+
import warnings
|
|
10
|
+
from datetime import datetime
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from typing import Any, Literal
|
|
13
|
+
|
|
14
|
+
import click
|
|
15
|
+
from pydantic import SecretStr
|
|
16
|
+
|
|
17
|
+
from kimi_cli.agent import (
|
|
18
|
+
DEFAULT_AGENT_FILE,
|
|
19
|
+
AgentGlobals,
|
|
20
|
+
BuiltinSystemPromptArgs,
|
|
21
|
+
load_agent_with_mcp,
|
|
22
|
+
load_agents_md,
|
|
23
|
+
)
|
|
24
|
+
from kimi_cli.config import (
|
|
25
|
+
Config,
|
|
26
|
+
ConfigError,
|
|
27
|
+
LLMModel,
|
|
28
|
+
LLMProvider,
|
|
29
|
+
load_config,
|
|
30
|
+
)
|
|
31
|
+
from kimi_cli.metadata import Session, continue_session, new_session
|
|
32
|
+
from kimi_cli.share import get_share_dir
|
|
33
|
+
from kimi_cli.soul.approval import Approval
|
|
34
|
+
from kimi_cli.soul.context import Context
|
|
35
|
+
from kimi_cli.soul.denwarenji import DenwaRenji
|
|
36
|
+
from kimi_cli.soul.kimisoul import KimiSoul
|
|
37
|
+
from kimi_cli.ui.acp import ACPServer
|
|
38
|
+
from kimi_cli.ui.print import InputFormat, OutputFormat, PrintApp
|
|
39
|
+
from kimi_cli.ui.shell import Reload, ShellApp
|
|
40
|
+
from kimi_cli.utils.logging import StreamToLogger, logger
|
|
41
|
+
from kimi_cli.utils.provider import augment_provider_with_env_vars, create_llm
|
|
42
|
+
|
|
43
|
+
__version__ = importlib.metadata.version("kimi-cli")
|
|
44
|
+
USER_AGENT = f"KimiCLI/{__version__}"
|
|
45
|
+
|
|
46
|
+
UIMode = Literal["shell", "print", "acp"]
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@click.command(context_settings=dict(help_option_names=["-h", "--help"]))
|
|
50
|
+
@click.version_option(__version__)
|
|
51
|
+
@click.option(
|
|
52
|
+
"--verbose",
|
|
53
|
+
is_flag=True,
|
|
54
|
+
default=False,
|
|
55
|
+
help="Print verbose information. Default: no.",
|
|
56
|
+
)
|
|
57
|
+
@click.option(
|
|
58
|
+
"--debug",
|
|
59
|
+
is_flag=True,
|
|
60
|
+
default=False,
|
|
61
|
+
help="Log debug information. Default: no.",
|
|
62
|
+
)
|
|
63
|
+
@click.option(
|
|
64
|
+
"--agent-file",
|
|
65
|
+
type=click.Path(exists=True, file_okay=True, dir_okay=False, path_type=Path),
|
|
66
|
+
default=DEFAULT_AGENT_FILE,
|
|
67
|
+
help="Custom agent specification file. Default: builtin Kimi Koder.",
|
|
68
|
+
)
|
|
69
|
+
@click.option(
|
|
70
|
+
"--model",
|
|
71
|
+
"-m",
|
|
72
|
+
"model_name",
|
|
73
|
+
type=str,
|
|
74
|
+
default=None,
|
|
75
|
+
help="LLM model to use. Default: default model set in config file.",
|
|
76
|
+
)
|
|
77
|
+
@click.option(
|
|
78
|
+
"--work-dir",
|
|
79
|
+
"-w",
|
|
80
|
+
type=click.Path(exists=True, file_okay=False, dir_okay=True, path_type=Path),
|
|
81
|
+
default=Path.cwd(),
|
|
82
|
+
help="Working directory for the agent. Default: current directory.",
|
|
83
|
+
)
|
|
84
|
+
@click.option(
|
|
85
|
+
"--continue",
|
|
86
|
+
"-C",
|
|
87
|
+
"continue_",
|
|
88
|
+
is_flag=True,
|
|
89
|
+
default=False,
|
|
90
|
+
help="Continue the previous session for the working directory. Default: no.",
|
|
91
|
+
)
|
|
92
|
+
@click.option(
|
|
93
|
+
"--command",
|
|
94
|
+
"-c",
|
|
95
|
+
"--query",
|
|
96
|
+
"-q",
|
|
97
|
+
"command",
|
|
98
|
+
type=str,
|
|
99
|
+
default=None,
|
|
100
|
+
help="User query to the agent. Default: prompt interactively.",
|
|
101
|
+
)
|
|
102
|
+
@click.option(
|
|
103
|
+
"--ui",
|
|
104
|
+
"ui",
|
|
105
|
+
type=click.Choice(["shell", "print", "acp"]),
|
|
106
|
+
default="shell",
|
|
107
|
+
help="UI mode to use. Default: shell.",
|
|
108
|
+
)
|
|
109
|
+
@click.option(
|
|
110
|
+
"--print",
|
|
111
|
+
"ui",
|
|
112
|
+
flag_value="print",
|
|
113
|
+
help="Run in print mode. Shortcut for `--ui print`.",
|
|
114
|
+
)
|
|
115
|
+
@click.option(
|
|
116
|
+
"--acp",
|
|
117
|
+
"ui",
|
|
118
|
+
flag_value="acp",
|
|
119
|
+
help="Start ACP server. Shortcut for `--ui acp`.",
|
|
120
|
+
)
|
|
121
|
+
@click.option(
|
|
122
|
+
"--input-format",
|
|
123
|
+
type=click.Choice(["text", "stream-json"]),
|
|
124
|
+
default=None,
|
|
125
|
+
help=(
|
|
126
|
+
"Input format to use. Must be used with `--print` "
|
|
127
|
+
"and the input must be piped in via stdin. "
|
|
128
|
+
"Default: text."
|
|
129
|
+
),
|
|
130
|
+
)
|
|
131
|
+
@click.option(
|
|
132
|
+
"--output-format",
|
|
133
|
+
type=click.Choice(["text", "stream-json"]),
|
|
134
|
+
default=None,
|
|
135
|
+
help="Output format to use. Must be used with `--print`. Default: text.",
|
|
136
|
+
)
|
|
137
|
+
@click.option(
|
|
138
|
+
"--mcp-config-file",
|
|
139
|
+
type=click.Path(exists=True, file_okay=True, dir_okay=False, path_type=Path),
|
|
140
|
+
multiple=True,
|
|
141
|
+
help=(
|
|
142
|
+
"MCP config file to load. Add this option multiple times to specify multiple MCP configs. "
|
|
143
|
+
"Default: none."
|
|
144
|
+
),
|
|
145
|
+
)
|
|
146
|
+
@click.option(
|
|
147
|
+
"--mcp-config",
|
|
148
|
+
type=str,
|
|
149
|
+
multiple=True,
|
|
150
|
+
help=(
|
|
151
|
+
"MCP config JSON to load. Add this option multiple times to specify multiple MCP configs. "
|
|
152
|
+
"Default: none."
|
|
153
|
+
),
|
|
154
|
+
)
|
|
155
|
+
def kimi(
|
|
156
|
+
verbose: bool,
|
|
157
|
+
debug: bool,
|
|
158
|
+
agent_file: Path,
|
|
159
|
+
model_name: str | None,
|
|
160
|
+
work_dir: Path,
|
|
161
|
+
continue_: bool,
|
|
162
|
+
command: str | None,
|
|
163
|
+
ui: UIMode,
|
|
164
|
+
input_format: InputFormat | None,
|
|
165
|
+
output_format: OutputFormat | None,
|
|
166
|
+
mcp_config_file: list[Path],
|
|
167
|
+
mcp_config: list[str],
|
|
168
|
+
):
|
|
169
|
+
"""Kimi, your next CLI agent."""
|
|
170
|
+
echo = click.echo if verbose else lambda *args, **kwargs: None
|
|
171
|
+
|
|
172
|
+
logger.add(
|
|
173
|
+
get_share_dir() / "logs" / "kimi.log",
|
|
174
|
+
level="DEBUG" if debug else "INFO",
|
|
175
|
+
rotation="06:00",
|
|
176
|
+
retention="10 days",
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
work_dir = work_dir.absolute()
|
|
180
|
+
|
|
181
|
+
if continue_:
|
|
182
|
+
session = continue_session(work_dir)
|
|
183
|
+
if session is None:
|
|
184
|
+
raise click.BadOptionUsage(
|
|
185
|
+
"--continue", "No previous session found for the working directory"
|
|
186
|
+
)
|
|
187
|
+
echo(f"✓ Continuing previous session: {session.id}")
|
|
188
|
+
else:
|
|
189
|
+
session = new_session(work_dir)
|
|
190
|
+
echo(f"✓ Created new session: {session.id}")
|
|
191
|
+
echo(f"✓ Session history file: {session.history_file}")
|
|
192
|
+
|
|
193
|
+
if input_format is not None and ui != "print":
|
|
194
|
+
raise click.BadOptionUsage(
|
|
195
|
+
"--input-format",
|
|
196
|
+
"Input format is only supported for print UI",
|
|
197
|
+
)
|
|
198
|
+
if output_format is not None and ui != "print":
|
|
199
|
+
raise click.BadOptionUsage(
|
|
200
|
+
"--output-format",
|
|
201
|
+
"Output format is only supported for print UI",
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
try:
|
|
205
|
+
mcp_configs = [json.loads(conf.read_text()) for conf in mcp_config_file]
|
|
206
|
+
except json.JSONDecodeError as e:
|
|
207
|
+
raise click.BadOptionUsage("--mcp-config-file", f"Invalid JSON: {e}") from e
|
|
208
|
+
|
|
209
|
+
try:
|
|
210
|
+
mcp_configs += [json.loads(conf) for conf in mcp_config]
|
|
211
|
+
except json.JSONDecodeError as e:
|
|
212
|
+
raise click.BadOptionUsage("--mcp-config", f"Invalid JSON: {e}") from e
|
|
213
|
+
|
|
214
|
+
while True:
|
|
215
|
+
try:
|
|
216
|
+
try:
|
|
217
|
+
config = load_config()
|
|
218
|
+
except ConfigError as e:
|
|
219
|
+
raise click.ClickException(f"Failed to load config: {e}") from e
|
|
220
|
+
echo(f"✓ Loaded config: {config}")
|
|
221
|
+
|
|
222
|
+
succeeded = asyncio.run(
|
|
223
|
+
kimi_run(
|
|
224
|
+
config=config,
|
|
225
|
+
model_name=model_name,
|
|
226
|
+
work_dir=work_dir,
|
|
227
|
+
session=session,
|
|
228
|
+
command=command,
|
|
229
|
+
agent_file=agent_file,
|
|
230
|
+
verbose=verbose,
|
|
231
|
+
ui=ui,
|
|
232
|
+
input_format=input_format,
|
|
233
|
+
output_format=output_format,
|
|
234
|
+
mcp_configs=mcp_configs,
|
|
235
|
+
)
|
|
236
|
+
)
|
|
237
|
+
if not succeeded:
|
|
238
|
+
sys.exit(1)
|
|
239
|
+
break
|
|
240
|
+
except Reload:
|
|
241
|
+
continue
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
async def kimi_run(
|
|
245
|
+
*,
|
|
246
|
+
config: Config,
|
|
247
|
+
model_name: str | None,
|
|
248
|
+
work_dir: Path,
|
|
249
|
+
session: Session,
|
|
250
|
+
command: str | None = None,
|
|
251
|
+
agent_file: Path = DEFAULT_AGENT_FILE,
|
|
252
|
+
verbose: bool = True,
|
|
253
|
+
ui: UIMode = "shell",
|
|
254
|
+
input_format: InputFormat | None = None,
|
|
255
|
+
output_format: OutputFormat | None = None,
|
|
256
|
+
mcp_configs: list[dict[str, Any]] | None = None,
|
|
257
|
+
) -> bool:
|
|
258
|
+
"""Run Kimi CLI."""
|
|
259
|
+
echo = click.echo if verbose else lambda *args, **kwargs: None
|
|
260
|
+
|
|
261
|
+
model: LLMModel | None = None
|
|
262
|
+
provider: LLMProvider | None = None
|
|
263
|
+
|
|
264
|
+
# try to use config file
|
|
265
|
+
if not model_name and config.default_model:
|
|
266
|
+
# no --model specified && default model is set in config
|
|
267
|
+
model = config.models[config.default_model]
|
|
268
|
+
provider = config.providers[model.provider]
|
|
269
|
+
if model_name and model_name in config.models:
|
|
270
|
+
# --model specified && model is set in config
|
|
271
|
+
model = config.models[model_name]
|
|
272
|
+
provider = config.providers[model.provider]
|
|
273
|
+
|
|
274
|
+
if not model:
|
|
275
|
+
model = LLMModel(provider="", model="", max_context_size=100_000)
|
|
276
|
+
provider = LLMProvider(type="kimi", base_url="", api_key=SecretStr(""))
|
|
277
|
+
|
|
278
|
+
# try overwrite with environment variables
|
|
279
|
+
assert provider is not None
|
|
280
|
+
assert model is not None
|
|
281
|
+
augment_provider_with_env_vars(provider, model)
|
|
282
|
+
|
|
283
|
+
if not provider.base_url or not model.model:
|
|
284
|
+
llm = None
|
|
285
|
+
else:
|
|
286
|
+
echo(f"✓ Using LLM provider: {provider}")
|
|
287
|
+
echo(f"✓ Using LLM model: {model}")
|
|
288
|
+
stream = ui != "print" # use non-streaming mode only for print UI
|
|
289
|
+
llm = create_llm(provider, model, stream=stream)
|
|
290
|
+
|
|
291
|
+
# TODO: support Windows
|
|
292
|
+
ls = subprocess.run(["ls", "-la"], capture_output=True, text=True)
|
|
293
|
+
agents_md = load_agents_md(work_dir) or ""
|
|
294
|
+
if agents_md:
|
|
295
|
+
echo(f"✓ Loaded agents.md: {textwrap.shorten(agents_md, width=100)}")
|
|
296
|
+
|
|
297
|
+
agent_globals = AgentGlobals(
|
|
298
|
+
config=config,
|
|
299
|
+
llm=llm,
|
|
300
|
+
builtin_args=BuiltinSystemPromptArgs(
|
|
301
|
+
KIMI_NOW=datetime.now().astimezone().isoformat(),
|
|
302
|
+
KIMI_WORK_DIR=work_dir,
|
|
303
|
+
KIMI_WORK_DIR_LS=ls.stdout,
|
|
304
|
+
KIMI_AGENTS_MD=agents_md,
|
|
305
|
+
),
|
|
306
|
+
denwa_renji=DenwaRenji(),
|
|
307
|
+
session=session,
|
|
308
|
+
approval=Approval(),
|
|
309
|
+
)
|
|
310
|
+
try:
|
|
311
|
+
agent = await load_agent_with_mcp(agent_file, agent_globals, mcp_configs or [])
|
|
312
|
+
except ValueError as e:
|
|
313
|
+
raise click.BadParameter(f"Failed to load agent: {e}") from e
|
|
314
|
+
echo(f"✓ Loaded agent: {agent.name}")
|
|
315
|
+
echo(f"✓ Loaded system prompt: {textwrap.shorten(agent.system_prompt, width=100)}")
|
|
316
|
+
echo(f"✓ Loaded tools: {[tool.name for tool in agent.toolset.tools]}")
|
|
317
|
+
|
|
318
|
+
if command is not None:
|
|
319
|
+
command = command.strip()
|
|
320
|
+
if not command:
|
|
321
|
+
raise click.BadParameter("Command cannot be empty")
|
|
322
|
+
|
|
323
|
+
context = Context(session.history_file)
|
|
324
|
+
restored = await context.restore()
|
|
325
|
+
if restored:
|
|
326
|
+
echo(f"✓ Restored history from {session.history_file}")
|
|
327
|
+
|
|
328
|
+
soul = KimiSoul(
|
|
329
|
+
agent,
|
|
330
|
+
agent_globals,
|
|
331
|
+
context=context,
|
|
332
|
+
loop_control=config.loop_control,
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
original_cwd = Path.cwd()
|
|
336
|
+
os.chdir(work_dir)
|
|
337
|
+
|
|
338
|
+
try:
|
|
339
|
+
if ui == "shell":
|
|
340
|
+
if command is None and not sys.stdin.isatty():
|
|
341
|
+
command = sys.stdin.read().strip()
|
|
342
|
+
echo(f"✓ Read command from stdin: {command}")
|
|
343
|
+
|
|
344
|
+
app = ShellApp(
|
|
345
|
+
soul,
|
|
346
|
+
welcome_info={
|
|
347
|
+
"Directory": str(work_dir),
|
|
348
|
+
"Session": session.id,
|
|
349
|
+
},
|
|
350
|
+
)
|
|
351
|
+
# to ignore possible warnings from dateparser
|
|
352
|
+
warnings.filterwarnings("ignore", category=DeprecationWarning)
|
|
353
|
+
with contextlib.redirect_stderr(StreamToLogger()):
|
|
354
|
+
return await app.run(command)
|
|
355
|
+
elif ui == "print":
|
|
356
|
+
app = PrintApp(soul, input_format or "text", output_format or "text")
|
|
357
|
+
return await app.run(command)
|
|
358
|
+
elif ui == "acp":
|
|
359
|
+
if command is not None:
|
|
360
|
+
logger.warning("ACP server ignores command argument")
|
|
361
|
+
app = ACPServer(soul)
|
|
362
|
+
return await app.run()
|
|
363
|
+
else:
|
|
364
|
+
raise click.BadParameter(f"Invalid UI mode: {ui}")
|
|
365
|
+
finally:
|
|
366
|
+
os.chdir(original_cwd)
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
def main():
|
|
370
|
+
kimi()
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
if __name__ == "__main__":
|
|
374
|
+
main()
|