Skip to content

Dev/knowledge plane - #2606

Open
SoMiReMiReDo wants to merge 2 commits into
MoonshotAI:mainfrom
SoMiReMiReDo:dev/knowledge-plane
Open

Dev/knowledge plane#2606
SoMiReMiReDo wants to merge 2 commits into
MoonshotAI:mainfrom
SoMiReMiReDo:dev/knowledge-plane

Conversation

@SoMiReMiReDo

@SoMiReMiReDo SoMiReMiReDo commented Aug 18, 2026

Copy link
Copy Markdown

Related Issue

Resolve #(issue_number)

Description

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked the related issue, if any.
  • I have added tests that prove my fix is effective or that my feature works.
  • I have run make gen-changelog to update the changelog.
  • I have run make gen-docs to update the user documentation.

Open in Devin Review

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Devin Review found 5 potential issues.

View 3 additional findings in Devin Review.

Open in Devin Review

Comment on lines +565 to +577
else:
project_env_file = Path(str(work_dir)) / ".env"
project_env = load_dotenv_values(project_env_file if project_env_file.is_file() else None)
if project_config := project_env.get("KIMI_CONFIG_FILE"):
config_path = Path(project_config).expanduser()
if not config_path.is_absolute():
config_path = Path(str(work_dir)) / config_path
config_path = config_path.resolve(strict=False)
if not config_path.is_file():
raise typer.BadParameter(
f"Project config file not found: {config_path}", param_hint="KIMI_CONFIG_FILE"
)
config = config_path

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Custom env file passed on the command line is ignored when it points at a project config file

The config-file setting from a user-supplied env file is never read (load_dotenv_values(project_env_file ...) at src/kimi_cli/cli/__init__.py:566-567), because only the working directory's .env is consulted, so a project chosen with the command-line env option silently starts with the wrong configuration file.
Impact: Users who point the CLI at a non-default env file get the default (or another project's) configuration instead of the one they asked for, with no warning.

Why the option is skipped during config resolution

--env-file is accepted by the callback (src/kimi_cli/cli/__init__.py:199-209) and forwarded to KimiCLI.create (src/kimi_cli/cli/__init__.py:691), where it drives LLM env overrides (src/kimi_cli/app.py:263-268). However the KIMI_CONFIG_FILE lookup added at src/kimi_cli/cli/__init__.py:565-577 hard-codes Path(str(work_dir)) / ".env" and never considers env_file. Consequently, with --env-file custom.env, LLM settings come from custom.env while KIMI_CONFIG_FILE is read from <work-dir>/.env (or nowhere), which contradicts the documented behavior in docs/zh/configuration/env-vars.md:5-13 ("也可通过 --env-file PATH 指定其他文件").

Suggested change
else:
project_env_file = Path(str(work_dir)) / ".env"
project_env = load_dotenv_values(project_env_file if project_env_file.is_file() else None)
if project_config := project_env.get("KIMI_CONFIG_FILE"):
config_path = Path(project_config).expanduser()
if not config_path.is_absolute():
config_path = Path(str(work_dir)) / config_path
config_path = config_path.resolve(strict=False)
if not config_path.is_file():
raise typer.BadParameter(
f"Project config file not found: {config_path}", param_hint="KIMI_CONFIG_FILE"
)
config = config_path
else:
default_env_file = Path(str(work_dir)) / ".env"
selected_env_file = env_file or (default_env_file if default_env_file.is_file() else None)
project_env = load_dotenv_values(selected_env_file)
if project_config := project_env.get("KIMI_CONFIG_FILE"):
config_path = Path(project_config).expanduser()
if not config_path.is_absolute():
config_path = Path(str(work_dir)) / config_path
config_path = config_path.resolve(strict=False)
if not config_path.is_file():
raise typer.BadParameter(
f"Project config file not found: {config_path}", param_hint="KIMI_CONFIG_FILE"
)
config = config_path
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread src/kimi_cli/llm.py
Comment on lines +336 to +338
env: Mapping[str, str] | None = None,
) -> LLM | None:
env = os.environ if env is None else env

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Model tuning values from the project environment file are dropped for helper agents and model switches

Model tuning values are read only from the environment map handed to the main model builder (create_llm(..., env=...) at src/kimi_cli/llm.py:336-338), while other places that build a model do not pass it, so settings from a project environment file stop applying as soon as a helper agent or a model switch creates a new model.
Impact: Temperature, top-p, max-token and thinking-keep settings defined per project silently revert to whatever the shell environment has for subagents and after switching models.

Call sites that build an LLM without the project env map

create_llm reads KIMI_MODEL_TEMPERATURE, KIMI_MODEL_TOP_P, KIMI_MODEL_MAX_COMPLETION_TOKENS / KIMI_MODEL_MAX_TOKENS (src/kimi_cli/llm.py:368-388) and KIMI_MODEL_THINKING_KEEP (src/kimi_cli/llm.py:496) from the env mapping, defaulting to os.environ. Only KimiCLI.create passes the dotenv-overlaid mapping (src/kimi_cli/app.py:285-292). Other builders — clone_llm_with_model_alias used for subagent model overrides (src/kimi_cli/llm.py:528-534, src/kimi_cli/subagents/builder.py:20-26) and the ACP model-switch handler (src/kimi_cli/acp/server.py:357-363) — omit env, so they fall back to os.environ, which by design never contains the project .env values. Provider base_url/api_key survive because augment_provider_with_env_vars mutates the shared config objects in place, but the generation parameters do not.

