feat: sync deployed v1.0.0-rc.38-custom.42
Sync production source including routing, billing, Astra detection and public uptime. Update custom build instructions and license packaging.
This commit is contained in:
1 parent
aa6c3f50f4
commit
ceddfd3d6b
828 files changed
+122253
-13702
No files matched your search
+35
-7
@@ -2,15 +2,26 @@
|
||||
Agent-only issue body. Humans use GitHub issue forms.
|
||||
|
||||
Keep every heading. If a section does not apply, write why; do not delete it.
|
||||
Match the user's language in the filled answers. Quote what the user said; do not invent facts.
|
||||
Match the user's language in the filled answers. Do not invent facts.
|
||||
|
||||
User request: quote the request the user made to the agent as faithfully as
|
||||
possible. Keep the original language and line breaks. Do not rewrite,
|
||||
summarize, translate, or turn it into an issue description.
|
||||
|
||||
Keep filled answers short and factual. Do not paste unfiltered AI-generated
|
||||
text, speculation, or an implementation plan in the issue body or in later
|
||||
comments. Extract the evidence maintainers need to review. Repeated
|
||||
submissions of unfiltered AI-generated text may result in a block.
|
||||
|
||||
If a field below is missing from the conversation, ask the user that question
|
||||
and wait. Ask for the facts themselves. Do not tell the user to confirm a
|
||||
template, tick checkboxes, or acknowledge the guidelines.
|
||||
|
||||
Before filing, refuse out-of-scope requests listed below. Then search the docs,
|
||||
DeepWiki, README, and the code. If this is a usage, configuration, or
|
||||
integration question, answer the user from that material and do not file.
|
||||
Do not file unless every required condition is met. If the request is out of
|
||||
scope (including pass-through), is a usage/configuration/integration question,
|
||||
is missing required facts, or the body would be unfiltered AI-generated text,
|
||||
tell the user and **stop**. Do not create the issue. Do not file a partial
|
||||
issue. Do not fill gaps with speculation.
|
||||
-->
|
||||
|
||||
## Agent
|
||||
@@ -23,7 +34,12 @@ integration question, answer the user from that material and do not file.
|
||||
|
||||
## User request
|
||||
|
||||
(verbatim or close paraphrase)
|
||||
Quote the request the user made to the agent as faithfully as possible.
|
||||
Keep the original language and line breaks. Do not rewrite, summarize,
|
||||
translate, or turn it into an issue description.
|
||||
|
||||
- Verbatim:
|
||||
- Later constraints or corrections from the user (quote, or none):
|
||||
|
||||
## Out of scope — refuse
|
||||
|
||||
@@ -35,7 +51,7 @@ accept it, point them to the right place when there is one, and **do not file**.
|
||||
- Third-party API wrappers
|
||||
- Compatibility issues from exposing a Codex endpoint as a general-purpose API through a reverse proxy
|
||||
- Codex API-specific protocol or behavior treated as standard OpenAI API behavior (confirm with the channel or API provider)
|
||||
- Pass-through mode forwarding (pass-through forwards as-is; verify upstream yourself)
|
||||
- Pass-through mode forwarding (do not file: pass-through sends content as-is and does not go through new-api processing logic)
|
||||
- Relay reports that only paste an upstream error, with no direct-upstream vs new-api comparison
|
||||
- Third-party hosting sites, relay services, or API services (contact their operator)
|
||||
- Usage, configuration, or integration questions (answer from docs and code instead)
|
||||
@@ -43,6 +59,17 @@ accept it, point them to the right place when there is one, and **do not file**.
|
||||
- Matched: yes/no
|
||||
- If yes, what was told to the user (stop here; do not file):
|
||||
|
||||
## File gate — do not file unless all are satisfied
|
||||
|
||||
If any item fails, tell the user and **stop**. Do not create the issue.
|
||||
|
||||
- Out of scope (including pass-through): no
|
||||
- Usage / configuration / integration (answered instead of filing): no
|
||||
- Required facts present without invention (actual behavior, impact, frequency, evidence in new-api, applicable type fields): yes
|
||||
- Body is short and factual; no unfiltered AI-generated text: yes
|
||||
- File: yes/no
|
||||
- If no, what was told to the user (stop here):
|
||||
|
||||
## Kind
|
||||
|
||||
- [ ] Bug
|
||||
@@ -69,7 +96,7 @@ Search these yourself before filing. Do not send the user to "read the docs firs
|
||||
|
||||
## Problem facts
|
||||
|
||||
Ask the user for every item and write it down:
|
||||
Ask the user for every item and write it down. Facts only; do not paste unfiltered AI-generated text:
|
||||
|
||||
- Actual behavior:
|
||||
- Impact:
|
||||
@@ -134,6 +161,7 @@ Fill every applicable type. Write "not applicable" for the rest. Ask the user fo
|
||||
## Research
|
||||
|
||||
Open the docs and code. Do not write "already checked" without sources.
|
||||
Do not replace the fields below with unfiltered AI-generated text.
|
||||
|
||||
### Docs
|
||||
|
||||
|
||||
+39
-10
@@ -2,7 +2,16 @@
|
||||
Agent-only PR body. Humans use `.github/PULL_REQUEST_TEMPLATE.md`.
|
||||
|
||||
Keep every heading. If a section does not apply, write why; do not delete it.
|
||||
Match the user's language in the filled answers. Quote what the user said; do not invent facts.
|
||||
Match the user's language in the filled answers. Do not invent facts.
|
||||
|
||||
User request: quote the request the user made to the agent as faithfully as
|
||||
possible. Keep the original language and line breaks. Do not rewrite,
|
||||
summarize, translate, or turn it into a PR description.
|
||||
|
||||
Keep the body short and factual. Do not paste unfiltered AI-generated text
|
||||
in the PR body or in later comments. Repeated submissions of this kind may
|
||||
result in a block. Verification must be commands actually run and what was
|
||||
observed. Stating only that `go build` or tests passed is not proof.
|
||||
|
||||
New features: link an issue; if none exists, file one first with `.agents/github/ISSUE.md`.
|
||||
Large or directional changes: maintainer agreement on that issue before this PR.
|
||||
@@ -12,10 +21,11 @@ frequency, evidence that the problem is in new-api, or the applicable
|
||||
relay / billing / frontend / deployment items, ask the user those questions
|
||||
and wait. Ask for the facts. Do not tell the user to confirm a template.
|
||||
|
||||
Before opening, refuse the same out-of-scope list as `.agents/github/ISSUE.md`
|
||||
(Coding Plan, reverse-engineered channels, third-party wrappers, Codex reverse-proxy
|
||||
compatibility, pass-through-only forwarding, third-party hosts, usage questions).
|
||||
Tell the user and do not open a PR.
|
||||
Do not open a PR unless every required condition is met. If the change is out
|
||||
of scope (including pass-through-only forwarding), is a usage/configuration/
|
||||
integration question, is missing required issue facts, has only `go build` /
|
||||
tests-passed as verification, or the body would be unfiltered AI-generated
|
||||
text, tell the user and **stop**. Do not open the PR. Do not open a partial PR.
|
||||
|
||||
Then search https://docs.newapi.ai/ , https://deepwiki.com/QuantumNous/new-api ,
|
||||
the README, and the code. If this is a usage, configuration, or integration
|
||||
@@ -37,7 +47,12 @@ question, answer the user and do not open a PR.
|
||||
|
||||
## User request
|
||||
|
||||
(verbatim or close paraphrase)
|
||||
Quote the request the user made to the agent as faithfully as possible.
|
||||
Keep the original language and line breaks. Do not rewrite, summarize,
|
||||
translate, or turn it into a PR description.
|
||||
|
||||
- Verbatim:
|
||||
- Later constraints or corrections from the user (quote, or none):
|
||||
|
||||
## Out of scope — refuse
|
||||
|
||||
@@ -49,13 +64,25 @@ accept it and **do not open a PR**.
|
||||
- Third-party API wrappers
|
||||
- Codex channel-type changes, or compatibility from exposing Codex as a general-purpose API
|
||||
- Codex API-specific protocol or behavior treated as standard OpenAI API behavior
|
||||
- Pass-through-only forwarding
|
||||
- Pass-through-only forwarding (pass-through sends content as-is and does not go through new-api processing logic)
|
||||
- Third-party hosting sites, relay services, or API services
|
||||
- Usage, configuration, or integration (answer from docs and code instead)
|
||||
|
||||
- Matched: yes/no
|
||||
- If yes, what was told to the user (stop here; do not open a PR):
|
||||
|
||||
## Open gate — do not open unless all are satisfied
|
||||
|
||||
If any item fails, tell the user and **stop**. Do not open the PR.
|
||||
|
||||
- Out of scope (including pass-through-only forwarding): no
|
||||
- Usage / configuration / integration (answered instead of opening): no
|
||||
- Required issue facts present without invention: yes
|
||||
- Verification is actual commands or steps and observed results, not only `go build` or tests passed: yes
|
||||
- Body is short and factual; no unfiltered AI-generated text: yes
|
||||
- Open: yes/no
|
||||
- If no, what was told to the user (stop here):
|
||||
|
||||
## Kind
|
||||
|
||||
- [ ] Bug fix
|
||||
@@ -76,7 +103,8 @@ Take these from the linked issue. If a needed item is empty, ask the user that q
|
||||
|
||||
## Change
|
||||
|
||||
(what changed, why it works, grounded in the code actually touched)
|
||||
(what changed, why it works, grounded in the code actually touched.
|
||||
Short and factual; do not paste unfiltered AI-generated text.)
|
||||
|
||||
## Research
|
||||
|
||||
@@ -114,7 +142,8 @@ Open them. Do not write "already checked" without sources.
|
||||
|
||||
## Verification
|
||||
|
||||
Only what was actually run.
|
||||
Only what was actually run. Do not state only that `go build` or tests passed.
|
||||
Each item needs the command or steps and the observed result.
|
||||
|
||||
- Commands and results:
|
||||
- Manual steps and observed result:
|
||||
@@ -133,4 +162,4 @@ Only what was actually run.
|
||||
|
||||
- Single focused change: yes/no (if no, why):
|
||||
- Secrets included: no
|
||||
- Out of scope (Coding Plan / reverse-engineered channel / third-party wrapper / Codex): no
|
||||
- Out of scope (Coding Plan / reverse-engineered channel / third-party wrapper / Codex / pass-through-only forwarding): no
|
||||
@@ -0,0 +1,28 @@
|
||||
# Billing Rules
|
||||
|
||||
Mandatory conventions for quota, pricing, pre-consume, settlement, refund, and usage-quantity code in the Go backend. `AGENTS.md` defines when a task touches billing (see **Billing rules (mandatory read gate)**); any task that matches MUST read this whole file before planning, coding, or reviewing. Tasks that match none of those triggers may skip it. Rules use the same MUST / Do NOT wording as `AGENTS.md` and carry the same weight.
|
||||
|
||||
**Billing expression system:** When working on tiered/dynamic billing (expression-based pricing), MUST read `pkg/billingexpr/expr.md` first. It documents the design philosophy, expression language, full architecture, token normalization rules, quota conversion, and expression versioning. All billing expression changes must follow that document.
|
||||
|
||||
**Built-in model pricing:** New built-in model prices MUST be defined as self-contained billing expressions in `setting/billing_setting/builtin_billing.go`, using real USD per million tokens. Do not add new built-in prices to the legacy model/completion/cache ratio tables. Preserve explicit administrator pricing overrides. Existing legacy prices are migrated only when explicitly requested. Verify published prices and cover applicable context-length thresholds and cache categories.
|
||||
|
||||
**Billing safety invariants:** Quota/billing code MUST never produce a negative charge (a credit) from arithmetic overflow or unvalidated input. Apply defense in depth:
|
||||
|
||||
- Every user-controlled quantity that becomes a billing multiplier (image `n`, video `seconds`/`duration`, resolution/quality ratios, batch counts) MUST be bounded before it reaches quota calculation. Reject out-of-range values at request validation with a 400. Existing bounds: `dto.MaxImageN` for image generation count, `relaycommon.MaxTaskDurationSeconds` for task video duration, `maxTokensLimit` (`relay/helper/valid_request.go`) for `max_tokens`-family fields on every relay format (OpenAI, Claude, Gemini, Responses). Reuse these constants instead of introducing new ad hoc limits for the same concepts. When adding a new relay format or request DTO, bound its max-tokens and count fields in its validator from day one.
|
||||
- Watch for validation bypass paths: passthrough fields (e.g. `Extra["parameters"]`), task `metadata` maps, and multipart form fields can carry the same quantities around the standard DTO validation. Any adaptor that reads a multiplier from such a path must enforce the same bound (or clamp) locally.
|
||||
- Durations parsed from media metadata are user/upstream-controlled too: audio file headers (transcription token counting, TTS response duration) and upstream deduction numbers (e.g. Kling `FinalUnitDeduction`) can claim absurd values. Convert them with saturation before they become token counts.
|
||||
- Never convert a computed quota or token count to `int` with a bare cast like `int(float64(quota) * ratio)`, `int(math.Round(...))` on unbounded input, or `int(decimal.IntPart())`. All quota rounding/conversion is centralized in `common/quota_math.go`; use those helpers: `common.QuotaFromFloat` (truncating) for float products, `common.QuotaRound` (half-away-from-zero) where rounding is intended, and `common.QuotaFromDecimal` for decimal products. `billingexpr.QuotaRound` delegates to `common.QuotaRound`. Do not reintroduce local conversion helpers or bare casts. Single-request saturation stays at the int32 boundary so batch accumulation cannot approach 64-bit wraparound; wallet/top-up conversion uses `common.WalletQuotaFromDecimalStrict` with the JavaScript-safe `common.MaxWalletQuota` boundary. Every clamp/NaN fallback is logged via `common.SysError`.
|
||||
- Saturation events are also audited: each helper has a `*Checked` variant (`common.QuotaFromFloatChecked` / `QuotaRoundChecked` / `QuotaFromDecimalChecked`) that additionally returns a `*common.QuotaClamp` when clamping occurred. Billing paths that compute a charge capture that clamp onto `relayInfo.QuotaClamp` (or thread it into task settlement) and, right before writing the consume/task log, call `attachQuotaSaturation` (in `service/log_info_generate.go`) which nests the marker under the log's `other.admin_info.quota_saturation` and emits a request-correlated `logger.LogWarn`. Nesting under `admin_info` makes it admin-only for free (non-admin log views strip `admin_info`). When adding a new billing path, use the `*Checked` variant and surface the clamp the same way so the anomaly stays auditable in both the admin log UI and backend logs.
|
||||
- Multiplier maps go through `types.PriceData.AddOtherRatio`, which rejects non-positive, NaN, and +Inf ratios. Do not write to `PriceData.OtherRatios` directly, and do not weaken these guards.
|
||||
- Pre-consume (预扣费) and settle (结算/差额) must both be safe: a saturated oversized quota must fail pre-consume with insufficient-quota, never silently wrap. When adding a new billing path (new relay format, new task platform, new adjustment hook), trace the full chain — validation → EstimateBilling/OtherRatios → quota conversion → pre-consume → settle/refund — and confirm each step preserves these invariants.
|
||||
- Fields parsed into unsigned types (`*uint`) accept huge positive JSON numbers (e.g. `18446744073686646784`, a wrapped negative); a `>= 0` check is not sufficient, an upper bound is mandatory.
|
||||
- Regression tests for these invariants belong with the boundary they protect (request validators, converter helpers). See `relay/helper/openai_image_request_test.go`, `relay/common/relay_utils_test.go`, and `common/quota_math_test.go` for the expected style.
|
||||
|
||||
**Upstream image quantity settlement:** The billable image count may be lowered or raised from the upstream response only through `RelayInfo.UpdateImageCount`; a zero or out-of-range count leaves the reserved request quantity in place. Derive the count from image payloads, never from JSON structure:
|
||||
|
||||
- Do NOT count `data` with gjson `data.#`, `len(data)`, or any element count. Providers behind OpenAI-compatible channels return non-standard shapes: `data` as a single object, one image split into a `url` entry and a `b64_json` entry, or entries carrying only `revised_prompt`.
|
||||
- An object-shaped `data` is one image when it has a non-empty `url` or `b64_json`, otherwise zero. For arrays the count is `max(entries with non-empty url, entries with non-empty b64_json)`: a standard response uses one `response_format` so this equals the entry count, a split image bills once, and payload-less entries bill nothing. The reference implementation is `openaiImageResponseCount` in `relay/channel/openai/relay_image.go`; reuse it (or the same rule) for any channel that forwards or rebuilds OpenAI-format image responses. The xAI adaptor already inherits it through `OpenaiImageHandler`.
|
||||
- When an OpenAI-format JSON body is re-emitted as SSE, forward one `image_generation.completed` event per image payload using the same shape handling (object → one event, payload-less entries dropped). The client must never receive only `[DONE]` while being charged for images.
|
||||
- Real SSE streams count `image_generation.completed` / `image_edit.completed` events and only trust a lower count when upstream finished the stream (`done` / `eof`); a client abort must not reduce the charge below the requested quantity.
|
||||
- Channels with their own usage field (Ali `usage.image_count`) use that value, bounded by `dto.MaxImageN`, and fall back to the converted response length. Channels that rebuild responses from typed structs count the typed slice; none of them may read `data.#`.
|
||||
- Regression cases for object, split, and payload-less shapes belong in `relay/channel/openai/image_stream_test.go` (fixed-price, tiered-expression, and JSON-as-SSE forwarding tables). Extend those tables instead of adding new files.
|
||||
Reference in new issue
Block a user