@brokr/sdk 1.0.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.
package/dist/auth.js ADDED
@@ -0,0 +1,175 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __esm = (fn, res) => function __init() {
7
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
8
+ };
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
22
+
23
+ // src/runtime.ts
24
+ var BrokrError;
25
+ var init_runtime = __esm({
26
+ "src/runtime.ts"() {
27
+ "use strict";
28
+ BrokrError = class extends Error {
29
+ constructor(message, code, capability, retryable = false) {
30
+ super(message);
31
+ this.code = code;
32
+ this.capability = capability;
33
+ this.retryable = retryable;
34
+ this.name = "BrokrError";
35
+ }
36
+ };
37
+ }
38
+ });
39
+
40
+ // src/auth.ts
41
+ var auth_exports = {};
42
+ __export(auth_exports, {
43
+ BrokrAuthClient: () => BrokrAuthClient,
44
+ authMiddleware: () => authMiddleware
45
+ });
46
+ module.exports = __toCommonJS(auth_exports);
47
+ function parseCookies(cookieHeader) {
48
+ const cookies = /* @__PURE__ */ new Map();
49
+ for (const pair of cookieHeader.split(";")) {
50
+ const eqIdx = pair.indexOf("=");
51
+ if (eqIdx === -1) continue;
52
+ const name = pair.slice(0, eqIdx).trim();
53
+ const value = pair.slice(eqIdx + 1).trim();
54
+ if (name) cookies.set(name, value);
55
+ }
56
+ return cookies;
57
+ }
58
+ function authMiddleware(options) {
59
+ const { protectedRoutes = [], publicOnlyRoutes = [] } = options;
60
+ return async function middleware(request) {
61
+ const url = new URL(request.url);
62
+ const pathname = url.pathname;
63
+ const isProtected = protectedRoutes.some((route) => pathname.startsWith(route));
64
+ const isPublicOnly = publicOnlyRoutes.some((route) => pathname.startsWith(route));
65
+ if (!isProtected && !isPublicOnly) return void 0;
66
+ const cookieHeader = request.headers.get("cookie") ?? "";
67
+ const cookies = parseCookies(cookieHeader);
68
+ const hasSession = cookies.has("better-auth.session_token");
69
+ if (isProtected && !hasSession) {
70
+ return Response.redirect(new URL("/sign-in", request.url).toString(), 302);
71
+ }
72
+ if (isPublicOnly && hasSession) {
73
+ return Response.redirect(new URL("/", request.url).toString(), 302);
74
+ }
75
+ return void 0;
76
+ };
77
+ }
78
+ var BrokrAuthClient;
79
+ var init_auth = __esm({
80
+ "src/auth.ts"() {
81
+ init_runtime();
82
+ BrokrAuthClient = class {
83
+ constructor(token, gatewayUrl, appUrl) {
84
+ this._token = token;
85
+ this._gatewayUrl = gatewayUrl;
86
+ this._appUrl = appUrl ?? (typeof process !== "undefined" ? process.env.BETTER_AUTH_URL : void 0);
87
+ }
88
+ /**
89
+ * Get current user from an incoming request's cookies.
90
+ * Calls the local Better Auth API (runs inside your app).
91
+ */
92
+ async currentUser(request) {
93
+ const session = await this.getSession(request);
94
+ return session?.user ?? null;
95
+ }
96
+ /**
97
+ * Get the full session (user + metadata) from an incoming request.
98
+ * Calls the local Better Auth API.
99
+ */
100
+ async getSession(request) {
101
+ const appUrl = this._appUrl;
102
+ if (!appUrl) {
103
+ throw new BrokrError(
104
+ "[brokr] BETTER_AUTH_URL is not set. Auth may not be provisioned.",
105
+ "AUTH_NOT_CONFIGURED",
106
+ "auth"
107
+ );
108
+ }
109
+ const cookieHeader = request.headers.get("cookie") ?? "";
110
+ if (!cookieHeader) return null;
111
+ const res = await fetch(`${appUrl}/api/auth/get-session`, {
112
+ method: "GET",
113
+ headers: { cookie: cookieHeader }
114
+ });
115
+ if (!res.ok) return null;
116
+ const data = await res.json();
117
+ if (!data?.user || !data?.session) return null;
118
+ return {
119
+ user: {
120
+ id: data.user.id,
121
+ email: data.user.email,
122
+ name: data.user.name ?? null,
123
+ avatarUrl: data.user.image ?? null,
124
+ emailVerified: data.user.emailVerified ? /* @__PURE__ */ new Date() : null
125
+ },
126
+ sessionId: data.session.id,
127
+ expiresAt: new Date(data.session.expiresAt)
128
+ };
129
+ }
130
+ /**
131
+ * Generate an OAuth authorization URL.
132
+ */
133
+ async getOAuthUrl(provider, options) {
134
+ const appUrl = this._appUrl;
135
+ if (!appUrl) {
136
+ throw new BrokrError("[brokr] BETTER_AUTH_URL is not set.", "AUTH_NOT_CONFIGURED", "auth");
137
+ }
138
+ const redirectTo = options?.redirectTo ?? "/";
139
+ if (!redirectTo.startsWith("/") || redirectTo.startsWith("//")) {
140
+ throw new BrokrError("[brokr] redirectTo must be a relative path (start with /)", "INVALID_REDIRECT", "auth");
141
+ }
142
+ const params = new URLSearchParams({ callbackURL: redirectTo });
143
+ return { redirectUrl: `${appUrl}/api/auth/sign-in/social?provider=${provider}&${params}` };
144
+ }
145
+ /**
146
+ * Send a magic link email (requires email capability).
147
+ */
148
+ async sendMagicLink(email, options) {
149
+ const appUrl = this._appUrl;
150
+ if (!appUrl) {
151
+ throw new BrokrError("[brokr] BETTER_AUTH_URL is not set.", "AUTH_NOT_CONFIGURED", "auth");
152
+ }
153
+ const res = await fetch(`${appUrl}/api/auth/magic-link/send`, {
154
+ method: "POST",
155
+ headers: { "Content-Type": "application/json" },
156
+ body: JSON.stringify({ email, callbackURL: options?.redirectTo ?? "/" })
157
+ });
158
+ if (!res.ok) {
159
+ const data = await res.json().catch(() => ({}));
160
+ throw new BrokrError(
161
+ data.message ?? `[brokr] Failed to send magic link (HTTP ${res.status})`,
162
+ "AUTH_MAGIC_LINK_FAILED",
163
+ "auth"
164
+ );
165
+ }
166
+ }
167
+ };
168
+ }
169
+ });
170
+ init_auth();
171
+ // Annotate the CommonJS export names for ESM import in node:
172
+ 0 && (module.exports = {
173
+ BrokrAuthClient,
174
+ authMiddleware
175
+ });
package/dist/auth.mjs ADDED
@@ -0,0 +1,151 @@
1
+ var __getOwnPropNames = Object.getOwnPropertyNames;
2
+ var __esm = (fn, res) => function __init() {
3
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
4
+ };
5
+
6
+ // src/runtime.ts
7
+ var BrokrError;
8
+ var init_runtime = __esm({
9
+ "src/runtime.ts"() {
10
+ "use strict";
11
+ BrokrError = class extends Error {
12
+ constructor(message, code, capability, retryable = false) {
13
+ super(message);
14
+ this.code = code;
15
+ this.capability = capability;
16
+ this.retryable = retryable;
17
+ this.name = "BrokrError";
18
+ }
19
+ };
20
+ }
21
+ });
22
+
23
+ // src/auth.ts
24
+ function parseCookies(cookieHeader) {
25
+ const cookies = /* @__PURE__ */ new Map();
26
+ for (const pair of cookieHeader.split(";")) {
27
+ const eqIdx = pair.indexOf("=");
28
+ if (eqIdx === -1) continue;
29
+ const name = pair.slice(0, eqIdx).trim();
30
+ const value = pair.slice(eqIdx + 1).trim();
31
+ if (name) cookies.set(name, value);
32
+ }
33
+ return cookies;
34
+ }
35
+ function authMiddleware(options) {
36
+ const { protectedRoutes = [], publicOnlyRoutes = [] } = options;
37
+ return async function middleware(request) {
38
+ const url = new URL(request.url);
39
+ const pathname = url.pathname;
40
+ const isProtected = protectedRoutes.some((route) => pathname.startsWith(route));
41
+ const isPublicOnly = publicOnlyRoutes.some((route) => pathname.startsWith(route));
42
+ if (!isProtected && !isPublicOnly) return void 0;
43
+ const cookieHeader = request.headers.get("cookie") ?? "";
44
+ const cookies = parseCookies(cookieHeader);
45
+ const hasSession = cookies.has("better-auth.session_token");
46
+ if (isProtected && !hasSession) {
47
+ return Response.redirect(new URL("/sign-in", request.url).toString(), 302);
48
+ }
49
+ if (isPublicOnly && hasSession) {
50
+ return Response.redirect(new URL("/", request.url).toString(), 302);
51
+ }
52
+ return void 0;
53
+ };
54
+ }
55
+ var BrokrAuthClient;
56
+ var init_auth = __esm({
57
+ "src/auth.ts"() {
58
+ init_runtime();
59
+ BrokrAuthClient = class {
60
+ constructor(token, gatewayUrl, appUrl) {
61
+ this._token = token;
62
+ this._gatewayUrl = gatewayUrl;
63
+ this._appUrl = appUrl ?? (typeof process !== "undefined" ? process.env.BETTER_AUTH_URL : void 0);
64
+ }
65
+ /**
66
+ * Get current user from an incoming request's cookies.
67
+ * Calls the local Better Auth API (runs inside your app).
68
+ */
69
+ async currentUser(request) {
70
+ const session = await this.getSession(request);
71
+ return session?.user ?? null;
72
+ }
73
+ /**
74
+ * Get the full session (user + metadata) from an incoming request.
75
+ * Calls the local Better Auth API.
76
+ */
77
+ async getSession(request) {
78
+ const appUrl = this._appUrl;
79
+ if (!appUrl) {
80
+ throw new BrokrError(
81
+ "[brokr] BETTER_AUTH_URL is not set. Auth may not be provisioned.",
82
+ "AUTH_NOT_CONFIGURED",
83
+ "auth"
84
+ );
85
+ }
86
+ const cookieHeader = request.headers.get("cookie") ?? "";
87
+ if (!cookieHeader) return null;
88
+ const res = await fetch(`${appUrl}/api/auth/get-session`, {
89
+ method: "GET",
90
+ headers: { cookie: cookieHeader }
91
+ });
92
+ if (!res.ok) return null;
93
+ const data = await res.json();
94
+ if (!data?.user || !data?.session) return null;
95
+ return {
96
+ user: {
97
+ id: data.user.id,
98
+ email: data.user.email,
99
+ name: data.user.name ?? null,
100
+ avatarUrl: data.user.image ?? null,
101
+ emailVerified: data.user.emailVerified ? /* @__PURE__ */ new Date() : null
102
+ },
103
+ sessionId: data.session.id,
104
+ expiresAt: new Date(data.session.expiresAt)
105
+ };
106
+ }
107
+ /**
108
+ * Generate an OAuth authorization URL.
109
+ */
110
+ async getOAuthUrl(provider, options) {
111
+ const appUrl = this._appUrl;
112
+ if (!appUrl) {
113
+ throw new BrokrError("[brokr] BETTER_AUTH_URL is not set.", "AUTH_NOT_CONFIGURED", "auth");
114
+ }
115
+ const redirectTo = options?.redirectTo ?? "/";
116
+ if (!redirectTo.startsWith("/") || redirectTo.startsWith("//")) {
117
+ throw new BrokrError("[brokr] redirectTo must be a relative path (start with /)", "INVALID_REDIRECT", "auth");
118
+ }
119
+ const params = new URLSearchParams({ callbackURL: redirectTo });
120
+ return { redirectUrl: `${appUrl}/api/auth/sign-in/social?provider=${provider}&${params}` };
121
+ }
122
+ /**
123
+ * Send a magic link email (requires email capability).
124
+ */
125
+ async sendMagicLink(email, options) {
126
+ const appUrl = this._appUrl;
127
+ if (!appUrl) {
128
+ throw new BrokrError("[brokr] BETTER_AUTH_URL is not set.", "AUTH_NOT_CONFIGURED", "auth");
129
+ }
130
+ const res = await fetch(`${appUrl}/api/auth/magic-link/send`, {
131
+ method: "POST",
132
+ headers: { "Content-Type": "application/json" },
133
+ body: JSON.stringify({ email, callbackURL: options?.redirectTo ?? "/" })
134
+ });
135
+ if (!res.ok) {
136
+ const data = await res.json().catch(() => ({}));
137
+ throw new BrokrError(
138
+ data.message ?? `[brokr] Failed to send magic link (HTTP ${res.status})`,
139
+ "AUTH_MAGIC_LINK_FAILED",
140
+ "auth"
141
+ );
142
+ }
143
+ }
144
+ };
145
+ }
146
+ });
147
+ init_auth();
148
+ export {
149
+ BrokrAuthClient,
150
+ authMiddleware
151
+ };
@@ -0,0 +1,333 @@
1
+ """
2
+ Brokr Runtime SDK — Python
3
+ ==========================
4
+
5
+ Drop-in client for apps provisioned by Brokr.
6
+ Reads BROKR_TOKEN from env — auto-injected at deploy time.
7
+
8
+ Usage::
9
+
10
+ from brokr_runtime import Brokr
11
+
12
+ brokr = Brokr()
13
+ reply = brokr.ai.chat([{"role": "user", "content": "Hello"}])
14
+ print(reply.content)
15
+
16
+ No dependencies beyond the Python standard library. Requires Python 3.8+.
17
+ """
18
+
19
+ import json
20
+ import os
21
+ import urllib.error
22
+ import urllib.request
23
+ from dataclasses import dataclass
24
+ from typing import Any, Dict, List, Optional, Union
25
+
26
+ _GATEWAY_URL = "https://api.brokr.sh"
27
+ _DEFAULT_TIMEOUT = 30
28
+
29
+
30
+ # ---------------------------------------------------------------------------
31
+ # Error hierarchy
32
+ # ---------------------------------------------------------------------------
33
+
34
+
35
+ class BrokrError(Exception):
36
+ """Base Brokr SDK error."""
37
+
38
+ def __init__(self, message: str, code: str = "UNKNOWN", capability: str = "",
39
+ retryable: bool = False):
40
+ super().__init__(message)
41
+ self.code = code
42
+ self.capability = capability
43
+ self.retryable = retryable
44
+
45
+
46
+ class BrokrAuthError(BrokrError):
47
+ """Token missing or invalid."""
48
+
49
+ def __init__(self, message: str, code: str = "BROKR_TOKEN_MISSING"):
50
+ super().__init__(message, code, "auth", False)
51
+
52
+
53
+ class BrokrRateLimitError(BrokrError):
54
+ """HTTP 429 — rate limited."""
55
+
56
+ def __init__(self, message: str, retry_after: int = 60, capability: str = ""):
57
+ super().__init__(message, "RATE_LIMITED", capability, True)
58
+ self.retry_after = retry_after
59
+
60
+
61
+ class BrokrNetworkError(BrokrError):
62
+ """Gateway unreachable."""
63
+
64
+ def __init__(self, message: str, capability: str = ""):
65
+ super().__init__(message, "NETWORK_ERROR", capability, True)
66
+
67
+
68
+ # ---------------------------------------------------------------------------
69
+ # Response dataclasses
70
+ # ---------------------------------------------------------------------------
71
+
72
+
73
+ @dataclass
74
+ class TokenUsage:
75
+ prompt_tokens: int
76
+ completion_tokens: int
77
+
78
+
79
+ @dataclass
80
+ class ChatResponse:
81
+ content: str
82
+ model: str
83
+ usage: TokenUsage
84
+
85
+
86
+ @dataclass
87
+ class UploadResult:
88
+ key: str
89
+ url: str
90
+
91
+
92
+ @dataclass
93
+ class EmailResult:
94
+ id: str
95
+
96
+
97
+ # ---------------------------------------------------------------------------
98
+ # Internal helpers
99
+ # ---------------------------------------------------------------------------
100
+
101
+
102
+ def _validate_token(token: Optional[str], capability: str) -> str:
103
+ if not token:
104
+ raise BrokrAuthError(
105
+ "[brokr] BROKR_TOKEN is not set.\n"
106
+ "Brokr injects this automatically at deploy time.\n"
107
+ "For local development, run: brokr env pull --stack <name>"
108
+ )
109
+ return token
110
+
111
+
112
+ def _gateway_request(
113
+ gateway_url: str, token: str, path: str, payload: dict, capability: str,
114
+ timeout: int = _DEFAULT_TIMEOUT,
115
+ ) -> Any:
116
+ data = json.dumps(payload).encode()
117
+ req = urllib.request.Request(
118
+ f"{gateway_url}{path}",
119
+ data=data,
120
+ headers={
121
+ "Content-Type": "application/json",
122
+ "Authorization": f"Bearer {token}",
123
+ },
124
+ method="POST",
125
+ )
126
+ try:
127
+ with urllib.request.urlopen(req, timeout=timeout) as resp:
128
+ return json.loads(resp.read())
129
+ except urllib.error.HTTPError as e:
130
+ if e.code == 429:
131
+ raise BrokrRateLimitError(
132
+ f"[brokr] Rate limited on {capability}.",
133
+ retry_after=60,
134
+ capability=capability,
135
+ ) from e
136
+ if e.code == 401:
137
+ raise BrokrAuthError("[brokr] Invalid or expired BROKR_TOKEN.",
138
+ "BROKR_TOKEN_INVALID") from e
139
+ raise BrokrError(
140
+ f"[brokr] {capability} request failed: HTTP {e.code}",
141
+ f"{capability.upper()}_FAILED",
142
+ capability,
143
+ ) from e
144
+ except (urllib.error.URLError, OSError) as e:
145
+ raise BrokrNetworkError(
146
+ f"[brokr] Could not reach Brokr gateway: {e}",
147
+ capability,
148
+ ) from e
149
+
150
+
151
+ # ---------------------------------------------------------------------------
152
+ # BrokrAI
153
+ # ---------------------------------------------------------------------------
154
+
155
+
156
+ class BrokrAI:
157
+ def __init__(self, token: Optional[str], gateway_url: str) -> None:
158
+ self._token = token
159
+ self._gateway_url = gateway_url
160
+
161
+ def chat(
162
+ self,
163
+ messages: List[Dict[str, str]],
164
+ *,
165
+ model: Optional[str] = None,
166
+ max_tokens: Optional[int] = None,
167
+ temperature: Optional[float] = None,
168
+ ) -> ChatResponse:
169
+ """
170
+ Send messages to the Brokr AI gateway.
171
+
172
+ Returns a ChatResponse dataclass with .content, .model, and .usage.
173
+ """
174
+ token = _validate_token(self._token, "ai")
175
+ payload: Dict[str, Any] = {"messages": messages}
176
+ if model:
177
+ payload["model"] = model
178
+ if max_tokens:
179
+ payload["max_tokens"] = max_tokens
180
+ if temperature is not None:
181
+ payload["temperature"] = temperature
182
+
183
+ body = _gateway_request(self._gateway_url, token,
184
+ "/v1/chat/completions", payload, "ai")
185
+
186
+ choices = body.get("choices") or [{}]
187
+ usage_raw = body.get("usage", {})
188
+
189
+ return ChatResponse(
190
+ content=choices[0].get("message", {}).get("content", ""),
191
+ model=body.get("model", ""),
192
+ usage=TokenUsage(
193
+ prompt_tokens=usage_raw.get("prompt_tokens", 0),
194
+ completion_tokens=usage_raw.get("completion_tokens", 0),
195
+ ),
196
+ )
197
+
198
+ @property
199
+ def base_url(self) -> str:
200
+ """OpenAI-SDK compatible base URL."""
201
+ return f"{self._gateway_url}/v1"
202
+
203
+ @property
204
+ def api_key(self) -> str:
205
+ """Returns BROKR_TOKEN — use as api_key with the openai package."""
206
+ return _validate_token(self._token, "ai")
207
+
208
+
209
+ # ---------------------------------------------------------------------------
210
+ # BrokrStorage
211
+ # ---------------------------------------------------------------------------
212
+
213
+
214
+ class BrokrStorage:
215
+ def __init__(self, token: Optional[str], gateway_url: str) -> None:
216
+ self._token = token
217
+ self._gateway_url = gateway_url
218
+
219
+ def get_upload_url(
220
+ self, filename: str, content_type: str = "application/octet-stream",
221
+ ) -> Dict[str, Any]:
222
+ """Get a presigned upload URL + object key."""
223
+ token = _validate_token(self._token, "storage")
224
+ return _gateway_request(
225
+ self._gateway_url, token, "/v1/storage/sign-upload",
226
+ {"filename": filename, "contentType": content_type}, "storage",
227
+ )
228
+
229
+ def upload(
230
+ self, data: Union[bytes, str], filename: str,
231
+ content_type: str = "application/octet-stream",
232
+ ) -> UploadResult:
233
+ """Upload data to R2 storage."""
234
+ result = self.get_upload_url(filename, content_type)
235
+ body = data if isinstance(data, bytes) else data.encode()
236
+ put_req = urllib.request.Request(
237
+ result["url"], data=body,
238
+ headers={"Content-Type": content_type}, method="PUT",
239
+ )
240
+ try:
241
+ with urllib.request.urlopen(put_req, timeout=_DEFAULT_TIMEOUT):
242
+ pass
243
+ except urllib.error.HTTPError as e:
244
+ raise BrokrError(f"[brokr] Upload failed: HTTP {e.code}",
245
+ "STORAGE_UPLOAD_FAILED", "storage") from e
246
+
247
+ return UploadResult(key=result["key"], url=result["url"])
248
+
249
+ def url(self, key: str, expires_in: Optional[int] = None) -> Dict[str, Any]:
250
+ """Get a presigned download URL for a stored object key."""
251
+ token = _validate_token(self._token, "storage")
252
+ payload: Dict[str, Any] = {"key": key}
253
+ if expires_in is not None:
254
+ payload["expiresIn"] = expires_in
255
+ return _gateway_request(
256
+ self._gateway_url, token, "/v1/storage/sign-download",
257
+ payload, "storage",
258
+ )
259
+
260
+ def get_url(self, key: str, expires_in: Optional[int] = None) -> Dict[str, Any]:
261
+ """Deprecated — use url() instead."""
262
+ return self.url(key, expires_in)
263
+
264
+
265
+ # ---------------------------------------------------------------------------
266
+ # BrokrEmail
267
+ # ---------------------------------------------------------------------------
268
+
269
+
270
+ class BrokrEmail:
271
+ """Routes email through the Brokr gateway — only BROKR_TOKEN required."""
272
+
273
+ def __init__(self, token: Optional[str], gateway_url: str) -> None:
274
+ self._token = token
275
+ self._gateway_url = gateway_url
276
+
277
+ def send(
278
+ self,
279
+ to: Union[str, List[str]],
280
+ subject: str,
281
+ *,
282
+ html: Optional[str] = None,
283
+ text: Optional[str] = None,
284
+ from_: Optional[str] = None,
285
+ ) -> EmailResult:
286
+ """Send an email via the Brokr gateway."""
287
+ token = _validate_token(self._token, "email")
288
+ payload: Dict[str, Any] = {"to": to, "subject": subject}
289
+ if from_:
290
+ payload["from"] = from_
291
+ if html:
292
+ payload["html"] = html
293
+ if text:
294
+ payload["text"] = text
295
+
296
+ result = _gateway_request(
297
+ self._gateway_url, token, "/v1/email/send", payload, "email",
298
+ )
299
+ return EmailResult(id=result.get("id", ""))
300
+
301
+
302
+ # ---------------------------------------------------------------------------
303
+ # Brokr (top-level)
304
+ # ---------------------------------------------------------------------------
305
+
306
+
307
+ class Brokr:
308
+ """
309
+ Brokr runtime client. Zero config required.
310
+
311
+ All env vars are injected automatically by Brokr at provision time.
312
+
313
+ Example::
314
+
315
+ from brokr_runtime import Brokr
316
+
317
+ brokr = Brokr()
318
+ reply = brokr.ai.chat([{"role": "user", "content": "Summarize this..."}])
319
+ print(reply.content)
320
+ """
321
+
322
+ def __init__(
323
+ self,
324
+ *,
325
+ token: Optional[str] = None,
326
+ gateway_url: Optional[str] = None,
327
+ ) -> None:
328
+ _token = token or os.environ.get("BROKR_TOKEN")
329
+ _gateway = gateway_url or _GATEWAY_URL
330
+
331
+ self.ai = BrokrAI(_token, _gateway)
332
+ self.storage = BrokrStorage(_token, _gateway)
333
+ self.email = BrokrEmail(_token, _gateway)
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Brokr SDK — root entry point
3
+ *
4
+ * Runtime client (for deployed apps):
5
+ * import { createBrokr } from '@brokr/sdk';
6
+ *
7
+ * Management client (for CLI / provisioning tools):
8
+ * import { createBrokrClient } from '@brokr/sdk';
9
+ */
10
+ export { createBrokr, BrokrRuntime, BrokrAIClient, BrokrStorageClient, BrokrEmailClient, BrokrError } from './src/runtime';
11
+ export type { ChatMessage, ChatResponse, EmailParams, UploadResult, RuntimeOptions } from './src/runtime';
12
+ export { authMiddleware } from './src/auth';
13
+ export type { AuthUser, AuthSession } from './src/auth';
14
+ export { BrokrClient, create, default as createBrokrClient } from './src/management';
15
+ export type { BrokrConfig } from './src/management';
16
+ export type { StackResponse, ProviderResponse, CreateStackInput, AddProviderInput } from './types';
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3H,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAG1G,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAGxD,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrF,YAAY,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAGpD,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC"}