diff --git a/src/content/docs-lite/en/claude-code-other-models.md b/src/content/docs-lite/en/claude-code-other-models.md index d1bdd86..b4c6c67 100644 --- a/src/content/docs-lite/en/claude-code-other-models.md +++ b/src/content/docs-lite/en/claude-code-other-models.md @@ -10,13 +10,13 @@ ThinkWatch Lite connects Claude Code to a gateway on the same computer, which fo ## Steps -1. On the Upstreams page, choose **New upstream**. The first step, **Service**, lists the services that can be connected, account sign-ins first and API access after them, with a search box; picking one goes straight to **Connection**: +1. On the Upstreams page, choose **New upstream**. The first step, **Service**, lists the services in three groups, with a search box; picking one goes straight to **Connection**, which asks only for what that service needs: - **DeepSeek** fills in `https://api.deepseek.com/anthropic` and the protocol. Enter the **API key**. - - GLM with a key: **Custom**, with `https://open.bigmodel.cn/api/anthropic` or `https://api.z.ai/api/anthropic` as the **Base URL**, **Protocol** set to **Anthropic Messages**, and the **API key**. GLM's OpenAI-compatible address also works from ThinkWatch Lite 2026.10.5, with **Protocol** set to **OpenAI Chat Completions**: `https://api.z.ai/api/paas/v4` or `https://open.bigmodel.cn/api/paas/v4`, and `…/api/coding/paas/v4` on a GLM Coding Plan. Claude Code's requests are then converted, so the Anthropic address is the more direct choice. - - GLM with an account: **Z.ai / BigModel account**. Select the **Account service**, tick **Acknowledge the notes above and continue signing in**, choose **Sign in** and authorize in the browser. The app creates an API key named `thinkwatch` on the account and saves the upstream. + - GLM with a key: **Z.ai / BigModel**. Choose the **Site**, **Z.ai (international)** or **BigModel (mainland China)**, which sets the Anthropic-compatible address, and enter the **API key**. GLM's OpenAI-compatible address also works from ThinkWatch Lite 2026.10.5, with **Custom** and **Protocol** set to **OpenAI Chat Completions**: `https://api.z.ai/api/paas/v4` or `https://open.bigmodel.cn/api/paas/v4`, and `…/api/coding/paas/v4` on a GLM Coding Plan. Claude Code's requests are then converted, so the Anthropic address is the more direct choice. + - GLM with an account: **Z.ai / BigModel**, with **Authentication** set to **Account sign-in**. Choose the **Site**, tick **Acknowledge the notes above**, choose **Sign in with the browser** and authorize; to sign in from a browser other than the default one, choose **Copy sign-in link** instead. The app creates an API key named `thinkwatch` on the account and saves the upstream. - Kimi: **Custom**, with the Anthropic-compatible base URL from Kimi's documentation and **Protocol** set to **Anthropic Messages**. For Kimi For Coding, also turn on **Forward client identity**. - **Check connection** verifies the address and key and fetches the model list at no cost. Choose **Next** twice, then **Create**. + With a key, **Check connection** verifies the address and key and fetches the model list at no cost; choose **Next** twice, then **Create**. After an account sign-in the upstream is already saved; choose **Next** twice, then **Done**. 2. On the Clients page, choose **Connect…** on the Claude Code row. The dialog lists the fields that change in `~/.claude/settings.json`: `env.ANTHROPIC_BASE_URL`, `env.ANTHROPIC_AUTH_TOKEN` (a new key named `claude-code`) and `env.CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY`. Choose **Connect**. 3. Choose how the model is selected: - **By name.** In Claude Code, `/model ` switches to the model, and `claude --model ` starts with it. To map Claude Code's model aliases to it, add these to the `env` block of `~/.claude/settings.json`; the Haiku one also runs background tasks. @@ -35,6 +35,7 @@ ThinkWatch Lite connects Claude Code to a gateway on the same computer, which fo - **Format conversion.** Claude Code sends Anthropic Messages; with that protocol the request goes out unchanged, apart from identity fields such as `metadata.user_id`, which the gateway removes. Only an upstream in another format, such as an OpenAI-compatible address set to OpenAI Chat Completions, gets a converted request: Traffic marks it **Converted** and its details list any dropped fields. Web search, a server-side tool, cannot be converted and is not sent to such an upstream. **Auto-detect** does not recognize these addresses and forwards requests in the client's own format, which suits Claude Code but not Codex. - **Forward client identity** is off by default, so upstreams see ThinkWatch's User-Agent and no client identity. Kimi For Coding, Bailian Coding Plan and similar upstreams accept only certain clients; with the switch on, they receive Claude Code's own User-Agent, identity headers such as `x-app` and the identity fields in the body, unaltered. - **GLM Coding Plan.** An upstream on `api.z.ai` or `open.bigmodel.cn`, signed in or added with a key, shows its 5-hour and weekly limits, and the credits left on a plan billed in credits, in the Quota / billing column and in the menu bar or tray menu. +- **Balance.** A DeepSeek upstream, and a Kimi upstream on `api.moonshot.cn` or `api.moonshot.ai`, shows the account balance in the Quota / billing column. - **The /model list** shows gateway models only when their names contain `claude` or `anthropic`. Other models are typed by name, or added as one entry with `ANTHROPIC_CUSTOM_MODEL_OPTION`. - **Cost.** A rewritten request is priced as the model actually sent. - **Restore…** puts back only the fields the app wrote; model variables added by hand stay in `settings.json`. diff --git a/src/content/docs-lite/en/codex-other-models.md b/src/content/docs-lite/en/codex-other-models.md index 1cd6d92..f6b9db9 100644 --- a/src/content/docs-lite/en/codex-other-models.md +++ b/src/content/docs-lite/en/codex-other-models.md @@ -10,7 +10,7 @@ ThinkWatch Lite connects Codex to a gateway on the same computer that accepts th ## Steps -1. On the Upstreams page, choose **New upstream** and pick the service on the first step, **Service**, which goes straight to **Connection**: **Anthropic** for Claude, or **Google Gemini**; each fills in the address and protocol. For a relay, choose **Custom**, enter its **Base URL** without an endpoint path such as `/chat/completions`, and set **Protocol** to **OpenAI Chat Completions**; for GLM, for example, `https://api.z.ai/api/paas/v4`, or `…/api/coding/paas/v4` on a GLM Coding Plan. A base URL that ends with its own version, such as `/v4` or Volcengine Ark's `/api/v3`, is used as written from ThinkWatch Lite 2026.10.5. Enter the **API key**, choose **Check connection**, then **Next**. If the relay lists no models, or leaves some out, type each missing model ID in the box at the end of **Models** and press Enter. Choose **Next**, then **Create**. +1. On the Upstreams page, choose **New upstream** and pick the service on the first step, **Service**, which goes straight to **Connection**: **Anthropic** for Claude, or **Google Gemini**; each fills in the address and protocol. For a relay, choose its service under **Platforms and relays**, or **Custom** for any other. **OpenRouter** fills in its address and protocol. For **Sub2API**, **New API / One API** and **Custom**, enter the relay's **Base URL** without an endpoint path such as `/chat/completions`, and set **Protocol** to **OpenAI Chat Completions**; for GLM, for example, choose **Custom** with `https://api.z.ai/api/paas/v4`, or `…/api/coding/paas/v4` on a GLM Coding Plan. A base URL that ends with its own version, such as `/v4` or Volcengine Ark's `/api/v3`, is used as written from ThinkWatch Lite 2026.10.5. Enter the **API key**, choose **Check connection**, then **Next**. If the relay lists no models, or leaves some out, type each missing model ID in the box at the end of **Models** and press Enter. Choose **Next**, then **Create**. 2. On the Clients page, choose **Connect…** on the Codex row. The dialog shows the change to `~/.codex/config.toml`: | Field | Value | diff --git a/src/content/docs-lite/en/compare-cc-switch.md b/src/content/docs-lite/en/compare-cc-switch.md index 4bd4903..63411a3 100644 --- a/src/content/docs-lite/en/compare-cc-switch.md +++ b/src/content/docs-lite/en/compare-cc-switch.md @@ -17,12 +17,12 @@ A dash means the feature is not described in that product's documentation. | | CC Switch | ThinkWatch Lite | |---|---|---| | Clients | Claude Code, Claude Desktop, Codex, Gemini CLI, Grok Build, OpenCode, OpenClaw, Hermes Agent, Pi, MiniMax Code | In one step: Claude Code, Claude Desktop, Codex (also in the ChatGPT desktop app), opencode, Pi, oh-my-pi, Grok Build, Qwen Code, Hermes Agent, Zed, Aider, DeepSeek Harness. With instructions: Cursor, Continue, Antigravity CLI | -| Adding providers | More than 50 presets; `ccswitch://` links import providers, MCP servers, prompts and skills | A new upstream starts from the service: a ChatGPT or Z.ai / BigModel account sign-in, API access to Anthropic, OpenAI, Google Gemini, Amazon Bedrock, DeepSeek or Ollama, or any compatible endpoint; `thinkwatch://import` links from a relay or vendor pre-fill one upstream | +| Adding providers | More than 50 presets; `ccswitch://` links import providers, MCP servers, prompts and skills | A new upstream starts from the service, in three groups: model vendors (Anthropic, OpenAI, Google Gemini, DeepSeek, Z.ai / BigModel), platforms and relays (Amazon Bedrock, OpenRouter, ThinkWatch Enterprise, Sub2API, New API / One API), and Ollama or any compatible endpoint; ChatGPT and Z.ai / BigModel accounts sign in inside the dialog; `thinkwatch://import` links from a relay or vendor pre-fill one upstream | | Routing | In proxy mode, each client's requests go to its current provider; models can be mapped per provider | Ordered rules per key by model, API format, input tokens, tools, images, extended thinking and more; rules can rewrite the model | | Failover | Queue in priority order with a circuit breaker (proxy mode) | Next upstream in the group when an attempt fails before the answer begins; a session stays on one upstream | | Load balancing | — | Group strategies: in order, manual, round robin, lowest latency, lowest cost | | API format conversion | Proxy mode: Claude Code to OpenAI Chat Completions or Responses; Codex to Chat Completions or Anthropic Messages | Among Anthropic Messages, OpenAI Chat Completions, OpenAI Responses and Gemini | -| Usage and cost | Requests, tokens, cache hit rate and estimated cost, from proxy logs or the clients' session logs; custom prices, optional sync from models.dev; quota and balance display | Tokens, cost and requests by period, model and upstream; LiteLLM prices refreshed daily, or custom price sheets; estimates marked, unpriced requests counted separately | +| Usage and cost | Requests, tokens, cache hit rate and estimated cost, from proxy logs or the clients' session logs; custom prices, optional sync from models.dev; quota and balance display | Tokens, cost and requests by period, model and upstream; LiteLLM prices refreshed daily, or custom price sheets; estimates marked, unpriced requests counted separately; the balances and quotas that upstreams report | | Request details | Provider, model, tokens, cost, timing and status; parameters, a response summary and errors | Matched rule, each attempt with its status, request and response bodies, cost; full-text search; replay against another upstream | | Outbound redaction and tool-call inspection | — | API keys, private keys, ID and bank card numbers replaced before a request leaves; tool calls that download and run code or send out credentials cut off. Both start by only recording | | MCP and skills | One MCP server list synced to the selected clients; skills installed from GitHub or ZIP files | MCP servers of 13 clients side by side, copied or removed for 4; skills and hooks listed; all scanned for hidden characters, prompt injection, dangerous commands and overly broad permissions | diff --git a/src/content/docs-lite/en/failover-and-load-balancing.md b/src/content/docs-lite/en/failover-and-load-balancing.md index 3d00cfe..2d0c54a 100644 --- a/src/content/docs-lite/en/failover-and-load-balancing.md +++ b/src/content/docs-lite/en/failover-and-load-balancing.md @@ -9,7 +9,7 @@ ThinkWatch Lite turns each relay key into an upstream and puts several upstreams ## Steps -1. On the Upstreams page, choose **New upstream** and pick the service under **Service** (**Custom** for a relay). Under **Connection**, enter a **Name**, the **Base URL** and one **API key**, choose **Check connection**, then **Next** until **Create**. Repeat for each key: an upstream holds one key, and failover and pauses work per upstream. +1. On the Upstreams page, choose **New upstream** and pick the service under **Service** (for a relay, its service under **Platforms and relays**, or **Custom**). Under **Connection**, enter a **Name**, the **Base URL** where it is asked for and one **API key**, choose **Check connection**, then **Next** until **Create**. Repeat for each key: an upstream holds one key, and failover and pauses work per upstream. 2. On the Routing page, choose **New group** under **Groups**. Enter a **Name**, choose a **Strategy**, tick the upstreams under **Members**, drag them into order and choose **Create**. For **Round robin**, also enter each member's **Weight** and choose **Distribute by**. 3. Under **Routes**, open the route, choose **Edit…** on the rule that should use the group (usually **All requests (catch-all)**), select the group in **Forward to** and choose **Save** in both dialogs. 4. **Dry run** checks the result without sending anything. On the Traffic page, a request's **Routing** tab lists the upstreams it tried under **Attempts**. diff --git a/src/content/docs-lite/en/faq.md b/src/content/docs-lite/en/faq.md index af3e54e..1619787 100644 --- a/src/content/docs-lite/en/faq.md +++ b/src/content/docs-lite/en/faq.md @@ -30,7 +30,7 @@ Through the gateway, Claude Code can use an Anthropic API key, Amazon Bedrock, a ## Can ThinkWatch Lite use relays and Chinese models such as GLM, Kimi, Qwen or DeepSeek? -Yes. Any service with an Anthropic, OpenAI or Gemini API can be an upstream: on the Upstreams page, choose **New upstream**, set **Service** to **Custom**, and enter the **Base URL** and **API key**. DeepSeek is in the Service list, and a Z.ai or BigModel account can be signed in directly, with its GLM Coding Plan quota shown in the app. +Yes. Any service with an Anthropic, OpenAI or Gemini API can be an upstream: on the Upstreams page, choose **New upstream**, set **Service** to **Custom**, and enter the **Base URL** and **API key**. DeepSeek, OpenRouter, Sub2API and New API / One API are in the Service list, and a Z.ai or BigModel account can be signed in directly, with its GLM Coding Plan quota shown in the app. Upstreams that accept only particular clients, such as Kimi For Coding or Bailian Coding Plan, need **Forward client identity** turned on in the upstream's connection settings; otherwise requests identify themselves as ThinkWatch. A custom price sheet covers a relay whose prices differ from the official ones, and a routing rule can rewrite the model name, in which case the request is priced by the name it was sent with. diff --git a/src/content/docs-lite/en/features.md b/src/content/docs-lite/en/features.md index 042aec5..57106a8 100644 --- a/src/content/docs-lite/en/features.md +++ b/src/content/docs-lite/en/features.md @@ -45,7 +45,13 @@ Usage limits keep one client from using up a budget: each caps the key at a numb ## Upstreams -Upstreams are the services requests are forwarded to: API keys for Anthropic, OpenAI, Google Gemini, DeepSeek or any compatible endpoint, Amazon Bedrock (with an API key, access keys or an AWS profile), a ChatGPT account or a Z.ai / BigModel account signed in from the app, relays such as OpenRouter, and local models such as Ollama. **New upstream** starts with the service: account sign-ins (ChatGPT, Z.ai / BigModel) first, then API access (Anthropic, OpenAI, Google Gemini, Amazon Bedrock, DeepSeek, Ollama and Custom), with a search box; picking one goes straight to **Connection**. A ChatGPT account shows its usage limits and reset times. So does an upstream on a GLM Coding Plan, that is, one whose address is on `api.z.ai` or `open.bigmodel.cn`, whether it was signed in from the app or added with a key: its 5-hour and weekly limits and, on a plan billed in credits, the credits left (“1,976 / 2,000 credits left”). When a client and an upstream use different API formats, requests are converted between Anthropic Messages, OpenAI Chat Completions, OpenAI Responses and Gemini, and the fields that cannot be carried over are listed on the request. A model's reasoning survives the conversion: the reasoning a Chat Completions upstream such as DeepSeek, Kimi or GLM returns reaches the client as it is and goes back to that upstream on the next turn, so a conversation with tool calls can continue, and the thought signatures on a Gemini model's tool calls are kept as well. When a Chat Completions model writes a tool call into its answer text, the gateway recognises it as an ordinary tool call, provided the request defined that tool, and it goes through tool-call inspection like any other. A request body a client sends compressed with gzip, deflate or zstd is read as usual, and an answer an upstream sends compressed reaches the client decoded. Clients such as Codex mark no prompt-cache breakpoints; when their requests are converted for an upstream in Anthropic Messages format, or for a Claude model on Bedrock that AWS lists for prompt caching (Claude 3.5 Sonnet v2, Claude 3.7 Sonnet, and Claude 4.5 and later), the gateway marks them, so each turn reads what the previous one cached. An upstream that refuses the marks receives the request again without them. Upstreams can be reached through an outbound proxy and priced with a price sheet of their own; aliases, proxies and price sheets have tabs on the same page. The **Traffic · 24 h** column of the **Proxies** tab gives the upload and download through each proxy over the last 24 hours, with 7 and 30 days on hover. An optional **Concurrency limit** suits relays and accounts that allow only so many requests at once: when the upstream is full, a conversation that stays on it waits for a free slot, other requests go to the next upstream, and when every upstream is full a request waits and then receives a busy error. A streamed request waiting for a slot or for its key's usage window receives keep-alive pings while it waits. **Specs…** in an upstream's model list sets by hand a model's context window, maximum output, and whether it reasons and takes images, for a model the price table lacks or gets wrong; the values set there are used in place of the price table's. A connection test times the DNS lookup and the TCP, TLS and proxy handshakes without incurring any cost; an inference test measures the time to first token and estimates its cost before it runs. +Upstreams are the services requests are forwarded to: API keys for Anthropic, OpenAI, Google Gemini, DeepSeek or any compatible endpoint, Amazon Bedrock (with an API key, access keys or an AWS profile), a ChatGPT account or a Z.ai / BigModel account signed in from the app, relays such as OpenRouter, Sub2API and New API / One API, a ThinkWatch Enterprise gateway, and local models such as Ollama. When a client and an upstream use different API formats, requests are converted between Anthropic Messages, OpenAI Chat Completions, OpenAI Responses and Gemini, and the fields that cannot be carried over are listed on the request. A model's reasoning survives the conversion: the reasoning a Chat Completions upstream such as DeepSeek, Kimi or GLM returns reaches the client as it is and goes back to that upstream on the next turn, so a conversation with tool calls can continue, and the thought signatures on a Gemini model's tool calls are kept as well. When a Chat Completions model writes a tool call into its answer text, the gateway recognises it as an ordinary tool call, provided the request defined that tool, and it goes through tool-call inspection like any other. A request body a client sends compressed with gzip, deflate or zstd is read as usual, and an answer an upstream sends compressed reaches the client decoded. Clients such as Codex mark no prompt-cache breakpoints; when their requests are converted for an upstream in Anthropic Messages format, or for a Claude model on Bedrock that AWS lists for prompt caching (Claude 3.5 Sonnet v2, Claude 3.7 Sonnet, and Claude 4.5 and later), the gateway marks them, so each turn reads what the previous one cached. An upstream that refuses the marks receives the request again without them. Upstreams can be reached through an outbound proxy and priced with a price sheet of their own; aliases, proxies and price sheets have tabs on the same page. The **Traffic · 24 h** column of the **Proxies** tab gives the upload and download through each proxy over the last 24 hours, with 7 and 30 days on hover. An optional **Concurrency limit** suits relays and accounts that allow only so many requests at once: when the upstream is full, a conversation that stays on it waits for a free slot, other requests go to the next upstream, and when every upstream is full a request waits and then receives a busy error. A streamed request waiting for a slot or for its key's usage window receives keep-alive pings while it waits. **Specs…** in an upstream's model list sets by hand a model's context window, maximum output, and whether it reasons and takes images, for a model the price table lacks or gets wrong; the values set there are used in place of the price table's. A connection test times the DNS lookup and the TCP, TLS and proxy handshakes without incurring any cost; an inference test measures the time to first token and estimates its cost before it runs. + +**New upstream** starts with the service. The services are listed in three groups, each with its logo and a one-line description, and can be searched: **Model vendors** (Anthropic, OpenAI, Google Gemini, DeepSeek, Z.ai / BigModel), **Platforms and relays** (Amazon Bedrock, OpenRouter, ThinkWatch, Sub2API, New API / One API) and **Local and custom** (Ollama, Custom). Picking one goes straight to **Connection**, which asks only for what that service needs. **Authentication** offers the methods the service has: an API key or a ChatGPT account for OpenAI, an API key or an account sign-in for Z.ai / BigModel, an API key, access keys or an AWS profile for Bedrock, and an API key or OAuth for relays and custom endpoints; a service with a single method shows no choice. What the service already decides, such as its address, its protocol or that Ollama takes no key, is filled in or left out. A ChatGPT or Z.ai / BigModel account is signed in inside the dialog, once its notes are acknowledged: in the default browser, or in another browser through **Copy sign-in link**, and a ChatGPT account also with a device code. Once signed in, the upstream is saved, and the next two steps set its models and billing. When the app is connected to a remote core, a ChatGPT account signs in with a device code only, and the verification address and the code can each be copied. + +**Edit upstream** recognizes the service from the upstream's address, or for Sub2API, New API / One API and ThinkWatch from where its balance is read, shows its logo and name, and asks what creating it would ask. A value already set is always shown, even where the service would not ask for it. A Z.ai or BigModel upstream written by signing in shows **Account sign-in** as its method, with **Sign in again**; one added with a key can switch to **Account sign-in**, and signing in replaces its key while the model scope, billing and other settings stay as they are. + +The **Quota / billing** column shows the quotas and balances that services report. A ChatGPT account shows its usage limits and reset times. So does an upstream on a GLM Coding Plan, that is, one whose address is on `api.z.ai` or `open.bigmodel.cn`, whether it was signed in from the app or added with a key: its 5-hour and weekly limits and, on a plan billed in credits, the credits left (“1,976 / 2,000 credits left”). Other upstreams show their balance: the key's quota, or the tightest of its time windows, as a bar with what is left; the money left in the account (“Balance $18.40”); or, for a key without a limit, what it has spent (“$12.40 spent this month”). Hovering lists every window with its use and reset time, the exact amounts and when the balance was read. Balances are read from OpenRouter, DeepSeek, Moonshot, Sub2API, New API / One API and ThinkWatch Enterprise; the source is recognized from the address, or set by the service picked when the upstream was created. On a ThinkWatch Enterprise gateway, a key with limits of its own shows its own limits and use; a key without them shows the account's limits and its total over all of its keys, marked as the account's. **Check connection** shows the balance under its result, and an upstream's menu has **Refresh balance**. A balance that cannot be read shows why on hover; reading it never affects requests. An upstream's models are the ones it lists plus any added by hand. Upstreams often leave out models they serve: an account backend hides newer models, a relay lists only some. **Add models…** in an upstream's model list adds such models by their exact IDs, several at a time. An ID cannot contain `*` or `?` or have spaces around it, is at most 256 characters, and is added once; the dialog points out an ID that breaks these rules, or one the upstream already lists, before saving. A model added by hand is marked **Manual**, and routing and failover, aliases, routing rules that name a model, a key's allowed models, the model list clients see, the dry run and the speed test all treat it like a listed model. The summary at the top of the list counts the models the upstream lists apart from those added by hand. Hovering over a manual model shows **Remove**, which takes effect at once, with **Undo** in the message that follows. The **Models** section of the **New upstream** and **Edit upstream** dialogs ends with the same input, for an upstream with or without a list, so models can also be added while it is created or edited. They are saved with the rest of the upstream, and with **Selected models** a model added there is enabled at once. For an upstream that lists no models, the models added by hand are its whole list. diff --git a/src/content/docs-lite/en/overview.md b/src/content/docs-lite/en/overview.md index 5e8cfb1..a167413 100644 --- a/src/content/docs-lite/en/overview.md +++ b/src/content/docs-lite/en/overview.md @@ -23,7 +23,7 @@ ThinkWatch Lite is a local gateway for Claude Code, Codex and other AI clients, | Traffic | Every request, or requests grouped into sessions, with the details of each | | Clients | Pointing clients at the gateway, and restoring them | | Keys | The gateway keys clients connect with, each with its route and limits | -| Upstreams | Upstreams, outbound proxies and price sheets | +| Upstreams | Upstreams with their balances and quotas, outbound proxies and price sheets | | Routing | Routes, rules and groups, auxiliary requests, and the dry run | | Security | The security log and the three protections with their rules | | MCP | MCP servers, skills and hooks in each client, and the configuration scan | diff --git a/src/content/docs-lite/en/remote-core.md b/src/content/docs-lite/en/remote-core.md index d563d9c..57b472b 100644 --- a/src/content/docs-lite/en/remote-core.md +++ b/src/content/docs-lite/en/remote-core.md @@ -52,7 +52,7 @@ Clients on this computer, including those inside WSL on Windows, that point to t - **Overview, Traffic, Keys, Upstreams, Routing and Security** show and change the configuration and history of the core on the server. - **Clients and MCP** still act on the computer the app runs on: the Clients page points this computer's clients at the server's gateway, and the MCP page checks this computer's MCP servers, skills and hooks. A note at the top of each page says so. Clients on other machines are configured by hand with the server's gateway address and a gateway key. - **Settings** is divided into the app on this computer (connection, general settings, about, uninstall) and the configuration on the server (listening, log retention). The remote control port and its key can be changed only on the server. -- **ChatGPT sign-in** uses a device code: a browser sign-in returns to the machine that runs core, which is the server. +- **ChatGPT sign-in** uses a device code only, with the verification address and the code each ready to copy: a browser sign-in returns to the machine that runs core, which is the server. - `${NAME}` in an upstream's key or headers reads the environment of the core process on the server, and the **system proxy** option means the server's system proxy. - The **diagnostics bundle** is not available. The server refuses three things over a remote connection: producing the bundle, stopping core, and changing `listen.control`. - If the connection drops, the pages keep showing the state at the moment of the disconnect and cannot be changed until the connection is restored. A system notification reports the disconnect, and the app reconnects on its own. diff --git a/src/content/docs-lite/zh-CN/claude-code-other-models.md b/src/content/docs-lite/zh-CN/claude-code-other-models.md index 43d4df6..517f29c 100644 --- a/src/content/docs-lite/zh-CN/claude-code-other-models.md +++ b/src/content/docs-lite/zh-CN/claude-code-other-models.md @@ -10,13 +10,13 @@ ThinkWatch Lite 把 Claude Code 接到本机的网关上,网关再把每个请 ## 步骤 -1. 在「上游」页点击「新建上游」。第一步「服务类型」列出可接入的服务,账号登录在前、API 接入在后,可以搜索;选定后直接进入「连接」: +1. 在「上游」页点击「新建上游」。第一步「服务类型」把服务分三组列出,可以搜索;选定后直接进入「连接」,只询问该服务需要的内容: - 「DeepSeek」:自动填入 `https://api.deepseek.com/anthropic` 和接口协议,再填写「API 密钥」。 - - GLM(API 密钥):选「自定义」,「接口地址」填 `https://open.bigmodel.cn/api/anthropic` 或 `https://api.z.ai/api/anthropic`,「接口协议」选「Anthropic Messages」,再填写「API 密钥」。自 ThinkWatch Lite 2026.10.5 起,也可以使用 GLM 的 OpenAI 兼容地址,「接口协议」选「OpenAI Chat Completions」:`https://api.z.ai/api/paas/v4` 或 `https://open.bigmodel.cn/api/paas/v4`,GLM Coding Plan 使用 `…/api/coding/paas/v4`。这时 Claude Code 的请求需要转换格式,因此 Anthropic 地址更直接。 - - GLM(账号登录):选「Z.ai / BigModel 账号」,在「账号归属」中选择站点,勾选「已阅读上述说明,继续登录」,点击「登录」并在浏览器中完成授权。应用在该账号中创建一把名为 `thinkwatch` 的 API 密钥,并写入上游。 + - GLM(API 密钥):选「Z.ai / BigModel」,在「站点」中选择「Z.ai(国际)」或「BigModel(中国大陆)」,兼容 Anthropic 接口的地址随之确定,再填写「API 密钥」。自 ThinkWatch Lite 2026.10.5 起,也可以选「自定义」使用 GLM 的 OpenAI 兼容地址,「接口协议」选「OpenAI Chat Completions」:`https://api.z.ai/api/paas/v4` 或 `https://open.bigmodel.cn/api/paas/v4`,GLM Coding Plan 使用 `…/api/coding/paas/v4`。这时 Claude Code 的请求需要转换格式,因此 Anthropic 地址更直接。 + - GLM(账号登录):选「Z.ai / BigModel」,「认证方式」选「账号登录」,在「站点」中选择站点,勾选「已阅读上述说明」,点击「在浏览器中登录」并完成授权;要在默认浏览器以外的浏览器中登录,改点「复制登录链接」。应用在该账号中创建一把名为 `thinkwatch` 的 API 密钥,并写入上游。 - Kimi:选「自定义」,「接口地址」填 Kimi 文档给出的兼容 Anthropic 接口的地址,「接口协议」选「Anthropic Messages」。Kimi For Coding 还需打开「转发客户端身份」。 - 「检测连接」验证地址与凭据并获取模型列表,不产生费用。之后点击两次「下一步」,再点击「创建」。 + 使用 API 密钥时,「检测连接」验证地址与凭据并获取模型列表,不产生费用;之后点击两次「下一步」,再点击「创建」。账号登录后上游已经写入,点击两次「下一步」,再点击「完成」。 2. 在「客户端」页 Claude Code 一行点击「接管…」。对话框列出 `~/.claude/settings.json` 中要修改的字段:`env.ANTHROPIC_BASE_URL`、`env.ANTHROPIC_AUTH_TOKEN`(新密钥 `claude-code`)和 `env.CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY`。点击「接管」。 3. 选择指定模型的方式: - **直接使用模型名。**在 Claude Code 中输入 `/model <模型 ID>` 即切换到该模型,也可以用 `claude --model <模型 ID>` 启动。要让 Claude Code 的模型别名对应到该模型,在 `~/.claude/settings.json` 的 `env` 中加入以下变量;其中 Haiku 一项也用于后台任务。 @@ -35,6 +35,7 @@ ThinkWatch Lite 把 Claude Code 接到本机的网关上,网关再把每个请 - **格式转换。**Claude Code 发出的是 Anthropic Messages;接口协议同为 Anthropic Messages 时,请求按原格式发出,网关只去掉 `metadata.user_id` 等身份字段。只有上游使用其他格式时才会转换,例如兼容 OpenAI 的地址配合接口协议 OpenAI Chat Completions:此时「流量」页把该请求标为「已转换」,请求详情列出被丢弃的字段。网页搜索是服务端工具,无法转换,这类请求不会发往此类上游。「自动识别」认不出这三个服务商的地址,会按客户端的原格式转发,对 Claude Code 可用,对 Codex 这类使用其他格式的客户端则不可用。 - **转发客户端身份**默认关闭,上游看到的是 ThinkWatch 的 User-Agent,不带客户端身份。Kimi For Coding、百炼 Coding Plan 等上游只接受特定客户端;打开开关后,上游收到 Claude Code 自己的 User-Agent、`x-app` 等身份请求头和请求体中的身份字段,均为原值。 - **GLM Coding Plan。**地址在 `api.z.ai` 或 `open.bigmodel.cn` 上的上游,无论应用内登录还是手动填写密钥,都在「额度 / 计费」列和菜单栏(或托盘菜单)中显示 5 小时与每周额度,积分制套餐另外显示剩余积分。 +- **余额。**DeepSeek 上游,以及地址在 `api.moonshot.cn` 或 `api.moonshot.ai` 上的 Kimi 上游,在「额度 / 计费」列中显示账户余额。 - **`/model` 列表**只显示名称含 `claude` 或 `anthropic` 的网关模型;其他模型需要输入名称,或用 `ANTHROPIC_CUSTOM_MODEL_OPTION` 加入一项。 - **费用。**改写过模型名的请求按实际发出的模型计价。 - **「还原…」**只恢复应用写入的字段,手动加入的模型变量仍留在 `settings.json` 中。 diff --git a/src/content/docs-lite/zh-CN/codex-other-models.md b/src/content/docs-lite/zh-CN/codex-other-models.md index 7aed046..f030d09 100644 --- a/src/content/docs-lite/zh-CN/codex-other-models.md +++ b/src/content/docs-lite/zh-CN/codex-other-models.md @@ -10,7 +10,7 @@ ThinkWatch Lite 把 Codex 接到本机的网关上,网关接收 OpenAI Respons ## 步骤 -1. 在「上游」页点击「新建上游」,在第一步「服务类型」中选择服务,选定后直接进入「连接」:Claude 选「Anthropic」,Gemini 选「Google Gemini」,接口地址和接口协议会自动填入。中转站选「自定义」,「接口地址」填它的 Base URL(不含 `/chat/completions` 等接口路径),「接口协议」选「OpenAI Chat Completions」;例如 GLM 填 `https://api.z.ai/api/paas/v4`,GLM Coding Plan 填 `…/api/coding/paas/v4`。以自带版本号结尾的地址(如 `/v4`、火山方舟的 `/api/v3`),自 ThinkWatch Lite 2026.10.5 起按原样使用。填写「API 密钥」,点击「检测连接」,再点击「下一步」。中转站不提供模型列表或没有列全时,在「模型」一节末尾的输入框中逐个填写缺少的模型 ID 并回车。再点击「下一步」,然后点击「创建」。 +1. 在「上游」页点击「新建上游」,在第一步「服务类型」中选择服务,选定后直接进入「连接」:Claude 选「Anthropic」,Gemini 选「Google Gemini」,接口地址和接口协议会自动填入。中转站在「平台与中转」中选择对应的服务,其他中转站选「自定义」。「OpenRouter」自动填入地址和接口协议;选「Sub2API」「New API / One API」或「自定义」时,「接口地址」填中转站的 Base URL(不含 `/chat/completions` 等接口路径),「接口协议」选「OpenAI Chat Completions」;例如 GLM 选「自定义」,填 `https://api.z.ai/api/paas/v4`,GLM Coding Plan 填 `…/api/coding/paas/v4`。以自带版本号结尾的地址(如 `/v4`、火山方舟的 `/api/v3`),自 ThinkWatch Lite 2026.10.5 起按原样使用。填写「API 密钥」,点击「检测连接」,再点击「下一步」。中转站不提供模型列表或没有列全时,在「模型」一节末尾的输入框中逐个填写缺少的模型 ID 并回车。再点击「下一步」,然后点击「创建」。 2. 在「客户端」页 Codex 一行点击「接管…」。对话框列出对 `~/.codex/config.toml` 的修改: | 字段 | 写入 | diff --git a/src/content/docs-lite/zh-CN/compare-cc-switch.md b/src/content/docs-lite/zh-CN/compare-cc-switch.md index e212ac9..33d87f5 100644 --- a/src/content/docs-lite/zh-CN/compare-cc-switch.md +++ b/src/content/docs-lite/zh-CN/compare-cc-switch.md @@ -17,12 +17,12 @@ ThinkWatch Lite 在本机运行网关 ThinkWatch Core。在客户端页把每个 | | CC Switch | ThinkWatch Lite | |---|---|---| | 客户端 | Claude Code、Claude Desktop、Codex、Gemini CLI、Grok Build、OpenCode、OpenClaw、Hermes Agent、Pi、MiniMax Code | 一键接管:Claude Code、Claude Desktop、Codex(含 ChatGPT 桌面版中的 Codex)、opencode、Pi、oh-my-pi、Grok Build、Qwen Code、Hermes Agent、Zed、Aider、DeepSeek Harness;提供配置方法:Cursor、Continue、Antigravity CLI | -| 添加供应商 | 50 余个供应商预设;`ccswitch://` 链接可导入供应商、MCP 服务器、提示词与技能 | 新建上游先选择服务:ChatGPT 与 Z.ai / BigModel 账号登录,或 Anthropic、OpenAI、Google Gemini、Amazon Bedrock、DeepSeek、Ollama 的 API 接入,也可填写任何兼容接口;中转站或服务商可通过 `thinkwatch://import` 链接预填一个上游 | +| 添加供应商 | 50 余个供应商预设;`ccswitch://` 链接可导入供应商、MCP 服务器、提示词与技能 | 新建上游先选择服务,分三组:模型厂商(Anthropic、OpenAI、Google Gemini、DeepSeek、Z.ai / BigModel)、平台与中转(Amazon Bedrock、OpenRouter、ThinkWatch 企业版、Sub2API、New API / One API),以及 Ollama 与任何兼容接口;ChatGPT 与 Z.ai / BigModel 账号在对话框内登录;中转站或服务商可通过 `thinkwatch://import` 链接预填一个上游 | | 路由 | 代理模式下,每个客户端的请求发往它当前的供应商;可按供应商映射模型 | 每把密钥的规则按顺序匹配模型、API 格式、输入 token、工具、图片、扩展思考等条件;规则可以改写模型 | | 故障转移 | 按优先级排列的故障转移队列,带熔断(代理模式) | 回答开始之前尝试失败时,转到策略组中的下一个上游;同一会话默认保持在同一个上游 | | 负载均衡 | — | 策略组:按顺序、手动选择、轮询、延迟最低、费用最低 | | API 格式转换 | 代理模式下:Claude Code 接 OpenAI Chat Completions 或 Responses 的供应商;Codex 接 Chat Completions 或 Anthropic Messages 的供应商 | 在 Anthropic Messages、OpenAI Chat Completions、OpenAI Responses 与 Gemini 之间转换 | -| 用量与费用 | 请求数、token、缓存命中率与估算费用,数据来自代理日志或客户端的会话日志;自定义价格,可选从 models.dev 同步价格;显示订阅额度与余额 | 按区间、模型、上游统计 token、费用与请求数;价格取自每天更新的 LiteLLM 价目表或自定义价目表;估算部分单独标出,无法计价的请求单独计数 | +| 用量与费用 | 请求数、token、缓存命中率与估算费用,数据来自代理日志或客户端的会话日志;自定义价格,可选从 models.dev 同步价格;显示订阅额度与余额 | 按区间、模型、上游统计 token、费用与请求数;价格取自每天更新的 LiteLLM 价目表或自定义价目表;估算部分单独标出,无法计价的请求单独计数;显示上游报告的余额与额度 | | 请求详情 | 供应商、模型、token、费用、耗时与状态;可查看请求参数、响应摘要与错误信息 | 命中的规则、每一次尝试及其状态、请求与响应正文、费用;可全文搜索;可在另一个上游重放 | | 出站脱敏与工具调用审查 | — | 请求发出前把 API 密钥、私钥、身份证号与银行卡号替换为占位符;回答中含下载并执行代码、外发凭据等工具调用时切断响应。两项出厂均为「观察」,只记录、不改动 | | MCP 与技能 | 统一的 MCP 服务器列表,同步到选定的客户端;从 GitHub 仓库或 ZIP 文件安装技能 | 并排列出 13 个客户端的 MCP 服务器,其中 4 个可复制或移除;列出技能与钩子;扫描隐藏字符、提示注入、危险命令与过宽权限 | diff --git a/src/content/docs-lite/zh-CN/failover-and-load-balancing.md b/src/content/docs-lite/zh-CN/failover-and-load-balancing.md index 70843eb..b5c8367 100644 --- a/src/content/docs-lite/zh-CN/failover-and-load-balancing.md +++ b/src/content/docs-lite/zh-CN/failover-and-load-balancing.md @@ -9,7 +9,7 @@ ThinkWatch Lite 把每个中转站的每把密钥建成一个上游,再把多 ## 步骤 -1. 在上游页选择「新建上游」,在「服务类型」中选择服务(中转站选「自定义」)。在「连接」中填写「名称」「接口地址」和一把「API 密钥」,选择「检测连接」,再依次选择「下一步」直到「创建」。每把密钥重复一次:一个上游只有一把密钥,故障转移和暂停都以上游为单位。 +1. 在上游页选择「新建上游」,在「服务类型」中选择服务(中转站在「平台与中转」中选择对应的服务,或选「自定义」)。在「连接」中填写「名称」和一把「API 密钥」,服务要求时再填写「接口地址」,选择「检测连接」,再依次选择「下一步」直到「创建」。每把密钥重复一次:一个上游只有一把密钥,故障转移和暂停都以上游为单位。 2. 在路由页的「策略组」标签中选择「新建策略组」。填写「名称」,选择「策略」,在「成员」中勾选上游并拖动排序,然后选择「创建」。策略为「轮询」时,还要填写每个成员的「权重」并选择「分配依据」。 3. 在「路由」标签中打开路由,对要使用该策略组的规则选择「编辑…」(通常是「全部请求(兜底)」那一条),在「转发至」中选择该策略组,并在两个对话框中各选择一次「保存」。 4. 「试算」可以检查结果,不会发出请求。在流量页打开请求,「路由」标签的「尝试链」列出尝试过的每个上游。 diff --git a/src/content/docs-lite/zh-CN/faq.md b/src/content/docs-lite/zh-CN/faq.md index 3b3eaec..77e2ac7 100644 --- a/src/content/docs-lite/zh-CN/faq.md +++ b/src/content/docs-lite/zh-CN/faq.md @@ -30,7 +30,7 @@ ThinkWatch Lite 支持 macOS 12 及以上(Apple 芯片,不提供 Intel 芯 ## ThinkWatch Lite 能使用中转站和 GLM、Kimi、通义千问、DeepSeek 等国产模型吗? -能。任何提供 Anthropic、OpenAI 或 Gemini 接口的服务都可以作为上游:在上游页点击「新建上游」,「服务类型」选择「自定义」,填写「接口地址」与「API 密钥」。「服务类型」中列有 DeepSeek;Z.ai 或 BigModel 账号可以直接在应用内登录,并显示 GLM Coding Plan 的额度。 +能。任何提供 Anthropic、OpenAI 或 Gemini 接口的服务都可以作为上游:在上游页点击「新建上游」,「服务类型」选择「自定义」,填写「接口地址」与「API 密钥」。「服务类型」中列有 DeepSeek、OpenRouter、Sub2API 与 New API / One API;Z.ai 或 BigModel 账号可以直接在应用内登录,并显示 GLM Coding Plan 的额度。 Kimi For Coding、百炼 Coding Plan 等只接受特定客户端的上游,需要在该上游的连接设置中打开「转发客户端身份」,否则请求以 ThinkWatch 的身份发出。中转站的价格与官方不同时,可以使用自定义价目表;路由规则可以改写客户端请求的模型名,此时按发出的模型名计价。 diff --git a/src/content/docs-lite/zh-CN/features.md b/src/content/docs-lite/zh-CN/features.md index 5d6c44b..cbb6309 100644 --- a/src/content/docs-lite/zh-CN/features.md +++ b/src/content/docs-lite/zh-CN/features.md @@ -45,7 +45,13 @@ WSL 2 默认使用 NAT 网络,此时 Windows 上的网关无法从 WSL 内访 ## 上游 -上游是网关转发请求的目标:Anthropic、OpenAI、Google Gemini、DeepSeek 或任何兼容接口的 API 密钥,Amazon Bedrock(API 密钥、访问密钥或 AWS 配置文件),在应用内登录的 ChatGPT 账号或 Z.ai / BigModel 账号,OpenRouter 等中转服务,以及 Ollama 等本机模型。「新建上游」先选择服务:账号登录(ChatGPT、Z.ai / BigModel)在前,API 接入(Anthropic、OpenAI、Google Gemini、Amazon Bedrock、DeepSeek、Ollama 与自定义)在后,可以搜索;选定后直接进入「连接」。ChatGPT 账号显示订阅额度与重置时间;GLM Coding Plan 的上游(地址在 `api.z.ai` 或 `open.bigmodel.cn` 上,在应用内登录或手动填写密钥均可)同样显示:5 小时与每周额度,积分制套餐另外显示剩余积分(「剩余 1,976 / 2,000 积分」)。客户端与上游的 API 格式不同时,请求在 Anthropic Messages、OpenAI Chat Completions、OpenAI Responses 与 Gemini 之间自动转换,无法转换的字段会在请求上逐一列出。模型的思考在转换中保留:DeepSeek、Kimi、GLM 等 Chat Completions 格式上游返回的思考内容原样交给客户端,下一轮送回同一上游,带工具调用的对话因此能继续;Gemini 模型工具调用上的思考签名同样保留。Chat Completions 格式的模型把工具调用写进回答正文时,只要请求定义了这个工具,网关就把它识别为普通的工具调用,并与其他工具调用一样经过工具调用审查。客户端以 gzip、deflate 或 zstd 压缩发送的请求正文照常读取,上游压缩返回的回答解码后交给客户端。Codex 等不标注提示缓存断点的客户端,请求转换后发往 Anthropic Messages 格式的上游,或 Bedrock 上 AWS 列为支持提示缓存的 Claude 模型(Claude 3.5 Sonnet v2、Claude 3.7 Sonnet 以及 Claude 4.5 起的模型)时,由网关标注断点,每一轮都能读取上一轮写入的缓存。上游拒绝这些标注时,网关去掉标注重新发送一次。上游可以经出站代理访问,也可以使用单独的价目表计价,别名、代理与价目表在同一页的标签中管理。「代理」标签页的「流量 · 24 小时」一列给出经过每个代理的上传与下载,悬停可查看 7 天与 30 天的数据。可选的「并发上限」适用于限制并发的中转站或账号:上游已满时,留在它上面的对话等待空位,其他请求交给下一个上游;所有上游都满时,请求先等待,仍无空位则返回繁忙错误。流式请求等待空位或密钥的用量窗口期间,客户端会收到保活心跳。在上游的模型列表中选择「规格…」,可以手动设置模型的上下文窗口、输出上限,以及是否支持推理与图片输入,适用于价目表中没有或数值有误的模型,手动设置的值优先于价目表。链路测速测量 DNS 解析以及 TCP、TLS、代理握手的耗时,不产生费用;推理测速测量首个 token 的时间,运行前先给出费用预估。 +上游是网关转发请求的目标:Anthropic、OpenAI、Google Gemini、DeepSeek 或任何兼容接口的 API 密钥,Amazon Bedrock(API 密钥、访问密钥或 AWS profile),在应用内登录的 ChatGPT 账号或 Z.ai / BigModel 账号,OpenRouter、Sub2API、New API / One API 等中转服务,ThinkWatch 企业版网关,以及 Ollama 等本机模型。客户端与上游的 API 格式不同时,请求在 Anthropic Messages、OpenAI Chat Completions、OpenAI Responses 与 Gemini 之间自动转换,无法转换的字段会在请求上逐一列出。模型的思考在转换中保留:DeepSeek、Kimi、GLM 等 Chat Completions 格式上游返回的思考内容原样交给客户端,下一轮送回同一上游,带工具调用的对话因此能继续;Gemini 模型工具调用上的思考签名同样保留。Chat Completions 格式的模型把工具调用写进回答正文时,只要请求定义了这个工具,网关就把它识别为普通的工具调用,并与其他工具调用一样经过工具调用审查。客户端以 gzip、deflate 或 zstd 压缩发送的请求正文照常读取,上游压缩返回的回答解码后交给客户端。Codex 等不标注提示缓存断点的客户端,请求转换后发往 Anthropic Messages 格式的上游,或 Bedrock 上 AWS 列为支持提示缓存的 Claude 模型(Claude 3.5 Sonnet v2、Claude 3.7 Sonnet 以及 Claude 4.5 起的模型)时,由网关标注断点,每一轮都能读取上一轮写入的缓存。上游拒绝这些标注时,网关去掉标注重新发送一次。上游可以经出站代理访问,也可以使用单独的价目表计价,别名、代理与价目表在同一页的标签中管理。「代理」标签页的「流量 · 24 小时」一列给出经过每个代理的上传与下载,悬停可查看 7 天与 30 天的数据。可选的「并发上限」适用于限制并发的中转站或账号:上游已满时,留在它上面的对话等待空位,其他请求交给下一个上游;所有上游都满时,请求先等待,仍无空位则返回繁忙错误。流式请求等待空位或密钥的用量窗口期间,客户端会收到保活心跳。在上游的模型列表中选择「规格…」,可以手动设置模型的上下文窗口、输出上限,以及是否支持推理与图片输入,适用于价目表中没有或数值有误的模型,手动设置的值优先于价目表。链路测速测量 DNS 解析以及 TCP、TLS、代理握手的耗时,不产生费用;推理测速测量首个 token 的时间,运行前先给出费用预估。 + +「新建上游」先选择服务。服务分为「模型厂商」(Anthropic、OpenAI、Google Gemini、DeepSeek、Z.ai / BigModel)、「平台与中转」(Amazon Bedrock、OpenRouter、ThinkWatch、Sub2API、New API / One API)与「本机与自定义」(Ollama、自定义)三组,各带标志和一句介绍,可以搜索。选定后直接进入「连接」,只询问该服务需要的内容。「认证方式」按服务给出:OpenAI 为 API 密钥或 ChatGPT 账号,Z.ai / BigModel 为 API 密钥或账号登录,Bedrock 为 API 密钥、访问密钥或 AWS profile,中转与自定义为 API 密钥或 OAuth;只有一种方式的服务不显示这一项。服务已经决定的内容,例如地址、接口协议,或 Ollama 不需要密钥,直接填好或不再显示。ChatGPT 与 Z.ai / BigModel 账号在对话框内登录,阅读说明后,可以在默认浏览器中登录,也可以「复制登录链接」到常用的浏览器中打开;ChatGPT 账号还可以用设备码登录。登录后上游即写入配置,后两步设置它的模型与计费。连接远程 core 时,ChatGPT 账号只能用设备码登录,验证网址和设备码都可以复制。 + +「编辑上游」按地址认出服务(Sub2API、New API / One API 与 ThinkWatch 按余额来源认出),显示它的标志和名称,询问的内容与新建时一致;已经设置的值始终显示,即使该服务新建时不询问这一项。经账号登录写入的 Z.ai 或 BigModel 上游,认证方式显示为「账号登录」,可以「重新登录」;手动填写密钥的上游可以改为「账号登录」,登录后账号中取得的密钥替换当前密钥,模型范围、计费方式等设置保持不变。 + +「额度 / 计费」一列显示服务报告的额度与余额。ChatGPT 账号显示订阅额度与重置时间;GLM Coding Plan 的上游(地址在 `api.z.ai` 或 `open.bigmodel.cn` 上,在应用内登录或手动填写密钥均可)同样显示:5 小时与每周额度,积分制套餐另外显示剩余积分(「剩余 1,976 / 2,000 积分」)。其他上游显示余额:密钥的额度或最紧的时间窗口,以进度条和剩余量表示;账户中的余额(「余额 $18.40」);没有限额的密钥则显示已用金额(「本月已用 $12.40」)。悬停可以查看全部窗口的用量与重置时间、确切数字和读取时间。余额来源包括 OpenRouter、DeepSeek、Moonshot、Sub2API、New API / One API 与 ThinkWatch 企业版,按地址认出,或由新建上游时所选的服务决定。在 ThinkWatch 企业版网关上,密钥设了自己的限额时显示密钥的限额与用量;没设时显示账号的限额与所有密钥合计的用量,并注明是账号的。「检测连接」的结果下方也显示余额,上游的菜单中有「刷新余额」。余额读不到时,悬停可以查看原因;读取余额不影响请求转发。 一家上游的模型,是它自己列出的模型加上手动添加的模型。上游常常没有列全它能服务的模型:账号类的后端会隐藏较新的模型,中转站只列出一部分。在上游的模型列表中选择「添加模型…」,可以按确切的模型 ID 添加这类模型,一次可以添加多个。模型 ID 不能含 `*` 或 `?`,前后不能有空格,最多 256 个字符,且不能重复;不符合要求的,以及上游已经列出的,对话框在保存之前当场指出。手动添加的模型标有「手动」,路由与故障转移、别名、指定模型的路由规则、密钥的可用模型、客户端看到的模型列表、试算与推理测速都把它当作列出的模型。列表顶部的摘要把上游列出的模型与手动添加的模型分开计数。悬停在手动添加的模型上会出现「移除」,立即生效,随后的提示中可以「撤销」。「新建上游」与「编辑上游」对话框的「模型」一节末尾有同样的输入框,无论上游是否提供模型列表,创建或编辑时都可以在这里添加模型,随上游的其他设置一起保存;启用范围为「指定模型」时,在这里添加的模型立即勾选启用。上游不提供模型列表时,手动添加的模型就是它的全部模型。 diff --git a/src/content/docs-lite/zh-CN/overview.md b/src/content/docs-lite/zh-CN/overview.md index ac87ada..5aec106 100644 --- a/src/content/docs-lite/zh-CN/overview.md +++ b/src/content/docs-lite/zh-CN/overview.md @@ -23,7 +23,7 @@ ThinkWatch Lite 是 Claude Code、Codex 等 AI 客户端的本地网关,支持 | 流量 | 逐条请求或按会话归组的请求,以及每个请求的详情 | | 客户端 | 把客户端指向网关,以及还原 | | 密钥 | 客户端连接网关所用的密钥,及其路由与限制 | -| 上游 | 上游、出站代理与价目表 | +| 上游 | 上游及其余额与额度、出站代理与价目表 | | 路由 | 路由、规则与策略组,辅助请求,以及试算 | | 安全 | 安全日志,以及三项防护及其规则 | | MCP | 各客户端的 MCP 服务器、技能与钩子,以及配置扫描 | diff --git a/src/content/docs-lite/zh-CN/remote-core.md b/src/content/docs-lite/zh-CN/remote-core.md index e779c83..5b3524a 100644 --- a/src/content/docs-lite/zh-CN/remote-core.md +++ b/src/content/docs-lite/zh-CN/remote-core.md @@ -52,7 +52,7 @@ sudo -u thinkwatch THINKWATCH_HOME=/var/lib/thinkwatch twcore control-key - **概览、流量、密钥、上游、路由与安全**显示和修改的是服务器上 core 的配置与历史。 - **客户端与 MCP**仍作用于运行应用的这台电脑:客户端页把这台电脑上的客户端改为指向服务器的网关,MCP 页检查这台电脑上的 MCP 服务器、技能与钩子。两页顶部都有相应说明。其他机器上的客户端需要手动填写服务器的网关地址与网关密钥。 - **设置**分为这台电脑上的应用(连接、通用、关于、卸载)与服务器上的配置(网关监听、日志保留)两部分。远程控制端口及其密钥只能在服务器上修改。 -- **ChatGPT 登录**只能使用设备码:浏览器登录完成后会回到运行 core 的机器,也就是服务器。 +- **ChatGPT 登录**只能使用设备码,验证网址和设备码都可以复制:浏览器登录完成后会回到运行 core 的机器,也就是服务器。 - 上游密钥或请求头中的 `${变量名}` 读取的是服务器上 core 进程的环境变量,**系统代理**选项指的是服务器的系统代理。 - 不提供**诊断包**。经远程连接,服务器拒绝三项操作:生成诊断包、停止 core,以及修改 `listen.control`。 - 连接中断时,各页面保持断开时的状态,恢复连接之前不可修改。应用会发送系统通知,并自动重新连接。 diff --git a/src/content/docs/en/api-reference.md b/src/content/docs/en/api-reference.md index 26a4e37..01a7674 100644 --- a/src/content/docs/en/api-reference.md +++ b/src/content/docs/en/api-reference.md @@ -31,9 +31,20 @@ The gateway serves three API formats on a single port, allowing clients to use w | `POST /v1/messages` | Anthropic Messages API | Claude Code, Anthropic SDK | | `POST /v1/responses` | OpenAI Responses API | OpenAI SDK (2025 format) | | `GET /v1/models` | OpenAI Models | All clients | +| `GET /v1/usage` | Usage and limits of the calling key | Any client with a gateway API key | All three endpoints authenticate identically (API Key or JWT), route through the same model router and rate limiter, and produce the same usage records and audit logs. +### Limits and budgets + +Before a request is sent upstream, it is checked against the rate limits and budgets of its API key and of the key's owner, using what earlier requests have used; tokens are counted after the response, answers from the response cache included. The owner's limits come from their roles, those assigned globally and those attached to a team they belong to, merged most-restrictive, then from the user's own overrides. A request over a limit gets `429` with `Retry-After`, the seconds until the limit frees, and a message that names the limit, such as `Rate limited: user:requests/1m`. A request refused by these limits, or because its key may not use the model, counts against none of them. + +**Route caps.** A model route can carry an **RPM cap** and a **TPM cap**, set in the route editor. Both count over a sliding minute, the TPM cap in weighted tokens like the other token limits. A route at either cap is skipped, and the model's next route serves the request; when every remaining route is at its cap, the request gets `429` with `Retry-After`, labelled `route:requests/1m` or `route:tokens/1m`. Such a request has passed the caller's own limits and counts on them. + +**Limits that cannot be checked.** When Redis cannot be reached, or the database fails while a request's limits are loaded, `security.rate_limit_fail_closed` decides. Off, the default, the request goes on without those limits and a warning is logged; on, it is refused with `429` and `Retry-After: 30`, labelled `rate_limiter_unavailable`, `budget_unavailable` or `limits_unavailable`. Route caps follow the same setting. See [Limits that cannot be checked](/docs/configuration#limits-that-cannot-be-checked). + +[`GET /v1/usage`](#get-v1usage) tells a client what its key has used and how much room its limits leave. + ### POST /v1/chat/completions OpenAI-compatible chat completions endpoint. Proxies requests to the configured upstream provider. @@ -196,6 +207,95 @@ curl http://localhost:3000/v1/models \ --- +### GET /v1/usage + +What the calling API key has used and how much room its limits leave on the AI gateway. A client can show its user what is left, or slow down before a limit refuses its requests. + +**Authentication:** API Key with access to the AI gateway, as for a model request + +Calling it charges no limit, writes no request log entry and is not a use of the key: `last_used_at` stays as it was, so polling does not keep an idle key from its inactivity timeout. + +#### Request + +No request body. No query parameters. + +#### Response Body + +```json +{ + "scope": "key", + "usage": { + "requests_today": 12, + "tokens_today": 48210, + "requests_month": 340, + "tokens_month": 1290455, + "cost_usd_month": 3.82 + }, + "limits": [ + { + "scope": "key", + "kind": "tokens", + "window": "daily", + "window_secs": null, + "limit": 100000, + "used": 48210, + "resets_at": "2026-10-12T00:00:00Z" + }, + { + "scope": "key", + "kind": "requests", + "window": "1m", + "window_secs": 60, + "limit": 60, + "used": 4, + "resets_at": null + } + ], + "expires_at": "2026-12-31T00:00:00Z" +} +``` + +The answer is about one of two subjects, named in `scope`: + +- `"key"` when the key has limits of its own on the AI gateway: `limits` lists only the key's limits, each with `used` counted for the key, and `usage` is the key's own, across its rotations. +- `"user"` when it has none: `limits` lists its owner's effective limits (their roles, including those a team grants, merged most-restrictive, then the user's overrides), each with `used` counted for everything the owner does, and `usage` is the owner's total over all of their keys. With no limits on the owner either, `limits` is empty. + +Whoever holds a key without limits of its own therefore sees its owner's totals and limits; a key handed to someone else should carry limits of its own. + +| Field | Type | Description | +| ----------------------------------------------- | -------------- | --------------------------------------------------------------------------- | +| `scope` | string | `key` or `user`, as above | +| `usage.requests_today`, `usage.requests_month` | integer | Requests the rate limits let through in the UTC day and month, answers from the response cache included | +| `usage.tokens_today`, `usage.tokens_month` | integer | Weighted tokens, counted as limits count them, in the UTC day and month | +| `usage.cost_usd_month` | number \| null | Cost this month from the request log; `null` without ClickHouse | +| `limits[].scope` | string | Whose limit it is; the same as `scope` | +| `limits[].kind` | string | `requests` or `tokens` (weighted) | +| `limits[].window` | string | A rate limit's sliding window (`1m`, `5m`, `1h`, `5h`, `1d`, `1w`) or a budget's calendar period (`daily`, `weekly`, `monthly`) | +| `limits[].window_secs` | integer \| null | The sliding window's length in seconds; `null` for a calendar period | +| `limits[].limit` | integer | The limit | +| `limits[].used` | integer | What has been used, read from the counter that refuses requests | +| `limits[].resets_at` | string \| null | The end of a calendar period (UTC); `null` for a sliding window | +| `expires_at` | string \| null | The key's expiry or the end of its rotation grace period, whichever comes first; `null` when there is neither | + +The limit with the least left comes first. Limits on the MCP gateway are not listed. `usage` counts from the upgrade to ThinkWatch 3.5.0 on. + +#### Example + +```bash +curl http://localhost:3000/v1/usage \ + -H "Authorization: Bearer tw-your-api-key" +``` + +#### Error Responses + +| Status | Condition | +| ------ | ------------------------------------------------------------------------- | +| 401 | Missing or invalid key, as for a model request | +| 403 | The key may not use the AI gateway, as for a model request | +| 503 | The key's limits or their counters could not be read, whichever way `security.rate_limit_fail_closed` is set | + +--- + ### POST /v1/messages Anthropic Messages API endpoint. Accepts requests in the native Anthropic format and proxies them to the configured upstream provider. This allows Claude Code and the Anthropic SDK to connect directly without format translation on the client side. @@ -997,6 +1097,8 @@ curl http://localhost:3001/api/auth/me \ ### API Keys +An API key's own rate limits and budgets are edited on the **Limits** tab of the key's edit dialog in the console: rate limits on requests or weighted tokens over 1m, 5m, 1h, 5h, 1d or 1w, and daily, weekly or monthly budgets in weighted tokens, each with what it has used. They apply on top of the owner's limits, on counters of their own, and follow the key across rotations. The tab reads and changes them through `/api/admin/limits/api_key/{id}/rules`, `/api/admin/limits/api_key/{id}/budgets` and `/api/admin/limits/api_key/{id}/usage`. Reading needs `rate_limits:read` and changing `rate_limits:write`, in a scope that covers the key; without write access the tab is read-only, and without read access the dialog has no Limits tab. + #### GET /api/keys List all API keys belonging to the authenticated user. diff --git a/src/content/docs/en/configuration.md b/src/content/docs/en/configuration.md index fa39414..206d237 100644 --- a/src/content/docs/en/configuration.md +++ b/src/content/docs/en/configuration.md @@ -498,6 +498,7 @@ Changes to dynamic settings take effect immediately without requiring a server r | `security.redact` | `{}` | Outbound redaction policy, see [Request guards](#request-guards) | | `security.inspect_tools` | `{}` | Tool-call inspection policy, see [Request guards](#request-guards) | | `security.content` | `{}` | Content filter policy, see [Request guards](#request-guards) | +| `security.rate_limit_fail_closed` | `false` | Refuse requests whose limits cannot be checked, see [Limits that cannot be checked](#limits-that-cannot-be-checked) | #### Request guards @@ -516,6 +517,15 @@ Outbound redaction, tool-call inspection and the content filter each keep their The Content Security page of the console edits these objects. Through `PATCH /api/admin/settings` a key is written whole and checked first: a misspelt field, an unknown built-in rule, a pattern that does not compile or a malformed code point is refused with `400`. Writing `security.redact` takes the `pii_redactor:write` permission, and the other two keys take `content_filter:write`. `GET /api/admin/security` lists each guard's mode and every rule, and `POST /api/admin/security/{guard}/test` tries a sample against them. A deployment upgraded from a version that kept `security.content_filter_patterns`, `security.pii_redactor_patterns`, `security.hidden_text` and `security.tool_inspection` has them converted into these keys at its first start. +#### Limits that cannot be checked + +`security.rate_limit_fail_closed` decides what happens to a request whose limits cannot be checked: Redis cannot be reached, or the database fails while the request's rate limits and budgets are loaded. It covers the rate limits and budgets of users, API keys and roles and the RPM and TPM caps of routes, on the AI gateway and the MCP gateway. + +- `false`, the default: the request goes on without the limits that could not be checked, and a warning with the error is logged and counted in the `*_fail_open_total` metrics. +- `true`: the request is refused, labelled `limits_unavailable`, `budget_unavailable` or `rate_limiter_unavailable`. The AI gateway answers `429` with `Retry-After: 30` in the client's API format; the MCP gateway answers `429` with a JSON-RPC error. + +Turn it on where a request that escapes its limits is worse than a refused one. `GET /v1/usage` answers `503` while the limits cannot be read, whichever way the setting is. In the console, the setting is **Fail closed when limits can't be checked** under Settings › Security › Rate Limiter. + ### Budget | Setting | Default | Description | diff --git a/src/content/docs/en/deployment-guide.md b/src/content/docs/en/deployment-guide.md index d8084c8..644e1ee 100644 --- a/src/content/docs/en/deployment-guide.md +++ b/src/content/docs/en/deployment-guide.md @@ -231,7 +231,7 @@ docker compose -f deploy/docker-compose.yml --env-file .env.production up -d To pin a release instead of `latest`, set `IMAGE_TAG` to its version, or to the SHA of a commit on `main`: ```bash -IMAGE_TAG=3.4.0 docker compose -f deploy/docker-compose.yml --env-file .env.production up -d +IMAGE_TAG=3.5.0 docker compose -f deploy/docker-compose.yml --env-file .env.production up -d ``` This starts: @@ -724,6 +724,7 @@ The gateway (port 3000) serves three API formats on a single port: | `POST /v1/messages` | Anthropic Messages API | Claude Code, Anthropic SDK | | `POST /v1/responses` | OpenAI Responses API | OpenAI SDK (2025 format) | | `GET /v1/models` | OpenAI Models list | All clients | +| `GET /v1/usage` | Usage and limits of the calling key | Any client with a gateway API key | All endpoints accept `tw-` API keys via the `Authorization: Bearer` header. @@ -744,8 +745,8 @@ The server is stateless, so rolling updates work out of the box: ```bash # Update the image tag helm upgrade think-watch deploy/helm/think-watch \ - --set image.server.tag=3.4.0 \ - --set image.web.tag=3.4.0 \ + --set image.server.tag=3.5.0 \ + --set image.web.tag=3.5.0 \ --reuse-values ``` diff --git a/src/content/docs/zh-CN/api-reference.md b/src/content/docs/zh-CN/api-reference.md index 5d0a4e6..dddfb3d 100644 --- a/src/content/docs/zh-CN/api-reference.md +++ b/src/content/docs/zh-CN/api-reference.md @@ -31,9 +31,20 @@ | `POST /v1/messages` | Anthropic Messages API | Claude Code、Anthropic SDK | | `POST /v1/responses` | OpenAI Responses API | OpenAI SDK(2025 格式) | | `GET /v1/models` | OpenAI Models | 所有客户端 | +| `GET /v1/usage` | 调用方密钥的用量与限额 | 持有网关 API 密钥的任何客户端 | 三个端点使用相同的认证方式(API Key 或 JWT),经过相同的模型路由器和速率限制器,并生成相同的用量记录和审计日志。 +### 限流与预算 + +请求发往上游之前,按此前的用量检查其 API 密钥与密钥所属用户的限流和预算;token 在响应之后计入,由响应缓存应答的请求同样计入。所属用户的限额来自其角色(全局分配的角色,以及用户所在团队挂载的角色),按最严格的合并,再应用用户自己的覆盖。超出限额的请求返回 `429`,`Retry-After` 给出限额释放前的秒数,错误消息注明是哪一项限额,例如 `Rate limited: user:requests/1m`。被这些限额拒绝的请求,以及密钥无权使用所请求模型的请求,不计入任何限额。 + +**路由上限。**模型路由可以设置「RPM 上限」和「TPM 上限」(在路由编辑器中设置),都按一分钟的滑动窗口计数,TPM 上限与其他 token 限额一样按加权 token 计。达到任一上限的路由会被跳过,由该模型的下一条路由处理请求;剩余路由全部达到上限时,请求返回 `429` 和 `Retry-After`,标签为 `route:requests/1m` 或 `route:tokens/1m`。这样的请求已经通过调用方自己的限额,并计入其中。 + +**无法检查限额时。**Redis 无法访问,或加载请求的限额时数据库出错,由 `security.rate_limit_fail_closed` 决定:关闭(默认)时请求照常进行,不受这些限额约束,并记录一条警告;打开时拒绝请求,返回 `429` 和 `Retry-After: 30`,标签为 `rate_limiter_unavailable`、`budget_unavailable` 或 `limits_unavailable`。路由上限同样遵循这一设置。见[无法检查限额时](/zh-CN/docs/configuration#无法检查限额时)。 + +[`GET /v1/usage`](#get-v1usage) 告诉客户端它的密钥已用多少、限额还剩多少。 + ### POST /v1/chat/completions OpenAI 兼容的聊天补全端点。将请求代理到已配置的上游提供商。 @@ -196,6 +207,95 @@ curl http://localhost:3000/v1/models \ --- +### GET /v1/usage + +查询调用方 API 密钥在 AI 网关上已用多少、限额还剩多少。客户端可以据此向用户显示剩余额度,或在限额拒绝请求之前放慢速度。 + +**认证:** 可访问 AI 网关的 API Key,与模型请求相同 + +调用它不计入任何限额,不写请求日志,也不算作一次使用密钥:`last_used_at` 保持不变,因此轮询不会让闲置的密钥免于不活跃超时。 + +#### 请求 + +无请求体。无查询参数。 + +#### 响应体 + +```json +{ + "scope": "key", + "usage": { + "requests_today": 12, + "tokens_today": 48210, + "requests_month": 340, + "tokens_month": 1290455, + "cost_usd_month": 3.82 + }, + "limits": [ + { + "scope": "key", + "kind": "tokens", + "window": "daily", + "window_secs": null, + "limit": 100000, + "used": 48210, + "resets_at": "2026-10-12T00:00:00Z" + }, + { + "scope": "key", + "kind": "requests", + "window": "1m", + "window_secs": 60, + "limit": 60, + "used": 4, + "resets_at": null + } + ], + "expires_at": "2026-12-31T00:00:00Z" +} +``` + +回答针对两种对象之一,由 `scope` 指明: + +- `"key"`:密钥在 AI 网关上设有自己的限额。`limits` 只列出密钥自己的限额,`used` 按这把密钥计数;`usage` 是密钥自己的用量,跨轮换累计。 +- `"user"`:密钥没有自己的限额。`limits` 列出其所属用户的有效限额(各角色的限额,包括团队授予的角色,按最严格的合并,再应用用户自己的覆盖),`used` 按该用户的全部用量计数;`usage` 是该用户所有密钥的合计。用户也没有限额时,`limits` 为空。 + +因此,持有一把没有自己限额的密钥,就能看到其所属用户的合计用量与限额;交给他人使用的密钥应设置自己的限额。 + +| 字段 | 类型 | 描述 | +| ----------------------------------------------- | -------------- | --------------------------------------------------------------------------- | +| `scope` | string | `key` 或 `user`,见上文 | +| `usage.requests_today`、`usage.requests_month` | integer | UTC 当天与当月通过限流的请求数,包括由响应缓存应答的请求 | +| `usage.tokens_today`、`usage.tokens_month` | integer | UTC 当天与当月的加权 token,计法与限额相同 | +| `usage.cost_usd_month` | number \| null | 本月费用,取自请求日志;未配置 ClickHouse 时为 `null` | +| `limits[].scope` | string | 限额属于谁,与 `scope` 相同 | +| `limits[].kind` | string | `requests` 或 `tokens`(加权) | +| `limits[].window` | string | 限流的滑动窗口(`1m`、`5m`、`1h`、`5h`、`1d`、`1w`),或预算的日历周期(`daily`、`weekly`、`monthly`) | +| `limits[].window_secs` | integer \| null | 滑动窗口的长度(秒);日历周期为 `null` | +| `limits[].limit` | integer | 限额 | +| `limits[].used` | integer | 已用量,读自拒绝请求所依据的计数器 | +| `limits[].resets_at` | string \| null | 日历周期的结束时间(UTC);滑动窗口为 `null` | +| `expires_at` | string \| null | 密钥的过期时间或轮换宽限期的结束时间,取较早者;两者都没有时为 `null` | + +剩余比例最小的限额排在最前。MCP 网关上的限额不列出。`usage` 从升级到 ThinkWatch 3.5.0 时开始计数。 + +#### 示例 + +```bash +curl http://localhost:3000/v1/usage \ + -H "Authorization: Bearer tw-your-api-key" +``` + +#### 错误响应 + +| 状态码 | 条件 | +| ------ | ------------------------------------------------------------------------- | +| 401 | 密钥缺失或无效,与模型请求相同 | +| 403 | 密钥不能使用 AI 网关,与模型请求相同 | +| 503 | 无法读取密钥的限额或其计数器,与 `security.rate_limit_fail_closed` 的设置无关 | + +--- + ### POST /v1/messages Anthropic Messages API 端点。接受原生 Anthropic 格式的请求并代理到已配置的上游提供商。这允许 Claude Code 和 Anthropic SDK 直接连接,无需在客户端进行格式转换。 @@ -997,6 +1097,8 @@ curl http://localhost:3001/api/auth/me \ ### API 密钥 +API 密钥自己的限流与预算在控制台中密钥编辑对话框的「限额」标签页里编辑:按请求数或加权 token 计的限流(窗口为 1m、5m、1h、5h、1d 或 1w),以及按日、周或月计的加权 token 预算,各自显示已用量。它们叠加在所属用户的限额之上,单独计数,并在密钥轮换后保留。该标签页通过 `/api/admin/limits/api_key/{id}/rules`、`/api/admin/limits/api_key/{id}/budgets` 和 `/api/admin/limits/api_key/{id}/usage` 读取和修改限额。读取需要 `rate_limits:read`,修改需要 `rate_limits:write`,且权限范围须覆盖这把密钥;没有修改权限时标签页只读,没有读取权限时对话框中不显示「限额」标签页。 + #### GET /api/keys 列出当前认证用户的所有 API 密钥。 diff --git a/src/content/docs/zh-CN/configuration.md b/src/content/docs/zh-CN/configuration.md index f62d4d0..3cd4720 100644 --- a/src/content/docs/zh-CN/configuration.md +++ b/src/content/docs/zh-CN/configuration.md @@ -498,6 +498,7 @@ openssl rand -base64 32 | `security.redact` | `{}` | 出站脱敏的策略,见[请求防护](#请求防护) | | `security.inspect_tools` | `{}` | 工具调用审查的策略,见[请求防护](#请求防护) | | `security.content` | `{}` | 内容过滤的策略,见[请求防护](#请求防护) | +| `security.rate_limit_fail_closed` | `false` | 限额无法检查时拒绝请求,见[无法检查限额时](#无法检查限额时) | #### 请求防护 @@ -516,6 +517,15 @@ openssl rand -base64 32 控制台的「内容安全」页编辑这些对象。经 `PATCH /api/admin/settings` 写入时,一个键整体写入,写入前先校验:字段名拼错、内置规则 id 不存在、正则无法编译或码位写法有误时返回 `400`。写入 `security.redact` 需要 `pii_redactor:write` 权限,另外两个键需要 `content_filter:write`。`GET /api/admin/security` 列出每项防护的档位与全部规则,`POST /api/admin/security/{guard}/test` 用一段样本测试这些规则。从仍使用 `security.content_filter_patterns`、`security.pii_redactor_patterns`、`security.hidden_text` 和 `security.tool_inspection` 的版本升级时,这些设置在首次启动时转换为上述三个键。 +#### 无法检查限额时 + +请求的限额无法检查时,即 Redis 无法访问,或加载请求的限流与预算时数据库出错,由 `security.rate_limit_fail_closed` 决定如何处理。这一设置覆盖用户、API 密钥与角色的限流和预算,以及路由的 RPM 与 TPM 上限,对 AI 网关和 MCP 网关都有效。 + +- `false`(默认):请求照常进行,不受无法检查的限额约束;错误作为警告写入日志,并计入 `*_fail_open_total` 指标。 +- `true`:拒绝请求,标签为 `limits_unavailable`、`budget_unavailable` 或 `rate_limiter_unavailable`。AI 网关按客户端的 API 格式返回 `429` 和 `Retry-After: 30`;MCP 网关返回 `429` 和 JSON-RPC 错误。 + +漏算限额比拒绝请求更糟时,应打开这一设置。无论如何设置,限额无法读取时 `GET /v1/usage` 都返回 `503`。在控制台中,这一设置是「设置 › 安全 › 限速引擎」中的「限额无法检查时拒绝请求」。 + ### 预算 | 设置 | 默认值 | 描述 | diff --git a/src/content/docs/zh-CN/deployment-guide.md b/src/content/docs/zh-CN/deployment-guide.md index 2a325c8..e4ddd8c 100644 --- a/src/content/docs/zh-CN/deployment-guide.md +++ b/src/content/docs/zh-CN/deployment-guide.md @@ -231,7 +231,7 @@ docker compose -f deploy/docker-compose.yml --env-file .env.production up -d 如需固定某个版本而非 `latest`,将 `IMAGE_TAG` 设为该版本号,或 `main` 分支上某次提交的 SHA: ```bash -IMAGE_TAG=3.4.0 docker compose -f deploy/docker-compose.yml --env-file .env.production up -d +IMAGE_TAG=3.5.0 docker compose -f deploy/docker-compose.yml --env-file .env.production up -d ``` 这将启动: @@ -724,6 +724,7 @@ ThinkWatch 在 Web 控制台中内置了**配置指南**页面,位于 `/gatewa | `POST /v1/messages` | Anthropic Messages API | Claude Code、Anthropic SDK | | `POST /v1/responses` | OpenAI Responses API | OpenAI SDK(2025 格式) | | `GET /v1/models` | OpenAI Models 列表 | 所有客户端 | +| `GET /v1/usage` | 调用方密钥的用量与限额 | 持有网关 API 密钥的任何客户端 | 所有端点通过 `Authorization: Bearer` 请求头接受 `tw-` API 密钥。 @@ -744,8 +745,8 @@ ThinkWatch 在 Web 控制台中内置了**配置指南**页面,位于 `/gatewa ```bash # Update the image tag helm upgrade think-watch deploy/helm/think-watch \ - --set image.server.tag=3.4.0 \ - --set image.web.tag=3.4.0 \ + --set image.server.tag=3.5.0 \ + --set image.web.tag=3.5.0 \ --reuse-values ``` diff --git a/src/data/core-docs/config.md b/src/data/core-docs/config.md index fac9474..4320ddf 100644 --- a/src/data/core-docs/config.md +++ b/src/data/core-docs/config.md @@ -405,6 +405,8 @@ Upstreams: the APIs requests are forwarded to. | `model_specs` | map of model id → [`providers[].model_specs.*`](#cfg-providers-model_specs) | `{}` | Context window, output limit, reasoning and image input of single models of this upstream, written by hand, by exact model id. They take precedence over the price table: for models it does not know, or gets wrong. | | `max_concurrent` | integer | — | Most requests sent to this upstream at the same time, from 1 to 1000. When it is full, a conversation that stays on it waits for a free slot and other requests go to the next upstream; see `failover.slot_wait_secs`. Unset: no limit. | | `disabled` | bool | `false` | Take the upstream out of routing and out of the model list, and keep its configuration. | +| `balance` | `auto` \| `off` \| `openrouter` \| `deepseek` \| `moonshot` \| `sub2api` \| `newapi` \| `thinkwatch` | `auto` | Where the upstream's balance is read from, with its own key and proxy: `openrouter`, `deepseek`, `moonshot`, `sub2api`, `newapi` (New API and One API) or `thinkwatch` (a ThinkWatch Enterprise gateway). `auto`: recognized from `base_url` for OpenRouter, DeepSeek and Moonshot; any other address, except Anthropic's, OpenAI's and Gemini's own, is asked once whether it is a Sub2API, ThinkWatch Enterprise or New API relay, and the answer is kept in memory only. `off`: no balance. ChatGPT and Z.ai accounts and Bedrock have no balance whatever is written here. | +| `signed_in` | `zai` \| `bigmodel` | — | Which account sign-in the `key` came from: `zai` (Z.ai) or `bigmodel` (BigModel). Signing in to the account in the desktop app writes it; replacing the key there removes it. It does not change how requests are sent. Unset: the key was written by hand. | A credential is one of four things: `key`, which goes in the header the diff --git a/src/data/core-docs/config.zh-CN.md b/src/data/core-docs/config.zh-CN.md index 94b7cf7..4934f04 100644 --- a/src/data/core-docs/config.zh-CN.md +++ b/src/data/core-docs/config.zh-CN.md @@ -303,6 +303,8 @@ clients: | `model_specs` | 映射: 模型 ID → [`providers[].model_specs.*`](#cfg-providers-model_specs) | `{}` | 手写这家上游某些模型的上下文窗口、输出上限、会不会推理、收不收图,按模型 ID 完全匹配。写了就优先于价目表,用于价目表里没有或写错的模型。 | | `max_concurrent` | 整数 | — | 同时发给这家的请求最多几个,取值 1 到 1000。满了的时候,留在这家的对话等空位,别的请求换下一家;等多久见 `failover.slot_wait_secs`。不写:不限。 | | `disabled` | 布尔 | `false` | 不参与路由,模型也不出现在模型列表里;配置原样保留。 | +| `balance` | `auto` \| `off` \| `openrouter` \| `deepseek` \| `moonshot` \| `sub2api` \| `newapi` \| `thinkwatch` | `auto` | 从哪里读这家上游的余额,用它自己的密钥、走它自己的代理:`openrouter`、`deepseek`、`moonshot`、`sub2api`、`newapi`(New API 和 One API)或 `thinkwatch`(ThinkWatch 企业网关)。`auto`:OpenRouter、DeepSeek、Moonshot 按 `base_url` 识别;其他地址(Anthropic、OpenAI、Gemini 的官方地址除外)询问一次它是不是 Sub2API、ThinkWatch 企业网关或 New API 中转站,结果只保存在内存中。`off`:不读余额。ChatGPT、Z.ai 账号和 Bedrock 不读余额,与这里写什么无关。 | +| `signed_in` | `zai` \| `bigmodel` | — | `key` 来自哪一家的账号登录:`zai`(Z.ai)或 `bigmodel`(BigModel)。在桌面端登录账号时写入,在桌面端更换密钥时删除。不影响请求的发送方式。不写:密钥是手动填写的。 | 凭据有四种写法:`key`,放进协议规定的请求头;`oauth`,用 refresh token 换取 token;`aws`,Bedrock 上游签名请求用的访问密钥;`headers`,用于上游自有的鉴权方式。`headers` 可以和其余几种同时使用,但不能再设置已经承载凭据的那个请求头。 diff --git a/src/data/core-docs/manifest.json b/src/data/core-docs/manifest.json index 16a5b42..18e4e4a 100644 --- a/src/data/core-docs/manifest.json +++ b/src/data/core-docs/manifest.json @@ -1,9 +1,9 @@ { "repository": "ThinkWatchProject/ThinkWatch-Core", - "ref": "v0.69.0", + "ref": "v0.70.0", "files": { - "docs/config.md": "71c13485896f5c94579b72e906ea3d834c50305a584b11faf00d4af0e4ef59bb", - "docs/config.zh-CN.md": "f487fb3c15c2e8004078d33954198db5971afc967495f6712569b286a2b4f47f", + "docs/config.md": "6f281936051e2586c4076c62e22759a0addaad7b493b53dc427d74966a84a109", + "docs/config.zh-CN.md": "bc2a649755cc7f705151658213232a78dcdcf176b770f8f66cf1fdf9a7e27a6f", "docs/server.md": "5e1e9b901bef2b46d417aea057a1db24c78457d3c1938b8540ecb4766515b68f", "docs/server.zh-CN.md": "1f508e7c39b8ded28653773ca4d8701e6bdc2247bcd359c3a8fd00fd1401a6ff" } diff --git a/src/i18n/index.ts b/src/i18n/index.ts index 259cc7d..bbf0cbc 100644 --- a/src/i18n/index.ts +++ b/src/i18n/index.ts @@ -89,7 +89,7 @@ const dict = { { title: "Per-model routing: automatic or manual", body: "Each model has its own routing setting. Automatic modes weight upstreams by latency, by success rate, or by both combined (the default); manual mode splits traffic by fixed weights set on a drag bar. A circuit breaker takes failing upstreams out of rotation, a request that fails with a retryable error is sent to another upstream, and the console shows live health for every route." }, { title: "Multiple providers and a model-level kill switch", body: "OpenAI, Anthropic, Google Gemini, Azure OpenAI, AWS Bedrock, or any OpenAI-compatible endpoint, with automatic format conversion. A single model can be paused without disabling the whole provider, and every request log records the upstream model that actually served the request." }, { title: "Virtual API keys", body: "Each tw- key belongs to one user and can be limited to the AI gateway, the MCP gateway, the admin API, or any combination, and tagged with a cost center. Keys support expiry, inactivity timeouts, and rotation with a grace period in which the old key keeps working; revoked and disabled keys are listed on a separate tab. The plaintext is shown once, and only a hash is stored." }, - { title: "Rate limits & budgets", body: "Sliding windows from one minute to one week limit requests or tokens, and daily, weekly, or monthly budgets cap token use, weighted per model. Both attach to users, API keys, or roles and apply to MCP tool calls as well as model requests. Request counts are checked before a request; tokens and budgets are counted after the response, and once a budget is used up further requests are refused. If Redis is unavailable, limits are skipped by default; a setting makes the gateway refuse requests instead." }, + { title: "Rate limits & budgets", body: "Sliding windows from one minute to one week limit requests or tokens, and daily, weekly, or monthly budgets cap token use, weighted per model. Both attach to users, API keys, or roles and apply to MCP tool calls as well as model requests. Request counts are checked before a request; tokens and budgets are counted after the response, and once a budget is used up further requests are refused. A client can ask the gateway what its key has used and how much room its limits leave. If Redis or the database cannot be read, limits are skipped by default; a setting makes the gateway refuse those requests instead." }, { title: "Cost reporting", body: "Each request is priced from a platform-wide per-token price and per-model weights. Spend is reported by model, user, provider, and cost center and can be filtered by team, with CSV chargeback reports and a month-end forecast. Budget alerts at 50%, 80%, 95%, and 100% are written to the audit log once per period." }, { title: "Management API & OpenAPI", body: "API keys, users, providers, and settings can be managed through the admin API, using a tw- key that is allowed to call it. An OpenAPI specification describes the endpoints, so scripts and CI pipelines can manage key lifecycles without the console." }, ], @@ -321,7 +321,7 @@ const dict = { { title: "按模型路由:自动或手动", body: "每个模型有独立的路由设置。自动模式按延迟、成功率或两者结合(默认)为上游分配权重;手动模式通过拖拽流量条按固定比例分配。熔断器将故障上游移出轮换,因可重试错误而失败的请求会转发到其他上游,控制台展示每条路由的实时健康状态。" }, { title: "多 Provider 与模型级开关", body: "OpenAI、Anthropic、Google Gemini、Azure OpenAI、AWS Bedrock,或任意 OpenAI 兼容端点,请求格式自动转换。可在不停用整个 Provider 的前提下暂停单个模型;每条请求日志均记录实际提供服务的上游模型。" }, { title: "虚拟 API 密钥", body: "每把 tw- 密钥归属于一位用户,可限定用于 AI 网关、MCP 网关、管理 API 或其任意组合,并可标注成本中心。密钥支持到期时间、闲置超时,以及带宽限期的轮换(宽限期内旧密钥仍可使用);已吊销和已停用的密钥列在单独的分页中。明文仅展示一次,只存储哈希。" }, - { title: "限流与预算", body: "滑动窗口(1 分钟至 1 周)限制请求数或 token 数,按日、周或月设置的预算限制 token 用量(按模型加权)。两者均可设置在用户、API 密钥或角色上,同时作用于模型请求与 MCP 工具调用。请求数在请求前检查;token 与预算在响应后计入,预算用尽后的请求会被拒绝。Redis 不可用时默认不做限制,也可设置为直接拒绝请求。" }, + { title: "限流与预算", body: "滑动窗口(1 分钟至 1 周)限制请求数或 token 数,按日、周或月设置的预算限制 token 用量(按模型加权)。两者均可设置在用户、API 密钥或角色上,同时作用于模型请求与 MCP 工具调用。请求数在请求前检查;token 与预算在响应后计入,预算用尽后的请求会被拒绝。客户端可以向网关查询自己的密钥已用多少、限额还剩多少。Redis 或数据库读取失败时默认不做限制,也可设置为直接拒绝这些请求。" }, { title: "成本核算", body: "每个请求按平台统一的 token 单价与各模型的权重计价。费用可按模型、用户、Provider 与成本中心汇总,并可按团队筛选,支持导出 CSV 分摊报表和月末预测。预算用量达到 50%、80%、95%、100% 时,每个周期各在审计日志中记录一次预警。" }, { title: "管理 API 与 OpenAPI 文档", body: "API 密钥、用户、Provider 与各项设置均可通过管理 API 管理,使用获准调用管理 API 的 tw- 密钥即可。OpenAPI 规范描述了各个接口,脚本与 CI 流水线无需控制台即可管理密钥的生命周期。" }, ], diff --git a/src/i18n/pages/lite.ts b/src/i18n/pages/lite.ts index a4dc6c1..4ac2c42 100644 --- a/src/i18n/pages/lite.ts +++ b/src/i18n/pages/lite.ts @@ -148,7 +148,7 @@ export const liteCopy = { { id: "upstreams", title: "Any upstream, any API format", - body: "API keys, Amazon Bedrock, ChatGPT and Z.ai accounts, relays such as OpenRouter and local Ollama models all serve as upstreams, with subscription quotas and reset times shown. Requests are converted between the Anthropic, OpenAI and Gemini APIs, so Codex can also use models that only speak Chat Completions.", + body: "API keys, Amazon Bedrock, ChatGPT and Z.ai accounts, relays such as OpenRouter and local Ollama models all serve as upstreams, with the balances, quotas and reset times their services report shown. Requests are converted between the Anthropic, OpenAI and Gemini APIs, so Codex can also use models that only speak Chat Completions.", alt: "The Upstreams page: API-key upstreams for Anthropic, DeepSeek and Gemini, a relay priced with its own price sheet, a ChatGPT Plus account with 58% of its 5-hour limit used, OpenRouter through a proxy and a local Ollama set to free, each with its requests, cost and latency over 24 hours", }, { @@ -391,7 +391,7 @@ export const liteCopy = { { id: "upstreams", title: "多种上游,接口互转", - body: "API 密钥、Amazon Bedrock、ChatGPT 与 Z.ai 账号、OpenRouter 等中转服务以及本机 Ollama 均可作为上游,订阅额度与重置时间一并显示。Anthropic、OpenAI、Gemini 接口之间自动转换,Codex 也能使用只支持 Chat Completions 的模型。", + body: "API 密钥、Amazon Bedrock、ChatGPT 与 Z.ai 账号、OpenRouter 等中转服务以及本机 Ollama 均可作为上游,服务报告的余额、额度与重置时间一并显示。Anthropic、OpenAI、Gemini 接口之间自动转换,Codex 也能使用只支持 Chat Completions 的模型。", alt: "上游页:Anthropic、DeepSeek、Gemini 等 API 密钥上游,按自有价目表计价的中转,5 小时额度已用 58% 的 ChatGPT Plus 账号,经代理访问的 OpenRouter,以及设为免费的本机 Ollama,并列出各自 24 小时的请求数、费用与延迟", }, {