@get-bb/plugin-sdk 0.4.34 → 0.4.35
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 +1 -1
- package/bundled-types/bb-plugin-sdk-host.d.ts +1 -1
- package/bundled-types/bb-plugin-sdk-internal-host-policy.d.ts +16 -8
- package/bundled-types/bb-plugin-sdk-testing.d.ts +1 -1
- package/bundled-types/bb-plugin-sdk.d.ts +20 -7
- package/dist/internal/host-policy.js +64 -1
- package/dist/testing/index.js +109 -31
- package/package.json +1 -1
|
@@ -35,7 +35,7 @@ interface PluginRpcError {
|
|
|
35
35
|
issues?: PluginRpcValidationIssue[];
|
|
36
36
|
}
|
|
37
37
|
/**
|
|
38
|
-
* The validator-neutral subset of Standard Schema v1 used by plugin
|
|
38
|
+
* The validator-neutral subset of Standard Schema v1 used by plugin contracts.
|
|
39
39
|
* Zod 4 schemas implement this interface directly; other validators can do
|
|
40
40
|
* the same without becoming part of BB's public protocol.
|
|
41
41
|
*/
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import { z } from 'zod';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* The validator-neutral subset of Standard Schema v1 used by plugin
|
|
11
|
+
* The validator-neutral subset of Standard Schema v1 used by plugin contracts.
|
|
12
12
|
* Zod 4 schemas implement this interface directly; other validators can do
|
|
13
13
|
* the same without becoming part of BB's public protocol.
|
|
14
14
|
*/
|
|
@@ -459,7 +459,7 @@ type JsonValue = string | number | boolean | null | JsonValue[] | {
|
|
|
459
459
|
};
|
|
460
460
|
|
|
461
461
|
/**
|
|
462
|
-
* The validator-neutral subset of Standard Schema v1 used by plugin
|
|
462
|
+
* The validator-neutral subset of Standard Schema v1 used by plugin contracts.
|
|
463
463
|
* Zod 4 schemas implement this interface directly; other validators can do
|
|
464
464
|
* the same without becoming part of BB's public protocol.
|
|
465
465
|
*/
|
|
@@ -491,11 +491,6 @@ interface PluginRpcMethodContract<InputSchema extends StandardSchemaV1 = Standar
|
|
|
491
491
|
readonly output: OutputSchema;
|
|
492
492
|
}
|
|
493
493
|
|
|
494
|
-
/**
|
|
495
|
-
* Declarative settings descriptors (`bb.settings.define`). Deliberately plain
|
|
496
|
-
* data — not zod — so the host can render settings forms and the CLI can
|
|
497
|
-
* parse values without executing plugin code.
|
|
498
|
-
*/
|
|
499
494
|
type PluginSettingDescriptor = {
|
|
500
495
|
type: "string";
|
|
501
496
|
label: string;
|
|
@@ -507,22 +502,30 @@ type PluginSettingDescriptor = {
|
|
|
507
502
|
* be multi-line.
|
|
508
503
|
*/
|
|
509
504
|
experimental_multiline?: boolean;
|
|
505
|
+
/** Synchronously validate without transforming a proposed value. */
|
|
506
|
+
experimental_schema?: StandardSchemaV1<string, string>;
|
|
510
507
|
default?: string;
|
|
511
508
|
} | {
|
|
512
509
|
type: "boolean";
|
|
513
510
|
label: string;
|
|
514
511
|
description?: string;
|
|
512
|
+
/** Synchronously validate without transforming a proposed value. */
|
|
513
|
+
experimental_schema?: StandardSchemaV1<boolean, boolean>;
|
|
515
514
|
default?: boolean;
|
|
516
515
|
} | {
|
|
517
516
|
type: "select";
|
|
518
517
|
label: string;
|
|
519
518
|
description?: string;
|
|
520
519
|
options: string[];
|
|
520
|
+
/** Synchronously validate without transforming a proposed value. */
|
|
521
|
+
experimental_schema?: StandardSchemaV1<string, string>;
|
|
521
522
|
default?: string;
|
|
522
523
|
} | {
|
|
523
524
|
type: "project";
|
|
524
525
|
label: string;
|
|
525
526
|
description?: string;
|
|
527
|
+
/** Synchronously validate without transforming a proposed value. */
|
|
528
|
+
experimental_schema?: StandardSchemaV1<string, string>;
|
|
526
529
|
default?: string;
|
|
527
530
|
};
|
|
528
531
|
type PluginSettingDescriptors = Record<string, PluginSettingDescriptor>;
|
|
@@ -1227,7 +1230,12 @@ declare function isStandardSchema(value: unknown): value is StandardSchemaV1;
|
|
|
1227
1230
|
declare function readRpcMethodContract(method: string, value: unknown): PluginRpcMethodContract;
|
|
1228
1231
|
/** Duck-typed zod detection: plugin sources may carry their own zod copy,
|
|
1229
1232
|
* so instanceof is useless — anything with safeParse is treated as zod. */
|
|
1230
|
-
|
|
1233
|
+
type ZodSchemaLike = {
|
|
1234
|
+
safeParse: z.ZodType["safeParse"];
|
|
1235
|
+
toJSONSchema?: z.ZodType["toJSONSchema"];
|
|
1236
|
+
};
|
|
1237
|
+
declare function isZodSchemaLike(value: unknown): value is ZodSchemaLike;
|
|
1238
|
+
declare function zodSchemaToJsonSchema(schema: ZodSchemaLike): unknown;
|
|
1231
1239
|
/**
|
|
1232
1240
|
* Reject recursive local references before a tool schema reaches a provider.
|
|
1233
1241
|
* Some providers reject the complete tool list when any one schema contains a
|
|
@@ -1312,5 +1320,5 @@ declare function storePluginHook<K extends PluginHookName>(records: {
|
|
|
1312
1320
|
/** The refusal a second handler for one hook from one plugin gets. */
|
|
1313
1321
|
declare function pluginHookAlreadyRegisteredMessage(hook: PluginHookName): string;
|
|
1314
1322
|
|
|
1315
|
-
export { AGENT_TOOL_NAME_PATTERN, BACKGROUND_NAME_PATTERN, CLI_COMMAND_NAME_PATTERN, KV_VALUE_MAX_BYTES, MENTION_PROVIDER_ID_PATTERN, PLUGIN_AGENT_DYNAMIC_INSTRUCTIONS_MAX_CHARS, PLUGIN_AGENT_SELECTION_MAX_IDS, PLUGIN_AGENT_STATIC_INSTRUCTIONS_MAX_CHARS, PLUGIN_AGENT_STATUS_LABEL_MAX_CHARS, PLUGIN_AGENT_TOOL_PARAMETERS_MAX_BYTES, PLUGIN_HTTP_METHODS, PLUGIN_MENTION_TRIGGER_VALUES, PLUGIN_PROVIDER_BRIDGE_OPTIONS_MAX_BYTES, PLUGIN_PROVIDER_COMPOSER_ACTION_VALUES, PLUGIN_PROVIDER_DISPLAY_NAME_MAX_CHARS, PLUGIN_PROVIDER_PERMISSION_MODE_VALUES, PLUGIN_PROVIDER_REASONING_LEVEL_VALUES, PROVIDER_ID_PATTERN, RESERVED_AGENT_TOOL_NAMES, RESERVED_BB_CLI_COMMANDS, RPC_METHOD_PATTERN, SERVER_DIRECT_AI_SERVICE_IDS, SETTING_KEY_PATTERN, adoptHttpRouteResponse, agentToolIconRefusalMessage, aiServiceAlreadyRegisteredMessage, assertAiServiceRegistrable, assertNoRecursiveJsonSchemaReferences, deriveValidatedProviderOptions, enforcePluginCliOutputLimit, isPluginMentionTrigger, isStandardSchema, isZodSchemaLike, normalizeMentionProviderTriggers, parsePluginAgentToolPresentation, pluginCliCollisionWarning, pluginHookAlreadyRegisteredMessage, providerAlreadyRegisteredMessage, providerIconRefusalMessage, providerWithoutBridgeMessage, readRpcMethodContract, registerSettingDescriptors, rejectStaleAgentToolFields, storePluginHook, summarizeParseIssues, undeclaredIconProblem, validatePluginAiServiceDeclaration, validatePluginProviderDeclaration, validateSettingsUpdate };
|
|
1323
|
+
export { AGENT_TOOL_NAME_PATTERN, BACKGROUND_NAME_PATTERN, CLI_COMMAND_NAME_PATTERN, KV_VALUE_MAX_BYTES, MENTION_PROVIDER_ID_PATTERN, PLUGIN_AGENT_DYNAMIC_INSTRUCTIONS_MAX_CHARS, PLUGIN_AGENT_SELECTION_MAX_IDS, PLUGIN_AGENT_STATIC_INSTRUCTIONS_MAX_CHARS, PLUGIN_AGENT_STATUS_LABEL_MAX_CHARS, PLUGIN_AGENT_TOOL_PARAMETERS_MAX_BYTES, PLUGIN_HTTP_METHODS, PLUGIN_MENTION_TRIGGER_VALUES, PLUGIN_PROVIDER_BRIDGE_OPTIONS_MAX_BYTES, PLUGIN_PROVIDER_COMPOSER_ACTION_VALUES, PLUGIN_PROVIDER_DISPLAY_NAME_MAX_CHARS, PLUGIN_PROVIDER_PERMISSION_MODE_VALUES, PLUGIN_PROVIDER_REASONING_LEVEL_VALUES, PROVIDER_ID_PATTERN, RESERVED_AGENT_TOOL_NAMES, RESERVED_BB_CLI_COMMANDS, RPC_METHOD_PATTERN, SERVER_DIRECT_AI_SERVICE_IDS, SETTING_KEY_PATTERN, adoptHttpRouteResponse, agentToolIconRefusalMessage, aiServiceAlreadyRegisteredMessage, assertAiServiceRegistrable, assertNoRecursiveJsonSchemaReferences, deriveValidatedProviderOptions, enforcePluginCliOutputLimit, isPluginMentionTrigger, isStandardSchema, isZodSchemaLike, normalizeMentionProviderTriggers, parsePluginAgentToolPresentation, pluginCliCollisionWarning, pluginHookAlreadyRegisteredMessage, providerAlreadyRegisteredMessage, providerIconRefusalMessage, providerWithoutBridgeMessage, readRpcMethodContract, registerSettingDescriptors, rejectStaleAgentToolFields, storePluginHook, summarizeParseIssues, undeclaredIconProblem, validatePluginAiServiceDeclaration, validatePluginProviderDeclaration, validateSettingsUpdate, zodSchemaToJsonSchema };
|
|
1316
1324
|
export type { AiServiceHostBinding, NormalizedPluginProviderDeclaration };
|
|
@@ -74,7 +74,7 @@ type JsonValue = string | number | boolean | null | JsonValue[] | {
|
|
|
74
74
|
};
|
|
75
75
|
|
|
76
76
|
/**
|
|
77
|
-
* The validator-neutral subset of Standard Schema v1 used by plugin
|
|
77
|
+
* The validator-neutral subset of Standard Schema v1 used by plugin contracts.
|
|
78
78
|
* Zod 4 schemas implement this interface directly; other validators can do
|
|
79
79
|
* the same without becoming part of BB's public protocol.
|
|
80
80
|
*/
|
|
@@ -44,6 +44,7 @@ interface ProviderNativeRootsInputLike {
|
|
|
44
44
|
|
|
45
45
|
declare const appSettingsSchema: z$1.ZodObject<{
|
|
46
46
|
defaultProviderId: z$1.ZodNullable<z$1.ZodString>;
|
|
47
|
+
managedBranchPrefix: z$1.ZodString;
|
|
47
48
|
providerOrder: z$1.ZodArray<z$1.ZodString>;
|
|
48
49
|
showKeyboardHints: z$1.ZodBoolean;
|
|
49
50
|
showUnhandledProviderEvents: z$1.ZodBoolean;
|
|
@@ -68,6 +69,7 @@ declare const appKeybindingOverridesSchema: z$1.ZodArray<z$1.ZodObject<{
|
|
|
68
69
|
"modelPicker.cycleReasoning": "modelPicker.cycleReasoning";
|
|
69
70
|
"modelPicker.cycleReasoningBackward": "modelPicker.cycleReasoningBackward";
|
|
70
71
|
"modelPicker.toggle": "modelPicker.toggle";
|
|
72
|
+
"notifications.open": "notifications.open";
|
|
71
73
|
"palette.open": "palette.open";
|
|
72
74
|
"pane.close": "pane.close";
|
|
73
75
|
"pane.focus.1": "pane.focus.1";
|
|
@@ -8324,6 +8326,7 @@ declare const systemConfigResponseSchema: z$1.ZodObject<{
|
|
|
8324
8326
|
"modelPicker.cycleReasoning": "modelPicker.cycleReasoning";
|
|
8325
8327
|
"modelPicker.cycleReasoningBackward": "modelPicker.cycleReasoningBackward";
|
|
8326
8328
|
"modelPicker.toggle": "modelPicker.toggle";
|
|
8329
|
+
"notifications.open": "notifications.open";
|
|
8327
8330
|
"palette.open": "palette.open";
|
|
8328
8331
|
"pane.close": "pane.close";
|
|
8329
8332
|
"pane.focus.1": "pane.focus.1";
|
|
@@ -8422,6 +8425,7 @@ declare const systemConfigResponseSchema: z$1.ZodObject<{
|
|
|
8422
8425
|
}, z$1.core.$strip>;
|
|
8423
8426
|
generalSettings: z$1.ZodObject<{
|
|
8424
8427
|
defaultProviderId: z$1.ZodNullable<z$1.ZodString>;
|
|
8428
|
+
managedBranchPrefix: z$1.ZodString;
|
|
8425
8429
|
providerOrder: z$1.ZodArray<z$1.ZodString>;
|
|
8426
8430
|
showKeyboardHints: z$1.ZodBoolean;
|
|
8427
8431
|
showUnhandledProviderEvents: z$1.ZodBoolean;
|
|
@@ -8445,6 +8449,7 @@ declare const systemConfigResponseSchema: z$1.ZodObject<{
|
|
|
8445
8449
|
"modelPicker.cycleReasoning": "modelPicker.cycleReasoning";
|
|
8446
8450
|
"modelPicker.cycleReasoningBackward": "modelPicker.cycleReasoningBackward";
|
|
8447
8451
|
"modelPicker.toggle": "modelPicker.toggle";
|
|
8452
|
+
"notifications.open": "notifications.open";
|
|
8448
8453
|
"palette.open": "palette.open";
|
|
8449
8454
|
"pane.close": "pane.close";
|
|
8450
8455
|
"pane.focus.1": "pane.focus.1";
|
|
@@ -8518,6 +8523,7 @@ declare const systemConfigResponseSchema: z$1.ZodObject<{
|
|
|
8518
8523
|
"modelPicker.cycleReasoning": "modelPicker.cycleReasoning";
|
|
8519
8524
|
"modelPicker.cycleReasoningBackward": "modelPicker.cycleReasoningBackward";
|
|
8520
8525
|
"modelPicker.toggle": "modelPicker.toggle";
|
|
8526
|
+
"notifications.open": "notifications.open";
|
|
8521
8527
|
"palette.open": "palette.open";
|
|
8522
8528
|
"pane.close": "pane.close";
|
|
8523
8529
|
"pane.focus.1": "pane.focus.1";
|
|
@@ -12418,7 +12424,7 @@ interface PluginRpcError {
|
|
|
12418
12424
|
issues?: PluginRpcValidationIssue[];
|
|
12419
12425
|
}
|
|
12420
12426
|
/**
|
|
12421
|
-
* The validator-neutral subset of Standard Schema v1 used by plugin
|
|
12427
|
+
* The validator-neutral subset of Standard Schema v1 used by plugin contracts.
|
|
12422
12428
|
* Zod 4 schemas implement this interface directly; other validators can do
|
|
12423
12429
|
* the same without becoming part of BB's public protocol.
|
|
12424
12430
|
*/
|
|
@@ -15977,11 +15983,6 @@ interface PluginLogger {
|
|
|
15977
15983
|
warn(message: string): void;
|
|
15978
15984
|
error(message: string): void;
|
|
15979
15985
|
}
|
|
15980
|
-
/**
|
|
15981
|
-
* Declarative settings descriptors (`bb.settings.define`). Deliberately plain
|
|
15982
|
-
* data — not zod — so the host can render settings forms and the CLI can
|
|
15983
|
-
* parse values without executing plugin code.
|
|
15984
|
-
*/
|
|
15985
15986
|
type PluginSettingDescriptor = {
|
|
15986
15987
|
type: "string";
|
|
15987
15988
|
label: string;
|
|
@@ -15993,22 +15994,30 @@ type PluginSettingDescriptor = {
|
|
|
15993
15994
|
* be multi-line.
|
|
15994
15995
|
*/
|
|
15995
15996
|
experimental_multiline?: boolean;
|
|
15997
|
+
/** Synchronously validate without transforming a proposed value. */
|
|
15998
|
+
experimental_schema?: StandardSchemaV1<string, string>;
|
|
15996
15999
|
default?: string;
|
|
15997
16000
|
} | {
|
|
15998
16001
|
type: "boolean";
|
|
15999
16002
|
label: string;
|
|
16000
16003
|
description?: string;
|
|
16004
|
+
/** Synchronously validate without transforming a proposed value. */
|
|
16005
|
+
experimental_schema?: StandardSchemaV1<boolean, boolean>;
|
|
16001
16006
|
default?: boolean;
|
|
16002
16007
|
} | {
|
|
16003
16008
|
type: "select";
|
|
16004
16009
|
label: string;
|
|
16005
16010
|
description?: string;
|
|
16006
16011
|
options: string[];
|
|
16012
|
+
/** Synchronously validate without transforming a proposed value. */
|
|
16013
|
+
experimental_schema?: StandardSchemaV1<string, string>;
|
|
16007
16014
|
default?: string;
|
|
16008
16015
|
} | {
|
|
16009
16016
|
type: "project";
|
|
16010
16017
|
label: string;
|
|
16011
16018
|
description?: string;
|
|
16019
|
+
/** Synchronously validate without transforming a proposed value. */
|
|
16020
|
+
experimental_schema?: StandardSchemaV1<string, string>;
|
|
16012
16021
|
default?: string;
|
|
16013
16022
|
};
|
|
16014
16023
|
type PluginSettingDescriptors = Record<string, PluginSettingDescriptor>;
|
|
@@ -16025,7 +16034,11 @@ type PluginSettingValueOf<D extends PluginSettingDescriptor> = D extends {
|
|
|
16025
16034
|
interface PluginSettingsHandle<Ds extends Record<string, PluginSettingDescriptor>> {
|
|
16026
16035
|
/** Load-safe: callable inside the factory. */
|
|
16027
16036
|
get(): Promise<PluginSettingsValues<Ds>>;
|
|
16028
|
-
/**
|
|
16037
|
+
/** Validate and persist this handle's fields; `null` unsets a stored value. */
|
|
16038
|
+
experimental_set(values: Partial<{
|
|
16039
|
+
[K in keyof Ds]: PluginSettingValueOf<Ds[K]> | null;
|
|
16040
|
+
}>): Promise<PluginSettingsValues<Ds>>;
|
|
16041
|
+
/** Fires after effective values change through any settings write. */
|
|
16029
16042
|
onChange(listener: (next: PluginSettingsValues<Ds>, prev: PluginSettingsValues<Ds>) => void): void;
|
|
16030
16043
|
}
|
|
16031
16044
|
interface PluginSettings {
|
|
@@ -293,12 +293,19 @@ var settingsBaseFields = {
|
|
|
293
293
|
label: z3.string().min(1),
|
|
294
294
|
description: z3.string().min(1).optional()
|
|
295
295
|
};
|
|
296
|
+
var stringSettingSchemaSchema = z3.custom(
|
|
297
|
+
(value) => isStandardSchema(value)
|
|
298
|
+
);
|
|
299
|
+
var booleanSettingSchemaSchema = z3.custom(
|
|
300
|
+
(value) => isStandardSchema(value)
|
|
301
|
+
);
|
|
296
302
|
var settingDescriptorSchema = z3.discriminatedUnion("type", [
|
|
297
303
|
z3.object({
|
|
298
304
|
type: z3.literal("string"),
|
|
299
305
|
...settingsBaseFields,
|
|
300
306
|
secret: z3.literal(true).optional(),
|
|
301
307
|
experimental_multiline: z3.boolean().optional(),
|
|
308
|
+
experimental_schema: stringSettingSchemaSchema.optional(),
|
|
302
309
|
default: z3.string().optional()
|
|
303
310
|
}).strict().refine(
|
|
304
311
|
(descriptor) => !(descriptor.secret === true && descriptor.experimental_multiline === true),
|
|
@@ -310,17 +317,20 @@ var settingDescriptorSchema = z3.discriminatedUnion("type", [
|
|
|
310
317
|
z3.object({
|
|
311
318
|
type: z3.literal("boolean"),
|
|
312
319
|
...settingsBaseFields,
|
|
320
|
+
experimental_schema: booleanSettingSchemaSchema.optional(),
|
|
313
321
|
default: z3.boolean().optional()
|
|
314
322
|
}).strict(),
|
|
315
323
|
z3.object({
|
|
316
324
|
type: z3.literal("select"),
|
|
317
325
|
...settingsBaseFields,
|
|
318
326
|
options: z3.array(z3.string().min(1)).min(1),
|
|
327
|
+
experimental_schema: stringSettingSchemaSchema.optional(),
|
|
319
328
|
default: z3.string().optional()
|
|
320
329
|
}).strict(),
|
|
321
330
|
z3.object({
|
|
322
331
|
type: z3.literal("project"),
|
|
323
332
|
...settingsBaseFields,
|
|
333
|
+
experimental_schema: stringSettingSchemaSchema.optional(),
|
|
324
334
|
default: z3.string().optional()
|
|
325
335
|
}).strict()
|
|
326
336
|
]);
|
|
@@ -349,11 +359,39 @@ function registerSettingDescriptors(target, added) {
|
|
|
349
359
|
`default for setting "${key}" must be one of its options`
|
|
350
360
|
);
|
|
351
361
|
}
|
|
362
|
+
if (descriptor.default !== void 0) {
|
|
363
|
+
const errors = validateSettingsUpdate(
|
|
364
|
+
{ [key]: descriptor },
|
|
365
|
+
{ [key]: descriptor.default }
|
|
366
|
+
);
|
|
367
|
+
if (errors.length > 0) {
|
|
368
|
+
throw new Error(`invalid default for setting "${key}": ${errors[0]}`);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
352
371
|
validated[key] = descriptor;
|
|
353
372
|
}
|
|
354
373
|
Object.assign(target, validated);
|
|
355
374
|
return validated;
|
|
356
375
|
}
|
|
376
|
+
function settingSchemaError(key, schema, value) {
|
|
377
|
+
if (schema === void 0) return null;
|
|
378
|
+
try {
|
|
379
|
+
const result = schema["~standard"].validate(value);
|
|
380
|
+
if (result instanceof Promise) {
|
|
381
|
+
return `schema for setting "${key}" must validate synchronously`;
|
|
382
|
+
}
|
|
383
|
+
if (result.issues !== void 0) {
|
|
384
|
+
return result.issues[0]?.message ?? `schema for setting "${key}" rejected the value`;
|
|
385
|
+
}
|
|
386
|
+
if (result.value !== value) {
|
|
387
|
+
return `schema for setting "${key}" must not transform its value`;
|
|
388
|
+
}
|
|
389
|
+
return null;
|
|
390
|
+
} catch (error) {
|
|
391
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
392
|
+
return `schema for setting "${key}" failed: ${detail}`;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
357
395
|
function validateSettingsUpdate(descriptors, values) {
|
|
358
396
|
const errors = [];
|
|
359
397
|
for (const [key, value] of Object.entries(values)) {
|
|
@@ -366,6 +404,15 @@ function validateSettingsUpdate(descriptors, values) {
|
|
|
366
404
|
if (descriptor.type === "boolean") {
|
|
367
405
|
if (typeof value !== "boolean") {
|
|
368
406
|
errors.push(`setting "${key}" expects a boolean`);
|
|
407
|
+
continue;
|
|
408
|
+
}
|
|
409
|
+
const validationError2 = settingSchemaError(
|
|
410
|
+
key,
|
|
411
|
+
descriptor.experimental_schema,
|
|
412
|
+
value
|
|
413
|
+
);
|
|
414
|
+
if (validationError2 !== null) {
|
|
415
|
+
errors.push(validationError2);
|
|
369
416
|
}
|
|
370
417
|
continue;
|
|
371
418
|
}
|
|
@@ -377,6 +424,15 @@ function validateSettingsUpdate(descriptors, values) {
|
|
|
377
424
|
errors.push(
|
|
378
425
|
`setting "${key}" must be one of: ${descriptor.options.join(", ")}`
|
|
379
426
|
);
|
|
427
|
+
continue;
|
|
428
|
+
}
|
|
429
|
+
const validationError = settingSchemaError(
|
|
430
|
+
key,
|
|
431
|
+
descriptor.experimental_schema,
|
|
432
|
+
value
|
|
433
|
+
);
|
|
434
|
+
if (validationError !== null) {
|
|
435
|
+
errors.push(validationError);
|
|
380
436
|
}
|
|
381
437
|
}
|
|
382
438
|
return errors;
|
|
@@ -1290,6 +1346,12 @@ function readRpcMethodContract(method, value) {
|
|
|
1290
1346
|
function isZodSchemaLike(value) {
|
|
1291
1347
|
return typeof value === "object" && value !== null && typeof value.safeParse === "function";
|
|
1292
1348
|
}
|
|
1349
|
+
function zodSchemaToJsonSchema(schema) {
|
|
1350
|
+
if (typeof schema.toJSONSchema === "function") {
|
|
1351
|
+
return schema.toJSONSchema({ io: "input" });
|
|
1352
|
+
}
|
|
1353
|
+
return z3.toJSONSchema(schema, { io: "input" });
|
|
1354
|
+
}
|
|
1293
1355
|
var SINGLE_SCHEMA_KEYWORDS = [
|
|
1294
1356
|
"additionalItems",
|
|
1295
1357
|
"additionalProperties",
|
|
@@ -1663,5 +1725,6 @@ export {
|
|
|
1663
1725
|
undeclaredIconProblem,
|
|
1664
1726
|
validatePluginAiServiceDeclaration,
|
|
1665
1727
|
validatePluginProviderDeclaration,
|
|
1666
|
-
validateSettingsUpdate
|
|
1728
|
+
validateSettingsUpdate,
|
|
1729
|
+
zodSchemaToJsonSchema
|
|
1667
1730
|
};
|
package/dist/testing/index.js
CHANGED
|
@@ -6,7 +6,6 @@ import { join } from "node:path";
|
|
|
6
6
|
import Database from "better-sqlite3";
|
|
7
7
|
import { CronExpressionParser } from "cron-parser";
|
|
8
8
|
import { Hono } from "hono";
|
|
9
|
-
import { z as z4 } from "zod";
|
|
10
9
|
|
|
11
10
|
// ../domain/src/plugin-interaction-limits.ts
|
|
12
11
|
var PLUGIN_INTERACTION_MAX_TITLE_LENGTH = 160;
|
|
@@ -307,12 +306,19 @@ var settingsBaseFields = {
|
|
|
307
306
|
label: z3.string().min(1),
|
|
308
307
|
description: z3.string().min(1).optional()
|
|
309
308
|
};
|
|
309
|
+
var stringSettingSchemaSchema = z3.custom(
|
|
310
|
+
(value) => isStandardSchema(value)
|
|
311
|
+
);
|
|
312
|
+
var booleanSettingSchemaSchema = z3.custom(
|
|
313
|
+
(value) => isStandardSchema(value)
|
|
314
|
+
);
|
|
310
315
|
var settingDescriptorSchema = z3.discriminatedUnion("type", [
|
|
311
316
|
z3.object({
|
|
312
317
|
type: z3.literal("string"),
|
|
313
318
|
...settingsBaseFields,
|
|
314
319
|
secret: z3.literal(true).optional(),
|
|
315
320
|
experimental_multiline: z3.boolean().optional(),
|
|
321
|
+
experimental_schema: stringSettingSchemaSchema.optional(),
|
|
316
322
|
default: z3.string().optional()
|
|
317
323
|
}).strict().refine(
|
|
318
324
|
(descriptor) => !(descriptor.secret === true && descriptor.experimental_multiline === true),
|
|
@@ -324,17 +330,20 @@ var settingDescriptorSchema = z3.discriminatedUnion("type", [
|
|
|
324
330
|
z3.object({
|
|
325
331
|
type: z3.literal("boolean"),
|
|
326
332
|
...settingsBaseFields,
|
|
333
|
+
experimental_schema: booleanSettingSchemaSchema.optional(),
|
|
327
334
|
default: z3.boolean().optional()
|
|
328
335
|
}).strict(),
|
|
329
336
|
z3.object({
|
|
330
337
|
type: z3.literal("select"),
|
|
331
338
|
...settingsBaseFields,
|
|
332
339
|
options: z3.array(z3.string().min(1)).min(1),
|
|
340
|
+
experimental_schema: stringSettingSchemaSchema.optional(),
|
|
333
341
|
default: z3.string().optional()
|
|
334
342
|
}).strict(),
|
|
335
343
|
z3.object({
|
|
336
344
|
type: z3.literal("project"),
|
|
337
345
|
...settingsBaseFields,
|
|
346
|
+
experimental_schema: stringSettingSchemaSchema.optional(),
|
|
338
347
|
default: z3.string().optional()
|
|
339
348
|
}).strict()
|
|
340
349
|
]);
|
|
@@ -363,11 +372,39 @@ function registerSettingDescriptors(target, added) {
|
|
|
363
372
|
`default for setting "${key}" must be one of its options`
|
|
364
373
|
);
|
|
365
374
|
}
|
|
375
|
+
if (descriptor.default !== void 0) {
|
|
376
|
+
const errors = validateSettingsUpdate(
|
|
377
|
+
{ [key]: descriptor },
|
|
378
|
+
{ [key]: descriptor.default }
|
|
379
|
+
);
|
|
380
|
+
if (errors.length > 0) {
|
|
381
|
+
throw new Error(`invalid default for setting "${key}": ${errors[0]}`);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
366
384
|
validated[key] = descriptor;
|
|
367
385
|
}
|
|
368
386
|
Object.assign(target, validated);
|
|
369
387
|
return validated;
|
|
370
388
|
}
|
|
389
|
+
function settingSchemaError(key, schema, value) {
|
|
390
|
+
if (schema === void 0) return null;
|
|
391
|
+
try {
|
|
392
|
+
const result = schema["~standard"].validate(value);
|
|
393
|
+
if (result instanceof Promise) {
|
|
394
|
+
return `schema for setting "${key}" must validate synchronously`;
|
|
395
|
+
}
|
|
396
|
+
if (result.issues !== void 0) {
|
|
397
|
+
return result.issues[0]?.message ?? `schema for setting "${key}" rejected the value`;
|
|
398
|
+
}
|
|
399
|
+
if (result.value !== value) {
|
|
400
|
+
return `schema for setting "${key}" must not transform its value`;
|
|
401
|
+
}
|
|
402
|
+
return null;
|
|
403
|
+
} catch (error) {
|
|
404
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
405
|
+
return `schema for setting "${key}" failed: ${detail}`;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
371
408
|
function validateSettingsUpdate(descriptors, values) {
|
|
372
409
|
const errors = [];
|
|
373
410
|
for (const [key, value] of Object.entries(values)) {
|
|
@@ -380,6 +417,15 @@ function validateSettingsUpdate(descriptors, values) {
|
|
|
380
417
|
if (descriptor.type === "boolean") {
|
|
381
418
|
if (typeof value !== "boolean") {
|
|
382
419
|
errors.push(`setting "${key}" expects a boolean`);
|
|
420
|
+
continue;
|
|
421
|
+
}
|
|
422
|
+
const validationError2 = settingSchemaError(
|
|
423
|
+
key,
|
|
424
|
+
descriptor.experimental_schema,
|
|
425
|
+
value
|
|
426
|
+
);
|
|
427
|
+
if (validationError2 !== null) {
|
|
428
|
+
errors.push(validationError2);
|
|
383
429
|
}
|
|
384
430
|
continue;
|
|
385
431
|
}
|
|
@@ -391,6 +437,15 @@ function validateSettingsUpdate(descriptors, values) {
|
|
|
391
437
|
errors.push(
|
|
392
438
|
`setting "${key}" must be one of: ${descriptor.options.join(", ")}`
|
|
393
439
|
);
|
|
440
|
+
continue;
|
|
441
|
+
}
|
|
442
|
+
const validationError = settingSchemaError(
|
|
443
|
+
key,
|
|
444
|
+
descriptor.experimental_schema,
|
|
445
|
+
value
|
|
446
|
+
);
|
|
447
|
+
if (validationError !== null) {
|
|
448
|
+
errors.push(validationError);
|
|
394
449
|
}
|
|
395
450
|
}
|
|
396
451
|
return errors;
|
|
@@ -1294,6 +1349,12 @@ function readRpcMethodContract(method, value) {
|
|
|
1294
1349
|
function isZodSchemaLike(value) {
|
|
1295
1350
|
return typeof value === "object" && value !== null && typeof value.safeParse === "function";
|
|
1296
1351
|
}
|
|
1352
|
+
function zodSchemaToJsonSchema(schema) {
|
|
1353
|
+
if (typeof schema.toJSONSchema === "function") {
|
|
1354
|
+
return schema.toJSONSchema({ io: "input" });
|
|
1355
|
+
}
|
|
1356
|
+
return z3.toJSONSchema(schema, { io: "input" });
|
|
1357
|
+
}
|
|
1297
1358
|
var SINGLE_SCHEMA_KEYWORDS = [
|
|
1298
1359
|
"additionalItems",
|
|
1299
1360
|
"additionalProperties",
|
|
@@ -2082,7 +2143,9 @@ function createFakePluginHostInternal(options, sharedState) {
|
|
|
2082
2143
|
"ALTER TABLE _bb_migrations ADD COLUMN statement_hash TEXT"
|
|
2083
2144
|
);
|
|
2084
2145
|
}
|
|
2085
|
-
const rows = database.prepare(
|
|
2146
|
+
const rows = database.prepare(
|
|
2147
|
+
"SELECT id, statement_hash FROM _bb_migrations ORDER BY id"
|
|
2148
|
+
).all();
|
|
2086
2149
|
const applied = /* @__PURE__ */ new Map();
|
|
2087
2150
|
for (const row of rows) applied.set(row.id, row.statement_hash);
|
|
2088
2151
|
const statementHashes = statements.map(migrationStatementHash);
|
|
@@ -2119,20 +2182,57 @@ function createFakePluginHostInternal(options, sharedState) {
|
|
|
2119
2182
|
const settingsDescriptors = {};
|
|
2120
2183
|
const settingsListeners = [];
|
|
2121
2184
|
const storedSettings = persistentState.storedSettings;
|
|
2185
|
+
async function setSettingsValues(values) {
|
|
2186
|
+
const errors = validateSettingsUpdate(settingsDescriptors, values);
|
|
2187
|
+
if (errors.length > 0) {
|
|
2188
|
+
throw new Error(errors.join("; "));
|
|
2189
|
+
}
|
|
2190
|
+
const prev = readSettingsValues(settingsDescriptors, storedSettings);
|
|
2191
|
+
for (const [key, value] of Object.entries(values)) {
|
|
2192
|
+
if (value === null) storedSettings.delete(key);
|
|
2193
|
+
else if (typeof value === "string" || typeof value === "boolean") {
|
|
2194
|
+
storedSettings.set(key, value);
|
|
2195
|
+
} else {
|
|
2196
|
+
throw new Error(`setting "${key}" has an unsupported value`);
|
|
2197
|
+
}
|
|
2198
|
+
}
|
|
2199
|
+
const next = readSettingsValues(settingsDescriptors, storedSettings);
|
|
2200
|
+
if (JSON.stringify(next) === JSON.stringify(prev)) return;
|
|
2201
|
+
for (const listener of settingsListeners) {
|
|
2202
|
+
try {
|
|
2203
|
+
listener(next, prev);
|
|
2204
|
+
} catch (error) {
|
|
2205
|
+
emitLog(
|
|
2206
|
+
"warn",
|
|
2207
|
+
`settings onChange listener failed: ${errorMessage(error)}`
|
|
2208
|
+
);
|
|
2209
|
+
}
|
|
2210
|
+
}
|
|
2211
|
+
}
|
|
2122
2212
|
const settings = {
|
|
2123
2213
|
define(descriptors) {
|
|
2124
2214
|
assertLive();
|
|
2125
|
-
registerSettingDescriptors(
|
|
2215
|
+
const validated = registerSettingDescriptors(
|
|
2126
2216
|
settingsDescriptors,
|
|
2127
2217
|
descriptors
|
|
2128
2218
|
);
|
|
2129
2219
|
return {
|
|
2130
2220
|
async get() {
|
|
2131
2221
|
assertLive();
|
|
2132
|
-
return readSettingsValues(
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
);
|
|
2222
|
+
return readSettingsValues(validated, storedSettings);
|
|
2223
|
+
},
|
|
2224
|
+
async experimental_set(values) {
|
|
2225
|
+
assertLive();
|
|
2226
|
+
const rawValues = {};
|
|
2227
|
+
for (const [key, value] of Object.entries(values)) {
|
|
2228
|
+
rawValues[key] = value;
|
|
2229
|
+
}
|
|
2230
|
+
const errors = validateSettingsUpdate(validated, rawValues);
|
|
2231
|
+
if (errors.length > 0) {
|
|
2232
|
+
throw new Error(errors.join("; "));
|
|
2233
|
+
}
|
|
2234
|
+
await setSettingsValues(rawValues);
|
|
2235
|
+
return readSettingsValues(validated, storedSettings);
|
|
2136
2236
|
},
|
|
2137
2237
|
onChange(listener) {
|
|
2138
2238
|
assertLive();
|
|
@@ -2462,9 +2562,7 @@ function createFakePluginHostInternal(options, sharedState) {
|
|
|
2462
2562
|
let parse;
|
|
2463
2563
|
if (isZodSchemaLike(parameters)) {
|
|
2464
2564
|
try {
|
|
2465
|
-
inputSchema =
|
|
2466
|
-
io: "input"
|
|
2467
|
-
});
|
|
2565
|
+
inputSchema = zodSchemaToJsonSchema(parameters);
|
|
2468
2566
|
} catch (error) {
|
|
2469
2567
|
throw new Error(
|
|
2470
2568
|
`tool "${name}" parameters look like a zod schema but could not be converted to JSON Schema (${errorMessage(error)}) \u2014 use zod 4, or pass a plain JSON-schema object`
|
|
@@ -2978,27 +3076,7 @@ function createFakePluginHostInternal(options, sharedState) {
|
|
|
2978
3076
|
pending.resolve({ outcome: "cancelled", reason: "user" });
|
|
2979
3077
|
},
|
|
2980
3078
|
async setSettings(values) {
|
|
2981
|
-
|
|
2982
|
-
if (errors.length > 0) {
|
|
2983
|
-
throw new Error(errors.join("; "));
|
|
2984
|
-
}
|
|
2985
|
-
const prev = readSettingsValues(settingsDescriptors, storedSettings);
|
|
2986
|
-
for (const [key, value] of Object.entries(values)) {
|
|
2987
|
-
if (value === null) storedSettings.delete(key);
|
|
2988
|
-
else storedSettings.set(key, value);
|
|
2989
|
-
}
|
|
2990
|
-
const next = readSettingsValues(settingsDescriptors, storedSettings);
|
|
2991
|
-
if (JSON.stringify(next) === JSON.stringify(prev)) return;
|
|
2992
|
-
for (const listener of settingsListeners) {
|
|
2993
|
-
try {
|
|
2994
|
-
listener(next, prev);
|
|
2995
|
-
} catch (error) {
|
|
2996
|
-
emitLog(
|
|
2997
|
-
"warn",
|
|
2998
|
-
`settings onChange listener failed: ${errorMessage(error)}`
|
|
2999
|
-
);
|
|
3000
|
-
}
|
|
3001
|
-
}
|
|
3079
|
+
await setSettingsValues(values);
|
|
3002
3080
|
},
|
|
3003
3081
|
async callRpc(method, input) {
|
|
3004
3082
|
const record = rpcHandlers.get(method);
|