@downcity/plugins 1.0.56 → 1.0.59

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (318) hide show
  1. package/bin/BuiltinPlugins.d.ts.map +1 -1
  2. package/bin/BuiltinPlugins.js +0 -6
  3. package/bin/BuiltinPlugins.js.map +1 -1
  4. package/bin/asr/Plugin.d.ts +67 -7
  5. package/bin/asr/Plugin.d.ts.map +1 -1
  6. package/bin/asr/Plugin.js +229 -461
  7. package/bin/asr/Plugin.js.map +1 -1
  8. package/bin/asr/types/AsrPlugin.d.ts +114 -0
  9. package/bin/asr/types/AsrPlugin.d.ts.map +1 -0
  10. package/bin/asr/types/AsrPlugin.js +10 -0
  11. package/bin/asr/types/AsrPlugin.js.map +1 -0
  12. package/bin/auth/types/AuthPlugin.d.ts +12 -16
  13. package/bin/auth/types/AuthPlugin.d.ts.map +1 -1
  14. package/bin/auth/types/AuthPlugin.js +9 -13
  15. package/bin/auth/types/AuthPlugin.js.map +1 -1
  16. package/bin/chat/ChatPlugin.d.ts +37 -6
  17. package/bin/chat/ChatPlugin.d.ts.map +1 -1
  18. package/bin/chat/ChatPlugin.js +58 -80
  19. package/bin/chat/ChatPlugin.js.map +1 -1
  20. package/bin/chat/Index.d.ts +4 -1
  21. package/bin/chat/Index.d.ts.map +1 -1
  22. package/bin/chat/Index.js +2 -1
  23. package/bin/chat/Index.js.map +1 -1
  24. package/bin/chat/channels/Configuration.d.ts +1 -1
  25. package/bin/chat/channels/Configuration.js +1 -1
  26. package/bin/chat/channels/RuntimeChannel.d.ts +145 -0
  27. package/bin/chat/channels/RuntimeChannel.d.ts.map +1 -0
  28. package/bin/chat/channels/RuntimeChannel.js +148 -0
  29. package/bin/chat/channels/RuntimeChannel.js.map +1 -0
  30. package/bin/chat/runtime/ChatAuthorizationRuntime.d.ts +22 -0
  31. package/bin/chat/runtime/ChatAuthorizationRuntime.d.ts.map +1 -0
  32. package/bin/chat/runtime/ChatAuthorizationRuntime.js +189 -0
  33. package/bin/chat/runtime/ChatAuthorizationRuntime.js.map +1 -0
  34. package/bin/chat/runtime/ChatChannelActions.d.ts.map +1 -1
  35. package/bin/chat/runtime/ChatChannelActions.js +19 -9
  36. package/bin/chat/runtime/ChatChannelActions.js.map +1 -1
  37. package/bin/chat/runtime/ChatChannelConfig.d.ts +2 -18
  38. package/bin/chat/runtime/ChatChannelConfig.d.ts.map +1 -1
  39. package/bin/chat/runtime/ChatChannelConfig.js +2 -73
  40. package/bin/chat/runtime/ChatChannelConfig.js.map +1 -1
  41. package/bin/chat/runtime/ChatChannelCore.d.ts +22 -1
  42. package/bin/chat/runtime/ChatChannelCore.d.ts.map +1 -1
  43. package/bin/chat/runtime/ChatChannelCore.js +5 -5
  44. package/bin/chat/runtime/ChatChannelCore.js.map +1 -1
  45. package/bin/chat/runtime/ChatPluginActionRegistry.js +1 -1
  46. package/bin/chat/runtime/ChatPluginActionRegistry.js.map +1 -1
  47. package/bin/chat/runtime/PluginPoints.d.ts +3 -3
  48. package/bin/chat/runtime/PluginPoints.js +3 -3
  49. package/bin/chat/types/ChannelStatus.d.ts +1 -1
  50. package/bin/chat/types/ChatPluginOptions.d.ts +76 -0
  51. package/bin/chat/types/ChatPluginOptions.d.ts.map +1 -0
  52. package/bin/chat/types/ChatPluginOptions.js +10 -0
  53. package/bin/chat/types/ChatPluginOptions.js.map +1 -0
  54. package/bin/image/ImagePlugin.d.ts +1 -1
  55. package/bin/image/ImagePlugin.d.ts.map +1 -1
  56. package/bin/image/ImagePlugin.js +23 -5
  57. package/bin/image/ImagePlugin.js.map +1 -1
  58. package/bin/index.d.ts +6 -3
  59. package/bin/index.d.ts.map +1 -1
  60. package/bin/index.js +2 -2
  61. package/bin/index.js.map +1 -1
  62. package/bin/skill/Action.d.ts.map +1 -1
  63. package/bin/skill/Action.js +2 -2
  64. package/bin/skill/Action.js.map +1 -1
  65. package/bin/skill/Command.js +5 -5
  66. package/bin/skill/Command.js.map +1 -1
  67. package/bin/skill/Plugin.js +1 -1
  68. package/bin/skill/Plugin.js.map +1 -1
  69. package/bin/skill/runtime/Discovery.d.ts +4 -4
  70. package/bin/skill/runtime/Discovery.d.ts.map +1 -1
  71. package/bin/skill/runtime/Discovery.js +5 -5
  72. package/bin/skill/runtime/Discovery.js.map +1 -1
  73. package/bin/skill/runtime/Paths.d.ts +1 -5
  74. package/bin/skill/runtime/Paths.d.ts.map +1 -1
  75. package/bin/skill/runtime/Paths.js +1 -9
  76. package/bin/skill/runtime/Paths.js.map +1 -1
  77. package/bin/skill/runtime/Prompt.d.ts +2 -2
  78. package/bin/skill/runtime/Prompt.d.ts.map +1 -1
  79. package/bin/skill/runtime/Prompt.js +3 -3
  80. package/bin/skill/runtime/Prompt.js.map +1 -1
  81. package/bin/skill/runtime/Store.d.ts +2 -2
  82. package/bin/skill/runtime/Store.d.ts.map +1 -1
  83. package/bin/skill/runtime/Store.js.map +1 -1
  84. package/bin/skill/runtime/SystemProvider.js +4 -4
  85. package/bin/skill/runtime/SystemProvider.js.map +1 -1
  86. package/bin/skill/runtime/Types.d.ts +3 -3
  87. package/bin/skill/runtime/Types.d.ts.map +1 -1
  88. package/bin/skill/types/{ClaudeSkill.d.ts → SkillDefinition.d.ts} +4 -4
  89. package/bin/skill/types/SkillDefinition.d.ts.map +1 -0
  90. package/bin/skill/types/{ClaudeSkill.js → SkillDefinition.js} +2 -2
  91. package/bin/skill/types/SkillDefinition.js.map +1 -0
  92. package/bin/skill/types/SkillPlugin.d.ts +2 -2
  93. package/bin/skill/types/SkillPlugin.d.ts.map +1 -1
  94. package/bin/tts/Plugin.d.ts +53 -6
  95. package/bin/tts/Plugin.d.ts.map +1 -1
  96. package/bin/tts/Plugin.js +197 -474
  97. package/bin/tts/Plugin.js.map +1 -1
  98. package/bin/tts/types/TtsPlugin.d.ts +63 -102
  99. package/bin/tts/types/TtsPlugin.d.ts.map +1 -1
  100. package/bin/tts/types/TtsPlugin.js +4 -3
  101. package/bin/tts/types/TtsPlugin.js.map +1 -1
  102. package/bin/web/PROMPT.d.ts +1 -1
  103. package/bin/web/PROMPT.d.ts.map +1 -1
  104. package/bin/web/PROMPT.js +1 -1
  105. package/bin/web/PROMPT.js.map +1 -1
  106. package/bin/web/Plugin.d.ts +66 -5
  107. package/bin/web/Plugin.d.ts.map +1 -1
  108. package/bin/web/Plugin.js +126 -450
  109. package/bin/web/Plugin.js.map +1 -1
  110. package/bin/web/WebPromptAssets.d.ts +1 -9
  111. package/bin/web/WebPromptAssets.d.ts.map +1 -1
  112. package/bin/web/WebPromptAssets.js +1 -11
  113. package/bin/web/WebPromptAssets.js.map +1 -1
  114. package/bin/web/runtime/Install.d.ts +19 -0
  115. package/bin/web/runtime/Install.d.ts.map +1 -0
  116. package/bin/web/runtime/Install.js +178 -0
  117. package/bin/web/runtime/Install.js.map +1 -0
  118. package/bin/web/types/WebPlugin.d.ts +38 -109
  119. package/bin/web/types/WebPlugin.d.ts.map +1 -1
  120. package/bin/web/types/WebPlugin.js +5 -7
  121. package/bin/web/types/WebPlugin.js.map +1 -1
  122. package/bin/workboard/Plugin.d.ts +23 -3
  123. package/bin/workboard/Plugin.d.ts.map +1 -1
  124. package/bin/workboard/Plugin.js +66 -85
  125. package/bin/workboard/Plugin.js.map +1 -1
  126. package/package.json +2 -2
  127. package/src/BuiltinPlugins.ts +0 -6
  128. package/src/asr/Plugin.ts +264 -483
  129. package/src/asr/types/AsrPlugin.ts +118 -0
  130. package/src/auth/types/AuthPlugin.ts +12 -17
  131. package/src/chat/ChatPlugin.ts +92 -89
  132. package/src/chat/Index.ts +18 -1
  133. package/src/chat/channels/Configuration.ts +1 -1
  134. package/src/chat/channels/RuntimeChannel.ts +264 -0
  135. package/src/chat/runtime/ChatAuthorizationRuntime.ts +229 -0
  136. package/src/chat/runtime/ChatChannelActions.ts +24 -9
  137. package/src/chat/runtime/ChatChannelConfig.ts +2 -100
  138. package/src/chat/runtime/ChatChannelCore.ts +20 -8
  139. package/src/chat/runtime/ChatPluginActionRegistry.ts +1 -1
  140. package/src/chat/runtime/PluginPoints.ts +3 -3
  141. package/src/chat/types/ChannelStatus.ts +1 -1
  142. package/src/chat/types/ChatPluginOptions.ts +79 -0
  143. package/src/image/ImagePlugin.ts +23 -5
  144. package/src/index.ts +29 -6
  145. package/src/skill/Action.ts +10 -7
  146. package/src/skill/Command.ts +5 -5
  147. package/src/skill/Plugin.ts +1 -1
  148. package/src/skill/runtime/Discovery.ts +14 -11
  149. package/src/skill/runtime/Paths.ts +1 -13
  150. package/src/skill/runtime/Prompt.ts +5 -5
  151. package/src/skill/runtime/Store.ts +6 -3
  152. package/src/skill/runtime/SystemProvider.ts +4 -4
  153. package/src/skill/runtime/Types.ts +3 -3
  154. package/src/skill/types/{ClaudeSkill.ts → SkillDefinition.ts} +3 -3
  155. package/src/skill/types/SkillPlugin.ts +2 -2
  156. package/src/tts/Plugin.ts +225 -492
  157. package/src/tts/types/TtsPlugin.ts +67 -102
  158. package/src/web/PROMPT.ts +1 -1
  159. package/src/web/PROMPT.ts.txt +32 -6
  160. package/src/web/Plugin.ts +119 -453
  161. package/src/web/WebPromptAssets.ts +1 -13
  162. package/src/web/runtime/Install.ts +241 -0
  163. package/src/web/types/WebPlugin.ts +38 -114
  164. package/src/workboard/Plugin.ts +80 -95
  165. package/bin/asr/Config.d.ts +0 -43
  166. package/bin/asr/Config.d.ts.map +0 -1
  167. package/bin/asr/Config.js +0 -107
  168. package/bin/asr/Config.js.map +0 -1
  169. package/bin/asr/Dependency.d.ts +0 -77
  170. package/bin/asr/Dependency.d.ts.map +0 -1
  171. package/bin/asr/Dependency.js +0 -238
  172. package/bin/asr/Dependency.js.map +0 -1
  173. package/bin/asr/InboundAugment.d.ts +0 -17
  174. package/bin/asr/InboundAugment.d.ts.map +0 -1
  175. package/bin/asr/InboundAugment.js +0 -47
  176. package/bin/asr/InboundAugment.js.map +0 -1
  177. package/bin/asr/ModelCatalog.d.ts +0 -29
  178. package/bin/asr/ModelCatalog.d.ts.map +0 -1
  179. package/bin/asr/ModelCatalog.js +0 -25
  180. package/bin/asr/ModelCatalog.js.map +0 -1
  181. package/bin/auth/Plugin.d.ts +0 -17
  182. package/bin/auth/Plugin.d.ts.map +0 -1
  183. package/bin/auth/Plugin.js +0 -199
  184. package/bin/auth/Plugin.js.map +0 -1
  185. package/bin/chat/ChatPluginTypes.d.ts +0 -122
  186. package/bin/chat/ChatPluginTypes.d.ts.map +0 -1
  187. package/bin/chat/ChatPluginTypes.js +0 -10
  188. package/bin/chat/ChatPluginTypes.js.map +0 -1
  189. package/bin/skill/types/ClaudeSkill.d.ts.map +0 -1
  190. package/bin/skill/types/ClaudeSkill.js.map +0 -1
  191. package/bin/tts/Dependency.d.ts +0 -90
  192. package/bin/tts/Dependency.d.ts.map +0 -1
  193. package/bin/tts/Dependency.js +0 -344
  194. package/bin/tts/Dependency.js.map +0 -1
  195. package/bin/tts/PluginSupport.d.ts +0 -25
  196. package/bin/tts/PluginSupport.d.ts.map +0 -1
  197. package/bin/tts/PluginSupport.js +0 -72
  198. package/bin/tts/PluginSupport.js.map +0 -1
  199. package/bin/tts/runtime/Catalog.d.ts +0 -21
  200. package/bin/tts/runtime/Catalog.d.ts.map +0 -1
  201. package/bin/tts/runtime/Catalog.js +0 -90
  202. package/bin/tts/runtime/Catalog.js.map +0 -1
  203. package/bin/tts/runtime/DependencyInstaller.d.ts +0 -143
  204. package/bin/tts/runtime/DependencyInstaller.d.ts.map +0 -1
  205. package/bin/tts/runtime/DependencyInstaller.js +0 -261
  206. package/bin/tts/runtime/DependencyInstaller.js.map +0 -1
  207. package/bin/tts/runtime/Installer.d.ts +0 -89
  208. package/bin/tts/runtime/Installer.d.ts.map +0 -1
  209. package/bin/tts/runtime/Installer.js +0 -188
  210. package/bin/tts/runtime/Installer.js.map +0 -1
  211. package/bin/tts/runtime/Paths.d.ts +0 -20
  212. package/bin/tts/runtime/Paths.d.ts.map +0 -1
  213. package/bin/tts/runtime/Paths.js +0 -32
  214. package/bin/tts/runtime/Paths.js.map +0 -1
  215. package/bin/tts/runtime/Synthesizer.d.ts +0 -44
  216. package/bin/tts/runtime/Synthesizer.d.ts.map +0 -1
  217. package/bin/tts/runtime/Synthesizer.js +0 -363
  218. package/bin/tts/runtime/Synthesizer.js.map +0 -1
  219. package/bin/tts/types/Tts.d.ts +0 -91
  220. package/bin/tts/types/Tts.d.ts.map +0 -1
  221. package/bin/tts/types/Tts.js +0 -9
  222. package/bin/tts/types/Tts.js.map +0 -1
  223. package/bin/voice/Config.d.ts +0 -43
  224. package/bin/voice/Config.d.ts.map +0 -1
  225. package/bin/voice/Config.js +0 -104
  226. package/bin/voice/Config.js.map +0 -1
  227. package/bin/voice/Dependency.d.ts +0 -77
  228. package/bin/voice/Dependency.d.ts.map +0 -1
  229. package/bin/voice/Dependency.js +0 -237
  230. package/bin/voice/Dependency.js.map +0 -1
  231. package/bin/voice/InboundAugment.d.ts +0 -17
  232. package/bin/voice/InboundAugment.d.ts.map +0 -1
  233. package/bin/voice/InboundAugment.js +0 -47
  234. package/bin/voice/InboundAugment.js.map +0 -1
  235. package/bin/voice/ModelCatalog.d.ts +0 -29
  236. package/bin/voice/ModelCatalog.d.ts.map +0 -1
  237. package/bin/voice/ModelCatalog.js +0 -25
  238. package/bin/voice/ModelCatalog.js.map +0 -1
  239. package/bin/voice/runtime/Catalog.d.ts +0 -18
  240. package/bin/voice/runtime/Catalog.d.ts.map +0 -1
  241. package/bin/voice/runtime/Catalog.js +0 -61
  242. package/bin/voice/runtime/Catalog.js.map +0 -1
  243. package/bin/voice/runtime/DependencyInstaller.d.ts +0 -145
  244. package/bin/voice/runtime/DependencyInstaller.d.ts.map +0 -1
  245. package/bin/voice/runtime/DependencyInstaller.js +0 -309
  246. package/bin/voice/runtime/DependencyInstaller.js.map +0 -1
  247. package/bin/voice/runtime/Installer.d.ts +0 -94
  248. package/bin/voice/runtime/Installer.d.ts.map +0 -1
  249. package/bin/voice/runtime/Installer.js +0 -200
  250. package/bin/voice/runtime/Installer.js.map +0 -1
  251. package/bin/voice/runtime/Paths.d.ts +0 -8
  252. package/bin/voice/runtime/Paths.d.ts.map +0 -1
  253. package/bin/voice/runtime/Paths.js +0 -26
  254. package/bin/voice/runtime/Paths.js.map +0 -1
  255. package/bin/voice/runtime/Transcriber.d.ts +0 -57
  256. package/bin/voice/runtime/Transcriber.d.ts.map +0 -1
  257. package/bin/voice/runtime/Transcriber.js +0 -329
  258. package/bin/voice/runtime/Transcriber.js.map +0 -1
  259. package/bin/voice/types/Voice.d.ts +0 -58
  260. package/bin/voice/types/Voice.d.ts.map +0 -1
  261. package/bin/voice/types/Voice.js +0 -9
  262. package/bin/voice/types/Voice.js.map +0 -1
  263. package/bin/voice/types/VoicePlugin.d.ts +0 -190
  264. package/bin/voice/types/VoicePlugin.d.ts.map +0 -1
  265. package/bin/voice/types/VoicePlugin.js +0 -9
  266. package/bin/voice/types/VoicePlugin.js.map +0 -1
  267. package/bin/web/Dependency.d.ts +0 -10
  268. package/bin/web/Dependency.d.ts.map +0 -1
  269. package/bin/web/Dependency.js +0 -10
  270. package/bin/web/Dependency.js.map +0 -1
  271. package/bin/web/PROMPT.agent-browser.d.ts +0 -7
  272. package/bin/web/PROMPT.agent-browser.d.ts.map +0 -1
  273. package/bin/web/PROMPT.agent-browser.js +0 -8
  274. package/bin/web/PROMPT.agent-browser.js.map +0 -1
  275. package/bin/web/PROMPT.web-access.d.ts +0 -7
  276. package/bin/web/PROMPT.web-access.d.ts.map +0 -1
  277. package/bin/web/PROMPT.web-access.js +0 -8
  278. package/bin/web/PROMPT.web-access.js.map +0 -1
  279. package/bin/web/runtime/Config.d.ts +0 -21
  280. package/bin/web/runtime/Config.d.ts.map +0 -1
  281. package/bin/web/runtime/Config.js +0 -79
  282. package/bin/web/runtime/Config.js.map +0 -1
  283. package/bin/web/runtime/Source.d.ts +0 -29
  284. package/bin/web/runtime/Source.d.ts.map +0 -1
  285. package/bin/web/runtime/Source.js +0 -209
  286. package/bin/web/runtime/Source.js.map +0 -1
  287. package/src/asr/Config.ts +0 -138
  288. package/src/asr/Dependency.ts +0 -336
  289. package/src/asr/InboundAugment.ts +0 -59
  290. package/src/asr/ModelCatalog.ts +0 -43
  291. package/src/auth/Plugin.ts +0 -237
  292. package/src/chat/ChatPluginTypes.ts +0 -126
  293. package/src/tts/Dependency.ts +0 -473
  294. package/src/tts/PluginSupport.ts +0 -85
  295. package/src/tts/runtime/Catalog.ts +0 -97
  296. package/src/tts/runtime/DependencyInstaller.ts +0 -436
  297. package/src/tts/runtime/Installer.ts +0 -297
  298. package/src/tts/runtime/Paths.ts +0 -39
  299. package/src/tts/runtime/Synthesizer.ts +0 -480
  300. package/src/tts/types/Tts.ts +0 -99
  301. package/src/voice/Config.ts +0 -135
  302. package/src/voice/Dependency.ts +0 -329
  303. package/src/voice/InboundAugment.ts +0 -59
  304. package/src/voice/ModelCatalog.ts +0 -43
  305. package/src/voice/runtime/Catalog.ts +0 -68
  306. package/src/voice/runtime/DependencyInstaller.ts +0 -505
  307. package/src/voice/runtime/Installer.ts +0 -324
  308. package/src/voice/runtime/Paths.ts +0 -26
  309. package/src/voice/runtime/Transcriber.ts +0 -467
  310. package/src/voice/types/Voice.ts +0 -68
  311. package/src/voice/types/VoicePlugin.ts +0 -194
  312. package/src/web/Dependency.ts +0 -17
  313. package/src/web/PROMPT.agent-browser.ts +0 -9
  314. package/src/web/PROMPT.agent-browser.ts.txt +0 -17
  315. package/src/web/PROMPT.web-access.ts +0 -9
  316. package/src/web/PROMPT.web-access.ts.txt +0 -13
  317. package/src/web/runtime/Config.ts +0 -105
  318. package/src/web/runtime/Source.ts +0 -257
