runapi-core 0.3.5 → 0.4.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 +21 -2
- data/lib/runapi/core/client.rb +5 -2
- data/lib/runapi/core/files.rb +58 -0
- data/lib/runapi/core/http_client.rb +3 -1
- data/lib/runapi/core/uploads.rb +71 -0
- data/lib/runapi/core/version.rb +1 -1
- data/lib/runapi/core.rb +1 -0
- metadata +6 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 637b4efaf326f8a8dcc33d58d6c0679da5879960056c4040150ea497c5fc5a68
|
|
4
|
+
data.tar.gz: 9ed2208c604121e8be6ebf68c80437aa4b3338cbb6f57cd3b4923c0cd4dda4ca
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d6ec013b3c3424f8a6e32dcc0006dbd57c7e9662e09e46216d11648ea2aadabbdc244f61c559e5e33499f40483e78c5eecc8ed8908629039ab8a2d9690248878
|
|
7
|
+
data.tar.gz: 97a1416061efda6cd4d4fa47c94e29d631bea7ed4f5927bdbd75a1b9b2e37a948c94ce10a82ad52f41abf68cd83d939470748c9a3b432754df32dd849bcb049c
|
data/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# RunAPI Core Ruby SDK
|
|
2
2
|
|
|
3
|
-
The RunAPI Core Ruby SDK provides shared authentication, HTTP, retry, error, and polling primitives for RunAPI model gems. Install `runapi-core` only when you are building SDK infrastructure or shared Ruby tooling; application code should normally install a concrete model gem such as `runapi-suno`.
|
|
3
|
+
The RunAPI Core Ruby SDK provides shared authentication, HTTP, retry, error, Files, Uploads, and polling primitives for RunAPI model gems. Install `runapi-core` only when you are building SDK infrastructure or shared Ruby tooling; application code should normally install a concrete model gem such as `runapi-suno`.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -67,7 +67,7 @@ runapi_task_id = response.runapi_task_id
|
|
|
67
67
|
runapi_task_id = response.response_headers["X-RunAPI-Task-Id"]
|
|
68
68
|
```
|
|
69
69
|
|
|
70
|
-
## File Upload
|
|
70
|
+
## Temporary File Upload
|
|
71
71
|
|
|
72
72
|
```ruby
|
|
73
73
|
client = RunApi::NanoBanana::Client.new(api_key: ENV["RUNAPI_API_KEY"])
|
|
@@ -79,6 +79,25 @@ puts upload.url
|
|
|
79
79
|
> [!IMPORTANT]
|
|
80
80
|
> Uploaded file URLs expire 1 hour after creation. Pass them to a model promptly rather than storing them for later use.
|
|
81
81
|
|
|
82
|
+
## Persistent Files And Multipart Uploads
|
|
83
|
+
|
|
84
|
+
The existing `files.create` method above keeps its temporary URL behavior. Use `create_file` for a persistent File object and `uploads` when sending one or more Parts:
|
|
85
|
+
|
|
86
|
+
```ruby
|
|
87
|
+
file = client.files.create_file(file: "./knowledge.pdf")
|
|
88
|
+
content = client.files.content(file.id)
|
|
89
|
+
|
|
90
|
+
upload = client.uploads.create(
|
|
91
|
+
bytes: 1_048_576,
|
|
92
|
+
filename: "archive.bin",
|
|
93
|
+
mime_type: "application/octet-stream"
|
|
94
|
+
)
|
|
95
|
+
part = client.uploads.add_part(upload.id, data: "./archive.part-01")
|
|
96
|
+
completed = client.uploads.complete(upload.id, part_ids: [part.id])
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Use `files.list`, `retrieve`, and `delete_file` for the remaining File lifecycle. See https://runapi.ai/docs/resources/files for limits and REST examples.
|
|
100
|
+
|
|
82
101
|
## License
|
|
83
102
|
|
|
84
103
|
Licensed under the Apache License, Version 2.0.
|
data/lib/runapi/core/client.rb
CHANGED
|
@@ -3,18 +3,20 @@
|
|
|
3
3
|
module RunApi
|
|
4
4
|
module Core
|
|
5
5
|
# Base class for every RunAPI client. Resolves the API key, builds the shared
|
|
6
|
-
# HTTP client, and exposes the Universal Resources (
|
|
6
|
+
# HTTP client, and exposes the Universal Resources (Files, Uploads, account, pricing) that
|
|
7
7
|
# are available on any client regardless of which model gem was required.
|
|
8
8
|
#
|
|
9
9
|
# Provider clients inherit from this and build their model resources from the
|
|
10
10
|
# protected +http+ reader.
|
|
11
11
|
class Client
|
|
12
|
-
# @return [Files]
|
|
12
|
+
# @return [Files] Persistent File lifecycle and temporary URL upload operations.
|
|
13
13
|
attr_reader :files
|
|
14
14
|
# @return [Account] Account info and balance operations.
|
|
15
15
|
attr_reader :account
|
|
16
16
|
# @return [Pricing] Live Price Schedule lookup and Price Quote operations.
|
|
17
17
|
attr_reader :pricing
|
|
18
|
+
# @return [Uploads] Multipart Upload lifecycle operations.
|
|
19
|
+
attr_reader :uploads
|
|
18
20
|
|
|
19
21
|
def initialize(api_key: nil, **options)
|
|
20
22
|
@api_key = Core::Auth.resolve_api_key(api_key)
|
|
@@ -24,6 +26,7 @@ module RunApi
|
|
|
24
26
|
@files = Files.new(@http)
|
|
25
27
|
@account = Account.new(@http)
|
|
26
28
|
@pricing = Pricing.new(@http)
|
|
29
|
+
@uploads = Uploads.new(@http)
|
|
27
30
|
end
|
|
28
31
|
|
|
29
32
|
# Closes the SDK-created HTTP client. Injected clients remain caller-owned.
|
data/lib/runapi/core/files.rb
CHANGED
|
@@ -10,6 +10,7 @@ module RunApi
|
|
|
10
10
|
ENDPOINT = "/api/v1/files"
|
|
11
11
|
PREPARE_ENDPOINT = "#{ENDPOINT}/prepare"
|
|
12
12
|
CONFIRM_ENDPOINT = "#{ENDPOINT}/confirm"
|
|
13
|
+
PROTOCOL_ENDPOINT = "/v1/files"
|
|
13
14
|
|
|
14
15
|
class UploadResponse < RunApi::Core::BaseModel
|
|
15
16
|
required :file_name, String
|
|
@@ -20,6 +21,30 @@ module RunApi
|
|
|
20
21
|
required :expires_at, String
|
|
21
22
|
end
|
|
22
23
|
|
|
24
|
+
class FileObject < RunApi::Core::BaseModel
|
|
25
|
+
required :id, String
|
|
26
|
+
required :object, String
|
|
27
|
+
required :bytes, Integer
|
|
28
|
+
required :created_at, Integer
|
|
29
|
+
optional :expires_at, Integer
|
|
30
|
+
required :filename, String
|
|
31
|
+
required :purpose, String
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
class FileList < RunApi::Core::BaseModel
|
|
35
|
+
required :object, String
|
|
36
|
+
required :data, [FileObject]
|
|
37
|
+
optional :first_id, String
|
|
38
|
+
optional :last_id, String
|
|
39
|
+
required :has_more
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
class DeletedFile < RunApi::Core::BaseModel
|
|
43
|
+
required :id, String
|
|
44
|
+
required :object, String
|
|
45
|
+
required :deleted
|
|
46
|
+
end
|
|
47
|
+
|
|
23
48
|
RESPONSE_CLASS = UploadResponse
|
|
24
49
|
|
|
25
50
|
def initialize(http)
|
|
@@ -34,6 +59,33 @@ module RunApi
|
|
|
34
59
|
request(:post, ENDPOINT, body: compact_params(source:, file_name:), options:)
|
|
35
60
|
end
|
|
36
61
|
|
|
62
|
+
def create_file(file:, purpose: "user_data", file_name: nil, options: nil)
|
|
63
|
+
path = file_path(file)
|
|
64
|
+
body = MultipartBody.new(
|
|
65
|
+
fields: {purpose:},
|
|
66
|
+
files: {file: MultipartFile.new(path:, filename: file_name || File.basename(path))}
|
|
67
|
+
)
|
|
68
|
+
request(:post, PROTOCOL_ENDPOINT, body:, options:, response_class: FileObject)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def list(after_id: nil, limit: nil, order: nil, purpose: nil, options: nil)
|
|
72
|
+
query = URI.encode_www_form(compact_params(after: after_id, limit:, order:, purpose:))
|
|
73
|
+
path = query.empty? ? PROTOCOL_ENDPOINT : "#{PROTOCOL_ENDPOINT}?#{query}"
|
|
74
|
+
request(:get, path, options:, response_class: FileList)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def retrieve(file_id, options: nil)
|
|
78
|
+
request(:get, protocol_file_path(file_id), options:, response_class: FileObject)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def content(file_id, options: nil)
|
|
82
|
+
@http.request(:get, "#{protocol_file_path(file_id)}/content", options:, raw: true)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def delete_file(file_id, options: nil)
|
|
86
|
+
request(:delete, protocol_file_path(file_id), options:, response_class: DeletedFile)
|
|
87
|
+
end
|
|
88
|
+
|
|
37
89
|
private
|
|
38
90
|
|
|
39
91
|
def validate_source!(file:, source:)
|
|
@@ -71,6 +123,12 @@ module RunApi
|
|
|
71
123
|
|
|
72
124
|
raise ArgumentError, "file must be a file path or respond to :path"
|
|
73
125
|
end
|
|
126
|
+
|
|
127
|
+
def protocol_file_path(file_id)
|
|
128
|
+
raise ArgumentError, "file_id is required" if file_id.to_s.strip.empty?
|
|
129
|
+
|
|
130
|
+
"#{PROTOCOL_ENDPOINT}/#{URI.encode_www_form_component(file_id)}"
|
|
131
|
+
end
|
|
74
132
|
end
|
|
75
133
|
end
|
|
76
134
|
end
|
|
@@ -12,7 +12,7 @@ module RunApi
|
|
|
12
12
|
end
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
def request(method, path, body: nil, options: nil)
|
|
15
|
+
def request(method, path, body: nil, options: nil, raw: false)
|
|
16
16
|
uri = URI.join(@options.base_url, path)
|
|
17
17
|
req = build_request(method, uri, body, options)
|
|
18
18
|
max_retries = options&.max_retries || @options.max_retries
|
|
@@ -42,6 +42,8 @@ module RunApi
|
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
if response.is_a?(Net::HTTPSuccess)
|
|
45
|
+
return response.body if raw
|
|
46
|
+
|
|
45
47
|
body = parse_body(response.body)
|
|
46
48
|
return nil if body.nil?
|
|
47
49
|
return body unless body.is_a?(Hash) || body.is_a?(Array)
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RunApi
|
|
4
|
+
module Core
|
|
5
|
+
class Uploads
|
|
6
|
+
include RunApi::Core::ResourceHelpers
|
|
7
|
+
|
|
8
|
+
ENDPOINT = "/v1/uploads"
|
|
9
|
+
|
|
10
|
+
class UploadObject < RunApi::Core::BaseModel
|
|
11
|
+
required :id, String
|
|
12
|
+
required :object, String
|
|
13
|
+
required :bytes, Integer
|
|
14
|
+
required :created_at, Integer
|
|
15
|
+
required :filename, String
|
|
16
|
+
required :purpose, String
|
|
17
|
+
required :status, String
|
|
18
|
+
required :expires_at, Integer
|
|
19
|
+
optional :file, -> { Files::FileObject }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class UploadPart < RunApi::Core::BaseModel
|
|
23
|
+
required :id, String
|
|
24
|
+
required :object, String
|
|
25
|
+
required :created_at, Integer
|
|
26
|
+
required :upload_id, String
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
RESPONSE_CLASS = UploadObject
|
|
30
|
+
|
|
31
|
+
def initialize(http)
|
|
32
|
+
@http = http
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def create(bytes:, filename:, mime_type:, purpose: "user_data", options: nil)
|
|
36
|
+
request(:post, ENDPOINT, body: {bytes:, filename:, mime_type:, purpose:}, options:)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def add_part(upload_id, data:, file_name: nil, options: nil)
|
|
40
|
+
path = file_path(data)
|
|
41
|
+
body = MultipartBody.new(
|
|
42
|
+
files: {data: MultipartFile.new(path:, filename: file_name || File.basename(path))}
|
|
43
|
+
)
|
|
44
|
+
request(:post, "#{upload_path(upload_id)}/parts", body:, options:, response_class: UploadPart)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def complete(upload_id, part_ids:, options: nil)
|
|
48
|
+
request(:post, "#{upload_path(upload_id)}/complete", body: {part_ids:}, options:)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def cancel(upload_id, options: nil)
|
|
52
|
+
request(:post, "#{upload_path(upload_id)}/cancel", body: {}, options:)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
def file_path(file)
|
|
58
|
+
return file if file.is_a?(String)
|
|
59
|
+
return file.path if file.respond_to?(:path)
|
|
60
|
+
|
|
61
|
+
raise ArgumentError, "data must be a file path or respond to :path"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def upload_path(upload_id)
|
|
65
|
+
raise ArgumentError, "upload_id is required" if upload_id.to_s.strip.empty?
|
|
66
|
+
|
|
67
|
+
"#{ENDPOINT}/#{URI.encode_www_form_component(upload_id)}"
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
data/lib/runapi/core/version.rb
CHANGED
data/lib/runapi/core.rb
CHANGED
|
@@ -20,6 +20,7 @@ require_relative "core/http_client"
|
|
|
20
20
|
require_relative "core/polling"
|
|
21
21
|
require_relative "core/resource_helpers"
|
|
22
22
|
require_relative "core/files"
|
|
23
|
+
require_relative "core/uploads"
|
|
23
24
|
require_relative "core/account"
|
|
24
25
|
require_relative "core/pricing"
|
|
25
26
|
require_relative "core/client"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: runapi-core
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- RunAPI
|
|
@@ -30,9 +30,9 @@ dependencies:
|
|
|
30
30
|
- !ruby/object:Gem::Version
|
|
31
31
|
version: '4'
|
|
32
32
|
description: The RunAPI Core Ruby SDK provides shared authentication, HTTP, retry,
|
|
33
|
-
error, and polling primitives for RunAPI model gems. Install `runapi-core`
|
|
34
|
-
when you are building SDK infrastructure or shared Ruby tooling; application
|
|
35
|
-
should normally install a concrete model gem such as `runapi-suno`.
|
|
33
|
+
error, Files, Uploads, and polling primitives for RunAPI model gems. Install `runapi-core`
|
|
34
|
+
only when you are building SDK infrastructure or shared Ruby tooling; application
|
|
35
|
+
code should normally install a concrete model gem such as `runapi-suno`.
|
|
36
36
|
email:
|
|
37
37
|
- contact@runapi.ai
|
|
38
38
|
executables: []
|
|
@@ -59,6 +59,7 @@ files:
|
|
|
59
59
|
- lib/runapi/core/resource_helpers.rb
|
|
60
60
|
- lib/runapi/core/response.rb
|
|
61
61
|
- lib/runapi/core/types.rb
|
|
62
|
+
- lib/runapi/core/uploads.rb
|
|
62
63
|
- lib/runapi/core/version.rb
|
|
63
64
|
homepage: https://runapi.ai/models
|
|
64
65
|
licenses:
|
|
@@ -84,7 +85,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
84
85
|
- !ruby/object:Gem::Version
|
|
85
86
|
version: '0'
|
|
86
87
|
requirements: []
|
|
87
|
-
rubygems_version: 4.0.
|
|
88
|
+
rubygems_version: 4.0.10
|
|
88
89
|
specification_version: 4
|
|
89
90
|
summary: RunAPI Core Ruby SDK
|
|
90
91
|
test_files: []
|