@openhands/extensions 0.8.0 → 0.10.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.
Files changed (91) hide show
  1. package/.github/workflows/deprecation-check.yml +25 -0
  2. package/.release-please-manifest.json +1 -1
  3. package/README.md +3 -2
  4. package/automations/catalog/jira-issue-to-pr.json +14 -0
  5. package/automations/index.js +2 -0
  6. package/integrations/README.md +25 -0
  7. package/integrations/catalog/atlassian.json +91 -3
  8. package/integrations/catalog/datadog.json +33 -2
  9. package/integrations/catalog/github.json +20 -0
  10. package/integrations/catalog/microsoft-outlook.json +13 -0
  11. package/integrations/catalog/microsoft-teams.json +13 -0
  12. package/integrations/catalog/notion.json +13 -0
  13. package/integrations/catalog/onedrive.json +13 -0
  14. package/integrations/catalog/sharepoint.json +13 -0
  15. package/integrations/catalog/slack.json +14 -0
  16. package/integrations/catalog/superhuman-mail.json +36 -0
  17. package/integrations/catalog/vanta.json +55 -0
  18. package/integrations/catalog-index.js +73 -69
  19. package/integrations/catalog.schema.json +70 -3
  20. package/integrations/index.d.ts +49 -3
  21. package/marketplaces/openhands-extensions.json +10 -0
  22. package/package.json +1 -1
  23. package/plugins/cobol-modernization/skills/build-setup/SKILL.md +1 -0
  24. package/plugins/cobol-modernization/skills/cobol-modernization/SKILL.md +9 -0
  25. package/plugins/migration-scoring/skills/migration-scoring/SKILL.md +11 -0
  26. package/plugins/onboarding/skills/agent-readiness-report/SKILL.md +2 -0
  27. package/plugins/openhands/SKILL.md +7 -0
  28. package/plugins/release-notes/SKILL.md +9 -0
  29. package/pyproject.toml +6 -1
  30. package/python/openhands_extensions/__init__.py +38 -0
  31. package/python/openhands_extensions/_version.py +2 -2
  32. package/python/openhands_extensions/deprecation.py +159 -0
  33. package/python/openhands_extensions/integration_models.py +233 -0
  34. package/python/openhands_extensions/integrations.py +59 -4
  35. package/scripts/build-skills-catalog.mjs +1 -1
  36. package/scripts/check_deprecations.py +488 -0
  37. package/skills/add-skill/SKILL.md +2 -0
  38. package/skills/azure-devops/SKILL.md +12 -1
  39. package/skills/bitbucket-cloud/SKILL.md +11 -0
  40. package/skills/code-review/SKILL.md +1 -0
  41. package/skills/datadog/SKILL.md +3 -1
  42. package/skills/datadog/references/windows.md +45 -0
  43. package/skills/discord/SKILL.md +2 -0
  44. package/skills/docker/SKILL.md +5 -1
  45. package/skills/github/SKILL.md +3 -1
  46. package/skills/github/references/windows.md +48 -0
  47. package/skills/github-pr-review/SKILL.md +1 -0
  48. package/skills/github-pr-review/references/windows.md +47 -0
  49. package/skills/github-pr-reviewer/SKILL.md +1 -0
  50. package/skills/github-pr-reviewer/references/windows.md +61 -0
  51. package/skills/github-repo-monitor/SKILL.md +1 -0
  52. package/skills/github-repo-monitor/references/windows.md +61 -0
  53. package/skills/gitlab/SKILL.md +3 -1
  54. package/skills/incident-retrospective/SKILL.md +2 -0
  55. package/skills/index.js +36 -30
  56. package/skills/iterate/SKILL.md +1 -0
  57. package/skills/iterate/references/windows.md +41 -0
  58. package/skills/jira-issue-to-pr/.plugin/plugin.json +19 -0
  59. package/skills/jira-issue-to-pr/README.md +56 -0
  60. package/skills/jira-issue-to-pr/SKILL.md +216 -0
  61. package/skills/jira-issue-to-pr/references/setup.md +170 -0
  62. package/skills/jira-issue-to-pr/scripts/main.py +341 -0
  63. package/skills/jupyter/SKILL.md +7 -1
  64. package/skills/kubernetes/SKILL.md +2 -1
  65. package/skills/kubernetes/references/windows.md +38 -0
  66. package/skills/linear/SKILL.md +2 -0
  67. package/skills/linear/references/windows.md +29 -0
  68. package/skills/linear-triage/SKILL.md +2 -0
  69. package/skills/notion/SKILL.md +2 -0
  70. package/skills/notion/references/windows.md +43 -0
  71. package/skills/openhands-api/SKILL.md +1 -0
  72. package/skills/openhands-api/references/windows.md +44 -0
  73. package/skills/openhands-automation/SKILL.md +1 -0
  74. package/skills/openhands-automation/references/custom-automation.md +20 -0
  75. package/skills/openhands-automation/references/windows.md +57 -0
  76. package/skills/pdflatex/SKILL.md +3 -1
  77. package/skills/research-brief/SKILL.md +2 -0
  78. package/skills/skill-creator/SKILL.md +1 -0
  79. package/skills/skill-creator/references/windows.md +30 -0
  80. package/skills/slack-channel-monitor/SKILL.md +1 -0
  81. package/skills/slack-channel-monitor/references/windows.md +64 -0
  82. package/skills/slack-standup-digest/SKILL.md +2 -0
  83. package/skills/spark-version-upgrade/SKILL.md +2 -1
  84. package/skills/ssh/SKILL.md +2 -1
  85. package/skills/ssh/references/windows.md +59 -0
  86. package/skills/swift-linux/SKILL.md +2 -1
  87. package/skills/vercel/SKILL.md +5 -0
  88. package/tests/test_catalog_schema.py +58 -0
  89. package/tests/test_catalogs.py +6 -1
  90. package/tests/test_deprecations.py +136 -0
  91. package/tests/test_integration_catalog_in_sync.py +118 -7
