Skip to content

feat(acp): support locale injection via ACP initialize for i18n - #128

Open
Million-mo wants to merge 4 commits into
wolf1069b:develop/agenticfrom
Million-mo:feature/acp-locale-i18n
Open

feat(acp): support locale injection via ACP initialize for i18n#128
Million-mo wants to merge 4 commits into
wolf1069b:develop/agenticfrom
Million-mo:feature/acp-locale-i18n

Conversation

@Million-mo

@Million-mo Million-mo commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

Summary

支持通过 ACP initialize 请求传入 locale 变量,实现 agent 输出的多语言国际化。

客户端在 ACP initialize 时通过 _meta 字段传入 locale,agentpool 将其透传到 session,并作为 callable system prompt 注入到 agent,指导 agent 以指定语言响应。

Background

当前 agentpool 不支持任何 i18n 基础设施。agent 输出语言完全由 YAML 配置中的静态 prompt 文本决定,客户端无法在运行时指定语言偏好。

Changes

服务端(agentpool)

文件 改动
acp_agent.py initialize()params.field_meta 提取 locale,存储为 self.client_locale;在 new_session/fork_session/load_session/resume_session 中透传
session_manager.py create_session()resume_session() 接受 client_locale 参数,转发给 ACPSession
session.py ACPSession 增加 client_locale 字段;__post_init__()switch_active_agent() 中注入 get_locale_prompt() callable prompt
test_acp_session_resume.py 更新断言以包含 client_locale kwarg

客户端支持

ACP 客户端在 initialize 请求中通过 _meta 字段传入 locale:

{
  "method": "initialize",
  "params": {
    "protocolVersion": 1,
    "clientInfo": { "name": "xeno-agent", "title": "Xeno Agent", "version": "1.0" },
    "clientCapabilities": { "terminal": true, "fs": { "readTextFile": true, "writeTextFile": true } },
    "_meta": { "locale": "en" }
  }
}

如果使用 agentpool 的 ACP 客户端 SDK(ACPAgentAPI):

await client.initialize(
    title="Xeno Agent",
    version="1.0",
    name="xeno-agent",
    metadata={"locale": "en"},  # 传入 locale
)

metadata 参数会被序列化为 field_meta,在 JSON-RPC 中映射为 _meta

How It Works

  1. 客户端 initialize 时通过 _meta.locale 传入语言偏好
  2. AgentPoolACPAgent.initialize() 提取并存储 self.client_locale
  3. new_session/fork_session/load_session/resume_session 将 locale 传递到 ACPSessionManager
  4. ACPSession.__post_init__()get_locale_prompt 作为 callable prompt 注册到 agent 的 sys_prompts.prompts
  5. pydantic-ai 在每次 model call 时调用该 callable,生成 "Language: You MUST respond in en." 指令
  6. agent 按指定语言输出

复用了已有的 callable prompt 机制(与 get_cwd_context 完全同构),在 switch_active_agent 时也会正确清理和重新注入。

Testing

  • ruff check
  • mypy
  • pytest tests/servers/acp_server/ — 315 passed, 4 skipped ✅
  • pytest tests/acp/ tests/agents/acp_agent/ — 251 passed ✅

Limitations / Future Work

  • 当前 locale 以追加 callable prompt 的方式注入,不直接嵌入 YAML Jinja2 模板。后续可扩展 format_system_prompt() 支持 {{ locale }} 模板变量
  • 同一 agentpool 实例可服务不同 locale 的客户端(每个连接独立 AgentPoolACPAgent 实例)
  • 可扩展支持 new_session 级别的 locale 覆盖

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces support for client locales within the ACP server by extracting the locale from client metadata and injecting a language directive into the agent's system prompts. Feedback highlights a potential prompt injection vulnerability where the client-provided locale should be validated, and suggests using explicit is not None checks for metadata dictionary presence. Additionally, a potential memory leak and state residue risk was identified, recommending that the locale prompt be cleaned up in ACPSession.close() to ensure proper garbage collection.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/agentpool_server/acp_server/acp_agent.py Outdated
Comment thread src/agentpool_server/acp_server/session.py
@Million-mo
Million-mo requested a review from Leoyzen July 8, 2026 06:24
Client can pass locale through ACP initialize request's _meta field.
The locale is propagated through session creation and injected as a
callable system prompt that instructs the agent to respond in the
specified language.

Changes:
- AgentPoolACPAgent.initialize(): extract locale from params.field_meta
- AgentPoolACPAgent: thread client_locale through all session creation
  paths (new_session, fork_session, load_session, resume_session)
- ACPSessionManager: accept and forward client_locale in
  create_session() and resume_session()
- ACPSession: add client_locale field, inject get_locale_prompt()
  callable prompt in __post_init__() and switch_active_agent()
- Update test assertion to include client_locale kwarg

Client usage (ACP initialize JSON-RPC):
  {
    "method": "initialize",
    "params": {
      "_meta": { "locale": "en" },
      "protocolVersion": 1,
      ...
    }
  }
Address code review feedback:
- Extract locale validation into _extract_locale() helper with format
  checking (alphanumeric + hyphens, max 15 chars) to prevent prompt
  injection via crafted locale strings
- Use explicit 'is not None' check for field_meta instead of implicit
  truthiness
- Add get_locale_prompt cleanup in ACPSession.close() to prevent
  memory leak and stale state residue
…ies test

The test_from_config_capabilities_not_duplicated test used
model='openai:gpt-4o-mini' which requires OPENAI_API_KEY to
initialize the OpenAI client. This causes CI failures on fork PRs
where repository secrets are not available. Switch to
TestModelConfig which needs no API credentials.
@Million-mo
Million-mo force-pushed the feature/acp-locale-i18n branch from ffef79f to a515134 Compare July 8, 2026 07:48
@Million-mo

Copy link
Copy Markdown
Collaborator Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces support for client locales in the ACP server. It extracts and validates the client's locale from metadata during initialization, propagates it to sessions, and appends a system prompt instructing the agent to respond in the preferred language. The review feedback highlights a security improvement in the locale validation logic, suggesting that the character check be restricted to ASCII alphanumeric characters to prevent potential prompt injection via Unicode characters.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/agentpool_server/acp_server/acp_agent.py Outdated
Per review feedback, c.isalnum() returns True for Unicode characters
(Chinese, Cyrillic, etc.), which could allow prompt injection via
crafted locale strings. Added c.isascii() guard to restrict to
ASCII-only alphanumeric characters, hyphens, and underscores.
Million-mo added a commit to Million-mo/agentpool that referenced this pull request Jul 8, 2026
Same fix as PR wolf1069b#128 — replace openai:gpt-4o-mini with TestModelConfig
so the test doesn't need real API credentials in CI.
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