@tencent-rtc/trtc-agent-skills 0.1.1 → 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 -97
- package/CLAUDE.md +15 -120
- 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 +26 -3
- 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 +155 -0
- package/knowledge-base/slices/conference/web/login-auth.md +16 -2
- package/knowledge-base/slices/conference/web/official-roomkit-login-ui.md +41 -13
- package/knowledge-base/slices/conference/web/prejoin-check.md +8 -5
- 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 -244
- 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/room-builder/assets/local-usersig/basic-info-config.ts +39 -0
- package/skills/trtc/room-builder/assets/local-usersig/lib-generate-test-usersig-es.min.d.ts +4 -0
- package/skills/trtc/room-builder/assets/local-usersig/lib-generate-test-usersig-es.min.js +2 -0
- package/skills/{trtc-topic → trtc}/runtime/README.md +2 -2
- package/skills/{trtc-onboarding/reference/reporting-protocol.md → trtc/runtime/REPORTING.md} +5 -3
- 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/runtime/usersig-handling.md +134 -0
- 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 -92
- package/ai-instructions/base.md +0 -13
- package/ai-instructions/ui-mode.md +0 -86
- package/knowledge-base/index.yaml +0 -454
- package/skills/trtc/room-builder/SKILL.md +0 -138
- 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 -839
- package/skills/trtc-onboarding/reference/path-a1-demo.md +0 -103
- package/skills/trtc-onboarding/reference/path-a2-integrate.md +0 -693
- package/skills/trtc-onboarding/reference/path-b-troubleshoot.md +0 -115
- package/skills/trtc-onboarding/reference/path-c-expand.md +0 -43
- package/skills/trtc-onboarding/reference/supported-matrix.md +0 -100
- package/skills/trtc-onboarding/reference/usersig-handling.md +0 -140
- package/skills/trtc-search/SKILL.md +0 -221
- package/skills/trtc-topic/SKILL.md +0 -638
- 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-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
|
+
"""session-summary FastAPI sub-router."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import os
|
|
5
|
+
from typing import List, Optional
|
|
6
|
+
|
|
7
|
+
from fastapi import APIRouter, HTTPException
|
|
8
|
+
from pydantic import BaseModel, Field
|
|
9
|
+
|
|
10
|
+
from .recorder import get_recorder
|
|
11
|
+
from .summarizer import summarize
|
|
12
|
+
|
|
13
|
+
router = APIRouter()
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# ---------------------------------------------------------------------------
|
|
17
|
+
# Request bodies
|
|
18
|
+
# ---------------------------------------------------------------------------
|
|
19
|
+
class TurnItem(BaseModel):
|
|
20
|
+
role: str = Field(..., max_length=16)
|
|
21
|
+
text: str = Field("", max_length=4096)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class RecordBody(BaseModel):
|
|
25
|
+
"""Batch-upload conversation turns so a summary can be attached to a ticket
|
|
26
|
+
before the frontend requests a handoff."""
|
|
27
|
+
|
|
28
|
+
turns: List[TurnItem] = Field(default_factory=list)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@router.get("/_list")
|
|
32
|
+
def list_recent(_offset: int = 0, _limit: int = 20) -> dict:
|
|
33
|
+
if _limit < 1 or _limit > 200:
|
|
34
|
+
raise HTTPException(status_code=400, detail="_limit out of range [1,200]")
|
|
35
|
+
return {"code": 0, "data": get_recorder().list_recent(offset=_offset, limit=_limit)}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@router.get("/{session_id}")
|
|
39
|
+
def get_summary(session_id: str) -> dict:
|
|
40
|
+
rec = get_recorder().get(session_id)
|
|
41
|
+
if rec is None:
|
|
42
|
+
raise HTTPException(status_code=404, detail=f"session not found: {session_id}")
|
|
43
|
+
return {"code": 0, "data": rec.to_dict()}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@router.post("/{session_id}/record")
|
|
47
|
+
def record_turns(session_id: str, body: RecordBody) -> dict:
|
|
48
|
+
"""Batch-record conversation turns for a session.
|
|
49
|
+
|
|
50
|
+
Called by the frontend right before requesting a human handoff, so that
|
|
51
|
+
attach_summary_to_ticket can produce a context summary from the transcript.
|
|
52
|
+
Safe to call repeatedly; idempotent per turn text.
|
|
53
|
+
"""
|
|
54
|
+
recorder = get_recorder()
|
|
55
|
+
recorder.open(session_id)
|
|
56
|
+
accepted = 0
|
|
57
|
+
for t in body.turns:
|
|
58
|
+
role = (t.role or "").strip().lower()
|
|
59
|
+
if role not in ("user", "assistant", "system", "tool"):
|
|
60
|
+
continue
|
|
61
|
+
if not t.text:
|
|
62
|
+
continue
|
|
63
|
+
recorder.add_turn(session_id, role, t.text)
|
|
64
|
+
accepted += 1
|
|
65
|
+
rec = recorder.get(session_id)
|
|
66
|
+
return {
|
|
67
|
+
"code": 0,
|
|
68
|
+
"data": {
|
|
69
|
+
"session_id": session_id,
|
|
70
|
+
"accepted": accepted,
|
|
71
|
+
"total_turns": len(rec.turns) if rec else 0,
|
|
72
|
+
},
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@router.post("/{session_id}/finalize")
|
|
77
|
+
def finalize(session_id: str) -> dict:
|
|
78
|
+
rec = get_recorder().get(session_id)
|
|
79
|
+
if rec is None:
|
|
80
|
+
raise HTTPException(status_code=404, detail=f"session not found: {session_id}")
|
|
81
|
+
prefer_llm = os.getenv("SS_LLM_SUMMARY", "true").lower() == "true"
|
|
82
|
+
summary = summarize(rec, prefer_llm=prefer_llm)
|
|
83
|
+
rec = get_recorder().finalize(session_id, summary)
|
|
84
|
+
# Write-back: select mock / local_json / default_rest by SS_ADAPTER (safe degradation to mock on failure)
|
|
85
|
+
writeback = None
|
|
86
|
+
try:
|
|
87
|
+
from .adapters.factory import get_sink
|
|
88
|
+
writeback = get_sink().write(rec.to_dict())
|
|
89
|
+
except Exception as exc: # noqa: BLE001
|
|
90
|
+
writeback = {"accepted": False, "error": str(exc)}
|
|
91
|
+
data = rec.to_dict()
|
|
92
|
+
data["writeback"] = writeback
|
|
93
|
+
return {"code": 0, "data": data}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"""Structured summary generator.
|
|
2
|
+
|
|
3
|
+
Strategy:
|
|
4
|
+
- Offline heuristic (default): extract questions / to-do keywords / key nouns, done locally with zero dependencies.
|
|
5
|
+
- LLM secondary summarization (optional, requires LLM_API_KEY): serialize turns and call OpenAI-compatible protocol.
|
|
6
|
+
|
|
7
|
+
Output JSON:
|
|
8
|
+
{
|
|
9
|
+
"topics": ["..."],
|
|
10
|
+
"user_intents": ["..."],
|
|
11
|
+
"next_actions": ["..."],
|
|
12
|
+
"highlights": ["..."],
|
|
13
|
+
"engine": "heuristic" | "llm",
|
|
14
|
+
"model": "gpt-4o-mini" | null
|
|
15
|
+
}
|
|
16
|
+
"""
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
import json
|
|
20
|
+
import logging
|
|
21
|
+
import os
|
|
22
|
+
import re
|
|
23
|
+
from typing import Any, Dict, List, Optional
|
|
24
|
+
|
|
25
|
+
from .recorder import SessionRecord
|
|
26
|
+
|
|
27
|
+
logger = logging.getLogger(__name__)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
_QUESTION_RE = re.compile(r"[^??]+[??]")
|
|
31
|
+
_ACTION_RE = re.compile(r"(I want|please help|need to|please)([^。.!??!\n]+)", re.IGNORECASE)
|
|
32
|
+
_NOUN_RE = re.compile(r"[A-Z][A-Za-z0-9_]{2,}|[\u4e00-\u9fff]{2,}")
|
|
33
|
+
_STOPWORDS = {"the", "a", "an", "because", "so", "when", "can", "need"}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _heuristic(record: SessionRecord) -> Dict[str, Any]:
|
|
37
|
+
topics: List[str] = []
|
|
38
|
+
intents: List[str] = []
|
|
39
|
+
actions: List[str] = []
|
|
40
|
+
highlights: List[str] = []
|
|
41
|
+
seen_topic, seen_intent, seen_action = set(), set(), set()
|
|
42
|
+
for t in record.turns:
|
|
43
|
+
if t.role != "user":
|
|
44
|
+
continue
|
|
45
|
+
for q in _QUESTION_RE.findall(t.text):
|
|
46
|
+
q = q.strip()
|
|
47
|
+
if q and q not in seen_intent:
|
|
48
|
+
intents.append(q[:120])
|
|
49
|
+
seen_intent.add(q)
|
|
50
|
+
for m in _ACTION_RE.finditer(t.text):
|
|
51
|
+
phrase = (m.group(1) + m.group(2)).strip()[:120]
|
|
52
|
+
if phrase and phrase not in seen_action:
|
|
53
|
+
actions.append(phrase)
|
|
54
|
+
seen_action.add(phrase)
|
|
55
|
+
for noun in _NOUN_RE.findall(t.text):
|
|
56
|
+
if noun in _STOPWORDS or len(noun) > 24:
|
|
57
|
+
continue
|
|
58
|
+
if noun not in seen_topic and len(topics) < 8:
|
|
59
|
+
topics.append(noun)
|
|
60
|
+
seen_topic.add(noun)
|
|
61
|
+
if record.turns:
|
|
62
|
+
highlights.append(f"{len(record.turns)} turns recorded")
|
|
63
|
+
return {
|
|
64
|
+
"topics": topics,
|
|
65
|
+
"user_intents": intents[:5],
|
|
66
|
+
"next_actions": actions[:5],
|
|
67
|
+
"highlights": highlights,
|
|
68
|
+
"engine": "heuristic",
|
|
69
|
+
"model": None,
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _llm_summarize(record: SessionRecord) -> Dict[str, Any]:
|
|
74
|
+
api_key = os.getenv("LLM_API_KEY")
|
|
75
|
+
api_url = os.getenv("LLM_API_URL", "https://api.openai.com/v1/chat/completions")
|
|
76
|
+
model = os.getenv("LLM_MODEL", "gpt-4o-mini")
|
|
77
|
+
if not api_key:
|
|
78
|
+
raise RuntimeError("LLM_API_KEY not configured")
|
|
79
|
+
import requests
|
|
80
|
+
|
|
81
|
+
transcript = "\n".join(f"[{t.role}] {t.text}" for t in record.turns[-50:])
|
|
82
|
+
prompt = (
|
|
83
|
+
"You are a session summary assistant. Summarize the following conversation as JSON with keys: topics, user_intents,"
|
|
84
|
+
" next_actions, highlights. Each value is a string array (max 5 items)."
|
|
85
|
+
"Do not include any sensitive information (API Key/Token etc.).\n"
|
|
86
|
+
f"Conversation content:\n{transcript}\n"
|
|
87
|
+
"Output JSON only."
|
|
88
|
+
)
|
|
89
|
+
resp = requests.post(
|
|
90
|
+
api_url,
|
|
91
|
+
headers={"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"},
|
|
92
|
+
json={
|
|
93
|
+
"model": model,
|
|
94
|
+
"messages": [{"role": "user", "content": prompt}],
|
|
95
|
+
"temperature": 0.2,
|
|
96
|
+
"response_format": {"type": "json_object"},
|
|
97
|
+
},
|
|
98
|
+
timeout=20,
|
|
99
|
+
)
|
|
100
|
+
resp.raise_for_status()
|
|
101
|
+
data = resp.json()
|
|
102
|
+
content = data["choices"][0]["message"]["content"]
|
|
103
|
+
try:
|
|
104
|
+
parsed = json.loads(content)
|
|
105
|
+
except json.JSONDecodeError:
|
|
106
|
+
parsed = {"highlights": [content[:512]]}
|
|
107
|
+
parsed.setdefault("topics", [])
|
|
108
|
+
parsed.setdefault("user_intents", [])
|
|
109
|
+
parsed.setdefault("next_actions", [])
|
|
110
|
+
parsed.setdefault("highlights", [])
|
|
111
|
+
parsed["engine"] = "llm"
|
|
112
|
+
parsed["model"] = model
|
|
113
|
+
return parsed
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def summarize(record: SessionRecord, *, prefer_llm: bool = True) -> Dict[str, Any]:
|
|
117
|
+
if prefer_llm and os.getenv("LLM_API_KEY"):
|
|
118
|
+
try:
|
|
119
|
+
return _llm_summarize(record)
|
|
120
|
+
except Exception as exc: # noqa: BLE001
|
|
121
|
+
logger.warning("LLM summarize failed, fallback to heuristic: %s", exc)
|
|
122
|
+
return _heuristic(record)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def summarize_paragraph(record: SessionRecord) -> Optional[str]:
|
|
126
|
+
"""Generate a one-paragraph narrative summary of the session via LLM.
|
|
127
|
+
|
|
128
|
+
Used by the handoff flow to fill a ticket's Description with an LLM summary of the
|
|
129
|
+
chat from AI connect → handoff trigger. Returns None if LLM is not configured or the
|
|
130
|
+
session has no turns (caller then leaves the description unchanged).
|
|
131
|
+
"""
|
|
132
|
+
api_key = os.getenv("LLM_API_KEY")
|
|
133
|
+
if not api_key:
|
|
134
|
+
return None
|
|
135
|
+
if not record.turns:
|
|
136
|
+
return None
|
|
137
|
+
import requests
|
|
138
|
+
|
|
139
|
+
api_url = os.getenv("LLM_API_URL", "https://api.openai.com/v1/chat/completions")
|
|
140
|
+
model = os.getenv("LLM_MODEL", "gpt-4o-mini")
|
|
141
|
+
transcript = "\n".join(f"[{t.role}] {t.text}" for t in record.turns[-50:])
|
|
142
|
+
prompt = (
|
|
143
|
+
"You are a customer-service ticket summarizer. Read the conversation below between "
|
|
144
|
+
"a customer and an AI assistant, then write ONE concise paragraph (2-4 sentences) "
|
|
145
|
+
"summarizing what the customer asked about and what was discussed, from the moment "
|
|
146
|
+
"the AI connected up to the point the customer requested a human agent. Do not invent "
|
|
147
|
+
"facts not present in the conversation. Do not include any sensitive data (API key / "
|
|
148
|
+
"token etc.). Output only the paragraph, with no preamble.\n"
|
|
149
|
+
f"Conversation:\n{transcript}\n"
|
|
150
|
+
)
|
|
151
|
+
resp = requests.post(
|
|
152
|
+
api_url,
|
|
153
|
+
headers={"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"},
|
|
154
|
+
json={
|
|
155
|
+
"model": model,
|
|
156
|
+
"messages": [{"role": "user", "content": prompt}],
|
|
157
|
+
"temperature": 0.3,
|
|
158
|
+
},
|
|
159
|
+
timeout=20,
|
|
160
|
+
)
|
|
161
|
+
resp.raise_for_status()
|
|
162
|
+
data = resp.json()
|
|
163
|
+
return (data["choices"][0]["message"]["content"] or "").strip() or None
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# tool-calling Interface Adaptation SOP
|
|
2
|
+
|
|
3
|
+
> Alpha/beta dual-track tool calling. This capability's source code has not been refactored to ports/adapters/core in this release (Phase 1 compromise),
|
|
4
|
+
> but the manifest already declares the full `business_contract.alpha_track` / `beta_track` / `arbitration` contracts.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 1. Dual-Track Contract Overview
|
|
9
|
+
|
|
10
|
+
### 1.1 Alpha Track (local functions)
|
|
11
|
+
|
|
12
|
+
```yaml
|
|
13
|
+
alpha_track:
|
|
14
|
+
registration_schema:
|
|
15
|
+
name: string # e.g.: query_order
|
|
16
|
+
description: string # Tool description for LLM consumption
|
|
17
|
+
parameters: object # JSON Schema
|
|
18
|
+
handler: callable # Sync or async Python function
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Alpha track is suitable for: low latency, tight business coupling, tools that are inconvenient to expose as HTTP services.
|
|
22
|
+
|
|
23
|
+
### 1.2 Beta Track (remote APIs)
|
|
24
|
+
|
|
25
|
+
```yaml
|
|
26
|
+
beta_track:
|
|
27
|
+
api_schema:
|
|
28
|
+
method: GET | POST | PUT | DELETE | PATCH
|
|
29
|
+
path: string
|
|
30
|
+
request_schema: object
|
|
31
|
+
response_schema: object
|
|
32
|
+
auth: bearer | api_key | none
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Beta track is suitable for: cross-service calls, tools that need to reuse existing API gateways.
|
|
36
|
+
|
|
37
|
+
### 1.3 Arbitration Rules
|
|
38
|
+
|
|
39
|
+
```yaml
|
|
40
|
+
arbitration:
|
|
41
|
+
default_priority: alpha # Alpha first
|
|
42
|
+
fallback_on_failure: true # Alpha failure auto-degrades to beta
|
|
43
|
+
timeout_ms: 3000 # Single-track call timeout
|
|
44
|
+
merge_strategy: first_success # Take first success only
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## 2. Three Scenarios When User Interfaces Don't Match
|
|
50
|
+
|
|
51
|
+
### 2.1 Scenario 1: User's alpha-track function signature differs
|
|
52
|
+
|
|
53
|
+
**Symptom**: The user already has local functions (e.g. `def get_order(order_id, user_id) -> dict`),
|
|
54
|
+
but the skeleton expects parameters named `id` / `customer_id`.
|
|
55
|
+
|
|
56
|
+
**Solution**: Write a thin wrapper registration function — no need to modify the skeleton.
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
# Inside user project
|
|
60
|
+
from capabilities.tool_calling.src.dispatcher import register_tool
|
|
61
|
+
|
|
62
|
+
def get_order(order_id, user_id):
|
|
63
|
+
"""User's existing function."""
|
|
64
|
+
return {"order_id": order_id, "status": "shipped"}
|
|
65
|
+
|
|
66
|
+
# Adaptation layer: parameter remapping
|
|
67
|
+
register_tool(
|
|
68
|
+
name="query_order",
|
|
69
|
+
description="Query order status",
|
|
70
|
+
parameters={
|
|
71
|
+
"type": "object",
|
|
72
|
+
"properties": {
|
|
73
|
+
"id": {"type": "string"},
|
|
74
|
+
"customer_id": {"type": "string"},
|
|
75
|
+
},
|
|
76
|
+
"required": ["id", "customer_id"],
|
|
77
|
+
},
|
|
78
|
+
handler=lambda id, customer_id: get_order(id, customer_id), # Field remapping
|
|
79
|
+
)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### 2.2 Scenario 2: User's beta-track remote API uses a different protocol
|
|
83
|
+
|
|
84
|
+
**Symptom**: The remote business API is not OpenAI Tool Calling-style JSON-RPC,
|
|
85
|
+
but a user's own REST endpoint (e.g. `POST /api/v1/orders/query`).
|
|
86
|
+
|
|
87
|
+
**Solution**: Declare the full API schema when registering in `tools.yaml`.
|
|
88
|
+
|
|
89
|
+
```yaml
|
|
90
|
+
# capabilities/tool-calling/data/tools.yaml
|
|
91
|
+
tools:
|
|
92
|
+
- name: query_order
|
|
93
|
+
description: Query order status
|
|
94
|
+
alpha: null # No local implementation
|
|
95
|
+
beta:
|
|
96
|
+
base_url: https://api.example.com # Must be HTTPS
|
|
97
|
+
method: POST
|
|
98
|
+
path: /api/v1/orders/query
|
|
99
|
+
headers:
|
|
100
|
+
X-Api-Key: ${USER_KB_TOKEN} # Read from environment variable
|
|
101
|
+
request_template:
|
|
102
|
+
body:
|
|
103
|
+
order_no: "{{ id }}" # Template render: map tool input id to order_no
|
|
104
|
+
uid: "{{ customer_id }}"
|
|
105
|
+
response_path: "$.data.order" # Response field extraction (JSONPath)
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
> This release's advanced template rendering in tools.yaml is **not fully implemented**;
|
|
109
|
+
> for complex mapping needs, it's recommended to rewrite as an alpha-track local function + internal `requests` call.
|
|
110
|
+
|
|
111
|
+
### 2.3 Scenario 3: User wants to disable beta track (local functions only)
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
export TC_PRIORITY=alpha
|
|
115
|
+
export TC_DISABLE_BETA=1
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
The skeleton only uses alpha track; beta failures will not trigger. Vice versa (`TC_DISABLE_ALPHA=1`).
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## 3. Arbitration Priority Override
|
|
123
|
+
|
|
124
|
+
The manifest defaults to `priority=alpha`; can be overridden via environment variables:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
export TC_PRIORITY=beta # Beta first (when alpha implementation is not yet stable)
|
|
128
|
+
export TC_PRIORITY=manifest_order # Follow order of alpha/beta fields in tools.yaml
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## 4. Phase 4 Plan: Full ports/adapters Refactor
|
|
134
|
+
|
|
135
|
+
The following will be introduced in the future:
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
capabilities/tool-calling/src/
|
|
139
|
+
├── ports/
|
|
140
|
+
│ ├── local_tool.py # ABC: LocalTool
|
|
141
|
+
│ └── remote_tool.py # ABC: RemoteToolClient
|
|
142
|
+
└── adapters/
|
|
143
|
+
├── alpha_python.py # Alpha default implementation (current dispatcher behavior)
|
|
144
|
+
├── beta_rest.py # Beta default implementation
|
|
145
|
+
└── user_custom.py # User integration wizard generator
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
This document will be supplemented with automated adaptation workflows at that time.
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## 5. Security Checklist
|
|
153
|
+
|
|
154
|
+
- [ ] Beta track `base_url` must use https:// (localhost excepted)
|
|
155
|
+
- [ ] Reject private network access (9.* / 10.* / 172.16-31.* / 192.168.*)
|
|
156
|
+
- [ ] `Authorization` / `X-Api-Key` only from environment variables
|
|
157
|
+
- [ ] Alpha track handlers must not expose `eval` / `exec` / arbitrary command execution
|
|
158
|
+
- [ ] Tool result re-injection must have prompt injection protection (manifest.security.injection_protection)
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# tool-calling · Alpha/Beta Dual-Track Tool Calling
|
|
2
|
+
|
|
3
|
+
> Provides local function (alpha) + remote API (beta) tool calling on top of conversation-core,
|
|
4
|
+
> with alpha-first by default and automatic degradation to beta on alpha failure (P1 arbitration rules).
|
|
5
|
+
|
|
6
|
+
## Install
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
python scripts/add-capability.py tool-calling
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Configuration
|
|
13
|
+
|
|
14
|
+
| Env Variable | Default | Description |
|
|
15
|
+
|:---|:---|:---|
|
|
16
|
+
| `TC_REGISTRY_FILE` | `capabilities/tool-calling/data/tools.yaml` | Tool declaration file |
|
|
17
|
+
|
|
18
|
+
Tool declaration format in `data/tools.yaml`, supports hot-reload (`POST /api/v1/tools/reload`).
|
|
19
|
+
|
|
20
|
+
## REST API
|
|
21
|
+
|
|
22
|
+
| Method | Path | Purpose |
|
|
23
|
+
|:---|:---|:---|
|
|
24
|
+
| GET | `/api/v1/tools/list` | List all tools |
|
|
25
|
+
| POST | `/api/v1/tools/invoke` | Explicit invocation `{name, params, priority?}` |
|
|
26
|
+
| POST | `/api/v1/tools/reload` | Reload registry |
|
|
27
|
+
|
|
28
|
+
## In-Conversation Trigger
|
|
29
|
+
|
|
30
|
+
Push the following text to `agent/control` to trigger:
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
/tool get_order {"order_id": "A1234"}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The dispatcher replaces the original text with a `[tool_result ...]...[/tool_result]` block and injects it into the LLM.
|
|
37
|
+
|
|
38
|
+
## Arbitration Rules
|
|
39
|
+
|
|
40
|
+
- `priority=alpha` (default): alpha first, then beta
|
|
41
|
+
- `priority=beta`: beta first, then alpha
|
|
42
|
+
- `priority=manifest_order`: follow declaration order
|
|
43
|
+
|
|
44
|
+
Automatic degradation to the next available track on any track failure; returns `ok=false` and `fallback_chain` when all fail.
|
|
45
|
+
|
|
46
|
+
## Security
|
|
47
|
+
|
|
48
|
+
- Beta track enforces HTTPS (except `http://localhost*`);
|
|
49
|
+
- Tool name ≤ 64, trigger text ≤ 4096;
|
|
50
|
+
- Tool parameters auto-redacted in logs (manifest declares `log_redaction.patterns`).
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# tool-calling default tool registry — generic AI customer service toolset (industry-neutral)
|
|
2
|
+
#
|
|
3
|
+
# Dual-track notes:
|
|
4
|
+
# alpha (α track) = local function / mock implementation: works out of the box, no real backend needed, easy local demo
|
|
5
|
+
# beta (β track) = remote HTTPS API: point the endpoint at your real business system
|
|
6
|
+
# Default priority=alpha: prefer local mock; change priority or pass priority=beta in a single invoke to force real API.
|
|
7
|
+
# When interfaces don't align, refer to INTERFACE_ADAPT.md for request/response field mapping.
|
|
8
|
+
|
|
9
|
+
priority: alpha # alpha | beta | manifest_order
|
|
10
|
+
|
|
11
|
+
tools:
|
|
12
|
+
- name: query_order_status
|
|
13
|
+
description: "Query document/order/ticket status (input order_id) — high-frequency customer service action"
|
|
14
|
+
alpha:
|
|
15
|
+
module: "capabilities.tool_calling.examples.local_tools"
|
|
16
|
+
function: "query_order_status"
|
|
17
|
+
timeout_ms: 600
|
|
18
|
+
beta:
|
|
19
|
+
endpoint: "https://api.example.com/v1/orders/status"
|
|
20
|
+
method: "POST"
|
|
21
|
+
timeout_ms: 5000
|
|
22
|
+
headers: {}
|
|
23
|
+
|
|
24
|
+
- name: get_business_info
|
|
25
|
+
description: "Query business info: hours/address/contact (topic=hours|address|contact|all)"
|
|
26
|
+
alpha:
|
|
27
|
+
module: "capabilities.tool_calling.examples.local_tools"
|
|
28
|
+
function: "get_business_info"
|
|
29
|
+
timeout_ms: 400
|
|
30
|
+
beta:
|
|
31
|
+
endpoint: "https://api.example.com/v1/business/info"
|
|
32
|
+
method: "GET"
|
|
33
|
+
timeout_ms: 5000
|
|
34
|
+
headers: {}
|
|
35
|
+
|
|
36
|
+
- name: book_appointment
|
|
37
|
+
description: "Create appointment/booking: restaurant reservations, service appointments, etc. (date, time_slot, party_size)"
|
|
38
|
+
alpha:
|
|
39
|
+
module: "capabilities.tool_calling.examples.local_tools"
|
|
40
|
+
function: "book_appointment"
|
|
41
|
+
timeout_ms: 800
|
|
42
|
+
beta:
|
|
43
|
+
endpoint: "https://api.example.com/v1/appointments"
|
|
44
|
+
method: "POST"
|
|
45
|
+
timeout_ms: 5000
|
|
46
|
+
headers: {}
|
|
47
|
+
|
|
48
|
+
- name: submit_feedback
|
|
49
|
+
description: "Submit satisfaction rating/feedback (rating 1-5, comment) — common end-of-session action"
|
|
50
|
+
alpha:
|
|
51
|
+
module: "capabilities.tool_calling.examples.local_tools"
|
|
52
|
+
function: "submit_feedback"
|
|
53
|
+
timeout_ms: 400
|
|
54
|
+
beta:
|
|
55
|
+
endpoint: "https://api.example.com/v1/feedback"
|
|
56
|
+
method: "POST"
|
|
57
|
+
timeout_ms: 5000
|
|
58
|
+
headers: {}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""tool-calling built-in example tools namespace."""
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"""tool-calling built-in "Generic AI Customer Service Tool Set" (alpha-track default = local mock).
|
|
2
|
+
|
|
3
|
+
Design principles (aligned with SKILL §6 point 2):
|
|
4
|
+
- Industry-neutral: not tied to specific verticals; covers common actions across most customer service scenarios
|
|
5
|
+
(check document status / check business info / make appointment / submit feedback).
|
|
6
|
+
- Works out of the box: each tool has a directly runnable alpha-track mock implementation;
|
|
7
|
+
users on Path A or local demos can see the capability in effect immediately, even without a real backend API.
|
|
8
|
+
- Smoothly replaceable: each tool also declares a beta-track (remote HTTPS) placeholder in data/tools.yaml;
|
|
9
|
+
connecting to a real system only requires pointing the beta endpoint to your own API (or adapting per INTERFACE_ADAPT.md).
|
|
10
|
+
|
|
11
|
+
Return value must be JSON-serializable; mock data uniformly carries "_mock": true marker,
|
|
12
|
+
making it easy for frontend / logs to distinguish "demo data" from "real business data".
|
|
13
|
+
"""
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import hashlib
|
|
17
|
+
import time
|
|
18
|
+
from typing import Any, Dict
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _stable_pick(seed: str, choices):
|
|
22
|
+
"""Stably select a value based on seed (same input always returns the same result, making demos reproducible)."""
|
|
23
|
+
h = int(hashlib.md5(seed.encode("utf-8")).hexdigest(), 16)
|
|
24
|
+
return choices[h % len(choices)]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def query_order_status(order_id: str = "", **_: Any) -> Dict[str, Any]:
|
|
28
|
+
"""Query document / order / ticket status (generic customer service action).
|
|
29
|
+
|
|
30
|
+
Parameters:
|
|
31
|
+
order_id: Document number (order number / ticket number / appointment number fine).
|
|
32
|
+
"""
|
|
33
|
+
if not order_id:
|
|
34
|
+
return {"_mock": True, "error": "order_id is required"}
|
|
35
|
+
status = _stable_pick(order_id, ["processing", "confirmed", "in_progress", "completed", "cancelled"])
|
|
36
|
+
return {
|
|
37
|
+
"_mock": True,
|
|
38
|
+
"order_id": order_id,
|
|
39
|
+
"status": status,
|
|
40
|
+
"updated_at": int(time.time()),
|
|
41
|
+
"note": "Demo data from built-in mock tool; point the β endpoint to your real system to use live data.",
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def get_business_info(topic: str = "hours", **_: Any) -> Dict[str, Any]:
|
|
46
|
+
"""Query business info (hours / address / contact etc.), common high-frequency customer service question.
|
|
47
|
+
|
|
48
|
+
Parameters:
|
|
49
|
+
topic: hours | address | contact | all
|
|
50
|
+
"""
|
|
51
|
+
info = {
|
|
52
|
+
"hours": "Mon-Sun 10:00-22:00 (last entry 21:00)",
|
|
53
|
+
"address": "No.1 Demo Street, Example District",
|
|
54
|
+
"contact": "+86-000-0000-0000 / support@example.com",
|
|
55
|
+
}
|
|
56
|
+
topic = (topic or "hours").lower()
|
|
57
|
+
data = info if topic == "all" else {topic: info.get(topic, info["hours"])}
|
|
58
|
+
return {"_mock": True, "topic": topic, **data,
|
|
59
|
+
"note": "Demo data from built-in mock tool; replace with your real business profile."}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def book_appointment(date: str = "", time_slot: str = "", party_size: int = 2, **_: Any) -> Dict[str, Any]:
|
|
63
|
+
"""Create reservation / booking (restaurant reservation, service appointment, callback booking etc. generic actions).
|
|
64
|
+
|
|
65
|
+
Parameters:
|
|
66
|
+
date: Date, e.g. 2026-06-12
|
|
67
|
+
time_slot: Time slot, e.g. 18:30
|
|
68
|
+
party_size: Party size / quantity
|
|
69
|
+
"""
|
|
70
|
+
if not date or not time_slot:
|
|
71
|
+
return {"_mock": True, "error": "date and time_slot are required"}
|
|
72
|
+
confirm = "BK" + hashlib.md5(f"{date}{time_slot}{party_size}".encode()).hexdigest()[:8].upper()
|
|
73
|
+
return {
|
|
74
|
+
"_mock": True,
|
|
75
|
+
"confirmation_id": confirm,
|
|
76
|
+
"date": date,
|
|
77
|
+
"time_slot": time_slot,
|
|
78
|
+
"party_size": int(party_size) if str(party_size).isdigit() else party_size,
|
|
79
|
+
"status": "confirmed",
|
|
80
|
+
"note": "Demo booking created by built-in mock tool; wire the β endpoint to your reservation system.",
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def submit_feedback(rating: int = 5, comment: str = "", **_: Any) -> Dict[str, Any]:
|
|
85
|
+
"""Submit satisfaction / feedback (common end-of-session action).
|
|
86
|
+
|
|
87
|
+
Parameters:
|
|
88
|
+
rating: 1-5 rating
|
|
89
|
+
comment: Text feedback (optional)
|
|
90
|
+
"""
|
|
91
|
+
try:
|
|
92
|
+
rating = max(1, min(5, int(rating)))
|
|
93
|
+
except (TypeError, ValueError):
|
|
94
|
+
rating = 5
|
|
95
|
+
return {
|
|
96
|
+
"_mock": True,
|
|
97
|
+
"received": True,
|
|
98
|
+
"rating": rating,
|
|
99
|
+
"comment": (comment or "")[:512],
|
|
100
|
+
"note": "Demo acknowledgement from built-in mock tool.",
|
|
101
|
+
}
|