@seanhogg/builderforce-sdk 0.4.0 → 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.
- package/README.md +28 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Typed TypeScript SDK for the [Builderforce.ai](https://builderforce.ai) LLM gateway. OpenAI-compatible chat completions with tool calling and structured output, embeddings, model registry, and usage analytics — all behind a single tenant API key. Vendor failover (OpenRouter / Cerebras / Ollama / Claude / GPT / Gemini / Grok) is handled server-side so your code only knows about Builderforce.
|
|
4
4
|
|
|
5
5
|
- **Vanilla `fetch` / `AbortController` / `ReadableStream` / `TextDecoder`** — runs on Node 18+, Cloudflare Workers, browsers, edge runtimes.
|
|
6
|
-
- **Zero runtime dependencies.** ~
|
|
6
|
+
- **Zero runtime dependencies.** ~23 kB compressed, ~102 kB unpacked.
|
|
7
7
|
- **Dual ESM + CJS + `.d.ts`** out of the box.
|
|
8
8
|
|
|
9
9
|
## Install
|
|
@@ -18,9 +18,9 @@ npm install @seanhogg/builderforce-sdk
|
|
|
18
18
|
import { BuilderforceClient } from '@seanhogg/builderforce-sdk';
|
|
19
19
|
|
|
20
20
|
const client = new BuilderforceClient({
|
|
21
|
-
apiKey:
|
|
21
|
+
apiKey: process.env.BUILDERFORCE_API_KEY!,
|
|
22
|
+
baseUrl: process.env.BUILDERFORCE_BASE_URL ?? 'https://api.builderforce.ai',
|
|
22
23
|
// Optional:
|
|
23
|
-
// baseUrl: 'https://api.builderforce.ai',
|
|
24
24
|
// timeoutMs: 60_000,
|
|
25
25
|
});
|
|
26
26
|
|
|
@@ -31,6 +31,13 @@ const res = await client.chat.completions.create({
|
|
|
31
31
|
console.log(res.choices?.[0]?.message?.content);
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
+
**Env-var convention:**
|
|
35
|
+
|
|
36
|
+
| Var | Required | Value |
|
|
37
|
+
|---|---|---|
|
|
38
|
+
| `BUILDERFORCE_API_KEY` | yes | Your `bfk_*` / `clk_*` / tenant-JWT (mint at `/settings/api-keys`) |
|
|
39
|
+
| `BUILDERFORCE_BASE_URL` | no | `https://api.builderforce.ai` (production). Override for staging or self-hosted gateways. |
|
|
40
|
+
|
|
34
41
|
When you don't pass a `model`, the gateway picks one from your plan's pool and reorders by **request shape** — presence of `tools`, `response_format`, image content blocks. When you do pass a `model`, the gateway treats it as a hint (it tries that model first, may substitute on cooldown / failure — read `_builderforce.resolvedModel` to detect substitution). See [docs/SCENARIOS.md](./docs/SCENARIOS.md) for typical request shapes per scenario.
|
|
35
42
|
|
|
36
43
|
## Auth
|
|
@@ -39,10 +46,26 @@ The SDK sends `Authorization: Bearer <apiKey>` automatically. The gateway accept
|
|
|
39
46
|
|
|
40
47
|
| Prefix | Issued by | Best for |
|
|
41
48
|
|---|---|---|
|
|
42
|
-
| `bfk_*` | `POST /api/tenants/:tenantId/api-keys` (owner-only) | Tenant apps (server-to-server). Long-lived, tenant-scoped, revocable. |
|
|
49
|
+
| `bfk_*` | `POST /api/tenants/:tenantId/api-keys` (owner-only) | Tenant apps (server-to-server). Long-lived, tenant-scoped, revocable, optional origin allowlist. |
|
|
43
50
|
| `clk_*` | `POST /api/claws` (CoderClaw registration) | Self-hosted CoderClaw instances; carries optional per-claw daily token cap. |
|
|
44
51
|
| Tenant JWT | `POST /api/auth/web/login` → `POST /api/auth/tenant-token` | Browser-side calls from a logged-in user. Short-lived. |
|
|
45
52
|
|
|
53
|
+
### Browser use & origin allowlist
|
|
54
|
+
|
|
55
|
+
By default, every `bfk_*` is a **server-only** key — any request that arrives with an `Origin` header (i.e. came from a browser) is rejected with `403`. This protects against the common failure mode of leaking a long-lived secret through devtools.
|
|
56
|
+
|
|
57
|
+
To use a key from a browser, register the allowed origins when minting it (in the portal at `/settings/api-keys`, or via the SDK):
|
|
58
|
+
|
|
59
|
+
| Allowlist | Browser behaviour |
|
|
60
|
+
|---|---|
|
|
61
|
+
| `null` (default) | Server-only. Browser requests rejected. |
|
|
62
|
+
| `['https://app.example.com']` | Browser calls allowed only from `https://app.example.com`. Exact match — no port/subdomain wildcards. |
|
|
63
|
+
| `['*']` | Any origin allowed. Escape hatch — equivalent to shipping a long-lived secret to the world. Don't. |
|
|
64
|
+
|
|
65
|
+
When you change a key's allowlist later, in-flight calls are unaffected; new calls take the new policy on the next request.
|
|
66
|
+
|
|
67
|
+
The SDK preflight headers (`Authorization`, `Idempotency-Key`, `Content-Type`) and exposed response headers (`x-builderforce-daily-tokens-*`, `x-request-id`) are all configured on the gateway's CORS policy — your origin only needs to be in your key's allowlist.
|
|
68
|
+
|
|
46
69
|
## Streaming chat
|
|
47
70
|
|
|
48
71
|
```ts
|
|
@@ -285,6 +308,7 @@ try {
|
|
|
285
308
|
| 409 | `idempotent_replay` | `Idempotency-Key` was used within the last 10 min — treat as no-op |
|
|
286
309
|
| 429 | `plan_token_limit_exceeded` | Tenant hit daily plan budget |
|
|
287
310
|
| 429 | `claw_token_limit_exceeded` | Per-claw daily cap exceeded (`clk_*` keys only) |
|
|
311
|
+
| 403 | `origin_not_authorized` | Browser request from an origin not in the key's allowlist (or key has no allowlist — server-only) |
|
|
288
312
|
| 503 | (no code) | Vendor key not configured for the active plan tier |
|
|
289
313
|
| 401 | `missing_api_key` | Auth issues |
|
|
290
314
|
| 403 | (varied) | Wrong scope / wrong tenant for the URL |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seanhogg/builderforce-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Typed SDK for the Builderforce.ai LLM gateway — chat completions with tool-calling and structured output, embeddings, models, and usage analytics over an OpenAI-compatible surface.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Sean Hogg",
|