import { assert, it } from "@effect/vitest";import { ProviderDriverKind, ProviderInstanceId, ProviderSessionId, ThreadId, type OrchestrationV2ThreadProjection,} from "@t3tools/contracts";import * as DateTime from "effect/DateTime";import * as Effect from "effect/Effect";import * as Layer from "effect/Layer"; import { CodexProviderCapabilitiesV2 } from "./Adapters/CodexAdapterV2.ts";import type { ProviderAdapterV2Shape } from "./ProviderAdapter.ts";import * as ProviderAdapterRegistry from "./ProviderAdapterRegistry.ts";import * as ProviderSwitch from "./ProviderSwitchService.ts"; const driver = ProviderDriverKind.make("codex");const currentInstanceId = ProviderInstanceId.make("codex_primary");const currentSessionId = ProviderSessionId.make("session_primary");const now = DateTime.makeUnsafe("2026-06-20T00:00:00.000Z");const capabilitiesWithoutModelSwitch = { ...CodexProviderCapabilitiesV2, sessions: { ...CodexProviderCapabilitiesV2.sessions, supportsModelSwitchInSession: false, },}; function projection(): OrchestrationV2ThreadProjection { return { thread: { id: ThreadId.make("thread_switch_service"), modelSelection: { instanceId: currentInstanceId, model: "gpt-5.1-codex" }, runtimeMode: "full-access", interactionMode: "default", worktreePath: "/repo", }, providerSessions: [ { id: currentSessionId, providerInstanceId: currentInstanceId, status: "ready", cwd: "/repo", capabilities: capabilitiesWithoutModelSwitch, updatedAt: now, }, ], providerThreads: [], } as unknown as OrchestrationV2ThreadProjection;} function testLayer(metadata: Readonly<Record<string, { continuationKey: string }>>) { const adapter = (instanceId: ProviderInstanceId): ProviderAdapterV2Shape => ({ instanceId, driver, getCapabilities: () => Effect.succeed(capabilitiesWithoutModelSwitch), planSelectionTransition: () => Effect.succeed({ type: "restart_session" }), openSession: () => Effect.die("ProviderSwitchService tests do not open sessions."), }); const registry = Layer.mock(ProviderAdapterRegistry.ProviderAdapterRegistryV2)({ get: (instanceId) => metadata[instanceId] === undefined ? Effect.fail( new ProviderAdapterRegistry.ProviderAdapterRegistryLookupError({ instanceId }), ) : Effect.succeed(adapter(instanceId)), list: () => Effect.succeed(Object.keys(metadata).map((id) => ProviderInstanceId.make(id))), getMetadata: (instanceId) => { const value = metadata[instanceId]; return value === undefined ? Effect.fail( new ProviderAdapterRegistry.ProviderAdapterRegistryLookupError({ instanceId }), ) : Effect.succeed({ driver, continuationKey: value.continuationKey, enabled: true, capabilities: capabilitiesWithoutModelSwitch, }); }, }); return ProviderSwitch.layer.pipe(Layer.provide(registry));} it.effect( "restarts and releases the current session for unsupported in-session model changes", () => Effect.gen(function* () { const service = yield* ProviderSwitch.ProviderSwitchServiceV2; const result = yield* service.plan({ projection: projection(), targetModelSelection: { instanceId: currentInstanceId, model: "gpt-5.2-codex" }, }); assert.equal(result.transition.type, "restart_and_resume"); assert.deepEqual(result.releaseProviderSessionIds, [currentSessionId]); }).pipe( Effect.provide( testLayer({ [currentInstanceId]: { continuationKey: "codex:account:primary" } }), ), ),); it.effect("distinguishes compatible and incompatible instances of the same driver", () => Effect.gen(function* () { const service = yield* ProviderSwitch.ProviderSwitchServiceV2; const compatibleId = ProviderInstanceId.make("codex_compatible"); const incompatibleId = ProviderInstanceId.make("codex_incompatible"); const compatible = yield* service.plan({ projection: projection(), targetModelSelection: { instanceId: compatibleId, model: "gpt-5.1-codex" }, }); const incompatible = yield* service.plan({ projection: projection(), targetModelSelection: { instanceId: incompatibleId, model: "gpt-5.1-codex" }, }); assert.equal(compatible.transition.type, "restart_and_resume"); assert.equal(incompatible.transition.type, "create_with_handoff"); }).pipe( Effect.provide( testLayer({ [currentInstanceId]: { continuationKey: "codex:account:primary" }, codex_compatible: { continuationKey: "codex:account:primary" }, codex_incompatible: { continuationKey: "codex:account:other" }, }), ), ),);
import { assert, it } from "@effect/vitest";
import {
ProviderDriverKind,
ProviderInstanceId,
ProviderSessionId,
ThreadId,
type OrchestrationV2ThreadProjection,
} from "@t3tools/contracts";
import * as DateTime from "effect/DateTime";
import * as Effect from "effect/Effect";
import * as Layer from "effect/Layer";
import { CodexProviderCapabilitiesV2 } from "./Adapters/CodexAdapterV2.ts";
import type { ProviderAdapterV2Shape } from "./ProviderAdapter.ts";
import * as ProviderAdapterRegistry from "./ProviderAdapterRegistry.ts";
import * as ProviderSwitch from "./ProviderSwitchService.ts";
const driver = ProviderDriverKind.make("codex");
const currentInstanceId = ProviderInstanceId.make("codex_primary");
const currentSessionId = ProviderSessionId.make("session_primary");
const now = DateTime.makeUnsafe("2026-06-20T00:00:00.000Z");
const capabilitiesWithoutModelSwitch = {
...CodexProviderCapabilitiesV2,
sessions: {
...CodexProviderCapabilitiesV2.sessions,
supportsModelSwitchInSession: false,
},
};
function projection(): OrchestrationV2ThreadProjection {
return {
thread: {
id: ThreadId.make("thread_switch_service"),
modelSelection: { instanceId: currentInstanceId, model: "gpt-5.1-codex" },
runtimeMode: "full-access",
interactionMode: "default",
worktreePath: "/repo",
},
providerSessions: [
{
id: currentSessionId,
providerInstanceId: currentInstanceId,
status: "ready",
cwd: "/repo",
capabilities: capabilitiesWithoutModelSwitch,
updatedAt: now,
},
],
providerThreads: [],
} as unknown as OrchestrationV2ThreadProjection;
}
function testLayer(metadata: Readonly<Record<string, { continuationKey: string }>>) {
const adapter = (instanceId: ProviderInstanceId): ProviderAdapterV2Shape => ({
instanceId,
driver,
getCapabilities: () => Effect.succeed(capabilitiesWithoutModelSwitch),
planSelectionTransition: () => Effect.succeed({ type: "restart_session" }),
openSession: () => Effect.die("ProviderSwitchService tests do not open sessions."),
});
const registry = Layer.mock(ProviderAdapterRegistry.ProviderAdapterRegistryV2)({
get: (instanceId) =>
metadata[instanceId] === undefined
? Effect.fail(
new ProviderAdapterRegistry.ProviderAdapterRegistryLookupError({ instanceId }),
)
: Effect.succeed(adapter(instanceId)),
list: () => Effect.succeed(Object.keys(metadata).map((id) => ProviderInstanceId.make(id))),
getMetadata: (instanceId) => {
const value = metadata[instanceId];
return value === undefined
? Effect.fail(
new ProviderAdapterRegistry.ProviderAdapterRegistryLookupError({ instanceId }),
)
: Effect.succeed({
driver,
continuationKey: value.continuationKey,
enabled: true,
capabilities: capabilitiesWithoutModelSwitch,
});
},
});
return ProviderSwitch.layer.pipe(Layer.provide(registry));
}
it.effect(
"restarts and releases the current session for unsupported in-session model changes",
() =>
Effect.gen(function* () {
const service = yield* ProviderSwitch.ProviderSwitchServiceV2;
const result = yield* service.plan({
projection: projection(),
targetModelSelection: { instanceId: currentInstanceId, model: "gpt-5.2-codex" },
});
assert.equal(result.transition.type, "restart_and_resume");
assert.deepEqual(result.releaseProviderSessionIds, [currentSessionId]);
}).pipe(
Effect.provide(
testLayer({ [currentInstanceId]: { continuationKey: "codex:account:primary" } }),
),
),
);
it.effect("distinguishes compatible and incompatible instances of the same driver", () =>
Effect.gen(function* () {
const service = yield* ProviderSwitch.ProviderSwitchServiceV2;
const compatibleId = ProviderInstanceId.make("codex_compatible");
const incompatibleId = ProviderInstanceId.make("codex_incompatible");
const compatible = yield* service.plan({
projection: projection(),
targetModelSelection: { instanceId: compatibleId, model: "gpt-5.1-codex" },
});
const incompatible = yield* service.plan({
projection: projection(),
targetModelSelection: { instanceId: incompatibleId, model: "gpt-5.1-codex" },
});
assert.equal(compatible.transition.type, "restart_and_resume");
assert.equal(incompatible.transition.type, "create_with_handoff");
}).pipe(
Effect.provide(
testLayer({
[currentInstanceId]: { continuationKey: "codex:account:primary" },
codex_compatible: { continuationKey: "codex:account:primary" },
codex_incompatible: { continuationKey: "codex:account:other" },
}),
),
),
);