skillrouter 0.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/lib/skillrouter/client.rb +152 -0
- data/lib/skillrouter/configuration.rb +12 -0
- data/lib/skillrouter/errors.rb +9 -0
- data/lib/skillrouter/version.rb +3 -0
- data/lib/skillrouter.rb +22 -0
- metadata +49 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 86d4927e3c17824677d528040ea63bf5f763f7b981fb64e6d623785bfc34f46f
|
|
4
|
+
data.tar.gz: e1b61db17c4c136b13d05b4d1bf373e0bff04e2e9e04cb19a1b19de8f38a32f7
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 03bfaca3966c6deb0c74bd72d2c47fcb013ca769dfaeec230c8386d0297aed9af95459a7026b09b1cc632437204b090ffdde54b652f4b5ece014c95d7c10acfc
|
|
7
|
+
data.tar.gz: 51a4bcb5891e0a52b062767bc4a7ad1b91e404cd934730345285a467fee01270cad2ec43f3ad14381dc09c04178e21e47fff0a34d0095227c01a184e182fd44a
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
require "net/http"
|
|
2
|
+
require "uri"
|
|
3
|
+
require "json"
|
|
4
|
+
|
|
5
|
+
module SkillRouter
|
|
6
|
+
class Client
|
|
7
|
+
attr_reader :api_key, :base_url, :timeout, :max_retries
|
|
8
|
+
|
|
9
|
+
def initialize(api_key: nil, base_url: nil, timeout: nil, max_retries: nil)
|
|
10
|
+
config = SkillRouter.configuration
|
|
11
|
+
@api_key = api_key || config.api_key
|
|
12
|
+
@base_url = base_url || config.base_url
|
|
13
|
+
@timeout = timeout || config.timeout
|
|
14
|
+
@max_retries = max_retries || config.max_retries
|
|
15
|
+
|
|
16
|
+
raise AuthenticationError, "API key is required. Set it via SkillRouter.configure or pass api_key:" unless @api_key
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# List skills with optional filters
|
|
20
|
+
def skills(category: nil, provider: nil, search: nil, page: 1, per_page: 20)
|
|
21
|
+
params = { page: page, per_page: per_page }
|
|
22
|
+
params[:category] = category if category
|
|
23
|
+
params[:provider] = provider if provider
|
|
24
|
+
params[:search] = search if search
|
|
25
|
+
request(:get, "/v1/skills", params: params)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Get a single skill by ID or slug
|
|
29
|
+
def skill(id)
|
|
30
|
+
request(:get, "/v1/skills/#{id}")
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Discover skills using natural language
|
|
34
|
+
def discover(query, category: nil, limit: 5)
|
|
35
|
+
body = { query: query, limit: limit }
|
|
36
|
+
body[:category] = category if category
|
|
37
|
+
request(:post, "/v1/skills/discover", body: body)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Execute a skill
|
|
41
|
+
def execute(skill_id:, params:, async: false, timeout_ms: nil)
|
|
42
|
+
body = { skill_id: skill_id, params: params }
|
|
43
|
+
body[:async] = async if async
|
|
44
|
+
body[:timeout_ms] = timeout_ms if timeout_ms
|
|
45
|
+
request(:post, "/v1/execute", body: body)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# List executions
|
|
49
|
+
def executions(page: 1, per_page: 20)
|
|
50
|
+
request(:get, "/v1/executions", params: { page: page, per_page: per_page })
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Get a single execution
|
|
54
|
+
def execution(id)
|
|
55
|
+
request(:get, "/v1/executions/#{id}")
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Get usage stats
|
|
59
|
+
def usage
|
|
60
|
+
request(:get, "/v1/usage")
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Get account info
|
|
64
|
+
def account
|
|
65
|
+
request(:get, "/v1/account")
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# List skillsets
|
|
69
|
+
def skillsets
|
|
70
|
+
request(:get, "/v1/skillsets")
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Create a skillset
|
|
74
|
+
def create_skillset(name:, description: nil, skill_ids: [])
|
|
75
|
+
body = { name: name, skill_ids: skill_ids }
|
|
76
|
+
body[:description] = description if description
|
|
77
|
+
request(:post, "/v1/skillsets", body: body)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Delete a skillset
|
|
81
|
+
def delete_skillset(id)
|
|
82
|
+
request(:delete, "/v1/skillsets/#{id}")
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
private
|
|
86
|
+
|
|
87
|
+
def request(method, path, params: {}, body: nil)
|
|
88
|
+
uri = URI("#{@base_url}#{path}")
|
|
89
|
+
uri.query = URI.encode_www_form(params) unless params.empty?
|
|
90
|
+
|
|
91
|
+
retries = 0
|
|
92
|
+
begin
|
|
93
|
+
response = make_request(method, uri, body)
|
|
94
|
+
handle_response(response)
|
|
95
|
+
rescue RateLimitError, ServerError => e
|
|
96
|
+
retries += 1
|
|
97
|
+
raise e if retries > @max_retries
|
|
98
|
+
sleep(2 ** retries * 0.5)
|
|
99
|
+
retry
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def make_request(method, uri, body)
|
|
104
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
105
|
+
http.use_ssl = uri.scheme == "https"
|
|
106
|
+
http.open_timeout = @timeout
|
|
107
|
+
http.read_timeout = @timeout
|
|
108
|
+
|
|
109
|
+
req = case method
|
|
110
|
+
when :get then Net::HTTP::Get.new(uri)
|
|
111
|
+
when :post then Net::HTTP::Post.new(uri)
|
|
112
|
+
when :delete then Net::HTTP::Delete.new(uri)
|
|
113
|
+
else raise ArgumentError, "Unsupported HTTP method: #{method}"
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
req["Authorization"] = "Bearer #{@api_key}"
|
|
117
|
+
req["Content-Type"] = "application/json"
|
|
118
|
+
req["User-Agent"] = "skillrouter-ruby/#{VERSION}"
|
|
119
|
+
|
|
120
|
+
if body
|
|
121
|
+
req.body = body.to_json
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
http.request(req)
|
|
125
|
+
rescue Net::OpenTimeout, Net::ReadTimeout
|
|
126
|
+
raise TimeoutError, "Request timed out after #{@timeout}s"
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def handle_response(response)
|
|
130
|
+
body = response.body ? JSON.parse(response.body, symbolize_names: true) : {}
|
|
131
|
+
|
|
132
|
+
case response.code.to_i
|
|
133
|
+
when 200..299
|
|
134
|
+
body
|
|
135
|
+
when 401
|
|
136
|
+
raise AuthenticationError, body[:error] || "Invalid API key"
|
|
137
|
+
when 404
|
|
138
|
+
raise NotFoundError, body[:error] || "Resource not found"
|
|
139
|
+
when 422
|
|
140
|
+
raise ValidationError, body[:error] || "Validation failed"
|
|
141
|
+
when 429
|
|
142
|
+
raise RateLimitError, body[:error] || "Rate limit exceeded"
|
|
143
|
+
when 500..599
|
|
144
|
+
raise ServerError, body[:error] || "Server error (#{response.code})"
|
|
145
|
+
else
|
|
146
|
+
raise Error, body[:error] || "Unexpected response (#{response.code})"
|
|
147
|
+
end
|
|
148
|
+
rescue JSON::ParserError
|
|
149
|
+
raise Error, "Invalid JSON response from server"
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module SkillRouter
|
|
2
|
+
class Configuration
|
|
3
|
+
attr_accessor :api_key, :base_url, :timeout, :max_retries
|
|
4
|
+
|
|
5
|
+
def initialize
|
|
6
|
+
@api_key = ENV["SKILLROUTER_API_KEY"]
|
|
7
|
+
@base_url = "https://api.skillrouter.dev"
|
|
8
|
+
@timeout = 30
|
|
9
|
+
@max_retries = 2
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
module SkillRouter
|
|
2
|
+
class Error < StandardError; end
|
|
3
|
+
class AuthenticationError < Error; end
|
|
4
|
+
class RateLimitError < Error; end
|
|
5
|
+
class NotFoundError < Error; end
|
|
6
|
+
class ValidationError < Error; end
|
|
7
|
+
class ServerError < Error; end
|
|
8
|
+
class TimeoutError < Error; end
|
|
9
|
+
end
|
data/lib/skillrouter.rb
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
require_relative "skillrouter/version"
|
|
2
|
+
require_relative "skillrouter/configuration"
|
|
3
|
+
require_relative "skillrouter/client"
|
|
4
|
+
require_relative "skillrouter/errors"
|
|
5
|
+
|
|
6
|
+
module SkillRouter
|
|
7
|
+
class << self
|
|
8
|
+
attr_writer :configuration
|
|
9
|
+
|
|
10
|
+
def configuration
|
|
11
|
+
@configuration ||= Configuration.new
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def configure
|
|
15
|
+
yield(configuration)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def reset!
|
|
19
|
+
@configuration = Configuration.new
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: skillrouter
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- SkillRouter
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies: []
|
|
12
|
+
description: Discover, validate, and execute skills for AI agents via the SkillRouter
|
|
13
|
+
API. One API to give your agents access to 1,000+ tools.
|
|
14
|
+
email: developers@skillrouter.dev
|
|
15
|
+
executables: []
|
|
16
|
+
extensions: []
|
|
17
|
+
extra_rdoc_files: []
|
|
18
|
+
files:
|
|
19
|
+
- lib/skillrouter.rb
|
|
20
|
+
- lib/skillrouter/client.rb
|
|
21
|
+
- lib/skillrouter/configuration.rb
|
|
22
|
+
- lib/skillrouter/errors.rb
|
|
23
|
+
- lib/skillrouter/version.rb
|
|
24
|
+
homepage: https://skillrouter.dev
|
|
25
|
+
licenses:
|
|
26
|
+
- MIT
|
|
27
|
+
metadata:
|
|
28
|
+
homepage_uri: https://skillrouter.dev
|
|
29
|
+
source_code_uri: https://github.com/skillrouter/ruby-sdk
|
|
30
|
+
documentation_uri: https://skillrouter.dev/docs/sdk/ruby
|
|
31
|
+
bug_tracker_uri: https://github.com/skillrouter/ruby-sdk/issues
|
|
32
|
+
rdoc_options: []
|
|
33
|
+
require_paths:
|
|
34
|
+
- lib
|
|
35
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: 3.0.0
|
|
40
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
41
|
+
requirements:
|
|
42
|
+
- - ">="
|
|
43
|
+
- !ruby/object:Gem::Version
|
|
44
|
+
version: '0'
|
|
45
|
+
requirements: []
|
|
46
|
+
rubygems_version: 3.6.8
|
|
47
|
+
specification_version: 4
|
|
48
|
+
summary: Official Ruby client for the SkillRouter API
|
|
49
|
+
test_files: []
|