dsh-agora 0.2.3 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,96 +1,65 @@
1
1
  # dsh-agora
2
2
 
3
- DSH (DeepSeek Harness) skill plugin: a **thin shell** that ships the Agora
4
- skill — RTC, RTM, ConvoAI, CLI, Cloud Recording, Server, Server Gateway,
5
- tokens — synced **verbatim** from
6
- [`AgoraIO/skills`](https://github.com/AgoraIO/skills) at a pinned release tag.
3
+ **A DeepSeek Harness (DSH) plugin that adds the official Agora skill plus a China-mainland (国内/声网) companion skill to your agent.** One install gives you voice AI agents, RTC video/voice calls, RTM chat & signaling, Cloud Recording, Agora CLI acceleration, and server-side token generation — driven from natural language.
7
4
 
8
- The plugin registers one bundled skill, `agora`, into DSH's skill registry
9
- the same name and content as the Claude Code / Cursor ecosystems.
5
+ The skill is synced verbatim from the official [AgoraIO/skills](https://github.com/AgoraIO/skills) repository, so it always matches the Agora docs and quickstarts.
10
6
 
11
- ## Install
12
-
13
- ```sh
14
- dsh plugin --profile web add dsh-agora
15
- ```
7
+ ## Prerequisites
16
8
 
17
- Then restart the web profile. The `agora` skill appears in the skill catalog.
9
+ - DeepSeek Harness (DSH) installed and running
10
+ - An [Agora](https://console.agora.io) account (for tokens/App ID when you build a real app)
18
11
 
19
- From a local checkout (development):
12
+ ## Install
20
13
 
21
14
  ```sh
22
- dsh plugin --profile web add /path/to/dsh-agora
15
+ dsh plugin --profile web add dsh-agora
23
16
  ```
24
17
 
25
- > **pnpm workspace-root gotcha**: with pnpm ≥ 8.15 the profile's workspace
26
- > root rejects a bare `add` (`ERR_PNPM_ADDING_TO_ROOT`). The clean fix is to
27
- > disable the check once per profile so plain `dsh plugin add` just works:
18
+ > **Note**: with pnpm ≥ 8.15 (e.g. 9.15) the profile workspace root rejects a
19
+ > bare `add` with `ERR_PNPM_ADDING_TO_ROOT`. If you hit that, pass `-w`:
28
20
  >
29
21
  > ```sh
30
- > echo "ignore-workspace-root-check=true" > ~/.dsh/profiles/web/.npmrc
31
- > dsh plugin --profile web add dsh-agora
22
+ > dsh plugin --profile web add -w dsh-agora
32
23
  > ```
33
- >
34
- > (Alternative: add `-w` to the command: `dsh plugin --profile web add -w dsh-agora`.
35
- > The root cause is dsh's `plugin` subcommand forwarding verbatim to pnpm with
36
- > no package-manager switch — worth an upstream issue if it bites more users.)
37
- >
38
- > **link: dev mode**: the profile must resolve the runtime peer
39
- > `@deepseek-ai/dsh-skill`. Install it in the repo checkout first
40
- > (`pnpm install`); otherwise `index.js` fails with
41
- > `ERR_MODULE_NOT_FOUND` at load time (decision D-09).
42
-
43
- ## What it contains
44
24
 
45
- ```
46
- dsh-agora/
47
- ├── package.json # dsh.bundle.patch declaration (bundle form)
48
- ├── cordis.patch.yml # inserts the provider row into the profile tree
49
- ├── index.js # Cordis entry: registers the bundled agora provider
50
- ├── scripts/sync-deps.sh # ★ the only automation: tag-sync from AgoraIO/skills
51
- └── assets/agora/ # synced output (gitignored, not committed)
52
- ├── SKILL.md # upstream verbatim, zero rewrite
53
- └── references/ # full reference set (54 files)
54
- ```
25
+ Restart the web profile, and the `agora` skill appears in the skill catalog, alongside the `agora-cn` companion.
55
26
 
56
- ## How content stays in sync
27
+ ## What the skill covers
57
28
 
58
- `npm publish` runs `prepack` `scripts/sync-deps.sh`, which:
29
+ | Area | What you can do |
30
+ |---|---|
31
+ | **Voice AI agents** (ConvoAI) | Build voice agents / voicebots |
32
+ | **RTC** | Video & voice calls, live streaming, screen sharing |
33
+ | **RTM** | Chat, presence, signaling |
34
+ | **Cloud Recording** | Record calls and streams |
35
+ | **Server** | Generate tokens & App IDs server-side |
36
+ | **Server Gateway** | Cross-product server coordination |
37
+ | **Agora CLI** | CLI acceleration (auto-detected if installed) |
59
38
 
60
- 1. resolves the release tag (`$TAG` env → GitHub latest release → pinned
61
- fallback `v1.8.1`),
62
- 2. pulls the `AgoraIO/skills` tarball for that tag,
63
- 3. `rsync -a --delete`s `skills/agora/` → `assets/agora/` — **zero rewrite**,
64
- so the two copies can never drift.
39
+ ## China-mainland (国内/声网) support
65
40
 
66
- The repo keeps no permanent copy of the skill content; `assets/` is
67
- gitignored and rebuilt at release time. Run it manually with
68
- `npm run sync:deps`.
41
+ The plugin also ships a companion skill, **`agora-cn`**, that documents only the delta between the global (overseas) path and the China-mainland (国内 / 声网 / `console.shengwang.cn`) path — per product:
69
42
 
70
- ## Skill: `agora`
43
+ | Product | CN delta |
44
+ |---|---|
45
+ | RTC | CN region (`setArea({ areaCode: "CHINA" })` / `AREA_CODE_CN`) + `sd-rtn.com` + cloud proxy |
46
+ | RTM | CN region (`setArea({ areaCodes: ["CHINA"] })` / `RtmAreaCode.CN`) + CN data center |
47
+ | Cloud Recording | `api.sd-rtn.com` + `clientRequest.region="CN"` + mainland storage |
48
+ | Server (token) | token algorithm unchanged; CN REST domain + credential menu path |
49
+ | Agora CLI | `agora login --region cn` / `--rtm-data-center CN` |
50
+ | ConvoAI | endpoint (`Area.CN`) + CN vendor catalog + managed/BYOK — **recorded as current status; end-to-end not yet verified** |
71
51
 
72
- Upstream routing: RTC (video/voice calls), RTM (chat/signaling), ConvoAI
73
- (voice AI agents), Agora CLI, Cloud Recording, Server (tokens), Server
74
- Gateway, and cross-product coordination. ConvoAI follows the upstream
75
- "proven baseline first" rule (run the official quickstart before scaffolding
76
- from memory); CLI acceleration is runtime-detected (`agora` on `PATH`), never
77
- bundled.
52
+ `agora-cn` supplements `agora` without rewriting it: the official skill stays verbatim, and `agora-cn` only adds the China-region differences. For a domestic (国内/声网) deployment, load `agora-cn`; otherwise use `agora`.
78
53
 
79
- Design rules and decisions (D-01…D-10) and the ROADMAP are kept local-only
80
- under `docs/` — not committed to this public repo.
54
+ ## Using the skill
81
55
 
82
- ## Verify locally
56
+ Describe what you want in natural language — e.g. *"set up a voice AI agent with Agora"* or *"build an RTC video call app"*. The skill routes to the official quickstarts and guides you through setup, including auth and token flows.
83
57
 
84
- ```sh
85
- dsh --profile web --dump-config --patch ./cordis.patch.yml # row composes
86
- ```
58
+ ## FAQ
87
59
 
88
- For a real mount test, install into a throwaway profile:
60
+ **Does this repo contain the skill itself?** The official `agora` skill is synced verbatim from the AgoraIO/skills repo at each release (not committed); the `agora-cn` companion is maintained in this repo under `assets/agora-cn/`.
89
61
 
90
- ```sh
91
- dsh plugin --profile agoratest add .
92
- dsh --profile agoratest --dump-config | grep agora-skills
93
- ```
62
+ **Do I need the Agora CLI installed?** No. It's optional; if it's on your `PATH`, the skill uses it for faster workflows.
94
63
 
95
64
  ## License
96
65
 
@@ -0,0 +1,58 @@
1
+ ---
2
+ name: agora-cn
3
+ description: >-
4
+ Activate for China-mainland (国内/声网) Agora deployment: console.shengwang.cn
5
+ control plane, CN endpoints on the sd-rtn.com domain, `agora login --region
6
+ cn` + CN data center, ConvoAI (Area.CN → api-cn-*.sd-rtn.com/cn + CN vendor/
7
+ BYOK), and CN region selection for RTC (setArea CHINA / AREA_CODE_CN), RTM
8
+ (setArea areaCodes / RtmAreaCode.CN), and Cloud Recording (clientRequest.
9
+ region). Use when the user wants domestic deployment, 声网, China region (CN),
10
+ or mainland data residency. Supplements the `agora` skill.
11
+ metadata:
12
+ author: agora
13
+ version: '0.1.0'
14
+ ---
15
+
16
+ # Agora 国内区域(声网 / CN Region)
17
+
18
+ > 本 skill 是 `agora` 的**国内补充**:只覆盖"大陆 / 声网 / CN 区域"与海外版的差异。
19
+ > 基础机制(quickstart、token flow、生命周期)仍以 `agora` skill 为准。
20
+ > 验证基线:CLI `0.2.8`(本机 `introspect --json` 实测)+ 声网/海外官方文档对照(各产品 SDK 版本见各 reference)。
21
+
22
+ ## 何时用本 skill
23
+
24
+ 用户目标是**国内/大陆部署**、`声网`、`console.shengwang.cn`、`CN 区域`、或国内数据合规时使用。
25
+ 否则仍走 `agora`。
26
+
27
+ ## 国内 vs 海外:四件套差异
28
+
29
+ 1. **账号**:国内控制台是 `console.shengwang.cn`(声网),且需在控制台**开通对应服务**(海外没有这个独立步骤)。
30
+ 2. **CLI**:`agora login --region cn`;`agora init --rtm-data-center CN`。
31
+ 3. **端点**:各产品 CN 端点以 `sd-rtn.com` 为主域名(详见各产品 reference)。
32
+ 4. **vendor**:ConvoAI 需换 CN vendor 目录,并按 managed/BYOK 矩阵填 key(详见 `conversational-ai.md`)。
33
+
34
+ ## Routing(按产品,与 `agora` 同构)
35
+
36
+ | 产品 | 国内 delta | 读这里 |
37
+ |---|---|---|
38
+ | **RTC** | area code / CN 域名 / 云代理 | [references/rtc.md](references/rtc.md) ✅ |
39
+ | **RTM** | region / 数据中心 | [references/rtm.md](references/rtm.md) ✅ |
40
+ | **Cloud Recording** | CN 端点 / `clientRequest.region` / 存储 | [references/cloud-recording.md](references/cloud-recording.md) ✅ |
41
+ | **Server(token)** | token 不变 / CN 域名 / 菜单路径 | [references/server.md](references/server.md) ✅ |
42
+ | **CLI** | 国内命令 / 版本要求 | [references/cli.md](references/cli.md) ✅ |
43
+ | **ConvoAI** | 端点 + CN vendor + managed/BYOK | [references/conversational-ai.md](references/conversational-ai.md) 📋 现状已记录(端到端待验证) |
44
+
45
+ ## 状态标注(诚实边界)
46
+
47
+ | 状态 | 内容 |
48
+ |---|---|
49
+ | ✅ 已确认(源码/文档级) | RTC/RTM/Cloud Recording/Server/CLI 国内 delta 已填实(各文件内仍有"待验证"小节) |
50
+ | 📋 ConvoAI 现状 | 端点 + CN vendor + managed/BYOK 已源码确认;但**免-key 直接启动体验未端到端验证**,不承诺与海外一致 |
51
+ | ⚠️ 待运行时验证 | 原生 RTC/RTM 精确信令 host、`clientRequest.region` 是否需显式传、迁移期 `api.agora.io` 可用性、ConvoAI 免-key 组合等(见各文件"待验证") |
52
+
53
+ ## Guardrails
54
+
55
+ 1. **本 skill 只补差异**;quickstart 克隆 / 生命周期 / token / baseline-first 约束沿用 `agora` skill。
56
+ 2. **区域取值别混用**:Web SDK 用 `"CHINA"`、原生 SDK 用 `CN`(RTC/RTM 一致);RTM Web 是复数 `areaCodes`、RTC Web 是单数 `areaCode`。
57
+ 3. **ConvoAI 别断言"改一行 `Area` 就国内跑通"**:`Area.CN` 只解决端点路由,vendor 仍需换 CN 类并处理 key;国内免-key 体验未验证。
58
+ 4. 未在本 skill 标注为"已确认"的能力,不要凭记忆承诺;必要时回落到声网官方文档(`doc.shengwang.cn`)现查。
@@ -0,0 +1,41 @@
1
+ ---
2
+ name: agora-cn-cli
3
+ description: |
4
+ China-mainland Agora CLI commands: login/console region, CN RTM data center,
5
+ webhook delivery region, and the version requirement for CN flags. Use for
6
+ 国内 CLI, agora login --region cn, or --rtm-data-center CN.
7
+ license: MIT
8
+ metadata:
9
+ author: agora
10
+ version: '0.1.0'
11
+ ---
12
+
13
+ # 国内 CLI 命令与版本
14
+
15
+ 验证基线:CLI `0.2.8`(`agora introspect --json` 实测)。
16
+
17
+ > 注意版本漂移:`agora` skill 内容基线是 CLI `0.2.1`,其中 `agora project create --region global|cn`
18
+ > 在 `0.2.8` 已**不存在**——国内 flag 已经搬家到 login / data-center。
19
+
20
+ ## 国内命令面(0.2.8 实测)
21
+
22
+ - 登录国内控制台:`agora login --region cn`(等价 `agora auth login --region cn`;默认 `global`)
23
+ - RTM 数据中心:`agora project create ... --rtm-data-center CN`(可选 `CN|NA|EU|AP`,默认 `NA`)
24
+ - 一键脚手架:`agora init <name> --template <t> --rtm-data-center CN`
25
+ - Webhook 投递区域:`agora project webhook create ... --delivery-region cn`(可选 `cn|sea|na|eu`)
26
+
27
+ ## 版本要求
28
+
29
+ - CN 入口(`login --region cn`、`--rtm-data-center CN`)比 `agora` skill 的验证基线 `0.2.1` 新。
30
+ - **确切引入版本待钉**:本机 `0.2.8` 已实测具备这两个 flag;低于该版本的 CLI 没有它们。
31
+ - 落地建议:国内路径要求 CLI 至少为实测具备 CN flag 的版本(当前以 `0.2.8` 为参照下界)。
32
+
33
+ ## 端点相关环境变量(`agora env-help --json` 实测)
34
+
35
+ - `AGORA_CONSOLE_URL` — 覆盖 `agora open --target console` 的 URL
36
+ - `AGORA_API_BASE_URL`(默认 `https://agora-cli.agora.io`)
37
+ - `AGORA_OAUTH_BASE_URL`(默认 `https://sso2.agora.io`)
38
+
39
+ ## 待验证
40
+
41
+ - `agora login --region cn` 的 OAuth 流程端到端(需声网账号实测)。
@@ -0,0 +1,59 @@
1
+ ---
2
+ name: agora-cn-cloud-recording
3
+ description: |
4
+ China-mainland (国内/声网) Cloud Recording delta: 声网 console + enable-service,
5
+ the (now-unified) api.sd-rtn.com base URL, clientRequest.region="CN", and CN
6
+ storage regions. Use for 国内录制, cloud recording CN, clientRequest.region, 录制存储.
7
+ license: MIT
8
+ metadata:
9
+ author: agora
10
+ version: '0.1.0'
11
+ ---
12
+
13
+ # 国内 Cloud Recording:控制台 / 端点 / 存储
14
+
15
+ 验证基线:声网 `doc.shengwang.cn` 与海外 `docs.agora.io` 对照。
16
+
17
+ ## 已确认的国内 delta
18
+
19
+ ### 1. 控制台 / 账号 / 开通
20
+
21
+ - 国内控制台 `console.shengwang.cn`(声网)。App ID / App 证书 / 客户 ID·密钥 / 开通服务都在声网控制台完成。
22
+ - 需先**开通云端录制服务**(项目类型选**通用项目**)。
23
+
24
+ ### 2. 端点:`api.sd-rtn.com`(关键修正:云端录制已基本统一,非 CN 独有)
25
+
26
+ - 国内 quick-start 全程 `https://api.sd-rtn.com/v1/apps/{appid}/cloud_recording/...`(acquire/start/stop 一致)。
27
+ - **海外 canonical 参考也写 base URL `https://api.sd-rtn.com`**——即云端录制当前 base URL 在两套文档里**已统一为 `api.sd-rtn.com`**。
28
+ `api.agora.io` 只残留在海外 quickstart/认证示例里,属陈旧内容。
29
+ - 路径与海外**完全一致,且无 `/cn/` 前缀**。
30
+
31
+ ### 3. CN 区域绑定:`clientRequest.region = "CN"`
32
+
33
+ - acquire 请求体有 `clientRequest.region`(string):`"CN"`(中国大陆)/ `"AP"` / `"EU"` / `"NA"`。
34
+ - 默认「使用发起请求所在服务器的区域」;一旦显式设置,服务不访问该区域之外。
35
+ - **约束**:`start` 时第三方云存储的 `region` 必须与之匹配。
36
+
37
+ ## 与海外一致(无 delta)
38
+
39
+ - **操作路径**:acquire / start / query / update / updateLayout / stop 六个操作 path 完全一致。
40
+ - **存储 vendor 枚举**:`1`=Amazon S3、`2`=阿里云 OSS、`3`=腾讯云 COS、`5`=Azure、`6`=GCP、`7`=华为云 OBS、`8`=百度云 BOS、`11`=其他 S3(需 `extensionParams.endpoint`);无 vendor 4。
41
+ - **存储 region(大陆可用,两边都有)**:阿里云 `CN_*`(杭州/上海/北京/广州/成都…)、腾讯云 `AP_Beijing/AP_Shanghai/AP_Guangzhou/…`、AWS `CN_NORTH_1`/`CN_NORTHWEST_1`、华为云 `CN_*`、百度云(保定/苏州/广州)。
42
+ - **鉴权机制**:HTTP Basic Auth `Authorization: Basic base64(CustomerID:CustomerSecret)` 完全一致;仅 Customer ID/Secret 的生成控制台不同(声网:设置 → RESTful API)。
43
+ - **录制模式/特性**:`individual`/`mix`/`web`、`streamMode`、`transcodingConfig`、订阅黑白名单、NCS webhook、云端截图、格式转换——均一致。
44
+ - **storageConfig 字段集**:bucket/accessKey/secretKey/fileNamePrefix + `stsToken`/`stsExpiration`(S3/Aliyun/Tencent)一致。
45
+
46
+ ## 待验证 / 未知
47
+
48
+ 1. `clientRequest.region` 字段在**声网(CN)文档**里是否逐字一致未直接取到(CN operation 页 doc-mcp 返回"获取文档内容失败";字段已从海外 canonical acquire 参考确认,但 CN 侧逐字出处缺失)。
49
+ 2. 阿里云 region 编号 26/27 命名在 CN 与海外文档不一致(一方疑似笔误,未判定哪方正确)。
50
+ 3. 迁移期 `api.agora.io` 是否仍实际可用(海外 canonical 已统一为 `api.sd-rtn.com`)。
51
+ 4. 是否需要显式传 `clientRequest.region="CN"`(默认按发起服务器区域;声网账号默认是否已落 CN 未实测)。硬性大陆数据驻留时建议显式 `"CN"` 并匹配存储 region,但未经运行时验证。
52
+
53
+ ## 来源
54
+
55
+ - 声网云端录制快速开始:https://doc.shengwang.cn/doc/cloud-recording/restful/get-started/quick-start
56
+ - 声网开通服务:https://doc.shengwang.cn/doc/cloud-recording/restful/get-started/enable-service
57
+ - 海外 canonical:https://docs.agora.io/en/realtime-media/cloud-recording/reference/restful-api.md
58
+ - acquire `clientRequest.region`:https://docs.agora.io/en/api-reference/api-ref/cloud-recording/acquire.md
59
+ - region/vendor 对照:https://docs.agora.io/en/realtime-media/cloud-recording/reference/region-vendor.md
@@ -0,0 +1,110 @@
1
+ ---
2
+ name: agora-cn-conversational-ai
3
+ description: |
4
+ China-mainland (国内/声网) Conversational AI delta: console.shengwang.cn + service
5
+ enablement, CN REST endpoint routing (Area.CN), and the CN vendor catalog with its
6
+ managed-vs-BYOK credential matrix. Use for 国内 voice agent, 声网 ConvoAI, Area.CN,
7
+ or CN vendor/BYOK questions.
8
+ license: MIT
9
+ metadata:
10
+ author: agora
11
+ version: '0.1.0'
12
+ ---
13
+
14
+ # 国内 ConvoAI:现状 + 端点 / vendor
15
+
16
+ > **现状说明(先读)**:国内 ConvoAI 的**端点路由 + CN vendor 清单 + managed/BYOK 矩阵已从 SDK 源码确认**
17
+ > (下面这些是可信事实);但"像海外那样只填 App ID / App Certificate 就一键启动"的体验
18
+ > **尚未端到端跑通**——国内 LLM/TTS 的免-key(托管)面更窄,且整条链路未经运行时验证。
19
+ > 因此本文是**现状记录**,不是"照着就能跑通"的承诺;动手前按"待验证"清单实测。
20
+
21
+ 验证基线:SDK `agora-agents` 2.6.0(TypeScript 与 Python 一致)。
22
+
23
+ ## 账号与控制台
24
+
25
+ - 国内控制台:`https://console.shengwang.cn`(声网);ConvoAI 入口
26
+ `https://console.shengwang.cn/product/ConversationAI?tab=Playground`。
27
+ - **开通服务(enable-service)**:国内需先在声网控制台开通 ConvoAI 服务(海外没有这个独立步骤)。
28
+ - 海外控制台是 `console.agora.io`;两者账号/项目体系不同,国内用声网账号。
29
+
30
+ ## CN 端点(Area.CN)
31
+
32
+ `Area` 枚举(`agora-agents` 2.6.0):
33
+
34
+ ```text
35
+ US = 1, EU = 2, AP = 3, CN = 4 # CN = "eastern and northern regions of Chinese mainland"
36
+ ```
37
+
38
+ `Area.CN` 时 SDK 自动路由(DNS 解析选择):
39
+
40
+ - 区域前缀:`api-cn-east-1`、`api-cn-north-1`
41
+ - 主域名:`sd-rtn.com`(回退 `agora.io`)
42
+ - 路径:`/cn/api/conversational-ai-agent`(海外是 `/api/conversational-ai-agent`)
43
+
44
+ 即完整端点形如:
45
+
46
+ ```text
47
+ https://api-cn-east-1.sd-rtn.com/cn/api/conversational-ai-agent/v2/projects/{appid}/join
48
+ https://api-cn-north-1.sd-rtn.com/cn/api/conversational-ai-agent/v2/projects/{appid}/join
49
+ ```
50
+
51
+ > 说明:声网文档示例里也出现过 `https://api.agora.io/cn/api/conversational-ai-agent/v2/projects/...`
52
+ > 这种写法(`api.agora.io` + `/cn/` 路径)。以 SDK 2.6.0 的实际运行时为准:设置 `Area.CN` 后
53
+ > 走 `api-cn-*.sd-rtn.com` + `/cn/` 路径。
54
+
55
+ ## 区域绑定方式
56
+
57
+ - 客户端:`AgoraClient({ area: Area.CN, ... })`(TS)/ `AsyncAgora(area=Area.CN, ...)`(Python)。
58
+ - SDK 提供 CN 专属类:`CNAgora` / `CNAsyncAgora`(Python,预绑定 `Area.CN`)。
59
+ - `Agent(client=...)` 在 `area_scope == "cn"` 时返回 `CNAgent`。
60
+
61
+ ## CN vendor 目录(`agentkit/vendors/cn.py`)
62
+
63
+ `area_scope == "cn"` 时切换到 CN vendor 命名空间,可选厂商与海外不同:
64
+
65
+ | 类别 | CN 可选厂商 |
66
+ |---|---|
67
+ | ASR | fengming, tencent, microsoft, xfyun, xfyun_bigmodel, xfyun_dialect |
68
+ | TTS | minimax, tencent, bytedance, microsoft, cosyvoice, bytedance_duplex, stepfun, generic |
69
+ | LLM | aliyun, bytedance, deepseek, tencent |
70
+ | MLLM | qwen_omni |
71
+ | Avatar | sensetime, spatius |
72
+
73
+ ## managed / BYOK 矩阵(源码级确认)
74
+
75
+ 概念:**managed(免 key)** = 不填 vendor key、Agora 托管(常见 vendor 的表达式是"省略 api_key");
76
+ **BYOK** = 填 vendor 自己的 key(LLM 还需 base_url)。没有统一的顶层 `credential_mode` 开关——
77
+ `credential_mode: "managed"|"byok"` 字面量**只存在于 `RimeTTS`** 单个 vendor。
78
+
79
+ | 环节 | 免 key(managed) | 需 BYOK |
80
+ |---|---|---|
81
+ | ASR | `fengming`(风鸣,无 key 字段,纯托管) | `tencent`(key/app_id/secret 必填)、`microsoft`;`xfyun` 系列 api_key 等可选(BYOK 时填) |
82
+ | LLM | 仅白名单 `gpt-4o-mini` / `gpt-4.1-mini` / `gpt-5-nano` / `gpt-5-mini`(托管) | `deepseek` / `aliyun` / `bytedance` / `tencent` 必须 api_key + base_url |
83
+ | TTS | (见"待验证") | CN `minimax` 通常要 key(官方说明 "not Agora-managed in the same way and typically includes key");`tencent` / `bytedance` / `cosyvoice` / `stepfun` |
84
+ | MLLM | 无 | `qwen_omni`(api_key 必填) |
85
+ | Avatar | 无 | `sensetime` / `spatius`(BYOK) |
86
+
87
+ 要点:
88
+
89
+ - CN 原生 LLM(DeepSeek/阿里/字节/腾讯)**没有免 key 托管**——托管白名单仍是 OpenAI 的
90
+ `gpt-4o-mini` 等几个模型(`_OPENAI_MANAGED_MODELS`)。
91
+ - SDK 默认 ASR:`area_scope == "cn"` 且未显式传 STT 时,默认 `fengming`(否则 `ares`)。
92
+
93
+ ## 已知组合(待验证,勿当作"可用配方")
94
+
95
+ 以下组合基于上面的矩阵推导,**均未端到端跑通**:
96
+
97
+ 1. **免 key 最小组合(理论)**:ASR `fengming` + LLM `gpt-4o-mini`(托管白名单)+ TTS(⚠️ 是否有免 key 项未知)
98
+ 2. **国内原生组合(需 BYOK)**:ASR `fengming` + LLM `deepseek`(api_key + base_url)+ TTS `minimax`(key)
99
+
100
+ ## 不支持的边界
101
+
102
+ - `properties.geofence.area` 可选值只有 `GLOBAL / NORTH_AMERICA / EUROPE / ASIA / INDIA / JAPAN`,
103
+ **没有 `CHINA`**。即无法用 `geofence` 强制 agent 引擎只在大陆运行(`ASIA` 是最近的一档,不等于大陆)。
104
+
105
+ ## 待验证 / 未知
106
+
107
+ - 免 key 组合是否端到端跑通(尤其 TTS 环节)。
108
+ - 国内是否存在一款完全托管的 TTS(源码里 CN MiniMax 的 `key` 为可选,但官方说明"通常要 key")。
109
+ - "只把 `Area.US` 改成 `Area.CN`、vendor 仍用海外类(Deepgram/OpenAI/MiniMax)"能否在 CN 端点跑通——未实测,不要默认可行。
110
+ - ConvoAI 直接 REST 在 CN 的官方推荐 host:`api.agora.io/cn/...` 还是 `api-cn-*.sd-rtn.com/cn/...`(未实测)。
@@ -0,0 +1,180 @@
1
+ ---
2
+ name: agora-cn-rtc
3
+ description: |
4
+ China-mainland (国内/声网) delta for Agora RTC (video/voice calling, live
5
+ streaming, screen share, join/publish/subscribe): CN region selection
6
+ (Web setArea / native areaCode), CN signaling domain (sd-rtn.com), and the
7
+ cloud-proxy / firewall setup for mainland restricted networks. Use for 国内
8
+ RTC, 声网 RTC, AREA_CODE_CN, setArea CHINA, or 云代理 questions.
9
+ license: MIT
10
+ metadata:
11
+ author: agora
12
+ version: '0.1.0'
13
+ ---
14
+
15
+ # 国内 RTC 差异(声网 / CN Region)
16
+
17
+ > 本页只记录国内(大陆 / 声网 / CN 区域)与海外 RTC 的差异。
18
+ > 基础机制(join / publish / subscribe / token / channel profile)仍以 `agora` skill 的
19
+ > `references/rtc/*` 为准。海外基线里**完全没有** region/area/domain 内容,本页补齐。
20
+
21
+ 验证基线:Web SDK `agora-rtc-sdk-ng` 4.24.7(`rtc-sdk_en.d.ts` 实测);原生 SDK 4.x 声网文档
22
+ (`doc.shengwang.cn` + `docs-md.agora.io`)。
23
+
24
+ ---
25
+
26
+ ## 已确认的国内 delta
27
+
28
+ ### 1. Web SDK(`agora-rtc-sdk-ng`)选择 CN 区域
29
+
30
+ **正确 API 是 `AgoraRTC.setArea`,值是大写 `"CHINA"`,不是 `"CN"`。**
31
+
32
+ ```js
33
+ // 只连国内服务器
34
+ AgoraRTC.setArea({ areaCode: "CHINA" });
35
+
36
+ // 或:全球里排除中国大陆
37
+ AgoraRTC.setArea({ areaCode: "GLOBAL", excludedArea: "CHINA" });
38
+ ```
39
+
40
+ - 枚举:`AREAS.CHINA = "CHINA"`(`ASIA / NORTH_AMERICA / EUROPE / JAPAN / INDIA / GLOBAL` 等并列)。
41
+ - TS 签名(4.24.7):`setArea(area: AREAS[] | { areaCode: AREAS[]; excludedArea?: AREAS })`,自 4.2.0 起。
42
+ - ⚠️ **不是** `AgoraRTC.createClient({ areaCode: "CN" })`:4.x 的 `ClientConfig` 里没有 `areaCode` 字段
43
+ (`createClient` 只接受 `mode/codec/role/clientRoleOptions` 等)。
44
+ - ⚠️ **没有**静态 `AgoraRTC.setCloudProxy`(这个猜测不存在于当前 Web SDK)。
45
+
46
+ 来源:
47
+ - `https://cdn.jsdelivr.net/npm/agora-rtc-sdk-ng@4.24.7/rtc-sdk_en.d.ts`(`AREAS` 枚举 + `setArea` 签名 + `ClientConfig`)
48
+ - `https://registry.npmjs.org/agora-rtc-sdk-ng`(latest = 4.24.7)
49
+ - `https://doc.shengwang.cn/doc/rtc/javascript/advanced-features/region`
50
+
51
+ ### 2. Web SDK 云代理(受限网络)
52
+
53
+ 云代理是 **client 实例方法**,不是全局静态方法;需先向声网申请开通。
54
+
55
+ ```js
56
+ const client = AgoraRTC.createClient({ mode: "rtc", codec: "vp8" });
57
+
58
+ client.startProxyServer(3); // 3 = Force UDP 云代理;5 = Force TCP/TLS 443(v4.9.0+)
59
+ await client.join(APP_ID, channel, token, null);
60
+ // ...
61
+ await client.leave();
62
+ client.stopProxyServer(); // 离开频道后才能关闭
63
+ ```
64
+
65
+ - `startProxyServer` 必须在 `join` **之前**调用;`stopProxyServer` 必须在 `leave` **之后**调用。
66
+ - 开通前置:联系 `sales@shengwang.cn` 提供 App ID / 使用区域 / 并发规模 / 运营商(不是开箱即用)。
67
+ - 判断媒体是否走代理:`client.on("is-using-cloud-proxy", (isUsingProxy) => ...)`。
68
+ - 自建代理(私有化/混合部署,非云代理):`client.setProxyServer(domain)`(ASCII 域名)+ `client.setTurnServer(config)`;
69
+ 二者与 `startProxyServer` **不能混用**。
70
+
71
+ 来源:
72
+ - `https://doc.shengwang.cn/doc/rtc/javascript/basic-features/firewall`
73
+ - `https://cdn.jsdelivr.net/npm/agora-rtc-sdk-ng@4.24.7/rtc-sdk_en.d.ts`(`startProxyServer`/`stopProxyServer`/`setProxyServer`)
74
+
75
+ ### 3. 原生 SDK 区域码(Android / iOS / C++)
76
+
77
+ **Android**(`RtcEngineConfig.mAreaCode`):
78
+
79
+ ```java
80
+ RtcEngineConfig config = new RtcEngineConfig();
81
+ config.mAppId = appId;
82
+ config.mContext = mContext;
83
+ config.mAreaCode = AREA_CODE_CN; // 中国大陆
84
+ mRtcEngine = RtcEngine.create(config);
85
+ ```
86
+
87
+ - 常量 `AREA_CODE_CN = 0x00000001`(`Constants.AreaCode`)。其余:`AREA_CODE_GLOB`(默认)/ `NA` / `EU` / `AS` / `JP` / `IN`。
88
+ - 支持位运算:排除大陆用 `AREA_CODE_GLOB ^ AREA_CODE_CN`。
89
+
90
+ **iOS**(`AgoraRtcEngineConfig.areaCode`):
91
+
92
+ ```swift
93
+ let config = AgoraRtcEngineConfig()
94
+ config.appId = "YourAppId"
95
+ config.areaCode = .CN // AgoraAreaCodeTypeCN
96
+ agoraKit = AgoraRtcEngineKit.sharedEngine(with: config, delegate: self)
97
+ ```
98
+
99
+ - 枚举:`AgoraAreaCodeTypeGlobal`(默认)/ `AgoraAreaCodeTypeCN` / `...NA` / `...EUR` / `...AS` / `...JP` / `...IN`。
100
+
101
+ **C++ / Windows**(`RtcEngineContext.areaCode`):
102
+
103
+ ```cpp
104
+ RtcEngineContext context;
105
+ context.appId = appId;
106
+ context.areaCode = AREA_CODE_CN; // 中国大陆
107
+ m_rtcEngine->initialize(context);
108
+ ```
109
+
110
+ 来源:
111
+ - `https://doc.shengwang.cn/doc/rtc/android/advanced-features/region`
112
+ - `https://doc.shengwang.cn/doc/rtc/ios/advanced-features/region`
113
+ - `https://doc.shengwang.cn/doc/rtc/windows/advanced-features/region`
114
+ - `https://doc.shengwang.cn/api-ref/rtc/android/API/class_areacode`(`AREA_CODE_CN = 0x00000001`)
115
+
116
+ ### 4. 原生 SDK 云代理(受限网络)
117
+
118
+ 原生在受限网络下**只支持云代理,不支持防火墙域名白名单**(见 §6 表格)。
119
+
120
+ - Android/C++:`RtcEngine.setCloudProxy(proxyType)`
121
+ - `TRANSPORT_TYPE_NONE_PROXY`(0) 默认自动;`TRANSPORT_TYPE_UDP_PROXY`(1) Force UDP;`TRANSPORT_TYPE_TCP_PROXY`(2) Force TCP/TLS 443。
122
+ - iOS:`setCloudProxy(_ proxyType: AgoraCloudProxyType)`
123
+ - `AgoraNoneProxy`(0) / `AgoraUdpProxy`(1) / `AgoraTcpProxy`(2)。
124
+ - 需在频道外调用,`RtcEngine` 生命周期内有效;同样要先向 `sales@shengwang.cn` 申请开通并加白名单 IP。
125
+
126
+ 来源:
127
+ - `https://doc.shengwang.cn/doc/rtc/android/basic-features/firewall`
128
+ - `https://doc.shengwang.cn/api-ref/rtc/ios/API/enum_cloudproxytype`
129
+
130
+ ### 5. CN 域名后缀 / 信令域名
131
+
132
+ - 国内主域名后缀 **`sd-rtn.com`**(海外 `agora.io`)。
133
+ - Web SDK 防火墙白名单域名(国内部分):
134
+ `*.sd-rtn.com`、`*.edge.sd-rtn.com`、`*.ap.sd-rtn.com`、`*.statscollector.sd-rtn.com`、`*.webrtc-cloud-proxy.sd-rtn.com`
135
+ (海外是 `*.agora.io` / `*.edge.agora.io`)。
136
+ - REST API 主域名(服务端在大陆时):`api.sd-rtn.com`(海外 `api.agora.io`);CN 区域子域
137
+ `api-cn-east-1.sd-rtn.com` / `api-cn-north-1.sd-rtn.com`。
138
+
139
+ 来源:
140
+ - `https://docs-md.agora.io/en/broadcast-streaming/reference/firewall_web.md`
141
+ - `https://docs-md.agora.io/en/broadcast-streaming/channel-management-api/best-practices/ensure-service-reliability.md`
142
+
143
+ ### 6. 网络/防火墙策略差异(Web vs 原生)
144
+
145
+ | 产品 | 防火墙域名白名单 | 声网云代理 |
146
+ |---|---|---|
147
+ | Video SDK(原生 / 三方框架) | ✘ 不支持 | ✔ |
148
+ | Video SDK(Web) | ✔ | ✔ |
149
+
150
+ - 即:**原生 RTC 在受限网络只能走云代理**(申请开通 + `setCloudProxy`);只有 Web SDK 能走域名白名单。
151
+
152
+ 来源:
153
+ - `https://docs-md.agora.io/en/broadcast-streaming/reference/firewall_android.md`
154
+
155
+ ---
156
+
157
+ ## 与海外一致(无 delta)
158
+
159
+ - **凭据模型**:App ID + App Certificate + token(`join` 传 token)这套完全不变;国内只是去
160
+ `console.shengwang.cn`(声网)建项目拿 App ID,拿到后 SDK 用法与海外一致。
161
+ - **频道机制**:`joinChannel` / `createClient` / `publish` / `subscribe` / channel profile
162
+ (`rtc`/`live`) / client role (`host`/`audience`) 全部同海外。
163
+ - **token 续期**:`token-privilege-will-expire`(Web)/ `onTokenPrivilegeWillExpire`(原生)+ `renewToken` 同海外。
164
+ - **编解码/双流/屏幕共享**等能力面无 CN 差异;差异只在"连哪个区域/什么网络"。
165
+
166
+ ---
167
+
168
+ ## 待验证 / 未知
169
+
170
+ - **原生 RTC 信令的精确接入点域名**:设置 `AREA_CODE_CN` 后原生 SDK 连接的确切信令主机名
171
+ (是否字面就是 `api.sd-rtn.com`)没有公开的"白名单域名"页可查(原生不支持防火墙白名单,官方未列域名)。
172
+ 已确认的是后缀 `sd-rtn.com` + REST 主域名 `api.sd-rtn.com`;原生媒体信令具体 host 记为待验证。
173
+ - **私有媒体网关(本地接入点 / 混合部署)**:确认原生有 `AgoraLocalAccessPointConfiguration` +
174
+ `setLocalAccessPoint`、Web 有 `setProxyServer`,但这是单独的企业私有化/混合部署项目(需声网部署本地媒体网关),
175
+ 未在本任务里核实其完整开通流程与字段,落地前需按 `doc.shengwang.cn` 现查。
176
+ - **Web `setArea` 单字符串写法**:中文文档示例是 `AgoraRTC.setArea("ASIA")`(单字符串),
177
+ 而 4.24.7 类型签名是 `AREAS[] | { areaCode, excludedArea }`;运行时是否仍兼容单字符串未实测,
178
+ 建议统一用 `setArea({ areaCode: "CHINA" })`。
179
+ - **云代理"国内测试 IP"清单会漂移**:中文防火墙文档列出的国内测试 IP(如 `150.138.153.78` 等)
180
+ 仅供测试、正式上线要声网另发,且清单随版本更新,落地以申请后声网提供为准。
@@ -0,0 +1,159 @@
1
+ ---
2
+ name: agora-cn-rtm
3
+ description: |
4
+ China-mainland (国内/声网) delta for Agora Signaling (RTM, 云信令): CN area
5
+ code / region selection on Web (AgoraRTM.setArea) and native (RtmAreaCode.CN /
6
+ AgoraRtmAreaCode.CN), the CN data-center concept vs the CLI
7
+ `--rtm-data-center CN` control-plane flag, and the CN endpoint domain
8
+ (sd-rtn.com). Use for 国内 RTM / 云信令, RTM data center CN, RTM setArea
9
+ CHINA, RtmAreaCode.CN questions.
10
+ license: MIT
11
+ metadata:
12
+ author: agora
13
+ version: '0.1.0'
14
+ ---
15
+
16
+ # 国内 RTM(云信令 / Signaling)差异:区域 / 数据中心
17
+
18
+ > 本页只记录国内(大陆 / 声网 / CN 区域)与海外 RTM 的差异。
19
+ > 基础机制(login / subscribe / publish / presence / storage / lock / stream channel)仍以
20
+ > `agora` skill 的 `references/rtm/*` 为准。海外基线里**完全没有** region/area/domain 内容,本页补齐。
21
+
22
+ 验证基线:Web SDK `agora-rtm` 2.3.0(npm 包 `agora-rtm.d.ts` 实测,latest=2.3.0);原生 SDK 2.x
23
+ 声网文档(`doc.shengwang.cn` api-ref + `docs.agora.io` signaling 文档)。
24
+
25
+ ---
26
+
27
+ ## 已确认的国内 delta
28
+
29
+ ### 1. Web SDK(`agora-rtm` v2)选择 CN 区域
30
+
31
+ **API 是顶层 `AgoraRTM.setArea`,值是大写字符串 `"CHINA"`,不是 `"CN"`。**(与 RTC 的
32
+ `AgoraRTC.setArea({ areaCode: "CHINA" })` 形状不同:RTM 用的是**复数数组** `areaCodes`。)
33
+
34
+ ```js
35
+ import AgoraRTM from "agora-rtm";
36
+
37
+ // 只连国内服务器(中国大陆)
38
+ AgoraRTM.setArea({ areaCodes: ["CHINA"] });
39
+
40
+ // 或:全球里排除中国大陆(海外场景)
41
+ AgoraRTM.setArea({ areaCodes: ["GLOBAL"], excludedArea: "CHINA" });
42
+
43
+ // 之后才创建实例
44
+ const rtm = new AgoraRTM.RTM(appId, userId, { logLevel: "info" });
45
+ ```
46
+
47
+ - TS 签名(2.3.0):`setArea(options: { areaCodes: AreaCode[]; excludedArea?: AreaCode }): void`。
48
+ - 枚举 `AreaCode`(v2 字符串值):`GLOBAL`(默认)/ `CHINA`(中国大陆)/ `INDIA` / `JAPAN` /
49
+ `ASIA`(除大陆外亚洲)/ `EUROPE` / `NORTH_AMERICA`。
50
+ - ⚠️ **不是** `new RTM(appId, uid, { areaCode: ... })`:v2 的 `RTMConfig`(构造器第三参)里**没有**
51
+ `areaCode` 字段(只有 `encryptionMode/salt/cipherKey/presenceTimeout/logUpload/cloudProxy/
52
+ useStringUserId/logLevel/heartbeatInterval/privateConfig`)。
53
+ - ⚠️ 包内还保留了 legacy v1 的 `LegacyAreaCode` 枚举(`CN = "CN"`, `GLOB = "GLOB"`, `NA`, `EU`,
54
+ `AS`, `JP`, `IN`, `OC`, `SA`, `AF`, `KR`, `US`, `OVS`)——那是 v1 兼容枚举,**v2 请用
55
+ `AreaCode.CHINA = "CHINA"`**,不要照搬 v1 的 `"CN"`。
56
+
57
+ 来源:
58
+ - `https://registry.npmjs.org/agora-rtm`(latest=2.3.0;`agora-rtm.d.ts` 的 `AreaCode` / `LegacyAreaCode` / `setArea` / `RTMConfig`)
59
+ - `https://docs.agora.io/en/signaling/get-started/client-configuration?platform=web`("Geographical area configuration" 示例 `setArea({ areaCodes: ["GLOBAL"], excludedArea: "CHINA" })`)
60
+
61
+ ### 2. Android SDK(`io.agora:agora-rtm` v2)选择 CN 区域
62
+
63
+ **字段是 `RtmConfig.Builder(...).areaCode(...)`,类型 `EnumSet<RtmAreaCode>`,CN 常量是 `RtmAreaCode.CN`。**
64
+
65
+ ```kotlin
66
+ import io.agora.rtm.RtmConfig
67
+ import io.agora.rtm.RtmConstants
68
+
69
+ val rtmConfig = RtmConfig.Builder("your-app-id", "user-id")
70
+ .areaCode(EnumSet.of(RtmConstants.RtmAreaCode.CN)) // 中国大陆
71
+ .eventListener(rtmEventListener)
72
+ .build()
73
+ val rtmClient = RtmClient.create(rtmConfig)
74
+ ```
75
+
76
+ - 枚举 `RtmAreaCode`(位掩码):`CN` = `0x00000001`(中国大陆)、`NA` = `0x00000002`、`EU` =
77
+ `0x00000004`、`AS` = `0x00000008`(除大陆外亚洲)、`JP` = `0x00000010`、`IN` = `0x00000020`、
78
+ `GLOB` = `0xFFFFFFFF`(默认,全球)。
79
+ - 默认值 `GLOB`;不设 `areaCode` 即全球,不限定大陆。
80
+
81
+ 来源:
82
+ - `https://docs.agora.io/en/signaling/get-started/client-configuration?platform=android`(`.areaCode(EnumSet.of(RtmConstants.RtmAreaCode.AS, RtmConstants.RtmAreaCode.CN))`)
83
+ - `https://doc.shengwang.cn/api-ref/rtm2/android/enumv`(`RtmAreaCode.CN` = `0x00000001` 中国大陆)
84
+
85
+ ### 3. iOS SDK(`AgoraRtmKit` / `AgoraRtmClientKit` v2)选择 CN 区域
86
+
87
+ **字段是 `AgoraRtmClientConfig.areaCode`,类型 `AgoraRtmAreaCode`(OptionSet),CN 是 `.CN`。**
88
+
89
+ ```swift
90
+ import AgoraRtmKit
91
+
92
+ let config = AgoraRtmClientConfig(appId: "yourAppId", userId: "yourUserId")
93
+ config.areaCode = [.CN] // 中国大陆(可组合多区域,如 [.CN, .NA])
94
+ let rtmClient = try AgoraRtmClientKit(config, delegate: nil)
95
+ ```
96
+
97
+ - 枚举 `AgoraRtmAreaCode`(位掩码):`CN` = `0x00000001`(中国大陆)、`NA` = `0x00000002`、`EU` =
98
+ `0x00000004`、`AS` = `0x00000008`、`JP` = `0x00000010`、`IN` = `0x00000020`、`GLOB` =
99
+ `0xFFFFFFFF`(默认,全球)。
100
+ - Objective-C 写法:`rtm_config.areaCode = AgoraRtmAreaCodeCN;`(`@property (nonatomic, assign) AgoraRtmAreaCode areaCode;`,默认 `AgoraRtmAreaCodeGLOB`)。
101
+
102
+ 来源:
103
+ - `https://doc.shengwang.cn/api-ref/rtm2/swift/toc-configuration/configuration`(`config.areaCode = [.CN, .NA]` 示例)
104
+ - `https://doc.shengwang.cn/api-ref/rtm2/ios/enumv`(`AgoraRtmAreaCodeCN` = `0x00000001` 中国大陆)
105
+ - `https://doc.shengwang.cn/api-ref/rtm2/ios/toc-configuration/configuration`(`areaCode` 属性声明)
106
+
107
+ ### 4. RTM 数据中心:控制面 vs 数据面(与 CLI `--rtm-data-center CN` 的关系)
108
+
109
+ 国内 RTM 涉及**两层独立配置**,二者互补、不可互相替代:
110
+
111
+ | 层 | 入口 | 作用 | CN 取值 |
112
+ |---|---|---|---|
113
+ | **控制面**(项目/凭据落在哪个区域后端) | CLI `agora project create ... --rtm-data-center CN` / `agora init --rtm-data-center CN` | 决定项目在哪个区域后台开通、去哪个控制台拿 App ID | `CN`(另 `NA`/`EU`/`AP`,默认 `NA`) |
114
+ | **数据面**(SDK 运行时连哪个 SDRTN 边缘区域) | 客户端 area code(§1–§3 的 `setArea` / `areaCode`) | 决定 SDK 连到哪个区域的 RTM 服务边缘节点 | Web `"CHINA"`;Android `RtmAreaCode.CN`;iOS `.CN` |
115
+
116
+ - CLI 的 `--rtm-data-center CN` **不会**替客户端设置 area code,反之亦然:国内部署要**两者都设**
117
+ (CN 项目拿 App ID + 客户端 areaCode = CN)。
118
+ - ⚠️ 取值集不对齐:CLI 是 `CN|NA|EU|AP`,SDK area code 是更细的位掩码
119
+ (`CN/NA/EU/AS/JP/IN/GLOB`),没有字面一一对应(CLI 的 `AP` 无同名 SDK 码)。这是"控制面 vs 数据面"
120
+ 两个维度,不是同一枚举的两套别名。
121
+
122
+ 来源:CLI 行为以 `agora` CLI 实测为准(`agora init --rtm-data-center CN` / `project create`);SDK
123
+ area code 见 §1–§3 来源。
124
+
125
+ ### 5. CN 域名 / 端点(RTM Web 消息频道)
126
+
127
+ - 国内主域名后缀 **`sd-rtn.com`**(海外 `agora.io`)。
128
+ - Signaling SDK(Web)消息频道防火墙白名单里同时列了两套,其中 **国内(`sd-rtn.com`)部分**:
129
+ `.edge.sd-rtn.com`、`web-1.ap.sd-rtn.com` … `web-4.ap.sd-rtn.com`、`rtm.statscollector.sd-rtn.com`、
130
+ `rtm.logservice.sd-rtn.com`;**海外(`agora.io`)部分**:`.edge.agora.io`、`ap-web-1.agora.io` …
131
+ `ap-web-4.agora.io`、`webcollector-rtm.agora.io`、`logservice-rtm.agora.io`。
132
+ - 端口(消息频道):`443; 9591; 9593; 27387`(TCP);v1.x 另加 `9601`。
133
+
134
+ 来源:
135
+ - `https://docs.agora.io/en/signaling/reference/firewall`("Signaling SDK (Web) → Message channel → Domains")
136
+
137
+ ---
138
+
139
+ ## 与海外一致(无 delta)
140
+
141
+ - **凭据模型**:App ID + App Certificate + token 完全不变。国内只是去 `console.shengwang.cn`
142
+ 建项目拿 App ID/证书,token 生成方式(App ID + App Certificate → token)与海外一致。
143
+ - **RTM API 面**:`login` / `subscribe` / `publish` / presence(`getOnlineUsers`/事件)/ storage /
144
+ lock / stream channel(topic)全部同海外;RTM UID 仍是字符串、RTC↔RTM 命名空间隔离等规则不变。
145
+ - **客户端形态**:RTM 仍是纯客户端 SDK(无服务端 SDK / 无 Electron/桌面版),CN 下不变。
146
+ - **areaCode 是可选的**:不设默认 `GLOB`(全球),行为与海外完全一致;只有需要限定/合规时才设 CN。
147
+
148
+ ---
149
+
150
+ ## 待验证 / 未知
151
+
152
+ - **原生(Android/iOS)RTM 的精确 CN 接入点域名**:海外防火墙文档"Signaling SDK (Native)"小节只列了
153
+ `.agora.io`(未列出 `.sd-rtn.com` 原生宿主名)。已确认的是后缀 `sd-rtn.com` + Web 端列出的
154
+ `rtm.*.sd-rtn.com` 系列;原生设 `RtmAreaCode.CN` / `.CN` 后连接的确切信令 host 未在公开白名单页
155
+ 单独枚举,落地如需精确域名按 `doc.shengwang.cn` 现查。
156
+ - **`--rtm-data-center CN` 与 SDK area code 的字面等价**:官方文档没有一句"CLI CN == 客户端 areaCode CN"
157
+ 的直接表述;本页按"控制面 vs 数据面"两层表述(§4),但若需要权威原文确认二者的绑定关系,属待验证。
158
+ - **v1(legacy)SDK 的国内配置**:v2 包里保留的 `LegacyAreaCode.CN = "CN"` 是 v1 兼容枚举;独立 v1
159
+ 包(`agora-rtm-sdk`)的国内 area code 具体 API/取值未在本任务核实。
@@ -0,0 +1,77 @@
1
+ ---
2
+ name: agora-cn-server
3
+ description: |
4
+ China-mainland (国内/声网) server-side token/auth delta: token algorithm is
5
+ region-agnostic, CN REST domain (api.sd-rtn.com), CN console RESTful API
6
+ credential location, and the CN Docker token image. Use for 国内 token,
7
+ 声网 token server, api.sd-rtn.com, RESTful API 凭证.
8
+ license: MIT
9
+ metadata:
10
+ author: agora
11
+ version: '0.1.0'
12
+ ---
13
+
14
+ # 国内 Server:token / 鉴权
15
+
16
+ 验证基线:官方文档(声网 `doc.shengwang.cn` 与海外 `docs.agora.io` 对照)。
17
+
18
+ ## 已确认的国内 delta
19
+
20
+ ### 1. 服务端 REST 域名(直接调服务端 API 时)
21
+
22
+ CN 主域名 `sd-rtn.com`,但**不是所有服务端产品都换域名**:
23
+
24
+ | 服务端产品 | CN 域名 | 海外域名 |
25
+ |---|---|---|
26
+ | 云端录制 REST | `https://api.sd-rtn.com` | `https://api.sd-rtn.com`(canonical 已统一;`api.agora.io` 仅残留于 quickstart 示例) |
27
+ | RTC 服务端 RESTful(频道管理/踢人规则等) | `https://api.sd-rtn.com` | `https://api.agora.io` |
28
+
29
+ > 云端录制 base URL 已在海外/国内两套文档里统一为 `api.sd-rtn.com`、且无 `/cn/` 前缀;
30
+ > 其真正的国内差异是「控制台换成声网 + `clientRequest.region="CN"`」,详见 [cloud-recording.md](cloud-recording.md)。
31
+
32
+ ### 2. Basic Auth 的客户 ID / 密钥获取位置不同
33
+
34
+ 鉴权 Header 完全一致:`Authorization: Basic base64(customerID:customerSecret)`。
35
+ 但**菜单路径不同**:
36
+
37
+ - **CN(声网)**:`console.shengwang.cn` → 设置 (Settings) → **RESTful API** → 添加密钥。
38
+ - **海外**:`console.agora.io` → **Developer Toolkit** → RESTful API → Add a secret。
39
+
40
+ (即:CN 走"设置 → RESTful API",海外走"Developer Toolkit → RESTful API"。)
41
+
42
+ ### 3. CN 专属 token 服务器 Docker 镜像
43
+
44
+ 声网文档给的 Docker 部署镜像名是 `agoracn/token:0.1.2023053011`(`agoracn` 命名空间)。
45
+ 部署层面小贴士:可用 `goproxy.cn` 加速 `go get`。
46
+
47
+ ## 与海外一致(无 delta)
48
+
49
+ ### Token 算法 / 输入完全一致,无 region 参数(确认)
50
+
51
+ - 同一开源仓库 `AgoraIO/Tools` 的 `DynamicKey/AgoraDynamicKey`,算法 HMAC-SHA256(AccessToken2)。
52
+ - 同一函数签名、同样输入(App ID + App Certificate + channel + UID/account + role + 过期时间),**无 region 参数**:
53
+ - RTC:`BuildTokenWithUid(...)` / `RtcTokenBuilder.buildTokenWithUid(...)` / `buildTokenWithRtm(...)` / `buildTokenWithUserAccount(...)`
54
+ - RTM:`RtmTokenBuilder2.BuildToken(appId, appCertificate, userId, expire)`
55
+ - **结论**:token builder 是 region-agnostic 的;region 内嵌于 App ID / App Certificate(CN 项目与海外项目是两套不同的 App ID + 证书)。因此**同一个 `agora-token` / `buildTokenWithRtm` 直接用于 CN 项目**,无需 CN 变体或额外参数。
56
+
57
+ ### 无 CN 版 token 库 / npm 包
58
+
59
+ CN 文档指向的仍是同一个 `AgoraDynamicKey` 仓库;`agora-token`(npm)全球同一包,CN 直接复用。
60
+ 唯一的 CN 专属产物是上述 Docker 镜像 `agoracn/token`(部署层,非库/算法层)。
61
+
62
+ ### 其余一致
63
+
64
+ - token 约束:24h 最长有效期、过期前 30s `token-privilege-will-expire`、UID 范围 1..(2³²-1)——CN 与海外相同。
65
+
66
+ ## 待验证 / 未知
67
+
68
+ 1. 云端录制 base URL 已在两套文档统一为 `api.sd-rtn.com`(已确认);但 RTC 服务端 RESTful 是否也在向 `api.sd-rtn.com` 统一、迁移期 `api.agora.io` 是否仍可用——未钉死。
69
+ 2. `agoracn/token` 是否有海外等价镜像 `agoraio/token`(未在海外文档找到,未确认)。
70
+
71
+ ## 来源
72
+
73
+ - 声网 token 生成:https://doc.shengwang.cn/doc/rtc/javascript/basic-features/token-authentication
74
+ - 声网 RTM token:https://doc.shengwang.cn/doc/rtm2/javascript/user-guide/token/token-generation
75
+ - 声网云录制 REST 快速开始:https://doc.shengwang.cn/doc/cloud-recording/restful/get-started/quick-start
76
+ - 声网 RTC 服务端 REST:https://doc.shengwang.cn/doc/rtc/restful/get-started/call-api
77
+ - 海外对照:https://docs-md.agora.io/en/video-calling/token-authentication/deploy-token-server.md
package/index.js CHANGED
@@ -1,44 +1,76 @@
1
- // dsh-agora — bundled skill provider for DeepSeek Harness.
1
+ // dsh-agora — bundled skill providers for DeepSeek Harness.
2
2
  //
3
- // Registers the `agora` skill on ctx.skills, mirroring the official
4
- // `@deepseek-ai/dsh-skill-badge` provider pattern: a Cordis plugin whose
5
- // apply() registers one immutable provider. The SKILL.md body and references/
6
- // live in assets/agora/ and are synced verbatim from AgoraIO/skills at a
7
- // pinned release tag (see scripts/sync-deps.sh) zero rewrite, no drift.
3
+ // Registers two skills on ctx.skills, mirroring the official
4
+ // `@deepseek-ai/dsh-skill-badge` provider pattern:
5
+ // - `agora` — the official Agora skill, synced verbatim from
6
+ // AgoraIO/skills at a pinned release tag (zero rewrite).
7
+ // The SKILL.md body and references/ live in assets/agora/.
8
+ // - `agora-cn` — a shell-maintained companion documenting only the
9
+ // China-mainland (国内/声网) delta. It lives in
10
+ // assets/agora-cn/, which scripts/sync-deps.sh never touches.
8
11
  import { readFile } from 'node:fs/promises'
9
12
  import { fileURLToPath } from 'node:url'
10
13
  import { BUNDLED_SKILL_RANK } from '@deepseek-ai/dsh-skill'
11
14
 
12
15
  const PROVIDER_NAME = 'agora'
13
- const SKILL_DIR_URL = new URL('./assets/agora/', import.meta.url)
14
- const SKILL_BODY_URL = new URL('./assets/agora/SKILL.md', import.meta.url)
15
- const RESOURCE_BASE = {
16
- kind: 'directory',
17
- path: fileURLToPath(SKILL_DIR_URL),
18
- }
16
+
17
+ const AGORA_DIR_URL = new URL('./assets/agora/', import.meta.url)
18
+ const AGORA_BODY_URL = new URL('./assets/agora/SKILL.md', import.meta.url)
19
+
20
+ const CN_DIR_URL = new URL('./assets/agora-cn/', import.meta.url)
21
+ const CN_BODY_URL = new URL('./assets/agora-cn/SKILL.md', import.meta.url)
19
22
 
20
23
  const CANDIDATE = {
21
24
  name: 'agora',
22
25
  description:
23
- 'Activate when the user wants to build voice AI agents, video or voice calls, live streaming, screen sharing, in-app messaging and presence, recording, token or auth flows, or use the `agora` CLI for login, quickstarts, env setup, diagnostics, introspection, skills, or MCP serving, especially when integrating Agora into an app.',
26
+ 'Activate when the user wants to build voice AI agents, video or voice calls, live streaming, screen sharing, in-app messaging and presence, recording, token or auth flows, or use the `agora` CLI for login, quickstarts, env setup, diagnostics, introspection, skills, or MCP serving, especially when integrating Agora into an app. For China-mainland (国内/声网) deployment, load the `agora-cn` skill instead.',
24
27
  invocation: {
25
28
  modelInvocable: true,
26
29
  userInvocable: true,
27
30
  },
28
31
  provider: PROVIDER_NAME,
29
32
  source: 'bundled',
30
- resourceBase: RESOURCE_BASE,
33
+ resourceBase: {
34
+ kind: 'directory',
35
+ path: fileURLToPath(AGORA_DIR_URL),
36
+ },
31
37
  rank: BUNDLED_SKILL_RANK,
32
- locator: SKILL_BODY_URL,
38
+ locator: AGORA_BODY_URL,
39
+ }
40
+
41
+ const CN_CANDIDATE = {
42
+ name: 'agora-cn',
43
+ description:
44
+ 'Activate for China-mainland (国内/声网) Agora deployment: console.shengwang.cn control plane, CN endpoints on the sd-rtn.com domain, `agora login --region cn` + CN data center, ConvoAI (Area.CN → api-cn-*.sd-rtn.com/cn + CN vendor/BYOK), and CN region selection for RTC (setArea CHINA / AREA_CODE_CN), RTM (setArea areaCodes / RtmAreaCode.CN), and Cloud Recording (clientRequest.region). Use when the user wants domestic deployment, 声网, China region (CN), or mainland data residency. Supplements the `agora` skill.',
45
+ whenToUse:
46
+ 'Use when the user wants China-mainland (国内/声网) or CN-region deployment. Load the `agora` skill alongside it for the baseline mechanics.',
47
+ invocation: {
48
+ modelInvocable: true,
49
+ userInvocable: true,
50
+ },
51
+ provider: PROVIDER_NAME,
52
+ source: 'bundled',
53
+ resourceBase: {
54
+ kind: 'directory',
55
+ path: fileURLToPath(CN_DIR_URL),
56
+ },
57
+ rank: BUNDLED_SKILL_RANK,
58
+ locator: CN_BODY_URL,
59
+ }
60
+
61
+ const BODY_BY_NAME = {
62
+ agora: AGORA_BODY_URL,
63
+ 'agora-cn': CN_BODY_URL,
33
64
  }
34
65
 
35
66
  const provider = {
36
67
  name: PROVIDER_NAME,
37
- list: () => Promise.resolve([CANDIDATE]),
38
- async get(_candidate) {
68
+ list: () => Promise.resolve([CANDIDATE, CN_CANDIDATE]),
69
+ async get(candidate) {
70
+ const bodyUrl = BODY_BY_NAME[candidate.name]
39
71
  return {
40
- ...CANDIDATE,
41
- content: await readFile(SKILL_BODY_URL, 'utf8'),
72
+ ...candidate,
73
+ content: bodyUrl ? await readFile(bodyUrl, 'utf8') : '',
42
74
  }
43
75
  },
44
76
  }
@@ -47,7 +79,7 @@ const provider = {
47
79
  export const name = 'agora-skills'
48
80
  /** Service required by the bundled provider. */
49
81
  export const inject = ['skills']
50
- /** Register the bundled `agora` provider on `ctx.skills`. */
82
+ /** Register the bundled `agora` providers on `ctx.skills`. */
51
83
  export function apply(ctx) {
52
84
  ctx.skills.registerProvider(() => provider)
53
85
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-agora",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "description": "DSH skill bundle: the Agora skill (RTC, RTM, ConvoAI, CLI, Cloud Recording, tokens) synced verbatim from AgoraIO/skills at a pinned release tag. Install to add the `agora` skill to DeepSeek Harness.",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -12,7 +12,8 @@
12
12
  "files": [
13
13
  "index.js",
14
14
  "cordis.patch.yml",
15
- "assets/agora"
15
+ "assets/agora",
16
+ "assets/agora-cn"
16
17
  ],
17
18
  "license": "MIT",
18
19
  "repository": {