cadet-agent 0.15.1 → 0.15.2

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/package.json +1 -1
  2. package/src/install.mjs +69 -4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cadet-agent",
3
- "version": "0.15.1",
3
+ "version": "0.15.2",
4
4
  "description": "Cross-IDE agent framework for Unity/C# game-development — one-command install",
5
5
  "type": "module",
6
6
  "bin": {
package/src/install.mjs CHANGED
@@ -274,13 +274,13 @@ function walkDir(dir, fn) {
274
274
 
275
275
  function deleteObsoleteManagedFiles(targetDir, managedPaths, zipFilenames) {
276
276
  const normalizedZip = new Set(
277
- zipFilenames.map(f => f.replace(/^\.?\/?/, '').replace(/\\/g, '/'))
277
+ zipFilenames.map(f => f.replace(/^\.\//, '').replace(/\\/g, '/'))
278
278
  );
279
279
  const deleted = [];
280
280
 
281
281
  for (const managed of managedPaths) {
282
- const mn = managed.replace(/^\.?\/?/, '').replace(/\\/g, '/');
283
- const managedPath = join(targetDir, managed.replace(/^\.?\/?/, ''));
282
+ const mn = managed.replace(/^\.\//, '').replace(/\\/g, '/');
283
+ const managedPath = join(targetDir, managed.replace(/^\.\//, ''));
284
284
  const stat = (() => { try { return statSync(managedPath); } catch { return null; } })();
285
285
  if (!stat) continue;
286
286
 
@@ -340,7 +340,61 @@ async function extractZipWithManifest(buf, targetDir, { preserved, managed }) {
340
340
  // Delete obsolete managed files no longer in the zip (renamed/removed managed paths)
341
341
  const deleted = deleteObsoleteManagedFiles(targetDir, managed, zipFilenames);
342
342
 
343
- return { updated, preserved: preserved_list, added, deleted };
343
+ return { updated, preserved: preserved_list, added, deleted, zipFilenames };
344
+ }
345
+
346
+ // ── Removed-managed-path cleanup ─────────────────────────────────────────────
347
+
348
+ export function findManagedPathsInZip(buf) {
349
+ try {
350
+ const eocdOff = findEocd(buf);
351
+ const cdSize = read32(buf, eocdOff + 12);
352
+ const cdOff = read32(buf, eocdOff + 16);
353
+
354
+ for (const entry of centralDirectoryEntries(buf, cdOff, cdSize)) {
355
+ const fn = entry.filename.replace(/^\.\//, '').replace(/\\/g, '/');
356
+ if (fn === '.cadet/agent/core/FrameworkManifest.json') {
357
+ // Extract just this one entry to read managedPaths
358
+ const lfhFilenameLen = read16(buf, entry.localHeaderOff + 26);
359
+ const lfhExtraLen = read16(buf, entry.localHeaderOff + 28);
360
+ const dataStart = entry.localHeaderOff + 30 + lfhFilenameLen + lfhExtraLen;
361
+ const compressed = buf.subarray(dataStart, dataStart + entry.compressedSize);
362
+ let data;
363
+ if (entry.method === 0) data = compressed;
364
+ else if (entry.method === 8) data = inflateRawSync(compressed);
365
+ else break;
366
+ const manifest = JSON.parse(data.toString('utf-8'));
367
+ return manifest.managedPaths || [];
368
+ }
369
+ }
370
+ } catch {
371
+ // Not a valid zip or manifest not found
372
+ }
373
+ return [];
374
+ }
375
+
376
+ export function deleteRemovedManagedPaths(targetDir, oldManaged, newManaged) {
377
+ const newSet = new Set(newManaged.map(p => p.replace(/^\.\//, '').replace(/\\/g, '/')));
378
+ const deleted = [];
379
+
380
+ for (const old of oldManaged) {
381
+ const oldNorm = old.replace(/^\.\//, '').replace(/\\/g, '/');
382
+ if (newSet.has(oldNorm)) continue;
383
+
384
+ // This path was in the old manifest but is absent from the new one — remove it
385
+ const fullPath = join(targetDir, old.replace(/^\.\//, ''));
386
+ const st = (() => { try { return statSync(fullPath); } catch { return null; } })();
387
+ if (!st) continue;
388
+
389
+ if (st.isFile()) {
390
+ try { unlinkSync(fullPath); deleted.push(fullPath); } catch {}
391
+ } else if (st.isDirectory()) {
392
+ walkDir(fullPath, (filePath) => {
393
+ try { unlinkSync(filePath); deleted.push(filePath); } catch {}
394
+ });
395
+ }
396
+ }
397
+ return deleted;
344
398
  }
345
399
 
346
400
  // ── Public sync entry ───────────────────────────────────────────────────────
@@ -384,6 +438,17 @@ export async function sync(targetDir, opts = {}) {
384
438
  managed: existingManifest.managedPaths || [],
385
439
  });
386
440
 
441
+ // 4b. Find new managed paths from the zip and delete any old paths that were removed
442
+ const newManagedPaths = findManagedPathsInZip(zipBuf);
443
+ const removedDeleted = deleteRemovedManagedPaths(
444
+ targetDir,
445
+ existingManifest.managedPaths || [],
446
+ newManagedPaths
447
+ );
448
+ if (removedDeleted.length > 0) {
449
+ result.deleted.push(...removedDeleted);
450
+ }
451
+
387
452
  // 5. Report
388
453
  console.log('');
389
454
  console.log(`✅ Cadet-Agent synced: v${oldVersionNorm} → v${newVersion}`);