@termix-ssh/plugin-sdk 1.0.22 → 1.0.23

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.
Files changed (30) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/PLUGIN-GUIDE.md +69 -1
  3. package/dist/backend.d.ts +107 -0
  4. package/dist/capabilities.js +3 -0
  5. package/dist/host/{PluginsTab-CM2B33BD.js → PluginsTab-MNQU5OJ3.js} +4 -4
  6. package/dist/host/{chunk-P26QKKU5.js → chunk-6WLECSNB.js} +35 -5
  7. package/dist/host/{chunk-TK3Y437H.js → chunk-BP42N374.js} +1 -1
  8. package/dist/host/{chunk-ROB2SH5Q.js → chunk-C52NRTA6.js} +9 -5
  9. package/dist/host/{chunk-VKNGNEF3.js → chunk-DN6YKMFJ.js} +1 -1
  10. package/dist/host/{chunk-I5F2PSMR.js → chunk-GBBKHJRQ.js} +9 -9
  11. package/dist/host/{chunk-JRV2HIDK.js → chunk-GRH7GSKG.js} +1 -1
  12. package/dist/host/{chunk-7J4QNGFM.js → chunk-IMPLAAUM.js} +1 -1
  13. package/dist/host/{chunk-HQ6NNFSX.js → chunk-X65V7ZRW.js} +15 -3
  14. package/dist/host/core-classes.json +1 -1
  15. package/dist/host/frame-host.css +1 -1
  16. package/dist/host/frame-host.js +5 -5
  17. package/dist/host/{linked-server-J5G457OA.js → linked-server-YCAJ2NX3.js} +1 -1
  18. package/dist/host/{rbac-api-PY22W5UY.js → rbac-api-A64TXDL5.js} +1 -1
  19. package/dist/host/testing-host.js +6 -6
  20. package/dist/host/types/src/ui/lib/db-health-monitor.d.ts +5 -0
  21. package/dist/host/ui.js +9 -9
  22. package/dist/host/{use-permissions-EWRI3WLT.js → use-permissions-FLQAN6I7.js} +1 -1
  23. package/dist/manifest.d.ts +6 -1
  24. package/dist/manifest.js +7 -1
  25. package/dist/operations.d.ts +222 -0
  26. package/dist/operations.js +650 -0
  27. package/dist/testing.d.ts +9 -1
  28. package/dist/testing.js +45 -0
  29. package/package.json +5 -1
  30. package/schema/manifest.schema.json +25 -0
@@ -1,7 +1,7 @@
1
1
  const __termixNoGlob = () => ({});
2
2
  import {
3
3
  Toaster
4
- } from "./chunk-TK3Y437H.js";
4
+ } from "./chunk-BP42N374.js";
5
5
  import {
6
6
  ThemeProvider,
7
7
  createPluginApp,
@@ -12,8 +12,8 @@ import {
12
12
  setPluginThemes,
13
13
  sshHostToHost,
14
14
  useTheme
15
- } from "./chunk-HQ6NNFSX.js";
16
- import "./chunk-JRV2HIDK.js";
15
+ } from "./chunk-X65V7ZRW.js";
16
+ import "./chunk-GRH7GSKG.js";
17
17
  import {
18
18
  SurfaceScope,
19
19
  notifyShellReady,
@@ -21,13 +21,13 @@ import {
21
21
  setShellCallbacks,
22
22
  setShellHosts,
23
23
  shellHost
24
- } from "./chunk-VKNGNEF3.js";
24
+ } from "./chunk-DN6YKMFJ.js";
25
25
  import {
26
26
  getSSHHosts,
27
27
  getTabType,
28
28
  setFrontendState,
29
29
  setPluginSummaries
30
- } from "./chunk-P26QKKU5.js";
30
+ } from "./chunk-6WLECSNB.js";
31
31
  import {
32
32
  init_define_import_meta_env
33
33
  } from "./chunk-YGYBM7SQ.js";
@@ -4,7 +4,7 @@ import {
4
4
  getLinkedSession,
5
5
  notifySyncChanged,
6
6
  useDesktopLinked
7
- } from "./chunk-P26QKKU5.js";
7
+ } from "./chunk-6WLECSNB.js";
8
8
  import "./chunk-YGYBM7SQ.js";
