Files
kandev/apps/web/lib/ws/handlers/session-models.ts
T

74 lines
2.8 KiB
TypeScript

import type { StoreApi } from "zustand";
import type { AppState } from "@/lib/state/store";
import type { WsHandlers } from "@/lib/ws/handlers/types";
import type { SessionModelsPayload } from "@/lib/types/backend";
export function registerSessionModelsHandlers(store: StoreApi<AppState>): WsHandlers {
return {
"session.models_updated": (message) => {
const payload = message.payload as SessionModelsPayload | undefined;
if (!payload?.session_id) {
return;
}
const acpModels = payload.models ?? [];
// Resolve currentModelId: prefer the explicit field, fall back to the "model"
// config option's currentValue (some ACP agents send currentModelId as empty).
let currentModelId = payload.current_model_id || "";
if (!currentModelId) {
const modelOpt = (payload.config_options ?? []).find(
(o) => o.id === "model" || o.category === "model",
);
if (modelOpt?.current_value) {
currentModelId = modelOpt.current_value;
}
}
console.log("[session-models] received session.models_updated", {
sessionId: payload.session_id,
rawCurrentModelId: payload.current_model_id,
resolvedCurrentModelId: currentModelId,
modelsCount: acpModels.length,
models: acpModels.map((m) => ({ id: m.model_id, name: m.name })),
configOptions: (payload.config_options ?? []).map((o) => ({
id: o.id,
category: o.category,
currentValue: o.current_value,
options: o.options?.map((opt: { value: string; name: string }) => opt.value),
})),
rawPayload: payload,
});
store.getState().setSessionModels(payload.session_id, {
currentModelId,
models: acpModels.map((m) => ({
modelId: m.model_id,
name: m.name,
description: m.description,
usageMultiplier: m.usage_multiplier,
meta: m.meta,
})),
configOptions: (payload.config_options ?? []).map((o) => ({
type: o.type,
id: o.id,
name: o.name,
currentValue: o.current_value,
category: o.category,
options: o.options,
})),
});
// Clear stale activeModel if it uses a profile ID that doesn't exist in ACP models.
// This happens when a user selected a static model before ACP models arrived.
if (acpModels.length > 0) {
const state = store.getState();
const currentActive = state.activeModel.bySessionId[payload.session_id];
if (currentActive && !acpModels.some((m) => m.model_id === currentActive)) {
console.log("[session-models] clearing stale activeModel", {
sessionId: payload.session_id,
staleModel: currentActive,
});
state.setActiveModel(payload.session_id, "");
}
}
},
};
}