fix(bots): restore the #97008 session contracts on the rebuilt modules
createCanonicalChat sends follow_profile_config and ensureGroupChatSession sends room_plumbing + follow_profile_config again, as main's plugin.js did before the rebuild. Without them, bot sessions created by this branch fell back to the server's legacy title heuristics (exact 'Bot Chat' title; hidden + 'Group: ' prefix) — the exact dependence the explicit contracts were introduced to replace. Contract-shape tests pin both params.
This commit is contained in:
@@ -125,7 +125,15 @@ describe('the lazy row is materialized before anything else touches it', () => {
|
||||
const { createCanonicalChat } = await loadModule()
|
||||
await createCanonicalChat('alpha')
|
||||
|
||||
expect(created).toMatchObject({ hidden: true, title: 'Bot Chat' })
|
||||
expect(created).toMatchObject({
|
||||
hidden: true,
|
||||
title: 'Bot Chat',
|
||||
// The PR #97008 contract: the canonical Bot Chat's runtime always
|
||||
// follows the profile's CURRENT config on resume — never the stored
|
||||
// model/provider pin. Dropping this param silently regresses bots to
|
||||
// the server's exact-title legacy fallback.
|
||||
follow_profile_config: true
|
||||
})
|
||||
})
|
||||
|
||||
it('sends the one intro turn on New Bot creation (kickoff: true)', async () => {
|
||||
|
||||
@@ -302,7 +302,14 @@ export function createCanonicalChat(
|
||||
// plugin-owned. Core applies this via the generic `hidden` flag
|
||||
// (deferred as pending_hidden until the row exists); older gateways
|
||||
// ignore the unknown param and it stays visible.
|
||||
hidden: true
|
||||
hidden: true,
|
||||
// Explicit contract (PR #97008): this session's runtime always follows
|
||||
// the member profile's CURRENT config. Resume must NOT restore the
|
||||
// stored model/provider pin from an old row — that left bot DMs stuck
|
||||
// on a stale/dead provider after a profile switch. Older gateways
|
||||
// ignore the unknown param; the server's exact-title backfill then
|
||||
// covers the legacy path.
|
||||
follow_profile_config: true
|
||||
})
|
||||
|
||||
const sid = res?.stored_session_id
|
||||
|
||||
@@ -30,6 +30,7 @@ export interface ScriptedMessage {
|
||||
}
|
||||
|
||||
export interface ScriptedSession {
|
||||
contracts?: { follow_profile_config: boolean; room_plumbing: boolean }
|
||||
messages: ScriptedMessage[]
|
||||
profile: string
|
||||
runtime: string
|
||||
@@ -219,6 +220,10 @@ export function createGroupGateway(options: GatewayOptions = {}): ScriptedGatewa
|
||||
const title = String(params.title ?? '')
|
||||
|
||||
const session: ScriptedSession = {
|
||||
contracts: {
|
||||
follow_profile_config: params.follow_profile_config === true,
|
||||
room_plumbing: params.room_plumbing === true
|
||||
},
|
||||
messages: [],
|
||||
profile,
|
||||
runtime: `rt-${profile}-${sequence}`,
|
||||
|
||||
@@ -81,6 +81,26 @@ describe('session resolution', () => {
|
||||
expect(room.gateway.sessions.get(String(fresh.stored))?.title).toBe('Group: r-abc')
|
||||
})
|
||||
|
||||
it('creates member sessions with the room_plumbing + follow_profile_config contracts', async () => {
|
||||
// The PR #97008 contracts: room member sessions always rebuild from the
|
||||
// member profile's CURRENT config on resume, never a stale stored
|
||||
// model/provider pin. Dropping either param silently regresses rooms to
|
||||
// the server's hidden + "Group: " title legacy fallback.
|
||||
const room = await loadRoom()
|
||||
|
||||
room.chat.updateGroupChat('Contract', current => {
|
||||
current.roomId = 'r-contract'
|
||||
|
||||
return current
|
||||
})
|
||||
const handle = await room.turns.ensureGroupChatSession('Contract', { name: 'research', title: '' })
|
||||
|
||||
expect(room.gateway.sessions.get(String(handle.stored))?.contracts).toEqual({
|
||||
follow_profile_config: true,
|
||||
room_plumbing: true
|
||||
})
|
||||
})
|
||||
|
||||
it('mints fresh member sessions when a same-name group is recreated after disband', async () => {
|
||||
const room = await loadRoom()
|
||||
const member: GroupMember = { name: 'research', title: '' }
|
||||
|
||||
@@ -198,7 +198,13 @@ export async function ensureGroupChatSession(group: string, member: GroupMember)
|
||||
profile: member.name,
|
||||
title,
|
||||
// Room member sessions are plumbing — always hidden from the sidebar.
|
||||
hidden: true
|
||||
hidden: true,
|
||||
// Explicit contracts (PR #97008): room plumbing sessions always rebuild
|
||||
// from the member profile's CURRENT config on resume, never a stale
|
||||
// stored model/provider pin. Older gateways ignore the unknown params;
|
||||
// the server's hidden + "Group: " title fallback then covers legacy.
|
||||
room_plumbing: true,
|
||||
follow_profile_config: true
|
||||
})) as { session_id?: string; stored_session_id?: string }
|
||||
|
||||
const stored = created?.stored_session_id || null
|
||||
|
||||
Reference in New Issue
Block a user