refactor(core): convert more opencode tests to nodes (#34464)
This commit is contained in:
parent
de185559dd
commit
d4fd528152
45 changed files with 209 additions and 203 deletions
|
|
@ -2,6 +2,7 @@ import { Agent } from "@/agent/agent"
|
|||
import { Command } from "@/command"
|
||||
import { InstanceRef } from "@/effect/instance-ref"
|
||||
import { InstanceStore } from "@/project/instance-store"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { ProviderV2 } from "@opencode-ai/core/provider"
|
||||
import { ModelV2 } from "@opencode-ai/core/model"
|
||||
import { Provider } from "@/provider/provider"
|
||||
|
|
@ -207,4 +208,8 @@ export const defaultLayer = layer.pipe(
|
|||
Layer.provide(InstanceStore.defaultLayer),
|
||||
)
|
||||
|
||||
export const loaderNode = LayerNode.make({ service: Loader, layer: loaderLayer, deps: [Provider.node, Agent.node, Command.node, InstanceStore.node] })
|
||||
|
||||
export const node = LayerNode.make({ service: Service, layer, deps: [loaderNode] })
|
||||
|
||||
export * as Directory from "./directory"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ import type { AgentSideConnection, Usage } from "@agentclientprotocol/sdk"
|
|||
import type { AssistantMessage as OpenCodeAssistantMessage, Message } from "@opencode-ai/sdk/v2"
|
||||
import { InstanceRef } from "@/effect/instance-ref"
|
||||
import { InstanceStore } from "@/project/instance-store"
|
||||
import { makeGlobalNode, Node } from "@opencode-ai/core/effect/app-node"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { ProviderV2 } from "@opencode-ai/core/provider"
|
||||
import { ModelV2 } from "@opencode-ai/core/model"
|
||||
import { Provider } from "@/provider/provider"
|
||||
|
|
@ -229,4 +231,14 @@ export const defaultLayer = layer.pipe(
|
|||
Layer.provide(InstanceStore.defaultLayer),
|
||||
)
|
||||
|
||||
export const messageLoaderNode = LayerNode.unbound(MessageLoader, Node.tags.values.global)
|
||||
|
||||
export const contextLimitLoaderNode = makeGlobalNode({
|
||||
service: ContextLimitLoader,
|
||||
layer: contextLimitLoaderLayer,
|
||||
deps: [Provider.node, InstanceStore.node],
|
||||
})
|
||||
|
||||
export const node = makeGlobalNode({ service: Service, layer, deps: [messageLoaderNode, contextLimitLoaderNode] })
|
||||
|
||||
export * as UsageService from "./usage"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
import { expect } from "bun:test"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { httpClient } from "@opencode-ai/core/effect/app-node-platform"
|
||||
import { Duration, Effect, Layer, Option, Schema } from "effect"
|
||||
import { sql } from "drizzle-orm"
|
||||
import { HttpClient, HttpClientError, HttpClientResponse } from "effect/unstable/http"
|
||||
|
|
@ -25,15 +27,16 @@ const truncate = Layer.effectDiscard(
|
|||
yield* db.run(sql`DELETE FROM account_state`)
|
||||
yield* db.run(sql`DELETE FROM account`)
|
||||
}),
|
||||
).pipe(Layer.provide(Database.defaultLayer))
|
||||
)
|
||||
const truncateNode = LayerNode.make({ name: "truncate-account", layer: truncate, deps: [Database.node] })
|
||||
|
||||
const it = testEffect(Layer.merge(AccountRepo.defaultLayer, truncate))
|
||||
const it = testEffect(LayerNode.compile(LayerNode.group([AccountRepo.node, truncateNode])))
|
||||
|
||||
const insideEagerRefreshWindow = Duration.toMillis(Duration.minutes(1))
|
||||
const outsideEagerRefreshWindow = Duration.toMillis(Duration.minutes(10))
|
||||
|
||||
const live = (client: HttpClient.HttpClient) =>
|
||||
Account.layer.pipe(Layer.provide(Layer.succeed(HttpClient.HttpClient, client)))
|
||||
LayerNode.compile(Account.node, [[httpClient, Layer.succeed(HttpClient.HttpClient, client)]])
|
||||
|
||||
const json = (req: Parameters<typeof HttpClientResponse.fromWeb>[0], body: unknown, status = 200) =>
|
||||
HttpClientResponse.fromWeb(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { describe, expect } from "bun:test"
|
||||
import { Directory } from "@/acp/directory"
|
||||
import { Command } from "@/command"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { ProviderV2 } from "@opencode-ai/core/provider"
|
||||
import { ModelV2 } from "@opencode-ai/core/model"
|
||||
import { Provider } from "@/provider/provider"
|
||||
|
|
@ -83,8 +84,9 @@ const snapshot = (directory: string) => {
|
|||
}
|
||||
|
||||
const fakeLayer = (calls: string[]) =>
|
||||
Directory.layer.pipe(
|
||||
Layer.provide(
|
||||
LayerNode.compile(Directory.node, [
|
||||
[
|
||||
Directory.loaderNode,
|
||||
Layer.succeed(
|
||||
Directory.Loader,
|
||||
Directory.Loader.of({
|
||||
|
|
@ -95,8 +97,8 @@ const fakeLayer = (calls: string[]) =>
|
|||
}),
|
||||
}),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
])
|
||||
|
||||
describe("ACP directory snapshot", () => {
|
||||
it.effect("two concurrent callers share one load", () => {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { describe, expect, test } from "bun:test"
|
||||
import type { SessionNotification } from "@agentclientprotocol/sdk"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { ProviderV2 } from "@opencode-ai/core/provider"
|
||||
import { ModelV2 } from "@opencode-ai/core/model"
|
||||
import { UsageService } from "@/acp/usage"
|
||||
|
|
@ -97,24 +98,26 @@ const fakeLayer = (input: {
|
|||
readonly messages?: Effect.Effect<readonly UsageService.SessionMessage[], unknown>
|
||||
readonly providers?: (directory: string) => Effect.Effect<Record<ProviderV2.ID, Provider.Info>, unknown>
|
||||
}) =>
|
||||
UsageService.layer.pipe(
|
||||
Layer.provide(
|
||||
Layer.mergeAll(
|
||||
Layer.succeed(
|
||||
UsageService.MessageLoader,
|
||||
UsageService.MessageLoader.of({
|
||||
messages: () => input.messages ?? Effect.succeed([]),
|
||||
}),
|
||||
),
|
||||
Layer.succeed(
|
||||
UsageService.ContextLimitLoader,
|
||||
UsageService.ContextLimitLoader.of({
|
||||
providers: input.providers ?? (() => Effect.succeed(providers())),
|
||||
}),
|
||||
),
|
||||
LayerNode.compile(UsageService.node, [
|
||||
[
|
||||
UsageService.messageLoaderNode,
|
||||
Layer.succeed(
|
||||
UsageService.MessageLoader,
|
||||
UsageService.MessageLoader.of({
|
||||
messages: () => input.messages ?? Effect.succeed([]),
|
||||
}),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
[
|
||||
UsageService.contextLimitLoaderNode,
|
||||
Layer.succeed(
|
||||
UsageService.ContextLimitLoader,
|
||||
UsageService.ContextLimitLoader.of({
|
||||
providers: input.providers ?? (() => Effect.succeed(providers())),
|
||||
}),
|
||||
),
|
||||
],
|
||||
])
|
||||
|
||||
const connection = (updates: SessionNotification[]) => ({
|
||||
sessionUpdate(params: SessionNotification) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { afterEach, expect } from "bun:test"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { Cause, Effect, Exit, Layer } from "effect"
|
||||
import path from "path"
|
||||
import { disposeAllInstances, TestInstance } from "../fixture/fixture"
|
||||
|
|
@ -14,18 +15,11 @@ import { Plugin } from "../../src/plugin"
|
|||
import { Provider } from "../../src/provider/provider"
|
||||
import { Skill } from "../../src/skill"
|
||||
import { Truncate } from "../../src/tool/truncate"
|
||||
import { LocationServiceMap, locationServiceMapLayer } from "@opencode-ai/core/location-services"
|
||||
|
||||
const agentLayer = (flags: Partial<RuntimeFlags.Info> = {}) =>
|
||||
Agent.layer.pipe(
|
||||
Layer.provide(Plugin.defaultLayer),
|
||||
Layer.provide(Provider.defaultLayer),
|
||||
Layer.provide(Auth.defaultLayer),
|
||||
Layer.provide(Config.defaultLayer),
|
||||
Layer.provide(Skill.defaultLayer),
|
||||
Layer.provide(locationServiceMapLayer),
|
||||
Layer.provide(RuntimeFlags.layer(flags)),
|
||||
)
|
||||
LayerNode.compile(LayerNode.group([Agent.node, Plugin.node, Provider.node, Auth.node, Config.node, Skill.node, RuntimeFlags.node]), [
|
||||
[RuntimeFlags.node, RuntimeFlags.layer(flags)],
|
||||
])
|
||||
|
||||
const it = testEffect(agentLayer())
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import path from "path"
|
||||
import { NodeFileSystem } from "@effect/platform-node"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { FSUtil } from "@opencode-ai/core/fs-util"
|
||||
import { describe, expect, test } from "bun:test"
|
||||
import { Effect, FileSystem, Layer } from "effect"
|
||||
|
|
@ -98,7 +99,7 @@ function userMessage(
|
|||
}
|
||||
}
|
||||
|
||||
const it = testEffect(Layer.mergeAll(FSUtil.defaultLayer, NodeFileSystem.layer))
|
||||
const it = testEffect(Layer.mergeAll(LayerNode.compile(FSUtil.node), NodeFileSystem.layer))
|
||||
|
||||
function remap(root: string, file: string) {
|
||||
if (file === Global.Path.state) {
|
||||
|
|
@ -123,7 +124,7 @@ function remappedFs(root: string) {
|
|||
writeJson: (file, data, mode) => fs.writeJson(remap(root, file), data, mode),
|
||||
})
|
||||
}),
|
||||
).pipe(Layer.provide(FSUtil.defaultLayer))
|
||||
).pipe(Layer.provide(LayerNode.compile(FSUtil.node)))
|
||||
}
|
||||
|
||||
describe("run variant shared", () => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { expect } from "bun:test"
|
||||
import path from "path"
|
||||
import { pathToFileURL } from "url"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { Effect, Layer } from "effect"
|
||||
import { FSUtil } from "@opencode-ai/core/fs-util"
|
||||
import { Global } from "@opencode-ai/core/global"
|
||||
|
|
@ -11,7 +12,7 @@ import { TuiConfig } from "../../src/config/tui"
|
|||
import { TestInstance } from "../fixture/fixture"
|
||||
import { testEffect } from "../lib/effect"
|
||||
|
||||
const it = testEffect(Layer.mergeAll(Config.defaultLayer, FSUtil.defaultLayer))
|
||||
const it = testEffect(LayerNode.compile(LayerNode.group([Config.node, FSUtil.node])))
|
||||
const winIt = process.platform === "win32" ? it.instance : it.instance.skip
|
||||
|
||||
const globalConfigFiles = ["opencode.json", "opencode.jsonc", "tui.json", "tui.jsonc"].map((file) =>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { expect } from "bun:test"
|
||||
import { CrossSpawnSpawner } from "@opencode-ai/core/cross-spawn-spawner"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { $ } from "bun"
|
||||
import { Context, Deferred, Duration, Effect, Exit, Fiber, Layer } from "effect"
|
||||
import { InstanceState } from "@/effect/instance-state"
|
||||
|
|
@ -12,7 +13,7 @@ import {
|
|||
} from "../fixture/fixture"
|
||||
import { testEffect } from "../lib/effect"
|
||||
|
||||
const it = testEffect(Layer.mergeAll(CrossSpawnSpawner.defaultLayer, testInstanceStoreLayer))
|
||||
const it = testEffect(Layer.mergeAll(LayerNode.compile(CrossSpawnSpawner.node), testInstanceStoreLayer))
|
||||
|
||||
const access = <A, E>(state: InstanceState.InstanceState<A, E>, dir: string) =>
|
||||
InstanceState.get(state).pipe(provideInstanceEffect(dir))
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { NodeFileSystem } from "@effect/platform-node"
|
||||
import { describe, expect } from "bun:test"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { Effect, Layer } from "effect"
|
||||
import { provideTmpdirInstance, testInstanceStoreLayer, TestInstance } from "../fixture/fixture"
|
||||
import { testEffect } from "../lib/effect"
|
||||
|
|
@ -7,7 +8,7 @@ import { CrossSpawnSpawner } from "@opencode-ai/core/cross-spawn-spawner"
|
|||
import { Format } from "../../src/format"
|
||||
import * as Formatter from "../../src/format/formatter"
|
||||
|
||||
const it = testEffect(Layer.mergeAll(Format.defaultLayer, CrossSpawnSpawner.defaultLayer, NodeFileSystem.layer))
|
||||
const it = testEffect(Layer.mergeAll(LayerNode.compile(LayerNode.group([Format.node, CrossSpawnSpawner.node])), NodeFileSystem.layer))
|
||||
|
||||
describe("Format", () => {
|
||||
it.instance("status() returns empty list when no formatters are configured", () =>
|
||||
|
|
@ -106,7 +107,7 @@ describe("Format", () => {
|
|||
)
|
||||
|
||||
testEffect(
|
||||
Layer.mergeAll(Format.defaultLayer, CrossSpawnSpawner.defaultLayer, NodeFileSystem.layer, testInstanceStoreLayer),
|
||||
Layer.mergeAll(LayerNode.compile(LayerNode.group([Format.node, CrossSpawnSpawner.node])), NodeFileSystem.layer, testInstanceStoreLayer),
|
||||
).live("status() initializes formatter state per directory", () =>
|
||||
Effect.gen(function* () {
|
||||
const a = yield* provideTmpdirInstance(() => Format.use.status(), {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
import { describe, expect } from "bun:test"
|
||||
import { makeGlobalNode } from "@opencode-ai/core/effect/app-node"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { httpClient } from "@opencode-ai/core/effect/app-node-platform"
|
||||
import { Effect, Layer, Stream } from "effect"
|
||||
import { HttpClient, HttpClientRequest, HttpClientResponse } from "effect/unstable/http"
|
||||
import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"
|
||||
|
|
@ -52,8 +55,12 @@ function testLayer(
|
|||
httpHandler: (request: HttpClientRequest.HttpClientRequest) => Response,
|
||||
spawnHandler?: (cmd: string, args: readonly string[]) => string | { code: number; stdout?: string; stderr?: string },
|
||||
) {
|
||||
const appProcess = AppProcess.layer.pipe(Layer.provide(mockSpawner(spawnHandler)))
|
||||
return Installation.layer.pipe(Layer.provide(mockHttpClient(httpHandler)), Layer.provide(appProcess))
|
||||
const spawnerNode = makeGlobalNode({ service: ChildProcessSpawner.ChildProcessSpawner, layer: mockSpawner(spawnHandler), deps: [] })
|
||||
const appProcessNode = makeGlobalNode({ service: AppProcess.Service, layer: AppProcess.layer, deps: [spawnerNode] })
|
||||
return LayerNode.compile(Installation.node, [
|
||||
[httpClient, mockHttpClient(httpHandler)],
|
||||
[AppProcess.node, appProcessNode],
|
||||
])
|
||||
}
|
||||
|
||||
describe("installation", () => {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { describe, expect, spyOn } from "bun:test"
|
||||
import path from "path"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { Deferred, Effect, Layer } from "effect"
|
||||
import { EventV2Bridge } from "@/event-v2-bridge"
|
||||
import { Config } from "@/config/config"
|
||||
|
|
@ -11,19 +12,17 @@ import { TestInstance } from "../fixture/fixture"
|
|||
import { awaitWithTimeout, testEffect } from "../lib/effect"
|
||||
|
||||
const lspLayer = (flags: Parameters<typeof RuntimeFlags.layer>[0] = {}) =>
|
||||
LSP.layer.pipe(
|
||||
Layer.provide(Config.defaultLayer),
|
||||
Layer.provide(RuntimeFlags.layer(flags)),
|
||||
Layer.provideMerge(EventV2Bridge.defaultLayer),
|
||||
)
|
||||
LayerNode.compile(LayerNode.group([LSP.node, Config.node, RuntimeFlags.node, EventV2Bridge.node]), [
|
||||
[RuntimeFlags.node, RuntimeFlags.layer(flags)],
|
||||
])
|
||||
|
||||
const it = testEffect(Layer.mergeAll(lspLayer(), CrossSpawnSpawner.defaultLayer))
|
||||
const it = testEffect(Layer.mergeAll(lspLayer(), LayerNode.compile(CrossSpawnSpawner.node)))
|
||||
const experimentalTyIt = testEffect(
|
||||
Layer.mergeAll(lspLayer({ experimentalLspTy: true }), CrossSpawnSpawner.defaultLayer),
|
||||
Layer.mergeAll(lspLayer({ experimentalLspTy: true }), LayerNode.compile(CrossSpawnSpawner.node)),
|
||||
)
|
||||
const fakeServerPath = path.join(__dirname, "../fixture/lsp/fake-lsp-server.js")
|
||||
const disabledDownloadIt = testEffect(
|
||||
Layer.mergeAll(lspLayer({ disableLspDownload: true }), CrossSpawnSpawner.defaultLayer),
|
||||
Layer.mergeAll(lspLayer({ disableLspDownload: true }), LayerNode.compile(CrossSpawnSpawner.node)),
|
||||
)
|
||||
|
||||
describe("lsp.spawn", () => {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { expect, test } from "bun:test"
|
||||
import { setTimeout as sleep } from "node:timers/promises"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { Effect, Layer } from "effect"
|
||||
import { FSUtil } from "@opencode-ai/core/fs-util"
|
||||
import { EffectFlock } from "@opencode-ai/core/util/effect-flock"
|
||||
|
|
@ -41,14 +42,14 @@ function authFile() {
|
|||
: fs.writeJson(file, value, mode),
|
||||
})
|
||||
}),
|
||||
).pipe(Layer.provide(FSUtil.defaultLayer))
|
||||
).pipe(Layer.provide(LayerNode.compile(FSUtil.node)))
|
||||
|
||||
return { layer, raw: () => raw }
|
||||
}
|
||||
|
||||
function authService(layer: Layer.Layer<FSUtil.Service>) {
|
||||
return McpAuth.Service.use((auth) => Effect.succeed(auth)).pipe(
|
||||
Effect.provide(McpAuth.layer.pipe(Layer.provide(EffectFlock.defaultLayer), Layer.provide(layer))),
|
||||
Effect.provide(LayerNode.compile(McpAuth.node, [[FSUtil.node, layer]])),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { expect, mock, beforeEach } from "bun:test"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { Effect, Layer } from "effect"
|
||||
import { testEffect } from "../lib/effect"
|
||||
|
||||
|
|
@ -155,16 +156,7 @@ const { FSUtil } = await import("@opencode-ai/core/fs-util")
|
|||
const { CrossSpawnSpawner } = await import("@opencode-ai/core/cross-spawn-spawner")
|
||||
|
||||
const mcpTest = testEffect(
|
||||
Layer.mergeAll(
|
||||
MCP.layer.pipe(
|
||||
Layer.provide(McpAuth.defaultLayer),
|
||||
Layer.provideMerge(EventV2Bridge.defaultLayer),
|
||||
Layer.provide(Config.defaultLayer),
|
||||
Layer.provide(CrossSpawnSpawner.defaultLayer),
|
||||
Layer.provide(FSUtil.defaultLayer),
|
||||
),
|
||||
McpAuth.defaultLayer,
|
||||
),
|
||||
LayerNode.compile(LayerNode.group([MCP.node, McpAuth.node, EventV2Bridge.node, Config.node, CrossSpawnSpawner.node, FSUtil.node])),
|
||||
)
|
||||
|
||||
const config = (name: string) => ({
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { expect, mock, beforeEach } from "bun:test"
|
||||
import { EventEmitter } from "events"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { Deferred, Effect, Layer, Option } from "effect"
|
||||
import { awaitWithTimeout, testEffect } from "../lib/effect"
|
||||
import type { MCP as MCPNS } from "../../src/mcp/index"
|
||||
|
|
@ -122,13 +123,7 @@ const { McpOAuthCallback } = await import("../../src/mcp/oauth-callback")
|
|||
const { FSUtil } = await import("@opencode-ai/core/fs-util")
|
||||
const { CrossSpawnSpawner } = await import("@opencode-ai/core/cross-spawn-spawner")
|
||||
const mcpTest = testEffect(
|
||||
MCP.layer.pipe(
|
||||
Layer.provide(McpAuth.defaultLayer),
|
||||
Layer.provideMerge(EventV2Bridge.defaultLayer),
|
||||
Layer.provide(Config.defaultLayer),
|
||||
Layer.provide(CrossSpawnSpawner.defaultLayer),
|
||||
Layer.provide(FSUtil.defaultLayer),
|
||||
),
|
||||
LayerNode.compile(LayerNode.group([MCP.node, McpAuth.node, EventV2Bridge.node, Config.node, CrossSpawnSpawner.node, FSUtil.node])),
|
||||
)
|
||||
const service = MCP.Service as unknown as Effect.Effect<MCPNS.Interface, never, never>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { describe, expect, test } from "bun:test"
|
||||
import path from "path"
|
||||
import { pathToFileURL } from "url"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { Effect, Layer } from "effect"
|
||||
import { FSUtil } from "@opencode-ai/core/fs-util"
|
||||
import { provideInstance, TestInstance, tmpdirScoped } from "../fixture/fixture"
|
||||
|
|
@ -15,7 +16,7 @@ import { testEffect } from "../lib/effect"
|
|||
import { CrossSpawnSpawner } from "@opencode-ai/core/cross-spawn-spawner"
|
||||
import { ProviderV2 } from "@opencode-ai/core/provider"
|
||||
|
||||
const it = testEffect(Layer.mergeAll(CrossSpawnSpawner.defaultLayer, FSUtil.defaultLayer))
|
||||
const it = testEffect(LayerNode.compile(LayerNode.group([CrossSpawnSpawner.node, FSUtil.node])))
|
||||
|
||||
function layer(directory: string, plugins: string[]) {
|
||||
return ProviderAuth.layer.pipe(
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { afterEach, describe, expect, spyOn } from "bun:test"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { Effect, Layer } from "effect"
|
||||
import fs from "fs/promises"
|
||||
import path from "path"
|
||||
|
|
@ -20,7 +21,7 @@ afterEach(async () => {
|
|||
await disposeAllInstances()
|
||||
})
|
||||
|
||||
const it = testEffect(Layer.mergeAll(CrossSpawnSpawner.defaultLayer, FSUtil.defaultLayer, testInstanceStoreLayer))
|
||||
const it = testEffect(Layer.mergeAll(LayerNode.compile(LayerNode.group([CrossSpawnSpawner.node, FSUtil.node])), testInstanceStoreLayer))
|
||||
|
||||
function withTmp<T, A, E, R>(
|
||||
init: (dir: string) => Promise<T>,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { afterEach, expect, test } from "bun:test"
|
||||
import { mkdir, unlink } from "fs/promises"
|
||||
import path from "path"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { Effect, Layer } from "effect"
|
||||
import { ModelsDev } from "@opencode-ai/core/models-dev"
|
||||
import { FSUtil } from "@opencode-ai/core/fs-util"
|
||||
|
|
@ -57,14 +58,9 @@ afterEach(async () => {
|
|||
})
|
||||
|
||||
const providerLayer = (flags: Partial<RuntimeFlags.Info> = {}) =>
|
||||
Provider.layer.pipe(
|
||||
Layer.provide(FSUtil.defaultLayer),
|
||||
Layer.provide(Env.defaultLayer),
|
||||
Layer.provide(Config.defaultLayer),
|
||||
Layer.provide(Auth.defaultLayer),
|
||||
Layer.provide(Plugin.defaultLayer),
|
||||
Layer.provide(ModelsDev.defaultLayer),
|
||||
Layer.provide(RuntimeFlags.layer(flags)),
|
||||
LayerNode.compile(
|
||||
LayerNode.group([Provider.node, FSUtil.node, Env.node, Config.node, Auth.node, Plugin.node, ModelsDev.node, RuntimeFlags.node]),
|
||||
[[RuntimeFlags.node, RuntimeFlags.layer(flags)]],
|
||||
)
|
||||
|
||||
const list = Provider.use.list()
|
||||
|
|
@ -77,7 +73,7 @@ const paid = (providers: Record<string, { models: Record<string, { cost: { input
|
|||
|
||||
const languageBaseURL = (language: unknown) => (language as { config: { baseURL: string } }).config.baseURL
|
||||
|
||||
const it = testEffect(Layer.mergeAll(Provider.defaultLayer, Env.defaultLayer, Plugin.defaultLayer))
|
||||
const it = testEffect(LayerNode.compile(LayerNode.group([Provider.node, Env.node, Plugin.node])))
|
||||
const experimentalModels = testEffect(providerLayer({ enableExperimentalModels: true }))
|
||||
|
||||
const alphaProviderConfig = {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
import { describe, expect } from "bun:test"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { SessionProjector } from "@opencode-ai/core/session/projector"
|
||||
import { Deferred, Effect, Layer } from "effect"
|
||||
import { Project } from "@/project/project"
|
||||
import { Session as SessionNs } from "@/session/session"
|
||||
|
|
@ -6,7 +8,9 @@ import { CrossSpawnSpawner } from "@opencode-ai/core/cross-spawn-spawner"
|
|||
import { provideInstance, TestInstance, tmpdirScoped } from "../fixture/fixture"
|
||||
import { testEffect } from "../lib/effect"
|
||||
|
||||
const it = testEffect(Layer.mergeAll(SessionNs.defaultLayer, Project.defaultLayer, CrossSpawnSpawner.defaultLayer))
|
||||
const it = testEffect(
|
||||
LayerNode.compile(LayerNode.group([SessionNs.node, SessionProjector.node, Project.node, CrossSpawnSpawner.node])),
|
||||
)
|
||||
|
||||
const withSession = (input?: Parameters<SessionNs.Interface["create"]>[0]) =>
|
||||
Effect.acquireRelease(SessionNs.use.create(input), (created) =>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { afterEach, describe, expect } from "bun:test"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { Deferred, Effect, Fiber, Layer } from "effect"
|
||||
import { HttpClient, HttpClientResponse } from "effect/unstable/http"
|
||||
import { eq } from "drizzle-orm"
|
||||
|
|
@ -15,7 +16,7 @@ import { disposeAllInstances, TestInstance } from "../fixture/fixture"
|
|||
import { testEffect } from "../lib/effect"
|
||||
import { httpApiLayer, requestInDirectory } from "./httpapi-layer"
|
||||
|
||||
const it = testEffect(Layer.mergeAll(Session.defaultLayer, Database.defaultLayer, httpApiLayer))
|
||||
const it = testEffect(Layer.mergeAll(LayerNode.compile(LayerNode.group([Session.node, Database.node])), httpApiLayer))
|
||||
const testWorktreeMutations = process.platform === "win32" ? it.instance.skip : it.instance
|
||||
|
||||
function request(path: string, directory: string, init: RequestInit = {}) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { describe, expect } from "bun:test"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { FSUtil } from "@opencode-ai/core/fs-util"
|
||||
import { Effect, Layer } from "effect"
|
||||
import path from "path"
|
||||
|
|
@ -15,7 +16,7 @@ const testStateLayer = Layer.effectDiscard(
|
|||
),
|
||||
)
|
||||
|
||||
const it = testEffect(Layer.mergeAll(testStateLayer, FSUtil.defaultLayer, httpApiLayer))
|
||||
const it = testEffect(Layer.mergeAll(testStateLayer, LayerNode.compile(FSUtil.node), httpApiLayer))
|
||||
const projectOptions = { config: { formatter: false, lsp: false } }
|
||||
const providerID = "test-oauth-parity"
|
||||
const oauthURL = "https://example.com/oauth"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { afterEach, describe, expect } from "bun:test"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { Effect, Layer } from "effect"
|
||||
import { HttpClientResponse } from "effect/unstable/http"
|
||||
import { eq } from "drizzle-orm"
|
||||
|
|
@ -16,7 +17,7 @@ import { ProviderV2 } from "@opencode-ai/core/provider"
|
|||
import { ModelV2 } from "@opencode-ai/core/model"
|
||||
import { httpApiLayer, requestInDirectory } from "./httpapi-layer"
|
||||
|
||||
const it = testEffect(Layer.mergeAll(Session.defaultLayer, Database.defaultLayer, httpApiLayer))
|
||||
const it = testEffect(Layer.mergeAll(LayerNode.compile(LayerNode.group([Session.node, Database.node])), httpApiLayer))
|
||||
|
||||
const text = (response: HttpClientResponse.HttpClientResponse) => response.text
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { afterEach, describe, expect, mock } from "bun:test"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { Context, Effect, Layer } from "effect"
|
||||
import { Flag } from "@opencode-ai/core/flag/flag"
|
||||
import { SyncPaths } from "../../src/server/routes/instance/httpapi/groups/sync"
|
||||
|
|
@ -11,7 +12,7 @@ import { httpApiLayer, requestInDirectory } from "./httpapi-layer"
|
|||
|
||||
const originalWorkspaces = Flag.OPENCODE_EXPERIMENTAL_WORKSPACES
|
||||
const context = Context.empty() as Context.Context<unknown>
|
||||
const it = testEffect(Layer.mergeAll(Session.defaultLayer, httpApiLayer))
|
||||
const it = testEffect(Layer.mergeAll(LayerNode.compile(Session.node), httpApiLayer))
|
||||
|
||||
afterEach(async () => {
|
||||
mock.restore()
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
// strict `NonNegativeInt` schema then made every load of the message list
|
||||
// fail to encode, killing Desktop boot for every user with such a row.
|
||||
import { describe, expect } from "bun:test"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { Effect, Layer } from "effect"
|
||||
import { eq } from "drizzle-orm"
|
||||
|
||||
|
|
@ -21,7 +22,7 @@ import { ProviderV2 } from "@opencode-ai/core/provider"
|
|||
import { ModelV2 } from "@opencode-ai/core/model"
|
||||
import { httpApiLayer, requestInDirectory } from "./httpapi-layer"
|
||||
|
||||
const it = testEffect(Layer.mergeAll(Session.defaultLayer, Database.defaultLayer, httpApiLayer))
|
||||
const it = testEffect(Layer.mergeAll(LayerNode.compile(LayerNode.group([Session.node, Database.node])), httpApiLayer))
|
||||
|
||||
function seedNegativeTokenSession() {
|
||||
return Effect.gen(function* () {
|
||||
|
|
|
|||
|
|
@ -2,12 +2,13 @@ import { afterEach, describe, expect } from "bun:test"
|
|||
import { $ } from "bun"
|
||||
import fs from "fs/promises"
|
||||
import path from "path"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { Effect, Layer } from "effect"
|
||||
import { HttpClientResponse } from "effect/unstable/http"
|
||||
import { FSUtil } from "@opencode-ai/core/fs-util"
|
||||
import { Database } from "@opencode-ai/core/database/database"
|
||||
import { Snapshot } from "@/snapshot"
|
||||
import { InstanceBootstrap } from "@/project/bootstrap-service"
|
||||
import { InstanceBootstrap } from "@/project/bootstrap"
|
||||
import { InstanceStore } from "@/project/instance-store"
|
||||
import { resetDatabase } from "../fixture/db"
|
||||
import { disposeAllInstances, TestInstance } from "../fixture/fixture"
|
||||
|
|
@ -20,9 +21,9 @@ afterEach(async () => {
|
|||
})
|
||||
|
||||
const noopBootstrap = Layer.succeed(InstanceBootstrap.Service, InstanceBootstrap.Service.of({ run: Effect.void }))
|
||||
const testInstanceStore = InstanceStore.defaultLayer.pipe(Layer.provide(noopBootstrap))
|
||||
const testInstanceStore = LayerNode.compile(InstanceStore.node, [[InstanceBootstrap.node, noopBootstrap]])
|
||||
const it = testEffect(
|
||||
Layer.mergeAll(FSUtil.defaultLayer, Database.defaultLayer, Snapshot.defaultLayer, testInstanceStore, httpApiLayer),
|
||||
Layer.mergeAll(LayerNode.compile(LayerNode.group([FSUtil.node, Database.node, Snapshot.node])), testInstanceStore, httpApiLayer),
|
||||
)
|
||||
|
||||
function request(directory: string, url: string, init: RequestInit = {}) {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
import { afterEach, describe, expect } from "bun:test"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { FSUtil } from "@opencode-ai/core/fs-util"
|
||||
import { Effect, Layer } from "effect"
|
||||
import { HttpClientResponse } from "effect/unstable/http"
|
||||
import path from "path"
|
||||
import { InstanceRef } from "../../src/effect/instance-ref"
|
||||
import { InstanceBootstrap } from "../../src/project/bootstrap-service"
|
||||
import { InstanceBootstrap } from "../../src/project/bootstrap"
|
||||
import { InstanceStore } from "../../src/project/instance-store"
|
||||
import { GlobalBus, type GlobalEvent } from "../../src/bus/global"
|
||||
import { Snapshot } from "../../src/snapshot"
|
||||
|
|
@ -19,9 +20,9 @@ afterEach(async () => {
|
|||
})
|
||||
|
||||
const noopBootstrap = Layer.succeed(InstanceBootstrap.Service, InstanceBootstrap.Service.of({ run: Effect.void }))
|
||||
const testInstanceStore = InstanceStore.defaultLayer.pipe(Layer.provide(noopBootstrap))
|
||||
const testInstanceStore = LayerNode.compile(InstanceStore.node, [[InstanceBootstrap.node, noopBootstrap]])
|
||||
|
||||
const it = testEffect(Layer.mergeAll(FSUtil.defaultLayer, Snapshot.defaultLayer, testInstanceStore, httpApiLayer))
|
||||
const it = testEffect(Layer.mergeAll(LayerNode.compile(LayerNode.group([FSUtil.node, Snapshot.node])), testInstanceStore, httpApiLayer))
|
||||
|
||||
function request(directory: string, url: string, init: RequestInit = {}) {
|
||||
return requestInDirectory(url, directory, init)
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
import { afterEach, describe, expect, mock } from "bun:test"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { Effect, Layer } from "effect"
|
||||
import { Session as SessionNs } from "@/session/session"
|
||||
import { disposeAllInstances, TestInstance } from "../fixture/fixture"
|
||||
import { testEffect } from "../lib/effect"
|
||||
import { httpApiLayer, requestInDirectory } from "./httpapi-layer"
|
||||
|
||||
const it = testEffect(Layer.mergeAll(SessionNs.defaultLayer, httpApiLayer))
|
||||
const it = testEffect(Layer.mergeAll(LayerNode.compile(SessionNs.node), httpApiLayer))
|
||||
|
||||
afterEach(async () => {
|
||||
mock.restore()
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
* asserts that GET /session/<id>/diff returns 200 with empty data.
|
||||
*/
|
||||
import { afterEach, describe, expect } from "bun:test"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { Effect, Layer } from "effect"
|
||||
import { SessionPaths } from "@/server/routes/instance/httpapi/groups/session"
|
||||
import { Session } from "@/session/session"
|
||||
|
|
@ -24,7 +25,7 @@ import { disposeAllInstances, TestInstance } from "../fixture/fixture"
|
|||
import { testEffect } from "../lib/effect"
|
||||
import { httpApiLayer, requestInDirectory } from "./httpapi-layer"
|
||||
|
||||
const it = testEffect(Layer.mergeAll(Session.defaultLayer, Storage.defaultLayer, httpApiLayer))
|
||||
const it = testEffect(Layer.mergeAll(LayerNode.compile(LayerNode.group([Session.node, Storage.node])), httpApiLayer))
|
||||
|
||||
afterEach(async () => {
|
||||
await disposeAllInstances()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { afterEach, describe, expect } from "bun:test"
|
||||
import { SessionV1 } from "@opencode-ai/core/v1/session"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { Effect, Layer } from "effect"
|
||||
import { HttpClientResponse } from "effect/unstable/http"
|
||||
import { Session as SessionNs } from "@/session/session"
|
||||
|
|
@ -12,7 +13,7 @@ import { ProviderV2 } from "@opencode-ai/core/provider"
|
|||
import { ModelV2 } from "@opencode-ai/core/model"
|
||||
import { httpApiLayer, requestInDirectory } from "./httpapi-layer"
|
||||
|
||||
const it = testEffect(Layer.mergeAll(SessionNs.defaultLayer, httpApiLayer))
|
||||
const it = testEffect(Layer.mergeAll(LayerNode.compile(SessionNs.node), httpApiLayer))
|
||||
|
||||
const model = {
|
||||
providerID: ProviderV2.ID.make("test"),
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
import { describe, expect } from "bun:test"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { Effect, Layer } from "effect"
|
||||
import { Session } from "@/session/session"
|
||||
import { TestInstance } from "../fixture/fixture"
|
||||
import { testEffect } from "../lib/effect"
|
||||
import { httpApiLayer, requestInDirectory } from "./httpapi-layer"
|
||||
|
||||
const it = testEffect(Layer.mergeAll(Session.defaultLayer, httpApiLayer))
|
||||
const it = testEffect(Layer.mergeAll(LayerNode.compile(Session.node), httpApiLayer))
|
||||
|
||||
describe("tui.selectSession endpoint", () => {
|
||||
it.instance(
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { describe, expect } from "bun:test"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { Effect, Layer } from "effect"
|
||||
import type { Agent } from "../../src/agent/agent"
|
||||
import { NamedError } from "@opencode-ai/core/util/error"
|
||||
|
|
@ -6,7 +7,6 @@ import { Skill } from "../../src/skill"
|
|||
import { Permission } from "../../src/permission"
|
||||
import { SystemPrompt } from "../../src/session/system"
|
||||
import { MCP } from "../../src/mcp"
|
||||
import { LocationServiceMap, locationServiceMapLayer } from "@opencode-ai/core/location-services"
|
||||
import { testEffect } from "../lib/effect"
|
||||
|
||||
const skills: Skill.Info[] = [
|
||||
|
|
@ -43,9 +43,9 @@ const build: Agent.Info = {
|
|||
}
|
||||
|
||||
const it = testEffect(
|
||||
SystemPrompt.layer.pipe(
|
||||
Layer.provide(locationServiceMapLayer),
|
||||
Layer.provide(
|
||||
LayerNode.compile(SystemPrompt.node, [
|
||||
[
|
||||
MCP.node,
|
||||
Layer.mock(MCP.Service, {
|
||||
instructions: () =>
|
||||
Effect.succeed([
|
||||
|
|
@ -61,8 +61,9 @@ const it = testEffect(
|
|||
},
|
||||
]),
|
||||
}),
|
||||
),
|
||||
Layer.provide(
|
||||
],
|
||||
[
|
||||
Skill.node,
|
||||
Layer.succeed(
|
||||
Skill.Service,
|
||||
Skill.Service.of({
|
||||
|
|
@ -77,8 +78,8 @@ const it = testEffect(
|
|||
available: () => Effect.succeed(skills),
|
||||
}),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
]),
|
||||
)
|
||||
|
||||
describe("session.system", () => {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { describe, expect } from "bun:test"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { Effect, Layer } from "effect"
|
||||
import { Skill } from "../../src/skill"
|
||||
import { Discovery } from "../../src/skill/discovery"
|
||||
|
|
@ -13,33 +14,19 @@ import { testEffect } from "../lib/effect"
|
|||
import path from "path"
|
||||
import fs from "fs/promises"
|
||||
|
||||
const node = CrossSpawnSpawner.defaultLayer
|
||||
const node = LayerNode.compile(CrossSpawnSpawner.node)
|
||||
|
||||
const it = testEffect(Layer.mergeAll(Skill.defaultLayer, node, testInstanceStoreLayer))
|
||||
const it = testEffect(Layer.mergeAll(LayerNode.compile(Skill.node), node, testInstanceStoreLayer))
|
||||
const itWithoutClaudeCodeSkills = testEffect(
|
||||
Layer.mergeAll(
|
||||
Skill.layer.pipe(
|
||||
Layer.provide(Discovery.defaultLayer),
|
||||
Layer.provide(Config.defaultLayer),
|
||||
Layer.provide(EventV2Bridge.defaultLayer),
|
||||
Layer.provide(FSUtil.defaultLayer),
|
||||
Layer.provide(Global.layer),
|
||||
Layer.provide(RuntimeFlags.layer({ disableClaudeCodeSkills: true })),
|
||||
),
|
||||
LayerNode.compile(Skill.node, [[RuntimeFlags.node, RuntimeFlags.layer({ disableClaudeCodeSkills: true })]]),
|
||||
node,
|
||||
testInstanceStoreLayer,
|
||||
),
|
||||
)
|
||||
const itWithoutExternalSkills = testEffect(
|
||||
Layer.mergeAll(
|
||||
Skill.layer.pipe(
|
||||
Layer.provide(Discovery.defaultLayer),
|
||||
Layer.provide(Config.defaultLayer),
|
||||
Layer.provide(EventV2Bridge.defaultLayer),
|
||||
Layer.provide(FSUtil.defaultLayer),
|
||||
Layer.provide(Global.layer),
|
||||
Layer.provide(RuntimeFlags.layer({ disableExternalSkills: true })),
|
||||
),
|
||||
LayerNode.compile(Skill.node, [[RuntimeFlags.node, RuntimeFlags.layer({ disableExternalSkills: true })]]),
|
||||
node,
|
||||
testInstanceStoreLayer,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { afterEach, expect } from "bun:test"
|
||||
import { $ } from "bun"
|
||||
import { CrossSpawnSpawner } from "@opencode-ai/core/cross-spawn-spawner"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { FSUtil } from "@opencode-ai/core/fs-util"
|
||||
import fs from "fs/promises"
|
||||
import path from "path"
|
||||
|
|
@ -15,7 +16,7 @@ import {
|
|||
} from "../fixture/fixture"
|
||||
import { testEffect } from "../lib/effect"
|
||||
|
||||
const it = testEffect(Layer.mergeAll(Snapshot.defaultLayer, FSUtil.defaultLayer, testInstanceStoreLayer))
|
||||
const it = testEffect(Layer.mergeAll(LayerNode.compile(LayerNode.group([Snapshot.node, FSUtil.node])), testInstanceStoreLayer))
|
||||
// Windows forbids both * and : in directory names.
|
||||
const nonWindowsIt = process.platform === "win32" ? it.live.skip : it.live
|
||||
|
||||
|
|
@ -74,11 +75,11 @@ const withTrackedSnapshot = <A, E, R>(
|
|||
})
|
||||
|
||||
const bootstrapScoped = Effect.fn("SnapshotTest.bootstrapScoped")(function* () {
|
||||
const dir = yield* tmpdirScoped({ git: true }).pipe(Effect.provide(CrossSpawnSpawner.defaultLayer))
|
||||
const dir = yield* tmpdirScoped({ git: true }).pipe(Effect.provide(LayerNode.compile(CrossSpawnSpawner.node)))
|
||||
return { path: dir, extra: yield* initialize(dir) }
|
||||
})
|
||||
|
||||
const scopedGitTmpdir = () => tmpdirScoped({ git: true }).pipe(Effect.provide(CrossSpawnSpawner.defaultLayer))
|
||||
const scopedGitTmpdir = () => tmpdirScoped({ git: true }).pipe(Effect.provide(LayerNode.compile(CrossSpawnSpawner.node)))
|
||||
|
||||
const cleanupWorktree = (repo: string, worktree: string, files: string[] = []) =>
|
||||
Effect.promise(async () => {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { describe, expect } from "bun:test"
|
||||
import path from "path"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { Effect, Exit, Layer } from "effect"
|
||||
import { FSUtil } from "@opencode-ai/core/fs-util"
|
||||
import { CrossSpawnSpawner } from "@opencode-ai/core/cross-spawn-spawner"
|
||||
|
|
@ -11,7 +12,7 @@ import { testEffect } from "../lib/effect"
|
|||
|
||||
const dir = path.join(Global.Path.data, "storage")
|
||||
|
||||
const it = testEffect(Layer.mergeAll(Storage.defaultLayer, FSUtil.defaultLayer, CrossSpawnSpawner.defaultLayer))
|
||||
const it = testEffect(LayerNode.compile(LayerNode.group([Storage.node, FSUtil.node, CrossSpawnSpawner.node])))
|
||||
|
||||
const scope = Effect.fnUntraced(function* () {
|
||||
const root = ["storage_test", crypto.randomUUID()]
|
||||
|
|
@ -50,14 +51,14 @@ function remappedFs(root: string) {
|
|||
fs.glob(pattern, options?.cwd ? { ...options, cwd: remap(root, options.cwd) } : options),
|
||||
})
|
||||
}),
|
||||
).pipe(Layer.provide(FSUtil.defaultLayer))
|
||||
).pipe(Layer.provide(LayerNode.compile(FSUtil.node)))
|
||||
}
|
||||
|
||||
// Layer.fresh forces a new Storage instance — without it, Effect's in-test layer cache
|
||||
// returns the outer testEffect's Storage (which uses the real FSUtil), not a new
|
||||
// one built on top of remappedFs.
|
||||
const remappedStorage = (root: string) =>
|
||||
Layer.fresh(Storage.layer.pipe(Layer.provide(remappedFs(root)), Layer.provide(Git.defaultLayer)))
|
||||
Layer.fresh(LayerNode.compile(Storage.node, [[FSUtil.node, remappedFs(root)]]))
|
||||
|
||||
describe("Storage", () => {
|
||||
it.live("round-trips JSON content", () =>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { describe, expect } from "bun:test"
|
||||
import path from "path"
|
||||
import * as fs from "fs/promises"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { Cause, Effect, Exit, Layer } from "effect"
|
||||
import { ApplyPatchTool } from "../../src/tool/apply_patch"
|
||||
import { LSP } from "@/lsp/lsp"
|
||||
|
|
@ -14,14 +15,7 @@ import { SessionID, MessageID } from "../../src/session/schema"
|
|||
import { testEffect } from "../lib/effect"
|
||||
|
||||
const it = testEffect(
|
||||
Layer.mergeAll(
|
||||
LSP.defaultLayer,
|
||||
FSUtil.defaultLayer,
|
||||
Format.defaultLayer,
|
||||
EventV2Bridge.defaultLayer,
|
||||
Truncate.defaultLayer,
|
||||
Agent.defaultLayer,
|
||||
),
|
||||
LayerNode.compile(LayerNode.group([LSP.node, FSUtil.node, Format.node, EventV2Bridge.node, Truncate.node, Agent.node])),
|
||||
)
|
||||
|
||||
const baseCtx = {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { afterEach, describe, expect } from "bun:test"
|
||||
import path from "path"
|
||||
import fs from "fs/promises"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { Cause, Deferred, Effect, Exit, Fiber, Layer } from "effect"
|
||||
import { EditTool } from "../../src/tool/edit"
|
||||
import { disposeAllInstances, TestInstance } from "../fixture/fixture"
|
||||
|
|
@ -30,14 +31,7 @@ afterEach(async () => {
|
|||
await disposeAllInstances()
|
||||
})
|
||||
|
||||
const layer = Layer.mergeAll(
|
||||
LSP.defaultLayer,
|
||||
FSUtil.defaultLayer,
|
||||
Format.defaultLayer,
|
||||
EventV2Bridge.defaultLayer,
|
||||
Truncate.defaultLayer,
|
||||
Agent.defaultLayer,
|
||||
)
|
||||
const layer = LayerNode.compile(LayerNode.group([LSP.node, FSUtil.node, Format.node, EventV2Bridge.node, Truncate.node, Agent.node]))
|
||||
|
||||
const it = testEffect(layer)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { PermissionV1 } from "@opencode-ai/core/v1/permission"
|
||||
import { describe, expect } from "bun:test"
|
||||
import path from "path"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { Cause, Effect, Exit, Layer } from "effect"
|
||||
import { GlobTool } from "../../src/tool/glob"
|
||||
import { SessionID, MessageID } from "../../src/session/schema"
|
||||
|
|
@ -20,14 +21,7 @@ import { Permission } from "../../src/permission"
|
|||
import type * as Tool from "../../src/tool/tool"
|
||||
|
||||
const toolLayer = (flags: Partial<RuntimeFlags.Info> = {}) =>
|
||||
Layer.mergeAll(
|
||||
CrossSpawnSpawner.defaultLayer,
|
||||
FSUtil.defaultLayer,
|
||||
Ripgrep.defaultLayer,
|
||||
Truncate.defaultLayer,
|
||||
Agent.defaultLayer,
|
||||
Git.defaultLayer,
|
||||
)
|
||||
LayerNode.compile(LayerNode.group([CrossSpawnSpawner.node, FSUtil.node, Ripgrep.node, Truncate.node, Agent.node, Git.node]))
|
||||
|
||||
const it = testEffect(toolLayer())
|
||||
const full = (p: string) => (process.platform === "win32" ? Filesystem.normalizePath(p) : p)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { describe, expect } from "bun:test"
|
|||
import fs from "fs/promises"
|
||||
import os from "os"
|
||||
import path from "path"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { Effect, Layer } from "effect"
|
||||
import { GrepTool } from "../../src/tool/grep"
|
||||
import { provideInstance, testInstanceStoreLayer, TestInstance, tmpdirScoped } from "../fixture/fixture"
|
||||
|
|
@ -22,14 +23,7 @@ import { Git } from "@/git"
|
|||
import { Filesystem } from "@/util/filesystem"
|
||||
|
||||
const toolLayer = (flags: Partial<RuntimeFlags.Info> = {}) =>
|
||||
Layer.mergeAll(
|
||||
CrossSpawnSpawner.defaultLayer,
|
||||
FSUtil.defaultLayer,
|
||||
Ripgrep.defaultLayer,
|
||||
Truncate.defaultLayer,
|
||||
Agent.defaultLayer,
|
||||
Git.defaultLayer,
|
||||
)
|
||||
LayerNode.compile(LayerNode.group([CrossSpawnSpawner.node, FSUtil.node, Ripgrep.node, Truncate.node, Agent.node, Git.node]))
|
||||
|
||||
const it = testEffect(toolLayer())
|
||||
const rooted = testEffect(Layer.mergeAll(toolLayer(), testInstanceStoreLayer))
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { PermissionV1 } from "@opencode-ai/core/v1/permission"
|
||||
import { afterEach, describe, expect } from "bun:test"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { Effect, Layer } from "effect"
|
||||
import path from "path"
|
||||
import { Agent } from "../../src/agent/agent"
|
||||
|
|
@ -56,7 +57,9 @@ const lsp = Layer.succeed(
|
|||
)
|
||||
|
||||
const it = testEffect(
|
||||
Layer.mergeAll(Agent.defaultLayer, FSUtil.defaultLayer, CrossSpawnSpawner.defaultLayer, Truncate.defaultLayer, lsp),
|
||||
LayerNode.compile(LayerNode.group([Agent.node, FSUtil.node, CrossSpawnSpawner.node, Truncate.node, LSP.node]), [
|
||||
[LSP.node, lsp],
|
||||
]),
|
||||
)
|
||||
|
||||
const init = Effect.fn("LspToolTest.init")(function* () {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { PermissionV1 } from "@opencode-ai/core/v1/permission"
|
||||
import { afterEach, describe, expect } from "bun:test"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { Cause, Effect, Exit, Layer, Stream } from "effect"
|
||||
import path from "path"
|
||||
import { Agent } from "../../src/agent/agent"
|
||||
|
|
@ -44,14 +45,8 @@ const ctx = {
|
|||
}
|
||||
|
||||
const readLayer = (flags: Partial<RuntimeFlags.Info> = {}) =>
|
||||
Layer.mergeAll(
|
||||
Agent.defaultLayer,
|
||||
FSUtil.defaultLayer,
|
||||
CrossSpawnSpawner.defaultLayer,
|
||||
Instruction.defaultLayer,
|
||||
LSP.defaultLayer,
|
||||
Ripgrep.defaultLayer,
|
||||
Truncate.defaultLayer,
|
||||
LayerNode.compile(
|
||||
LayerNode.group([Agent.node, FSUtil.node, CrossSpawnSpawner.node, Instruction.node, LSP.node, Ripgrep.node, Truncate.node]),
|
||||
)
|
||||
|
||||
const it = testEffect(Layer.mergeAll(readLayer(), testInstanceStoreLayer))
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { PermissionV1 } from "@opencode-ai/core/v1/permission"
|
||||
import { describe, expect } from "bun:test"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { Cause, Effect, Exit, Layer } from "effect"
|
||||
import type * as Scope from "effect/Scope"
|
||||
import os from "os"
|
||||
|
|
@ -22,13 +23,17 @@ import { RuntimeFlags } from "@/effect/runtime-flags"
|
|||
import { InstanceStore } from "@/project/instance-store"
|
||||
|
||||
const shellLayer = Layer.mergeAll(
|
||||
CrossSpawnSpawner.defaultLayer,
|
||||
FSUtil.defaultLayer,
|
||||
Plugin.defaultLayer,
|
||||
Truncate.defaultLayer,
|
||||
Config.defaultLayer,
|
||||
Agent.defaultLayer,
|
||||
RuntimeFlags.defaultLayer,
|
||||
LayerNode.compile(
|
||||
LayerNode.group([
|
||||
CrossSpawnSpawner.node,
|
||||
FSUtil.node,
|
||||
Plugin.node,
|
||||
Truncate.node,
|
||||
Config.node,
|
||||
Agent.node,
|
||||
RuntimeFlags.node,
|
||||
]),
|
||||
),
|
||||
testInstanceStoreLayer,
|
||||
)
|
||||
const it = testEffect(shellLayer)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { PermissionV1 } from "@opencode-ai/core/v1/permission"
|
||||
import { CrossSpawnSpawner } from "@opencode-ai/core/cross-spawn-spawner"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { Ripgrep } from "@opencode-ai/core/ripgrep"
|
||||
import { Cause, Effect, Exit, Layer } from "effect"
|
||||
import { afterEach, describe, expect } from "bun:test"
|
||||
|
|
@ -26,9 +27,7 @@ afterEach(async () => {
|
|||
await disposeAllInstances()
|
||||
})
|
||||
|
||||
const node = CrossSpawnSpawner.defaultLayer
|
||||
|
||||
const it = testEffect(Layer.mergeAll(ToolRegistry.defaultLayer, node).pipe(Layer.provide(Ripgrep.defaultLayer)))
|
||||
const it = testEffect(LayerNode.compile(LayerNode.group([ToolRegistry.node, CrossSpawnSpawner.node, Ripgrep.node])))
|
||||
|
||||
describe("tool.skill", () => {
|
||||
it.instance("execute returns skill content block with files", () =>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import { afterEach, describe, expect } from "bun:test"
|
||||
import { SessionV1 } from "@opencode-ai/core/v1/session"
|
||||
import { Database } from "@opencode-ai/core/database/database"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { SessionProjector } from "@opencode-ai/core/session/projector"
|
||||
import { Deferred, Effect, Exit, Fiber, Layer } from "effect"
|
||||
import { Agent } from "../../src/agent/agent"
|
||||
import { BackgroundJob } from "@/background/job"
|
||||
|
|
@ -33,20 +35,25 @@ const ref = {
|
|||
}
|
||||
|
||||
const layer = (flags: Partial<RuntimeFlags.Info> = {}) =>
|
||||
Layer.mergeAll(
|
||||
Agent.defaultLayer,
|
||||
BackgroundJob.defaultLayer,
|
||||
EventV2Bridge.defaultLayer,
|
||||
Config.defaultLayer,
|
||||
CrossSpawnSpawner.defaultLayer,
|
||||
Session.defaultLayer,
|
||||
SessionRunState.defaultLayer,
|
||||
SessionStatus.defaultLayer,
|
||||
Truncate.defaultLayer,
|
||||
ToolRegistry.defaultLayer,
|
||||
Database.defaultLayer,
|
||||
RuntimeFlags.layer(flags),
|
||||
).pipe(Layer.provide(Ripgrep.defaultLayer))
|
||||
LayerNode.compile(
|
||||
LayerNode.group([
|
||||
Agent.node,
|
||||
BackgroundJob.node,
|
||||
EventV2Bridge.node,
|
||||
Config.node,
|
||||
CrossSpawnSpawner.node,
|
||||
Session.node,
|
||||
SessionProjector.node,
|
||||
SessionRunState.node,
|
||||
SessionStatus.node,
|
||||
Truncate.node,
|
||||
ToolRegistry.node,
|
||||
Database.node,
|
||||
RuntimeFlags.node,
|
||||
Ripgrep.node,
|
||||
]),
|
||||
[[RuntimeFlags.node, RuntimeFlags.layer(flags)]],
|
||||
)
|
||||
|
||||
const it = testEffect(layer())
|
||||
const background = testEffect(layer({ experimentalBackgroundSubagents: true }))
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import { describe, expect } from "bun:test"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { httpClient } from "@opencode-ai/core/effect/app-node-platform"
|
||||
import { Effect, Layer } from "effect"
|
||||
import { FetchHttpClient } from "effect/unstable/http"
|
||||
import { FetchHttpClient, HttpClient } from "effect/unstable/http"
|
||||
import { Agent } from "../../src/agent/agent"
|
||||
import { Truncate } from "@/tool/truncate"
|
||||
import { WebFetchTool } from "../../src/tool/webfetch"
|
||||
|
|
@ -8,7 +10,11 @@ import { SessionID, MessageID } from "../../src/session/schema"
|
|||
import { Tool } from "@/tool/tool"
|
||||
import { testEffect } from "../lib/effect"
|
||||
|
||||
const it = testEffect(Layer.mergeAll(FetchHttpClient.layer, Truncate.defaultLayer, Agent.defaultLayer))
|
||||
const it = testEffect(
|
||||
LayerNode.compile(LayerNode.group([httpClient, Truncate.node, Agent.node]), [
|
||||
[httpClient, FetchHttpClient.layer as Layer.Layer<HttpClient.HttpClient>],
|
||||
]),
|
||||
)
|
||||
|
||||
const ctx = {
|
||||
sessionID: SessionID.make("ses_test"),
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { afterEach, describe, expect } from "bun:test"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { Effect, Layer } from "effect"
|
||||
import path from "path"
|
||||
import fs from "fs/promises"
|
||||
|
|
@ -31,14 +32,8 @@ afterEach(async () => {
|
|||
})
|
||||
|
||||
const it = testEffect(
|
||||
Layer.mergeAll(
|
||||
LSP.defaultLayer,
|
||||
FSUtil.defaultLayer,
|
||||
EventV2Bridge.defaultLayer,
|
||||
Format.defaultLayer,
|
||||
CrossSpawnSpawner.defaultLayer,
|
||||
Truncate.defaultLayer,
|
||||
Agent.defaultLayer,
|
||||
LayerNode.compile(
|
||||
LayerNode.group([LSP.node, FSUtil.node, EventV2Bridge.node, Format.node, CrossSpawnSpawner.node, Truncate.node, Agent.node]),
|
||||
),
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue