Class: Leash::Integrations

Inherits:
Object
  • Object
show all
Defined in:
lib/leash/integrations.rb

Overview

Main client for accessing Leash platform integrations.

Examples:

client = Leash::Integrations.new(auth_token: "your-jwt-token")
messages = client.gmail.list_messages(query: "is:unread")
events = client.calendar.list_events(time_min: "2026-04-10T00:00:00Z")
files = client.drive.list_files

Instance Method Summary collapse

Constructor Details

#initialize(auth_token:, platform_url: DEFAULT_PLATFORM_URL, api_key: nil) ⇒ Integrations

Returns a new instance of Integrations.

Parameters:

  • auth_token (String)

    the leash-auth JWT token

  • platform_url (String) (defaults to: DEFAULT_PLATFORM_URL)

    base URL of the Leash platform API

  • api_key (String, nil) (defaults to: nil)

    optional API key for server-to-server auth



27
28
29
30
31
# File 'lib/leash/integrations.rb', line 27

def initialize(auth_token:, platform_url: DEFAULT_PLATFORM_URL, api_key: nil)
  @auth_token = auth_token
  @platform_url = platform_url.chomp("/")
  @api_key = api_key || ENV["LEASH_API_KEY"]
end

Instance Method Details

#calendarCalendarClient

Google Calendar integration client.

Returns:



43
44
45
# File 'lib/leash/integrations.rb', line 43

def calendar
  @calendar ||= CalendarClient.new(method(:call))
end

#call(provider, action, params = nil) ⇒ Object

Generic proxy call for any provider action.

Parameters:

  • provider (String)

    integration provider name (e.g. “gmail”)

  • action (String)

    action to perform (e.g. “list-messages”)

  • params (Hash, nil) (defaults to: nil)

    optional request body parameters

Returns:

  • (Object)

    the “data” field from the platform response

Raises:



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/leash/integrations.rb', line 75

def call(provider, action, params = nil)
  uri = URI("#{@platform_url}/api/integrations/#{provider}/#{action}")

  request = Net::HTTP::Post.new(uri)
  request["Content-Type"] = "application/json"
  request["Authorization"] = "Bearer #{@auth_token}"
  request["X-API-Key"] = @api_key if @api_key
  request.body = (params || {}).to_json

  response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http|
    http.request(request)
  end

  data = JSON.parse(response.body)

  unless data["success"]
    raise_error(data)
  end

  data["data"]
end

#connect_url(provider_id, return_url: nil) ⇒ String

Get the URL to connect a provider (for UI buttons).

Parameters:

  • provider_id (String)

    the provider identifier

  • return_url (String, nil) (defaults to: nil)

    optional URL to redirect back to after connecting

Returns:

  • (String)

    the full URL to initiate the OAuth connection flow



136
137
138
139
140
# File 'lib/leash/integrations.rb', line 136

def connect_url(provider_id, return_url: nil)
  url = "#{@platform_url}/api/integrations/connect/#{provider_id}"
  url += "?return_url=#{URI.encode_www_form_component(return_url)}" if return_url
  url
end

#connected?(provider_id) ⇒ Boolean

Check if a provider is connected for the current user.

Parameters:

  • provider_id (String)

    the provider identifier (e.g. “gmail”)

Returns:

  • (Boolean)


101
102
103
104
105
106
# File 'lib/leash/integrations.rb', line 101

def connected?(provider_id)
  conn = connections.find { |c| c["providerId"] == provider_id }
  conn&.dig("status") == "active"
rescue StandardError
  false
end

#connectionsArray<Hash>

Get connection status for all providers.

Returns:

  • (Array<Hash>)

    list of connection status hashes



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/leash/integrations.rb', line 111

def connections
  uri = URI("#{@platform_url}/api/integrations/connections")

  request = Net::HTTP::Get.new(uri)
  request["Authorization"] = "Bearer #{@auth_token}"
  request["X-API-Key"] = @api_key if @api_key

  response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http|
    http.request(request)
  end

  data = JSON.parse(response.body)

  unless data["success"]
    raise_error(data)
  end

  data["data"] || []
end

#driveDriveClient

Google Drive integration client.

Returns:



50
51
52
# File 'lib/leash/integrations.rb', line 50

def drive
  @drive ||= DriveClient.new(method(:call))
end

#get_env(key = nil) ⇒ Hash, ...

Fetch env vars from the platform. Cached after first call.

Parameters:

  • key (String, nil) (defaults to: nil)

    optional key to look up

Returns:

  • (Hash, String, nil)

    all env vars as a Hash, or a single value if key given

Raises:

  • (Leash::Error)

    if the platform returns a non-success response



179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/leash/integrations.rb', line 179

def get_env(key = nil)
  @env_cache ||= begin
    uri = URI("#{@platform_url}/api/apps/env")

    request = Net::HTTP::Get.new(uri)
    request["Authorization"] = "Bearer #{@auth_token}" if @auth_token
    request["X-API-Key"] = @api_key if @api_key

    response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http|
      http.request(request)
    end

    data = JSON.parse(response.body)

    unless data["success"]
      raise_error(data)
    end

    data["data"] || {}
  end

  key ? @env_cache[key] : @env_cache
end

#gmailGmailClient

Gmail integration client.

Returns:



36
37
38
# File 'lib/leash/integrations.rb', line 36

def gmail
  @gmail ||= GmailClient.new(method(:call))
end

#integration(name) ⇒ CustomIntegration

Access a custom integration by name. Returns an untyped client.

Examples:

stripe = client.integration("stripe")
charges = stripe.call("/v1/charges", method: "GET")

Parameters:

  • name (String)

    the custom integration name

Returns:



62
63
64
# File 'lib/leash/integrations.rb', line 62

def integration(name)
  CustomIntegration.new(name, method(:call_custom))
end

#mcp(package_name, tool, args = {}) ⇒ Object

Call any MCP server tool directly.

Parameters:

  • package_name (String)

    the npm package name of the MCP server

  • tool (String)

    the tool name to invoke

  • args (Hash) (defaults to: {})

    optional arguments to pass to the tool

Returns:

  • (Object)

    the “data” field from the platform response

Raises:

  • (Leash::Error)

    if the platform returns a non-success response



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/leash/integrations.rb', line 149

def mcp(package_name, tool, args = {})
  uri = URI("#{@platform_url}/api/mcp/run")

  request = Net::HTTP::Post.new(uri)
  request["Content-Type"] = "application/json"
  request["Authorization"] = "Bearer #{@auth_token}" if @auth_token
  request["X-API-Key"] = @api_key if @api_key

  payload = { package: package_name, tool: tool }
  payload[:args] = args unless args.nil? || args.empty?
  request.body = payload.to_json

  response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http|
    http.request(request)
  end

  data = JSON.parse(response.body)

  unless data["success"]
    raise_error(data)
  end

  data["data"]
end