Files
dsh-telegram-channel/lib/models.js
T
owoandCursor 819010de1c fix: stabilize /model reasoning-effort selection (v0.3.5)
Keep pending model outside the picker map, omit undefined reasoningEffort in selectModel payload, auto-apply single-effort models, and surface RPC errors.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-14 22:41:43 +08:00

76 lines
2.5 KiB
JavaScript

import { randomUUID } from 'node:crypto';
import { resolveApiProxy } from './apiproxy.js';
function unwrap(res) {
const r = res;
if (r?.result?.ok === true)
return r.result.value;
return undefined;
}
function unwrapError(res) {
const r = res;
if (r?.result && r.result.ok === false) {
const err = r.result.error;
if (!err)
return 'rpc failed';
return err.code ? `${err.code}: ${err.message ?? ''}`.trim() : (err.message ?? 'rpc failed');
}
return undefined;
}
async function call(fn, payload) {
if (typeof fn !== 'function')
throw new Error('apiProxy sessions API unavailable');
return fn({ rpcId: randomUUID(), payload });
}
export async function loadSessionModels(ctx, sessionId) {
const api = resolveApiProxy(ctx);
if (!api?.sessions?.models) {
throw new Error('apiProxy unavailable (use ctx.get / inject apiProxy)');
}
const raw = await call(api.sessions.models, { sessionId });
const value = unwrap(raw);
if (!value) {
throw new Error(unwrapError(raw) ?? 'failed to load session models');
}
const options = [];
for (const group of value.groups ?? []) {
for (const m of group.models ?? []) {
options.push({
provider: group.id,
model: m.id,
label: `${group.name}/${m.name}`,
efforts: m.reasoning?.efforts?.map((e) => ({ id: e.id, name: e.name })),
});
}
}
return {
current: value.current,
routable: value.routable,
options,
};
}
export async function selectSessionModel(ctx, sessionId, selection) {
const api = resolveApiProxy(ctx);
if (!api?.sessions?.selectModel) {
throw new Error('apiProxy unavailable (use ctx.get / inject apiProxy)');
}
// Omit undefined reasoningEffort — some validators treat explicit undefined as invalid.
const payload = {
sessionId,
provider: selection.provider,
model: selection.model,
};
if (selection.reasoningEffort !== undefined && selection.reasoningEffort !== '') {
payload.reasoningEffort = selection.reasoningEffort;
}
const raw = await call(api.sessions.selectModel, payload);
const value = unwrap(raw);
if (!value?.selected) {
throw new Error(unwrapError(raw) ?? 'failed to select model');
}
return value.selected;
}
export function formatModel(sel) {
const base = `${sel.provider}/${sel.model}`;
return sel.reasoningEffort ? `${base} (${sel.reasoningEffort})` : base;
}