@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,225 @@
1
+ #!/usr/bin/env python3
2
+ """post-install-patch.py — safety-net patch script after capability assembly.
3
+
4
+ When to Call
5
+ ------------
6
+ SKILL.md §6 Path A Step 2.5 (after add-capability, before UI overlay)
7
+
8
+ What It Does
9
+ ------------
10
+ 1. **Fix legacy extension point misplacement**
11
+ Early versions of `conversation-core/manifest.yaml` wrote `agent.before_push_text`
12
+ as `before:push_text`, which add-capability.py interpreted as "insert at same indent
13
+ before the `def push_text` line," resulting in class-scope placement that referenced
14
+ local variables `session_id`/`text`, causing NameError.
15
+ The new version uses sentinel anchor `_ext_before_push_text_` (inside push_text method body).
16
+ This patch scans the deployed agent.py and moves any "class-scope misplaced injection block"
17
+ into the correct method-body position. If already in the method body, it is skipped (idempotent).
18
+ The same logic also covers `_ext_after_start_`.
19
+
20
+ 2. **Auto-append .env default capability variables**
21
+ recipe.yaml ui_overlay / capability adapter defaults (KB_ADAPTER=mock /
22
+ HH_ADAPTER=local_queue, etc.) previously required manual .env editing. This patch
23
+ appends missing entries to an existing .env without overwriting existing values.
24
+
25
+ 3. **server.py StaticFiles html=True verification**
26
+ Ensures `/static/admin/`, `/static/dev/`, etc. subdirectory access can fallback to index.html.
27
+
28
+ Output
29
+ ------
30
+ A JSON line (structured). Exit code 0 = all OK or idempotent skips; non-0 = anomalies
31
+ requiring manual intervention.
32
+
33
+ Only modifies these whitelisted files:
34
+ capabilities/conversation-core/src/agent.py
35
+ capabilities/conversation-core/src/server.py
36
+ capabilities/conversation-core/.env
37
+ """
38
+ from __future__ import annotations
39
+
40
+ import json
41
+ import os
42
+ import re
43
+ import sys
44
+ from pathlib import Path
45
+
46
+ ROOT = Path(__file__).resolve().parent.parent
47
+ AGENT_PY = ROOT / "capabilities" / "conversation-core" / "src" / "agent.py"
48
+ SERVER_PY = ROOT / "capabilities" / "conversation-core" / "src" / "server.py"
49
+ ENV_FILE = ROOT / "capabilities" / "conversation-core" / ".env"
50
+
51
+ # .env 默认值(与 scenarios/customer-service/recipe.yaml 对齐)
52
+ ENV_DEFAULTS = {
53
+ "KB_ADAPTER": "mock",
54
+ "KB_TOP_K": "3",
55
+ "KB_MIN_SCORE": "0.05",
56
+ "HH_ADAPTER": "local_queue",
57
+ }
58
+
59
+ # Known capability injection block markers (by capability name)
60
+ CAP_MARKERS = ("human-handoff", "tool-calling", "session-summary", "knowledge-base")
61
+
62
+
63
+ # --------------------------------------------------------------------------- #
64
+ # 1. agent.py misplaced injection fix
65
+ # --------------------------------------------------------------------------- #
66
+ def _patch_agent_py(report: dict) -> None:
67
+ if not AGENT_PY.exists():
68
+ report["agent_py"] = {"ok": False, "skipped": True, "reason": "agent.py not found"}
69
+ return
70
+
71
+ src = AGENT_PY.read_text(encoding="utf-8")
72
+
73
+ # Check whether each capability's marker still appears at 4-space indent in class scope
74
+ # (correct position is 8+ spaces = inside method body)
75
+ misplaced: list[str] = []
76
+ for cap in CAP_MARKERS:
77
+ marker = f"# [{cap}]"
78
+ # Class scope 4 spaces + marker
79
+ if re.search(rf"^ {re.escape(marker)}", src, re.MULTILINE):
80
+ misplaced.append(cap)
81
+
82
+ if not misplaced:
83
+ report["agent_py"] = {"ok": True, "patched": [], "note": "no misplaced capability injections"}
84
+ return
85
+
86
+ # For each misplaced capability, strip it from class scope → move before the corresponding method body sentinel
87
+ new_src = src
88
+ moved: list[str] = []
89
+ failures: list[dict] = []
90
+ for cap in misplaced:
91
+ marker = f"# [{cap}]"
92
+ # Extract consecutive 4-space-indented block starting with the marker
93
+ block_re = re.compile(
94
+ rf"(?:^ {re.escape(marker)}[^\n]*\n(?:^ [^\n]*\n)+)",
95
+ re.MULTILINE,
96
+ )
97
+ m = block_re.search(new_src)
98
+ if not m:
99
+ failures.append({"capability": cap, "reason": "marker found but block extract failed"})
100
+ continue
101
+ block_text = m.group(0)
102
+ # Promote 4-space indent to 8-space (method body)
103
+ rebased = "\n".join(
104
+ (" " + line) if line.startswith(" ") else line
105
+ for line in block_text.splitlines()
106
+ ) + "\n"
107
+ # Choose sentinel: human-handoff before_push_text uses _ext_before_push_text_;
108
+ # the same capability's after_start uses _ext_after_start_.
109
+ # Simple heuristic: pick whichever sentinel appears first; decide by whether the cap references `text`.
110
+ sentinel = (
111
+ "_ext_before_push_text_"
112
+ if "maybe_handoff(session_id, text" in block_text
113
+ or "maybe_dispatch(text" in block_text
114
+ or "record_user_turn(session_id, text" in block_text
115
+ else "_ext_after_start_"
116
+ )
117
+ # Insert rebased before the sentinel comment line
118
+ sentinel_re = re.compile(
119
+ rf"^([ \t]*)# {re.escape(sentinel)}\b[^\n]*$",
120
+ re.MULTILINE,
121
+ )
122
+ s_match = sentinel_re.search(new_src)
123
+ if not s_match:
124
+ failures.append({"capability": cap, "reason": f"sentinel {sentinel} not found in agent.py"})
125
+ continue
126
+ # Build insertion text (indent aligned to sentinel, i.e. 8 spaces)
127
+ # rebased is already 8-space indented
128
+ # First remove old misplaced block from new_src
129
+ without_old = new_src[: m.start()] + new_src[m.end():]
130
+ # Re-locate sentinel line (position may have shifted)
131
+ s_match2 = re.compile(
132
+ rf"^([ \t]*)# {re.escape(sentinel)}\b[^\n]*$",
133
+ re.MULTILINE,
134
+ ).search(without_old)
135
+ if not s_match2:
136
+ failures.append({"capability": cap, "reason": f"sentinel {sentinel} lost after stripping old block"})
137
+ continue
138
+ new_src = (
139
+ without_old[: s_match2.start()]
140
+ + rebased
141
+ + without_old[s_match2.start():]
142
+ )
143
+ moved.append(cap)
144
+
145
+ if new_src != src:
146
+ AGENT_PY.write_text(new_src, encoding="utf-8")
147
+
148
+ report["agent_py"] = {
149
+ "ok": not failures,
150
+ "patched": moved,
151
+ "failed": failures,
152
+ }
153
+
154
+
155
+ # --------------------------------------------------------------------------- #
156
+ # 2. server.py StaticFiles html=True verification
157
+ # --------------------------------------------------------------------------- #
158
+ def _patch_server_py(report: dict) -> None:
159
+ if not SERVER_PY.exists():
160
+ report["server_py"] = {"ok": False, "skipped": True, "reason": "server.py not found"}
161
+ return
162
+ src = SERVER_PY.read_text(encoding="utf-8")
163
+ if "StaticFiles(directory=str(_DEMO_DIR), html=False)" in src:
164
+ new_src = src.replace(
165
+ "StaticFiles(directory=str(_DEMO_DIR), html=False)",
166
+ "StaticFiles(directory=str(_DEMO_DIR), html=True)",
167
+ )
168
+ SERVER_PY.write_text(new_src, encoding="utf-8")
169
+ report["server_py"] = {"ok": True, "patched": ["StaticFiles html=True"]}
170
+ elif "StaticFiles(directory=str(_DEMO_DIR), html=True)" in src:
171
+ report["server_py"] = {"ok": True, "patched": [], "note": "already html=True"}
172
+ else:
173
+ report["server_py"] = {"ok": True, "patched": [], "note": "no matching StaticFiles mount"}
174
+
175
+
176
+ # --------------------------------------------------------------------------- #
177
+ # 3. Append .env defaults (do not overwrite existing)
178
+ # --------------------------------------------------------------------------- #
179
+ def _patch_env(report: dict) -> None:
180
+ if not ENV_FILE.exists():
181
+ report["env"] = {"ok": True, "skipped": True, "reason": ".env not present yet (run setup-credentials first)"}
182
+ return
183
+ text = ENV_FILE.read_text(encoding="utf-8")
184
+ existing_keys = {
185
+ line.split("=", 1)[0].strip()
186
+ for line in text.splitlines()
187
+ if "=" in line and not line.strip().startswith("#")
188
+ }
189
+ appended = []
190
+ additions = [
191
+ f"{k}={v}" for k, v in ENV_DEFAULTS.items() if k not in existing_keys
192
+ ]
193
+ if additions:
194
+ if not text.endswith("\n"):
195
+ text += "\n"
196
+ text += "\n# Added by post-install-patch.py (capability adapter defaults)\n"
197
+ text += "\n".join(additions) + "\n"
198
+ ENV_FILE.write_text(text, encoding="utf-8")
199
+ appended = [a.split("=", 1)[0] for a in additions]
200
+ report["env"] = {"ok": True, "appended": appended}
201
+
202
+
203
+ # --------------------------------------------------------------------------- #
204
+ # Main
205
+ # --------------------------------------------------------------------------- #
206
+ def main() -> int:
207
+ report: dict = {}
208
+ try:
209
+ _patch_agent_py(report)
210
+ _patch_server_py(report)
211
+ _patch_env(report)
212
+ except Exception as exc: # noqa: BLE001
213
+ report["fatal"] = repr(exc)
214
+ print(json.dumps(report, ensure_ascii=False))
215
+ return 2
216
+ overall_ok = all(
217
+ v.get("ok", False) or v.get("skipped", False) for v in report.values()
218
+ )
219
+ report["ok"] = overall_ok
220
+ print(json.dumps(report, ensure_ascii=False))
221
+ return 0 if overall_ok else 1
222
+
223
+
224
+ if __name__ == "__main__":
225
+ sys.exit(main())
@@ -0,0 +1,393 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """3-Key interactive configuration script.
4
+
5
+ Features:
6
+ 1. Each key is validated for connectivity immediately after input; failure prevents proceeding to the next key.
7
+ 2. Successfully verified keys are written to .credentials_cache (permissions 600);
8
+ re-running the script auto-skips already-passed keys, supporting checkpoint resume (idempotent).
9
+ 3. Final artifacts: root-level `.env` file (permissions 600) + config-report.json.
10
+
11
+ Usage:
12
+ python scripts/setup-credentials.py
13
+ python scripts/setup-credentials.py --reset # Clear cache and reconfigure
14
+ python scripts/setup-credentials.py validate-tencent-cloud --secret-id ... --secret-key ...
15
+ python scripts/setup-credentials.py validate-trtc --app-id ... --app-key ...
16
+ python scripts/setup-credentials.py validate-llm --api-key ... --endpoint ...
17
+ """
18
+ from __future__ import annotations
19
+
20
+ import argparse
21
+ import getpass
22
+ import hashlib
23
+ import json
24
+ import os
25
+ import sys
26
+ import time
27
+ from pathlib import Path
28
+ from typing import Dict
29
+
30
+ # Add capabilities/conversation-core to sys.path to reuse skeleton self-check logic
31
+ _HERE = Path(__file__).resolve().parent
32
+ _PROJECT_ROOT = _HERE.parent
33
+ _CORE_DIR = _PROJECT_ROOT / "capabilities" / "conversation-core"
34
+ sys.path.insert(0, str(_CORE_DIR))
35
+
36
+ from src.credentials import ( # noqa: E402 pylint: disable=wrong-import-position
37
+ LlmCredential,
38
+ TencentCloudCredential,
39
+ TrtcCredential,
40
+ )
41
+ from src.health import ( # noqa: E402 pylint: disable=wrong-import-position
42
+ check_llm,
43
+ check_tencent_cloud,
44
+ check_trtc,
45
+ )
46
+
47
+ # Credential files go into the conversation-core directory, matching src/server.py's load_dotenv path
48
+ # (server.py: _BASE_DIR = capabilities/conversation-core, reads _BASE_DIR/.env)
49
+ CACHE_FILE = _CORE_DIR / ".credentials_cache"
50
+ ENV_FILE = _CORE_DIR / ".env"
51
+ REPORT_FILE = _PROJECT_ROOT / "config-report.json"
52
+
53
+
54
+ # ---------------------------------------------------------------------------
55
+ # Internationalization
56
+ # ---------------------------------------------------------------------------
57
+ def _is_zh() -> bool:
58
+ return os.getenv("LANG", "").lower().startswith("zh")
59
+
60
+
61
+ _T = {
62
+ "header": ("=== TRTC Voice Agent 配置引导 ===", "=== TRTC Voice Agent Setup ==="),
63
+ "step_tc": ("[1/3] 腾讯云 API 密钥", "[1/3] Tencent Cloud API Credentials"),
64
+ "step_trtc": ("[2/3] TRTC 应用凭据", "[2/3] TRTC Application Credentials"),
65
+ "step_llm": ("[3/3] 外部 LLM 接入密钥", "[3/3] External LLM API Key"),
66
+ "input_secret_id": ("SecretId: ", "SecretId: "),
67
+ "input_secret_key": ("SecretKey (隐藏输入): ", "SecretKey (hidden): "),
68
+ "input_region": ("Region [ap-guangzhou]: ", "Region [ap-guangzhou]: "),
69
+ "input_app_id": ("SDKAppID (整数): ", "SDKAppID (integer): "),
70
+ "input_app_key": ("SDKSecretKey (隐藏输入): ", "SDKSecretKey (hidden): "),
71
+ "input_llm_key": ("LLM API Key: ", "LLM API Key: "),
72
+ "input_llm_url": (
73
+ "LLM API URL [https://api.openai.com/v1/chat/completions]: ",
74
+ "LLM API URL [https://api.openai.com/v1/chat/completions]: ",
75
+ ),
76
+ "input_llm_model": ("LLM Model [gpt-4o-mini]: ", "LLM Model [gpt-4o-mini]: "),
77
+ "skip_cached": ("✓ 检测到已通过验证的缓存,跳过本步骤。", "✓ Cached credential found, skipping."),
78
+ "validating": (" 正在校验...", " Validating..."),
79
+ "ok": ("✅ 校验通过", "✅ OK"),
80
+ "fail": ("❌ 校验失败", "❌ Failed"),
81
+ "retry": ("是否重新输入?[Y/n] ", "Retry? [Y/n] "),
82
+ "done": ("=== 三把 Key 配置完成 ===", "=== All 3 keys configured ==="),
83
+ "next_step": (
84
+ "执行 `bash start.sh` 或 `python -m src.server` 启动 Web Demo。",
85
+ "Run `bash start.sh` or `python -m src.server` to launch the Web Demo.",
86
+ ),
87
+ }
88
+
89
+
90
+ def t(key: str) -> str:
91
+ pair = _T[key]
92
+ return pair[0] if _is_zh() else pair[1]
93
+
94
+
95
+ # ---------------------------------------------------------------------------
96
+ # Cache
97
+ # ---------------------------------------------------------------------------
98
+ def _hash(value: str) -> str:
99
+ return hashlib.sha256(value.encode("utf-8")).hexdigest()
100
+
101
+
102
+ def _load_cache() -> Dict[str, str]:
103
+ if not CACHE_FILE.exists():
104
+ return {}
105
+ try:
106
+ return json.loads(CACHE_FILE.read_text(encoding="utf-8"))
107
+ except Exception:
108
+ return {}
109
+
110
+
111
+ def _save_cache(cache: Dict[str, str]) -> None:
112
+ CACHE_FILE.write_text(json.dumps(cache, indent=2), encoding="utf-8")
113
+ try:
114
+ os.chmod(CACHE_FILE, 0o600)
115
+ except OSError:
116
+ pass
117
+
118
+
119
+ def _persist_env(values: Dict[str, str]) -> None:
120
+ """Write / merge .env file and enforce permissions 600."""
121
+ existing: Dict[str, str] = {}
122
+ if ENV_FILE.exists():
123
+ for line in ENV_FILE.read_text(encoding="utf-8").splitlines():
124
+ if "=" in line and not line.strip().startswith("#"):
125
+ k, _, v = line.partition("=")
126
+ existing[k.strip()] = v.strip()
127
+ existing.update(values)
128
+ rendered = "\n".join(f"{k}={v}" for k, v in existing.items()) + "\n"
129
+ ENV_FILE.write_text(rendered, encoding="utf-8")
130
+ try:
131
+ os.chmod(ENV_FILE, 0o600)
132
+ except OSError:
133
+ pass
134
+
135
+
136
+ def _read_env_value(key: str) -> str:
137
+ """Read a single variable value from the generated .env file (for sharing across multi-step config)."""
138
+ if not ENV_FILE.exists():
139
+ return ""
140
+ for line in ENV_FILE.read_text(encoding="utf-8").splitlines():
141
+ if "=" in line and not line.strip().startswith("#"):
142
+ k, _, v = line.partition("=")
143
+ if k.strip() == key:
144
+ return v.strip()
145
+ return ""
146
+
147
+
148
+ # ---------------------------------------------------------------------------
149
+ # Interactive flow
150
+ # ---------------------------------------------------------------------------
151
+ def _step_tencent_cloud(cache: Dict[str, str], report: Dict[str, dict]) -> None:
152
+ print()
153
+ print(t("step_tc"))
154
+ while True:
155
+ secret_id = input(t("input_secret_id")).strip()
156
+ secret_key = getpass.getpass(t("input_secret_key")).strip()
157
+ region = input(t("input_region")).strip() or "ap-guangzhou"
158
+ if not secret_id or not secret_key:
159
+ print(t("fail") + ": empty input")
160
+ continue
161
+ sig = _hash(secret_id + ":" + secret_key)
162
+ if cache.get("tencent_cloud") == sig:
163
+ print(t("skip_cached"))
164
+ return
165
+ print(t("validating"))
166
+ result = check_tencent_cloud(
167
+ TencentCloudCredential(secret_id=secret_id, secret_key=secret_key, region=region)
168
+ )
169
+ report["tencent_cloud"] = result.to_dict() | {"checked_at": int(time.time())}
170
+ if result.ok:
171
+ print(f"{t('ok')} (latency {result.latency_ms}ms)")
172
+ _persist_env(
173
+ {
174
+ "TENCENT_CLOUD_SECRET_ID": secret_id,
175
+ "TENCENT_CLOUD_SECRET_KEY": secret_key,
176
+ "TENCENT_CLOUD_REGION": region,
177
+ }
178
+ )
179
+ cache["tencent_cloud"] = sig
180
+ _save_cache(cache)
181
+ return
182
+ print(f"{t('fail')} [{result.error_code}]: {result.detail}")
183
+ if input(t("retry")).strip().lower() in ("n", "no"):
184
+ sys.exit(1)
185
+
186
+
187
+ def _step_trtc(cache: Dict[str, str], report: Dict[str, dict]) -> None:
188
+ print()
189
+ print(t("step_trtc"))
190
+ # Read previously configured Tencent Cloud credentials for real OpenAPI validation
191
+ tc_cred = TencentCloudCredential(
192
+ secret_id=os.getenv("TENCENT_CLOUD_SECRET_ID", "")
193
+ or _read_env_value("TENCENT_CLOUD_SECRET_ID"),
194
+ secret_key=os.getenv("TENCENT_CLOUD_SECRET_KEY", "")
195
+ or _read_env_value("TENCENT_CLOUD_SECRET_KEY"),
196
+ region=_read_env_value("TENCENT_CLOUD_REGION") or "ap-guangzhou",
197
+ )
198
+ while True:
199
+ app_id_raw = input(t("input_app_id")).strip()
200
+ app_key = getpass.getpass(t("input_app_key")).strip()
201
+ if not app_id_raw or not app_key:
202
+ print(t("fail") + ": empty input")
203
+ continue
204
+ try:
205
+ app_id = int(app_id_raw)
206
+ except ValueError:
207
+ print(t("fail") + ": SDKAppID must be integer")
208
+ continue
209
+
210
+ # —— SDKSecretKey defensive validation ——
211
+ # TRTC SDKSecretKey is a 64-char hex string (format copied directly from trtc.io console).
212
+ # Common error: user pastes twice → 128 chars; or pastes extra whitespace.
213
+ if not all(c in "0123456789abcdefABCDEF" for c in app_key):
214
+ print(
215
+ t("fail")
216
+ + ": SDKSecretKey only allows 0-9 / a-f characters, please re-copy from TRTC console"
217
+ )
218
+ continue
219
+ if len(app_key) == 128 and app_key[:64] == app_key[64:]:
220
+ print(
221
+ " ⚠ Detected SDKSecretKey pasted twice (128 chars = same string copied twice), "
222
+ "auto-truncated to first 64 characters"
223
+ )
224
+ app_key = app_key[:64]
225
+ if len(app_key) != 64:
226
+ print(
227
+ f"{t('fail')}: SDKSecretKey must be 64 characters (you entered {len(app_key)}), "
228
+ "please re-copy"
229
+ )
230
+ continue
231
+
232
+ sig = _hash(f"{app_id}:{app_key}")
233
+ if cache.get("trtc") == sig:
234
+ print(t("skip_cached"))
235
+ return
236
+ print(t("validating"))
237
+ # Default to intl (trtc.io international); overseas devs don't need to select region
238
+ result = check_trtc(
239
+ TrtcCredential(sdk_app_id=app_id, sdk_secret_key=app_key, region="intl"),
240
+ tencent=tc_cred if tc_cred.configured else None,
241
+ )
242
+ report["trtc"] = result.to_dict() | {"checked_at": int(time.time())}
243
+ if result.ok:
244
+ print(f"{t('ok')} (latency {result.latency_ms}ms; {result.detail or ''})")
245
+ _persist_env(
246
+ {
247
+ "TRTC_SDK_APP_ID": str(app_id),
248
+ "TRTC_SDK_SECRET_KEY": app_key,
249
+ }
250
+ )
251
+ cache["trtc"] = sig
252
+ _save_cache(cache)
253
+ return
254
+ print(f"{t('fail')} [{result.error_code}]: {result.detail}")
255
+ if input(t("retry")).strip().lower() in ("n", "no"):
256
+ sys.exit(1)
257
+
258
+
259
+ def _step_llm(cache: Dict[str, str], report: Dict[str, dict]) -> None:
260
+ print()
261
+ print(t("step_llm"))
262
+ retries = 0
263
+ while True:
264
+ api_key = input(t("input_llm_key")).strip()
265
+ api_url = input(t("input_llm_url")).strip() or "https://api.openai.com/v1/chat/completions"
266
+ model = input(t("input_llm_model")).strip() or "gpt-4o-mini"
267
+ if not api_key:
268
+ print(t("fail") + ": empty input")
269
+ continue
270
+ sig = _hash(f"{api_key}:{api_url}:{model}")
271
+ if cache.get("llm") == sig:
272
+ print(t("skip_cached"))
273
+ return
274
+ print(t("validating"))
275
+ result = check_llm(
276
+ LlmCredential(api_key=api_key, api_url=api_url, model=model)
277
+ )
278
+ report["llm"] = result.to_dict() | {"checked_at": int(time.time())}
279
+ if result.ok:
280
+ print(f"{t('ok')} (latency {result.latency_ms}ms)")
281
+ _persist_env(
282
+ {"LLM_API_KEY": api_key, "LLM_API_URL": api_url, "LLM_MODEL": model}
283
+ )
284
+ cache["llm"] = sig
285
+ _save_cache(cache)
286
+ return
287
+ retries += 1
288
+ print(f"{t('fail')} [{result.error_code}]: {result.detail}")
289
+ if retries >= 3:
290
+ print("Reached 3 failure limit. Please check your LLM Endpoint / Key and retry.")
291
+ sys.exit(1)
292
+ if input(t("retry")).strip().lower() in ("n", "no"):
293
+ sys.exit(1)
294
+
295
+
296
+ # ---------------------------------------------------------------------------
297
+ # Single-step validation subcommands (for start.sh reuse)
298
+ # ---------------------------------------------------------------------------
299
+ def _validate_tencent_cloud(args: argparse.Namespace) -> int:
300
+ r = check_tencent_cloud(
301
+ TencentCloudCredential(args.secret_id, args.secret_key, args.region or "ap-guangzhou")
302
+ )
303
+ print(json.dumps(r.to_dict()))
304
+ return 0 if r.ok else 1
305
+
306
+
307
+ def _validate_trtc(args: argparse.Namespace) -> int:
308
+ try:
309
+ app_id = int(args.app_id)
310
+ except ValueError:
311
+ print(json.dumps({"status": "failed", "error_code": "E002", "detail": "invalid app_id"}))
312
+ return 1
313
+ tc = None
314
+ if getattr(args, "secret_id", None) and getattr(args, "secret_key", None):
315
+ tc = TencentCloudCredential(args.secret_id, args.secret_key, args.region or "ap-guangzhou")
316
+ r = check_trtc(
317
+ TrtcCredential(sdk_app_id=app_id, sdk_secret_key=args.app_key),
318
+ tencent=tc,
319
+ )
320
+ print(json.dumps(r.to_dict()))
321
+ return 0 if r.ok else 1
322
+
323
+
324
+ def _validate_llm(args: argparse.Namespace) -> int:
325
+ r = check_llm(
326
+ LlmCredential(
327
+ api_key=args.api_key,
328
+ api_url=args.endpoint or "https://api.openai.com/v1/chat/completions",
329
+ model=args.model or "gpt-4o-mini",
330
+ )
331
+ )
332
+ print(json.dumps(r.to_dict()))
333
+ return 0 if r.ok else 1
334
+
335
+
336
+ # ---------------------------------------------------------------------------
337
+ # main
338
+ # ---------------------------------------------------------------------------
339
+ def main() -> int:
340
+ parser = argparse.ArgumentParser(description="TRTC Voice Agent credentials setup")
341
+ parser.add_argument("--reset", action="store_true", help="Clear cache and reconfigure")
342
+ sub = parser.add_subparsers(dest="cmd")
343
+
344
+ p_tc = sub.add_parser("validate-tencent-cloud")
345
+ p_tc.add_argument("--secret-id", required=True)
346
+ p_tc.add_argument("--secret-key", required=True)
347
+ p_tc.add_argument("--region", default="ap-guangzhou")
348
+
349
+ p_trtc = sub.add_parser("validate-trtc")
350
+ p_trtc.add_argument("--app-id", required=True)
351
+ p_trtc.add_argument("--app-key", required=True)
352
+ p_trtc.add_argument("--secret-id", default="", help="Tencent Cloud SecretId (optional, enables deep validation)")
353
+ p_trtc.add_argument("--secret-key", default="", help="Tencent Cloud SecretKey (optional, enables deep validation)")
354
+ p_trtc.add_argument("--region", default="ap-guangzhou")
355
+
356
+ p_llm = sub.add_parser("validate-llm")
357
+ p_llm.add_argument("--api-key", required=True)
358
+ p_llm.add_argument("--endpoint", default="")
359
+ p_llm.add_argument("--model", default="")
360
+
361
+ args = parser.parse_args()
362
+
363
+ if args.cmd == "validate-tencent-cloud":
364
+ return _validate_tencent_cloud(args)
365
+ if args.cmd == "validate-trtc":
366
+ return _validate_trtc(args)
367
+ if args.cmd == "validate-llm":
368
+ return _validate_llm(args)
369
+
370
+ if args.reset and CACHE_FILE.exists():
371
+ CACHE_FILE.unlink()
372
+
373
+ print(t("header"))
374
+ cache = _load_cache()
375
+ report: Dict[str, dict] = {}
376
+ _step_tencent_cloud(cache, report)
377
+ _step_trtc(cache, report)
378
+ _step_llm(cache, report)
379
+
380
+ REPORT_FILE.write_text(json.dumps(report, indent=2, ensure_ascii=False), encoding="utf-8")
381
+ try:
382
+ os.chmod(REPORT_FILE, 0o644)
383
+ except OSError:
384
+ pass
385
+
386
+ print()
387
+ print(t("done"))
388
+ print(t("next_step"))
389
+ return 0
390
+
391
+
392
+ if __name__ == "__main__":
393
+ sys.exit(main())