Prompt for agents
Project-local dotenv values are only visible to the single create_llm() call in KimiCLI.create (src/kimi_cli/app.py). Other LLM construction paths — clone_llm_with_model_alias() (src/kimi_cli/llm.py), used by SubagentBuilder for per-subagent model overrides, and the ACP set-model handler in src/kimi_cli/acp/server.py — call create_llm() without the env mapping and therefore fall back to os.environ, losing KIMI_MODEL_TEMPERATURE / TOP_P / MAX_COMPLETION_TOKENS / THINKING_KEEP overrides from the project .env. Consider storing the resolved llm_env mapping on the Runtime (or another long-lived object) when KimiCLI.create builds it, and threading it through clone_llm_with_model_alias and the ACP model-switch path so all LLM instances in the process observe the same environment.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.


**生产影响:** 长期项目中,Agent 会重复探索仓库、重复询问约束,并可能做出与历史决策冲突的修改。直接把全部历史会话塞入上下文又会增加 Token 成本、隐私暴露和错误召回风险,因此生产实现必须包含作用域、来源、过期、删除和可解释引用,而不只是增加一个数据库。

**代码证据:** [`Session.dir`](../../src/kimi_cli/session.py#L48) 将数据限定在当前会话目录,[`Session.find`](../../src/kimi_cli/session.py#L183) 也要求使用明确的 `session_id` 恢复;[`SubagentStore.root`](../../src/kimi_cli/subagents/store.py#L68) 位于 `session.dir/subagents`。这些代码证明已有持久化,但其边界仍是单个会话。

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Internal planning and résumé documents dropped into the docs site directory break the documentation build

Ten Chinese planning/résumé documents were added inside the documentation site tree (docs/mk/Kimi Code CLI核心短板与秋招项目评估.md:21 and siblings) instead of the required docs/zh / docs/en structure, and they link to source files outside the site, so the documentation build fails and unrelated personal content would be published.
Impact: The docs site no longer builds, and if it did it would ship internal career-planning material to end users.

Why VitePress rejects these files

docs/AGENTS.md requires every page to live under docs/en/ or docs/zh/ with mirrored paths and to be wired into nav/sidebar in docs/.vitepress/config.ts. The new files live in docs/mk/ and docs/dev_note/ (plus a raw docs/mk/resume-kimi-code-cli.html) and are not registered anywhere. docs/.vitepress/config.ts sets no srcExclude, so VitePress picks up every .md under docs/ as a page. Those pages contain relative links to repository source such as [\Session.dir`](../../src/kimi_cli/session.py#L48)and`collect_git_context`; VitePress dead-link checking treats these as internal links to non-existent pages and fails npm run build` by default.

Prompt for agents
The PR adds planning/résumé documents under docs/mk/ and docs/dev_note/ (including a raw HTML file). docs/AGENTS.md mandates that documentation pages live under docs/en/ and docs/zh/ with mirrored slugs and be registered in docs/.vitepress/config.ts. Because docs/.vitepress/config.ts defines no srcExclude, every markdown file under docs/ becomes a site page, and these files link to repository sources with relative paths such as ../../src/kimi_cli/session.py#L48, which VitePress dead-link checking rejects, failing npm run build. Move this material out of the docs site (for example to a non-published directory or drop it from the PR), or, if it must stay, exclude it from the VitePress build and remove the links to non-page targets.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread src/kimi_cli/app.py
Comment on lines +139 to +140
@staticmethod
async def create( # Agent启动的入口

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Stray whitespace in the application startup file makes the repository's formatting check fail

A trailing space was left on the decorator line above the startup entry point (@staticmethod at src/kimi_cli/app.py:139), so the mandatory formatting check reports the file as unformatted and the commit hooks/CI stop.
Impact: Contributors running the standard check or committing with hooks enabled get a failure unrelated to their own work.

Formatting rules involved

make check-kimi-cli runs uv run ruff format --check (see Makefile:67-71), and prek hooks run make format-kimi-cli / make check-kimi-cli per AGENTS.md and CONTRIBUTING.md. ruff format strips trailing whitespace, so src/kimi_cli/app.py:139 ( @staticmethod with a trailing space) plus the inline comment placement on line 140 make the file differ from formatted output. Similar single-blank-line separations before module-level decorators were introduced in src/kimi_cli/cli/__init__.py (e.g. the comment banner directly above @cli.command() around line 978), which the formatter also rewrites. Running make format resolves all of these.

Suggested change
@staticmethod
async def create( # Agent启动的入口
@staticmethod
async def create( # Agent启动的入口
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread src/kimi_cli/app.py
Comment on lines +263 to +268
default_env_file = Path(str(session.work_dir)) / ".env"
selected_env_file = env_file or (default_env_file if default_env_file.is_file() else None)
llm_env: Mapping[str, str] = load_llm_env(selected_env_file)
if selected_env_file is not None:
logger.info("Loaded local LLM environment from: {file}", file=selected_env_file)
env_overrides = augment_provider_with_env_vars(provider, model, llm_env)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟨 Project-local .env credentials are auto-loaded from the working directory without opt-in

KimiCLI.create now silently discovers and applies <work-dir>/.env (src/kimi_cli/app.py:263-268), letting any repository the user opens override KIMI_BASE_URL, KIMI_API_KEY and the config file used (KIMI_CONFIG_FILE handling at src/kimi_cli/cli/__init__.py:565-577). Simply running kimi inside an untrusted clone that ships a .env redirects model traffic (including prompts and file contents) to an attacker-controlled base_url, or replaces the whole configuration with an attacker-supplied TOML/JSON file. The resolved API key is additionally propagated into globally persisted plugin config files via collect_host_values / refresh_plugin_configs (src/kimi_cli/app.py:332-334), so a project-scoped credential can be written outside the project.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant