@openhands/extensions 0.17.0 → 0.18.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 (42) hide show
  1. package/.release-please-manifest.json +1 -1
  2. package/README.md +5 -2
  3. package/automations/README.md +3 -2
  4. package/automations/bundle-index.js +9 -0
  5. package/automations/catalog/github-agents-md-maintainer/manifest.json +96 -0
  6. package/automations/catalog/github-issue-to-pr/manifest.json +107 -0
  7. package/automations/catalog/github-pr-reviewer/manifest.json +1 -0
  8. package/automations/catalog/github-repo-monitor/manifest.json +1 -0
  9. package/automations/catalog/news-digest/manifest.json +76 -0
  10. package/automations/catalog-index.js +13 -7
  11. package/automations/catalog.schema.json +10 -2
  12. package/automations/index.d.ts +18 -1
  13. package/automations/interface.json +3 -1
  14. package/marketplaces/openhands-extensions.json +38 -0
  15. package/package.json +1 -1
  16. package/pyproject.toml +1 -1
  17. package/python/openhands_extensions/_version.py +1 -1
  18. package/skills/github-agents-md-maintainer/.plugin/plugin.json +19 -0
  19. package/skills/github-agents-md-maintainer/README.md +59 -0
  20. package/skills/github-agents-md-maintainer/SKILL.md +271 -0
  21. package/skills/github-agents-md-maintainer/commands/agents-md-setup.md +8 -0
  22. package/skills/github-agents-md-maintainer/references/state-schema.md +113 -0
  23. package/skills/github-agents-md-maintainer/scripts/main.py +1187 -0
  24. package/skills/github-issue-to-pr/.plugin/plugin.json +19 -0
  25. package/skills/github-issue-to-pr/README.md +84 -0
  26. package/skills/github-issue-to-pr/SKILL.md +373 -0
  27. package/skills/github-issue-to-pr/commands/issue-to-pr-setup.md +8 -0
  28. package/skills/github-issue-to-pr/references/state-schema.md +139 -0
  29. package/skills/github-issue-to-pr/scripts/main.py +1305 -0
  30. package/skills/index.js +27 -0
  31. package/skills/news-digest/.plugin/plugin.json +19 -0
  32. package/skills/news-digest/README.md +71 -0
  33. package/skills/news-digest/SKILL.md +284 -0
  34. package/skills/news-digest/commands/news-digest-setup.md +8 -0
  35. package/skills/news-digest/references/state-schema.md +178 -0
  36. package/skills/news-digest/scripts/main.py +1250 -0
  37. package/tests/fixtures/automations/github-repo-monitor.json +77 -0
  38. package/tests/test_automation_setup.py +34 -0
  39. package/tests/test_catalogs.py +3 -1
  40. package/tests/test_github_agents_md_maintainer.py +352 -0
  41. package/tests/test_github_issue_to_pr.py +539 -0
  42. package/tests/test_news_digest.py +646 -0
