3662 lines · 136.5 KB · TypeScript
RawDownload
import {  AgentSessionImportSource,  ApprovalRequestId,  ChatAttachment,  CheckpointRef,  IsoDateTime,  MessageId,  NonNegativeInt,  OrchestrationCheckpointFile,  OrchestrationProposedPlanId,  OrchestrationReadModel,  OrchestrationThreadSearchSource,  OrchestrationShellSnapshot,  OrchestrationThread,  OrchestrationThreadDetailSnapshot,  ProjectScript,  ProjectIconOverride,  TurnId,  type OrchestrationCheckpointSummary,  type OrchestrationLatestTurn,  type OrchestrationMessage,  type OrchestrationProjectShell,  type OrchestrationProposedPlan,  type OrchestrationProject,  type OrchestrationSession,  type OrchestrationThreadActivity,  type OrchestrationThreadShell,  ModelSelection,  ProjectId,  ThreadLinkedPullRequest,  ThreadId,  ThreadPullRequestSnapshot,  ThreadPullRequestStack,  type ThreadPullRequestLink,} from "@t3tools/contracts";import { legacyLinkedPullRequestOf } from "@t3tools/shared/threadPullRequests";import * as Arr from "effect/Array";import * as Effect from "effect/Effect";import * as Layer from "effect/Layer";import * as Option from "effect/Option";import * as Result from "effect/Result";import * as Schema from "effect/Schema";import * as Struct from "effect/Struct";import * as SqlClient from "effect/unstable/sql/SqlClient";import * as SqlSchema from "effect/unstable/sql/SqlSchema"; import {  isPersistenceError,  toPersistenceDecodeError,  toPersistenceSqlError,  type ProjectionRepositoryError,} from "../../persistence/Errors.ts";import { ProjectionCheckpoint } from "../../persistence/Services/ProjectionCheckpoints.ts";import { ThreadBackgroundLivenessService } from "../ThreadBackgroundLiveness.ts";import { ThreadPlanProgressService } from "../ThreadPlanProgress.ts";import { ProjectionProject } from "../../persistence/Services/ProjectionProjects.ts";import { ProjectionState } from "../../persistence/Services/ProjectionState.ts";import { ProjectionThreadActivity } from "../../persistence/Services/ProjectionThreadActivities.ts";import { ProjectionThreadMessage } from "../../persistence/Services/ProjectionThreadMessages.ts";import { ProjectionThreadProposedPlan } from "../../persistence/Services/ProjectionThreadProposedPlans.ts";import { ProjectionThreadPullRequest } from "../../persistence/ProjectionThreadPullRequests.ts";import { ProjectionThreadSession } from "../../persistence/Services/ProjectionThreadSessions.ts";import { ProjectionThread } from "../../persistence/Services/ProjectionThreads.ts";import {  decodeThreadDetailPageCursor,  encodeThreadDetailPageCursor,} from "../threadDetailCursor.ts";import { projectActivityPayload } from "../ActivityPayloadProjection.ts";import * as RepositoryIdentityResolver from "../../project/RepositoryIdentityResolver.ts";import { ORCHESTRATION_PROJECTOR_NAMES } from "./ProjectionPipeline.ts";import {  ProjectionSnapshotQuery,  type ProjectionEventReplayStats,  type ProjectionFullThreadDiffContext,  type ProjectionSnapshotCounts,  type ProjectionThreadCheckpointContext,  type ProjectionThreadDetailQuery,  type ProjectionSnapshotQueryShape,} from "../Services/ProjectionSnapshotQuery.ts"; const decodeReadModel = Schema.decodeUnknownEffect(OrchestrationReadModel);const decodeShellSnapshot = Schema.decodeUnknownEffect(OrchestrationShellSnapshot);const decodeThread = Schema.decodeUnknownEffect(OrchestrationThread);const decodeImportedTranscriptsPayload = Schema.decodeUnknownOption(  Schema.fromJsonString(    Schema.Struct({      importedTranscripts: Schema.Array(Schema.Unknown),    }),  ),);const decodeAgentSessionImportSource = Schema.decodeUnknownOption(AgentSessionImportSource);// Keep detail reads consistent with the in-memory projector's retained// activity window. Applying the limit in SQL avoids decoding an unbounded// payload_json set before the projector can enforce that invariant.const THREAD_DETAIL_ACTIVITY_LIMIT = 500;// Snapshot payloads are decoded and projected in small sequential batches so// one client read does not retain the raw payloads for the full activity window.const THREAD_DETAIL_ACTIVITY_PAYLOAD_BATCH_SIZE = 25;// SQLite trim defaults to spaces. Match the whitespace removed by String.trim.const MESSAGE_TRIM_WHITESPACE =  "\t\n\v\f\r \u00a0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000\ufeff";const ProjectionProjectDbRowSchema = ProjectionProject.mapFields(  Struct.assign({    defaultModelSelection: Schema.NullOr(Schema.fromJsonString(ModelSelection)),    autoPull: Schema.Number,    projectIcon: Schema.NullOr(Schema.fromJsonString(ProjectIconOverride)),    scripts: Schema.fromJsonString(Schema.Array(ProjectScript)),  }),);const ProjectionThreadMessageDbRowSchema = ProjectionThreadMessage.mapFields(  Struct.assign({    isStreaming: Schema.Number,    attachments: Schema.NullOr(Schema.fromJsonString(Schema.Array(ChatAttachment))),  }),);const ProjectionTurnStartMessageDbRowSchema = ProjectionThreadMessageDbRowSchema.mapFields(  Struct.assign({ hasOtherUserMessages: Schema.Number }),);const ProjectionThreadProposedPlanDbRowSchema = ProjectionThreadProposedPlan;const ProjectionThreadPullRequestDbRowSchema = ProjectionThreadPullRequest.mapFields(  Struct.assign({    snapshot: Schema.NullOr(Schema.fromJsonString(ThreadPullRequestSnapshot)),    stack: Schema.NullOr(Schema.fromJsonString(ThreadPullRequestStack)),  }),);const ProjectionThreadDbRowSchema = ProjectionThread.mapFields(  Struct.assign({    modelSelection: Schema.fromJsonString(ModelSelection),    linkedPullRequest: Schema.NullOr(Schema.fromJsonString(ThreadLinkedPullRequest)),    branchPullRequest: Schema.NullOr(Schema.fromJsonString(ThreadLinkedPullRequest)),  }),);const ProjectionThreadActivityDbRowSchema = ProjectionThreadActivity.mapFields(  Struct.assign({    payload: Schema.fromJsonString(Schema.Unknown),    sequence: Schema.NullOr(NonNegativeInt),  }),);const ProjectionThreadActivityIdRowSchema = Schema.Struct({  activityId: ProjectionThreadActivity.fields.activityId,});const ProjectionThreadSessionDbRowSchema = ProjectionThreadSession;const ProjectionThreadRuntimeContextDbRowSchema = Schema.Struct({  id: ThreadId,  title: Schema.String,  session: Schema.NullOr(ProjectionThreadSessionDbRowSchema),});const ProjectionCheckpointDbRowSchema = ProjectionCheckpoint.mapFields(  Struct.assign({    files: Schema.fromJsonString(Schema.Array(OrchestrationCheckpointFile)),  }),);const ProjectionLatestTurnDbRowSchema = Schema.Struct({  threadId: ProjectionThread.fields.threadId,  turnId: TurnId,  state: Schema.String,  requestedAt: IsoDateTime,  startedAt: Schema.NullOr(IsoDateTime),  completedAt: Schema.NullOr(IsoDateTime),  assistantMessageId: Schema.NullOr(MessageId),  sourceProposedPlanThreadId: Schema.NullOr(ThreadId),  sourceProposedPlanId: Schema.NullOr(OrchestrationProposedPlanId),});const ProjectionStateDbRowSchema = ProjectionState;const ProjectionCountsRowSchema = Schema.Struct({  projectCount: Schema.Number,  threadCount: Schema.Number,});const EventReplayStatsInput = Schema.Struct({  fromSequenceExclusive: NonNegativeInt,  toSequenceInclusive: NonNegativeInt,});const EventReplayStatsRowSchema = Schema.Struct({  eventCount: Schema.Number,  payloadBytes: Schema.Number,});const ProjectionThreadSearchRequest = Schema.Struct({  pattern: Schema.String,  limit: Schema.Int,});const ProjectionThreadSearchRow = Schema.Struct({  threadId: ThreadId,  projectId: ProjectId,  source: OrchestrationThreadSearchSource,  matchText: Schema.String,  messageCreatedAt: Schema.NullOr(IsoDateTime),});const WorkspaceRootLookupInput = Schema.Struct({  workspaceRoot: Schema.String,});const ProjectIdLookupInput = Schema.Struct({  projectId: ProjectId,});const ProjectionImportedAgentSessionSourcesRowSchema = Schema.Struct({  threadId: ThreadId,  runtimePayload: Schema.Unknown,});const ThreadIdLookupInput = Schema.Struct({  threadId: ThreadId,});const TurnStartMessageLookupInput = Schema.Struct({  threadId: ThreadId,  messageId: MessageId,});const ThreadActivityKindsLookupInput = Schema.Struct({  threadId: ThreadId,  activityKinds: Schema.Array(Schema.String),});const ThreadActivityIdsLookupInput = Schema.Struct({  activityIds: Schema.Array(ProjectionThreadActivity.fields.activityId),});// Windowed reads order turns by the stable keyset (anchor, turn key), where// anchor is requested_at and turn key is// COALESCE(turn_id, ''). Both are event-derived, so cursors survive the// revert projector's row-id rewrite and full projection rebuilds.const ThreadTurnWindowLookupInput = Schema.Struct({  threadId: ThreadId,  // Exclusive keyset upper bound. Sentinels "~"/"" mean unbounded ("~" sorts  // after every ISO timestamp).  beforeAnchorAt: Schema.String,  beforeTurnKey: Schema.String,  userTurnLimit: Schema.Number,  maxRawTurns: Schema.Number,});const ProjectionTurnWindowRowSchema = Schema.Struct({  // The turn's timeline anchor, used to bound rows that have no turn linkage  // (user messages and turnless activities) to the same page window.  anchorAt: Schema.String,  turnKey: Schema.String,});const ThreadTurnRangeLookupInput = Schema.Struct({  threadId: ThreadId,  // Turn-linked rows are bounded by the keyset range [min, before) over  // (anchor, turn key); turnless rows by the matching [minAnchorAt,  // beforeAnchorAt) time range. Unbounded ends use sentinels: "" for the  // lower bound, "~" (sorts after ISO dates) for the upper bound.  minAnchorAt: Schema.String,  minTurnKey: Schema.String,  beforeAnchorAt: Schema.String,  beforeTurnKey: Schema.String,});const ProjectionProjectLookupRowSchema = ProjectionProjectDbRowSchema;const ProjectionThreadIdLookupRowSchema = Schema.Struct({  threadId: ThreadId,});const ProjectionThreadCheckpointContextThreadRowSchema = Schema.Struct({  threadId: ThreadId,  projectId: ProjectId,  workspaceRoot: Schema.String,  worktreePath: Schema.NullOr(Schema.String),});const FullThreadDiffContextLookupInput = Schema.Struct({  threadId: ThreadId,  checkpointTurnCount: NonNegativeInt,});const ProjectionFullThreadDiffContextRowSchema = Schema.Struct({  threadId: ThreadId,  projectId: ProjectId,  workspaceRoot: Schema.String,  worktreePath: Schema.NullOr(Schema.String),  latestCheckpointTurnCount: Schema.NullOr(NonNegativeInt),  toCheckpointRef: Schema.NullOr(CheckpointRef),}); const REQUIRED_SNAPSHOT_PROJECTORS = [  ORCHESTRATION_PROJECTOR_NAMES.projects,  ORCHESTRATION_PROJECTOR_NAMES.threads,  ORCHESTRATION_PROJECTOR_NAMES.threadMessages,  ORCHESTRATION_PROJECTOR_NAMES.threadProposedPlans,  ORCHESTRATION_PROJECTOR_NAMES.threadActivities,  ORCHESTRATION_PROJECTOR_NAMES.threadSessions,  ORCHESTRATION_PROJECTOR_NAMES.checkpoints,] as const; function maxIso(left: string | null, right: string): string {  if (left === null) {    return right;  }  return left > right ? left : right;} function escapeLikePattern(value: string): string {  return value.replaceAll("!", "!!").replaceAll("%", "!%").replaceAll("_", "!_");} function foldAsciiCase(value: string): string {  return value.replace(/[A-Z]/g, (character) => character.toLowerCase());} function buildSearchSnippet(text: string, query: string): string {  const normalizedText = text.replace(/\s+/g, " ").trim();  if (normalizedText.length <= 240) {    return normalizedText;  }   const normalizedQuery = foldAsciiCase(query.replace(/\s+/g, " ").trim());  const matchIndex = foldAsciiCase(normalizedText).indexOf(normalizedQuery);  const bodyLength = 236;  const idealStart = Math.max(0, matchIndex - 72);  const start = Math.min(idealStart, normalizedText.length - bodyLength);  const end = Math.min(normalizedText.length, start + bodyLength);  return `${start > 0 ? "…" : ""}${normalizedText.slice(start, end)}${    end < normalizedText.length ? "…" : ""  }`;} function computeSnapshotSequence(  stateRows: ReadonlyArray<Schema.Schema.Type<typeof ProjectionStateDbRowSchema>>,): number {  if (stateRows.length === 0) {    return 0;  }  const sequenceByProjector = new Map(    stateRows.map((row) => [row.projector, row.lastAppliedSequence] as const),  );   let minSequence = Number.POSITIVE_INFINITY;  for (const projector of REQUIRED_SNAPSHOT_PROJECTORS) {    const sequence = sequenceByProjector.get(projector);    if (sequence === undefined) {      return 0;    }    if (sequence < minSequence) {      minSequence = sequence;    }  }   return Number.isFinite(minSequence) ? minSequence : 0;} function mapLatestTurn(  row: Schema.Schema.Type<typeof ProjectionLatestTurnDbRowSchema>,): OrchestrationLatestTurn {  return {    turnId: row.turnId,    state:      row.state === "error"        ? "error"        : row.state === "interrupted"          ? "interrupted"          : row.state === "completed"            ? "completed"            : "running",    requestedAt: row.requestedAt,    startedAt: row.startedAt,    completedAt: row.completedAt,    assistantMessageId: row.assistantMessageId,    ...(row.sourceProposedPlanThreadId !== null && row.sourceProposedPlanId !== null      ? {          sourceProposedPlan: {            threadId: row.sourceProposedPlanThreadId,            planId: row.sourceProposedPlanId,          },        }      : {}),  };} function mapTitleRegeneration(row: Schema.Schema.Type<typeof ProjectionThreadDbRowSchema>) {  return row.titleRegenerationRequestId != null && row.titleRegenerationStartedAt != null    ? {        requestId: row.titleRegenerationRequestId,        startedAt: row.titleRegenerationStartedAt,      }    : null;} function mapSessionRow(  row: Schema.Schema.Type<typeof ProjectionThreadSessionDbRowSchema>,): OrchestrationSession {  return {    threadId: row.threadId,    status: row.status,    providerName: row.providerName,    ...(row.providerInstanceId !== null ? { providerInstanceId: row.providerInstanceId } : {}),    runtimeMode: row.runtimeMode,    activeTurnId: row.activeTurnId,    lastError: row.lastError,    updatedAt: row.updatedAt,  };} function mapProjectShellRow(  row: Schema.Schema.Type<typeof ProjectionProjectDbRowSchema>,  repositoryIdentity: OrchestrationProject["repositoryIdentity"],): OrchestrationProjectShell {  return {    id: row.projectId,    title: row.title,    workspaceRoot: row.workspaceRoot,    repositoryIdentity,    defaultModelSelection: row.defaultModelSelection,    defaultThreadEnvMode: row.defaultThreadEnvMode,    autoPull: row.autoPull === 1,    faviconPath: row.faviconPath ?? null,    projectIcon: row.projectIcon ?? null,    scripts: row.scripts,    createdAt: row.createdAt,    updatedAt: row.updatedAt,  };} function mapProposedPlanRow(  row: Schema.Schema.Type<typeof ProjectionThreadProposedPlanDbRowSchema>,): OrchestrationProposedPlan {  return {    id: row.planId,    turnId: row.turnId,    planMarkdown: row.planMarkdown,    implementedAt: row.implementedAt,    implementationThreadId: row.implementationThreadId,    createdAt: row.createdAt,    updatedAt: row.updatedAt,  };} function mapPullRequestRow(  row: Schema.Schema.Type<typeof ProjectionThreadPullRequestDbRowSchema>,): ThreadPullRequestLink {  return {    host: row.host,    repository: row.repository,    number: row.number,    url: row.url,    source: row.source,    linkedAt: row.linkedAt,    snapshot: row.snapshot,    stack: row.stack,  };} function groupPullRequestRowsByThread(  rows: ReadonlyArray<Schema.Schema.Type<typeof ProjectionThreadPullRequestDbRowSchema>>,): Map<string, Array<ThreadPullRequestLink>> {  const byThread = new Map<string, Array<ThreadPullRequestLink>>();  for (const row of rows) {    const links = byThread.get(row.threadId) ?? [];    links.push(mapPullRequestRow(row));    byThread.set(row.threadId, links);  }  return byThread;} /** * The link array plus the legacy single-link field derived from it, so clients * from before `pullRequests` keep seeing the thread's current pull request. */function mapThreadPullRequests(  pullRequests: ReadonlyArray<ThreadPullRequestLink>,  projectId: ProjectId,  identity?: OrchestrationProject["repositoryIdentity"],): Pick<OrchestrationThread, "pullRequests" | "linkedPullRequest"> {  const linkedPullRequest = legacyLinkedPullRequestOf(pullRequests, projectId, identity);  return {    pullRequests,    ...(linkedPullRequest === null ? {} : { linkedPullRequest }),  };} function mapThreadActivityRow(  row: Schema.Schema.Type<typeof ProjectionThreadActivityDbRowSchema>,): OrchestrationThreadActivity {  return {    id: row.activityId,    tone: row.tone,    kind: row.kind,    summary: row.summary,    payload: row.payload,    turnId: row.turnId,    createdAt: row.createdAt,    ...(row.sequence !== null ? { sequence: row.sequence } : {}),  };} function toPersistenceSqlOrDecodeError(sqlOperation: string, decodeOperation: string) {  return (cause: unknown): ProjectionRepositoryError =>    Schema.isSchemaError(cause)      ? toPersistenceDecodeError(decodeOperation)(cause)      : toPersistenceSqlError(sqlOperation)(cause);} const makeProjectionSnapshotQuery = Effect.gen(function* () {  const threadBackgroundLiveness = yield* ThreadBackgroundLivenessService;  const threadPlanProgress = yield* ThreadPlanProgressService;  const sql = yield* SqlClient.SqlClient;  const repositoryIdentityResolver = yield* RepositoryIdentityResolver.RepositoryIdentityResolver;  const repositoryIdentityResolutionConcurrency = 4;  const resolveRepositoryIdentitiesForProjects = Effect.fn(    "ProjectionSnapshotQuery.resolveRepositoryIdentitiesForProjects",  )(function* (    projectRows: ReadonlyArray<Schema.Schema.Type<typeof ProjectionProjectDbRowSchema>>,    options?: {      readonly includeDeleted?: boolean;    },  ) {    const filteredProjectRows =      options?.includeDeleted === true        ? projectRows        : projectRows.filter((row) => row.deletedAt === null);    const uniqueWorkspaceRoots = [...new Set(filteredProjectRows.map((row) => row.workspaceRoot))];

Lines 1–500 of 3662.