@tencent-rtc/trtc-agent-skills 0.1.3 → 0.1.4

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 (360) hide show
  1. package/.cursor/rules/main.mdc +12 -0
  2. package/AGENTS.md +14 -104
  3. package/CLAUDE.md +15 -127
  4. package/CODEBUDDY.md +32 -118
  5. package/README.md +7 -5
  6. package/README.zh.md +7 -5
  7. package/bin/cli.js +133 -41
  8. package/hooks/__pycache__/cursor-adapter.cpython-313.pyc +0 -0
  9. package/hooks/cursor-adapter.py +45 -18
  10. package/hooks/hooks-cursor.json +5 -18
  11. package/hooks/hooks.json +6 -31
  12. package/knowledge-base/conference/web/index.yaml +143 -0
  13. package/knowledge-base/platform-slice-template.md +1041 -133
  14. package/knowledge-base/products.yaml +76 -0
  15. package/knowledge-base/scenario-spec.md +1316 -115
  16. package/knowledge-base/scenarios/conference/base/general-conference.md +22 -2
  17. package/knowledge-base/scenarios/conference/base/webinar-conference.md +14 -0
  18. package/knowledge-base/scenarios/conference/medical/1v1-video-consultation.md +19 -0
  19. package/knowledge-base/scenarios/conference/medical/medical-multidoctor-consultation.md +13 -0
  20. package/knowledge-base/scenarios/live/entertainment-live-room.md +12 -0
  21. package/knowledge-base/slice-spec.md +2377 -299
  22. package/knowledge-base/slices/conference/web/integration-audit.md +1 -1
  23. package/knowledge-base/slices/conference/web/login-auth.md +14 -1
  24. package/knowledge-base/tooling/aliases.yaml +92 -0
  25. package/knowledge-base/tooling/intent-signals.yaml +181 -0
  26. package/knowledge-base/tooling/symptom-keywords.yaml +21 -0
  27. package/package.json +1 -1
  28. package/skills/trtc/SKILL.md +202 -245
  29. package/skills/trtc/hooks/__pycache__/report_prompt.cpython-313.pyc +0 -0
  30. package/skills/{trtc-topic/guardrails → trtc/hooks}/gate_slice_read.py +12 -8
  31. package/skills/{trtc-topic/guardrails → trtc/hooks}/gate_slice_write.py +16 -12
  32. package/skills/{trtc-topic/guardrails → trtc/hooks}/stop_require_apply_evidence.py +22 -14
  33. package/skills/trtc/hooks/topic_phase_gate.py +161 -0
  34. package/skills/{trtc-topic → trtc}/runtime/README.md +2 -2
  35. package/skills/{trtc-onboarding/reference/reporting-protocol.md → trtc/runtime/REPORTING.md} +5 -5
  36. package/skills/{trtc-topic → trtc}/runtime/RUNTIME.md +5 -5
  37. package/skills/trtc/runtime/lib/__init__.py +0 -0
  38. package/skills/{trtc-topic → trtc}/runtime/package-lock.json +2 -2
  39. package/skills/{trtc-topic → trtc}/runtime/package.json +2 -2
  40. package/skills/{trtc-topic → trtc}/runtime/telemetry-bridge.mjs +1 -1
  41. package/skills/{trtc-topic/scripts → trtc/tools}/STATE-MACHINE-GUIDE.md +23 -23
  42. package/skills/trtc/tools/__init__.py +2 -0
  43. package/skills/trtc/tools/__pycache__/__init__.cpython-313.pyc +0 -0
  44. package/skills/trtc/tools/__pycache__/query_classifier.cpython-313.pyc +0 -0
  45. package/skills/trtc/tools/__pycache__/reporting.cpython-313.pyc +0 -0
  46. package/skills/trtc/tools/__pycache__/search.cpython-313.pyc +0 -0
  47. package/skills/trtc/tools/__pycache__/session.cpython-313.pyc +0 -0
  48. package/skills/trtc/tools/apply.py +540 -0
  49. package/skills/trtc/tools/docs.py +712 -0
  50. package/skills/trtc/tools/docsbot.py +182 -0
  51. package/skills/trtc/tools/entry/render_ai_instructions.py +92 -0
  52. package/skills/trtc/tools/flow.py +1089 -0
  53. package/skills/{trtc-topic/scripts → trtc/tools}/init_slice_queue.py +5 -4
  54. package/skills/{trtc-topic/scripts → trtc/tools}/next_slice.py +5 -4
  55. package/skills/trtc/tools/query_classifier.py +301 -0
  56. package/skills/trtc/tools/reporting.py +447 -0
  57. package/skills/trtc/tools/search.py +817 -0
  58. package/skills/trtc/tools/session.py +1261 -0
  59. package/skills/trtc/tools/state_machine.py +690 -0
  60. package/skills/trtc-ai-service/README.md +195 -0
  61. package/skills/trtc-ai-service/README.zh-CN.md +193 -0
  62. package/skills/trtc-ai-service/SKILL.md +945 -0
  63. package/skills/trtc-ai-service/auto_adapters/README.md +40 -0
  64. package/skills/trtc-ai-service/auto_adapters/frontend-spa/README.md +27 -0
  65. package/skills/trtc-ai-service/auto_adapters/frontend-spa/angular/voice-agent.component.ts.tpl +131 -0
  66. package/skills/trtc-ai-service/auto_adapters/frontend-spa/manifest.yaml +57 -0
  67. package/skills/trtc-ai-service/auto_adapters/frontend-spa/react/VoiceAgent.tsx.tpl +142 -0
  68. package/skills/trtc-ai-service/auto_adapters/frontend-spa/vue/VoiceAgent.vue.tpl +121 -0
  69. package/skills/trtc-ai-service/auto_adapters/integration_templates/generic-backend.md +45 -0
  70. package/skills/trtc-ai-service/auto_adapters/integration_templates/generic-frontend.md +51 -0
  71. package/skills/trtc-ai-service/auto_adapters/integration_templates/generic-rest-api.md +93 -0
  72. package/skills/trtc-ai-service/auto_adapters/java-backend/README.md +25 -0
  73. package/skills/trtc-ai-service/auto_adapters/java-backend/manifest.yaml +30 -0
  74. package/skills/trtc-ai-service/auto_adapters/java-backend/quarkus/VoiceAgentFilter.java.tpl +64 -0
  75. package/skills/trtc-ai-service/auto_adapters/java-backend/springboot/VoiceAgentFilter.java.tpl +91 -0
  76. package/skills/trtc-ai-service/auto_adapters/manifest.yaml +43 -0
  77. package/skills/trtc-ai-service/auto_adapters/node-backend/README.md +25 -0
  78. package/skills/trtc-ai-service/auto_adapters/node-backend/express.js.tpl +40 -0
  79. package/skills/trtc-ai-service/auto_adapters/node-backend/fastify.js.tpl +27 -0
  80. package/skills/trtc-ai-service/auto_adapters/node-backend/koa.js.tpl +31 -0
  81. package/skills/trtc-ai-service/auto_adapters/node-backend/manifest.yaml +47 -0
  82. package/skills/trtc-ai-service/auto_adapters/python-backend/README.md +22 -0
  83. package/skills/trtc-ai-service/auto_adapters/python-backend/django.py.tpl +32 -0
  84. package/skills/trtc-ai-service/auto_adapters/python-backend/fastapi.py.tpl +35 -0
  85. package/skills/trtc-ai-service/auto_adapters/python-backend/flask.py.tpl +31 -0
  86. package/skills/trtc-ai-service/auto_adapters/python-backend/manifest.yaml +45 -0
  87. package/skills/trtc-ai-service/capabilities/__init__.py +43 -0
  88. package/skills/trtc-ai-service/capabilities/conversation-core/.env.example +29 -0
  89. package/skills/trtc-ai-service/capabilities/conversation-core/INTEGRATION.md +134 -0
  90. package/skills/trtc-ai-service/capabilities/conversation-core/INTERFACE_ADAPT.md +111 -0
  91. package/skills/trtc-ai-service/capabilities/conversation-core/QUICK_START.md +62 -0
  92. package/skills/trtc-ai-service/capabilities/conversation-core/manifest.yaml +250 -0
  93. package/skills/trtc-ai-service/capabilities/conversation-core/requirements.txt +6 -0
  94. package/skills/trtc-ai-service/capabilities/conversation-core/src/__init__.py +10 -0
  95. package/skills/trtc-ai-service/capabilities/conversation-core/src/_capability_loader.py +218 -0
  96. package/skills/trtc-ai-service/capabilities/conversation-core/src/agent.py +231 -0
  97. package/skills/trtc-ai-service/capabilities/conversation-core/src/credentials.py +132 -0
  98. package/skills/trtc-ai-service/capabilities/conversation-core/src/health.py +355 -0
  99. package/skills/trtc-ai-service/capabilities/conversation-core/src/log_filter.py +76 -0
  100. package/skills/trtc-ai-service/capabilities/conversation-core/src/modality.py +109 -0
  101. package/skills/trtc-ai-service/capabilities/conversation-core/src/server.py +312 -0
  102. package/skills/trtc-ai-service/capabilities/conversation-core/src/trtc_client.py +315 -0
  103. package/skills/trtc-ai-service/capabilities/conversation-core/src/usersig.py +90 -0
  104. package/skills/trtc-ai-service/capabilities/conversation-core/tests/test_skeleton.py +216 -0
  105. package/skills/trtc-ai-service/capabilities/conversation-core/web-demo/README.md +48 -0
  106. package/skills/trtc-ai-service/capabilities/conversation-core/web-demo/app.js +415 -0
  107. package/skills/trtc-ai-service/capabilities/conversation-core/web-demo/index.html +68 -0
  108. package/skills/trtc-ai-service/capabilities/conversation-core/web-demo/styles.css +136 -0
  109. package/skills/trtc-ai-service/capabilities/digital-human/README.md +31 -0
  110. package/skills/trtc-ai-service/capabilities/digital-human/manifest.yaml +64 -0
  111. package/skills/trtc-ai-service/capabilities/digital-human/src/__init__.py +2 -0
  112. package/skills/trtc-ai-service/capabilities/digital-human/src/router.py +43 -0
  113. package/skills/trtc-ai-service/capabilities/human-handoff/INTERFACE_ADAPT.md +353 -0
  114. package/skills/trtc-ai-service/capabilities/human-handoff/README.md +44 -0
  115. package/skills/trtc-ai-service/capabilities/human-handoff/manifest.yaml +227 -0
  116. package/skills/trtc-ai-service/capabilities/human-handoff/src/__init__.py +2 -0
  117. package/skills/trtc-ai-service/capabilities/human-handoff/src/adapters/__init__.py +9 -0
  118. package/skills/trtc-ai-service/capabilities/human-handoff/src/adapters/default_rest.py +242 -0
  119. package/skills/trtc-ai-service/capabilities/human-handoff/src/adapters/factory.py +89 -0
  120. package/skills/trtc-ai-service/capabilities/human-handoff/src/adapters/local_queue.py +258 -0
  121. package/skills/trtc-ai-service/capabilities/human-handoff/src/adapters/mock.py +132 -0
  122. package/skills/trtc-ai-service/capabilities/human-handoff/src/core/__init__.py +25 -0
  123. package/skills/trtc-ai-service/capabilities/human-handoff/src/core/intent_detector.py +75 -0
  124. package/skills/trtc-ai-service/capabilities/human-handoff/src/core/models.py +163 -0
  125. package/skills/trtc-ai-service/capabilities/human-handoff/src/core/service.py +192 -0
  126. package/skills/trtc-ai-service/capabilities/human-handoff/src/feedback_store.py +54 -0
  127. package/skills/trtc-ai-service/capabilities/human-handoff/src/ports/__init__.py +4 -0
  128. package/skills/trtc-ai-service/capabilities/human-handoff/src/ports/handoff_client.py +86 -0
  129. package/skills/trtc-ai-service/capabilities/human-handoff/src/queue.py +62 -0
  130. package/skills/trtc-ai-service/capabilities/human-handoff/src/router.py +201 -0
  131. package/skills/trtc-ai-service/capabilities/human-handoff/src/summary_link.py +77 -0
  132. package/skills/trtc-ai-service/capabilities/human-handoff/src/trigger.py +25 -0
  133. package/skills/trtc-ai-service/capabilities/knowledge-base/INTERFACE_ADAPT.md +297 -0
  134. package/skills/trtc-ai-service/capabilities/knowledge-base/README.md +51 -0
  135. package/skills/trtc-ai-service/capabilities/knowledge-base/data/faq.json +20 -0
  136. package/skills/trtc-ai-service/capabilities/knowledge-base/manifest.yaml +211 -0
  137. package/skills/trtc-ai-service/capabilities/knowledge-base/src/__init__.py +8 -0
  138. package/skills/trtc-ai-service/capabilities/knowledge-base/src/adapters/__init__.py +9 -0
  139. package/skills/trtc-ai-service/capabilities/knowledge-base/src/adapters/default_rest.py +209 -0
  140. package/skills/trtc-ai-service/capabilities/knowledge-base/src/adapters/factory.py +86 -0
  141. package/skills/trtc-ai-service/capabilities/knowledge-base/src/adapters/local_json.py +172 -0
  142. package/skills/trtc-ai-service/capabilities/knowledge-base/src/adapters/mock.py +91 -0
  143. package/skills/trtc-ai-service/capabilities/knowledge-base/src/core/__init__.py +12 -0
  144. package/skills/trtc-ai-service/capabilities/knowledge-base/src/core/models.py +77 -0
  145. package/skills/trtc-ai-service/capabilities/knowledge-base/src/core/scoring.py +73 -0
  146. package/skills/trtc-ai-service/capabilities/knowledge-base/src/core/service.py +78 -0
  147. package/skills/trtc-ai-service/capabilities/knowledge-base/src/ports/__init__.py +4 -0
  148. package/skills/trtc-ai-service/capabilities/knowledge-base/src/ports/kb_client.py +61 -0
  149. package/skills/trtc-ai-service/capabilities/knowledge-base/src/retriever.py +56 -0
  150. package/skills/trtc-ai-service/capabilities/knowledge-base/src/router.py +85 -0
  151. package/skills/trtc-ai-service/capabilities/session-summary/INTERFACE_ADAPT.md +99 -0
  152. package/skills/trtc-ai-service/capabilities/session-summary/README.md +47 -0
  153. package/skills/trtc-ai-service/capabilities/session-summary/data/test_session.json +18 -0
  154. package/skills/trtc-ai-service/capabilities/session-summary/manifest.yaml +165 -0
  155. package/skills/trtc-ai-service/capabilities/session-summary/src/__init__.py +2 -0
  156. package/skills/trtc-ai-service/capabilities/session-summary/src/adapters/__init__.py +5 -0
  157. package/skills/trtc-ai-service/capabilities/session-summary/src/adapters/base.py +31 -0
  158. package/skills/trtc-ai-service/capabilities/session-summary/src/adapters/default_rest.py +67 -0
  159. package/skills/trtc-ai-service/capabilities/session-summary/src/adapters/factory.py +51 -0
  160. package/skills/trtc-ai-service/capabilities/session-summary/src/adapters/local_json.py +42 -0
  161. package/skills/trtc-ai-service/capabilities/session-summary/src/adapters/mock.py +22 -0
  162. package/skills/trtc-ai-service/capabilities/session-summary/src/recorder.py +210 -0
  163. package/skills/trtc-ai-service/capabilities/session-summary/src/router.py +93 -0
  164. package/skills/trtc-ai-service/capabilities/session-summary/src/summarizer.py +163 -0
  165. package/skills/trtc-ai-service/capabilities/tool-calling/INTERFACE_ADAPT.md +158 -0
  166. package/skills/trtc-ai-service/capabilities/tool-calling/README.md +50 -0
  167. package/skills/trtc-ai-service/capabilities/tool-calling/data/tools.yaml +58 -0
  168. package/skills/trtc-ai-service/capabilities/tool-calling/examples/__init__.py +1 -0
  169. package/skills/trtc-ai-service/capabilities/tool-calling/examples/local_tools.py +101 -0
  170. package/skills/trtc-ai-service/capabilities/tool-calling/manifest.yaml +146 -0
  171. package/skills/trtc-ai-service/capabilities/tool-calling/src/__init__.py +8 -0
  172. package/skills/trtc-ai-service/capabilities/tool-calling/src/dispatcher.py +54 -0
  173. package/skills/trtc-ai-service/capabilities/tool-calling/src/registry.py +219 -0
  174. package/skills/trtc-ai-service/capabilities/tool-calling/src/router.py +50 -0
  175. package/skills/trtc-ai-service/references/business-contract-spec.md +263 -0
  176. package/skills/trtc-ai-service/scenarios/custom-builder/README.md +86 -0
  177. package/skills/trtc-ai-service/scenarios/custom-builder/output-templates/recipe.yaml.j2 +194 -0
  178. package/skills/trtc-ai-service/scenarios/custom-builder/prompts/q1-business-scenario.md +43 -0
  179. package/skills/trtc-ai-service/scenarios/custom-builder/prompts/q2-io-modality.md +57 -0
  180. package/skills/trtc-ai-service/scenarios/custom-builder/prompts/q3-ui-form.md +55 -0
  181. package/skills/trtc-ai-service/scenarios/custom-builder/prompts/q4-capabilities.md +78 -0
  182. package/skills/trtc-ai-service/scenarios/customer-service/README.md +114 -0
  183. package/skills/trtc-ai-service/scenarios/customer-service/recipe.yaml +154 -0
  184. package/skills/trtc-ai-service/scenarios/customer-service/sample-data/README.md +32 -0
  185. package/skills/trtc-ai-service/scenarios/customer-service/sample-data/faq-sample.json +37 -0
  186. package/skills/trtc-ai-service/scenarios/customer-service/system-prompt.template.md +94 -0
  187. package/skills/trtc-ai-service/scenarios/customer-service/ui/admin-board/app.js +347 -0
  188. package/skills/trtc-ai-service/scenarios/customer-service/ui/admin-board/index.html +125 -0
  189. package/skills/trtc-ai-service/scenarios/customer-service/ui/admin-board/styles.css +487 -0
  190. package/skills/trtc-ai-service/scenarios/customer-service/ui/admin-board/tokens.css +71 -0
  191. package/skills/trtc-ai-service/scenarios/customer-service/ui/design-system/DESIGN_GUIDELINES.md +370 -0
  192. package/skills/trtc-ai-service/scenarios/customer-service/ui/voice-customer-service/README.md +68 -0
  193. package/skills/trtc-ai-service/scenarios/customer-service/ui/voice-customer-service/app.js +1307 -0
  194. package/skills/trtc-ai-service/scenarios/customer-service/ui/voice-customer-service/data.js +40 -0
  195. package/skills/trtc-ai-service/scenarios/customer-service/ui/voice-customer-service/index.html +233 -0
  196. package/skills/trtc-ai-service/scenarios/customer-service/ui/voice-customer-service/mock-shop.json +21 -0
  197. package/skills/trtc-ai-service/scenarios/customer-service/ui/voice-customer-service/styles.css +603 -0
  198. package/skills/trtc-ai-service/scenarios/customer-service/ui/voice-customer-service/tokens.css +71 -0
  199. package/skills/trtc-ai-service/scenarios/customer-service/ui/widget-floating/agent-link.js +323 -0
  200. package/skills/trtc-ai-service/scenarios/customer-service/ui/widget-floating/app.js +458 -0
  201. package/skills/trtc-ai-service/scenarios/customer-service/ui/widget-floating/index.html +109 -0
  202. package/skills/trtc-ai-service/scenarios/customer-service/ui/widget-floating/styles.css +489 -0
  203. package/skills/trtc-ai-service/scenarios/customer-service/ui/widget-floating/tokens.css +59 -0
  204. package/skills/trtc-ai-service/scripts/add-capability.py +364 -0
  205. package/skills/trtc-ai-service/scripts/contract-adapt.py +334 -0
  206. package/skills/trtc-ai-service/scripts/detect-stack.py +40 -0
  207. package/skills/trtc-ai-service/scripts/lib/__init__.py +20 -0
  208. package/skills/trtc-ai-service/scripts/lib/adapter_codegen.py +509 -0
  209. package/skills/trtc-ai-service/scripts/lib/arbitrator.py +152 -0
  210. package/skills/trtc-ai-service/scripts/lib/contract_resolver.py +519 -0
  211. package/skills/trtc-ai-service/scripts/lib/credential_validators.py +253 -0
  212. package/skills/trtc-ai-service/scripts/lib/curl_parser.py +303 -0
  213. package/skills/trtc-ai-service/scripts/lib/degrader.py +140 -0
  214. package/skills/trtc-ai-service/scripts/lib/injector.py +347 -0
  215. package/skills/trtc-ai-service/scripts/lib/manifest_resolver.py +288 -0
  216. package/skills/trtc-ai-service/scripts/lib/openapi_parser.py +289 -0
  217. package/skills/trtc-ai-service/scripts/lib/stack_detector.py +159 -0
  218. package/skills/trtc-ai-service/scripts/lib/tokens_compile.py +204 -0
  219. package/skills/trtc-ai-service/scripts/post-install-patch.py +225 -0
  220. package/skills/trtc-ai-service/scripts/setup-credentials.py +393 -0
  221. package/skills/trtc-ai-service/scripts/verify-credentials.py +108 -0
  222. package/skills/trtc-ai-service/start.sh +111 -0
  223. package/skills/trtc-ai-service/tests/__init__.py +1 -0
  224. package/skills/trtc-ai-service/tests/test_arbitrator.py +64 -0
  225. package/skills/trtc-ai-service/tests/test_capability_overlay.py +85 -0
  226. package/skills/trtc-ai-service/tests/test_contract_resolver.py +190 -0
  227. package/skills/trtc-ai-service/tests/test_handoff_ports.py +195 -0
  228. package/skills/trtc-ai-service/tests/test_kb_ports.py +195 -0
  229. package/skills/trtc-ai-service/tests/test_manifest_resolver.py +95 -0
  230. package/skills/trtc-ai-service/tests/test_recipe_assembly.py +175 -0
  231. package/skills/trtc-ai-service/tests/test_stack_and_degrader.py +101 -0
  232. package/skills/trtc-ai-service/tests/test_verify_credentials.py +285 -0
  233. package/skills/trtc-ai-service/triggers.yaml +29 -0
  234. package/skills/trtc-conference/SKILL.md +324 -0
  235. package/skills/trtc-conference/flows/onboarding.md +205 -0
  236. package/skills/trtc-conference/flows/topic.md +474 -0
  237. package/skills/trtc-conference/flows/troubleshoot.md +85 -0
  238. package/skills/trtc-conference/hooks/pretooluse_require_business_decisions.py +213 -0
  239. package/skills/trtc-conference/playbooks/medical-quickstart.md +84 -0
  240. package/skills/trtc-conference/playbooks/official-roomkit.md +97 -0
  241. package/skills/trtc-conference/references/local-usersig/basic-info-config.ts +39 -0
  242. package/skills/trtc-conference/references/usersig-handling.md +134 -0
  243. package/skills/trtc-conference/templates/medical-consultation/src/config/lib-generate-test-usersig-es.min.d.ts +4 -0
  244. package/skills/trtc-conference/templates/medical-consultation/src/config/lib-generate-test-usersig-es.min.js +2 -0
  245. package/skills/trtc-conference/tests/__pycache__/test_conference_onboarding_contract.cpython-313-pytest-9.0.2.pyc +0 -0
  246. package/skills/trtc-conference/tests/__pycache__/test_conference_topic_flow_contract.cpython-313-pytest-9.0.2.pyc +0 -0
  247. package/skills/trtc-conference/tests/test_conference_index_contract.py +43 -0
  248. package/skills/trtc-conference/tests/test_conference_onboarding_contract.py +103 -0
  249. package/skills/trtc-conference/tests/test_conference_template_contract.py +25 -0
  250. package/skills/trtc-conference/tests/test_conference_topic_flow_contract.py +132 -0
  251. package/skills/trtc-conference/tools/apply_checks.py +328 -0
  252. package/skills/trtc-conference/verify_lib/__init__.py +0 -0
  253. package/skills/{trtc-apply/guardrails/apply_lib → trtc-conference/verify_lib}/rule_parser.py +1 -1
  254. package/skills/trtc-docs/SKILL.md +91 -119
  255. package/.cursor/rules/ui-mode.mdc +0 -99
  256. package/ai-instructions/base.md +0 -13
  257. package/ai-instructions/ui-mode.md +0 -93
  258. package/knowledge-base/index.yaml +0 -462
  259. package/skills/trtc/room-builder/SKILL.md +0 -133
  260. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/README.md +0 -108
  261. package/skills/trtc/room-builder/tools/render_ai_instructions.py +0 -226
  262. package/skills/trtc-apply/SKILL.md +0 -97
  263. package/skills/trtc-onboarding/SKILL.md +0 -841
  264. package/skills/trtc-onboarding/reference/path-a1-demo.md +0 -103
  265. package/skills/trtc-onboarding/reference/path-a2-integrate.md +0 -737
  266. package/skills/trtc-onboarding/reference/path-b-troubleshoot.md +0 -186
  267. package/skills/trtc-onboarding/reference/path-c-expand.md +0 -43
  268. package/skills/trtc-onboarding/reference/supported-matrix.md +0 -100
  269. package/skills/trtc-search/SKILL.md +0 -228
  270. package/skills/trtc-topic/SKILL.md +0 -622
  271. package/skills/trtc-topic/scripts/apply.py +0 -581
  272. package/skills/trtc-topic/scripts/lib/state_machine.py +0 -328
  273. package/skills/trtc-topic/tests/README.md +0 -70
  274. package/skills/trtc-topic/tests/conftest.py +0 -72
  275. package/skills/trtc-topic/tests/test_apply_cli.py +0 -480
  276. package/skills/trtc-topic/tests/test_end_to_end.py +0 -305
  277. package/skills/trtc-topic/tests/test_finalize_session.py +0 -51
  278. package/skills/trtc-topic/tests/test_gates.py +0 -316
  279. package/skills/trtc-topic/tests/test_session_resolver.py +0 -260
  280. package/skills/trtc-topic/tests/test_state_machine.py +0 -414
  281. package/skills/trtc-topic/tests/test_stop_require_apply.py +0 -99
  282. package/skills/trtc-topic/tests/test_topic_skill_invariants.py +0 -130
  283. /package/skills/{trtc-topic → trtc}/runtime/lib/platforms.py +0 -0
  284. /package/skills/{trtc-topic → trtc}/runtime/telemetry_collector.py +0 -0
  285. /package/skills/{trtc-onboarding/reference → trtc/runtime}/usersig-handling.md +0 -0
  286. /package/skills/{trtc-topic/scripts → trtc/tools}/finalize_session.py +0 -0
  287. /package/skills/{trtc-apply/guardrails/apply_lib → trtc-ai-service/capabilities/conversation-core/tests}/__init__.py +0 -0
  288. /package/skills/{trtc-topic → trtc-conference}/references/execution-units.yaml +0 -0
  289. /package/skills/{trtc/room-builder/templates/scenarios/medical-consultation/src/config → trtc-conference/references/local-usersig}/lib-generate-test-usersig-es.min.d.ts +0 -0
  290. /package/skills/{trtc/room-builder/templates/scenarios/medical-consultation/src/config → trtc-conference/references/local-usersig}/lib-generate-test-usersig-es.min.js +0 -0
  291. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/docs/backend-contract.zh-CN.md +0 -0
  292. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/docs/integration.zh-CN.md +0 -0
  293. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/docs/theme.zh-CN.md +0 -0
  294. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/index.html +0 -0
  295. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/package.json +0 -0
  296. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/postcss.config.js +0 -0
  297. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/App.vue +0 -0
  298. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/components/ConsultationManagePanel.vue +0 -0
  299. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/components/LanguageSwitch.vue +0 -0
  300. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/components/LoadingSpinner.vue +0 -0
  301. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/components/MedicalAlert.vue +0 -0
  302. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/components/MedicalBusinessPanel.vue +0 -0
  303. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/components/MedicalButton.vue +0 -0
  304. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/components/MedicalConfirmDialog.vue +0 -0
  305. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/components/MedicalDataPanel.vue +0 -0
  306. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/components/MedicalRecordPanel.vue +0 -0
  307. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/components/PrescriptionPanel.vue +0 -0
  308. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/config/basic-info-config.ts +0 -0
  309. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/config/runtime-config.ts +0 -0
  310. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/env.d.ts +0 -0
  311. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/features/consultation/components/ConsultationChatPanel.vue +0 -0
  312. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/features/consultation/components/ConsultationMembersPanel.vue +0 -0
  313. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/features/consultation/components/ConsultationTranscriptionPanel.vue +0 -0
  314. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/features/consultation/components/ConsultationVideoStage.vue +0 -0
  315. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/features/consultation/components/InviteDoctorDialog.vue +0 -0
  316. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/features/consultation/components/KickMemberConfirmDialog.vue +0 -0
  317. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/features/consultation/types.ts +0 -0
  318. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/features/consultation/useConsultationChat.ts +0 -0
  319. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/features/consultation/useConsultationDevices.ts +0 -0
  320. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/features/consultation/useConsultationParticipants.ts +0 -0
  321. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/features/consultation/useConsultationPermissions.ts +0 -0
  322. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/features/consultation/utils.ts +0 -0
  323. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/i18n/en-US/index.ts +0 -0
  324. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/i18n/index.ts +0 -0
  325. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/i18n/medicalTranslate.ts +0 -0
  326. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/i18n/state.ts +0 -0
  327. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/i18n/zh-CN/index.ts +0 -0
  328. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/main.ts +0 -0
  329. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/mock/appointments.ts +0 -0
  330. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/mock/users.ts +0 -0
  331. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/router/index.ts +0 -0
  332. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/services/adapters/index.ts +0 -0
  333. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/services/adapters/integration/appointmentService.ts +0 -0
  334. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/services/adapters/integration/authService.ts +0 -0
  335. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/services/adapters/integration/launchContext.ts +0 -0
  336. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/services/adapters/integration/userService.ts +0 -0
  337. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/services/adapters/mock/appointmentService.ts +0 -0
  338. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/services/adapters/mock/authService.ts +0 -0
  339. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/services/adapters/mock/userService.ts +0 -0
  340. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/services/adapters/types.ts +0 -0
  341. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/shared/icons.ts +0 -0
  342. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/styles/index.css +0 -0
  343. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/styles/tailwind.css +0 -0
  344. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/styles/theme.css +0 -0
  345. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/utils/auth.ts +0 -0
  346. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/utils/format.ts +0 -0
  347. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/utils/navigation.ts +0 -0
  348. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/utils/session.ts +0 -0
  349. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/views/DoctorConsultationView.vue +0 -0
  350. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/views/DoctorDashboardView.vue +0 -0
  351. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/views/LoginView.vue +0 -0
  352. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/views/PatientConsultationFinishedView.vue +0 -0
  353. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/views/PatientConsultationView.vue +0 -0
  354. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/views/PatientSelectDoctorView.vue +0 -0
  355. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/views/PatientWaitingView.vue +0 -0
  356. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/tsconfig.json +0 -0
  357. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/tsconfig.node.json +0 -0
  358. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/vite.config.ts +0 -0
  359. /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation//346/216/245/345/205/245/350/257/264/346/230/216.md" +0 -0
  360. /package/skills/{trtc-topic/runtime/lib → trtc-conference/tools}/__init__.py +0 -0
