Ctrl K
ComunidadGuías…

lib/agent-models.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
/**
 * Shared registry (client + server) of models and settings of the agent of
 * cloud code (MIN-46). NO server-only import: the model picker (UI) and the
 * server-side resolution (`lib/server/agent/model.ts`) both import it.
 */

export interface AgentModelOption {
  /** id OpenRouter au format `provider/model`. */
  id: string;
  /** label displayed in the picker. */
  label: string;
  /** short note (cost / usage). */
  hint?: string;
}

/**
 * Curated labels from a handful of top models. The picker (launch +
 * personal default) is NO LONGER limited to this list: it searches the entire index
 * OpenRouter (`/api/agent/models`) and formats the names via `formatModelName`.
 * This list is only used to provide nice known labels (cf. `model-display`)
 * for these specific ids. Ids to be confirmed against OpenRouter index `/models`.
 */
export const AGENT_ALLOWED_MODELS: AgentModelOption[] = [
  { id: "deepseek/deepseek-v4-flash", label: "DeepSeek V4 Flash", hint: "Économique · défaut" },
  { id: "anthropic/claude-sonnet-5", label: "Claude Sonnet 5", hint: "Équilibré, fort en code" },
  { id: "anthropic/claude-opus-4.8", label: "Claude Opus 4.8", hint: "Qualité maximale" },
];

// ── Context compaction (hardening, very long runs) ────────────────────
/** Beyond this estimation of tokens, we summarize the middle of the history.
 Conservative (proxy characters/4 which underestimates the code): safe on models
 with a wide window (DeepSeek, Claude…). */
export const AGENT_COMPACT_TOKEN_THRESHOLD = 70_000;
/**
 * CALIBRATED VALUE of the compaction threshold: what it is worth at the reference price, and
 * the FLOOR under which it never falls (see `agentCompactThreshold`, which
 * transposes it to the price of the run model — it was a fixed ceiling until MIN-248).
 *
 * Window ≠ budget. The threshold was 75% of the window, and the models we
 * use have windows from 1M to 1.05M → effective threshold ~787,000 tokens, i.e.
 * 5× our largest checkpoint. Result: compaction never ran a single time in production (MIN-113). What caps a long session is not
 * the window, it is the COST PER ROUND: we return the entire history with each call
 * and — measured, not assumed — prompt caching does not amortize it (the breakpoints of
 * `caching.ts` are at the top of the history, so the block hidden remains frozen while
 * the history increases; the observed cost sticks to the full input rate to within 2%).
 *
 * 120,000 comes from the MIN-101 measurement of 814 agent `ai_usage` calls:
 * • p90 of real context = 86,815 tokens → a normal session never sees it;
 * • max observed = 158,301 → a cap at 180k would NEVER trigger, this which
 * would reproduce the bug that we are correcting here;
 * • summarizing is amortized in ~1.2 rounds from 60 k, so it is the quality (do not
 * harass the short sessions) which sets the floor, not the profitability.
 * To be reviewed if the distribution of contexts changes — not to the blind man.
 */
export const AGENT_COMPACT_BASELINE_TOKENS = 120_000;
/**
 * Entry price AT WHICH the 120,000 above were calibrated: that of model
 * minddy's default at the time of measurement (`deepseek/deepseek-v4-flash`,
 * $0.14/Mtok). This is what makes the cap TRANSPOSABLE: at this price, the prompt
 * of a round costs $0.0168, and it is this COST PER ROUND — not the number of
 * tokens — that the cap actually limits.
 */
export const AGENT_COMPACT_REFERENCE_INPUT_USD_PER_MTOK = 0.14;
/**
 * How high the cap can GO for a cheap model. Twice the value
 * calibrated, and the reason is that of MIN-113: the largest context ever
 * observed on the agent is 158,301 tokens. A threshold beyond 240,000 would therefore never trigger — that is, it would not exist.
 */
export const AGENT_COMPACT_MAX_TOKENS_CEILING = 240_000;

/**
 * COMPACTION THRESHOLD of the run, derived from the model rather than written in hard copy.
 *
 * The 120,000 cap said a real thing — "a round should not cost
 * more than that to return" — but it said it in TOKENS, which does not mean la
 * same as for a model at the same price. Between `deepseek-v4-flash`
 * ($0.14/Mtok) and `claude-opus-4.8` ($5/Mtok), the same history of 120,000
 * tokens costs $0.017 or $0.60 per round: thirty-six times the difference, for a
 * safeguard supposed to limit an expense.
 *
 * The threshold is therefore read in dollars and is converted into tokens at the price of the model.
 * Three terminals, and each repairs a known fault:
 *
 * - **floor to `AGENT_COMPACT_BASELINE_TOKENS`** — we never GO
 * below the calibrated value, even for a very expensive model. Compacting earlier
 * saves nothing: the model buys back in rereads what is taken from it, and
 * is exactly MIN-248. An expensive model therefore keeps the behavior
 * of today, down to the byte.
 * - **ceiling at `AGENT_COMPACT_MAX_TOKENS_CEILING`** — a threshold that runs
 * never reach has never been triggered (MIN-113).
 * - **and always ≤ 75% of the window**: the budget cannot exceed what
 * the model can read.
 *
 * `inputUsdPerMTok` unknown (BYOK provider outside the OpenRouter catalog) or null
 * (free model) → we fall back on the calibrated value. Ignoring the price is not
 * a license to move up: it is a reason not to move.
 */
export function agentCompactThreshold(opts: {
  contextWindow?: number | null;
  inputUsdPerMTok?: number | null;
}): number {
  const fromWindow = opts.contextWindow
    ? Math.floor(opts.contextWindow * 0.75)
    : AGENT_COMPACT_TOKEN_THRESHOLD;

  const price = opts.inputUsdPerMTok;
  const affordable =
    typeof price === "number" && Number.isFinite(price) && price > 0
      ? Math.floor(
          (AGENT_COMPACT_BASELINE_TOKENS * AGENT_COMPACT_REFERENCE_INPUT_USD_PER_MTOK) / price,
        )
      : AGENT_COMPACT_BASELINE_TOKENS;

  const budget = Math.min(
    Math.max(affordable, AGENT_COMPACT_BASELINE_TOKENS),
    AGENT_COMPACT_MAX_TOKENS_CEILING,
  );
  return Math.min(fromWindow, budget);
}