Skip to content

feat(coding-agent): derive the projected-history ceiling from the model context window - #5189

Closed
mdwsk88 wants to merge 1 commit into
lidge-jun:devfrom
mdwsk88:feat/coding-agent-window-derived-history-cap
Closed

mdwsk88 wants to merge 1 commit into
lidge-jun:devfrom
mdwsk88:feat/coding-agent-window-derived-history-cap

Conversation

@mdwsk88

@mdwsk88 mdwsk88 commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

Summary

  • The coding-agent CLIs (CodeBuddy Code, Qoder CLI) replay the whole conversation each turn by projecting it into one legal user message over stream-json stdin. The projection had a flat 200k-character history ceiling: roughly 50k tokens of English or code, a fraction of what even a 128k-token model holds, and far below the newer 1M-token families — long sessions silently lost their earliest context at a bound unrelated to the model.
  • This PR derives the ceiling from the declared model context window on the routed provider row (modelContextWindows resolved per model through the established modelRecordValue lookup, then the provider-wide contextWindow): window × 3 chars per token, floored at the legacy 200k flat cap so small windows and missing metadata keep today behavior exactly, capped by a 4M hard ceiling so runaway metadata cannot unbound stdin. The ceiling remains a runaway-memory bound; caller-side compaction stays the token authority.
  • The resolution lives once in the shared runCodingAgentTurn driver, so both CodeBuddy and Qoder turns get it and the family adapters are unchanged. buildConversationInput takes an optional maxHistoryChars, defaulting to the legacy cap — the pure protocol module stays process-free and the wire behavior for callers without window metadata is byte-identical.
  • This closes the metadata chain end to end: whatever the catalog and config declare as a window now governs the replay bound, so roster/catalog improvements flow into the adapter without further code changes.

