exa-ai 0.11.2 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +112 -0
- data/exe/exa-ai +28 -1
- data/exe/exa-ai-agent-run-cancel +90 -0
- data/exe/exa-ai-agent-run-create +278 -0
- data/exe/exa-ai-agent-run-delete +96 -0
- data/exe/exa-ai-agent-run-events +105 -0
- data/exe/exa-ai-agent-run-get +90 -0
- data/exe/exa-ai-agent-run-list +94 -0
- data/lib/exa/cli/formatters/agent_run_formatter.rb +149 -0
- data/lib/exa/client.rb +77 -0
- data/lib/exa/resources/agent_run.rb +54 -0
- data/lib/exa/resources/agent_run_event_list.rb +21 -0
- data/lib/exa/resources/agent_run_list.rb +18 -0
- data/lib/exa/services/agent_run_cancel.rb +32 -0
- data/lib/exa/services/agent_run_create.rb +33 -0
- data/lib/exa/services/agent_run_delete.rb +37 -0
- data/lib/exa/services/agent_run_events.rb +28 -0
- data/lib/exa/services/agent_run_get.rb +33 -0
- data/lib/exa/services/agent_run_list.rb +41 -0
- data/lib/exa/services/agent_run_stream.rb +110 -0
- data/lib/exa/services/parameter_converter.rb +2 -0
- data/lib/exa/version.rb +1 -1
- data/lib/exa.rb +11 -0
- metadata +18 -1
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../resources/agent_run"
|
|
4
|
+
|
|
5
|
+
module Exa
|
|
6
|
+
module Services
|
|
7
|
+
class AgentRunDelete
|
|
8
|
+
def initialize(connection, run_id:)
|
|
9
|
+
@connection = connection
|
|
10
|
+
@run_id = run_id
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def call
|
|
14
|
+
response = @connection.delete("/agent/runs/#{@run_id}")
|
|
15
|
+
body = response.body
|
|
16
|
+
|
|
17
|
+
# ponytail: 204-vs-200 unconfirmed; nil-guarded. Confirm against live API.
|
|
18
|
+
if body.nil? || body.empty?
|
|
19
|
+
return Resources::AgentRun.new(id: @run_id, object: "agent_run", status: "deleted")
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
Resources::AgentRun.new(
|
|
23
|
+
id: body["id"],
|
|
24
|
+
object: body["object"],
|
|
25
|
+
status: body["status"],
|
|
26
|
+
stop_reason: body["stopReason"],
|
|
27
|
+
created_at: body["createdAt"],
|
|
28
|
+
completed_at: body["completedAt"],
|
|
29
|
+
request: body["request"],
|
|
30
|
+
output: body["output"],
|
|
31
|
+
usage: body["usage"],
|
|
32
|
+
cost_dollars: body["costDollars"]
|
|
33
|
+
)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../resources/agent_run_event_list"
|
|
4
|
+
|
|
5
|
+
module Exa
|
|
6
|
+
module Services
|
|
7
|
+
class AgentRunEvents
|
|
8
|
+
def initialize(connection, run_id:, **params)
|
|
9
|
+
@connection = connection
|
|
10
|
+
@run_id = run_id
|
|
11
|
+
@params = params
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def call
|
|
15
|
+
response = @connection.get("/agent/runs/#{@run_id}/events", @params)
|
|
16
|
+
body = response.body
|
|
17
|
+
|
|
18
|
+
# Confirmed live: GET /agent/runs/{id}/events returns a paginated list
|
|
19
|
+
# {object: "list", data: [...], hasMore, nextCursor}.
|
|
20
|
+
Resources::AgentRunEventList.new(
|
|
21
|
+
data: body["data"] || [],
|
|
22
|
+
has_more: body["hasMore"],
|
|
23
|
+
next_cursor: body["nextCursor"]
|
|
24
|
+
)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../resources/agent_run"
|
|
4
|
+
|
|
5
|
+
module Exa
|
|
6
|
+
module Services
|
|
7
|
+
class AgentRunGet
|
|
8
|
+
def initialize(connection, run_id:, **params)
|
|
9
|
+
@connection = connection
|
|
10
|
+
@run_id = run_id
|
|
11
|
+
@params = params
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def call
|
|
15
|
+
response = @connection.get("/agent/runs/#{@run_id}", @params)
|
|
16
|
+
body = response.body
|
|
17
|
+
|
|
18
|
+
Resources::AgentRun.new(
|
|
19
|
+
id: body["id"],
|
|
20
|
+
object: body["object"],
|
|
21
|
+
status: body["status"],
|
|
22
|
+
stop_reason: body["stopReason"],
|
|
23
|
+
created_at: body["createdAt"],
|
|
24
|
+
completed_at: body["completedAt"],
|
|
25
|
+
request: body["request"],
|
|
26
|
+
output: body["output"],
|
|
27
|
+
usage: body["usage"],
|
|
28
|
+
cost_dollars: body["costDollars"]
|
|
29
|
+
)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../resources/agent_run"
|
|
4
|
+
require_relative "../resources/agent_run_list"
|
|
5
|
+
|
|
6
|
+
module Exa
|
|
7
|
+
module Services
|
|
8
|
+
class AgentRunList
|
|
9
|
+
def initialize(connection, **params)
|
|
10
|
+
@connection = connection
|
|
11
|
+
@params = params
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def call
|
|
15
|
+
response = @connection.get("/agent/runs", @params)
|
|
16
|
+
body = response.body
|
|
17
|
+
|
|
18
|
+
data = body["data"].map do |run_data|
|
|
19
|
+
Resources::AgentRun.new(
|
|
20
|
+
id: run_data["id"],
|
|
21
|
+
object: run_data["object"],
|
|
22
|
+
status: run_data["status"],
|
|
23
|
+
stop_reason: run_data["stopReason"],
|
|
24
|
+
created_at: run_data["createdAt"],
|
|
25
|
+
completed_at: run_data["completedAt"],
|
|
26
|
+
request: run_data["request"],
|
|
27
|
+
output: run_data["output"],
|
|
28
|
+
usage: run_data["usage"],
|
|
29
|
+
cost_dollars: run_data["costDollars"]
|
|
30
|
+
)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
Resources::AgentRunList.new(
|
|
34
|
+
data: data,
|
|
35
|
+
has_more: body["hasMore"],
|
|
36
|
+
next_cursor: body["nextCursor"]
|
|
37
|
+
)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
require_relative "parameter_converter"
|
|
3
|
+
require_relative "../resources/agent_run"
|
|
4
|
+
|
|
5
|
+
# ponytail: copied AnswerStream's SSE parser rather than extracting a shared module — agent frames add event:/id: lines and the two may diverge. Extract only if a third SSE consumer appears.
|
|
6
|
+
|
|
7
|
+
module Exa
|
|
8
|
+
module Services
|
|
9
|
+
class AgentRunStream
|
|
10
|
+
TERMINAL_EVENTS = %w[agent_run.completed agent_run.failed agent_run.cancelled].freeze
|
|
11
|
+
|
|
12
|
+
def initialize(connection, **params)
|
|
13
|
+
@connection = connection
|
|
14
|
+
@params = params
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Streams SSE frames to the block as (event_type, data). Returns the final
|
|
18
|
+
# AgentRun built from the terminal event's payload (completed/failed/
|
|
19
|
+
# cancelled), or nil if the stream ended before a terminal event arrived.
|
|
20
|
+
def call(&block)
|
|
21
|
+
raise ArgumentError, "block required for streaming" unless block_given?
|
|
22
|
+
|
|
23
|
+
@buffer = ""
|
|
24
|
+
@final_payload = nil
|
|
25
|
+
|
|
26
|
+
# Capture the terminal payload as it streams, then forward to the caller.
|
|
27
|
+
interceptor = proc do |event_type, data|
|
|
28
|
+
@final_payload = data if TERMINAL_EVENTS.include?(event_type)
|
|
29
|
+
block.call(event_type, data)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
body = ParameterConverter.convert(@params)
|
|
33
|
+
|
|
34
|
+
@connection.post("/agent/runs", body) do |req|
|
|
35
|
+
req.headers["Accept"] = "text/event-stream"
|
|
36
|
+
req.options.on_data = proc do |chunk|
|
|
37
|
+
@buffer += chunk
|
|
38
|
+
process_sse_buffer(&interceptor)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
process_remaining_buffer(&interceptor) if @buffer.length.positive?
|
|
43
|
+
|
|
44
|
+
@final_payload && Resources::AgentRun.from_response(@final_payload)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
def process_sse_buffer
|
|
50
|
+
return if @buffer.empty?
|
|
51
|
+
|
|
52
|
+
parts = @buffer.split("\n\n")
|
|
53
|
+
|
|
54
|
+
if @buffer.end_with?("\n\n")
|
|
55
|
+
complete_parts = parts
|
|
56
|
+
@buffer = ""
|
|
57
|
+
else
|
|
58
|
+
complete_parts = parts[0...-1]
|
|
59
|
+
@buffer = parts.last || ""
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
complete_parts.each do |frame|
|
|
63
|
+
next if frame.empty?
|
|
64
|
+
|
|
65
|
+
event_type = nil
|
|
66
|
+
data_json = nil
|
|
67
|
+
|
|
68
|
+
frame.split("\n").each do |line|
|
|
69
|
+
if line.start_with?("event: ")
|
|
70
|
+
event_type = line.sub(/^event: /, "").strip
|
|
71
|
+
elsif line.start_with?("data: ")
|
|
72
|
+
data_json = line.sub(/^data: /, "").strip
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
next if data_json.nil?
|
|
77
|
+
|
|
78
|
+
begin
|
|
79
|
+
data = JSON.parse(data_json)
|
|
80
|
+
yield(event_type, data)
|
|
81
|
+
rescue JSON::ParserError
|
|
82
|
+
# Skip lines that aren't valid JSON
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def process_remaining_buffer
|
|
88
|
+
event_type = nil
|
|
89
|
+
data_json = nil
|
|
90
|
+
|
|
91
|
+
@buffer.split("\n").each do |line|
|
|
92
|
+
if line.start_with?("event: ")
|
|
93
|
+
event_type = line.sub(/^event: /, "").strip
|
|
94
|
+
elsif line.start_with?("data: ")
|
|
95
|
+
data_json = line.sub(/^data: /, "").strip
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
return if data_json.nil?
|
|
100
|
+
|
|
101
|
+
begin
|
|
102
|
+
data = JSON.parse(data_json)
|
|
103
|
+
yield(event_type, data)
|
|
104
|
+
rescue JSON::ParserError
|
|
105
|
+
# Skip lines that aren't valid JSON
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
data/lib/exa/version.rb
CHANGED
data/lib/exa.rb
CHANGED
|
@@ -12,6 +12,9 @@ require_relative "exa/resources/find_similar_result"
|
|
|
12
12
|
require_relative "exa/resources/contents_result"
|
|
13
13
|
require_relative "exa/resources/research_task"
|
|
14
14
|
require_relative "exa/resources/research_list"
|
|
15
|
+
require_relative "exa/resources/agent_run"
|
|
16
|
+
require_relative "exa/resources/agent_run_list"
|
|
17
|
+
require_relative "exa/resources/agent_run_event_list"
|
|
15
18
|
require_relative "exa/resources/answer"
|
|
16
19
|
require_relative "exa/resources/context_result"
|
|
17
20
|
require_relative "exa/resources/webset_collection"
|
|
@@ -32,6 +35,13 @@ require_relative "exa/services/get_contents"
|
|
|
32
35
|
require_relative "exa/services/research_get"
|
|
33
36
|
require_relative "exa/services/research_start"
|
|
34
37
|
require_relative "exa/services/research_list"
|
|
38
|
+
require_relative "exa/services/agent_run_create"
|
|
39
|
+
require_relative "exa/services/agent_run_stream"
|
|
40
|
+
require_relative "exa/services/agent_run_get"
|
|
41
|
+
require_relative "exa/services/agent_run_list"
|
|
42
|
+
require_relative "exa/services/agent_run_cancel"
|
|
43
|
+
require_relative "exa/services/agent_run_delete"
|
|
44
|
+
require_relative "exa/services/agent_run_events"
|
|
35
45
|
require_relative "exa/services/answer"
|
|
36
46
|
require_relative "exa/services/answer_stream"
|
|
37
47
|
require_relative "exa/services/context"
|
|
@@ -74,6 +84,7 @@ require_relative "exa/cli/formatters/webset_search_formatter"
|
|
|
74
84
|
require_relative "exa/cli/formatters/context_formatter"
|
|
75
85
|
require_relative "exa/cli/formatters/contents_formatter"
|
|
76
86
|
require_relative "exa/cli/formatters/research_formatter"
|
|
87
|
+
require_relative "exa/cli/formatters/agent_run_formatter"
|
|
77
88
|
require_relative "exa/cli/formatters/answer_formatter"
|
|
78
89
|
require_relative "exa/cli/formatters/webset_formatter"
|
|
79
90
|
require_relative "exa/cli/formatters/webset_item_formatter"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: exa-ai
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.12.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Benjamin Jackson
|
|
@@ -146,6 +146,12 @@ files:
|
|
|
146
146
|
- LICENSE
|
|
147
147
|
- README.md
|
|
148
148
|
- exe/exa-ai
|
|
149
|
+
- exe/exa-ai-agent-run-cancel
|
|
150
|
+
- exe/exa-ai-agent-run-create
|
|
151
|
+
- exe/exa-ai-agent-run-delete
|
|
152
|
+
- exe/exa-ai-agent-run-events
|
|
153
|
+
- exe/exa-ai-agent-run-get
|
|
154
|
+
- exe/exa-ai-agent-run-list
|
|
149
155
|
- exe/exa-ai-answer
|
|
150
156
|
- exe/exa-ai-context
|
|
151
157
|
- exe/exa-ai-enrichment-cancel
|
|
@@ -188,6 +194,7 @@ files:
|
|
|
188
194
|
- lib/exa.rb
|
|
189
195
|
- lib/exa/cli/base.rb
|
|
190
196
|
- lib/exa/cli/error_handler.rb
|
|
197
|
+
- lib/exa/cli/formatters/agent_run_formatter.rb
|
|
191
198
|
- lib/exa/cli/formatters/answer_formatter.rb
|
|
192
199
|
- lib/exa/cli/formatters/contents_formatter.rb
|
|
193
200
|
- lib/exa/cli/formatters/context_formatter.rb
|
|
@@ -207,6 +214,9 @@ files:
|
|
|
207
214
|
- lib/exa/constants/websets.rb
|
|
208
215
|
- lib/exa/error.rb
|
|
209
216
|
- lib/exa/middleware/raise_error.rb
|
|
217
|
+
- lib/exa/resources/agent_run.rb
|
|
218
|
+
- lib/exa/resources/agent_run_event_list.rb
|
|
219
|
+
- lib/exa/resources/agent_run_list.rb
|
|
210
220
|
- lib/exa/resources/answer.rb
|
|
211
221
|
- lib/exa/resources/contents_result.rb
|
|
212
222
|
- lib/exa/resources/context_result.rb
|
|
@@ -226,6 +236,13 @@ files:
|
|
|
226
236
|
- lib/exa/resources/webset_enrichment_collection.rb
|
|
227
237
|
- lib/exa/resources/webset_item_collection.rb
|
|
228
238
|
- lib/exa/resources/webset_search.rb
|
|
239
|
+
- lib/exa/services/agent_run_cancel.rb
|
|
240
|
+
- lib/exa/services/agent_run_create.rb
|
|
241
|
+
- lib/exa/services/agent_run_delete.rb
|
|
242
|
+
- lib/exa/services/agent_run_events.rb
|
|
243
|
+
- lib/exa/services/agent_run_get.rb
|
|
244
|
+
- lib/exa/services/agent_run_list.rb
|
|
245
|
+
- lib/exa/services/agent_run_stream.rb
|
|
229
246
|
- lib/exa/services/answer.rb
|
|
230
247
|
- lib/exa/services/answer_stream.rb
|
|
231
248
|
- lib/exa/services/context.rb
|