Skip to content

Commit c50ecb7

Browse files
authored
feat(tool): conditional description for read file (#603)
Signed-off-by: Richard Chien <stdrc@outlook.com>
1 parent 6eaf8bd commit c50ecb7

13 files changed

Lines changed: 191 additions & 26 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ Only write entries that are worth mentioning to users.
1111

1212
## Unreleased
1313

14+
- Tool: Make `ReadFile` tool description reflect model capabilities for image/video support
15+
1416
## 0.75 (2026-01-09)
1517

1618
- Tool: Improve `ReadFile` tool description

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,9 @@ ai-test: ## Run the test suite with Kimi CLI.
110110
.PHONY: gen-changelog gen-docs
111111
gen-changelog: ## Generate changelog with Kimi CLI.
112112
@echo "==> Generating changelog"
113-
@uv run kimi -c "$$(cat ./docs/prompts/gen-changelog.txt)" --yolo
113+
@uv run kimi -c "$$(cat .kimi/prompts/gen-changelog.md)" --yolo
114114
gen-docs: ## Generate user docs with Kimi CLI.
115115
@echo "==> Generating user docs"
116-
@uv run kimi -c "$$(cat ./docs/prompts/gen-docs.txt)" --yolo
116+
@uv run kimi -c "$$(cat .kimi/prompts/gen-docs.md)" --yolo
117117

118118
include src/kimi_cli/deps/Makefile

docs/en/release-notes/changelog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ This page documents the changes in each Kimi CLI release.
44

55
## Unreleased
66

7+
- Tool: Make `ReadFile` tool description reflect model capabilities for image/video support
8+
79
## 0.75 (2026-01-09)
810

911
- Tool: Improve `ReadFile` tool description

docs/zh/release-notes/changelog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
## 未发布
66

7+
- Tool:让 `ReadFile` 工具描述根据模型能力动态反映图片/视频支持情况
8+
79
## 0.75 (2026-01-09)
810

911
- Tool:改进 `ReadFile` 工具描述

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ dependencies = [
2828
"pykaos==0.6.0",
2929
"batrachian-toad==0.5.23; python_version >= \"3.14\"",
3030
"tomlkit==0.13.3",
31+
"jinja2==3.1.4",
3132
]
3233

3334
[dependency-groups]

src/kimi_cli/tools/file/read.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,20 @@ Read content from a file.
1313
- Use `line_offset` and `n_lines` parameters when you only need to read a part of the file.
1414
- The maximum number of lines that can be read at once is ${MAX_LINES}.
1515
- Any lines longer than ${MAX_LINE_LENGTH} characters will be truncated, ending with "...".
16+
{% if "image_in" in capabilities and "video_in" in capabilities %}
1617
- For image and video files:
17-
- Content will be returned in a form that you can view and understand. If you do not support image/video input, try other tools to process media files.
18+
- Content will be returned in a form that you can view and understand. Feel confident to read image/video files with this tool.
1819
- The maximum size that can be read is ${MAX_MEDIA_BYTES} bytes. An error will be returned if the file is larger than this limit.
20+
{% elif "image_in" in capabilities %}
21+
- For image files:
22+
- Content will be returned in a form that you can view and understand. Feel confident to read image files with this tool.
23+
- The maximum size that can be read is ${MAX_MEDIA_BYTES} bytes. An error will be returned if the file is larger than this limit.
24+
- Other media files (e.g., video, PDFs) are not supported by this tool. Use other proper tools to process them.
25+
{% elif "video_in" in capabilities %}
26+
- For video files:
27+
- Content will be returned in a form that you can view and understand. Feel confident to read video files with this tool.
28+
- The maximum size that can be read is ${MAX_MEDIA_BYTES} bytes. An error will be returned if the file is larger than this limit.
29+
- Other media files (e.g., image, PDFs) are not supported by this tool. Use other proper tools to process them.
30+
{% else %}
31+
- Media files (e.g., image, video, PDFs) are not supported by this tool. Use other proper tools to process them.
32+
{% endif %}

src/kimi_cli/tools/file/read.py

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
from kosong.tooling import CallableTool2, ToolError, ToolOk, ToolReturnValue
77
from pydantic import BaseModel, Field
88

9-
from kimi_cli.soul.agent import BuiltinSystemPromptArgs
9+
from kimi_cli.soul.agent import Runtime
1010
from kimi_cli.tools.file.utils import MEDIA_SNIFF_BYTES, FileType, detect_file_type
11-
from kimi_cli.tools.utils import load_desc, truncate_line
11+
from kimi_cli.tools.utils import load_desc_jinja, truncate_line
1212
from kimi_cli.utils.path import is_within_directory
1313
from kimi_cli.wire.types import ImageURLPart, VideoURLPart
1414

@@ -52,20 +52,22 @@ class Params(BaseModel):
5252

5353
class ReadFile(CallableTool2[Params]):
5454
name: str = "ReadFile"
55-
description: str = load_desc(
56-
Path(__file__).parent / "read.md",
57-
{
58-
"MAX_LINES": str(MAX_LINES),
59-
"MAX_LINE_LENGTH": str(MAX_LINE_LENGTH),
60-
"MAX_BYTES": str(MAX_BYTES),
61-
"MAX_MEDIA_BYTES": str(MAX_MEDIA_BYTES),
62-
},
63-
)
6455
params: type[Params] = Params
6556

66-
def __init__(self, builtin_args: BuiltinSystemPromptArgs) -> None:
67-
super().__init__()
68-
self._work_dir = builtin_args.KIMI_WORK_DIR
57+
def __init__(self, runtime: Runtime) -> None:
58+
capabilities = runtime.llm.capabilities if runtime.llm else set[str]()
59+
description = load_desc_jinja(
60+
Path(__file__).parent / "read.md",
61+
{
62+
"MAX_LINES": MAX_LINES,
63+
"MAX_LINE_LENGTH": MAX_LINE_LENGTH,
64+
"MAX_BYTES": MAX_BYTES,
65+
"MAX_MEDIA_BYTES": MAX_MEDIA_BYTES,
66+
"capabilities": capabilities,
67+
},
68+
)
69+
super().__init__(description=description)
70+
self._work_dir = runtime.builtin_args.KIMI_WORK_DIR
6971

7072
async def _validate_path(self, path: KaosPath) -> ToolError | None:
7173
"""Validate that the path is safe to read."""

src/kimi_cli/tools/utils.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import string
33
from pathlib import Path
44

5+
from jinja2 import Environment
56
from kosong.tooling import BriefDisplayBlock, DisplayBlock, ToolError, ToolReturnValue
67
from kosong.utils.typing import JsonType
78

@@ -14,6 +15,21 @@ def load_desc(path: Path, substitutions: dict[str, str] | None = None) -> str:
1415
return description
1516

1617

18+
def load_desc_jinja(path: Path, context: dict[str, object] | None = None) -> str:
19+
"""Load a tool description from a file, rendered via Jinja2."""
20+
description = path.read_text(encoding="utf-8")
21+
env = Environment(
22+
autoescape=False,
23+
keep_trailing_newline=True,
24+
lstrip_blocks=True,
25+
trim_blocks=True,
26+
variable_start_string="${",
27+
variable_end_string="}",
28+
)
29+
template = env.from_string(description)
30+
return template.render(context or {})
31+
32+
1733
def truncate_line(line: str, max_length: int, marker: str = "...") -> str:
1834
"""
1935
Truncate a line if it exceeds `max_length`, preserving the beginning and the line break.

tests/conftest.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
from pydantic import SecretStr
1919

2020
from kimi_cli.config import Config, MoonshotSearchConfig, get_default_config
21-
from kimi_cli.llm import LLM
21+
from kimi_cli.llm import ALL_MODEL_CAPABILITIES, LLM
2222
from kimi_cli.metadata import WorkDirMeta
2323
from kimi_cli.session import Session
2424
from kimi_cli.soul.agent import Agent, BuiltinSystemPromptArgs, LaborMarket, Runtime
@@ -58,7 +58,7 @@ def llm() -> LLM:
5858
return LLM(
5959
chat_provider=MockChatProvider([]),
6060
max_context_size=100_000,
61-
capabilities=set(),
61+
capabilities=ALL_MODEL_CAPABILITIES,
6262
)
6363

6464

@@ -242,9 +242,9 @@ def shell_tool(approval: Approval, environment: Environment) -> Generator[Shell]
242242

243243

244244
@pytest.fixture
245-
def read_file_tool(builtin_args: BuiltinSystemPromptArgs) -> ReadFile:
245+
def read_file_tool(runtime: Runtime) -> ReadFile:
246246
"""Create a ReadFile tool instance."""
247-
return ReadFile(builtin_args)
247+
return ReadFile(runtime)
248248

249249

250250
@pytest.fixture

tests/test_default_agent.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ async def test_default_agent(runtime: Runtime):
320320
- The maximum number of lines that can be read at once is 1000.
321321
- Any lines longer than 2000 characters will be truncated, ending with "...".
322322
- For image and video files:
323-
- Content will be returned in a form that you can view and understand. If you do not support image/video input, try other tools to process media files.
323+
- Content will be returned in a form that you can view and understand. Feel confident to read image/video files with this tool.
324324
- The maximum size that can be read is 83886080 bytes. An error will be returned if the file is larger than this limit.
325325
""",
326326
parameters={

0 commit comments

Comments
 (0)