@modelrelay/sdk 0.14.1 → 0.17.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 +79 -3
- package/dist/index.cjs +291 -72
- package/dist/index.d.cts +82 -43
- package/dist/index.d.ts +82 -43
- package/dist/index.js +288 -68
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -261,7 +261,7 @@ function isTokenReusable(token) {
|
|
|
261
261
|
// package.json
|
|
262
262
|
var package_default = {
|
|
263
263
|
name: "@modelrelay/sdk",
|
|
264
|
-
version: "0.
|
|
264
|
+
version: "0.17.0",
|
|
265
265
|
description: "TypeScript SDK for the ModelRelay API",
|
|
266
266
|
type: "module",
|
|
267
267
|
main: "dist/index.cjs",
|
|
@@ -320,30 +320,6 @@ var StopReasons = {
|
|
|
320
320
|
Incomplete: "incomplete",
|
|
321
321
|
Unknown: "unknown"
|
|
322
322
|
};
|
|
323
|
-
var Providers = {
|
|
324
|
-
OpenAI: "openai",
|
|
325
|
-
Anthropic: "anthropic",
|
|
326
|
-
XAI: "xai",
|
|
327
|
-
GoogleAIStudio: "google-ai-studio",
|
|
328
|
-
Echo: "echo"
|
|
329
|
-
};
|
|
330
|
-
var Models = {
|
|
331
|
-
// OpenAI models (provider-agnostic identifiers)
|
|
332
|
-
Gpt4o: "gpt-4o",
|
|
333
|
-
Gpt4oMini: "gpt-4o-mini",
|
|
334
|
-
Gpt51: "gpt-5.1",
|
|
335
|
-
// Anthropic models (provider-agnostic identifiers)
|
|
336
|
-
Claude35HaikuLatest: "claude-3-5-haiku-latest",
|
|
337
|
-
Claude35SonnetLatest: "claude-3-5-sonnet-latest",
|
|
338
|
-
ClaudeOpus45: "claude-opus-4-5",
|
|
339
|
-
Claude35Haiku: "claude-3.5-haiku",
|
|
340
|
-
// xAI / Grok models
|
|
341
|
-
Grok2: "grok-2",
|
|
342
|
-
Grok4_1FastNonReasoning: "grok-4-1-fast-non-reasoning",
|
|
343
|
-
Grok4_1FastReasoning: "grok-4-1-fast-reasoning",
|
|
344
|
-
// Internal echo model for testing.
|
|
345
|
-
Echo1: "echo-1"
|
|
346
|
-
};
|
|
347
323
|
function createUsage(inputTokens, outputTokens, totalTokens) {
|
|
348
324
|
return {
|
|
349
325
|
inputTokens,
|
|
@@ -354,14 +330,24 @@ function createUsage(inputTokens, outputTokens, totalTokens) {
|
|
|
354
330
|
var ToolTypes = {
|
|
355
331
|
Function: "function",
|
|
356
332
|
Web: "web",
|
|
333
|
+
WebSearch: "web_search",
|
|
357
334
|
XSearch: "x_search",
|
|
358
335
|
CodeExecution: "code_execution"
|
|
359
336
|
};
|
|
337
|
+
var WebToolModes = {
|
|
338
|
+
Search: "search",
|
|
339
|
+
Browse: "browse"
|
|
340
|
+
};
|
|
360
341
|
var ToolChoiceTypes = {
|
|
361
342
|
Auto: "auto",
|
|
362
343
|
Required: "required",
|
|
363
344
|
None: "none"
|
|
364
345
|
};
|
|
346
|
+
var ResponseFormatTypes = {
|
|
347
|
+
Text: "text",
|
|
348
|
+
JsonObject: "json_object",
|
|
349
|
+
JsonSchema: "json_schema"
|
|
350
|
+
};
|
|
365
351
|
function mergeMetrics(base, override) {
|
|
366
352
|
if (!base && !override) return void 0;
|
|
367
353
|
return {
|
|
@@ -395,34 +381,14 @@ function stopReasonToString(value) {
|
|
|
395
381
|
if (typeof value === "string") return value;
|
|
396
382
|
return value.other?.trim() || void 0;
|
|
397
383
|
}
|
|
398
|
-
function normalizeProvider(value) {
|
|
399
|
-
if (value === void 0 || value === null) return void 0;
|
|
400
|
-
const str = String(value).trim();
|
|
401
|
-
if (!str) return void 0;
|
|
402
|
-
const lower = str.toLowerCase();
|
|
403
|
-
for (const p of Object.values(Providers)) {
|
|
404
|
-
if (lower === p) return p;
|
|
405
|
-
}
|
|
406
|
-
return { other: str };
|
|
407
|
-
}
|
|
408
|
-
function providerToString(value) {
|
|
409
|
-
if (!value) return void 0;
|
|
410
|
-
if (typeof value === "string") return value;
|
|
411
|
-
return value.other?.trim() || void 0;
|
|
412
|
-
}
|
|
413
384
|
function normalizeModelId(value) {
|
|
414
385
|
if (value === void 0 || value === null) return void 0;
|
|
415
386
|
const str = String(value).trim();
|
|
416
387
|
if (!str) return void 0;
|
|
417
|
-
|
|
418
|
-
for (const m of Object.values(Models)) {
|
|
419
|
-
if (lower === m) return m;
|
|
420
|
-
}
|
|
421
|
-
return { other: str };
|
|
388
|
+
return str;
|
|
422
389
|
}
|
|
423
390
|
function modelToString(value) {
|
|
424
|
-
|
|
425
|
-
return value.other?.trim() || "";
|
|
391
|
+
return String(value).trim();
|
|
426
392
|
}
|
|
427
393
|
|
|
428
394
|
// src/tools.ts
|
|
@@ -1080,7 +1046,6 @@ var ChatCompletionsClient = class {
|
|
|
1080
1046
|
if (!hasUserMessage(params.messages)) {
|
|
1081
1047
|
throw new ConfigError("at least one user message is required");
|
|
1082
1048
|
}
|
|
1083
|
-
validateRequestModel(params.model);
|
|
1084
1049
|
const authHeaders = await this.auth.authForChat(params.customerId);
|
|
1085
1050
|
const body = buildProxyBody(
|
|
1086
1051
|
params,
|
|
@@ -1094,7 +1059,6 @@ var ChatCompletionsClient = class {
|
|
|
1094
1059
|
const baseContext = {
|
|
1095
1060
|
method: "POST",
|
|
1096
1061
|
path: "/llm/proxy",
|
|
1097
|
-
provider: params.provider,
|
|
1098
1062
|
model: params.model,
|
|
1099
1063
|
requestId
|
|
1100
1064
|
};
|
|
@@ -1144,6 +1108,80 @@ var ChatCompletionsClient = class {
|
|
|
1144
1108
|
trace
|
|
1145
1109
|
);
|
|
1146
1110
|
}
|
|
1111
|
+
/**
|
|
1112
|
+
* Stream structured JSON responses using the NDJSON contract defined for
|
|
1113
|
+
* /llm/proxy. The request must include a structured responseFormat.
|
|
1114
|
+
*/
|
|
1115
|
+
async streamJSON(params, options = {}) {
|
|
1116
|
+
const metrics = mergeMetrics(this.metrics, options.metrics);
|
|
1117
|
+
const trace = mergeTrace(this.trace, options.trace);
|
|
1118
|
+
if (!params?.messages?.length) {
|
|
1119
|
+
throw new ConfigError("at least one message is required");
|
|
1120
|
+
}
|
|
1121
|
+
if (!hasUserMessage(params.messages)) {
|
|
1122
|
+
throw new ConfigError("at least one user message is required");
|
|
1123
|
+
}
|
|
1124
|
+
if (!params.responseFormat || params.responseFormat.type !== "json_object" && params.responseFormat.type !== "json_schema") {
|
|
1125
|
+
throw new ConfigError(
|
|
1126
|
+
"responseFormat with type=json_object or json_schema is required for structured streaming"
|
|
1127
|
+
);
|
|
1128
|
+
}
|
|
1129
|
+
const authHeaders = await this.auth.authForChat(params.customerId);
|
|
1130
|
+
const body = buildProxyBody(
|
|
1131
|
+
params,
|
|
1132
|
+
mergeMetadata(this.defaultMetadata, params.metadata, options.metadata)
|
|
1133
|
+
);
|
|
1134
|
+
const requestId = params.requestId || options.requestId;
|
|
1135
|
+
const headers = { ...options.headers || {} };
|
|
1136
|
+
if (requestId) {
|
|
1137
|
+
headers[REQUEST_ID_HEADER] = requestId;
|
|
1138
|
+
}
|
|
1139
|
+
const baseContext = {
|
|
1140
|
+
method: "POST",
|
|
1141
|
+
path: "/llm/proxy",
|
|
1142
|
+
model: params.model,
|
|
1143
|
+
requestId
|
|
1144
|
+
};
|
|
1145
|
+
const response = await this.http.request("/llm/proxy", {
|
|
1146
|
+
method: "POST",
|
|
1147
|
+
body,
|
|
1148
|
+
headers,
|
|
1149
|
+
apiKey: authHeaders.apiKey,
|
|
1150
|
+
accessToken: authHeaders.accessToken,
|
|
1151
|
+
accept: "application/x-ndjson",
|
|
1152
|
+
raw: true,
|
|
1153
|
+
signal: options.signal,
|
|
1154
|
+
timeoutMs: options.timeoutMs ?? 0,
|
|
1155
|
+
useDefaultTimeout: false,
|
|
1156
|
+
connectTimeoutMs: options.connectTimeoutMs,
|
|
1157
|
+
retry: options.retry,
|
|
1158
|
+
metrics,
|
|
1159
|
+
trace,
|
|
1160
|
+
context: baseContext
|
|
1161
|
+
});
|
|
1162
|
+
const resolvedRequestId = requestIdFromHeaders(response.headers) || requestId || void 0;
|
|
1163
|
+
if (!response.ok) {
|
|
1164
|
+
throw await parseErrorResponse(response);
|
|
1165
|
+
}
|
|
1166
|
+
const contentType = response.headers.get("Content-Type") || "";
|
|
1167
|
+
if (!/application\/(x-)?ndjson/i.test(contentType)) {
|
|
1168
|
+
throw new TransportError(
|
|
1169
|
+
`expected NDJSON structured stream, got Content-Type ${contentType || "missing"}`,
|
|
1170
|
+
{ kind: "request" }
|
|
1171
|
+
);
|
|
1172
|
+
}
|
|
1173
|
+
const streamContext = {
|
|
1174
|
+
...baseContext,
|
|
1175
|
+
requestId: resolvedRequestId ?? baseContext.requestId
|
|
1176
|
+
};
|
|
1177
|
+
return new StructuredJSONStream(
|
|
1178
|
+
response,
|
|
1179
|
+
resolvedRequestId,
|
|
1180
|
+
streamContext,
|
|
1181
|
+
metrics,
|
|
1182
|
+
trace
|
|
1183
|
+
);
|
|
1184
|
+
}
|
|
1147
1185
|
};
|
|
1148
1186
|
var ChatCompletionsStream = class {
|
|
1149
1187
|
constructor(response, requestId, context, metrics, trace) {
|
|
@@ -1245,6 +1283,164 @@ var ChatCompletionsStream = class {
|
|
|
1245
1283
|
});
|
|
1246
1284
|
}
|
|
1247
1285
|
};
|
|
1286
|
+
var StructuredJSONStream = class {
|
|
1287
|
+
constructor(response, requestId, context, metrics, trace) {
|
|
1288
|
+
this.closed = false;
|
|
1289
|
+
this.sawTerminal = false;
|
|
1290
|
+
if (!response.body) {
|
|
1291
|
+
throw new ConfigError("streaming response is missing a body");
|
|
1292
|
+
}
|
|
1293
|
+
this.response = response;
|
|
1294
|
+
this.requestId = requestId;
|
|
1295
|
+
this.context = context;
|
|
1296
|
+
this.metrics = metrics;
|
|
1297
|
+
this.trace = trace;
|
|
1298
|
+
}
|
|
1299
|
+
async cancel(reason) {
|
|
1300
|
+
this.closed = true;
|
|
1301
|
+
try {
|
|
1302
|
+
await this.response.body?.cancel(reason);
|
|
1303
|
+
} catch {
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
async *[Symbol.asyncIterator]() {
|
|
1307
|
+
if (this.closed) {
|
|
1308
|
+
return;
|
|
1309
|
+
}
|
|
1310
|
+
const body = this.response.body;
|
|
1311
|
+
if (!body) {
|
|
1312
|
+
throw new ConfigError("streaming response is missing a body");
|
|
1313
|
+
}
|
|
1314
|
+
const reader = body.getReader();
|
|
1315
|
+
const decoder = new TextDecoder();
|
|
1316
|
+
let buffer = "";
|
|
1317
|
+
try {
|
|
1318
|
+
while (true) {
|
|
1319
|
+
if (this.closed) {
|
|
1320
|
+
await reader.cancel();
|
|
1321
|
+
return;
|
|
1322
|
+
}
|
|
1323
|
+
const { value, done } = await reader.read();
|
|
1324
|
+
if (done) {
|
|
1325
|
+
const { records: records2 } = consumeNDJSONBuffer(buffer, true);
|
|
1326
|
+
for (const line of records2) {
|
|
1327
|
+
const evt = this.parseRecord(line);
|
|
1328
|
+
if (evt) {
|
|
1329
|
+
this.traceStructuredEvent(evt, line);
|
|
1330
|
+
yield evt;
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
if (!this.sawTerminal) {
|
|
1334
|
+
throw new TransportError(
|
|
1335
|
+
"structured stream ended without completion or error",
|
|
1336
|
+
{ kind: "request" }
|
|
1337
|
+
);
|
|
1338
|
+
}
|
|
1339
|
+
return;
|
|
1340
|
+
}
|
|
1341
|
+
buffer += decoder.decode(value, { stream: true });
|
|
1342
|
+
const { records, remainder } = consumeNDJSONBuffer(buffer);
|
|
1343
|
+
buffer = remainder;
|
|
1344
|
+
for (const line of records) {
|
|
1345
|
+
const evt = this.parseRecord(line);
|
|
1346
|
+
if (evt) {
|
|
1347
|
+
this.traceStructuredEvent(evt, line);
|
|
1348
|
+
yield evt;
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1352
|
+
} catch (err) {
|
|
1353
|
+
this.trace?.streamError?.({ context: this.context, error: err });
|
|
1354
|
+
throw err;
|
|
1355
|
+
} finally {
|
|
1356
|
+
this.closed = true;
|
|
1357
|
+
reader.releaseLock();
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
1360
|
+
async collect() {
|
|
1361
|
+
let last;
|
|
1362
|
+
for await (const evt of this) {
|
|
1363
|
+
last = evt;
|
|
1364
|
+
if (evt.type === "completion") {
|
|
1365
|
+
return evt.payload;
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
throw new TransportError(
|
|
1369
|
+
"structured stream ended without completion or error",
|
|
1370
|
+
{ kind: "request" }
|
|
1371
|
+
);
|
|
1372
|
+
}
|
|
1373
|
+
parseRecord(line) {
|
|
1374
|
+
let parsed;
|
|
1375
|
+
try {
|
|
1376
|
+
parsed = JSON.parse(line);
|
|
1377
|
+
} catch (err) {
|
|
1378
|
+
throw new TransportError("invalid JSON in structured stream", {
|
|
1379
|
+
kind: "request",
|
|
1380
|
+
cause: err
|
|
1381
|
+
});
|
|
1382
|
+
}
|
|
1383
|
+
if (!parsed || typeof parsed !== "object") {
|
|
1384
|
+
throw new TransportError("structured stream record is not an object", {
|
|
1385
|
+
kind: "request"
|
|
1386
|
+
});
|
|
1387
|
+
}
|
|
1388
|
+
const obj = parsed;
|
|
1389
|
+
const rawType = String(obj.type || "").trim().toLowerCase();
|
|
1390
|
+
if (!rawType) return null;
|
|
1391
|
+
if (rawType === "start") {
|
|
1392
|
+
return null;
|
|
1393
|
+
}
|
|
1394
|
+
if (rawType === "error") {
|
|
1395
|
+
this.sawTerminal = true;
|
|
1396
|
+
const status = typeof obj.status === "number" && obj.status > 0 ? obj.status : 500;
|
|
1397
|
+
const message = typeof obj.message === "string" && obj.message.trim() ? obj.message : "structured stream error";
|
|
1398
|
+
const code = typeof obj.code === "string" && obj.code.trim() ? obj.code : void 0;
|
|
1399
|
+
throw new APIError(message, {
|
|
1400
|
+
status,
|
|
1401
|
+
code,
|
|
1402
|
+
requestId: this.requestId
|
|
1403
|
+
});
|
|
1404
|
+
}
|
|
1405
|
+
if (rawType !== "update" && rawType !== "completion") {
|
|
1406
|
+
return null;
|
|
1407
|
+
}
|
|
1408
|
+
if (obj.payload === void 0 || obj.payload === null) {
|
|
1409
|
+
throw new TransportError(
|
|
1410
|
+
"structured stream record missing payload",
|
|
1411
|
+
{ kind: "request" }
|
|
1412
|
+
);
|
|
1413
|
+
}
|
|
1414
|
+
if (rawType === "completion") {
|
|
1415
|
+
this.sawTerminal = true;
|
|
1416
|
+
}
|
|
1417
|
+
const event = {
|
|
1418
|
+
type: rawType,
|
|
1419
|
+
// biome-ignore lint/suspicious/noExplicitAny: payload is untyped json
|
|
1420
|
+
payload: obj.payload,
|
|
1421
|
+
requestId: this.requestId
|
|
1422
|
+
};
|
|
1423
|
+
return event;
|
|
1424
|
+
}
|
|
1425
|
+
traceStructuredEvent(evt, raw) {
|
|
1426
|
+
if (!this.trace?.streamEvent) return;
|
|
1427
|
+
const event = {
|
|
1428
|
+
type: "custom",
|
|
1429
|
+
event: "structured",
|
|
1430
|
+
data: { type: evt.type, payload: evt.payload },
|
|
1431
|
+
textDelta: void 0,
|
|
1432
|
+
toolCallDelta: void 0,
|
|
1433
|
+
toolCalls: void 0,
|
|
1434
|
+
responseId: void 0,
|
|
1435
|
+
model: void 0,
|
|
1436
|
+
stopReason: void 0,
|
|
1437
|
+
usage: void 0,
|
|
1438
|
+
requestId: this.requestId,
|
|
1439
|
+
raw
|
|
1440
|
+
};
|
|
1441
|
+
this.trace.streamEvent({ context: this.context, event });
|
|
1442
|
+
}
|
|
1443
|
+
};
|
|
1248
1444
|
function consumeSSEBuffer(buffer, flush = false) {
|
|
1249
1445
|
const events = [];
|
|
1250
1446
|
let eventName = "";
|
|
@@ -1287,6 +1483,19 @@ function consumeSSEBuffer(buffer, flush = false) {
|
|
|
1287
1483
|
}
|
|
1288
1484
|
return { events, remainder };
|
|
1289
1485
|
}
|
|
1486
|
+
function consumeNDJSONBuffer(buffer, flush = false) {
|
|
1487
|
+
const lines = buffer.split(/\r?\n/);
|
|
1488
|
+
const records = [];
|
|
1489
|
+
const lastIndex = lines.length - 1;
|
|
1490
|
+
const limit = flush ? lines.length : Math.max(0, lastIndex);
|
|
1491
|
+
for (let i = 0; i < limit; i++) {
|
|
1492
|
+
const line = lines[i]?.trim();
|
|
1493
|
+
if (!line) continue;
|
|
1494
|
+
records.push(line);
|
|
1495
|
+
}
|
|
1496
|
+
const remainder = flush ? "" : lines[lastIndex] ?? "";
|
|
1497
|
+
return { records, remainder };
|
|
1498
|
+
}
|
|
1290
1499
|
function mapChatEvent(raw, requestId) {
|
|
1291
1500
|
let parsed = raw.data;
|
|
1292
1501
|
if (raw.data) {
|
|
@@ -1415,7 +1624,6 @@ function normalizeChatResponse(payload, requestId) {
|
|
|
1415
1624
|
const p = payload;
|
|
1416
1625
|
const response = {
|
|
1417
1626
|
id: p?.id,
|
|
1418
|
-
provider: normalizeProvider(p?.provider),
|
|
1419
1627
|
content: Array.isArray(p?.content) ? p.content : p?.content ? [String(p.content)] : [],
|
|
1420
1628
|
stopReason: normalizeStopReason(p?.stop_reason),
|
|
1421
1629
|
model: normalizeModelId(p?.model),
|
|
@@ -1446,19 +1654,6 @@ function normalizeUsage(payload) {
|
|
|
1446
1654
|
const totalTokens = Number(payload.total_tokens ?? 0);
|
|
1447
1655
|
return createUsage(inputTokens, outputTokens, totalTokens || void 0);
|
|
1448
1656
|
}
|
|
1449
|
-
function validateRequestModel(model) {
|
|
1450
|
-
if (model === void 0 || model === null) return;
|
|
1451
|
-
const value = modelToString(model).trim();
|
|
1452
|
-
if (!value) {
|
|
1453
|
-
throw new ConfigError("model id must be a non-empty string when provided");
|
|
1454
|
-
}
|
|
1455
|
-
const knownModels = Object.values(Models);
|
|
1456
|
-
if (!knownModels.includes(value)) {
|
|
1457
|
-
throw new ConfigError(
|
|
1458
|
-
`unsupported model id "${value}". Use one of the SDK Models.* constants or omit model to use the tier's default model.`
|
|
1459
|
-
);
|
|
1460
|
-
}
|
|
1461
|
-
}
|
|
1462
1657
|
function buildProxyBody(params, metadata) {
|
|
1463
1658
|
const modelValue = params.model ? modelToString(params.model).trim() : "";
|
|
1464
1659
|
const body = {
|
|
@@ -1468,7 +1663,6 @@ function buildProxyBody(params, metadata) {
|
|
|
1468
1663
|
body.model = modelValue;
|
|
1469
1664
|
}
|
|
1470
1665
|
if (typeof params.maxTokens === "number") body.max_tokens = params.maxTokens;
|
|
1471
|
-
if (params.provider) body.provider = providerToString(params.provider);
|
|
1472
1666
|
if (typeof params.temperature === "number")
|
|
1473
1667
|
body.temperature = params.temperature;
|
|
1474
1668
|
if (metadata && Object.keys(metadata).length > 0) body.metadata = metadata;
|
|
@@ -1476,6 +1670,7 @@ function buildProxyBody(params, metadata) {
|
|
|
1476
1670
|
if (params.stopSequences?.length) body.stop_sequences = params.stopSequences;
|
|
1477
1671
|
if (params.tools?.length) body.tools = normalizeTools(params.tools);
|
|
1478
1672
|
if (params.toolChoice) body.tool_choice = normalizeToolChoice(params.toolChoice);
|
|
1673
|
+
if (params.responseFormat) body.response_format = params.responseFormat;
|
|
1479
1674
|
return body;
|
|
1480
1675
|
}
|
|
1481
1676
|
function normalizeMessages(messages) {
|
|
@@ -1655,6 +1850,32 @@ var CustomersClient = class {
|
|
|
1655
1850
|
});
|
|
1656
1851
|
return response.customer;
|
|
1657
1852
|
}
|
|
1853
|
+
/**
|
|
1854
|
+
* Claim a customer by email, setting their external_id.
|
|
1855
|
+
* Used when a customer subscribes via Stripe Checkout (email only) and later
|
|
1856
|
+
* authenticates to the app, needing to link their identity.
|
|
1857
|
+
*
|
|
1858
|
+
* @throws {APIError} with status 404 if customer not found by email
|
|
1859
|
+
* @throws {APIError} with status 409 if customer already claimed or external_id in use
|
|
1860
|
+
*/
|
|
1861
|
+
async claim(request) {
|
|
1862
|
+
this.ensureSecretKey();
|
|
1863
|
+
if (!request.email?.trim()) {
|
|
1864
|
+
throw new ConfigError("email is required");
|
|
1865
|
+
}
|
|
1866
|
+
if (!isValidEmail(request.email)) {
|
|
1867
|
+
throw new ConfigError("invalid email format");
|
|
1868
|
+
}
|
|
1869
|
+
if (!request.external_id?.trim()) {
|
|
1870
|
+
throw new ConfigError("external_id is required");
|
|
1871
|
+
}
|
|
1872
|
+
const response = await this.http.json("/customers/claim", {
|
|
1873
|
+
method: "POST",
|
|
1874
|
+
body: request,
|
|
1875
|
+
apiKey: this.apiKey
|
|
1876
|
+
});
|
|
1877
|
+
return response.customer;
|
|
1878
|
+
}
|
|
1658
1879
|
/**
|
|
1659
1880
|
* Delete a customer by ID.
|
|
1660
1881
|
*/
|
|
@@ -2131,10 +2352,10 @@ export {
|
|
|
2131
2352
|
ErrorCodes,
|
|
2132
2353
|
ModelRelay,
|
|
2133
2354
|
ModelRelayError,
|
|
2134
|
-
|
|
2135
|
-
Providers,
|
|
2355
|
+
ResponseFormatTypes,
|
|
2136
2356
|
SDK_VERSION,
|
|
2137
2357
|
StopReasons,
|
|
2358
|
+
StructuredJSONStream,
|
|
2138
2359
|
TiersClient,
|
|
2139
2360
|
ToolArgsError,
|
|
2140
2361
|
ToolCallAccumulator,
|
|
@@ -2142,6 +2363,7 @@ export {
|
|
|
2142
2363
|
ToolRegistry,
|
|
2143
2364
|
ToolTypes,
|
|
2144
2365
|
TransportError,
|
|
2366
|
+
WebToolModes,
|
|
2145
2367
|
assistantMessageWithToolCalls,
|
|
2146
2368
|
createAccessTokenAuth,
|
|
2147
2369
|
createApiKeyAuth,
|
|
@@ -2166,12 +2388,10 @@ export {
|
|
|
2166
2388
|
mergeTrace,
|
|
2167
2389
|
modelToString,
|
|
2168
2390
|
normalizeModelId,
|
|
2169
|
-
normalizeProvider,
|
|
2170
2391
|
normalizeStopReason,
|
|
2171
2392
|
parseErrorResponse,
|
|
2172
2393
|
parseToolArgs,
|
|
2173
2394
|
parseToolArgsRaw,
|
|
2174
|
-
providerToString,
|
|
2175
2395
|
respondToToolCall,
|
|
2176
2396
|
stopReasonToString,
|
|
2177
2397
|
toolChoiceAuto,
|