Class: Melaya::Client

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

Overview

The unified Melaya client.

Exposes every public endpoint in the Melaya REST API surface through three domain namespaces and flat module accessors (for backward compatibility).

Primary API — namespaced (recommended):

melaya.trading.market.ticker(...)         # market data
melaya.trading.strategies.create(...)     # trading strategies
melaya.agents.pipelines.list(...)         # agent pipeline runs
melaya.agents.hitl.pending                # HITL approval queue
melaya.platform.projects.list             # platform projects
melaya.platform.billing.subscription      # billing

Flat accessors (backward-compatible aliases):

melaya.market.ticker(...)    # same object as melaya.trading.market
melaya.pipelines.list(...)   # same object as melaya.agents.pipelines
melaya.projects.list         # same object as melaya.platform.projects

Namespace groupings:

  • trading — market, account, sim, strategies, backtest, stream, trade
  • agents — pipelines (also .runs), hitl, assistant, phone, evals, models
  • platform — projects, credentials, connectors, billing, team, templates, overview, runner, auth (also .mfa), accounts, bugs, events

Authentication: pass your mk_* platform API key via api_key:. Every REST call sends it as an Authorization: Bearer header. For session JWT workflows (login/refresh) construct the client with the JWT instead. Never log or expose the key — it is stored opaquely in the HTTP client.

Examples:

require "melaya"

melaya = Melaya::Client.new(api_key: ENV["MELAYA_API_KEY"])

# Namespaced — primary API
t = melaya.trading.market.ticker(exchange: "binance", symbol: "BTC/USDT", market: "spot")
puts t["last"]

# Agent pipelines
runs = melaya.agents.pipelines.list(project: "my-project", limit: 10)
# or via the alias:
runs = melaya.agents.runs.list(project: "my-project", limit: 10)

# HITL approvals
pending = melaya.agents.hitl.pending
pending.each { |r| melaya.agents.hitl.approve(r["requestId"]) }

# Platform
projects = melaya.platform.projects.list
melaya.platform.auth.(username: "you@example.com", password: "s3cr3t")

# Real-time events (Socket.IO) — also on platform namespace
melaya.platform.events.on_run_update("run-123") { |e| puts e["event_type"] }

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(api_key:, base_url: HttpClient::DEFAULT_BASE_URL, ws_url: StreamAPI::DEFAULT_WS_URL, verify_ssl: nil, connect_events: false) ⇒ Client

Returns a new instance of Client.

Parameters:

  • api_key (String)

    Melaya platform API key, prefixed mk_. Create one at melaya.org → Settings → API Keys. May also be a session JWT for auth-plane operations (login/refresh return a JWT).

  • base_url (String) (defaults to: HttpClient::DEFAULT_BASE_URL)

    Override the REST base URL.

  • ws_url (String) (defaults to: StreamAPI::DEFAULT_WS_URL)

    Override the WebSocket base URL.

  • verify_ssl (Boolean) (defaults to: nil)

    Retained for compatibility; false is rejected.

  • connect_events (Boolean) (defaults to: false)

    If false, do not open a Socket.IO connection on construction. Call events to connect lazily. Default: false (lazy).

Raises:

  • (ArgumentError)


193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
# File 'lib/melaya.rb', line 193

