/** * Multi-instance validation slices for `ProviderInstanceRegistryLive`. * * Two axes of the driver/registry refactor are exercised here: * * 1. **Same driver, many instances** — the "multi-instance codex slice" * describe block below configures two independent `codex` instances and * asserts each gets its own closures and identity. This is the * multi-codex capability the refactor exists to unlock. * * 2. **Many drivers, one registry** — the "all drivers slice" describe * block below configures one instance of every shipped driver * (`codex`, `claudeAgent`, `cursor`, `opencode`) in a single * `ProviderInstanceConfigMap` and asserts the registry boots them all * without cross-contamination. This proves the driver SPI is uniform * across every provider — any driver plugs into the registry through * the same `ProviderDriver` value contract. * * Every instance in these tests is configured with `enabled: false` so the * provider-status checks short-circuit to pending/disabled snapshots * without trying to spawn real `codex` / `claude` / `agent` / `opencode` * binaries. That keeps the assertions focused on registry routing * behaviour rather than the runtime details of each provider. */import { describe, expect, it } from "@effect/vitest";import * as NodeServices from "@effect/platform-node/NodeServices";import { type ClaudeSettings, type CodexSettings, type CursorSettings, type OpenCodeSettings, ProviderDriverKind, type ProviderInstanceConfigMap, ProviderInstanceId,} from "@t3tools/contracts";import * as Effect from "effect/Effect";import * as Layer from "effect/Layer";import { HttpClient, HttpClientResponse } from "effect/unstable/http"; import { ServerConfig } from "../../config.ts";import { ClaudeDriver } from "../Drivers/ClaudeDriver.ts";import { CodexDriver } from "../Drivers/CodexDriver.ts";import { CursorDriver } from "../Drivers/CursorDriver.ts";import { OpenCodeDriver } from "../Drivers/OpenCodeDriver.ts";import { OpenCodeRuntimeLive } from "../opencodeRuntime.ts";import { NoOpProviderEventLoggers, ProviderEventLoggers } from "./ProviderEventLoggers.ts";import { makeProviderInstanceRegistry } from "./ProviderInstanceRegistryLive.ts"; const TestHttpClientLive = Layer.succeed( HttpClient.HttpClient, HttpClient.make((request) => Effect.succeed(HttpClientResponse.fromWeb(request, Response.json({ version: "0.0.0" }))), ),); const makeCodexConfig = (overrides: Partial<CodexSettings>): CodexSettings => ({ enabled: false, binaryPath: "codex", homePath: "", shadowHomePath: "", customModels: [], ...overrides,}); const makeClaudeConfig = (overrides: Partial<ClaudeSettings>): ClaudeSettings => ({ enabled: false, binaryPath: "claude", homePath: "", customModels: [], launchArgs: "", ...overrides,}); const makeCursorConfig = (overrides: Partial<CursorSettings>): CursorSettings => ({ enabled: false, binaryPath: "agent", apiEndpoint: "", customModels: [], ...overrides,}); const makeOpenCodeConfig = (overrides: Partial<OpenCodeSettings>): OpenCodeSettings => ({ enabled: false, binaryPath: "opencode", serverUrl: "", serverPassword: "", customModels: [], ...overrides,}); describe("ProviderInstanceRegistryLive — multi-instance codex slice", () => { // `ServerConfig.layerTest` needs `FileSystem` to materialize its scratch // directory. `Layer.merge` just unions requirements, so we have to push // `NodeServices.layer` through `Layer.provideMerge` to satisfy that // dependency while still surfacing NodeServices to the test body (the // codex driver's `create` yields `ChildProcessSpawner` directly). const testLayer = ServerConfig.layerTest(process.cwd(), { prefix: "provider-instance-registry-test", }).pipe( Layer.provideMerge(NodeServices.layer), Layer.provideMerge(TestHttpClientLive), Layer.provideMerge(Layer.succeed(ProviderEventLoggers, NoOpProviderEventLoggers)), ); it.live("boots two independent codex instances from a ProviderInstanceConfigMap", () => Effect.gen(function* () { const personalId = ProviderInstanceId.make("codex_personal"); const workId = ProviderInstanceId.make("codex_work"); const codexDriverKind = ProviderDriverKind.make("codex"); const configMap: ProviderInstanceConfigMap = { [personalId]: { driver: codexDriverKind, displayName: "Codex (personal)", enabled: false, config: makeCodexConfig({ binaryPath: "/opt/codex-personal/bin/codex", homePath: "/home/julius/.codex_personal", customModels: ["personal-preview"], }), }, [workId]: { driver: codexDriverKind, displayName: "Codex (work)", enabled: false, config: makeCodexConfig({ binaryPath: "/opt/codex-work/bin/codex", homePath: "/home/julius/.codex", customModels: ["work-preview"], }), }, }; const { registry } = yield* makeProviderInstanceRegistry({ drivers: [CodexDriver], configMap, }); const instances = yield* registry.listInstances; expect(instances.map((instance) => instance.instanceId).toSorted()).toEqual( [personalId, workId].toSorted(), ); expect(instances.every((instance) => instance.driverKind === codexDriverKind)).toBe(true); expect(instances.map((instance) => instance.displayName).toSorted()).toEqual( ["Codex (personal)", "Codex (work)"].toSorted(), ); // Each instance must be retrievable by id and carry its *own* closures. const personal = yield* registry.getInstance(personalId); const work = yield* registry.getInstance(workId); expect(personal).toBeDefined(); expect(work).toBeDefined(); expect(personal!.adapter).not.toBe(work!.adapter); expect(personal!.textGeneration).not.toBe(work!.textGeneration); expect(personal!.snapshot).not.toBe(work!.snapshot); // Snapshots identify themselves by instanceId + driver — this is // what makes per-instance routing distinguishable downstream. const personalSnapshot = yield* personal!.snapshot.getSnapshot; expect(personalSnapshot.instanceId).toBe(personalId); expect(personalSnapshot.driver).toBe(codexDriverKind); expect(personalSnapshot.enabled).toBe(false); expect(personalSnapshot.continuation?.groupKey).toBe( "codex:home:/home/julius/.codex_personal", ); const workSnapshot = yield* work!.snapshot.getSnapshot; expect(workSnapshot.instanceId).toBe(workId); expect(workSnapshot.driver).toBe(codexDriverKind); expect(workSnapshot.enabled).toBe(false); expect(workSnapshot.continuation?.groupKey).toBe("codex:home:/home/julius/.codex"); // Nothing goes to the unavailable bucket — both drivers are registered. const unavailable = yield* registry.listUnavailable; expect(unavailable).toEqual([]); }).pipe(Effect.provide(testLayer)), ); it.live( "shadows instances whose driver is not registered in this build without failing boot", () => Effect.gen(function* () { const codexId = ProviderInstanceId.make("codex_main"); const ghostId = ProviderInstanceId.make("ghost_main"); const configMap: ProviderInstanceConfigMap = { [codexId]: { driver: ProviderDriverKind.make("codex"), enabled: false, config: makeCodexConfig({}), }, [ghostId]: { driver: ProviderDriverKind.make("ghostDriver"), displayName: "A fork-only driver we don't ship", enabled: false, config: { arbitrary: "payload", preserved: true }, }, }; const { registry } = yield* makeProviderInstanceRegistry({ drivers: [CodexDriver], configMap, }); const instances = yield* registry.listInstances; expect(instances).toHaveLength(1); expect(instances[0]!.instanceId).toBe(codexId); const unavailable = yield* registry.listUnavailable; expect(unavailable).toHaveLength(1); const ghost = unavailable[0]!; expect(ghost.instanceId).toBe(ghostId); expect(ghost.driver).toBe("ghostDriver"); expect(ghost.availability).toBe("unavailable"); expect(ghost.unavailableReason).toMatch(/ghostDriver/); }).pipe(Effect.provide(testLayer)), );}); describe("ProviderInstanceRegistryLive — all drivers slice", () => { // All four drivers need `NodeServices` (ChildProcessSpawner + FileSystem + // Path). `OpenCodeDriver.create` additionally yields `OpenCodeRuntime` // at construction time, so we wire `OpenCodeRuntimeLive` into the stack. // `OpenCodeRuntimeLive` bundles its own `NetService.layer` via // `Layer.provide`, so the only external requirement it still exposes is // `ChildProcessSpawner` — resolved here by piping it through // `provideMerge(NodeServices.layer)`. // // The nested `provideMerge`s read bottom-up: `NodeServices.layer` // provides `OpenCodeRuntimeLive`'s deps while keeping its own outputs // surfaced; that merged layer then provides `ServerConfig.layerTest`'s // `FileSystem` dep while keeping everything else surfaced to the test. const infraLayer = OpenCodeRuntimeLive.pipe(Layer.provideMerge(NodeServices.layer)); const testLayer = ServerConfig.layerTest(process.cwd(), { prefix: "provider-instance-registry-all-drivers-test", }).pipe( Layer.provideMerge(infraLayer), Layer.provideMerge(TestHttpClientLive), Layer.provideMerge(Layer.succeed(ProviderEventLoggers, NoOpProviderEventLoggers)), ); it.live("boots one instance of every shipped driver from a single config map", () => Effect.gen(function* () { const codexId = ProviderInstanceId.make("codex_default"); const claudeId = ProviderInstanceId.make("claude_default"); const cursorId = ProviderInstanceId.make("cursor_default"); const openCodeId = ProviderInstanceId.make("opencode_default"); const codexDriverKind = ProviderDriverKind.make("codex"); const claudeDriverKind = ProviderDriverKind.make("claudeAgent"); const cursorDriverKind = ProviderDriverKind.make("cursor"); const openCodeDriverKind = ProviderDriverKind.make("opencode"); const configMap: ProviderInstanceConfigMap = { [codexId]: { driver: codexDriverKind, displayName: "Codex", enabled: false, config: makeCodexConfig({ homePath: "/home/julius/.codex" }), }, [claudeId]: { driver: claudeDriverKind, displayName: "Claude", enabled: false, config: makeClaudeConfig({ homePath: "/home/julius/.claude-work", launchArgs: "--verbose", }), }, [cursorId]: { driver: cursorDriverKind, displayName: "Cursor", enabled: false, config: makeCursorConfig({}), }, [openCodeId]: { driver: openCodeDriverKind, displayName: "OpenCode", enabled: false, config: makeOpenCodeConfig({}), }, }; const { registry } = yield* makeProviderInstanceRegistry({ drivers: [CodexDriver, ClaudeDriver, CursorDriver, OpenCodeDriver], configMap, }); // Every configured instance must materialize — none downgraded to a // shadow snapshot, because every driver in the map is registered. const unavailable = yield* registry.listUnavailable; expect(unavailable).toEqual([]); const instances = yield* registry.listInstances; expect(instances).toHaveLength(4); expect(instances.map((instance) => instance.instanceId).toSorted()).toEqual( [codexId, claudeId, cursorId, openCodeId].toSorted(), ); // Instance lookup by id resolves each instance to its own bundle — // this is how rest-of-server routes turn/session calls in the new // model. Each driver's bundle carries its advertised `driverKind`. const codex = yield* registry.getInstance(codexId); const claude = yield* registry.getInstance(claudeId); const cursor = yield* registry.getInstance(cursorId); const openCode = yield* registry.getInstance(openCodeId); expect(codex?.driverKind).toBe(codexDriverKind); expect(claude?.driverKind).toBe(claudeDriverKind); expect(cursor?.driverKind).toBe(cursorDriverKind); expect(openCode?.driverKind).toBe(openCodeDriverKind); expect(codex?.displayName).toBe("Codex"); expect(claude?.displayName).toBe("Claude"); expect(cursor?.displayName).toBe("Cursor"); expect(openCode?.displayName).toBe("OpenCode"); // Every instance owns its own set of closures — no sharing across // drivers. `adapter` / `textGeneration` / `snapshot` are all // distinct references even when two instances happen to share a // trait (e.g. Cursor + others all use a stub-or-real // `textGeneration`; they must still be different object values). const adapters = [codex!.adapter, claude!.adapter, cursor!.adapter, openCode!.adapter]; expect(new Set(adapters).size).toBe(adapters.length); const textGenerations = [ codex!.textGeneration, claude!.textGeneration, cursor!.textGeneration, openCode!.textGeneration, ]; expect(new Set(textGenerations).size).toBe(textGenerations.length); const snapshots = [codex!.snapshot, claude!.snapshot, cursor!.snapshot, openCode!.snapshot]; expect(new Set(snapshots).size).toBe(snapshots.length); // Snapshots identify themselves by `instanceId` + `driver` so // downstream aggregation in `ProviderRegistry` can tell instances // apart even when two share a driver. With `enabled: false`, the // check short-circuits and we get a disabled/pending snapshot back // — that's enough signal to validate the stamping wrapper without // spawning real binaries. const codexSnapshot = yield* codex!.snapshot.getSnapshot; expect(codexSnapshot.instanceId).toBe(codexId); expect(codexSnapshot.driver).toBe(codexDriverKind); expect(codexSnapshot.enabled).toBe(false); expect(codexSnapshot.continuation?.groupKey).toBe("codex:home:/home/julius/.codex"); const claudeSnapshot = yield* claude!.snapshot.getSnapshot; expect(claudeSnapshot.instanceId).toBe(claudeId); expect(claudeSnapshot.driver).toBe(claudeDriverKind); expect(claudeSnapshot.enabled).toBe(false); expect(claudeSnapshot.continuation?.groupKey).toBe("claude:home:/home/julius/.claude-work"); const cursorSnapshot = yield* cursor!.snapshot.getSnapshot; expect(cursorSnapshot.instanceId).toBe(cursorId); expect(cursorSnapshot.driver).toBe(cursorDriverKind); expect(cursorSnapshot.enabled).toBe(false); expect(cursorSnapshot.continuation?.groupKey).toBe( `${cursorDriverKind}:instance:${cursorId}`, ); const openCodeSnapshot = yield* openCode!.snapshot.getSnapshot; expect(openCodeSnapshot.instanceId).toBe(openCodeId); expect(openCodeSnapshot.driver).toBe(openCodeDriverKind); expect(openCodeSnapshot.enabled).toBe(false); expect(openCodeSnapshot.continuation?.groupKey).toBe( `${openCodeDriverKind}:instance:${openCodeId}`, ); }).pipe(Effect.provide(testLayer)), );});
/**
* Multi-instance validation slices for `ProviderInstanceRegistryLive`.
*
* Two axes of the driver/registry refactor are exercised here:
*
* 1. **Same driver, many instances** — the "multi-instance codex slice"
* describe block below configures two independent `codex` instances and
* asserts each gets its own closures and identity. This is the
* multi-codex capability the refactor exists to unlock.
*
* 2. **Many drivers, one registry** — the "all drivers slice" describe
* block below configures one instance of every shipped driver
* (`codex`, `claudeAgent`, `cursor`, `opencode`) in a single
* `ProviderInstanceConfigMap` and asserts the registry boots them all
* without cross-contamination. This proves the driver SPI is uniform
* across every provider — any driver plugs into the registry through
* the same `ProviderDriver` value contract.
*
* Every instance in these tests is configured with `enabled: false` so the
* provider-status checks short-circuit to pending/disabled snapshots
* without trying to spawn real `codex` / `claude` / `agent` / `opencode`
* binaries. That keeps the assertions focused on registry routing
* behaviour rather than the runtime details of each provider.
*/
import { describe, expect, it } from "@effect/vitest";
import * as NodeServices from "@effect/platform-node/NodeServices";
import {
type ClaudeSettings,
type CodexSettings,
type CursorSettings,
type OpenCodeSettings,
ProviderDriverKind,
type ProviderInstanceConfigMap,
ProviderInstanceId,
} from "@t3tools/contracts";
import * as Effect from "effect/Effect";
import * as Layer from "effect/Layer";
import { HttpClient, HttpClientResponse } from "effect/unstable/http";
import { ServerConfig } from "../../config.ts";
import { ClaudeDriver } from "../Drivers/ClaudeDriver.ts";
import { CodexDriver } from "../Drivers/CodexDriver.ts";
import { CursorDriver } from "../Drivers/CursorDriver.ts";
import { OpenCodeDriver } from "../Drivers/OpenCodeDriver.ts";
import { OpenCodeRuntimeLive } from "../opencodeRuntime.ts";
import { NoOpProviderEventLoggers, ProviderEventLoggers } from "./ProviderEventLoggers.ts";
import { makeProviderInstanceRegistry } from "./ProviderInstanceRegistryLive.ts";
const TestHttpClientLive = Layer.succeed(
HttpClient.HttpClient,
HttpClient.make((request) =>
Effect.succeed(HttpClientResponse.fromWeb(request, Response.json({ version: "0.0.0" }))),
),
);
const makeCodexConfig = (overrides: Partial<CodexSettings>): CodexSettings => ({
enabled: false,
binaryPath: "codex",
homePath: "",
shadowHomePath: "",
customModels: [],
...overrides,
});
const makeClaudeConfig = (overrides: Partial<ClaudeSettings>): ClaudeSettings => ({
enabled: false,
binaryPath: "claude",
homePath: "",
customModels: [],
launchArgs: "",
...overrides,
});
const makeCursorConfig = (overrides: Partial<CursorSettings>): CursorSettings => ({
enabled: false,
binaryPath: "agent",
apiEndpoint: "",
customModels: [],
...overrides,
});
const makeOpenCodeConfig = (overrides: Partial<OpenCodeSettings>): OpenCodeSettings => ({
enabled: false,
binaryPath: "opencode",
serverUrl: "",
serverPassword: "",
customModels: [],
...overrides,
});
describe("ProviderInstanceRegistryLive — multi-instance codex slice", () => {
// `ServerConfig.layerTest` needs `FileSystem` to materialize its scratch
// directory. `Layer.merge` just unions requirements, so we have to push
// `NodeServices.layer` through `Layer.provideMerge` to satisfy that
// dependency while still surfacing NodeServices to the test body (the
// codex driver's `create` yields `ChildProcessSpawner` directly).
const testLayer = ServerConfig.layerTest(process.cwd(), {
prefix: "provider-instance-registry-test",
}).pipe(
Layer.provideMerge(NodeServices.layer),
Layer.provideMerge(TestHttpClientLive),
Layer.provideMerge(Layer.succeed(ProviderEventLoggers, NoOpProviderEventLoggers)),
);
it.live("boots two independent codex instances from a ProviderInstanceConfigMap", () =>
Effect.gen(function* () {
const personalId = ProviderInstanceId.make("codex_personal");
const workId = ProviderInstanceId.make("codex_work");
const codexDriverKind = ProviderDriverKind.make("codex");
const configMap: ProviderInstanceConfigMap = {
[personalId]: {
driver: codexDriverKind,
displayName: "Codex (personal)",
enabled: false,
config: makeCodexConfig({
binaryPath: "/opt/codex-personal/bin/codex",
homePath: "/home/julius/.codex_personal",
customModels: ["personal-preview"],
}),
},
[workId]: {
driver: codexDriverKind,
displayName: "Codex (work)",
enabled: false,
config: makeCodexConfig({
binaryPath: "/opt/codex-work/bin/codex",
homePath: "/home/julius/.codex",
customModels: ["work-preview"],
}),
},
};
const { registry } = yield* makeProviderInstanceRegistry({
drivers: [CodexDriver],
configMap,
});
const instances = yield* registry.listInstances;
expect(instances.map((instance) => instance.instanceId).toSorted()).toEqual(
[personalId, workId].toSorted(),
);
expect(instances.every((instance) => instance.driverKind === codexDriverKind)).toBe(true);
expect(instances.map((instance) => instance.displayName).toSorted()).toEqual(
["Codex (personal)", "Codex (work)"].toSorted(),
);
// Each instance must be retrievable by id and carry its *own* closures.
const personal = yield* registry.getInstance(personalId);
const work = yield* registry.getInstance(workId);
expect(personal).toBeDefined();
expect(work).toBeDefined();
expect(personal!.adapter).not.toBe(work!.adapter);
expect(personal!.textGeneration).not.toBe(work!.textGeneration);
expect(personal!.snapshot).not.toBe(work!.snapshot);
// Snapshots identify themselves by instanceId + driver — this is
// what makes per-instance routing distinguishable downstream.
const personalSnapshot = yield* personal!.snapshot.getSnapshot;
expect(personalSnapshot.instanceId).toBe(personalId);
expect(personalSnapshot.driver).toBe(codexDriverKind);
expect(personalSnapshot.enabled).toBe(false);
expect(personalSnapshot.continuation?.groupKey).toBe(
"codex:home:/home/julius/.codex_personal",
);
const workSnapshot = yield* work!.snapshot.getSnapshot;
expect(workSnapshot.instanceId).toBe(workId);
expect(workSnapshot.driver).toBe(codexDriverKind);
expect(workSnapshot.enabled).toBe(false);
expect(workSnapshot.continuation?.groupKey).toBe("codex:home:/home/julius/.codex");
// Nothing goes to the unavailable bucket — both drivers are registered.
const unavailable = yield* registry.listUnavailable;
expect(unavailable).toEqual([]);
}).pipe(Effect.provide(testLayer)),
);
it.live(
"shadows instances whose driver is not registered in this build without failing boot",
() =>
Effect.gen(function* () {
const codexId = ProviderInstanceId.make("codex_main");
const ghostId = ProviderInstanceId.make("ghost_main");
const configMap: ProviderInstanceConfigMap = {
[codexId]: {
driver: ProviderDriverKind.make("codex"),
enabled: false,
config: makeCodexConfig({}),
},
[ghostId]: {
driver: ProviderDriverKind.make("ghostDriver"),
displayName: "A fork-only driver we don't ship",
enabled: false,
config: { arbitrary: "payload", preserved: true },
},
};
const { registry } = yield* makeProviderInstanceRegistry({
drivers: [CodexDriver],
configMap,
});
const instances = yield* registry.listInstances;
expect(instances).toHaveLength(1);
expect(instances[0]!.instanceId).toBe(codexId);
const unavailable = yield* registry.listUnavailable;
expect(unavailable).toHaveLength(1);
const ghost = unavailable[0]!;
expect(ghost.instanceId).toBe(ghostId);
expect(ghost.driver).toBe("ghostDriver");
expect(ghost.availability).toBe("unavailable");
expect(ghost.unavailableReason).toMatch(/ghostDriver/);
}).pipe(Effect.provide(testLayer)),
);
});
describe("ProviderInstanceRegistryLive — all drivers slice", () => {
// All four drivers need `NodeServices` (ChildProcessSpawner + FileSystem +
// Path). `OpenCodeDriver.create` additionally yields `OpenCodeRuntime`
// at construction time, so we wire `OpenCodeRuntimeLive` into the stack.
// `OpenCodeRuntimeLive` bundles its own `NetService.layer` via
// `Layer.provide`, so the only external requirement it still exposes is
// `ChildProcessSpawner` — resolved here by piping it through
// `provideMerge(NodeServices.layer)`.
//
// The nested `provideMerge`s read bottom-up: `NodeServices.layer`
// provides `OpenCodeRuntimeLive`'s deps while keeping its own outputs
// surfaced; that merged layer then provides `ServerConfig.layerTest`'s
// `FileSystem` dep while keeping everything else surfaced to the test.
const infraLayer = OpenCodeRuntimeLive.pipe(Layer.provideMerge(NodeServices.layer));
const testLayer = ServerConfig.layerTest(process.cwd(), {
prefix: "provider-instance-registry-all-drivers-test",
}).pipe(
Layer.provideMerge(infraLayer),
Layer.provideMerge(TestHttpClientLive),
Layer.provideMerge(Layer.succeed(ProviderEventLoggers, NoOpProviderEventLoggers)),
);
it.live("boots one instance of every shipped driver from a single config map", () =>
Effect.gen(function* () {
const codexId = ProviderInstanceId.make("codex_default");
const claudeId = ProviderInstanceId.make("claude_default");
const cursorId = ProviderInstanceId.make("cursor_default");
const openCodeId = ProviderInstanceId.make("opencode_default");
const codexDriverKind = ProviderDriverKind.make("codex");
const claudeDriverKind = ProviderDriverKind.make("claudeAgent");
const cursorDriverKind = ProviderDriverKind.make("cursor");
const openCodeDriverKind = ProviderDriverKind.make("opencode");
const configMap: ProviderInstanceConfigMap = {
[codexId]: {
driver: codexDriverKind,
displayName: "Codex",
enabled: false,
config: makeCodexConfig({ homePath: "/home/julius/.codex" }),
},
[claudeId]: {
driver: claudeDriverKind,
displayName: "Claude",
enabled: false,
config: makeClaudeConfig({
homePath: "/home/julius/.claude-work",
launchArgs: "--verbose",
}),
},
[cursorId]: {
driver: cursorDriverKind,
displayName: "Cursor",
enabled: false,
config: makeCursorConfig({}),
},
[openCodeId]: {
driver: openCodeDriverKind,
displayName: "OpenCode",
enabled: false,
config: makeOpenCodeConfig({}),
},
};
const { registry } = yield* makeProviderInstanceRegistry({
drivers: [CodexDriver, ClaudeDriver, CursorDriver, OpenCodeDriver],
configMap,
});
// Every configured instance must materialize — none downgraded to a
// shadow snapshot, because every driver in the map is registered.
const unavailable = yield* registry.listUnavailable;
expect(unavailable).toEqual([]);
const instances = yield* registry.listInstances;
expect(instances).toHaveLength(4);
expect(instances.map((instance) => instance.instanceId).toSorted()).toEqual(
[codexId, claudeId, cursorId, openCodeId].toSorted(),
);
// Instance lookup by id resolves each instance to its own bundle —
// this is how rest-of-server routes turn/session calls in the new
// model. Each driver's bundle carries its advertised `driverKind`.
const codex = yield* registry.getInstance(codexId);
const claude = yield* registry.getInstance(claudeId);
const cursor = yield* registry.getInstance(cursorId);
const openCode = yield* registry.getInstance(openCodeId);
expect(codex?.driverKind).toBe(codexDriverKind);
expect(claude?.driverKind).toBe(claudeDriverKind);
expect(cursor?.driverKind).toBe(cursorDriverKind);
expect(openCode?.driverKind).toBe(openCodeDriverKind);
expect(codex?.displayName).toBe("Codex");
expect(claude?.displayName).toBe("Claude");
expect(cursor?.displayName).toBe("Cursor");
expect(openCode?.displayName).toBe("OpenCode");
// Every instance owns its own set of closures — no sharing across
// drivers. `adapter` / `textGeneration` / `snapshot` are all
// distinct references even when two instances happen to share a
// trait (e.g. Cursor + others all use a stub-or-real
// `textGeneration`; they must still be different object values).
const adapters = [codex!.adapter, claude!.adapter, cursor!.adapter, openCode!.adapter];
expect(new Set(adapters).size).toBe(adapters.length);
const textGenerations = [
codex!.textGeneration,
claude!.textGeneration,
cursor!.textGeneration,
openCode!.textGeneration,
];
expect(new Set(textGenerations).size).toBe(textGenerations.length);
const snapshots = [codex!.snapshot, claude!.snapshot, cursor!.snapshot, openCode!.snapshot];
expect(new Set(snapshots).size).toBe(snapshots.length);
// Snapshots identify themselves by `instanceId` + `driver` so
// downstream aggregation in `ProviderRegistry` can tell instances
// apart even when two share a driver. With `enabled: false`, the
// check short-circuits and we get a disabled/pending snapshot back
// — that's enough signal to validate the stamping wrapper without
// spawning real binaries.
const codexSnapshot = yield* codex!.snapshot.getSnapshot;
expect(codexSnapshot.instanceId).toBe(codexId);
expect(codexSnapshot.driver).toBe(codexDriverKind);
expect(codexSnapshot.enabled).toBe(false);
expect(codexSnapshot.continuation?.groupKey).toBe("codex:home:/home/julius/.codex");
const claudeSnapshot = yield* claude!.snapshot.getSnapshot;
expect(claudeSnapshot.instanceId).toBe(claudeId);
expect(claudeSnapshot.driver).toBe(claudeDriverKind);
expect(claudeSnapshot.enabled).toBe(false);
expect(claudeSnapshot.continuation?.groupKey).toBe("claude:home:/home/julius/.claude-work");
const cursorSnapshot = yield* cursor!.snapshot.getSnapshot;
expect(cursorSnapshot.instanceId).toBe(cursorId);
expect(cursorSnapshot.driver).toBe(cursorDriverKind);
expect(cursorSnapshot.enabled).toBe(false);
expect(cursorSnapshot.continuation?.groupKey).toBe(
`${cursorDriverKind}:instance:${cursorId}`,
);
const openCodeSnapshot = yield* openCode!.snapshot.getSnapshot;
expect(openCodeSnapshot.instanceId).toBe(openCodeId);
expect(openCodeSnapshot.driver).toBe(openCodeDriverKind);
expect(openCodeSnapshot.enabled).toBe(false);
expect(openCodeSnapshot.continuation?.groupKey).toBe(
`${openCodeDriverKind}:instance:${openCodeId}`,
);
}).pipe(Effect.provide(testLayer)),
);
});