driftgate-sdk 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/README.md +32 -0
- data/lib/driftgate_sdk.rb +149 -0
- metadata +48 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 7e9548e25eb817913f839fbf3fb79c281555fe93bbf5334a94ecc3547f322fce
|
|
4
|
+
data.tar.gz: 7c059174999ffa60dfe982e29980b4af2aa05e6b7762f4847f8a00db0f54fea5
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: d820734ab5c4359abd3788eee60da12c0b1e0820853a9b6e8a058abe758698e21656c63d7335465ddbff38f32c8a89d5403e32223349bda826a1ab9161e1ef98
|
|
7
|
+
data.tar.gz: 81c4ac11d3f14b53d5a9c3ba12d7dc7751392c4063a04287b4e3e6df25d4a452f6e89e2f4303415063a2197861cda9f75c62982b368af901bd3f48cd881639e7
|
data/README.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# DriftGate Ruby SDK
|
|
2
|
+
|
|
3
|
+
Canonical V4 envelope SDK for Ruby.
|
|
4
|
+
|
|
5
|
+
See canonical envelope docs: [`docs/sdk/response-envelope.md`](/Users/jordandavis/Documents/Code/DriftGateAI/driftgate-v4-sdk-wt/docs/sdk/response-envelope.md).
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
gem install driftgate-sdk -v 0.1.0
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Hello World (2 lines)
|
|
14
|
+
|
|
15
|
+
```ruby
|
|
16
|
+
session = DriftGateSDK::Client.new(base_url: "https://api.driftgate.ai").session.start(agent: "refund-agent")
|
|
17
|
+
session.execute(input: { orderId: "123" })
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Full Example
|
|
21
|
+
|
|
22
|
+
```ruby
|
|
23
|
+
client = DriftGateSDK::Client.new(base_url: "https://api.driftgate.ai", bearer_token: ENV.fetch("DRIFTGATE_TOKEN"))
|
|
24
|
+
session = client.session.start(
|
|
25
|
+
agent: "refund-agent",
|
|
26
|
+
policy: { ref: "refund", version: "2026-02" },
|
|
27
|
+
route: { provider: "openai", model: "gpt-4.1-mini", region: "us-east-1" },
|
|
28
|
+
risk: { decision: "review" }
|
|
29
|
+
)
|
|
30
|
+
response = session.execute(input: { orderId: "123" })
|
|
31
|
+
puts response.fetch("meta").fetch("requestId")
|
|
32
|
+
```
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
require "net/http"
|
|
5
|
+
require "uri"
|
|
6
|
+
|
|
7
|
+
module DriftGateSDK
|
|
8
|
+
ERROR_CODES = %w[
|
|
9
|
+
AUTH_INVALID
|
|
10
|
+
POLICY_DENIED
|
|
11
|
+
RISK_EXCEEDED
|
|
12
|
+
ROUTE_UNAVAILABLE
|
|
13
|
+
TOOL_BLOCKED
|
|
14
|
+
RATE_LIMITED
|
|
15
|
+
TIMEOUT
|
|
16
|
+
INTERNAL
|
|
17
|
+
].freeze
|
|
18
|
+
|
|
19
|
+
class Error < StandardError
|
|
20
|
+
attr_reader :code, :status, :retryable, :request_id, :details
|
|
21
|
+
|
|
22
|
+
def initialize(code:, message:, status:, retryable:, request_id: nil, details: nil)
|
|
23
|
+
super(message)
|
|
24
|
+
@code = code
|
|
25
|
+
@status = status
|
|
26
|
+
@retryable = retryable
|
|
27
|
+
@request_id = request_id
|
|
28
|
+
@details = details
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class SessionHandle
|
|
33
|
+
attr_reader :session, :start_envelope
|
|
34
|
+
|
|
35
|
+
def initialize(client:, session:, start_envelope:)
|
|
36
|
+
@client = client
|
|
37
|
+
@session = session
|
|
38
|
+
@start_envelope = start_envelope
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def session_id
|
|
42
|
+
@session.fetch("sessionId")
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def execute(input:, policy: nil, route: nil, risk: nil, workflow_version_id: nil)
|
|
46
|
+
payload = { input: input }
|
|
47
|
+
payload[:policy] = policy if policy
|
|
48
|
+
payload[:route] = route if route
|
|
49
|
+
payload[:risk] = risk if risk
|
|
50
|
+
payload[:workflowVersionId] = workflow_version_id if workflow_version_id
|
|
51
|
+
@client.execute_session(session_id: session_id, payload: payload)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
class Client
|
|
56
|
+
attr_accessor :api_key, :bearer_token
|
|
57
|
+
|
|
58
|
+
def initialize(base_url:, api_key: nil, bearer_token: nil, http: Net::HTTP)
|
|
59
|
+
@base_url = base_url.sub(%r{/$}, "")
|
|
60
|
+
@api_key = api_key
|
|
61
|
+
@bearer_token = bearer_token
|
|
62
|
+
@http = http
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def session
|
|
66
|
+
self
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def start(agent:, workspace_id: nil, subject: nil, metadata: nil, policy: nil, route: nil, risk: nil, workflow_version_id: nil, expires_at: nil)
|
|
70
|
+
payload = { agent: agent }
|
|
71
|
+
payload[:workspaceId] = workspace_id if workspace_id
|
|
72
|
+
payload[:subject] = subject if subject
|
|
73
|
+
payload[:metadata] = metadata if metadata
|
|
74
|
+
payload[:policy] = policy if policy
|
|
75
|
+
payload[:route] = route if route
|
|
76
|
+
payload[:risk] = risk if risk
|
|
77
|
+
payload[:workflowVersionId] = workflow_version_id if workflow_version_id
|
|
78
|
+
payload[:expiresAt] = expires_at if expires_at
|
|
79
|
+
|
|
80
|
+
envelope = request(method: "POST", path: "/v4/sessions.start", payload: payload)
|
|
81
|
+
raise_envelope_error(envelope) unless envelope.fetch("ok")
|
|
82
|
+
|
|
83
|
+
SessionHandle.new(client: self, session: envelope.fetch("data").fetch("session"), start_envelope: envelope)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def execute_session(session_id:, payload:)
|
|
87
|
+
envelope = request(method: "POST", path: "/v4/sessions/#{session_id}/executions.execute", payload: payload)
|
|
88
|
+
raise_envelope_error(envelope) unless envelope.fetch("ok")
|
|
89
|
+
envelope
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def execute(agent:, input:, workspace_id: nil, subject: nil, metadata: nil, policy: nil, route: nil, risk: nil, workflow_version_id: nil)
|
|
93
|
+
payload = {
|
|
94
|
+
agent: agent,
|
|
95
|
+
input: input
|
|
96
|
+
}
|
|
97
|
+
payload[:workspaceId] = workspace_id if workspace_id
|
|
98
|
+
payload[:subject] = subject if subject
|
|
99
|
+
payload[:metadata] = metadata if metadata
|
|
100
|
+
payload[:policy] = policy if policy
|
|
101
|
+
payload[:route] = route if route
|
|
102
|
+
payload[:risk] = risk if risk
|
|
103
|
+
payload[:workflowVersionId] = workflow_version_id if workflow_version_id
|
|
104
|
+
|
|
105
|
+
envelope = request(method: "POST", path: "/v4/execute", payload: payload)
|
|
106
|
+
raise_envelope_error(envelope) unless envelope.fetch("ok")
|
|
107
|
+
envelope
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
private
|
|
111
|
+
|
|
112
|
+
def request(method:, path:, payload:)
|
|
113
|
+
uri = URI.parse("#{@base_url}#{path}")
|
|
114
|
+
request_class = Net::HTTP.const_get(method.capitalize)
|
|
115
|
+
request = request_class.new(uri)
|
|
116
|
+
request["content-type"] = "application/json"
|
|
117
|
+
request["x-driftgate-api-key"] = @api_key if @api_key
|
|
118
|
+
request["authorization"] = "Bearer #{@bearer_token}" if @bearer_token
|
|
119
|
+
request.body = JSON.generate(payload)
|
|
120
|
+
|
|
121
|
+
response = @http.start(uri.host, uri.port, use_ssl: uri.scheme == "https") do |http|
|
|
122
|
+
http.request(request)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
body = response.body && !response.body.empty? ? JSON.parse(response.body) : {}
|
|
126
|
+
if response.code.to_i >= 400
|
|
127
|
+
raise_envelope_error(body)
|
|
128
|
+
end
|
|
129
|
+
body
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def raise_envelope_error(payload)
|
|
133
|
+
if payload.is_a?(Hash) && payload["error"].is_a?(Hash)
|
|
134
|
+
error = payload["error"]
|
|
135
|
+
meta = payload["meta"].is_a?(Hash) ? payload["meta"] : {}
|
|
136
|
+
raise Error.new(
|
|
137
|
+
code: error.fetch("code", "INTERNAL"),
|
|
138
|
+
message: error.fetch("message", "request failed"),
|
|
139
|
+
status: error.fetch("status", 500),
|
|
140
|
+
retryable: error.fetch("retryable", false),
|
|
141
|
+
request_id: meta["requestId"],
|
|
142
|
+
details: error["details"]
|
|
143
|
+
)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
raise Error.new(code: "INTERNAL", message: "request failed", status: 500, retryable: false)
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: driftgate-sdk
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- DriftGate
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-03-03 00:00:00.000000000 Z
|
|
12
|
+
dependencies: []
|
|
13
|
+
description: DriftGate Ruby SDK for canonical V4 session and execution APIs.
|
|
14
|
+
email:
|
|
15
|
+
- support@driftgate.ai
|
|
16
|
+
executables: []
|
|
17
|
+
extensions: []
|
|
18
|
+
extra_rdoc_files: []
|
|
19
|
+
files:
|
|
20
|
+
- README.md
|
|
21
|
+
- lib/driftgate_sdk.rb
|
|
22
|
+
homepage: https://docs.driftgate.ai
|
|
23
|
+
licenses:
|
|
24
|
+
- Apache-2.0
|
|
25
|
+
metadata:
|
|
26
|
+
homepage_uri: https://docs.driftgate.ai
|
|
27
|
+
source_code_uri: https://github.com/driftgate/driftgate-sdk
|
|
28
|
+
changelog_uri: https://docs.driftgate.ai/changelog
|
|
29
|
+
post_install_message:
|
|
30
|
+
rdoc_options: []
|
|
31
|
+
require_paths:
|
|
32
|
+
- lib
|
|
33
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
34
|
+
requirements:
|
|
35
|
+
- - ">="
|
|
36
|
+
- !ruby/object:Gem::Version
|
|
37
|
+
version: 3.0.0
|
|
38
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
39
|
+
requirements:
|
|
40
|
+
- - ">="
|
|
41
|
+
- !ruby/object:Gem::Version
|
|
42
|
+
version: '0'
|
|
43
|
+
requirements: []
|
|
44
|
+
rubygems_version: 3.5.22
|
|
45
|
+
signing_key:
|
|
46
|
+
specification_version: 4
|
|
47
|
+
summary: DriftGate canonical V4 envelope SDK
|
|
48
|
+
test_files: []
|