@@ -0,0 +1,96 @@
1
+ {
2
+ "id": "github-agents-md-maintainer",
3
+ "name": "AGENTS.md Maintainer",
4
+ "category": "Documentation",
5
+ "icon": "bot",
6
+ "description": "Keep AGENTS.md current in your repositories. On a schedule, an agent reads the repository, creates or updates AGENTS.md, and opens a pull request - and stays quiet while one of its pull requests is still open.",
7
+ "requires": {
8
+ "integrations": {
9
+ "github": {
10
+ "message": "Used to read the repository, push the branch, and open the pull request."
11
+ }
12
+ },
13
+ "features": [
14
+ "customTarball"
15
+ ]
16
+ },
17
+ "popularityRank": 80,
18
+ "estimatedSetupMinutes": 3,
19
+ "exampleImplementation": "Trigger: cron, weekly by default (0 9 * * 1)\nRequired secret: GITHUB_PERSONAL_ACCESS_TOKEN, with permission to write contents and pull requests\n\n1. Read the repositories, branch prefix, pull request mode, and schedule from setup.\n2. Process each repository independently, with its own state, so one falling behind never blocks another.\n3. Key one unit of work to the ISO week, so a cron that fires more often, a retried run, or a restarted service cannot open the same pull request twice.\n4. Skip a repository whose previous pull request from this automation is still open; a second one would edit the same file.\n5. Ask GitHub whether AGENTS.md exists, which decides create vs update and the pull request title.\n6. Clone the default branch into a directory of its own, create the working branch, and start an OpenHands conversation with that directory as its workspace.\n7. The agent reads the repository, edits AGENTS.md, commits, pushes, and opens the pull request; the script verifies that on GitHub and opens it itself when the agent did not.\n8. Record no-changes when AGENTS.md is already accurate, which is the expected result most weeks.\n9. Remove the clone once the conversation has stopped.",
20
+ "setup": {
21
+ "version": "1.0",
22
+ "mode": "direct",
23
+ "form": {
24
+ "triggers": {
25
+ "cron": {
26
+ "schedule": {
27
+ "type": "cron",
28
+ "label": "Check frequency",
29
+ "help": "How often to review AGENTS.md. Work is keyed by ISO week, so a schedule more frequent than weekly only polls.",
30
+ "default": "0 9 * * 1",
31
+ "required": true
32
+ },
33
+ "timezone": {
34
+ "type": "timezone",
35
+ "label": "Timezone",
36
+ "help": "Timezone the schedule is interpreted in.",
37
+ "default": "UTC",
38
+ "required": true
39
+ }
40
+ }
41
+ },
42
+ "args": {
43
+ "repositories": {
44
+ "type": "repo-picker",
45
+ "label": "Repositories",
46
+ "help": "The repositories whose AGENTS.md is maintained. Each keeps its own state and its own weekly claim.",
47
+ "provider": "github",
48
+ "multiple": true,
49
+ "required": true
50
+ },
51
+ "branchPrefix": {
52
+ "type": "text",
53
+ "label": "Branch prefix",
54
+ "help": "Branches are named after this prefix and the ISO week, such as openhands/agents-md-2026-W34. It is also how the automation recognises its own open pull requests.",
55
+ "default": "openhands/agents-md",
56
+ "required": true,
57
+ "constraints": {
58
+ "minLength": 1,
59
+ "maxLength": 50
60
+ }
61
+ },
62
+ "pullRequestMode": {
63
+ "type": "select",
64
+ "label": "Pull request mode",
65
+ "help": "Whether the pull request is opened as a draft or ready for review.",
66
+ "default": "draft",
67
+ "required": true,
68
+ "options": [
69
+ {
70
+ "value": "draft",
71
+ "label": "Draft"
72
+ },
73
+ {
74
+ "value": "ready",
75
+ "label": "Ready for review"
76
+ }
77
+ ]
78
+ }
79
+ }
80
+ },
81
+ "bundle": {
82
+ "version": "1.0.0",
83
+ "entrypoint": "python3 main.py",
84
+ "timeout": 900,
85
+ "files": {
86
+ "main.py": "skills/github-agents-md-maintainer/scripts/main.py"
87
+ },
88
+ "config": {
89
+ "repos": "{{form.repositories}}",
90
+ "branch_prefix": "{{form.branchPrefix}}",
91
+ "pull_request_mode": "{{form.pullRequestMode}}"
92
+ }
93
+ },
94
+ "message": "This deployment cannot run the scheduled AGENTS.md automation directly. Set it up in this conversation instead: confirm the repositories to maintain, the branch prefix, whether pull requests open as drafts, and the schedule, then create the automation."
95
+ }
96
+ }
@@ -0,0 +1,107 @@
1
+ {
2
+ "id": "github-issue-to-pr",
3
+ "name": "GitHub Issue to PR Agent",
4
+ "category": "Software development",
5
+ "description": "Watch for a configurable label on GitHub issues, implement the issue in a clone of the default branch, and open a pull request for each label event.",
6
+ "requires": {
7
+ "integrations": {
8
+ "github": {
9
+ "message": "Used to read labelled issues, push the branch, and open the pull request."
10
+ }
11
+ },
12
+ "features": [
13
+ "customTarball"
14
+ ]
15
+ },
16
+ "popularityRank": 95,
17
+ "estimatedSetupMinutes": 4,
18
+ "exampleImplementation": "Trigger: cron polling for open GitHub issues with a configured label such as openhands\nRequired secret: GITHUB_PERSONAL_ACCESS_TOKEN, with permission to write contents, issues, and pull requests\n\n1. Read the repositories, trigger label, branch prefix, draft mode, and polling schedule from setup.\n2. Poll each repository independently, with its own state, so issue numbers never collide.\n3. List open labelled issues, drop pull requests, and find the latest matching GitHub labeled issue event for each.\n4. Deduplicate on the label event ID so every label application queues exactly one attempt.\n5. Clone the default branch into a directory of its own, create the working branch, and start an OpenHands conversation with that directory as its workspace. The clone carries no credential and the agent is handed no secrets, because the prompt is built from an issue body that anyone can write.\n6. Comment on the issue with the branch and the conversation link.\n7. Once the conversation has stopped, commit whatever the agent left, push the branch, open a draft pull request titled after the issue, and comment the link on the issue. An agent that made no changes gets its answer posted instead.\n8. Remove the clone once the conversation has stopped, so nothing accumulates between runs.",
19
+ "setup": {
20
+ "version": "1.0",
21
+ "mode": "direct",
22
+ "form": {
23
+ "triggers": {
24
+ "cron": {
25
+ "schedule": {
26
+ "type": "cron",
27
+ "label": "Check frequency",
28
+ "help": "How often to look for newly labelled issues.",
29
+ "default": "*/15 * * * *",
30
+ "required": true
31
+ },
32
+ "timezone": {
33
+ "type": "timezone",
34
+ "label": "Timezone",
35
+ "help": "Timezone the schedule is interpreted in.",
36
+ "default": "UTC",
37
+ "required": true
38
+ }
39
+ }
40
+ },
41
+ "args": {
42
+ "repositories": {
43
+ "type": "repo-picker",
44
+ "label": "Repositories",
45
+ "help": "The repositories whose labelled issues are implemented. Each is polled independently and keeps its own state, so issue numbers never collide between them.",
46
+ "provider": "github",
47
+ "multiple": true,
48
+ "required": true
49
+ },
50
+ "triggerLabel": {
51
+ "type": "text",
52
+ "label": "Trigger label",
53
+ "help": "Only issues carrying this label are worked on.",
54
+ "default": "openhands",
55
+ "required": true,
56
+ "constraints": {
57
+ "minLength": 1,
58
+ "maxLength": 50
59
+ }
60
+ },
61
+ "branchPrefix": {
62
+ "type": "text",
63
+ "label": "Branch prefix",
64
+ "help": "Branches are named after this prefix and the issue number, such as openhands/issue-42.",
65
+ "default": "openhands/issue",
66
+ "required": true,
67
+ "constraints": {
68
+ "minLength": 1,
69
+ "maxLength": 50
70
+ }
71
+ },
72
+ "pullRequestMode": {
73
+ "type": "select",
74
+ "label": "Pull request mode",
75
+ "help": "Whether the pull request is opened as a draft or ready for review.",
76
+ "default": "draft",
77
+ "required": true,
78
+ "options": [
79
+ {
80
+ "value": "draft",
81
+ "label": "Draft"
82
+ },
83
+ {
84
+ "value": "ready",
85
+ "label": "Ready for review"
86
+ }
87
+ ]
88
+ }
89
+ }
90
+ },
91
+ "bundle": {
92
+ "version": "1.0.0",
93
+ "entrypoint": "python3 main.py",
94
+ "timeout": 900,
95
+ "files": {
96
+ "main.py": "skills/github-issue-to-pr/scripts/main.py"
97
+ },
98
+ "config": {
99
+ "repos": "{{form.repositories}}",
100
+ "trigger_label": "{{form.triggerLabel}}",
101
+ "branch_prefix": "{{form.branchPrefix}}",
102
+ "pull_request_mode": "{{form.pullRequestMode}}"
103
+ }
104
+ },
105
+ "message": "This deployment cannot run the scheduled issue-to-PR automation directly. Set it up in this conversation instead: confirm the repositories to watch, the trigger label, the branch prefix, whether pull requests open as drafts, and the polling schedule, then create the automation."
106
+ }
107
+ }
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "id": "github-pr-reviewer",
3
+ "version": "1.0.0",
3
4
  "name": "GitHub Code Review Agent",
4
5
  "category": "Code review",
5
6
  "description": "Watch for a configurable label on GitHub pull requests, inspect full PR and repository context, and post an AI review comment once per label event.",
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "id": "github-repo-monitor",
3
+ "version": "1.0.0",
3
4
  "name": "GitHub repository monitor",
4
5
  "category": "Developer tools",
5
6
  "description": "Watch a repository for @OpenHands mentions in issues and PR comments, start a conversation, and post the agent's reply back to GitHub.",
@@ -0,0 +1,76 @@
1
+ {
2
+ "id": "news-digest",
3
+ "name": "Daily news digest",
4
+ "category": "Research",
5
+ "icon": "activity",
6
+ "description": "Read a list of public RSS and Atom feeds on a schedule, hand an agent everything new, and have it pick out what matters for your topics and write a short digest. Connects to nothing and needs no credentials.",
7
+ "requires": {
8
+ "integrations": {},
9
+ "features": [
10
+ "customTarball"
11
+ ]
12
+ },
13
+ "popularityRank": 78,
14
+ "estimatedSetupMinutes": 2,
15
+ "exampleImplementation": "Trigger: cron, daily by default (0 8 * * *)\nRequired secret: none. The feeds are public URLs and the conversation is started with an empty secret allow-list and no MCP servers.\n\n1. Read the feed list, the topics, and the schedule from setup.\n2. Key one unit of work to the UTC date, so a cron that fires more often, a retried run, or a restarted service cannot write the same digest twice.\n3. Fetch every feed over plain HTTPS and parse RSS 2.0, RSS 1.0/RDF and Atom by local element name. A feed that is down, moved, or no longer a feed is reported and skipped; the run fails only when every feed fails.\n4. Drop stories already covered by an earlier digest and stories older than the lookback window. Do not judge what a story is about: that has no right answer and is the agent's call.\n5. Start no conversation at all when nothing new was published, and leave the day open for a later run. A quiet day costs no tokens.\n6. Otherwise start an OpenHands conversation with the newest stories and the topics in the prompt, and let it decide which are relevant, group them, merge duplicate coverage, and write the digest.\n7. Deliver it three ways that need no credentials: it stays in the conversation, it is printed into the run log, and its opening is kept in state.\n8. Remember the reported stories only once a digest exists, so a failed run is recovered by the next one rather than lost.",
16
+ "setup": {
17
+ "version": "1.0",
18
+ "mode": "direct",
19
+ "form": {
20
+ "triggers": {
21
+ "cron": {
22
+ "schedule": {
23
+ "type": "cron",
24
+ "label": "Digest time",
25
+ "help": "When the digest is written. Work is keyed by UTC date, so a schedule more frequent than daily only polls until there is something new.",
26
+ "default": "0 8 * * *",
27
+ "required": true
28
+ },
29
+ "timezone": {
30
+ "type": "timezone",
31
+ "label": "Timezone",
32
+ "help": "Timezone the schedule is interpreted in.",
33
+ "default": "UTC",
34
+ "required": true
35
+ }
36
+ }
37
+ },
38
+ "args": {
39
+ "feeds": {
40
+ "type": "textarea",
41
+ "label": "Feeds",
42
+ "help": "One RSS or Atom feed URL per line. They must be public: this automation signs in to nothing, so a feed behind a login will simply fail and be skipped.",
43
+ "default": "https://news.ycombinator.com/rss\nhttps://feeds.arstechnica.com/arstechnica/index\nhttps://www.theverge.com/rss/index.xml",
44
+ "required": true,
45
+ "constraints": {
46
+ "minLength": 8,
47
+ "maxLength": 4000
48
+ }
49
+ },
50
+ "topics": {
51
+ "type": "textarea",
52
+ "label": "Topics of interest",
53
+ "help": "One topic per line, or separated by commas. The agent reads every new story and decides which ones are about these, so write them the way you would explain your interests to a colleague rather than as search terms. Leave this empty to cover whatever is most significant.",
54
+ "default": "artificial intelligence, open source, developer tools",
55
+ "required": false,
56
+ "constraints": {
57
+ "maxLength": 2000
58
+ }
59
+ }
60
+ }
61
+ },
62
+ "bundle": {
63
+ "version": "1.0.0",
64
+ "entrypoint": "python3 main.py",
65
+ "timeout": 900,
66
+ "files": {
67
+ "main.py": "skills/news-digest/scripts/main.py"
68
+ },
69
+ "config": {
70
+ "feeds": "{{form.feeds}}",
71
+ "topics": "{{form.topics}}"
72
+ }
73
+ },
74
+ "message": "This deployment cannot run the scheduled news digest directly. Set it up in this conversation instead: confirm the feeds to read, the topics to watch for, and the schedule, then create the automation."
75
+ }
76
+ }
@@ -4,13 +4,16 @@
4
4
 
