@icyfenix-dmla/cli 2026.4.19-920 → 2026.4.19-954

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@icyfenix-dmla/cli",
3
- "version": "2026.4.19-920",
3
+ "version": "2026.4.19-954",
4
4
  "description": "DMLA 沙箱服务命令行工具",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -114,7 +114,75 @@ async function findServiceContainer() {
114
114
  }
115
115
 
116
116
  /**
117
- * 启动服务
117
+ * 查找服务器入口文件
118
+ */
119
+ function findServerPath() {
120
+ const serverPath = path.resolve(__dirname, '../../../local-server/src/index.js')
121
+ const standaloneServerPath = path.resolve(__dirname, '../server/index.js')
122
+
123
+ return fs.existsSync(serverPath) ? serverPath :
124
+ fs.existsSync(standaloneServerPath) ? standaloneServerPath : null
125
+ }
126
+
127
+ /**
128
+ * 同步启动服务(在当前进程运行,用于调试)
129
+ * @param {number} port - 服务端口
130
+ * @param {boolean} useGpu - 是否使用 GPU
131
+ */
132
+ export async function startServerSync(port, useGpu = false) {
133
+ // 检查端口
134
+ const portAvailable = await checkPortAvailable(port)
135
+ if (!portAvailable) {
136
+ console.log(chalk.red(`❌ 端口 ${port} 已被占用`))
137
+ console.log(chalk.yellow('💡 提示: 使用 --port 选项指定其他端口'))
138
+ return
139
+ }
140
+
141
+ // 检查镜像
142
+ const imageType = useGpu ? 'gpu' : 'cpu'
143
+ const imageExists = await checkImageExists(imageType)
144
+ if (!imageExists) {
145
+ console.log(chalk.red(`❌ 镜像 ${useGpu ? CONFIG.imageGpu : CONFIG.imageCpu} 不存在`))
146
+ console.log(chalk.yellow('💡 提示: 运行 dmla install 安装镜像'))
147
+ return
148
+ }
149
+
150
+ // 检查服务是否已运行
151
+ const alreadyRunning = await checkServiceRunning(port)
152
+ if (alreadyRunning) {
153
+ console.log(chalk.green(`✅ 服务已在端口 ${port} 运行`))
154
+ return
155
+ }
156
+
157
+ // 查找服务器入口
158
+ const actualServerPath = findServerPath()
159
+ if (!actualServerPath) {
160
+ console.log(chalk.red('❌ 找不到服务入口文件'))
161
+ console.log(chalk.yellow('💡 提示: 确保正确安装了 @icyfenix-dmla/cli'))
162
+ return
163
+ }
164
+
165
+ console.log(chalk.gray(' 同步模式启动...'))
166
+ console.log(chalk.gray(` 服务入口: ${actualServerPath}`))
167
+ console.log()
168
+
169
+ // 设置环境变量
170
+ process.env.PORT = port.toString()
171
+ process.env.USE_GPU = useGpu ? 'true' : 'false'
172
+ process.env.DMLA_SYNC_MODE = 'true' // 标记同步模式,让服务器在 import 时启动
173
+
174
+ // 动态 import 服务器模块并直接运行
175
+ // 服务器模块会在 import 时自动启动(因为入口点检测逻辑)
176
+ try {
177
+ await import(actualServerPath)
178
+ } catch (error) {
179
+ console.log(chalk.red(`❌ 服务启动失败: ${error.message}`))
180
+ console.log(chalk.gray(error.stack))
181
+ }
182
+ }
183
+
184
+ /**
185
+ * 启动服务(异步模式,spawn 子进程)
118
186
  */
119
187
  export async function startServer(port, useGpu = false) {
120
188
  // 检查端口
@@ -145,14 +213,7 @@ export async function startServer(port, useGpu = false) {
145
213
  console.log(chalk.gray(' 正在启动...'))
146
214
 
147
215
  try {
148
- // 使用 spawn 启动 server 进程
149
- const serverPath = path.resolve(__dirname, '../../../local-server/src/index.js')
150
-
151
- // 如果 server 文件不存在,说明是独立安装模式,需要启动内置服务
152
- const standaloneServerPath = path.resolve(__dirname, '../server/index.js')
153
-
154
- const actualServerPath = fs.existsSync(serverPath) ? serverPath :
155
- fs.existsSync(standaloneServerPath) ? standaloneServerPath : null
216
+ const actualServerPath = findServerPath()
156
217
 
157
218
  if (!actualServerPath) {
158
219
  console.log(chalk.red('❌ 找不到服务入口文件'))
package/src/index.js CHANGED
@@ -4,7 +4,7 @@
4
4
  */
5
5
  import { program } from 'commander'
6
6
  import chalk from 'chalk'
7
- import { startServer, stopServer, getStatus } from './commands/server.js'
7
+ import { startServer, startServerSync, stopServer, getStatus } from './commands/server.js'
8
8
  import { updateAll, runDoctor } from './commands/manage.js'
9
9
  import { runInstallTUI } from '@icyfenix-dmla/install'
10
10
 
@@ -23,13 +23,24 @@ program
23
23
  .description('启动沙箱服务')
24
24
  .option('-p, --port <number>', '服务端口', '3001')
25
25
  .option('--gpu', '使用 GPU 镜像')
26
+ .option('--sync', '同步模式:在当前进程运行,日志直接输出(用于调试)')
26
27
  .action(async (options) => {
27
28
  const port = parseInt(options.port, 10)
28
29
  const useGpu = options.gpu
30
+ const sync = options.sync
31
+
29
32
  console.log(chalk.blue('🚀 启动 DMLA 沙箱服务...'))
30
33
  console.log(chalk.gray(` 端口: ${port}`))
31
34
  console.log(chalk.gray(` 镜像: ${useGpu ? 'GPU' : 'CPU'}`))
32
- await startServer(port, useGpu)
35
+ if (sync) {
36
+ console.log(chalk.yellow(` 模式: 同步(调试模式)`))
37
+ }
38
+
39
+ if (sync) {
40
+ await startServerSync(port, useGpu)
41
+ } else {
42
+ await startServer(port, useGpu)
43
+ }
33
44
  })
34
45
 
35
46
  // ─────────────────────────────────────────────────────────────
@@ -4,6 +4,8 @@
4
4
  */
5
5
  import express from 'express'
6
6
  import cors from 'cors'
7
+ import { fileURLToPath } from 'url'
8
+ import { resolve } from 'path'
7
9
  import sandboxRouter from './routes/sandbox.js'
8
10
 
9
11
  export const app = express()
@@ -30,8 +32,14 @@ app.use((err, req, res, next) => {
30
32
  })
31
33
  })
32
34
 
33
- // 仅在直接运行时启动服务器(测试时不启动)
34
- if (import.meta.url === `file://${process.argv[1]}`) {
35
+ // 启动服务器
36
+ // 条件1: 直接运行(入口点匹配)
37
+ // 条件2: 同步模式(DMLA_SYNC_MODE 环境变量)
38
+ const __filename = fileURLToPath(import.meta.url)
39
+ const entryPoint = resolve(process.argv[1] || '')
40
+ const shouldStart = __filename === entryPoint || process.env.DMLA_SYNC_MODE === 'true'
41
+
42
+ if (shouldStart) {
35
43
  app.listen(PORT, () => {
36
44
  console.log(`🚀 DMLA 本地服务已启动`)
37
45
  console.log(` API: http://localhost:${PORT}`)