Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
4ca0588
fix(proxy): 修复 tool_use.input 非法 JSON 序列化导致的级联故障转移失败; (#213)
ThreeFish-AI Apr 29, 2026
ea962d3
fix(usage-parser): 补充 OpenAI/Gemini SSE 流式分支的 model_served 提取; (#214)
ThreeFish-AI Apr 29, 2026
96e7263
build(version): 升级版本号 0.3.1a3 → 0.3.1a4;
ThreeFish-AI Apr 29, 2026
f497077
fix(vendor-channels): 为 tool_result 块注入 id 字段,修复 zhipu GLM-5 后端 500 错…
ThreeFish-AI Apr 29, 2026
1523286
build(version): 升级版本号 0.3.1a4 → 0.3.1a5;
ThreeFish-AI Apr 29, 2026
fdd4a92
fix(vendor-channels): 移除 zhipu 目标转换中有害步骤,修复 500 级联故障及遗留测试; (#216)
ThreeFish-AI Apr 29, 2026
ed71c02
docs(agents): 新增"In-depth and close to the facts"协作准则;
ThreeFish-AI Apr 29, 2026
d622333
build(version): 升级版本号 0.3.1a5 → 0.3.1a6;
ThreeFish-AI Apr 29, 2026
cff2dc9
build(version): 升级版本号 0.3.1a6 → 0.3.1a7;
ThreeFish-AI Apr 30, 2026
43488a1
fix(vendor-channels): 修复 zhipu tool_result 500 级联故障 (#217)
ThreeFish-AI Apr 30, 2026
2bac9a7
revert(vendor-channels): 还原至 v0.3.0 基线,修复 failover 级联 server_tool_use…
ThreeFish-AI Apr 30, 2026
d4eec1b
feat(session-policy): 新增 Session 级别路由策略与会话活动面板 (#219)
ThreeFish-AI Apr 30, 2026
9960a45
build(version): 升级版本号 0.3.1a7 → 0.3.1a8;
ThreeFish-AI Apr 30, 2026
02d3aa5
feat(dashboard): 拆分首页为 Overview / Recent Active Sessions 双页签; (#220)
ThreeFish-AI Apr 30, 2026
131a0a4
feat(session-vendor): 新增 Session 级别运行时 vendor 绑定能力 (#221)
ThreeFish-AI Apr 30, 2026
e9fc4b9
build(version): 升级版本号 0.3.1a8 → 0.3.1a9;
ThreeFish-AI Apr 30, 2026
b04dc3c
fix(dashboard): 优化 Recent Active Sessions 表格 UI,消除滚动条并新增分页 (#222)
ThreeFish-AI Apr 30, 2026
6347bec
build(version): 升级版本号 0.3.1a9 → 0.3.1a10;
ThreeFish-AI Apr 30, 2026
24e4318
fix(dashboard): 优化 Recent Active Sessions 表格列显示,消除内容截断 (#223)
ThreeFish-AI Apr 30, 2026
fcad99e
fix(dashboard): 优化 Recent Active Sessions 表格显示与交互体验 (#224)
ThreeFish-AI Apr 30, 2026
70f200e
fix(dashboard): 优化 Session 表格显示与交互体验 (#225)
ThreeFish-AI Apr 30, 2026
98b5cdb
style(dashboard): 将页签导航移至头部栏,优化为胶囊样式; (#226)
ThreeFish-AI Apr 30, 2026
5eaaba8
fix(dashboard): 重构 Session 详情卡片布局,解决内容重叠问题; (#227)
ThreeFish-AI Apr 30, 2026
b490c65
style(dashboard): 优化 Session 详情卡片布局与信息展示; (#228)
ThreeFish-AI May 1, 2026
43a35d1
fix(dashboard): 切换页签时自动刷新当前页数据; (#229)
ThreeFish-AI May 1, 2026
1f18797
fix(dashboard): 修复供应商状态卡片进度条显示异常,使用 quota-group 包裹配额元素确保折行一致性; (#230)
ThreeFish-AI May 1, 2026
18dbe16
style(dashboard): 收窄 KPI 卡片间隙至原来的 1/3; (#231)
ThreeFish-AI May 1, 2026
41c2927
fix(dashboard): 修复 Session 详情卡片内容折行问题,强制单行显示; (#232)
ThreeFish-AI May 1, 2026
9188736
chore(release): 发布 v0.4.0 版本;
ThreeFish-AI May 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,8 @@ config.yaml
.claude/.prompts.md
.python-version

# Playwright MCP
.playwright-mcp/

# Log files (dual-write logging)
coding-proxy.log*
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
1. **Python**: 严禁使用 pip/poetry,**必须**统一使用 `uv` 进行包管理与脚本执行(如 `uv run`);
2. **JavaScript/TypeScript**: 严禁使用 npm/yarn,**必须**统一使用 `pnpm` 进行包管理与脚本执行。
- **Database Management**: 谨慎操作,数据迁移、测试等操作严禁将现有数据删除,谨慎操作数据迁移的回滚,防止数据被清理。
- **In-depth and close to the facts**:系统且全面地进行问题的分析,深入贴近事实,如有疑问,需先发问,不要乱做决定。

## Documentation Standards (文档规范)

Expand Down
26 changes: 19 additions & 7 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,27 @@

## [Unreleased]

- fix(vendor-channels): 新增 zhipu 同 vendor 自清理通道,修复 GLM-5 自循环 400 + tool_results 偶发降级;
- fix(vendor-channels): 修复 `_rewrite_srvtoolu_ids` 块顺序敏感性导致 inline tool_result 漏改名,进而 enforce 阶段 dict key 与 tool_use_ids 错位、anthropic 报 `tool_use ids without tool_result blocks immediately after` 的 cascade failover 问题(改为两遍扫描:先收集 id_map,再统一改写所有 tool_result.tool_use_id 引用);
- fix(vendor-channels): `enforce_anthropic_tool_pairing` 增加全局 sanity check pass,主循环边角错位让 dangling tool_use 漏过校验时兜底合成 is_error 占位并打 `pairing_sanity_repaired` 标签,避免 anthropic 二次报错;
## [v0.4.0](https://github.com/ThreeFish-AI/coding-proxy/releases/tag/v0.4.0) — 2026-05-01

### Bug Fixes
> [!IMPORTANT]
>
> **🚀 Session 级专属路由策略!**
>
> 给每个 Session 指定专属的 vendor,动态调节不同 vendors 间的 LLM 流量。

![session](assets/session-v0.4.0.png)

### ✨ 核心亮点

- feat(session-policy): 新增 Session 级专属路由策略 (#219)
- feat(dashboard): 新增会话活动面板 (#222)

### 🔧 更多特性

- fix(vendor-channels): 新增 `anthropic → zhipu` 跨供应商转换通道,修复 Anthropic beta 功能(web search, computer use)产生的 `server_tool_use` 块导致 zhipu 400 错误的问题;
- fix(error-classifier): 增强语义拒绝检测,识别 zhipu 等供应商返回的中文错误消息(如「API 调用参数有误」code=1210),确保正确触发故障转移;
- fix(vendor-channels): `_remove_vendor_blocks` 增加空内容占位保护,防止内容块全部剥离后消息结构不合法。
- refactor(logging): 移除已被 ModelCall 汇总行覆盖的冗余 DEBUG 日志 (#203)
- style(dashboard): 加宽图表 tooltip 令模型名称与用量值单行显示 (#211)
- fix(usage-parser): 补充 OpenAI/Gemini SSE 流式分支的 model_served 提取 (#214)
- fix(usage-parser): 兼容 SSE chunk 中 usage 字段为 null 的极端格式 (#212)

## [v0.3.0](https://github.com/ThreeFish-AI/coding-proxy/releases/tag/v0.3.0) — 2026-04-20

Expand Down
Binary file added assets/session-v0.4.0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
96 changes: 0 additions & 96 deletions docs/issue.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,99 +45,3 @@ if "usage" in data: # 仅判断 key 存在

- 本仓库内 `parse_usage_from_chunk` 的 Gemini `usageMetadata` 分支 (line ~219) 已经使用 `isinstance(um, dict)` 防御, 不受影响, 可作为参考实现。
- 检查其他解析器 (如 routing / vendor adapter 层) 是否还有 `if "key" in data: v = data["key"]; v.get(...)` 这种模式, 必要时同步加固。

---

## zhipu 自循环 400 + tool_results 偶发降级

**问题描述**

生产日志反复出现下述链路: 请求一开始命中 zhipu 主 tier, 但在含 `tool_results` 的多轮工具调用场景下偶发返回 400, 触发到 copilot 二级 tier。具体日志特征:

```
WARNING Tier zhipu likely format incompatibility (400 + tool_results), trying next tier without recording failure
WARNING Tier zhipu semantic rejection (400), trying next tier without recording failure
DEBUG Applied transition channel zhipu → copilot: rewritten_38_srvtoolu_ids, stripped_16_thinking_blocks, removed_3_cache_control_fields, misplaced_tool_result_relocated
```

zhipu → copilot 通道的 adaptations 列表暴露了上一轮 zhipu 响应中存在的非标准产物 (`srvtoolu_*` ID、自签 thinking、错位的 `tool_result`)。

**表因**

zhipu 自身偶发返回 400, 但错误体非 JSON 结构, 由 `_is_likely_request_format_error()` 判定为「格式不兼容」并跳过当前 tier。

**根因**

1. zhipu 是 `NativeAnthropicVendor` 薄透传供应商, **不做任何请求体预处理**。
2. `executor._determine_source_vendor` 三条优先级路径均以 `source != target_name` 过滤掉了同 vendor 自转换。
3. `VENDOR_TRANSITIONS` 注册表中无 `("zhipu", "zhipu")` 条目。

后果: GLM-5 偶发产出非标准产物 (assistant 内联 `tool_result`、`server_tool_use_delta` 流式残块) 后, Claude Code 把这些产物原样回送下一轮请求时, **没有任何清洗发生**, 直接被转发到 zhipu 自身, 命中 zhipu 端的输入校验返回 400。

**处理方式**

- 在 `vendor_channels.py` 新增 `prepare_zhipu_self_cleanup` 函数, 仅修复 zhipu 自身拒绝的两类产物:
1. 剥离 `server_tool_use_delta` 流式残块
2. `enforce_anthropic_tool_pairing` 把 assistant 内联 `tool_result` 重定位到紧随 user 消息
- 显式 **保留** zhipu 原生支持的特性: `srvtoolu_*` ID、`server_tool_use` 类型、自签 thinking signature、`cache_control` (cache_read 已在生产实证)、顶层 `thinking` 参数。
- 在 `VENDOR_TRANSITIONS` 注册 `("zhipu", "zhipu") = prepare_zhipu_self_cleanup`。
- 在 `executor._determine_source_vendor` 三条优先级路径中, 把「`source != target`」过滤替换为「通道已注册」门控 (`get_transition_channel(...) is not None`), 让自转换通道在显式注册时启用, 未注册时退化为原行为。

**后续防范**

- 新增 `NativeAnthropicVendor` 子类 (minimax / kimi / doubao / xiaomi / alibaba 等) 时, 若上游 vendor 偶发产出违反 Anthropic 规范的产物, 可按需注册同名自清理通道, executor 无需任何额外改动。
- 同 vendor 自转换通道应**精确剪裁**: 仅修复 vendor 自身拒绝的产物, 不要套用跨 vendor 通道的全量清理 (会误伤 vendor 原生支持的特性, 如 cache_control 损失带来 cache_read miss)。

**同类问题影响与处理注意事项**

- `enforce_anthropic_tool_pairing` 仅识别 `tool_use` 类型 (不含 `server_tool_use`), 因为 `server_tool_use` 由 vendor 自身执行, 不需要客户端 `tool_result`。构造测试或类似清洗逻辑时需注意此差别。
- `_is_likely_request_format_error()` 把「400 + tool_results + 非结构化错误体」一律标记为格式不兼容并跳过 tier 不计熔断器, 这层兜底虽能维持可用性但会**掩盖** vendor 自身的间歇性问题, 让根因更难发现。处理类似 400 偶发时, 应优先看 `Applied transition channel` 日志中的 adaptations 列表, 它能精确暴露上游响应中的非标准产物。

---

## anthropic 报 messages.X tool_use 缺 tool_result (zhipu→anthropic 故障转移失败)

**问题描述**

zhipu 完成响应后, executor 故障转移至 anthropic 时反复失败 (HTTP 400):

```
DEBUG Applied transition channel zhipu → anthropic: rewritten_86_srvtoolu_ids, misplaced_tool_result_relocated, stripped_18_thinking_blocks
WARNING anthropic stream error: status=400 ... messages.3: `tool_use` ids were found without `tool_result` blocks immediately after: toolu_normalized_3.
INFO Failover: anthropic → zhipu (reason: HTTP 400)
```

adaptations 列表显示 `misplaced_tool_result_relocated` 但**没有** `orphaned_tool_use_repaired`, 即 enforce 单遍扫描视角下认为所有 tool_use 都已配对; 但 anthropic 仍报 messages.X 缺 tool_result, 导致请求级 cascade failover 反复回到 zhipu。

**表因**

`prepare_zhipu_to_anthropic` 链路输出的请求体中, 某个 assistant 的 `tool_use` 在紧邻的 user 消息中没有匹配的 `tool_result` 块。

**根因**

`_rewrite_srvtoolu_ids` 采用单遍正向扫描: 在同一次循环中一边收集 srvtoolu_* → toolu_normalized_* 的 id_map, 一边改写遇到的 `tool_result.tool_use_id`。GLM-5 流式偶发将 inline tool_result 输出在本消息 `server_tool_use` 之前 (block 顺序异常), 导致:

1. 处理 inline tool_result 时, id_map 尚未填入对应 srvtoolu_* → 漏改名, inline 仍保留 `srvtoolu_X`
2. 处理本消息 server_tool_use 时, 填入 id_map 并把 tool_use 改名为 `toolu_normalized_X`
3. 进入 `enforce_anthropic_tool_pairing` 时:
- A 步 extracted dict key = `srvtoolu_X` (inline 保留的旧 ID)
- B 步 tool_use_ids = `[toolu_normalized_X]` (已改名)
- F 步 `uid in extracted` 检查失败 (key 错位), 但若 next user 已含其他 stale tool_result 让 existing_result_ids "巧合" 命中, F 步会跳过 synth → 不触发 orphan 标签
- 最终 anthropic 看到 messages.X 真的缺 toolu_normalized_X 的 tool_result → 400

**处理方式**

- `_rewrite_srvtoolu_ids` 改为**两遍扫描**: Pass 1 仅遍历 assistant 消息, 收集 id_map 并改写 tool_use 自身的 id 与 type; Pass 2 全量遍历所有消息 (含 user / 异常 assistant 内联), 统一改写所有 `tool_result.tool_use_id` 引用。彻底消除 block 顺序敏感性。
- `enforce_anthropic_tool_pairing` 主循环结束后追加**全局 sanity check pass**: 重新遍历每条 assistant, 验证其 tool_use_ids 全部在 next user 的 tool_result 中存在; 发现遗漏直接合成 is_error 占位并打 `pairing_sanity_repaired` 标签。作为防御深度抵御未来其他主循环边角错位。
- A 步对 `tool_use_id` 缺失的破损 inline tool_result 也计入 relocated_count (避免 silent drop 影响 adaptations 标签可观测性)。

**后续防范**

- 任何"按出现顺序填充字典 + 同遍引用查询"的两阶段操作都应警惕**顺序耦合**问题。两遍扫描 (collect → apply) 是消除此类 bug 的标准 pattern。
- 关键校验函数应有**主循环 + 全局 sanity check** 的双层结构, 单层校验在边角场景下容易被绕过。
- 处理 anthropic `tool_use ids without tool_result blocks immediately after` 类 cascade failover 时, **adaptations 标签能否复现日志**是定位 root cause 的强信号: 若 enforce 视角与 anthropic 视角不一致 (有 misplaced 但无 orphan, anthropic 仍报错), 必有上游 _rewrite / id 改写阶段的隐藏漏洞。

**同类问题影响与处理注意事项**

- 任何对 messages 进行 ID 重写的转换链 (如 `_rewrite_srvtoolu_ids`、`anthropic_to_openai`、`anthropic_to_gemini`) 都应使用两遍扫描或一次性收集后再批量改写, 以保证 block 顺序无关性。
- enforce 类校验函数若依赖 dict key 与 list 元素的**等同性**, 必须先确保两者在同一参考系下 (改名前 vs 改名后); 否则错位会以 "看起来 OK 实际有漏" 的方式静默泄漏到下游。
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "coding-proxy"
version = "0.3.1a3"
version = "0.4.0"
description = "A High-Availability, Transparent, and Smart Multi-Vendor Proxy for Claude Code. Support Claude Plans, GitHub Copilot, Google Antigravity, ZAI/GLM, MiniMax, Qwen, Xiaomi, Kimi, Doubao..."
readme = "README.md"
requires-python = ">=3.12"
Expand Down
95 changes: 95 additions & 0 deletions src/coding/proxy/cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@
# 注册 Auth 子应用
app.add_typer(auth_app, name="auth")

# 注册 Session 子应用
session_app = typer.Typer(name="session", help="管理 Session-Vendor 运行时绑定")
app.add_typer(session_app, name="session")


def _build_token_store(cfg_path: Path | None = None):
"""按配置解析 Token Store 路径并完成加载."""
Expand Down Expand Up @@ -264,6 +268,97 @@ def reset(
console.print("[red]代理服务未运行[/red]")


# ── Session 子命令 ───────────────────────────────────────────────


@session_app.command("bind")
def session_bind(
key: str = typer.Option(..., "--key", "-k", help="Session key"),
vendor: str = typer.Option(
..., "--vendor", "-v", help="绑定 vendor(逗号分隔多个)"
),
port: int = typer.Option(3392, "--port", "-p", help="代理服务端口"),
) -> None:
"""为指定 Session 绑定 vendor 优先级."""
import httpx as _httpx

vendors = [v.strip() for v in vendor.split(",") if v.strip()]
try:
resp = _httpx.put(
f"http://127.0.0.1:{port}/api/session-vendor",
json={"session_key": key, "vendors": vendors},
timeout=5,
)
if resp.status_code == 200:
data = resp.json()
console.print(
f"[green]绑定成功:[/] session [cyan]{key[:16]}…[/cyan] → "
+ " → ".join(data.get("vendors", vendors))
)
else:
try:
err = resp.json()
msg = err.get("error", {}).get("message", resp.text)
except Exception:
msg = resp.text
console.print(f"[red]绑定失败: {msg}[/red]")
except _httpx.ConnectError:
console.print("[red]代理服务未运行[/red]")


@session_app.command("unbind")
def session_unbind(
key: str = typer.Option(..., "--key", "-k", help="Session key"),
port: int = typer.Option(3392, "--port", "-p", help="代理服务端口"),
) -> None:
"""解除指定 Session 的 vendor 绑定."""
from urllib.parse import quote

import httpx as _httpx

try:
resp = _httpx.delete(
f"http://127.0.0.1:{port}/api/session-vendor/{quote(key, safe='')}",
timeout=5,
)
if resp.status_code == 200:
console.print(f"[green]已解除绑定:[/] session [cyan]{key[:16]}…[/cyan]")
elif resp.status_code == 404:
console.print(f"[yellow]未找到绑定:[/] session [cyan]{key[:16]}…[/cyan]")
else:
console.print(f"[red]解除失败: {resp.status_code} {resp.text}[/red]")
except _httpx.ConnectError:
console.print("[red]代理服务未运行[/red]")


@session_app.command("list")
def session_list(
port: int = typer.Option(3392, "--port", "-p", help="代理服务端口"),
) -> None:
"""列出所有运行时 Session-Vendor 绑定."""
import httpx as _httpx

try:
resp = _httpx.get(
f"http://127.0.0.1:{port}/api/session-vendor",
timeout=5,
)
if resp.status_code == 200:
data = resp.json()
bindings = data.get("bindings", [])
if not bindings:
console.print("[dim]当前无运行时绑定[/dim]")
return
for b in bindings:
key = b.get("session_key", "?")
vendors = b.get("vendors", [])
console.print(f" [cyan]{key[:24]}…[/cyan] → " + " → ".join(vendors))
else:
console.print(f"[red]查询失败: {resp.status_code} {resp.text}[/red]")
except _httpx.ConnectError:
console.print("[red]代理服务未运行[/red]")


def _resolve_config_path(config: str | Path | None = None) -> Path | None:
"""标准化配置路径输入."""
if config is None:
Expand Down
28 changes: 28 additions & 0 deletions src/coding/proxy/config/config.default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -644,3 +644,31 @@ native_api:
base_url: "https://api.anthropic.com"
timeout_ms: 300000
connect_timeout_ms: 15000

# === Session 级别路由策略(可选)===
#
# 为特定 Session 或客户端类别定制 vendor 优先级顺序。
# 匹配策略按定义顺序求值,首次匹配生效。
#
# 支持的匹配条件(OR 语义,满足任一即匹配):
# session_keys: 精确匹配的 session key 列表
# client_category: 按客户端类别匹配(⚠️ 预留字段,当前版本暂未生效,后续版本支持)
#
# tiers: 覆盖全局 tier 顺序的供应商优先级列表(未提及的 vendor 保持在末尾)
#
# 示例 1:为特定 session 绑定专属 vendor 组合
# session_policies:
# - name: "vip-session"
# match:
# session_keys: ["my-specific-session-id"]
# tiers: ["anthropic", "copilot", "zhipu"]
#
# 示例 2:Claude Code 请求优先走 Copilot
# session_policies:
# - name: "claude-code-preferred"
# match:
# client_category: "cc"
# tiers: ["copilot", "anthropic", "zhipu"]
#
# 未配置时(默认),所有 Session 使用全局 tiers 顺序。
session_policies: []
19 changes: 18 additions & 1 deletion src/coding/proxy/config/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@

# ── 子模块 re-export ────────────────────────────────────────────
from .server import DatabaseConfig, LoggingConfig, ServerConfig # noqa: F401
from .session_policy import SessionPoliciesConfig # noqa: F401
from .vendors import ( # noqa: F401
AlibabaConfig,
AnthropicConfig,
Expand Down Expand Up @@ -152,11 +153,19 @@ class ProxyConfig(BaseModel):
"三个 provider 默认 enabled=False,显式启用才暴露 /api/{provider}/* 端点。"
),
)
# Session 级别路由策略
session_policies: SessionPoliciesConfig = Field(
default_factory=SessionPoliciesConfig,
description=(
"Session 级别的路由策略配置。"
"可为特定 Session 或客户端类别定制 vendor 优先级顺序。"
),
)

@model_validator(mode="before")
@classmethod
def _migrate_legacy_fields(cls, data: Any) -> Any:
"""向后兼容迁移(legacy flat 格式 → vendors 列表格式).
"""向后兼容迁移(legacy flat 格式 → vendors 列表格式)+ session_policies 规范化.

迁移规则:
1. ``anthropic`` / ``zhipu`` 字段名自动映射为 ``primary`` / ``fallback``
Expand All @@ -165,6 +174,12 @@ def _migrate_legacy_fields(cls, data: Any) -> Any:
if not isinstance(data, dict):
return data

# session_policies 规范化:YAML 中 session_policies: [] 解析为 list,
# 需转为 dict 包装以匹配 SessionPoliciesConfig 模型
sp = data.get("session_policies")
if isinstance(sp, list):
data["session_policies"] = {"policies": sp}

# 1. 字段别名迁移
if "anthropic" in data and "primary" not in data:
data["primary"] = data.pop("anthropic")
Expand Down Expand Up @@ -331,4 +346,6 @@ def compat_state_path(self) -> Path:
"AlibabaConfig",
# native api passthrough
"NativeApiConfig",
# session policy
"SessionPoliciesConfig",
]
Loading
Loading