5
5
  import entry0 from "./catalog/github-pr-reviewer/manifest.json" with { type: "json" };
6
6
  import entry1 from "./catalog/github-repo-monitor/manifest.json" with { type: "json" };
7
- import entry2 from "./catalog/slack-standup-digest/manifest.json" with { type: "json" };
8
- import entry3 from "./catalog/slack-channel-monitor/manifest.json" with { type: "json" };
9
- import entry4 from "./catalog/linear-triage-assistant/manifest.json" with { type: "json" };
10
- import entry5 from "./catalog/jira-issue-to-pr/manifest.json" with { type: "json" };
11
- import entry6 from "./catalog/research-brief-writer/manifest.json" with { type: "json" };
12
- import entry7 from "./catalog/upstream-fork-sync/manifest.json" with { type: "json" };
13
- import entry8 from "./catalog/incident-retrospective-drafter/manifest.json" with { type: "json" };
7
+ import entry2 from "./catalog/github-issue-to-pr/manifest.json" with { type: "json" };
8
+ import entry3 from "./catalog/slack-standup-digest/manifest.json" with { type: "json" };
9
+ import entry4 from "./catalog/slack-channel-monitor/manifest.json" with { type: "json" };
10
+ import entry5 from "./catalog/linear-triage-assistant/manifest.json" with { type: "json" };
11
+ import entry6 from "./catalog/jira-issue-to-pr/manifest.json" with { type: "json" };
12
+ import entry7 from "./catalog/research-brief-writer/manifest.json" with { type: "json" };
13
+ import entry8 from "./catalog/github-agents-md-maintainer/manifest.json" with { type: "json" };
14
+ import entry9 from "./catalog/upstream-fork-sync/manifest.json" with { type: "json" };
15
+ import entry10 from "./catalog/incident-retrospective-drafter/manifest.json" with { type: "json" };
16
+ import entry11 from "./catalog/news-digest/manifest.json" with { type: "json" };
14
17
 
