@get-bb/plugin-sdk 0.4.10 → 0.4.12
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/bundled-types/bb-plugin-sdk-app.d.ts +131 -8
- package/bundled-types/bb-plugin-sdk-internal-host-policy.d.ts +165 -9
- package/bundled-types/bb-plugin-sdk-provider-bridge-testing.d.ts +3314 -0
- package/bundled-types/bb-plugin-sdk-provider-bridge.d.ts +1114 -371
- package/bundled-types/bb-plugin-sdk-testing-app.d.ts +6 -1
- package/bundled-types/bb-plugin-sdk.d.ts +1445 -277
- package/dist/app.js +2 -0
- package/dist/internal/host-policy.js +369 -10
- package/dist/provider-bridge-testing.js +5777 -0
- package/dist/provider-bridge.js +2697 -2083
- package/dist/testing/app.js +11 -1
- package/dist/testing/index.js +384 -27
- package/package.json +7 -1
package/dist/app.js
CHANGED
|
@@ -22,6 +22,7 @@ var experimental_useSidebarThreads = runtime.experimental_useSidebarThreads;
|
|
|
22
22
|
var experimental_useSidebarThreadActions = runtime.experimental_useSidebarThreadActions;
|
|
23
23
|
var experimental_useSidebarThreadPullRequest = runtime.experimental_useSidebarThreadPullRequest;
|
|
24
24
|
var experimental_useSidebarThreadSplit = runtime.experimental_useSidebarThreadSplit;
|
|
25
|
+
var experimental_useProviders = runtime.experimental_useProviders;
|
|
25
26
|
export {
|
|
26
27
|
Markdown,
|
|
27
28
|
ThreadChat,
|
|
@@ -33,6 +34,7 @@ export {
|
|
|
33
34
|
experimental_UrlLink,
|
|
34
35
|
experimental_useAppPanel,
|
|
35
36
|
experimental_useFixedTabTarget,
|
|
37
|
+
experimental_useProviders,
|
|
36
38
|
experimental_useSidebarThreadActions,
|
|
37
39
|
experimental_useSidebarThreadPullRequest,
|
|
38
40
|
experimental_useSidebarThreadSplit,
|
|
@@ -256,7 +256,7 @@ function validateProviderLiteralArray(args) {
|
|
|
256
256
|
}
|
|
257
257
|
return Object.freeze(normalized);
|
|
258
258
|
}
|
|
259
|
-
function normalizeProviderBridgeOptions(providerId, value) {
|
|
259
|
+
function normalizeProviderBridgeOptions(providerId, value, label = "experimental_bridgeOptions") {
|
|
260
260
|
const active = /* @__PURE__ */ new Set();
|
|
261
261
|
function visit(current, path) {
|
|
262
262
|
if (current === null || typeof current === "string" || typeof current === "boolean") {
|
|
@@ -265,14 +265,14 @@ function normalizeProviderBridgeOptions(providerId, value) {
|
|
|
265
265
|
if (typeof current === "number") {
|
|
266
266
|
if (!Number.isFinite(current)) {
|
|
267
267
|
throw new Error(
|
|
268
|
-
`provider "${providerId}"
|
|
268
|
+
`provider "${providerId}" ${label}${path} must be finite JSON`
|
|
269
269
|
);
|
|
270
270
|
}
|
|
271
271
|
return current;
|
|
272
272
|
}
|
|
273
273
|
if (typeof current !== "object") {
|
|
274
274
|
throw new Error(
|
|
275
|
-
`provider "${providerId}"
|
|
275
|
+
`provider "${providerId}" ${label}${path} must be JSON`
|
|
276
276
|
);
|
|
277
277
|
}
|
|
278
278
|
if (active.has(current)) {
|
|
@@ -292,7 +292,7 @@ function normalizeProviderBridgeOptions(providerId, value) {
|
|
|
292
292
|
const prototype = Object.getPrototypeOf(current);
|
|
293
293
|
if (prototype !== Object.prototype && prototype !== null) {
|
|
294
294
|
throw new Error(
|
|
295
|
-
`provider "${providerId}"
|
|
295
|
+
`provider "${providerId}" ${label}${path} must contain only plain JSON objects`
|
|
296
296
|
);
|
|
297
297
|
}
|
|
298
298
|
const normalized2 = Object.fromEntries(
|
|
@@ -310,16 +310,329 @@ function normalizeProviderBridgeOptions(providerId, value) {
|
|
|
310
310
|
const normalized = visit(value, "");
|
|
311
311
|
if (normalized === null || Array.isArray(normalized) || typeof normalized !== "object") {
|
|
312
312
|
throw new Error(
|
|
313
|
-
`provider "${providerId}"
|
|
313
|
+
`provider "${providerId}" ${label} must be an object`
|
|
314
314
|
);
|
|
315
315
|
}
|
|
316
316
|
if (Buffer.byteLength(JSON.stringify(normalized), "utf8") > PLUGIN_PROVIDER_BRIDGE_OPTIONS_MAX_BYTES) {
|
|
317
317
|
throw new Error(
|
|
318
|
-
`provider "${providerId}"
|
|
318
|
+
`provider "${providerId}" ${label} exceeds ${PLUGIN_PROVIDER_BRIDGE_OPTIONS_MAX_BYTES} bytes`
|
|
319
319
|
);
|
|
320
320
|
}
|
|
321
321
|
return normalized;
|
|
322
322
|
}
|
|
323
|
+
var PROVIDER_STRING_MAX_CHARS = 512;
|
|
324
|
+
var PROVIDER_EXTENSION_KIND_NAME_PATTERN = /^[a-z0-9-]+$/u;
|
|
325
|
+
var PROVIDER_EXTENSION_KINDS_MAX = 32;
|
|
326
|
+
function requireNonBlankString(args) {
|
|
327
|
+
const { providerId, field, value } = args;
|
|
328
|
+
if (typeof value !== "string" || value.trim().length === 0 || value.length > PROVIDER_STRING_MAX_CHARS) {
|
|
329
|
+
throw new Error(
|
|
330
|
+
`provider "${providerId}" ${field} must be a non-blank string of at most ${PROVIDER_STRING_MAX_CHARS} characters`
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
return value;
|
|
334
|
+
}
|
|
335
|
+
function validateProviderStrings(providerId, value) {
|
|
336
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
337
|
+
throw new Error(
|
|
338
|
+
`provider "${providerId}" experimental_strings must be an object`
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
const record = Object.fromEntries(
|
|
342
|
+
Object.entries(value)
|
|
343
|
+
);
|
|
344
|
+
const required = (field) => requireNonBlankString({
|
|
345
|
+
providerId,
|
|
346
|
+
field: `experimental_strings.${field}`,
|
|
347
|
+
value: record[field]
|
|
348
|
+
});
|
|
349
|
+
const optional = (field) => record[field] === void 0 ? void 0 : requireNonBlankString({
|
|
350
|
+
providerId,
|
|
351
|
+
field: `experimental_strings.${field}`,
|
|
352
|
+
value: record[field]
|
|
353
|
+
});
|
|
354
|
+
let iconTint;
|
|
355
|
+
if (record.iconTint !== void 0) {
|
|
356
|
+
const tint = record.iconTint;
|
|
357
|
+
if (typeof tint !== "object" || tint === null || Array.isArray(tint)) {
|
|
358
|
+
throw new Error(
|
|
359
|
+
`provider "${providerId}" experimental_strings.iconTint must be { light, dark }`
|
|
360
|
+
);
|
|
361
|
+
}
|
|
362
|
+
const tintRecord = Object.fromEntries(
|
|
363
|
+
Object.entries(tint)
|
|
364
|
+
);
|
|
365
|
+
iconTint = Object.freeze({
|
|
366
|
+
light: requireNonBlankString({
|
|
367
|
+
providerId,
|
|
368
|
+
field: "experimental_strings.iconTint.light",
|
|
369
|
+
value: tintRecord.light
|
|
370
|
+
}),
|
|
371
|
+
dark: requireNonBlankString({
|
|
372
|
+
providerId,
|
|
373
|
+
field: "experimental_strings.iconTint.dark",
|
|
374
|
+
value: tintRecord.dark
|
|
375
|
+
})
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
const brandPrefix = optional("brandPrefix");
|
|
379
|
+
const planModeCopy = optional("planModeCopy");
|
|
380
|
+
return Object.freeze({
|
|
381
|
+
signInHint: required("signInHint"),
|
|
382
|
+
expiredHint: required("expiredHint"),
|
|
383
|
+
installUrl: required("installUrl"),
|
|
384
|
+
...brandPrefix === void 0 ? {} : { brandPrefix },
|
|
385
|
+
...planModeCopy === void 0 ? {} : { planModeCopy },
|
|
386
|
+
...iconTint === void 0 ? {} : { iconTint }
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
function validateProviderOptionDescriptors(args) {
|
|
390
|
+
const { providerId, field, value } = args;
|
|
391
|
+
if (!Array.isArray(value) || value.length === 0) {
|
|
392
|
+
throw new Error(
|
|
393
|
+
`provider "${providerId}" ${field} must be a non-empty array of { id, label, description? }`
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
const seen = /* @__PURE__ */ new Set();
|
|
397
|
+
const normalized = value.map(
|
|
398
|
+
(entry, index) => {
|
|
399
|
+
if (typeof entry !== "object" || entry === null || Array.isArray(entry)) {
|
|
400
|
+
throw new Error(
|
|
401
|
+
`provider "${providerId}" ${field}[${index}] must be { id, label, description? }`
|
|
402
|
+
);
|
|
403
|
+
}
|
|
404
|
+
const record = Object.fromEntries(
|
|
405
|
+
Object.entries(entry)
|
|
406
|
+
);
|
|
407
|
+
const id = requireNonBlankString({
|
|
408
|
+
providerId,
|
|
409
|
+
field: `${field}[${index}].id`,
|
|
410
|
+
value: record.id
|
|
411
|
+
});
|
|
412
|
+
if (seen.has(id)) {
|
|
413
|
+
throw new Error(
|
|
414
|
+
`provider "${providerId}" ${field} id ${JSON.stringify(id)} is duplicated`
|
|
415
|
+
);
|
|
416
|
+
}
|
|
417
|
+
seen.add(id);
|
|
418
|
+
const label = requireNonBlankString({
|
|
419
|
+
providerId,
|
|
420
|
+
field: `${field}[${index}].label`,
|
|
421
|
+
value: record.label
|
|
422
|
+
});
|
|
423
|
+
const description = record.description === void 0 ? void 0 : requireNonBlankString({
|
|
424
|
+
providerId,
|
|
425
|
+
field: `${field}[${index}].description`,
|
|
426
|
+
value: record.description
|
|
427
|
+
});
|
|
428
|
+
return Object.freeze({
|
|
429
|
+
id,
|
|
430
|
+
label,
|
|
431
|
+
...description === void 0 ? {} : { description }
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
);
|
|
435
|
+
return Object.freeze(normalized);
|
|
436
|
+
}
|
|
437
|
+
function validateProviderExtensionKinds(providerId, value) {
|
|
438
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
439
|
+
throw new Error(
|
|
440
|
+
`provider "${providerId}" experimental_extensionKinds must be an object keyed by kind name`
|
|
441
|
+
);
|
|
442
|
+
}
|
|
443
|
+
const entries = Object.entries(value);
|
|
444
|
+
if (entries.length > PROVIDER_EXTENSION_KINDS_MAX) {
|
|
445
|
+
throw new Error(
|
|
446
|
+
`provider "${providerId}" experimental_extensionKinds declares more than ${PROVIDER_EXTENSION_KINDS_MAX} kinds`
|
|
447
|
+
);
|
|
448
|
+
}
|
|
449
|
+
const normalized = {};
|
|
450
|
+
for (const [name, declaration] of entries) {
|
|
451
|
+
if (!PROVIDER_EXTENSION_KIND_NAME_PATTERN.test(name)) {
|
|
452
|
+
throw new Error(
|
|
453
|
+
`provider "${providerId}" experimental_extensionKinds name ${JSON.stringify(name)} must match ${PROVIDER_EXTENSION_KIND_NAME_PATTERN}`
|
|
454
|
+
);
|
|
455
|
+
}
|
|
456
|
+
if (typeof declaration !== "object" || declaration === null || Array.isArray(declaration)) {
|
|
457
|
+
throw new Error(
|
|
458
|
+
`provider "${providerId}" experimental_extensionKinds.${name} must be { item?, state? }`
|
|
459
|
+
);
|
|
460
|
+
}
|
|
461
|
+
const item = Reflect.get(declaration, "item");
|
|
462
|
+
const state = Reflect.get(declaration, "state");
|
|
463
|
+
if (item === void 0 && state === void 0) {
|
|
464
|
+
throw new Error(
|
|
465
|
+
`provider "${providerId}" experimental_extensionKinds.${name} must declare an item schema, a state schema, or both`
|
|
466
|
+
);
|
|
467
|
+
}
|
|
468
|
+
if (item !== void 0 && !isStandardSchema(item)) {
|
|
469
|
+
throw new Error(
|
|
470
|
+
`provider "${providerId}" experimental_extensionKinds.${name}.item must be a Standard Schema v1 validator`
|
|
471
|
+
);
|
|
472
|
+
}
|
|
473
|
+
if (state !== void 0 && !isStandardSchema(state)) {
|
|
474
|
+
throw new Error(
|
|
475
|
+
`provider "${providerId}" experimental_extensionKinds.${name}.state must be a Standard Schema v1 validator`
|
|
476
|
+
);
|
|
477
|
+
}
|
|
478
|
+
normalized[name] = Object.freeze({
|
|
479
|
+
...item === void 0 ? {} : { item },
|
|
480
|
+
...state === void 0 ? {} : { state }
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
return Object.freeze(normalized);
|
|
484
|
+
}
|
|
485
|
+
var PROVIDER_FALLBACK_MODELS_MAX = 64;
|
|
486
|
+
var PROVIDER_ENV_PASSTHROUGH_MAX = 32;
|
|
487
|
+
var PROVIDER_ENV_NAME_PATTERN = /^[A-Z_][A-Z0-9_]*$/u;
|
|
488
|
+
function validateProviderEnvPassthrough(providerId, value) {
|
|
489
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
490
|
+
throw new Error(
|
|
491
|
+
`provider "${providerId}" experimental_env must be { passthrough: [...] }`
|
|
492
|
+
);
|
|
493
|
+
}
|
|
494
|
+
const passthrough = Reflect.get(value, "passthrough");
|
|
495
|
+
if (!Array.isArray(passthrough)) {
|
|
496
|
+
throw new Error(
|
|
497
|
+
`provider "${providerId}" experimental_env.passthrough must be an array of variable names`
|
|
498
|
+
);
|
|
499
|
+
}
|
|
500
|
+
if (passthrough.length > PROVIDER_ENV_PASSTHROUGH_MAX) {
|
|
501
|
+
throw new Error(
|
|
502
|
+
`provider "${providerId}" experimental_env.passthrough names more than ${PROVIDER_ENV_PASSTHROUGH_MAX} variables`
|
|
503
|
+
);
|
|
504
|
+
}
|
|
505
|
+
const seen = /* @__PURE__ */ new Set();
|
|
506
|
+
for (const name of passthrough) {
|
|
507
|
+
if (typeof name !== "string" || !PROVIDER_ENV_NAME_PATTERN.test(name)) {
|
|
508
|
+
throw new Error(
|
|
509
|
+
`provider "${providerId}" experimental_env.passthrough entries must match ${PROVIDER_ENV_NAME_PATTERN}`
|
|
510
|
+
);
|
|
511
|
+
}
|
|
512
|
+
if (seen.has(name)) {
|
|
513
|
+
throw new Error(
|
|
514
|
+
`provider "${providerId}" experimental_env.passthrough repeats ${JSON.stringify(name)}`
|
|
515
|
+
);
|
|
516
|
+
}
|
|
517
|
+
seen.add(name);
|
|
518
|
+
}
|
|
519
|
+
return Object.freeze([...seen]);
|
|
520
|
+
}
|
|
521
|
+
function validateProviderFallbackModels(providerId, value) {
|
|
522
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
523
|
+
throw new Error(
|
|
524
|
+
`provider "${providerId}" experimental_models must be { fallback: [...] }`
|
|
525
|
+
);
|
|
526
|
+
}
|
|
527
|
+
const fallback = Reflect.get(value, "fallback");
|
|
528
|
+
if (!Array.isArray(fallback)) {
|
|
529
|
+
throw new Error(
|
|
530
|
+
`provider "${providerId}" experimental_models.fallback must be an array`
|
|
531
|
+
);
|
|
532
|
+
}
|
|
533
|
+
if (fallback.length > PROVIDER_FALLBACK_MODELS_MAX) {
|
|
534
|
+
throw new Error(
|
|
535
|
+
`provider "${providerId}" experimental_models.fallback lists more than ${PROVIDER_FALLBACK_MODELS_MAX} models`
|
|
536
|
+
);
|
|
537
|
+
}
|
|
538
|
+
const seen = /* @__PURE__ */ new Set();
|
|
539
|
+
let defaults = 0;
|
|
540
|
+
const normalized = fallback.map((entry, index) => {
|
|
541
|
+
const field = `experimental_models.fallback[${index}]`;
|
|
542
|
+
if (typeof entry !== "object" || entry === null || Array.isArray(entry)) {
|
|
543
|
+
throw new Error(`provider "${providerId}" ${field} must be an object`);
|
|
544
|
+
}
|
|
545
|
+
const record = Object.fromEntries(
|
|
546
|
+
Object.entries(entry)
|
|
547
|
+
);
|
|
548
|
+
const id = requireNonBlankString({
|
|
549
|
+
providerId,
|
|
550
|
+
field: `${field}.id`,
|
|
551
|
+
value: record.id
|
|
552
|
+
});
|
|
553
|
+
if (seen.has(id)) {
|
|
554
|
+
throw new Error(
|
|
555
|
+
`provider "${providerId}" experimental_models.fallback id ${JSON.stringify(id)} is duplicated`
|
|
556
|
+
);
|
|
557
|
+
}
|
|
558
|
+
seen.add(id);
|
|
559
|
+
const displayName = requireNonBlankString({
|
|
560
|
+
providerId,
|
|
561
|
+
field: `${field}.displayName`,
|
|
562
|
+
value: record.displayName
|
|
563
|
+
});
|
|
564
|
+
const description = requireNonBlankString({
|
|
565
|
+
providerId,
|
|
566
|
+
field: `${field}.description`,
|
|
567
|
+
value: record.description
|
|
568
|
+
});
|
|
569
|
+
const efforts = record.supportedReasoningEfforts;
|
|
570
|
+
if (!Array.isArray(efforts) || efforts.length === 0) {
|
|
571
|
+
throw new Error(
|
|
572
|
+
`provider "${providerId}" ${field}.supportedReasoningEfforts must be a non-empty array`
|
|
573
|
+
);
|
|
574
|
+
}
|
|
575
|
+
const levels = /* @__PURE__ */ new Set();
|
|
576
|
+
const supportedReasoningEfforts = efforts.map(
|
|
577
|
+
(effort, effortIndex) => {
|
|
578
|
+
if (typeof effort !== "object" || effort === null || Array.isArray(effort)) {
|
|
579
|
+
throw new Error(
|
|
580
|
+
`provider "${providerId}" ${field}.supportedReasoningEfforts[${effortIndex}] must be { reasoningEffort, description }`
|
|
581
|
+
);
|
|
582
|
+
}
|
|
583
|
+
const reasoningEffort = Reflect.get(effort, "reasoningEffort");
|
|
584
|
+
if (typeof reasoningEffort !== "string" || !PLUGIN_PROVIDER_REASONING_LEVEL_VALUES.includes(
|
|
585
|
+
reasoningEffort
|
|
586
|
+
)) {
|
|
587
|
+
throw new Error(
|
|
588
|
+
`provider "${providerId}" ${field}.supportedReasoningEfforts[${effortIndex}].reasoningEffort must be one of ${PLUGIN_PROVIDER_REASONING_LEVEL_VALUES.join(", ")}`
|
|
589
|
+
);
|
|
590
|
+
}
|
|
591
|
+
const level = reasoningEffort;
|
|
592
|
+
if (levels.has(level)) {
|
|
593
|
+
throw new Error(
|
|
594
|
+
`provider "${providerId}" ${field}.supportedReasoningEfforts repeats ${JSON.stringify(level)}`
|
|
595
|
+
);
|
|
596
|
+
}
|
|
597
|
+
levels.add(level);
|
|
598
|
+
return Object.freeze({
|
|
599
|
+
reasoningEffort: level,
|
|
600
|
+
description: requireNonBlankString({
|
|
601
|
+
providerId,
|
|
602
|
+
field: `${field}.supportedReasoningEfforts[${effortIndex}].description`,
|
|
603
|
+
value: Reflect.get(effort, "description")
|
|
604
|
+
})
|
|
605
|
+
});
|
|
606
|
+
}
|
|
607
|
+
);
|
|
608
|
+
const defaultReasoningEffort = record.defaultReasoningEffort;
|
|
609
|
+
if (typeof defaultReasoningEffort !== "string" || !levels.has(defaultReasoningEffort)) {
|
|
610
|
+
throw new Error(
|
|
611
|
+
`provider "${providerId}" ${field}.defaultReasoningEffort must be one of its supportedReasoningEfforts`
|
|
612
|
+
);
|
|
613
|
+
}
|
|
614
|
+
if (typeof record.isDefault !== "boolean") {
|
|
615
|
+
throw new Error(
|
|
616
|
+
`provider "${providerId}" ${field}.isDefault must be a boolean`
|
|
617
|
+
);
|
|
618
|
+
}
|
|
619
|
+
if (record.isDefault) defaults += 1;
|
|
620
|
+
return Object.freeze({
|
|
621
|
+
id,
|
|
622
|
+
displayName,
|
|
623
|
+
description,
|
|
624
|
+
supportedReasoningEfforts: Object.freeze(supportedReasoningEfforts),
|
|
625
|
+
defaultReasoningEffort,
|
|
626
|
+
isDefault: record.isDefault
|
|
627
|
+
});
|
|
628
|
+
});
|
|
629
|
+
if (normalized.length > 0 && defaults !== 1) {
|
|
630
|
+
throw new Error(
|
|
631
|
+
`provider "${providerId}" experimental_models.fallback must mark exactly one model isDefault (found ${defaults})`
|
|
632
|
+
);
|
|
633
|
+
}
|
|
634
|
+
return Object.freeze(normalized);
|
|
635
|
+
}
|
|
323
636
|
function validatePluginProviderDeclaration(declaration) {
|
|
324
637
|
if (typeof declaration !== "object" || declaration === null) {
|
|
325
638
|
throw new Error("provider declaration must be an object");
|
|
@@ -330,6 +643,12 @@ function validatePluginProviderDeclaration(declaration) {
|
|
|
330
643
|
`invalid provider id ${JSON.stringify(id)} \u2014 use 2-64 lowercase letters, digits, and "-", starting with a letter or digit`
|
|
331
644
|
);
|
|
332
645
|
}
|
|
646
|
+
const family = declaration.experimental_family;
|
|
647
|
+
if (family !== void 0 && (typeof family !== "string" || !PROVIDER_ID_PATTERN.test(family))) {
|
|
648
|
+
throw new Error(
|
|
649
|
+
`provider "${id}" experimental_family must use the provider id grammar (2-64 lowercase letters, digits, and "-")`
|
|
650
|
+
);
|
|
651
|
+
}
|
|
333
652
|
const displayName = typeof declaration.displayName === "string" ? declaration.displayName.trim() : "";
|
|
334
653
|
if (displayName.length === 0 || displayName.length > PLUGIN_PROVIDER_DISPLAY_NAME_MAX_CHARS) {
|
|
335
654
|
throw new Error(
|
|
@@ -380,8 +699,7 @@ function validatePluginProviderDeclaration(declaration) {
|
|
|
380
699
|
"supportsNativeUserQuestion",
|
|
381
700
|
"supportsManualCompaction",
|
|
382
701
|
"supportsThreadArchive",
|
|
383
|
-
"supportsThreadRename"
|
|
384
|
-
"supportsWorkflows"
|
|
702
|
+
"supportsThreadRename"
|
|
385
703
|
];
|
|
386
704
|
for (const field of booleanCapabilityFields) {
|
|
387
705
|
if (typeof capabilities[field] !== "boolean") {
|
|
@@ -405,7 +723,6 @@ function validatePluginProviderDeclaration(declaration) {
|
|
|
405
723
|
supportsManualCompaction: capabilities.supportsManualCompaction,
|
|
406
724
|
supportsThreadArchive: capabilities.supportsThreadArchive,
|
|
407
725
|
supportsThreadRename: capabilities.supportsThreadRename,
|
|
408
|
-
supportsWorkflows: capabilities.supportsWorkflows,
|
|
409
726
|
permissionModes: validateProviderLiteralArray({
|
|
410
727
|
providerId: id,
|
|
411
728
|
field: "capabilities.permissionModes",
|
|
@@ -443,16 +760,57 @@ function validatePluginProviderDeclaration(declaration) {
|
|
|
443
760
|
`provider "${id}" experimental_visibility "installed" requires experimental_providerHealth`
|
|
444
761
|
);
|
|
445
762
|
}
|
|
763
|
+
const strings = declaration.experimental_strings === void 0 ? void 0 : validateProviderStrings(id, declaration.experimental_strings);
|
|
764
|
+
const serviceTiers = declaration.experimental_serviceTiers === void 0 ? void 0 : validateProviderOptionDescriptors({
|
|
765
|
+
providerId: id,
|
|
766
|
+
field: "experimental_serviceTiers",
|
|
767
|
+
value: declaration.experimental_serviceTiers
|
|
768
|
+
});
|
|
769
|
+
const reasoningLevels = declaration.experimental_reasoningLevels === void 0 ? void 0 : validateProviderOptionDescriptors({
|
|
770
|
+
providerId: id,
|
|
771
|
+
field: "experimental_reasoningLevels",
|
|
772
|
+
value: declaration.experimental_reasoningLevels
|
|
773
|
+
});
|
|
774
|
+
const extensionKinds = declaration.experimental_extensionKinds === void 0 ? void 0 : validateProviderExtensionKinds(
|
|
775
|
+
id,
|
|
776
|
+
declaration.experimental_extensionKinds
|
|
777
|
+
);
|
|
778
|
+
const fallbackModels = declaration.experimental_models === void 0 ? void 0 : validateProviderFallbackModels(id, declaration.experimental_models);
|
|
779
|
+
const envPassthrough = declaration.experimental_env === void 0 ? void 0 : validateProviderEnvPassthrough(id, declaration.experimental_env);
|
|
780
|
+
const deriveProviderOptions = declaration.experimental_deriveProviderOptions;
|
|
781
|
+
if (deriveProviderOptions !== void 0 && typeof deriveProviderOptions !== "function") {
|
|
782
|
+
throw new Error(
|
|
783
|
+
`provider "${id}" experimental_deriveProviderOptions must be a function (context) => providerOptions`
|
|
784
|
+
);
|
|
785
|
+
}
|
|
446
786
|
return Object.freeze({
|
|
447
787
|
id,
|
|
448
788
|
displayName,
|
|
789
|
+
...family === void 0 ? {} : { experimental_family: family },
|
|
449
790
|
...icon === void 0 ? {} : { icon },
|
|
450
791
|
...bridgeOptions === void 0 ? {} : { experimental_bridgeOptions: bridgeOptions },
|
|
451
792
|
experimental_visibility: visibility,
|
|
452
793
|
capabilities: normalizedCapabilities,
|
|
453
|
-
composerActions
|
|
794
|
+
composerActions,
|
|
795
|
+
...strings === void 0 ? {} : { experimental_strings: strings },
|
|
796
|
+
...serviceTiers === void 0 ? {} : { experimental_serviceTiers: serviceTiers },
|
|
797
|
+
...reasoningLevels === void 0 ? {} : { experimental_reasoningLevels: reasoningLevels },
|
|
798
|
+
...extensionKinds === void 0 ? {} : { experimental_extensionKinds: extensionKinds },
|
|
799
|
+
...fallbackModels === void 0 ? {} : { experimental_models: Object.freeze({ fallback: fallbackModels }) },
|
|
800
|
+
...envPassthrough === void 0 ? {} : { experimental_env: Object.freeze({ passthrough: envPassthrough }) },
|
|
801
|
+
...deriveProviderOptions === void 0 ? {} : { experimental_deriveProviderOptions: deriveProviderOptions }
|
|
454
802
|
});
|
|
455
803
|
}
|
|
804
|
+
function deriveValidatedProviderOptions(args) {
|
|
805
|
+
const hook = args.declaration.experimental_deriveProviderOptions;
|
|
806
|
+
if (hook === void 0) return Object.freeze({});
|
|
807
|
+
const result = hook(args.context);
|
|
808
|
+
return normalizeProviderBridgeOptions(
|
|
809
|
+
args.declaration.id,
|
|
810
|
+
result,
|
|
811
|
+
"experimental_deriveProviderOptions result"
|
|
812
|
+
);
|
|
813
|
+
}
|
|
456
814
|
function isStandardSchema(value) {
|
|
457
815
|
if (typeof value !== "object" || value === null) return false;
|
|
458
816
|
const standard = Reflect.get(value, "~standard");
|
|
@@ -723,6 +1081,7 @@ export {
|
|
|
723
1081
|
SETTING_KEY_PATTERN,
|
|
724
1082
|
adoptHttpRouteResponse,
|
|
725
1083
|
assertNoRecursiveJsonSchemaReferences,
|
|
1084
|
+
deriveValidatedProviderOptions,
|
|
726
1085
|
enforcePluginCliOutputLimit,
|
|
727
1086
|
isPluginMentionTrigger,
|
|
728
1087
|
isStandardSchema,
|