9
9
  export {
10
10
  SYNC_CHANGED_EVENT,
@@ -25,7 +25,7 @@ import {
25
25
  shareHost,
26
26
  updateHostAccess,
27
27
  updateRole
28
- } from "./chunk-P26QKKU5.js";
28
+ } from "./chunk-6WLECSNB.js";
29
29
  import "./chunk-YGYBM7SQ.js";
30
30
  export {
31
31
  assignRoleToUser,
@@ -7,7 +7,7 @@ import {
7
7
  PluginViewPlaceholder,
8
8
  renderTabContent,
9
9
  trackTabHandle
10
- } from "./chunk-I5F2PSMR.js";
10
+ } from "./chunk-GBBKHJRQ.js";
11
11
  import {
12
12
  RAIL_ITEMS,
13
13
  ServerStatusProvider,
@@ -61,11 +61,11 @@ import {
61
61
  setRemoteServerUrlForTesting,
62
62
  useShellController,
63
63
  useTabStageStore
64
- } from "./chunk-HQ6NNFSX.js";
64
+ } from "./chunk-X65V7ZRW.js";
65
65
  import {
66
66
  setPermissionsForTesting
67
- } from "./chunk-JRV2HIDK.js";
68
- import "./chunk-7J4QNGFM.js";
67
+ } from "./chunk-GRH7GSKG.js";
68
+ import "./chunk-IMPLAAUM.js";
69
69
  import {
70
70
  SurfaceScope,
71
71
  notifyShellReady,
@@ -73,14 +73,14 @@ import {
73
73
  setShellCallbacks,
74
74
  setShellHosts,
75
75
  setShellLayoutProvider
76
- } from "./chunk-VKNGNEF3.js";
76
+ } from "./chunk-DN6YKMFJ.js";
77
77
  import {
78
78
  getTabType,
79
79
  listTabTypes,
80
80
  resetPluginStore,
81
81
  setFrontendState,
82
82
  setPluginSummaries
83
- } from "./chunk-P26QKKU5.js";
83
+ } from "./chunk-6WLECSNB.js";
84
84
  import {
85
85
  init_define_import_meta_env
86
86
  } from "./chunk-YGYBM7SQ.js";
