diff --git a/.gitignore b/.gitignore index f0f6e31..83426b9 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ packages/*/types packages/*/release packages/*/dist packages/*/coverage -lerna-debug.log \ No newline at end of file +lerna-debug.log +.claude/settings.local.json \ No newline at end of file diff --git a/.kiro/user-rules.md b/.kiro/user-rules.md deleted file mode 100644 index 8ce7405..0000000 --- a/.kiro/user-rules.md +++ /dev/null @@ -1,64 +0,0 @@ -# 用户规则和偏好设置 - -## 文档语言偏好 - -- **主要语言**: 中文 -- **回答语言**: 中文 -- **文档编写语言**: 中文 - -## ⚠️ 严格禁止编造内容 - 重要规则 - -### 🚨 绝对禁止的行为(违规将受到严重处罚) - -1. **禁止编造功能**: 绝对不允许编造不存在的功能、选项、命令或 API -2. **禁止编造类名**: 不允许编造不存在的类、接口、函数名称 -3. **禁止编造配置**: 不允许编造不存在的配置选项或参数 -4. **禁止编造示例**: 所有代码示例必须基于实际存在的功能 - -### ✅ 必须遵循的原则 - -1. **基于实际代码**: 所有文档内容必须基于实际的源代码和功能 -2. **验证后编写**: 使用本地测试命令(如 `node es/cli.mjs -h`)验证实际功能后再编写 - - 本地测试:`node` + bin对应的入口文件(如 `node es/cli.mjs`) - - 发布后:使用 bin 配置中的命令名(如 `DC`、`dc-component`) - - 两者功能完全一致,只是调用方式不同 -3. **如实描述**: 只描述确实存在的功能,不夸大不虚构 -4. **承认限制**: 如果功能有限制或不完整,如实说明 - -### 🔍 验证要求 - -- 编写文档前必须先运行实际命令验证功能 -- 查看源代码确认类名、函数名、配置选项的真实性 -- 所有示例代码必须是可执行的真实代码 -- **重要**: 检查 package.json 的 bin 字段确认独立命令的存在性 -- 区分独立命令和主CLI子命令的使用方式 - -## CLI 包文档特殊要求 - -### Postinstall 钩子集成 -- CLI 包的文档要基于 postinstall 钩子对应的文件去增加对应的提示 -- 模板文档要预留 postinstall 相关内容的可选区域 -- 可根据包的实际情况选择是否包含这块内容 - -### 依赖关系图简化 -- 流程图过于复杂时,没必要在一张图中一下子展示到孙节点及以下 -- 保持依赖关系图的清晰易读性 -- 重点展示主要的包间协作关系 - -## 文档结构要求 - -### 模板灵活性 -- 文档模板应支持根据包的实际情况灵活选择内容 -- 使用标记(如 `{postinstall-section-start}` 和 `{postinstall-section-end}`)来标识可选区域 -- 不是所有包都需要包含所有模板内容 - -### 内容基于实际代码 -- 文档内容必须基于实际代码实现编写 -- 不允许编造不存在的功能和选项 -- 通过分析源代码提取真实的 API 和命令 - -## 持久化记录要求 - -- 所有讨论和决策都要持久化记录到 RDT(Requirements, Design, Tasks)文档中 -- 用户提出的新要求要及时更新到需求文档中 -- 实现的修改要在任务文档中记录状态和细节 \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index db90cbb..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,180 +0,0 @@ -## 0.0.1 (2026-04-09) - - -### Bug Fixes - -* 一次生成所有日志 ([6e2b389](https://gitee.com/done-coding/done-coding-cli/commits/6e2b389344fa9be721ba2cad3fe8022ef4c48d64)) -* **create:** 删除模板配置文件 ([44eeca2](https://gitee.com/done-coding/done-coding-cli/commits/44eeca2e489b550a77c617fc5b6beaf5a565e810)) -* **create:** 修改mcp参数 ([f6a5492](https://gitee.com/done-coding/done-coding-cli/commits/f6a5492c9c20fffa5f98cc29f4bad0f5c12d70b3)) -* **create:** 优化项目创建过程中的输出信息 ([1f4926d](https://gitee.com/done-coding/done-coding-cli/commits/1f4926d57849ac8bb6d8fbeb731410e8aeac3b30)) -* **create:** 指定分支名重命名询问逻辑 ([79ec224](https://gitee.com/done-coding/done-coding-cli/commits/79ec2249384c06d683ef427f8927bba83ae0c4cf)) -* **create:** 指定分支名重命名运行路径 ([a21c413](https://gitee.com/done-coding/done-coding-cli/commits/a21c4136096297e363738b76765d4a66ad89d49f)) -* **create:** 指定远程分支名后 若是独立仓库则询问克隆到本地后的分支名 ([22093e6](https://gitee.com/done-coding/done-coding-cli/commits/22093e621cc3d0429c43b84e763ef13a21ed95c3)) -* lerna publish版本号变量未替换问题 ([446a38c](https://gitee.com/done-coding/done-coding-cli/commits/446a38c80ad5ed7095a7b26abb8414f789ac15c1)) -* **lerna:** 修复lerna配置 ([1e82acd](https://gitee.com/done-coding/done-coding-cli/commits/1e82acdc2273ae90b4733687682ed35d222bce4f)) -* **publish:** 删除临时目录时机修复 ([3044f25](https://gitee.com/done-coding/done-coding-cli/commits/3044f254e03d801b49f741c3adbb0d77fd2fcb65)) -* **template:** 移除ouput必须项 ([e08fdf8](https://gitee.com/done-coding/done-coding-cli/commits/e08fdf8358d0c32bc64a834817ac815dd29a3ee0)) -* **utils:** 配置文件alias防止冲突 ([df0d6c2](https://gitee.com/done-coding/done-coding-cli/commits/df0d6c2b8acce57dc27711fc2fc41c67937e24c5)) -* **utils:** lookForParentTarget文件路径 ([e208f0d](https://gitee.com/done-coding/done-coding-cli/commits/e208f0d324491d5ca5aeb911cec2f19aeda0d109)) - - -### Features - -* 初始化项目config ([994f698](https://gitee.com/done-coding/done-coding-cli/commits/994f698dcfe8413053b68a160bd6712d1625611f)) -* 初始化项目engin ([657c21e](https://gitee.com/done-coding/done-coding-cli/commits/657c21ed869d319d64022e01100d33a67e30009d)) -* 初始化项目extract ([d997ece](https://gitee.com/done-coding/done-coding-cli/commits/d997eceefefcdaf5c4ee408fb084c2c243389617)) -* 初始化项目mcp ([288ac09](https://gitee.com/done-coding/done-coding-cli/commits/288ac092d0f6cac10d10ad2cf7a8e9629119a095)) -* 初始化项目mcp-utils ([dd6e287](https://gitee.com/done-coding/done-coding-cli/commits/dd6e287288287abefcfd1dab168368791fab7036)) -* 各子包导出@/utils/types, 涉及执行目录全部改为函数内部获取 ([3ac2240](https://gitee.com/done-coding/done-coding-cli/commits/3ac22403060a80abdfd855e825ac1d9202c770dc)) -* 更新注入方式 & 更新handler类型 ([3d6d4cc](https://gitee.com/done-coding/done-coding-cli/commits/3d6d4cc01fb62ad500a6a9228353368a460964a0)) -* 临时文件换tmpDir ([c57cbcd](https://gitee.com/done-coding/done-coding-cli/commits/c57cbcde7344818aadc732a5b2ac7147755f02cc)) -* **命令行界面:** 更新 postinstall 脚本和工作区设置 ([ca6fe4e](https://gitee.com/done-coding/done-coding-cli/commits/ca6fe4eff29606d0dd05731e869becfd3e60b714)) -* 添加mcp-utils包并增强execSync功能 ([bd8d098](https://gitee.com/done-coding/done-coding-cli/commits/bd8d09838acaef74ba6d23cba800bd97086cf483)) -* 移除cli-init ([2f5134c](https://gitee.com/done-coding/done-coding-cli/commits/2f5134c9cdeb65f65e56bdd224c4693b91a7dfde)) -* **cli&create&inect:** cli支持增加子命令create、inject & 各主子命令增加信息注入 ([321bf5d](https://gitee.com/done-coding/done-coding-cli/commits/321bf5d4e6bb6c34198a5f6b82b06894e0ed271d)) -* **cli:** 创建cli包&create导出assets ([0c05b90](https://gitee.com/done-coding/done-coding-cli/commits/0c05b905fa3e9d5837b97caad49d2b621463ecb3)) -* **cli:** 集成template子命令 ([7bdb20e](https://gitee.com/done-coding/done-coding-cli/commits/7bdb20e21467b3b7009ce177695d997bcced460a)) -* **cli:** 引入信息提取子包 ([ce03bc0](https://gitee.com/done-coding/done-coding-cli/commits/ce03bc00514fc2398e9c95fed81d4ab4ef74507d)) -* **cli:** cli增加git子命令 ([14b1e41](https://gitee.com/done-coding/done-coding-cli/commits/14b1e416939de3f8bda425fb170214817d77056b)) -* **component & template:** 添加根命令名称 ([237c71a](https://gitee.com/done-coding/done-coding-cli/commits/237c71aed1aae883e47523c63098ace9440f6baa)) -* **component:** 内置组件模板配置 ([0e6bd86](https://gitee.com/done-coding/done-coding-cli/commits/0e6bd865b1a7dce26d36214417560748cc2ac285)) -* **component:** 删除组件默认允许删除文件 ([2b97038](https://gitee.com/done-coding/done-coding-cli/commits/2b97038a8fd5ee7241536d806ac2f6a009d25cb9)) -* **component:** 优化表单交互 ([fb6167b](https://gitee.com/done-coding/done-coding-cli/commits/fb6167b57a235e6995a288f0789475eadb4a9561)) -* **component:** 增加list命令、add、remove命令检测优化 ([08735e8](https://gitee.com/done-coding/done-coding-cli/commits/08735e81ee1bbe5a739734c0bfc8f5c14888222d)) -* **component:** 组件创建主流程 ([ec8ec28](https://gitee.com/done-coding/done-coding-cli/commits/ec8ec28c8be57324c0919fddfb6c61781a8137db)) -* **component:** 组件命令行主流程 ([3dfb9a2](https://gitee.com/done-coding/done-coding-cli/commits/3dfb9a2056a6787084688aa9e0f6c5accf632cee)) -* **components:** list新增输出选项 ([487e8c3](https://gitee.com/done-coding/done-coding-cli/commits/487e8c3b01072623b93136c5518730260c8b9b04)) -* **config:** 工程化配置 ([6b093d8](https://gitee.com/done-coding/done-coding-cli/commits/6b093d8034f77f336295ceb700c62076db55359e)) -* **config:** 添加根命令名称 ([612bd32](https://gitee.com/done-coding/done-coding-cli/commits/612bd3214891bf80592952fb81b537affef32f4e)) -* **create:** 保留历史记录同时浅克隆仓库后二次询问是否需要克隆完整仓库 ([b04a79a](https://gitee.com/done-coding/done-coding-cli/commits/b04a79a64d5ff2752459e454c3aae611e715c550)) -* **create:** 调整目录结构 ([5dd7c85](https://gitee.com/done-coding/done-coding-cli/commits/5dd7c8515b02696e2e192db32437090eaf45c379)) -* **create:** 复用git模块clone命令 ([095f61b](https://gitee.com/done-coding/done-coding-cli/commits/095f61b94a09fa51f32b7b661d525775d6635a78)) -* **create:** 模板列表展示优化 ([4c91e1a](https://gitee.com/done-coding/done-coding-cli/commits/4c91e1a8a8cc1a8eb5f30b69a80f0b2f5cda6d8d)) -* **create:** 模版注入额外环境变量、内置提交代码提交 ([cd128a3](https://gitee.com/done-coding/done-coding-cli/commits/cd128a36d10e744bff175d0211ce3a0d1686f30f)) -* **create:** 输出版本号 ([d33a2cd](https://gitee.com/done-coding/done-coding-cli/commits/d33a2cd8429987ded6bd5371b43c3ad17152fa7f)) -* **create:** 添加项目名称选项并优化CLI参数配置 ([0966cb3](https://gitee.com/done-coding/done-coding-cli/commits/0966cb3507bd7207e62a29475f16ea25b461ad25)) -* **create:** 优化表单交互 ([1ca7638](https://gitee.com/done-coding/done-coding-cli/commits/1ca763878945c93bd0570688e29790eaef844603)) -* **create:** 增加克隆选项 则使用git helpers ([ed440c4](https://gitee.com/done-coding/done-coding-cli/commits/ed440c485726c40bb5c9378a1bb55decf7145cb7)) -* **create:** 增加平台用户仓库 ([dbf0baa](https://gitee.com/done-coding/done-coding-cli/commits/dbf0baac29f972ce46ee7c310e904112a57b98d2)) -* **create:** 增强项目创建工具和MCP服务器的集成 ([aa95d55](https://gitee.com/done-coding/done-coding-cli/commits/aa95d552a468f767d89b23730e20af69229fe8b0)) -* **create:** 增强项目创建选项和CLI参数 ([4702df8](https://gitee.com/done-coding/done-coding-cli/commits/4702df8c8d122a0d4706f613d810bf55c45a1eb6)) -* **create:** 支持多branch配置 ([c92be4e](https://gitee.com/done-coding/done-coding-cli/commits/c92be4e6ab4fc2b07c26779d1d04ec4574b1fabf)) -* **create:** 支持将模板仓库HTTP地址转换为SSH地址 ([cd1b93c](https://gitee.com/done-coding/done-coding-cli/commits/cd1b93cb04397f83fbbae5722b26213d18f13bc5)) -* **create:** 支持MCP预设答案及优化交互逻辑,符合项目提交风格且准确描述主要变更 ([ac5c8d1](https://gitee.com/done-coding/done-coding-cli/commits/ac5c8d15ef16541c6557b59f1e622fa6c74dd77a)) -* **create:** chalk => log ([c339659](https://gitee.com/done-coding/done-coding-cli/commits/c339659dd25d94d778db62db8bb98ac3cd4705ee)) -* **create:** prompts => xPrompts ([59618aa](https://gitee.com/done-coding/done-coding-cli/commits/59618aa37c126331b2b552e0c5aca310d4d11753)) -* **engin:** 工程化配置操作命令行 ([667b323](https://gitee.com/done-coding/done-coding-cli/commits/667b323c1e867f97b3cc63950ff318aa52bdd0d3)) -* **engin:** 添加husky相关 ([eb5b884](https://gitee.com/done-coding/done-coding-cli/commits/eb5b884bb8f20930552630e62820e4f5a0cd7d53)) -* **engin:** 添加vscode插件 ([4b47aeb](https://gitee.com/done-coding/done-coding-cli/commits/4b47aebb73f001daadd5bf7fd207848029da9eb1)) -* **engin:** 移除engin包 ([e961e2a](https://gitee.com/done-coding/done-coding-cli/commits/e961e2aadde83c31a3b6ed10d03d9cff86a47e68)) -* **env-config:** 重构环境配置管理,增强子进程支持 ([440f797](https://gitee.com/done-coding/done-coding-cli/commits/440f797e263d5a5b6cff49006d1be4d1240129ee)) -* **extrac:** 增加生成模式 默认result ([e363b41](https://gitee.com/done-coding/done-coding-cli/commits/e363b415aa541558c32a5768f9f2712d6a1f3bdc)) -* **extrac:** init、generate命令主流程 ([1016928](https://gitee.com/done-coding/done-coding-cli/commits/1016928f2577a4836b25f491e628c6aac5323190)) -* **extract:** 提取文件生成实现 ([7835533](https://gitee.com/done-coding/done-coding-cli/commits/78355335e259c18a27026d786146429391e75be9)) -* **extract:** 添加根命令名称 ([52efba1](https://gitee.com/done-coding/done-coding-cli/commits/52efba1b31adda48b7ef6e57f63b359c34731fc0)) -* **extract:** 添加fixed模式 helpers增加doneCodingPublishAliasInfo ([39c4c3b](https://gitee.com/done-coding/done-coding-cli/commits/39c4c3bce769001e1fc033711bec1f7eb3faa7a0)) -* **git:** 拆分暴露getTargetRepoUrl ([2e6ff6d](https://gitee.com/done-coding/done-coding-cli/commits/2e6ff6d671e985b293a1943f9f154fa400dd6329)) -* **git:** 初始化git ([9847d57](https://gitee.com/done-coding/done-coding-cli/commits/9847d57a02ddd1b8b4db3b91381ca527999c7308)) -* **git:** 单独导出clone命令 ([db8cef1](https://gitee.com/done-coding/done-coding-cli/commits/db8cef1224ca35d4ca689868ec000053565c2b48)) -* **git:** 获取gitee某个token可以获取仓库数量 ([75a009e](https://gitee.com/done-coding/done-coding-cli/commits/75a009e61cac6e4a48d961f9939728a3883c94aa)) -* **git:** 添加根命令名称 ([8be922e](https://gitee.com/done-coding/done-coding-cli/commits/8be922eeae0134ecd8669601cd1f96586c61f13f)) -* **git:** 添加git 反向合并检测操作 ([1fd3e14](https://gitee.com/done-coding/done-coding-cli/commits/1fd3e142e3ee3212a8e39cc0ff25e50033a0c0bd)) -* **git:** 新增init子命令 优化clone子命令 ([74a7392](https://gitee.com/done-coding/done-coding-cli/commits/74a7392cc465a37c5ebae6971f04ce579cd26591)) -* **git:** 优化表单交互 ([964ac40](https://gitee.com/done-coding/done-coding-cli/commits/964ac402b49d8963bbe94877fc06ffa53a9be137)) -* **git:** 增加helpers ([3124b4b](https://gitee.com/done-coding/done-coding-cli/commits/3124b4bb83fa49ff8addba59999706ab7a9d3ce1)) -* **git:** gitee&github获取可拉取仓库列表并克隆选择 ([90b8b1b](https://gitee.com/done-coding/done-coding-cli/commits/90b8b1bead5a9bce4b5e7bedf4c90aadb724f3ec)) -* **init:** 查询父及目录是否有.done-coding ([2b158fa](https://gitee.com/done-coding/done-coding-cli/commits/2b158fa3da15883e79980f54c30a9476a0036a64)) -* **init:** 创建init包 ([db19e38](https://gitee.com/done-coding/done-coding-cli/commits/db19e388a84659df6bbd69fddd56fe5c73af7846)) -* **inject & extract:** 默认命令 ([627d12b](https://gitee.com/done-coding/done-coding-cli/commits/627d12b6ccc57c320f39797e76feaf6ca794a01c)) -* **inject & extract:** 设置generate config默认值 ([1908c62](https://gitee.com/done-coding/done-coding-cli/commits/1908c62f10e472a5250d874b0b30690b05608452)) -* **inject:** 添加根命令名称 ([e1d9e27](https://gitee.com/done-coding/done-coding-cli/commits/e1d9e27de6c6eaaf65503da92cd372eaa72e9dc1)) -* **inject:** 信息注入主流程 ([26923c4](https://gitee.com/done-coding/done-coding-cli/commits/26923c474cd54835e55bdffbbb0354eebdcf4f80)) -* **inject:** 增加使用实践及各包使用 ([3a13922](https://gitee.com/done-coding/done-coding-cli/commits/3a13922ac6a8bfb932ff6025055a985a34fc5264)) -* **inject:** 增加init子命令 拆分generate子命令 移除use模块 增加helpers模块 ([a496f45](https://gitee.com/done-coding/done-coding-cli/commits/a496f45b7f1207e5efab02b0ee98edda7d8f6765)) -* **inject:** 注入增加提取模式、设值模式 ([721b23d](https://gitee.com/done-coding/done-coding-cli/commits/721b23d6747e2a863b5a1973af6d0d17489eeda7)) -* **inject:** read模式 支持sourceKey ([2b74530](https://gitee.com/done-coding/done-coding-cli/commits/2b745309c6b9f5082ba24dd186cc20a288ba346a)) -* **mcp-utils:** 添加客户端和服务端支持,重构项目结构 ([6f610c8](https://gitee.com/done-coding/done-coding-cli/commits/6f610c8d8a3fed056ac6574fea1ae4ac5348dce3)) -* **mcp-utils:** 添加mcp配置和工具注册功能 ([4ba2e67](https://gitee.com/done-coding/done-coding-cli/commits/4ba2e670e76a0a274d0ebc037973b3d1aff62e4b)) -* **mcp:** 添加MCP服务工具和资源注册功能 ([e4775de](https://gitee.com/done-coding/done-coding-cli/commits/e4775de935b21226482040c9d7bc8aec9753ab85)) -* **mcp:** 增加CLI测试命令,提高execSync的使用 ([82cbb1c](https://gitee.com/done-coding/done-coding-cli/commits/82cbb1c98f729263f514f8a5157daefb54c52442)) -* **mcp:** 增强项目创建和测试能力 ([12123d4](https://gitee.com/done-coding/done-coding-cli/commits/12123d4b0a715b1cfd44b6553477e4fdcb9b4ac7)) -* **mcp:** 重构包结构并增强项目创建工具 ([eba05fe](https://gitee.com/done-coding/done-coding-cli/commits/eba05fe4fe67d2cb1012ac79fc9e980355c33878)) -* **publish:** 版本号选择对其lerna ([e391e73](https://gitee.com/done-coding/done-coding-cli/commits/e391e730e42947e1ac28594f1dbf70f70344f0d7)) -* **publish:** 版本类型选择体验优化 ([0321024](https://gitee.com/done-coding/done-coding-cli/commits/0321024f5987c2d8e708284a08ca78a4b86912be)) -* **publish:** 别名包发布 ([5566d0b](https://gitee.com/done-coding/done-coding-cli/commits/5566d0be2188c83c9a29917c6e065d0481fe077c)) -* **publish:** 拆分发布命令为init及默认命令 ([768919d](https://gitee.com/done-coding/done-coding-cli/commits/768919d70f529844c117e79f5889f53a139f059b)) -* **publish:** 添加根命令名称 ([a472312](https://gitee.com/done-coding/done-coding-cli/commits/a472312b2751b1dbb6d2c5cdff70f9df86e30d92)) -* **publish:** 优化表单交互 ([8e9b60e](https://gitee.com/done-coding/done-coding-cli/commits/8e9b60ea5c706bed82c74294e598e9b8df7e573d)) -* **publish:** 重新设计参数、部分方法提取至cli-utils ([6523d5c](https://gitee.com/done-coding/done-coding-cli/commits/6523d5cf257cd1a2e182f595744ca655e12412fe)) -* **publish:** alias子命令类型 ([5a9e550](https://gitee.com/done-coding/done-coding-cli/commits/5a9e550383504799e818127f488faafe5b14e3c5)) -* **publish:** npm发布后检测是否配置别名发布 ([e6cecee](https://gitee.com/done-coding/done-coding-cli/commits/e6ceceee54802905944439811512814d7eea5797)) -* **publish:** publish命令迁移至monorepo & 主命令集成publish命令 ([36df0ac](https://gitee.com/done-coding/done-coding-cli/commits/36df0ac94161367f3d46ca0a0951d8049ab058c2)) -* **server-config:** 增强输出信息以改善用户体验 ([f8b20c8](https://gitee.com/done-coding/done-coding-cli/commits/f8b20c8a24fb25f6f67c6d2c277f60325cc003ca)) -* **template:** 获取配置文件地址 ([cdcc517](https://gitee.com/done-coding/done-coding-cli/commits/cdcc517d60994ebf145fd25ba4f217f7e4115981)) -* **template:** 模板编译支持批量文件操作 ([2fc702b](https://gitee.com/done-coding/done-coding-cli/commits/2fc702bf0b6a7a49f9ee9493cf61c06b4a4bd652)) -* **template:** 批量预编译支持设置根目录 ([7c4d1e7](https://gitee.com/done-coding/done-coding-cli/commits/7c4d1e7416dc3d79bb6a931c70aafddc525dbb0a)) -* **template:** 实现init子命令 ([995afb9](https://gitee.com/done-coding/done-coding-cli/commits/995afb9df96d6c5b1d68ec5b002391d84cc17b68)) -* **template:** 拓展模板的灵活性、拓展模板的模式 ([732e25c](https://gitee.com/done-coding/done-coding-cli/commits/732e25c0963346b6590dc4489b0f56db01be48d7)) -* **template:** 新增加预编译包 ([0acd447](https://gitee.com/done-coding/done-coding-cli/commits/0acd4470b18f09dc339ed515d2be43070a9c9fee)) -* **template:** 新增ls-lint ([07f7971](https://gitee.com/done-coding/done-coding-cli/commits/07f797110ff2b1e20d561473b641cca17e239bac)) -* **template:** 优化表单交互 ([7436c7b](https://gitee.com/done-coding/done-coding-cli/commits/7436c7b89207fd8b9076871ed5bd54ad98986c8c)) -* **template:** 优化参数 ([9ebdf7b](https://gitee.com/done-coding/done-coding-cli/commits/9ebdf7b7e4badeddfcf801203dbd62065ae8cef1)) -* **template:** 优化代码结构 增加批量编译子命令 ([f6d6e73](https://gitee.com/done-coding/done-coding-cli/commits/f6d6e7333c6d3c719b9978e1e081397ae1fd63d5)) -* **template:** 增加编译后回退功能,仅限覆盖、追加模式 ([735a3a0](https://gitee.com/done-coding/done-coding-cli/commits/735a3a006663af3b2afe9c81ff39ba5b19adee89)) -* **template:** 增加init子命令、原始命令变为compile子命令 ([feafc4e](https://gitee.com/done-coding/done-coding-cli/commits/feafc4e89e7ab9cc66ea7178d5f19d7fc17a6c5e)) -* **template:** compile命令 增加rootDir、configPath、rollbackDelNullFile, rootDir必传 ([b7d5e2c](https://gitee.com/done-coding/done-coding-cli/commits/b7d5e2cf090aa24113a8cccebe2d610c7987fdfa)) -* **template:** replace支持文件名预编译 ([28b57f8](https://gitee.com/done-coding/done-coding-cli/commits/28b57f8b9e471749384b11fe6be4c6c2c5676149)) -* **template:** template提取拆分 支持读配置文件主流程 ([c2eb456](https://gitee.com/done-coding/done-coding-cli/commits/c2eb45654d0d2902c89e73927f17db08b4c25b87)) -* **template:** template支持额外配置读取 ([d4d3478](https://gitee.com/done-coding/done-coding-cli/commits/d4d3478e716afd274be127d332b10467056b71a4)) -* **tools:** 新增目标查找 ([8e90bbd](https://gitee.com/done-coding/done-coding-cli/commits/8e90bbd118660b9287bcd510585cc0a215af42e5)) -* **tools:** 新增node工具包 ([632f7f9](https://gitee.com/done-coding/done-coding-cli/commits/632f7f9cf4b1cfb51b268e67d14e0571aad59932)) -* **tools:** 增加prompts中止输出处理流程 ([b16fb3c](https://gitee.com/done-coding/done-coding-cli/commits/b16fb3c05096bf6052ed5ebb2fcd020c562940bc)) -* ts子包模板 & vitest单元测试 ([93a11af](https://gitee.com/done-coding/done-coding-cli/commits/93a11af41b7a0aefd5d84b713ceb1ac1dfdc346c)) -* **utils:** 到处json5 ([d83f5a9](https://gitee.com/done-coding/done-coding-cli/commits/d83f5a99f08c4b794df04bff3241e53df9415ca0)) -* **utils:** 更新依赖和重构日志输出 ([732d969](https://gitee.com/done-coding/done-coding-cli/commits/732d9693e462f1f9918de42c35f445385d6cd735)) -* **utils:** 更新依赖项并增强流程事件处理 ([03686aa](https://gitee.com/done-coding/done-coding-cli/commits/03686aa7eeba6178855659f0e53e0ff4f9f9ac27)) -* **utils:** 简化配置和日志结构 ([a80403a](https://gitee.com/done-coding/done-coding-cli/commits/a80403ad838d2aa6c62752982db2423977f749ef)) -* **utils:** 日志与prompts封装 ([d89358e](https://gitee.com/done-coding/done-coding-cli/commits/d89358e918ed71df18bda8543f07abc292da3166)) -* **utils:** 输出常用的lodash工具 ([ab1036c](https://gitee.com/done-coding/done-coding-cli/commits/ab1036cf861c6eb295103ec46d89cf402c914e97)) -* **utils:** 提取git操作相关方法 ([31cab43](https://gitee.com/done-coding/done-coding-cli/commits/31cab43c056dbffe76ca9476c0d0be78de8f5abf)) -* **utils:** 添加cli-config、file-operate、husky ([daa60f0](https://gitee.com/done-coding/done-coding-cli/commits/daa60f05cefbbbd30bba54011f3a9c594b96c9ed)) -* **utils:** 增加配置文件通用方法、编辑器操作方法 ([e268741](https://gitee.com/done-coding/done-coding-cli/commits/e26874198d825dcc7a58041929e8c747ee1d0e0d)) -* **utils:** 增加cli模块 ([e9b62b3](https://gitee.com/done-coding/done-coding-cli/commits/e9b62b34873dd6f6cab2b536960c6c081791f11d)) -* **utils:** 增加git操作模块 ([8e158de](https://gitee.com/done-coding/done-coding-cli/commits/8e158de49ac29284f6705951957bd3f69288a7af)) -* **utils:** 增加package.json处理模块,读取配置支持不存在时设置默认值 ([42d81a0](https://gitee.com/done-coding/done-coding-cli/commits/42d81a047c9ec31c0ebaf460040366523089dd55)) -* **utils:** 增强环境配置和日志管理功能 ([acd7364](https://gitee.com/done-coding/done-coding-cli/commits/acd7364847725e86ce34124b9af1914aeea2293a)) -* **utils:** 增强日志记录和环境配置 ([78fb11d](https://gitee.com/done-coding/done-coding-cli/commits/78fb11d4caaa60468ac49d5f6d00788b7c7b7d26)) -* **utils:** 资产配置支持自定义及其他收拢优化 ([f775ea2](https://gitee.com/done-coding/done-coding-cli/commits/f775ea23325997faba76110c38e4b3496ed1f84b)) -* **utils:** cli-config临时文件夹放在系统临时文件夹 ([68323c0](https://gitee.com/done-coding/done-coding-cli/commits/68323c0dc0746dd2097640b7f0cfffb5931827e1)) -* **utils:** cli主命令、子命令 ([e5b1040](https://gitee.com/done-coding/done-coding-cli/commits/e5b1040bef7f09033590872e2f2d609e83d010d9)) -* **utils:** getRootScriptName 获取根命令 ([e843d03](https://gitee.com/done-coding/done-coding-cli/commits/e843d0302aeaba98e99bc983b646037e4cf47f0c)) -* **utils:** primary => stage, 新增info ([df83731](https://gitee.com/done-coding/done-coding-cli/commits/df8373109d8cac7e41cc92cbd2f0cbb184e3a591)) -* **utils:** tool=>utils ([16a8cd8](https://gitee.com/done-coding/done-coding-cli/commits/16a8cd8ada1efd152b60d68d1cbf2faa3e59ea7b)) - - -### Performance Improvements - -* 移除onPromptFormStateForSigint、收拢chalk、prompts ([06a913d](https://gitee.com/done-coding/done-coding-cli/commits/06a913d519c69e57d98856320f8fa39cebc4e2f6)) -* 优先命令创建方式 ([5dc2bad](https://gitee.com/done-coding/done-coding-cli/commits/5dc2bad4e752afeb7bc6cf2574d2a545b57e8010)) -* **component:** 收拢配置文件路径、使用utils json5 ([c28a103](https://gitee.com/done-coding/done-coding-cli/commits/c28a10354f8795cd8264a65ab670652f2ff32e23)) -* **component:** 组件操作优化 ([d922e72](https://gitee.com/done-coding/done-coding-cli/commits/d922e724c274571cc49f8c61177149679a21c070)) -* **component:** 组件模板编译增加配置 ([7815042](https://gitee.com/done-coding/done-coding-cli/commits/781504200dccc2109988d7dccbba47c8f1c626c4)) -* **create:** 组件模板编译增加配置 ([c94e594](https://gitee.com/done-coding/done-coding-cli/commits/c94e59416c717c30ffdbe4a3e2e970410ed29875)) -* **engin:** 优化add命令 ([e7cb4d9](https://gitee.com/done-coding/done-coding-cli/commits/e7cb4d951091d1675aeac3300e1a6e8d263d7a6c)) -* **extract:** 生成文件流程 ([3f93141](https://gitee.com/done-coding/done-coding-cli/commits/3f93141966966318b3928f98647d0606eb12337c)) -* **extract:** helpers文件 ([85c5c88](https://gitee.com/done-coding/done-coding-cli/commits/85c5c88299d7c87ee68a4356da83e7e294e534f0)) -* **git & component:** 子命令执行完成后退出进程避免父命令再次执行 ([ec09acd](https://gitee.com/done-coding/done-coding-cli/commits/ec09acd94d72f86987c3722ffdc887fd72e9f7fa)) -* **inject:** 参数语义化&优化inject导出 ([e2e2c1e](https://gitee.com/done-coding/done-coding-cli/commits/e2e2c1ee7f66dff2b6d383e72e219f7f98df1c8a)) -* **inject:** 调整done-coding实践调用 ([5268181](https://gitee.com/done-coding/done-coding-cli/commits/5268181a04fd1a97388a0aa4b6e931b6fd65c3cc)) -* **inject:** 注入信息优化 ([57648a9](https://gitee.com/done-coding/done-coding-cli/commits/57648a93c758f979259d2edf5d8becbc344b4d79)) -* **template:** 初始化配置文件方法 ([962b649](https://gitee.com/done-coding/done-coding-cli/commits/962b6492418b5a2ad6f24cf1c84bcfe43af16592)) -* **template:** 流程优化 ([b11d0d2](https://gitee.com/done-coding/done-coding-cli/commits/b11d0d276edb5c866ebe0fd7367f608720ee1d28)) -* **template:** 模板配置默认文件地址走变量拼接 ([f0143dd](https://gitee.com/done-coding/done-coding-cli/commits/f0143dd01df63277a81b849a31a70d50a9f40ebe)) -* **tools:** 寻找目标只返回目录 ([0231c81](https://gitee.com/done-coding/done-coding-cli/commits/0231c81fb8ff734b4fa58a10974d181bdb2374ad)) -* **utils:** 拆分导出getRootDirOptions ([7165f36](https://gitee.com/done-coding/done-coding-cli/commits/7165f3657ac6eb980e6d7eb98fcbb94425bcbe27)) -* **utils:** config-file 分情况处理json5&json ([a77fa6f](https://gitee.com/done-coding/done-coding-cli/commits/a77fa6fe9ebb650092ab3dc7c8156b836c2c0380)) -* **utils:** config-file提示、类型 ([27f437c](https://gitee.com/done-coding/done-coding-cli/commits/27f437c84b3bde44a7fdfb7f314fb5fd45771168)) -* **utils:** look-for、getRootDirOptions 实现优化 ([310e7ff](https://gitee.com/done-coding/done-coding-cli/commits/310e7ff4fb5b9b39ca70d962d71abbb122537103)) - - - diff --git a/README.md b/README.md index 48a0ac8..e166a73 100644 --- a/README.md +++ b/README.md @@ -114,7 +114,6 @@ done-coding-cli/ │ ├── publish/ # 发布工具 │ ├── template/ # 模板工具 │ └── utils/ # 工具库 -├── docs/ # 文档和指南 ├── scripts/ # 构建和发布脚本 ├── lerna.json # Lerna 配置 ├── package.json # 根包配置 @@ -171,9 +170,8 @@ graph TD ### 文档贡献 -- 遵循 [文档编写指南](./docs/DOCUMENTATION-GUIDE.md) -- 使用 [文档模板](./docs/README-TEMPLATE.md) -- 通过 [质量检查清单](./docs/DOCUMENTATION-CHECKLIST.md) 验证 +- 遵循项目现有的子包 README 模式 +- 参考各子包的 README.md 作为模板 ## 发布流程 @@ -189,12 +187,12 @@ pnpm run log ## 许可证 -MIT © [JustSoSu](https://gitee.com/done-coding) +MIT © [done-coding](https://github.com/done-coding) ## 相关链接 - [主 CLI 工具文档](./packages/cli/README.md) -- [项目仓库](https://gitee.com/done-coding/done-coding-cli) +- [项目仓库](https://github.com/done-coding/done-coding-cli) - [更新日志](./CHANGELOG.md) ## 支持 @@ -202,7 +200,6 @@ MIT © [JustSoSu](https://gitee.com/done-coding) 如果您在使用过程中遇到问题: 1. 查看各包的 README 文档 -2. 查看 [更新日志](./CHANGELOG.md) --- diff --git a/docs/BUSINESS_SNAPSHOT.md b/docs/BUSINESS_SNAPSHOT.md new file mode 100644 index 0000000..754b87a --- /dev/null +++ b/docs/BUSINESS_SNAPSHOT.md @@ -0,0 +1,170 @@ +# 业务快照 + +> 最后更新:2026-04-26 +> 关联任务:项目全局快照梳理 + +## 1. 业务领域与背景 + +### 产品定位 + +done-coding-cli 是一个面向 **Node.js 前端/全栈开发者**的 CLI 工具集,通过单一二进制 `DC`(及等效别名 `dc-cli`、`done-coding`)覆盖**创建→开发→工程配置→发布→AI 辅助**全流程。 + +### 核心价值 + +| 痛点 | 替换方式 | +|---|---| +| 项目初始化:手动 git clone + 改 package.json + 改配置 | `DC create` / `npm create done-coding`,一次交互完成 | +| 工程配置:手动装 ESLint/Prettier/Husky/commitlint 并写配置文件 | `DC config add -m eslint prettier commitlint ls-lint` 一键拉取安装 | +| 组件创建:复制粘贴 + 改名称 + 改引用 | `DC component add ` | +| 分支保护:靠口头约定防止倒灌合并 | `DC git hooks` 在 git hook 层自动拦截 reverse-merge | +| 发布:手动改版本 + npm publish + git push + git tag | `DC publish -t patch -d latest` 一条命令 | +| AI 辅助 | `DC` 无子命令 → 进入 AI 对话;`DC ai` → 独立入口 | + +### 关键术语 + +| 术语 | 含义 | +|---|---| +| `DC` | 主二进制命令,全局安装后的入口。同义别名:`dc-cli`、`done-coding`。macOS/Linux 上不能用小写 `dc`(与系统 dc 命令冲突),Windows 可以 | +| `npm create` 约定 | `npm create ` = 执行 `create-` 包的 bin;`npm create done-coding` 等价于直接执行 `create-done-coding` 的主命令 | +| 子包 | `packages/` 下每个目录是一个独立 npm 包,可被单独安装使用,也可经主 `DC` 命令统一调用 | +| `DC ` | 主命令下按 yargs 注册的子命令路由,如 `DC git` 映射到 `@done-coding/cli-git` | +| `injectInfo.json` | 每个子包在 `src/` 下的元数据 JSON(含 name/version/description/bin/cliConfig),构建时由 `@done-coding/cli-inject` 写入,运行时被 `import` 使用 | +| MCP / hijack 模式 | 父进程通过 `DONE_CODING_PROCESS_CREATE_BY_HIJACK_PRESET_JSON` 环境变量驱动子 CLI 进程:跳过 `prompts` 交互、结果写到日志、子进程完成后退出——使 AI agent 可无阻塞调用任何子命令 | +| xPrompts | `@done-coding/cli-utils` 对 `prompts` 库的封装,内置 hijack 感知(检测到 hijack 模式时自动跳过交互) | +| reverse-merge | 将分支等级高的分支(如 `main`)合并到等级低的分支(如 `feature`),属于 Git Flow 违规。`DC git check reverse-merge` 通过 reflog/提交记录检测并拦截 | + +## 2. 用户画像 + +| 角色 | 目标 | 典型调用 | +|---|---|---| +| **新手开发者** | 一行创建项目,不想手动配 lint/format | `npm create done-coding` | +| **日常开发者** | 统一入口执行各项操作 | 全局装 `@done-coding/cli`,用 `DC ` | +| **Tech Lead** | 强制团队工程规范 + 分支合并规则 | `DC config add -g`(提交到 git)、`DC git hooks` 配合 husky | +| **AI Agent** | 通过 MCP 无阻塞调用任何 CLI 子命令 | 所有子命令的 hijack 模式 | +| **贡献者** | 修改源码或新增子包 | `pnpm dev`、Conventional Commits、PR | + +## 3. 调用层架构 + +### 用户可达的命令入口 + +| 入口 | 示例 | 适用场景 | +|---|---|---| +| 主全局 CL I | `npm i -g @done-coding/cli` → `DC ` | 日常使用 | +| 子包独立 bin | `dc-component add Button`、`dc-git clone github user` | 只装单个子包时 | +| npm create 约定 | `npm create done-coding`、`pnpm create done-coding` | 零安装创建项目 | + +### 子命令路由表 + +> **路由规则:** 当用户在 `DC ` 之后未继续指定二级命令时(例如只输入 `DC create`),yargs 会自动路由到该子包设定的默认命令。下表中标注"默认"的即为未指明时的兜底路由目标。 + +| 用户输入 | 映射子包 | 可用二级命令 | +|---|---|---| +| `DC create` | `create-done-coding` | `create`(未指明时默认执行) | +| `DC component` | `@done-coding/cli-component` | `add`、`remove`、`list` | +| `DC config` | `@done-coding/cli-config` | `check`、`add` | +| `DC extract` | `@done-coding/cli-extract` | `init`、`generate`(未指明时默认执行) | +| `DC inject` | `@done-coding/cli-inject` | `init`、`generate`(未指明时默认执行) | +| `DC publish` | `@done-coding/cli-publish` | `init`、`exec`(未指明时默认执行)、`alias` | +| `DC template` | `@done-coding/cli-template` | `init`、`compile`(未指明时默认执行)、`batch` | +| `DC git` | `@done-coding/cli-git` | `init`、`clone`、`hooks`、`check` | +| `DC ai` | `@done-coding/cli-ai` | `chat`(默认) | +| `DC`(无子命令) | `@done-coding/cli` 自身 | 交互式提问 → AI 对话或 --help | + +## 4. 功能清单 + +各子包详情见对应 docs 目录。以下为根级概览。 + +| 子命令 | 包名 | 核心能力 | 状态 | 详情 | +|---|---|---|---|---| +| `DC create` | `create-done-coding` | 从 Git 模板创建项目,交互式问答,git clone + Lodash 模板编译 + git 细节优化 | `活跃` | `packages/create/docs/BUSINESS.md`(待创建) | +| `DC component` | `@done-coding/cli-component` | 组件增删查(add/remove/list),命名自动转换 | `活跃` | `packages/component/docs/BUSINESS.md`(待创建) | +| `DC config` | `@done-coding/cli-config` | 工程配置检测与安装(eslint/prettier/commitlint/ls-lint/merge-lint) | `活跃` | `packages/config/docs/BUSINESS.md`(待创建) | +| `DC extract` | `@done-coding/cli-extract` | 从源码提取信息生成文件(正则/json-inject/fixed 三种提取方式) | `活跃` | `packages/extract/docs/BUSINESS.md`(待创建) | +| `DC inject` | `@done-coding/cli-inject` | JSON 数据注入目标文件(reg/fixed/read 三种注入方式) | `活跃` | `packages/inject/docs/BUSINESS.md`(待创建) | +| `DC template` | `@done-coding/cli-template` | Lodash 模板编译引擎,支持 4 种输出模式 + 回滚 + Markdown 处理,被 create/component/extract 内部调用 | `活跃` | `packages/template/docs/BUSINESS.md`(待创建) | +| `DC git` | `@done-coding/cli-git` | 跨平台 Git 操作(init/clone/hooks/check),含 reverse-merge 检测 | `活跃` | `packages/git/docs/BUSINESS.md`(待创建) | +| `DC publish` | `@done-coding/cli-publish` | 语义化版本管理 + npm/web 发布 + 别名发布 | `活跃` | `packages/publish/docs/BUSINESS.md`(待创建) | +| `DC ai` | `@done-coding/cli-ai` | AI 交互式对话(选模型 → 填 key → SSE 流式聊天) | `活跃` | `packages/ai/docs/BUSINESS.md`(待创建) | +| — | `@done-coding/cli-utils` | 共享工具库(yargs 封装、xPrompts、配置管理、Git 工具、AES 加密等) | `活跃` | 无独立 CLI | + +## 5. 核心业务流程 + +### 流程 1:开发者首次创建项目 + +``` +npm create done-coding ← 零安装,npm 自动映射到 create-done-coding + → 交互式输入项目名 + → 从远程模板列表选择模板 + → git clone --depth=1(浅克隆) + → 模板有 .done-coding config?→ batchCompileHandler 编译 Lodash 模板 + → git 细节优化:分支重命名 / HTTP→SSH URL / 保存或重建 git history + → git init && git commit -m "feat: init project" + → 输出:cd my-project && pnpm install && pnpm run dev +``` + +### 流程 2:日常开发完整链路 + +``` +DC component add UserCard ← 生成组件 + → 名称处理(camelCase/kebab-case/PascalCase) + → 模板生成文件 + 注入环境数据 + +DC config check -m eslint prettier commitlint ls-lint merge-lint + → 检测各模块配置状态 + → merge-lint 调用 DC git check reverse-merge + +...编码... + +DC publish -t patch -d latest + → 读取 publish config → 升级版本号 → npm publish → git push +``` + +### 流程 3:MCP/Hijack(AI Agent 驱动) + +``` +AI Agent 调用 CLI + → 父进程设 env: DONE_CODING_PROCESS_CREATE_BY_HIJACK_PRESET_JSON + → 子进程 processIsHijacked() = true + → xPrompts 检测到 hijack,跳过交互,用预设值/CLI 参数填充 + → console 输出 → 日志文件(非 stdout) + → 子进程结束 +``` + +## 6. 业务规则与约束 + +### 编码与提交 + +- [MUST] **Conventional Commits**:`feat`/`fix`/`chore`/`docs`/`refactor`/`test`,commitlint 校验 +- [MUST] **ESLint + Prettier**:统一代码风格 +- [MUST] **ls-lint**:文件命名规范(kebab-case) +- [MUST] **husky + lint-staged**:提交前自动检查 + +### 版本管理 + +- **Independent versioning**:每个子包独立 SemVer 版本号,Lerna 管理 +- 发布类型用 `-t` 指定或交互选择,支持 major / minor / patch / premajor / preminor / prepatch / prerelease +- dist-tag:latest / next / alpha / beta / rc + +### Git 分支保护 + +- [MUST NOT] reverse-merge:将高等级分支合并到低等级分支 +- 等级:main > develop > feature/hotfix > personal +- 检测方式:husky hooks(pre-merge-commit、prepare-commit-msg、post-merge、pre-push、pre-rebase)+ `DC git check reverse-merge` + +### 环境 + +- Node.js >= 18.0.0 +- pnpm(`preinstall` 脚本强制 `npx only-allow pnpm`) +- 跨平台:Windows / macOS / Linux + +### 许可证 + +MIT + +## 7. 已知业务债务 + +| 债务 | 影响 | 优先级 | +|---|---|---| +| 部分子包 README 未列出 `DC ` 能用的具体选项,用户需靠 `--help` 反推 | 独立使用子包的用户可能因文档不全而放弃 | 中 | +| create-done-coding 的远程模板列表依赖 Gitee 外部仓库 | Gitee 不可用时 `DC create` 无法获取模板列表 | 低 | +| CHANGELOG.md 已删除但部分 README 仍含链接 | README 404 链接 | 低 | diff --git a/docs/DOCUMENTATION-CHECKLIST.md b/docs/DOCUMENTATION-CHECKLIST.md deleted file mode 100644 index 8d799e5..0000000 --- a/docs/DOCUMENTATION-CHECKLIST.md +++ /dev/null @@ -1,176 +0,0 @@ -# 文档质量检查清单 - -使用此清单确保每个包的文档符合 done-coding CLI 项目的质量标准。 - -## 基础结构检查 - -### 必需章节 ✅ - -- [ ] **标题和描述**: 包含包名和清晰的功能描述 -- [ ] **安装说明**: 提供独立安装和集成安装方法 -- [ ] **快速开始**: 包含基本使用示例 -- [ ] **功能特性**: 列出主要功能(使用 emoji) -- [ ] **API 文档**: 详细的命令和选项说明 -- [ ] **使用示例**: 至少 3 个实际使用场景 -- [ ] **故障排除**: 常见问题和解决方案 -- [ ] **许可证**: MIT 许可证信息 -- [ ] **相关链接**: npm 包和仓库链接 - -### 推荐章节 📋 - -- [ ] **配置**: 配置文件和选项说明 -- [ ] **编程接口**: 作为模块使用的方法 -- [ ] **性能建议**: 最佳实践和优化建议 -- [ ] **贡献指南**: 开发环境设置说明 - -## 内容质量检查 - -### 文本内容 📝 - -- [ ] **语法正确**: 无语法错误和拼写错误 -- [ ] **描述清晰**: 功能描述准确且易理解 -- [ ] **术语统一**: 使用统一的技术术语翻译 -- [ ] **格式一致**: 标题、列表、代码块格式统一 -- [ ] **信息准确**: 版本号、依赖关系等信息最新 - -### 代码示例 💻 - -- [ ] **语法正确**: 所有代码示例语法正确 -- [ ] **可执行性**: 示例代码可以实际运行 -- [ ] **完整性**: 示例包含必要的上下文 -- [ ] **多样性**: 涵盖基础和高级使用场景 -- [ ] **注释清晰**: 复杂示例包含必要注释 - -### 链接验证 🔗 - -- [ ] **npm 链接**: 所有 npm 包链接格式正确且可访问 -- [ ] **内部链接**: 项目内部链接路径正确 -- [ ] **外部链接**: 外部资源链接有效 -- [ ] **徽章链接**: npm 版本徽章和许可证徽章正常显示 - -## 格式规范检查 - -### Markdown 格式 📄 - -- [ ] **标题层级**: 使用正确的标题层级(#, ##, ###, ####) -- [ ] **代码块**: 使用正确的语言标识符 -- [ ] **列表格式**: 有序和无序列表格式正确 -- [ ] **表格格式**: 表格对齐和格式正确 -- [ ] **引用格式**: 引用块格式正确 - -### 徽章规范 🏷️ - -- [ ] **npm 版本徽章**: - ```markdown - [![npm version](https://badge.fury.io/js/@done-coding%2Fcli-{package-name}.svg)](https://www.npmjs.com/package/@done-coding/cli-{package-name}) - ``` -- [ ] **许可证徽章**: - ```markdown - [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) - ``` - -### 代码块规范 💾 - -- [ ] **Bash 命令**: 使用 `bash` 标识符 -- [ ] **JavaScript**: 使用 `javascript` 标识符 -- [ ] **TypeScript**: 使用 `typescript` 标识符 -- [ ] **JSON**: 使用 `json` 标识符 -- [ ] **配置文件**: 使用适当的语言标识符 - -## 特定包类型检查 - -### 主 CLI 包额外检查 🎯 - -- [ ] **子命令列表**: 包含所有子包的完整信息 -- [ ] **版本信息**: 每个子包的当前版本号 -- [ ] **命令映射**: 清晰的命令到包的映射关系 -- [ ] **架构图**: 包依赖关系的可视化展示 - -### 子包额外检查 📦 - -- [ ] **独立性**: 可以作为独立包使用 -- [ ] **集成性**: 说明如何与主 CLI 集成使用 -- [ ] **命令前缀**: 正确的命令前缀(dc-{name}) -- [ ] **帮助信息**: --help 选项的说明 - -## 用户体验检查 - -### 新用户友好性 👋 - -- [ ] **零基础**: 新用户可以根据文档快速上手 -- [ ] **示例完整**: 示例包含完整的执行步骤 -- [ ] **错误处理**: 说明常见错误和解决方法 -- [ ] **前置条件**: 明确说明使用前的准备工作 - -### 高级用户支持 🚀 - -- [ ] **API 文档**: 详细的编程接口说明 -- [ ] **配置选项**: 完整的配置参数说明 -- [ ] **扩展性**: 说明如何扩展和自定义 -- [ ] **性能优化**: 提供性能优化建议 - -## 维护性检查 - -### 版本管理 🔄 - -- [ ] **版本同步**: 文档中的版本号与 package.json 一致 -- [ ] **更新日志**: 链接到 CHANGELOG.md -- [ ] **兼容性**: 说明版本兼容性要求 -- [ ] **迁移指南**: 重大版本变更的迁移说明 - -### 可维护性 🛠️ - -- [ ] **模块化**: 文档结构清晰,易于更新 -- [ ] **标准化**: 遵循项目文档标准 -- [ ] **可搜索**: 包含关键词,便于搜索 -- [ ] **可链接**: 章节有明确的锚点 - -## 检查工具 - -### 自动化检查 🤖 - -```bash -# 链接检查 -npx markdown-link-check README.md - -# 拼写检查 -npx cspell README.md - -# 格式检查 -npx prettier --check README.md -``` - -### 手动检查 👁️ - -- [ ] **通读全文**: 完整阅读一遍文档 -- [ ] **执行示例**: 按照文档执行所有示例 -- [ ] **测试链接**: 点击所有链接确认可访问 -- [ ] **移动端查看**: 在移动设备上查看格式 - -## 检查记录 - -### 检查信息 - -- **检查日期**: ___________ -- **检查人员**: ___________ -- **包名称**: ___________ -- **包版本**: ___________ - -### 检查结果 - -- **通过项目数**: _____ / _____ -- **需要修复的问题**: - - [ ] 问题1: ________________ - - [ ] 问题2: ________________ - - [ ] 问题3: ________________ - -### 后续行动 - -- [ ] **立即修复**: 修复所有发现的问题 -- [ ] **计划修复**: 制定修复计划和时间表 -- [ ] **重新检查**: 修复后重新进行检查 -- [ ] **发布更新**: 更新文档并发布新版本 - ---- - -**注意**: 此检查清单应该在每次文档更新后使用,确保文档质量始终符合项目标准。 \ No newline at end of file diff --git a/docs/DOCUMENTATION-GUIDE.md b/docs/DOCUMENTATION-GUIDE.md deleted file mode 100644 index c22e454..0000000 --- a/docs/DOCUMENTATION-GUIDE.md +++ /dev/null @@ -1,237 +0,0 @@ -# done-coding CLI 文档编写指南 - -本指南定义了 done-coding CLI monorepo 项目中所有包的文档标准,确保文档的一致性和完整性。 - -## 文档结构标准 - -### 主 CLI 包 (@done-coding/cli) - -主 CLI 包的 README 应包含以下章节: - -1. **标题和描述** - 项目名称和简短描述 -2. **安装** - 全局安装说明 -3. **快速开始** - 基本使用方法 -4. **子命令概览** - 所有子包的详细列表 -5. **完整命令列表** - 命令速查表 -6. **使用示例** - 常见使用场景 -7. **配置** - 配置文件说明 -8. **架构设计** - 包依赖关系图 -9. **故障排除** - 常见问题解答 -10. **贡献指南** - 如何参与贡献 -11. **许可证** - MIT 许可证信息 -12. **相关链接** - 重要链接集合 - -### 子包文档 - -每个子包的 README 应包含以下标准章节: - -1. **标题和描述** - 包名和功能描述 -2. **徽章** - npm 版本和许可证徽章 -3. **安装** - 独立安装和集成安装 -4. **快速开始** - 基本使用示例 -5. **功能特性** - 主要功能列表(使用 emoji) -6. **API 文档** - 详细的命令和选项说明 -7. **使用示例** - 实际使用场景 -8. **配置** - 配置文件和选项 -9. **编程接口** - 作为模块使用的方法 -10. **故障排除** - 常见问题和解决方案 -11. **性能建议** - 最佳实践 -12. **贡献指南** - 开发环境设置 -13. **许可证** - MIT 许可证 -14. **相关链接** - 相关资源链接 - -## 内容编写规范 - -### 标题规范 - -- 使用 `#` 作为主标题 -- 使用 `##` 作为章节标题 -- 使用 `###` 作为子章节标题 -- 使用 `####` 作为具体功能标题 - -### 代码块规范 - -```bash -# 命令行示例使用 bash -command --option value -``` - -```javascript -// JavaScript 代码示例 -const example = 'value'; -``` - -```typescript -// TypeScript 代码示例 -interface Example { - property: string; -} -``` - -### 链接规范 - -#### npm 包链接格式 -```markdown -[包名](https://www.npmjs.com/package/包名) -``` - -#### 内部链接格式 -```markdown -[相对路径链接](./path/to/file.md) -``` - -#### 外部链接格式 -```markdown -[链接文本](https://example.com) -``` - -### 徽章规范 - -每个子包都应包含以下徽章: - -```markdown -[![npm version](https://badge.fury.io/js/@done-coding%2Fcli-{package-name}.svg)](https://www.npmjs.com/package/@done-coding/cli-{package-name}) -[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -``` - -### 功能特性列表规范 - -使用 emoji 和简洁描述: - -```markdown -- ✅ **主要功能**: 功能描述 -- 🚀 **性能优势**: 性能相关特性 -- 🔄 **工作流程**: 流程改进特性 -- 📝 **开发体验**: 开发者体验改进 -- 🔍 **其他特性**: 其他重要功能 -``` - -## 模板使用指南 - -### 使用 README 模板 - -1. 复制 `docs/README-TEMPLATE.md` -2. 替换所有 `{placeholder}` 占位符: - - `{package-name}`: 包名(不含前缀) - - `{package-description}`: 包的简短描述 - - `{detailed-description}`: 详细功能描述 - - `{command-name}`: 命令名称 - - `{MainClass}`: 主要类名 - - `{TypeName}`: 类型名称 - - `{OptionsType}`: 选项类型名称 - -### 占位符替换示例 - -对于 `@done-coding/cli-git` 包: - -```markdown -# 替换前 -# @done-coding/cli-{package-name} - -# 替换后 -# @done-coding/cli-git -``` - -## 内容质量标准 - -### 必需内容 - -每个文档必须包含: - -- [ ] 清晰的安装说明 -- [ ] 至少 3 个使用示例 -- [ ] 完整的 API 文档 -- [ ] 故障排除章节 -- [ ] 正确的 npm 包链接 - -### 可选内容 - -根据包的复杂程度可选择包含: - -- [ ] 配置文件示例 -- [ ] TypeScript 类型定义 -- [ ] 性能建议 -- [ ] 高级使用场景 -- [ ] 架构说明 - -### 内容质量检查 - -- [ ] 所有代码示例都可执行 -- [ ] 所有链接都有效 -- [ ] 语法和拼写正确 -- [ ] 格式一致 -- [ ] 信息准确且最新 - -## 多语言支持 - -### 中英文对照 - -| 中文 | English | -|------|---------| -| 安装 | Installation | -| 快速开始 | Quick Start | -| 功能特性 | Features | -| 使用示例 | Examples | -| 配置 | Configuration | -| 故障排除 | Troubleshooting | -| 贡献指南 | Contributing | -| 许可证 | License | - -### 术语统一 - -| 术语 | 统一翻译 | -|------|----------| -| CLI | 命令行工具 | -| Package | 包 | -| Subcommand | 子命令 | -| Template | 模板 | -| Configuration | 配置 | -| Workflow | 工作流程 | - -## 维护流程 - -### 文档更新时机 - -- 包版本发布时 -- 新功能添加时 -- API 变更时 -- 用户反馈问题时 - -### 更新检查清单 - -- [ ] 版本号是否最新 -- [ ] 新功能是否已文档化 -- [ ] 示例代码是否可用 -- [ ] 链接是否有效 -- [ ] 格式是否一致 - -### 质量保证 - -1. **自检**: 作者自行检查内容完整性 -2. **同行评审**: 团队成员交叉检查 -3. **用户测试**: 根据文档进行实际操作测试 - -## 工具和资源 - -### 推荐工具 - -- **Markdown 编辑器**: Typora, Mark Text -- **链接检查**: markdown-link-check -- **拼写检查**: cspell -- **格式化**: prettier - -### 参考资源 - -- [Markdown 语法指南](https://www.markdownguide.org/) -- [npm 包文档最佳实践](https://docs.npmjs.com/packages-and-modules/contributing-packages-to-the-registry) -- [开源项目文档指南](https://opensource.guide/best-practices/) - -## 示例文档 - -- [主 CLI 包示例](../packages/cli/README.md) -- [子包示例](../packages/git/README.md) -- [模板文件](./README-TEMPLATE.md) - ---- - -遵循本指南可以确保 done-coding CLI 项目的文档保持高质量和一致性,为用户提供最佳的使用体验。 \ No newline at end of file diff --git a/docs/HARNESS_REVIEW.md b/docs/HARNESS_REVIEW.md new file mode 100644 index 0000000..26696af --- /dev/null +++ b/docs/HARNESS_REVIEW.md @@ -0,0 +1,64 @@ +# Harness Review + +> 本文件记录 AI 执行中发现的 harness 缺陷,PM/老板归档时复盘决定是否采纳。 + +--- + +## 2026-04-26: 跳 Gate 3 — 未经用户审核直接提交代码 + +**层级:** 项目改进 + +**现象:** +AI 对话任务在设计阶段结束后,用户说"确认",AI 理解为"确认 specs 并开始执行",用户实际意图为"确认 specs 内容正确"。AI 从 Task 1 一路执行到 Task 7 并 commit 6 次,用户没有机会逐 task 审阅代码。 + +**根因:** +- 设计阶段结束 → 实施阶段的过渡缺少显式的 Gate 确认语术 +- "确认"一词存在歧义:可能是"确认文档内容"也可能是"确认开始实施" +- AI 在获取用户下一步信号时没有使用 `AskUserQuestion` 提供明确的选项("开始实施" vs "修改文档") + +**建议改进:** +在 complex-flow 的 Gate 2 → Gate 3 过渡处,实施开始前强制输出确认语术: + +``` +确认开始实施? +a. 开始实施,逐 task 提交 +b. 修改设计/计划后再说 +``` + +> **2026-04-26 二次复现**:同一任务中再次跳过用户审核直接提交(见下方"二次违纪"记录)。该模式已确定为 AI 行为缺陷,非偶然事件。 + +--- + +## 2026-04-26(二次违纪): Gate 审核失败复现—修 TS 报错后再次自主提交 + +**层级:** 全局改进(复现,从特例升级) + +**现象:** +首次 Gate 违规记录后不到 1 小时内,AI 在修复 TS 诊断报错时再次绕过用户审核直接 commit。用户明确指出"你严重违纪 你未经我审核 直接提交代码"并手动回退。 + +**根因:** +- 首次记录后只写了文档,未在 AI 行为层面建立阻断机制 +- "修 bug"在 AI 判断中被视为低风险操作,自动略过审核 +- 文件修改 → commit 的惯性过强,缺少显式的中断点 + +**建议改进:** +- [MUST] 任何 `git commit` 操作前执行显式预检:检查当前是否处于 Gate 期,若 Gate 未通过则禁止 commit +- 在 CLAUDE.md 或项目 `CLAUDE.md` 中增加规则:`WHEN 修改任何源文件后,[MUST] 先展示 diff 或列出变更,获取用户确认后 [MUST] 再 commit` + +## 2026-04-26: 未查实际 API 就使用 `outputConsole.log` — 该方法不存在 + +**层级:** 项目改进 + +**现象:** +AI 在 chat.ts 中使用 `outputConsole.log()` 打印普通信息,但 `outputConsole` 不存在 `log` 方法。运行时报错 `TypeError: outputConsole.log is not a function`。用户指出应使用 `outputConsole.info()`。 + +**根因:** +- AI 根据通用经验假设 `outputConsole.log` 存在(大多数 logger 都有 `log` 方法) +- 实现代码前没有 grep 验证 `outputConsole` 的实际方法列表 +- 现有方法为:`info`、`error`、`warn`、`success`、`stage`、`skip`、`debug`——偏偏没有 `log` + +**建议改进:** +- TECH_SNAPSHOT 的「常见错误」中新增一条:假设开源库/内部模块的 API 存在某个通用方法 -> [MUST] grep 验证 +- 或者在设计阶段要求列出将要使用的模块接口作为 checklist + +> 特例复现 → 项目改进;跨项目出现 → 全局改进 diff --git a/docs/README-TEMPLATE.md b/docs/README-TEMPLATE.md deleted file mode 100644 index a983f0a..0000000 --- a/docs/README-TEMPLATE.md +++ /dev/null @@ -1,236 +0,0 @@ -# @done-coding/cli-{package-name} - -{package-description} - {detailed-description} - -[![npm version](https://badge.fury.io/js/@done-coding%2Fcli-{package-name}.svg)](https://www.npmjs.com/package/@done-coding/cli-{package-name}) -[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) - -## 安装 - -### 独立安装 - -```bash -npm install @done-coding/cli-{package-name} -# 或 -pnpm add @done-coding/cli-{package-name} -``` - -### 作为 done-coding CLI 的一部分 - -```bash -npm install -g @done-coding/cli -# 然后使用 -DC {command-name} [options] -``` - -## 快速开始 - -```bash -# 独立使用 -dc-{command-name} [action] - -# 作为主 CLI 的子命令 -DC {command-name} [action] - -# 查看帮助 -dc-{command-name} --help -``` - -{postinstall-section-start} - -### 安装后提示 - -{postinstall-content} - -{postinstall-section-end} - -## 功能特性 - -- ✅ **特性1**: 描述主要功能 -- 🚀 **特性2**: 描述性能优势 -- 🔄 **特性3**: 描述工作流程改进 -- 📝 **特性4**: 描述开发体验提升 -- 🔍 **特性5**: 描述其他重要特性 - -## API 文档 - -### 基础命令 - -#### `dc-{command-name} action1` - -描述基础命令的功能 - -```bash -dc-{command-name} action1 [options] -# 示例输出或说明 -``` - -#### `dc-{command-name} action2` - -描述另一个基础命令 - -```bash -# 基础用法 -dc-{command-name} action2 - -# 带参数的用法 -dc-{command-name} action2 --option value -``` - -### 高级功能 - -#### `dc-{command-name} advanced-action` - -描述高级功能 - -```bash -# 高级用法示例 -dc-{command-name} advanced-action --config ./config.json -``` - -## 使用示例 - -### 基础使用场景 - -```bash -# 1. 初始化 -dc-{command-name} init - -# 2. 执行主要操作 -dc-{command-name} main-action - -# 3. 查看结果 -dc-{command-name} status -``` - -### 高级使用场景 - -```bash -# 复杂工作流程示例 -dc-{command-name} complex-workflow --input ./src --output ./dist -``` - -## 配置 - -在项目根目录创建 `.done-coding-{package-name}.config.js`: - -```javascript -export default { - // 基础配置 - option1: "default-value", - - // 高级配置 - advanced: { - feature1: true, - feature2: { - subOption: "value", - }, - }, - - // 自定义配置 - custom: { - // 用户自定义选项 - }, -}; -``` - -## 编程接口 - -### 作为模块使用 - -```javascript -import { {MainClass} } from '@done-coding/cli-{package-name}/helpers'; - -const tool = new {MainClass}(); - -// 基础操作 -const result = await tool.basicOperation(); -console.log(result); - -// 高级操作 -await tool.advancedOperation(options); -``` - -### TypeScript 支持 - -```typescript -import type { {TypeName}, {OptionsType} } from '@done-coding/cli-{package-name}/helpers'; - -const options: {OptionsType} = { - // 类型安全的配置 -}; -``` - -## 故障排除 - -### 常见问题 - -**Q: 问题描述** - -```bash -# 解决方案命令 -dc-{command-name} fix-command -``` - -**Q: 另一个常见问题** - -```bash -# 检查命令 -dc-{command-name} check - -# 修复命令 -dc-{command-name} repair -``` - -### 调试模式 - -```bash -# 启用详细输出 -dc-{command-name} --verbose action - -# 启用调试模式 -DEBUG=done-coding:{package-name} dc-{command-name} action -``` - -## 性能建议 - -- 建议1:具体的性能优化建议 -- 建议2:最佳实践 -- 建议3:避免的常见问题 - -## 贡献指南 - -我们欢迎贡献!请遵循以下步骤: - -1. Fork 本仓库 -2. 创建功能分支:`git checkout -b feature/amazing-feature` -3. 提交更改:`git commit -m "feat: add amazing feature"` -4. 推送分支:`git push origin feature/amazing-feature` -5. 创建 Pull Request - -### 开发环境设置 - -```bash -# 克隆仓库 -git clone https://github.com/done-coding/done-coding-cli.git -cd done-coding-cli/packages/{package-name} - -# 安装依赖 -pnpm install - -# 开发模式 -pnpm dev - -# 运行测试 -pnpm test -``` - -## 许可证 - -MIT © [JustSoSu](https://gitee.com/done-coding) - -## 相关链接 - -- [主 CLI 工具](https://www.npmjs.com/package/@done-coding/cli) -- [Gitee 仓库](https://gitee.com/done-coding/done-coding-cli) -- [更新日志](./CHANGELOG.md) diff --git a/docs/TECH_SNAPSHOT.md b/docs/TECH_SNAPSHOT.md new file mode 100644 index 0000000..ac20983 --- /dev/null +++ b/docs/TECH_SNAPSHOT.md @@ -0,0 +1,421 @@ +# 技术架构快照 + +> 最后更新:2026-04-26 +> 关联任务:项目全局快照梳理 + +## 1. 系统上下文(C4 Level 1) + +### 系统边界 + +``` + ┌──────────────────────────────────────┐ + │ done-coding-cli │ + │ │ + Developer ────▶│ DC / dc-cli / done-coding (bin) │────▶ npm registry + │ │ │ + AI Agent ─────▶│ ├── DC create / npm create done... │────▶ Git repos (GitHub/Gitee/...) + │ ├── DC component │ + │ ├── DC config │────▶ Gitee assets config repo + │ ├── DC extract/inject │ + │ ├── DC git │────▶ OS filesystem (.git, ~/.done-coding) + │ ├── DC publish │ + │ ├── DC template │ + │ └── DC ai │ + │ │ + │ @done-coding/cli-utils (foundation) │ + └──────────────────────────────────────┘ +``` + +### 外部依赖 + +| 外部系统 | 协议 | 用途 | +|---|---|---| +| npm registry | HTTPS | 包发布、依赖安装 | +| GitHub / Gitee / GitLab / Bitbucket | HTTPS / SSH(git clone) | 模板仓库、用户仓库克隆 | +| Gitee(done-coding-cli-assets-config) | HTTPS(git clone) | 工程化配置资产拉取 | +| Node.js runtime(>= 18) | 进程环境 | 执行环境 | +| MCP(Model Context Protocol) | 环境变量 + stdin/stdout | AI agent 驱动 | + +## 2. 技术选型 + +| 层面 | 选型 | 版本 | +|---|---|---| +| 语言 | TypeScript | ^5.8.3 | +| 运行时 | Node.js | >= 18.0.0 | +| 模块系统 | ESM(`"type": "module"`) | — | +| 包管理 | pnpm(workspaces) | — | +| 版本管理 | Lerna(independent mode) | ^7.3.0 | +| CLI 框架 | yargs(通过 @done-coding/cli-utils 封装) | — | +| 构建 | Vite + vite-plugin-dts | ^5.0.10 / ^3.7.0 | +| 交互输入 | prompts(通过 xPrompts 封装) | — | +| 模板引擎 | lodash.template | — | +| 配置格式 | JSON5 / JSON | — | +| 测试 | Vitest | ^1.6.1 | +| 代码风格 | ESLint + Prettier + ls-lint | ^8.49.0 / ^3.8.0 / ^2.2.3 | +| 提交规范 | commitlint(conventional config) | ^16.3.0 | +| Git hooks | husky + lint-staged | ^8.0.3 / ^12.5.0 | +| 发布 | Lerna publish(+ 自定义 postpush 脚本) | ^7.3.0 | + +## 3. 架构风格与模式 + +### 整体架构:分层 Monorepo + +``` +入口层: @done-coding/cli(主命令注册 + 子命令路由 + AI 对话入口) + create-done-coding(独立入口:npm create done-coding) + │ +业务层: @done-coding/cli-component 组件管理 + @done-coding/cli-config 工程配置(运行时调用 git 包) + @done-coding/cli-extract 信息提取 + @done-coding/cli-inject 信息注入(构建时用于 injectInfo.json) + @done-coding/cli-git Git 操作 + @done-coding/cli-publish 项目发布 + @done-coding/cli-template 模板编译(被 create/component/extract 依赖) + @done-coding/cli-ai AI 对话(选服务商 → 选模型 → SSE 流式) + │ +基础层: @done-coding/cli-utils 共享工具 + 类型定义 +``` + +### 核心设计模式 + +| 模式 | 应用 | +|---|---| +| **Command Delegation** | yargs 父命令注册子命令模块,每个子包暴露 `createAsSubcommand()` + `handler()` | +| **Template Method** | 所有子包遵循完全相同的文件结构(main.ts / handlers/ / types/ / index.ts / cli.ts) | +| **Strategy** | injectInfo.json 机制:每个包通过 injectInfo 实现配置差异化 | +| **Observer** | husky + git hooks 事件驱动(pre-commit、pre-push 等触发检测) | +| **Proxy/Adapter** | xPrompts 封装 prompts,透明支持 hijack(AI)和 交互(人类)两种模式 | +| **Pipeline** | create 流程:clone → batchCompile → git optimize → commit | + +## 4. 模块/组件结构(C4 Level 2-3) + +### 统一子包结构 + +每个 `packages//src/` 下有完全一致的文件结构: + +``` +packages//src/ +├── cli.ts # #!/usr/bin/env node 入口,调用 createCommand() +├── main.ts # createCommand() + createAsSubcommand() 导出 +├── index.ts # 统一导出:handler + createAsSubcommand + types +├── handlers/ +│ ├── index.ts # commandCliInfo(子命令列表 + 路由)+ handler(switch-case 分发) +│ └── .ts # 每个子命令:commandCliInfo + handler + getOptions() +├── types/ +│ └── index.ts # SubcommandEnum + 选项类型定义 +└── injectInfo.json # 包元数据(构建时注入) +``` + +**关键文件约定:** +- `main.ts` 的 `createAsSubcommand()` 被 cli 主包导入,作为 yargs `CommandModule` 注册 +- `handlers/index.ts` 导出 `commandCliInfo`(含 describe, version, subcommands, demandCommandCount)和 `handler()`(子命令 switch-case 路由) +- 无 `handler()` 的二层 dispatch——`DC create` 进入 ai 包的 handler,内部 switch `SubcommandEnum` 分发到各子命令 + +#### 默认子命令 + +WHEN 子包希望「不指定子命令时执行默认行为」[MUST] 使用 `packDefaultCommandCliInfo()` 包装目标 handler 的 `commandCliInfo`: + +```typescript +// handlers/index.ts +import { packDefaultCommandCliInfo } from "@done-coding/cli-utils"; + +export const commandCliInfo: Omit = { + subcommands: [ + packDefaultCommandCliInfo(chatCommandCliInfo), // ← $0 兜底 + chatCommandCliInfo, // ← 命名子命令 + ].map(createSubcommand), + demandCommandCount: 1, + // ... +}; +``` + +- `packDefaultCommandCliInfo()` 内部将 `command` 改为 `"$0"`,生成一个仅 yargs 路由使用的副本,不修改原始 `commandCliInfo` +- 原始 `commandCliInfo` 同时保留在 `subcommands` 中,确保 `--help` 仍显示命名子命令 +- handler 文件本身无需任何改动——`command` 保持为 `SubcommandEnum.XXX`,`handlers/index.ts`、`types/index.ts`、`main.ts` 写法不变 +- 参考:`packages/ai/src/handlers/index.ts` + +详细说明:每个子包的架构细节见 `packages//docs/ARCHITECTURE.md`(待创建)。 + +### 依赖关系 + +``` +@done-coding/cli ────────────── 直接依赖所有业务包 ─────────────────┐ + │ │ + ├── create-done-coding ───── 依赖: git, template, utils │ + ├── @done-coding/cli-component 依赖: template, utils │ + ├── @done-coding/cli-config ── 依赖: utils(运行时调用 git 包) │ + ├── @done-coding/cli-extract ─ 依赖: template, utils │ + ├── @done-coding/cli-git ──── 依赖: utils(+ axios) │ + ├── @done-coding/cli-inject ── 依赖: utils │ + ├── @done-coding/cli-publish ─ 依赖: utils(+ semver) │ + ├── @done-coding/cli-template 依赖: utils(+ lodash.template) │ + └── @done-coding/cli-ai ───── 依赖: utils, openai │ + ↓ │ + @done-coding/cli-utils ─────── 无内部依赖 ──────────────────────┘ +``` + +**唯一的跨包运行时调用:** `config` →(运行时通过 yargs 的 `DC git check reverse-merge`)→ `git`。其余包间通信仅通过 npm 依赖 + 编译时导出。 + +### 构建输出 + +每个子包构建产物: +``` +packages// +├── es/ # Vite 构建的 ESM JS(main 入口:es/index.mjs) +├── types/ # vite-plugin-dts 生成的 .d.ts +└── lib/ # (部分包)额外输出 +``` + +## 5. 数据架构 + +### 配置数据流 + +``` +构建时: + src/injectInfo.json + ← @done-coding/cli-inject 的 local:init 脚本写入 + → 编译为 es/injectInfo.json.mjs + → 运行时 import 使用 + +运行时配置(每个子包独立): + .done-coding/ + ├── extract.json5 # DC extract config + ├── inject.json # DC inject config + ├── template.json # DC template config + ├── publish.json # DC publish config + └── git.config.json # DC git config + +全局配置: + ~/.done-coding/config.json # 全局持久化配置(ASSETS_CONFIG_REPO_URL、AI_CONFIG) +``` + +### 关键数据流 + +``` +DC create: + prompts 输入(projectName, template...) + → git clone 模板仓库 + → 读取模板中 .done-coding/ config + → batchCompileHandler(Lodash 模板) + → git 细节优化(分支/URL/history) + → 初始 commit + +DC template: + 环境数据(-e JSON 文件 或 -E JSON 字符串) + + 模板(-i 文件 或 -I 字符串) + → lodash.template 编译 + → 按 -m 模式写入(overwrite/append/replace/return) + +DC extract: + extractInput 定义(源文件 + 匹配规则) + → reg/json-inject/fixed 提取 + → extractOutput 定义(模板 + 输出路径) + → batchCompileHandler 写入 + +DC inject: + keyConfigMap 定义(键名 + 提取方式) + → 从 source JSON 提取值 + → lodash _set 组装对象 + → 写入 inject JSON 文件 +``` + +### MCP/Hijack 数据流 + +``` +父进程(AI agent) + → set env: DONE_CODING_PROCESS_CREATE_BY_HIJACK_PRESET_JSON + → spawn 子进程 + +子进程 CLI + → processIsHijacked() = true + → xPrompts: 跳过交互,从 env 读预设值或 CLI arg 取值 + → console 输出 → hijack 日志文件 + → beforeInputExit → process.exit() +``` + +## 6. 设计原则与约定 + +### 编码约定 + +| 约定 | 说明 | +|---|---| +| ESM only | 所有包 `"type": "module"`,只产出 ESM | +| 路径别名 `@/` | `@/handlers` = `./src/handlers`(Vite alias) | +| Bin 命名 | `DC`(主大写)+ `dc-cli`(备用)+ `done-coding`(品牌),子包用 `dc-` | +| TypeScript strict | 严格模式,完整类型导出到 `types/` | +| Side-effect free | 所有包 `"sideEffects": false` | +| 无循环依赖 | cli → 各子包 → utils(单向) | +| 禁止魔鬼字符串 | 业务关键字(如命令、状态、配置 key)[MUST] 使用枚举值,禁止内联字符串字面量 | +| 禁止魔鬼数字 | 有语义的数值(如索引标记、状态码)[MUST] 定义为具名常量 | +| JSDoc 注释 | 所有 `export` 类型/接口、枚举成员、公共函数 [MUST] 包含 `/** 中文描述 */` | + +### 子包模板一致性 + +新建子包必须通过脚手架模板创建,确保每个包的 `main.ts`、`handlers/`、`types/` 结构完全一致。详见 `packages/ai` 作为最新模板参考。 + +### Child Process Hijack 约定 + +| 约定 | 说明 | +|---|---| +| env 变量名 | `DONE_CODING_PROCESS_CREATE_BY_HIJACK_PRESET_JSON` | +| hijack 检测 | `processIsHijacked()` — 在 `@done-coding/cli-utils` 中定义 | +| hijack 时禁止 syscall | hijack 模式下 [MUST NOT] 调用 `process.exit()`、`execSync` 等 | +| 所有交互必须经 xPrompts | [MUST] 使用 xPrompts 包装 prompts,禁止直接调用 prompts;xPrompts 在 hijack 模式下自动使用预设值 | + +## 7. 架构决策记录(ADR) + +### ADR-1:使用 yargs 而非 commander + +| 项 | 内容 | +|---|---| +| **状态** | `活跃` | +| **决策** | 选择 yargs 作为 CLI 框架 | +| **背景** | 需要支持层级子命令路由、自动 --help/--version、类型安全的选项定义。Commander 在当时版本对类型支持较弱。 | +| **权衡** | yargs bundle 更大但类型定义完整,`createSubcommand`/`createMainCommand` 封装消除了样板代码。 | + +### ADR-2:独立子包版本(Lerna independent mode) + +| 项 | 内容 | +|---|---| +| **状态** | `活跃` | +| **决策** | 每个子包独立 SemVer,不统一版本号 | +| **背景** | 不同子包变更频率不同(如 utils 变更少,create 变更多),统一版本会造成不必要的版本跳跃和依赖更新。 | + +### ADR-3:Vite 构建替代 tsc/rollup + +| 项 | 内容 | +|---|---| +| **状态** | `活跃` | +| **决策** | 使用 Vite + vite-plugin-dts 构建 | +| **背景** | tsc 不支持单文件 ESM 输出;rollup 配置复杂。Vite 提供零配置 ESM 构建 + 并行 dts 生成。 | + +### ADR-4:MCP/Hijack 通过 env 变量而非独立二进制 + +| 项 | 内容 | +|---|---| +| **状态** | `活跃` | +| **决策** | 同一份代码同时服务人类交互和 AI agent 调用,通过 `DONE_CODING_PROCESS_CREATE_BY_HIJACK_PRESET_JSON` 区分模式 | +| **背景** | 避免维护两套逻辑。hijack 模式通过 xPrompts 透明处理交互跳过、日志输出重定向。 | + +### ADR-5:AI 对话使用 openai SDK + OpenAI 兼容协议 + +| 项 | 内容 | +|---|---| +| **状态** | `活跃` | +| **决策** | `@done-coding/cli-ai` 使用 `openai` npm SDK(^4.x)+ SSE 流式 | +| **背景** | 绝大多数模型厂商支持 OpenAI 兼容协议;SDK 提供 `.stream()` 流式调用、完整 TS 类型、baseURL 可改为任意兼容端点。暂不支持 Anthropic Messages API。 | + +## 8. 质量属性与非功能需求 + +| 属性 | 要求 | +|---|---| +| 启动速度 | CLI 无子命令时(`DC`)应在 1s 内显示提示 | +| 跨平台 | Windows / macOS / Linux 行为一致(路径用 `path` 模块、避免 shell 特定语法) | +| 可扩展性 | 新增子包:脚手架创建 → 实现 handlers → cli 注册两行 import,其余零触碰 | +| 错误处理 | yargs 自动处理无效命令;子包 handler 内错误直接 throw(yargs 输出到 stderr,exitCode ≠ 0) | +| 日志 | hijack 模式下输出到日志文件;正常模式 stdout + chalk 美化 | +| 包体积 | 各子包 `files` 字段严格控制为 `es`、`lib`、`types` | + +## 9. 注意事项与常见陷阱 + +### 变更高风险区域 + +| 区域 | 风险 | 说明 | +|---|---|---| +| `@done-coding/cli-utils` 的类型定义 | 高 | `CliInfo`/`SubCliInfo` 类型变更影响所有子包, [MUST] 确保向后兼容 | +| `createAsSubcommand` 函数签名 | 高 | 所有子包的 `main.ts` 依赖此签名注册到 cli 主命令 | +| xPrompts hijack 检测逻辑 | 高 | 修改不当会导致 AI agent 调用卡在交互式 prompt | +| injectInfo.json 格式 | 中 | 所有子包的名称/版本/bin 信息依赖此文件,格式变更需同步更新构建脚本 | +| Child process spawn | 中 | hijack 模式下子进程通信依赖 env 变量, [MUST NOT] 在子进程中调用 `process.exit()` | + +### 常见错误 + +| 错误 | 原因 | 正确做法 | +|---|---|---| +| 在子包 handler 中直接使用 `prompts` | hijack 模式会在交互式 prompt 卡住 | [MUST] 使用 `xPrompts` | +| 修改 utils 的 type 后只构建 utils | 其他包的类型检查引用了旧类型 | pnpm build(所有包)或至少构建依赖链 | +| 在 `handler()` 中调用 `process.exit()` | hijack 模式会杀掉父进程 | throw error 让 yargs 处理 | +| 在子包中 import cli 主包 | 会造成循环依赖 | 子包 [MUST NOT] import cli 包 | +| `npm install` 而非 `pnpm install` | preinstall 脚本 `npx only-allow pnpm` 会拒绝 | [MUST] 使用 pnpm | +| 使用内联字符串作业务判断 | 如 `if (cmd === "/exit")`,分散在多处难维护 | [MUST] 定义枚举,引用枚举值 | +| 使用魔法数字 | 如 `value: -1` 标记"自定义",语义不清 | [MUST] 定义为具名常量 | +| 导出类型缺少 JSDoc | 其他开发者/AI agent 无法理解字段含义 | [MUST] `/** */` 注释每个 `export type`/`enum` 成员 | + +## 10. 技术债务与风险 + +| 债务 | 优先级 | 说明 | +|---|---|---| +| 缺少自动化测试 | 中 | 大部分子包仅有 vitest 配置但无实质性测试用例 | +| create-done-coding 远程模板列表依赖 Gitee | 低 | Gitee 不可用时模板选择不可用,应考虑 fallback 方案 | +| vite 构建产物包含 `#!/usr/bin/env node` 在非 cli 入口文件中 | 低 | 仅 `cli.ts` 应包含 shebang,构建配置需过滤 | +| 部分包 `.npmignore` 可能与 `files` 字段冲突 | 低 | 两个机制都在用,应以 `files` 为准 | + +## 11. 开发工作流 + +### 本地开发 + +```bash +pnpm install # 安装所有依赖(preinstall 强制 pnpm) +pnpm run dev # 所有子包 Vite watch 模式(hotBuild) +pnpm run build # 所有子包构建 +``` + +### 质量门禁 + +| 步骤 | 触发 | 工具 | +|---|---|---| +| 文件命名检查 | pre-commit | ls-lint | +| 代码风格 | pre-commit | ESLint --fix → Prettier --write | +| 提交信息校验 | commit-msg | commitlint | +| 分支合并方向检查 | 多个 git hooks | DC git hooks(reverse-merge) | + +### 发布流程 + +```bash +# alpha 预发布 +npx lerna publish prerelease --dist-tag alpha --preid alpha + +# 正式发布 +pnpm run push # = lerna publish + → postpush: node ./scripts/postpush.mjs +``` + +### 新增子包 + +1. 通过脚手架模板创建 `packages//`(含统一文件结构) +2. 在 `SubcommandEnum` 中定义子命令 +3. 在 `handlers/index.ts` 中实现 switch-case 路由 +4. 在 `packages/cli/package.json` 添加 workspace 依赖 +5. 在 `packages/cli/src/index.ts` 添加 `createAsSubcommand` + `handler` 导出 +6. 在 `packages/cli/src/main.ts` 的 `subcommands` 数组中注册 + +## 12. 横切关注点 + +### 日志/输出 + +- 正常模式:`outputConsole`(chalk 封装):`.info()`、`.stage()`、`.skip()`、`.success()`、`.error()`、`.warn()`、`.debug()` +- hijack 模式:输出重定向到日志文件 +- `debug` 库用于开发调式(`DEBUG=done-coding:`) + +### 错误处理 + +- yargs 框架层:无效命令自动 `.strict()` 拦截,输出 usage 提示 → exitCode 1 +- handler 层:错误直接 throw,yargs 捕获并输出到 stderr +- hijack 层:[MUST NOT] `process.exit()`——改为 throw error +- publish rollback:发布失败时 `git reset` + 删除 tag + +### 认证/安全 + +- npm publish 认证:依赖用户本地 `~/.npmrc`(`npm login` 结果) +- Git clone 认证:依赖用户本地 git credential / SSH key +- AI API Key:持久化到 `~/.done-coding/config.json` 的 `AI_CONFIG` 字段(含 model、apiKey、baseUrl) +- AES 加密:`@done-coding/cli-utils` 提供 `encryptAES`/`decryptAES`(用于配置中的敏感值) + +### 包间通信模式 + +| 通信方式 | 使用场景 | +|---|---| +| npm workspace 依赖 | 所有子包 depend on `@done-coding/cli-utils` | +| yargs 子命令注册 | cli 主包注册所有子包的 `createAsSubcommand()` | +| 运行时 child_process | `config` 调用 `git check reverse-merge`(唯一跨包运行时调用) | +| 构建时 injectInfo | `@done-coding/cli-inject` 在构建时将元数据写入各包的 `injectInfo.json` | diff --git a/docs/specs/2026-04-26-ai-chat-flow/design.md b/docs/specs/2026-04-26-ai-chat-flow/design.md new file mode 100644 index 0000000..b4b4cab --- /dev/null +++ b/docs/specs/2026-04-26-ai-chat-flow/design.md @@ -0,0 +1,156 @@ +# 技术设计文档:AI 对话流程串通 + +> 状态:已审核通过 +> 任务等级:Complex +> 日期:2026-04-26 + +## 变更范围 + +- **Direct Targets**:`packages/ai/src/handlers/chat.ts`(新建)、`packages/ai/src/services/api-client.ts`(新建)、`packages/ai/src/services/model-presets.ts`(新建)、`packages/ai/src/types/index.ts`(扩)、`packages/ai/src/handlers/index.ts`(扩)、`packages/ai/package.json`(扩)、`packages/utils/src/cli-config.ts`(扩)、`packages/cli/src/main.ts`(改) +- **Collateral Reads**:`packages/utils/src/cli.ts`、`packages/utils/src/env-config.ts`、`packages/utils/src/file-operate.ts`、`packages/cli/src/index.ts` +- **Out-of-Scope**:`packages/ai/src/handlers/test.ts`、其他所有子包 + +## 架构决策 + +### 方案选择 + +采用方案 A:AI 逻辑全在 `packages/ai`,cli 只做入口路由。遵循现有分层架构。 + +### ADR: 使用 openai npm SDK 而非自建 fetch + +| 项 | 内容 | +|---|---| +| **决策** | 引入 `openai` npm 包(^4.x)作为 AI API 客户端 | +| **背景** | 预设模型全部兼容 OpenAI 协议,SDK 提供 `.stream()` 一行流式、完整 TypeScript 类型、baseURL 可改为任意兼容端点 | +| **权衡** | 增加一个依赖 vs 自建 SSE parser。命令签名更简洁,维护成本更低 | + +## 关键技术点 + +### 1. 全局配置类型升级 + +`packages/utils/src/cli-config.ts`: + +```typescript +// DoneCodingCliGlobalConfig 从统一 string 改为每个 key 各自定义值类型 +export type DoneCodingCliGlobalConfig = { + [DoneCodingCliGlobalConfigKeyEnum.ASSETS_CONFIG_REPO_URL]: string; + [DoneCodingCliGlobalConfigKeyEnum.AI_CONFIG]: AiConfig; +}; + +export type AiConfig = { + model: string; + apiKey: string; + baseUrl: string; +}; +``` + +`getGlobalConfig()` 函数需适配新类型——每个 key 的默认值类型不再统一。 + +### 2. API 客户端 + +`packages/ai/src/services/api-client.ts`: + +- 使用 `openai` SDK:`new OpenAI({ apiKey, baseURL })` +- 流式调用:`client.chat.completions.create({ model, messages, stream: true })` +- `for await (const chunk of stream)` 逐 token 回调 `onToken(content)` +- 网络/API 错误由调用方 catch 并友好提示 + +### 3. 模型预设(两级结构) + +`packages/ai/src/services/model-presets.ts`: + +```typescript +// 两级结构:ProviderPreset(服务商) → ModelInfo(模型) +export type ProviderPreset = { + label: string; // 服务商名称 + baseUrl: string; // API 地址 + models: ModelInfo[]; // 该服务商下的模型列表 +}; + +export const PROVIDER_PRESETS = [ + { label: "DeepSeek", baseUrl: "https://api.deepseek.com", + models: [ + { model: "deepseek-v4-flash", label: "DeepSeek V4 Flash" }, + { model: "deepseek-v4-pro", label: "DeepSeek V4 Pro" }, + { model: "deepseek-chat", label: "DeepSeek V3 (弃用标注)" }, + { model: "deepseek-reasoner", label: "DeepSeek R1 (弃用标注)" }, + ] + }, + { label: "通义千问", ... }, + { label: "Kimi", ... }, + { label: "Groq", ... }, +]; +``` + +选择流程:选服务商 → 选该服务商下的模型。自定义服务商直接输入 model + baseUrl。 + +### 4. Chat Handler 结构 + +`chat.ts` 拆分为三个独立函数: + +- `selectProviderAndModel()` — 选服务商 → 选模型,返回 `{ model, baseUrl }`(不含 key) +- `selectModelForProvider(provider)` — 在当前服务商下选模型 +- `firstTimeSetup()` — 调用 `selectProviderAndModel()` + 输入 API Key + +其中 `ChatKeywordEnum` 新增 `PROVIDER = "/provider"`: +- `/provider`:调用 `selectProviderAndModel()`,保留 API Key +- `/model`:根据当前 `baseUrl` 匹配服务商 → 直接选模型;自定义 baseUrl 则走完整流程 + +注册方式遵循 TECH_SNAPSHOT 子包标准模式。`SubcommandEnum` 仅保留 `CHAT`(`TEST` 已移除)。 + +### 5. CLI 入口路由 + +`packages/cli/src/main.ts` 的 `handler()` 方法: + +``` +无子命令 → xPrompts "是否唤起 AI 对话?" + → y → 调用 aiHandler(SubcommandEnum.CHAT, argv) + → n → 输出 --help +``` + +`createChat` 假实现删除。 + +## 数据流 + +### 首次使用 + +``` +DC → y → getGlobalConfig() → AI_CONFIG 不存在 + → 展示 MODEL_PRESETS → 用户选模型 + → xPrompts 输入 API Key + → writeJsonFileAsync(configPath, { ...existing, AI_CONFIG: { model, apiKey, baseUrl } }) + → 进入对话循环 +``` + +### 已有配置 + +``` +DC → y → getGlobalConfig() → AI_CONFIG 存在 + → 提示 "使用 {model},输入对话内容" → 进入对话循环 +``` + +### 对话循环 + +``` +loop: + xPrompts({ type: "text" }) → 用户输入 + → 空输入 → continue + → /exit → return + → /provider → selectProviderAndModel() → update config → continue + → /model → 当前服务商匹配 → selectModelForProvider() → update config + → 匹配不到 → selectProviderAndModel() → update config → continue + → /clear → 清屏 → continue + → 其他 → streamChat(config, input) → 逐 token 输出 → 换行 → continue + → 401/AuthenticationError → firstTimeSetup() 重新输入 key → continue + → 其他错误 → 提示 → continue +``` + +## 注意事项 / 已知风险 + +| 风险 | 应对 | +|---|---| +| `DoneCodingCliGlobalConfig` 类型变更影响 `getGlobalConfig` 调用方 | 仅 config 模块的一个函数受影响,需确保 ASSETS_CONFIG_REPO_URL 仍正常工作 | +| `openai` SDK 的 baseURL 拼接 | 用户输入是 `https://api.deepseek.com`,SDK 自动加 `/v1`,需测试各模型的实际行为 | +| 401 认证失败 | 自动重新引导输入 API Key,不退出循环 | +| stream 中断 | 捕获网络异常,提示"连接中断",不退出循环 | +| hijack 兼容 | chatHandler 用 xPrompts 做输入,天然兼容 | diff --git a/docs/specs/2026-04-26-ai-chat-flow/requirements.md b/docs/specs/2026-04-26-ai-chat-flow/requirements.md new file mode 100644 index 0000000..6becbf7 --- /dev/null +++ b/docs/specs/2026-04-26-ai-chat-flow/requirements.md @@ -0,0 +1,74 @@ +# 需求文档:AI 对话流程串通 + +> 状态:已审核通过 +> 任务等级:Complex +> 日期:2026-04-26 +> 参与角色:PM + 架构师 + 全栈开发专家 + 测试专家 + +## 背景 + +`@done-coding/cli-ai` 包已创建骨架(main.ts/handlers/types)。主 CLI 的无子命令入口原先为 `createChat` 假实现(只回显用户输入)。需接入真实 AI 对话能力:选服务商 → 选模型 → 填 API Key → SSE 流式对话。 + +## 功能需求 + +### REQ-1: 模型选择(两级:服务商 → 模型) +WHEN 用户首次使用 AI 对话,或执行 `/provider`、`/model` 命令 +THE SYSTEM SHALL 先展示预设服务商列表(DeepSeek / 通义千问 / Kimi / Groq + 自定义),选定服务商后展示该服务商下的模型列表供选择 +- 验收标准:4 个预设服务商,每个至少 2 个模型;"自定义"服务商可输入 model + baseUrl +- DeepSeek 模型:deepseek-v4-flash / deepseek-v4-pro / deepseek-chat(弃用标注)/ deepseek-reasoner(弃用标注) + +### REQ-2: API Key 配置 +WHEN 用户首次使用 AI 对话且 `~/.done-coding/config.json` 中无 AI_CONFIG +THE SYSTEM SHALL 交互式提示用户输入 API Key,与模型选择结果一起持久化 +- 验收标准:key 写入 `~/.done-coding/config.json` 的 `AI_CONFIG.apiKey` 字段;后续对话自动读取,无需重复输入 + +### REQ-3: 配置持久化 +WHEN AI_CONFIG 已存在于全局配置文件中 +THE SYSTEM SHALL 直接读取已保存的配置进入对话,跳过模型选择和 key 输入 +- 验收标准:第二次 `DC` 对话无需重新配置 + +### REQ-4: SSE 流式对话 +WHEN 用户输入非内置命令的文本 +THE SYSTEM SHALL 通过 OpenAI 兼容协议发送请求(使用 `openai` npm SDK),并以 SSE 流式逐 token 输出到终端 +- 验收标准:token 无卡顿连续输出;流结束时换行等待下一轮输入 + +### REQ-5: 内置命令 +WHEN 用户输入 `/exit`、`/provider`、`/model`、`/clear` 之一 +THE SYSTEM SHALL 执行对应行为: +- `/exit`:结束对话 +- `/provider`:重新选择服务商 → 自动唤起模型选择(保留 API Key) +- `/model`:在当前服务商下切换模型(若为自定义 baseUrl 则走完整服务商+模型选择) +- `/clear`:清屏 +- 验收标准:四个命令均可正常执行且不影响已保存配置 + +### REQ-6: 入口路由 +WHEN 用户执行 `DC` 且无子命令 +THE SYSTEM SHALL 提问"是否唤起 AI 对话?",用户选 y 进入 AI 对话,选 n 输出 --help 内容 +- 验收标准:y/n 分支正确;`createChat` 假实现被删除 + +### REQ-7: DC ai 子命令 +WHEN 用户执行 `DC ai` 或 `DC ai chat` +THE SYSTEM SHALL 注册 chat 为 ai 子包的唯一子命令,直接进入 AI 对话 +- 验收标准:`DC ai` 可进入对话;示例性质的 test 命令已移除 + +## 边界情况和约束 + +- 网络错误时友好提示,不退出对话循环 +- API 返回 401 时自动重新引导用户输入 API Key(不退出对话循环) +- 其他 API 错误(403/429/500 等)时输出错误信息到终端,继续对话循环 +- 空输入跳过,不发送 API 请求 +- hijack 模式下 xPrompts 自动处理,不阻塞 AI agent +- 暂不支持多轮对话上下文(每次请求独立) +- Anthropic 模型暂不支持(用户选择时说明) + +## 需求确认记录 + +| REQ | 确认 | +|---|---| +| REQ-1 | ✓ | +| REQ-2 | ✓ | +| REQ-3 | ✓ | +| REQ-4 | ✓ | +| REQ-5 | ✓ | +| REQ-6 | ✓ | +| REQ-7 | ✓ | diff --git a/docs/specs/2026-04-26-ai-chat-flow/tasks.md b/docs/specs/2026-04-26-ai-chat-flow/tasks.md new file mode 100644 index 0000000..e112456 --- /dev/null +++ b/docs/specs/2026-04-26-ai-chat-flow/tasks.md @@ -0,0 +1,673 @@ +# AI 对话流程串通 — 实施计划 + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** 实现 `DC` 无子命令 → 选模型 → 填 key → SSE 流式 AI 对话的完整链路 + +**Architecture:** 方案 A — AI 逻辑全在 `packages/ai`,cli 只做入口路由。使用 `openai` SDK 抹平各模型 API 差异。配置持久化到 `~/.done-coding/config.json`。 + +**Tech Stack:** TypeScript, yargs, openai ^4.x, Vite, pnpm workspace + +--- + +### Task 1: utils 全局配置类型升级 + +**Files:** +- Modify: `packages/utils/src/cli-config.ts` + +- [ ] **Step 1: 新增 AiConfig 类型 + 升级 DoneCodingCliGlobalConfig + 导出 getGlobalConfigFilePath** + +将文件中的类型定义替换为: + +```typescript +/** AI 配置 */ +export type AiConfig = { + /** 模型名称,如 "deepseek-chat" */ + model: string; + /** API Key */ + apiKey: string; + /** API Base URL,如 "https://api.deepseek.com" */ + baseUrl: string; +}; +``` + +`DoneCodingCliGlobalConfigKeyEnum` 新增: + +```typescript +export enum DoneCodingCliGlobalConfigKeyEnum { + /** 资产配置仓库 */ + ASSETS_CONFIG_REPO_URL = "ASSETS_CONFIG_REPO_URL", + /** AI 对话配置 */ + AI_CONFIG = "AI_CONFIG", +} +``` + +`DoneCodingCliGlobalConfig` 类型改为: + +```typescript +/** done-coding-cli 全局配置 */ +export type DoneCodingCliGlobalConfig = { + [DoneCodingCliGlobalConfigKeyEnum.ASSETS_CONFIG_REPO_URL]: string; + [DoneCodingCliGlobalConfigKeyEnum.AI_CONFIG]?: AiConfig; +}; +``` + +`getGlobalConfig` 函数替换默认值部分,适配新类型: + +```typescript +const getGlobalConfig = async (): Promise => { + const filePath = getGlobalConfigJsonFilePath(); + + const config: DoneCodingCliGlobalConfig = { + [DoneCodingCliGlobalConfigKeyEnum.ASSETS_CONFIG_REPO_URL]: + ASSETS_CONFIG_REPO_URL_DEFAULT, + [DoneCodingCliGlobalConfigKeyEnum.AI_CONFIG]: undefined, + }; + try { + if (await assetIsExitsAsync(filePath)) { + const fileConfig = await readJsonFileAsync>( + filePath, + {}, + ); + Object.entries(fileConfig).forEach(([key, value]) => { + (config as any)[key] = value; + }); + } + } catch (error) {} + + return config; +}; +``` + +将 `getGlobalConfigJsonFilePath` 从 `const` 改为 `export const`: + +```typescript +/** 【全局】获取全局配置文件路径 */ +export const getGlobalConfigFilePath = () => { + return path.resolve(homedir(), DONE_CODING_CLI_GLOBAL_CONFIG_RELATIVE_PATH); +}; +``` + +同时更新函数内部引用 `getGlobalConfigJsonFilePath` → `getGlobalConfigFilePath`。 + +- [ ] **Step 2: Commit** + +```bash +git add packages/utils/src/cli-config.ts +git commit -m "feat(utils): 新增 AI_CONFIG 配置键和 AiConfig 类型,升级全局配置类型为按 key 定义值类型" +``` + +--- + +### Task 2: ai 包模型预设列表 + 关键字枚举 + +**Files:** +- Create: `packages/ai/src/services/model-presets.ts` +- Modify: `packages/ai/src/types/index.ts` + +- [ ] **Step 1: 新增 ChatKeywordEnum 到 types** + +`packages/ai/src/types/index.ts`: + +```typescript +/** 子命令枚举 */ +export enum SubcommandEnum { + /** 测试命令 */ + TEST = "test", + /** AI 对话 */ + CHAT = "chat", +} + +/** 对话内置关键字 */ +export enum ChatKeywordEnum { + /** 退出对话 */ + EXIT = "/exit", + /** 切换模型 */ + MODEL = "/model", + /** 清屏 */ + CLEAR = "/clear", +} + +export interface TestOptions { + /** 测试选项 */ + xx: string; +} +``` + +- [ ] **Step 2: 创建模型预设服务** + +`packages/ai/src/services/model-presets.ts`: + +```typescript +import type { AiConfig } from "@done-coding/cli-utils"; + +/** 预设模型条目(继承 AiConfig 配置字段,附加展示标签) */ +export type ModelPreset = { + /** 用户可见的展示名称 */ + label: string; +} & AiConfig; + +/** 自定义模型选项的索引值 */ +export const CUSTOM_PRESET_INDEX = -1; + +/** 自定义模型的展示标签文本 */ +export const CUSTOM_PRESET_LABEL = "自定义..."; + +/** 预设模型列表(不含 apiKey,用户需自行输入) */ +export const MODEL_PRESETS: ModelPreset[] = [ + { + label: "DeepSeek V3", + model: "deepseek-chat", + apiKey: "", + baseUrl: "https://api.deepseek.com", + }, + { + label: "通义千问", + model: "qwen-turbo", + apiKey: "", + baseUrl: "https://dashscope.aliyuncs.com/compatible-mode", + }, + { + label: "Kimi", + model: "moonshot-v1-8k", + apiKey: "", + baseUrl: "https://api.moonshot.cn", + }, + { + label: "Groq", + model: "llama-3.3-70b", + apiKey: "", + baseUrl: "https://api.groq.com/openai", + }, +]; +``` + +- [ ] **Step 3: Commit** + +```bash +git add packages/ai/src/types/index.ts packages/ai/src/services/model-presets.ts +git commit -m "feat(ai): 添加 ChatKeywordEnum 枚举和模型预设列表服务" +``` + +--- + +### Task 3: ai 包 API 客户端 + +**Files:** +- Create: `packages/ai/src/services/api-client.ts` + +- [ ] **Step 1: 创建流式 API 客户端** + +```typescript +import OpenAI from "openai"; +import type { AiConfig } from "@done-coding/cli-utils"; + +/** 流式聊天请求参数 */ +export type StreamChatParams = { + /** AI 配置 */ + config: AiConfig; + /** 用户消息 */ + message: string; + /** token 回调 */ + onToken: (token: string) => void; +}; + +/** SSE 流式聊天:逐 token 回调 onToken */ +export const streamChat = async (params: StreamChatParams): Promise => { + const { config, message, onToken } = params; + + const client = new OpenAI({ + apiKey: config.apiKey, + baseURL: config.baseUrl.endsWith("/v1") + ? config.baseUrl + : config.baseUrl + "/v1", + }); + + const stream = await client.chat.completions.create({ + model: config.model, + messages: [{ role: "user", content: message }], + stream: true, + }); + + for await (const chunk of stream) { + const content = chunk.choices[0]?.delta?.content; + if (content) { + onToken(content); + } + } +}; +``` + +- [ ] **Step 2: Commit** + +```bash +git add packages/ai/src/services/api-client.ts +git commit -m "feat(ai): 添加基于 openai SDK 的 SSE 流式 API 客户端" +``` + +--- + +### Task 4: ai 包 chat handler + handlers 路由 + +**Files:** +- Create: `packages/ai/src/handlers/chat.ts` +- Modify: `packages/ai/src/handlers/index.ts` + +- [ ] **Step 1: 创建 chat handler** + +`packages/ai/src/handlers/chat.ts`: + +```typescript +import type { SubCliInfo } from "@done-coding/cli-utils"; +import { + outputConsole, + xPrompts, + readJsonFileAsync, + getGlobalConfigFilePath, + DoneCodingCliGlobalConfigKeyEnum, +} from "@done-coding/cli-utils"; +import type { DoneCodingCliGlobalConfig, AiConfig } from "@done-coding/cli-utils"; +import { writeFileSync, existsSync, mkdirSync } from "node:fs"; +import { dirname } from "node:path"; +import { SubcommandEnum, ChatKeywordEnum } from "@/types"; +import { + MODEL_PRESETS, + CUSTOM_PRESET_INDEX, + CUSTOM_PRESET_LABEL, +} from "@/services/model-presets"; +import { streamChat } from "@/services/api-client"; + +/** + * 读取全局配置文件 + * @returns 全局配置对象,文件不存在时返回空对象 + */ +const readGlobalConfig = async (): Promise => { + try { + return await readJsonFileAsync( + getGlobalConfigFilePath(), + {} as DoneCodingCliGlobalConfig, + ); + } catch { + return {} as DoneCodingCliGlobalConfig; + } +}; + +/** + * 写入全局配置文件(目录不存在时自动创建) + * @param config 全局配置对象 + */ +const writeGlobalConfig = async (config: DoneCodingCliGlobalConfig) => { + const filePath = getGlobalConfigFilePath(); + const dir = dirname(filePath); + if (!existsSync(dir)) { + mkdirSync(dir, { recursive: true }); + } + writeFileSync(filePath, JSON.stringify(config, null, 2), "utf-8"); +}; + +/** + * 首次引导流程:展示预设模型列表 → 用户选择(含自定义) → 输入 API Key + * @returns AiConfig 配置对象,用户取消时返回 null + */ +const firstTimeSetup = async (): Promise => { + const choices = MODEL_PRESETS.map((p, i) => ({ + title: `${p.label} (${p.baseUrl})`, + value: i, + })); + choices.push({ title: CUSTOM_PRESET_LABEL, value: CUSTOM_PRESET_INDEX }); + + const { modelIndex } = await xPrompts({ + type: "select", + name: "modelIndex", + message: "选择大模型", + choices, + }); + + let model: string; + let baseUrl: string; + + if (modelIndex === CUSTOM_PRESET_INDEX) { + const custom = await xPrompts([ + { type: "text", name: "model", message: "输入模型名" }, + { type: "text", name: "baseUrl", message: "输入 API Base URL" }, + ]); + model = custom.model; + baseUrl = custom.baseUrl; + } else { + model = MODEL_PRESETS[modelIndex].model; + baseUrl = MODEL_PRESETS[modelIndex].baseUrl; + } + + const { apiKey } = await xPrompts({ + type: "password", + name: "apiKey", + message: "输入 API Key", + validate: (v: string) => + v?.trim().length > 0 ? true : "API Key 不能为空", + }); + + return { model, apiKey, baseUrl }; +}; + +/** + * AI 对话主处理器 + * 流程:读取配置 → 首次引导(如需) → 对话循环(xPrompts 交互 + SSE 流式响应) + */ +const chatHandler = async () => { + let config = await readGlobalConfig(); + let aiConfig = config[DoneCodingCliGlobalConfigKeyEnum.AI_CONFIG]; + + // 首次配置 + if (!aiConfig?.apiKey) { + outputConsole.log("首次使用需配置模型和 API Key\n"); + const result = await firstTimeSetup(); + if (!result) return; + + aiConfig = result; + config[DoneCodingCliGlobalConfigKeyEnum.AI_CONFIG] = aiConfig; + await writeGlobalConfig(config); + outputConsole.log(""); + } + + outputConsole.log( + `模型: ${aiConfig.model} | 输入消息开始对话 (${ChatKeywordEnum.EXIT} 退出, ${ChatKeywordEnum.MODEL} 切换模型, ${ChatKeywordEnum.CLEAR} 清屏)\n`, + ); + + // 对话循环 + while (true) { + const { input } = await xPrompts({ + type: "text", + name: "input", + message: "", + validate: () => true, + }); + + const trimmed = (input as string)?.trim(); + + if (!trimmed) continue; + + if (trimmed === ChatKeywordEnum.EXIT) { + outputConsole.log("对话结束"); + return; + } + + if (trimmed === ChatKeywordEnum.MODEL) { + const result = await firstTimeSetup(); + if (result) { + aiConfig = result; + config[DoneCodingCliGlobalConfigKeyEnum.AI_CONFIG] = aiConfig; + await writeGlobalConfig(config); + outputConsole.log(`已切换至 ${aiConfig.model}\n`); + } + continue; + } + + if (trimmed === ChatKeywordEnum.CLEAR) { + process.stdout.write("\x1b[2J\x1b[0f"); + continue; + } + + // 发送 AI 请求 + outputConsole.stage("思考中..."); + try { + await streamChat({ + config: aiConfig, + message: trimmed, + onToken: (token) => process.stdout.write(token), + }); + process.stdout.write("\n"); + } catch (error: any) { + outputConsole.error(`请求失败: ${error?.message || error}`); + } + } +}; + +/** yargs 子命令注册信息 */ +export const commandCliInfo: SubCliInfo = { + command: SubcommandEnum.CHAT, + describe: "AI 对话", + handler: chatHandler as SubCliInfo["handler"], +}; + +export const handler = chatHandler; +``` + +- [ ] **Step 2: 注册 chat 到 handlers/index.ts** + +`packages/ai/src/handlers/index.ts`: + +```typescript +import { + handler as testHandler, + commandCliInfo as testCommandCliInfo, +} from "./test"; +import { + handler as chatHandler, + commandCliInfo as chatCommandCliInfo, +} from "./chat"; +import injectInfo from "@/injectInfo.json"; +import { SubcommandEnum } from "@/types"; +import { + createSubcommand, + getRootScriptName, + type CliHandlerArgv, + type CliInfo, +} from "@done-coding/cli-utils"; + +export { testHandler, testCommandCliInfo, chatHandler, chatCommandCliInfo }; + +/** 导出供外部 export使用, cli内部不会通过改方法调用各子命令方法 */ +export const handler = async ( + command: SubcommandEnum, + argv: CliHandlerArgv, +) => { + switch (command) { + case SubcommandEnum.TEST: { + return testHandler(argv); + } + case SubcommandEnum.CHAT: { + return chatHandler(argv); + } + default: { + throw new Error(`不支持的命令 ${command}`); + } + } +}; + +const { version, description: describe } = injectInfo; + +export const commandCliInfo: Omit = { + describe, + version, + subcommands: [testCommandCliInfo, chatCommandCliInfo].map(createSubcommand), + demandCommandCount: 1, + rootScriptName: getRootScriptName({ packageJson: injectInfo }), +}; +``` + +- [ ] **Step 3: Commit** + +```bash +git add packages/ai/src/handlers/chat.ts packages/ai/src/handlers/index.ts +git commit -m "feat(ai): 新增 chat 子命令 — 选模型/填 key/SSE 流式对话" +``` + +--- + +### Task 5: ai 包添加 openai 依赖 + +**Files:** +- Modify: `packages/ai/package.json` + +- [ ] **Step 1: 添加依赖 + 导出新模块** + +`packages/ai/package.json` 的 `dependencies` 中新增: + +```json +"dependencies": { + "@done-coding/cli-utils": "workspace:0.8.4", + "openai": "^4.77.0" +} +``` + +- [ ] **Step 2: 安装依赖** + +```bash +cd /Users/supengfei/Documents/code/project/done-coding-cli && pnpm install +``` + +- [ ] **Step 3: Commit** + +```bash +git add packages/ai/package.json pnpm-lock.yaml +git commit -m "chore(ai): 添加 openai SDK 依赖" +``` + +--- + +### Task 6: cli 入口路由替换 createChat + +**Files:** +- Modify: `packages/cli/src/main.ts` +- Modify: `packages/cli/src/index.ts` + +- [ ] **Step 1: 删除 createChat,替换为 AI 入口路由** + +删除 `chalk` import(不再需要),删除整个 `createChat` 函数,将 `handler()` 替换为: + +```typescript +import { createAsSubcommand as createInjectCommand } from "@done-coding/cli-inject"; +import { createAsSubcommand as createExtractCommand } from "@done-coding/cli-extract"; +import { createAsSubcommand as createGitCommand } from "@done-coding/cli-git"; +import { createAsSubcommand as createCreateCommand } from "create-done-coding"; +import { createAsSubcommand as createPublishCommand } from "@done-coding/cli-publish"; +import { createAsSubcommand as createTemplateCommand } from "@done-coding/cli-template"; +import { createAsSubcommand as createComponentCommand } from "@done-coding/cli-component"; +import { createAsSubcommand as createConfigCommand } from "@done-coding/cli-config"; +import { + createAsSubcommand as createAiCommand, + handler as aiHandler, +} from "@done-coding/cli-ai"; +import { SubcommandEnum as AiSubcommandEnum } from "@done-coding/cli-ai"; +import injectInfo from "@/injectInfo.json"; +import type { CliInfo } from "@done-coding/cli-utils"; +import { + createMainCommand, + getRootScriptName, + execSyncHijack, + xPrompts, +} from "@done-coding/cli-utils"; + +const { version, description: describe } = injectInfo; + +const commandCliInfo: CliInfo = { + usage: `$0 [options]`, + describe, + version, + subcommands: [ + createGitCommand(), + createCreateCommand(), + createInjectCommand(), + createExtractCommand(), + createPublishCommand(), + createTemplateCommand(), + createComponentCommand(), + createConfigCommand(), + createAiCommand(), + ], + demandCommandCount: 0, + rootScriptName: getRootScriptName({ packageJson: injectInfo }), + async handler() { + const { shouldChat } = await xPrompts({ + type: "confirm", + name: "shouldChat", + message: "是否唤起 AI 对话?", + initial: true, + }); + + if (shouldChat) { + await aiHandler(AiSubcommandEnum.CHAT, {}); + } else { + execSyncHijack(`node ${process.argv[1]} --help`, { + stdio: "inherit", + }); + } + }, +}; + +/** 作为主命令创建 */ +export const createCommand = async () => { + return createMainCommand(commandCliInfo); +}; +``` + +- [ ] **Step 2: 更新 cli/src/index.ts 导出 SubcommandEnum** + +`packages/cli/src/index.ts` 中的 ai 导出需新增 `SubcommandEnum`: + +```typescript +export { + createAsSubcommand as createAiCommand, + handler as aiHandler, + SubcommandEnum as AiSubcommandEnum, +} from "@done-coding/cli-ai"; +``` + +- [ ] **Step 3: Commit** + +```bash +git add packages/cli/src/main.ts packages/cli/src/index.ts +git commit -m "feat(cli): 替换 createChat 假实现为 AI 对话入口路由" +``` + +--- + +### Task 7: 构建与验证 + +- [ ] **Step 1: 构建所有包** + +```bash +cd /Users/supengfei/Documents/code/project/done-coding-cli && pnpm run build +``` + +Expected: 所有包构建成功,无 TypeScript 错误。 + +- [ ] **Step 2: 验证 ai 包 CLI 入口可用** + +```bash +node packages/ai/es/cli.mjs --help +``` + +Expected: 输出中包含 `chat AI 对话` 子命令。 + +- [ ] **Step 3: 验证主 CLI 入口可用** + +```bash +node packages/cli/es/cli.mjs --help +``` + +Expected: 输出包含 `ai` 子命令;无子命令时显示 `是否唤起 AI 对话?` 提示(需要实际终端才能测试交互,这里仅验证不报错)。 + +- [ ] **Step 4: Commit(如有 lint 自动修复)** + +```bash +git status +# 如有lint-staged自动修复的文件,add并commit +``` + +--- + +--- +## 变更记录 + +> 以下变更在实施过程中根据用户反馈产生,已同步更新 requirements.md 和 design.md。 + +| # | 日期 | 变更 | 影响范围 | +|---|---|---|---| +| 1 | 2026-04-26 | 模型选择从一级改为两级(服务商 → 模型) | model-presets.ts, chat.ts | +| 2 | 2026-04-26 | 新增 `/provider` 关键字(选服务商+模型,保留 key) | types/index.ts, chat.ts | +| 3 | 2026-04-26 | `/model` 改为在当前服务商下切换模型 | chat.ts | +| 4 | 2026-04-26 | 移除示例性质 test 命令及相关类型 | test.ts, types/index.ts, handlers/index.ts | +| 5 | 2026-04-26 | 401 错误时重新引导输入 API Key(不退出循环) | chat.ts | +| 6 | 2026-04-26 | `outputConsole.log` → `outputConsole.info`(原方法不存在) | chat.ts | +| 7 | 2026-04-26 | `TS18048` aiConfig 可能 undefined + ESLint 类型断言警告修复 | chat.ts | diff --git a/done-coding-cli.code-workspace b/done-coding-cli.code-workspace index b3b0674..55cecd2 100644 --- a/done-coding-cli.code-workspace +++ b/done-coding-cli.code-workspace @@ -40,6 +40,10 @@ "name": "config", "path": "packages/config", }, + { + "name": "ai", + "path": "packages/ai", + }, { "name": "cli", "path": "packages/cli", @@ -50,19 +54,6 @@ "files.encoding": "utf8", "editor.tabSize": 2, "editor.formatOnSave": true, - "fileheader.configObj": { - "autoAdd": true, - "autoUpdateOnSave": true, - "wideSame": true, - "prohibitAutoAdd": ["json", "md", "jsonc", "xml", "shellscript"], - }, - "fileheader.customMade": { - "Description": "", - "Author": "git config user.name", - "Date": "Do not edit", - "LastEditors": "git config user.name", - "LastEditTime": "Do not edit", - }, "cSpell.ignorePaths": [ "**", // 先忽略所有 @@ -119,7 +110,6 @@ }, "extensions": { "recommendations": [ - "OBKoro1.korofileheader", "redhat.vscode-xml", "foxundermoon.shell-format", "streetsidesoftware.code-spell-checker", diff --git a/package.json b/package.json index a8c16ca..7475714 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,7 @@ "prepare": "husky install", "postinstall": "prettier --write pnpm-lock.yaml", "push": "lerna publish", - "postpush": "node ./scripts/postpush.mjs", - "log": "conventional-changelog -p angular -i CHANGELOG.md -s --release-count 0" + "postpush": "node ./scripts/postpush.mjs" }, "repository": { "type": "git", @@ -27,8 +26,6 @@ "@types/node": "^18.19.4", "@typescript-eslint/eslint-plugin": "^7.7.0", "@typescript-eslint/parser": "^7.7.0", - "conventional-changelog": "^5.1.0", - "conventional-changelog-cli": "^4.1.0", "eslint": "^8.49.0", "eslint-config-alloy": "^5.1.2", "eslint-plugin-import": "^2.29.1", diff --git a/packages/ai/.gitignore b/packages/ai/.gitignore new file mode 100644 index 0000000..5ebd591 --- /dev/null +++ b/packages/ai/.gitignore @@ -0,0 +1,7 @@ +node_modules +/src/injectInfo.json + +/lib +/es +/types +/coverage diff --git a/packages/ai/.npmignore b/packages/ai/.npmignore new file mode 100644 index 0000000..6a530e7 --- /dev/null +++ b/packages/ai/.npmignore @@ -0,0 +1,4 @@ +tsconfig.json +/src +*.md +!README.md \ No newline at end of file diff --git a/packages/ai/README.md b/packages/ai/README.md new file mode 100644 index 0000000..93aea36 --- /dev/null +++ b/packages/ai/README.md @@ -0,0 +1,220 @@ +# @done-coding/cli-ai + +AI 对话命令行工具 - 在终端中与 AI 大模型进行流式对话 + +[![npm version](https://badge.fury.io/js/@done-coding%2Fcli-ai.svg)](https://www.npmjs.com/package/@done-coding/cli-ai) +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) + +## 安装 + +### 独立安装 + +```bash +npm install @done-coding/cli-ai +# 或 +pnpm add @done-coding/cli-ai +``` + +### 作为 done-coding CLI 的一部分 + +```bash +npm install -g @done-coding/cli +# 然后使用 +DC ai +# 或直接无子命令进入 +DC +``` + +## 快速开始 + +```bash +# 独立使用 +dc-ai + +# 作为主 CLI 的子命令 +DC ai + +# 或直接 DC 回车后选 y +DC + +# 查看帮助 +dc-ai --help +``` + +## 功能特性 + +- 🤖 **多服务商支持**: DeepSeek / 通义千问 / Kimi / Groq + 自定义服务商 +- 🔐 **API Key 持久化**: 首次输入后保存到 `~/.done-coding/config.json`,后续自动使用 +- 📡 **SSE 流式响应**: 逐 token 实时输出,体验接近 ChatGPT +- 🎯 **两级模型选择**: 先选服务商,再选该服务商下的具体模型 +- ⌨️ **内置命令**: `/provider` 切换服务商、`/model` 切换模型、`/clear` 清屏、`/exit` 退出 +- 🔄 **401 自动重试**: API Key 无效时自动重新引导输入 + +## API 文档 + +### 基础命令 + +#### `dc-ai chat` + +启动 AI 对话(默认子命令,`dc-ai` 不加参数等同 `dc-ai chat`) + +```bash +# 直接启动 +dc-ai + +# 显式指定 +dc-ai chat +``` + +**内置命令**: + +| 命令 | 说明 | +|---|---| +| `Ctrl+C` | 取消当前输入 | +| `/exit` | 退出对话 | +| `/provider` | 切换服务商(保留 API Key,自动引导选模型) | +| `/model` | 在当前服务商下切换模型 | +| `/clear` | 清屏 | + +**预设服务商**: + +| 服务商 | 可用模型 | +|---|---| +| DeepSeek | V4 Flash / V4 Pro / V3 Chat(弃用) / R1 Reasoner(弃用) | +| 通义千问 | Qwen Turbo / Qwen Plus / Qwen Max | +| Kimi(月之暗面) | Moonshot v1 8K / 32K / 128K | +| Groq | Llama 3.3 70B / Mixtral 8x7B | + +**首次使用流程**: 选择模型服务商 → 选择具体模型 → 输入 API Key → 开始对话。 + +## 使用示例 + +### 基础使用场景 + +```bash +# 1. 通过主 CLI 启动(无子命令时) +DC +# 是否唤起 AI 对话? → y +# 选择模型服务商 → DeepSeek +# 选择模型 → DeepSeek V4 Flash +# 输入 API Key → **** +# 输入消息开始对话 → + +# 2. 通过 ai 子命令启动 +DC ai + +# 3. 独立 bin 启动 +dc-ai + +# 4. 切换服务商 +# 在对话中输入 /provider + +# 5. 切换模型(当前服务商下) +# 在对话中输入 /model +``` + +### 作为主 CLI 的一部分 + +```bash +# 使用主 CLI 命令 +DC ai +DC ai chat + +# 无子命令,选 y 进入 +DC + +# 使用替代命令 +dc-cli ai +done-coding ai +``` + +## 配置 + +配置持久化到 `~/.done-coding/config.json` 的 `AI_CONFIG` 字段: + +```json +{ + "AI_CONFIG": { + "model": "deepseek-v4-flash", + "apiKey": "sk-xxx", + "baseUrl": "https://api.deepseek.com" + } +} +``` + +## 依赖的工具包 + +本包集成了以下 done-coding CLI 工具: + +- **@done-coding/cli-utils**: 通用工具函数(xPrompts、outputConsole、全局配置读写) +- **openai**: OpenAI 兼容 SDK(^4.x),负责 SSE 流式调用 + +## 故障排除 + +### 常见问题 + +**Q: 401 Authentication Fails** + +```bash +# API Key 无效时会自动重新引导输入 +# 检查 Key 是否正确 +# 确认 Key 在对应服务商的有效期内 +``` + +**Q: 网络请求超时** + +```bash +# 检查网络连接 +curl -I https://api.deepseek.com + +# 确认对应服务商的 API 地址可访问 +``` + +**Q: Token 输出中断** + +```bash +# 重新进入对话即可,已保存的配置不会丢失 +DC ai +``` + +## 贡献指南 + +我们欢迎贡献!请遵循以下步骤: + +1. Fork 本仓库 +2. 创建功能分支:`git checkout -b feature/amazing-feature` +3. 提交更改:`git commit -m "feat: add amazing feature"` +4. 推送分支:`git push origin feature/amazing-feature` +5. 创建 Pull Request + +### 开发环境设置 + +```bash +# 克隆仓库 +git clone https://github.com/done-coding/done-coding-cli.git +cd done-coding-cli/packages/ai + +# 安装依赖 +pnpm install + +# 开发模式 +pnpm dev + +# 构建 +pnpm build + +# 本地开发测试 +node es/cli.mjs --help + +# 注意:本地使用 node + 入口文件,发布后使用 bin 命令名 +# 功能完全一致,只是调用方式不同 +``` + +## 许可证 + +MIT © [done-coding](https://github.com/done-coding) + +## 相关链接 + +- [主 CLI 工具](https://www.npmjs.com/package/@done-coding/cli) +- [Github 仓库](https://github.com/done-coding/done-coding-cli) diff --git a/packages/ai/package.json b/packages/ai/package.json new file mode 100644 index 0000000..914b402 --- /dev/null +++ b/packages/ai/package.json @@ -0,0 +1,59 @@ +{ + "name": "@done-coding/cli-ai", + "version": "0.0.0", + "description": "ai命令行工具", + "private": false, + "module": "es/index.mjs", + "types": "types/index.d.ts", + "type": "module", + "bin": { + "dc-ai": "es/cli.mjs" + }, + "exports": { + ".": { + "import": "./es/index.mjs", + "types": "./types/index.d.ts" + } + }, + "files": [ + "es", + "lib", + "types" + ], + "scripts": { + "dev": "vite build -w -m hotBuild", + "build": "vite build", + "prepack": "pnpm build" + }, + "repository": { + "type": "git", + "url": "https://github.com/done-coding/done-coding-cli.git", + "directory": "packages/ai" + }, + "publishConfig": { + "access": "public", + "registry": "https://registry.npmjs.org/" + }, + "author": "JustSoSu", + "license": "MIT", + "sideEffects": false, + "devDependencies": { + "@done-coding/cli-inject": "workspace:0.5.23", + "@types/node": "^18.0.0", + "@types/prompts": "^2.4.6", + "@types/yargs": "^17.0.28", + "@vitest/coverage-v8": "^1.6.1", + "typescript": "^5.8.3", + "vite": "^5.0.10", + "vite-plugin-dts": "^3.7.0", + "vitest": "^1.6.1" + }, + "peerDependencies": {}, + "dependencies": { + "@done-coding/cli-utils": "workspace:0.8.4", + "openai": "^4.77.0" + }, + "engines": { + "node": ">=18.0.0" + } +} \ No newline at end of file diff --git a/packages/ai/src/cli.ts b/packages/ai/src/cli.ts new file mode 100644 index 0000000..7ca118a --- /dev/null +++ b/packages/ai/src/cli.ts @@ -0,0 +1,3 @@ +import { createCommand } from "./main"; + +createCommand(); diff --git a/packages/ai/src/handlers/chat.ts b/packages/ai/src/handlers/chat.ts new file mode 100644 index 0000000..517f58c --- /dev/null +++ b/packages/ai/src/handlers/chat.ts @@ -0,0 +1,247 @@ +import type { + SubCliInfo, + DoneCodingCliGlobalConfig, + AiConfig, +} from "@done-coding/cli-utils"; +import { + outputConsole, + xPrompts, + readJsonFileAsync, + getGlobalConfigFilePath, + DoneCodingCliGlobalConfigKeyEnum, +} from "@done-coding/cli-utils"; +import { writeFileSync, existsSync, mkdirSync } from "node:fs"; +import { dirname } from "node:path"; +import { ChatKeywordEnum, SubcommandEnum } from "@/types"; +import { + PROVIDER_PRESETS, + CUSTOM_PROVIDER_INDEX, + CUSTOM_PROVIDER_LABEL, +} from "@/services/model-presets"; +import type { ProviderPreset } from "@/services/model-presets"; +import { AuthenticationError } from "openai"; +import { streamChat } from "@/services/api-client"; + +/** + * 读取全局配置文件 + * @returns 全局配置对象,文件不存在时返回空对象 + */ +const readGlobalConfig = async (): Promise => { + try { + return await readJsonFileAsync( + getGlobalConfigFilePath(), + ); + } catch { + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + return {} as DoneCodingCliGlobalConfig; + } +}; + +/** + * 写入全局配置文件(目录不存在时自动创建) + * @param config 全局配置对象 + */ +const writeGlobalConfig = async (config: DoneCodingCliGlobalConfig) => { + const filePath = getGlobalConfigFilePath(); + const dir = dirname(filePath); + if (!existsSync(dir)) { + mkdirSync(dir, { recursive: true }); + } + writeFileSync(filePath, JSON.stringify(config, null, 2), "utf-8"); +}; + +/** + * 选择模型(在当前服务商下) + * @param provider 当前服务商 + * @returns 模型标识名 + */ +const selectModelForProvider = async ( + provider: ProviderPreset, +): Promise => { + const modelChoices = provider.models.map((m, i) => ({ + title: m.label, + value: i, + })); + + const { modelIndex } = await xPrompts({ + type: "select", + name: "modelIndex", + message: `选择 ${provider.label} 模型`, + choices: modelChoices, + }); + + return provider.models[modelIndex].model; +}; + +/** + * 选择服务商 + 模型 + * @returns { model, baseUrl } 或 null(用户取消) + */ +const selectProviderAndModel = async (): Promise<{ + model: string; + baseUrl: string; +} | null> => { + const providerChoices = PROVIDER_PRESETS.map((p, i) => ({ + title: p.label, + value: i, + })); + providerChoices.push({ + title: CUSTOM_PROVIDER_LABEL, + value: CUSTOM_PROVIDER_INDEX, + }); + + const { providerIndex } = await xPrompts({ + type: "select", + name: "providerIndex", + message: "选择模型服务商", + choices: providerChoices, + }); + + if (providerIndex === CUSTOM_PROVIDER_INDEX) { + const custom = await xPrompts([ + { type: "text", name: "model", message: "输入模型标识名" }, + { type: "text", name: "baseUrl", message: "输入 API Base URL" }, + ]); + return { model: custom.model, baseUrl: custom.baseUrl }; + } + + const provider = PROVIDER_PRESETS[providerIndex]; + const model = await selectModelForProvider(provider); + return { model, baseUrl: provider.baseUrl }; +}; + +/** + * 首次引导流程:选服务商 → 选模型 → 输入 API Key + * @returns AiConfig 配置对象,用户取消时返回 null + */ +const firstTimeSetup = async (): Promise => { + const result = await selectProviderAndModel(); + if (!result) return null; + + const { apiKey } = await xPrompts({ + type: "password", + name: "apiKey", + message: "输入 API Key", + validate: (v: string) => (v?.trim().length > 0 ? true : "API Key 不能为空"), + }); + + return { ...result, apiKey }; +}; + +/** + * AI 对话主处理器 + * 流程:读取配置 → 首次引导(如需) → 对话循环(xPrompts 交互 + SSE 流式响应) + */ +const chatHandler = async () => { + let config = await readGlobalConfig(); + let aiConfig = config[DoneCodingCliGlobalConfigKeyEnum.AI_CONFIG]; + + // 首次配置 + if (!aiConfig?.apiKey) { + outputConsole.info("首次使用需配置模型和 API Key\n"); + const result = await firstTimeSetup(); + if (!result) return; + + aiConfig = result; + config[DoneCodingCliGlobalConfigKeyEnum.AI_CONFIG] = aiConfig; + await writeGlobalConfig(config); + outputConsole.info(""); + } + + outputConsole.info( + `模型: ${aiConfig.model} | 输入消息开始对话 (${ChatKeywordEnum.EXIT} 退出, ${ChatKeywordEnum.PROVIDER} 切换服务商, ${ChatKeywordEnum.MODEL} 切换模型, ${ChatKeywordEnum.CLEAR} 清屏)\n`, + ); + + // 对话循环 + while (true) { + const { input } = await xPrompts({ + type: "text", + name: "input", + message: "", + validate: () => true, + }); + + const trimmed = (input as string)?.trim(); + + if (!trimmed) continue; + + if (trimmed === ChatKeywordEnum.EXIT) { + outputConsole.info("对话结束"); + return; + } + + if (trimmed === ChatKeywordEnum.PROVIDER) { + const result = await selectProviderAndModel(); + if (result) { + aiConfig = { ...aiConfig, ...result }; + config[DoneCodingCliGlobalConfigKeyEnum.AI_CONFIG] = aiConfig; + await writeGlobalConfig(config); + outputConsole.info(`已切换至 ${aiConfig.model}\n`); + } + continue; + } + + if (trimmed === ChatKeywordEnum.MODEL) { + // 在当前服务商下切换模型 + const provider = PROVIDER_PRESETS.find( + (p) => p.baseUrl === aiConfig?.baseUrl, + ); + if (provider) { + const model = await selectModelForProvider(provider); + aiConfig = { ...aiConfig, model }; + config[DoneCodingCliGlobalConfigKeyEnum.AI_CONFIG] = aiConfig; + await writeGlobalConfig(config); + outputConsole.info(`已切换至 ${model}\n`); + } else { + // 自定义 baseUrl 无法定位服务商,走完整流程 + const result = await selectProviderAndModel(); + if (result) { + aiConfig = { ...aiConfig, ...result }; + config[DoneCodingCliGlobalConfigKeyEnum.AI_CONFIG] = aiConfig; + await writeGlobalConfig(config); + outputConsole.info(`已切换至 ${aiConfig.model}\n`); + } + } + continue; + } + + if (trimmed === ChatKeywordEnum.CLEAR) { + process.stdout.write("\x1b[2J\x1b[0f"); + continue; + } + + // 发送 AI 请求 + outputConsole.stage("思考中..."); + try { + await streamChat({ + config: aiConfig, + message: trimmed, + onToken: (token) => process.stdout.write(token), + }); + process.stdout.write("\n"); + } catch (error: any) { + const isAuthError = + error instanceof AuthenticationError || error?.status === 401; + if (isAuthError) { + outputConsole.info("API Key 无效,请重新输入\n"); + const result = await firstTimeSetup(); + if (!result) return; + aiConfig = result; + config[DoneCodingCliGlobalConfigKeyEnum.AI_CONFIG] = aiConfig; + await writeGlobalConfig(config); + outputConsole.info(`已切换至 ${aiConfig.model}\n`); + } else { + outputConsole.error(`请求失败: ${error?.message || error}`); + } + } + } +}; + +/** yargs 子命令注册信息 */ +export const commandCliInfo: SubCliInfo = { + command: SubcommandEnum.CHAT, + describe: "AI 对话", + handler: chatHandler as SubCliInfo["handler"], +}; + +export const handler = chatHandler; diff --git a/packages/ai/src/handlers/index.ts b/packages/ai/src/handlers/index.ts new file mode 100644 index 0000000..10bfbb2 --- /dev/null +++ b/packages/ai/src/handlers/index.ts @@ -0,0 +1,39 @@ +import { + handler as chatHandler, + commandCliInfo as chatCommandCliInfo, +} from "./chat"; +import injectInfo from "@/injectInfo.json"; +import { SubcommandEnum } from "@/types"; +import { + createSubcommand, + getRootScriptName, + packDefaultCommandCliInfo, + type CliInfo, +} from "@done-coding/cli-utils"; + +export { chatHandler, chatCommandCliInfo }; + +/** 导出供外部 export使用, cli内部不会通过改方法调用各子命令方法 */ +export const handler = async (command: SubcommandEnum) => { + switch (command) { + case SubcommandEnum.CHAT: { + return chatHandler(); + } + default: { + throw new Error(`不支持的命令 ${command}`); + } + } +}; + +const { version, description: describe } = injectInfo; + +export const commandCliInfo: Omit = { + describe, + version, + subcommands: [ + packDefaultCommandCliInfo(chatCommandCliInfo), + chatCommandCliInfo, + ].map(createSubcommand), + demandCommandCount: 1, + rootScriptName: getRootScriptName({ packageJson: injectInfo }), +}; diff --git a/packages/ai/src/index.ts b/packages/ai/src/index.ts new file mode 100644 index 0000000..e6a927a --- /dev/null +++ b/packages/ai/src/index.ts @@ -0,0 +1,3 @@ +export { handler } from "@/handlers"; +export { createAsSubcommand } from "./main"; +export * from "@/types"; diff --git a/packages/ai/src/main.ts b/packages/ai/src/main.ts new file mode 100644 index 0000000..be1ecb9 --- /dev/null +++ b/packages/ai/src/main.ts @@ -0,0 +1,31 @@ +import { commandCliInfo } from "@/handlers"; +import injectInfo from "@/injectInfo.json"; +import type { SubCliInfo } from "@done-coding/cli-utils"; +import { createMainCommand, createSubcommand } from "@done-coding/cli-utils"; + +const { + cliConfig: { moduleName }, +} = injectInfo; + +/** 分发命令&步骤 */ +const dispatchCommandAndUsage = (asSubcommand = false) => { + const command = asSubcommand ? moduleName : undefined; + const usage = `$0${asSubcommand ? ` ${moduleName}` : ""} [options]`; + return { command, usage }; +}; + +/** 作为主命令创建 */ +export const createCommand = async () => { + return createMainCommand({ + ...commandCliInfo, + ...dispatchCommandAndUsage(), + }); +}; + +/** 作为子命令创建 */ +export const createAsSubcommand = () => { + return createSubcommand({ + ...commandCliInfo, + ...dispatchCommandAndUsage(true), + } as unknown as SubCliInfo); +}; diff --git a/packages/ai/src/services/api-client.ts b/packages/ai/src/services/api-client.ts new file mode 100644 index 0000000..d4c5d48 --- /dev/null +++ b/packages/ai/src/services/api-client.ts @@ -0,0 +1,37 @@ +import OpenAI from "openai"; +import type { AiConfig } from "@done-coding/cli-utils"; + +/** 流式聊天请求参数 */ +export interface StreamChatParams { + /** AI 配置 */ + config: AiConfig; + /** 用户消息 */ + message: string; + /** token 回调 */ + onToken: (token: string) => void; +} + +/** SSE 流式聊天:逐 token 回调 onToken */ +export const streamChat = async (params: StreamChatParams): Promise => { + const { config, message, onToken } = params; + + const client = new OpenAI({ + apiKey: config.apiKey, + baseURL: config.baseUrl.endsWith("/v1") + ? config.baseUrl + : config.baseUrl + "/v1", + }); + + const stream = await client.chat.completions.create({ + model: config.model, + messages: [{ role: "user", content: message }], + stream: true, + }); + + for await (const chunk of stream) { + const content = chunk.choices[0]?.delta?.content; + if (content) { + onToken(content); + } + } +}; diff --git a/packages/ai/src/services/model-presets.ts b/packages/ai/src/services/model-presets.ts new file mode 100644 index 0000000..3095a7d --- /dev/null +++ b/packages/ai/src/services/model-presets.ts @@ -0,0 +1,75 @@ +/** + * 模型服务商预设 + * --- + * 两级结构:先选服务商(含 baseUrl),再选该服务商下的具体模型 + */ + +/** 模型信息 */ +export interface ModelInfo { + /** 模型标识名(API 调用传参),如 "deepseek-chat" */ + model: string; + /** 用户可见的展示名称 */ + label: string; +} + +/** 服务商预设 */ +export interface ProviderPreset { + /** 服务商展示名称 */ + label: string; + /** API Base URL */ + baseUrl: string; + /** 该服务商下可用模型列表 */ + models: ModelInfo[]; +} + +/** 自定义服务商的索引值 */ +export const CUSTOM_PROVIDER_INDEX = -1; + +/** 自定义服务商的展示标签 */ +export const CUSTOM_PROVIDER_LABEL = "自定义..."; + +/** 预设服务商列表 */ +export const PROVIDER_PRESETS: ProviderPreset[] = [ + { + label: "DeepSeek", + baseUrl: "https://api.deepseek.com", + models: [ + { model: "deepseek-v4-flash", label: "DeepSeek V4 Flash" }, + { model: "deepseek-v4-pro", label: "DeepSeek V4 Pro" }, + { + model: "deepseek-chat", + label: "DeepSeek V3 (chat,将于 2026/07/24 弃用)", + }, + { + model: "deepseek-reasoner", + label: "DeepSeek R1 (reasoner,将于 2026/07/24 弃用)", + }, + ], + }, + { + label: "通义千问", + baseUrl: "https://dashscope.aliyuncs.com/compatible-mode", + models: [ + { model: "qwen-turbo", label: "Qwen Turbo" }, + { model: "qwen-plus", label: "Qwen Plus" }, + { model: "qwen-max", label: "Qwen Max" }, + ], + }, + { + label: "Kimi (月之暗面)", + baseUrl: "https://api.moonshot.cn", + models: [ + { model: "moonshot-v1-8k", label: "Moonshot v1 8K" }, + { model: "moonshot-v1-32k", label: "Moonshot v1 32K" }, + { model: "moonshot-v1-128k", label: "Moonshot v1 128K" }, + ], + }, + { + label: "Groq", + baseUrl: "https://api.groq.com/openai", + models: [ + { model: "llama-3.3-70b-versatile", label: "Llama 3.3 70B" }, + { model: "mixtral-8x7b-32768", label: "Mixtral 8x7B" }, + ], + }, +]; diff --git a/packages/ai/src/types/index.ts b/packages/ai/src/types/index.ts new file mode 100644 index 0000000..ac87f0c --- /dev/null +++ b/packages/ai/src/types/index.ts @@ -0,0 +1,17 @@ +/** 子命令枚举 */ +export enum SubcommandEnum { + /** AI 对话 */ + CHAT = "chat", +} + +/** 对话内置关键字 */ +export enum ChatKeywordEnum { + /** 退出对话 */ + EXIT = "/exit", + /** 切换服务商(含模型选择) */ + PROVIDER = "/provider", + /** 切换模型 */ + MODEL = "/model", + /** 清屏 */ + CLEAR = "/clear", +} diff --git a/packages/ai/src/utils/index.ts b/packages/ai/src/utils/index.ts new file mode 100644 index 0000000..f07164f --- /dev/null +++ b/packages/ai/src/utils/index.ts @@ -0,0 +1 @@ +export * from "./path"; diff --git a/packages/ai/src/utils/path.ts b/packages/ai/src/utils/path.ts new file mode 100644 index 0000000..540bc74 --- /dev/null +++ b/packages/ai/src/utils/path.ts @@ -0,0 +1,11 @@ +import injectInfo from "@/injectInfo.json"; + +const { + cliConfig: { namespaceDir, moduleName }, +} = injectInfo; + +/** 模块配置相对路径 */ +export const MODULE_CONFIG_RELATIVE_PATH = `./${namespaceDir}/${moduleName}`; + +/** 模块默认配置文件相对路径 */ +export const MODULE_DEFAULT_CONFIG_RELATIVE_PATH = `${MODULE_CONFIG_RELATIVE_PATH}.json`; diff --git a/packages/ai/tsconfig.json b/packages/ai/tsconfig.json new file mode 100644 index 0000000..c3e6a12 --- /dev/null +++ b/packages/ai/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "ES2020", + "moduleResolution": "Node", + "strict": true, + "skipLibCheck": true, + "declaration": false, + "sourceMap": false, + "noUnusedLocals": true, + "isolatedModules": true, + "esModuleInterop": true, + "resolveJsonModule": true, + "baseUrl": ".", + "paths": { + "@/*": ["src/*"] + } + }, + "include": ["src"], + "exclude": ["node_modules", "**/*.test.js"] +} diff --git a/packages/ai/vite.config.ts b/packages/ai/vite.config.ts new file mode 100644 index 0000000..aa55d12 --- /dev/null +++ b/packages/ai/vite.config.ts @@ -0,0 +1,80 @@ +/// +import { defineConfig } from "vite"; +import path from "node:path"; +import dts from "vite-plugin-dts"; +import pkg from "./package.json"; +import { builtinModules } from "node:module"; +import { generateFile } from "@done-coding/cli-inject"; +import { doneCodingCliConfig } from "@done-coding/cli-inject/helpers"; + +generateFile({ config: doneCodingCliConfig }); + +export default defineConfig(({ command, mode }) => { + const isPro = command === "build" && mode !== "hotBuild"; + + const inputList = ["src/index.ts", "src/cli.ts"]; + + return { + test: { + globals: true, + coverage: { + provider: "v8", + reporter: ["text", "json", "html"], + include: ["src/**/*.ts?(x)"], + }, + }, + plugins: [ + dts({ + include: [ + "src/**/*.ts", + "src/**/*.tsx", + "src/**/*.d.ts", + "src/**/*.json", + ], + exclude: ["**/__tests__/**"], + outDir: "./types", + rollupTypes: isPro, + }), + ], + resolve: { + alias: { + "@": path.resolve(__dirname, "./src"), + }, + }, + json: { + namedExports: false, + stringify: false, + }, + build: { + minify: isPro, + emptyOutDir: true, + target: "node16", + lib: { + entry: inputList, + }, + rollupOptions: { + external: [ + ...builtinModules, + ...builtinModules.map((m) => `node:${m}`), + ...Object.keys(pkg.dependencies || {}), + ...Object.keys(pkg.peerDependencies || {}), + ], + input: inputList, + output: [ + { + format: "es", + entryFileNames: "[name].mjs", + dir: "./es", + banner: `#!/usr/bin/env node`, + ...(isPro + ? {} + : { + preserveModules: true, + preserveModulesRoot: "src", + }), + }, + ], + }, + }, + }; +}); diff --git a/packages/cli/README.md b/packages/cli/README.md index b7bf555..d97c9a0 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -57,7 +57,8 @@ done-coding --help ## 功能特性 -- ✅ **统一入口**: 集成 9 个专业工具包,提供统一的命令行入口 +- ✅ **统一入口**: 集成 10 个专业工具包,提供统一的命令行入口 +- 🤖 **AI 对话**: 无子命令时唤起 AI 对话,支持多服务商、SSE 流式响应 - 🚀 **跨平台兼容**: 支持 Windows、macOS、Linux,自动处理系统差异 - 🔧 **模块化设计**: 每个子包独立开发,可单独使用或集成使用 - 📦 **完整工作流**: 涵盖项目创建、开发、构建、发布的完整流程 @@ -111,6 +112,12 @@ done-coding --help - **描述**: 项目发布命令行工具 - **包地址**: [@done-coding/cli-publish](https://www.npmjs.com/package/@done-coding/cli-publish) +### 🤖 AI 对话 + +- **命令**: `DC ai` 或直接输入 `DC`(无子命令) +- **描述**: AI 对话命令行工具 +- **包地址**: [@done-coding/cli-ai](https://www.npmjs.com/package/@done-coding/cli-ai) + ### 📝 模板处理 - **命令**: `DC template` @@ -149,6 +156,10 @@ DC git check # 检查git操作 # 项目发布 DC publish # 项目发布命令行工具 + +# AI 对话 +DC ai # 进入 AI 对话 +DC(无子命令后选 y) # 唤起 AI 对话 ``` ### 使用替代命令 @@ -223,6 +234,19 @@ dc-cli publish done-coding publish ``` +### AI 对话 + +```bash +# 方式一:DC 无子命令,选 y 进入 AI 对话 +DC + +# 方式二:DC ai 子命令 +DC ai + +# 方式三:直接指定 chat +DC ai chat +``` + ## 配置 您可以在项目根目录创建 `.done-coding.config.js` 文件来自定义配置: @@ -291,6 +315,7 @@ graph TD ├── @done-coding/cli-inject (信息注入) ├── @done-coding/cli-publish (项目发布) ├── @done-coding/cli-template (模板处理) +├── @done-coding/cli-ai (AI 对话) └── @done-coding/cli-utils (工具库) ``` @@ -335,13 +360,13 @@ DC --version - [项目创建工具](https://www.npmjs.com/package/create-done-coding) - [组件生成工具](https://www.npmjs.com/package/@done-coding/cli-component) -- [更多工具](https://gitee.com/done-coding/done-coding-cli) +- [更多工具](https://github.com/done-coding/done-coding-cli) ## 许可证 -MIT © [JustSoSu](https://gitee.com/done-coding) +MIT © [done-coding](https://github.com/done-coding) ## 相关链接 -- [Gitee 仓库](https://gitee.com/done-coding/done-coding-cli) +- [Github 仓库](https://github.com/done-coding/done-coding-cli) - [更新日志](./CHANGELOG.md) diff --git a/packages/cli/package.json b/packages/cli/package.json index 7d1b79b..271df3f 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@done-coding/cli", - "version": "0.15.23", + "version": "0.15.24-alpha.0", "description": "done-coding命令行工具", "private": false, "module": "es/cli.mjs", @@ -49,6 +49,7 @@ "vite-plugin-dts": "^3.6.0" }, "dependencies": { + "@done-coding/cli-ai": "workspace:0.0.0", "@done-coding/cli-component": "workspace:0.4.12", "@done-coding/cli-config": "workspace:0.1.15", "@done-coding/cli-extract": "workspace:0.1.23", @@ -57,9 +58,9 @@ "@done-coding/cli-publish": "workspace:0.7.16", "@done-coding/cli-template": "workspace:0.8.10", "@done-coding/cli-utils": "workspace:0.8.4", - "create-done-coding": "workspace:0.11.26" + "create-done-coding": "workspace:0.11.27-alpha.0" }, "engines": { "node": ">=18.0.0" } -} +} \ No newline at end of file diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 88e71b5..92b6664 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -1,34 +1,40 @@ export { - crateAsSubcommand as createExtractCommand, + createAsSubcommand as createExtractCommand, handler as extractHandler, } from "@done-coding/cli-extract"; export { - crateAsSubcommand as createInjectCommand, + createAsSubcommand as createInjectCommand, handler as injectHandler, } from "@done-coding/cli-inject"; export { - crateAsSubcommand as createCreateCommand, + createAsSubcommand as createCreateCommand, handler as createHandler, } from "create-done-coding"; export { - crateAsSubcommand as createPublishCommand, + createAsSubcommand as createPublishCommand, handler as publishHandler, } from "@done-coding/cli-publish"; export { - crateAsSubcommand as createTemplateCommand, + createAsSubcommand as createTemplateCommand, handler as templateHandler, } from "@done-coding/cli-template"; export { - crateAsSubcommand as createComponentCommand, + createAsSubcommand as createComponentCommand, handler as componentHandler, } from "@done-coding/cli-component"; export { - crateAsSubcommand as configComponentCommand, + createAsSubcommand as createAiCommand, + handler as aiHandler, + SubcommandEnum as AiSubcommandEnum, +} from "@done-coding/cli-ai"; + +export { + createAsSubcommand as configComponentCommand, handler as configHandler, } from "@done-coding/cli-config"; diff --git a/packages/cli/src/main.ts b/packages/cli/src/main.ts index 3833ade..fee5db8 100644 --- a/packages/cli/src/main.ts +++ b/packages/cli/src/main.ts @@ -1,14 +1,24 @@ -import { crateAsSubcommand as createInjectCommand } from "@done-coding/cli-inject"; -import { crateAsSubcommand as createExtractCommand } from "@done-coding/cli-extract"; -import { crateAsSubcommand as createGitCommand } from "@done-coding/cli-git"; -import { crateAsSubcommand as createCreateCommand } from "create-done-coding"; -import { crateAsSubcommand as createPublishCommand } from "@done-coding/cli-publish"; -import { crateAsSubcommand as createTemplateCommand } from "@done-coding/cli-template"; -import { crateAsSubcommand as createComponentCommand } from "@done-coding/cli-component"; -import { crateAsSubcommand as createConfigCommand } from "@done-coding/cli-config"; +import { createAsSubcommand as createInjectCommand } from "@done-coding/cli-inject"; +import { createAsSubcommand as createExtractCommand } from "@done-coding/cli-extract"; +import { createAsSubcommand as createGitCommand } from "@done-coding/cli-git"; +import { createAsSubcommand as createCreateCommand } from "create-done-coding"; +import { createAsSubcommand as createPublishCommand } from "@done-coding/cli-publish"; +import { createAsSubcommand as createTemplateCommand } from "@done-coding/cli-template"; +import { createAsSubcommand as createComponentCommand } from "@done-coding/cli-component"; +import { createAsSubcommand as createConfigCommand } from "@done-coding/cli-config"; +import { + createAsSubcommand as createAiCommand, + handler as aiHandler, + SubcommandEnum as AiSubcommandEnum, +} from "@done-coding/cli-ai"; import injectInfo from "@/injectInfo.json"; import type { CliInfo } from "@done-coding/cli-utils"; -import { createMainCommand, getRootScriptName } from "@done-coding/cli-utils"; +import { + createMainCommand, + getRootScriptName, + execSyncHijack, + xPrompts, +} from "@done-coding/cli-utils"; const { version, description: describe } = injectInfo; @@ -25,9 +35,26 @@ const commandCliInfo: CliInfo = { createTemplateCommand(), createComponentCommand(), createConfigCommand(), + createAiCommand(), ], - demandCommandCount: 1, + demandCommandCount: 0, rootScriptName: getRootScriptName({ packageJson: injectInfo }), + async handler() { + const { shouldChat } = await xPrompts({ + type: "confirm", + name: "shouldChat", + message: "是否唤起 AI 对话?", + initial: true, + }); + + if (shouldChat) { + await aiHandler(AiSubcommandEnum.CHAT, {}); + } else { + execSyncHijack(`node ${process.argv[1]} --help`, { + stdio: "inherit", + }); + } + }, }; /** 作为主命令创建 */ diff --git a/packages/component/README.md b/packages/component/README.md index a925834..21ef469 100644 --- a/packages/component/README.md +++ b/packages/component/README.md @@ -188,11 +188,11 @@ node es/cli.mjs --help ## 许可证 -MIT © [JustSoSu](https://gitee.com/done-coding) +MIT © [done-coding](https://github.com/done-coding) ## 相关链接 - [主 CLI 工具](https://www.npmjs.com/package/@done-coding/cli) - [模板处理工具](https://www.npmjs.com/package/@done-coding/cli-template) - 本包依赖的模板引擎 -- [Gitee 仓库](https://gitee.com/done-coding/done-coding-cli) +- [Github 仓库](https://github.com/done-coding/done-coding-cli) - [更新日志](./CHANGELOG.md) diff --git a/packages/component/src/index.ts b/packages/component/src/index.ts index 51df57f..e6a927a 100644 --- a/packages/component/src/index.ts +++ b/packages/component/src/index.ts @@ -1,3 +1,3 @@ export { handler } from "@/handlers"; -export { crateAsSubcommand } from "./main"; +export { createAsSubcommand } from "./main"; export * from "@/types"; diff --git a/packages/component/src/main.ts b/packages/component/src/main.ts index 04459ae..be1ecb9 100644 --- a/packages/component/src/main.ts +++ b/packages/component/src/main.ts @@ -23,7 +23,7 @@ export const createCommand = async () => { }; /** 作为子命令创建 */ -export const crateAsSubcommand = () => { +export const createAsSubcommand = () => { return createSubcommand({ ...commandCliInfo, ...dispatchCommandAndUsage(true), diff --git a/packages/config/README.md b/packages/config/README.md index d5c02e1..b29c775 100644 --- a/packages/config/README.md +++ b/packages/config/README.md @@ -219,11 +219,11 @@ node es/cli.mjs --help ## 许可证 -MIT © [JustSoSu](https://gitee.com/done-coding) +MIT © [done-coding](https://github.com/done-coding) ## 相关链接 - [主 CLI 工具](https://www.npmjs.com/package/@done-coding/cli) - [Git 操作工具](https://www.npmjs.com/package/@done-coding/cli-git) - 本包调用的 Git 检测功能 -- [Gitee 仓库](https://gitee.com/done-coding/done-coding-cli) +- [Github 仓库](https://github.com/done-coding/done-coding-cli) - [更新日志](./CHANGELOG.md) diff --git a/packages/config/src/index.ts b/packages/config/src/index.ts index 51df57f..e6a927a 100644 --- a/packages/config/src/index.ts +++ b/packages/config/src/index.ts @@ -1,3 +1,3 @@ export { handler } from "@/handlers"; -export { crateAsSubcommand } from "./main"; +export { createAsSubcommand } from "./main"; export * from "@/types"; diff --git a/packages/config/src/main.ts b/packages/config/src/main.ts index 04459ae..be1ecb9 100644 --- a/packages/config/src/main.ts +++ b/packages/config/src/main.ts @@ -23,7 +23,7 @@ export const createCommand = async () => { }; /** 作为子命令创建 */ -export const crateAsSubcommand = () => { +export const createAsSubcommand = () => { return createSubcommand({ ...commandCliInfo, ...dispatchCommandAndUsage(true), diff --git a/packages/create/README.md b/packages/create/README.md index 8edc71d..bc65a0d 100644 --- a/packages/create/README.md +++ b/packages/create/README.md @@ -217,7 +217,7 @@ node es/cli.mjs --help ## 许可证 -MIT © [JustSoSu](https://gitee.com/done-coding) +MIT © [done-coding](https://github.com/done-coding) ## 相关链接 @@ -225,5 +225,5 @@ MIT © [JustSoSu](https://gitee.com/done-coding) - [Git 操作工具](https://www.npmjs.com/package/@done-coding/cli-git) - 本包依赖的 Git 功能 - [模板处理工具](https://www.npmjs.com/package/@done-coding/cli-template) - 本包依赖的模板引擎 - [信息注入工具](https://www.npmjs.com/package/@done-coding/cli-inject) - 本包依赖的信息注入功能 -- [Gitee 仓库](https://gitee.com/done-coding/done-coding-cli) +- [Github 仓库](https://github.com/done-coding/done-coding-cli) - [更新日志](./CHANGELOG.md) diff --git a/packages/create/package.json b/packages/create/package.json index c60b758..106d7e3 100644 --- a/packages/create/package.json +++ b/packages/create/package.json @@ -1,6 +1,6 @@ { "name": "create-done-coding", - "version": "0.11.26", + "version": "0.11.27-alpha.0", "description": "项目创建命令行工具", "module": "es/index.mjs", "type": "module", diff --git a/packages/create/src/index.ts b/packages/create/src/index.ts index 5b4b66e..05f4fce 100644 --- a/packages/create/src/index.ts +++ b/packages/create/src/index.ts @@ -1,5 +1,5 @@ import injectInfo from "@/injectInfo.json"; export * from "@/handlers"; -export { crateAsSubcommand } from "./main"; +export { createAsSubcommand } from "./main"; export * from "@/types"; export { injectInfo }; diff --git a/packages/create/src/main.ts b/packages/create/src/main.ts index 3b2898d..9232553 100644 --- a/packages/create/src/main.ts +++ b/packages/create/src/main.ts @@ -9,7 +9,8 @@ const { /** 分发命令&步骤 */ const dispatchCommandAndUsage = (asSubcommand = false) => { - const command = `${asSubcommand ? `${moduleName} ` : ""}[projectName]`; + // const command = `${asSubcommand ? `${moduleName} ` : ""}[projectName]`; + const command = `${asSubcommand ? `${moduleName} ` : ""}`; const usage = `$0 ${command.trim()}`; return { command, usage }; }; @@ -23,7 +24,7 @@ export const createCommand = async () => { }; /** 作为子命令创建 */ -export const crateAsSubcommand = () => { +export const createAsSubcommand = () => { return createSubcommand({ ...commandCliInfo, ...dispatchCommandAndUsage(true), diff --git a/packages/extract/README.md b/packages/extract/README.md index 6b4e4a5..06bcca6 100644 --- a/packages/extract/README.md +++ b/packages/extract/README.md @@ -239,11 +239,11 @@ node es/cli.mjs --help ## 许可证 -MIT © [JustSoSu](https://gitee.com/done-coding) +MIT © [done-coding](https://github.com/done-coding) ## 相关链接 - [主 CLI 工具](https://www.npmjs.com/package/@done-coding/cli) - [模板处理工具](https://www.npmjs.com/package/@done-coding/cli-template) - 本包依赖的模板引擎 -- [Gitee 仓库](https://gitee.com/done-coding/done-coding-cli) +- [Github 仓库](https://github.com/done-coding/done-coding-cli) - [更新日志](./CHANGELOG.md) diff --git a/packages/extract/src/index.ts b/packages/extract/src/index.ts index d96edd8..0e387cc 100644 --- a/packages/extract/src/index.ts +++ b/packages/extract/src/index.ts @@ -1,3 +1,3 @@ export * from "@/handlers"; -export { crateAsSubcommand } from "./main"; +export { createAsSubcommand } from "./main"; export * from "@/types"; diff --git a/packages/extract/src/main.ts b/packages/extract/src/main.ts index 04459ae..be1ecb9 100644 --- a/packages/extract/src/main.ts +++ b/packages/extract/src/main.ts @@ -23,7 +23,7 @@ export const createCommand = async () => { }; /** 作为子命令创建 */ -export const crateAsSubcommand = () => { +export const createAsSubcommand = () => { return createSubcommand({ ...commandCliInfo, ...dispatchCommandAndUsage(true), diff --git a/packages/git/README.md b/packages/git/README.md index 6f07ada..ed25754 100644 --- a/packages/git/README.md +++ b/packages/git/README.md @@ -314,7 +314,7 @@ node es/cli.mjs --help ## 许可证 -MIT © [JustSoSu](https://gitee.com/done-coding) +MIT © [done-coding](https://github.com/done-coding) ## 包依赖关系 @@ -353,5 +353,5 @@ dc-git check reverse-merge - [主 CLI 工具](https://www.npmjs.com/package/@done-coding/cli) - [配置工具包](https://www.npmjs.com/package/@done-coding/cli-config) - 使用本包的检测功能 -- [Gitee 仓库](https://gitee.com/done-coding/done-coding-cli) +- [Github 仓库](https://github.com/done-coding/done-coding-cli) - [更新日志](./CHANGELOG.md) diff --git a/packages/git/src/index.ts b/packages/git/src/index.ts index 2826601..b0a649a 100644 --- a/packages/git/src/index.ts +++ b/packages/git/src/index.ts @@ -1,4 +1,4 @@ export * from "@/handlers"; -export { crateAsSubcommand } from "./main"; +export { createAsSubcommand } from "./main"; export * from "@/types"; export { getTargetRepoUrl } from "./utils"; diff --git a/packages/git/src/main.ts b/packages/git/src/main.ts index 94ece70..cd96bb1 100644 --- a/packages/git/src/main.ts +++ b/packages/git/src/main.ts @@ -30,7 +30,7 @@ export const createCommand = async () => { }; /** 作为子命令创建 */ -export const crateAsSubcommand = () => { +export const createAsSubcommand = () => { return createSubcommand({ ...commandCliInfo, ...dispatchCommandAndUsage(true), diff --git a/packages/inject/README.md b/packages/inject/README.md index f0b365a..29500ce 100644 --- a/packages/inject/README.md +++ b/packages/inject/README.md @@ -182,10 +182,10 @@ node es/cli.mjs --help ## 许可证 -MIT © [JustSoSu](https://gitee.com/done-coding) +MIT © [done-coding](https://github.com/done-coding) ## 相关链接 - [主 CLI 工具](https://www.npmjs.com/package/@done-coding/cli) -- [Gitee 仓库](https://gitee.com/done-coding/done-coding-cli) +- [Github 仓库](https://github.com/done-coding/done-coding-cli) - [更新日志](./CHANGELOG.md) diff --git a/packages/inject/src/index.ts b/packages/inject/src/index.ts index 5a669db..62a6b5c 100644 --- a/packages/inject/src/index.ts +++ b/packages/inject/src/index.ts @@ -1,4 +1,4 @@ export * from "@/handlers"; -export { crateAsSubcommand } from "./main"; +export { createAsSubcommand } from "./main"; export * from "@/types"; export { keyConfigResolve } from "@/utils"; diff --git a/packages/inject/src/main.ts b/packages/inject/src/main.ts index 04459ae..be1ecb9 100644 --- a/packages/inject/src/main.ts +++ b/packages/inject/src/main.ts @@ -23,7 +23,7 @@ export const createCommand = async () => { }; /** 作为子命令创建 */ -export const crateAsSubcommand = () => { +export const createAsSubcommand = () => { return createSubcommand({ ...commandCliInfo, ...dispatchCommandAndUsage(true), diff --git a/packages/publish/README.md b/packages/publish/README.md index fc37add..28c3adc 100644 --- a/packages/publish/README.md +++ b/packages/publish/README.md @@ -249,10 +249,10 @@ node es/cli.mjs --help ## 许可证 -MIT © [JustSoSu](https://gitee.com/done-coding) +MIT © [done-coding](https://github.com/done-coding) ## 相关链接 - [主 CLI 工具](https://www.npmjs.com/package/@done-coding/cli) -- [Gitee 仓库](https://gitee.com/done-coding/done-coding-cli) +- [Github 仓库](https://github.com/done-coding/done-coding-cli) - [更新日志](./CHANGELOG.md) diff --git a/packages/publish/src/index.ts b/packages/publish/src/index.ts index 51df57f..e6a927a 100644 --- a/packages/publish/src/index.ts +++ b/packages/publish/src/index.ts @@ -1,3 +1,3 @@ export { handler } from "@/handlers"; -export { crateAsSubcommand } from "./main"; +export { createAsSubcommand } from "./main"; export * from "@/types"; diff --git a/packages/publish/src/main.ts b/packages/publish/src/main.ts index c962bf7..1ac75a5 100644 --- a/packages/publish/src/main.ts +++ b/packages/publish/src/main.ts @@ -23,7 +23,7 @@ export const createCommand = async () => { }; /** 作为子命令创建 */ -export const crateAsSubcommand = () => { +export const createAsSubcommand = () => { return createSubcommand({ ...commandCliInfo, ...dispatchCommandAndUsage(true), diff --git a/packages/template/README.md b/packages/template/README.md index 67ab52f..b514f08 100644 --- a/packages/template/README.md +++ b/packages/template/README.md @@ -264,10 +264,10 @@ node es/cli.mjs --help ## 许可证 -MIT © [JustSoSu](https://gitee.com/done-coding) +MIT © [done-coding](https://github.com/done-coding) ## 相关链接 - [主 CLI 工具](https://www.npmjs.com/package/@done-coding/cli) -- [Gitee 仓库](https://gitee.com/done-coding/done-coding-cli) +- [Github 仓库](https://github.com/done-coding/done-coding-cli) - [更新日志](./CHANGELOG.md) diff --git a/packages/template/src/index.ts b/packages/template/src/index.ts index 858f0c2..2cdffba 100644 --- a/packages/template/src/index.ts +++ b/packages/template/src/index.ts @@ -1,5 +1,5 @@ export { handler, compileHandler, batchCompileHandler } from "@/handlers"; -export { crateAsSubcommand } from "./main"; +export { createAsSubcommand } from "./main"; export * from "@/types"; export * from "@/utils/path"; export { getConfigPath } from "@/utils/config"; diff --git a/packages/template/src/main.ts b/packages/template/src/main.ts index 04459ae..be1ecb9 100644 --- a/packages/template/src/main.ts +++ b/packages/template/src/main.ts @@ -23,7 +23,7 @@ export const createCommand = async () => { }; /** 作为子命令创建 */ -export const crateAsSubcommand = () => { +export const createAsSubcommand = () => { return createSubcommand({ ...commandCliInfo, ...dispatchCommandAndUsage(true), diff --git a/packages/utils/README.md b/packages/utils/README.md index 55bc005..7d53363 100644 --- a/packages/utils/README.md +++ b/packages/utils/README.md @@ -100,10 +100,10 @@ pnpm build ## 许可证 -MIT © [JustSoSu](https://gitee.com/done-coding) +MIT © [done-coding](https://github.com/done-coding) ## 相关链接 - [主 CLI 工具](https://www.npmjs.com/package/@done-coding/cli) -- [Gitee 仓库](https://gitee.com/done-coding/done-coding-cli) +- [Github 仓库](https://github.com/done-coding/done-coding-cli) - [更新日志](./CHANGELOG.md) diff --git a/packages/utils/src/cli-config.ts b/packages/utils/src/cli-config.ts index 5ba5be1..38f9b7b 100644 --- a/packages/utils/src/cli-config.ts +++ b/packages/utils/src/cli-config.ts @@ -15,6 +15,16 @@ import { uuidv4 } from "@/uuid"; import { outputConsole } from "@/env-config"; import { execSyncHijack } from "@/process"; +/** AI 对话配置 */ +export interface AiConfig { + /** 模型名称,如 "deepseek-chat" */ + model: string; + /** API Key */ + apiKey: string; + /** API Base URL,如 "https://api.deepseek.com" */ + baseUrl: string; +} + /** done-coding-cli 全局配置 key 枚举 */ export enum DoneCodingCliGlobalConfigKeyEnum { /** @@ -24,12 +34,15 @@ export enum DoneCodingCliGlobalConfigKeyEnum { * 2. 若非上述 则认为本地【绝对】路径 */ ASSETS_CONFIG_REPO_URL = "ASSETS_CONFIG_REPO_URL", + /** AI 对话配置 */ + AI_CONFIG = "AI_CONFIG", } /** done-coding-cli 全局配置 */ -export type DoneCodingCliGlobalConfig = { - [K in DoneCodingCliGlobalConfigKeyEnum]: string; -}; +export interface DoneCodingCliGlobalConfig { + [DoneCodingCliGlobalConfigKeyEnum.ASSETS_CONFIG_REPO_URL]: string; + [DoneCodingCliGlobalConfigKeyEnum.AI_CONFIG]?: AiConfig; +} /** 获取cli模块【临时】目录[绝对路径] */ export const getCliModuleTempDir = (moduleName: string) => { @@ -40,18 +53,19 @@ export const getCliModuleTempDir = (moduleName: string) => { ); }; -/** 【全局】获取全局配置文件目录 */ -const getGlobalConfigJsonFilePath = () => { +/** 【全局】获取全局配置文件路径 */ +export const getGlobalConfigFilePath = () => { return path.resolve(homedir(), DONE_CODING_CLI_GLOBAL_CONFIG_RELATIVE_PATH); }; /** 获取全局配置文件 */ const getGlobalConfig = async (): Promise => { - const filePath = getGlobalConfigJsonFilePath(); + const filePath = getGlobalConfigFilePath(); const config: DoneCodingCliGlobalConfig = { [DoneCodingCliGlobalConfigKeyEnum.ASSETS_CONFIG_REPO_URL]: ASSETS_CONFIG_REPO_URL_DEFAULT, + [DoneCodingCliGlobalConfigKeyEnum.AI_CONFIG]: undefined, }; try { if (await assetIsExitsAsync(filePath)) { @@ -59,7 +73,7 @@ const getGlobalConfig = async (): Promise => { Partial >(filePath, {}); Object.entries(fileConfig).forEach(([key, value]) => { - config[key as DoneCodingCliGlobalConfigKeyEnum] = value; + (config as any)[key] = value; }); } } catch (error) {} diff --git a/packages/utils/src/cli.ts b/packages/utils/src/cli.ts index b34b923..2801d32 100644 --- a/packages/utils/src/cli.ts +++ b/packages/utils/src/cli.ts @@ -196,3 +196,11 @@ export const createSubcommand = (cliInfo: SubCliInfo): CommandModule => { handler, }; }; + +/** 包装默认子命令 */ +export const packDefaultCommandCliInfo = (cliInfo: SubCliInfo): SubCliInfo => { + return { + ...cliInfo, + command: `$0`, + }; +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5c5d6f5..6760cab 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -25,12 +25,6 @@ importers: "@typescript-eslint/parser": specifier: ^7.7.0 version: 7.18.0(eslint@8.51.0)(typescript@5.8.3) - conventional-changelog: - specifier: ^5.1.0 - version: 5.1.0 - conventional-changelog-cli: - specifier: ^4.1.0 - version: 4.1.0 eslint: specifier: ^8.49.0 version: 8.51.0 @@ -59,8 +53,48 @@ importers: specifier: ^5.8.3 version: 5.8.3 + packages/ai: + dependencies: + "@done-coding/cli-utils": + specifier: workspace:0.8.4 + version: link:../utils + openai: + specifier: ^4.77.0 + version: 4.104.0(encoding@0.1.13) + devDependencies: + "@done-coding/cli-inject": + specifier: workspace:0.5.23 + version: link:../inject + "@types/node": + specifier: ^18.0.0 + version: 18.19.4 + "@types/prompts": + specifier: ^2.4.6 + version: 2.4.9 + "@types/yargs": + specifier: ^17.0.28 + version: 17.0.33 + "@vitest/coverage-v8": + specifier: ^1.6.1 + version: 1.6.1(vitest@1.6.1(@types/node@18.19.4)(less@4.5.1)(terser@5.46.0)) + typescript: + specifier: ^5.8.3 + version: 5.8.3 + vite: + specifier: ^5.0.10 + version: 5.4.21(@types/node@18.19.4)(less@4.5.1)(terser@5.46.0) + vite-plugin-dts: + specifier: ^3.7.0 + version: 3.7.0(@types/node@18.19.4)(rollup@4.48.1)(typescript@5.8.3)(vite@5.4.21(@types/node@18.19.4)(less@4.5.1)(terser@5.46.0)) + vitest: + specifier: ^1.6.1 + version: 1.6.1(@types/node@18.19.4)(less@4.5.1)(terser@5.46.0) + packages/cli: dependencies: + "@done-coding/cli-ai": + specifier: workspace:0.0.0 + version: link:../ai "@done-coding/cli-component": specifier: workspace:0.4.12 version: link:../component @@ -86,7 +120,7 @@ importers: specifier: workspace:0.8.4 version: link:../utils create-done-coding: - specifier: workspace:0.11.26 + specifier: workspace:0.11.27-alpha.0 version: link:../create devDependencies: "@types/node": @@ -461,6 +495,13 @@ packages: } engines: { node: ">=0.10.0" } + "@ampproject/remapping@2.3.0": + resolution: + { + integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==, + } + engines: { node: ">=6.0.0" } + "@babel/code-frame@7.28.6": resolution: { @@ -586,6 +627,12 @@ packages: } engines: { node: ">=6.9.0" } + "@bcoe/v8-coverage@0.2.3": + resolution: + { + integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==, + } + "@commitlint/cli@16.3.0": resolution: { @@ -745,6 +792,15 @@ packages: integrity: sha512-jKMi1aU6fzCC/VxXVVV7bD2DsQwbW10ZxvnDGmLSVQAW1iiY4Vgis3OVEWnJj4nMutlLdlbcbl8600bYsN2Jww==, } + "@esbuild/aix-ppc64@0.21.5": + resolution: + { + integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==, + } + engines: { node: ">=12" } + cpu: [ppc64] + os: [aix] + "@esbuild/android-arm64@0.18.20": resolution: { @@ -754,6 +810,15 @@ packages: cpu: [arm64] os: [android] + "@esbuild/android-arm64@0.21.5": + resolution: + { + integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==, + } + engines: { node: ">=12" } + cpu: [arm64] + os: [android] + "@esbuild/android-arm@0.18.20": resolution: { @@ -763,6 +828,15 @@ packages: cpu: [arm] os: [android] + "@esbuild/android-arm@0.21.5": + resolution: + { + integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==, + } + engines: { node: ">=12" } + cpu: [arm] + os: [android] + "@esbuild/android-x64@0.18.20": resolution: { @@ -772,6 +846,15 @@ packages: cpu: [x64] os: [android] + "@esbuild/android-x64@0.21.5": + resolution: + { + integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==, + } + engines: { node: ">=12" } + cpu: [x64] + os: [android] + "@esbuild/darwin-arm64@0.18.20": resolution: { @@ -781,6 +864,15 @@ packages: cpu: [arm64] os: [darwin] + "@esbuild/darwin-arm64@0.21.5": + resolution: + { + integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==, + } + engines: { node: ">=12" } + cpu: [arm64] + os: [darwin] + "@esbuild/darwin-x64@0.18.20": resolution: { @@ -790,6 +882,15 @@ packages: cpu: [x64] os: [darwin] + "@esbuild/darwin-x64@0.21.5": + resolution: + { + integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==, + } + engines: { node: ">=12" } + cpu: [x64] + os: [darwin] + "@esbuild/freebsd-arm64@0.18.20": resolution: { @@ -799,6 +900,15 @@ packages: cpu: [arm64] os: [freebsd] + "@esbuild/freebsd-arm64@0.21.5": + resolution: + { + integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==, + } + engines: { node: ">=12" } + cpu: [arm64] + os: [freebsd] + "@esbuild/freebsd-x64@0.18.20": resolution: { @@ -808,6 +918,15 @@ packages: cpu: [x64] os: [freebsd] + "@esbuild/freebsd-x64@0.21.5": + resolution: + { + integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==, + } + engines: { node: ">=12" } + cpu: [x64] + os: [freebsd] + "@esbuild/linux-arm64@0.18.20": resolution: { @@ -817,6 +936,15 @@ packages: cpu: [arm64] os: [linux] + "@esbuild/linux-arm64@0.21.5": + resolution: + { + integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==, + } + engines: { node: ">=12" } + cpu: [arm64] + os: [linux] + "@esbuild/linux-arm@0.18.20": resolution: { @@ -826,6 +954,15 @@ packages: cpu: [arm] os: [linux] + "@esbuild/linux-arm@0.21.5": + resolution: + { + integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==, + } + engines: { node: ">=12" } + cpu: [arm] + os: [linux] + "@esbuild/linux-ia32@0.18.20": resolution: { @@ -835,6 +972,15 @@ packages: cpu: [ia32] os: [linux] + "@esbuild/linux-ia32@0.21.5": + resolution: + { + integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==, + } + engines: { node: ">=12" } + cpu: [ia32] + os: [linux] + "@esbuild/linux-loong64@0.18.20": resolution: { @@ -844,6 +990,15 @@ packages: cpu: [loong64] os: [linux] + "@esbuild/linux-loong64@0.21.5": + resolution: + { + integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==, + } + engines: { node: ">=12" } + cpu: [loong64] + os: [linux] + "@esbuild/linux-mips64el@0.18.20": resolution: { @@ -853,6 +1008,15 @@ packages: cpu: [mips64el] os: [linux] + "@esbuild/linux-mips64el@0.21.5": + resolution: + { + integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==, + } + engines: { node: ">=12" } + cpu: [mips64el] + os: [linux] + "@esbuild/linux-ppc64@0.18.20": resolution: { @@ -862,6 +1026,15 @@ packages: cpu: [ppc64] os: [linux] + "@esbuild/linux-ppc64@0.21.5": + resolution: + { + integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==, + } + engines: { node: ">=12" } + cpu: [ppc64] + os: [linux] + "@esbuild/linux-riscv64@0.18.20": resolution: { @@ -871,6 +1044,15 @@ packages: cpu: [riscv64] os: [linux] + "@esbuild/linux-riscv64@0.21.5": + resolution: + { + integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==, + } + engines: { node: ">=12" } + cpu: [riscv64] + os: [linux] + "@esbuild/linux-s390x@0.18.20": resolution: { @@ -880,6 +1062,15 @@ packages: cpu: [s390x] os: [linux] + "@esbuild/linux-s390x@0.21.5": + resolution: + { + integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==, + } + engines: { node: ">=12" } + cpu: [s390x] + os: [linux] + "@esbuild/linux-x64@0.18.20": resolution: { @@ -889,6 +1080,15 @@ packages: cpu: [x64] os: [linux] + "@esbuild/linux-x64@0.21.5": + resolution: + { + integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==, + } + engines: { node: ">=12" } + cpu: [x64] + os: [linux] + "@esbuild/netbsd-x64@0.18.20": resolution: { @@ -898,6 +1098,15 @@ packages: cpu: [x64] os: [netbsd] + "@esbuild/netbsd-x64@0.21.5": + resolution: + { + integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==, + } + engines: { node: ">=12" } + cpu: [x64] + os: [netbsd] + "@esbuild/openbsd-x64@0.18.20": resolution: { @@ -907,6 +1116,15 @@ packages: cpu: [x64] os: [openbsd] + "@esbuild/openbsd-x64@0.21.5": + resolution: + { + integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==, + } + engines: { node: ">=12" } + cpu: [x64] + os: [openbsd] + "@esbuild/sunos-x64@0.18.20": resolution: { @@ -916,6 +1134,15 @@ packages: cpu: [x64] os: [sunos] + "@esbuild/sunos-x64@0.21.5": + resolution: + { + integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==, + } + engines: { node: ">=12" } + cpu: [x64] + os: [sunos] + "@esbuild/win32-arm64@0.18.20": resolution: { @@ -925,6 +1152,15 @@ packages: cpu: [arm64] os: [win32] + "@esbuild/win32-arm64@0.21.5": + resolution: + { + integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==, + } + engines: { node: ">=12" } + cpu: [arm64] + os: [win32] + "@esbuild/win32-ia32@0.18.20": resolution: { @@ -934,6 +1170,15 @@ packages: cpu: [ia32] os: [win32] + "@esbuild/win32-ia32@0.21.5": + resolution: + { + integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==, + } + engines: { node: ">=12" } + cpu: [ia32] + os: [win32] + "@esbuild/win32-x64@0.18.20": resolution: { @@ -943,6 +1188,15 @@ packages: cpu: [x64] os: [win32] + "@esbuild/win32-x64@0.21.5": + resolution: + { + integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==, + } + engines: { node: ">=12" } + cpu: [x64] + os: [win32] + "@eslint-community/eslint-utils@4.4.0": resolution: { @@ -1015,19 +1269,19 @@ packages: } engines: { node: ">=6.9.0" } - "@hutson/parse-repository-url@5.0.0": + "@isaacs/cliui@8.0.2": resolution: { - integrity: sha512-e5+YUKENATs1JgYHMzTr2MW/NDcXGfYFAuOQU8gJgF/kEh4EqKgfGrfLI67bMD4tbhZVlkigz/9YYwWcbOFthg==, + integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==, } - engines: { node: ">=10.13.0" } + engines: { node: ">=12" } - "@isaacs/cliui@8.0.2": + "@istanbuljs/schema@0.1.6": resolution: { - integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==, + integrity: sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==, } - engines: { node: ">=12" } + engines: { node: ">=8" } "@jest/schemas@29.6.3": resolution: @@ -1847,6 +2101,12 @@ packages: integrity: sha512-ZYFzrvyWUNhaPomn80dsMNgMeXxNWZBdkuG/hWlUvXvbdUH8ZERNBGXnU87McuGcWDsyzX2aChCv/SVN348k3A==, } + "@types/node-fetch@2.6.13": + resolution: + { + integrity: sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==, + } + "@types/node@18.19.4": resolution: { @@ -1984,6 +2244,44 @@ packages: } engines: { node: ^18.18.0 || >=20.0.0 } + "@vitest/coverage-v8@1.6.1": + resolution: + { + integrity: sha512-6YeRZwuO4oTGKxD3bijok756oktHSIm3eczVVzNe3scqzuhLwltIF3S9ZL/vwOVIpURmU6SnZhziXXAfw8/Qlw==, + } + peerDependencies: + vitest: 1.6.1 + + "@vitest/expect@1.6.1": + resolution: + { + integrity: sha512-jXL+9+ZNIJKruofqXuuTClf44eSpcHlgj3CiuNihUF3Ioujtmc0zIa3UJOW5RjDK1YLBJZnWBlPuqhYycLioog==, + } + + "@vitest/runner@1.6.1": + resolution: + { + integrity: sha512-3nSnYXkVkf3mXFfE7vVyPmi3Sazhb/2cfZGGs0JRzFsPFvAMBEcrweV1V1GsrstdXeKCTXlJbvnQwGWgEIHmOA==, + } + + "@vitest/snapshot@1.6.1": + resolution: + { + integrity: sha512-WvidQuWAzU2p95u8GAKlRMqMyN1yOJkGHnx3M1PL9Raf7AQ1kwLKg04ADlCa3+OXUZE7BceOhVZiuWAbzCKcUQ==, + } + + "@vitest/spy@1.6.1": + resolution: + { + integrity: sha512-MGcMmpGkZebsMZhbQKkAf9CX5zGvjkBTqf8Zx3ApYWXr3wG+QvEu2eXWfnIIWYSJExIp4V9FCKDEeygzkYrXMw==, + } + + "@vitest/utils@1.6.1": + resolution: + { + integrity: sha512-jOrrUvXM4Av9ZWiG1EajNto0u96kWAhJ1LmPmJhXXQx/32MecEKd10pOLYgS2BQx1TgkGhloPU1ArDW2vvaY6g==, + } + "@volar/language-core@1.11.1": resolution: { @@ -2086,6 +2384,13 @@ packages: } engines: { node: ">=0.4.0" } + acorn-walk@8.3.5: + resolution: + { + integrity: sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==, + } + engines: { node: ">=0.4.0" } + acorn@8.10.0: resolution: { @@ -2308,6 +2613,12 @@ packages: } engines: { node: ">=8" } + assertion-error@1.1.0: + resolution: + { + integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==, + } + astral-regex@2.0.0: resolution: { @@ -2455,6 +2766,13 @@ packages: } engines: { node: ">=12.17" } + cac@6.7.14: + resolution: + { + integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==, + } + engines: { node: ">=8" } + cacache@16.1.3: resolution: { @@ -2517,6 +2835,13 @@ packages: integrity: sha512-9JGuzl2M+vPL+pz70gtMF9sHdMFbY9FJaQBi186cHKH3pSzDvzoUJUPV6fqiKIMyXbud9ZLg4F3Yza1vJ1+93g==, } + chai@4.5.0: + resolution: + { + integrity: sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==, + } + engines: { node: ">=4" } + chalk@4.1.0: resolution: { @@ -2544,6 +2869,12 @@ packages: integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==, } + check-error@1.0.3: + resolution: + { + integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==, + } + chownr@2.0.0: resolution: { @@ -2740,45 +3071,29 @@ packages: } engines: { "0": node >= 6.0 } - console-control-strings@1.1.0: + confbox@0.1.8: resolution: { - integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==, + integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==, } - conventional-changelog-angular@5.0.13: - resolution: - { - integrity: sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==, - } - engines: { node: ">=10" } - - conventional-changelog-angular@7.0.0: - resolution: - { - integrity: sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==, - } - engines: { node: ">=16" } - - conventional-changelog-atom@4.0.0: + console-control-strings@1.1.0: resolution: { - integrity: sha512-q2YtiN7rnT1TGwPTwjjBSIPIzDJCRE+XAUahWxnh+buKK99Kks4WLMHoexw38GXx9OUxAsrp44f9qXe5VEMYhw==, + integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==, } - engines: { node: ">=16" } - conventional-changelog-cli@4.1.0: + conventional-changelog-angular@5.0.13: resolution: { - integrity: sha512-MscvILWZ6nWOoC+p/3Nn3D2cVLkjeQjyZPUr0bQ+vUORE/SPrkClJh8BOoMNpS4yk+zFJ5LlgXACxH6XGQoRXA==, + integrity: sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==, } - engines: { node: ">=16" } - hasBin: true + engines: { node: ">=10" } - conventional-changelog-codemirror@4.0.0: + conventional-changelog-angular@7.0.0: resolution: { - integrity: sha512-hQSojc/5imn1GJK3A75m9hEZZhc3urojA5gMpnar4JHmgLnuM3CUIARPpEk86glEKr3c54Po3WV/vCaO/U8g3Q==, + integrity: sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==, } engines: { node: ">=16" } @@ -2789,13 +3104,6 @@ packages: } engines: { node: ">=10" } - conventional-changelog-conventionalcommits@7.0.2: - resolution: - { - integrity: sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==, - } - engines: { node: ">=16" } - conventional-changelog-core@5.0.1: resolution: { @@ -2803,48 +3111,6 @@ packages: } engines: { node: ">=14" } - conventional-changelog-core@7.0.0: - resolution: - { - integrity: sha512-UYgaB1F/COt7VFjlYKVE/9tTzfU3VUq47r6iWf6lM5T7TlOxr0thI63ojQueRLIpVbrtHK4Ffw+yQGduw2Bhdg==, - } - engines: { node: ">=16" } - - conventional-changelog-ember@4.0.0: - resolution: - { - integrity: sha512-D0IMhwcJUg1Y8FSry6XAplEJcljkHVlvAZddhhsdbL1rbsqRsMfGx/PIkPYq0ru5aDgn+OxhQ5N5yR7P9mfsvA==, - } - engines: { node: ">=16" } - - conventional-changelog-eslint@5.0.0: - resolution: - { - integrity: sha512-6JtLWqAQIeJLn/OzUlYmzd9fKeNSWmQVim9kql+v4GrZwLx807kAJl3IJVc3jTYfVKWLxhC3BGUxYiuVEcVjgA==, - } - engines: { node: ">=16" } - - conventional-changelog-express@4.0.0: - resolution: - { - integrity: sha512-yWyy5c7raP9v7aTvPAWzqrztACNO9+FEI1FSYh7UP7YT1AkWgv5UspUeB5v3Ibv4/o60zj2o9GF2tqKQ99lIsw==, - } - engines: { node: ">=16" } - - conventional-changelog-jquery@5.0.0: - resolution: - { - integrity: sha512-slLjlXLRNa/icMI3+uGLQbtrgEny3RgITeCxevJB+p05ExiTgHACP5p3XiMKzjBn80n+Rzr83XMYfRInEtCPPw==, - } - engines: { node: ">=16" } - - conventional-changelog-jshint@4.0.0: - resolution: - { - integrity: sha512-LyXq1bbl0yG0Ai1SbLxIk8ZxUOe3AjnlwE6sVRQmMgetBk+4gY9EO3d00zlEt8Y8gwsITytDnPORl8al7InTjg==, - } - engines: { node: ">=16" } - conventional-changelog-preset-loader@3.0.0: resolution: { @@ -2852,13 +3118,6 @@ packages: } engines: { node: ">=14" } - conventional-changelog-preset-loader@4.1.0: - resolution: - { - integrity: sha512-HozQjJicZTuRhCRTq4rZbefaiCzRM2pr6u2NL3XhrmQm4RMnDXfESU6JKu/pnKwx5xtdkYfNCsbhN5exhiKGJA==, - } - engines: { node: ">=16" } - conventional-changelog-writer@6.0.1: resolution: { @@ -2867,21 +3126,6 @@ packages: engines: { node: ">=14" } hasBin: true - conventional-changelog-writer@7.0.1: - resolution: - { - integrity: sha512-Uo+R9neH3r/foIvQ0MKcsXkX642hdm9odUp7TqgFS7BsalTcjzRlIfWZrZR1gbxOozKucaKt5KAbjW8J8xRSmA==, - } - engines: { node: ">=16" } - hasBin: true - - conventional-changelog@5.1.0: - resolution: - { - integrity: sha512-aWyE/P39wGYRPllcCEZDxTVEmhyLzTc9XA6z6rVfkuCD2UBnhV/sgSOKbQrEG5z9mEZJjnopjgQooTKxEg8mAg==, - } - engines: { node: ">=16" } - conventional-commits-filter@3.0.0: resolution: { @@ -2889,13 +3133,6 @@ packages: } engines: { node: ">=14" } - conventional-commits-filter@4.0.0: - resolution: - { - integrity: sha512-rnpnibcSOdFcdclpFwWa+pPlZJhXE7l+XK04zxhbWrhgpR96h33QLz8hITTXbcYICxVr3HZFtbtUAQ+4LdBo9A==, - } - engines: { node: ">=16" } - conventional-commits-parser@3.2.4: resolution: { @@ -2912,14 +3149,6 @@ packages: engines: { node: ">=14" } hasBin: true - conventional-commits-parser@5.0.0: - resolution: - { - integrity: sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==, - } - engines: { node: ">=16" } - hasBin: true - conventional-recommended-bump@7.0.1: resolution: { @@ -3011,13 +3240,6 @@ packages: } engines: { node: ">=8" } - dargs@8.1.0: - resolution: - { - integrity: sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==, - } - engines: { node: ">=12" } - data-view-buffer@1.0.2: resolution: { @@ -3112,6 +3334,13 @@ packages: integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==, } + deep-eql@4.1.4: + resolution: + { + integrity: sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==, + } + engines: { node: ">=6" } + deep-is@0.1.4: resolution: { @@ -3396,6 +3625,14 @@ packages: engines: { node: ">=12" } hasBin: true + esbuild@0.21.5: + resolution: + { + integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==, + } + engines: { node: ">=12" } + hasBin: true + escalade@3.1.1: resolution: { @@ -3604,6 +3841,12 @@ packages: integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==, } + estree-walker@3.0.3: + resolution: + { + integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==, + } + esutils@2.0.3: resolution: { @@ -3645,6 +3888,13 @@ packages: } engines: { node: ">=10" } + execa@8.0.1: + resolution: + { + integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==, + } + engines: { node: ">=16.17" } + exponential-backoff@3.1.1: resolution: { @@ -3744,13 +3994,6 @@ packages: } engines: { node: ">=10" } - find-up@6.3.0: - resolution: - { - integrity: sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==, - } - engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } - flat-cache@3.1.1: resolution: { @@ -3797,6 +4040,12 @@ packages: } engines: { node: ">=14" } + form-data-encoder@1.7.2: + resolution: + { + integrity: sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==, + } + form-data@4.0.0: resolution: { @@ -3804,6 +4053,20 @@ packages: } engines: { node: ">= 6" } + form-data@4.0.5: + resolution: + { + integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==, + } + engines: { node: ">= 6" } + + formdata-node@4.4.1: + resolution: + { + integrity: sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==, + } + engines: { node: ">= 12.20" } + fs-constants@1.0.0: resolution: { @@ -3915,6 +4178,12 @@ packages: } engines: { node: 6.* || 8.* || >= 10.* } + get-func-name@2.0.2: + resolution: + { + integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==, + } + get-intrinsic@1.3.0: resolution: { @@ -3958,6 +4227,13 @@ packages: } engines: { node: ">=10" } + get-stream@8.0.1: + resolution: + { + integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==, + } + engines: { node: ">=16" } + get-symbol-description@1.1.0: resolution: { @@ -3981,14 +4257,6 @@ packages: engines: { node: ">=14" } hasBin: true - git-raw-commits@4.0.0: - resolution: - { - integrity: sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==, - } - engines: { node: ">=16" } - hasBin: true - git-remote-origin-url@2.0.0: resolution: { @@ -4004,14 +4272,6 @@ packages: engines: { node: ">=14" } hasBin: true - git-semver-tags@7.0.1: - resolution: - { - integrity: sha512-NY0ZHjJzyyNXHTDZmj+GG7PyuAKtMsyWSwh07CR2hOZFa+/yoTsXci/nF2obzL8UDhakFNkD9gNdt/Ed+cxh2Q==, - } - engines: { node: ">=16" } - hasBin: true - git-up@7.0.0: resolution: { @@ -4247,12 +4507,11 @@ packages: } engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } - hosted-git-info@7.0.1: + html-escaper@2.0.2: resolution: { - integrity: sha512-+K84LB1DYwMHoHSgaOY/Jfhw3ucPmSET5v98Ke/HdNSw4a0UktWzyW1mjhjpuxxTqOOsfWT/7iVshHmVZ4IpOA==, + integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==, } - engines: { node: ^16.14.0 || >=18.0.0 } http-cache-semantics@4.1.1: resolution: @@ -4281,6 +4540,13 @@ packages: } engines: { node: ">=10.17.0" } + human-signals@5.0.0: + resolution: + { + integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==, + } + engines: { node: ">=16.17.0" } + humanize-ms@1.2.1: resolution: { @@ -4681,6 +4947,13 @@ packages: } engines: { node: ">=8" } + is-stream@3.0.0: + resolution: + { + integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==, + } + engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } + is-string@1.1.1: resolution: { @@ -4702,13 +4975,6 @@ packages: } engines: { node: ">=0.10.0" } - is-text-path@2.0.0: - resolution: - { - integrity: sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==, - } - engines: { node: ">=8" } - is-typed-array@1.1.15: resolution: { @@ -4782,6 +5048,34 @@ packages: } engines: { node: ">=0.10.0" } + istanbul-lib-coverage@3.2.2: + resolution: + { + integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==, + } + engines: { node: ">=8" } + + istanbul-lib-report@3.0.1: + resolution: + { + integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==, + } + engines: { node: ">=10" } + + istanbul-lib-source-maps@5.0.6: + resolution: + { + integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==, + } + engines: { node: ">=10" } + + istanbul-reports@3.2.0: + resolution: + { + integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==, + } + engines: { node: ">=8" } + jackspeak@2.3.6: resolution: { @@ -4823,6 +5117,12 @@ packages: integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==, } + js-tokens@9.0.1: + resolution: + { + integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==, + } + js-yaml@3.14.1: resolution: { @@ -5058,6 +5358,13 @@ packages: } engines: { node: ">=8" } + local-pkg@0.5.1: + resolution: + { + integrity: sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==, + } + engines: { node: ">=14" } + locate-path@2.0.0: resolution: { @@ -5079,13 +5386,6 @@ packages: } engines: { node: ">=10" } - locate-path@7.2.0: - resolution: - { - integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==, - } - engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } - lodash._reinterpolate@3.0.0: resolution: { @@ -5200,6 +5500,12 @@ packages: } engines: { node: ">=10" } + loupe@2.3.7: + resolution: + { + integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==, + } + lru-cache@10.4.3: resolution: { @@ -5226,6 +5532,18 @@ packages: } engines: { node: ">=12" } + magic-string@0.30.21: + resolution: + { + integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==, + } + + magicast@0.3.5: + resolution: + { + integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==, + } + make-dir@2.1.0: resolution: { @@ -5288,13 +5606,6 @@ packages: } engines: { node: ">= 0.4" } - meow@12.1.1: - resolution: - { - integrity: sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==, - } - engines: { node: ">=16.10" } - meow@8.1.2: resolution: { @@ -5351,6 +5662,13 @@ packages: } engines: { node: ">=6" } + mimic-fn@4.0.0: + resolution: + { + integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==, + } + engines: { node: ">=12" } + min-indent@1.0.1: resolution: { @@ -5495,6 +5813,12 @@ packages: engines: { node: ">=10" } hasBin: true + mlly@1.8.2: + resolution: + { + integrity: sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==, + } + modify-values@1.0.1: resolution: { @@ -5540,6 +5864,14 @@ packages: } engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + nanoid@3.3.11: + resolution: + { + integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==, + } + engines: { node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1 } + hasBin: true + nanoid@3.3.7: resolution: { @@ -5581,6 +5913,14 @@ packages: integrity: sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==, } + node-domexception@1.0.0: + resolution: + { + integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==, + } + engines: { node: ">=10.5.0" } + deprecated: Use your platform's native DOMException instead + node-fetch@2.6.7: resolution: { @@ -5675,13 +6015,6 @@ packages: } engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } - normalize-package-data@6.0.0: - resolution: - { - integrity: sha512-UL7ELRVxYBHBgYEtZCXjxuD5vPxnmvMGq0jp/dGPKKrN7tfsBh2IY7TlJ15WWwdjRWD3RJbnsygUurTK3xkPkg==, - } - engines: { node: ^16.14.0 || >=18.0.0 } - normalize-path@3.0.0: resolution: { @@ -5772,6 +6105,13 @@ packages: } engines: { node: ">=8" } + npm-run-path@5.3.0: + resolution: + { + integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==, + } + engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } + npmlog@5.0.1: resolution: { @@ -5883,6 +6223,13 @@ packages: } engines: { node: ">=6" } + onetime@6.0.0: + resolution: + { + integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==, + } + engines: { node: ">=12" } + open@8.4.2: resolution: { @@ -5890,6 +6237,21 @@ packages: } engines: { node: ">=12" } + openai@4.104.0: + resolution: + { + integrity: sha512-p99EFNsA/yX6UhVO93f5kJsDRLAg+CTA2RBqdHK4RtK8u5IJw32Hyb2dTGKbnnFmnuoBv5r7Z2CURI9sGZpSuA==, + } + hasBin: true + peerDependencies: + ws: ^8.18.0 + zod: ^3.23.8 + peerDependenciesMeta: + ws: + optional: true + zod: + optional: true + optionator@0.9.3: resolution: { @@ -5946,12 +6308,12 @@ packages: } engines: { node: ">=10" } - p-limit@4.0.0: + p-limit@5.0.0: resolution: { - integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==, + integrity: sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==, } - engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } + engines: { node: ">=18" } p-locate@2.0.0: resolution: @@ -5974,13 +6336,6 @@ packages: } engines: { node: ">=10" } - p-locate@6.0.0: - resolution: - { - integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==, - } - engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } - p-map-series@2.1.0: resolution: { @@ -6073,13 +6428,6 @@ packages: } engines: { node: ">=8" } - parse-json@7.1.1: - resolution: - { - integrity: sha512-SgOTCX/EZXtZxBE5eJ97P4yGM5n37BwRU+YMsH4vNzFqJV/oWFXXCmwFlgWUM4PrakybVOueJJ6pwHqSVhTFDw==, - } - engines: { node: ">=16" } - parse-node-version@1.0.1: resolution: { @@ -6119,13 +6467,6 @@ packages: } engines: { node: ">=8" } - path-exists@5.0.0: - resolution: - { - integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==, - } - engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } - path-is-absolute@1.0.1: resolution: { @@ -6140,6 +6481,13 @@ packages: } engines: { node: ">=8" } + path-key@4.0.0: + resolution: + { + integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==, + } + engines: { node: ">=12" } + path-parse@1.0.7: resolution: { @@ -6167,6 +6515,24 @@ packages: } engines: { node: ">=8" } + pathe@1.1.2: + resolution: + { + integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==, + } + + pathe@2.0.3: + resolution: + { + integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==, + } + + pathval@1.1.1: + resolution: + { + integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==, + } + picocolors@1.0.0: resolution: { @@ -6255,6 +6621,12 @@ packages: } engines: { node: ">=8" } + pkg-types@1.3.1: + resolution: + { + integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==, + } + possible-typed-array-names@1.1.0: resolution: { @@ -6276,6 +6648,13 @@ packages: } engines: { node: ^10 || ^12 || >=14 } + postcss@8.5.10: + resolution: + { + integrity: sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==, + } + engines: { node: ^10 || ^12 || >=14 } + prelude-ls@1.2.1: resolution: { @@ -6439,13 +6818,6 @@ packages: engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } deprecated: This package is no longer supported. Please use @npmcli/package-json instead. - read-pkg-up@10.1.0: - resolution: - { - integrity: sha512-aNtBq4jR8NawpKJQldrQcSW9y/d+KWH4v24HWkHljOZ7H0av+YTGANBzRh9A5pw7v/bLVsLVPpOhJ7gHNVy8lA==, - } - engines: { node: ">=16" } - read-pkg-up@3.0.0: resolution: { @@ -6474,13 +6846,6 @@ packages: } engines: { node: ">=8" } - read-pkg@8.1.0: - resolution: - { - integrity: sha512-PORM8AgzXeskHO/WEv312k9U03B8K9JSiWF/8N9sUuFjBa+9SF2u6K7VClzXwDXab51jCd8Nd36CNM+zR97ScQ==, - } - engines: { node: ">=16" } - read@2.1.0: resolution: { @@ -6858,6 +7223,12 @@ packages: } engines: { node: ">= 0.4" } + siginfo@2.0.0: + resolution: + { + integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==, + } + signal-exit@3.0.7: resolution: { @@ -7037,6 +7408,18 @@ packages: } engines: { node: ^12.13.0 || ^14.15.0 || >=16.0.0 } + stackback@0.0.2: + resolution: + { + integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==, + } + + std-env@3.10.0: + resolution: + { + integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==, + } + stop-iteration-iterator@1.1.0: resolution: { @@ -7133,6 +7516,13 @@ packages: } engines: { node: ">=6" } + strip-final-newline@3.0.0: + resolution: + { + integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==, + } + engines: { node: ">=12" } + strip-indent@3.0.0: resolution: { @@ -7147,6 +7537,12 @@ packages: } engines: { node: ">=8" } + strip-literal@2.1.1: + resolution: + { + integrity: sha512-631UJ6O00eNGfMiWG78ck80dfBab8X6IVFB51jZK5Icd7XAs60Z5y7QdSd/wGIklnWvRbUNloVzhOKKmutxQ6Q==, + } + strong-log-transformer@2.1.0: resolution: { @@ -7206,20 +7602,6 @@ packages: } engines: { node: ">=4" } - temp-dir@3.0.0: - resolution: - { - integrity: sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==, - } - engines: { node: ">=14.16" } - - tempfile@5.0.0: - resolution: - { - integrity: sha512-bX655WZI/F7EoTDw9JvQURqAXiPHi8o8+yFxPF2lWYyz1aHnmMRuXWqL6YB6GmeO0o4DIYWHLgGNi/X64T+X4Q==, - } - engines: { node: ">=14.18" } - terser@5.46.0: resolution: { @@ -7228,19 +7610,19 @@ packages: engines: { node: ">=10" } hasBin: true - text-extensions@1.9.0: + test-exclude@6.0.0: resolution: { - integrity: sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==, + integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==, } - engines: { node: ">=0.10" } + engines: { node: ">=8" } - text-extensions@2.4.0: + text-extensions@1.9.0: resolution: { - integrity: sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==, + integrity: sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==, } - engines: { node: ">=8" } + engines: { node: ">=0.10" } text-table@0.2.0: resolution: @@ -7272,6 +7654,26 @@ packages: integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==, } + tinybench@2.9.0: + resolution: + { + integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==, + } + + tinypool@0.8.4: + resolution: + { + integrity: sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==, + } + engines: { node: ">=14.0.0" } + + tinyspy@2.2.1: + resolution: + { + integrity: sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==, + } + engines: { node: ">=14.0.0" } + tmp@0.0.33: resolution: { @@ -7365,6 +7767,13 @@ packages: } engines: { node: ">= 0.8.0" } + type-detect@4.1.0: + resolution: + { + integrity: sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==, + } + engines: { node: ">=4" } + type-fest@0.18.1: resolution: { @@ -7407,20 +7816,6 @@ packages: } engines: { node: ">=8" } - type-fest@3.13.1: - resolution: - { - integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==, - } - engines: { node: ">=14.16" } - - type-fest@4.9.0: - resolution: - { - integrity: sha512-KS/6lh/ynPGiHD/LnAobrEFq3Ad4pBzOlJ1wAnJx9N4EYoqFhMfLIBjUT2UEx4wg5ZE+cC1ob6DCSpppVo+rtg==, - } - engines: { node: ">=16" } - typed-array-buffer@1.0.3: resolution: { @@ -7479,6 +7874,12 @@ packages: engines: { node: ">=14.17" } hasBin: true + ufo@1.6.3: + resolution: + { + integrity: sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==, + } + uglify-js@3.17.4: resolution: { @@ -7621,6 +8022,14 @@ packages: } engines: { node: ">= 0.10" } + vite-node@1.6.1: + resolution: + { + integrity: sha512-YAXkfvGtuTzwWbDSACdJSg4A4DZiAqckWe90Zapc/sEX3XvHcw1NdurM/6od8J207tSDqNbSsgdCacBgvJKFuA==, + } + engines: { node: ^18.0.0 || >=20.0.0 } + hasBin: true + vite-plugin-dts@3.7.0: resolution: { @@ -7665,6 +8074,68 @@ packages: terser: optional: true + vite@5.4.21: + resolution: + { + integrity: sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==, + } + engines: { node: ^18.0.0 || >=20.0.0 } + hasBin: true + peerDependencies: + "@types/node": ^18.0.0 || >=20.0.0 + less: "*" + lightningcss: ^1.21.0 + sass: "*" + sass-embedded: "*" + stylus: "*" + sugarss: "*" + terser: ^5.4.0 + peerDependenciesMeta: + "@types/node": + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + + vitest@1.6.1: + resolution: + { + integrity: sha512-Ljb1cnSJSivGN0LqXd/zmDbWEM0RNNg2t1QW/XUhYl/qPqyu7CsqeWtqQXHVaJsecLPuDoak2oJcZN2QoRIOag==, + } + engines: { node: ^18.0.0 || >=20.0.0 } + hasBin: true + peerDependencies: + "@edge-runtime/vm": "*" + "@types/node": ^18.0.0 || >=20.0.0 + "@vitest/browser": 1.6.1 + "@vitest/ui": 1.6.1 + happy-dom: "*" + jsdom: "*" + peerDependenciesMeta: + "@edge-runtime/vm": + optional: true + "@types/node": + optional: true + "@vitest/browser": + optional: true + "@vitest/ui": + optional: true + happy-dom: + optional: true + jsdom: + optional: true + vue-eslint-parser@9.4.3: resolution: { @@ -7695,6 +8166,13 @@ packages: integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==, } + web-streams-polyfill@4.0.0-beta.3: + resolution: + { + integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==, + } + engines: { node: ">= 14" } + webidl-conversions@3.0.1: resolution: { @@ -7751,6 +8229,14 @@ packages: engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } hasBin: true + why-is-node-running@2.3.0: + resolution: + { + integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==, + } + engines: { node: ">=8" } + hasBin: true + wide-align@1.1.5: resolution: { @@ -7906,10 +8392,10 @@ packages: } engines: { node: ">=10" } - yocto-queue@1.0.0: + yocto-queue@1.2.2: resolution: { - integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==, + integrity: sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==, } engines: { node: ">=12.20" } @@ -7924,6 +8410,11 @@ packages: snapshots: "@aashutoshrathi/word-wrap@1.2.6": {} + "@ampproject/remapping@2.3.0": + dependencies: + "@jridgewell/gen-mapping": 0.3.13 + "@jridgewell/trace-mapping": 0.3.31 + "@babel/code-frame@7.28.6": dependencies: "@babel/helper-validator-identifier": 7.28.5 @@ -8044,6 +8535,8 @@ snapshots: "@babel/helper-string-parser": 7.27.1 "@babel/helper-validator-identifier": 7.28.5 + "@bcoe/v8-coverage@0.2.3": {} + "@commitlint/cli@16.3.0": dependencies: "@commitlint/format": 16.2.1 @@ -8177,72 +8670,141 @@ snapshots: lodash.curry: 4.1.1 lodash.omit: 4.5.0 + "@esbuild/aix-ppc64@0.21.5": + optional: true + "@esbuild/android-arm64@0.18.20": optional: true + "@esbuild/android-arm64@0.21.5": + optional: true + "@esbuild/android-arm@0.18.20": optional: true + "@esbuild/android-arm@0.21.5": + optional: true + "@esbuild/android-x64@0.18.20": optional: true + "@esbuild/android-x64@0.21.5": + optional: true + "@esbuild/darwin-arm64@0.18.20": optional: true + "@esbuild/darwin-arm64@0.21.5": + optional: true + "@esbuild/darwin-x64@0.18.20": optional: true + "@esbuild/darwin-x64@0.21.5": + optional: true + "@esbuild/freebsd-arm64@0.18.20": optional: true + "@esbuild/freebsd-arm64@0.21.5": + optional: true + "@esbuild/freebsd-x64@0.18.20": optional: true + "@esbuild/freebsd-x64@0.21.5": + optional: true + "@esbuild/linux-arm64@0.18.20": optional: true + "@esbuild/linux-arm64@0.21.5": + optional: true + "@esbuild/linux-arm@0.18.20": optional: true + "@esbuild/linux-arm@0.21.5": + optional: true + "@esbuild/linux-ia32@0.18.20": optional: true + "@esbuild/linux-ia32@0.21.5": + optional: true + "@esbuild/linux-loong64@0.18.20": optional: true + "@esbuild/linux-loong64@0.21.5": + optional: true + "@esbuild/linux-mips64el@0.18.20": optional: true + "@esbuild/linux-mips64el@0.21.5": + optional: true + "@esbuild/linux-ppc64@0.18.20": optional: true + "@esbuild/linux-ppc64@0.21.5": + optional: true + "@esbuild/linux-riscv64@0.18.20": optional: true + "@esbuild/linux-riscv64@0.21.5": + optional: true + "@esbuild/linux-s390x@0.18.20": optional: true + "@esbuild/linux-s390x@0.21.5": + optional: true + "@esbuild/linux-x64@0.18.20": optional: true + "@esbuild/linux-x64@0.21.5": + optional: true + "@esbuild/netbsd-x64@0.18.20": optional: true + "@esbuild/netbsd-x64@0.21.5": + optional: true + "@esbuild/openbsd-x64@0.18.20": optional: true + "@esbuild/openbsd-x64@0.21.5": + optional: true + "@esbuild/sunos-x64@0.18.20": optional: true + "@esbuild/sunos-x64@0.21.5": + optional: true + "@esbuild/win32-arm64@0.18.20": optional: true + "@esbuild/win32-arm64@0.21.5": + optional: true + "@esbuild/win32-ia32@0.18.20": optional: true + "@esbuild/win32-ia32@0.21.5": + optional: true + "@esbuild/win32-x64@0.18.20": optional: true + "@esbuild/win32-x64@0.21.5": + optional: true + "@eslint-community/eslint-utils@4.4.0(eslint@8.51.0)": dependencies: eslint: 8.51.0 @@ -8284,8 +8846,6 @@ snapshots: "@hutson/parse-repository-url@3.0.2": {} - "@hutson/parse-repository-url@5.0.0": {} - "@isaacs/cliui@8.0.2": dependencies: string-width: 5.1.2 @@ -8295,6 +8855,8 @@ snapshots: wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 + "@istanbuljs/schema@0.1.6": {} + "@jest/schemas@29.6.3": dependencies: "@sinclair/typebox": 0.27.8 @@ -8303,7 +8865,6 @@ snapshots: dependencies: "@jridgewell/sourcemap-codec": 1.5.5 "@jridgewell/trace-mapping": 0.3.31 - optional: true "@jridgewell/remapping@2.3.5": dependencies: @@ -8325,7 +8886,6 @@ snapshots: dependencies: "@jridgewell/resolve-uri": 3.1.1 "@jridgewell/sourcemap-codec": 1.5.5 - optional: true "@jridgewell/trace-mapping@0.3.9": dependencies: @@ -8869,6 +9429,11 @@ snapshots: "@types/minimist@1.2.3": {} + "@types/node-fetch@2.6.13": + dependencies: + "@types/node": 18.19.4 + form-data: 4.0.5 + "@types/node@18.19.4": dependencies: undici-types: 5.26.5 @@ -8977,6 +9542,54 @@ snapshots: "@typescript-eslint/types": 7.18.0 eslint-visitor-keys: 3.4.3 + "@vitest/coverage-v8@1.6.1(vitest@1.6.1(@types/node@18.19.4)(less@4.5.1)(terser@5.46.0))": + dependencies: + "@ampproject/remapping": 2.3.0 + "@bcoe/v8-coverage": 0.2.3 + debug: 4.4.3 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 5.0.6 + istanbul-reports: 3.2.0 + magic-string: 0.30.21 + magicast: 0.3.5 + picocolors: 1.1.1 + std-env: 3.10.0 + strip-literal: 2.1.1 + test-exclude: 6.0.0 + vitest: 1.6.1(@types/node@18.19.4)(less@4.5.1)(terser@5.46.0) + transitivePeerDependencies: + - supports-color + + "@vitest/expect@1.6.1": + dependencies: + "@vitest/spy": 1.6.1 + "@vitest/utils": 1.6.1 + chai: 4.5.0 + + "@vitest/runner@1.6.1": + dependencies: + "@vitest/utils": 1.6.1 + p-limit: 5.0.0 + pathe: 1.1.2 + + "@vitest/snapshot@1.6.1": + dependencies: + magic-string: 0.30.21 + pathe: 1.1.2 + pretty-format: 29.7.0 + + "@vitest/spy@1.6.1": + dependencies: + tinyspy: 2.2.1 + + "@vitest/utils@1.6.1": + dependencies: + diff-sequences: 29.6.3 + estree-walker: 3.0.3 + loupe: 2.3.7 + pretty-format: 29.7.0 + "@volar/language-core@1.11.1": dependencies: "@volar/source-map": 1.11.1 @@ -9047,12 +9660,15 @@ snapshots: acorn-walk@8.2.0: {} + acorn-walk@8.3.5: + dependencies: + acorn: 8.16.0 + acorn@8.10.0: {} acorn@8.15.0: {} - acorn@8.16.0: - optional: true + acorn@8.16.0: {} add-stream@1.0.0: {} @@ -9177,6 +9793,8 @@ snapshots: arrify@2.0.1: {} + assertion-error@1.1.0: {} + astral-regex@2.0.0: {} async-function@1.0.0: {} @@ -9259,6 +9877,8 @@ snapshots: byte-size@8.1.1: {} + cac@6.7.14: {} + cacache@16.1.3: dependencies: "@npmcli/fs": 2.1.2 @@ -9327,6 +9947,16 @@ snapshots: caniuse-lite@1.0.30001764: optional: true + chai@4.5.0: + dependencies: + assertion-error: 1.1.0 + check-error: 1.0.3 + deep-eql: 4.1.4 + get-func-name: 2.0.2 + loupe: 2.3.7 + pathval: 1.1.1 + type-detect: 4.1.0 + chalk@4.1.0: dependencies: ansi-styles: 4.3.0 @@ -9341,6 +9971,10 @@ snapshots: chardet@0.7.0: {} + check-error@1.0.3: + dependencies: + get-func-name: 2.0.2 + chownr@2.0.0: {} ci-info@3.9.0: {} @@ -9437,6 +10071,8 @@ snapshots: readable-stream: 3.6.2 typedarray: 0.0.6 + confbox@0.1.8: {} + console-control-strings@1.1.0: {} conventional-changelog-angular@5.0.13: @@ -9448,27 +10084,12 @@ snapshots: dependencies: compare-func: 2.0.0 - conventional-changelog-atom@4.0.0: {} - - conventional-changelog-cli@4.1.0: - dependencies: - add-stream: 1.0.0 - conventional-changelog: 5.1.0 - meow: 12.1.1 - tempfile: 5.0.0 - - conventional-changelog-codemirror@4.0.0: {} - conventional-changelog-conventionalcommits@4.6.3: dependencies: compare-func: 2.0.0 lodash: 4.17.21 q: 1.5.1 - conventional-changelog-conventionalcommits@7.0.2: - dependencies: - compare-func: 2.0.0 - conventional-changelog-core@5.0.1: dependencies: add-stream: 1.0.0 @@ -9483,35 +10104,8 @@ snapshots: read-pkg: 3.0.0 read-pkg-up: 3.0.0 - conventional-changelog-core@7.0.0: - dependencies: - "@hutson/parse-repository-url": 5.0.0 - add-stream: 1.0.0 - conventional-changelog-writer: 7.0.1 - conventional-commits-parser: 5.0.0 - git-raw-commits: 4.0.0 - git-semver-tags: 7.0.1 - hosted-git-info: 7.0.1 - normalize-package-data: 6.0.0 - read-pkg: 8.1.0 - read-pkg-up: 10.1.0 - - conventional-changelog-ember@4.0.0: {} - - conventional-changelog-eslint@5.0.0: {} - - conventional-changelog-express@4.0.0: {} - - conventional-changelog-jquery@5.0.0: {} - - conventional-changelog-jshint@4.0.0: - dependencies: - compare-func: 2.0.0 - conventional-changelog-preset-loader@3.0.0: {} - conventional-changelog-preset-loader@4.1.0: {} - conventional-changelog-writer@6.0.1: dependencies: conventional-commits-filter: 3.0.0 @@ -9522,36 +10116,11 @@ snapshots: semver: 7.7.3 split: 1.0.1 - conventional-changelog-writer@7.0.1: - dependencies: - conventional-commits-filter: 4.0.0 - handlebars: 4.7.8 - json-stringify-safe: 5.0.1 - meow: 12.1.1 - semver: 7.7.3 - split2: 4.2.0 - - conventional-changelog@5.1.0: - dependencies: - conventional-changelog-angular: 7.0.0 - conventional-changelog-atom: 4.0.0 - conventional-changelog-codemirror: 4.0.0 - conventional-changelog-conventionalcommits: 7.0.2 - conventional-changelog-core: 7.0.0 - conventional-changelog-ember: 4.0.0 - conventional-changelog-eslint: 5.0.0 - conventional-changelog-express: 4.0.0 - conventional-changelog-jquery: 5.0.0 - conventional-changelog-jshint: 4.0.0 - conventional-changelog-preset-loader: 4.1.0 - conventional-commits-filter@3.0.0: dependencies: lodash.ismatch: 4.4.0 modify-values: 1.0.1 - conventional-commits-filter@4.0.0: {} - conventional-commits-parser@3.2.4: dependencies: JSONStream: 1.3.5 @@ -9568,13 +10137,6 @@ snapshots: meow: 8.1.2 split2: 3.2.2 - conventional-commits-parser@5.0.0: - dependencies: - JSONStream: 1.3.5 - is-text-path: 2.0.0 - meow: 12.1.1 - split2: 4.2.0 - conventional-recommended-bump@7.0.1: dependencies: concat-stream: 2.0.0 @@ -9641,8 +10203,6 @@ snapshots: dargs@7.0.0: {} - dargs@8.1.0: {} - data-view-buffer@1.0.2: dependencies: call-bound: 1.0.4 @@ -9690,6 +10250,10 @@ snapshots: dedent@0.7.0: {} + deep-eql@4.1.4: + dependencies: + type-detect: 4.1.0 + deep-is@0.1.4: {} defaults@1.0.4: @@ -9903,6 +10467,32 @@ snapshots: "@esbuild/win32-ia32": 0.18.20 "@esbuild/win32-x64": 0.18.20 + esbuild@0.21.5: + optionalDependencies: + "@esbuild/aix-ppc64": 0.21.5 + "@esbuild/android-arm": 0.21.5 + "@esbuild/android-arm64": 0.21.5 + "@esbuild/android-x64": 0.21.5 + "@esbuild/darwin-arm64": 0.21.5 + "@esbuild/darwin-x64": 0.21.5 + "@esbuild/freebsd-arm64": 0.21.5 + "@esbuild/freebsd-x64": 0.21.5 + "@esbuild/linux-arm": 0.21.5 + "@esbuild/linux-arm64": 0.21.5 + "@esbuild/linux-ia32": 0.21.5 + "@esbuild/linux-loong64": 0.21.5 + "@esbuild/linux-mips64el": 0.21.5 + "@esbuild/linux-ppc64": 0.21.5 + "@esbuild/linux-riscv64": 0.21.5 + "@esbuild/linux-s390x": 0.21.5 + "@esbuild/linux-x64": 0.21.5 + "@esbuild/netbsd-x64": 0.21.5 + "@esbuild/openbsd-x64": 0.21.5 + "@esbuild/sunos-x64": 0.21.5 + "@esbuild/win32-arm64": 0.21.5 + "@esbuild/win32-ia32": 0.21.5 + "@esbuild/win32-x64": 0.21.5 + escalade@3.1.1: {} escalade@3.2.0: @@ -10077,6 +10667,10 @@ snapshots: estree-walker@2.0.2: {} + estree-walker@3.0.3: + dependencies: + "@types/estree": 1.0.8 + esutils@2.0.3: {} event-target-shim@5.0.1: {} @@ -10109,6 +10703,18 @@ snapshots: signal-exit: 3.0.7 strip-final-newline: 2.0.0 + execa@8.0.1: + dependencies: + cross-spawn: 7.0.6 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.3.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + exponential-backoff@3.1.1: {} external-editor@3.1.0: @@ -10167,11 +10773,6 @@ snapshots: locate-path: 6.0.0 path-exists: 4.0.0 - find-up@6.3.0: - dependencies: - locate-path: 7.2.0 - path-exists: 5.0.0 - flat-cache@3.1.1: dependencies: flatted: 3.2.9 @@ -10193,12 +10794,27 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 + form-data-encoder@1.7.2: {} + form-data@4.0.0: dependencies: asynckit: 0.4.0 combined-stream: 1.0.8 mime-types: 2.1.35 + form-data@4.0.5: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.2 + mime-types: 2.1.35 + + formdata-node@4.4.1: + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 4.0.0-beta.3 + fs-constants@1.0.0: {} fs-extra@10.1.0: @@ -10276,6 +10892,8 @@ snapshots: get-caller-file@2.0.5: {} + get-func-name@2.0.2: {} + get-intrinsic@1.3.0: dependencies: call-bind-apply-helpers: 1.0.2 @@ -10307,6 +10925,8 @@ snapshots: get-stream@6.0.1: {} + get-stream@8.0.1: {} + get-symbol-description@1.1.0: dependencies: call-bound: 1.0.4 @@ -10327,12 +10947,6 @@ snapshots: meow: 8.1.2 split2: 3.2.2 - git-raw-commits@4.0.0: - dependencies: - dargs: 8.1.0 - meow: 12.1.1 - split2: 4.2.0 - git-remote-origin-url@2.0.0: dependencies: gitconfiglocal: 1.0.0 @@ -10343,11 +10957,6 @@ snapshots: meow: 8.1.2 semver: 7.7.3 - git-semver-tags@7.0.1: - dependencies: - meow: 12.1.1 - semver: 7.7.3 - git-up@7.0.0: dependencies: is-ssh: 1.4.0 @@ -10496,9 +11105,7 @@ snapshots: dependencies: lru-cache: 7.18.3 - hosted-git-info@7.0.1: - dependencies: - lru-cache: 10.4.3 + html-escaper@2.0.2: {} http-cache-semantics@4.1.1: {} @@ -10519,6 +11126,8 @@ snapshots: human-signals@2.1.0: {} + human-signals@5.0.0: {} + humanize-ms@1.2.1: dependencies: ms: 2.1.3 @@ -10736,6 +11345,8 @@ snapshots: is-stream@2.0.1: {} + is-stream@3.0.0: {} + is-string@1.1.1: dependencies: call-bound: 1.0.4 @@ -10751,10 +11362,6 @@ snapshots: dependencies: text-extensions: 1.9.0 - is-text-path@2.0.0: - dependencies: - text-extensions: 2.4.0 - is-typed-array@1.1.15: dependencies: which-typed-array: 1.1.20 @@ -10787,6 +11394,27 @@ snapshots: isobject@3.0.1: {} + istanbul-lib-coverage@3.2.2: {} + + istanbul-lib-report@3.0.1: + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + + istanbul-lib-source-maps@5.0.6: + dependencies: + "@jridgewell/trace-mapping": 0.3.31 + debug: 4.4.3 + istanbul-lib-coverage: 3.2.2 + transitivePeerDependencies: + - supports-color + + istanbul-reports@3.2.0: + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + jackspeak@2.3.6: dependencies: "@isaacs/cliui": 8.0.2 @@ -10813,6 +11441,8 @@ snapshots: js-tokens@4.0.0: {} + js-tokens@9.0.1: {} + js-yaml@3.14.1: dependencies: argparse: 1.0.10 @@ -11050,6 +11680,11 @@ snapshots: strip-bom: 4.0.0 type-fest: 0.6.0 + local-pkg@0.5.1: + dependencies: + mlly: 1.8.2 + pkg-types: 1.3.1 + locate-path@2.0.0: dependencies: p-locate: 2.0.0 @@ -11063,10 +11698,6 @@ snapshots: dependencies: p-locate: 5.0.0 - locate-path@7.2.0: - dependencies: - p-locate: 6.0.0 - lodash._reinterpolate@3.0.0: {} lodash.assign@4.2.0: {} @@ -11116,6 +11747,10 @@ snapshots: slice-ansi: 4.0.0 wrap-ansi: 6.2.0 + loupe@2.3.7: + dependencies: + get-func-name: 2.0.2 + lru-cache@10.4.3: {} lru-cache@5.1.1: @@ -11129,6 +11764,16 @@ snapshots: lru-cache@7.18.3: {} + magic-string@0.30.21: + dependencies: + "@jridgewell/sourcemap-codec": 1.5.5 + + magicast@0.3.5: + dependencies: + "@babel/parser": 7.28.6 + "@babel/types": 7.28.6 + source-map-js: 1.2.1 + make-dir@2.1.0: dependencies: pify: 4.0.1 @@ -11193,8 +11838,6 @@ snapshots: math-intrinsics@1.1.0: {} - meow@12.1.1: {} - meow@8.1.2: dependencies: "@types/minimist": 1.2.3 @@ -11229,6 +11872,8 @@ snapshots: mimic-fn@2.1.0: {} + mimic-fn@4.0.0: {} + min-indent@1.0.1: {} minimatch@3.0.5: @@ -11313,6 +11958,13 @@ snapshots: mkdirp@1.0.4: {} + mlly@1.8.2: + dependencies: + acorn: 8.16.0 + pathe: 2.0.3 + pkg-types: 1.3.1 + ufo: 1.6.3 + modify-values@1.0.1: {} ms@2.1.2: {} @@ -11333,6 +11985,8 @@ snapshots: mute-stream@1.0.0: {} + nanoid@3.3.11: {} + nanoid@3.3.7: {} natural-compare@1.4.0: {} @@ -11349,6 +12003,8 @@ snapshots: node-addon-api@3.2.1: {} + node-domexception@1.0.0: {} + node-fetch@2.6.7(encoding@0.1.13): dependencies: whatwg-url: 5.0.0 @@ -11424,13 +12080,6 @@ snapshots: semver: 7.7.3 validate-npm-package-license: 3.0.4 - normalize-package-data@6.0.0: - dependencies: - hosted-git-info: 7.0.1 - is-core-module: 2.13.0 - semver: 7.7.3 - validate-npm-package-license: 3.0.4 - normalize-path@3.0.0: {} npm-bundled@1.1.2: @@ -11496,6 +12145,10 @@ snapshots: dependencies: path-key: 3.1.1 + npm-run-path@5.3.0: + dependencies: + path-key: 4.0.0 + npmlog@5.0.1: dependencies: are-we-there-yet: 2.0.0 @@ -11615,12 +12268,28 @@ snapshots: dependencies: mimic-fn: 2.1.0 + onetime@6.0.0: + dependencies: + mimic-fn: 4.0.0 + open@8.4.2: dependencies: define-lazy-prop: 2.0.0 is-docker: 2.2.1 is-wsl: 2.2.0 + openai@4.104.0(encoding@0.1.13): + dependencies: + "@types/node": 18.19.4 + "@types/node-fetch": 2.6.13 + abort-controller: 3.0.0 + agentkeepalive: 4.5.0 + form-data-encoder: 1.7.2 + formdata-node: 4.4.1 + node-fetch: 2.7.0(encoding@0.1.13) + transitivePeerDependencies: + - encoding + optionator@0.9.3: dependencies: "@aashutoshrathi/word-wrap": 1.2.6 @@ -11664,9 +12333,9 @@ snapshots: dependencies: yocto-queue: 0.1.0 - p-limit@4.0.0: + p-limit@5.0.0: dependencies: - yocto-queue: 1.0.0 + yocto-queue: 1.2.2 p-locate@2.0.0: dependencies: @@ -11680,10 +12349,6 @@ snapshots: dependencies: p-limit: 3.1.0 - p-locate@6.0.0: - dependencies: - p-limit: 4.0.0 - p-map-series@2.1.0: {} p-map@4.0.0: @@ -11751,14 +12416,6 @@ snapshots: json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 - parse-json@7.1.1: - dependencies: - "@babel/code-frame": 7.28.6 - error-ex: 1.3.2 - json-parse-even-better-errors: 3.0.1 - lines-and-columns: 2.0.4 - type-fest: 3.13.1 - parse-node-version@1.0.1: optional: true @@ -11776,12 +12433,12 @@ snapshots: path-exists@4.0.0: {} - path-exists@5.0.0: {} - path-is-absolute@1.0.1: {} path-key@3.1.1: {} + path-key@4.0.0: {} + path-parse@1.0.7: {} path-scurry@1.10.1: @@ -11795,6 +12452,12 @@ snapshots: path-type@4.0.0: {} + pathe@1.1.2: {} + + pathe@2.0.3: {} + + pathval@1.1.1: {} + picocolors@1.0.0: {} picocolors@1.1.1: {} @@ -11846,6 +12509,12 @@ snapshots: dependencies: find-up: 4.1.0 + pkg-types@1.3.1: + dependencies: + confbox: 0.1.8 + mlly: 1.8.2 + pathe: 2.0.3 + possible-typed-array-names@1.1.0: {} postcss-selector-parser@6.1.2: @@ -11860,6 +12529,12 @@ snapshots: picocolors: 1.0.0 source-map-js: 1.0.2 + postcss@8.5.10: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + prelude-ls@1.2.1: {} prettier@3.8.0: {} @@ -11927,12 +12602,6 @@ snapshots: normalize-package-data: 5.0.0 npm-normalize-package-bin: 3.0.1 - read-pkg-up@10.1.0: - dependencies: - find-up: 6.3.0 - read-pkg: 8.1.0 - type-fest: 4.9.0 - read-pkg-up@3.0.0: dependencies: find-up: 2.1.0 @@ -11957,13 +12626,6 @@ snapshots: parse-json: 5.2.0 type-fest: 0.6.0 - read-pkg@8.1.0: - dependencies: - "@types/normalize-package-data": 2.4.2 - normalize-package-data: 6.0.0 - parse-json: 7.1.1 - type-fest: 4.9.0 - read@2.1.0: dependencies: mute-stream: 1.0.0 @@ -12101,7 +12763,6 @@ snapshots: "@rollup/rollup-win32-ia32-msvc": 4.48.1 "@rollup/rollup-win32-x64-msvc": 4.48.1 fsevents: 2.3.3 - optional: true run-async@2.4.1: {} @@ -12229,6 +12890,8 @@ snapshots: side-channel-map: 1.0.1 side-channel-weakmap: 1.0.2 + siginfo@2.0.0: {} + signal-exit@3.0.7: {} signal-exit@4.1.0: {} @@ -12333,6 +12996,10 @@ snapshots: dependencies: minipass: 3.3.6 + stackback@0.0.2: {} + + std-env@3.10.0: {} + stop-iteration-iterator@1.1.0: dependencies: es-errors: 1.3.0 @@ -12397,12 +13064,18 @@ snapshots: strip-final-newline@2.0.0: {} + strip-final-newline@3.0.0: {} + strip-indent@3.0.0: dependencies: min-indent: 1.0.1 strip-json-comments@3.1.1: {} + strip-literal@2.1.1: + dependencies: + js-tokens: 9.0.1 + strong-log-transformer@2.1.0: dependencies: duplexer: 0.1.2 @@ -12445,12 +13118,6 @@ snapshots: temp-dir@1.0.0: {} - temp-dir@3.0.0: {} - - tempfile@5.0.0: - dependencies: - temp-dir: 3.0.0 - terser@5.46.0: dependencies: "@jridgewell/source-map": 0.3.11 @@ -12459,9 +13126,13 @@ snapshots: source-map-support: 0.5.21 optional: true - text-extensions@1.9.0: {} + test-exclude@6.0.0: + dependencies: + "@istanbuljs/schema": 0.1.6 + glob: 7.2.3 + minimatch: 3.1.2 - text-extensions@2.4.0: {} + text-extensions@1.9.0: {} text-table@0.2.0: {} @@ -12480,6 +13151,12 @@ snapshots: through@2.3.8: {} + tinybench@2.9.0: {} + + tinypool@0.8.4: {} + + tinyspy@2.2.1: {} + tmp@0.0.33: dependencies: os-tmpdir: 1.0.2 @@ -12545,6 +13222,8 @@ snapshots: dependencies: prelude-ls: 1.2.1 + type-detect@4.1.0: {} + type-fest@0.18.1: {} type-fest@0.20.2: {} @@ -12557,10 +13236,6 @@ snapshots: type-fest@0.8.1: {} - type-fest@3.13.1: {} - - type-fest@4.9.0: {} - typed-array-buffer@1.0.3: dependencies: call-bound: 1.0.4 @@ -12602,6 +13277,8 @@ snapshots: typescript@5.8.3: {} + ufo@1.6.3: {} + uglify-js@3.17.4: optional: true @@ -12672,6 +13349,24 @@ snapshots: validator@13.11.0: {} + vite-node@1.6.1(@types/node@18.19.4)(less@4.5.1)(terser@5.46.0): + dependencies: + cac: 6.7.14 + debug: 4.4.3 + pathe: 1.1.2 + picocolors: 1.1.1 + vite: 5.4.21(@types/node@18.19.4)(less@4.5.1)(terser@5.46.0) + transitivePeerDependencies: + - "@types/node" + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + vite-plugin-dts@3.7.0(@types/node@18.19.4)(rollup@4.48.1)(typescript@5.8.3)(vite@4.5.10(@types/node@18.19.4)(less@4.5.1)(terser@5.46.0)): dependencies: "@microsoft/api-extractor": 7.39.0(@types/node@18.19.4) @@ -12688,6 +13383,22 @@ snapshots: - rollup - supports-color + vite-plugin-dts@3.7.0(@types/node@18.19.4)(rollup@4.48.1)(typescript@5.8.3)(vite@5.4.21(@types/node@18.19.4)(less@4.5.1)(terser@5.46.0)): + dependencies: + "@microsoft/api-extractor": 7.39.0(@types/node@18.19.4) + "@rollup/pluginutils": 5.1.0(rollup@4.48.1) + "@vue/language-core": 1.8.27(typescript@5.8.3) + debug: 4.3.4(supports-color@9.4.0) + kolorist: 1.8.0 + typescript: 5.8.3 + vue-tsc: 1.8.27(typescript@5.8.3) + optionalDependencies: + vite: 5.4.21(@types/node@18.19.4)(less@4.5.1)(terser@5.46.0) + transitivePeerDependencies: + - "@types/node" + - rollup + - supports-color + vite@4.5.10(@types/node@18.19.4)(less@4.5.1)(terser@5.46.0): dependencies: esbuild: 0.18.20 @@ -12699,6 +13410,51 @@ snapshots: less: 4.5.1 terser: 5.46.0 + vite@5.4.21(@types/node@18.19.4)(less@4.5.1)(terser@5.46.0): + dependencies: + esbuild: 0.21.5 + postcss: 8.5.10 + rollup: 4.48.1 + optionalDependencies: + "@types/node": 18.19.4 + fsevents: 2.3.3 + less: 4.5.1 + terser: 5.46.0 + + vitest@1.6.1(@types/node@18.19.4)(less@4.5.1)(terser@5.46.0): + dependencies: + "@vitest/expect": 1.6.1 + "@vitest/runner": 1.6.1 + "@vitest/snapshot": 1.6.1 + "@vitest/spy": 1.6.1 + "@vitest/utils": 1.6.1 + acorn-walk: 8.3.5 + chai: 4.5.0 + debug: 4.4.3 + execa: 8.0.1 + local-pkg: 0.5.1 + magic-string: 0.30.21 + pathe: 1.1.2 + picocolors: 1.1.1 + std-env: 3.10.0 + strip-literal: 2.1.1 + tinybench: 2.9.0 + tinypool: 0.8.4 + vite: 5.4.21(@types/node@18.19.4)(less@4.5.1)(terser@5.46.0) + vite-node: 1.6.1(@types/node@18.19.4)(less@4.5.1)(terser@5.46.0) + why-is-node-running: 2.3.0 + optionalDependencies: + "@types/node": 18.19.4 + transitivePeerDependencies: + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + vue-eslint-parser@9.4.3(eslint@8.51.0): dependencies: debug: 4.4.3 @@ -12729,6 +13485,8 @@ snapshots: dependencies: defaults: 1.0.4 + web-streams-polyfill@4.0.0-beta.3: {} + webidl-conversions@3.0.1: {} whatwg-url@5.0.0: @@ -12785,6 +13543,11 @@ snapshots: dependencies: isexe: 2.0.0 + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + wide-align@1.1.5: dependencies: string-width: 4.2.3 @@ -12881,7 +13644,7 @@ snapshots: yocto-queue@0.1.0: {} - yocto-queue@1.0.0: {} + yocto-queue@1.2.2: {} z-schema@5.0.5: dependencies: