@yeaft/webchat-agent 0.1.242 → 0.1.244

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/index.js +113 -9
  2. package/package.json +1 -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, mkdirSync } from 'fs';
3
+ import { existsSync, readFileSync, writeFileSync, mkdirSync, cpSync } from 'fs';
4
4
  import { join, dirname } from 'path';
5
5
  import { exec } from 'child_process';
6
6
  import { promisify } from 'util';
@@ -138,29 +138,133 @@ async function ensureDependencies() {
138
138
  }
139
139
  }
140
140
 
141
- // 确保 yeaft-skills 插件已安装/更新
141
+ // 确保 yeaft-skills 插件已安装到 Claude CLI plugin 系统并注册为 marketplace
142
142
  async function ensureYeaftSkills() {
143
- const skillsDir = join(homedir(), '.claude', 'skills', 'yeaft-skills');
143
+ const MARKETPLACE_NAME = 'yeaft-skills-dev';
144
+ const PLUGIN_NAME = 'yeaft-skills';
145
+ const PLUGIN_KEY = `${PLUGIN_NAME}@${MARKETPLACE_NAME}`;
146
+ const PLUGIN_VERSION = '0.1.0';
144
147
  const REPO_URL = 'https://github.com/yeaft/yeaft-skills.git';
148
+ const claudeDir = join(homedir(), '.claude');
149
+ const pluginsDir = join(claudeDir, 'plugins');
150
+ const marketplacesDir = join(pluginsDir, 'marketplaces');
151
+ const installDir = join(marketplacesDir, MARKETPLACE_NAME);
152
+ const knownFile = join(pluginsDir, 'known_marketplaces.json');
153
+ const installedFile = join(pluginsDir, 'installed_plugins.json');
154
+ const settingsFile = join(claudeDir, 'settings.json');
155
+ const cacheDir = join(pluginsDir, 'cache', MARKETPLACE_NAME, PLUGIN_NAME, PLUGIN_VERSION);
145
156
 
146
157
  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 });
