Class: Insika::ContextTraceStore

Inherits:
Object
  • Object
show all
Defined in:
lib/insika/context_trace_store.rb

Overview

Per-session CONTEXT trace, for the Studio's breakdown-by-category card One record per session in the raw backend (scope "context_traces") — RUNTIME data, next to sessions/tasks, like the ToolTraceStore it mirrors. A capped LIST of entries, ONE PER TURN, written by the Executor after tool assembly.

Unlike the tool trace there is NO security machinery here by construction: the entry is counts and provider ids only (category -> tokens/fragments/ pinned, the tools estimate, the budget verdict) — never fragment content, so there is nothing to mask. record still rescues everything: the trace NEVER breaks the turn.

Constant Summary collapse

SCOPE =
"context_traces"
MAX_PER_SESSION =

one per turn; turns are the unit, not tool calls

50

Instance Method Summary collapse

Constructor Details

#initialize(store:) ⇒ ContextTraceStore

Returns a new instance of ContextTraceStore.



19
20
21
# File 'lib/insika/context_trace_store.rb', line 19

def initialize(store:)
  @store = store
end

Instance Method Details

#clear(session_id) ⇒ Object

Discards a session's trace (cleanup). -> bool (did it exist?).



44
# File 'lib/insika/context_trace_store.rb', line 44

def clear(session_id) = @store.delete(SCOPE, session_id.to_s)

#for_session(session_id) ⇒ Object

-> [Hash] session entries in chronological order. [] if none.



41
# File 'lib/insika/context_trace_store.rb', line 41

def for_session(session_id) = @store.get(SCOPE, session_id.to_s) || []

#record(session_id:, entry:) ⇒ Object

Writes an entry into the session — UPSERT by (task_id, turn): a turn that suspends (approval) and resumes re-runs the context stage, and the re-record replaces the first one instead of duplicating it. (turn is 1-based PER TASK, so the task is part of the key.) Missing session_id -> no-op.



28
29
30
31
32
33
34
35
36
37
38
# File 'lib/insika/context_trace_store.rb', line 28

def record(session_id:, entry:)
  sid = session_id.to_s
  return if sid.empty?

  e = sanitize(entry)
  key = [e["task_id"], e["turn"]]
  list = (@store.get(SCOPE, sid) || []).reject { |x| [x["task_id"], x["turn"]] == key } + [e]
  @store.set(SCOPE, sid, list.last(MAX_PER_SESSION))
rescue StandardError
  nil
end