From aa39af1c66041a69d7e6280f3a94765bcf6a112f Mon Sep 17 00:00:00 2001 From: pi-bot-01 Date: Sat, 14 Mar 2026 11:52:35 -0700 Subject: [PATCH] docs: fix stale env vars, add missing tools, expand README MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - TOOL.md: rename PI_WEBHOOK_*/PI_BOT_POLL_* → GITEA_* throughout - TOOL.md: add gitea_edit_issue, gitea_repo_config, gitea_tracked_repos - TOOL.md: split env vars into required/tools/webhook/openclaw sections - SKILL.md: add gitea_edit_issue and management tools to quick reference - SKILL.md: add close-issue step to triage workflow - SKILL.md: add Configure Bot Behavior section - README.md: add Runtime Detection table (pi-bot vs openclaw auto-detect) - README.md: add @mention routing section - README.md: add openclaw Docker install instructions - README.md: fix auth note (GITEA_WEBHOOK_TOKEN not PI_WEBHOOK_TOKEN) - README.md: split env table into required/core/webhook/openclaw sections --- README.md | 120 +++++++++++++++++++++++++++++++++++++++------- SKILL.md | 31 +++++++++--- TOOL.md | 140 +++++++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 246 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index 6b4285a..179b306 100644 --- a/README.md +++ b/README.md @@ -2,23 +2,45 @@ Consolidated Gitea API client and pi extension for git.dominat.us. -Provides a pure TypeScript Gitea API client (no external dependencies), a pi extension that registers tools for LLM use, and a standalone CLI. +Provides a pure TypeScript Gitea API client (zero external dependencies), a pi extension with 22 tools for LLM use, and a standalone CLI. Works as a pi extension in both **pi-bot** (persistent session, webhook server + notification polling) and **openclaw** (ephemeral sessions, tools-only). ## Structure ``` -src/ Core API client (pure fetch, token auth, zero deps) -pi-extension/ Pi extension adapter (registers tools + webhook server) -cli.ts Standalone CLI -SKILL.md Agent skill definition (auto-discovered by pi) -TOOL.md Tool reference documentation +src/ Core API client (pure fetch, token auth, zero deps) + client.ts GiteaClient class + request helpers + repos.ts Repo operations + issues.ts Issues + comments + pulls.ts Pull requests + actions.ts CI/Actions workflow runs + files.ts File read/write (POST for create, PUT for update) + webhooks.ts Webhook management + index.ts Re-exports + +pi-extension/ Pi extension adapter + index.ts Registers tools, lifecycle hooks, runtime detection + tools/ + read-tools.ts 8 read tools + write-tools.ts 12 write + management tools + webhook/ + server.ts Inbound webhook server, notification poller, @mention routing + +cli.ts Standalone CLI (replaces gitea-scripts/gitea.js) +SKILL.md Agent skill definition (auto-discovered by pi) +TOOL.md Full tool + environment variable reference ``` ## Installation ### As a pi extension -Add to your `settings.json`: +Symlink or copy `pi-extension/` into your `/extensions/` directory: + +```bash +ln -sf /path/to/gitea/pi-extension ~/.pi/agent/extensions/pi-gitea +``` + +Or add to `settings.json`: ```json { @@ -26,7 +48,19 @@ Add to your `settings.json`: } ``` -Or place/symlink `pi-extension/` into your `/extensions/` directory. +### In pi-bot (Docker) + +The `pi-bot` Dockerfile mounts the whole package and symlinks it: + +``` +-v /srv/pods/pi-bot/gitea:/app/gitea:Z +``` + +`entrypoint.sh` creates `~/.pi/agent/extensions/pi-gitea → /app/gitea/pi-extension` on startup. + +### In openclaw (Docker) + +The `openclaw-custom` Dockerfile copies `gitea/` into `/app/gitea/`. An entrypoint wrapper creates the symlink into `agentDir/extensions/pi-gitea` at container start. Webhook server + polling are disabled automatically (tools only); openclaw's hooks system handles inbound events. ### As a library @@ -35,7 +69,7 @@ import { GiteaClient, listRepos, getIssue } from "./src/index.js"; const client = new GiteaClient({ url: "https://git.dominat.us", - token: "your-token", + token: process.env.GITEA_TOKEN!, }); const repos = await listRepos(client); @@ -49,22 +83,76 @@ export GITEA_TOKEN="your-token" npx tsx cli.ts whoami npx tsx cli.ts repos npx tsx cli.ts issues owner/repo +npx tsx cli.ts issue owner/repo 42 npx tsx cli.ts create-issue owner/repo "Bug title" --body "Description" +npx tsx cli.ts comment owner/repo 42 "Fixed in #7" +npx tsx cli.ts close owner/repo 42 +npx tsx cli.ts prs owner/repo +npx tsx cli.ts runs owner/repo +npx tsx cli.ts logs owner/repo 1234 ``` +## Runtime Detection + +On `session_start` the extension auto-detects which runtime it's in: + +| Condition | Mode | Behaviour | +|-----------|------|-----------| +| `ctx.sendUserMessage` exists | **pi-bot** | Events injected directly into session; webhook server + notification poller start | +| `GITEA_HOOKS_URL` set | **openclaw** | Events POSTed to `GITEA_HOOKS_URL/hooks/agent`; no server/poller | +| `GITEA_ENABLE_POLLING=1` | forced polling | Webhook server + poller start regardless of other settings | + +## @mention Routing + +In collab repos (where the bot isn't the owner), the default response mode is `"mention"` — the bot only responds when its username appears as `@botname` in the text. Own repos default to `"all"`. + +Override per repo with the `gitea_repo_config` tool: + +``` +gitea_repo_config repo="oc/myrepo" respondTo="all" +``` + +## Authentication + +All API calls use `Authorization: token ` — no HMAC secrets. + +The inbound webhook endpoint optionally validates `Authorization: Bearer `. + ## Configuration +### Required + +| Variable | Purpose | +|----------|---------| +| `GITEA_TOKEN` | Gitea API token | + +### Core + | Variable | Purpose | Default | |----------|---------|---------| | `GITEA_URL` | Gitea instance URL | `https://git.dominat.us` | -| `GITEA_TOKEN` | API token (required) | — | -| `GITEA_OWNER` | Default repo owner | — | -| `GITEA_REPO` | Default repo name | — | +| `GITEA_USER` | Bot's own username (for @mention detection) | — | +| `GITEA_OWNER` | Default repo owner for tools | — | +| `GITEA_REPO` | Default repo name for tools | — | -See [TOOL.md](TOOL.md) for full tool documentation and [SKILL.md](SKILL.md) for the agent skill definition. +### pi-bot (webhook server + polling) -## Auth +| Variable | Purpose | Default | +|----------|---------|---------| +| `GITEA_WEBHOOK_HOST` | Bind address | `0.0.0.0` | +| `GITEA_WEBHOOK_PORT` | Inbound webhook port | `3000` | +| `GITEA_WEBHOOK_TOKEN` | Bearer token for webhook validation | — (open) | +| `GITEA_WEBHOOK_URL` | Public URL registered with Gitea | — | +| `GITEA_POLL_INTERVAL` | Repo discovery interval (seconds) | `300` | +| `GITEA_NOTIF_INTERVAL` | Notification poll interval (seconds) | `30` | -All API calls use `Authorization: token ` header. No HMAC secrets. +### openclaw (hooks delivery) -Webhook endpoint optionally validates with `Authorization: Bearer `. +| Variable | Purpose | Default | +|----------|---------|---------| +| `GITEA_HOOKS_URL` | openclaw gateway base URL | — | +| `GITEA_HOOKS_TOKEN` | Bearer token for the hooks endpoint | — | +| `GITEA_HOOKS_PATH` | Hooks endpoint path | `/hooks/agent` | +| `GITEA_ENABLE_POLLING` | Set `"1"` to force webhook server + polling | — | + +See [TOOL.md](TOOL.md) for the full tool reference and [SKILL.md](SKILL.md) for the agent skill definition. diff --git a/SKILL.md b/SKILL.md index 4ffa301..25eae6f 100644 --- a/SKILL.md +++ b/SKILL.md @@ -1,6 +1,6 @@ --- name: gitea -description: Interact with Gitea repositories, issues, PRs, CI runs, and files via git.dominat.us. Use when working with Gitea repos, triaging issues, reviewing PRs, checking CI logs, creating branches, updating files, or managing webhooks. +description: Interact with Gitea repositories, issues, PRs, CI runs, and files via git.dominat.us. Use when working with Gitea repos, triaging issues, reviewing PRs, checking CI logs, creating branches, updating files, managing webhooks, or configuring bot response behavior. --- # Gitea @@ -16,6 +16,7 @@ Tools for interacting with a Gitea instance (git.dominat.us by default). - Reading or updating files in a repo via the API - Creating branches for feature work - Setting up webhooks for event notifications +- Configuring which repos the bot monitors and how it responds ## Quick Reference @@ -42,12 +43,20 @@ See [TOOL.md](TOOL.md) for full parameter details on every tool. | `gitea_ensure_repo` | Get or create a repository | | `gitea_create_issue` | Open a new issue | | `gitea_create_issue_comment` | Comment on an issue or PR | +| `gitea_edit_issue` | Change title, body, or state of an issue | | `gitea_create_branch` | Create a branch | -| `gitea_update_file` | Create or update a file | +| `gitea_update_file` | Create or update a file (handles new vs existing automatically) | | `gitea_create_pr` | Open a pull request | | `gitea_merge_pr` | Merge a pull request | | `gitea_create_webhook` | Add a webhook to a repo | +### Management + +| Tool | Purpose | +|------|---------| +| `gitea_repo_config` | Set per-repo response mode (`"all"` or `"mention"`) | +| `gitea_tracked_repos` | List all tracked repos with type and response mode | + ## Common Workflows ### Triage an Issue @@ -55,30 +64,38 @@ See [TOOL.md](TOOL.md) for full parameter details on every tool. 1. `gitea_list_issues` to see open issues 2. `gitea_get_issue` to read details and comments 3. `gitea_create_issue_comment` to respond +4. `gitea_edit_issue` with `state: "closed"` when resolved ### Fix an Issue via PR 1. `gitea_get_issue` to understand the problem 2. `gitea_create_branch` to create a feature branch -3. `gitea_get_file_content` to read the file that needs fixing -4. `gitea_update_file` to push the fix (on the feature branch) +3. `gitea_get_file_content` to read the file(s) that need fixing (saves the SHA) +4. `gitea_update_file` to push the fix on the feature branch (pass the SHA for existing files) 5. `gitea_create_pr` to open a PR referencing the issue -6. `gitea_create_issue_comment` to note the fix +6. `gitea_edit_issue` with `state: "closed"` to close the issue ### Check CI Status 1. `gitea_list_runs` to see recent workflow runs 2. `gitea_get_run_logs` to read logs for a failing run -## Configuration +### Configure Bot Behavior -All tools use these environment variables for defaults: +- `gitea_tracked_repos` — see what the bot is monitoring +- `gitea_repo_config repo="owner/name" respondTo="all"` — respond to all events on this repo +- `gitea_repo_config repo="owner/name" respondTo="mention"` — only respond when @mentioned + +## Configuration | Variable | Purpose | Default | |----------|---------|---------| | `GITEA_URL` | Gitea instance URL | `https://git.dominat.us` | | `GITEA_TOKEN` | API token (required) | — | +| `GITEA_USER` | Bot's own username | — | | `GITEA_OWNER` | Default repo owner | — | | `GITEA_REPO` | Default repo name | — | Most tools accept `owner` and `repo` parameters to override defaults per-call. + +See [TOOL.md](TOOL.md) for the full environment variable reference including webhook server and openclaw hooks settings. diff --git a/TOOL.md b/TOOL.md index 4b59073..e3778c0 100644 --- a/TOOL.md +++ b/TOOL.md @@ -1,7 +1,7 @@ # Gitea Tools Reference -All tools use token-based authentication via `GITEA_TOKEN` environment variable. -Owner and repo parameters default to `GITEA_OWNER` and `GITEA_REPO` env vars when omitted. +All tools authenticate via `GITEA_TOKEN`. `owner` and `repo` parameters fall back to +`GITEA_OWNER` / `GITEA_REPO` env vars when omitted. --- @@ -16,6 +16,8 @@ List repositories accessible to you, or public repos for a specific owner. | `owner` | string | No | authenticated user | Owner to list repos for | | `limit` | number | No | 50 | Max results | +--- + ### `gitea_list_issues` List issues for a repository. @@ -27,6 +29,8 @@ List issues for a repository. | `state` | `"open"` \| `"closed"` \| `"all"` | No | `"open"` | Issue state filter | | `limit` | number | No | 20 | Max results | +--- + ### `gitea_get_issue` Get a single issue by number, including all comments. @@ -39,6 +43,8 @@ Get a single issue by number, including all comments. **Returns:** Issue title, state, author, labels, body, and all comments. +--- + ### `gitea_list_prs` List pull requests for a repository. @@ -49,6 +55,8 @@ List pull requests for a repository. | `repo` | string | No | `GITEA_REPO` | Repo name | | `state` | `"open"` \| `"closed"` \| `"all"` | No | `"open"` | PR state filter | +--- + ### `gitea_get_pr` Get a single pull request by number, including comments. @@ -61,6 +69,8 @@ Get a single pull request by number, including comments. **Returns:** PR title, state, author, head/base branches, merge status, body, and all comments. +--- + ### `gitea_list_runs` List recent CI/Actions workflow runs. @@ -71,6 +81,8 @@ List recent CI/Actions workflow runs. | `repo` | string | No | `GITEA_REPO` | Repo name | | `limit` | number | No | 10 | Max results | +--- + ### `gitea_get_run_logs` Get full log output for a workflow run (fetches all jobs, downloads each job's logs). @@ -81,6 +93,8 @@ Get full log output for a workflow run (fetches all jobs, downloads each job's l | `owner` | string | No | `GITEA_OWNER` | Repo owner | | `repo` | string | No | `GITEA_REPO` | Repo name | +--- + ### `gitea_get_file_content` Get file content from a repository. @@ -108,6 +122,8 @@ Create a new repository for the authenticated user. | `private` | boolean | No | `false` | Private repository | | `description` | string | No | `""` | Repository description | +--- + ### `gitea_ensure_repo` Get a repository if it exists, create it if not. Returns clone URL. @@ -118,6 +134,8 @@ Get a repository if it exists, create it if not. Returns clone URL. | `owner` | string | No | `GITEA_OWNER` | Repo owner | | `private` | boolean | No | `false` | Private if creating | +--- + ### `gitea_create_issue` Create a new issue in a repository. @@ -129,6 +147,8 @@ Create a new issue in a repository. | `repo` | string | No | `GITEA_REPO` | Repo name | | `body` | string | No | `""` | Issue body (Markdown) | +--- + ### `gitea_create_issue_comment` Post a comment on an issue or pull request. @@ -140,6 +160,25 @@ Post a comment on an issue or pull request. | `owner` | string | No | `GITEA_OWNER` | Repo owner | | `repo` | string | No | `GITEA_REPO` | Repo name | +--- + +### `gitea_edit_issue` + +Edit an issue — change its title, body, or state. Use to close issues when work is done. + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `index` | number | **Yes** | — | Issue number | +| `owner` | string | No | `GITEA_OWNER` | Repo owner | +| `repo` | string | No | `GITEA_REPO` | Repo name | +| `title` | string | No | unchanged | New title | +| `body` | string | No | unchanged | New body (Markdown) | +| `state` | `"open"` \| `"closed"` | No | unchanged | New state | + +**Note:** All edit fields are optional — only supplied fields are changed. + +--- + ### `gitea_create_branch` Create a new branch from an existing ref. @@ -149,21 +188,27 @@ Create a new branch from an existing ref. | `branch` | string | **Yes** | — | Name for the new branch | | `owner` | string | No | `GITEA_OWNER` | Repo owner | | `repo` | string | No | `GITEA_REPO` | Repo name | -| `ref` | string | No | `"main"` | Source branch | +| `ref` | string | No | `"main"` | Source branch or SHA | + +--- ### `gitea_update_file` -Create or update a file in a repository. For updates, you must provide the current file's SHA (get it from `gitea_get_file_content`). +Create or update a file in a repository. | Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | `path` | string | **Yes** | — | File path | -| `content` | string | **Yes** | — | File content | +| `content` | string | **Yes** | — | File content (plain text, not base64) | | `message` | string | **Yes** | — | Commit message | | `owner` | string | No | `GITEA_OWNER` | Repo owner | | `repo` | string | No | `GITEA_REPO` | Repo name | | `branch` | string | No | `"main"` | Target branch | -| `sha` | string | No | — | Current file SHA (required for updates) | +| `sha` | string | No | — | Current file SHA — omit for new files, required for updates | + +**Tip:** Get the SHA for an existing file with `gitea_get_file_content` first. + +--- ### `gitea_create_pr` @@ -176,7 +221,9 @@ Create a pull request. | `base` | string | **Yes** | — | Target branch | | `owner` | string | No | `GITEA_OWNER` | Repo owner | | `repo` | string | No | `GITEA_REPO` | Repo name | -| `body` | string | No | `""` | PR description | +| `body` | string | No | `""` | PR description (Markdown) | + +--- ### `gitea_merge_pr` @@ -189,34 +236,83 @@ Merge a pull request. | `repo` | string | No | `GITEA_REPO` | Repo name | | `merge_method` | `"merge"` \| `"rebase"` \| `"squash"` | No | `"merge"` | Merge strategy | +--- + ### `gitea_create_webhook` -Create a webhook on a repository. Uses bearer token auth (not HMAC secrets). +Create a webhook on a repository (bearer token auth, not HMAC). | Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | `url` | string | **Yes** | — | Webhook delivery URL | | `owner` | string | No | `GITEA_OWNER` | Repo owner | | `repo` | string | No | `GITEA_REPO` | Repo name | -| `token` | string | No | — | Bearer token for webhook auth | -| `events` | string[] | No | `["issues", "issue_comment", "pull_request", "push"]` | Events to listen for | +| `token` | string | No | — | Bearer token for webhook validation | +| `events` | string[] | No | `["issues","issue_comment","pull_request","push"]` | Events to subscribe to | --- -## Authentication +## Management Tools -All API calls use `Authorization: token ` header. +### `gitea_repo_config` -Webhook endpoint uses `Authorization: Bearer ` for incoming request validation (optional — if not set, endpoint is open). +Set how the bot responds to events on a repo. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `repo` | string | **Yes** | Repository (`owner/name`) | +| `respondTo` | `"all"` \| `"mention"` | **Yes** | Response mode | + +- `"all"` — respond to every issue/PR/comment event +- `"mention"` — respond only when `@botname` appears in the text, or when assigned + +**Defaults:** Repos where the bot is owner default to `"all"`; collab repos default to `"mention"`. + +--- + +### `gitea_tracked_repos` + +List all repos the bot is currently tracking, with their type and response mode. + +No parameters. + +**Returns:** Each tracked repo's name, type (`webhook` or `collab`), and `respondTo` setting. + +--- + +## Environment Variables + +### Required | Variable | Purpose | |----------|---------| -| `GITEA_URL` | Gitea instance URL (default: `https://git.dominat.us`) | -| `GITEA_TOKEN` | Gitea API token (**required**) | -| `GITEA_OWNER` | Default repo owner | -| `GITEA_REPO` | Default repo name | -| `PI_WEBHOOK_TOKEN` | Bearer token to validate inbound webhooks (optional) | -| `PI_WEBHOOK_HOST` | Webhook server bind host (default: `0.0.0.0`) | -| `PI_WEBHOOK_PORT` | Webhook server port (default: `3000`) | -| `PI_WEBHOOK_URL` | Public URL for webhook registration (used by auto-polling) | -| `PI_BOT_POLL_INTERVAL` | Polling interval in seconds for new repos (default: `300`) | +| `GITEA_TOKEN` | API token for all Gitea API calls | + +### Defaults (tools) + +| Variable | Purpose | Default | +|----------|---------|---------| +| `GITEA_URL` | Gitea instance URL | `https://git.dominat.us` | +| `GITEA_OWNER` | Default repo owner | — | +| `GITEA_REPO` | Default repo name | — | +| `GITEA_USER` | Bot's own username (for @mention detection) | — | + +### Webhook server (pi-bot mode) + +| Variable | Purpose | Default | +|----------|---------|---------| +| `GITEA_WEBHOOK_HOST` | Bind address for inbound webhook server | `0.0.0.0` | +| `GITEA_WEBHOOK_PORT` | Port for inbound webhook server | `3000` | +| `GITEA_WEBHOOK_TOKEN` | Bearer token to validate inbound webhook requests | — (open) | +| `GITEA_WEBHOOK_URL` | Public URL registered with Gitea repos | — | +| `GITEA_POLL_INTERVAL` | Repo discovery interval in seconds | `300` | +| `GITEA_NOTIF_INTERVAL` | Notification polling interval in seconds | `30` | + +### openclaw / hooks mode + +| Variable | Purpose | Default | +|----------|---------|---------| +| `GITEA_HOOKS_URL` | openclaw gateway URL to POST events to | — | +| `GITEA_HOOKS_TOKEN` | Bearer token for the openclaw hooks endpoint | — | +| `GITEA_HOOKS_PATH` | Path on the hooks endpoint | `/hooks/agent` | +| `GITEA_ENABLE_POLLING` | Set to `"1"` to force webhook server + polling even when `GITEA_HOOKS_URL` is set | — |