mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-06-28 02:11:30 +00:00
🛡️ fix: Codex round 5 — refuse unresolvable resolves; expose pending action
Two of three findings on c8abd826e1 (the third deferred to Slice B):
- J3 resolve() refuses a requires_action job that has lost its pendingAction
(e.g. a malformed record dropped on deserialize): it expires/finalizes the
job instead of driving a resumed run with no reviewed interrupt payload —
consistent with how active-listing + cleanup already treat a stale prompt.
- J2 /chat/status returns the live pendingAction for a paused stream, so a
client rebuilding from status (reload / cross-replica) has the action id +
payload to render and submit the prompt, not just "paused".
Deferred (Slice B): J1 — emitting a terminal SSE event on approval expiry so
already-subscribed clients close. The store-level lifecycle can't emit
transport events, and there are no live SSE subscribers to a paused stream
until the Slice B runtime wiring exists; tracked for that work.
tsc + lint clean; policy + type-contract specs pass.
This commit is contained in:
parent
c8abd826e1
commit
e7d9cf21b6
2 changed files with 12 additions and 0 deletions
|
|
@ -218,6 +218,10 @@ router.get('/chat/status/:conversationId', async (req, res) => {
|
|||
aggregatedContent: resumeState?.aggregatedContent ?? [],
|
||||
createdAt: job.createdAt,
|
||||
resumeState,
|
||||
// Surface the live pending approval so a client rebuilding from /chat/status
|
||||
// (reload / cross-replica) has the action id + payload to render and submit
|
||||
// the prompt, not just the knowledge that the stream is paused.
|
||||
pendingAction: job.status === 'requires_action' && pendingLive ? pendingAction : undefined,
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -77,6 +77,14 @@ export class ApprovalLifecycle {
|
|||
*/
|
||||
async resolve(streamId: string, expectedActionId?: string): Promise<boolean> {
|
||||
const job = await this.store.getJob(streamId);
|
||||
if (job?.status === 'requires_action' && !job.pendingAction) {
|
||||
// The prompt was lost (e.g. a malformed record dropped on deserialize).
|
||||
// It can't be reviewed, so finalize the job instead of driving a resumed
|
||||
// run with no reviewed interrupt payload — consistent with how the active
|
||||
// listing and cleanup treat a stale pending action.
|
||||
await this.expire(streamId);
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
job?.status === 'requires_action' &&
|
||||
job.pendingAction &&
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue