Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# These are supported funding model platforms

github: code-yeongyu
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
polar: # Replace with a single Polar username
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
thanks_dev: # Replace with a single thanks.dev username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
41 changes: 41 additions & 0 deletions .github/workflows/cla.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: CLA Assistant

on:
issue_comment:
types: [created]
pull_request_target:
types: [opened, closed, synchronize]

permissions:
actions: write
contents: write
pull-requests: write
statuses: write

jobs:
cla:
runs-on: ubuntu-latest
steps:
- name: CLA Assistant
if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target'
uses: contributor-assistant/[email protected]
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
path-to-signatures: 'signatures/cla.json'
path-to-document: 'https://github.com/code-yeongyu/oh-my-opencode/blob/master/CLA.md'
branch: 'dev'
allowlist: bot*,dependabot*,github-actions*,*[bot],sisyphus-dev-ai
custom-notsigned-prcomment: |
Thank you for your contribution! Before we can merge this PR, we need you to sign our [Contributor License Agreement (CLA)](https://github.com/code-yeongyu/oh-my-opencode/blob/master/CLA.md).

**To sign the CLA**, please comment on this PR with:
```
I have read the CLA Document and I hereby sign the CLA
```

This is a one-time requirement. Once signed, all your future contributions will be automatically accepted.
custom-pr-sign-comment: 'I have read the CLA Document and I hereby sign the CLA'
custom-allsigned-prcomment: |
All contributors have signed the CLA. Thank you! ✅
lock-pullrequest-aftermerge: false
280 changes: 280 additions & 0 deletions .github/workflows/sisyphus-agent.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,280 @@
name: Sisyphus Agent

on:
workflow_dispatch:
inputs:
prompt:
description: "Custom prompt"
required: false
issue_comment:
types: [created]
pull_request_review:
types: [submitted]
pull_request_review_comment:
types: [created]

jobs:
agent:
runs-on: ubuntu-latest
# @sisyphus-dev-ai mention only (maintainers, exclude self)
if: |
github.event_name == 'workflow_dispatch' ||
(contains(github.event.comment.body || github.event.review.body, '@sisyphus-dev-ai') &&
(github.event.comment.user.login || github.event.review.user.login) != 'sisyphus-dev-ai' &&
contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association || github.event.review.author_association))

# Minimal default GITHUB_TOKEN permissions
permissions:
contents: read

steps:
# Checkout with sisyphus-dev-ai's PAT
- uses: actions/checkout@v5
with:
token: ${{ secrets.GH_PAT }}
fetch-depth: 0

# Git config - commits as sisyphus-dev-ai
- name: Configure Git as sisyphus-dev-ai
run: |
git config user.name "sisyphus-dev-ai"
git config user.email "[email protected]"

# gh CLI auth as sisyphus-dev-ai
- name: Authenticate gh CLI as sisyphus-dev-ai
run: |
echo "${{ secrets.GH_PAT }}" | gh auth login --with-token
gh auth status

- name: Ensure tmux is available (Linux)
if: runner.os == 'Linux'
run: |
set -euo pipefail
if ! command -v tmux >/dev/null 2>&1; then
sudo apt-get update
sudo apt-get install -y --no-install-recommends tmux
fi
tmux -V

- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest

- name: Cache Bun dependencies
uses: actions/cache@v4
with:
path: |
~/.bun/install/cache
node_modules
key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lock') }}
restore-keys: |
${{ runner.os }}-bun-

