mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-09-01 15:32:11 +08:00
7aaa25d97e
Introduce a primaryWorktree Effect that queries Git plumbing commands to locate the main checkout from any linked worktree. Integrate it into config loading so .kilo directory settings from the primary checkout act as local-scoped fallbacks beneath the active worktree and KILO_CONFIG_DIR overrides. Wire primaryPaths into skill discovery so project skills installed in the primary checkout appear as fallbacks unless overridden locally. Refactor session family matching to consider sandbox directories and filter out nested Git repositories when resolving worktree roots. Convert baselineDirectory in indexing to an Effect that delegates to primaryWorktree instead of reading Instance.project.worktree directly. Restore the content() signal usage in the TUI text part renderer. Provide Git.defaultLayer across all affected test layers and add coverage for linked worktrees, submodules, paths with spaces, sandbox project matching, and primary config directory precedence.
140 lines
5.2 KiB
TypeScript
140 lines
5.2 KiB
TypeScript
import { afterEach, describe, expect } from "bun:test"
|
|
import { Effect, Layer } from "effect"
|
|
import { FetchHttpClient } from "effect/unstable/http"
|
|
import { CrossSpawnSpawner } from "@opencode-ai/core/cross-spawn-spawner"
|
|
import { AppFileSystem } from "@opencode-ai/core/filesystem"
|
|
import { EffectFlock } from "@opencode-ai/core/util/effect-flock"
|
|
import path from "path"
|
|
import { pathToFileURL } from "url"
|
|
import { Auth } from "../../src/auth"
|
|
import { Bus } from "../../src/bus"
|
|
import { Config } from "../../src/config/config"
|
|
import { Env } from "../../src/env"
|
|
import { Git } from "../../src/git" // kilocode_change
|
|
import { RuntimeFlags } from "../../src/effect/runtime-flags"
|
|
import { Workspace } from "../../src/control-plane/workspace"
|
|
import { Plugin } from "../../src/plugin/index"
|
|
import { InstanceBootstrap } from "../../src/project/bootstrap-service"
|
|
import { InstanceStore } from "../../src/project/instance-store"
|
|
import { Project } from "../../src/project/project"
|
|
import { Vcs } from "../../src/project/vcs"
|
|
import { InstanceState } from "../../src/effect/instance-state"
|
|
import { Session } from "../../src/session/session"
|
|
import { SessionPrompt } from "../../src/session/prompt"
|
|
import { SyncEvent } from "../../src/sync"
|
|
import { disposeAllInstances, provideTmpdirInstance } from "../fixture/fixture"
|
|
import { testEffect } from "../lib/effect"
|
|
import { AccountTest } from "../fake/account"
|
|
import { AuthTest } from "../fake/auth"
|
|
import { NpmTest } from "../fake/npm"
|
|
|
|
const configLayer = Config.layer.pipe(
|
|
Layer.provide(Git.defaultLayer), // kilocode_change
|
|
Layer.provide(EffectFlock.defaultLayer),
|
|
Layer.provide(AppFileSystem.defaultLayer),
|
|
Layer.provide(Env.defaultLayer),
|
|
Layer.provide(AuthTest.empty),
|
|
Layer.provide(AccountTest.empty),
|
|
Layer.provide(NpmTest.noop),
|
|
Layer.provide(FetchHttpClient.layer),
|
|
)
|
|
const pluginLayer = Plugin.layer.pipe(
|
|
Layer.provide(Bus.layer),
|
|
Layer.provide(configLayer),
|
|
Layer.provide(RuntimeFlags.layer({ disableDefaultPlugins: true })),
|
|
)
|
|
const noopBootstrapLayer = Layer.succeed(InstanceBootstrap.Service, InstanceBootstrap.Service.of({ run: Effect.void }))
|
|
const workspaceLayer = Workspace.layer.pipe(
|
|
Layer.provide(Auth.defaultLayer),
|
|
Layer.provide(Session.defaultLayer),
|
|
Layer.provide(SyncEvent.defaultLayer),
|
|
Layer.provide(SessionPrompt.defaultLayer),
|
|
Layer.provide(Project.defaultLayer),
|
|
Layer.provide(Vcs.defaultLayer),
|
|
Layer.provide(FetchHttpClient.layer),
|
|
Layer.provide(AppFileSystem.defaultLayer),
|
|
Layer.provide(InstanceStore.defaultLayer.pipe(Layer.provide(noopBootstrapLayer))),
|
|
Layer.provide(RuntimeFlags.layer({ experimentalWorkspaces: true })),
|
|
)
|
|
const it = testEffect(Layer.mergeAll(pluginLayer, workspaceLayer, CrossSpawnSpawner.defaultLayer))
|
|
|
|
afterEach(async () => {
|
|
await disposeAllInstances()
|
|
})
|
|
|
|
describe("plugin.workspace", () => {
|
|
it.live("plugin can install a workspace adapter", () =>
|
|
provideTmpdirInstance((dir) =>
|
|
Effect.gen(function* () {
|
|
const type = `plug-${Math.random().toString(36).slice(2)}`
|
|
const file = path.join(dir, "plugin.ts")
|
|
const mark = path.join(dir, "created.json")
|
|
const space = path.join(dir, "space")
|
|
yield* Effect.promise(() =>
|
|
Bun.write(
|
|
file,
|
|
[
|
|
"export default async ({ experimental_workspace }) => {",
|
|
` experimental_workspace.register(${JSON.stringify(type)}, {`,
|
|
' name: "plug",',
|
|
' description: "plugin workspace adapter",',
|
|
" configure(input) {",
|
|
` return { ...input, name: "plug", branch: "plug/main", directory: ${JSON.stringify(space)} }`,
|
|
" },",
|
|
" async create(input) {",
|
|
` await Bun.write(${JSON.stringify(mark)}, JSON.stringify(input))`,
|
|
" },",
|
|
" async remove() {},",
|
|
" target(input) {",
|
|
' return { type: "local", directory: input.directory }',
|
|
" },",
|
|
" })",
|
|
" return {}",
|
|
"}",
|
|
"",
|
|
].join("\n"),
|
|
),
|
|
)
|
|
|
|
yield* Effect.promise(() =>
|
|
Bun.write(
|
|
path.join(dir, "opencode.json"),
|
|
JSON.stringify(
|
|
{
|
|
$schema: "https://opencode.ai/config.json",
|
|
plugin: [pathToFileURL(file).href],
|
|
},
|
|
null,
|
|
2,
|
|
),
|
|
),
|
|
)
|
|
|
|
const plugin = yield* Plugin.Service
|
|
yield* plugin.init()
|
|
const workspace = yield* Workspace.Service
|
|
const ctx = yield* InstanceState.context
|
|
const info = yield* workspace.create({
|
|
type,
|
|
branch: null,
|
|
extra: { key: "value" },
|
|
projectID: ctx.project.id,
|
|
})
|
|
|
|
expect(info.type).toBe(type)
|
|
expect(info.name).toBe("plug")
|
|
expect(info.branch).toBe("plug/main")
|
|
expect(info.directory).toBe(space)
|
|
expect(info.extra).toEqual({ key: "value" })
|
|
expect(JSON.parse(yield* Effect.promise(() => Bun.file(mark).text()))).toMatchObject({
|
|
type,
|
|
name: "plug",
|
|
branch: "plug/main",
|
|
directory: space,
|
|
extra: { key: "value" },
|
|
})
|
|
}),
|
|
),
|
|
)
|
|
})
|