bereach-openclaw 1.6.5 → 1.6.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -106,4 +106,8 @@ export interface CacheStore {
|
|
|
106
106
|
campaignTaskStatus?: Record<string, Record<string, number>>;
|
|
107
107
|
/** LLM circuit breaker status: "auth" | "billing" | "error" when tripped, null when OK */
|
|
108
108
|
llmStatus?: string | null;
|
|
109
|
+
/** User's current fast model slug (e.g. "anthropic/claude-haiku-4-5", "google/gemini-2.5-flash"). Used to detect mid-session provider swaps. */
|
|
110
|
+
aiFastModel?: string | null;
|
|
111
|
+
/** User's current creative model slug. Used to detect mid-session provider swaps. */
|
|
112
|
+
aiCreativeModel?: string | null;
|
|
109
113
|
}
|
|
@@ -248,6 +248,12 @@ export interface SessionState {
|
|
|
248
248
|
postsThisSession: number;
|
|
249
249
|
/** Track current task ID to detect task switches and reset per-task counters. */
|
|
250
250
|
currentTaskId: string | null;
|
|
251
|
+
/** Fast model slug captured on the first turn of this session. Used to detect mid-session provider swaps that corrupt message history format. */
|
|
252
|
+
initialAiFastModel: string | null;
|
|
253
|
+
/** Creative model slug captured on the first turn of this session. */
|
|
254
|
+
initialAiCreativeModel: string | null;
|
|
255
|
+
/** True once we've warned the agent about a mid-session provider swap — prevents spamming the warning on every turn. */
|
|
256
|
+
providerMismatchWarningInjected: boolean;
|
|
251
257
|
}
|
|
252
258
|
|
|
253
259
|
export function createSessionState(): SessionState {
|
|
@@ -271,6 +277,9 @@ export function createSessionState(): SessionState {
|
|
|
271
277
|
sessionStarted: false,
|
|
272
278
|
postsThisSession: 0,
|
|
273
279
|
currentTaskId: null,
|
|
280
|
+
initialAiFastModel: null,
|
|
281
|
+
initialAiCreativeModel: null,
|
|
282
|
+
providerMismatchWarningInjected: false,
|
|
274
283
|
};
|
|
275
284
|
}
|
|
276
285
|
|
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
package/src/hooks/cache.ts
CHANGED
|
@@ -154,7 +154,7 @@ export async function fetchSnapshot(apiKey: string): Promise<CacheStore> {
|
|
|
154
154
|
pendingDrafts: 0, failedDrafts: 0, unreadDMs: 0, pendingSentInvitations: 0,
|
|
155
155
|
activeAccount: null, accounts: [], leadGenState: null, outreachState: null,
|
|
156
156
|
activeCampaigns: [], campaignTaskStatus: {}, campaignChecks: {}, sessionMeta: null, onboardingState: null,
|
|
157
|
-
recentEvents: [], llmStatus: null,
|
|
157
|
+
recentEvents: [], llmStatus: null, aiFastModel: null, aiCreativeModel: null,
|
|
158
158
|
};
|
|
159
159
|
}
|
|
160
160
|
|
|
@@ -178,6 +178,8 @@ export async function fetchSnapshot(apiKey: string): Promise<CacheStore> {
|
|
|
178
178
|
onboardingState: snapshot.onboardingState ?? null,
|
|
179
179
|
recentEvents: snapshot.recentEvents ?? [],
|
|
180
180
|
llmStatus: snapshot.llmStatus ?? null,
|
|
181
|
+
aiFastModel: snapshot.aiFastModel ?? null,
|
|
182
|
+
aiCreativeModel: snapshot.aiCreativeModel ?? null,
|
|
181
183
|
};
|
|
182
184
|
|
|
183
185
|
// Fallback: if snapshot didn't include limits, fetch from dedicated endpoint
|
|
@@ -235,6 +237,9 @@ export async function getOrFetch(apiKey: string): Promise<CacheStore> {
|
|
|
235
237
|
sessionMeta: get<SessionMeta>("sessionMeta"),
|
|
236
238
|
onboardingState: get<OnboardingState>("onboardingState"),
|
|
237
239
|
recentEvents: get<RecentEvent[]>("recentEvents") ?? [],
|
|
240
|
+
llmStatus: get<string>("llmStatus") ?? null,
|
|
241
|
+
aiFastModel: get<string>("aiFastModel") ?? null,
|
|
242
|
+
aiCreativeModel: get<string>("aiCreativeModel") ?? null,
|
|
238
243
|
};
|
|
239
244
|
}
|
|
240
245
|
|
|
@@ -45,6 +45,9 @@ export function resetContextState(state: SessionState) {
|
|
|
45
45
|
state.onboardingDirectiveInjected = false;
|
|
46
46
|
state.sessionStarted = false;
|
|
47
47
|
state.currentTaskMode = null;
|
|
48
|
+
state.initialAiFastModel = null;
|
|
49
|
+
state.initialAiCreativeModel = null;
|
|
50
|
+
state.providerMismatchWarningInjected = false;
|
|
48
51
|
}
|
|
49
52
|
|
|
50
53
|
/** Reset profile-related flags for account switch (mid-session). */
|
|
@@ -309,8 +312,55 @@ export function registerContextHook(api: any, apiKey: string | undefined, state:
|
|
|
309
312
|
|
|
310
313
|
await autoInitProfile(state, liveData, key);
|
|
311
314
|
|
|
315
|
+
// Mid-session provider swap detection (B38.4).
|
|
316
|
+
// The gateway process is long-lived. If the user changes their AI model
|
|
317
|
+
// in Settings while a chat is open (Gemini → Claude Haiku, etc.), the
|
|
318
|
+
// session message history is still formatted for the previous provider
|
|
319
|
+
// and the new one will fail to parse it. Detect the mismatch and force
|
|
320
|
+
// a fresh chat.
|
|
321
|
+
const currentFast = liveData.aiFastModel ?? null;
|
|
322
|
+
const currentCreative = liveData.aiCreativeModel ?? null;
|
|
323
|
+
let providerMismatch = false;
|
|
324
|
+
if (!state.initialAiFastModel && !state.initialAiCreativeModel) {
|
|
325
|
+
state.initialAiFastModel = currentFast;
|
|
326
|
+
state.initialAiCreativeModel = currentCreative;
|
|
327
|
+
} else {
|
|
328
|
+
const fastChanged = !!currentFast && currentFast !== state.initialAiFastModel;
|
|
329
|
+
const creativeChanged =
|
|
330
|
+
!!currentCreative && currentCreative !== state.initialAiCreativeModel;
|
|
331
|
+
providerMismatch = fastChanged || creativeChanged;
|
|
332
|
+
}
|
|
333
|
+
|
|
312
334
|
const { staticContext, dynamicContext } = buildInteractiveContext(state, soulTemplate, liveData, key);
|
|
313
335
|
|
|
336
|
+
if (providerMismatch && !state.providerMismatchWarningInjected) {
|
|
337
|
+
state.providerMismatchWarningInjected = true;
|
|
338
|
+
const warning = [
|
|
339
|
+
"",
|
|
340
|
+
"## CRITICAL — AI PROVIDER CHANGED MID-SESSION",
|
|
341
|
+
"",
|
|
342
|
+
`The user changed their AI model in Settings while this chat was already open.`,
|
|
343
|
+
`- Session was started with: fast=${state.initialAiFastModel} creative=${state.initialAiCreativeModel}`,
|
|
344
|
+
`- Current setting: fast=${currentFast} creative=${currentCreative}`,
|
|
345
|
+
"",
|
|
346
|
+
"The existing message history in this conversation is formatted for the previous",
|
|
347
|
+
"provider and the new provider cannot parse it. Any tool call in this turn will fail.",
|
|
348
|
+
"",
|
|
349
|
+
"You MUST respond with ONLY this message and NOTHING else:",
|
|
350
|
+
"",
|
|
351
|
+
"> I see you changed your AI model. The conversation history can't be converted between providers mid-session, so please type `/new` to start a fresh chat with the new model.",
|
|
352
|
+
"",
|
|
353
|
+
"Do NOT call any tools. Do NOT summarize status. Do NOT continue the previous task.",
|
|
354
|
+
"Just output the message above verbatim and stop.",
|
|
355
|
+
"",
|
|
356
|
+
].join("\n");
|
|
357
|
+
log(`provider mismatch detected — injecting /new warning (was fast=${state.initialAiFastModel} now fast=${currentFast})`);
|
|
358
|
+
return {
|
|
359
|
+
appendSystemContext: staticContext,
|
|
360
|
+
prependContext: warning + dynamicContext,
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
|
|
314
364
|
// appendSystemContext = cached by gateway (soul template, static across turns)
|
|
315
365
|
// prependContext = per-turn dynamic data (live status, activity, tone)
|
|
316
366
|
return {
|