@openhands/extensions 0.19.0 → 0.21.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 (64) hide show
  1. package/.github/workflows/check-extensions.yml +4 -0
  2. package/.github/workflows/pr-artifacts.yml +294 -0
  3. package/.github/workflows/pr-description-check.yml +4 -2
  4. package/.release-please-manifest.json +1 -1
  5. package/AGENTS.md +28 -4
  6. package/README.md +5 -2
  7. package/automations/README.md +52 -36
  8. package/automations/bundle-index.js +13 -3
  9. package/automations/catalog/custom-automation/manifest.json +229 -0
  10. package/automations/catalog/github-agents-md-maintainer/manifest.json +2 -1
  11. package/automations/catalog/github-issue-to-pr/manifest.json +3 -2
  12. package/automations/catalog/github-issue-triage/manifest.json +72 -0
  13. package/automations/catalog/github-pr-reviewer/manifest.json +3 -2
  14. package/automations/catalog/gitlab-issue-to-mr/manifest.json +124 -0
  15. package/automations/catalog/qa-changes/manifest.json +1 -1
  16. package/automations/catalog-index.js +23 -17
  17. package/automations/catalog.schema.json +81 -7
  18. package/automations/index.d.ts +52 -2
  19. package/automations/interface.json +2 -1
  20. package/integrations/catalog/gitlab.json +27 -5
  21. package/integrations/catalog/reportportal.json +76 -0
  22. package/integrations/catalog-index.js +6 -4
  23. package/marketplaces/openhands-extensions.json +36 -0
  24. package/package.json +1 -1
  25. package/pyproject.toml +2 -2
  26. package/python/openhands_extensions/_version.py +1 -1
  27. package/skills/github/scripts/github_client.py +204 -0
  28. package/skills/github-agents-md-maintainer/SKILL.md +7 -1
  29. package/skills/github-agents-md-maintainer/scripts/main.py +4 -40
  30. package/skills/github-issue-to-pr/SKILL.md +8 -1
  31. package/skills/github-issue-to-pr/scripts/main.py +3 -40
  32. package/skills/github-issue-triage/.plugin/plugin.json +9 -0
  33. package/skills/github-issue-triage/README.md +9 -0
  34. package/skills/github-issue-triage/SKILL.md +37 -0
  35. package/skills/github-issue-triage/commands/github-issue-triage.md +8 -0
  36. package/skills/github-issue-triage/scripts/worker.py +123 -0
  37. package/skills/github-pr-reviewer/SKILL.md +8 -1
  38. package/skills/github-pr-reviewer/scripts/main.py +3 -41
  39. package/skills/github-repo-monitor/SKILL.md +7 -1
  40. package/skills/github-repo-monitor/scripts/main.py +4 -46
  41. package/skills/gitlab-issue-to-mr/.plugin/plugin.json +19 -0
  42. package/skills/gitlab-issue-to-mr/README.md +92 -0
  43. package/skills/gitlab-issue-to-mr/SKILL.md +408 -0
  44. package/skills/gitlab-issue-to-mr/commands/issue-to-mr-setup.md +8 -0
  45. package/skills/gitlab-issue-to-mr/references/state-schema.md +140 -0
  46. package/skills/gitlab-issue-to-mr/scripts/main.py +1448 -0
  47. package/skills/index.js +43 -6
  48. package/skills/openhands-automation/README.md +1 -1
  49. package/skills/openhands-automation/SKILL.md +18 -8
  50. package/skills/openhands-enterprise-troubleshooting/.plugin/plugin.json +20 -0
  51. package/skills/openhands-enterprise-troubleshooting/README.md +79 -0
  52. package/skills/openhands-enterprise-troubleshooting/SKILL.md +339 -0
  53. package/skills/openhands-enterprise-troubleshooting/references/diagnostics.md +698 -0
  54. package/skills/openhands-enterprise-troubleshooting/references/support-bundle-analysis.md +570 -0
  55. package/skills/openhands-enterprise-troubleshooting/scripts/bundle_triage.py +532 -0
  56. package/skills/openhands-sdk/SKILL.md +2 -0
  57. package/tests/fixtures/automations/custom-automation.json +398 -0
  58. package/tests/fixtures/automations/github-pr-reviewer.json +9 -9
  59. package/tests/github_automation_helpers.py +25 -0
  60. package/tests/test_automation_setup.py +340 -92
  61. package/tests/test_github_automation_foundation.py +73 -0
  62. package/tests/test_github_skill_installation.py +63 -0
  63. package/tests/test_github_triage_delivery.py +53 -0
  64. package/tests/test_gitlab_issue_to_mr.py +823 -0
@@ -0,0 +1,140 @@
1
+ # State Schema
2
+
3
+ The automation maintains a JSON state document **per project**, persisted across
4
+ polling runs. It is the source of truth for which trigger-label events have
5
+ already queued work, which conversations are still active, and which clones are
6
+ still on disk.
7
+
8
+ Each project in `PROJECTS` gets its own document, so issue IIDs from different
9
+ projects never share a bucket.
10
+
11
+ The document holds only what a poll needs in order to decide what to do next.
12
+ Issue metadata that can be read back from GitLab is not mirrored here, so there
13
+ is nothing to drift.
14
+
15
+ ---
16
+
17
+ ## Storage
18
+
19
+ **Primary (cloud):** The state is stored in the automation service's built-in KV
20
+ store under the key `state:{group}__{project}` - for example
21
+ `state:gitlab-org__gitlab`. Subgroups keep their separators, so
22
+ `group/team/service` becomes `state:group__team__service`. The KV store is
23
+ available when `AUTOMATION_KV_TOKEN` is injected into the run environment. Each
24
+ automation has its own isolated namespace.
25
+
26
+ **Fallback (local/dev):** When the KV store is not available, the state is
27
+ written to a local JSON file at:
28
+
29
+ ```
30
+ {WORKSPACE_BASE_ROOT}/automation-state/gitlab_issue_to_mr_{automation_id}_{group}__{project}.json
31
+ ```
32
+
33
+ `WORKSPACE_BASE_ROOT` is derived by going two levels up from the `WORKSPACE_BASE`
34
+ environment variable, stripping `automation-runs/{run_id}`.
35
+
36
+ Example on a local install:
37
+
38
+ ```
39
+ ~/.openhands/workspaces/automation-state/gitlab_issue_to_mr_abc12345-..._myorg__backend.json
40
+ ```
41
+
42
+ The `automation_id` is read from the `AUTOMATION_EVENT_PAYLOAD` environment
43
+ variable, field `automation_id`.
44
+
45
+ ---
46
+
47
+ ## Top-Level Schema
48
+
49
+ ```jsonc
50
+ {
51
+ "version": 1,
52
+ "project": "group/project",
53
+ "trigger_label": "openhands",
54
+ "updated_at": 1717200000.0,
55
+ "tasks": {}
56
+ }
57
+ ```
58
+
59
+ ---
60
+
61
+ ## `tasks` Map
62
+
63
+ Key: `"{issue_iid}:label:{label_event_id}"`. This makes the latest GitLab
64
+ resource label event with `action: "add"` the idempotency key. Re-applying the
65
+ trigger label creates a new event and therefore a new task, on a new branch.
66
+
67
+ Value: **TaskRecord**
68
+
69
+ ```jsonc
70
+ {
71
+ "issue_iid": 42,
72
+ "issue_title": "Retry uploads on a 502",
73
+ "trigger_label_event_id": 123456789,
74
+ "trigger_label_event_created_at": "2026-06-12T00:00:00Z",
75
+ "web_url": "https://gitlab.com/group/project/-/issues/42",
76
+ "base_branch": "main",
77
+ "base_sha": "0123456789abcdef...",
78
+ "branch": "openhands/issue-42",
79
+ "status": "active",
80
+ "conversation_id": "conv_abc123",
81
+ "workspace_dir": "/workspace/issue-to-mr/group__project/issue-42-123456789",
82
+ "last_activity": 1717200000.0,
83
+ "finalize_attempts": 1,
84
+ "merge_request_url": "https://gitlab.com/group/project/-/merge_requests/57",
85
+ "merge_request_iid": 57,
86
+ "completed_at": 1717203600.0,
87
+ "expired_after": 7200.5,
88
+ "error": "git push origin ... failed (128): ..."
89
+ }
90
+ ```
91
+
92
+ | Field | Written when | Meaning |
93
+ |---|---|---|
94
+ | `issue_iid` | claim | The issue being implemented, by its project-scoped IID |
95
+ | `issue_title` | claim | Used for the commit message and the merge request title |
96
+ | `trigger_label_event_id` | claim | The GitLab label event this task belongs to |
97
+ | `trigger_label_event_created_at` | claim | When that label was applied |
98
+ | `web_url` | claim | The issue URL |
99
+ | `base_branch` | claim | The project's default branch at claim time |
100
+ | `base_sha` | start | The commit the clone starts from; commits are counted against it |
101
+ | `branch` | start | The branch the merge request is opened from |
102
+ | `status` | throughout | See the lifecycle below |
103
+ | `conversation_id` | start | The OpenHands conversation doing the work |
104
+ | `workspace_dir` | start | The clone. Removed, and the field dropped, once the task ends |
105
+ | `last_activity` | throughout | Drives the debounce, the two-hour abandonment, and the stalled-claim release |
106
+ | `finalize_attempts` | finalize | How many times pushing and opening the merge request has been tried |
107
+ | `merge_request_url` / `merge_request_iid` | success | The merge request that was opened |
108
+ | `completed_at` | end | When the task reached a terminal status |
109
+ | `expired_after` | expiry | Seconds the conversation ran before being abandoned |
110
+ | `error` | failure | The last finalization error, after the retries ran out |
111
+
112
+ ---
113
+
114
+ ## Task Lifecycle
115
+
116
+ ```
117
+ label event seen
118
+ │
119
+ ▼
120
+ "starting" ── claim persisted before the slow work, so an
121
+ │ overlapping poll cannot start it twice.
122
+ │ Released after 15 minutes if the poll died.
123
+ clone + conversation
124
+ │
125
+ ▼
126
+ "active"
127
+ │
128
+ ┌─────────────┬───────┴────────┬──────────────┬─────────────────┐
129
+ ▼ ▼ ▼ ▼ ▼
130
+ "issue-closed" "failed" "no-changes" "closed" "expired"
131
+ issue closed conversation agent produced merge request no terminal
132
+ meanwhile errored, or no commits; opened and status within
133
+ push/MR gave its answer is linked on the two hours
134
+ up after 3 posted on the issue
135
+ attempts issue
136
+ ```
137
+
138
+ Every terminal status releases the clone, but only once the conversation is
139
+ confirmed stopped. When that cannot be confirmed, `workspace_dir` stays in the
140
+ record and a later poll retries the removal.