@openhands/extensions 0.19.0 → 0.20.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.
@@ -108,6 +108,10 @@
108
108
  "message": {
109
109
  "description": "Setup context handed to the agent conversation that finishes setup. Required for assisted mode. Optional for direct mode, where it seeds the fallback conversation the host offers when the deployment cannot run the direct path. The command that opens it comes from the skill, so it is not repeated here. Capped so this never becomes a channel for runtime instructions.",
110
110
  "allOf": [{ "$ref": "#/$defs/templateCopy" }, { "maxLength": 2000 }]
111
+ },
112
+ "actions": {
113
+ "description": "direct only, and the alternative to prompt or bundle. User-selectable creation paths for one setup card; the key maps to a known automation service endpoint.",
114
+ "$ref": "#/$defs/actions"
111
115
  }
112
116
  },
113
117
  "allOf": [
@@ -118,8 +122,9 @@
118
122
  },
119
123
  "then": {
120
124
  "oneOf": [
121
- { "required": ["prompt"], "not": { "required": ["bundle"] } },
122
- { "required": ["bundle"], "not": { "required": ["prompt"] } }
125
+ { "required": ["prompt"], "not": { "anyOf": [{ "required": ["bundle"] }, { "required": ["actions"] }] } },
126
+ { "required": ["bundle"], "not": { "anyOf": [{ "required": ["prompt"] }, { "required": ["actions"] }] } },
127
+ { "required": ["actions"], "not": { "anyOf": [{ "required": ["prompt"] }, { "required": ["bundle"] }] } }
123
128
  ]
124
129
  }
125
130
  },
@@ -133,7 +138,8 @@
133
138
  "allOf": [
134
139
  { "not": { "required": ["prompt"] } },
135
140
  { "not": { "required": ["bundle"] } },
136
- { "not": { "required": ["filter"] } }
141
+ { "not": { "required": ["filter"] } },
142
+ { "not": { "required": ["actions"] } }
137
143
  ]
138
144
  }
139
145
  },
@@ -157,6 +163,63 @@
157
163
  }
158
164
  ]
159
165
  },
