Class: PiAgent::Session
- Inherits:
-
Object
- Object
- PiAgent::Session
- Defined in:
- lib/pi_agent/session.rb
Overview
High-level agent session. Wraps a Client and exposes prompt-flow ergonomics: submit a prompt and iterate the resulting event stream.
PiAgent.session do |session|
session.prompt("Write a haiku").each do |event|
print event.delta if event.type == :message_update
end
end
A pi RPC process hosts exactly one session, so there is no create/select step — the Session is the running pi process.
v1 limitation: ‘prompt` streams one agent cycle (agent_start..agent_end). Messages queued mid-flight via `follow_up`/`steer` run in subsequent cycles; consume those by calling `prompt`-less `events` or another `prompt`. Bidirectional extension UI is not yet surfaced here.
Constant Summary collapse
- DEFAULT_EVENT_TIMEOUT =
Max time to wait for the next event before assuming the agent stalled.
300- DEFAULT_ACK_TIMEOUT =
Max time to wait for a command to be acknowledged.
30
Instance Attribute Summary collapse
-
#client ⇒ Object
readonly
Returns the value of attribute client.
Instance Method Summary collapse
-
#abort ⇒ Object
Abort the current agent run.
-
#available_models ⇒ Object
All configured models, as an array of Model hashes.
-
#clone_session ⇒ Object
Duplicate the current active branch into a new session at the current position.
- #close ⇒ Object
-
#compact(custom_instructions: nil) ⇒ Object
Manually compact the conversation context to reduce token usage.
-
#cycle_model ⇒ Object
Switch to the next configured model.
-
#follow_up(message, images: nil) ⇒ Object
Queue a follow-up message, delivered only after the agent stops.
-
#fork(entry_id) ⇒ Object
Fork a new branch from a previous user message (an entryId from ‘fork_messages`).
-
#fork_messages ⇒ Object
List user messages available for forking.
- #get_state ⇒ Object
-
#initialize(client) ⇒ Session
constructor
A new instance of Session.
-
#last_assistant_text ⇒ Object
Text of the last assistant message, or nil if there is none.
-
#messages ⇒ Object
Full conversation history, as an array of AgentMessage hashes.
-
#new_session(parent_session: nil) ⇒ Object
Start a fresh session in the same pi process.
-
#prompt(message, images: nil, event_timeout: DEFAULT_EVENT_TIMEOUT, &block) ⇒ Object
Submit a user prompt.
-
#run(message, images: nil, event_timeout: DEFAULT_EVENT_TIMEOUT) ⇒ Object
Single-shot helper mirroring pi’s print mode: submit ‘message`, drain the whole event stream, and return the final assistant text (nil if the agent produced none).
-
#session_stats ⇒ Object
Token usage, cost, and context-window stats for the current session.
-
#set_model(provider, model_id = nil) ⇒ Object
Switch to a specific model.
- #set_session_name(name) ⇒ Object
-
#set_thinking(level) ⇒ Object
Set the reasoning level: “off”, “minimal”, “low”, “medium”, “high”, or “xhigh” (xhigh is OpenAI codex-max only).
-
#steer(message, images: nil) ⇒ Object
Queue a steering message while the agent is running.
-
#switch_session(path) ⇒ Object
Load a different session file into this process.
Constructor Details
#initialize(client) ⇒ Session
Returns a new instance of Session.
28 29 30 |
# File 'lib/pi_agent/session.rb', line 28 def initialize(client) @client = client end |
Instance Attribute Details
#client ⇒ Object (readonly)
Returns the value of attribute client.
26 27 28 |
# File 'lib/pi_agent/session.rb', line 26 def client @client end |
Instance Method Details
#abort ⇒ Object
Abort the current agent run. Fire-and-forget.
73 74 75 76 |
# File 'lib/pi_agent/session.rb', line 73 def abort @client.notify("abort") self end |
#available_models ⇒ Object
All configured models, as an array of Model hashes.
95 96 97 |
# File 'lib/pi_agent/session.rb', line 95 def available_models request_data("get_available_models").fetch("models", []) end |
#clone_session ⇒ Object
Duplicate the current active branch into a new session at the current position. Returns { “cancelled” => bool }. Maps to the ‘clone` RPC command (named `clone_session` to avoid shadowing Object#clone).
167 168 169 |
# File 'lib/pi_agent/session.rb', line 167 def clone_session request_data("clone") end |
#close ⇒ Object
176 177 178 |
# File 'lib/pi_agent/session.rb', line 176 def close @client.close end |
#compact(custom_instructions: nil) ⇒ Object
Manually compact the conversation context to reduce token usage. Returns the result hash ({ “summary” =>, “firstKeptEntryId” =>, “tokensBefore” => }).
123 124 125 126 127 |
# File 'lib/pi_agent/session.rb', line 123 def compact(custom_instructions: nil) params = {} params[:customInstructions] = custom_instructions if custom_instructions request_data("compact", params) end |
#cycle_model ⇒ Object
Switch to the next configured model. Returns the new { “model” =>, “thinkingLevel” =>, “isScoped” => } hash, or {} when only one model is available.
90 91 92 |
# File 'lib/pi_agent/session.rb', line 90 def cycle_model request_data("cycle_model") end |
#follow_up(message, images: nil) ⇒ Object
Queue a follow-up message, delivered only after the agent stops.
56 57 58 59 |
# File 'lib/pi_agent/session.rb', line 56 def follow_up(, images: nil) @client.request("follow_up", (, images)).value!(timeout: DEFAULT_ACK_TIMEOUT) self end |
#fork(entry_id) ⇒ Object
Fork a new branch from a previous user message (an entryId from ‘fork_messages`). Returns { “text” => <forked-from text>, “cancelled” => bool }; `cancelled` is true if an extension vetoed it.
159 160 161 |
# File 'lib/pi_agent/session.rb', line 159 def fork(entry_id) request_data("fork", entryId: entry_id) end |
#fork_messages ⇒ Object
List user messages available for forking. Returns an array of { “entryId” => …, “text” => … } hashes.
152 153 154 |
# File 'lib/pi_agent/session.rb', line 152 def request_data("get_fork_messages").fetch("messages", []) end |
#get_state ⇒ Object
106 107 108 |
# File 'lib/pi_agent/session.rb', line 106 def get_state @client.request("get_state").value!(timeout: DEFAULT_ACK_TIMEOUT) end |
#last_assistant_text ⇒ Object
Text of the last assistant message, or nil if there is none.
116 117 118 |
# File 'lib/pi_agent/session.rb', line 116 def last_assistant_text request_data("get_last_assistant_text")["text"] end |
#messages ⇒ Object
Full conversation history, as an array of AgentMessage hashes.
111 112 113 |
# File 'lib/pi_agent/session.rb', line 111 def request_data("get_messages").fetch("messages", []) end |
#new_session(parent_session: nil) ⇒ Object
Start a fresh session in the same pi process. Pass ‘parent_session:` (a session file path) to record provenance. Returns { “cancelled” => bool }; cancelled is true if an extension vetoed it.
132 133 134 135 136 |
# File 'lib/pi_agent/session.rb', line 132 def new_session(parent_session: nil) params = {} params[:parentSession] = parent_session if parent_session request_data("new_session", params) end |
#prompt(message, images: nil, event_timeout: DEFAULT_EVENT_TIMEOUT, &block) ⇒ Object
Submit a user prompt. With a block, yields each Event until the agent finishes (agent_end), then returns self. Without a block, returns an Enumerator of Events.
‘images` accepts PiAgent::Image objects, file path strings, or raw ImageContent hashes — in any mix.
38 39 40 41 42 43 44 45 |
# File 'lib/pi_agent/session.rb', line 38 def prompt(, images: nil, event_timeout: DEFAULT_EVENT_TIMEOUT, &block) stream = event_stream("prompt", (, images), event_timeout: event_timeout) return stream unless block stream.each(&block) self end |
#run(message, images: nil, event_timeout: DEFAULT_EVENT_TIMEOUT) ⇒ Object
Single-shot helper mirroring pi’s print mode: submit ‘message`, drain the whole event stream, and return the final assistant text (nil if the agent produced none). Yields each Event to an optional block while the stream drains.
65 66 67 68 69 70 |
# File 'lib/pi_agent/session.rb', line 65 def run(, images: nil, event_timeout: DEFAULT_EVENT_TIMEOUT) prompt(, images: images, event_timeout: event_timeout) do |event| yield event if block_given? end last_assistant_text end |
#session_stats ⇒ Object
Token usage, cost, and context-window stats for the current session. Returns the data hash, including “sessionId” and “sessionFile”.
146 147 148 |
# File 'lib/pi_agent/session.rb', line 146 def session_stats request_data("get_session_stats") end |
#set_model(provider, model_id = nil) ⇒ Object
Switch to a specific model. Accepts either a single “provider/modelId” string or the two parts as separate arguments.
80 81 82 83 84 85 |
# File 'lib/pi_agent/session.rb', line 80 def set_model(provider, model_id = nil) provider, model_id = provider.split("/", 2) if model_id.nil? @client.request("set_model", provider: provider, modelId: model_id) .value!(timeout: DEFAULT_ACK_TIMEOUT) self end |
#set_session_name(name) ⇒ Object
171 172 173 174 |
# File 'lib/pi_agent/session.rb', line 171 def set_session_name(name) @client.request("set_session_name", name: name).value!(timeout: DEFAULT_ACK_TIMEOUT) self end |
#set_thinking(level) ⇒ Object
Set the reasoning level: “off”, “minimal”, “low”, “medium”, “high”, or “xhigh” (xhigh is OpenAI codex-max only).
101 102 103 104 |
# File 'lib/pi_agent/session.rb', line 101 def set_thinking(level) @client.request("set_thinking_level", level: level).value!(timeout: DEFAULT_ACK_TIMEOUT) self end |
#steer(message, images: nil) ⇒ Object
Queue a steering message while the agent is running. Delivered after the current assistant turn finishes its tool calls, before the next LLM call. Fire-and-forget; raises on rejection.
50 51 52 53 |
# File 'lib/pi_agent/session.rb', line 50 def steer(, images: nil) @client.request("steer", (, images)).value!(timeout: DEFAULT_ACK_TIMEOUT) self end |
#switch_session(path) ⇒ Object
Load a different session file into this process. Returns { “cancelled” => bool }; cancelled is true if an extension vetoed it.
140 141 142 |
# File 'lib/pi_agent/session.rb', line 140 def switch_session(path) request_data("switch_session", sessionPath: path) end |