1import {
2 NonNegativeInt,
3 OrchestratorMcpFailure,
4 PreviewAutomationUnavailableError,
5 PreviewListResult,
6 PreviewTabId,
7} from "@t3tools/contracts";
8import * as Schema from "effect/Schema";
9import { Tool, Toolkit } from "effect/ai";
10import * as ThreadManagementService from "../../../orchestration-v2/ThreadManagementService.ts";
11import * as PreviewManager from "../../../preview/Manager.ts";
12import * as PreviewAutomationBroker from "../../PreviewAutomationBroker.ts";
13import * as McpInvocationContext from "../../McpInvocationContext.ts";
14
15const shared = {
16 failure: Schema.Union([OrchestratorMcpFailure, PreviewAutomationUnavailableError]),
17 failureMode: "return" as const,
18 dependencies: [
19 McpInvocationContext.McpInvocationContext,
20 ThreadManagementService.ThreadManagementService,
21 PreviewManager.PreviewManager,
22 PreviewAutomationBroker.PreviewAutomationBroker,
23 ],
24};
25const PreviewListTool = Tool.make("t3_preview_list", {
26 ...shared,
27 description:
28 "List this thread's preview tabs. Pages reflect the current server state and may shift as tabs change.",
29 parameters: Schema.Struct({
30 cursor: Schema.optional(NonNegativeInt),
31 limit: Schema.optional(Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 50 }))),
32 }),
33 success: Schema.Struct({
34 ...PreviewListResult.fields,
35 nextCursor: Schema.NullOr(NonNegativeInt),
36 }),
37})
38 .annotate(Tool.Readonly, true)
39 .annotate(Tool.Destructive, false);
40const PreviewCloseTool = Tool.make("t3_preview_close", {
41 ...shared,
42 description:
43 "Close one preview tab owned by this thread through the normal server/host tab lifecycle. This does not wait for renderer cleanup.",
44 parameters: Schema.Struct({ tabId: PreviewTabId }),
45 success: Schema.Struct({}),
46}).annotate(Tool.Destructive, true);
47export const PreviewControlsToolkit = Toolkit.make(PreviewListTool, PreviewCloseTool);