@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.
- package/.pr/custom-automation-event-trigger.png +0 -0
- package/.pr/custom-automation-plugin-fields.png +0 -0
- package/.pr/custom-automation-prompt-review.png +0 -0
- package/.pr/custom-automation-prompt-scheduled.png +0 -0
- package/.pr/custom-automation-upload-fields.png +0 -0
- package/.release-please-manifest.json +1 -1
- package/AGENTS.md +1 -1
- package/automations/README.md +52 -36
- package/automations/catalog/custom-automation/manifest.json +229 -0
- package/automations/catalog/github-issue-to-pr/manifest.json +1 -1
- package/automations/catalog/github-pr-reviewer/manifest.json +1 -1
- package/automations/catalog/qa-changes/manifest.json +1 -1
- package/automations/catalog-index.js +19 -17
- package/automations/catalog.schema.json +81 -7
- package/automations/index.d.ts +52 -2
- package/automations/interface.json +2 -1
- package/integrations/catalog/gitlab.json +27 -5
- package/package.json +1 -1
- package/pyproject.toml +1 -1
- package/python/openhands_extensions/_version.py +1 -1
- package/tests/fixtures/automations/custom-automation.json +398 -0
- package/tests/fixtures/automations/github-pr-reviewer.json +9 -9
- package/tests/test_automation_setup.py +340 -92
|
@@ -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.
|
|
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
|
|
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": {
|
|
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"]
|
package/automations/index.d.ts
CHANGED
|
@@ -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
|
/**
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "gitlab",
|
|
3
3
|
"name": "GitLab",
|
|
4
|
-
"description": "
|
|
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/
|
|
11
|
-
"notes": "Supports GitLab.com
|
|
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
package/pyproject.toml
CHANGED
|
@@ -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.
|
|
21
|
+
_FALLBACK_VERSION = "0.20.0" # x-release-please-version
|
|
22
22
|
|
|
23
23
|
try:
|
|
24
24
|
__version__: str = version("openhands-extensions")
|