@clawhub-montycn-5d2001fa43
Manage the Tuwunel Matrix Homeserver (register users, create rooms, manage room membership, upload files to media server). Use only for explicit standalone a...
---
name: matrix-server-management
description: Manage the Tuwunel Matrix Homeserver (register users, create rooms, manage room membership, upload files to media server). Use only for explicit standalone admin requests — Worker and project creation handle Matrix operations internally via their own scripts. Also use this skill whenever you need to send a file to the admin (upload via media API, then send as m.file message).
---
# Matrix Server Management
## Overview
This skill allows you to manage the Tuwunel Matrix Homeserver. Tuwunel is a conduwuit fork running at `http://127.0.0.1:6167`. Access the server directly (not through the Higress gateway).
## Environment Variables
These environment variables are pre-configured in the Manager container:
```bash
# Core configuration (set by hiclaw-install.sh)
HICLAW_MATRIX_DOMAIN # Matrix server domain (e.g., matrix-local.hiclaw.io:8080)
HICLAW_ADMIN_USER # Admin username
HICLAW_REGISTRATION_TOKEN # Token for registering new Matrix users
HICLAW_MANAGER_PASSWORD # Manager's Matrix password (for login)
```
No need to set defaults - these are always available in the container environment.
## User Registration
Tuwunel uses **single-step registration** with a registration token (no UIAA flow).
### Register a New User
```bash
curl -X POST http://127.0.0.1:6167/_matrix/client/v3/register \
-H 'Content-Type: application/json' \
-d '{
"username": "<USERNAME>",
"password": "<PASSWORD>",
"auth": {
"type": "m.login.registration_token",
"token": "'"HICLAW_REGISTRATION_TOKEN"'"
}
}'
```
Response includes `user_id` and `access_token`.
### Login (Get Access Token)
```bash
curl -X POST http://127.0.0.1:6167/_matrix/client/v3/login \
-H 'Content-Type: application/json' \
-d '{
"type": "m.login.password",
"identifier": {"type": "m.id.user", "user": "<USERNAME>"},
"password": "<PASSWORD>"
}'
```
Response: `{"access_token": "...", "user_id": "@<USERNAME>:<DOMAIN>", ...}`
## Room Management
### Create a Room (3-party: Human + Manager + Worker)
When creating a Worker, always create a Room with the human admin, Manager, and Worker. Use `trusted_private_chat` preset so all invited members are auto-joined (no invite acceptance needed), and override power levels so Admin + Manager get 100 (admin) while Workers get 0 (regular user):
```bash
MANAGER_TOKEN="<manager_access_token>"
curl -X POST http://127.0.0.1:6167/_matrix/client/v3/createRoom \
-H "Authorization: Bearer MANAGER_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"name": "Worker: <WORKER_NAME>",
"topic": "Communication channel for <WORKER_NAME>",
"invite": [
"@'"HICLAW_ADMIN_USER"':'"HICLAW_MATRIX_DOMAIN"'",
"@<WORKER_NAME>:'"HICLAW_MATRIX_DOMAIN"'"
],
"preset": "trusted_private_chat",
"power_level_content_override": {
"users": {
"@manager:'"HICLAW_MATRIX_DOMAIN"'": 100,
"@'"HICLAW_ADMIN_USER"':'"HICLAW_MATRIX_DOMAIN"'": 100,
"@<WORKER_NAME>:'"HICLAW_MATRIX_DOMAIN"'": 0
}
}
}'
```
Response: `{"room_id": "!<id>:<DOMAIN>"}`
**Power levels:** `trusted_private_chat` auto-joins all invited members (no invite acceptance needed). `power_level_content_override` ensures Admin (100) and Manager (100) have admin rights while Workers are explicitly set to 0 (regular user).
### Send a Message in a Room
**Simple message (no mention):**
```bash
curl -X PUT "http://127.0.0.1:6167/_matrix/client/v3/rooms/<ROOM_ID>/send/m.room.message/$(date +%s)" \
-H "Authorization: Bearer MANAGER_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"msgtype": "m.text",
"body": "Hello, this is a general announcement..."
}'
```
### Send a Message with @Mention (Critical for Workers)
**IMPORTANT**: When sending messages to Workers in group rooms, you MUST include the `m.mentions` field for them to receive the message. Workers have `requireMention: true` enabled, meaning they only process messages that properly @mention them.
```bash
# Mention a single user
curl -X PUT "http://127.0.0.1:6167/_matrix/client/v3/rooms/<ROOM_ID>/send/m.room.message/$(date +%s)" \
-H "Authorization: Bearer MANAGER_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"msgtype": "m.text",
"body": "@<WORKER_NAME>:'"HICLAW_MATRIX_DOMAIN"' Your task assignment: ...",
"m.mentions": {
"user_ids": ["@<WORKER_NAME>:'"HICLAW_MATRIX_DOMAIN"'"]
}
}'
```
```bash
# Mention multiple users
curl -X PUT "http://127.0.0.1:6167/_matrix/client/v3/rooms/<ROOM_ID>/send/m.room.message/$(date +%s)" \
-H "Authorization: Bearer MANAGER_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"msgtype": "m.text",
"body": "@alice:'"HICLAW_MATRIX_DOMAIN"' and @bob:'"HICLAW_MATRIX_DOMAIN"' please coordinate on this task...",
"m.mentions": {
"user_ids": [
"@alice:'"HICLAW_MATRIX_DOMAIN"'",
"@bob:'"HICLAW_MATRIX_DOMAIN"'"
]
}
}'
```
**Rules for @mentions:**
- The `user_ids` array in `m.mentions` MUST contain the full Matrix user ID (e.g., `@alice:matrix-local.hiclaw.io:8080`)
- The user ID in the body text and in `m.mentions.user_ids` must match exactly
- Without `m.mentions`, Workers will receive the message but will NOT process it (it will be ignored)
- This follows Matrix MSC3952 (Intentional Mentions) specification
### Upload a File (Media Upload)
Use this to send files to the admin — task output artifacts, generated reports, config exports, log files, etc.
```bash
curl -X POST "http://127.0.0.1:6167/_matrix/media/v3/upload?filename=<FILENAME>" \
-H "Authorization: Bearer MANAGER_TOKEN" \
-H "Content-Type: application/octet-stream" \
--data-binary @/path/to/file
```
Response: `{"content_uri": "mxc://<SERVER>/<MEDIA_ID>"}`
After uploading, send the `mxc://` URI to the admin as a Matrix message using the `m.file` (or `m.image` / `m.text`) msgtype:
```bash
curl -X PUT "http://127.0.0.1:6167/_matrix/client/v3/rooms/<ROOM_ID>/send/m.room.message/$(date +%s)" \
-H "Authorization: Bearer MANAGER_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"msgtype": "m.file",
"body": "<FILENAME>",
"url": "mxc://<SERVER>/<MEDIA_ID>"
}'
```
Then reply in the conversation with:
```
MEDIA: mxc://<SERVER>/<MEDIA_ID>
```
**Notes:**
- Use `Content-Type: text/plain` for plain text files, `application/octet-stream` as a safe fallback for any binary
- The `mxc://` URI is permanent and accessible to all room members via the Matrix client (Element Web)
### List Joined Rooms
```bash
curl -s http://127.0.0.1:6167/_matrix/client/v3/joined_rooms \
-H "Authorization: Bearer MANAGER_TOKEN" | jq
```
### Get Room Messages
```bash
curl -s "http://127.0.0.1:6167/_matrix/client/v3/rooms/<ROOM_ID>/messages?dir=b&limit=20" \
-H "Authorization: Bearer MANAGER_TOKEN" | jq
```
## Important Notes
- **Environment prefix**: Tuwunel uses `CONDUWUIT_` environment variable prefix (NOT `TUWUNEL_`)
- **Server name**: Set in `CONDUWUIT_SERVER_NAME`, usually `HICLAW_MATRIX_DOMAIN`
- **User ID format**: `@<username>:HICLAW_MATRIX_DOMAIN`
- **Registration token**: Stored in `HICLAW_REGISTRATION_TOKEN` env var
- **Direct access**: Use `http://127.0.0.1:6167` for server management (not through Higress Gateway port 8080)
<!-- hiclaw-builtin-end -->
FILE:_meta.json
{"ownerId": "local", "slug": "matrix-server-management", "version": "1.0.0", "publishedAt": 1773995073000}
Manage the Higress AI Gateway via its Console API (consumers, routes, AI providers, MCP servers). Use when creating consumers, configuring routes, or managin...
--- name: higress-gateway-management description: Manage the Higress AI Gateway via its Console API (consumers, routes, AI providers, MCP servers). Use when creating consumers, configuring routes, or managing AI gateway settings. --- # Higress AI Gateway Management ## Overview This skill allows you to manage the Higress AI Gateway via its Console API. The Console API runs at `http://127.0.0.1:8001` and uses **Session Cookie** authentication (NOT Basic Auth). ## Environment Variables These environment variables are pre-configured in the Manager container. Access them directly in bash: ```bash # Core configuration (set by hiclaw-install.sh) HICLAW_ADMIN_USER # Admin username for Higress Console HICLAW_ADMIN_PASSWORD # Admin password for Higress Console HICLAW_AI_GATEWAY_DOMAIN # AI Gateway domain (e.g., aigw-local.hiclaw.io) HIGRESS_COOKIE_FILE # Path to session cookie file ``` No need to set defaults - these are always available in the container environment. ## Authentication A session cookie file is stored at the path in `HIGRESS_COOKIE_FILE` environment variable. Use it with `curl -b "HIGRESS_COOKIE_FILE"`. If the cookie expires, re-login: ```bash curl -X POST http://127.0.0.1:8001/session/login \ -H 'Content-Type: application/json' \ -c "HIGRESS_COOKIE_FILE" \ -d '{"name": "'"HICLAW_ADMIN_USER"'", "password": "'"HICLAW_ADMIN_PASSWORD"'"}' ``` ## Consumer Management ### List Consumers ```bash curl -s http://127.0.0.1:8001/v1/consumers -b "HIGRESS_COOKIE_FILE" | jq ``` ### Create Consumer ```bash curl -X POST http://127.0.0.1:8001/v1/consumers \ -b "HIGRESS_COOKIE_FILE" \ -H 'Content-Type: application/json' \ -d '{ "name": "worker-alice", "credentials": [{ "type": "key-auth", "source": "BEARER", "values": ["<GENERATED_KEY>"] }] }' ``` ### Update Consumer (e.g., replace credential key) ```bash # GET-modify-PUT pattern (consumers do NOT have a version field) NEW_KEY=$(openssl rand -hex 32) CONSUMER=$(curl -s http://127.0.0.1:8001/v1/consumers/worker-alice -b "HIGRESS_COOKIE_FILE") UPDATED=$(echo $CONSUMER | jq --arg new "$NEW_KEY" '.credentials[0].values = [$new]') curl -X PUT http://127.0.0.1:8001/v1/consumers/worker-alice \ -b "HIGRESS_COOKIE_FILE" \ -H 'Content-Type: application/json' \ -d "$UPDATED" ``` ### Delete Consumer ```bash curl -X DELETE http://127.0.0.1:8001/v1/consumers/worker-alice -b "HIGRESS_COOKIE_FILE" ``` ## AI Route Management AI routes are **internal routes** managed via a separate API at `/v1/ai/routes`. They define LLM provider routing with model-level predicates, domain matching, and consumer auth. **Do NOT use `/v1/routes` for AI routes.** ### List AI Routes ```bash curl -s http://127.0.0.1:8001/v1/ai/routes -b "HIGRESS_COOKIE_FILE" | jq ``` ### Get AI Route by Name ```bash curl -s http://127.0.0.1:8001/v1/ai/routes/default-ai-route -b "HIGRESS_COOKIE_FILE" | jq ``` ### Create AI Route The system initializes with a `default-ai-route` that has no `modelPredicates` — all model requests go through it. When the human asks to add a **new provider**, create a separate AI route with `modelPredicates` to distinguish which models go where: ```bash # Example: add a DeepSeek route alongside the existing default route curl -X POST http://127.0.0.1:8001/v1/ai/routes \ -b "HIGRESS_COOKIE_FILE" \ -H 'Content-Type: application/json' \ -d '{ "name": "deepseek-route", "domains": ["HICLAW_AI_GATEWAY_DOMAIN"], "pathPredicate": {"matchType": "PRE", "matchValue": "/", "caseSensitive": false}, "upstreams": [{"provider": "deepseek", "weight": 100, "modelMapping": {}}], "modelPredicates": [{"matchType": "PRE", "matchValue": "deepseek"}], "authConfig": { "enabled": true, "allowedCredentialTypes": ["key-auth"], "allowedConsumers": ["manager"] } }' ``` When adding a new provider route with `modelPredicates`, also update the `default-ai-route` to add matching `modelPredicates` for its own models, so routes are unambiguous. Key fields: - **domains**: which domain(s) this AI route serves (e.g. `HICLAW_AI_GATEWAY_DOMAIN`) - **upstreams**: LLM provider(s) with weight and optional model mapping - **modelPredicates**: match models by prefix/exact/regex (e.g. `{"matchType":"PRE","matchValue":"deepseek"}` routes all `deepseek*` models). Omit when only one route exists - **authConfig**: consumer-level access control ### Update AI Route (e.g., grant Worker access) ```bash # Step 1: GET current AI route AI_ROUTE=$(curl -s http://127.0.0.1:8001/v1/ai/routes/default-ai-route -b "HIGRESS_COOKIE_FILE") # Step 2: Add worker-alice to allowedConsumers UPDATED=$(echo $AI_ROUTE | jq '.authConfig.allowedConsumers += ["worker-alice"]') # Step 3: PUT full object (AI Route has "version" field, include it) curl -X PUT http://127.0.0.1:8001/v1/ai/routes/default-ai-route \ -b "HIGRESS_COOKIE_FILE" \ -H 'Content-Type: application/json' \ -d "$UPDATED" ``` ### Delete AI Route ```bash curl -X DELETE http://127.0.0.1:8001/v1/ai/routes/<route-name> -b "HIGRESS_COOKIE_FILE" ``` ## LLM Provider Configuration ### List AI Providers ```bash curl -s http://127.0.0.1:8001/v1/ai/providers -b "HIGRESS_COOKIE_FILE" | jq ``` ### Create Provider ```bash # Qwen (native type) curl -X POST http://127.0.0.1:8001/v1/ai/providers \ -b "HIGRESS_COOKIE_FILE" \ -H 'Content-Type: application/json' \ -d '{ "type": "qwen", "name": "qwen", "tokens": ["<API_KEY>"], "protocol": "openai/v1", "tokenFailoverConfig": {"enabled": false}, "rawConfigs": {"qwenEnableSearch": false, "qwenEnableCompatible": true, "qwenFileIds": []} }' # OpenAI-compatible (generic) curl -X POST http://127.0.0.1:8001/v1/ai/providers \ -b "HIGRESS_COOKIE_FILE" \ -H 'Content-Type: application/json' \ -d '{ "type": "openai", "name": "my-provider", "tokens": ["<API_KEY>"], "protocol": "openai/v1", "modelMapping": {}, "rawConfigs": {"apiUrl": "https://api.example.com/v1"} }' ``` ### Update Provider (e.g., rotate API keys) ```bash # GET-modify-PUT pattern (provider has "version" field) PROVIDER=$(curl -s http://127.0.0.1:8001/v1/ai/providers/qwen -b "HIGRESS_COOKIE_FILE") UPDATED=$(echo $PROVIDER | jq '.tokens = ["<NEW_KEY>"]') curl -X PUT http://127.0.0.1:8001/v1/ai/providers/qwen \ -b "HIGRESS_COOKIE_FILE" \ -H 'Content-Type: application/json' \ -d "$UPDATED" ``` ## MCP Server Management For creating, updating, listing, and deleting MCP Servers, as well as managing consumer access to MCP tools, see the **`mcp-server-management`** skill. ## Important Notes - **Auth Plugin Activation**: First configuration takes ~40s, subsequent changes ~10s - **Version field**: AI Routes and Providers have a `version` field. Always GET before PUT to get the latest version. - **Consumer version**: Consumers do NOT have a `version` field - **MCP Server**: See `mcp-server-management` skill for full details on creating and managing MCP servers <!-- hiclaw-builtin-end --> FILE:_meta.json {"ownerId": "local", "slug": "higress-gateway-management", "version": "1.0.0", "publishedAt": 1773996579000} FILE:references/higress-api-doc.json { "openapi": "3.0.1", "info": { "title": "Higress Console", "description": "Higress is a next-generation cloud-native gateway based on Alibaba's internal gateway practices.", "contact": { "name": "Higress Authors", "url": "https://github.com/higress-group/higress-console" }, "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0" } }, "servers": [ { "url": "http://localhost:8080", "description": "Generated server url" } ], "paths": { "/v1/wasm-plugins/{name}": { "get": { "tags": [ "Wasm Plugin APIs" ], "summary": "Get Wasm plugin by name", "operationId": "query", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "lang", "in": "query", "description": "Available languages: zh-CN/en-US", "required": false, "schema": { "type": "string" } } ], "responses": { "404": { "description": "Plugin not found", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseWasmPlugin" } } } }, "200": { "description": "Plugin found", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseWasmPlugin" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseWasmPlugin" } } } } } }, "put": { "tags": [ "Wasm Plugin APIs" ], "summary": "Update an existed plugin", "operationId": "update", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WasmPlugin" } } }, "required": true }, "responses": { "200": { "description": "Plugin updated successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseWasmPlugin" } } } }, "400": { "description": "Plugin data is not valid or plugin name in the URL doesn't match the one in the body.", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseWasmPlugin" } } } }, "409": { "description": "Plugin already existed with the same name.", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseWasmPlugin" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseWasmPlugin" } } } } } }, "delete": { "tags": [ "Wasm Plugin APIs" ], "summary": "Delete a custom plugin", "operationId": "delete", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "204": { "description": "Plugin deleted successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseWasmPluginConfig" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseWasmPluginConfig" } } } } } } }, "/v1/tls-certificates/{name}": { "get": { "tags": [ "TLS Certificate APIs" ], "summary": "Get TLS certificate by name", "operationId": "query_1", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "404": { "description": "TLS certificate not found", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseTlsCertificate" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseTlsCertificate" } } } }, "200": { "description": "TLS certificate found", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseTlsCertificate" } } } } } }, "put": { "tags": [ "TLS Certificate APIs" ], "summary": "Update an existed TLS certificate", "operationId": "put", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TlsCertificate" } } }, "required": true }, "responses": { "200": { "description": "TLS certificate updated successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseTlsCertificate" } } } }, "400": { "description": "TLS certificate data is not valid or TLS certificate name in the URL doesn't match the one in the body.", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseTlsCertificate" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseTlsCertificate" } } } }, "409": { "description": "TLS certificate already existed with the same name.", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseTlsCertificate" } } } } } }, "delete": { "tags": [ "TLS Certificate APIs" ], "summary": "Delete a TLS certificate", "operationId": "delete_1", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseTlsCertificate" } } } }, "204": { "description": "TLS certificate deleted successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseTlsCertificate" } } } } } } }, "/v1/services/{serviceName}/plugin-instances/{name}": { "get": { "tags": [ "Wasm Plugin Instance APIs" ], "summary": "Get a specific service-bound plugin instance", "operationId": "queryServiceInstance", "parameters": [ { "name": "serviceName", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Instances retrieved successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseWasmPluginInstance" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseWasmPluginInstance" } } } } } }, "put": { "tags": [ "Wasm Plugin Instance APIs" ], "summary": "Add or update a specific service-bound plugin instance", "operationId": "addOrUpdateServiceInstance", "parameters": [ { "name": "serviceName", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WasmPluginInstance" } } }, "required": true }, "responses": { "200": { "description": "Instances retrieved successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseWasmPluginInstance" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseWasmPluginInstance" } } } } } }, "delete": { "tags": [ "Wasm Plugin Instance APIs" ], "summary": "Delete a service-bound plugin instance", "operationId": "deleteServiceInstance", "parameters": [ { "name": "serviceName", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "204": { "description": "Instance deleted successfully" }, "500": { "description": "Internal server error" } } } }, "/v1/service-sources/{name}": { "get": { "tags": [ "Service Source APIs" ], "summary": "Get service source by name", "operationId": "query_2", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "404": { "description": "Service source not found", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseServiceSource" } } } }, "200": { "description": "Service source found", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseServiceSource" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseServiceSource" } } } } } }, "put": { "tags": [ "Service Source APIs" ], "summary": "Update an existed service source", "operationId": "addOrUpdate", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServiceSource" } } }, "required": true }, "responses": { "409": { "description": "Service source trying to add already existed", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseServiceSource" } } } }, "400": { "description": "Service source data is not valid", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseServiceSource" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseServiceSource" } } } }, "200": { "description": "Service source updated successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseServiceSource" } } } } } }, "delete": { "tags": [ "Service Source APIs" ], "summary": "Delete a service source", "operationId": "delete_2", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "400": { "description": "Deleting an internal service source is not allowed.", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseServiceSource" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseServiceSource" } } } }, "204": { "description": "Service source deleted successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseServiceSource" } } } } } } }, "/v1/routes/{routeName}/plugin-instances/{name}": { "get": { "tags": [ "Wasm Plugin Instance APIs" ], "summary": "Get a specific route-bound plugin instance", "operationId": "queryRouteInstance", "parameters": [ { "name": "routeName", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Instances retrieved successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseWasmPluginInstance" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseWasmPluginInstance" } } } } } }, "put": { "tags": [ "Wasm Plugin Instance APIs" ], "summary": "Add or update a specific route-bound plugin instance", "operationId": "addOrUpdateRouteInstance", "parameters": [ { "name": "routeName", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WasmPluginInstance" } } }, "required": true }, "responses": { "200": { "description": "Instances retrieved successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseWasmPluginInstance" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseWasmPluginInstance" } } } } } }, "delete": { "tags": [ "Wasm Plugin Instance APIs" ], "summary": "Delete a route-bound plugin instance", "operationId": "deleteRouteInstance", "parameters": [ { "name": "routeName", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "204": { "description": "Instance deleted successfully" }, "500": { "description": "Internal server error" } } } }, "/v1/routes/{name}": { "get": { "tags": [ "Route APIs" ], "summary": "Get route by name", "operationId": "query_3", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "404": { "description": "Route not found", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseRoute" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseRoute" } } } }, "200": { "description": "Route found", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseRoute" } } } } } }, "put": { "tags": [ "Route APIs" ], "summary": "Update an existed route", "operationId": "update_1", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Route" } } }, "required": true }, "responses": { "409": { "description": "Route already existed with the same name.", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseRoute" } } } }, "200": { "description": "Route updated successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseRoute" } } } }, "400": { "description": "Route data is not valid or route name in the URL doesn't match the one in the body.", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseRoute" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseRoute" } } } } } }, "delete": { "tags": [ "Route APIs" ], "summary": "Delete a route", "operationId": "delete_3", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "400": { "description": "Deleting an internal route is not allowed.", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseRoute" } } } }, "204": { "description": "Route deleted successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseRoute" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseRoute" } } } } } } }, "/v1/proxy-servers/{name}": { "get": { "tags": [ "Proxy Server APIs" ], "summary": "Get proxy server by name", "operationId": "query_4", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "404": { "description": "Proxy server not found", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseProxyServer" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseProxyServer" } } } }, "200": { "description": "Proxy server found", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseProxyServer" } } } } } }, "put": { "tags": [ "Proxy Server APIs" ], "summary": "Update an existed proxy server", "operationId": "addOrUpdate_1", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProxyServer" } } }, "required": true }, "responses": { "400": { "description": "Proxy server data is not valid", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseProxyServer" } } } }, "200": { "description": "Proxy server updated successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseProxyServer" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseProxyServer" } } } }, "409": { "description": "Proxy server trying to add already existed", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseProxyServer" } } } } } }, "delete": { "tags": [ "Proxy Server APIs" ], "summary": "Delete a proxy server", "operationId": "delete_4", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "204": { "description": "Proxy server deleted successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseProxyServer" } } } }, "400": { "description": "Deleting an internal proxy server is not allowed.", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseProxyServer" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseProxyServer" } } } } } } }, "/v1/mcpServer": { "get": { "tags": [ "Mcp APIs" ], "summary": "List mcp server", "operationId": "list_6", "parameters": [ { "name": "mcpServerName", "in": "query", "description": "McpServer name associated with route.", "required": false, "schema": { "type": "string", "description": "McpServer name associated with route." } }, { "name": "type", "in": "query", "description": "Mcp server type", "required": false, "schema": { "type": "string", "description": "Mcp server type" } }, { "name": "pageNum", "in": "query", "description": "Page number, starting from 1. If omitted, all items will be returned.", "required": false, "schema": { "type": "string", "description": "Page number, starting from 1. If omitted, all items will be returned." } }, { "name": "pageSize", "in": "query", "description": "Number of items per page. If omitted, all items will be returned.", "required": false, "schema": { "type": "string", "description": "Number of items per page. If omitted, all items will be returned." } } ], "responses": { "200": { "description": "McpServers listed successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/PaginatedResponseMcpServer" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/PaginatedResponseMcpServer" } } } } } }, "put": { "tags": [ "Mcp APIs" ], "summary": "Add or update a mcp server instance", "operationId": "addOrUpdateMcpInstance", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/McpServer" } } }, "required": true }, "responses": { "200": { "description": "Instances saved successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseMcpServer" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseMcpServer" } } } } } } }, "/v1/mcpServer/consumers": { "get": { "tags": [ "Mcp APIs" ], "summary": "List mcp server allow consumers", "operationId": "listAllowConsumers", "parameters": [ { "name": "mcpServerName", "in": "query", "description": "McpServer name associated with route.", "required": false, "schema": { "type": "string", "description": "McpServer name associated with route." } }, { "name": "consumerName", "in": "query", "description": "Consumer name for search.", "required": false, "schema": { "type": "string", "description": "Consumer name for search." } }, { "name": "pageNum", "in": "query", "description": "Page number, starting from 1. If omitted, all items will be returned.", "required": false, "schema": { "type": "string", "description": "Page number, starting from 1. If omitted, all items will be returned." } }, { "name": "pageSize", "in": "query", "description": "Number of items per page. If omitted, all items will be returned.", "required": false, "schema": { "type": "string", "description": "Number of items per page. If omitted, all items will be returned." } } ], "responses": { "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/PaginatedResponseMcpServerConsumerDetail" } } } }, "200": { "description": "List mcp server allow consumers successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/PaginatedResponseMcpServerConsumerDetail" } } } } } }, "put": { "tags": [ "Mcp APIs" ], "summary": "Add mcp server allow consumers", "operationId": "addAllowConsumers", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/McpServerConsumers" } } }, "required": true }, "responses": { "204": { "description": "Add mcp server allow consumers successfully" }, "500": { "description": "Internal server error" } } }, "delete": { "tags": [ "Mcp APIs" ], "summary": "Delete mcp server allow consumers", "operationId": "deleteAllowConsumers", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/McpServerConsumers" } } }, "required": true }, "responses": { "500": { "description": "Internal server error" }, "204": { "description": "Delete mcp server allow consumers successfully" } } } }, "/v1/global/plugin-instances/{name}": { "get": { "tags": [ "Wasm Plugin Instance APIs" ], "summary": "Get a specific global plugin instance", "operationId": "queryGlobalInstance", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Instances retrieved successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseWasmPluginInstance" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseWasmPluginInstance" } } } } } }, "put": { "tags": [ "Wasm Plugin Instance APIs" ], "summary": "Add or update a specific global plugin instance", "operationId": "addOrUpdateGlobalInstance", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WasmPluginInstance" } } }, "required": true }, "responses": { "200": { "description": "Instances retrieved successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseWasmPluginInstance" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseWasmPluginInstance" } } } } } }, "delete": { "tags": [ "Wasm Plugin Instance APIs" ], "summary": "Delete a global plugin instance", "operationId": "deleteGlobalInstance", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "204": { "description": "Instance deleted successfully" }, "500": { "description": "Internal server error" } } } }, "/v1/domains/{name}": { "get": { "tags": [ "Domain APIs" ], "summary": "Get domain by name", "operationId": "query_6", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Domain found", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseDomain" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseDomain" } } } }, "404": { "description": "Domain not found", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseDomain" } } } } } }, "put": { "tags": [ "Domain APIs" ], "summary": "Update an existed domain", "operationId": "put_1", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Domain" } } }, "required": true }, "responses": { "409": { "description": "Domain already existed with the same name.", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseDomain" } } } }, "400": { "description": "Domain data is not valid or domain name in the URL doesn't match the one in the body.", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseDomain" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseDomain" } } } }, "200": { "description": "Domain updated successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseDomain" } } } } } }, "delete": { "tags": [ "Domain APIs" ], "summary": "Delete a domain", "operationId": "delete_6", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseDomain" } } } }, "204": { "description": "Domain deleted successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseDomain" } } } } } } }, "/v1/domains/{domainName}/plugin-instances/{name}": { "get": { "tags": [ "Wasm Plugin Instance APIs" ], "summary": "Get a specific domain-bound plugin instance", "operationId": "queryDomainInstance", "parameters": [ { "name": "domainName", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Instances retrieved successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseWasmPluginInstance" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseWasmPluginInstance" } } } } } }, "put": { "tags": [ "Wasm Plugin Instance APIs" ], "summary": "Add or update a specific domain-bound plugin instance", "operationId": "addOrUpdateDomainInstance", "parameters": [ { "name": "domainName", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WasmPluginInstance" } } }, "required": true }, "responses": { "200": { "description": "Instances retrieved successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseWasmPluginInstance" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseWasmPluginInstance" } } } } } }, "delete": { "tags": [ "Wasm Plugin Instance APIs" ], "summary": "Delete a domain-bound plugin instance", "operationId": "deleteDomainInstance", "parameters": [ { "name": "domainName", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "204": { "description": "Instance deleted successfully" }, "500": { "description": "Internal server error" } } } }, "/v1/consumers/{name}": { "get": { "tags": [ "Consumer APIs" ], "summary": "Get consumer by name", "operationId": "query_7", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "404": { "description": "Consumer not found", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseConsumer" } } } }, "200": { "description": "Consumer found", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseConsumer" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseConsumer" } } } } } }, "put": { "tags": [ "Consumer APIs" ], "summary": "Update an existed consumer", "operationId": "put_2", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Consumer" } } }, "required": true }, "responses": { "200": { "description": "Consumer updated successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseConsumer" } } } }, "400": { "description": "Consumer data is not valid", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseConsumer" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseConsumer" } } } } } }, "delete": { "tags": [ "Consumer APIs" ], "summary": "Delete a consumer", "operationId": "delete_7", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "204": { "description": "Consumer deleted successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseConsumer" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseConsumer" } } } } } } }, "/v1/ai/routes/{name}": { "get": { "tags": [ "AI Route APIs" ], "summary": "Get AI route by name", "operationId": "query_8", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "404": { "description": "Route not found", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseAiRoute" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseAiRoute" } } } }, "200": { "description": "Route found", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseAiRoute" } } } } } }, "put": { "tags": [ "AI Route APIs" ], "summary": "Update an existed AI route", "operationId": "put_3", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AiRoute" } } }, "required": true }, "responses": { "409": { "description": "Route already existed with the same name.", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseAiRoute" } } } }, "200": { "description": "Route updated successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseAiRoute" } } } }, "400": { "description": "Route data is not valid or route name in the URL doesn't match the one in the body.", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseAiRoute" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseAiRoute" } } } } } }, "delete": { "tags": [ "AI Route APIs" ], "summary": "Delete an AI route", "operationId": "delete_8", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "400": { "description": "Deleting an internal route is not allowed.", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseAiRoute" } } } }, "204": { "description": "Route deleted successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseAiRoute" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseAiRoute" } } } } } } }, "/v1/ai/providers/{name}": { "get": { "tags": [ "LLM Provider APIs" ], "summary": "Get LLM provider by name", "operationId": "query_9", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "404": { "description": "Provider not found", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseLlmProvider" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseLlmProvider" } } } }, "200": { "description": "Provider found", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseLlmProvider" } } } } } }, "put": { "tags": [ "LLM Provider APIs" ], "summary": "Update an existed provider", "operationId": "put_4", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LlmProvider" } } }, "required": true }, "responses": { "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseLlmProvider" } } } }, "400": { "description": "Provider data is not valid or provider name in the URL doesn't match the one in the body.", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseLlmProvider" } } } }, "200": { "description": "Provider updated successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseLlmProvider" } } } } } }, "delete": { "tags": [ "LLM Provider APIs" ], "summary": "Delete an LLM provider", "operationId": "delete_9", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "204": { "description": "Provider deleted successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseLlmProvider" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseLlmProvider" } } } } } } }, "/system/higress-config": { "get": { "tags": [ "System APIs" ], "summary": "Get the content of higress-config ConfigMap", "operationId": "getHigressConfig", "responses": { "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseString" } } } }, "200": { "description": "higress-config retrieved successfully.", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseString" } } } } } }, "put": { "tags": [ "System APIs" ], "summary": "Update the content of higress-config ConfigMap", "operationId": "updateHigressConfig", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateHigressConfigRequest" } } }, "required": true }, "responses": { "200": { "description": "higress-config updated successfully.", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseString" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseString" } } } }, "400": { "description": "Config data is not valid", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseString" } } } }, "409": { "description": "Config data has been updated by someone else.", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseString" } } } } } } }, "/dashboard/info": { "get": { "tags": [ "Dashboard APIs" ], "summary": "Get dashboard info", "operationId": "info_1", "parameters": [ { "name": "type", "in": "query", "description": "Available types: MAIN/AI/LOG Default: MAIN", "required": false, "schema": { "type": "string" } } ], "responses": { "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseDashboardInfo" } } } }, "200": { "description": "Dashboard info retrieved successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseDashboardInfo" } } } } } }, "put": { "tags": [ "Dashboard APIs" ], "summary": "Set custom dashboard URL", "description": "Set the URL of dashboard. Only works when the built-in dashboard is not installed.", "operationId": "setUrl", "parameters": [ { "name": "type", "in": "query", "description": "Available types: MAIN/AI/LOG Default: MAIN", "required": false, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DashboardInfo" } } }, "required": true }, "responses": { "200": { "description": "Dashboard info updated successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseDashboardInfo" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseDashboardInfo" } } } }, "400": { "description": "Invalid request data", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseDashboardInfo" } } } } } } }, "/v1/wasm-plugins": { "get": { "tags": [ "Wasm Plugin APIs" ], "summary": "List Wasm plugins", "operationId": "list", "parameters": [ { "name": "lang", "in": "query", "description": "Plugin data language", "required": false, "schema": { "type": "string", "description": "Plugin data language", "enum": [ "zh-CN", "en-US" ] } }, { "name": "pageNum", "in": "query", "description": "Page number, starting from 1. If omitted, all items will be returned.", "required": false, "schema": { "type": "string", "description": "Page number, starting from 1. If omitted, all items will be returned." } }, { "name": "pageSize", "in": "query", "description": "Number of items per page. If omitted, all items will be returned.", "required": false, "schema": { "type": "string", "description": "Number of items per page. If omitted, all items will be returned." } } ], "responses": { "200": { "description": "Plugins listed successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/PaginatedResponseWasmPlugin" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/PaginatedResponseWasmPlugin" } } } } } }, "post": { "tags": [ "Wasm Plugin APIs" ], "summary": "Add a new plugin", "operationId": "add", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WasmPlugin" } } }, "required": true }, "responses": { "200": { "description": "Route added successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseWasmPlugin" } } } }, "409": { "description": "Plugin already existed with the same name.", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseWasmPlugin" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseWasmPlugin" } } } }, "400": { "description": "Plugin data is not valid", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseWasmPlugin" } } } } } } }, "/v1/tls-certificates": { "get": { "tags": [ "TLS Certificate APIs" ], "summary": "List TLS certificates", "operationId": "list_1", "parameters": [ { "name": "pageNum", "in": "query", "description": "Page number, starting from 1. If omitted, all items will be returned.", "required": false, "schema": { "type": "string", "description": "Page number, starting from 1. If omitted, all items will be returned." } }, { "name": "pageSize", "in": "query", "description": "Number of items per page. If omitted, all items will be returned.", "required": false, "schema": { "type": "string", "description": "Number of items per page. If omitted, all items will be returned." } } ], "responses": { "200": { "description": "TLS certificates listed successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/PaginatedResponseTlsCertificate" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/PaginatedResponseTlsCertificate" } } } } } }, "post": { "tags": [ "TLS Certificate APIs" ], "summary": "Add a new TLS certificate", "operationId": "add_1", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TlsCertificate" } } }, "required": true }, "responses": { "200": { "description": "TLS certificate added successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseTlsCertificate" } } } }, "400": { "description": "TLS certificate data is not valid", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseTlsCertificate" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseTlsCertificate" } } } }, "409": { "description": "TLS certificate already existed with the same name.", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseTlsCertificate" } } } } } } }, "/v1/service-sources": { "get": { "tags": [ "Service Source APIs" ], "summary": "List service sources", "operationId": "list_3", "parameters": [ { "name": "pageNum", "in": "query", "description": "Page number, starting from 1. If omitted, all items will be returned.", "required": false, "schema": { "type": "string", "description": "Page number, starting from 1. If omitted, all items will be returned." } }, { "name": "pageSize", "in": "query", "description": "Number of items per page. If omitted, all items will be returned.", "required": false, "schema": { "type": "string", "description": "Number of items per page. If omitted, all items will be returned." } } ], "responses": { "200": { "description": "Service sources listed successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/PaginatedResponseServiceSource" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/PaginatedResponseServiceSource" } } } } } }, "post": { "tags": [ "Service Source APIs" ], "summary": "Add a new service source", "operationId": "add_2", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ServiceSource" } } }, "required": true }, "responses": { "200": { "description": "Service source added successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseServiceSource" } } } }, "400": { "description": "Service source data is not valid", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseServiceSource" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseServiceSource" } } } }, "409": { "description": "Service source already existed with the same name.", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseServiceSource" } } } } } } }, "/v1/routes": { "get": { "tags": [ "Route APIs" ], "summary": "List routes", "operationId": "list_4", "parameters": [ { "name": "domainName", "in": "query", "description": "Domain name associated with route.", "required": false, "schema": { "type": "string", "description": "Domain name associated with route." } }, { "name": "all", "in": "query", "description": "true to list routes in all K8s namespaces, false to list only routes in the higress namespace.", "required": false, "schema": { "type": "string", "description": "true to list routes in all K8s namespaces, false to list only routes in the higress namespace." } }, { "name": "pageNum", "in": "query", "description": "Page number, starting from 1. If omitted, all items will be returned.", "required": false, "schema": { "type": "string", "description": "Page number, starting from 1. If omitted, all items will be returned." } }, { "name": "pageSize", "in": "query", "description": "Number of items per page. If omitted, all items will be returned.", "required": false, "schema": { "type": "string", "description": "Number of items per page. If omitted, all items will be returned." } } ], "responses": { "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/PaginatedResponseRoute" } } } }, "200": { "description": "Routes listed successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/PaginatedResponseRoute" } } } } } }, "post": { "tags": [ "Route APIs" ], "summary": "Add a new route", "operationId": "add_3", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Route" } } }, "required": true }, "responses": { "409": { "description": "Route already existed with the same name.", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseRoute" } } } }, "200": { "description": "Route added successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseRoute" } } } }, "400": { "description": "Route data is not valid", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseRoute" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseRoute" } } } } } } }, "/v1/proxy-servers": { "get": { "tags": [ "Proxy Server APIs" ], "summary": "List proxy servers", "operationId": "list_5", "parameters": [ { "name": "pageNum", "in": "query", "description": "Page number, starting from 1. If omitted, all items will be returned.", "required": false, "schema": { "type": "string", "description": "Page number, starting from 1. If omitted, all items will be returned." } }, { "name": "pageSize", "in": "query", "description": "Number of items per page. If omitted, all items will be returned.", "required": false, "schema": { "type": "string", "description": "Number of items per page. If omitted, all items will be returned." } } ], "responses": { "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/PaginatedResponseProxyServer" } } } }, "200": { "description": "Proxy servers listed successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/PaginatedResponseProxyServer" } } } } } }, "post": { "tags": [ "Proxy Server APIs" ], "summary": "Add a new proxy server", "operationId": "add_4", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProxyServer" } } }, "required": true }, "responses": { "200": { "description": "Proxy server added successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseProxyServer" } } } }, "400": { "description": "Proxy server data is not valid", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseProxyServer" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseProxyServer" } } } }, "409": { "description": "Proxy server already existed with the same name.", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseProxyServer" } } } } } } }, "/v1/mcpServer/swaggerToMcpConfig": { "post": { "tags": [ "Mcp APIs" ], "summary": "swagger to mcp config", "operationId": "swaggerToMcpConfig", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SwaggerContent" } } }, "required": true }, "responses": { "200": { "description": "swagger convert successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseString" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseString" } } } } } } }, "/v1/domains": { "get": { "tags": [ "Domain APIs" ], "summary": "List domains", "operationId": "list_7", "parameters": [ { "name": "pageNum", "in": "query", "description": "Page number, starting from 1. If omitted, all items will be returned.", "required": false, "schema": { "type": "string", "description": "Page number, starting from 1. If omitted, all items will be returned." } }, { "name": "pageSize", "in": "query", "description": "Number of items per page. If omitted, all items will be returned.", "required": false, "schema": { "type": "string", "description": "Number of items per page. If omitted, all items will be returned." } } ], "responses": { "200": { "description": "Domains listed successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/PaginatedResponseDomain" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/PaginatedResponseDomain" } } } } } }, "post": { "tags": [ "Domain APIs" ], "summary": "Add a new domain", "operationId": "add_5", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Domain" } } }, "required": true }, "responses": { "200": { "description": "Domain added successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseDomain" } } } }, "409": { "description": "Domain already existed with the same name.", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseDomain" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseDomain" } } } }, "400": { "description": "Domain data is not valid", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseDomain" } } } } } } }, "/v1/consumers": { "get": { "tags": [ "Consumer APIs" ], "summary": "List consumers", "operationId": "list_8", "parameters": [ { "name": "pageNum", "in": "query", "description": "Page number, starting from 1. If omitted, all items will be returned.", "required": false, "schema": { "type": "string", "description": "Page number, starting from 1. If omitted, all items will be returned." } }, { "name": "pageSize", "in": "query", "description": "Number of items per page. If omitted, all items will be returned.", "required": false, "schema": { "type": "string", "description": "Number of items per page. If omitted, all items will be returned." } } ], "responses": { "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/PaginatedResponseConsumer" } } } }, "200": { "description": "Consumers listed successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/PaginatedResponseConsumer" } } } } } }, "post": { "tags": [ "Consumer APIs" ], "summary": "Add a consumer", "operationId": "add_6", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Consumer" } } }, "required": true }, "responses": { "400": { "description": "Consumer data is not valid", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseConsumer" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseConsumer" } } } }, "200": { "description": "Consumer added successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseConsumer" } } } } } } }, "/v1/ai/routes": { "get": { "tags": [ "AI Route APIs" ], "summary": "List AI routes", "operationId": "list_9", "parameters": [ { "name": "pageNum", "in": "query", "description": "Page number, starting from 1. If omitted, all items will be returned.", "required": false, "schema": { "type": "string", "description": "Page number, starting from 1. If omitted, all items will be returned." } }, { "name": "pageSize", "in": "query", "description": "Number of items per page. If omitted, all items will be returned.", "required": false, "schema": { "type": "string", "description": "Number of items per page. If omitted, all items will be returned." } } ], "responses": { "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/PaginatedResponseAiRoute" } } } }, "200": { "description": "Routes listed successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/PaginatedResponseAiRoute" } } } } } }, "post": { "tags": [ "AI Route APIs" ], "summary": "Add a new AI route", "operationId": "add_7", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AiRoute" } } }, "required": true }, "responses": { "409": { "description": "Route already existed with the same name.", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseAiRoute" } } } }, "200": { "description": "Route added successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseAiRoute" } } } }, "400": { "description": "Route data is not valid", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseAiRoute" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseAiRoute" } } } } } } }, "/v1/ai/providers": { "get": { "tags": [ "LLM Provider APIs" ], "summary": "List LLM providers", "operationId": "list_10", "parameters": [ { "name": "query", "in": "query", "required": false, "schema": { "$ref": "#/components/schemas/CommonPageQuery" } } ], "responses": { "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/PaginatedResponseLlmProvider" } } } }, "200": { "description": "Providers listed successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/PaginatedResponseLlmProvider" } } } } } }, "post": { "tags": [ "LLM Provider APIs" ], "summary": "Add a new LLM provider", "operationId": "add_8", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LlmProvider" } } }, "required": true }, "responses": { "409": { "description": "Route already existed with the same name.", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseLlmProvider" } } } }, "200": { "description": "Route added successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseLlmProvider" } } } }, "400": { "description": "Route data is not valid", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseLlmProvider" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseLlmProvider" } } } } } } }, "/user/changePassword": { "post": { "tags": [ "User APIs" ], "summary": "Change password", "operationId": "logout", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ChangePasswordRequest" } } }, "required": true }, "responses": { "200": { "description": "Password changed successfully.", "content": { "*/*": { "schema": { "type": "object" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "type": "object" } } } }, "404": { "description": "Invalid request data", "content": { "*/*": { "schema": { "type": "object" } } } } } } }, "/system/init": { "post": { "tags": [ "System APIs" ], "summary": "Initialize", "operationId": "initialize", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SystemInitRequest" } } }, "required": true }, "responses": { "400": { "description": "Incomplete initialization data.", "content": { "*/*": { "schema": { "type": "object" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "type": "object" } } } }, "200": { "description": "System initialized successfully.", "content": { "*/*": { "schema": { "type": "object" } } } } } } }, "/session/login": { "post": { "tags": [ "Session APIs" ], "summary": "Login", "operationId": "login", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LoginRequest" } } }, "required": true }, "responses": { "200": { "description": "Logged in successfully.", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseUser" } } } }, "400": { "description": "Missing user name or password.", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseUser" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseUser" } } } } } } }, "/v1/wasm-plugins/{name}/readme": { "get": { "tags": [ "Wasm Plugin APIs" ], "summary": "Get readme document by plugin name", "operationId": "queryReadme", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "lang", "in": "query", "required": false, "schema": { "type": "string" } } ], "responses": { "404": { "description": "Plugin not found", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseString" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseString" } } } }, "200": { "description": "Readme document retrieved successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseString" } } } } } } }, "/v1/wasm-plugins/{name}/config": { "get": { "tags": [ "Wasm Plugin APIs" ], "summary": "Get configuration schema by plugin name", "operationId": "queryConfig", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "lang", "in": "query", "required": false, "schema": { "type": "string" } } ], "responses": { "404": { "description": "Plugin not found", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseWasmPluginConfig" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseWasmPluginConfig" } } } }, "200": { "description": "Configuration schema retrieved successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseWasmPluginConfig" } } } } } } }, "/v1/services": { "get": { "tags": [ "Service APIs" ], "summary": "List services", "operationId": "list_2", "parameters": [ { "name": "pageNum", "in": "query", "description": "Page number, starting from 1. If omitted, all items will be returned.", "required": false, "schema": { "type": "string", "description": "Page number, starting from 1. If omitted, all items will be returned." } }, { "name": "pageSize", "in": "query", "description": "Number of items per page. If omitted, all items will be returned.", "required": false, "schema": { "type": "string", "description": "Number of items per page. If omitted, all items will be returned." } } ], "responses": { "200": { "description": "Services listed successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/PaginatedResponseService" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/PaginatedResponseService" } } } } } } }, "/v1/services/{serviceName}/plugin-instances": { "get": { "tags": [ "Wasm Plugin Instance APIs" ], "summary": "List plugin instances bound to a service", "operationId": "listServiceInstances", "parameters": [ { "name": "serviceName", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/PaginatedResponseWasmPluginInstance" } } } }, "200": { "description": "Instances listed successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/PaginatedResponseWasmPluginInstance" } } } } } } }, "/v1/routes/{routeName}/plugin-instances": { "get": { "tags": [ "Wasm Plugin Instance APIs" ], "summary": "List plugin instances bound to a route", "operationId": "listRouteInstances", "parameters": [ { "name": "routeName", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/PaginatedResponseWasmPluginInstance" } } } }, "200": { "description": "Instances listed successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/PaginatedResponseWasmPluginInstance" } } } } } } }, "/v1/mcpServer/{name}": { "get": { "tags": [ "Mcp APIs" ], "summary": "Get detail for mcp server", "operationId": "query_5", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "McpServer detail query successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseMcpServer" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseMcpServer" } } } } } }, "delete": { "tags": [ "Mcp APIs" ], "summary": "Delete a mcp server", "operationId": "delete_5", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "204": { "description": "Route deleted successfully" }, "500": { "description": "Internal server error" } } } }, "/v1/global/plugin-instances": { "get": { "tags": [ "Wasm Plugin Instance APIs" ], "summary": "List global plugin instances", "operationId": "listGlobalInstances", "responses": { "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/PaginatedResponseWasmPluginInstance" } } } }, "200": { "description": "Instances listed successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/PaginatedResponseWasmPluginInstance" } } } } } } }, "/v1/domains/{name}/routes": { "get": { "tags": [ "Domain APIs" ], "summary": "List routes bound with a domain", "operationId": "queryRoutes", "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "commonPageQuery", "in": "query", "required": true, "schema": { "$ref": "#/components/schemas/CommonPageQuery" } } ], "responses": { "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/PaginatedResponseRoute" } } } }, "200": { "description": "Routes listed successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/PaginatedResponseRoute" } } } } } } }, "/v1/domains/{domainName}/plugin-instances": { "get": { "tags": [ "Wasm Plugin Instance APIs" ], "summary": "List plugin instances bound to a domain", "operationId": "listDomainInstances", "parameters": [ { "name": "domainName", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/PaginatedResponseWasmPluginInstance" } } } }, "200": { "description": "Instances listed successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/PaginatedResponseWasmPluginInstance" } } } } } } }, "/user/info": { "get": { "tags": [ "User APIs" ], "summary": "Get user info", "operationId": "getUserInfo", "responses": { "200": { "description": "User info retrieved successfully.", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseUser" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseUser" } } } } } } }, "/system/info": { "get": { "tags": [ "System APIs" ], "summary": "Get system info", "operationId": "info", "responses": { "200": { "description": "System info retrieved successfully.", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/SystemInfo" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/SystemInfo" } } } } } } }, "/system/config": { "get": { "tags": [ "System APIs" ], "summary": "Get system configurations", "operationId": "getConfigs", "responses": { "200": { "description": "System configurations retrieved successfully.", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseMapStringObject" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseMapStringObject" } } } } } } }, "/session/logout": { "get": { "tags": [ "Session APIs" ], "summary": "Logout", "operationId": "logout_1", "responses": { "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "type": "object" } } } }, "200": { "description": "Logged out successfully.", "content": { "*/*": { "schema": { "type": "object" } } } } } } }, "/dashboard/init": { "get": { "tags": [ "Dashboard APIs" ], "summary": "Initialize dashboards", "description": "Initialize dashboards with default settings. ", "operationId": "init", "parameters": [ { "name": "force", "in": "query", "description": "If true, the dashboard will be re-initialized even if it has been initialized before.", "required": false, "schema": { "type": "boolean" } } ], "responses": { "200": { "description": "Dashboard initialized successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseDashboardInfo" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseDashboardInfo" } } } } } } }, "/dashboard/configData": { "get": { "tags": [ "Dashboard APIs" ], "summary": "Get Grafana dashboard configuration", "description": "Get the configuration data for Grafana dashboard. The data source UID is required to generate the configuration.", "operationId": "getConfigData", "parameters": [ { "name": "type", "in": "query", "description": "Available types: MAIN/AI/LOG Default: MAIN", "required": false, "schema": { "type": "string" } }, { "name": "dataSourceUid", "in": "query", "description": "The UID of data source set in Grafana for the dashboard", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Dashboard info updated successfully", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseString" } } } }, "500": { "description": "Internal server error", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/ResponseString" } } } } } } } }, "components": { "schemas": { "AiModelPredicate": { "type": "object", "properties": { "matchType": { "$ref": "#/components/schemas/RoutePredicateTypeEnum" }, "matchValue": { "type": "string", "description": "The value to match against" }, "caseSensitive": { "type": "boolean", "description": "Whether to match the value case-sensitively" } }, "description": "AI Model Predicate" }, "AiRoute": { "type": "object", "properties": { "name": { "type": "string", "description": "Route name" }, "version": { "type": "string", "description": "Route version. Required when updating." }, "domains": { "type": "array", "description": "Domains that the route applies to. If empty, the route applies to all domains.", "items": { "type": "string", "description": "Domains that the route applies to. If empty, the route applies to all domains." } }, "pathPredicate": { "$ref": "#/components/schemas/RoutePredicate" }, "headerPredicates": { "type": "array", "description": "Header predicates", "items": { "$ref": "#/components/schemas/KeyedRoutePredicate" } }, "urlParamPredicates": { "type": "array", "description": "URL parameter predicates", "items": { "$ref": "#/components/schemas/KeyedRoutePredicate" } }, "upstreams": { "type": "array", "description": "Route upstreams", "items": { "$ref": "#/components/schemas/AiUpstream" } }, "modelPredicates": { "type": "array", "description": "Model predicates", "items": { "$ref": "#/components/schemas/AiModelPredicate" } }, "authConfig": { "$ref": "#/components/schemas/RouteAuthConfig" }, "fallbackConfig": { "$ref": "#/components/schemas/AiRouteFallbackConfig" }, "cors": { "$ref": "#/components/schemas/CorsConfig" }, "headerControl": { "$ref": "#/components/schemas/HeaderControlConfig" }, "proxyNextUpstream": { "$ref": "#/components/schemas/ProxyNextUpstreamConfig" }, "customConfigs": { "type": "object", "additionalProperties": { "type": "string", "description": "Custom configurations, e.g., custom annotations" }, "description": "Custom configurations, e.g., custom annotations" }, "customLabels": { "type": "object", "additionalProperties": { "type": "string", "description": "Custom labels" }, "description": "Custom labels" } }, "description": "AI Route" }, "AiRouteFallbackConfig": { "type": "object", "properties": { "enabled": { "type": "boolean", "description": "Whether fallback is enabled" }, "upstreams": { "type": "array", "description": "Fallback upstreams. Only one upstream is allowed when fallbackStrategy is SEQ.", "items": { "$ref": "#/components/schemas/AiUpstream" } }, "fallbackStrategy": { "$ref": "#/components/schemas/AiRouteFallbackStrategy" }, "responseCodes": { "type": "array", "description": "response codes that need fallback", "items": { "type": "string", "description": "response codes that need fallback" } } }, "description": "AI Route fallback configuration" }, "AiRouteFallbackStrategy": { "type": "string", "description": "AI Route fallback strategy", "enum": [ "RAND", "SEQ" ] }, "AiUpstream": { "type": "object", "properties": { "provider": { "type": "string", "description": "LLM provider name" }, "weight": { "type": "integer", "description": "Weight of the upstream", "format": "int32" }, "modelMapping": { "type": "object", "additionalProperties": { "type": "string", "description": "Model mapping" }, "description": "Model mapping" } }, "description": "AI Route Upstream" }, "CapabilityKey": { "type": "string", "description": "System Capability Keys", "enum": [ "CONFIG_INGRESS_V1" ] }, "ChangePasswordRequest": { "type": "object", "properties": { "oldPassword": { "type": "string", "description": "Old password" }, "newPassword": { "type": "string", "description": "New password" } }, "description": "Change Password Request" }, "CommonPageQuery": { "type": "object", "properties": { "pageNum": { "type": "integer", "description": "Page number, starting from 1. If omitted, all items will be returned.", "format": "int32" }, "pageSize": { "type": "integer", "description": "Number of items per page. If omitted, all items will be returned.", "format": "int32" } }, "description": "Query criteria for generic entity listing with pagination support." }, "Consumer": { "type": "object", "properties": { "name": { "type": "string", "description": "Consumer name" }, "credentials": { "type": "array", "description": "Consumer credentials", "items": { "oneOf": [ { "$ref": "#/components/schemas/Credential" }, { "$ref": "#/components/schemas/KeyAuthCredential" } ] } } }, "description": "Service Consumer" }, "ConsumerAuthInfo": { "type": "object", "properties": { "type": { "type": "string" }, "enable": { "type": "boolean" }, "allowedConsumers": { "type": "array", "description": "Allowed consumer names", "items": { "type": "string", "description": "Allowed consumer names" } } }, "description": "Mcp server consumer auth info" }, "CorsConfig": { "type": "object", "properties": { "enabled": { "type": "boolean", "description": "Whether to enable CORS" }, "allowOrigins": { "type": "array", "description": "Allowed origins, Access-Control-Allow-Origin", "items": { "type": "string", "description": "Allowed origins, Access-Control-Allow-Origin" } }, "allowMethods": { "type": "array", "description": "Allowed methods, Access-Control-Allow-Methods", "items": { "type": "string", "description": "Allowed methods, Access-Control-Allow-Methods" } }, "allowHeaders": { "type": "array", "description": "Allowed headers, Access-Control-Allow-Headers", "items": { "type": "string", "description": "Allowed headers, Access-Control-Allow-Headers" } }, "exposeHeaders": { "type": "array", "description": "Exposed headers, Access-Control-Expose-Headers", "items": { "type": "string", "description": "Exposed headers, Access-Control-Expose-Headers" } }, "maxAge": { "type": "integer", "description": "Max age, Access-Control-Max-Age", "format": "int32" }, "allowCredentials": { "type": "boolean", "description": "Whether to allow credentials, Access-Control-Allow-Credentials" } }, "description": "CORS Configuration" }, "Credential": { "type": "object", "properties": { "type": { "$ref": "#/components/schemas/CredentialType" } }, "description": "Consumer Credential", "discriminator": { "propertyName": "type" }, "oneOf": [ { "$ref": "#/components/schemas/KeyAuthCredential" } ] }, "CredentialType": { "type": "string", "description": "Credential Type", "enum": [ "key-auth" ] }, "DashboardInfo": { "type": "object", "properties": { "builtIn": { "type": "boolean" }, "uid": { "type": "string" }, "url": { "type": "string" } } }, "Discriminator": { "type": "object", "properties": { "propertyName": { "type": "string" }, "mapping": { "type": "object", "additionalProperties": { "type": "string" } } } }, "Domain": { "type": "object", "properties": { "name": { "type": "string", "description": "Domain name" }, "version": { "type": "string", "description": "Domain version. Required when updating." }, "enableHttps": { "type": "string", "description": "HTTPS configuration", "enum": [ "off", "on", "force" ] }, "certIdentifier": { "type": "string", "description": "Certificate name" } }, "description": "Gateway Domain" }, "ExternalDocumentation": { "type": "object", "properties": { "description": { "type": "string" }, "url": { "type": "string" }, "extensions": { "type": "object", "additionalProperties": { "type": "object" }, "writeOnly": true } } }, "Header": { "type": "object", "properties": { "key": { "type": "string" }, "value": { "type": "string" } }, "description": "Headers to set" }, "HeaderControlConfig": { "type": "object", "properties": { "enabled": { "type": "boolean", "description": "Whether to enable the header control feature." }, "request": { "$ref": "#/components/schemas/HeaderControlStageConfig" }, "response": { "$ref": "#/components/schemas/HeaderControlStageConfig" } }, "description": "Header Control Configuration" }, "HeaderControlStageConfig": { "type": "object", "properties": { "add": { "type": "array", "description": "Headers to add", "items": { "$ref": "#/components/schemas/Header" } }, "set": { "type": "array", "description": "Headers to set", "items": { "$ref": "#/components/schemas/Header" } }, "remove": { "type": "array", "description": "Headers to remove", "items": { "type": "string", "description": "Headers to remove" } } }, "description": "Header Control Stage Configuration" }, "KeyAuthCredential": { "type": "object", "description": "KeyAuth Credential", "allOf": [ { "$ref": "#/components/schemas/Credential" }, { "type": "object", "properties": { "source": { "$ref": "#/components/schemas/KeyAuthCredentialSource" }, "key": { "type": "string", "description": "Credential Key. Required when source is HEADER or QUERY" }, "values": { "type": "array", "description": "Credential Values", "items": { "type": "string", "description": "Credential Values" } } } } ] }, "KeyAuthCredentialSource": { "type": "string", "description": "KeyAuth Credential Source", "enum": [ "BEARER", "HEADER", "QUERY" ] }, "KeyedRoutePredicate": { "type": "object", "properties": { "matchType": { "$ref": "#/components/schemas/RoutePredicateTypeEnum" }, "matchValue": { "type": "string", "description": "The value to match against" }, "caseSensitive": { "type": "boolean", "description": "Whether to match the value case-sensitively" }, "key": { "type": "string" } }, "description": "Route Predicate with a Key" }, "LlmProvider": { "type": "object", "properties": { "name": { "type": "string", "description": "Provider name" }, "type": { "$ref": "#/components/schemas/LlmProviderType" }, "protocol": { "$ref": "#/components/schemas/LlmProviderProtocol" }, "proxyName": { "type": "string", "description": "Proxy server name" }, "tokens": { "type": "array", "description": "Tokens used to request the provider", "items": { "type": "string", "description": "Tokens used to request the provider" } }, "tokenFailoverConfig": { "$ref": "#/components/schemas/TokenFailoverConfig" }, "rawConfigs": { "type": "object", "additionalProperties": { "type": "object", "description": "Raw configuration key-value pairs used by ai-proxy plugin" }, "description": "Raw configuration key-value pairs used by ai-proxy plugin" } }, "description": "LLM Service Provider" }, "LlmProviderProtocol": { "type": "string", "description": "LLM Service Provider Protocols", "enum": [ "openai/v1", "original" ] }, "LlmProviderType": { "type": "string", "description": "LLM Service Provider Types", "enum": [ "qwen", "openai", "moonshot", "azure", "ai360", "github", "groq", "baichuan", "yi", "deepseek", "zhipuai", "ollama", "claude", "baidu", "hunyuan", "stepfun", "minimax", "cloudflare", "spark", "gemini", "deepl", "mistral", "cohere", "doubao", "coze", "together-ai", "openrouter", "grok" ] }, "LoginRequest": { "type": "object", "properties": { "username": { "type": "string", "description": "Username" }, "password": { "type": "string", "description": "Password" }, "autoLogin": { "type": "boolean", "description": "Whether to automatically log in when opening a new browser window." } }, "description": "Login Request" }, "McpServer": { "type": "object", "properties": { "id": { "type": "string", "deprecated": true }, "name": { "type": "string", "description": "Mcp server name" }, "description": { "type": "string", "description": "Mcp server description" }, "domains": { "type": "array", "description": "Domains that the mcp server applies to.", "items": { "type": "string", "description": "Domains that the mcp server applies to." } }, "services": { "type": "array", "description": "Mcp server upstream services", "items": { "$ref": "#/components/schemas/UpstreamService" } }, "type": { "type": "string", "description": "Mcp Server Type Enum", "enum": [ "OPEN_API", "DATABASE", "DIRECT_ROUTE" ] }, "consumerAuthInfo": { "$ref": "#/components/schemas/ConsumerAuthInfo" }, "rawConfigurations": { "type": "string", "description": "Raw configurations in YAML format" }, "dbConfig": { "$ref": "#/components/schemas/McpServerDBConfig" }, "dbType": { "type": "string", "description": "Mcp Server DB Type Enum", "enum": [ "MYSQL", "POSTGRESQL", "SQLITE", "CLICKHOUSE" ] }, "directRouteConfig": { "$ref": "#/components/schemas/McpServerDirectRouteConfig" } } }, "McpServerConsumerDetail": { "type": "object", "properties": { "mcpServerName": { "type": "string", "description": "Mcp server name" }, "consumerName": { "type": "string", "description": "Consumer name" } }, "description": "Response data." }, "McpServerConsumers": { "type": "object", "properties": { "mcpServerName": { "type": "string", "description": "Mcp server route name" }, "consumers": { "type": "array", "description": "Consumer names", "items": { "type": "string", "description": "Consumer names" } } } }, "McpServerDBConfig": { "type": "object", "properties": { "host": { "type": "string" }, "port": { "type": "string" }, "username": { "type": "string" }, "password": { "type": "string" }, "dbname": { "type": "string" }, "otherParams": { "type": "object", "additionalProperties": { "type": "object" } } }, "description": "Database config. For DB type server, it is required" }, "McpServerDBTypeEnum": { "type": "string", "description": "Mcp Server DB Type Enum", "enum": [ "MYSQL", "POSTGRESQL", "SQLITE", "CLICKHOUSE" ] }, "McpServerDirectRouteConfig": { "type": "object", "properties": { "path": { "type": "string" }, "transportType": { "type": "string" } }, "description": "Direct route config." }, "McpServerTypeEnum": { "type": "string", "description": "Mcp Server Type Enum", "enum": [ "OPEN_API", "DATABASE", "DIRECT_ROUTE" ] }, "PaginatedResponseAiRoute": { "type": "object", "properties": { "success": { "type": "boolean", "description": "Whether the request is successful." }, "message": { "type": "string", "description": "Error message." }, "data": { "type": "array", "description": "Response data.", "items": { "$ref": "#/components/schemas/AiRoute" } }, "total": { "type": "integer", "description": "Total number of data.", "format": "int32" }, "pageNum": { "type": "integer", "description": "Page number starting from 0.", "format": "int32" }, "pageSize": { "type": "integer", "description": "Number of data per page.", "format": "int32" } }, "description": "Response with paginated data." }, "PaginatedResponseConsumer": { "type": "object", "properties": { "success": { "type": "boolean", "description": "Whether the request is successful." }, "message": { "type": "string", "description": "Error message." }, "data": { "type": "array", "description": "Response data.", "items": { "$ref": "#/components/schemas/Consumer" } }, "total": { "type": "integer", "description": "Total number of data.", "format": "int32" }, "pageNum": { "type": "integer", "description": "Page number starting from 0.", "format": "int32" }, "pageSize": { "type": "integer", "description": "Number of data per page.", "format": "int32" } }, "description": "Response with paginated data." }, "PaginatedResponseDomain": { "type": "object", "properties": { "success": { "type": "boolean", "description": "Whether the request is successful." }, "message": { "type": "string", "description": "Error message." }, "data": { "type": "array", "description": "Response data.", "items": { "$ref": "#/components/schemas/Domain" } }, "total": { "type": "integer", "description": "Total number of data.", "format": "int32" }, "pageNum": { "type": "integer", "description": "Page number starting from 0.", "format": "int32" }, "pageSize": { "type": "integer", "description": "Number of data per page.", "format": "int32" } }, "description": "Response with paginated data." }, "PaginatedResponseLlmProvider": { "type": "object", "properties": { "success": { "type": "boolean", "description": "Whether the request is successful." }, "message": { "type": "string", "description": "Error message." }, "data": { "type": "array", "description": "Response data.", "items": { "$ref": "#/components/schemas/LlmProvider" } }, "total": { "type": "integer", "description": "Total number of data.", "format": "int32" }, "pageNum": { "type": "integer", "description": "Page number starting from 0.", "format": "int32" }, "pageSize": { "type": "integer", "description": "Number of data per page.", "format": "int32" } }, "description": "Response with paginated data." }, "PaginatedResponseMcpServer": { "type": "object", "properties": { "success": { "type": "boolean", "description": "Whether the request is successful." }, "message": { "type": "string", "description": "Error message." }, "data": { "type": "array", "description": "Response data.", "items": { "$ref": "#/components/schemas/McpServer" } }, "total": { "type": "integer", "description": "Total number of data.", "format": "int32" }, "pageNum": { "type": "integer", "description": "Page number starting from 0.", "format": "int32" }, "pageSize": { "type": "integer", "description": "Number of data per page.", "format": "int32" } }, "description": "Response with paginated data." }, "PaginatedResponseMcpServerConsumerDetail": { "type": "object", "properties": { "success": { "type": "boolean", "description": "Whether the request is successful." }, "message": { "type": "string", "description": "Error message." }, "data": { "type": "array", "description": "Response data.", "items": { "$ref": "#/components/schemas/McpServerConsumerDetail" } }, "total": { "type": "integer", "description": "Total number of data.", "format": "int32" }, "pageNum": { "type": "integer", "description": "Page number starting from 0.", "format": "int32" }, "pageSize": { "type": "integer", "description": "Number of data per page.", "format": "int32" } }, "description": "Response with paginated data." }, "PaginatedResponseProxyServer": { "type": "object", "properties": { "success": { "type": "boolean", "description": "Whether the request is successful." }, "message": { "type": "string", "description": "Error message." }, "data": { "type": "array", "description": "Response data.", "items": { "$ref": "#/components/schemas/ProxyServer" } }, "total": { "type": "integer", "description": "Total number of data.", "format": "int32" }, "pageNum": { "type": "integer", "description": "Page number starting from 0.", "format": "int32" }, "pageSize": { "type": "integer", "description": "Number of data per page.", "format": "int32" } }, "description": "Response with paginated data." }, "PaginatedResponseRoute": { "type": "object", "properties": { "success": { "type": "boolean", "description": "Whether the request is successful." }, "message": { "type": "string", "description": "Error message." }, "data": { "type": "array", "description": "Response data.", "items": { "$ref": "#/components/schemas/Route" } }, "total": { "type": "integer", "description": "Total number of data.", "format": "int32" }, "pageNum": { "type": "integer", "description": "Page number starting from 0.", "format": "int32" }, "pageSize": { "type": "integer", "description": "Number of data per page.", "format": "int32" } }, "description": "Response with paginated data." }, "PaginatedResponseService": { "type": "object", "properties": { "success": { "type": "boolean", "description": "Whether the request is successful." }, "message": { "type": "string", "description": "Error message." }, "data": { "type": "array", "description": "Response data.", "items": { "$ref": "#/components/schemas/Service" } }, "total": { "type": "integer", "description": "Total number of data.", "format": "int32" }, "pageNum": { "type": "integer", "description": "Page number starting from 0.", "format": "int32" }, "pageSize": { "type": "integer", "description": "Number of data per page.", "format": "int32" } }, "description": "Response with paginated data." }, "PaginatedResponseServiceSource": { "type": "object", "properties": { "success": { "type": "boolean", "description": "Whether the request is successful." }, "message": { "type": "string", "description": "Error message." }, "data": { "type": "array", "description": "Response data.", "items": { "$ref": "#/components/schemas/ServiceSource" } }, "total": { "type": "integer", "description": "Total number of data.", "format": "int32" }, "pageNum": { "type": "integer", "description": "Page number starting from 0.", "format": "int32" }, "pageSize": { "type": "integer", "description": "Number of data per page.", "format": "int32" } }, "description": "Response with paginated data." }, "PaginatedResponseTlsCertificate": { "type": "object", "properties": { "success": { "type": "boolean", "description": "Whether the request is successful." }, "message": { "type": "string", "description": "Error message." }, "data": { "type": "array", "description": "Response data.", "items": { "$ref": "#/components/schemas/TlsCertificate" } }, "total": { "type": "integer", "description": "Total number of data.", "format": "int32" }, "pageNum": { "type": "integer", "description": "Page number starting from 0.", "format": "int32" }, "pageSize": { "type": "integer", "description": "Number of data per page.", "format": "int32" } }, "description": "Response with paginated data." }, "PaginatedResponseWasmPlugin": { "type": "object", "properties": { "success": { "type": "boolean", "description": "Whether the request is successful." }, "message": { "type": "string", "description": "Error message." }, "data": { "type": "array", "description": "Response data.", "items": { "$ref": "#/components/schemas/WasmPlugin" } }, "total": { "type": "integer", "description": "Total number of data.", "format": "int32" }, "pageNum": { "type": "integer", "description": "Page number starting from 0.", "format": "int32" }, "pageSize": { "type": "integer", "description": "Number of data per page.", "format": "int32" } }, "description": "Response with paginated data." }, "PaginatedResponseWasmPluginInstance": { "type": "object", "properties": { "success": { "type": "boolean", "description": "Whether the request is successful." }, "message": { "type": "string", "description": "Error message." }, "data": { "type": "array", "description": "Response data.", "items": { "$ref": "#/components/schemas/WasmPluginInstance" } }, "total": { "type": "integer", "description": "Total number of data.", "format": "int32" }, "pageNum": { "type": "integer", "description": "Page number starting from 0.", "format": "int32" }, "pageSize": { "type": "integer", "description": "Number of data per page.", "format": "int32" } }, "description": "Response with paginated data." }, "ProxyNextUpstreamConfig": { "type": "object", "properties": { "enabled": { "type": "boolean", "description": "Whether to enable the proxy next upstream feature." }, "attempts": { "type": "integer", "description": "Specifies the number of attempts to pass a request to the next server.", "format": "int32" }, "timeout": { "type": "integer", "description": "Specifies the timeout for passing a request to the next server.", "format": "int32" }, "conditions": { "type": "array", "description": "Specifies in which cases a request should be passed to the next server.", "items": { "type": "string", "description": "Specifies in which cases a request should be passed to the next server.", "enum": [ "error", "timeout", "invalid_header", "http_500", "http_502", "http_503", "http_504", "http_403", "http_404", "http_429", "non_idempotent" ] }, "enum": [ "error", "timeout", "invalid_header", "http_500", "http_502", "http_503", "http_504", "http_403", "http_404", "http_429", "non_idempotent" ] } }, "description": "Proxy Next Upstream Configuration" }, "ProxyServer": { "type": "object", "properties": { "type": { "type": "string", "description": "Proxy server type", "enum": [ "http" ] }, "name": { "type": "string", "description": "Proxy server name" }, "version": { "type": "string", "description": "Proxy server version. Required when updating." }, "serverAddress": { "type": "string", "description": "Proxy server address, can be IP or domain name" }, "serverPort": { "type": "integer", "description": "Proxy server port", "format": "int32" }, "connectTimeout": { "type": "integer", "description": "Proxy server connect timeout in milliseconds, default is 1200", "format": "int32" } }, "description": "Proxy Server" }, "ResponseAiRoute": { "type": "object", "properties": { "success": { "type": "boolean", "description": "Whether the request is successful." }, "message": { "type": "string", "description": "Error message." }, "data": { "$ref": "#/components/schemas/AiRoute" } } }, "ResponseConsumer": { "type": "object", "properties": { "success": { "type": "boolean", "description": "Whether the request is successful." }, "message": { "type": "string", "description": "Error message." }, "data": { "$ref": "#/components/schemas/Consumer" } } }, "ResponseDashboardInfo": { "type": "object", "properties": { "success": { "type": "boolean", "description": "Whether the request is successful." }, "message": { "type": "string", "description": "Error message." }, "data": { "$ref": "#/components/schemas/DashboardInfo" } } }, "ResponseDomain": { "type": "object", "properties": { "success": { "type": "boolean", "description": "Whether the request is successful." }, "message": { "type": "string", "description": "Error message." }, "data": { "$ref": "#/components/schemas/Domain" } } }, "ResponseLlmProvider": { "type": "object", "properties": { "success": { "type": "boolean", "description": "Whether the request is successful." }, "message": { "type": "string", "description": "Error message." }, "data": { "$ref": "#/components/schemas/LlmProvider" } } }, "ResponseMapStringObject": { "type": "object", "properties": { "success": { "type": "boolean", "description": "Whether the request is successful." }, "message": { "type": "string", "description": "Error message." }, "data": { "type": "object", "additionalProperties": { "type": "object", "description": "Response data." }, "description": "Response data." } } }, "ResponseMcpServer": { "type": "object", "properties": { "success": { "type": "boolean", "description": "Whether the request is successful." }, "message": { "type": "string", "description": "Error message." }, "data": { "$ref": "#/components/schemas/McpServer" } } }, "ResponseProxyServer": { "type": "object", "properties": { "success": { "type": "boolean", "description": "Whether the request is successful." }, "message": { "type": "string", "description": "Error message." }, "data": { "$ref": "#/components/schemas/ProxyServer" } } }, "ResponseRoute": { "type": "object", "properties": { "success": { "type": "boolean", "description": "Whether the request is successful." }, "message": { "type": "string", "description": "Error message." }, "data": { "$ref": "#/components/schemas/Route" } } }, "ResponseServiceSource": { "type": "object", "properties": { "success": { "type": "boolean", "description": "Whether the request is successful." }, "message": { "type": "string", "description": "Error message." }, "data": { "$ref": "#/components/schemas/ServiceSource" } } }, "ResponseString": { "type": "object", "properties": { "success": { "type": "boolean", "description": "Whether the request is successful." }, "message": { "type": "string", "description": "Error message." }, "data": { "type": "string", "description": "Response data." } } }, "ResponseTlsCertificate": { "type": "object", "properties": { "success": { "type": "boolean", "description": "Whether the request is successful." }, "message": { "type": "string", "description": "Error message." }, "data": { "$ref": "#/components/schemas/TlsCertificate" } } }, "ResponseUser": { "type": "object", "properties": { "success": { "type": "boolean", "description": "Whether the request is successful." }, "message": { "type": "string", "description": "Error message." }, "data": { "$ref": "#/components/schemas/User" } } }, "ResponseWasmPlugin": { "type": "object", "properties": { "success": { "type": "boolean", "description": "Whether the request is successful." }, "message": { "type": "string", "description": "Error message." }, "data": { "$ref": "#/components/schemas/WasmPlugin" } } }, "ResponseWasmPluginConfig": { "type": "object", "properties": { "success": { "type": "boolean", "description": "Whether the request is successful." }, "message": { "type": "string", "description": "Error message." }, "data": { "$ref": "#/components/schemas/WasmPluginConfig" } } }, "ResponseWasmPluginInstance": { "type": "object", "properties": { "success": { "type": "boolean", "description": "Whether the request is successful." }, "message": { "type": "string", "description": "Error message." }, "data": { "$ref": "#/components/schemas/WasmPluginInstance" } } }, "RewriteConfig": { "type": "object", "properties": { "enabled": { "type": "boolean", "description": "Enable or disable the rewrite" }, "path": { "type": "string", "description": "Rewritten path" }, "host": { "type": "string", "description": "Rewritten host" } }, "description": "Request Rewrite Config" }, "Route": { "type": "object", "properties": { "name": { "type": "string", "description": "Route name" }, "version": { "type": "string", "description": "Route version. Required when updating." }, "domains": { "type": "array", "description": "Domains that the route applies to. If empty, the route applies to all domains.", "items": { "type": "string", "description": "Domains that the route applies to. If empty, the route applies to all domains." } }, "path": { "$ref": "#/components/schemas/RoutePredicate" }, "methods": { "type": "array", "description": "Methods that the route applies to. If empty, the route applies to all methods.", "items": { "type": "string", "description": "Methods that the route applies to. If empty, the route applies to all methods." } }, "headers": { "type": "array", "description": "Header predicates", "items": { "$ref": "#/components/schemas/KeyedRoutePredicate" } }, "urlParams": { "type": "array", "description": "URL parameter predicates", "items": { "$ref": "#/components/schemas/KeyedRoutePredicate" } }, "services": { "type": "array", "description": "Route upstream services", "items": { "$ref": "#/components/schemas/UpstreamService" } }, "rewrite": { "$ref": "#/components/schemas/RewriteConfig" }, "proxyNextUpstream": { "$ref": "#/components/schemas/ProxyNextUpstreamConfig" }, "cors": { "$ref": "#/components/schemas/CorsConfig" }, "headerControl": { "$ref": "#/components/schemas/HeaderControlConfig" }, "authConfig": { "$ref": "#/components/schemas/RouteAuthConfig" }, "customConfigs": { "type": "object", "additionalProperties": { "type": "string", "description": "Custom configurations, e.g., custom annotations" }, "description": "Custom configurations, e.g., custom annotations" }, "customLabels": { "type": "object", "additionalProperties": { "type": "string", "description": "Custom labels" }, "description": "Custom labels" } }, "description": "Gateway Route" }, "RouteAuthConfig": { "type": "object", "properties": { "enabled": { "type": "boolean", "description": "Whether auth is enabled" }, "allowedCredentialTypes": { "type": "array", "description": "Allowed credential types", "items": { "type": "string", "description": "Allowed credential types" } }, "allowedConsumers": { "type": "array", "description": "Allowed consumer names", "items": { "type": "string", "description": "Allowed consumer names" } } }, "description": "Route auth configuration" }, "RoutePredicate": { "type": "object", "properties": { "matchType": { "$ref": "#/components/schemas/RoutePredicateTypeEnum" }, "matchValue": { "type": "string", "description": "The value to match against" }, "caseSensitive": { "type": "boolean", "description": "Whether to match the value case-sensitively" } }, "description": "Route Predicate" }, "RoutePredicateTypeEnum": { "type": "string", "description": "Route Predicate Types", "enum": [ "EXACT", "PRE", "REGEX" ] }, "Schema": { "type": "object", "properties": { "title": { "type": "string" }, "multipleOf": { "type": "number" }, "maximum": { "type": "number" }, "exclusiveMaximum": { "type": "boolean" }, "minimum": { "type": "number" }, "exclusiveMinimum": { "type": "boolean" }, "maxLength": { "type": "integer", "format": "int32" }, "minLength": { "type": "integer", "format": "int32" }, "pattern": { "type": "string" }, "maxItems": { "type": "integer", "format": "int32" }, "minItems": { "type": "integer", "format": "int32" }, "uniqueItems": { "type": "boolean" }, "maxProperties": { "type": "integer", "format": "int32" }, "minProperties": { "type": "integer", "format": "int32" }, "required": { "type": "array", "items": { "type": "string" } }, "type": { "type": "string" }, "not": { "$ref": "#/components/schemas/Schema" }, "properties": { "type": "object", "additionalProperties": { "$ref": "#/components/schemas/Schema" } }, "additionalProperties": { "type": "object" }, "description": { "type": "string" }, "format": { "type": "string" }, "get$ref": { "type": "string" }, "nullable": { "type": "boolean" }, "readOnly": { "type": "boolean" }, "writeOnly": { "type": "boolean" }, "example": { "type": "object" }, "externalDocs": { "$ref": "#/components/schemas/ExternalDocumentation" }, "deprecated": { "type": "boolean" }, "xml": { "$ref": "#/components/schemas/XML" }, "extensions": { "type": "object", "additionalProperties": { "type": "object" }, "writeOnly": true }, "discriminator": { "$ref": "#/components/schemas/Discriminator" }, "allOf": { "type": "array", "items": { "$ref": "#/components/schemas/Schema" } }, "anyOf": { "type": "array", "items": { "$ref": "#/components/schemas/Schema" } }, "oneOf": { "type": "array", "items": { "$ref": "#/components/schemas/Schema" } }, "items": { "$ref": "#/components/schemas/SchemaObject" }, "get$vocabulary": { "type": "string" }, "get$dynamicAnchor": { "type": "string" }, "default": { "type": "object" }, "enum": { "type": "array", "items": { "type": "object" } } } }, "SchemaObject": { "type": "object", "properties": { "title": { "type": "string" }, "multipleOf": { "type": "number" }, "maximum": { "type": "number" }, "exclusiveMaximum": { "type": "boolean" }, "minimum": { "type": "number" }, "exclusiveMinimum": { "type": "boolean" }, "maxLength": { "type": "integer", "format": "int32" }, "minLength": { "type": "integer", "format": "int32" }, "pattern": { "type": "string" }, "maxItems": { "type": "integer", "format": "int32" }, "minItems": { "type": "integer", "format": "int32" }, "uniqueItems": { "type": "boolean" }, "maxProperties": { "type": "integer", "format": "int32" }, "minProperties": { "type": "integer", "format": "int32" }, "required": { "type": "array", "items": { "type": "string" } }, "type": { "type": "string" }, "not": { "$ref": "#/components/schemas/Schema" }, "properties": { "type": "object", "additionalProperties": { "$ref": "#/components/schemas/Schema" } }, "additionalProperties": { "type": "object" }, "description": { "type": "string" }, "format": { "type": "string" }, "get$ref": { "type": "string" }, "nullable": { "type": "boolean" }, "readOnly": { "type": "boolean" }, "writeOnly": { "type": "boolean" }, "example": { "type": "object" }, "externalDocs": { "$ref": "#/components/schemas/ExternalDocumentation" }, "deprecated": { "type": "boolean" }, "xml": { "$ref": "#/components/schemas/XML" }, "extensions": { "type": "object", "additionalProperties": { "type": "object" }, "writeOnly": true }, "discriminator": { "$ref": "#/components/schemas/Discriminator" }, "allOf": { "type": "array", "items": { "$ref": "#/components/schemas/Schema" } }, "anyOf": { "type": "array", "items": { "$ref": "#/components/schemas/Schema" } }, "oneOf": { "type": "array", "items": { "$ref": "#/components/schemas/Schema" } }, "items": { "$ref": "#/components/schemas/SchemaObject" }, "get$vocabulary": { "type": "string" }, "get$dynamicAnchor": { "type": "string" }, "default": { "type": "object" }, "enum": { "type": "array", "items": { "type": "object" } } }, "description": "Wasm plugin configuration schema" }, "Service": { "type": "object", "properties": { "name": { "type": "string" }, "namespace": { "type": "string" }, "port": { "type": "integer", "format": "int32" }, "version": { "type": "integer", "format": "int32" }, "endpoints": { "type": "array", "items": { "type": "string" } }, "protocol": { "type": "string" } }, "description": "Response data." }, "ServiceSource": { "type": "object", "properties": { "name": { "type": "string", "description": "Service source name" }, "vport": { "$ref": "#/components/schemas/VPort" }, "version": { "type": "string", "description": "Service source version. Required when updating." }, "type": { "type": "string", "description": "Service source type", "enum": [ "nacos", "nacos2", "nacos3", "zookeeper", "consul", "eureka", "static", "dns" ] }, "domain": { "type": "string", "description": "Service source domain(s). For static type, use ip:port format. For dns type, use domain list." }, "port": { "type": "integer", "description": "Service source port. Always use 80 for static type.", "format": "int32" }, "protocol": { "type": "string", "description": "Service source protocol. Used in static and dns types.", "enum": [ "http", "https", "grpc", "grpcs" ] }, "sni": { "type": "string", "description": "Service source SNI. Used in static and dns types when TLS is enabled." }, "proxyName": { "type": "string", "description": "Proxy server name. Only supported in static and dns types." }, "properties": { "type": "object", "additionalProperties": { "type": "object", "description": "Service source extra properties, depending on the type.\nFor nacos/nacos2/nacos3: nacosGroups, nacosNamespaceId\nFor MCP supported types (e.g. nacos3): enableMCPServer, mcpServerBaseUrl, mcpServerExportDomains\nFor consul: consulDatacenter, consulServiceTag, consulRefreshInterval\nFor zookeeper: zkServicesPath" }, "description": "Service source extra properties, depending on the type.\nFor nacos/nacos2/nacos3: nacosGroups, nacosNamespaceId\nFor MCP supported types (e.g. nacos3): enableMCPServer, mcpServerBaseUrl, mcpServerExportDomains\nFor consul: consulDatacenter, consulServiceTag, consulRefreshInterval\nFor zookeeper: zkServicesPath" }, "authN": { "$ref": "#/components/schemas/ServiceSourceAuthN" } }, "description": "Gateway Service Source" }, "ServiceSourceAuthN": { "type": "object", "properties": { "enabled": { "type": "boolean", "description": "Enable authentication when accessing the service source" }, "properties": { "type": "object", "additionalProperties": { "type": "string", "description": "Authentication properties, depending on the type.\nFor nacos/nacos2: nacosUsername, nacosPassword\nFor consul: consulToken\n" }, "description": "Authentication properties, depending on the type.\nFor nacos/nacos2: nacosUsername, nacosPassword\nFor consul: consulToken\n" } }, "description": "Gateway Service Source Authentication Config" }, "ServiceVport": { "type": "object", "properties": { "name": { "type": "string" }, "value": { "type": "integer", "format": "int32" } } }, "SwaggerContent": { "required": [ "content" ], "type": "object", "properties": { "content": { "type": "string", "description": "Swagger content" } }, "description": "Swagger Content" }, "SystemInfo": { "type": "object", "properties": { "version": { "type": "string", "description": "System version" }, "capabilities": { "$ref": "#/components/schemas/CapabilityKey" } }, "description": "System Information" }, "SystemInitRequest": { "type": "object", "properties": { "adminUser": { "$ref": "#/components/schemas/User" }, "configs": { "type": "object", "additionalProperties": { "type": "object", "description": "System configuration key-value pairs" }, "description": "System configuration key-value pairs" } }, "description": "System Init Request" }, "TlsCertificate": { "type": "object", "properties": { "name": { "type": "string", "description": "Certificate name" }, "version": { "type": "string", "description": "Certificate version. Required when updating." }, "cert": { "type": "string", "description": "Certificate content in PEM format" }, "key": { "type": "string", "description": "Private key content in PEM format" }, "domains": { "type": "array", "description": "Domains (SAN inluded) that the certificate applies to", "items": { "type": "string", "description": "Domains (SAN inluded) that the certificate applies to" } }, "validityStart": { "type": "string", "description": "Validity start time", "format": "date-time" }, "validityEnd": { "type": "string", "description": "Validity end time", "format": "date-time" } }, "description": "TLS Certificate" }, "TokenFailoverConfig": { "type": "object", "properties": { "enabled": { "type": "boolean" }, "failureThreshold": { "type": "integer", "format": "int32" }, "successThreshold": { "type": "integer", "format": "int32" }, "healthCheckInterval": { "type": "integer", "format": "int32" }, "healthCheckTimeout": { "type": "integer", "format": "int32" }, "healthCheckModel": { "type": "string" } }, "description": "Token Failover Config" }, "UpdateHigressConfigRequest": { "type": "object", "properties": { "config": { "type": "string", "description": "higress-config content in YAML format" } }, "description": "Update higress-config Request" }, "UpstreamService": { "type": "object", "properties": { "name": { "type": "string" }, "port": { "type": "integer", "format": "int32" }, "version": { "type": "string" }, "weight": { "type": "integer", "format": "int32" } }, "description": "Route upstream services" }, "User": { "type": "object", "properties": { "name": { "type": "string" }, "password": { "type": "string" }, "displayName": { "type": "string" }, "avatarUrl": { "type": "string" } }, "description": "The new admin user" }, "VPort": { "type": "object", "properties": { "defaultValue": { "type": "integer", "format": "int32" }, "servicesVport": { "type": "array", "items": { "$ref": "#/components/schemas/ServiceVport" } } }, "description": "Register vport configuration with default and service-specific values. Optional.", "example": { "default": 8080, "services": [ { "name": "svc1", "value": 9090 } ] } }, "WasmPlugin": { "type": "object", "properties": { "name": { "type": "string", "description": "Plugin name" }, "pluginVersion": { "type": "string", "description": "Plugin version. Fixed to 1.0.0" }, "version": { "type": "string", "description": "Plugin resource version. Required when updating." }, "category": { "type": "string", "description": "Plugin category" }, "title": { "type": "string", "description": "Plugin title for display" }, "description": { "type": "string", "description": "Plugin description for display" }, "builtIn": { "type": "boolean", "description": "Whether the plugin is built-in" }, "icon": { "type": "string", "description": "Plugin icon URL" }, "imageRepository": { "type": "string", "description": "Plugin image repository" }, "imageVersion": { "type": "string", "description": "Plugin image tag" }, "imagePullPolicy": { "type": "string", "description": "Plugin image pull policy" }, "imagePullSecret": { "type": "string", "description": "Plugin image pull secret" }, "phase": { "$ref": "#/components/schemas/PluginPhase" }, "priority": { "maximum": 1000, "minimum": 0, "type": "integer", "description": "Plugin execution priority in the given phase", "format": "int32" } }, "description": "Wasm Plugin" }, "WasmPluginConfig": { "type": "object", "properties": { "schema": { "$ref": "#/components/schemas/SchemaObject" } }, "description": "Wasm Plugin Config" }, "WasmPluginInstance": { "type": "object", "properties": { "version": { "type": "string", "description": "Plugin instance version. Required when updating." }, "scope": { "type": "string", "description": "Wasm Plugin Instance Scope", "deprecated": true, "enum": [ "GLOBAL", "DOMAIN", "ROUTE", "SERVICE", "global", "domain", "route", "service" ] }, "target": { "type": "string", "deprecated": true }, "targets": { "type": "object", "additionalProperties": { "type": "string", "description": "Plugin instance targets" }, "description": "Plugin instance targets" }, "pluginName": { "type": "string", "description": "Plugin name" }, "pluginVersion": { "type": "string", "description": "Plugin version. Fixed to 1.0.0" }, "internal": { "type": "boolean", "description": "Whether this is an internal plugin instance managed by the console itself" }, "enabled": { "type": "boolean", "description": "Whether this plugin instance is enabled" }, "rawConfigurations": { "type": "string", "description": "Raw configurations in YAML format" }, "configurations": { "type": "object", "additionalProperties": { "type": "object", "description": "Configurations" }, "description": "Configurations" } }, "description": "Wasm Plugin Instance" }, "XML": { "type": "object", "properties": { "name": { "type": "string" }, "namespace": { "type": "string" }, "prefix": { "type": "string" }, "attribute": { "type": "boolean" }, "wrapped": { "type": "boolean" }, "extensions": { "type": "object", "additionalProperties": { "type": "object" }, "writeOnly": true } } } } } }
Execute any git command on behalf of Workers without credentials by processing their git-request messages and managing workspace synchronization safely.
---
name: git-delegation-management
description: Execute git operations on behalf of Workers who don't have git credentials. Use when a Worker sends a git-request: message to clone, push, pull, commit, rebase, or perform any git operation.
---
# Git Delegation Management
This skill enables the Manager to execute **any git operation** on behalf of Workers. Workers cannot access git credentials, so they delegate all git operations to the Manager.
## Prerequisites
The Manager has access to:
- Host's `.gitconfig` via `/host-share/.gitconfig` (symlinked to `/root/.gitconfig`)
- Git credentials (SSH keys, credential helpers) configured on the host
This allows git operations to use the correct author name, email, and authentication.
---
## Handling `git-request:` Messages
When a Worker sends a message containing `git-request:`:
```
task-{task-id} git-request:
workspace: /root/hiclaw-fs/shared/tasks/{task-id}/workspace/{repo-name}
operations:
- git clone https://github.com/org/repo.git
- git checkout -b feature-auth
- git add .
- git commit -m "feat: add authentication"
- git push origin feature-auth
---CONTEXT---
{description of what they're trying to accomplish}
---END---
```
**Extract:**
- `task-id`: Task identifier
- `workspace`: Path to work in (for clone: parent directory; for other ops: repo directory)
- `operations`: List of git commands to execute (literally what to run)
- `context`: (Optional) What the Worker is trying to accomplish
---
## Execution Flow
### 1. Sync and Check Processing Marker
```bash
task_id="task-YYYYMMDD-HHMMSS"
workspace="/root/hiclaw-fs/shared/tasks/task_id/workspace/{repo-name}"
# Sync from MinIO
mc mirror "hiclaw/hiclaw-storage/shared/tasks/task_id/" \
"/root/hiclaw-fs/shared/tasks/task_id/"
# Check for processing marker
bash /opt/hiclaw/agent/skills/task-coordination/scripts/check-processing-marker.sh "$task_id"
if [ $? -ne 0 ]; then
# Respond with git-failed: explaining the conflict
exit 1
fi
# Create processing marker
bash /opt/hiclaw/agent/skills/task-coordination/scripts/create-processing-marker.sh "$task_id" "manager" 15
```
### 2. Execute Git Commands
Navigate to the workspace and execute the git commands:
```bash
cd "$workspace"
# Execute each git command
git clone https://github.com/org/repo.git
git checkout -b feature-auth
# ... etc
# Log output for debugging
```
You know how to use git. Execute the commands the Worker requests. If something goes wrong (merge conflict, authentication failure, etc.), handle it appropriately.
### 3. Cleanup and Respond
```bash
# Remove processing marker
bash /opt/hiclaw/agent/skills/task-coordination/scripts/remove-processing-marker.sh "$task_id"
# Sync to MinIO
mc mirror "/root/hiclaw-fs/shared/tasks/task_id/" \
"hiclaw/hiclaw-storage/shared/tasks/task_id/" --overwrite
```
**On success** — send to Worker:
```
@{worker}:DOMAIN task-{task-id} git-result:
Git operations completed successfully.
{Summary of what was done - commits, pushes, branches created, etc.}
Run `bash /opt/hiclaw/agent/skills/file-sync/scripts/hiclaw-sync.sh` to sync.
```
**On failure** — send to Worker:
```
@{worker}:DOMAIN task-{task-id} git-failed:
Git operation failed: {error message}
{Suggestion for how to fix it, if applicable}
```
---
## What Operations Can Be Delegated
**Any git operation**, including but not limited to:
| Category | Commands |
|----------|----------|
| Repository | `git clone`, `git init` |
| Branches | `git branch`, `git checkout`, `git switch` |
| Remote | `git remote`, `git fetch`, `git pull`, `git push` |
| Commits | `git add`, `git commit`, `git reset`, `git revert` |
| History | `git log`, `git show`, `git diff` |
| Rebase | `git rebase`, `git rebase -i` |
| Cherry-pick | `git cherry-pick` |
| Merge | `git merge` |
| Stash | `git stash` |
| Tags | `git tag` |
| Submodules | `git submodule` |
| Config | `git config` (local to repo) |
If git can do it, the Worker can delegate it.
---
## Error Handling
When git operations fail:
1. **Read the error message** and understand what went wrong
2. **Try to fix it** if it's a simple issue (e.g., set upstream, configure user locally)
3. **Report to Worker** if it requires their action (e.g., merge conflicts, rebasing decisions)
4. **Escalate to admin** if it's a credential or permission issue
Common issues:
- Merge conflicts → Ask Worker to resolve locally
- Authentication failure → Check `/host-share/.gitconfig` and credential helper
- Branch divergence → Worker may need to pull/rebase first
---
## Integration with Task Coordination
Always use the `.processing` marker to prevent conflicts when both Worker and Manager might modify the workspace.
<!-- hiclaw-builtin-end -->
FILE:_meta.json
{"ownerId": "local", "slug": "git-delegation-management", "version": "1.0.0", "publishedAt": 1773995073000}
Manage and execute AI coding CLI tools on behalf of Workers by running their coding prompts in the Worker’s workspace and returning results.
---
name: coding-cli-management
description: Execute AI coding CLI tools (Claude Code / Gemini CLI / qodercli) on behalf of Workers. Use when a Worker sends a coding-request: message, asking Manager to run coding operations in their workspace.
---
# Coding CLI Management
This skill enables the Manager to execute AI coding CLI tools (claude/gemini/qodercli) on behalf of Workers. Workers generate precise prompts; the Manager runs the CLI in the Worker's workspace and returns the result.
## Config File
Path: `~/coding-cli-config.json`
```json
{
"enabled": true,
"cli": "claude",
"confirmed_at": "2026-02-23T10:00:00Z"
}
```
| `enabled` | `cli` | Meaning |
|-----------|-------|---------|
| `false` | any | Admin declined; use normal task flow |
| `true` | `"claude"` / `"gemini"` / `"qodercli"` | Active — use this CLI |
---
## Step 1: First-Time Detection (before assigning a coding task)
Run when `~/coding-cli-config.json` does not exist:
```bash
bash /opt/hiclaw/agent/skills/coding-cli-management/scripts/detect-available-cli.sh
```
**If no CLIs are available** (`available` array is empty):
```bash
echo '{"enabled":false,"cli":null,"confirmed_at":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"}' \
> ~/coding-cli-config.json
```
Proceed with normal task assignment (Worker codes on their own).
**If CLIs are available**, ask the admin via the primary channel or Matrix DM — **in the language the admin used**:
> I found the following AI coding CLI tools available: [list]. Would you like to enable CLI delegation mode? Workers will generate coding prompts, and I'll use the CLI tool to make the code changes. Reply with the tool name (claude/gemini/qodercli) to enable, or 'no' to have workers code on their own.
On admin reply:
- Tool name (`claude` / `gemini` / `qodercli`):
```bash
echo '{"enabled":true,"cli":"<chosen-tool>","confirmed_at":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"}' \
> ~/coding-cli-config.json
```
- `"no"` or decline:
```bash
echo '{"enabled":false,"cli":null,"confirmed_at":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"}' \
> ~/coding-cli-config.json
```
---
## Step 2: Assigning a Coding Task (CLI mode enabled)
When `coding-cli-config.json` has `enabled: true`:
1. **Ensure the Worker has the `coding-cli` skill.** Check `workers-registry.json`:
```bash
cat ~/hiclaw-fs/agents/manager/workers-registry.json | jq '.workers[] | select(.name=="<worker>") | .skills'
```
If `coding-cli` is missing, distribute it:
```bash
bash /opt/hiclaw/agent/skills/worker-management/scripts/push-worker-skills.sh \
--worker <worker-name> --skill coding-cli
```
2. **Add a "Coding CLI Mode" section to spec.md** (see template below).
---
## Step 3: Handling a `coding-request:` Message
When a Worker sends a message containing `coding-request:` (in their Worker Room or a Project Room):
**Parse the message:**
```
task-{task-id} coding-request:
workspace: ~/hiclaw-fs/shared/tasks/{task-id}/workspace
---PROMPT---
{prompt content}
---END---
```
**Execute:**
```bash
# 1. Sync workspace from MinIO
task_id="task-YYYYMMDD-HHMMSS"
workspace="/root/hiclaw-fs/shared/tasks/task_id/workspace"
mc mirror "hiclaw/hiclaw-storage/shared/tasks/task_id/" "/root/hiclaw-fs/shared/tasks/task_id/"
# 2. Check for processing marker (task coordination)
bash /opt/hiclaw/agent/skills/task-coordination/scripts/check-processing-marker.sh "$task_id"
if [ $? -ne 0 ]; then
# Another process is working on this task
echo "Task task_id is being processed by another operation. Retry later."
exit 1
fi
# 3. Create processing marker
bash /opt/hiclaw/agent/skills/task-coordination/scripts/create-processing-marker.sh "$task_id" "manager" 15
# 4. Save prompt to file
timestamp=$(date +%Y%m%d-%H%M%S)
prompt_dir="/root/hiclaw-fs/shared/tasks/task_id/coding-prompts"
mkdir -p "$prompt_dir"
prompt_file="$prompt_dir/timestamp.txt"
cat > "$prompt_file" << 'PROMPT_EOF'
{extracted prompt content}
PROMPT_EOF
# 5. Get configured CLI
cli=$(jq -r '.cli' ~/coding-cli-config.json)
# 6. Run CLI
bash /opt/hiclaw/agent/skills/coding-cli-management/scripts/run-coding-cli.sh \
--cli "$cli" \
--workspace "$workspace" \
--prompt-file "$prompt_file" \
--timeout 600
exit_code=$?
# 7. Remove processing marker
bash /opt/hiclaw/agent/skills/task-coordination/scripts/remove-processing-marker.sh "$task_id"
# 8. On success (exit 0): push changes to MinIO
if [ "$exit_code" -eq 0 ]; then
mc mirror "/root/hiclaw-fs/shared/tasks/task_id/workspace/" "hiclaw/hiclaw-storage/shared/tasks/task_id/workspace/" --overwrite
fi
```
**On success** — send to Worker in the same Room:
```
@{worker}:DOMAIN task-{task-id} coding-result:
CLI 工具已完成编码。请同步工作目录并 review 变更:
bash /opt/hiclaw/agent/skills/file-sync/scripts/hiclaw-sync.sh
变更记录:~/hiclaw-fs/shared/tasks/{task-id}/workspace/coding-cli-logs/
```
**On failure** (exit ≠ 0 or timeout) — see Step 4.
---
## Step 4: Handling Failure
**Notify Worker** in the task Room:
```
@{worker}:DOMAIN task-{task-id} coding-failed:
CLI 工具执行失败(exit code: {code})。请自行完成编码任务。
你生成的提示词已保存于:~/hiclaw-fs/shared/tasks/{task-id}/coding-prompts/
```
**Notify Human Admin** via escalate-to-admin.sh or primary channel:
```
Worker {worker-name} 的编码委托任务 {task-id} 中,{cli} 工具执行失败。
错误信息:{last lines from log file}
建议检查:
- ~/.{cli}/ 凭证是否有效(token 是否过期)
- /host-share/.{cli}/ 软链是否正常(ls -la /root/.{cli})
- {cli} binary 是否在容器内可用(which {cli})
```
**Record in config** (optional, for heartbeat diagnostics):
```bash
jq --arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" --arg tid "$task_id" \
'.last_failure = {task_id: $tid, failed_at: $ts}' \
~/coding-cli-config.json > /tmp/cfg.json && \
mv /tmp/cfg.json ~/coding-cli-config.json
```
---
## Spec.md Coding CLI Mode Template
Append to the end of spec.md when CLI mode is enabled:
```markdown
## Coding CLI Mode
本任务涉及代码修改。请使用 **Coding CLI 委托模式** 完成:
1. 克隆/准备代码到工作目录:`~/hiclaw-fs/shared/tasks/{task-id}/workspace/`
2. 推送到 MinIO:`mc mirror ~/hiclaw-fs/shared/tasks/{task-id}/workspace/ hiclaw/hiclaw-storage/shared/tasks/{task-id}/workspace/`
3. 根据你的理解和 `coding-cli` skill 生成编码提示词,发送给我
4. 等待我执行 CLI 工具并返回结果
5. Sync 拉取变更:`bash /opt/hiclaw/agent/skills/file-sync/scripts/hiclaw-sync.sh`
6. Review 变更并报告完成
如收到 `coding-failed:`,请自行完成编码工作。
```
<!-- hiclaw-builtin-end -->
FILE:_meta.json
{"ownerId": "local", "slug": "coding-cli-management", "version": "1.0.0", "publishedAt": 1773997350000}
FILE:scripts/detect-available-cli.sh
#!/bin/bash
# Detect available AI coding CLI tools and their config directories
# Output: JSON with available tools and details
# Usage: bash detect-available-cli.sh
result='{"available":[],"details":{}}'
for cli in claude gemini qodercli; do
binary_ok=false
config_ok=false
if command -v "$cli" &>/dev/null; then
binary_ok=true
fi
case "$cli" in
claude) [ -d "$HOME/.claude" ] && config_ok=true ;;
gemini) [ -d "$HOME/.gemini" ] && config_ok=true ;;
qodercli) [ -d "$HOME/.qoder" ] && config_ok=true ;;
esac
if $binary_ok && $config_ok; then
result=$(echo "$result" | jq --arg c "$cli" '.available += [$c]')
fi
result=$(echo "$result" | jq \
--arg c "$cli" \
--argjson b "$binary_ok" \
--argjson co "$config_ok" \
'.details[$c] = {binary: $b, config: $co}')
done
echo "$result"
FILE:scripts/run-coding-cli.sh
#!/bin/bash
# Execute an AI coding CLI tool in a given workspace
# Usage: run-coding-cli.sh --cli <tool> --workspace <dir> --prompt-file <file> [--timeout <secs>]
set -e
cli=""
workspace=""
prompt_file=""
timeout_secs=600
while [[ $# -gt 0 ]]; do
case "$1" in
--cli) cli="$2"; shift 2 ;;
--workspace) workspace="$2"; shift 2 ;;
--prompt-file) prompt_file="$2"; shift 2 ;;
--timeout) timeout_secs="$2"; shift 2 ;;
*) echo "Unknown argument: $1" >&2; exit 1 ;;
esac
done
if [ -z "$cli" ] || [ -z "$workspace" ] || [ -z "$prompt_file" ]; then
echo "Usage: $0 --cli <tool> --workspace <dir> --prompt-file <file> [--timeout <secs>]" >&2
exit 1
fi
if [ ! -f "$prompt_file" ]; then
echo "Prompt file not found: $prompt_file" >&2
exit 1
fi
if [ ! -d "$workspace" ]; then
echo "Workspace directory not found: $workspace" >&2
exit 1
fi
# Save output to log file in the workspace's coding-cli-logs directory
log_dir="$workspace/coding-cli-logs"
mkdir -p "$log_dir"
timestamp=$(date +%Y%m%d-%H%M%S)
log_file="$log_dir/run-timestamp.log"
echo "[run-coding-cli] cli=$cli workspace=$workspace prompt_file=$prompt_file timeout=timeout_secss"
echo "[run-coding-cli] Log: $log_file"
cd "$workspace"
case "$cli" in
claude)
timeout "$timeout_secs" claude -p "$(cat "$prompt_file")" \
--dangerously-skip-permissions --output-format text 2>&1 | tee "$log_file"
exit_code=PIPESTATUS[0]
;;
gemini)
timeout "$timeout_secs" gemini -p "$(cat "$prompt_file")" -y 2>&1 | tee "$log_file"
exit_code=PIPESTATUS[0]
;;
qodercli)
timeout "$timeout_secs" qodercli -p "$(cat "$prompt_file")" \
--yolo -w "$workspace" 2>&1 | tee "$log_file"
exit_code=PIPESTATUS[0]
;;
*)
echo "Unknown CLI tool: $cli. Supported: claude, gemini, qodercli" >&2 | tee -a "$log_file"
exit 1
;;
esac
if [ "$exit_code" -eq 124 ]; then
echo "[run-coding-cli] TIMEOUT after timeout_secss" | tee -a "$log_file"
exit 124
fi
echo "[run-coding-cli] Finished with exit code $exit_code" | tee -a "$log_file"
exit "$exit_code"
Manage multiple communication channels, admin identity recognition, and primary channel configuration
--- name: channel-management description: Manage multiple communication channels, admin identity recognition, and primary channel configuration assign_when: Not assigned to workers — this is a manager-only capability --- # Channel Management Skill ## Identity Recognition When receiving a message in any room, determine the sender's identity. The rules differ by context: ### DM (any channel) All DM senders are **Human Admin** — OpenClaw allowlist guarantees only the admin can DM you. ### Matrix Group Room Matrix rooms may contain the admin, Workers, trusted contacts, and unknown users. Identify by Matrix user ID: | Sender | How to identify | Action | |--------|----------------|--------| | **Human Admin** | `@HICLAW_ADMIN_USER:HICLAW_MATRIX_DOMAIN` | Full trust — execute any request | | **Worker** | Registered in `~/workers-registry.json` | Normal Worker interaction (task handoffs, status updates) | | **Trusted Contact** | `{"channel": "matrix", "sender_id": "<matrix_user_id>"}` in `~/trusted-contacts.json` | Respond to general questions; withhold sensitive info; deny management operations | | **Unknown** | None of the above | **Silently ignore** — no response | ### Non-Matrix Group Room (Discord, Telegram, etc.) | Sender | How to identify | Action | |--------|----------------|--------| | **Human Admin** | `sender_id` matches `primary-channel.json`'s `sender_id` (same channel type) | Full trust | | **Trusted Contact** | `{channel, sender_id}` in `~/trusted-contacts.json` | Restricted trust (same rules as above) | | **Unknown** | None of the above | **Silently ignore** | ## Trusted Contacts File: `~/trusted-contacts.json` ```json { "contacts": [ { "channel": "discord", "sender_id": "987654321098765432", "approved_at": "2026-02-23T10:00:00Z", "note": "optional label" } ] } ``` ### Adding a Trusted Contact Trigger: unknown sender messages in a group room → silently ignore. If the human admin then says "you can talk to the person who just messaged" (or equivalent): 1. Identify the most recent unknown sender's `channel` and `sender_id` from the current session context 2. Append to `trusted-contacts.json`: ```bash # Read existing, append, write back (use jq) jq --arg ch "<channel>" --arg sid "<sender_id>" --arg ts "<ISO-8601 now>" \ '.contacts += [{"channel": $ch, "sender_id": $sid, "approved_at": $ts, "note": ""}]' \ ~/trusted-contacts.json > /tmp/tc.json && \ mv /tmp/tc.json ~/trusted-contacts.json ``` If file doesn't exist yet: `echo '{"contacts":[]}' > ~/trusted-contacts.json` first. 3. Confirm to admin in their language, e.g.: "OK, I'll engage with them. Note: I won't share any sensitive information with them." ### Communicating with Trusted Contacts When a trusted contact sends a message: - Respond normally to general questions - **Never share**: API keys, tokens, passwords, Worker credentials, internal system configuration, or any other sensitive operational data - **Never execute**: management operations (create/delete workers, change config, assign tasks, etc.) - If they ask for something outside their role, decline politely and suggest they contact the admin directly ### Removing a Trusted Contact When admin revokes access ("don't talk to X anymore"): ```bash jq --arg ch "<channel>" --arg sid "<sender_id>" \ '.contacts |= map(select(.channel != $ch or .sender_id != $sid))' \ ~/trusted-contacts.json > /tmp/tc.json && \ mv /tmp/tc.json ~/trusted-contacts.json ``` ## Primary Channel State File: `~/primary-channel.json` ```json { "confirmed": true, "channel": "discord", "to": "user:123456789012345678", "sender_id": "123456789012345678", "channel_name": "Discord", "confirmed_at": "2026-02-22T10:00:00Z" } ``` Fields: - `confirmed`: `true` = use this channel for proactive notifications; `false` = Matrix DM fallback - `channel`: channel identifier string, used as the `channel` parameter when calling the `message` tool (e.g. `"discord"`, `"telegram"`, `"slack"`) - `to`: recipient identifier, used as the `target` parameter when calling the `message` tool. Format varies by channel: - Discord DM: `user:USER_ID` (e.g. `user:123456789012345678`) - Feishu DM: open_id,即 `ou_` 开头的字符串(e.g. `ou_abc123def456`);群聊则用 `chat_id`(`oc_` 开头) - Telegram: chat ID (e.g. `123456789`) - WhatsApp/Signal: phone number (e.g. `+15551234567`) - `sender_id`: the admin's raw ID on that channel (used for identity tracking) - `channel_name`: human-readable name for display (e.g. `"Discord"`, `"飞书"`) - `confirmed_at`: ISO-8601 timestamp when the admin confirmed this choice Read with: ```bash bash /opt/hiclaw/agent/skills/channel-management/scripts/manage-primary-channel.sh --action show ``` ## Sending Messages to Primary Channel Use the built-in `message` tool to send proactive notifications (daily reminders, heartbeat check-ins, task updates, escalation questions) to the admin on their primary channel. ### Steps 1. Read `primary-channel.json`: ```bash bash /opt/hiclaw/agent/skills/channel-management/scripts/manage-primary-channel.sh --action show ``` 2. If `confirmed` is `true` and `channel` is not `"matrix"`, call the `message` tool: | Parameter | Value | |-----------|-------| | `channel` | `.channel` from the file (e.g. `"discord"`) | | `target` | `.to` from the file (e.g. `"user:123456789012345678"`) | | `message` | Your notification text | 3. If `confirmed` is `false`, `.channel` is `"matrix"`, or the file doesn't exist — fall back to Matrix DM. ### Example Given `primary-channel.json`: ```json {"confirmed": true, "channel": "discord", "to": "user:123456789012345678"} ``` Call the `message` tool with: - `channel`: `"discord"` - `target`: `"user:123456789012345678"` - `message`: `"You have 2 tasks pending review. Want me to summarize?"` ### Notes - The `message` tool is a built-in OpenClaw tool — no HTTP calls or scripts needed. - When calling `message` from within a Matrix session, you MUST explicitly set `channel` and `target`; otherwise the message goes to the current Matrix room. - The `target` parameter corresponds to the `to` field in `primary-channel.json`. Despite the name difference, pass the value directly without transformation. ## First-Contact Protocol Trigger: admin sends a DM from a channel that doesn't match `primary-channel.json`'s `.channel`. Steps: 1. Read `primary-channel.json` — check if `.channel` matches the current session's channel: ```bash bash /opt/hiclaw/agent/skills/channel-management/scripts/manage-primary-channel.sh --action show ``` 2. Respond to the admin's message normally 3. Send a follow-up asking about primary channel preference, **in the same language the admin used in their message**: > I noticed this is your first time contacting me via [Channel Name]. Would you like to set [Channel Name] as your primary channel? If so, my daily reminders and proactive notifications will be sent here instead of Matrix DM. Reply "yes" to confirm, or "no" to keep using Matrix DM. 4. On **"yes" / "confirm" / 「是」/ 「确认」** (or equivalent in their language): ```bash bash /opt/hiclaw/agent/skills/channel-management/scripts/manage-primary-channel.sh \ --action confirm --channel "<channel>" --to "<to>" \ --sender-id "<sender_id>" --channel-name "<Channel Name>" ``` 5. On **「否」/ "no"**: ```bash bash /opt/hiclaw/agent/skills/channel-management/scripts/manage-primary-channel.sh --action reset ``` Matrix DM remains primary. 6. On no reply (session ends): leave unchanged; Matrix DM remains primary ## Changing Primary Channel When admin requests a switch (e.g. "switch to Discord as primary", "切换到飞书作为主频道", etc.), in any language: 1. Read current state: ```bash bash /opt/hiclaw/agent/skills/channel-management/scripts/manage-primary-channel.sh --action show ``` 2. Update to the new channel: ```bash bash /opt/hiclaw/agent/skills/channel-management/scripts/manage-primary-channel.sh \ --action confirm --channel "<channel>" --to "<to>" \ --sender-id "<sender_id>" --channel-name "<Channel Name>" ``` 3. Confirm in the admin's language, e.g.: "Primary channel switched to [Channel Name]. Daily reminders and proactive notifications will now be sent there." ## Cross-Channel Escalation When blocked on an admin decision while working in a Matrix room: ### When to Use - Blocked on irreversible action needing explicit approval - Worker/project is stalled and needs admin judgment call - Cannot wait for next heartbeat or scheduled DM check-in ### How to Escalate 1. Resolve the notification channel: ```bash bash /opt/hiclaw/agent/skills/task-management/scripts/resolve-notify-channel.sh ``` 2. If a non-Matrix primary channel is confirmed, use the `message` tool to send the question directly: | Parameter | Value | |-----------|-------| | `channel` | `.channel` from the file | | `target` | `.to` from the file | | `message` | A clear, friendly escalation message containing the question and asking the admin to reply | 3. After sending, note the pending escalation in your memory so you can connect the admin's reply back to the blocked workflow when it arrives. ### Reply Handling When the admin replies on the primary channel, you will receive their message in a DM session for that channel. At that point: 1. Recognize the reply as the answer to the pending escalation 2. Continue the blocked workflow in the original Matrix room 3. @mention relevant workers in the room with the outcome ### Fallback If `primary-channel.json` is missing, `confirmed` is `false`, or channel is `matrix`: fall back to @mentioning the admin in the current Matrix room. ## Troubleshooting **通知发送到错误目标**:管理员反映收不到通知。检查 `primary-channel.json` 的 `to` 字段是否正确,向管理员确认其频道 ID 后重新写入。 **Message tool send failure**: 使用 `message` 工具发送到主用频道失败时: 1. Is openclaw running? (`ps aux | grep openclaw`) 2. Is the target channel configured in openclaw? (check the corresponding channel config, e.g. `channels.discord.enabled`) 3. Is the `to` value in `primary-channel.json` correct for the channel format? (see "Primary Channel State" field descriptions above) 4. Fallback to Matrix DM is automatic; no manual intervention needed for individual failures **Admin confirmed wrong channel**: Admin wants to revert to Matrix DM: ```bash bash /opt/hiclaw/agent/skills/channel-management/scripts/manage-primary-channel.sh --action reset ``` <!-- hiclaw-builtin-end --> FILE:_meta.json {"ownerId": "local", "slug": "channel-management", "version": "1.0.0", "publishedAt": 1773995073000} FILE:scripts/manage-primary-channel.sh #!/bin/bash # manage-primary-channel.sh - Atomic primary-channel.json operations # # Replaces manual cat/jq writes by the Agent with validated, atomic script calls. # # Usage: # manage-primary-channel.sh --action confirm --channel CH --to TO --sender-id SID [--channel-name NAME] # manage-primary-channel.sh --action reset # manage-primary-channel.sh --action show # # Actions: # confirm Set primary channel with validation (requires --channel, --to, --sender-id) # reset Reset to unconfirmed state (Matrix DM fallback) # show Print current primary-channel.json (or default if missing) set -euo pipefail PRIMARY_CHANNEL_FILE="HOME/primary-channel.json" _ts() { date -u '+%Y-%m-%dT%H:%M:%SZ' } action_confirm() { # Validate required fields are non-empty if [ -z "$CHANNEL" ]; then echo "ERROR: --channel is required and cannot be empty" >&2 exit 1 fi if [ "$CHANNEL" = "matrix" ]; then echo "ERROR: primary channel cannot be 'matrix' — Matrix DM is the default fallback. Use --action reset to revert to Matrix DM." >&2 exit 1 fi if [ -z "$TO" ]; then echo "ERROR: --to is required and cannot be empty" >&2 exit 1 fi if [ -z "$SENDER_ID" ]; then echo "ERROR: --sender-id is required and cannot be empty" >&2 exit 1 fi # Default channel_name to capitalized channel if not provided local name="-$(echo "$CHANNEL" | awk '{print toupper(substr($0,1,1)) tolower(substr($0,2))')}" local tmp tmp=$(mktemp) jq -n \ --argjson confirmed true \ --arg channel "$CHANNEL" \ --arg to "$TO" \ --arg sender_id "$SENDER_ID" \ --arg channel_name "$name" \ --arg confirmed_at "$(_ts)" \ '{ confirmed: $confirmed, channel: $channel, to: $to, sender_id: $sender_id, channel_name: $channel_name, confirmed_at: $confirmed_at }' > "$tmp" && mv "$tmp" "$PRIMARY_CHANNEL_FILE" echo "OK: primary channel set to $name ($CHANNEL), target=$TO" } action_reset() { local tmp tmp=$(mktemp) jq -n --argjson confirmed false '{confirmed: $confirmed}' > "$tmp" && mv "$tmp" "$PRIMARY_CHANNEL_FILE" echo "OK: primary channel reset to unconfirmed (Matrix DM fallback)" } action_show() { if [ -f "$PRIMARY_CHANNEL_FILE" ]; then cat "$PRIMARY_CHANNEL_FILE" else echo '{"confirmed":false}' fi } # ─── Argument parsing ───────────────────────────────────────────────────────── ACTION="" CHANNEL="" TO="" SENDER_ID="" CHANNEL_NAME="" while [[ $# -gt 0 ]]; do case "$1" in --action) ACTION="$2"; shift 2 ;; --channel) CHANNEL="$2"; shift 2 ;; --to) TO="$2"; shift 2 ;; --sender-id) SENDER_ID="$2"; shift 2 ;; --channel-name) CHANNEL_NAME="$2"; shift 2 ;; *) echo "Unknown argument: $1" >&2 exit 1 ;; esac done if [ -z "$ACTION" ]; then echo "Usage: $0 --action <confirm|reset|show> [options]" >&2 echo "" >&2 echo "Actions:" >&2 echo " confirm --channel CH --to TO --sender-id SID [--channel-name NAME]" >&2 echo " reset Reset to unconfirmed (Matrix DM fallback)" >&2 echo " show Print current state" >&2 exit 1 fi case "$ACTION" in confirm) action_confirm ;; reset) action_reset ;; show) action_show ;; *) echo "ERROR: Unknown action '$ACTION'. Use: confirm, reset, show" >&2 exit 1 ;; esac