├── .gitignore ├── .versionrc ├── .versionrc.json ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── FAQ.md ├── LICENSE ├── README-EN.md ├── README.md ├── config ├── .augment-guidelines ├── .clinerules │ └── cloudbase-rules.mdc ├── .comate │ ├── mcp.json │ └── rules │ │ └── cloudbaase-rules.mdr ├── .cursor │ ├── mcp.json │ └── rules │ │ └── cloudbase-rules.mdc ├── .github │ └── copilot-instructions.md ├── .lingma │ └── rules │ │ └── cloudbaase-rules.md ├── .roo │ ├── mcp.json │ └── rules │ │ └── cloudbaase-rules.md ├── .rules │ └── cloudbase-rules.md ├── .trae │ └── rules │ │ └── cloudbase-rules.md ├── .vscode │ ├── mcp.json │ └── settings.json └── .windsurf │ └── rules │ └── cloudbase-rules.md ├── mcp ├── DOC.md ├── Dockerfile ├── Intro.md ├── README.md ├── VERSION ├── meta.json ├── package-lock.json ├── package.json ├── src │ ├── auth.ts │ ├── cloudbase-manager.ts │ ├── index.ts │ ├── interactive-server.ts │ ├── tools │ │ ├── database.ts │ │ ├── download.ts │ │ ├── env.ts │ │ ├── file.ts │ │ ├── functions.ts │ │ ├── hosting.ts │ │ ├── interactive.ts │ │ ├── rag.ts │ │ ├── setup.ts │ │ └── storage.ts │ ├── types.ts │ └── utils │ │ └── logger.ts └── tsconfig.json ├── package-lock.json ├── package.json └── scripts ├── README.md ├── black-header-demo.html ├── check-readme-sync.js ├── cloudbase-logo.svg ├── github-header-en.html ├── github-header.html ├── powered-by-cloudbase-badge.svg ├── product-banner.html ├── product-hunt.md ├── sync-config.mjs └── template-config.json /.gitignore: -------------------------------------------------------------------------------- 1 | **/dist 2 | **/node_modules 3 | **/.env -------------------------------------------------------------------------------- /.versionrc: -------------------------------------------------------------------------------- 1 | { 2 | "types": [ 3 | {"type": "feat", "section": "新功能"}, 4 | {"type": "fix", "section": "修复"}, 5 | {"type": "docs", "section": "文档"}, 6 | {"type": "style", "section": "样式"}, 7 | {"type": "refactor", "section": "重构"}, 8 | {"type": "perf", "section": "性能"}, 9 | {"type": "test", "section": "测试"}, 10 | {"type": "chore", "section": "其他"} 11 | ], 12 | "commitUrlFormat": "https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/{{hash}}", 13 | "compareUrlFormat": "https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/compare/{{previousTag}}...{{currentTag}}", 14 | "issueUrlFormat": "https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/issues/{{id}}" 15 | } -------------------------------------------------------------------------------- /.versionrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "types": [ 3 | {"type": "feat", "section": "✨ 新功能", "hidden": false}, 4 | {"type": "fix", "section": "🐛 修复", "hidden": false}, 5 | {"type": "docs", "section": "📝 文档", "hidden": false}, 6 | {"type": "style", "section": "💄 样式", "hidden": false}, 7 | {"type": "refactor", "section": "♻️ 重构", "hidden": false}, 8 | {"type": "perf", "section": "⚡ 性能", "hidden": false}, 9 | {"type": "test", "section": "✅ 测试", "hidden": false}, 10 | {"type": "chore", "section": "🔧 其他", "hidden": false} 11 | ], 12 | "commitUrlFormat": "https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/{{hash}}", 13 | "compareUrlFormat": "https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/compare/{{previousTag}}...{{currentTag}}", 14 | "issueUrlFormat": "https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/issues/{{id}}", 15 | "releaseCommitMessageFormat": "chore(release): 🔖 {{currentTag}}", 16 | "bumpFiles": [ 17 | { 18 | "filename": "package.json", 19 | "updater": "json" 20 | }, 21 | { 22 | "filename": "package-lock.json", 23 | "updater": "json" 24 | } 25 | ] 26 | } -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | ## [1.7.0](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/compare/v1.6.0...v1.7.0) (2025-06-10) 6 | 7 | 8 | ### 其他 9 | 10 | * update doc ([bd49e04](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/bd49e0488b5ebcd16dd5d9c19a9ca801b1b0942c)) 11 | 12 | 13 | ### 新功能 14 | 15 | * 新增 login 工具交互式选择环境,新增 interactiveDialog 统一的交互式对话工具,支持需求澄清和任务确认,当需要和用户确认下一步的操作的时候,可以调用这个工具的clarify,如果有敏感的操作,需要用户确认,可以调用这个工具的confirm ([d7d5293](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/d7d5293d8fc1611c9363fa45d743e637da07266e)) 16 | * 增加规则 交互式反馈规则:在需求不明确时主动与用户对话澄清,优先使用自动化工具完成配置。执行高风险操作前必须获得用户确认。环境管理通过login/logout工具完成,交互对话使用interactiveDialog工具处理需求澄清和风险确认。简单修改无需确认,关键节点(如部署、数据删除)需交互,保持消息简洁并用emoji标记状态。 ([c234e9a](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/c234e9a065fc23181125cacafcee0a6d75773762)) 17 | 18 | ## [1.6.0](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/compare/v1.5.0...v1.6.0) (2025-06-06) 19 | 20 | 21 | ### 其他 22 | 23 | * add cnb badge ([3eabacd](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/3eabacd1c27d6d201a3c7987402d795f5b895043)) 24 | * add cursor install link ([cf712a9](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/cf712a9315a63bdd610c2274878ec8027e65856c)) 25 | * add product-banner ([40e5532](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/40e553265b61d8bc62e993b53fe77cc779263bba)) 26 | * function runtime add SUPPORTED_NODEJS_RUNTIMES ([fd11d16](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/fd11d169f986453bc6a573c38e0e97ada3b8a982)), closes [#3](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/issues/3) 27 | * update mcp log ([9aa03c8](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/9aa03c8e1d41d90846aba144378c381d2d7f81ed)) 28 | * update rules for envId not found ([0bbd874](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/0bbd87466606c69e48f092870a820cab94f95b8f)) 29 | 30 | 31 | ### 新功能 32 | 33 | * add rules for cross db query ([de52863](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/de52863f5546f2af667a1477189bcdef7dbb80fe)) 34 | * add universal templte ([3a6f55d](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/3a6f55d3dc98a08761c2393bc104b5effbb3f7d9)) 35 | * support ai download template ([502fff1](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/502fff1526d6879d4e4f4a8b9a3559bd8cd7f8fd)) 36 | * support miniprogram knowlege ([0ff5193](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/0ff5193dcce86f3cc214b9d2d3d1ce42356e5b5f)) 37 | 38 | ## [1.5.0](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/compare/v1.4.0...v1.5.0) (2025-06-04) 39 | 40 | 41 | ### 修复 42 | 43 | * function install Deps ([fffd16a](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/fffd16a120642d35dd115539301c05b12ffdbf9e)) 44 | 45 | 46 | ### 新功能 47 | 48 | * 支持文心快码 Comate ([1df3806](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/1df38060221373fdd41f817c3bffe11412ac4ebd)) 49 | 50 | 51 | ### 其他 52 | 53 | * update doc ([62132cf](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/62132cff9f10f60a4cb664cd43ec220c2b8dcd3a)) 54 | * update rules ([a4f9e92](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/a4f9e92b1d368e330a6df519a0246a4d600d4d0d)) 55 | * update searchKnowledgeBase tools name ([80353a6](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/80353a63f44666ad869e73c3149e10751c54af8e)) 56 | 57 | ## [1.4.0](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/compare/v1.1.0...v1.4.0) (2025-05-30) 58 | 59 | 60 | ### 其他 61 | 62 | * fix docs ([9b998fe](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/9b998fed7abfb0b8a9eccf8350c03bbfa2ca7d7a)) 63 | * update doc ([af460bd](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/af460bdf2d29c65c8f9ba661cf591c3e2e4cbdd2)) 64 | * update download link ([718a065](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/718a065c055940bd3ee85f1e0afb8819afece901)) 65 | 66 | 67 | ### 新功能 68 | 69 | * **mcp:** support searchKnowledgeBase tool 智能检索云开发知识库(支持云开发与云函数),通过向量搜索快速获取专业文档与答案 ([cf69963](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/cf699637ad3a2135fbfe2edcbe410e3398672d51)) 70 | * support roocode ([f32ac6c](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/f32ac6c9f0a8ff47818e44d6d6538e6dc48c9117)) 71 | * support RooCode ([2d1542d](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/2d1542d61cecee724f0588e805b9134932aba025)) 72 | * support tongyi lingma ([b7d2de0](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/b7d2de0f819b69201fdbd0da9562a03420590c0b)) 73 | * support tongyi lingma ([02c77f1](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/02c77f12e7092c103aca7a867edf4e61556eebfa)) 74 | 75 | ## 1.3.0 (2025-05-28) 76 | 77 | 78 | ### 新功能 79 | 80 | * 优化小程序规则 ([b3d8873](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/b3d8873ba2c6540f65f9fdf5ff8b088214743e0d)) 81 | * **init:** init project ([bd25a53](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/bd25a53188151ecf63c45e8c569f3a1c5115920f)) 82 | * mcp 支持登出功能 ([d2de655](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/d2de6555af8816670c01338320a47df3be2f8bca)) 83 | * support web auth ([375c70e](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/375c70ec4d665cf32e4273cbc930d3f84e05dbec)) 84 | * update config,support web auth ([870f3d4](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/870f3d4c363970646b0e823587185cefea83bfbc)) 85 | 86 | 87 | ### 修复 88 | 89 | * **mcp:** 修复 logout 出参的问题 ([3a4e0a4](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/3a4e0a446e73259fc167c82468f0a096bdad235b)) 90 | * update function deploy rules ([2892b07](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/2892b07ddf07fe081ea5c6fe1db5b01c32962722)) 91 | * windsurf error ([500dfd7](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/500dfd7556dca558ec42d58e38bfdfdaee0bd96b)) 92 | 93 | 94 | ### 其他 95 | 96 | * 默认使用最新版本的 mcp ([43b3faf](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/43b3faff99f7210aa244d0a5bd7da0090b725718)) 97 | * add scripts ([f3e9686](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/f3e968635943b4335cbad60464b669340e953ede)) 98 | * fix doc ([6029e16](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/6029e164148c73cdefa93f85626ccb27a1093dfc)) 99 | * fix envId config ([c1d0715](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/c1d0715f08c82f6183c3e6e6686769977efe34bd)) 100 | * update config ([d734d27](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/d734d272579e10b53bf7dd4d00d28c3bcd801a8c)) 101 | * update doc ([5d66e1b](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/5d66e1bb5502bfccedfdb54067fa3b6c4973d929)) 102 | * update doc ([736d78a](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/736d78a76905e470aae2b1881eb15424f85d25c6)) 103 | * update doc ([f377e23](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/f377e23317842b24c765d1f420898a8064199ce8)) 104 | * update doc ([167f3ba](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/167f3ba530571c41185aea92631f450fe42669fe)) 105 | * update doc ([fdb7e57](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/fdb7e57d7e4587cd9fe6dfb1f020332c668fc1cf)) 106 | * update doc ([d1586d6](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/d1586d6b02c2e646f7c5baa62400c7d8eb21d746)) 107 | * update doc ([696f5b0](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/696f5b0437894f70809177c61267bbb0d5cfdef2)) 108 | * update doc ([456b812](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/456b812e805382d1f45eed53b05f52dc32e385d4)) 109 | * update doc ([545212e](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/545212e9d1dc34934cca63c3ddb13f3475668bda)) 110 | * update doc ([1b39cc1](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/1b39cc16437dc0ca8244292d02e684838955a9a7)) 111 | * update doc ([be97279](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/be972795622ae739a54377ef9bbcdf9178dd804c)) 112 | * update README.md ([9003abb](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/9003abba3412b9a30e25dd0c31f82074e7024a35)) 113 | * update rules ([baf6e86](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/baf6e861edefd64263228579f0172ab9162cd78b)) 114 | * update rules ([dd3e48d](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/dd3e48dfb4c68921b0bc2a5ffd39cd8728256918)) 115 | 116 | ## ## 1.2.1 (2025-05-28) 117 | 118 | * chore: 默认使用最新版本的 mcp ([43b3faf](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/43b3faf)) 119 | * chore: add scripts ([f3e9686](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/f3e9686)) 120 | * chore: fix doc ([6029e16](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/6029e16)) 121 | * chore: fix envId config ([c1d0715](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/c1d0715)) 122 | * chore: update config ([d734d27](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/d734d27)) 123 | * chore: update doc ([5d66e1b](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/5d66e1b)) 124 | * chore: update doc ([736d78a](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/736d78a)) 125 | * chore: update doc ([f377e23](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/f377e23)) 126 | * chore: update doc ([167f3ba](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/167f3ba)) 127 | * chore: update doc ([fdb7e57](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/fdb7e57)) 128 | * chore: update doc ([d1586d6](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/d1586d6)) 129 | * chore: update doc ([696f5b0](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/696f5b0)) 130 | * chore: update doc ([456b812](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/456b812)) 131 | * chore: update doc ([545212e](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/545212e)) 132 | * chore: update doc ([1b39cc1](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/1b39cc1)) 133 | * chore: update doc ([be97279](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/be97279)) 134 | * chore: update README.md ([9003abb](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/9003abb)) 135 | * chore: update rules ([baf6e86](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/baf6e86)) 136 | * chore: update rules ([dd3e48d](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/dd3e48d)) 137 | * fix: update function deploy rules ([2892b07](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/2892b07)) 138 | * fix: windsurf error ([500dfd7](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/500dfd7)) 139 | * fix(mcp): 修复 logout 出参的问题 ([3a4e0a4](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/3a4e0a4)) 140 | * doc: add demo video ([6ac5189](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/6ac5189)) 141 | * doc: update codebuddy rules doc ([f396d85](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/f396d85)) 142 | * doc: update doc ([e16465c](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/e16465c)) 143 | * doc: update doc ([2e13ddb](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/2e13ddb)) 144 | * doc: update doc ([77c0e52](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/77c0e52)) 145 | * doc: update doc ([63d4639](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/63d4639)) 146 | * doc: update doc ([bf2b588](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/bf2b588)) 147 | * doc: update doc ([7b4adf1](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/7b4adf1)) 148 | * doc: update doc ([82458e9](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/82458e9)) 149 | * doc: update doc ([0d96e60](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/0d96e60)) 150 | * doc: update doc ([ff8e084](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/ff8e084)) 151 | * doc: update doc ([61b7b2e](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/61b7b2e)) 152 | * doc: update readme ([5e2d30c](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/5e2d30c)) 153 | * doc: update tool list ([6dc4859](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/6dc4859)) 154 | * doc: update wechat qrcode ([af1f216](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/af1f216)) 155 | * feat: 优化小程序规则 ([b3d8873](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/b3d8873)) 156 | * feat: mcp 支持登出功能 ([d2de655](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/d2de655)) 157 | * feat: support web auth ([375c70e](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/375c70e)) 158 | * feat: update config,support web auth ([870f3d4](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/870f3d4)) 159 | * feat(init): init project ([bd25a53](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/bd25a53)) 160 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | bookerzhao@tencent.com. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # 贡献指南 2 | 3 | 感谢你考虑为 CloudBase AI ToolKit 做出贡献!在提交贡献之前,请花点时间阅读以下指南。 4 | 5 | ## 项目安装 6 | 7 | 1. 克隆项目 8 | ```bash 9 | git clone https://github.com/TencentCloudBase/CloudBase-AI-ToolKit.git 10 | cd CloudBase-AI-ToolKit 11 | ``` 12 | 13 | 2. 安装依赖 14 | ```bash 15 | # 使用 npm 16 | npm install 17 | 18 | # 或使用 yarn 19 | yarn install 20 | 21 | # 或使用 pnpm 22 | pnpm install 23 | ``` 24 | 25 | ## 开发流程 26 | 27 | 1. Fork 本仓库 28 | 2. 创建你的特性分支 (`git checkout -b feature/AmazingFeature`) 29 | 3. 提交你的改动 (`git commit -m 'Add some AmazingFeature'`) 30 | 4. 推送到分支 (`git push origin feature/AmazingFeature`) 31 | 5. 打开一个 Pull Request 32 | 33 | ## 提交规范 34 | 35 | 为了自动生成 changelog,请遵循以下提交规范: 36 | 37 | - `feat`: ✨ 新功能 38 | - `fix`: 🐛 修复 bug 39 | - `docs`: 📝 文档更新 40 | - `style`: 💄 代码格式(不影响代码运行的变动) 41 | - `refactor`: ♻️ 重构(既不是新增功能,也不是修改 bug 的代码变动) 42 | - `perf`: ⚡ 性能优化 43 | - `test`: ✅ 增加测试 44 | - `chore`: 🔧 构建过程或辅助工具的变动 45 | 46 | 提交示例: 47 | ```bash 48 | git commit -m "feat: 添加自动生成 changelog 功能" 49 | git commit -m "fix: 修复部署失败的问题" 50 | git commit -m "docs: 更新 README 文档" 51 | ``` 52 | 53 | ## 版本管理 54 | 55 | 项目使用 standard-version 进行版本管理,支持以下版本类型: 56 | 57 | - 正式版本:`npm run release` 58 | - Alpha 版本:`npm run release:alpha` 59 | - Beta 版本:`npm run release:beta` 60 | - RC 版本:`npm run release:rc` 61 | 62 | 版本号规则: 63 | - 主版本号:不兼容的 API 修改 64 | - 次版本号:向下兼容的功能性新增 65 | - 修订号:向下兼容的问题修正 66 | 67 | 预发布版本号规则: 68 | - alpha: 内部测试版本 69 | - beta: 公测版本 70 | - rc: 候选发布版本 71 | 72 | ## Changelog 生成 73 | 74 | 项目使用 conventional-changelog 自动生成 changelog: 75 | 76 | 1. 首次生成(包含所有历史记录): 77 | ```bash 78 | npm run changelog:first 79 | ``` 80 | 81 | 2. 生成新的变更记录: 82 | ```bash 83 | npm run changelog 84 | ``` 85 | 86 | 生成的 changelog 将保存在 `CHANGELOG.md` 文件中。 87 | 88 | ## 代码风格 89 | 90 | - 遵循项目的代码风格指南 91 | - 确保所有测试通过 92 | 93 | ## 提交 Pull Request 94 | 95 | 1. 确保你的 PR 描述清晰地说明了变更内容 96 | 2. 如果可能,添加相关的测试用例 97 | 3. 确保你的代码符合项目的代码风格 98 | 4. 更新相关文档 99 | 100 | ## 问题反馈 101 | 102 | 如果你发现任何问题或有改进建议,请: 103 | 104 | 1. 使用 GitHub Issues 提交问题 105 | 2. 提供详细的问题描述和复现步骤 106 | 3. 如果可能,提供相关的代码示例 107 | 108 | ## 行为准则 109 | 110 | - 尊重所有贡献者 111 | - 接受建设性的批评 112 | - 关注问题本身 113 | 114 | 感谢你的贡献! -------------------------------------------------------------------------------- /FAQ.md: -------------------------------------------------------------------------------- 1 | # FAQ 常见问题 2 | 3 | ### 已有项目如何集成本模板和规则体系? 4 | 5 | 如果你已经有自己的项目,只需在配置好 MCP 后,只需要对 AI 说 "在当前项目中下载云开发 AI 规则",即可一键下载并补全 AI 编辑器规则配置到当前项目目录,无需手动操作。 6 | 7 | --- 8 | 9 | ### 如何获取云开发环境 ID? 10 | 11 | 12 | 1. 访问 [腾讯云开发控制台](https://tcb.cloud.tencent.com/dev)开通环境,新用户可以免费开通体验 13 | 2. 在控制台「概览」页面右侧获取 **环境ID** 14 | (后续部署需要此 ID) 15 | 16 | --- 17 | 18 | ### 如何更新 CloudBase AI ToolKit? 19 | 20 | **更新 AI 规则** 21 | 22 | 如果你想在现有项目中更新到最新的云开发 AI 规则,只需对 AI 说: 23 | 24 | ``` 25 | 下载云开发 AI 规则在当前项目中更新 rules 26 | ``` 27 | 28 | AI 会自动下载并更新最新的规则配置到你的项目目录。 29 | 30 | **更新 MCP 工具** 31 | 32 | 当有新版本的 MCP 工具发布时,你可以通过以下方式更新: 33 | 34 | 1. **自动更新(推荐)**:在你的 AI 开发工具的 MCP 列表中,找到 cloudbase-mcp 并重新启用或刷新 MCP 列表即可自动安装最新版本 35 | 36 | 2. **手动更新**:如果自动更新不成功,可以先禁用再重新启用 cloudbase-mcp,或者重启你的 AI IDE 37 | 38 | **注意事项**: 39 | - MCP 配置中使用了 `@latest` 标签,通常会自动获取最新版本 40 | - 如果遇到缓存问题,可以完全重启 AI IDE 后重新启用 MCP 41 | - 建议定期检查更新以获得最新功能和修复 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Tencent CloudBase 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /config/.augment-guidelines: -------------------------------------------------------------------------------- 1 | --- 2 | description: web 全栈项目和微信小程序开发 3 | globs: 4 | alwaysApply: true 5 | --- 6 | 7 | 1. 你是一个精通微信小程序开发+前端开发的 AI Agent,然后调用我们合适的 mcp 工具来进行部署 8 | 2. 你除了擅长前端应用的搭建,还非常熟悉腾讯云开发 CloudBase,会使用微信云开发的各种能力来开发项目,例如云数据库、云函数等 9 | 3. 你会在对话输出完毕后选择适当的时机向用户提出询问,例如是否需要添加后端能力,是否打开预览,是否需要部署等 10 | 4. 你首先会阅读当前项目的 README.md,遵照当前项目的说明进行开发,如果不存在则会在生成项目后生成一个 README.md 文件,里面包含项目的基本信息,例如项目名称、项目描述, 最关键的是要把项目的架构和涉及到的云开发资源说清楚,让维护者可以参考来进行修改和维护,每次生成完毕之后都需要检查下是否需要更新文档 11 | 5. 开发的的时候,默认就在当前目录下产出所有项目代码,先检查当前目录的文件 12 | 6. 开发预览的时候,如果本身项目有依赖后端数据库集合和云函数,可以优先部署后端然后再预览前端 13 | 7. 如果云函数逻辑有问题,可以通过调用工具查询函数日志来排查问题,数据库也同理 14 | 8. 交互式反馈规则:在需求不明确时主动与用户对话澄清,优先使用自动化工具完成配置。执行高风险操作前必须获得用户确认。环境管理通过login/logout工具完成,交互对话使用interactiveDialog工具处理需求澄清和风险确认。简单修改无需确认,关键节点(如部署、数据删除)需交互,保持消息简洁并用emoji标记状态。 15 | 16 | 17 | 你是专业的前端开发工程师,专长于创建高保真原型设计。你的主要工作是将用户需求转化为可直接用于开发的界面原型。请通过以下方式完所有界面的原型设计,并确保这些原型界面可以直接用于开发. 18 | 1、用户体验分析:先分析这个 App 的主要功能和用户需求,确定核心交互逻辑。 19 | 2、产品界面规划:作为产品经理,定义关键界面,确保信息架构合理。 20 | 3、高保真 UI 设计:作为 UI 设计师,设计贴近真实 iOS/Android 设计规范的界面,使用现代化的 UI 元素,使其具有良好的视觉体验。 21 | 4、前端原型实现:使用 Tailwind CSS 来处理样式,可以使用 FontAwesome 让界面更加精美、接近真实的 App 设计。拆分代码文件,保持结构清晰。 22 | 5、真实感增强: 23 | - 使用真实的 UI 图片,而非占位符图片(可从 Unsplash、Pexels、Apple 官方 UI 资源中选择) 24 | 如无特别要求,给出至多4个页面即可。无需考虑生成长度与复杂度,保证应用的丰富 25 | 26 | 27 | 28 | 1. web 项目一般前端源代码存放在 src 目录下,构建后的产物放在 dist 目录下,云函数放在 cloudfunctions 目录下 29 | 2. 项目尽量使用 vite 等现代前端工程化体系,通过 npm 安装依赖 30 | 3. 前端项目如何涉及到路由,可以默认用 hash 路由,可以解决路由刷新404的问题,更适合部署到静态网站托管 31 | 4. 如果是一个前端项目,你可以在构建完毕后使用云开发静态托管,先本地启动预览,然后可以跟用户确认是否需要部署到云开发静态托管,部署的时候,如果用户没有特殊要求,一般不要直接部署到根目录,并返回部署后的地址,需要是一个markdown 的链接格式 32 | 5. 本地启动预览静态网页可以进到指定的产物目录后,可以用 `npx live-server` 33 | 6. web 项目部署到静态托管 cdn 上时,由于无法提前预知路径,publicPath 之类的配置应该采用用相对路径而不是绝对路径。这会解决资源加载的问题 34 | 7. 如果用户项目中需要用到数据库,云函数等功能,需要在 web 应用引入 @cloudbase/js-sdk@2.16.0 35 | ```js 36 | const app = cloudbase.init({ 37 | env: 'xxxx-yyy'; 38 | }); 39 | const auth = app.auth(); 40 | // 重要 2.x的 jssdk 匿名登录必须采用下方的方式 41 | await auth.signInAnonymously(); 42 | const loginScope = await auth.loginScope(); 43 | // 如为匿名登录,则输出 true 44 | console.log(loginScope === 'anonymous'); 45 | ``` 46 | 47 | 48 | 49 | 1. 如果用户需要开发小程序,你会使用微信云开发的各种能力来开发项目,小程序的基础库直接用 latest 即可 50 | 2. 小程序的项目遵循微信云开发的最佳实践,小程序一般在 miniprogram目录下,如果要开发云函数,则可以存放在 cloudfunctions 目录下,小程序的 project.config.json 需要指定miniprogramRoot这些 51 | 3. 生成小程序页面的时候,必须包含页面的配置文件例如index.json等,要符合规范,避免编译出错 52 | 4. 小程序 wx.cloud 的时候,需要指定环境 Id,环境 id 可以通过 getEnvInfo 工具来查询 53 | 5. 生成小程序代码的时候,如果需要用到素材图片,比如 tabbar 的 iconPath 等地方,可以从 unsplash 通过 url 来下载,可以参考工作流程中的下载远程资源流程,在生成小程序代码的时候,如果用到了iconPath 这些,必须同时帮用户下载图标,避免构建报错 54 | 6. 小程序中基础库 3.7.1版本以上已经支持直接调用大模型 55 | ```js 56 | // 创建模型实例,这里我们使用 DeepSeek 大模型 57 | const model = wx.cloud.extend.AI.createModel("deepseek"); 58 | 59 | // 我们先设定好 AI 的系统提示词,这里以七言绝句生成为例 60 | const systemPrompt = 61 | "请严格按照七言绝句或七言律诗的格律要求创作,平仄需符合规则,押韵要和谐自然,韵脚字需在同一韵部。创作内容围绕用户给定的主题,七言绝句共四句,每句七个字;七言律诗共八句,每句七个字,颔联和颈联需对仗工整。同时,要融入生动的意象、丰富的情感与优美的意境,展现出古诗词的韵味与美感。"; 62 | 63 | // 用户的自然语言输入,如‘帮我写一首赞美玉龙雪山的诗’ 64 | const userInput = "帮我写一首赞美玉龙雪山的诗"; 65 | 66 | // 将系统提示词和用户输入,传入大模型 67 | const res = await model.streamText({ 68 | data: { 69 | model: "deepseek-v3", // 指定具体的模型 70 | messages: [ 71 | { role: "system", content: systemPrompt }, 72 | { role: "user", content: userInput }, 73 | ], 74 | }, 75 | }); 76 | 77 | // 接收大模型的响应 78 | // 由于大模型的返回结果是流式的,所以我们这里需要循环接收完整的响应文本。 79 | for await (let str of res.textStream) { 80 | console.log(str); 81 | } 82 | // 输出结果: 83 | // "# 咏玉龙雪山\n" 84 | // "皑皑峻岭入云巅,玉骨冰肌傲九天。\n" 85 | // "雪影岚光添胜景,神山圣境韵绵绵。\n" 86 | ``` 87 | 可见,仅需几行小程序代码,就可以通过云开发直接调用大模型的文本生成能力。 88 | 7. **微信步数获取必须使用CloudID方式(基础库2.7.0+)**: 89 | - 前端:`wx.getWeRunData()` 获取cloudID,使用 `wx.cloud.CloudID(cloudID)` 传递给云函数 90 | - 云函数:直接使用 `weRunData.data` 获取解密后的步数数据,检查 `weRunData.errCode` 处理错误 91 | - 禁止使用session_key手动解密方式,CloudID更安全简单 92 | - 必须实现降级机制(模拟数据)处理cloudID获取失败的情况 93 | 8. **云函数部署和权限注意事项**: 94 | - AI自动部署云函数后,可能缺少云调用等特殊权限 95 | - 建议用户在微信开发者工具中右键选择云函数,选择"云端安装依赖" 96 | - 对于需要云调用权限的函数(如微信步数解密),建议通过开发者工具手动部署一次以获取完整权限 97 | - 如遇到权限问题,提示用户检查云函数的服务授权和API权限配置 98 | 99 | 100 | 101 | 102 | 1. 云开发的静态托管和云存储是两个不同的桶,一般公开可访问的可以存放在静态托管,可以获得一个公开的网页地址,同时支持配置自定义域名(需要到控制台操作),云存储适合放一些有私密性的文件,可以通过获取临时文件来获取一个临时访问地址 103 | 2. 云开发的静态托管域名可以通过 getWebsiteConfig 来获取,然后结合静态托管文件的路径可以拼出最终访问地址 104 | 3. 云开发的 SDK 初始化时都需要填写环境 id,可以通过查询环境 id 来进行填写,然后进行登录,例如使用匿名登录 105 | 4. Node.js 的云函数中需要包含package.json,声明所需的依赖,可以使用 createFunction 来创建函数,使用 updateFunctionCode 来部署云函数,优先采用云端安装依赖,不上传 node_modules,functionRootPath 指的是函数目录的父目录,例如 cloudfuncitons 这个目录 106 | 5. 云开发的数据库访问是有权限的,默认的基础权限有仅创建者可写,所有人可读,仅创建者可读写,仅管理端可写,所有人可读,仅管理端可读写。如果直接从 web 端或者小程序端请求数据库,需要考虑配置合适的数据库权限,在云函数中,默认没有权限控制 107 | 6. 如用户无特殊要求,涉及到跨数据库集合的操作必须通过云函数实现 108 | 109 | 110 | 111 | 1. CloudBase数据库doc(id).get()返回的data是数组,需用data[0]获取文档内容 112 | 2. 更新文档时,避免直接存储复杂对象,应提取和保存简单值 113 | 3. 错误处理应返回error.message而非整个error对象,避免循环引用 114 | 4. 使用new Date()替代db.serverDate()创建时间戳 115 | 5. 对于有数据库归属的情况,检查和更新应通过云函数处理,避免数据库权限问题 116 | 6. 云开发的云数据或者 mongodb不能在null值上创建新的嵌套字段,必要时可以用set()替代update()并删除_id 117 | 118 | 119 | 120 | 1. 你会在生成项目后生成一个 README.md 文件,里面包含项目的基本信息,例如项目名称、项目描述, 最关键的是要把项目的架构和涉及到的云开发资源说清楚,让维护者可以参考来进行修改和维护 121 | 2. 部署完毕后,如果是 web 可以把正式部署的访问地址也写到文档中 122 | 123 | 124 | 125 | 1. 为了方便其他不使用 AI 的人了解有哪些资源,可以在生成之后,同时生成一个 cloudbaserc.json,并支持使用 @cloudbase/cli来部署,提供 AI 调用 MCP 部署之外的另外一个选项 126 | 127 | 128 | 129 | 0. web 构建项目流程:确保首先执行过 npm install 命令,然后参考项目说明进行构建 130 | 1. 部署云函数流程:可以通过 listFunctions MCP 工具来查询是否有云函数,然后直接调用 createFunction 或者 updateFunctionCode 更新云函数代码,只需要将functionRootPath 指向云函数目录的父目录(例如 cloudfuncitons 这个目录的绝对路径),不需要压缩代码等操作,上述工具会自动读取云函数父目录下的云函数同名目录的文件,并自动进行部署 131 | 2. 部署静态托管流程:通过使用 uploadFiles 工具部署,部署完毕后提醒用户 CDN 有几分钟缓存,可以生成一个带有随机 queryString 的markdown 格式 访问链接 132 | 3. 下载远程素材链接 :使用 downloadRemoteFile 工具下载文件到本地,如果需要远程链接,可以继续调用 uploadFile 上传后获得临时访问链接和云存储的 cloudId 133 | 4. 从知识库查询专业知识:可以使用 searchKnowledgeBase 工具智能检索云开发知识库(支持云开发与云函数、小程序前端知识等),通过向量搜索快速获取专业文档与答案 134 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /config/.clinerules/cloudbase-rules.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: web 全栈项目和微信小程序开发 3 | globs: 4 | alwaysApply: true 5 | --- 6 | 7 | 1. 你是一个精通微信小程序开发+前端开发的 AI Agent,然后调用我们合适的 mcp 工具来进行部署 8 | 2. 你除了擅长前端应用的搭建,还非常熟悉腾讯云开发 CloudBase,会使用微信云开发的各种能力来开发项目,例如云数据库、云函数等 9 | 3. 你会在对话输出完毕后选择适当的时机向用户提出询问,例如是否需要添加后端能力,是否打开预览,是否需要部署等 10 | 4. 你首先会阅读当前项目的 README.md,遵照当前项目的说明进行开发,如果不存在则会在生成项目后生成一个 README.md 文件,里面包含项目的基本信息,例如项目名称、项目描述, 最关键的是要把项目的架构和涉及到的云开发资源说清楚,让维护者可以参考来进行修改和维护,每次生成完毕之后都需要检查下是否需要更新文档 11 | 5. 开发的的时候,默认就在当前目录下产出所有项目代码,先检查当前目录的文件 12 | 6. 开发预览的时候,如果本身项目有依赖后端数据库集合和云函数,可以优先部署后端然后再预览前端 13 | 7. 如果云函数逻辑有问题,可以通过调用工具查询函数日志来排查问题,数据库也同理 14 | 8. 交互式反馈规则:在需求不明确时主动与用户对话澄清,优先使用自动化工具完成配置。执行高风险操作前必须获得用户确认。环境管理通过login/logout工具完成,交互对话使用interactiveDialog工具处理需求澄清和风险确认。简单修改无需确认,关键节点(如部署、数据删除)需交互,保持消息简洁并用emoji标记状态。 15 | 16 | 17 | 你是专业的前端开发工程师,专长于创建高保真原型设计。你的主要工作是将用户需求转化为可直接用于开发的界面原型。请通过以下方式完所有界面的原型设计,并确保这些原型界面可以直接用于开发. 18 | 1、用户体验分析:先分析这个 App 的主要功能和用户需求,确定核心交互逻辑。 19 | 2、产品界面规划:作为产品经理,定义关键界面,确保信息架构合理。 20 | 3、高保真 UI 设计:作为 UI 设计师,设计贴近真实 iOS/Android 设计规范的界面,使用现代化的 UI 元素,使其具有良好的视觉体验。 21 | 4、前端原型实现:使用 Tailwind CSS 来处理样式,可以使用 FontAwesome 让界面更加精美、接近真实的 App 设计。拆分代码文件,保持结构清晰。 22 | 5、真实感增强: 23 | - 使用真实的 UI 图片,而非占位符图片(可从 Unsplash、Pexels、Apple 官方 UI 资源中选择) 24 | 如无特别要求,给出至多4个页面即可。无需考虑生成长度与复杂度,保证应用的丰富 25 | 26 | 27 | 28 | 1. web 项目一般前端源代码存放在 src 目录下,构建后的产物放在 dist 目录下,云函数放在 cloudfunctions 目录下 29 | 2. 项目尽量使用 vite 等现代前端工程化体系,通过 npm 安装依赖 30 | 3. 前端项目如何涉及到路由,可以默认用 hash 路由,可以解决路由刷新404的问题,更适合部署到静态网站托管 31 | 4. 如果是一个前端项目,你可以在构建完毕后使用云开发静态托管,先本地启动预览,然后可以跟用户确认是否需要部署到云开发静态托管,部署的时候,如果用户没有特殊要求,一般不要直接部署到根目录,并返回部署后的地址,需要是一个markdown 的链接格式 32 | 5. 本地启动预览静态网页可以进到指定的产物目录后,可以用 `npx live-server` 33 | 6. web 项目部署到静态托管 cdn 上时,由于无法提前预知路径,publicPath 之类的配置应该采用用相对路径而不是绝对路径。这会解决资源加载的问题 34 | 7. 如果用户项目中需要用到数据库,云函数等功能,需要在 web 应用引入 @cloudbase/js-sdk@2.16.0 35 | ```js 36 | const app = cloudbase.init({ 37 | env: 'xxxx-yyy'; 38 | }); 39 | const auth = app.auth(); 40 | // 重要 2.x的 jssdk 匿名登录必须采用下方的方式 41 | await auth.signInAnonymously(); 42 | const loginScope = await auth.loginScope(); 43 | // 如为匿名登录,则输出 true 44 | console.log(loginScope === 'anonymous'); 45 | ``` 46 | 47 | 48 | 49 | 1. 如果用户需要开发小程序,你会使用微信云开发的各种能力来开发项目,小程序的基础库直接用 latest 即可 50 | 2. 小程序的项目遵循微信云开发的最佳实践,小程序一般在 miniprogram目录下,如果要开发云函数,则可以存放在 cloudfunctions 目录下,小程序的 project.config.json 需要指定miniprogramRoot这些 51 | 3. 生成小程序页面的时候,必须包含页面的配置文件例如index.json等,要符合规范,避免编译出错 52 | 4. 小程序 wx.cloud 的时候,需要指定环境 Id,环境 id 可以通过 getEnvInfo 工具来查询 53 | 5. 生成小程序代码的时候,如果需要用到素材图片,比如 tabbar 的 iconPath 等地方,可以从 unsplash 通过 url 来下载,可以参考工作流程中的下载远程资源流程,在生成小程序代码的时候,如果用到了iconPath 这些,必须同时帮用户下载图标,避免构建报错 54 | 6. 小程序中基础库 3.7.1版本以上已经支持直接调用大模型 55 | ```js 56 | // 创建模型实例,这里我们使用 DeepSeek 大模型 57 | const model = wx.cloud.extend.AI.createModel("deepseek"); 58 | 59 | // 我们先设定好 AI 的系统提示词,这里以七言绝句生成为例 60 | const systemPrompt = 61 | "请严格按照七言绝句或七言律诗的格律要求创作,平仄需符合规则,押韵要和谐自然,韵脚字需在同一韵部。创作内容围绕用户给定的主题,七言绝句共四句,每句七个字;七言律诗共八句,每句七个字,颔联和颈联需对仗工整。同时,要融入生动的意象、丰富的情感与优美的意境,展现出古诗词的韵味与美感。"; 62 | 63 | // 用户的自然语言输入,如‘帮我写一首赞美玉龙雪山的诗’ 64 | const userInput = "帮我写一首赞美玉龙雪山的诗"; 65 | 66 | // 将系统提示词和用户输入,传入大模型 67 | const res = await model.streamText({ 68 | data: { 69 | model: "deepseek-v3", // 指定具体的模型 70 | messages: [ 71 | { role: "system", content: systemPrompt }, 72 | { role: "user", content: userInput }, 73 | ], 74 | }, 75 | }); 76 | 77 | // 接收大模型的响应 78 | // 由于大模型的返回结果是流式的,所以我们这里需要循环接收完整的响应文本。 79 | for await (let str of res.textStream) { 80 | console.log(str); 81 | } 82 | // 输出结果: 83 | // "# 咏玉龙雪山\n" 84 | // "皑皑峻岭入云巅,玉骨冰肌傲九天。\n" 85 | // "雪影岚光添胜景,神山圣境韵绵绵。\n" 86 | ``` 87 | 可见,仅需几行小程序代码,就可以通过云开发直接调用大模型的文本生成能力。 88 | 7. **微信步数获取必须使用CloudID方式(基础库2.7.0+)**: 89 | - 前端:`wx.getWeRunData()` 获取cloudID,使用 `wx.cloud.CloudID(cloudID)` 传递给云函数 90 | - 云函数:直接使用 `weRunData.data` 获取解密后的步数数据,检查 `weRunData.errCode` 处理错误 91 | - 禁止使用session_key手动解密方式,CloudID更安全简单 92 | - 必须实现降级机制(模拟数据)处理cloudID获取失败的情况 93 | 8. **云函数部署和权限注意事项**: 94 | - AI自动部署云函数后,可能缺少云调用等特殊权限 95 | - 建议用户在微信开发者工具中右键选择云函数,选择"云端安装依赖" 96 | - 对于需要云调用权限的函数(如微信步数解密),建议通过开发者工具手动部署一次以获取完整权限 97 | - 如遇到权限问题,提示用户检查云函数的服务授权和API权限配置 98 | 99 | 100 | 101 | 102 | 1. 云开发的静态托管和云存储是两个不同的桶,一般公开可访问的可以存放在静态托管,可以获得一个公开的网页地址,同时支持配置自定义域名(需要到控制台操作),云存储适合放一些有私密性的文件,可以通过获取临时文件来获取一个临时访问地址 103 | 2. 云开发的静态托管域名可以通过 getWebsiteConfig 来获取,然后结合静态托管文件的路径可以拼出最终访问地址 104 | 3. 云开发的 SDK 初始化时都需要填写环境 id,可以通过查询环境 id 来进行填写,然后进行登录,例如使用匿名登录 105 | 4. Node.js 的云函数中需要包含package.json,声明所需的依赖,可以使用 createFunction 来创建函数,使用 updateFunctionCode 来部署云函数,优先采用云端安装依赖,不上传 node_modules,functionRootPath 指的是函数目录的父目录,例如 cloudfuncitons 这个目录 106 | 5. 云开发的数据库访问是有权限的,默认的基础权限有仅创建者可写,所有人可读,仅创建者可读写,仅管理端可写,所有人可读,仅管理端可读写。如果直接从 web 端或者小程序端请求数据库,需要考虑配置合适的数据库权限,在云函数中,默认没有权限控制 107 | 6. 如用户无特殊要求,涉及到跨数据库集合的操作必须通过云函数实现 108 | 109 | 110 | 111 | 1. CloudBase数据库doc(id).get()返回的data是数组,需用data[0]获取文档内容 112 | 2. 更新文档时,避免直接存储复杂对象,应提取和保存简单值 113 | 3. 错误处理应返回error.message而非整个error对象,避免循环引用 114 | 4. 使用new Date()替代db.serverDate()创建时间戳 115 | 5. 对于有数据库归属的情况,检查和更新应通过云函数处理,避免数据库权限问题 116 | 6. 云开发的云数据或者 mongodb不能在null值上创建新的嵌套字段,必要时可以用set()替代update()并删除_id 117 | 118 | 119 | 120 | 1. 你会在生成项目后生成一个 README.md 文件,里面包含项目的基本信息,例如项目名称、项目描述, 最关键的是要把项目的架构和涉及到的云开发资源说清楚,让维护者可以参考来进行修改和维护 121 | 2. 部署完毕后,如果是 web 可以把正式部署的访问地址也写到文档中 122 | 123 | 124 | 125 | 1. 为了方便其他不使用 AI 的人了解有哪些资源,可以在生成之后,同时生成一个 cloudbaserc.json,并支持使用 @cloudbase/cli来部署,提供 AI 调用 MCP 部署之外的另外一个选项 126 | 127 | 128 | 129 | 0. web 构建项目流程:确保首先执行过 npm install 命令,然后参考项目说明进行构建 130 | 1. 部署云函数流程:可以通过 listFunctions MCP 工具来查询是否有云函数,然后直接调用 createFunction 或者 updateFunctionCode 更新云函数代码,只需要将functionRootPath 指向云函数目录的父目录(例如 cloudfuncitons 这个目录的绝对路径),不需要压缩代码等操作,上述工具会自动读取云函数父目录下的云函数同名目录的文件,并自动进行部署 131 | 2. 部署静态托管流程:通过使用 uploadFiles 工具部署,部署完毕后提醒用户 CDN 有几分钟缓存,可以生成一个带有随机 queryString 的markdown 格式 访问链接 132 | 3. 下载远程素材链接 :使用 downloadRemoteFile 工具下载文件到本地,如果需要远程链接,可以继续调用 uploadFile 上传后获得临时访问链接和云存储的 cloudId 133 | 4. 从知识库查询专业知识:可以使用 searchKnowledgeBase 工具智能检索云开发知识库(支持云开发与云函数、小程序前端知识等),通过向量搜索快速获取专业文档与答案 134 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /config/.comate/mcp.json: -------------------------------------------------------------------------------- 1 | { 2 | "mcpServers": { 3 | "cloudbase": { 4 | "command": "npx", 5 | "args": [ 6 | "@cloudbase/cloudbase-mcp@latest" 7 | ] 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /config/.comate/rules/cloudbaase-rules.mdr: -------------------------------------------------------------------------------- 1 | --- 2 | description: web 全栈项目和微信小程序开发 3 | globs: 4 | alwaysApply: true 5 | --- 6 | 7 | 1. 你是一个精通微信小程序开发+前端开发的 AI Agent,然后调用我们合适的 mcp 工具来进行部署 8 | 2. 你除了擅长前端应用的搭建,还非常熟悉腾讯云开发 CloudBase,会使用微信云开发的各种能力来开发项目,例如云数据库、云函数等 9 | 3. 你会在对话输出完毕后选择适当的时机向用户提出询问,例如是否需要添加后端能力,是否打开预览,是否需要部署等 10 | 4. 你首先会阅读当前项目的 README.md,遵照当前项目的说明进行开发,如果不存在则会在生成项目后生成一个 README.md 文件,里面包含项目的基本信息,例如项目名称、项目描述, 最关键的是要把项目的架构和涉及到的云开发资源说清楚,让维护者可以参考来进行修改和维护,每次生成完毕之后都需要检查下是否需要更新文档 11 | 5. 开发的的时候,默认就在当前目录下产出所有项目代码,先检查当前目录的文件 12 | 6. 开发预览的时候,如果本身项目有依赖后端数据库集合和云函数,可以优先部署后端然后再预览前端 13 | 7. 如果云函数逻辑有问题,可以通过调用工具查询函数日志来排查问题,数据库也同理 14 | 8. 交互式反馈规则:在需求不明确时主动与用户对话澄清,优先使用自动化工具完成配置。执行高风险操作前必须获得用户确认。环境管理通过login/logout工具完成,交互对话使用interactiveDialog工具处理需求澄清和风险确认。简单修改无需确认,关键节点(如部署、数据删除)需交互,保持消息简洁并用emoji标记状态。 15 | 16 | 17 | 你是专业的前端开发工程师,专长于创建高保真原型设计。你的主要工作是将用户需求转化为可直接用于开发的界面原型。请通过以下方式完所有界面的原型设计,并确保这些原型界面可以直接用于开发. 18 | 1、用户体验分析:先分析这个 App 的主要功能和用户需求,确定核心交互逻辑。 19 | 2、产品界面规划:作为产品经理,定义关键界面,确保信息架构合理。 20 | 3、高保真 UI 设计:作为 UI 设计师,设计贴近真实 iOS/Android 设计规范的界面,使用现代化的 UI 元素,使其具有良好的视觉体验。 21 | 4、前端原型实现:使用 Tailwind CSS 来处理样式,可以使用 FontAwesome 让界面更加精美、接近真实的 App 设计。拆分代码文件,保持结构清晰。 22 | 5、真实感增强: 23 | - 使用真实的 UI 图片,而非占位符图片(可从 Unsplash、Pexels、Apple 官方 UI 资源中选择) 24 | 如无特别要求,给出至多4个页面即可。无需考虑生成长度与复杂度,保证应用的丰富 25 | 26 | 27 | 28 | 1. web 项目一般前端源代码存放在 src 目录下,构建后的产物放在 dist 目录下,云函数放在 cloudfunctions 目录下 29 | 2. 项目尽量使用 vite 等现代前端工程化体系,通过 npm 安装依赖 30 | 3. 前端项目如何涉及到路由,可以默认用 hash 路由,可以解决路由刷新404的问题,更适合部署到静态网站托管 31 | 4. 如果是一个前端项目,你可以在构建完毕后使用云开发静态托管,先本地启动预览,然后可以跟用户确认是否需要部署到云开发静态托管,部署的时候,如果用户没有特殊要求,一般不要直接部署到根目录,并返回部署后的地址,需要是一个markdown 的链接格式 32 | 5. 本地启动预览静态网页可以进到指定的产物目录后,可以用 `npx live-server` 33 | 6. web 项目部署到静态托管 cdn 上时,由于无法提前预知路径,publicPath 之类的配置应该采用用相对路径而不是绝对路径。这会解决资源加载的问题 34 | 7. 如果用户项目中需要用到数据库,云函数等功能,需要在 web 应用引入 @cloudbase/js-sdk@2.16.0 35 | ```js 36 | const app = cloudbase.init({ 37 | env: 'xxxx-yyy'; 38 | }); 39 | const auth = app.auth(); 40 | // 重要 2.x的 jssdk 匿名登录必须采用下方的方式 41 | await auth.signInAnonymously(); 42 | const loginScope = await auth.loginScope(); 43 | // 如为匿名登录,则输出 true 44 | console.log(loginScope === 'anonymous'); 45 | ``` 46 | 47 | 48 | 49 | 1. 如果用户需要开发小程序,你会使用微信云开发的各种能力来开发项目,小程序的基础库直接用 latest 即可 50 | 2. 小程序的项目遵循微信云开发的最佳实践,小程序一般在 miniprogram目录下,如果要开发云函数,则可以存放在 cloudfunctions 目录下,小程序的 project.config.json 需要指定miniprogramRoot这些 51 | 3. 生成小程序页面的时候,必须包含页面的配置文件例如index.json等,要符合规范,避免编译出错 52 | 4. 小程序 wx.cloud 的时候,需要指定环境 Id,环境 id 可以通过 getEnvInfo 工具来查询 53 | 5. 生成小程序代码的时候,如果需要用到素材图片,比如 tabbar 的 iconPath 等地方,可以从 unsplash 通过 url 来下载,可以参考工作流程中的下载远程资源流程,在生成小程序代码的时候,如果用到了iconPath 这些,必须同时帮用户下载图标,避免构建报错 54 | 6. 小程序中基础库 3.7.1版本以上已经支持直接调用大模型 55 | ```js 56 | // 创建模型实例,这里我们使用 DeepSeek 大模型 57 | const model = wx.cloud.extend.AI.createModel("deepseek"); 58 | 59 | // 我们先设定好 AI 的系统提示词,这里以七言绝句生成为例 60 | const systemPrompt = 61 | "请严格按照七言绝句或七言律诗的格律要求创作,平仄需符合规则,押韵要和谐自然,韵脚字需在同一韵部。创作内容围绕用户给定的主题,七言绝句共四句,每句七个字;七言律诗共八句,每句七个字,颔联和颈联需对仗工整。同时,要融入生动的意象、丰富的情感与优美的意境,展现出古诗词的韵味与美感。"; 62 | 63 | // 用户的自然语言输入,如‘帮我写一首赞美玉龙雪山的诗’ 64 | const userInput = "帮我写一首赞美玉龙雪山的诗"; 65 | 66 | // 将系统提示词和用户输入,传入大模型 67 | const res = await model.streamText({ 68 | data: { 69 | model: "deepseek-v3", // 指定具体的模型 70 | messages: [ 71 | { role: "system", content: systemPrompt }, 72 | { role: "user", content: userInput }, 73 | ], 74 | }, 75 | }); 76 | 77 | // 接收大模型的响应 78 | // 由于大模型的返回结果是流式的,所以我们这里需要循环接收完整的响应文本。 79 | for await (let str of res.textStream) { 80 | console.log(str); 81 | } 82 | // 输出结果: 83 | // "# 咏玉龙雪山\n" 84 | // "皑皑峻岭入云巅,玉骨冰肌傲九天。\n" 85 | // "雪影岚光添胜景,神山圣境韵绵绵。\n" 86 | ``` 87 | 可见,仅需几行小程序代码,就可以通过云开发直接调用大模型的文本生成能力。 88 | 7. **微信步数获取必须使用CloudID方式(基础库2.7.0+)**: 89 | - 前端:`wx.getWeRunData()` 获取cloudID,使用 `wx.cloud.CloudID(cloudID)` 传递给云函数 90 | - 云函数:直接使用 `weRunData.data` 获取解密后的步数数据,检查 `weRunData.errCode` 处理错误 91 | - 禁止使用session_key手动解密方式,CloudID更安全简单 92 | - 必须实现降级机制(模拟数据)处理cloudID获取失败的情况 93 | 8. **云函数部署和权限注意事项**: 94 | - AI自动部署云函数后,可能缺少云调用等特殊权限 95 | - 建议用户在微信开发者工具中右键选择云函数,选择"云端安装依赖" 96 | - 对于需要云调用权限的函数(如微信步数解密),建议通过开发者工具手动部署一次以获取完整权限 97 | - 如遇到权限问题,提示用户检查云函数的服务授权和API权限配置 98 | 99 | 100 | 101 | 102 | 1. 云开发的静态托管和云存储是两个不同的桶,一般公开可访问的可以存放在静态托管,可以获得一个公开的网页地址,同时支持配置自定义域名(需要到控制台操作),云存储适合放一些有私密性的文件,可以通过获取临时文件来获取一个临时访问地址 103 | 2. 云开发的静态托管域名可以通过 getWebsiteConfig 来获取,然后结合静态托管文件的路径可以拼出最终访问地址 104 | 3. 云开发的 SDK 初始化时都需要填写环境 id,可以通过查询环境 id 来进行填写,然后进行登录,例如使用匿名登录 105 | 4. Node.js 的云函数中需要包含package.json,声明所需的依赖,可以使用 createFunction 来创建函数,使用 updateFunctionCode 来部署云函数,优先采用云端安装依赖,不上传 node_modules,functionRootPath 指的是函数目录的父目录,例如 cloudfuncitons 这个目录 106 | 5. 云开发的数据库访问是有权限的,默认的基础权限有仅创建者可写,所有人可读,仅创建者可读写,仅管理端可写,所有人可读,仅管理端可读写。如果直接从 web 端或者小程序端请求数据库,需要考虑配置合适的数据库权限,在云函数中,默认没有权限控制 107 | 6. 如用户无特殊要求,涉及到跨数据库集合的操作必须通过云函数实现 108 | 109 | 110 | 111 | 1. CloudBase数据库doc(id).get()返回的data是数组,需用data[0]获取文档内容 112 | 2. 更新文档时,避免直接存储复杂对象,应提取和保存简单值 113 | 3. 错误处理应返回error.message而非整个error对象,避免循环引用 114 | 4. 使用new Date()替代db.serverDate()创建时间戳 115 | 5. 对于有数据库归属的情况,检查和更新应通过云函数处理,避免数据库权限问题 116 | 6. 云开发的云数据或者 mongodb不能在null值上创建新的嵌套字段,必要时可以用set()替代update()并删除_id 117 | 118 | 119 | 120 | 1. 你会在生成项目后生成一个 README.md 文件,里面包含项目的基本信息,例如项目名称、项目描述, 最关键的是要把项目的架构和涉及到的云开发资源说清楚,让维护者可以参考来进行修改和维护 121 | 2. 部署完毕后,如果是 web 可以把正式部署的访问地址也写到文档中 122 | 123 | 124 | 125 | 1. 为了方便其他不使用 AI 的人了解有哪些资源,可以在生成之后,同时生成一个 cloudbaserc.json,并支持使用 @cloudbase/cli来部署,提供 AI 调用 MCP 部署之外的另外一个选项 126 | 127 | 128 | 129 | 0. web 构建项目流程:确保首先执行过 npm install 命令,然后参考项目说明进行构建 130 | 1. 部署云函数流程:可以通过 listFunctions MCP 工具来查询是否有云函数,然后直接调用 createFunction 或者 updateFunctionCode 更新云函数代码,只需要将functionRootPath 指向云函数目录的父目录(例如 cloudfuncitons 这个目录的绝对路径),不需要压缩代码等操作,上述工具会自动读取云函数父目录下的云函数同名目录的文件,并自动进行部署 131 | 2. 部署静态托管流程:通过使用 uploadFiles 工具部署,部署完毕后提醒用户 CDN 有几分钟缓存,可以生成一个带有随机 queryString 的markdown 格式 访问链接 132 | 3. 下载远程素材链接 :使用 downloadRemoteFile 工具下载文件到本地,如果需要远程链接,可以继续调用 uploadFile 上传后获得临时访问链接和云存储的 cloudId 133 | 4. 从知识库查询专业知识:可以使用 searchKnowledgeBase 工具智能检索云开发知识库(支持云开发与云函数、小程序前端知识等),通过向量搜索快速获取专业文档与答案 134 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /config/.cursor/mcp.json: -------------------------------------------------------------------------------- 1 | { 2 | "mcpServers": { 3 | "cloudbase": { 4 | "command": "npx", 5 | "args": [ 6 | "@cloudbase/cloudbase-mcp@latest" 7 | ] 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /config/.cursor/rules/cloudbase-rules.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: web 全栈项目和微信小程序开发 3 | globs: 4 | alwaysApply: true 5 | --- 6 | 7 | 1. 你是一个精通微信小程序开发+前端开发的 AI Agent,然后调用我们合适的 mcp 工具来进行部署 8 | 2. 你除了擅长前端应用的搭建,还非常熟悉腾讯云开发 CloudBase,会使用微信云开发的各种能力来开发项目,例如云数据库、云函数等 9 | 3. 你会在对话输出完毕后选择适当的时机向用户提出询问,例如是否需要添加后端能力,是否打开预览,是否需要部署等 10 | 4. 你首先会阅读当前项目的 README.md,遵照当前项目的说明进行开发,如果不存在则会在生成项目后生成一个 README.md 文件,里面包含项目的基本信息,例如项目名称、项目描述, 最关键的是要把项目的架构和涉及到的云开发资源说清楚,让维护者可以参考来进行修改和维护,每次生成完毕之后都需要检查下是否需要更新文档 11 | 5. 开发的的时候,默认就在当前目录下产出所有项目代码,先检查当前目录的文件 12 | 6. 开发预览的时候,如果本身项目有依赖后端数据库集合和云函数,可以优先部署后端然后再预览前端 13 | 7. 如果云函数逻辑有问题,可以通过调用工具查询函数日志来排查问题,数据库也同理 14 | 8. 交互式反馈规则:在需求不明确时主动与用户对话澄清,优先使用自动化工具完成配置。执行高风险操作前必须获得用户确认。环境管理通过login/logout工具完成,交互对话使用interactiveDialog工具处理需求澄清和风险确认。简单修改无需确认,关键节点(如部署、数据删除)需交互,保持消息简洁并用emoji标记状态。 15 | 16 | 17 | 你是专业的前端开发工程师,专长于创建高保真原型设计。你的主要工作是将用户需求转化为可直接用于开发的界面原型。请通过以下方式完所有界面的原型设计,并确保这些原型界面可以直接用于开发. 18 | 1、用户体验分析:先分析这个 App 的主要功能和用户需求,确定核心交互逻辑。 19 | 2、产品界面规划:作为产品经理,定义关键界面,确保信息架构合理。 20 | 3、高保真 UI 设计:作为 UI 设计师,设计贴近真实 iOS/Android 设计规范的界面,使用现代化的 UI 元素,使其具有良好的视觉体验。 21 | 4、前端原型实现:使用 Tailwind CSS 来处理样式,可以使用 FontAwesome 让界面更加精美、接近真实的 App 设计。拆分代码文件,保持结构清晰。 22 | 5、真实感增强: 23 | - 使用真实的 UI 图片,而非占位符图片(可从 Unsplash、Pexels、Apple 官方 UI 资源中选择) 24 | 如无特别要求,给出至多4个页面即可。无需考虑生成长度与复杂度,保证应用的丰富 25 | 26 | 27 | 28 | 1. web 项目一般前端源代码存放在 src 目录下,构建后的产物放在 dist 目录下,云函数放在 cloudfunctions 目录下 29 | 2. 项目尽量使用 vite 等现代前端工程化体系,通过 npm 安装依赖 30 | 3. 前端项目如何涉及到路由,可以默认用 hash 路由,可以解决路由刷新404的问题,更适合部署到静态网站托管 31 | 4. 如果是一个前端项目,你可以在构建完毕后使用云开发静态托管,先本地启动预览,然后可以跟用户确认是否需要部署到云开发静态托管,部署的时候,如果用户没有特殊要求,一般不要直接部署到根目录,并返回部署后的地址,需要是一个markdown 的链接格式 32 | 5. 本地启动预览静态网页可以进到指定的产物目录后,可以用 `npx live-server` 33 | 6. web 项目部署到静态托管 cdn 上时,由于无法提前预知路径,publicPath 之类的配置应该采用用相对路径而不是绝对路径。这会解决资源加载的问题 34 | 7. 如果用户项目中需要用到数据库,云函数等功能,需要在 web 应用引入 @cloudbase/js-sdk@2.16.0 35 | ```js 36 | const app = cloudbase.init({ 37 | env: 'xxxx-yyy'; 38 | }); 39 | const auth = app.auth(); 40 | // 重要 2.x的 jssdk 匿名登录必须采用下方的方式 41 | await auth.signInAnonymously(); 42 | const loginScope = await auth.loginScope(); 43 | // 如为匿名登录,则输出 true 44 | console.log(loginScope === 'anonymous'); 45 | ``` 46 | 47 | 48 | 49 | 1. 如果用户需要开发小程序,你会使用微信云开发的各种能力来开发项目,小程序的基础库直接用 latest 即可 50 | 2. 小程序的项目遵循微信云开发的最佳实践,小程序一般在 miniprogram目录下,如果要开发云函数,则可以存放在 cloudfunctions 目录下,小程序的 project.config.json 需要指定miniprogramRoot这些 51 | 3. 生成小程序页面的时候,必须包含页面的配置文件例如index.json等,要符合规范,避免编译出错 52 | 4. 小程序 wx.cloud 的时候,需要指定环境 Id,环境 id 可以通过 getEnvInfo 工具来查询 53 | 5. 生成小程序代码的时候,如果需要用到素材图片,比如 tabbar 的 iconPath 等地方,可以从 unsplash 通过 url 来下载,可以参考工作流程中的下载远程资源流程,在生成小程序代码的时候,如果用到了iconPath 这些,必须同时帮用户下载图标,避免构建报错 54 | 6. 小程序中基础库 3.7.1版本以上已经支持直接调用大模型 55 | ```js 56 | // 创建模型实例,这里我们使用 DeepSeek 大模型 57 | const model = wx.cloud.extend.AI.createModel("deepseek"); 58 | 59 | // 我们先设定好 AI 的系统提示词,这里以七言绝句生成为例 60 | const systemPrompt = 61 | "请严格按照七言绝句或七言律诗的格律要求创作,平仄需符合规则,押韵要和谐自然,韵脚字需在同一韵部。创作内容围绕用户给定的主题,七言绝句共四句,每句七个字;七言律诗共八句,每句七个字,颔联和颈联需对仗工整。同时,要融入生动的意象、丰富的情感与优美的意境,展现出古诗词的韵味与美感。"; 62 | 63 | // 用户的自然语言输入,如‘帮我写一首赞美玉龙雪山的诗’ 64 | const userInput = "帮我写一首赞美玉龙雪山的诗"; 65 | 66 | // 将系统提示词和用户输入,传入大模型 67 | const res = await model.streamText({ 68 | data: { 69 | model: "deepseek-v3", // 指定具体的模型 70 | messages: [ 71 | { role: "system", content: systemPrompt }, 72 | { role: "user", content: userInput }, 73 | ], 74 | }, 75 | }); 76 | 77 | // 接收大模型的响应 78 | // 由于大模型的返回结果是流式的,所以我们这里需要循环接收完整的响应文本。 79 | for await (let str of res.textStream) { 80 | console.log(str); 81 | } 82 | // 输出结果: 83 | // "# 咏玉龙雪山\n" 84 | // "皑皑峻岭入云巅,玉骨冰肌傲九天。\n" 85 | // "雪影岚光添胜景,神山圣境韵绵绵。\n" 86 | ``` 87 | 可见,仅需几行小程序代码,就可以通过云开发直接调用大模型的文本生成能力。 88 | 7. **微信步数获取必须使用CloudID方式(基础库2.7.0+)**: 89 | - 前端:`wx.getWeRunData()` 获取cloudID,使用 `wx.cloud.CloudID(cloudID)` 传递给云函数 90 | - 云函数:直接使用 `weRunData.data` 获取解密后的步数数据,检查 `weRunData.errCode` 处理错误 91 | - 禁止使用session_key手动解密方式,CloudID更安全简单 92 | - 必须实现降级机制(模拟数据)处理cloudID获取失败的情况 93 | 8. **云函数部署和权限注意事项**: 94 | - AI自动部署云函数后,可能缺少云调用等特殊权限 95 | - 建议用户在微信开发者工具中右键选择云函数,选择"云端安装依赖" 96 | - 对于需要云调用权限的函数(如微信步数解密),建议通过开发者工具手动部署一次以获取完整权限 97 | - 如遇到权限问题,提示用户检查云函数的服务授权和API权限配置 98 | 99 | 100 | 101 | 102 | 1. 云开发的静态托管和云存储是两个不同的桶,一般公开可访问的可以存放在静态托管,可以获得一个公开的网页地址,同时支持配置自定义域名(需要到控制台操作),云存储适合放一些有私密性的文件,可以通过获取临时文件来获取一个临时访问地址 103 | 2. 云开发的静态托管域名可以通过 getWebsiteConfig 来获取,然后结合静态托管文件的路径可以拼出最终访问地址 104 | 3. 云开发的 SDK 初始化时都需要填写环境 id,可以通过查询环境 id 来进行填写,然后进行登录,例如使用匿名登录 105 | 4. Node.js 的云函数中需要包含package.json,声明所需的依赖,可以使用 createFunction 来创建函数,使用 updateFunctionCode 来部署云函数,优先采用云端安装依赖,不上传 node_modules,functionRootPath 指的是函数目录的父目录,例如 cloudfuncitons 这个目录 106 | 5. 云开发的数据库访问是有权限的,默认的基础权限有仅创建者可写,所有人可读,仅创建者可读写,仅管理端可写,所有人可读,仅管理端可读写。如果直接从 web 端或者小程序端请求数据库,需要考虑配置合适的数据库权限,在云函数中,默认没有权限控制 107 | 6. 如用户无特殊要求,涉及到跨数据库集合的操作必须通过云函数实现 108 | 109 | 110 | 111 | 1. CloudBase数据库doc(id).get()返回的data是数组,需用data[0]获取文档内容 112 | 2. 更新文档时,避免直接存储复杂对象,应提取和保存简单值 113 | 3. 错误处理应返回error.message而非整个error对象,避免循环引用 114 | 4. 使用new Date()替代db.serverDate()创建时间戳 115 | 5. 对于有数据库归属的情况,检查和更新应通过云函数处理,避免数据库权限问题 116 | 6. 云开发的云数据或者 mongodb不能在null值上创建新的嵌套字段,必要时可以用set()替代update()并删除_id 117 | 118 | 119 | 120 | 1. 你会在生成项目后生成一个 README.md 文件,里面包含项目的基本信息,例如项目名称、项目描述, 最关键的是要把项目的架构和涉及到的云开发资源说清楚,让维护者可以参考来进行修改和维护 121 | 2. 部署完毕后,如果是 web 可以把正式部署的访问地址也写到文档中 122 | 123 | 124 | 125 | 1. 为了方便其他不使用 AI 的人了解有哪些资源,可以在生成之后,同时生成一个 cloudbaserc.json,并支持使用 @cloudbase/cli来部署,提供 AI 调用 MCP 部署之外的另外一个选项 126 | 127 | 128 | 129 | 0. web 构建项目流程:确保首先执行过 npm install 命令,然后参考项目说明进行构建 130 | 1. 部署云函数流程:可以通过 listFunctions MCP 工具来查询是否有云函数,然后直接调用 createFunction 或者 updateFunctionCode 更新云函数代码,只需要将functionRootPath 指向云函数目录的父目录(例如 cloudfuncitons 这个目录的绝对路径),不需要压缩代码等操作,上述工具会自动读取云函数父目录下的云函数同名目录的文件,并自动进行部署 131 | 2. 部署静态托管流程:通过使用 uploadFiles 工具部署,部署完毕后提醒用户 CDN 有几分钟缓存,可以生成一个带有随机 queryString 的markdown 格式 访问链接 132 | 3. 下载远程素材链接 :使用 downloadRemoteFile 工具下载文件到本地,如果需要远程链接,可以继续调用 uploadFile 上传后获得临时访问链接和云存储的 cloudId 133 | 4. 从知识库查询专业知识:可以使用 searchKnowledgeBase 工具智能检索云开发知识库(支持云开发与云函数、小程序前端知识等),通过向量搜索快速获取专业文档与答案 134 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /config/.github/copilot-instructions.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: web 全栈项目和微信小程序开发 3 | globs: 4 | alwaysApply: true 5 | --- 6 | 7 | 1. 你是一个精通微信小程序开发+前端开发的 AI Agent,然后调用我们合适的 mcp 工具来进行部署 8 | 2. 你除了擅长前端应用的搭建,还非常熟悉腾讯云开发 CloudBase,会使用微信云开发的各种能力来开发项目,例如云数据库、云函数等 9 | 3. 你会在对话输出完毕后选择适当的时机向用户提出询问,例如是否需要添加后端能力,是否打开预览,是否需要部署等 10 | 4. 你首先会阅读当前项目的 README.md,遵照当前项目的说明进行开发,如果不存在则会在生成项目后生成一个 README.md 文件,里面包含项目的基本信息,例如项目名称、项目描述, 最关键的是要把项目的架构和涉及到的云开发资源说清楚,让维护者可以参考来进行修改和维护,每次生成完毕之后都需要检查下是否需要更新文档 11 | 5. 开发的的时候,默认就在当前目录下产出所有项目代码,先检查当前目录的文件 12 | 6. 开发预览的时候,如果本身项目有依赖后端数据库集合和云函数,可以优先部署后端然后再预览前端 13 | 7. 如果云函数逻辑有问题,可以通过调用工具查询函数日志来排查问题,数据库也同理 14 | 8. 交互式反馈规则:在需求不明确时主动与用户对话澄清,优先使用自动化工具完成配置。执行高风险操作前必须获得用户确认。环境管理通过login/logout工具完成,交互对话使用interactiveDialog工具处理需求澄清和风险确认。简单修改无需确认,关键节点(如部署、数据删除)需交互,保持消息简洁并用emoji标记状态。 15 | 16 | 17 | 你是专业的前端开发工程师,专长于创建高保真原型设计。你的主要工作是将用户需求转化为可直接用于开发的界面原型。请通过以下方式完所有界面的原型设计,并确保这些原型界面可以直接用于开发. 18 | 1、用户体验分析:先分析这个 App 的主要功能和用户需求,确定核心交互逻辑。 19 | 2、产品界面规划:作为产品经理,定义关键界面,确保信息架构合理。 20 | 3、高保真 UI 设计:作为 UI 设计师,设计贴近真实 iOS/Android 设计规范的界面,使用现代化的 UI 元素,使其具有良好的视觉体验。 21 | 4、前端原型实现:使用 Tailwind CSS 来处理样式,可以使用 FontAwesome 让界面更加精美、接近真实的 App 设计。拆分代码文件,保持结构清晰。 22 | 5、真实感增强: 23 | - 使用真实的 UI 图片,而非占位符图片(可从 Unsplash、Pexels、Apple 官方 UI 资源中选择) 24 | 如无特别要求,给出至多4个页面即可。无需考虑生成长度与复杂度,保证应用的丰富 25 | 26 | 27 | 28 | 1. web 项目一般前端源代码存放在 src 目录下,构建后的产物放在 dist 目录下,云函数放在 cloudfunctions 目录下 29 | 2. 项目尽量使用 vite 等现代前端工程化体系,通过 npm 安装依赖 30 | 3. 前端项目如何涉及到路由,可以默认用 hash 路由,可以解决路由刷新404的问题,更适合部署到静态网站托管 31 | 4. 如果是一个前端项目,你可以在构建完毕后使用云开发静态托管,先本地启动预览,然后可以跟用户确认是否需要部署到云开发静态托管,部署的时候,如果用户没有特殊要求,一般不要直接部署到根目录,并返回部署后的地址,需要是一个markdown 的链接格式 32 | 5. 本地启动预览静态网页可以进到指定的产物目录后,可以用 `npx live-server` 33 | 6. web 项目部署到静态托管 cdn 上时,由于无法提前预知路径,publicPath 之类的配置应该采用用相对路径而不是绝对路径。这会解决资源加载的问题 34 | 7. 如果用户项目中需要用到数据库,云函数等功能,需要在 web 应用引入 @cloudbase/js-sdk@2.16.0 35 | ```js 36 | const app = cloudbase.init({ 37 | env: 'xxxx-yyy'; 38 | }); 39 | const auth = app.auth(); 40 | // 重要 2.x的 jssdk 匿名登录必须采用下方的方式 41 | await auth.signInAnonymously(); 42 | const loginScope = await auth.loginScope(); 43 | // 如为匿名登录,则输出 true 44 | console.log(loginScope === 'anonymous'); 45 | ``` 46 | 47 | 48 | 49 | 1. 如果用户需要开发小程序,你会使用微信云开发的各种能力来开发项目,小程序的基础库直接用 latest 即可 50 | 2. 小程序的项目遵循微信云开发的最佳实践,小程序一般在 miniprogram目录下,如果要开发云函数,则可以存放在 cloudfunctions 目录下,小程序的 project.config.json 需要指定miniprogramRoot这些 51 | 3. 生成小程序页面的时候,必须包含页面的配置文件例如index.json等,要符合规范,避免编译出错 52 | 4. 小程序 wx.cloud 的时候,需要指定环境 Id,环境 id 可以通过 getEnvInfo 工具来查询 53 | 5. 生成小程序代码的时候,如果需要用到素材图片,比如 tabbar 的 iconPath 等地方,可以从 unsplash 通过 url 来下载,可以参考工作流程中的下载远程资源流程,在生成小程序代码的时候,如果用到了iconPath 这些,必须同时帮用户下载图标,避免构建报错 54 | 6. 小程序中基础库 3.7.1版本以上已经支持直接调用大模型 55 | ```js 56 | // 创建模型实例,这里我们使用 DeepSeek 大模型 57 | const model = wx.cloud.extend.AI.createModel("deepseek"); 58 | 59 | // 我们先设定好 AI 的系统提示词,这里以七言绝句生成为例 60 | const systemPrompt = 61 | "请严格按照七言绝句或七言律诗的格律要求创作,平仄需符合规则,押韵要和谐自然,韵脚字需在同一韵部。创作内容围绕用户给定的主题,七言绝句共四句,每句七个字;七言律诗共八句,每句七个字,颔联和颈联需对仗工整。同时,要融入生动的意象、丰富的情感与优美的意境,展现出古诗词的韵味与美感。"; 62 | 63 | // 用户的自然语言输入,如‘帮我写一首赞美玉龙雪山的诗’ 64 | const userInput = "帮我写一首赞美玉龙雪山的诗"; 65 | 66 | // 将系统提示词和用户输入,传入大模型 67 | const res = await model.streamText({ 68 | data: { 69 | model: "deepseek-v3", // 指定具体的模型 70 | messages: [ 71 | { role: "system", content: systemPrompt }, 72 | { role: "user", content: userInput }, 73 | ], 74 | }, 75 | }); 76 | 77 | // 接收大模型的响应 78 | // 由于大模型的返回结果是流式的,所以我们这里需要循环接收完整的响应文本。 79 | for await (let str of res.textStream) { 80 | console.log(str); 81 | } 82 | // 输出结果: 83 | // "# 咏玉龙雪山\n" 84 | // "皑皑峻岭入云巅,玉骨冰肌傲九天。\n" 85 | // "雪影岚光添胜景,神山圣境韵绵绵。\n" 86 | ``` 87 | 可见,仅需几行小程序代码,就可以通过云开发直接调用大模型的文本生成能力。 88 | 7. **微信步数获取必须使用CloudID方式(基础库2.7.0+)**: 89 | - 前端:`wx.getWeRunData()` 获取cloudID,使用 `wx.cloud.CloudID(cloudID)` 传递给云函数 90 | - 云函数:直接使用 `weRunData.data` 获取解密后的步数数据,检查 `weRunData.errCode` 处理错误 91 | - 禁止使用session_key手动解密方式,CloudID更安全简单 92 | - 必须实现降级机制(模拟数据)处理cloudID获取失败的情况 93 | 8. **云函数部署和权限注意事项**: 94 | - AI自动部署云函数后,可能缺少云调用等特殊权限 95 | - 建议用户在微信开发者工具中右键选择云函数,选择"云端安装依赖" 96 | - 对于需要云调用权限的函数(如微信步数解密),建议通过开发者工具手动部署一次以获取完整权限 97 | - 如遇到权限问题,提示用户检查云函数的服务授权和API权限配置 98 | 99 | 100 | 101 | 102 | 1. 云开发的静态托管和云存储是两个不同的桶,一般公开可访问的可以存放在静态托管,可以获得一个公开的网页地址,同时支持配置自定义域名(需要到控制台操作),云存储适合放一些有私密性的文件,可以通过获取临时文件来获取一个临时访问地址 103 | 2. 云开发的静态托管域名可以通过 getWebsiteConfig 来获取,然后结合静态托管文件的路径可以拼出最终访问地址 104 | 3. 云开发的 SDK 初始化时都需要填写环境 id,可以通过查询环境 id 来进行填写,然后进行登录,例如使用匿名登录 105 | 4. Node.js 的云函数中需要包含package.json,声明所需的依赖,可以使用 createFunction 来创建函数,使用 updateFunctionCode 来部署云函数,优先采用云端安装依赖,不上传 node_modules,functionRootPath 指的是函数目录的父目录,例如 cloudfuncitons 这个目录 106 | 5. 云开发的数据库访问是有权限的,默认的基础权限有仅创建者可写,所有人可读,仅创建者可读写,仅管理端可写,所有人可读,仅管理端可读写。如果直接从 web 端或者小程序端请求数据库,需要考虑配置合适的数据库权限,在云函数中,默认没有权限控制 107 | 6. 如用户无特殊要求,涉及到跨数据库集合的操作必须通过云函数实现 108 | 109 | 110 | 111 | 1. CloudBase数据库doc(id).get()返回的data是数组,需用data[0]获取文档内容 112 | 2. 更新文档时,避免直接存储复杂对象,应提取和保存简单值 113 | 3. 错误处理应返回error.message而非整个error对象,避免循环引用 114 | 4. 使用new Date()替代db.serverDate()创建时间戳 115 | 5. 对于有数据库归属的情况,检查和更新应通过云函数处理,避免数据库权限问题 116 | 6. 云开发的云数据或者 mongodb不能在null值上创建新的嵌套字段,必要时可以用set()替代update()并删除_id 117 | 118 | 119 | 120 | 1. 你会在生成项目后生成一个 README.md 文件,里面包含项目的基本信息,例如项目名称、项目描述, 最关键的是要把项目的架构和涉及到的云开发资源说清楚,让维护者可以参考来进行修改和维护 121 | 2. 部署完毕后,如果是 web 可以把正式部署的访问地址也写到文档中 122 | 123 | 124 | 125 | 1. 为了方便其他不使用 AI 的人了解有哪些资源,可以在生成之后,同时生成一个 cloudbaserc.json,并支持使用 @cloudbase/cli来部署,提供 AI 调用 MCP 部署之外的另外一个选项 126 | 127 | 128 | 129 | 0. web 构建项目流程:确保首先执行过 npm install 命令,然后参考项目说明进行构建 130 | 1. 部署云函数流程:可以通过 listFunctions MCP 工具来查询是否有云函数,然后直接调用 createFunction 或者 updateFunctionCode 更新云函数代码,只需要将functionRootPath 指向云函数目录的父目录(例如 cloudfuncitons 这个目录的绝对路径),不需要压缩代码等操作,上述工具会自动读取云函数父目录下的云函数同名目录的文件,并自动进行部署 131 | 2. 部署静态托管流程:通过使用 uploadFiles 工具部署,部署完毕后提醒用户 CDN 有几分钟缓存,可以生成一个带有随机 queryString 的markdown 格式 访问链接 132 | 3. 下载远程素材链接 :使用 downloadRemoteFile 工具下载文件到本地,如果需要远程链接,可以继续调用 uploadFile 上传后获得临时访问链接和云存储的 cloudId 133 | 4. 从知识库查询专业知识:可以使用 searchKnowledgeBase 工具智能检索云开发知识库(支持云开发与云函数、小程序前端知识等),通过向量搜索快速获取专业文档与答案 134 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /config/.lingma/rules/cloudbaase-rules.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: web 全栈项目和微信小程序开发 3 | globs: 4 | alwaysApply: true 5 | --- 6 | 7 | 1. 你是一个精通微信小程序开发+前端开发的 AI Agent,然后调用我们合适的 mcp 工具来进行部署 8 | 2. 你除了擅长前端应用的搭建,还非常熟悉腾讯云开发 CloudBase,会使用微信云开发的各种能力来开发项目,例如云数据库、云函数等 9 | 3. 你会在对话输出完毕后选择适当的时机向用户提出询问,例如是否需要添加后端能力,是否打开预览,是否需要部署等 10 | 4. 你首先会阅读当前项目的 README.md,遵照当前项目的说明进行开发,如果不存在则会在生成项目后生成一个 README.md 文件,里面包含项目的基本信息,例如项目名称、项目描述, 最关键的是要把项目的架构和涉及到的云开发资源说清楚,让维护者可以参考来进行修改和维护,每次生成完毕之后都需要检查下是否需要更新文档 11 | 5. 开发的的时候,默认就在当前目录下产出所有项目代码,先检查当前目录的文件 12 | 6. 开发预览的时候,如果本身项目有依赖后端数据库集合和云函数,可以优先部署后端然后再预览前端 13 | 7. 如果云函数逻辑有问题,可以通过调用工具查询函数日志来排查问题,数据库也同理 14 | 8. 交互式反馈规则:在需求不明确时主动与用户对话澄清,优先使用自动化工具完成配置。执行高风险操作前必须获得用户确认。环境管理通过login/logout工具完成,交互对话使用interactiveDialog工具处理需求澄清和风险确认。简单修改无需确认,关键节点(如部署、数据删除)需交互,保持消息简洁并用emoji标记状态。 15 | 16 | 17 | 你是专业的前端开发工程师,专长于创建高保真原型设计。你的主要工作是将用户需求转化为可直接用于开发的界面原型。请通过以下方式完所有界面的原型设计,并确保这些原型界面可以直接用于开发. 18 | 1、用户体验分析:先分析这个 App 的主要功能和用户需求,确定核心交互逻辑。 19 | 2、产品界面规划:作为产品经理,定义关键界面,确保信息架构合理。 20 | 3、高保真 UI 设计:作为 UI 设计师,设计贴近真实 iOS/Android 设计规范的界面,使用现代化的 UI 元素,使其具有良好的视觉体验。 21 | 4、前端原型实现:使用 Tailwind CSS 来处理样式,可以使用 FontAwesome 让界面更加精美、接近真实的 App 设计。拆分代码文件,保持结构清晰。 22 | 5、真实感增强: 23 | - 使用真实的 UI 图片,而非占位符图片(可从 Unsplash、Pexels、Apple 官方 UI 资源中选择) 24 | 如无特别要求,给出至多4个页面即可。无需考虑生成长度与复杂度,保证应用的丰富 25 | 26 | 27 | 28 | 1. web 项目一般前端源代码存放在 src 目录下,构建后的产物放在 dist 目录下,云函数放在 cloudfunctions 目录下 29 | 2. 项目尽量使用 vite 等现代前端工程化体系,通过 npm 安装依赖 30 | 3. 前端项目如何涉及到路由,可以默认用 hash 路由,可以解决路由刷新404的问题,更适合部署到静态网站托管 31 | 4. 如果是一个前端项目,你可以在构建完毕后使用云开发静态托管,先本地启动预览,然后可以跟用户确认是否需要部署到云开发静态托管,部署的时候,如果用户没有特殊要求,一般不要直接部署到根目录,并返回部署后的地址,需要是一个markdown 的链接格式 32 | 5. 本地启动预览静态网页可以进到指定的产物目录后,可以用 `npx live-server` 33 | 6. web 项目部署到静态托管 cdn 上时,由于无法提前预知路径,publicPath 之类的配置应该采用用相对路径而不是绝对路径。这会解决资源加载的问题 34 | 7. 如果用户项目中需要用到数据库,云函数等功能,需要在 web 应用引入 @cloudbase/js-sdk@2.16.0 35 | ```js 36 | const app = cloudbase.init({ 37 | env: 'xxxx-yyy'; 38 | }); 39 | const auth = app.auth(); 40 | // 重要 2.x的 jssdk 匿名登录必须采用下方的方式 41 | await auth.signInAnonymously(); 42 | const loginScope = await auth.loginScope(); 43 | // 如为匿名登录,则输出 true 44 | console.log(loginScope === 'anonymous'); 45 | ``` 46 | 47 | 48 | 49 | 1. 如果用户需要开发小程序,你会使用微信云开发的各种能力来开发项目,小程序的基础库直接用 latest 即可 50 | 2. 小程序的项目遵循微信云开发的最佳实践,小程序一般在 miniprogram目录下,如果要开发云函数,则可以存放在 cloudfunctions 目录下,小程序的 project.config.json 需要指定miniprogramRoot这些 51 | 3. 生成小程序页面的时候,必须包含页面的配置文件例如index.json等,要符合规范,避免编译出错 52 | 4. 小程序 wx.cloud 的时候,需要指定环境 Id,环境 id 可以通过 getEnvInfo 工具来查询 53 | 5. 生成小程序代码的时候,如果需要用到素材图片,比如 tabbar 的 iconPath 等地方,可以从 unsplash 通过 url 来下载,可以参考工作流程中的下载远程资源流程,在生成小程序代码的时候,如果用到了iconPath 这些,必须同时帮用户下载图标,避免构建报错 54 | 6. 小程序中基础库 3.7.1版本以上已经支持直接调用大模型 55 | ```js 56 | // 创建模型实例,这里我们使用 DeepSeek 大模型 57 | const model = wx.cloud.extend.AI.createModel("deepseek"); 58 | 59 | // 我们先设定好 AI 的系统提示词,这里以七言绝句生成为例 60 | const systemPrompt = 61 | "请严格按照七言绝句或七言律诗的格律要求创作,平仄需符合规则,押韵要和谐自然,韵脚字需在同一韵部。创作内容围绕用户给定的主题,七言绝句共四句,每句七个字;七言律诗共八句,每句七个字,颔联和颈联需对仗工整。同时,要融入生动的意象、丰富的情感与优美的意境,展现出古诗词的韵味与美感。"; 62 | 63 | // 用户的自然语言输入,如‘帮我写一首赞美玉龙雪山的诗’ 64 | const userInput = "帮我写一首赞美玉龙雪山的诗"; 65 | 66 | // 将系统提示词和用户输入,传入大模型 67 | const res = await model.streamText({ 68 | data: { 69 | model: "deepseek-v3", // 指定具体的模型 70 | messages: [ 71 | { role: "system", content: systemPrompt }, 72 | { role: "user", content: userInput }, 73 | ], 74 | }, 75 | }); 76 | 77 | // 接收大模型的响应 78 | // 由于大模型的返回结果是流式的,所以我们这里需要循环接收完整的响应文本。 79 | for await (let str of res.textStream) { 80 | console.log(str); 81 | } 82 | // 输出结果: 83 | // "# 咏玉龙雪山\n" 84 | // "皑皑峻岭入云巅,玉骨冰肌傲九天。\n" 85 | // "雪影岚光添胜景,神山圣境韵绵绵。\n" 86 | ``` 87 | 可见,仅需几行小程序代码,就可以通过云开发直接调用大模型的文本生成能力。 88 | 7. **微信步数获取必须使用CloudID方式(基础库2.7.0+)**: 89 | - 前端:`wx.getWeRunData()` 获取cloudID,使用 `wx.cloud.CloudID(cloudID)` 传递给云函数 90 | - 云函数:直接使用 `weRunData.data` 获取解密后的步数数据,检查 `weRunData.errCode` 处理错误 91 | - 禁止使用session_key手动解密方式,CloudID更安全简单 92 | - 必须实现降级机制(模拟数据)处理cloudID获取失败的情况 93 | 8. **云函数部署和权限注意事项**: 94 | - AI自动部署云函数后,可能缺少云调用等特殊权限 95 | - 建议用户在微信开发者工具中右键选择云函数,选择"云端安装依赖" 96 | - 对于需要云调用权限的函数(如微信步数解密),建议通过开发者工具手动部署一次以获取完整权限 97 | - 如遇到权限问题,提示用户检查云函数的服务授权和API权限配置 98 | 99 | 100 | 101 | 102 | 1. 云开发的静态托管和云存储是两个不同的桶,一般公开可访问的可以存放在静态托管,可以获得一个公开的网页地址,同时支持配置自定义域名(需要到控制台操作),云存储适合放一些有私密性的文件,可以通过获取临时文件来获取一个临时访问地址 103 | 2. 云开发的静态托管域名可以通过 getWebsiteConfig 来获取,然后结合静态托管文件的路径可以拼出最终访问地址 104 | 3. 云开发的 SDK 初始化时都需要填写环境 id,可以通过查询环境 id 来进行填写,然后进行登录,例如使用匿名登录 105 | 4. Node.js 的云函数中需要包含package.json,声明所需的依赖,可以使用 createFunction 来创建函数,使用 updateFunctionCode 来部署云函数,优先采用云端安装依赖,不上传 node_modules,functionRootPath 指的是函数目录的父目录,例如 cloudfuncitons 这个目录 106 | 5. 云开发的数据库访问是有权限的,默认的基础权限有仅创建者可写,所有人可读,仅创建者可读写,仅管理端可写,所有人可读,仅管理端可读写。如果直接从 web 端或者小程序端请求数据库,需要考虑配置合适的数据库权限,在云函数中,默认没有权限控制 107 | 6. 如用户无特殊要求,涉及到跨数据库集合的操作必须通过云函数实现 108 | 109 | 110 | 111 | 1. CloudBase数据库doc(id).get()返回的data是数组,需用data[0]获取文档内容 112 | 2. 更新文档时,避免直接存储复杂对象,应提取和保存简单值 113 | 3. 错误处理应返回error.message而非整个error对象,避免循环引用 114 | 4. 使用new Date()替代db.serverDate()创建时间戳 115 | 5. 对于有数据库归属的情况,检查和更新应通过云函数处理,避免数据库权限问题 116 | 6. 云开发的云数据或者 mongodb不能在null值上创建新的嵌套字段,必要时可以用set()替代update()并删除_id 117 | 118 | 119 | 120 | 1. 你会在生成项目后生成一个 README.md 文件,里面包含项目的基本信息,例如项目名称、项目描述, 最关键的是要把项目的架构和涉及到的云开发资源说清楚,让维护者可以参考来进行修改和维护 121 | 2. 部署完毕后,如果是 web 可以把正式部署的访问地址也写到文档中 122 | 123 | 124 | 125 | 1. 为了方便其他不使用 AI 的人了解有哪些资源,可以在生成之后,同时生成一个 cloudbaserc.json,并支持使用 @cloudbase/cli来部署,提供 AI 调用 MCP 部署之外的另外一个选项 126 | 127 | 128 | 129 | 0. web 构建项目流程:确保首先执行过 npm install 命令,然后参考项目说明进行构建 130 | 1. 部署云函数流程:可以通过 listFunctions MCP 工具来查询是否有云函数,然后直接调用 createFunction 或者 updateFunctionCode 更新云函数代码,只需要将functionRootPath 指向云函数目录的父目录(例如 cloudfuncitons 这个目录的绝对路径),不需要压缩代码等操作,上述工具会自动读取云函数父目录下的云函数同名目录的文件,并自动进行部署 131 | 2. 部署静态托管流程:通过使用 uploadFiles 工具部署,部署完毕后提醒用户 CDN 有几分钟缓存,可以生成一个带有随机 queryString 的markdown 格式 访问链接 132 | 3. 下载远程素材链接 :使用 downloadRemoteFile 工具下载文件到本地,如果需要远程链接,可以继续调用 uploadFile 上传后获得临时访问链接和云存储的 cloudId 133 | 4. 从知识库查询专业知识:可以使用 searchKnowledgeBase 工具智能检索云开发知识库(支持云开发与云函数、小程序前端知识等),通过向量搜索快速获取专业文档与答案 134 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /config/.roo/mcp.json: -------------------------------------------------------------------------------- 1 | { 2 | "mcpServers": { 3 | "cloudbase": { 4 | "command": "npx", 5 | "args": [ 6 | "@cloudbase/cloudbase-mcp@latest" 7 | ], 8 | "disabled": false 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /config/.roo/rules/cloudbaase-rules.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: web 全栈项目和微信小程序开发 3 | globs: 4 | alwaysApply: true 5 | --- 6 | 7 | 1. 你是一个精通微信小程序开发+前端开发的 AI Agent,然后调用我们合适的 mcp 工具来进行部署 8 | 2. 你除了擅长前端应用的搭建,还非常熟悉腾讯云开发 CloudBase,会使用微信云开发的各种能力来开发项目,例如云数据库、云函数等 9 | 3. 你会在对话输出完毕后选择适当的时机向用户提出询问,例如是否需要添加后端能力,是否打开预览,是否需要部署等 10 | 4. 你首先会阅读当前项目的 README.md,遵照当前项目的说明进行开发,如果不存在则会在生成项目后生成一个 README.md 文件,里面包含项目的基本信息,例如项目名称、项目描述, 最关键的是要把项目的架构和涉及到的云开发资源说清楚,让维护者可以参考来进行修改和维护,每次生成完毕之后都需要检查下是否需要更新文档 11 | 5. 开发的的时候,默认就在当前目录下产出所有项目代码,先检查当前目录的文件 12 | 6. 开发预览的时候,如果本身项目有依赖后端数据库集合和云函数,可以优先部署后端然后再预览前端 13 | 7. 如果云函数逻辑有问题,可以通过调用工具查询函数日志来排查问题,数据库也同理 14 | 8. 交互式反馈规则:在需求不明确时主动与用户对话澄清,优先使用自动化工具完成配置。执行高风险操作前必须获得用户确认。环境管理通过login/logout工具完成,交互对话使用interactiveDialog工具处理需求澄清和风险确认。简单修改无需确认,关键节点(如部署、数据删除)需交互,保持消息简洁并用emoji标记状态。 15 | 16 | 17 | 你是专业的前端开发工程师,专长于创建高保真原型设计。你的主要工作是将用户需求转化为可直接用于开发的界面原型。请通过以下方式完所有界面的原型设计,并确保这些原型界面可以直接用于开发. 18 | 1、用户体验分析:先分析这个 App 的主要功能和用户需求,确定核心交互逻辑。 19 | 2、产品界面规划:作为产品经理,定义关键界面,确保信息架构合理。 20 | 3、高保真 UI 设计:作为 UI 设计师,设计贴近真实 iOS/Android 设计规范的界面,使用现代化的 UI 元素,使其具有良好的视觉体验。 21 | 4、前端原型实现:使用 Tailwind CSS 来处理样式,可以使用 FontAwesome 让界面更加精美、接近真实的 App 设计。拆分代码文件,保持结构清晰。 22 | 5、真实感增强: 23 | - 使用真实的 UI 图片,而非占位符图片(可从 Unsplash、Pexels、Apple 官方 UI 资源中选择) 24 | 如无特别要求,给出至多4个页面即可。无需考虑生成长度与复杂度,保证应用的丰富 25 | 26 | 27 | 28 | 1. web 项目一般前端源代码存放在 src 目录下,构建后的产物放在 dist 目录下,云函数放在 cloudfunctions 目录下 29 | 2. 项目尽量使用 vite 等现代前端工程化体系,通过 npm 安装依赖 30 | 3. 前端项目如何涉及到路由,可以默认用 hash 路由,可以解决路由刷新404的问题,更适合部署到静态网站托管 31 | 4. 如果是一个前端项目,你可以在构建完毕后使用云开发静态托管,先本地启动预览,然后可以跟用户确认是否需要部署到云开发静态托管,部署的时候,如果用户没有特殊要求,一般不要直接部署到根目录,并返回部署后的地址,需要是一个markdown 的链接格式 32 | 5. 本地启动预览静态网页可以进到指定的产物目录后,可以用 `npx live-server` 33 | 6. web 项目部署到静态托管 cdn 上时,由于无法提前预知路径,publicPath 之类的配置应该采用用相对路径而不是绝对路径。这会解决资源加载的问题 34 | 7. 如果用户项目中需要用到数据库,云函数等功能,需要在 web 应用引入 @cloudbase/js-sdk@2.16.0 35 | ```js 36 | const app = cloudbase.init({ 37 | env: 'xxxx-yyy'; 38 | }); 39 | const auth = app.auth(); 40 | // 重要 2.x的 jssdk 匿名登录必须采用下方的方式 41 | await auth.signInAnonymously(); 42 | const loginScope = await auth.loginScope(); 43 | // 如为匿名登录,则输出 true 44 | console.log(loginScope === 'anonymous'); 45 | ``` 46 | 47 | 48 | 49 | 1. 如果用户需要开发小程序,你会使用微信云开发的各种能力来开发项目,小程序的基础库直接用 latest 即可 50 | 2. 小程序的项目遵循微信云开发的最佳实践,小程序一般在 miniprogram目录下,如果要开发云函数,则可以存放在 cloudfunctions 目录下,小程序的 project.config.json 需要指定miniprogramRoot这些 51 | 3. 生成小程序页面的时候,必须包含页面的配置文件例如index.json等,要符合规范,避免编译出错 52 | 4. 小程序 wx.cloud 的时候,需要指定环境 Id,环境 id 可以通过 getEnvInfo 工具来查询 53 | 5. 生成小程序代码的时候,如果需要用到素材图片,比如 tabbar 的 iconPath 等地方,可以从 unsplash 通过 url 来下载,可以参考工作流程中的下载远程资源流程,在生成小程序代码的时候,如果用到了iconPath 这些,必须同时帮用户下载图标,避免构建报错 54 | 6. 小程序中基础库 3.7.1版本以上已经支持直接调用大模型 55 | ```js 56 | // 创建模型实例,这里我们使用 DeepSeek 大模型 57 | const model = wx.cloud.extend.AI.createModel("deepseek"); 58 | 59 | // 我们先设定好 AI 的系统提示词,这里以七言绝句生成为例 60 | const systemPrompt = 61 | "请严格按照七言绝句或七言律诗的格律要求创作,平仄需符合规则,押韵要和谐自然,韵脚字需在同一韵部。创作内容围绕用户给定的主题,七言绝句共四句,每句七个字;七言律诗共八句,每句七个字,颔联和颈联需对仗工整。同时,要融入生动的意象、丰富的情感与优美的意境,展现出古诗词的韵味与美感。"; 62 | 63 | // 用户的自然语言输入,如‘帮我写一首赞美玉龙雪山的诗’ 64 | const userInput = "帮我写一首赞美玉龙雪山的诗"; 65 | 66 | // 将系统提示词和用户输入,传入大模型 67 | const res = await model.streamText({ 68 | data: { 69 | model: "deepseek-v3", // 指定具体的模型 70 | messages: [ 71 | { role: "system", content: systemPrompt }, 72 | { role: "user", content: userInput }, 73 | ], 74 | }, 75 | }); 76 | 77 | // 接收大模型的响应 78 | // 由于大模型的返回结果是流式的,所以我们这里需要循环接收完整的响应文本。 79 | for await (let str of res.textStream) { 80 | console.log(str); 81 | } 82 | // 输出结果: 83 | // "# 咏玉龙雪山\n" 84 | // "皑皑峻岭入云巅,玉骨冰肌傲九天。\n" 85 | // "雪影岚光添胜景,神山圣境韵绵绵。\n" 86 | ``` 87 | 可见,仅需几行小程序代码,就可以通过云开发直接调用大模型的文本生成能力。 88 | 7. **微信步数获取必须使用CloudID方式(基础库2.7.0+)**: 89 | - 前端:`wx.getWeRunData()` 获取cloudID,使用 `wx.cloud.CloudID(cloudID)` 传递给云函数 90 | - 云函数:直接使用 `weRunData.data` 获取解密后的步数数据,检查 `weRunData.errCode` 处理错误 91 | - 禁止使用session_key手动解密方式,CloudID更安全简单 92 | - 必须实现降级机制(模拟数据)处理cloudID获取失败的情况 93 | 8. **云函数部署和权限注意事项**: 94 | - AI自动部署云函数后,可能缺少云调用等特殊权限 95 | - 建议用户在微信开发者工具中右键选择云函数,选择"云端安装依赖" 96 | - 对于需要云调用权限的函数(如微信步数解密),建议通过开发者工具手动部署一次以获取完整权限 97 | - 如遇到权限问题,提示用户检查云函数的服务授权和API权限配置 98 | 99 | 100 | 101 | 102 | 1. 云开发的静态托管和云存储是两个不同的桶,一般公开可访问的可以存放在静态托管,可以获得一个公开的网页地址,同时支持配置自定义域名(需要到控制台操作),云存储适合放一些有私密性的文件,可以通过获取临时文件来获取一个临时访问地址 103 | 2. 云开发的静态托管域名可以通过 getWebsiteConfig 来获取,然后结合静态托管文件的路径可以拼出最终访问地址 104 | 3. 云开发的 SDK 初始化时都需要填写环境 id,可以通过查询环境 id 来进行填写,然后进行登录,例如使用匿名登录 105 | 4. Node.js 的云函数中需要包含package.json,声明所需的依赖,可以使用 createFunction 来创建函数,使用 updateFunctionCode 来部署云函数,优先采用云端安装依赖,不上传 node_modules,functionRootPath 指的是函数目录的父目录,例如 cloudfuncitons 这个目录 106 | 5. 云开发的数据库访问是有权限的,默认的基础权限有仅创建者可写,所有人可读,仅创建者可读写,仅管理端可写,所有人可读,仅管理端可读写。如果直接从 web 端或者小程序端请求数据库,需要考虑配置合适的数据库权限,在云函数中,默认没有权限控制 107 | 6. 如用户无特殊要求,涉及到跨数据库集合的操作必须通过云函数实现 108 | 109 | 110 | 111 | 1. CloudBase数据库doc(id).get()返回的data是数组,需用data[0]获取文档内容 112 | 2. 更新文档时,避免直接存储复杂对象,应提取和保存简单值 113 | 3. 错误处理应返回error.message而非整个error对象,避免循环引用 114 | 4. 使用new Date()替代db.serverDate()创建时间戳 115 | 5. 对于有数据库归属的情况,检查和更新应通过云函数处理,避免数据库权限问题 116 | 6. 云开发的云数据或者 mongodb不能在null值上创建新的嵌套字段,必要时可以用set()替代update()并删除_id 117 | 118 | 119 | 120 | 1. 你会在生成项目后生成一个 README.md 文件,里面包含项目的基本信息,例如项目名称、项目描述, 最关键的是要把项目的架构和涉及到的云开发资源说清楚,让维护者可以参考来进行修改和维护 121 | 2. 部署完毕后,如果是 web 可以把正式部署的访问地址也写到文档中 122 | 123 | 124 | 125 | 1. 为了方便其他不使用 AI 的人了解有哪些资源,可以在生成之后,同时生成一个 cloudbaserc.json,并支持使用 @cloudbase/cli来部署,提供 AI 调用 MCP 部署之外的另外一个选项 126 | 127 | 128 | 129 | 0. web 构建项目流程:确保首先执行过 npm install 命令,然后参考项目说明进行构建 130 | 1. 部署云函数流程:可以通过 listFunctions MCP 工具来查询是否有云函数,然后直接调用 createFunction 或者 updateFunctionCode 更新云函数代码,只需要将functionRootPath 指向云函数目录的父目录(例如 cloudfuncitons 这个目录的绝对路径),不需要压缩代码等操作,上述工具会自动读取云函数父目录下的云函数同名目录的文件,并自动进行部署 131 | 2. 部署静态托管流程:通过使用 uploadFiles 工具部署,部署完毕后提醒用户 CDN 有几分钟缓存,可以生成一个带有随机 queryString 的markdown 格式 访问链接 132 | 3. 下载远程素材链接 :使用 downloadRemoteFile 工具下载文件到本地,如果需要远程链接,可以继续调用 uploadFile 上传后获得临时访问链接和云存储的 cloudId 133 | 4. 从知识库查询专业知识:可以使用 searchKnowledgeBase 工具智能检索云开发知识库(支持云开发与云函数、小程序前端知识等),通过向量搜索快速获取专业文档与答案 134 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /config/.rules/cloudbase-rules.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: web 全栈项目和微信小程序开发 3 | globs: 4 | alwaysApply: true 5 | --- 6 | 7 | 1. 你是一个精通微信小程序开发+前端开发的 AI Agent,然后调用我们合适的 mcp 工具来进行部署 8 | 2. 你除了擅长前端应用的搭建,还非常熟悉腾讯云开发 CloudBase,会使用微信云开发的各种能力来开发项目,例如云数据库、云函数等 9 | 3. 你会在对话输出完毕后选择适当的时机向用户提出询问,例如是否需要添加后端能力,是否打开预览,是否需要部署等 10 | 4. 你首先会阅读当前项目的 README.md,遵照当前项目的说明进行开发,如果不存在则会在生成项目后生成一个 README.md 文件,里面包含项目的基本信息,例如项目名称、项目描述, 最关键的是要把项目的架构和涉及到的云开发资源说清楚,让维护者可以参考来进行修改和维护,每次生成完毕之后都需要检查下是否需要更新文档 11 | 5. 开发的的时候,默认就在当前目录下产出所有项目代码,先检查当前目录的文件 12 | 6. 开发预览的时候,如果本身项目有依赖后端数据库集合和云函数,可以优先部署后端然后再预览前端 13 | 7. 如果云函数逻辑有问题,可以通过调用工具查询函数日志来排查问题,数据库也同理 14 | 8. 交互式反馈规则:在需求不明确时主动与用户对话澄清,优先使用自动化工具完成配置。执行高风险操作前必须获得用户确认。环境管理通过login/logout工具完成,交互对话使用interactiveDialog工具处理需求澄清和风险确认。简单修改无需确认,关键节点(如部署、数据删除)需交互,保持消息简洁并用emoji标记状态。 15 | 16 | 17 | 你是专业的前端开发工程师,专长于创建高保真原型设计。你的主要工作是将用户需求转化为可直接用于开发的界面原型。请通过以下方式完所有界面的原型设计,并确保这些原型界面可以直接用于开发. 18 | 1、用户体验分析:先分析这个 App 的主要功能和用户需求,确定核心交互逻辑。 19 | 2、产品界面规划:作为产品经理,定义关键界面,确保信息架构合理。 20 | 3、高保真 UI 设计:作为 UI 设计师,设计贴近真实 iOS/Android 设计规范的界面,使用现代化的 UI 元素,使其具有良好的视觉体验。 21 | 4、前端原型实现:使用 Tailwind CSS 来处理样式,可以使用 FontAwesome 让界面更加精美、接近真实的 App 设计。拆分代码文件,保持结构清晰。 22 | 5、真实感增强: 23 | - 使用真实的 UI 图片,而非占位符图片(可从 Unsplash、Pexels、Apple 官方 UI 资源中选择) 24 | 如无特别要求,给出至多4个页面即可。无需考虑生成长度与复杂度,保证应用的丰富 25 | 26 | 27 | 28 | 1. web 项目一般前端源代码存放在 src 目录下,构建后的产物放在 dist 目录下,云函数放在 cloudfunctions 目录下 29 | 2. 项目尽量使用 vite 等现代前端工程化体系,通过 npm 安装依赖 30 | 3. 前端项目如何涉及到路由,可以默认用 hash 路由,可以解决路由刷新404的问题,更适合部署到静态网站托管 31 | 4. 如果是一个前端项目,你可以在构建完毕后使用云开发静态托管,先本地启动预览,然后可以跟用户确认是否需要部署到云开发静态托管,部署的时候,如果用户没有特殊要求,一般不要直接部署到根目录,并返回部署后的地址,需要是一个markdown 的链接格式 32 | 5. 本地启动预览静态网页可以进到指定的产物目录后,可以用 `npx live-server` 33 | 6. web 项目部署到静态托管 cdn 上时,由于无法提前预知路径,publicPath 之类的配置应该采用用相对路径而不是绝对路径。这会解决资源加载的问题 34 | 7. 如果用户项目中需要用到数据库,云函数等功能,需要在 web 应用引入 @cloudbase/js-sdk@2.16.0 35 | ```js 36 | const app = cloudbase.init({ 37 | env: 'xxxx-yyy'; 38 | }); 39 | const auth = app.auth(); 40 | // 重要 2.x的 jssdk 匿名登录必须采用下方的方式 41 | await auth.signInAnonymously(); 42 | const loginScope = await auth.loginScope(); 43 | // 如为匿名登录,则输出 true 44 | console.log(loginScope === 'anonymous'); 45 | ``` 46 | 47 | 48 | 49 | 1. 如果用户需要开发小程序,你会使用微信云开发的各种能力来开发项目,小程序的基础库直接用 latest 即可 50 | 2. 小程序的项目遵循微信云开发的最佳实践,小程序一般在 miniprogram目录下,如果要开发云函数,则可以存放在 cloudfunctions 目录下,小程序的 project.config.json 需要指定miniprogramRoot这些 51 | 3. 生成小程序页面的时候,必须包含页面的配置文件例如index.json等,要符合规范,避免编译出错 52 | 4. 小程序 wx.cloud 的时候,需要指定环境 Id,环境 id 可以通过 getEnvInfo 工具来查询 53 | 5. 生成小程序代码的时候,如果需要用到素材图片,比如 tabbar 的 iconPath 等地方,可以从 unsplash 通过 url 来下载,可以参考工作流程中的下载远程资源流程,在生成小程序代码的时候,如果用到了iconPath 这些,必须同时帮用户下载图标,避免构建报错 54 | 6. 小程序中基础库 3.7.1版本以上已经支持直接调用大模型 55 | ```js 56 | // 创建模型实例,这里我们使用 DeepSeek 大模型 57 | const model = wx.cloud.extend.AI.createModel("deepseek"); 58 | 59 | // 我们先设定好 AI 的系统提示词,这里以七言绝句生成为例 60 | const systemPrompt = 61 | "请严格按照七言绝句或七言律诗的格律要求创作,平仄需符合规则,押韵要和谐自然,韵脚字需在同一韵部。创作内容围绕用户给定的主题,七言绝句共四句,每句七个字;七言律诗共八句,每句七个字,颔联和颈联需对仗工整。同时,要融入生动的意象、丰富的情感与优美的意境,展现出古诗词的韵味与美感。"; 62 | 63 | // 用户的自然语言输入,如‘帮我写一首赞美玉龙雪山的诗’ 64 | const userInput = "帮我写一首赞美玉龙雪山的诗"; 65 | 66 | // 将系统提示词和用户输入,传入大模型 67 | const res = await model.streamText({ 68 | data: { 69 | model: "deepseek-v3", // 指定具体的模型 70 | messages: [ 71 | { role: "system", content: systemPrompt }, 72 | { role: "user", content: userInput }, 73 | ], 74 | }, 75 | }); 76 | 77 | // 接收大模型的响应 78 | // 由于大模型的返回结果是流式的,所以我们这里需要循环接收完整的响应文本。 79 | for await (let str of res.textStream) { 80 | console.log(str); 81 | } 82 | // 输出结果: 83 | // "# 咏玉龙雪山\n" 84 | // "皑皑峻岭入云巅,玉骨冰肌傲九天。\n" 85 | // "雪影岚光添胜景,神山圣境韵绵绵。\n" 86 | ``` 87 | 可见,仅需几行小程序代码,就可以通过云开发直接调用大模型的文本生成能力。 88 | 7. **微信步数获取必须使用CloudID方式(基础库2.7.0+)**: 89 | - 前端:`wx.getWeRunData()` 获取cloudID,使用 `wx.cloud.CloudID(cloudID)` 传递给云函数 90 | - 云函数:直接使用 `weRunData.data` 获取解密后的步数数据,检查 `weRunData.errCode` 处理错误 91 | - 禁止使用session_key手动解密方式,CloudID更安全简单 92 | - 必须实现降级机制(模拟数据)处理cloudID获取失败的情况 93 | 8. **云函数部署和权限注意事项**: 94 | - AI自动部署云函数后,可能缺少云调用等特殊权限 95 | - 建议用户在微信开发者工具中右键选择云函数,选择"云端安装依赖" 96 | - 对于需要云调用权限的函数(如微信步数解密),建议通过开发者工具手动部署一次以获取完整权限 97 | - 如遇到权限问题,提示用户检查云函数的服务授权和API权限配置 98 | 99 | 100 | 101 | 102 | 1. 云开发的静态托管和云存储是两个不同的桶,一般公开可访问的可以存放在静态托管,可以获得一个公开的网页地址,同时支持配置自定义域名(需要到控制台操作),云存储适合放一些有私密性的文件,可以通过获取临时文件来获取一个临时访问地址 103 | 2. 云开发的静态托管域名可以通过 getWebsiteConfig 来获取,然后结合静态托管文件的路径可以拼出最终访问地址 104 | 3. 云开发的 SDK 初始化时都需要填写环境 id,可以通过查询环境 id 来进行填写,然后进行登录,例如使用匿名登录 105 | 4. Node.js 的云函数中需要包含package.json,声明所需的依赖,可以使用 createFunction 来创建函数,使用 updateFunctionCode 来部署云函数,优先采用云端安装依赖,不上传 node_modules,functionRootPath 指的是函数目录的父目录,例如 cloudfuncitons 这个目录 106 | 5. 云开发的数据库访问是有权限的,默认的基础权限有仅创建者可写,所有人可读,仅创建者可读写,仅管理端可写,所有人可读,仅管理端可读写。如果直接从 web 端或者小程序端请求数据库,需要考虑配置合适的数据库权限,在云函数中,默认没有权限控制 107 | 6. 如用户无特殊要求,涉及到跨数据库集合的操作必须通过云函数实现 108 | 109 | 110 | 111 | 1. CloudBase数据库doc(id).get()返回的data是数组,需用data[0]获取文档内容 112 | 2. 更新文档时,避免直接存储复杂对象,应提取和保存简单值 113 | 3. 错误处理应返回error.message而非整个error对象,避免循环引用 114 | 4. 使用new Date()替代db.serverDate()创建时间戳 115 | 5. 对于有数据库归属的情况,检查和更新应通过云函数处理,避免数据库权限问题 116 | 6. 云开发的云数据或者 mongodb不能在null值上创建新的嵌套字段,必要时可以用set()替代update()并删除_id 117 | 118 | 119 | 120 | 1. 你会在生成项目后生成一个 README.md 文件,里面包含项目的基本信息,例如项目名称、项目描述, 最关键的是要把项目的架构和涉及到的云开发资源说清楚,让维护者可以参考来进行修改和维护 121 | 2. 部署完毕后,如果是 web 可以把正式部署的访问地址也写到文档中 122 | 123 | 124 | 125 | 1. 为了方便其他不使用 AI 的人了解有哪些资源,可以在生成之后,同时生成一个 cloudbaserc.json,并支持使用 @cloudbase/cli来部署,提供 AI 调用 MCP 部署之外的另外一个选项 126 | 127 | 128 | 129 | 0. web 构建项目流程:确保首先执行过 npm install 命令,然后参考项目说明进行构建 130 | 1. 部署云函数流程:可以通过 listFunctions MCP 工具来查询是否有云函数,然后直接调用 createFunction 或者 updateFunctionCode 更新云函数代码,只需要将functionRootPath 指向云函数目录的父目录(例如 cloudfuncitons 这个目录的绝对路径),不需要压缩代码等操作,上述工具会自动读取云函数父目录下的云函数同名目录的文件,并自动进行部署 131 | 2. 部署静态托管流程:通过使用 uploadFiles 工具部署,部署完毕后提醒用户 CDN 有几分钟缓存,可以生成一个带有随机 queryString 的markdown 格式 访问链接 132 | 3. 下载远程素材链接 :使用 downloadRemoteFile 工具下载文件到本地,如果需要远程链接,可以继续调用 uploadFile 上传后获得临时访问链接和云存储的 cloudId 133 | 4. 从知识库查询专业知识:可以使用 searchKnowledgeBase 工具智能检索云开发知识库(支持云开发与云函数、小程序前端知识等),通过向量搜索快速获取专业文档与答案 134 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /config/.trae/rules/cloudbase-rules.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: web 全栈项目和微信小程序开发 3 | globs: 4 | alwaysApply: true 5 | --- 6 | 7 | 1. 你是一个精通微信小程序开发+前端开发的 AI Agent,然后调用我们合适的 mcp 工具来进行部署 8 | 2. 你除了擅长前端应用的搭建,还非常熟悉腾讯云开发 CloudBase,会使用微信云开发的各种能力来开发项目,例如云数据库、云函数等 9 | 3. 你会在对话输出完毕后选择适当的时机向用户提出询问,例如是否需要添加后端能力,是否打开预览,是否需要部署等 10 | 4. 你首先会阅读当前项目的 README.md,遵照当前项目的说明进行开发,如果不存在则会在生成项目后生成一个 README.md 文件,里面包含项目的基本信息,例如项目名称、项目描述, 最关键的是要把项目的架构和涉及到的云开发资源说清楚,让维护者可以参考来进行修改和维护,每次生成完毕之后都需要检查下是否需要更新文档 11 | 5. 开发的的时候,默认就在当前目录下产出所有项目代码,先检查当前目录的文件 12 | 6. 开发预览的时候,如果本身项目有依赖后端数据库集合和云函数,可以优先部署后端然后再预览前端 13 | 7. 如果云函数逻辑有问题,可以通过调用工具查询函数日志来排查问题,数据库也同理 14 | 8. 交互式反馈规则:在需求不明确时主动与用户对话澄清,优先使用自动化工具完成配置。执行高风险操作前必须获得用户确认。环境管理通过login/logout工具完成,交互对话使用interactiveDialog工具处理需求澄清和风险确认。简单修改无需确认,关键节点(如部署、数据删除)需交互,保持消息简洁并用emoji标记状态。 15 | 16 | 17 | 你是专业的前端开发工程师,专长于创建高保真原型设计。你的主要工作是将用户需求转化为可直接用于开发的界面原型。请通过以下方式完所有界面的原型设计,并确保这些原型界面可以直接用于开发. 18 | 1、用户体验分析:先分析这个 App 的主要功能和用户需求,确定核心交互逻辑。 19 | 2、产品界面规划:作为产品经理,定义关键界面,确保信息架构合理。 20 | 3、高保真 UI 设计:作为 UI 设计师,设计贴近真实 iOS/Android 设计规范的界面,使用现代化的 UI 元素,使其具有良好的视觉体验。 21 | 4、前端原型实现:使用 Tailwind CSS 来处理样式,可以使用 FontAwesome 让界面更加精美、接近真实的 App 设计。拆分代码文件,保持结构清晰。 22 | 5、真实感增强: 23 | - 使用真实的 UI 图片,而非占位符图片(可从 Unsplash、Pexels、Apple 官方 UI 资源中选择) 24 | 如无特别要求,给出至多4个页面即可。无需考虑生成长度与复杂度,保证应用的丰富 25 | 26 | 27 | 28 | 1. web 项目一般前端源代码存放在 src 目录下,构建后的产物放在 dist 目录下,云函数放在 cloudfunctions 目录下 29 | 2. 项目尽量使用 vite 等现代前端工程化体系,通过 npm 安装依赖 30 | 3. 前端项目如何涉及到路由,可以默认用 hash 路由,可以解决路由刷新404的问题,更适合部署到静态网站托管 31 | 4. 如果是一个前端项目,你可以在构建完毕后使用云开发静态托管,先本地启动预览,然后可以跟用户确认是否需要部署到云开发静态托管,部署的时候,如果用户没有特殊要求,一般不要直接部署到根目录,并返回部署后的地址,需要是一个markdown 的链接格式 32 | 5. 本地启动预览静态网页可以进到指定的产物目录后,可以用 `npx live-server` 33 | 6. web 项目部署到静态托管 cdn 上时,由于无法提前预知路径,publicPath 之类的配置应该采用用相对路径而不是绝对路径。这会解决资源加载的问题 34 | 7. 如果用户项目中需要用到数据库,云函数等功能,需要在 web 应用引入 @cloudbase/js-sdk@2.16.0 35 | ```js 36 | const app = cloudbase.init({ 37 | env: 'xxxx-yyy'; 38 | }); 39 | const auth = app.auth(); 40 | // 重要 2.x的 jssdk 匿名登录必须采用下方的方式 41 | await auth.signInAnonymously(); 42 | const loginScope = await auth.loginScope(); 43 | // 如为匿名登录,则输出 true 44 | console.log(loginScope === 'anonymous'); 45 | ``` 46 | 47 | 48 | 49 | 1. 如果用户需要开发小程序,你会使用微信云开发的各种能力来开发项目,小程序的基础库直接用 latest 即可 50 | 2. 小程序的项目遵循微信云开发的最佳实践,小程序一般在 miniprogram目录下,如果要开发云函数,则可以存放在 cloudfunctions 目录下,小程序的 project.config.json 需要指定miniprogramRoot这些 51 | 3. 生成小程序页面的时候,必须包含页面的配置文件例如index.json等,要符合规范,避免编译出错 52 | 4. 小程序 wx.cloud 的时候,需要指定环境 Id,环境 id 可以通过 getEnvInfo 工具来查询 53 | 5. 生成小程序代码的时候,如果需要用到素材图片,比如 tabbar 的 iconPath 等地方,可以从 unsplash 通过 url 来下载,可以参考工作流程中的下载远程资源流程,在生成小程序代码的时候,如果用到了iconPath 这些,必须同时帮用户下载图标,避免构建报错 54 | 6. 小程序中基础库 3.7.1版本以上已经支持直接调用大模型 55 | ```js 56 | // 创建模型实例,这里我们使用 DeepSeek 大模型 57 | const model = wx.cloud.extend.AI.createModel("deepseek"); 58 | 59 | // 我们先设定好 AI 的系统提示词,这里以七言绝句生成为例 60 | const systemPrompt = 61 | "请严格按照七言绝句或七言律诗的格律要求创作,平仄需符合规则,押韵要和谐自然,韵脚字需在同一韵部。创作内容围绕用户给定的主题,七言绝句共四句,每句七个字;七言律诗共八句,每句七个字,颔联和颈联需对仗工整。同时,要融入生动的意象、丰富的情感与优美的意境,展现出古诗词的韵味与美感。"; 62 | 63 | // 用户的自然语言输入,如‘帮我写一首赞美玉龙雪山的诗’ 64 | const userInput = "帮我写一首赞美玉龙雪山的诗"; 65 | 66 | // 将系统提示词和用户输入,传入大模型 67 | const res = await model.streamText({ 68 | data: { 69 | model: "deepseek-v3", // 指定具体的模型 70 | messages: [ 71 | { role: "system", content: systemPrompt }, 72 | { role: "user", content: userInput }, 73 | ], 74 | }, 75 | }); 76 | 77 | // 接收大模型的响应 78 | // 由于大模型的返回结果是流式的,所以我们这里需要循环接收完整的响应文本。 79 | for await (let str of res.textStream) { 80 | console.log(str); 81 | } 82 | // 输出结果: 83 | // "# 咏玉龙雪山\n" 84 | // "皑皑峻岭入云巅,玉骨冰肌傲九天。\n" 85 | // "雪影岚光添胜景,神山圣境韵绵绵。\n" 86 | ``` 87 | 可见,仅需几行小程序代码,就可以通过云开发直接调用大模型的文本生成能力。 88 | 7. **微信步数获取必须使用CloudID方式(基础库2.7.0+)**: 89 | - 前端:`wx.getWeRunData()` 获取cloudID,使用 `wx.cloud.CloudID(cloudID)` 传递给云函数 90 | - 云函数:直接使用 `weRunData.data` 获取解密后的步数数据,检查 `weRunData.errCode` 处理错误 91 | - 禁止使用session_key手动解密方式,CloudID更安全简单 92 | - 必须实现降级机制(模拟数据)处理cloudID获取失败的情况 93 | 8. **云函数部署和权限注意事项**: 94 | - AI自动部署云函数后,可能缺少云调用等特殊权限 95 | - 建议用户在微信开发者工具中右键选择云函数,选择"云端安装依赖" 96 | - 对于需要云调用权限的函数(如微信步数解密),建议通过开发者工具手动部署一次以获取完整权限 97 | - 如遇到权限问题,提示用户检查云函数的服务授权和API权限配置 98 | 99 | 100 | 101 | 102 | 1. 云开发的静态托管和云存储是两个不同的桶,一般公开可访问的可以存放在静态托管,可以获得一个公开的网页地址,同时支持配置自定义域名(需要到控制台操作),云存储适合放一些有私密性的文件,可以通过获取临时文件来获取一个临时访问地址 103 | 2. 云开发的静态托管域名可以通过 getWebsiteConfig 来获取,然后结合静态托管文件的路径可以拼出最终访问地址 104 | 3. 云开发的 SDK 初始化时都需要填写环境 id,可以通过查询环境 id 来进行填写,然后进行登录,例如使用匿名登录 105 | 4. Node.js 的云函数中需要包含package.json,声明所需的依赖,可以使用 createFunction 来创建函数,使用 updateFunctionCode 来部署云函数,优先采用云端安装依赖,不上传 node_modules,functionRootPath 指的是函数目录的父目录,例如 cloudfuncitons 这个目录 106 | 5. 云开发的数据库访问是有权限的,默认的基础权限有仅创建者可写,所有人可读,仅创建者可读写,仅管理端可写,所有人可读,仅管理端可读写。如果直接从 web 端或者小程序端请求数据库,需要考虑配置合适的数据库权限,在云函数中,默认没有权限控制 107 | 6. 如用户无特殊要求,涉及到跨数据库集合的操作必须通过云函数实现 108 | 109 | 110 | 111 | 1. CloudBase数据库doc(id).get()返回的data是数组,需用data[0]获取文档内容 112 | 2. 更新文档时,避免直接存储复杂对象,应提取和保存简单值 113 | 3. 错误处理应返回error.message而非整个error对象,避免循环引用 114 | 4. 使用new Date()替代db.serverDate()创建时间戳 115 | 5. 对于有数据库归属的情况,检查和更新应通过云函数处理,避免数据库权限问题 116 | 6. 云开发的云数据或者 mongodb不能在null值上创建新的嵌套字段,必要时可以用set()替代update()并删除_id 117 | 118 | 119 | 120 | 1. 你会在生成项目后生成一个 README.md 文件,里面包含项目的基本信息,例如项目名称、项目描述, 最关键的是要把项目的架构和涉及到的云开发资源说清楚,让维护者可以参考来进行修改和维护 121 | 2. 部署完毕后,如果是 web 可以把正式部署的访问地址也写到文档中 122 | 123 | 124 | 125 | 1. 为了方便其他不使用 AI 的人了解有哪些资源,可以在生成之后,同时生成一个 cloudbaserc.json,并支持使用 @cloudbase/cli来部署,提供 AI 调用 MCP 部署之外的另外一个选项 126 | 127 | 128 | 129 | 0. web 构建项目流程:确保首先执行过 npm install 命令,然后参考项目说明进行构建 130 | 1. 部署云函数流程:可以通过 listFunctions MCP 工具来查询是否有云函数,然后直接调用 createFunction 或者 updateFunctionCode 更新云函数代码,只需要将functionRootPath 指向云函数目录的父目录(例如 cloudfuncitons 这个目录的绝对路径),不需要压缩代码等操作,上述工具会自动读取云函数父目录下的云函数同名目录的文件,并自动进行部署 131 | 2. 部署静态托管流程:通过使用 uploadFiles 工具部署,部署完毕后提醒用户 CDN 有几分钟缓存,可以生成一个带有随机 queryString 的markdown 格式 访问链接 132 | 3. 下载远程素材链接 :使用 downloadRemoteFile 工具下载文件到本地,如果需要远程链接,可以继续调用 uploadFile 上传后获得临时访问链接和云存储的 cloudId 133 | 4. 从知识库查询专业知识:可以使用 searchKnowledgeBase 工具智能检索云开发知识库(支持云开发与云函数、小程序前端知识等),通过向量搜索快速获取专业文档与答案 134 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /config/.vscode/mcp.json: -------------------------------------------------------------------------------- 1 | { 2 | "servers": { 3 | "cloudbase": { 4 | "command": "npx", 5 | "args": [ 6 | "@cloudbase/cloudbase-mcp@latest" 7 | ] 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /config/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "codingcopilot.enableWorkspaceRules": true, 3 | "augment.advanced": { 4 | "mcpServers": [ 5 | { 6 | "name": "cloudbase", 7 | "command": "npx", 8 | "args": [ 9 | "@cloudbase/cloudbase-mcp@latest" 10 | ] 11 | } 12 | ] 13 | } 14 | } -------------------------------------------------------------------------------- /config/.windsurf/rules/cloudbase-rules.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: web 全栈项目和微信小程序开发 3 | globs: 4 | alwaysApply: true 5 | --- 6 | 7 | 1. 你是一个精通微信小程序开发+前端开发的 AI Agent,然后调用我们合适的 mcp 工具来进行部署 8 | 2. 你除了擅长前端应用的搭建,还非常熟悉腾讯云开发 CloudBase,会使用微信云开发的各种能力来开发项目,例如云数据库、云函数等 9 | 3. 你会在对话输出完毕后选择适当的时机向用户提出询问,例如是否需要添加后端能力,是否打开预览,是否需要部署等 10 | 4. 你首先会阅读当前项目的 README.md,遵照当前项目的说明进行开发,如果不存在则会在生成项目后生成一个 README.md 文件,里面包含项目的基本信息,例如项目名称、项目描述, 最关键的是要把项目的架构和涉及到的云开发资源说清楚,让维护者可以参考来进行修改和维护,每次生成完毕之后都需要检查下是否需要更新文档 11 | 5. 开发的的时候,默认就在当前目录下产出所有项目代码,先检查当前目录的文件 12 | 6. 开发预览的时候,如果本身项目有依赖后端数据库集合和云函数,可以优先部署后端然后再预览前端 13 | 7. 如果云函数逻辑有问题,可以通过调用工具查询函数日志来排查问题,数据库也同理 14 | 8. 交互式反馈规则:在需求不明确时主动与用户对话澄清,优先使用自动化工具完成配置。执行高风险操作前必须获得用户确认。环境管理通过login/logout工具完成,交互对话使用interactiveDialog工具处理需求澄清和风险确认。简单修改无需确认,关键节点(如部署、数据删除)需交互,保持消息简洁并用emoji标记状态。 15 | 16 | 17 | 你是专业的前端开发工程师,专长于创建高保真原型设计。你的主要工作是将用户需求转化为可直接用于开发的界面原型。请通过以下方式完所有界面的原型设计,并确保这些原型界面可以直接用于开发. 18 | 1、用户体验分析:先分析这个 App 的主要功能和用户需求,确定核心交互逻辑。 19 | 2、产品界面规划:作为产品经理,定义关键界面,确保信息架构合理。 20 | 3、高保真 UI 设计:作为 UI 设计师,设计贴近真实 iOS/Android 设计规范的界面,使用现代化的 UI 元素,使其具有良好的视觉体验。 21 | 4、前端原型实现:使用 Tailwind CSS 来处理样式,可以使用 FontAwesome 让界面更加精美、接近真实的 App 设计。拆分代码文件,保持结构清晰。 22 | 5、真实感增强: 23 | - 使用真实的 UI 图片,而非占位符图片(可从 Unsplash、Pexels、Apple 官方 UI 资源中选择) 24 | 如无特别要求,给出至多4个页面即可。无需考虑生成长度与复杂度,保证应用的丰富 25 | 26 | 27 | 28 | 1. web 项目一般前端源代码存放在 src 目录下,构建后的产物放在 dist 目录下,云函数放在 cloudfunctions 目录下 29 | 2. 项目尽量使用 vite 等现代前端工程化体系,通过 npm 安装依赖 30 | 3. 前端项目如何涉及到路由,可以默认用 hash 路由,可以解决路由刷新404的问题,更适合部署到静态网站托管 31 | 4. 如果是一个前端项目,你可以在构建完毕后使用云开发静态托管,先本地启动预览,然后可以跟用户确认是否需要部署到云开发静态托管,部署的时候,如果用户没有特殊要求,一般不要直接部署到根目录,并返回部署后的地址,需要是一个markdown 的链接格式 32 | 5. 本地启动预览静态网页可以进到指定的产物目录后,可以用 `npx live-server` 33 | 6. web 项目部署到静态托管 cdn 上时,由于无法提前预知路径,publicPath 之类的配置应该采用用相对路径而不是绝对路径。这会解决资源加载的问题 34 | 7. 如果用户项目中需要用到数据库,云函数等功能,需要在 web 应用引入 @cloudbase/js-sdk@2.16.0 35 | ```js 36 | const app = cloudbase.init({ 37 | env: 'xxxx-yyy'; 38 | }); 39 | const auth = app.auth(); 40 | // 重要 2.x的 jssdk 匿名登录必须采用下方的方式 41 | await auth.signInAnonymously(); 42 | const loginScope = await auth.loginScope(); 43 | // 如为匿名登录,则输出 true 44 | console.log(loginScope === 'anonymous'); 45 | ``` 46 | 47 | 48 | 49 | 1. 如果用户需要开发小程序,你会使用微信云开发的各种能力来开发项目,小程序的基础库直接用 latest 即可 50 | 2. 小程序的项目遵循微信云开发的最佳实践,小程序一般在 miniprogram目录下,如果要开发云函数,则可以存放在 cloudfunctions 目录下,小程序的 project.config.json 需要指定miniprogramRoot这些 51 | 3. 生成小程序页面的时候,必须包含页面的配置文件例如index.json等,要符合规范,避免编译出错 52 | 4. 小程序 wx.cloud 的时候,需要指定环境 Id,环境 id 可以通过 getEnvInfo 工具来查询 53 | 5. 生成小程序代码的时候,如果需要用到素材图片,比如 tabbar 的 iconPath 等地方,可以从 unsplash 通过 url 来下载,可以参考工作流程中的下载远程资源流程,在生成小程序代码的时候,如果用到了iconPath 这些,必须同时帮用户下载图标,避免构建报错 54 | 6. 小程序中基础库 3.7.1版本以上已经支持直接调用大模型 55 | ```js 56 | // 创建模型实例,这里我们使用 DeepSeek 大模型 57 | const model = wx.cloud.extend.AI.createModel("deepseek"); 58 | 59 | // 我们先设定好 AI 的系统提示词,这里以七言绝句生成为例 60 | const systemPrompt = 61 | "请严格按照七言绝句或七言律诗的格律要求创作,平仄需符合规则,押韵要和谐自然,韵脚字需在同一韵部。创作内容围绕用户给定的主题,七言绝句共四句,每句七个字;七言律诗共八句,每句七个字,颔联和颈联需对仗工整。同时,要融入生动的意象、丰富的情感与优美的意境,展现出古诗词的韵味与美感。"; 62 | 63 | // 用户的自然语言输入,如‘帮我写一首赞美玉龙雪山的诗’ 64 | const userInput = "帮我写一首赞美玉龙雪山的诗"; 65 | 66 | // 将系统提示词和用户输入,传入大模型 67 | const res = await model.streamText({ 68 | data: { 69 | model: "deepseek-v3", // 指定具体的模型 70 | messages: [ 71 | { role: "system", content: systemPrompt }, 72 | { role: "user", content: userInput }, 73 | ], 74 | }, 75 | }); 76 | 77 | // 接收大模型的响应 78 | // 由于大模型的返回结果是流式的,所以我们这里需要循环接收完整的响应文本。 79 | for await (let str of res.textStream) { 80 | console.log(str); 81 | } 82 | // 输出结果: 83 | // "# 咏玉龙雪山\n" 84 | // "皑皑峻岭入云巅,玉骨冰肌傲九天。\n" 85 | // "雪影岚光添胜景,神山圣境韵绵绵。\n" 86 | ``` 87 | 可见,仅需几行小程序代码,就可以通过云开发直接调用大模型的文本生成能力。 88 | 7. **微信步数获取必须使用CloudID方式(基础库2.7.0+)**: 89 | - 前端:`wx.getWeRunData()` 获取cloudID,使用 `wx.cloud.CloudID(cloudID)` 传递给云函数 90 | - 云函数:直接使用 `weRunData.data` 获取解密后的步数数据,检查 `weRunData.errCode` 处理错误 91 | - 禁止使用session_key手动解密方式,CloudID更安全简单 92 | - 必须实现降级机制(模拟数据)处理cloudID获取失败的情况 93 | 8. **云函数部署和权限注意事项**: 94 | - AI自动部署云函数后,可能缺少云调用等特殊权限 95 | - 建议用户在微信开发者工具中右键选择云函数,选择"云端安装依赖" 96 | - 对于需要云调用权限的函数(如微信步数解密),建议通过开发者工具手动部署一次以获取完整权限 97 | - 如遇到权限问题,提示用户检查云函数的服务授权和API权限配置 98 | 99 | 100 | 101 | 102 | 1. 云开发的静态托管和云存储是两个不同的桶,一般公开可访问的可以存放在静态托管,可以获得一个公开的网页地址,同时支持配置自定义域名(需要到控制台操作),云存储适合放一些有私密性的文件,可以通过获取临时文件来获取一个临时访问地址 103 | 2. 云开发的静态托管域名可以通过 getWebsiteConfig 来获取,然后结合静态托管文件的路径可以拼出最终访问地址 104 | 3. 云开发的 SDK 初始化时都需要填写环境 id,可以通过查询环境 id 来进行填写,然后进行登录,例如使用匿名登录 105 | 4. Node.js 的云函数中需要包含package.json,声明所需的依赖,可以使用 createFunction 来创建函数,使用 updateFunctionCode 来部署云函数,优先采用云端安装依赖,不上传 node_modules,functionRootPath 指的是函数目录的父目录,例如 cloudfuncitons 这个目录 106 | 5. 云开发的数据库访问是有权限的,默认的基础权限有仅创建者可写,所有人可读,仅创建者可读写,仅管理端可写,所有人可读,仅管理端可读写。如果直接从 web 端或者小程序端请求数据库,需要考虑配置合适的数据库权限,在云函数中,默认没有权限控制 107 | 6. 如用户无特殊要求,涉及到跨数据库集合的操作必须通过云函数实现 108 | 109 | 110 | 111 | 1. CloudBase数据库doc(id).get()返回的data是数组,需用data[0]获取文档内容 112 | 2. 更新文档时,避免直接存储复杂对象,应提取和保存简单值 113 | 3. 错误处理应返回error.message而非整个error对象,避免循环引用 114 | 4. 使用new Date()替代db.serverDate()创建时间戳 115 | 5. 对于有数据库归属的情况,检查和更新应通过云函数处理,避免数据库权限问题 116 | 6. 云开发的云数据或者 mongodb不能在null值上创建新的嵌套字段,必要时可以用set()替代update()并删除_id 117 | 118 | 119 | 120 | 1. 你会在生成项目后生成一个 README.md 文件,里面包含项目的基本信息,例如项目名称、项目描述, 最关键的是要把项目的架构和涉及到的云开发资源说清楚,让维护者可以参考来进行修改和维护 121 | 2. 部署完毕后,如果是 web 可以把正式部署的访问地址也写到文档中 122 | 123 | 124 | 125 | 1. 为了方便其他不使用 AI 的人了解有哪些资源,可以在生成之后,同时生成一个 cloudbaserc.json,并支持使用 @cloudbase/cli来部署,提供 AI 调用 MCP 部署之外的另外一个选项 126 | 127 | 128 | 129 | 0. web 构建项目流程:确保首先执行过 npm install 命令,然后参考项目说明进行构建 130 | 1. 部署云函数流程:可以通过 listFunctions MCP 工具来查询是否有云函数,然后直接调用 createFunction 或者 updateFunctionCode 更新云函数代码,只需要将functionRootPath 指向云函数目录的父目录(例如 cloudfuncitons 这个目录的绝对路径),不需要压缩代码等操作,上述工具会自动读取云函数父目录下的云函数同名目录的文件,并自动进行部署 131 | 2. 部署静态托管流程:通过使用 uploadFiles 工具部署,部署完毕后提醒用户 CDN 有几分钟缓存,可以生成一个带有随机 queryString 的markdown 格式 访问链接 132 | 3. 下载远程素材链接 :使用 downloadRemoteFile 工具下载文件到本地,如果需要远程链接,可以继续调用 uploadFile 上传后获得临时访问链接和云存储的 cloudId 133 | 4. 从知识库查询专业知识:可以使用 searchKnowledgeBase 工具智能检索云开发知识库(支持云开发与云函数、小程序前端知识等),通过向量搜索快速获取专业文档与答案 134 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /mcp/DOC.md: -------------------------------------------------------------------------------- 1 | # 云开发基础能力 MCP 接入 2 | 3 | 支持通过 MCP 协议来管理云开发基础能力,包括云开发环境管理、静态网站部署,数据库集合管理、数据库文档操作等。 4 | 5 | [前往云开发平台运行 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-tcb) 6 | 7 | 8 | --- 9 | 10 | ## 功能特点 11 | 12 | - **☁️ 云开发环境管理**:提供获取所有云开发环境信息、获取环境合法域名列表、添加和删除安全域名、获取和修改当前环境信息等功能。 13 | - **💻 数据库集合管理**:支持创建、检查存在、更新、获取详细信息、列出集合、检查索引存在、查询数据分布等数据库集合相关操作。 14 | - **📒 数据库文档操作**:可向集合中插入文档、查询文档、更新文档、删除文档。 15 | - **🌍 静态托管管理**:实现上传文件到静态网站托管、获取文件列表、删除文件或文件夹、搜索文件、绑定和解绑自定义域名、获取静态网站配置、检查域名配置、修改域名配置等功能。 16 | - **💻临时文件管理**:能在临时目录创建文件,支持文本内容或 base64 编码的二进制内容;读取临时目录中的文件,支持文本和二进制文件。 17 | 18 | ## 使用示例 19 | 20 | ![](https://tcb-advanced-a656fc-1257967285.tcloudbaseapp.com/resources/2025-04/lowcode-2256227) 21 | 22 | ## 使用说明 23 | 24 | ### 远程 MCP 25 | 26 | 本项目支持[一键部署到腾讯云开发平台](https://docs.cloudbase.net/ai/mcp/develop/host-mcp),提供远程 SSE 访问 27 | 28 | [☁️ 前往云开发平台部署 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-alapi-cn) 29 | 30 | 部署完毕之后,可参考页面中的使用 MCP 说明,使用远程 SSE 访问 MCP Server。 31 | 32 | ### 本地 MCP 33 | 34 | 在支持 MCP 的本地客户端运行时,也可以使用通过 `npx` 来调用 `cloudbase-mcp` 工具。 35 | 36 | ```js 37 | { 38 | "mcpServers": { 39 | "cloudbase-mcp": { 40 | "command": "npx", 41 | "args": ["@cloudbase/cloudbase-mcp@latest"], 42 | "env": { 43 | "TENCENTCLOUD_SECRETID": "腾讯云 SecretId", 44 | "TENCENTCLOUD_SECRETKEY": "腾讯云 SecretKey", 45 | "TENCENTCLOUD_SESSIONTOKEN": "腾讯云临时密钥Token,如果使用临时密钥才需要传入", 46 | "CLOUDBASE_ENV_ID": "云开发环境 ID" 47 | } 48 | } 49 | } 50 | } 51 | ``` 52 | 53 | ## 环境变量 54 | 55 | 56 | - 需要将 `TENCENTCLOUD_SECRETID` 和 `TENCENTCLOUD_SECRETKEY` / `TENCENTCLOUD_SESSIONTOKEN`配置为**您在云开发控制台获取的 SecretId 和 SecretKey** ([获取腾讯云 API 密钥](https://console.cloud.tencent.com/cam/capi)) 57 | - 需要将 `CLOUDBASE_ENV_ID` 配置为**您在云开发控制台获取的环境 ID**, [获取云开发环境 ID](https://tcb.cloud.tencent.com/dev) 58 | 59 | 60 | --- 61 | 62 | ## 🗺️ 功能清单 63 | 64 | ### 云开发环境管理 65 | 66 | | 工具标识 | 功能描述 | 核心参数 | 67 | |---------------------------|-----------------------------------------|---------------------------------------------------------------------------------------------| 68 | | `listEnvs` | 获取所有云开发环境信息 | 无 | 69 | | `getEnvAuthDomains` | 获取云开发环境的合法域名列表 | 无 | 70 | | `createEnvDomain` | 为云开发环境添加安全域名 | `domains`(必填,安全域名数组) | 71 | | `deleteEnvDomain` | 删除云开发环境的指定安全域名 | `domains`(必填,安全域名数组) | 72 | | `getEnvInfo` | 获取当前云开发环境信息 | 无 | 73 | | `updateEnvInfo` | 修改云开发环境别名 | `alias`(必填,环境别名) | 74 | 75 | 76 | --- 77 | 78 | ### 数据库集合管理 79 | 80 | | 工具标识 | 功能描述 | 核心参数 | 81 | |---------------------------|-----------------------------------------|---------------------------------------------------------------------------------------------| 82 | | `createCollection` | 创建一个新的云开发数据库集合 | `collectionName`(必填,集合名称) | 83 | | `checkCollectionExists` | 检查云开发数据库集合是否存在 | `collectionName`(必填,集合名称) | 84 | | `updateCollection` | 更新云开发数据库集合配置(创建或删除索引) | `collectionName`(必填,集合名称),`options`(必填,更新选项,支持创建和删除索引) | 85 | | `describeCollection` | 获取云开发数据库集合的详细信息 | `collectionName`(必填,集合名称) | 86 | | `listCollections` | 获取云开发数据库集合列表 | `offset`(选填,偏移量),`limit`(选填,返回数量限制) | 87 | | `checkIndexExists` | 检查索引是否存在 | `collectionName`(必填,集合名称),`indexName`(必填,索引名称) | 88 | | `distribution` | 查询数据库中集合的数据分布情况 | 无 | 89 | 90 | --- 91 | 92 | ### 数据库文档操作 93 | 94 | | 工具标识 | 功能描述 | 核心参数 | 95 | |---------------------------|-----------------------------------------|---------------------------------------------------------------------------------------------| 96 | | `insertDocuments` | 向集合中插入一个或多个文档 | `collectionName`(必填,集合名称),`documents`(必填,要插入的文档数组,每个文档为 JSON 字符串) | 97 | | `queryDocuments` | 查询集合中的文档 | `collectionName`(必填,集合名称),`query`(选填,查询条件,JSON 字符串),`projection`(选填,返回字段投影,JSON 字符串),`sort`(选填,排序条件,JSON 字符串),`limit`(选填,返回数量限制),`offset`(选填,跳过的记录数) | 98 | | `updateDocuments` | 更新集合中的文档 | `collectionName`(必填,集合名称),`query`(必填,查询条件,JSON 字符串),`update`(必填,更新内容,JSON 字符串),`isMulti`(选填,是否更新多条记录),`upsert`(选填,是否在不存在时插入) | 99 | | `deleteDocuments` | 删除集合中的文档 | `collectionName`(必填,集合名称),`query`(必填,查询条件,JSON 字符串),`isMulti`(选填,是否删除多条记录) | 100 | 101 | --- 102 | 103 | ### 静态托管管理 104 | 105 | | 工具标识 | 功能描述 | 核心参数 | 106 | |---------------------------|-----------------------------------------|---------------------------------------------------------------------------------------------| 107 | | `uploadFiles` | 上传文件到静态网站托管 | `localPath`(选填,本地文件或文件夹路径),`cloudPath`(选填,云端文件或文件夹路径),`files`(选填,多文件上传配置),`ignore`(选填,忽略文件模式) | 108 | | `listFiles` | 获取静态网站托管的文件列表 | 无 | 109 | | `deleteFiles` | 删除静态网站托管的文件或文件夹 | `cloudPath`(必填,云端文件或文件夹路径),`isDir`(选填,是否为文件夹,默认为 `false`) | 110 | | `findFiles` | 搜索静态网站托管的文件 | `prefix`(必填,匹配前缀),`marker`(选填,起始对象键标记),`maxKeys`(选填,单次返回最大条目数) | 111 | | `createHostingDomain` | 绑定自定义域名 | `domain`(必填,自定义域名),`certId`(必填,证书 ID) | 112 | | `deleteHostingDomain` | 解绑自定义域名 | `domain`(必填,自定义域名) | 113 | | `getWebsiteConfig` | 获取静态网站配置 | 无 | 114 | | `tcbCheckResource` | 检查域名配置 | `domains`(必填,域名列表) | 115 | | `tcbModifyAttribute` | 修改域名配置 | `domain`(必填,域名),`domainId`(必填,域名 ID),`domainConfig`(必填,域名配置) | 116 | 117 | --- 118 | 119 | ### 临时文件管理 120 | 121 | | 工具标识 | 功能描述 | 核心参数 | 122 | |---------------------------|-----------------------------------------|---------------------------------------------------------------------------------------------| 123 | | `createTempFile` | 在临时目录创建文件,支持文本内容或 base64 编码的二进制内容 | `content`(必填,文件内容,可以是普通文本或 base64 编码的二进制内容),`isBase64`(选填,是否为 base64 编码,默认为 `false`),`extension`(选填,文件扩展名,如 `.txt`, `.png` 等) | 124 | | `readTempFile` | 读取临时目录中的文件,支持文本和二进制文件 | `filePath`(必填,文件路径),`asBase64`(选填,是否以 base64 格式返回内容,默认为 `false`) | 125 | 126 | 127 | 128 | --- 129 | 130 | ## 🔌 使用方式 131 | 132 | - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) 133 | - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) 134 | - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) 135 | 136 | --- 137 | 138 | [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) 139 | -------------------------------------------------------------------------------- /mcp/Dockerfile: -------------------------------------------------------------------------------- 1 | # 使用 Node.js 官方 Alpine 镜像作为基础 2 | FROM node:20-alpine 3 | 4 | # 配置腾讯云镜像源 5 | RUN npm config set registry https://mirrors.cloud.tencent.com/npm/ \ 6 | && yarn config set registry https://mirrors.cloud.tencent.com/npm/ 7 | 8 | # 配置 Alpine 国内镜像源 9 | RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tencent.com/g' /etc/apk/repositories 10 | 11 | # 安装 Python(自动创建 python/pip 链接) 12 | RUN apk update \ 13 | && apk add --no-cache python3 py3-pip \ 14 | && apk add curl 15 | 16 | # 如果你的项目是一个 python 项目,推荐全局安装,提升运行态的性能 17 | # 例如 RUN pip3 install --break-system-packages mysql-mcp-server 18 | RUN pip3 install --break-system-packages uv 19 | 20 | ## 全局安装必须的 npm 依赖 21 | ## @cloudbase/mcp-transformer 必须安装 22 | ## 如果你的项目是一个 npm 包,推荐全局安装,提升运行态的性能 23 | RUN npm install -g @cloudbase/mcp-transformer @cloudbase/cloudbase-mcp 24 | 25 | # 固定暴露端口 26 | EXPOSE 80 27 | 28 | # 启动命令 29 | ## 这里是使用 cloudbase-mcp-transformer 命令来将 Stdio 转换为远程 MCP 服务 30 | ## --stdioCmd 是指定需要转换的命令,其中可以引用环境变量,例如 $USER、$PASSWORD、$HOST、$PORT、$DATABASE 31 | ## 在创建云托管服务的时候,用户可以指定环境变量 32 | ## 如果你的项目依赖环境变量,需要在 mcp-meta.json 中进行声明 33 | ## --port 是指定转换后的服务端口,默认为 3000 34 | CMD cloudbase-mcp-transformer stdioToCloudrun --stdioCmd "cloudbase-mcp" --port 3000 -------------------------------------------------------------------------------- /mcp/Intro.md: -------------------------------------------------------------------------------- 1 | # 云开发基础能力 MCP 接入 2 | 3 | 支持通过 MCP 协议来管理云开发基础能力,包括云开发环境管理、静态网站部署,数据库集合管理、数据库文档操作等。 4 | 5 | [前往云开发平台运行 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-tcb) 6 | 7 | 8 | --- 9 | 10 | ## 功能特点 11 | 12 | - **☁️ 云开发环境管理**:提供获取所有云开发环境信息、获取环境合法域名列表、添加和删除安全域名、获取和修改当前环境信息等功能。 13 | - **💻 数据库集合管理**:支持创建、检查存在、更新、获取详细信息、列出集合、检查索引存在、查询数据分布等数据库集合相关操作。 14 | - **📒 数据库文档操作**:可向集合中插入文档、查询文档、更新文档、删除文档。 15 | - **🌍 静态托管管理**:实现上传文件到静态网站托管、获取文件列表、删除文件或文件夹、搜索文件、绑定和解绑自定义域名、获取静态网站配置、检查域名配置、修改域名配置等功能。 16 | - **💻临时文件管理**:能在临时目录创建文件,支持文本内容或 base64 编码的二进制内容;读取临时目录中的文件,支持文本和二进制文件。 17 | 18 | ## 使用示例 19 | 20 | ![](https://tcb-advanced-a656fc-1257967285.tcloudbaseapp.com/resources/2025-04/lowcode-2256227) 21 | 22 | ## 使用说明 23 | 24 | ### 远程 MCP 25 | 26 | 本项目支持[一键部署到腾讯云开发平台](https://docs.cloudbase.net/ai/mcp/develop/host-mcp),提供远程 SSE 访问 27 | 28 | [☁️ 前往云开发平台部署 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-alapi-cn) 29 | 30 | 部署完毕之后,可参考页面中的使用 MCP 说明,使用远程 SSE 访问 MCP Server。 31 | 32 | ### 本地 MCP 33 | 34 | 在支持 MCP 的本地客户端运行时,也可以使用通过 `npx` 来调用 `cloudbase-mcp` 工具。 35 | 36 | ```js 37 | { 38 | "mcpServers": { 39 | "cloudbase-mcp": { 40 | "command": "npx", 41 | "args": ["@cloudbase/cloudbase-mcp@latest"], 42 | "env": { 43 | "TENCENTCLOUD_SECRETID": "腾讯云 SecretId", 44 | "TENCENTCLOUD_SECRETKEY": "腾讯云 SecretKey", 45 | "TENCENTCLOUD_SESSIONTOKEN": "腾讯云临时密钥Token,如果使用临时密钥才需要传入", 46 | "CLOUDBASE_ENV_ID": "云开发环境 ID" 47 | } 48 | } 49 | } 50 | } 51 | ``` 52 | 53 | ## 环境变量 54 | 55 | 56 | - 需要将 `TENCENTCLOUD_SECRETID` 和 `TENCENTCLOUD_SECRETKEY` / `TENCENTCLOUD_SESSIONTOKEN`配置为**您在云开发控制台获取的 SecretId 和 SecretKey** ([获取腾讯云 API 密钥](https://console.cloud.tencent.com/cam/capi)) 57 | - 需要将 `CLOUDBASE_ENV_ID` 配置为**您在云开发控制台获取的环境 ID**, [获取云开发环境 ID](https://tcb.cloud.tencent.com/dev) 58 | 59 | 60 | --- 61 | 62 | ## 🗺️ 功能清单 63 | 64 | ### 云开发环境管理 65 | 66 | | 工具标识 | 功能描述 | 核心参数 | 67 | |---------------------------|-----------------------------------------|---------------------------------------------------------------------------------------------| 68 | | `listEnvs` | 获取所有云开发环境信息 | 无 | 69 | | `getEnvAuthDomains` | 获取云开发环境的合法域名列表 | 无 | 70 | | `createEnvDomain` | 为云开发环境添加安全域名 | `domains`(必填,安全域名数组) | 71 | | `deleteEnvDomain` | 删除云开发环境的指定安全域名 | `domains`(必填,安全域名数组) | 72 | | `getEnvInfo` | 获取当前云开发环境信息 | 无 | 73 | | `updateEnvInfo` | 修改云开发环境别名 | `alias`(必填,环境别名) | 74 | 75 | 76 | --- 77 | 78 | ### 数据库集合管理 79 | 80 | | 工具标识 | 功能描述 | 核心参数 | 81 | |---------------------------|-----------------------------------------|---------------------------------------------------------------------------------------------| 82 | | `createCollection` | 创建一个新的云开发数据库集合 | `collectionName`(必填,集合名称) | 83 | | `checkCollectionExists` | 检查云开发数据库集合是否存在 | `collectionName`(必填,集合名称) | 84 | | `updateCollection` | 更新云开发数据库集合配置(创建或删除索引) | `collectionName`(必填,集合名称),`options`(必填,更新选项,支持创建和删除索引) | 85 | | `describeCollection` | 获取云开发数据库集合的详细信息 | `collectionName`(必填,集合名称) | 86 | | `listCollections` | 获取云开发数据库集合列表 | `offset`(选填,偏移量),`limit`(选填,返回数量限制) | 87 | | `checkIndexExists` | 检查索引是否存在 | `collectionName`(必填,集合名称),`indexName`(必填,索引名称) | 88 | | `distribution` | 查询数据库中集合的数据分布情况 | 无 | 89 | 90 | --- 91 | 92 | ### 数据库文档操作 93 | 94 | | 工具标识 | 功能描述 | 核心参数 | 95 | |---------------------------|-----------------------------------------|---------------------------------------------------------------------------------------------| 96 | | `insertDocuments` | 向集合中插入一个或多个文档 | `collectionName`(必填,集合名称),`documents`(必填,要插入的文档数组,每个文档为 JSON 字符串) | 97 | | `queryDocuments` | 查询集合中的文档 | `collectionName`(必填,集合名称),`query`(选填,查询条件,JSON 字符串),`projection`(选填,返回字段投影,JSON 字符串),`sort`(选填,排序条件,JSON 字符串),`limit`(选填,返回数量限制),`offset`(选填,跳过的记录数) | 98 | | `updateDocuments` | 更新集合中的文档 | `collectionName`(必填,集合名称),`query`(必填,查询条件,JSON 字符串),`update`(必填,更新内容,JSON 字符串),`isMulti`(选填,是否更新多条记录),`upsert`(选填,是否在不存在时插入) | 99 | | `deleteDocuments` | 删除集合中的文档 | `collectionName`(必填,集合名称),`query`(必填,查询条件,JSON 字符串),`isMulti`(选填,是否删除多条记录) | 100 | 101 | --- 102 | 103 | ### 静态托管管理 104 | 105 | | 工具标识 | 功能描述 | 核心参数 | 106 | |---------------------------|-----------------------------------------|---------------------------------------------------------------------------------------------| 107 | | `uploadFiles` | 上传文件到静态网站托管 | `localPath`(选填,本地文件或文件夹路径),`cloudPath`(选填,云端文件或文件夹路径),`files`(选填,多文件上传配置),`ignore`(选填,忽略文件模式) | 108 | | `listFiles` | 获取静态网站托管的文件列表 | 无 | 109 | | `deleteFiles` | 删除静态网站托管的文件或文件夹 | `cloudPath`(必填,云端文件或文件夹路径),`isDir`(选填,是否为文件夹,默认为 `false`) | 110 | | `findFiles` | 搜索静态网站托管的文件 | `prefix`(必填,匹配前缀),`marker`(选填,起始对象键标记),`maxKeys`(选填,单次返回最大条目数) | 111 | | `createHostingDomain` | 绑定自定义域名 | `domain`(必填,自定义域名),`certId`(必填,证书 ID) | 112 | | `deleteHostingDomain` | 解绑自定义域名 | `domain`(必填,自定义域名) | 113 | | `getWebsiteConfig` | 获取静态网站配置 | 无 | 114 | | `tcbCheckResource` | 检查域名配置 | `domains`(必填,域名列表) | 115 | | `tcbModifyAttribute` | 修改域名配置 | `domain`(必填,域名),`domainId`(必填,域名 ID),`domainConfig`(必填,域名配置) | 116 | 117 | --- 118 | 119 | ### 临时文件管理 120 | 121 | | 工具标识 | 功能描述 | 核心参数 | 122 | |---------------------------|-----------------------------------------|---------------------------------------------------------------------------------------------| 123 | | `createTempFile` | 在临时目录创建文件,支持文本内容或 base64 编码的二进制内容 | `content`(必填,文件内容,可以是普通文本或 base64 编码的二进制内容),`isBase64`(选填,是否为 base64 编码,默认为 `false`),`extension`(选填,文件扩展名,如 `.txt`, `.png` 等) | 124 | | `readTempFile` | 读取临时目录中的文件,支持文本和二进制文件 | `filePath`(必填,文件路径),`asBase64`(选填,是否以 base64 格式返回内容,默认为 `false`) | 125 | 126 | 127 | 128 | --- 129 | 130 | ## 🔌 使用方式 131 | 132 | - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) 133 | - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) 134 | - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) 135 | 136 | --- 137 | 138 | [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) 139 | -------------------------------------------------------------------------------- /mcp/VERSION: -------------------------------------------------------------------------------- 1 | 0.0.2 -------------------------------------------------------------------------------- /mcp/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mcp-tcb", 3 | "title": "云开发基础能力", 4 | "description": "支持通过 MCP 协议来管理云开发基础能力,包括云开发环境管理、静态网站部署,数据库集合管理、数据库文档操作等。", 5 | "author": { 6 | "name": "云开发", 7 | "avatar": "cloud://tcb-advanced-a656fc.7463-tcb-advanced-a656fc-1257967285/weda-uploader/ea7adbf26fbfed25b2f79b118628b73b-logo.svg" 8 | }, 9 | "container_image": "crunbuild-az-new.tencentcloudcr.com/cloudbase/cloudrun-mcp-tcb:0.0.1", 10 | "tags": [ 11 | "云开发", 12 | "环境管理", 13 | "数据库管理", 14 | "静态托管" 15 | ], 16 | "port": 3000, 17 | "logo": [ 18 | "cloud://tcb-advanced-a656fc.7463-tcb-advanced-a656fc-1257967285/weda-uploader/ea7adbf26fbfed25b2f79b118628b73b-logo.svg" 19 | ], 20 | "memory": 0.5, 21 | "cpu": 0.25, 22 | "min_instances": 1, 23 | "max_instances": 1, 24 | "env_params": { 25 | "TENCENTCLOUD_SECRETID": "腾讯云 SecretId", 26 | "TENCENTCLOUD_SECRETKEY": "腾讯云 SecretKey", 27 | "CLOUDBASE_ENV_ID": "云开发环境 ID", 28 | "NODE_INSTANCE": "1" 29 | }, 30 | "transport": "sse" 31 | } -------------------------------------------------------------------------------- /mcp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@cloudbase/cloudbase-mcp", 3 | "version": "1.7.2", 4 | "description": "腾讯云开发 MCP Server,支持静态托管/环境查询/", 5 | "main": "index.js", 6 | "type": "module", 7 | "bin": { 8 | "cloudbase-mcp": "./dist/index.js" 9 | }, 10 | "homepage": "https://github.com/TencentCloudBase/CloudBase-AI-ToolKit", 11 | "bugs": { 12 | "url": "https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/issues", 13 | "email": "bookerzhao@tencent.com" 14 | }, 15 | "scripts": { 16 | "clean": "rm -rf dist", 17 | "prebuild": "npm run clean", 18 | "build": "tsc && chmod 755 dist/index.js", 19 | "prepublishOnly": "npm run build" 20 | }, 21 | "files": [ 22 | "dist" 23 | ], 24 | "keywords": [], 25 | "author": "", 26 | "license": "MIT", 27 | "dependencies": { 28 | "@cloudbase/manager-node": "^4.2.10", 29 | "@cloudbase/mcp": "^1.0.0-beta.25", 30 | "@cloudbase/toolbox": "^0.7.5", 31 | "@modelcontextprotocol/sdk": "1.9.0", 32 | "@types/unzipper": "^0.10.11", 33 | "cors": "^2.8.5", 34 | "express": "^5.1.0", 35 | "open": "^10.1.2", 36 | "unzipper": "^0.12.3", 37 | "ws": "^8.18.2", 38 | "zod": "^3.24.3" 39 | }, 40 | "devDependencies": { 41 | "@types/express": "^5.0.3", 42 | "@types/node": "^22.14.1", 43 | "@types/ws": "^8.18.1", 44 | "typescript": "^5.8.3" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /mcp/src/auth.ts: -------------------------------------------------------------------------------- 1 | import { AuthSupevisor } from '@cloudbase/toolbox' 2 | import { debug,error } from './utils/logger.js'; 3 | 4 | const auth = AuthSupevisor.getInstance({ 5 | }) 6 | 7 | export async function getLoginState() { 8 | const { 9 | TENCENTCLOUD_SECRETID, 10 | TENCENTCLOUD_SECRETKEY, 11 | TENCENTCLOUD_SESSIONTOKEN 12 | } = process.env 13 | debug('TENCENTCLOUD_SECRETID',TENCENTCLOUD_SECRETID) 14 | if (TENCENTCLOUD_SECRETID && TENCENTCLOUD_SECRETKEY) { 15 | debug('loginByApiSecret') 16 | await auth.loginByApiSecret(TENCENTCLOUD_SECRETID, TENCENTCLOUD_SECRETKEY, TENCENTCLOUD_SESSIONTOKEN) 17 | } 18 | const loginState = await auth.getLoginState() 19 | if (!loginState) { 20 | debug('loginByApiSecret') 21 | await auth.loginByWebAuth({}) 22 | const loginState = await auth.getLoginState() 23 | return loginState 24 | } else { 25 | return loginState 26 | } 27 | } 28 | 29 | export async function logout() { 30 | const result = await auth.logout() 31 | return result 32 | } -------------------------------------------------------------------------------- /mcp/src/cloudbase-manager.ts: -------------------------------------------------------------------------------- 1 | import { getLoginState } from './auth.js' 2 | import { ensureEnvId, autoSetupEnvironmentId } from './tools/interactive.js' 3 | import CloudBase from "@cloudbase/manager-node"; 4 | import { debug,error } from './utils/logger.js'; 5 | 6 | let initializationPromise: Promise | null = null; 7 | let noEnvIdInitializationPromise: Promise | null = null; 8 | const INITIALIZATION_TIMEOUT = 30000; // 30 seconds 9 | 10 | interface GetManagerOptions { 11 | requireEnvId?: boolean; 12 | } 13 | 14 | export function getCloudBaseManager(options: GetManagerOptions = {}): Promise { 15 | const { requireEnvId = true } = options; 16 | 17 | if (requireEnvId) { 18 | if (initializationPromise) { 19 | return initializationPromise; 20 | } 21 | 22 | const executor = async (): Promise => { 23 | try { 24 | // 检查并确保环境ID已配置 25 | let userEnvId = await ensureEnvId(); 26 | if (!userEnvId) { 27 | debug("未找到环境ID,尝试自动设置..."); 28 | userEnvId = await autoSetupEnvironmentId(); 29 | 30 | if (!userEnvId) { 31 | throw new Error("CloudBase Environment ID not found after auto setup. Please set CLOUDBASE_ENV_ID or run setupEnvironmentId tool."); 32 | } 33 | } 34 | 35 | const loginState = await getLoginState() 36 | const { 37 | envId, 38 | secretId, 39 | secretKey, 40 | token 41 | } = loginState; 42 | 43 | const manager = new CloudBase({ 44 | secretId, 45 | secretKey, 46 | envId: userEnvId, 47 | token, 48 | proxy: process.env.http_proxy 49 | }); 50 | 51 | return manager; 52 | } catch (err) { 53 | error('Failed to initialize CloudBase Manager:', err); 54 | throw err; 55 | } 56 | }; 57 | 58 | const timeoutPromise = new Promise((_, reject) => { 59 | const id = setTimeout(() => { 60 | clearTimeout(id); 61 | reject(new Error(`CloudBase Manager initialization timed out after ${INITIALIZATION_TIMEOUT / 1000} seconds.`)); 62 | }, INITIALIZATION_TIMEOUT); 63 | }); 64 | 65 | initializationPromise = Promise.race([executor(), timeoutPromise]); 66 | 67 | initializationPromise.catch(() => { 68 | initializationPromise = null; 69 | }); 70 | 71 | return initializationPromise; 72 | } 73 | 74 | if (noEnvIdInitializationPromise) { 75 | return noEnvIdInitializationPromise; 76 | } 77 | 78 | const noEnvIdExecutor = async (): Promise => { 79 | try { 80 | const loginState = await getLoginState(); 81 | const { 82 | secretId, 83 | secretKey, 84 | token 85 | } = loginState; 86 | 87 | const manager = new CloudBase({ 88 | secretId, 89 | secretKey, 90 | token, 91 | proxy: process.env.http_proxy 92 | }); 93 | 94 | return manager; 95 | } catch (err) { 96 | error('Failed to initialize CloudBase Manager (no envId):', err instanceof Error ? err.message : String(err)); 97 | throw err; 98 | } 99 | }; 100 | 101 | const timeoutPromise = new Promise((_, reject) => { 102 | const id = setTimeout(() => { 103 | clearTimeout(id); 104 | reject(new Error(`CloudBase Manager (no envId) initialization timed out after ${INITIALIZATION_TIMEOUT / 1000} seconds.`)); 105 | }, INITIALIZATION_TIMEOUT); 106 | }); 107 | 108 | noEnvIdInitializationPromise = Promise.race([noEnvIdExecutor(), timeoutPromise]); 109 | 110 | noEnvIdInitializationPromise.catch(() => { 111 | noEnvIdInitializationPromise = null; 112 | }); 113 | 114 | return noEnvIdInitializationPromise; 115 | } -------------------------------------------------------------------------------- /mcp/src/index.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; 4 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; 5 | import { registerEnvTools } from "./tools/env.js"; 6 | import { registerFileTools } from "./tools/file.js"; 7 | import { registerFunctionTools } from "./tools/functions.js"; 8 | import { registerDatabaseTools } from "./tools/database.js"; 9 | import { registerHostingTools } from "./tools/hosting.js"; 10 | import { registerDownloadTools } from "./tools/download.js"; 11 | import { registerStorageTools } from "./tools/storage.js"; 12 | import { registerRagTools } from './tools/rag.js'; 13 | import { registerSetupTools } from "./tools/setup.js"; 14 | import { registerInteractiveTools } from "./tools/interactive.js"; 15 | 16 | // Create server instance 17 | const server = new McpServer({ 18 | name: "cloudbase-mcp", 19 | version: "1.0.0", 20 | capabilities: { 21 | resources: {}, 22 | tools: {}, 23 | }, 24 | }); 25 | 26 | // Register environment management tools 27 | registerEnvTools(server); 28 | 29 | // Register RAG tools 30 | registerRagTools(server) 31 | 32 | // // Register file management tools 33 | // registerFileTools(server); 34 | 35 | // Register database management tools 36 | registerDatabaseTools(server); 37 | 38 | // Register hosting management tools 39 | registerHostingTools(server); 40 | 41 | // Register function management tools 42 | registerFunctionTools(server); 43 | 44 | // Register download tools 45 | registerDownloadTools(server); 46 | 47 | // Register storage tools 48 | registerStorageTools(server); 49 | 50 | // Register setup tools 51 | registerSetupTools(server); 52 | 53 | // Register interactive tools 54 | registerInteractiveTools(server); 55 | 56 | async function main() { 57 | const transport = new StdioServerTransport(); 58 | await server.connect(transport); 59 | console.log("TencentCloudBase MCP Server running on stdio"); 60 | } 61 | 62 | main().catch((error) => { 63 | console.error("Fatal error in main():", error); 64 | process.exit(1); 65 | }); -------------------------------------------------------------------------------- /mcp/src/tools/download.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; 3 | import * as fsPromises from "fs/promises"; 4 | import * as fs from "fs"; 5 | import * as path from "path"; 6 | import * as os from "os"; 7 | import * as crypto from "crypto"; 8 | import * as https from "https"; 9 | import * as http from "http"; 10 | import { URL } from "url"; 11 | import * as net from "net"; 12 | import * as dns from "dns"; 13 | import { getCloudBaseManager } from '../cloudbase-manager.js' 14 | 15 | // 常量定义 16 | const MAX_FILE_SIZE = 100 * 1024 * 1024; // 100MB 17 | const ALLOWED_PROTOCOLS = ["http:", "https:"]; 18 | const ALLOWED_CONTENT_TYPES = [ 19 | "text/", 20 | "image/", 21 | "application/json", 22 | "application/xml", 23 | "application/pdf", 24 | "application/zip", 25 | "application/x-zip-compressed" 26 | ]; 27 | 28 | // 检查是否为内网 IP 29 | function isPrivateIP(ip: string): boolean { 30 | // 如果不是有效的 IP 地址,返回 true(保守处理) 31 | if (!net.isIP(ip)) { 32 | return true; 33 | } 34 | 35 | // 检查特殊地址 36 | if (ip === '127.0.0.1' || 37 | ip === 'localhost' || 38 | ip === '::1' || // IPv6 本地回环 39 | ip.startsWith('169.254.') || // 链路本地地址 40 | ip.startsWith('0.')) { // 特殊用途地址 41 | return true; 42 | } 43 | 44 | // 转换 IP 地址为长整数进行范围检查 45 | const ipv4Parts = ip.split('.').map(part => parseInt(part, 10)); 46 | if (ipv4Parts.length === 4) { 47 | const ipNum = (ipv4Parts[0] << 24) + (ipv4Parts[1] << 16) + (ipv4Parts[2] << 8) + ipv4Parts[3]; 48 | 49 | // 检查私有 IP 范围 50 | // 10.0.0.0 - 10.255.255.255 51 | if (ipNum >= 167772160 && ipNum <= 184549375) return true; 52 | 53 | // 172.16.0.0 - 172.31.255.255 54 | if (ipNum >= 2886729728 && ipNum <= 2887778303) return true; 55 | 56 | // 192.168.0.0 - 192.168.255.255 57 | if (ipNum >= 3232235520 && ipNum <= 3232301055) return true; 58 | } 59 | 60 | // 检查 IPv6 私有地址 61 | if (net.isIPv6(ip)) { 62 | const normalizedIP = ip.toLowerCase(); 63 | if (normalizedIP.startsWith('fc00:') || // 唯一本地地址 64 | normalizedIP.startsWith('fe80:') || // 链路本地地址 65 | normalizedIP.startsWith('fec0:') || // 站点本地地址 66 | normalizedIP.startsWith('::1')) { // 本地回环 67 | return true; 68 | } 69 | } 70 | 71 | return false; 72 | } 73 | 74 | // 检查域名是否解析到内网 IP 75 | async function doesDomainResolveToPrivateIP(hostname: string): Promise { 76 | try { 77 | const addresses = await new Promise((resolve, reject) => { 78 | dns.resolve(hostname, (err, addresses) => { 79 | if (err) reject(err); 80 | else resolve(addresses); 81 | }); 82 | }); 83 | 84 | return addresses.some(ip => isPrivateIP(ip)); 85 | } catch (error) { 86 | // 如果解析失败,为安全起见返回 true 87 | return true; 88 | } 89 | } 90 | 91 | // 生成随机文件名 92 | function generateRandomFileName(extension = '') { 93 | const randomBytes = crypto.randomBytes(16); 94 | const fileName = randomBytes.toString('hex'); 95 | return `${fileName}${extension}`; 96 | } 97 | 98 | // 获取安全的临时文件路径 99 | function getSafeTempFilePath(fileName: string) { 100 | return path.join(os.tmpdir(), fileName); 101 | } 102 | 103 | // 从 URL 或 Content-Disposition 获取文件扩展名 104 | function getFileExtension(url: string, contentType: string, contentDisposition?: string): string { 105 | let extension = ""; 106 | 107 | // 从 URL 获取扩展名 108 | const urlPath = new URL(url).pathname; 109 | const urlExt = path.extname(urlPath); 110 | if (urlExt) { 111 | extension = urlExt; 112 | } 113 | 114 | // 从 Content-Disposition 获取扩展名 115 | if (contentDisposition) { 116 | const filenameMatch = contentDisposition.match(/filename=["']?([^"']+)["']?/); 117 | if (filenameMatch) { 118 | const dispositionExt = path.extname(filenameMatch[1]); 119 | if (dispositionExt) { 120 | extension = dispositionExt; 121 | } 122 | } 123 | } 124 | 125 | // 从 Content-Type 获取扩展名 126 | if (!extension && contentType) { 127 | const mimeToExt: { [key: string]: string } = { 128 | "text/plain": ".txt", 129 | "text/html": ".html", 130 | "text/css": ".css", 131 | "text/javascript": ".js", 132 | "image/jpeg": ".jpg", 133 | "image/png": ".png", 134 | "image/gif": ".gif", 135 | "image/webp": ".webp", 136 | "application/json": ".json", 137 | "application/xml": ".xml", 138 | "application/pdf": ".pdf", 139 | "application/zip": ".zip", 140 | "application/x-zip-compressed": ".zip" 141 | }; 142 | extension = mimeToExt[contentType] || ""; 143 | } 144 | 145 | return extension; 146 | } 147 | 148 | // 验证 URL 和内容类型是否安全 149 | async function isUrlAndContentTypeSafe(url: string, contentType: string): Promise { 150 | try { 151 | const parsedUrl = new URL(url); 152 | 153 | // 检查协议 154 | if (!ALLOWED_PROTOCOLS.includes(parsedUrl.protocol)) { 155 | return false; 156 | } 157 | 158 | // 检查主机名是否为 IP 地址 159 | const hostname = parsedUrl.hostname; 160 | if (net.isIP(hostname) && isPrivateIP(hostname)) { 161 | return false; 162 | } 163 | 164 | // 如果是域名,检查它是否解析到内网 IP 165 | if (!net.isIP(hostname) && await doesDomainResolveToPrivateIP(hostname)) { 166 | return false; 167 | } 168 | 169 | // 检查内容类型 170 | return ALLOWED_CONTENT_TYPES.some(allowedType => contentType.startsWith(allowedType)); 171 | } catch { 172 | return false; 173 | } 174 | } 175 | 176 | // 下载文件 177 | function downloadFile(url: string): Promise<{ 178 | filePath: string; 179 | contentType: string; 180 | fileSize: number; 181 | }> { 182 | return new Promise((resolve, reject) => { 183 | const client = url.startsWith('https:') ? https : http; 184 | 185 | client.get(url, async (res) => { 186 | if (res.statusCode !== 200) { 187 | reject(new Error(`HTTP Error: ${res.statusCode}`)); 188 | return; 189 | } 190 | 191 | const contentType = res.headers['content-type'] || ''; 192 | const contentLength = parseInt(res.headers['content-length'] || '0', 10); 193 | const contentDisposition = res.headers['content-disposition']; 194 | 195 | // 安全检查 196 | if (!await isUrlAndContentTypeSafe(url, contentType)) { 197 | reject(new Error('不安全的 URL 或内容类型,或者目标为内网地址')); 198 | return; 199 | } 200 | 201 | // 文件大小检查 202 | if (contentLength > MAX_FILE_SIZE) { 203 | reject(new Error(`文件大小 ${contentLength} 字节超过 ${MAX_FILE_SIZE} 字节限制`)); 204 | return; 205 | } 206 | 207 | // 生成临时文件路径 208 | const extension = getFileExtension(url, contentType, contentDisposition); 209 | const fileName = generateRandomFileName(extension); 210 | const filePath = getSafeTempFilePath(fileName); 211 | 212 | // 创建写入流 213 | const fileStream = fs.createWriteStream(filePath); 214 | let downloadedSize = 0; 215 | 216 | res.on('data', (chunk) => { 217 | downloadedSize += chunk.length; 218 | if (downloadedSize > MAX_FILE_SIZE) { 219 | fileStream.destroy(); 220 | fsPromises.unlink(filePath).catch(() => {}); 221 | reject(new Error(`文件大小超过 ${MAX_FILE_SIZE} 字节限制`)); 222 | } 223 | }); 224 | 225 | res.pipe(fileStream); 226 | 227 | fileStream.on('finish', () => { 228 | resolve({ 229 | filePath, 230 | contentType, 231 | fileSize: downloadedSize 232 | }); 233 | }); 234 | 235 | fileStream.on('error', (error: NodeJS.ErrnoException) => { 236 | fsPromises.unlink(filePath).catch(() => {}); 237 | reject(error); 238 | }); 239 | }).on('error', (error: NodeJS.ErrnoException) => { 240 | reject(error); 241 | }); 242 | }); 243 | } 244 | 245 | export function registerDownloadTools(server: McpServer) { 246 | server.tool( 247 | "downloadRemoteFile", 248 | "下载远程文件到本地临时文件,返回一个系统的绝对路径", 249 | { 250 | url: z.string().describe("远程文件的 URL 地址"), 251 | }, 252 | async ({ url }) => { 253 | try { 254 | const result = await downloadFile(url); 255 | 256 | return { 257 | content: [ 258 | { 259 | type: "text", 260 | text: JSON.stringify({ 261 | success: true, 262 | filePath: result.filePath, 263 | contentType: result.contentType, 264 | fileSize: result.fileSize, 265 | message: "文件下载成功" 266 | }, null, 2) 267 | } 268 | ] 269 | }; 270 | } catch (error: any) { 271 | return { 272 | content: [ 273 | { 274 | type: "text", 275 | text: JSON.stringify({ 276 | success: false, 277 | error: error.message, 278 | message: "文件下载失败" 279 | }, null, 2) 280 | } 281 | ] 282 | }; 283 | } 284 | } 285 | ); 286 | } -------------------------------------------------------------------------------- /mcp/src/tools/env.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; 3 | import { getCloudBaseManager } from '../cloudbase-manager.js' 4 | import { logout } from '../auth.js' 5 | import { clearUserEnvId, _promptAndSetEnvironmentId } from './interactive.js' 6 | import { debug } from '../utils/logger.js' 7 | 8 | export function registerEnvTools(server: McpServer) { 9 | // login - 登录云开发环境 10 | server.tool( 11 | "login", 12 | "登录云开发环境并选择要使用的环境", 13 | { 14 | forceUpdate: z.boolean().optional().describe("是否强制重新选择环境") 15 | }, 16 | async ({ forceUpdate = false }) => { 17 | try { 18 | const { selectedEnvId, cancelled, error, noEnvs } = await _promptAndSetEnvironmentId(false); 19 | 20 | debug("login", { selectedEnvId, cancelled, error, noEnvs }); 21 | 22 | if (error) { 23 | return { content: [{ type: "text", text: error }] }; 24 | } 25 | 26 | if (noEnvs) { 27 | return { content: [{ type: "text", text: "当前账户下暂无可用的云开发环境,请先在腾讯云控制台创建环境" }] }; 28 | } 29 | 30 | if (cancelled) { 31 | return { content: [{ type: "text", text: "用户取消了登录" }] }; 32 | } 33 | 34 | if (selectedEnvId) { 35 | return { 36 | content: [{ 37 | type: "text", 38 | text: `✅ 登录成功,当前环境: ${selectedEnvId}` 39 | }] 40 | }; 41 | } 42 | 43 | throw new Error("登录失败"); 44 | } catch (error) { 45 | return { 46 | content: [{ 47 | type: "text", 48 | text: `登录失败: ${error instanceof Error ? error.message : String(error)}` 49 | }] 50 | }; 51 | } 52 | } 53 | ); 54 | 55 | // logout - 退出云开发环境 56 | server.tool( 57 | "logout", 58 | "退出云开发环境", 59 | { 60 | confirm: z.literal("yes").describe("确认操作,默认传 yes") 61 | }, 62 | async () => { 63 | try { 64 | // 登出账户 65 | await logout(); 66 | // 清理环境ID配置 67 | await clearUserEnvId(); 68 | 69 | return { 70 | content: [{ 71 | type: "text", 72 | text: "✅ 已退出登录" 73 | }] 74 | }; 75 | } catch (error) { 76 | return { 77 | content: [{ 78 | type: "text", 79 | text: `退出失败: ${error instanceof Error ? error.message : String(error)}` 80 | }] 81 | }; 82 | } 83 | } 84 | ); 85 | 86 | // listEnvs 87 | server.tool( 88 | "listEnvs", 89 | "获取所有云开发环境信息", 90 | { 91 | confirm: z.literal("yes").describe("确认操作,默认传 yes") 92 | }, 93 | async () => { 94 | const cloudbase = await getCloudBaseManager({ requireEnvId: false }) 95 | const result = await cloudbase.env.listEnvs(); 96 | return { 97 | content: [ 98 | { 99 | type: "text", 100 | text: JSON.stringify(result, null, 2) 101 | } 102 | ] 103 | }; 104 | } 105 | ); 106 | 107 | // getEnvAuthDomains 108 | server.tool( 109 | "getEnvAuthDomains", 110 | "获取云开发环境的合法域名列表", 111 | { 112 | confirm: z.literal("yes").describe("确认操作,默认传 yes") 113 | }, 114 | async () => { 115 | const cloudbase = await getCloudBaseManager() 116 | const result = await cloudbase.env.getEnvAuthDomains(); 117 | return { 118 | content: [ 119 | { 120 | type: "text", 121 | text: JSON.stringify(result, null, 2) 122 | } 123 | ] 124 | }; 125 | } 126 | ); 127 | 128 | // createEnvDomain 129 | server.tool( 130 | "createEnvDomain", 131 | "为云开发环境添加安全域名", 132 | { 133 | domains: z.array(z.string()).describe("安全域名数组") 134 | }, 135 | async ({ domains }) => { 136 | const cloudbase = await getCloudBaseManager() 137 | const result = await cloudbase.env.createEnvDomain(domains); 138 | return { 139 | content: [ 140 | { 141 | type: "text", 142 | text: JSON.stringify(result, null, 2) 143 | } 144 | ] 145 | }; 146 | } 147 | ); 148 | 149 | // deleteEnvDomain 150 | server.tool( 151 | "deleteEnvDomain", 152 | "删除云开发环境的指定安全域名", 153 | { 154 | domains: z.array(z.string()).describe("安全域名数组") 155 | }, 156 | async ({ domains }) => { 157 | const cloudbase = await getCloudBaseManager() 158 | const result = await cloudbase.env.deleteEnvDomain(domains); 159 | return { 160 | content: [ 161 | { 162 | type: "text", 163 | text: JSON.stringify(result, null, 2) 164 | } 165 | ] 166 | }; 167 | } 168 | ); 169 | 170 | // getEnvInfo 171 | server.tool( 172 | "getEnvInfo", 173 | "获取当前云开发环境信息", 174 | { 175 | confirm: z.literal("yes").describe("确认操作,默认传 yes") 176 | }, 177 | async () => { 178 | const cloudbase = await getCloudBaseManager() 179 | const result = await cloudbase.env.getEnvInfo(); 180 | return { 181 | content: [ 182 | { 183 | type: "text", 184 | text: JSON.stringify(result, null, 2) 185 | } 186 | ] 187 | }; 188 | } 189 | ); 190 | 191 | // updateEnvInfo 192 | server.tool( 193 | "updateEnvInfo", 194 | "修改云开发环境别名", 195 | { 196 | alias: z.string().describe("环境别名") 197 | }, 198 | async ({ alias }) => { 199 | const cloudbase = await getCloudBaseManager() 200 | const result = await cloudbase.env.updateEnvInfo(alias); 201 | return { 202 | content: [ 203 | { 204 | type: "text", 205 | text: JSON.stringify(result, null, 2) 206 | } 207 | ] 208 | }; 209 | } 210 | ); 211 | 212 | // // getLoginConfigList 213 | // server.tool( 214 | // "getLoginConfigList", 215 | // "拉取登录配置列表", 216 | // {}, 217 | // async () => { 218 | // const cloudbase = await getCloudBaseManager() 219 | // const result = await cloudbase.env.getLoginConfigList(); 220 | // return { 221 | // content: [ 222 | // { 223 | // type: "text", 224 | // text: JSON.stringify(result, null, 2) 225 | // } 226 | // ] 227 | // }; 228 | // } 229 | // ); 230 | 231 | // // createLoginConfig 232 | // server.tool( 233 | // "createLoginConfig", 234 | // "创建登录方式", 235 | // { 236 | // platform: z.enum(["WECHAT-OPEN", "WECHAT-PUBLIC", "QQ", "ANONYMOUS"]).describe("平台类型"), 237 | // appId: z.string().describe("第三方平台的AppID"), 238 | // appSecret: z.string().optional().describe("第三方平台的AppSecret") 239 | // }, 240 | // async ({ platform, appId, appSecret }) => { 241 | // const cloudbase = await getCloudBaseManager() 242 | // const result = await cloudbase.env.createLoginConfig(platform, appId, appSecret); 243 | // return { 244 | // content: [ 245 | // { 246 | // type: "text", 247 | // text: JSON.stringify(result, null, 2) 248 | // } 249 | // ] 250 | // }; 251 | // } 252 | // ); 253 | 254 | // // updateLoginConfig 255 | // server.tool( 256 | // "updateLoginConfig", 257 | // "更新登录方式配置", 258 | // { 259 | // configId: z.string().describe("配置的记录ID"), 260 | // status: z.enum(["ENABLE", "DISABLE"]).describe("配置状态"), 261 | // appId: z.string().describe("第三方平台的AppId"), 262 | // appSecret: z.string().optional().describe("第三方平台的AppSecret") 263 | // }, 264 | // async ({ configId, status, appId, appSecret }) => { 265 | // const cloudbase = await getCloudBaseManager() 266 | // const result = await cloudbase.env.updateLoginConfig(configId, status, appId, appSecret); 267 | // return { 268 | // content: [ 269 | // { 270 | // type: "text", 271 | // text: JSON.stringify(result, null, 2) 272 | // } 273 | // ] 274 | // }; 275 | // } 276 | // ); 277 | 278 | // // createCustomLoginKeys 279 | // server.tool( 280 | // "createCustomLoginKeys", 281 | // "创建自定义登录密钥", 282 | // {}, 283 | // async () => { 284 | // const cloudbase = await getCloudBaseManager() 285 | // const result = await cloudbase.env.createCustomLoginKeys(); 286 | // return { 287 | // content: [ 288 | // { 289 | // type: "text", 290 | // text: JSON.stringify(result, null, 2) 291 | // } 292 | // ] 293 | // }; 294 | // } 295 | // ); 296 | } -------------------------------------------------------------------------------- /mcp/src/tools/file.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; 3 | import * as fs from "fs/promises"; 4 | import * as path from "path"; 5 | import * as os from "os"; 6 | import * as crypto from "crypto"; 7 | import { getCloudBaseManager } from '../cloudbase-manager.js' 8 | 9 | // 常量定义 10 | const MAX_FILE_SIZE = 100 * 1024; // 100KB in bytes 11 | 12 | // 生成随机文件名 13 | function generateRandomFileName(extension = '') { 14 | const randomBytes = crypto.randomBytes(16); 15 | const fileName = randomBytes.toString('hex'); 16 | return `${fileName}${extension}`; 17 | } 18 | 19 | // 获取安全的临时文件路径 20 | function getSafeTempFilePath(fileName: string) { 21 | return path.join(os.tmpdir(), fileName); 22 | } 23 | 24 | // 检查 base64 字符串大小 25 | function checkBase64Size(base64String: string): boolean { 26 | // 计算 base64 解码后的实际大小 27 | // base64 字符串长度 * 0.75 约等于实际二进制数据大小 28 | const actualSize = Math.ceil(base64String.length * 0.75); 29 | return actualSize <= MAX_FILE_SIZE; 30 | } 31 | 32 | // 检查文件路径是否在临时目录中 33 | function isInTempDir(filePath: string): boolean { 34 | const normalizedPath = path.normalize(filePath); 35 | const normalizedTempDir = path.normalize(os.tmpdir()); 36 | return normalizedPath.startsWith(normalizedTempDir); 37 | } 38 | 39 | export function registerFileTools(server: McpServer) { 40 | // 创建文件 41 | server.tool( 42 | "createTempFile", 43 | "在云开发 MCP 服务的临时目录创建文件,支持文本内容或 base64 编码的二进制内容(最大 100KB)", 44 | { 45 | content: z.string().describe("文件内容,可以是普通文本或 base64 编码的二进制内容"), 46 | isBase64: z.boolean().default(false).describe("是否为 base64 编码的内容"), 47 | extension: z.string().optional().describe("文件扩展名,例如 .txt, .png 等") 48 | }, 49 | async ({ content, isBase64 = false, extension = '' }) => { 50 | try { 51 | // 如果是 base64 内容,先检查大小 52 | if (isBase64) { 53 | if (!checkBase64Size(content)) { 54 | return { 55 | content: [ 56 | { 57 | type: "text", 58 | text: JSON.stringify({ 59 | success: false, 60 | error: "文件大小超过限制", 61 | message: `文件大小超过 ${MAX_FILE_SIZE / 1024}KB 限制` 62 | }, null, 2) 63 | } 64 | ] 65 | }; 66 | } 67 | } 68 | 69 | const fileName = generateRandomFileName(extension); 70 | const filePath = getSafeTempFilePath(fileName); 71 | 72 | if (isBase64) { 73 | // 解码 base64 并写入二进制文件 74 | const buffer = Buffer.from(content, 'base64'); 75 | await fs.writeFile(filePath, buffer); 76 | } else { 77 | // 写入文本文件 78 | await fs.writeFile(filePath, content, 'utf-8'); 79 | } 80 | 81 | return { 82 | content: [ 83 | { 84 | type: "text", 85 | text: JSON.stringify({ 86 | success: true, 87 | filePath, 88 | message: "文件创建成功", 89 | fileSize: isBase64 ? Math.ceil(content.length * 0.75) : Buffer.from(content).length 90 | }, null, 2) 91 | } 92 | ] 93 | }; 94 | } catch (error: any) { 95 | return { 96 | content: [ 97 | { 98 | type: "text", 99 | text: JSON.stringify({ 100 | success: false, 101 | error: error.message, 102 | message: "文件创建失败" 103 | }, null, 2) 104 | } 105 | ] 106 | }; 107 | } 108 | } 109 | ); 110 | 111 | // 读取文件 112 | server.tool( 113 | "readTempFile", 114 | "读取临时目录中的文件,支持文本和二进制文件(二进制文件将以 base64 格式返回)", 115 | { 116 | filePath: z.string().describe("要读取的文件路径"), 117 | asBase64: z.boolean().default(false).describe("是否以 base64 格式返回内容(用于二进制文件)") 118 | }, 119 | async ({ filePath, asBase64 = false }) => { 120 | try { 121 | // 安全检查:确保文件路径在临时目录中 122 | if (!isInTempDir(filePath)) { 123 | return { 124 | content: [ 125 | { 126 | type: "text", 127 | text: JSON.stringify({ 128 | success: false, 129 | error: "安全限制", 130 | message: "只能读取临时目录中的文件" 131 | }, null, 2) 132 | } 133 | ] 134 | }; 135 | } 136 | 137 | // 检查文件是否存在 138 | try { 139 | await fs.access(filePath); 140 | } catch { 141 | return { 142 | content: [ 143 | { 144 | type: "text", 145 | text: JSON.stringify({ 146 | success: false, 147 | error: "文件不存在", 148 | message: "指定的文件不存在" 149 | }, null, 2) 150 | } 151 | ] 152 | }; 153 | } 154 | 155 | // 检查文件大小 156 | const stats = await fs.stat(filePath); 157 | if (stats.size > MAX_FILE_SIZE) { 158 | return { 159 | content: [ 160 | { 161 | type: "text", 162 | text: JSON.stringify({ 163 | success: false, 164 | error: "文件大小超过限制", 165 | message: `文件大小 ${stats.size} 字节超过 ${MAX_FILE_SIZE} 字节限制` 166 | }, null, 2) 167 | } 168 | ] 169 | }; 170 | } 171 | 172 | // 读取文件 173 | const buffer = await fs.readFile(filePath); 174 | 175 | let content: string; 176 | if (asBase64) { 177 | content = buffer.toString('base64'); 178 | } else { 179 | content = buffer.toString('utf-8'); 180 | } 181 | 182 | return { 183 | content: [ 184 | { 185 | type: "text", 186 | text: JSON.stringify({ 187 | success: true, 188 | content, 189 | fileSize: buffer.length, 190 | encoding: asBase64 ? 'base64' : 'utf-8', 191 | message: "文件读取成功" 192 | }, null, 2) 193 | } 194 | ] 195 | }; 196 | } catch (error: any) { 197 | return { 198 | content: [ 199 | { 200 | type: "text", 201 | text: JSON.stringify({ 202 | success: false, 203 | error: error.message, 204 | message: "文件读取失败" 205 | }, null, 2) 206 | } 207 | ] 208 | }; 209 | } 210 | } 211 | ); 212 | } -------------------------------------------------------------------------------- /mcp/src/tools/hosting.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; 3 | import { getCloudBaseManager } from '../cloudbase-manager.js' 4 | 5 | // 定义扩展的EnvInfo接口,包含StaticStorages属性 6 | interface ExtendedEnvInfo { 7 | EnvInfo: { 8 | StaticStorages?: Array<{ 9 | StaticDomain: string; 10 | [key: string]: any; 11 | }>; 12 | [key: string]: any; 13 | }; 14 | [key: string]: any; 15 | } 16 | 17 | export function registerHostingTools(server: McpServer) { 18 | // uploadFiles - 上传文件到静态网站托管 19 | server.tool( 20 | "uploadFiles", 21 | "上传文件到静态网站托管", 22 | { 23 | localPath: z.string().optional().describe("本地文件或文件夹路径,需要是绝对路径,例如 /tmp/files/data.txt"), 24 | cloudPath: z.string().optional().describe("云端文件或文件夹路径,例如files/data.txt"), 25 | files: z.array(z.object({ 26 | localPath: z.string(), 27 | cloudPath: z.string() 28 | })).default([]).describe("多文件上传配置"), 29 | ignore: z.union([z.string(), z.array(z.string())]).optional().describe("忽略文件模式") 30 | }, 31 | async ({ localPath, cloudPath, files, ignore }) => { 32 | const cloudbase = await getCloudBaseManager() 33 | const result = await cloudbase.hosting.uploadFiles({ 34 | localPath, 35 | cloudPath, 36 | files, 37 | ignore 38 | }); 39 | 40 | // 获取环境信息 41 | const envInfo = await cloudbase.env.getEnvInfo() as ExtendedEnvInfo; 42 | 43 | // 获取静态网站地址 44 | let staticDomain = ""; 45 | if (envInfo?.EnvInfo?.StaticStorages && envInfo.EnvInfo.StaticStorages.length > 0) { 46 | staticDomain = envInfo.EnvInfo.StaticStorages[0].StaticDomain; 47 | } 48 | 49 | return { 50 | content: [ 51 | { 52 | type: "text", 53 | text: JSON.stringify({ 54 | uploadResult: result?.files.map((item: { Key: any; }) => { 55 | return item.Key 56 | }), 57 | staticWebsiteUrl: staticDomain ? `https://${staticDomain}` : "", 58 | // 返回文件的完整访问URL 59 | fileUrl: staticDomain && cloudPath ? `https://${staticDomain}/${cloudPath}` : "" 60 | }, null, 2) 61 | } 62 | ] 63 | }; 64 | } 65 | ); 66 | 67 | // listFiles - 获取文件列表 68 | server.tool( 69 | "listFiles", 70 | "获取静态网站托管的文件列表", 71 | { 72 | confirm: z.literal("yes").describe("确认操作,默认传 yes") 73 | }, 74 | async () => { 75 | const cloudbase = await getCloudBaseManager() 76 | const result = await cloudbase.hosting.listFiles(); 77 | return { 78 | content: [ 79 | { 80 | type: "text", 81 | text: JSON.stringify(result, null, 2) 82 | } 83 | ] 84 | }; 85 | } 86 | ); 87 | 88 | // deleteFiles - 删除文件 89 | server.tool( 90 | "deleteFiles", 91 | "删除静态网站托管的文件或文件夹", 92 | { 93 | cloudPath: z.string().describe("云端文件或文件夹路径"), 94 | isDir: z.boolean().default(false).describe("是否为文件夹") 95 | }, 96 | async ({ cloudPath, isDir }) => { 97 | const cloudbase = await getCloudBaseManager() 98 | const result = await cloudbase.hosting.deleteFiles({ 99 | cloudPath, 100 | isDir 101 | }); 102 | return { 103 | content: [ 104 | { 105 | type: "text", 106 | text: JSON.stringify(result, null, 2) 107 | } 108 | ] 109 | }; 110 | } 111 | ); 112 | 113 | // findFiles - 搜索文件 114 | server.tool( 115 | "findFiles", 116 | "搜索静态网站托管的文件", 117 | { 118 | prefix: z.string().describe("匹配前缀"), 119 | marker: z.string().optional().describe("起始对象键标记"), 120 | maxKeys: z.number().optional().describe("单次返回最大条目数") 121 | }, 122 | async ({ prefix, marker, maxKeys }) => { 123 | const cloudbase = await getCloudBaseManager() 124 | const result = await cloudbase.hosting.findFiles({ 125 | prefix, 126 | marker, 127 | maxKeys 128 | }); 129 | return { 130 | content: [ 131 | { 132 | type: "text", 133 | text: JSON.stringify(result, null, 2) 134 | } 135 | ] 136 | }; 137 | } 138 | ); 139 | 140 | // domainManagement - 统一的域名管理工具 141 | server.tool( 142 | "domainManagement", 143 | "统一的域名管理工具,支持绑定、解绑、查询和修改域名配置", 144 | { 145 | action: z.enum(["create", "delete", "check", "modify"]).describe("操作类型: create=绑定域名, delete=解绑域名, check=查询域名配置, modify=修改域名配置"), 146 | // 绑定域名参数 147 | domain: z.string().optional().describe("域名"), 148 | certId: z.string().optional().describe("证书ID(绑定域名时必需)"), 149 | // 查询域名参数 150 | domains: z.array(z.string()).optional().describe("域名列表(查询配置时使用)"), 151 | // 修改域名参数 152 | domainId: z.number().optional().describe("域名ID(修改配置时必需)"), 153 | domainConfig: z.object({ 154 | Refer: z.object({ 155 | Switch: z.string(), 156 | RefererRules: z.array(z.object({ 157 | RefererType: z.string(), 158 | Referers: z.array(z.string()), 159 | AllowEmpty: z.boolean() 160 | })).optional() 161 | }).optional(), 162 | Cache: z.array(z.object({ 163 | RuleType: z.string(), 164 | RuleValue: z.string(), 165 | CacheTtl: z.number() 166 | })).optional(), 167 | IpFilter: z.object({ 168 | Switch: z.string(), 169 | FilterType: z.string().optional(), 170 | Filters: z.array(z.string()).optional() 171 | }).optional(), 172 | IpFreqLimit: z.object({ 173 | Switch: z.string(), 174 | Qps: z.number().optional() 175 | }).optional() 176 | }).optional().describe("域名配置(修改配置时使用)") 177 | }, 178 | async ({ action, domain, certId, domains, domainId, domainConfig }) => { 179 | const cloudbase = await getCloudBaseManager() 180 | let result; 181 | 182 | switch (action) { 183 | case "create": 184 | if (!domain || !certId) { 185 | throw new Error("绑定域名需要提供域名和证书ID"); 186 | } 187 | result = await cloudbase.hosting.CreateHostingDomain({ 188 | domain, 189 | certId 190 | }); 191 | break; 192 | 193 | case "delete": 194 | if (!domain) { 195 | throw new Error("解绑域名需要提供域名"); 196 | } 197 | result = await cloudbase.hosting.deleteHostingDomain({ 198 | domain 199 | }); 200 | break; 201 | 202 | case "check": 203 | if (!domains || domains.length === 0) { 204 | throw new Error("查询域名配置需要提供域名列表"); 205 | } 206 | result = await cloudbase.hosting.tcbCheckResource({ 207 | domains 208 | }); 209 | break; 210 | 211 | case "modify": 212 | if (!domain || domainId === undefined || !domainConfig) { 213 | throw new Error("修改域名配置需要提供域名、域名ID和配置信息"); 214 | } 215 | result = await cloudbase.hosting.tcbModifyAttribute({ 216 | domain, 217 | domainId, 218 | domainConfig 219 | }); 220 | break; 221 | 222 | default: 223 | throw new Error(`不支持的操作类型: ${action}`); 224 | } 225 | 226 | return { 227 | content: [ 228 | { 229 | type: "text", 230 | text: JSON.stringify({ 231 | action, 232 | result 233 | }, null, 2) 234 | } 235 | ] 236 | }; 237 | } 238 | ); 239 | 240 | // getWebsiteConfig - 获取静态网站配置 241 | server.tool( 242 | "getWebsiteConfig", 243 | "获取静态网站配置", 244 | { 245 | confirm: z.literal("yes").describe("确认操作,默认传 yes") 246 | }, 247 | async () => { 248 | const cloudbase = await getCloudBaseManager() 249 | const result = await cloudbase.hosting.getWebsiteConfig(); 250 | return { 251 | content: [ 252 | { 253 | type: "text", 254 | text: JSON.stringify(result, null, 2) 255 | } 256 | ] 257 | }; 258 | } 259 | ); 260 | } 261 | -------------------------------------------------------------------------------- /mcp/src/tools/interactive.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; 3 | import { getInteractiveServer } from "../interactive-server.js"; 4 | import { getCloudBaseManager } from '../cloudbase-manager.js'; 5 | import { getLoginState } from '../auth.js'; 6 | import { debug, info, warn, error } from '../utils/logger.js'; 7 | import fs from 'fs/promises'; 8 | import path from 'path'; 9 | import os from 'os'; 10 | 11 | export function registerInteractiveTools(server: McpServer) { 12 | // 统一的交互式对话工具 13 | server.tool( 14 | "interactiveDialog", 15 | "统一的交互式对话工具,支持需求澄清和任务确认,当需要和用户确认下一步的操作的时候,可以调用这个工具的clarify,如果有敏感的操作,需要用户确认,可以调用这个工具的confirm", 16 | { 17 | type: z.enum(['clarify', 'confirm']).describe("交互类型: clarify=需求澄清, confirm=任务确认"), 18 | message: z.string().optional().describe("对话消息内容"), 19 | options: z.array(z.string()).optional().describe("可选的预设选项"), 20 | forceUpdate: z.boolean().optional().describe("是否强制更新环境ID配置"), 21 | risks: z.array(z.string()).optional().describe("操作风险提示") 22 | }, 23 | async ({ type, message, options, forceUpdate = false, risks }) => { 24 | try { 25 | switch (type) { 26 | case 'clarify': { 27 | if (!message) { 28 | throw new Error("需求澄清必须提供message参数"); 29 | } 30 | 31 | const interactiveServer = getInteractiveServer(); 32 | const result = await interactiveServer.clarifyRequest(message, options); 33 | 34 | if (result.cancelled) { 35 | return { content: [{ type: "text", text: "用户取消了需求澄清" }] }; 36 | } 37 | 38 | return { 39 | content: [{ 40 | type: "text", 41 | text: `📝 用户澄清反馈:\n${result.data}` 42 | }] 43 | }; 44 | } 45 | 46 | case 'confirm': { 47 | if (!message) { 48 | throw new Error("任务确认必须提供message参数"); 49 | } 50 | 51 | let dialogMessage = `🎯 即将执行任务:\n${message}`; 52 | 53 | if (risks && risks.length > 0) { 54 | dialogMessage += `\n\n⚠️ 风险提示:\n${risks.map(risk => `• ${risk}`).join('\n')}`; 55 | } 56 | 57 | dialogMessage += `\n\n是否继续执行此任务?`; 58 | 59 | const dialogOptions = options || ["确认执行", "取消操作", "需要修改任务"]; 60 | 61 | const interactiveServer = getInteractiveServer(); 62 | const result = await interactiveServer.clarifyRequest(dialogMessage, dialogOptions); 63 | 64 | if (result.cancelled || (result.data && result.data.includes && result.data.includes('取消'))) { 65 | return { content: [{ type: "text", text: "❌ 用户取消了任务执行" }] }; 66 | } 67 | 68 | return { 69 | content: [{ 70 | type: "text", 71 | text: `✅ 用户确认: ${result.data}` 72 | }] 73 | }; 74 | } 75 | } 76 | } catch (error) { 77 | return { 78 | content: [{ 79 | type: "text", 80 | text: `交互对话出错: ${error instanceof Error ? error.message : String(error)}` 81 | }] 82 | }; 83 | } 84 | } 85 | ); 86 | } 87 | 88 | // 封装了获取环境、提示选择、保存配置的核心逻辑 89 | export async function _promptAndSetEnvironmentId(autoSelectSingle: boolean): Promise<{ selectedEnvId: string | null; cancelled: boolean; error?: string; noEnvs?: boolean }> { 90 | // 1. 确保用户已登录 91 | 92 | const loginState = await getLoginState(); 93 | debug('loginState',loginState) 94 | if (!loginState) { 95 | debug('请先登录云开发账户') 96 | return { selectedEnvId: null, cancelled: false, error: "请先登录云开发账户" }; 97 | } 98 | 99 | // 2. 获取可用环境列表 100 | const cloudbase = await getCloudBaseManager({requireEnvId: false}); 101 | const envResult = await cloudbase.env.listEnvs(); 102 | debug('envResult', envResult); 103 | if (!envResult || !envResult.EnvList || envResult.EnvList.length === 0) { 104 | return { selectedEnvId: null, cancelled: false, noEnvs: true }; 105 | } 106 | 107 | const { EnvList } = envResult; 108 | let selectedEnvId: string | null = null; 109 | 110 | // 3. 根据情况选择或提示用户选择 111 | if (autoSelectSingle && EnvList.length === 1 && EnvList[0].EnvId) { 112 | selectedEnvId = EnvList[0].EnvId; 113 | } else { 114 | const interactiveServer = getInteractiveServer(); 115 | const result = await interactiveServer.collectEnvId(EnvList); 116 | 117 | if (result.cancelled) { 118 | return { selectedEnvId: null, cancelled: true }; 119 | } 120 | selectedEnvId = result.data; 121 | } 122 | 123 | // 4. 保存并设置环境ID 124 | if (selectedEnvId) { 125 | await saveEnvIdToUserConfig(selectedEnvId); 126 | process.env.CLOUDBASE_ENV_ID = selectedEnvId; 127 | } 128 | 129 | return { selectedEnvId, cancelled: false }; 130 | } 131 | 132 | // 获取用户配置文件路径 133 | function getUserConfigPath(): string { 134 | return path.join(os.homedir(), '.cloudbase-env-id'); 135 | } 136 | 137 | // 保存环境ID到用户配置文件 138 | async function saveEnvIdToUserConfig(envId: string): Promise { 139 | const configPath = getUserConfigPath(); 140 | 141 | try { 142 | const config = { 143 | envId, 144 | updatedAt: new Date().toISOString(), 145 | version: '1.0' 146 | }; 147 | 148 | await fs.writeFile(configPath, JSON.stringify(config, null, 2), 'utf8'); 149 | // 环境ID已保存 - 静默操作避免干扰MCP返回值 150 | 151 | } catch (error) { 152 | console.error('保存环境ID配置失败:', error); 153 | throw error; 154 | } 155 | } 156 | 157 | // 从用户配置文件读取环境ID 158 | async function loadEnvIdFromUserConfig(): Promise { 159 | const configPath = getUserConfigPath(); 160 | 161 | try { 162 | const configContent = await fs.readFile(configPath, 'utf8'); 163 | const config = JSON.parse(configContent); 164 | const envId = config.envId || null; 165 | if (!envId) { 166 | warn(`Config file ${configPath} found, but 'envId' property is missing or empty.`); 167 | } 168 | return envId; 169 | } catch (err: any) { 170 | // 文件不存在是正常情况,不应告警。只在文件存在但有问题时告警。 171 | if (err.code !== 'ENOENT') { 172 | warn(`Failed to load envId from config file at ${configPath}. Error: ${err.message}`); 173 | } else { 174 | debug(`Env config file not found at ${configPath}, which is expected if not set.`); 175 | } 176 | return null; 177 | } 178 | } 179 | 180 | // 检查并设置环境ID 181 | export async function ensureEnvId(): Promise { 182 | // 优先使用进程环境变量 183 | if (process.env.CLOUDBASE_ENV_ID) { 184 | return process.env.CLOUDBASE_ENV_ID; 185 | } 186 | 187 | // 从用户配置文件读取 188 | const envId = await loadEnvIdFromUserConfig(); 189 | if (envId) { 190 | // 设置到进程环境变量中 191 | process.env.CLOUDBASE_ENV_ID = envId; 192 | return envId; 193 | } 194 | 195 | return null; 196 | } 197 | 198 | // 清理用户环境ID配置 199 | export async function clearUserEnvId(): Promise { 200 | const configPath = getUserConfigPath(); 201 | 202 | try { 203 | await fs.unlink(configPath); 204 | // 清理进程环境变量 205 | delete process.env.CLOUDBASE_ENV_ID; 206 | delete process.env.TENCENTCLOUD_SECRETID; 207 | delete process.env.TENCENTCLOUD_SECRETKEY; 208 | delete process.env.TENCENTCLOUD_SESSIONTOKEN; 209 | // 环境ID配置已清理 - 静默操作 210 | } catch (error) { 211 | // 文件不存在或删除失败,忽略错误 212 | // 环境ID配置文件不存在或已清理 - 静默操作 213 | } 214 | } 215 | 216 | // 自动设置环境ID(无需MCP工具调用) 217 | export async function autoSetupEnvironmentId(): Promise { 218 | try { 219 | const { selectedEnvId, cancelled, error, noEnvs } = await _promptAndSetEnvironmentId(true); 220 | 221 | if (error || noEnvs || cancelled) { 222 | debug('Auto setup environment ID interrupted or failed silently.', { error, noEnvs, cancelled }); 223 | return null; 224 | } 225 | 226 | debug('Auto setup environment ID successful.', { selectedEnvId }); 227 | return selectedEnvId; 228 | 229 | } catch (error) { 230 | console.error('自动配置环境ID时出错:', error); 231 | return null; 232 | } 233 | } -------------------------------------------------------------------------------- /mcp/src/tools/rag.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; 3 | 4 | // 1. 枚举定义 5 | const KnowledgeBaseEnum = z.enum(["cloudbase", "scf", "miniprogram"]); 6 | // 2. 枚举到后端 id 的映射 7 | const KnowledgeBaseIdMap: Record, string> = { 8 | cloudbase: "ykfzskv4_ad28", 9 | scf: "scfsczskzyws_4bdc", 10 | miniprogram: "xcxzskws_25d8", 11 | }; 12 | 13 | // 安全 JSON.parse 14 | function safeParse(str: string) { 15 | try { 16 | return JSON.parse(str); 17 | } catch (e) { 18 | return {}; 19 | } 20 | } 21 | 22 | // 安全 JSON.stringify,处理循环引用 23 | function safeStringify(obj: any) { 24 | const seen = new WeakSet(); 25 | try { 26 | return JSON.stringify(obj, function(key, value) { 27 | if (typeof value === "object" && value !== null) { 28 | if (seen.has(value)) return; 29 | seen.add(value); 30 | } 31 | return value; 32 | }); 33 | } catch (e) { 34 | return ""; 35 | } 36 | } 37 | 38 | export function registerRagTools(server: McpServer) { 39 | // 知识库检索 40 | server.tool( 41 | 'searchKnowledgeBase', 42 | '云开发知识库智能检索工具,支持云开发与云函数知识的向量查询', 43 | { 44 | threshold: z.number().default(0.5).optional().describe("相似性检索阈值"), 45 | id: KnowledgeBaseEnum.describe("知识库范围,cloudbase=云开发全量知识,scf=云开发的云函数知识, miniprogram=小程序知识(不包含云开发与云函数知识)"), 46 | content: z.string().describe("检索内容"), 47 | options: z.object({ 48 | chunkExpand: z.array(z.number()).min(2).max(2).default([3, 3]).describe("指定返回的文档内容的展开长度,例如 [3,3]代表前后展开长度"), 49 | }).optional().describe("其他选项"), 50 | limit: z.number().default(5).optional().describe("指定返回最相似的 Top K 的 K 的值") 51 | }, 52 | async ({ 53 | id, 54 | content, 55 | options: { 56 | chunkExpand = [3, 3] 57 | } = {}, 58 | limit = 5, 59 | threshold = 0.5 60 | }) => { 61 | // 枚举到后端 id 映射 62 | const backendId = KnowledgeBaseIdMap[id as keyof typeof KnowledgeBaseIdMap] || id; 63 | const signInRes = await fetch('https://tcb-advanced-a656fc.api.tcloudbasegateway.com/auth/v1/signin/anonymously',{ 64 | method: 'POST', 65 | headers: { 66 | 'Content-Type': 'application/json', 67 | 'Accept': 'application/json', 68 | 'x-device-id': 'cloudbase-ai-toolkit' 69 | }, 70 | body: safeStringify({ 71 | collectionView: backendId, 72 | options: { 73 | chunkExpand 74 | }, 75 | search: { 76 | content: content, 77 | limit 78 | } 79 | }) 80 | }) 81 | const token = (await signInRes.json()).access_token 82 | const res = await fetch(`https://tcb-advanced-a656fc.api.tcloudbasegateway.com/v1/knowledge/search`, { 83 | method: 'POST', 84 | headers: { 85 | 'Content-Type': 'application/json', 86 | 'Authorization': `Bearer ${token}` 87 | }, 88 | body: safeStringify({ 89 | collectionView: backendId, 90 | options: { 91 | chunkExpand 92 | }, 93 | search: { 94 | content: content, 95 | limit 96 | } 97 | }) 98 | }) 99 | const result = await res.json() 100 | 101 | if (result.code) { 102 | throw new Error(result.message) 103 | } 104 | console.log(result) 105 | return { 106 | content: [{ 107 | type: "text", 108 | text: safeStringify(result.data.documents 109 | .filter((item: any) => item.score >= threshold) 110 | .map((item: any) => { 111 | return { 112 | score: item.score, 113 | fileTile: item.documentSet.fileTitle, 114 | url: safeParse(item.documentSet.fileMetaData).url, 115 | paragraphTitle: item.data.paragraphTitle, 116 | text:`${item.data.pre?.join('\n') || ''} 117 | ${item.data.text} 118 | ${item.data.next?.join('\n') || ''}`, 119 | } 120 | }) 121 | ) 122 | }] 123 | } 124 | }) 125 | } -------------------------------------------------------------------------------- /mcp/src/tools/setup.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; 3 | import * as fs from "fs"; 4 | import * as fsPromises from "fs/promises"; 5 | import * as path from "path"; 6 | import * as os from "os"; 7 | import * as https from "https"; 8 | import * as http from "http"; 9 | import { execSync } from "child_process"; 10 | import * as unzipper from "unzipper"; 11 | 12 | // CloudBase 模板配置 13 | const TEMPLATES = { 14 | "react": { 15 | description: "React + CloudBase 全栈应用模板", 16 | url: "https://static.cloudbase.net/cloudbase-examples/web-cloudbase-react-template.zip" 17 | }, 18 | "miniprogram": { 19 | description: "微信小程序 + 云开发模板", 20 | url: "https://static.cloudbase.net/cloudbase-examples/miniprogram-cloudbase-miniprogram-template.zip" 21 | }, 22 | "rules": { 23 | description: "AI编辑器配置模板(包含所有主流编辑器配置)", 24 | url: "https://static.cloudbase.net/cloudbase-examples/web-cloudbase-project.zip" 25 | } 26 | }; 27 | 28 | // 下载文件到临时目录 29 | async function downloadFile(url: string, filePath: string): Promise { 30 | return new Promise((resolve, reject) => { 31 | const client = url.startsWith('https:') ? https : http; 32 | 33 | client.get(url, (res) => { 34 | if (res.statusCode === 200) { 35 | const file = fs.createWriteStream(filePath); 36 | res.pipe(file); 37 | file.on('finish', () => { 38 | file.close(); 39 | resolve(); 40 | }); 41 | file.on('error', reject); 42 | } else if (res.statusCode === 302 || res.statusCode === 301) { 43 | // 处理重定向 44 | if (res.headers.location) { 45 | downloadFile(res.headers.location, filePath).then(resolve).catch(reject); 46 | } else { 47 | reject(new Error('重定向但没有location header')); 48 | } 49 | } else { 50 | reject(new Error(`下载失败,状态码: ${res.statusCode}`)); 51 | } 52 | }).on('error', reject); 53 | }); 54 | } 55 | 56 | // 解压ZIP文件 57 | async function extractZip(zipPath: string, extractPath: string): Promise { 58 | try { 59 | // 创建解压目录 60 | await fsPromises.mkdir(extractPath, { recursive: true }); 61 | 62 | // 使用 unzipper 库进行解压,兼容性更好 63 | await fs.createReadStream(zipPath) 64 | .pipe(unzipper.Extract({ path: extractPath })) 65 | .promise(); 66 | 67 | } catch (error) { 68 | throw new Error(`解压失败: ${error instanceof Error ? error.message : '未知错误'}`); 69 | } 70 | } 71 | 72 | // 获取目录下所有文件的相对路径列表 73 | async function getAllFiles(dir: string, baseDir: string = dir): Promise { 74 | const files: string[] = []; 75 | const entries = await fsPromises.readdir(dir, { withFileTypes: true }); 76 | 77 | for (const entry of entries) { 78 | const fullPath = path.join(dir, entry.name); 79 | if (entry.isDirectory()) { 80 | const subFiles = await getAllFiles(fullPath, baseDir); 81 | files.push(...subFiles); 82 | } else { 83 | files.push(path.relative(baseDir, fullPath)); 84 | } 85 | } 86 | 87 | return files; 88 | } 89 | 90 | // 复制文件,不覆盖已存在的文件 91 | async function copyFileIfNotExists(src: string, dest: string): Promise<{ copied: boolean; reason?: string }> { 92 | try { 93 | // 检查目标文件是否存在 94 | if (fs.existsSync(dest)) { 95 | return { copied: false, reason: '文件已存在' }; 96 | } 97 | 98 | // 创建目标目录 99 | await fsPromises.mkdir(path.dirname(dest), { recursive: true }); 100 | 101 | // 复制文件 102 | await fsPromises.copyFile(src, dest); 103 | return { copied: true }; 104 | } catch (error) { 105 | return { copied: false, reason: `复制失败: ${error instanceof Error ? error.message : '未知错误'}` }; 106 | } 107 | } 108 | 109 | // 复制文件,支持覆盖模式 110 | async function copyFile(src: string, dest: string, overwrite: boolean = false): Promise<{ copied: boolean; reason?: string; action?: string }> { 111 | try { 112 | const destExists = fs.existsSync(dest); 113 | 114 | // 如果目标文件存在且不允许覆盖 115 | if (destExists && !overwrite) { 116 | return { copied: false, reason: '文件已存在', action: 'skipped' }; 117 | } 118 | 119 | // 创建目标目录 120 | await fsPromises.mkdir(path.dirname(dest), { recursive: true }); 121 | 122 | // 复制文件 123 | await fsPromises.copyFile(src, dest); 124 | return { 125 | copied: true, 126 | action: destExists ? 'overwritten' : 'created' 127 | }; 128 | } catch (error) { 129 | return { copied: false, reason: `复制失败: ${error instanceof Error ? error.message : '未知错误'}` }; 130 | } 131 | } 132 | 133 | export function registerSetupTools(server: McpServer) { 134 | server.tool( 135 | "downloadTemplate", 136 | `自动下载并部署CloudBase项目模板。 137 | 138 | 支持的模板: 139 | - react: React + CloudBase 全栈应用模板 140 | - miniprogram: 微信小程序 + 云开发模板 141 | - rules: 只包含AI编辑器配置文件(包含Cursor、WindSurf、CodeBuddy等所有主流编辑器配置),适合在已有项目中补充AI编辑器配置 142 | 143 | 工具会自动下载模板到临时目录,解压后如果检测到WORKSPACE_FOLDER_PATHS环境变量,则复制到项目目录。`, 144 | { 145 | template: z.enum(["react", "miniprogram", "rules"]).describe("要下载的模板类型"), 146 | overwrite: z.boolean().optional().describe("是否覆盖已存在的文件,默认为false(不覆盖)") 147 | }, 148 | async ({ template, overwrite = false }) => { 149 | try { 150 | const templateConfig = TEMPLATES[template]; 151 | if (!templateConfig) { 152 | return { 153 | content: [ 154 | { 155 | type: "text", 156 | text: `❌ 不支持的模板类型: ${template}` 157 | } 158 | ] 159 | }; 160 | } 161 | 162 | // 创建临时目录 163 | const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cloudbase-template-')); 164 | const zipPath = path.join(tempDir, 'template.zip'); 165 | const extractDir = path.join(tempDir, 'extracted'); 166 | 167 | // 下载和解压 168 | await downloadFile(templateConfig.url, zipPath); 169 | await extractZip(zipPath, extractDir); 170 | const extractedFiles = await getAllFiles(extractDir); 171 | 172 | // 检查是否需要复制到项目目录 173 | const workspaceFolder = process.env.WORKSPACE_FOLDER_PATHS; 174 | let finalFiles: string[] = []; 175 | let createdCount = 0; 176 | let overwrittenCount = 0; 177 | let skippedCount = 0; 178 | const results: string[] = []; 179 | 180 | if (workspaceFolder) { 181 | for (const relativePath of extractedFiles) { 182 | const srcPath = path.join(extractDir, relativePath); 183 | const destPath = path.join(workspaceFolder, relativePath); 184 | 185 | const copyResult = await copyFile(srcPath, destPath, overwrite); 186 | 187 | if (copyResult.copied) { 188 | if (copyResult.action === 'overwritten') { 189 | overwrittenCount++; 190 | } else { 191 | createdCount++; 192 | } 193 | finalFiles.push(destPath); 194 | } else { 195 | skippedCount++; 196 | finalFiles.push(srcPath); 197 | } 198 | } 199 | 200 | results.push(`✅ ${templateConfig.description} 同步完成`); 201 | results.push(`📁 临时目录: ${extractDir}`); 202 | 203 | const stats: string[] = []; 204 | if (createdCount > 0) stats.push(`新建 ${createdCount} 个文件`); 205 | if (overwrittenCount > 0) stats.push(`覆盖 ${overwrittenCount} 个文件`); 206 | if (skippedCount > 0) stats.push(`跳过 ${skippedCount} 个已存在文件`); 207 | 208 | if (stats.length > 0) { 209 | results.push(`📊 ${stats.join(',')}`); 210 | } 211 | 212 | if (overwrite || overwrittenCount > 0 || skippedCount > 0) { 213 | results.push(`🔄 覆盖模式: ${overwrite ? '启用' : '禁用'}`); 214 | } 215 | } else { 216 | finalFiles = extractedFiles.map(relativePath => path.join(extractDir, relativePath)); 217 | results.push(`✅ ${templateConfig.description} 下载完成`); 218 | results.push(`📁 保存在临时目录: ${extractDir}`); 219 | } 220 | 221 | // 文件路径列表 222 | results.push(''); 223 | results.push('📋 文件列表:'); 224 | finalFiles.forEach(filePath => { 225 | results.push(`${filePath}`); 226 | }); 227 | 228 | return { 229 | content: [ 230 | { 231 | type: "text", 232 | text: results.join('\n') 233 | } 234 | ] 235 | }; 236 | 237 | } catch (error) { 238 | return { 239 | content: [ 240 | { 241 | type: "text", 242 | text: `❌ 下载模板失败: ${error instanceof Error ? error.message : '未知错误'}` 243 | } 244 | ] 245 | }; 246 | } 247 | } 248 | ); 249 | } -------------------------------------------------------------------------------- /mcp/src/tools/storage.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; 3 | import { getCloudBaseManager } from '../cloudbase-manager.js' 4 | 5 | export function registerStorageTools(server: McpServer) { 6 | // uploadFile - 上传文件到云存储 7 | server.tool( 8 | "uploadFile", 9 | "上传文件到云存储(区别于静态网站托管,云存储更适合存储业务数据文件)", 10 | { 11 | localPath: z.string().describe("本地文件路径,建议传入绝对路径,例如 /tmp/files/data.txt"), 12 | cloudPath: z.string().describe("云端文件路径,例如 files/data.txt"), 13 | }, 14 | async ({ localPath, cloudPath }) => { 15 | const cloudbase = await getCloudBaseManager() 16 | // 上传文件 17 | await cloudbase.storage.uploadFile({ 18 | localPath, 19 | cloudPath, 20 | onProgress: (progressData) => { 21 | console.log("Upload progress:", progressData); 22 | } 23 | }); 24 | 25 | // 获取文件临时下载地址 26 | const fileUrls = await cloudbase.storage.getTemporaryUrl([{ 27 | cloudPath: cloudPath, 28 | maxAge: 3600 // 临时链接有效期1小时 29 | }]); 30 | 31 | return { 32 | content: [ 33 | { 34 | type: "text", 35 | text: JSON.stringify({ 36 | message: "文件上传成功", 37 | cloudPath: cloudPath, 38 | temporaryUrl: fileUrls[0]?.url || "", 39 | expireTime: "1小时" 40 | }, null, 2) 41 | } 42 | ] 43 | }; 44 | } 45 | ); 46 | } -------------------------------------------------------------------------------- /mcp/src/types.ts: -------------------------------------------------------------------------------- 1 | export interface UploadFileParams { 2 | cloudPath: string; 3 | fileContent: string; 4 | } 5 | 6 | export interface ListFilesParams { 7 | prefix: string; 8 | marker?: string; 9 | } 10 | 11 | export interface DeleteFileParams { 12 | cloudPath: string; 13 | } 14 | 15 | export interface GetFileInfoParams { 16 | cloudPath: string; 17 | } 18 | 19 | export interface ToolResponse { 20 | success: boolean; 21 | [key: string]: any; 22 | } -------------------------------------------------------------------------------- /mcp/src/utils/logger.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs/promises'; 2 | import path from 'path'; 3 | import os from 'os'; 4 | 5 | export enum LogLevel { 6 | DEBUG = 0, 7 | INFO = 1, 8 | WARN = 2, 9 | ERROR = 3 10 | } 11 | 12 | export interface LoggerOptions { 13 | enabled?: boolean; 14 | level?: LogLevel; 15 | logFile?: string; 16 | console?: boolean; 17 | } 18 | 19 | class Logger { 20 | private enabled: boolean; 21 | private level: LogLevel; 22 | private logFile: string | null; 23 | private useConsole: boolean; 24 | 25 | constructor(options: LoggerOptions = {}) { 26 | // 默认开启 27 | this.enabled = options.enabled ?? true; 28 | this.level = options.level ?? LogLevel.INFO; 29 | this.useConsole = options.console ?? false; 30 | 31 | // 默认日志文件路径 32 | this.logFile = options.logFile ?? path.join(os.tmpdir(), 'cloudbase-mcp.log'); 33 | } 34 | 35 | private async writeLog(level: LogLevel, message: string, data?: any) { 36 | if (!this.enabled || level < this.level) return; 37 | 38 | const timestamp = new Date().toISOString(); 39 | const levelName = LogLevel[level]; 40 | const logMessage = data 41 | ? `[${timestamp}] [${levelName}] ${message} ${JSON.stringify(data, null, 2)}` 42 | : `[${timestamp}] [${levelName}] ${message}`; 43 | 44 | // 输出到控制台(仅在调试模式下) 45 | if (this.useConsole && process.env.NODE_ENV === 'development') { 46 | console.error(logMessage); // 使用 stderr 避免污染 stdout 47 | } 48 | 49 | // 写入日志文件 50 | if (this.logFile) { 51 | try { 52 | await fs.appendFile(this.logFile, logMessage + '\n'); 53 | } catch (error) { 54 | // 静默处理日志写入错误,避免影响主要功能 55 | } 56 | } 57 | } 58 | 59 | debug(message: string, data?: any) { 60 | this.writeLog(LogLevel.DEBUG, message, data); 61 | } 62 | 63 | info(message: string, data?: any) { 64 | this.writeLog(LogLevel.INFO, message, data); 65 | } 66 | 67 | warn(message: string, data?: any) { 68 | this.writeLog(LogLevel.WARN, message, data); 69 | } 70 | 71 | error(message: string, data?: any) { 72 | this.writeLog(LogLevel.ERROR, message, data); 73 | } 74 | 75 | // 设置日志级别 76 | setLevel(level: LogLevel) { 77 | this.level = level; 78 | } 79 | 80 | // 启用/禁用日志 81 | setEnabled(enabled: boolean) { 82 | this.enabled = enabled; 83 | } 84 | 85 | // 获取日志文件路径 86 | getLogFile(): string | null { 87 | return this.logFile; 88 | } 89 | 90 | // 清理日志文件 91 | async clearLogs() { 92 | if (this.logFile) { 93 | try { 94 | await fs.writeFile(this.logFile, ''); 95 | } catch (error) { 96 | // 静默处理 97 | } 98 | } 99 | } 100 | 101 | // 读取日志内容 102 | async getLogs(maxLines: number = 1000): Promise { 103 | if (!this.logFile) return []; 104 | 105 | try { 106 | const content = await fs.readFile(this.logFile, 'utf-8'); 107 | const lines = content.split('\n').filter(line => line.trim()); 108 | 109 | // 返回最近的 maxLines 行 110 | return lines.slice(-maxLines); 111 | } catch (error) { 112 | return [`读取日志文件失败: ${error instanceof Error ? error.message : String(error)}`]; 113 | } 114 | } 115 | 116 | // 获取日志状态信息 117 | getStatus() { 118 | return { 119 | enabled: this.enabled, 120 | level: LogLevel[this.level], 121 | logFile: this.logFile, 122 | useConsole: this.useConsole 123 | }; 124 | } 125 | } 126 | 127 | // 创建全局 logger 实例 128 | export const logger = new Logger({ 129 | enabled: process.env.MCP_DEBUG === 'true', 130 | level: LogLevel.INFO, 131 | console: process.env.NODE_ENV === 'development' 132 | }); 133 | 134 | // 便捷的导出函数 135 | export const debug = (message: string, data?: any) => logger.error(message, data); 136 | export const info = (message: string, data?: any) => logger.info(message, data); 137 | export const warn = (message: string, data?: any) => logger.warn(message, data); 138 | export const error = (message: string, data?: any) => logger.error(message, data); 139 | 140 | // 日志管理函数 141 | export const getLogs = (maxLines?: number) => logger.getLogs(maxLines); 142 | export const getLoggerStatus = () => logger.getStatus(); 143 | export const clearLogs = () => logger.clearLogs(); -------------------------------------------------------------------------------- /mcp/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2022", 4 | "module": "Node16", 5 | "moduleResolution": "Node16", 6 | "outDir": "./dist", 7 | "rootDir": "./src", 8 | "strict": true, 9 | "esModuleInterop": true, 10 | "skipLibCheck": true, 11 | "forceConsistentCasingInFileNames": true 12 | }, 13 | "include": ["src/**/*"], 14 | "exclude": ["node_modules"] 15 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cloudbase-ai-toolkit", 3 | "version": "1.7.0", 4 | "scripts": { 5 | "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s --commit-path . --preset-config ./.versionrc.json", 6 | "changelog:first": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0 --commit-path . --preset-config ./.versionrc.json", 7 | "release": "standard-version", 8 | "release:alpha": "standard-version --prerelease alpha", 9 | "release:beta": "standard-version --prerelease beta", 10 | "release:rc": "standard-version --prerelease rc", 11 | "check:readme-sync": "node scripts/check-readme-sync.js" 12 | }, 13 | "devDependencies": { 14 | "conventional-changelog-angular": "^6.0.0", 15 | "conventional-changelog-cli": "^4.1.0", 16 | "standard-version": "^9.5.0" 17 | }, 18 | "changelog": { 19 | "commitUrlFormat": "https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/commit/{{hash}}", 20 | "compareUrlFormat": "https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/compare/{{previousTag}}...{{currentTag}}", 21 | "issueUrlFormat": "https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/issues/{{id}}" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /scripts/README.md: -------------------------------------------------------------------------------- 1 | # 脚本使用说明 2 | 3 | ## sync-config.mjs - 配置同步脚本 4 | 5 | 这个脚本用于将 `config/` 目录下的配置文件同步到 [awsome-cloudbase-examples](https://github.com/TencentCloudBase/awsome-cloudbase-examples) 项目的各个模板中。 6 | 7 | ### 🚀 快速开始 8 | 9 | 1. **准备目标仓库** 10 | ```bash 11 | cd .. 12 | git clone https://github.com/TencentCloudBase/awsome-cloudbase-examples.git 13 | cd cloudbase-turbo-delploy 14 | ``` 15 | 16 | 2. **运行同步脚本** 17 | ```bash 18 | # 同步所有模板 19 | node scripts/sync-config.mjs 20 | 21 | # 干运行模式(预览操作,不实际执行) 22 | node scripts/sync-config.mjs --dry-run 23 | ``` 24 | 25 | ### 📋 命令选项 26 | 27 | | 选项 | 说明 | 28 | |-----|------| 29 | | `--help`, `-h` | 显示帮助信息 | 30 | | `--dry-run` | 干运行模式,只显示将要执行的操作 | 31 | | `--skip-git` | 跳过 Git 提交和推送操作 | 32 | | `--backup` | 创建备份(覆盖配置文件设置) | 33 | | `--filter <关键词>` | 只同步路径包含指定关键词的模板 | 34 | 35 | ### 💡 使用示例 36 | 37 | ```bash 38 | # 同步所有模板 39 | node scripts/sync-config.mjs 40 | 41 | # 只同步包含 "web" 的模板 42 | node scripts/sync-config.mjs --filter web 43 | 44 | # 只同步小程序模板 45 | node scripts/sync-config.mjs --filter miniprogram 46 | 47 | # 干运行模式,查看将要同步的内容 48 | node scripts/sync-config.mjs --dry-run 49 | 50 | # 同步但跳过 Git 操作 51 | node scripts/sync-config.mjs --skip-git 52 | 53 | # 创建备份并同步 54 | node scripts/sync-config.mjs --backup 55 | ``` 56 | 57 | ### ⚙️ 配置文件 58 | 59 | #### template-config.json 60 | 61 | 脚本的主要配置文件,结构简单明了: 62 | 63 | ```json 64 | { 65 | "description": "awsome-cloudbase-examples 项目模板路径配置", 66 | "version": "1.0.0", 67 | "templates": [ 68 | "web/react-starter", 69 | "miniprogram/blog", 70 | "cloudbaserun/deepseek-agent", 71 | "..." 72 | ], 73 | "excludePatterns": ["node_modules", ".DS_Store", "*.log"], 74 | "syncConfig": { 75 | "createBackup": false, 76 | "overwrite": true, 77 | "autoCommit": true, 78 | "commitMessage": "chore: sync config and rules from cloudbase-turbo-deploy" 79 | } 80 | } 81 | ``` 82 | 83 | **配置说明:** 84 | - `templates`: 模板路径数组,每个路径对应 awsome-cloudbase-examples 中的一个模板目录 85 | - `excludePatterns`: 同步时需要排除的文件/目录模式 86 | - `syncConfig`: 同步相关配置 87 | - `createBackup`: 是否创建备份 88 | - `overwrite`: 是否覆盖已存在的文件 89 | - `autoCommit`: 是否自动提交和推送 90 | - `commitMessage`: 默认提交信息 91 | 92 | ### 🔧 工作流程 93 | 94 | 1. **读取配置**: 从 `template-config.json` 读取模板列表和配置 95 | 2. **过滤模板**: 根据 `--filter` 参数过滤要同步的模板 96 | 3. **检查环境**: 验证 `config/` 目录和目标仓库是否存在 97 | 4. **同步文件**: 将 `config/` 下的内容复制到各个模板目录 98 | 5. **Git 操作**: 自动提交更改并推送到远程仓库 99 | 100 | ### 📁 同步的内容 101 | 102 | 脚本会将 `config/` 目录下的所有内容同步到目标模板,包括: 103 | 104 | - `.github/` - GitHub Actions 配置 105 | - `.rules/` - 规则配置文件 106 | - `.cursor/` - Cursor 编辑器配置 107 | - `.windsurf/` - Windsurf 编辑器配置 108 | - `.vscode/` - VSCode 配置 109 | - `.clinerules/` - CLI 规则配置 110 | - `.trae/` - Trae 配置 111 | 112 | ### 🔍 过滤功能 113 | 114 | 使用 `--filter` 参数可以只同步特定类型的模板: 115 | 116 | ```bash 117 | # 同步所有 web 相关模板 118 | node scripts/sync-config.mjs --filter web 119 | 120 | # 同步所有小程序模板 121 | node scripts/sync-config.mjs --filter miniprogram 122 | 123 | # 同步所有云函数模板 124 | node scripts/sync-config.mjs --filter cloudrunfunctions 125 | 126 | # 同步所有 CloudBase Run 模板 127 | node scripts/sync-config.mjs --filter cloudbaserun 128 | ``` 129 | 130 | ### ⚠️ 注意事项 131 | 132 | 1. **权限要求**: 确保你有目标仓库的推送权限 133 | 2. **备份建议**: 首次使用建议启用 `--backup` 选项 134 | 3. **干运行**: 不确定操作结果时,先使用 `--dry-run` 预览 135 | 4. **路径结构**: 目标仓库必须位于 `../awsome-cloudbase-examples/` 136 | 137 | ### 🐛 故障排除 138 | 139 | **问题**: 目标目录不存在 140 | - **解决**: 确保已正确克隆目标仓库,且路径正确 141 | 142 | **问题**: Git 操作失败 143 | - **解决**: 检查网络连接和仓库权限,可使用 `--skip-git` 跳过 Git 操作 144 | 145 | **问题**: 配置文件读取失败 146 | - **解决**: 检查 `template-config.json` 格式是否正确 147 | 148 | ### 📝 日志输出 149 | 150 | 脚本会输出详细的操作日志,包括: 151 | - 📁 源目录信息 152 | - 📋 要处理的模板数量 153 | - 🔍 过滤条件(如果使用) 154 | - ✅ 成功同步的文件 155 | - ⚠️ 跳过的文件和原因 156 | - 📊 最终统计信息 -------------------------------------------------------------------------------- /scripts/check-readme-sync.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * README 同步检查脚本 5 | * 检查中英文 README 文件的基本同步状态 6 | */ 7 | 8 | const fs = require('fs'); 9 | const path = require('path'); 10 | 11 | // 文件路径 12 | const README_CN = path.join(__dirname, '../README.md'); 13 | const README_EN = path.join(__dirname, '../README-EN.md'); 14 | 15 | // 关键章节标题(用于检查结构一致性) 16 | const KEY_SECTIONS = [ 17 | '## ✨', // 核心特性 / Key Features 18 | '## 🚀', // 快速开始 / Quick Start 19 | '## 🎯', // 使用案例 / Use Cases 20 | '## 🛠️', // 工具一览 / Tools Overview 21 | '## 🏗️', // 架构原理 / Architecture 22 | '## 🌟', // 为什么选择 / Why Choose 23 | '## 💬', // 技术交流群 / Community 24 | '## 🤝', // 贡献指南 / Contributing 25 | '## 📄', // 开源协议 / License 26 | ]; 27 | 28 | // 关键词检查(确保重要概念都被翻译) 29 | const KEY_TERMS = { 30 | cn: ['云开发', '环境ID', '小程序', 'AI编程', '一键部署'], 31 | en: ['CloudBase', 'Environment ID', 'Mini-Program', 'AI IDE', 'One-Click'] 32 | }; 33 | 34 | function readFile(filePath) { 35 | try { 36 | return fs.readFileSync(filePath, 'utf8'); 37 | } catch (error) { 38 | console.error(`❌ 无法读取文件: ${filePath}`); 39 | return null; 40 | } 41 | } 42 | 43 | function checkFileExists() { 44 | const cnExists = fs.existsSync(README_CN); 45 | const enExists = fs.existsSync(README_EN); 46 | 47 | console.log('📁 文件存在性检查:'); 48 | console.log(` 中文版 README.md: ${cnExists ? '✅' : '❌'}`); 49 | console.log(` 英文版 README-EN.md: ${enExists ? '✅' : '❌'}`); 50 | 51 | return cnExists && enExists; 52 | } 53 | 54 | function checkSectionStructure(cnContent, enContent) { 55 | console.log('\n📋 章节结构检查:'); 56 | 57 | let allMatch = true; 58 | 59 | KEY_SECTIONS.forEach(section => { 60 | const cnHas = cnContent.includes(section); 61 | const enHas = enContent.includes(section); 62 | const match = cnHas === enHas; 63 | 64 | console.log(` ${section}: 中文${cnHas ? '✅' : '❌'} 英文${enHas ? '✅' : '❌'} ${match ? '✅' : '❌'}`); 65 | 66 | if (!match) allMatch = false; 67 | }); 68 | 69 | return allMatch; 70 | } 71 | 72 | function checkKeyTerms(cnContent, enContent) { 73 | console.log('\n🔍 关键词检查:'); 74 | 75 | let allMatch = true; 76 | 77 | // 检查中文关键词 78 | console.log(' 中文关键词:'); 79 | KEY_TERMS.cn.forEach(term => { 80 | const exists = cnContent.includes(term); 81 | console.log(` ${term}: ${exists ? '✅' : '❌'}`); 82 | if (!exists) allMatch = false; 83 | }); 84 | 85 | // 检查英文关键词 86 | console.log(' 英文关键词:'); 87 | KEY_TERMS.en.forEach(term => { 88 | const exists = enContent.includes(term); 89 | console.log(` ${term}: ${exists ? '✅' : '❌'}`); 90 | if (!exists) allMatch = false; 91 | }); 92 | 93 | return allMatch; 94 | } 95 | 96 | function checkLanguageNavigation(cnContent, enContent) { 97 | console.log('\n🌍 语言导航检查:'); 98 | 99 | const cnNavPattern = /Languages.*中文.*English.*README-EN\.md/; 100 | const enNavPattern = /Languages.*中文.*README\.md.*English/; 101 | 102 | const cnHasNav = cnNavPattern.test(cnContent); 103 | const enHasNav = enNavPattern.test(enContent); 104 | 105 | console.log(` 中文版语言导航: ${cnHasNav ? '✅' : '❌'}`); 106 | console.log(` 英文版语言导航: ${enHasNav ? '✅' : '❌'}`); 107 | 108 | return cnHasNav && enHasNav; 109 | } 110 | 111 | function getBasicStats(content) { 112 | return { 113 | lines: content.split('\n').length, 114 | characters: content.length, 115 | headers: (content.match(/^#+\s/gm) || []).length, 116 | links: (content.match(/\[.*?\]\(.*?\)/g) || []).length, 117 | images: (content.match(/!\[.*?\]\(.*?\)/g) || []).length, 118 | }; 119 | } 120 | 121 | function checkBasicStats(cnContent, enContent) { 122 | console.log('\n📊 基本统计比较:'); 123 | 124 | const cnStats = getBasicStats(cnContent); 125 | const enStats = getBasicStats(enContent); 126 | 127 | console.log(' 指标 中文版 英文版 差异'); 128 | console.log(' ---- ------ ------ ----'); 129 | console.log(` 行数 ${cnStats.lines.toString().padEnd(8)} ${enStats.lines.toString().padEnd(8)} ${Math.abs(cnStats.lines - enStats.lines)}`); 130 | console.log(` 字符数 ${cnStats.characters.toString().padEnd(8)} ${enStats.characters.toString().padEnd(8)} ${Math.abs(cnStats.characters - enStats.characters)}`); 131 | console.log(` 标题数 ${cnStats.headers.toString().padEnd(8)} ${enStats.headers.toString().padEnd(8)} ${Math.abs(cnStats.headers - enStats.headers)}`); 132 | console.log(` 链接数 ${cnStats.links.toString().padEnd(8)} ${enStats.links.toString().padEnd(8)} ${Math.abs(cnStats.links - enStats.links)}`); 133 | console.log(` 图片数 ${cnStats.images.toString().padEnd(8)} ${enStats.images.toString().padEnd(8)} ${Math.abs(cnStats.images - enStats.images)}`); 134 | 135 | // 简单的差异检查(允许一定容差) 136 | const headersDiff = Math.abs(cnStats.headers - enStats.headers); 137 | const linksDiff = Math.abs(cnStats.links - enStats.links); 138 | const imagesDiff = Math.abs(cnStats.images - enStats.images); 139 | 140 | return headersDiff <= 2 && linksDiff <= 3 && imagesDiff <= 1; 141 | } 142 | 143 | function main() { 144 | console.log('🔍 CloudBase AI ToolKit README 同步检查\n'); 145 | console.log('=' * 50); 146 | 147 | // 检查文件存在性 148 | if (!checkFileExists()) { 149 | console.log('\n❌ 同步检查失败:文件缺失'); 150 | process.exit(1); 151 | } 152 | 153 | // 读取文件内容 154 | const cnContent = readFile(README_CN); 155 | const enContent = readFile(README_EN); 156 | 157 | if (!cnContent || !enContent) { 158 | console.log('\n❌ 同步检查失败:无法读取文件内容'); 159 | process.exit(1); 160 | } 161 | 162 | // 执行各项检查 163 | const structureOK = checkSectionStructure(cnContent, enContent); 164 | const termsOK = checkKeyTerms(cnContent, enContent); 165 | const navOK = checkLanguageNavigation(cnContent, enContent); 166 | const statsOK = checkBasicStats(cnContent, enContent); 167 | 168 | // 总结 169 | console.log('\n📋 同步检查总结:'); 170 | console.log('=' * 30); 171 | console.log(`章节结构: ${structureOK ? '✅ 通过' : '❌ 失败'}`); 172 | console.log(`关键词检查: ${termsOK ? '✅ 通过' : '❌ 失败'}`); 173 | console.log(`语言导航: ${navOK ? '✅ 通过' : '❌ 失败'}`); 174 | console.log(`基本统计: ${statsOK ? '✅ 通过' : '⚠️ 差异较大'}`); 175 | 176 | const allPassed = structureOK && termsOK && navOK && statsOK; 177 | 178 | if (allPassed) { 179 | console.log('\n🎉 同步检查通过!中英文 README 基本同步。'); 180 | process.exit(0); 181 | } else { 182 | console.log('\n⚠️ 同步检查发现问题,请参考 docs/README-SYNC.md 进行修复。'); 183 | process.exit(1); 184 | } 185 | } 186 | 187 | // 运行检查 188 | if (require.main === module) { 189 | main(); 190 | } 191 | 192 | module.exports = { 193 | checkFileExists, 194 | checkSectionStructure, 195 | checkKeyTerms, 196 | checkLanguageNavigation, 197 | checkBasicStats 198 | }; -------------------------------------------------------------------------------- /scripts/cloudbase-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /scripts/powered-by-cloudbase-badge.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 52 | 55 | 56 | 57 | 60 | 63 | 64 | 65 | 66 | Powered by 67 | 68 | 69 | CloudBase 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /scripts/product-banner.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | CloudBase AI ToolKit - Product Update 7 | 8 | 237 | 238 | 239 |
240 |
241 |