def initialize(api_key:, base_url: HttpClient::DEFAULT_BASE_URL,
               ws_url: StreamAPI::DEFAULT_WS_URL,
               verify_ssl: nil,
               connect_events: false)
  raise ArgumentError,
    "Melaya: api_key is required (create one at melaya.org → Settings → API Keys)." \
    if api_key.nil? || api_key.to_s.empty?
  # Allow JWTs (which don't start with mk_) for auth-plane use cases
  # while still guiding developers who forget the prefix.
  if !api_key.to_s.start_with?("mk_") && !api_key.to_s.start_with?("ey")
    raise ArgumentError,
      "Melaya: API keys must be prefixed 'mk_' (or a Bearer JWT starting with 'ey')."
  end

  if verify_ssl == false
    raise ArgumentError, "Melaya: TLS certificate verification cannot be disabled."
  end
  ssl = true

  http = HttpClient.new(api_key: api_key, base_url: base_url, verify_ssl: ssl)

  # Trading plane
  @market     = MarketAPI.new(http)
  @account    = AccountAPI.new(http)
  @sim        = SimAPI.new(http)
  @strategies = StrategiesAPI.new(http)
  @backtest   = BacktestAPI.new(http)
  @stream     = StreamAPI.new(api_key, ws_url, http, verify_ssl: ssl)
  @trade      = TradeAPI.new(http)

  # Platform / agents plane
  @auth        = AuthAPI.new(http)
  @accounts    = AccountsAPI.new(http)
  @billing     = BillingAPI.new(http)
  @runner      = RunnerAPI.new(http)
  @projects    = ProjectsAPI.new(http)
  @pipelines   = PipelinesAPI.new(http)
  @hitl        = HitlAPI.new(http)
  @credentials = CredentialsAPI.new(http)
  @connectors  = ConnectorsAPI.new(http)
  @phone       = PhoneAPI.new(http)
  @team        = TeamAPI.new(http)
  @templates   = TemplatesAPI.new(http)
  @assistant   = AssistantAPI.new(http)
  @evals       = EvalsAPI.new(http)
  @bugs        = BugsAPI.new(http)

  if connect_events
    @events = Events.new(api_key: api_key, base_url: base_url, verify_ssl: ssl)
  else
    @_events_api_key   = api_key
    @_events_base_url  = base_url
    @_events_verify_ssl = ssl
    @events = nil
  end

  # ── Domain namespaces ────────────────────────────────────────────────────
  # Each attribute is the SAME instance as the flat accessor — no copies,
  # no extra HTTP clients.

  @trading = TradingNamespace.new(
    market:     @market,
    account:    @account,
    sim:        @sim,
    strategies: @strategies,
    backtest:   @backtest,
    stream:     @stream,
    trade:      @trade
  )

  @agents = AgentsNamespace.new(
    pipelines: @pipelines,
    hitl:      @hitl,
    assistant: @assistant,
    phone:     @phone,
    evals:     @evals,
    # credentials#list_models is the canonical "models" surface; expose the
    # full CredentialsAPI object here so callers can do agents.models.list_models(...)
    models:    @credentials
  )

  # Platform namespace: events slot uses a lazy proxy so the Socket.IO
  # thread is still only started on first access (same as the flat #events).
  platform_self = self
  @platform = PlatformNamespace.new(
    projects:    @projects,
    credentials: @credentials,
    connectors:  @connectors,
    billing:     @billing,
    team:        @team,
    templates:   @templates,
    overview:    @pipelines,  # overview dashboard lives on PipelinesAPI
    runner:      @runner,
    auth:        @auth,
    accounts:    @accounts,
    bugs:        @bugs,
    events:      nil          # filled lazily below
  )

  # Patch platform#events to delegate to the lazy flat accessor.
  # We do this with a singleton method so PlatformNamespace remains a plain
  # Struct (no subclassing required).
  @platform.define_singleton_method(:events) { platform_self.events }
end

Instance Attribute Details

#accountObject (readonly)

Authenticated account reads: connected keys, tier limits, usage.



98
99
100
# File 'lib/melaya.rb', line 98

def 
  @account
end

#accountsObject (readonly)

Account management: GDPR export, CEX key removal, profile updates.



114
115
116
# File 'lib/melaya.rb', line 114

def accounts
  @accounts
end

#agentsAgentsNamespace (readonly)

Agent-plane namespace. Groups: pipelines (alias: runs), hitl, assistant, phone, evals, models.

Examples:

melaya.agents.pipelines.list(project: "my-project")
melaya.agents.runs.list(project: "my-project")  # alias for pipelines
melaya.agents.hitl.pending
melaya.agents.assistant.get_profile
melaya.agents.evals.list_runs
melaya.agents.models.list_models(provider: "anthropic")

Returns:



169
170
171
# File 'lib/melaya.rb', line 169

def agents
  @agents
end

#assistantObject (readonly)

Assistant onboarding profile (get + set).



136
137
138
# File 'lib/melaya.rb', line 136

def assistant
  @assistant
end

#authObject (readonly)

── Platform / agents plane ──────────────────────────────────────────────── Auth: login, MFA, registration, password management, session tokens.



112
113
114
# File 'lib/melaya.rb', line 112

def auth
  @auth
end

#backtestObject (readonly)

Historical backtests + parameter sweeps on the Rust engine.



104
105
106
# File 'lib/melaya.rb', line 104

def backtest
  @backtest
end

#billingObject (readonly)

Billing: subscription, Stripe checkout/portal, pricing plans, credit balances.



