Skip to content

fix(cli): preserve editor context prompt prefix - #13379

Merged
marius-kilocode merged 7 commits into
mainfrom
investigate-local-model-date-prompt-issue
Aug 25, 2026
Merged

fix(cli): preserve editor context prompt prefix#13379
marius-kilocode merged 7 commits into
mainfrom
investigate-local-model-date-prompt-issue

Conversation

@marius-kilocode

@marius-kilocode marius-kilocode commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

<environment_details> is currently generated only for the newest user message in each request. On the next user turn, that synthetic part disappears from its previous position and is regenerated on the new message. Prefix caches therefore stop matching where the previous block began, even though the conversation before that point did not change.

This fixes #13336 by reconstructing a deterministic block for every retained user message. Each block uses that message's stored editor context, creation time, and the session's existing route metadata. Historical messages remain byte-identical across later turns, while the newest message still receives its current editor context. The blocks remain ephemeral prompt scaffolding: they are not written as message parts, emitted as durable events, synced, or shared.

The timezone representation is not the cache problem. 2026-08-25T12:36:48+02:00 and 2026-08-25T10:36:48Z identify the same instant, and either form is cache-safe when its bytes remain fixed. The regression came from regenerating Current time and moving the complete block between messages. This change records the user turn's creation instant as stable UTC Message time, strips fractional seconds consistently, and appends a new timestamp only with the newly appended user turn.

Regression history

Confirmed impact

The capture in #13336 used five arithmetic turns and compared each outgoing prompt byte-for-byte with its predecessor. All four boundaries diverged at the previous location of <environment_details> and discarded exactly 204 characters each. The same report measured a synthetic post-compaction turn retaining 16,172 of 24,386 characters, and a real 356,786-character session retaining only the first 70,819 characters, leaving 285,968 characters to recompute.

An independent end-to-end CLI capture reproduced the same mechanism through an OpenAI-compatible local route. On four identical turn boundaries, the unmodified 7.4.23 path retained 99.3% of the previous toy prompt and discarded 167 characters at the old block position. A stable-history path retained 100.0% and discarded zero previous characters. The smaller absolute block size reflects the smaller captured environment, not a different failure mode.

The regression assertion in this branch operates on MessageV2.toModelMessages, the serialized model-message path rather than a test-only representation. Against the base implementation, turn two is not prefixed by the complete serialized turn-one prompt. With this change, it is. Repeated loop iterations produce identical bytes, user-authored <environment_details> text is not mistaken for injected scaffolding, per-turn editor state remains attached to its original message, and route fallback is derived from stable session metadata rather than the current Agent Manager route.

Durable behavior

  • Rebuild every retained user message's block from persisted message/session metadata instead of maintaining a separate process-lifetime cache.
  • Use the user message creation time and label it Message time, avoiding a stale historical value presented as the current wall clock.
  • Preserve the session directory/worktree represented by the session's existing directory and relative path; imported messages that already contain route fields keep those fields.
  • Keep generation ephemeral so absolute paths and editor state do not gain a new durable part/event/sync footprint.
  • Continue using a per-loop map so payload-prune rebuilds and agentic loop steps reuse byte-identical strings.
  • Let compaction/history filtering bound the number of reconstructed blocks to the retained conversation.

The first request for an existing session after upgrading can acquire deterministic blocks on older retained user messages that previously had none. After that one-time prompt-shape change, subsequent requests preserve those bytes. Each retained user turn also keeps one compact environment block in model history; this intentional linear token cost replaces repeated invalidation of the much larger conversation suffix.

This does not change the content-part separator behavior tracked in #13110.

@kilo-code-bot

kilo-code-bot Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Files Reviewed (2 files)
  • packages/opencode/src/kilocode/editor-context.ts
  • packages/opencode/test/kilocode/system-prompt.test.ts
Previous Review Summaries (2 snapshots, latest commit 955b2c5)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 955b2c5)

Status: No Issues Found | Recommendation: Merge

Files Reviewed (5 files)
  • packages/opencode/src/kilocode/editor-context.ts
  • packages/opencode/src/kilocode/session/prompt.ts
  • packages/opencode/src/session/prompt.ts
  • packages/opencode/test/kilocode/editor-context-injection.test.ts
  • packages/opencode/test/kilocode/system-prompt.test.ts

Previous review (commit c658cd4)

Status: 3 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 3
Issue Details (click to expand)

SUGGESTION

File Line Issue
packages/opencode/src/session/prompt.ts 852 Keep the durable Instance stamp out of shared createUserMessage
packages/opencode/src/session/prompt.ts 141 Revert formatting-only Interface rewraps in this upstream file
packages/opencode/test/kilocode/editor-context-injection.test.ts 116 Date assertion is timezone-sensitive and does not lock time.created
Files Reviewed (6 files)
  • .changeset/stable-editor-context-prompt-prefix.md
  • packages/opencode/src/kilocode/editor-context.ts
  • packages/opencode/src/kilocode/session/prompt.ts
  • packages/opencode/src/session/prompt.ts - 2 issues
  • packages/opencode/test/kilocode/editor-context-injection.test.ts - 1 issue
  • packages/opencode/test/kilocode/system-prompt.test.ts

Fix these issues in Kilo Cloud


Reviewed by grok-4.6 · Input: 97.8K · Output: 5.3K · Cached: 205.3K

Review guidance: REVIEW.md from base branch main

Comment thread packages/opencode/src/kilocode/session/prompt.ts
Comment thread packages/opencode/src/kilocode/editor-context.ts Outdated
Comment thread packages/opencode/test/kilocode/system-prompt.test.ts Outdated

@iscekic iscekic left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved, bot remarks below, feel free to ignore

Bot remarks outside the diff lines:

  • packages/opencode/test/kilocode/editor-context-injection.test.ts:320 — The test verifies the reconstructed workspace root by computing path.resolve(session.directory, ".."), which re-derives the value with the exact same formula as the implementation, so it cannot detect a defect in the reconstruction logic. The effect is that the new route.worktree computation is effectively untested for anything beyond the trivial single-".." case.

Comment thread packages/opencode/src/kilocode/session/prompt.ts
Comment thread packages/opencode/src/kilocode/editor-context.ts
Comment thread packages/opencode/src/kilocode/session/prompt.ts
@marius-kilocode

Copy link
Copy Markdown
Collaborator Author

Map.getOrInsertComputed: explicitly informational, no action needed.
Timestamp freshness: not an actual regression. The old implementation also cached Current time for the full agentic turn through EnvCache; it did not refresh on every tool-loop step. The new Message time preserves the same per-turn behavior while making historical reconstruction stable. An agent needing the live clock can use date.
Historical block size: an intentional tradeoff required to preserve the prefix. Editor context is already capped at 200 visible files and 20 tabs, and the existing REQUEST_PRUNE_BYTES guard handles oversized payloads. Reducing historical blocks would reintroduce the cache mutation.
Worktree reconstruction: low-risk and not actionable for normal sessions. Session paths are generated relative to the current worktree and standard sessions remain inside it. Fixing arbitrary external-directory sessions would require persisting the worktree explicitly, which adds unnecessary path metadata.

@marius-kilocode
marius-kilocode merged commit a79c2f3 into main Aug 25, 2026
31 checks passed
@marius-kilocode
marius-kilocode deleted the investigate-local-model-date-prompt-issue branch August 25, 2026 12:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

<environment_details> moves to the newest user message on every turn, discarding the prompt cache

3 participants