32 lines
2.9 KiB
Markdown
32 lines
2.9 KiB
Markdown
# Anthropic projection: assistant ターン内ブロックを 1 message に束ねる
|
||
|
||
## 背景
|
||
|
||
`crates/llm-worker/src/llm_client/scheme/anthropic/request.rs` の `convert_items_to_messages` は、Worker が 1 ターンで生成する `[Reasoning, assistant_message, ToolCall]` の連列を、Anthropic wire 上で **複数の隣接した assistant message** に分割している。
|
||
|
||
具体的には:
|
||
- `Item::Reasoning` を `pending_assistant` に push
|
||
- 次の `Item::Message { Role::Assistant }` が到来すると `pending_assistant` を flush し、自分自身は別 message として messages に直 push
|
||
- 続く `Item::ToolCall` は再び `pending_assistant` に積まれ、turn 末で flush され 3 つ目の assistant message に
|
||
|
||
結果として 1 turn が `assistant[Thinking] / assistant[text] / assistant[tool_use]` の 3 message に展開される。
|
||
|
||
Anthropic Messages API は user/assistant の交互を要求し、同一論理 turn 内の thinking/text/tool_use は **1 つの assistant message の `content` 配列** に並べる仕様。新世代 Claude (Opus 4.5+/Sonnet 4.6+) で thinking signature を round-trip する際、隣接 assistant message に分かれていると signature の文脈が崩れて 400 になる懸念がある(reasoning-history-persist のレビュー指摘)。
|
||
|
||
なお、本バグは reasoning-history-persist で導入されたものではなく、`assistant_message` + `tool_call` の組合せで以前から存在していた pre-existing な分割。Reasoning が同じ flush 経路を継承した形。
|
||
|
||
## 要件
|
||
|
||
- 同一論理ターンに属する `Item::Reasoning` / `Item::Message(Assistant)` / `Item::ToolCall` を、Anthropic wire 上の **1 つの assistant message の `content` 配列** に束ねる
|
||
- 順序は arrival 順 (= history 順)。Anthropic 仕様の典型は thinking → text → tool_use
|
||
- user / system role の `Item::Message` や `Item::ToolResult` を境界として assistant burst を区切る
|
||
- 既存の breakpoint (cache_control) 計算が壊れないこと: 各 item のオリジン index → (msg_idx, part_idx) マッピングは flush_pending 経由で記録されているので、Item::Message(Assistant) も pending を経由するように揃えれば自然に追従する
|
||
- Single-text 専用の `AnthropicContent::Text` shorthand は assistant burst 内 1 part のみのときに限定して維持するか、簡潔さのために常に `Parts` 形式に統一するかは実装時に判断
|
||
- 既存テスト群(`completed_turn`, `single_text_message_uses_text_shorthand_without_breakpoint`, `breakpoint_on_tool_result_head` 等)の意図を逸脱しないよう更新
|
||
|
||
## スコープ外
|
||
|
||
- モデル世代別の thinking keep/strip デフォルト分岐(reasoning-history-persist のフォローアップ候補と同じ扱い)
|
||
- `clear_thinking_20251015` context-edit
|
||
- prune.rs の reasoning aware 化
|