@@ -1,324 +0,0 @@
1
- import path from "node:path";
2
- import fs from "node:fs";
3
- import fsExtra from "fs-extra";
4
- import { Readable } from "node:stream";
5
- import { pipeline } from "node:stream/promises";
6
- import type { VoiceModelCatalogItem, VoiceModelId } from "@/voice/types/Voice.js";
7
-
8
- const HUGGINGFACE_HOST = "https://huggingface.co";
9
-
10
- type HuggingFaceModelApiResponse = {
11
- siblings?: Array<{
12
- rfilename?: string;
13
- }>;
14
- };
15
-
16
- /**
17
- * Voice 模型安装结果。
18
- */
19
- export interface VoiceModelInstallResult {
20
- /**
21
- * 模型目录(绝对路径)。
22
- */
23
- modelDir: string;
24
- /**
25
- * 本次下载文件数。
26
- */
27
- downloadedFiles: number;
28
- /**
29
- * 本次跳过文件数(已存在且未强制覆盖)。
30
- */
31
- skippedFiles: number;
32
- /**
33
- * 本次实际下载的文件路径(相对模型目录)。
34
- */
35
- downloadedFilePaths: string[];
36
- /**
37
- * 本次跳过的文件路径(相对模型目录)。
38
- */
39
- skippedFilePaths: string[];
40
- /**
41
- * 安装源仓库 ID。
42
- */
43
- repoId: string;
44
- /**
45
- * 安装源 revision。
46
- */
47
- revision: string;
48
- }
49
-
50
- /**
51
- * Voice 模型安装进度事件。
52
- */
53
- export interface VoiceModelInstallProgressEvent {
54
- /**
55
- * 当前阶段。
56
- */
57
- stage:
58
- | "discover"
59
- | "skip"
60
- | "download_start"
61
- | "download_done"
62
- | "manifest";
63
- /**
64
- * 文件路径(相对模型目录,可选)。
65
- */
66
- filePath?: string;
67
- /**
68
- * 文件总数(可选)。
69
- */
70
- totalFiles?: number;
71
- /**
72
- * 当前文件序号(从 1 开始,可选)。
73
- */
74
- index?: number;
75
- }
76
-
77
- /**
78
- * 判断模型在本地是否已安装。
79
- *
80
- * 关键点(中文)
81
- * - 优先识别安装清单 `downcity.voice.install.json`。
82
- * - 若无清单但目录非空,也视为已存在模型,避免重复下载。
83
- */
84
- export async function detectLocalVoiceModelInstallState(input: {
85
- modelId: VoiceModelId;
86
- modelsRootDir: string;
87
- }): Promise<{
88
- /**
89
- * 模型目录(绝对路径)。
90
- */
91
- modelDir: string;
92
- /**
93
- * 是否判断为“已安装”。
94
- */
95
- installed: boolean;
96
- /**
97
- * 已安装来源。
98
- */
99
- source?: "manifest" | "directory";
100
- }> {
101
- const modelDir = path.resolve(input.modelsRootDir, input.modelId);
102
- const manifestPath = path.join(modelDir, "downcity.voice.install.json");
103
- const hasManifest = await fsExtra.pathExists(manifestPath);
104
- if (hasManifest) {
105
- return {
106
- modelDir,
107
- installed: true,
108
- source: "manifest",
109
- };
110
- }
111
-
112
- const hasModelDir = await fsExtra.pathExists(modelDir);
113
- if (!hasModelDir) {
114
- return {
115
- modelDir,
116
- installed: false,
117
- };
118
- }
119
-
120
- const entries = await fsExtra.readdir(modelDir).catch(() => []);
121
- const hasPersistedFiles = entries.some(
122
- (entry) => !String(entry).endsWith(".downloading"),
123
- );
124
- if (!hasPersistedFiles) {
125
- return {
126
- modelDir,
127
- installed: false,
128
- };
129
- }
130
-
131
- return {
132
- modelDir,
133
- installed: true,
134
- source: "directory",
135
- };
136
- }
137
-
138
- function encodePathSegments(input: string): string {
139
- return input
140
- .split("/")
141
- .map((segment) => encodeURIComponent(segment))
142
- .join("/");
143
- }
144
-
145
- function buildAuthHeaders(token?: string): Record<string, string> | undefined {
146
- const t = String(token || "").trim();
147
- if (!t) return undefined;
148
- return { Authorization: `Bearer ${t}` };
149
- }
150
-
151
- function resolveSafeTargetPath(baseDir: string, relativePath: string): string {
152
- const normalized = relativePath.replace(/\\/g, "/");
153
- const target = path.resolve(baseDir, normalized);
154
- const base = path.resolve(baseDir);
155
- if (target !== base && !target.startsWith(`${base}${path.sep}`)) {
156
- throw new Error(`Unsafe file path from HuggingFace: ${relativePath}`);
157
- }
158
- return target;
159
- }
160
-
161
- async function readModelFiles(input: {
162
- repoId: string;
163
- hfToken?: string;
164
- }): Promise<string[]> {
165
- const repoUrlPath = encodePathSegments(input.repoId);
166
- const metadataUrl = `${HUGGINGFACE_HOST}/api/models/${repoUrlPath}`;
167
- const response = await fetch(metadataUrl, {
168
- headers: {
169
- Accept: "application/json",
170
- ...(buildAuthHeaders(input.hfToken) || {}),
171
- },
172
- });
173
- if (!response.ok) {
174
- const responseText = await response.text().catch(() => "");
175
- throw new Error(
176
- `Failed to fetch model metadata (${input.repoId}): HTTP ${response.status}${responseText ? ` ${responseText.slice(0, 300)}` : ""}`,
177
- );
178
- }
179
- const payload = (await response.json()) as HuggingFaceModelApiResponse;
180
- const files = (Array.isArray(payload.siblings) ? payload.siblings : [])
181
- .map((item) => String(item?.rfilename || "").trim())
182
- .filter(Boolean)
183
- .filter((item) => item !== ".gitattributes");
184
- if (files.length === 0) {
185
- throw new Error(`No downloadable files found in repo: ${input.repoId}`);
186
- }
187
- return files;
188
- }
189
-
190
- async function downloadModelFile(input: {
191
- repoId: string;
192
- revision: string;
193
- filePath: string;
194
- targetPath: string;
195
- hfToken?: string;
196
- }): Promise<void> {
197
- const repoPath = encodePathSegments(input.repoId);
198
- const revision = encodeURIComponent(input.revision);
199
- const filePath = encodePathSegments(input.filePath);
200
- const url = `${HUGGINGFACE_HOST}/${repoPath}/resolve/${revision}/${filePath}?download=1`;
201
- const response = await fetch(url, {
202
- headers: {
203
- ...(buildAuthHeaders(input.hfToken) || {}),
204
- },
205
- });
206
- if (!response.ok) {
207
- const responseText = await response.text().catch(() => "");
208
- throw new Error(
209
- `Failed to download ${input.filePath}: HTTP ${response.status}${responseText ? ` ${responseText.slice(0, 300)}` : ""}`,
210
- );
211
- }
212
- if (!response.body) {
213
- throw new Error(`Empty response body for file: ${input.filePath}`);
214
- }
215
-
216
- const tempPath = `${input.targetPath}.downloading`;
217
- await fsExtra.ensureDir(path.dirname(input.targetPath));
218
- try {
219
- const body = Readable.fromWeb(
220
- response.body as unknown as globalThis.ReadableStream<Uint8Array>,
221
- );
222
- await pipeline(body, fs.createWriteStream(tempPath));
223
- await fsExtra.move(tempPath, input.targetPath, { overwrite: true });
224
- } catch (error) {
225
- await fsExtra.remove(tempPath).catch(() => undefined);
226
- throw error;
227
- }
228
- }
229
-
230
- /**
231
- * 安装指定 voice 模型到本地目录。
232
- *
233
- * 关键点(中文)
234
- * - 使用 HTTP 文件级下载,不依赖 git-lfs。
235
- * - 默认复用已有文件;`force=true` 时覆盖重下。
236
- */
237
- export async function installVoiceModelFromHuggingFace(input: {
238
- model: VoiceModelCatalogItem;
239
- modelsRootDir: string;
240
- force?: boolean;
241
- hfToken?: string;
242
- onProgress?: (event: VoiceModelInstallProgressEvent) => void;
243
- }): Promise<VoiceModelInstallResult> {
244
- const modelDir = path.resolve(input.modelsRootDir, input.model.id);
245
- await fsExtra.ensureDir(modelDir);
246
-
247
- const files = await readModelFiles({
248
- repoId: input.model.huggingfaceRepo,
249
- hfToken: input.hfToken,
250
- });
251
- input.onProgress?.({
252
- stage: "discover",
253
- totalFiles: files.length,
254
- });
255
-
256
- let downloadedFiles = 0;
257
- let skippedFiles = 0;
258
- const downloadedFilePaths: string[] = [];
259
- const skippedFilePaths: string[] = [];
260
- for (let i = 0; i < files.length; i += 1) {
261
- const filePath = files[i];
262
- const targetPath = resolveSafeTargetPath(modelDir, filePath);
263
- const exists = await fsExtra.pathExists(targetPath);
264
- if (exists && input.force !== true) {
265
- skippedFiles += 1;
266
- skippedFilePaths.push(filePath);
267
- input.onProgress?.({
268
- stage: "skip",
269
- filePath,
270
- index: i + 1,
271
- totalFiles: files.length,
272
- });
273
- continue;
274
- }
275
- input.onProgress?.({
276
- stage: "download_start",
277
- filePath,
278
- index: i + 1,
279
- totalFiles: files.length,
280
- });
281
- await downloadModelFile({
282
- repoId: input.model.huggingfaceRepo,
283
- revision: input.model.revision,
284
- filePath,
285
- targetPath,
286
- hfToken: input.hfToken,
287
- });
288
- downloadedFiles += 1;
289
- downloadedFilePaths.push(filePath);
290
- input.onProgress?.({
291
- stage: "download_done",
292
- filePath,
293
- index: i + 1,
294
- totalFiles: files.length,
295
- });
296
- }
297
-
298
- await fsExtra.writeJson(
299
- path.join(modelDir, "downcity.voice.install.json"),
300
- {
301
- modelId: input.model.id,
302
- label: input.model.label,
303
- repoId: input.model.huggingfaceRepo,
304
- revision: input.model.revision,
305
- installedAt: new Date().toISOString(),
306
- downloadedFiles,
307
- skippedFiles,
308
- },
309
- { spaces: 2 },
310
- );
311
- input.onProgress?.({
312
- stage: "manifest",
313
- });
314
-
315
- return {
316
- modelDir,
317
- downloadedFiles,
318
- skippedFiles,
319
- downloadedFilePaths,
320
- skippedFilePaths,
321
- repoId: input.model.huggingfaceRepo,
322
- revision: input.model.revision,
323
- };
324
- }
@@ -1,26 +0,0 @@
1
- import path from "node:path";
2
- import os from "node:os";
3
-
4
- function expandHomePath(inputPath: string): string {
5
- const raw = String(inputPath || "").trim();
6
- if (!raw) return raw;
7
- if (raw === "~") return os.homedir();
8
- if (raw.startsWith("~/")) {
9
- return path.join(os.homedir(), raw.slice(2));
10
- }
11
- return raw;
12
- }
13
-
14
- /**
15
- * 将相对路径解析为绝对路径;空值时回退默认目录。
16
- */
17
- export function resolveVoiceModelsRootDir(input: {
18
- projectRoot: string;
19
- modelsDir?: string;
20
- }): string {
21
- const fallback = path.join(os.homedir(), ".downcity", "models", "voice");
22
- const raw = expandHomePath(String(input.modelsDir || fallback).trim());
23
- if (!raw) return path.resolve(fallback);
24
- if (path.isAbsolute(raw)) return path.resolve(raw);
25
- return path.resolve(input.projectRoot, raw);
26
- }