fix(bot-mode): persist canonical chat before opening

This commit is contained in:
Mauvis Ledford
2026-08-21 01:03:10 +08:00
committed by Teknium
parent 209e2ebdda
commit e95dd466b1
3 changed files with 45 additions and 1 deletions

View File

@@ -4149,6 +4149,24 @@ function createCanonicalChat(name) {
const sid = res?.stored_session_id
const runtime = res?.session_id
// session.create is intentionally lazy: its stored row does not exist until
// the first prompt. Mounting `sid` immediately therefore emits a noisy REST
// 404 ("Session not found"), and the turn-start auto-titler can win the race
// against the deferred `title: 'Bot Chat'` — under name-identity that is an
// identity outage: until the row is titled, the registry has no "Bot Chat"
// entry, so a second click during the intro turn mints a duplicate.
// session.title materializes the row now and records a user-authority title
// before either the open or kickoff, closing both the 404 race and the
// untitled window. Older gateways may not support the eager write; retain
// the kickoff-and-retry fallback below.
if (runtime) {
try {
await host.request('session.title', { session_id: runtime, title: CANONICAL_CHAT_TITLE })
} catch {
/* compatibility fallback: prompt.submit will persist the lazy row */
}
}
// Mount the session view FIRST, then send the kickoff — submitting into
// an unmounted session left the intro reply invisible until reopen.
let opened = false

View File

@@ -22,7 +22,31 @@ function loadCanonicalCreation({ openSession, request }) {
return { ...context.__canonical }
}
test('regression: navigation retries after the kickoff persists a new canonical chat', async () => {
test('regression: creation materializes and titles the lazy row before opening it', async () => {
const events = []
const runtime = loadCanonicalCreation({
openSession: async id => events.push(`open:${id}`),
request: async (method, params) => {
events.push(method)
if (method === 'session.create') return { stored_session_id: 'stored-1', session_id: 'runtime-1' }
if (method === 'session.title') {
assert.deepEqual(params, { session_id: 'runtime-1', title: 'Bot Chat' })
}
return {}
}
})
assert.equal(await runtime.createCanonicalChat('ops'), 'stored-1')
assert.deepEqual(events, [
'session.list',
'session.create',
'session.title',
'open:stored-1',
'prompt.submit'
])
})
test('compatibility: navigation retries after kickoff when eager title persistence is unavailable', async () => {
const events = []
let attempts = 0
const runtime = loadCanonicalCreation({
@@ -33,6 +57,7 @@ test('regression: navigation retries after the kickoff persists a new canonical
},
request: async method => {
if (method === 'session.create') return { stored_session_id: 'stored-1', session_id: 'runtime-1' }
if (method === 'session.title') throw new Error('unknown method')
if (method === 'prompt.submit') events.push('kickoff:persisted')
return {}
}

View File

@@ -0,0 +1 @@
krunkosaurus