Class: Rubino::Context::PromptAssembler

Inherits:
Object
  • Object
show all
Defined in:
lib/rubino/context/prompt_assembler.rb

Overview

Assembles the complete prompt from all context sources. Returns the message array (system + summary + history) for LLM submission.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(session:, memory_context:, config:, agent_definition: nil, ignore_rules: false) ⇒ PromptAssembler

Returns a new instance of PromptAssembler.



43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/rubino/context/prompt_assembler.rb', line 43

def initialize(session:, memory_context:, config:, agent_definition: nil,
               ignore_rules: false)
  @session = session
  @memory_context = memory_context
  @config = config
  @agent_definition = agent_definition
  # --ignore-rules suppresses project-context discovery
  # (AGENTS.md/CLAUDE.md/.rubino.md/.cursorrules). The flag is threaded
  # from Lifecycle so the CLI option genuinely skips discovery (#47), not
  # just the trust gate.
  @ignore_rules = ignore_rules
  @message_store = Session::Store.new
end

Class Method Details

.reset_all_snapshots!Object

Test/teardown hook. Not part of the public API.



38
39
40
# File 'lib/rubino/context/prompt_assembler.rb', line 38

def reset_all_snapshots!
  @snapshots_mutex.synchronize { @snapshots.clear }
end

.reset_snapshot!(session_id) ⇒ Object

Drops the cached snapshot for a session so the next assembly captures fresh memory state. Use this when a tool call must influence the very next turn (trade-off: the freeze stops protecting against same-turn poisoning).



33
34
35
# File 'lib/rubino/context/prompt_assembler.rb', line 33

def reset_snapshot!(session_id)
  @snapshots_mutex.synchronize { @snapshots.delete(session_id) }
end

.snapshot_for(session_id) ⇒ Object

Returns the cached snapshot for a session, computing it via the supplied block on first access. The block receives no args and must return the memory-context hash to freeze.



23
24
25
26
27
# File 'lib/rubino/context/prompt_assembler.rb', line 23

def snapshot_for(session_id)
  @snapshots_mutex.synchronize do
    @snapshots[session_id] ||= yield
  end
end

Instance Method Details

#buildObject

Builds and returns the full message array for LLM submission



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/rubino/context/prompt_assembler.rb', line 58

def build
  messages = []

  # System prompt (always first)
  messages << { role: "system", content: build_system_prompt }

  # Session summary (if compacted)
  summary = load_summary
  messages << { role: "system", content: "[Session Summary]\n#{summary}" } if summary

  # Conversation history. Repair tool pairing across the FULL list before
  # mapping to wire format — this is the defensive "net" that recovers
  # sessions already corrupted by the historical metadata-dropping bug in
  # compaction/fork (those rows exist in prod). Mirrors Claude Code's
  # pre-call sanitization: never emit an orphan tool block that 400s a
  # strict provider. Conservative by design — when in doubt, keep.
  history = repair_tool_pairs(@message_store.for_session(@session[:id]))
  history.each do |msg|
    messages << msg.to_context
  end

  messages
end