Skip to content

context: define the degraded modes when the provider does not speak (no usage, unclassified rejection, silent eviction) #4623

Description

@Joob1n

Summary

#4574 makes the provider the only judge of whether a request fits: Maka's own action is a reversible fold, triggered either by the previous accepted request's real usage reaching the user-declared window, or by a real provider rejection. That contract assumes the provider speaks: it reports usage, and it rejects a request that does not fit in a way Maka can classify. Three situations break that assumption. Review of #4574 (@likun666661) asked that they be named and given a visible behaviour rather than left as open semantics. This issue is that definition, plus the two small follow-up PRs that close the remaining gap.

The three degraded modes

Provider behaviour What Maka can observe Behaviour after #4574 Gap
No usage in the response (some relays) token_usage has no lastRequestAnchor No baseline → no proactive fold, no eviction check. Provider rejection still folds once and retries. The composer indicator (#4576) shows a dash with "provider reported no usage". None planned. OpenAI-compatible chat now requests stream usage by default (stream_options.include_usage); a relay that rejects that field fails with its own error, by contract (test in #4574).
Rejection Maka cannot classify (unknown wording) An ordinary 4xx provider error Turn ends with the provider's message; the user's message stays editable; manual /compact then resend works. Same as before #4574. PR E: a "compact and retry" action on that error, running the same fold-once → resend path the runtime already has for classified overflow. UI + one runtime command.
Silent eviction / rewrite (Ollama truncating to num_ctx, server-side compaction) Usage stops growing or drops while Maka only appended Declared window: the proactive fold keeps usage under it; the provider never truncates. Undeclared: within one send the context_provider_dropping note fires from step 2 on; across turns nothing fires#4574's own live Ollama run plateaued at 3716 input tokens with no signal. PR D: apply the same rule at the turn boundary: first request of a send has inputTokens at or below the persisted anchor's, and Maka neither folded nor pruned before sending → write the context_provider_dropping note. Not-greater, not strictly-fewer: a provider truncating to its own window reports the same total on every later request, which is exactly the plateau the live Ollama run showed. Note only; no action; a rare false positive after a user edit costs one line of text.

What "no declared window" guarantees, stated

  • Maka never fails a request on its own estimate. Every send goes to the provider.
  • A classified rejection is folded once and resent; a second rejection is reported as the provider's error.
  • With usage present, a shrinking or stalled input while Maka only appended is reported as a note (mid-turn today, cross-turn after PR D).
  • Without usage, the only signal is the indicator's dash; compaction is reactive only.

Plan

Refs #4559, #4574

中文

#4574 之后,"请求放不放得下"只由供应商裁决,Maka 自己只做可逆的折叠。这个约定的前提是供应商会说话:返回 usage,拒绝时报 Maka 认得出的错。三种情况打破这个前提,评审要求把它们的信号和行为写清楚,而不是留成开放语义。

  • 不返回 usage:没有基线,不主动折叠;供应商拒绝时仍折叠一次重发;指示器显示横线。不再另做。
  • 拒绝但认不出措辞:turn 以供应商原文报错结束,消息可编辑;手动 /compact 后重发可用。PR E 加一个"压缩后重试"按钮,走同一条 fold-once → 重发。
  • 静默丢弃(Ollama 截到 num_ctx):设了窗口就被主动折叠兜住;没设窗口时,同一次发送内第 2 步起能检测,跨 turn 抓不到。PR D 把同一条规则挪到 turn 边界:新发送第一步 input 不高于上次落盘 anchor,且发送前没折叠没归档,就写提示(持平就是 Ollama 那种截断的信号,严格小于抓不到)。只写提示,不做动作。

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions