446 lines · 14.6 KB · TypeScript
RawDownload
import * as Schema from "effect/Schema";import { RepositoryIdentity, ThreadEnvMode } from "./environment.ts";import { ModelSelection } from "./modelSelection.ts";import {  CommandId,  IsoDateTime,  NonNegativeInt,  PositiveInt,  ProjectId,  TrimmedNonEmptyString,  TrimmedString,} from "./baseSchemas.ts"; const PROJECT_SEARCH_ENTRIES_MAX_LIMIT = 200;const PROJECT_SEARCH_CONTENTS_MAX_LIMIT = 500;const PROJECT_WRITE_FILE_PATH_MAX_LENGTH = 512;const PROJECT_READ_FILE_PATH_MAX_LENGTH = 512; export const ProjectScriptIcon = Schema.Literals([  "play",  "test",  "lint",  "configure",  "build",  "debug",]);export type ProjectScriptIcon = typeof ProjectScriptIcon.Type; export const ProjectScript = Schema.Struct({  id: TrimmedNonEmptyString,  name: TrimmedNonEmptyString,  command: TrimmedNonEmptyString,  icon: ProjectScriptIcon,  runOnWorktreeCreate: Schema.Boolean,  previewUrl: Schema.optional(TrimmedNonEmptyString),  autoOpenPreview: Schema.optional(Schema.Boolean),});export type ProjectScript = typeof ProjectScript.Type; export const ProjectIconColor = Schema.Literals([  "gray",  "red",  "orange",  "amber",  "yellow",  "lime",  "green",  "emerald",  "teal",  "cyan",  "sky",  "blue",  "indigo",  "violet",  "purple",  "fuchsia",  "pink",  "rose",]);export type ProjectIconColor = typeof ProjectIconColor.Type; const ProjectLucideIconName = TrimmedNonEmptyString.check(  Schema.isMaxLength(64),  Schema.isPattern(/^[a-z0-9]+(?:-[a-z0-9]+)*$/),); const ProjectEmoji = TrimmedNonEmptyString.check(Schema.isMaxLength(32)); export const ProjectIconOverride = Schema.Union([  Schema.Struct({    kind: Schema.Literal("lucide"),    name: ProjectLucideIconName,    color: ProjectIconColor,  }),  Schema.Struct({    kind: Schema.Literal("emoji"),    emoji: ProjectEmoji,  }),]);export type ProjectIconOverride = typeof ProjectIconOverride.Type; export const Project = Schema.Struct({  id: ProjectId,  title: TrimmedNonEmptyString,  workspaceRoot: TrimmedNonEmptyString,  repositoryIdentity: Schema.optional(Schema.NullOr(RepositoryIdentity)),  faviconPath: Schema.optional(Schema.NullOr(TrimmedNonEmptyString)),  projectIcon: Schema.optional(Schema.NullOr(ProjectIconOverride)),  defaultModelSelection: Schema.NullOr(ModelSelection),  defaultThreadEnvMode: Schema.optional(Schema.NullOr(ThreadEnvMode)),  // Opt-in because background sync performs network I/O and may move the checkout.  autoPull: Schema.optional(Schema.Boolean),  scripts: Schema.Array(ProjectScript),  createdAt: IsoDateTime,  updatedAt: IsoDateTime,  deletedAt: Schema.NullOr(IsoDateTime),});export type Project = typeof Project.Type; export const ProjectSnapshot = Schema.Struct({  projects: Schema.Array(Project),  updatedAt: IsoDateTime,});export type ProjectSnapshot = typeof ProjectSnapshot.Type; export const ProjectChange = Schema.Union([  Schema.Struct({ type: Schema.Literal("project.upserted"), project: Project }),  Schema.Struct({    type: Schema.Literal("project.deleted"),    projectId: ProjectId,    deletedAt: IsoDateTime,  }),]);export type ProjectChange = typeof ProjectChange.Type; export const ProjectMutation = Schema.Union([  Schema.Struct({    type: Schema.Literal("project.create"),    commandId: CommandId,    projectId: ProjectId,    title: TrimmedNonEmptyString,    workspaceRoot: TrimmedNonEmptyString,    createWorkspaceRootIfMissing: Schema.optional(Schema.Boolean),    defaultModelSelection: Schema.optional(Schema.NullOr(ModelSelection)),    scripts: Schema.optional(Schema.Array(ProjectScript)),  }),  Schema.Struct({    type: Schema.Literal("project.update"),    commandId: CommandId,    projectId: ProjectId,    title: Schema.optional(TrimmedNonEmptyString),    workspaceRoot: Schema.optional(TrimmedNonEmptyString),    defaultModelSelection: Schema.optional(Schema.NullOr(ModelSelection)),    autoPull: Schema.optional(Schema.Boolean),    projectIcon: Schema.optional(Schema.NullOr(ProjectIconOverride)),    faviconPath: Schema.optional(Schema.NullOr(TrimmedNonEmptyString)),    defaultThreadEnvMode: Schema.optional(Schema.NullOr(ThreadEnvMode)),    scripts: Schema.optional(Schema.Array(ProjectScript)),  }),  Schema.Struct({    type: Schema.Literal("project.delete"),    commandId: CommandId,    projectId: ProjectId,    force: Schema.optional(Schema.Boolean),  }),]);export type ProjectMutation = typeof ProjectMutation.Type; export class ProjectMutationError extends Schema.TaggedErrorClass<ProjectMutationError>()(  "ProjectMutationError",  {    commandId: CommandId,    message: Schema.String,    cause: Schema.optional(Schema.Defect()),  },) {} export const ProjectEntryKind = Schema.Literals(["file", "directory"]);export type ProjectEntryKind = typeof ProjectEntryKind.Type; export const ProjectSearchEntriesInput = Schema.Struct({  cwd: TrimmedNonEmptyString,  // An empty query is a bounded browse: the index returns frecency-ordered  // entries, which the file picker uses for its initial results.  query: TrimmedString.check(Schema.isMaxLength(256)),  limit: PositiveInt.check(Schema.isLessThanOrEqualTo(PROJECT_SEARCH_ENTRIES_MAX_LIMIT)),  kind: Schema.optional(ProjectEntryKind),  imageOnly: Schema.optional(Schema.Boolean),});export type ProjectSearchEntriesInput = typeof ProjectSearchEntriesInput.Type; export const ProjectEntry = Schema.Struct({  path: TrimmedNonEmptyString,  kind: ProjectEntryKind,});export type ProjectEntry = typeof ProjectEntry.Type; export const ProjectSearchEntriesResult = Schema.Struct({  entries: Schema.Array(ProjectEntry),  truncated: Schema.Boolean,});export type ProjectSearchEntriesResult = typeof ProjectSearchEntriesResult.Type; export const ProjectSearchContentsInput = Schema.Struct({  cwd: TrimmedNonEmptyString,  // Whitespace is significant in content queries (" foo", regex trailing  // spaces), so the query is deliberately not trimmed on the wire.  query: Schema.String.check(Schema.isNonEmpty(), Schema.isMaxLength(256)),  limit: PositiveInt.check(Schema.isLessThanOrEqualTo(PROJECT_SEARCH_CONTENTS_MAX_LIMIT)),  caseSensitive: Schema.Boolean,  wholeWord: Schema.Boolean,  useRegex: Schema.Boolean,});export type ProjectSearchContentsInput = typeof ProjectSearchContentsInput.Type; export const ProjectContentMatchRange = Schema.Struct({  start: NonNegativeInt,  end: NonNegativeInt,});export type ProjectContentMatchRange = typeof ProjectContentMatchRange.Type; export const ProjectContentMatch = Schema.Struct({  path: TrimmedNonEmptyString,  lineNumber: PositiveInt,  lineContent: Schema.String,  matchRanges: Schema.Array(ProjectContentMatchRange),});export type ProjectContentMatch = typeof ProjectContentMatch.Type; export const ProjectSearchContentsResult = Schema.Struct({  matches: Schema.Array(ProjectContentMatch),  truncated: Schema.Boolean,  regexFallbackError: Schema.optional(Schema.String),});export type ProjectSearchContentsResult = typeof ProjectSearchContentsResult.Type; export const ProjectListEntriesInput = Schema.Struct({  cwd: TrimmedNonEmptyString,});export type ProjectListEntriesInput = typeof ProjectListEntriesInput.Type; export const ProjectListEntriesResult = Schema.Struct({  entries: Schema.Array(ProjectEntry),  truncated: Schema.Boolean,});export type ProjectListEntriesResult = typeof ProjectListEntriesResult.Type; export const ProjectEntriesFailure = Schema.Literals([  "workspace_root_not_found",  "workspace_root_create_failed",  "workspace_root_stat_failed",  "workspace_root_not_directory",  "search_index_create_failed",  "search_index_scan_timed_out",  "search_index_search_failed",]);export type ProjectEntriesFailure = typeof ProjectEntriesFailure.Type; type ProjectEntriesFailureContext = {  readonly failure: ProjectEntriesFailure;  readonly normalizedCwd?: string;  readonly timeout?: string;  readonly detail?: string;  readonly cause?: unknown;}; function decodedProjectErrorMessage(props: object): string | undefined {  if (!("message" in props)) return undefined;  return typeof props.message === "string" ? props.message : undefined;} export class ProjectSearchEntriesError extends Schema.TaggedErrorClass<ProjectSearchEntriesError>()(  "ProjectSearchEntriesError",  {    cwd: Schema.optional(TrimmedNonEmptyString),    queryLength: Schema.optional(NonNegativeInt),    limit: Schema.optional(PositiveInt),    failure: Schema.optional(ProjectEntriesFailure),    normalizedCwd: Schema.optional(TrimmedNonEmptyString),    timeout: Schema.optional(TrimmedNonEmptyString),    detail: Schema.optional(TrimmedNonEmptyString),    message: TrimmedNonEmptyString,    cause: Schema.optional(Schema.Defect()),  },) {  // The structured fields are optional on the wire so newer peers can decode legacy message-only  // failures. New application code must provide them through this constructor.  // @effect-diagnostics-next-line overriddenSchemaConstructor:off  constructor(    props: ProjectEntriesFailureContext & {      readonly cwd: string;      readonly queryLength: number;      readonly limit: number;    },  ) {    super({      ...props,      message:        decodedProjectErrorMessage(props) ??        `Failed to search workspace entries in '${props.cwd}'.`,    } as any);  }} export class ProjectSearchContentsError extends Schema.TaggedErrorClass<ProjectSearchContentsError>()(  "ProjectSearchContentsError",  {    cwd: Schema.optional(TrimmedNonEmptyString),    queryLength: Schema.optional(NonNegativeInt),    limit: Schema.optional(PositiveInt),    failure: Schema.optional(ProjectEntriesFailure),    normalizedCwd: Schema.optional(TrimmedNonEmptyString),    timeout: Schema.optional(TrimmedNonEmptyString),    detail: Schema.optional(TrimmedNonEmptyString),    message: TrimmedNonEmptyString,    cause: Schema.optional(Schema.Defect()),  },) {  // @effect-diagnostics-next-line overriddenSchemaConstructor:off  constructor(    props: ProjectEntriesFailureContext & {      readonly cwd: string;      readonly queryLength: number;      readonly limit: number;    },  ) {    super({      ...props,      message:        decodedProjectErrorMessage(props) ??        `Failed to search workspace contents in '${props.cwd}'.`,    } as any);  }} export class ProjectListEntriesError extends Schema.TaggedErrorClass<ProjectListEntriesError>()(  "ProjectListEntriesError",  {    cwd: Schema.optional(TrimmedNonEmptyString),    failure: Schema.optional(ProjectEntriesFailure),    normalizedCwd: Schema.optional(TrimmedNonEmptyString),    timeout: Schema.optional(TrimmedNonEmptyString),    detail: Schema.optional(TrimmedNonEmptyString),    message: TrimmedNonEmptyString,    cause: Schema.optional(Schema.Defect()),  },) {  // @effect-diagnostics-next-line overriddenSchemaConstructor:off  constructor(props: ProjectEntriesFailureContext & { readonly cwd: string }) {    super({      ...props,      message:        decodedProjectErrorMessage(props) ?? `Failed to list workspace entries in '${props.cwd}'.`,    } as any);  }} export const ProjectReadFileInput = Schema.Struct({  cwd: TrimmedNonEmptyString,  // Workspace-relative, or an absolute host path for a file outside the  // workspace. Only workspace-relative paths can be written back.  relativePath: TrimmedNonEmptyString.check(Schema.isMaxLength(PROJECT_READ_FILE_PATH_MAX_LENGTH)),});export type ProjectReadFileInput = typeof ProjectReadFileInput.Type; export const ProjectReadFileResult = Schema.Struct({  relativePath: TrimmedNonEmptyString,  contents: Schema.String,  byteLength: NonNegativeInt,  truncated: Schema.Boolean,});export type ProjectReadFileResult = typeof ProjectReadFileResult.Type; export const ProjectFileFailure = Schema.Literals([  "workspace_path_outside_root",  "resolved_path_outside_root",  "path_not_file",  "binary_file",  "operation_failed",]);export type ProjectFileFailure = typeof ProjectFileFailure.Type; export const ProjectFileOperation = Schema.Literals([  "realpath-workspace-root",  "realpath-target",  "open",  "stat",  "read",  "close",  "make-directory",  "write-file",]);export type ProjectFileOperation = typeof ProjectFileOperation.Type; type ProjectFileFailureContext = {  readonly cwd: string;  readonly relativePath: string;  readonly failure: ProjectFileFailure;  readonly resolvedPath?: string;  readonly resolvedWorkspaceRoot?: string;  readonly operation?: ProjectFileOperation;  readonly operationPath?: string;  readonly cause?: unknown;}; export class ProjectReadFileError extends Schema.TaggedErrorClass<ProjectReadFileError>()(  "ProjectReadFileError",  {    cwd: Schema.optional(TrimmedNonEmptyString),    relativePath: Schema.optional(TrimmedNonEmptyString),    failure: Schema.optional(ProjectFileFailure),    resolvedPath: Schema.optional(TrimmedNonEmptyString),    resolvedWorkspaceRoot: Schema.optional(TrimmedNonEmptyString),    operation: Schema.optional(ProjectFileOperation),    operationPath: Schema.optional(TrimmedNonEmptyString),    message: TrimmedNonEmptyString,    cause: Schema.optional(Schema.Defect()),  },) {  // @effect-diagnostics-next-line overriddenSchemaConstructor:off  constructor(props: ProjectFileFailureContext) {    super({      ...props,      message:        decodedProjectErrorMessage(props) ??        `Failed to read workspace file '${props.relativePath}' in '${props.cwd}'.`,    } as any);  }} export const ProjectWriteFileInput = Schema.Struct({  cwd: TrimmedNonEmptyString,  relativePath: TrimmedNonEmptyString.check(Schema.isMaxLength(PROJECT_WRITE_FILE_PATH_MAX_LENGTH)),  contents: Schema.String,});export type ProjectWriteFileInput = typeof ProjectWriteFileInput.Type; export const ProjectWriteFileResult = Schema.Struct({  relativePath: TrimmedNonEmptyString,});export type ProjectWriteFileResult = typeof ProjectWriteFileResult.Type; export class ProjectWriteFileError extends Schema.TaggedErrorClass<ProjectWriteFileError>()(  "ProjectWriteFileError",  {    cwd: Schema.optional(TrimmedNonEmptyString),    relativePath: Schema.optional(TrimmedNonEmptyString),    failure: Schema.optional(ProjectFileFailure),    resolvedPath: Schema.optional(TrimmedNonEmptyString),    resolvedWorkspaceRoot: Schema.optional(TrimmedNonEmptyString),    operation: Schema.optional(ProjectFileOperation),    operationPath: Schema.optional(TrimmedNonEmptyString),    message: TrimmedNonEmptyString,    cause: Schema.optional(Schema.Defect()),  },) {  // @effect-diagnostics-next-line overriddenSchemaConstructor:off  constructor(props: ProjectFileFailureContext) {    super({      ...props,      message:        decodedProjectErrorMessage(props) ??        `Failed to write workspace file '${props.relativePath}' in '${props.cwd}'.`,    } as any);  }}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t