diff --git a/.claude/.mcp.json b/.claude/.mcp.json new file mode 100644 index 0000000..0e61620 --- /dev/null +++ b/.claude/.mcp.json @@ -0,0 +1,16 @@ +{ + "mcpServers": { + "ols-mcp": { + "type": "stdio", + "command": "uvx", + "args": [ + "ols-mcp" + ], + "env": {} + }, + "pubmed": { + "type": "http", + "url": "https://pubmed.mcp.claude.com/mcp" + } + } +} diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..29f0ffc --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,14 @@ +{ + "permissions": { + "allow": [ + "Bash(*)", + "Edit", + "MultiEdit", + "NotebookEdit", + "FileEdit", + "WebFetch", + "WebSearch", + "Write" + ] + } +} diff --git a/.github/actions/claude-code-action/action.yml b/.github/actions/claude-code-action/action.yml index bb08c05..7616989 100644 --- a/.github/actions/claude-code-action/action.yml +++ b/.github/actions/claude-code-action/action.yml @@ -7,10 +7,13 @@ inputs: required: true anthropic_api_key: description: "Anthropic API key" - required: true + required: false cborg_api_key: description: "CBORG API key" - required: true + required: false + claude_code_oauth_token: + description: "Claude Code OAuth token" + required: false prompt: description: "The prompt to send to Claude Code" required: false @@ -90,6 +93,7 @@ runs: shell: bash id: prepare_prompt run: | + # Check if either prompt or prompt_file is provided if [ -z "${{ inputs.prompt }}" ] && [ -z "${{ inputs.prompt_file }}" ]; then echo "::error::Neither 'prompt' nor 'prompt_file' was provided. At least one is required." @@ -125,6 +129,14 @@ runs: shell: bash id: run_claude run: | + + if [ ! -z "${{ inputs.claude_code_oauth_token }}" ]; then + echo CLAUDE AUTH TOKEN IS NOT SET + else + echo CLAUDE AUTH TOKEN IS SET + export ANTHROPIC_API_KEY= + fi + ALLOWED_TOOLS_ARG="" if [ ! -z "${{ inputs.allowed_tools }}" ]; then ALLOWED_TOOLS_ARG="--allowedTools ${{ inputs.allowed_tools }}" @@ -135,7 +147,7 @@ runs: if [ -z "${{ inputs.output_file }}" ]; then # Run Claude Code and output to console - timeout $timeout_seconds claude \ + claude \ -p \ --verbose \ --output-format stream-json \ @@ -143,7 +155,7 @@ runs: ${{ inputs.allowed_tools != '' && format('--allowedTools "{0}"', inputs.allowed_tools) || '' }} else # Run Claude Code and tee output to console and file - timeout $timeout_seconds claude \ + claude \ -p \ --verbose \ --output-format stream-json \ @@ -160,8 +172,9 @@ runs: fi env: - ANTHROPIC_API_KEY: "." - ANTHROPIC_AUTH_TOKEN: ${{ inputs.cborg_api_key }} + ANTHROPIC_API_KEY: ${{ inputs.anthropic_api_key }} + # ANTHROPIC_AUTH_TOKEN: ${{ inputs.cborg_api_key }} + CLAUDE_CODE_OAUTH_TOKEN: ${{ inputs.claude_code_oauth_token }} GITHUB_TOKEN: ${{ inputs.github_token }} - ANTHROPIC_BASE_URL: "https://api.cborg.lbl.gov" - DISABLE_NON_ESSENTIAL_MODEL_CALLS: "1" + # ANTHROPIC_BASE_URL: "https://api.cborg.lbl.gov" + # DISABLE_NON_ESSENTIAL_MODEL_CALLS: "1" diff --git a/.github/actions/claude-issue-summarize-action/action.yml b/.github/actions/claude-issue-summarize-action/action.yml index b497d17..896af91 100644 --- a/.github/actions/claude-issue-summarize-action/action.yml +++ b/.github/actions/claude-issue-summarize-action/action.yml @@ -8,10 +8,13 @@ inputs: default: "5" anthropic_api_key: description: "Anthropic API key" - required: true + required: false cborg_api_key: description: "CBORG API key" - required: true + required: false + claude_code_oauth_token: + description: "Claude Code OAuth token" + required: false github_token: description: "GitHub token with repo and issues permissions" required: true @@ -22,7 +25,7 @@ runs: - name: Checkout repository code uses: actions/checkout@v4 with: - fetch-depth: 0 + ref: ${{ github.ref }} - name: Create prompt file shell: bash @@ -70,5 +73,6 @@ runs: install_artl_mcp: "true" timeout_minutes: ${{ inputs.timeout_minutes }} anthropic_api_key: ${{ inputs.anthropic_api_key }} + claude_code_oauth_token: ${{ inputs.claude_code_oauth_token }} cborg_api_key: ${{ inputs.cborg_api_key }} github_token: ${{ inputs.github_token }} diff --git a/.github/actions/claude-issue-triage-action/action.yml b/.github/actions/claude-issue-triage-action/action.yml index 22fcd82..caaad89 100644 --- a/.github/actions/claude-issue-triage-action/action.yml +++ b/.github/actions/claude-issue-triage-action/action.yml @@ -8,7 +8,10 @@ inputs: default: "5" anthropic_api_key: description: "Anthropic API key" - required: true + required: false + claude_code_oauth_token: + description: "Claude Code OAuth token" + required: false cborg_api_key: description: "CBORG API key" required: true @@ -22,7 +25,7 @@ runs: - name: Checkout repository code uses: actions/checkout@v4 with: - fetch-depth: 0 + ref: ${{ github.ref }} - name: Create prompt file shell: bash @@ -87,5 +90,6 @@ runs: install_github_mcp: "true" timeout_minutes: ${{ inputs.timeout_minutes }} anthropic_api_key: ${{ inputs.anthropic_api_key }} + claude_code_oauth_token: ${{ inputs.claude_code_oauth_token }} cborg_api_key: ${{ inputs.cborg_api_key }} github_token: ${{ inputs.github_token }} diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..232902c --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,22 @@ +# CLAUDE.md for + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +WARNING: read this closely as it gets a bit meta. + +This is a repo for a copier project intended to allow people to set up their github repo with AI github actions. + +- template files are in `template/` +- all other files are for this repo itself + +So for example + +- template/.github/workflows/claude.yml - A template that is copied into a users target repo to set up claude gh actions +- .github/workflows/claude.yml - The actual github actions for this repo itself. + +This repo eats its own dogfood! We will occasionally run + +`copier copy template .` + + + diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml new file mode 100644 index 0000000..5bf8ce5 --- /dev/null +++ b/.github/workflows/claude-code-review.yml @@ -0,0 +1,78 @@ +name: Claude Code Review + +on: + pull_request: + types: [opened, synchronize] + # Optional: Only run on specific file changes + # paths: + # - "src/**/*.ts" + # - "src/**/*.tsx" + # - "src/**/*.js" + # - "src/**/*.jsx" + +jobs: + claude-review: + # Optional: Filter by PR author + # if: | + # github.event.pull_request.user.login == 'external-contributor' || + # github.event.pull_request.user.login == 'new-developer' || + # github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR' + + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: read + issues: read + id-token: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Run Claude Code Review + id: claude-review + uses: anthropics/claude-code-action@beta + with: + claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + + # Optional: Specify model (defaults to Claude Sonnet 4, uncomment for Claude Opus 4) + # model: "claude-opus-4-20250514" + + # Direct prompt for automated review (no @claude mention needed) + direct_prompt: | + Please review this pull request and provide feedback on: + - Code quality and best practices + - Potential bugs or issues + - Performance considerations + - Security concerns + - Test coverage + + Be constructive and helpful in your feedback. + + # Optional: Use sticky comments to make Claude reuse the same comment on subsequent pushes to the same PR + # use_sticky_comment: true + + # Optional: Customize review based on file types + # direct_prompt: | + # Review this PR focusing on: + # - For TypeScript files: Type safety and proper interface usage + # - For API endpoints: Security, input validation, and error handling + # - For React components: Performance, accessibility, and best practices + # - For tests: Coverage, edge cases, and test quality + + # Optional: Different prompts for different authors + # direct_prompt: | + # ${{ github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR' && + # 'Welcome! Please review this PR from a first-time contributor. Be encouraging and provide detailed explanations for any suggestions.' || + # 'Please provide a thorough code review focusing on our coding standards and best practices.' }} + + # Optional: Add specific tools for running tests or linting + # allowed_tools: "Bash(npm run test),Bash(npm run lint),Bash(npm run typecheck)" + + # Optional: Skip review for certain conditions + # if: | + # !contains(github.event.pull_request.title, '[skip-review]') && + # !contains(github.event.pull_request.title, '[WIP]') + diff --git a/.github/workflows/claude-issue-summarize.yml b/.github/workflows/claude-issue-summarize.yml new file mode 100644 index 0000000..710195f --- /dev/null +++ b/.github/workflows/claude-issue-summarize.yml @@ -0,0 +1,27 @@ +name: Claude Issue summarize +description: "Automatically summarize GitHub issues using Claude Code" + +on: + issues: + types: [opened] + +jobs: + summarize-issue: + runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + contents: read + issues: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} + + - name: Run Claude Issue summarize + uses: ./.github/actions/claude-issue-summarize-action + with: + anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} + claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + cborg_api_key: ${{ secrets.CBORG_API_KEY }} + github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/claude-issue-triage.yml b/.github/workflows/claude-issue-triage.yml new file mode 100644 index 0000000..ddec43e --- /dev/null +++ b/.github/workflows/claude-issue-triage.yml @@ -0,0 +1,27 @@ +name: Claude Issue Triage +description: "Automatically triage GitHub issues using Claude Code" + +on: + issues: + types: [opened] + +jobs: + triage-issue: + runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + contents: read + issues: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} + + - name: Run Claude Issue Triage + uses: ./.github/actions/claude-issue-triage-action + with: + anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} + claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + cborg_api_key: ${{ secrets.CBORG_API_KEY }} + github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/claude-ontology-review.yml b/.github/workflows/claude-ontology-review.yml new file mode 100644 index 0000000..1f847b0 --- /dev/null +++ b/.github/workflows/claude-ontology-review.yml @@ -0,0 +1,115 @@ +# This action invokes claude to review a PR. +# This is a generic action - you can customize, or delete in favor of the ontology review PR. +# -- +# This github action is from the copier template in https://github.com/ai4curation/github-ai-integrations, donated by the Monarch Initiative +# For more documentation, see https://ai4curation.github.io/aidocs/how-tos/set-up-github-actions/ +# Author: Chris Mungall (@cmungall) +name: Claude Code Ontology Review + +on: + pull_request: + types: [opened, synchronize] + paths: + - "src/ontology" + +jobs: + claude-review: + # Optional: Filter by PR author + # if: | + # github.event.pull_request.user.login == 'external-contributor' || + # github.event.pull_request.user.login == 'new-developer' || + # github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR' + + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: read + issues: read + id-token: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Run Claude Code Ontology Review + id: claude-review + uses: anthropics/claude-code-action@beta + with: + claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + + # Optional: Specify model (commenting defaults to Claude Sonnet 4) + model: "claude-opus-4-1-20250805" + + # Direct prompt for automated review (no @claude mention needed) + direct_prompt: | + REPO: ${{ github.repository }} + PR NUMBER: ${{ github.event.pull_request.number }} + + This PR modifies critical ontology files. + + Review this PR against our team checklist: + + ## Issue alignment + - [ ] The PR aligns with the source issue, and only closes it if all components of the issue addressed + - [ ] The PR summary gives sufficient context for any decisions made, attributing them to issue authors where appropriate + + ## Ontology Metadata + - [ ] PR is linked to source issue(s) via appropriate annotation property + - [ ] any added definitions have provenance + + ## Identifiers and hallucinations + - [ ] all identifiers are CURIEs (or URLs), with standard prefixes + - [ ] I have looked up term identifiers and confirm that they denote what is intended + - [ ] all PMIDs and publication references resolve to the appropriate article/title + + ## Design patterns (DPs) + - [ ] any new terms conform to documented DPs for this ontology + - [ ] if the term fits into a DP, then the label is constructed in a standard way (although scientific norms prevail) + - [ ] if the term is compositional in nature, then it should conform to a DP, and have a relevant logical definition + + ## Definitions (if the PR adds or updates a definition) + - [ ] Definitions are present for any new term + - [ ] Definitions conform to the style guide for this ontology + - [ ] Definitions follows genus-differentia form (while prioritizing normal scientific phrasing over awkward ontology language) + - [ ] The genus of the definition is an ancestor of the term + - [ ] The differentia of the definition are necessary and sufficient for distinguishing from the genus + - [ ] The definition has appropriate provenance + - [ ] I have looked up the provenance, and it is correct and relevant + - [ ] The label, definition, and logical definition (when present) are largely consistent + + ## Relationships and logical axioms + - [ ] If a logical definition is not present, then there should be at least one is_a (subClassOf) to the most precise parent term + - [ ] If a logical definition is present, then there is reasonable expectation the term should classify precisely + - [ ] Other relationships are present to a reasonable degree and as dictated by the general ontology stye (e.g part-ofs for anatomy) + - [ ] Additional logical axioms (such as disjointness) are added as appropriate, depending on ontology style, and design patterns + - [ ] Additional logical axioms make sense and do not over-constrain + + Be constructive and helpful in your feedback. + + # Optional: Use sticky comments to make Claude reuse the same comment on subsequent pushes to the same PR + use_sticky_comment: true + + # Optional: Customize review based on file types + # direct_prompt: | + # Review this PR focusing on: + # - For TypeScript files: Type safety and proper interface usage + # - For API endpoints: Security, input validation, and error handling + # - For React components: Performance, accessibility, and best practices + # - For tests: Coverage, edge cases, and test quality + + # Optional: Different prompts for different authors + # direct_prompt: | + # ${{ github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR' && + # 'Welcome! Please review this PR from a first-time contributor. Be encouraging and provide detailed explanations for any suggestions.' || + # 'Please provide a thorough code review focusing on our coding standards and best practices.' }} + + # Optional: Add specific tools for running tests or linting + # allowed_tools: "Bash(npm run test),Bash(npm run lint),Bash(npm run typecheck)" + + # Optional: Skip review for certain conditions + # if: | + # !contains(github.event.pull_request.title, '[skip-review]') && + # !contains(github.event.pull_request.title, '[WIP]') + diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml new file mode 100644 index 0000000..e1d4a43 --- /dev/null +++ b/.github/workflows/claude.yml @@ -0,0 +1,90 @@ +name: Claude Code + +on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + issues: + types: [opened, assigned] + pull_request_review: + types: [submitted] + +jobs: + claude: + if: | + (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) || + (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) || + (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) || + (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude'))) + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + issues: write + id-token: write + actions: read # Required for Claude to read CI results on PRs + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Install uv + uses: astral-sh/setup-uv@v5 + + - name: Install python tools + run: | + uv sync + + - name: Run Claude Code + id: claude + uses: anthropics/claude-code-action@beta + + with: + claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + mcp_config: | + { + "mcpServers": { + "ols": { + "command": "uvx", + "args": [ + "ols-mcp" + ] + }, + "sequential-thinking": { + "command": "npx", + "args": [ + "-y", + "@modelcontextprotocol/server-sequential-thinking" + ] + } + } + } + + # This is an optional setting that allows Claude to read CI results on PRs + additional_permissions: | + actions: read + + # Optional: Specify model (defaults to Claude Sonnet 4, uncomment for Claude Opus 4.1) + # model: "claude-opus-4-1-20250805" + + # Optional: Customize the trigger phrase (default: @claude) + # trigger_phrase: "/claude" + + # Optional: Trigger when specific user is assigned to an issue + # assignee_trigger: "claude-bot" + + # Optional: Allow Claude to run specific commands + allowed_tools: "Bash(*),FileEdit,Edit,MultiEdit,WebSearch,WebFetch,mcp__ols_mcp__search_all_ontologies,mcp__ols_mcp__get_terms_from_ontology" + + # Optional: Add custom instructions for Claude to customize its behavior for your project + # custom_instructions: | + # Follow our coding standards + # Ensure all new code has tests + # Use TypeScript for new files + + # Optional: Custom environment variables for Claude + # claude_env: | + # NODE_ENV: test + diff --git a/.github/workflows/dragon-ai.yml b/.github/workflows/dragon-ai.yml new file mode 100644 index 0000000..584bb43 --- /dev/null +++ b/.github/workflows/dragon-ai.yml @@ -0,0 +1,190 @@ +name: Dragon AI Agent GitHub Mentions + +env: + ROBOT_VERSION: v1.9.7 + TOOLS_DIR: ${{ github.workspace }}/tools + +on: + issues: + types: [opened, edited] + issue_comment: + types: [created, edited] + pull_request: + types: [opened, edited] + pull_request_review_comment: + types: [created, edited] + +jobs: + check-mention: + runs-on: ubuntu-latest + outputs: + result: ${{ steps.check.outputs.result }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + # this seems to be necessary to ensure actions uses the latest; see + # https://github.com/actions/checkout/issues/439 + with: + ref: ${{ github.ref }} + + - name: Check for qualifying mention + id: check + uses: actions/github-script@v6 + with: + github-token: ${{ secrets.PAT_FOR_PR }} # Use PAT instead of default token + script: | + // Load allowed users from config + const fs = require('fs'); + let allowedUsers = []; + try { + const configContent = fs.readFileSync('.github/ai-controllers.json', 'utf8'); + allowedUsers = JSON.parse(configContent); + } catch (error) { + console.log('Error loading allowed users:', error); + allowedUsers = ['cmungall']; // Fallback + } + + // Get content and user from event payload directly to avoid API calls when possible + let content = ''; + let userLogin = ''; + let itemType = ''; + let itemNumber = 0; + + if (context.eventName === 'issues') { + content = context.payload.issue.body || ''; + userLogin = context.payload.issue.user.login; + itemType = 'issue'; + itemNumber = context.payload.issue.number; + } else if (context.eventName === 'pull_request') { + content = context.payload.pull_request.body || ''; + userLogin = context.payload.pull_request.user.login; + itemType = 'pull_request'; + itemNumber = context.payload.pull_request.number; + } else if (context.eventName === 'issue_comment') { + content = context.payload.comment.body || ''; + userLogin = context.payload.comment.user.login; + itemType = 'issue'; + itemNumber = context.payload.issue.number; + } else if (context.eventName === 'pull_request_review_comment') { + content = context.payload.comment.body || ''; + userLogin = context.payload.comment.user.login; + itemType = 'pull_request'; + itemNumber = context.payload.pull_request.number; + } + + // Check if user is allowed and mention exists + const isAllowed = allowedUsers.includes(userLogin); + const mentionRegex = /@dragon-ai-agent\s+please\s+(.*)/i; + const mentionMatch = content.match(mentionRegex); + + const qualifiedMention = isAllowed && mentionMatch !== null; + const prompt = qualifiedMention ? mentionMatch[1].trim() : ''; + + console.log(`User: ${userLogin}, Allowed: ${isAllowed}, Has mention: ${mentionMatch !== null}`); + + return { + qualifiedMention, + itemType, + itemNumber, + prompt, + user: userLogin, + controllers: allowedUsers.map(u => '@' + u).join(', ') + }; + + respond-to-mention: + needs: check-mention + if: fromJSON(needs.check-mention.outputs.result).qualifiedMention == true + permissions: + contents: write + pull-requests: write + issues: write + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} + token: ${{ secrets.PAT_FOR_PR }} # Use PAT for checkout to allow committing later + + - name: Configure Git + run: | + git config --global user.name "Dragon-AI Agent" + git config --global user.email "dragon-ai-agent[bot]@users.noreply.github.com" + + - name: Create tools directory + run: mkdir -p ${{ env.TOOLS_DIR }} + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: '18' + + - name: install claude + run: | + npm install -g @anthropic-ai/claude-code + + + - name: Add tools to PATH + run: | + echo "${{ env.TOOLS_DIR }}" >> $GITHUB_PATH + ls -alt ${{ github.workspace }} + ls -alt ${{ env.TOOLS_DIR }} + + - name: Install uv + uses: astral-sh/setup-uv@v5 + + - name: Install python tools + run: | + uv venv + source .venv/bin/activate + + - name: Set up environment + run: | + # Safely write prompt to file + mkdir -p /tmp/claude-input + echo "${{ fromJSON(needs.check-mention.outputs.result).prompt }}" > /tmp/claude-input/prompt.txt + + - name: Create structured Claude prompt + env: + CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + GH_TOKEN: ${{ secrets.PAT_FOR_PR }} + run: | + cat > /tmp/claude-input/claude_prompt.txt << EOL + You are @dragon-ai-agent. + You're responding to a request from or relayed by @${{ fromJSON(needs.check-mention.outputs.result).user }} on GitHub ${{ fromJSON(needs.check-mention.outputs.result).itemType }} #${{ fromJSON(needs.check-mention.outputs.result).itemNumber }}. + You only respond to requests from the following authorized controllers: ${{ fromJSON(needs.check-mention.outputs.result).controllers }}. + + You should use \`gh\` to communicate with the user via the GitHub issue/ticket. + If instructed to modify files, you should make changes on a branch and submit a PR, communicating clearly and in + detail on the PR. + + Always end by informing the user what you did (or were not able to do) with a message, either on an issue or a PR, + as appropriate. + + The request is below, enclosed in triple backticks: + \`\`\` + $(cat /tmp/claude-input/prompt.txt) + \`\`\` + + However, you should use `gh` to read the complete context of the request, and look at any linked issues or PRs + that provide additional context. + + EOL + + + - name: Run Claude Code in headless mode + id: claude-response + env: + CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + + export PATH="${{ env.TOOLS_DIR }}:$PATH" + + # Run Claude with proper permissions + claude -p "$(cat /tmp/claude-input/claude_prompt.txt)" \ + --permission-mode bypassPermissions \ + --output-format stream-json \ + --verbose + diff --git a/ai.just b/ai.just new file mode 100644 index 0000000..c675bda --- /dev/null +++ b/ai.just @@ -0,0 +1,49 @@ +claude: + [ -f CLAUDE.md ] || ln -s AGENTS.md CLAUDE.md + +goosehints: + [ -f .goosehints ] || ln -s AGENTS.md .goosehints + +copilot-instructions: + [ -f .github/copilot-instructions.md ] || cd .github && ln -s ../AGENTS.md copilot-instructions.md + +setup-ai: setup-ai-instructions setup-gh + +setup-ai-instructions: claude goosehints copilot-instructions + +setup-gh: gh-add-topics gh-add-secrets + +gh-add-topics: + gh repo edit --add-topic "monarchinitiative,ai4curation" + +gh-add-secrets: + #!/usr/bin/env bash + set -euo pipefail + + # Function to set secret if env var exists + set_secret_if_exists() { + local secret_name="$1" + local gh_var="GH_$secret_name" + local plain_var="$secret_name" + + if [ -n "${!gh_var:-}" ]; then + echo "Setting $secret_name from $gh_var" + gh secret set "$secret_name" --body "${!gh_var}" + elif [ -n "${!plain_var:-}" ]; then + echo "Setting $secret_name from $plain_var" + gh secret set "$secret_name" --body "${!plain_var}" + else + echo "Skipping $secret_name (neither $gh_var nor $plain_var is set)" + fi + } + + # Set each secret if the corresponding env var exists + set_secret_if_exists "PAT_FOR_PR" + set_secret_if_exists "ANTHROPIC_API_KEY" + set_secret_if_exists "OPENAI_API_KEY" + set_secret_if_exists "CBORG_API_KEY" + set_secret_if_exists "CLAUDE_CODE_OAUTH_TOKEN" + +gh-invite-dragon-ai: + gh api repos/:owner/:repo/collaborators/dragon-ai-agent --method PUT --field permission=write > /dev/null +