301 lines · 9.8 KB · TypeScript
RawDownload
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));});