@tencent-rtc/trtc-agent-skills 0.1.6 → 0.1.8

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.
Files changed (194) hide show
  1. package/AGENTS.md +1 -1
  2. package/CLAUDE.md +1 -1
  3. package/CODEBUDDY.md +1 -1
  4. package/README.md +12 -76
  5. package/README.zh.md +12 -72
  6. package/bin/cli.js +200 -46
  7. package/knowledge-base/conference/web/index.yaml +6 -6
  8. package/knowledge-base/slices/conference/web/official-roomkit-api.md +119 -8
  9. package/package.json +1 -1
  10. package/skills/trtc/SKILL.md +97 -11
  11. package/skills/trtc-ai-oral-coach/README.ja.md +131 -0
  12. package/skills/trtc-ai-oral-coach/README.md +132 -0
  13. package/skills/trtc-ai-oral-coach/README.zh-CN.md +131 -0
  14. package/skills/trtc-ai-oral-coach/SKILL.md +398 -0
  15. package/skills/trtc-ai-oral-coach/auto_adapters/integration_templates/custom-learning-kb-sample.md +88 -0
  16. package/skills/trtc-ai-oral-coach/auto_adapters/integration_templates/generic-integration.md +104 -0
  17. package/skills/trtc-ai-oral-coach/auto_adapters/manifest.yaml +27 -0
  18. package/skills/trtc-ai-oral-coach/auto_adapters/python/README.md +49 -0
  19. package/skills/trtc-ai-oral-coach/auto_adapters/python/coach_client.py.tpl +185 -0
  20. package/skills/trtc-ai-oral-coach/auto_adapters/web/README.md +46 -0
  21. package/skills/trtc-ai-oral-coach/auto_adapters/web/oral-coach-client.js.tpl +210 -0
  22. package/skills/trtc-ai-oral-coach/capabilities/ability-report/manifest.yaml +52 -0
  23. package/skills/trtc-ai-oral-coach/capabilities/ability-report/src/__init__.py +2 -0
  24. package/skills/trtc-ai-oral-coach/capabilities/ability-report/src/adapters/__init__.py +2 -0
  25. package/skills/trtc-ai-oral-coach/capabilities/ability-report/src/adapters/default.py +177 -0
  26. package/skills/trtc-ai-oral-coach/capabilities/ability-report/src/handler.py +29 -0
  27. package/skills/trtc-ai-oral-coach/capabilities/ability-report/src/router.py +23 -0
  28. package/skills/trtc-ai-oral-coach/capabilities/conversation-core/.env.example +59 -0
  29. package/skills/trtc-ai-oral-coach/capabilities/conversation-core/manifest.yaml +46 -0
  30. package/skills/trtc-ai-oral-coach/capabilities/conversation-core/requirements.txt +6 -0
  31. package/skills/trtc-ai-oral-coach/capabilities/conversation-core/src/TLSSigAPIv2.py +275 -0
  32. package/skills/trtc-ai-oral-coach/capabilities/conversation-core/src/__init__.py +2 -0
  33. package/skills/trtc-ai-oral-coach/capabilities/conversation-core/src/_capability_loader.py +227 -0
  34. package/skills/trtc-ai-oral-coach/capabilities/conversation-core/src/agent.py +197 -0
  35. package/skills/trtc-ai-oral-coach/capabilities/conversation-core/src/config.py +149 -0
  36. package/skills/trtc-ai-oral-coach/capabilities/conversation-core/src/core/__init__.py +2 -0
  37. package/skills/trtc-ai-oral-coach/capabilities/conversation-core/src/core/report_llm.py +129 -0
  38. package/skills/trtc-ai-oral-coach/capabilities/conversation-core/src/health.py +36 -0
  39. package/skills/trtc-ai-oral-coach/capabilities/conversation-core/src/server.py +205 -0
  40. package/skills/trtc-ai-oral-coach/capabilities/conversation-core/src/trtc_client.py +86 -0
  41. package/skills/trtc-ai-oral-coach/capabilities/conversation-core/src/usersig.py +33 -0
  42. package/skills/trtc-ai-oral-coach/capabilities/custom-learning-kb/manifest.yaml +65 -0
  43. package/skills/trtc-ai-oral-coach/capabilities/custom-learning-kb/src/__init__.py +2 -0
  44. package/skills/trtc-ai-oral-coach/capabilities/custom-learning-kb/src/adapters/__init__.py +2 -0
  45. package/skills/trtc-ai-oral-coach/capabilities/custom-learning-kb/src/adapters/clients.py +126 -0
  46. package/skills/trtc-ai-oral-coach/capabilities/custom-learning-kb/src/ports.py +46 -0
  47. package/skills/trtc-ai-oral-coach/capabilities/custom-learning-kb/src/router.py +27 -0
  48. package/skills/trtc-ai-oral-coach/capabilities/quick-correct/manifest.yaml +48 -0
  49. package/skills/trtc-ai-oral-coach/capabilities/quick-correct/src/__init__.py +2 -0
  50. package/skills/trtc-ai-oral-coach/capabilities/quick-correct/src/adapters/__init__.py +2 -0
  51. package/skills/trtc-ai-oral-coach/capabilities/quick-correct/src/adapters/default.py +106 -0
  52. package/skills/trtc-ai-oral-coach/capabilities/quick-correct/src/handler.py +33 -0
  53. package/skills/trtc-ai-oral-coach/capabilities/quick-correct/src/router.py +23 -0
  54. package/skills/trtc-ai-oral-coach/capabilities/reply-suggestion/manifest.yaml +49 -0
  55. package/skills/trtc-ai-oral-coach/capabilities/reply-suggestion/src/__init__.py +2 -0
  56. package/skills/trtc-ai-oral-coach/capabilities/reply-suggestion/src/adapters/__init__.py +2 -0
  57. package/skills/trtc-ai-oral-coach/capabilities/reply-suggestion/src/adapters/default.py +86 -0
  58. package/skills/trtc-ai-oral-coach/capabilities/reply-suggestion/src/handler.py +29 -0
  59. package/skills/trtc-ai-oral-coach/capabilities/reply-suggestion/src/router.py +23 -0
  60. package/skills/trtc-ai-oral-coach/capabilities/scenario-roleplay/data/practice-scenarios.json +500 -0
  61. package/skills/trtc-ai-oral-coach/capabilities/scenario-roleplay/manifest.yaml +54 -0
  62. package/skills/trtc-ai-oral-coach/capabilities/scenario-roleplay/src/__init__.py +2 -0
  63. package/skills/trtc-ai-oral-coach/capabilities/scenario-roleplay/src/adapters/__init__.py +2 -0
  64. package/skills/trtc-ai-oral-coach/capabilities/scenario-roleplay/src/adapters/default.py +113 -0
  65. package/skills/trtc-ai-oral-coach/capabilities/scenario-roleplay/src/compose.py +143 -0
  66. package/skills/trtc-ai-oral-coach/capabilities/scenario-roleplay/src/defaults.py +140 -0
  67. package/skills/trtc-ai-oral-coach/capabilities/scenario-roleplay/src/handler.py +29 -0
  68. package/skills/trtc-ai-oral-coach/capabilities/scenario-roleplay/src/router.py +22 -0
  69. package/skills/trtc-ai-oral-coach/capabilities/scenario-roleplay/src/scenario_source.py +179 -0
  70. package/skills/trtc-ai-oral-coach/references/design-specs.md +36 -0
  71. package/skills/trtc-ai-oral-coach/references/evaluator-port.md +75 -0
  72. package/skills/trtc-ai-oral-coach/scenarios/speaking-coach/recipe.yaml +86 -0
  73. package/skills/trtc-ai-oral-coach/scenarios/speaking-coach/ui/avatars/friend.png +0 -0
  74. package/skills/trtc-ai-oral-coach/scenarios/speaking-coach/ui/avatars/listener.png +0 -0
  75. package/skills/trtc-ai-oral-coach/scenarios/speaking-coach/ui/avatars/local.png +0 -0
  76. package/skills/trtc-ai-oral-coach/scenarios/speaking-coach/ui/coach.html +1986 -0
  77. package/skills/trtc-ai-oral-coach/scenarios/speaking-coach/ui/i18n.js +323 -0
  78. package/skills/trtc-ai-oral-coach/scenarios/speaking-coach/ui/practice-scenarios.json +500 -0
  79. package/skills/trtc-ai-oral-coach/scenarios/speaking-coach/ui/tokens.css +100 -0
  80. package/skills/trtc-ai-oral-coach/scripts/add-capability.py +256 -0
  81. package/skills/trtc-ai-oral-coach/scripts/verify-credentials.py +96 -0
  82. package/skills/trtc-ai-oral-coach/start.sh +59 -0
  83. package/skills/trtc-ai-oral-coach/triggers.yaml +32 -0
  84. package/skills/trtc-ai-realtime-interpreter/README.ja.md +197 -0
  85. package/skills/trtc-ai-realtime-interpreter/README.md +197 -0
  86. package/skills/trtc-ai-realtime-interpreter/README.zh-CN.md +197 -0
  87. package/skills/trtc-ai-realtime-interpreter/SKILL.md +748 -0
  88. package/skills/trtc-ai-realtime-interpreter/auto_adapters/integration_templates/generic-rest-api.md +85 -0
  89. package/skills/trtc-ai-realtime-interpreter/auto_adapters/integration_templates/room-owner-authz-note.md +53 -0
  90. package/skills/trtc-ai-realtime-interpreter/auto_adapters/manifest.yaml +49 -0
  91. package/skills/trtc-ai-realtime-interpreter/auto_adapters/python/README.md +11 -0
  92. package/skills/trtc-ai-realtime-interpreter/auto_adapters/python/fastapi_reverse_proxy.py.tpl +84 -0
  93. package/skills/trtc-ai-realtime-interpreter/capabilities/conversation-core/.env.example +17 -0
  94. package/skills/trtc-ai-realtime-interpreter/capabilities/conversation-core/frontend/silent-listener.ts +91 -0
  95. package/skills/trtc-ai-realtime-interpreter/capabilities/conversation-core/manifest.yaml +110 -0
  96. package/skills/trtc-ai-realtime-interpreter/capabilities/conversation-core/requirements.txt +5 -0
  97. package/skills/trtc-ai-realtime-interpreter/capabilities/conversation-core/src/__init__.py +0 -0
  98. package/skills/trtc-ai-realtime-interpreter/capabilities/conversation-core/src/_capability_loader.py +89 -0
  99. package/skills/trtc-ai-realtime-interpreter/capabilities/conversation-core/src/agent.py +153 -0
  100. package/skills/trtc-ai-realtime-interpreter/capabilities/conversation-core/src/credentials.py +112 -0
  101. package/skills/trtc-ai-realtime-interpreter/capabilities/conversation-core/src/health.py +218 -0
  102. package/skills/trtc-ai-realtime-interpreter/capabilities/conversation-core/src/log_filter.py +33 -0
  103. package/skills/trtc-ai-realtime-interpreter/capabilities/conversation-core/src/server.py +266 -0
  104. package/skills/trtc-ai-realtime-interpreter/capabilities/conversation-core/src/trtc_client.py +188 -0
  105. package/skills/trtc-ai-realtime-interpreter/capabilities/conversation-core/src/usersig.py +53 -0
  106. package/skills/trtc-ai-realtime-interpreter/capabilities/meeting-ops/README.md +46 -0
  107. package/skills/trtc-ai-realtime-interpreter/capabilities/meeting-ops/manifest.yaml +63 -0
  108. package/skills/trtc-ai-realtime-interpreter/capabilities/meeting-ops/src/__init__.py +0 -0
  109. package/skills/trtc-ai-realtime-interpreter/capabilities/meeting-ops/src/fanout.py +149 -0
  110. package/skills/trtc-ai-realtime-interpreter/capabilities/meeting-ops/src/router.py +83 -0
  111. package/skills/trtc-ai-realtime-interpreter/capabilities/realtime-translation/frontend/subtitle-parser.ts +145 -0
  112. package/skills/trtc-ai-realtime-interpreter/capabilities/realtime-translation/manifest.yaml +68 -0
  113. package/skills/trtc-ai-realtime-interpreter/capabilities/realtime-translation/src/__init__.py +0 -0
  114. package/skills/trtc-ai-realtime-interpreter/capabilities/realtime-translation/src/modes.py +73 -0
  115. package/skills/trtc-ai-realtime-interpreter/capabilities/realtime-translation/src/router.py +83 -0
  116. package/skills/trtc-ai-realtime-interpreter/capabilities/realtime-translation/src/service.py +77 -0
  117. package/skills/trtc-ai-realtime-interpreter/scenarios/meeting-interpreter/README.md +23 -0
  118. package/skills/trtc-ai-realtime-interpreter/scenarios/meeting-interpreter/backend/app/__init__.py +0 -0
  119. package/skills/trtc-ai-realtime-interpreter/scenarios/meeting-interpreter/backend/app/server.py +277 -0
  120. package/skills/trtc-ai-realtime-interpreter/scenarios/meeting-interpreter/backend/requirements.txt +5 -0
  121. package/skills/trtc-ai-realtime-interpreter/scenarios/meeting-interpreter/backend/start.sh +28 -0
  122. package/skills/trtc-ai-realtime-interpreter/scenarios/meeting-interpreter/recipe.yaml +72 -0
  123. package/skills/trtc-ai-realtime-interpreter/scenarios/meeting-interpreter/ui/index.html +12 -0
  124. package/skills/trtc-ai-realtime-interpreter/scenarios/meeting-interpreter/ui/legacy/index.html +738 -0
  125. package/skills/trtc-ai-realtime-interpreter/scenarios/meeting-interpreter/ui/package-lock.json +4302 -0
  126. package/skills/trtc-ai-realtime-interpreter/scenarios/meeting-interpreter/ui/package.json +33 -0
  127. package/skills/trtc-ai-realtime-interpreter/scenarios/meeting-interpreter/ui/postcss.config.js +6 -0
  128. package/skills/trtc-ai-realtime-interpreter/scenarios/meeting-interpreter/ui/src/App.vue +18 -0
  129. package/skills/trtc-ai-realtime-interpreter/scenarios/meeting-interpreter/ui/src/api/backend.ts +82 -0
  130. package/skills/trtc-ai-realtime-interpreter/scenarios/meeting-interpreter/ui/src/components/SetupScreen.vue +362 -0
  131. package/skills/trtc-ai-realtime-interpreter/scenarios/meeting-interpreter/ui/src/components/SummaryScreen.vue +203 -0
  132. package/skills/trtc-ai-realtime-interpreter/scenarios/meeting-interpreter/ui/src/components/conference/ChatPanel.vue +188 -0
  133. package/skills/trtc-ai-realtime-interpreter/scenarios/meeting-interpreter/ui/src/components/conference/ConferenceRoom.vue +453 -0
  134. package/skills/trtc-ai-realtime-interpreter/scenarios/meeting-interpreter/ui/src/components/conference/ParticipantViewUI.vue +170 -0
  135. package/skills/trtc-ai-realtime-interpreter/scenarios/meeting-interpreter/ui/src/components/conference/PeoplePanel.vue +206 -0
  136. package/skills/trtc-ai-realtime-interpreter/scenarios/meeting-interpreter/ui/src/components/conference/SidePanel.vue +77 -0
  137. package/skills/trtc-ai-realtime-interpreter/scenarios/meeting-interpreter/ui/src/components/conference/Toolbar.vue +371 -0
  138. package/skills/trtc-ai-realtime-interpreter/scenarios/meeting-interpreter/ui/src/components/conference/TopBar.vue +310 -0
  139. package/skills/trtc-ai-realtime-interpreter/scenarios/meeting-interpreter/ui/src/components/conference/TranscriptPanel.vue +225 -0
  140. package/skills/trtc-ai-realtime-interpreter/scenarios/meeting-interpreter/ui/src/composables/useAiInterpreter.ts +263 -0
  141. package/skills/trtc-ai-realtime-interpreter/scenarios/meeting-interpreter/ui/src/composables/useConference.ts +98 -0
  142. package/skills/trtc-ai-realtime-interpreter/scenarios/meeting-interpreter/ui/src/env.d.ts +7 -0
  143. package/skills/trtc-ai-realtime-interpreter/scenarios/meeting-interpreter/ui/src/main.ts +5 -0
  144. package/skills/trtc-ai-realtime-interpreter/scenarios/meeting-interpreter/ui/src/store.ts +103 -0
  145. package/skills/trtc-ai-realtime-interpreter/scenarios/meeting-interpreter/ui/src/style.css +19 -0
  146. package/skills/trtc-ai-realtime-interpreter/scenarios/meeting-interpreter/ui/tailwind.config.js +25 -0
  147. package/skills/trtc-ai-realtime-interpreter/scenarios/meeting-interpreter/ui/tsconfig.json +25 -0
  148. package/skills/trtc-ai-realtime-interpreter/scenarios/meeting-interpreter/ui/tsconfig.node.json +10 -0
  149. package/skills/trtc-ai-realtime-interpreter/scenarios/meeting-interpreter/ui/vite.config.ts +26 -0
  150. package/skills/trtc-ai-realtime-interpreter/scripts/add-capability.py +163 -0
  151. package/skills/trtc-ai-realtime-interpreter/scripts/deploy-demo.sh +64 -0
  152. package/skills/trtc-ai-realtime-interpreter/scripts/lib/__init__.py +0 -0
  153. package/skills/trtc-ai-realtime-interpreter/scripts/lib/credential_validators.py +143 -0
  154. package/skills/trtc-ai-realtime-interpreter/scripts/lib/manifest_resolver.py +60 -0
  155. package/skills/trtc-ai-realtime-interpreter/scripts/lib/stack_detector.py +50 -0
  156. package/skills/trtc-ai-realtime-interpreter/scripts/post-install-patch.py +79 -0
  157. package/skills/trtc-ai-realtime-interpreter/scripts/verify-credentials.py +76 -0
  158. package/skills/trtc-ai-realtime-interpreter/start.sh +85 -0
  159. package/skills/trtc-ai-realtime-interpreter/triggers.yaml +29 -0
  160. package/skills/trtc-ai-service/README.ja.md +18 -35
  161. package/skills/trtc-ai-service/README.md +18 -35
  162. package/skills/trtc-ai-service/README.zh-CN.md +18 -35
  163. package/skills/trtc-ai-service/SKILL.md +194 -124
  164. package/skills/trtc-ai-service/capabilities/conversation-core/src/credentials.py +1 -1
  165. package/skills/trtc-chat/SKILL.md +1 -1
  166. package/skills/trtc-chat/docs/SKILL.md +1 -1
  167. package/skills/trtc-conference/flows/onboarding.md +6 -0
  168. package/skills/trtc-conference/flows/topic.md +6 -2
  169. package/skills/trtc-conference/playbooks/official-roomkit.md +3 -1
  170. package/skills/trtc-conference/tests/test_conference_index_contract.py +16 -0
  171. package/skills/trtc-conference/tests/test_conference_onboarding_contract.py +9 -0
  172. package/skills/trtc-conference/tests/test_conference_topic_flow_contract.py +16 -0
  173. package/skills/trtc-push/SKILL.md +118 -0
  174. package/skills/trtc-push/issues/ROUTER.json +429 -0
  175. package/skills/trtc-push/issues/cards/android/fcm-gms-domestic.md +53 -0
  176. package/skills/trtc-push/issues/cards/android/vendor-huawei.md +72 -0
  177. package/skills/trtc-push/issues/cards/common/console-certificate-quota.md +46 -0
  178. package/skills/trtc-push/issues/cards/common/registration-binding.md +67 -0
  179. package/skills/trtc-push/issues/cards/ios/aps-environment-3000.md +55 -0
  180. package/skills/trtc-push/issues/cards/ios/certificate-businessid.md +56 -0
  181. package/skills/trtc-push/issues/cards/ios/xcodegen-cocoapods-module.md +54 -0
  182. package/skills/trtc-push/issues/flows/android/delivered-not-displayed.md +52 -0
  183. package/skills/trtc-push/issues/flows/android/vendor-not-received.md +57 -0
  184. package/skills/trtc-push/issues/flows/common/badge.md +49 -0
  185. package/skills/trtc-push/issues/flows/common/console-product-limits.md +48 -0
  186. package/skills/trtc-push/issues/flows/common/server-api.md +51 -0
  187. package/skills/trtc-push/issues/flows/cross-platform/harmonyos.md +51 -0
  188. package/skills/trtc-push/issues/flows/cross-platform/uniapp-integration.md +57 -0
  189. package/skills/trtc-push/issues/flows/ios/offline-not-received.md +57 -0
  190. package/skills/trtc-push/references/code-templates.md +386 -0
  191. package/skills/trtc-push/references/hard-rules.md +112 -0
  192. package/skills/trtc-push/references/timpush-sdk-api.md +72 -0
  193. package/skills/trtc-push/references/workflow-protocol.md +82 -0
  194. /package/.cursor/rules/{main.mdc → ui-mode.mdc} +0 -0