@@ -5,75 +5,77 @@
5
5
  import entry0 from "./catalog/github.json" with { type: "json" };
6
6
  import entry1 from "./catalog/slack.json" with { type: "json" };
7
7
  import entry2 from "./catalog/tavily.json" with { type: "json" };
8
- import entry3 from "./catalog/linear.json" with { type: "json" };
9
- import entry4 from "./catalog/notion.json" with { type: "json" };
10
- import entry5 from "./catalog/ordinal.json" with { type: "json" };
11
- import entry6 from "./catalog/elevenlabs.json" with { type: "json" };
12
- import entry7 from "./catalog/bitbucket.json" with { type: "json" };
13
- import entry8 from "./catalog/xero.json" with { type: "json" };
14
- import entry9 from "./catalog/quickbooks.json" with { type: "json" };
15
- import entry10 from "./catalog/okta.json" with { type: "json" };
16
- import entry11 from "./catalog/netlify.json" with { type: "json" };
17
- import entry12 from "./catalog/vercel.json" with { type: "json" };
18
- import entry13 from "./catalog/supabase.json" with { type: "json" };
19
- import entry14 from "./catalog/posthog.json" with { type: "json" };
20
- import entry15 from "./catalog/sentry.json" with { type: "json" };
21
- import entry16 from "./catalog/datadog.json" with { type: "json" };
22
- import entry17 from "./catalog/canva.json" with { type: "json" };
23
- import entry18 from "./catalog/miro.json" with { type: "json" };
24
- import entry19 from "./catalog/webflow.json" with { type: "json" };
25
- import entry20 from "./catalog/zoom.json" with { type: "json" };
26
- import entry21 from "./catalog/discord.json" with { type: "json" };
27
- import entry22 from "./catalog/stripe.json" with { type: "json" };
28
- import entry23 from "./catalog/intercom.json" with { type: "json" };
29
- import entry24 from "./catalog/hubspot.json" with { type: "json" };
30
- import entry25 from "./catalog/salesforce.json" with { type: "json" };
31
- import entry26 from "./catalog/sharepoint.json" with { type: "json" };
32
- import entry27 from "./catalog/onedrive.json" with { type: "json" };
33
- import entry28 from "./catalog/microsoft-teams.json" with { type: "json" };
34
- import entry29 from "./catalog/microsoft-outlook.json" with { type: "json" };
35
- import entry30 from "./catalog/box.json" with { type: "json" };
36
- import entry31 from "./catalog/airtable.json" with { type: "json" };
37
- import entry32 from "./catalog/monday.json" with { type: "json" };
38
- import entry33 from "./catalog/trello.json" with { type: "json" };
39
- import entry34 from "./catalog/asana.json" with { type: "json" };
40
- import entry35 from "./catalog/confluence.json" with { type: "json" };
41
- import entry36 from "./catalog/jira.json" with { type: "json" };
42
- import entry37 from "./catalog/google-calendar.json" with { type: "json" };
43
- import entry38 from "./catalog/gmail.json" with { type: "json" };
44
- import entry39 from "./catalog/google-sheets.json" with { type: "json" };
45
- import entry40 from "./catalog/google-drive.json" with { type: "json" };
46
- import entry41 from "./catalog/figma.json" with { type: "json" };
47
- import entry42 from "./catalog/google-docs.json" with { type: "json" };
48
- import entry43 from "./catalog/apify.json" with { type: "json" };
49
- import entry44 from "./catalog/atlassian.json" with { type: "json" };
50
- import entry45 from "./catalog/brave-search.json" with { type: "json" };
51
- import entry46 from "./catalog/browser-mcp.json" with { type: "json" };
52
- import entry47 from "./catalog/clickhouse.json" with { type: "json" };
53
- import entry48 from "./catalog/cloudflare-bindings.json" with { type: "json" };
54
- import entry49 from "./catalog/cloudflare-browser-rendering.json" with { type: "json" };
55
- import entry50 from "./catalog/cloudflare-builds.json" with { type: "json" };
56
- import entry51 from "./catalog/cloudflare-docs.json" with { type: "json" };
57
- import entry52 from "./catalog/cloudflare-observability.json" with { type: "json" };
58
- import entry53 from "./catalog/deepwiki.json" with { type: "json" };
59
- import entry54 from "./catalog/everything.json" with { type: "json" };
60
- import entry55 from "./catalog/exa.json" with { type: "json" };
61
- import entry56 from "./catalog/fetch.json" with { type: "json" };
62
- import entry57 from "./catalog/filesystem.json" with { type: "json" };
63
- import entry58 from "./catalog/firecrawl.json" with { type: "json" };
64
- import entry59 from "./catalog/git.json" with { type: "json" };
65
- import entry60 from "./catalog/huggingface.json" with { type: "json" };
66
- import entry61 from "./catalog/kagi.json" with { type: "json" };
67
- import entry62 from "./catalog/memory.json" with { type: "json" };
68
- import entry63 from "./catalog/mongodb.json" with { type: "json" };
69
- import entry64 from "./catalog/neon.json" with { type: "json" };
70
- import entry65 from "./catalog/obsidian.json" with { type: "json" };
71
- import entry66 from "./catalog/paypal.json" with { type: "json" };
72
- import entry67 from "./catalog/playwright.json" with { type: "json" };
73
- import entry68 from "./catalog/redis.json" with { type: "json" };
74
- import entry69 from "./catalog/resend.json" with { type: "json" };
75
- import entry70 from "./catalog/sequential-thinking.json" with { type: "json" };
76
- import entry71 from "./catalog/time.json" with { type: "json" };
8
+ import entry3 from "./catalog/atlassian.json" with { type: "json" };
9
+ import entry4 from "./catalog/linear.json" with { type: "json" };
10
+ import entry5 from "./catalog/notion.json" with { type: "json" };
11
+ import entry6 from "./catalog/vanta.json" with { type: "json" };
12
+ import entry7 from "./catalog/ordinal.json" with { type: "json" };
13
+ import entry8 from "./catalog/elevenlabs.json" with { type: "json" };
14
+ import entry9 from "./catalog/bitbucket.json" with { type: "json" };
15
+ import entry10 from "./catalog/xero.json" with { type: "json" };
16
+ import entry11 from "./catalog/quickbooks.json" with { type: "json" };
17
+ import entry12 from "./catalog/okta.json" with { type: "json" };
18
+ import entry13 from "./catalog/netlify.json" with { type: "json" };
19
+ import entry14 from "./catalog/vercel.json" with { type: "json" };
20
+ import entry15 from "./catalog/supabase.json" with { type: "json" };
21
+ import entry16 from "./catalog/posthog.json" with { type: "json" };
22
+ import entry17 from "./catalog/sentry.json" with { type: "json" };
23
+ import entry18 from "./catalog/datadog.json" with { type: "json" };
24
+ import entry19 from "./catalog/canva.json" with { type: "json" };
25
+ import entry20 from "./catalog/miro.json" with { type: "json" };
26
+ import entry21 from "./catalog/webflow.json" with { type: "json" };
27
+ import entry22 from "./catalog/zoom.json" with { type: "json" };
28
+ import entry23 from "./catalog/discord.json" with { type: "json" };
29
+ import entry24 from "./catalog/stripe.json" with { type: "json" };
30
+ import entry25 from "./catalog/intercom.json" with { type: "json" };
31
+ import entry26 from "./catalog/hubspot.json" with { type: "json" };
32
+ import entry27 from "./catalog/salesforce.json" with { type: "json" };
33
+ import entry28 from "./catalog/sharepoint.json" with { type: "json" };
34
+ import entry29 from "./catalog/onedrive.json" with { type: "json" };
35
+ import entry30 from "./catalog/microsoft-teams.json" with { type: "json" };
36
+ import entry31 from "./catalog/microsoft-outlook.json" with { type: "json" };
37
+ import entry32 from "./catalog/box.json" with { type: "json" };
38
+ import entry33 from "./catalog/airtable.json" with { type: "json" };
39
+ import entry34 from "./catalog/monday.json" with { type: "json" };
40
+ import entry35 from "./catalog/trello.json" with { type: "json" };
41
+ import entry36 from "./catalog/asana.json" with { type: "json" };
42
+ import entry37 from "./catalog/confluence.json" with { type: "json" };
43
+ import entry38 from "./catalog/jira.json" with { type: "json" };
44
+ import entry39 from "./catalog/google-calendar.json" with { type: "json" };
45
+ import entry40 from "./catalog/gmail.json" with { type: "json" };
46
+ import entry41 from "./catalog/google-sheets.json" with { type: "json" };
47
+ import entry42 from "./catalog/google-drive.json" with { type: "json" };
48
+ import entry43 from "./catalog/figma.json" with { type: "json" };
49
+ import entry44 from "./catalog/google-docs.json" with { type: "json" };
50
+ import entry45 from "./catalog/apify.json" with { type: "json" };
51
+ import entry46 from "./catalog/brave-search.json" with { type: "json" };
52
+ import entry47 from "./catalog/browser-mcp.json" with { type: "json" };
53
+ import entry48 from "./catalog/clickhouse.json" with { type: "json" };
54
+ import entry49 from "./catalog/cloudflare-bindings.json" with { type: "json" };
55
+ import entry50 from "./catalog/cloudflare-browser-rendering.json" with { type: "json" };
56
+ import entry51 from "./catalog/cloudflare-builds.json" with { type: "json" };
57
+ import entry52 from "./catalog/cloudflare-docs.json" with { type: "json" };
58
+ import entry53 from "./catalog/cloudflare-observability.json" with { type: "json" };
59
+ import entry54 from "./catalog/deepwiki.json" with { type: "json" };
60
+ import entry55 from "./catalog/everything.json" with { type: "json" };
61
+ import entry56 from "./catalog/exa.json" with { type: "json" };
62
+ import entry57 from "./catalog/fetch.json" with { type: "json" };
63
+ import entry58 from "./catalog/filesystem.json" with { type: "json" };
64
+ import entry59 from "./catalog/firecrawl.json" with { type: "json" };
65
+ import entry60 from "./catalog/git.json" with { type: "json" };
66
+ import entry61 from "./catalog/huggingface.json" with { type: "json" };
67
+ import entry62 from "./catalog/kagi.json" with { type: "json" };
68
+ import entry63 from "./catalog/memory.json" with { type: "json" };
69
+ import entry64 from "./catalog/mongodb.json" with { type: "json" };
70
+ import entry65 from "./catalog/neon.json" with { type: "json" };
71
+ import entry66 from "./catalog/obsidian.json" with { type: "json" };
72
+ import entry67 from "./catalog/paypal.json" with { type: "json" };
73
+ import entry68 from "./catalog/playwright.json" with { type: "json" };
74
+ import entry69 from "./catalog/redis.json" with { type: "json" };
75
+ import entry70 from "./catalog/resend.json" with { type: "json" };
76
+ import entry71 from "./catalog/sequential-thinking.json" with { type: "json" };
77
+ import entry72 from "./catalog/superhuman-mail.json" with { type: "json" };
78
+ import entry73 from "./catalog/time.json" with { type: "json" };
77
79
 
