@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.
- package/.cursor/rules/main.mdc +12 -0
- package/AGENTS.md +14 -104
- package/CLAUDE.md +15 -127
- package/CODEBUDDY.md +32 -118
- package/README.md +7 -5
- package/README.zh.md +7 -5
- package/bin/cli.js +133 -41
- package/hooks/__pycache__/cursor-adapter.cpython-313.pyc +0 -0
- package/hooks/cursor-adapter.py +45 -18
- package/hooks/hooks-cursor.json +5 -18
- package/hooks/hooks.json +6 -31
- package/knowledge-base/conference/web/index.yaml +143 -0
- package/knowledge-base/platform-slice-template.md +1041 -133
- package/knowledge-base/products.yaml +76 -0
- package/knowledge-base/scenario-spec.md +1316 -115
- package/knowledge-base/scenarios/conference/base/general-conference.md +22 -2
- package/knowledge-base/scenarios/conference/base/webinar-conference.md +14 -0
- package/knowledge-base/scenarios/conference/medical/1v1-video-consultation.md +19 -0
- package/knowledge-base/scenarios/conference/medical/medical-multidoctor-consultation.md +13 -0
- package/knowledge-base/scenarios/live/entertainment-live-room.md +12 -0
- package/knowledge-base/slice-spec.md +2377 -299
- package/knowledge-base/slices/conference/web/integration-audit.md +1 -1
- package/knowledge-base/slices/conference/web/login-auth.md +14 -1
- package/knowledge-base/tooling/aliases.yaml +92 -0
- package/knowledge-base/tooling/intent-signals.yaml +181 -0
- package/knowledge-base/tooling/symptom-keywords.yaml +21 -0
- package/package.json +1 -1
- package/skills/trtc/SKILL.md +202 -245
- package/skills/trtc/hooks/__pycache__/report_prompt.cpython-313.pyc +0 -0
- package/skills/{trtc-topic/guardrails → trtc/hooks}/gate_slice_read.py +12 -8
- package/skills/{trtc-topic/guardrails → trtc/hooks}/gate_slice_write.py +16 -12
- package/skills/{trtc-topic/guardrails → trtc/hooks}/stop_require_apply_evidence.py +22 -14
- package/skills/trtc/hooks/topic_phase_gate.py +161 -0
- package/skills/{trtc-topic → trtc}/runtime/README.md +2 -2
- package/skills/{trtc-onboarding/reference/reporting-protocol.md → trtc/runtime/REPORTING.md} +5 -5
- package/skills/{trtc-topic → trtc}/runtime/RUNTIME.md +5 -5
- package/skills/trtc/runtime/lib/__init__.py +0 -0
- package/skills/{trtc-topic → trtc}/runtime/package-lock.json +2 -2
- package/skills/{trtc-topic → trtc}/runtime/package.json +2 -2
- package/skills/{trtc-topic → trtc}/runtime/telemetry-bridge.mjs +1 -1
- package/skills/{trtc-topic/scripts → trtc/tools}/STATE-MACHINE-GUIDE.md +23 -23
- package/skills/trtc/tools/__init__.py +2 -0
- package/skills/trtc/tools/__pycache__/__init__.cpython-313.pyc +0 -0
- package/skills/trtc/tools/__pycache__/query_classifier.cpython-313.pyc +0 -0
- package/skills/trtc/tools/__pycache__/reporting.cpython-313.pyc +0 -0
- package/skills/trtc/tools/__pycache__/search.cpython-313.pyc +0 -0
- package/skills/trtc/tools/__pycache__/session.cpython-313.pyc +0 -0
- package/skills/trtc/tools/apply.py +540 -0
- package/skills/trtc/tools/docs.py +712 -0
- package/skills/trtc/tools/docsbot.py +182 -0
- package/skills/trtc/tools/entry/render_ai_instructions.py +92 -0
- package/skills/trtc/tools/flow.py +1089 -0
- package/skills/{trtc-topic/scripts → trtc/tools}/init_slice_queue.py +5 -4
- package/skills/{trtc-topic/scripts → trtc/tools}/next_slice.py +5 -4
- package/skills/trtc/tools/query_classifier.py +301 -0
- package/skills/trtc/tools/reporting.py +447 -0
- package/skills/trtc/tools/search.py +817 -0
- package/skills/trtc/tools/session.py +1261 -0
- package/skills/trtc/tools/state_machine.py +690 -0
- package/skills/trtc-ai-service/README.md +195 -0
- package/skills/trtc-ai-service/README.zh-CN.md +193 -0
- package/skills/trtc-ai-service/SKILL.md +945 -0
- package/skills/trtc-ai-service/auto_adapters/README.md +40 -0
- package/skills/trtc-ai-service/auto_adapters/frontend-spa/README.md +27 -0
- package/skills/trtc-ai-service/auto_adapters/frontend-spa/angular/voice-agent.component.ts.tpl +131 -0
- package/skills/trtc-ai-service/auto_adapters/frontend-spa/manifest.yaml +57 -0
- package/skills/trtc-ai-service/auto_adapters/frontend-spa/react/VoiceAgent.tsx.tpl +142 -0
- package/skills/trtc-ai-service/auto_adapters/frontend-spa/vue/VoiceAgent.vue.tpl +121 -0
- package/skills/trtc-ai-service/auto_adapters/integration_templates/generic-backend.md +45 -0
- package/skills/trtc-ai-service/auto_adapters/integration_templates/generic-frontend.md +51 -0
- package/skills/trtc-ai-service/auto_adapters/integration_templates/generic-rest-api.md +93 -0
- package/skills/trtc-ai-service/auto_adapters/java-backend/README.md +25 -0
- package/skills/trtc-ai-service/auto_adapters/java-backend/manifest.yaml +30 -0
- package/skills/trtc-ai-service/auto_adapters/java-backend/quarkus/VoiceAgentFilter.java.tpl +64 -0
- package/skills/trtc-ai-service/auto_adapters/java-backend/springboot/VoiceAgentFilter.java.tpl +91 -0
- package/skills/trtc-ai-service/auto_adapters/manifest.yaml +43 -0
- package/skills/trtc-ai-service/auto_adapters/node-backend/README.md +25 -0
- package/skills/trtc-ai-service/auto_adapters/node-backend/express.js.tpl +40 -0
- package/skills/trtc-ai-service/auto_adapters/node-backend/fastify.js.tpl +27 -0
- package/skills/trtc-ai-service/auto_adapters/node-backend/koa.js.tpl +31 -0
- package/skills/trtc-ai-service/auto_adapters/node-backend/manifest.yaml +47 -0
- package/skills/trtc-ai-service/auto_adapters/python-backend/README.md +22 -0
- package/skills/trtc-ai-service/auto_adapters/python-backend/django.py.tpl +32 -0
- package/skills/trtc-ai-service/auto_adapters/python-backend/fastapi.py.tpl +35 -0
- package/skills/trtc-ai-service/auto_adapters/python-backend/flask.py.tpl +31 -0
- package/skills/trtc-ai-service/auto_adapters/python-backend/manifest.yaml +45 -0
- package/skills/trtc-ai-service/capabilities/__init__.py +43 -0
- package/skills/trtc-ai-service/capabilities/conversation-core/.env.example +29 -0
- package/skills/trtc-ai-service/capabilities/conversation-core/INTEGRATION.md +134 -0
- package/skills/trtc-ai-service/capabilities/conversation-core/INTERFACE_ADAPT.md +111 -0
- package/skills/trtc-ai-service/capabilities/conversation-core/QUICK_START.md +62 -0
- package/skills/trtc-ai-service/capabilities/conversation-core/manifest.yaml +250 -0
- package/skills/trtc-ai-service/capabilities/conversation-core/requirements.txt +6 -0
- package/skills/trtc-ai-service/capabilities/conversation-core/src/__init__.py +10 -0
- package/skills/trtc-ai-service/capabilities/conversation-core/src/_capability_loader.py +218 -0
- package/skills/trtc-ai-service/capabilities/conversation-core/src/agent.py +231 -0
- package/skills/trtc-ai-service/capabilities/conversation-core/src/credentials.py +132 -0
- package/skills/trtc-ai-service/capabilities/conversation-core/src/health.py +355 -0
- package/skills/trtc-ai-service/capabilities/conversation-core/src/log_filter.py +76 -0
- package/skills/trtc-ai-service/capabilities/conversation-core/src/modality.py +109 -0
- package/skills/trtc-ai-service/capabilities/conversation-core/src/server.py +312 -0
- package/skills/trtc-ai-service/capabilities/conversation-core/src/trtc_client.py +315 -0
- package/skills/trtc-ai-service/capabilities/conversation-core/src/usersig.py +90 -0
- package/skills/trtc-ai-service/capabilities/conversation-core/tests/test_skeleton.py +216 -0
- package/skills/trtc-ai-service/capabilities/conversation-core/web-demo/README.md +48 -0
- package/skills/trtc-ai-service/capabilities/conversation-core/web-demo/app.js +415 -0
- package/skills/trtc-ai-service/capabilities/conversation-core/web-demo/index.html +68 -0
- package/skills/trtc-ai-service/capabilities/conversation-core/web-demo/styles.css +136 -0
- package/skills/trtc-ai-service/capabilities/digital-human/README.md +31 -0
- package/skills/trtc-ai-service/capabilities/digital-human/manifest.yaml +64 -0
- package/skills/trtc-ai-service/capabilities/digital-human/src/__init__.py +2 -0
- package/skills/trtc-ai-service/capabilities/digital-human/src/router.py +43 -0
- package/skills/trtc-ai-service/capabilities/human-handoff/INTERFACE_ADAPT.md +353 -0
- package/skills/trtc-ai-service/capabilities/human-handoff/README.md +44 -0
- package/skills/trtc-ai-service/capabilities/human-handoff/manifest.yaml +227 -0
- package/skills/trtc-ai-service/capabilities/human-handoff/src/__init__.py +2 -0
- package/skills/trtc-ai-service/capabilities/human-handoff/src/adapters/__init__.py +9 -0
- package/skills/trtc-ai-service/capabilities/human-handoff/src/adapters/default_rest.py +242 -0
- package/skills/trtc-ai-service/capabilities/human-handoff/src/adapters/factory.py +89 -0
- package/skills/trtc-ai-service/capabilities/human-handoff/src/adapters/local_queue.py +258 -0
- package/skills/trtc-ai-service/capabilities/human-handoff/src/adapters/mock.py +132 -0
- package/skills/trtc-ai-service/capabilities/human-handoff/src/core/__init__.py +25 -0
- package/skills/trtc-ai-service/capabilities/human-handoff/src/core/intent_detector.py +75 -0
- package/skills/trtc-ai-service/capabilities/human-handoff/src/core/models.py +163 -0
- package/skills/trtc-ai-service/capabilities/human-handoff/src/core/service.py +192 -0
- package/skills/trtc-ai-service/capabilities/human-handoff/src/feedback_store.py +54 -0
- package/skills/trtc-ai-service/capabilities/human-handoff/src/ports/__init__.py +4 -0
- package/skills/trtc-ai-service/capabilities/human-handoff/src/ports/handoff_client.py +86 -0
- package/skills/trtc-ai-service/capabilities/human-handoff/src/queue.py +62 -0
- package/skills/trtc-ai-service/capabilities/human-handoff/src/router.py +201 -0
- package/skills/trtc-ai-service/capabilities/human-handoff/src/summary_link.py +77 -0
- package/skills/trtc-ai-service/capabilities/human-handoff/src/trigger.py +25 -0
- package/skills/trtc-ai-service/capabilities/knowledge-base/INTERFACE_ADAPT.md +297 -0
- package/skills/trtc-ai-service/capabilities/knowledge-base/README.md +51 -0
- package/skills/trtc-ai-service/capabilities/knowledge-base/data/faq.json +20 -0
- package/skills/trtc-ai-service/capabilities/knowledge-base/manifest.yaml +211 -0
- package/skills/trtc-ai-service/capabilities/knowledge-base/src/__init__.py +8 -0
- package/skills/trtc-ai-service/capabilities/knowledge-base/src/adapters/__init__.py +9 -0
- package/skills/trtc-ai-service/capabilities/knowledge-base/src/adapters/default_rest.py +209 -0
- package/skills/trtc-ai-service/capabilities/knowledge-base/src/adapters/factory.py +86 -0
- package/skills/trtc-ai-service/capabilities/knowledge-base/src/adapters/local_json.py +172 -0
- package/skills/trtc-ai-service/capabilities/knowledge-base/src/adapters/mock.py +91 -0
- package/skills/trtc-ai-service/capabilities/knowledge-base/src/core/__init__.py +12 -0
- package/skills/trtc-ai-service/capabilities/knowledge-base/src/core/models.py +77 -0
- package/skills/trtc-ai-service/capabilities/knowledge-base/src/core/scoring.py +73 -0
- package/skills/trtc-ai-service/capabilities/knowledge-base/src/core/service.py +78 -0
- package/skills/trtc-ai-service/capabilities/knowledge-base/src/ports/__init__.py +4 -0
- package/skills/trtc-ai-service/capabilities/knowledge-base/src/ports/kb_client.py +61 -0
- package/skills/trtc-ai-service/capabilities/knowledge-base/src/retriever.py +56 -0
- package/skills/trtc-ai-service/capabilities/knowledge-base/src/router.py +85 -0
- package/skills/trtc-ai-service/capabilities/session-summary/INTERFACE_ADAPT.md +99 -0
- package/skills/trtc-ai-service/capabilities/session-summary/README.md +47 -0
- package/skills/trtc-ai-service/capabilities/session-summary/data/test_session.json +18 -0
- package/skills/trtc-ai-service/capabilities/session-summary/manifest.yaml +165 -0
- package/skills/trtc-ai-service/capabilities/session-summary/src/__init__.py +2 -0
- package/skills/trtc-ai-service/capabilities/session-summary/src/adapters/__init__.py +5 -0
- package/skills/trtc-ai-service/capabilities/session-summary/src/adapters/base.py +31 -0
- package/skills/trtc-ai-service/capabilities/session-summary/src/adapters/default_rest.py +67 -0
- package/skills/trtc-ai-service/capabilities/session-summary/src/adapters/factory.py +51 -0
- package/skills/trtc-ai-service/capabilities/session-summary/src/adapters/local_json.py +42 -0
- package/skills/trtc-ai-service/capabilities/session-summary/src/adapters/mock.py +22 -0
- package/skills/trtc-ai-service/capabilities/session-summary/src/recorder.py +210 -0
- package/skills/trtc-ai-service/capabilities/session-summary/src/router.py +93 -0
- package/skills/trtc-ai-service/capabilities/session-summary/src/summarizer.py +163 -0
- package/skills/trtc-ai-service/capabilities/tool-calling/INTERFACE_ADAPT.md +158 -0
- package/skills/trtc-ai-service/capabilities/tool-calling/README.md +50 -0
- package/skills/trtc-ai-service/capabilities/tool-calling/data/tools.yaml +58 -0
- package/skills/trtc-ai-service/capabilities/tool-calling/examples/__init__.py +1 -0
- package/skills/trtc-ai-service/capabilities/tool-calling/examples/local_tools.py +101 -0
- package/skills/trtc-ai-service/capabilities/tool-calling/manifest.yaml +146 -0
- package/skills/trtc-ai-service/capabilities/tool-calling/src/__init__.py +8 -0
- package/skills/trtc-ai-service/capabilities/tool-calling/src/dispatcher.py +54 -0
- package/skills/trtc-ai-service/capabilities/tool-calling/src/registry.py +219 -0
- package/skills/trtc-ai-service/capabilities/tool-calling/src/router.py +50 -0
- package/skills/trtc-ai-service/references/business-contract-spec.md +263 -0
- package/skills/trtc-ai-service/scenarios/custom-builder/README.md +86 -0
- package/skills/trtc-ai-service/scenarios/custom-builder/output-templates/recipe.yaml.j2 +194 -0
- package/skills/trtc-ai-service/scenarios/custom-builder/prompts/q1-business-scenario.md +43 -0
- package/skills/trtc-ai-service/scenarios/custom-builder/prompts/q2-io-modality.md +57 -0
- package/skills/trtc-ai-service/scenarios/custom-builder/prompts/q3-ui-form.md +55 -0
- package/skills/trtc-ai-service/scenarios/custom-builder/prompts/q4-capabilities.md +78 -0
- package/skills/trtc-ai-service/scenarios/customer-service/README.md +114 -0
- package/skills/trtc-ai-service/scenarios/customer-service/recipe.yaml +154 -0
- package/skills/trtc-ai-service/scenarios/customer-service/sample-data/README.md +32 -0
- package/skills/trtc-ai-service/scenarios/customer-service/sample-data/faq-sample.json +37 -0
- package/skills/trtc-ai-service/scenarios/customer-service/system-prompt.template.md +94 -0
- package/skills/trtc-ai-service/scenarios/customer-service/ui/admin-board/app.js +347 -0
- package/skills/trtc-ai-service/scenarios/customer-service/ui/admin-board/index.html +125 -0
- package/skills/trtc-ai-service/scenarios/customer-service/ui/admin-board/styles.css +487 -0
- package/skills/trtc-ai-service/scenarios/customer-service/ui/admin-board/tokens.css +71 -0
- package/skills/trtc-ai-service/scenarios/customer-service/ui/design-system/DESIGN_GUIDELINES.md +370 -0
- package/skills/trtc-ai-service/scenarios/customer-service/ui/voice-customer-service/README.md +68 -0
- package/skills/trtc-ai-service/scenarios/customer-service/ui/voice-customer-service/app.js +1307 -0
- package/skills/trtc-ai-service/scenarios/customer-service/ui/voice-customer-service/data.js +40 -0
- package/skills/trtc-ai-service/scenarios/customer-service/ui/voice-customer-service/index.html +233 -0
- package/skills/trtc-ai-service/scenarios/customer-service/ui/voice-customer-service/mock-shop.json +21 -0
- package/skills/trtc-ai-service/scenarios/customer-service/ui/voice-customer-service/styles.css +603 -0
- package/skills/trtc-ai-service/scenarios/customer-service/ui/voice-customer-service/tokens.css +71 -0
- package/skills/trtc-ai-service/scenarios/customer-service/ui/widget-floating/agent-link.js +323 -0
- package/skills/trtc-ai-service/scenarios/customer-service/ui/widget-floating/app.js +458 -0
- package/skills/trtc-ai-service/scenarios/customer-service/ui/widget-floating/index.html +109 -0
- package/skills/trtc-ai-service/scenarios/customer-service/ui/widget-floating/styles.css +489 -0
- package/skills/trtc-ai-service/scenarios/customer-service/ui/widget-floating/tokens.css +59 -0
- package/skills/trtc-ai-service/scripts/add-capability.py +364 -0
- package/skills/trtc-ai-service/scripts/contract-adapt.py +334 -0
- package/skills/trtc-ai-service/scripts/detect-stack.py +40 -0
- package/skills/trtc-ai-service/scripts/lib/__init__.py +20 -0
- package/skills/trtc-ai-service/scripts/lib/adapter_codegen.py +509 -0
- package/skills/trtc-ai-service/scripts/lib/arbitrator.py +152 -0
- package/skills/trtc-ai-service/scripts/lib/contract_resolver.py +519 -0
- package/skills/trtc-ai-service/scripts/lib/credential_validators.py +253 -0
- package/skills/trtc-ai-service/scripts/lib/curl_parser.py +303 -0
- package/skills/trtc-ai-service/scripts/lib/degrader.py +140 -0
- package/skills/trtc-ai-service/scripts/lib/injector.py +347 -0
- package/skills/trtc-ai-service/scripts/lib/manifest_resolver.py +288 -0
- package/skills/trtc-ai-service/scripts/lib/openapi_parser.py +289 -0
- package/skills/trtc-ai-service/scripts/lib/stack_detector.py +159 -0
- package/skills/trtc-ai-service/scripts/lib/tokens_compile.py +204 -0
- package/skills/trtc-ai-service/scripts/post-install-patch.py +225 -0
- package/skills/trtc-ai-service/scripts/setup-credentials.py +393 -0
- package/skills/trtc-ai-service/scripts/verify-credentials.py +108 -0
- package/skills/trtc-ai-service/start.sh +111 -0
- package/skills/trtc-ai-service/tests/__init__.py +1 -0
- package/skills/trtc-ai-service/tests/test_arbitrator.py +64 -0
- package/skills/trtc-ai-service/tests/test_capability_overlay.py +85 -0
- package/skills/trtc-ai-service/tests/test_contract_resolver.py +190 -0
- package/skills/trtc-ai-service/tests/test_handoff_ports.py +195 -0
- package/skills/trtc-ai-service/tests/test_kb_ports.py +195 -0
- package/skills/trtc-ai-service/tests/test_manifest_resolver.py +95 -0
- package/skills/trtc-ai-service/tests/test_recipe_assembly.py +175 -0
- package/skills/trtc-ai-service/tests/test_stack_and_degrader.py +101 -0
- package/skills/trtc-ai-service/tests/test_verify_credentials.py +285 -0
- package/skills/trtc-ai-service/triggers.yaml +29 -0
- package/skills/trtc-conference/SKILL.md +324 -0
- package/skills/trtc-conference/flows/onboarding.md +205 -0
- package/skills/trtc-conference/flows/topic.md +474 -0
- package/skills/trtc-conference/flows/troubleshoot.md +85 -0
- package/skills/trtc-conference/hooks/pretooluse_require_business_decisions.py +213 -0
- package/skills/trtc-conference/playbooks/medical-quickstart.md +84 -0
- package/skills/trtc-conference/playbooks/official-roomkit.md +97 -0
- package/skills/trtc-conference/references/local-usersig/basic-info-config.ts +39 -0
- package/skills/trtc-conference/references/usersig-handling.md +134 -0
- package/skills/trtc-conference/templates/medical-consultation/src/config/lib-generate-test-usersig-es.min.d.ts +4 -0
- package/skills/trtc-conference/templates/medical-consultation/src/config/lib-generate-test-usersig-es.min.js +2 -0
- package/skills/trtc-conference/tests/__pycache__/test_conference_onboarding_contract.cpython-313-pytest-9.0.2.pyc +0 -0
- package/skills/trtc-conference/tests/__pycache__/test_conference_topic_flow_contract.cpython-313-pytest-9.0.2.pyc +0 -0
- package/skills/trtc-conference/tests/test_conference_index_contract.py +43 -0
- package/skills/trtc-conference/tests/test_conference_onboarding_contract.py +103 -0
- package/skills/trtc-conference/tests/test_conference_template_contract.py +25 -0
- package/skills/trtc-conference/tests/test_conference_topic_flow_contract.py +132 -0
- package/skills/trtc-conference/tools/apply_checks.py +328 -0
- package/skills/trtc-conference/verify_lib/__init__.py +0 -0
- package/skills/{trtc-apply/guardrails/apply_lib → trtc-conference/verify_lib}/rule_parser.py +1 -1
- package/skills/trtc-docs/SKILL.md +91 -119
- package/.cursor/rules/ui-mode.mdc +0 -99
- package/ai-instructions/base.md +0 -13
- package/ai-instructions/ui-mode.md +0 -93
- package/knowledge-base/index.yaml +0 -462
- package/skills/trtc/room-builder/SKILL.md +0 -133
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/README.md +0 -108
- package/skills/trtc/room-builder/tools/render_ai_instructions.py +0 -226
- package/skills/trtc-apply/SKILL.md +0 -97
- package/skills/trtc-onboarding/SKILL.md +0 -841
- package/skills/trtc-onboarding/reference/path-a1-demo.md +0 -103
- package/skills/trtc-onboarding/reference/path-a2-integrate.md +0 -737
- package/skills/trtc-onboarding/reference/path-b-troubleshoot.md +0 -186
- package/skills/trtc-onboarding/reference/path-c-expand.md +0 -43
- package/skills/trtc-onboarding/reference/supported-matrix.md +0 -100
- package/skills/trtc-search/SKILL.md +0 -228
- package/skills/trtc-topic/SKILL.md +0 -622
- package/skills/trtc-topic/scripts/apply.py +0 -581
- package/skills/trtc-topic/scripts/lib/state_machine.py +0 -328
- package/skills/trtc-topic/tests/README.md +0 -70
- package/skills/trtc-topic/tests/conftest.py +0 -72
- package/skills/trtc-topic/tests/test_apply_cli.py +0 -480
- package/skills/trtc-topic/tests/test_end_to_end.py +0 -305
- package/skills/trtc-topic/tests/test_finalize_session.py +0 -51
- package/skills/trtc-topic/tests/test_gates.py +0 -316
- package/skills/trtc-topic/tests/test_session_resolver.py +0 -260
- package/skills/trtc-topic/tests/test_state_machine.py +0 -414
- package/skills/trtc-topic/tests/test_stop_require_apply.py +0 -99
- package/skills/trtc-topic/tests/test_topic_skill_invariants.py +0 -130
- /package/skills/{trtc-topic → trtc}/runtime/lib/platforms.py +0 -0
- /package/skills/{trtc-topic → trtc}/runtime/telemetry_collector.py +0 -0
- /package/skills/{trtc-onboarding/reference → trtc/runtime}/usersig-handling.md +0 -0
- /package/skills/{trtc-topic/scripts → trtc/tools}/finalize_session.py +0 -0
- /package/skills/{trtc-apply/guardrails/apply_lib → trtc-ai-service/capabilities/conversation-core/tests}/__init__.py +0 -0
- /package/skills/{trtc-topic → trtc-conference}/references/execution-units.yaml +0 -0
- /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
- /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
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/docs/backend-contract.zh-CN.md +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/docs/integration.zh-CN.md +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/docs/theme.zh-CN.md +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/index.html +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/package.json +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/postcss.config.js +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/App.vue +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/components/ConsultationManagePanel.vue +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/components/LanguageSwitch.vue +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/components/LoadingSpinner.vue +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/components/MedicalAlert.vue +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/components/MedicalBusinessPanel.vue +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/components/MedicalButton.vue +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/components/MedicalConfirmDialog.vue +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/components/MedicalDataPanel.vue +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/components/MedicalRecordPanel.vue +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/components/PrescriptionPanel.vue +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/config/basic-info-config.ts +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/config/runtime-config.ts +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/env.d.ts +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/features/consultation/components/ConsultationChatPanel.vue +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/features/consultation/components/ConsultationMembersPanel.vue +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/features/consultation/components/ConsultationTranscriptionPanel.vue +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/features/consultation/components/ConsultationVideoStage.vue +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/features/consultation/components/InviteDoctorDialog.vue +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/features/consultation/components/KickMemberConfirmDialog.vue +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/features/consultation/types.ts +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/features/consultation/useConsultationChat.ts +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/features/consultation/useConsultationDevices.ts +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/features/consultation/useConsultationParticipants.ts +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/features/consultation/useConsultationPermissions.ts +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/features/consultation/utils.ts +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/i18n/en-US/index.ts +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/i18n/index.ts +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/i18n/medicalTranslate.ts +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/i18n/state.ts +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/i18n/zh-CN/index.ts +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/main.ts +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/mock/appointments.ts +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/mock/users.ts +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/router/index.ts +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/services/adapters/index.ts +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/services/adapters/integration/appointmentService.ts +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/services/adapters/integration/authService.ts +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/services/adapters/integration/launchContext.ts +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/services/adapters/integration/userService.ts +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/services/adapters/mock/appointmentService.ts +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/services/adapters/mock/authService.ts +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/services/adapters/mock/userService.ts +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/services/adapters/types.ts +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/shared/icons.ts +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/styles/index.css +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/styles/tailwind.css +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/styles/theme.css +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/utils/auth.ts +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/utils/format.ts +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/utils/navigation.ts +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/utils/session.ts +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/views/DoctorConsultationView.vue +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/views/DoctorDashboardView.vue +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/views/LoginView.vue +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/views/PatientConsultationFinishedView.vue +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/views/PatientConsultationView.vue +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/views/PatientSelectDoctorView.vue +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/src/views/PatientWaitingView.vue +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/tsconfig.json +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/tsconfig.node.json +0 -0
- /package/skills/{trtc/room-builder/templates/scenarios → trtc-conference/templates}/medical-consultation/vite.config.ts +0 -0
- /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
- /package/skills/{trtc-topic/runtime/lib → trtc-conference/tools}/__init__.py +0 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Generic REST API Integration Guide (L3 Manual Fallback)
|
|
2
|
+
|
|
3
|
+
> When the Agent cannot identify your tech stack, or it's not in the supported adapter list,
|
|
4
|
+
> connect directly via the REST API exposed by conversation-core.
|
|
5
|
+
|
|
6
|
+
## 1. Start the Skeleton
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
cd capabilities/conversation-core
|
|
10
|
+
python -m src.server # Default 0.0.0.0:3000
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## 2. Endpoint List
|
|
14
|
+
|
|
15
|
+
| Method | Path | Description |
|
|
16
|
+
|:---|:---|:---|
|
|
17
|
+
| GET | `/api/v1/health` | Real-time connectivity check for 3 keys |
|
|
18
|
+
| POST | `/api/v1/get_config` | Issue RoomId / UserSig |
|
|
19
|
+
| POST | `/api/v1/agent/start` | Start AI channel bot |
|
|
20
|
+
| POST | `/api/v1/agent/stop` | Stop AI channel bot |
|
|
21
|
+
| POST | `/api/v1/agent/control` | Text injection / interrupt |
|
|
22
|
+
| GET | `/api/v1/sessions` | In-memory session list (debugging) |
|
|
23
|
+
|
|
24
|
+
Capability extension endpoints:
|
|
25
|
+
|
|
26
|
+
| Capability | Prefix |
|
|
27
|
+
|:---|:---|
|
|
28
|
+
| knowledge-base | `/api/v1/kb/*` |
|
|
29
|
+
| tool-calling | `/api/v1/tools/*` |
|
|
30
|
+
| human-handoff | `/api/v1/handoff/*` |
|
|
31
|
+
| session-summary | `/api/v1/summary/*` |
|
|
32
|
+
| digital-human | `/api/v1/digital-human/*` |
|
|
33
|
+
|
|
34
|
+
## 3. Call Examples
|
|
35
|
+
|
|
36
|
+
### 3.1 Request Room Credentials
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
curl -X POST http://localhost:3000/api/v1/get_config \
|
|
40
|
+
-H "Content-Type: application/json" \
|
|
41
|
+
-d '{}'
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Response:
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"code": 0,
|
|
49
|
+
"data": {
|
|
50
|
+
"session_id": "xxx",
|
|
51
|
+
"sdk_app_id": 1234567890,
|
|
52
|
+
"room_id": "987654321",
|
|
53
|
+
"user_id": "u_abc",
|
|
54
|
+
"user_sig": "...",
|
|
55
|
+
"agent_user_id": "ai_xyz",
|
|
56
|
+
"io_modality": { "voice_input": { ... } }
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### 3.2 Start AI Bot
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
curl -X POST http://localhost:3000/api/v1/agent/start \
|
|
65
|
+
-H "Content-Type: application/json" \
|
|
66
|
+
-d '{"session_id":"xxx","language":"zh"}'
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### 3.3 Text Injection
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
curl -X POST http://localhost:3000/api/v1/agent/control \
|
|
73
|
+
-H "Content-Type: application/json" \
|
|
74
|
+
-d '{"session_id":"xxx","text":"Hello","interrupt":true}'
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## 4. SDK Packages
|
|
78
|
+
|
|
79
|
+
If you'd rather not call REST directly, use these SDKs:
|
|
80
|
+
|
|
81
|
+
| Ecosystem | Package |
|
|
82
|
+
|:---|:---|
|
|
83
|
+
| npm | `@trtc/voice-agent-sdk` |
|
|
84
|
+
| maven | `com.tencent.trtc:voice-agent-sdk` |
|
|
85
|
+
| pypi | `trtc-voice-agent` |
|
|
86
|
+
|
|
87
|
+
> SDK versions align with skeleton manifest; in Phase 2, REST is authoritative.
|
|
88
|
+
|
|
89
|
+
## 5. Security Compliance
|
|
90
|
+
|
|
91
|
+
- **HTTPS**: Enforce in production.
|
|
92
|
+
- **SecretKey not sent to client**: The skeleton only sends `user_sig` (with TTL) to the client; never exposes `SDKSecretKey`.
|
|
93
|
+
- **Log redaction**: The skeleton includes a built-in `RedactingFilter`; the reverse proxy layer should also suppress Authorization header logging.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# java-backend Adapter
|
|
2
|
+
|
|
3
|
+
Connect the conversation-core skeleton as a Filter into Spring Boot / Quarkus projects.
|
|
4
|
+
|
|
5
|
+
| Framework | Template | Default Target |
|
|
6
|
+
|:---|:---|:---|
|
|
7
|
+
| Spring Boot | `springboot/VoiceAgentFilter.java.tpl` | `src/main/java/com/example/voiceagent/VoiceAgentFilter.java` |
|
|
8
|
+
| Quarkus | `quarkus/VoiceAgentFilter.java.tpl` | Same as above |
|
|
9
|
+
|
|
10
|
+
## Configuration
|
|
11
|
+
|
|
12
|
+
`application.yml` / `application.properties`:
|
|
13
|
+
|
|
14
|
+
```yaml
|
|
15
|
+
skeleton:
|
|
16
|
+
base-url: ${SKELETON_BASE_URL}
|
|
17
|
+
api-prefix: ${API_PREFIX}
|
|
18
|
+
route-prefix: ${ROUTE_PREFIX}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Notes
|
|
22
|
+
|
|
23
|
+
- The template package `com.example.voiceagent` is replaced by the Agent during L1 rendering based on the user's actual project package name.
|
|
24
|
+
- Default `connectTimeout=3s`, `request timeout=10s`; adjustable as needed.
|
|
25
|
+
- Spring Boot registers `voiceAgentFilter` with order 10; should be placed before business Filters.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
name: "java-backend"
|
|
2
|
+
version: "1.0.0"
|
|
3
|
+
target_role: "backend"
|
|
4
|
+
tech_stack: ["spring-boot", "quarkus"]
|
|
5
|
+
description: "Java backend Filter: forward requests to skeleton process"
|
|
6
|
+
|
|
7
|
+
templates:
|
|
8
|
+
spring-boot:
|
|
9
|
+
file: "springboot/VoiceAgentFilter.java.tpl"
|
|
10
|
+
target_path: "src/main/java/com/example/voiceagent/VoiceAgentFilter.java"
|
|
11
|
+
install_hint: |
|
|
12
|
+
Filter already includes @Component; Spring Boot auto-scans it.
|
|
13
|
+
To customize the path prefix, modify the PATH_PREFIX constant or inject via application.yml.
|
|
14
|
+
package_dependencies:
|
|
15
|
+
- "org.springframework.boot:spring-boot-starter-web"
|
|
16
|
+
quarkus:
|
|
17
|
+
file: "quarkus/VoiceAgentFilter.java.tpl"
|
|
18
|
+
target_path: "src/main/java/com/example/voiceagent/VoiceAgentFilter.java"
|
|
19
|
+
install_hint: |
|
|
20
|
+
Filter already includes @Provider; place the file in any package path scanned by Quarkus.
|
|
21
|
+
package_dependencies:
|
|
22
|
+
- "io.quarkus:quarkus-rest-client-reactive"
|
|
23
|
+
|
|
24
|
+
defaults:
|
|
25
|
+
SKELETON_BASE_URL: "http://localhost:3000"
|
|
26
|
+
API_PREFIX: "/api/v1"
|
|
27
|
+
ROUTE_PREFIX: "/voice-agent"
|
|
28
|
+
|
|
29
|
+
security:
|
|
30
|
+
https_required: true
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// VoiceAgentFilter.java (Quarkus, JAX-RS ContainerRequestFilter)
|
|
2
|
+
// Auto-generated by conversation-core/auto_adapters/java-backend
|
|
3
|
+
package com.example.voiceagent;
|
|
4
|
+
|
|
5
|
+
import jakarta.ws.rs.client.Client;
|
|
6
|
+
import jakarta.ws.rs.client.ClientBuilder;
|
|
7
|
+
import jakarta.ws.rs.client.Entity;
|
|
8
|
+
import jakarta.ws.rs.container.ContainerRequestContext;
|
|
9
|
+
import jakarta.ws.rs.container.ContainerRequestFilter;
|
|
10
|
+
import jakarta.ws.rs.container.PreMatching;
|
|
11
|
+
import jakarta.ws.rs.core.Response;
|
|
12
|
+
import jakarta.ws.rs.ext.Provider;
|
|
13
|
+
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
|
14
|
+
|
|
15
|
+
import java.io.IOException;
|
|
16
|
+
import java.io.InputStream;
|
|
17
|
+
|
|
18
|
+
@Provider
|
|
19
|
+
@PreMatching
|
|
20
|
+
public class VoiceAgentFilter implements ContainerRequestFilter {
|
|
21
|
+
|
|
22
|
+
@ConfigProperty(name = "skeleton.base-url", defaultValue = "${SKELETON_BASE_URL}")
|
|
23
|
+
String skeletonBaseUrl;
|
|
24
|
+
|
|
25
|
+
@ConfigProperty(name = "skeleton.api-prefix", defaultValue = "${API_PREFIX}")
|
|
26
|
+
String apiPrefix;
|
|
27
|
+
|
|
28
|
+
@ConfigProperty(name = "skeleton.route-prefix", defaultValue = "${ROUTE_PREFIX}")
|
|
29
|
+
String routePrefix;
|
|
30
|
+
|
|
31
|
+
private final Client client = ClientBuilder.newClient();
|
|
32
|
+
|
|
33
|
+
@Override
|
|
34
|
+
public void filter(ContainerRequestContext ctx) throws IOException {
|
|
35
|
+
String path = ctx.getUriInfo().getPath();
|
|
36
|
+
if (!("/" + path).startsWith(routePrefix)) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
String suffix = ("/" + path).substring(routePrefix.length());
|
|
40
|
+
String upstream = skeletonBaseUrl + apiPrefix + suffix;
|
|
41
|
+
|
|
42
|
+
try (InputStream in = ctx.getEntityStream()) {
|
|
43
|
+
byte[] body = in.readAllBytes();
|
|
44
|
+
Response.ResponseBuilder rb;
|
|
45
|
+
try {
|
|
46
|
+
Response resp;
|
|
47
|
+
if ("GET".equalsIgnoreCase(ctx.getMethod())) {
|
|
48
|
+
resp = client.target(upstream).request().get();
|
|
49
|
+
} else {
|
|
50
|
+
resp = client.target(upstream).request()
|
|
51
|
+
.method(ctx.getMethod(),
|
|
52
|
+
Entity.entity(body, "application/json"));
|
|
53
|
+
}
|
|
54
|
+
rb = Response.status(resp.getStatus())
|
|
55
|
+
.entity(resp.readEntity(byte[].class));
|
|
56
|
+
} catch (Exception e) {
|
|
57
|
+
rb = Response.status(502)
|
|
58
|
+
.entity("{\"code\":\"bad_gateway\",\"message\":\""
|
|
59
|
+
+ e.getMessage().replace("\"", "'") + "\"}");
|
|
60
|
+
}
|
|
61
|
+
ctx.abortWith(rb.type("application/json").build());
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
package/skills/trtc-ai-service/auto_adapters/java-backend/springboot/VoiceAgentFilter.java.tpl
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// VoiceAgentFilter.java (Spring Boot)
|
|
2
|
+
// Auto-generated by conversation-core/auto_adapters/java-backend
|
|
3
|
+
// Reverse-proxy ${ROUTE_PREFIX}/* to skeleton ${SKELETON_BASE_URL}${API_PREFIX}/*
|
|
4
|
+
package com.example.voiceagent;
|
|
5
|
+
|
|
6
|
+
import jakarta.servlet.*;
|
|
7
|
+
import jakarta.servlet.http.HttpServletRequest;
|
|
8
|
+
import jakarta.servlet.http.HttpServletResponse;
|
|
9
|
+
import org.springframework.beans.factory.annotation.Value;
|
|
10
|
+
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
|
11
|
+
import org.springframework.context.annotation.Bean;
|
|
12
|
+
import org.springframework.stereotype.Component;
|
|
13
|
+
|
|
14
|
+
import java.io.IOException;
|
|
15
|
+
import java.io.InputStream;
|
|
16
|
+
import java.net.URI;
|
|
17
|
+
import java.net.http.HttpClient;
|
|
18
|
+
import java.net.http.HttpRequest;
|
|
19
|
+
import java.net.http.HttpResponse;
|
|
20
|
+
import java.nio.charset.StandardCharsets;
|
|
21
|
+
import java.time.Duration;
|
|
22
|
+
|
|
23
|
+
@Component
|
|
24
|
+
public class VoiceAgentFilter implements Filter {
|
|
25
|
+
|
|
26
|
+
@Value("${skeleton.base-url:${SKELETON_BASE_URL}}")
|
|
27
|
+
private String skeletonBaseUrl;
|
|
28
|
+
|
|
29
|
+
@Value("${skeleton.api-prefix:${API_PREFIX}}")
|
|
30
|
+
private String apiPrefix;
|
|
31
|
+
|
|
32
|
+
@Value("${skeleton.route-prefix:${ROUTE_PREFIX}}")
|
|
33
|
+
private String routePrefix;
|
|
34
|
+
|
|
35
|
+
private final HttpClient client = HttpClient.newBuilder()
|
|
36
|
+
.connectTimeout(Duration.ofSeconds(3))
|
|
37
|
+
.build();
|
|
38
|
+
|
|
39
|
+
@Override
|
|
40
|
+
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
|
|
41
|
+
throws IOException, ServletException {
|
|
42
|
+
HttpServletRequest httpReq = (HttpServletRequest) req;
|
|
43
|
+
HttpServletResponse httpRes = (HttpServletResponse) res;
|
|
44
|
+
String path = httpReq.getRequestURI();
|
|
45
|
+
if (!path.startsWith(routePrefix)) {
|
|
46
|
+
chain.doFilter(req, res);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
String suffix = path.substring(routePrefix.length());
|
|
50
|
+
String upstream = skeletonBaseUrl + apiPrefix + suffix;
|
|
51
|
+
try (InputStream in = httpReq.getInputStream()) {
|
|
52
|
+
byte[] body = in.readAllBytes();
|
|
53
|
+
HttpRequest.Builder builder = HttpRequest.newBuilder()
|
|
54
|
+
.uri(URI.create(upstream))
|
|
55
|
+
.timeout(Duration.ofSeconds(10))
|
|
56
|
+
.header("Content-Type", "application/json");
|
|
57
|
+
switch (httpReq.getMethod()) {
|
|
58
|
+
case "GET":
|
|
59
|
+
case "HEAD":
|
|
60
|
+
builder.GET();
|
|
61
|
+
break;
|
|
62
|
+
case "DELETE":
|
|
63
|
+
builder.DELETE();
|
|
64
|
+
break;
|
|
65
|
+
default:
|
|
66
|
+
builder.method(httpReq.getMethod(),
|
|
67
|
+
HttpRequest.BodyPublishers.ofByteArray(body));
|
|
68
|
+
}
|
|
69
|
+
HttpResponse<byte[]> resp = client.send(builder.build(),
|
|
70
|
+
HttpResponse.BodyHandlers.ofByteArray());
|
|
71
|
+
httpRes.setStatus(resp.statusCode());
|
|
72
|
+
resp.headers().firstValue("Content-Type").ifPresent(httpRes::setContentType);
|
|
73
|
+
httpRes.getOutputStream().write(resp.body());
|
|
74
|
+
} catch (Exception e) {
|
|
75
|
+
httpRes.setStatus(HttpServletResponse.SC_BAD_GATEWAY);
|
|
76
|
+
httpRes.getWriter().write(
|
|
77
|
+
"{\"code\":\"bad_gateway\",\"message\":\""
|
|
78
|
+
+ e.getMessage().replace("\"", "'") + "\"}"
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
@Bean
|
|
84
|
+
public FilterRegistrationBean<VoiceAgentFilter> voiceAgentFilterRegistration() {
|
|
85
|
+
FilterRegistrationBean<VoiceAgentFilter> reg = new FilterRegistrationBean<>(this);
|
|
86
|
+
reg.addUrlPatterns(routePrefix + "/*");
|
|
87
|
+
reg.setName("voiceAgentFilter");
|
|
88
|
+
reg.setOrder(10);
|
|
89
|
+
return reg;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# auto_adapters index manifest
|
|
2
|
+
# For add-capability CLI / Agent to parse adapter-to-tech-stack mappings.
|
|
3
|
+
|
|
4
|
+
version: "1.0.0"
|
|
5
|
+
description: "Tech stack decoupling adapter component library, Phase 2 initial coverage of 4 adapter types / 12 tech stacks"
|
|
6
|
+
|
|
7
|
+
# Rendering variable format ${VAR}, replaced by CLI before writing
|
|
8
|
+
default_variables:
|
|
9
|
+
SKELETON_BASE_URL: "http://localhost:3000"
|
|
10
|
+
API_PREFIX: "/api/v1"
|
|
11
|
+
COMPONENT_NAME: "VoiceAgent"
|
|
12
|
+
ROUTE_PREFIX: "/voice-agent"
|
|
13
|
+
|
|
14
|
+
adapters:
|
|
15
|
+
- name: "frontend-spa"
|
|
16
|
+
path: "frontend-spa"
|
|
17
|
+
tech_stack: ["react", "vue", "angular", "next"]
|
|
18
|
+
description: "Frontend SPA adapter, generates join-room component and connects to skeleton /api/v1/*"
|
|
19
|
+
target_role: "frontend"
|
|
20
|
+
|
|
21
|
+
- name: "node-backend"
|
|
22
|
+
path: "node-backend"
|
|
23
|
+
tech_stack: ["express", "koa", "fastify"]
|
|
24
|
+
description: "Node.js backend adapter, generates reverse proxy middleware"
|
|
25
|
+
target_role: "backend"
|
|
26
|
+
|
|
27
|
+
- name: "java-backend"
|
|
28
|
+
path: "java-backend"
|
|
29
|
+
tech_stack: ["spring-boot", "quarkus"]
|
|
30
|
+
description: "Java backend adapter, generates Filter / Quarkus Filter"
|
|
31
|
+
target_role: "backend"
|
|
32
|
+
|
|
33
|
+
- name: "python-backend"
|
|
34
|
+
path: "python-backend"
|
|
35
|
+
tech_stack: ["flask", "fastapi", "django"]
|
|
36
|
+
description: "Python backend adapter, generates decorators / sub-router mounting"
|
|
37
|
+
target_role: "backend"
|
|
38
|
+
|
|
39
|
+
# General templates referenced by three-level degrader
|
|
40
|
+
fallback_templates:
|
|
41
|
+
guided_frontend: "integration_templates/generic-frontend.md"
|
|
42
|
+
guided_backend: "integration_templates/generic-backend.md"
|
|
43
|
+
manual_rest_api: "integration_templates/generic-rest-api.md"
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# node-backend Adapter
|
|
2
|
+
|
|
3
|
+
Connect the conversation-core skeleton as a reverse proxy into a Node.js backend,
|
|
4
|
+
keeping the skeleton address hidden from the frontend and allowing the backend to inject auth / rate limiting / business policies before and after forwarding.
|
|
5
|
+
|
|
6
|
+
| Framework | Template | Default Install Location |
|
|
7
|
+
|:---|:---|:---|
|
|
8
|
+
| Express | `express.js.tpl` | `routes/voice-agent.js` |
|
|
9
|
+
| Koa | `koa.js.tpl` | `routes/voice-agent.js` |
|
|
10
|
+
| Fastify | `fastify.js.tpl` | `routes/voice-agent.js` |
|
|
11
|
+
|
|
12
|
+
## Configuration
|
|
13
|
+
|
|
14
|
+
| Env Variable | Default | Description |
|
|
15
|
+
|:---|:---|:---|
|
|
16
|
+
| `SKELETON_BASE_URL` | `http://localhost:3000` | Skeleton process address |
|
|
17
|
+
| `API_PREFIX` | `/api/v1` | Skeleton REST prefix |
|
|
18
|
+
| `ROUTE_PREFIX` | `/voice-agent` | Self-mounting path |
|
|
19
|
+
|
|
20
|
+
## Security
|
|
21
|
+
|
|
22
|
+
- **SSRF Protection**: The template detects whether `SKELETON_BASE_URL` falls within private network ranges (`10/192.168/172.16-31/9/11/21/30/127`),
|
|
23
|
+
and will output a warning in production; internal network access requires explicit user confirmation.
|
|
24
|
+
- **HTTPS**: Enforced in production deployment.
|
|
25
|
+
- **Request Body Limit**: Default `64KB`, preventing malicious large payloads from overwhelming the skeleton ASR/LLM pipeline.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// routes/voice-agent.js (Express)
|
|
2
|
+
// Auto-generated by conversation-core/auto_adapters/node-backend.
|
|
3
|
+
// Reverse-proxy user requests to the skeleton process, avoiding direct frontend exposure of the skeleton address.
|
|
4
|
+
const express = require('express');
|
|
5
|
+
const fetch = (...args) => import('node-fetch').then(({ default: f }) => f(...args));
|
|
6
|
+
|
|
7
|
+
const SKELETON_BASE_URL = process.env.SKELETON_BASE_URL || '${SKELETON_BASE_URL}';
|
|
8
|
+
const API_PREFIX = process.env.API_PREFIX || '${API_PREFIX}';
|
|
9
|
+
|
|
10
|
+
const router = express.Router();
|
|
11
|
+
router.use(express.json({ limit: '64kb' }));
|
|
12
|
+
|
|
13
|
+
// Security: prevent reverse proxy from pointing to private networks (aligned with global SSRF protection)
|
|
14
|
+
function isPrivate(host) {
|
|
15
|
+
if (!host) return false;
|
|
16
|
+
const blocks = [/^10\./, /^192\.168\./, /^172\.(1[6-9]|2\d|3[0-1])\./, /^9\./, /^11\./, /^21\./, /^30\./, /^127\./];
|
|
17
|
+
return blocks.some((re) => re.test(host));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const target = new URL(SKELETON_BASE_URL);
|
|
21
|
+
if (isPrivate(target.hostname) && process.env.NODE_ENV !== 'development') {
|
|
22
|
+
console.warn('[voice-agent] WARNING: SKELETON_BASE_URL points to a private network');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
router.all('*', async (req, res) => {
|
|
26
|
+
const url = SKELETON_BASE_URL + API_PREFIX + req.path;
|
|
27
|
+
try {
|
|
28
|
+
const resp = await fetch(url, {
|
|
29
|
+
method: req.method,
|
|
30
|
+
headers: { 'Content-Type': 'application/json' },
|
|
31
|
+
body: ['GET', 'HEAD'].includes(req.method) ? undefined : JSON.stringify(req.body || {}),
|
|
32
|
+
});
|
|
33
|
+
const text = await resp.text();
|
|
34
|
+
res.status(resp.status).type(resp.headers.get('content-type') || 'application/json').send(text);
|
|
35
|
+
} catch (err) {
|
|
36
|
+
res.status(502).json({ code: 'bad_gateway', message: err.message });
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
module.exports = router;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// routes/voice-agent.js (Fastify plugin)
|
|
2
|
+
// Auto-generated by conversation-core/auto_adapters/node-backend.
|
|
3
|
+
const fetch = (...args) => import('node-fetch').then(({ default: f }) => f(...args));
|
|
4
|
+
|
|
5
|
+
const SKELETON_BASE_URL = process.env.SKELETON_BASE_URL || '${SKELETON_BASE_URL}';
|
|
6
|
+
const API_PREFIX = process.env.API_PREFIX || '${API_PREFIX}';
|
|
7
|
+
|
|
8
|
+
module.exports = async function voiceAgent(fastify, _opts) {
|
|
9
|
+
fastify.all('/*', async (request, reply) => {
|
|
10
|
+
const url = SKELETON_BASE_URL + API_PREFIX + request.url.replace(/^\/voice-agent/, '');
|
|
11
|
+
try {
|
|
12
|
+
const body = ['GET', 'HEAD'].includes(request.method)
|
|
13
|
+
? undefined
|
|
14
|
+
: JSON.stringify(request.body || {});
|
|
15
|
+
const resp = await fetch(url, {
|
|
16
|
+
method: request.method,
|
|
17
|
+
headers: { 'Content-Type': 'application/json' },
|
|
18
|
+
body,
|
|
19
|
+
});
|
|
20
|
+
reply.code(resp.status).type(resp.headers.get('content-type') || 'application/json');
|
|
21
|
+
return await resp.text();
|
|
22
|
+
} catch (err) {
|
|
23
|
+
reply.code(502);
|
|
24
|
+
return { code: 'bad_gateway', message: err.message };
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// routes/voice-agent.js (Koa)
|
|
2
|
+
// Auto-generated by conversation-core/auto_adapters/node-backend.
|
|
3
|
+
const Router = require('@koa/router');
|
|
4
|
+
const fetch = (...args) => import('node-fetch').then(({ default: f }) => f(...args));
|
|
5
|
+
|
|
6
|
+
const SKELETON_BASE_URL = process.env.SKELETON_BASE_URL || '${SKELETON_BASE_URL}';
|
|
7
|
+
const API_PREFIX = process.env.API_PREFIX || '${API_PREFIX}';
|
|
8
|
+
const ROUTE_PREFIX = process.env.ROUTE_PREFIX || '${ROUTE_PREFIX}';
|
|
9
|
+
|
|
10
|
+
const router = new Router({ prefix: ROUTE_PREFIX });
|
|
11
|
+
|
|
12
|
+
router.all('(.*)', async (ctx) => {
|
|
13
|
+
const subPath = ctx.path.startsWith(ROUTE_PREFIX) ? ctx.path.slice(ROUTE_PREFIX.length) : ctx.path;
|
|
14
|
+
const url = SKELETON_BASE_URL + API_PREFIX + subPath;
|
|
15
|
+
try {
|
|
16
|
+
const body = ['GET', 'HEAD'].includes(ctx.method) ? undefined : JSON.stringify(ctx.request.body || {});
|
|
17
|
+
const resp = await fetch(url, {
|
|
18
|
+
method: ctx.method,
|
|
19
|
+
headers: { 'Content-Type': 'application/json' },
|
|
20
|
+
body,
|
|
21
|
+
});
|
|
22
|
+
ctx.status = resp.status;
|
|
23
|
+
ctx.set('Content-Type', resp.headers.get('content-type') || 'application/json');
|
|
24
|
+
ctx.body = await resp.text();
|
|
25
|
+
} catch (err) {
|
|
26
|
+
ctx.status = 502;
|
|
27
|
+
ctx.body = { code: 'bad_gateway', message: err.message };
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
module.exports = router;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
name: "node-backend"
|
|
2
|
+
version: "1.0.0"
|
|
3
|
+
target_role: "backend"
|
|
4
|
+
tech_stack: ["express", "koa", "fastify"]
|
|
5
|
+
description: "Node.js backend reverse proxy: transparently proxy ${ROUTE_PREFIX}/* to skeleton ${SKELETON_BASE_URL}${API_PREFIX}/*"
|
|
6
|
+
|
|
7
|
+
templates:
|
|
8
|
+
express:
|
|
9
|
+
file: "express.js.tpl"
|
|
10
|
+
target_path: "routes/voice-agent.js"
|
|
11
|
+
install_hint: |
|
|
12
|
+
In Express app:
|
|
13
|
+
const voiceAgent = require('./routes/voice-agent');
|
|
14
|
+
app.use('${ROUTE_PREFIX}', voiceAgent);
|
|
15
|
+
package_dependencies:
|
|
16
|
+
- "express@^4.17.0"
|
|
17
|
+
- "node-fetch@^3.3.0"
|
|
18
|
+
koa:
|
|
19
|
+
file: "koa.js.tpl"
|
|
20
|
+
target_path: "routes/voice-agent.js"
|
|
21
|
+
install_hint: |
|
|
22
|
+
In Koa app:
|
|
23
|
+
const Router = require('@koa/router');
|
|
24
|
+
const proxy = require('./routes/voice-agent');
|
|
25
|
+
app.use(proxy.routes()).use(proxy.allowedMethods());
|
|
26
|
+
package_dependencies:
|
|
27
|
+
- "@koa/router@^12.0.0"
|
|
28
|
+
- "node-fetch@^3.3.0"
|
|
29
|
+
fastify:
|
|
30
|
+
file: "fastify.js.tpl"
|
|
31
|
+
target_path: "routes/voice-agent.js"
|
|
32
|
+
install_hint: |
|
|
33
|
+
In Fastify app:
|
|
34
|
+
const voiceAgent = require('./routes/voice-agent');
|
|
35
|
+
fastify.register(voiceAgent, { prefix: '${ROUTE_PREFIX}' });
|
|
36
|
+
package_dependencies:
|
|
37
|
+
- "fastify@^4.0.0"
|
|
38
|
+
- "node-fetch@^3.3.0"
|
|
39
|
+
|
|
40
|
+
defaults:
|
|
41
|
+
SKELETON_BASE_URL: "http://localhost:3000"
|
|
42
|
+
API_PREFIX: "/api/v1"
|
|
43
|
+
ROUTE_PREFIX: "/voice-agent"
|
|
44
|
+
|
|
45
|
+
security:
|
|
46
|
+
https_required: true
|
|
47
|
+
forbid_internal_ip: true # Reverse proxy target defaults to rejecting private network ranges (10/192.168/172.16-31/9/11/21/30)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# python-backend Adapter
|
|
2
|
+
|
|
3
|
+
Connect the conversation-core skeleton as a reverse proxy into a Python backend.
|
|
4
|
+
|
|
5
|
+
| Framework | Template | Default Target |
|
|
6
|
+
|:---|:---|:---|
|
|
7
|
+
| Flask | `flask.py.tpl` | `voice_agent_proxy.py` (Blueprint) |
|
|
8
|
+
| FastAPI | `fastapi.py.tpl` | `voice_agent_proxy.py` (APIRouter) |
|
|
9
|
+
| Django | `django.py.tpl` | `voice_agent_proxy/views.py` (function view) |
|
|
10
|
+
|
|
11
|
+
## Configuration
|
|
12
|
+
|
|
13
|
+
| Env Variable | Default | Description |
|
|
14
|
+
|:---|:---|:---|
|
|
15
|
+
| `SKELETON_BASE_URL` | `http://localhost:3000` | Skeleton address |
|
|
16
|
+
| `API_PREFIX` | `/api/v1` | Skeleton prefix |
|
|
17
|
+
| `ROUTE_PREFIX` | `/voice-agent` | Self-mounting path |
|
|
18
|
+
|
|
19
|
+
## Notes
|
|
20
|
+
|
|
21
|
+
- The Django template uses `@csrf_exempt`, suitable only for reverse proxy scenarios; for CSRF support, integrate DRF separately.
|
|
22
|
+
- The FastAPI template is based on `httpx.AsyncClient`, aligning with the skeleton's async pipeline.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# voice_agent_proxy/views.py (Django function view)
|
|
2
|
+
# Auto-generated by conversation-core/auto_adapters/python-backend
|
|
3
|
+
import json
|
|
4
|
+
import os
|
|
5
|
+
|
|
6
|
+
import requests
|
|
7
|
+
from django.http import HttpResponse, JsonResponse
|
|
8
|
+
from django.views.decorators.csrf import csrf_exempt
|
|
9
|
+
|
|
10
|
+
SKELETON_BASE_URL = os.getenv("SKELETON_BASE_URL", "${SKELETON_BASE_URL}")
|
|
11
|
+
API_PREFIX = os.getenv("API_PREFIX", "${API_PREFIX}")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@csrf_exempt
|
|
15
|
+
def proxy_view(request, rest: str = ""):
|
|
16
|
+
upstream = f"{SKELETON_BASE_URL}{API_PREFIX}/{rest}"
|
|
17
|
+
try:
|
|
18
|
+
kwargs = {"timeout": 10}
|
|
19
|
+
if request.method != "GET":
|
|
20
|
+
try:
|
|
21
|
+
kwargs["json"] = json.loads(request.body or b"{}")
|
|
22
|
+
except json.JSONDecodeError:
|
|
23
|
+
kwargs["json"] = {}
|
|
24
|
+
resp = requests.request(
|
|
25
|
+
request.method, upstream,
|
|
26
|
+
headers={"Content-Type": "application/json"},
|
|
27
|
+
**kwargs,
|
|
28
|
+
)
|
|
29
|
+
ctype = resp.headers.get("Content-Type", "application/json")
|
|
30
|
+
return HttpResponse(resp.content, status=resp.status_code, content_type=ctype)
|
|
31
|
+
except requests.RequestException as exc:
|
|
32
|
+
return JsonResponse({"code": "bad_gateway", "message": str(exc)}, status=502)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# voice_agent_proxy.py (FastAPI sub-router)
|
|
2
|
+
# Auto-generated by conversation-core/auto_adapters/python-backend
|
|
3
|
+
import os
|
|
4
|
+
from typing import Any, Dict, Optional
|
|
5
|
+
|
|
6
|
+
import httpx
|
|
7
|
+
from fastapi import APIRouter, HTTPException, Request
|
|
8
|
+
|
|
9
|
+
SKELETON_BASE_URL = os.getenv("SKELETON_BASE_URL", "${SKELETON_BASE_URL}")
|
|
10
|
+
API_PREFIX = os.getenv("API_PREFIX", "${API_PREFIX}")
|
|
11
|
+
|
|
12
|
+
router = APIRouter()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@router.api_route("/{subpath:path}", methods=["GET", "POST", "PUT", "DELETE"])
|
|
16
|
+
async def proxy(subpath: str, request: Request) -> Any:
|
|
17
|
+
upstream = f"{SKELETON_BASE_URL}{API_PREFIX}/{subpath}"
|
|
18
|
+
body: Optional[Dict[str, Any]] = None
|
|
19
|
+
if request.method != "GET":
|
|
20
|
+
try:
|
|
21
|
+
body = await request.json()
|
|
22
|
+
except Exception:
|
|
23
|
+
body = {}
|
|
24
|
+
async with httpx.AsyncClient(timeout=10) as client:
|
|
25
|
+
try:
|
|
26
|
+
resp = await client.request(
|
|
27
|
+
request.method, upstream,
|
|
28
|
+
headers={"Content-Type": "application/json"},
|
|
29
|
+
json=body if request.method != "GET" else None,
|
|
30
|
+
)
|
|
31
|
+
except httpx.HTTPError as exc:
|
|
32
|
+
raise HTTPException(status_code=502, detail={"code": "bad_gateway", "message": str(exc)})
|
|
33
|
+
if resp.headers.get("content-type", "").startswith("application/json"):
|
|
34
|
+
return resp.json()
|
|
35
|
+
return resp.text
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# voice_agent_proxy.py (Flask Blueprint)
|
|
2
|
+
# Auto-generated by conversation-core/auto_adapters/python-backend
|
|
3
|
+
import os
|
|
4
|
+
from flask import Blueprint, request, Response
|
|
5
|
+
import requests
|
|
6
|
+
|
|
7
|
+
SKELETON_BASE_URL = os.getenv("SKELETON_BASE_URL", "${SKELETON_BASE_URL}")
|
|
8
|
+
API_PREFIX = os.getenv("API_PREFIX", "${API_PREFIX}")
|
|
9
|
+
|
|
10
|
+
bp = Blueprint("voice_agent_proxy", __name__)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@bp.route("/<path:subpath>", methods=["GET", "POST", "PUT", "DELETE"])
|
|
14
|
+
def proxy(subpath: str):
|
|
15
|
+
upstream = f"{SKELETON_BASE_URL}{API_PREFIX}/{subpath}"
|
|
16
|
+
try:
|
|
17
|
+
kwargs = {"timeout": 10}
|
|
18
|
+
if request.method != "GET":
|
|
19
|
+
kwargs["json"] = request.get_json(silent=True) or {}
|
|
20
|
+
resp = requests.request(
|
|
21
|
+
request.method, upstream,
|
|
22
|
+
headers={"Content-Type": "application/json"},
|
|
23
|
+
**kwargs,
|
|
24
|
+
)
|
|
25
|
+
return Response(
|
|
26
|
+
resp.content,
|
|
27
|
+
status=resp.status_code,
|
|
28
|
+
content_type=resp.headers.get("Content-Type", "application/json"),
|
|
29
|
+
)
|
|
30
|
+
except requests.RequestException as exc:
|
|
31
|
+
return {"code": "bad_gateway", "message": str(exc)}, 502
|