phaseo_sdk 2.1.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 +7 -0
- data/README.md +99 -0
- data/examples/models.rb +16 -0
- data/lib/gen/client.rb +86 -0
- data/lib/gen/models.rb +2124 -0
- data/lib/gen/operations.rb +512 -0
- data/lib/index.rb +974 -0
- data/lib/phaseo_sdk/model_ids.rb +1840 -0
- data/lib/phaseo_sdk/version.rb +3 -0
- data/lib/phaseo_sdk.rb +2 -0
- data/phaseo_sdk.gemspec +22 -0
- data/tests/api_key_mutations_test.rb +39 -0
- data/tests/api_key_test.rb +30 -0
- data/tests/api_keys_test.rb +30 -0
- data/tests/async_jobs_test.rb +13 -0
- data/tests/batches_test.rb +124 -0
- data/tests/chat_test.rb +75 -0
- data/tests/current_key_test.rb +29 -0
- data/tests/devtools_test.rb +364 -0
- data/tests/endpoints_test.rb +27 -0
- data/tests/files_test.rb +67 -0
- data/tests/generation_test.rb +29 -0
- data/tests/health_test.rb +26 -0
- data/tests/lifecycle_test.rb +55 -0
- data/tests/models_test.rb +39 -0
- data/tests/organisations_test.rb +36 -0
- data/tests/pricing_calculate_test.rb +36 -0
- data/tests/pricing_models_test.rb +42 -0
- data/tests/provider_ops_test.rb +44 -0
- data/tests/smoke_chat.rb +22 -0
- data/tests/smoke_responses.rb +25 -0
- data/tests/smoke_responses_sdk.rb +30 -0
- data/tests/video_test.rb +152 -0
- data/tests/workspace_mutations_test.rb +39 -0
- data/tests/workspaces_test.rb +45 -0
- metadata +81 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 442f1a085f0d40c85475b6a863d76ca22105403424729088e1e4a65ef7432b41
|
|
4
|
+
data.tar.gz: 011eb38bf5ec8a6c589afdce5f20f2e640a6943135b98405f8b4c48101042404
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 3d4d6647a4f64012a98f0875647eb6ad2d5a9bd27f982ba0f1762d36e33c223ca93e66b69b9e563ebad9dbc2f03f7d0569cedf788a6f823ec5e89cb4b1fb07d9
|
|
7
|
+
data.tar.gz: 71af9cc544a1d6285cd06b1d4a15bd0dac40aa355648ddc77fe415b62a4e9479ca32c534e3751e83154153535acbc845978ebb4a4cd1cef90029dcf62c64cb73
|
data/README.md
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Phaseo Ruby SDK
|
|
2
|
+
|
|
3
|
+
Official Ruby SDK for Phaseo Gateway.
|
|
4
|
+
|
|
5
|
+
RubyGems package name: `phaseo_sdk`
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
gem "phaseo_sdk"
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Then run:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
bundle install
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Quick start
|
|
20
|
+
|
|
21
|
+
```ruby
|
|
22
|
+
require "phaseo_sdk"
|
|
23
|
+
|
|
24
|
+
client = PhaseoSdk::Phaseo.new(
|
|
25
|
+
api_key: ENV.fetch("PHASEO_API_KEY"),
|
|
26
|
+
base_path: ENV.fetch("PHASEO_BASE_URL", "https://api.phaseo.app/v1")
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
response = client.create_response(
|
|
30
|
+
model: "google/gemma-3-27b:free",
|
|
31
|
+
input: "Reply with: Ruby SDK works"
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
puts response["id"]
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Common methods
|
|
38
|
+
|
|
39
|
+
- `create_response(payload)`
|
|
40
|
+
- `create_chat_completion(payload)`
|
|
41
|
+
- `list_models(options = {})`
|
|
42
|
+
- `list_organisations(options = {})` for paginated `/organisations` discovery
|
|
43
|
+
- `list_pricing_models(options = {})` for `/pricing/models` catalogue pricing discovery
|
|
44
|
+
- `calculate_pricing(payload)` for `/pricing/calculate` usage estimation
|
|
45
|
+
- `list_providers(options = {})`, `get_credits(options = {})`, `get_activity(options = {})`, and `get_analytics(options = {})` for provider discovery and management-key usage surfaces
|
|
46
|
+
- `list_api_keys(options = {})` for management-key `/keys` discovery
|
|
47
|
+
- `create_api_key(payload)`, `update_api_key(id, payload)`, and `delete_api_key(id)` for management-key API-key lifecycle changes
|
|
48
|
+
- `get_api_key(id)` for management-key `/keys/{id}` lookup
|
|
49
|
+
- `list_workspaces(options = {})`, `get_workspace(id)`, `create_workspace(payload)`, `update_workspace(id, payload)`, and `delete_workspace(id)` for management-key workspace lifecycle management
|
|
50
|
+
- `get_current_api_key`
|
|
51
|
+
- `health`
|
|
52
|
+
- `get_model_deprecation_info(model_id)`
|
|
53
|
+
- `validate_model(model_id)`
|
|
54
|
+
|
|
55
|
+
Model discovery supports the public `/models` filters, including `provider`, `provider_status`, `provider_routing_status`, `model_routing_status`, `capability_status`, `provider_availability_status`, `provider_availability_reason`, `status`, `organisation`, `endpoints`, `input_types`, `output_types`, `params`, `availability`, `limit`, and `offset`.
|
|
56
|
+
|
|
57
|
+
Use `provider_availability_reason` with `availability: "all"` when you want rollout-state entries such as `preview_only`, `provider_not_ready`, `gated`, `access_limited`, `region_limited`, `project_limited`, `paused`, or `soft_blocked`. Use `capability_status` with `availability: "all"` when you want non-routable endpoint mappings such as `coming_soon` or `internal_testing`.
|
|
58
|
+
|
|
59
|
+
```ruby
|
|
60
|
+
models = client.list_models(
|
|
61
|
+
provider: "anthropic",
|
|
62
|
+
provider_status: "beta,not_ready",
|
|
63
|
+
provider_availability_reason: "preview_only,provider_not_ready",
|
|
64
|
+
capability_status: "coming_soon,internal_testing",
|
|
65
|
+
availability: "all",
|
|
66
|
+
)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Async job websocket helpers
|
|
70
|
+
|
|
71
|
+
Batch and video operations can expose a websocket lifecycle stream at `/v1/async/{kind}/{id}/ws`.
|
|
72
|
+
|
|
73
|
+
```ruby
|
|
74
|
+
batch_socket_url = client.batch_websocket_url("batch_123", interval_ms: 1500)
|
|
75
|
+
video_socket_url = client.video_websocket_url("video_123", close_on_terminal: true)
|
|
76
|
+
generic_socket_url = client.get_async_job_websocket_url("video", "video_123")
|
|
77
|
+
resource_socket_url = client.async_jobs.websocket_url("video", "video_123")
|
|
78
|
+
|
|
79
|
+
puts batch_socket_url
|
|
80
|
+
puts video_socket_url
|
|
81
|
+
puts generic_socket_url
|
|
82
|
+
puts resource_socket_url
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Free and paid models
|
|
86
|
+
|
|
87
|
+
- Models with `:free` in the model ID can be called with zero deposited credits.
|
|
88
|
+
- Paid models require available wallet balance.
|
|
89
|
+
|
|
90
|
+
## Environment variables
|
|
91
|
+
|
|
92
|
+
- `PHASEO_API_KEY` (required unless passed in code)
|
|
93
|
+
- `PHASEO_BASE_URL` (optional, defaults to `https://api.phaseo.app/v1`)
|
|
94
|
+
|
|
95
|
+
## Regeneration and local checks
|
|
96
|
+
|
|
97
|
+
- Regenerate generated client: `pnpm openapi:gen:ruby`
|
|
98
|
+
- Build gem: `pnpm --filter @phaseo/ruby-sdk run build`
|
|
99
|
+
- Test: `pnpm --filter @phaseo/ruby-sdk run test`
|
data/examples/models.rb
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require_relative '../lib/index'
|
|
2
|
+
|
|
3
|
+
api_key = ENV['PHASEO_API_KEY']
|
|
4
|
+
raise 'Set PHASEO_API_KEY' unless api_key
|
|
5
|
+
|
|
6
|
+
client = PhaseoSdk::Phaseo.new(api_key: api_key)
|
|
7
|
+
resp = client.list_models(
|
|
8
|
+
provider: "anthropic",
|
|
9
|
+
provider_status: "beta,not_ready",
|
|
10
|
+
provider_availability_reason: "preview_only,provider_not_ready",
|
|
11
|
+
capability_status: "coming_soon,internal_testing",
|
|
12
|
+
availability: "all",
|
|
13
|
+
limit: 5,
|
|
14
|
+
)
|
|
15
|
+
models = resp.is_a?(Hash) ? (resp["models"] || []) : []
|
|
16
|
+
puts "models: #{models.length}"
|
data/lib/gen/client.rb
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
require "net/http"
|
|
3
|
+
require "uri"
|
|
4
|
+
|
|
5
|
+
module Phaseo
|
|
6
|
+
module Gen
|
|
7
|
+
class RequestError < StandardError
|
|
8
|
+
attr_reader :status_code, :response_body
|
|
9
|
+
|
|
10
|
+
def initialize(status_code:, response_body:, status_message: nil, message: nil)
|
|
11
|
+
super(message || build_message(status_code, response_body, status_message))
|
|
12
|
+
@status_code = status_code
|
|
13
|
+
@response_body = response_body
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def build_message(status_code, response_body, status_message)
|
|
19
|
+
trimmed = response_body.to_s.strip
|
|
20
|
+
prefix = status_message.to_s.strip.empty? ? "Request failed: #{status_code}" : "Request failed: #{status_code} #{status_message}"
|
|
21
|
+
return prefix if trimmed.empty?
|
|
22
|
+
|
|
23
|
+
"#{prefix} #{trimmed}"
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
class Client
|
|
28
|
+
def initialize(base_url:, headers: {})
|
|
29
|
+
@base_url = base_url.chomp("/")
|
|
30
|
+
@headers = headers
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def build_request(method:, path:, query: nil, headers: nil, body: nil)
|
|
34
|
+
uri = URI.join(@base_url + "/", path.sub(%r{^/}, ""))
|
|
35
|
+
uri.query = URI.encode_www_form(query) if query && !query.empty?
|
|
36
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
37
|
+
http.use_ssl = uri.scheme == "https"
|
|
38
|
+
request_class = Net::HTTP.const_get(method.capitalize)
|
|
39
|
+
req = request_class.new(uri)
|
|
40
|
+
(@headers || {}).merge(headers || {}).each { |k, v| req[k] = v }
|
|
41
|
+
if body
|
|
42
|
+
req["Content-Type"] = "application/json"
|
|
43
|
+
req.body = JSON.dump(body)
|
|
44
|
+
end
|
|
45
|
+
[http, req]
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def request(method:, path:, query: nil, headers: nil, body: nil)
|
|
49
|
+
http, req = build_request(method:, path:, query:, headers:, body:)
|
|
50
|
+
response = http.request(req)
|
|
51
|
+
unless response.is_a?(Net::HTTPSuccess)
|
|
52
|
+
raise RequestError.new(status_code: response.code.to_i, response_body: response.body.to_s)
|
|
53
|
+
end
|
|
54
|
+
return nil if response.body.nil? || response.body.empty?
|
|
55
|
+
JSON.parse(response.body)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def request_bytes(method:, path:, query: nil, headers: nil, body: nil)
|
|
59
|
+
http, req = build_request(method:, path:, query:, headers:, body:)
|
|
60
|
+
response = http.request(req)
|
|
61
|
+
unless response.is_a?(Net::HTTPSuccess)
|
|
62
|
+
raise RequestError.new(status_code: response.code.to_i, response_body: response.body.to_s)
|
|
63
|
+
end
|
|
64
|
+
response.body.to_s.b
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def request_stream(method:, path:, query: nil, headers: nil, body: nil)
|
|
68
|
+
return enum_for(__method__, method:, path:, query:, headers:, body:) unless block_given?
|
|
69
|
+
http, req = build_request(method:, path:, query:, headers: (headers || {}).merge("Accept" => "text/event-stream"), body:)
|
|
70
|
+
http.request(req) do |response|
|
|
71
|
+
unless response.is_a?(Net::HTTPSuccess)
|
|
72
|
+
raise RequestError.new(status_code: response.code.to_i, response_body: response.body.to_s)
|
|
73
|
+
end
|
|
74
|
+
buffer = String.new
|
|
75
|
+
response.read_body do |chunk|
|
|
76
|
+
buffer << chunk
|
|
77
|
+
while (index = buffer.index("\n"))
|
|
78
|
+
yield buffer.slice!(0, index + 1).sub(/\r?\n\z/, "")
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
yield buffer unless buffer.empty?
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|