@agent-webui/ai-desk-daemon 1.0.52-beta6 → 1.0.53

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/README.md CHANGED
@@ -49,6 +49,7 @@ aidesk status
49
49
 
50
50
  **可用命令**:
51
51
  - `aidesk start` - 启动守护进程(后台运行,沿用当前已保存 mode)
52
+ - `aidesk start --no-update` - 跳过启动前的稳定版更新检查
52
53
  - `aidesk start --mode native` - 切到 Native mode 并启动
53
54
  - `aidesk start --mode cli-anything` - 切到 Bundled CLI-Anything runtime mode 并启动
54
55
  - `aidesk start --log` - 启动守护进程(前台运行,跟随日志)
@@ -63,6 +64,8 @@ aidesk status
63
64
  - `Native mode`:检测、模型查询、命令执行走 daemon 原生实现。
64
65
  - `Bundled CLI-Anything runtime mode`:使用 npm 安装时随包准备好的 Python runtime 和 `cli_anything` 入口;如果某个功能当前 runtime 不支持,daemon 会按配置回退到 native。
65
66
 
67
+ **更新说明**:`aidesk start` 默认会检查并安装 npm 上最新的稳定版 `@agent-webui/ai-desk`,会自动忽略 beta/prerelease 版本。可用 `--no-update` 或 `AIDESK_DISABLE_AUTO_UPDATE=1` 跳过。
68
+
66
69
  📖 详细使用说明:[NPM_CLI.md](NPM_CLI.md)
67
70
 
68
71
  ---
package/bin/cli.js CHANGED
@@ -11,6 +11,7 @@ const path = require('path');
11
11
  const { start, stop, restart, status } = require('../lib/daemon-manager');
12
12
  const { getLogPath } = require('../lib/platform');
13
13
  const { VERSION } = require('../lib/platform');
14
+ const { ensureLatestStableAIDesk, reexecAideskCommand } = require('../lib/self-update');
14
15
 
