test(core): reproduce explorer tool leak

This commit is contained in:
Kit Langton
2026-07-07 11:53:22 -04:00
parent d27746e5b3
commit a142d76eec
2 changed files with 68 additions and 1 deletions
+37 -1
View File
@@ -3,7 +3,7 @@ import path from "path"
import { describe, expect } from "bun:test"
import { Config } from "@opencode-ai/schema/config"
import { Plugin } from "@opencode-ai/schema/plugin"
import { Context, DateTime, Effect, Equal, Hash, RcMap, Schema, Stream } from "effect"
import { Context, DateTime, Deferred, Effect, Equal, Hash, RcMap, Schema, Stream } from "effect"
import { Plugin as EffectPlugin } from "@opencode-ai/plugin/v2/effect"
import { AgentV2 } from "@opencode-ai/core/agent"
import { Catalog } from "@opencode-ai/core/catalog"
@@ -66,6 +66,42 @@ describe("LocationServiceMap", () => {
),
)
itWithSdk.live("does not advertise shell before explorer activation completes", () =>
Effect.acquireRelease(
Effect.promise(() => tmpdir()),
(dir) => Effect.promise(() => dir[Symbol.asyncDispose]()),
).pipe(
Effect.flatMap((dir) =>
Effect.gen(function* () {
const started = yield* Deferred.make<void>()
const release = yield* Deferred.make<void>()
const sdk = yield* SdkPlugins.Service
yield* sdk.register(
EffectPlugin.define({
id: "blocked-initial-activation",
effect: () => Deferred.succeed(started, undefined).pipe(Effect.andThen(Deferred.await(release))),
}),
)
const locations = yield* LocationServiceMap.Service
const context = yield* locations.contextEffect(
Location.Ref.make({ directory: AbsolutePath.make(dir.path) }),
)
yield* Deferred.await(started)
const tools = yield* Effect.gen(function* () {
const agents = yield* AgentV2.Service
const registry = yield* ToolRegistry.Service
const explorer = yield* agents.select("explore")
return yield* toolDefinitions(registry, explorer.info?.permissions)
}).pipe(Effect.provide(context), Effect.ensuring(Deferred.succeed(release, undefined)))
expect(tools.map((tool) => tool.name)).not.toContain("shell")
}),
),
),
)
it.live("applies ordered plugin config operations during boot", () =>
Effect.acquireRelease(
Effect.promise(() => tmpdir()),
+31
View File
@@ -1045,6 +1045,37 @@ describe("SessionRunnerLLM", () => {
}),
)
it.effect("does not advertise unrestricted tools while the selected agent is unavailable", () =>
Effect.gen(function* () {
yield* setup
const { db } = yield* Database.Service
const registry = yield* ToolRegistry.Service
yield* registry.register({
shell: Tool.make({
description: "Execute a shell command",
input: Schema.Struct({ command: Schema.String }),
output: Schema.Struct({}),
execute: () => Effect.succeed({}),
}),
})
yield* db
.update(SessionTable)
.set({ agent: "explore" })
.where(eq(SessionTable.id, sessionID))
.run()
.pipe(Effect.orDie)
const session = yield* SessionV2.Service
yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Inspect files" }), resume: false })
requests.length = 0
response = []
yield* session.resume(sessionID)
expect(requests).toHaveLength(1)
expect(requests[0]?.tools.map((tool) => tool.name)).not.toContain("shell")
}),
)
it.effect("updates selected-agent skill guidance after an agent switch", () =>
Effect.gen(function* () {
const session = yield* setup