yo-moss-ai 0.0.24 → 0.0.25

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 (94) hide show
  1. package/bin/bootstrap-deps.mjs +46 -35
  2. package/bin/runtime-manifest.json +1 -1
  3. package/bin/yo-moss-ai.mjs +48 -3
  4. package/dist/assets/esp-flasher-CLKzE7JE.js +2 -27
  5. package/dist/assets/index-C1bPuFAs.js +45 -0
  6. package/dist/assets/{index-CcIQTHSI.css → index-CzQKR67c.css} +1 -1
  7. package/dist/index.html +2 -2
  8. package/dist-server/board-presets.mjs +1 -1
  9. package/dist-server/camera.mjs +1 -1
  10. package/dist-server/dev-ui.mjs +1 -1
  11. package/dist-server/device-chat-sync.mjs +1 -1
  12. package/dist-server/device-config-view.mjs +1 -1
  13. package/dist-server/device-focus.mjs +1 -1
  14. package/dist-server/device-http.mjs +1 -1
  15. package/dist-server/device-identity.mjs +1 -1
  16. package/dist-server/device-presence.mjs +1 -1
  17. package/dist-server/device-probe.mjs +1 -1
  18. package/dist-server/device-registry.mjs +1 -1
  19. package/dist-server/device-routes.mjs +1 -1
  20. package/dist-server/device-runtime.mjs +1 -1
  21. package/dist-server/device-session.mjs +1 -1
  22. package/dist-server/ffmpeg.mjs +1 -1
  23. package/dist-server/gimbal-control.mjs +1 -1
  24. package/dist-server/home-path.mjs +1 -1
  25. package/dist-server/index.mjs +1 -1
  26. package/dist-server/ir-import-validate.mjs +1 -1
  27. package/dist-server/known-scan-device.mjs +1 -1
  28. package/dist-server/lan-discover.mjs +1 -1
  29. package/dist-server/listen-port.mjs +1 -1
  30. package/dist-server/mcp/backoff.mjs +1 -1
  31. package/dist-server/mcp/bridge-manager.mjs +1 -1
  32. package/dist-server/mcp/builtin-tools.mjs +1 -1
  33. package/dist-server/mcp/dedupe-servers.mjs +1 -1
  34. package/dist-server/mcp/doctor.mjs +1 -1
  35. package/dist-server/mcp/fixtures/echo-mcp.mjs +1 -1
  36. package/dist-server/mcp/fixtures/hotkey-mcp.mjs +1 -1
  37. package/dist-server/mcp/fixtures/mihome-mcp.mjs +1 -1
  38. package/dist-server/mcp/fixtures/onvif-mcp.mjs +1 -1
  39. package/dist-server/mcp/fixtures/shell-mcp.mjs +1 -1
  40. package/dist-server/mcp/fixtures/yunxiangji-mcp.mjs +1 -1
  41. package/dist-server/mcp/hotkey-agent-docs.mjs +1 -1
  42. package/dist-server/mcp/hotkey-driver.mjs +1 -1
  43. package/dist-server/mcp/hotkey-handlers.mjs +1 -1
  44. package/dist-server/mcp/hotkey-import-validate.mjs +1 -1
  45. package/dist-server/mcp/hotkey-store.mjs +1 -1
  46. package/dist-server/mcp/http-client.mjs +1 -1
  47. package/dist-server/mcp/http-pipe.mjs +1 -1
  48. package/dist-server/mcp/local-probe.mjs +1 -1
  49. package/dist-server/mcp/marketplace.mjs +1 -1
  50. package/dist-server/mcp/onvif-handlers.mjs +1 -1
  51. package/dist-server/mcp/parse-server-json.mjs +1 -1
  52. package/dist-server/mcp/paths.mjs +1 -1
  53. package/dist-server/mcp/routes.mjs +1 -1
  54. package/dist-server/mcp/schema.mjs +1 -1
  55. package/dist-server/mcp/settings.mjs +1 -1
  56. package/dist-server/mcp/shell-approval.mjs +1 -1
  57. package/dist-server/mcp/shell-policy.mjs +1 -1
  58. package/dist-server/mcp/shell-trash.mjs +1 -1
  59. package/dist-server/mcp/stdio-pipe.mjs +1 -1
  60. package/dist-server/mcp/store.mjs +1 -1
  61. package/dist-server/mcp/task-notify.mjs +1 -1
  62. package/dist-server/mcp/ws-connect.mjs +1 -1
  63. package/dist-server/mcp/yunxiangji.mjs +1 -1
  64. package/dist-server/media-cache.mjs +1 -1
  65. package/dist-server/mihome/cloud.mjs +1 -1
  66. package/dist-server/mihome/devices.mjs +1 -1
  67. package/dist-server/mihome/local.mjs +1 -1
  68. package/dist-server/mihome/mcp-desc.mjs +1 -1
  69. package/dist-server/mihome/queue.mjs +1 -1
  70. package/dist-server/mihome/rc4.mjs +1 -1
  71. package/dist-server/mihome/routes.mjs +1 -1
  72. package/dist-server/mihome/service.mjs +1 -1
  73. package/dist-server/mihome/sign.mjs +1 -1
  74. package/dist-server/mihome/spec.mjs +1 -1
  75. package/dist-server/mihome/store.mjs +1 -1
  76. package/dist-server/onboard-preview.mjs +1 -1
  77. package/dist-server/tab-focus.mjs +1 -1
  78. package/dist-server/voice-wake.mjs +1 -1
  79. package/package.json +4 -2
  80. package/dist/assets/index-JwpZFyvc.js +0 -692
  81. package/dist/models/mediapipe/blaze_face_full_range.tflite +0 -0
  82. package/dist/models/mediapipe/blaze_face_short_range.tflite +0 -0
  83. package/dist/models/mediapipe/wasm/vision_wasm_internal.js +0 -8841
  84. package/dist/models/mediapipe/wasm/vision_wasm_internal.wasm +0 -0
  85. package/dist/models/mediapipe/wasm/vision_wasm_nosimd_internal.js +0 -8832
  86. package/dist/models/mediapipe/wasm/vision_wasm_nosimd_internal.wasm +0 -0
  87. package/dist/stl/moss.stl +0 -0
  88. package/dist/stl/planetary_engine.stl +0 -0
  89. package/dist/textures/earth-lights.png +0 -0
  90. package/dist/textures/earth-night.jpg +0 -0
  91. package/dist/textures/earth_clouds.jpg +0 -0
  92. package/dist/textures/moon-base.jpg +0 -0
  93. package/dist/textures/moon-bump.jpg +0 -0
  94. package/dist/textures/wandering.png +0 -0
