## AI assistant (`ai`)

Model connection settings and connection test, the model rating table, availability and quota, conversation history, and the assistant look.

Authentication: User · Docs: https://www-demo.kuxitong.com/en/docs/api/ai

### GET `/api/v2/ai/conversations`

List my AI conversations · Authentication: User

```sh
curl "https://panel.example.com/api/v2/ai/conversations" \
  -H "X-API-Key: $GOCDN_API_KEY"
```

### GET `/api/v2/ai/conversations/{id}`

Get my AI conversation · Authentication: User

```sh
curl "https://panel.example.com/api/v2/ai/conversations/{id}" \
  -H "X-API-Key: $GOCDN_API_KEY"
```

### DELETE `/api/v2/ai/conversations/{id}`

Delete my AI conversation · Authentication: User

```sh
curl -X DELETE "https://panel.example.com/api/v2/ai/conversations/{id}" \
  -H "X-API-Key: $GOCDN_API_KEY"
```

### GET `/api/v2/ai/look`

Get my assistant look · Authentication: User

```sh
curl "https://panel.example.com/api/v2/ai/look" \
  -H "X-API-Key: $GOCDN_API_KEY"
```

### PUT `/api/v2/ai/look`

Save my assistant look · Authentication: User

Request body:

| Field | Type | Required | Description |
|---|---|---|---|
| `name` | string | Yes | Assistant name; empty means the default name. |
| `pet` | AiPet | Yes | Assistant figure: orb, cat, dog, bot, or ai (drawn from the custom parameters in spec). Values: ["orb","cat","dog","bot","ai"] |
| `spec` | AiLookSpec |  | Parameters of the AI custom figure (whitelisted values only; the panel draws it from fixed SVG parts). Absent from AiLook when never customised. Required when saving with pet ai or theme custom (code required); omitted means the stored one is kept. The server re-checks and normalises it (lowercase colours, primary darkened until white text is readable). |
| `theme` | AiTheme | Yes | Assistant accent colour: blue, teal, sunset, morandi, ink, or custom (the three colours in the custom parameters, spec). Applies to the assistant panel only. Values: ["blue","teal","sunset","morandi","ink","custom"] |

```sh
curl -X PUT "https://panel.example.com/api/v2/ai/look" \
  -H "X-API-Key: $GOCDN_API_KEY"
```

### GET `/api/v2/ai/look/avatar`

Get my uploaded assistant avatar · Authentication: User

```sh
curl "https://panel.example.com/api/v2/ai/look/avatar" \
  -H "X-API-Key: $GOCDN_API_KEY"
```

### PUT `/api/v2/ai/look/avatar`

Upload my assistant avatar · Authentication: User

```sh
curl -X PUT "https://panel.example.com/api/v2/ai/look/avatar" \
  -H "X-API-Key: $GOCDN_API_KEY"
```

### DELETE `/api/v2/ai/look/avatar`

Remove my uploaded assistant avatar · Authentication: User

```sh
curl -X DELETE "https://panel.example.com/api/v2/ai/look/avatar" \
  -H "X-API-Key: $GOCDN_API_KEY"
```

### POST `/api/v2/ai/look/generate`

Generate a custom assistant figure from a description · Authentication: User

Request body:

| Field | Type | Required | Description |
|---|---|---|---|
| `text` | string | Yes | The look you want, at most 60 characters after control characters and angle brackets are removed. |

```sh
curl -X POST "https://panel.example.com/api/v2/ai/look/generate" \
  -H "X-API-Key: $GOCDN_API_KEY"
```

### POST `/api/v2/ai/messages`

Send a message to the AI assistant · Authentication: User

Request body:

| Field | Type | Required | Description |
|---|---|---|---|
| `context` | AiContext |  | Current page context: only the page name and the ID of the open item; the server fetches the data. Pages with detailed data: home, attack_logs (ref = record ID), sites (ref = site ID); other pages pass only the name. |
| `conversation_id` | integer |  | Conversation to continue; omit to start a new one (titled from this message). |
| `text` | string | Yes | The look you want, at most 60 characters after control characters and angle brackets are removed. |

```sh
curl -X POST "https://panel.example.com/api/v2/ai/messages" \
  -H "X-API-Key: $GOCDN_API_KEY"
```

### GET `/api/v2/ai/models`

List AI model ratings · Authentication: Admin only

```sh
curl "https://panel.example.com/api/v2/ai/models" \
  -H "X-API-Key: $GOCDN_API_KEY"
```

### POST `/api/v2/ai/plans/cancel`

Cancel an AI assistant plan · Authentication: User

Request body:

| Field | Type | Required | Description |
|---|---|---|---|
| `plan_id` | AiPlanKey | Yes | Plan id (random, 32 hex digits). |

```sh
curl -X POST "https://panel.example.com/api/v2/ai/plans/cancel" \
  -H "X-API-Key: $GOCDN_API_KEY"
```

### POST `/api/v2/ai/plans/execute`

Execute an AI assistant plan · Authentication: User

Request body:

