Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

applyCaching gate keyed on model-name substring, not capability — non-Anthropic cacheable models (openrouter/openai-compatible/copilot) never get cache_control

オープン
#965 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

評価

難易度
5/5
見積もり時間
1週間以上
初心者へのやさしさ
45/100
issue の種類
バグ
明瞭さ
おおむね明確
活発さ
静か
技術スタック
typescript
領域
ai, backend

調査の方向性

packages/opencode/src/provider/transform.ts から始め、特に 285-297 行の ProviderTransform.message() と 196-210 行の applyCaching() を確認し、その後 provider.ts:787 の capabilities スキーマを調べます。ゲートを、サポートされているプロバイダーオプションおよび既存のカバレッジと比較します。選択した capability またはプロバイダールールが明確に定義され、Anthropic 以外のキャッシュ可能なモデルが意図したディレクティブを受け取り、既存の動作を後退させないことが完了条件です。

索引モデルが issue の本文から書いたものです。

説明

Description

Found via static analysis of prompt-cache anti-patterns (CacheLint), then confirmed by hand on main @ f0fb1e1.

ProviderTransform.message() decides whether to call applyCaching() using a hard-coded model-name gate (packages/opencode/src/provider/transform.ts:285-297):

if (
  (model.providerID === "anthropic" ||
    model.providerID === "google-vertex-anthropic" ||
    model.providerID === "altimate-backend" ||
    model.api.id.includes("anthropic") ||
    model.api.id.includes("claude") ||
    model.id.includes("anthropic") ||
    model.id.includes("claude") ||
    model.api.npm === "@ai-sdk/anthropic") &&
  model.api.npm !== "@ai-sdk/gateway"
) {
  msgs = applyCaching(msgs, model)
}

But applyCaching() itself already defines cache directives for five providers, not just Anthropic (transform.ts:196-210):

const providerOptions = {
  anthropic:        { cacheControl:         { type: "ephemeral" } },
  openrouter:       { cacheControl:         { type: "ephemeral" } },
  bedrock:          { cachePoint:           { type: "default"   } },
  openaiCompatible: { cache_control:        { type: "ephemeral" } },
  copilot:          { copilot_cache_control:{ type: "ephemeral" } },
}

So a cacheable model served through openrouter / openai-compatible / copilot whose id contains neither claude nor anthropic (e.g. a GPT / Gemini / Qwen / Kimi routed through those providers) never enters applyCaching() and never gets a cache breakpoint — even though the function clearly intends to cache it.

This is an under-claim: caching silently fails to engage. It is not cache-busting, and Anthropic-named models are unaffected.

Impact

For an affected model, the system prefix (system prompt + tool schema + earlier turns) is re-sent at full input price on every turn instead of being read from cache. On long agentic loops that is roughly the usual cached-prefix discount forgone each turn, plus higher TTFB — for exactly the self-hosted / BYO-LLM users the project targets. The blast radius is bounded to non-Anthropic-named models that genuinely support explicit cache_control via openrouter/openai-compatible/copilot.

Steps to reproduce

  1. Configure a cacheable model through openrouter (or openai-compatible / copilot) whose id does not contain claude/anthropic (e.g. an OpenRouter-served model that honors cache_control).
  2. Run a multi-turn session.
  3. Observe that no cacheControl/cache_control provider option is stamped on the system/last-user blocks (the applyCaching branch is skipped), so the prefix is billed as fresh input every turn.

Suggested fix (for discussion)

Decouple the applyCaching gate from the model-name list and drive it off an explicit capability/provider-support signal, so the gate matches the set of providers applyCaching already knows how to cache:

  • introduce a capabilities.caching flag on the model (the capabilities schema in provider.ts:787 currently has no caching field), populated from the model registry; or
  • gate on a per-provider "supports prompt cache" set covering anthropic / openrouter / bedrock / openaiCompatible / copilot (the same five keys already in providerOptions).

I want to flag the design angle rather than send a drive-by PR: this is a hot path, and #891 was deliberately deferred for the same "needs design + careful testing, don't regress gateway cache-hit rates" reason. It also overlaps with #891's goal of having a single source of truth for the cache-control gate. I'm happy to open a PR if a maintainer confirms the preferred shape (capability flag vs provider set) and that emitting these directives for non-Anthropic providers is intended.

Caveat: confirmed present and unguarded on main @ f0fb1e1; line numbers may drift.

主要言語
TypeScript
スター
813
フォーク
134
平均マージ
2日 3時間
マージ済み PR(30日)
65

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

AltimateAI/altimate-code のほかの issue

AltimateAI/altimate-code の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。