78
80
  export const INTEGRATION_CATALOG_ENTRIES = [
79
81
  entry0,
@@ -148,4 +150,6 @@ export const INTEGRATION_CATALOG_ENTRIES = [
148
150
  entry69,
149
151
  entry70,
150
152
  entry71,
153
+ entry72,
154
+ entry73,
151
155
  ];
@@ -5,7 +5,7 @@
5
5
  "description": "Strict schema for integrations/catalog/*.json. Mirrors integrations/index.d.ts and encodes the cross-field connectability rules the catalog contract depends on.",
6
6
  "type": "object",
7
7
  "additionalProperties": false,
8
- "required": ["id", "name", "description", "connectionOptions"],
8
+ "required": ["id", "name", "description", "docsUrl", "connectionOptions"],
9
9
  "properties": {
10
10
  "id": { "type": "string", "minLength": 1 },
11
11
  "name": { "type": "string", "minLength": 1 },
@@ -39,7 +39,7 @@
39
39
  "marketplaceField": {
40
40
  "type": "object",
41
41
  "additionalProperties": false,
42
- "required": ["key", "label"],
42
+ "required": ["key", "label", "type", "required"],
43
43
  "properties": {
44
44
  "key": { "type": "string", "minLength": 1 },
45
45
  "label": { "type": "string", "minLength": 1 },
@@ -91,6 +91,72 @@
91
91
  }
92
92
  }
93
93
  },
94
+ "identityPath": {
95
+ "type": "string",
96
+ "pattern": "^[A-Za-z0-9_-]+(?:\\.[A-Za-z0-9_-]+)*$",
97
+ "minLength": 1
98
+ },
99
+ "identityMapping": {
100
+ "type": "object",
101
+ "additionalProperties": false,
102
+ "required": ["source", "externalPrincipalIdPath"],
103
+ "properties": {
104
+ "source": {
105
+ "enum": ["oauth_token_response", "access_token_claims", "identity_api"]
106
+ },
107
+ "endpoint": { "type": "string", "pattern": "^https://", "minLength": 8 },
108
+ "externalPrincipalIdPath": { "$ref": "#/$defs/identityPath" },
109
+ "externalTenantIdPath": { "$ref": "#/$defs/identityPath" },
110
+ "externalResourceIdPath": { "$ref": "#/$defs/identityPath" },
111
+ "resourceNamePath": { "$ref": "#/$defs/identityPath" },
112
+ "resourceUrlPath": { "$ref": "#/$defs/identityPath" }
113
+ },
114
+ "allOf": [
115
+ {
116
+ "if": { "properties": { "source": { "const": "identity_api" } } },
117
+ "then": { "required": ["endpoint"] },
118
+ "else": { "not": { "required": ["endpoint"] } }
119
+ }
120
+ ]
121
+ },
122
+ "resourceDiscovery": {
123
+ "type": "object",
124
+ "additionalProperties": false,
125
+ "required": ["endpoint", "externalResourceIdPath"],
126
+ "properties": {
127
+ "endpoint": { "type": "string", "pattern": "^https://", "minLength": 8 },
128
+ "itemsPath": { "$ref": "#/$defs/identityPath" },
129
+ "externalResourceIdPath": { "$ref": "#/$defs/identityPath" },
130
+ "resourceNamePath": { "$ref": "#/$defs/identityPath" },
131
+ "resourceUrlPath": { "$ref": "#/$defs/identityPath" }
132
+ }
133
+ },
134
+ "connectionModel": {
135
+ "type": "object",
136
+ "additionalProperties": false,
137
+ "required": [
138
+ "principalType",
139
+ "credentialScope",
140
+ "resourceType",
141
+ "resourceCardinality",
142
+ "selectionMode"
143
+ ],
144
+ "properties": {
145
+ "principalType": { "enum": ["user", "bot", "service_account", "application"] },
146
+ "credentialScope": { "enum": ["account", "tenant", "organization", "resource"] },
147
+ "resourceType": { "type": "string", "minLength": 1 },
148
+ "resourceCardinality": { "enum": ["one", "many"] },
149
+ "selectionMode": { "enum": ["automatic", "post_auth", "runtime"] },
150
+ "identityMapping": { "$ref": "#/$defs/identityMapping" },
151
+ "resourceDiscovery": { "$ref": "#/$defs/resourceDiscovery" }
152
+ },
153
+ "allOf": [
154
+ {
155
+ "if": { "properties": { "selectionMode": { "const": "post_auth" } } },
156
+ "then": { "required": ["resourceDiscovery"] }
157
+ }
158
+ ]
159
+ },
94
160
  "authConfig": {
95
161
  "type": "object",
96
162
  "additionalProperties": false,
@@ -186,7 +252,8 @@
186
252
  "provider": { "enum": ["mcp", "http"] },
187
253
  "transport": { "$ref": "#/$defs/transport" },
188
254
  "http": { "$ref": "#/$defs/httpConfig" },
189
- "auth": { "$ref": "#/$defs/authConfig" }
255
+ "auth": { "$ref": "#/$defs/authConfig" },
256
+ "connectionModel": { "$ref": "#/$defs/connectionModel" }
190
257
  },
191
258
  "allOf": [
192
259
  {
@@ -3,11 +3,11 @@ export type MarketplaceFieldType = "text" | "password";
3
3
  export interface MarketplaceField {
4
4
  key: string;
5
5
  label: string;
6
- type?: MarketplaceFieldType;
6
+ type: MarketplaceFieldType;
7
7
  placeholder?: string;
8
8
  helperText?: string;
9
9
  helperLink?: string;
10
- required?: boolean;
10
+ required: boolean;
11
11
  }
12
12
 
13
13
  export type IntegrationTransport =
@@ -95,12 +95,58 @@ export interface IntegrationHttpConfig {
95
95
  openApiUrl?: string;
96
96
  }
97
97
 
98
+ export type IntegrationPrincipalType =
99
+ | "user"
100
+ | "bot"
101
+ | "service_account"
102
+ | "application";
103
+
104
+ export type IntegrationCredentialScope =
105
+ | "account"
106
+ | "tenant"
107
+ | "organization"
108
+ | "resource";
109
+
110
+ export type IntegrationIdentitySource =
111
+ | "oauth_token_response"
112
+ | "access_token_claims"
113
+ | "identity_api";
114
+
115
+ export interface IntegrationIdentityMapping {
116
+ source: IntegrationIdentitySource;
117
+ endpoint?: string;
118
+ externalPrincipalIdPath: string;
119
+ externalTenantIdPath?: string;
120
+ externalResourceIdPath?: string;
121
+ resourceNamePath?: string;
122
+ resourceUrlPath?: string;
123
+ }
124
+
125
+ export interface IntegrationResourceDiscovery {
126
+ endpoint: string;
127
+ itemsPath?: string;
128
+ externalResourceIdPath: string;
129
+ resourceNamePath?: string;
130
+ resourceUrlPath?: string;
131
+ }
132
+
133
+ export interface IntegrationConnectionModel {
134
+ principalType: IntegrationPrincipalType;
135
+ credentialScope: IntegrationCredentialScope;
136
+ resourceType: string;
137
+ resourceCardinality: "one" | "many";
138
+ selectionMode: "automatic" | "post_auth" | "runtime";
139
+ identityMapping?: IntegrationIdentityMapping;
140
+ resourceDiscovery?: IntegrationResourceDiscovery;
141
+ }
142
+
98
143
  export interface IntegrationConnectionOption {
99
144
  id: "oauth" | "api" | "none" | string;
100
145
  provider: IntegrationProvider;
101
146
  transport?: IntegrationTransport;
102
147
  http?: IntegrationHttpConfig;
103
148
  auth: IntegrationAuthConfig;
149
+ connectionModel?: IntegrationConnectionModel;
104
150
  }
105
151
 
106
152
 
@@ -110,7 +156,7 @@ export interface IntegrationCatalogEntry {
110
156
  description: string;
111
157
  categories?: string[];
112
158
  appUrl?: string;
113
- docsUrl?: string;
159
+ docsUrl: string;
114
160
  notes?: string;
115
161
  iconBg?: string;
116
162
  iconColor?: string;
@@ -737,6 +737,16 @@
737
737
  "keywords": [
738
738
  "plain-english"
739
739
  ]
740
+ },
741
+ {
742
+ "name": "jira-issue-to-pr",
743
+ "source": "./skills/jira-issue-to-pr",
744
+ "description": "Deploy a cron-based OpenHands automation that watches a Jira Cloud project for issues labeled with a configurable label (default: create-pr) and spawns an agent conversation to create a GitHub pull request for each new issue found. The target GitHub repo is read from the ticket body - no repo parameter required at deploy time.",
745
+ "category": "productivity",
746
+ "keywords": [
747
+ "jira",
748
+ "atlassian"
749
+ ]
740
750
  }
741
751
  ]
742
752
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openhands/extensions",
3
- "version": "0.8.0",
3
+ "version": "0.10.0",
4
4
  "description": "Public OpenHands extension catalogs for skills, plugins, integrations, and automation templates.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -13,6 +13,7 @@ triggers:
13
13
  Set up a build environment and create test fixtures for validating COBOL-to-Java migrations.
14
14
 
15
15
  To install GnuCOBOL, run: `./scripts/install-gnucobol.sh`
16
+ On Windows, run that shell script from Git Bash/WSL (`bash scripts/install-gnucobol.sh`) or install GnuCOBOL with a Windows package manager and document the chosen command in `build_notes.md`.
16
17
 
17
18
  ## Phase 1: Build Setup
18
19
 
@@ -37,6 +37,15 @@ export LLM_MODEL="anthropic/claude-3-5-sonnet-20241022"
37
37
  uv run python -m lc_sdk_examples.cobol_modernization --src-path /path/to/cobol/project
38
38
  ```
39
39
 
40
+ PowerShell equivalent for the environment setup:
41
+
42
+ ```powershell
43
+ $env:LLM_API_KEY = "your-api-key"
44
+ $env:LLM_MODEL = "anthropic/claude-3-5-sonnet-20241022"
45
+
46
+ uv run python -m lc_sdk_examples.cobol_modernization --src-path C:\path\to\cobol\project
47
+ ```
48
+
40
49
  ## Workflow Phases
41
50
 
42
51
  ### Phase 1: Build Setup
@@ -39,6 +39,17 @@ uv run python -m lc_sdk_examples.migration_scoring \
39
39
  --rubric-path /path/to/style_rubric.txt
40
40
  ```
41
41
 
42
+ PowerShell equivalent for the environment setup:
43
+
44
+ ```powershell
45
+ $env:LLM_API_KEY = "your-api-key"
46
+ $env:LLM_MODEL = "anthropic/claude-3-5-sonnet-20241022"
47
+
48
+ uv run python -m lc_sdk_examples.migration_scoring `
49
+ --src-path C:\path\to\migration\project `
50
+ --rubric-path C:\path\to\style_rubric.txt
51
+ ```
52
+
42
53
  ## Workflow Phases
43
54
 
44
55
  ### Phase 1: Migration Mapping
@@ -51,6 +51,8 @@ Or scan all five at once:
51
51
  for s in scripts/scan_*.sh; do bash "$s" /path/to/repo; echo; done
52
52
  ```
53
53
 
54
+ On Windows, run these `.sh` helpers from Git Bash or WSL and pass a path that environment can read. Native PowerShell cannot execute the shell scripts directly.
55
+
54
56
  **Important**: The scripts are helpers, not scorers. They find files and
55
57
  patterns but do not evaluate quality. Many features require judgment that only
56
58
  reading the actual files can provide — for example, whether a README includes
@@ -31,6 +31,12 @@ This plugin provides a unified entry point and the CLI integration script.
31
31
  command -v openhands &>/dev/null && echo "CLI available" || echo "CLI not found"
32
32
  ```
33
33
 
34
+ PowerShell check:
35
+
36
+ ```powershell
37
+ if (Get-Command openhands -ErrorAction SilentlyContinue) { "CLI available" } else { "CLI not found" }
38
+ ```
39
+
34
40
  2. **If CLI is available**, use it — it manages auth and API keys automatically.
35
41
  3. **If CLI is not available**, check for an API key:
36
42
  - Preferred env var: `OPENHANDS_CLOUD_API_KEY`
@@ -49,6 +55,7 @@ command -v openhands &>/dev/null && echo "CLI available" || echo "CLI not found"
49
55
  ```
50
56
 
51
57
  The script checks for the CLI, installs it if needed, sends the task, and opens the resulting conversation URL.
58
+ On Windows, run this POSIX shell script from Git Bash or WSL (`bash scripts/run.sh "Investigate flaky tests in tests/test_api.py"`) unless a native PowerShell launcher is available.
52
59
 
53
60
  If the script exits with code `2` (`AUTH_REQUIRED`), ask the user to complete authentication in the browser, then re-run.
54
61
 
@@ -32,6 +32,15 @@ curl -o .github/workflows/release-notes.yml \
32
32
  https://raw.githubusercontent.com/OpenHands/extensions/main/plugins/release-notes/workflows/release-notes.yml
33
33
  ```
34
34
 
35
+ PowerShell equivalent:
36
+
37
+ ```powershell
38
+ New-Item -ItemType Directory -Force .github\workflows | Out-Null
39
+ Invoke-WebRequest `
40
+ -Uri https://raw.githubusercontent.com/OpenHands/extensions/main/plugins/release-notes/workflows/release-notes.yml `
41
+ -OutFile .github\workflows\release-notes.yml
42
+ ```
43
+
35
44
  Configure required secrets (see the README for details).
36
45
 
37
46
  ### Manual Invocation
package/pyproject.toml CHANGED
@@ -1,8 +1,13 @@
1
1
  [project]
2
2
  name = "openhands-extensions"
3
- version = "0.8.0"
3
+ version = "0.10.0"
4
4
  description = "OpenHands extensions, plugins, and skills (Python bindings for the integration catalog)"
5
5
  requires-python = ">=3.12"
6
+ dependencies = [
7
+ "deprecation>=2.1,<3",
8
+ "packaging>=24,<26",
9
+ "pydantic>=2.10,<3",
10
+ ]
6
11
 
7
12
  [build-system]
8
13
  requires = ["hatchling>=1.21"]
@@ -13,12 +13,50 @@ from ._version import __version__
13
13
  from .integrations import (
14
14
  INTEGRATION_CATALOG_SNAPSHOT,
15
15
  get_integration_catalog_entry,
16
+ get_integration_catalog_entry_model,
16
17
  list_integration_catalog,
18
+ list_integration_catalog_models,
19
+ )
20
+ from .integration_models import (
21
+ HttpConnectionOption,
22
+ IntegrationAuthConfig,
23
+ IntegrationCatalogEntry,
24
+ IntegrationCatalogSnapshot,
25
+ IntegrationConnectionOption,
26
+ IntegrationConnectionModel,
27
+ IntegrationHttpConfig,
28
+ IntegrationIdentityMapping,
29
+ IntegrationOAuthConfig,
30
+ IntegrationResourceDiscovery,
31
+ IntegrationTransport,
32
+ McpConnectionOption,
33
+ MarketplaceField,
34
+ SseTransport,
35
+ StdioTransport,
36
+ StreamableHttpTransport,
17
37
  )
18
38
 
19
39
  __all__ = [
20
40
  "INTEGRATION_CATALOG_SNAPSHOT",
41
+ "HttpConnectionOption",
42
+ "IntegrationAuthConfig",
43
+ "IntegrationCatalogEntry",
44
+ "IntegrationCatalogSnapshot",
45
+ "IntegrationConnectionOption",
46
+ "IntegrationConnectionModel",
47
+ "IntegrationHttpConfig",
48
+ "IntegrationIdentityMapping",
49
+ "IntegrationOAuthConfig",
50
+ "IntegrationResourceDiscovery",
51
+ "IntegrationTransport",
52
+ "MarketplaceField",
53
+ "McpConnectionOption",
54
+ "SseTransport",
55
+ "StdioTransport",
56
+ "StreamableHttpTransport",
21
57
  "__version__",
22
58
  "get_integration_catalog_entry",
59
+ "get_integration_catalog_entry_model",
23
60
  "list_integration_catalog",
61
+ "list_integration_catalog_models",
24
62
  ]
@@ -16,8 +16,8 @@ from importlib.metadata import PackageNotFoundError, version
16
16
 
17
17
  #: Fallback used only when the package is not installed (no dist metadata).
18
18
  #: Kept in lock-step with pyproject.toml/package.json by the version test.
19
- # x-release-please-update-version
20
- _FALLBACK_VERSION = "0.8.0"
19
+ # x-release-please-version
20
+ _FALLBACK_VERSION = "0.10.0"
21
21
 
22
22
  try:
23
23
  __version__: str = version("openhands-extensions")