434 lines · 14.3 KB · TypeScript
RawDownload
import { Schema } from "effect";import { NonNegativeInt, PositiveInt, ThreadId, TrimmedNonEmptyString } from "./baseSchemas.ts"; const TrimmedNonEmptyStringSchema = TrimmedNonEmptyString;const GIT_LIST_BRANCHES_MAX_LIMIT = 200; // Domain Types export const GitStackedAction = Schema.Literals([  "commit",  "push",  "create_pr",  "commit_push",  "commit_push_pr",]);export type GitStackedAction = typeof GitStackedAction.Type;export const GitActionProgressPhase = Schema.Literals(["branch", "commit", "push", "pr"]);export type GitActionProgressPhase = typeof GitActionProgressPhase.Type;export const GitActionProgressKind = Schema.Literals([  "action_started",  "phase_started",  "hook_started",  "hook_output",  "hook_finished",  "action_finished",  "action_failed",]);export type GitActionProgressKind = typeof GitActionProgressKind.Type;export const GitActionProgressStream = Schema.Literals(["stdout", "stderr"]);export type GitActionProgressStream = typeof GitActionProgressStream.Type;const GitCommitStepStatus = Schema.Literals([  "created",  "skipped_no_changes",  "skipped_not_requested",]);const GitPushStepStatus = Schema.Literals([  "pushed",  "skipped_not_requested",  "skipped_up_to_date",]);const GitBranchStepStatus = Schema.Literals(["created", "skipped_not_requested"]);const GitPrStepStatus = Schema.Literals(["created", "opened_existing", "skipped_not_requested"]);const GitStatusPrState = Schema.Literals(["open", "closed", "merged"]);const GitPullRequestReference = TrimmedNonEmptyStringSchema;const GitPullRequestState = Schema.Literals(["open", "closed", "merged"]);const GitPreparePullRequestThreadMode = Schema.Literals(["local", "worktree"]);export const GitHostingProviderKind = Schema.Literals(["github", "gitlab", "unknown"]);export type GitHostingProviderKind = typeof GitHostingProviderKind.Type;export const GitHostingProvider = Schema.Struct({  kind: GitHostingProviderKind,  name: TrimmedNonEmptyStringSchema,  baseUrl: Schema.String,});export type GitHostingProvider = typeof GitHostingProvider.Type;export const GitRunStackedActionToastRunAction = Schema.Struct({  kind: GitStackedAction,});export type GitRunStackedActionToastRunAction = typeof GitRunStackedActionToastRunAction.Type;const GitRunStackedActionToastCta = Schema.Union([  Schema.Struct({    kind: Schema.Literal("none"),  }),  Schema.Struct({    kind: Schema.Literal("open_pr"),    label: TrimmedNonEmptyStringSchema,    url: Schema.String,  }),  Schema.Struct({    kind: Schema.Literal("run_action"),    label: TrimmedNonEmptyStringSchema,    action: GitRunStackedActionToastRunAction,  }),]);export type GitRunStackedActionToastCta = typeof GitRunStackedActionToastCta.Type;const GitRunStackedActionToast = Schema.Struct({  title: TrimmedNonEmptyStringSchema,  description: Schema.optional(TrimmedNonEmptyStringSchema),  cta: GitRunStackedActionToastCta,});export type GitRunStackedActionToast = typeof GitRunStackedActionToast.Type; export const GitBranch = Schema.Struct({  name: TrimmedNonEmptyStringSchema,  isRemote: Schema.optional(Schema.Boolean),  remoteName: Schema.optional(TrimmedNonEmptyStringSchema),  current: Schema.Boolean,  isDefault: Schema.Boolean,  worktreePath: TrimmedNonEmptyStringSchema.pipe(Schema.NullOr),});export type GitBranch = typeof GitBranch.Type; const GitWorktree = Schema.Struct({  path: TrimmedNonEmptyStringSchema,  branch: TrimmedNonEmptyStringSchema,});const GitResolvedPullRequest = Schema.Struct({  number: PositiveInt,  title: TrimmedNonEmptyStringSchema,  url: Schema.String,  baseBranch: TrimmedNonEmptyStringSchema,  headBranch: TrimmedNonEmptyStringSchema,  state: GitPullRequestState,});export type GitResolvedPullRequest = typeof GitResolvedPullRequest.Type; // RPC Inputs export const GitStatusInput = Schema.Struct({  cwd: TrimmedNonEmptyStringSchema,});export type GitStatusInput = typeof GitStatusInput.Type; export const GitPullInput = Schema.Struct({  cwd: TrimmedNonEmptyStringSchema,});export type GitPullInput = typeof GitPullInput.Type; export const GitRunStackedActionInput = Schema.Struct({  actionId: TrimmedNonEmptyStringSchema,  cwd: TrimmedNonEmptyStringSchema,  action: GitStackedAction,  commitMessage: Schema.optional(TrimmedNonEmptyStringSchema.check(Schema.isMaxLength(10_000))),  featureBranch: Schema.optional(Schema.Boolean),  filePaths: Schema.optional(    Schema.Array(TrimmedNonEmptyStringSchema).check(Schema.isMinLength(1)),  ),});export type GitRunStackedActionInput = typeof GitRunStackedActionInput.Type; export const GitListBranchesInput = Schema.Struct({  cwd: TrimmedNonEmptyStringSchema,  query: Schema.optional(TrimmedNonEmptyStringSchema.check(Schema.isMaxLength(256))),  cursor: Schema.optional(NonNegativeInt),  limit: Schema.optional(    PositiveInt.check(Schema.isLessThanOrEqualTo(GIT_LIST_BRANCHES_MAX_LIMIT)),  ),});export type GitListBranchesInput = typeof GitListBranchesInput.Type; export const GitCreateWorktreeInput = Schema.Struct({  cwd: TrimmedNonEmptyStringSchema,  branch: TrimmedNonEmptyStringSchema,  newBranch: Schema.optional(TrimmedNonEmptyStringSchema),  path: Schema.NullOr(TrimmedNonEmptyStringSchema),});export type GitCreateWorktreeInput = typeof GitCreateWorktreeInput.Type; export const GitPullRequestRefInput = Schema.Struct({  cwd: TrimmedNonEmptyStringSchema,  reference: GitPullRequestReference,});export type GitPullRequestRefInput = typeof GitPullRequestRefInput.Type; export const GitPreparePullRequestThreadInput = Schema.Struct({  cwd: TrimmedNonEmptyStringSchema,  reference: GitPullRequestReference,  mode: GitPreparePullRequestThreadMode,  threadId: Schema.optional(ThreadId),});export type GitPreparePullRequestThreadInput = typeof GitPreparePullRequestThreadInput.Type; export const GitRemoveWorktreeInput = Schema.Struct({  cwd: TrimmedNonEmptyStringSchema,  path: TrimmedNonEmptyStringSchema,  force: Schema.optional(Schema.Boolean),});export type GitRemoveWorktreeInput = typeof GitRemoveWorktreeInput.Type; export const GitCreateBranchInput = Schema.Struct({  cwd: TrimmedNonEmptyStringSchema,  branch: TrimmedNonEmptyStringSchema,  checkout: Schema.optional(Schema.Boolean),});export type GitCreateBranchInput = typeof GitCreateBranchInput.Type; export const GitCreateBranchResult = Schema.Struct({  branch: TrimmedNonEmptyStringSchema,});export type GitCreateBranchResult = typeof GitCreateBranchResult.Type; export const GitCheckoutInput = Schema.Struct({  cwd: TrimmedNonEmptyStringSchema,  branch: TrimmedNonEmptyStringSchema,});export type GitCheckoutInput = typeof GitCheckoutInput.Type; export const GitInitInput = Schema.Struct({  cwd: TrimmedNonEmptyStringSchema,});export type GitInitInput = typeof GitInitInput.Type; // RPC Results const GitStatusPr = Schema.Struct({  number: PositiveInt,  title: TrimmedNonEmptyStringSchema,  url: Schema.String,  baseBranch: TrimmedNonEmptyStringSchema,  headBranch: TrimmedNonEmptyStringSchema,  state: GitStatusPrState,}); const GitStatusLocalShape = {  isRepo: Schema.Boolean,  hostingProvider: Schema.optional(GitHostingProvider),  hasOriginRemote: Schema.Boolean,  isDefaultBranch: Schema.Boolean,  branch: Schema.NullOr(TrimmedNonEmptyStringSchema),  hasWorkingTreeChanges: Schema.Boolean,  workingTree: Schema.Struct({    files: Schema.Array(      Schema.Struct({        path: TrimmedNonEmptyStringSchema,        insertions: NonNegativeInt,        deletions: NonNegativeInt,      }),    ),    insertions: NonNegativeInt,    deletions: NonNegativeInt,  }),}; const GitStatusRemoteShape = {  hasUpstream: Schema.Boolean,  aheadCount: NonNegativeInt,  behindCount: NonNegativeInt,  pr: Schema.NullOr(GitStatusPr),}; export const GitStatusLocalResult = Schema.Struct(GitStatusLocalShape);export type GitStatusLocalResult = typeof GitStatusLocalResult.Type; export const GitStatusRemoteResult = Schema.Struct(GitStatusRemoteShape);export type GitStatusRemoteResult = typeof GitStatusRemoteResult.Type; export const GitStatusResult = Schema.Struct({  ...GitStatusLocalShape,  ...GitStatusRemoteShape,});export type GitStatusResult = typeof GitStatusResult.Type; export const GitStatusStreamEvent = Schema.Union([  Schema.TaggedStruct("snapshot", {    local: GitStatusLocalResult,    remote: Schema.NullOr(GitStatusRemoteResult),  }),  Schema.TaggedStruct("localUpdated", {    local: GitStatusLocalResult,  }),  Schema.TaggedStruct("remoteUpdated", {    remote: Schema.NullOr(GitStatusRemoteResult),  }),]);export type GitStatusStreamEvent = typeof GitStatusStreamEvent.Type; export const GitListBranchesResult = Schema.Struct({  branches: Schema.Array(GitBranch),  isRepo: Schema.Boolean,  hasOriginRemote: Schema.Boolean,  nextCursor: NonNegativeInt.pipe(Schema.NullOr),  totalCount: NonNegativeInt,});export type GitListBranchesResult = typeof GitListBranchesResult.Type; export const GitCreateWorktreeResult = Schema.Struct({  worktree: GitWorktree,});export type GitCreateWorktreeResult = typeof GitCreateWorktreeResult.Type; export const GitResolvePullRequestResult = Schema.Struct({  pullRequest: GitResolvedPullRequest,});export type GitResolvePullRequestResult = typeof GitResolvePullRequestResult.Type; export const GitPreparePullRequestThreadResult = Schema.Struct({  pullRequest: GitResolvedPullRequest,  branch: TrimmedNonEmptyStringSchema,  worktreePath: TrimmedNonEmptyStringSchema.pipe(Schema.NullOr),});export type GitPreparePullRequestThreadResult = typeof GitPreparePullRequestThreadResult.Type; export const GitCheckoutResult = Schema.Struct({  branch: Schema.NullOr(TrimmedNonEmptyStringSchema),});export type GitCheckoutResult = typeof GitCheckoutResult.Type; export const GitRunStackedActionResult = Schema.Struct({  action: GitStackedAction,  branch: Schema.Struct({    status: GitBranchStepStatus,    name: Schema.optional(TrimmedNonEmptyStringSchema),  }),  commit: Schema.Struct({    status: GitCommitStepStatus,    commitSha: Schema.optional(TrimmedNonEmptyStringSchema),    subject: Schema.optional(TrimmedNonEmptyStringSchema),  }),  push: Schema.Struct({    status: GitPushStepStatus,    branch: Schema.optional(TrimmedNonEmptyStringSchema),    upstreamBranch: Schema.optional(TrimmedNonEmptyStringSchema),    setUpstream: Schema.optional(Schema.Boolean),  }),  pr: Schema.Struct({    status: GitPrStepStatus,    url: Schema.optional(Schema.String),    number: Schema.optional(PositiveInt),    baseBranch: Schema.optional(TrimmedNonEmptyStringSchema),    headBranch: Schema.optional(TrimmedNonEmptyStringSchema),    title: Schema.optional(TrimmedNonEmptyStringSchema),  }),  toast: GitRunStackedActionToast,});export type GitRunStackedActionResult = typeof GitRunStackedActionResult.Type; export const GitPullResult = Schema.Struct({  status: Schema.Literals(["pulled", "skipped_up_to_date"]),  branch: TrimmedNonEmptyStringSchema,  upstreamBranch: TrimmedNonEmptyStringSchema.pipe(Schema.NullOr),});export type GitPullResult = typeof GitPullResult.Type; // RPC / domain errorsexport class GitCommandError extends Schema.TaggedErrorClass<GitCommandError>()("GitCommandError", {  operation: Schema.String,  command: Schema.String,  cwd: Schema.String,  detail: Schema.String,  cause: Schema.optional(Schema.Defect),}) {  override get message(): string {    return `Git command failed in ${this.operation}: ${this.command} (${this.cwd}) - ${this.detail}`;  }} export class GitHubCliError extends Schema.TaggedErrorClass<GitHubCliError>()("GitHubCliError", {  operation: Schema.String,  detail: Schema.String,  cause: Schema.optional(Schema.Defect),}) {  override get message(): string {    return `GitHub CLI failed in ${this.operation}: ${this.detail}`;  }} export class TextGenerationError extends Schema.TaggedErrorClass<TextGenerationError>()(  "TextGenerationError",  {    operation: Schema.String,    detail: Schema.String,    cause: Schema.optional(Schema.Defect),  },) {  override get message(): string {    return `Text generation failed in ${this.operation}: ${this.detail}`;  }} export class GitManagerError extends Schema.TaggedErrorClass<GitManagerError>()("GitManagerError", {  operation: Schema.String,  detail: Schema.String,  cause: Schema.optional(Schema.Defect),}) {  override get message(): string {    return `Git manager failed in ${this.operation}: ${this.detail}`;  }} export const GitManagerServiceError = Schema.Union([  GitManagerError,  GitCommandError,  GitHubCliError,  TextGenerationError,]);export type GitManagerServiceError = typeof GitManagerServiceError.Type; const GitActionProgressBase = Schema.Struct({  actionId: TrimmedNonEmptyStringSchema,  cwd: TrimmedNonEmptyStringSchema,  action: GitStackedAction,}); const GitActionStartedEvent = Schema.Struct({  ...GitActionProgressBase.fields,  kind: Schema.Literal("action_started"),  phases: Schema.Array(GitActionProgressPhase),});const GitActionPhaseStartedEvent = Schema.Struct({  ...GitActionProgressBase.fields,  kind: Schema.Literal("phase_started"),  phase: GitActionProgressPhase,  label: TrimmedNonEmptyStringSchema,});const GitActionHookStartedEvent = Schema.Struct({  ...GitActionProgressBase.fields,  kind: Schema.Literal("hook_started"),  hookName: TrimmedNonEmptyStringSchema,});const GitActionHookOutputEvent = Schema.Struct({  ...GitActionProgressBase.fields,  kind: Schema.Literal("hook_output"),  hookName: Schema.NullOr(TrimmedNonEmptyStringSchema),  stream: GitActionProgressStream,  text: TrimmedNonEmptyStringSchema,});const GitActionHookFinishedEvent = Schema.Struct({  ...GitActionProgressBase.fields,  kind: Schema.Literal("hook_finished"),  hookName: TrimmedNonEmptyStringSchema,  exitCode: Schema.NullOr(Schema.Int),  durationMs: Schema.NullOr(NonNegativeInt),});const GitActionFinishedEvent = Schema.Struct({  ...GitActionProgressBase.fields,  kind: Schema.Literal("action_finished"),  result: GitRunStackedActionResult,});const GitActionFailedEvent = Schema.Struct({  ...GitActionProgressBase.fields,  kind: Schema.Literal("action_failed"),  phase: Schema.NullOr(GitActionProgressPhase),  message: TrimmedNonEmptyStringSchema,}); export const GitActionProgressEvent = Schema.Union([  GitActionStartedEvent,  GitActionPhaseStartedEvent,  GitActionHookStartedEvent,  GitActionHookOutputEvent,  GitActionHookFinishedEvent,  GitActionFinishedEvent,  GitActionFailedEvent,]);export type GitActionProgressEvent = typeof GitActionProgressEvent.Type;