AI IDE 集成
开发效率提升 10 倍

242 |
243 | 244 |
245 |
246 |

CloudBase AI ToolKit 现已支持主流 AI IDE,让开发更智能、更高效

247 |
248 |
249 |
250 | 251 |
252 | AI 自动生成前后端代码 253 |
254 |
255 |
256 | 257 |
258 | 一键部署到云开发平台 259 |
260 |
261 |
262 | 263 |
264 | 智能问题诊断与修复 265 |
266 |
267 |
268 | 269 |
270 |
271 |
272 |
273 |
274 | 275 |
276 | Cursor 277 |
278 |
279 |
280 | 281 |
282 | WindSurf 283 |
284 |
285 |
286 | 287 |
288 | CodeBuddy 289 |
290 |
291 |
292 | 293 |
294 | CLINE 295 |
296 |
297 |
298 | 同时支持 Github CopilotTrae通义灵码RooCode文心快码 等多款 AI IDE 和 VSCode 插件 299 |
300 | 301 | 立即体验 302 | 303 |
304 |
305 |
306 |
307 | 308 | -------------------------------------------------------------------------------- /scripts/product-hunt.md: -------------------------------------------------------------------------------- 1 | # CloudBase AI ToolKit - AI-Powered Cloud Development Platform 2 | 3 | ![CloudBase AI ToolKit](https://7463-tcb-advanced-a656fc-1257967285.tcb.qcloud.la/mcp/cloudbase-ai-toolkit.png) 4 | 5 | ## 🚀 Turn AI Prompts into Deployable Applications 6 | 7 | CloudBase AI ToolKit is a revolutionary development platform that combines AI code generation with Tencent Cloud's serverless infrastructure. Simply describe your application idea, and watch as AI automatically generates and deploys your full-stack application to the cloud. 8 | 9 | ## ✨ Key Features 10 | 11 | - 🤖 **AI-First Development**: Generate production-ready code with natural language prompts 12 | - ☁️ **One-Click Deployment**: Automatically deploy to Tencent Cloud's serverless platform 13 | - 🎯 **Full-Stack Support**: Build web apps, mini-programs, and backend services 14 | - 🔧 **Smart Debugging**: AI-powered error detection and automatic fixes 15 | - ⚡ **Lightning Fast**: Optimized for China's network with local CDN support 16 | 17 | ## 🎯 Perfect For 18 | 19 | - **Startups**: Quickly prototype and launch MVPs 20 | - **Developers**: Reduce development time with AI assistance 21 | - **Product Teams**: Rapidly iterate on ideas without infrastructure concerns 22 | - **Students**: Learn full-stack development with AI guidance 23 | 24 | ## 🛠️ Tech Stack 25 | 26 | - **Frontend**: React, Vue, Mini-Program 27 | - **Backend**: Serverless Functions 28 | - **Database**: Cloud Database 29 | - **Storage**: Cloud Storage 30 | - **Hosting**: Static Website Hosting 31 | 32 | ## 🌟 Why Choose CloudBase AI ToolKit? 33 | 34 | - **10x Faster Development**: Turn ideas into deployed applications in minutes 35 | - **Zero Infrastructure Management**: Focus on building, not maintaining servers 36 | - **AI-Powered Development**: Leverage the latest AI models for code generation 37 | - **Enterprise-Grade Security**: Built on Tencent Cloud's secure infrastructure 38 | - **Cost-Effective**: Pay only for what you use with serverless architecture 39 | 40 | ## 🎮 Quick Start 41 | 42 | 1. Install an AI IDE (Cursor, VSCode with GitHub Copilot, etc.) 43 | 2. Get your CloudBase environment ID 44 | 3. Describe your application idea 45 | 4. Watch as AI generates and deploys your application 46 | 47 | ## 💡 Use Cases 48 | 49 | - **Real-time Multiplayer Games**: Build and deploy in minutes 50 | - **AI-Enhanced Mini-Programs**: Create interactive mobile experiences 51 | - **Web Applications**: From simple landing pages to complex web apps 52 | - **Backend Services**: Generate and deploy API endpoints instantly 53 | 54 | ## 🔗 Links 55 | 56 | - [GitHub Repository](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) 57 | - [Documentation](https://docs.cloudbase.net/) 58 | - [Community](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/discussions) 59 | 60 | ## 🎉 Special Offer 61 | 62 | New users get free access to CloudBase's development environment. Start building your AI-powered applications today! 63 | 64 | --- 65 | 66 | Made with ❤️ by Tencent CloudBase Team -------------------------------------------------------------------------------- /scripts/sync-config.mjs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { execSync } from 'child_process'; 4 | import fs from 'fs'; 5 | import path from 'path'; 6 | import { fileURLToPath } from 'url'; 7 | 8 | const __filename = fileURLToPath(import.meta.url); 9 | const __dirname = path.dirname(__filename); 10 | 11 | // 项目根目录 12 | const projectRoot = path.resolve(__dirname, '..'); 13 | const configDir = path.join(projectRoot, 'config'); 14 | const templateConfigPath = path.join(__dirname, 'template-config.json'); 15 | 16 | // 读取模板配置 17 | let templateConfig; 18 | try { 19 | const configContent = fs.readFileSync(templateConfigPath, 'utf8'); 20 | templateConfig = JSON.parse(configContent); 21 | } catch (error) { 22 | console.error('❌ 无法读取模板配置文件:', error.message); 23 | process.exit(1); 24 | } 25 | 26 | /** 27 | * 复制目录内容 28 | * @param {string} srcDir 源目录 29 | * @param {string} destDir 目标目录 30 | * @param {Array} excludePatterns 排除模式 31 | */ 32 | function copyDirectory(srcDir, destDir, excludePatterns = []) { 33 | try { 34 | // 确保目标目录存在 35 | if (!fs.existsSync(destDir)) { 36 | fs.mkdirSync(destDir, { recursive: true }); 37 | } 38 | 39 | const items = fs.readdirSync(srcDir); 40 | 41 | for (const item of items) { 42 | // 检查是否需要排除 43 | if (excludePatterns.some(pattern => { 44 | if (pattern.includes('*')) { 45 | const regex = new RegExp(pattern.replace(/\*/g, '.*')); 46 | return regex.test(item); 47 | } 48 | return item === pattern; 49 | })) { 50 | console.log(` ⏭️ 跳过: ${item} (匹配排除规则)`); 51 | continue; 52 | } 53 | 54 | const srcPath = path.join(srcDir, item); 55 | const destPath = path.join(destDir, item); 56 | 57 | const stat = fs.statSync(srcPath); 58 | 59 | if (stat.isDirectory()) { 60 | copyDirectory(srcPath, destPath, excludePatterns); 61 | } else { 62 | fs.copyFileSync(srcPath, destPath); 63 | console.log(` ✓ 已复制: ${path.relative(projectRoot, destPath)}`); 64 | } 65 | } 66 | } catch (error) { 67 | console.error(`复制目录失败: ${srcDir} -> ${destDir}`, error.message); 68 | } 69 | } 70 | 71 | /** 72 | * 检查目标路径是否存在 73 | * @param {string} targetPath 目标路径 74 | * @returns {boolean} 75 | */ 76 | function checkTargetExists(targetPath) { 77 | return fs.existsSync(targetPath); 78 | } 79 | 80 | /** 81 | * 执行Git命令 82 | * @param {string} command Git命令 83 | * @param {string} cwd 工作目录 84 | */ 85 | function executeGitCommand(command, cwd = projectRoot) { 86 | try { 87 | const result = execSync(command, { 88 | cwd, 89 | encoding: 'utf8', 90 | stdio: ['inherit', 'pipe', 'pipe'] 91 | }); 92 | return result.trim(); 93 | } catch (error) { 94 | console.error(`Git命令执行失败: ${command}`); 95 | console.error(error.message); 96 | throw error; 97 | } 98 | } 99 | 100 | /** 101 | * 获取当前Git分支 102 | */ 103 | function getCurrentBranch(cwd = projectRoot) { 104 | try { 105 | return executeGitCommand('git rev-parse --abbrev-ref HEAD', cwd); 106 | } catch (error) { 107 | return 'main'; // 默认分支 108 | } 109 | } 110 | 111 | /** 112 | * 检查是否有未提交的更改 113 | */ 114 | function hasUncommittedChanges(cwd = projectRoot) { 115 | try { 116 | const status = executeGitCommand('git status --porcelain', cwd); 117 | return status.length > 0; 118 | } catch (error) { 119 | return false; 120 | } 121 | } 122 | 123 | /** 124 | * 创建备份 125 | * @param {string} targetDir 目标目录 126 | */ 127 | function createBackup(targetDir) { 128 | if (!fs.existsSync(targetDir)) return null; 129 | 130 | const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); 131 | const backupDir = `${targetDir}.backup.${timestamp}`; 132 | 133 | try { 134 | execSync(`cp -r "${targetDir}" "${backupDir}"`); 135 | console.log(` 💾 已创建备份: ${path.basename(backupDir)}`); 136 | return backupDir; 137 | } catch (error) { 138 | console.error(`创建备份失败:`, error.message); 139 | return null; 140 | } 141 | } 142 | 143 | /** 144 | * 主同步函数 145 | */ 146 | async function syncConfigs(options = {}) { 147 | const { 148 | filter = null, // 过滤器,支持字符串匹配 149 | dryRun = false, // 干运行模式 150 | skipGit = false, // 跳过Git操作 151 | createBackup: shouldBackup = templateConfig.syncConfig?.createBackup || false 152 | } = options; 153 | 154 | console.log('🚀 开始同步配置和规则到模板项目...\n'); 155 | 156 | // 检查config目录是否存在 157 | if (!fs.existsSync(configDir)) { 158 | console.error('❌ config目录不存在,请确保项目结构正确'); 159 | process.exit(1); 160 | } 161 | 162 | console.log(`📁 配置源目录: ${configDir}`); 163 | 164 | // 获取要同步的模板路径 165 | let templatePaths = templateConfig.templates; 166 | 167 | if (filter) { 168 | templatePaths = templatePaths.filter(path => path.includes(filter)); 169 | console.log(`🔍 过滤条件: 包含 "${filter}"`); 170 | } 171 | 172 | console.log(`📋 共需要同步 ${templatePaths.length} 个模板`); 173 | console.log(`🔧 模式: ${dryRun ? '干运行' : '实际执行'}\n`); 174 | 175 | let successCount = 0; 176 | let skipCount = 0; 177 | 178 | // 遍历模板列表 179 | for (let i = 0; i < templatePaths.length; i++) { 180 | const templatePath = templatePaths[i]; 181 | console.log(`\n[${i + 1}/${templatePaths.length}] 处理模板: ${templatePath}`); 182 | 183 | const targetDir = path.join(projectRoot, '..', 'awsome-cloudbase-examples', templatePath); 184 | 185 | if (!checkTargetExists(path.dirname(targetDir))) { 186 | console.log(` ⚠️ 跳过: 目标目录不存在 ${templatePath}`); 187 | skipCount++; 188 | continue; 189 | } 190 | 191 | if (dryRun) { 192 | console.log(` 🔍 [干运行] 将同步到: ${targetDir}`); 193 | successCount++; 194 | continue; 195 | } 196 | 197 | // 创建备份 198 | if (shouldBackup) { 199 | createBackup(targetDir); 200 | } 201 | 202 | // 确保目标目录存在 203 | if (!fs.existsSync(targetDir)) { 204 | fs.mkdirSync(targetDir, { recursive: true }); 205 | } 206 | 207 | // 同步config目录下的所有内容 208 | const configItems = fs.readdirSync(configDir); 209 | for (const configItem of configItems) { 210 | const srcPath = path.join(configDir, configItem); 211 | const destPath = path.join(targetDir, configItem); 212 | 213 | if (fs.statSync(srcPath).isDirectory()) { 214 | console.log(` 📂 同步目录: ${configItem}`); 215 | copyDirectory(srcPath, destPath, templateConfig.excludePatterns); 216 | } else { 217 | console.log(` 📄 同步文件: ${configItem}`); 218 | fs.copyFileSync(srcPath, destPath); 219 | } 220 | } 221 | 222 | successCount++; 223 | console.log(` ✅ 同步完成: ${templatePath}`); 224 | } 225 | 226 | console.log(`\n📊 同步统计:`); 227 | console.log(` ✅ 成功同步: ${successCount} 个模板`); 228 | console.log(` ⚠️ 跳过: ${skipCount} 个模板`); 229 | 230 | // Git提交和推送 231 | if (!skipGit && !dryRun && templateConfig.syncConfig?.autoCommit) { 232 | await handleGitOperations(); 233 | } else if (dryRun) { 234 | console.log('\n🔍 [干运行] 跳过Git操作'); 235 | } else if (skipGit) { 236 | console.log('\n⏭️ 已跳过Git操作'); 237 | } 238 | } 239 | 240 | /** 241 | * 处理Git操作 242 | */ 243 | async function handleGitOperations() { 244 | console.log('\n🔄 开始Git操作...'); 245 | 246 | const examplesDir = path.join(projectRoot, '..', 'awsome-cloudbase-examples'); 247 | 248 | if (!fs.existsSync(examplesDir)) { 249 | console.log('⚠️ awsome-cloudbase-examples 目录不存在,跳过Git操作'); 250 | console.log('请先克隆该仓库到上级目录:'); 251 | console.log('git clone https://github.com/TencentCloudBase/awsome-cloudbase-examples.git'); 252 | return; 253 | } 254 | 255 | try { 256 | // 检查Git状态 257 | if (!hasUncommittedChanges(examplesDir)) { 258 | console.log('📝 没有检测到更改,跳过提交'); 259 | return; 260 | } 261 | 262 | const currentBranch = getCurrentBranch(examplesDir); 263 | console.log(`📍 当前分支: ${currentBranch}`); 264 | 265 | // 添加所有更改 266 | console.log('📝 添加更改到暂存区...'); 267 | executeGitCommand('git add .', examplesDir); 268 | 269 | // 生成提交信息 270 | const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); 271 | const commitMessage = templateConfig.syncConfig?.commitMessage || 272 | `chore: sync config and rules from cloudbase-turbo-deploy ${timestamp}`; 273 | 274 | // 提交更改 275 | console.log('💾 提交更改...'); 276 | executeGitCommand(`git commit -m "${commitMessage}"`, examplesDir); 277 | 278 | // 推送到远程仓库 279 | console.log('🚀 推送到远程仓库...'); 280 | executeGitCommand(`git pull --rebase`, examplesDir); 281 | executeGitCommand(`git push origin ${currentBranch}`, examplesDir); 282 | 283 | console.log('✅ Git操作完成!'); 284 | 285 | } catch (error) { 286 | console.error('❌ Git操作失败:', error.message); 287 | console.log('\n请手动检查并处理Git操作:'); 288 | console.log('1. cd ../awsome-cloudbase-examples'); 289 | console.log('2. git add .'); 290 | console.log('3. git commit -m "sync config and rules"'); 291 | console.log('4. git push'); 292 | } 293 | } 294 | 295 | /** 296 | * 显示使用说明 297 | */ 298 | function showUsage() { 299 | console.log(` 300 | 📖 使用说明: 301 | 302 | 基本用法: 303 | node scripts/sync-config.mjs [选项] 304 | 305 | 选项: 306 | --help, -h 显示帮助信息 307 | --dry-run 干运行模式,不实际执行操作 308 | --skip-git 跳过Git提交和推送操作 309 | --backup 创建备份(覆盖配置文件设置) 310 | --filter <关键词> 只同步路径包含指定关键词的模板 311 | 312 | 示例: 313 | node scripts/sync-config.mjs # 同步所有模板 314 | node scripts/sync-config.mjs --dry-run # 干运行模式 315 | node scripts/sync-config.mjs --filter web # 只同步包含"web"的模板 316 | node scripts/sync-config.mjs --filter miniprogram # 只同步小程序模板 317 | node scripts/sync-config.mjs --skip-git # 跳过Git操作 318 | node scripts/sync-config.mjs --backup # 创建备份 319 | 320 | 准备工作: 321 | 1. 克隆目标仓库到上级目录: 322 | cd .. 323 | git clone https://github.com/TencentCloudBase/awsome-cloudbase-examples.git 324 | 325 | 2. 确保你有该仓库的推送权限 326 | 327 | 配置文件: scripts/template-config.json 328 | 模板总数: ${templateConfig.templates.length} 个 329 | `); 330 | } 331 | 332 | /** 333 | * 解析命令行参数 334 | */ 335 | function parseArgs(args) { 336 | const options = { 337 | dryRun: false, 338 | skipGit: false, 339 | createBackup: undefined, 340 | filter: null, 341 | showHelp: false 342 | }; 343 | 344 | for (let i = 0; i < args.length; i++) { 345 | const arg = args[i]; 346 | 347 | switch (arg) { 348 | case '--help': 349 | case '-h': 350 | options.showHelp = true; 351 | break; 352 | case '--dry-run': 353 | options.dryRun = true; 354 | break; 355 | case '--skip-git': 356 | options.skipGit = true; 357 | break; 358 | case '--backup': 359 | options.createBackup = true; 360 | break; 361 | case '--filter': 362 | if (i + 1 < args.length) { 363 | options.filter = args[i + 1]; 364 | i++; // 跳过下一个参数 365 | } 366 | break; 367 | } 368 | } 369 | 370 | return options; 371 | } 372 | 373 | // 主函数 374 | async function main() { 375 | const args = process.argv.slice(2); 376 | const options = parseArgs(args); 377 | 378 | if (options.showHelp) { 379 | showUsage(); 380 | return; 381 | } 382 | 383 | try { 384 | await syncConfigs(options); 385 | console.log('\n🎉 所有操作完成!'); 386 | } catch (error) { 387 | console.error('\n❌ 脚本执行失败:', error.message); 388 | process.exit(1); 389 | } 390 | } 391 | 392 | // 运行主函数 393 | main().catch(console.error); -------------------------------------------------------------------------------- /scripts/template-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "awsome-cloudbase-examples 项目模板路径配置", 3 | "version": "1.0.0", 4 | "templates": [ 5 | "web/cloudbase-react-template", 6 | "web/cloudbase-project", 7 | "miniprogram/cloudbase-miniprogram-template" 8 | ], 9 | "excludePatterns": [ 10 | ".git", 11 | "node_modules", 12 | ".DS_Store", 13 | "*.log", 14 | ".env", 15 | ".env.local" 16 | ], 17 | "syncConfig": { 18 | "createBackup": false, 19 | "overwrite": true, 20 | "autoCommit": true, 21 | "commitMessage": "chore: sync config and rules from cloudbase-turbo-deploy" 22 | } 23 | } --------------------------------------------------------------------------------