@jini-ai/agent-plugins 0.6.17 → 0.6.19
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/CHANGELOG.md +29 -1
- package/NOTICE +14 -0
- package/README.md +35 -14
- package/charts-echarts/plugin.json +39 -0
- package/charts-echarts/skills/charts-echarts/SKILL.md +110 -0
- package/charts-recharts/plugin.json +32 -0
- package/charts-recharts/skills/charts-recharts/SKILL.md +108 -0
- package/cloudflare/NOTES.md +16 -0
- package/cloudflare/form-destinations/cloudflare-d1.mjs +9 -0
- package/cloudflare/lib/api.mjs +96 -0
- package/cloudflare/lib/assets.mjs +65 -0
- package/cloudflare/lib/dns.mjs +32 -0
- package/cloudflare/lib/domain-inventory.mjs +61 -0
- package/cloudflare/lib/domain-status.mjs +48 -0
- package/cloudflare/lib/domains.mjs +95 -0
- package/cloudflare/lib/forms.mjs +254 -0
- package/cloudflare/lib/pages-upload.mjs +51 -0
- package/cloudflare/lib/target.mjs +165 -0
- package/cloudflare/lib/workers-upload.mjs +48 -0
- package/cloudflare/lib/zones.mjs +25 -0
- package/cloudflare/mcp.json +4 -0
- package/cloudflare/plugin.json +96 -0
- package/cloudflare/skills/cloudflare/SKILL.md +57 -0
- package/cloudflare/skills/cloudflare/references/domains.md +31 -0
- package/cloudflare/skills/cloudflare/references/pages.md +18 -0
- package/cloudflare/skills/cloudflare/references/permissions.md +29 -0
- package/cloudflare/skills/cloudflare/references/troubleshooting.md +20 -0
- package/cloudflare/skills/cloudflare/references/workers.md +42 -0
- package/cloudflare/targets/cloudflare-pages.mjs +12 -0
- package/cloudflare/targets/cloudflare-workers.mjs +17 -0
- package/cloudflare/tovu-consent.json +6 -0
- package/cloudflare/tovu-deploy-targets.json +630 -0
- package/cloudflare/tovu-form-destinations.json +12 -0
- package/cloudflare/worker/forms-receiver.mjs +249 -0
- package/composio/mcp.json +10 -0
- package/composio/plugin.json +68 -0
- package/composio/skills/composio/SKILL.md +85 -0
- package/dist/core/identity-namespace.d.ts +12 -0
- package/dist/core/identity-namespace.js +20 -0
- package/dist/folder-zip-node.js +29 -7
- package/dist/lifecycle/bundled-digests.js +4 -3
- package/dist/lifecycle/install.d.ts +7 -0
- package/dist/lifecycle/install.js +45 -3
- package/dist/lifecycle/manifest.d.ts +2 -2
- package/dist/lifecycle/manifest.js +5 -3
- package/dist/lifecycle/node.js +2 -0
- package/dist/lifecycle/persistent-state.js +1 -1
- package/dist/lifecycle/ports.d.ts +8 -0
- package/dist/lifecycle/seed-bundled.js +4 -1
- package/dist/manifest.d.ts +1 -1
- package/dist/manifest.js +3 -2
- package/fly/deploy-configs/fly.mjs +115 -0
- package/fly/deploy-ops/fly.mjs +102 -0
- package/fly/mcp.json +4 -0
- package/fly/plugin.json +81 -0
- package/fly/scripts/render-deploy-workflow.mjs +150 -0
- package/fly/skills/fly/SKILL.md +43 -0
- package/fly/skills/fly/references/fly-deploy.template.yml +117 -0
- package/fly/skills/fly/references/fly.template.toml +81 -0
- package/fly/tovu-credential-schemes.json +11 -0
- package/fly/tovu-deploy-configs.json +21 -0
- package/fly/tovu-deploy-ops.json +14 -0
- package/github/deploy-ops/github-actions.mjs +164 -0
- package/github/deployments/github.mjs +415 -0
- package/github/mcp.json +4 -0
- package/github/plugin.json +105 -0
- package/github/skills/github/SKILL.md +249 -0
- package/github/skills/github/references/actions.md +224 -0
- package/github/skills/github/references/auth-and-tokens.md +140 -0
- package/github/skills/github/references/repo-files.md +135 -0
- package/github/skills/github/references/site-backup.md +159 -0
- package/github/skills/github/references/source-control.md +123 -0
- package/github/source-control/backup-push.mjs +242 -0
- package/github/source-control/commit-site.mjs +459 -0
- package/github/source-control/github.mjs +93 -0
- package/github/source-control/write-files.mjs +468 -0
- package/github/tovu-deploy-ops.json +13 -0
- package/github/tovu-source-control.json +117 -0
- package/github-pages/NOTES.md +19 -0
- package/github-pages/mcp.json +4 -0
- package/github-pages/plugin.json +48 -0
- package/github-pages/skills/github-pages/SKILL.md +44 -0
- package/github-pages/targets/github-pages.mjs +543 -0
- package/github-pages/tovu-deploy-targets.json +327 -0
- package/google-login/exports/google-g.svg +1 -0
- package/google-login/exports/sign-in-button.css +68 -0
- package/google-login/exports/sign-in-button.html +4 -0
- package/google-login/mcp.json +4 -0
- package/google-login/plugin.json +59 -0
- package/google-login/skills/google-login/SKILL.md +96 -0
- package/google-login/tovu-login-providers.json +21 -0
- package/google-workspace/README.md +132 -0
- package/google-workspace/form-destinations/README.md +87 -0
- package/google-workspace/form-destinations/dedupe.mjs +43 -0
- package/google-workspace/form-destinations/delivery-result.mjs +69 -0
- package/google-workspace/form-destinations/mapping.mjs +152 -0
- package/google-workspace/form-destinations/sheets.mjs +202 -0
- package/google-workspace/lib/auth.mjs +81 -0
- package/google-workspace/lib/drive-files.mjs +54 -0
- package/google-workspace/lib/form-destination-settings.mjs +72 -0
- package/google-workspace/lib/http.mjs +168 -0
- package/google-workspace/lib/picker-flow.mjs +171 -0
- package/google-workspace/lib/picker-selection.mjs +107 -0
- package/google-workspace/lib/product-state.mjs +93 -0
- package/google-workspace/lib/request-policy.mjs +163 -0
- package/google-workspace/lib/sheets-a1.mjs +79 -0
- package/google-workspace/lib/sheets-admin-csv.mjs +82 -0
- package/google-workspace/lib/sheets-admin-request-kinds.mjs +183 -0
- package/google-workspace/lib/sheets-client.mjs +286 -0
- package/google-workspace/lib/surface-actions.mjs +107 -0
- package/google-workspace/mcp.json +4 -0
- package/google-workspace/plugin.json +77 -0
- package/google-workspace/products.json +12 -0
- package/google-workspace/skills/google-workspace/SKILL.md +82 -0
- package/google-workspace/skills/google-workspace/references/connection.md +102 -0
- package/google-workspace/skills/google-workspace/references/form-delivery.md +50 -0
- package/google-workspace/skills/google-workspace/references/sheets.md +149 -0
- package/google-workspace/skills/google-workspace/references/troubleshooting.md +31 -0
- package/google-workspace/tools/account-info.mjs +18 -0
- package/google-workspace/tools/sheets/README.md +54 -0
- package/google-workspace/tools/sheets/copy-tab.mjs +23 -0
- package/google-workspace/tools/sheets/copy.mjs +23 -0
- package/google-workspace/tools/sheets/create.mjs +35 -0
- package/google-workspace/tools/sheets/find-replace.mjs +38 -0
- package/google-workspace/tools/sheets/find.mjs +52 -0
- package/google-workspace/tools/sheets/get-by-data-filter.mjs +23 -0
- package/google-workspace/tools/sheets/get.mjs +22 -0
- package/google-workspace/tools/sheets/values-append.mjs +27 -0
- package/google-workspace/tools/sheets/values-batch-clear.mjs +20 -0
- package/google-workspace/tools/sheets/values-batch-get.mjs +20 -0
- package/google-workspace/tools/sheets/values-batch-update.mjs +29 -0
- package/google-workspace/tools/sheets/values-by-data-filter.mjs +62 -0
- package/google-workspace/tools/sheets/values-clear.mjs +20 -0
- package/google-workspace/tools/sheets/values-get.mjs +21 -0
- package/google-workspace/tools/sheets/values-update.mjs +26 -0
- package/google-workspace/tools/sheets-admin/README.md +45 -0
- package/google-workspace/tools/sheets-admin/basic-filter.mjs +32 -0
- package/google-workspace/tools/sheets-admin/batch-update.mjs +25 -0
- package/google-workspace/tools/sheets-admin/developer-metadata.mjs +28 -0
- package/google-workspace/tools/sheets-admin/export-csv.mjs +67 -0
- package/google-workspace/tools/sheets-admin/filter-views.mjs +38 -0
- package/google-workspace/tools/sheets-admin/format.mjs +70 -0
- package/google-workspace/tools/sheets-admin/named-ranges.mjs +42 -0
- package/google-workspace/tools/sheets-admin/open-existing.mjs +34 -0
- package/google-workspace/tools/sheets-admin/protected-ranges-get.mjs +18 -0
- package/google-workspace/tools/sheets-admin/sort.mjs +18 -0
- package/google-workspace/tools/sheets-admin/tab-modify.mjs +36 -0
- package/google-workspace/tovu-admin-surfaces.json +63 -0
- package/google-workspace/tovu-agent-tools.json +1178 -0
- package/google-workspace/tovu-connections.json +35 -0
- package/google-workspace/tovu-form-destinations.json +10 -0
- package/google-workspace/ui/README.md +73 -0
- package/google-workspace/ui/connection-panel.handler.mjs +167 -0
- package/google-workspace/ui/connection-panel.html +17 -0
- package/google-workspace/ui/connection-panel.mjs +189 -0
- package/google-workspace/ui/connection-view.mjs +120 -0
- package/google-workspace/ui/destination-panel.handler.mjs +106 -0
- package/google-workspace/ui/destination-panel.html +17 -0
- package/google-workspace/ui/destination-panel.mjs +150 -0
- package/google-workspace/ui/dom.mjs +140 -0
- package/google-workspace/ui/panel.css +170 -0
- package/google-workspace/ui/picker-flow.mjs +87 -0
- package/google-workspace/ui/picker-view.mjs +44 -0
- package/google-workspace/ui/picker.handler.mjs +56 -0
- package/google-workspace/ui/picker.html +17 -0
- package/google-workspace/ui/picker.mjs +88 -0
- package/google-workspace/ui/surface-client.mjs +227 -0
- package/higgsfield-media/mcp.json +9 -0
- package/higgsfield-media/plugin.json +109 -0
- package/higgsfield-media/skills/higgsfield-media/SKILL.md +325 -0
- package/higgsfield-media/skills/higgsfield-media/references/failure-modes.md +116 -0
- package/higgsfield-media/skills/higgsfield-media/references/models-and-plan-gates.md +142 -0
- package/jev/mcp.json +4 -0
- package/jev/plugin.json +44 -0
- package/jev/skills/jev/SKILL.md +308 -0
- package/jev/skills/jev/references/cookbooks.md +197 -0
- package/jev/skills/jev/references/jaggedness.md +135 -0
- package/jev/skills/jev/references/javascript-sdk.md +146 -0
- package/jev/skills/jev/references/patterns.md +123 -0
- package/jev/skills/jev/references/primitives-reference.md +187 -0
- package/langfuse/plugin.json +22 -0
- package/meilisearch/mcp.json +4 -0
- package/meilisearch/plugin.json +54 -0
- package/meilisearch/providers/meilisearch.mjs +651 -0
- package/meilisearch/skills/meilisearch/SKILL.md +43 -0
- package/meilisearch/tovu-search-providers.json +10 -0
- package/netlify/NOTES.md +13 -0
- package/netlify/mcp.json +4 -0
- package/netlify/plugin.json +47 -0
- package/netlify/skills/netlify/SKILL.md +39 -0
- package/netlify/targets/netlify.mjs +384 -0
- package/netlify/tovu-consent.json +6 -0
- package/netlify/tovu-deploy-targets.json +163 -0
- package/opentelemetry/mcp.json +4 -0
- package/opentelemetry/plugin.json +52 -0
- package/opentelemetry/skills/opentelemetry/SKILL.md +39 -0
- package/package.json +161 -6
- package/posthog/mcp.json +4 -0
- package/posthog/plugin.json +46 -0
- package/posthog/skills/posthog/SKILL.md +36 -0
- package/railway/deploy-configs/railway.mjs +135 -0
- package/railway/deploy-ops/railway.mjs +167 -0
- package/railway/mcp.json +4 -0
- package/railway/plugin.json +45 -0
- package/railway/skills/railway/SKILL.md +66 -0
- package/railway/tovu-deploy-configs.json +16 -0
- package/railway/tovu-deploy-ops.json +11 -0
- package/render/deploy-configs/render.mjs +141 -0
- package/render/deploy-ops/render.mjs +152 -0
- package/render/mcp.json +4 -0
- package/render/plugin.json +47 -0
- package/render/skills/render/SKILL.md +63 -0
- package/render/tovu-deploy-configs.json +16 -0
- package/render/tovu-deploy-ops.json +11 -0
- package/resend/NOTES.md +52 -0
- package/resend/adapters/resend.mjs +161 -0
- package/resend/lib/domains.mjs +137 -0
- package/resend/lib/errors.mjs +25 -0
- package/resend/lib/feedback.mjs +118 -0
- package/resend/mcp.json +13 -0
- package/resend/plugin.json +192 -0
- package/resend/skills/resend/SKILL.md +107 -0
- package/resend/tovu-mail-adapters.json +22 -0
- package/s3-compatible/NOTES.md +11 -0
- package/s3-compatible/mcp.json +4 -0
- package/s3-compatible/object-stores/s3-compatible.mjs +287 -0
- package/s3-compatible/plugin.json +56 -0
- package/s3-compatible/skills/s3-compatible/SKILL.md +39 -0
- package/s3-compatible/targets/s3-compatible.mjs +1054 -0
- package/s3-compatible/tovu-deploy-targets.json +432 -0
- package/s3-compatible/tovu-object-stores.json +29 -0
- package/sentry/mcp.json +4 -0
- package/sentry/plugin.json +49 -0
- package/sentry/skills/sentry/SKILL.md +34 -0
- package/shopify/mcp.json +4 -0
- package/shopify/plugin.json +22 -0
- package/shopify/skills/shopify/SKILL.md +103 -0
- package/shopify/skills/shopify/references/catalog-sync.md +74 -0
- package/shopify/skills/shopify/references/domains.md +26 -0
- package/shopify/skills/shopify/references/live-storefront.md +34 -0
- package/shopify/skills/shopify/references/storefront-snippets.md +21 -0
- package/site-compliance/mcp.json +4 -0
- package/site-compliance/plugin.json +34 -0
- package/site-compliance/skills/site-compliance/SKILL.md +220 -0
- package/site-compliance/skills/site-compliance/references/ccpa-cpra.md +115 -0
- package/site-compliance/skills/site-compliance/references/gdpr-eu-uk.md +143 -0
- package/site-compliance/skills/site-compliance/references/wcag-2-2.md +129 -0
- package/site-import/mcp.json +4 -0
- package/site-import/plugin.json +41 -0
- package/site-import/skills/site-import/SKILL.md +232 -0
- package/site-import/skills/site-import/references/content-mapping.md +166 -0
- package/site-import/skills/site-import/references/discovery-and-classification.md +117 -0
- package/site-import/skills/site-import/references/theme-extraction.md +34 -0
- package/slide-design/com.anthropic.claude-code/hooks/hooks.json +4 -0
- package/slide-design/mcp.json +4 -0
- package/slide-design/plugin.json +26 -0
- package/slide-design/skills/slide-design/SKILL.md +103 -0
- package/slide-design/skills/slide-design/references/charts-and-exhibits.md +100 -0
- package/slide-design/skills/slide-design/references/html-deck.md +175 -0
- package/slide-design/skills/slide-design/references/layout-and-style.md +131 -0
- package/slide-design/skills/slide-design/references/review.md +93 -0
- package/slide-design/skills/slide-design/references/storyline.md +118 -0
- package/stripe/plugin.json +22 -0
- package/supabase/mcp.json +26 -0
- package/supabase/plugin.json +78 -0
- package/supabase/skills/supabase/SKILL.md +169 -0
- package/supabase/skills/supabase/references/failure-modes.md +101 -0
- package/ui-ux-design/CHANGELOG.md +28 -0
- package/ui-ux-design/LICENSE +201 -0
- package/ui-ux-design/NOTICE +14 -0
- package/ui-ux-design/README.md +62 -0
- package/ui-ux-design/com.anthropic.claude-code/hooks/hooks.json +4 -0
- package/ui-ux-design/mcp.json +4 -0
- package/ui-ux-design/plugin.json +26 -0
- package/ui-ux-design/skills/frontend-accessibility/SKILL.md +60 -0
- package/ui-ux-design/skills/gstack-design/SKILL.md +53 -0
- package/ui-ux-design/skills/gstack-design/references/consultation.md +30 -0
- package/ui-ux-design/skills/gstack-design/references/html.md +29 -0
- package/ui-ux-design/skills/gstack-design/references/review.md +28 -0
- package/ui-ux-design/skills/gstack-design/references/shotgun.md +33 -0
- package/ui-ux-design/skills/gstack-design/references/upstream-notes.md +23 -0
- package/ui-ux-design/skills/interface-design/ORIGINAL.md +16 -0
- package/ui-ux-design/skills/interface-design/SKILL.md +41 -0
- package/ui-ux-design/skills/interface-design/references/commands/audit.md +40 -0
- package/ui-ux-design/skills/interface-design/references/commands/critique.md +21 -0
- package/ui-ux-design/skills/interface-design/references/commands/extract.md +34 -0
- package/ui-ux-design/skills/interface-design/references/commands/init.md +31 -0
- package/ui-ux-design/skills/interface-design/references/commands/status.md +22 -0
- package/ui-ux-design/skills/interface-design/references/examples/system-precision.md +29 -0
- package/ui-ux-design/skills/interface-design/references/examples/system-warmth.md +29 -0
- package/ui-ux-design/skills/interface-design/references/system-template.md +57 -0
- package/ui-ux-design/skills/shadcn-ui/README.md +244 -0
- package/ui-ux-design/skills/shadcn-ui/SKILL.md +333 -0
- package/ui-ux-design/skills/shadcn-ui/examples/auth-layout.tsx +177 -0
- package/ui-ux-design/skills/shadcn-ui/examples/data-table.tsx +313 -0
- package/ui-ux-design/skills/shadcn-ui/examples/form-pattern.tsx +177 -0
- package/ui-ux-design/skills/shadcn-ui/resources/component-catalog.md +481 -0
- package/ui-ux-design/skills/shadcn-ui/resources/customization-guide.md +516 -0
- package/ui-ux-design/skills/shadcn-ui/resources/migration-guide.md +463 -0
- package/ui-ux-design/skills/shadcn-ui/resources/setup-guide.md +412 -0
- package/ui-ux-design/skills/shadcn-ui/scripts/verify-setup.sh +134 -0
- package/ui-ux-design/skills/ui-ux-design/SKILL.md +171 -0
- package/ui-ux-design/skills/ui-ux-design/references/brand-and-voice.md +78 -0
- package/ui-ux-design/skills/ui-ux-design/references/chrome-mobile-test-matrix.md +137 -0
- package/ui-ux-design/skills/ui-ux-design/references/components-and-states.md +112 -0
- package/ui-ux-design/skills/ui-ux-design/references/delight-and-motion.md +54 -0
- package/ui-ux-design/skills/ui-ux-design/references/foundations.md +145 -0
- package/ui-ux-design/skills/ui-ux-design/references/inclusive-ai-imagery.md +57 -0
- package/ui-ux-design/skills/ui-ux-design/references/kole-jain-uiux-concepts.md +104 -0
- package/ui-ux-design/skills/ui-ux-design/references/kuinetic-reference.md +184 -0
- package/ui-ux-design/skills/ui-ux-design/references/openai-frontend-skill.md +139 -0
- package/ui-ux-design/skills/ui-ux-design/references/premium-ui.md +55 -0
- package/ui-ux-design/skills/ui-ux-design/references/research-and-validation.md +88 -0
- package/ui-ux-design/skills/ui-ux-design/references/sam-crawford-premium-websites.md +103 -0
- package/ui-ux-design/skills/ui-ux-design/references/self-made-web-designer-core-skills.md +119 -0
- package/ui-ux-design/skills/ui-ux-design/references/ui-animation.md +173 -0
- package/ui-ux-design/skills/ui-ux-design/references/ui-loop.md +234 -0
- package/ui-ux-design/skills/ui-ux-design/references/visual-storytelling.md +54 -0
- package/ui-ux-design/skills/vercel-web-design-guidelines/SKILL.md +39 -0
- package/ui-ux-design/skills/web-compliance/SKILL.md +134 -0
- package/ui-ux-design/skills/web-compliance/references/audit-evidence.md +59 -0
- package/vercel/NOTES.md +23 -0
- package/vercel/mcp.json +4 -0
- package/vercel/object-stores/vercel-blob.mjs +147 -0
- package/vercel/plugin.json +47 -0
- package/vercel/skills/vercel/SKILL.md +48 -0
- package/vercel/targets/vercel.mjs +586 -0
- package/vercel/tovu-consent.json +6 -0
- package/vercel/tovu-deploy-targets.json +219 -0
- package/vercel/tovu-object-stores.json +10 -0
- package/wordpress/NOTES.md +33 -0
- package/wordpress/plugin.json +30 -0
- package/wordpress/skills/wordpress/SKILL.md +43 -0
- package/wordpress/skills/wordpress/references/free-site-redirect.md +46 -0
- package/wordpress/skills/wordpress/references/subdomain.md +66 -0
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
import { createSign } from "node:crypto";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file The first-party `github` deployment provider — GitHub App installation auth over the
|
|
5
|
+
* guarded ADR-038 `HttpClientPort`.
|
|
6
|
+
*
|
|
7
|
+
* Why a GitHub App and not `gh` or a stored PAT (ADS deployments debate, all three rounds, 5/5):
|
|
8
|
+
* a PAT is a long-lived, human-scoped credential with no per-workspace or per-repository boundary
|
|
9
|
+
* in a multi-tenant process; `gh` inherits whatever credential is on the host's global config and
|
|
10
|
+
* bypasses the guarded HTTP client entirely. A GitHub App installation token is narrowable to one
|
|
11
|
+
* repository and one permission (`deployments: write`) at mint time, and expires in exactly one
|
|
12
|
+
* hour regardless of caller-supplied TTL — verified against
|
|
13
|
+
* docs.github.com/en/rest/apps/apps#create-an-installation-access-token-for-an-app. The App JWT
|
|
14
|
+
* used to mint it must be RS256 with `exp` no more than ten minutes past `iat` — verified against
|
|
15
|
+
* docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/generating-a-json-web-token-jwt-for-a-github-app.
|
|
16
|
+
*
|
|
17
|
+
* `EgressPolicy` cannot pin a host — see the host deployment port's file header. `sendPinned` below is this
|
|
18
|
+
* file's answer: the ONLY function allowed to call `http.send`, and it refuses anything whose
|
|
19
|
+
* resolved origin is not exactly `https://api.github.com`, so a malformed URL template (or a
|
|
20
|
+
* future workspace-supplied GitHub Enterprise base URL, if that is ever added) fails closed instead
|
|
21
|
+
* of silently reaching an arbitrary host.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
export const GITHUB_DEPLOYMENT_PROVIDER_ID = "github";
|
|
25
|
+
|
|
26
|
+
const GITHUB_API_ORIGIN = "https://api.github.com";
|
|
27
|
+
const API_VERSION = "2022-11-28";
|
|
28
|
+
const DEFAULT_TIMEOUT_MS = 10_000;
|
|
29
|
+
|
|
30
|
+
/** GitHub App JWTs: `exp` MUST be no more than 10 minutes past `iat` (verified — see file header).
|
|
31
|
+
* 9 minutes leaves margin against clock drift between signing and GitHub's verification. */
|
|
32
|
+
const APP_JWT_TTL_SECONDS = 9 * 60;
|
|
33
|
+
/** GitHub's own guidance is to back-date `iat` by up to 60s to tolerate clock skew between this
|
|
34
|
+
* process and GitHub's clock (verified — see file header). */
|
|
35
|
+
const APP_JWT_CLOCK_SKEW_SECONDS = 60;
|
|
36
|
+
|
|
37
|
+
function fail(
|
|
38
|
+
code,
|
|
39
|
+
message,
|
|
40
|
+
optional = {}
|
|
41
|
+
) {
|
|
42
|
+
return {
|
|
43
|
+
code,
|
|
44
|
+
message,
|
|
45
|
+
retryable: optional.retryable ?? false,
|
|
46
|
+
...(optional.providerStatus === undefined ? {} : { providerStatus: optional.providerStatus }),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Reads and validates `target.config`'s three required GitHub-specific fields.
|
|
52
|
+
*
|
|
53
|
+
* @complexity O(1).
|
|
54
|
+
*/
|
|
55
|
+
function readGitHubTargetConfig(target) {
|
|
56
|
+
const { owner, repo, environmentName } = target.config;
|
|
57
|
+
if (typeof owner !== "string" || owner.length === 0) return null;
|
|
58
|
+
if (typeof repo !== "string" || repo.length === 0) return null;
|
|
59
|
+
if (typeof environmentName !== "string" || environmentName.length === 0) return null;
|
|
60
|
+
return { owner, repo, environmentName };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* The origin pin. This is the ONLY call site for `http.send` in this file — every outbound request
|
|
65
|
+
* (minting a token, creating a deployment, polling statuses) is routed through it. See the file
|
|
66
|
+
* header for why this check cannot be delegated to `EgressPolicy`.
|
|
67
|
+
*
|
|
68
|
+
* Exported so this guard can be tested directly (see `../__tests__/deployments-provider.test.mjs`'s "sendPinned
|
|
69
|
+
* refuses..." case) — every current call site builds its URL through `githubApiUrl()`, which
|
|
70
|
+
* already can only resolve under `GITHUB_API_ORIGIN`, so an adapter-level test alone cannot prove
|
|
71
|
+
* this check is load-bearing (confirmed by a mutation check: disabling it did not fail any
|
|
72
|
+
* adapter-level test). This function is the actual safety boundary for a future call site that
|
|
73
|
+
* builds a URL a different way — e.g. a workspace-supplied GitHub Enterprise base URL, if that is
|
|
74
|
+
* ever added — so it must be proven correct on its own.
|
|
75
|
+
*
|
|
76
|
+
* @complexity O(1) beyond the underlying `http.send` call.
|
|
77
|
+
*/
|
|
78
|
+
export async function sendPinned(http, request) {
|
|
79
|
+
const url = new URL(request.url);
|
|
80
|
+
if (url.origin !== GITHUB_API_ORIGIN) {
|
|
81
|
+
throw new Error(
|
|
82
|
+
`github deployment adapter refused to send to '${url.origin}' — pinned to ${GITHUB_API_ORIGIN} only`
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
return http.send(request);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** Builds a same-origin URL from a path. Every caller-influenced path segment (owner, repo,
|
|
89
|
+
* installation id, provider run ref) MUST already be `encodeURIComponent`-encoded before reaching
|
|
90
|
+
* this function — encoding is what stops a value like `../../app/installations/1` from being
|
|
91
|
+
* interpreted as a literal dot-segment and resolving outside the intended endpoint: RFC 3986
|
|
92
|
+
* dot-segment removal only recognizes literal, unencoded `..` between `/` characters, never a
|
|
93
|
+
* percent-encoded `%2E%2E`. */
|
|
94
|
+
function githubApiUrl(path) {
|
|
95
|
+
return new URL(path, GITHUB_API_ORIGIN).toString();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function githubHeaders(token) {
|
|
99
|
+
return {
|
|
100
|
+
accept: "application/vnd.github+json",
|
|
101
|
+
authorization: `Bearer ${token}`,
|
|
102
|
+
"user-agent": "Tovu-CMS",
|
|
103
|
+
"x-github-api-version": API_VERSION,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function base64url(input) {
|
|
108
|
+
return Buffer.from(input).toString("base64url");
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Signs a GitHub App JWT locally. The private key never leaves this process.
|
|
113
|
+
*
|
|
114
|
+
* @complexity O(1) (one RSA signature over a short, fixed-shape payload).
|
|
115
|
+
*/
|
|
116
|
+
function signGitHubAppJwt(input) {
|
|
117
|
+
const header = base64url(JSON.stringify({ alg: "RS256", typ: "JWT" }));
|
|
118
|
+
const payload = base64url(JSON.stringify({ iat: input.issuedAt, exp: input.expiresAt, iss: input.appId }));
|
|
119
|
+
const signature = createSign("RSA-SHA256")
|
|
120
|
+
.update(`${header}.${payload}`)
|
|
121
|
+
.sign(input.privateKeyPem)
|
|
122
|
+
.toString("base64url");
|
|
123
|
+
return `${header}.${payload}.${signature}`;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function sanitizeMessage(value) {
|
|
127
|
+
if (typeof value !== "string") return null;
|
|
128
|
+
return value.replace(/[\r\n\0]/g, " ").slice(0, 500);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Mints a short-lived App JWT, exchanges it for an installation access token narrowed to exactly
|
|
133
|
+
* this installation's `deployments: write` permission. Minted fresh on every call rather than
|
|
134
|
+
* cached: simpler and correct, at the cost of one extra round trip per deploy action — acceptable
|
|
135
|
+
* given deploy actions are infrequent, not a hot path.
|
|
136
|
+
*
|
|
137
|
+
* @complexity One outbound HTTP request, hard-bounded by `DEFAULT_TIMEOUT_MS`.
|
|
138
|
+
*/
|
|
139
|
+
async function mintInstallationToken(
|
|
140
|
+
http,
|
|
141
|
+
credentials,
|
|
142
|
+
nowMs
|
|
143
|
+
) {
|
|
144
|
+
const now = Math.floor(nowMs() / 1000);
|
|
145
|
+
const jwt = signGitHubAppJwt({
|
|
146
|
+
appId: credentials.appId,
|
|
147
|
+
privateKeyPem: credentials.privateKeyPem,
|
|
148
|
+
issuedAt: now - APP_JWT_CLOCK_SKEW_SECONDS,
|
|
149
|
+
expiresAt: now + APP_JWT_TTL_SECONDS,
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
let response;
|
|
153
|
+
try {
|
|
154
|
+
response = await sendPinned(http, {
|
|
155
|
+
method: "POST",
|
|
156
|
+
url: githubApiUrl(`/app/installations/${encodeURIComponent(credentials.installationId)}/access_tokens`),
|
|
157
|
+
headers: { ...githubHeaders(jwt), "content-type": "application/json" },
|
|
158
|
+
body: JSON.stringify({ permissions: { deployments: "write" } }),
|
|
159
|
+
timeoutMs: DEFAULT_TIMEOUT_MS,
|
|
160
|
+
});
|
|
161
|
+
} catch (err) {
|
|
162
|
+
return { ok: false, error: fail("TRANSPORT_ERROR", err instanceof Error ? err.message : String(err), { retryable: true }) };
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (response.status >= 400) {
|
|
166
|
+
return {
|
|
167
|
+
ok: false,
|
|
168
|
+
error: fail("PROVIDER_ERROR", `GitHub installation token exchange failed: ${response.status}`, {
|
|
169
|
+
providerStatus: response.status,
|
|
170
|
+
retryable: response.status >= 500,
|
|
171
|
+
}),
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
let body;
|
|
176
|
+
try {
|
|
177
|
+
body = JSON.parse(response.bodyText);
|
|
178
|
+
} catch {
|
|
179
|
+
return { ok: false, error: fail("PROVIDER_RESPONSE_INVALID", "GitHub returned invalid JSON minting an installation token") };
|
|
180
|
+
}
|
|
181
|
+
// Token formats are opaque; do not assume a fixed prefix or length.
|
|
182
|
+
if (typeof body.token !== "string" || body.token.length === 0) {
|
|
183
|
+
return { ok: false, error: fail("PROVIDER_RESPONSE_INVALID", "GitHub returned an empty installation token") };
|
|
184
|
+
}
|
|
185
|
+
return { ok: true, token: body.token };
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function requireCredentials(
|
|
189
|
+
credentials
|
|
190
|
+
) {
|
|
191
|
+
const { appId, installationId, privateKeyPem } = credentials;
|
|
192
|
+
if (!appId || !installationId || !privateKeyPem) return null;
|
|
193
|
+
return { appId, installationId, privateKeyPem };
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Sends the `POST .../deployments` call and validates its response — split out of `startRun` so
|
|
198
|
+
* the pre-checks (target config, release shape, credentials) and the HTTP round-trip each carry
|
|
199
|
+
* only their own branches. `release` is the two fields already narrowed out of
|
|
200
|
+
* `input.release` by `startRun`'s own `kind !== "git-revision"` guard.
|
|
201
|
+
*/
|
|
202
|
+
async function createGitHubDeployment(
|
|
203
|
+
ctx,
|
|
204
|
+
token,
|
|
205
|
+
config,
|
|
206
|
+
release
|
|
207
|
+
) {
|
|
208
|
+
let response;
|
|
209
|
+
try {
|
|
210
|
+
response = await sendPinned(ctx.httpClient, {
|
|
211
|
+
method: "POST",
|
|
212
|
+
url: githubApiUrl(`/repos/${encodeURIComponent(config.owner)}/${encodeURIComponent(config.repo)}/deployments`),
|
|
213
|
+
headers: { ...githubHeaders(token), "content-type": "application/json" },
|
|
214
|
+
body: JSON.stringify({
|
|
215
|
+
ref: release.commitSha,
|
|
216
|
+
environment: config.environmentName,
|
|
217
|
+
description: `Tovu deployment of release ${release.releaseId}`,
|
|
218
|
+
auto_merge: false,
|
|
219
|
+
required_contexts: [],
|
|
220
|
+
transient_environment: false,
|
|
221
|
+
production_environment: config.environmentName === "production",
|
|
222
|
+
}),
|
|
223
|
+
timeoutMs: DEFAULT_TIMEOUT_MS,
|
|
224
|
+
});
|
|
225
|
+
} catch (err) {
|
|
226
|
+
return { ok: false, error: fail("TRANSPORT_ERROR", err instanceof Error ? err.message : String(err), { retryable: true }) };
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (response.status >= 400) {
|
|
230
|
+
return {
|
|
231
|
+
ok: false,
|
|
232
|
+
error: fail("PROVIDER_ERROR", `GitHub deployment create failed: ${response.status}`, {
|
|
233
|
+
providerStatus: response.status,
|
|
234
|
+
retryable: response.status >= 500,
|
|
235
|
+
}),
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
let body;
|
|
240
|
+
try {
|
|
241
|
+
body = JSON.parse(response.bodyText);
|
|
242
|
+
} catch {
|
|
243
|
+
return { ok: false, error: fail("PROVIDER_RESPONSE_INVALID", "GitHub returned invalid JSON creating a deployment") };
|
|
244
|
+
}
|
|
245
|
+
if (!Number.isSafeInteger(body.id) || (body.id) <= 0) {
|
|
246
|
+
return { ok: false, error: fail("PROVIDER_RESPONSE_INVALID", "GitHub returned an invalid deployment id") };
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return { ok: true, providerRunRef: String(body.id), reconciliation: "callback" };
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Creates a GitHub Deployment for an existing commit. Does NOT wait for (or fabricate) evidence
|
|
254
|
+
* that a build or deploy has started — GitHub's own docs state it does not access or deploy to the
|
|
255
|
+
* target servers itself; creating a deployment only dispatches a `deployment` event to whatever is
|
|
256
|
+
* listening.
|
|
257
|
+
*
|
|
258
|
+
* @complexity Two outbound HTTP requests (mint token, create deployment), each hard-bounded by
|
|
259
|
+
* `DEFAULT_TIMEOUT_MS`.
|
|
260
|
+
*/
|
|
261
|
+
async function startRun(input, ctx) {
|
|
262
|
+
const config = readGitHubTargetConfig(input.target);
|
|
263
|
+
if (!config) {
|
|
264
|
+
return { ok: false, error: fail("INVALID_TARGET_CONFIG", "github target is missing owner/repo/environmentName") };
|
|
265
|
+
}
|
|
266
|
+
if (input.release.source.kind !== "git-revision") {
|
|
267
|
+
// The honesty constraint, enforced at the one place it can be: this adapter promotes an
|
|
268
|
+
// EXISTING commit. It cannot manufacture one from an "external-artifact" release — the host's CLI
|
|
269
|
+
// has no build or export command.
|
|
270
|
+
return {
|
|
271
|
+
ok: false,
|
|
272
|
+
error: fail("INVALID_RELEASE", "github deployment target requires a git-revision release (commit sha), not an external artifact"),
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
const credentials = requireCredentials(ctx.credentials);
|
|
276
|
+
if (!credentials) {
|
|
277
|
+
return { ok: false, error: fail("NO_CREDENTIALS_CONFIGURED", "github deployment target is missing appId/installationId/privateKeyPem") };
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
const token = await mintInstallationToken(ctx.httpClient, credentials, ctx.now);
|
|
281
|
+
if (!token.ok) return { ok: false, error: token.error };
|
|
282
|
+
|
|
283
|
+
return createGitHubDeployment(ctx, token.token, config, {
|
|
284
|
+
commitSha: input.release.source.commitSha,
|
|
285
|
+
releaseId: input.release.id,
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* GitHub's real deployment-status `state` enum has SEVEN values — `error`, `failure`, `inactive`,
|
|
291
|
+
* `in_progress`, `queued`, `pending`, `success` — verified against
|
|
292
|
+
* docs.github.com/en/rest/deployments/statuses. Every value is handled explicitly here; an
|
|
293
|
+
* unrecognized future value falls to `"running"` (never a terminal state), so it can never be
|
|
294
|
+
* mistaken for success or a permanent failure.
|
|
295
|
+
*
|
|
296
|
+
* GitHub never fires a `deployment_status` WEBHOOK for `inactive` (verified against
|
|
297
|
+
* docs.github.com/en/webhooks/webhook-events-and-payloads#deployment_status) — so this mapping is
|
|
298
|
+
* the only place `inactive` is ever observed, and only via `pollRun`, never a callback.
|
|
299
|
+
*
|
|
300
|
+
* @complexity O(1).
|
|
301
|
+
*/
|
|
302
|
+
export function mapGitHubDeploymentStatus(status) {
|
|
303
|
+
const providerStatusId = String(status.id);
|
|
304
|
+
const message = sanitizeMessage(status.description);
|
|
305
|
+
switch (status.state) {
|
|
306
|
+
case "success":
|
|
307
|
+
return { status: "succeeded", providerStatusId, message };
|
|
308
|
+
case "failure":
|
|
309
|
+
case "error":
|
|
310
|
+
return { status: "failed", providerStatusId, message };
|
|
311
|
+
case "inactive":
|
|
312
|
+
return { status: "cancelled", providerStatusId, message };
|
|
313
|
+
case "in_progress":
|
|
314
|
+
return { status: "running", providerStatusId, message };
|
|
315
|
+
case "queued":
|
|
316
|
+
case "pending":
|
|
317
|
+
return { status: "queued", providerStatusId, message };
|
|
318
|
+
default:
|
|
319
|
+
return { status: "running", providerStatusId, message };
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Sends the `GET .../statuses` call and resolves the latest status from it — split out of
|
|
325
|
+
* `pollRun` for the same "pre-checks vs. HTTP round-trip" reason as `createGitHubDeployment`. Does
|
|
326
|
+
* NOT assume the response is newest-first — GitHub's docs describe pagination for this endpoint but
|
|
327
|
+
* state no response order (verified against docs.github.com/en/rest/deployments/statuses). Status
|
|
328
|
+
* ids are assigned monotonically, so the correct status is the one with the greatest `id`,
|
|
329
|
+
* independent of array position.
|
|
330
|
+
*/
|
|
331
|
+
async function pollGitHubDeploymentStatuses(
|
|
332
|
+
ctx,
|
|
333
|
+
token,
|
|
334
|
+
config,
|
|
335
|
+
providerRunRef
|
|
336
|
+
) {
|
|
337
|
+
let response;
|
|
338
|
+
try {
|
|
339
|
+
response = await sendPinned(ctx.httpClient, {
|
|
340
|
+
method: "GET",
|
|
341
|
+
url: githubApiUrl(
|
|
342
|
+
`/repos/${encodeURIComponent(config.owner)}/${encodeURIComponent(config.repo)}/deployments/` +
|
|
343
|
+
`${encodeURIComponent(providerRunRef)}/statuses?per_page=100`
|
|
344
|
+
),
|
|
345
|
+
headers: githubHeaders(token),
|
|
346
|
+
timeoutMs: DEFAULT_TIMEOUT_MS,
|
|
347
|
+
});
|
|
348
|
+
} catch (err) {
|
|
349
|
+
return { ok: false, error: fail("TRANSPORT_ERROR", err instanceof Error ? err.message : String(err), { retryable: true }) };
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
if (response.status >= 400) {
|
|
353
|
+
return {
|
|
354
|
+
ok: false,
|
|
355
|
+
error: fail("PROVIDER_ERROR", `GitHub deployment status poll failed: ${response.status}`, {
|
|
356
|
+
providerStatus: response.status,
|
|
357
|
+
retryable: response.status >= 500,
|
|
358
|
+
}),
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
let statuses;
|
|
363
|
+
try {
|
|
364
|
+
const parsed = JSON.parse(response.bodyText);
|
|
365
|
+
if (!Array.isArray(parsed)) throw new Error("not an array");
|
|
366
|
+
statuses = parsed;
|
|
367
|
+
} catch {
|
|
368
|
+
return { ok: false, error: fail("PROVIDER_RESPONSE_INVALID", "GitHub returned a malformed statuses response") };
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
if (statuses.length === 0) {
|
|
372
|
+
return { ok: true, update: { status: "queued", providerStatusId: null, message: null } };
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
const latest = statuses.reduce((best, candidate) => (candidate.id > best.id ? candidate : best));
|
|
376
|
+
return { ok: true, update: mapGitHubDeploymentStatus(latest) };
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Polls the latest deployment status.
|
|
381
|
+
*
|
|
382
|
+
* @complexity One outbound HTTP request (plus the token mint) and a single linear scan over the
|
|
383
|
+
* returned statuses (bounded by `per_page=100`), each hard-bounded by `DEFAULT_TIMEOUT_MS`.
|
|
384
|
+
*/
|
|
385
|
+
async function pollRun(input, ctx) {
|
|
386
|
+
const config = readGitHubTargetConfig(input.target);
|
|
387
|
+
if (!config) {
|
|
388
|
+
return { ok: false, error: fail("INVALID_TARGET_CONFIG", "github target is missing owner/repo/environmentName") };
|
|
389
|
+
}
|
|
390
|
+
if (!/^[1-9]\d*$/.test(input.providerRunRef)) {
|
|
391
|
+
return { ok: false, error: fail("INVALID_TARGET_CONFIG", "providerRunRef is not a github deployment id") };
|
|
392
|
+
}
|
|
393
|
+
const credentials = requireCredentials(ctx.credentials);
|
|
394
|
+
if (!credentials) {
|
|
395
|
+
return { ok: false, error: fail("NO_CREDENTIALS_CONFIGURED", "github deployment target is missing appId/installationId/privateKeyPem") };
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
const token = await mintInstallationToken(ctx.httpClient, credentials, ctx.now);
|
|
399
|
+
if (!token.ok) return { ok: false, error: token.error };
|
|
400
|
+
|
|
401
|
+
return pollGitHubDeploymentStatuses(ctx, token.token, config, input.providerRunRef);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Builds the `github` deployment provider adapter. Stateless — safe to construct once and reuse
|
|
406
|
+
* across requests; all per-call state lives in the `ctx` passed to each method.
|
|
407
|
+
*/
|
|
408
|
+
export function createGitHubDeploymentProvider() {
|
|
409
|
+
return {
|
|
410
|
+
id: GITHUB_DEPLOYMENT_PROVIDER_ID,
|
|
411
|
+
credentialKeys: ["appId", "installationId", "privateKeyPem"],
|
|
412
|
+
startRun,
|
|
413
|
+
pollRun,
|
|
414
|
+
};
|
|
415
|
+
}
|
package/github/mcp.json
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
|
|
3
|
+
"name": "github",
|
|
4
|
+
"version": "1.1.0",
|
|
5
|
+
"description": "Everything a host's assistant needs to work against a GitHub repository through the workspace's own saved credentials, with no git, no gh CLI, and no token ever passing through the assistant: writing and updating files in one atomic commit, dispatching and following a GitHub Actions run, reading a failed run's logs, committing the site's rendered static export, backing up the site itself (database, media, themes, plugins, settings) to a private repository, and deploying the host's server through its GitHub Actions deploy workflow (the `github-actions` deployment ops platform). Encodes the rules that generic GitHub knowledge gets wrong here — a 204 dispatch means queued and never deployed, a workflow only fires on the branch its own trigger names, a repository secret is the human's step and never the assistant's, a 403 on an org-wide listing is a normal app-scoped-token boundary rather than a broken credential, and editing an existing file means diffing the MODIFIED files and not only the added and deleted ones.",
|
|
6
|
+
"author": "Tovu",
|
|
7
|
+
"license": "Apache-2.0",
|
|
8
|
+
"extensions": {
|
|
9
|
+
"tovu": {
|
|
10
|
+
"vendorAliases": ["github_pat_"],
|
|
11
|
+
"displayName": "GitHub",
|
|
12
|
+
"summary": "Lets the assistant save your site's files to GitHub, run builds there, and back up your whole site.",
|
|
13
|
+
"id": "tovu/github",
|
|
14
|
+
"provides": [
|
|
15
|
+
"source-control",
|
|
16
|
+
"site-backup",
|
|
17
|
+
"deploy-ops:github-actions"
|
|
18
|
+
],
|
|
19
|
+
"credentialCards": [
|
|
20
|
+
{
|
|
21
|
+
"target": "github",
|
|
22
|
+
"title": "Connect GitHub",
|
|
23
|
+
"label": "github",
|
|
24
|
+
"category": "source-control",
|
|
25
|
+
"intro": "Connect GitHub for repository files, Actions and site backups.",
|
|
26
|
+
"usedFor": [
|
|
27
|
+
"Reads and updates repository files",
|
|
28
|
+
"Starts workflows and checks their results and logs",
|
|
29
|
+
"Backs up your site to a private repository"
|
|
30
|
+
],
|
|
31
|
+
"keyHint": "Select only the repositories you need. Contents → Read and write for commits; Workflows → Read and write for workflow files; Actions → Read for runs or Read and write for dispatch. Reading secret names needs Secrets → Read. Never grant secret-writing access for this flow.",
|
|
32
|
+
"saveKind": "api",
|
|
33
|
+
"helpUrl": "https://github.com/settings/personal-access-tokens/new",
|
|
34
|
+
"helpLabel": "Create a fine-grained token",
|
|
35
|
+
"baseUrl": "https://api.github.com",
|
|
36
|
+
"probeUrl": "https://api.github.com/user"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"target": "github-source-control",
|
|
40
|
+
"title": "Connect GitHub for source control",
|
|
41
|
+
"label": "default",
|
|
42
|
+
"category": "source-control",
|
|
43
|
+
"intro": "Connect GitHub to commit this site’s rendered static export to a repository.",
|
|
44
|
+
"usedFor": [
|
|
45
|
+
"Commits your site's exported website files to a repository"
|
|
46
|
+
],
|
|
47
|
+
"keyHint": "Select only the destination repository, with Contents → Read and write. A classic token with repo scope also works but has broader access.",
|
|
48
|
+
"saveKind": "source-control",
|
|
49
|
+
"saveTarget": "github",
|
|
50
|
+
"helpUrl": "https://github.com/settings/personal-access-tokens/new",
|
|
51
|
+
"helpLabel": "Create a fine-grained token",
|
|
52
|
+
"baseUrl": "https://api.github.com"
|
|
53
|
+
}
|
|
54
|
+
],
|
|
55
|
+
"toolKeywords": {
|
|
56
|
+
"credential_save": "github",
|
|
57
|
+
"deployment_ops_deploy": "github",
|
|
58
|
+
"deployment_ops_logs": "github",
|
|
59
|
+
"deployment_ops_status": "github",
|
|
60
|
+
"site_backup_plan": "github",
|
|
61
|
+
"site_backup_push": "github",
|
|
62
|
+
"skills_install": "github",
|
|
63
|
+
"source_control_execute_commit": "github",
|
|
64
|
+
"source_control_get_capabilities": "github"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
"keywords": [
|
|
69
|
+
"github",
|
|
70
|
+
"git",
|
|
71
|
+
"repo",
|
|
72
|
+
"repository",
|
|
73
|
+
"commit",
|
|
74
|
+
"push",
|
|
75
|
+
"branch",
|
|
76
|
+
"pull-request",
|
|
77
|
+
"source-control",
|
|
78
|
+
"version-control",
|
|
79
|
+
"github-actions",
|
|
80
|
+
"actions",
|
|
81
|
+
"workflow",
|
|
82
|
+
"workflow-dispatch",
|
|
83
|
+
"ci",
|
|
84
|
+
"cd",
|
|
85
|
+
"pipeline",
|
|
86
|
+
"run",
|
|
87
|
+
"job",
|
|
88
|
+
"logs",
|
|
89
|
+
"secrets",
|
|
90
|
+
"repository-secret",
|
|
91
|
+
"token",
|
|
92
|
+
"pat",
|
|
93
|
+
"scopes",
|
|
94
|
+
"permissions",
|
|
95
|
+
"api",
|
|
96
|
+
"rest",
|
|
97
|
+
"git-data-api",
|
|
98
|
+
"blob",
|
|
99
|
+
"tree",
|
|
100
|
+
"ref",
|
|
101
|
+
"backup",
|
|
102
|
+
"site-backup",
|
|
103
|
+
"deploy-ops:github-actions"
|
|
104
|
+
]
|
|
105
|
+
}
|