166
+ "actionFeatures": {
167
+ "description": "Deployment capabilities needed only for this selectable action variant.",
168
+ "type": "array",
169
+ "minItems": 1,
170
+ "uniqueItems": true,
171
+ "items": { "type": "string", "minLength": 1 }
172
+ },
173
+ "promptAction": {
174
+ "type": "object",
175
+ "additionalProperties": false,
176
+ "required": ["label", "help", "features", "args", "prompt"],
177
+ "properties": {
178
+ "label": { "$ref": "#/$defs/copy" },
179
+ "help": { "$ref": "#/$defs/copy" },
180
+ "features": { "$ref": "#/$defs/actionFeatures" },
181
+ "args": { "$ref": "#/$defs/formFields" },
182
+ "prompt": { "$ref": "#/$defs/templateValue" }
183
+ }
184
+ },
185
+ "pluginAction": {
186
+ "type": "object",
187
+ "additionalProperties": false,
188
+ "required": ["label", "help", "features", "args", "prompt", "plugins"],
189
+ "properties": {
190
+ "label": { "$ref": "#/$defs/copy" },
191
+ "help": { "$ref": "#/$defs/copy" },
192
+ "features": { "$ref": "#/$defs/actionFeatures" },
193
+ "args": { "$ref": "#/$defs/formFields" },
194
+ "prompt": { "$ref": "#/$defs/templateValue" },
195
+ "plugins": { "$ref": "#/$defs/templateValue" }
196
+ }
197
+ },
198
+ "uploadAction": {
199
+ "type": "object",
200
+ "additionalProperties": false,
201
+ "required": ["label", "help", "features", "args", "tarballPath", "entrypoint"],
202
+ "properties": {
203
+ "label": { "$ref": "#/$defs/copy" },
204
+ "help": { "$ref": "#/$defs/copy" },
205
+ "features": { "$ref": "#/$defs/actionFeatures" },
206
+ "args": { "$ref": "#/$defs/formFields" },
207
+ "tarballPath": { "$ref": "#/$defs/templateValue" },
208
+ "entrypoint": { "$ref": "#/$defs/templateValue" },
209
+ "setupScript": { "$ref": "#/$defs/templateValue" }
210
+ }
211
+ },
212
+ "actions": {
213
+ "description": "Selectable direct-setup creation paths: prompt -> /v1/preset/prompt, plugin -> /v1/preset/plugin, upload -> /v1/uploads then /v1.",
214
+ "type": "object",
215
+ "additionalProperties": false,
216
+ "minProperties": 1,
217
+ "properties": {
218
+ "prompt": { "$ref": "#/$defs/promptAction" },
219
+ "plugin": { "$ref": "#/$defs/pluginAction" },
220
+ "upload": { "$ref": "#/$defs/uploadAction" }
221
+ }
222
+ },
160
223
  "bundle": {
161
224
  "description": "What the host packs into a .tar.gz and uploads before creating the automation. It names files inside this repository and the command that runs them - never a host, a URL, or code to evaluate.",
162
225
  "type": "object",
@@ -303,7 +366,7 @@
303
366
  "properties": {
304
367
  "note": { "$ref": "#/$defs/copy" },
305
368
  "triggers": {
306
- "description": "Inputs that decide when the automation runs, keyed by trigger kind. The key set is the trigger kinds the deployment must support, so it is not restated anywhere else.",
369
+ "description": "Inputs that decide when the automation runs, keyed by trigger kind. Multiple keys are selectable variants; a deployment can offer any variant whose trigger kind it supports.",
307
370
  "type": "object",
308
371
  "additionalProperties": false,
309
372
  "minProperties": 1,
@@ -331,20 +394,29 @@
331
394
  "required": ["type", "label", "help", "required"],
332
395
  "properties": {
333
396
  "type": {
334
- "description": "Semantic field types. The host renders a cron field without knowing what cron means to an automation, and resolves the deployment's schedule limits and timezone list for the cron and timezone types, so an entry never restates them.",
397
+ "description": "Semantic field types. The host renders cron, timezone, llm-profile, event-source, and event-type fields from deployment capabilities or user settings rather than entry-owned option lists.",
335
398
  "enum": [
336
399
  "text",
337
400
  "textarea",
338
401
  "select",
402
+ "number",
339
403
  "cron",
340
404
  "timezone",
341
- "repo-picker"
405
+ "repo-picker",
406
+ "llm-profile",
407
+ "event-source",
408
+ "event-type",
409
+ "plugin-sources",
410
+ "tarball-upload"
342
411
  ]
343
412
  },
344
413
  "label": { "$ref": "#/$defs/copy" },
345
414
  "help": { "$ref": "#/$defs/copy" },
346
415
  "placeholder": { "$ref": "#/$defs/copy" },
347
- "default": { "type": "string" },
416
+ "default": {
417
+ "description": "Initial value for fields whose defaults are entry-owned. Semantic fields may ignore it.",
418
+ "type": ["string", "number", "boolean", "null"]
419
+ },
348
420
  "required": { "type": "boolean" },
349
421
  "provider": { "enum": ["github", "gitlab", "bitbucket"] },
350
422
  "multiple": {
@@ -371,6 +443,8 @@
371
443
  "properties": {
372
444
  "minLength": { "type": "integer", "minimum": 0 },
373
445
  "maxLength": { "type": "integer", "minimum": 1 },
446
+ "min": { "type": "integer", "minimum": 0 },
447
+ "max": { "type": "integer", "minimum": 1 },
374
448
  "format": {
375
449
  "description": "A host-implemented check, named from a closed set. Setup blocks cannot supply their own regex, so one cannot hand the host a pathological pattern. safeExpressionLiteral marks a value that is interpolated into a filter expression string literal, so quotes and backslashes must be rejected before they can break the expression.",
376
450
  "enum": ["safeExpressionLiteral"]
@@ -70,9 +70,15 @@ export type AutomationFieldType =
70
70
  | "text"
71
71
  | "textarea"
72
72
  | "select"
73
+ | "number"
73
74
  | "cron"
74
75
  | "timezone"
75
- | "repo-picker";
76
+ | "repo-picker"
77
+ | "llm-profile"
78
+ | "event-source"
79
+ | "event-type"
80
+ | "plugin-sources"
81
+ | "tarball-upload";
76
82
  export type AutomationGitProvider = "github" | "gitlab" | "bitbucket";
77
83
  export type AutomationTriggerKind = "cron" | "event";
78
84
 
@@ -84,6 +90,8 @@ export interface AutomationFieldOption {
84
90
  export interface AutomationFieldConstraints {
85
91
  minLength?: number;
86
92
  maxLength?: number;
93
+ min?: number;
94
+ max?: number;
87
95
  /** Host-implemented check, named from a closed set. Entries supply no regex. */
88
96
  format?: "safeExpressionLiteral";
89
97
  }
@@ -93,7 +101,7 @@ export interface AutomationFormField {
93
101
  label: string;
94
102
  help: string;
95
103
  placeholder?: string;
96
- default?: string;
104
+ default?: string | number | boolean | null;
97
105
  required: boolean;
98
106
  provider?: AutomationGitProvider;
99
107
  /**
@@ -160,6 +168,46 @@ export interface AutomationBundle {
160
168
  config: Record<string, AutomationBundleConfigValue>;
161
169
  }
162
170
 
171
+
172
+ export interface AutomationPromptAction {
173
+ label: string;
174
+ help: string;
175
+ features: string[];
176
+ args: AutomationFormFields;
177
+ /** Prompt sent to /v1/preset/prompt. */
178
+ prompt: string;
179
+ }
180
+
181
+ export interface AutomationPluginAction {
182
+ label: string;
183
+ help: string;
184
+ features: string[];
185
+ args: AutomationFormFields;
186
+ /** Prompt sent to /v1/preset/plugin. */
187
+ prompt: string;
188
+ /** PluginSource list sent to /v1/preset/plugin, usually {{form.plugins}}. */
189
+ plugins: string;
190
+ }
191
+
192
+ export interface AutomationUploadAction {
193
+ label: string;
194
+ help: string;
195
+ features: string[];
196
+ args: AutomationFormFields;
197
+ /** tarball_path produced by uploading the selected tarball file. */
198
+ tarballPath: string;
199
+ /** Entrypoint command sent to /v1. */
200
+ entrypoint: string;
201
+ /** Optional setup_script_path sent to /v1. */
202
+ setupScript?: string;
203
+ }
204
+
205
+ export interface AutomationSetupActions {
206
+ prompt?: AutomationPromptAction;
207
+ plugin?: AutomationPluginAction;
208
+ upload?: AutomationUploadAction;
209
+ }
210
+
163
211
  export interface AutomationSetup {
164
212
  version: "1.0";
165
213
  mode: AutomationSetupMode;
@@ -168,6 +216,8 @@ export interface AutomationSetup {
168
216
  prompt?: string;
169
217
  /** direct only, and the alternative to `prompt`. Exactly one is present. */
170
218
  bundle?: AutomationBundle;
219
+ /** direct only, and the alternative to `prompt` or `bundle`. */
220
+ actions?: AutomationSetupActions;
171
221
  /** direct only, event trigger only. Which delivered events belong to it. */
172
222
  filter?: string;
173
223
  /**
@@ -153,7 +153,8 @@
153
153
  "github-agents-md-maintainer",
154
154
  "news-digest",
155
155
  "github-issue-to-pr",
156
- "slack-channel-monitor"
156
+ "slack-channel-monitor",
157
+ "custom-automation"
157
158
  ],
158
159
  "responderIntegrationIds": ["github", "slack"]
159
160
  }
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "id": "gitlab",
3
3
  "name": "GitLab",
4
- "description": "Repositories, issues, merge requests, and CI/CD workflows through the GitLab API.",
4
+ "description": "Access projects, issues, merge requests, and CI/CD workflows through GitLab's official MCP server or API.",
5
5
  "categories": [
6
6
  "Engineering",
7
7
  "Source control"
8
8
  ],
9
9
  "appUrl": "https://gitlab.com",
10
- "docsUrl": "https://docs.gitlab.com/api/",
11
- "notes": "Supports GitLab.com projects through a personal access token.",
10
+ "docsUrl": "https://docs.gitlab.com/user/model_context_protocol/mcp_server/",
11
+ "notes": "Supports GitLab.com through either the official MCP server (beta) with OAuth or the API with a personal access token. For the OAuth MCP connection to work on GitLab.com, MCP server access must be enabled for a top-level group you belong to (set GitLab Duo availability to Always on or On by default for the top-level group, turn on beta and experimental features, and allow access to the MCP server); otherwise GitLab rejects the connection with a 404 after OAuth, which the client reports as 'Session terminated'. For GitLab Self-Managed, edit the MCP URL to your instance's server and the OAuth flow discovers the host-specific endpoints.",
12
12
  "popularityRank": 60,
13
13
  "connectionOptions": [
14
14
  {
@@ -27,6 +27,25 @@
27
27
  "apiBaseUrl": "https://gitlab.com/api/v4",
28
28
  "openApiUrl": "https://gitlab.com/gitlab-org/gitlab/-/raw/master/doc/api/openapi/openapi_v2.yaml"
29
29
  }
30
+ },
31
+ {
32
+ "id": "oauth",
33
+ "provider": "mcp",
34
+ "auth": {
35
+ "strategy": "oauth2",
36
+ "oauth": {
37
+ "scopes": [
38
+ "mcp"
39
+ ],
40
+ "pkce": true,
41
+ "clientAuthentication": "none"
42
+ }
43
+ },
44
+ "transport": {
45
+ "kind": "shttp",
46
+ "url": "https://gitlab.com/api/v4/mcp",
47
+ "urlEditable": true
48
+ }
30
49
  }
31
50
  ],
32
51
  "iconBg": "var(--oh-surface)",
@@ -36,6 +55,9 @@
36
55
  "merge request",
37
56
  "repo",
38
57
  "issues",
39
- "code"
40
- ]
58
+ "code",
59
+ "mr",
60
+ "devops"
61
+ ],
62
+ "installHint": "The GitLab MCP server supports OAuth 2.0. Before installing, make sure an admin has enabled 'MCP client access' for the top-level GitLab group you belong to. If this prerequisite isn't met, GitLab returns 404 after OAuth and the connection fails with 'Session terminated'. For GitLab Self-Managed, edit the URL to https://<your-instance>/api/v4/mcp and make sure MCP server access is enabled for the instance."
41
63
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openhands/extensions",
3
- "version": "0.19.0",
3
+ "version": "0.20.0",
4
4
  "description": "Public OpenHands extension catalogs for skills, plugins, integrations, and automation templates.",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/pyproject.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "openhands-extensions"
3
- version = "0.19.0"
3
+ version = "0.20.0"
4
4
  description = "OpenHands extensions, plugins, and skills (Python bindings for the integration catalog)"
5
5
  requires-python = ">=3.12"
6
6
  dependencies = [
@@ -18,7 +18,7 @@ from importlib.metadata import PackageNotFoundError, version
18
18
  #: Kept in lock-step with pyproject.toml/package.json by the version test.
19
19
  #: release-please only rewrites a semver found on the annotated line itself, so
20
20
  #: the annotation must stay on the assignment; on its own line it is a no-op.
21
- _FALLBACK_VERSION = "0.19.0" # x-release-please-version
21
+ _FALLBACK_VERSION = "0.20.0" # x-release-please-version
22
22
 
23
23
  try:
24
24
  __version__: str = version("openhands-extensions")