@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,263 @@
|
|
|
1
|
+
# `business_contract` Field Specification (v1.0)
|
|
2
|
+
|
|
3
|
+
> Scope: the `business_contract` section in `capabilities/<name>/manifest.yaml`.
|
|
4
|
+
>
|
|
5
|
+
> Purpose: enable capability packages to **structurally** declare the business interface contracts they call / are called by,
|
|
6
|
+
> so that `scripts/contract-adapt.py` (Phase 3 Stage 4) can generate executable adapters based on them,
|
|
7
|
+
> and the assembly guide (Path A / Path B) can proactively list the contract manifest at the end.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 1. Top-Level Structure
|
|
12
|
+
|
|
13
|
+
```yaml
|
|
14
|
+
business_contract:
|
|
15
|
+
port_class: "<dotted.path>" # Full dotted path to ABC abstract base class
|
|
16
|
+
default_adapter: "<dotted.path>" # Default implementation (production)
|
|
17
|
+
mock_adapter: "<dotted.path>" # Mock implementation (demo / video recording)
|
|
18
|
+
external_apis: # outbound / inbound interface contract list
|
|
19
|
+
- <ExternalApi>
|
|
20
|
+
customization_sop: "INTERFACE_ADAPT.md" # Path to interface adaptation SOP (relative to capability root)
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Special case**: `tool-calling` does not use the port/adapter abstraction; it uses the alpha/beta dual-track contract section defined in §5 instead.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 2. `external_apis[]` Field Definition
|
|
28
|
+
|
|
29
|
+
```yaml
|
|
30
|
+
- name: <string> # Contract name (snake_case dot-delimited), globally unique
|
|
31
|
+
direction: outbound | inbound # outbound = we call the business side; inbound = business side calls back to us
|
|
32
|
+
method: GET | POST | PUT | DELETE | PATCH
|
|
33
|
+
path: <string> # Path template, may contain {placeholder}
|
|
34
|
+
description: <string> # One-line description (for assembly wrap-up printing)
|
|
35
|
+
request_schema: # Request schema (simplified JSON Schema)
|
|
36
|
+
<field>: <type | enum[...] | object | array>
|
|
37
|
+
response_schema: # Response schema
|
|
38
|
+
<field>: <type | enum[...] | object | array>
|
|
39
|
+
adapter_slots: # Field paths allowed for user remapping (dot-delimited)
|
|
40
|
+
- <request|response>.<field-path>
|
|
41
|
+
auth: # (optional) Auth method
|
|
42
|
+
type: bearer | api_key | none
|
|
43
|
+
location: header | query
|
|
44
|
+
name: <header-name | query-key>
|
|
45
|
+
retry: # (optional) Retry policy
|
|
46
|
+
max: <int>
|
|
47
|
+
backoff_ms: <int>
|
|
48
|
+
timeout_ms: <int> # (optional) Timeout
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 2.1 `type` Value Convention
|
|
52
|
+
|
|
53
|
+
| Type | Meaning |
|
|
54
|
+
|---|---|
|
|
55
|
+
| `string` | String |
|
|
56
|
+
| `int` / `integer` | Integer |
|
|
57
|
+
| `float` / `number` | Float |
|
|
58
|
+
| `bool` / `boolean` | Boolean |
|
|
59
|
+
| `string[]` / `int[]` / `<T>[]` | Homogeneous array |
|
|
60
|
+
| `enum[a, b, c]` | Enum literal |
|
|
61
|
+
| `object` | Nested object (can be further expanded as sub-schema) |
|
|
62
|
+
| Nested dict | Write nested structure directly |
|
|
63
|
+
|
|
64
|
+
### 2.2 `adapter_slots` Field Path Rules
|
|
65
|
+
|
|
66
|
+
- Starts with `request.` or `response.`
|
|
67
|
+
- Nested levels use dot separation: `response.data.ticket_id`
|
|
68
|
+
- Arrays use `[]`: `request.transcript[]`
|
|
69
|
+
- Only lists fields **allowed for user remapping**; unlisted fields are treated as "our contract is fixed, user modification forbidden"
|
|
70
|
+
|
|
71
|
+
### 2.3 Special Nature of `direction = inbound`
|
|
72
|
+
|
|
73
|
+
An inbound contract means "the business side calls back to us", in which case:
|
|
74
|
+
- `path` is the endpoint we expose (e.g.: `/api/v1/handoff/callback/ticket-status`)
|
|
75
|
+
- `request_schema` is the payload structure sent by the business side
|
|
76
|
+
- `response_schema` is the ack structure we return (typically `{code: int, message: string}`)
|
|
77
|
+
- `adapter_slots` declares "business side field names may differ from our expectations", used by contract-adapt to generate inbound field mappers
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## 3. Naming Conventions
|
|
82
|
+
|
|
83
|
+
| Element | Rule | Example |
|
|
84
|
+
|---|---|---|
|
|
85
|
+
| `name` | `<domain>.<action>` snake_case | `ticket.create`, `faq.search`, `crm.write` |
|
|
86
|
+
| `port_class` | `src.ports.<file>.<ClassName>` | `src.ports.handoff_client.HandoffClient` |
|
|
87
|
+
| `default_adapter` / `mock_adapter` | `src.adapters.<file>.<ClassName>` | `src.adapters.local_queue.LocalQueueHandoffClient` |
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## 4. Full Example: `human-handoff`
|
|
92
|
+
|
|
93
|
+
```yaml
|
|
94
|
+
business_contract:
|
|
95
|
+
port_class: "src.ports.handoff_client.HandoffClient"
|
|
96
|
+
default_adapter: "src.adapters.local_queue.LocalQueueHandoffClient"
|
|
97
|
+
mock_adapter: "src.adapters.mock.MockHandoffClient"
|
|
98
|
+
customization_sop: "INTERFACE_ADAPT.md"
|
|
99
|
+
external_apis:
|
|
100
|
+
- name: ticket.create
|
|
101
|
+
direction: outbound
|
|
102
|
+
method: POST
|
|
103
|
+
path: /tickets
|
|
104
|
+
description: "Create a new ticket in the ticketing system when user triggers handoff"
|
|
105
|
+
request_schema:
|
|
106
|
+
user_id: string
|
|
107
|
+
subject: string
|
|
108
|
+
description: string
|
|
109
|
+
priority: enum[low, normal, high, urgent]
|
|
110
|
+
transcript: string[]
|
|
111
|
+
response_schema:
|
|
112
|
+
ticket_id: string
|
|
113
|
+
queue_position: int
|
|
114
|
+
eta_seconds: int
|
|
115
|
+
adapter_slots:
|
|
116
|
+
- request.subject
|
|
117
|
+
- request.priority
|
|
118
|
+
- response.ticket_id
|
|
119
|
+
- response.queue_position
|
|
120
|
+
- response.eta_seconds
|
|
121
|
+
auth:
|
|
122
|
+
type: bearer
|
|
123
|
+
location: header
|
|
124
|
+
name: Authorization
|
|
125
|
+
timeout_ms: 5000
|
|
126
|
+
|
|
127
|
+
- name: ticket.status_query
|
|
128
|
+
direction: outbound
|
|
129
|
+
method: GET
|
|
130
|
+
path: /tickets/{ticket_id}
|
|
131
|
+
description: "Poll ticket status for queue progress updates"
|
|
132
|
+
request_schema:
|
|
133
|
+
ticket_id: string
|
|
134
|
+
response_schema:
|
|
135
|
+
ticket_id: string
|
|
136
|
+
status: enum[pending, processing, closed, canceled]
|
|
137
|
+
agent_id: string
|
|
138
|
+
updated_at: int
|
|
139
|
+
adapter_slots:
|
|
140
|
+
- response.status
|
|
141
|
+
- response.agent_id
|
|
142
|
+
timeout_ms: 3000
|
|
143
|
+
|
|
144
|
+
- name: ticket.cancel
|
|
145
|
+
direction: outbound
|
|
146
|
+
method: POST
|
|
147
|
+
path: /tickets/{ticket_id}/cancel
|
|
148
|
+
description: "Notify ticketing system when user cancels handoff"
|
|
149
|
+
request_schema:
|
|
150
|
+
ticket_id: string
|
|
151
|
+
reason: string
|
|
152
|
+
response_schema:
|
|
153
|
+
ticket_id: string
|
|
154
|
+
canceled: bool
|
|
155
|
+
adapter_slots:
|
|
156
|
+
- request.reason
|
|
157
|
+
timeout_ms: 3000
|
|
158
|
+
|
|
159
|
+
- name: ticket.status_callback
|
|
160
|
+
direction: inbound
|
|
161
|
+
method: POST
|
|
162
|
+
path: /api/v1/handoff/callback/ticket-status
|
|
163
|
+
description: "Callback from ticketing system to notify status changes (optional; when disabled, status_query polling is used instead)"
|
|
164
|
+
request_schema:
|
|
165
|
+
ticket_id: string
|
|
166
|
+
status: enum[pending, processing, closed, canceled]
|
|
167
|
+
agent_id: string
|
|
168
|
+
response_schema:
|
|
169
|
+
code: int
|
|
170
|
+
message: string
|
|
171
|
+
adapter_slots:
|
|
172
|
+
- request.status
|
|
173
|
+
- request.agent_id
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## 5. `tool-calling` Exclusive Contract Section (replaces §1 port/adapter triple)
|
|
179
|
+
|
|
180
|
+
```yaml
|
|
181
|
+
business_contract:
|
|
182
|
+
alpha_track: # Alpha track: local function registration spec
|
|
183
|
+
interface: "src.ports.local_tool.LocalTool"
|
|
184
|
+
registration_schema:
|
|
185
|
+
name: string # Tool name (globally unique)
|
|
186
|
+
description: string
|
|
187
|
+
parameters: object # JSON Schema describing parameter structure
|
|
188
|
+
handler: callable # Function object (runtime-only)
|
|
189
|
+
invocation_schema:
|
|
190
|
+
input: object # Same schema as parameters
|
|
191
|
+
output: object # User-defined return structure
|
|
192
|
+
fail_fast: bool # Default true: local exceptions thrown immediately for arbitration decisions
|
|
193
|
+
|
|
194
|
+
beta_track: # Beta track: remote business API integration spec
|
|
195
|
+
interface: "src.ports.remote_tool.RemoteToolClient"
|
|
196
|
+
api_schema:
|
|
197
|
+
method: enum[GET, POST, PUT, DELETE, PATCH]
|
|
198
|
+
path: string
|
|
199
|
+
request_schema: object
|
|
200
|
+
response_schema: object
|
|
201
|
+
auth: enum[bearer, api_key, none]
|
|
202
|
+
timeout_ms: 5000
|
|
203
|
+
retry: { max: 1, backoff_ms: 200 }
|
|
204
|
+
|
|
205
|
+
arbitration: # Arbitration rules
|
|
206
|
+
default_priority: enum[alpha, beta, manifest_order]
|
|
207
|
+
fallback_on_failure: bool
|
|
208
|
+
timeout_ms: int # Single-track call timeout; triggers fallback on expiry
|
|
209
|
+
merge_strategy: enum[first_success, alpha_then_beta_diff]
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
`merge_strategy` values:
|
|
213
|
+
|
|
214
|
+
| Value | Behavior |
|
|
215
|
+
|---|---|
|
|
216
|
+
| `first_success` | Return immediately on priority track success; backup track not called (default) |
|
|
217
|
+
| `alpha_then_beta_diff` | Both tracks called; diff log recorded when results differ (for canary comparison) |
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## 6. How `contract-adapt.py` Consumes This Field
|
|
222
|
+
|
|
223
|
+
1. Read `business_contract.external_apis[].request_schema` / `response_schema`
|
|
224
|
+
2. Parse user-submitted curl / OpenAPI, extract the user API's schema
|
|
225
|
+
3. Compare against `adapter_slots` list to generate field mapping `mapping.yaml`
|
|
226
|
+
4. Render adapter template (inheriting `port_class`), output to `src/adapters/user_custom.py`
|
|
227
|
+
5. Three-level degradation:
|
|
228
|
+
- **L1**: Only `adapter_slots` field differences → fully executable adapter
|
|
229
|
+
- **L2**: Schema nesting or type differences exist → adapter template + TODO comments
|
|
230
|
+
- **L3**: Protocol-level differences (webhook / MQ / gRPC) or parse failure → output corresponding `INTERFACE_ADAPT.md` section path
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## 7. Validation Rules (mandatory at resolver stage)
|
|
235
|
+
|
|
236
|
+
| Rule | Error Code | Behavior |
|
|
237
|
+
|---|---|---|
|
|
238
|
+
| `port_class` / `default_adapter` / `mock_adapter` any not importable | `BC001` | Resolve failure, block install |
|
|
239
|
+
| `external_apis[].name` duplicate | `BC002` | Same as above |
|
|
240
|
+
| `direction = outbound` without `method` or `path` | `BC003` | Same as above |
|
|
241
|
+
| `adapter_slots` path not found in `request_schema` / `response_schema` | `BC004` | Warning only, does not block |
|
|
242
|
+
| `tool-calling.arbitration.default_priority` invalid value | `BC005` | Resolve failure |
|
|
243
|
+
| `auth.type = bearer` but no env variable source declared | `BC006` | Warning only |
|
|
244
|
+
|
|
245
|
+
Implementation location: `scripts/lib/contract_resolver.py` (Phase 3 Stage 4 implementation).
|
|
246
|
+
In Phase 1, only the field definitions are agreed upon; resolver validation will be implemented in Stage 4.
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## 8. Relationship with Existing Manifest Fields
|
|
251
|
+
|
|
252
|
+
- `business_contract` and existing `extensions` / `endpoints` / `integration` fields **do not affect each other**; can be independently added/removed
|
|
253
|
+
- `endpoints` describes "the REST endpoints we expose to the frontend / user"
|
|
254
|
+
- `business_contract.external_apis` describes "the interfaces we call / are called back by the business side"
|
|
255
|
+
- Both coexist without conflict, serving different consumers (frontend / Agent / business side)
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## 9. Version Compatibility
|
|
260
|
+
|
|
261
|
+
- Current spec version: `v1.0`
|
|
262
|
+
- No forward compatibility; if a future breaking change is needed, it will be marked with a `business_contract.spec_version: "2.0"` field
|
|
263
|
+
- The resource resolver (`manifest_resolver.py`) currently ignores unknown fields; adding this field will not break existing Phase 1/2 functionality
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# scenarios/custom-builder —— Path B Custom Flow
|
|
2
|
+
|
|
3
|
+
> Companion doc: repo root `SKILL.md` (Path B SOP §6).
|
|
4
|
+
|
|
5
|
+
This directory contains all artifacts for **Path B** ("Custom"). It has **no executable scripts** —
|
|
6
|
+
the 4-round Q&A is entirely facilitated by the Coding Agent using `ask_followup_question`.
|
|
7
|
+
This directory provides only two types of static materials:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
scenarios/custom-builder/
|
|
11
|
+
├── README.md ← This file
|
|
12
|
+
├── prompts/ ← Question templates for AI (does not modify user's project)
|
|
13
|
+
│ ├── q1-business-scenario.md ← Q1: Business description (free text)
|
|
14
|
+
│ ├── q2-io-modality.md ← Q2: I/O modality (4 choose 1)
|
|
15
|
+
│ ├── q3-ui-form.md ← Q3: UI form (3 choose 1)
|
|
16
|
+
│ └── q4-capabilities.md ← Q4: Capability selection (multi-select; defaults to none)
|
|
17
|
+
└── output-templates/
|
|
18
|
+
└── recipe.yaml.j2 ← AI rendering artifact template (output to <workspace>/recipe.yaml)
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## AI Execution Flow (aligned with SKILL.md §6)
|
|
24
|
+
|
|
25
|
+
| Step | Tool | Source |
|
|
26
|
+
|---|---|---|
|
|
27
|
+
| 6.1 | `ask_followup_question` (free text) | `prompts/q1-business-scenario.md` |
|
|
28
|
+
| 6.2 | `ask_followup_question` (single-select 4 items) | `prompts/q2-io-modality.md` |
|
|
29
|
+
| 6.3 | `ask_followup_question` (single-select 3 items) | `prompts/q3-ui-form.md` |
|
|
30
|
+
| 6.4 | `ask_followup_question` (multi-select 4 items) | `prompts/q4-capabilities.md` |
|
|
31
|
+
| 6.5 | `write_to_file` render `recipe.yaml` | `output-templates/recipe.yaml.j2` |
|
|
32
|
+
| 6.6 | `execute_command("python3 scripts/add-capability.py <Q4 selections> --apply --json")` | Q4 selections; skip if none |
|
|
33
|
+
| 6.7 | Remaining steps same as Path A (§7 Keys → §8 Contract → §9 Launch) | SKILL.md |
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Constraints / Red Lines
|
|
38
|
+
|
|
39
|
+
- **No builder.py**: The 4-round Q&A is **entirely** facilitated by AI; do not turn this into a local script (the user experience would drop out of the chat window)
|
|
40
|
+
- **No manifest.yaml generation**: Each capability already has its own `manifest.yaml`; Path B does not need to regenerate
|
|
41
|
+
- **prompts/q*.md are static materials**: AI **reads** them only; no content modification / re-formatting
|
|
42
|
+
- **recipe.yaml.j2 uses Jinja2 syntax**: But the AI does not need to actually invoke a Jinja2 interpreter; it can do string replacement mentally and then `write_to_file` the final yaml. The template is just a **structural contract** for the AI
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## After Collecting All Answer Variables, AI Constructs This Context
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
context = {
|
|
50
|
+
# Q1
|
|
51
|
+
"business_desc": "<user's original text>",
|
|
52
|
+
"business_name": "<optional; defaults to 'we' if user didn't specify>",
|
|
53
|
+
|
|
54
|
+
# Q2 option → internal enum
|
|
55
|
+
"io_modality": "text_with_tts", # text_only | text_with_tts | omni | voice_only
|
|
56
|
+
|
|
57
|
+
# Q3 option → internal enum
|
|
58
|
+
"ui_form": "floating", # floating | fullscreen | headless
|
|
59
|
+
|
|
60
|
+
# Q4 user-selected capability array
|
|
61
|
+
"extra_capabilities": [ # any subset; empty array installs skeleton only
|
|
62
|
+
"knowledge-base",
|
|
63
|
+
"human-handoff",
|
|
64
|
+
# "tool-calling",
|
|
65
|
+
# "session-summary",
|
|
66
|
+
],
|
|
67
|
+
|
|
68
|
+
# Meta info (AI fills in)
|
|
69
|
+
"render_time": "<ISO 8601>",
|
|
70
|
+
"rendered_by": "Coding Agent",
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Feed this to `output-templates/recipe.yaml.j2` to get the customized `<workspace>/recipe.yaml`.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Differences from Path A (reference table)
|
|
79
|
+
|
|
80
|
+
| Dimension | Path A | Path B |
|
|
81
|
+
|---|---|---|
|
|
82
|
+
| Entry | "Build me an AI customer service agent with TRTC" | Same, SKILL.md §4 choose B |
|
|
83
|
+
| Installed capabilities | Default `knowledge-base + human-handoff` | Default none; user selects via Q4 |
|
|
84
|
+
| Business prompt | Just ask "describe your business" before launch | Q1 is required (more explicit) |
|
|
85
|
+
| UI | Floating widget + ticket dashboard (default) | Controlled by Q3: floating / fullscreen / headless |
|
|
86
|
+
| recipe.yaml location | `scenarios/customer-service/recipe.yaml` (static in repo) | `<workspace>/recipe.yaml` (generated each time; can be manually edited and re-installed) |
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
{# =========================================================================
|
|
2
|
+
Path B Custom Recipe Render Template (Jinja2)
|
|
3
|
+
|
|
4
|
+
Output: <workspace>/recipe.yaml
|
|
5
|
+
Input (collected by AI in Q1~Q4):
|
|
6
|
+
business_desc string Q1 user answer (required, raw text)
|
|
7
|
+
business_name string Optional (default "Our Company")
|
|
8
|
+
io_modality enum Q2 option → internal enum:
|
|
9
|
+
text_only | text_with_tts | omni | voice_only
|
|
10
|
+
ui_form enum Q3 option → floating | fullscreen | headless
|
|
11
|
+
extra_capabilities list Q4 selected subset; values:
|
|
12
|
+
knowledge-base | human-handoff | tool-calling | session-summary
|
|
13
|
+
|
|
14
|
+
AI rendering notes:
|
|
15
|
+
- Do not push rendering logic down to Python; prefer the AI to perform string replacement / Jinja eval
|
|
16
|
+
mentally, then write the final recipe.yaml all at once with write_to_file
|
|
17
|
+
- If a boolean field cannot be mapped (vague user answer), fallback to the defaults below and confirm with the user
|
|
18
|
+
========================================================================= #}
|
|
19
|
+
# =====================================================================
|
|
20
|
+
# Path B Custom Recipe — {{ business_name | default("Our Company") }} AI Customer Service
|
|
21
|
+
#
|
|
22
|
+
# Generated by SKILL.md §7 flow + custom-builder/output-templates/recipe.yaml.j2
|
|
23
|
+
# Render time: {{ render_time | default("(AI writes ISO timestamp)") }}
|
|
24
|
+
# Rendered by: {{ rendered_by | default("Coding Agent") }}
|
|
25
|
+
# =====================================================================
|
|
26
|
+
apiVersion: ai-customer-service/v1
|
|
27
|
+
kind: Recipe
|
|
28
|
+
metadata:
|
|
29
|
+
name: customer-service-custom
|
|
30
|
+
scenario: customer-service
|
|
31
|
+
source: custom-builder
|
|
32
|
+
version: "1.0.0"
|
|
33
|
+
description: "Generated from Path B 4-round Q&A; can be manually edited and reassembled"
|
|
34
|
+
|
|
35
|
+
# ---------------------------------------------------------------------------
|
|
36
|
+
# Q1: Business description (drives system prompt rendering)
|
|
37
|
+
# ---------------------------------------------------------------------------
|
|
38
|
+
agent_runtime:
|
|
39
|
+
language: "{{ language | default('en') }}"
|
|
40
|
+
voice_id: "{{ voice_id | default('') }}"
|
|
41
|
+
greeting: "{{ greeting | default('Hello, this is the AI customer service for ' ~ (business_name | default('Our Company')) ~ '. How can we help you?') }}"
|
|
42
|
+
max_idle_time: 60
|
|
43
|
+
system_prompt:
|
|
44
|
+
template_file: "../customer-service/system-prompt.template.md"
|
|
45
|
+
variables:
|
|
46
|
+
business_desc: |
|
|
47
|
+
{{ business_desc | trim | replace('\n', '\n ') }}
|
|
48
|
+
business_name: "{{ business_name | default('Our Company') }}"
|
|
49
|
+
|
|
50
|
+
# ---------------------------------------------------------------------------
|
|
51
|
+
# Q2: I/O Modality
|
|
52
|
+
# ---------------------------------------------------------------------------
|
|
53
|
+
runtime_modality:
|
|
54
|
+
preset: "{{ io_modality }}" # text_only | text_with_tts | omni | voice_only
|
|
55
|
+
{%- if io_modality == "text_only" %}
|
|
56
|
+
voice_input: false
|
|
57
|
+
voice_output: false
|
|
58
|
+
text_input: true
|
|
59
|
+
text_output: true
|
|
60
|
+
{%- elif io_modality == "text_with_tts" %}
|
|
61
|
+
voice_input: false
|
|
62
|
+
voice_output: true
|
|
63
|
+
text_input: true
|
|
64
|
+
text_output: true
|
|
65
|
+
{%- elif io_modality == "omni" %}
|
|
66
|
+
voice_input: true
|
|
67
|
+
voice_output: true
|
|
68
|
+
text_input: true
|
|
69
|
+
text_output: true
|
|
70
|
+
{%- elif io_modality == "voice_only" %}
|
|
71
|
+
voice_input: true
|
|
72
|
+
voice_output: true
|
|
73
|
+
text_input: false
|
|
74
|
+
text_output: false
|
|
75
|
+
{%- else %}
|
|
76
|
+
# Unknown modality enum; fallback to text_with_tts
|
|
77
|
+
voice_input: false
|
|
78
|
+
voice_output: true
|
|
79
|
+
text_input: true
|
|
80
|
+
text_output: true
|
|
81
|
+
{%- endif %}
|
|
82
|
+
|
|
83
|
+
# ---------------------------------------------------------------------------
|
|
84
|
+
# Q3: UI Form
|
|
85
|
+
#
|
|
86
|
+
# UI base notes (important):
|
|
87
|
+
# widget-floating has been upgraded to a "real connection" implementation — it reuses
|
|
88
|
+
# conversation-core's TRTC + agent/start pipeline via agent-link.js; AI replies come
|
|
89
|
+
# from LLM subtitle stream, and capabilities (handoff / tools / summaries) are
|
|
90
|
+
# dynamically mounted based on actual backend enablement.
|
|
91
|
+
# (The old hardcoded IM approach is deprecated; always include agent-link.js when
|
|
92
|
+
# overlaying the widget-floating directory.)
|
|
93
|
+
#
|
|
94
|
+
# B2 custom UI: The AI takes the widget-floating "real connection base" and generates
|
|
95
|
+
# a customized skin (business panel / copy / token values) based on the user's business
|
|
96
|
+
# info and color preferences. The core pipeline is unchanged, ensuring the AI is always
|
|
97
|
+
# genuinely connected and satisfies design-system hard constraints (fonts / icons /
|
|
98
|
+
# no emoji / via tokens).
|
|
99
|
+
# ---------------------------------------------------------------------------
|
|
100
|
+
ui:
|
|
101
|
+
form: "{{ ui_form }}" # floating | fullscreen | headless
|
|
102
|
+
{%- if ui_form == "headless" %}
|
|
103
|
+
overlay_required: false
|
|
104
|
+
ui_overlay: null
|
|
105
|
+
{%- else %}
|
|
106
|
+
overlay_required: true
|
|
107
|
+
ui_overlay:
|
|
108
|
+
source_root: "scenarios/customer-service/ui"
|
|
109
|
+
target: "capabilities/conversation-core/web-demo"
|
|
110
|
+
layers:
|
|
111
|
+
- source: "widget-floating"
|
|
112
|
+
target: "."
|
|
113
|
+
replace: true
|
|
114
|
+
{%- if "human-handoff" in extra_capabilities %}
|
|
115
|
+
- source: "admin-board"
|
|
116
|
+
target: "admin"
|
|
117
|
+
replace: true
|
|
118
|
+
{%- endif %}
|
|
119
|
+
{%- if ui_form == "fullscreen" %}
|
|
120
|
+
layout_hint: "fullscreen" # 浮窗模板 + body 上挂 fullscreen class(CSS 强制铺满)
|
|
121
|
+
{%- endif %}
|
|
122
|
+
{%- endif %}
|
|
123
|
+
|
|
124
|
+
# ---------------------------------------------------------------------------
|
|
125
|
+
# Q4: Capabilities Checklist
|
|
126
|
+
# Assembly command (AI executes in §7.3):
|
|
127
|
+
# python3 scripts/add-capability.py {{ extra_capabilities | join(' ') }} --apply --json
|
|
128
|
+
# Skip assembly when extra_capabilities is empty
|
|
129
|
+
# ---------------------------------------------------------------------------
|
|
130
|
+
capabilities:
|
|
131
|
+
required:
|
|
132
|
+
- name: conversation-core
|
|
133
|
+
role: skeleton
|
|
134
|
+
install:
|
|
135
|
+
{%- for cap in extra_capabilities %}
|
|
136
|
+
{%- if cap == "knowledge-base" %}
|
|
137
|
+
- name: knowledge-base
|
|
138
|
+
role: capability
|
|
139
|
+
adapter: mock # Default mock; switch to local_json or default_rest before launch
|
|
140
|
+
env:
|
|
141
|
+
KB_ADAPTER: mock
|
|
142
|
+
KB_TOP_K: "3"
|
|
143
|
+
KB_MIN_SCORE: "0.1"
|
|
144
|
+
{%- elif cap == "human-handoff" %}
|
|
145
|
+
- name: human-handoff
|
|
146
|
+
role: capability
|
|
147
|
+
adapter: local_queue # Default local queue; switch to default_rest to connect to real ticketing system
|
|
148
|
+
env:
|
|
149
|
+
HH_ADAPTER: local_queue
|
|
150
|
+
{%- elif cap == "tool-calling" %}
|
|
151
|
+
- name: tool-calling
|
|
152
|
+
role: capability
|
|
153
|
+
# For tool-calling alpha/beta dual-track details, see capabilities/tool-calling/INTERFACE_ADAPT.md
|
|
154
|
+
{%- elif cap == "session-summary" %}
|
|
155
|
+
- name: session-summary
|
|
156
|
+
role: capability
|
|
157
|
+
# Depends on LLM_API_KEY; ensure §5 LLM Key configuration is complete
|
|
158
|
+
{%- endif %}
|
|
159
|
+
{%- endfor %}
|
|
160
|
+
{%- if not extra_capabilities %}
|
|
161
|
+
[] # No capability selected; install skeleton only
|
|
162
|
+
{%- endif %}
|
|
163
|
+
optional: []
|
|
164
|
+
excluded:
|
|
165
|
+
- name: digital-human # Not in current scope
|
|
166
|
+
|
|
167
|
+
# ---------------------------------------------------------------------------
|
|
168
|
+
# Post-launch must-do: contract checklist reminder (see SKILL.md §9)
|
|
169
|
+
# ---------------------------------------------------------------------------
|
|
170
|
+
post_assembly:
|
|
171
|
+
contract_review:
|
|
172
|
+
enabled: true
|
|
173
|
+
capabilities:
|
|
174
|
+
{%- for cap in extra_capabilities %}
|
|
175
|
+
- "{{ cap }}"
|
|
176
|
+
{%- endfor %}
|
|
177
|
+
{%- if not extra_capabilities %}
|
|
178
|
+
[]
|
|
179
|
+
{%- endif %}
|
|
180
|
+
sop_section: "SKILL.md#8"
|
|
181
|
+
health_check:
|
|
182
|
+
url: "http://localhost:3000/api/v1/health"
|
|
183
|
+
expect_field: "status"
|
|
184
|
+
expect_value: "ok"
|
|
185
|
+
|
|
186
|
+
# ---------------------------------------------------------------------------
|
|
187
|
+
# Design language lock (consistent with Path A)
|
|
188
|
+
# ---------------------------------------------------------------------------
|
|
189
|
+
design:
|
|
190
|
+
tokens_file: "../../design_tokens.json"
|
|
191
|
+
guidelines: "../customer-service/ui/design-system/DESIGN_GUIDELINES.md"
|
|
192
|
+
theme: "dark"
|
|
193
|
+
emoji_in_ui: false
|
|
194
|
+
font_family: "SF Pro, Inter, 'Helvetica Neue', sans-serif"
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Q1 —— Business Description (free text)
|
|
2
|
+
|
|
3
|
+
> Path B Question 1. AI uses `ask_followup_question` as a standalone question, **without options**, letting the user type freely.
|
|
4
|
+
>
|
|
5
|
+
> AI saves the user's answer to the internal variable `business_desc`, for later use in:
|
|
6
|
+
> 1. Rendering `{{business_desc}}` in `scenarios/customer-service/system-prompt.template.md`
|
|
7
|
+
> 2. Writing to `<workspace>/recipe.yaml` at `agent_runtime.system_prompt.variables.business_desc`
|
|
8
|
+
>
|
|
9
|
+
> AI must **not** guess the industry; leave unsaid fields blank and backfill after Q4.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## What the AI should say
|
|
14
|
+
|
|
15
|
+
> Question 1 (of 4): What business is your customer service bot for?
|
|
16
|
+
> Just describe the **business scope** and **typical questions** in a sentence or two. For example:
|
|
17
|
+
>
|
|
18
|
+
> - "We are an e-commerce store selling smart home appliances — air fryers, robot vacuums, humidifiers. Users usually ask about warranty, returns, and shipping."
|
|
19
|
+
> - "I run customer support for a SaaS HR platform. Common issues are login failures, org structure sync, and plan upgrades."
|
|
20
|
+
> - "A restaurant delivery service. Users mainly ask about order status, refunds, menu stock, and delivery fees."
|
|
21
|
+
>
|
|
22
|
+
> The more specific your business, the better the final system prompt will match your real scenario.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Validation after receiving the answer
|
|
27
|
+
|
|
28
|
+
- Length ≥ 8 and ≤ 600 characters. If too short, follow up: "That's quite brief — could you add a bit more about typical issues or industry keywords?"
|
|
29
|
+
- Must contain at least one noun phrase (industry name, product name, user type); pure interjections or casual chat → **re-ask**
|
|
30
|
+
- Do not ask the user to provide brand name / company name (if needed, the template uses placeholder `{{business_name | default('we')}}`)
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Answer write-back
|
|
35
|
+
|
|
36
|
+
```yaml
|
|
37
|
+
# Render to <workspace>/recipe.yaml
|
|
38
|
+
agent_runtime:
|
|
39
|
+
system_prompt:
|
|
40
|
+
variables:
|
|
41
|
+
business_desc: |
|
|
42
|
+
<user's original text>
|
|
43
|
+
```
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Q2 —— I/O Modality (4 choose 1)
|
|
2
|
+
|
|
3
|
+
> Path B Question 2. AI uses `ask_followup_question` in **single-select** mode.
|
|
4
|
+
>
|
|
5
|
+
> Answer written to internal variable `io_modality` (mapped to English enums in the table below), later used to:
|
|
6
|
+
> 1. Determine whether `agent_runtime.greeting` uses TTS audio
|
|
7
|
+
> 2. Set conversation-core `io_modality.*.enabled` fields
|
|
8
|
+
> 3. Decide whether the floating widget UI exposes a microphone button
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## What the AI should say (recommend copy-pasting directly into ask_followup_question)
|
|
13
|
+
|
|
14
|
+
> Question 2: What I/O modality should be used between end users and the AI agent?
|
|
15
|
+
|
|
16
|
+
`options` (keep order; order corresponds one-to-one with enums below):
|
|
17
|
+
|
|
18
|
+
```text
|
|
19
|
+
① Text-only IM (user types → AI replies in text; no voice)
|
|
20
|
+
② Text + TTS (user types → AI replies in text + reads aloud, recommended)
|
|
21
|
+
③ Omni-modal (voice + text, bidirectional; user can also speak)
|
|
22
|
+
④ Voice-only call (user dials → AI answers → full voice; no demo UI in this release)
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`multiSelect: false`
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Option → Backend Config Mapping
|
|
30
|
+
|
|
31
|
+
| User Option | Internal Enum (`io_modality`) | conversation-core io_modality Config | UI Impact |
|
|
32
|
+
|---|---|---|---|
|
|
33
|
+
| ① Text-only | `text_only` | voice_input=disabled, voice_output=disabled | Widget shows input box only; mic hidden |
|
|
34
|
+
| ② Text + TTS (recommended) | `text_with_tts` | voice_input=disabled, voice_output=enabled (trtc-tts) | Widget shows input box + "read aloud" toggle; mic hidden |
|
|
35
|
+
| ③ Omni-modal | `omni` | voice_input=enabled (trtc-asr), voice_output=enabled | Widget shows input box + mic (push-to-talk) |
|
|
36
|
+
| ④ Voice-only call | `voice_only` | voice_input=enabled, voice_output=enabled, text_input=disabled | No UI; backend phone gateway only (no floating widget in this release) |
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Validation / Fallback
|
|
41
|
+
|
|
42
|
+
- User picks ④ but Q3 picks "floating" → warn about conflict, guide user to change Q3 to "headless"
|
|
43
|
+
- User picks ② / ③ but LLM verification fails → save the choice, still write to recipe per user's intent; after launch, the widget will show "voice output depends on TTS key, currently unavailable"
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Answer write-back
|
|
48
|
+
|
|
49
|
+
```yaml
|
|
50
|
+
# Render to <workspace>/recipe.yaml
|
|
51
|
+
runtime_modality:
|
|
52
|
+
preset: text_with_tts # From "Internal Enum" column above
|
|
53
|
+
voice_input: false
|
|
54
|
+
voice_output: true
|
|
55
|
+
text_input: true
|
|
56
|
+
text_output: true
|
|
57
|
+
```
|