@vetta-org/plugin-sdk 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/activity-tab.d.ts +2 -0
- package/dist/activity-tab.d.ts.map +1 -1
- package/dist/activity-tab.js +1 -1
- package/dist/activity-tab.js.map +1 -1
- package/dist/agent.d.ts +158 -2
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +14 -1
- package/dist/agent.js.map +1 -1
- package/dist/ai.d.ts +93 -0
- package/dist/ai.d.ts.map +1 -0
- package/dist/ai.js +2 -0
- package/dist/ai.js.map +1 -0
- package/dist/app-actions.d.ts +9 -0
- package/dist/app-actions.d.ts.map +1 -1
- package/dist/app-actions.js.map +1 -1
- package/dist/artifacts.d.ts +31 -0
- package/dist/artifacts.d.ts.map +1 -0
- package/dist/artifacts.js +2 -0
- package/dist/artifacts.js.map +1 -0
- package/dist/browser.d.ts +119 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +2 -0
- package/dist/browser.js.map +1 -0
- package/dist/capture.d.ts +64 -0
- package/dist/capture.d.ts.map +1 -0
- package/dist/capture.js +2 -0
- package/dist/capture.js.map +1 -0
- package/dist/context.d.ts +46 -5
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js.map +1 -1
- package/dist/conversation.d.ts +66 -2
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js.map +1 -1
- package/dist/gateway.d.ts +37 -0
- package/dist/gateway.d.ts.map +1 -0
- package/dist/gateway.js +14 -0
- package/dist/gateway.js.map +1 -0
- package/dist/index.d.ts +20 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/jobs.d.ts +34 -0
- package/dist/jobs.d.ts.map +1 -0
- package/dist/jobs.js +2 -0
- package/dist/jobs.js.map +1 -0
- package/dist/manifest-schema.d.ts +234 -0
- package/dist/manifest-schema.d.ts.map +1 -0
- package/dist/manifest-schema.js +145 -0
- package/dist/manifest-schema.js.map +1 -0
- package/dist/manifest.d.ts +21 -55
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +342 -1
- package/dist/manifest.js.map +1 -1
- package/dist/media.d.ts +193 -0
- package/dist/media.d.ts.map +1 -0
- package/dist/media.js +11 -0
- package/dist/media.js.map +1 -0
- package/dist/network.d.ts +2 -1
- package/dist/network.d.ts.map +1 -1
- package/dist/network.js.map +1 -1
- package/dist/npm-package.d.ts +17 -0
- package/dist/npm-package.d.ts.map +1 -0
- package/dist/npm-package.js +38 -0
- package/dist/npm-package.js.map +1 -0
- package/dist/official.d.ts +218 -10
- package/dist/official.d.ts.map +1 -1
- package/dist/official.js.map +1 -1
- package/dist/permissions.d.ts +2 -1
- package/dist/permissions.d.ts.map +1 -1
- package/dist/permissions.js +54 -1
- package/dist/permissions.js.map +1 -1
- package/dist/prompt-attachment.d.ts +30 -6
- package/dist/prompt-attachment.d.ts.map +1 -1
- package/dist/prompt-attachment.js +35 -1
- package/dist/prompt-attachment.js.map +1 -1
- package/dist/quickjs.d.ts +147 -0
- package/dist/quickjs.d.ts.map +1 -0
- package/dist/quickjs.js +2 -0
- package/dist/quickjs.js.map +1 -0
- package/dist/storage.d.ts +7 -0
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js.map +1 -1
- package/dist/ui.d.ts +223 -15
- package/dist/ui.d.ts.map +1 -1
- package/dist/ui.js.map +1 -1
- package/package.json +21 -2
- package/src/tailwind-theme.css +30 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
import { PLUGIN_PERMISSIONS } from "./permissions.js";
|
|
3
|
+
const NON_WHITESPACE_PATTERN = "\\S";
|
|
4
|
+
export const PluginIdSchema = Type.String({
|
|
5
|
+
minLength: 1,
|
|
6
|
+
maxLength: 64,
|
|
7
|
+
pattern: "^[a-z0-9][a-z0-9._-]{0,63}$",
|
|
8
|
+
description: "Stable lowercase plugin identifier.",
|
|
9
|
+
});
|
|
10
|
+
export const PluginVersionSchema = Type.String({
|
|
11
|
+
minLength: 1,
|
|
12
|
+
maxLength: 64,
|
|
13
|
+
pattern: "^[a-zA-Z0-9][a-zA-Z0-9._+-]{0,63}$",
|
|
14
|
+
description: "Plugin version without path separators.",
|
|
15
|
+
});
|
|
16
|
+
export const PluginCommandNameSchema = Type.String({
|
|
17
|
+
minLength: 1,
|
|
18
|
+
maxLength: 64,
|
|
19
|
+
pattern: "^[a-zA-Z0-9][a-zA-Z0-9._+-]{0,63}$",
|
|
20
|
+
description: "Bare executable name declared by the plugin.",
|
|
21
|
+
});
|
|
22
|
+
export const PluginCommandNamesSchema = Type.Array(PluginCommandNameSchema);
|
|
23
|
+
export const PluginNetworkManifestSchema = Type.Object({
|
|
24
|
+
allowedHosts: Type.Array(Type.String({ minLength: 1, maxLength: 253, pattern: NON_WHITESPACE_PATTERN }), {
|
|
25
|
+
minItems: 1,
|
|
26
|
+
maxItems: 128,
|
|
27
|
+
}),
|
|
28
|
+
}, { additionalProperties: true });
|
|
29
|
+
export const PluginBrowserManifestSchema = Type.Object({
|
|
30
|
+
allowedHosts: Type.Array(Type.String({ minLength: 1, maxLength: 253, pattern: NON_WHITESPACE_PATTERN }), {
|
|
31
|
+
minItems: 1,
|
|
32
|
+
maxItems: 128,
|
|
33
|
+
}),
|
|
34
|
+
}, { additionalProperties: true });
|
|
35
|
+
export const PluginPermissionSchema = Type.Union(PLUGIN_PERMISSIONS.map((permission) => Type.Literal(permission)), { description: "Host capability requested by the plugin." });
|
|
36
|
+
const NonWhitespaceStringSchema = Type.String({ pattern: NON_WHITESPACE_PATTERN });
|
|
37
|
+
const OptionalAgentModesSchema = Type.Optional(Type.Union([NonWhitespaceStringSchema, Type.Array(NonWhitespaceStringSchema)]));
|
|
38
|
+
const StringRecordSchema = Type.Record(Type.String(), Type.String());
|
|
39
|
+
const PluginSettingBaseProperties = {
|
|
40
|
+
key: NonWhitespaceStringSchema,
|
|
41
|
+
description: Type.Optional(Type.String()),
|
|
42
|
+
default: Type.Optional(Type.Union([Type.String(), Type.Number(), Type.Boolean()])),
|
|
43
|
+
enum: Type.Optional(Type.Array(NonWhitespaceStringSchema)),
|
|
44
|
+
visibleWhen: Type.Optional(Type.Object({
|
|
45
|
+
key: NonWhitespaceStringSchema,
|
|
46
|
+
in: Type.Array(NonWhitespaceStringSchema),
|
|
47
|
+
}, { additionalProperties: true })),
|
|
48
|
+
};
|
|
49
|
+
const PluginInputSettingSchema = Type.Object({
|
|
50
|
+
...PluginSettingBaseProperties,
|
|
51
|
+
type: Type.Union([
|
|
52
|
+
Type.Literal("string"),
|
|
53
|
+
Type.Literal("number"),
|
|
54
|
+
Type.Literal("boolean"),
|
|
55
|
+
Type.Literal("enum"),
|
|
56
|
+
Type.Literal("secret"),
|
|
57
|
+
]),
|
|
58
|
+
title: NonWhitespaceStringSchema,
|
|
59
|
+
}, { additionalProperties: true });
|
|
60
|
+
const PluginDescriptionSettingSchema = Type.Object({
|
|
61
|
+
...PluginSettingBaseProperties,
|
|
62
|
+
type: Type.Literal("desc"),
|
|
63
|
+
title: Type.Optional(Type.String()),
|
|
64
|
+
}, { additionalProperties: true });
|
|
65
|
+
export const PluginSettingDefinitionSchema = Type.Union([
|
|
66
|
+
PluginInputSettingSchema,
|
|
67
|
+
PluginDescriptionSettingSchema,
|
|
68
|
+
]);
|
|
69
|
+
const PluginMcpCommonProperties = {
|
|
70
|
+
disabled: Type.Optional(Type.Boolean()),
|
|
71
|
+
autoApprove: Type.Optional(Type.Array(NonWhitespaceStringSchema)),
|
|
72
|
+
startupTimeout: Type.Optional(Type.Number()),
|
|
73
|
+
debug: Type.Optional(Type.Boolean()),
|
|
74
|
+
displayName: Type.Optional(Type.String()),
|
|
75
|
+
description: Type.Optional(Type.String()),
|
|
76
|
+
agent_mode: OptionalAgentModesSchema,
|
|
77
|
+
};
|
|
78
|
+
export const PluginMcpStdioServerConfigSchema = Type.Object({
|
|
79
|
+
...PluginMcpCommonProperties,
|
|
80
|
+
type: Type.Optional(Type.Literal("stdio")),
|
|
81
|
+
command: NonWhitespaceStringSchema,
|
|
82
|
+
args: Type.Optional(Type.Array(Type.String())),
|
|
83
|
+
env: Type.Optional(StringRecordSchema),
|
|
84
|
+
cwd: Type.Optional(Type.String()),
|
|
85
|
+
}, { additionalProperties: true });
|
|
86
|
+
export const PluginMcpHttpServerConfigSchema = Type.Object({
|
|
87
|
+
...PluginMcpCommonProperties,
|
|
88
|
+
type: Type.Literal("http"),
|
|
89
|
+
url: NonWhitespaceStringSchema,
|
|
90
|
+
headers: Type.Optional(StringRecordSchema),
|
|
91
|
+
oauthClientId: Type.Optional(Type.String()),
|
|
92
|
+
oauthDeviceFlow: Type.Optional(Type.Boolean()),
|
|
93
|
+
oauthScopes: Type.Optional(Type.String()),
|
|
94
|
+
}, { additionalProperties: true });
|
|
95
|
+
export const PluginMcpServerConfigSchema = Type.Union([
|
|
96
|
+
PluginMcpStdioServerConfigSchema,
|
|
97
|
+
PluginMcpHttpServerConfigSchema,
|
|
98
|
+
]);
|
|
99
|
+
const PluginMcpServerMapSchema = Type.Record(Type.String({ pattern: NON_WHITESPACE_PATTERN }), PluginMcpServerConfigSchema, { additionalProperties: false });
|
|
100
|
+
export const PluginAgentManifestSchema = Type.Object({
|
|
101
|
+
systemPrompt: Type.Optional(Type.Object({
|
|
102
|
+
promptPaths: Type.Optional(Type.Array(NonWhitespaceStringSchema)),
|
|
103
|
+
}, { additionalProperties: true })),
|
|
104
|
+
skillPaths: Type.Optional(Type.Array(NonWhitespaceStringSchema)),
|
|
105
|
+
mcpServers: Type.Optional(Type.Union([NonWhitespaceStringSchema, PluginMcpServerMapSchema])),
|
|
106
|
+
toolPolicy: Type.Optional(Type.Object({
|
|
107
|
+
allow: Type.Optional(Type.Array(NonWhitespaceStringSchema)),
|
|
108
|
+
deny: Type.Optional(Type.Array(NonWhitespaceStringSchema)),
|
|
109
|
+
}, { additionalProperties: true })),
|
|
110
|
+
}, { additionalProperties: true });
|
|
111
|
+
export const PluginModuleFederationManifestSchema = Type.Object({
|
|
112
|
+
remoteName: Type.String({ pattern: "^[A-Za-z_$][A-Za-z0-9_$-]{0,63}$" }),
|
|
113
|
+
expose: Type.String({ pattern: "^\\./(?!.*\\.\\.)(?!.*\\\\).+$" }),
|
|
114
|
+
}, { additionalProperties: true });
|
|
115
|
+
export const PluginManifestSchema = Type.Object({
|
|
116
|
+
id: PluginIdSchema,
|
|
117
|
+
name: NonWhitespaceStringSchema,
|
|
118
|
+
version: PluginVersionSchema,
|
|
119
|
+
pluginApiVersion: NonWhitespaceStringSchema,
|
|
120
|
+
entry: NonWhitespaceStringSchema,
|
|
121
|
+
moduleFederation: PluginModuleFederationManifestSchema,
|
|
122
|
+
agent: Type.Optional(PluginAgentManifestSchema),
|
|
123
|
+
styles: Type.Optional(Type.Array(NonWhitespaceStringSchema)),
|
|
124
|
+
permissions: Type.Optional(Type.Array(PluginPermissionSchema)),
|
|
125
|
+
network: Type.Optional(PluginNetworkManifestSchema),
|
|
126
|
+
browser: Type.Optional(PluginBrowserManifestSchema),
|
|
127
|
+
commands: Type.Optional(PluginCommandNamesSchema),
|
|
128
|
+
contributes: Type.Optional(Type.Object({
|
|
129
|
+
settings: Type.Optional(Type.Array(PluginSettingDefinitionSchema)),
|
|
130
|
+
}, { additionalProperties: true })),
|
|
131
|
+
description: Type.Optional(Type.String()),
|
|
132
|
+
author: Type.Optional(Type.String()),
|
|
133
|
+
icon: Type.Optional(NonWhitespaceStringSchema),
|
|
134
|
+
guidingWords: Type.Optional(Type.Array(NonWhitespaceStringSchema)),
|
|
135
|
+
defaultLocale: Type.Optional(Type.String({ minLength: 2, maxLength: 16, pattern: "^[a-zA-Z][a-zA-Z0-9-]{1,15}$" })),
|
|
136
|
+
contributionMode: Type.Optional(Type.Object({
|
|
137
|
+
hardIsolation: Type.Optional(Type.Boolean()),
|
|
138
|
+
}, { additionalProperties: true })),
|
|
139
|
+
agent_mode: OptionalAgentModesSchema,
|
|
140
|
+
}, {
|
|
141
|
+
$id: "PluginManifest",
|
|
142
|
+
additionalProperties: true,
|
|
143
|
+
description: "Vetta desktop plugin manifest (plugin.json).",
|
|
144
|
+
});
|
|
145
|
+
//# sourceMappingURL=manifest-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest-schema.js","sourceRoot":"","sources":["../src/manifest-schema.ts"],"names":[],"mappings":"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","sourcesContent":["import { Type, type Static } from \"@sinclair/typebox\";\nimport { PLUGIN_PERMISSIONS } from \"./permissions.js\";\n\nconst NON_WHITESPACE_PATTERN = \"\\\\S\";\n\nexport const PluginIdSchema = Type.String({\n\tminLength: 1,\n\tmaxLength: 64,\n\tpattern: \"^[a-z0-9][a-z0-9._-]{0,63}$\",\n\tdescription: \"Stable lowercase plugin identifier.\",\n});\n\nexport const PluginVersionSchema = Type.String({\n\tminLength: 1,\n\tmaxLength: 64,\n\tpattern: \"^[a-zA-Z0-9][a-zA-Z0-9._+-]{0,63}$\",\n\tdescription: \"Plugin version without path separators.\",\n});\n\nexport const PluginCommandNameSchema = Type.String({\n\tminLength: 1,\n\tmaxLength: 64,\n\tpattern: \"^[a-zA-Z0-9][a-zA-Z0-9._+-]{0,63}$\",\n\tdescription: \"Bare executable name declared by the plugin.\",\n});\n\nexport const PluginCommandNamesSchema = Type.Array(PluginCommandNameSchema);\n\nexport const PluginNetworkManifestSchema = Type.Object(\n\t{\n\t\tallowedHosts: Type.Array(Type.String({ minLength: 1, maxLength: 253, pattern: NON_WHITESPACE_PATTERN }), {\n\t\t\tminItems: 1,\n\t\t\tmaxItems: 128,\n\t\t}),\n\t},\n\t{ additionalProperties: true },\n);\n\nexport const PluginBrowserManifestSchema = Type.Object(\n\t{\n\t\tallowedHosts: Type.Array(Type.String({ minLength: 1, maxLength: 253, pattern: NON_WHITESPACE_PATTERN }), {\n\t\t\tminItems: 1,\n\t\t\tmaxItems: 128,\n\t\t}),\n\t},\n\t{ additionalProperties: true },\n);\n\nexport const PluginPermissionSchema = Type.Union(\n\tPLUGIN_PERMISSIONS.map((permission) => Type.Literal(permission)),\n\t{ description: \"Host capability requested by the plugin.\" },\n);\n\nconst NonWhitespaceStringSchema = Type.String({ pattern: NON_WHITESPACE_PATTERN });\nconst OptionalAgentModesSchema = Type.Optional(\n\tType.Union([NonWhitespaceStringSchema, Type.Array(NonWhitespaceStringSchema)]),\n);\nconst StringRecordSchema = Type.Record(Type.String(), Type.String());\n\nconst PluginSettingBaseProperties = {\n\tkey: NonWhitespaceStringSchema,\n\tdescription: Type.Optional(Type.String()),\n\tdefault: Type.Optional(Type.Union([Type.String(), Type.Number(), Type.Boolean()])),\n\tenum: Type.Optional(Type.Array(NonWhitespaceStringSchema)),\n\tvisibleWhen: Type.Optional(\n\t\tType.Object(\n\t\t\t{\n\t\t\t\tkey: NonWhitespaceStringSchema,\n\t\t\t\tin: Type.Array(NonWhitespaceStringSchema),\n\t\t\t},\n\t\t\t{ additionalProperties: true },\n\t\t),\n\t),\n};\n\nconst PluginInputSettingSchema = Type.Object(\n\t{\n\t\t...PluginSettingBaseProperties,\n\t\ttype: Type.Union([\n\t\t\tType.Literal(\"string\"),\n\t\t\tType.Literal(\"number\"),\n\t\t\tType.Literal(\"boolean\"),\n\t\t\tType.Literal(\"enum\"),\n\t\t\tType.Literal(\"secret\"),\n\t\t]),\n\t\ttitle: NonWhitespaceStringSchema,\n\t},\n\t{ additionalProperties: true },\n);\n\nconst PluginDescriptionSettingSchema = Type.Object(\n\t{\n\t\t...PluginSettingBaseProperties,\n\t\ttype: Type.Literal(\"desc\"),\n\t\ttitle: Type.Optional(Type.String()),\n\t},\n\t{ additionalProperties: true },\n);\n\nexport const PluginSettingDefinitionSchema = Type.Union([\n\tPluginInputSettingSchema,\n\tPluginDescriptionSettingSchema,\n]);\n\nconst PluginMcpCommonProperties = {\n\tdisabled: Type.Optional(Type.Boolean()),\n\tautoApprove: Type.Optional(Type.Array(NonWhitespaceStringSchema)),\n\tstartupTimeout: Type.Optional(Type.Number()),\n\tdebug: Type.Optional(Type.Boolean()),\n\tdisplayName: Type.Optional(Type.String()),\n\tdescription: Type.Optional(Type.String()),\n\tagent_mode: OptionalAgentModesSchema,\n};\n\nexport const PluginMcpStdioServerConfigSchema = Type.Object(\n\t{\n\t\t...PluginMcpCommonProperties,\n\t\ttype: Type.Optional(Type.Literal(\"stdio\")),\n\t\tcommand: NonWhitespaceStringSchema,\n\t\targs: Type.Optional(Type.Array(Type.String())),\n\t\tenv: Type.Optional(StringRecordSchema),\n\t\tcwd: Type.Optional(Type.String()),\n\t},\n\t{ additionalProperties: true },\n);\n\nexport const PluginMcpHttpServerConfigSchema = Type.Object(\n\t{\n\t\t...PluginMcpCommonProperties,\n\t\ttype: Type.Literal(\"http\"),\n\t\turl: NonWhitespaceStringSchema,\n\t\theaders: Type.Optional(StringRecordSchema),\n\t\toauthClientId: Type.Optional(Type.String()),\n\t\toauthDeviceFlow: Type.Optional(Type.Boolean()),\n\t\toauthScopes: Type.Optional(Type.String()),\n\t},\n\t{ additionalProperties: true },\n);\n\nexport const PluginMcpServerConfigSchema = Type.Union([\n\tPluginMcpStdioServerConfigSchema,\n\tPluginMcpHttpServerConfigSchema,\n]);\n\nconst PluginMcpServerMapSchema = Type.Record(\n\tType.String({ pattern: NON_WHITESPACE_PATTERN }),\n\tPluginMcpServerConfigSchema,\n\t{ additionalProperties: false },\n);\n\nexport const PluginAgentManifestSchema = Type.Object(\n\t{\n\t\tsystemPrompt: Type.Optional(\n\t\t\tType.Object(\n\t\t\t\t{\n\t\t\t\t\tpromptPaths: Type.Optional(Type.Array(NonWhitespaceStringSchema)),\n\t\t\t\t},\n\t\t\t\t{ additionalProperties: true },\n\t\t\t),\n\t\t),\n\t\tskillPaths: Type.Optional(Type.Array(NonWhitespaceStringSchema)),\n\t\tmcpServers: Type.Optional(Type.Union([NonWhitespaceStringSchema, PluginMcpServerMapSchema])),\n\t\ttoolPolicy: Type.Optional(\n\t\t\tType.Object(\n\t\t\t\t{\n\t\t\t\t\tallow: Type.Optional(Type.Array(NonWhitespaceStringSchema)),\n\t\t\t\t\tdeny: Type.Optional(Type.Array(NonWhitespaceStringSchema)),\n\t\t\t\t},\n\t\t\t\t{ additionalProperties: true },\n\t\t\t),\n\t\t),\n\t},\n\t{ additionalProperties: true },\n);\n\nexport const PluginModuleFederationManifestSchema = Type.Object(\n\t{\n\t\tremoteName: Type.String({ pattern: \"^[A-Za-z_$][A-Za-z0-9_$-]{0,63}$\" }),\n\t\texpose: Type.String({ pattern: \"^\\\\./(?!.*\\\\.\\\\.)(?!.*\\\\\\\\).+$\" }),\n\t},\n\t{ additionalProperties: true },\n);\n\nexport const PluginManifestSchema = Type.Object(\n\t{\n\t\tid: PluginIdSchema,\n\t\tname: NonWhitespaceStringSchema,\n\t\tversion: PluginVersionSchema,\n\t\tpluginApiVersion: NonWhitespaceStringSchema,\n\t\tentry: NonWhitespaceStringSchema,\n\t\tmoduleFederation: PluginModuleFederationManifestSchema,\n\t\tagent: Type.Optional(PluginAgentManifestSchema),\n\t\tstyles: Type.Optional(Type.Array(NonWhitespaceStringSchema)),\n\t\tpermissions: Type.Optional(Type.Array(PluginPermissionSchema)),\n\t\tnetwork: Type.Optional(PluginNetworkManifestSchema),\n\t\tbrowser: Type.Optional(PluginBrowserManifestSchema),\n\t\tcommands: Type.Optional(PluginCommandNamesSchema),\n\t\tcontributes: Type.Optional(\n\t\t\tType.Object(\n\t\t\t\t{\n\t\t\t\t\tsettings: Type.Optional(Type.Array(PluginSettingDefinitionSchema)),\n\t\t\t\t},\n\t\t\t\t{ additionalProperties: true },\n\t\t\t),\n\t\t),\n\t\tdescription: Type.Optional(Type.String()),\n\t\tauthor: Type.Optional(Type.String()),\n\t\ticon: Type.Optional(NonWhitespaceStringSchema),\n\t\tguidingWords: Type.Optional(Type.Array(NonWhitespaceStringSchema)),\n\t\tdefaultLocale: Type.Optional(\n\t\t\tType.String({ minLength: 2, maxLength: 16, pattern: \"^[a-zA-Z][a-zA-Z0-9-]{1,15}$\" }),\n\t\t),\n\t\tcontributionMode: Type.Optional(\n\t\t\tType.Object(\n\t\t\t\t{\n\t\t\t\t\thardIsolation: Type.Optional(Type.Boolean()),\n\t\t\t\t},\n\t\t\t\t{ additionalProperties: true },\n\t\t\t),\n\t\t),\n\t\tagent_mode: OptionalAgentModesSchema,\n\t},\n\t{\n\t\t$id: \"PluginManifest\",\n\t\tadditionalProperties: true,\n\t\tdescription: \"Vetta desktop plugin manifest (plugin.json).\",\n\t},\n);\n\nexport type PluginSettingSchema = Static<typeof PluginSettingDefinitionSchema>;\nexport type PluginMcpServerConfig = Static<typeof PluginMcpServerConfigSchema>;\nexport type PluginAgentManifest = Static<typeof PluginAgentManifestSchema>;\nexport type PluginNetworkManifest = Static<typeof PluginNetworkManifestSchema>;\nexport type PluginBrowserManifest = Static<typeof PluginBrowserManifestSchema>;\nexport type PluginManifestInput = Static<typeof PluginManifestSchema>;\nexport type PluginManifest = PluginManifestInput;\n"]}
|
package/dist/manifest.d.ts
CHANGED
|
@@ -1,57 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export type
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
cwd?: string;
|
|
11
|
-
disabled?: boolean;
|
|
12
|
-
autoApprove?: string[];
|
|
13
|
-
startupTimeout?: number;
|
|
14
|
-
debug?: boolean;
|
|
15
|
-
displayName?: string;
|
|
16
|
-
description?: string;
|
|
17
|
-
/** 该 server 的工具允许出现的工作模式 slug(agent_mode 轴,缺省/空 = 通用)。见 ADR-0046。 */
|
|
18
|
-
agent_mode?: string | string[];
|
|
19
|
-
} | {
|
|
20
|
-
type: "http";
|
|
21
|
-
url: string;
|
|
22
|
-
headers?: Record<string, string>;
|
|
23
|
-
oauthClientId?: string;
|
|
24
|
-
oauthDeviceFlow?: boolean;
|
|
25
|
-
oauthScopes?: string;
|
|
26
|
-
disabled?: boolean;
|
|
27
|
-
autoApprove?: string[];
|
|
28
|
-
startupTimeout?: number;
|
|
29
|
-
debug?: boolean;
|
|
30
|
-
displayName?: string;
|
|
31
|
-
description?: string;
|
|
32
|
-
/** 该 server 的工具允许出现的工作模式 slug(agent_mode 轴,缺省/空 = 通用)。见 ADR-0046。 */
|
|
33
|
-
agent_mode?: string | string[];
|
|
34
|
-
};
|
|
35
|
-
export interface PluginAgentManifest {
|
|
36
|
-
systemPrompt?: {
|
|
37
|
-
/**
|
|
38
|
-
* Plugin-packaged prompt contribution file paths. Main-process aggregation
|
|
39
|
-
* resolves these relative to the installed plugin root.
|
|
40
|
-
*/
|
|
41
|
-
promptPaths?: string[];
|
|
42
|
-
};
|
|
43
|
-
/** Plugin-packaged skill files or directories to add to the agent resource graph. */
|
|
44
|
-
skillPaths?: string[];
|
|
45
|
-
/**
|
|
46
|
-
* Plugin-scoped MCP servers. Either a relative path to `.mcp.json`
|
|
47
|
-
* (shape `{ mcpServers: { ... } }`) or an inline map of server configs.
|
|
48
|
-
* Requires permission `agent.mcp.control`. Never written into user mcp.json.
|
|
49
|
-
*/
|
|
50
|
-
mcpServers?: string | Record<string, PluginMcpServerConfig>;
|
|
51
|
-
/** Declarative tool visibility policy. Names are tool ids after registration. */
|
|
52
|
-
toolPolicy?: {
|
|
53
|
-
allow?: string[];
|
|
54
|
-
deny?: string[];
|
|
55
|
-
};
|
|
1
|
+
import { type PluginManifest, type PluginMcpServerConfig } from "./manifest-schema.js";
|
|
2
|
+
export { PluginAgentManifestSchema, PluginBrowserManifestSchema, PluginCommandNameSchema, PluginCommandNamesSchema, PluginIdSchema, PluginManifestSchema, PluginMcpHttpServerConfigSchema, PluginMcpServerConfigSchema, PluginMcpStdioServerConfigSchema, PluginModuleFederationManifestSchema, PluginNetworkManifestSchema, PluginPermissionSchema, PluginSettingDefinitionSchema, PluginVersionSchema, } from "./manifest-schema.js";
|
|
3
|
+
export type { PluginAgentManifest, PluginBrowserManifest, PluginManifest, PluginManifestInput, PluginMcpServerConfig, PluginNetworkManifest, PluginSettingSchema, } from "./manifest-schema.js";
|
|
4
|
+
export { PLUGIN_PERMISSIONS } from "./permissions.js";
|
|
5
|
+
export type { PluginPermission } from "./permissions.js";
|
|
6
|
+
export interface PluginManifestResourceReference {
|
|
7
|
+
field: string;
|
|
8
|
+
path: string;
|
|
9
|
+
kind: "file" | "file-or-directory";
|
|
56
10
|
}
|
|
11
|
+
export declare function validatePluginId(id: string): void;
|
|
12
|
+
export declare function validatePluginVersion(version: string): void;
|
|
13
|
+
export declare function validatePluginRelativePath(value: string, fieldName: string): string;
|
|
14
|
+
export declare function parsePluginCommandNames(value: unknown): string[];
|
|
15
|
+
/** @deprecated agent_mode 已无任何运行时语义(ADR-0071),保留仅为容忍既有 manifest。 */
|
|
16
|
+
export declare function normalizePluginAgentModes(value: unknown): string[] | undefined;
|
|
17
|
+
export declare function parsePluginMcpServerConfig(name: string, raw: unknown): PluginMcpServerConfig;
|
|
18
|
+
export declare function isPluginPassthroughIconRef(icon: string): boolean;
|
|
19
|
+
export declare function isPluginPackagedIconPath(icon: string): boolean;
|
|
20
|
+
export declare function parsePluginManifest(raw: unknown): PluginManifest;
|
|
21
|
+
export declare function listPluginManifestResources(manifest: PluginManifest): PluginManifestResourceReference[];
|
|
22
|
+
export declare function isPluginApiCompatible(hostVersion: string, range: string): boolean;
|
|
57
23
|
//# sourceMappingURL=manifest.d.ts.map
|
package/dist/manifest.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,MAAM,qBAAqB,GAC9B;IACA,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uHAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC9B,GACD;IACA,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uHAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC9B,CAAC;AAEL,MAAM,WAAW,mBAAmB;IACnC,YAAY,CAAC,EAAE;QACd;;;WAGG;QACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;KACvB,CAAC;IACF,qFAAqF;IACrF,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;IAC5D,iFAAiF;IACjF,UAAU,CAAC,EAAE;QACZ,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;QACjB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;KAChB,CAAC;CACF","sourcesContent":["/**\n * MCP server config declared inside a plugin (stdio or http). Relative paths in\n * stdio `command`/`args`/`cwd` are resolved against the plugin root at contribute time.\n */\nexport type PluginMcpServerConfig =\n\t| {\n\t\t\ttype?: \"stdio\";\n\t\t\tcommand: string;\n\t\t\targs?: string[];\n\t\t\tenv?: Record<string, string>;\n\t\t\tcwd?: string;\n\t\t\tdisabled?: boolean;\n\t\t\tautoApprove?: string[];\n\t\t\tstartupTimeout?: number;\n\t\t\tdebug?: boolean;\n\t\t\tdisplayName?: string;\n\t\t\tdescription?: string;\n\t\t\t/** 该 server 的工具允许出现的工作模式 slug(agent_mode 轴,缺省/空 = 通用)。见 ADR-0046。 */\n\t\t\tagent_mode?: string | string[];\n\t }\n\t| {\n\t\t\ttype: \"http\";\n\t\t\turl: string;\n\t\t\theaders?: Record<string, string>;\n\t\t\toauthClientId?: string;\n\t\t\toauthDeviceFlow?: boolean;\n\t\t\toauthScopes?: string;\n\t\t\tdisabled?: boolean;\n\t\t\tautoApprove?: string[];\n\t\t\tstartupTimeout?: number;\n\t\t\tdebug?: boolean;\n\t\t\tdisplayName?: string;\n\t\t\tdescription?: string;\n\t\t\t/** 该 server 的工具允许出现的工作模式 slug(agent_mode 轴,缺省/空 = 通用)。见 ADR-0046。 */\n\t\t\tagent_mode?: string | string[];\n\t };\n\nexport interface PluginAgentManifest {\n\tsystemPrompt?: {\n\t\t/**\n\t\t * Plugin-packaged prompt contribution file paths. Main-process aggregation\n\t\t * resolves these relative to the installed plugin root.\n\t\t */\n\t\tpromptPaths?: string[];\n\t};\n\t/** Plugin-packaged skill files or directories to add to the agent resource graph. */\n\tskillPaths?: string[];\n\t/**\n\t * Plugin-scoped MCP servers. Either a relative path to `.mcp.json`\n\t * (shape `{ mcpServers: { ... } }`) or an inline map of server configs.\n\t * Requires permission `agent.mcp.control`. Never written into user mcp.json.\n\t */\n\tmcpServers?: string | Record<string, PluginMcpServerConfig>;\n\t/** Declarative tool visibility policy. Names are tool ids after registration. */\n\ttoolPolicy?: {\n\t\tallow?: string[];\n\t\tdeny?: string[];\n\t};\n}\n"]}
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAGA,OAAO,EASN,KAAK,cAAc,EAEnB,KAAK,qBAAqB,EAG1B,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EACN,yBAAyB,EACzB,2BAA2B,EAC3B,uBAAuB,EACvB,wBAAwB,EACxB,cAAc,EACd,oBAAoB,EACpB,+BAA+B,EAC/B,2BAA2B,EAC3B,gCAAgC,EAChC,oCAAoC,EACpC,2BAA2B,EAC3B,sBAAsB,EACtB,6BAA6B,EAC7B,mBAAmB,GACnB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EACX,mBAAmB,EACnB,qBAAqB,EACrB,cAAc,EACd,mBAAmB,EACnB,qBAAqB,EACrB,qBAAqB,EACrB,mBAAmB,GACnB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,YAAY,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,MAAM,WAAW,+BAA+B;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,mBAAmB,CAAC;CACnC;AAuMD,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAIjD;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAI3D;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAiBnF;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,CAIhE;AAED,8GAAoE;AACpE,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,GAAG,SAAS,CAK9E;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,qBAAqB,CAG5F;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAMhE;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,cAAc,CAsDhE;AAED,wBAAgB,2BAA2B,CAC1C,QAAQ,EAAE,cAAc,GACtB,+BAA+B,EAAE,CAoBnC;AAkBD,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAWjF","sourcesContent":["import { type Static, type TSchema } from \"@sinclair/typebox\";\nimport type { ValueError } from \"@sinclair/typebox/errors\";\nimport { Value } from \"@sinclair/typebox/value\";\nimport {\n\tPluginCommandNameSchema,\n\tPluginCommandNamesSchema,\n\tPluginIdSchema,\n\tPluginManifestSchema,\n\tPluginMcpServerConfigSchema,\n\tPluginVersionSchema,\n\ttype PluginAgentManifest,\n\ttype PluginBrowserManifest,\n\ttype PluginManifest,\n\ttype PluginManifestInput,\n\ttype PluginMcpServerConfig,\n\ttype PluginNetworkManifest,\n\ttype PluginSettingSchema,\n} from \"./manifest-schema.js\";\nimport { PLUGIN_PERMISSIONS, type PluginPermission } from \"./permissions.js\";\n\nexport {\n\tPluginAgentManifestSchema,\n\tPluginBrowserManifestSchema,\n\tPluginCommandNameSchema,\n\tPluginCommandNamesSchema,\n\tPluginIdSchema,\n\tPluginManifestSchema,\n\tPluginMcpHttpServerConfigSchema,\n\tPluginMcpServerConfigSchema,\n\tPluginMcpStdioServerConfigSchema,\n\tPluginModuleFederationManifestSchema,\n\tPluginNetworkManifestSchema,\n\tPluginPermissionSchema,\n\tPluginSettingDefinitionSchema,\n\tPluginVersionSchema,\n} from \"./manifest-schema.js\";\nexport type {\n\tPluginAgentManifest,\n\tPluginBrowserManifest,\n\tPluginManifest,\n\tPluginManifestInput,\n\tPluginMcpServerConfig,\n\tPluginNetworkManifest,\n\tPluginSettingSchema,\n} from \"./manifest-schema.js\";\nexport { PLUGIN_PERMISSIONS } from \"./permissions.js\";\nexport type { PluginPermission } from \"./permissions.js\";\n\nexport interface PluginManifestResourceReference {\n\tfield: string;\n\tpath: string;\n\tkind: \"file\" | \"file-or-directory\";\n}\n\nfunction schemaErrorPath(path: string): string {\n\tif (!path) return \"\";\n\treturn path\n\t\t.split(\"/\")\n\t\t.slice(1)\n\t\t.map((segment) => segment.replace(/~1/g, \"/\").replace(/~0/g, \"~\"))\n\t\t.map((segment) => {\n\t\t\tif (segment === \"\") return '[\"\"]';\n\t\t\treturn /^\\d+$/.test(segment) ? `[${segment}]` : `.${segment}`;\n\t\t})\n\t\t.join(\"\");\n}\n\nfunction mostSpecificSchemaError(issue: ValueError): ValueError {\n\tconst nested = issue.errors.flatMap((iterator) =>\n\t\t[...iterator].map((child) => mostSpecificSchemaError(child)),\n\t);\n\tconst deeper = nested.filter((child) => child.path.length > issue.path.length);\n\tif (deeper.length === 0) return issue;\n\treturn deeper.reduce((best, child) => (child.path.length > best.path.length ? child : best));\n}\n\nfunction assertSchema<Schema extends TSchema>(\n\tschema: Schema,\n\tvalue: unknown,\n\tfieldName: string,\n): asserts value is Static<Schema> {\n\tif (Value.Check(schema, value)) return;\n\tconst firstIssue = Value.Errors(schema, value).First();\n\tconst issue = firstIssue ? mostSpecificSchemaError(firstIssue) : undefined;\n\tconst location = `${fieldName}${schemaErrorPath(issue?.path ?? \"\")}`;\n\tthrow new Error(`Invalid plugin ${location}: ${issue?.message ?? \"schema validation failed\"}`);\n}\n\nfunction trimString(value: string): string {\n\treturn value.trim();\n}\n\nfunction normalizeStringArray(values: string[] | undefined): string[] {\n\treturn (values ?? []).map(trimString);\n}\n\nfunction normalizeOptionalAgentModes(value: string | string[] | undefined): string | string[] | undefined {\n\tif (value === undefined) return undefined;\n\treturn Array.isArray(value) ? normalizeStringArray(value) : trimString(value);\n}\n\nfunction normalizeSetting(setting: PluginSettingSchema): PluginSettingSchema {\n\tconst common = {\n\t\tkey: trimString(setting.key),\n\t\tdescription: setting.description,\n\t\tdefault: setting.default,\n\t\tenum: setting.enum?.map(trimString),\n\t\tvisibleWhen: setting.visibleWhen\n\t\t\t? {\n\t\t\t\t\tkey: trimString(setting.visibleWhen.key),\n\t\t\t\t\tin: setting.visibleWhen.in.map(trimString),\n\t\t\t\t}\n\t\t\t: undefined,\n\t};\n\tif (setting.type === \"desc\") {\n\t\treturn {\n\t\t\t...common,\n\t\t\ttype: \"desc\",\n\t\t\ttitle: setting.title === undefined ? undefined : trimString(setting.title),\n\t\t};\n\t}\n\treturn {\n\t\t...common,\n\t\ttype: setting.type,\n\t\ttitle: trimString(setting.title),\n\t};\n}\n\nfunction normalizeSettings(settings: PluginSettingSchema[] | undefined): PluginSettingSchema[] | undefined {\n\tif (!settings || settings.length === 0) return undefined;\n\treturn settings.map(normalizeSetting);\n}\n\nfunction normalizePermissions(permissions: PluginPermission[] | undefined): PluginPermission[] {\n\treturn Array.from(new Set(permissions ?? []));\n}\n\nfunction normalizeAllowedHost(value: string, fieldName: \"network\" | \"browser\"): string {\n\tconst raw = trimString(value).toLowerCase();\n\tif (raw === \"*\") return raw;\n\tconst wildcard = raw.startsWith(\"*.\");\n\tconst candidate = wildcard ? raw.slice(2) : raw;\n\tif (!candidate || candidate.includes(\"*\") || /[\\\\/?#@]/.test(candidate)) {\n\t\tthrow new Error(`Invalid plugin ${fieldName}.allowedHosts entry: ${value}`);\n\t}\n\tconst unwrapped = candidate.startsWith(\"[\") && candidate.endsWith(\"]\") ? candidate.slice(1, -1) : candidate;\n\tif (wildcard && unwrapped.includes(\":\")) {\n\t\tthrow new Error(`Invalid plugin ${fieldName}.allowedHosts entry: ${value}`);\n\t}\n\ttry {\n\t\tconst parsed = new URL(`http://${unwrapped.includes(\":\") ? `[${unwrapped}]` : unwrapped}`);\n\t\tconst hostname = parsed.hostname.replace(/^\\[|\\]$/g, \"\").replace(/\\.$/, \"\").toLowerCase();\n\t\tif (!hostname || parsed.port || parsed.username || parsed.password) throw new Error(\"invalid host\");\n\t\treturn wildcard ? `*.${hostname}` : hostname;\n\t} catch {\n\t\tthrow new Error(`Invalid plugin ${fieldName}.allowedHosts entry: ${value}`);\n\t}\n}\n\nfunction normalizeNetworkManifest(network: PluginNetworkManifest | undefined): PluginNetworkManifest | undefined {\n\tif (!network) return undefined;\n\treturn { allowedHosts: Array.from(new Set(network.allowedHosts.map((host) => normalizeAllowedHost(host, \"network\")))) };\n}\n\nfunction normalizeBrowserManifest(browser: PluginBrowserManifest | undefined): PluginBrowserManifest | undefined {\n\tif (!browser) return undefined;\n\treturn { allowedHosts: Array.from(new Set(browser.allowedHosts.map((host) => normalizeAllowedHost(host, \"browser\")))) };\n}\n\nfunction normalizeModuleFederation(\n\tmoduleFederation: PluginManifestInput[\"moduleFederation\"],\n): PluginManifest[\"moduleFederation\"] {\n\treturn {\n\t\tremoteName: trimString(moduleFederation.remoteName),\n\t\texpose: trimString(moduleFederation.expose),\n\t};\n}\n\nfunction normalizeToolPolicy(\n\ttoolPolicy: PluginAgentManifest[\"toolPolicy\"],\n): PluginAgentManifest[\"toolPolicy\"] {\n\tif (!toolPolicy) return undefined;\n\treturn {\n\t\tallow: normalizeStringArray(toolPolicy.allow),\n\t\tdeny: normalizeStringArray(toolPolicy.deny),\n\t};\n}\n\nfunction normalizeMcpServers(\n\tmcpServers: PluginAgentManifest[\"mcpServers\"],\n): PluginAgentManifest[\"mcpServers\"] {\n\tif (mcpServers === undefined) return undefined;\n\tif (typeof mcpServers === \"string\") {\n\t\treturn validatePluginRelativePath(trimString(mcpServers), \"agent.mcpServers\");\n\t}\n\tconst result: Record<string, PluginMcpServerConfig> = {};\n\tfor (const [name, config] of Object.entries(mcpServers)) {\n\t\tresult[trimString(name)] = normalizePluginMcpServerConfig(config);\n\t}\n\treturn result;\n}\n\nfunction normalizeAgentManifest(agent: PluginAgentManifest | undefined): PluginAgentManifest | undefined {\n\tif (!agent) return undefined;\n\treturn {\n\t\tsystemPrompt: agent.systemPrompt\n\t\t\t? {\n\t\t\t\t\tpromptPaths: normalizeStringArray(agent.systemPrompt.promptPaths).map((path) =>\n\t\t\t\t\t\tvalidatePluginRelativePath(path, \"agent.systemPrompt.promptPaths\"),\n\t\t\t\t\t),\n\t\t\t\t}\n\t\t\t: undefined,\n\t\tskillPaths: normalizeStringArray(agent.skillPaths).map((path) =>\n\t\t\tvalidatePluginRelativePath(path, \"agent.skillPaths\"),\n\t\t),\n\t\tmcpServers: normalizeMcpServers(agent.mcpServers),\n\t\ttoolPolicy: normalizeToolPolicy(agent.toolPolicy),\n\t};\n}\n\nfunction normalizePluginMcpServerConfig(config: PluginMcpServerConfig): PluginMcpServerConfig {\n\tconst common = {\n\t\tdisabled: config.disabled,\n\t\tautoApprove: config.autoApprove?.map(trimString),\n\t\tstartupTimeout: config.startupTimeout,\n\t\tdebug: config.debug,\n\t\tdisplayName: config.displayName,\n\t\tdescription: config.description,\n\t\tagent_mode: normalizeOptionalAgentModes(config.agent_mode),\n\t};\n\tif (config.type === \"http\") {\n\t\treturn {\n\t\t\ttype: \"http\",\n\t\t\turl: trimString(config.url),\n\t\t\theaders: config.headers ? { ...config.headers } : undefined,\n\t\t\toauthClientId: config.oauthClientId,\n\t\t\toauthDeviceFlow: config.oauthDeviceFlow,\n\t\t\toauthScopes: config.oauthScopes,\n\t\t\t...common,\n\t\t};\n\t}\n\treturn {\n\t\ttype: config.type,\n\t\tcommand: trimString(config.command),\n\t\targs: config.args ? [...config.args] : undefined,\n\t\tenv: config.env ? { ...config.env } : undefined,\n\t\tcwd: config.cwd,\n\t\t...common,\n\t};\n}\n\nexport function validatePluginId(id: string): void {\n\tif (!Value.Check(PluginIdSchema, id)) {\n\t\tthrow new Error(\"Plugin id must be 1-64 chars: lowercase letters, numbers, dot, underscore, or dash\");\n\t}\n}\n\nexport function validatePluginVersion(version: string): void {\n\tif (!Value.Check(PluginVersionSchema, version)) {\n\t\tthrow new Error(\"Plugin version must be 1-64 chars and cannot contain path separators\");\n\t}\n}\n\nexport function validatePluginRelativePath(value: string, fieldName: string): string {\n\tif (value.startsWith(\"/\") || /^[a-zA-Z]:/.test(value)) {\n\t\tthrow new Error(`Invalid plugin ${fieldName}`);\n\t}\n\tconst parts: string[] = [];\n\tfor (const part of value.replace(/\\\\/g, \"/\").split(\"/\")) {\n\t\tif (part === \"\" || part === \".\") continue;\n\t\tif (part === \"..\") {\n\t\t\tif (parts.length === 0) throw new Error(`Invalid plugin ${fieldName}`);\n\t\t\tparts.pop();\n\t\t\tcontinue;\n\t\t}\n\t\tparts.push(part);\n\t}\n\tconst normalized = parts.join(\"/\");\n\tif (!normalized) throw new Error(`Invalid plugin ${fieldName}`);\n\treturn normalized;\n}\n\nexport function parsePluginCommandNames(value: unknown): string[] {\n\tif (value === undefined) return [];\n\tassertSchema(PluginCommandNamesSchema, value, \"commands\");\n\treturn Array.from(new Set(value));\n}\n\n/** @deprecated agent_mode 已无任何运行时语义(ADR-0071),保留仅为容忍既有 manifest。 */\nexport function normalizePluginAgentModes(value: unknown): string[] | undefined {\n\tif (value === undefined || value === null) return undefined;\n\tconst values = Array.isArray(value) ? value : [value];\n\tconst modes = values.map((item) => String(item).trim()).filter(Boolean);\n\treturn modes.length > 0 ? modes : undefined;\n}\n\nexport function parsePluginMcpServerConfig(name: string, raw: unknown): PluginMcpServerConfig {\n\tassertSchema(PluginMcpServerConfigSchema, raw, `MCP server '${name}'`);\n\treturn normalizePluginMcpServerConfig(raw);\n}\n\nexport function isPluginPassthroughIconRef(icon: string): boolean {\n\treturn (\n\t\ticon.startsWith(\"http://\") ||\n\t\ticon.startsWith(\"https://\") ||\n\t\t/^[a-z0-9]+(?:-[a-z0-9]+)*:[a-z0-9]+(?:-[a-z0-9]+)*$/.test(icon)\n\t);\n}\n\nexport function isPluginPackagedIconPath(icon: string): boolean {\n\treturn !isPluginPassthroughIconRef(icon);\n}\n\nexport function parsePluginManifest(raw: unknown): PluginManifest {\n\tif (typeof raw === \"object\" && raw !== null && \"runtime\" in raw) {\n\t\tthrow new Error(\n\t\t\t'Invalid plugin manifest.runtime: runtime selection is unsupported; plugins use Module Federation.',\n\t\t);\n\t}\n\tassertSchema(PluginManifestSchema, raw, \"manifest\");\n\tconst commands = parsePluginCommandNames(raw.commands);\n\tconst icon = raw.icon === undefined ? undefined : trimString(raw.icon);\n\tconst permissions = normalizePermissions(raw.permissions);\n\tconst network = normalizeNetworkManifest(raw.network);\n\tconst browser = normalizeBrowserManifest(raw.browser);\n\tif (permissions.includes(\"network.fetch\") && !network) {\n\t\tthrow new Error(\"Plugin network.allowedHosts is required with network.fetch\");\n\t}\n\tconst browserPermissions = permissions.filter((permission) => permission.startsWith(\"browser.\"));\n\tif (browserPermissions.length > 0 && !browser) {\n\t\tthrow new Error(\"Plugin browser.allowedHosts is required with browser permissions\");\n\t}\n\tif (permissions.includes(\"browser.interact\") && !permissions.includes(\"browser.read\")) {\n\t\tthrow new Error(\"Plugin browser.interact requires browser.read\");\n\t}\n\treturn {\n\t\tid: raw.id,\n\t\tname: trimString(raw.name),\n\t\tversion: raw.version,\n\t\tpluginApiVersion: trimString(raw.pluginApiVersion),\n\t\tentry: validatePluginRelativePath(trimString(raw.entry), \"entry\"),\n\t\tmoduleFederation: normalizeModuleFederation(raw.moduleFederation),\n\t\tagent: normalizeAgentManifest(raw.agent),\n\t\tstyles: normalizeStringArray(raw.styles).map((style) => validatePluginRelativePath(style, \"styles\")),\n\t\tpermissions,\n\t\tnetwork,\n\t\tbrowser,\n\t\tcommands: commands.length > 0 ? commands : undefined,\n\t\tcontributes: raw.contributes\n\t\t\t? (() => {\n\t\t\t\t\tconst settings = normalizeSettings(raw.contributes.settings);\n\t\t\t\t\treturn settings ? { settings } : undefined;\n\t\t\t\t})()\n\t\t\t: undefined,\n\t\tdescription: raw.description,\n\t\tauthor: raw.author,\n\t\ticon:\n\t\t\ticon === undefined || isPluginPassthroughIconRef(icon)\n\t\t\t\t? icon\n\t\t\t\t: validatePluginRelativePath(icon, \"icon\"),\n\t\tguidingWords: raw.guidingWords?.map(trimString),\n\t\tdefaultLocale: raw.defaultLocale ?? \"zh\",\n\t\tcontributionMode: raw.contributionMode\n\t\t\t? { hardIsolation: raw.contributionMode.hardIsolation === true }\n\t\t\t: undefined,\n\t\tagent_mode: normalizePluginAgentModes(raw.agent_mode),\n\t};\n}\n\nexport function listPluginManifestResources(\n\tmanifest: PluginManifest,\n): PluginManifestResourceReference[] {\n\tconst resources: PluginManifestResourceReference[] = [\n\t\t{ field: \"entry\", path: manifest.entry, kind: \"file\" },\n\t];\n\tfor (const stylePath of manifest.styles ?? []) {\n\t\tresources.push({ field: \"styles\", path: stylePath, kind: \"file\" });\n\t}\n\tif (manifest.icon && isPluginPackagedIconPath(manifest.icon)) {\n\t\tresources.push({ field: \"icon\", path: manifest.icon, kind: \"file\" });\n\t}\n\tfor (const promptPath of manifest.agent?.systemPrompt?.promptPaths ?? []) {\n\t\tresources.push({ field: \"agent.systemPrompt.promptPaths\", path: promptPath, kind: \"file-or-directory\" });\n\t}\n\tfor (const skillPath of manifest.agent?.skillPaths ?? []) {\n\t\tresources.push({ field: \"agent.skillPaths\", path: skillPath, kind: \"file-or-directory\" });\n\t}\n\tif (typeof manifest.agent?.mcpServers === \"string\") {\n\t\tresources.push({ field: \"agent.mcpServers\", path: manifest.agent.mcpServers, kind: \"file\" });\n\t}\n\treturn resources;\n}\n\nfunction parseApiVersion(value: string): readonly [number, number, number] | undefined {\n\tconst match = /^(\\d+)\\.(\\d+)\\.(\\d+)$/.exec(value);\n\tif (!match) return undefined;\n\treturn [Number(match[1]), Number(match[2]), Number(match[3])];\n}\n\nfunction compareApiVersions(\n\tleft: readonly [number, number, number],\n\tright: readonly [number, number, number],\n): number {\n\tfor (let index = 0; index < left.length; index += 1) {\n\t\tif (left[index] !== right[index]) return left[index] - right[index];\n\t}\n\treturn 0;\n}\n\nexport function isPluginApiCompatible(hostVersion: string, range: string): boolean {\n\tconst host = parseApiVersion(hostVersion);\n\tif (!host) return false;\n\tconst normalized = range.trim();\n\tconst exact = parseApiVersion(normalized);\n\tif (exact) return exact[0] === host[0] && compareApiVersions(host, exact) >= 0;\n\tconst caret = normalized.startsWith(\"^\") ? parseApiVersion(normalized.slice(1)) : undefined;\n\tif (caret) return caret[0] === host[0] && compareApiVersions(host, caret) >= 0;\n\tif (normalized === `^${host[0]}` || normalized === `${host[0]}.x`) return true;\n\tconst minimum = normalized.startsWith(\">=\") ? parseApiVersion(normalized.slice(2)) : undefined;\n\treturn minimum !== undefined && compareApiVersions(host, minimum) >= 0;\n}\n"]}
|
package/dist/manifest.js
CHANGED
|
@@ -1,2 +1,343 @@
|
|
|
1
|
-
|
|
1
|
+
import { Value } from "@sinclair/typebox/value";
|
|
2
|
+
import { PluginCommandNamesSchema, PluginIdSchema, PluginManifestSchema, PluginMcpServerConfigSchema, PluginVersionSchema, } from "./manifest-schema.js";
|
|
3
|
+
import "./permissions.js";
|
|
4
|
+
export { PluginAgentManifestSchema, PluginBrowserManifestSchema, PluginCommandNameSchema, PluginCommandNamesSchema, PluginIdSchema, PluginManifestSchema, PluginMcpHttpServerConfigSchema, PluginMcpServerConfigSchema, PluginMcpStdioServerConfigSchema, PluginModuleFederationManifestSchema, PluginNetworkManifestSchema, PluginPermissionSchema, PluginSettingDefinitionSchema, PluginVersionSchema, } from "./manifest-schema.js";
|
|
5
|
+
export { PLUGIN_PERMISSIONS } from "./permissions.js";
|
|
6
|
+
function schemaErrorPath(path) {
|
|
7
|
+
if (!path)
|
|
8
|
+
return "";
|
|
9
|
+
return path
|
|
10
|
+
.split("/")
|
|
11
|
+
.slice(1)
|
|
12
|
+
.map((segment) => segment.replace(/~1/g, "/").replace(/~0/g, "~"))
|
|
13
|
+
.map((segment) => {
|
|
14
|
+
if (segment === "")
|
|
15
|
+
return '[""]';
|
|
16
|
+
return /^\d+$/.test(segment) ? `[${segment}]` : `.${segment}`;
|
|
17
|
+
})
|
|
18
|
+
.join("");
|
|
19
|
+
}
|
|
20
|
+
function mostSpecificSchemaError(issue) {
|
|
21
|
+
const nested = issue.errors.flatMap((iterator) => [...iterator].map((child) => mostSpecificSchemaError(child)));
|
|
22
|
+
const deeper = nested.filter((child) => child.path.length > issue.path.length);
|
|
23
|
+
if (deeper.length === 0)
|
|
24
|
+
return issue;
|
|
25
|
+
return deeper.reduce((best, child) => (child.path.length > best.path.length ? child : best));
|
|
26
|
+
}
|
|
27
|
+
function assertSchema(schema, value, fieldName) {
|
|
28
|
+
if (Value.Check(schema, value))
|
|
29
|
+
return;
|
|
30
|
+
const firstIssue = Value.Errors(schema, value).First();
|
|
31
|
+
const issue = firstIssue ? mostSpecificSchemaError(firstIssue) : undefined;
|
|
32
|
+
const location = `${fieldName}${schemaErrorPath(issue?.path ?? "")}`;
|
|
33
|
+
throw new Error(`Invalid plugin ${location}: ${issue?.message ?? "schema validation failed"}`);
|
|
34
|
+
}
|
|
35
|
+
function trimString(value) {
|
|
36
|
+
return value.trim();
|
|
37
|
+
}
|
|
38
|
+
function normalizeStringArray(values) {
|
|
39
|
+
return (values ?? []).map(trimString);
|
|
40
|
+
}
|
|
41
|
+
function normalizeOptionalAgentModes(value) {
|
|
42
|
+
if (value === undefined)
|
|
43
|
+
return undefined;
|
|
44
|
+
return Array.isArray(value) ? normalizeStringArray(value) : trimString(value);
|
|
45
|
+
}
|
|
46
|
+
function normalizeSetting(setting) {
|
|
47
|
+
const common = {
|
|
48
|
+
key: trimString(setting.key),
|
|
49
|
+
description: setting.description,
|
|
50
|
+
default: setting.default,
|
|
51
|
+
enum: setting.enum?.map(trimString),
|
|
52
|
+
visibleWhen: setting.visibleWhen
|
|
53
|
+
? {
|
|
54
|
+
key: trimString(setting.visibleWhen.key),
|
|
55
|
+
in: setting.visibleWhen.in.map(trimString),
|
|
56
|
+
}
|
|
57
|
+
: undefined,
|
|
58
|
+
};
|
|
59
|
+
if (setting.type === "desc") {
|
|
60
|
+
return {
|
|
61
|
+
...common,
|
|
62
|
+
type: "desc",
|
|
63
|
+
title: setting.title === undefined ? undefined : trimString(setting.title),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
...common,
|
|
68
|
+
type: setting.type,
|
|
69
|
+
title: trimString(setting.title),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function normalizeSettings(settings) {
|
|
73
|
+
if (!settings || settings.length === 0)
|
|
74
|
+
return undefined;
|
|
75
|
+
return settings.map(normalizeSetting);
|
|
76
|
+
}
|
|
77
|
+
function normalizePermissions(permissions) {
|
|
78
|
+
return Array.from(new Set(permissions ?? []));
|
|
79
|
+
}
|
|
80
|
+
function normalizeAllowedHost(value, fieldName) {
|
|
81
|
+
const raw = trimString(value).toLowerCase();
|
|
82
|
+
if (raw === "*")
|
|
83
|
+
return raw;
|
|
84
|
+
const wildcard = raw.startsWith("*.");
|
|
85
|
+
const candidate = wildcard ? raw.slice(2) : raw;
|
|
86
|
+
if (!candidate || candidate.includes("*") || /[\\/?#@]/.test(candidate)) {
|
|
87
|
+
throw new Error(`Invalid plugin ${fieldName}.allowedHosts entry: ${value}`);
|
|
88
|
+
}
|
|
89
|
+
const unwrapped = candidate.startsWith("[") && candidate.endsWith("]") ? candidate.slice(1, -1) : candidate;
|
|
90
|
+
if (wildcard && unwrapped.includes(":")) {
|
|
91
|
+
throw new Error(`Invalid plugin ${fieldName}.allowedHosts entry: ${value}`);
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
const parsed = new URL(`http://${unwrapped.includes(":") ? `[${unwrapped}]` : unwrapped}`);
|
|
95
|
+
const hostname = parsed.hostname.replace(/^\[|\]$/g, "").replace(/\.$/, "").toLowerCase();
|
|
96
|
+
if (!hostname || parsed.port || parsed.username || parsed.password)
|
|
97
|
+
throw new Error("invalid host");
|
|
98
|
+
return wildcard ? `*.${hostname}` : hostname;
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
throw new Error(`Invalid plugin ${fieldName}.allowedHosts entry: ${value}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function normalizeNetworkManifest(network) {
|
|
105
|
+
if (!network)
|
|
106
|
+
return undefined;
|
|
107
|
+
return { allowedHosts: Array.from(new Set(network.allowedHosts.map((host) => normalizeAllowedHost(host, "network")))) };
|
|
108
|
+
}
|
|
109
|
+
function normalizeBrowserManifest(browser) {
|
|
110
|
+
if (!browser)
|
|
111
|
+
return undefined;
|
|
112
|
+
return { allowedHosts: Array.from(new Set(browser.allowedHosts.map((host) => normalizeAllowedHost(host, "browser")))) };
|
|
113
|
+
}
|
|
114
|
+
function normalizeModuleFederation(moduleFederation) {
|
|
115
|
+
return {
|
|
116
|
+
remoteName: trimString(moduleFederation.remoteName),
|
|
117
|
+
expose: trimString(moduleFederation.expose),
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function normalizeToolPolicy(toolPolicy) {
|
|
121
|
+
if (!toolPolicy)
|
|
122
|
+
return undefined;
|
|
123
|
+
return {
|
|
124
|
+
allow: normalizeStringArray(toolPolicy.allow),
|
|
125
|
+
deny: normalizeStringArray(toolPolicy.deny),
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
function normalizeMcpServers(mcpServers) {
|
|
129
|
+
if (mcpServers === undefined)
|
|
130
|
+
return undefined;
|
|
131
|
+
if (typeof mcpServers === "string") {
|
|
132
|
+
return validatePluginRelativePath(trimString(mcpServers), "agent.mcpServers");
|
|
133
|
+
}
|
|
134
|
+
const result = {};
|
|
135
|
+
for (const [name, config] of Object.entries(mcpServers)) {
|
|
136
|
+
result[trimString(name)] = normalizePluginMcpServerConfig(config);
|
|
137
|
+
}
|
|
138
|
+
return result;
|
|
139
|
+
}
|
|
140
|
+
function normalizeAgentManifest(agent) {
|
|
141
|
+
if (!agent)
|
|
142
|
+
return undefined;
|
|
143
|
+
return {
|
|
144
|
+
systemPrompt: agent.systemPrompt
|
|
145
|
+
? {
|
|
146
|
+
promptPaths: normalizeStringArray(agent.systemPrompt.promptPaths).map((path) => validatePluginRelativePath(path, "agent.systemPrompt.promptPaths")),
|
|
147
|
+
}
|
|
148
|
+
: undefined,
|
|
149
|
+
skillPaths: normalizeStringArray(agent.skillPaths).map((path) => validatePluginRelativePath(path, "agent.skillPaths")),
|
|
150
|
+
mcpServers: normalizeMcpServers(agent.mcpServers),
|
|
151
|
+
toolPolicy: normalizeToolPolicy(agent.toolPolicy),
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
function normalizePluginMcpServerConfig(config) {
|
|
155
|
+
const common = {
|
|
156
|
+
disabled: config.disabled,
|
|
157
|
+
autoApprove: config.autoApprove?.map(trimString),
|
|
158
|
+
startupTimeout: config.startupTimeout,
|
|
159
|
+
debug: config.debug,
|
|
160
|
+
displayName: config.displayName,
|
|
161
|
+
description: config.description,
|
|
162
|
+
agent_mode: normalizeOptionalAgentModes(config.agent_mode),
|
|
163
|
+
};
|
|
164
|
+
if (config.type === "http") {
|
|
165
|
+
return {
|
|
166
|
+
type: "http",
|
|
167
|
+
url: trimString(config.url),
|
|
168
|
+
headers: config.headers ? { ...config.headers } : undefined,
|
|
169
|
+
oauthClientId: config.oauthClientId,
|
|
170
|
+
oauthDeviceFlow: config.oauthDeviceFlow,
|
|
171
|
+
oauthScopes: config.oauthScopes,
|
|
172
|
+
...common,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
return {
|
|
176
|
+
type: config.type,
|
|
177
|
+
command: trimString(config.command),
|
|
178
|
+
args: config.args ? [...config.args] : undefined,
|
|
179
|
+
env: config.env ? { ...config.env } : undefined,
|
|
180
|
+
cwd: config.cwd,
|
|
181
|
+
...common,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
export function validatePluginId(id) {
|
|
185
|
+
if (!Value.Check(PluginIdSchema, id)) {
|
|
186
|
+
throw new Error("Plugin id must be 1-64 chars: lowercase letters, numbers, dot, underscore, or dash");
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
export function validatePluginVersion(version) {
|
|
190
|
+
if (!Value.Check(PluginVersionSchema, version)) {
|
|
191
|
+
throw new Error("Plugin version must be 1-64 chars and cannot contain path separators");
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
export function validatePluginRelativePath(value, fieldName) {
|
|
195
|
+
if (value.startsWith("/") || /^[a-zA-Z]:/.test(value)) {
|
|
196
|
+
throw new Error(`Invalid plugin ${fieldName}`);
|
|
197
|
+
}
|
|
198
|
+
const parts = [];
|
|
199
|
+
for (const part of value.replace(/\\/g, "/").split("/")) {
|
|
200
|
+
if (part === "" || part === ".")
|
|
201
|
+
continue;
|
|
202
|
+
if (part === "..") {
|
|
203
|
+
if (parts.length === 0)
|
|
204
|
+
throw new Error(`Invalid plugin ${fieldName}`);
|
|
205
|
+
parts.pop();
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
parts.push(part);
|
|
209
|
+
}
|
|
210
|
+
const normalized = parts.join("/");
|
|
211
|
+
if (!normalized)
|
|
212
|
+
throw new Error(`Invalid plugin ${fieldName}`);
|
|
213
|
+
return normalized;
|
|
214
|
+
}
|
|
215
|
+
export function parsePluginCommandNames(value) {
|
|
216
|
+
if (value === undefined)
|
|
217
|
+
return [];
|
|
218
|
+
assertSchema(PluginCommandNamesSchema, value, "commands");
|
|
219
|
+
return Array.from(new Set(value));
|
|
220
|
+
}
|
|
221
|
+
/** @deprecated agent_mode 已无任何运行时语义(ADR-0071),保留仅为容忍既有 manifest。 */
|
|
222
|
+
export function normalizePluginAgentModes(value) {
|
|
223
|
+
if (value === undefined || value === null)
|
|
224
|
+
return undefined;
|
|
225
|
+
const values = Array.isArray(value) ? value : [value];
|
|
226
|
+
const modes = values.map((item) => String(item).trim()).filter(Boolean);
|
|
227
|
+
return modes.length > 0 ? modes : undefined;
|
|
228
|
+
}
|
|
229
|
+
export function parsePluginMcpServerConfig(name, raw) {
|
|
230
|
+
assertSchema(PluginMcpServerConfigSchema, raw, `MCP server '${name}'`);
|
|
231
|
+
return normalizePluginMcpServerConfig(raw);
|
|
232
|
+
}
|
|
233
|
+
export function isPluginPassthroughIconRef(icon) {
|
|
234
|
+
return (icon.startsWith("http://") ||
|
|
235
|
+
icon.startsWith("https://") ||
|
|
236
|
+
/^[a-z0-9]+(?:-[a-z0-9]+)*:[a-z0-9]+(?:-[a-z0-9]+)*$/.test(icon));
|
|
237
|
+
}
|
|
238
|
+
export function isPluginPackagedIconPath(icon) {
|
|
239
|
+
return !isPluginPassthroughIconRef(icon);
|
|
240
|
+
}
|
|
241
|
+
export function parsePluginManifest(raw) {
|
|
242
|
+
if (typeof raw === "object" && raw !== null && "runtime" in raw) {
|
|
243
|
+
throw new Error('Invalid plugin manifest.runtime: runtime selection is unsupported; plugins use Module Federation.');
|
|
244
|
+
}
|
|
245
|
+
assertSchema(PluginManifestSchema, raw, "manifest");
|
|
246
|
+
const commands = parsePluginCommandNames(raw.commands);
|
|
247
|
+
const icon = raw.icon === undefined ? undefined : trimString(raw.icon);
|
|
248
|
+
const permissions = normalizePermissions(raw.permissions);
|
|
249
|
+
const network = normalizeNetworkManifest(raw.network);
|
|
250
|
+
const browser = normalizeBrowserManifest(raw.browser);
|
|
251
|
+
if (permissions.includes("network.fetch") && !network) {
|
|
252
|
+
throw new Error("Plugin network.allowedHosts is required with network.fetch");
|
|
253
|
+
}
|
|
254
|
+
const browserPermissions = permissions.filter((permission) => permission.startsWith("browser."));
|
|
255
|
+
if (browserPermissions.length > 0 && !browser) {
|
|
256
|
+
throw new Error("Plugin browser.allowedHosts is required with browser permissions");
|
|
257
|
+
}
|
|
258
|
+
if (permissions.includes("browser.interact") && !permissions.includes("browser.read")) {
|
|
259
|
+
throw new Error("Plugin browser.interact requires browser.read");
|
|
260
|
+
}
|
|
261
|
+
return {
|
|
262
|
+
id: raw.id,
|
|
263
|
+
name: trimString(raw.name),
|
|
264
|
+
version: raw.version,
|
|
265
|
+
pluginApiVersion: trimString(raw.pluginApiVersion),
|
|
266
|
+
entry: validatePluginRelativePath(trimString(raw.entry), "entry"),
|
|
267
|
+
moduleFederation: normalizeModuleFederation(raw.moduleFederation),
|
|
268
|
+
agent: normalizeAgentManifest(raw.agent),
|
|
269
|
+
styles: normalizeStringArray(raw.styles).map((style) => validatePluginRelativePath(style, "styles")),
|
|
270
|
+
permissions,
|
|
271
|
+
network,
|
|
272
|
+
browser,
|
|
273
|
+
commands: commands.length > 0 ? commands : undefined,
|
|
274
|
+
contributes: raw.contributes
|
|
275
|
+
? (() => {
|
|
276
|
+
const settings = normalizeSettings(raw.contributes.settings);
|
|
277
|
+
return settings ? { settings } : undefined;
|
|
278
|
+
})()
|
|
279
|
+
: undefined,
|
|
280
|
+
description: raw.description,
|
|
281
|
+
author: raw.author,
|
|
282
|
+
icon: icon === undefined || isPluginPassthroughIconRef(icon)
|
|
283
|
+
? icon
|
|
284
|
+
: validatePluginRelativePath(icon, "icon"),
|
|
285
|
+
guidingWords: raw.guidingWords?.map(trimString),
|
|
286
|
+
defaultLocale: raw.defaultLocale ?? "zh",
|
|
287
|
+
contributionMode: raw.contributionMode
|
|
288
|
+
? { hardIsolation: raw.contributionMode.hardIsolation === true }
|
|
289
|
+
: undefined,
|
|
290
|
+
agent_mode: normalizePluginAgentModes(raw.agent_mode),
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
export function listPluginManifestResources(manifest) {
|
|
294
|
+
const resources = [
|
|
295
|
+
{ field: "entry", path: manifest.entry, kind: "file" },
|
|
296
|
+
];
|
|
297
|
+
for (const stylePath of manifest.styles ?? []) {
|
|
298
|
+
resources.push({ field: "styles", path: stylePath, kind: "file" });
|
|
299
|
+
}
|
|
300
|
+
if (manifest.icon && isPluginPackagedIconPath(manifest.icon)) {
|
|
301
|
+
resources.push({ field: "icon", path: manifest.icon, kind: "file" });
|
|
302
|
+
}
|
|
303
|
+
for (const promptPath of manifest.agent?.systemPrompt?.promptPaths ?? []) {
|
|
304
|
+
resources.push({ field: "agent.systemPrompt.promptPaths", path: promptPath, kind: "file-or-directory" });
|
|
305
|
+
}
|
|
306
|
+
for (const skillPath of manifest.agent?.skillPaths ?? []) {
|
|
307
|
+
resources.push({ field: "agent.skillPaths", path: skillPath, kind: "file-or-directory" });
|
|
308
|
+
}
|
|
309
|
+
if (typeof manifest.agent?.mcpServers === "string") {
|
|
310
|
+
resources.push({ field: "agent.mcpServers", path: manifest.agent.mcpServers, kind: "file" });
|
|
311
|
+
}
|
|
312
|
+
return resources;
|
|
313
|
+
}
|
|
314
|
+
function parseApiVersion(value) {
|
|
315
|
+
const match = /^(\d+)\.(\d+)\.(\d+)$/.exec(value);
|
|
316
|
+
if (!match)
|
|
317
|
+
return undefined;
|
|
318
|
+
return [Number(match[1]), Number(match[2]), Number(match[3])];
|
|
319
|
+
}
|
|
320
|
+
function compareApiVersions(left, right) {
|
|
321
|
+
for (let index = 0; index < left.length; index += 1) {
|
|
322
|
+
if (left[index] !== right[index])
|
|
323
|
+
return left[index] - right[index];
|
|
324
|
+
}
|
|
325
|
+
return 0;
|
|
326
|
+
}
|
|
327
|
+
export function isPluginApiCompatible(hostVersion, range) {
|
|
328
|
+
const host = parseApiVersion(hostVersion);
|
|
329
|
+
if (!host)
|
|
330
|
+
return false;
|
|
331
|
+
const normalized = range.trim();
|
|
332
|
+
const exact = parseApiVersion(normalized);
|
|
333
|
+
if (exact)
|
|
334
|
+
return exact[0] === host[0] && compareApiVersions(host, exact) >= 0;
|
|
335
|
+
const caret = normalized.startsWith("^") ? parseApiVersion(normalized.slice(1)) : undefined;
|
|
336
|
+
if (caret)
|
|
337
|
+
return caret[0] === host[0] && compareApiVersions(host, caret) >= 0;
|
|
338
|
+
if (normalized === `^${host[0]}` || normalized === `${host[0]}.x`)
|
|
339
|
+
return true;
|
|
340
|
+
const minimum = normalized.startsWith(">=") ? parseApiVersion(normalized.slice(2)) : undefined;
|
|
341
|
+
return minimum !== undefined && compareApiVersions(host, minimum) >= 0;
|
|
342
|
+
}
|
|
2
343
|
//# sourceMappingURL=manifest.js.map
|