Repository navigation
feat: generate plugin skills from a registry of source repositories #53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
da7b738
feat: generate plugin skills from a registry of source repositories
brendanjryan f3d46bc
ci: pin create-pull-request to the merged release
brendanjryan c59991a
fix: stage the registry directory so plugins without an MCP record ca…
brendanjryan 2d7081a
ci: pin skill-sync to the merged release
brendanjryan 7ee48e2
Merge remote-tracking branch 'origin/main' into brendanjryan/skill-sy…
brendanjryan df6e2e3
ci: align sync workflow pins with main
brendanjryan df75b19
fix: read the docs skill from public/SKILL.md, which SKILL.md now lin…
brendanjryan File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| # Allow only the main-branch skill sync workflow to open its generated | ||
| # update pull requests in this repository. | ||
| subject: repo:tempoxyz@211589300/plugins@1356140289:ref:refs/heads/main | ||
| claim_pattern: | ||
| job_workflow_ref: tempoxyz/plugins/\.github/workflows/sync-skills\.yml@refs/heads/main | ||
| permissions: | ||
| contents: write | ||
| pull_requests: write |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| name: Sync skills | ||
|
|
||
| # Each plugin's skills are copied from the repositories listed in skills.json. | ||
| # One pull request per plugin keeps a failing source from blocking the rest; | ||
| # generated-only pull requests merge once validation passes. | ||
| on: | ||
| schedule: | ||
| - cron: "*/30 * * * *" | ||
| workflow_dispatch: | ||
| repository_dispatch: | ||
| types: [skill-source-updated] | ||
|
|
||
| concurrency: | ||
| group: sync-skills | ||
| cancel-in-progress: false | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| plugins: | ||
| name: List plugins | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 5 | ||
| permissions: | ||
| contents: read | ||
| id-token: write | ||
| outputs: | ||
| plugins: ${{ steps.list.outputs.plugins }} | ||
| steps: | ||
| - name: Secure runner | ||
| uses: tempoxyz/gh-actions/actions/secure-runner@947d9a3ccb2425a9c94d563fd721cc0e33c89e26 # 2026-10-15T00-15-06Z-947d9a3c | ||
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | ||
| with: | ||
| persist-credentials: false | ||
| - id: list | ||
| run: echo "plugins=$(jq -c '[.skills[] | .plugin // .name] | unique' skills.json)" >> "$GITHUB_OUTPUT" | ||
|
|
||
| sync: | ||
| name: Sync ${{ matrix.plugin }} | ||
| needs: plugins | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 10 | ||
| permissions: | ||
| contents: read | ||
| id-token: write | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| plugin: ${{ fromJSON(needs.plugins.outputs.plugins) }} | ||
| steps: | ||
| - name: Secure runner | ||
| uses: tempoxyz/gh-actions/actions/secure-runner@947d9a3ccb2425a9c94d563fd721cc0e33c89e26 # 2026-10-15T00-15-06Z-947d9a3c | ||
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | ||
| with: | ||
| persist-credentials: false | ||
| - name: Sync skills from their sources | ||
| id: sync | ||
| uses: tempoxyz/gh-actions/actions/skill-sync@caf7c59ea3a8359618ca5640d123a161a2a87721 # 2026-10-15T17-04-41Z-caf7c59e | ||
| with: | ||
| only: ${{ matrix.plugin }} | ||
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | ||
| if: steps.sync.outputs.changed == 'true' | ||
| with: | ||
| node-version: 24 | ||
| cache: npm | ||
| - name: Bump the plugin version and regenerate manifests | ||
| if: steps.sync.outputs.changed == 'true' | ||
| env: | ||
| PLUGIN: ${{ matrix.plugin }} | ||
| run: | | ||
| npm ci --ignore-scripts | ||
| npx tsx scripts/bump-plugin-version.ts "$PLUGIN" | ||
| npm run build | ||
| npm run update:goldens | ||
| - name: Fetch GitHub token via STS | ||
| if: steps.sync.outputs.changed == 'true' | ||
| id: sts | ||
| uses: tempoxyz/gh-actions/actions/github-sts@947d9a3ccb2425a9c94d563fd721cc0e33c89e26 # 2026-10-15T00-15-06Z-947d9a3c | ||
| with: | ||
| policy: skill-sync | ||
| ttl: 10m | ||
| - name: Open or update the sync pull request | ||
| if: steps.sync.outputs.changed == 'true' | ||
| uses: tempoxyz/gh-actions/actions/create-pull-request@a4fa1d51aa4014d86628f43b1dff8ba88219e04d # 2026-10-15T00-03-55Z-a4fa1d51 | ||
| with: | ||
| token: ${{ steps.sts.outputs.token }} | ||
| branch: automation/sync-skills/${{ matrix.plugin }} | ||
| commit-message: "chore(${{ matrix.plugin }}): sync skills" | ||
| title: "chore(${{ matrix.plugin }}): sync skills" | ||
| body: | | ||
| Generated from `skills.json` by `.github/workflows/sync-skills.yml`. Edit the source, not these copies. | ||
|
|
||
| ${{ steps.sync.outputs.summary }} | ||
| add-paths: | | ||
| plugins/${{ matrix.plugin }} | ||
| registry | ||
| skills.lock.json | ||
| manifest.config.ts | ||
| test/fixtures/golden | ||
| auto-merge: squash | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| import { readFileSync, writeFileSync } from 'node:fs' | ||
| import { resolve } from 'node:path' | ||
| import { fileURLToPath } from 'node:url' | ||
|
|
||
| const configPath = fileURLToPath(new URL('../manifest.config.ts', import.meta.url)) | ||
|
|
||
| /** Bump one plugin's patch version so installed clients pick up synced skill changes. */ | ||
| export const bumpPluginVersion = (config: string, name: string): string => { | ||
| const pattern = new RegExp(`(\\n name: '${name}',\\n version: ')(\\d+)\\.(\\d+)\\.(\\d+)(')`) | ||
| const match = pattern.exec(config) | ||
| if (!match) throw new Error(`manifest.config.ts has no version for plugin "${name}"`) | ||
| const [, prefix, major, minor, patch, suffix] = match | ||
| return config.replace(pattern, `${prefix}${major}.${minor}.${Number(patch) + 1}${suffix}`) | ||
| } | ||
|
|
||
| const isMain = process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url) | ||
| if (isMain) { | ||
| const name = process.argv[2] | ||
| if (!name) throw new Error('usage: bump-plugin-version.ts <plugin>') | ||
| writeFileSync(configPath, bumpPluginVersion(readFileSync(configPath, 'utf8'), name)) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| { | ||
| "skills": [ | ||
| { | ||
| "name": "docs", | ||
| "plugin": "docs", | ||
|
brendanjryan marked this conversation as resolved.
|
||
| "repo": "tempoxyz/docs", | ||
| "path": "public/SKILL.md", | ||
| "ref": "main" | ||
| }, | ||
| { | ||
| "name": "wallet", | ||
| "plugin": "wallet", | ||
| "repo": "tempoxyz/wallet-cli", | ||
| "path": "SKILL.md", | ||
| "ref": "release" | ||
| }, | ||
| { | ||
| "name": "mercator", | ||
| "plugin": "mercator", | ||
| "repo": "tempoxyz/mercator", | ||
| "path": "skills/mercator", | ||
| "ref": "main" | ||
| }, | ||
| { | ||
| "name": "mercator-setup", | ||
| "plugin": "mercator", | ||
| "repo": "tempoxyz/mercator", | ||
| "path": "skills/mercator-setup", | ||
| "ref": "main" | ||
| } | ||
| ] | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| { | ||
| "version": 1, | ||
| "skills": [ | ||
| { | ||
| "name": "mercator", | ||
|
brendanjryan marked this conversation as resolved.
|
||
| "plugin": "mercator", | ||
| "repo": "tempoxyz/mercator", | ||
| "path": "skills/mercator", | ||
| "ref": "main", | ||
| "commit": "598f247026fbe99d87e10ccf1cef914918eb5389", | ||
| "digest": "sha256:2832e9166e61033bc8c16d7ecedb807c14f5e9dc8d95eef6f44c11fd478bc22e", | ||
| "dest": "plugins/mercator/skills/mercator" | ||
| }, | ||
| { | ||
| "name": "mercator-setup", | ||
| "plugin": "mercator", | ||
| "repo": "tempoxyz/mercator", | ||
| "path": "skills/mercator-setup", | ||
| "ref": "main", | ||
| "commit": "598f247026fbe99d87e10ccf1cef914918eb5389", | ||
| "digest": "sha256:d7c7f672a8327800a09086604f508253b3a452689b338e7b337e5ec674a1d8d4", | ||
| "dest": "plugins/mercator/skills/mercator-setup" | ||
| } | ||
| ] | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| import { readFileSync } from 'node:fs' | ||
| import { describe, expect, it } from 'vitest' | ||
| import { bumpPluginVersion } from '../scripts/bump-plugin-version.ts' | ||
|
|
||
| const config = readFileSync(new URL('../manifest.config.ts', import.meta.url), 'utf8') | ||
| const version = (source: string, name: string): string | undefined => | ||
| new RegExp(`\\n name: '${name}',\\n version: '([^']+)'`).exec(source)?.[1] | ||
|
|
||
| describe('bumpPluginVersion', () => { | ||
| it.each(['docs', 'wallet', 'mercator'])('bumps only the %s patch version', (name) => { | ||
| const bumped = bumpPluginVersion(config, name) | ||
| const [major, minor, patch] = version(config, name)!.split('.') | ||
| expect(version(bumped, name)).toBe(`${major}.${minor}.${Number(patch) + 1}`) | ||
| for (const other of ['docs', 'wallet', 'mercator'].filter((plugin) => plugin !== name)) { | ||
| expect(version(bumped, other)).toBe(version(config, other)) | ||
| } | ||
| }) | ||
|
|
||
| it('rejects an unknown plugin', () => { | ||
| expect(() => bumpPluginVersion(config, 'missing')).toThrow(/no version for plugin "missing"/) | ||
| }) | ||
| }) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.