diff --git a/.changeset/fuzzy-pigs-drop.md b/.changeset/fuzzy-pigs-drop.md new file mode 100644 index 00000000000..2f393ccd949 --- /dev/null +++ b/.changeset/fuzzy-pigs-drop.md @@ -0,0 +1,5 @@ +--- +"@kilocode/cli": patch +--- + +Install npm-managed plugins and runtime packages under Kilo's cache directory. diff --git a/packages/opencode/src/npm/index.ts b/packages/opencode/src/npm/index.ts index d6322d5488b..11838b960a6 100644 --- a/packages/opencode/src/npm/index.ts +++ b/packages/opencode/src/npm/index.ts @@ -9,8 +9,11 @@ import { definitions, flatten, nerfDarts, shorthands } from "@npmcli/config/lib/ import { Effect, Schema, Context, Layer, Option, FileSystem } from "effect" import { NodeFileSystem } from "@effect/platform-node" import { AppFileSystem } from "@opencode-ai/shared/filesystem" -import { Global } from "@opencode-ai/shared/global" +import { Global as Shared } from "@opencode-ai/shared/global" // kilocode_change import { EffectFlock } from "@opencode-ai/shared/util/effect-flock" +// kilocode_change start - keep npm-managed package caches in Kilo's XDG paths. +import { Global as Kilo } from "../global" +// kilocode_change end import { makeRuntime } from "../effect/runtime" @@ -103,7 +106,7 @@ export const layer = Layer.effect( Service, Effect.gen(function* () { const afs = yield* AppFileSystem.Service - const global = yield* Global.Service + const global = yield* Shared.Service // kilocode_change const fs = yield* FileSystem.FileSystem const flock = yield* EffectFlock.Service const directory = (pkg: string) => path.join(global.cache, "packages", sanitize(pkg)) @@ -299,10 +302,27 @@ export const layer = Layer.effect( }), ) +// kilocode_change start - the shared global layer is still opencode-branded upstream. +const kilo = Layer.succeed( + Shared.Service, + Shared.Service.of({ + home: Kilo.Path.home, + data: Kilo.Path.data, + cache: Kilo.Path.cache, + config: Kilo.Path.config, + state: Kilo.Path.state, + bin: Kilo.Path.bin, + log: Kilo.Path.log, + }), +) +// kilocode_change end + export const defaultLayer = layer.pipe( Layer.provide(EffectFlock.layer), Layer.provide(AppFileSystem.layer), - Layer.provide(Global.layer), + // kilocode_change start + Layer.provide(kilo), + // kilocode_change end Layer.provide(NodeFileSystem.layer), ) diff --git a/packages/opencode/test/npm.test.ts b/packages/opencode/test/npm.test.ts index a8ec92c2a7b..4bedc820f5a 100644 --- a/packages/opencode/test/npm.test.ts +++ b/packages/opencode/test/npm.test.ts @@ -3,6 +3,9 @@ import path from "path" import { describe, expect, test } from "bun:test" import { Npm } from "../src/npm" import { tmpdir } from "./fixture/fixture" +// kilocode_change start +import { Global } from "../src/global" +// kilocode_change end const win = process.platform === "win32" const writePackage = (dir: string, pkg: Record) => @@ -51,5 +54,19 @@ describe("Npm.install", () => { await expect(fs.stat(path.join(tmp.path, "node_modules", "prod-pkg"))).resolves.toBeDefined() await expect(fs.stat(path.join(tmp.path, "node_modules", "dev-pkg"))).rejects.toThrow() + }) // kilocode_change +}) // kilocode_change + +// kilocode_change start - Kilo should not inherit opencode-branded npm cache paths. +describe("Npm.add", () => { + test("uses Kilo cache path", async () => { + const dir = path.join(Global.Path.cache, "packages", "acme", "node_modules", ".bin") + await fs.mkdir(dir, { recursive: true }) + await Bun.write(path.join(dir, "acme"), "#!/usr/bin/env node\n") + + const result = await Npm.which("acme") + + expect(result).toBe(path.join(dir, "acme")) }) }) +// kilocode_change end