@get-bb/plugin-sdk 0.4.47 → 0.4.50
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 +12 -0
- package/bundled-types/bb-plugin-sdk-app.d.ts +203 -28
- package/bundled-types/bb-plugin-sdk-environment-provider.d.ts +266 -0
- package/bundled-types/bb-plugin-sdk-host.d.ts +33 -2
- package/bundled-types/bb-plugin-sdk-internal-composer-customization-validation.d.ts +2 -1
- package/bundled-types/bb-plugin-sdk-internal-host-policy.d.ts +231 -8
- package/bundled-types/bb-plugin-sdk-internal-plugin-app-collector.d.ts +2 -1
- package/bundled-types/bb-plugin-sdk-provider-bridge-acp.d.ts +7 -0
- package/bundled-types/bb-plugin-sdk-provider-bridge-testing.d.ts +195 -1
- package/bundled-types/bb-plugin-sdk-provider-bridge.d.ts +202 -167
- package/bundled-types/bb-plugin-sdk-testing-app.d.ts +5 -1
- package/bundled-types/bb-plugin-sdk-testing.d.ts +308 -3
- package/bundled-types/bb-plugin-sdk.d.ts +1639 -572
- package/dist/app.js +6 -0
- package/dist/environment-provider.js +0 -0
- package/dist/host.js +734 -30
- package/dist/internal/composer-customization-validation.js +9 -0
- package/dist/internal/host-policy.js +233 -64
- package/dist/internal/plugin-app-collector.js +26 -0
- package/dist/provider-bridge-acp.js +46 -2
- package/dist/provider-bridge-testing.js +62 -1
- package/dist/provider-bridge.js +23 -1
- package/dist/testing/app.js +86 -1
- package/dist/testing/index.js +254 -72
- package/package.json +7 -1
|
@@ -40,6 +40,14 @@ function requireSlotId(kind, value) {
|
|
|
40
40
|
}
|
|
41
41
|
return value;
|
|
42
42
|
}
|
|
43
|
+
function requireEnvironmentProviderId(kind, value) {
|
|
44
|
+
if (typeof value !== "string" || !PLUGIN_SLOT_ID_PATTERN.test(value)) {
|
|
45
|
+
throw new Error(
|
|
46
|
+
`${kind}: "environmentProviderId" must match ${String(PLUGIN_SLOT_ID_PATTERN)}, got ${JSON.stringify(value)}`
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
return value;
|
|
50
|
+
}
|
|
43
51
|
function requireProviderId(kind, value) {
|
|
44
52
|
if (typeof value !== "string" || !PLUGIN_SLOT_ID_PATTERN.test(value)) {
|
|
45
53
|
throw new Error(
|
|
@@ -248,6 +256,7 @@ export {
|
|
|
248
256
|
collectComposerCustomization,
|
|
249
257
|
normalizePluginThreadRowStatus,
|
|
250
258
|
requireComponent,
|
|
259
|
+
requireEnvironmentProviderId,
|
|
251
260
|
requireMessageDirectiveId,
|
|
252
261
|
requireNonEmptyString,
|
|
253
262
|
requireOptionalString,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/internal/host-policy.ts
|
|
2
|
-
import { z as
|
|
2
|
+
import { z as z4 } from "zod";
|
|
3
3
|
|
|
4
4
|
// ../domain/src/plugin-icon.ts
|
|
5
5
|
function isPluginOwnedIconPath(icon) {
|
|
@@ -23,6 +23,7 @@ function parseNamespacedGlyph(glyph) {
|
|
|
23
23
|
|
|
24
24
|
// ../domain/src/plugin-cli.ts
|
|
25
25
|
var RESERVED_BB_CLI_COMMANDS = [
|
|
26
|
+
"browser",
|
|
26
27
|
"environment",
|
|
27
28
|
"file",
|
|
28
29
|
"guide",
|
|
@@ -69,37 +70,54 @@ function isRelativeProviderSkillRootPath(value) {
|
|
|
69
70
|
return !normalized.startsWith("/") && !/^[a-zA-Z]:\//u.test(normalized) && normalized.split("/").every((segment) => segment !== "" && segment !== "." && segment !== "..");
|
|
70
71
|
}
|
|
71
72
|
|
|
72
|
-
// ../domain/src/
|
|
73
|
+
// ../domain/src/json-value.ts
|
|
73
74
|
import { z as z2 } from "zod";
|
|
75
|
+
var jsonValueSchema = z2.lazy(
|
|
76
|
+
() => z2.union([
|
|
77
|
+
z2.string(),
|
|
78
|
+
z2.number(),
|
|
79
|
+
z2.boolean(),
|
|
80
|
+
z2.null(),
|
|
81
|
+
z2.array(jsonValueSchema),
|
|
82
|
+
z2.record(z2.string(), jsonValueSchema)
|
|
83
|
+
])
|
|
84
|
+
);
|
|
85
|
+
var jsonObjectSchema = z2.record(
|
|
86
|
+
z2.string(),
|
|
87
|
+
jsonValueSchema
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
// ../domain/src/native-roots.ts
|
|
91
|
+
import { z as z3 } from "zod";
|
|
74
92
|
var PROVIDER_NATIVE_ROOTS_MAX = 32;
|
|
75
93
|
var PROVIDER_NATIVE_ROOT_NAME_PREFIX_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,62}:$/u;
|
|
76
|
-
var nativeRootNamePrefixSchema =
|
|
94
|
+
var nativeRootNamePrefixSchema = z3.string().refine(
|
|
77
95
|
(value) => value === "" || PROVIDER_NATIVE_ROOT_NAME_PREFIX_PATTERN.test(value),
|
|
78
96
|
"A root name prefix is a plugin-name-like token ending in ':'"
|
|
79
97
|
);
|
|
80
|
-
var nativeRootManifestPathSchema =
|
|
98
|
+
var nativeRootManifestPathSchema = z3.string().min(1).refine(
|
|
81
99
|
isRelativeProviderSkillRootPath,
|
|
82
100
|
"A manifest marker is a relative path without dot segments"
|
|
83
101
|
);
|
|
84
|
-
var relativeNativeRootPathSchema =
|
|
102
|
+
var relativeNativeRootPathSchema = z3.string().min(1).refine(
|
|
85
103
|
isRelativeProviderSkillRootPath,
|
|
86
104
|
"Roots must be relative paths without dot segments"
|
|
87
105
|
);
|
|
88
|
-
var absoluteNativeRootPathSchema =
|
|
106
|
+
var absoluteNativeRootPathSchema = z3.string().min(1).refine(
|
|
89
107
|
isAbsoluteProviderSkillRootPath,
|
|
90
108
|
"Absolute roots must be absolute paths without dot segments"
|
|
91
109
|
);
|
|
92
|
-
var providerNativeRootInputSchema =
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
path:
|
|
110
|
+
var providerNativeRootInputSchema = z3.union([
|
|
111
|
+
z3.string().min(1),
|
|
112
|
+
z3.object({
|
|
113
|
+
path: z3.string().min(1),
|
|
96
114
|
/** Skills nest in subdirectories (the agent scans recursively). */
|
|
97
|
-
recursive:
|
|
115
|
+
recursive: z3.boolean().optional(),
|
|
98
116
|
/**
|
|
99
117
|
* Scan the same relative directory in every ancestor of the workspace
|
|
100
118
|
* up to the repository root (`project` roots only).
|
|
101
119
|
*/
|
|
102
|
-
ancestors:
|
|
120
|
+
ancestors: z3.boolean().optional(),
|
|
103
121
|
/**
|
|
104
122
|
* Prepended to every name under the root, a vendor plugin's
|
|
105
123
|
* `plugin-name:`; a prefixed root is listed as a plugin root.
|
|
@@ -114,14 +132,14 @@ var providerNativeRootInputSchema = z2.union([
|
|
|
114
132
|
skipIfManifest: nativeRootManifestPathSchema.optional()
|
|
115
133
|
}).strict()
|
|
116
134
|
]);
|
|
117
|
-
var providerNativeRootsInputSchema =
|
|
118
|
-
user:
|
|
119
|
-
project:
|
|
135
|
+
var providerNativeRootsInputSchema = z3.object({
|
|
136
|
+
user: z3.array(providerNativeRootInputSchema).optional(),
|
|
137
|
+
project: z3.array(providerNativeRootInputSchema).optional()
|
|
120
138
|
}).strict();
|
|
121
|
-
var providerNativeRootSchema =
|
|
122
|
-
path:
|
|
123
|
-
recursive:
|
|
124
|
-
ancestors:
|
|
139
|
+
var providerNativeRootSchema = z3.object({
|
|
140
|
+
path: z3.string().min(1),
|
|
141
|
+
recursive: z3.boolean(),
|
|
142
|
+
ancestors: z3.boolean(),
|
|
125
143
|
namePrefix: nativeRootNamePrefixSchema,
|
|
126
144
|
/** Absent: every skill-shaped directory under the root is a skill. */
|
|
127
145
|
skipIfManifest: nativeRootManifestPathSchema.optional()
|
|
@@ -130,7 +148,7 @@ function uniqueByPath(roots) {
|
|
|
130
148
|
return new Set(roots.map((root) => root.path)).size === roots.length;
|
|
131
149
|
}
|
|
132
150
|
function nativeRootSideSchema(side) {
|
|
133
|
-
return
|
|
151
|
+
return z3.array(
|
|
134
152
|
providerNativeRootSchema.extend({ path: relativeNativeRootPathSchema }).superRefine((root, context) => {
|
|
135
153
|
if (root.ancestors && side !== "project") {
|
|
136
154
|
context.addIssue({
|
|
@@ -141,7 +159,7 @@ function nativeRootSideSchema(side) {
|
|
|
141
159
|
})
|
|
142
160
|
).max(PROVIDER_NATIVE_ROOTS_MAX).refine(uniqueByPath, "Roots must not repeat a path");
|
|
143
161
|
}
|
|
144
|
-
var providerNativeRootsSchema =
|
|
162
|
+
var providerNativeRootsSchema = z3.object({
|
|
145
163
|
user: nativeRootSideSchema("user"),
|
|
146
164
|
project: nativeRootSideSchema("project")
|
|
147
165
|
}).strict();
|
|
@@ -167,19 +185,19 @@ function normalizeProviderNativeRoots(roots) {
|
|
|
167
185
|
project: (roots?.project ?? []).map(normalizeProviderNativeRoot)
|
|
168
186
|
};
|
|
169
187
|
}
|
|
170
|
-
var providerResolvedNativeRootShapeSchema =
|
|
188
|
+
var providerResolvedNativeRootShapeSchema = z3.enum([
|
|
171
189
|
"skills",
|
|
172
190
|
"skill",
|
|
173
191
|
"skill-file",
|
|
174
192
|
"commands",
|
|
175
193
|
"command-file"
|
|
176
194
|
]);
|
|
177
|
-
var resolvedNativeRootFieldsSchema =
|
|
195
|
+
var resolvedNativeRootFieldsSchema = z3.object({
|
|
178
196
|
path: absoluteNativeRootPathSchema,
|
|
179
|
-
origin:
|
|
180
|
-
recursive:
|
|
197
|
+
origin: z3.enum(["user", "project"]),
|
|
198
|
+
recursive: z3.boolean(),
|
|
181
199
|
/** Only with origin `project`, for a path inside the workspace. */
|
|
182
|
-
ancestors:
|
|
200
|
+
ancestors: z3.boolean(),
|
|
183
201
|
namePrefix: nativeRootNamePrefixSchema,
|
|
184
202
|
shape: providerResolvedNativeRootShapeSchema,
|
|
185
203
|
/**
|
|
@@ -187,7 +205,7 @@ var resolvedNativeRootFieldsSchema = z2.object({
|
|
|
187
205
|
* none. A vendor plugin's root SKILL.md takes the plugin's name; absent
|
|
188
206
|
* means the parent directory's name.
|
|
189
207
|
*/
|
|
190
|
-
fallbackName:
|
|
208
|
+
fallbackName: z3.string().min(1).optional(),
|
|
191
209
|
/**
|
|
192
210
|
* `skills` only: a file, relative to a skill directory under this root,
|
|
193
211
|
* that marks the directory as a vendor plugin rather than a skill; the
|
|
@@ -231,14 +249,14 @@ var resolvedCommandShapes = /* @__PURE__ */ new Set([
|
|
|
231
249
|
"command-file"
|
|
232
250
|
]);
|
|
233
251
|
var PROVIDER_RESOLVED_NATIVE_ROOTS_MAX = 256;
|
|
234
|
-
var providerResolvedNativeRootsSchema =
|
|
235
|
-
skills:
|
|
252
|
+
var providerResolvedNativeRootsSchema = z3.object({
|
|
253
|
+
skills: z3.array(
|
|
236
254
|
providerResolvedNativeRootSchema.refine(
|
|
237
255
|
(root) => resolvedSkillShapes.has(root.shape),
|
|
238
256
|
"A skills root needs a skill shape"
|
|
239
257
|
)
|
|
240
258
|
).max(PROVIDER_RESOLVED_NATIVE_ROOTS_MAX),
|
|
241
|
-
commands:
|
|
259
|
+
commands: z3.array(
|
|
242
260
|
providerResolvedNativeRootSchema.refine(
|
|
243
261
|
(root) => resolvedCommandShapes.has(root.shape),
|
|
244
262
|
"A commands root needs a command shape"
|
|
@@ -249,7 +267,7 @@ var EMPTY_PROVIDER_RESOLVED_NATIVE_ROOTS = Object.freeze({
|
|
|
249
267
|
skills: Object.freeze([]),
|
|
250
268
|
commands: Object.freeze([])
|
|
251
269
|
});
|
|
252
|
-
var providerNativeRootSetSchema =
|
|
270
|
+
var providerNativeRootSetSchema = z3.object({
|
|
253
271
|
skills: providerNativeRootsSchema,
|
|
254
272
|
commands: providerNativeRootsSchema,
|
|
255
273
|
resolved: providerResolvedNativeRootsSchema
|
|
@@ -282,16 +300,16 @@ var CLI_COMMAND_NAME_PATTERN = /^[a-z0-9-]+$/;
|
|
|
282
300
|
var AGENT_TOOL_NAME_PATTERN = /^[a-zA-Z0-9_-]+$/;
|
|
283
301
|
var PLUGIN_PROVIDER_ENV_NAME_PATTERN = /^[A-Z_][A-Z0-9_]*$/;
|
|
284
302
|
var PLUGIN_PROVIDER_ENV_MAX_ENTRIES = 32;
|
|
285
|
-
var pluginProviderEnvEntrySchema =
|
|
286
|
-
name:
|
|
287
|
-
value:
|
|
288
|
-
|
|
289
|
-
|
|
303
|
+
var pluginProviderEnvEntrySchema = z4.object({
|
|
304
|
+
name: z4.string().regex(PLUGIN_PROVIDER_ENV_NAME_PATTERN),
|
|
305
|
+
value: z4.union([
|
|
306
|
+
z4.string(),
|
|
307
|
+
z4.object({ serverPath: z4.string().startsWith("/") }).strict()
|
|
290
308
|
]),
|
|
291
|
-
reason:
|
|
292
|
-
secret:
|
|
309
|
+
reason: z4.string(),
|
|
310
|
+
secret: z4.boolean()
|
|
293
311
|
}).strict();
|
|
294
|
-
var pluginProviderEnvEntriesSchema =
|
|
312
|
+
var pluginProviderEnvEntriesSchema = z4.array(pluginProviderEnvEntrySchema).max(PLUGIN_PROVIDER_ENV_MAX_ENTRIES).superRefine((entries, context) => {
|
|
295
313
|
const names = /* @__PURE__ */ new Set();
|
|
296
314
|
for (let index = 0; index < entries.length; index += 1) {
|
|
297
315
|
const name = entries[index]?.name;
|
|
@@ -326,26 +344,26 @@ var PROVIDER_ID_PATTERN = /^[a-z0-9][a-z0-9-]{1,63}$/;
|
|
|
326
344
|
var PLUGIN_PROVIDER_BRIDGE_OPTIONS_MAX_BYTES = 64 * 1024;
|
|
327
345
|
var SETTING_KEY_PATTERN = /^[a-zA-Z0-9_-]+$/;
|
|
328
346
|
var settingsBaseFields = {
|
|
329
|
-
label:
|
|
330
|
-
description:
|
|
347
|
+
label: z4.string().min(1),
|
|
348
|
+
description: z4.string().min(1).optional()
|
|
331
349
|
};
|
|
332
|
-
var stringSettingSchemaSchema =
|
|
350
|
+
var stringSettingSchemaSchema = z4.custom(
|
|
333
351
|
(value) => isStandardSchema(value)
|
|
334
352
|
);
|
|
335
|
-
var booleanSettingSchemaSchema =
|
|
353
|
+
var booleanSettingSchemaSchema = z4.custom(
|
|
336
354
|
(value) => isStandardSchema(value)
|
|
337
355
|
);
|
|
338
|
-
var numberSettingSchemaSchema =
|
|
356
|
+
var numberSettingSchemaSchema = z4.custom(
|
|
339
357
|
(value) => isStandardSchema(value)
|
|
340
358
|
);
|
|
341
|
-
var settingDescriptorSchema =
|
|
342
|
-
|
|
343
|
-
type:
|
|
359
|
+
var settingDescriptorSchema = z4.discriminatedUnion("type", [
|
|
360
|
+
z4.object({
|
|
361
|
+
type: z4.literal("string"),
|
|
344
362
|
...settingsBaseFields,
|
|
345
|
-
secret:
|
|
346
|
-
experimental_multiline:
|
|
363
|
+
secret: z4.literal(true).optional(),
|
|
364
|
+
experimental_multiline: z4.boolean().optional(),
|
|
347
365
|
experimental_schema: stringSettingSchemaSchema.optional(),
|
|
348
|
-
default:
|
|
366
|
+
default: z4.string().optional()
|
|
349
367
|
}).strict().refine(
|
|
350
368
|
(descriptor) => !(descriptor.secret === true && descriptor.experimental_multiline === true),
|
|
351
369
|
{
|
|
@@ -353,30 +371,30 @@ var settingDescriptorSchema = z3.discriminatedUnion("type", [
|
|
|
353
371
|
path: ["experimental_multiline"]
|
|
354
372
|
}
|
|
355
373
|
),
|
|
356
|
-
|
|
357
|
-
type:
|
|
374
|
+
z4.object({
|
|
375
|
+
type: z4.literal("boolean"),
|
|
358
376
|
...settingsBaseFields,
|
|
359
377
|
experimental_schema: booleanSettingSchemaSchema.optional(),
|
|
360
|
-
default:
|
|
378
|
+
default: z4.boolean().optional()
|
|
361
379
|
}).strict(),
|
|
362
|
-
|
|
363
|
-
type:
|
|
380
|
+
z4.object({
|
|
381
|
+
type: z4.literal("number"),
|
|
364
382
|
...settingsBaseFields,
|
|
365
383
|
experimental_schema: numberSettingSchemaSchema.optional(),
|
|
366
|
-
default:
|
|
384
|
+
default: z4.number().finite().optional()
|
|
367
385
|
}).strict(),
|
|
368
|
-
|
|
369
|
-
type:
|
|
386
|
+
z4.object({
|
|
387
|
+
type: z4.literal("select"),
|
|
370
388
|
...settingsBaseFields,
|
|
371
|
-
options:
|
|
389
|
+
options: z4.array(z4.string().min(1)).min(1),
|
|
372
390
|
experimental_schema: stringSettingSchemaSchema.optional(),
|
|
373
|
-
default:
|
|
391
|
+
default: z4.string().optional()
|
|
374
392
|
}).strict(),
|
|
375
|
-
|
|
376
|
-
type:
|
|
393
|
+
z4.object({
|
|
394
|
+
type: z4.literal("project"),
|
|
377
395
|
...settingsBaseFields,
|
|
378
396
|
experimental_schema: stringSettingSchemaSchema.optional(),
|
|
379
|
-
default:
|
|
397
|
+
default: z4.string().optional()
|
|
380
398
|
}).strict()
|
|
381
399
|
]);
|
|
382
400
|
function registerSettingDescriptors(target, added) {
|
|
@@ -1406,11 +1424,21 @@ function readRpcMethodContract(method, value) {
|
|
|
1406
1424
|
function isZodSchemaLike(value) {
|
|
1407
1425
|
return typeof value === "object" && value !== null && typeof value.safeParse === "function";
|
|
1408
1426
|
}
|
|
1427
|
+
function standardSchemaToJsonSchema(schema) {
|
|
1428
|
+
if (isZodSchemaLike(schema)) {
|
|
1429
|
+
return zodSchemaToJsonSchema(schema);
|
|
1430
|
+
}
|
|
1431
|
+
const convertible = schema;
|
|
1432
|
+
if (typeof convertible.toJSONSchema === "function") {
|
|
1433
|
+
return convertible.toJSONSchema();
|
|
1434
|
+
}
|
|
1435
|
+
throw new Error("the validator exposes no JSON Schema conversion");
|
|
1436
|
+
}
|
|
1409
1437
|
function zodSchemaToJsonSchema(schema) {
|
|
1410
1438
|
if (typeof schema.toJSONSchema === "function") {
|
|
1411
1439
|
return schema.toJSONSchema({ io: "input" });
|
|
1412
1440
|
}
|
|
1413
|
-
return
|
|
1441
|
+
return z4.toJSONSchema(schema, { io: "input" });
|
|
1414
1442
|
}
|
|
1415
1443
|
var SINGLE_SCHEMA_KEYWORDS = [
|
|
1416
1444
|
"additionalItems",
|
|
@@ -1631,6 +1659,16 @@ function parsePluginAgentToolPresentation(toolName, value) {
|
|
|
1631
1659
|
}
|
|
1632
1660
|
return presentation;
|
|
1633
1661
|
}
|
|
1662
|
+
function summarizeStandardIssues(issues) {
|
|
1663
|
+
if (issues.length === 0) return "invalid";
|
|
1664
|
+
return issues.map((issue) => {
|
|
1665
|
+
const segments = issue.path === void 0 ? [] : Array.isArray(issue.path) ? issue.path.map(
|
|
1666
|
+
(segment) => typeof segment === "object" && segment !== null ? String(segment.key) : String(segment)
|
|
1667
|
+
) : [String(issue.path)];
|
|
1668
|
+
const path = segments.length > 0 ? segments.join(".") : "(input)";
|
|
1669
|
+
return `${path}: ${issue.message}`;
|
|
1670
|
+
}).join("; ");
|
|
1671
|
+
}
|
|
1634
1672
|
function summarizeParseIssues(error) {
|
|
1635
1673
|
const issues = error?.issues;
|
|
1636
1674
|
if (Array.isArray(issues) && issues.length > 0) {
|
|
@@ -1736,11 +1774,140 @@ function storePluginHook(records, hook, handler) {
|
|
|
1736
1774
|
function pluginHookAlreadyRegisteredMessage(hook) {
|
|
1737
1775
|
return `a "${hook}" hook handler is already registered by this plugin`;
|
|
1738
1776
|
}
|
|
1777
|
+
var ENVIRONMENT_PROVIDER_ID_PATTERN = /^[a-z0-9][a-z0-9-]{1,63}$/;
|
|
1778
|
+
var ENVIRONMENT_PROVIDER_DISPLAY_NAME_MAX_CHARS = 80;
|
|
1779
|
+
var ENVIRONMENT_PROVIDER_REQUIREMENT_NAMES = [
|
|
1780
|
+
"projectCheckout",
|
|
1781
|
+
"gitCheckout",
|
|
1782
|
+
"gitRemote",
|
|
1783
|
+
"projectless"
|
|
1784
|
+
];
|
|
1785
|
+
function validatePluginEnvironmentProviderDeclaration(declaration) {
|
|
1786
|
+
if (typeof declaration !== "object" || declaration === null) {
|
|
1787
|
+
throw new Error("environment provider declaration must be an object");
|
|
1788
|
+
}
|
|
1789
|
+
const id = declaration.id;
|
|
1790
|
+
if (typeof id !== "string" || !ENVIRONMENT_PROVIDER_ID_PATTERN.test(id)) {
|
|
1791
|
+
throw new Error(
|
|
1792
|
+
`invalid environment provider id ${JSON.stringify(id)} \u2014 use 2-64 lowercase letters, digits, or "-", starting with a letter or digit`
|
|
1793
|
+
);
|
|
1794
|
+
}
|
|
1795
|
+
const displayName = typeof declaration.displayName === "string" ? declaration.displayName.trim() : "";
|
|
1796
|
+
if (displayName.length === 0 || displayName.length > ENVIRONMENT_PROVIDER_DISPLAY_NAME_MAX_CHARS) {
|
|
1797
|
+
throw new Error(
|
|
1798
|
+
`environment provider "${id}" needs a displayName of 1-${ENVIRONMENT_PROVIDER_DISPLAY_NAME_MAX_CHARS} characters`
|
|
1799
|
+
);
|
|
1800
|
+
}
|
|
1801
|
+
const icon = declaration.icon === void 0 ? null : z4.string().min(1).parse(declaration.icon).trim();
|
|
1802
|
+
if (icon !== null) {
|
|
1803
|
+
if (isPluginOwnedIconPath(icon))
|
|
1804
|
+
validateProviderRelativePath(icon, `"${id}" icon`);
|
|
1805
|
+
else if (!isNamespacedGlyph(icon) && /[/\\]/u.test(icon))
|
|
1806
|
+
throw new Error(
|
|
1807
|
+
`environment provider "${id}" icon must be a glyph, declared icon, or plugin-relative path`
|
|
1808
|
+
);
|
|
1809
|
+
}
|
|
1810
|
+
if (icon !== null && icon.length === 0) {
|
|
1811
|
+
throw new Error(`environment provider "${id}" declares an empty icon`);
|
|
1812
|
+
}
|
|
1813
|
+
const requires = normalizeEnvironmentProviderRequirements(id, declaration);
|
|
1814
|
+
const inputs = normalizeEnvironmentProviderInputs(id, declaration);
|
|
1815
|
+
if (typeof declaration.create !== "function" || typeof declaration.remove !== "function") {
|
|
1816
|
+
throw new Error(
|
|
1817
|
+
`environment provider "${id}" must declare create and remove functions`
|
|
1818
|
+
);
|
|
1819
|
+
}
|
|
1820
|
+
if (declaration.validate !== void 0 && typeof declaration.validate !== "function") {
|
|
1821
|
+
throw new Error(
|
|
1822
|
+
`environment provider "${id}" declares a validate that is not a function`
|
|
1823
|
+
);
|
|
1824
|
+
}
|
|
1825
|
+
if (declaration.availability !== void 0 && typeof declaration.availability !== "function") {
|
|
1826
|
+
throw new Error(
|
|
1827
|
+
`environment provider "${id}" declares availability that is not a function`
|
|
1828
|
+
);
|
|
1829
|
+
}
|
|
1830
|
+
return {
|
|
1831
|
+
id,
|
|
1832
|
+
displayName,
|
|
1833
|
+
icon,
|
|
1834
|
+
requires,
|
|
1835
|
+
inputs: inputs === null ? null : inputs.schema,
|
|
1836
|
+
inputsJsonSchema: inputs === null ? null : inputs.jsonSchema,
|
|
1837
|
+
availability: declaration.availability ?? null,
|
|
1838
|
+
validate: declaration.validate ?? null,
|
|
1839
|
+
create: declaration.create,
|
|
1840
|
+
remove: declaration.remove,
|
|
1841
|
+
policy: environmentProviderPolicySchema.parse(declaration.policy ?? {})
|
|
1842
|
+
};
|
|
1843
|
+
}
|
|
1844
|
+
function normalizeEnvironmentProviderInputs(id, declaration) {
|
|
1845
|
+
const inputs = declaration.inputs;
|
|
1846
|
+
if (inputs === void 0) {
|
|
1847
|
+
return null;
|
|
1848
|
+
}
|
|
1849
|
+
if (!isStandardSchema(inputs)) {
|
|
1850
|
+
throw new Error(
|
|
1851
|
+
`environment provider "${id}" declares an inputs that is not a Standard Schema v1 validator`
|
|
1852
|
+
);
|
|
1853
|
+
}
|
|
1854
|
+
let converted;
|
|
1855
|
+
try {
|
|
1856
|
+
converted = JSON.parse(JSON.stringify(standardSchemaToJsonSchema(inputs)));
|
|
1857
|
+
} catch (error) {
|
|
1858
|
+
throw new Error(
|
|
1859
|
+
`environment provider "${id}" declares an inputs validator that cannot be published as JSON Schema (${error instanceof Error ? error.message : String(error)}) \u2014 declare it with zod 4 or a validator exposing toJSONSchema()`
|
|
1860
|
+
);
|
|
1861
|
+
}
|
|
1862
|
+
const jsonSchema = jsonValueSchema.safeParse(converted);
|
|
1863
|
+
if (!jsonSchema.success) {
|
|
1864
|
+
throw new Error(
|
|
1865
|
+
`environment provider "${id}" declares an inputs schema whose JSON Schema is not JSON-serializable`
|
|
1866
|
+
);
|
|
1867
|
+
}
|
|
1868
|
+
return { schema: inputs, jsonSchema: jsonSchema.data };
|
|
1869
|
+
}
|
|
1870
|
+
function normalizeEnvironmentProviderRequirements(id, declaration) {
|
|
1871
|
+
const requires = declaration.requires ?? {};
|
|
1872
|
+
if (typeof requires !== "object" || requires === null || Array.isArray(requires)) {
|
|
1873
|
+
throw new Error(
|
|
1874
|
+
`environment provider "${id}" declares a requires that is not an object`
|
|
1875
|
+
);
|
|
1876
|
+
}
|
|
1877
|
+
const normalized = {};
|
|
1878
|
+
for (const name of ENVIRONMENT_PROVIDER_REQUIREMENT_NAMES) {
|
|
1879
|
+
const value = requires[name];
|
|
1880
|
+
if (value !== void 0 && typeof value !== "boolean") {
|
|
1881
|
+
throw new Error(
|
|
1882
|
+
`environment provider "${id}" declares a requires.${name} that is not a boolean`
|
|
1883
|
+
);
|
|
1884
|
+
}
|
|
1885
|
+
normalized[name] = value === true;
|
|
1886
|
+
}
|
|
1887
|
+
if (normalized.gitCheckout) {
|
|
1888
|
+
normalized.projectCheckout = true;
|
|
1889
|
+
}
|
|
1890
|
+
if (normalized.projectless && (normalized.projectCheckout || normalized.gitRemote)) {
|
|
1891
|
+
throw new Error(
|
|
1892
|
+
`environment provider "${id}" declares requires.projectless together with a project requirement \u2014 a projectless thread has no checkout or remote`
|
|
1893
|
+
);
|
|
1894
|
+
}
|
|
1895
|
+
return normalized;
|
|
1896
|
+
}
|
|
1897
|
+
var environmentProviderPolicySchema = z4.object({
|
|
1898
|
+
retireGraceMs: z4.number().int().nonnegative().nullable().default(3e5),
|
|
1899
|
+
pathKeys: z4.enum(["per-thread", "per-attempt"]).default("per-thread")
|
|
1900
|
+
}).strict();
|
|
1901
|
+
var MACHINE_PROVIDER_REQUIREMENT_NAMES = ["gitRemote"];
|
|
1739
1902
|
export {
|
|
1740
1903
|
AGENT_TOOL_NAME_PATTERN,
|
|
1741
1904
|
BACKGROUND_NAME_PATTERN,
|
|
1742
1905
|
CLI_COMMAND_NAME_PATTERN,
|
|
1906
|
+
ENVIRONMENT_PROVIDER_DISPLAY_NAME_MAX_CHARS,
|
|
1907
|
+
ENVIRONMENT_PROVIDER_ID_PATTERN,
|
|
1908
|
+
ENVIRONMENT_PROVIDER_REQUIREMENT_NAMES,
|
|
1743
1909
|
KV_VALUE_MAX_BYTES,
|
|
1910
|
+
MACHINE_PROVIDER_REQUIREMENT_NAMES,
|
|
1744
1911
|
MENTION_PROVIDER_ID_PATTERN,
|
|
1745
1912
|
PLUGIN_AGENT_DYNAMIC_INSTRUCTIONS_MAX_CHARS,
|
|
1746
1913
|
PLUGIN_AGENT_SELECTION_MAX_IDS,
|
|
@@ -1784,8 +1951,10 @@ export {
|
|
|
1784
1951
|
rejectStaleAgentToolFields,
|
|
1785
1952
|
storePluginHook,
|
|
1786
1953
|
summarizeParseIssues,
|
|
1954
|
+
summarizeStandardIssues,
|
|
1787
1955
|
undeclaredIconProblem,
|
|
1788
1956
|
validatePluginAiServiceDeclaration,
|
|
1957
|
+
validatePluginEnvironmentProviderDeclaration,
|
|
1789
1958
|
validatePluginProviderDeclaration,
|
|
1790
1959
|
validatePluginProviderEnvEntries,
|
|
1791
1960
|
validateSettingsUpdate,
|
|
@@ -9,6 +9,14 @@ function requireSlotId(kind, value) {
|
|
|
9
9
|
}
|
|
10
10
|
return value;
|
|
11
11
|
}
|
|
12
|
+
function requireEnvironmentProviderId(kind, value) {
|
|
13
|
+
if (typeof value !== "string" || !PLUGIN_SLOT_ID_PATTERN.test(value)) {
|
|
14
|
+
throw new Error(
|
|
15
|
+
`${kind}: "environmentProviderId" must match ${String(PLUGIN_SLOT_ID_PATTERN)}, got ${JSON.stringify(value)}`
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
return value;
|
|
19
|
+
}
|
|
12
20
|
function requireProviderId(kind, value) {
|
|
13
21
|
if (typeof value !== "string" || !PLUGIN_SLOT_ID_PATTERN.test(value)) {
|
|
14
22
|
throw new Error(
|
|
@@ -391,6 +399,7 @@ function collectPluginAppRegistrations(definition, onComposerCustomizationReject
|
|
|
391
399
|
commandPaletteActions: [],
|
|
392
400
|
providerIcons: [],
|
|
393
401
|
timelineRenderers: [],
|
|
402
|
+
environmentProviderInputs: [],
|
|
394
403
|
contentScripts: []
|
|
395
404
|
};
|
|
396
405
|
sidebarFooterItemsByRegistrationSet.set(collected, sidebarFooterItems);
|
|
@@ -415,6 +424,7 @@ function collectPluginAppRegistrations(definition, onComposerCustomizationReject
|
|
|
415
424
|
commandPaletteAction: /* @__PURE__ */ new Set(),
|
|
416
425
|
providerIcon: /* @__PURE__ */ new Set(),
|
|
417
426
|
timelineRenderer: /* @__PURE__ */ new Set(),
|
|
427
|
+
environmentProviderInputs: /* @__PURE__ */ new Set(),
|
|
418
428
|
contentScript: /* @__PURE__ */ new Set()
|
|
419
429
|
};
|
|
420
430
|
definition.setup({
|
|
@@ -765,6 +775,22 @@ function collectPluginAppRegistrations(definition, onComposerCustomizationReject
|
|
|
765
775
|
kind: itemKind,
|
|
766
776
|
component: requireComponent(kind, registration.component)
|
|
767
777
|
});
|
|
778
|
+
},
|
|
779
|
+
experimental_environmentProviderInputs(registration) {
|
|
780
|
+
const kind = "slots.experimental_environmentProviderInputs";
|
|
781
|
+
const environmentProviderId = requireEnvironmentProviderId(
|
|
782
|
+
kind,
|
|
783
|
+
registration?.environmentProviderId
|
|
784
|
+
);
|
|
785
|
+
requireUniqueId(
|
|
786
|
+
kind,
|
|
787
|
+
seenIds.environmentProviderInputs,
|
|
788
|
+
environmentProviderId
|
|
789
|
+
);
|
|
790
|
+
collected.environmentProviderInputs.push({
|
|
791
|
+
environmentProviderId,
|
|
792
|
+
component: requireComponent(kind, registration.component)
|
|
793
|
+
});
|
|
768
794
|
}
|
|
769
795
|
},
|
|
770
796
|
experimental_sidebarFooter: new SidebarFooterCollector(
|
|
@@ -1316,7 +1316,7 @@ var systemThreadProvisioningStatusSchema = z11.enum(
|
|
|
1316
1316
|
var systemThreadProvisioningEventDataSchema = z11.object({
|
|
1317
1317
|
provisioningId: z11.string(),
|
|
1318
1318
|
status: systemThreadProvisioningStatusSchema,
|
|
1319
|
-
environmentId: z11.string(),
|
|
1319
|
+
environmentId: z11.string().nullable(),
|
|
1320
1320
|
entries: z11.array(provisioningTranscriptEntrySchema)
|
|
1321
1321
|
});
|
|
1322
1322
|
var systemLegacyUserMessageEventDataSchema = z11.object({
|
|
@@ -1717,6 +1717,19 @@ var threadEventItemTruncationSchema = z14.object({
|
|
|
1717
1717
|
result: threadEventTextTruncationSchema.optional(),
|
|
1718
1718
|
resultText: threadEventTextTruncationSchema.optional()
|
|
1719
1719
|
});
|
|
1720
|
+
var threadEventImageGenerationItemSchema = z14.object({
|
|
1721
|
+
type: z14.literal("imageGeneration"),
|
|
1722
|
+
id: z14.string(),
|
|
1723
|
+
status: threadEventItemStatusSchema,
|
|
1724
|
+
prompt: z14.string().nullable(),
|
|
1725
|
+
path: z14.string().nullable(),
|
|
1726
|
+
result: z14.string().optional(),
|
|
1727
|
+
error: z14.string().nullable(),
|
|
1728
|
+
transparentBackground: z14.boolean(),
|
|
1729
|
+
truncation: threadEventItemTruncationSchema.optional(),
|
|
1730
|
+
...itemPresentationField,
|
|
1731
|
+
parentToolCallId: z14.string().optional()
|
|
1732
|
+
});
|
|
1720
1733
|
var threadEventUserContentSchema = z14.discriminatedUnion("type", [
|
|
1721
1734
|
z14.object({ type: z14.literal("text"), text: z14.string() }),
|
|
1722
1735
|
z14.object({ type: z14.literal("image"), url: z14.string() }),
|
|
@@ -1828,6 +1841,7 @@ var threadEventItemSchema = z14.discriminatedUnion("type", [
|
|
|
1828
1841
|
threadEventWebSearchItemSchema,
|
|
1829
1842
|
threadEventWebFetchItemSchema,
|
|
1830
1843
|
threadEventImageViewItemSchema,
|
|
1844
|
+
threadEventImageGenerationItemSchema,
|
|
1831
1845
|
threadEventFileReadItemSchema,
|
|
1832
1846
|
threadEventSearchItemSchema,
|
|
1833
1847
|
z14.object({
|
|
@@ -2896,6 +2910,14 @@ var deltaItemShapeSchema = z25.discriminatedUnion("type", [
|
|
|
2896
2910
|
pattern: z25.string().nullable()
|
|
2897
2911
|
}),
|
|
2898
2912
|
z25.object({ type: z25.literal("imageView"), path: z25.string() }),
|
|
2913
|
+
z25.object({
|
|
2914
|
+
type: z25.literal("imageGeneration"),
|
|
2915
|
+
prompt: z25.string().nullable(),
|
|
2916
|
+
path: z25.string().nullable(),
|
|
2917
|
+
result: z25.string().optional(),
|
|
2918
|
+
error: z25.string().nullable(),
|
|
2919
|
+
transparentBackground: z25.boolean()
|
|
2920
|
+
}),
|
|
2899
2921
|
deltaBackgroundTaskShapeSchema,
|
|
2900
2922
|
deltaFileReadShapeSchema,
|
|
2901
2923
|
deltaSearchShapeSchema,
|
|
@@ -3831,6 +3853,7 @@ import { promises as fs2, readFileSync } from "node:fs";
|
|
|
3831
3853
|
import { createServer } from "node:net";
|
|
3832
3854
|
import { dirname as dirname2, isAbsolute, basename as basename3, relative, resolve as resolve3 } from "node:path";
|
|
3833
3855
|
import { fileURLToPath } from "node:url";
|
|
3856
|
+
import { isDeepStrictEqual } from "node:util";
|
|
3834
3857
|
import { z as z40 } from "zod";
|
|
3835
3858
|
|
|
3836
3859
|
// ../provider-bridge-acp/src/bridge-protocol.ts
|
|
@@ -8751,6 +8774,7 @@ async function startAgentSession(request) {
|
|
|
8751
8774
|
});
|
|
8752
8775
|
session = {
|
|
8753
8776
|
bbThreadId,
|
|
8777
|
+
construction: params,
|
|
8754
8778
|
providerThreadId: "",
|
|
8755
8779
|
cwd: params.cwd,
|
|
8756
8780
|
dialect,
|
|
@@ -9484,7 +9508,7 @@ async function handleRequest2(request) {
|
|
|
9484
9508
|
}
|
|
9485
9509
|
case "turn/start": {
|
|
9486
9510
|
const params = request.params;
|
|
9487
|
-
|
|
9511
|
+
let session = liveSessionForThread(params.threadId);
|
|
9488
9512
|
if (session === void 0) {
|
|
9489
9513
|
sendError(request.id, -32e3, "No active ACP session");
|
|
9490
9514
|
return;
|
|
@@ -9493,6 +9517,26 @@ async function handleRequest2(request) {
|
|
|
9493
9517
|
sendError(request.id, -32e3, "A turn is already active");
|
|
9494
9518
|
return;
|
|
9495
9519
|
}
|
|
9520
|
+
if (Object.keys(params.options.envVars ?? {}).length > 0) {
|
|
9521
|
+
const envVars = {
|
|
9522
|
+
...decodeLaunchSpec(params.options.providerOptions)?.env ?? {},
|
|
9523
|
+
...params.options.envVars
|
|
9524
|
+
};
|
|
9525
|
+
if (!isDeepStrictEqual(envVars, session.construction.envVars ?? {})) {
|
|
9526
|
+
const previousProviderThreadId = session.providerThreadId;
|
|
9527
|
+
session = await startAgentSession({
|
|
9528
|
+
kind: "resume",
|
|
9529
|
+
params: { ...session.construction, envVars },
|
|
9530
|
+
resumeProviderThreadId: previousProviderThreadId
|
|
9531
|
+
});
|
|
9532
|
+
sendNotification(BRIDGE_NOTIFICATION_METHODS.sessionReplaced, {
|
|
9533
|
+
threadId: params.threadId,
|
|
9534
|
+
providerThreadId: session.providerThreadId,
|
|
9535
|
+
reason: "Execution settings changed; the ACP session was rebuilt to apply them.",
|
|
9536
|
+
contextLost: session.providerThreadId !== previousProviderThreadId
|
|
9537
|
+
});
|
|
9538
|
+
}
|
|
9539
|
+
}
|
|
9496
9540
|
const pending = {
|
|
9497
9541
|
clientRequestId: params.clientRequestId,
|
|
9498
9542
|
input: params.input,
|