1311 lines · 43.0 KB · TypeScript
RawDownload
import * as Effect from "effect/Effect";import * as Option from "effect/Option";import * as Schema from "effect/Schema";import * as SchemaIssue from "effect/SchemaIssue";import * as SchemaTransformation from "effect/SchemaTransformation";import * as Struct from "effect/Struct";import { ProviderOptionSelections } from "./model.ts";import { RepositoryIdentity } from "./environment.ts";import {  ApprovalRequestId,  CheckpointRef,  CommandId,  EventId,  IsoDateTime,  MessageId,  NonNegativeInt,  ProjectId,  ProviderItemId,  ThreadId,  TrimmedNonEmptyString,  TurnId,} from "./baseSchemas.ts";import { ProviderInstanceId } from "./providerInstance.ts"; export const ORCHESTRATION_WS_METHODS = {  dispatchCommand: "orchestration.dispatchCommand",  getTurnDiff: "orchestration.getTurnDiff",  getFullThreadDiff: "orchestration.getFullThreadDiff",  replayEvents: "orchestration.replayEvents",  getArchivedShellSnapshot: "orchestration.getArchivedShellSnapshot",  subscribeShell: "orchestration.subscribeShell",  subscribeThread: "orchestration.subscribeThread",} as const; export const ProviderApprovalPolicy = Schema.Literals([  "untrusted",  "on-failure",  "on-request",  "never",]);export type ProviderApprovalPolicy = typeof ProviderApprovalPolicy.Type;export const ProviderSandboxMode = Schema.Literals([  "read-only",  "workspace-write",  "danger-full-access",]);export type ProviderSandboxMode = typeof ProviderSandboxMode.Type; /** * `ModelSelection` — selection of a model on a configured provider instance. * * The routing key is `instanceId` (a user-defined slug identifying one * configured provider instance). Drivers, credentials, working-directory * bindings, and any other per-instance state are recovered from the * runtime registry via the instance id. * * Wire legacy: persisted selections produced before the driver/instance * split carried a `provider: <driver-id>` field instead. The schema absorbs * that shape via a pre-decoding transform — `{provider, model}` is promoted * to `{instanceId: defaultInstanceIdForDriver(provider), model}`. No * post-decode compatibility code lives in the runtime; the transform is the * only compat surface. */const ModelSelectionWire = Schema.Struct({  instanceId: ProviderInstanceId,  model: TrimmedNonEmptyString,  options: Schema.optionalKey(ProviderOptionSelections),}); // Source shape for persisted legacy payloads. Fields are typed as// `Schema.Unknown` so malformed drafts still make it into the transform and// fail validation through the target schema (with proper error messages)// rather than at the source-struct layer where the error is less actionable.const ModelSelectionSource = Schema.Struct({  provider: Schema.optional(Schema.Unknown),  instanceId: Schema.optional(Schema.Unknown),  model: Schema.Unknown,  options: Schema.optional(Schema.Unknown),}); export const ModelSelection = ModelSelectionSource.pipe(  Schema.decodeTo(    ModelSelectionWire,    SchemaTransformation.transformOrFail({      decode: (raw) => {        // Resolve the routing key: prefer an explicit `instanceId`; fall        // back to promoting the legacy `provider` slug (the canonical        // `defaultInstanceIdForDriver` mapping) so persisted rollout-era        // payloads decode without data loss. The target schema brands the        // string as `ProviderInstanceId`.        const instanceIdSource =          raw.instanceId !== undefined            ? raw.instanceId            : typeof raw.provider === "string"              ? raw.provider              : undefined;        const base: Record<string, unknown> = {          instanceId: instanceIdSource,          model: raw.model,        };        if (raw.options !== undefined) base.options = raw.options;        return Effect.succeed(base as typeof ModelSelectionWire.Encoded);      },      encode: (value) => {        const base: Record<string, unknown> = {          model: value.model,          instanceId: value.instanceId,        };        if (value.options !== undefined) base.options = value.options;        return Effect.succeed(base as typeof ModelSelectionSource.Encoded);      },    }),  ),);export type ModelSelection = typeof ModelSelection.Type; export const RuntimeMode = Schema.Literals([  "approval-required",  "auto-accept-edits",  "full-access",]);export type RuntimeMode = typeof RuntimeMode.Type;export const DEFAULT_RUNTIME_MODE: RuntimeMode = "full-access";export const ProviderInteractionMode = Schema.Literals(["default", "plan"]);export type ProviderInteractionMode = typeof ProviderInteractionMode.Type;export const DEFAULT_PROVIDER_INTERACTION_MODE: ProviderInteractionMode = "default";export const ProviderRequestKind = Schema.Literals(["command", "file-read", "file-change"]);export type ProviderRequestKind = typeof ProviderRequestKind.Type;export const AssistantDeliveryMode = Schema.Literals(["buffered", "streaming"]);export type AssistantDeliveryMode = typeof AssistantDeliveryMode.Type;export const ProviderApprovalDecision = Schema.Literals([  "accept",  "acceptForSession",  "decline",  "cancel",]);export type ProviderApprovalDecision = typeof ProviderApprovalDecision.Type;export const ProviderUserInputAnswers = Schema.Record(Schema.String, Schema.Unknown);export type ProviderUserInputAnswers = typeof ProviderUserInputAnswers.Type; export const PROVIDER_SEND_TURN_MAX_INPUT_CHARS = 120_000;export const PROVIDER_SEND_TURN_MAX_ATTACHMENTS = 8;export const PROVIDER_SEND_TURN_MAX_IMAGE_BYTES = 10 * 1024 * 1024;const PROVIDER_SEND_TURN_MAX_IMAGE_DATA_URL_CHARS = 14_000_000;const CHAT_ATTACHMENT_ID_MAX_CHARS = 128;// Correlation id is command id by design in this model.export const CorrelationId = CommandId;export type CorrelationId = typeof CorrelationId.Type; const ChatAttachmentId = TrimmedNonEmptyString.check(  Schema.isMaxLength(CHAT_ATTACHMENT_ID_MAX_CHARS),  Schema.isPattern(/^[a-z0-9_-]+$/i),);export type ChatAttachmentId = typeof ChatAttachmentId.Type; export const ChatImageAttachment = Schema.Struct({  type: Schema.Literal("image"),  id: ChatAttachmentId,  name: TrimmedNonEmptyString.check(Schema.isMaxLength(255)),  mimeType: TrimmedNonEmptyString.check(Schema.isMaxLength(100), Schema.isPattern(/^image\//i)),  sizeBytes: NonNegativeInt.check(Schema.isLessThanOrEqualTo(PROVIDER_SEND_TURN_MAX_IMAGE_BYTES)),});export type ChatImageAttachment = typeof ChatImageAttachment.Type; const UploadChatImageAttachment = Schema.Struct({  type: Schema.Literal("image"),  name: TrimmedNonEmptyString.check(Schema.isMaxLength(255)),  mimeType: TrimmedNonEmptyString.check(Schema.isMaxLength(100), Schema.isPattern(/^image\//i)),  sizeBytes: NonNegativeInt.check(Schema.isLessThanOrEqualTo(PROVIDER_SEND_TURN_MAX_IMAGE_BYTES)),  dataUrl: TrimmedNonEmptyString.check(    Schema.isMaxLength(PROVIDER_SEND_TURN_MAX_IMAGE_DATA_URL_CHARS),  ),});export type UploadChatImageAttachment = typeof UploadChatImageAttachment.Type; export const ChatAttachment = Schema.Union([ChatImageAttachment]);export type ChatAttachment = typeof ChatAttachment.Type;const UploadChatAttachment = Schema.Union([UploadChatImageAttachment]);export type UploadChatAttachment = typeof UploadChatAttachment.Type; 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,  /**   * URL to open in the in-app browser preview when this script runs (or   * when the user explicitly requests a preview). Optional; only honored on   * the desktop build.   */  previewUrl: Schema.optional(TrimmedNonEmptyString),  /**   * When true, automatically open the preview panel pointed at `previewUrl`   * the moment this script starts. Ignored without `previewUrl` or on web.   */  autoOpenPreview: Schema.optional(Schema.Boolean),});export type ProjectScript = typeof ProjectScript.Type; export const OrchestrationProject = Schema.Struct({  id: ProjectId,  title: TrimmedNonEmptyString,  workspaceRoot: TrimmedNonEmptyString,  repositoryIdentity: Schema.optional(Schema.NullOr(RepositoryIdentity)),  defaultModelSelection: Schema.NullOr(ModelSelection),  scripts: Schema.Array(ProjectScript),  createdAt: IsoDateTime,  updatedAt: IsoDateTime,  deletedAt: Schema.NullOr(IsoDateTime),});export type OrchestrationProject = typeof OrchestrationProject.Type; export const OrchestrationMessageRole = Schema.Literals(["user", "assistant", "system"]);export type OrchestrationMessageRole = typeof OrchestrationMessageRole.Type; export const OrchestrationMessage = Schema.Struct({  id: MessageId,  role: OrchestrationMessageRole,  text: Schema.String,  attachments: Schema.optional(Schema.Array(ChatAttachment)),  turnId: Schema.NullOr(TurnId),  streaming: Schema.Boolean,  createdAt: IsoDateTime,  updatedAt: IsoDateTime,});export type OrchestrationMessage = typeof OrchestrationMessage.Type; export const OrchestrationProposedPlanId = TrimmedNonEmptyString;export type OrchestrationProposedPlanId = typeof OrchestrationProposedPlanId.Type; export const OrchestrationProposedPlan = Schema.Struct({  id: OrchestrationProposedPlanId,  turnId: Schema.NullOr(TurnId),  planMarkdown: TrimmedNonEmptyString,  implementedAt: Schema.NullOr(IsoDateTime).pipe(Schema.withDecodingDefault(Effect.succeed(null))),  implementationThreadId: Schema.NullOr(ThreadId).pipe(    Schema.withDecodingDefault(Effect.succeed(null)),  ),  createdAt: IsoDateTime,  updatedAt: IsoDateTime,});export type OrchestrationProposedPlan = typeof OrchestrationProposedPlan.Type; const SourceProposedPlanReference = Schema.Struct({  threadId: ThreadId,  planId: OrchestrationProposedPlanId,}); export const OrchestrationSessionStatus = Schema.Literals([  "idle",  "starting",  "running",  "ready",  "interrupted",  "stopped",  "error",]);export type OrchestrationSessionStatus = typeof OrchestrationSessionStatus.Type; export const OrchestrationSession = Schema.Struct({  threadId: ThreadId,  status: OrchestrationSessionStatus,  providerName: Schema.NullOr(TrimmedNonEmptyString),  providerInstanceId: Schema.optional(ProviderInstanceId),  runtimeMode: RuntimeMode.pipe(Schema.withDecodingDefault(Effect.succeed(DEFAULT_RUNTIME_MODE))),  activeTurnId: Schema.NullOr(TurnId),  lastError: Schema.NullOr(TrimmedNonEmptyString),  updatedAt: IsoDateTime,});export type OrchestrationSession = typeof OrchestrationSession.Type; export const OrchestrationCheckpointFile = Schema.Struct({  path: TrimmedNonEmptyString,  kind: TrimmedNonEmptyString,  additions: NonNegativeInt,  deletions: NonNegativeInt,});export type OrchestrationCheckpointFile = typeof OrchestrationCheckpointFile.Type; export const OrchestrationCheckpointStatus = Schema.Literals(["ready", "missing", "error"]);export type OrchestrationCheckpointStatus = typeof OrchestrationCheckpointStatus.Type; export const OrchestrationCheckpointSummary = Schema.Struct({  turnId: TurnId,  checkpointTurnCount: NonNegativeInt,  checkpointRef: CheckpointRef,  status: OrchestrationCheckpointStatus,  files: Schema.Array(OrchestrationCheckpointFile),  assistantMessageId: Schema.NullOr(MessageId),  completedAt: IsoDateTime,});export type OrchestrationCheckpointSummary = typeof OrchestrationCheckpointSummary.Type; export const OrchestrationThreadActivityTone = Schema.Literals([  "info",  "tool",  "approval",  "error",]);export type OrchestrationThreadActivityTone = typeof OrchestrationThreadActivityTone.Type; export const OrchestrationThreadActivity = Schema.Struct({  id: EventId,  tone: OrchestrationThreadActivityTone,  kind: TrimmedNonEmptyString,  summary: TrimmedNonEmptyString,  payload: Schema.Unknown,  turnId: Schema.NullOr(TurnId),  sequence: Schema.optional(NonNegativeInt),  createdAt: IsoDateTime,});export type OrchestrationThreadActivity = typeof OrchestrationThreadActivity.Type; const OrchestrationLatestTurnState = Schema.Literals([  "running",  "interrupted",  "completed",  "error",]);export type OrchestrationLatestTurnState = typeof OrchestrationLatestTurnState.Type; export const OrchestrationLatestTurn = Schema.Struct({  turnId: TurnId,  state: OrchestrationLatestTurnState,  requestedAt: IsoDateTime,  startedAt: Schema.NullOr(IsoDateTime),  completedAt: Schema.NullOr(IsoDateTime),  assistantMessageId: Schema.NullOr(MessageId),  sourceProposedPlan: Schema.optional(SourceProposedPlanReference),});export type OrchestrationLatestTurn = typeof OrchestrationLatestTurn.Type; export const OrchestrationThread = Schema.Struct({  id: ThreadId,  projectId: ProjectId,  title: TrimmedNonEmptyString,  modelSelection: ModelSelection,  runtimeMode: RuntimeMode,  interactionMode: ProviderInteractionMode.pipe(    Schema.withDecodingDefault(Effect.succeed(DEFAULT_PROVIDER_INTERACTION_MODE)),  ),  branch: Schema.NullOr(TrimmedNonEmptyString),  worktreePath: Schema.NullOr(TrimmedNonEmptyString),  latestTurn: Schema.NullOr(OrchestrationLatestTurn),  createdAt: IsoDateTime,  updatedAt: IsoDateTime,  archivedAt: Schema.NullOr(IsoDateTime).pipe(Schema.withDecodingDefault(Effect.succeed(null))),  deletedAt: Schema.NullOr(IsoDateTime),  messages: Schema.Array(OrchestrationMessage),  proposedPlans: Schema.Array(OrchestrationProposedPlan).pipe(    Schema.withDecodingDefault(Effect.succeed([])),  ),  activities: Schema.Array(OrchestrationThreadActivity),  checkpoints: Schema.Array(OrchestrationCheckpointSummary),  session: Schema.NullOr(OrchestrationSession),});export type OrchestrationThread = typeof OrchestrationThread.Type; export const OrchestrationReadModel = Schema.Struct({  snapshotSequence: NonNegativeInt,  projects: Schema.Array(OrchestrationProject),  threads: Schema.Array(OrchestrationThread),  updatedAt: IsoDateTime,});export type OrchestrationReadModel = typeof OrchestrationReadModel.Type; export const OrchestrationProjectShell = Schema.Struct({  id: ProjectId,  title: TrimmedNonEmptyString,  workspaceRoot: TrimmedNonEmptyString,  repositoryIdentity: Schema.optional(Schema.NullOr(RepositoryIdentity)),  defaultModelSelection: Schema.NullOr(ModelSelection),  scripts: Schema.Array(ProjectScript),  createdAt: IsoDateTime,  updatedAt: IsoDateTime,});export type OrchestrationProjectShell = typeof OrchestrationProjectShell.Type; export const OrchestrationThreadShell = Schema.Struct({  id: ThreadId,  projectId: ProjectId,  title: TrimmedNonEmptyString,  modelSelection: ModelSelection,  runtimeMode: RuntimeMode,  interactionMode: ProviderInteractionMode.pipe(    Schema.withDecodingDefault(Effect.succeed(DEFAULT_PROVIDER_INTERACTION_MODE)),  ),  branch: Schema.NullOr(TrimmedNonEmptyString),  worktreePath: Schema.NullOr(TrimmedNonEmptyString),  latestTurn: Schema.NullOr(OrchestrationLatestTurn),  createdAt: IsoDateTime,  updatedAt: IsoDateTime,  archivedAt: Schema.NullOr(IsoDateTime).pipe(Schema.withDecodingDefault(Effect.succeed(null))),  session: Schema.NullOr(OrchestrationSession),  latestUserMessageAt: Schema.NullOr(IsoDateTime),  hasPendingApprovals: Schema.Boolean,  hasPendingUserInput: Schema.Boolean,  hasActionableProposedPlan: Schema.Boolean,});export type OrchestrationThreadShell = typeof OrchestrationThreadShell.Type; export const OrchestrationShellSnapshot = Schema.Struct({  snapshotSequence: NonNegativeInt,  projects: Schema.Array(OrchestrationProjectShell),  threads: Schema.Array(OrchestrationThreadShell),  updatedAt: IsoDateTime,});export type OrchestrationShellSnapshot = typeof OrchestrationShellSnapshot.Type; export const OrchestrationShellStreamEvent = Schema.Union([  Schema.Struct({    kind: Schema.Literal("project-upserted"),    sequence: NonNegativeInt,    project: OrchestrationProjectShell,  }),  Schema.Struct({    kind: Schema.Literal("project-removed"),    sequence: NonNegativeInt,    projectId: ProjectId,  }),  Schema.Struct({    kind: Schema.Literal("thread-upserted"),    sequence: NonNegativeInt,    thread: OrchestrationThreadShell,  }),  Schema.Struct({    kind: Schema.Literal("thread-removed"),    sequence: NonNegativeInt,    threadId: ThreadId,  }),]);export type OrchestrationShellStreamEvent = typeof OrchestrationShellStreamEvent.Type; export const OrchestrationShellStreamItem = Schema.Union([  Schema.Struct({    kind: Schema.Literal("snapshot"),    snapshot: OrchestrationShellSnapshot,  }),  OrchestrationShellStreamEvent,]);export type OrchestrationShellStreamItem = typeof OrchestrationShellStreamItem.Type; export const OrchestrationSubscribeShellInput = Schema.Struct({  /**   * When provided, the server skips the initial full shell snapshot and instead   * replays shell events after this sequence before streaming live events.   * Clients that already hold a cached (or HTTP-loaded) shell snapshot pass its   * sequence here so the subscription resumes without re-sending the entire   * projects/threads list (overlapping events are deduped by sequence on the   * client).   */  afterSequence: Schema.optionalKey(NonNegativeInt),});export type OrchestrationSubscribeShellInput = typeof OrchestrationSubscribeShellInput.Type; export const OrchestrationSubscribeThreadInput = Schema.Struct({  threadId: ThreadId,  /**   * When provided, the server skips the initial snapshot frame and instead   * replays events after this sequence before streaming live events. Clients   * that load the snapshot over HTTP pass the snapshot's sequence here so the   * live subscription resumes without a gap (overlapping events are deduped by   * sequence on the client).   */  afterSequence: Schema.optionalKey(NonNegativeInt),});export type OrchestrationSubscribeThreadInput = typeof OrchestrationSubscribeThreadInput.Type; export const OrchestrationThreadDetailSnapshot = Schema.Struct({  snapshotSequence: NonNegativeInt,  thread: OrchestrationThread,});export type OrchestrationThreadDetailSnapshot = typeof OrchestrationThreadDetailSnapshot.Type; export const ProjectCreateCommand = 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)),  createdAt: IsoDateTime,}); const ProjectMetaUpdateCommand = Schema.Struct({  type: Schema.Literal("project.meta.update"),  commandId: CommandId,  projectId: ProjectId,

Lines 1–500 of 1311.