@@ -4,8 +4,11 @@ import path from 'node:path'
4
4
  import http from 'node:http'
5
5
  import https from 'node:https'
6
6
  import { spawn } from 'node:child_process'
7
+ import { createRequire } from 'node:module'
7
8
  import { pipeline } from 'node:stream/promises'
8
9
 
10
+ export const RUNTIME_PACKAGE_NAMES = ['express', 'cors', 'ws', 'onvif', 'qrcode', 'bonjour-service']
11
+
9
12
  export const PROGRESS_BAR_WIDTH = 28
10
13
  export const MEDIA_PACKAGE_NAME = 'yo-moss-ai-media'
11
14
 
@@ -128,9 +131,7 @@ export function copyTree(src, dest) {
128
131
  }
129
132
  }
130
133
 
131
- export const NPM_INSTALL_TIMEOUT_MS = 60_000
132
-
133
- function runNpmInstall(cwd, extraArgs = [], timeoutMs = NPM_INSTALL_TIMEOUT_MS) {
134
+ function runNpmInstall(cwd, extraArgs = []) {
134
135
  return new Promise((resolve, reject) => {
135
136
  const npmCmd = process.platform === 'win32' ? 'npm.cmd' : 'npm'
136
137
  const child = spawn(
@@ -143,20 +144,10 @@ function runNpmInstall(cwd, extraArgs = [], timeoutMs = NPM_INSTALL_TIMEOUT_MS)
143
144
  },
144
145
  )
145
146
  let errText = ''
146
- let settled = false
147
- const timer = setTimeout(() => {
148
- if (settled) return
149
- settled = true
150
- child.kill()
151
- reject(new Error(`npm install 超时(${Math.round(timeoutMs / 1000)}s)`))
152
- }, timeoutMs)
153
147
  child.stderr.on('data', (chunk) => {
154
148
  errText += String(chunk)
155
149
  })
156
150
  child.on('exit', (code) => {
157
- clearTimeout(timer)
158
- if (settled) return
159
- settled = true
160
151
  if (code === 0) resolve()
161
152
  else reject(new Error(errText.trim() || `npm install 失败,退出码 ${code}`))
162
153
  })
@@ -300,6 +291,33 @@ export function mediaCacheReady(files, cacheDir = mediaCacheDir()) {
300
291
  return files.every((file) => fileReady(path.join(cacheDir, file.path), file.size))
301
292
  }
302
293
 
294
+ /** 源码仓库(npx 会优先跑本地 bin,而不是 npm 上的已发布包) */
295
+ export function isSourceCheckout(root) {
296
+ return fs.existsSync(path.join(root, 'server', 'index.mjs'))
297
+ && fs.existsSync(path.join(root, 'package.json'))
298
+ }
299
+
300
+ /** Node 能否从该包根解析运行时 npm 依赖(pnpm 未 hoist / node_modules 损坏时为 false) */
301
+ export function runtimePackagesResolvable(root, names = RUNTIME_PACKAGE_NAMES) {
302
+ try {
303
+ const req = createRequire(path.join(root, 'package.json'))
304
+ for (const name of names) req.resolve(name)
305
+ return true
306
+ } catch {
307
+ return false
308
+ }
309
+ }
310
+
311
+ export function missingRuntimeDepsMessage(root) {
312
+ if (isSourceCheckout(root)) {
313
+ return [
314
+ '当前目录是源码仓库,npx 会启动本地构建,但 node_modules 里缺少 express 等运行依赖。',
315
+ '请先在本目录执行 pnpm install 后再运行;或换到其他目录执行 npx yo-moss-ai 使用已发布版本。',
316
+ ].join('\n')
317
+ }
318
+ return '运行依赖未安装完整,请重新执行 npx yo-moss-ai 让 npm 自动安装。'
319
+ }
320
+
303
321
  /**
304
322
  * npx 安装精简包后,启动服务前下载媒体资源与扩展 npm 依赖。
305
323
  */
@@ -311,26 +329,24 @@ export async function bootstrapRuntimeDeps(opts) {
311
329
  depsRoot = runtimeDepsRoot(),
312
330
  installMediaBundle = installMediaBundleFromNpm,
313
331
  installNpmDeps = (npmDeps, onProgress) => ensureRuntimeNpmDeps(npmDeps, depsRoot, { onProgress }),
314
- deferNpm = false,
315
332
  } = opts
316
333
 
317
334
  const distDir = path.join(root, 'dist')
318
- if (process.env.MOSS_SKIP_BOOTSTRAP === '1') {
335
+ if (process.env.MOSS_SKIP_BOOTSTRAP === '1' || hasBundledMedia(distDir)) {
319
336
  return { skipped: true }
320
337
  }
321
338
 
322
- const bundled = hasBundledMedia(distDir)
323
339
  const manifest = loadManifest(root)
324
- if (!manifest && !bundled) {
340
+ if (!manifest) {
325
341
  console.warn('缺少 bin/runtime-manifest.json,跳过资源预下载')
326
342
  return { skipped: true }
327
343
  }
328
344
 
329
- const mediaVersion = manifest?.mediaVersion || version
330
- const mediaFiles = manifest?.mediaFiles || []
331
- const npmDeps = manifest?.npmDeps || []
345
+ const mediaVersion = manifest.mediaVersion || version
346
+ const mediaFiles = manifest.mediaFiles || []
347
+ const npmDeps = manifest.npmDeps || []
332
348
  const totalBytes = mediaFiles.reduce((sum, file) => sum + (file.size || 0), 0)
333
- const needMedia = !bundled && mediaFiles.length > 0 && !mediaCacheReady(mediaFiles, cacheDir)
349
+ const needMedia = !mediaCacheReady(mediaFiles, cacheDir)
334
350
  const needNpm = !runtimeDepsReady(npmDeps, depsRoot)
335
351
 
336
352
  if (!needMedia && !needNpm) {
@@ -343,10 +359,8 @@ export async function bootstrapRuntimeDeps(opts) {
343
359
  if (needMedia) {
344
360
  const mb = (totalBytes / 1024 / 1024).toFixed(0)
345
361
  console.log(`首次运行:正在下载 UI 资源(约 ${mb} MB),完成后自动启动…`)
346
- } else if (needNpm && !deferNpm) {
362
+ } else if (needNpm) {
347
363
  console.log('首次运行:正在安装扩展组件,完成后自动启动…')
348
- } else if (needNpm && deferNpm) {
349
- console.log('正在打开界面;快捷键组件在后台安装,不影响使用。')
350
364
  }
351
365
 
352
366
  if (needMedia) {
@@ -367,17 +381,14 @@ export async function bootstrapRuntimeDeps(opts) {
367
381
  if (needNpm) {
368
382
  const reportNpm = createProgressReporter('安装扩展依赖')
369
383
  reportNpm(0.02)
370
- const work = Promise.resolve()
371
- .then(() => installNpmDeps(npmDeps, reportNpm))
372
- .then(() => {
373
- if (process.stdout.isTTY) process.stdout.write('\n')
374
- else console.log(formatProgressBar('安装扩展依赖', 1))
375
- })
376
- .catch((err) => {
377
- if (process.stdout.isTTY) process.stdout.write('\n')
378
- console.warn('扩展组件安装失败,快捷键/媒体键可能不可用:', err.message)
379
- })
380
- if (!deferNpm) await work
384
+ try {
385
+ await installNpmDeps(npmDeps, reportNpm)
386
+ if (process.stdout.isTTY) process.stdout.write('\n')
387
+ else console.log(formatProgressBar('安装扩展依赖', 1))
388
+ } catch (err) {
389
+ if (process.stdout.isTTY) process.stdout.write('\n')
390
+ console.warn('扩展组件安装失败,快捷键/媒体键可能不可用:', err.message)
391
+ }
381
392
  }
382
393
 
383
394
  process.env.MOSS_MEDIA_ROOT = cacheDir
@@ -1,5 +1,5 @@
1
1
  {
2
- "mediaVersion": "0.0.24",
2
+ "mediaVersion": "0.0.25",
3
3
  "mediaFiles": [
4
4
  {
5
5
  "path": "models/mediapipe/blaze_face_full_range.tflite",
@@ -1,8 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  import fs from 'node:fs'
3
+ import os from 'node:os'
3
4
  import path from 'node:path'
5
+ import { spawn } from 'node:child_process'
4
6
  import { fileURLToPath, pathToFileURL } from 'node:url'
5
- import { bootstrapRuntimeDeps } from './bootstrap-deps.mjs'
7
+ import {
8
+ bootstrapRuntimeDeps,
9
+ isSourceCheckout,
10
+ missingRuntimeDepsMessage,
11
+ runtimePackagesResolvable,
12
+ } from './bootstrap-deps.mjs'
6
13
 
7
14
  const root = path.join(path.dirname(fileURLToPath(import.meta.url)), '..')
8
15
  let pkgVersion = ''
@@ -27,11 +34,26 @@ if (!fs.existsSync(server)) {
27
34
  process.exit(1)
28
35
  }
29
36
 
37
+ if (!runtimePackagesResolvable(root)) {
38
+ if (isSourceCheckout(root) && process.env.MOSS_NO_SOURCE_FALLBACK !== '1') {
39
+ console.log(`yo-moss-ai${pkgVersion ? ` v${pkgVersion}` : ''} 本地依赖不完整,改用 npm 已发布版本…`)
40
+ try {
41
+ process.exit(await runPublishedFromTemp(pkg.version))
42
+ } catch (err) {
43
+ console.error(missingRuntimeDepsMessage(root))
44
+ console.error(err?.message || err)
45
+ process.exit(1)
46
+ }
47
+ }
48
+ console.error(missingRuntimeDepsMessage(root))
49
+ process.exit(1)
50
+ }
51
+
30
52
  console.log(`yo-moss-ai${pkgVersion ? ` v${pkgVersion}` : ''}`)
31
53
  if (typeof process.stdout.write === 'function') process.stdout.write('')
32
54
 
33
55
  try {
34
- await bootstrapRuntimeDeps({ root, version: pkg.version, deferNpm: true })
56
+ await bootstrapRuntimeDeps({ root, version: pkg.version })
35
57
  } catch (err) {
36
58
  console.error('\n启动准备失败:', err?.message || err)
37
59
  console.error('请检查网络连接后重新运行:npx yo-moss-ai')
@@ -42,4 +64,27 @@ process.env.NODE_ENV = 'production'
42
64
  process.env.MOSS_OPEN_BROWSER = process.env.MOSS_OPEN_BROWSER || '1'
43
65
  process.env.MOSS_VERSION = pkg.version
44
66
 
45
- await import(pathToFileURL(server).href)
67
+ try {
68
+ await import(pathToFileURL(server).href)
69
+ } catch (err) {
70
+ if (err?.code === 'ERR_MODULE_NOT_FOUND') {
71
+ console.error(missingRuntimeDepsMessage(root))
72
+ console.error(err.message)
73
+ process.exit(1)
74
+ }
75
+ throw err
76
+ }
77
+
78
+ function runPublishedFromTemp(version) {
79
+ return new Promise((resolve, reject) => {
80
+ const npxCmd = process.platform === 'win32' ? 'npx.cmd' : 'npx'
81
+ const child = spawn(npxCmd, ['--yes', `yo-moss-ai@${version}`], {
82
+ cwd: os.tmpdir(),
83
+ stdio: 'inherit',
84
+ shell: process.platform === 'win32',
85
+ env: { ...process.env, MOSS_NO_SOURCE_FALLBACK: '1' },
86
+ })
87
+ child.on('error', reject)
88
+ child.on('exit', (code) => resolve(code ?? 1))
89
+ })
90
+ }