15
18
  export const AUTOMATION_CATALOG_ENTRIES = [
16
19
  entry0,
@@ -22,4 +25,7 @@ export const AUTOMATION_CATALOG_ENTRIES = [
22
25
  entry6,
23
26
  entry7,
24
27
  entry8,
28
+ entry9,
29
+ entry10,
30
+ entry11,
25
31
  ];
@@ -21,8 +21,17 @@
21
21
  "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$",
22
22
  "description": "Stable identifier. Must equal the name of the directory holding this manifest."
23
23
  },
24
+ "version": {
25
+ "type": "string",
26
+ "pattern": "^\\d+\\.\\d+\\.\\d+$",
27
+ "description": "Semantic version of this template. Present only on entries whose direct setup sends provenance to the automation service; bump it when the prompt, form, or filter changes meaningfully."
28
+ },
24
29
  "name": { "type": "string", "minLength": 1 },
25
30
  "category": { "type": "string", "minLength": 1 },
31
+ "icon": {
32
+ "description": "The glyph the card shows, named from the same closed set the interface manifest's navigation uses. Absent means the host derives one from requires.integrations, which is right for an automation whose identity is the service it talks to and wrong for one whose identity is the work itself.",
33
+ "enum": ["layout-dashboard", "sparkles", "bot", "circle-alert", "activity", "timer"]
34
+ },
26
35
  "description": { "type": "string", "minLength": 1 },
