studio/chat: let user pick OpenAI container before first send
Previously the picker silently no-op'd until the user sent the first message, because Dexie's ThreadRecord is only materialized inside the runtime-provider's `initialize` hook (assistant-ui's first-message callback). That kept users from binding a thread to an existing OpenAI container up front; they had to either send a message and risk the chat adapter auto-creating one, or accept the cross-thread inheritance default. - Export `ensureThreadRecord` from runtime-provider so other surfaces can materialize the row idempotently. - In OpenAICodeExecSection.onPick, await ensureThreadRecord before the update, with modelType="base" (the settings sheet that hosts this section is only rendered in single-thread mode). Behaviour after this commit: - New thread + user picks a container in the sidebar → thread row is created with that container_id; first send uses it, no auto-create. - New thread + user does nothing → row still absent; first send goes through the existing inherit/lazy-create path as before. - The auto-bind effect remains silent best-effort: it does not eagerly create the thread row, so it cannot pre-empt the user's pick on a fresh thread.
This commit is contained in:
parent
b2afc53e1e
commit
ef2b59bd9f
2 changed files with 14 additions and 10 deletions
|
|
@ -44,6 +44,7 @@ import {
|
|||
import { db } from "../db";
|
||||
import type { ExternalProviderConfig } from "../external-providers";
|
||||
import { useLiveQuery } from "../db";
|
||||
import { ensureThreadRecord } from "../runtime-provider";
|
||||
|
||||
const AUTO_OPTION_VALUE = "__auto__";
|
||||
const DEFAULT_TTL_MINUTES = 20;
|
||||
|
|
@ -155,20 +156,23 @@ export function OpenAICodeExecSection({
|
|||
const onPick = async (value: string) => {
|
||||
if (!activeThreadId) return;
|
||||
const next = value === AUTO_OPTION_VALUE ? null : value;
|
||||
// Dexie's `update` returns the count of rows changed: 0 means the
|
||||
// thread record is not yet in IndexedDB. That happens when the user
|
||||
// is on a brand-new thread before sending the first message — the
|
||||
// thread row is materialized on first send by the chat adapter.
|
||||
// Without this guard the selection silently no-ops and the picker
|
||||
// snaps back to "Auto-create per thread", which looks broken.
|
||||
// The thread row is normally materialized on first send by the
|
||||
// chat adapter. When the user picks a container before sending the
|
||||
// first message, the row does not exist yet and Dexie's `update`
|
||||
// returns 0 rows — the selection would silently no-op and the
|
||||
// picker would snap back to "Auto-create per thread". Eagerly
|
||||
// create the row so the user can pin a container up front.
|
||||
// modelType "base" is correct here: the settings sheet that hosts
|
||||
// this section is only rendered in single-thread mode, where the
|
||||
// chat-page passes modelType="base" into ChatRuntimeProvider.
|
||||
try {
|
||||
await ensureThreadRecord({ threadId: activeThreadId, modelType: "base" });
|
||||
const affected = await db.threads.update(activeThreadId, {
|
||||
openaiCodeExecContainerId: next,
|
||||
});
|
||||
if (affected === 0) {
|
||||
toast.error(
|
||||
"Send a message first to pin a container to this thread.",
|
||||
);
|
||||
// Defensive: ensureThreadRecord should have written the row.
|
||||
toast.error("Could not update thread.");
|
||||
}
|
||||
} catch (err) {
|
||||
toast.error(
|
||||
|
|
|
|||
|
|
@ -396,7 +396,7 @@ function toThreadMessage(m: MessageRecord): ThreadMessage {
|
|||
};
|
||||
}
|
||||
|
||||
async function ensureThreadRecord({
|
||||
export async function ensureThreadRecord({
|
||||
threadId,
|
||||
modelType,
|
||||
pairId,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue