feat(tess): persist durable session state (#729)
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful

This commit was merged in pull request #729.
This commit is contained in:
2026-07-13 05:14:11 +00:00
parent e3b5113be2
commit 99a2d0fc9d
27 changed files with 19237 additions and 15 deletions

View File

@@ -487,6 +487,120 @@ export const agentLogs = pgTable(
],
);
// ─── Tess durable session state ─────────────────────────────────────────────
// PostgreSQL is canonical for restart-safe Tess session recovery. The state
// machine lives in @mosaicstack/agent; these records are its durable adapter.
export const interactionInboxStatusEnum = pgEnum('interaction_inbox_status', [
'pending',
'processing',
'processed',
]);
export const interactionOutboxStatusEnum = pgEnum('interaction_outbox_status', [
'pending',
'processing',
'delivered',
]);
export const interactionHandoffStatusEnum = pgEnum('interaction_handoff_status', [
'pending',
'accepted',
]);
export const interactionSessions = pgTable('interaction_sessions', {
id: text('id').primaryKey(),
agentName: text('agent_name').notNull(),
tenantId: text('tenant_id').notNull(),
ownerId: text('owner_id')
.notNull()
.references(() => users.id, { onDelete: 'cascade' }),
providerId: text('provider_id').notNull(),
runtimeSessionId: text('runtime_session_id').notNull(),
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
});
export const interactionInbox = pgTable(
'interaction_inbox',
{
id: uuid('id').primaryKey().defaultRandom(),
sessionId: text('session_id')
.notNull()
.references(() => interactionSessions.id, { onDelete: 'cascade' }),
idempotencyKey: text('idempotency_key').notNull(),
correlationId: text('correlation_id').notNull(),
content: text('content').notNull(),
contentDigest: text('content_digest').notNull(),
status: interactionInboxStatusEnum('status').notNull().default('pending'),
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
},
(t) => [
uniqueIndex('interaction_inbox_session_idempotency_idx').on(t.sessionId, t.idempotencyKey),
index('interaction_inbox_session_status_created_idx').on(t.sessionId, t.status, t.createdAt),
],
);
export const interactionOutbox = pgTable(
'interaction_outbox',
{
id: uuid('id').primaryKey().defaultRandom(),
sessionId: text('session_id')
.notNull()
.references(() => interactionSessions.id, { onDelete: 'cascade' }),
idempotencyKey: text('idempotency_key').notNull(),
correlationId: text('correlation_id').notNull(),
channelId: text('channel_id').notNull(),
kind: text('kind').notNull(),
content: text('content').notNull(),
contentDigest: text('content_digest').notNull(),
status: interactionOutboxStatusEnum('status').notNull().default('pending'),
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
},
(t) => [
uniqueIndex('interaction_outbox_session_idempotency_idx').on(t.sessionId, t.idempotencyKey),
index('interaction_outbox_session_status_created_idx').on(t.sessionId, t.status, t.createdAt),
],
);
export const interactionCheckpoints = pgTable(
'interaction_checkpoints',
{
id: uuid('id').primaryKey().defaultRandom(),
sessionId: text('session_id')
.notNull()
.references(() => interactionSessions.id, { onDelete: 'cascade' }),
checkpointId: text('checkpoint_id').notNull(),
contentDigest: text('content_digest').notNull(),
cursor: text('cursor').notNull(),
summary: text('summary').notNull(),
compactionEpoch: integer('compaction_epoch').notNull(),
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
},
(t) => [
uniqueIndex('interaction_checkpoints_session_idempotency_idx').on(t.sessionId, t.checkpointId),
index('interaction_checkpoints_session_epoch_idx').on(t.sessionId, t.compactionEpoch),
],
);
export const interactionHandoffs = pgTable(
'interaction_handoffs',
{
handoffId: text('handoff_id').primaryKey(),
sessionId: text('session_id')
.notNull()
.references(() => interactionSessions.id, { onDelete: 'cascade' }),
destination: text('destination').notNull(),
correlationId: text('correlation_id').notNull(),
checkpointId: text('checkpoint_id').notNull(),
status: interactionHandoffStatusEnum('status').notNull().default('pending'),
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
},
(t) => [index('interaction_handoffs_session_status_idx').on(t.sessionId, t.status)],
);
// ─── Skills ─────────────────────────────────────────────────────────────────
export const skills = pgTable(