@zhama/tego-plugin-sdk 0.0.0-stage → 1.36.1
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/LICENSE +172 -0
- package/README.md +846 -2
- package/access-catalog.schema.json +304 -0
- package/access-fixtures/resolve.json +1359 -0
- package/bin/tego-plugin-pack.mjs +2 -0
- package/bin/tego-plugin.mjs +3 -0
- package/dist/access-drizzle.cjs +1 -0
- package/dist/access-drizzle.d.cts +726 -0
- package/dist/access-drizzle.d.ts +726 -0
- package/dist/access-drizzle.js +1 -0
- package/dist/access-hono.cjs +3 -0
- package/dist/access-hono.d.cts +108 -0
- package/dist/access-hono.d.ts +108 -0
- package/dist/access-hono.js +3 -0
- package/dist/access-implications.cjs +1 -0
- package/dist/access-implications.d.cts +25 -0
- package/dist/access-implications.d.ts +25 -0
- package/dist/access-implications.js +1 -0
- package/dist/access.cjs +26 -0
- package/dist/access.d.cts +884 -0
- package/dist/access.d.ts +884 -0
- package/dist/access.js +26 -0
- package/dist/catalog-CSSbrfEf.d.cts +361 -0
- package/dist/catalog-CSSbrfEf.d.ts +361 -0
- package/dist/chunk-3KUOBGJN.js +19 -0
- package/dist/chunk-3WA3M347.cjs +1 -0
- package/dist/chunk-5CU33JVY.js +1 -0
- package/dist/chunk-7K37PVGV.js +5 -0
- package/dist/chunk-7XHF3YSK.js +1 -0
- package/dist/chunk-AJY7ZHXK.cjs +3 -0
- package/dist/chunk-BN6TGHSB.cjs +1 -0
- package/dist/chunk-BTHXQWHT.js +1 -0
- package/dist/chunk-C2OCOPZQ.cjs +1 -0
- package/dist/chunk-IMAVYQ4U.cjs +4 -0
- package/dist/chunk-OP64Y4IN.cjs +1 -0
- package/dist/chunk-QKSPPMVN.js +1 -0
- package/dist/chunk-ROFUQLOZ.cjs +1 -0
- package/dist/chunk-SNUCO2MK.js +1 -0
- package/dist/chunk-THMWRUAT.cjs +19 -0
- package/dist/chunk-VMCGDDGP.js +3 -0
- package/dist/chunk-W7C357A6.cjs +5 -0
- package/dist/chunk-WLTASJF6.js +4 -0
- package/dist/egress.cjs +7 -0
- package/dist/egress.d.cts +9 -0
- package/dist/egress.d.ts +9 -0
- package/dist/egress.js +7 -0
- package/dist/frontend.cjs +2 -0
- package/dist/frontend.d.cts +353 -0
- package/dist/frontend.d.ts +353 -0
- package/dist/frontend.js +2 -0
- package/dist/gateway-signature.cjs +1 -0
- package/dist/gateway-signature.d.cts +112 -0
- package/dist/gateway-signature.d.ts +112 -0
- package/dist/gateway-signature.js +1 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +528 -0
- package/dist/index.d.ts +528 -0
- package/dist/index.js +1 -0
- package/dist/manifest-types-DQARCQJt.d.cts +627 -0
- package/dist/manifest-types-DQARCQJt.d.ts +627 -0
- package/dist/manifest.cjs +1 -0
- package/dist/manifest.d.cts +2824 -0
- package/dist/manifest.d.ts +2824 -0
- package/dist/manifest.js +1 -0
- package/dist/mcp-identity.cjs +2 -0
- package/dist/mcp-identity.d.cts +106 -0
- package/dist/mcp-identity.d.ts +106 -0
- package/dist/mcp-identity.js +2 -0
- package/dist/pack.cjs +1 -0
- package/dist/pack.d.cts +169 -0
- package/dist/pack.d.ts +169 -0
- package/dist/pack.js +1 -0
- package/dist/publish.cjs +1 -0
- package/dist/publish.d.cts +96 -0
- package/dist/publish.d.ts +96 -0
- package/dist/publish.js +1 -0
- package/dist/scaffold.cjs +523 -0
- package/dist/scaffold.d.cts +182 -0
- package/dist/scaffold.d.ts +182 -0
- package/dist/scaffold.js +523 -0
- package/dist/server-runtime.cjs +1 -0
- package/dist/server-runtime.d.cts +63 -0
- package/dist/server-runtime.d.ts +63 -0
- package/dist/server-runtime.js +1 -0
- package/dist/server.cjs +1 -0
- package/dist/server.d.cts +1808 -0
- package/dist/server.d.ts +1808 -0
- package/dist/server.js +1 -0
- package/dist/testing.cjs +2 -0
- package/dist/testing.d.cts +92 -0
- package/dist/testing.d.ts +92 -0
- package/dist/testing.js +2 -0
- package/dist/vite.cjs +1 -0
- package/dist/vite.d.cts +133 -0
- package/dist/vite.d.ts +133 -0
- package/dist/vite.js +1 -0
- package/package.json +160 -4
- package/sql/access.sql +73 -0
|
@@ -0,0 +1,627 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Operator-supplied configuration, declared per part.
|
|
3
|
+
*
|
|
4
|
+
* Three sections, never one. A plugin's browser code, its backend process and
|
|
5
|
+
* its claw extension are three different audiences, and folding their settings
|
|
6
|
+
* into a single object makes "does the frontend get to see this API key" a
|
|
7
|
+
* question answered by remembering to strip a field before responding. Split,
|
|
8
|
+
* the frontend simply has no path to the other two.
|
|
9
|
+
*
|
|
10
|
+
* The frontend and backend sections are declared here, in `tego.plugin.json`.
|
|
11
|
+
* The claw section is not: `claw/openclaw.plugin.json` already carries a
|
|
12
|
+
* `configSchema`, claw itself validates against it, and a second declaration
|
|
13
|
+
* would be a second truth about the same fields.
|
|
14
|
+
*
|
|
15
|
+
* ## Why the schema subset is this narrow
|
|
16
|
+
*
|
|
17
|
+
* A flat object of scalars, string enums and string arrays. Two reasons, and
|
|
18
|
+
* the second is the load-bearing one:
|
|
19
|
+
*
|
|
20
|
+
* - The form has to render without an author previewing it. Anything the
|
|
21
|
+
* renderer would fall back to a JSON textarea for is a field the operator
|
|
22
|
+
* fills by typing JSON, which is not a form.
|
|
23
|
+
* - Per-avatar claw overrides merge at top-level key granularity, on purpose:
|
|
24
|
+
* deep-merging nested objects and arrays has no single obvious semantics.
|
|
25
|
+
* A nested object would therefore be replaced wholesale by an override,
|
|
26
|
+
* which is not what its shape suggests. Refusing nesting keeps the storage
|
|
27
|
+
* model and the declaration honest with each other.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
/** The three audiences a plugin's settings can belong to. */
|
|
31
|
+
declare const PLUGIN_CONFIG_SECTIONS: readonly ["frontend", "backend", "claw"];
|
|
32
|
+
type PluginConfigSection = (typeof PLUGIN_CONFIG_SECTIONS)[number];
|
|
33
|
+
/**
|
|
34
|
+
* Stands in for a stored secret whenever a value leaves the server towards a
|
|
35
|
+
* human.
|
|
36
|
+
*
|
|
37
|
+
* The same string claw uses, deliberately: a secret that survived a round trip
|
|
38
|
+
* through one console and got clobbered by the other would be the worst
|
|
39
|
+
* possible outcome of having two sentinels. Writing it back means "leave the
|
|
40
|
+
* stored value alone".
|
|
41
|
+
*/
|
|
42
|
+
declare const PLUGIN_CONFIG_SECRET_SENTINEL = "__OPENCLAW_REDACTED__";
|
|
43
|
+
type PluginConfigFieldType = 'string' | 'number' | 'integer' | 'boolean' | 'array';
|
|
44
|
+
/** One field. Flat by construction — no `properties`, no `$ref`, no unions. */
|
|
45
|
+
interface PluginConfigFieldSchema {
|
|
46
|
+
type: PluginConfigFieldType;
|
|
47
|
+
title?: string;
|
|
48
|
+
description?: string;
|
|
49
|
+
default?: unknown;
|
|
50
|
+
/** Closed set of allowed values. Strings and numbers only. */
|
|
51
|
+
enum?: (string | number)[];
|
|
52
|
+
minLength?: number;
|
|
53
|
+
maxLength?: number;
|
|
54
|
+
pattern?: string;
|
|
55
|
+
format?: 'uri' | 'email';
|
|
56
|
+
minimum?: number;
|
|
57
|
+
maximum?: number;
|
|
58
|
+
/** Required for `type: "array"`, and only a string element is supported. */
|
|
59
|
+
items?: {
|
|
60
|
+
type: 'string';
|
|
61
|
+
enum?: string[];
|
|
62
|
+
};
|
|
63
|
+
maxItems?: number;
|
|
64
|
+
}
|
|
65
|
+
interface PluginConfigSchema {
|
|
66
|
+
type: 'object';
|
|
67
|
+
properties: Record<string, PluginConfigFieldSchema>;
|
|
68
|
+
required?: string[];
|
|
69
|
+
/** Always false: an operator cannot invent a key the plugin never reads. */
|
|
70
|
+
additionalProperties?: false;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* How one field is presented.
|
|
74
|
+
*
|
|
75
|
+
* `label` and `help` are {@link LocalizedText} because the platform ships ten
|
|
76
|
+
* languages and a plugin's settings screen has no reason to be the one part of
|
|
77
|
+
* it that is English-only. A plain string still works and means "the same in
|
|
78
|
+
* every language", which is right for a field named after a protocol.
|
|
79
|
+
*/
|
|
80
|
+
interface PluginConfigUiHint {
|
|
81
|
+
label?: LocalizedText;
|
|
82
|
+
help?: LocalizedText;
|
|
83
|
+
placeholder?: LocalizedText;
|
|
84
|
+
order?: number;
|
|
85
|
+
/** Collapsed by default. For knobs with a sane default nobody should touch. */
|
|
86
|
+
advanced?: boolean;
|
|
87
|
+
/**
|
|
88
|
+
* Stored encrypted, never returned in plaintext, never placed in the
|
|
89
|
+
* container environment.
|
|
90
|
+
*
|
|
91
|
+
* Illegal in the frontend section: that section is delivered to the browser
|
|
92
|
+
* in full, so a secret there is public by construction. Validation rejects
|
|
93
|
+
* it rather than quietly stripping the flag.
|
|
94
|
+
*/
|
|
95
|
+
sensitive?: boolean;
|
|
96
|
+
}
|
|
97
|
+
interface PluginConfigDeclaration {
|
|
98
|
+
schema: PluginConfigSchema;
|
|
99
|
+
uiHints?: Record<string, PluginConfigUiHint>;
|
|
100
|
+
}
|
|
101
|
+
/** What the install screen says about one section, without opening a schema. */
|
|
102
|
+
interface PluginConfigSectionSummary {
|
|
103
|
+
fieldCount: number;
|
|
104
|
+
/** Property names the section cannot run without. */
|
|
105
|
+
required: string[];
|
|
106
|
+
/** Property names stored encrypted. */
|
|
107
|
+
sensitive: string[];
|
|
108
|
+
}
|
|
109
|
+
declare const EMPTY_CONFIG_SECTION_SUMMARY: PluginConfigSectionSummary;
|
|
110
|
+
declare function summarizeConfigDeclaration(declaration: PluginConfigDeclaration | undefined): PluginConfigSectionSummary;
|
|
111
|
+
/**
|
|
112
|
+
* The same summary for the claw section, read out of an OpenClaw manifest.
|
|
113
|
+
*
|
|
114
|
+
* Separate because that schema is not held to the subset above — claw owns it,
|
|
115
|
+
* and holding an already-valid OpenClaw extension to a Tego-only restriction
|
|
116
|
+
* would refuse packages claw itself runs. Anything nested is counted at the
|
|
117
|
+
* top level and rendered by the form's own fallback.
|
|
118
|
+
*/
|
|
119
|
+
declare function summarizeClawConfig(clawManifest: Record<string, unknown> | null): PluginConfigSectionSummary;
|
|
120
|
+
/**
|
|
121
|
+
* Replace every stored secret with the sentinel.
|
|
122
|
+
*
|
|
123
|
+
* Applied on the way out to any human-facing surface. Keys absent from the
|
|
124
|
+
* stored value stay absent — writing a sentinel for a secret nobody has set
|
|
125
|
+
* would make the form show a filled field the operator cannot clear.
|
|
126
|
+
*/
|
|
127
|
+
declare function redactSecrets(value: Record<string, unknown>, sensitive: readonly string[]): Record<string, unknown>;
|
|
128
|
+
/**
|
|
129
|
+
* Put the stored secret back wherever the submitted value is the sentinel.
|
|
130
|
+
*
|
|
131
|
+
* The inverse of {@link redactSecrets}, and the reason a form can be saved
|
|
132
|
+
* without the operator retyping every key it never showed them.
|
|
133
|
+
*
|
|
134
|
+
* A sentinel with no stored counterpart is dropped rather than saved
|
|
135
|
+
* literally: it means the form rendered a value that has since been deleted,
|
|
136
|
+
* and persisting the marker itself would give the plugin a password of
|
|
137
|
+
* `__OPENCLAW_REDACTED__`.
|
|
138
|
+
*/
|
|
139
|
+
declare function restoreSecrets(submitted: Record<string, unknown>, stored: Record<string, unknown>, sensitive: readonly string[]): Record<string, unknown>;
|
|
140
|
+
/**
|
|
141
|
+
* Fill in declared defaults for keys the operator left unset.
|
|
142
|
+
*
|
|
143
|
+
* `properties` is defaulted although the type requires it: the claw section's
|
|
144
|
+
* schema is whatever an OpenClaw manifest declares, which this type describes
|
|
145
|
+
* but does not enforce, and a schema of `{"type":"object"}` would otherwise
|
|
146
|
+
* throw here rather than simply having no defaults to apply.
|
|
147
|
+
*/
|
|
148
|
+
declare function applyConfigDefaults(schema: PluginConfigSchema, value: Record<string, unknown>): Record<string, unknown>;
|
|
149
|
+
/** A hint's label in one language, falling back to the property name. */
|
|
150
|
+
declare function configFieldLabel(name: string, hint: PluginConfigUiHint | undefined, field: PluginConfigFieldSchema | undefined, locale: string): string;
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* `tego.plugin.json` — the one manifest every Tego plugin ships.
|
|
154
|
+
*
|
|
155
|
+
* A plugin is a single archive containing up to three parts: a frontend module
|
|
156
|
+
* loaded into the host shell, a backend process the platform runs, and an
|
|
157
|
+
* OpenClaw extension loaded by claw containers. At least one part is required;
|
|
158
|
+
* a plugin with only `claw` is exactly what the ecosystem uploads today.
|
|
159
|
+
*
|
|
160
|
+
* The claw part keeps its own upstream `openclaw.plugin.json` untouched inside
|
|
161
|
+
* its subdirectory. This manifest wraps it rather than replacing it, so claw's
|
|
162
|
+
* loader and this platform never have to agree on a schema.
|
|
163
|
+
*/
|
|
164
|
+
|
|
165
|
+
/** A display string, either a single value or one per locale tag. */
|
|
166
|
+
type LocalizedText = string | Record<string, string>;
|
|
167
|
+
/**
|
|
168
|
+
* Icon names a nav entry may choose from.
|
|
169
|
+
*
|
|
170
|
+
* A closed list rather than "any `lucide-react` name", because resolving an
|
|
171
|
+
* arbitrary string to a component means importing the whole icon set into the
|
|
172
|
+
* shell — which is why every plugin entry used to render the same generic
|
|
173
|
+
* puzzle piece. A fixed list is a static map the bundler can shake.
|
|
174
|
+
*
|
|
175
|
+
* Adding a name is a minor host API bump: older shells would render the
|
|
176
|
+
* fallback for an icon they have no entry for.
|
|
177
|
+
*/
|
|
178
|
+
declare const PLUGIN_NAV_ICONS: readonly ["bar-chart", "bell", "bookmark", "book-open", "bot", "briefcase", "building", "calendar", "chart-pie", "clipboard-list", "clock", "contact", "credit-card", "database", "file-text", "folder", "globe", "handshake", "inbox", "key", "layers", "layout-dashboard", "library", "link", "list-todo", "mail", "map-pin", "message-square", "mic", "package", "phone", "puzzle", "receipt", "search", "settings", "shield", "shopping-cart", "sliders", "sparkles", "star", "table", "tag", "target", "trending-up", "truck", "users", "wallet", "workflow", "wrench", "zap"];
|
|
179
|
+
type PluginNavIcon = (typeof PLUGIN_NAV_ICONS)[number];
|
|
180
|
+
/** Rendered for an entry that names no icon. */
|
|
181
|
+
declare const PLUGIN_NAV_ICON_FALLBACK: PluginNavIcon;
|
|
182
|
+
/**
|
|
183
|
+
* One page a frontend part registers.
|
|
184
|
+
*
|
|
185
|
+
* These are not sidebar rows. The shell gives a plugin exactly one row —
|
|
186
|
+
* itself — which opens the plugin at its root; the plugin routes its pages
|
|
187
|
+
* from there. A plugin with at least one entry gets that row.
|
|
188
|
+
*
|
|
189
|
+
* Entries do not gate access. Who may open a plugin follows the AI employees
|
|
190
|
+
* it is installed on (tenant-scoped plugins are open to the whole tenant),
|
|
191
|
+
* and the host writes no role menu or permission for them.
|
|
192
|
+
*/
|
|
193
|
+
interface PluginNavEntry {
|
|
194
|
+
/** Stable identifier within the plugin; what `ctx.can(key)` checks. */
|
|
195
|
+
key: string;
|
|
196
|
+
/** i18n key resolved against the plugin's own bundle, not the host's. */
|
|
197
|
+
labelKey: string;
|
|
198
|
+
/**
|
|
199
|
+
* Kept for manifest compatibility; the host does not read it. The sidebar
|
|
200
|
+
* row's icon is the frontend part's own `icon`.
|
|
201
|
+
*/
|
|
202
|
+
icon?: PluginNavIcon;
|
|
203
|
+
/** Kept for manifest compatibility; the host does not read it. */
|
|
204
|
+
order?: number;
|
|
205
|
+
/** Subpath under `/p/<pluginId>`. Defaults to the plugin root. */
|
|
206
|
+
path?: string;
|
|
207
|
+
}
|
|
208
|
+
interface PluginFrontendPart {
|
|
209
|
+
/** Directory inside the archive. Defaults to `frontend`. */
|
|
210
|
+
dir?: string;
|
|
211
|
+
/** SystemJS entry relative to `dir`. Defaults to `index.js`. */
|
|
212
|
+
entry?: string;
|
|
213
|
+
/** Locale JSON directory relative to `dir`. Defaults to `i18n`. */
|
|
214
|
+
i18nDir?: string;
|
|
215
|
+
/**
|
|
216
|
+
* The plugin's icon in the shell's sidebar. Defaults to the generic plugin
|
|
217
|
+
* icon.
|
|
218
|
+
*
|
|
219
|
+
* Declared here and not taken from `nav`, because the row stands for the
|
|
220
|
+
* plugin rather than for any one of its pages: borrowing the first page's
|
|
221
|
+
* icon would put a dashboard glyph next to "CRM" only because the author
|
|
222
|
+
* happened to list the dashboard first.
|
|
223
|
+
*/
|
|
224
|
+
icon?: PluginNavIcon;
|
|
225
|
+
nav?: PluginNavEntry[];
|
|
226
|
+
/**
|
|
227
|
+
* Settings delivered to the browser alongside discovery.
|
|
228
|
+
*
|
|
229
|
+
* Public by construction — anything here reaches the page — so a
|
|
230
|
+
* `sensitive` hint in this section is a validation error rather than a
|
|
231
|
+
* field that gets quietly stripped.
|
|
232
|
+
*/
|
|
233
|
+
config?: PluginConfigDeclaration;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Resource caps for the backend process.
|
|
237
|
+
*
|
|
238
|
+
* Only what the orchestrator actually applies. Egress controls used to be
|
|
239
|
+
* declarable here and were enforced nowhere — a field that reads as a network
|
|
240
|
+
* policy while every host stays reachable is worse than no field, because it
|
|
241
|
+
* is the one an operator would rely on.
|
|
242
|
+
*/
|
|
243
|
+
interface PluginBackendLimits {
|
|
244
|
+
memoryMb?: number;
|
|
245
|
+
cpuMs?: number;
|
|
246
|
+
requestTimeoutMs?: number;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Language runtime of the backend process.
|
|
250
|
+
*
|
|
251
|
+
* Each value maps to one platform-owned runner image; a package never ships
|
|
252
|
+
* its own. See `docs/architecture/plugin-backend-protocol.md`.
|
|
253
|
+
*/
|
|
254
|
+
type PluginBackendRuntime = 'node' | 'python';
|
|
255
|
+
declare const PLUGIN_BACKEND_RUNTIMES: readonly PluginBackendRuntime[];
|
|
256
|
+
type PluginBackendPlatform = 'linux/amd64' | 'linux/arm64';
|
|
257
|
+
declare const PLUGIN_BACKEND_PLATFORMS: readonly PluginBackendPlatform[];
|
|
258
|
+
type PluginPublicRouteMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
259
|
+
/**
|
|
260
|
+
* One anonymous entry point into the backend.
|
|
261
|
+
*
|
|
262
|
+
* `path` is literal segments and `:name` parameters, e.g.
|
|
263
|
+
* `/public/inspections/:token`. The gateway forwards only requests that match
|
|
264
|
+
* a declaration; everything else under the public prefix is a 404 that never
|
|
265
|
+
* reaches the plugin.
|
|
266
|
+
*/
|
|
267
|
+
interface PluginPublicRoute {
|
|
268
|
+
method: PluginPublicRouteMethod;
|
|
269
|
+
path: string;
|
|
270
|
+
}
|
|
271
|
+
interface PluginSchemaRepair {
|
|
272
|
+
id: string;
|
|
273
|
+
/** SQL generated from an isolated legacy schema, relative to backend dir. */
|
|
274
|
+
sqlFile: string;
|
|
275
|
+
table: string;
|
|
276
|
+
column: string;
|
|
277
|
+
postgresType: 'integer' | 'text' | 'boolean' | 'bigint' | 'jsonb';
|
|
278
|
+
}
|
|
279
|
+
interface PluginBackendPart {
|
|
280
|
+
/** Directory inside the archive. Defaults to `backend`. */
|
|
281
|
+
dir?: string;
|
|
282
|
+
/** Defaults to `node`. */
|
|
283
|
+
runtime?: PluginBackendRuntime;
|
|
284
|
+
/**
|
|
285
|
+
* Entry relative to `dir`. Defaults to `index.js` for node and `app.py` for
|
|
286
|
+
* python.
|
|
287
|
+
*/
|
|
288
|
+
entry?: string;
|
|
289
|
+
/**
|
|
290
|
+
* CPU architectures the package's vendored wheels cover. Python only, and
|
|
291
|
+
* defaults to both: a release that installs on one node pool and not the
|
|
292
|
+
* other fails at the worst possible moment.
|
|
293
|
+
*/
|
|
294
|
+
platforms?: PluginBackendPlatform[];
|
|
295
|
+
/**
|
|
296
|
+
* Exact outbound targets. A bare hostname means HTTPS 443; hostname:port
|
|
297
|
+
* and IP:port permit that specific port through the platform egress proxy.
|
|
298
|
+
* A lone `*` permits every routable target and port, including private IPs.
|
|
299
|
+
*/
|
|
300
|
+
egress?: string[];
|
|
301
|
+
/**
|
|
302
|
+
* Append-only SQL directory relative to `dir`, applied by the host into the
|
|
303
|
+
* plugin's dedicated schema. Defaults to `migrations`.
|
|
304
|
+
*/
|
|
305
|
+
migrationsDir?: string;
|
|
306
|
+
compatibilityRepairs?: PluginSchemaRepair[];
|
|
307
|
+
/** Readiness path the runtime polls. Defaults to `/healthz`. */
|
|
308
|
+
healthPath?: string;
|
|
309
|
+
limits?: PluginBackendLimits;
|
|
310
|
+
/**
|
|
311
|
+
* Routes anyone may call without signing in — a QR code scanned on a
|
|
312
|
+
* phone, a link sent to a contractor. Avatar plugins require a bound and
|
|
313
|
+
* enabled employee in the public URL (or an existing legacy target).
|
|
314
|
+
* Each request carries a signed anonymous context; the plugin verifies its token.
|
|
315
|
+
*/
|
|
316
|
+
publicRoutes?: PluginPublicRoute[];
|
|
317
|
+
/**
|
|
318
|
+
* Settings the backend process reads at startup.
|
|
319
|
+
*
|
|
320
|
+
* Fetched over the host API rather than injected as environment variables:
|
|
321
|
+
* env is visible to `docker inspect`, to the orchestrator's API and to crash
|
|
322
|
+
* dumps, and it is fixed at container creation, so rotating a key would mean
|
|
323
|
+
* recreating the container.
|
|
324
|
+
*
|
|
325
|
+
* A required field with no value leaves the install in `awaiting_config` —
|
|
326
|
+
* installed, no container, and an explanation instead of a 502.
|
|
327
|
+
*/
|
|
328
|
+
config?: PluginConfigDeclaration;
|
|
329
|
+
}
|
|
330
|
+
interface PluginClawHooks {
|
|
331
|
+
allowPromptInjection?: boolean;
|
|
332
|
+
allowConversationAccess?: boolean;
|
|
333
|
+
}
|
|
334
|
+
interface PluginClawPart {
|
|
335
|
+
/** Runtime hook access disclosed by the installed package. */
|
|
336
|
+
hooks?: PluginClawHooks;
|
|
337
|
+
/** Directory inside the archive holding an intact OpenClaw extension. */
|
|
338
|
+
dir?: string;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* A static site served to anonymous visitors — the pages behind
|
|
342
|
+
* `publicRoutes`. Built with its own dependencies, not against the host's
|
|
343
|
+
* shared modules: nobody signed in means no shell to load into.
|
|
344
|
+
*/
|
|
345
|
+
interface PluginPublicFrontendPart {
|
|
346
|
+
/** Directory inside the archive holding `index.html`. Defaults to `public-frontend`. */
|
|
347
|
+
dir?: string;
|
|
348
|
+
}
|
|
349
|
+
interface PluginParts {
|
|
350
|
+
frontend?: PluginFrontendPart;
|
|
351
|
+
backend?: PluginBackendPart;
|
|
352
|
+
claw?: PluginClawPart;
|
|
353
|
+
publicFrontend?: PluginPublicFrontendPart;
|
|
354
|
+
}
|
|
355
|
+
interface PluginPermissions {
|
|
356
|
+
required?: string[];
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* The plugin's own roles and permissions, enforced by its backend through
|
|
360
|
+
* `@tego/plugin-sdk/access`.
|
|
361
|
+
*
|
|
362
|
+
* `catalog` is a path inside the package, so the same file the backend is
|
|
363
|
+
* built from is the one upload validates and discloses. Accounts still come
|
|
364
|
+
* from the host; the catalog only says what they may do inside this plugin.
|
|
365
|
+
*/
|
|
366
|
+
interface PluginAccess {
|
|
367
|
+
catalog: string;
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Who a plugin belongs to once installed.
|
|
371
|
+
*
|
|
372
|
+
* `avatar` — the plugin is a capability of a digital avatar. Install picks
|
|
373
|
+
* which avatars get it, and its pages are visible while one of those is
|
|
374
|
+
* active.
|
|
375
|
+
*
|
|
376
|
+
* `tenant` — a workspace-wide application with no per-avatar meaning. Visible
|
|
377
|
+
* to everyone in the tenant who holds the menu permission. A claw part on a
|
|
378
|
+
* tenant-scoped plugin goes to every avatar in the tenant, including avatars
|
|
379
|
+
* created later: nobody picks avatars, so nobody can forget the new ones.
|
|
380
|
+
*
|
|
381
|
+
* Declared, never inferred. "Has a claw part" happens to correlate today, but
|
|
382
|
+
* a frontend-only reporting page over the same backend is tenant-scoped, and
|
|
383
|
+
* guessing wrong means the plugin is either invisible or visible to everyone.
|
|
384
|
+
*/
|
|
385
|
+
type PluginScope = 'avatar' | 'tenant';
|
|
386
|
+
/**
|
|
387
|
+
* What installing this plugin will bring, shown to the operator before they
|
|
388
|
+
* confirm.
|
|
389
|
+
*
|
|
390
|
+
* These are **disclosures**, not grants. Plugins are first-party and the
|
|
391
|
+
* frontend runs with the shell's own privileges, so calling them permissions
|
|
392
|
+
* would promise an isolation boundary that does not exist. `database` is the
|
|
393
|
+
* exception that also changes behaviour, because provisioning a schema is a
|
|
394
|
+
* thing the host does or does not do.
|
|
395
|
+
*/
|
|
396
|
+
interface PluginDeclares {
|
|
397
|
+
/**
|
|
398
|
+
* The backend gets a dedicated Postgres schema and a role scoped to it, and
|
|
399
|
+
* the host applies the package's migrations into it.
|
|
400
|
+
*
|
|
401
|
+
* Defaults to true when a backend part exists, which is what the platform
|
|
402
|
+
* has always done. A backend that only proxies or computes sets it false and
|
|
403
|
+
* then finds `host.db` unavailable.
|
|
404
|
+
*/
|
|
405
|
+
database?: boolean;
|
|
406
|
+
/**
|
|
407
|
+
* The backend stores objects through the host storage API, under a prefix
|
|
408
|
+
* derived from the install.
|
|
409
|
+
*
|
|
410
|
+
* A byte budget is deliberately not declarable: nothing accounts total usage
|
|
411
|
+
* yet, and a number no one enforces reads as a cap. The per-object ceiling
|
|
412
|
+
* the host does enforce is a platform constant, not a plugin's choice.
|
|
413
|
+
*/
|
|
414
|
+
storage?: boolean;
|
|
415
|
+
/**
|
|
416
|
+
* The backend publishes `plugin.<id>.*` events to the tenant's subscribers.
|
|
417
|
+
*
|
|
418
|
+
* Publish-only. Plugin backends cannot subscribe to platform events.
|
|
419
|
+
*/
|
|
420
|
+
events?: boolean;
|
|
421
|
+
/** The backend may send durable, recipient-scoped messages to the host inbox. */
|
|
422
|
+
notifications?: boolean;
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Business wording for a plugin tool in the audit trail. Without it an auditor
|
|
426
|
+
* sees `crm_query_customer {"id":"C123"}`; with it, "查询客户 C123 的持仓".
|
|
427
|
+
*/
|
|
428
|
+
interface PluginAuditToolDeclaration {
|
|
429
|
+
category?: 'read' | 'write' | 'search' | 'browse' | 'exec' | 'knowledge' | 'memory' | 'message' | 'schedule' | 'delegate' | 'document' | 'plugin';
|
|
430
|
+
/** Template with `{param}` placeholders filled from the call parameters. */
|
|
431
|
+
title?: LocalizedText;
|
|
432
|
+
/** Parameter naming the business object, e.g. `customerId`. */
|
|
433
|
+
target?: string;
|
|
434
|
+
/** `high` raises a risk flag on every call. */
|
|
435
|
+
risk?: 'low' | 'medium' | 'high';
|
|
436
|
+
/** Data classes touched, e.g. `pii`, `account`, `trade`. */
|
|
437
|
+
dataClasses?: string[];
|
|
438
|
+
}
|
|
439
|
+
interface PluginAuditDeclarations {
|
|
440
|
+
/** Keyed by the tool name the claw part registers. */
|
|
441
|
+
tools?: Record<string, PluginAuditToolDeclaration>;
|
|
442
|
+
}
|
|
443
|
+
interface PluginAgentReadinessDeclaration {
|
|
444
|
+
/** Backend route path (relative to plugin root) returning PluginAgentReadinessResponse. */
|
|
445
|
+
path: string;
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Text fields are `LocalizedText`: the host picks the viewer's locale, then
|
|
449
|
+
* `en`. `action.route` is relative to the plugin's own pages (`/deals`), never
|
|
450
|
+
* an absolute URL.
|
|
451
|
+
*/
|
|
452
|
+
interface PluginAgentReadinessItem {
|
|
453
|
+
id: string;
|
|
454
|
+
title: LocalizedText;
|
|
455
|
+
why?: LocalizedText | undefined;
|
|
456
|
+
status: 'ready' | 'action_needed' | 'not_applicable' | 'unknown';
|
|
457
|
+
owner: 'self' | 'other';
|
|
458
|
+
ownerHint?: LocalizedText | undefined;
|
|
459
|
+
optional?: boolean | undefined;
|
|
460
|
+
action?: {
|
|
461
|
+
label: LocalizedText;
|
|
462
|
+
route: string;
|
|
463
|
+
} | undefined;
|
|
464
|
+
}
|
|
465
|
+
interface PluginAgentReadinessResponse {
|
|
466
|
+
items: PluginAgentReadinessItem[];
|
|
467
|
+
}
|
|
468
|
+
interface PluginWorkDelegationDeclaration {
|
|
469
|
+
allowedAvatarRoles: string[];
|
|
470
|
+
/**
|
|
471
|
+
* @deprecated Host API 1.33 grants and revokes in its own dialog. Still
|
|
472
|
+
* accepted so older manifests validate; the host no longer links to it.
|
|
473
|
+
*/
|
|
474
|
+
settingsRoute?: string;
|
|
475
|
+
/** Host API 1.33: one sentence in the consent dialog, at most 120 characters. */
|
|
476
|
+
summary?: LocalizedText;
|
|
477
|
+
/** Host API 1.33: https link shown in the consent dialog. */
|
|
478
|
+
privacyPolicyUrl?: string;
|
|
479
|
+
/**
|
|
480
|
+
* Host API 1.33: the consent dialog offers, unchecked, to also record the
|
|
481
|
+
* person's new conversations with the employee for this plugin.
|
|
482
|
+
*/
|
|
483
|
+
conversationCapture?: boolean;
|
|
484
|
+
}
|
|
485
|
+
interface TegoPluginManifest {
|
|
486
|
+
/** Bumped only when this manifest's own shape breaks. */
|
|
487
|
+
manifestVersion: 1;
|
|
488
|
+
/**
|
|
489
|
+
* Flat identifier. Doubles as a directory name under claw's `extensions/`
|
|
490
|
+
* and as an `openclaw.json` object key, so scoped npm-style ids are refused.
|
|
491
|
+
*/
|
|
492
|
+
id: string;
|
|
493
|
+
version: string;
|
|
494
|
+
displayName: LocalizedText;
|
|
495
|
+
description?: LocalizedText;
|
|
496
|
+
author?: string;
|
|
497
|
+
homepage?: string;
|
|
498
|
+
/** Icon path inside the archive. */
|
|
499
|
+
icon?: string;
|
|
500
|
+
category?: string;
|
|
501
|
+
tags?: string[];
|
|
502
|
+
/**
|
|
503
|
+
* Caret range of the host API this plugin was built against, e.g. `^1.2.0`.
|
|
504
|
+
* Required once a frontend or backend part exists, because both bind to host
|
|
505
|
+
* modules; a claw-only plugin is governed by claw's own `minHostVersion`.
|
|
506
|
+
*/
|
|
507
|
+
hostApiRange?: string;
|
|
508
|
+
scope: PluginScope;
|
|
509
|
+
declares?: PluginDeclares;
|
|
510
|
+
parts: PluginParts;
|
|
511
|
+
permissions?: PluginPermissions;
|
|
512
|
+
/** Host API 1.22: plugin-owned roles and permissions. */
|
|
513
|
+
access?: PluginAccess;
|
|
514
|
+
/** How this plugin's tools read in the audit trail. */
|
|
515
|
+
audit?: PluginAuditDeclarations;
|
|
516
|
+
/** Employee templates shipped as immutable assets in this plugin release. */
|
|
517
|
+
agentTemplates?: {
|
|
518
|
+
key: string;
|
|
519
|
+
entry: string;
|
|
520
|
+
icon?: string;
|
|
521
|
+
}[];
|
|
522
|
+
/**
|
|
523
|
+
* Host-enforced eligibility for work delegation. Omit to disable; `*` allows any role.
|
|
524
|
+
* Requires a backend part. The host owns the consent dialog and the grant
|
|
525
|
+
* and revoke entries, so a plugin builds no delegation UI of its own.
|
|
526
|
+
*/
|
|
527
|
+
workDelegation?: PluginWorkDelegationDeclaration;
|
|
528
|
+
/** Read-only record routes used by the generic conversation binding API. */
|
|
529
|
+
conversationRecordRoutes?: {
|
|
530
|
+
entity: string;
|
|
531
|
+
path: string;
|
|
532
|
+
contextQuery?: string;
|
|
533
|
+
labelFields?: string[];
|
|
534
|
+
}[];
|
|
535
|
+
/** Per-user business readiness endpoint for digital employees using this plugin. */
|
|
536
|
+
agentReadiness?: PluginAgentReadinessDeclaration;
|
|
537
|
+
}
|
|
538
|
+
declare const PLUGIN_MANIFEST_FILENAME = "tego.plugin.json";
|
|
539
|
+
/** Mirrors OpenClaw's own manifest filename, found inside the claw part. */
|
|
540
|
+
declare const CLAW_MANIFEST_FILENAME = "openclaw.plugin.json";
|
|
541
|
+
declare const PLUGIN_PART_DEFAULTS: {
|
|
542
|
+
readonly frontend: {
|
|
543
|
+
readonly dir: "frontend";
|
|
544
|
+
readonly entry: "index.js";
|
|
545
|
+
readonly i18nDir: "i18n";
|
|
546
|
+
};
|
|
547
|
+
readonly backend: {
|
|
548
|
+
readonly dir: "backend";
|
|
549
|
+
readonly runtime: "node";
|
|
550
|
+
readonly entry: {
|
|
551
|
+
readonly node: "index.js";
|
|
552
|
+
readonly python: "app.py";
|
|
553
|
+
};
|
|
554
|
+
readonly migrationsDir: "migrations";
|
|
555
|
+
readonly healthPath: "/healthz";
|
|
556
|
+
};
|
|
557
|
+
readonly claw: {
|
|
558
|
+
readonly dir: "claw";
|
|
559
|
+
};
|
|
560
|
+
readonly publicFrontend: {
|
|
561
|
+
readonly dir: "public-frontend";
|
|
562
|
+
readonly entry: "index.html";
|
|
563
|
+
};
|
|
564
|
+
};
|
|
565
|
+
/**
|
|
566
|
+
* Scope of a manifest, tolerating one written before the field existed.
|
|
567
|
+
*
|
|
568
|
+
* Validation requires `scope` on every upload, so the fallback only ever fires
|
|
569
|
+
* for a manifest already stored on a release row. It reproduces what those
|
|
570
|
+
* releases got in practice — a claw part made the plugin an avatar capability,
|
|
571
|
+
* and nothing else was avatar-scoped.
|
|
572
|
+
*/
|
|
573
|
+
declare function resolvePluginScope(manifest: Pick<TegoPluginManifest, 'parts'> & {
|
|
574
|
+
scope?: PluginScope;
|
|
575
|
+
}): PluginScope;
|
|
576
|
+
/** Every disclosure with its default applied, so callers never see undefined. */
|
|
577
|
+
declare function resolvePluginDeclares(manifest: Pick<TegoPluginManifest, 'parts' | 'declares'>): Required<PluginDeclares>;
|
|
578
|
+
type PluginPartName = keyof PluginParts;
|
|
579
|
+
declare const PLUGIN_PART_NAMES: readonly PluginPartName[];
|
|
580
|
+
/** Part names this manifest actually declares, in stable order. */
|
|
581
|
+
declare function declaredPartNames(manifest: TegoPluginManifest): PluginPartName[];
|
|
582
|
+
interface ResolvedFrontendPart {
|
|
583
|
+
dir: string;
|
|
584
|
+
entryPath: string;
|
|
585
|
+
i18nDirPath: string;
|
|
586
|
+
nav: PluginNavEntry[];
|
|
587
|
+
config?: PluginConfigDeclaration;
|
|
588
|
+
}
|
|
589
|
+
interface ResolvedBackendPart {
|
|
590
|
+
dir: string;
|
|
591
|
+
runtime: PluginBackendRuntime;
|
|
592
|
+
entryPath: string;
|
|
593
|
+
/** Empty for node, which ships no native dependencies. */
|
|
594
|
+
platforms: PluginBackendPlatform[];
|
|
595
|
+
egress: string[];
|
|
596
|
+
migrationsDirPath: string;
|
|
597
|
+
compatibilityRepairs?: PluginSchemaRepair[];
|
|
598
|
+
healthPath: string;
|
|
599
|
+
limits: PluginBackendLimits;
|
|
600
|
+
publicRoutes: PluginPublicRoute[];
|
|
601
|
+
config?: PluginConfigDeclaration;
|
|
602
|
+
}
|
|
603
|
+
interface ResolvedClawPart {
|
|
604
|
+
hooks?: PluginClawHooks;
|
|
605
|
+
dir: string;
|
|
606
|
+
manifestPath: string;
|
|
607
|
+
}
|
|
608
|
+
interface ResolvedPublicFrontendPart {
|
|
609
|
+
dir: string;
|
|
610
|
+
entryPath: string;
|
|
611
|
+
}
|
|
612
|
+
interface ResolvedPluginParts {
|
|
613
|
+
frontend?: ResolvedFrontendPart;
|
|
614
|
+
backend?: ResolvedBackendPart;
|
|
615
|
+
claw?: ResolvedClawPart;
|
|
616
|
+
publicFrontend?: ResolvedPublicFrontendPart;
|
|
617
|
+
}
|
|
618
|
+
/**
|
|
619
|
+
* Apply every part default once, producing archive-relative paths.
|
|
620
|
+
*
|
|
621
|
+
* The only place defaults live. Validation, install and the runtimes all read
|
|
622
|
+
* this, so a plugin that omits `entry` cannot be resolved differently by two
|
|
623
|
+
* callers.
|
|
624
|
+
*/
|
|
625
|
+
declare function resolvePluginParts(manifest: TegoPluginManifest): ResolvedPluginParts;
|
|
626
|
+
|
|
627
|
+
export { resolvePluginParts as $, type PluginConfigDeclaration as A, type PluginConfigFieldSchema as B, CLAW_MANIFEST_FILENAME as C, type PluginConfigFieldType as D, EMPTY_CONFIG_SECTION_SUMMARY as E, type PluginConfigSchema as F, type PluginConfigUiHint as G, type PluginFrontendPart as H, type PluginParts as I, type PluginPermissions as J, type PluginPublicFrontendPart as K, type LocalizedText as L, type PluginPublicRouteMethod as M, type PluginSchemaRepair as N, type PluginWorkDelegationDeclaration as O, type PluginPublicRoute as P, type ResolvedClawPart as Q, type ResolvedBackendPart as R, type ResolvedFrontendPart as S, type TegoPluginManifest as T, type ResolvedPluginParts as U, type ResolvedPublicFrontendPart as V, applyConfigDefaults as W, configFieldLabel as X, declaredPartNames as Y, redactSecrets as Z, resolvePluginDeclares as _, type PluginBackendRuntime as a, resolvePluginScope as a0, restoreSecrets as a1, summarizeClawConfig as a2, summarizeConfigDeclaration as a3, type PluginScope as b, type PluginPartName as c, type PluginDeclares as d, type PluginConfigSection as e, type PluginConfigSectionSummary as f, type PluginNavIcon as g, type PluginNavEntry as h, type PluginAgentReadinessDeclaration as i, PLUGIN_BACKEND_PLATFORMS as j, PLUGIN_BACKEND_RUNTIMES as k, PLUGIN_CONFIG_SECRET_SENTINEL as l, PLUGIN_CONFIG_SECTIONS as m, PLUGIN_MANIFEST_FILENAME as n, PLUGIN_NAV_ICONS as o, PLUGIN_NAV_ICON_FALLBACK as p, PLUGIN_PART_DEFAULTS as q, PLUGIN_PART_NAMES as r, type PluginAgentReadinessItem as s, type PluginAgentReadinessResponse as t, type PluginAuditDeclarations as u, type PluginAuditToolDeclaration as v, type PluginBackendLimits as w, type PluginBackendPart as x, type PluginBackendPlatform as y, type PluginClawPart as z };
|