| ... | @@ -419,7 +419,7 @@ const make = Effect.gen(function* () { | ... | @@ -419,7 +419,7 @@ const make = Effect.gen(function* () { |
| 419 | readonly detail: string; | 419 | readonly detail: string; |
| 420 | readonly createdAt: string; | 420 | readonly createdAt: string; |
| 421 | }) { | 421 | }) { |
| 422 | const thread = yield* resolveThread(input.threadId); | 422 | const thread = yield* resolveThreadShell(input.threadId); |
| 423 | if (!thread) { | 423 | if (!thread) { |
| 424 | return; | 424 | return; |
| 425 | } | 425 | } |
| ... | @@ -447,7 +447,7 @@ const make = Effect.gen(function* () { | ... | @@ -447,7 +447,7 @@ const make = Effect.gen(function* () { |
| 447 | compactingThreadIds.delete(threadId); | 447 | compactingThreadIds.delete(threadId); |
| 448 | return; | 448 | return; |
| 449 | } | 449 | } |
| 450 | const thread = yield* resolveThread(threadId); | 450 | const thread = yield* resolveThreadShell(threadId); |
| 451 | if (!thread?.session) return; | 451 | if (!thread?.session) return; |
| 452 | if ( | 452 | if ( |
| 453 | thread.session.status !== "starting" && | 453 | thread.session.status !== "starting" && |
| ... | @@ -525,7 +525,13 @@ const make = Effect.gen(function* () { | ... | @@ -525,7 +525,13 @@ const make = Effect.gen(function* () { |
| 525 | ); | 525 | ); |
| 526 | }); | 526 | }); |
| 527 | | 527 | |
| 528 | const resolveThread = Effect.fnUntraced(function* (threadId: ThreadId) { | 528 | const resolveThreadShell = Effect.fnUntraced(function* (threadId: ThreadId) { |
| | 529 | return yield* projectionSnapshotQuery |
| | 530 | .getThreadShellById(threadId) |
| | 531 | .pipe(Effect.map(Option.getOrUndefined)); |
| | 532 | }); |
| | 533 | |
| | 534 | const resolveThreadDetail = Effect.fnUntraced(function* (threadId: ThreadId) { |
| 529 | return yield* projectionSnapshotQuery | 535 | return yield* projectionSnapshotQuery |
| 530 | .getThreadDetailById(threadId, { activityKinds: [] }) | 536 | .getThreadDetailById(threadId, { activityKinds: [] }) |
| 531 | .pipe(Effect.map(Option.getOrUndefined)); | 537 | .pipe(Effect.map(Option.getOrUndefined)); |
| ... | @@ -571,7 +577,7 @@ const make = Effect.gen(function* () { | ... | @@ -571,7 +577,7 @@ const make = Effect.gen(function* () { |
| 571 | readonly pendingTurnStart?: boolean; | 577 | readonly pendingTurnStart?: boolean; |
| 572 | }, | 578 | }, |
| 573 | ) { | 579 | ) { |
| 574 | const thread = yield* resolveThread(threadId); | 580 | const thread = yield* resolveThreadShell(threadId); |
| 575 | if (!thread) { | 581 | if (!thread) { |
| 576 | return yield* Effect.die(new Error(`Thread '${threadId}' was not found in read model.`)); | 582 | return yield* Effect.die(new Error(`Thread '${threadId}' was not found in read model.`)); |
| 577 | } | 583 | } |
| ... | @@ -834,7 +840,7 @@ const make = Effect.gen(function* () { | ... | @@ -834,7 +840,7 @@ const make = Effect.gen(function* () { |
| 834 | readonly interactionMode?: "default" | "plan"; | 840 | readonly interactionMode?: "default" | "plan"; |
| 835 | readonly createdAt: string; | 841 | readonly createdAt: string; |
| 836 | }) { | 842 | }) { |
| 837 | const thread = yield* resolveThread(input.threadId); | 843 | const thread = yield* resolveThreadShell(input.threadId); |
| 838 | if (!thread) { | 844 | if (!thread) { |
| 839 | return yield* Effect.die( | 845 | return yield* Effect.die( |
| 840 | new Error(`Thread '${input.threadId}' was not found in read model.`), | 846 | new Error(`Thread '${input.threadId}' was not found in read model.`), |
| ... | @@ -975,7 +981,7 @@ const make = Effect.gen(function* () { | ... | @@ -975,7 +981,7 @@ const make = Effect.gen(function* () { |
| 975 | ); | 981 | ); |
| 976 | if (!generated) return; | 982 | if (!generated) return; |
| 977 | | 983 | |
| 978 | const thread = yield* resolveThread(input.threadId); | 984 | const thread = yield* resolveThreadShell(input.threadId); |
| 979 | if (!thread) return; | 985 | if (!thread) return; |
| 980 | if (!canReplaceThreadTitle(thread.title, input.titleSeed)) { | 986 | if (!canReplaceThreadTitle(thread.title, input.titleSeed)) { |
| 981 | return; | 987 | return; |
| ... | @@ -1007,7 +1013,7 @@ const make = Effect.gen(function* () { | ... | @@ -1007,7 +1013,7 @@ const make = Effect.gen(function* () { |
| 1007 | return { _tag: "Superseded" } as const; | 1013 | return { _tag: "Superseded" } as const; |
| 1008 | } | 1014 | } |
| 1009 | | 1015 | |
| 1010 | const thread = yield* resolveThread(event.payload.threadId); | 1016 | const thread = yield* resolveThreadDetail(event.payload.threadId); |
| 1011 | if (!thread || thread.titleRegeneration?.requestId !== requestId) { | 1017 | if (!thread || thread.titleRegeneration?.requestId !== requestId) { |
| 1012 | return { _tag: "Superseded" } as const; | 1018 | return { _tag: "Superseded" } as const; |
| 1013 | } | 1019 | } |
| ... | @@ -1040,7 +1046,7 @@ const make = Effect.gen(function* () { | ... | @@ -1040,7 +1046,7 @@ const make = Effect.gen(function* () { |
| 1040 | return { _tag: "Completed", title: undefined } as const; | 1046 | return { _tag: "Completed", title: undefined } as const; |
| 1041 | } | 1047 | } |
| 1042 | | 1048 | |
| 1043 | const latestThread = yield* resolveThread(event.payload.threadId); | 1049 | const latestThread = yield* resolveThreadShell(event.payload.threadId); |
| 1044 | if ( | 1050 | if ( |
| 1045 | !latestThread || | 1051 | !latestThread || |
| 1046 | latestThread.titleRegeneration?.requestId !== requestId || | 1052 | latestThread.titleRegeneration?.requestId !== requestId || |
| ... | @@ -1177,7 +1183,7 @@ const make = Effect.gen(function* () { | ... | @@ -1177,7 +1183,7 @@ const make = Effect.gen(function* () { |
| 1177 | return; | 1183 | return; |
| 1178 | } | 1184 | } |
| 1179 | | 1185 | |
| 1180 | const thread = yield* resolveThread(event.payload.threadId); | 1186 | const thread = yield* resolveThreadDetail(event.payload.threadId); |
| 1181 | if (!thread) { | 1187 | if (!thread) { |
| 1182 | return; | 1188 | return; |
| 1183 | } | 1189 | } |
| ... | @@ -1366,7 +1372,7 @@ const make = Effect.gen(function* () { | ... | @@ -1366,7 +1372,7 @@ const make = Effect.gen(function* () { |
| 1366 | "Context compaction requires an existing conversation.", | 1372 | "Context compaction requires an existing conversation.", |
| 1367 | ); | 1373 | ); |
| 1368 | } | 1374 | } |
| 1369 | const latestThread = yield* resolveThread(event.payload.threadId); | 1375 | const latestThread = yield* resolveThreadShell(event.payload.threadId); |
| 1370 | if ( | 1376 | if ( |
| 1371 | compactingThreadIds.has(event.payload.threadId) || | 1377 | compactingThreadIds.has(event.payload.threadId) || |
| 1372 | latestThread?.session?.status === "starting" || | 1378 | latestThread?.session?.status === "starting" || |
| ... | @@ -1436,7 +1442,7 @@ const make = Effect.gen(function* () { | ... | @@ -1436,7 +1442,7 @@ const make = Effect.gen(function* () { |
| 1436 | const processTurnInterruptRequested = Effect.fn("processTurnInterruptRequested")(function* ( | 1442 | const processTurnInterruptRequested = Effect.fn("processTurnInterruptRequested")(function* ( |
| 1437 | event: Extract<ProviderIntentEvent, { type: "thread.turn-interrupt-requested" }>, | 1443 | event: Extract<ProviderIntentEvent, { type: "thread.turn-interrupt-requested" }>, |
| 1438 | ) { | 1444 | ) { |
| 1439 | const thread = yield* resolveThread(event.payload.threadId); | 1445 | const thread = yield* resolveThreadShell(event.payload.threadId); |
| 1440 | if (!thread) { | 1446 | if (!thread) { |
| 1441 | return; | 1447 | return; |
| 1442 | } | 1448 | } |
| ... | @@ -1459,7 +1465,7 @@ const make = Effect.gen(function* () { | ... | @@ -1459,7 +1465,7 @@ const make = Effect.gen(function* () { |
| 1459 | | 1465 | |
| 1460 | const detail = formatFailureDetail(cause); | 1466 | const detail = formatFailureDetail(cause); |
| 1461 | return Effect.gen(function* () { | 1467 | return Effect.gen(function* () { |
| 1462 | const latestThread = yield* resolveThread(event.payload.threadId); | 1468 | const latestThread = yield* resolveThreadShell(event.payload.threadId); |
| 1463 | const latestSession = latestThread?.session; | 1469 | const latestSession = latestThread?.session; |
| 1464 | if ( | 1470 | if ( |
| 1465 | !latestSession || | 1471 | !latestSession || |
| ... | @@ -1487,7 +1493,7 @@ const make = Effect.gen(function* () { | ... | @@ -1487,7 +1493,7 @@ const make = Effect.gen(function* () { |
| 1487 | ); | 1493 | ); |
| 1488 | }), | 1494 | }), |
| 1489 | ); | 1495 | ); |
| 1490 | const stoppedThread = yield* resolveThread(event.payload.threadId); | 1496 | const stoppedThread = yield* resolveThreadShell(event.payload.threadId); |
| 1491 | const stoppedSession = stoppedThread?.session; | 1497 | const stoppedSession = stoppedThread?.session; |
| 1492 | if ( | 1498 | if ( |
| 1493 | !stoppedSession || | 1499 | !stoppedSession || |
| ... | @@ -1531,7 +1537,7 @@ const make = Effect.gen(function* () { | ... | @@ -1531,7 +1537,7 @@ const make = Effect.gen(function* () { |
| 1531 | const processApprovalResponseRequested = Effect.fn("processApprovalResponseRequested")(function* ( | 1537 | const processApprovalResponseRequested = Effect.fn("processApprovalResponseRequested")(function* ( |
| 1532 | event: Extract<ProviderIntentEvent, { type: "thread.approval-response-requested" }>, | 1538 | event: Extract<ProviderIntentEvent, { type: "thread.approval-response-requested" }>, |
| 1533 | ) { | 1539 | ) { |
| 1534 | const thread = yield* resolveThread(event.payload.threadId); | 1540 | const thread = yield* resolveThreadShell(event.payload.threadId); |
| 1535 | if (!thread) { | 1541 | if (!thread) { |
| 1536 | return; | 1542 | return; |
| 1537 | } | 1543 | } |
| ... | @@ -1575,7 +1581,7 @@ const make = Effect.gen(function* () { | ... | @@ -1575,7 +1581,7 @@ const make = Effect.gen(function* () { |
| 1575 | function* ( | 1581 | function* ( |
| 1576 | event: Extract<ProviderIntentEvent, { type: "thread.user-input-response-requested" }>, | 1582 | event: Extract<ProviderIntentEvent, { type: "thread.user-input-response-requested" }>, |
| 1577 | ) { | 1583 | ) { |
| 1578 | const thread = yield* resolveThread(event.payload.threadId); | 1584 | const thread = yield* resolveThreadShell(event.payload.threadId); |
| 1579 | if (!thread) { | 1585 | if (!thread) { |
| 1580 | return; | 1586 | return; |
| 1581 | } | 1587 | } |
| ... | @@ -1619,7 +1625,7 @@ const make = Effect.gen(function* () { | ... | @@ -1619,7 +1625,7 @@ const make = Effect.gen(function* () { |
| 1619 | const processSessionStopRequested = Effect.fn("processSessionStopRequested")(function* ( | 1625 | const processSessionStopRequested = Effect.fn("processSessionStopRequested")(function* ( |
| 1620 | event: Extract<ProviderIntentEvent, { type: "thread.session-stop-requested" }>, | 1626 | event: Extract<ProviderIntentEvent, { type: "thread.session-stop-requested" }>, |
| 1621 | ) { | 1627 | ) { |
| 1622 | const thread = yield* resolveThread(event.payload.threadId); | 1628 | const thread = yield* resolveThreadShell(event.payload.threadId); |
| 1623 | if (!thread) { | 1629 | if (!thread) { |
| 1624 | return; | 1630 | return; |
| 1625 | } | 1631 | } |
| ... | @@ -1696,7 +1702,7 @@ const make = Effect.gen(function* () { | ... | @@ -1696,7 +1702,7 @@ const make = Effect.gen(function* () { |
| 1696 | yield* threadTitleRegenerationWorker.enqueue(event); | 1702 | yield* threadTitleRegenerationWorker.enqueue(event); |
| 1697 | return; | 1703 | return; |
| 1698 | case "thread.runtime-mode-set": { | 1704 | case "thread.runtime-mode-set": { |
| 1699 | const thread = yield* resolveThread(event.payload.threadId); | 1705 | const thread = yield* resolveThreadShell(event.payload.threadId); |
| 1700 | if (!thread?.session || thread.session.status === "stopped") { | 1706 | if (!thread?.session || thread.session.status === "stopped") { |
| 1701 | return; | 1707 | return; |
| 1702 | } | 1708 | } |