Verification

  • bun test tests/providers/codebuddy-protocol.test.ts tests/providers/codebuddy-adapter.test.ts tests/providers/qoder-adapter.test.ts — 72 pass, including four new protocol unit tests (invalid or missing metadata keeps the flat cap; a small window never lowers it; a large window scales until the hard ceiling; buildConversationInput keeps 250k characters of history under a 1M-window derived cap and still truncates under the default) and one end-to-end adapter regression that runs a real injected turn with modelContextWindows and asserts the spawned CLI stdin kept the history the derived cap admits while the no-metadata path still truncates.
  • bun run typecheck — clean. bun run structure:check — clean. bun run privacy:scan — clean.
  • bun run test:changed — 21,880 tests: 21,839 pass, 38 skip, 3 fail. The three failures are the same macOS-host environment failures already verified on the base commit without this change (bubblewrap executable-permission semantics and a shim-probe timeout; see the verification note on fix(transport): fill a default User-Agent on proxy-originated provider outbound #5186). None touch the coding-agent adapter path.

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed.
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults.

Review readiness checklist

This PR stays in draft until every box below is ticked. Tick all four boxes once the requirements are met:

  • All CI tests are green on my local testing.

  • I pushed my PR to the latest dev commit.

  • I resolved all correct Codex and CodeRabbit findings.

  • My PR is ready for review.

Related: #5146 (CodeBuddy integration design), #5147 (account-roster discovery — where the model metadata starts), #5186, #5188.

…el context window

The coding-agent CLIs replay the whole conversation each turn as a single projected user message over stream-json stdin, and the projection had a flat 200k-character history ceiling: about 50k tokens of English or code, a fraction of what even a 128k-token model holds, and far below the newer 1M-token families. Derive the ceiling from the declared model context window on the routed provider row (modelContextWindows by model, then the provider-wide contextWindow): window times 3 chars per token, floored at the legacy 200k cap so small windows and missing metadata keep today behavior exactly, and capped by a 4M hard ceiling so runaway metadata cannot unbound stdin. The ceiling stays a runaway-memory bound; caller-side compaction remains the token authority.
@coderabbitai

coderabbitai Bot commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@github-actions github-actions Bot added the enhancement New feature or request label Sep 19, 2026
@github-actions

Copy link
Copy Markdown
Contributor

⏳ DRAFT

  • review readiness checklist open (0/4 boxes ticked).

What to do

  • Tick all four boxes in the PR description once you're done (currently 0/4).

Review readiness checklist

  • ⬜ All CI tests are green on my local testing.
  • ⬜ I pushed my PR to the latest dev commit.
  • ⬜ I resolved all correct Codex and CodeRabbit findings.
  • ⬜ My PR is ready for review.

0/4 boxes ticked.

This PR stays in draft until every box above is ticked.

@lidge-jun

Copy link
Copy Markdown
Owner

리뷰 · 우선순위 64 / 80

CodeBuddy와 Qoder는 한 턴마다 지금까지의 대화를 통째로 다시 넣습니다. 그 글은 사용자 메시지 하나로 합쳐져 CLI 입력으로 들어갑니다. 합친 기록의 상한이 20만 자로 고정되어 있었습니다. 모델 창이 커도 앞부분이 잘렸습니다. 글 종류에 따라 5만에서 13만 토큰 정도입니다.

이 PR은 상한을 모델 창에서 구합니다. 창의 토큰 수에 3을 곱한 값이 새 상한입니다. 그 값이 20만보다 작으면 20만으로 두고, 400만을 넘으면 400만에서 자릅니다. 창 숫자가 없거나 0이거나 무한대면 20만입니다. 계산은 runCodingAgentTurn 한곳에만 있습니다. CodeBuddy와 Qoder가 그 함수를 같이 쓰므로 둘 다 바뀝니다. buildConversationInput에 상한을 안 넘기면 예전 20만과 같습니다. 새 어댑터 테스트는 CodeBuddy만 돌립니다.

베이스는 dev입니다. 지금 tip은 efb55e71e547ac83563e1d45dd60fb0b646e6cf7이고, 패키지는 @bitkyc08/opencodex 2.60.0입니다. 그 커밋 제목은 Resolve static model policy once for catalog and routing (#5171)입니다. 이 PR 머리 f4f202ba1beb는 tip보다 3커밋 뒤입니다. 뒤처진 것은 #5167, #5187, #5171입니다. 셋 다 src/adapters/coding-agent/는 그대로입니다. types.ts / config.ts 분할과는 무관해서, 분할 때문에 닫을 건 아닙니다. 부모 스택은 없습니다. 본문이 관련으로 적은 #5186과 #5188은 User-Agent와 Alibaba 와이어라 이 변경과 다릅니다. 깃허브에서는 아직 초안입니다. 준비 체크리스트는 0/4입니다. 이 머리에서 끝난 검사는 hygiene, label, resolve-pr입니다. enforce-target은 취소됐습니다. 본문의 테스트 숫자는 이 원격 머리에서 다시 돌리지 못했습니다.

src/adapters/coding-agent/turn.ts:253 - 모델별 창이 없으면 제공자 전체 contextWindow를 씁니다. 새로 넣은 어댑터 테스트는 modelContextWindows만 넣고, 이 오른쪽 가지는 안 봅니다.

메인테이너의 판단이 필요한 지점

20만 바닥을 유지할지는 제품 선택입니다. 6만 4천 토큰 창도 20만 자를 그대로 받습니다. 테스트가 그 경우를 고정합니다. 오늘과 같습니다. 작은 창을 창 크기에 맞게 줄이는 일은 이 PR이 일부러 하지 않습니다.

글자 3 대 토큰 1도 선택입니다. 한국어는 토큰이 더 잘게 나뉘어, 같은 글자 수가 창을 넘을 수 있습니다. 본문은 이 상한을 메모리 울타리로 두고, 토큰 계산은 호출 쪽 압축이 맡는다고 합니다. runCodingAgentTurn 안에서는 압축을 하지 않습니다. 그 압축이 이 경로보다 앞에서 항상 도는지 확인해 주세요.

tip의 #5171은 모델 정책을 resolveModelPolicy 한곳에서 해석합니다. 이 PR은 그 함수를 부르지 않고, 제공자 행의 modelContextWindowscontextWindowmodelRecordValue로 직접 읽습니다. 어댑터가 받는 행이 그 해석 결과와 같은지는 이 머리에서 확인하지 못했습니다. dev에 다시 맞춘 뒤, 해석된 contextWindow를 쓸지 지금 조회를 유지할지는 정해 주세요.

너의 추천

초안을 유지하세요. 머지 추천은 아닙니다. 방향은 맞습니다. 20만 고정 칼이 큰 창의 앞 대화를 버리던 것을, 창이 클 때만 늘립니다. dev tip에 다시 맞추고 체크리스트를 채운 뒤에 초안을 풀면 됩니다.

이 댓글은 grok-bot이 작성했습니다

@lidge-jun

Copy link
Copy Markdown
Owner

landed-via #5265 (merge 447ac22 on dev). Coding-agent projected-history ceiling derived from model context window shipped there; this branch is superseded.

@lidge-jun lidge-jun closed this Sep 20, 2026
@lidge-jun

Copy link
Copy Markdown
Owner

Superseded by #5265, merged to dev as 447ac22ca65baabd573dbd429abe28ed9deff594.

Your projected-history ceiling derived from the declared context window landed unchanged in substance, carried with Co-authored-by: mdwsk88. It sits next to a separate fix for the Devin output budget, kept as a distinct quantity: the history ceiling bounds replayed input, and nothing in it decides how long a reply may run.

Closing as superseded rather than stale.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants