Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .changeset/fast-canonical-session-state.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@roomote/cloud-agents': patch
'@roomote/sdk': patch
'@roomote/types': patch
'@roomote/db': patch
'@roomote/web': patch
---

Sessions no longer announce an outdated status as current. Every model-relevant input, including events the transcript hides, is recorded in one ordered per-Session log with the time it was observed and the order it was admitted. Before each turn, a deterministic reducer decides which state facts are still current, which stay as history, and which are obsolete, using authoritative versions where a source provides them; a queued update that a newer version has already replaced no longer runs. Conversations also rebuild from that same log after a restart, so a resumed Session and a continuing one describe the same state.
6 changes: 6 additions & 0 deletions apps/web/src/trpc/commands/setup/setup-session.test.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

37 changes: 34 additions & 3 deletions apps/web/src/trpc/commands/setup/setup-session.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { createHash } from 'node:crypto';

import { buildFastAgentArtifactCreator } from '@roomote/sdk/server';
import {
buildFastAgentArtifactCreator,
enqueueFastAgentParentEvent,
} from '@roomote/sdk/server';
import { buildFastAgentSetupAdapter } from '@roomote/cloud-agents/server';
import {
and,
Expand Down Expand Up @@ -465,10 +468,38 @@ export async function scheduleSetupPlatformEvent(
): Promise<{ scheduled: boolean }> {
const turn = await buildSetupPlatformEventTurn(auth, input);
if (!turn) return { scheduled: false };
scheduleWebFastAgentTurn(turn);
await enqueueDurableWebPlatformEventTurn(turn);
return { scheduled: true };
}

async function enqueueDurableWebPlatformEventTurn(
turn: Parameters<typeof scheduleWebFastAgentTurn>[0],
): Promise<void> {
if (!turn.durableSessionId || !turn.setupContext || !turn.currentMessageId) {
throw new Error('A setup platform event requires durable turn context.');
}
await enqueueFastAgentParentEvent({
parent: {
sessionId: turn.durableSessionId,
conversation: turn.delivery.conversation,
},
event: {
type: 'human_follow_up',
eventId: turn.currentMessageId,
currentMessageId: turn.currentMessageId,
userId: turn.userId,
question: turn.question,
turnSource: 'platform_event',
platformEventKind: turn.platformEventKind ?? 'setup',
...(turn.platformEventVisibility
? { platformEventVisibility: turn.platformEventVisibility }
: {}),
setupSession: true,
setupContext: turn.setupContext,
},
});
}

async function buildSetupPlatformEventTurn(
auth: UserAuthSuccess,
input: {
Expand Down Expand Up @@ -784,7 +815,7 @@ export async function reconcileSetupPlatformEvents(
},
{ conversation, setupSnapshot },
);
if (turn) scheduleWebFastAgentTurn(turn);
if (turn) await enqueueDurableWebPlatformEventTurn(turn);
return setupCompleted;
}

Expand Down
Loading
Loading