name: Issue Agent on: issues: types: [opened, edited, reopened, labeled] permissions: issues: write jobs: analyze-issue: runs-on: ubuntu-latest steps: - name: Analyze issue and post comment uses: actions/github-script@v7 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | const issueNumber = context.issue.number; const issueTitle = context.payload.issue.title; const issueBody = context.payload.issue.body || '(no description provided)'; const issueUser = context.payload.issue.user.login; const labels = (context.payload.issue.labels || []).map(l => l.name).join(', ') || 'none'; // Call GitHub Models API for AI-powered analysis const response = await fetch('https://models.inference.ai.azure.com/chat/completions', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${process.env.GITHUB_TOKEN}` }, body: JSON.stringify({ model: 'gpt-4o-mini', messages: [ { role: 'system', content: `You are a rigorous technical agent reviewing GitHub issues for the "simulation-theory" repository — a research project on simulation theory, mathematics, quantum mechanics, and philosophy. Your job is to carefully read each issue and provide a thorough, structured analysis. For each issue produce: 1. **Summary** — a concise one-paragraph summary of what the issue is about. 2. **Key Points** — bullet list of the most important observations or questions raised. 3. **Relevance to Simulation Theory** — how this issue connects to the project's themes. 4. **Suggested Actions** — concrete next steps or questions for the author. Be rigorous, thoughtful, and constructive. Keep the tone academic and helpful.` }, { role: 'user', content: `Please analyze this GitHub issue:\n\n**Title:** ${issueTitle}\n**Author:** ${issueUser}\n**Labels:** ${labels}\n\n**Description:**\n${issueBody}` } ], max_tokens: 1500, temperature: 0.4 }) }); let analysisText; if (response.ok) { let data; try { data = await response.json(); } catch (error) { console.log('Failed to parse JSON from GitHub Models API response:', error); } if (data && data.choices && data.choices.length > 0 && data.choices[0].message) { analysisText = data.choices[0].message.content; } else if (data) { console.log('Unexpected response structure from GitHub Models API:', JSON.stringify(data)); } } else { console.log(`GitHub Models API returned ${response.status}: ${await response.text()}`); } // Fallback: structured analysis without AI if (!analysisText) { analysisText = `**Summary**\nIssue #${issueNumber} titled *"${issueTitle}"* was submitted by @${issueUser}. ${issueBody.length > 0 ? 'It contains a description that may include images or text.' : 'No description was provided.'}\n\n**Labels:** ${labels}\n\n**Suggested Actions**\n- Review the content of this issue and add appropriate labels if missing.\n- Respond to the author with any clarifying questions.\n- Link related issues or pull requests if applicable.`; } const marker = '*This comment was generated automatically by the Issue Agent workflow.*'; const commentBody = `## 🤖 Agent Analysis\n\n${analysisText}\n\n---\n${marker}`; // Look for an existing Issue Agent comment and update it if found to avoid spamming const { data: existingComments } = await github.rest.issues.listComments({ owner: context.repo.owner, repo: context.repo.repo, issue_number: issueNumber, per_page: 100 }); const existingAgentComment = existingComments.find(c => c.user && c.user.type === 'Bot' && typeof c.body === 'string' && c.body.includes(marker) ); if (existingAgentComment) { await github.rest.issues.updateComment({ owner: context.repo.owner, repo: context.repo.repo, comment_id: existingAgentComment.id, body: commentBody }); } else { await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, issue_number: issueNumber, body: commentBody }); }