27
36
  "requires": { "$ref": "#/$defs/requires" },
28
37
  "popularityRank": { "type": "integer", "minimum": 0 },
@@ -233,9 +242,8 @@
233
242
  "required": ["integrations"],
234
243
  "properties": {
235
244
  "integrations": {
236
- "description": "Keyed by integration id, each of which must resolve to an integrations/catalog entry.",
245
+ "description": "Keyed by integration id, each of which must resolve to an integrations/catalog entry. Empty when the automation connects to nothing and needs no credential - a requirement worth stating, and the reason the key stays required rather than becoming optional.",
237
246
  "type": "object",
238
- "minProperties": 1,
239
247
  "propertyNames": { "type": "string", "minLength": 1 },
240
248
  "additionalProperties": {
241
249
  "type": "object",
@@ -1,7 +1,24 @@
1
1
  export interface RecommendedAutomation {
2
2
  id: string;
3
+ /**
4
+ * Semantic version of this template. Present only on entries whose direct
5
+ * setup sends provenance to the automation service; bumped when the prompt,
6
+ * form, or filter changes meaningfully.
7
+ */
8
+ version?: string;
3
9
  name: string;
4
10
  category: string;
11
+ /**
12
+ * The glyph the card shows, from the closed set the interface manifest's
13
+ * navigation uses. Absent means the host derives one from the integrations.
14
+ */
15
+ icon?:
16
+ | "layout-dashboard"
17
+ | "sparkles"
18
+ | "bot"
19
+ | "circle-alert"
20
+ | "activity"
21
+ | "timer";
5
22
  description: string;
6
23
  requires: AutomationPrerequisites;
7
24
  popularityRank: number;
@@ -83,7 +100,7 @@ export interface AutomationIntegrationRequirement {
83
100
  }
84
101
 
85
102
  export interface AutomationPrerequisites {
86
- /** Keyed by integration catalog id. */
103
+ /** Keyed by integration catalog id. Empty when the automation needs nothing connected. */
87
104
  integrations: Record<string, AutomationIntegrationRequirement>;
88
105
  /** Deployment capabilities this automation cannot run without. */
89
106
  features?: string[];
@@ -150,7 +150,9 @@
150
150
  },
151
151
  "featuredAutomationIds": [
152
152
  "github-pr-reviewer",
153
- "github-repo-monitor",
153
+ "github-agents-md-maintainer",
154
+ "news-digest",
155
+ "github-issue-to-pr",
154
156
  "slack-channel-monitor"
155
157
  ],
156
158
  "responderIntegrationIds": ["github", "slack"]
@@ -681,6 +681,32 @@
681
681
  "official"
682
682
  ]
683
683
  },
684
+ {
685
+ "name": "github-agents-md-maintainer",
686
+ "source": "./skills/github-agents-md-maintainer",
687
+ "description": "Create an automation that keeps AGENTS.md current in one or more GitHub repositories. On a schedule an agent reads the repository, creates or updates AGENTS.md, and opens a pull request - staying quiet while one of its own pull requests is still open.",
688
+ "category": "automations",
689
+ "keywords": [
690
+ "github",
691
+ "agents-md",
692
+ "documentation",
693
+ "maintenance",
694
+ "automation"
695
+ ]
696
+ },
697
+ {
698
+ "name": "github-issue-to-pr",
699
+ "source": "./skills/github-issue-to-pr",
700
+ "description": "Create an automation that implements GitHub issues when a configurable trigger label is applied. Clones the default branch for the agent, then commits, pushes, and opens the pull request itself - the agent is handed no GitHub credential.",
701
+ "category": "automations",
702
+ "keywords": [
703
+ "github",
704
+ "issue",
705
+ "pull-request",
706
+ "automation",
707
+ "integration"
708
+ ]
709
+ },
684
710
  {
685
711
  "name": "github-pr-reviewer",
686
712
  "source": "./skills/github-pr-reviewer",
@@ -781,6 +807,18 @@
781
807
  "jira",
782
808
  "atlassian"
783
809
  ]
810
+ },
811
+ {
812
+ "name": "news-digest",
813
+ "source": "./skills/news-digest",
814
+ "description": "Create an automation that reads public RSS and Atom feeds on a schedule, keeps what is new and matches the configured topics, and has an agent write a short digest of it. Needs no credentials.",
815
+ "category": "automations",
816
+ "keywords": [
817
+ "news",
818
+ "rss",
819
+ "atom",
820
+ "digest"
821
+ ]
784
822
  }
785
823
  ]
