95 lines · 3.6 KB · TypeScript
RawDownload
import * as Schema from "effect/Schema";import * as SchemaTransformation from "effect/SchemaTransformation"; import { ThreadEnvMode } from "./environment.ts";import { ProjectScriptIcon } from "./orchestration.ts"; /** File name of the checked-in T3 project file, resolved at the workspace root. */export const T3_PROJECT_FILE_NAME = "t3.json"; /** Public URL of the published JSON Schema for {@link T3ProjectFile}. */export const T3_PROJECT_FILE_SCHEMA_URL = "https://t3.codes/schema/t3.json"; const T3_PROJECT_FILE_PATH_MAX_LENGTH = 512;const T3_PROJECT_FILE_MAX_SCRIPTS = 50; // Annotations go on the encoded (string) side so they survive into the// published JSON Schema; decoding still trims and re-validates non-emptiness.const trimmedNonEmpty = (annotations: { readonly description: string }, maxLength?: number) => {  const annotated = Schema.String.annotate(annotations);  const encoded =    maxLength === undefined      ? annotated.check(Schema.isNonEmpty())      : annotated.check(Schema.isNonEmpty(), Schema.isMaxLength(maxLength));  return encoded.pipe(Schema.decodeTo(encoded, SchemaTransformation.trim()));}; export const T3ProjectFileScript = Schema.Struct({  name: trimmedNonEmpty({    description: "Display name for the script, shown in the T3 Code scripts menu.",  }),  command: trimmedNonEmpty({    description: "Shell command executed in a T3 Code terminal at the project root.",  }),  icon: Schema.optionalKey(    ProjectScriptIcon.annotate({      description: 'Icon shown next to the script in the scripts menu. Defaults to "play".',    }),  ),  runOnWorktreeCreate: Schema.optionalKey(    Schema.Boolean.annotate({      description:        "When true, the script runs automatically after a worktree is created for a new thread.",    }),  ),  previewUrl: Schema.optionalKey(    trimmedNonEmpty({      description:        "URL opened in the in-app browser preview when this script runs. Only honored on the desktop build.",    }),  ),  autoOpenPreview: Schema.optionalKey(    Schema.Boolean.annotate({      description:        "When true, automatically open the preview panel at `previewUrl` the moment the script starts.",    }),  ),}).annotate({  description: "A project script that team members can import into T3 Code.",});export type T3ProjectFileScript = typeof T3ProjectFileScript.Type; export const T3ProjectFile = Schema.Struct({  $schema: Schema.optionalKey(    Schema.String.annotate({      description: `URL of the JSON Schema for this file, typically "${T3_PROJECT_FILE_SCHEMA_URL}".`,    }),  ),  iconPath: Schema.optionalKey(    trimmedNonEmpty(      {        description:          'Workspace-relative path to the project icon (e.g. "assets/logo.svg"). Checked before T3 Code\'s built-in icon locations.',      },      T3_PROJECT_FILE_PATH_MAX_LENGTH,    ),  ),  defaultThreadEnvMode: Schema.optionalKey(    ThreadEnvMode.annotate({      description:        'Where new threads start for this repository: "worktree" for a fresh git worktree, "local" for the current checkout. A per-project setting in T3 Code overrides this; when neither is set, the global default applies.',    }),  ),  scripts: Schema.optionalKey(    Schema.Array(T3ProjectFileScript)      .annotate({        description: "Project scripts shared with everyone who opens this repository in T3 Code.",      })      .check(Schema.isMaxLength(T3_PROJECT_FILE_MAX_SCRIPTS)),  ),}).annotate({  title: "T3 project file",  description:    "Checked-in project configuration for T3 Code (t3.json at the repository root). See https://t3.codes for documentation.",});export type T3ProjectFile = typeof T3ProjectFile.Type;