import { ApprovalRequestId, ChatAttachment, CheckpointRef, IsoDateTime, MessageId, NonNegativeInt, ProjectScript, TurnId, ModelSelection, ProjectId, ProjectIconOverride, ThreadId,} from "@t3tools/contracts";import { OrchestrationCheckpointFile, OrchestrationProposedPlanId, OrchestrationReadModel, OrchestrationThreadSearchSource, OrchestrationShellSnapshot, OrchestrationThread, OrchestrationThreadDetailSnapshot, type OrchestrationCheckpointSummary, type OrchestrationLatestTurn, type OrchestrationMessage, type OrchestrationProjectShell, type OrchestrationProposedPlan, type OrchestrationProject, type OrchestrationSession, type OrchestrationThreadActivity, type OrchestrationThreadShell,} from "@t3tools/contracts/legacy-orchestration";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 { ProjectionThreadSession } from "../../persistence/Services/ProjectionThreadSessions.ts";import { ProjectionThread } from "../../persistence/Services/ProjectionThreads.ts";import { ProjectEnrichmentService } from "../../project/ProjectEnrichmentService.ts";import { decodeThreadDetailPageCursor, encodeThreadDetailPageCursor,} from "../threadDetailCursor.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);// 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;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 ProjectionThreadProposedPlanDbRowSchema = ProjectionThreadProposedPlan;const ProjectionThreadDbRowSchema = ProjectionThread.mapFields( Struct.assign({ modelSelection: Schema.fromJsonString(ModelSelection), }),);const ProjectionThreadActivityDbRowSchema = ProjectionThreadActivity.mapFields( Struct.assign({ payload: Schema.fromJsonString(Schema.Unknown), sequence: Schema.NullOr(NonNegativeInt), }),);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 ThreadIdLookupInput = Schema.Struct({ threadId: ThreadId,});const ThreadActivityKindsLookupInput = Schema.Struct({ threadId: ThreadId, activityKinds: Schema.Array(Schema.String),});// 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 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 projectEnrichment = yield* ProjectEnrichmentService; const getAvailableRepositoryIdentities = Effect.fn( "ProjectionSnapshotQuery.getAvailableRepositoryIdentities", )(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))]; const repositoryIdentityByWorkspaceRoot = new Map( yield* Effect.forEach( uniqueWorkspaceRoots, (workspaceRoot) => projectEnrichment .getAvailable(workspaceRoot) .pipe( Effect.map((enrichment) => [workspaceRoot, enrichment.repositoryIdentity] as const), ), { concurrency: 16 }, ), ); return new Map( filteredProjectRows.map((row) => [ row.projectId, repositoryIdentityByWorkspaceRoot.get(row.workspaceRoot) ?? null, ]), ); }); const listProjectRows = SqlSchema.findAll({ Request: Schema.Void, Result: ProjectionProjectDbRowSchema, execute: () => sql` SELECT project_id AS "projectId", title, workspace_root AS "workspaceRoot", default_model_selection_json AS "defaultModelSelection", default_thread_env_mode AS "defaultThreadEnvMode", auto_pull AS "autoPull", favicon_path AS "faviconPath", project_icon_json AS "projectIcon", scripts_json AS "scripts", created_at AS "createdAt", updated_at AS "updatedAt", deleted_at AS "deletedAt" FROM projection_projects ORDER BY created_at ASC, project_id ASC `, }); const listThreadRows = SqlSchema.findAll({ Request: Schema.Void, Result: ProjectionThreadDbRowSchema, execute: () => sql` SELECT thread_id AS "threadId", project_id AS "projectId", title, model_selection_json AS "modelSelection", runtime_mode AS "runtimeMode", interaction_mode AS "interactionMode", branch, worktree_path AS "worktreePath", linked_pull_request_json AS "linkedPullRequest", latest_turn_id AS "latestTurnId", created_at AS "createdAt", updated_at AS "updatedAt", archived_at AS "archivedAt", settled_override AS "settledOverride", settled_at AS "settledAt", unsettled_at AS "unsettledAt", snoozed_until AS "snoozedUntil", snoozed_at AS "snoozedAt", pinned_at AS "pinnedAt", pin_order_key AS "pinOrderKey", title_regeneration_request_id AS "titleRegenerationRequestId", title_regeneration_started_at AS "titleRegenerationStartedAt", latest_user_message_at AS "latestUserMessageAt", pending_approval_count AS "pendingApprovalCount", pending_user_input_count AS "pendingUserInputCount", has_actionable_proposed_plan AS "hasActionableProposedPlan", deleted_at AS "deletedAt" FROM projection_threads ORDER BY created_at ASC, thread_id ASC `, }); const listActiveThreadRows = SqlSchema.findAll({ Request: Schema.Void, Result: ProjectionThreadDbRowSchema, execute: () => sql` SELECT thread_id AS "threadId", project_id AS "projectId", title, model_selection_json AS "modelSelection", runtime_mode AS "runtimeMode", interaction_mode AS "interactionMode", branch, worktree_path AS "worktreePath", linked_pull_request_json AS "linkedPullRequest", latest_turn_id AS "latestTurnId", created_at AS "createdAt", updated_at AS "updatedAt", archived_at AS "archivedAt", settled_override AS "settledOverride", settled_at AS "settledAt", unsettled_at AS "unsettledAt",Lines 1–500 of 3135. Load more
import { ApprovalRequestId, ChatAttachment, CheckpointRef, IsoDateTime, MessageId, NonNegativeInt, ProjectScript, TurnId, ModelSelection, ProjectId, ProjectIconOverride, ThreadId, } from "@t3tools/contracts"; import { OrchestrationCheckpointFile, OrchestrationProposedPlanId, OrchestrationReadModel, OrchestrationThreadSearchSource, OrchestrationShellSnapshot, OrchestrationThread, OrchestrationThreadDetailSnapshot, type OrchestrationCheckpointSummary, type OrchestrationLatestTurn, type OrchestrationMessage, type OrchestrationProjectShell, type OrchestrationProposedPlan, type OrchestrationProject, type OrchestrationSession, type OrchestrationThreadActivity, type OrchestrationThreadShell, } from "@t3tools/contracts/legacy-orchestration"; 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 { ProjectionThreadSession } from "../../persistence/Services/ProjectionThreadSessions.ts"; import { ProjectionThread } from "../../persistence/Services/ProjectionThreads.ts"; import { ProjectEnrichmentService } from "../../project/ProjectEnrichmentService.ts"; import { decodeThreadDetailPageCursor, encodeThreadDetailPageCursor, } from "../threadDetailCursor.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); // 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; 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 ProjectionThreadProposedPlanDbRowSchema = ProjectionThreadProposedPlan; const ProjectionThreadDbRowSchema = ProjectionThread.mapFields( Struct.assign({ modelSelection: Schema.fromJsonString(ModelSelection), }), ); const ProjectionThreadActivityDbRowSchema = ProjectionThreadActivity.mapFields( Struct.assign({ payload: Schema.fromJsonString(Schema.Unknown), sequence: Schema.NullOr(NonNegativeInt), }), ); 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 ThreadIdLookupInput = Schema.Struct({ threadId: ThreadId, }); const ThreadActivityKindsLookupInput = Schema.Struct({ threadId: ThreadId, activityKinds: Schema.Array(Schema.String), }); // 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 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 projectEnrichment = yield* ProjectEnrichmentService; const getAvailableRepositoryIdentities = Effect.fn( "ProjectionSnapshotQuery.getAvailableRepositoryIdentities", )(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))]; const repositoryIdentityByWorkspaceRoot = new Map( yield* Effect.forEach( uniqueWorkspaceRoots, (workspaceRoot) => projectEnrichment .getAvailable(workspaceRoot) .pipe( Effect.map((enrichment) => [workspaceRoot, enrichment.repositoryIdentity] as const), ), { concurrency: 16 }, ), ); return new Map( filteredProjectRows.map((row) => [ row.projectId, repositoryIdentityByWorkspaceRoot.get(row.workspaceRoot) ?? null, ]), ); }); const listProjectRows = SqlSchema.findAll({ Request: Schema.Void, Result: ProjectionProjectDbRowSchema, execute: () => sql` SELECT project_id AS "projectId", title, workspace_root AS "workspaceRoot", default_model_selection_json AS "defaultModelSelection", default_thread_env_mode AS "defaultThreadEnvMode", auto_pull AS "autoPull", favicon_path AS "faviconPath", project_icon_json AS "projectIcon", scripts_json AS "scripts", created_at AS "createdAt", updated_at AS "updatedAt", deleted_at AS "deletedAt" FROM projection_projects ORDER BY created_at ASC, project_id ASC `, }); const listThreadRows = SqlSchema.findAll({ Request: Schema.Void, Result: ProjectionThreadDbRowSchema, execute: () => sql` SELECT thread_id AS "threadId", project_id AS "projectId", title, model_selection_json AS "modelSelection", runtime_mode AS "runtimeMode", interaction_mode AS "interactionMode", branch, worktree_path AS "worktreePath", linked_pull_request_json AS "linkedPullRequest", latest_turn_id AS "latestTurnId", created_at AS "createdAt", updated_at AS "updatedAt", archived_at AS "archivedAt", settled_override AS "settledOverride", settled_at AS "settledAt", unsettled_at AS "unsettledAt", snoozed_until AS "snoozedUntil", snoozed_at AS "snoozedAt", pinned_at AS "pinnedAt", pin_order_key AS "pinOrderKey", title_regeneration_request_id AS "titleRegenerationRequestId", title_regeneration_started_at AS "titleRegenerationStartedAt", latest_user_message_at AS "latestUserMessageAt", pending_approval_count AS "pendingApprovalCount", pending_user_input_count AS "pendingUserInputCount", has_actionable_proposed_plan AS "hasActionableProposedPlan", deleted_at AS "deletedAt" FROM projection_threads ORDER BY created_at ASC, thread_id ASC `, }); const listActiveThreadRows = SqlSchema.findAll({ Request: Schema.Void, Result: ProjectionThreadDbRowSchema, execute: () => sql` SELECT thread_id AS "threadId", project_id AS "projectId", title, model_selection_json AS "modelSelection", runtime_mode AS "runtimeMode", interaction_mode AS "interactionMode", branch, worktree_path AS "worktreePath", linked_pull_request_json AS "linkedPullRequest", latest_turn_id AS "latestTurnId", created_at AS "createdAt", updated_at AS "updatedAt", archived_at AS "archivedAt", settled_override AS "settledOverride", settled_at AS "settledAt", unsettled_at AS "unsettledAt",