Class: Ask::ACP::ReplayClient
- Inherits:
-
Object
- Object
- Ask::ACP::ReplayClient
- Defined in:
- lib/ask/acp/replay_client.rb
Overview
ACP client that replays pre-recorded interactions from a fixture file.
Like VCR for stdio — no subprocess, instant response, deterministic. Records are newline-delimited JSON with format:
{"request": {...}} ← request sent to agent
{"response": {...}} ← response from agent (or mock)
{"notification": {...}} ← async notification from agent
Instance Attribute Summary collapse
-
#fixture_path ⇒ Object
readonly
Returns the value of attribute fixture_path.
-
#running ⇒ Object
readonly
Returns the value of attribute running.
Instance Method Summary collapse
-
#initialize(fixture_path:) ⇒ ReplayClient
constructor
A new instance of ReplayClient.
-
#initialize!(client_name:, client_version:, capabilities: {}) ⇒ Object
── ACP Methods (same interface as Client) ──.
- #on_notification(&handler) ⇒ Object
- #running? ⇒ Boolean
- #session_close(session_id) ⇒ Object
- #session_list(cwd: nil) ⇒ Object
- #session_load(session_id) ⇒ Object
- #session_new(cwd: ".", model: nil) ⇒ Object
- #session_prompt(session_id, prompt, timeout: nil, &block) ⇒ Object
- #session_resume(session_id) ⇒ Object
- #start ⇒ Object
- #stop ⇒ Object
Constructor Details
#initialize(fixture_path:) ⇒ ReplayClient
Returns a new instance of ReplayClient.
22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/ask/acp/replay_client.rb', line 22 def initialize(fixture_path:) @fixture_path = fixture_path @events = [] @index = 0 @running = false @initialized = false @event_handlers = [] @pending = {} @next_id = 1 @mutex = Mutex.new end |
Instance Attribute Details
#fixture_path ⇒ Object (readonly)
Returns the value of attribute fixture_path.
20 21 22 |
# File 'lib/ask/acp/replay_client.rb', line 20 def fixture_path @fixture_path end |
#running ⇒ Object (readonly)
Returns the value of attribute running.
20 21 22 |
# File 'lib/ask/acp/replay_client.rb', line 20 def running @running end |
Instance Method Details
#initialize!(client_name:, client_version:, capabilities: {}) ⇒ Object
── ACP Methods (same interface as Client) ──
54 55 56 57 58 59 |
# File 'lib/ask/acp/replay_client.rb', line 54 def initialize!(client_name:, client_version:, capabilities: {}) @initialized = true make_request("initialize", { protocolVersion: 1, clientInfo: { name: client_name, version: client_version }, capabilities: capabilities }) end |
#on_notification(&handler) ⇒ Object
48 49 50 |
# File 'lib/ask/acp/replay_client.rb', line 48 def on_notification(&handler) @mutex.synchronize { @event_handlers << handler } end |
#running? ⇒ Boolean
44 45 46 |
# File 'lib/ask/acp/replay_client.rb', line 44 def running? @running end |
#session_close(session_id) ⇒ Object
88 89 90 91 |
# File 'lib/ask/acp/replay_client.rb', line 88 def session_close(session_id) ensure_initialized! make_request(Protocol::AGENT_METHODS[:session_close], { sessionId: session_id }) end |
#session_list(cwd: nil) ⇒ Object
74 75 76 77 78 79 80 |
# File 'lib/ask/acp/replay_client.rb', line 74 def session_list(cwd: nil) ensure_initialized! params = {} params[:cwd] = cwd if cwd result = make_request(Protocol::AGENT_METHODS[:session_list], params) (result["sessions"] || result[:sessions] || []).map { |s| normalize_session(s) } end |
#session_load(session_id) ⇒ Object
68 69 70 71 72 |
# File 'lib/ask/acp/replay_client.rb', line 68 def session_load(session_id) ensure_initialized! result = make_request(Protocol::AGENT_METHODS[:session_load], { sessionId: session_id }) normalize_session(result) end |
#session_new(cwd: ".", model: nil) ⇒ Object
61 62 63 64 65 66 |
# File 'lib/ask/acp/replay_client.rb', line 61 def session_new(cwd: ".", model: nil) ensure_initialized! params = { cwd: cwd, mcpServers: [] } params[:model] = model if model normalize_session(make_request(Protocol::AGENT_METHODS[:session_new], params)) end |
#session_prompt(session_id, prompt, timeout: nil, &block) ⇒ Object
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/ask/acp/replay_client.rb', line 93 def session_prompt(session_id, prompt, timeout: nil, &block) ensure_initialized! prompt_blocks = prompt.is_a?(Array) ? prompt : [{ type: "text", text: prompt.to_s }] params = { sessionId: session_id, prompt: prompt_blocks } # Same block form as Client: a temporary handler that streams events # as { method:, params: } before the response arrives. handler = nil if block handler = ->(msg) { block.call(method: msg["method"], params: msg["params"] || {}) if msg["method"] } on_notification(&handler) end begin # Dispatch any notifications before the response while @index < @events.length event = @events[@index] break if event.key?("response") if event.key?("notification") dispatch_event(event["notification"]) end @index += 1 end # Get the response event = @events[@index] @index += 1 if event && event["response"] result = event["response"]["result"] error = event["response"]["error"] raise Error.new("[#{error["code"]}] #{error["message"]}") if error result else { "status" => "completed" } end ensure @mutex.synchronize { @event_handlers.delete(handler) } if handler end end |
#session_resume(session_id) ⇒ Object
82 83 84 85 86 |
# File 'lib/ask/acp/replay_client.rb', line 82 def session_resume(session_id) ensure_initialized! result = make_request(Protocol::AGENT_METHODS[:session_resume], { sessionId: session_id }) normalize_session(result) end |
#start ⇒ Object
34 35 36 37 |
# File 'lib/ask/acp/replay_client.rb', line 34 def start load_fixture @running = true end |
#stop ⇒ Object
39 40 41 42 |
# File 'lib/ask/acp/replay_client.rb', line 39 def stop @running = false @initialized = false end |