Skip to content
Source
Sign inSign up

handlers.ts

44 lines1.8 KB

1import * as Effect from "effect/Effect";
2import * as Preview from "../../../preview/Manager.ts";
3import { requireThreadMcpCapability } from "../../McpInvocationContext.ts";
4import * as McpToolAccess from "../../McpToolAccess.ts";
5import { unavailable } from "../../threadAccess.ts";
6import { PreviewControlsToolkit } from "./tools.ts";
7import * as PreviewAutomationBroker from "../../PreviewAutomationBroker.ts";
8​
9const access = Effect.gen(function* () {
10 const scope = yield* requireThreadMcpCapability("preview");
11 return { scope, manager: yield* Preview.PreviewManager };
12});
13export const layer = McpToolAccess.toLayer(PreviewControlsToolkit, {
14 t3_preview_list: McpToolAccess.readsAsCaller((input) =>
15 Effect.gen(function* () {
16 const { scope, manager } = yield* access;
17 const result = yield* manager.list({ threadId: scope.thread.threadId });
18 const start = input.cursor ?? 0;
19 const end = start + (input.limit ?? 20);
20 return {
21 ...result,
22 sessions: result.sessions.slice(start, end),
23 nextCursor: end < result.sessions.length ? end : null,
24 };
25 }),
26 ),
27 t3_preview_close: McpToolAccess.actsAsCaller((input) =>
28 Effect.gen(function* () {
29 const { scope, manager } = yield* access;
30 const { sessions } = yield* manager.list({ threadId: scope.thread.threadId });
31 if (
32 sessions.some((session) => session.tabId === input.tabId && session.runtime === "server")
33 ) {
34 const broker = yield* PreviewAutomationBroker.PreviewAutomationBroker;
35 yield* broker.invoke({ scope, operation: "close", input: {}, tabId: input.tabId });
36 return {};
37 }
38 yield* manager
39 .close({ threadId: scope.thread.threadId, tabId: input.tabId })
40 .pipe(Effect.mapError(unavailable));
41 return {};
42 }),
43 ),
44});