@xisui-pa/chatserver 1.0.0 → 1.1.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 +142 -39
- package/dist/index.js +1670 -569
- package/dist/index.js.map +1 -1
- package/dist/models/chatserver-models.js +116 -59
- package/dist/models/chatserver-models.js.map +1 -1
- package/package.json +1 -1
- package/schemas/config.schema.json +14 -13
- package/schemas/models.schema.json +2 -2
|
@@ -43,8 +43,8 @@ var __webpack_unused_export__;
|
|
|
43
43
|
|
|
44
44
|
// Keep matching config schema defaults and bounds in sync when changing them here.
|
|
45
45
|
__webpack_unused_export__ = ({ value: true });
|
|
46
|
-
|
|
47
|
-
__webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = exports.MAX_WEB_TEXT_CHARS = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = exports.MAX_SETUP_CHOICES = exports.MODEL_DISCOVERY_TIMEOUT_MS = __webpack_unused_export__ = exports.MODEL_RETRY_DELAY_MS = exports.MAX_MODEL_RETRIES = exports.DEFAULT_MODEL_TIMEOUT_MS =
|
|
46
|
+
exports.MAX_TIMER_MS = __webpack_unused_export__ = __webpack_unused_export__ = exports.MAX_TTS_INPUT_CHARS = exports.MAX_VOICE_PADDING_MS = exports.MIN_VOICE_PADDING_MS = exports.AUDIO_CLEANUP_RETRY_DELAY_MS = exports.AUDIO_CLEANUP_RETRIES = exports.AUDIO_CONVERSION_STDERR_CHARS = exports.AUDIO_CONVERSION_TIMEOUT_MS = exports.MAX_TRANSCRIPT_CHARS = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = exports.MAX_ENCODED_AUDIO_BYTES = exports.MAX_AUDIO_BYTES = __webpack_unused_export__ = exports.MAX_IMAGE_BYTES = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = void 0;
|
|
47
|
+
__webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = exports.MAX_WEB_TEXT_CHARS = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = exports.MAX_SETUP_CHOICES = exports.MODEL_DISCOVERY_TIMEOUT_MS = __webpack_unused_export__ = exports.MODEL_RETRY_DELAY_MS = exports.MAX_MODEL_RETRIES = exports.DEFAULT_MODEL_TIMEOUT_MS = void 0;
|
|
48
48
|
// Model input and conversation snapshots.
|
|
49
49
|
/**
|
|
50
50
|
* Budget calculations with the current values:
|
|
@@ -110,8 +110,8 @@ __webpack_unused_export__ = 20;
|
|
|
110
110
|
__webpack_unused_export__ = 50;
|
|
111
111
|
/** Maximum supporting source IDs per proposed memory note. */
|
|
112
112
|
__webpack_unused_export__ = 64;
|
|
113
|
-
/** Maximum characters in
|
|
114
|
-
__webpack_unused_export__ =
|
|
113
|
+
/** Maximum characters in memory, source, and cached image IDs; accommodates encoded WeChat IDs. */
|
|
114
|
+
__webpack_unused_export__ = 1_024;
|
|
115
115
|
// Images, voice input, and local audio conversion.
|
|
116
116
|
/** Default maximum generated image width in pixels. */
|
|
117
117
|
__webpack_unused_export__ = 1024;
|
|
@@ -155,17 +155,15 @@ exports.MIN_VOICE_PADDING_MS = 500;
|
|
|
155
155
|
exports.MAX_VOICE_PADDING_MS = 2_000;
|
|
156
156
|
/** Maximum characters submitted to a speech synthesis endpoint. */
|
|
157
157
|
exports.MAX_TTS_INPUT_CHARS = 4_096;
|
|
158
|
-
/** Maximum wait for
|
|
158
|
+
/** Maximum wait for one WeChat text send or media job to confirm delivery. */
|
|
159
159
|
__webpack_unused_export__ = 180_000;
|
|
160
|
-
/**
|
|
161
|
-
__webpack_unused_export__ = 1_000;
|
|
162
|
-
/** Deadline for a best-effort voice-job cancellation after failure or shutdown. */
|
|
160
|
+
/** Deadline for a best-effort send or job cancellation after failure or shutdown. */
|
|
163
161
|
__webpack_unused_export__ = 5_000;
|
|
164
162
|
// Model requests, pacing, and transport defaults.
|
|
165
|
-
/**
|
|
166
|
-
exports.MAX_TIMER_MS =
|
|
163
|
+
/** Maximum configured timeout or timer delay: one hour. */
|
|
164
|
+
exports.MAX_TIMER_MS = 60 * 60 * 1_000;
|
|
167
165
|
/** Default provider deadline for generation and transcription requests. */
|
|
168
|
-
exports.DEFAULT_MODEL_TIMEOUT_MS =
|
|
166
|
+
exports.DEFAULT_MODEL_TIMEOUT_MS = 300_000;
|
|
169
167
|
/** Retries after the initial attempt of a complete model generation. */
|
|
170
168
|
exports.MAX_MODEL_RETRIES = 3;
|
|
171
169
|
/** Delay between complete model-generation retries. */
|
|
@@ -184,18 +182,30 @@ __webpack_unused_export__ = 180_000;
|
|
|
184
182
|
__webpack_unused_export__ = 2;
|
|
185
183
|
/** Initial delay for pending-media retries; doubles on each retry. */
|
|
186
184
|
__webpack_unused_export__ = 30_000;
|
|
187
|
-
/** Default delay
|
|
188
|
-
__webpack_unused_export__ =
|
|
189
|
-
/** Default deadline for each WeChat REST request. */
|
|
185
|
+
/** Default base delay before reconnecting an interrupted WeChat event stream. */
|
|
186
|
+
__webpack_unused_export__ = 1_000;
|
|
187
|
+
/** Default deadline for each WeChat REST request and SSE connect/idle wait. */
|
|
190
188
|
__webpack_unused_export__ = 30_000;
|
|
191
|
-
/**
|
|
192
|
-
__webpack_unused_export__ = 20_000;
|
|
193
|
-
/** Maximum exponent used by WeChat polling failure backoff. */
|
|
194
|
-
__webpack_unused_export__ = 6;
|
|
195
|
-
/** Chat rows requested per WeChat API page. */
|
|
189
|
+
/** Maximum wait for a WeChat stream reader to acknowledge cancellation. */
|
|
196
190
|
__webpack_unused_export__ = 100;
|
|
197
|
-
/**
|
|
198
|
-
__webpack_unused_export__ =
|
|
191
|
+
/** Maximum exponent used by WeChat event-stream reconnect backoff. */
|
|
192
|
+
__webpack_unused_export__ = 6;
|
|
193
|
+
/** Maximum cached WeChat contact and group-member display names. */
|
|
194
|
+
__webpack_unused_export__ = 1_000;
|
|
195
|
+
/** Lifetime of a successfully resolved WeChat display name. */
|
|
196
|
+
__webpack_unused_export__ = 10 * 60_000;
|
|
197
|
+
/** Lifetime of a failed or empty WeChat display-name lookup. */
|
|
198
|
+
__webpack_unused_export__ = 60_000;
|
|
199
|
+
/** Largest signed 64-bit event cursor accepted from the WeChat daemon. */
|
|
200
|
+
__webpack_unused_export__ = 9223372036854775807n;
|
|
201
|
+
/** Maximum characters buffered for one unterminated SSE line. */
|
|
202
|
+
__webpack_unused_export__ = 1_048_576;
|
|
203
|
+
/** Maximum characters accepted in one SSE data payload. */
|
|
204
|
+
__webpack_unused_export__ = 1_048_576;
|
|
205
|
+
/** Maximum bytes read from a rejected SSE response body. */
|
|
206
|
+
__webpack_unused_export__ = 16_384;
|
|
207
|
+
/** Recent live message IDs retained for replay deduplication; cursors are the primary guard. */
|
|
208
|
+
__webpack_unused_export__ = 2_000;
|
|
199
209
|
/** Default interval between ignore-file reload checks; zero disables caching. */
|
|
200
210
|
__webpack_unused_export__ = 1_000;
|
|
201
211
|
// Tool execution and web content.
|
|
@@ -247,6 +257,7 @@ __webpack_unused_export__ = 100;
|
|
|
247
257
|
var __webpack_unused_export__;
|
|
248
258
|
|
|
249
259
|
__webpack_unused_export__ = ({ value: true });
|
|
260
|
+
__webpack_unused_export__ = audioExtension;
|
|
250
261
|
exports.audioFile = audioFile;
|
|
251
262
|
const limit_1 = __webpack_require__(9258);
|
|
252
263
|
const media_1 = __webpack_require__(2358);
|
|
@@ -255,12 +266,21 @@ const formats = {
|
|
|
255
266
|
wav: 'audio/wav', ogg: 'audio/ogg', flac: 'audio/flac',
|
|
256
267
|
m4a: 'audio/mp4', mp4: 'audio/mp4', webm: 'audio/webm'
|
|
257
268
|
};
|
|
269
|
+
/** Maps an upstream audio MIME type to the extension used for STT uploads. */
|
|
270
|
+
function audioExtension(mimeType) {
|
|
271
|
+
const type = mimeType.split(';')[0].trim().toLowerCase();
|
|
272
|
+
const extension = Object.keys(formats).find((key) => formats[key] === type);
|
|
273
|
+
if (extension === undefined) {
|
|
274
|
+
throw new media_1.MediaUnavailableError(`Unsupported voice MIME type "${mimeType}"; agent-wechat must provide decoded WAV or another supported audio format.`);
|
|
275
|
+
}
|
|
276
|
+
return extension;
|
|
277
|
+
}
|
|
258
278
|
/** Decodes supported upstream audio without writing files or attempting local conversion. */
|
|
259
279
|
function audioFile(data, format, id) {
|
|
260
280
|
const extension = format.toLowerCase();
|
|
261
281
|
const mimeType = formats[extension];
|
|
262
282
|
if (!Object.hasOwn(formats, extension)) {
|
|
263
|
-
throw new media_1.MediaUnavailableError(`Unsupported voice format "${format}"; agent-wechat must
|
|
283
|
+
throw new media_1.MediaUnavailableError(`Unsupported voice format "${format}"; agent-wechat must provide decoded WAV or another supported audio format.`);
|
|
264
284
|
}
|
|
265
285
|
if (!data || data.length > limit_1.MAX_ENCODED_AUDIO_BYTES || data.length % 4 !== 0 || !/^[A-Za-z0-9+/]+={0,2}$/.test(data)) {
|
|
266
286
|
throw new media_1.MediaUnavailableError(`Voice data must be valid base64 no larger than ${limit_1.MAX_AUDIO_BYTES / (1024 * 1024)} MiB.`);
|
|
@@ -1239,6 +1259,7 @@ const limit_1 = __webpack_require__(9258);
|
|
|
1239
1259
|
const node_fs_1 = __webpack_require__(3024);
|
|
1240
1260
|
const node_path_1 = __importDefault(__webpack_require__(6760));
|
|
1241
1261
|
const responses_client_1 = __webpack_require__(102);
|
|
1262
|
+
const type_guards_1 = __webpack_require__(3012);
|
|
1242
1263
|
/**
|
|
1243
1264
|
* Name of the file that holds model configurations inside the config folder.
|
|
1244
1265
|
*/
|
|
@@ -1259,28 +1280,22 @@ exports.ModelStoreError = ModelStoreError;
|
|
|
1259
1280
|
function getModelsPath(configDir) {
|
|
1260
1281
|
return node_path_1.default.join(configDir, exports.MODELS_FILE_NAME);
|
|
1261
1282
|
}
|
|
1262
|
-
/**
|
|
1263
|
-
* Returns true for plain JSON objects (not null, arrays, or primitives).
|
|
1264
|
-
*/
|
|
1265
|
-
function isPlainObject(value) {
|
|
1266
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
1267
|
-
}
|
|
1268
1283
|
/**
|
|
1269
1284
|
* Validates one model entry.
|
|
1270
1285
|
*/
|
|
1271
1286
|
function parseModelEntry(value, where, seen) {
|
|
1272
|
-
if (!
|
|
1287
|
+
if (!(0, type_guards_1.isRecord)(value)) {
|
|
1273
1288
|
throw new ModelStoreError(`${where} must be an object.`);
|
|
1274
1289
|
}
|
|
1275
|
-
if (
|
|
1290
|
+
if (!(0, type_guards_1.isString)(value.id) || value.id.trim() === '') {
|
|
1276
1291
|
throw new ModelStoreError(`${where}: "id" must be a non-empty string.`);
|
|
1277
1292
|
}
|
|
1278
1293
|
const id = value.id.trim();
|
|
1279
1294
|
const name = value.name ?? id;
|
|
1280
|
-
if (
|
|
1295
|
+
if (!(0, type_guards_1.isString)(name) || name.trim() === '') {
|
|
1281
1296
|
throw new ModelStoreError(`${where}: "name" must be a non-empty string.`);
|
|
1282
1297
|
}
|
|
1283
|
-
if (value.supportsImageToolResults !== undefined &&
|
|
1298
|
+
if (value.supportsImageToolResults !== undefined && !(0, type_guards_1.isBoolean)(value.supportsImageToolResults)) {
|
|
1284
1299
|
throw new ModelStoreError(`${where}: "supportsImageToolResults" must be a boolean.`);
|
|
1285
1300
|
}
|
|
1286
1301
|
const entry = {
|
|
@@ -1298,14 +1313,14 @@ function parseModelEntry(value, where, seen) {
|
|
|
1298
1313
|
*/
|
|
1299
1314
|
function parseProvider(value, index, modelsPath) {
|
|
1300
1315
|
const where = `${modelsPath}: providers[${index}]`;
|
|
1301
|
-
if (!
|
|
1316
|
+
if (!(0, type_guards_1.isRecord)(value)) {
|
|
1302
1317
|
throw new ModelStoreError(`${where} must be an object.`);
|
|
1303
1318
|
}
|
|
1304
|
-
if (
|
|
1319
|
+
if (!(0, type_guards_1.isString)(value.provider) || value.provider.trim() === '') {
|
|
1305
1320
|
throw new ModelStoreError(`${where}: "provider" must be a non-empty string.`);
|
|
1306
1321
|
}
|
|
1307
1322
|
const baseUrl = value.baseUrl;
|
|
1308
|
-
if (
|
|
1323
|
+
if (!(0, type_guards_1.isString)(baseUrl) || baseUrl.trim() === '') {
|
|
1309
1324
|
throw new ModelStoreError(`${where}: "baseUrl" must be a non-empty string.`);
|
|
1310
1325
|
}
|
|
1311
1326
|
if (!Array.isArray(value.models)) {
|
|
@@ -1348,10 +1363,10 @@ async function loadModels(configDir) {
|
|
|
1348
1363
|
catch (error) {
|
|
1349
1364
|
throw new ModelStoreError(`Invalid JSON in ${modelsPath}: ${error.message}`);
|
|
1350
1365
|
}
|
|
1351
|
-
if (!
|
|
1366
|
+
if (!(0, type_guards_1.isRecord)(parsed) || !Array.isArray(parsed.providers)) {
|
|
1352
1367
|
throw new ModelStoreError(`${modelsPath} must contain an object with a "providers" array.`);
|
|
1353
1368
|
}
|
|
1354
|
-
if (parsed.$schema !== undefined &&
|
|
1369
|
+
if (parsed.$schema !== undefined && !(0, type_guards_1.isString)(parsed.$schema)) {
|
|
1355
1370
|
throw new ModelStoreError(`${modelsPath}: "$schema" must be a string.`);
|
|
1356
1371
|
}
|
|
1357
1372
|
const seen = new Set();
|
|
@@ -1524,9 +1539,10 @@ __webpack_unused_export__ = extractOutputText;
|
|
|
1524
1539
|
__webpack_unused_export__ = extractCitations;
|
|
1525
1540
|
exports.createResponse = createResponse;
|
|
1526
1541
|
const limit_1 = __webpack_require__(9258);
|
|
1542
|
+
const type_guards_1 = __webpack_require__(3012);
|
|
1527
1543
|
/** Validates durations against Node's timer range, including programmatic callers. */
|
|
1528
1544
|
function resolveModelTimeoutMs(value = limit_1.DEFAULT_MODEL_TIMEOUT_MS) {
|
|
1529
|
-
if (
|
|
1545
|
+
if (!(0, type_guards_1.isNumber)(value) || !Number.isSafeInteger(value) || value < 1 || value > limit_1.MAX_TIMER_MS) {
|
|
1530
1546
|
throw new Error(`Model timeout must be an integer from 1 to ${limit_1.MAX_TIMER_MS} milliseconds.`);
|
|
1531
1547
|
}
|
|
1532
1548
|
return value;
|
|
@@ -1545,12 +1561,6 @@ class ResponsesApiError extends Error {
|
|
|
1545
1561
|
}
|
|
1546
1562
|
}
|
|
1547
1563
|
exports.ResponsesApiError = ResponsesApiError;
|
|
1548
|
-
/**
|
|
1549
|
-
* Returns true for plain JSON objects (not null, arrays, or primitives).
|
|
1550
|
-
*/
|
|
1551
|
-
function isRecord(value) {
|
|
1552
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
1553
|
-
}
|
|
1554
1564
|
/**
|
|
1555
1565
|
* Builds the endpoint used for Responses API calls.
|
|
1556
1566
|
*/
|
|
@@ -1564,10 +1574,10 @@ function responsesEndpoint(baseUrl) {
|
|
|
1564
1574
|
* back to a top-level `output_text` string for compatible servers that use it.
|
|
1565
1575
|
*/
|
|
1566
1576
|
function extractOutputText(payload) {
|
|
1567
|
-
if (!isRecord(payload)) {
|
|
1577
|
+
if (!(0, type_guards_1.isRecord)(payload)) {
|
|
1568
1578
|
return '';
|
|
1569
1579
|
}
|
|
1570
|
-
if (
|
|
1580
|
+
if ((0, type_guards_1.isString)(payload.output_text)) {
|
|
1571
1581
|
return payload.output_text.trim();
|
|
1572
1582
|
}
|
|
1573
1583
|
if (!Array.isArray(payload.output)) {
|
|
@@ -1575,11 +1585,11 @@ function extractOutputText(payload) {
|
|
|
1575
1585
|
}
|
|
1576
1586
|
const parts = [];
|
|
1577
1587
|
for (const item of payload.output) {
|
|
1578
|
-
if (!isRecord(item) || !Array.isArray(item.content)) {
|
|
1588
|
+
if (!(0, type_guards_1.isRecord)(item) || !Array.isArray(item.content)) {
|
|
1579
1589
|
continue;
|
|
1580
1590
|
}
|
|
1581
1591
|
for (const content of item.content) {
|
|
1582
|
-
if (isRecord(content) && content.type === 'output_text' &&
|
|
1592
|
+
if ((0, type_guards_1.isRecord)(content) && content.type === 'output_text' && (0, type_guards_1.isString)(content.text)) {
|
|
1583
1593
|
parts.push(content.text);
|
|
1584
1594
|
}
|
|
1585
1595
|
}
|
|
@@ -1588,20 +1598,20 @@ function extractOutputText(payload) {
|
|
|
1588
1598
|
}
|
|
1589
1599
|
/** Retains URL citations even when generated text uses provider-specific markers. */
|
|
1590
1600
|
function extractCitations(payload) {
|
|
1591
|
-
if (!isRecord(payload) || !Array.isArray(payload.output)) {
|
|
1601
|
+
if (!(0, type_guards_1.isRecord)(payload) || !Array.isArray(payload.output)) {
|
|
1592
1602
|
return [];
|
|
1593
1603
|
}
|
|
1594
1604
|
const urls = new Set();
|
|
1595
1605
|
for (const item of payload.output) {
|
|
1596
|
-
if (!isRecord(item) || item.type !== 'message' || !Array.isArray(item.content)) {
|
|
1606
|
+
if (!(0, type_guards_1.isRecord)(item) || item.type !== 'message' || !Array.isArray(item.content)) {
|
|
1597
1607
|
continue;
|
|
1598
1608
|
}
|
|
1599
1609
|
for (const content of item.content) {
|
|
1600
|
-
if (!isRecord(content) || content.type !== 'output_text' || !Array.isArray(content.annotations)) {
|
|
1610
|
+
if (!(0, type_guards_1.isRecord)(content) || content.type !== 'output_text' || !Array.isArray(content.annotations)) {
|
|
1601
1611
|
continue;
|
|
1602
1612
|
}
|
|
1603
1613
|
for (const annotation of content.annotations) {
|
|
1604
|
-
if (!isRecord(annotation) || annotation.type !== 'url_citation' ||
|
|
1614
|
+
if (!(0, type_guards_1.isRecord)(annotation) || annotation.type !== 'url_citation' || !(0, type_guards_1.isString)(annotation.url)) {
|
|
1605
1615
|
continue;
|
|
1606
1616
|
}
|
|
1607
1617
|
try {
|
|
@@ -1676,11 +1686,11 @@ async function createResponse(request) {
|
|
|
1676
1686
|
catch (error) {
|
|
1677
1687
|
throw new ResponsesApiError(`Response from ${url} was not valid JSON: ${error.message}`, response.status, text);
|
|
1678
1688
|
}
|
|
1679
|
-
if (isRecord(parsed) && ((parsed.error !== undefined && parsed.error !== null) || parsed.status === 'failed' || parsed.status === 'incomplete')) {
|
|
1689
|
+
if ((0, type_guards_1.isRecord)(parsed) && ((parsed.error !== undefined && parsed.error !== null) || parsed.status === 'failed' || parsed.status === 'incomplete')) {
|
|
1680
1690
|
throw new ResponsesApiError(`Response from ${url} did not complete successfully.`, response.status);
|
|
1681
1691
|
}
|
|
1682
1692
|
const result = { outputText: extractOutputText(parsed), citations: extractCitations(parsed), raw: parsed };
|
|
1683
|
-
if (isRecord(parsed) &&
|
|
1693
|
+
if ((0, type_guards_1.isRecord)(parsed) && (0, type_guards_1.isString)(parsed.id)) {
|
|
1684
1694
|
result.id = parsed.id;
|
|
1685
1695
|
}
|
|
1686
1696
|
return result;
|
|
@@ -1754,6 +1764,7 @@ exports.setupInteractive = setupInteractive;
|
|
|
1754
1764
|
exports.setupModelId = setupModelId;
|
|
1755
1765
|
const limit_1 = __webpack_require__(9258);
|
|
1756
1766
|
const cli_support_1 = __webpack_require__(8256);
|
|
1767
|
+
const type_guards_1 = __webpack_require__(3012);
|
|
1757
1768
|
/** Reads an optional nonempty, trimmed command-line value. */
|
|
1758
1769
|
function setupValue(cli, key, flag) {
|
|
1759
1770
|
const value = (0, cli_support_1.optionalValue)(cli, key)?.trim();
|
|
@@ -1864,10 +1875,10 @@ async function setupModelId(provider, apiKey) {
|
|
|
1864
1875
|
throw new Error(`HTTP ${response.status}`);
|
|
1865
1876
|
}
|
|
1866
1877
|
const body = await response.json();
|
|
1867
|
-
if (
|
|
1878
|
+
if (!(0, type_guards_1.isObject)(body) || !('data' in body) || !Array.isArray(body.data)) {
|
|
1868
1879
|
throw new Error('Unsupported model list');
|
|
1869
1880
|
}
|
|
1870
|
-
ids = [...new Set(body.data.flatMap((model) =>
|
|
1881
|
+
ids = [...new Set(body.data.flatMap((model) => (0, type_guards_1.isObject)(model) && 'id' in model && (0, type_guards_1.isString)(model.id) && model.id.trim()
|
|
1871
1882
|
? [model.id.trim()] : []))].sort();
|
|
1872
1883
|
}
|
|
1873
1884
|
catch {
|
|
@@ -2071,6 +2082,7 @@ const command_support_1 = __webpack_require__(2327);
|
|
|
2071
2082
|
const speech_client_1 = __webpack_require__(5314);
|
|
2072
2083
|
const voice_synthesizer_1 = __webpack_require__(7393);
|
|
2073
2084
|
const retry_1 = __webpack_require__(7718);
|
|
2085
|
+
const type_guards_1 = __webpack_require__(3012);
|
|
2074
2086
|
const DEFAULT_SPEECH_TEST_TEXT = 'Hello! This is a speech synthesis test.';
|
|
2075
2087
|
exports.TEST_TTS_HELP = `Usage: chatserver-models test-tts --provider <name> --name <name> [options]
|
|
2076
2088
|
|
|
@@ -2106,7 +2118,7 @@ function speechOptions(encoded) {
|
|
|
2106
2118
|
throw new cli_support_1.CliError('--options must contain a valid JSON object.');
|
|
2107
2119
|
}
|
|
2108
2120
|
}
|
|
2109
|
-
if (
|
|
2121
|
+
if (!(0, type_guards_1.isRecord)(value)) {
|
|
2110
2122
|
throw new cli_support_1.CliError('--options must contain a JSON object.');
|
|
2111
2123
|
}
|
|
2112
2124
|
for (const key of ['model', 'input', 'response_format', 'stream_format']) {
|
|
@@ -2264,6 +2276,7 @@ __webpack_unused_export__ = ({ value: true });
|
|
|
2264
2276
|
exports.createTranscription = createTranscription;
|
|
2265
2277
|
const limit_1 = __webpack_require__(9258);
|
|
2266
2278
|
const responses_client_1 = __webpack_require__(102);
|
|
2279
|
+
const type_guards_1 = __webpack_require__(3012);
|
|
2267
2280
|
/** Calls an OpenAI-compatible audio/transcriptions endpoint using native multipart upload. */
|
|
2268
2281
|
async function createTranscription(request) {
|
|
2269
2282
|
request.signal?.throwIfAborted();
|
|
@@ -2301,8 +2314,8 @@ async function createTranscription(request) {
|
|
|
2301
2314
|
}
|
|
2302
2315
|
throw new responses_client_1.ResponsesApiError('Transcription model returned invalid JSON.', response.status);
|
|
2303
2316
|
}
|
|
2304
|
-
if (
|
|
2305
|
-
!('text' in result) ||
|
|
2317
|
+
if (!(0, type_guards_1.isRecord)(result) ||
|
|
2318
|
+
!('text' in result) || !(0, type_guards_1.isString)(result.text) || result.text.length > limit_1.MAX_TRANSCRIPT_CHARS) {
|
|
2306
2319
|
throw new responses_client_1.ResponsesApiError(`Transcription model must return a text string of at most ${limit_1.MAX_TRANSCRIPT_CHARS} characters.`, response.status);
|
|
2307
2320
|
}
|
|
2308
2321
|
return result.text.trim();
|
|
@@ -2576,6 +2589,50 @@ class VoiceSynthesizer {
|
|
|
2576
2589
|
__webpack_unused_export__ = VoiceSynthesizer;
|
|
2577
2590
|
|
|
2578
2591
|
|
|
2592
|
+
/***/ },
|
|
2593
|
+
|
|
2594
|
+
/***/ 3012
|
|
2595
|
+
(__unused_webpack_module, exports) {
|
|
2596
|
+
|
|
2597
|
+
var __webpack_unused_export__;
|
|
2598
|
+
|
|
2599
|
+
/**
|
|
2600
|
+
* Shared runtime type guards for values that arrive as untrusted data, such as
|
|
2601
|
+
* parsed JSON, provider responses, and configuration files.
|
|
2602
|
+
*/
|
|
2603
|
+
__webpack_unused_export__ = ({ value: true });
|
|
2604
|
+
exports.isString = isString;
|
|
2605
|
+
exports.isNumber = isNumber;
|
|
2606
|
+
exports.isBoolean = isBoolean;
|
|
2607
|
+
exports.isObject = isObject;
|
|
2608
|
+
exports.isRecord = isRecord;
|
|
2609
|
+
__webpack_unused_export__ = isFunction;
|
|
2610
|
+
/** Returns true when `value` is a string. */
|
|
2611
|
+
function isString(value) {
|
|
2612
|
+
return typeof value === 'string';
|
|
2613
|
+
}
|
|
2614
|
+
/** Returns true when `value` is a number, including `NaN` and infinities. */
|
|
2615
|
+
function isNumber(value) {
|
|
2616
|
+
return typeof value === 'number';
|
|
2617
|
+
}
|
|
2618
|
+
/** Returns true when `value` is a boolean. */
|
|
2619
|
+
function isBoolean(value) {
|
|
2620
|
+
return typeof value === 'boolean';
|
|
2621
|
+
}
|
|
2622
|
+
/** Returns true for any non-null object, including arrays, dates, and maps. */
|
|
2623
|
+
function isObject(value) {
|
|
2624
|
+
return typeof value === 'object' && value !== null;
|
|
2625
|
+
}
|
|
2626
|
+
/** Returns true for non-null objects that are not arrays; functions are rejected. */
|
|
2627
|
+
function isRecord(value) {
|
|
2628
|
+
return isObject(value) && !Array.isArray(value);
|
|
2629
|
+
}
|
|
2630
|
+
/** Returns true for functions, typed as callable so callers need no assertions. */
|
|
2631
|
+
function isFunction(value) {
|
|
2632
|
+
return typeof value === 'function';
|
|
2633
|
+
}
|
|
2634
|
+
|
|
2635
|
+
|
|
2579
2636
|
/***/ },
|
|
2580
2637
|
|
|
2581
2638
|
/***/ 1421
|