Class: Rubino::Context::PromptAssembler
- Inherits:
-
Object
- Object
- Rubino::Context::PromptAssembler
- 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
-
.reset_all_snapshots! ⇒ Object
Test/teardown hook.
-
.reset_snapshot!(session_id) ⇒ Object
Drops the cached snapshot for a session so the next assembly captures fresh memory state.
-
.snapshot_for(session_id) ⇒ Object
Returns the cached snapshot for a session, computing it via the supplied block on first access.
Instance Method Summary collapse
-
#build ⇒ Object
Builds and returns the full message array for LLM submission.
-
#initialize(session:, memory_context:, config:, agent_definition: nil, ignore_rules: false) ⇒ PromptAssembler
constructor
A new instance of PromptAssembler.
Constructor Details
#initialize(session:, memory_context:, config:, agent_definition: nil, ignore_rules: false) ⇒ PromptAssembler
Returns a new instance of PromptAssembler.
46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/rubino/context/prompt_assembler.rb', line 46 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.
41 42 43 |
# File 'lib/rubino/context/prompt_assembler.rb', line 41 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).
36 37 38 |
# File 'lib/rubino/context/prompt_assembler.rb', line 36 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.
26 27 28 29 30 |
# File 'lib/rubino/context/prompt_assembler.rb', line 26 def snapshot_for(session_id) @snapshots_mutex.synchronize do @snapshots[session_id] ||= yield end end |
Instance Method Details
#build ⇒ Object
Builds and returns the full message array for LLM submission
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/rubino/context/prompt_assembler.rb', line 61 def build = [] # Single system message. The content is split into a STABLE PREFIX # (identity / product / env / user-profile snapshot / skills / project # context) and a VOLATILE TAIL (freshly-retrieved relevant-memories + # the post-compaction session-summary). The prefix carries the prompt- # cache breakpoint (#311); the tail — which can change turn-to-turn — # sits AFTER it so the cached bytes stay byte-stable. Both regions live # in ONE role:"system" entry (#253), built as a Content::Raw array of # text blocks when caching is on, or a plain joined String otherwise. << { role: "system", content: system_content } # 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| << msg.to_context end end |