seekmodo-sdk 0.5.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/.github/workflows/ci.yml +52 -0
- data/.gitignore +12 -0
- data/.rspec +2 -0
- data/.rubocop.yml +32 -0
- data/Gemfile +11 -0
- data/README.md +135 -0
- data/docs/tool-catalog.README.md +12 -0
- data/lib/seekmodo/sdk/admin/client.rb +120 -0
- data/lib/seekmodo/sdk/auto_promoter.rb +124 -0
- data/lib/seekmodo/sdk/browser_token.rb +62 -0
- data/lib/seekmodo/sdk/circuit_breaker.rb +123 -0
- data/lib/seekmodo/sdk/connector/client.rb +250 -0
- data/lib/seekmodo/sdk/events/click_beacon.rb +58 -0
- data/lib/seekmodo/sdk/events/events_queue.rb +50 -0
- data/lib/seekmodo/sdk/exceptions/breaker_open_error.rb +10 -0
- data/lib/seekmodo/sdk/exceptions/client_error.rb +66 -0
- data/lib/seekmodo/sdk/exceptions/over_quota_error.rb +10 -0
- data/lib/seekmodo/sdk/exceptions/seekmodo_error.rb +8 -0
- data/lib/seekmodo/sdk/exceptions/signature_mismatch_error.rb +10 -0
- data/lib/seekmodo/sdk/exceptions/tenant_unavailable_error.rb +10 -0
- data/lib/seekmodo/sdk/hmac_signer.rb +43 -0
- data/lib/seekmodo/sdk/mcp/client.rb +105 -0
- data/lib/seekmodo/sdk/mode.rb +41 -0
- data/lib/seekmodo/sdk/mode_fsm.rb +52 -0
- data/lib/seekmodo/sdk/pairing.rb +114 -0
- data/lib/seekmodo/sdk/signature_mismatch_tracker.rb +52 -0
- data/lib/seekmodo/sdk/storage/memory/stores.rb +100 -0
- data/lib/seekmodo/sdk/storage/protocols.rb +47 -0
- data/lib/seekmodo/sdk/storefront/client.rb +71 -0
- data/lib/seekmodo/sdk/storefront/transport.rb +198 -0
- data/lib/seekmodo/sdk/tenant_snapshot.rb +65 -0
- data/lib/seekmodo/sdk/tools/registry.rb +88 -0
- data/lib/seekmodo/sdk/version.rb +7 -0
- data/lib/seekmodo/sdk.rb +33 -0
- data/lib/seekmodo-sdk.rb +3 -0
- metadata +109 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
require "faraday"
|
|
5
|
+
|
|
6
|
+
module Seekmodo
|
|
7
|
+
module Sdk
|
|
8
|
+
module Storefront
|
|
9
|
+
class Transport
|
|
10
|
+
DEFAULT_BASE_URL = "https://gateway.seekmodo.com"
|
|
11
|
+
DEFAULT_TIMEOUT_MS = 8000
|
|
12
|
+
|
|
13
|
+
def initialize(
|
|
14
|
+
tenant_id:,
|
|
15
|
+
get_token:,
|
|
16
|
+
base_url: DEFAULT_BASE_URL,
|
|
17
|
+
connection: nil,
|
|
18
|
+
timeout_ms: DEFAULT_TIMEOUT_MS,
|
|
19
|
+
signal: nil,
|
|
20
|
+
on_error: nil,
|
|
21
|
+
get_region: nil,
|
|
22
|
+
user_agent: "seekmodo-ruby-sdk/0.5.0"
|
|
23
|
+
)
|
|
24
|
+
raise ArgumentError, "Seekmodo SDK: tenant_id is required" if tenant_id.to_s.empty?
|
|
25
|
+
raise ArgumentError, "Seekmodo SDK: get_token callback is required" unless get_token.respond_to?(:call)
|
|
26
|
+
|
|
27
|
+
@tenant_id = tenant_id
|
|
28
|
+
@get_token = get_token
|
|
29
|
+
@base_url = base_url.to_s.delete_suffix("/")
|
|
30
|
+
@timeout_ms = timeout_ms
|
|
31
|
+
@signal = signal
|
|
32
|
+
@on_error = on_error
|
|
33
|
+
@get_region = get_region
|
|
34
|
+
@user_agent = user_agent
|
|
35
|
+
@cached_token = nil
|
|
36
|
+
@owns_connection = connection.nil?
|
|
37
|
+
@connection = connection || Faraday.new do |f|
|
|
38
|
+
f.options.timeout = timeout_ms / 1000.0
|
|
39
|
+
f.adapter Faraday.default_adapter
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def clear_token_cache
|
|
44
|
+
@cached_token = nil
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def call(tool, args = {}, opts = {})
|
|
48
|
+
begin
|
|
49
|
+
call_once(tool, args, opts, false)
|
|
50
|
+
rescue AuthError => e
|
|
51
|
+
clear_token_cache
|
|
52
|
+
begin
|
|
53
|
+
call_once(tool, args, opts, true)
|
|
54
|
+
rescue StandardError => retry_err
|
|
55
|
+
@on_error&.call(retry_err, tool: tool)
|
|
56
|
+
raise retry_err
|
|
57
|
+
end
|
|
58
|
+
rescue StandardError => e
|
|
59
|
+
@on_error&.call(e, tool: tool)
|
|
60
|
+
raise e
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
private
|
|
65
|
+
|
|
66
|
+
def call_once(tool, args, opts, is_retry)
|
|
67
|
+
token = resolve_token(is_retry)
|
|
68
|
+
url = "#{@base_url}/v1/#{Faraday::Utils.escape(tool)}"
|
|
69
|
+
headers = {
|
|
70
|
+
"Content-Type" => "application/json",
|
|
71
|
+
"Authorization" => "Bearer #{token}",
|
|
72
|
+
"X-Seekmodo-Tenant" => @tenant_id,
|
|
73
|
+
"X-Seekmodo-SDK" => @user_agent,
|
|
74
|
+
"User-Agent" => @user_agent
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if @get_region
|
|
78
|
+
begin
|
|
79
|
+
slug = @get_region.call
|
|
80
|
+
headers["Seekmodo-Region"] = slug if slug.is_a?(String) && !slug.empty?
|
|
81
|
+
rescue StandardError
|
|
82
|
+
# ignore misconfigured region hook
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
timeout_ms = opts[:timeout_ms] || @timeout_ms
|
|
87
|
+
response = @connection.post(url) do |req|
|
|
88
|
+
req.headers.update(headers)
|
|
89
|
+
req.body = JSON.generate(args)
|
|
90
|
+
req.options.timeout = timeout_ms / 1000.0
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
body = response.body.to_s.empty? ? nil : safe_json(response.body)
|
|
94
|
+
|
|
95
|
+
if [401, 403].include?(response.status)
|
|
96
|
+
raise AuthError.new(response.status, body, tool)
|
|
97
|
+
end
|
|
98
|
+
if response.status == 402
|
|
99
|
+
raise QuotaError.new(body, tool)
|
|
100
|
+
end
|
|
101
|
+
if response.status >= 500
|
|
102
|
+
raise ServerError.new(response.status, body, tool)
|
|
103
|
+
end
|
|
104
|
+
unless response.status >= 200 && response.status < 300
|
|
105
|
+
raise RequestError.new(response.status, body, tool)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
body
|
|
109
|
+
rescue Faraday::Error => e
|
|
110
|
+
raise NetworkError.new(e, tool)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def resolve_token(force_refresh)
|
|
114
|
+
now_ms = (Time.now.to_f * 1000).to_i
|
|
115
|
+
if !force_refresh && @cached_token && @cached_token[:expires_at] - 10_000 > now_ms
|
|
116
|
+
return @cached_token[:token]
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
result = @get_token.call
|
|
120
|
+
if result.is_a?(String)
|
|
121
|
+
@cached_token = { token: result, expires_at: now_ms + 60_000 }
|
|
122
|
+
return result
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
if result.is_a?(Hash) && result["token"].is_a?(String) && result["expires_at"].is_a?(Numeric)
|
|
126
|
+
@cached_token = { token: result["token"], expires_at: result["expires_at"].to_i }
|
|
127
|
+
return result["token"]
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
raise ArgumentError, "Seekmodo SDK: get_token must return a string or { token, expires_at }"
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def safe_json(text)
|
|
134
|
+
JSON.parse(text)
|
|
135
|
+
rescue JSON::ParserError
|
|
136
|
+
text
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
class Error < StandardError
|
|
140
|
+
attr_reader :tool
|
|
141
|
+
|
|
142
|
+
def initialize(tool)
|
|
143
|
+
@tool = tool
|
|
144
|
+
super()
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
class AuthError < Error
|
|
149
|
+
attr_reader :status, :body
|
|
150
|
+
|
|
151
|
+
def initialize(status, body, tool)
|
|
152
|
+
@status = status
|
|
153
|
+
@body = body
|
|
154
|
+
super(tool)
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
class QuotaError < Error
|
|
159
|
+
attr_reader :body
|
|
160
|
+
|
|
161
|
+
def initialize(body, tool)
|
|
162
|
+
@body = body
|
|
163
|
+
super(tool)
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
class ServerError < Error
|
|
168
|
+
attr_reader :status, :body
|
|
169
|
+
|
|
170
|
+
def initialize(status, body, tool)
|
|
171
|
+
@status = status
|
|
172
|
+
@body = body
|
|
173
|
+
super(tool)
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
class RequestError < Error
|
|
178
|
+
attr_reader :status, :body
|
|
179
|
+
|
|
180
|
+
def initialize(status, body, tool)
|
|
181
|
+
@status = status
|
|
182
|
+
@body = body
|
|
183
|
+
super(tool)
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
class NetworkError < Error
|
|
188
|
+
attr_reader :cause
|
|
189
|
+
|
|
190
|
+
def initialize(cause, tool)
|
|
191
|
+
@cause = cause
|
|
192
|
+
super(tool)
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "connector/client"
|
|
4
|
+
require_relative "storage/protocols"
|
|
5
|
+
|
|
6
|
+
module Seekmodo
|
|
7
|
+
module Sdk
|
|
8
|
+
class TenantSnapshot
|
|
9
|
+
DEFAULT_TTL_SECONDS = 300
|
|
10
|
+
DEFAULT_STALE_TTL_SECONDS = 60
|
|
11
|
+
CACHE_KEY = "numinix.seekmodo.tenant_snapshot"
|
|
12
|
+
CACHE_KEY_FETCHED_AT = "numinix.seekmodo.tenant_snapshot.fetched_at"
|
|
13
|
+
|
|
14
|
+
def initialize(
|
|
15
|
+
client,
|
|
16
|
+
cache,
|
|
17
|
+
ttl_seconds: DEFAULT_TTL_SECONDS,
|
|
18
|
+
stale_after_seconds: DEFAULT_STALE_TTL_SECONDS,
|
|
19
|
+
clock: nil
|
|
20
|
+
)
|
|
21
|
+
@client = client
|
|
22
|
+
@cache = cache
|
|
23
|
+
@ttl_seconds = ttl_seconds
|
|
24
|
+
@stale_after_seconds = [stale_after_seconds, ttl_seconds].min
|
|
25
|
+
@clock = clock || -> { Time.now.to_i }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def get
|
|
29
|
+
cached = @cache.get(CACHE_KEY)
|
|
30
|
+
fetched_at = @cache.get(CACHE_KEY_FETCHED_AT, 0).to_i
|
|
31
|
+
|
|
32
|
+
if cached.is_a?(Hash) && fetched_at > 0
|
|
33
|
+
age = @clock.call - fetched_at
|
|
34
|
+
if age < @stale_after_seconds
|
|
35
|
+
return cached
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
begin
|
|
39
|
+
return refresh
|
|
40
|
+
rescue StandardError
|
|
41
|
+
return cached
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
begin
|
|
46
|
+
refresh
|
|
47
|
+
rescue StandardError
|
|
48
|
+
{}
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def refresh
|
|
53
|
+
snapshot = @client.tenant_snapshot
|
|
54
|
+
@cache.set(CACHE_KEY, snapshot, @ttl_seconds)
|
|
55
|
+
@cache.set(CACHE_KEY_FETCHED_AT, @clock.call, @ttl_seconds)
|
|
56
|
+
snapshot
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def forget
|
|
60
|
+
@cache.delete(CACHE_KEY)
|
|
61
|
+
@cache.delete(CACHE_KEY_FETCHED_AT)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Seekmodo
|
|
4
|
+
module Sdk
|
|
5
|
+
module Tools
|
|
6
|
+
class Registry
|
|
7
|
+
ADMIN_PREFIXES = %w[
|
|
8
|
+
synonyms. pins. ltr. analytics. tenant. merchandising. experiments.
|
|
9
|
+
catalog. queries. segments. banners. deboosts. esp. regions.
|
|
10
|
+
recommendations. bundles. image_search. bot_check. schema.
|
|
11
|
+
].freeze
|
|
12
|
+
|
|
13
|
+
ADMIN_TOOLS = %w[
|
|
14
|
+
synonyms.list synonyms.add synonyms.remove
|
|
15
|
+
pins.list pins.set pins.remove
|
|
16
|
+
ltr.status ltr.retrain ltr.toggle ltr.config.set
|
|
17
|
+
analytics.top_queries analytics.zero_results
|
|
18
|
+
tenant.snapshot tenant.config tenant.config.set
|
|
19
|
+
].freeze
|
|
20
|
+
|
|
21
|
+
def initialize(connector: nil, admin: nil, tenant_id: nil)
|
|
22
|
+
@connector = connector
|
|
23
|
+
@admin = admin
|
|
24
|
+
@tenant_id = tenant_id
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def call(tool, args = {}, tenant_id: @tenant_id)
|
|
28
|
+
normalized = normalize_tool(tool)
|
|
29
|
+
if admin_tool?(normalized)
|
|
30
|
+
unless @admin
|
|
31
|
+
raise ArgumentError, "Admin client required for tool #{normalized}"
|
|
32
|
+
end
|
|
33
|
+
unless tenant_id
|
|
34
|
+
raise ArgumentError, "tenant_id required for admin tool #{normalized}"
|
|
35
|
+
end
|
|
36
|
+
return @admin.call(normalized, args, tenant_id: tenant_id)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
unless @connector
|
|
40
|
+
raise ArgumentError, "Connector client required for tool #{normalized}"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
route_connector(normalized, args)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
def normalize_tool(tool)
|
|
49
|
+
tool.to_s.tr("_", ".")
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def admin_tool?(tool)
|
|
53
|
+
return true if ADMIN_TOOLS.include?(tool)
|
|
54
|
+
return true if tool.start_with?("admin.")
|
|
55
|
+
|
|
56
|
+
ADMIN_PREFIXES.any? { |prefix| tool.start_with?(prefix) }
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def route_connector(tool, args)
|
|
60
|
+
case tool
|
|
61
|
+
when "search"
|
|
62
|
+
@connector.search(args)
|
|
63
|
+
when "index"
|
|
64
|
+
documents = args["documents"] || args[:documents] || []
|
|
65
|
+
action = args["action"] || args[:action] || "upsert"
|
|
66
|
+
@connector.index(documents, action: action)
|
|
67
|
+
when "events"
|
|
68
|
+
events = args["events"] || args[:events] || []
|
|
69
|
+
@connector.events(events)
|
|
70
|
+
when "tenant.handshake"
|
|
71
|
+
@connector.tenant_handshake
|
|
72
|
+
when "tenant.snapshot"
|
|
73
|
+
@connector.tenant_snapshot
|
|
74
|
+
when "tenants/token"
|
|
75
|
+
audience = args["audience"] || args[:audience]
|
|
76
|
+
@connector.browser_token(audience)
|
|
77
|
+
when "tools"
|
|
78
|
+
@connector.tools
|
|
79
|
+
when "health"
|
|
80
|
+
@connector.health
|
|
81
|
+
else
|
|
82
|
+
@connector.post_json("/v1/#{tool}", args)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
data/lib/seekmodo/sdk.rb
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "sdk/version"
|
|
4
|
+
require_relative "sdk/exceptions/seekmodo_error"
|
|
5
|
+
require_relative "sdk/exceptions/client_error"
|
|
6
|
+
require_relative "sdk/exceptions/tenant_unavailable_error"
|
|
7
|
+
require_relative "sdk/exceptions/over_quota_error"
|
|
8
|
+
require_relative "sdk/exceptions/signature_mismatch_error"
|
|
9
|
+
require_relative "sdk/exceptions/breaker_open_error"
|
|
10
|
+
require_relative "sdk/hmac_signer"
|
|
11
|
+
require_relative "sdk/mode"
|
|
12
|
+
require_relative "sdk/circuit_breaker"
|
|
13
|
+
require_relative "sdk/connector/client"
|
|
14
|
+
require_relative "sdk/tenant_snapshot"
|
|
15
|
+
require_relative "sdk/mode_fsm"
|
|
16
|
+
require_relative "sdk/auto_promoter"
|
|
17
|
+
require_relative "sdk/pairing"
|
|
18
|
+
require_relative "sdk/browser_token"
|
|
19
|
+
require_relative "sdk/signature_mismatch_tracker"
|
|
20
|
+
require_relative "sdk/storage/protocols"
|
|
21
|
+
require_relative "sdk/storage/memory/stores"
|
|
22
|
+
require_relative "sdk/events/click_beacon"
|
|
23
|
+
require_relative "sdk/events/events_queue"
|
|
24
|
+
require_relative "sdk/storefront/transport"
|
|
25
|
+
require_relative "sdk/storefront/client"
|
|
26
|
+
require_relative "sdk/admin/client"
|
|
27
|
+
require_relative "sdk/mcp/client"
|
|
28
|
+
require_relative "sdk/tools/registry"
|
|
29
|
+
|
|
30
|
+
module Seekmodo
|
|
31
|
+
module Sdk
|
|
32
|
+
end
|
|
33
|
+
end
|
data/lib/seekmodo-sdk.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: seekmodo-sdk
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.5.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Seekmodo
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-06-19 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: faraday
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '2.0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '2.0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: jwt
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '2.7'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '2.7'
|
|
41
|
+
description: Ruby SDK for the Seekmodo MCP gateway with HMAC connector transport,
|
|
42
|
+
JWT storefront client, admin tools, and JSON-RPC MCP support.
|
|
43
|
+
email:
|
|
44
|
+
- support@seekmodo.com
|
|
45
|
+
executables: []
|
|
46
|
+
extensions: []
|
|
47
|
+
extra_rdoc_files: []
|
|
48
|
+
files:
|
|
49
|
+
- ".github/workflows/ci.yml"
|
|
50
|
+
- ".gitignore"
|
|
51
|
+
- ".rspec"
|
|
52
|
+
- ".rubocop.yml"
|
|
53
|
+
- Gemfile
|
|
54
|
+
- README.md
|
|
55
|
+
- docs/tool-catalog.README.md
|
|
56
|
+
- lib/seekmodo-sdk.rb
|
|
57
|
+
- lib/seekmodo/sdk.rb
|
|
58
|
+
- lib/seekmodo/sdk/admin/client.rb
|
|
59
|
+
- lib/seekmodo/sdk/auto_promoter.rb
|
|
60
|
+
- lib/seekmodo/sdk/browser_token.rb
|
|
61
|
+
- lib/seekmodo/sdk/circuit_breaker.rb
|
|
62
|
+
- lib/seekmodo/sdk/connector/client.rb
|
|
63
|
+
- lib/seekmodo/sdk/events/click_beacon.rb
|
|
64
|
+
- lib/seekmodo/sdk/events/events_queue.rb
|
|
65
|
+
- lib/seekmodo/sdk/exceptions/breaker_open_error.rb
|
|
66
|
+
- lib/seekmodo/sdk/exceptions/client_error.rb
|
|
67
|
+
- lib/seekmodo/sdk/exceptions/over_quota_error.rb
|
|
68
|
+
- lib/seekmodo/sdk/exceptions/seekmodo_error.rb
|
|
69
|
+
- lib/seekmodo/sdk/exceptions/signature_mismatch_error.rb
|
|
70
|
+
- lib/seekmodo/sdk/exceptions/tenant_unavailable_error.rb
|
|
71
|
+
- lib/seekmodo/sdk/hmac_signer.rb
|
|
72
|
+
- lib/seekmodo/sdk/mcp/client.rb
|
|
73
|
+
- lib/seekmodo/sdk/mode.rb
|
|
74
|
+
- lib/seekmodo/sdk/mode_fsm.rb
|
|
75
|
+
- lib/seekmodo/sdk/pairing.rb
|
|
76
|
+
- lib/seekmodo/sdk/signature_mismatch_tracker.rb
|
|
77
|
+
- lib/seekmodo/sdk/storage/memory/stores.rb
|
|
78
|
+
- lib/seekmodo/sdk/storage/protocols.rb
|
|
79
|
+
- lib/seekmodo/sdk/storefront/client.rb
|
|
80
|
+
- lib/seekmodo/sdk/storefront/transport.rb
|
|
81
|
+
- lib/seekmodo/sdk/tenant_snapshot.rb
|
|
82
|
+
- lib/seekmodo/sdk/tools/registry.rb
|
|
83
|
+
- lib/seekmodo/sdk/version.rb
|
|
84
|
+
homepage: https://seekmodo.com/docs/sdk
|
|
85
|
+
licenses:
|
|
86
|
+
- MIT
|
|
87
|
+
metadata:
|
|
88
|
+
homepage_uri: https://seekmodo.com/docs/sdk
|
|
89
|
+
source_code_uri: https://github.com/numinix/seekmodo-ruby-sdk
|
|
90
|
+
post_install_message:
|
|
91
|
+
rdoc_options: []
|
|
92
|
+
require_paths:
|
|
93
|
+
- lib
|
|
94
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
95
|
+
requirements:
|
|
96
|
+
- - ">="
|
|
97
|
+
- !ruby/object:Gem::Version
|
|
98
|
+
version: 3.1.0
|
|
99
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - ">="
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '0'
|
|
104
|
+
requirements: []
|
|
105
|
+
rubygems_version: 3.5.22
|
|
106
|
+
signing_key:
|
|
107
|
+
specification_version: 4
|
|
108
|
+
summary: Seekmodo Ruby SDK — connector, storefront, admin, and MCP clients
|
|
109
|
+
test_files: []
|