yo-moss-ai 0.0.11 → 0.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/bootstrap-deps.mjs +111 -40
- package/bin/runtime-manifest.json +1 -1
- package/bin/yo-moss-ai.mjs +2 -1
- package/dist/assets/esp-flasher-CLKzE7JE.js +2 -2
- package/dist/assets/index-CZ_NROJp.js +8 -8
- package/dist/models/mediapipe/blaze_face_full_range.tflite +0 -0
- package/dist/models/mediapipe/blaze_face_short_range.tflite +0 -0
- package/dist/models/mediapipe/wasm/vision_wasm_internal.js +8841 -0
- package/dist/models/mediapipe/wasm/vision_wasm_internal.wasm +0 -0
- package/dist/models/mediapipe/wasm/vision_wasm_nosimd_internal.js +8832 -0
- package/dist/models/mediapipe/wasm/vision_wasm_nosimd_internal.wasm +0 -0
- package/dist/stl/moss.stl +0 -0
- package/dist/stl/planetary_engine.stl +0 -0
- package/dist/textures/earth-lights.png +0 -0
- package/dist/textures/earth-night.jpg +0 -0
- package/dist/textures/earth_clouds.jpg +0 -0
- package/dist/textures/moon-base.jpg +0 -0
- package/dist/textures/moon-bump.jpg +0 -0
- package/dist/textures/wandering.png +0 -0
- package/dist-server/camera.mjs +1 -1
- package/dist-server/ffmpeg.mjs +1 -1
- package/dist-server/index.mjs +1 -1
- package/dist-server/ir-import-validate.mjs +1 -1
- package/dist-server/mcp/backoff.mjs +1 -1
- package/dist-server/mcp/bridge-manager.mjs +1 -1
- package/dist-server/mcp/builtin-tools.mjs +1 -1
- package/dist-server/mcp/dedupe-servers.mjs +1 -1
- package/dist-server/mcp/doctor.mjs +1 -1
- package/dist-server/mcp/fixtures/echo-mcp.mjs +1 -1
- package/dist-server/mcp/fixtures/hotkey-mcp.mjs +1 -1
- package/dist-server/mcp/fixtures/onvif-mcp.mjs +1 -1
- package/dist-server/mcp/fixtures/shell-mcp.mjs +1 -1
- package/dist-server/mcp/hotkey-agent-docs.mjs +1 -1
- package/dist-server/mcp/hotkey-driver.mjs +1 -1
- package/dist-server/mcp/hotkey-handlers.mjs +1 -1
- package/dist-server/mcp/hotkey-import-validate.mjs +1 -1
- package/dist-server/mcp/hotkey-store.mjs +1 -1
- package/dist-server/mcp/http-client.mjs +1 -1
- package/dist-server/mcp/http-pipe.mjs +1 -1
- package/dist-server/mcp/local-probe.mjs +1 -1
- package/dist-server/mcp/marketplace.mjs +1 -1
- package/dist-server/mcp/onvif-handlers.mjs +1 -1
- package/dist-server/mcp/parse-server-json.mjs +1 -1
- package/dist-server/mcp/paths.mjs +1 -1
- package/dist-server/mcp/routes.mjs +1 -1
- package/dist-server/mcp/schema.mjs +1 -1
- package/dist-server/mcp/settings.mjs +1 -1
- package/dist-server/mcp/shell-approval.mjs +1 -1
- package/dist-server/mcp/shell-policy.mjs +1 -1
- package/dist-server/mcp/shell-trash.mjs +1 -1
- package/dist-server/mcp/stdio-pipe.mjs +1 -1
- package/dist-server/mcp/store.mjs +1 -1
- package/dist-server/mcp/task-notify.mjs +1 -1
- package/dist-server/mcp/ws-connect.mjs +1 -1
- package/dist-server/media-cache.mjs +1 -1
- package/package.json +1 -1
package/bin/bootstrap-deps.mjs
CHANGED
|
@@ -7,6 +7,7 @@ import { spawn } from 'node:child_process'
|
|
|
7
7
|
import { pipeline } from 'node:stream/promises'
|
|
8
8
|
|
|
9
9
|
export const PROGRESS_BAR_WIDTH = 28
|
|
10
|
+
export const MEDIA_PACKAGE_NAME = 'yo-moss-ai-media'
|
|
10
11
|
|
|
11
12
|
export function mediaCacheDir() {
|
|
12
13
|
return process.env.MOSS_MEDIA_ROOT || path.join(os.homedir(), '.moss-desktop', 'media')
|
|
@@ -28,11 +29,12 @@ function renderBar(label, ratio) {
|
|
|
28
29
|
process.stdout.write(`\r\x1b[2K${formatProgressBar(label, ratio)}`)
|
|
29
30
|
}
|
|
30
31
|
|
|
32
|
+
/** @deprecated 单文件 CDN 对大体积 npm 包不可靠,保留仅供测试/兜底 */
|
|
31
33
|
export function cdnUrls(version, relativePath) {
|
|
32
34
|
const encoded = relativePath.split('/').map((part) => encodeURIComponent(part)).join('/')
|
|
33
35
|
return [
|
|
34
|
-
`https://cdn.jsdelivr.net/npm
|
|
35
|
-
`https://unpkg.com
|
|
36
|
+
`https://cdn.jsdelivr.net/npm/${MEDIA_PACKAGE_NAME}@${version}/${encoded}`,
|
|
37
|
+
`https://unpkg.com/${MEDIA_PACKAGE_NAME}@${version}/${encoded}`,
|
|
36
38
|
]
|
|
37
39
|
}
|
|
38
40
|
|
|
@@ -90,14 +92,41 @@ export function fileReady(filePath, expectedSize) {
|
|
|
90
92
|
}
|
|
91
93
|
}
|
|
92
94
|
|
|
93
|
-
function
|
|
95
|
+
export function dirByteSize(dir) {
|
|
96
|
+
if (!fs.existsSync(dir)) return 0
|
|
97
|
+
let total = 0
|
|
98
|
+
for (const name of fs.readdirSync(dir)) {
|
|
99
|
+
const full = path.join(dir, name)
|
|
100
|
+
const stat = fs.statSync(full)
|
|
101
|
+
if (stat.isDirectory()) total += dirByteSize(full)
|
|
102
|
+
else total += stat.size
|
|
103
|
+
}
|
|
104
|
+
return total
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function copyTree(src, dest) {
|
|
108
|
+
fs.mkdirSync(dest, { recursive: true })
|
|
109
|
+
for (const name of fs.readdirSync(src)) {
|
|
110
|
+
if (name.startsWith('.')) continue
|
|
111
|
+
const from = path.join(src, name)
|
|
112
|
+
const to = path.join(dest, name)
|
|
113
|
+
if (fs.statSync(from).isDirectory()) copyTree(from, to)
|
|
114
|
+
else fs.copyFileSync(from, to)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function runNpmInstall(cwd, extraArgs = []) {
|
|
94
119
|
return new Promise((resolve, reject) => {
|
|
95
120
|
const npmCmd = process.platform === 'win32' ? 'npm.cmd' : 'npm'
|
|
96
|
-
const child = spawn(
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
121
|
+
const child = spawn(
|
|
122
|
+
npmCmd,
|
|
123
|
+
['install', '--omit=dev', '--no-audit', '--no-fund', '--loglevel=error', ...extraArgs],
|
|
124
|
+
{
|
|
125
|
+
cwd,
|
|
126
|
+
stdio: ['ignore', 'ignore', 'pipe'],
|
|
127
|
+
shell: process.platform === 'win32',
|
|
128
|
+
},
|
|
129
|
+
)
|
|
101
130
|
let errText = ''
|
|
102
131
|
child.stderr.on('data', (chunk) => {
|
|
103
132
|
errText += String(chunk)
|
|
@@ -109,6 +138,72 @@ function runNpmInstall(cwd) {
|
|
|
109
138
|
})
|
|
110
139
|
}
|
|
111
140
|
|
|
141
|
+
/**
|
|
142
|
+
* 通过 npm registry 安装 yo-moss-ai-media 整包(比 CDN 单文件拉取可靠)。
|
|
143
|
+
*/
|
|
144
|
+
export const NPM_REGISTRIES = [
|
|
145
|
+
'https://registry.npmjs.org',
|
|
146
|
+
'https://registry.npmmirror.com',
|
|
147
|
+
]
|
|
148
|
+
|
|
149
|
+
export async function installMediaBundleFromNpm(
|
|
150
|
+
version,
|
|
151
|
+
cacheDir,
|
|
152
|
+
{ totalBytes = 0, onProgress, installImpl } = {},
|
|
153
|
+
) {
|
|
154
|
+
const staging = path.join(cacheDir, '.npm-staging')
|
|
155
|
+
fs.rmSync(staging, { recursive: true, force: true })
|
|
156
|
+
fs.mkdirSync(staging, { recursive: true })
|
|
157
|
+
fs.writeFileSync(
|
|
158
|
+
path.join(staging, 'package.json'),
|
|
159
|
+
`${JSON.stringify({
|
|
160
|
+
name: 'yo-moss-ai-media-staging',
|
|
161
|
+
private: true,
|
|
162
|
+
dependencies: { [MEDIA_PACKAGE_NAME]: version },
|
|
163
|
+
}, null, 2)}\n`,
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
const expected = totalBytes > 0 ? totalBytes : 56_000_000
|
|
167
|
+
const poll = setInterval(() => {
|
|
168
|
+
const size = dirByteSize(path.join(staging, 'node_modules', MEDIA_PACKAGE_NAME))
|
|
169
|
+
onProgress?.(Math.min(0.92, size / expected))
|
|
170
|
+
}, 400)
|
|
171
|
+
|
|
172
|
+
let lastError
|
|
173
|
+
try {
|
|
174
|
+
for (const registry of NPM_REGISTRIES) {
|
|
175
|
+
try {
|
|
176
|
+
const installer = installImpl || ((cwd) => runNpmInstall(cwd, ['--registry', registry]))
|
|
177
|
+
await installer(staging)
|
|
178
|
+
lastError = null
|
|
179
|
+
break
|
|
180
|
+
} catch (err) {
|
|
181
|
+
lastError = err
|
|
182
|
+
fs.rmSync(path.join(staging, 'node_modules'), { recursive: true, force: true })
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
if (lastError) {
|
|
186
|
+
throw new Error(`运行资源自动安装失败(${MEDIA_PACKAGE_NAME}@${version}),请检查网络后重试 npx yo-moss-ai`)
|
|
187
|
+
}
|
|
188
|
+
} finally {
|
|
189
|
+
clearInterval(poll)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const pkgRoot = path.join(staging, 'node_modules', MEDIA_PACKAGE_NAME)
|
|
193
|
+
if (!fs.existsSync(pkgRoot)) {
|
|
194
|
+
throw new Error(`运行资源自动安装失败(${MEDIA_PACKAGE_NAME}@${version}),请检查网络后重试 npx yo-moss-ai`)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
onProgress?.(0.95)
|
|
198
|
+
for (const dir of ['models', 'textures', 'stl']) {
|
|
199
|
+
const from = path.join(pkgRoot, dir)
|
|
200
|
+
if (!fs.existsSync(from)) continue
|
|
201
|
+
copyTree(from, path.join(cacheDir, dir))
|
|
202
|
+
}
|
|
203
|
+
fs.rmSync(staging, { recursive: true, force: true })
|
|
204
|
+
onProgress?.(1)
|
|
205
|
+
}
|
|
206
|
+
|
|
112
207
|
export async function ensureRuntimeNpmDeps(npmDeps, depsRoot = runtimeDepsRoot(), installImpl = runNpmInstall) {
|
|
113
208
|
fs.mkdirSync(depsRoot, { recursive: true })
|
|
114
209
|
const pkgPath = path.join(depsRoot, 'package.json')
|
|
@@ -164,7 +259,7 @@ export async function bootstrapRuntimeDeps(opts) {
|
|
|
164
259
|
version,
|
|
165
260
|
cacheDir = mediaCacheDir(),
|
|
166
261
|
depsRoot = runtimeDepsRoot(),
|
|
167
|
-
|
|
262
|
+
installMediaBundle = installMediaBundleFromNpm,
|
|
168
263
|
installNpmDeps = (npmDeps) => ensureRuntimeNpmDeps(npmDeps, depsRoot),
|
|
169
264
|
} = opts
|
|
170
265
|
|
|
@@ -201,40 +296,16 @@ export async function bootstrapRuntimeDeps(opts) {
|
|
|
201
296
|
}
|
|
202
297
|
|
|
203
298
|
if (needMedia) {
|
|
204
|
-
let doneBytes = 0
|
|
205
299
|
renderBar('下载资源', 0)
|
|
300
|
+
await installMediaBundle(mediaVersion, cacheDir, {
|
|
301
|
+
totalBytes,
|
|
302
|
+
onProgress: (ratio) => renderBar('下载资源', ratio),
|
|
303
|
+
})
|
|
304
|
+
process.stdout.write('\n')
|
|
206
305
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
if (fileReady(dest, file.size)) {
|
|
210
|
-
doneBytes += file.size || 0
|
|
211
|
-
renderBar('下载资源', totalBytes ? doneBytes / totalBytes : 1)
|
|
212
|
-
continue
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
const fileSize = file.size || 0
|
|
216
|
-
let fileDone = 0
|
|
217
|
-
let lastError
|
|
218
|
-
for (const url of cdnUrls(mediaVersion, file.path)) {
|
|
219
|
-
try {
|
|
220
|
-
await downloadFile(url, dest, (chunkLen) => {
|
|
221
|
-
fileDone += chunkLen
|
|
222
|
-
const current = doneBytes + Math.min(fileDone, fileSize || fileDone)
|
|
223
|
-
renderBar('下载资源', totalBytes ? current / totalBytes : 1)
|
|
224
|
-
})
|
|
225
|
-
lastError = null
|
|
226
|
-
break
|
|
227
|
-
} catch (err) {
|
|
228
|
-
lastError = err
|
|
229
|
-
fileDone = 0
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
if (lastError) throw new Error(`无法下载 ${file.path}: ${lastError.message}`)
|
|
233
|
-
|
|
234
|
-
doneBytes += fileSize || fs.statSync(dest).size
|
|
235
|
-
renderBar('下载资源', totalBytes ? doneBytes / totalBytes : 1)
|
|
306
|
+
if (!mediaCacheReady(mediaFiles, cacheDir)) {
|
|
307
|
+
throw new Error('媒体资源安装完成但校验失败,请删除 ~/.moss-desktop/media 后重试')
|
|
236
308
|
}
|
|
237
|
-
process.stdout.write('\n')
|
|
238
309
|
}
|
|
239
310
|
|
|
240
311
|
if (needNpm) {
|
package/bin/yo-moss-ai.mjs
CHANGED
|
@@ -32,7 +32,8 @@ console.log(`yo-moss-ai${pkgVersion ? ` v${pkgVersion}` : ''}`)
|
|
|
32
32
|
try {
|
|
33
33
|
await bootstrapRuntimeDeps({ root, version: pkg.version })
|
|
34
34
|
} catch (err) {
|
|
35
|
-
console.error('\n
|
|
35
|
+
console.error('\n启动准备失败:', err?.message || err)
|
|
36
|
+
console.error('请检查网络连接后重新运行:npx yo-moss-ai')
|
|
36
37
|
process.exit(1)
|
|
37
38
|
}
|
|
38
39
|
|