kimi-cli 0.35__py3-none-any.whl → 0.52__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.
- kimi_cli/CHANGELOG.md +165 -0
- kimi_cli/__init__.py +0 -374
- kimi_cli/agents/{koder → default}/agent.yaml +1 -1
- kimi_cli/agents/{koder → default}/system.md +1 -1
- kimi_cli/agentspec.py +115 -0
- kimi_cli/app.py +208 -0
- kimi_cli/cli.py +321 -0
- kimi_cli/config.py +33 -16
- kimi_cli/constant.py +4 -0
- kimi_cli/exception.py +16 -0
- kimi_cli/llm.py +144 -3
- kimi_cli/metadata.py +6 -69
- kimi_cli/prompts/__init__.py +4 -0
- kimi_cli/session.py +103 -0
- kimi_cli/soul/__init__.py +130 -9
- kimi_cli/soul/agent.py +159 -0
- kimi_cli/soul/approval.py +5 -6
- kimi_cli/soul/compaction.py +106 -0
- kimi_cli/soul/context.py +1 -1
- kimi_cli/soul/kimisoul.py +180 -80
- kimi_cli/soul/message.py +6 -6
- kimi_cli/soul/runtime.py +96 -0
- kimi_cli/soul/toolset.py +3 -2
- kimi_cli/tools/__init__.py +35 -31
- kimi_cli/tools/bash/__init__.py +25 -9
- kimi_cli/tools/bash/cmd.md +31 -0
- kimi_cli/tools/dmail/__init__.py +5 -4
- kimi_cli/tools/file/__init__.py +8 -0
- kimi_cli/tools/file/glob.md +1 -1
- kimi_cli/tools/file/glob.py +4 -4
- kimi_cli/tools/file/grep.py +36 -19
- kimi_cli/tools/file/patch.py +52 -10
- kimi_cli/tools/file/read.py +6 -5
- kimi_cli/tools/file/replace.py +16 -4
- kimi_cli/tools/file/write.py +16 -4
- kimi_cli/tools/mcp.py +7 -4
- kimi_cli/tools/task/__init__.py +60 -41
- kimi_cli/tools/task/task.md +1 -1
- kimi_cli/tools/todo/__init__.py +4 -2
- kimi_cli/tools/utils.py +1 -1
- kimi_cli/tools/web/fetch.py +2 -1
- kimi_cli/tools/web/search.py +13 -12
- kimi_cli/ui/__init__.py +0 -68
- kimi_cli/ui/acp/__init__.py +67 -38
- kimi_cli/ui/print/__init__.py +46 -69
- kimi_cli/ui/shell/__init__.py +145 -154
- kimi_cli/ui/shell/console.py +27 -1
- kimi_cli/ui/shell/debug.py +187 -0
- kimi_cli/ui/shell/keyboard.py +183 -0
- kimi_cli/ui/shell/metacmd.py +34 -81
- kimi_cli/ui/shell/prompt.py +245 -28
- kimi_cli/ui/shell/replay.py +104 -0
- kimi_cli/ui/shell/setup.py +19 -19
- kimi_cli/ui/shell/update.py +11 -5
- kimi_cli/ui/shell/visualize.py +576 -0
- kimi_cli/ui/wire/README.md +109 -0
- kimi_cli/ui/wire/__init__.py +340 -0
- kimi_cli/ui/wire/jsonrpc.py +48 -0
- kimi_cli/utils/__init__.py +0 -0
- kimi_cli/utils/aiohttp.py +10 -0
- kimi_cli/utils/changelog.py +6 -2
- kimi_cli/utils/clipboard.py +10 -0
- kimi_cli/utils/message.py +15 -1
- kimi_cli/utils/rich/__init__.py +33 -0
- kimi_cli/utils/rich/markdown.py +959 -0
- kimi_cli/utils/rich/markdown_sample.md +108 -0
- kimi_cli/utils/rich/markdown_sample_short.md +2 -0
- kimi_cli/utils/signals.py +41 -0
- kimi_cli/utils/string.py +8 -0
- kimi_cli/utils/term.py +114 -0
- kimi_cli/wire/__init__.py +73 -0
- kimi_cli/wire/message.py +191 -0
- kimi_cli-0.52.dist-info/METADATA +186 -0
- kimi_cli-0.52.dist-info/RECORD +99 -0
- kimi_cli-0.52.dist-info/entry_points.txt +3 -0
- kimi_cli/agent.py +0 -261
- kimi_cli/agents/koder/README.md +0 -3
- kimi_cli/prompts/metacmds/__init__.py +0 -4
- kimi_cli/soul/wire.py +0 -101
- kimi_cli/ui/shell/liveview.py +0 -158
- kimi_cli/utils/provider.py +0 -64
- kimi_cli-0.35.dist-info/METADATA +0 -24
- kimi_cli-0.35.dist-info/RECORD +0 -76
- kimi_cli-0.35.dist-info/entry_points.txt +0 -3
- /kimi_cli/agents/{koder → default}/sub.yaml +0 -0
- /kimi_cli/prompts/{metacmds/compact.md → compact.md} +0 -0
- /kimi_cli/prompts/{metacmds/init.md → init.md} +0 -0
- {kimi_cli-0.35.dist-info → kimi_cli-0.52.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: kimi-cli
|
|
3
|
+
Version: 0.52
|
|
4
|
+
Summary: Kimi CLI is your next CLI agent.
|
|
5
|
+
Requires-Dist: agent-client-protocol==0.6.3
|
|
6
|
+
Requires-Dist: aiofiles==25.1.0
|
|
7
|
+
Requires-Dist: aiohttp==3.13.2
|
|
8
|
+
Requires-Dist: typer==0.20.0
|
|
9
|
+
Requires-Dist: kosong==0.22.0
|
|
10
|
+
Requires-Dist: loguru==0.7.3
|
|
11
|
+
Requires-Dist: patch-ng==1.19.0
|
|
12
|
+
Requires-Dist: prompt-toolkit==3.0.52
|
|
13
|
+
Requires-Dist: pillow==12.0.0
|
|
14
|
+
Requires-Dist: pyyaml==6.0.3
|
|
15
|
+
Requires-Dist: rich==14.2.0
|
|
16
|
+
Requires-Dist: ripgrepy==2.2.0
|
|
17
|
+
Requires-Dist: streamingjson==0.0.5
|
|
18
|
+
Requires-Dist: trafilatura==2.0.0
|
|
19
|
+
Requires-Dist: tenacity==9.1.2
|
|
20
|
+
Requires-Dist: fastmcp==2.12.5
|
|
21
|
+
Requires-Dist: pydantic==2.12.4
|
|
22
|
+
Requires-Dist: httpx[socks]==0.28.1
|
|
23
|
+
Requires-Python: >=3.13
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
|
|
26
|
+
# Kimi CLI
|
|
27
|
+
|
|
28
|
+
[](https://github.com/MoonshotAI/kimi-cli/graphs/commit-activity)
|
|
29
|
+
[](https://github.com/MoonshotAI/kimi-cli/actions)
|
|
30
|
+
[](https://pypi.org/project/kimi-cli/)
|
|
31
|
+
[](https://pypistats.org/packages/kimi-cli)
|
|
32
|
+
[](https://deepwiki.com/MoonshotAI/kimi-cli)
|
|
33
|
+
|
|
34
|
+
[中文](https://www.kimi.com/coding/docs/kimi-cli.html)
|
|
35
|
+
|
|
36
|
+
Kimi CLI is a new CLI agent that can help you with your software development tasks and terminal operations.
|
|
37
|
+
|
|
38
|
+
> [!IMPORTANT]
|
|
39
|
+
> Kimi CLI is currently in technical preview.
|
|
40
|
+
|
|
41
|
+
## Key features
|
|
42
|
+
|
|
43
|
+
- Shell-like UI and shell command execution
|
|
44
|
+
- Zsh integration
|
|
45
|
+
- [Agent Client Protocol] support
|
|
46
|
+
- MCP support
|
|
47
|
+
- And more to come...
|
|
48
|
+
|
|
49
|
+
[Agent Client Protocol]: https://github.com/agentclientprotocol/agent-client-protocol
|
|
50
|
+
|
|
51
|
+
## Installation
|
|
52
|
+
|
|
53
|
+
Kimi CLI is published as a Python package on PyPI. We highly recommend installing it with [uv](https://docs.astral.sh/uv/). If you have not installed uv yet, please follow the instructions [here](https://docs.astral.sh/uv/getting-started/installation/) to install it first.
|
|
54
|
+
|
|
55
|
+
Once uv is installed, you can install Kimi CLI with:
|
|
56
|
+
|
|
57
|
+
```sh
|
|
58
|
+
uv tool install --python 3.13 kimi-cli
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Run `kimi --help` to check if Kimi CLI is installed successfully.
|
|
62
|
+
|
|
63
|
+
> [!IMPORTANT]
|
|
64
|
+
> Due to the security checks on macOS, the first time you run `kimi` command may take 10 seconds or more depending on your system environment.
|
|
65
|
+
|
|
66
|
+
## Upgrading
|
|
67
|
+
|
|
68
|
+
Upgrade Kimi CLI to the latest version with:
|
|
69
|
+
|
|
70
|
+
```sh
|
|
71
|
+
uv tool upgrade kimi-cli --no-cache
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Usage
|
|
75
|
+
|
|
76
|
+
Run `kimi` command in the directory you want to work on, then send `/setup` to setup Kimi CLI:
|
|
77
|
+
|
|
78
|
+

|
|
79
|
+
|
|
80
|
+
After setup, Kimi CLI will be ready to use. You can send `/help` to get more information.
|
|
81
|
+
|
|
82
|
+
## Features
|
|
83
|
+
|
|
84
|
+
### Shell mode
|
|
85
|
+
|
|
86
|
+
Kimi CLI is not only a coding agent, but also a shell. You can switch the mode by pressing `Ctrl-X`. In shell mode, you can directly run shell commands without leaving Kimi CLI.
|
|
87
|
+
|
|
88
|
+
> [!NOTE]
|
|
89
|
+
> Built-in shell commands like `cd` are not supported yet.
|
|
90
|
+
|
|
91
|
+
### Zsh integration
|
|
92
|
+
|
|
93
|
+
You can use Kimi CLI together with Zsh, to empower your shell experience with AI agent capabilities.
|
|
94
|
+
|
|
95
|
+
Install the [zsh-kimi-cli](https://github.com/MoonshotAI/zsh-kimi-cli) plugin via:
|
|
96
|
+
|
|
97
|
+
```sh
|
|
98
|
+
git clone https://github.com/MoonshotAI/zsh-kimi-cli.git \
|
|
99
|
+
${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/kimi-cli
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
> [!NOTE]
|
|
103
|
+
> If you are using a plugin manager other than Oh My Zsh, you may need to refer to the plugin's README for installation instructions.
|
|
104
|
+
|
|
105
|
+
Then add `kimi-cli` to your Zsh plugin list in `~/.zshrc`:
|
|
106
|
+
|
|
107
|
+
```sh
|
|
108
|
+
plugins=(... kimi-cli)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
After restarting Zsh, you can switch to agent mode by pressing `Ctrl-X`.
|
|
112
|
+
|
|
113
|
+
### ACP support
|
|
114
|
+
|
|
115
|
+
Kimi CLI supports [Agent Client Protocol] out of the box. You can use it together with any ACP-compatible editor or IDE.
|
|
116
|
+
|
|
117
|
+
For example, to use Kimi CLI with [Zed](https://zed.dev/), add the following configuration to your `~/.config/zed/settings.json`:
|
|
118
|
+
|
|
119
|
+
```json
|
|
120
|
+
{
|
|
121
|
+
"agent_servers": {
|
|
122
|
+
"Kimi CLI": {
|
|
123
|
+
"command": "kimi",
|
|
124
|
+
"args": ["--acp"],
|
|
125
|
+
"env": {}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Then you can create Kimi CLI threads in Zed's agent panel.
|
|
132
|
+
|
|
133
|
+
### Using MCP tools
|
|
134
|
+
|
|
135
|
+
Kimi CLI supports the well-established MCP config convention. For example:
|
|
136
|
+
|
|
137
|
+
```json
|
|
138
|
+
{
|
|
139
|
+
"mcpServers": {
|
|
140
|
+
"context7": {
|
|
141
|
+
"url": "https://mcp.context7.com/mcp",
|
|
142
|
+
"headers": {
|
|
143
|
+
"CONTEXT7_API_KEY": "YOUR_API_KEY"
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
"chrome-devtools": {
|
|
147
|
+
"command": "npx",
|
|
148
|
+
"args": ["-y", "chrome-devtools-mcp@latest"]
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Run `kimi` with `--mcp-config-file` option to connect to the specified MCP servers:
|
|
155
|
+
|
|
156
|
+
```sh
|
|
157
|
+
kimi --mcp-config-file /path/to/mcp.json
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Development
|
|
161
|
+
|
|
162
|
+
To develop Kimi CLI, run:
|
|
163
|
+
|
|
164
|
+
```sh
|
|
165
|
+
git clone https://github.com/MoonshotAI/kimi-cli.git
|
|
166
|
+
cd kimi-cli
|
|
167
|
+
|
|
168
|
+
make prepare # prepare the development environment
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Then you can start working on Kimi CLI.
|
|
172
|
+
|
|
173
|
+
Refer to the following commands after you make changes:
|
|
174
|
+
|
|
175
|
+
```sh
|
|
176
|
+
uv run kimi # run Kimi CLI
|
|
177
|
+
|
|
178
|
+
make format # format code
|
|
179
|
+
make check # run linting and type checking
|
|
180
|
+
make test # run tests
|
|
181
|
+
make help # show all make targets
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Contributing
|
|
185
|
+
|
|
186
|
+
We welcome contributions to Kimi CLI! Please refer to [CONTRIBUTING.md](./CONTRIBUTING.md) for more information.
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
kimi_cli/CHANGELOG.md,sha256=cc0250bcf4e0ef66c39068a33440df96190cae22b740ce43273cb98f3829b9cc,10268
|
|
2
|
+
kimi_cli/__init__.py,sha256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855,0
|
|
3
|
+
kimi_cli/agents/default/agent.yaml,sha256=6e5c51987ef5cfc0c4c4e34cc20b6fc975953ee219623fccae81a19155aab7b3,709
|
|
4
|
+
kimi_cli/agents/default/sub.yaml,sha256=e0c1ea34fdb04b0d6dc635709f0f130aff25d7f9fb97e238470143c8145be251,634
|
|
5
|
+
kimi_cli/agents/default/system.md,sha256=1d8fd4956b2442215396b5e9651771c9da8f9505ccbd3b6d5e91b1ac4ff35418,5001
|
|
6
|
+
kimi_cli/agentspec.py,sha256=1148b5184ca610b2fb261ce365a63eb2fc9d09497330fe0ea4b2567fc98d5657,4307
|
|
7
|
+
kimi_cli/app.py,sha256=f2e5607329ee90636f7ff08876d3be3c3fa5234220586049c89c6172461d6e8a,7495
|
|
8
|
+
kimi_cli/cli.py,sha256=a565cbf6529baa59729c629ab3b8a2e12a3c1e2476733b93859a986a9b4182fd,9094
|
|
9
|
+
kimi_cli/config.py,sha256=db5f038c00920be9e10ad30bdecd4cb6be4b77de22845423a83c974e14f67dfc,4962
|
|
10
|
+
kimi_cli/constant.py,sha256=78e25b9304cca7b6f70bb08bf0e1fee4b066297a05386e56dd6935ba42027cd9,110
|
|
11
|
+
kimi_cli/exception.py,sha256=a3fec07566da7d2d34be8cc454fb825f34109bbde3cddf69e1ece6ab21b4b219,259
|
|
12
|
+
kimi_cli/llm.py,sha256=0502113bc3830cffb4334342c775a5588bfd7323b2b46de3d6a3d526e812f5ea,5283
|
|
13
|
+
kimi_cli/metadata.py,sha256=bde1e7eaa3d9c27a83cdeaf5506fe384290fb1b5d094f0fe9bb182cbbfec6b1f,1573
|
|
14
|
+
kimi_cli/prompts/__init__.py,sha256=6dc5ed2d841f145c09550075f30853cdc51f00d2f5d9aa1097f8edea770536e7,174
|
|
15
|
+
kimi_cli/prompts/compact.md,sha256=6655bd7d8270b24d8f97b51ef7c471cf71d686c56f8ec9a5cc9e47caa3aae87c,1877
|
|
16
|
+
kimi_cli/prompts/init.md,sha256=d271a0df6dd7b330ffec4f645a74c0392dafc1b3bfc1e3f2a77624e96cf6abbe,1380
|
|
17
|
+
kimi_cli/py.typed,sha256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855,0
|
|
18
|
+
kimi_cli/session.py,sha256=a5ec3caa828428dd65fe6cb540cee1768a4def33a84a2f42d4744711e7bf550e,3681
|
|
19
|
+
kimi_cli/share.py,sha256=4292df7f44177419c45c772a933b5f36e2b7533f8cef9842629a438bc7856dc0,204
|
|
20
|
+
kimi_cli/soul/__init__.py,sha256=7183fea252b68dcddf710ec292419fb7c53bb163a30525f0331f43a8541826ca,5792
|
|
21
|
+
kimi_cli/soul/agent.py,sha256=6d44374a884b0f8e5075337188c59be8cd820f635fbb6195c5d4099a65d05206,5025
|
|
22
|
+
kimi_cli/soul/approval.py,sha256=48cd230dff81dfd70bd85f1ad2b99604d5569cf617a4c79c444f9772bbc89ce6,2552
|
|
23
|
+
kimi_cli/soul/compaction.py,sha256=e38e5386fec2c236a1960a3814611cb093bd2e10645759961f2ef47b5d3747d0,3594
|
|
24
|
+
kimi_cli/soul/context.py,sha256=8ae001e6fc0229ccf74c94f1aadfbef90a48d8eb0a78b9113ed720d32b5e543f,5850
|
|
25
|
+
kimi_cli/soul/denwarenji.py,sha256=66b95f052a1fa844e2347972d34e1916a7be24d3e493701b451f5380b0375c9f,1384
|
|
26
|
+
kimi_cli/soul/kimisoul.py,sha256=80b9cbc8bb8d2a017631bc639886f0b2da96f56fb24f0182b0c5e1f76c298a6d,12889
|
|
27
|
+
kimi_cli/soul/message.py,sha256=ed31c9eecfe83a5d363327e0c91c74ef66106faf741c3892a0826d9226faf674,2536
|
|
28
|
+
kimi_cli/soul/runtime.py,sha256=9421a3ce6882587a95ecdf77b3d75f3b7ecab55cf68dc57e3e563b93e5a02e46,2690
|
|
29
|
+
kimi_cli/soul/toolset.py,sha256=9eda995fbbf18a17855ac15a83b28d3af88d34fc64efbac0674a2bf2221b52fc,772
|
|
30
|
+
kimi_cli/tools/__init__.py,sha256=ab932d54793212c7036a29e1fa54b4f763349b450f0ab4da3108a2b2b3646068,3432
|
|
31
|
+
kimi_cli/tools/bash/__init__.py,sha256=6302aad1ca202a633ea68ffa0dfac0de407966b5b3bb4ba5757e15915fd09ca4,3489
|
|
32
|
+
kimi_cli/tools/bash/bash.md,sha256=5d9cc54b3718097951340b0a737c8e1fa308341fd2c4ebd121be94de31dd5f73,2348
|
|
33
|
+
kimi_cli/tools/bash/cmd.md,sha256=af5a0042ba2e2373078427f14f078205a51585f888f3744af5280fb23c0ab45a,2603
|
|
34
|
+
kimi_cli/tools/dmail/__init__.py,sha256=a33270355aee9d8acae93aeb5cf51bcff5018607b8be79ed579619f058e7826c,1326
|
|
35
|
+
kimi_cli/tools/dmail/dmail.md,sha256=0d18cae387dd52127ddc99e296253c09e68ccba5f343153c0adbe77d7586e759,1912
|
|
36
|
+
kimi_cli/tools/file/__init__.py,sha256=1516fb4c71097f9c14b605e7b9a1872af8786bdcb48323d1fa83bb1419436abb,546
|
|
37
|
+
kimi_cli/tools/file/glob.md,sha256=11fbfaf6033f57b69c6f91077ddd90505036937cd7217600d96992b9a48b7ca7,1400
|
|
38
|
+
kimi_cli/tools/file/glob.py,sha256=a95f0f502fe6458f8c21a7aa5f15e27828993b05fed83b83f8a7c0dc9c50a48b,5431
|
|
39
|
+
kimi_cli/tools/file/grep.md,sha256=12353db42cf3b5d9d91ac7c0f0b9c2a732e8b050c23a78f4e668db823cca4d50,245
|
|
40
|
+
kimi_cli/tools/file/grep.py,sha256=269f106bac7a3ab95f395a1e8233b45a104bcc11fc0a90a8f2beac08ef06588b,10710
|
|
41
|
+
kimi_cli/tools/file/patch.md,sha256=f9edbed6c6a03bf7448a51acc1f42622395fd7f1674a814e9a3b2302d3b7b92e,404
|
|
42
|
+
kimi_cli/tools/file/patch.py,sha256=7f96b7735609d183d54136adde8fd05352f20d865c2aebc640173c492d5257ab,6624
|
|
43
|
+
kimi_cli/tools/file/read.md,sha256=4c2d83e557daadc0612fb1a613e252b2c8e4df7ae57e6db094e9e75e994cb23b,1066
|
|
44
|
+
kimi_cli/tools/file/read.py,sha256=76ea260a813a987a4e34706f6cc3c2b77fc3f31a76831883caa91f9ab86df6a6,5109
|
|
45
|
+
kimi_cli/tools/file/replace.md,sha256=f429f263fa580f2f6107907a33ba8800dcdbd4fc1d9ff8dc4f858bd76ec6bbc6,267
|
|
46
|
+
kimi_cli/tools/file/replace.py,sha256=d2dd7381e004d0539a8cc0b6fa294aaed879d6ff18dde81dc0f4837b7c46c220,5206
|
|
47
|
+
kimi_cli/tools/file/write.md,sha256=f37b0f4742da57797ec4dd29fbd4fdc9b6617c6be644724a3b16d651c6129cec,324
|
|
48
|
+
kimi_cli/tools/file/write.py,sha256=ce40a695be5d45fc725545ec7134f0b963c7ddda0084e6ba59a0ac0d6d465d26,4380
|
|
49
|
+
kimi_cli/tools/mcp.py,sha256=68c307e702a61737ec7d761a273abb74261a57925d50ffa59fbd2db1b2037dc4,3731
|
|
50
|
+
kimi_cli/tools/task/__init__.py,sha256=7a57f159bc0775fbc9b2ebb18c2cf8b973a4e0c82eb298225d9f78f4628f0ea9,6927
|
|
51
|
+
kimi_cli/tools/task/task.md,sha256=391cc3553c7d310a323626bae180dd41cb810fb1233583713ebde105f954147a,2280
|
|
52
|
+
kimi_cli/tools/test.py,sha256=c094a91a2d1a5259e192f1147facd5eebd5e5c413787fce167db90e4b41b5119,1442
|
|
53
|
+
kimi_cli/tools/think/__init__.py,sha256=31b06088e2404cb09d42e0acec97c185e4861890bb687f28b41f39cea01b5733,603
|
|
54
|
+
kimi_cli/tools/think/think.md,sha256=ab40d4de1d8adb208384a4ab548e35776283cb0a681c6e208b041fc40ccba724,200
|
|
55
|
+
kimi_cli/tools/todo/__init__.py,sha256=2ea7deb0c06c97e200ccbb4c9b1e8cf0eb440ca8b0e87167204dcd41df0715fc,961
|
|
56
|
+
kimi_cli/tools/todo/set_todo_list.md,sha256=89509503f43ab321d440a04dc133ddc3e29859f68907a42c39e6093f7bfd485c,1654
|
|
57
|
+
kimi_cli/tools/utils.py,sha256=2e00d6f04f91e05a91bfb691e547a76193063fa6769a03f7d3ff992aba9372bf,4596
|
|
58
|
+
kimi_cli/tools/web/__init__.py,sha256=e13108c598828a8a05907a7a821e7ac92f5d63572bb9866dc12ca026094acb42,95
|
|
59
|
+
kimi_cli/tools/web/fetch.md,sha256=56d00bd93b4e379c4f7efe445fce963eb26b8d20f85d4c19097ba6f33bd0019a,67
|
|
60
|
+
kimi_cli/tools/web/fetch.py,sha256=66448121d27d67f75b977c32244c721c2ccff1b2e097c2fe6717e66018d8f747,3183
|
|
61
|
+
kimi_cli/tools/web/search.md,sha256=24049f9e90d37083e0fc78b8b2e3a5f6fadf09bea00f36712b235d1212a2f532,146
|
|
62
|
+
kimi_cli/tools/web/search.py,sha256=8f757f1eb83a878bd2a9d8c3d0c137c244c2a1314b5de8d2a55da5261773b162,4469
|
|
63
|
+
kimi_cli/ui/__init__.py,sha256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855,0
|
|
64
|
+
kimi_cli/ui/acp/__init__.py,sha256=bfcdd6e32ed84b710b3c5034edcfdd1cad3141dfee649a29601c8c955968d4ca,18294
|
|
65
|
+
kimi_cli/ui/print/__init__.py,sha256=8c55a2a9ee8382544b24da90a286a7611e0ebd706cdc98aeb42059635f4cc0e6,5541
|
|
66
|
+
kimi_cli/ui/shell/__init__.py,sha256=bc209f41d2c3e5da4a4442e9f84002f34be1c12256182786c99e02cc05a7d0d2,12125
|
|
67
|
+
kimi_cli/ui/shell/console.py,sha256=bcbf7efd214cba3d2259f2a2c1842250cde96d49e4f9f1e0b60273cf1c366be3,842
|
|
68
|
+
kimi_cli/ui/shell/debug.py,sha256=b6d7f5475580814bc3dc34abdc472e5bd2c06368e88cae517de1bacc343af9bf,5557
|
|
69
|
+
kimi_cli/ui/shell/keyboard.py,sha256=23e5fbc4b6acda4c0f3b5297a0ae6eb09a90f4b5b37b2e95b7ce86a2da0d5dca,5160
|
|
70
|
+
kimi_cli/ui/shell/metacmd.py,sha256=85f09997bc40279029ada6a12819d4edb4fb7d0ccac5e535d385257bb7e14347,7649
|
|
71
|
+
kimi_cli/ui/shell/prompt.py,sha256=c078b7071a114e0869f655e90258f78bbffa80c70da7dc36164bde6921a8a76c,26697
|
|
72
|
+
kimi_cli/ui/shell/replay.py,sha256=dfc50d6721dbd43566683f224c6df3b7c6e8f0ea06a726a1e4f3139fdb102227,3762
|
|
73
|
+
kimi_cli/ui/shell/setup.py,sha256=6270ea039ebffbe11834e73a5c6f895d46c76d2460760bc5bec2741062f6a6fb,5258
|
|
74
|
+
kimi_cli/ui/shell/update.py,sha256=56dcb0bd1da82b98c22bfdddca717a2805bd8ac3e93bf23fb3b508549c41fae8,7340
|
|
75
|
+
kimi_cli/ui/shell/visualize.py,sha256=fa425172f252d4bf4b05fa515fff0e87559d9d10590b4a33c6b8b9a72d24cb87,21531
|
|
76
|
+
kimi_cli/ui/wire/README.md,sha256=0d9beaf38d4f4f1777013e85445e615fcacfe3a169d11151c42a141dec6196bd,4849
|
|
77
|
+
kimi_cli/ui/wire/__init__.py,sha256=9252f53cd32b5a114afdbc402817a627818a48897554977908b5c5e64864801e,11932
|
|
78
|
+
kimi_cli/ui/wire/jsonrpc.py,sha256=c093a540e70026cb48eae494cf4c8ad04f1180338eaaad0a23d64798bb679944,995
|
|
79
|
+
kimi_cli/utils/__init__.py,sha256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855,0
|
|
80
|
+
kimi_cli/utils/aiohttp.py,sha256=f8f61e3beaf6439e949c33c3a10db3035bf88136e882b09c858ea92a4c888e00,245
|
|
81
|
+
kimi_cli/utils/changelog.py,sha256=8079109bae377c141d8f50b8ea5e5c2f1e44a6a70c0dcfb9987b3b480283ed9b,3536
|
|
82
|
+
kimi_cli/utils/clipboard.py,sha256=81944e1ba313c8784e513b10e2a0bb759ac5acd4ee27cb335c876e5e93bb8fe6,212
|
|
83
|
+
kimi_cli/utils/logging.py,sha256=129298ac214ecd8d913c3431cc05d754f9c4c8c4042c458618bf9e8ddebdb763,399
|
|
84
|
+
kimi_cli/utils/message.py,sha256=e2ed32c5cac8e2c637fc9ea89c6643fd80a06e211b68d126312e4118b94b2d06,727
|
|
85
|
+
kimi_cli/utils/path.py,sha256=fdd4fc08999ddc7c610f884b4ba8d27932248b9ed06b5eb4139519edd00b3f75,687
|
|
86
|
+
kimi_cli/utils/pyinstaller.py,sha256=e5d709d0490ef8645bbed2d2363920c59f25bd17c04f471bf4a8c0fa2ebe1801,581
|
|
87
|
+
kimi_cli/utils/rich/__init__.py,sha256=2cb421c8491bd11aa2360119f88a4788337fc9884aba05d6400761a0e24c4c2b,909
|
|
88
|
+
kimi_cli/utils/rich/markdown.py,sha256=e81efafad7e82d52fab7d0d873d81c829054dd6c147c385b02ae91f9d8de4f92,33863
|
|
89
|
+
kimi_cli/utils/rich/markdown_sample.md,sha256=2b04c7ad3eadca4bff61e5ccf4d9f2bc400110867afbce190e671ef3ff28007c,1792
|
|
90
|
+
kimi_cli/utils/rich/markdown_sample_short.md,sha256=52f9186332bd41e0e84586c7025c3e69df69cf406add8e71d2413735aeb8aa24,17
|
|
91
|
+
kimi_cli/utils/signals.py,sha256=20e0d158a1043189d44815fe3624cd0bfe41e99620a18ac9e12c0eda6db5220f,1387
|
|
92
|
+
kimi_cli/utils/string.py,sha256=0d437d3633199df1051813af8b49a2f808c6525547310cc5c3d427710d2eae06,593
|
|
93
|
+
kimi_cli/utils/term.py,sha256=89dc154e08730c56b2a69c8a2073a76b9736841b56bebc2b30a7bd1d0723c8f5,3049
|
|
94
|
+
kimi_cli/wire/__init__.py,sha256=86e62344d4a56a4979eb08f5b62c74aeb858a4b0ef54bfc2ec8b095eb7fe1b49,2037
|
|
95
|
+
kimi_cli/wire/message.py,sha256=826d21d7c2aca32124449b50d6352b880edbf517e87173441d4d38d6700f915f,5573
|
|
96
|
+
kimi_cli-0.52.dist-info/WHEEL,sha256=70ab3c2925fe316809860cb034f99ba13c4b49819b339959274aab755cc084a8,78
|
|
97
|
+
kimi_cli-0.52.dist-info/entry_points.txt,sha256=4a8d437328d2f5f95fd5b718206f7c249c99542444c452d9b45befef1bd58b62,43
|
|
98
|
+
kimi_cli-0.52.dist-info/METADATA,sha256=ea845873311442b649724a6878df8f3cc87c49d231ee8257c46d8c7139241a2b,5206
|
|
99
|
+
kimi_cli-0.52.dist-info/RECORD,,
|
kimi_cli/agent.py
DELETED
|
@@ -1,261 +0,0 @@
|
|
|
1
|
-
import importlib
|
|
2
|
-
import inspect
|
|
3
|
-
import string
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
from typing import Any, NamedTuple
|
|
6
|
-
|
|
7
|
-
import fastmcp
|
|
8
|
-
import yaml
|
|
9
|
-
from kosong.tooling import Toolset
|
|
10
|
-
from kosong.tooling.simple import ToolType
|
|
11
|
-
from pydantic import BaseModel, Field
|
|
12
|
-
|
|
13
|
-
from kimi_cli.config import Config
|
|
14
|
-
from kimi_cli.llm import LLM
|
|
15
|
-
from kimi_cli.metadata import Session
|
|
16
|
-
from kimi_cli.soul.approval import Approval
|
|
17
|
-
from kimi_cli.soul.denwarenji import DenwaRenji
|
|
18
|
-
from kimi_cli.soul.toolset import CustomToolset
|
|
19
|
-
from kimi_cli.tools.mcp import MCPTool
|
|
20
|
-
from kimi_cli.utils.logging import logger
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
class AgentSpec(BaseModel):
|
|
24
|
-
"""Agent specification."""
|
|
25
|
-
|
|
26
|
-
extend: str | None = Field(default=None, description="Agent file to extend")
|
|
27
|
-
name: str | None = Field(default=None, description="Agent name") # required
|
|
28
|
-
system_prompt_path: Path | None = Field(
|
|
29
|
-
default=None, description="System prompt path"
|
|
30
|
-
) # required
|
|
31
|
-
system_prompt_args: dict[str, str] = Field(
|
|
32
|
-
default_factory=dict, description="System prompt arguments"
|
|
33
|
-
)
|
|
34
|
-
tools: list[str] | None = Field(default=None, description="Tools") # required
|
|
35
|
-
exclude_tools: list[str] | None = Field(default=None, description="Tools to exclude")
|
|
36
|
-
subagents: dict[str, "SubagentSpec"] | None = Field(default=None, description="Subagents")
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
class SubagentSpec(BaseModel):
|
|
40
|
-
"""Subagent specification."""
|
|
41
|
-
|
|
42
|
-
path: Path = Field(description="Subagent file path")
|
|
43
|
-
description: str = Field(description="Subagent description")
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
class BuiltinSystemPromptArgs(NamedTuple):
|
|
47
|
-
"""Builtin system prompt arguments."""
|
|
48
|
-
|
|
49
|
-
KIMI_NOW: str
|
|
50
|
-
"""The current datetime."""
|
|
51
|
-
KIMI_WORK_DIR: Path
|
|
52
|
-
"""The current working directory."""
|
|
53
|
-
KIMI_WORK_DIR_LS: str
|
|
54
|
-
"""The `ls -la` output of current working directory."""
|
|
55
|
-
KIMI_AGENTS_MD: str # TODO: move to first message from system prompt
|
|
56
|
-
"""The content of AGENTS.md."""
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
class AgentGlobals(NamedTuple):
|
|
60
|
-
"""Agent globals."""
|
|
61
|
-
|
|
62
|
-
config: Config
|
|
63
|
-
llm: LLM | None
|
|
64
|
-
builtin_args: BuiltinSystemPromptArgs
|
|
65
|
-
denwa_renji: DenwaRenji
|
|
66
|
-
session: Session
|
|
67
|
-
approval: Approval
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
class Agent(NamedTuple):
|
|
71
|
-
"""The loaded agent."""
|
|
72
|
-
|
|
73
|
-
name: str
|
|
74
|
-
system_prompt: str
|
|
75
|
-
toolset: Toolset
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
def get_agents_dir() -> Path:
|
|
79
|
-
return Path(__file__).parent / "agents"
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
DEFAULT_AGENT_FILE = get_agents_dir() / "koder" / "agent.yaml"
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
async def load_agent_with_mcp(
|
|
86
|
-
agent_file: Path,
|
|
87
|
-
globals_: AgentGlobals,
|
|
88
|
-
mcp_configs: list[dict[str, Any]],
|
|
89
|
-
) -> Agent:
|
|
90
|
-
agent = load_agent(agent_file, globals_)
|
|
91
|
-
assert isinstance(agent.toolset, CustomToolset)
|
|
92
|
-
if mcp_configs:
|
|
93
|
-
await _load_mcp_tools(agent.toolset, mcp_configs)
|
|
94
|
-
return agent
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
def load_agent(
|
|
98
|
-
agent_file: Path,
|
|
99
|
-
globals_: AgentGlobals,
|
|
100
|
-
) -> Agent:
|
|
101
|
-
"""
|
|
102
|
-
Load agent from specification file.
|
|
103
|
-
|
|
104
|
-
Raises:
|
|
105
|
-
ValueError: If the agent spec is not valid.
|
|
106
|
-
"""
|
|
107
|
-
agent_spec = _load_agent_spec(agent_file)
|
|
108
|
-
assert agent_spec.extend is None, "agent extension should be recursively resolved"
|
|
109
|
-
if agent_spec.name is None:
|
|
110
|
-
raise ValueError("Agent name is required")
|
|
111
|
-
if agent_spec.system_prompt_path is None:
|
|
112
|
-
raise ValueError("System prompt path is required")
|
|
113
|
-
if agent_spec.tools is None:
|
|
114
|
-
raise ValueError("Tools are required")
|
|
115
|
-
|
|
116
|
-
system_prompt = _load_system_prompt(
|
|
117
|
-
agent_spec.system_prompt_path, agent_spec.system_prompt_args, globals_.builtin_args
|
|
118
|
-
)
|
|
119
|
-
|
|
120
|
-
tool_deps = {
|
|
121
|
-
AgentSpec: agent_spec,
|
|
122
|
-
AgentGlobals: globals_,
|
|
123
|
-
Config: globals_.config,
|
|
124
|
-
BuiltinSystemPromptArgs: globals_.builtin_args,
|
|
125
|
-
Session: globals_.session,
|
|
126
|
-
DenwaRenji: globals_.denwa_renji,
|
|
127
|
-
Approval: globals_.approval,
|
|
128
|
-
}
|
|
129
|
-
tools = agent_spec.tools
|
|
130
|
-
if agent_spec.exclude_tools:
|
|
131
|
-
logger.debug("Excluding tools: {tools}", tools=agent_spec.exclude_tools)
|
|
132
|
-
tools = [tool for tool in tools if tool not in agent_spec.exclude_tools]
|
|
133
|
-
toolset = CustomToolset()
|
|
134
|
-
bad_tools = _load_tools(toolset, tools, tool_deps)
|
|
135
|
-
if bad_tools:
|
|
136
|
-
raise ValueError(f"Invalid tools: {bad_tools}")
|
|
137
|
-
|
|
138
|
-
return Agent(
|
|
139
|
-
name=agent_spec.name,
|
|
140
|
-
system_prompt=system_prompt,
|
|
141
|
-
toolset=toolset,
|
|
142
|
-
)
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
def _load_agent_spec(agent_file: Path) -> AgentSpec:
|
|
146
|
-
assert agent_file.is_file(), "expect agent file to exist"
|
|
147
|
-
with open(agent_file, encoding="utf-8") as f:
|
|
148
|
-
data: dict[str, Any] = yaml.safe_load(f)
|
|
149
|
-
|
|
150
|
-
version = data.get("version", 1)
|
|
151
|
-
if version != 1:
|
|
152
|
-
raise ValueError(f"Unsupported agent spec version: {version}")
|
|
153
|
-
|
|
154
|
-
agent_spec = AgentSpec(**data.get("agent", {}))
|
|
155
|
-
if agent_spec.system_prompt_path is not None:
|
|
156
|
-
agent_spec.system_prompt_path = agent_file.parent / agent_spec.system_prompt_path
|
|
157
|
-
if agent_spec.subagents is not None:
|
|
158
|
-
for v in agent_spec.subagents.values():
|
|
159
|
-
v.path = agent_file.parent / v.path
|
|
160
|
-
if agent_spec.extend:
|
|
161
|
-
if agent_spec.extend == "default":
|
|
162
|
-
base_agent_file = DEFAULT_AGENT_FILE
|
|
163
|
-
else:
|
|
164
|
-
base_agent_file = agent_file.parent / agent_spec.extend
|
|
165
|
-
base_agent_spec = _load_agent_spec(base_agent_file)
|
|
166
|
-
if agent_spec.name is not None:
|
|
167
|
-
base_agent_spec.name = agent_spec.name
|
|
168
|
-
if agent_spec.system_prompt_path is not None:
|
|
169
|
-
base_agent_spec.system_prompt_path = agent_spec.system_prompt_path
|
|
170
|
-
for k, v in agent_spec.system_prompt_args.items():
|
|
171
|
-
base_agent_spec.system_prompt_args[k] = v
|
|
172
|
-
if agent_spec.tools is not None:
|
|
173
|
-
base_agent_spec.tools = agent_spec.tools
|
|
174
|
-
if agent_spec.exclude_tools is not None:
|
|
175
|
-
base_agent_spec.exclude_tools = agent_spec.exclude_tools
|
|
176
|
-
if agent_spec.subagents is not None:
|
|
177
|
-
base_agent_spec.subagents = agent_spec.subagents
|
|
178
|
-
agent_spec = base_agent_spec
|
|
179
|
-
return agent_spec
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
def _load_system_prompt(
|
|
183
|
-
path: Path, args: dict[str, str], builtin_args: BuiltinSystemPromptArgs
|
|
184
|
-
) -> str:
|
|
185
|
-
system_prompt = path.read_text().strip()
|
|
186
|
-
logger.debug(
|
|
187
|
-
"Substituting system prompt with builtin args: {builtin_args}, spec args: {spec_args}",
|
|
188
|
-
builtin_args=builtin_args,
|
|
189
|
-
spec_args=args,
|
|
190
|
-
)
|
|
191
|
-
return string.Template(system_prompt).substitute(builtin_args._asdict(), **args)
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
def _load_tools(
|
|
195
|
-
toolset: CustomToolset,
|
|
196
|
-
tool_paths: list[str],
|
|
197
|
-
dependencies: dict[type[Any], Any],
|
|
198
|
-
) -> list[str]:
|
|
199
|
-
bad_tools = []
|
|
200
|
-
for tool_path in tool_paths:
|
|
201
|
-
tool = _load_tool(tool_path, dependencies)
|
|
202
|
-
if tool:
|
|
203
|
-
toolset += tool
|
|
204
|
-
else:
|
|
205
|
-
bad_tools.append(tool_path)
|
|
206
|
-
logger.debug("Loaded tools: {tools}", tools=toolset.tools)
|
|
207
|
-
if bad_tools:
|
|
208
|
-
logger.error("Bad tools: {bad_tools}", bad_tools=bad_tools)
|
|
209
|
-
return bad_tools
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
def _load_tool(tool_path: str, dependencies: dict[type[Any], Any]) -> ToolType | None:
|
|
213
|
-
logger.debug("Loading tool: {tool_path}", tool_path=tool_path)
|
|
214
|
-
module_name, class_name = tool_path.rsplit(":", 1)
|
|
215
|
-
try:
|
|
216
|
-
module = importlib.import_module(module_name)
|
|
217
|
-
except ImportError:
|
|
218
|
-
return None
|
|
219
|
-
cls = getattr(module, class_name, None)
|
|
220
|
-
if cls is None:
|
|
221
|
-
return None
|
|
222
|
-
args = []
|
|
223
|
-
for param in inspect.signature(cls).parameters.values():
|
|
224
|
-
if param.kind == inspect.Parameter.KEYWORD_ONLY:
|
|
225
|
-
# once we encounter a keyword-only parameter, we stop injecting dependencies
|
|
226
|
-
break
|
|
227
|
-
# all positional parameters should be dependencies to be injected
|
|
228
|
-
if param.annotation not in dependencies:
|
|
229
|
-
raise ValueError(f"Tool dependency not found: {param.annotation}")
|
|
230
|
-
args.append(dependencies[param.annotation])
|
|
231
|
-
return cls(*args)
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
async def _load_mcp_tools(
|
|
235
|
-
toolset: CustomToolset,
|
|
236
|
-
mcp_configs: list[dict[str, Any]],
|
|
237
|
-
):
|
|
238
|
-
"""
|
|
239
|
-
Raises:
|
|
240
|
-
ValueError: If the MCP config is not valid.
|
|
241
|
-
RuntimeError: If the MCP server cannot be connected.
|
|
242
|
-
"""
|
|
243
|
-
for mcp_config in mcp_configs:
|
|
244
|
-
client = fastmcp.Client(mcp_config)
|
|
245
|
-
async with client:
|
|
246
|
-
for tool in await client.list_tools():
|
|
247
|
-
toolset += MCPTool(tool, client)
|
|
248
|
-
return toolset
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
def load_agents_md(work_dir: Path) -> str | None:
|
|
252
|
-
paths = [
|
|
253
|
-
work_dir / "AGENTS.md",
|
|
254
|
-
work_dir / "agents.md",
|
|
255
|
-
]
|
|
256
|
-
for path in paths:
|
|
257
|
-
if path.is_file():
|
|
258
|
-
logger.debug("Loaded agents.md: {path}", path=path)
|
|
259
|
-
return path.read_text().strip()
|
|
260
|
-
logger.debug("No AGENTS.md found")
|
|
261
|
-
return None
|
kimi_cli/agents/koder/README.md
DELETED
kimi_cli/soul/wire.py
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import asyncio
|
|
2
|
-
import uuid
|
|
3
|
-
from contextvars import ContextVar
|
|
4
|
-
from enum import Enum
|
|
5
|
-
from typing import NamedTuple
|
|
6
|
-
|
|
7
|
-
from kosong.base.message import ContentPart, ToolCall, ToolCallPart
|
|
8
|
-
from kosong.tooling import ToolResult
|
|
9
|
-
|
|
10
|
-
from kimi_cli.soul import StatusSnapshot
|
|
11
|
-
from kimi_cli.utils.logging import logger
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class StepBegin(NamedTuple):
|
|
15
|
-
n: int
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class StepInterrupted(NamedTuple):
|
|
19
|
-
pass
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
class StatusUpdate(NamedTuple):
|
|
23
|
-
status: StatusSnapshot
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
type ControlFlowEvent = StepBegin | StepInterrupted | StatusUpdate
|
|
27
|
-
type Event = ControlFlowEvent | ContentPart | ToolCall | ToolCallPart | ToolResult
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
class ApprovalResponse(Enum):
|
|
31
|
-
APPROVE = "approve"
|
|
32
|
-
APPROVE_FOR_SESSION = "approve_for_session"
|
|
33
|
-
REJECT = "reject"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
class ApprovalRequest:
|
|
37
|
-
def __init__(self, tool_call_id: str, action: str, description: str):
|
|
38
|
-
self.id = str(uuid.uuid4())
|
|
39
|
-
self.tool_call_id = tool_call_id
|
|
40
|
-
self.action = action
|
|
41
|
-
self.description = description
|
|
42
|
-
self._future = asyncio.Future[ApprovalResponse]()
|
|
43
|
-
|
|
44
|
-
def __repr__(self) -> str:
|
|
45
|
-
return (
|
|
46
|
-
f"ApprovalRequest(id={self.id}, tool_call_id={self.tool_call_id}, "
|
|
47
|
-
f"action={self.action}, description={self.description})"
|
|
48
|
-
)
|
|
49
|
-
|
|
50
|
-
async def wait(self) -> ApprovalResponse:
|
|
51
|
-
"""
|
|
52
|
-
Wait for the request to be resolved or cancelled.
|
|
53
|
-
|
|
54
|
-
Returns:
|
|
55
|
-
ApprovalResponse: The response to the approval request.
|
|
56
|
-
"""
|
|
57
|
-
return await self._future
|
|
58
|
-
|
|
59
|
-
def resolve(self, response: ApprovalResponse) -> None:
|
|
60
|
-
"""
|
|
61
|
-
Resolve the approval request with the given response.
|
|
62
|
-
This will cause the `wait()` method to return the response.
|
|
63
|
-
"""
|
|
64
|
-
self._future.set_result(response)
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
type WireMessage = Event | ApprovalRequest
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
class Wire:
|
|
71
|
-
"""
|
|
72
|
-
A channel for communication between the soul and the UI.
|
|
73
|
-
"""
|
|
74
|
-
|
|
75
|
-
def __init__(self):
|
|
76
|
-
self._queue = asyncio.Queue[WireMessage]()
|
|
77
|
-
|
|
78
|
-
def send(self, msg: WireMessage) -> None:
|
|
79
|
-
if not isinstance(msg, ContentPart | ToolCallPart):
|
|
80
|
-
logger.debug("Sending wire message: {msg}", msg=msg)
|
|
81
|
-
self._queue.put_nowait(msg)
|
|
82
|
-
|
|
83
|
-
async def receive(self) -> WireMessage:
|
|
84
|
-
msg = await self._queue.get()
|
|
85
|
-
if not isinstance(msg, ContentPart | ToolCallPart):
|
|
86
|
-
logger.debug("Receiving wire message: {msg}", msg=msg)
|
|
87
|
-
return msg
|
|
88
|
-
|
|
89
|
-
def shutdown(self) -> None:
|
|
90
|
-
self._queue.shutdown()
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
current_wire = ContextVar[Wire | None]("current_wire", default=None)
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
def get_wire_or_none() -> Wire | None:
|
|
97
|
-
"""
|
|
98
|
-
Get the current wire or None.
|
|
99
|
-
Expect to be not None when called from anywhere in the agent loop.
|
|
100
|
-
"""
|
|
101
|
-
return current_wire.get()
|