Skip to content

Commit f5aa68e

Browse files
committed
chore: add workflow to prevent AGENTS.md modifications in pull requests
1 parent d1f6224 commit f5aa68e

2 files changed

Lines changed: 139 additions & 0 deletions

File tree

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
name: agents-md-guard
2+
3+
on:
4+
pull_request_target:
5+
types:
6+
- opened
7+
- synchronize
8+
- reopened
9+
10+
permissions:
11+
contents: read
12+
issues: write
13+
pull-requests: write
14+
15+
jobs:
16+
close-when-agents-md-changed:
17+
runs-on: ubuntu-latest
18+
steps:
19+
- name: Detect AGENTS.md changes and close PR
20+
uses: actions/github-script@v7
21+
with:
22+
script: |
23+
const prNumber = context.payload.pull_request.number;
24+
const { owner, repo } = context.repo;
25+
26+
const files = await github.paginate(github.rest.pulls.listFiles, {
27+
owner,
28+
repo,
29+
pull_number: prNumber,
30+
per_page: 100,
31+
});
32+
33+
const touchesAgentsMd = (path) =>
34+
typeof path === "string" &&
35+
(path === "AGENTS.md" || path.endsWith("/AGENTS.md"));
36+
37+
const touched = files.filter(
38+
(f) => touchesAgentsMd(f.filename) || touchesAgentsMd(f.previous_filename),
39+
);
40+
41+
if (touched.length === 0) {
42+
core.info("No AGENTS.md changes detected.");
43+
return;
44+
}
45+
46+
const changedList = touched
47+
.map((f) =>
48+
f.previous_filename && f.previous_filename !== f.filename
49+
? `- ${f.previous_filename} -> ${f.filename}`
50+
: `- ${f.filename}`,
51+
)
52+
.join("\n");
53+
54+
const body = [
55+
"This repository does not allow modifying `AGENTS.md` in pull requests.",
56+
"",
57+
"Detected changes:",
58+
changedList,
59+
"",
60+
"Please revert these changes and open a new PR without touching `AGENTS.md`.",
61+
].join("\n");
62+
63+
try {
64+
await github.rest.issues.createComment({
65+
owner,
66+
repo,
67+
issue_number: prNumber,
68+
body,
69+
});
70+
} catch (error) {
71+
core.warning(`Failed to comment on PR #${prNumber}: ${error.message}`);
72+
}
73+
74+
await github.rest.pulls.update({
75+
owner,
76+
repo,
77+
pull_number: prNumber,
78+
state: "closed",
79+
});
80+
81+
core.setFailed("PR modifies AGENTS.md");

AGENTS.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# AGENTS.md
2+
3+
Go 1.26+ proxy server providing OpenAI/Gemini/Claude/Codex compatible APIs with OAuth and round-robin load balancing.
4+
5+
## Repository
6+
- GitHub: https://github.com/router-for-me/CLIProxyAPI
7+
8+
## Commands
9+
```bash
10+
gofmt -w . # Format (required after Go changes)
11+
go build -o cli-proxy-api ./cmd/server # Build
12+
go run ./cmd/server # Run dev server
13+
go test ./... # Run all tests
14+
go test -v -run TestName ./path/to/pkg # Run single test
15+
go build -o test-output ./cmd/server && rm test-output # Verify compile (REQUIRED after changes)
16+
```
17+
- Common flags: `--config <path>`, `--tui`, `--standalone`, `--local-model`, `--no-browser`, `--oauth-callback-port <port>`
18+
19+
## Config
20+
- Default config: `config.yaml` (template: `config.example.yaml`)
21+
- `.env` is auto-loaded from the working directory
22+
- Auth material defaults under `auths/`
23+
- Storage backends: file-based default; optional Postgres/git/object store (`PGSTORE_*`, `GITSTORE_*`, `OBJECTSTORE_*`)
24+
25+
## Architecture
26+
- `cmd/server/` — Server entrypoint
27+
- `internal/api/` — Gin HTTP API (routes, middleware, modules)
28+
- `internal/api/modules/amp/` — Amp integration (Amp-style routes + reverse proxy)
29+
- `internal/thinking/` — Thinking/reasoning token processing (`internal/thinking/provider/` for per-provider config)
30+
- `internal/runtime/executor/` — Per-provider runtime executors (incl. Codex WebSocket)
31+
- `internal/translator/` — Provider protocol translators (and shared `common`)
32+
- `internal/registry/` — Model registry + remote updater (`StartModelsUpdater`); `--local-model` disables remote updates
33+
- `internal/store/` — Storage implementations and secret resolution
34+
- `internal/managementasset/` — Config snapshots and management assets
35+
- `internal/cache/` — Request signature caching
36+
- `internal/watcher/` — Config hot-reload and watchers
37+
- `internal/wsrelay/` — WebSocket relay sessions
38+
- `internal/usage/` — Usage and token accounting
39+
- `internal/tui/` — Bubbletea terminal UI (`--tui`, `--standalone`)
40+
- `sdk/cliproxy/` — Embeddable SDK entry (service/builder/watchers/pipeline)
41+
- `test/` — Cross-module integration tests
42+
43+
## Code Conventions
44+
- Keep changes small and simple (KISS)
45+
- Comments in English only
46+
- If editing code that already contains non-English comments, translate them to English (don’t add new non-English comments)
47+
- For user-visible strings, keep the existing language used in that file/area
48+
- New Markdown docs should be in English unless the file is explicitly language-specific (e.g. `README_CN.md`)
49+
- As a rule, do not make standalone changes to `internal/translator/`. You may modify it only as part of broader changes elsewhere.
50+
- 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.
51+
- `internal/runtime/executor/` should contain executors and their unit tests only. Place any helper/supporting files under `internal/runtime/executor/helps/`.
52+
- Follow `gofmt`; keep imports goimports-style; wrap errors with context where helpful
53+
- Do not use `log.Fatal`/`log.Fatalf` (terminates the process); prefer returning errors and logging via logrus
54+
- Shadowed variables: use method suffix (`errStart := server.Start()`)
55+
- Wrap defer errors: `defer func() { if err := f.Close(); err != nil { log.Errorf(...) } }()`
56+
- Use logrus structured logging; avoid leaking secrets/tokens in logs
57+
- Avoid panics in HTTP handlers; prefer logged errors and meaningful HTTP status codes
58+
- 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

0 commit comments

Comments
 (0)