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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Only write entries that are worth mentioning to users.

## Unreleased

- Core: Fix HTTP header values containing trailing whitespace/newlines on certain Linux systems (e.g. kernel 6.8.0-101) causing connection errors — strip whitespace from ASCII header values before sending
- Core: Fix OpenAI Responses provider sending implicit `reasoning.effort=null` which breaks Responses-compatible endpoints that require reasoning — reasoning parameters are now omitted unless explicitly set
- Core: Fix context compaction failing when conversation contains media parts (images, audio, video) — switch from blacklist filtering (exclude `ThinkPart`) to whitelist filtering (only keep `TextPart`) to prevent unsupported content types from being sent to the compaction API
- Web: Fix `@` file mention index not refreshing after switching sessions or when workspace files change — reset index on session switch, auto-refresh after 30s staleness, and support path-prefix search beyond the 500-file limit
Expand Down
1 change: 1 addition & 0 deletions docs/en/release-notes/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ This page documents the changes in each Kimi Code CLI release.

## Unreleased

- Core: Fix HTTP header values containing trailing whitespace/newlines on certain Linux systems (e.g. kernel 6.8.0-101) causing connection errors — strip whitespace from ASCII header values before sending
- Core: Fix OpenAI Responses provider sending implicit `reasoning.effort=null` which breaks Responses-compatible endpoints that require reasoning — reasoning parameters are now omitted unless explicitly set
- Core: Fix context compaction failing when conversation contains media parts (images, audio, video) — switch from blacklist filtering (exclude `ThinkPart`) to whitelist filtering (only keep `TextPart`) to prevent unsupported content types from being sent to the compaction API
- Web: Fix `@` file mention index not refreshing after switching sessions or when workspace files change — reset index on session switch, auto-refresh after 30s staleness, and support path-prefix search beyond the 500-file limit
Expand Down
1 change: 1 addition & 0 deletions docs/zh/release-notes/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

## 未发布

- Core:修复部分 Linux 系统(如内核版本 6.8.0-101)上 HTTP 请求头包含尾部空白/换行符导致连接错误的问题——发送前对 ASCII 请求头值执行空白裁剪
- Core:修复 OpenAI Responses provider 隐式发送 `reasoning.effort=null` 导致需要推理的 Responses 兼容端点报错的问题——现在仅在显式设置时才发送推理参数
- Core:修复对话包含媒体内容(图片、音频、视频)时上下文压缩失败的问题——将过滤策略从黑名单(排除 `ThinkPart`)改为白名单(仅保留 `TextPart`),防止不支持的内容类型被发送到压缩 API
- Web:修复 `@` 文件提及索引在切换会话或工作区文件变更后不刷新的问题——切换会话时重置索引,30 秒过期自动刷新,输入路径前缀可查找超出 500 文件上限的文件
Expand Down
2 changes: 1 addition & 1 deletion src/kimi_cli/auth/oauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ def get_device_id() -> str:
def _ascii_header_value(value: str, *, fallback: str = "unknown") -> str:
try:
value.encode("ascii")
return value
return value.strip()
except UnicodeEncodeError:
sanitized = value.encode("ascii", errors="ignore").decode("ascii").strip()
return sanitized or fallback
Comment on lines 195 to 201
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_ascii_header_value() now strips whitespace for ASCII-only values, but unlike the Unicode-sanitization path it does not fall back when the stripped result becomes empty (e.g., value is only whitespace). Consider returning fallback when value.strip() is empty as well, to keep behavior consistent and avoid emitting empty header values.

Copilot uses AI. Check for mistakes.
Expand Down
42 changes: 42 additions & 0 deletions tests/auth/test_ascii_header.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"""Tests for _ascii_header_value and _common_headers in oauth module.

Regression tests for the issue where Linux kernel version strings containing
trailing whitespace/newlines (e.g. platform.version() returning
"#101-Ubuntu SMP ...\n") would be included in HTTP headers, causing
connection errors.
"""

from unittest.mock import patch

from kimi_cli.auth.oauth import _ascii_header_value, _common_headers

Comment on lines +1 to +12
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This new test module is missing from __future__ import annotations, which appears to be used consistently across the existing test suite. Adding it keeps test files stylistically consistent and avoids surprises with forward references in type hints.

Copilot uses AI. Check for mistakes.

class TestAsciiHeaderValue:
"""Test cases for _ascii_header_value."""

def test_plain_ascii(self) -> None:
assert _ascii_header_value("hello") == "hello"

def test_strips_trailing_newline(self) -> None:
"""Regression: Linux platform.version() may contain trailing newline."""
assert _ascii_header_value("6.8.0-101\n") == "6.8.0-101"

def test_non_ascii_sanitized(self) -> None:
assert _ascii_header_value("héllo") == "hllo"

def test_all_non_ascii_returns_fallback(self) -> None:
assert _ascii_header_value("你好") == "unknown"


class TestCommonHeaders:
"""Test that _common_headers returns clean header values."""

@patch("kimi_cli.auth.oauth.platform")
@patch("kimi_cli.auth.oauth.get_device_id", return_value="abc123")
def test_no_whitespace_in_header_values(self, _mock_device_id, mock_platform) -> None:
"""All header values must be free of leading/trailing whitespace."""
mock_platform.node.return_value = "myhost"
mock_platform.version.return_value = "#101-Ubuntu SMP\n"
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test patches the entire kimi_cli.auth.oauth.platform module, but only configures node() and version(). Because _common_headers() also calls _device_model() (which calls platform.system(), platform.machine(), etc.), those calls become MagicMocks and can take unintended branches (e.g., system == "Darwin" evaluating truthy), making the test less robust. Prefer patching only platform.node/platform.version, or explicitly set system()/machine()/release() return values to deterministic strings.

Suggested change
mock_platform.version.return_value = "#101-Ubuntu SMP\n"
mock_platform.version.return_value = "#101-Ubuntu SMP\n"
mock_platform.system.return_value = "Linux"
mock_platform.machine.return_value = "x86_64"
mock_platform.release.return_value = "6.8.0-101"

Copilot uses AI. Check for mistakes.
headers = _common_headers()
for key, value in headers.items():
assert value == value.strip(), f"Header {key!r} has untrimmed whitespace: {value!r}"
Loading