Class: Kward::SessionStore::Session
- Inherits:
-
Object
- Object
- Kward::SessionStore::Session
- Defined in:
- lib/kward/session_store.rb
Overview
Live handle that attaches persistence callbacks to a conversation.
Once attached, every append/compact/tool execution writes a JSONL record and
advances leaf_id for session tree navigation. Avoid mutating the attached
conversation directly without these callbacks unless deliberately importing
or reconstructing history.
Instance Attribute Summary collapse
-
#created_at ⇒ Time
readonly
Creation timestamp used for sorting and filenames.
-
#cwd ⇒ String
readonly
Workspace directory recorded when the session was created.
-
#id ⇒ String
readonly
Stable persisted session id from the JSONL header.
-
#leaf_id ⇒ String?
Active tree leaf id used to restore the selected branch.
-
#name ⇒ String?
User-visible session name persisted as metadata records.
-
#parent_id ⇒ String?
readonly
Source session id when this session was cloned or forked.
-
#parent_path ⇒ String?
readonly
Source session path when this session was cloned or forked.
-
#path ⇒ String
readonly
Absolute JSONL session file path.
Instance Method Summary collapse
-
#append_branch_summary(parent_id, from_id:, summary:, details: {}) ⇒ Object
Adds a branch-summary node under
parent_idand selects it as the leaf. -
#append_label_change(entry_id, label) ⇒ Object
Persists a display label override for one tree entry.
-
#append_message(message) ⇒ Object
Persists a message as a tree entry and advances the session leaf.
-
#append_system_prompt_snapshot(system_message, reason: "changed") ⇒ Object
Persists the current system prompt as audit metadata when it changes.
-
#append_tool_execution(tool_call, content) ⇒ Object
Persists normalized tool execution metadata alongside transcript messages.
-
#attach(conversation) ⇒ Object
Installs persistence callbacks on
conversation. -
#branch(entry_id) ⇒ Object
Moves the active leaf to an existing entry so future messages fork there.
-
#compact(message) ⇒ Object
Persists a compaction summary entry and makes it the active leaf.
-
#delete_if_unused ⇒ Object
Removes this session file when it is still empty and unnamed.
-
#initialize(store:, id:, path:, cwd:, created_at:, name: nil, parent_id: nil, parent_path: nil, leaf_id: nil) ⇒ Session
constructor
Creates an object for JSONL session persistence.
-
#rename(name) ⇒ Object
Persists a user-visible session name without rewriting earlier records.
-
#reset_leaf ⇒ Object
Clears the active leaf so the next append starts a fresh root branch.
-
#update_memory_state(session_memories:, last_retrieval: nil) ⇒ Object
Persists the session memory snapshot used when the session is restored.
-
#update_runtime(provider: nil, model:, reasoning_effort:) ⇒ Object
Persists model/runtime metadata so restored sessions keep their context.
Constructor Details
#initialize(store:, id:, path:, cwd:, created_at:, name: nil, parent_id: nil, parent_path: nil, leaf_id: nil) ⇒ Session
Creates an object for JSONL session persistence.
59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/kward/session_store.rb', line 59 def initialize(store:, id:, path:, cwd:, created_at:, name: nil, parent_id: nil, parent_path: nil, leaf_id: nil) @store = store @id = id @path = path @cwd = cwd @created_at = created_at @name = name @parent_id = parent_id @parent_path = parent_path @leaf_id = leaf_id end |
Instance Attribute Details
#created_at ⇒ Time (readonly)
Returns creation timestamp used for sorting and filenames.
48 49 50 |
# File 'lib/kward/session_store.rb', line 48 def created_at @created_at end |
#cwd ⇒ String (readonly)
Returns workspace directory recorded when the session was created.
46 47 48 |
# File 'lib/kward/session_store.rb', line 46 def cwd @cwd end |
#id ⇒ String (readonly)
Returns stable persisted session id from the JSONL header.
42 43 44 |
# File 'lib/kward/session_store.rb', line 42 def id @id end |
#leaf_id ⇒ String?
Returns active tree leaf id used to restore the selected branch.
56 57 58 |
# File 'lib/kward/session_store.rb', line 56 def leaf_id @leaf_id end |
#name ⇒ String?
Returns user-visible session name persisted as metadata records.
54 55 56 |
# File 'lib/kward/session_store.rb', line 54 def name @name end |
#parent_id ⇒ String? (readonly)
Returns source session id when this session was cloned or forked.
50 51 52 |
# File 'lib/kward/session_store.rb', line 50 def parent_id @parent_id end |
#parent_path ⇒ String? (readonly)
Returns source session path when this session was cloned or forked.
52 53 54 |
# File 'lib/kward/session_store.rb', line 52 def parent_path @parent_path end |
#path ⇒ String (readonly)
Returns absolute JSONL session file path.
44 45 46 |
# File 'lib/kward/session_store.rb', line 44 def path @path end |
Instance Method Details
#append_branch_summary(parent_id, from_id:, summary:, details: {}) ⇒ Object
Adds a branch-summary node under parent_id and selects it as the leaf.
147 148 149 150 151 152 |
# File 'lib/kward/session_store.rb', line 147 def append_branch_summary(parent_id, from_id:, summary:, details: {}) record = @store.build_tree_record(@path, "branch_summary", parent_id, fromId: from_id, summary: summary, details: details || {}) @leaf_id = record[:id] @store.append_record(@path, record) record[:id] end |
#append_label_change(entry_id, label) ⇒ Object
Persists a display label override for one tree entry.
142 143 144 |
# File 'lib/kward/session_store.rb', line 142 def append_label_change(entry_id, label) @store.append_label_change(@path, entry_id, label) end |
#append_message(message) ⇒ Object
Persists a message as a tree entry and advances the session leaf.
87 88 89 90 91 |
# File 'lib/kward/session_store.rb', line 87 def () record = @store.build_tree_record(@path, "message", @leaf_id, message: ) @leaf_id = record[:id] @store.append_record(@path, record) end |
#append_system_prompt_snapshot(system_message, reason: "changed") ⇒ Object
Persists the current system prompt as audit metadata when it changes.
106 107 108 |
# File 'lib/kward/session_store.rb', line 106 def append_system_prompt_snapshot(, reason: "changed") @store.append_system_prompt_snapshot(@path, , reason: reason) end |
#append_tool_execution(tool_call, content) ⇒ Object
Persists normalized tool execution metadata alongside transcript messages.
101 102 103 |
# File 'lib/kward/session_store.rb', line 101 def append_tool_execution(tool_call, content) @store.append_record(@path, RPC::ToolEventNormalizer.new(tool_call, content: content).execution_record) end |
#attach(conversation) ⇒ Object
Installs persistence callbacks on conversation.
The callbacks are intentionally simple lambdas so Conversation remains
storage-agnostic while SessionStore remains the only owner of JSONL
record shape.
76 77 78 79 80 81 82 83 84 |
# File 'lib/kward/session_store.rb', line 76 def attach(conversation) conversation.on_append = lambda { || () } conversation.on_compact = lambda { || compact() } conversation.on_tool_execution = lambda { |tool_call, content| append_tool_execution(tool_call, content) } conversation.on_runtime_update = lambda { |provider:, model:, reasoning_effort:| update_runtime(provider: provider, model: model, reasoning_effort: reasoning_effort) } conversation. = lambda { || append_system_prompt_snapshot(, reason: "changed") } append_system_prompt_snapshot(conversation., reason: "attach") self end |
#branch(entry_id) ⇒ Object
Moves the active leaf to an existing entry so future messages fork there.
131 132 133 134 |
# File 'lib/kward/session_store.rb', line 131 def branch(entry_id) @leaf_id = entry_id.to_s.empty? ? nil : entry_id.to_s @store.append_leaf_change(@path, @leaf_id) end |
#compact(message) ⇒ Object
Persists a compaction summary entry and makes it the active leaf.
94 95 96 97 98 |
# File 'lib/kward/session_store.rb', line 94 def compact() record = @store.build_tree_record(@path, "compaction", @leaf_id, message: ) @leaf_id = record[:id] @store.append_record(@path, record) end |
#delete_if_unused ⇒ Object
Removes this session file when it is still empty and unnamed.
167 168 169 |
# File 'lib/kward/session_store.rb', line 167 def delete_if_unused @store.delete_unused_session(self) end |
#rename(name) ⇒ Object
Persists a user-visible session name without rewriting earlier records.
121 122 123 124 125 126 127 128 |
# File 'lib/kward/session_store.rb', line 121 def rename(name) @name = name.to_s.strip.empty? ? nil : name.to_s.strip @store.append_record(@path, { type: "session_info", timestamp: Time.now.utc.iso8601(3), name: @name }) end |
#reset_leaf ⇒ Object
Clears the active leaf so the next append starts a fresh root branch.
137 138 139 |
# File 'lib/kward/session_store.rb', line 137 def reset_leaf branch(nil) end |
#update_memory_state(session_memories:, last_retrieval: nil) ⇒ Object
Persists the session memory snapshot used when the session is restored.
111 112 113 114 115 116 117 118 |
# File 'lib/kward/session_store.rb', line 111 def update_memory_state(session_memories:, last_retrieval: nil) @store.append_record(@path, { type: "memory_state", timestamp: Time.now.utc.iso8601(3), sessionMemories: Array(session_memories), lastRetrieval: last_retrieval }) end |
#update_runtime(provider: nil, model:, reasoning_effort:) ⇒ Object
Persists model/runtime metadata so restored sessions keep their context.
155 156 157 158 159 160 161 162 163 164 |
# File 'lib/kward/session_store.rb', line 155 def update_runtime(provider: nil, model:, reasoning_effort:) @store.append_record(@path, { type: "session_info", timestamp: Time.now.utc.iso8601(3), name: @name, provider: provider.to_s, model: model.to_s, reasoningEffort: reasoning_effort.to_s }.delete_if { |_key, value| value.to_s.empty? }) end |