mirror of
https://mirror.skon.top/github.com/router-for-me/CLIProxyAPI
synced 2026-04-21 01:10:14 +08:00
chore: add workflow to prevent AGENTS.md modifications in pull requests
This commit is contained in:
81
.github/workflows/agents-md-guard.yml
vendored
Normal file
81
.github/workflows/agents-md-guard.yml
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
name: agents-md-guard
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
- synchronize
|
||||
- reopened
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
close-when-agents-md-changed:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Detect AGENTS.md changes and close PR
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const prNumber = context.payload.pull_request.number;
|
||||
const { owner, repo } = context.repo;
|
||||
|
||||
const files = await github.paginate(github.rest.pulls.listFiles, {
|
||||
owner,
|
||||
repo,
|
||||
pull_number: prNumber,
|
||||
per_page: 100,
|
||||
});
|
||||
|
||||
const touchesAgentsMd = (path) =>
|
||||
typeof path === "string" &&
|
||||
(path === "AGENTS.md" || path.endsWith("/AGENTS.md"));
|
||||
|
||||
const touched = files.filter(
|
||||
(f) => touchesAgentsMd(f.filename) || touchesAgentsMd(f.previous_filename),
|
||||
);
|
||||
|
||||
if (touched.length === 0) {
|
||||
core.info("No AGENTS.md changes detected.");
|
||||
return;
|
||||
}
|
||||
|
||||
const changedList = touched
|
||||
.map((f) =>
|
||||
f.previous_filename && f.previous_filename !== f.filename
|
||||
? `- ${f.previous_filename} -> ${f.filename}`
|
||||
: `- ${f.filename}`,
|
||||
)
|
||||
.join("\n");
|
||||
|
||||
const body = [
|
||||
"This repository does not allow modifying `AGENTS.md` in pull requests.",
|
||||
"",
|
||||
"Detected changes:",
|
||||
changedList,
|
||||
"",
|
||||
"Please revert these changes and open a new PR without touching `AGENTS.md`.",
|
||||
].join("\n");
|
||||
|
||||
try {
|
||||
await github.rest.issues.createComment({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: prNumber,
|
||||
body,
|
||||
});
|
||||
} catch (error) {
|
||||
core.warning(`Failed to comment on PR #${prNumber}: ${error.message}`);
|
||||
}
|
||||
|
||||
await github.rest.pulls.update({
|
||||
owner,
|
||||
repo,
|
||||
pull_number: prNumber,
|
||||
state: "closed",
|
||||
});
|
||||
|
||||
core.setFailed("PR modifies AGENTS.md");
|
||||
58
AGENTS.md
Normal file
58
AGENTS.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# AGENTS.md
|
||||
|
||||
Go 1.26+ proxy server providing OpenAI/Gemini/Claude/Codex compatible APIs with OAuth and round-robin load balancing.
|
||||
|
||||
## Repository
|
||||
- GitHub: https://github.com/router-for-me/CLIProxyAPI
|
||||
|
||||
## Commands
|
||||
```bash
|
||||
gofmt -w . # Format (required after Go changes)
|
||||
go build -o cli-proxy-api ./cmd/server # Build
|
||||
go run ./cmd/server # Run dev server
|
||||
go test ./... # Run all tests
|
||||
go test -v -run TestName ./path/to/pkg # Run single test
|
||||
go build -o test-output ./cmd/server && rm test-output # Verify compile (REQUIRED after changes)
|
||||
```
|
||||
- Common flags: `--config <path>`, `--tui`, `--standalone`, `--local-model`, `--no-browser`, `--oauth-callback-port <port>`
|
||||
|
||||
## Config
|
||||
- Default config: `config.yaml` (template: `config.example.yaml`)
|
||||
- `.env` is auto-loaded from the working directory
|
||||
- Auth material defaults under `auths/`
|
||||
- Storage backends: file-based default; optional Postgres/git/object store (`PGSTORE_*`, `GITSTORE_*`, `OBJECTSTORE_*`)
|
||||
|
||||
## Architecture
|
||||
- `cmd/server/` — Server entrypoint
|
||||
- `internal/api/` — Gin HTTP API (routes, middleware, modules)
|
||||
- `internal/api/modules/amp/` — Amp integration (Amp-style routes + reverse proxy)
|
||||
- `internal/thinking/` — Thinking/reasoning token processing (`internal/thinking/provider/` for per-provider config)
|
||||
- `internal/runtime/executor/` — Per-provider runtime executors (incl. Codex WebSocket)
|
||||
- `internal/translator/` — Provider protocol translators (and shared `common`)
|
||||
- `internal/registry/` — Model registry + remote updater (`StartModelsUpdater`); `--local-model` disables remote updates
|
||||
- `internal/store/` — Storage implementations and secret resolution
|
||||
- `internal/managementasset/` — Config snapshots and management assets
|
||||
- `internal/cache/` — Request signature caching
|
||||
- `internal/watcher/` — Config hot-reload and watchers
|
||||
- `internal/wsrelay/` — WebSocket relay sessions
|
||||
- `internal/usage/` — Usage and token accounting
|
||||
- `internal/tui/` — Bubbletea terminal UI (`--tui`, `--standalone`)
|
||||
- `sdk/cliproxy/` — Embeddable SDK entry (service/builder/watchers/pipeline)
|
||||
- `test/` — Cross-module integration tests
|
||||
|
||||
## Code Conventions
|
||||
- Keep changes small and simple (KISS)
|
||||
- Comments in English only
|
||||
- If editing code that already contains non-English comments, translate them to English (don’t add new non-English comments)
|
||||
- For user-visible strings, keep the existing language used in that file/area
|
||||
- New Markdown docs should be in English unless the file is explicitly language-specific (e.g. `README_CN.md`)
|
||||
- As a rule, do not make standalone changes to `internal/translator/`. You may modify it only as part of broader changes elsewhere.
|
||||
- If a task requires changing only `internal/translator/`, run `gh repo view --json viewerPermission -q .viewerPermission` to confirm you have `WRITE`, `MAINTAIN`, or `ADMIN`. If you do, you may proceed; otherwise, file a GitHub issue including the goal, rationale, and the intended implementation code, then stop further work.
|
||||
- `internal/runtime/executor/` should contain executors and their unit tests only. Place any helper/supporting files under `internal/runtime/executor/helps/`.
|
||||
- Follow `gofmt`; keep imports goimports-style; wrap errors with context where helpful
|
||||
- Do not use `log.Fatal`/`log.Fatalf` (terminates the process); prefer returning errors and logging via logrus
|
||||
- Shadowed variables: use method suffix (`errStart := server.Start()`)
|
||||
- Wrap defer errors: `defer func() { if err := f.Close(); err != nil { log.Errorf(...) } }()`
|
||||
- Use logrus structured logging; avoid leaking secrets/tokens in logs
|
||||
- Avoid panics in HTTP handlers; prefer logged errors and meaningful HTTP status codes
|
||||
- Timeouts are allowed only during credential acquisition; after an upstream connection is established, do not set timeouts for any subsequent network behavior. Intentional exceptions that must remain allowed are the Codex websocket liveness deadlines in `internal/runtime/executor/codex_websockets_executor.go`, the wsrelay session deadlines in `internal/wsrelay/session.go`, the management APICall timeout in `internal/api/handlers/management/api_tools.go`, and the `cmd/fetch_antigravity_models` utility timeouts
|
||||
Reference in New Issue
Block a user