116
117
118
# File 'lib/melaya.rb', line 116

def billing
  @billing
end

#bugsObject (readonly)

Bug reports: submit, track, and comment.



140
141
142
# File 'lib/melaya.rb', line 140

def bugs
  @bugs
end

#connectorsObject (readonly)

Project-scoped connector credentials.



128
129
130
# File 'lib/melaya.rb', line 128

def connectors
  @connectors
end

#credentialsObject (readonly)

User-scoped credential storage (services, OAuth, env handles, models).



126
127
128
# File 'lib/melaya.rb', line 126

def credentials
  @credentials
end

#evalsObject (readonly)

Agent evaluation runs and benchmarks.



138
139
140
# File 'lib/melaya.rb', line 138

def evals
  @evals
end

#eventsObject (readonly)

Lazily initialize and return the events client. If connect_events: true was passed to the constructor, returns the already-connected client. Otherwise creates and connects on first access. Also accessible as melaya.platform.events.



144
145
146
# File 'lib/melaya.rb', line 144

def events
  @events
end

#hitlObject (readonly)

Human-in-the-loop approval queue: list pending, approve, reject.



124
125
126
# File 'lib/melaya.rb', line 124

def hitl
  @hitl
end

#marketObject (readonly)

── Trading plane ────────────────────────────────────────────────────────── REST market-data + reference endpoints (public + authenticated).



96
97
98
# File 'lib/melaya.rb', line 96

def market
  @market
end

#phoneObject (readonly)

Phone device control: pair, list, screen-tree, apps.



130
131
132
# File 'lib/melaya.rb', line 130

def phone
  @phone
end

#pipelinesObject (readonly)

Pipeline runs, traces, schedules, and overview dashboard.



122
123
124
# File 'lib/melaya.rb', line 122

def pipelines
  @pipelines
end

#platformPlatformNamespace (readonly)

Platform-plane namespace. Groups: projects, credentials, connectors, billing, team, templates, overview, runner, auth (alias: mfa), accounts, bugs, events.

Examples:

melaya.platform.projects.list
melaya.platform.billing.subscription
melaya.platform.auth.(username: "u", password: "p")
melaya.platform.mfa.mfa_setup           # alias for auth
melaya.platform.credentials.set("openai", value: "sk-...")
melaya.platform.events.on_run_update("run-123") { |e| puts e["event_type"] }

Returns:



183
184
185
# File 'lib/melaya.rb', line 183

def platform
  @platform
end

#projectsObject (readonly)

Agent projects: create and list.



120
121
122
# File 'lib/melaya.rb', line 120

def projects
  @projects
end

#runnerObject (readonly)

Runner tokens: mint, list, revoke mel_run_ tokens.



118
119
120
# File 'lib/melaya.rb', line 118

def runner
  @runner
end

#simObject (readonly)

Paper trading (sim broker): virtual balance, positions, and orders.



100
101
102
# File 'lib/melaya.rb', line 100

def sim
  @sim
end

#strategiesObject (readonly)

Launch, control, and inspect trading strategies (paper + live).



102
103
104
# File 'lib/melaya.rb', line 102

def strategies
  @strategies
end

#streamObject (readonly)

WebSocket streaming endpoints (public market data + private feeds).



106
107
108
# File 'lib/melaya.rb', line 106

def stream
  @stream
end

#teamObject (readonly)

Project team management: members, roles, invite links.



132
133
134
# File 'lib/melaya.rb', line 132

def team
  @team
end

#templatesObject (readonly)

Pipeline templates: create, share, assign, and manage visibility.



134
135
136
# File 'lib/melaya.rb', line 134

def templates
  @templates
end

#tradeObject (readonly)

Live trading — credentialed order placement on a connected exchange. WARNING: real funds.



108
109
110
# File 'lib/melaya.rb', line 108

def trade
  @trade
end

#tradingTradingNamespace (readonly)

Trading-plane namespace. Groups: market, account, sim, strategies, backtest, stream, trade.

Examples:

melaya.trading.market.ticker(exchange: "binance", symbol: "BTC/USDT", market: "spot")
melaya.trading.strategies.create(name: "bot", strategy_type: "custom", ...)
melaya.trading.stream.ticker(exchange: "binance", symbol: "BTC/USDT", market: "spot") { |f| ... }

Returns:



156
157
158
# File 'lib/melaya.rb', line 156

def trading
  @trading
end