Module: RubynCode::Context::ContextCollapse
- Defined in:
- lib/rubyn_code/context/context_collapse.rb
Overview
Lightweight context reduction that removes old conversation turns without calling the LLM. Runs before auto-compact — if collapse alone brings the context under threshold, the expensive LLM summarization is skipped.
Keeps the first message (initial user request), the most recent N exchanges, and replaces everything in between with a “[earlier conversation snipped]” marker.
Constant Summary collapse
- SNIP_MARKER =
'[%d earlier messages snipped for context efficiency]'- CHARS_PER_TOKEN =
4
Class Method Summary collapse
-
.call(messages, threshold:, keep_recent: 6) ⇒ Array<Hash>?
Returns a collapsed copy of messages if doing so brings the estimated token count under threshold.
- .first_real_user_message(messages) ⇒ Object
- .system_injection?(msg) ⇒ Boolean
Class Method Details
.call(messages, threshold:, keep_recent: 6) ⇒ Array<Hash>?
Returns a collapsed copy of messages if doing so brings the estimated token count under threshold. Returns nil if collapse isn’t sufficient (caller should fall through to full auto-compact).
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/rubyn_code/context/context_collapse.rb', line 23 def self.call(, threshold:, keep_recent: 6) return nil if .size <= keep_recent + 2 # Always preserve the very first message (may contain critical # system-level context like auth shims) AND the first real user # message so the agent retains the user's original request. anchors = build_anchors() recent = .last(keep_recent) snipped_count = .size - keep_recent - anchors.size collapsed = [ *anchors, { role: 'user', content: format(SNIP_MARKER, snipped_count) }, *recent ] # Only use collapse if it gets us under threshold estimated = (JSON.generate(collapsed).length.to_f / CHARS_PER_TOKEN).ceil estimated <= threshold ? collapsed : nil rescue JSON::GeneratorError nil end |
.first_real_user_message(messages) ⇒ Object
66 67 68 69 70 |
# File 'lib/rubyn_code/context/context_collapse.rb', line 66 def self.() [1..].find do |msg| msg[:role] == 'user' && !system_injection?(msg) end end |
.system_injection?(msg) ⇒ Boolean
61 62 63 64 |
# File 'lib/rubyn_code/context/context_collapse.rb', line 61 def self.system_injection?(msg) content = msg[:content] content.is_a?(String) && content.start_with?('[system]') end |