786
824
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openhands/extensions",
3
- "version": "0.17.0",
3
+ "version": "0.18.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.17.0"
3
+ version = "0.18.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.17.0" # x-release-please-version
21
+ _FALLBACK_VERSION = "0.18.0" # x-release-please-version
22
22
 
23
23
  try:
24
24
  __version__: str = version("openhands-extensions")
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "github-agents-md-maintainer",
3
+ "version": "1.0.0",
4
+ "description": "Create an automation that keeps AGENTS.md current in one or more GitHub repositories. On a schedule it clones the default branch, has an agent read the repository and create or update AGENTS.md, and opens a pull request - staying quiet while one of its own pull requests is still open.",
5
+ "author": {
6
+ "name": "OpenHands",
7
+ "email": "contact@all-hands.dev"
8
+ },
9
+ "homepage": "https://github.com/OpenHands/extensions",
10
+ "repository": "https://github.com/OpenHands/extensions",
11
+ "license": "MIT",
12
+ "keywords": [
13
+ "github",
14
+ "agents-md",
15
+ "documentation",
16
+ "maintenance",
17
+ "automation"
18
+ ]
19
+ }
@@ -0,0 +1,59 @@
1
+ # AGENTS.md Maintainer
2
+
3
+ Create an automation that keeps `AGENTS.md` current in one or more GitHub
4
+ repositories, on a schedule.
5
+
6
+ ## Trigger
7
+
8
+ This skill is activated by:
9
+
10
+ - `/agents-md:setup`
11
+
12
+ ## Features
13
+
14
+ - Creates `AGENTS.md` when it is missing, updates it when the repository has
15
+ moved on, and leaves it alone when it is accurate
16
+ - Runs weekly by default, keyed by ISO week, so extra runs inside a week are
17
+ harmless
18
+ - Stays quiet while one of its own pull requests is still open, instead of
19
+ stacking a pull request per week over the same file
20
+ - Maintains several repositories from one automation, each with its own state
21
+ - Clones the default branch for the agent and removes the clone when the run ends
22
+ - Lets the agent open the pull request, and opens it in Python when the agent
23
+ did not - a failed push or a dead conversation never loses the work
24
+ - Opens draft pull requests by default, titled `docs: update AGENTS.md` or
25
+ `docs: add AGENTS.md`
26
+
27
+ ## What the agent is asked to do
28
+
29
+ Read the repository - layout, the build, test, lint and format commands as they
30
+ are actually defined, language and framework versions, contributing docs - and
31
+ edit `AGENTS.md` to match. It is told to treat an existing file as someone
32
+ else's writing: correct what is wrong, add what is missing, remove what no
33
+ longer exists, and leave the rest alone. Only knowledge that helps in most
34
+ future tasks belongs there, which is the rule the `agent-memory` skill sets out;
35
+ task-specific notes and unverified commands do not.
36
+
37
+ ## Prerequisites
38
+
39
+ Set `GITHUB_PERSONAL_ACCESS_TOKEN` in OpenHands Settings -> Secrets, able to
40
+ read the repositories, **write contents** (to push the branch) and **write pull
41
+ requests**. No issue permission is needed - this automation never comments on an
42
+ issue.
43
+
44
+ The automation runtime must have `git` available.
45
+
46
+ ## Quick Start
47
+
48
+ Ask OpenHands:
49
+
50
+ > "Set up an AGENTS.md maintenance automation for `myorg/backend` and
51
+ > `myorg/frontend`, weekly."
52
+
53
+ ## See Also
54
+
55
+ - [SKILL.md](SKILL.md) - Full setup workflow reference
56
+ - [references/state-schema.md](references/state-schema.md) - State document and
57
+ task lifecycle
58
+ - [../agent-memory/SKILL.md](../agent-memory/SKILL.md) - What belongs in an
59
+ AGENTS.md, and what does not