76 lines · 2.5 KB · TypeScript
RawDownload
import * as NodeCrypto from "@effect/platform-node/NodeCrypto";import { expect, it } from "@effect/vitest";import { EnvironmentId, ProviderInstanceId, ThreadId } from "@t3tools/contracts";import * as Effect from "effect/Effect";import * as Layer from "effect/Layer"; import { OrchestratorProjectionError } from "../orchestration-v2/Orchestrator.ts";import * as ThreadManagement from "../orchestration-v2/ThreadManagementService.ts";import type * as McpInvocationContext from "./McpInvocationContext.ts";import * as ThreadMetadataMcp from "./ThreadMetadataMcpService.ts"; const threadId = ThreadId.make("thread:metadata-caller");const scope: McpInvocationContext.McpInvocationScope = {  environmentId: EnvironmentId.make("environment:metadata-test"),  threadId,  providerSessionId: "provider-session:metadata-test",  providerInstanceId: ProviderInstanceId.make("codex"),  capabilities: new Set(["orchestration"]),  issuedAt: 1,}; function serviceLayer(  getThreadShell: ThreadManagement.ThreadManagementService["Service"]["getThreadShell"],) {  return ThreadMetadataMcp.layer.pipe(    Layer.provide(      Layer.merge(        Layer.mock(ThreadManagement.ThreadManagementService)({          getThreadShell,          getThreadProjection: () => Effect.die("projection must not load after shell failure"),        } satisfies Partial<ThreadManagement.ThreadManagementService["Service"]>),        NodeCrypto.layer,      ),    ),  );} const updateCallingThread = Effect.gen(function* () {  const service = yield* ThreadMetadataMcp.ThreadMetadataMcpService;  return yield* service.update(scope, {    action: "rename",    title: "Renamed thread",    clientRequestId: "metadata-caller-classification",  });}); it.effect("reports an absent calling thread as thread_not_found", () =>  Effect.gen(function* () {    const error = yield* updateCallingThread.pipe(      Effect.provide(serviceLayer(() => Effect.succeed(null))),      Effect.flip,    );     expect(error.code).toBe("thread_not_found");  }),); it.effect("keeps calling-thread storage failures as orchestration errors", () =>  Effect.gen(function* () {    const error = yield* updateCallingThread.pipe(      Effect.provide(        serviceLayer(() =>          Effect.fail(            new OrchestratorProjectionError({              threadId,              cause: new Error("storage unavailable"),            }),          ),        ),      ),      Effect.flip,    );     expect(error.code).toBe("orchestration_error");  }),);