| Field | Type | Required | Description |
|---|---|---|---|
| `password` | string |  | Current login password. |
| `plan_id` | AiPlanKey | Yes | Plan id (random, 32 hex digits). |
| `totp_code` | string |  | Current 6-digit TOTP code; the account must have TOTP enabled. |

```sh
curl -X POST "https://panel.example.com/api/v2/ai/plans/execute" \
  -H "X-API-Key: $GOCDN_API_KEY"
```

### POST `/api/v2/ai/plans/revise`

Revise the parameters of an AI assistant plan · Authentication: User

Request body:

| Field | Type | Required | Description |
|---|---|---|---|
| `domain` | string | Yes | Site domain. |
| `origin` | string | Yes | Origin address (IP or hostname). |
| `plan_id` | AiPlanKey | Yes | Plan id (random, 32 hex digits). |
| `port` | integer | Yes | Origin port. |
| `upid` | integer | Yes | Purchased package to use (must belong to the plan's owning tenant). |

```sh
curl -X POST "https://panel.example.com/api/v2/ai/plans/revise" \
  -H "X-API-Key: $GOCDN_API_KEY"
```

### GET `/api/v2/ai/plans/{plan_id}`

Get an AI assistant plan · Authentication: User

```sh
curl "https://panel.example.com/api/v2/ai/plans/{plan_id}" \
  -H "X-API-Key: $GOCDN_API_KEY"
```

### GET `/api/v2/ai/settings`

Get AI assistant settings · Authentication: Admin only

```sh
curl "https://panel.example.com/api/v2/ai/settings" \
  -H "X-API-Key: $GOCDN_API_KEY"
```

### PUT `/api/v2/ai/settings`

Save AI assistant settings · Authentication: Admin only

Request body:

| Field | Type | Required | Description |
|---|---|---|---|
| `api_key` | string |  | API key; omit to keep the stored one, or send an empty string to clear it (which disables the assistant). Stored sealed and never returned. |
| `api_type` | AiApiType | Yes | API type: openai is OpenAI-compatible (/chat/completions, also used by most providers in mainland China); claude is the native Anthropic API (/messages); moonshot is Kimi (OpenAI-compatible with a different default address). Values: ["openai","claude","moonshot"] |
| `base_url` | string |  | Service address (public HTTPS); empty if never saved. |
| `model` | string | Yes | Model name. |

```sh
curl -X PUT "https://panel.example.com/api/v2/ai/settings" \
  -H "X-API-Key: $GOCDN_API_KEY"
```

### POST `/api/v2/ai/settings/probe`

Test AI assistant connection · Authentication: Admin only

Request body:

| Field | Type | Required | Description |
|---|---|---|---|
| `api_key` | string |  | API key; omit to keep the stored one, or send an empty string to clear it (which disables the assistant). Stored sealed and never returned. |
| `api_type` | AiApiType | Yes | API type: openai is OpenAI-compatible (/chat/completions, also used by most providers in mainland China); claude is the native Anthropic API (/messages); moonshot is Kimi (OpenAI-compatible with a different default address). Values: ["openai","claude","moonshot"] |
| `base_url` | string |  | Service address (public HTTPS); empty if never saved. |
| `model` | string | Yes | Model name. |

```sh
curl -X POST "https://panel.example.com/api/v2/ai/settings/probe" \
  -H "X-API-Key: $GOCDN_API_KEY"
```

### GET `/api/v2/ai/status`

Get AI assistant availability · Authentication: User

```sh
curl "https://panel.example.com/api/v2/ai/status" \
  -H "X-API-Key: $GOCDN_API_KEY"
```

AI assistant object:

| Field | Type | Required | Description |
|---|---|---|---|
| `api_key` | string |  | API key; omit to keep the stored one, or send an empty string to clear it (which disables the assistant). Stored sealed and never returned. |
| `api_type` | AiApiType |  | API type: openai is OpenAI-compatible (/chat/completions, also used by most providers in mainland China); claude is the native Anthropic API (/messages); moonshot is Kimi (OpenAI-compatible with a different default address). Values: ["openai","claude","moonshot"] |
| `available` | boolean |  | Whether the assistant is shown and usable; true but read-only for a delegated session (reason=delegated). |
| `avatar_ver` | integer |  | Avatar version; 0 means no uploaded avatar (the chosen figure is shown), above 0 fetch it with GET /ai/look/avatar; grows on every change. |
| `base_url` | string |  | Service address (public HTTPS); empty if never saved. |
| `cert_id` | integer |  | The requested certificate. |
| `cname` | string |  | CNAME target from the create response; while waiting for DNS the user points the domain to it. |
| `code` | string |  | Failure detail: blocked (address rejected, such as private), auth (key rejected), rate_limited (upstream rate limit), timeout, refused (model refused), protocol (malformed response), http (other status code), connect (unreachable). |
| `connect_ms` | integer |  | Connect time in milliseconds (latest request). |
| `context` | AiContext |  | Current page context: only the page name and the ID of the open item; the server fetches the data. Pages with detailed data: home, attack_logs (ref = record ID), sites (ref = site ID); other pages pass only the name. |
| `conversation_id` | integer |  | Conversation to continue; omit to start a new one (titled from this message). |
| `created_at` | string |  | Created at. |
| `detail` | string |  | Explanation for the admin (includes an upstream error excerpt, never the key). |
| `domain` | string | Yes | Site domain. |
| `error` | string |  | Why the plan failed. |
| `expires_at` | string |  | The plan cannot be executed after this time. |
| `fetched_on` | string |  | Date the data was fetched. |
| `first_token_ms` | integer |  | Slowest first-token time in milliseconds over the rounds run. |
| `high_risk` | boolean |  | Re-authentication is required before executing. |
| `id` | integer |  | Conversation ID. |
| `items` | AiConversation[] |  | Conversations (without messages). |
| `key_set` | boolean |  | Whether an API key is set (the key itself is never returned). |
| `kind` | AiPlanKind |  | create_site: add a site (HTTP first; the certificate is requested after DNS is set up); delete_site: delete a site (high risk, re-authentication required). Values: ["create_site","delete_site"] |
| `messages` | AiMessage[] |  | All messages (only when getting a single conversation). |
| `model` | string |  | Model name. |
| `name` | string |  | Assistant name; empty means the default name. |
| `ok` | boolean |  | Whether the probe passed. |
| `origin` | string | Yes | Origin address (IP or hostname). |
| `outdated` | boolean |  | Data is more than 90 days old; the panel shows that ratings may be outdated. |
| `params` | AiPlanParams |  | Frozen plan parameters. Adding a site: domain, origin, port, upid, package (plus tenant_id when an admin creates for a tenant); deleting a site: site_id, with site_name and domains for review. |
| `password` | string |  | Current login password. |
| `pet` | AiPet |  | Assistant figure: orb, cat, dog, bot, or ai (drawn from the custom parameters in spec). Values: ["orb","cat","dog","bot","ai"] |
| `plan_id` | AiPlanKey | Yes | Plan id (random, 32 hex digits). |
| `port` | integer | Yes | Origin port. |
| `probe_first_token_ms` | integer |  | Slowest first-token time in milliseconds over the 3 probe rounds; 0 if not passed. |
| `probe_ok` | boolean |  | Whether the save-time probe passed; reset when the model or key changes. |
| `probe_round_ms` | integer |  | Slowest round time in milliseconds over the 3 probe rounds; 0 if not passed. |
| `probed_at` | string |  | When the probe passed; null if not passed. |
| `ready` | boolean |  | Whether the settings are usable (key set, model set and probe passed); the license is checked separately, see /ai/status. |
| `reason` | string |  | Why unavailable: unlicensed (not enabled), expired (license expired), not_configured (the admin has not connected a model), delegated (a delegated session; only with available=true, read-only, cannot send), demo (demo mode). Values: ["unlicensed","expired","not_configured","delegated","demo"] |
| `reauth_methods` | AiReauthMethod[] |  | Re-authentication methods available for a high-risk plan; empty otherwise. |
| `revoking_until` | string |  | When the provider has revoked the license, usable until this time. |
| `round_ms` | integer |  | Slowest round time in milliseconds over the rounds run. |
| `rounds` | integer |  | Rounds completed (3 when passed). |
| `site_id` | integer |  | The created site. |
| `spec` | AiLookSpec |  | Parameters of the AI custom figure (whitelisted values only; the panel draws it from fixed SVG parts). Absent from AiLook when never customised. Required when saving with pet ai or theme custom (code required); omitted means the stored one is kept. The server re-checks and normalises it (lowercase colours, primary darkened until white text is readable). |
| `state` | AiPlanState |  | proposed: waiting to run; running: in progress; wait_dns: site created, waiting for the DNS record (executing again requests the certificate); done; failed (see error); cancelled; superseded: replaced by a revised plan. Values: ["proposed","running","wait_dns","done","failed","cancelled","superseded"] |
| `step` | string |  | Where a failed probe stopped: connect (unreachable or upstream error), tool (did not call the tool with the numbers), echo (wrong echo), first_token (first token too slow), round (round too slow). Values: ["connect","tool","echo","first_token","round"] |
| `text` | string | Yes | The look you want, at most 60 characters after control characters and angle brackets are removed. |
| `theme` | AiTheme |  | Assistant accent colour: blue, teal, sunset, morandi, ink, or custom (the three colours in the custom parameters, spec). Applies to the assistant panel only. Values: ["blue","teal","sunset","morandi","ink","custom"] |
| `title` | string |  | Title (start of the first question). |
| `totp_code` | string |  | Current 6-digit TOTP code; the account must have TOTP enabled. |
| `updated_at` | string |  | Time of the last message (retention counts from it). |
| `upid` | integer | Yes | Purchased package to use (must belong to the plan's owning tenant). |
| `usage` | object |  | Your usage and quota after this generation (already counted). |
| `version` | string |  | Rating methodology version. |
