@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,146 @@
|
|
|
1
|
+
# tool-calling capability self-describing manifest
|
|
2
|
+
# Type: capability (optional install)
|
|
3
|
+
# Risk mitigation: P1 alpha/beta dual-track priority arbitration (manifest explicitly declares priority)
|
|
4
|
+
|
|
5
|
+
name: "tool-calling"
|
|
6
|
+
version: "1.0.0"
|
|
7
|
+
type: "capability"
|
|
8
|
+
description: "Business tool calling - alpha/beta dual-track (local function first, remote API as fallback) + result re-injection"
|
|
9
|
+
|
|
10
|
+
dependencies:
|
|
11
|
+
- name: "conversation-core"
|
|
12
|
+
version: ">=1.0.0,<2.0.0"
|
|
13
|
+
|
|
14
|
+
# ---------------------------------------------------------------------------
|
|
15
|
+
# Injection extensions into skeleton
|
|
16
|
+
# ---------------------------------------------------------------------------
|
|
17
|
+
extensions:
|
|
18
|
+
- inject_at: "agent.before_push_text"
|
|
19
|
+
inline_code: |
|
|
20
|
+
# [tool-calling] intercept text injection: recognize "/tool name args" to trigger local tool call
|
|
21
|
+
from ._capability_loader import try_load_capability
|
|
22
|
+
_tc_dispatcher = try_load_capability("tool-calling", "src/dispatcher.py")
|
|
23
|
+
if _tc_dispatcher is not None:
|
|
24
|
+
_hijack = _tc_dispatcher.maybe_dispatch(text)
|
|
25
|
+
if _hijack is not None:
|
|
26
|
+
# Replace original text with tool result, ensuring LLM receives tool-augmented content
|
|
27
|
+
text = _hijack
|
|
28
|
+
- inject_at: "server.router_extension"
|
|
29
|
+
inline_code: |
|
|
30
|
+
# [tool-calling] mount sub-router
|
|
31
|
+
from ._capability_loader import try_load_capability as _try_load_capability
|
|
32
|
+
_tc_router_mod = _try_load_capability("tool-calling", "src/router.py")
|
|
33
|
+
if _tc_router_mod is not None and hasattr(_tc_router_mod, "router"):
|
|
34
|
+
app.include_router(
|
|
35
|
+
_tc_router_mod.router, prefix="/api/v1/tools", tags=["tool-calling"]
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
# ---------------------------------------------------------------------------
|
|
39
|
+
# Configuration interface (alpha/beta dual-track)
|
|
40
|
+
# ---------------------------------------------------------------------------
|
|
41
|
+
config:
|
|
42
|
+
priority:
|
|
43
|
+
description: "Priority arbitration rule: alpha | beta | manifest_order"
|
|
44
|
+
default: "alpha"
|
|
45
|
+
timeout_ms_alpha:
|
|
46
|
+
default: 1000
|
|
47
|
+
timeout_ms_beta:
|
|
48
|
+
default: 5000
|
|
49
|
+
retry_alpha:
|
|
50
|
+
default: 0
|
|
51
|
+
retry_beta:
|
|
52
|
+
default: 1
|
|
53
|
+
registry_file:
|
|
54
|
+
description: "Tool registration declaration file (YAML), supports hot-reload"
|
|
55
|
+
default: "capabilities/tool-calling/data/tools.yaml"
|
|
56
|
+
|
|
57
|
+
# ---------------------------------------------------------------------------
|
|
58
|
+
# API endpoints
|
|
59
|
+
# ---------------------------------------------------------------------------
|
|
60
|
+
endpoints:
|
|
61
|
+
- method: GET
|
|
62
|
+
path: /api/v1/tools/list
|
|
63
|
+
description: List registered alpha/beta tools and their priority
|
|
64
|
+
- method: POST
|
|
65
|
+
path: /api/v1/tools/invoke
|
|
66
|
+
description: "Explicit tool invocation (body shape: {name, params, priority?})"
|
|
67
|
+
- method: POST
|
|
68
|
+
path: /api/v1/tools/reload
|
|
69
|
+
description: "Hot-reload registry"
|
|
70
|
+
|
|
71
|
+
# ---------------------------------------------------------------------------
|
|
72
|
+
# Integration rules
|
|
73
|
+
# ---------------------------------------------------------------------------
|
|
74
|
+
integration:
|
|
75
|
+
mode: "auto"
|
|
76
|
+
auto_adapters:
|
|
77
|
+
- tech_stack: ["express", "koa", "fastify", "next"]
|
|
78
|
+
adapter: "node-backend"
|
|
79
|
+
description: "Register beta-track remote tool implementation in Node.js backend"
|
|
80
|
+
- tech_stack: ["flask", "fastapi", "django"]
|
|
81
|
+
adapter: "python-backend"
|
|
82
|
+
description: "Directly register alpha-track local function in Python backend"
|
|
83
|
+
- tech_stack: ["spring-boot", "quarkus"]
|
|
84
|
+
adapter: "java-backend"
|
|
85
|
+
description: "Expose beta-track REST endpoints via Filter"
|
|
86
|
+
fallback:
|
|
87
|
+
guided_templates:
|
|
88
|
+
- "../../auto_adapters/integration_templates/generic-backend.md"
|
|
89
|
+
manual_api:
|
|
90
|
+
rest_endpoint: "/api/v1/tools"
|
|
91
|
+
|
|
92
|
+
security:
|
|
93
|
+
log_redaction:
|
|
94
|
+
enabled: true
|
|
95
|
+
patterns: ["api_key", "token", "credential", "authorization"]
|
|
96
|
+
injection_protection:
|
|
97
|
+
prompt_injection_guard: true # Whitelist validation of tool trigger keywords before entering LLM
|
|
98
|
+
network:
|
|
99
|
+
enforce_https: true # Beta-track remote calls enforce HTTPS
|
|
100
|
+
|
|
101
|
+
# ---------------------------------------------------------------------------
|
|
102
|
+
# Business contract (Phase 3 new; follows references/business-contract-spec.md v1.0 §5)
|
|
103
|
+
# tool-calling uses its own contract section (alpha/beta/arbitration), not the port/adapter template.
|
|
104
|
+
# Source code is not refactored in this phase (compromise strategy); only declares contract for contract-adapt.py consumption.
|
|
105
|
+
# ---------------------------------------------------------------------------
|
|
106
|
+
business_contract:
|
|
107
|
+
customization_sop: "INTERFACE_ADAPT.md"
|
|
108
|
+
|
|
109
|
+
# Alpha track: local function registration specification
|
|
110
|
+
alpha_track:
|
|
111
|
+
interface: "src.dispatcher.LocalToolHandler" # Equivalent abstraction in existing dispatcher
|
|
112
|
+
registration_schema:
|
|
113
|
+
name: string # Tool name (globally unique, snake_case)
|
|
114
|
+
description: string # One-line description for LLM consumption
|
|
115
|
+
parameters: object # JSON Schema describing parameters
|
|
116
|
+
handler: callable # Sync/async Python callable
|
|
117
|
+
invocation_schema:
|
|
118
|
+
input: object # Same schema as parameters
|
|
119
|
+
output: object # User-defined return structure (must be JSON-serializable)
|
|
120
|
+
fail_fast: true # Local exceptions thrown immediately for arbitration decision
|
|
121
|
+
|
|
122
|
+
# Beta track: remote business API integration specification
|
|
123
|
+
beta_track:
|
|
124
|
+
interface: "src.dispatcher.RemoteToolClient" # Remote HTTP/RPC client abstraction
|
|
125
|
+
api_schema:
|
|
126
|
+
method: enum[GET, POST, PUT, DELETE, PATCH]
|
|
127
|
+
path: string
|
|
128
|
+
request_schema: object # JSON Schema
|
|
129
|
+
response_schema: object # JSON Schema
|
|
130
|
+
auth: enum[bearer, api_key, none]
|
|
131
|
+
timeout_ms: 5000
|
|
132
|
+
retry:
|
|
133
|
+
max: 1
|
|
134
|
+
backoff_ms: 200
|
|
135
|
+
|
|
136
|
+
# Arbitration rules
|
|
137
|
+
arbitration:
|
|
138
|
+
default_priority: alpha # alpha | beta | manifest_order
|
|
139
|
+
fallback_on_failure: true
|
|
140
|
+
timeout_ms: 3000 # Single-track call timeout; triggers fallback on expiry
|
|
141
|
+
merge_strategy: first_success # first_success | alpha_then_beta_diff
|
|
142
|
+
|
|
143
|
+
acceptance:
|
|
144
|
+
- "Provide ToolRegistry supporting simultaneous alpha/beta implementation declarations"
|
|
145
|
+
- "Default alpha-first; auto-degraded to beta on alpha failure/unavailability"
|
|
146
|
+
- "REST endpoints available immediately after skeleton startup"
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"""tool-calling capability: alpha/beta dual-track tool calling.
|
|
2
|
+
|
|
3
|
+
Core modules:
|
|
4
|
+
- registry Load tools from YAML registration declarations + Python entry points
|
|
5
|
+
- dispatcher Recognize and trigger calls from conversation text ("/tool name {json}")
|
|
6
|
+
- router REST endpoints
|
|
7
|
+
"""
|
|
8
|
+
__version__ = "1.0.0"
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""Text injection interceptor: recognize "/tool" invocations from the conversation stream.
|
|
2
|
+
|
|
3
|
+
Expected text format:
|
|
4
|
+
/tool <name> {json_params}
|
|
5
|
+
|
|
6
|
+
Example:
|
|
7
|
+
/tool get_order {"order_id": "A1234"}
|
|
8
|
+
|
|
9
|
+
Dispatcher parses and calls ToolRegistry, returning the result as a structured string,
|
|
10
|
+
which is then forwarded to the LLM by conversation-core's injection point.
|
|
11
|
+
"""
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import json
|
|
15
|
+
import re
|
|
16
|
+
from typing import Optional
|
|
17
|
+
|
|
18
|
+
from .registry import get_loader
|
|
19
|
+
|
|
20
|
+
_TOOL_RE = re.compile(r"^\s*/tool\s+([A-Za-z0-9_\-]{1,64})\s*(\{.*\})?\s*$", re.DOTALL)
|
|
21
|
+
_MAX_TEXT_LEN = 4096
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def maybe_dispatch(text: str) -> Optional[str]:
|
|
25
|
+
"""Recognize "/tool" trigger, return new text with tool result; return None when not triggered."""
|
|
26
|
+
if not text or len(text) > _MAX_TEXT_LEN:
|
|
27
|
+
return None
|
|
28
|
+
m = _TOOL_RE.match(text)
|
|
29
|
+
if not m:
|
|
30
|
+
return None
|
|
31
|
+
name = m.group(1)
|
|
32
|
+
raw_params = m.group(2) or "{}"
|
|
33
|
+
try:
|
|
34
|
+
params = json.loads(raw_params)
|
|
35
|
+
if not isinstance(params, dict):
|
|
36
|
+
params = {}
|
|
37
|
+
except json.JSONDecodeError:
|
|
38
|
+
params = {}
|
|
39
|
+
result = get_loader().call(name, params)
|
|
40
|
+
payload = {
|
|
41
|
+
"tool": result.tool,
|
|
42
|
+
"track": result.track,
|
|
43
|
+
"ok": result.ok,
|
|
44
|
+
"output": result.output,
|
|
45
|
+
"error": result.error,
|
|
46
|
+
"latency_ms": result.latency_ms,
|
|
47
|
+
"fallback_chain": result.fallback_chain,
|
|
48
|
+
}
|
|
49
|
+
# Return in convention block, making it easy for LLM system prompt to recognize tool results
|
|
50
|
+
return (
|
|
51
|
+
f"[tool_result name={result.tool} track={result.track} ok={result.ok}]\n"
|
|
52
|
+
+ json.dumps(payload, ensure_ascii=False)
|
|
53
|
+
+ "\n[/tool_result]"
|
|
54
|
+
)
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
"""ToolRegistry loader.
|
|
2
|
+
|
|
3
|
+
YAML declaration example:
|
|
4
|
+
priority: alpha # alpha | beta | manifest_order
|
|
5
|
+
tools:
|
|
6
|
+
- name: get_order
|
|
7
|
+
alpha:
|
|
8
|
+
module: "capabilities.tool_calling.examples.local_tools"
|
|
9
|
+
function: "get_order"
|
|
10
|
+
timeout_ms: 800
|
|
11
|
+
beta:
|
|
12
|
+
endpoint: "https://internal.example.com/api/orders"
|
|
13
|
+
method: "POST"
|
|
14
|
+
timeout_ms: 5000
|
|
15
|
+
description: "Query order"
|
|
16
|
+
|
|
17
|
+
Loading strategy:
|
|
18
|
+
- Alpha-track functions loaded dynamically via ``importlib``; when a module is missing, the tool retains only the beta track.
|
|
19
|
+
- Beta track is declaration-only; invocation is done by dispatcher injecting ``beta_invoker``.
|
|
20
|
+
"""
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
import importlib
|
|
24
|
+
import logging
|
|
25
|
+
import os
|
|
26
|
+
import threading
|
|
27
|
+
from pathlib import Path
|
|
28
|
+
from typing import Any, Dict, List, Optional
|
|
29
|
+
|
|
30
|
+
import yaml
|
|
31
|
+
|
|
32
|
+
# Import arbitrator via relative path (Phase 2 shared infrastructure)
|
|
33
|
+
import sys
|
|
34
|
+
_PROJECT_ROOT = Path(__file__).resolve().parents[3]
|
|
35
|
+
if str(_PROJECT_ROOT) not in sys.path:
|
|
36
|
+
sys.path.insert(0, str(_PROJECT_ROOT))
|
|
37
|
+
from scripts.lib.arbitrator import ( # noqa: E402
|
|
38
|
+
AlphaTool,
|
|
39
|
+
BetaTool,
|
|
40
|
+
ToolCallResult,
|
|
41
|
+
ToolRegistry,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
logger = logging.getLogger(__name__)
|
|
45
|
+
|
|
46
|
+
_DEFAULT_REGISTRY_FILE = Path(
|
|
47
|
+
os.getenv(
|
|
48
|
+
"TC_REGISTRY_FILE",
|
|
49
|
+
str(Path(__file__).resolve().parent.parent / "data" / "tools.yaml"),
|
|
50
|
+
)
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class ToolRegistryLoader:
|
|
55
|
+
def __init__(self, registry_file: Optional[Path] = None) -> None:
|
|
56
|
+
self._lock = threading.RLock()
|
|
57
|
+
self._registry_file = Path(registry_file) if registry_file else _DEFAULT_REGISTRY_FILE
|
|
58
|
+
self._registry: ToolRegistry = ToolRegistry()
|
|
59
|
+
self._descriptions: Dict[str, str] = {}
|
|
60
|
+
if self._registry_file.exists():
|
|
61
|
+
self.reload()
|
|
62
|
+
|
|
63
|
+
@property
|
|
64
|
+
def registry(self) -> ToolRegistry:
|
|
65
|
+
with self._lock:
|
|
66
|
+
return self._registry
|
|
67
|
+
|
|
68
|
+
def reload(self) -> int:
|
|
69
|
+
if not self._registry_file.exists():
|
|
70
|
+
return 0
|
|
71
|
+
raw = yaml.safe_load(self._registry_file.read_text(encoding="utf-8")) or {}
|
|
72
|
+
priority = (raw.get("priority") or "alpha").strip()
|
|
73
|
+
new_reg = ToolRegistry(default_priority=priority)
|
|
74
|
+
descriptions: Dict[str, str] = {}
|
|
75
|
+
for tool_def in raw.get("tools") or []:
|
|
76
|
+
name = str(tool_def.get("name") or "").strip()
|
|
77
|
+
if not name:
|
|
78
|
+
continue
|
|
79
|
+
descriptions[name] = str(tool_def.get("description", ""))
|
|
80
|
+
alpha_def = tool_def.get("alpha")
|
|
81
|
+
beta_def = tool_def.get("beta")
|
|
82
|
+
if alpha_def:
|
|
83
|
+
func = self._load_callable(alpha_def)
|
|
84
|
+
if func is not None:
|
|
85
|
+
new_reg.register_alpha(
|
|
86
|
+
AlphaTool(
|
|
87
|
+
name=name,
|
|
88
|
+
func=func,
|
|
89
|
+
timeout_ms=int(alpha_def.get("timeout_ms", 1000)),
|
|
90
|
+
description=descriptions[name],
|
|
91
|
+
)
|
|
92
|
+
)
|
|
93
|
+
if beta_def and beta_def.get("endpoint"):
|
|
94
|
+
new_reg.register_beta(
|
|
95
|
+
BetaTool(
|
|
96
|
+
name=name,
|
|
97
|
+
endpoint=str(beta_def["endpoint"]),
|
|
98
|
+
method=str(beta_def.get("method", "POST")),
|
|
99
|
+
timeout_ms=int(beta_def.get("timeout_ms", 5000)),
|
|
100
|
+
headers=dict(beta_def.get("headers") or {}),
|
|
101
|
+
description=descriptions[name],
|
|
102
|
+
)
|
|
103
|
+
)
|
|
104
|
+
with self._lock:
|
|
105
|
+
self._registry = new_reg
|
|
106
|
+
self._descriptions = descriptions
|
|
107
|
+
return len(descriptions)
|
|
108
|
+
|
|
109
|
+
def list_tools(self) -> List[Dict[str, Any]]:
|
|
110
|
+
with self._lock:
|
|
111
|
+
return self._registry.list_tools()
|
|
112
|
+
|
|
113
|
+
def call(
|
|
114
|
+
self,
|
|
115
|
+
name: str,
|
|
116
|
+
params: Optional[Dict[str, Any]] = None,
|
|
117
|
+
*,
|
|
118
|
+
priority: Optional[str] = None,
|
|
119
|
+
) -> ToolCallResult:
|
|
120
|
+
return self._registry.call(
|
|
121
|
+
name,
|
|
122
|
+
params,
|
|
123
|
+
priority=priority,
|
|
124
|
+
beta_invoker=_default_beta_invoker,
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
@staticmethod
|
|
128
|
+
def _load_callable(alpha_def: Dict[str, Any]):
|
|
129
|
+
mod_name = alpha_def.get("module")
|
|
130
|
+
func_name = alpha_def.get("function")
|
|
131
|
+
if not mod_name or not func_name:
|
|
132
|
+
return None
|
|
133
|
+
module = None
|
|
134
|
+
try:
|
|
135
|
+
module = importlib.import_module(mod_name)
|
|
136
|
+
except ImportError:
|
|
137
|
+
# Fallback: capability directory name has hyphens (tool-calling), standard import cannot resolve it
|
|
138
|
+
# capabilities.tool_calling.* - switched to file-path-based loading (registry knows its own location).
|
|
139
|
+
module = ToolRegistryLoader._load_module_by_path(mod_name)
|
|
140
|
+
if module is None:
|
|
141
|
+
logger.warning("alpha tool module not loadable: %s", mod_name)
|
|
142
|
+
return None
|
|
143
|
+
return getattr(module, func_name, None)
|
|
144
|
+
|
|
145
|
+
@staticmethod
|
|
146
|
+
def _load_module_by_path(mod_name: str):
|
|
147
|
+
"""Map dotted module name to file path within capability package and load.
|
|
148
|
+
|
|
149
|
+
Convention: module name like ``capabilities.tool_calling.examples.local_tools``,
|
|
150
|
+
take the ``examples`` segment and everything after as the path relative to ``<capability_root>``.
|
|
151
|
+
"""
|
|
152
|
+
import importlib.util
|
|
153
|
+
|
|
154
|
+
cap_root = Path(__file__).resolve().parent.parent # capabilities/tool-calling/
|
|
155
|
+
parts = mod_name.split(".")
|
|
156
|
+
# Strip capabilities.<cap> prefix (regardless of underscores / hyphens), keep the examples/... tail
|
|
157
|
+
tail: List[str] = []
|
|
158
|
+
seen_examples = False
|
|
159
|
+
for p in parts:
|
|
160
|
+
if p == "examples":
|
|
161
|
+
seen_examples = True
|
|
162
|
+
if seen_examples:
|
|
163
|
+
tail.append(p)
|
|
164
|
+
if not tail:
|
|
165
|
+
tail = parts[-2:] # Fallback: take last two segments
|
|
166
|
+
file_path = cap_root.joinpath(*tail).with_suffix(".py")
|
|
167
|
+
if not file_path.is_file():
|
|
168
|
+
return None
|
|
169
|
+
qual = "_tc_local_" + "_".join(tail)
|
|
170
|
+
cached = sys.modules.get(qual)
|
|
171
|
+
if cached is not None:
|
|
172
|
+
return cached
|
|
173
|
+
spec = importlib.util.spec_from_file_location(qual, file_path)
|
|
174
|
+
if spec is None or spec.loader is None:
|
|
175
|
+
return None
|
|
176
|
+
module = importlib.util.module_from_spec(spec)
|
|
177
|
+
sys.modules[qual] = module
|
|
178
|
+
try:
|
|
179
|
+
spec.loader.exec_module(module)
|
|
180
|
+
except Exception as exc: # noqa: BLE001
|
|
181
|
+
sys.modules.pop(qual, None)
|
|
182
|
+
logger.warning("alpha tool file load failed %s: %s", file_path, exc)
|
|
183
|
+
return None
|
|
184
|
+
return module
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
# ---------------------------------------------------------------------------
|
|
188
|
+
# Beta-track default implementation: requests sync POST / GET
|
|
189
|
+
# ---------------------------------------------------------------------------
|
|
190
|
+
def _default_beta_invoker(tool: BetaTool, params: Dict[str, Any]) -> Any:
|
|
191
|
+
import requests # Already in skeleton requirements
|
|
192
|
+
|
|
193
|
+
if not tool.endpoint.startswith("https://") and not tool.endpoint.startswith("http://localhost"):
|
|
194
|
+
# Security: except localhost debugging, beta-track enforces HTTPS (manifest.security.network.enforce_https)
|
|
195
|
+
raise RuntimeError(f"β endpoint must use HTTPS: {tool.endpoint}")
|
|
196
|
+
headers = {"Content-Type": "application/json", **tool.headers}
|
|
197
|
+
timeout = max(tool.timeout_ms, 100) / 1000.0
|
|
198
|
+
method = tool.method.upper()
|
|
199
|
+
if method == "GET":
|
|
200
|
+
resp = requests.get(tool.endpoint, params=params, headers=headers, timeout=timeout)
|
|
201
|
+
else:
|
|
202
|
+
resp = requests.request(
|
|
203
|
+
method, tool.endpoint, json=params, headers=headers, timeout=timeout
|
|
204
|
+
)
|
|
205
|
+
resp.raise_for_status()
|
|
206
|
+
ctype = resp.headers.get("Content-Type", "")
|
|
207
|
+
if "application/json" in ctype:
|
|
208
|
+
return resp.json()
|
|
209
|
+
return resp.text
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
# ---------------------------------------------------------------------------
|
|
213
|
+
# Global singleton (used by dispatcher / router)
|
|
214
|
+
# ---------------------------------------------------------------------------
|
|
215
|
+
_global_loader = ToolRegistryLoader()
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def get_loader() -> ToolRegistryLoader:
|
|
219
|
+
return _global_loader
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""tool-calling FastAPI sub-router."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from typing import Any, Dict, Optional
|
|
5
|
+
|
|
6
|
+
from fastapi import APIRouter, HTTPException
|
|
7
|
+
from pydantic import BaseModel, Field
|
|
8
|
+
|
|
9
|
+
from .registry import get_loader
|
|
10
|
+
|
|
11
|
+
router = APIRouter()
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class InvokeRequest(BaseModel):
|
|
15
|
+
name: str = Field(..., max_length=64)
|
|
16
|
+
params: Dict[str, Any] = Field(default_factory=dict)
|
|
17
|
+
priority: Optional[str] = Field(default=None, pattern="^(alpha|beta|manifest_order)$")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@router.get("/list")
|
|
21
|
+
def list_tools() -> dict:
|
|
22
|
+
return {"code": 0, "data": get_loader().list_tools()}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@router.post("/invoke")
|
|
26
|
+
def invoke(req: InvokeRequest) -> dict:
|
|
27
|
+
result = get_loader().call(req.name, req.params, priority=req.priority)
|
|
28
|
+
if not result.ok:
|
|
29
|
+
# 200 + ok=false or 502? Here we use 200; caller judges by ok field; beta network errors use 502
|
|
30
|
+
if result.track == "beta" and "Connection" in (result.error or ""):
|
|
31
|
+
raise HTTPException(status_code=502, detail=result.error)
|
|
32
|
+
return {
|
|
33
|
+
"code": 0 if result.ok else 1,
|
|
34
|
+
"msg": "success" if result.ok else result.error,
|
|
35
|
+
"data": {
|
|
36
|
+
"tool": result.tool,
|
|
37
|
+
"track": result.track,
|
|
38
|
+
"ok": result.ok,
|
|
39
|
+
"output": result.output,
|
|
40
|
+
"error": result.error,
|
|
41
|
+
"latency_ms": result.latency_ms,
|
|
42
|
+
"fallback_chain": result.fallback_chain,
|
|
43
|
+
},
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@router.post("/reload")
|
|
48
|
+
def reload_registry() -> dict:
|
|
49
|
+
n = get_loader().reload()
|
|
50
|
+
return {"code": 0, "data": {"count": n}}
|