import { assert, it, vi } from "@effect/vitest";import { NodeId, ProviderSessionId, RuntimeRequestId, ThreadId, type OrchestrationV2RuntimeRequest, type OrchestrationV2ThreadProjection,} from "@t3tools/contracts";import * as DateTime from "effect/DateTime";import * as Effect from "effect/Effect";import * as Layer from "effect/Layer";import * as Option from "effect/Option"; import type { ProviderAdapterV2RuntimeRequestResponseInput } from "./ProviderAdapter.ts";import { ProjectionStoreV2 } from "./ProjectionStore.ts";import { ProviderSessionLookupError, ProviderSessionManagerV2, type ProviderSessionManagerV2Shape,} from "./ProviderSessionManager.ts";import { layer as runtimeRequestServiceLayer, RuntimeRequestResponseExecutionError, RuntimeRequestServiceV2,} from "./RuntimeRequestService.ts"; function projectionWithRuntimeRequest( runtimeRequest?: OrchestrationV2RuntimeRequest,): OrchestrationV2ThreadProjection { return { runtimeRequests: runtimeRequest === undefined ? [] : [runtimeRequest], } as unknown as OrchestrationV2ThreadProjection;} function resolvedRuntimeRequest( requestId: RuntimeRequestId, providerSessionId: ProviderSessionId,): OrchestrationV2RuntimeRequest { return { id: requestId, nodeId: NodeId.make(`node-${requestId}`), providerTurnId: null, nativeRequestRef: null, kind: "command", status: "resolved", responseCapability: { type: "live", providerSessionId, }, createdAt: DateTime.makeUnsafe("2026-07-29T00:00:00.000Z"), resolvedAt: DateTime.makeUnsafe("2026-07-29T00:00:01.000Z"), };} function runtimeRequestTestLayer( projection: OrchestrationV2ThreadProjection, getSession: ProviderSessionManagerV2Shape["get"],) { return runtimeRequestServiceLayer.pipe( Layer.provide( Layer.mergeAll( Layer.mock(ProjectionStoreV2)({ getRuntimeRequest: (_threadId, requestId) => Effect.succeed(projection.runtimeRequests.find((request) => request.id === requestId)), }), Layer.mock(ProviderSessionManagerV2)({ get: getSession, }), ), ), );} it.effect("forwards orchestrator-resolved runtime requests to the live adapter", () => { const threadId = ThreadId.make("thread-runtime-request-resolved"); const providerSessionId = ProviderSessionId.make("provider-session-runtime-request-resolved"); const requestId = RuntimeRequestId.make("request-resolved"); const respondToRuntimeRequest = vi.fn( (_input: ProviderAdapterV2RuntimeRequestResponseInput) => Effect.void, ); const getSession = vi.fn(() => Effect.succeed( Option.some({ respondToRuntimeRequest, } as never), ), ); const projection = { runtimeRequests: [ { id: requestId, nodeId: NodeId.make("node-runtime-request-resolved"), providerTurnId: null, nativeRequestRef: null, kind: "command", status: "resolved", responseCapability: { type: "live", providerSessionId, }, createdAt: DateTime.makeUnsafe("2026-07-29T00:00:00.000Z"), resolvedAt: DateTime.makeUnsafe("2026-07-29T00:00:01.000Z"), }, ], } as unknown as OrchestrationV2ThreadProjection; const testLayer = runtimeRequestServiceLayer.pipe( Layer.provide( Layer.mergeAll( Layer.mock(ProjectionStoreV2)({ getRuntimeRequest: (_threadId, requestId) => Effect.succeed(projection.runtimeRequests.find((request) => request.id === requestId)), }), Layer.mock(ProviderSessionManagerV2)({ get: getSession, }), ), ), ); return Effect.gen(function* () { const service = yield* RuntimeRequestServiceV2; yield* service.respond({ threadId, providerSessionId, requestId, decision: "accept", }); assert.equal(getSession.mock.calls.length, 1); assert.equal(respondToRuntimeRequest.mock.calls.length, 1); assert.deepEqual(respondToRuntimeRequest.mock.calls[0]?.[0], { requestId, decision: "accept", }); }).pipe(Effect.provide(testLayer));}); it.effect("rejects expired runtime requests before invoking the live adapter", () => { const threadId = ThreadId.make("thread-runtime-request-expired"); const providerSessionId = ProviderSessionId.make("provider-session-runtime-request-expired"); const requestId = RuntimeRequestId.make("request-expired"); const respondToRuntimeRequest = vi.fn( (_input: ProviderAdapterV2RuntimeRequestResponseInput) => Effect.void, ); const getSession = vi.fn(() => Effect.succeed( Option.some({ respondToRuntimeRequest, } as never), ), ); const projection = { runtimeRequests: [ { id: requestId, nodeId: NodeId.make("node-runtime-request-expired"), providerTurnId: null, nativeRequestRef: null, kind: "command", status: "expired", responseCapability: { type: "live", providerSessionId, }, createdAt: DateTime.makeUnsafe("2026-07-29T00:00:00.000Z"), resolvedAt: DateTime.makeUnsafe("2026-07-29T00:00:01.000Z"), }, ], } as unknown as OrchestrationV2ThreadProjection; const testLayer = runtimeRequestServiceLayer.pipe( Layer.provide( Layer.mergeAll( Layer.mock(ProjectionStoreV2)({ getRuntimeRequest: (_threadId, requestId) => Effect.succeed(projection.runtimeRequests.find((request) => request.id === requestId)), }), Layer.mock(ProviderSessionManagerV2)({ get: getSession, }), ), ), ); return Effect.gen(function* () { const service = yield* RuntimeRequestServiceV2; const error = yield* service .respond({ threadId, providerSessionId, requestId, decision: "accept", }) .pipe(Effect.flip); assert.equal(error.reason, "request-not-ready"); assert.equal( error.message, `Runtime request ${requestId} on thread ${threadId} is not ready for response execution.`, ); assert.isUndefined(error.cause); assert.equal(getSession.mock.calls.length, 0); assert.equal(respondToRuntimeRequest.mock.calls.length, 0); }).pipe(Effect.provide(testLayer));}); it.effect("classifies runtime request response validation failures", () => { const threadId = ThreadId.make("thread-runtime-request-validation"); const providerSessionId = ProviderSessionId.make("provider-session-runtime-request-validation"); const otherProviderSessionId = ProviderSessionId.make( "provider-session-runtime-request-validation-other", ); const requestId = RuntimeRequestId.make("request-validation"); const unexpectedGetSession = vi.fn(() => Effect.succeed(Option.none())); const missingLayer = runtimeRequestTestLayer( projectionWithRuntimeRequest(), unexpectedGetSession, ); const notResumableLayer = runtimeRequestTestLayer( projectionWithRuntimeRequest(resolvedRuntimeRequest(requestId, otherProviderSessionId)), unexpectedGetSession, ); const inactiveLayer = runtimeRequestTestLayer( projectionWithRuntimeRequest(resolvedRuntimeRequest(requestId, providerSessionId)), () => Effect.succeed(Option.none()), ); const respond = Effect.gen(function* () { const service = yield* RuntimeRequestServiceV2; return yield* service .respond({ threadId, providerSessionId, requestId, decision: "accept", }) .pipe(Effect.flip); }); return Effect.gen(function* () { const missing = yield* respond.pipe(Effect.provide(missingLayer)); assert.equal(missing.reason, "request-missing"); assert.equal( missing.message, `Runtime request ${requestId} no longer exists on thread ${threadId}.`, ); assert.isUndefined(missing.cause); const notResumable = yield* respond.pipe(Effect.provide(notResumableLayer)); assert.equal(notResumable.reason, "request-not-resumable"); assert.equal( notResumable.message, `Runtime request ${requestId} on thread ${threadId} is not resumable on provider session ${providerSessionId}.`, ); assert.isUndefined(notResumable.cause); const inactive = yield* respond.pipe(Effect.provide(inactiveLayer)); assert.equal(inactive.reason, "provider-session-not-active"); assert.equal( inactive.message, `Provider session ${providerSessionId} is not active for runtime request ${requestId} on thread ${threadId}.`, ); assert.isUndefined(inactive.cause); assert.equal(unexpectedGetSession.mock.calls.length, 0); });}); it.effect("preserves genuine provider session lookup failures as the cause", () => { const threadId = ThreadId.make("thread-runtime-request-lookup-failure"); const providerSessionId = ProviderSessionId.make( "provider-session-runtime-request-lookup-failure", ); const requestId = RuntimeRequestId.make("request-lookup-failure"); const lookupFailure = new ProviderSessionLookupError({ providerSessionId, cause: "lookup failed", }); const testLayer = runtimeRequestTestLayer( projectionWithRuntimeRequest(resolvedRuntimeRequest(requestId, providerSessionId)), () => Effect.fail(lookupFailure), ); return Effect.gen(function* () { const service = yield* RuntimeRequestServiceV2; const error = yield* service .respond({ threadId, providerSessionId, requestId, decision: "accept", }) .pipe(Effect.flip); assert.instanceOf(error, RuntimeRequestResponseExecutionError); assert.equal(error.reason, "unexpected-failure"); assert.equal( error.message, `Failed to respond to runtime request ${requestId} on thread ${threadId} via provider session ${providerSessionId}.`, ); assert.strictEqual(error.cause, lookupFailure); }).pipe(Effect.provide(testLayer));});
import { assert, it, vi } from "@effect/vitest";
import {
NodeId,
ProviderSessionId,
RuntimeRequestId,
ThreadId,
type OrchestrationV2RuntimeRequest,
type OrchestrationV2ThreadProjection,
} from "@t3tools/contracts";
import * as DateTime from "effect/DateTime";
import * as Effect from "effect/Effect";
import * as Layer from "effect/Layer";
import * as Option from "effect/Option";
import type { ProviderAdapterV2RuntimeRequestResponseInput } from "./ProviderAdapter.ts";
import { ProjectionStoreV2 } from "./ProjectionStore.ts";
import {
ProviderSessionLookupError,
ProviderSessionManagerV2,
type ProviderSessionManagerV2Shape,
} from "./ProviderSessionManager.ts";
import {
layer as runtimeRequestServiceLayer,
RuntimeRequestResponseExecutionError,
RuntimeRequestServiceV2,
} from "./RuntimeRequestService.ts";
function projectionWithRuntimeRequest(
runtimeRequest?: OrchestrationV2RuntimeRequest,
): OrchestrationV2ThreadProjection {
return {
runtimeRequests: runtimeRequest === undefined ? [] : [runtimeRequest],
} as unknown as OrchestrationV2ThreadProjection;
}
function resolvedRuntimeRequest(
requestId: RuntimeRequestId,
providerSessionId: ProviderSessionId,
): OrchestrationV2RuntimeRequest {
return {
id: requestId,
nodeId: NodeId.make(`node-${requestId}`),
providerTurnId: null,
nativeRequestRef: null,
kind: "command",
status: "resolved",
responseCapability: {
type: "live",
providerSessionId,
},
createdAt: DateTime.makeUnsafe("2026-07-29T00:00:00.000Z"),
resolvedAt: DateTime.makeUnsafe("2026-07-29T00:00:01.000Z"),
};
}
function runtimeRequestTestLayer(
projection: OrchestrationV2ThreadProjection,
getSession: ProviderSessionManagerV2Shape["get"],
) {
return runtimeRequestServiceLayer.pipe(
Layer.provide(
Layer.mergeAll(
Layer.mock(ProjectionStoreV2)({
getRuntimeRequest: (_threadId, requestId) =>
Effect.succeed(projection.runtimeRequests.find((request) => request.id === requestId)),
}),
Layer.mock(ProviderSessionManagerV2)({
get: getSession,
}),
),
),
);
}
it.effect("forwards orchestrator-resolved runtime requests to the live adapter", () => {
const threadId = ThreadId.make("thread-runtime-request-resolved");
const providerSessionId = ProviderSessionId.make("provider-session-runtime-request-resolved");
const requestId = RuntimeRequestId.make("request-resolved");
const respondToRuntimeRequest = vi.fn(
(_input: ProviderAdapterV2RuntimeRequestResponseInput) => Effect.void,
);
const getSession = vi.fn(() =>
Effect.succeed(
Option.some({
respondToRuntimeRequest,
} as never),
),
);
const projection = {
runtimeRequests: [
{
id: requestId,
nodeId: NodeId.make("node-runtime-request-resolved"),
providerTurnId: null,
nativeRequestRef: null,
kind: "command",
status: "resolved",
responseCapability: {
type: "live",
providerSessionId,
},
createdAt: DateTime.makeUnsafe("2026-07-29T00:00:00.000Z"),
resolvedAt: DateTime.makeUnsafe("2026-07-29T00:00:01.000Z"),
},
],
} as unknown as OrchestrationV2ThreadProjection;
const testLayer = runtimeRequestServiceLayer.pipe(
Layer.provide(
Layer.mergeAll(
Layer.mock(ProjectionStoreV2)({
getRuntimeRequest: (_threadId, requestId) =>
Effect.succeed(projection.runtimeRequests.find((request) => request.id === requestId)),
}),
Layer.mock(ProviderSessionManagerV2)({
get: getSession,
}),
),
),
);
return Effect.gen(function* () {
const service = yield* RuntimeRequestServiceV2;
yield* service.respond({
threadId,
providerSessionId,
requestId,
decision: "accept",
});
assert.equal(getSession.mock.calls.length, 1);
assert.equal(respondToRuntimeRequest.mock.calls.length, 1);
assert.deepEqual(respondToRuntimeRequest.mock.calls[0]?.[0], {
requestId,
decision: "accept",
});
}).pipe(Effect.provide(testLayer));
});
it.effect("rejects expired runtime requests before invoking the live adapter", () => {
const threadId = ThreadId.make("thread-runtime-request-expired");
const providerSessionId = ProviderSessionId.make("provider-session-runtime-request-expired");
const requestId = RuntimeRequestId.make("request-expired");
const respondToRuntimeRequest = vi.fn(
(_input: ProviderAdapterV2RuntimeRequestResponseInput) => Effect.void,
);
const getSession = vi.fn(() =>
Effect.succeed(
Option.some({
respondToRuntimeRequest,
} as never),
),
);
const projection = {
runtimeRequests: [
{
id: requestId,
nodeId: NodeId.make("node-runtime-request-expired"),
providerTurnId: null,
nativeRequestRef: null,
kind: "command",
status: "expired",
responseCapability: {
type: "live",
providerSessionId,
},
createdAt: DateTime.makeUnsafe("2026-07-29T00:00:00.000Z"),
resolvedAt: DateTime.makeUnsafe("2026-07-29T00:00:01.000Z"),
},
],
} as unknown as OrchestrationV2ThreadProjection;
const testLayer = runtimeRequestServiceLayer.pipe(
Layer.provide(
Layer.mergeAll(
Layer.mock(ProjectionStoreV2)({
getRuntimeRequest: (_threadId, requestId) =>
Effect.succeed(projection.runtimeRequests.find((request) => request.id === requestId)),
}),
Layer.mock(ProviderSessionManagerV2)({
get: getSession,
}),
),
),
);
return Effect.gen(function* () {
const service = yield* RuntimeRequestServiceV2;
const error = yield* service
.respond({
threadId,
providerSessionId,
requestId,
decision: "accept",
})
.pipe(Effect.flip);
assert.equal(error.reason, "request-not-ready");
assert.equal(
error.message,
`Runtime request ${requestId} on thread ${threadId} is not ready for response execution.`,
);
assert.isUndefined(error.cause);
assert.equal(getSession.mock.calls.length, 0);
assert.equal(respondToRuntimeRequest.mock.calls.length, 0);
}).pipe(Effect.provide(testLayer));
});
it.effect("classifies runtime request response validation failures", () => {
const threadId = ThreadId.make("thread-runtime-request-validation");
const providerSessionId = ProviderSessionId.make("provider-session-runtime-request-validation");
const otherProviderSessionId = ProviderSessionId.make(
"provider-session-runtime-request-validation-other",
);
const requestId = RuntimeRequestId.make("request-validation");
const unexpectedGetSession = vi.fn(() => Effect.succeed(Option.none()));
const missingLayer = runtimeRequestTestLayer(
projectionWithRuntimeRequest(),
unexpectedGetSession,
);
const notResumableLayer = runtimeRequestTestLayer(
projectionWithRuntimeRequest(resolvedRuntimeRequest(requestId, otherProviderSessionId)),
unexpectedGetSession,
);
const inactiveLayer = runtimeRequestTestLayer(
projectionWithRuntimeRequest(resolvedRuntimeRequest(requestId, providerSessionId)),
() => Effect.succeed(Option.none()),
);
const respond = Effect.gen(function* () {
const service = yield* RuntimeRequestServiceV2;
return yield* service
.respond({
threadId,
providerSessionId,
requestId,
decision: "accept",
})
.pipe(Effect.flip);
});
return Effect.gen(function* () {
const missing = yield* respond.pipe(Effect.provide(missingLayer));
assert.equal(missing.reason, "request-missing");
assert.equal(
missing.message,
`Runtime request ${requestId} no longer exists on thread ${threadId}.`,
);
assert.isUndefined(missing.cause);
const notResumable = yield* respond.pipe(Effect.provide(notResumableLayer));
assert.equal(notResumable.reason, "request-not-resumable");
assert.equal(
notResumable.message,
`Runtime request ${requestId} on thread ${threadId} is not resumable on provider session ${providerSessionId}.`,
);
assert.isUndefined(notResumable.cause);
const inactive = yield* respond.pipe(Effect.provide(inactiveLayer));
assert.equal(inactive.reason, "provider-session-not-active");
assert.equal(
inactive.message,
`Provider session ${providerSessionId} is not active for runtime request ${requestId} on thread ${threadId}.`,
);
assert.isUndefined(inactive.cause);
assert.equal(unexpectedGetSession.mock.calls.length, 0);
});
});
it.effect("preserves genuine provider session lookup failures as the cause", () => {
const threadId = ThreadId.make("thread-runtime-request-lookup-failure");
const providerSessionId = ProviderSessionId.make(
"provider-session-runtime-request-lookup-failure",
);
const requestId = RuntimeRequestId.make("request-lookup-failure");
const lookupFailure = new ProviderSessionLookupError({
providerSessionId,
cause: "lookup failed",
});
const testLayer = runtimeRequestTestLayer(
projectionWithRuntimeRequest(resolvedRuntimeRequest(requestId, providerSessionId)),
() => Effect.fail(lookupFailure),
);
return Effect.gen(function* () {
const service = yield* RuntimeRequestServiceV2;
const error = yield* service
.respond({
threadId,
providerSessionId,
requestId,
decision: "accept",
})
.pipe(Effect.flip);
assert.instanceOf(error, RuntimeRequestResponseExecutionError);
assert.equal(error.reason, "unexpected-failure");
assert.equal(
error.message,
`Failed to respond to runtime request ${requestId} on thread ${threadId} via provider session ${providerSessionId}.`,
);
assert.strictEqual(error.cause, lookupFailure);
}).pipe(Effect.provide(testLayer));
});