# Install OpenCode + oh-my-opencode + auth in single step
- name: Setup OpenCode with oh-my-opencode
env:
OPENCODE_AUTH_JSON: ${{ secrets.OPENCODE_AUTH_JSON }}
ANTHROPIC_BASE_URL: ${{ secrets.ANTHROPIC_BASE_URL }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
export PATH="$HOME/.opencode/bin:$PATH"

# Install OpenCode (skip if cached)
if ! command -v opencode &>/dev/null; then
for i in 1 2 3; do
echo "Attempt $i: Installing OpenCode..."
curl -fsSL https://opencode.ai/install -o /tmp/opencode-install.sh
if file /tmp/opencode-install.sh | grep -q "shell script\|text"; then
bash /tmp/opencode-install.sh && break
fi
echo "Download corrupted, retrying in 5s..."
sleep 5
done
fi
opencode --version

bunx oh-my-opencode install --no-tui --claude=max20 --chatgpt=no --gemini=no

OPENCODE_JSON=~/.config/opencode/opencode.json
jq --arg baseURL "$ANTHROPIC_BASE_URL" --arg apiKey "$ANTHROPIC_API_KEY" '
.provider.anthropic = {
"name": "Anthropic",
"npm": "@ai-sdk/anthropic",
"options": {
"baseURL": $baseURL,
"apiKey": $apiKey
},
"models": {
"claude-opus-4-5": {
"id": "claude-opus-4-5-20251101",
"name": "Opus 4.5",
"limit": { "context": 200000, "output": 64000 },
"options": { "effort": "high" }
},
"claude-opus-4-5-high": {
"id": "claude-opus-4-5-20251101",
"name": "Opus 4.5 High",
"limit": { "context": 200000, "output": 128000 },
"options": { "effort": "high", "thinking": { "type": "enabled", "budgetTokens": 64000 } }
},
"claude-sonnet-4-5": {
"id": "claude-sonnet-4-5-20250929",
"name": "Sonnet 4.5",
"limit": { "context": 200000, "output": 64000 }
},
"claude-sonnet-4-5-high": {
"id": "claude-sonnet-4-5-20250929",
"name": "Sonnet 4.5 High",
"limit": { "context": 200000, "output": 128000 },
"options": { "thinking": { "type": "enabled", "budgetTokens": 64000 } }
},
"claude-haiku-4-5": {
"id": "claude-haiku-4-5-20251001",
"name": "Haiku 4.5",
"limit": { "context": 200000, "output": 64000 }
}
}
}
' "$OPENCODE_JSON" > /tmp/oc.json && mv /tmp/oc.json "$OPENCODE_JSON"

OMO_JSON=~/.config/opencode/oh-my-opencode.json
PROMPT_APPEND=$(cat << 'PROMPT_EOF'

## GitHub Actions Environment

You are `sisyphus-dev-ai` in GitHub Actions.

### CRITICAL: GitHub Comments = Your ONLY Output

User CANNOT see console. Post everything via `gh issue comment` or `gh pr comment`.

### Rules
- EVERY response = GitHub comment
- Code changes = PR (never push main/master)
- Setup: bun install first
- Acknowledge immediately, report when done

### Git Config
- user.name: sisyphus-dev-ai
- user.email: [email protected]
PROMPT_EOF
)
jq --arg append "$PROMPT_APPEND" '.agents.Sisyphus.prompt_append = $append' "$OMO_JSON" > /tmp/omo.json && mv /tmp/omo.json "$OMO_JSON"

mkdir -p ~/.local/share/opencode
echo "$OPENCODE_AUTH_JSON" > ~/.local/share/opencode/auth.json
chmod 600 ~/.local/share/opencode/auth.json

cat "$OPENCODE_JSON"

# Collect context
- name: Collect Context
id: context
env:
GITHUB_TOKEN: ${{ secrets.GH_PAT }}
run: |
EVENT="${{ github.event_name }}"

if [[ "$EVENT" == "issue_comment" ]]; then
ISSUE_NUM="${{ github.event.issue.number }}"
COMMENT="${{ github.event.comment.body }}"
AUTHOR="${{ github.event.comment.user.login }}"
COMMENT_ID="${{ github.event.comment.id }}"

# Check if PR or Issue
if gh api "repos/${{ github.repository }}/issues/${ISSUE_NUM}" | jq -e '.pull_request' > /dev/null; then
echo "type=pr" >> $GITHUB_OUTPUT
echo "number=${ISSUE_NUM}" >> $GITHUB_OUTPUT
else
echo "type=issue" >> $GITHUB_OUTPUT
echo "number=${ISSUE_NUM}" >> $GITHUB_OUTPUT
fi
elif [[ "$EVENT" == "pull_request_review_comment" ]]; then
echo "type=pr" >> $GITHUB_OUTPUT
echo "number=${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT
COMMENT="${{ github.event.comment.body }}"
AUTHOR="${{ github.event.comment.user.login }}"
COMMENT_ID="${{ github.event.comment.id }}"
elif [[ "$EVENT" == "pull_request_review" ]]; then
echo "type=pr" >> $GITHUB_OUTPUT
echo "number=${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT
COMMENT="${{ github.event.review.body }}"
AUTHOR="${{ github.event.review.user.login }}"
COMMENT_ID=""
fi

echo "comment<<EOF" >> $GITHUB_OUTPUT
echo "$COMMENT" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
echo "author=$AUTHOR" >> $GITHUB_OUTPUT
echo "comment_id=$COMMENT_ID" >> $GITHUB_OUTPUT

# Add :eyes: reaction (as sisyphus-dev-ai)
- name: Add eyes reaction
if: steps.context.outputs.comment_id != ''
env:
GITHUB_TOKEN: ${{ secrets.GH_PAT }}
run: |
gh api "/repos/${{ github.repository }}/issues/comments/${{ steps.context.outputs.comment_id }}/reactions" \
-X POST -f content="eyes" || true

- name: Run OpenCode
env:
GITHUB_TOKEN: ${{ secrets.GH_PAT }}
run: |
export PATH="$HOME/.opencode/bin:$PATH"

PROMPT="
Your username is @sisyphus-dev-ai, mentioned by @${{ steps.context.outputs.author }} in ${{ github.repository }}.

## Context
- Type: ${{ steps.context.outputs.type }}
- Number: #${{ steps.context.outputs.number }}
- Repository: ${{ github.repository }}
- Default Branch: ${{ github.event.repository.default_branch }}

## User's Request
${{ steps.context.outputs.comment }}

---

First, acknowledge with \`gh issue comment ${{ steps.context.outputs.number }} --body \"👋 Hey @${{ steps.context.outputs.author }}! I'm on it...\"\`

Then write everything using the todo tools.
Then investigate and satisfy the request. Only if user requested to you to work explicitely, then use plan agent to plan, todo obsessivley then create a PR to \`${{ github.event.repository.default_branch }}\` branch."

opencode run "$PROMPT"

# Push changes (as sisyphus-dev-ai)
- name: Push changes
if: always()
env:
GITHUB_TOKEN: ${{ secrets.GH_PAT }}
run: |
if [[ -n "$(git status --porcelain)" ]]; then
git add -A
git commit -m "chore: changes by sisyphus-dev-ai" || true
fi

BRANCH=$(git branch --show-current)
if [[ "$BRANCH" != "main" && "$BRANCH" != "master" ]]; then
git push origin "$BRANCH" || true
fi

# Remove :eyes:, add :+1:
- name: Update reaction
if: always() && steps.context.outputs.comment_id != ''
env:
GITHUB_TOKEN: ${{ secrets.GH_PAT }}
run: |
# Remove eyes
REACTION_ID=$(gh api "/repos/${{ github.repository }}/issues/comments/${{ steps.context.outputs.comment_id }}/reactions" \
--jq '.[] | select(.content == "eyes" and .user.login == "sisyphus-dev-ai") | .id' | head -1)
if [[ -n "$REACTION_ID" ]]; then
gh api -X DELETE "/repos/${{ github.repository }}/reactions/${REACTION_ID}" || true
fi

# Add thumbs up
gh api "/repos/${{ github.repository }}/issues/comments/${{ steps.context.outputs.comment_id }}/reactions" \
-X POST -f content="+1" || true
Empty file added =
Empty file.
Loading
Loading