zcode-api / src /config /types.ts
bolikoto's picture
Deploy minimal Docker Space
67d18ac verified
Raw History Blame Contribute Delete
9.33 kB
/**
* Configuration types for zcode-proxy.
* @see .omo/plans/zcode-proxy.md Task 2
*/
/** Provider endpoint configuration (one per upstream provider). */
export interface ProviderEndpoints {
/** Base URL for Anthropic-format API, e.g. "https://api.z.ai/api/anthropic". */
anthropicBase: string;
/** Base URL for OpenAI-format API, e.g. "https://api.z.ai/api/coding/paas/v4". */
openaiBase: string;
}
/** Auth section of the proxy configuration. */
interface AuthConfig {
/**
* Key that clients must provide to use the proxy (via `Authorization: Bearer {proxyApiKey}`).
* If unset, the proxy does not require client auth.
*/
proxyApiKey?: string;
/** Path to stored OAuth credentials created by `auth login`. */
oauthCredentialsPath?: string;
}
/**
* Identity headers injected on every upstream request to mimic the ZCode
* desktop client. Mirrors the `pio` builder in the reverse-engineered bundle
* (`_reverse/zcode.cjs`); see `_reverse/NOTEPAD.md` "How Credential is Used".
*
* Resolution: env var (matches ZCode's own convention) → YAML override → default.
* `appVersion` must be printable ASCII (`/^[\x20-\x7e]+$/`); non-conforming
* values are silently dropped and fall back to the default (current ZCode
* release), exactly like `fio` in the bundle.
*/
export interface ProxyIdentity {
appVersion: string;
sourceTitle: string;
refererOrigin: string;
/**
* Device identity for `X-Device-Mid` (mirrors ZCode's telemetry deviceMid:
* a random UUIDv4 generated ONCE and reused forever — no hardware values).
* Empty/undefined omits the header. Desktop: persisted in config.yaml
* (`ensureDeviceMidInConfig`). Android: injected via the
* `ZCODE_IDENTITY_DEVICE_MID` env var (NodeRunner, app-private file) — env
* wins over YAML. Must stay stable per anti-pattern #13; never randomize
* per-request.
*/
deviceMid?: string;
}
/** Local client-session inference mode for upstream session affinity. */
export interface ClientIdentityConfig {
/** "observe" logs/instruments only; "enforce" reuses upstream x-session-id; "off" disables inference. */
mode: "off" | "observe" | "enforce";
/** In-memory session TTL in seconds. */
ttlSeconds: number;
/** Maximum number of inferred sessions retained in memory. */
maxSessions: number;
}
/**
* Responses-API (`/v1/responses`) configuration. When `enabled`, the proxy
* translates Codex-style Responses requests to the GLM Chat Completions upstream.
*/
export interface ResponsesConfig {
/** Enable the `/v1/responses` route. Default `true`. */
enabled: boolean;
/** Max stored responses (LRU). Default 1000. */
storeMaxEntries: number;
/** Stored-response TTL in ms. Default 24h (in-memory; cleared on restart). */
storeTtlMs: number;
}
/** GLM MCP hosted-tool configuration. Endpoints are derived from the active provider. */
export interface McpConfig {
/** Enable MCP interception (web_search) and function-tool injection (web_reader/zread). Default `true`. */
enabled: boolean;
/** Intercept `web_search` / `web_search_preview` hosted tools via GLM `web_search_prime` MCP. Default `true`. */
webSearch: boolean;
/** Inject `webReader` as a function tool the model can call. Default `false` (off by default to limit scope). */
webReader: boolean;
/** Inject the three `zread` tools as function tools. Default `false`. */
zread: boolean;
}
/**
* Async (off-peak / idle-plan) bridge configuration. When `enabled`, exposes
* `/async/v1/messages` and `/async/v1/chat/completions` that route to ZCode's
* off-peak ticket-queue backend. The proxy keeps the client connection alive
* with SSE comments during ticket-queue wait, forwards the LLM stream once
* the ticket is `ready`, and auto-retries on ticket-expired (up to `maxRetries`).
*
* Requires a logged-in oauth credential (off-peak needs both
* `Authorization: Bearer ${jwt}` and `X-Coding-Plan-Api-Key` headers). A
* credential lacking the JWT makes the route entry return 400
* `async_credentials_unavailable`.
*
* @see _reverse/NOTEPAD.md "Off-Peak / Idle Plan" section for full upstream protocol.
*/
export interface AsyncConfig {
/** Enable the `/async/*` routes. Default `false`. */
enabled: boolean;
/** Base origin for off-peak endpoints. Default `"https://zcode.z.ai"`. */
origin: string;
/** Ticket-status poll interval in ms. Default `5000`. */
pollIntervalMs: number;
/** SSE keepalive comment interval during ticket-queue wait, in ms. Default `3000`. */
keepAliveIntervalMs: number;
/** Maximum total wait time for a ticket to become `ready`, in ms. `0` = unlimited. Default `0`. */
maxWaitMs: number;
/** Maximum auto-retry count on `off-peak-ticket-expired`. Default `3`. */
maxRetries: number;
/** Settle call timeout in ms (best-effort close-out on completion/abort). Default `8000`. */
settleTimeoutMs: number;
/** Control-plane call (takeTicket/pollStatus) timeout in ms. Default `15000`. */
controlTimeoutMs: number;
/** Optional model override; empty string uses the request's `model`. Default `""`. */
defaultModel: string;
}
/**
* Manual claim ("weekend plan") — mirrors the ZCode 3.10 desktop client's
* `manualClaimPlan` feature: periodically list claimable trial plans
* (`GET {origin}/api/v1/zcode-plan/billing/preview`) and, when one is
* available, claim it (`POST {origin}/api/v1/zcode-plan/billing/claim`) with
* the OAuth JWT and an Aliyun captcha token. Claimed plans grant Start-Plan
* style quota with delayed activation (`effective_at` / `starts_at`).
*
* Requires `auth.mode: oauth` (claim uses `Authorization: Bearer ${jwt}`).
*
* @see _reverse/NOTEPAD.md "Manual Claim Plan" section for the protocol.
*/
export interface ClaimConfig {
/** Enable the claim subsystem (CLI `claim` command + auto scheduler). Default `true`. */
enabled: boolean;
/** Auto-claim in the background while the proxy is serving. Default `true` (effective when `enabled`). */
auto: boolean;
/** Base origin of the zcode-plan billing endpoints. Default `"https://zcode.z.ai"`. */
origin: string;
/** Preview poll interval in ms. Default `300000` (5 min). */
pollIntervalMs: number;
/** Backoff after a failed claim attempt in ms. Default `600000` (10 min). */
cooldownMs: number;
/** Optional `plan_id` to claim; empty string claims the highest-priority preview. Default `""`. */
planId: string;
}
/**
* Provider endpoint routing — mirrors the ZCode client's
* `ProviderEndpointRoutingService`: periodically fetch
* `GET {configUrl}/api/v1/agent/configs` and rewrite matching upstream URLs
* per the server-controlled `data.proxyEndpoint.mapping` table. As of
* 2026-08-19 only the coding-plan Anthropic endpoints are mapped (to
* `zcode.z.ai/api/v1/ultra[-zai]/...`); resolution is generic so future
* entries apply automatically. Always fail-open.
*/
export interface EndpointRoutingConfig {
/** Enable URL remapping. Default `true`. */
enabled: boolean;
/** Base origin of the agent-configs endpoint. Default `"https://zcode.z.ai"`. */
origin: string;
}
/**
* Client request signing V4 — mirrors the ZCode 3.9.1
* `ClientRequestSigningV4Signer`. When enabled, the proxy probes the same
* feature gate the client uses (`GET {origin}/api/v1/agent/configs` →
* `data.codingPlanSignature.enable`) and, only if the server turns the feature
* on, signs coding-plan upstream requests (handshake + Ed25519 + proof-of-work,
* with the client's fail-open retry ladder). Start-plan and off-peak paths are
* permanently exempt.
*/
export interface ClientSigningConfig {
/** Enable gate probing + signing. Default `true`. */
enabled: boolean;
/** Base origin of the feature-gate endpoint. Default `"https://zcode.z.ai"`. */
origin: string;
}
/** Top-level proxy configuration. */
export interface ProxyConfig {
server: {
port: number;
host: string;
};
auth: AuthConfig;
/** Active upstream provider. */
provider: "zai" | "bigmodel";
/** Which plan tier to use. "coding-plan" (default) uses direct upstream endpoints; "start-plan" routes through zcode.z.ai with JWT auth. */
plan: "coding-plan" | "start-plan";
/** Per-provider endpoint overrides. */
providers: {
zai: ProviderEndpoints;
bigmodel: ProviderEndpoints;
};
/** Default model id used when client request omits `model`. */
defaultModel: string;
/** Whitelist of allowed model ids. */
models: string[];
/**
* Identity headers injected upstream. Always present after `loadConfig`;
* defaults mirror the production ZCode desktop client.
*/
identity: ProxyIdentity;
/** Local client session inference for cache-affinity experiments. */
clientIdentity: ClientIdentityConfig;
/** Responses-API (`/v1/responses`) configuration. */
responses: ResponsesConfig;
/** Server-controlled upstream URL remapping (ultra endpoints). */
endpointRouting: EndpointRoutingConfig;
/** Client request signing V4 (Ed25519 + PoW, gate-driven). */
clientSigning: ClientSigningConfig;
/** GLM MCP hosted-tool configuration. */
mcp: McpConfig;
/** Async (off-peak / idle-plan) bridge configuration. */
async: AsyncConfig;
/** Manual claim ("weekend plan") configuration. */
claim: ClaimConfig;
logging: {
level: "debug" | "info" | "warn" | "error";
};
}