From 85dc2a9bf40c007ab0e9ead627c23acd788075fa Mon Sep 17 00:00:00 2001 From: Changyong Gong Date: Tue, 10 Mar 2026 16:43:58 +0800 Subject: [PATCH 1/5] docs: redesign issuelens agent --- .github/agents/issuelens.agent.md | 168 ++++++------------ .github/skills/label-issue/SKILL.md | 114 ++++++++++++ .../references/label_instructions_template.md | 56 ++++++ .../__pycache__/label_issue.cpython-312.pyc | Bin 0 -> 5580 bytes .../skills/label-issue/scripts/label_issue.py | 78 ++++++++ .github/skills/send-email/SKILL.md | 116 ++++++++++++ .../send-email/references/payload-schema.json | 34 ++++ .github/skills/send-notification/SKILL.md | 91 ++++++++++ .../references/payload-schema.json | 85 +++++++++ .../send-personal-notification/SKILL.md | 88 +++++++++ .../references/payload-schema.json | 25 +++ .github/workflows/issueLens-run.yml | 60 +++---- 12 files changed, 767 insertions(+), 148 deletions(-) create mode 100644 .github/skills/label-issue/SKILL.md create mode 100644 .github/skills/label-issue/references/label_instructions_template.md create mode 100644 .github/skills/label-issue/scripts/__pycache__/label_issue.cpython-312.pyc create mode 100644 .github/skills/label-issue/scripts/label_issue.py create mode 100644 .github/skills/send-email/SKILL.md create mode 100644 .github/skills/send-email/references/payload-schema.json create mode 100644 .github/skills/send-notification/SKILL.md create mode 100644 .github/skills/send-notification/references/payload-schema.json create mode 100644 .github/skills/send-personal-notification/SKILL.md create mode 100644 .github/skills/send-personal-notification/references/payload-schema.json diff --git a/.github/agents/issuelens.agent.md b/.github/agents/issuelens.agent.md index 34bae617..0eb460d2 100644 --- a/.github/agents/issuelens.agent.md +++ b/.github/agents/issuelens.agent.md @@ -1,127 +1,61 @@ --- name: IssueLens -description: An agent speciallized in Java Tooling (IDE, extensions, build tools, language servers) area, responsible for triaging GitHub issues. -# version: 2025-12-01a -tools: ['github/list_issues', 'github/issue_read', 'read', 'mcp-datetime/*'] -target: github-copilot +description: "An agent specialized in Java Tooling (IDE, extensions, build tools, language servers) area, responsible for commenting and labeling on GitHub issues. Use when: triaging issues, labeling issues, analyzing Java tooling bugs." +tools: ['github/*', 'execute', 'read', 'search', 'web', 'javatooling-search/*'] +mcp-servers: + javatooling-search: + type: http + url: ${{ secrets.JAVATOOLING_INDEX_URL }} --- -# Triage Agent +# IssueLens — Java Tooling Issue Triage Agent -You are an experienced developer specializing in Java tooling (IDEs, extensions, build tools, language servers). Your role is to triage GitHub issues and identify critical ones for the given Java tooling repo. +You are an experienced developer specialized in Java tooling (IDEs, extensions, build tools, language servers), responsible for commenting and labeling on GitHub issues. -## Goal -Identify and summarize critical issues updated today related to the given repo. +## Step 1: Comment on the Issue -## Critical Issue Criteria -- **Hot Issues** - - At least 2 similar issues reported by different users (same symptom or error pattern). - - At least 2 users reacted (👍) or commented on the issue. - - More than 3 non-bot comments (exclude comments from automation like "github-action"). -- **Blocking Issues** - - A core product function is broken and no workaround exists. -- **Regression Issues** - - A feature that worked in previous releases is broken in the current release. +### 1.1 Scope Check +Analyze whether the issue is related to Java tooling. If it is not, post a brief comment explaining your scope and stop. -## Steps -1. Invoke `mcp-datetime`to get the current date. -2. Invoke `github/list_issues` to retrieve issues opened today. Remember the total number of issues retrieved. -3. For each issue: - - Check if it relates to Java tooling. If not, discard it. - - Use `github/issue_read` to get more details if needed. -4. Apply the critical issue criteria to filter the list. Remember the number of critical issues identified. -5. Generate a concise, structured response in JSON format. - - The JSON schema for the summary is as follows: -```json -{ - "type": "object", - "properties": { - "title": { - "type": "string" - }, - "repoId": { - "type": "string" - }, - "timeFrame": { - "type": "string" - }, - "totalIssues": { - "type": "integer" - }, - "criticalIssues": { - "type": "integer" - }, - "criticalIssuesSummary": { - "type": "array", - "items": { - "type": "object", - "properties": { - "issueNumber": { - "type": "integer" - }, - "url": { - "type": "string" - }, - "title": { - "type": "string" - }, - "summary": { - "type": "string" - }, - "labels": { - "type": "string" - } - }, - "required": [ - "issueNumber", - "url", - "title", - "summary", - "labels" - ] - } - }, - "repoLink": { - "type": "string" - }, - "repoIssueLink": { - "type": "string" - } - } -} -``` - - An example response: -``` -{ - "title": "Weekly GitHub Issues Summary", - "repoId": "microsoft/vscode-java-pack", - "timeFrame": "December 4-11, 2025", - "totalIssues": 8, - "criticalIssues": 3, - "criticalIssuesSummary": [ - { - "issueNumber": 1234, - "url": "https://github.com/microsoft/vscode-java-pack/issues/1234", - "title": "Java debugger crashes on Windows with JDK 21", - "summary": "Users report debugger crashes when using JDK 21 on Windows. Investigating compatibility issues.", - "labels": "🔴 **High Priority** | 🏷️ bug, debugger" - }, - { - "issueNumber": 1256, - "url": "https://github.com/microsoft/vscode-java-pack/issues/1256", - "title": "Add support for Java 22 preview features", - "summary": "Request to add syntax highlighting and IntelliSense for Java 22 preview features.", - "labels": "🟡 **Medium Priority** | 🏷️ enhancement, java-22" - } - ], - "repoLink": "https://github.com/microsoft/vscode-java-pack", - "repoIssueLink": "https://github.com/microsoft/vscode-java-pack/issues" -} -``` - - Ensure the response is in valid JSON format. - - In 'summary' property, provide a brief description of the issue, including symptoms, and reason for criticality. - - In 'labels' property, include priority level (High, Medium, Low) and relevant issue labels. +### 1.2 Search for Relevant Issues +Use `javatooling-search/search_issues` to search for existing issues and documentation relevant to the user's issue. + +### 1.3 Analyze Results +Evaluate each search result for relevance to the user's issue. Drop results that are absolutely irrelevant. + +### 1.4 Compose the Comment +Follow these rules strictly: +- **DO NOT make up solutions.** Only provide a solution if you can find one from the search results or documentation. +- If a solution exists, provide it with reference links. +- If a similar issue exists but no solution can be derived from it, link to the issue with a brief description. +- Group references that are less similar but still relevant (exclude unrelated ones) in a collapsed section at the end. + +The comment should include, in order: +1. **Solution** — if one exists from the search results. +2. **Duplicate issues** — if any exist. +3. **Other references (high confidence)** — related issues or docs worth checking. +4. **Other references (low confidence)** — appended at the end of the comment body (not a new section), collapsed by default: + ``` +
+ Other references with low confidence + + - **Title**: description / solution if any — [link](url) + - ... +
+ ``` + +Post the comment on the issue using `github/add_issue_comment`. + +## Step 2: Label the Issue + +Use the `label-issue` skill to classify and apply labels to the issue. + +## Step 3: Send Triage Summary Email + +Use the `send-email` skill to send a triage summary email of the operations performed: +- Send to the email addresses specified in the `REPORT_RECIPIENTS` environment variable (comma-separated list). +- Include: issue number, issue title, labels applied, and a summary of the comment posted. ## Notes -- Always use available tools to complete the task. -- Output the JSON summary at the very end of your response. +- Use `gh` CLI as a fallback if you encounter issues with MCP tools. +- Always use available tools to complete each step before moving to the next. diff --git a/.github/skills/label-issue/SKILL.md b/.github/skills/label-issue/SKILL.md new file mode 100644 index 00000000..272340f1 --- /dev/null +++ b/.github/skills/label-issue/SKILL.md @@ -0,0 +1,114 @@ +--- +name: label-issue +description: Classify and label GitHub issues based on repository-specific labeling instructions. Use when (1) auto-labeling new issues, (2) classifying issue types (bug, feature, etc.), (3) adding priority or area labels, (4) applying consistent labeling rules. Triggers on requests like "label issue", "classify issue", "what labels should this issue have", "add labels to issue". +--- + +# Label Issue Skill + +Automatically classify and label GitHub issues based on repository-specific labeling instructions. + +## Overview + +This skill analyzes GitHub issue content (title, body, comments) and applies appropriate labels based on labeling rules defined in the target repository's `.github/llms.md` file. + +## Workflow + +1. **Input**: Receive issue URL or issue number with repository (owner/repo) +2. **Fetch labeling instructions**: Read `.github/llms.md` from the repository +3. **Fetch issue**: Get issue details (title, body, existing labels) +4. **Analyze issue**: Match issue content against labeling rules +5. **Determine labels**: Select appropriate labels based on: + - Keyword matching + - Issue type detection (bug, feature, question, etc.) + - Priority assessment + - Area/component identification +6. **Apply labels**: Use Python script to add labels via GitHub API +7. **Report**: Confirm labels applied with reasoning + +## Reading Labeling Instructions + +Fetch `.github/llms.md` from the target repository using GitHub MCP tools. The file should define: + +- **Available labels**: List of valid labels with descriptions +- **Labeling rules**: Criteria for when to apply each label +- **Keywords mapping**: Keywords that trigger specific labels + +For template format, see [references/label_instructions_template.md](references/label_instructions_template.md). + +If `.github/label-instructions.md` is not found: +1. Fetch the list of labels defined in the target repository using `github/list_labels` +2. Create a brief summary of available labels based on their names and descriptions +3. Use the summary to determine which labels best match the issue content + +## Issue Analysis + +Analyze issue content to determine appropriate labels by: + +1. **Type Detection**: Match issue keywords against label names/descriptions +2. **Priority Assessment**: Identify severity indicators in the issue +3. **Area Detection**: Match issue content against area-specific labels + +## Applying Labels + +Run the bundled Python script to add labels: + +```bash +# Install dependency +pip install requests + +# Add labels to an issue +python scripts/label_issue.py + +# Example: add bug and priority:high labels +python scripts/label_issue.py microsoft vscode 123 "bug,priority:high" + +# Example: add multiple area labels +python scripts/label_issue.py microsoft vscode 123 "bug,area:ui,area:api" +``` + +The script [scripts/label_issue.py](scripts/label_issue.py) handles the GitHub API call. + +## Example Commands + +- "Label issue #123 in microsoft/vscode" +- "What labels should this issue have? https://github.com/owner/repo/issues/456" +- "Classify and label issue #789" +- "Add appropriate labels to this bug report" + +## Output + +Report the labeling decision with: + +- **Labels applied**: List of labels added +- **Reasoning**: Why each label was chosen + - Type: "Detected as bug (keywords: 'not working', 'error')" + - Priority: "High priority (affects core functionality)" + - Area: "Matched 'ui' area (keywords: button, dialog)" +- **Existing labels**: Labels already on the issue (not modified) + +## Example Output + +``` +✅ Labels added to issue #123: bug, priority:high, area:ui + +**Reasoning:** +- **bug**: Issue describes broken functionality ("button not working") +- **priority:high**: Core feature affected, no workaround mentioned +- **area:ui**: UI-related keywords detected (button, click, display) + +**Existing labels:** needs-triage (unchanged) +``` + +## Configuration + +The skill requires: + +1. **GITHUB_ACCESS_TOKEN** or **GITHUB_PAT** environment variable with `repo` scope +2. **label-instructions.md** in target repository (optional but recommended) + +## Fallback Behavior + +If labeling instructions are not found: +1. Use default type detection rules +2. Skip priority and area labels +3. Report that default rules were used diff --git a/.github/skills/label-issue/references/label_instructions_template.md b/.github/skills/label-issue/references/label_instructions_template.md new file mode 100644 index 00000000..9ecd5873 --- /dev/null +++ b/.github/skills/label-issue/references/label_instructions_template.md @@ -0,0 +1,56 @@ +# Label Instructions Template + +This template shows the expected format for `.github/label-instructions.md` in target repositories. + +## Example Format + +```markdown +# Issue Labeling Instructions + +## Available Labels + +### Type Labels +- **bug**: Something isn't working correctly +- **feature**: New feature request +- **enhancement**: Improvement to existing functionality +- **documentation**: Documentation updates needed +- **question**: Questions about usage or behavior + +### Priority Labels +- **priority:critical**: Blocking issue, needs immediate attention +- **priority:high**: Important, should be addressed soon +- **priority:medium**: Normal priority +- **priority:low**: Nice to have, can wait + +### Area Labels +- **area:ui**: User interface related +- **area:api**: API or backend related +- **area:performance**: Performance issues +- **area:security**: Security concerns + +## Labeling Rules + +1. Every issue should have exactly one **type** label +2. Add **priority** labels based on user impact and urgency +3. Add relevant **area** labels based on affected components +4. Issues mentioning "crash", "error", or "broken" should be labeled `bug` +5. Issues starting with "Feature request" or "Please add" should be labeled `feature` +6. Security-related issues should always get `priority:critical` and `area:security` + +## Keywords to Label Mapping + +| Keywords | Labels | +|----------|--------| +| crash, error, broken, not working | bug | +| feature request, please add, would be nice | feature | +| slow, performance, timeout, lag | area:performance | +| security, vulnerability, CVE | area:security, priority:critical | +| documentation, docs, readme | documentation | +``` + +## Best Practices + +1. **Be specific**: Include concrete keywords and patterns +2. **Define priorities clearly**: Explain what qualifies for each priority level +3. **List all available labels**: Include descriptions for each label +4. **Provide examples**: Show sample issues and their expected labels diff --git a/.github/skills/label-issue/scripts/__pycache__/label_issue.cpython-312.pyc b/.github/skills/label-issue/scripts/__pycache__/label_issue.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4d03663f2c59aef2076f5e3b24e937ca065a80d2 GIT binary patch literal 5580 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 literal 0 HcmV?d00001 diff --git a/.github/skills/label-issue/scripts/label_issue.py b/.github/skills/label-issue/scripts/label_issue.py new file mode 100644 index 00000000..5b7fcc36 --- /dev/null +++ b/.github/skills/label-issue/scripts/label_issue.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python3 +""" +Add labels to GitHub issues. + +Usage: + python label_issue.py + +Environment Variables: + GITHUB_ACCESS_TOKEN or GITHUB_PAT: GitHub personal access token with repo scope +""" + +import os +import sys +import argparse +import requests + + +def get_github_token() -> str: + """Get GitHub token from environment variables.""" + token = os.environ.get("GITHUB_ACCESS_TOKEN") or os.environ.get("GITHUB_PAT") + if not token: + raise ValueError( + "GitHub token not found. Set GITHUB_ACCESS_TOKEN or GITHUB_PAT environment variable." + ) + return token + + +def add_labels( + owner: str, repo: str, issue_number: int, labels: list[str], token: str +) -> dict: + """Add labels to a GitHub issue.""" + url = f"https://api.github.com/repos/{owner}/{repo}/issues/{issue_number}/labels" + headers = { + "Authorization": f"Bearer {token}", + "Accept": "application/vnd.github+json", + "X-GitHub-Api-Version": "2022-11-28", + } + response = requests.post(url, headers=headers, json={"labels": labels}) + response.raise_for_status() + return response.json() + + +def main(): + parser = argparse.ArgumentParser( + description="Add labels to GitHub issues." + ) + parser.add_argument("owner", help="Repository owner (e.g., 'microsoft')") + parser.add_argument("repo", help="Repository name (e.g., 'vscode')") + parser.add_argument("issue_number", type=int, help="Issue number to label") + parser.add_argument( + "labels", help="Comma-separated list of labels (e.g., 'bug,priority:high')" + ) + + args = parser.parse_args() + labels = [label.strip() for label in args.labels.split(",") if label.strip()] + + if not labels: + print("❌ No labels provided.", file=sys.stderr) + sys.exit(1) + + try: + token = get_github_token() + result = add_labels(args.owner, args.repo, args.issue_number, labels, token) + applied_labels = [label["name"] for label in result] + print(f"✅ Labels added to issue #{args.issue_number}: {', '.join(applied_labels)}") + sys.exit(0) + except ValueError as e: + print(f"❌ Configuration error: {e}", file=sys.stderr) + sys.exit(1) + except requests.HTTPError as e: + print(f"❌ GitHub API error: {e}", file=sys.stderr) + if e.response is not None: + print(f" Response: {e.response.text}", file=sys.stderr) + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/.github/skills/send-email/SKILL.md b/.github/skills/send-email/SKILL.md new file mode 100644 index 00000000..01bccf64 --- /dev/null +++ b/.github/skills/send-email/SKILL.md @@ -0,0 +1,116 @@ +--- +name: send-email +description: Send HTML email notifications via Azure Logic App. Use when (1) sending formatted emails to recipients, (2) delivering reports or summaries via email, (3) triggering email notifications from workflows. Triggers on requests like "send email", "email this", "send via email", "mail to". +--- + +# Send Email Skill + +Send HTML email notifications to specified recipients via an Azure Logic App HTTP trigger. + +## Overview + +This skill constructs a well-formatted HTML email from user-provided content and posts it to a configured Logic App endpoint for delivery. + +## Usage + +### Required Environment Variable + +The mailing URL must be set via environment variable: +- `MAILING_URL`: The Azure Logic App HTTP trigger URL for email sending + +### Required Input from User + +The user must provide: +1. **Content**: The information/message to be sent (any format - text, data, structured content) +2. **Recipients**: One or more email addresses +3. **Title** (optional): Subject line for the email +4. **Time frame** (optional): Relevant date/period context + +### Payload Schema + +The skill constructs and sends a JSON payload: + +```json +{ + "title": "Email Subject", + "timeFrame": "January 28, 2026", + "body": "...", + "workflowRunUrl": "https://github.com/org/repo/actions/runs/12345", + "recipients": ["user1@example.com", "user2@example.com"] +} +``` + +For the full JSON schema, see [references/payload-schema.json](references/payload-schema.json). + +### HTML Body Construction + +The skill must transform user-provided content into well-formatted HTML: + +1. **Use semantic HTML structure with inline CSS** (email clients don't support external stylesheets) + +2. **Base template**: + ```html + + +
+

{{title}}

+

{{timeFrame}}

+
+ + + {{content}} + +
+

+ Generated by GitHub Actions workflow +

+ + + ``` + +3. **Content formatting guidelines**: + - Plain text → Wrap in `

` tags + - Lists → Use `