@@ -23,16 +23,19 @@ import {
2323 type OrchestrationV2Run ,
2424 type OrchestrationV2ThreadShellSnapshot ,
2525 type OrchestrationV2ThreadProjection ,
26+ type OrchestrationV2ThreadTranscript ,
2627 type OrchestrationV2ThreadShell ,
2728 type OrchestrationV2TurnItem ,
2829 ProjectId ,
30+ PROVIDER_SEND_TURN_MAX_FILE_BYTES ,
2931 ProviderInstanceId ,
3032 resolveProjectProviderInstanceEnabled ,
3133 RunId ,
3234 type ScheduledTaskId ,
3335 ThreadId ,
3436 type TurnItemId ,
3537} from "@t3tools/contracts" ;
38+ import { threadTranscriptHeader } from "@t3tools/shared/threadTranscript" ;
3639import * as Context from "effect/Context" ;
3740import * as DateTime from "effect/DateTime" ;
3841import * as Duration from "effect/Duration" ;
@@ -45,6 +48,8 @@ import * as Stream from "effect/Stream";
4548
4649import * as CommandReceiptStore from "./CommandReceiptStore.ts" ;
4750import * as Orchestrator from "./Orchestrator.ts" ;
51+ import * as ServerEnvironment from "../environment/ServerEnvironment.ts" ;
52+ import { projectedRowEncodedBytes } from "./threadHistoryPaging.ts" ;
4853import * as ProviderSessionManager from "./ProviderSessionManager.ts" ;
4954import * as ThreadCommandExecutor from "./ThreadCommandExecutor.ts" ;
5055import { DispatchModeLimit , exceededDispatchModeLimit } from "./DispatchModeLimit.ts" ;
@@ -186,6 +191,15 @@ export class ThreadManagementThreadNotFoundError extends Schema.TaggedError<Thre
186191 }
187192}
188193
194+ export class ThreadTranscriptTooLargeError extends Schema . TaggedError < ThreadTranscriptTooLargeError > ( ) (
195+ "ThreadTranscriptTooLargeError" ,
196+ { threadId : ThreadId } ,
197+ ) {
198+ override get message ( ) : string {
199+ return "The thread transcript exceeds the file attachment limit." ;
200+ }
201+ }
202+
189203export class ThreadManagementRunNotFoundError extends Schema . TaggedError < ThreadManagementRunNotFoundError > ( ) (
190204 "ThreadManagementRunNotFoundError" ,
191205 {
@@ -336,6 +350,13 @@ export interface ThreadManagementServiceShape {
336350 ) => Effect . Effect < OrchestrationV2ThreadProjection , Orchestrator . OrchestratorV2Error > ;
337351 readonly getCheckpointContext : Orchestrator . OrchestratorV2 [ "Service" ] [ "getCheckpointContext" ] ;
338352 readonly getThreadSnapshot : Orchestrator . OrchestratorV2 [ "Service" ] [ "getThreadSnapshot" ] ;
353+ readonly getThreadTranscript : (
354+ threadId : ThreadId ,
355+ ) => Effect . Effect <
356+ OrchestrationV2ThreadTranscript ,
357+ Orchestrator . OrchestratorV2Error | ThreadTranscriptTooLargeError ,
358+ ServerEnvironment . ServerEnvironmentIdentity
359+ > ;
339360 readonly getThreadSnapshotWindow : Orchestrator . OrchestratorV2 [ "Service" ] [ "getThreadSnapshotWindow" ] ;
340361 readonly getProjectThreadRecords : < K extends ProjectionRecordField > (
341362 input : { readonly projectId : ProjectId ; readonly threadId : ThreadId } ,
@@ -627,6 +648,32 @@ const make = Effect.gen(function* () {
627648 ensureProjectionTranscript ( threadId ) . pipe (
628649 Effect . andThen ( orchestrator . getThreadSnapshot ( threadId ) ) ,
629650 ) ;
651+ const getThreadTranscript = Effect . fn ( "orchestrationV2.threadManagement.getThreadTranscript" ) (
652+ function * ( threadId : ThreadId ) {
653+ const { projection } = yield * getThreadSnapshot ( threadId ) ;
654+ const environment = yield * ServerEnvironment . ServerEnvironmentIdentity ;
655+ const transcript = {
656+ threadId : projection . thread . id ,
657+ title : projection . thread . title ,
658+ updatedAt : projection . updatedAt ,
659+ items : projection . visibleTurnItems ,
660+ } ;
661+ let sizeBytes = Buffer . byteLength (
662+ threadTranscriptHeader ( yield * environment . getEnvironmentId , transcript ) ,
663+ "utf8" ,
664+ ) ;
665+ if ( sizeBytes > PROVIDER_SEND_TURN_MAX_FILE_BYTES ) {
666+ return yield * new ThreadTranscriptTooLargeError ( { threadId } ) ;
667+ }
668+ for ( const row of transcript . items ) {
669+ sizeBytes += projectedRowEncodedBytes ( row ) + 1 ;
670+ if ( sizeBytes > PROVIDER_SEND_TURN_MAX_FILE_BYTES ) {
671+ return yield * new ThreadTranscriptTooLargeError ( { threadId } ) ;
672+ }
673+ }
674+ return transcript ;
675+ } ,
676+ ) ;
630677 const getThreadSnapshotWindow : ThreadManagementServiceShape [ "getThreadSnapshotWindow" ] = (
631678 threadId ,
632679 options ,
@@ -1161,6 +1208,7 @@ const make = Effect.gen(function* () {
11611208 getThreadProjection,
11621209 getCheckpointContext,
11631210 getThreadSnapshot,
1211+ getThreadTranscript,
11641212 getThreadSnapshotWindow,
11651213 getProjectThreadRecords,
11661214 getProjectThread,
0 commit comments