Alvin Unreal 1 maand geleden
bovenliggende
commit
5114ecc717
3 gewijzigde bestanden met toevoegingen van 93 en 7 verwijderingen
  1. 1 1
      package.json
  2. 61 5
      src/cli/cache.test.ts
  3. 31 1
      src/cli/config-io.ts

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "oh-my-opencode-slim",
-  "version": "2.0.0",
+  "version": "2.0.1",
   "description": "Lightweight agent orchestration plugin for OpenCode - a slimmed-down fork of oh-my-opencode",
   "main": "dist/index.js",
   "types": "dist/index.d.ts",

+ 61 - 5
src/cli/cache.test.ts

@@ -10,6 +10,7 @@ import {
   test,
 } from 'bun:test';
 import {
+  existsSync,
   mkdirSync,
   mkdtempSync,
   readFileSync,
@@ -90,7 +91,7 @@ describe('warmOpenCodePluginCache', () => {
     getExistingConfigPathSpy.mockRestore();
   });
 
-  test('prewarms the OpenCode cache for bunx installs', async () => {
+  test('prewarms the @latest OpenCode cache for bunx @latest installs', async () => {
     const tmpDir = mkdirTemp();
     const cacheHome = join(tmpDir, 'cache');
     process.env.XDG_CACHE_HOME = cacheHome;
@@ -104,7 +105,7 @@ describe('warmOpenCodePluginCache', () => {
     mkdirSync(join(packageRoot, 'dist', 'cli'), { recursive: true });
     writeFileSync(
       join(packageRoot, 'package.json'),
-      JSON.stringify({ name: 'oh-my-opencode-slim' }),
+      JSON.stringify({ name: 'oh-my-opencode-slim', version: '2.0.0' }),
     );
     process.argv[1] = join(packageRoot, 'dist', 'cli', 'index.js');
 
@@ -193,6 +194,61 @@ describe('warmOpenCodePluginCache', () => {
     rmSync(tmpDir, { recursive: true, force: true });
   });
 
+  test('removes stale @latest cache artifacts before reinstalling', async () => {
+    const tmpDir = mkdirTemp();
+    const cacheHome = join(tmpDir, 'cache');
+    process.env.XDG_CACHE_HOME = cacheHome;
+
+    const packageRoot = join(
+      tmpDir,
+      'bunx-1000-oh-my-opencode-slim@latest',
+      'node_modules',
+      'oh-my-opencode-slim',
+    );
+    mkdirSync(join(packageRoot, 'dist', 'cli'), { recursive: true });
+    writeFileSync(
+      join(packageRoot, 'package.json'),
+      JSON.stringify({ name: 'oh-my-opencode-slim', version: '2.0.1' }),
+    );
+    process.argv[1] = join(packageRoot, 'dist', 'cli', 'index.js');
+
+    const expectedCacheDir = join(
+      cacheHome,
+      'opencode',
+      'packages',
+      'oh-my-opencode-slim@latest',
+    );
+    const stalePluginDir = join(
+      expectedCacheDir,
+      'node_modules',
+      'oh-my-opencode-slim',
+    );
+    mkdirSync(stalePluginDir, { recursive: true });
+    writeFileSync(
+      join(stalePluginDir, 'package.json'),
+      JSON.stringify({ name: 'oh-my-opencode-slim', version: '1.1.2' }),
+    );
+    writeFileSync(join(expectedCacheDir, 'bun.lock'), 'stale lockfile');
+
+    crossSpawnMock.mockImplementation(
+      (_command: string[], options?: SpawnOptions) => {
+        expect(options?.cwd).toBe(expectedCacheDir);
+        expect(existsSync(stalePluginDir)).toBe(false);
+        expect(existsSync(join(expectedCacheDir, 'bun.lock'))).toBe(false);
+        writeCachedPluginPackage(options?.cwd);
+        return createSpawnResult();
+      },
+    );
+
+    const { warmOpenCodePluginCache } = await importFreshConfigIo();
+    const result = await warmOpenCodePluginCache();
+
+    expect(result?.success).toBe(true);
+    expect(result?.configPath).toBe(expectedCacheDir);
+
+    rmSync(tmpDir, { recursive: true, force: true });
+  });
+
   test('fails when bun install does not create the cached plugin package', async () => {
     const tmpDir = mkdirTemp();
     const cacheHome = join(tmpDir, 'cache');
@@ -409,7 +465,7 @@ describe('warmOpenCodePluginCache', () => {
     }
   });
 
-  test('uses running version from package.json when config is unpinned (bunx @beta scenario)', async () => {
+  test('uses requested dist-tag when config is unpinned (bunx @beta scenario)', async () => {
     const tmpDir = mkdirTemp();
     const cacheHome = join(tmpDir, 'cache');
     process.env.XDG_CACHE_HOME = cacheHome;
@@ -436,7 +492,7 @@ describe('warmOpenCodePluginCache', () => {
       cacheHome,
       'opencode',
       'packages',
-      'oh-my-opencode-slim@2.0.0-beta.13',
+      'oh-my-opencode-slim@beta',
     );
 
     expect(result?.success).toBe(true);
@@ -447,7 +503,7 @@ describe('warmOpenCodePluginCache', () => {
       name: 'oh-my-opencode-slim-cache',
       private: true,
       dependencies: {
-        'oh-my-opencode-slim': '2.0.0-beta.13',
+        'oh-my-opencode-slim': 'beta',
       },
     });
 

+ 31 - 1
src/cli/config-io.ts

@@ -4,6 +4,7 @@ import {
   mkdirSync,
   readFileSync,
   renameSync,
+  rmSync,
   statSync,
   writeFileSync,
 } from 'node:fs';
@@ -169,6 +170,23 @@ function getPinnedVersionFromConfig(): string | undefined {
   return undefined;
 }
 
+function getRequestedPackageTag(packageRoot: string): string | undefined {
+  const normalizedPath = normalizePathForMatch(packageRoot);
+  const marker = `/bunx-`;
+  const markerIndex = normalizedPath.lastIndexOf(marker);
+  if (markerIndex === -1) return undefined;
+
+  const bunxSegment = normalizedPath
+    .slice(markerIndex + marker.length)
+    .split('/')[0];
+  const packagePrefix = `${PACKAGE_NAME}@`;
+  const packageIndex = bunxSegment.lastIndexOf(packagePrefix);
+  if (packageIndex === -1) return undefined;
+
+  const tag = bunxSegment.slice(packageIndex + packagePrefix.length);
+  return tag || undefined;
+}
+
 /**
  * Reads the version from the package.json at the given package root.
  * Used as a fallback when the config entry is unpinned (e.g. bunx @beta install).
@@ -224,6 +242,15 @@ function writeOpenCodePluginCacheManifest(
   }
 }
 
+function removeOpenCodePluginCacheArtifacts(cacheDir: string): void {
+  rmSync(join(cacheDir, 'node_modules', PACKAGE_NAME), {
+    recursive: true,
+    force: true,
+  });
+  rmSync(join(cacheDir, 'bun.lock'), { force: true });
+  rmSync(join(cacheDir, 'bun.lockb'), { force: true });
+}
+
 function verifyOpenCodePluginCache(cacheDir: string): ConfigMergeResult | null {
   const pluginPackageJsonPath = join(
     cacheDir,
@@ -278,7 +305,8 @@ export async function warmOpenCodePluginCache(): Promise<ConfigMergeResult | nul
 
   const pinnedVersion = getPinnedVersionFromConfig();
   const runningVersion = getVersionFromPackageRoot(packageRoot);
-  const cacheVersion = pinnedVersion ?? runningVersion;
+  const requestedTag = getRequestedPackageTag(packageRoot);
+  const cacheVersion = pinnedVersion ?? requestedTag ?? runningVersion;
   const cacheDir = getOpenCodePluginCacheDir(cacheVersion);
 
   try {
@@ -297,6 +325,8 @@ export async function warmOpenCodePluginCache(): Promise<ConfigMergeResult | nul
   );
   if (manifestError) return manifestError;
 
+  removeOpenCodePluginCacheArtifacts(cacheDir);
+
   try {
     const proc = crossSpawn(['bun', 'install', '--ignore-scripts'], {
       cwd: cacheDir,