@@ -19,6 +19,8 @@ declare class DatabaseHealthMonitor {
19
19
  private static instance;
20
20
  private listeners;
21
21
  private degradedActive;
22
+ private probe;
23
+ private probing;
22
24
  private constructor();
23
25
  static getInstance(): DatabaseHealthMonitor;
24
26
  on(event: string, listener: EventListener): void;
@@ -26,6 +28,9 @@ declare class DatabaseHealthMonitor {
26
28
  private emit;
27
29
  reportSessionExpired(): void;
28
30
  reportDatabaseError(error: unknown): void;
31
+ /** Sets the quick check used after a request times out. */
32
+ setReachabilityProbe(probe: (() => Promise<boolean>) | null): void;
33
+ private markDegraded;
29
34
  reportDatabaseSuccess(): void;
30
35
  isDegraded(): boolean;
31
36
  reset(): void;
package/dist/host/ui.js CHANGED
@@ -21,10 +21,10 @@ import {
21
21
  useInstalledPlugins,
22
22
  usePluginHostSections,
23
23
  useTabHandlesVersion
24
- } from "./chunk-I5F2PSMR.js";
24
+ } from "./chunk-GBBKHJRQ.js";
25
25
  import {
26
26
  Toaster
27
- } from "./chunk-TK3Y437H.js";
27
+ } from "./chunk-BP42N374.js";
28
28
  import {
29
29
  ACCENT_PRESET_COLORS,
30
30
  BUILTIN_THEMES,
@@ -165,10 +165,10 @@ import {
165
165
  useThemes,
166
166
  verifySecondFactor,
167
167
  withProtocolSettings
168
- } from "./chunk-HQ6NNFSX.js";
168
+ } from "./chunk-X65V7ZRW.js";
169
169
  import {
170
170
  usePermissions
171
- } from "./chunk-JRV2HIDK.js";
171
+ } from "./chunk-GRH7GSKG.js";
172
172
  import {
173
173
  AddButton,
174
174
  Card,
@@ -189,7 +189,7 @@ import {
189
189
  isPrerelease,
190
190
  reportBetaFeedbackUrl,
191
191
  reportCoreIssueUrl
192
- } from "./chunk-ROB2SH5Q.js";
192
+ } from "./chunk-C52NRTA6.js";
193
193
  import {
194
194
  Button,
195
195
  DefaultsOnly,
@@ -206,7 +206,7 @@ import {
206
206
  hasVisibleFields,
207
207
  isFieldShown,
208
208
  useIsDefaultsEditor
209
- } from "./chunk-7J4QNGFM.js";
209
+ } from "./chunk-IMPLAAUM.js";
210
210
  import {
211
211
  Action,
212
212
  Activity,
@@ -381,7 +381,7 @@ import {
381
381
  useSurfaceKind,
382
382
  useUiPreference,
383
383
  useUiPreferencesContext
384
- } from "./chunk-VKNGNEF3.js";
384
+ } from "./chunk-DN6YKMFJ.js";
385
385
  import {
386
386
  CREDENTIAL_ROW_FIELD_KEYS,
387
387
  PRESETS,
@@ -544,7 +544,7 @@ import {
544
544
  useTabs,
545
545
  useTabsSafe,
546
546
  verifyPasswordResetCode
547
- } from "./chunk-P26QKKU5.js";
547
+ } from "./chunk-6WLECSNB.js";
548
548
  import {
549
549
  define_import_meta_env_default,
550
550
  init_define_import_meta_env
@@ -557,7 +557,7 @@ init_define_import_meta_env();
557
557
  init_define_import_meta_env();
558
558
  import { jsx } from "react/jsx-runtime";
559
559
  var alertVariants = cva(
560
- "relative w-full border border-border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current",
560
+ "relative w-full border border-border px-4 py-3 text-sm not-has-[>svg]:block grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current",
561
561
  {
562
562
  variants: {
563
563
  variant: {
@@ -7,7 +7,7 @@ import {
7
7
  resetPermissionsCache,
8
8
  setPermissionsForTesting,
9
9
  usePermissions
10
- } from "./chunk-JRV2HIDK.js";
10
+ } from "./chunk-GRH7GSKG.js";
11
11
  import "./chunk-YGYBM7SQ.js";
12
12
  export {
13
13
  hasPermission,
@@ -9,6 +9,7 @@
9
9
  * "permissionGroups" used to validate clean and be silently dropped, which
10
10
  * made a manifest look like it declared something it did not.
11
11
  */
12
+ import { type PluginOperationsContribution } from "./operations.js";
12
13
  import { type PluginEnvVar } from "./docs.js";
13
14
  export { validateThemeCss } from "./theme-css.js";
14
15
  export { ENV_NAME_PATTERN, MAX_ENV_DESCRIPTION_LENGTH, pluginDocsPage, pluginDocsUrl, pluginEnvVars, type PluginEnvVar, } from "./docs.js";
@@ -20,7 +21,7 @@ export { ENV_NAME_PATTERN, MAX_ENV_DESCRIPTION_LENGTH, pluginDocsPage, pluginDoc
20
21
  * "^1.2" needs 1.2 or later). engine.termix is checked against the core
21
22
  * version by the server.
22
23
  */
23
- export declare const PLUGIN_API_VERSION = "1.13.0";
24
+ export declare const PLUGIN_API_VERSION = "1.14.0";
24
25
  /** The API major, the default engine.api for a new plugin. */
25
26
  export declare const SUPPORTED_PLUGIN_API_VERSION: string;
26
27
  /** Whether this build's plugin API satisfies a manifest's engine.api. */
@@ -305,6 +306,10 @@ export interface PluginContributions {
305
306
  tabs?: PluginTabContribution[];
306
307
  panels?: PluginViewContribution[];
307
308
  dashboardCards?: PluginViewContribution[];
309
+ /** Cards on the host page, filled with app.registerHostSection. */
310
+ hostSections?: PluginViewContribution[];
311
+ /** What this plugin can do, for every surface to find on its own. */
312
+ operations?: PluginOperationsContribution;
308
313
  /**
309
314
  * The frontend also runs on anonymous guest pages (shared-session and
310
315
  * collab links), where it is activated with app.guest set.
package/dist/manifest.js CHANGED
@@ -11,6 +11,7 @@
11
11
  */
12
12
  import semver from "semver";
13
13
  import { isKnownCapability } from "./capabilities.js";
14
+ import { checkOperationReferences, validateOperations, } from "./operations.js";
14
15
  import { ENV_NAME_PATTERN, MAX_ENV_DESCRIPTION_LENGTH, pluginDocsUrl, } from "./docs.js";
15
16
  export { validateThemeCss } from "./theme-css.js";
16
17
  export { ENV_NAME_PATTERN, MAX_ENV_DESCRIPTION_LENGTH, pluginDocsPage, pluginDocsUrl, pluginEnvVars, } from "./docs.js";
@@ -22,7 +23,7 @@ export { ENV_NAME_PATTERN, MAX_ENV_DESCRIPTION_LENGTH, pluginDocsPage, pluginDoc
22
23
  * "^1.2" needs 1.2 or later). engine.termix is checked against the core
23
24
  * version by the server.
24
25
  */
25
- export const PLUGIN_API_VERSION = "1.13.0";
26
+ export const PLUGIN_API_VERSION = "1.14.0";
26
27
  /** The API major, the default engine.api for a new plugin. */
27
28
  export const SUPPORTED_PLUGIN_API_VERSION = String(semver.major(PLUGIN_API_VERSION));
28
29
  /** Whether this build's plugin API satisfies a manifest's engine.api. */
@@ -245,6 +246,8 @@ const ALLOWED_CONTRIBUTES = new Set([
245
246
  "tabs",
246
247
  "panels",
247
248
  "dashboardCards",
249
+ "hostSections",
250
+ "operations",
248
251
  "guest",
249
252
  "guestViews",
250
253
  "actions",
@@ -835,6 +838,8 @@ function validateContributes(contributes, pluginId, errors) {
835
838
  validateTabs(contributes.tabs, errors);
836
839
  validateViews(contributes.panels, "panels", errors);
837
840
  validateViews(contributes.dashboardCards, "dashboardCards", errors);
841
+ validateViews(contributes.hostSections, "hostSections", errors);
842
+ validateOperations(contributes.operations, pluginId, errors);
838
843
  if (contributes.guest !== undefined &&
839
844
  typeof contributes.guest !== "boolean") {
840
845
  errors.push('Field "contributes.guest" must be a boolean');
@@ -1767,6 +1772,7 @@ export function parseManifest(raw) {
1767
1772
  errors.push(`contributes.actions["${action.id}"].permission "${action.permission}" is not declared in contributes.permissions`);
1768
1773
  }
1769
1774
  }
1775
+ checkOperationReferences(manifest.contributes?.operations, manifest.capabilities, (name) => declared.has(qualifyPermission(manifest.id, name)), errors);
1770
1776
  // A settings field may gate on one of this plugin's own permissions, or on
1771
1777
  // a core/other-plugin id used as given. Only the first form is checkable
1772
1778
  // here, and an undeclared one would hide the field from every admin.
@@ -0,0 +1,222 @@
1
+ /**
2
+ * The operations contract: what a plugin declares it can do, in one shape every
3
+ * surface reads (Automations, Fleets, AI, CLI, Mobile, palette, API, MCP).
4
+ *
5
+ * Declarations are data in the manifest, so a surface can list and describe an
6
+ * action without loading the plugin's code. Handlers are registered at
7
+ * activation with ctx.operations.register and must match a declaration.
8
+ *
9
+ * No Node imports: the frontend, the CLI and Mobile read this file too.
10
+ */
11
+ import type { PluginSettingsOption } from "./manifest.js";
12
+ export declare const OPERATION_RISKS: readonly ["read", "change", "destructive"];
13
+ export type OperationRisk = (typeof OPERATION_RISKS)[number];
14
+ export declare const OPERATION_SCOPES: readonly ["host", "resource", "server"];
15
+ export type OperationScope = (typeof OPERATION_SCOPES)[number];
16
+ export declare const OPERATION_HOST_ACCESS: readonly ["connect", "view", "edit", "manage"];
17
+ export type OperationHostAccess = (typeof OPERATION_HOST_ACCESS)[number];
18
+ export declare const OPERATION_DRY_RUN: readonly ["native", "describe"];
19
+ /** native: the handler checks ctx.dryRun. describe: core reports its text. */
20
+ export type OperationDryRun = (typeof OPERATION_DRY_RUN)[number];
21
+ export declare const OPERATION_FIELD_TYPES: readonly ["boolean", "string", "number", "select", "multiselect", "secret", "textarea", "json", "resource"];
22
+ export type OperationFieldType = (typeof OPERATION_FIELD_TYPES)[number];
23
+ export declare const OPERATION_SEVERITIES: readonly ["info", "warning", "critical"];
24
+ export type OperationSeverity = (typeof OPERATION_SEVERITIES)[number];
25
+ export declare const SIGNAL_KINDS: readonly ["count", "gauge", "status", "list"];
26
+ export type SignalKind = (typeof SIGNAL_KINDS)[number];
27
+ export declare const SIGNAL_STATUSES: readonly ["ok", "warn", "fail", "unknown"];
28
+ export type SignalStatus = (typeof SIGNAL_STATUSES)[number];
29
+ export declare const RESOURCE_COLUMN_TYPES: readonly ["text", "status", "bytes", "percent", "time", "tags"];
30
+ export type ResourceColumnType = (typeof RESOURCE_COLUMN_TYPES)[number];
31
+ /** One input or output of an action. A subset of a settings field, plus rules. */
32
+ export interface OperationField {
33
+ key: string;
34
+ type: OperationFieldType;
35
+ labelKey?: string;
36
+ descriptionKey?: string;
37
+ placeholderKey?: string;
38
+ default?: unknown;
39
+ options?: PluginSettingsOption[];
40
+ min?: number;
41
+ max?: number;
42
+ /** Key of a boolean field in the same list that must be on. */
43
+ requires?: string;
44
+ group?: string;
45
+ required?: boolean;
46
+ /** string and textarea only. A regular expression the whole value matches. */
47
+ pattern?: string;
48
+ /** Read action whose rows fill the choices, for a list known only at run time. */
49
+ optionsFrom?: string;
50
+ /** type "resource" only: the resource id whose list fills the picker. */
51
+ resource?: string;
52
+ /** Outputs only: dropped before a run is stored or shown. */
53
+ sensitive?: boolean;
54
+ }
55
+ export interface OperationWhen {
56
+ /** Host setting values that must match, such as { enableDocker: true }. */
57
+ settings?: Record<string, boolean | string | number>;
58
+ /** Lowercase OS names. A host with no known OS passes. */
59
+ os?: string[];
60
+ }
61
+ export interface OperationSurfaces {
62
+ /** Offered to the AI assistant. Off unless set. */
63
+ assistant?: boolean;
64
+ /** Offered over MCP. Off unless set. */
65
+ mcp?: boolean;
66
+ /** Set false to keep out of the command palette. */
67
+ palette?: boolean;
68
+ /** Set false to keep out of Automations. */
69
+ automations?: boolean;
70
+ /** Set false to keep out of the phone app. */
71
+ mobile?: boolean;
72
+ /** Set false to keep out of the CLI. */
73
+ cli?: boolean;
74
+ }
75
+ export interface OperationAction {
76
+ /** `<pluginId>.<name>`. */
77
+ id: string;
78
+ /** Bump when inputs change in a way saved references cannot follow. */
79
+ version?: number;
80
+ titleKey: string;
81
+ descriptionKey?: string;
82
+ icon?: string;
83
+ scope: OperationScope;
84
+ /** Required for scope "resource": the resource this acts on. */
85
+ resource?: string;
86
+ inputs?: OperationField[];
87
+ outputs?: OperationField[];
88
+ risk: OperationRisk;
89
+ /** One of this plugin's own permissions, short or full. */
90
+ permission: string;
91
+ /** Lowest share level. Required for host and resource scopes. */
92
+ hostAccess?: OperationHostAccess;
93
+ dryRun?: OperationDryRun;
94
+ /** A read action of this plugin that proves the result. */
95
+ check?: string;
96
+ /** An action of this plugin that reverses this one. */
97
+ undo?: string;
98
+ /** Safe to run twice, so a rollout may retry it. */
99
+ idempotent?: boolean;
100
+ /** Only one such action per host at a time. */
101
+ exclusive?: boolean;
102
+ timeoutMs?: number;
103
+ when?: OperationWhen;
104
+ surfaces?: OperationSurfaces;
105
+ }
106
+ export interface OperationEvent {
107
+ id: string;
108
+ titleKey: string;
109
+ descriptionKey?: string;
110
+ severity?: OperationSeverity;
111
+ scope: "host" | "server";
112
+ payload?: OperationField[];
113
+ }
114
+ export interface ResourceColumn {
115
+ key: string;
116
+ titleKey: string;
117
+ type?: ResourceColumnType;
118
+ }
119
+ export interface OperationResource {
120
+ id: string;
121
+ titleKey: string;
122
+ icon?: string;
123
+ /** Read action that returns { rows: [...] } for one host. */
124
+ list: string;
125
+ /** Row field that is unique on a host. */
126
+ key: string;
127
+ /** Row field shown as the name. */
128
+ name: string;
129
+ /** Row field holding a status word. */
130
+ status?: string;
131
+ /** Row field holding a link, for auto links on the homepage. */
132
+ url?: string;
133
+ /** Tab type that opens this on a host. */
134
+ tab?: string;
135
+ columns?: ResourceColumn[];
136
+ filters?: string[];
137
+ }
138
+ export interface OperationSignal {
139
+ id: string;
140
+ titleKey: string;
141
+ /** Read action that returns a SignalResult. */
142
+ read: string;
143
+ scope: "host" | "server";
144
+ kind: SignalKind;
145
+ refreshSec?: number;
146
+ /** Action offered as the fix when this signal is not ok. */
147
+ fix?: string;
148
+ }
149
+ export interface PluginOperationsContribution {
150
+ actions?: OperationAction[];
151
+ events?: OperationEvent[];
152
+ resources?: OperationResource[];
153
+ signals?: OperationSignal[];
154
+ /**
155
+ * Actions this plugin may run through ctx.operations.invoke: exact ids,
156
+ * `<pluginId>.*`, or `*`.
157
+ */
158
+ invokes?: string[];
159
+ }
160
+ /** What a signal's read action returns. */
161
+ export interface SignalResult {
162
+ value?: number | string | null;
163
+ status: SignalStatus;
164
+ label?: string;
165
+ items?: {
166
+ label: string;
167
+ status?: SignalStatus;
168
+ }[];
169
+ link?: {
170
+ tab?: string;
171
+ data?: Record<string, unknown>;
172
+ };
173
+ }
174
+ /** What a resource's list action returns. */
175
+ export interface ResourceListResult {
176
+ rows: Record<string, unknown>[];
177
+ }
178
+ /** What a handler returns. */
179
+ export interface OperationResult {
180
+ /** One plain line for history and per host results. */
181
+ summary: string;
182
+ /** Whether anything actually changed. */
183
+ changed?: boolean;
184
+ data?: unknown;
185
+ /** Input for the `undo` action that reverses this exact run. */
186
+ undoInput?: Record<string, unknown>;
187
+ }
188
+ export declare const OPERATION_ID_PATTERN: RegExp;
189
+ export declare const MAX_OPERATION_TIMEOUT_MS = 3600000;
190
+ export declare const REDACTED_VALUE = "[redacted]";
191
+ /** Shape checks for contributes.operations, run by validateManifest. */
192
+ export declare function validateOperations(value: unknown, pluginId: string | undefined, errors: string[]): void;
193
+ /**
194
+ * The cross-field rules: every id one declaration names must exist in this
195
+ * plugin, or a surface would offer a button that goes nowhere.
196
+ */
197
+ export declare function checkOperationReferences(operations: PluginOperationsContribution | undefined, capabilities: readonly string[], hasPermission: (name: string) => boolean, errors: string[]): void;
198
+ /** Whether a plugin's invokes list lets it run an action. */
199
+ export declare function invokeAllowed(invokes: readonly string[] | undefined, actionId: string): boolean;
200
+ export declare function riskRank(risk: OperationRisk): number;
201
+ /** A surface's own switch. The assistant and MCP are opt in, the rest opt out. */
202
+ export declare function onSurface(action: Pick<OperationAction, "surfaces">, surface: keyof OperationSurfaces): boolean;
203
+ /** Whether an action applies to a host, from fields any client can read. */
204
+ export declare function matchesWhen(when: OperationWhen | undefined, host: {
205
+ settings?: Record<string, unknown>;
206
+ os?: string | null;
207
+ }): boolean;
208
+ export interface OperationInputResult {
209
+ values: Record<string, unknown>;
210
+ errors: string[];
211
+ }
212
+ /**
213
+ * Turns raw input into validated values. Keys no field declares are refused,
214
+ * so nothing a handler did not ask for ever reaches it.
215
+ */
216
+ export declare function parseOperationInput(fields: readonly OperationField[] | undefined, raw: unknown): OperationInputResult;
217
+ /** A copy safe to store or show: secret and sensitive values are replaced. */
218
+ export declare function redactFields(fields: readonly OperationField[] | undefined, values: unknown): unknown;
219
+ /** Trims text to a byte-friendly length with a plain marker. */
220
+ export declare function capText(text: string, maxLength: number): string;
221
+ /** JSON Schema for a field list, for AI tools, MCP and OpenAPI. */
222
+ export declare function toJsonSchema(fields: readonly OperationField[] | undefined, describe?: (field: OperationField) => string | undefined): Record<string, unknown>;