Cordis throws on ctx.apiProxy without inject; use ctx.get and declare apiProxy inject so catalog and model APIs work under dsh web. Co-authored-by: Cursor <cursoragent@cursor.com>
72 lines
2.3 KiB
JavaScript
72 lines
2.3 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)');
|
|
}
|
|
const raw = await call(api.sessions.selectModel, {
|
|
sessionId,
|
|
provider: selection.provider,
|
|
model: selection.model,
|
|
reasoningEffort: selection.reasoningEffort,
|
|
});
|
|
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;
|
|
}
|