@get-bb/plugin-sdk 0.4.48 → 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 +1587 -924
- 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 +232 -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 +253 -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) {
|
|
@@ -70,37 +70,54 @@ function isRelativeProviderSkillRootPath(value) {
|
|
|
70
70
|
return !normalized.startsWith("/") && !/^[a-zA-Z]:\//u.test(normalized) && normalized.split("/").every((segment) => segment !== "" && segment !== "." && segment !== "..");
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
// ../domain/src/
|
|
73
|
+
// ../domain/src/json-value.ts
|
|
74
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";
|
|
75
92
|
var PROVIDER_NATIVE_ROOTS_MAX = 32;
|
|
76
93
|
var PROVIDER_NATIVE_ROOT_NAME_PREFIX_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,62}:$/u;
|
|
77
|
-
var nativeRootNamePrefixSchema =
|
|
94
|
+
var nativeRootNamePrefixSchema = z3.string().refine(
|
|
78
95
|
(value) => value === "" || PROVIDER_NATIVE_ROOT_NAME_PREFIX_PATTERN.test(value),
|
|
79
96
|
"A root name prefix is a plugin-name-like token ending in ':'"
|
|
80
97
|
);
|
|
81
|
-
var nativeRootManifestPathSchema =
|
|
98
|
+
var nativeRootManifestPathSchema = z3.string().min(1).refine(
|
|
82
99
|
isRelativeProviderSkillRootPath,
|
|
83
100
|
"A manifest marker is a relative path without dot segments"
|
|
84
101
|
);
|
|
85
|
-
var relativeNativeRootPathSchema =
|
|
102
|
+
var relativeNativeRootPathSchema = z3.string().min(1).refine(
|
|
86
103
|
isRelativeProviderSkillRootPath,
|
|
87
104
|
"Roots must be relative paths without dot segments"
|
|
88
105
|
);
|
|
89
|
-
var absoluteNativeRootPathSchema =
|
|
106
|
+
var absoluteNativeRootPathSchema = z3.string().min(1).refine(
|
|
90
107
|
isAbsoluteProviderSkillRootPath,
|
|
91
108
|
"Absolute roots must be absolute paths without dot segments"
|
|
92
109
|
);
|
|
93
|
-
var providerNativeRootInputSchema =
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
path:
|
|
110
|
+
var providerNativeRootInputSchema = z3.union([
|
|
111
|
+
z3.string().min(1),
|
|
112
|
+
z3.object({
|
|
113
|
+
path: z3.string().min(1),
|
|
97
114
|
/** Skills nest in subdirectories (the agent scans recursively). */
|
|
98
|
-
recursive:
|
|
115
|
+
recursive: z3.boolean().optional(),
|
|
99
116
|
/**
|
|
100
117
|
* Scan the same relative directory in every ancestor of the workspace
|
|
101
118
|
* up to the repository root (`project` roots only).
|
|
102
119
|
*/
|
|
103
|
-
ancestors:
|
|
120
|
+
ancestors: z3.boolean().optional(),
|
|
104
121
|
/**
|
|
105
122
|
* Prepended to every name under the root, a vendor plugin's
|
|
106
123
|
* `plugin-name:`; a prefixed root is listed as a plugin root.
|
|
@@ -115,14 +132,14 @@ var providerNativeRootInputSchema = z2.union([
|
|
|
115
132
|
skipIfManifest: nativeRootManifestPathSchema.optional()
|
|
116
133
|
}).strict()
|
|
117
134
|
]);
|
|
118
|
-
var providerNativeRootsInputSchema =
|
|
119
|
-
user:
|
|
120
|
-
project:
|
|
135
|
+
var providerNativeRootsInputSchema = z3.object({
|
|
136
|
+
user: z3.array(providerNativeRootInputSchema).optional(),
|
|
137
|
+
project: z3.array(providerNativeRootInputSchema).optional()
|
|
121
138
|
}).strict();
|
|
122
|
-
var providerNativeRootSchema =
|
|
123
|
-
path:
|
|
124
|
-
recursive:
|
|
125
|
-
ancestors:
|
|
139
|
+
var providerNativeRootSchema = z3.object({
|
|
140
|
+
path: z3.string().min(1),
|
|
141
|
+
recursive: z3.boolean(),
|
|
142
|
+
ancestors: z3.boolean(),
|
|
126
143
|
namePrefix: nativeRootNamePrefixSchema,
|
|
127
144
|
/** Absent: every skill-shaped directory under the root is a skill. */
|
|
128
145
|
skipIfManifest: nativeRootManifestPathSchema.optional()
|
|
@@ -131,7 +148,7 @@ function uniqueByPath(roots) {
|
|
|
131
148
|
return new Set(roots.map((root) => root.path)).size === roots.length;
|
|
132
149
|
}
|
|
133
150
|
function nativeRootSideSchema(side) {
|
|
134
|
-
return
|
|
151
|
+
return z3.array(
|
|
135
152
|
providerNativeRootSchema.extend({ path: relativeNativeRootPathSchema }).superRefine((root, context) => {
|
|
136
153
|
if (root.ancestors && side !== "project") {
|
|
137
154
|
context.addIssue({
|
|
@@ -142,7 +159,7 @@ function nativeRootSideSchema(side) {
|
|
|
142
159
|
})
|
|
143
160
|
).max(PROVIDER_NATIVE_ROOTS_MAX).refine(uniqueByPath, "Roots must not repeat a path");
|
|
144
161
|
}
|
|
145
|
-
var providerNativeRootsSchema =
|
|
162
|
+
var providerNativeRootsSchema = z3.object({
|
|
146
163
|
user: nativeRootSideSchema("user"),
|
|
147
164
|
project: nativeRootSideSchema("project")
|
|
148
165
|
}).strict();
|
|
@@ -168,19 +185,19 @@ function normalizeProviderNativeRoots(roots) {
|
|
|
168
185
|
project: (roots?.project ?? []).map(normalizeProviderNativeRoot)
|
|
169
186
|
};
|
|
170
187
|
}
|
|
171
|
-
var providerResolvedNativeRootShapeSchema =
|
|
188
|
+
var providerResolvedNativeRootShapeSchema = z3.enum([
|
|
172
189
|
"skills",
|
|
173
190
|
"skill",
|
|
174
191
|
"skill-file",
|
|
175
192
|
"commands",
|
|
176
193
|
"command-file"
|
|
177
194
|
]);
|
|
178
|
-
var resolvedNativeRootFieldsSchema =
|
|
195
|
+
var resolvedNativeRootFieldsSchema = z3.object({
|
|
179
196
|
path: absoluteNativeRootPathSchema,
|
|
180
|
-
origin:
|
|
181
|
-
recursive:
|
|
197
|
+
origin: z3.enum(["user", "project"]),
|
|
198
|
+
recursive: z3.boolean(),
|
|
182
199
|
/** Only with origin `project`, for a path inside the workspace. */
|
|
183
|
-
ancestors:
|
|
200
|
+
ancestors: z3.boolean(),
|
|
184
201
|
namePrefix: nativeRootNamePrefixSchema,
|
|
185
202
|
shape: providerResolvedNativeRootShapeSchema,
|
|
186
203
|
/**
|
|
@@ -188,7 +205,7 @@ var resolvedNativeRootFieldsSchema = z2.object({
|
|
|
188
205
|
* none. A vendor plugin's root SKILL.md takes the plugin's name; absent
|
|
189
206
|
* means the parent directory's name.
|
|
190
207
|
*/
|
|
191
|
-
fallbackName:
|
|
208
|
+
fallbackName: z3.string().min(1).optional(),
|
|
192
209
|
/**
|
|
193
210
|
* `skills` only: a file, relative to a skill directory under this root,
|
|
194
211
|
* that marks the directory as a vendor plugin rather than a skill; the
|
|
@@ -232,14 +249,14 @@ var resolvedCommandShapes = /* @__PURE__ */ new Set([
|
|
|
232
249
|
"command-file"
|
|
233
250
|
]);
|
|
234
251
|
var PROVIDER_RESOLVED_NATIVE_ROOTS_MAX = 256;
|
|
235
|
-
var providerResolvedNativeRootsSchema =
|
|
236
|
-
skills:
|
|
252
|
+
var providerResolvedNativeRootsSchema = z3.object({
|
|
253
|
+
skills: z3.array(
|
|
237
254
|
providerResolvedNativeRootSchema.refine(
|
|
238
255
|
(root) => resolvedSkillShapes.has(root.shape),
|
|
239
256
|
"A skills root needs a skill shape"
|
|
240
257
|
)
|
|
241
258
|
).max(PROVIDER_RESOLVED_NATIVE_ROOTS_MAX),
|
|
242
|
-
commands:
|
|
259
|
+
commands: z3.array(
|
|
243
260
|
providerResolvedNativeRootSchema.refine(
|
|
244
261
|
(root) => resolvedCommandShapes.has(root.shape),
|
|
245
262
|
"A commands root needs a command shape"
|
|
@@ -250,7 +267,7 @@ var EMPTY_PROVIDER_RESOLVED_NATIVE_ROOTS = Object.freeze({
|
|
|
250
267
|
skills: Object.freeze([]),
|
|
251
268
|
commands: Object.freeze([])
|
|
252
269
|
});
|
|
253
|
-
var providerNativeRootSetSchema =
|
|
270
|
+
var providerNativeRootSetSchema = z3.object({
|
|
254
271
|
skills: providerNativeRootsSchema,
|
|
255
272
|
commands: providerNativeRootsSchema,
|
|
256
273
|
resolved: providerResolvedNativeRootsSchema
|
|
@@ -283,16 +300,16 @@ var CLI_COMMAND_NAME_PATTERN = /^[a-z0-9-]+$/;
|
|
|
283
300
|
var AGENT_TOOL_NAME_PATTERN = /^[a-zA-Z0-9_-]+$/;
|
|
284
301
|
var PLUGIN_PROVIDER_ENV_NAME_PATTERN = /^[A-Z_][A-Z0-9_]*$/;
|
|
285
302
|
var PLUGIN_PROVIDER_ENV_MAX_ENTRIES = 32;
|
|
286
|
-
var pluginProviderEnvEntrySchema =
|
|
287
|
-
name:
|
|
288
|
-
value:
|
|
289
|
-
|
|
290
|
-
|
|
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()
|
|
291
308
|
]),
|
|
292
|
-
reason:
|
|
293
|
-
secret:
|
|
309
|
+
reason: z4.string(),
|
|
310
|
+
secret: z4.boolean()
|
|
294
311
|
}).strict();
|
|
295
|
-
var pluginProviderEnvEntriesSchema =
|
|
312
|
+
var pluginProviderEnvEntriesSchema = z4.array(pluginProviderEnvEntrySchema).max(PLUGIN_PROVIDER_ENV_MAX_ENTRIES).superRefine((entries, context) => {
|
|
296
313
|
const names = /* @__PURE__ */ new Set();
|
|
297
314
|
for (let index = 0; index < entries.length; index += 1) {
|
|
298
315
|
const name = entries[index]?.name;
|
|
@@ -327,26 +344,26 @@ var PROVIDER_ID_PATTERN = /^[a-z0-9][a-z0-9-]{1,63}$/;
|
|
|
327
344
|
var PLUGIN_PROVIDER_BRIDGE_OPTIONS_MAX_BYTES = 64 * 1024;
|
|
328
345
|
var SETTING_KEY_PATTERN = /^[a-zA-Z0-9_-]+$/;
|
|
329
346
|
var settingsBaseFields = {
|
|
330
|
-
label:
|
|
331
|
-
description:
|
|
347
|
+
label: z4.string().min(1),
|
|
348
|
+
description: z4.string().min(1).optional()
|
|
332
349
|
};
|
|
333
|
-
var stringSettingSchemaSchema =
|
|
350
|
+
var stringSettingSchemaSchema = z4.custom(
|
|
334
351
|
(value) => isStandardSchema(value)
|
|
335
352
|
);
|
|
336
|
-
var booleanSettingSchemaSchema =
|
|
353
|
+
var booleanSettingSchemaSchema = z4.custom(
|
|
337
354
|
(value) => isStandardSchema(value)
|
|
338
355
|
);
|
|
339
|
-
var numberSettingSchemaSchema =
|
|
356
|
+
var numberSettingSchemaSchema = z4.custom(
|
|
340
357
|
(value) => isStandardSchema(value)
|
|
341
358
|
);
|
|
342
|
-
var settingDescriptorSchema =
|
|
343
|
-
|
|
344
|
-
type:
|
|
359
|
+
var settingDescriptorSchema = z4.discriminatedUnion("type", [
|
|
360
|
+
z4.object({
|
|
361
|
+
type: z4.literal("string"),
|
|
345
362
|
...settingsBaseFields,
|
|
346
|
-
secret:
|
|
347
|
-
experimental_multiline:
|
|
363
|
+
secret: z4.literal(true).optional(),
|
|
364
|
+
experimental_multiline: z4.boolean().optional(),
|
|
348
365
|
experimental_schema: stringSettingSchemaSchema.optional(),
|
|
349
|
-
default:
|
|
366
|
+
default: z4.string().optional()
|
|
350
367
|
}).strict().refine(
|
|
351
368
|
(descriptor) => !(descriptor.secret === true && descriptor.experimental_multiline === true),
|
|
352
369
|
{
|
|
@@ -354,30 +371,30 @@ var settingDescriptorSchema = z3.discriminatedUnion("type", [
|
|
|
354
371
|
path: ["experimental_multiline"]
|
|
355
372
|
}
|
|
356
373
|
),
|
|
357
|
-
|
|
358
|
-
type:
|
|
374
|
+
z4.object({
|
|
375
|
+
type: z4.literal("boolean"),
|
|
359
376
|
...settingsBaseFields,
|
|
360
377
|
experimental_schema: booleanSettingSchemaSchema.optional(),
|
|
361
|
-
default:
|
|
378
|
+
default: z4.boolean().optional()
|
|
362
379
|
}).strict(),
|
|
363
|
-
|
|
364
|
-
type:
|
|
380
|
+
z4.object({
|
|
381
|
+
type: z4.literal("number"),
|
|
365
382
|
...settingsBaseFields,
|
|
366
383
|
experimental_schema: numberSettingSchemaSchema.optional(),
|
|
367
|
-
default:
|
|
384
|
+
default: z4.number().finite().optional()
|
|
368
385
|
}).strict(),
|
|
369
|
-
|
|
370
|
-
type:
|
|
386
|
+
z4.object({
|
|
387
|
+
type: z4.literal("select"),
|
|
371
388
|
...settingsBaseFields,
|
|
372
|
-
options:
|
|
389
|
+
options: z4.array(z4.string().min(1)).min(1),
|
|
373
390
|
experimental_schema: stringSettingSchemaSchema.optional(),
|
|
374
|
-
default:
|
|
391
|
+
default: z4.string().optional()
|
|
375
392
|
}).strict(),
|
|
376
|
-
|
|
377
|
-
type:
|
|
393
|
+
z4.object({
|
|
394
|
+
type: z4.literal("project"),
|
|
378
395
|
...settingsBaseFields,
|
|
379
396
|
experimental_schema: stringSettingSchemaSchema.optional(),
|
|
380
|
-
default:
|
|
397
|
+
default: z4.string().optional()
|
|
381
398
|
}).strict()
|
|
382
399
|
]);
|
|
383
400
|
function registerSettingDescriptors(target, added) {
|
|
@@ -1407,11 +1424,21 @@ function readRpcMethodContract(method, value) {
|
|
|
1407
1424
|
function isZodSchemaLike(value) {
|
|
1408
1425
|
return typeof value === "object" && value !== null && typeof value.safeParse === "function";
|
|
1409
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
|
+
}
|
|
1410
1437
|
function zodSchemaToJsonSchema(schema) {
|
|
1411
1438
|
if (typeof schema.toJSONSchema === "function") {
|
|
1412
1439
|
return schema.toJSONSchema({ io: "input" });
|
|
1413
1440
|
}
|
|
1414
|
-
return
|
|
1441
|
+
return z4.toJSONSchema(schema, { io: "input" });
|
|
1415
1442
|
}
|
|
1416
1443
|
var SINGLE_SCHEMA_KEYWORDS = [
|
|
1417
1444
|
"additionalItems",
|
|
@@ -1632,6 +1659,16 @@ function parsePluginAgentToolPresentation(toolName, value) {
|
|
|
1632
1659
|
}
|
|
1633
1660
|
return presentation;
|
|
1634
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
|
+
}
|
|
1635
1672
|
function summarizeParseIssues(error) {
|
|
1636
1673
|
const issues = error?.issues;
|
|
1637
1674
|
if (Array.isArray(issues) && issues.length > 0) {
|
|
@@ -1737,11 +1774,140 @@ function storePluginHook(records, hook, handler) {
|
|
|
1737
1774
|
function pluginHookAlreadyRegisteredMessage(hook) {
|
|
1738
1775
|
return `a "${hook}" hook handler is already registered by this plugin`;
|
|
1739
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"];
|
|
1740
1902
|
export {
|
|
1741
1903
|
AGENT_TOOL_NAME_PATTERN,
|
|
1742
1904
|
BACKGROUND_NAME_PATTERN,
|
|
1743
1905
|
CLI_COMMAND_NAME_PATTERN,
|
|
1906
|
+
ENVIRONMENT_PROVIDER_DISPLAY_NAME_MAX_CHARS,
|
|
1907
|
+
ENVIRONMENT_PROVIDER_ID_PATTERN,
|
|
1908
|
+
ENVIRONMENT_PROVIDER_REQUIREMENT_NAMES,
|
|
1744
1909
|
KV_VALUE_MAX_BYTES,
|
|
1910
|
+
MACHINE_PROVIDER_REQUIREMENT_NAMES,
|
|
1745
1911
|
MENTION_PROVIDER_ID_PATTERN,
|
|
1746
1912
|
PLUGIN_AGENT_DYNAMIC_INSTRUCTIONS_MAX_CHARS,
|
|
1747
1913
|
PLUGIN_AGENT_SELECTION_MAX_IDS,
|
|
@@ -1785,8 +1951,10 @@ export {
|
|
|
1785
1951
|
rejectStaleAgentToolFields,
|
|
1786
1952
|
storePluginHook,
|
|
1787
1953
|
summarizeParseIssues,
|
|
1954
|
+
summarizeStandardIssues,
|
|
1788
1955
|
undeclaredIconProblem,
|
|
1789
1956
|
validatePluginAiServiceDeclaration,
|
|
1957
|
+
validatePluginEnvironmentProviderDeclaration,
|
|
1790
1958
|
validatePluginProviderDeclaration,
|
|
1791
1959
|
validatePluginProviderEnvEntries,
|
|
1792
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,
|