mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-03 13:52:09 +03:00
Fusion's panel-model extraction in combo.ts only recognized plain string
or {model: string} entries in combo.models; a {kind:"combo-ref", comboName}
step (a first-class, Zod-validated combo-step shape the dashboard already
lets you add to a fusion panel) had neither field, so it was silently
filtered out — no error, no warning, and an opaque 400 if it was the only
panel member.
A combo-ref panel member is now dispatched as one black-box panel voice
(a recursive handleComboChat call into the referenced combo, reusing the
same executeComboRefUnit + cycle/depth guards every other combo-ref-
consuming strategy already uses), not a fan-out of the referenced combo's
own targets.
New module open-sse/services/combo/fusionPanel.ts keeps the frozen
combo.ts god-file's growth minimal (extraction/dispatch-wrapper logic
lives there; the fusion branch itself only wires it in).
80 lines
2.7 KiB
TypeScript
80 lines
2.7 KiB
TypeScript
/**
|
|
* Fusion panel member extraction — resolves combo.models entries for the
|
|
* fusion strategy, including nested `combo-ref` steps (#6764).
|
|
*
|
|
* A combo-ref panel member is dispatched as ONE black-box panel voice (a full
|
|
* recursive handleComboChat call for the referenced combo, reusing the same
|
|
* executeComboRefUnit + cycle/depth guards every other combo-ref-consuming
|
|
* strategy already uses) — NOT a fan-out of the referenced combo's own
|
|
* targets. This keeps panel sizing and cost predictable and matches how a
|
|
* literal `auto/*` string panel member already behaves via the single-
|
|
* dispatch safety net in src/sse/handlers/chat.ts.
|
|
*/
|
|
import { normalizeComboStep } from "../../../src/lib/combos/steps.ts";
|
|
import { executeComboRefUnit } from "./runtimeUnits.ts";
|
|
import type {
|
|
ComboCollectionLike,
|
|
ComboNestingContext,
|
|
HandleComboChatOptions,
|
|
HandleSingleModel,
|
|
ResolvedComboRefTarget,
|
|
} from "./types.ts";
|
|
|
|
export type FusionPanelSpec = {
|
|
/** Dispatch keys handed to fusion.ts's `models` — comboName for combo-ref members, plain model string otherwise. */
|
|
panel: string[];
|
|
/** comboName -> resolved combo-ref unit, consumed by buildFusionHandleSingleModel. */
|
|
comboRefUnits: Map<string, ResolvedComboRefTarget>;
|
|
};
|
|
|
|
export function extractFusionPanelSpec(
|
|
models: unknown[],
|
|
comboName: string,
|
|
allCombos: ComboCollectionLike
|
|
): FusionPanelSpec {
|
|
const panel: string[] = [];
|
|
const comboRefUnits = new Map<string, ResolvedComboRefTarget>();
|
|
models.forEach((entry, index) => {
|
|
const step = normalizeComboStep(entry, { comboName, index, allCombos });
|
|
if (!step) return;
|
|
if (step.kind === "combo-ref") {
|
|
if (!comboRefUnits.has(step.comboName)) {
|
|
comboRefUnits.set(step.comboName, {
|
|
kind: "combo-ref",
|
|
stepId: step.id,
|
|
executionKey: step.id,
|
|
comboName: step.comboName,
|
|
weight: step.weight,
|
|
label: step.label ?? null,
|
|
});
|
|
}
|
|
panel.push(step.comboName);
|
|
return;
|
|
}
|
|
panel.push(step.model);
|
|
});
|
|
return { panel, comboRefUnits };
|
|
}
|
|
|
|
export function buildFusionHandleSingleModel(args: {
|
|
handleSingleModel: HandleSingleModel;
|
|
comboRefUnits: Map<string, ResolvedComboRefTarget>;
|
|
allCombos: ComboCollectionLike;
|
|
nesting: ComboNestingContext;
|
|
baseOptions: HandleComboChatOptions;
|
|
runCombo: (options: HandleComboChatOptions) => Promise<Response>;
|
|
}): HandleSingleModel {
|
|
return (body, modelStr, target) => {
|
|
const unit = args.comboRefUnits.get(modelStr);
|
|
if (!unit) return args.handleSingleModel(body, modelStr, target);
|
|
return executeComboRefUnit({
|
|
body,
|
|
unit,
|
|
allCombos: args.allCombos,
|
|
runCombo: args.runCombo,
|
|
baseOptions: args.baseOptions,
|
|
nesting: args.nesting,
|
|
});
|
|
};
|
|
}
|