1import * as Schema from "effect/Schema";
2
3import { TrimmedNonEmptyString } from "./baseSchemas.ts";
4
5/** Uses the managed worktree folder; handoff detaches the provider, ending this turn and resuming there next run. */
6export const WorktreeMcpHandoffInput = Schema.Struct({
7 branch: TrimmedNonEmptyString,
8 baseRef: Schema.optional(
9 TrimmedNonEmptyString.annotate({
10 description: "Default: checked-out branch.",
11 }),
12 ),
13 startFromOrigin: Schema.optional(
14 Schema.Boolean.annotate({
15 description:
16 "True: fetch, start from the remote ref; check `startedFromOrigin`. Default: server setting.",
17 }),
18 ),
19 runSetupScript: Schema.optional(
20 Schema.Boolean.annotate({
21 description: "Default true.",
22 }),
23 ),
24 continuationPrompt: Schema.optional(
25 TrimmedNonEmptyString.check(Schema.isMaxLength(120_000)).annotate({
26 description: "Work to resume in the worktree next turn. Omitted: thread waits.",
27 }),
28 ),
29});
30export type WorktreeMcpHandoffInput = typeof WorktreeMcpHandoffInput.Type;
31
32export const WorktreeMcpSetupScriptStatus = Schema.Union([
33 Schema.Struct({
34 status: Schema.Literal("started"),
35 scriptName: TrimmedNonEmptyString,
36 terminalId: TrimmedNonEmptyString,
37 }),
38 Schema.Struct({
39 status: Schema.Literal("no-script"),
40 }),
41 Schema.Struct({
42 status: Schema.Literal("skipped"),
43 }),
44 Schema.Struct({
45 status: Schema.Literal("failed"),
46 detail: Schema.String,
47 }),
48]);
49export type WorktreeMcpSetupScriptStatus = typeof WorktreeMcpSetupScriptStatus.Type;
50
51export const WorktreeMcpContinuationStatus = Schema.Union([
52 Schema.Struct({
53 status: Schema.Literal("scheduled"),
54 delivery: Schema.Literals(["started", "queued", "steered", "restarted"]),
55 }),
56 Schema.Struct({
57 status: Schema.Literal("skipped"),
58 }),
59 Schema.Struct({
60 status: Schema.Literal("failed"),
61 detail: Schema.String,
62 }),
63]);
64export type WorktreeMcpContinuationStatus = typeof WorktreeMcpContinuationStatus.Type;
65
66export const WorktreeMcpHandoffResult = Schema.Struct({
67 worktreePath: TrimmedNonEmptyString,
68 branch: TrimmedNonEmptyString,
69 baseRef: TrimmedNonEmptyString,
70 startedFromOrigin: Schema.Boolean,
71 setupScript: WorktreeMcpSetupScriptStatus,
72 continuation: WorktreeMcpContinuationStatus,
73 note: Schema.String,
74});
75export type WorktreeMcpHandoffResult = typeof WorktreeMcpHandoffResult.Type;
76
77export const WorktreeMcpStatusResult = Schema.Struct({
78 attached: Schema.Boolean,
79 worktreePath: Schema.NullOr(TrimmedNonEmptyString),
80 branch: Schema.NullOr(TrimmedNonEmptyString),
81 projectWorkspaceRoot: TrimmedNonEmptyString,
82 defaultStartFromOrigin: Schema.Boolean.annotate({
83 description: "`startFromOrigin` default for `t3_worktree_handoff`.",
84 }),
85});
86export type WorktreeMcpStatusResult = typeof WorktreeMcpStatusResult.Type;
87
88export class WorktreeMcpFailure extends Schema.TaggedError<WorktreeMcpFailure>()(
89 "WorktreeMcpFailure",
90 {
91 code: Schema.Literals([
92 "capability_denied",
93 "thread_not_found",
94 "project_not_found",
95 "already_in_worktree",
96 "handoff_in_progress",
97 "invalid_request",
98 "operation_failed",
99 "thread_credential_required",
100 ]),
101 message: Schema.String,
102 },
103) {}