@yeaft/webchat-agent 0.1.239 → 0.1.241
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/connection/upgrade.js +16 -10
- package/index.js +31 -1
- package/package.json +1 -1
package/connection/upgrade.js
CHANGED
|
@@ -15,10 +15,20 @@ const PM2_APP_NAME = 'yeaft-agent';
|
|
|
15
15
|
// but process.execPath always points to the running node binary.
|
|
16
16
|
const nodeBinDir = dirname(process.execPath);
|
|
17
17
|
const isWin = platform() === 'win32';
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
// Windows: use bare 'npm'/'pm2' + shell:true — cmd.exe finds them via PATH.
|
|
19
|
+
// This was the working pattern before ce58bbc. Absolute paths break when
|
|
20
|
+
// the path contains spaces (e.g., "C:\Program Files\nodejs\npm.cmd").
|
|
21
|
+
// macOS/Linux: use absolute path — launchd/systemd have minimal PATH.
|
|
22
|
+
const npmPath = isWin ? 'npm' : join(nodeBinDir, 'npm');
|
|
23
|
+
const pm2Path = isWin ? 'pm2' : join(nodeBinDir, 'pm2');
|
|
20
24
|
const shellOpt = isWin ? { shell: true } : {};
|
|
21
25
|
|
|
26
|
+
// Ensure PATH includes nodeBinDir so that `#!/usr/bin/env node` shebangs
|
|
27
|
+
// can locate node in launchd/systemd environments with minimal PATH.
|
|
28
|
+
const currentPath = process.env.PATH || '/usr/bin:/bin:/usr/sbin:/sbin';
|
|
29
|
+
const safePath = currentPath.includes(nodeBinDir) ? currentPath : `${nodeBinDir}:${currentPath}`;
|
|
30
|
+
const safeEnv = { ...process.env, PATH: safePath };
|
|
31
|
+
|
|
22
32
|
// Shared cleanup logic for restart/upgrade
|
|
23
33
|
function cleanupAndExit(exitCode) {
|
|
24
34
|
setTimeout(() => {
|
|
@@ -55,7 +65,7 @@ export async function handleUpgradeAgent() {
|
|
|
55
65
|
const pkgName = ctx.pkgName || '@yeaft/webchat-agent';
|
|
56
66
|
// Check latest version (async to avoid blocking heartbeat)
|
|
57
67
|
const latestVersion = await new Promise((resolve, reject) => {
|
|
58
|
-
execFile(npmPath, ['view', pkgName, 'version'], { stdio: 'pipe', ...shellOpt }, (err, stdout) => {
|
|
68
|
+
execFile(npmPath, ['view', pkgName, 'version'], { stdio: 'pipe', env: safeEnv, ...shellOpt }, (err, stdout) => {
|
|
59
69
|
if (err) reject(err); else resolve(stdout.toString().trim());
|
|
60
70
|
});
|
|
61
71
|
});
|
|
@@ -83,7 +93,7 @@ export async function handleUpgradeAgent() {
|
|
|
83
93
|
|
|
84
94
|
// 判断全局安装 vs 局部安装
|
|
85
95
|
const isGlobalInstall = await new Promise((resolve) => {
|
|
86
|
-
execFile(npmPath, ['prefix', '-g'], { ...shellOpt }, (err, stdout) => {
|
|
96
|
+
execFile(npmPath, ['prefix', '-g'], { env: safeEnv, ...shellOpt }, (err, stdout) => {
|
|
87
97
|
if (err) { resolve(false); return; }
|
|
88
98
|
const globalPrefix = stdout.toString().trim().replace(/\\/g, '/');
|
|
89
99
|
resolve(installDir === globalPrefix || installDir === globalPrefix + '/lib');
|
|
@@ -103,7 +113,7 @@ export async function handleUpgradeAgent() {
|
|
|
103
113
|
const isPm2 = !!process.env.pm_id;
|
|
104
114
|
if (isPm2) {
|
|
105
115
|
try {
|
|
106
|
-
execFileSync(pm2Path, ['delete', PM2_APP_NAME], { stdio: 'pipe', ...shellOpt });
|
|
116
|
+
execFileSync(pm2Path, ['delete', PM2_APP_NAME], { stdio: 'pipe', env: safeEnv, ...shellOpt });
|
|
107
117
|
console.log(`[Agent] PM2 app deleted to prevent auto-restart during upgrade`);
|
|
108
118
|
} catch {
|
|
109
119
|
console.log(`[Agent] PM2 delete skipped (app may not be registered)`);
|
|
@@ -252,17 +262,13 @@ function spawnUnixUpgradeScript(pkgName, installDir, isGlobalInstall, latestVers
|
|
|
252
262
|
const isLaunchd = platform() === 'darwin' && existsSync(join(process.env.HOME || '', 'Library', 'LaunchAgents', 'com.yeaft.agent.plist'));
|
|
253
263
|
const cwd = isGlobalInstall ? undefined : installDir;
|
|
254
264
|
|
|
255
|
-
// Ensure PATH includes the node bin dir (critical for launchd which has minimal PATH)
|
|
256
|
-
const currentPath = process.env.PATH || '/usr/bin:/bin:/usr/sbin:/sbin';
|
|
257
|
-
const exportPath = currentPath.includes(nodeBinDir) ? currentPath : `${nodeBinDir}:${currentPath}`;
|
|
258
|
-
|
|
259
265
|
const shLines = [
|
|
260
266
|
'#!/bin/bash',
|
|
261
267
|
`PID=${pid}`,
|
|
262
268
|
`PKG="${pkgName}@latest"`,
|
|
263
269
|
`NPM="${npmPath}"`,
|
|
264
270
|
`LOGFILE="${join(configDir, 'logs', 'upgrade.log')}"`,
|
|
265
|
-
`export PATH="${
|
|
271
|
+
`export PATH="${safePath}"`,
|
|
266
272
|
'',
|
|
267
273
|
'# Redirect all output to log file',
|
|
268
274
|
'exec > "$LOGFILE" 2>&1',
|
package/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import 'dotenv/config';
|
|
2
2
|
import { platform, homedir } from 'os';
|
|
3
|
-
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
|
3
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
|
|
4
4
|
import { join, dirname } from 'path';
|
|
5
5
|
import { exec } from 'child_process';
|
|
6
6
|
import { promisify } from 'util';
|
|
@@ -138,6 +138,35 @@ async function ensureDependencies() {
|
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
+
// 确保 yeaft-skills 插件已安装/更新
|
|
142
|
+
async function ensureYeaftSkills() {
|
|
143
|
+
const skillsDir = join(homedir(), '.claude', 'skills', 'yeaft-skills');
|
|
144
|
+
const REPO_URL = 'https://github.com/yeaft/yeaft-skills.git';
|
|
145
|
+
|
|
146
|
+
try {
|
|
147
|
+
if (!existsSync(skillsDir)) {
|
|
148
|
+
console.log('[Startup] yeaft-skills not found, installing...');
|
|
149
|
+
const parentDir = join(homedir(), '.claude', 'skills');
|
|
150
|
+
mkdirSync(parentDir, { recursive: true });
|
|
151
|
+
await execAsync(`git clone ${REPO_URL} "${skillsDir}"`, { timeout: 60000 });
|
|
152
|
+
console.log('[Startup] yeaft-skills installed');
|
|
153
|
+
} else {
|
|
154
|
+
console.log('[Startup] yeaft-skills found, checking for updates...');
|
|
155
|
+
const { stdout } = await execAsync('git pull --ff-only', {
|
|
156
|
+
cwd: skillsDir,
|
|
157
|
+
timeout: 30000
|
|
158
|
+
});
|
|
159
|
+
if (stdout.includes('Already up to date')) {
|
|
160
|
+
console.log('[Startup] yeaft-skills is up to date');
|
|
161
|
+
} else {
|
|
162
|
+
console.log('[Startup] yeaft-skills updated');
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
} catch (e) {
|
|
166
|
+
console.warn('[Startup] yeaft-skills sync failed (skills will be unavailable):', e.message);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
141
170
|
// 优雅退出
|
|
142
171
|
function cleanup() {
|
|
143
172
|
// 清理所有终端
|
|
@@ -176,6 +205,7 @@ process.on('SIGTERM', () => {
|
|
|
176
205
|
// 启动 - 先确保依赖,再检测能力,再连接
|
|
177
206
|
(async () => {
|
|
178
207
|
await ensureDependencies();
|
|
208
|
+
await ensureYeaftSkills();
|
|
179
209
|
ctx.agentCapabilities = await detectCapabilities();
|
|
180
210
|
connect();
|
|
181
211
|
})();
|