158
+ // --- Layer 1: Clone or update the marketplace repo ---
159
+ let gitSha = '';
160
+ let needsCacheUpdate = false;
161
+ if (!existsSync(installDir)) {
162
+ console.log('[Startup] yeaft-skills not found, installing as marketplace plugin...');
163
+ mkdirSync(marketplacesDir, { recursive: true });
164
+ await execAsync(`git clone ${REPO_URL} "${installDir}"`, { timeout: 60000 });
165
+ needsCacheUpdate = true;
152
166
  console.log('[Startup] yeaft-skills installed');
153
167
  } else {
154
168
  console.log('[Startup] yeaft-skills found, checking for updates...');
169
+ // Record HEAD before pull to detect changes
170
+ let headBefore = '';
171
+ try {
172
+ const { stdout: h } = await execAsync('git rev-parse HEAD', { cwd: installDir, timeout: 5000 });
173
+ headBefore = h.trim();
174
+ } catch { /* ignore */ }
155
175
  const { stdout } = await execAsync('git pull --ff-only', {
156
- cwd: skillsDir,
176
+ cwd: installDir,
157
177
  timeout: 30000
158
178
  });
159
179
  if (stdout.includes('Already up to date')) {
160
180
  console.log('[Startup] yeaft-skills is up to date');
161
181
  } else {
182
+ needsCacheUpdate = true;
162
183
  console.log('[Startup] yeaft-skills updated');
163
184
  }
185
+ // Double-check: compare HEAD after pull
186
+ if (!needsCacheUpdate && headBefore) {
187
+ try {
188
+ const { stdout: h2 } = await execAsync('git rev-parse HEAD', { cwd: installDir, timeout: 5000 });
189
+ if (h2.trim() !== headBefore) needsCacheUpdate = true;
190
+ } catch { /* ignore */ }
191
+ }
192
+ }
193
+ // Get current commit SHA for installed_plugins.json
194
+ try {
195
+ const { stdout: sha } = await execAsync('git rev-parse HEAD', { cwd: installDir, timeout: 5000 });
196
+ gitSha = sha.trim();
197
+ } catch { /* non-critical */ }
198
+
199
+ // --- Layer 2: Register in known_marketplaces.json (idempotent) ---
200
+ let known = {};
201
+ if (existsSync(knownFile)) {
202
+ try {
203
+ known = JSON.parse(readFileSync(knownFile, 'utf-8'));
204
+ } catch { /* corrupted file, will recreate */ }
205
+ }
206
+ if (!known[MARKETPLACE_NAME]) {
207
+ known[MARKETPLACE_NAME] = {
208
+ source: { source: 'github', repo: 'yeaft/yeaft-skills' },
209
+ installLocation: installDir,
210
+ lastUpdated: new Date().toISOString()
211
+ };
212
+ writeFileSync(knownFile, JSON.stringify(known, null, 2));
213
+ console.log('[Startup] yeaft-skills registered in known_marketplaces.json');
214
+ } else {
215
+ known[MARKETPLACE_NAME].lastUpdated = new Date().toISOString();
216
+ known[MARKETPLACE_NAME].installLocation = installDir;
217
+ writeFileSync(knownFile, JSON.stringify(known, null, 2));
218
+ }
219
+
220
+ // --- Layer 3: Copy to plugin cache (on first install or after update) ---
221
+ if (!existsSync(cacheDir) || needsCacheUpdate) {
222
+ mkdirSync(cacheDir, { recursive: true });
223
+ cpSync(installDir, cacheDir, { recursive: true });
224
+ console.log(`[Startup] yeaft-skills ${needsCacheUpdate ? 'updated in' : 'copied to'} plugin cache`);
225
+ }
226
+
227
+ // --- Layer 4: Register in installed_plugins.json ---
228
+ let installed = { version: 2, plugins: {} };
229
+ if (existsSync(installedFile)) {
230
+ try {
231
+ installed = JSON.parse(readFileSync(installedFile, 'utf-8'));
232
+ } catch { /* corrupted, will recreate */ }
233
+ }
234
+ if (!installed.plugins) installed.plugins = {};
235
+ if (!installed.plugins[PLUGIN_KEY]) {
236
+ const now = new Date().toISOString();
237
+ installed.plugins[PLUGIN_KEY] = [{
238
+ scope: 'user',
239
+ installPath: cacheDir,
240
+ version: PLUGIN_VERSION,
241
+ installedAt: now,
242
+ lastUpdated: now,
243
+ ...(gitSha ? { gitCommitSha: gitSha } : {})
244
+ }];
245
+ writeFileSync(installedFile, JSON.stringify(installed, null, 2));
246
+ console.log('[Startup] yeaft-skills registered in installed_plugins.json');
247
+ }
248
+
249
+ // --- Layer 5: Enable in settings.json ---
250
+ // Read existing settings; on parse failure skip to avoid losing user config
251
+ let settings = null;
252
+ if (existsSync(settingsFile)) {
253
+ try {
254
+ settings = JSON.parse(readFileSync(settingsFile, 'utf-8'));
255
+ } catch {
256
+ console.warn('[Startup] settings.json corrupted, skipping enabledPlugins write');
257
+ }
258
+ } else {
259
+ settings = {};
260
+ }
261
+ if (settings !== null) {
262
+ if (!settings.enabledPlugins) settings.enabledPlugins = {};
263
+ if (!settings.enabledPlugins[PLUGIN_KEY]) {
264
+ settings.enabledPlugins[PLUGIN_KEY] = true;
265
+ writeFileSync(settingsFile, JSON.stringify(settings, null, 2));
266
+ console.log('[Startup] yeaft-skills enabled in settings.json');
267
+ }
164
268
  }
165
269
  } catch (e) {
166
270
  console.warn('[Startup] yeaft-skills sync failed (skills will be unavailable):', e.message);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yeaft/webchat-agent",
3
- "version": "0.1.242",
3
+ "version": "0.1.244",
4
4
  "description": "Remote agent for Yeaft WebChat — connects worker machines to the central server",
5
5
  "main": "index.js",
6
6
  "type": "module",