From 1505c5e8a3ef61705420690cf051697b5c634fff Mon Sep 17 00:00:00 2001 From: Hare Date: Tue, 14 Jul 2026 04:14:58 +0900 Subject: [PATCH] docs: generalize llm-engine comments --- crates/llm-engine-macros/README.md | 2 +- crates/llm-engine/README.md | 8 ++-- crates/llm-engine/src/engine.rs | 35 ++++++++--------- crates/llm-engine/src/interceptor.rs | 13 +++---- crates/llm-engine/src/llm_client/auth.rs | 28 ++++++-------- .../llm-engine/src/llm_client/scheme/mod.rs | 7 ++-- .../scheme/openai_responses/capability.rs | 4 +- .../scheme/openai_responses/events.rs | 2 +- .../llm_client/scheme/openai_responses/mod.rs | 18 ++++----- .../scheme/openai_responses/request.rs | 38 +++++++++---------- .../scheme/openai_responses/scheme_impl.rs | 15 ++++---- crates/llm-engine/src/llm_client/transport.rs | 9 ++--- crates/llm-engine/src/llm_client/types.rs | 7 ++-- crates/llm-engine/src/prune.rs | 6 +-- crates/llm-engine/src/tool_server.rs | 7 ++-- crates/llm-engine/src/usage_record.rs | 5 +-- 16 files changed, 93 insertions(+), 111 deletions(-) diff --git a/crates/llm-engine-macros/README.md b/crates/llm-engine-macros/README.md index a7cf7b99..733862d8 100644 --- a/crates/llm-engine-macros/README.md +++ b/crates/llm-engine-macros/README.md @@ -20,7 +20,7 @@ Does not own: ## Design notes -Macros reduce boilerplate, but they must not imply capability. A generated tool definition is still subject to manifest permissions, Worker scope, and runtime policy. +Macros reduce boilerplate, but they must not imply capability. A generated tool definition is still subject to host permissions, application scope, and runtime policy. ## See also diff --git a/crates/llm-engine/README.md b/crates/llm-engine/README.md index 19db5846..57320289 100644 --- a/crates/llm-engine/README.md +++ b/crates/llm-engine/README.md @@ -16,10 +16,10 @@ Owns: Does not own: -- Worker names, sockets, process lifecycle, or scope delegation (`worker`) -- product CLI shape (`yoi`) -- provider catalog and secret resolution (`provider`, `secrets`) -- durable Worker current state (`session-store` worker metadata) +- Host application names, sockets, process lifecycle, or scope delegation +- Product CLI shape +- Provider catalog and secret resolution +- Durable application state outside engine history ## Design notes diff --git a/crates/llm-engine/src/engine.rs b/crates/llm-engine/src/engine.rs index fa92a651..d41d8631 100644 --- a/crates/llm-engine/src/engine.rs +++ b/crates/llm-engine/src/engine.rs @@ -213,9 +213,9 @@ pub struct Engine { /// stream events become visible. lifecycle_trace_cbs: Vec>, /// Non-fatal warning callbacks. Invoked when the Engine wants to - /// surface an advisory message to the upper layer (e.g. Worker) so it - /// can be forwarded to the user — distinct from `tracing::warn!`, - /// which is for developer-facing logs. + /// surface an advisory message to the caller so it can be forwarded + /// to the user — distinct from `tracing::warn!`, which is for + /// developer-facing logs. warning_cbs: Vec>, /// Tool-result callbacks. Invoked once per completed tool call /// after post-execution interceptors and the output byte-cap @@ -253,8 +253,8 @@ pub struct Engine { /// Plumbed into [`Request::cache_anchor`] at request build time. cache_anchor: Option, /// Conversation-scoped cache key, set by higher layers. Plumbed into - /// [`Request::cache_key`] at request build time. Worker 側では - /// `SegmentId` を渡す。 + /// [`Request::cache_key`] at request build time. Callers should pass a + /// stable conversation identifier when the backend benefits from one. cache_key: Option, /// State marker _state: PhantomData, @@ -486,8 +486,8 @@ impl Engine { /// /// Fired after `post_tool_call` interceptors and any `content` /// truncation from `tool_output_limits`, so the callback observes - /// exactly what is persisted to history. Intended for upper layers - /// (e.g. Worker) to forward tool results to clients. + /// exactly what is persisted to history. Intended for callers that need + /// to forward tool results to clients. pub fn on_tool_result(&mut self, callback: impl Fn(&ToolResult) + Send + Sync + 'static) { self.tool_result_cbs.push(Box::new(callback)); } @@ -1121,10 +1121,10 @@ impl Engine { } // Drain interceptor-side inputs that are meant to land in - // history (notifications, cross-Worker events, system - // reminders). These are committed *before* the per-request - // clone so they participate in the LLM request below and - // get persisted by the upper layer that owns history.json. + // history (notifications, external events, system reminders). + // These are committed *before* the per-request clone so they + // participate in the LLM request below and get persisted by + // the caller that owns durable history. let pending = self.interceptor.pending_history_appends().await; if !pending.is_empty() { self.append_history_items(pending); @@ -1301,9 +1301,7 @@ impl Engine { self.turn_count += 1; // Collect and commit assistant items. Routed through - // `append_history_items` so observers (e.g. the - // Worker-side per-item session-log committer) see each item - // as it lands. + // `append_history_items` so observers see each item as it lands. let reasoning_items = self.thinking_block_collector.take_collected(); let text_blocks = self.text_block_collector.take_collected(); let tool_calls = self.tool_call_collector.take_collected(); @@ -1603,8 +1601,7 @@ impl Engine { } Ok(ToolExecutionResult::Completed(results)) => { // Route per-result pushes through the callback path so - // observers (e.g. the Worker-side per-item session-log - // committer) see each tool result as it lands. + // observers see each tool result as it lands. let items = results.into_iter().map(|result| { Item::tool_result_item( &result.tool_use_id, @@ -1707,9 +1704,9 @@ impl Engine { /// Install byte-size caps for tool execution `content`. /// - /// Passing `None` (the default) disables truncation. Higher layers - /// (e.g. Worker) translate manifest configuration into a concrete - /// [`ToolOutputLimits`] and install it here. + /// Passing `None` (the default) disables truncation. Callers translate + /// their own configuration into a concrete [`ToolOutputLimits`] and + /// install it here. pub fn set_tool_output_limits(&mut self, limits: Option) { self.tool_output_limits = limits; } diff --git a/crates/llm-engine/src/interceptor.rs b/crates/llm-engine/src/interceptor.rs index ae246e7d..3e088ced 100644 --- a/crates/llm-engine/src/interceptor.rs +++ b/crates/llm-engine/src/interceptor.rs @@ -1,9 +1,8 @@ //! Interceptor - control flow delegation for the Engine execution loop //! -//! Defines the [`Interceptor`] trait that upper layers (e.g. Worker) implement -//! to inject orchestration decisions (approval, skip, pause, abort) -//! into the Engine's turn loop without the Engine knowing about -//! higher-level concepts. +//! Defines the [`Interceptor`] trait that callers implement to inject +//! orchestration decisions (approval, skip, pause, abort) into the Engine's +//! turn loop without the Engine knowing about host-application concepts. use std::sync::Arc; @@ -132,8 +131,8 @@ pub struct ToolResultInfo { /// Intercepts the Engine execution loop at key decision points. /// /// All methods have default implementations that let the Engine -/// proceed without intervention. Upper layers (e.g. Worker) provide -/// richer implementations for approval flows, permission checks, etc. +/// proceed without intervention. Callers provide richer implementations for +/// approval flows, permission checks, etc. #[async_trait] pub trait Interceptor: Send + Sync { /// Called after receiving user input, before adding to history. @@ -149,7 +148,7 @@ pub trait Interceptor: Send + Sync { /// /// Use this for inputs that arrive from outside the LLM and need /// to be reflected in the on-disk history — notifications, - /// cross-Worker events, system reminders. Do **not** use + /// external events, system reminders. Do **not** use /// [`Self::pre_llm_request`] for that purpose: it mutates a /// per-request clone, so any committed assistant response that /// reacts to the injection would have no visible trigger on the diff --git a/crates/llm-engine/src/llm_client/auth.rs b/crates/llm-engine/src/llm_client/auth.rs index ba48fd6c..e5e061f9 100644 --- a/crates/llm-engine/src/llm_client/auth.rs +++ b/crates/llm-engine/src/llm_client/auth.rs @@ -1,15 +1,11 @@ //! `Scheme` 実装と通信層が要求する認証要件、および動的認証プロバイダ。 //! -//! マニフェスト側の型(`ModelConfig` / `SchemeKind` / `AuthRef`)は -//! `crates/manifest` に置き、llm-engine はそれを知らずに済む。 //! `AuthRequirement` は scheme が宣言する「この scheme はどんな認証を -//! 期待するか」のランタイム記述で、manifest 側の `AuthRef` との -//! 照合(`AuthRef → ResolvedAuth` 変換の適否)は `crates/provider` -//! で行う。 +//! 期待するか」のランタイム記述で、設定ファイルや環境変数などから +//! [`super::transport::ResolvedAuth`] を組み立てる責務は呼び出し側にある。 //! -//! Codex OAuth のようにリクエスト毎にトークンが変わり得る認証は -//! [`AuthProvider`] trait を `crates/provider` 側で実装し、 -//! [`super::transport::ResolvedAuth::Custom`] 経由で transport に渡す。 +//! リクエスト毎にトークンが変わり得る認証は [`AuthProvider`] trait を +//! 実装し、[`super::transport::ResolvedAuth::Custom`] 経由で transport に渡す。 use async_trait::async_trait; use reqwest::header::{HeaderName, HeaderValue}; @@ -27,16 +23,15 @@ pub enum AuthRequirement { XApiKey, /// クエリパラメータ `?=`(Gemini 形式) QueryParam { name: &'static str }, - /// 複合ヘッダ(Codex OAuth 等、`crates/provider` 側で解決) + /// 複合ヘッダ(呼び出し側が [`AuthProvider`] で解決) Custom, } /// リクエスト毎に認証ヘッダを動的に組み立てるプロバイダ。 /// -/// Codex OAuth のように access_token が refresh で更新されたり、 -/// `ChatGPT-Account-Id` / `X-OpenAI-Fedramp` のような複数ヘッダを -/// 同時に注入する必要があるケースで使う。実体は `crates/provider` -/// 側に置き、llm-engine は trait を知るだけ。 +/// access token が refresh で更新されたり、複数ヘッダを同時に注入する +/// 必要があるケースで使う。実体は呼び出し側に置き、llm-engine は +/// trait を知るだけ。 /// /// 返したヘッダはそのまま `HeaderMap` に挿入される。`Authorization` /// 含む scheme 既定の認証ヘッダは送出されないので、必要なら @@ -46,11 +41,10 @@ pub trait AuthProvider: Send + Sync + std::fmt::Debug { /// 1 リクエスト分の認証ヘッダを返す。refresh が必要なら内部で行う。 async fn headers(&self) -> Result, ClientError>; - /// ChatGPT Codex backend 向けの複合認証かどうか。 + /// Conversation header / request compression が必要な backend profile かどうか。 /// - /// transport は provider crate の具象型を知らないため、この hook だけで - /// Codex CLI 互換の wire behavior(conversation header / request compression 等) - /// を切り替える。 + /// transport は呼び出し側の具象型を知らないため、この hook だけで + /// 追加の wire behavior を切り替える。 fn is_codex_backend(&self) -> bool { false } diff --git a/crates/llm-engine/src/llm_client/scheme/mod.rs b/crates/llm-engine/src/llm_client/scheme/mod.rs index ecea20c2..8306b32d 100644 --- a/crates/llm-engine/src/llm_client/scheme/mod.rs +++ b/crates/llm-engine/src/llm_client/scheme/mod.rs @@ -45,8 +45,8 @@ pub trait Scheme: Clone + Send + Sync + 'static { /// プロバイダもあるため、モデル ID を受け取る。 fn path(&self, model_id: &str) -> String; - /// この scheme が要求する認証形式。`build_client` 時に - /// `manifest::AuthRef` と照合する。 + /// この scheme が要求する認証形式。呼び出し側は client 構築時に + /// 設定された認証情報と照合する。 fn required_auth(&self) -> AuthRequirement; /// `Content-Type` 以外の追加ヘッダ。`anthropic-version` / `anthropic-beta` 等。 @@ -78,8 +78,7 @@ pub trait Scheme: Clone + Send + Sync + 'static { /// scheme 既定の capability。モデル ID に関係なく、この wire で /// 安全に送れる最小共通項を返す。既知モデル ID の能力テーブルは - /// `provider::capability::lookup` 側(高レベル構築層)の責務で、 - /// scheme はここには関与しない。 + /// 高レベルの client 構築層の責務で、scheme はここには関与しない。 fn default_capability(&self) -> ModelCapability; /// scheme 側でサポートしていない `RequestConfig` フィールドを diff --git a/crates/llm-engine/src/llm_client/scheme/openai_responses/capability.rs b/crates/llm-engine/src/llm_client/scheme/openai_responses/capability.rs index d6257163..ce1df462 100644 --- a/crates/llm-engine/src/llm_client/scheme/openai_responses/capability.rs +++ b/crates/llm-engine/src/llm_client/scheme/openai_responses/capability.rs @@ -1,7 +1,7 @@ //! OpenAI Responses scheme の wire-level 既定 capability。 //! -//! モデル ID 固有のテーブル(`gpt-5` / `codex-` 系など)は高レベル構築層 -//! (`provider::capability`)の責務。ここでは wire の保守的 default のみ。 +//! モデル ID 固有の能力テーブルは高レベルの client 構築層の責務。 +//! ここでは wire の保守的 default のみ。 use crate::llm_client::capability::{ CacheStrategy, ModelCapability, StructuredOutput, ToolCallingSupport, diff --git a/crates/llm-engine/src/llm_client/scheme/openai_responses/events.rs b/crates/llm-engine/src/llm_client/scheme/openai_responses/events.rs index 24ac3f26..47c8233b 100644 --- a/crates/llm-engine/src/llm_client/scheme/openai_responses/events.rs +++ b/crates/llm-engine/src/llm_client/scheme/openai_responses/events.rs @@ -2,7 +2,7 @@ //! //! `response.*` 名前空間の SSE を共通の [`Event`](crate::llm_client::event::Event) //! に変換する。Responses の (output_index, content_index) 2 次元座標と -//! yoi 側 1 次元 `BlockStart/Delta/Stop::index` のマッピングは +//! この crate の 1 次元 `BlockStart/Delta/Stop::index` のマッピングは //! [`OpenAIResponsesState`] が保持する。 use std::collections::{BTreeMap, HashMap}; diff --git a/crates/llm-engine/src/llm_client/scheme/openai_responses/mod.rs b/crates/llm-engine/src/llm_client/scheme/openai_responses/mod.rs index 61256b5e..76e287a8 100644 --- a/crates/llm-engine/src/llm_client/scheme/openai_responses/mod.rs +++ b/crates/llm-engine/src/llm_client/scheme/openai_responses/mod.rs @@ -2,7 +2,7 @@ //! //! Chat Completions とは別物の item-based wire format。reasoning item と //! function_call item が first-class で、SSE イベントも `response.*` 名前空間で -//! 流れる。ChatGPT OAuth 経路 (codex) は本 scheme 必須。 +//! 流れる。 //! //! - リクエスト JSON 生成: [`request`] //! - SSE イベントパース → [`Event`](crate::llm_client::event::Event) 変換: [`events`] @@ -19,10 +19,10 @@ pub use scheme_impl::OpenAIResponsesState; /// `store` / `include_encrypted_content` / `send_max_output_tokens` / /// `send_sampling_params` は scheme 固定の wire 設定で、デフォルトは /// 公式 OpenAI Responses API 向け (stateless + ZDR + `max_output_tokens` -/// / `temperature` / `top_p` 送出可)。ChatGPT backend (codex-oauth) の -/// ように受理パラメータが subset の経路では provider 層で -/// `send_max_output_tokens=false` / `send_sampling_params=false` に -/// 上書きする。`ModelCapability` には入れない(モデル能力ではなく wire policy)。 +/// / `temperature` / `top_p` 送出可)。受理パラメータが subset の +/// 互換 backend では client 構築層で `send_max_output_tokens=false` / +/// `send_sampling_params=false` に上書きする。`ModelCapability` には +/// 入れない(モデル能力ではなく wire policy)。 #[derive(Debug, Clone)] pub struct OpenAIResponsesScheme { /// サーバ側に response を保存するか。ZDR/stateless 運用では `false`。 @@ -31,12 +31,12 @@ pub struct OpenAIResponsesScheme { /// `store=false` で reasoning を使うなら必須。 pub include_encrypted_content: bool, /// `max_output_tokens` を body に載せるか。公式 OpenAI Responses API は - /// 受理するが、ChatGPT backend (codex-oauth) は `Unsupported parameter` - /// で 400 を返すため、その経路では `false` にする。 + /// 受理するが、互換 backend によっては `Unsupported parameter` で + /// 400 を返すため、その経路では `false` にする。 pub send_max_output_tokens: bool, /// `temperature` / `top_p` を body に載せるか。公式 OpenAI Responses API - /// は受理するが、ChatGPT backend (codex-oauth) は `Unsupported parameter` - /// で 400 を返すため、その経路では `false` にする。 + /// は受理するが、互換 backend によっては `Unsupported parameter` で + /// 400 を返すため、その経路では `false` にする。 pub send_sampling_params: bool, } diff --git a/crates/llm-engine/src/llm_client/scheme/openai_responses/request.rs b/crates/llm-engine/src/llm_client/scheme/openai_responses/request.rs index 291cc3be..d487601c 100644 --- a/crates/llm-engine/src/llm_client/scheme/openai_responses/request.rs +++ b/crates/llm-engine/src/llm_client/scheme/openai_responses/request.rs @@ -38,21 +38,21 @@ pub(crate) struct ResponsesRequest { /// `["reasoning.encrypted_content"]` 等。 #[serde(skip_serializing_if = "Vec::is_empty")] pub include: Vec<&'static str>, - /// 公式 OpenAI Responses API では受理されるが、ChatGPT backend - /// (codex-oauth) は 400 で弾く。scheme の `send_max_output_tokens` - /// が `false` のときは `None` のまま送る (skip_serializing_if で除外)。 + /// 公式 OpenAI Responses API では受理されるが、互換 backend によっては + /// 400 で弾く。scheme の `send_max_output_tokens` が `false` のときは + /// `None` のまま送る (skip_serializing_if で除外)。 #[serde(skip_serializing_if = "Option::is_none")] pub max_output_tokens: Option, - /// 公式 OpenAI Responses API では受理されるが、ChatGPT backend - /// (codex-oauth) は `temperature` / `top_p` を 400 で弾く。scheme の + /// 公式 OpenAI Responses API では受理されるが、互換 backend によっては + /// `temperature` / `top_p` を 400 で弾く。scheme の /// `send_sampling_params` が `false` のときは `None` のまま送る。 #[serde(skip_serializing_if = "Option::is_none")] pub temperature: Option, #[serde(skip_serializing_if = "Option::is_none")] pub top_p: Option, - /// 会話単位の安定キー。ChatGPT backend (codex-oauth) は明示キーが - /// 無いとプロンプトキャッシュがほぼ効かない。worker 側は `SegmentId` - /// を渡す。`Request::cache_key` が `None` のときはキー自体を送らない。 + /// 会話単位の安定キー。明示キーを必要とする backend では、 + /// 呼び出し側が安定した conversation identifier を渡す。 + /// `Request::cache_key` が `None` のときはキー自体を送らない。 #[serde(skip_serializing_if = "Option::is_none")] pub prompt_cache_key: Option, } @@ -74,10 +74,9 @@ pub(crate) struct ReasoningConfig { #[serde(tag = "type", rename_all = "snake_case")] pub(crate) enum InputItem { /// 会話メッセージ。user / assistant / developer のいずれか。 - /// `Role::System` items は `developer` として投影する(ChatGPT - /// backend が `role: "system"` を拒否するため。Codex CLI も - /// system 相当の挿入には DeveloperInstructions = `role: "developer"` - /// を使う)。 + /// `Role::System` items は `developer` として投影する。OpenAI + /// Responses 互換 backend の一部は `role: "system"` を拒否するため、 + /// system 相当の挿入には `role: "developer"` を使う。 Message { role: &'static str, content: Vec, @@ -403,10 +402,9 @@ mod tests { #[test] fn system_role_item_is_projected_as_developer() { - // ChatGPT backend (codex-oauth) は input[] の `role: "system"` を - // "System messages are not allowed" で 400 拒否する。in-conversation - // な system note (notify / fs_view auto-read / compaction summary) は - // `role: "developer"` として投影し、両 backend で受理されるようにする。 + // Some compatible backends reject `role: "system"` in input[]. + // Project in-conversation system notes as `role: "developer"` so + // both official and compatible backends can accept them. let scheme = OpenAIResponsesScheme::new(); let req = Request::new() .user("hi") @@ -523,11 +521,9 @@ mod tests { fn reasoning_summary_field_is_always_serialized() { // Responses API は reasoning item に `summary` を必須で要求する。 // summary が空でも wire 上に `summary: []` として残らないと、 - // ChatGPT backend (codex-oauth) が - // 400 invalid_request_error: Missing required parameter: - // 'input[N].summary'. - // で弾く。GPT-5 + reasoning effort 未指定のターンでは summary text - // が付かないことがあるため、空のままでも skip しないこと。 + // backend によっては missing required parameter として拒否される。 + // reasoning effort 未指定のターンでは summary text が付かないことが + // あるため、空のままでも skip しないこと。 let scheme = OpenAIResponsesScheme::new(); let item = Item::reasoning("").with_encrypted_content("ENC"); let req = Request::new().user("hi").item(item); diff --git a/crates/llm-engine/src/llm_client/scheme/openai_responses/scheme_impl.rs b/crates/llm-engine/src/llm_client/scheme/openai_responses/scheme_impl.rs index e3f39a09..7c08c130 100644 --- a/crates/llm-engine/src/llm_client/scheme/openai_responses/scheme_impl.rs +++ b/crates/llm-engine/src/llm_client/scheme/openai_responses/scheme_impl.rs @@ -20,9 +20,8 @@ impl Scheme for OpenAIResponsesScheme { type State = OpenAIResponsesState; fn default_base_url(&self) -> &'static str { - // `/v1` は base_url 側に寄せる。ChatGPT OAuth 経由のときは - // `https://chatgpt.com/backend-api/codex` を base にすれば同じ - // `/responses` path で両系統を吸収できる(Codex CLI 準拠)。 + // `/v1` は base_url 側に寄せる。互換 backend を使う場合も、 + // base URL を差し替えるだけで同じ `/responses` path を使える。 "https://api.openai.com/v1" } @@ -59,16 +58,18 @@ impl Scheme for OpenAIResponsesScheme { fn validate_config(&self, config: &RequestConfig) -> Vec { let mut warnings = Vec::new(); - // ChatGPT backend (codex-oauth) は `max_output_tokens` を 400 で弾く。 - // scheme 構築時に `send_max_output_tokens=false` で組まれていれば - // body 投影は止まっているので、ユーザの意図が落ちることだけを通知する。 + // Some compatible backends reject `max_output_tokens` with HTTP 400. + // If the scheme was built with `send_max_output_tokens=false`, body + // projection is already disabled; only notify that the user's intent + // was dropped. if !self.send_max_output_tokens && config.max_tokens.is_some() { warnings.push(ConfigWarning::unsupported( "max_tokens", "OpenAI Responses (ChatGPT backend)", )); } - // 同上、`temperature` / `top_p` も ChatGPT backend では 400 で弾かれる。 + // Same for `temperature` / `top_p` on compatible backends that + // reject unsupported sampling parameters. if !self.send_sampling_params { if config.temperature.is_some() { warnings.push(ConfigWarning::unsupported( diff --git a/crates/llm-engine/src/llm_client/transport.rs b/crates/llm-engine/src/llm_client/transport.rs index 63661332..a1272099 100644 --- a/crates/llm-engine/src/llm_client/transport.rs +++ b/crates/llm-engine/src/llm_client/transport.rs @@ -28,11 +28,11 @@ use super::types::{Request, RequestConfig}; pub const DEFAULT_STREAM_OPEN_TIMEOUT: Duration = Duration::from_secs(20); pub const DEFAULT_FIRST_STREAM_EVENT_TIMEOUT: Duration = Duration::from_secs(30); -/// `AuthRef` を解決したランタイム表現。`crates/provider` が構築する。 +/// 認証設定をリクエスト時に使える形へ解決したランタイム表現。 /// /// - `None`: 認証ヘッダを送らない(Ollama 等の opt-out) /// - `ApiKey`: 静的な API key 文字列 -/// - `Custom`: リクエスト毎に動的にヘッダを組み立てる(Codex OAuth 等) +/// - `Custom`: リクエスト毎に動的にヘッダを組み立てる #[derive(Debug, Clone)] pub enum ResolvedAuth { None, @@ -226,9 +226,8 @@ impl HttpTransport { let value = HeaderValue::from_str(cache_key).map_err(|e| { ClientError::Config(format!("invalid Codex conversation header: {e}")) })?; - // Codex CLI sends hyphenated session/thread headers to the - // ChatGPT Codex backend. Keep the legacy underscore header for - // existing traces/backends while exposing the current Codex shape. + // Send both current hyphenated conversation headers and the + // legacy underscore form for compatibility with existing backends. headers.insert(HeaderName::from_static("session-id"), value.clone()); headers.insert(HeaderName::from_static("thread-id"), value.clone()); headers.insert(HeaderName::from_static("session_id"), value.clone()); diff --git a/crates/llm-engine/src/llm_client/types.rs b/crates/llm-engine/src/llm_client/types.rs index fbc62536..cd429441 100644 --- a/crates/llm-engine/src/llm_client/types.rs +++ b/crates/llm-engine/src/llm_client/types.rs @@ -1,6 +1,6 @@ //! LLM Client Common Types //! -//! Core conversation types for yoi's LLM interaction model. +//! Core conversation types for LLM interaction. //! The core abstraction is `Item` which represents different types of conversation elements: //! - Message items (user/assistant messages with content parts) //! - ToolCall items (tool invocations) @@ -521,9 +521,8 @@ pub struct Request { /// Providers without prompt caching ignore the field. pub cache_anchor: Option, /// 会話単位の安定キー。`prompt_cache_key` として送られる - /// (OpenAI Responses)。ChatGPT backend (codex-oauth) は明示キーが - /// 無いと org/project ハッシュ衝突でプロンプトキャッシュが - /// ほぼヒットしないため、worker 側で `SegmentId` を渡す運用を想定。 + /// (OpenAI Responses)。明示キーを必要とする backend では、 + /// 呼び出し側が安定した conversation identifier を渡す。 /// `cache_anchor` と違い名前空間キーであり、`prefix anchor` とは /// 別の概念。`cache_anchor` を読まない provider と同じく、 /// `prompt_cache_key` を持たない provider は無視する。 diff --git a/crates/llm-engine/src/prune.rs b/crates/llm-engine/src/prune.rs index 3ab45d89..4ad27b78 100644 --- a/crates/llm-engine/src/prune.rs +++ b/crates/llm-engine/src/prune.rs @@ -8,8 +8,8 @@ //! //! Prune は **コンテキスト射影** であり、history の変換ではない。 //! この crate が提供するのは pure な候補抽出 [`prunable_indices`] のみで、 -//! 射影の適用は上位層(`worker::prune_hook` 等)が LLM に送る一時コンテキスト -//! に対してだけ行う。Engine の永続履歴は決して変更されない。 +//! 射影の適用は LLM に送る一時コンテキストに対してだけ行う。 +//! Engine の永続履歴は決して変更されない。 //! //! 保護境界は末尾 token budget で決めるが、この crate は usage 履歴を //! 所有しない。prefix ごとの token 推定値と savings 推定は上位層から @@ -75,7 +75,7 @@ pub enum PruneDecision { } /// Optional observer invoked after each prune evaluation, regardless of -/// branch. Worker 等の上位層が install して metrics を発行する。 +/// branch. Callers can install this to publish metrics or traces. pub type PruneObserver = Box; /// Configuration for the Prune algorithm. diff --git a/crates/llm-engine/src/tool_server.rs b/crates/llm-engine/src/tool_server.rs index c7e61963..21d373ac 100644 --- a/crates/llm-engine/src/tool_server.rs +++ b/crates/llm-engine/src/tool_server.rs @@ -75,10 +75,9 @@ impl ToolServerHandle { /// Execute all pending factories and register the resulting tools. /// /// Called implicitly by `Engine::lock()` before the first turn. - /// Exposed as `pub` so higher layers (e.g. Worker) can force-materialise - /// tools earlier — for example when building a system-prompt template - /// context that needs the list of registered tool names. Redundant - /// calls are no-ops. + /// Exposed as `pub` so callers can force-materialise tools earlier — + /// for example when building a system-prompt template context that needs + /// the list of registered tool names. Redundant calls are no-ops. /// /// # Panics /// diff --git a/crates/llm-engine/src/usage_record.rs b/crates/llm-engine/src/usage_record.rs index cf3f966b..948b8cf0 100644 --- a/crates/llm-engine/src/usage_record.rs +++ b/crates/llm-engine/src/usage_record.rs @@ -2,9 +2,8 @@ //! //! 1 リクエストの送信時点での「ある history prefix 長で計測した占有量」を //! 1 件分にまとめたもの。`UsageEvent` (provider stream イベント) を -//! 受けて呼び出し側 (typically Worker) が組み立て、永続化層 -//! (session-store) に流したり、token accounting (`token_counter`) で -//! 履歴として参照したりする。 +//! 受けて呼び出し側が組み立て、永続化層に流したり、token accounting +//! (`token_counter`) で履歴として参照したりする。 /// LLM リクエスト送信時点での占有量スナップショット。 #[derive(Debug, Clone, PartialEq, Eq)]