@seanhogg/builderforce-sdk 0.2.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/LICENSE +21 -0
- package/README.md +98 -0
- package/dist/index.cjs +303 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +200 -0
- package/dist/index.d.ts +200 -0
- package/dist/index.mjs +272 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +61 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sean Hogg
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# @seanhogg/builderforce-sdk
|
|
2
|
+
|
|
3
|
+
Typed SDK for Builderforce LLM gateway APIs.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @seanhogg/builderforce-sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick start
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { BuilderforceClient } from '@seanhogg/builderforce-sdk';
|
|
15
|
+
|
|
16
|
+
const client = new BuilderforceClient({
|
|
17
|
+
apiKey: process.env.BUILDERFORCE_API_KEY!,
|
|
18
|
+
// Optional:
|
|
19
|
+
// baseUrl: 'https://api.builderforce.ai',
|
|
20
|
+
// timeoutMs: 60_000,
|
|
21
|
+
});
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Non-streaming chat
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
const res = await client.chat.completions.create({
|
|
28
|
+
useCase: 'ide.chat',
|
|
29
|
+
stream: false,
|
|
30
|
+
messages: [{ role: 'user', content: 'Summarize this PRD.' }],
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
console.log(res.choices?.[0]?.message?.content);
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Streaming chat
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
const stream = await client.chat.completions.create({
|
|
40
|
+
useCase: 'coach.chat',
|
|
41
|
+
stream: true,
|
|
42
|
+
messages: [{ role: 'user', content: 'Give me a weekly plan.' }],
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
for await (const chunk of stream) {
|
|
46
|
+
const delta = chunk.choices?.[0]?.delta?.content ?? '';
|
|
47
|
+
process.stdout.write(delta);
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Or collect all streaming text:
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
const text = await stream.toText();
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Models and usage
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
const models = await client.models.list();
|
|
61
|
+
const usage = await client.usage.get({ days: 30 });
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Errors
|
|
65
|
+
|
|
66
|
+
SDK requests throw `BuilderforceApiError` on non-2xx responses:
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
import { BuilderforceApiError } from '@seanhogg/builderforce-sdk';
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
await client.models.list();
|
|
73
|
+
} catch (error) {
|
|
74
|
+
if (error instanceof BuilderforceApiError) {
|
|
75
|
+
console.error(error.status, error.code, error.requestId, error.message);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Auth conventions
|
|
81
|
+
|
|
82
|
+
The SDK sends `Authorization: Bearer <apiKey>` automatically. The gateway accepts three credential types:
|
|
83
|
+
|
|
84
|
+
| Prefix | Issued by | Best for |
|
|
85
|
+
|---|---|---|
|
|
86
|
+
| `bfk_*` | `POST /api/tenants/:tenantId/api-keys` (owner-only) | Tenant apps (server-to-server). Long-lived, tenant-scoped, revocable. |
|
|
87
|
+
| `clk_*` | `POST /api/claws` (CoderClaw registration) | Self-hosted CoderClaw instances; carries optional per-claw daily token cap. |
|
|
88
|
+
| Tenant JWT | `POST /api/auth/web/login` → `POST /api/auth/tenant-token` | Browser-side calls from a logged-in user. Short-lived. |
|
|
89
|
+
|
|
90
|
+
Workforce model routing is server-side: pass `model: 'builderforce/workforce-<agentId>'` when needed.
|
|
91
|
+
|
|
92
|
+
## Use-case safety
|
|
93
|
+
|
|
94
|
+
`AIUseCase` is exported for compile-time checks:
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
import type { AIUseCase } from '@seanhogg/builderforce-sdk';
|
|
98
|
+
```
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,303 @@
|
|
|
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 __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
AI_USE_CASES: () => AI_USE_CASES,
|
|
24
|
+
BuilderforceApiError: () => BuilderforceApiError,
|
|
25
|
+
BuilderforceClient: () => BuilderforceClient,
|
|
26
|
+
ChatCompletionStream: () => ChatCompletionStream,
|
|
27
|
+
isAIUseCase: () => isAIUseCase
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(index_exports);
|
|
30
|
+
|
|
31
|
+
// src/infrastructure/sse.ts
|
|
32
|
+
async function* parseSseJson(stream) {
|
|
33
|
+
const reader = stream.getReader();
|
|
34
|
+
const decoder = new TextDecoder();
|
|
35
|
+
let buffer = "";
|
|
36
|
+
while (true) {
|
|
37
|
+
const { done, value } = await reader.read();
|
|
38
|
+
if (done) break;
|
|
39
|
+
buffer += decoder.decode(value, { stream: true });
|
|
40
|
+
const lines = buffer.split("\n");
|
|
41
|
+
buffer = lines.pop() ?? "";
|
|
42
|
+
for (const line of lines) {
|
|
43
|
+
const trimmed = line.trim();
|
|
44
|
+
if (!trimmed.startsWith("data: ")) continue;
|
|
45
|
+
const data = trimmed.slice(6).trim();
|
|
46
|
+
if (data === "[DONE]") return;
|
|
47
|
+
try {
|
|
48
|
+
yield JSON.parse(data);
|
|
49
|
+
} catch {
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// src/application/ChatCompletionsApi.ts
|
|
56
|
+
var ChatCompletionStream = class {
|
|
57
|
+
stream;
|
|
58
|
+
constructor(stream) {
|
|
59
|
+
this.stream = stream;
|
|
60
|
+
}
|
|
61
|
+
[Symbol.asyncIterator]() {
|
|
62
|
+
return parseSseJson(this.stream);
|
|
63
|
+
}
|
|
64
|
+
async toText() {
|
|
65
|
+
let full = "";
|
|
66
|
+
for await (const chunk of this) {
|
|
67
|
+
const delta = chunk.choices?.[0]?.delta?.content;
|
|
68
|
+
if (typeof delta === "string") {
|
|
69
|
+
full += delta;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return full;
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
var ChatCompletionsApi = class {
|
|
76
|
+
http;
|
|
77
|
+
constructor(http) {
|
|
78
|
+
this.http = http;
|
|
79
|
+
}
|
|
80
|
+
async create(params) {
|
|
81
|
+
if (params.stream) {
|
|
82
|
+
const response = await this.http.postRaw("/llm/v1/chat/completions", params);
|
|
83
|
+
if (!response.body) {
|
|
84
|
+
throw new Error("Streaming response body is missing");
|
|
85
|
+
}
|
|
86
|
+
return new ChatCompletionStream(response.body);
|
|
87
|
+
}
|
|
88
|
+
return this.http.postJson("/llm/v1/chat/completions", params);
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// src/application/ModelsApi.ts
|
|
93
|
+
var ModelsApi = class {
|
|
94
|
+
http;
|
|
95
|
+
constructor(http) {
|
|
96
|
+
this.http = http;
|
|
97
|
+
}
|
|
98
|
+
list() {
|
|
99
|
+
return this.http.getJson("/llm/v1/models");
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
// src/application/UsageApi.ts
|
|
104
|
+
var UsageApi = class {
|
|
105
|
+
http;
|
|
106
|
+
constructor(http) {
|
|
107
|
+
this.http = http;
|
|
108
|
+
}
|
|
109
|
+
get(params = {}) {
|
|
110
|
+
const query = typeof params.days === "number" ? `?days=${encodeURIComponent(String(params.days))}` : "";
|
|
111
|
+
return this.http.getJson(`/llm/v1/usage${query}`);
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
// src/infrastructure/httpClient.ts
|
|
116
|
+
var BuilderforceApiError = class extends Error {
|
|
117
|
+
status;
|
|
118
|
+
code;
|
|
119
|
+
details;
|
|
120
|
+
requestId;
|
|
121
|
+
constructor(message, status, code, details, requestId) {
|
|
122
|
+
super(message);
|
|
123
|
+
this.name = "BuilderforceApiError";
|
|
124
|
+
this.status = status;
|
|
125
|
+
this.code = code;
|
|
126
|
+
this.details = details;
|
|
127
|
+
this.requestId = requestId;
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
var HttpClient = class {
|
|
131
|
+
apiKey;
|
|
132
|
+
baseUrl;
|
|
133
|
+
fetchFn;
|
|
134
|
+
timeoutMs;
|
|
135
|
+
constructor(options) {
|
|
136
|
+
this.apiKey = options.apiKey;
|
|
137
|
+
this.baseUrl = options.baseUrl.replace(/\/$/, "");
|
|
138
|
+
this.fetchFn = options.fetchFn ?? fetch;
|
|
139
|
+
this.timeoutMs = options.timeoutMs ?? 6e4;
|
|
140
|
+
}
|
|
141
|
+
async getJson(path) {
|
|
142
|
+
const res = await this.fetchWithTimeout(`${this.baseUrl}${path}`, {
|
|
143
|
+
method: "GET",
|
|
144
|
+
headers: this.authHeaders()
|
|
145
|
+
});
|
|
146
|
+
return this.parseJsonResponse(res);
|
|
147
|
+
}
|
|
148
|
+
async postJson(path, body) {
|
|
149
|
+
const res = await this.fetchWithTimeout(`${this.baseUrl}${path}`, {
|
|
150
|
+
method: "POST",
|
|
151
|
+
headers: {
|
|
152
|
+
...this.authHeaders(),
|
|
153
|
+
"Content-Type": "application/json"
|
|
154
|
+
},
|
|
155
|
+
body: JSON.stringify(body)
|
|
156
|
+
});
|
|
157
|
+
return this.parseJsonResponse(res);
|
|
158
|
+
}
|
|
159
|
+
async postRaw(path, body) {
|
|
160
|
+
const res = await this.fetchWithTimeout(`${this.baseUrl}${path}`, {
|
|
161
|
+
method: "POST",
|
|
162
|
+
headers: {
|
|
163
|
+
...this.authHeaders(),
|
|
164
|
+
"Content-Type": "application/json"
|
|
165
|
+
},
|
|
166
|
+
body: JSON.stringify(body)
|
|
167
|
+
});
|
|
168
|
+
if (!res.ok) {
|
|
169
|
+
throw await this.toApiError(res);
|
|
170
|
+
}
|
|
171
|
+
return res;
|
|
172
|
+
}
|
|
173
|
+
authHeaders() {
|
|
174
|
+
return {
|
|
175
|
+
Authorization: `Bearer ${this.apiKey}`
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
async fetchWithTimeout(input, init) {
|
|
179
|
+
const controller = new AbortController();
|
|
180
|
+
const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
181
|
+
try {
|
|
182
|
+
return await this.fetchFn(input, { ...init, signal: controller.signal });
|
|
183
|
+
} catch (error) {
|
|
184
|
+
if (controller.signal.aborted) {
|
|
185
|
+
throw new BuilderforceApiError(`Request timed out after ${this.timeoutMs}ms`, 408, "timeout");
|
|
186
|
+
}
|
|
187
|
+
throw error;
|
|
188
|
+
} finally {
|
|
189
|
+
clearTimeout(timeout);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
async parseJsonResponse(res) {
|
|
193
|
+
if (!res.ok) {
|
|
194
|
+
throw await this.toApiError(res);
|
|
195
|
+
}
|
|
196
|
+
return res.json();
|
|
197
|
+
}
|
|
198
|
+
async toApiError(res) {
|
|
199
|
+
const fallback = `Request failed (${res.status})`;
|
|
200
|
+
const requestId = res.headers.get("x-request-id") ?? void 0;
|
|
201
|
+
try {
|
|
202
|
+
const payload = await res.json();
|
|
203
|
+
return new BuilderforceApiError(payload.error ?? fallback, res.status, payload.code, payload.details, requestId);
|
|
204
|
+
} catch {
|
|
205
|
+
const text = await res.text().catch(() => "");
|
|
206
|
+
return new BuilderforceApiError(text || fallback, res.status, void 0, void 0, requestId);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
// src/BuilderforceClient.ts
|
|
212
|
+
var BuilderforceClient = class {
|
|
213
|
+
chat;
|
|
214
|
+
models;
|
|
215
|
+
usage;
|
|
216
|
+
constructor(options) {
|
|
217
|
+
const apiKey = options.apiKey?.trim();
|
|
218
|
+
if (!apiKey) {
|
|
219
|
+
throw new BuilderforceApiError(
|
|
220
|
+
"BuilderforceClient requires a non-empty apiKey",
|
|
221
|
+
400,
|
|
222
|
+
"missing_api_key"
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
const http = new HttpClient({
|
|
226
|
+
apiKey,
|
|
227
|
+
baseUrl: options.baseUrl ?? "https://api.builderforce.ai",
|
|
228
|
+
fetchFn: options.fetch,
|
|
229
|
+
timeoutMs: options.timeoutMs
|
|
230
|
+
});
|
|
231
|
+
this.chat = {
|
|
232
|
+
completions: new ChatCompletionsApi(http)
|
|
233
|
+
};
|
|
234
|
+
this.models = new ModelsApi(http);
|
|
235
|
+
this.usage = new UsageApi(http);
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
// src/domain/aiUseCases.ts
|
|
240
|
+
var AI_USE_CASES = [
|
|
241
|
+
"ide.chat",
|
|
242
|
+
"ide.code_complete",
|
|
243
|
+
"training.dataset_generate",
|
|
244
|
+
"training.dataset_evaluate",
|
|
245
|
+
"agent.inference",
|
|
246
|
+
"coder.code",
|
|
247
|
+
"coder.review",
|
|
248
|
+
"coder.test",
|
|
249
|
+
"coder.debug",
|
|
250
|
+
"coder.refactor",
|
|
251
|
+
"coder.document",
|
|
252
|
+
"coder.architect",
|
|
253
|
+
"coach.chat",
|
|
254
|
+
"coach.insight",
|
|
255
|
+
"coach.classify",
|
|
256
|
+
"studio.compose",
|
|
257
|
+
"studio.script",
|
|
258
|
+
"studio.brief",
|
|
259
|
+
"pitch_deck.generate",
|
|
260
|
+
"investor.update",
|
|
261
|
+
"ask.general",
|
|
262
|
+
"tool.classify_email",
|
|
263
|
+
"tool.categorize_expense",
|
|
264
|
+
"tool.contract_analyze",
|
|
265
|
+
"tool.competitor_scan",
|
|
266
|
+
"tool.feature_score",
|
|
267
|
+
"tool.market_research",
|
|
268
|
+
"tool.health_score",
|
|
269
|
+
"tool.journey_insight",
|
|
270
|
+
"vision.describe",
|
|
271
|
+
"ocr.extract",
|
|
272
|
+
"embed.text",
|
|
273
|
+
"match",
|
|
274
|
+
"match_tailor",
|
|
275
|
+
"match_insights",
|
|
276
|
+
"resume_roast",
|
|
277
|
+
"skill_extract",
|
|
278
|
+
"job_parser",
|
|
279
|
+
"autofill",
|
|
280
|
+
"article_writer",
|
|
281
|
+
"studio_script",
|
|
282
|
+
"studio_edit_script",
|
|
283
|
+
"studio_misc",
|
|
284
|
+
"linkedin_post",
|
|
285
|
+
"interview_questions",
|
|
286
|
+
"interview_analyze",
|
|
287
|
+
"chat",
|
|
288
|
+
"career",
|
|
289
|
+
"discovery",
|
|
290
|
+
"dashboard_summary"
|
|
291
|
+
];
|
|
292
|
+
function isAIUseCase(value) {
|
|
293
|
+
return AI_USE_CASES.includes(value);
|
|
294
|
+
}
|
|
295
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
296
|
+
0 && (module.exports = {
|
|
297
|
+
AI_USE_CASES,
|
|
298
|
+
BuilderforceApiError,
|
|
299
|
+
BuilderforceClient,
|
|
300
|
+
ChatCompletionStream,
|
|
301
|
+
isAIUseCase
|
|
302
|
+
});
|
|
303
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/infrastructure/sse.ts","../src/application/ChatCompletionsApi.ts","../src/application/ModelsApi.ts","../src/application/UsageApi.ts","../src/infrastructure/httpClient.ts","../src/BuilderforceClient.ts","../src/domain/aiUseCases.ts"],"sourcesContent":["export { BuilderforceClient, type BuilderforceClientOptions } from './BuilderforceClient';\r\n\r\nexport {\r\n AI_USE_CASES,\r\n isAIUseCase,\r\n type AIUseCase,\r\n} from './domain/aiUseCases';\r\n\r\nexport type {\r\n ChatRole,\r\n ChatMessage,\r\n ChatCompletionCreateParams,\r\n ChatCompletionChunk,\r\n ChatCompletionResponse,\r\n ModelsListResponse,\r\n UsageByModel,\r\n UsageByDay,\r\n UsageByUser,\r\n UsageResponse,\r\n UsageGetParams,\r\n} from './domain/types';\r\n\r\nexport { ChatCompletionStream } from './application/ChatCompletionsApi';\r\nexport { BuilderforceApiError } from './infrastructure/httpClient';\r\n","export async function* parseSseJson<T>(\r\n stream: ReadableStream<Uint8Array>,\r\n): AsyncGenerator<T, void, unknown> {\r\n const reader = stream.getReader();\r\n const decoder = new TextDecoder();\r\n let buffer = '';\r\n\r\n while (true) {\r\n const { done, value } = await reader.read();\r\n if (done) break;\r\n\r\n buffer += decoder.decode(value, { stream: true });\r\n const lines = buffer.split('\\n');\r\n buffer = lines.pop() ?? '';\r\n\r\n for (const line of lines) {\r\n const trimmed = line.trim();\r\n if (!trimmed.startsWith('data: ')) continue;\r\n\r\n const data = trimmed.slice(6).trim();\r\n if (data === '[DONE]') return;\r\n\r\n try {\r\n yield JSON.parse(data) as T;\r\n } catch {\r\n // Skip malformed chunks instead of breaking the stream.\r\n }\r\n }\r\n }\r\n}\r\n","import type { ChatCompletionChunk, ChatCompletionCreateParams, ChatCompletionResponse } from '../domain/types';\r\nimport { HttpClient } from '../infrastructure/httpClient';\r\nimport { parseSseJson } from '../infrastructure/sse';\r\n\r\nexport class ChatCompletionStream implements AsyncIterable<ChatCompletionChunk> {\r\n private readonly stream: ReadableStream<Uint8Array>;\r\n\r\n constructor(stream: ReadableStream<Uint8Array>) {\r\n this.stream = stream;\r\n }\r\n\r\n [Symbol.asyncIterator](): AsyncIterator<ChatCompletionChunk, void, unknown> {\r\n return parseSseJson<ChatCompletionChunk>(this.stream);\r\n }\r\n\r\n async toText(): Promise<string> {\r\n let full = '';\r\n for await (const chunk of this) {\r\n const delta = chunk.choices?.[0]?.delta?.content;\r\n if (typeof delta === 'string') {\r\n full += delta;\r\n }\r\n }\r\n return full;\r\n }\r\n}\r\n\r\nexport class ChatCompletionsApi {\r\n private readonly http: HttpClient;\r\n\r\n constructor(http: HttpClient) {\r\n this.http = http;\r\n }\r\n\r\n async create(params: ChatCompletionCreateParams & { stream: true }): Promise<ChatCompletionStream>;\r\n async create(params: ChatCompletionCreateParams & { stream?: false | undefined }): Promise<ChatCompletionResponse>;\r\n async create(\r\n params: ChatCompletionCreateParams,\r\n ): Promise<ChatCompletionResponse | ChatCompletionStream> {\r\n if (params.stream) {\r\n const response = await this.http.postRaw('/llm/v1/chat/completions', params);\r\n if (!response.body) {\r\n throw new Error('Streaming response body is missing');\r\n }\r\n return new ChatCompletionStream(response.body);\r\n }\r\n\r\n return this.http.postJson<ChatCompletionResponse>('/llm/v1/chat/completions', params);\r\n }\r\n}\r\n","import type { ModelsListResponse } from '../domain/types';\r\nimport { HttpClient } from '../infrastructure/httpClient';\r\n\r\nexport class ModelsApi {\r\n private readonly http: HttpClient;\r\n\r\n constructor(http: HttpClient) {\r\n this.http = http;\r\n }\r\n\r\n list(): Promise<ModelsListResponse> {\r\n return this.http.getJson<ModelsListResponse>('/llm/v1/models');\r\n }\r\n}\r\n","import type { UsageGetParams, UsageResponse } from '../domain/types';\r\nimport { HttpClient } from '../infrastructure/httpClient';\r\n\r\nexport class UsageApi {\r\n private readonly http: HttpClient;\r\n\r\n constructor(http: HttpClient) {\r\n this.http = http;\r\n }\r\n\r\n get(params: UsageGetParams = {}): Promise<UsageResponse> {\r\n const query = typeof params.days === 'number' ? `?days=${encodeURIComponent(String(params.days))}` : '';\r\n return this.http.getJson<UsageResponse>(`/llm/v1/usage${query}`);\r\n }\r\n}\r\n","export class BuilderforceApiError extends Error {\r\n public readonly status: number;\r\n public readonly code?: string;\r\n public readonly details?: unknown;\r\n public readonly requestId?: string;\r\n\r\n constructor(message: string, status: number, code?: string, details?: unknown, requestId?: string) {\r\n super(message);\r\n this.name = 'BuilderforceApiError';\r\n this.status = status;\r\n this.code = code;\r\n this.details = details;\r\n this.requestId = requestId;\r\n }\r\n}\r\n\r\nexport interface HttpClientOptions {\r\n apiKey: string;\r\n baseUrl: string;\r\n fetchFn?: typeof fetch;\r\n timeoutMs?: number;\r\n}\r\n\r\nexport class HttpClient {\r\n private readonly apiKey: string;\r\n private readonly baseUrl: string;\r\n private readonly fetchFn: typeof fetch;\r\n private readonly timeoutMs: number;\r\n\r\n constructor(options: HttpClientOptions) {\r\n this.apiKey = options.apiKey;\r\n this.baseUrl = options.baseUrl.replace(/\\/$/, '');\r\n this.fetchFn = options.fetchFn ?? fetch;\r\n this.timeoutMs = options.timeoutMs ?? 60_000;\r\n }\r\n\r\n async getJson<T>(path: string): Promise<T> {\r\n const res = await this.fetchWithTimeout(`${this.baseUrl}${path}`, {\r\n method: 'GET',\r\n headers: this.authHeaders(),\r\n });\r\n return this.parseJsonResponse<T>(res);\r\n }\r\n\r\n async postJson<T>(path: string, body: unknown): Promise<T> {\r\n const res = await this.fetchWithTimeout(`${this.baseUrl}${path}`, {\r\n method: 'POST',\r\n headers: {\r\n ...this.authHeaders(),\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify(body),\r\n });\r\n return this.parseJsonResponse<T>(res);\r\n }\r\n\r\n async postRaw(path: string, body: unknown): Promise<Response> {\r\n const res = await this.fetchWithTimeout(`${this.baseUrl}${path}`, {\r\n method: 'POST',\r\n headers: {\r\n ...this.authHeaders(),\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify(body),\r\n });\r\n if (!res.ok) {\r\n throw await this.toApiError(res);\r\n }\r\n return res;\r\n }\r\n\r\n private authHeaders(): Record<string, string> {\r\n return {\r\n Authorization: `Bearer ${this.apiKey}`,\r\n };\r\n }\r\n\r\n private async fetchWithTimeout(input: RequestInfo | URL, init: RequestInit): Promise<Response> {\r\n const controller = new AbortController();\r\n const timeout = setTimeout(() => controller.abort(), this.timeoutMs);\r\n try {\r\n return await this.fetchFn(input, { ...init, signal: controller.signal });\r\n } catch (error) {\r\n if (controller.signal.aborted) {\r\n throw new BuilderforceApiError(`Request timed out after ${this.timeoutMs}ms`, 408, 'timeout');\r\n }\r\n throw error;\r\n } finally {\r\n clearTimeout(timeout);\r\n }\r\n }\r\n\r\n private async parseJsonResponse<T>(res: Response): Promise<T> {\r\n if (!res.ok) {\r\n throw await this.toApiError(res);\r\n }\r\n return res.json() as Promise<T>;\r\n }\r\n\r\n private async toApiError(res: Response): Promise<BuilderforceApiError> {\r\n const fallback = `Request failed (${res.status})`;\r\n const requestId = res.headers.get('x-request-id') ?? undefined;\r\n try {\r\n const payload = await res.json() as { error?: string; code?: string; details?: unknown };\r\n return new BuilderforceApiError(payload.error ?? fallback, res.status, payload.code, payload.details, requestId);\r\n } catch {\r\n const text = await res.text().catch(() => '');\r\n return new BuilderforceApiError(text || fallback, res.status, undefined, undefined, requestId);\r\n }\r\n }\r\n}\r\n","import { ChatCompletionsApi } from './application/ChatCompletionsApi';\r\nimport { ModelsApi } from './application/ModelsApi';\r\nimport { UsageApi } from './application/UsageApi';\r\nimport { BuilderforceApiError, HttpClient } from './infrastructure/httpClient';\r\n\r\nexport interface BuilderforceClientOptions {\r\n apiKey: string;\r\n baseUrl?: string;\r\n fetch?: typeof fetch;\r\n timeoutMs?: number;\r\n}\r\n\r\nexport class BuilderforceClient {\r\n public readonly chat: {\r\n completions: ChatCompletionsApi;\r\n };\r\n public readonly models: ModelsApi;\r\n public readonly usage: UsageApi;\r\n\r\n constructor(options: BuilderforceClientOptions) {\r\n const apiKey = options.apiKey?.trim();\r\n if (!apiKey) {\r\n throw new BuilderforceApiError(\r\n 'BuilderforceClient requires a non-empty apiKey',\r\n 400,\r\n 'missing_api_key',\r\n );\r\n }\r\n\r\n const http = new HttpClient({\r\n apiKey,\r\n baseUrl: options.baseUrl ?? 'https://api.builderforce.ai',\r\n fetchFn: options.fetch,\r\n timeoutMs: options.timeoutMs,\r\n });\r\n\r\n this.chat = {\r\n completions: new ChatCompletionsApi(http),\r\n };\r\n this.models = new ModelsApi(http);\r\n this.usage = new UsageApi(http);\r\n }\r\n}\r\n","// Keep this list aligned with api/src/application/llm/aiUseCases.ts.\r\nexport const AI_USE_CASES = [\r\n 'ide.chat',\r\n 'ide.code_complete',\r\n 'training.dataset_generate',\r\n 'training.dataset_evaluate',\r\n 'agent.inference',\r\n 'coder.code',\r\n 'coder.review',\r\n 'coder.test',\r\n 'coder.debug',\r\n 'coder.refactor',\r\n 'coder.document',\r\n 'coder.architect',\r\n 'coach.chat',\r\n 'coach.insight',\r\n 'coach.classify',\r\n 'studio.compose',\r\n 'studio.script',\r\n 'studio.brief',\r\n 'pitch_deck.generate',\r\n 'investor.update',\r\n 'ask.general',\r\n 'tool.classify_email',\r\n 'tool.categorize_expense',\r\n 'tool.contract_analyze',\r\n 'tool.competitor_scan',\r\n 'tool.feature_score',\r\n 'tool.market_research',\r\n 'tool.health_score',\r\n 'tool.journey_insight',\r\n 'vision.describe',\r\n 'ocr.extract',\r\n 'embed.text',\r\n 'match',\r\n 'match_tailor',\r\n 'match_insights',\r\n 'resume_roast',\r\n 'skill_extract',\r\n 'job_parser',\r\n 'autofill',\r\n 'article_writer',\r\n 'studio_script',\r\n 'studio_edit_script',\r\n 'studio_misc',\r\n 'linkedin_post',\r\n 'interview_questions',\r\n 'interview_analyze',\r\n 'chat',\r\n 'career',\r\n 'discovery',\r\n 'dashboard_summary',\r\n] as const;\r\n\r\nexport type AIUseCase = (typeof AI_USE_CASES)[number];\r\n\r\nexport function isAIUseCase(value: string): value is AIUseCase {\r\n return (AI_USE_CASES as readonly string[]).includes(value);\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,gBAAuB,aACrB,QACkC;AAClC,QAAM,SAAS,OAAO,UAAU;AAChC,QAAM,UAAU,IAAI,YAAY;AAChC,MAAI,SAAS;AAEb,SAAO,MAAM;AACX,UAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,QAAI,KAAM;AAEV,cAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAChD,UAAM,QAAQ,OAAO,MAAM,IAAI;AAC/B,aAAS,MAAM,IAAI,KAAK;AAExB,eAAW,QAAQ,OAAO;AACxB,YAAM,UAAU,KAAK,KAAK;AAC1B,UAAI,CAAC,QAAQ,WAAW,QAAQ,EAAG;AAEnC,YAAM,OAAO,QAAQ,MAAM,CAAC,EAAE,KAAK;AACnC,UAAI,SAAS,SAAU;AAEvB,UAAI;AACF,cAAM,KAAK,MAAM,IAAI;AAAA,MACvB,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AACF;;;ACzBO,IAAM,uBAAN,MAAyE;AAAA,EAC7D;AAAA,EAEjB,YAAY,QAAoC;AAC9C,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,CAAC,OAAO,aAAa,IAAuD;AAC1E,WAAO,aAAkC,KAAK,MAAM;AAAA,EACtD;AAAA,EAEA,MAAM,SAA0B;AAC9B,QAAI,OAAO;AACX,qBAAiB,SAAS,MAAM;AAC9B,YAAM,QAAQ,MAAM,UAAU,CAAC,GAAG,OAAO;AACzC,UAAI,OAAO,UAAU,UAAU;AAC7B,gBAAQ;AAAA,MACV;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACF;AAEO,IAAM,qBAAN,MAAyB;AAAA,EACb;AAAA,EAEjB,YAAY,MAAkB;AAC5B,SAAK,OAAO;AAAA,EACd;AAAA,EAIA,MAAM,OACJ,QACwD;AACxD,QAAI,OAAO,QAAQ;AACjB,YAAM,WAAW,MAAM,KAAK,KAAK,QAAQ,4BAA4B,MAAM;AAC3E,UAAI,CAAC,SAAS,MAAM;AAClB,cAAM,IAAI,MAAM,oCAAoC;AAAA,MACtD;AACA,aAAO,IAAI,qBAAqB,SAAS,IAAI;AAAA,IAC/C;AAEA,WAAO,KAAK,KAAK,SAAiC,4BAA4B,MAAM;AAAA,EACtF;AACF;;;AC9CO,IAAM,YAAN,MAAgB;AAAA,EACJ;AAAA,EAEjB,YAAY,MAAkB;AAC5B,SAAK,OAAO;AAAA,EACd;AAAA,EAEA,OAAoC;AAClC,WAAO,KAAK,KAAK,QAA4B,gBAAgB;AAAA,EAC/D;AACF;;;ACVO,IAAM,WAAN,MAAe;AAAA,EACH;AAAA,EAEjB,YAAY,MAAkB;AAC5B,SAAK,OAAO;AAAA,EACd;AAAA,EAEA,IAAI,SAAyB,CAAC,GAA2B;AACvD,UAAM,QAAQ,OAAO,OAAO,SAAS,WAAW,SAAS,mBAAmB,OAAO,OAAO,IAAI,CAAC,CAAC,KAAK;AACrG,WAAO,KAAK,KAAK,QAAuB,gBAAgB,KAAK,EAAE;AAAA,EACjE;AACF;;;ACdO,IAAM,uBAAN,cAAmC,MAAM;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEhB,YAAY,SAAiB,QAAgB,MAAe,SAAmB,WAAoB;AACjG,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,SAAS;AACd,SAAK,OAAO;AACZ,SAAK,UAAU;AACf,SAAK,YAAY;AAAA,EACnB;AACF;AASO,IAAM,aAAN,MAAiB;AAAA,EACL;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,SAA4B;AACtC,SAAK,SAAS,QAAQ;AACtB,SAAK,UAAU,QAAQ,QAAQ,QAAQ,OAAO,EAAE;AAChD,SAAK,UAAU,QAAQ,WAAW;AAClC,SAAK,YAAY,QAAQ,aAAa;AAAA,EACxC;AAAA,EAEA,MAAM,QAAW,MAA0B;AACzC,UAAM,MAAM,MAAM,KAAK,iBAAiB,GAAG,KAAK,OAAO,GAAG,IAAI,IAAI;AAAA,MAChE,QAAQ;AAAA,MACR,SAAS,KAAK,YAAY;AAAA,IAC5B,CAAC;AACD,WAAO,KAAK,kBAAqB,GAAG;AAAA,EACtC;AAAA,EAEA,MAAM,SAAY,MAAc,MAA2B;AACzD,UAAM,MAAM,MAAM,KAAK,iBAAiB,GAAG,KAAK,OAAO,GAAG,IAAI,IAAI;AAAA,MAChE,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,GAAG,KAAK,YAAY;AAAA,QACpB,gBAAgB;AAAA,MAClB;AAAA,MACA,MAAM,KAAK,UAAU,IAAI;AAAA,IAC3B,CAAC;AACD,WAAO,KAAK,kBAAqB,GAAG;AAAA,EACtC;AAAA,EAEA,MAAM,QAAQ,MAAc,MAAkC;AAC5D,UAAM,MAAM,MAAM,KAAK,iBAAiB,GAAG,KAAK,OAAO,GAAG,IAAI,IAAI;AAAA,MAChE,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,GAAG,KAAK,YAAY;AAAA,QACpB,gBAAgB;AAAA,MAClB;AAAA,MACA,MAAM,KAAK,UAAU,IAAI;AAAA,IAC3B,CAAC;AACD,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,MAAM,KAAK,WAAW,GAAG;AAAA,IACjC;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,cAAsC;AAC5C,WAAO;AAAA,MACL,eAAe,UAAU,KAAK,MAAM;AAAA,IACtC;AAAA,EACF;AAAA,EAEA,MAAc,iBAAiB,OAA0B,MAAsC;AAC7F,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,UAAU,WAAW,MAAM,WAAW,MAAM,GAAG,KAAK,SAAS;AACnE,QAAI;AACF,aAAO,MAAM,KAAK,QAAQ,OAAO,EAAE,GAAG,MAAM,QAAQ,WAAW,OAAO,CAAC;AAAA,IACzE,SAAS,OAAO;AACd,UAAI,WAAW,OAAO,SAAS;AAC7B,cAAM,IAAI,qBAAqB,2BAA2B,KAAK,SAAS,MAAM,KAAK,SAAS;AAAA,MAC9F;AACA,YAAM;AAAA,IACR,UAAE;AACA,mBAAa,OAAO;AAAA,IACtB;AAAA,EACF;AAAA,EAEA,MAAc,kBAAqB,KAA2B;AAC5D,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,MAAM,KAAK,WAAW,GAAG;AAAA,IACjC;AACA,WAAO,IAAI,KAAK;AAAA,EAClB;AAAA,EAEA,MAAc,WAAW,KAA8C;AACrE,UAAM,WAAW,mBAAmB,IAAI,MAAM;AAC9C,UAAM,YAAY,IAAI,QAAQ,IAAI,cAAc,KAAK;AACrD,QAAI;AACF,YAAM,UAAU,MAAM,IAAI,KAAK;AAC/B,aAAO,IAAI,qBAAqB,QAAQ,SAAS,UAAU,IAAI,QAAQ,QAAQ,MAAM,QAAQ,SAAS,SAAS;AAAA,IACjH,QAAQ;AACN,YAAM,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,EAAE;AAC5C,aAAO,IAAI,qBAAqB,QAAQ,UAAU,IAAI,QAAQ,QAAW,QAAW,SAAS;AAAA,IAC/F;AAAA,EACF;AACF;;;AClGO,IAAM,qBAAN,MAAyB;AAAA,EACd;AAAA,EAGA;AAAA,EACA;AAAA,EAEhB,YAAY,SAAoC;AAC9C,UAAM,SAAS,QAAQ,QAAQ,KAAK;AACpC,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,UAAM,OAAO,IAAI,WAAW;AAAA,MAC1B;AAAA,MACA,SAAS,QAAQ,WAAW;AAAA,MAC5B,SAAS,QAAQ;AAAA,MACjB,WAAW,QAAQ;AAAA,IACrB,CAAC;AAED,SAAK,OAAO;AAAA,MACV,aAAa,IAAI,mBAAmB,IAAI;AAAA,IAC1C;AACA,SAAK,SAAS,IAAI,UAAU,IAAI;AAChC,SAAK,QAAQ,IAAI,SAAS,IAAI;AAAA,EAChC;AACF;;;ACzCO,IAAM,eAAe;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAIO,SAAS,YAAY,OAAmC;AAC7D,SAAQ,aAAmC,SAAS,KAAK;AAC3D;","names":[]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
declare const AI_USE_CASES: readonly ["ide.chat", "ide.code_complete", "training.dataset_generate", "training.dataset_evaluate", "agent.inference", "coder.code", "coder.review", "coder.test", "coder.debug", "coder.refactor", "coder.document", "coder.architect", "coach.chat", "coach.insight", "coach.classify", "studio.compose", "studio.script", "studio.brief", "pitch_deck.generate", "investor.update", "ask.general", "tool.classify_email", "tool.categorize_expense", "tool.contract_analyze", "tool.competitor_scan", "tool.feature_score", "tool.market_research", "tool.health_score", "tool.journey_insight", "vision.describe", "ocr.extract", "embed.text", "match", "match_tailor", "match_insights", "resume_roast", "skill_extract", "job_parser", "autofill", "article_writer", "studio_script", "studio_edit_script", "studio_misc", "linkedin_post", "interview_questions", "interview_analyze", "chat", "career", "discovery", "dashboard_summary"];
|
|
2
|
+
type AIUseCase = (typeof AI_USE_CASES)[number];
|
|
3
|
+
declare function isAIUseCase(value: string): value is AIUseCase;
|
|
4
|
+
|
|
5
|
+
type ChatRole = 'system' | 'user' | 'assistant' | 'tool';
|
|
6
|
+
interface ChatMessage {
|
|
7
|
+
role: ChatRole;
|
|
8
|
+
content: string;
|
|
9
|
+
name?: string;
|
|
10
|
+
}
|
|
11
|
+
interface ChatCompletionCreateParams {
|
|
12
|
+
model?: string;
|
|
13
|
+
messages: ChatMessage[];
|
|
14
|
+
stream?: boolean;
|
|
15
|
+
useCase?: AIUseCase;
|
|
16
|
+
temperature?: number;
|
|
17
|
+
max_tokens?: number;
|
|
18
|
+
top_p?: number;
|
|
19
|
+
[key: string]: unknown;
|
|
20
|
+
}
|
|
21
|
+
interface ChatCompletionChunk {
|
|
22
|
+
id?: string;
|
|
23
|
+
object?: string;
|
|
24
|
+
created?: number;
|
|
25
|
+
model?: string;
|
|
26
|
+
choices?: Array<{
|
|
27
|
+
index?: number;
|
|
28
|
+
delta?: {
|
|
29
|
+
role?: ChatRole;
|
|
30
|
+
content?: string;
|
|
31
|
+
};
|
|
32
|
+
finish_reason?: string | null;
|
|
33
|
+
}>;
|
|
34
|
+
usage?: {
|
|
35
|
+
prompt_tokens?: number;
|
|
36
|
+
completion_tokens?: number;
|
|
37
|
+
total_tokens?: number;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
interface ChatCompletionResponse {
|
|
41
|
+
id?: string;
|
|
42
|
+
object?: string;
|
|
43
|
+
created?: number;
|
|
44
|
+
model?: string;
|
|
45
|
+
choices?: Array<{
|
|
46
|
+
index?: number;
|
|
47
|
+
message?: {
|
|
48
|
+
role?: ChatRole;
|
|
49
|
+
content?: string;
|
|
50
|
+
};
|
|
51
|
+
finish_reason?: string | null;
|
|
52
|
+
}>;
|
|
53
|
+
usage?: {
|
|
54
|
+
prompt_tokens?: number;
|
|
55
|
+
completion_tokens?: number;
|
|
56
|
+
total_tokens?: number;
|
|
57
|
+
};
|
|
58
|
+
_builderforce?: {
|
|
59
|
+
resolvedModel?: string;
|
|
60
|
+
retries?: number;
|
|
61
|
+
pool?: number;
|
|
62
|
+
product?: string;
|
|
63
|
+
effectivePlan?: string;
|
|
64
|
+
};
|
|
65
|
+
[key: string]: unknown;
|
|
66
|
+
}
|
|
67
|
+
interface ModelsListResponse {
|
|
68
|
+
configured?: boolean;
|
|
69
|
+
object?: 'list';
|
|
70
|
+
product?: string;
|
|
71
|
+
effectivePlan?: string;
|
|
72
|
+
data?: Array<{
|
|
73
|
+
model: string;
|
|
74
|
+
vendor: string;
|
|
75
|
+
preferred: boolean;
|
|
76
|
+
available: boolean;
|
|
77
|
+
cooldownUntil?: number;
|
|
78
|
+
}>;
|
|
79
|
+
models?: string[];
|
|
80
|
+
[key: string]: unknown;
|
|
81
|
+
}
|
|
82
|
+
interface UsageByModel {
|
|
83
|
+
llmProduct: string;
|
|
84
|
+
model: string;
|
|
85
|
+
requests: number;
|
|
86
|
+
prompt_tokens: string | number;
|
|
87
|
+
completion_tokens: string | number;
|
|
88
|
+
total_tokens: string | number;
|
|
89
|
+
retries: number;
|
|
90
|
+
}
|
|
91
|
+
interface UsageByDay {
|
|
92
|
+
day: string;
|
|
93
|
+
requests: number;
|
|
94
|
+
total_tokens: string | number;
|
|
95
|
+
}
|
|
96
|
+
interface UsageByUser {
|
|
97
|
+
user_id: string;
|
|
98
|
+
requests: number;
|
|
99
|
+
total_tokens: string | number;
|
|
100
|
+
}
|
|
101
|
+
interface UsageResponse {
|
|
102
|
+
days: number;
|
|
103
|
+
tenantId: number;
|
|
104
|
+
plan: string;
|
|
105
|
+
effectivePlan: string;
|
|
106
|
+
billingStatus: string;
|
|
107
|
+
totals: {
|
|
108
|
+
requests: number;
|
|
109
|
+
totalTokens: number;
|
|
110
|
+
promptTokens: number;
|
|
111
|
+
completionTokens: number;
|
|
112
|
+
};
|
|
113
|
+
mine: {
|
|
114
|
+
userId: string | null;
|
|
115
|
+
requests: number;
|
|
116
|
+
totalTokens: number;
|
|
117
|
+
promptTokens: number;
|
|
118
|
+
completionTokens: number;
|
|
119
|
+
};
|
|
120
|
+
byModel: UsageByModel[];
|
|
121
|
+
byDay: UsageByDay[];
|
|
122
|
+
byUser: UsageByUser[];
|
|
123
|
+
}
|
|
124
|
+
interface UsageGetParams {
|
|
125
|
+
days?: number;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
declare class BuilderforceApiError extends Error {
|
|
129
|
+
readonly status: number;
|
|
130
|
+
readonly code?: string;
|
|
131
|
+
readonly details?: unknown;
|
|
132
|
+
readonly requestId?: string;
|
|
133
|
+
constructor(message: string, status: number, code?: string, details?: unknown, requestId?: string);
|
|
134
|
+
}
|
|
135
|
+
interface HttpClientOptions {
|
|
136
|
+
apiKey: string;
|
|
137
|
+
baseUrl: string;
|
|
138
|
+
fetchFn?: typeof fetch;
|
|
139
|
+
timeoutMs?: number;
|
|
140
|
+
}
|
|
141
|
+
declare class HttpClient {
|
|
142
|
+
private readonly apiKey;
|
|
143
|
+
private readonly baseUrl;
|
|
144
|
+
private readonly fetchFn;
|
|
145
|
+
private readonly timeoutMs;
|
|
146
|
+
constructor(options: HttpClientOptions);
|
|
147
|
+
getJson<T>(path: string): Promise<T>;
|
|
148
|
+
postJson<T>(path: string, body: unknown): Promise<T>;
|
|
149
|
+
postRaw(path: string, body: unknown): Promise<Response>;
|
|
150
|
+
private authHeaders;
|
|
151
|
+
private fetchWithTimeout;
|
|
152
|
+
private parseJsonResponse;
|
|
153
|
+
private toApiError;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
declare class ChatCompletionStream implements AsyncIterable<ChatCompletionChunk> {
|
|
157
|
+
private readonly stream;
|
|
158
|
+
constructor(stream: ReadableStream<Uint8Array>);
|
|
159
|
+
[Symbol.asyncIterator](): AsyncIterator<ChatCompletionChunk, void, unknown>;
|
|
160
|
+
toText(): Promise<string>;
|
|
161
|
+
}
|
|
162
|
+
declare class ChatCompletionsApi {
|
|
163
|
+
private readonly http;
|
|
164
|
+
constructor(http: HttpClient);
|
|
165
|
+
create(params: ChatCompletionCreateParams & {
|
|
166
|
+
stream: true;
|
|
167
|
+
}): Promise<ChatCompletionStream>;
|
|
168
|
+
create(params: ChatCompletionCreateParams & {
|
|
169
|
+
stream?: false | undefined;
|
|
170
|
+
}): Promise<ChatCompletionResponse>;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
declare class ModelsApi {
|
|
174
|
+
private readonly http;
|
|
175
|
+
constructor(http: HttpClient);
|
|
176
|
+
list(): Promise<ModelsListResponse>;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
declare class UsageApi {
|
|
180
|
+
private readonly http;
|
|
181
|
+
constructor(http: HttpClient);
|
|
182
|
+
get(params?: UsageGetParams): Promise<UsageResponse>;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
interface BuilderforceClientOptions {
|
|
186
|
+
apiKey: string;
|
|
187
|
+
baseUrl?: string;
|
|
188
|
+
fetch?: typeof fetch;
|
|
189
|
+
timeoutMs?: number;
|
|
190
|
+
}
|
|
191
|
+
declare class BuilderforceClient {
|
|
192
|
+
readonly chat: {
|
|
193
|
+
completions: ChatCompletionsApi;
|
|
194
|
+
};
|
|
195
|
+
readonly models: ModelsApi;
|
|
196
|
+
readonly usage: UsageApi;
|
|
197
|
+
constructor(options: BuilderforceClientOptions);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export { type AIUseCase, AI_USE_CASES, BuilderforceApiError, BuilderforceClient, type BuilderforceClientOptions, type ChatCompletionChunk, type ChatCompletionCreateParams, type ChatCompletionResponse, ChatCompletionStream, type ChatMessage, type ChatRole, type ModelsListResponse, type UsageByDay, type UsageByModel, type UsageByUser, type UsageGetParams, type UsageResponse, isAIUseCase };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
declare const AI_USE_CASES: readonly ["ide.chat", "ide.code_complete", "training.dataset_generate", "training.dataset_evaluate", "agent.inference", "coder.code", "coder.review", "coder.test", "coder.debug", "coder.refactor", "coder.document", "coder.architect", "coach.chat", "coach.insight", "coach.classify", "studio.compose", "studio.script", "studio.brief", "pitch_deck.generate", "investor.update", "ask.general", "tool.classify_email", "tool.categorize_expense", "tool.contract_analyze", "tool.competitor_scan", "tool.feature_score", "tool.market_research", "tool.health_score", "tool.journey_insight", "vision.describe", "ocr.extract", "embed.text", "match", "match_tailor", "match_insights", "resume_roast", "skill_extract", "job_parser", "autofill", "article_writer", "studio_script", "studio_edit_script", "studio_misc", "linkedin_post", "interview_questions", "interview_analyze", "chat", "career", "discovery", "dashboard_summary"];
|
|
2
|
+
type AIUseCase = (typeof AI_USE_CASES)[number];
|
|
3
|
+
declare function isAIUseCase(value: string): value is AIUseCase;
|
|
4
|
+
|
|
5
|
+
type ChatRole = 'system' | 'user' | 'assistant' | 'tool';
|
|
6
|
+
interface ChatMessage {
|
|
7
|
+
role: ChatRole;
|
|
8
|
+
content: string;
|
|
9
|
+
name?: string;
|
|
10
|
+
}
|
|
11
|
+
interface ChatCompletionCreateParams {
|
|
12
|
+
model?: string;
|
|
13
|
+
messages: ChatMessage[];
|
|
14
|
+
stream?: boolean;
|
|
15
|
+
useCase?: AIUseCase;
|
|
16
|
+
temperature?: number;
|
|
17
|
+
max_tokens?: number;
|
|
18
|
+
top_p?: number;
|
|
19
|
+
[key: string]: unknown;
|
|
20
|
+
}
|
|
21
|
+
interface ChatCompletionChunk {
|
|
22
|
+
id?: string;
|
|
23
|
+
object?: string;
|
|
24
|
+
created?: number;
|
|
25
|
+
model?: string;
|
|
26
|
+
choices?: Array<{
|
|
27
|
+
index?: number;
|
|
28
|
+
delta?: {
|
|
29
|
+
role?: ChatRole;
|
|
30
|
+
content?: string;
|
|
31
|
+
};
|
|
32
|
+
finish_reason?: string | null;
|
|
33
|
+
}>;
|
|
34
|
+
usage?: {
|
|
35
|
+
prompt_tokens?: number;
|
|
36
|
+
completion_tokens?: number;
|
|
37
|
+
total_tokens?: number;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
interface ChatCompletionResponse {
|
|
41
|
+
id?: string;
|
|
42
|
+
object?: string;
|
|
43
|
+
created?: number;
|
|
44
|
+
model?: string;
|
|
45
|
+
choices?: Array<{
|
|
46
|
+
index?: number;
|
|
47
|
+
message?: {
|
|
48
|
+
role?: ChatRole;
|
|
49
|
+
content?: string;
|
|
50
|
+
};
|
|
51
|
+
finish_reason?: string | null;
|
|
52
|
+
}>;
|
|
53
|
+
usage?: {
|
|
54
|
+
prompt_tokens?: number;
|
|
55
|
+
completion_tokens?: number;
|
|
56
|
+
total_tokens?: number;
|
|
57
|
+
};
|
|
58
|
+
_builderforce?: {
|
|
59
|
+
resolvedModel?: string;
|
|
60
|
+
retries?: number;
|
|
61
|
+
pool?: number;
|
|
62
|
+
product?: string;
|
|
63
|
+
effectivePlan?: string;
|
|
64
|
+
};
|
|
65
|
+
[key: string]: unknown;
|
|
66
|
+
}
|
|
67
|
+
interface ModelsListResponse {
|
|
68
|
+
configured?: boolean;
|
|
69
|
+
object?: 'list';
|
|
70
|
+
product?: string;
|
|
71
|
+
effectivePlan?: string;
|
|
72
|
+
data?: Array<{
|
|
73
|
+
model: string;
|
|
74
|
+
vendor: string;
|
|
75
|
+
preferred: boolean;
|
|
76
|
+
available: boolean;
|
|
77
|
+
cooldownUntil?: number;
|
|
78
|
+
}>;
|
|
79
|
+
models?: string[];
|
|
80
|
+
[key: string]: unknown;
|
|
81
|
+
}
|
|
82
|
+
interface UsageByModel {
|
|
83
|
+
llmProduct: string;
|
|
84
|
+
model: string;
|
|
85
|
+
requests: number;
|
|
86
|
+
prompt_tokens: string | number;
|
|
87
|
+
completion_tokens: string | number;
|
|
88
|
+
total_tokens: string | number;
|
|
89
|
+
retries: number;
|
|
90
|
+
}
|
|
91
|
+
interface UsageByDay {
|
|
92
|
+
day: string;
|
|
93
|
+
requests: number;
|
|
94
|
+
total_tokens: string | number;
|
|
95
|
+
}
|
|
96
|
+
interface UsageByUser {
|
|
97
|
+
user_id: string;
|
|
98
|
+
requests: number;
|
|
99
|
+
total_tokens: string | number;
|
|
100
|
+
}
|
|
101
|
+
interface UsageResponse {
|
|
102
|
+
days: number;
|
|
103
|
+
tenantId: number;
|
|
104
|
+
plan: string;
|
|
105
|
+
effectivePlan: string;
|
|
106
|
+
billingStatus: string;
|
|
107
|
+
totals: {
|
|
108
|
+
requests: number;
|
|
109
|
+
totalTokens: number;
|
|
110
|
+
promptTokens: number;
|
|
111
|
+
completionTokens: number;
|
|
112
|
+
};
|
|
113
|
+
mine: {
|
|
114
|
+
userId: string | null;
|
|
115
|
+
requests: number;
|
|
116
|
+
totalTokens: number;
|
|
117
|
+
promptTokens: number;
|
|
118
|
+
completionTokens: number;
|
|
119
|
+
};
|
|
120
|
+
byModel: UsageByModel[];
|
|
121
|
+
byDay: UsageByDay[];
|
|
122
|
+
byUser: UsageByUser[];
|
|
123
|
+
}
|
|
124
|
+
interface UsageGetParams {
|
|
125
|
+
days?: number;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
declare class BuilderforceApiError extends Error {
|
|
129
|
+
readonly status: number;
|
|
130
|
+
readonly code?: string;
|
|
131
|
+
readonly details?: unknown;
|
|
132
|
+
readonly requestId?: string;
|
|
133
|
+
constructor(message: string, status: number, code?: string, details?: unknown, requestId?: string);
|
|
134
|
+
}
|
|
135
|
+
interface HttpClientOptions {
|
|
136
|
+
apiKey: string;
|
|
137
|
+
baseUrl: string;
|
|
138
|
+
fetchFn?: typeof fetch;
|
|
139
|
+
timeoutMs?: number;
|
|
140
|
+
}
|
|
141
|
+
declare class HttpClient {
|
|
142
|
+
private readonly apiKey;
|
|
143
|
+
private readonly baseUrl;
|
|
144
|
+
private readonly fetchFn;
|
|
145
|
+
private readonly timeoutMs;
|
|
146
|
+
constructor(options: HttpClientOptions);
|
|
147
|
+
getJson<T>(path: string): Promise<T>;
|
|
148
|
+
postJson<T>(path: string, body: unknown): Promise<T>;
|
|
149
|
+
postRaw(path: string, body: unknown): Promise<Response>;
|
|
150
|
+
private authHeaders;
|
|
151
|
+
private fetchWithTimeout;
|
|
152
|
+
private parseJsonResponse;
|
|
153
|
+
private toApiError;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
declare class ChatCompletionStream implements AsyncIterable<ChatCompletionChunk> {
|
|
157
|
+
private readonly stream;
|
|
158
|
+
constructor(stream: ReadableStream<Uint8Array>);
|
|
159
|
+
[Symbol.asyncIterator](): AsyncIterator<ChatCompletionChunk, void, unknown>;
|
|
160
|
+
toText(): Promise<string>;
|
|
161
|
+
}
|
|
162
|
+
declare class ChatCompletionsApi {
|
|
163
|
+
private readonly http;
|
|
164
|
+
constructor(http: HttpClient);
|
|
165
|
+
create(params: ChatCompletionCreateParams & {
|
|
166
|
+
stream: true;
|
|
167
|
+
}): Promise<ChatCompletionStream>;
|
|
168
|
+
create(params: ChatCompletionCreateParams & {
|
|
169
|
+
stream?: false | undefined;
|
|
170
|
+
}): Promise<ChatCompletionResponse>;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
declare class ModelsApi {
|
|
174
|
+
private readonly http;
|
|
175
|
+
constructor(http: HttpClient);
|
|
176
|
+
list(): Promise<ModelsListResponse>;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
declare class UsageApi {
|
|
180
|
+
private readonly http;
|
|
181
|
+
constructor(http: HttpClient);
|
|
182
|
+
get(params?: UsageGetParams): Promise<UsageResponse>;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
interface BuilderforceClientOptions {
|
|
186
|
+
apiKey: string;
|
|
187
|
+
baseUrl?: string;
|
|
188
|
+
fetch?: typeof fetch;
|
|
189
|
+
timeoutMs?: number;
|
|
190
|
+
}
|
|
191
|
+
declare class BuilderforceClient {
|
|
192
|
+
readonly chat: {
|
|
193
|
+
completions: ChatCompletionsApi;
|
|
194
|
+
};
|
|
195
|
+
readonly models: ModelsApi;
|
|
196
|
+
readonly usage: UsageApi;
|
|
197
|
+
constructor(options: BuilderforceClientOptions);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export { type AIUseCase, AI_USE_CASES, BuilderforceApiError, BuilderforceClient, type BuilderforceClientOptions, type ChatCompletionChunk, type ChatCompletionCreateParams, type ChatCompletionResponse, ChatCompletionStream, type ChatMessage, type ChatRole, type ModelsListResponse, type UsageByDay, type UsageByModel, type UsageByUser, type UsageGetParams, type UsageResponse, isAIUseCase };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
// src/infrastructure/sse.ts
|
|
2
|
+
async function* parseSseJson(stream) {
|
|
3
|
+
const reader = stream.getReader();
|
|
4
|
+
const decoder = new TextDecoder();
|
|
5
|
+
let buffer = "";
|
|
6
|
+
while (true) {
|
|
7
|
+
const { done, value } = await reader.read();
|
|
8
|
+
if (done) break;
|
|
9
|
+
buffer += decoder.decode(value, { stream: true });
|
|
10
|
+
const lines = buffer.split("\n");
|
|
11
|
+
buffer = lines.pop() ?? "";
|
|
12
|
+
for (const line of lines) {
|
|
13
|
+
const trimmed = line.trim();
|
|
14
|
+
if (!trimmed.startsWith("data: ")) continue;
|
|
15
|
+
const data = trimmed.slice(6).trim();
|
|
16
|
+
if (data === "[DONE]") return;
|
|
17
|
+
try {
|
|
18
|
+
yield JSON.parse(data);
|
|
19
|
+
} catch {
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// src/application/ChatCompletionsApi.ts
|
|
26
|
+
var ChatCompletionStream = class {
|
|
27
|
+
stream;
|
|
28
|
+
constructor(stream) {
|
|
29
|
+
this.stream = stream;
|
|
30
|
+
}
|
|
31
|
+
[Symbol.asyncIterator]() {
|
|
32
|
+
return parseSseJson(this.stream);
|
|
33
|
+
}
|
|
34
|
+
async toText() {
|
|
35
|
+
let full = "";
|
|
36
|
+
for await (const chunk of this) {
|
|
37
|
+
const delta = chunk.choices?.[0]?.delta?.content;
|
|
38
|
+
if (typeof delta === "string") {
|
|
39
|
+
full += delta;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return full;
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
var ChatCompletionsApi = class {
|
|
46
|
+
http;
|
|
47
|
+
constructor(http) {
|
|
48
|
+
this.http = http;
|
|
49
|
+
}
|
|
50
|
+
async create(params) {
|
|
51
|
+
if (params.stream) {
|
|
52
|
+
const response = await this.http.postRaw("/llm/v1/chat/completions", params);
|
|
53
|
+
if (!response.body) {
|
|
54
|
+
throw new Error("Streaming response body is missing");
|
|
55
|
+
}
|
|
56
|
+
return new ChatCompletionStream(response.body);
|
|
57
|
+
}
|
|
58
|
+
return this.http.postJson("/llm/v1/chat/completions", params);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// src/application/ModelsApi.ts
|
|
63
|
+
var ModelsApi = class {
|
|
64
|
+
http;
|
|
65
|
+
constructor(http) {
|
|
66
|
+
this.http = http;
|
|
67
|
+
}
|
|
68
|
+
list() {
|
|
69
|
+
return this.http.getJson("/llm/v1/models");
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
// src/application/UsageApi.ts
|
|
74
|
+
var UsageApi = class {
|
|
75
|
+
http;
|
|
76
|
+
constructor(http) {
|
|
77
|
+
this.http = http;
|
|
78
|
+
}
|
|
79
|
+
get(params = {}) {
|
|
80
|
+
const query = typeof params.days === "number" ? `?days=${encodeURIComponent(String(params.days))}` : "";
|
|
81
|
+
return this.http.getJson(`/llm/v1/usage${query}`);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// src/infrastructure/httpClient.ts
|
|
86
|
+
var BuilderforceApiError = class extends Error {
|
|
87
|
+
status;
|
|
88
|
+
code;
|
|
89
|
+
details;
|
|
90
|
+
requestId;
|
|
91
|
+
constructor(message, status, code, details, requestId) {
|
|
92
|
+
super(message);
|
|
93
|
+
this.name = "BuilderforceApiError";
|
|
94
|
+
this.status = status;
|
|
95
|
+
this.code = code;
|
|
96
|
+
this.details = details;
|
|
97
|
+
this.requestId = requestId;
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
var HttpClient = class {
|
|
101
|
+
apiKey;
|
|
102
|
+
baseUrl;
|
|
103
|
+
fetchFn;
|
|
104
|
+
timeoutMs;
|
|
105
|
+
constructor(options) {
|
|
106
|
+
this.apiKey = options.apiKey;
|
|
107
|
+
this.baseUrl = options.baseUrl.replace(/\/$/, "");
|
|
108
|
+
this.fetchFn = options.fetchFn ?? fetch;
|
|
109
|
+
this.timeoutMs = options.timeoutMs ?? 6e4;
|
|
110
|
+
}
|
|
111
|
+
async getJson(path) {
|
|
112
|
+
const res = await this.fetchWithTimeout(`${this.baseUrl}${path}`, {
|
|
113
|
+
method: "GET",
|
|
114
|
+
headers: this.authHeaders()
|
|
115
|
+
});
|
|
116
|
+
return this.parseJsonResponse(res);
|
|
117
|
+
}
|
|
118
|
+
async postJson(path, body) {
|
|
119
|
+
const res = await this.fetchWithTimeout(`${this.baseUrl}${path}`, {
|
|
120
|
+
method: "POST",
|
|
121
|
+
headers: {
|
|
122
|
+
...this.authHeaders(),
|
|
123
|
+
"Content-Type": "application/json"
|
|
124
|
+
},
|
|
125
|
+
body: JSON.stringify(body)
|
|
126
|
+
});
|
|
127
|
+
return this.parseJsonResponse(res);
|
|
128
|
+
}
|
|
129
|
+
async postRaw(path, body) {
|
|
130
|
+
const res = await this.fetchWithTimeout(`${this.baseUrl}${path}`, {
|
|
131
|
+
method: "POST",
|
|
132
|
+
headers: {
|
|
133
|
+
...this.authHeaders(),
|
|
134
|
+
"Content-Type": "application/json"
|
|
135
|
+
},
|
|
136
|
+
body: JSON.stringify(body)
|
|
137
|
+
});
|
|
138
|
+
if (!res.ok) {
|
|
139
|
+
throw await this.toApiError(res);
|
|
140
|
+
}
|
|
141
|
+
return res;
|
|
142
|
+
}
|
|
143
|
+
authHeaders() {
|
|
144
|
+
return {
|
|
145
|
+
Authorization: `Bearer ${this.apiKey}`
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
async fetchWithTimeout(input, init) {
|
|
149
|
+
const controller = new AbortController();
|
|
150
|
+
const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
151
|
+
try {
|
|
152
|
+
return await this.fetchFn(input, { ...init, signal: controller.signal });
|
|
153
|
+
} catch (error) {
|
|
154
|
+
if (controller.signal.aborted) {
|
|
155
|
+
throw new BuilderforceApiError(`Request timed out after ${this.timeoutMs}ms`, 408, "timeout");
|
|
156
|
+
}
|
|
157
|
+
throw error;
|
|
158
|
+
} finally {
|
|
159
|
+
clearTimeout(timeout);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
async parseJsonResponse(res) {
|
|
163
|
+
if (!res.ok) {
|
|
164
|
+
throw await this.toApiError(res);
|
|
165
|
+
}
|
|
166
|
+
return res.json();
|
|
167
|
+
}
|
|
168
|
+
async toApiError(res) {
|
|
169
|
+
const fallback = `Request failed (${res.status})`;
|
|
170
|
+
const requestId = res.headers.get("x-request-id") ?? void 0;
|
|
171
|
+
try {
|
|
172
|
+
const payload = await res.json();
|
|
173
|
+
return new BuilderforceApiError(payload.error ?? fallback, res.status, payload.code, payload.details, requestId);
|
|
174
|
+
} catch {
|
|
175
|
+
const text = await res.text().catch(() => "");
|
|
176
|
+
return new BuilderforceApiError(text || fallback, res.status, void 0, void 0, requestId);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
// src/BuilderforceClient.ts
|
|
182
|
+
var BuilderforceClient = class {
|
|
183
|
+
chat;
|
|
184
|
+
models;
|
|
185
|
+
usage;
|
|
186
|
+
constructor(options) {
|
|
187
|
+
const apiKey = options.apiKey?.trim();
|
|
188
|
+
if (!apiKey) {
|
|
189
|
+
throw new BuilderforceApiError(
|
|
190
|
+
"BuilderforceClient requires a non-empty apiKey",
|
|
191
|
+
400,
|
|
192
|
+
"missing_api_key"
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
const http = new HttpClient({
|
|
196
|
+
apiKey,
|
|
197
|
+
baseUrl: options.baseUrl ?? "https://api.builderforce.ai",
|
|
198
|
+
fetchFn: options.fetch,
|
|
199
|
+
timeoutMs: options.timeoutMs
|
|
200
|
+
});
|
|
201
|
+
this.chat = {
|
|
202
|
+
completions: new ChatCompletionsApi(http)
|
|
203
|
+
};
|
|
204
|
+
this.models = new ModelsApi(http);
|
|
205
|
+
this.usage = new UsageApi(http);
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
// src/domain/aiUseCases.ts
|
|
210
|
+
var AI_USE_CASES = [
|
|
211
|
+
"ide.chat",
|
|
212
|
+
"ide.code_complete",
|
|
213
|
+
"training.dataset_generate",
|
|
214
|
+
"training.dataset_evaluate",
|
|
215
|
+
"agent.inference",
|
|
216
|
+
"coder.code",
|
|
217
|
+
"coder.review",
|
|
218
|
+
"coder.test",
|
|
219
|
+
"coder.debug",
|
|
220
|
+
"coder.refactor",
|
|
221
|
+
"coder.document",
|
|
222
|
+
"coder.architect",
|
|
223
|
+
"coach.chat",
|
|
224
|
+
"coach.insight",
|
|
225
|
+
"coach.classify",
|
|
226
|
+
"studio.compose",
|
|
227
|
+
"studio.script",
|
|
228
|
+
"studio.brief",
|
|
229
|
+
"pitch_deck.generate",
|
|
230
|
+
"investor.update",
|
|
231
|
+
"ask.general",
|
|
232
|
+
"tool.classify_email",
|
|
233
|
+
"tool.categorize_expense",
|
|
234
|
+
"tool.contract_analyze",
|
|
235
|
+
"tool.competitor_scan",
|
|
236
|
+
"tool.feature_score",
|
|
237
|
+
"tool.market_research",
|
|
238
|
+
"tool.health_score",
|
|
239
|
+
"tool.journey_insight",
|
|
240
|
+
"vision.describe",
|
|
241
|
+
"ocr.extract",
|
|
242
|
+
"embed.text",
|
|
243
|
+
"match",
|
|
244
|
+
"match_tailor",
|
|
245
|
+
"match_insights",
|
|
246
|
+
"resume_roast",
|
|
247
|
+
"skill_extract",
|
|
248
|
+
"job_parser",
|
|
249
|
+
"autofill",
|
|
250
|
+
"article_writer",
|
|
251
|
+
"studio_script",
|
|
252
|
+
"studio_edit_script",
|
|
253
|
+
"studio_misc",
|
|
254
|
+
"linkedin_post",
|
|
255
|
+
"interview_questions",
|
|
256
|
+
"interview_analyze",
|
|
257
|
+
"chat",
|
|
258
|
+
"career",
|
|
259
|
+
"discovery",
|
|
260
|
+
"dashboard_summary"
|
|
261
|
+
];
|
|
262
|
+
function isAIUseCase(value) {
|
|
263
|
+
return AI_USE_CASES.includes(value);
|
|
264
|
+
}
|
|
265
|
+
export {
|
|
266
|
+
AI_USE_CASES,
|
|
267
|
+
BuilderforceApiError,
|
|
268
|
+
BuilderforceClient,
|
|
269
|
+
ChatCompletionStream,
|
|
270
|
+
isAIUseCase
|
|
271
|
+
};
|
|
272
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/infrastructure/sse.ts","../src/application/ChatCompletionsApi.ts","../src/application/ModelsApi.ts","../src/application/UsageApi.ts","../src/infrastructure/httpClient.ts","../src/BuilderforceClient.ts","../src/domain/aiUseCases.ts"],"sourcesContent":["export async function* parseSseJson<T>(\r\n stream: ReadableStream<Uint8Array>,\r\n): AsyncGenerator<T, void, unknown> {\r\n const reader = stream.getReader();\r\n const decoder = new TextDecoder();\r\n let buffer = '';\r\n\r\n while (true) {\r\n const { done, value } = await reader.read();\r\n if (done) break;\r\n\r\n buffer += decoder.decode(value, { stream: true });\r\n const lines = buffer.split('\\n');\r\n buffer = lines.pop() ?? '';\r\n\r\n for (const line of lines) {\r\n const trimmed = line.trim();\r\n if (!trimmed.startsWith('data: ')) continue;\r\n\r\n const data = trimmed.slice(6).trim();\r\n if (data === '[DONE]') return;\r\n\r\n try {\r\n yield JSON.parse(data) as T;\r\n } catch {\r\n // Skip malformed chunks instead of breaking the stream.\r\n }\r\n }\r\n }\r\n}\r\n","import type { ChatCompletionChunk, ChatCompletionCreateParams, ChatCompletionResponse } from '../domain/types';\r\nimport { HttpClient } from '../infrastructure/httpClient';\r\nimport { parseSseJson } from '../infrastructure/sse';\r\n\r\nexport class ChatCompletionStream implements AsyncIterable<ChatCompletionChunk> {\r\n private readonly stream: ReadableStream<Uint8Array>;\r\n\r\n constructor(stream: ReadableStream<Uint8Array>) {\r\n this.stream = stream;\r\n }\r\n\r\n [Symbol.asyncIterator](): AsyncIterator<ChatCompletionChunk, void, unknown> {\r\n return parseSseJson<ChatCompletionChunk>(this.stream);\r\n }\r\n\r\n async toText(): Promise<string> {\r\n let full = '';\r\n for await (const chunk of this) {\r\n const delta = chunk.choices?.[0]?.delta?.content;\r\n if (typeof delta === 'string') {\r\n full += delta;\r\n }\r\n }\r\n return full;\r\n }\r\n}\r\n\r\nexport class ChatCompletionsApi {\r\n private readonly http: HttpClient;\r\n\r\n constructor(http: HttpClient) {\r\n this.http = http;\r\n }\r\n\r\n async create(params: ChatCompletionCreateParams & { stream: true }): Promise<ChatCompletionStream>;\r\n async create(params: ChatCompletionCreateParams & { stream?: false | undefined }): Promise<ChatCompletionResponse>;\r\n async create(\r\n params: ChatCompletionCreateParams,\r\n ): Promise<ChatCompletionResponse | ChatCompletionStream> {\r\n if (params.stream) {\r\n const response = await this.http.postRaw('/llm/v1/chat/completions', params);\r\n if (!response.body) {\r\n throw new Error('Streaming response body is missing');\r\n }\r\n return new ChatCompletionStream(response.body);\r\n }\r\n\r\n return this.http.postJson<ChatCompletionResponse>('/llm/v1/chat/completions', params);\r\n }\r\n}\r\n","import type { ModelsListResponse } from '../domain/types';\r\nimport { HttpClient } from '../infrastructure/httpClient';\r\n\r\nexport class ModelsApi {\r\n private readonly http: HttpClient;\r\n\r\n constructor(http: HttpClient) {\r\n this.http = http;\r\n }\r\n\r\n list(): Promise<ModelsListResponse> {\r\n return this.http.getJson<ModelsListResponse>('/llm/v1/models');\r\n }\r\n}\r\n","import type { UsageGetParams, UsageResponse } from '../domain/types';\r\nimport { HttpClient } from '../infrastructure/httpClient';\r\n\r\nexport class UsageApi {\r\n private readonly http: HttpClient;\r\n\r\n constructor(http: HttpClient) {\r\n this.http = http;\r\n }\r\n\r\n get(params: UsageGetParams = {}): Promise<UsageResponse> {\r\n const query = typeof params.days === 'number' ? `?days=${encodeURIComponent(String(params.days))}` : '';\r\n return this.http.getJson<UsageResponse>(`/llm/v1/usage${query}`);\r\n }\r\n}\r\n","export class BuilderforceApiError extends Error {\r\n public readonly status: number;\r\n public readonly code?: string;\r\n public readonly details?: unknown;\r\n public readonly requestId?: string;\r\n\r\n constructor(message: string, status: number, code?: string, details?: unknown, requestId?: string) {\r\n super(message);\r\n this.name = 'BuilderforceApiError';\r\n this.status = status;\r\n this.code = code;\r\n this.details = details;\r\n this.requestId = requestId;\r\n }\r\n}\r\n\r\nexport interface HttpClientOptions {\r\n apiKey: string;\r\n baseUrl: string;\r\n fetchFn?: typeof fetch;\r\n timeoutMs?: number;\r\n}\r\n\r\nexport class HttpClient {\r\n private readonly apiKey: string;\r\n private readonly baseUrl: string;\r\n private readonly fetchFn: typeof fetch;\r\n private readonly timeoutMs: number;\r\n\r\n constructor(options: HttpClientOptions) {\r\n this.apiKey = options.apiKey;\r\n this.baseUrl = options.baseUrl.replace(/\\/$/, '');\r\n this.fetchFn = options.fetchFn ?? fetch;\r\n this.timeoutMs = options.timeoutMs ?? 60_000;\r\n }\r\n\r\n async getJson<T>(path: string): Promise<T> {\r\n const res = await this.fetchWithTimeout(`${this.baseUrl}${path}`, {\r\n method: 'GET',\r\n headers: this.authHeaders(),\r\n });\r\n return this.parseJsonResponse<T>(res);\r\n }\r\n\r\n async postJson<T>(path: string, body: unknown): Promise<T> {\r\n const res = await this.fetchWithTimeout(`${this.baseUrl}${path}`, {\r\n method: 'POST',\r\n headers: {\r\n ...this.authHeaders(),\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify(body),\r\n });\r\n return this.parseJsonResponse<T>(res);\r\n }\r\n\r\n async postRaw(path: string, body: unknown): Promise<Response> {\r\n const res = await this.fetchWithTimeout(`${this.baseUrl}${path}`, {\r\n method: 'POST',\r\n headers: {\r\n ...this.authHeaders(),\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify(body),\r\n });\r\n if (!res.ok) {\r\n throw await this.toApiError(res);\r\n }\r\n return res;\r\n }\r\n\r\n private authHeaders(): Record<string, string> {\r\n return {\r\n Authorization: `Bearer ${this.apiKey}`,\r\n };\r\n }\r\n\r\n private async fetchWithTimeout(input: RequestInfo | URL, init: RequestInit): Promise<Response> {\r\n const controller = new AbortController();\r\n const timeout = setTimeout(() => controller.abort(), this.timeoutMs);\r\n try {\r\n return await this.fetchFn(input, { ...init, signal: controller.signal });\r\n } catch (error) {\r\n if (controller.signal.aborted) {\r\n throw new BuilderforceApiError(`Request timed out after ${this.timeoutMs}ms`, 408, 'timeout');\r\n }\r\n throw error;\r\n } finally {\r\n clearTimeout(timeout);\r\n }\r\n }\r\n\r\n private async parseJsonResponse<T>(res: Response): Promise<T> {\r\n if (!res.ok) {\r\n throw await this.toApiError(res);\r\n }\r\n return res.json() as Promise<T>;\r\n }\r\n\r\n private async toApiError(res: Response): Promise<BuilderforceApiError> {\r\n const fallback = `Request failed (${res.status})`;\r\n const requestId = res.headers.get('x-request-id') ?? undefined;\r\n try {\r\n const payload = await res.json() as { error?: string; code?: string; details?: unknown };\r\n return new BuilderforceApiError(payload.error ?? fallback, res.status, payload.code, payload.details, requestId);\r\n } catch {\r\n const text = await res.text().catch(() => '');\r\n return new BuilderforceApiError(text || fallback, res.status, undefined, undefined, requestId);\r\n }\r\n }\r\n}\r\n","import { ChatCompletionsApi } from './application/ChatCompletionsApi';\r\nimport { ModelsApi } from './application/ModelsApi';\r\nimport { UsageApi } from './application/UsageApi';\r\nimport { BuilderforceApiError, HttpClient } from './infrastructure/httpClient';\r\n\r\nexport interface BuilderforceClientOptions {\r\n apiKey: string;\r\n baseUrl?: string;\r\n fetch?: typeof fetch;\r\n timeoutMs?: number;\r\n}\r\n\r\nexport class BuilderforceClient {\r\n public readonly chat: {\r\n completions: ChatCompletionsApi;\r\n };\r\n public readonly models: ModelsApi;\r\n public readonly usage: UsageApi;\r\n\r\n constructor(options: BuilderforceClientOptions) {\r\n const apiKey = options.apiKey?.trim();\r\n if (!apiKey) {\r\n throw new BuilderforceApiError(\r\n 'BuilderforceClient requires a non-empty apiKey',\r\n 400,\r\n 'missing_api_key',\r\n );\r\n }\r\n\r\n const http = new HttpClient({\r\n apiKey,\r\n baseUrl: options.baseUrl ?? 'https://api.builderforce.ai',\r\n fetchFn: options.fetch,\r\n timeoutMs: options.timeoutMs,\r\n });\r\n\r\n this.chat = {\r\n completions: new ChatCompletionsApi(http),\r\n };\r\n this.models = new ModelsApi(http);\r\n this.usage = new UsageApi(http);\r\n }\r\n}\r\n","// Keep this list aligned with api/src/application/llm/aiUseCases.ts.\r\nexport const AI_USE_CASES = [\r\n 'ide.chat',\r\n 'ide.code_complete',\r\n 'training.dataset_generate',\r\n 'training.dataset_evaluate',\r\n 'agent.inference',\r\n 'coder.code',\r\n 'coder.review',\r\n 'coder.test',\r\n 'coder.debug',\r\n 'coder.refactor',\r\n 'coder.document',\r\n 'coder.architect',\r\n 'coach.chat',\r\n 'coach.insight',\r\n 'coach.classify',\r\n 'studio.compose',\r\n 'studio.script',\r\n 'studio.brief',\r\n 'pitch_deck.generate',\r\n 'investor.update',\r\n 'ask.general',\r\n 'tool.classify_email',\r\n 'tool.categorize_expense',\r\n 'tool.contract_analyze',\r\n 'tool.competitor_scan',\r\n 'tool.feature_score',\r\n 'tool.market_research',\r\n 'tool.health_score',\r\n 'tool.journey_insight',\r\n 'vision.describe',\r\n 'ocr.extract',\r\n 'embed.text',\r\n 'match',\r\n 'match_tailor',\r\n 'match_insights',\r\n 'resume_roast',\r\n 'skill_extract',\r\n 'job_parser',\r\n 'autofill',\r\n 'article_writer',\r\n 'studio_script',\r\n 'studio_edit_script',\r\n 'studio_misc',\r\n 'linkedin_post',\r\n 'interview_questions',\r\n 'interview_analyze',\r\n 'chat',\r\n 'career',\r\n 'discovery',\r\n 'dashboard_summary',\r\n] as const;\r\n\r\nexport type AIUseCase = (typeof AI_USE_CASES)[number];\r\n\r\nexport function isAIUseCase(value: string): value is AIUseCase {\r\n return (AI_USE_CASES as readonly string[]).includes(value);\r\n}\r\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@seanhogg/builderforce-sdk",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Typed SDK for the Builderforce.ai LLM gateway — chat completions, models, and usage analytics over an OpenAI-compatible surface.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Sean Hogg",
|
|
7
|
+
"homepage": "https://github.com/SeanHogg/Builderforce.ai/tree/main/sdk#readme",
|
|
8
|
+
"bugs": {
|
|
9
|
+
"url": "https://github.com/SeanHogg/Builderforce.ai/issues"
|
|
10
|
+
},
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/SeanHogg/Builderforce.ai.git",
|
|
14
|
+
"directory": "sdk"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"builderforce",
|
|
18
|
+
"llm",
|
|
19
|
+
"openai-compatible",
|
|
20
|
+
"ai-gateway",
|
|
21
|
+
"chat-completions",
|
|
22
|
+
"openrouter",
|
|
23
|
+
"cerebras",
|
|
24
|
+
"ollama",
|
|
25
|
+
"sdk",
|
|
26
|
+
"typescript"
|
|
27
|
+
],
|
|
28
|
+
"type": "module",
|
|
29
|
+
"main": "dist/index.cjs",
|
|
30
|
+
"module": "dist/index.mjs",
|
|
31
|
+
"types": "dist/index.d.ts",
|
|
32
|
+
"exports": {
|
|
33
|
+
".": {
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
35
|
+
"import": "./dist/index.mjs",
|
|
36
|
+
"require": "./dist/index.cjs"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"files": [
|
|
40
|
+
"dist"
|
|
41
|
+
],
|
|
42
|
+
"publishConfig": {
|
|
43
|
+
"access": "public"
|
|
44
|
+
},
|
|
45
|
+
"scripts": {
|
|
46
|
+
"check:usecases": "node scripts/check-usecases-sync.mjs",
|
|
47
|
+
"build": "tsup --config tsup.config.ts",
|
|
48
|
+
"type-check": "tsc --noEmit",
|
|
49
|
+
"test": "npm run check:usecases && vitest run",
|
|
50
|
+
"prepublishOnly": "npm run build"
|
|
51
|
+
},
|
|
52
|
+
"engines": {
|
|
53
|
+
"node": ">=18"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@types/node": "^24.7.2",
|
|
57
|
+
"tsup": "^8.5.0",
|
|
58
|
+
"typescript": "^5.9.3",
|
|
59
|
+
"vitest": "^4.0.3"
|
|
60
|
+
}
|
|
61
|
+
}
|