| ... | @@ -28,8 +28,6 @@ const TURN_MESSAGE_IDS_BY_TURN_CACHE_CAPACITY = 10_000; | ... | @@ -28,8 +28,6 @@ const TURN_MESSAGE_IDS_BY_TURN_CACHE_CAPACITY = 10_000; |
| 28 | const TURN_MESSAGE_IDS_BY_TURN_TTL = Duration.minutes(120); | 28 | const TURN_MESSAGE_IDS_BY_TURN_TTL = Duration.minutes(120); |
| 29 | const BUFFERED_MESSAGE_TEXT_BY_MESSAGE_ID_CACHE_CAPACITY = 20_000; | 29 | const BUFFERED_MESSAGE_TEXT_BY_MESSAGE_ID_CACHE_CAPACITY = 20_000; |
| 30 | const BUFFERED_MESSAGE_TEXT_BY_MESSAGE_ID_TTL = Duration.minutes(120); | 30 | const BUFFERED_MESSAGE_TEXT_BY_MESSAGE_ID_TTL = Duration.minutes(120); |
| 31 | const BUFFERED_ASSISTANT_MESSAGE_SPILLED_CACHE_CAPACITY = 20_000; | | |
| 32 | const BUFFERED_ASSISTANT_MESSAGE_SPILLED_TTL = Duration.minutes(120); | | |
| 33 | const MAX_BUFFERED_ASSISTANT_CHARS = 24_000; | 31 | const MAX_BUFFERED_ASSISTANT_CHARS = 24_000; |
| 34 | | 32 | |
| 35 | type TurnStartRequestedDomainEvent = Extract< | 33 | type TurnStartRequestedDomainEvent = Extract< |
| ... | @@ -172,11 +170,6 @@ const make = Effect.gen(function* () { | ... | @@ -172,11 +170,6 @@ const make = Effect.gen(function* () { |
| 172 | timeToLive: BUFFERED_MESSAGE_TEXT_BY_MESSAGE_ID_TTL, | 170 | timeToLive: BUFFERED_MESSAGE_TEXT_BY_MESSAGE_ID_TTL, |
| 173 | lookup: () => Effect.succeed(""), | 171 | lookup: () => Effect.succeed(""), |
| 174 | }); | 172 | }); |
| 175 | const bufferedAssistantMessageSpilledByMessageId = yield* Cache.make<MessageId, true>({ | | |
| 176 | capacity: BUFFERED_ASSISTANT_MESSAGE_SPILLED_CACHE_CAPACITY, | | |
| 177 | timeToLive: BUFFERED_ASSISTANT_MESSAGE_SPILLED_TTL, | | |
| 178 | lookup: () => Effect.succeed(true), | | |
| 179 | }); | | |
| 180 | | 173 | |
| 181 | const rememberAssistantMessageId = ( | 174 | const rememberAssistantMessageId = ( |
| 182 | sessionId: ProviderSessionId, | 175 | sessionId: ProviderSessionId, |
| ... | @@ -263,26 +256,7 @@ const make = Effect.gen(function* () { | ... | @@ -263,26 +256,7 @@ const make = Effect.gen(function* () { |
| 263 | const clearBufferedAssistantText = (messageId: MessageId) => | 256 | const clearBufferedAssistantText = (messageId: MessageId) => |
| 264 | Cache.invalidate(bufferedAssistantTextByMessageId, messageId); | 257 | Cache.invalidate(bufferedAssistantTextByMessageId, messageId); |
| 265 | | 258 | |
| 266 | const markBufferedAssistantMessageSpilled = (messageId: MessageId) => | 259 | const clearAssistantMessageState = (messageId: MessageId) => clearBufferedAssistantText(messageId); |
| 267 | Cache.set(bufferedAssistantMessageSpilledByMessageId, messageId, true); | | |
| 268 | | | |
| 269 | const takeBufferedAssistantMessageSpilled = (messageId: MessageId) => | | |
| 270 | Cache.getOption(bufferedAssistantMessageSpilledByMessageId, messageId).pipe( | | |
| 271 | Effect.flatMap((spilled) => | | |
| 272 | Cache.invalidate(bufferedAssistantMessageSpilledByMessageId, messageId).pipe( | | |
| 273 | Effect.as(Option.isSome(spilled)), | | |
| 274 | ), | | |
| 275 | ), | | |
| 276 | ); | | |
| 277 | | | |
| 278 | const clearBufferedAssistantMessageSpilled = (messageId: MessageId) => | | |
| 279 | Cache.invalidate(bufferedAssistantMessageSpilledByMessageId, messageId); | | |
| 280 | | | |
| 281 | const clearAssistantMessageState = (messageId: MessageId) => | | |
| 282 | Effect.all( | | |
| 283 | [clearBufferedAssistantText(messageId), clearBufferedAssistantMessageSpilled(messageId)], | | |
| 284 | { concurrency: 1 }, | | |
| 285 | ).pipe(Effect.asVoid); | | |
| 286 | | 260 | |
| 287 | const finalizeAssistantMessage = (input: { | 261 | const finalizeAssistantMessage = (input: { |
| 288 | event: ProviderRuntimeEvent; | 262 | event: ProviderRuntimeEvent; |
| ... | @@ -291,16 +265,15 @@ const make = Effect.gen(function* () { | ... | @@ -291,16 +265,15 @@ const make = Effect.gen(function* () { |
| 291 | turnId?: TurnId; | 265 | turnId?: TurnId; |
| 292 | createdAt: string; | 266 | createdAt: string; |
| 293 | commandTag: string; | 267 | commandTag: string; |
| 294 | spillRemainderCommandTag: string; | 268 | finalDeltaCommandTag: string; |
| 295 | }) => | 269 | }) => |
| 296 | Effect.gen(function* () { | 270 | Effect.gen(function* () { |
| 297 | const text = yield* takeBufferedAssistantText(input.messageId); | 271 | const text = yield* takeBufferedAssistantText(input.messageId); |
| 298 | const spilled = yield* takeBufferedAssistantMessageSpilled(input.messageId); | | |
| 299 | | 272 | |
| 300 | if (spilled && text.length > 0) { | 273 | if (text.length > 0) { |
| 301 | yield* orchestrationEngine.dispatch({ | 274 | yield* orchestrationEngine.dispatch({ |
| 302 | type: "thread.message.assistant.delta", | 275 | type: "thread.message.assistant.delta", |
| 303 | commandId: providerCommandId(input.event, input.spillRemainderCommandTag), | 276 | commandId: providerCommandId(input.event, input.finalDeltaCommandTag), |
| 304 | threadId: input.threadId, | 277 | threadId: input.threadId, |
| 305 | messageId: input.messageId, | 278 | messageId: input.messageId, |
| 306 | delta: text, | 279 | delta: text, |
| ... | @@ -315,7 +288,7 @@ const make = Effect.gen(function* () { | ... | @@ -315,7 +288,7 @@ const make = Effect.gen(function* () { |
| 315 | threadId: input.threadId, | 288 | threadId: input.threadId, |
| 316 | messageId: input.messageId, | 289 | messageId: input.messageId, |
| 317 | ...(input.turnId ? { turnId: input.turnId } : {}), | 290 | ...(input.turnId ? { turnId: input.turnId } : {}), |
| 318 | text: spilled ? "" : text, | 291 | text: "", |
| 319 | createdAt: input.createdAt, | 292 | createdAt: input.createdAt, |
| 320 | }); | 293 | }); |
| 321 | yield* clearAssistantMessageState(input.messageId); | 294 | yield* clearAssistantMessageState(input.messageId); |
| ... | @@ -418,7 +391,6 @@ const make = Effect.gen(function* () { | ... | @@ -418,7 +391,6 @@ const make = Effect.gen(function* () { |
| 418 | if (assistantDeliveryMode === "buffered") { | 391 | if (assistantDeliveryMode === "buffered") { |
| 419 | const spillChunk = yield* appendBufferedAssistantText(assistantMessageId, event.delta); | 392 | const spillChunk = yield* appendBufferedAssistantText(assistantMessageId, event.delta); |
| 420 | if (spillChunk.length > 0) { | 393 | if (spillChunk.length > 0) { |
| 421 | yield* markBufferedAssistantMessageSpilled(assistantMessageId); | | |
| 422 | yield* orchestrationEngine.dispatch({ | 394 | yield* orchestrationEngine.dispatch({ |
| 423 | type: "thread.message.assistant.delta", | 395 | type: "thread.message.assistant.delta", |
| 424 | commandId: providerCommandId(event, "assistant-delta-buffer-spill"), | 396 | commandId: providerCommandId(event, "assistant-delta-buffer-spill"), |
| ... | @@ -456,7 +428,7 @@ const make = Effect.gen(function* () { | ... | @@ -456,7 +428,7 @@ const make = Effect.gen(function* () { |
| 456 | ...(turnId ? { turnId } : {}), | 428 | ...(turnId ? { turnId } : {}), |
| 457 | createdAt: now, | 429 | createdAt: now, |
| 458 | commandTag: "assistant-complete", | 430 | commandTag: "assistant-complete", |
| 459 | spillRemainderCommandTag: "assistant-delta-buffer-remainder", | 431 | finalDeltaCommandTag: "assistant-delta-finalize", |
| 460 | }); | 432 | }); |
| 461 | | 433 | |
| 462 | if (turnId) { | 434 | if (turnId) { |
| ... | @@ -479,7 +451,7 @@ const make = Effect.gen(function* () { | ... | @@ -479,7 +451,7 @@ const make = Effect.gen(function* () { |
| 479 | turnId, | 451 | turnId, |
| 480 | createdAt: now, | 452 | createdAt: now, |
| 481 | commandTag: "assistant-complete-finalize", | 453 | commandTag: "assistant-complete-finalize", |
| 482 | spillRemainderCommandTag: "assistant-delta-buffer-remainder-finalize", | 454 | finalDeltaCommandTag: "assistant-delta-finalize-fallback", |
| 483 | }); | 455 | }); |
| 484 | }), | 456 | }), |
| 485 | { concurrency: 1 }, | 457 | { concurrency: 1 }, |