package/bin/cli.js CHANGED
@@ -62,7 +62,10 @@ const SKILL_ALLOWLIST = new Set([
62
62
  "trtc-docs",
63
63
  "trtc-conference",
64
64
  "trtc-ai-service",
65
+ "trtc-ai-oral-coach",
66
+ "trtc-ai-realtime-interpreter",
65
67
  "trtc-chat",
68
+ "trtc-push",
66
69
  ]);
67
70
 
68
71
  function getSkillNames() {
@@ -106,6 +109,96 @@ const MCP_TARGETS = {
106
109
  const MCP_SERVER_NAME = "tencent-rtc-skill-tool";
107
110
  const MCP_SERVER_ENTRY = "@tencent-rtc/skill-tool@latest";
108
111
 
112
+ // Multi-MCP registry. tencent-rtc-skill-tool is always installed via npx.
113
+ // trtc-push-mcp is now public on npm and should be installed automatically with
114
+ // the skill suite. Maintainers can still force a local checkout via
115
+ // TRTC_PUSH_MCP_ENTRY / TIMPUSH_MCP_ENTRY when validating unpublished MCP code.
116
+ const TRTC_PUSH_MCP_NAME = "trtc-push-mcp";
117
+ const TRTC_PUSH_MCP_PACKAGE = process.env.TRTC_PUSH_MCP_PACKAGE || "@tencent-rtc/trtc-push-mcp@1";
118
+
119
+ function getDefaultPathFallbacks({ platform = process.platform, env = process.env } = {}) {
120
+ if (platform === "win32") {
121
+ const systemRoot = env.SystemRoot || env.WINDIR || "C:\\Windows";
122
+ return [path.win32.join(systemRoot, "System32"), systemRoot];
123
+ }
124
+ return ["/opt/homebrew/bin", "/usr/local/bin", "/usr/bin", "/bin", "/usr/sbin", "/sbin"];
125
+ }
126
+
127
+ function buildNodePathEnv({
128
+ execPath = process.execPath,
129
+ pathEnv = process.env.PATH || "",
130
+ platform = process.platform,
131
+ env = process.env,
132
+ } = {}) {
133
+ const nodeBin = path.dirname(execPath);
134
+ const fallback = getDefaultPathFallbacks({ platform, env });
135
+ const seen = new Set();
136
+ return [nodeBin, ...pathEnv.split(path.delimiter), ...fallback]
137
+ .filter(Boolean)
138
+ .filter((part) => {
139
+ if (seen.has(part)) return false;
140
+ seen.add(part);
141
+ return true;
142
+ })
143
+ .join(path.delimiter);
144
+ }
145
+
146
+ function buildNpxMcpEntry(packageName, { execPath = process.execPath, pathEnv = process.env.PATH || "" } = {}) {
147
+ return {
148
+ type: "stdio",
149
+ command: "npx",
150
+ args: ["-y", packageName],
151
+ env: {
152
+ PATH: buildNodePathEnv({ execPath, pathEnv }),
153
+ },
154
+ };
155
+ }
156
+
157
+ function resolveTrtcPushMcpEntry({
158
+ env = process.env,
159
+ execPath = process.execPath,
160
+ existsSync = fs.existsSync,
161
+ } = {}) {
162
+ const fromEnv = env.TRTC_PUSH_MCP_ENTRY || env.TIMPUSH_MCP_ENTRY;
163
+ if (fromEnv && existsSync(fromEnv)) {
164
+ return {
165
+ command: "node",
166
+ args: [path.resolve(fromEnv)],
167
+ source: "env",
168
+ env: { TRTC_PUSH_MCP_REPORT_DISABLED: "1" },
169
+ };
170
+ }
171
+ return {
172
+ ...buildNpxMcpEntry(env.TRTC_PUSH_MCP_PACKAGE || TRTC_PUSH_MCP_PACKAGE, {
173
+ execPath,
174
+ pathEnv: env.PATH || "",
175
+ }),
176
+ source: "npm",
177
+ };
178
+ }
179
+
180
+ function getMcpServersToInstall() {
181
+ const servers = [
182
+ {
183
+ name: MCP_SERVER_NAME,
184
+ entry: buildNpxMcpEntry(MCP_SERVER_ENTRY),
185
+ },
186
+ ];
187
+ const trtcPushMcp = resolveTrtcPushMcpEntry();
188
+ const entry = {
189
+ type: "stdio",
190
+ command: trtcPushMcp.command,
191
+ args: trtcPushMcp.args,
192
+ };
193
+ if (trtcPushMcp.env) entry.env = trtcPushMcp.env;
194
+ const note =
195
+ trtcPushMcp.source === "npm"
196
+ ? `npm → ${trtcPushMcp.args[1]}`
197
+ : `local → ${trtcPushMcp.args[0]}`;
198
+ servers.push({ name: TRTC_PUSH_MCP_NAME, entry, note });
199
+ return servers;
200
+ }
201
+
109
202
  // Hooks distribution targets per IDE.
110
203
  // claude / codebuddy / codex: hooks/ files copied to <root>/.{ide}/hooks/, and
111
204
  // hooks/hooks.json is rewritten + merged into <root>/.{ide}/settings.json.
@@ -156,7 +249,6 @@ const HOOKS_TARGETS = {
156
249
  // PLUGIN_ROOT by walking up to the nearest dir containing skills/, so
157
250
  // this nested location still resolves correctly.
158
251
  hooksDir: ".cursor/hooks/trtc-agent-skills",
159
- hooksFiles: ["cursor-adapter.py"],
160
252
  settingsFile: ".cursor/hooks.json",
161
253
  sourceConfig: "hooks-cursor.json",
162
254
  // The hardcoded path string we need to rewrite in hooks-cursor.json.
@@ -170,11 +262,13 @@ const HOOKS_TARGETS = {
170
262
  // one of these path-segment hints — every guardrail script we ship lives under
171
263
  // `skills/<skill>/hooks/` or `skills/<skill>/guardrails/`, and the cursor
172
264
  // adapter under our namespaced hooks subdir.
265
+ // NOTE: trtc-topic and trtc-apply are no longer in SKILL_ALLOWLIST, but their
266
+ // hints are kept here so --clean can remove hook entries left by older installs.
173
267
  const OWNED_COMMAND_HINTS = [
174
268
  "/skills/trtc/hooks/",
175
269
  "/skills/trtc/room-builder/guardrails/",
176
- "/skills/trtc-topic/guardrails/",
177
- "/skills/trtc-apply/guardrails/",
270
+ "/skills/trtc-topic/guardrails/", // legacy — removed from allowlist, kept for cleanup
271
+ "/skills/trtc-apply/guardrails/", // legacy — removed from allowlist, kept for cleanup
178
272
  "/skills/trtc-conference/hooks/",
179
273
  "/hooks/trtc-agent-skills/cursor-adapter.py",
180
274
  ];
@@ -249,6 +343,30 @@ function isSymlink(p) {
249
343
  catch { return false; }
250
344
  }
251
345
 
346
+ // Local checkout install (npx from sibling / `node bin/cli.js` inside this repo)
347
+ // should symlink skills so edits under skills/ are live in IDE skill roots.
348
+ // Opt out with TRTC_SKILLS_COPY=1; force on with TRTC_SKILLS_SYMLINK=1.
349
+ function shouldSymlinkSkills(skillsRootAbs, resolvedRoot) {
350
+ if (process.env.TRTC_SKILLS_COPY === "1") return false;
351
+ if (process.env.TRTC_SKILLS_SYMLINK === "1") return true;
352
+ const pkg = path.resolve(PKG_ROOT);
353
+ const root = path.resolve(resolvedRoot);
354
+ const skillsRoot = path.resolve(skillsRootAbs);
355
+ return root === pkg || skillsRoot.startsWith(pkg + path.sep);
356
+ }
357
+
358
+ function installSkillDir(src, dest, { symlink }) {
359
+ rmrf(dest);
360
+ if (symlink) {
361
+ ensureDir(path.dirname(dest));
362
+ const rel = path.relative(path.dirname(dest), src);
363
+ fs.symlinkSync(rel || src, dest, "dir");
364
+ return "symlink";
365
+ }
366
+ copyRecursive(src, dest);
367
+ return "copy";
368
+ }
369
+
252
370
  // ── project root resolution ───────────────────────────────────────────────────
253
371
  // Walk UP from cwd for strong repo-root signals (P1 monorepo manifest,
254
372
  // P2 package.json workspaces, P3 .git). Otherwise P4 cwd-local package.json,
@@ -343,7 +461,7 @@ function printHelp() {
343
461
  ${c.dim("KB :")} ${c.gray("alongside the skills root as knowledge-base/")}
344
462
  ${c.dim("Hooks :")} ${c.gray("<projectRoot>/.{ide}/hooks/ + settings file with hook events wired")}
345
463
  ${c.dim("Rules :")} ${c.gray("CLAUDE.md / AGENTS.md / CODEBUDDY.md (marker-merged)")}
346
- ${c.dim("MCP :")} ${c.gray("tencent-rtc-skill-tool IDE mcp config (npx @tencent-rtc/skill-tool@latest)")}
464
+ ${c.dim("MCP :")} ${c.gray("tencent-rtc-skill-tool + npm trtc-push-mcp (local only with TRTC_PUSH_MCP_ENTRY)")}
347
465
 
348
466
  ${c.dim("Skills are copied as sibling dirs so relative routing (../trtc-onboarding) keeps working.")}
349
467
  `);
@@ -351,13 +469,13 @@ function printHelp() {
351
469
 
352
470
  function listSkills() {
353
471
  const descriptions = {
354
- "trtc": "Entry router — detects product/platform, routes to sub-skills",
355
- "trtc-ai-service": "AI customer service scenarios (TRTC Conversational AI)",
356
- "trtc-onboarding": "Get-started / integration / troubleshooting flow",
357
- "trtc-docs": "Docs & error-code lookup",
358
- "trtc-topic": "Step-by-step scenario walkthrough",
359
- "trtc-search": "Internal slice lookup (AI-facing)",
360
- "trtc-apply": "Internal compile/integration quality gate",
472
+ "trtc": "Entry router — detects product/platform, routes to sub-skills",
473
+ "trtc-docs": "Docs & error-code lookup",
474
+ "trtc-conference": "Video conference / multi-person room scenarios",
475
+ "trtc-ai-service": "AI customer service scenarios (TRTC Conversational AI)",
476
+ "trtc-ai-oral-coach": "AI oral speaking coach / 口语陪练 (TRTC Conversational AI)",
477
+ "trtc-chat": "IM / Chat SDK integration",
478
+ "trtc-push": "TIMPush offline push integration (via trtc-push-mcp)",
361
479
  };
362
480
  console.log(`\n ${c.bold("Skills shipped in this package:")}\n`);
363
481
  for (const name of getSkillNames()) {
@@ -368,7 +486,7 @@ function listSkills() {
368
486
  }
369
487
 
370
488
  // ── core: skill install ─────────────────────────────────────────────────────────
371
- function cleanSkills(skillsRootAbs) {
489
+ function cleanSkills(skillsRootAbs, ide) {
372
490
  if (!fs.existsSync(skillsRootAbs)) return 0;
373
491
  let wiped = 0;
374
492
  for (const name of getSkillNames()) {
@@ -378,9 +496,15 @@ function cleanSkills(skillsRootAbs) {
378
496
  // also wipe a co-located knowledge-base copy if present
379
497
  const kb = path.join(path.dirname(skillsRootAbs), "knowledge-base");
380
498
  if (fs.existsSync(kb)) { rmrf(kb); }
381
- // also wipe a co-located hooks/ copy if present (npx-mode hook scripts)
382
- const hooks = path.join(path.dirname(skillsRootAbs), "hooks");
383
- if (fs.existsSync(hooks)) { rmrf(hooks); }
499
+ // Wipe only our exact hooks dir (not the IDE's hooks/ parent). For cursor
500
+ // this is the namespaced .cursor/hooks/trtc-agent-skills/ subdir; for other
501
+ // IDEs it coincides with the parent .{ide}/hooks/ dir.
502
+ const hooksTarget = HOOKS_TARGETS[ide];
503
+ const resolvedRoot = path.dirname(path.dirname(skillsRootAbs));
504
+ const hooksDir = hooksTarget
505
+ ? path.join(resolvedRoot, hooksTarget.hooksDir)
506
+ : path.join(path.dirname(skillsRootAbs), "hooks");
507
+ if (fs.existsSync(hooksDir)) { rmrf(hooksDir); }
384
508
  return wiped;
385
509
  }
386
510
 
@@ -462,14 +586,17 @@ function cleanHooksSettings(ideList, resolvedRoot) {
462
586
  }
463
587
  }
464
588
 
465
- function installSkills(skillsRootAbs) {
589
+ function installSkills(skillsRootAbs, resolvedRoot) {
466
590
  ensureDir(skillsRootAbs);
591
+ const symlink = shouldSymlinkSkills(skillsRootAbs, resolvedRoot);
592
+ const modes = [];
467
593
  for (const name of getSkillNames()) {
468
594
  const src = path.join(SKILLS_SRC, name);
469
- if (fs.existsSync(src)) {
470
- copyRecursive(src, path.join(skillsRootAbs, name));
471
- }
595
+ if (!fs.existsSync(src)) continue;
596
+ const mode = installSkillDir(src, path.join(skillsRootAbs, name), { symlink });
597
+ modes.push({ name, mode });
472
598
  }
599
+ return { symlink, modes };
473
600
  }
474
601
 
475
602
  // Copy knowledge-base so that skills can resolve it. Skills use
@@ -712,11 +839,7 @@ function installAiInstructions(ideList, resolvedRoot) {
712
839
 
713
840
  // ── MCP installation ──────────────────────────────────────────────────────────
714
841
  function installMcp(ideList, resolvedRoot) {
715
- const serverEntry = {
716
- type: "stdio",
717
- command: "npx",
718
- args: ["-y", MCP_SERVER_ENTRY],
719
- };
842
+ const servers = getMcpServersToInstall();
720
843
 
721
844
  for (const ide of ideList) {
722
845
  const mcpTarget = MCP_TARGETS[ide];
@@ -728,7 +851,9 @@ function installMcp(ideList, resolvedRoot) {
728
851
  ensureDir(path.dirname(configPath));
729
852
 
730
853
  if (mcpTarget.format === "toml") {
731
- installMcpToml(configPath, serverEntry);
854
+ for (const server of servers) {
855
+ installMcpToml(configPath, server.name, server.entry);
856
+ }
732
857
  } else {
733
858
  let config = {};
734
859
  if (fs.existsSync(configPath)) {
@@ -738,27 +863,39 @@ function installMcp(ideList, resolvedRoot) {
738
863
  if (!config.mcpServers || typeof config.mcpServers !== "object") {
739
864
  config.mcpServers = {};
740
865
  }
741
- config.mcpServers[MCP_SERVER_NAME] = serverEntry;
866
+ for (const server of servers) {
867
+ config.mcpServers[server.name] = server.entry;
868
+ }
742
869
  fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf8");
743
870
  }
744
- console.log(c.green(" ✓ ") + `${ide} MCP → ${configPath}`);
871
+ const labels = servers
872
+ .map(s => s.name + (s.note ? ` (${s.note})` : ""))
873
+ .join(", ");
874
+ console.log(c.green(" ✓ ") + `${ide} MCP → ${configPath}` + c.dim(` [${labels}]`));
745
875
  }
746
876
  }
747
877
 
748
- function installMcpToml(configPath, serverEntry) {
878
+ function installMcpToml(configPath, serverName, serverEntry) {
749
879
  let content = fs.existsSync(configPath) ? fs.readFileSync(configPath, "utf8") : "";
750
880
 
751
- const sectionHeader = `[mcp_servers.${MCP_SERVER_NAME}]`;
881
+ const sectionHeader = `[mcp_servers.${serverName}]`;
752
882
  const argsValue = JSON.stringify(serverEntry.args).replace(/,/g, ", ");
753
- const newSection = [
883
+ const lines = [
754
884
  sectionHeader,
755
885
  `command = "${serverEntry.command}"`,
756
886
  `args = ${argsValue}`,
757
- ].join("\n") + "\n";
887
+ ];
888
+ if (serverEntry.env && typeof serverEntry.env === "object") {
889
+ for (const [k, v] of Object.entries(serverEntry.env)) {
890
+ lines.push(`[mcp_servers.${serverName}.env]`);
891
+ lines.push(`${k} = "${String(v).replace(/"/g, '\\"')}"`);
892
+ }
893
+ }
894
+ const newSection = lines.join("\n") + "\n";
758
895
 
759
- const escapedName = MCP_SERVER_NAME.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
896
+ const escapedName = serverName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
760
897
  const sectionRegex = new RegExp(
761
- `\\[mcp_servers\\.${escapedName}\\]\\n(?:(?!\\[)[^\\n]*\\n)*`,
898
+ `\\[mcp_servers\\.${escapedName}\\](?:\\.[^\\]\\n]+)?\\n(?:(?!\\[)[^\\n]*\\n)*`,
762
899
  "g"
763
900
  );
764
901
  content = content.replace(sectionRegex, "");
@@ -782,7 +919,7 @@ function installClaudePermissions(ideList, resolvedRoot) {
782
919
  if (!settings.permissions || typeof settings.permissions !== "object") settings.permissions = {};
783
920
  if (!Array.isArray(settings.permissions.allow)) settings.permissions.allow = [];
784
921
 
785
- const rules = [`mcp__${MCP_SERVER_NAME}__*`];
922
+ const rules = [`mcp__${MCP_SERVER_NAME}__*`, `mcp__${TRTC_PUSH_MCP_NAME}__*`];
786
923
  const added = rules.filter(r => !settings.permissions.allow.includes(r));
787
924
  if (added.length > 0) {
788
925
  settings.permissions.allow.push(...added);
@@ -808,9 +945,13 @@ function installCursorPermissions(ideList, resolvedRoot) {
808
945
  }
809
946
  if (!Array.isArray(perms.mcpAllowlist)) perms.mcpAllowlist = [];
810
947
 
811
- const rule = `${MCP_SERVER_NAME}:skill_analysis`;
812
- if (!perms.mcpAllowlist.includes(rule)) {
813
- perms.mcpAllowlist.push(rule);
948
+ const rules = [
949
+ `${MCP_SERVER_NAME}:skill_analysis`,
950
+ `${TRTC_PUSH_MCP_NAME}:*`,
951
+ ];
952
+ const added = rules.filter(r => !perms.mcpAllowlist.includes(r));
953
+ if (added.length > 0) {
954
+ perms.mcpAllowlist.push(...added);
814
955
  fs.writeFileSync(permPath, JSON.stringify(perms, null, 2) + "\n", "utf8");
815
956
  console.log(c.green(" ✓ ") + `cursor permissions → ${permPath}`);
816
957
  } else {
@@ -912,12 +1053,15 @@ function main() {
912
1053
  console.log(` ${c.bold(ide)} ${c.gray("→ " + skillsRootAbs + "/")}`);
913
1054
 
914
1055
  if (isClean) {
915
- const wiped = cleanSkills(skillsRootAbs);
1056
+ const wiped = cleanSkills(skillsRootAbs, ide);
916
1057
  if (wiped > 0) console.log(c.dim(` ✓ cleaned ${wiped} existing skill ${wiped === 1 ? "entry" : "entries"}`));
917
1058
  }
918
1059
 
919
- installSkills(skillsRootAbs);
920
- for (const name of getSkillNames()) console.log(c.green(" ✓ ") + name + "/");
1060
+ const { modes } = installSkills(skillsRootAbs, resolvedRoot);
1061
+ for (const { name, mode } of modes) {
1062
+ const tag = mode === "symlink" ? c.dim(" (symlink → skills/" + name + ")") : "";
1063
+ console.log(c.green(" ✓ ") + name + "/" + tag);
1064
+ }
921
1065
 
922
1066
  const kbDest = copyKnowledgeBase(skillsRootAbs);
923
1067
  console.log(c.green(" ✓ ") + "knowledge-base/ " + c.dim("→ " + kbDest));
@@ -945,10 +1089,20 @@ function main() {
945
1089
  console.log(`\n ${c.bold("Done.")} ${c.dim("Just describe what you want to build in your IDE — the skill activates automatically.")}\n`);
946
1090
  }
947
1091
 
948
- try {
949
- main();
950
- } catch (err) {
951
- console.error(c.red(`\n Error: ${err.message || err}\n`));
952
- if (err.stack && process.env.DEBUG) console.error(c.dim(err.stack) + "\n");
953
- process.exit(1);
1092
+ module.exports = {
1093
+ getDefaultPathFallbacks,
1094
+ buildNodePathEnv,
1095
+ buildNpxMcpEntry,
1096
+ resolveTrtcPushMcpEntry,
1097
+ getMcpServersToInstall,
1098
+ };
1099
+
1100
+ if (require.main === module) {
1101
+ try {
1102
+ main();
1103
+ } catch (err) {
1104
+ console.error(c.red(`\n Error: ${err.message || err}\n`));
1105
+ if (err.stack && process.env.DEBUG) console.error(c.dim(err.stack) + "\n");
1106
+ process.exit(1);
1107
+ }
954
1108
  }
@@ -107,20 +107,20 @@ slices:
107
107
 
108
108
  - id: conference/official-roomkit-api
109
109
  name: 官方 RoomKit 适配层 API
110
- keywords: [roomkit, tuiroomkit, tui-roomkit, conference-api]
110
+ keywords: [roomkit, tuiroomkit, tui-roomkit, conference-api, react, vue3, roomkit-web-react]
111
111
  tags: [official-roomkit, conference-api, conference-object, setWidgetVisible, registerWidget,
112
- onWill, setFeatureConfig, createAndJoinRoom, joinRoom, UIKitProvider]
112
+ onWill, setFeatureConfig, createAndJoinRoom, joinRoom, UIKitProvider, React, Vue3]
113
113
  file: slices/conference/web/official-roomkit-api.md
114
114
  description: >
115
- 官方 RoomKit 集成模式下 conference 对象的完整 API 签名、枚举定义、调用时序和代码示例
115
+ 官方 RoomKit 集成模式下 Vue3 / React conference 对象的完整 API 签名、枚举定义、调用时序和代码示例
116
116
  (ui_mode=official-roomkit 专用)
117
117
 
118
118
  - id: conference/official-roomkit-login-ui
119
119
  name: 官方 RoomKit 登录 UI
120
- keywords: [roomkit, login-ui, tuiroomkit]
121
- tags: [official-roomkit, login-ui, layout, form, UIKitProvider, LoginPanel]
120
+ keywords: [roomkit, login-ui, tuiroomkit, react, vue3]
121
+ tags: [official-roomkit, login-ui, layout, form, UIKitProvider, LoginPanel, React, Vue3]
122
122
  file: slices/conference/web/official-roomkit-login-ui.md
123
- description: 官方 RoomKit 登录页的布局、表单、凭证提示与状态反馈规范,包括 UIKitProvider 与 LoginPanel 集成约束
123
+ description: 官方 RoomKit 登录页的布局、表单、凭证提示与状态反馈规范,包括 Vue3 / React UIKitProvider 与 LoginPanel 集成约束
124
124
 
125
125
  - id: conference/integration-audit
126
126
  name: Conference Web 集成审计
@@ -4,30 +4,44 @@ platform: web
4
4
  api_docs:
5
5
  - title: 快速接入 Web&H5 (Vue3)
6
6
  url: https://cloud.tencent.com/document/product/647/81962
7
+ - title: 快速接入 Web (React)
8
+ url: https://cloud.tencent.com/document/product/647/132839
7
9
  - title: 界面微调 (Web)
8
10
  url: https://cloud.tencent.com/document/product/647/129842
9
11
  ---
10
12
 
11
13
  # 官方 RoomKit 适配层 API — Web 实现
12
14
 
13
- > 本 slice 覆盖 `@tencentcloud/roomkit-web-vue3` 导出的 `conference` 对象的完整 API。
15
+ > 本 slice 覆盖官方 RoomKit Web 包导出的 `conference` 对象 API。
16
+ > Vue3 项目使用 `@tencentcloud/roomkit-web-vue3`,React 项目使用
17
+ > `@tencentcloud/roomkit-web-react`。两者的 `conference` API 调用时序保持一致。
14
18
  > 当 `ui_mode = official-roomkit` 时,业务侧通过此对象操作会议,
15
- > 而不是直接调用 composablecomposable 层见 `conference/web/room-lifecycle.md` 等)。
19
+ > 而不是直接调用 no-UI hooks/composablesno-UI 层见 `conference/web/room-lifecycle.md` 等)。
16
20
  >
17
- > 以下签名基于 `@tencentcloud/roomkit-web-vue3@5.9.0` 源码验证。
18
- > 源码参考:`RoomKit/adapter/conference.ts` + `RoomKit/adapter/type.ts`。
21
+ > Vue3 签名基于 `@tencentcloud/roomkit-web-vue3@5.9.0` 源码验证;React
22
+ > 签名基于官方 React 快速接入文档与同名导出校验。
19
23
 
20
24
  ## 前置条件
21
25
 
22
- **安装依赖**:
26
+ **安装依赖(按项目框架二选一,不要混装)**:
27
+
28
+ Vue3:
23
29
  ```bash
24
30
  npm install @tencentcloud/roomkit-web-vue3@5 tuikit-atomicx-vue3 \
25
31
  @tencentcloud/uikit-base-component-vue3 @tencentcloud/universal-api
26
32
  ```
27
33
 
28
- **版本要求**:lockfile 中 `@tencentcloud/roomkit-web-vue3` 解析版本必须 `>=5.4.3`。
34
+ React:
35
+ ```bash
36
+ npm install @tencentcloud/roomkit-web-react tuikit-atomicx-react \
37
+ @tencentcloud/uikit-base-component-react @tencentcloud/universal-api
38
+ ```
39
+
40
+ **版本要求**:
41
+ - Vue3:lockfile 中 `@tencentcloud/roomkit-web-vue3` 解析版本必须 `>=5.4.3`。
42
+ - React:使用 `@tencentcloud/roomkit-web-react` 与同版本族的 `tuikit-atomicx-react`。
29
43
 
30
- **导入来源**:
44
+ **导入来源(Vue3)**:
31
45
  ```ts
32
46
  // 会议组件 + conference API + 事件/枚举
33
47
  import {
@@ -43,6 +57,21 @@ import {
43
57
  import { UIKitProvider } from '@tencentcloud/uikit-base-component-vue3'
44
58
  ```
45
59
 
60
+ **导入来源(React)**:
61
+ ```tsx
62
+ // 会议组件 + conference API + 事件/枚举
63
+ import {
64
+ ConferenceMainView,
65
+ conference,
66
+ RoomEvent,
67
+ BuiltinWidget,
68
+ InterceptorAction,
69
+ } from '@tencentcloud/roomkit-web-react'
70
+
71
+ // UIKitProvider(包裹组件用)
72
+ import { UIKitProvider } from '@tencentcloud/uikit-base-component-react'
73
+ ```
74
+
46
75
  ## 枚举定义
47
76
 
48
77
  ```ts
@@ -189,7 +218,7 @@ interface FeatureConfig {
189
218
  7. RoomEvent.ROOM_LEAVE / ROOM_DISMISS 回调 → 清理注销函数
190
219
  ```
191
220
 
192
- ## 完整代码示例
221
+ ## 完整代码示例(Vue3)
193
222
 
194
223
  ```vue
195
224
  <template>
@@ -270,14 +299,93 @@ onUnmounted(() => {
270
299
  </script>
271
300
  ```
272
301
 
302
+ ## 完整代码示例(React)
303
+
304
+ ```tsx
305
+ import { useEffect } from 'react'
306
+ import { useNavigate, useSearchParams } from 'react-router-dom'
307
+ import {
308
+ ConferenceMainView,
309
+ conference,
310
+ RoomEvent,
311
+ BuiltinWidget,
312
+ } from '@tencentcloud/roomkit-web-react'
313
+ import { UIKitProvider } from '@tencentcloud/uikit-base-component-react'
314
+
315
+ export function MeetingRoom() {
316
+ const navigate = useNavigate()
317
+ const [searchParams] = useSearchParams()
318
+
319
+ useEffect(() => {
320
+ const sdkAppId = Number(searchParams.get('sdkAppId'))
321
+ const userId = searchParams.get('userId') || ''
322
+ const userSig = searchParams.get('userSig') || ''
323
+ const roomId = searchParams.get('roomId') || ''
324
+ const cleanupFns: Array<() => void> = []
325
+
326
+ const cleanupRoomListeners = () => {
327
+ conference.off(RoomEvent.ROOM_LEAVE, handleLeave)
328
+ conference.off(RoomEvent.ROOM_DISMISS, handleLeave)
329
+ cleanupFns.forEach((fn) => fn())
330
+ }
331
+
332
+ const handleLeave = () => {
333
+ cleanupRoomListeners()
334
+ navigate('/')
335
+ }
336
+
337
+ const start = async () => {
338
+ if (!sdkAppId || !userId || !userSig || !roomId) {
339
+ navigate('/')
340
+ return
341
+ }
342
+
343
+ await conference.login({ sdkAppId, userId, userSig })
344
+ await conference.setSelfInfo({ userName: userId, avatarUrl: '' })
345
+
346
+ conference.setWidgetVisible({
347
+ [BuiltinWidget.InviteWidget]: false,
348
+ })
349
+
350
+ conference.on(RoomEvent.ROOM_LEAVE, handleLeave)
351
+ conference.on(RoomEvent.ROOM_DISMISS, handleLeave)
352
+
353
+ await conference.createAndJoinRoom({
354
+ roomId,
355
+ options: { roomName: `会议-${roomId}` },
356
+ })
357
+
358
+ conference.setFeatureConfig({
359
+ shareLink: `${window.location.origin}/meeting?roomId=${roomId}`,
360
+ })
361
+ }
362
+
363
+ start().catch(() => navigate('/'))
364
+
365
+ return () => {
366
+ cleanupRoomListeners()
367
+ }
368
+ }, [navigate, searchParams])
369
+
370
+ return (
371
+ <UIKitProvider theme="light" language="zh-CN">
372
+ <ConferenceMainView />
373
+ </UIKitProvider>
374
+ )
375
+ }
376
+ ```
377
+
273
378
  ## 代码生成约束
274
379
 
275
380
  ### MUST
276
381
 
277
382
  1. **使用 UIKitProvider 包裹会议组件** — `ConferenceMainView` / `ConferenceMainViewH5` 必须放在 `UIKitProvider` 内。
383
+ - Vue3:`@tencentcloud/uikit-base-component-vue3`
384
+ - React:`@tencentcloud/uikit-base-component-react`
278
385
  2. **界面微调 API 在 login 之后、进房之前注册** — 避免按钮闪烁或拦截器遗漏。
279
386
  3. **registerWidget / onWill 返回的注销函数必须收集并在 ROOM_LEAVE + ROOM_DISMISS 时清理** — 防止重复注册。
280
387
  4. **shareLink 在进房成功后设置** — 依赖最终确定的 roomId。
388
+ 5. **按项目框架选择包名** — React 项目必须使用 `@tencentcloud/roomkit-web-react` / `tuikit-atomicx-react`,Vue3 项目必须使用 `@tencentcloud/roomkit-web-vue3` / `tuikit-atomicx-vue3`。
281
389
 
282
390
  ### MUST NOT
283
391
 
@@ -286,6 +394,7 @@ onUnmounted(() => {
286
394
  3. **不要给 joinRoom 传 isOpenCamera / isOpenMicrophone** — 只接受 `roomId`、`roomType`、`password`。
287
395
  4. **不要把 shareLink 写成对象** — `setFeatureConfig({ shareLink: '...' })` 是纯字符串。
288
396
  5. **不要用 CSS/DOM hack 修改 RoomKit 内部 UI** — 必须用 `setWidgetVisible` / `registerWidget` / `onWill`。
397
+ 6. **不要在 React 项目中生成 Vue SFC 或 Vue 包导入**;也不要在 Vue3 项目中生成 React JSX / TSX。
289
398
 
290
399
  ## 常见错误速查
291
400
 
@@ -296,3 +405,5 @@ onUnmounted(() => {
296
405
  | `joinRoom({ roomId, isOpenCamera: true })` | `joinRoom({ roomId })` | 无 isOpenCamera 参数 |
297
406
  | `setFeatureConfig({ shareLink: { link, title } })` | `setFeatureConfig({ shareLink: 'url' })` | shareLink 是字符串 |
298
407
  | `import { UIKitProvider } from '@tencentcloud/roomkit-web-vue3'` | `import { UIKitProvider } from '@tencentcloud/uikit-base-component-vue3'` | UIKitProvider 在 peer 包中 |
408
+ | React 项目 `import { ConferenceMainView } from '@tencentcloud/roomkit-web-vue3'` | `import { ConferenceMainView } from '@tencentcloud/roomkit-web-react'` | React 与 Vue3 包名不同 |
409
+ | React 项目 `import { useRoomState } from 'tuikit-atomicx-vue3/room'` | `import { useRoomState } from 'tuikit-atomicx-react/room'` | React no-UI hooks 使用 React 包 |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tencent-rtc/trtc-agent-skills",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "Installer for the TRTC Agent Skills suite (Chat, Call, RTC Engine, Live, Conference) + knowledge base, with one-command MCP setup for Claude Code / Cursor / CodeBuddy / Codex.",
5
5
  "bin": {
6
6
  "trtc-agent-skills": "bin/cli.js"