import type { OrchestrationV2AppThread, OrchestrationV2ConversationMessage, OrchestrationV2DomainEvent, OrchestrationV2ProjectedTurnItem, OrchestrationV2ProviderTurn, OrchestrationV2Run, OrchestrationV2Subagent, OrchestrationV2ThreadShellSnapshot, OrchestrationV2ShellThreadStatus, OrchestrationV2ThreadShell, OrchestrationV2ThreadProjection, OrchestrationV2TurnItem, ProviderSessionId, ProviderThreadId, ProviderTurnId, RunAttemptId, RuntimeRequestId, MessageId,} from "@t3tools/contracts";import { OrchestrationV2AppThreadJson as OrchestrationV2AppThreadJsonSchema, OrchestrationV2CheckpointJson as OrchestrationV2CheckpointJsonSchema, OrchestrationV2CheckpointScopeJson as OrchestrationV2CheckpointScopeJsonSchema, OrchestrationV2ContextHandoffJson as OrchestrationV2ContextHandoffJsonSchema, OrchestrationV2ContextTransferJson as OrchestrationV2ContextTransferJsonSchema, OrchestrationV2ConversationMessageJson as OrchestrationV2ConversationMessageJsonSchema, OrchestrationV2ExecutionNodeJson as OrchestrationV2ExecutionNodeJsonSchema, OrchestrationV2PlanArtifact as OrchestrationV2PlanArtifactSchema, OrchestrationV2ProviderSessionJson as OrchestrationV2ProviderSessionJsonSchema, OrchestrationV2ProviderThreadJson as OrchestrationV2ProviderThreadJsonSchema, OrchestrationV2ProviderTurnJson as OrchestrationV2ProviderTurnJsonSchema, OrchestrationV2RunAttemptJson as OrchestrationV2RunAttemptJsonSchema, OrchestrationV2RunJson as OrchestrationV2RunJsonSchema, OrchestrationV2RuntimeRequestJson as OrchestrationV2RuntimeRequestJsonSchema, OrchestrationV2SubagentJson as OrchestrationV2SubagentJsonSchema, OrchestrationV2TurnItemJson as OrchestrationV2TurnItemJsonSchema, RunId, ThreadId, TurnItemId,} from "@t3tools/contracts";import { isOrchestrationV2SupersededInterrupt, isOrchestrationV2TurnItemVisible,} from "@t3tools/shared/orchestrationV2Timeline";import { derivePendingBackgroundWork } from "@t3tools/shared/orchestrationV2PendingBackgroundWork";import * as Context from "effect/Context";import * as DateTime from "effect/DateTime";import * as Effect from "effect/Effect";import * as Layer from "effect/Layer";import * as Ref from "effect/Ref";import * as Schema from "effect/Schema";import * as SqlClient from "effect/unstable/sql/SqlClient"; export class ProjectionStoreApplyEventError extends Schema.TaggedErrorClass<ProjectionStoreApplyEventError>()( "ProjectionStoreApplyEventError", { eventType: Schema.String, cause: Schema.optional(Schema.Defect()), },) { override get message(): string { return `Failed to apply orchestration projection event ${this.eventType}.`; }} export class ProjectionStoreSetupError extends Schema.TaggedErrorClass<ProjectionStoreSetupError>()( "ProjectionStoreSetupError", { cause: Schema.optional(Schema.Defect()), },) { override get message(): string { return "Failed to initialize orchestration projection store."; }} export class ProjectionStoreThreadNotFoundError extends Schema.TaggedErrorClass<ProjectionStoreThreadNotFoundError>()( "ProjectionStoreThreadNotFoundError", { threadId: ThreadId, },) { override get message(): string { return `No orchestration projection exists for thread ${this.threadId}.`; }} export class ProjectionStoreReadError extends Schema.TaggedErrorClass<ProjectionStoreReadError>()( "ProjectionStoreReadError", { threadId: ThreadId, cause: Schema.optional(Schema.Defect()), },) { override get message(): string { return `Failed to read orchestration projection for thread ${this.threadId}.`; }} export const ProjectionStoreV2Error = Schema.Union([ ProjectionStoreSetupError, ProjectionStoreApplyEventError, ProjectionStoreThreadNotFoundError, ProjectionStoreReadError,]);export type ProjectionStoreV2Error = typeof ProjectionStoreV2Error.Type; export type ProjectionRecoveryKind = | "queued-runs" | "runtime" | "subagent-results" | "delegated-completions"; /** Thread activity needed by settlement, without transcript or fork history. */export type ProjectionSettlementCandidate = Pick< OrchestrationV2ThreadShell, | "id" | "projectId" | "branch" | "worktreePath" | "linkedPullRequest" | "createdAt" | "updatedAt" | "archivedAt" | "settledOverride" | "pinnedAt" | "snoozedUntil" | "snoozedAt" | "latestRunId" | "latestRunRequestedAt" | "latestRunStartedAt" | "latestRunCompletedAt" | "latestUserMessageAt" | "status" | "activityRunStatus" | "pendingRuntimeRequest" | "pendingBackgroundTasks">; const ProjectionCheckpointContext = Schema.Struct({ runs: Schema.Array( OrchestrationV2RunJsonSchema.mapFields(({ id, ordinal, status }) => ({ id, ordinal, status })), ), checkpointScopes: Schema.Array( OrchestrationV2CheckpointScopeJsonSchema.mapFields(({ id, runId, kind, cwd }) => ({ id, runId, kind, cwd, })), ), checkpoints: Schema.Array( OrchestrationV2CheckpointJsonSchema.mapFields( ({ scopeId, runId, appRunOrdinal, status, ref }) => ({ scopeId, runId, appRunOrdinal, status, ref, }), ), ),});export type ProjectionCheckpointContext = typeof ProjectionCheckpointContext.Type;const decodeCheckpointContext = Schema.decodeUnknownEffect(ProjectionCheckpointContext); /** Exact durable targets used by interrupt, restart, and steering effects. */export interface ProjectionProviderControlContext { readonly providerThread: OrchestrationV2ThreadProjection["providerThreads"][number] | undefined; readonly providerTurn: OrchestrationV2ProviderTurn | undefined; readonly attempt: OrchestrationV2ThreadProjection["attempts"][number] | undefined; readonly message: OrchestrationV2ConversationMessage | undefined; readonly run: OrchestrationV2Run | undefined;} export interface ProjectionProviderControlTarget { readonly providerThreadId: ProviderThreadId; readonly providerTurnId: ProviderTurnId; readonly attemptId?: RunAttemptId; readonly messageId?: MessageId;} export type ProjectionPendingUserInputs = Pick< OrchestrationV2ThreadProjection, "runtimeRequests" | "nodes" | "turnItems">; export interface ProjectionStoreV2Shape { readonly apply: ( event: OrchestrationV2DomainEvent, ) => Effect.Effect<void, ProjectionStoreV2Error>; readonly getShellSnapshot: (options?: { readonly location?: "active" | "archive"; }) => Effect.Effect<OrchestrationV2ThreadShellSnapshot, ProjectionStoreV2Error>; readonly getThreadShell: ( threadId: ThreadId, ) => Effect.Effect<OrchestrationV2ThreadShell | null, ProjectionStoreV2Error>; readonly getThread: ( threadId: ThreadId, ) => Effect.Effect<OrchestrationV2AppThread, ProjectionStoreV2Error>; readonly getSettlementCandidates: () => Effect.Effect< ReadonlyArray<ProjectionSettlementCandidate>, ProjectionStoreV2Error >; readonly getThreadProjection: ( threadId: ThreadId, ) => Effect.Effect<OrchestrationV2ThreadProjection, ProjectionStoreV2Error>; readonly getPendingNativeUserInputs: ( threadId: ThreadId, providerTurnId: ProviderTurnId, ) => Effect.Effect<ProjectionPendingUserInputs, ProjectionStoreV2Error>; readonly getRuntimeRequest: ( threadId: ThreadId, requestId: RuntimeRequestId, ) => Effect.Effect< OrchestrationV2ThreadProjection["runtimeRequests"][number] | undefined, ProjectionStoreV2Error >; readonly getProviderControlContext: ( threadId: ThreadId, target: ProjectionProviderControlTarget, ) => Effect.Effect<ProjectionProviderControlContext, ProjectionStoreV2Error>; readonly getCheckpointContext: ( threadId: ThreadId, ) => Effect.Effect<ProjectionCheckpointContext, ProjectionStoreV2Error>; readonly getRecoveryThreadIds: ( kind: ProjectionRecoveryKind, ) => Effect.Effect<ReadonlyArray<ThreadId>, ProjectionStoreV2Error>; readonly getUnreadableThreadIds: () => Effect.Effect< ReadonlyArray<ThreadId>, ProjectionStoreV2Error >; readonly getThreadSnapshot: (threadId: ThreadId) => Effect.Effect< { readonly schemaVersion: number; readonly snapshotSequence: number; readonly projection: OrchestrationV2ThreadProjection; }, ProjectionStoreV2Error >; readonly getThreadSnapshotWindow: ( threadId: ThreadId, options: { readonly rowLimit: number; readonly anchorItemId?: TurnItemId | undefined; readonly anchorThreadId?: ThreadId | undefined; readonly requiredRunId?: RunId | undefined; }, ) => Effect.Effect< { readonly schemaVersion: number; readonly snapshotSequence: number; readonly projection: OrchestrationV2ThreadProjection; }, ProjectionStoreV2Error >;} export class ProjectionStoreV2 extends Context.Service<ProjectionStoreV2, ProjectionStoreV2Shape>()( "t3/orchestration-v2/ProjectionStore/ProjectionStoreV2",) {} export const ORCHESTRATION_V2_PROJECTION_SCHEMA_VERSION = 2; function needsRecovery( projection: OrchestrationV2ThreadProjection, kind: ProjectionRecoveryKind,): boolean { if (projection.thread.deletedAt !== null) return false; switch (kind) { case "queued-runs": return ( projection.thread.archivedAt === null && projection.runs.some((run) => run.status === "queued") && !projection.runs.some((run) => ["preparing", "starting", "running", "waiting"].includes(run.status), ) ); case "delegated-completions": return projection.runs.some((run) => run.delegatedCompletion?.delivery != null); case "subagent-results": { const parentThreadId = projection.thread.lineage.parentThreadId; return ( projection.thread.lineage.relationshipToParent === "subagent" && parentThreadId !== null && projection.thread.forkedFrom?.type === "node" && ["completed", "interrupted", "failed", "cancelled", "rolled_back"].includes( projection.runs.at(-1)?.status ?? "idle", ) && !projection.contextTransfers.some( (transfer) => transfer.type === "subagent_result" && transfer.sourceThreadId === projection.thread.id && transfer.targetThreadId === parentThreadId, ) ); } case "runtime": return ( projection.runs.some((run) => ["queued", "preparing", "starting", "running", "waiting"].includes(run.status), ) || projection.runtimeRequests.some((request) => request.status === "pending") || projection.providerSessions.some( (session) => session.status !== "stopped" && session.status !== "error", ) || projection.providerThreads.some( (thread) => thread.status === "active" || (thread.pendingBackgroundTasks?.length ?? 0) > 0, ) || projection.turnItems.some( (item) => ["command_execution", "dynamic_tool", "subagent"].includes(item.type) && ["pending", "running", "waiting"].includes(item.status), ) ); }} function upsertById<T extends { readonly id: string }>(items: ReadonlyArray<T>, next: T): Array<T> { const index = items.findIndex((item) => item.id === next.id); if (index === -1) { return [...items, next]; } const updated = [...items]; updated[index] = next; return updated;} export function upsertProviderTurn( turns: ReadonlyArray<OrchestrationV2ProviderTurn>, next: OrchestrationV2ProviderTurn,): Array<OrchestrationV2ProviderTurn> { const current = turns.find((turn) => turn.id === next.id); return upsertById(turns, { ...next, ...((next.tokenUsage ?? current?.tokenUsage) === undefined ? {} : { tokenUsage: next.tokenUsage ?? current?.tokenUsage }), });} function preserveDelegatedCompletion( current: OrchestrationV2Run | undefined, next: OrchestrationV2Run,): OrchestrationV2Run { if (next.delegatedCompletion !== undefined || current?.delegatedCompletion === undefined) { return next; } return { ...next, delegatedCompletion: current.delegatedCompletion };} function preserveCompletionDelivery( current: OrchestrationV2Subagent | undefined, next: OrchestrationV2Subagent,): OrchestrationV2Subagent { if (next.completionDelivery !== undefined || current?.completionDelivery === undefined) { return next; } return { ...next, completionDelivery: current.completionDelivery };} export function emptyProjection( event: Extract<OrchestrationV2DomainEvent, { readonly type: "thread.created" }>,): OrchestrationV2ThreadProjection { return { thread: event.payload, runs: [], attempts: [], nodes: [], subagents: [], providerSessions: [], providerThreads: [], providerTurns: [], runtimeRequests: [], messages: [], plans: [], turnItems: [], checkpointScopes: [], checkpoints: [], contextHandoffs: [], contextTransfers: [], visibleTurnItems: [], updatedAt: event.occurredAt, };} export function applyToProjection( projection: OrchestrationV2ThreadProjection, event: OrchestrationV2DomainEvent,): OrchestrationV2ThreadProjection { const base = { ...projection, thread: { ...projection.thread, updatedAt: event.occurredAt, }, updatedAt: event.occurredAt, }; switch (event.type) { case "thread.created": case "thread.archived": case "thread.unarchived": case "thread.deleted": case "thread.settled": case "thread.unsettled": case "thread.snoozed": case "thread.unsnoozed": case "thread.pinned": case "thread.unpinned": case "thread.pin-reordered": case "thread.metadata-updated": case "thread.runtime-mode-updated": case "thread.interaction-mode-updated": case "thread.model-selection-updated": case "thread.provider-switched": return { ...base, thread: event.payload, }; // Visited tracking is read state, not activity: skip the updatedAt bump so // viewing a thread does not surface it as recently active. case "thread.visited": case "thread.marked-unread": return { ...projection, thread: event.payload, }; case "run.created": case "run.updated": return withLocalVisibleTurnItems({ ...base, runs: upsertById( base.runs, preserveDelegatedCompletion( base.runs.find((run) => run.id === event.payload.id), event.payload, ), ), }); case "run-attempt.created": case "run-attempt.updated": return withLocalVisibleTurnItems({ ...base, attempts: upsertById(base.attempts, event.payload), }); case "node.updated": return { ...base, nodes: upsertById(base.nodes, event.payload), }; case "subagent.updated": return { ...base, subagents: upsertById( base.subagents, preserveCompletionDelivery( base.subagents.find((task) => task.id === event.payload.id), event.payload, ), ), }; case "provider-session.attached": case "provider-session.updated": return { ...base, providerSessions: upsertById(base.providerSessions, event.payload), }; case "provider-session.detached": return { ...base, providerSessions: base.providerSessions.filter( (session) => session.id !== event.payload.providerSessionId, ), }; case "provider-thread.updated": return { ...base, thread: event.payload.appThreadId === base.thread.id ? { ...base.thread, activeProviderThreadId: event.payload.id, } : base.thread, providerThreads: upsertById(base.providerThreads, event.payload), }; case "provider-turn.updated": return { ...base, providerTurns: upsertProviderTurn(base.providerTurns, event.payload), }; case "runtime-request.updated": return { ...base, runtimeRequests: upsertById(base.runtimeRequests, event.payload), };Lines 1–500 of 4165. Load more
import type { OrchestrationV2AppThread, OrchestrationV2ConversationMessage, OrchestrationV2DomainEvent, OrchestrationV2ProjectedTurnItem, OrchestrationV2ProviderTurn, OrchestrationV2Run, OrchestrationV2Subagent, OrchestrationV2ThreadShellSnapshot, OrchestrationV2ShellThreadStatus, OrchestrationV2ThreadShell, OrchestrationV2ThreadProjection, OrchestrationV2TurnItem, ProviderSessionId, ProviderThreadId, ProviderTurnId, RunAttemptId, RuntimeRequestId, MessageId, } from "@t3tools/contracts"; import { OrchestrationV2AppThreadJson as OrchestrationV2AppThreadJsonSchema, OrchestrationV2CheckpointJson as OrchestrationV2CheckpointJsonSchema, OrchestrationV2CheckpointScopeJson as OrchestrationV2CheckpointScopeJsonSchema, OrchestrationV2ContextHandoffJson as OrchestrationV2ContextHandoffJsonSchema, OrchestrationV2ContextTransferJson as OrchestrationV2ContextTransferJsonSchema, OrchestrationV2ConversationMessageJson as OrchestrationV2ConversationMessageJsonSchema, OrchestrationV2ExecutionNodeJson as OrchestrationV2ExecutionNodeJsonSchema, OrchestrationV2PlanArtifact as OrchestrationV2PlanArtifactSchema, OrchestrationV2ProviderSessionJson as OrchestrationV2ProviderSessionJsonSchema, OrchestrationV2ProviderThreadJson as OrchestrationV2ProviderThreadJsonSchema, OrchestrationV2ProviderTurnJson as OrchestrationV2ProviderTurnJsonSchema, OrchestrationV2RunAttemptJson as OrchestrationV2RunAttemptJsonSchema, OrchestrationV2RunJson as OrchestrationV2RunJsonSchema, OrchestrationV2RuntimeRequestJson as OrchestrationV2RuntimeRequestJsonSchema, OrchestrationV2SubagentJson as OrchestrationV2SubagentJsonSchema, OrchestrationV2TurnItemJson as OrchestrationV2TurnItemJsonSchema, RunId, ThreadId, TurnItemId, } from "@t3tools/contracts"; import { isOrchestrationV2SupersededInterrupt, isOrchestrationV2TurnItemVisible, } from "@t3tools/shared/orchestrationV2Timeline"; import { derivePendingBackgroundWork } from "@t3tools/shared/orchestrationV2PendingBackgroundWork"; import * as Context from "effect/Context"; import * as DateTime from "effect/DateTime"; import * as Effect from "effect/Effect"; import * as Layer from "effect/Layer"; import * as Ref from "effect/Ref"; import * as Schema from "effect/Schema"; import * as SqlClient from "effect/unstable/sql/SqlClient"; export class ProjectionStoreApplyEventError extends Schema.TaggedErrorClass<ProjectionStoreApplyEventError>()( "ProjectionStoreApplyEventError", { eventType: Schema.String, cause: Schema.optional(Schema.Defect()), }, ) { override get message(): string { return `Failed to apply orchestration projection event ${this.eventType}.`; } } export class ProjectionStoreSetupError extends Schema.TaggedErrorClass<ProjectionStoreSetupError>()( "ProjectionStoreSetupError", { cause: Schema.optional(Schema.Defect()), }, ) { override get message(): string { return "Failed to initialize orchestration projection store."; } } export class ProjectionStoreThreadNotFoundError extends Schema.TaggedErrorClass<ProjectionStoreThreadNotFoundError>()( "ProjectionStoreThreadNotFoundError", { threadId: ThreadId, }, ) { override get message(): string { return `No orchestration projection exists for thread ${this.threadId}.`; } } export class ProjectionStoreReadError extends Schema.TaggedErrorClass<ProjectionStoreReadError>()( "ProjectionStoreReadError", { threadId: ThreadId, cause: Schema.optional(Schema.Defect()), }, ) { override get message(): string { return `Failed to read orchestration projection for thread ${this.threadId}.`; } } export const ProjectionStoreV2Error = Schema.Union([ ProjectionStoreSetupError, ProjectionStoreApplyEventError, ProjectionStoreThreadNotFoundError, ProjectionStoreReadError, ]); export type ProjectionStoreV2Error = typeof ProjectionStoreV2Error.Type; export type ProjectionRecoveryKind = | "queued-runs" | "runtime" | "subagent-results" | "delegated-completions"; /** Thread activity needed by settlement, without transcript or fork history. */ export type ProjectionSettlementCandidate = Pick< OrchestrationV2ThreadShell, | "id" | "projectId" | "branch" | "worktreePath" | "linkedPullRequest" | "createdAt" | "updatedAt" | "archivedAt" | "settledOverride" | "pinnedAt" | "snoozedUntil" | "snoozedAt" | "latestRunId" | "latestRunRequestedAt" | "latestRunStartedAt" | "latestRunCompletedAt" | "latestUserMessageAt" | "status" | "activityRunStatus" | "pendingRuntimeRequest" | "pendingBackgroundTasks" >; const ProjectionCheckpointContext = Schema.Struct({ runs: Schema.Array( OrchestrationV2RunJsonSchema.mapFields(({ id, ordinal, status }) => ({ id, ordinal, status })), ), checkpointScopes: Schema.Array( OrchestrationV2CheckpointScopeJsonSchema.mapFields(({ id, runId, kind, cwd }) => ({ id, runId, kind, cwd, })), ), checkpoints: Schema.Array( OrchestrationV2CheckpointJsonSchema.mapFields( ({ scopeId, runId, appRunOrdinal, status, ref }) => ({ scopeId, runId, appRunOrdinal, status, ref, }), ), ), }); export type ProjectionCheckpointContext = typeof ProjectionCheckpointContext.Type; const decodeCheckpointContext = Schema.decodeUnknownEffect(ProjectionCheckpointContext); /** Exact durable targets used by interrupt, restart, and steering effects. */ export interface ProjectionProviderControlContext { readonly providerThread: OrchestrationV2ThreadProjection["providerThreads"][number] | undefined; readonly providerTurn: OrchestrationV2ProviderTurn | undefined; readonly attempt: OrchestrationV2ThreadProjection["attempts"][number] | undefined; readonly message: OrchestrationV2ConversationMessage | undefined; readonly run: OrchestrationV2Run | undefined; } export interface ProjectionProviderControlTarget { readonly providerThreadId: ProviderThreadId; readonly providerTurnId: ProviderTurnId; readonly attemptId?: RunAttemptId; readonly messageId?: MessageId; } export type ProjectionPendingUserInputs = Pick< OrchestrationV2ThreadProjection, "runtimeRequests" | "nodes" | "turnItems" >; export interface ProjectionStoreV2Shape { readonly apply: ( event: OrchestrationV2DomainEvent, ) => Effect.Effect<void, ProjectionStoreV2Error>; readonly getShellSnapshot: (options?: { readonly location?: "active" | "archive"; }) => Effect.Effect<OrchestrationV2ThreadShellSnapshot, ProjectionStoreV2Error>; readonly getThreadShell: ( threadId: ThreadId, ) => Effect.Effect<OrchestrationV2ThreadShell | null, ProjectionStoreV2Error>; readonly getThread: ( threadId: ThreadId, ) => Effect.Effect<OrchestrationV2AppThread, ProjectionStoreV2Error>; readonly getSettlementCandidates: () => Effect.Effect< ReadonlyArray<ProjectionSettlementCandidate>, ProjectionStoreV2Error >; readonly getThreadProjection: ( threadId: ThreadId, ) => Effect.Effect<OrchestrationV2ThreadProjection, ProjectionStoreV2Error>; readonly getPendingNativeUserInputs: ( threadId: ThreadId, providerTurnId: ProviderTurnId, ) => Effect.Effect<ProjectionPendingUserInputs, ProjectionStoreV2Error>; readonly getRuntimeRequest: ( threadId: ThreadId, requestId: RuntimeRequestId, ) => Effect.Effect< OrchestrationV2ThreadProjection["runtimeRequests"][number] | undefined, ProjectionStoreV2Error >; readonly getProviderControlContext: ( threadId: ThreadId, target: ProjectionProviderControlTarget, ) => Effect.Effect<ProjectionProviderControlContext, ProjectionStoreV2Error>; readonly getCheckpointContext: ( threadId: ThreadId, ) => Effect.Effect<ProjectionCheckpointContext, ProjectionStoreV2Error>; readonly getRecoveryThreadIds: ( kind: ProjectionRecoveryKind, ) => Effect.Effect<ReadonlyArray<ThreadId>, ProjectionStoreV2Error>; readonly getUnreadableThreadIds: () => Effect.Effect< ReadonlyArray<ThreadId>, ProjectionStoreV2Error >; readonly getThreadSnapshot: (threadId: ThreadId) => Effect.Effect< { readonly schemaVersion: number; readonly snapshotSequence: number; readonly projection: OrchestrationV2ThreadProjection; }, ProjectionStoreV2Error >; readonly getThreadSnapshotWindow: ( threadId: ThreadId, options: { readonly rowLimit: number; readonly anchorItemId?: TurnItemId | undefined; readonly anchorThreadId?: ThreadId | undefined; readonly requiredRunId?: RunId | undefined; }, ) => Effect.Effect< { readonly schemaVersion: number; readonly snapshotSequence: number; readonly projection: OrchestrationV2ThreadProjection; }, ProjectionStoreV2Error >; } export class ProjectionStoreV2 extends Context.Service<ProjectionStoreV2, ProjectionStoreV2Shape>()( "t3/orchestration-v2/ProjectionStore/ProjectionStoreV2", ) {} export const ORCHESTRATION_V2_PROJECTION_SCHEMA_VERSION = 2; function needsRecovery( projection: OrchestrationV2ThreadProjection, kind: ProjectionRecoveryKind, ): boolean { if (projection.thread.deletedAt !== null) return false; switch (kind) { case "queued-runs": return ( projection.thread.archivedAt === null && projection.runs.some((run) => run.status === "queued") && !projection.runs.some((run) => ["preparing", "starting", "running", "waiting"].includes(run.status), ) ); case "delegated-completions": return projection.runs.some((run) => run.delegatedCompletion?.delivery != null); case "subagent-results": { const parentThreadId = projection.thread.lineage.parentThreadId; return ( projection.thread.lineage.relationshipToParent === "subagent" && parentThreadId !== null && projection.thread.forkedFrom?.type === "node" && ["completed", "interrupted", "failed", "cancelled", "rolled_back"].includes( projection.runs.at(-1)?.status ?? "idle", ) && !projection.contextTransfers.some( (transfer) => transfer.type === "subagent_result" && transfer.sourceThreadId === projection.thread.id && transfer.targetThreadId === parentThreadId, ) ); } case "runtime": return ( projection.runs.some((run) => ["queued", "preparing", "starting", "running", "waiting"].includes(run.status), ) || projection.runtimeRequests.some((request) => request.status === "pending") || projection.providerSessions.some( (session) => session.status !== "stopped" && session.status !== "error", ) || projection.providerThreads.some( (thread) => thread.status === "active" || (thread.pendingBackgroundTasks?.length ?? 0) > 0, ) || projection.turnItems.some( (item) => ["command_execution", "dynamic_tool", "subagent"].includes(item.type) && ["pending", "running", "waiting"].includes(item.status), ) ); } } function upsertById<T extends { readonly id: string }>(items: ReadonlyArray<T>, next: T): Array<T> { const index = items.findIndex((item) => item.id === next.id); if (index === -1) { return [...items, next]; } const updated = [...items]; updated[index] = next; return updated; } export function upsertProviderTurn( turns: ReadonlyArray<OrchestrationV2ProviderTurn>, next: OrchestrationV2ProviderTurn, ): Array<OrchestrationV2ProviderTurn> { const current = turns.find((turn) => turn.id === next.id); return upsertById(turns, { ...next, ...((next.tokenUsage ?? current?.tokenUsage) === undefined ? {} : { tokenUsage: next.tokenUsage ?? current?.tokenUsage }), }); } function preserveDelegatedCompletion( current: OrchestrationV2Run | undefined, next: OrchestrationV2Run, ): OrchestrationV2Run { if (next.delegatedCompletion !== undefined || current?.delegatedCompletion === undefined) { return next; } return { ...next, delegatedCompletion: current.delegatedCompletion }; } function preserveCompletionDelivery( current: OrchestrationV2Subagent | undefined, next: OrchestrationV2Subagent, ): OrchestrationV2Subagent { if (next.completionDelivery !== undefined || current?.completionDelivery === undefined) { return next; } return { ...next, completionDelivery: current.completionDelivery }; } export function emptyProjection( event: Extract<OrchestrationV2DomainEvent, { readonly type: "thread.created" }>, ): OrchestrationV2ThreadProjection { return { thread: event.payload, runs: [], attempts: [], nodes: [], subagents: [], providerSessions: [], providerThreads: [], providerTurns: [], runtimeRequests: [], messages: [], plans: [], turnItems: [], checkpointScopes: [], checkpoints: [], contextHandoffs: [], contextTransfers: [], visibleTurnItems: [], updatedAt: event.occurredAt, }; } export function applyToProjection( projection: OrchestrationV2ThreadProjection, event: OrchestrationV2DomainEvent, ): OrchestrationV2ThreadProjection { const base = { ...projection, thread: { ...projection.thread, updatedAt: event.occurredAt, }, updatedAt: event.occurredAt, }; switch (event.type) { case "thread.created": case "thread.archived": case "thread.unarchived": case "thread.deleted": case "thread.settled": case "thread.unsettled": case "thread.snoozed": case "thread.unsnoozed": case "thread.pinned": case "thread.unpinned": case "thread.pin-reordered": case "thread.metadata-updated": case "thread.runtime-mode-updated": case "thread.interaction-mode-updated": case "thread.model-selection-updated": case "thread.provider-switched": return { ...base, thread: event.payload, }; // Visited tracking is read state, not activity: skip the updatedAt bump so // viewing a thread does not surface it as recently active. case "thread.visited": case "thread.marked-unread": return { ...projection, thread: event.payload, }; case "run.created": case "run.updated": return withLocalVisibleTurnItems({ ...base, runs: upsertById( base.runs, preserveDelegatedCompletion( base.runs.find((run) => run.id === event.payload.id), event.payload, ), ), }); case "run-attempt.created": case "run-attempt.updated": return withLocalVisibleTurnItems({ ...base, attempts: upsertById(base.attempts, event.payload), }); case "node.updated": return { ...base, nodes: upsertById(base.nodes, event.payload), }; case "subagent.updated": return { ...base, subagents: upsertById( base.subagents, preserveCompletionDelivery( base.subagents.find((task) => task.id === event.payload.id), event.payload, ), ), }; case "provider-session.attached": case "provider-session.updated": return { ...base, providerSessions: upsertById(base.providerSessions, event.payload), }; case "provider-session.detached": return { ...base, providerSessions: base.providerSessions.filter( (session) => session.id !== event.payload.providerSessionId, ), }; case "provider-thread.updated": return { ...base, thread: event.payload.appThreadId === base.thread.id ? { ...base.thread, activeProviderThreadId: event.payload.id, } : base.thread, providerThreads: upsertById(base.providerThreads, event.payload), }; case "provider-turn.updated": return { ...base, providerTurns: upsertProviderTurn(base.providerTurns, event.payload), }; case "runtime-request.updated": return { ...base, runtimeRequests: upsertById(base.runtimeRequests, event.payload), };