@@ -0,0 +1,355 @@
1
+ """Real-time connectivity self-check for the 3 keys.
2
+
3
+ Each key is validated immediately after input; failures get instant feedback without proceeding to the next key.
4
+ """
5
+ from __future__ import annotations
6
+
7
+ import base64
8
+ import hashlib
9
+ import hmac
10
+ import json
11
+ import time
12
+ from dataclasses import dataclass
13
+ from datetime import datetime, timezone
14
+ from typing import Tuple
15
+ from urllib.parse import urlparse
16
+
17
+ import requests
18
+
19
+ from .credentials import LlmCredential, TencentCloudCredential, TrtcCredential
20
+ from .usersig import gen_user_sig
21
+
22
+
23
+ @dataclass
24
+ class CheckResult:
25
+ ok: bool
26
+ latency_ms: int
27
+ error_code: str = ""
28
+ detail: str = ""
29
+
30
+ def to_dict(self) -> dict:
31
+ return {
32
+ "status": "ok" if self.ok else "failed",
33
+ "latency_ms": self.latency_ms,
34
+ "error_code": self.error_code,
35
+ "detail": self.detail,
36
+ }
37
+
38
+
39
+ # ---------------------------------------------------------------------------
40
+ # 1) Tencent Cloud API Key: Call STS GetFederationToken
41
+ # ---------------------------------------------------------------------------
42
+ _STS_HOST = "sts.tencentcloudapi.com"
43
+ _STS_SERVICE = "sts"
44
+ _STS_VERSION = "2018-08-13"
45
+ _STS_ACTION = "GetFederationToken"
46
+
47
+
48
+ def _sign_tc3(secret_key: str, date: str, service: str, string_to_sign: str) -> str:
49
+ k_date = hmac.new(("TC3" + secret_key).encode("utf-8"), date.encode("utf-8"), hashlib.sha256).digest()
50
+ k_service = hmac.new(k_date, service.encode("utf-8"), hashlib.sha256).digest()
51
+ k_signing = hmac.new(k_service, b"tc3_request", hashlib.sha256).digest()
52
+ return hmac.new(k_signing, string_to_sign.encode("utf-8"), hashlib.sha256).hexdigest()
53
+
54
+
55
+ def check_tencent_cloud(cred: TencentCloudCredential, timeout: float = 5.0) -> CheckResult:
56
+ """Call STS GetFederationToken to verify SecretId/SecretKey validity."""
57
+ if not cred.configured:
58
+ return CheckResult(ok=False, latency_ms=0, error_code="E001", detail="empty credential")
59
+
60
+ payload = json.dumps(
61
+ {
62
+ "Name": "trtc-voice-agent-credential-check",
63
+ "Policy": json.dumps(
64
+ {
65
+ "version": "2.0",
66
+ "statement": [
67
+ {
68
+ "effect": "deny",
69
+ "action": ["*"],
70
+ "resource": ["*"],
71
+ }
72
+ ],
73
+ }
74
+ ),
75
+ "DurationSeconds": 1800,
76
+ },
77
+ separators=(",", ":"),
78
+ )
79
+ timestamp = int(time.time())
80
+ date = datetime.fromtimestamp(timestamp, tz=timezone.utc).strftime("%Y-%m-%d")
81
+
82
+ canonical_headers = (
83
+ f"content-type:application/json; charset=utf-8\n"
84
+ f"host:{_STS_HOST}\n"
85
+ f"x-tc-action:{_STS_ACTION.lower()}\n"
86
+ )
87
+ signed_headers = "content-type;host;x-tc-action"
88
+ hashed_payload = hashlib.sha256(payload.encode("utf-8")).hexdigest()
89
+ canonical_request = (
90
+ f"POST\n/\n\n{canonical_headers}\n{signed_headers}\n{hashed_payload}"
91
+ )
92
+ credential_scope = f"{date}/{_STS_SERVICE}/tc3_request"
93
+ hashed_canonical = hashlib.sha256(canonical_request.encode("utf-8")).hexdigest()
94
+ string_to_sign = (
95
+ f"TC3-HMAC-SHA256\n{timestamp}\n{credential_scope}\n{hashed_canonical}"
96
+ )
97
+ signature = _sign_tc3(cred.secret_key, date, _STS_SERVICE, string_to_sign)
98
+ authorization = (
99
+ f"TC3-HMAC-SHA256 Credential={cred.secret_id}/{credential_scope}, "
100
+ f"SignedHeaders={signed_headers}, Signature={signature}"
101
+ )
102
+ headers = {
103
+ "Authorization": authorization,
104
+ "Content-Type": "application/json; charset=utf-8",
105
+ "Host": _STS_HOST,
106
+ "X-TC-Action": _STS_ACTION,
107
+ "X-TC-Timestamp": str(timestamp),
108
+ "X-TC-Version": _STS_VERSION,
109
+ "X-TC-Region": cred.region,
110
+ }
111
+ started = time.perf_counter()
112
+ try:
113
+ resp = requests.post(
114
+ f"https://{_STS_HOST}",
115
+ headers=headers,
116
+ data=payload.encode("utf-8"),
117
+ timeout=timeout,
118
+ )
119
+ elapsed = int((time.perf_counter() - started) * 1000)
120
+ body = resp.json() if resp.content else {}
121
+ err = body.get("Response", {}).get("Error")
122
+ if resp.status_code == 200 and not err:
123
+ return CheckResult(ok=True, latency_ms=elapsed)
124
+ if err and err.get("Code", "").startswith("AuthFailure"):
125
+ return CheckResult(
126
+ ok=False,
127
+ latency_ms=elapsed,
128
+ error_code="E001",
129
+ detail=err.get("Message", "AuthFailure"),
130
+ )
131
+ return CheckResult(
132
+ ok=False,
133
+ latency_ms=elapsed,
134
+ error_code="E001",
135
+ detail=(err or {}).get("Message") or f"HTTP {resp.status_code}",
136
+ )
137
+ except requests.Timeout:
138
+ return CheckResult(ok=False, latency_ms=int(timeout * 1000), error_code="E004", detail="timeout")
139
+ except requests.RequestException as exc:
140
+ return CheckResult(ok=False, latency_ms=0, error_code="E004", detail=str(exc))
141
+
142
+
143
+ # ---------------------------------------------------------------------------
144
+ # 2) TRTC Application Credentials: Call TRTC OpenAPI DescribeAppStatistics to verify
145
+ # that SDKAppID + Tencent Cloud API Key combination actually works.
146
+ # Note: During StartAIConversation, TRTC server also validates SDKSecretKey
147
+ # against the room ID, so local UserSig generation alone cannot detect SecretKey
148
+ # misconfiguration. Hence we do a lightweight real OpenAPI call as a fallback
149
+ # (rate limit 50/s won't trigger throttling).
150
+ # endpoint switches by trtc.region: intl → trtc.intl.tencentcloudapi.com
151
+ # ---------------------------------------------------------------------------
152
+ _TRTC_SERVICE = "trtc"
153
+ _TRTC_VERSION = "2019-07-22"
154
+
155
+
156
+ def _trtc_sign_tc3(secret_key: str, date: str, string_to_sign: str) -> str:
157
+ k_date = hmac.new(
158
+ ("TC3" + secret_key).encode("utf-8"),
159
+ date.encode("utf-8"),
160
+ hashlib.sha256,
161
+ ).digest()
162
+ k_service = hmac.new(k_date, _TRTC_SERVICE.encode("utf-8"), hashlib.sha256).digest()
163
+ k_signing = hmac.new(k_service, b"tc3_request", hashlib.sha256).digest()
164
+ return hmac.new(k_signing, string_to_sign.encode("utf-8"), hashlib.sha256).hexdigest()
165
+
166
+
167
+ def check_trtc(
168
+ cred: TrtcCredential,
169
+ tencent: TencentCloudCredential | None = None,
170
+ timeout: float = 5.0,
171
+ ) -> CheckResult:
172
+ """Verify TRTC credentials.
173
+
174
+ 1. Required: Local UserSig generation (verify SDKAppID + SDKSecretKey self-consistency)
175
+ 2. Recommended: Call TRTC OpenAPI ``DescribeTRTCRealTimeQualityData``
176
+ to verify SDKAppID really exists under the Tencent Cloud account (depends on ``tencent`` cred)
177
+ endpoint switches by cred.region (intl / cn)
178
+ """
179
+ if not cred.configured:
180
+ return CheckResult(ok=False, latency_ms=0, error_code="E002", detail="empty credential")
181
+
182
+ started = time.perf_counter()
183
+ # —— Step 1: Local UserSig generation ——
184
+ try:
185
+ sig = gen_user_sig(
186
+ sdk_app_id=cred.sdk_app_id,
187
+ sdk_secret_key=cred.sdk_secret_key,
188
+ user_id="credential_check",
189
+ expire_seconds=60,
190
+ )
191
+ except Exception as exc:
192
+ return CheckResult(ok=False, latency_ms=0, error_code="E002", detail=str(exc))
193
+ if not sig or len(sig) < 32:
194
+ return CheckResult(
195
+ ok=False,
196
+ latency_ms=int((time.perf_counter() - started) * 1000),
197
+ error_code="E002",
198
+ detail="invalid usersig length",
199
+ )
200
+
201
+ # —— Step 2: Real OpenAPI verification (requires Tencent Cloud API credentials) ——
202
+ if tencent is None or not tencent.configured:
203
+ elapsed = int((time.perf_counter() - started) * 1000)
204
+ return CheckResult(ok=True, latency_ms=elapsed, detail="local-only (no tencent cred)")
205
+
206
+ trtc_host = cred.trtc_endpoint
207
+ trtc_region = cred.trtc_region
208
+
209
+ # Use DescribeTRTCRealTimeQualityData for a minimal probe: pass SdkAppId + very short time window
210
+ now_ts = int(time.time())
211
+ payload = json.dumps(
212
+ {
213
+ "SdkAppId": cred.sdk_app_id,
214
+ "StartTime": now_ts - 60,
215
+ "EndTime": now_ts,
216
+ },
217
+ separators=(",", ":"),
218
+ )
219
+ timestamp = now_ts
220
+ date = datetime.fromtimestamp(timestamp, tz=timezone.utc).strftime("%Y-%m-%d")
221
+ canonical_headers = (
222
+ f"content-type:application/json; charset=utf-8\n"
223
+ f"host:{trtc_host}\n"
224
+ f"x-tc-action:describetrtcrealtimequalitydata\n"
225
+ )
226
+ signed_headers = "content-type;host;x-tc-action"
227
+ hashed_payload = hashlib.sha256(payload.encode("utf-8")).hexdigest()
228
+ canonical_request = (
229
+ f"POST\n/\n\n{canonical_headers}\n{signed_headers}\n{hashed_payload}"
230
+ )
231
+ credential_scope = f"{date}/{_TRTC_SERVICE}/tc3_request"
232
+ hashed_canonical = hashlib.sha256(canonical_request.encode("utf-8")).hexdigest()
233
+ string_to_sign = (
234
+ f"TC3-HMAC-SHA256\n{timestamp}\n{credential_scope}\n{hashed_canonical}"
235
+ )
236
+ signature = _trtc_sign_tc3(tencent.secret_key, date, string_to_sign)
237
+ authorization = (
238
+ f"TC3-HMAC-SHA256 Credential={tencent.secret_id}/{credential_scope}, "
239
+ f"SignedHeaders={signed_headers}, Signature={signature}"
240
+ )
241
+ headers = {
242
+ "Authorization": authorization,
243
+ "Content-Type": "application/json; charset=utf-8",
244
+ "Host": trtc_host,
245
+ "X-TC-Action": "DescribeTRTCRealTimeQualityData",
246
+ "X-TC-Timestamp": str(timestamp),
247
+ "X-TC-Version": _TRTC_VERSION,
248
+ "X-TC-Region": trtc_region,
249
+ }
250
+ try:
251
+ resp = requests.post(
252
+ f"https://{trtc_host}",
253
+ headers=headers,
254
+ data=payload.encode("utf-8"),
255
+ timeout=timeout,
256
+ )
257
+ elapsed = int((time.perf_counter() - started) * 1000)
258
+ body = resp.json() if resp.content else {}
259
+ err = body.get("Response", {}).get("Error")
260
+ if resp.status_code == 200 and not err:
261
+ return CheckResult(
262
+ ok=True,
263
+ latency_ms=elapsed,
264
+ detail=f"region={cred.region}, endpoint={trtc_host}",
265
+ )
266
+ # Distinguish two error types: SdkAppId not under this account vs others
267
+ if err:
268
+ code = err.get("Code", "")
269
+ if "SdkAppId" in code or "AuthFailure" in code or "ResourceNotFound" in code:
270
+ return CheckResult(
271
+ ok=False,
272
+ latency_ms=elapsed,
273
+ error_code="E002",
274
+ detail=f"{code}: {err.get('Message', '')} (region={cred.region})",
275
+ )
276
+ # Other business errors (e.g. a sub-capability not enabled) don't affect SdkAppId ownership; treat as pass
277
+ return CheckResult(
278
+ ok=True,
279
+ latency_ms=elapsed,
280
+ detail=f"sdkappid valid; api warning: {code}",
281
+ )
282
+ return CheckResult(
283
+ ok=False,
284
+ latency_ms=elapsed,
285
+ error_code="E002",
286
+ detail=f"HTTP {resp.status_code}",
287
+ )
288
+ except requests.Timeout:
289
+ return CheckResult(
290
+ ok=False,
291
+ latency_ms=int(timeout * 1000),
292
+ error_code="E004",
293
+ detail="trtc api timeout",
294
+ )
295
+ except requests.RequestException as exc:
296
+ return CheckResult(ok=False, latency_ms=0, error_code="E004", detail=str(exc))
297
+
298
+
299
+ # ---------------------------------------------------------------------------
300
+ # 3) External LLM: Send a minimal prompt to verify the key is valid.
301
+ # ---------------------------------------------------------------------------
302
+ def check_llm(cred: LlmCredential, timeout: float = 10.0) -> CheckResult:
303
+ if not cred.configured:
304
+ return CheckResult(ok=False, latency_ms=0, error_code="E003", detail="empty credential")
305
+
306
+ parsed = urlparse(cred.api_url)
307
+ if parsed.scheme not in ("http", "https"):
308
+ return CheckResult(ok=False, latency_ms=0, error_code="E003", detail="invalid api_url scheme")
309
+
310
+ headers = {
311
+ "Authorization": f"Bearer {cred.api_key}",
312
+ "Content-Type": "application/json",
313
+ }
314
+ body = {
315
+ "model": cred.model,
316
+ "messages": [{"role": "user", "content": "ping"}],
317
+ "max_tokens": 1,
318
+ "temperature": 0,
319
+ "stream": False,
320
+ }
321
+ started = time.perf_counter()
322
+ try:
323
+ resp = requests.post(cred.api_url, headers=headers, json=body, timeout=timeout)
324
+ elapsed = int((time.perf_counter() - started) * 1000)
325
+ if resp.status_code == 200:
326
+ return CheckResult(ok=True, latency_ms=elapsed)
327
+ if resp.status_code in (401, 403):
328
+ return CheckResult(
329
+ ok=False,
330
+ latency_ms=elapsed,
331
+ error_code="E003",
332
+ detail=f"unauthorized: {resp.status_code}",
333
+ )
334
+ return CheckResult(
335
+ ok=False,
336
+ latency_ms=elapsed,
337
+ error_code="E003",
338
+ detail=f"HTTP {resp.status_code}: {resp.text[:200]}",
339
+ )
340
+ except requests.Timeout:
341
+ return CheckResult(ok=False, latency_ms=int(timeout * 1000), error_code="E004", detail="timeout")
342
+ except requests.RequestException as exc:
343
+ return CheckResult(ok=False, latency_ms=0, error_code="E004", detail=str(exc))
344
+
345
+
346
+ def check_all(
347
+ tencent: TencentCloudCredential,
348
+ trtc: TrtcCredential,
349
+ llm: LlmCredential,
350
+ ) -> Tuple[CheckResult, CheckResult, CheckResult]:
351
+ return (
352
+ check_tencent_cloud(tencent),
353
+ check_trtc(trtc, tencent=tencent),
354
+ check_llm(llm),
355
+ )
@@ -0,0 +1,76 @@
1
+ """Log redaction filter (P0 security requirement implemented).
2
+
3
+ Performs irreversible masking of credential fields in log records before logging,
4
+ based on the keywords declared in manifest.yaml security.log_redaction.patterns.
5
+ """
6
+ from __future__ import annotations
7
+
8
+ import logging
9
+ import re
10
+ from typing import Iterable
11
+
12
+ # Default sensitive field names to match (aligned with manifest.yaml security.log_redaction.patterns)
13
+ _DEFAULT_PATTERNS = (
14
+ "secret_id",
15
+ "secret_key",
16
+ "api_key",
17
+ "app_key",
18
+ "token",
19
+ "usersig",
20
+ "credential",
21
+ "authorization",
22
+ )
23
+
24
+
25
+ def _build_regex(patterns: Iterable[str]) -> re.Pattern[str]:
26
+ # Matches three common formats: key=value / "key": "value" / key: value
27
+ keys = "|".join(re.escape(p) for p in patterns)
28
+ pattern = (
29
+ r"(?i)(?P<key>" + keys + r")"
30
+ r"(?P<sep>\s*[:=]\s*\"?)"
31
+ r"(?P<val>[A-Za-z0-9_\-\.\+/=]{4,})"
32
+ )
33
+ return re.compile(pattern)
34
+
35
+
36
+ def _mask(value: str) -> str:
37
+ if len(value) <= 8:
38
+ return "***"
39
+ return f"{value[:2]}***{value[-2:]}"
40
+
41
+
42
+ class RedactingFilter(logging.Filter):
43
+ """Mask sensitive fields in log messages / args."""
44
+
45
+ def __init__(self, patterns: Iterable[str] = _DEFAULT_PATTERNS) -> None:
46
+ super().__init__()
47
+ self._regex = _build_regex(patterns)
48
+
49
+ def filter(self, record: logging.LogRecord) -> bool: # noqa: A003
50
+ try:
51
+ if isinstance(record.msg, str):
52
+ record.msg = self._regex.sub(
53
+ lambda m: f"{m.group('key')}{m.group('sep')}{_mask(m.group('val'))}",
54
+ record.msg,
55
+ )
56
+ if record.args:
57
+ record.args = tuple(
58
+ self._regex.sub(
59
+ lambda m: f"{m.group('key')}{m.group('sep')}{_mask(m.group('val'))}",
60
+ str(a),
61
+ )
62
+ if isinstance(a, str)
63
+ else a
64
+ for a in record.args
65
+ )
66
+ except Exception: # Redaction failure must not affect the main logging flow
67
+ pass
68
+ return True
69
+
70
+
71
+ def install_redacting_filter(logger: logging.Logger | None = None) -> None:
72
+ """Attach the redacting filter to the specified Logger (defaults to root Logger)."""
73
+ target = logger or logging.getLogger()
74
+ if any(isinstance(f, RedactingFilter) for f in target.filters):
75
+ return
76
+ target.addFilter(RedactingFilter())
@@ -0,0 +1,109 @@
1
+ """I/O modality configuration and degradation strategy (conversation-core built-in).
2
+
3
+ Four channels (voice input / voice output / text input / text output) are independently configurable.
4
+ When a channel service is unavailable, the system automatically degrades to an available channel
5
+ according to the strategy declared in this module, ensuring session continuity.
6
+ """
7
+ from __future__ import annotations
8
+
9
+ from dataclasses import dataclass, field
10
+ from enum import Enum
11
+ from typing import Optional
12
+
13
+
14
+ class Channel(str, Enum):
15
+ VOICE_INPUT = "voice_input"
16
+ TEXT_INPUT = "text_input"
17
+ VOICE_OUTPUT = "voice_output"
18
+ TEXT_OUTPUT = "text_output"
19
+
20
+
21
+ @dataclass
22
+ class ChannelConfig:
23
+ enabled: bool = True
24
+ provider: Optional[str] = None
25
+ fallback: Optional[Channel] = None
26
+ timeout_ms: int = 0
27
+
28
+
29
+ @dataclass
30
+ class IoModality:
31
+ voice_input: ChannelConfig = field(
32
+ default_factory=lambda: ChannelConfig(
33
+ enabled=True, provider="trtc-asr", fallback=Channel.TEXT_INPUT, timeout_ms=5000
34
+ )
35
+ )
36
+ text_input: ChannelConfig = field(default_factory=lambda: ChannelConfig(enabled=True))
37
+ voice_output: ChannelConfig = field(
38
+ default_factory=lambda: ChannelConfig(
39
+ enabled=True, provider="trtc-tts", fallback=Channel.TEXT_OUTPUT, timeout_ms=3000
40
+ )
41
+ )
42
+ text_output: ChannelConfig = field(default_factory=lambda: ChannelConfig(enabled=True))
43
+
44
+ def to_dict(self) -> dict:
45
+ def _dump(c: ChannelConfig) -> dict:
46
+ return {
47
+ "enabled": c.enabled,
48
+ "provider": c.provider,
49
+ "fallback": c.fallback.value if c.fallback else None,
50
+ "timeout_ms": c.timeout_ms,
51
+ }
52
+
53
+ return {
54
+ Channel.VOICE_INPUT.value: _dump(self.voice_input),
55
+ Channel.TEXT_INPUT.value: _dump(self.text_input),
56
+ Channel.VOICE_OUTPUT.value: _dump(self.voice_output),
57
+ Channel.TEXT_OUTPUT.value: _dump(self.text_output),
58
+ }
59
+
60
+ def resolve_input_channel(self, voice_available: bool) -> Channel:
61
+ """Return the input channel to use, based on enabled status + service availability."""
62
+ if self.voice_input.enabled and voice_available:
63
+ return Channel.VOICE_INPUT
64
+ if self.voice_input.fallback and self.text_input.enabled:
65
+ return Channel.TEXT_INPUT
66
+ if self.text_input.enabled:
67
+ return Channel.TEXT_INPUT
68
+ # Edge case: all input channels unavailable -> upper layer enters silent wait
69
+ raise RuntimeError("no usable input channel")
70
+
71
+ def resolve_output_channel(self, voice_available: bool) -> Channel:
72
+ if self.voice_output.enabled and voice_available:
73
+ return Channel.VOICE_OUTPUT
74
+ if self.voice_output.fallback and self.text_output.enabled:
75
+ return Channel.TEXT_OUTPUT
76
+ if self.text_output.enabled:
77
+ return Channel.TEXT_OUTPUT
78
+ raise RuntimeError("no usable output channel")
79
+
80
+
81
+ def from_dict(data: dict) -> IoModality:
82
+ """Construct IoModality instance from the io_modality section of manifest.yaml."""
83
+ if not data:
84
+ return IoModality()
85
+
86
+ def _channel(value: Optional[str]) -> Optional[Channel]:
87
+ if not value:
88
+ return None
89
+ return Channel(value)
90
+
91
+ def _build(cfg: dict | None, default: ChannelConfig) -> ChannelConfig:
92
+ if not cfg:
93
+ return default
94
+ return ChannelConfig(
95
+ enabled=cfg.get("enabled", default.enabled),
96
+ provider=cfg.get("provider", default.provider),
97
+ fallback=_channel(cfg.get("fallback"))
98
+ if "fallback" in cfg
99
+ else default.fallback,
100
+ timeout_ms=cfg.get("timeout_ms", default.timeout_ms),
101
+ )
102
+
103
+ base = IoModality()
104
+ return IoModality(
105
+ voice_input=_build(data.get("voice_input"), base.voice_input),
106
+ text_input=_build(data.get("text_input"), base.text_input),
107
+ voice_output=_build(data.get("voice_output"), base.voice_output),
108
+ text_output=_build(data.get("text_output"), base.text_output),
109
+ )