LemonRouter.RunProcess.CompactionTrigger (lemon_router v0.1.0)

View Source

Context-window overflow detection and preemptive compaction triggering.

Handles extraction of completion event fields (answer, error, usage, resume, engine), context-overflow detection, and marking sessions for compaction when usage approaches the model's context window limit.

Summary

Functions

context_length_exceeded_error?(err)

@spec context_length_exceeded_error?(term()) :: boolean()

extract_completed_answer(event)

@spec extract_completed_answer(LemonCore.Event.t() | term()) :: binary() | nil

extract_completed_engine(event)

@spec extract_completed_engine(LemonCore.Event.t() | term()) :: binary() | nil

extract_completed_ok_and_error(event)

@spec extract_completed_ok_and_error(LemonCore.Event.t() | term()) ::
  {boolean(), term()}

extract_completed_resume(event)

@spec extract_completed_resume(LemonCore.Event.t() | term()) :: term()

extract_completed_usage(event)

@spec extract_completed_usage(LemonCore.Event.t() | term()) :: map() | nil

extract_from_completed_or_payload(arg1, field)

@spec extract_from_completed_or_payload(LemonCore.Event.t() | term(), atom()) ::
  term()

maybe_mark_pending_compaction_near_limit(state, event)

@spec maybe_mark_pending_compaction_near_limit(map(), LemonCore.Event.t() | term()) ::
  :ok

maybe_reset_resume_on_context_overflow(state, event)

@spec maybe_reset_resume_on_context_overflow(map(), LemonCore.Event.t() | term()) ::
  :ok

maybe_store_chat_state(state, event)

@spec maybe_store_chat_state(map(), LemonCore.Event.t() | term()) :: :ok

Persist the run's resume token as chat state when a run completes.

The router owns this write. The gateway used to do it from its own finalization path, but the completion event carries :resume all the way here (see extract_completed_resume/1), so the write belonged on the side that already observes completions — and having both write it made the ownership ambiguous.

Skipped on context overflow: maybe_reset_resume_on_context_overflow/2 clears chat state in that case, and storing a token we are about to delete would race it.

normalize_resume_token(tok)

@spec normalize_resume_token(term()) :: LemonCore.ResumeToken.t() | nil

safe_error_label(err)

@spec safe_error_label(term()) :: String.t() | nil

usage_input_tokens(usage)

@spec usage_input_tokens(map() | term()) :: non_neg_integer() | nil