mirror of
https://github.com/NeuralNomadsAI/CodeNomad.git
synced 2026-08-26 08:42:02 +00:00
Add the CodeNomadBot GitHub App integration on top of the current dev branch. The server now validates GitHub webhooks, applies explicit policy rules, prepares managed issue/PR worktrees, launches OpenCode in GitHub mode, and exposes scoped GitHub operations through the plugin route. Wire the OpenCode plugin to expose a GitHub-only tool and command templates when CODENOMAD_MODE=github. Add GitHub App authentication, installation-token git helpers, bot signature handling, payload sanitization, latest-comment-wins job cancellation, and documentation for setup and operations. Also harden managed worktree creation by reusing valid existing worktrees, pruning stale registrations, and replacing orphaned directories. Add migrated webhook helper tests and worktree recovery coverage. Validation: npm run typecheck --workspace @neuralnomads/codenomad; npm run build --workspace @codenomad/codenomad-opencode-plugin; npx tsx --test packages/server/src/integrations/github/__tests__/*.test.ts packages/server/src/workspaces/__tests__/git-worktrees.test.ts
97 lines
4.2 KiB
TypeScript
97 lines
4.2 KiB
TypeScript
export type LoadedCommand = {
|
|
template: string
|
|
description?: string
|
|
agent?: string
|
|
model?: string
|
|
subtask?: boolean
|
|
}
|
|
|
|
export function loadGithubModeCommands(): Record<string, LoadedCommand> {
|
|
return GITHUB_COMMANDS
|
|
}
|
|
|
|
const HARD_RULES = [
|
|
"Hard rules",
|
|
"- Use the `github` tool for all GitHub operations.",
|
|
"- Do NOT use the `gh` CLI. It will not be authenticated.",
|
|
"- Do not ask interactive questions. If you need clarification, ask by posting a GitHub comment using the `github` tool.",
|
|
"- CodeNomad may hard-reset this git worktree between webhook runs. Commit changes before calling `github(op=publish_pr, ...)`.",
|
|
].join("\n")
|
|
|
|
const PAYLOAD = ["Payload (JSON arguments)", "", "```json", "$ARGUMENTS", "```"].join("\n")
|
|
|
|
const GITHUB_COMMANDS: Record<string, LoadedCommand> = {
|
|
"codenomad-github-default": {
|
|
description: "CodeNomad GitHub default",
|
|
template: [
|
|
"You are a GitHub App bot running inside CodeNomad in headless mode.",
|
|
HARD_RULES,
|
|
"Workflow",
|
|
"1) Read the relevant issue/PR thread context with `github(op=list_issue_comments, ...)`.",
|
|
"2) If review comments are relevant, read them with `github(op=list_pr_review_comments, ...)`.",
|
|
"3) Perform the requested work with tight scope.",
|
|
"4) Post one final result comment with `github(op=post_issue_comment, ...)`.",
|
|
"If `reusedSession=true`, refresh comments efficiently with `since` when you know the latest `updated_at` previously seen.",
|
|
PAYLOAD,
|
|
].join("\n\n"),
|
|
},
|
|
"codenomad-github-issue-comment": {
|
|
description: "CodeNomad GitHub issue/PR comment",
|
|
template: [
|
|
"You are a GitHub App bot running inside CodeNomad responding to an issue or pull request comment webhook.",
|
|
HARD_RULES,
|
|
"Scope discipline",
|
|
"- Avoid drive-by refactors.",
|
|
"- Avoid changing unrelated files.",
|
|
"- If your confidence in the request interpretation is below 90%, post a clarifying GitHub comment and stop.",
|
|
"Workflow",
|
|
"1) Read context: `github(op=list_issue_comments, issueNumber=<webhook.issue.number>)`.",
|
|
"2) Restate what you understood and any assumptions.",
|
|
"3) Perform the requested work.",
|
|
"4) Post a single final result comment.",
|
|
PAYLOAD,
|
|
].join("\n\n"),
|
|
},
|
|
"codenomad-github-issue-opened": {
|
|
description: "CodeNomad GitHub issue opened",
|
|
template: [
|
|
"You are a GitHub App bot running inside CodeNomad responding to an issue opened webhook.",
|
|
HARD_RULES,
|
|
"Workflow",
|
|
"1) Read the issue thread with `github(op=list_issue_comments, issueNumber=<issue number>)`.",
|
|
"2) Use the webhook title/body to understand the request.",
|
|
"3) Perform appropriate automation.",
|
|
"4) Post a single issue comment with the outcome.",
|
|
PAYLOAD,
|
|
].join("\n\n"),
|
|
},
|
|
"codenomad-github-pr-opened": {
|
|
description: "CodeNomad GitHub PR opened",
|
|
template: [
|
|
"You are a GitHub App bot running inside CodeNomad responding to a pull request opened webhook.",
|
|
HARD_RULES,
|
|
"Goal: perform a thorough, read-only code review unless explicitly asked to change code.",
|
|
"Workflow",
|
|
"1) Determine the PR number from the payload.",
|
|
"2) Load PR conversation comments with `github(op=list_issue_comments, issueNumber=<PR number>)`.",
|
|
"3) Inspect local git status, recent commits, and the diff against the PR base when available.",
|
|
"4) Review correctness, maintainability, security, performance, tests, and scope.",
|
|
"5) Post a single PR comment with findings and suggestions.",
|
|
PAYLOAD,
|
|
].join("\n\n"),
|
|
},
|
|
"codenomad-github-review-comment": {
|
|
description: "CodeNomad GitHub PR review comment",
|
|
template: [
|
|
"You are a GitHub App bot running inside CodeNomad responding to a pull request review comment webhook.",
|
|
HARD_RULES,
|
|
"Default to read-only unless the review comment explicitly asks you to make changes.",
|
|
"Workflow",
|
|
"1) Determine the PR number from the payload.",
|
|
"2) Load PR issue comments and review comments.",
|
|
"3) Inspect the local worktree and focus on the exact review thread concern.",
|
|
"4) Post a single PR comment with a concrete response.",
|
|
PAYLOAD,
|
|
].join("\n\n"),
|
|
},
|
|
}
|