yymaxapi 1.0.28 → 1.0.31

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 (2) hide show
  1. package/bin/yymaxapi.js +57 -23
  2. package/package.json +1 -1
package/bin/yymaxapi.js CHANGED
@@ -841,20 +841,27 @@ async function selectDockerContainer() {
841
841
  // 在 Docker 容器内执行命令
842
842
  function execInDocker(containerId, cmd, options = {}) {
843
843
  const escaped = cmd.replace(/'/g, "'\\''");
844
+ // 尝试 sh -c,fallback bash -lc
845
+ const r = safeExec(dockerCmd(`exec ${containerId} sh -c '${escaped}'`), { timeout: 30000, ...options });
846
+ if (r.ok) return r;
844
847
  return safeExec(dockerCmd(`exec ${containerId} bash -lc '${escaped}'`), { timeout: 30000, ...options });
845
848
  }
846
849
 
847
850
  // 在 Docker 容器内异步执行命令(后台启动 gateway 等)
848
- function spawnDetachedInDocker(containerId, cmd, env = {}) {
851
+ // shell 参数: 'sh -c' | 'bash -lc' | 'bash -c'
852
+ function spawnDetachedInDocker(containerId, cmd, shell = 'sh -c') {
849
853
  try {
854
+ const shellParts = shell.split(' ');
855
+ const shellBin = shellParts[0];
856
+ const shellFlag = shellParts.slice(1).join(' ');
850
857
  const prefix = _dockerNeedsSudo ? 'sudo' : 'docker';
851
858
  const args = _dockerNeedsSudo
852
- ? ['-n', 'docker', 'exec', '-d', containerId, 'bash', '-lc', cmd]
853
- : ['exec', '-d', containerId, 'bash', '-lc', cmd];
854
- const child = spawn(prefix, args, {
859
+ ? ['-n', 'docker', 'exec', '-d', containerId, shellBin, shellFlag, cmd]
860
+ : ['exec', '-d', containerId, shellBin, shellFlag, cmd];
861
+ const child = spawn(prefix, args.filter(Boolean), {
855
862
  detached: true,
856
863
  stdio: 'ignore',
857
- env: { ...process.env, ...env }
864
+ env: { ...process.env }
858
865
  });
859
866
  child.unref();
860
867
  return true;
@@ -1058,7 +1065,7 @@ function cleanupAgentProcesses() {
1058
1065
  if (detectGatewayEnv() === 'docker' && _selectedDockerContainer) {
1059
1066
  try {
1060
1067
  for (const name of ['openclaw', 'clawdbot', 'moltbot']) {
1061
- safeExec(dockerCmd(`exec ${_selectedDockerContainer.id} bash -c "pkill -f '${name}.*agent' 2>/dev/null || true"`), { timeout: 10000 });
1068
+ safeExec(dockerCmd(`exec ${_selectedDockerContainer.id} sh -c "pkill -f '${name}.*agent' 2>/dev/null || true"`), { timeout: 10000 });
1062
1069
  }
1063
1070
  } catch { /* ignore */ }
1064
1071
  }
@@ -1703,6 +1710,7 @@ async function tryAutoStartGateway(port, allowAutoDaemon) {
1703
1710
  if (container.cli === 'node') {
1704
1711
  dockerCmds.push(`node ${container.cliPath} gateway`);
1705
1712
  } else {
1713
+ if (container.cliPath) dockerCmds.push(`${container.cliPath} gateway`);
1706
1714
  dockerCmds.push(`${container.cli} gateway`);
1707
1715
  }
1708
1716
  for (const name of ['openclaw', 'clawdbot', 'moltbot']) {
@@ -1711,10 +1719,13 @@ async function tryAutoStartGateway(port, allowAutoDaemon) {
1711
1719
 
1712
1720
  for (const cmd of [...new Set(dockerCmds)].filter(Boolean)) {
1713
1721
  console.log(chalk.yellow(`⚠️ 尝试在容器内启动 Gateway: ${cmd}`));
1714
- if (spawnDetachedInDocker(container.id, cmd)) {
1715
- if (await waitForGateway(port, '127.0.0.1', 15000)) {
1716
- console.log(chalk.green(`✅ Gateway 已在 Docker 容器 ${container.name} 内启动`));
1717
- return { started: true, method: 'docker', container: container.name };
1722
+ // 尝试多种 shell
1723
+ for (const shell of ['sh -c', 'bash -lc', 'bash -c']) {
1724
+ if (spawnDetachedInDocker(container.id, cmd, shell)) {
1725
+ if (await waitForGateway(port, '127.0.0.1', 15000)) {
1726
+ console.log(chalk.green(`✅ Gateway 已在 Docker 容器 ${container.name} 内启动`));
1727
+ return { started: true, method: 'docker', container: container.name };
1728
+ }
1718
1729
  }
1719
1730
  }
1720
1731
  }
@@ -2892,9 +2903,21 @@ async function testConnection(paths, args = {}) {
2892
2903
 
2893
2904
  // 等待 Gateway 启动
2894
2905
  const gwSpinner = ora({ text: '等待 Gateway 启动...', spinner: 'dots' }).start();
2895
- await new Promise(resolve => setTimeout(resolve, 3000));
2896
2906
 
2897
- let gatewayRunning = await waitForGateway(gatewayPort, '127.0.0.1', 15000);
2907
+ let gatewayRunning = false;
2908
+
2909
+ if (restartOk) {
2910
+ // restartGateway 内部已经验证过端口可达,只需短暂确认
2911
+ await new Promise(resolve => setTimeout(resolve, 1000));
2912
+ gatewayRunning = await waitForGateway(gatewayPort, '127.0.0.1', 5000);
2913
+ }
2914
+
2915
+ if (!gatewayRunning) {
2916
+ // restart 失败或未就绪,先等待更长时间(macOS LaunchAgent 启动较慢)
2917
+ await new Promise(resolve => setTimeout(resolve, 3000));
2918
+ gatewayRunning = await waitForGateway(gatewayPort, '127.0.0.1', 20000);
2919
+ }
2920
+
2898
2921
  if (!gatewayRunning) {
2899
2922
  gwSpinner.text = '尝试自动启动 Gateway...';
2900
2923
  const autoResult = await tryAutoStartGateway(gatewayPort, allowAutoDaemon);
@@ -3055,26 +3078,34 @@ async function restartGateway() {
3055
3078
 
3056
3079
  const dockerCmds = [];
3057
3080
  if (container.cli === 'node') {
3058
- // 脚本路径模式(如 /opt/moltbot/moltbot.mjs)
3059
3081
  dockerCmds.push(`node ${container.cliPath} gateway restart`);
3060
3082
  } else {
3083
+ if (container.cliPath) dockerCmds.push(`${container.cliPath} gateway restart`);
3061
3084
  dockerCmds.push(`${container.cli} gateway restart`);
3062
3085
  }
3063
- // 通用回退
3064
3086
  for (const name of ['openclaw', 'clawdbot', 'moltbot']) {
3065
3087
  dockerCmds.push(`${name} gateway restart`);
3066
3088
  }
3067
3089
 
3090
+ // 每个命令尝试多种 shell(sh -c / bash -lc / bash -c)
3091
+ const shellVariants = ['sh -c', 'bash -lc', 'bash -c'];
3092
+
3068
3093
  return new Promise((resolve) => {
3094
+ // 展开为 [cmd1+sh, cmd1+bash-lc, cmd1+bash-c, cmd2+sh, ...]
3095
+ const allAttempts = [];
3096
+ for (const cmd of [...new Set(dockerCmds)].filter(Boolean)) {
3097
+ for (const shell of shellVariants) {
3098
+ allAttempts.push(dockerCmd(`exec ${container.id} ${shell} "${cmd}"`));
3099
+ }
3100
+ }
3069
3101
  let tried = 0;
3070
3102
  const tryNext = () => {
3071
- if (tried >= dockerCmds.length) {
3103
+ if (tried >= allAttempts.length) {
3072
3104
  console.log(chalk.yellow('Docker 容器内 Gateway 重启失败,尝试本地重启...'));
3073
3105
  restartGatewayNative().then(resolve);
3074
3106
  return;
3075
3107
  }
3076
- const cmd = dockerCmds[tried++];
3077
- const fullCmd = dockerCmd(`exec ${container.id} bash -lc "${cmd}"`);
3108
+ const fullCmd = allAttempts[tried++];
3078
3109
  exec(fullCmd, { timeout: 30000 }, (error) => {
3079
3110
  if (error) {
3080
3111
  tryNext();
@@ -3140,9 +3171,9 @@ async function forceRestartGateway(resolved, nodeInfo, useNode, env, gatewayPort
3140
3171
  // 1. 杀掉容器内旧 Gateway 进程
3141
3172
  try {
3142
3173
  for (const name of ['openclaw', 'clawdbot', 'moltbot']) {
3143
- safeExec(dockerCmd(`exec ${cid} bash -c "pkill -f '${name}.*gateway' 2>/dev/null || true"`), { timeout: 5000 });
3174
+ safeExec(dockerCmd(`exec ${cid} sh -c "pkill -f '${name}.*gateway' 2>/dev/null || true"`), { timeout: 5000 });
3144
3175
  }
3145
- safeExec(dockerCmd(`exec ${cid} bash -c "lsof -ti :${gatewayPort} 2>/dev/null | xargs -r kill -9 2>/dev/null || true"`), { timeout: 5000 });
3176
+ safeExec(dockerCmd(`exec ${cid} sh -c "lsof -ti :${gatewayPort} 2>/dev/null | xargs -r kill -9 2>/dev/null || true"`), { timeout: 5000 });
3146
3177
  console.log(chalk.gray(' 已尝试清理容器内旧 Gateway 进程'));
3147
3178
  } catch { /* ignore */ }
3148
3179
 
@@ -3153,6 +3184,7 @@ async function forceRestartGateway(resolved, nodeInfo, useNode, env, gatewayPort
3153
3184
  if (_selectedDockerContainer.cli === 'node') {
3154
3185
  dockerCmds.push(`node ${_selectedDockerContainer.cliPath} gateway`);
3155
3186
  } else {
3187
+ if (_selectedDockerContainer.cliPath) dockerCmds.push(`${_selectedDockerContainer.cliPath} gateway`);
3156
3188
  dockerCmds.push(`${_selectedDockerContainer.cli} gateway`);
3157
3189
  }
3158
3190
  for (const name of ['openclaw', 'clawdbot', 'moltbot']) {
@@ -3161,10 +3193,12 @@ async function forceRestartGateway(resolved, nodeInfo, useNode, env, gatewayPort
3161
3193
 
3162
3194
  for (const cmd of [...new Set(dockerCmds)].filter(Boolean)) {
3163
3195
  console.log(chalk.gray(` 尝试在容器内启动: ${cmd}`));
3164
- if (spawnDetachedInDocker(cid, cmd)) {
3165
- if (await waitForGateway(gatewayPort, '127.0.0.1', 12000)) {
3166
- console.log(chalk.green(`✅ Gateway 已在 Docker 容器 ${cName} 内强制重启成功`));
3167
- return true;
3196
+ for (const shell of ['sh -c', 'bash -lc', 'bash -c']) {
3197
+ if (spawnDetachedInDocker(cid, cmd, shell)) {
3198
+ if (await waitForGateway(gatewayPort, '127.0.0.1', 12000)) {
3199
+ console.log(chalk.green(`✅ Gateway 已在 Docker 容器 ${cName} 内强制重启成功`));
3200
+ return true;
3201
+ }
3168
3202
  }
3169
3203
  }
3170
3204
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yymaxapi",
3
- "version": "1.0.28",
3
+ "version": "1.0.31",
4
4
  "description": "跨平台 OpenClaw/Clawdbot 配置管理工具 - 管理中转地址、模型切换、API Keys、测速优化",
5
5
  "main": "bin/yymaxapi.js",
6
6
  "bin": {