feat(tess): wire durable interaction surfaces (#732)
Some checks failed
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was canceled

This commit was merged in pull request #732.
This commit is contained in:
2026-07-13 10:05:29 +00:00
parent 84d884b932
commit 0b621660c8
16 changed files with 782 additions and 58 deletions

View File

@@ -50,9 +50,20 @@ export class TessDurableSessionRepository implements DurableSessionStore {
.onConflictDoNothing();
const existing = await this.session(identity.sessionId);
if (!existing || !sameIdentity(existing, identity)) {
if (!existing || !sameEnrollmentScope(existing, identity)) {
throw new Error(`Durable Tess session identity conflict: ${identity.sessionId}`);
}
// A recovered/re-enrolled runtime can receive a new provider session ID;
// the conversation handle and owner scope remain immutable.
if (
existing.providerId !== identity.providerId ||
existing.runtimeSessionId !== identity.runtimeSessionId
) {
await this.db
.update(interactionSessions)
.set({ providerId: identity.providerId, runtimeSessionId: identity.runtimeSessionId })
.where(eq(interactionSessions.id, identity.sessionId));
}
}
async snapshot(sessionId: string): Promise<DurableSessionSnapshot | null> {
@@ -427,14 +438,12 @@ function matchesCheckpointDigest(stored: string, digest: string): boolean {
return stored === digest;
}
function sameIdentity(left: DurableSessionIdentity, right: DurableSessionIdentity): boolean {
function sameEnrollmentScope(left: DurableSessionIdentity, right: DurableSessionIdentity): boolean {
return (
left.agentName === right.agentName &&
left.sessionId === right.sessionId &&
left.tenantId === right.tenantId &&
left.ownerId === right.ownerId &&
left.providerId === right.providerId &&
left.runtimeSessionId === right.runtimeSessionId
left.ownerId === right.ownerId
);
}