15
16
  function wait(ms) {
16
17
  return new Promise((resolve) => setTimeout(resolve, ms));
@@ -139,9 +140,30 @@ program
139
140
  .option('-m, --mode <mode>', 'Implementation mode: native or cli-anything')
140
141
  .option('--cli-anything', 'Enable CLI-Anything mode before starting')
141
142
  .option('--native', 'Force native mode before starting')
143
+ .option('--no-update', 'Skip checking for the latest stable AI Desk package before starting')
142
144
  .option('--log', 'Follow daemon logs in foreground (Ctrl+C to stop daemon)')
143
145
  .action(async (options) => {
144
146
  try {
147
+ if (options.update !== false) {
148
+ const updateResult = ensureLatestStableAIDesk({
149
+ currentVersion: VERSION,
150
+ logger: {
151
+ info: (message) => console.log(chalk.cyan(message)),
152
+ warn: (message) => console.warn(chalk.yellow(message)),
153
+ },
154
+ });
155
+
156
+ if (updateResult.updated) {
157
+ console.log(chalk.cyan('Restarting aidesk start with the updated CLI...'));
158
+ try {
159
+ process.exit(reexecAideskCommand(process.argv.slice(2)));
160
+ } catch (error) {
161
+ console.warn(chalk.yellow(`Failed to restart updated CLI: ${error.message}`));
162
+ console.warn(chalk.yellow('Continuing with the current process.'));
163
+ }
164
+ }
165
+ }
166
+
145
167
  const mode = resolveRequestedMode(options) || 'native';
146
168
  const modeResult = configureRequestedMode(mode);
147
169
  start();
@@ -5,7 +5,7 @@
5
5
  const fs = require('fs');
6
6
  const { spawn, execSync } = require('child_process');
7
7
  const http = require('http');
8
- const { getDaemonBinaryPath, getPidPath, getConfiguredLogPath, getLogPath, VERSION } = require('./platform');
8
+ const { getDaemonBinaryPath, getPidPath, getConfiguredLogPath, getLogPath } = require('./platform');
9
9
  const { getPort, getConfigPath } = require('./config');
10
10
 
11
11
  /**
@@ -67,15 +67,6 @@ function getHealth() {
67
67
  });
68
68
  }
69
69
 
70
- function formatStartOutput({ pid, port, version, logPath }) {
71
- return [
72
- `Daemon started (PID: ${pid})`,
73
- `Version: ${version || 'unknown'}`,
74
- `Port: ${port}`,
75
- `Logs: ${logPath}`
76
- ];
77
- }
78
-
79
70
  /**
80
71
  * Start daemon
81
72
  */
@@ -131,14 +122,9 @@ function start() {
131
122
  // Save PID
132
123
  fs.writeFileSync(getPidPath(), child.pid.toString());
133
124
 
134
- for (const line of formatStartOutput({
135
- pid: child.pid,
136
- port: portNumber,
137
- version: VERSION,
138
- logPath: getLogPath()
139
- })) {
140
- console.log(line);
141
- }
125
+ console.log(`Daemon started (PID: ${child.pid})`);
126
+ console.log(`Port: ${portNumber}`);
127
+ console.log(`Logs: ${getLogPath()}`);
142
128
 
143
129
  return child.pid;
144
130
  }
@@ -198,6 +184,5 @@ module.exports = {
198
184
  start,
199
185
  stop,
200
186
  restart,
201
- status,
202
- _formatStartOutputForTest: formatStartOutput
187
+ status
203
188
  };
@@ -0,0 +1,260 @@
1
+ /**
2
+ * Self-update helpers for the public `aidesk` npm package.
3
+ */
4
+
5
+ const { spawnSync } = require('child_process');
6
+
7
+ const DEFAULT_PACKAGE_NAME = '@agent-webui/ai-desk';
8
+ const DEFAULT_REGISTRY = 'https://registry.npmjs.org/';
9
+ const SKIP_AUTO_UPDATE_ENV = 'AIDESK_SKIP_AUTO_UPDATE';
10
+ const DISABLE_AUTO_UPDATE_ENV = 'AIDESK_DISABLE_AUTO_UPDATE';
11
+ const STRICT_AUTO_UPDATE_ENV = 'AIDESK_STRICT_AUTO_UPDATE';
12
+
13
+ function getNpmCommand() {
14
+ return process.platform === 'win32' ? 'npm.cmd' : 'npm';
15
+ }
16
+
17
+ function getRegistry() {
18
+ return (
19
+ process.env.AIDESK_NPM_REGISTRY ||
20
+ process.env.npm_config_registry ||
21
+ DEFAULT_REGISTRY
22
+ );
23
+ }
24
+
25
+ function parseVersion(version) {
26
+ const raw = String(version || '').trim().replace(/^v/, '');
27
+ const match = raw.match(/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z][0-9A-Za-z.-]*))?(?:\+[0-9A-Za-z.-]+)?$/);
28
+ if (!match) {
29
+ return null;
30
+ }
31
+
32
+ return {
33
+ major: Number.parseInt(match[1], 10),
34
+ minor: Number.parseInt(match[2], 10),
35
+ patch: Number.parseInt(match[3], 10),
36
+ prerelease: match[4] || '',
37
+ };
38
+ }
39
+
40
+ function isStableVersion(version) {
41
+ const parsed = parseVersion(version);
42
+ return Boolean(parsed && !parsed.prerelease);
43
+ }
44
+
45
+ function compareVersionCore(left, right) {
46
+ const leftParsed = parseVersion(left);
47
+ const rightParsed = parseVersion(right);
48
+ if (!leftParsed || !rightParsed) {
49
+ return String(left || '').localeCompare(String(right || ''));
50
+ }
51
+
52
+ for (const key of ['major', 'minor', 'patch']) {
53
+ if (leftParsed[key] !== rightParsed[key]) {
54
+ return leftParsed[key] - rightParsed[key];
55
+ }
56
+ }
57
+
58
+ return 0;
59
+ }
60
+
61
+ function normalizeVersions(value) {
62
+ if (Array.isArray(value)) {
63
+ return value.map((item) => String(item));
64
+ }
65
+
66
+ if (typeof value === 'string' && value.trim()) {
67
+ return [value.trim()];
68
+ }
69
+
70
+ return [];
71
+ }
72
+
73
+ function findLatestStableVersion(versions) {
74
+ const stableVersions = normalizeVersions(versions)
75
+ .filter(isStableVersion)
76
+ .sort(compareVersionCore);
77
+
78
+ return stableVersions[stableVersions.length - 1] || '';
79
+ }
80
+
81
+ function shouldInstallStableVersion(currentVersion, latestStableVersion) {
82
+ const latestParsed = parseVersion(latestStableVersion);
83
+ if (!latestParsed || latestParsed.prerelease) {
84
+ return false;
85
+ }
86
+
87
+ const currentParsed = parseVersion(currentVersion);
88
+ if (!currentParsed) {
89
+ return true;
90
+ }
91
+
92
+ if (currentParsed.prerelease) {
93
+ return true;
94
+ }
95
+
96
+ return compareVersionCore(latestStableVersion, currentVersion) > 0;
97
+ }
98
+
99
+ function runNpm(args, options = {}) {
100
+ const result = spawnSync(getNpmCommand(), args, {
101
+ encoding: options.encoding || 'utf8',
102
+ env: {
103
+ ...process.env,
104
+ npm_config_update_notifier: 'false',
105
+ },
106
+ shell: process.platform === 'win32',
107
+ stdio: options.stdio || ['ignore', 'pipe', 'pipe'],
108
+ timeout: options.timeout || 30000,
109
+ });
110
+
111
+ if (result.error) {
112
+ throw result.error;
113
+ }
114
+
115
+ if (result.status !== 0) {
116
+ const stderr = result.stderr ? String(result.stderr).trim() : '';
117
+ const stdout = result.stdout ? String(result.stdout).trim() : '';
118
+ throw new Error(stderr || stdout || `npm exited with status ${result.status}`);
119
+ }
120
+
121
+ return result.stdout || '';
122
+ }
123
+
124
+ function fetchPublishedVersions(packageName, registry) {
125
+ const output = runNpm(
126
+ ['view', packageName, 'versions', '--json', `--registry=${registry}`],
127
+ { timeout: 15000 }
128
+ );
129
+ const parsed = JSON.parse(output);
130
+ return normalizeVersions(parsed);
131
+ }
132
+
133
+ function installPackageVersion(packageName, version, registry) {
134
+ runNpm(
135
+ ['install', '-g', `${packageName}@${version}`, `--registry=${registry}`],
136
+ { stdio: 'inherit', timeout: 120000 }
137
+ );
138
+ }
139
+
140
+ function writeInfo(logger, message) {
141
+ if (logger && typeof logger.info === 'function') {
142
+ logger.info(message);
143
+ }
144
+ }
145
+
146
+ function writeWarn(logger, message) {
147
+ if (logger && typeof logger.warn === 'function') {
148
+ logger.warn(message);
149
+ }
150
+ }
151
+
152
+ function isAutoUpdateDisabled(options = {}) {
153
+ return (
154
+ options.enabled === false ||
155
+ process.env[SKIP_AUTO_UPDATE_ENV] === '1' ||
156
+ process.env[DISABLE_AUTO_UPDATE_ENV] === '1'
157
+ );
158
+ }
159
+
160
+ function ensureLatestStableAIDesk(options = {}) {
161
+ const logger = options.logger || console;
162
+ const packageName = options.packageName || DEFAULT_PACKAGE_NAME;
163
+ const registry = options.registry || getRegistry();
164
+ const currentVersion = options.currentVersion || '';
165
+
166
+ if (isAutoUpdateDisabled(options)) {
167
+ return {
168
+ checked: false,
169
+ skipped: true,
170
+ updated: false,
171
+ reason: 'disabled',
172
+ };
173
+ }
174
+
175
+ try {
176
+ writeInfo(logger, 'Checking for AI Desk updates...');
177
+ const versions = fetchPublishedVersions(packageName, registry);
178
+ const latestStableVersion = findLatestStableVersion(versions);
179
+
180
+ if (!latestStableVersion) {
181
+ throw new Error(`No stable versions found for ${packageName}`);
182
+ }
183
+
184
+ if (!shouldInstallStableVersion(currentVersion, latestStableVersion)) {
185
+ writeInfo(logger, `AI Desk is up to date (${currentVersion || latestStableVersion}).`);
186
+ return {
187
+ checked: true,
188
+ latestVersion: latestStableVersion,
189
+ updated: false,
190
+ };
191
+ }
192
+
193
+ const fromVersion = currentVersion ? ` from ${currentVersion}` : '';
194
+ writeInfo(logger, `Updating AI Desk${fromVersion} to ${latestStableVersion}...`);
195
+ installPackageVersion(packageName, latestStableVersion, registry);
196
+ writeInfo(logger, `AI Desk updated to ${latestStableVersion}.`);
197
+
198
+ return {
199
+ checked: true,
200
+ latestVersion: latestStableVersion,
201
+ updated: true,
202
+ };
203
+ } catch (error) {
204
+ if (process.env[STRICT_AUTO_UPDATE_ENV] === '1') {
205
+ throw new Error(`AI Desk auto-update failed: ${error.message}`);
206
+ }
207
+
208
+ writeWarn(logger, `AI Desk update check failed: ${error.message}`);
209
+ writeWarn(logger, 'Starting the currently installed version.');
210
+
211
+ return {
212
+ checked: false,
213
+ error,
214
+ updated: false,
215
+ };
216
+ }
217
+ }
218
+
219
+ function reexecAideskCommand(args = process.argv.slice(2)) {
220
+ const scriptPath = process.argv[1];
221
+ if (!scriptPath) {
222
+ throw new Error('Unable to resolve current aidesk executable path');
223
+ }
224
+
225
+ const result = spawnSync(process.execPath, [scriptPath, ...args], {
226
+ env: {
227
+ ...process.env,
228
+ [SKIP_AUTO_UPDATE_ENV]: '1',
229
+ },
230
+ stdio: 'inherit',
231
+ });
232
+
233
+ if (result.error) {
234
+ throw result.error;
235
+ }
236
+
237
+ if (typeof result.status === 'number') {
238
+ return result.status;
239
+ }
240
+
241
+ return result.signal ? 1 : 0;
242
+ }
243
+
244
+ module.exports = {
245
+ DEFAULT_PACKAGE_NAME,
246
+ DEFAULT_REGISTRY,
247
+ SKIP_AUTO_UPDATE_ENV,
248
+ DISABLE_AUTO_UPDATE_ENV,
249
+ STRICT_AUTO_UPDATE_ENV,
250
+ ensureLatestStableAIDesk,
251
+ reexecAideskCommand,
252
+ _internals: {
253
+ compareVersionCore,
254
+ findLatestStableVersion,
255
+ isStableVersion,
256
+ normalizeVersions,
257
+ parseVersion,
258
+ shouldInstallStableVersion,
259
+ },
260
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-webui/ai-desk-daemon",
3
- "version": "1.0.52-beta6",
3
+ "version": "1.0.53",
4
4
  "description": "AI Desk Daemon - CLI tool for managing the AI Desk daemon service",
5
5
  "workspaces": [
6
6
  "packages/*"
@@ -39,16 +39,16 @@
39
39
  "chalk": "^4.1.2"
40
40
  },
41
41
  "optionalDependencies": {
42
- "@agent-webui/ai-desk-daemon-darwin-arm64": "1.0.52-beta6",
43
- "@agent-webui/ai-desk-daemon-darwin-x64": "1.0.52-beta6",
44
- "@agent-webui/ai-desk-daemon-linux-arm64": "1.0.52-beta6",
45
- "@agent-webui/ai-desk-daemon-linux-x64": "1.0.52-beta6",
46
- "@agent-webui/ai-desk-daemon-win32-x64": "1.0.52-beta6",
47
- "@agent-webui/ai-desk-python-darwin-arm64": "1.0.52-beta6",
48
- "@agent-webui/ai-desk-python-darwin-x64": "1.0.52-beta6",
49
- "@agent-webui/ai-desk-python-linux-arm64": "1.0.52-beta6",
50
- "@agent-webui/ai-desk-python-linux-x64": "1.0.52-beta6",
51
- "@agent-webui/ai-desk-python-win32-x64": "1.0.52-beta6"
42
+ "@agent-webui/ai-desk-daemon-darwin-arm64": "1.0.53",
43
+ "@agent-webui/ai-desk-daemon-darwin-x64": "1.0.53",
44
+ "@agent-webui/ai-desk-daemon-linux-arm64": "1.0.53",
45
+ "@agent-webui/ai-desk-daemon-linux-x64": "1.0.53",
46
+ "@agent-webui/ai-desk-daemon-win32-x64": "1.0.53",
47
+ "@agent-webui/ai-desk-python-darwin-arm64": "1.0.53",
48
+ "@agent-webui/ai-desk-python-darwin-x64": "1.0.53",
49
+ "@agent-webui/ai-desk-python-linux-arm64": "1.0.53",
50
+ "@agent-webui/ai-desk-python-linux-x64": "1.0.53",
51
+ "@agent-webui/ai-desk-python-win32-x64": "1.0.53"
52
52
  },
53
53
  "repository": {
54
54
  "type": "git",