From d3a8f83bd24c1dd3acb4f3c641e9af5f766e11a2 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Thu, 7 May 2026 14:46:53 +0000 Subject: [PATCH] test(cli): extract Kilo-specific instruction tests to own file Move KILO_CONFIG_DIR profile fallback tests out of the shared upstream instruction.test.ts into packages/opencode/test/kilocode/instruction.test.ts to reduce future merge conflicts with opencode. --- .../test/kilocode/instruction.test.ts | 137 ++++++++++++++++++ .../opencode/test/session/instruction.test.ts | 73 ---------- 2 files changed, 137 insertions(+), 73 deletions(-) create mode 100644 packages/opencode/test/kilocode/instruction.test.ts diff --git a/packages/opencode/test/kilocode/instruction.test.ts b/packages/opencode/test/kilocode/instruction.test.ts new file mode 100644 index 00000000000..6d76f01b054 --- /dev/null +++ b/packages/opencode/test/kilocode/instruction.test.ts @@ -0,0 +1,137 @@ +// kilocode_change - new file +import { describe, expect } from "bun:test" +import path from "path" +import { Effect, FileSystem, Layer } from "effect" +import { FetchHttpClient } from "effect/unstable/http" +import { NodeFileSystem } from "@effect/platform-node" +import { CrossSpawnSpawner } from "@opencode-ai/core/cross-spawn-spawner" +import { AppFileSystem } from "@opencode-ai/core/filesystem" +import { Config } from "@/config/config" +import { emptyConsoleState } from "@/config/console-state" +import { Instruction } from "../../src/session/instruction" +import { Global } from "@opencode-ai/core/global" +import { provideInstance, tmpdirScoped } from "../fixture/fixture" +import { testEffect } from "../lib/effect" + +const it = testEffect(Layer.mergeAll(CrossSpawnSpawner.defaultLayer, NodeFileSystem.layer)) + +const configLayer = Layer.succeed( + Config.Service, + Config.Service.of({ + get: () => Effect.succeed({}), + getGlobal: () => Effect.succeed({}), + getConsoleState: () => Effect.succeed(emptyConsoleState), + update: () => Effect.void, + updateGlobal: (config) => Effect.succeed(config), + invalidate: () => Effect.void, + directories: () => Effect.succeed([]), + waitForDependencies: () => Effect.void, + warnings: () => Effect.succeed([]), + }), +) + +const instructionLayer = (global: Partial) => + Instruction.layer.pipe( + Layer.provide(configLayer), + Layer.provide(AppFileSystem.defaultLayer), + Layer.provide(FetchHttpClient.layer), + Layer.provide(Global.layerWith(global)), + ) + +const provideInstruction = + (global: Partial) => + (self: Effect.Effect) => + self.pipe(Effect.provide(instructionLayer(global))) + +const write = (filepath: string, content: string) => + Effect.gen(function* () { + const fs = yield* FileSystem.FileSystem + yield* fs.makeDirectory(path.dirname(filepath), { recursive: true }) + yield* fs.writeFileString(filepath, content) + }) + +const writeFiles = (dir: string, files: Record) => + Effect.all( + Object.entries(files).map(([file, content]) => write(path.join(dir, file), content)), + { discard: true }, + ) + +const tmpWithFiles = (files: Record) => + Effect.gen(function* () { + const dir = yield* tmpdirScoped() + yield* writeFiles(dir, files) + return dir + }) + +const withConfigDir = + (value: string | undefined) => + (self: Effect.Effect) => + Effect.gen(function* () { + const original = process.env["KILO_CONFIG_DIR"] + if (value === undefined) delete process.env["KILO_CONFIG_DIR"] + else process.env["KILO_CONFIG_DIR"] = value + yield* Effect.addFinalizer(() => + Effect.sync(() => { + if (original === undefined) delete process.env["KILO_CONFIG_DIR"] + else process.env["KILO_CONFIG_DIR"] = original + }), + ) + return yield* self + }) + +describe("Instruction.systemPaths KILO_CONFIG_DIR profile fallback", () => { + it.live("prefers KILO_CONFIG_DIR AGENTS.md over global when both exist", () => + Effect.gen(function* () { + const profileTmp = yield* tmpWithFiles({ "AGENTS.md": "# Profile Instructions" }) + const globalTmp = yield* tmpWithFiles({ "AGENTS.md": "# Global Instructions" }) + const projectTmp = yield* tmpdirScoped() + + yield* Effect.gen(function* () { + const svc = yield* Instruction.Service + const paths = yield* svc.systemPaths() + expect(paths.has(path.join(profileTmp, "AGENTS.md"))).toBe(true) + expect(paths.has(path.join(globalTmp, "AGENTS.md"))).toBe(false) + }).pipe( + provideInstance(projectTmp), + provideInstruction({ home: globalTmp, config: globalTmp }), + withConfigDir(profileTmp), + ) + }), + ) + + it.live("falls back to global AGENTS.md when KILO_CONFIG_DIR has no AGENTS.md", () => + Effect.gen(function* () { + const profileTmp = yield* tmpdirScoped() + const globalTmp = yield* tmpWithFiles({ "AGENTS.md": "# Global Instructions" }) + const projectTmp = yield* tmpdirScoped() + + yield* Effect.gen(function* () { + const svc = yield* Instruction.Service + const paths = yield* svc.systemPaths() + expect(paths.has(path.join(profileTmp, "AGENTS.md"))).toBe(false) + expect(paths.has(path.join(globalTmp, "AGENTS.md"))).toBe(true) + }).pipe( + provideInstance(projectTmp), + provideInstruction({ home: globalTmp, config: globalTmp }), + withConfigDir(profileTmp), + ) + }), + ) + + it.live("uses global AGENTS.md when KILO_CONFIG_DIR is not set", () => + Effect.gen(function* () { + const globalTmp = yield* tmpWithFiles({ "AGENTS.md": "# Global Instructions" }) + const projectTmp = yield* tmpdirScoped() + + yield* Effect.gen(function* () { + const svc = yield* Instruction.Service + const paths = yield* svc.systemPaths() + expect(paths.has(path.join(globalTmp, "AGENTS.md"))).toBe(true) + }).pipe( + provideInstance(projectTmp), + provideInstruction({ home: globalTmp, config: globalTmp }), + withConfigDir(undefined), + ) + }), + ) +}) diff --git a/packages/opencode/test/session/instruction.test.ts b/packages/opencode/test/session/instruction.test.ts index 8050b4b9f5f..3ad97540ee9 100644 --- a/packages/opencode/test/session/instruction.test.ts +++ b/packages/opencode/test/session/instruction.test.ts @@ -244,77 +244,4 @@ describe("Instruction.systemPaths global config", () => { }).pipe(provideInstance(projectTmp), provideInstruction({ home: globalTmp, config: globalTmp })) }), ) - - // kilocode_change start - KILO_CONFIG_DIR profile fallback (replaces dropped Kilo-specific tests) - const withConfigDir = - (value: string | undefined) => - (self: Effect.Effect) => - Effect.gen(function* () { - const original = process.env["KILO_CONFIG_DIR"] - if (value === undefined) delete process.env["KILO_CONFIG_DIR"] - else process.env["KILO_CONFIG_DIR"] = value - yield* Effect.addFinalizer(() => - Effect.sync(() => { - if (original === undefined) delete process.env["KILO_CONFIG_DIR"] - else process.env["KILO_CONFIG_DIR"] = original - }), - ) - return yield* self - }) - - it.live("prefers KILO_CONFIG_DIR AGENTS.md over global when both exist", () => - Effect.gen(function* () { - const profileTmp = yield* tmpWithFiles({ "AGENTS.md": "# Profile Instructions" }) - const globalTmp = yield* tmpWithFiles({ "AGENTS.md": "# Global Instructions" }) - const projectTmp = yield* tmpdirScoped() - - yield* Effect.gen(function* () { - const svc = yield* Instruction.Service - const paths = yield* svc.systemPaths() - expect(paths.has(path.join(profileTmp, "AGENTS.md"))).toBe(true) - expect(paths.has(path.join(globalTmp, "AGENTS.md"))).toBe(false) - }).pipe( - provideInstance(projectTmp), - provideInstruction({ home: globalTmp, config: globalTmp }), - withConfigDir(profileTmp), - ) - }), - ) - - it.live("falls back to global AGENTS.md when KILO_CONFIG_DIR has no AGENTS.md", () => - Effect.gen(function* () { - const profileTmp = yield* tmpdirScoped() - const globalTmp = yield* tmpWithFiles({ "AGENTS.md": "# Global Instructions" }) - const projectTmp = yield* tmpdirScoped() - - yield* Effect.gen(function* () { - const svc = yield* Instruction.Service - const paths = yield* svc.systemPaths() - expect(paths.has(path.join(profileTmp, "AGENTS.md"))).toBe(false) - expect(paths.has(path.join(globalTmp, "AGENTS.md"))).toBe(true) - }).pipe( - provideInstance(projectTmp), - provideInstruction({ home: globalTmp, config: globalTmp }), - withConfigDir(profileTmp), - ) - }), - ) - - it.live("uses global AGENTS.md when KILO_CONFIG_DIR is not set", () => - Effect.gen(function* () { - const globalTmp = yield* tmpWithFiles({ "AGENTS.md": "# Global Instructions" }) - const projectTmp = yield* tmpdirScoped() - - yield* Effect.gen(function* () { - const svc = yield* Instruction.Service - const paths = yield* svc.systemPaths() - expect(paths.has(path.join(globalTmp, "AGENTS.md"))).toBe(true) - }).pipe( - provideInstance(projectTmp), - provideInstruction({ home: globalTmp, config: globalTmp }), - withConfigDir(undefined), - ) - }), - ) - // kilocode_change end })