From 99be27ac359f0d4e3555c1486799f9e983eb49a8 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 11 Nov 2026 21:53:03 +0000 Subject: [PATCH 1/2] Add /oc builder (caller workflow and AGENTS.md) Calls the shared builder in haimcslab/oc-builder on the dock self-hosted runner. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01WHvpr67K6CjkST2CT8CNZe --- .github/workflows/oc.yml | 22 ++++++++++++++++++++++ AGENTS.md | 24 ++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 .github/workflows/oc.yml create mode 100644 AGENTS.md diff --git a/.github/workflows/oc.yml b/.github/workflows/oc.yml new file mode 100644 index 00000000..ce84482c --- /dev/null +++ b/.github/workflows/oc.yml @@ -0,0 +1,22 @@ +# /oc builder: comment "/oc " on an issue or PR. Logic lives in haimcslab/oc-builder. +name: oc builder + +on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + +concurrency: + group: oc-${{ github.event.issue.number || github.event.pull_request.number }} + cancel-in-progress: false + +jobs: + oc: + uses: haimcslab/oc-builder/.github/workflows/builder.yml@main + permissions: + contents: write + pull-requests: write + issues: write + secrets: + CF_WORKERS_AI_TOKEN: ${{ secrets.CF_WORKERS_AI_TOKEN }} diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..22316e7c --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,24 @@ +# Instructions for agents working in OpenList-Worker + +haimcslab's fork of OpenListTeam/OpenList-Worker (TypeScript, Hono + SolidJS), deployed as the Cloudflare Worker "openlist-worker" at openlist.haimcslab.com. Cloudflare Workers Builds deploys every merge to main, so a merged PR goes live. + +## How work happens +- Work arrives as a GitHub issue. Do only what the issue asks. +- Make changes on a branch and open a pull request. Never push to main. +- The PR description says what changed, why, how you tested it, and anything a person must do by hand. +- Extend existing folders instead of creating parallel ones. +- Keep each PR small. If the issue needs a decision you cannot make from the repo, ask in the issue instead of guessing. + +## Secrets +- Never print, echo, cat or commit secrets, tokens, keys, .env or config.json files. Refer to secrets by name only. +- List the secret names a person must set in the PR description. + +## .github/workflows/ +**Never create, edit or delete files here.** The builder's token cannot push workflow changes, so the push fails and the work is lost. Put proposed workflow YAML in the PR description and a person adds it. + +## Rules for this fork +- Keep our local config in wrangler.jsonc: worker name "openlist-worker", D1 binding DB (database openlist, id d905961f-18d5-4cd0-9245-1b8c1fb65b91), DB_DRIVER=d1, DB_FORMAT=sql. When merging upstream, keep ours on these lines. +- Keep our English-only README.md when merging upstream. +- Prefer upstream behavior. Put fork-only changes in as few files as possible so upstream merges stay easy. +- This repo is public. Never commit anything lab-internal (IPs, hostnames, tokens). +- Build check before a PR: `pnpm install && pnpm run build` if the change touches src/ or api/. From 7939b36b8b3443183f410ff1466a5c2a71373480 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 11 Nov 2026 21:54:40 +0000 Subject: [PATCH 2/2] Run /oc inline on hosted runners; add daily upstream sync PR Public repos can't call the private oc-builder workflow and shouldn't use the dock runner, so oc.yml is an inline copy on ubuntu-latest (free for public repos). upstream-sync.yml opens a daily PR merging OpenListTeam main, keeping our wrangler.jsonc and README.md on conflict. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01WHvpr67K6CjkST2CT8CNZe --- .github/workflows/oc.yml | 62 ++++++++++++++++++++++++++--- .github/workflows/upstream-sync.yml | 61 ++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/upstream-sync.yml diff --git a/.github/workflows/oc.yml b/.github/workflows/oc.yml index ce84482c..03f4bccb 100644 --- a/.github/workflows/oc.yml +++ b/.github/workflows/oc.yml @@ -1,4 +1,7 @@ -# /oc builder: comment "/oc " on an issue or PR. Logic lives in haimcslab/oc-builder. +# /oc builder, inline copy of haimcslab/oc-builder/.github/workflows/builder.yml. +# This repo is public, so it cannot call the private oc-builder workflow, and it +# runs on GitHub-hosted runners (free for public repos) instead of the dock runner. +# Keep in sync with oc-builder by hand. name: oc builder on: @@ -12,11 +15,60 @@ concurrency: cancel-in-progress: false jobs: - oc: - uses: haimcslab/oc-builder/.github/workflows/builder.yml@main + opencode: + # Only owners/members/collaborators can start a run (each run spends model budget). + if: | + (contains(github.event.comment.body, '/oc') || contains(github.event.comment.body, '/opencode')) && + contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association) + runs-on: ubuntu-latest permissions: contents: write pull-requests: write issues: write - secrets: - CF_WORKERS_AI_TOKEN: ${{ secrets.CF_WORKERS_AI_TOKEN }} + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Configure git identity + run: | + git config --global user.name "MCS Studio Builder" + git config --global user.email "builder@haimcslab.com" + + # Default config outside the workspace so it is never committed. + # A repo's own opencode.json takes precedence over it. + - name: Write default opencode config + run: | + cat > "$RUNNER_TEMP/opencode.json" <<'JSON' + { + "$schema": "https://opencode.ai/config.json", + "enabled_providers": ["haimcslab-gw"], + "model": "haimcslab-gw/workers-ai/@cf/moonshotai/kimi-k2.7-code", + "small_model": "haimcslab-gw/workers-ai/@cf/zai-org/glm-5.3-flash", + "provider": { + "haimcslab-gw": { + "npm": "@ai-sdk/openai-compatible", + "name": "haimcslab AI Gateway (builder)", + "options": { + "baseURL": "https://gateway.ai.cloudflare.com/v1/23d2119251af1e3d761921eadb8e7e0f/haimcslab/compat", + "apiKey": "{env:CF_WORKERS_AI_TOKEN}", + "headers": { "cf-aig-authorization": "Bearer {env:CF_WORKERS_AI_TOKEN}", "cf-aig-metadata": "{\"user_id\":\"github-builder\",\"repo\":\"${{ github.repository }}\"}" } + }, + "models": { + "workers-ai/@cf/moonshotai/kimi-k2.7-code": { "name": "Kimi K2.7 Code" }, + "workers-ai/@cf/zai-org/glm-5.3-flash": { "name": "GLM-5.3 Flash" } + } + } + } + } + JSON + echo "OPENCODE_CONFIG=$RUNNER_TEMP/opencode.json" >> "$GITHUB_ENV" + + - uses: anomalyco/opencode/github@2c14fc5586fe0b88e5c04732d2e846769cc35671 # tag "latest" on 2026-11-11; release tags (v2.2.x) do not contain github/ + env: + CF_WORKERS_AI_TOKEN: ${{ secrets.CF_WORKERS_AI_TOKEN }} + GITHUB_TOKEN: ${{ github.token }} + with: + model: haimcslab-gw/workers-ai/@cf/moonshotai/kimi-k2.7-code + use_github_token: true diff --git a/.github/workflows/upstream-sync.yml b/.github/workflows/upstream-sync.yml new file mode 100644 index 00000000..381c2423 --- /dev/null +++ b/.github/workflows/upstream-sync.yml @@ -0,0 +1,61 @@ +# Daily: merge OpenListTeam/OpenList-Worker main into a branch and open a PR. +# Merging the PR deploys (Workers Builds). Our wrangler.jsonc and README.md win on conflict. +# Needs secret SYNC_TOKEN: fine-grained PAT for this repo with Contents, Pull requests +# and Workflows read/write (upstream changes .github/workflows, which GITHUB_TOKEN can't push). +name: upstream sync + +on: + schedule: + - cron: "0 9 * * *" + workflow_dispatch: + +concurrency: + group: upstream-sync + cancel-in-progress: false + +jobs: + sync: + if: github.repository == 'haimcslab/OpenList-Worker' + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.SYNC_TOKEN }} + + - name: Merge upstream + id: merge + env: + GH_TOKEN: ${{ secrets.SYNC_TOKEN }} + run: | + git config user.name "upstream-sync" + git config user.email "builder@haimcslab.com" + git remote add upstream https://github.com/OpenListTeam/OpenList-Worker.git + git fetch upstream main + behind=$(git rev-list --count HEAD..upstream/main) + echo "behind=$behind" + if [ "$behind" = 0 ]; then echo "Up to date."; exit 0; fi + if gh pr list --state open --json headRefName --jq '.[].headRefName' | grep -q '^upstream-sync/'; then + echo "An upstream sync PR is already open."; exit 0 + fi + branch="upstream-sync/$(date -u +%Y%m%d)" + git checkout -b "$branch" + if ! git merge --no-edit upstream/main; then + for f in wrangler.jsonc README.md; do + if git diff --name-only --diff-filter=U | grep -qx "$f"; then git checkout --ours -- "$f"; git add "$f"; fi + done + left=$(git diff --name-only --diff-filter=U) + if [ -n "$left" ]; then + git merge --abort + body=$(printf 'Upstream has %s new commits but these files conflict:\n\n```\n%s\n```\n\nResolve with a manual merge PR (keep our wrangler.jsonc D1 config and README).' "$behind" "$left") + gh issue create --title "Upstream sync conflict ($(date -u +%F))" --body "$body" + exit 0 + fi + git commit --no-edit + fi + git push -u origin "$branch" + log=$(git log --oneline --no-merges HEAD^1..upstream/main | head -60) + gh pr create --base main --head "$branch" \ + --title "chore(sync): merge upstream main ($behind commits)" \ + --body "$(printf 'Automated merge of OpenListTeam/OpenList-Worker main. Our wrangler.jsonc and README.md are kept on conflict. Merging deploys.\n\n```\n%s\n```' "$log")"