lastlight 0.1.15 → 0.2.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.
- package/README.md +265 -118
- package/agent-context/rules.md +62 -9
- package/agent-context/security.md +69 -0
- package/config/default.yaml +89 -0
- package/deploy/.env.production.example +20 -2
- package/deploy/entrypoint.sh +16 -17
- package/deploy/native/README.md +160 -0
- package/deploy/native/install.sh +110 -0
- package/deploy/native/lastlight.env.example +95 -0
- package/deploy/native/lastlight.service +50 -0
- package/deploy/sandbox-entrypoint.sh +59 -42
- package/dist/admin/auth.d.ts +1 -1
- package/dist/admin/auth.js +3 -1
- package/dist/admin/auth.js.map +1 -1
- package/dist/admin/chat-session-reader.d.ts +11 -14
- package/dist/admin/chat-session-reader.js +27 -51
- package/dist/admin/chat-session-reader.js.map +1 -1
- package/dist/admin/docker.d.ts +37 -0
- package/dist/admin/docker.js +86 -1
- package/dist/admin/docker.js.map +1 -1
- package/dist/admin/index.js +38 -3
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/log-search.test.d.ts +1 -0
- package/dist/admin/log-search.test.js +78 -0
- package/dist/admin/log-search.test.js.map +1 -0
- package/dist/admin/routes.d.ts +52 -3
- package/dist/admin/routes.js +780 -63
- package/dist/admin/routes.js.map +1 -1
- package/dist/admin/routes.test.js +680 -14
- package/dist/admin/routes.test.js.map +1 -1
- package/dist/admin/server-logs.test.d.ts +1 -0
- package/dist/admin/server-logs.test.js +58 -0
- package/dist/admin/server-logs.test.js.map +1 -0
- package/dist/admin/sessions.d.ts +26 -39
- package/dist/admin/sessions.js +86 -310
- package/dist/admin/sessions.js.map +1 -1
- package/dist/admin/sessions.test.d.ts +1 -0
- package/dist/admin/sessions.test.js +78 -0
- package/dist/admin/sessions.test.js.map +1 -0
- package/dist/admin/version.d.ts +15 -0
- package/dist/admin/version.js +73 -0
- package/dist/admin/version.js.map +1 -0
- package/dist/admin/version.test.d.ts +1 -0
- package/dist/admin/version.test.js +71 -0
- package/dist/admin/version.test.js.map +1 -0
- package/dist/cli-config.d.ts +55 -0
- package/dist/cli-config.js +119 -0
- package/dist/cli-config.js.map +1 -0
- package/dist/cli-config.test.d.ts +1 -0
- package/dist/cli-config.test.js +92 -0
- package/dist/cli-config.test.js.map +1 -0
- package/dist/cli-format.d.ts +19 -0
- package/dist/cli-format.js +107 -0
- package/dist/cli-format.js.map +1 -0
- package/dist/cli-server.d.ts +73 -0
- package/dist/cli-server.js +347 -0
- package/dist/cli-server.js.map +1 -0
- package/dist/cli-server.test.d.ts +1 -0
- package/dist/cli-server.test.js +38 -0
- package/dist/cli-server.test.js.map +1 -0
- package/dist/cli-timeline.d.ts +35 -0
- package/dist/cli-timeline.js +373 -0
- package/dist/cli-timeline.js.map +1 -0
- package/dist/cli-timeline.test.d.ts +1 -0
- package/dist/cli-timeline.test.js +104 -0
- package/dist/cli-timeline.test.js.map +1 -0
- package/dist/cli.d.ts +0 -19
- package/dist/cli.js +910 -194
- package/dist/cli.js.map +1 -1
- package/dist/config-overlay.test.d.ts +1 -0
- package/dist/config-overlay.test.js +112 -0
- package/dist/config-overlay.test.js.map +1 -0
- package/dist/config-resolve.d.ts +28 -0
- package/dist/config-resolve.js +47 -0
- package/dist/config-resolve.js.map +1 -0
- package/dist/config-resolve.test.d.ts +1 -0
- package/dist/config-resolve.test.js +68 -0
- package/dist/config-resolve.test.js.map +1 -0
- package/dist/config.d.ts +62 -49
- package/dist/config.js +452 -76
- package/dist/config.js.map +1 -1
- package/dist/config.test.js +201 -32
- package/dist/config.test.js.map +1 -1
- package/dist/connectors/github-webhook.js +83 -5
- package/dist/connectors/github-webhook.js.map +1 -1
- package/dist/connectors/github-webhook.test.d.ts +1 -0
- package/dist/connectors/github-webhook.test.js +156 -0
- package/dist/connectors/github-webhook.test.js.map +1 -0
- package/dist/connectors/messaging/session-manager.d.ts +18 -0
- package/dist/connectors/messaging/session-manager.js +83 -2
- package/dist/connectors/messaging/session-manager.js.map +1 -1
- package/dist/connectors/messaging/session-manager.test.d.ts +1 -0
- package/dist/connectors/messaging/session-manager.test.js +144 -0
- package/dist/connectors/messaging/session-manager.test.js.map +1 -0
- package/dist/connectors/slack/connector.d.ts +9 -0
- package/dist/connectors/slack/connector.js +15 -0
- package/dist/connectors/slack/connector.js.map +1 -1
- package/dist/connectors/slack/mrkdwn.js +81 -0
- package/dist/connectors/slack/mrkdwn.js.map +1 -1
- package/dist/connectors/slack/mrkdwn.test.js +49 -0
- package/dist/connectors/slack/mrkdwn.test.js.map +1 -1
- package/dist/connectors/types.d.ts +1 -1
- package/dist/cron/fanout.d.ts +33 -0
- package/dist/cron/fanout.js +55 -0
- package/dist/cron/fanout.js.map +1 -0
- package/dist/cron/fanout.test.d.ts +1 -0
- package/dist/cron/fanout.test.js +73 -0
- package/dist/cron/fanout.test.js.map +1 -0
- package/dist/cron/jobs.d.ts +5 -0
- package/dist/cron/jobs.js +10 -3
- package/dist/cron/jobs.js.map +1 -1
- package/dist/cron/scheduler.d.ts +12 -0
- package/dist/cron/scheduler.js +27 -1
- package/dist/cron/scheduler.js.map +1 -1
- package/dist/engine/agent-executor.d.ts +158 -0
- package/dist/engine/agent-executor.js +1140 -0
- package/dist/engine/agent-executor.js.map +1 -0
- package/dist/engine/agent-executor.test.d.ts +1 -0
- package/dist/engine/agent-executor.test.js +395 -0
- package/dist/engine/agent-executor.test.js.map +1 -0
- package/dist/engine/chat-runner.d.ts +123 -0
- package/dist/engine/chat-runner.js +379 -0
- package/dist/engine/chat-runner.js.map +1 -0
- package/dist/engine/chat-runner.test.d.ts +1 -0
- package/dist/engine/chat-runner.test.js +104 -0
- package/dist/engine/chat-runner.test.js.map +1 -0
- package/dist/engine/chat-skills.d.ts +45 -0
- package/dist/engine/chat-skills.js +184 -0
- package/dist/engine/chat-skills.js.map +1 -0
- package/dist/engine/chat-skills.test.d.ts +1 -0
- package/dist/engine/chat-skills.test.js +20 -0
- package/dist/engine/chat-skills.test.js.map +1 -0
- package/dist/engine/chat.d.ts +20 -23
- package/dist/engine/chat.js +251 -155
- package/dist/engine/chat.js.map +1 -1
- package/dist/engine/chat.test.d.ts +1 -0
- package/dist/engine/chat.test.js +42 -0
- package/dist/engine/chat.test.js.map +1 -0
- package/dist/engine/classifier.d.ts +35 -2
- package/dist/engine/classifier.js +170 -31
- package/dist/engine/classifier.js.map +1 -1
- package/dist/engine/classifier.test.d.ts +1 -0
- package/dist/engine/classifier.test.js +115 -0
- package/dist/engine/classifier.test.js.map +1 -0
- package/dist/engine/dispatcher.d.ts +60 -0
- package/dist/engine/dispatcher.js +601 -0
- package/dist/engine/dispatcher.js.map +1 -0
- package/dist/engine/dispatcher.test.d.ts +1 -0
- package/dist/engine/dispatcher.test.js +511 -0
- package/dist/engine/dispatcher.test.js.map +1 -0
- package/dist/engine/event-shim.d.ts +117 -0
- package/dist/engine/event-shim.js +435 -0
- package/dist/engine/event-shim.js.map +1 -0
- package/dist/engine/event-shim.test.d.ts +1 -0
- package/dist/engine/event-shim.test.js +194 -0
- package/dist/engine/event-shim.test.js.map +1 -0
- package/dist/engine/git-auth.d.ts +13 -17
- package/dist/engine/git-auth.js +99 -42
- package/dist/engine/git-auth.js.map +1 -1
- package/dist/engine/git-auth.test.d.ts +1 -0
- package/dist/engine/git-auth.test.js +117 -0
- package/dist/engine/git-auth.test.js.map +1 -0
- package/dist/engine/github-app-client.d.ts +7 -0
- package/dist/engine/github-app-client.js +16 -0
- package/dist/engine/github-app-client.js.map +1 -0
- package/dist/engine/github-app-client.test.d.ts +1 -0
- package/dist/engine/github-app-client.test.js +44 -0
- package/dist/engine/github-app-client.test.js.map +1 -0
- package/dist/engine/github-tools.d.ts +12 -0
- package/dist/engine/github-tools.js +261 -0
- package/dist/engine/github-tools.js.map +1 -0
- package/dist/engine/github.d.ts +1027 -43
- package/dist/engine/github.js +153 -14
- package/dist/engine/github.js.map +1 -1
- package/dist/engine/llm.d.ts +47 -0
- package/dist/engine/llm.js +221 -0
- package/dist/engine/llm.js.map +1 -0
- package/dist/engine/llm.test.d.ts +1 -0
- package/dist/engine/llm.test.js +189 -0
- package/dist/engine/llm.test.js.map +1 -0
- package/dist/engine/profiles.d.ts +249 -0
- package/dist/engine/profiles.js +42 -0
- package/dist/engine/profiles.js.map +1 -0
- package/dist/engine/router.d.ts +12 -6
- package/dist/engine/router.js +339 -81
- package/dist/engine/router.js.map +1 -1
- package/dist/engine/router.test.js +428 -78
- package/dist/engine/router.test.js.map +1 -1
- package/dist/engine/screen.d.ts +41 -0
- package/dist/engine/screen.js +93 -0
- package/dist/engine/screen.js.map +1 -0
- package/dist/engine/screen.test.d.ts +1 -0
- package/dist/engine/screen.test.js +82 -0
- package/dist/engine/screen.test.js.map +1 -0
- package/dist/index.js +377 -432
- package/dist/index.js.map +1 -1
- package/dist/managed-repos.d.ts +7 -9
- package/dist/managed-repos.js +12 -15
- package/dist/managed-repos.js.map +1 -1
- package/dist/managed-repos.test.js +24 -19
- package/dist/managed-repos.test.js.map +1 -1
- package/dist/notify/index.d.ts +15 -0
- package/dist/notify/index.js +6 -0
- package/dist/notify/index.js.map +1 -0
- package/dist/notify/model.d.ts +57 -0
- package/dist/notify/model.js +89 -0
- package/dist/notify/model.js.map +1 -0
- package/dist/notify/model.test.d.ts +1 -0
- package/dist/notify/model.test.js +109 -0
- package/dist/notify/model.test.js.map +1 -0
- package/dist/notify/notifier.d.ts +17 -0
- package/dist/notify/notifier.js +87 -0
- package/dist/notify/notifier.js.map +1 -0
- package/dist/notify/notifier.test.d.ts +1 -0
- package/dist/notify/notifier.test.js +100 -0
- package/dist/notify/notifier.test.js.map +1 -0
- package/dist/notify/render.d.ts +21 -0
- package/dist/notify/render.js +59 -0
- package/dist/notify/render.js.map +1 -0
- package/dist/notify/render.test.d.ts +1 -0
- package/dist/notify/render.test.js +65 -0
- package/dist/notify/render.test.js.map +1 -0
- package/dist/notify/transports/github.d.ts +26 -0
- package/dist/notify/transports/github.js +26 -0
- package/dist/notify/transports/github.js.map +1 -0
- package/dist/notify/transports/slack.d.ts +26 -0
- package/dist/notify/transports/slack.js +28 -0
- package/dist/notify/transports/slack.js.map +1 -0
- package/dist/notify/transports.test.d.ts +1 -0
- package/dist/notify/transports.test.js +71 -0
- package/dist/notify/transports.test.js.map +1 -0
- package/dist/notify/types.d.ts +95 -0
- package/dist/notify/types.js +16 -0
- package/dist/notify/types.js.map +1 -0
- package/dist/sandbox/docker-compose.test.d.ts +1 -0
- package/dist/sandbox/docker-compose.test.js +128 -0
- package/dist/sandbox/docker-compose.test.js.map +1 -0
- package/dist/sandbox/docker.d.ts +97 -9
- package/dist/sandbox/docker.js +192 -41
- package/dist/sandbox/docker.js.map +1 -1
- package/dist/sandbox/docker.test.d.ts +1 -0
- package/dist/sandbox/docker.test.js +137 -0
- package/dist/sandbox/docker.test.js.map +1 -0
- package/dist/sandbox/egress-allowlist.d.ts +69 -0
- package/dist/sandbox/egress-allowlist.js +164 -0
- package/dist/sandbox/egress-allowlist.js.map +1 -0
- package/dist/sandbox/egress-allowlist.test.d.ts +1 -0
- package/dist/sandbox/egress-allowlist.test.js +65 -0
- package/dist/sandbox/egress-allowlist.test.js.map +1 -0
- package/dist/sandbox/egress-firewall-config.d.ts +127 -0
- package/dist/sandbox/egress-firewall-config.js +434 -0
- package/dist/sandbox/egress-firewall-config.js.map +1 -0
- package/dist/sandbox/egress-firewall-config.test.d.ts +1 -0
- package/dist/sandbox/egress-firewall-config.test.js +244 -0
- package/dist/sandbox/egress-firewall-config.test.js.map +1 -0
- package/dist/sandbox/images.d.ts +23 -0
- package/dist/sandbox/images.js +55 -0
- package/dist/sandbox/images.js.map +1 -0
- package/dist/sandbox/index.d.ts +82 -3
- package/dist/sandbox/index.js +223 -93
- package/dist/sandbox/index.js.map +1 -1
- package/dist/sandbox/index.test.d.ts +1 -0
- package/dist/sandbox/index.test.js +157 -0
- package/dist/sandbox/index.test.js.map +1 -0
- package/dist/session-log.d.ts +63 -0
- package/dist/session-log.js +290 -0
- package/dist/session-log.js.map +1 -0
- package/dist/session-log.test.d.ts +1 -0
- package/dist/session-log.test.js +85 -0
- package/dist/session-log.test.js.map +1 -0
- package/dist/setup.d.ts +30 -1
- package/dist/setup.js +241 -25
- package/dist/setup.js.map +1 -1
- package/dist/setup.test.js +138 -6
- package/dist/setup.test.js.map +1 -1
- package/dist/state/approval-store.d.ts +86 -0
- package/dist/state/approval-store.js +140 -0
- package/dist/state/approval-store.js.map +1 -0
- package/dist/state/build-assets.d.ts +50 -0
- package/dist/state/build-assets.js +154 -0
- package/dist/state/build-assets.js.map +1 -0
- package/dist/state/build-assets.test.d.ts +1 -0
- package/dist/state/build-assets.test.js +106 -0
- package/dist/state/build-assets.test.js.map +1 -0
- package/dist/state/db.d.ts +65 -333
- package/dist/state/db.js +112 -835
- package/dist/state/db.js.map +1 -1
- package/dist/state/db.test.js +127 -91
- package/dist/state/db.test.js.map +1 -1
- package/dist/state/execution-store.d.ts +257 -0
- package/dist/state/execution-store.js +527 -0
- package/dist/state/execution-store.js.map +1 -0
- package/dist/state/migrate.d.ts +15 -0
- package/dist/state/migrate.js +175 -0
- package/dist/state/migrate.js.map +1 -0
- package/dist/state/workflow-run-store.d.ts +195 -0
- package/dist/state/workflow-run-store.js +363 -0
- package/dist/state/workflow-run-store.js.map +1 -0
- package/dist/state/workflow-run-store.test.d.ts +1 -0
- package/dist/state/workflow-run-store.test.js +264 -0
- package/dist/state/workflow-run-store.test.js.map +1 -0
- package/dist/telemetry/index.d.ts +38 -0
- package/dist/telemetry/index.js +253 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/telemetry/index.test.d.ts +1 -0
- package/dist/telemetry/index.test.js +73 -0
- package/dist/telemetry/index.test.js.map +1 -0
- package/dist/telemetry/pi-events.d.ts +12 -0
- package/dist/telemetry/pi-events.js +134 -0
- package/dist/telemetry/pi-events.js.map +1 -0
- package/dist/telemetry/pi-events.test.d.ts +1 -0
- package/dist/telemetry/pi-events.test.js +69 -0
- package/dist/telemetry/pi-events.test.js.map +1 -0
- package/dist/workflows/dag.d.ts +13 -1
- package/dist/workflows/dag.js +7 -3
- package/dist/workflows/dag.js.map +1 -1
- package/dist/workflows/dag.test.js +22 -0
- package/dist/workflows/dag.test.js.map +1 -1
- package/dist/workflows/golden-build.test.d.ts +1 -0
- package/dist/workflows/golden-build.test.js +45 -0
- package/dist/workflows/golden-build.test.js.map +1 -0
- package/dist/workflows/loader-overlay.test.d.ts +1 -0
- package/dist/workflows/loader-overlay.test.js +101 -0
- package/dist/workflows/loader-overlay.test.js.map +1 -0
- package/dist/workflows/loader.d.ts +36 -11
- package/dist/workflows/loader.js +311 -87
- package/dist/workflows/loader.js.map +1 -1
- package/dist/workflows/loader.test.js +114 -10
- package/dist/workflows/loader.test.js.map +1 -1
- package/dist/workflows/loop-eval.js +2 -0
- package/dist/workflows/loop-eval.js.map +1 -1
- package/dist/workflows/loop-eval.test.js +14 -0
- package/dist/workflows/loop-eval.test.js.map +1 -1
- package/dist/workflows/phase-executor.d.ts +145 -0
- package/dist/workflows/phase-executor.js +691 -0
- package/dist/workflows/phase-executor.js.map +1 -0
- package/dist/workflows/phase-executor.test.d.ts +1 -0
- package/dist/workflows/phase-executor.test.js +434 -0
- package/dist/workflows/phase-executor.test.js.map +1 -0
- package/dist/workflows/phase-ref.d.ts +44 -0
- package/dist/workflows/phase-ref.js +78 -0
- package/dist/workflows/phase-ref.js.map +1 -0
- package/dist/workflows/phase-ref.test.d.ts +1 -0
- package/dist/workflows/phase-ref.test.js +24 -0
- package/dist/workflows/phase-ref.test.js.map +1 -0
- package/dist/workflows/resume.d.ts +5 -11
- package/dist/workflows/resume.js +88 -7
- package/dist/workflows/resume.js.map +1 -1
- package/dist/workflows/runner.d.ts +34 -27
- package/dist/workflows/runner.js +252 -930
- package/dist/workflows/runner.js.map +1 -1
- package/dist/workflows/runner.test.js +346 -35
- package/dist/workflows/runner.test.js.map +1 -1
- package/dist/workflows/schema.d.ts +52 -10
- package/dist/workflows/schema.js +147 -7
- package/dist/workflows/schema.js.map +1 -1
- package/dist/workflows/simple.d.ts +67 -3
- package/dist/workflows/simple.js +248 -87
- package/dist/workflows/simple.js.map +1 -1
- package/dist/workflows/simple.test.d.ts +1 -0
- package/dist/workflows/simple.test.js +107 -0
- package/dist/workflows/simple.test.js.map +1 -0
- package/dist/workflows/templates.d.ts +29 -0
- package/dist/workflows/templates.js +42 -4
- package/dist/workflows/templates.js.map +1 -1
- package/dist/workflows/templates.test.js +103 -0
- package/dist/workflows/templates.test.js.map +1 -1
- package/dist/workflows/triggers.d.ts +21 -0
- package/dist/workflows/triggers.js +44 -0
- package/dist/workflows/triggers.js.map +1 -0
- package/dist/workflows/verdict.d.ts +19 -0
- package/dist/workflows/verdict.js +30 -0
- package/dist/workflows/verdict.js.map +1 -0
- package/dist/workflows/verdict.test.d.ts +1 -0
- package/dist/workflows/verdict.test.js +44 -0
- package/dist/workflows/verdict.test.js.map +1 -0
- package/dist/worktree/manager.d.ts +1 -1
- package/dist/worktree/manager.js +14 -14
- package/dist/worktree/manager.js.map +1 -1
- package/dist/worktree/manager.test.d.ts +1 -0
- package/dist/worktree/manager.test.js +87 -0
- package/dist/worktree/manager.test.js.map +1 -0
- package/docker-compose.yml +206 -5
- package/package.json +17 -7
- package/sandbox.Dockerfile +97 -18
- package/skills/README.md +40 -0
- package/skills/browser-qa/SKILL.md +193 -0
- package/skills/browser-qa/scripts/agent-browser.mjs +380 -0
- package/skills/building/SKILL.md +95 -0
- package/skills/chat/SKILL.md +30 -11
- package/skills/code-review/SKILL.md +59 -0
- package/skills/debug-production/SKILL.md +108 -0
- package/skills/demo/SKILL.md +194 -0
- package/skills/demo/scripts/compose-demo.sh +205 -0
- package/skills/issue-answer/SKILL.md +90 -0
- package/skills/issue-comment/SKILL.md +38 -24
- package/skills/issue-triage/SKILL.md +103 -37
- package/skills/issue-triage/references/AGENT-BRIEF.md +61 -0
- package/skills/pr-comment/SKILL.md +64 -0
- package/skills/pr-review/SKILL.md +65 -49
- package/skills/qa-test/SKILL.md +97 -0
- package/skills/repo-health/SKILL.md +48 -45
- package/skills/security-feedback/SKILL.md +173 -0
- package/skills/security-feedback/references/templates.md +77 -0
- package/skills/security-review/SKILL.md +213 -0
- package/skills/security-review/references/issue-format.md +302 -0
- package/skills/verify/SKILL.md +118 -0
- package/workflows/answer.yaml +37 -0
- package/workflows/build.yaml +32 -22
- package/workflows/cron-security.yaml +6 -0
- package/workflows/demo.yaml +55 -0
- package/workflows/explore.yaml +9 -0
- package/workflows/pr-comment.yaml +16 -0
- package/workflows/pr-fix.yaml +3 -0
- package/workflows/pr-review.yaml +4 -1
- package/workflows/prompts/answer.md +67 -0
- package/workflows/prompts/architect.md +24 -7
- package/workflows/prompts/demo.md +100 -0
- package/workflows/prompts/executor.md +29 -20
- package/workflows/prompts/explore-ask.md +51 -22
- package/workflows/prompts/explore-publish.md +2 -2
- package/workflows/prompts/explore-read.md +24 -10
- package/workflows/prompts/explore-synthesize.md +15 -8
- package/workflows/prompts/fix.md +9 -10
- package/workflows/prompts/guardrails.md +26 -8
- package/workflows/prompts/pr-fix.md +6 -7
- package/workflows/prompts/pr.md +11 -10
- package/workflows/prompts/qa-browser.md +95 -0
- package/workflows/prompts/qa-synth.md +44 -0
- package/workflows/prompts/qa-test.md +60 -0
- package/workflows/prompts/re-reviewer.md +8 -9
- package/workflows/prompts/reviewer.md +10 -9
- package/workflows/prompts/verify-browser.md +93 -0
- package/workflows/prompts/verify-synth.md +44 -0
- package/workflows/prompts/verify.md +63 -0
- package/workflows/qa-test.yaml +87 -0
- package/workflows/security-feedback.yaml +25 -0
- package/workflows/security-review.yaml +29 -0
- package/workflows/verify.yaml +85 -0
- package/deploy/mcp-config.tmpl.json +0 -14
- package/dist/cron/rate-limits.d.ts +0 -26
- package/dist/cron/rate-limits.js +0 -193
- package/dist/cron/rate-limits.js.map +0 -1
- package/dist/engine/executor.d.ts +0 -75
- package/dist/engine/executor.js +0 -292
- package/dist/engine/executor.js.map +0 -1
- package/mcp-github-app/package.json +0 -18
- package/mcp-github-app/src/auth.js +0 -66
- package/mcp-github-app/src/github.js +0 -371
- package/mcp-github-app/src/index.js +0 -534
- package/skills/devops/webhook-subscriptions/SKILL.md +0 -180
- package/skills/github/DESCRIPTION.md +0 -3
- package/skills/github/codebase-inspection/SKILL.md +0 -115
- package/skills/github/github-auth/SKILL.md +0 -54
- package/skills/github/github-auth/scripts/gh-env.sh +0 -66
- package/skills/github/github-code-review/SKILL.md +0 -480
- package/skills/github/github-code-review/references/review-output-template.md +0 -74
- package/skills/github/github-issues/SKILL.md +0 -369
- package/skills/github/github-issues/templates/bug-report.md +0 -35
- package/skills/github/github-issues/templates/feature-request.md +0 -31
- package/skills/github/github-pr-workflow/SKILL.md +0 -395
- package/skills/github/github-pr-workflow/references/ci-troubleshooting.md +0 -183
- package/skills/github/github-pr-workflow/references/conventional-commits.md +0 -71
- package/skills/github/github-pr-workflow/templates/pr-body-bugfix.md +0 -35
- package/skills/github/github-pr-workflow/templates/pr-body-feature.md +0 -33
- package/skills/github/github-repo-management/SKILL.md +0 -515
- package/skills/github/github-repo-management/references/github-api-cheatsheet.md +0 -161
- package/skills/github-orchestrator/SKILL.md +0 -103
- package/skills/mcp/DESCRIPTION.md +0 -3
- package/skills/mcp/mcporter/SKILL.md +0 -122
- package/skills/mcp/native-mcp/SKILL.md +0 -356
- package/skills/software-development/architect/SKILL.md +0 -154
- package/skills/software-development/assure-guardrails/SKILL.md +0 -239
- package/skills/software-development/plan/SKILL.md +0 -64
- package/skills/software-development/requesting-code-review/SKILL.md +0 -291
- package/skills/software-development/subagent-driven-development/SKILL.md +0 -433
- package/skills/software-development/systematic-debugging/SKILL.md +0 -366
- package/skills/software-development/test-driven-development/SKILL.md +0 -342
|
@@ -1,534 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
|
-
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
|
-
import { z } from "zod";
|
|
6
|
-
import { execSync } from "child_process";
|
|
7
|
-
import { GitHubAppAuth } from "./auth.js";
|
|
8
|
-
import { GitHubClient } from "./github.js";
|
|
9
|
-
|
|
10
|
-
// ── Config from environment ─────────────────────────────────────────
|
|
11
|
-
|
|
12
|
-
const appId = process.env.GITHUB_APP_ID;
|
|
13
|
-
const privateKeyPath = process.env.GITHUB_APP_PRIVATE_KEY_PATH;
|
|
14
|
-
const installationId = process.env.GITHUB_APP_INSTALLATION_ID;
|
|
15
|
-
const staticToken = process.env.GITHUB_TOKEN;
|
|
16
|
-
|
|
17
|
-
const hasAppCreds = Boolean(appId && privateKeyPath && installationId);
|
|
18
|
-
|
|
19
|
-
if (!staticToken && !hasAppCreds) {
|
|
20
|
-
console.error(
|
|
21
|
-
"Required auth env vars: either GITHUB_TOKEN or all of GITHUB_APP_ID, GITHUB_APP_PRIVATE_KEY_PATH, GITHUB_APP_INSTALLATION_ID"
|
|
22
|
-
);
|
|
23
|
-
process.exit(1);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// Prefer GitHub App credentials when both are present. Static-token mode is
|
|
27
|
-
// the fallback for low-trust sandboxes that intentionally clear the App env
|
|
28
|
-
// vars (see executor.ts: GITHUB_APP_ID="" + ALLOW_APP_PEM=0). This ordering
|
|
29
|
-
// stops a stale host-side GITHUB_TOKEN PAT from silently downgrading the
|
|
30
|
-
// agent's auth — which surfaced as a 403 "Resource not accessible by
|
|
31
|
-
// personal access token" when the chat skill tried to create an issue.
|
|
32
|
-
const auth = hasAppCreds
|
|
33
|
-
? new GitHubAppAuth({ appId, privateKeyPath, installationId })
|
|
34
|
-
: {
|
|
35
|
-
async getToken() {
|
|
36
|
-
return staticToken;
|
|
37
|
-
},
|
|
38
|
-
get expiresAt() {
|
|
39
|
-
return null;
|
|
40
|
-
},
|
|
41
|
-
};
|
|
42
|
-
const gh = new GitHubClient(auth);
|
|
43
|
-
|
|
44
|
-
// ── MCP Server ──────────────────────────────────────────────────────
|
|
45
|
-
|
|
46
|
-
const server = new McpServer({
|
|
47
|
-
name: "github-app",
|
|
48
|
-
version: "1.0.0",
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
// Helper to run a tool handler and return JSON result
|
|
52
|
-
function jsonResult(data) {
|
|
53
|
-
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
async function run(fn) {
|
|
57
|
-
try {
|
|
58
|
-
const result = await fn();
|
|
59
|
-
return jsonResult(result);
|
|
60
|
-
} catch (e) {
|
|
61
|
-
const status = e.status || e.response?.status;
|
|
62
|
-
const isTransient = [408, 429, 500, 502, 503, 504].includes(status);
|
|
63
|
-
return jsonResult({
|
|
64
|
-
error: e.message,
|
|
65
|
-
status: status || null,
|
|
66
|
-
transient: isTransient,
|
|
67
|
-
hint: isTransient
|
|
68
|
-
? "This is a transient error. The request was retried automatically but still failed. Wait and try again."
|
|
69
|
-
: status === 401
|
|
70
|
-
? "Authentication failed. Call refresh_git_auth to get a fresh token."
|
|
71
|
-
: null,
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// ── Git Auth Tools ──────────────────────────────────────────────────
|
|
77
|
-
|
|
78
|
-
server.tool(
|
|
79
|
-
"clone_repo",
|
|
80
|
-
"Clone a repository with GitHub App authentication. Sets up credential helper and bot identity automatically. git push/pull/fetch will just work after cloning.",
|
|
81
|
-
{
|
|
82
|
-
owner: z.string().describe("Repository owner"),
|
|
83
|
-
repo: z.string().describe("Repository name"),
|
|
84
|
-
branch: z.string().optional().describe("Branch to checkout (default: repo default branch)"),
|
|
85
|
-
path: z.string().optional().describe("Local path to clone into (default: repo name)"),
|
|
86
|
-
},
|
|
87
|
-
async ({ owner, repo, branch, path: clonePath }) => {
|
|
88
|
-
try {
|
|
89
|
-
const token = await auth.getToken();
|
|
90
|
-
const dest = clonePath || repo;
|
|
91
|
-
const url = `https://x-access-token:${token}@github.com/${owner}/${repo}.git`;
|
|
92
|
-
|
|
93
|
-
const branchArgs = branch ? ["--branch", branch] : [];
|
|
94
|
-
execSync(["git", "clone", ...branchArgs, url, dest].join(" "), {
|
|
95
|
-
stdio: "pipe",
|
|
96
|
-
timeout: 120_000,
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
// Configure credential helper so push/pull get fresh tokens
|
|
100
|
-
const credHelper = `!f() { echo "username=x-access-token"; echo "password=${token}"; }; f`;
|
|
101
|
-
execSync(`git -C ${dest} config credential.helper '${credHelper}'`, { stdio: "pipe" });
|
|
102
|
-
|
|
103
|
-
// Set bot identity for commits
|
|
104
|
-
execSync(`git -C ${dest} config user.name "last-light[bot]"`, { stdio: "pipe" });
|
|
105
|
-
execSync(
|
|
106
|
-
`git -C ${dest} config user.email "last-light[bot]@users.noreply.github.com"`,
|
|
107
|
-
{ stdio: "pipe" }
|
|
108
|
-
);
|
|
109
|
-
|
|
110
|
-
return jsonResult({
|
|
111
|
-
cloned: `${owner}/${repo}`,
|
|
112
|
-
path: dest,
|
|
113
|
-
branch: branch || "(default)",
|
|
114
|
-
expires_at: auth.expiresAt?.toISOString(),
|
|
115
|
-
});
|
|
116
|
-
} catch (e) {
|
|
117
|
-
return jsonResult({ error: e.message, stderr: e.stderr?.toString() });
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
);
|
|
121
|
-
|
|
122
|
-
server.tool(
|
|
123
|
-
"refresh_git_auth",
|
|
124
|
-
"Refresh the GitHub App token for an existing git clone. Call this if git push/pull fails with auth errors. Updates the credential helper with a fresh token.",
|
|
125
|
-
{
|
|
126
|
-
path: z.string().describe("Path to the git repository"),
|
|
127
|
-
},
|
|
128
|
-
async ({ path: repoPath }) => {
|
|
129
|
-
try {
|
|
130
|
-
const token = await auth.getToken();
|
|
131
|
-
const credHelper = `!f() { echo "username=x-access-token"; echo "password=${token}"; }; f`;
|
|
132
|
-
execSync(`git -C ${repoPath} config credential.helper '${credHelper}'`, { stdio: "pipe" });
|
|
133
|
-
return jsonResult({
|
|
134
|
-
refreshed: true,
|
|
135
|
-
path: repoPath,
|
|
136
|
-
expires_at: auth.expiresAt?.toISOString(),
|
|
137
|
-
});
|
|
138
|
-
} catch (e) {
|
|
139
|
-
return jsonResult({ error: e.message });
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
);
|
|
143
|
-
|
|
144
|
-
// DEPRECATED: Use clone_repo + refresh_git_auth instead.
|
|
145
|
-
// Kept for backward compatibility with Hermes-based workflows.
|
|
146
|
-
server.tool(
|
|
147
|
-
"setup_git_auth",
|
|
148
|
-
"[DEPRECATED — use clone_repo instead] Refresh the GitHub App token and write it to the credential file for Hermes sandbox sync.",
|
|
149
|
-
{ owner: z.string().describe("Repository owner"), repo: z.string().describe("Repository name") },
|
|
150
|
-
async ({ owner, repo }) => {
|
|
151
|
-
try {
|
|
152
|
-
const token = await auth.getToken();
|
|
153
|
-
const fs = await import("fs");
|
|
154
|
-
const nodePath = await import("path");
|
|
155
|
-
|
|
156
|
-
const hermesHome = process.env.HERMES_HOME || (process.env.HOME + "/.hermes");
|
|
157
|
-
const tokenPath = nodePath.join(hermesHome, ".gh-token");
|
|
158
|
-
fs.writeFileSync(tokenPath, token, { mode: 0o600 });
|
|
159
|
-
|
|
160
|
-
return jsonResult({
|
|
161
|
-
deprecated: "Use clone_repo instead — it handles auth, clone, and identity in one step.",
|
|
162
|
-
expires_at: auth.expiresAt?.toISOString(),
|
|
163
|
-
token_file: tokenPath,
|
|
164
|
-
configure_git: `git config --global include.path ${hermesHome}/.gitconfig-bot`,
|
|
165
|
-
clone_with: `git clone https://github.com/${owner}/${repo}.git`,
|
|
166
|
-
});
|
|
167
|
-
} catch (e) {
|
|
168
|
-
return jsonResult({ error: e.message });
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
);
|
|
172
|
-
|
|
173
|
-
// ── Repository Tools ────────────────────────────────────────────────
|
|
174
|
-
|
|
175
|
-
server.tool(
|
|
176
|
-
"get_repository",
|
|
177
|
-
"Get repository metadata",
|
|
178
|
-
{ owner: z.string(), repo: z.string() },
|
|
179
|
-
async ({ owner, repo }) => run(() => gh.getRepository(owner, repo))
|
|
180
|
-
);
|
|
181
|
-
|
|
182
|
-
server.tool(
|
|
183
|
-
"get_file_contents",
|
|
184
|
-
"Get contents of a file or directory from a repository",
|
|
185
|
-
{
|
|
186
|
-
owner: z.string(),
|
|
187
|
-
repo: z.string(),
|
|
188
|
-
path: z.string(),
|
|
189
|
-
branch: z.string().optional(),
|
|
190
|
-
},
|
|
191
|
-
async ({ owner, repo, path, branch }) =>
|
|
192
|
-
run(() => gh.getFileContents(owner, repo, path, branch))
|
|
193
|
-
);
|
|
194
|
-
|
|
195
|
-
server.tool(
|
|
196
|
-
"create_or_update_file",
|
|
197
|
-
"Create or update a single file in a repository",
|
|
198
|
-
{
|
|
199
|
-
owner: z.string(),
|
|
200
|
-
repo: z.string(),
|
|
201
|
-
path: z.string(),
|
|
202
|
-
content: z.string().describe("File content"),
|
|
203
|
-
message: z.string().describe("Commit message"),
|
|
204
|
-
branch: z.string().optional(),
|
|
205
|
-
sha: z.string().optional().describe("SHA of file being replaced (for updates)"),
|
|
206
|
-
},
|
|
207
|
-
async ({ owner, repo, path, content, message, branch, sha }) =>
|
|
208
|
-
run(() => gh.createOrUpdateFile(owner, repo, path, content, message, branch, sha))
|
|
209
|
-
);
|
|
210
|
-
|
|
211
|
-
server.tool(
|
|
212
|
-
"push_files",
|
|
213
|
-
"Push multiple files in a single commit",
|
|
214
|
-
{
|
|
215
|
-
owner: z.string(),
|
|
216
|
-
repo: z.string(),
|
|
217
|
-
branch: z.string(),
|
|
218
|
-
files: z.array(z.object({ path: z.string(), content: z.string() })),
|
|
219
|
-
message: z.string(),
|
|
220
|
-
},
|
|
221
|
-
async ({ owner, repo, branch, files, message }) =>
|
|
222
|
-
run(() => gh.pushFiles(owner, repo, branch, files, message))
|
|
223
|
-
);
|
|
224
|
-
|
|
225
|
-
server.tool(
|
|
226
|
-
"list_branches",
|
|
227
|
-
"List branches in a repository",
|
|
228
|
-
{
|
|
229
|
-
owner: z.string(),
|
|
230
|
-
repo: z.string(),
|
|
231
|
-
page: z.number().optional(),
|
|
232
|
-
per_page: z.number().optional(),
|
|
233
|
-
},
|
|
234
|
-
async ({ owner, repo, page, per_page }) =>
|
|
235
|
-
run(() => gh.listBranches(owner, repo, page, per_page))
|
|
236
|
-
);
|
|
237
|
-
|
|
238
|
-
server.tool(
|
|
239
|
-
"create_branch",
|
|
240
|
-
"Create a new branch from an existing branch",
|
|
241
|
-
{
|
|
242
|
-
owner: z.string(),
|
|
243
|
-
repo: z.string(),
|
|
244
|
-
branch: z.string().describe("New branch name"),
|
|
245
|
-
from_branch: z.string().describe("Source branch"),
|
|
246
|
-
},
|
|
247
|
-
async ({ owner, repo, branch, from_branch }) =>
|
|
248
|
-
run(() => gh.createBranch(owner, repo, branch, from_branch))
|
|
249
|
-
);
|
|
250
|
-
|
|
251
|
-
// ── Issue Tools ─────────────────────────────────────────────────────
|
|
252
|
-
|
|
253
|
-
server.tool(
|
|
254
|
-
"list_issues",
|
|
255
|
-
"List open issues in a repository",
|
|
256
|
-
{
|
|
257
|
-
owner: z.string(),
|
|
258
|
-
repo: z.string(),
|
|
259
|
-
state: z.enum(["open", "closed", "all"]).optional(),
|
|
260
|
-
labels: z.string().optional().describe("Comma-separated label names"),
|
|
261
|
-
sort: z.enum(["created", "updated", "comments"]).optional(),
|
|
262
|
-
direction: z.enum(["asc", "desc"]).optional(),
|
|
263
|
-
page: z.number().optional(),
|
|
264
|
-
per_page: z.number().optional(),
|
|
265
|
-
},
|
|
266
|
-
async ({ owner, repo, ...opts }) => run(() => gh.listIssues(owner, repo, opts))
|
|
267
|
-
);
|
|
268
|
-
|
|
269
|
-
server.tool(
|
|
270
|
-
"get_issue",
|
|
271
|
-
"Get a specific issue by number",
|
|
272
|
-
{ owner: z.string(), repo: z.string(), issue_number: z.number() },
|
|
273
|
-
async ({ owner, repo, issue_number }) => run(() => gh.getIssue(owner, repo, issue_number))
|
|
274
|
-
);
|
|
275
|
-
|
|
276
|
-
server.tool(
|
|
277
|
-
"create_issue",
|
|
278
|
-
"Create a new issue",
|
|
279
|
-
{
|
|
280
|
-
owner: z.string(),
|
|
281
|
-
repo: z.string(),
|
|
282
|
-
title: z.string(),
|
|
283
|
-
body: z.string().optional(),
|
|
284
|
-
labels: z.array(z.string()).optional(),
|
|
285
|
-
assignees: z.array(z.string()).optional(),
|
|
286
|
-
milestone: z.number().optional(),
|
|
287
|
-
},
|
|
288
|
-
async ({ owner, repo, title, body, ...opts }) =>
|
|
289
|
-
run(() => gh.createIssue(owner, repo, title, body, opts))
|
|
290
|
-
);
|
|
291
|
-
|
|
292
|
-
server.tool(
|
|
293
|
-
"update_issue",
|
|
294
|
-
"Update an existing issue (title, body, state, labels, assignees)",
|
|
295
|
-
{
|
|
296
|
-
owner: z.string(),
|
|
297
|
-
repo: z.string(),
|
|
298
|
-
issue_number: z.number(),
|
|
299
|
-
title: z.string().optional(),
|
|
300
|
-
body: z.string().optional(),
|
|
301
|
-
state: z.enum(["open", "closed"]).optional(),
|
|
302
|
-
labels: z.array(z.string()).optional(),
|
|
303
|
-
assignees: z.array(z.string()).optional(),
|
|
304
|
-
},
|
|
305
|
-
async ({ owner, repo, issue_number, ...updates }) =>
|
|
306
|
-
run(() => gh.updateIssue(owner, repo, issue_number, updates))
|
|
307
|
-
);
|
|
308
|
-
|
|
309
|
-
server.tool(
|
|
310
|
-
"add_issue_comment",
|
|
311
|
-
"Add a comment to an issue or pull request",
|
|
312
|
-
{
|
|
313
|
-
owner: z.string(),
|
|
314
|
-
repo: z.string(),
|
|
315
|
-
issue_number: z.number(),
|
|
316
|
-
body: z.string(),
|
|
317
|
-
},
|
|
318
|
-
async ({ owner, repo, issue_number, body }) =>
|
|
319
|
-
run(() => gh.addIssueComment(owner, repo, issue_number, body))
|
|
320
|
-
);
|
|
321
|
-
|
|
322
|
-
server.tool(
|
|
323
|
-
"list_issue_comments",
|
|
324
|
-
"List comments on an issue",
|
|
325
|
-
{
|
|
326
|
-
owner: z.string(),
|
|
327
|
-
repo: z.string(),
|
|
328
|
-
issue_number: z.number(),
|
|
329
|
-
page: z.number().optional(),
|
|
330
|
-
per_page: z.number().optional(),
|
|
331
|
-
},
|
|
332
|
-
async ({ owner, repo, issue_number, ...opts }) =>
|
|
333
|
-
run(() => gh.listIssueComments(owner, repo, issue_number, opts))
|
|
334
|
-
);
|
|
335
|
-
|
|
336
|
-
server.tool(
|
|
337
|
-
"add_labels",
|
|
338
|
-
"Add labels to an issue or PR",
|
|
339
|
-
{
|
|
340
|
-
owner: z.string(),
|
|
341
|
-
repo: z.string(),
|
|
342
|
-
issue_number: z.number(),
|
|
343
|
-
labels: z.array(z.string()),
|
|
344
|
-
},
|
|
345
|
-
async ({ owner, repo, issue_number, labels }) =>
|
|
346
|
-
run(() => gh.addLabels(owner, repo, issue_number, labels))
|
|
347
|
-
);
|
|
348
|
-
|
|
349
|
-
server.tool(
|
|
350
|
-
"remove_label",
|
|
351
|
-
"Remove a label from an issue or PR",
|
|
352
|
-
{
|
|
353
|
-
owner: z.string(),
|
|
354
|
-
repo: z.string(),
|
|
355
|
-
issue_number: z.number(),
|
|
356
|
-
name: z.string(),
|
|
357
|
-
},
|
|
358
|
-
async ({ owner, repo, issue_number, name }) =>
|
|
359
|
-
run(() => gh.removeLabel(owner, repo, issue_number, name))
|
|
360
|
-
);
|
|
361
|
-
|
|
362
|
-
server.tool(
|
|
363
|
-
"list_labels",
|
|
364
|
-
"List all labels in a repository",
|
|
365
|
-
{ owner: z.string(), repo: z.string() },
|
|
366
|
-
async ({ owner, repo }) => run(() => gh.listLabels(owner, repo))
|
|
367
|
-
);
|
|
368
|
-
|
|
369
|
-
server.tool(
|
|
370
|
-
"create_label",
|
|
371
|
-
"Create a new label in a repository",
|
|
372
|
-
{
|
|
373
|
-
owner: z.string(),
|
|
374
|
-
repo: z.string(),
|
|
375
|
-
name: z.string(),
|
|
376
|
-
color: z.string().describe("Hex color without #, e.g. 'ff0000'"),
|
|
377
|
-
description: z.string().optional(),
|
|
378
|
-
},
|
|
379
|
-
async ({ owner, repo, name, color, description }) =>
|
|
380
|
-
run(() => gh.createLabel(owner, repo, name, color, description))
|
|
381
|
-
);
|
|
382
|
-
|
|
383
|
-
// ── Pull Request Tools ──────────────────────────────────────────────
|
|
384
|
-
|
|
385
|
-
server.tool(
|
|
386
|
-
"list_pull_requests",
|
|
387
|
-
"List pull requests in a repository",
|
|
388
|
-
{
|
|
389
|
-
owner: z.string(),
|
|
390
|
-
repo: z.string(),
|
|
391
|
-
state: z.enum(["open", "closed", "all"]).optional(),
|
|
392
|
-
sort: z.enum(["created", "updated", "popularity", "long-running"]).optional(),
|
|
393
|
-
direction: z.enum(["asc", "desc"]).optional(),
|
|
394
|
-
head: z.string().optional().describe("Filter by head branch (user:branch)"),
|
|
395
|
-
base: z.string().optional().describe("Filter by base branch"),
|
|
396
|
-
page: z.number().optional(),
|
|
397
|
-
per_page: z.number().optional(),
|
|
398
|
-
},
|
|
399
|
-
async ({ owner, repo, ...opts }) => run(() => gh.listPullRequests(owner, repo, opts))
|
|
400
|
-
);
|
|
401
|
-
|
|
402
|
-
server.tool(
|
|
403
|
-
"get_pull_request",
|
|
404
|
-
"Get a specific pull request by number",
|
|
405
|
-
{ owner: z.string(), repo: z.string(), pull_number: z.number() },
|
|
406
|
-
async ({ owner, repo, pull_number }) => run(() => gh.getPullRequest(owner, repo, pull_number))
|
|
407
|
-
);
|
|
408
|
-
|
|
409
|
-
server.tool(
|
|
410
|
-
"create_pull_request",
|
|
411
|
-
"Create a new pull request",
|
|
412
|
-
{
|
|
413
|
-
owner: z.string(),
|
|
414
|
-
repo: z.string(),
|
|
415
|
-
title: z.string(),
|
|
416
|
-
body: z.string().optional(),
|
|
417
|
-
head: z.string().describe("Branch with changes"),
|
|
418
|
-
base: z.string().describe("Branch to merge into"),
|
|
419
|
-
},
|
|
420
|
-
async ({ owner, repo, title, body, head, base }) =>
|
|
421
|
-
run(() => gh.createPullRequest(owner, repo, title, body, head, base))
|
|
422
|
-
);
|
|
423
|
-
|
|
424
|
-
server.tool(
|
|
425
|
-
"list_pull_request_files",
|
|
426
|
-
"List files changed in a pull request",
|
|
427
|
-
{ owner: z.string(), repo: z.string(), pull_number: z.number() },
|
|
428
|
-
async ({ owner, repo, pull_number }) =>
|
|
429
|
-
run(() => gh.listPullRequestFiles(owner, repo, pull_number))
|
|
430
|
-
);
|
|
431
|
-
|
|
432
|
-
server.tool(
|
|
433
|
-
"get_pull_request_diff",
|
|
434
|
-
"Get the diff of a pull request",
|
|
435
|
-
{ owner: z.string(), repo: z.string(), pull_number: z.number() },
|
|
436
|
-
async ({ owner, repo, pull_number }) =>
|
|
437
|
-
run(() => gh.getPullRequestDiff(owner, repo, pull_number))
|
|
438
|
-
);
|
|
439
|
-
|
|
440
|
-
server.tool(
|
|
441
|
-
"create_pull_request_review",
|
|
442
|
-
"Create a review on a pull request",
|
|
443
|
-
{
|
|
444
|
-
owner: z.string(),
|
|
445
|
-
repo: z.string(),
|
|
446
|
-
pull_number: z.number(),
|
|
447
|
-
body: z.string().describe("Review summary"),
|
|
448
|
-
event: z.enum(["APPROVE", "REQUEST_CHANGES", "COMMENT"]),
|
|
449
|
-
comments: z
|
|
450
|
-
.array(
|
|
451
|
-
z.object({
|
|
452
|
-
path: z.string(),
|
|
453
|
-
position: z.number().optional(),
|
|
454
|
-
line: z.number().optional(),
|
|
455
|
-
body: z.string(),
|
|
456
|
-
})
|
|
457
|
-
)
|
|
458
|
-
.optional()
|
|
459
|
-
.describe("Inline review comments"),
|
|
460
|
-
},
|
|
461
|
-
async ({ owner, repo, pull_number, body, event, comments }) =>
|
|
462
|
-
run(() => gh.createPullRequestReview(owner, repo, pull_number, body, event, comments || []))
|
|
463
|
-
);
|
|
464
|
-
|
|
465
|
-
server.tool(
|
|
466
|
-
"merge_pull_request",
|
|
467
|
-
"Merge a pull request",
|
|
468
|
-
{
|
|
469
|
-
owner: z.string(),
|
|
470
|
-
repo: z.string(),
|
|
471
|
-
pull_number: z.number(),
|
|
472
|
-
commit_title: z.string().optional(),
|
|
473
|
-
commit_message: z.string().optional(),
|
|
474
|
-
merge_method: z.enum(["merge", "squash", "rebase"]).optional(),
|
|
475
|
-
},
|
|
476
|
-
async ({ owner, repo, pull_number, ...opts }) =>
|
|
477
|
-
run(() => gh.mergePullRequest(owner, repo, pull_number, opts))
|
|
478
|
-
);
|
|
479
|
-
|
|
480
|
-
// ── Commit Tools ────────────────────────────────────────────────────
|
|
481
|
-
|
|
482
|
-
server.tool(
|
|
483
|
-
"list_commits",
|
|
484
|
-
"List commits on a repository or branch",
|
|
485
|
-
{
|
|
486
|
-
owner: z.string(),
|
|
487
|
-
repo: z.string(),
|
|
488
|
-
sha: z.string().optional().describe("Branch name or commit SHA"),
|
|
489
|
-
path: z.string().optional().describe("Only commits touching this path"),
|
|
490
|
-
page: z.number().optional(),
|
|
491
|
-
per_page: z.number().optional(),
|
|
492
|
-
},
|
|
493
|
-
async ({ owner, repo, ...opts }) => run(() => gh.listCommits(owner, repo, opts))
|
|
494
|
-
);
|
|
495
|
-
|
|
496
|
-
// ── Search Tools ────────────────────────────────────────────────────
|
|
497
|
-
|
|
498
|
-
server.tool(
|
|
499
|
-
"search_repositories",
|
|
500
|
-
"Search for GitHub repositories",
|
|
501
|
-
{
|
|
502
|
-
query: z.string(),
|
|
503
|
-
page: z.number().optional(),
|
|
504
|
-
per_page: z.number().optional(),
|
|
505
|
-
},
|
|
506
|
-
async ({ query, page, per_page }) => run(() => gh.searchRepositories(query, page, per_page))
|
|
507
|
-
);
|
|
508
|
-
|
|
509
|
-
server.tool(
|
|
510
|
-
"search_issues",
|
|
511
|
-
"Search issues and pull requests across repositories",
|
|
512
|
-
{
|
|
513
|
-
query: z.string().describe("GitHub search query (e.g. 'repo:owner/name is:open label:bug')"),
|
|
514
|
-
page: z.number().optional(),
|
|
515
|
-
per_page: z.number().optional(),
|
|
516
|
-
},
|
|
517
|
-
async ({ query, page, per_page }) => run(() => gh.searchIssues(query, page, per_page))
|
|
518
|
-
);
|
|
519
|
-
|
|
520
|
-
server.tool(
|
|
521
|
-
"search_code",
|
|
522
|
-
"Search code across repositories",
|
|
523
|
-
{
|
|
524
|
-
query: z.string().describe("GitHub code search query"),
|
|
525
|
-
page: z.number().optional(),
|
|
526
|
-
per_page: z.number().optional(),
|
|
527
|
-
},
|
|
528
|
-
async ({ query, page, per_page }) => run(() => gh.searchCode(query, page, per_page))
|
|
529
|
-
);
|
|
530
|
-
|
|
531
|
-
// ── Start ───────────────────────────────────────────────────────────
|
|
532
|
-
|
|
533
|
-
const transport = new StdioServerTransport();
|
|
534
|
-
await server.connect(transport);
|
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: webhook-subscriptions
|
|
3
|
-
description: Create and manage webhook subscriptions for event-driven agent activation. Use when the user wants external services to trigger agent runs automatically.
|
|
4
|
-
version: 1.0.0
|
|
5
|
-
metadata:
|
|
6
|
-
hermes:
|
|
7
|
-
tags: [webhook, events, automation, integrations]
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
# Webhook Subscriptions
|
|
11
|
-
|
|
12
|
-
Create dynamic webhook subscriptions so external services (GitHub, GitLab, Stripe, CI/CD, IoT sensors, monitoring tools) can trigger Hermes agent runs by POSTing events to a URL.
|
|
13
|
-
|
|
14
|
-
## Setup (Required First)
|
|
15
|
-
|
|
16
|
-
The webhook platform must be enabled before subscriptions can be created. Check with:
|
|
17
|
-
```bash
|
|
18
|
-
hermes webhook list
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
If it says "Webhook platform is not enabled", set it up:
|
|
22
|
-
|
|
23
|
-
### Option 1: Setup wizard
|
|
24
|
-
```bash
|
|
25
|
-
hermes gateway setup
|
|
26
|
-
```
|
|
27
|
-
Follow the prompts to enable webhooks, set the port, and set a global HMAC secret.
|
|
28
|
-
|
|
29
|
-
### Option 2: Manual config
|
|
30
|
-
Add to `~/.hermes/config.yaml`:
|
|
31
|
-
```yaml
|
|
32
|
-
platforms:
|
|
33
|
-
webhook:
|
|
34
|
-
enabled: true
|
|
35
|
-
extra:
|
|
36
|
-
host: "0.0.0.0"
|
|
37
|
-
port: 8644
|
|
38
|
-
secret: "generate-a-strong-secret-here"
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
### Option 3: Environment variables
|
|
42
|
-
Add to `~/.hermes/.env`:
|
|
43
|
-
```bash
|
|
44
|
-
WEBHOOK_ENABLED=true
|
|
45
|
-
WEBHOOK_PORT=8644
|
|
46
|
-
WEBHOOK_SECRET=generate-a-strong-secret-here
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
After configuration, start (or restart) the gateway:
|
|
50
|
-
```bash
|
|
51
|
-
hermes gateway run
|
|
52
|
-
# Or if using systemd:
|
|
53
|
-
systemctl --user restart hermes-gateway
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
Verify it's running:
|
|
57
|
-
```bash
|
|
58
|
-
curl http://localhost:8644/health
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
## Commands
|
|
62
|
-
|
|
63
|
-
All management is via the `hermes webhook` CLI command:
|
|
64
|
-
|
|
65
|
-
### Create a subscription
|
|
66
|
-
```bash
|
|
67
|
-
hermes webhook subscribe <name> \
|
|
68
|
-
--prompt "Prompt template with {payload.fields}" \
|
|
69
|
-
--events "event1,event2" \
|
|
70
|
-
--description "What this does" \
|
|
71
|
-
--skills "skill1,skill2" \
|
|
72
|
-
--deliver telegram \
|
|
73
|
-
--deliver-chat-id "12345" \
|
|
74
|
-
--secret "optional-custom-secret"
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
Returns the webhook URL and HMAC secret. The user configures their service to POST to that URL.
|
|
78
|
-
|
|
79
|
-
### List subscriptions
|
|
80
|
-
```bash
|
|
81
|
-
hermes webhook list
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
### Remove a subscription
|
|
85
|
-
```bash
|
|
86
|
-
hermes webhook remove <name>
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
### Test a subscription
|
|
90
|
-
```bash
|
|
91
|
-
hermes webhook test <name>
|
|
92
|
-
hermes webhook test <name> --payload '{"key": "value"}'
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
## Prompt Templates
|
|
96
|
-
|
|
97
|
-
Prompts support `{dot.notation}` for accessing nested payload fields:
|
|
98
|
-
|
|
99
|
-
- `{issue.title}` — GitHub issue title
|
|
100
|
-
- `{pull_request.user.login}` — PR author
|
|
101
|
-
- `{data.object.amount}` — Stripe payment amount
|
|
102
|
-
- `{sensor.temperature}` — IoT sensor reading
|
|
103
|
-
|
|
104
|
-
If no prompt is specified, the full JSON payload is dumped into the agent prompt.
|
|
105
|
-
|
|
106
|
-
## Common Patterns
|
|
107
|
-
|
|
108
|
-
### GitHub: new issues
|
|
109
|
-
```bash
|
|
110
|
-
hermes webhook subscribe github-issues \
|
|
111
|
-
--events "issues" \
|
|
112
|
-
--prompt "New GitHub issue #{issue.number}: {issue.title}\n\nAction: {action}\nAuthor: {issue.user.login}\nBody:\n{issue.body}\n\nPlease triage this issue." \
|
|
113
|
-
--deliver telegram \
|
|
114
|
-
--deliver-chat-id "-100123456789"
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
Then in GitHub repo Settings → Webhooks → Add webhook:
|
|
118
|
-
- Payload URL: the returned webhook_url
|
|
119
|
-
- Content type: application/json
|
|
120
|
-
- Secret: the returned secret
|
|
121
|
-
- Events: "Issues"
|
|
122
|
-
|
|
123
|
-
### GitHub: PR reviews
|
|
124
|
-
```bash
|
|
125
|
-
hermes webhook subscribe github-prs \
|
|
126
|
-
--events "pull_request" \
|
|
127
|
-
--prompt "PR #{pull_request.number} {action}: {pull_request.title}\nBy: {pull_request.user.login}\nBranch: {pull_request.head.ref}\n\n{pull_request.body}" \
|
|
128
|
-
--skills "github-code-review" \
|
|
129
|
-
--deliver github_comment
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
### Stripe: payment events
|
|
133
|
-
```bash
|
|
134
|
-
hermes webhook subscribe stripe-payments \
|
|
135
|
-
--events "payment_intent.succeeded,payment_intent.payment_failed" \
|
|
136
|
-
--prompt "Payment {data.object.status}: {data.object.amount} cents from {data.object.receipt_email}" \
|
|
137
|
-
--deliver telegram \
|
|
138
|
-
--deliver-chat-id "-100123456789"
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
### CI/CD: build notifications
|
|
142
|
-
```bash
|
|
143
|
-
hermes webhook subscribe ci-builds \
|
|
144
|
-
--events "pipeline" \
|
|
145
|
-
--prompt "Build {object_attributes.status} on {project.name} branch {object_attributes.ref}\nCommit: {commit.message}" \
|
|
146
|
-
--deliver discord \
|
|
147
|
-
--deliver-chat-id "1234567890"
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
### Generic monitoring alert
|
|
151
|
-
```bash
|
|
152
|
-
hermes webhook subscribe alerts \
|
|
153
|
-
--prompt "Alert: {alert.name}\nSeverity: {alert.severity}\nMessage: {alert.message}\n\nPlease investigate and suggest remediation." \
|
|
154
|
-
--deliver origin
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
## Security
|
|
158
|
-
|
|
159
|
-
- Each subscription gets an auto-generated HMAC-SHA256 secret (or provide your own with `--secret`)
|
|
160
|
-
- The webhook adapter validates signatures on every incoming POST
|
|
161
|
-
- Static routes from config.yaml cannot be overwritten by dynamic subscriptions
|
|
162
|
-
- Subscriptions persist to `~/.hermes/webhook_subscriptions.json`
|
|
163
|
-
|
|
164
|
-
## How It Works
|
|
165
|
-
|
|
166
|
-
1. `hermes webhook subscribe` writes to `~/.hermes/webhook_subscriptions.json`
|
|
167
|
-
2. The webhook adapter hot-reloads this file on each incoming request (mtime-gated, negligible overhead)
|
|
168
|
-
3. When a POST arrives matching a route, the adapter formats the prompt and triggers an agent run
|
|
169
|
-
4. The agent's response is delivered to the configured target (Telegram, Discord, GitHub comment, etc.)
|
|
170
|
-
|
|
171
|
-
## Troubleshooting
|
|
172
|
-
|
|
173
|
-
If webhooks aren't working:
|
|
174
|
-
|
|
175
|
-
1. **Is the gateway running?** Check with `systemctl --user status hermes-gateway` or `ps aux | grep gateway`
|
|
176
|
-
2. **Is the webhook server listening?** `curl http://localhost:8644/health` should return `{"status": "ok"}`
|
|
177
|
-
3. **Check gateway logs:** `grep webhook ~/.hermes/logs/gateway.log | tail -20`
|
|
178
|
-
4. **Signature mismatch?** Verify the secret in your service matches the one from `hermes webhook list`. GitHub sends `X-Hub-Signature-256`, GitLab sends `X-Gitlab-Token`.
|
|
179
|
-
5. **Firewall/NAT?** The webhook URL must be reachable from the service. For local development, use a tunnel (ngrok, cloudflared).
|
|
180
|
-
6. **Wrong event type?** Check `--events` filter matches what the service sends. Use `hermes webhook test <name>` to verify the route works.
|