Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ Only write entries that are worth mentioning to users.

## Unreleased

- Config: Add `reserved_context_size` setting to customize auto-compaction trigger threshold (default: 50000 tokens)

## 0.81 (2026-01-21)

- Skills: Add flow skill type with embedded Agent Flow (Mermaid/D2) in SKILL.md, invoked via `/flow:<skill-name>` commands
Expand Down
2 changes: 2 additions & 0 deletions docs/en/configuration/config-files.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ max_context_size = 262144
max_steps_per_turn = 100
max_retries_per_step = 3
max_ralph_iterations = 0
reserved_context_size = 50000

[services.moonshot_search]
base_url = "https://api.kimi.com/coding/v1/search"
Expand Down Expand Up @@ -117,6 +118,7 @@ capabilities = ["thinking", "image_in"]
| `max_steps_per_turn` | `integer` | `100` | Maximum steps per turn (alias: `max_steps_per_run`) |
| `max_retries_per_step` | `integer` | `3` | Maximum retries per step |
| `max_ralph_iterations` | `integer` | `0` | Extra iterations after each user message; `0` disables; `-1` is unlimited |
| `reserved_context_size` | `integer` | `50000` | Reserved token count for LLM response generation; auto-compaction triggers when `context_tokens + reserved_context_size >= max_context_size` |

### `services`

Expand Down
2 changes: 2 additions & 0 deletions docs/en/release-notes/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ This page documents the changes in each Kimi CLI release.

## Unreleased

- Config: Add `reserved_context_size` setting to customize auto-compaction trigger threshold (default: 50000 tokens)

## 0.81 (2026-01-21)

- Skills: Add flow skill type with embedded Agent Flow (Mermaid/D2) in SKILL.md, invoked via `/flow:<skill-name>` commands
Expand Down
2 changes: 2 additions & 0 deletions docs/zh/configuration/config-files.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ max_context_size = 262144
max_steps_per_turn = 100
max_retries_per_step = 3
max_ralph_iterations = 0
reserved_context_size = 50000

[services.moonshot_search]
base_url = "https://api.kimi.com/coding/v1/search"
Expand Down Expand Up @@ -117,6 +118,7 @@ capabilities = ["thinking", "image_in"]
| `max_steps_per_turn` | `integer` | `100` | 单轮最大步数(别名:`max_steps_per_run`) |
| `max_retries_per_step` | `integer` | `3` | 单步最大重试次数 |
| `max_ralph_iterations` | `integer` | `0` | 每个 User 消息后额外自动迭代次数;`0` 表示关闭;`-1` 表示无限 |
| `reserved_context_size` | `integer` | `50000` | 预留给 LLM 响应生成的 token 数量;当 `context_tokens + reserved_context_size >= max_context_size` 时自动触发压缩 |

### `services`

Expand Down
2 changes: 2 additions & 0 deletions docs/zh/release-notes/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

## 未发布

- Config:添加 `reserved_context_size` 配置项,自定义自动压缩触发阈值(默认 50000 tokens)

## 0.81 (2026-01-21)

- Skills:添加 Flow Skill 类型,在 SKILL.md 中内嵌 Agent Flow(Mermaid/D2),通过 `/flow:<skill-name>` 命令调用
Expand Down
3 changes: 3 additions & 0 deletions src/kimi_cli/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ class LoopControl(BaseModel):
"""Maximum number of retries in one step"""
max_ralph_iterations: int = Field(default=0, ge=-1)
"""Extra iterations after the first turn in Ralph mode. Use -1 for unlimited."""
reserved_context_size: int = Field(default=50_000, ge=1000)
"""Reserved token count for LLM response generation. Auto-compaction triggers when
context_tokens + reserved_context_size >= max_context_size. Default is 50000."""


class MoonshotSearchConfig(BaseModel):
Expand Down
11 changes: 2 additions & 9 deletions src/kimi_cli/soul/kimisoul.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,6 @@ def type_check(soul: KimiSoul):
_: Soul = soul


RESERVED_TOKENS = 50_000

SKILL_COMMAND_PREFIX = "skill:"
FLOW_COMMAND_PREFIX = "flow:"
DEFAULT_MAX_FLOW_MOVES = 1000
Expand Down Expand Up @@ -110,9 +108,6 @@ def __init__(
self._context = context
self._loop_control = agent.runtime.config.loop_control
self._compaction = SimpleCompaction() # TODO: maybe configurable and composable
self._reserved_tokens = RESERVED_TOKENS
if self._runtime.llm is not None:
assert self._reserved_tokens <= self._runtime.llm.max_context_size

for tool in agent.toolset.tools:
if tool.name == SendDMail_NAME:
Expand Down Expand Up @@ -348,10 +343,8 @@ async def _pipe_approval_to_wire():
step_outcome: StepOutcome | None = None
try:
# compact the context if needed
if (
self._context.token_count + self._reserved_tokens
>= self._runtime.llm.max_context_size
):
reserved = self._loop_control.reserved_context_size
if self._context.token_count + reserved >= self._runtime.llm.max_context_size:
logger.info("Context too long, compacting...")
await self.compact_context()

Expand Down
11 changes: 11 additions & 0 deletions tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ def test_default_config_dump():
"max_steps_per_turn": 100,
"max_retries_per_step": 3,
"max_ralph_iterations": 0,
"reserved_context_size": 50000,
},
"services": {"moonshot_search": None, "moonshot_fetch": None},
"mcp": {"client": {"tool_call_timeout_ms": 60000}},
Expand All @@ -62,3 +63,13 @@ def test_load_config_text_invalid():
def test_load_config_invalid_ralph_iterations():
with pytest.raises(ConfigError, match="max_ralph_iterations"):
load_config_from_string('{"loop_control": {"max_ralph_iterations": -2}}')


def test_load_config_reserved_context_size():
config = load_config_from_string('{"loop_control": {"reserved_context_size": 30000}}')
assert config.loop_control.reserved_context_size == 30000


def test_load_config_reserved_context_size_too_low():
with pytest.raises(ConfigError, match="reserved_context_size"):
load_config_from_string('{"loop_control": {"reserved_context_size": 500}}')