@tencent-rtc/trtc-agent-skills 0.1.0
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/LICENSE +21 -0
- package/README.md +172 -0
- package/README.zh.md +173 -0
- package/bin/cli.js +434 -0
- package/knowledge-base/index.yaml +454 -0
- package/knowledge-base/platform-slice-template.md +233 -0
- package/knowledge-base/scenario-spec.md +350 -0
- package/knowledge-base/scenarios/conference/base/general-conference.md +365 -0
- package/knowledge-base/scenarios/conference/base/webinar-conference.md +130 -0
- package/knowledge-base/scenarios/conference/medical/1v1-video-consultation.md +145 -0
- package/knowledge-base/scenarios/conference/medical/medical-multidoctor-consultation.md +113 -0
- package/knowledge-base/scenarios/live/entertainment-live-room.md +118 -0
- package/knowledge-base/slice-spec.md +546 -0
- package/knowledge-base/slices/conference/web/ai-tools.md +225 -0
- package/knowledge-base/slices/conference/web/beauty-effects.md +188 -0
- package/knowledge-base/slices/conference/web/device-control.md +338 -0
- package/knowledge-base/slices/conference/web/login-auth.md +261 -0
- package/knowledge-base/slices/conference/web/network-quality.md +190 -0
- package/knowledge-base/slices/conference/web/official-roomkit-api.md +298 -0
- package/knowledge-base/slices/conference/web/official-roomkit-login-ui.md +246 -0
- package/knowledge-base/slices/conference/web/participant-list.md +238 -0
- package/knowledge-base/slices/conference/web/participant-management.md +718 -0
- package/knowledge-base/slices/conference/web/prejoin-check.md +293 -0
- package/knowledge-base/slices/conference/web/room-call.md +213 -0
- package/knowledge-base/slices/conference/web/room-chat.md +426 -0
- package/knowledge-base/slices/conference/web/room-lifecycle.md +534 -0
- package/knowledge-base/slices/conference/web/room-schedule.md +281 -0
- package/knowledge-base/slices/conference/web/screen-share.md +211 -0
- package/knowledge-base/slices/conference/web/video-layout.md +675 -0
- package/knowledge-base/slices/conference/web/virtual-background.md +197 -0
- package/knowledge-base/slices/conference/web/webinar-interaction.md +206 -0
- package/knowledge-base/slices/live/anchor-lifecycle.md +122 -0
- package/knowledge-base/slices/live/anchor-preview.md +90 -0
- package/knowledge-base/slices/live/anchor-room-config.md +104 -0
- package/knowledge-base/slices/live/audience-list.md +86 -0
- package/knowledge-base/slices/live/audience-manage.md +92 -0
- package/knowledge-base/slices/live/audience-watch.md +85 -0
- package/knowledge-base/slices/live/audio.md +116 -0
- package/knowledge-base/slices/live/barrage.md +88 -0
- package/knowledge-base/slices/live/beauty.md +99 -0
- package/knowledge-base/slices/live/coguest-apply.md +105 -0
- package/knowledge-base/slices/live/device-control.md +91 -0
- package/knowledge-base/slices/live/error-codes.md +167 -0
- package/knowledge-base/slices/live/gift.md +84 -0
- package/knowledge-base/slices/live/ios/.gitkeep +0 -0
- package/knowledge-base/slices/live/ios/anchor-lifecycle.md +313 -0
- package/knowledge-base/slices/live/ios/anchor-preview.md +228 -0
- package/knowledge-base/slices/live/ios/anchor-room-config.md +257 -0
- package/knowledge-base/slices/live/ios/audience-list.md +353 -0
- package/knowledge-base/slices/live/ios/audience-manage.md +381 -0
- package/knowledge-base/slices/live/ios/audience-watch.md +286 -0
- package/knowledge-base/slices/live/ios/audio.md +373 -0
- package/knowledge-base/slices/live/ios/barrage.md +285 -0
- package/knowledge-base/slices/live/ios/beauty.md +323 -0
- package/knowledge-base/slices/live/ios/coguest-apply.md +506 -0
- package/knowledge-base/slices/live/ios/device-control.md +286 -0
- package/knowledge-base/slices/live/ios/error-codes.md +270 -0
- package/knowledge-base/slices/live/ios/gift.md +315 -0
- package/knowledge-base/slices/live/ios/live-list.md +269 -0
- package/knowledge-base/slices/live/ios/login-auth.md +247 -0
- package/knowledge-base/slices/live/live-list.md +82 -0
- package/knowledge-base/slices/live/login-auth.md +78 -0
- package/package.json +34 -0
- package/skills/trtc/SKILL.md +326 -0
- package/skills/trtc/room-builder/SKILL.md +138 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/README.md +108 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/docs/backend-contract.zh-CN.md +162 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/docs/integration.zh-CN.md +154 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/docs/theme.zh-CN.md +78 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/index.html +12 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/package.json +28 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/postcss.config.js +5 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/App.vue +25 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/ConsultationManagePanel.vue +838 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/LanguageSwitch.vue +102 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/LoadingSpinner.vue +6 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/MedicalAlert.vue +34 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/MedicalBusinessPanel.vue +148 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/MedicalButton.vue +49 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/MedicalConfirmDialog.vue +68 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/MedicalDataPanel.vue +196 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/MedicalRecordPanel.vue +270 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/PrescriptionPanel.vue +363 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/config/basic-info-config.ts +29 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/config/lib-generate-test-usersig-es.min.d.ts +4 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/config/lib-generate-test-usersig-es.min.js +2 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/config/runtime-config.ts +12 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/env.d.ts +32 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/components/ConsultationChatPanel.vue +123 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/components/ConsultationMembersPanel.vue +230 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/components/ConsultationTranscriptionPanel.vue +135 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/components/ConsultationVideoStage.vue +113 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/components/InviteDoctorDialog.vue +132 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/components/KickMemberConfirmDialog.vue +50 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/types.ts +77 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/useConsultationChat.ts +97 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/useConsultationDevices.ts +48 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/useConsultationParticipants.ts +121 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/useConsultationPermissions.ts +25 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/utils.ts +70 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/i18n/en-US/index.ts +553 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/i18n/index.ts +25 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/i18n/medicalTranslate.ts +85 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/i18n/state.ts +49 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/i18n/zh-CN/index.ts +463 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/main.ts +12 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/mock/appointments.ts +96 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/mock/users.ts +79 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/router/index.ts +63 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/index.ts +25 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/integration/appointmentService.ts +77 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/integration/authService.ts +38 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/integration/launchContext.ts +31 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/integration/userService.ts +35 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/mock/appointmentService.ts +43 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/mock/authService.ts +33 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/mock/userService.ts +43 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/types.ts +135 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/shared/icons.ts +53 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/styles/index.css +106 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/styles/tailwind.css +3 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/styles/theme.css +209 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/utils/auth.ts +50 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/utils/format.ts +24 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/utils/navigation.ts +12 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/utils/session.ts +28 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/views/DoctorConsultationView.vue +777 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/views/DoctorDashboardView.vue +678 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/views/LoginView.vue +441 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/views/PatientConsultationFinishedView.vue +185 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/views/PatientConsultationView.vue +1003 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/views/PatientSelectDoctorView.vue +317 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/views/PatientWaitingView.vue +454 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/tsconfig.json +21 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/tsconfig.node.json +8 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/vite.config.ts +17 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation//346/216/245/345/205/245/350/257/264/346/230/216.md +6 -0
- package/skills/trtc/room-builder/tools/render_ai_instructions.py +226 -0
- package/skills/trtc-apply/SKILL.md +97 -0
- package/skills/trtc-apply/guardrails/apply_lib/__init__.py +0 -0
- package/skills/trtc-apply/guardrails/apply_lib/__pycache__/__init__.cpython-313.pyc +0 -0
- package/skills/trtc-apply/guardrails/apply_lib/__pycache__/rule_parser.cpython-313.pyc +0 -0
- package/skills/trtc-apply/guardrails/apply_lib/rule_parser.py +268 -0
- package/skills/trtc-docs/SKILL.md +207 -0
- package/skills/trtc-onboarding/SKILL.md +839 -0
- package/skills/trtc-onboarding/reference/path-a1-demo.md +103 -0
- package/skills/trtc-onboarding/reference/path-a2-integrate.md +693 -0
- package/skills/trtc-onboarding/reference/path-b-troubleshoot.md +115 -0
- package/skills/trtc-onboarding/reference/path-c-expand.md +43 -0
- package/skills/trtc-onboarding/reference/reporting-protocol.md +174 -0
- package/skills/trtc-onboarding/reference/supported-matrix.md +100 -0
- package/skills/trtc-onboarding/reference/usersig-handling.md +140 -0
- package/skills/trtc-search/SKILL.md +221 -0
- package/skills/trtc-topic/SKILL.md +638 -0
- package/skills/trtc-topic/guardrails/__pycache__/gate_slice_read.cpython-313.pyc +0 -0
- package/skills/trtc-topic/guardrails/__pycache__/gate_slice_write.cpython-313.pyc +0 -0
- package/skills/trtc-topic/guardrails/__pycache__/stop_require_apply_evidence.cpython-313.pyc +0 -0
- package/skills/trtc-topic/guardrails/gate_slice_read.py +133 -0
- package/skills/trtc-topic/guardrails/gate_slice_write.py +169 -0
- package/skills/trtc-topic/guardrails/stop_require_apply_evidence.py +97 -0
- package/skills/trtc-topic/references/execution-units.yaml +58 -0
- package/skills/trtc-topic/runtime/README.md +50 -0
- package/skills/trtc-topic/runtime/RUNTIME.md +128 -0
- package/skills/trtc-topic/runtime/lib/__init__.py +0 -0
- package/skills/trtc-topic/runtime/lib/platforms.py +194 -0
- package/skills/trtc-topic/runtime/package-lock.json +1211 -0
- package/skills/trtc-topic/runtime/package.json +13 -0
- package/skills/trtc-topic/runtime/telemetry-bridge.mjs +339 -0
- package/skills/trtc-topic/runtime/telemetry_collector.py +293 -0
- package/skills/trtc-topic/scripts/STATE-MACHINE-GUIDE.md +186 -0
- package/skills/trtc-topic/scripts/__pycache__/apply.cpython-313.pyc +0 -0
- package/skills/trtc-topic/scripts/apply.py +581 -0
- package/skills/trtc-topic/scripts/finalize_session.py +113 -0
- package/skills/trtc-topic/scripts/init_slice_queue.py +96 -0
- package/skills/trtc-topic/scripts/lib/__pycache__/state_machine.cpython-313.pyc +0 -0
- package/skills/trtc-topic/scripts/lib/state_machine.py +328 -0
- package/skills/trtc-topic/scripts/next_slice.py +137 -0
- package/skills/trtc-topic/tests/README.md +70 -0
- package/skills/trtc-topic/tests/__pycache__/conftest.cpython-313-pytest-9.0.2.pyc +0 -0
- package/skills/trtc-topic/tests/__pycache__/conftest.cpython-313-pytest-9.0.3.pyc +0 -0
- package/skills/trtc-topic/tests/__pycache__/test_apply_cli.cpython-313-pytest-9.0.2.pyc +0 -0
- package/skills/trtc-topic/tests/__pycache__/test_apply_cli.cpython-313-pytest-9.0.3.pyc +0 -0
- package/skills/trtc-topic/tests/__pycache__/test_end_to_end.cpython-313-pytest-9.0.2.pyc +0 -0
- package/skills/trtc-topic/tests/__pycache__/test_end_to_end.cpython-313-pytest-9.0.3.pyc +0 -0
- package/skills/trtc-topic/tests/__pycache__/test_finalize_session.cpython-313-pytest-9.0.2.pyc +0 -0
- package/skills/trtc-topic/tests/__pycache__/test_finalize_session.cpython-313-pytest-9.0.3.pyc +0 -0
- package/skills/trtc-topic/tests/__pycache__/test_gates.cpython-313-pytest-9.0.2.pyc +0 -0
- package/skills/trtc-topic/tests/__pycache__/test_gates.cpython-313-pytest-9.0.3.pyc +0 -0
- package/skills/trtc-topic/tests/__pycache__/test_session_resolver.cpython-313-pytest-9.0.2.pyc +0 -0
- package/skills/trtc-topic/tests/__pycache__/test_session_resolver.cpython-313-pytest-9.0.3.pyc +0 -0
- package/skills/trtc-topic/tests/__pycache__/test_state_machine.cpython-313-pytest-9.0.2.pyc +0 -0
- package/skills/trtc-topic/tests/__pycache__/test_state_machine.cpython-313-pytest-9.0.3.pyc +0 -0
- package/skills/trtc-topic/tests/__pycache__/test_stop_require_apply.cpython-313-pytest-9.0.2.pyc +0 -0
- package/skills/trtc-topic/tests/__pycache__/test_stop_require_apply.cpython-313-pytest-9.0.3.pyc +0 -0
- package/skills/trtc-topic/tests/__pycache__/test_topic_skill_invariants.cpython-313-pytest-9.0.2.pyc +0 -0
- package/skills/trtc-topic/tests/__pycache__/test_topic_skill_invariants.cpython-313-pytest-9.0.3.pyc +0 -0
- package/skills/trtc-topic/tests/conftest.py +72 -0
- package/skills/trtc-topic/tests/test_apply_cli.py +480 -0
- package/skills/trtc-topic/tests/test_end_to_end.py +305 -0
- package/skills/trtc-topic/tests/test_finalize_session.py +51 -0
- package/skills/trtc-topic/tests/test_gates.py +316 -0
- package/skills/trtc-topic/tests/test_session_resolver.py +260 -0
- package/skills/trtc-topic/tests/test_state_machine.py +414 -0
- package/skills/trtc-topic/tests/test_stop_require_apply.py +99 -0
- package/skills/trtc-topic/tests/test_topic_skill_invariants.py +130 -0
package/bin/cli.js
ADDED
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @tencent-rtc/trtc-agent-skills installer
|
|
7
|
+
*
|
|
8
|
+
* Installs the TRTC AI Integration skill suite (6 cross-referencing skills:
|
|
9
|
+
* trtc + trtc-onboarding/docs/topic/search/apply) plus the shared
|
|
10
|
+
* knowledge-base into your IDE's skills directory, and wires up the
|
|
11
|
+
* `tencent-rtc-skill-tool` MCP server (used for prompt / runtime telemetry).
|
|
12
|
+
*
|
|
13
|
+
* IMPORTANT — why skills are copied as SIBLING DIRECTORIES:
|
|
14
|
+
* The entry skill `trtc/SKILL.md` routes to the others via relative paths
|
|
15
|
+
* like `../trtc-onboarding/SKILL.md`. They MUST remain siblings under the
|
|
16
|
+
* same skills root, otherwise routing breaks. We therefore copy each
|
|
17
|
+
* skills/<name>/ dir verbatim — we never concatenate them.
|
|
18
|
+
*
|
|
19
|
+
* Usage:
|
|
20
|
+
* npx @tencent-rtc/trtc-agent-skills add
|
|
21
|
+
* npx @tencent-rtc/trtc-agent-skills add --ide cursor
|
|
22
|
+
* npx @tencent-rtc/trtc-agent-skills add --ide all
|
|
23
|
+
* npx @tencent-rtc/trtc-agent-skills add --clean
|
|
24
|
+
* npx @tencent-rtc/trtc-agent-skills add --no-report
|
|
25
|
+
* npx @tencent-rtc/trtc-agent-skills add --list
|
|
26
|
+
* npx @tencent-rtc/trtc-agent-skills add --help
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
const fs = require("fs");
|
|
30
|
+
const os = require("os");
|
|
31
|
+
const path = require("path");
|
|
32
|
+
|
|
33
|
+
// ── tiny color helpers (no deps) ───────────────────────────────────────────────
|
|
34
|
+
const useColor = process.stdout.isTTY && !process.env.NO_COLOR;
|
|
35
|
+
const c = {
|
|
36
|
+
bold: (s) => (useColor ? `\x1b[1m${s}\x1b[0m` : s),
|
|
37
|
+
cyan: (s) => (useColor ? `\x1b[36m${s}\x1b[0m` : s),
|
|
38
|
+
green: (s) => (useColor ? `\x1b[32m${s}\x1b[0m` : s),
|
|
39
|
+
yellow: (s) => (useColor ? `\x1b[33m${s}\x1b[0m` : s),
|
|
40
|
+
red: (s) => (useColor ? `\x1b[31m${s}\x1b[0m` : s),
|
|
41
|
+
gray: (s) => (useColor ? `\x1b[90m${s}\x1b[0m` : s),
|
|
42
|
+
dim: (s) => (useColor ? `\x1b[2m${s}\x1b[0m` : s),
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// ── paths ───────────────────────────────────────────────────────────────────────
|
|
46
|
+
const PKG_ROOT = path.resolve(__dirname, "..");
|
|
47
|
+
const PKG_JSON = require(path.join(PKG_ROOT, "package.json"));
|
|
48
|
+
const PKG_VERSION = PKG_JSON.version || "0.0.0";
|
|
49
|
+
const SKILLS_SRC = path.join(PKG_ROOT, "skills");
|
|
50
|
+
const KB_SRC = path.join(PKG_ROOT, "knowledge-base");
|
|
51
|
+
|
|
52
|
+
// The 6 skills that make up the suite. Order is cosmetic; `trtc` is the entry.
|
|
53
|
+
const SKILL_NAMES = [
|
|
54
|
+
"trtc",
|
|
55
|
+
"trtc-onboarding",
|
|
56
|
+
"trtc-docs",
|
|
57
|
+
"trtc-topic",
|
|
58
|
+
"trtc-search",
|
|
59
|
+
"trtc-apply",
|
|
60
|
+
];
|
|
61
|
+
|
|
62
|
+
// IDE skill-install targets (project-level). Each IDE reads skills from a
|
|
63
|
+
// different directory, but the layout inside is identical: one dir per skill.
|
|
64
|
+
const IDE_TARGETS = {
|
|
65
|
+
claude: { skillsRoot: ".claude/skills", kind: "dir" },
|
|
66
|
+
cursor: { skillsRoot: ".cursor/skills", kind: "dir" },
|
|
67
|
+
codebuddy: { skillsRoot: ".codebuddy/skills", kind: "dir" },
|
|
68
|
+
// Codex reads project-root .agents/skills/. Same dir-per-skill layout works.
|
|
69
|
+
codex: { skillsRoot: ".agents/skills", kind: "dir" },
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
// MCP config locations per IDE.
|
|
73
|
+
// claude: project-level <root>/.mcp.json (JSON)
|
|
74
|
+
// cursor: user-level ~/.cursor/mcp.json (JSON)
|
|
75
|
+
// codebuddy: user-level ~/.codebuddy/mcp.json (JSON)
|
|
76
|
+
// codex: user-level ~/.codex/config.toml (TOML, [mcp_servers.xxx])
|
|
77
|
+
const MCP_TARGETS = {
|
|
78
|
+
claude: { configFile: ".mcp.json", format: "json" },
|
|
79
|
+
cursor: { configFile: path.join(os.homedir(), ".cursor", "mcp.json"), format: "json" },
|
|
80
|
+
codebuddy: { configFile: path.join(os.homedir(), ".codebuddy", "mcp.json"), format: "json" },
|
|
81
|
+
codex: { configFile: path.join(os.homedir(), ".codex", "config.toml"), format: "toml" },
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const MCP_SERVER_NAME = "tencent-rtc-skill-tool";
|
|
85
|
+
const MCP_SERVER_ENTRY = "@tencent-rtc/skill-tool@latest";
|
|
86
|
+
|
|
87
|
+
// Knowledge-base lives next to the skills root (sibling), because skills
|
|
88
|
+
// reference it via ${CLAUDE_PLUGIN_ROOT}/knowledge-base — we mirror that by
|
|
89
|
+
// placing knowledge-base/ as a sibling of the skills dir's parent. To keep it
|
|
90
|
+
// simple and robust across IDEs, we copy KB into <skillsRoot>/../knowledge-base
|
|
91
|
+
// AND keep a project-root copy. See copyKnowledgeBase().
|
|
92
|
+
|
|
93
|
+
// ── fs helpers ──────────────────────────────────────────────────────────────────
|
|
94
|
+
function ensureDir(dir) {
|
|
95
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function copyRecursive(src, dest) {
|
|
99
|
+
const stat = fs.statSync(src);
|
|
100
|
+
if (stat.isDirectory()) {
|
|
101
|
+
ensureDir(dest);
|
|
102
|
+
for (const entry of fs.readdirSync(src)) {
|
|
103
|
+
copyRecursive(path.join(src, entry), path.join(dest, entry));
|
|
104
|
+
}
|
|
105
|
+
} else {
|
|
106
|
+
ensureDir(path.dirname(dest));
|
|
107
|
+
fs.copyFileSync(src, dest);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function rmrf(target) {
|
|
112
|
+
if (fs.existsSync(target) || isSymlink(target)) {
|
|
113
|
+
fs.rmSync(target, { recursive: true, force: true });
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function isSymlink(p) {
|
|
118
|
+
try { return fs.lstatSync(p).isSymbolicLink(); }
|
|
119
|
+
catch { return false; }
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// ── project root resolution ───────────────────────────────────────────────────
|
|
123
|
+
// Walk UP from cwd for strong repo-root signals (P1 monorepo manifest,
|
|
124
|
+
// P2 package.json workspaces, P3 .git). Otherwise P4 cwd-local package.json,
|
|
125
|
+
// else P5 cwd. Same semantics as the reference installer.
|
|
126
|
+
function findProjectRoot(startCwd) {
|
|
127
|
+
const start = path.resolve(startCwd);
|
|
128
|
+
let dir = start;
|
|
129
|
+
while (true) {
|
|
130
|
+
if (
|
|
131
|
+
fs.existsSync(path.join(dir, "pnpm-workspace.yaml")) ||
|
|
132
|
+
fs.existsSync(path.join(dir, "lerna.json")) ||
|
|
133
|
+
fs.existsSync(path.join(dir, "turbo.json"))
|
|
134
|
+
) return dir;
|
|
135
|
+
|
|
136
|
+
const pkgPath = path.join(dir, "package.json");
|
|
137
|
+
if (fs.existsSync(pkgPath)) {
|
|
138
|
+
try {
|
|
139
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
140
|
+
if (pkg && pkg.workspaces) return dir;
|
|
141
|
+
} catch { /* malformed — keep walking */ }
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (fs.existsSync(path.join(dir, ".git"))) return dir;
|
|
145
|
+
|
|
146
|
+
const parent = path.dirname(dir);
|
|
147
|
+
if (parent === dir) break;
|
|
148
|
+
dir = parent;
|
|
149
|
+
}
|
|
150
|
+
if (fs.existsSync(path.join(start, "package.json"))) return start;
|
|
151
|
+
return start;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// ── argv parsing ──────────────────────────────────────────────────────────────
|
|
155
|
+
function getFlag(args, name) {
|
|
156
|
+
const i = args.indexOf(name);
|
|
157
|
+
return i !== -1 ? args[i + 1] : undefined;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// ── help / list ───────────────────────────────────────────────────────────────
|
|
161
|
+
function printHelp() {
|
|
162
|
+
console.log(`
|
|
163
|
+
${c.bold("@tencent-rtc/trtc-agent-skills")} — Install TRTC AI Integration skills + MCP
|
|
164
|
+
|
|
165
|
+
${c.bold("Usage:")}
|
|
166
|
+
${c.cyan("npx @tencent-rtc/trtc-agent-skills add")} Install (default IDE: claude)
|
|
167
|
+
${c.cyan("npx @tencent-rtc/trtc-agent-skills add --ide <name>")} One of: claude / cursor / codebuddy / codex / all
|
|
168
|
+
${c.cyan("npx @tencent-rtc/trtc-agent-skills add --clean")} Wipe existing trtc* skill dirs first
|
|
169
|
+
${c.cyan("npx @tencent-rtc/trtc-agent-skills add --no-report")} Skip anonymous install reporting
|
|
170
|
+
${c.cyan("npx @tencent-rtc/trtc-agent-skills add --list")} List skills shipped in this package
|
|
171
|
+
${c.cyan("npx @tencent-rtc/trtc-agent-skills add --help")} Show this help
|
|
172
|
+
|
|
173
|
+
${c.bold("Installs:")}
|
|
174
|
+
${c.dim("Skills :")} ${c.gray("<projectRoot>/.claude/skills/ (or .cursor/, .codebuddy/, .agents/)")}
|
|
175
|
+
${c.dim("KB :")} ${c.gray("alongside the skills root as knowledge-base/")}
|
|
176
|
+
${c.dim("MCP :")} ${c.gray("tencent-rtc-skill-tool → IDE mcp config (npx @tencent-rtc/skill-tool@latest)")}
|
|
177
|
+
|
|
178
|
+
${c.dim("Skills are copied as sibling dirs so relative routing (../trtc-onboarding) keeps working.")}
|
|
179
|
+
`);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function listSkills() {
|
|
183
|
+
console.log(`\n ${c.bold("Skills shipped in this package:")}\n`);
|
|
184
|
+
console.log(` ${c.cyan("trtc/")} ${c.dim("Entry router — detects product/platform, routes to sub-skills")}`);
|
|
185
|
+
console.log(` ${c.cyan("trtc-onboarding/")} ${c.dim("Get-started / integration / troubleshooting flow")}`);
|
|
186
|
+
console.log(` ${c.cyan("trtc-docs/")} ${c.dim("Docs & error-code lookup")}`);
|
|
187
|
+
console.log(` ${c.cyan("trtc-topic/")} ${c.dim("Step-by-step scenario walkthrough")}`);
|
|
188
|
+
console.log(` ${c.cyan("trtc-search/")} ${c.dim("Internal slice lookup (AI-facing)")}`);
|
|
189
|
+
console.log(` ${c.cyan("trtc-apply/")} ${c.dim("Internal compile/integration quality gate")}`);
|
|
190
|
+
console.log("");
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// ── core: skill install ─────────────────────────────────────────────────────────
|
|
194
|
+
function cleanSkills(skillsRootAbs) {
|
|
195
|
+
if (!fs.existsSync(skillsRootAbs)) return 0;
|
|
196
|
+
let wiped = 0;
|
|
197
|
+
for (const name of SKILL_NAMES) {
|
|
198
|
+
const target = path.join(skillsRootAbs, name);
|
|
199
|
+
if (fs.existsSync(target)) { rmrf(target); wiped++; }
|
|
200
|
+
}
|
|
201
|
+
// also wipe a co-located knowledge-base copy if present
|
|
202
|
+
const kb = path.join(path.dirname(skillsRootAbs), "knowledge-base");
|
|
203
|
+
if (fs.existsSync(kb)) { rmrf(kb); }
|
|
204
|
+
return wiped;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function installSkills(skillsRootAbs) {
|
|
208
|
+
ensureDir(skillsRootAbs);
|
|
209
|
+
for (const name of SKILL_NAMES) {
|
|
210
|
+
const src = path.join(SKILLS_SRC, name);
|
|
211
|
+
if (fs.existsSync(src)) {
|
|
212
|
+
copyRecursive(src, path.join(skillsRootAbs, name));
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Copy knowledge-base so that skills can resolve it. Skills use
|
|
218
|
+
// ${CLAUDE_PLUGIN_ROOT}/knowledge-base; the practical robust choice is to put
|
|
219
|
+
// knowledge-base as a sibling of the skills root (e.g. .claude/knowledge-base),
|
|
220
|
+
// which is what plugin-style roots expect.
|
|
221
|
+
function copyKnowledgeBase(skillsRootAbs) {
|
|
222
|
+
const dest = path.join(path.dirname(skillsRootAbs), "knowledge-base");
|
|
223
|
+
rmrf(dest);
|
|
224
|
+
copyRecursive(KB_SRC, dest);
|
|
225
|
+
return dest;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// ── MCP installation ──────────────────────────────────────────────────────────
|
|
229
|
+
function installMcp(ideList, resolvedRoot) {
|
|
230
|
+
const serverEntry = {
|
|
231
|
+
type: "stdio",
|
|
232
|
+
command: "npx",
|
|
233
|
+
args: ["-y", MCP_SERVER_ENTRY],
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
for (const ide of ideList) {
|
|
237
|
+
const mcpTarget = MCP_TARGETS[ide];
|
|
238
|
+
if (!mcpTarget) continue;
|
|
239
|
+
|
|
240
|
+
const configPath = path.isAbsolute(mcpTarget.configFile)
|
|
241
|
+
? mcpTarget.configFile
|
|
242
|
+
: path.join(resolvedRoot, mcpTarget.configFile);
|
|
243
|
+
ensureDir(path.dirname(configPath));
|
|
244
|
+
|
|
245
|
+
if (mcpTarget.format === "toml") {
|
|
246
|
+
installMcpToml(configPath, serverEntry);
|
|
247
|
+
} else {
|
|
248
|
+
let config = {};
|
|
249
|
+
if (fs.existsSync(configPath)) {
|
|
250
|
+
try { config = JSON.parse(fs.readFileSync(configPath, "utf8")); }
|
|
251
|
+
catch { config = {}; }
|
|
252
|
+
}
|
|
253
|
+
if (!config.mcpServers || typeof config.mcpServers !== "object") {
|
|
254
|
+
config.mcpServers = {};
|
|
255
|
+
}
|
|
256
|
+
config.mcpServers[MCP_SERVER_NAME] = serverEntry;
|
|
257
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf8");
|
|
258
|
+
}
|
|
259
|
+
console.log(c.green(" ✓ ") + `${ide} MCP → ${configPath}`);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function installMcpToml(configPath, serverEntry) {
|
|
264
|
+
let content = fs.existsSync(configPath) ? fs.readFileSync(configPath, "utf8") : "";
|
|
265
|
+
|
|
266
|
+
const sectionHeader = `[mcp_servers.${MCP_SERVER_NAME}]`;
|
|
267
|
+
const argsValue = JSON.stringify(serverEntry.args).replace(/,/g, ", ");
|
|
268
|
+
const newSection = [
|
|
269
|
+
sectionHeader,
|
|
270
|
+
`command = "${serverEntry.command}"`,
|
|
271
|
+
`args = ${argsValue}`,
|
|
272
|
+
].join("\n") + "\n";
|
|
273
|
+
|
|
274
|
+
const escapedName = MCP_SERVER_NAME.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
275
|
+
const sectionRegex = new RegExp(
|
|
276
|
+
`\\[mcp_servers\\.${escapedName}\\]\\n(?:(?!\\[)[^\\n]*\\n)*`,
|
|
277
|
+
"g"
|
|
278
|
+
);
|
|
279
|
+
content = content.replace(sectionRegex, "");
|
|
280
|
+
content = content.trimEnd() + (content.trim() ? "\n\n" : "") + newSection;
|
|
281
|
+
fs.writeFileSync(configPath, content, "utf8");
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// ── Claude Code permissions (pre-approve MCP tool) ──────────────────────────────
|
|
285
|
+
function installClaudePermissions(ideList, resolvedRoot) {
|
|
286
|
+
if (!ideList.includes("claude")) return;
|
|
287
|
+
|
|
288
|
+
const settingsDir = path.join(resolvedRoot, ".claude");
|
|
289
|
+
const settingsPath = path.join(settingsDir, "settings.json");
|
|
290
|
+
ensureDir(settingsDir);
|
|
291
|
+
|
|
292
|
+
let settings = {};
|
|
293
|
+
if (fs.existsSync(settingsPath)) {
|
|
294
|
+
try { settings = JSON.parse(fs.readFileSync(settingsPath, "utf8")); }
|
|
295
|
+
catch { settings = {}; }
|
|
296
|
+
}
|
|
297
|
+
if (!settings.permissions || typeof settings.permissions !== "object") settings.permissions = {};
|
|
298
|
+
if (!Array.isArray(settings.permissions.allow)) settings.permissions.allow = [];
|
|
299
|
+
|
|
300
|
+
const rules = [`mcp__${MCP_SERVER_NAME}__*`];
|
|
301
|
+
const added = rules.filter(r => !settings.permissions.allow.includes(r));
|
|
302
|
+
if (added.length > 0) {
|
|
303
|
+
settings.permissions.allow.push(...added);
|
|
304
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
305
|
+
console.log(c.green(" ✓ ") + `claude permissions → ${settingsPath}`);
|
|
306
|
+
} else {
|
|
307
|
+
console.log(c.dim(` ✓ claude permissions already set, skipped`));
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// ── Cursor permissions (allowlist MCP tool) ─────────────────────────────────────
|
|
312
|
+
function installCursorPermissions(ideList, resolvedRoot) {
|
|
313
|
+
if (!ideList.includes("cursor")) return;
|
|
314
|
+
|
|
315
|
+
const permDir = path.join(resolvedRoot, ".cursor");
|
|
316
|
+
const permPath = path.join(permDir, "permissions.json");
|
|
317
|
+
ensureDir(permDir);
|
|
318
|
+
|
|
319
|
+
let perms = {};
|
|
320
|
+
if (fs.existsSync(permPath)) {
|
|
321
|
+
try { perms = JSON.parse(fs.readFileSync(permPath, "utf8")); }
|
|
322
|
+
catch { perms = {}; }
|
|
323
|
+
}
|
|
324
|
+
if (!Array.isArray(perms.mcpAllowlist)) perms.mcpAllowlist = [];
|
|
325
|
+
|
|
326
|
+
const rule = `${MCP_SERVER_NAME}:skill_analysis`;
|
|
327
|
+
if (!perms.mcpAllowlist.includes(rule)) {
|
|
328
|
+
perms.mcpAllowlist.push(rule);
|
|
329
|
+
fs.writeFileSync(permPath, JSON.stringify(perms, null, 2) + "\n", "utf8");
|
|
330
|
+
console.log(c.green(" ✓ ") + `cursor permissions → ${permPath}`);
|
|
331
|
+
} else {
|
|
332
|
+
console.log(c.dim(` ✓ cursor permissions already set, skipped`));
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// ── install reporting (fire-and-forget) ─────────────────────────────────────────
|
|
337
|
+
// Spawns the MCP server with --report. All reporting details (endpoint, etc.)
|
|
338
|
+
// live inside the MCP server; install.js only passes context fields.
|
|
339
|
+
function reportInstall({ ide }) {
|
|
340
|
+
const payload = JSON.stringify({
|
|
341
|
+
method: 2, // 2 = trtc-agent-skills install (1=chat-web-skill, 2=trtc-agent-skills)
|
|
342
|
+
version: PKG_VERSION,
|
|
343
|
+
framework: "all",
|
|
344
|
+
ide,
|
|
345
|
+
os: os.platform(),
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
try {
|
|
349
|
+
const { spawn } = require("child_process");
|
|
350
|
+
const child = spawn("npx", ["-y", MCP_SERVER_ENTRY, "--report", payload], {
|
|
351
|
+
detached: true,
|
|
352
|
+
stdio: "ignore",
|
|
353
|
+
});
|
|
354
|
+
child.unref();
|
|
355
|
+
} catch {
|
|
356
|
+
// never block install on reporting failure
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// ── main ──────────────────────────────────────────────────────────────────────
|
|
361
|
+
function main() {
|
|
362
|
+
const args = process.argv.slice(2);
|
|
363
|
+
const cmd = args[0];
|
|
364
|
+
|
|
365
|
+
if (!cmd || cmd === "--help" || cmd === "-h") { printHelp(); process.exit(0); }
|
|
366
|
+
if (cmd === "--list" || cmd === "-l") { listSkills(); process.exit(0); }
|
|
367
|
+
if (cmd !== "add") {
|
|
368
|
+
console.error(c.red(`\n Unknown command: ${cmd}`));
|
|
369
|
+
printHelp();
|
|
370
|
+
process.exit(1);
|
|
371
|
+
}
|
|
372
|
+
if (args.includes("--list")) { listSkills(); process.exit(0); }
|
|
373
|
+
|
|
374
|
+
const isClean = args.includes("--clean");
|
|
375
|
+
const noReport = args.includes("--no-report");
|
|
376
|
+
const ideArg = getFlag(args, "--ide") || "claude";
|
|
377
|
+
|
|
378
|
+
const ideList = ideArg === "all" ? Object.keys(IDE_TARGETS) : [ideArg];
|
|
379
|
+
for (const ide of ideList) {
|
|
380
|
+
if (!IDE_TARGETS[ide]) {
|
|
381
|
+
console.error(c.red(`\n ✗ Unknown IDE: ${ide}. Valid: ${Object.keys(IDE_TARGETS).join(", ")}, all\n`));
|
|
382
|
+
process.exit(1);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
const cwd = process.cwd();
|
|
387
|
+
let resolvedRoot = findProjectRoot(cwd);
|
|
388
|
+
// Guard: don't install into the package's own tree during local dev.
|
|
389
|
+
if (resolvedRoot === PKG_ROOT) resolvedRoot = cwd;
|
|
390
|
+
|
|
391
|
+
console.log(`\n ${c.bold(c.cyan("@tencent-rtc/trtc-agent-skills"))} ${c.dim("v" + PKG_VERSION)}`);
|
|
392
|
+
console.log(` ${c.gray("cwd : " + cwd)}`);
|
|
393
|
+
console.log(` ${c.gray("projectRoot : " + resolvedRoot)}`);
|
|
394
|
+
console.log(` ${c.gray("IDE(s) : " + ideList.join(", "))}`);
|
|
395
|
+
console.log("");
|
|
396
|
+
|
|
397
|
+
// 1. Install skill dirs (+ co-located knowledge-base) for each IDE.
|
|
398
|
+
for (const ide of ideList) {
|
|
399
|
+
const target = IDE_TARGETS[ide];
|
|
400
|
+
const skillsRootAbs = path.join(resolvedRoot, target.skillsRoot);
|
|
401
|
+
console.log(` ${c.bold(ide)} ${c.gray("→ " + skillsRootAbs + "/")}`);
|
|
402
|
+
|
|
403
|
+
if (isClean) {
|
|
404
|
+
const wiped = cleanSkills(skillsRootAbs);
|
|
405
|
+
if (wiped > 0) console.log(c.dim(` ✓ cleaned ${wiped} existing skill ${wiped === 1 ? "entry" : "entries"}`));
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
installSkills(skillsRootAbs);
|
|
409
|
+
for (const name of SKILL_NAMES) console.log(c.green(" ✓ ") + name + "/");
|
|
410
|
+
|
|
411
|
+
const kbDest = copyKnowledgeBase(skillsRootAbs);
|
|
412
|
+
console.log(c.green(" ✓ ") + "knowledge-base/ " + c.dim("→ " + kbDest));
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// 2. Install MCP server config + permissions.
|
|
416
|
+
console.log(`\n ${c.bold("MCP")}`);
|
|
417
|
+
installMcp(ideList, resolvedRoot);
|
|
418
|
+
installClaudePermissions(ideList, resolvedRoot);
|
|
419
|
+
installCursorPermissions(ideList, resolvedRoot);
|
|
420
|
+
|
|
421
|
+
// 3. Anonymous install reporting (fire-and-forget; opt out via --no-report).
|
|
422
|
+
if (!noReport) reportInstall({ ide: ideArg });
|
|
423
|
+
|
|
424
|
+
// 4. Done.
|
|
425
|
+
console.log(`\n ${c.bold("Done.")} ${c.dim("Just describe what you want to build in your IDE — the skill activates automatically.")}\n`);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
try {
|
|
429
|
+
main();
|
|
430
|
+
} catch (err) {
|
|
431
|
+
console.error(c.red(`\n Error: ${err.message || err}\n`));
|
|
432
|
+
if (err.stack && process.env.DEBUG) console.error(c.dim(err.stack) + "\n");
|
|
433
|
+
process.exit(1);
|
|
434
|
+
}
|