mirror of
https://github.com/MervinPraison/PraisonAIUI.git
synced 2026-11-07 05:56:17 -10:00
- claude.yml: add issues:[opened,labeled,assigned] + pull_request_review_comment triggers
- claude.yml: add issue-triage job (welcome comment on new issues)
- claude.yml: expand direct_prompt with PraisonAIUI-specific routing (STEP 0-6):
- architecture routing (core / features / UI builders / frontend / tests / docs)
- external-repo routing (PraisonAI / PraisonAI-Tools / PraisonAIDocs)
- conceptual checks (no duplicate exports, no class-first Ask*Message, lazy
optional deps, real DeprecationWarning on deprecations)
- import-time < 200ms + no heavy-dep leak invariant
- PR body template (Summary, Before/After, SHA-cited checklist, test evidence,
import-time proof)
- STEP 6 reviewer-loop instructions (respond to CodeRabbit/Copilot/human
review comments, push to same branch)
- auto-issue-comment.yml: optional workflow to escalate an issue to Claude by
adding the 'claude' label (workflow_dispatch-only; issues:opened trigger
commented out by default)
CodeRabbit + Copilot: no workflow file needed — both are GitHub Apps that
react to PRs automatically. The chain (CodeRabbit → Copilot → Claude) is
already orchestrated by auto-pr-comment.yml.
292 lines
16 KiB
YAML
292 lines
16 KiB
YAML
name: Claude Assistant
|
|
|
|
# Triggers:
|
|
# - issues:opened → lightweight triage (welcome comment + label)
|
|
# - issues:labeled → full implementation when `claude` label applied
|
|
# - issues:assigned → full implementation when issue assigned to Claude
|
|
# - issue_comment → full implementation when @claude mentioned (issues + PRs)
|
|
# - pull_request_review → full implementation when @claude mentioned in review
|
|
# - pull_request_review_comment → full implementation when @claude mentioned inline
|
|
#
|
|
# Focus: CLAUDE only. Copilot and CodeRabbit are GitHub Apps that react to PRs
|
|
# automatically — no workflow file needed. auto-pr-comment.yml orchestrates the
|
|
# CodeRabbit → Copilot → Claude review chain for PRs.
|
|
|
|
on:
|
|
issue_comment:
|
|
types: [created]
|
|
pull_request_review_comment:
|
|
types: [created]
|
|
issues:
|
|
types: [opened, labeled, assigned]
|
|
pull_request_review:
|
|
types: [submitted]
|
|
|
|
permissions:
|
|
contents: write
|
|
pull-requests: write
|
|
issues: write
|
|
actions: read
|
|
id-token: write
|
|
|
|
jobs:
|
|
# ================================================================
|
|
# Job 1 — Issue triage (runs on ANY new issue, including from external users)
|
|
# Posts a welcome comment. Does NOT execute Claude Code.
|
|
# To escalate to full implementation, a maintainer adds the `claude` label
|
|
# or mentions @claude in a comment — which triggers Job 2.
|
|
# ================================================================
|
|
issue-triage:
|
|
if: |
|
|
github.event_name == 'issues' &&
|
|
github.event.action == 'opened' &&
|
|
!contains(toJSON(github.event.issue.labels), 'claude')
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
issues: write
|
|
contents: read
|
|
steps:
|
|
- name: Post welcome comment
|
|
uses: actions/github-script@v7
|
|
with:
|
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
script: |
|
|
const body = [
|
|
'👋 Thanks for opening an issue in **PraisonAIUI**.',
|
|
'',
|
|
'A maintainer will triage this shortly. If you would like Claude to investigate and draft a fix, a maintainer can:',
|
|
'',
|
|
'- Apply the `claude` label to this issue, **or**',
|
|
'- Mention `@claude` in a comment with any additional instructions.',
|
|
'',
|
|
'Please make sure your issue includes:',
|
|
'',
|
|
'1. A clear description of the behaviour you expect vs what you see.',
|
|
'2. Minimal reproduction steps (code snippet or `aiui.template.yaml`).',
|
|
'3. Version: `python -c "import praisonaiui; print(praisonaiui.__version__)"`.',
|
|
'4. Any relevant log output.',
|
|
'',
|
|
'See [AGENTS.md](https://github.com/MervinPraison/PraisonAIUI/blob/main/AGENTS.md) for project conventions.'
|
|
].join('\n');
|
|
|
|
await github.rest.issues.createComment({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: context.issue.number,
|
|
body
|
|
});
|
|
|
|
# ================================================================
|
|
# Job 2 — Full Claude Code implementation
|
|
# Runs when:
|
|
# - A comment containing `@claude` is posted on an issue or PR
|
|
# - The `claude` label is added to an issue
|
|
# - The issue is assigned to a Claude bot
|
|
# - A PR review or review-comment contains `@claude`
|
|
# ================================================================
|
|
claude-response:
|
|
env:
|
|
ISSUE_NUMBER_RESOLVED: ${{ github.event.issue.number || github.event.pull_request.number }}
|
|
if: |
|
|
github.actor != 'dependabot[bot]' &&
|
|
github.actor != 'cursor[bot]' &&
|
|
github.actor != 'renovate[bot]' &&
|
|
(
|
|
(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' && github.event.action == 'labeled' && contains(toJSON(github.event.label), 'claude')) ||
|
|
(github.event_name == 'issues' && github.event.action == 'assigned')
|
|
)
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
token: ${{ secrets.GITHUB_TOKEN }}
|
|
ref: ${{ github.event.issue.pull_request && format('refs/pull/{0}/head', github.event.issue.number) || github.event.repository.default_branch }}
|
|
|
|
- name: Run Claude Code Action
|
|
uses: anthropics/claude-code-action@beta
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
with:
|
|
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
trigger_phrase: "@claude"
|
|
label_trigger: "claude"
|
|
allowed_bots: "praisonai-triage-agent[bot]"
|
|
timeout_minutes: "30"
|
|
direct_prompt: |
|
|
You are implementing changes in **MervinPraison/PraisonAIUI** (YAML-driven server-driven UI with agentic chat).
|
|
Follow `AGENTS.md` at the repository root. If a conflict arises between this prompt and `AGENTS.md`, `AGENTS.md` wins.
|
|
|
|
═══════════════════════════════════════════════════════════════
|
|
STEP 0 — GIT & GITHUB CLI
|
|
═══════════════════════════════════════════════════════════════
|
|
git config --global user.name "github-actions[bot]"
|
|
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
gh auth setup-git
|
|
|
|
═══════════════════════════════════════════════════════════════
|
|
STEP 1 — READ GUIDELINES
|
|
═══════════════════════════════════════════════════════════════
|
|
Read `AGENTS.md` and any `docs/principles.md`. Key invariants:
|
|
• Cold import of `praisonaiui` must stay under 200 ms; module count must not grow.
|
|
• Heavy / optional deps (`mcp`, `langchain`, `llama_index`, `semantic_kernel`,
|
|
`slack_sdk`, `discord.py`, `botbuilder.core`, `openai`, `anthropic`, `mistralai`,
|
|
`google.generativeai`) must be **lazy-imported** — never eager.
|
|
• Public API is verb-first. New classes in `src/praisonaiui/message.py` ending
|
|
in `Message` with a verb prefix (Ask*, Do*, Request*, …) are forbidden —
|
|
use a module-level `async def` verb helper instead (see `prompt`, `error`).
|
|
• Deprecations must emit a runtime `warnings.warn(..., DeprecationWarning, stacklevel=2)`
|
|
on first access, not only in the docstring.
|
|
• Deterministic serialisation in anything reaching the wire (sorted keys, stable field
|
|
order). See existing `to_dict` patterns.
|
|
• Multi-agent + async safe: no global mutable state without a lock.
|
|
|
|
═══════════════════════════════════════════════════════════════
|
|
STEP 2 — ARCHITECTURE VALIDATION & ROUTING (MANDATORY before any code)
|
|
═══════════════════════════════════════════════════════════════
|
|
Answer these questions inline in your response, then proceed only if you pass:
|
|
|
|
ROUTING:
|
|
1. **Core aiui** (`src/praisonaiui/`) — protocols, message types, server, features.
|
|
2. **Features** (`src/praisonaiui/features/`) — opt-in capabilities (MCP, platforms, lifecycle, audio, auth, sharing, etc.).
|
|
3. **UI builders** (`src/praisonaiui/ui.py`) — declarative component helpers.
|
|
4. **Frontend** (`src/frontend/`) — React components / stores / SSE handlers.
|
|
5. **Tests** (`tests/unit/`, `tests/integration/`) — new features require both smoke and real-agentic tests.
|
|
6. **Docs** (`docs/`) — canonical name per feature, migration table for renames.
|
|
|
|
EXTERNAL REPOS (do NOT edit from within this repo — route the work to the right place and stop):
|
|
• Core SDK: `MervinPraison/PraisonAI` (`praisonaiagents`, `praisonai`) — agent runtime.
|
|
• Tools: `MervinPraison/PraisonAI-Tools` — tool implementations.
|
|
• Docs site: `MervinPraison/PraisonAIDocs` — product docs.
|
|
If the requested change belongs in an external repo, comment on the issue explaining
|
|
where it should live and DO NOT open a PR in this repo.
|
|
|
|
CONCEPTUAL CHECKS (if ANY fails — add a comment, do NOT open a PR):
|
|
• Does it duplicate an existing public symbol in `src/praisonaiui/__init__.py`?
|
|
• Does it add new class-first message types (`class Ask*Message`, `class *Message`
|
|
with a verb in the name)? → Use a verb-first helper instead.
|
|
• Does it add a new hard dependency to `pyproject.toml` `[project] dependencies`?
|
|
→ Move to `[project.optional-dependencies]` and wrap imports lazily.
|
|
• Does it break backward compat (rename, signature change, removal)? → Add
|
|
a deprecation alias that emits `DeprecationWarning`; never hard-remove before the
|
|
documented removal version (e.g. `0.5.0`).
|
|
|
|
═══════════════════════════════════════════════════════════════
|
|
STEP 3 — IMPLEMENT
|
|
═══════════════════════════════════════════════════════════════
|
|
Single branch for the whole flow (reuse the same name in STEP 5):
|
|
BRANCH="claude/issue-${{ env.ISSUE_NUMBER_RESOLVED }}-$(date +%Y%m%d-%H%M%S)"
|
|
git checkout -b "$BRANCH"
|
|
|
|
Make minimal, focused changes:
|
|
• Stay within the files listed in the issue's "Scope" / "Files to change" section.
|
|
• Prefer extending existing modules over adding new ones.
|
|
• No emojis, no comments, no markdown except where the user asked for it.
|
|
• Python ≥ 3.10 style (`list[...]` not `List[...]`, `X | None` not `Optional[X]`).
|
|
|
|
═══════════════════════════════════════════════════════════════
|
|
STEP 4 — TEST / VERIFY
|
|
═══════════════════════════════════════════════════════════════
|
|
Run these targeted checks (NOT the full suite):
|
|
|
|
# 1. Lint on only the files you changed:
|
|
CHANGED=$(git diff --name-only origin/main...HEAD | grep -E '\.py$' | tr '\n' ' ')
|
|
[ -n "$CHANGED" ] && ruff check $CHANGED
|
|
|
|
# 2. Unit tests for the module(s) you touched:
|
|
pytest tests/unit/<your_new_test_file>.py -v --tb=short
|
|
|
|
# 3. Import-time invariant (MUST stay under 200 ms cold):
|
|
python -c "import time, sys; t=time.time(); import praisonaiui; dt=(time.time()-t)*1000; heavy=[m for m in sys.modules if any(h in m for h in ['langchain','llama_index','mcp','slack','discord','botbuilder','openai.','anthropic.','mistralai','google.generativeai'])]; print(f'{dt:.1f}ms modules={len(sys.modules)} leaked={heavy}'); assert heavy == [], f'Heavy deps leaked: {heavy}'"
|
|
|
|
# 4. Real agentic end-to-end test (write this into tests/integration/
|
|
# if your feature changes the agent-facing API):
|
|
# from praisonaiagents import Agent
|
|
# import praisonaiui as aiui
|
|
# agent = Agent(name="demo", instructions="You are a helpful assistant")
|
|
# result = agent.start("Say hello in one sentence")
|
|
# print(result)
|
|
|
|
If anything fails, fix the root cause (never skip, xfail, or delete the test).
|
|
|
|
═══════════════════════════════════════════════════════════════
|
|
STEP 5 — COMMIT, PUSH, OPEN PR (MANDATORY if you produced commits)
|
|
═══════════════════════════════════════════════════════════════
|
|
git add -A
|
|
git commit -m "feat: <short summary> (fixes #${{ env.ISSUE_NUMBER_RESOLVED }})"
|
|
git push -u origin "$BRANCH"
|
|
REPO="${{ github.repository }}"
|
|
COUNT=$(gh pr list --repo "$REPO" --head "$BRANCH" --json number --jq 'length')
|
|
if [ "$COUNT" -gt 0 ]; then
|
|
gh pr list --repo "$REPO" --head "$BRANCH" --json url --jq '.[0].url'
|
|
else
|
|
gh pr create --repo "$REPO" --base main --head "$BRANCH" \
|
|
--title "feat: <short title>" \
|
|
--body "Fixes #${{ env.ISSUE_NUMBER_RESOLVED }}
|
|
|
|
## Summary
|
|
|
|
<what changed in one paragraph>
|
|
|
|
## Before / After
|
|
|
|
<copy-pasteable snippet per public API change>
|
|
|
|
## Acceptance criteria
|
|
|
|
<copy from the issue; tick boxes only with commit SHA + file path evidence>
|
|
|
|
## Test evidence
|
|
|
|
\`\`\`
|
|
<paste pytest output>
|
|
\`\`\`
|
|
|
|
## Import-time proof
|
|
|
|
\`\`\`
|
|
<paste the python -c import-time output>
|
|
\`\`\`
|
|
"
|
|
fi
|
|
|
|
CRITICAL: Do NOT stop after `git push`. You MUST complete `gh pr create` (or print the
|
|
existing PR URL from the step above) and post that URL on the issue. Never ask a
|
|
human to open the PR manually.
|
|
|
|
═══════════════════════════════════════════════════════════════
|
|
STEP 6 — RESPOND TO REVIEW FEEDBACK (if this run was triggered by a review comment)
|
|
═══════════════════════════════════════════════════════════════
|
|
If you were invoked by a PR review comment, you are the Lead Engineer for this PR:
|
|
• Read ALL reviewer comments in chronological order (CodeRabbit → Copilot → human).
|
|
• Fix every VALID issue by pushing commits to THIS branch (do NOT open a new PR).
|
|
• Reply with a summary of which comments you addressed, which you disagreed with (and why).
|
|
• Never ship a fix that removes/weakens a test.
|
|
|
|
allowed_tools: |
|
|
Bash(git:*)
|
|
Bash(python:*)
|
|
Bash(pip:*)
|
|
Bash(pytest:*)
|
|
Bash(ruff:*)
|
|
Bash(gh:*)
|
|
Bash(npm:*)
|
|
Bash(npx:*)
|
|
Bash(python -m pytest:*)
|
|
Bash(python -m pip:*)
|
|
Bash(python -m ruff:*)
|
|
View
|
|
GlobTool
|
|
GrepTool
|
|
BatchTool
|
|
Edit
|
|
Replace
|
|
mcp__github__get_issue
|
|
mcp__github__get_issue_comments
|
|
mcp__github__update_issue
|