mirror of
https://github.com/getpaseo/paseo.git
synced 2026-11-05 07:54:38 +00:00
fix(app): a closed agent shows its stored options, and a provider switch asks about its own options
A closed agent's snapshot is projected from its stored record, which kept controls and provider options but dropped them from the payload, so the app drew no speed or other controls for it. The stored projection now carries them, with the legacy features derived from the same source. The draft read the form's provider and the model's options separately, so for the render after a manual provider change it asked the new provider about the previous provider's options. The request is now built from one snapshot of the model and is absent until the model has observed the new provider.
This commit is contained in:
@@ -397,6 +397,50 @@ describe("toAgentPayload", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("projects a closed agent's stored controls and options", () => {
|
||||
const controls: AgentOptionControl[] = [
|
||||
{
|
||||
type: "select",
|
||||
key: "service_tier",
|
||||
label: "Speed",
|
||||
defaultValue: "default",
|
||||
choices: [
|
||||
{ value: "default", label: "Normal" },
|
||||
{ value: "priority", label: "Fast" },
|
||||
],
|
||||
},
|
||||
];
|
||||
const record = toStoredAgentRecord(
|
||||
createManagedAgent({
|
||||
provider: "codex",
|
||||
lifecycle: "closed",
|
||||
controls,
|
||||
config: {
|
||||
provider: "codex",
|
||||
providerOptions: { service_tier: "priority", sandbox_mode: "read-only" },
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
const payload = buildStoredAgentPayload(record, ["codex"]);
|
||||
|
||||
expect(payload.status).toBe("closed");
|
||||
expect(payload.controls).toEqual(controls);
|
||||
expect(payload.options).toEqual({ service_tier: "priority", sandbox_mode: "read-only" });
|
||||
expect(payload.features).toEqual([
|
||||
{
|
||||
type: "select",
|
||||
id: "service_tier",
|
||||
label: "Speed",
|
||||
value: "priority",
|
||||
options: [
|
||||
{ id: "default", label: "Normal", isDefault: true },
|
||||
{ id: "priority", label: "Fast" },
|
||||
],
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("carries a stored lastError onto the payload", () => {
|
||||
const record = toStoredAgentRecord(
|
||||
createManagedAgent({ provider: "codex", config: { provider: "codex" }, lastError: "boom" }),
|
||||
|
||||
@@ -225,6 +225,21 @@ function visibilityFlags(agent: {
|
||||
};
|
||||
}
|
||||
|
||||
function buildStoredOptionControls(
|
||||
record: StoredAgentRecord,
|
||||
): Pick<AgentSnapshotPayload, "features" | "options" | "controls"> {
|
||||
const controls = normalizeControls(record.controls);
|
||||
const options = record.config?.providerOptions
|
||||
? sanitizeEffectiveOptions(record.config.providerOptions)
|
||||
: undefined;
|
||||
return {
|
||||
// COMPAT(featureValues): added in v0.15.0, remove after 2027-05-01.
|
||||
features: featuresFromControls({ controls, options }),
|
||||
...(options ? { options } : {}),
|
||||
controls,
|
||||
};
|
||||
}
|
||||
|
||||
export function buildStoredAgentPayload(
|
||||
record: StoredAgentRecord,
|
||||
validProviders: Iterable<AgentProvider>,
|
||||
@@ -246,6 +261,7 @@ export function buildStoredAgentPayload(
|
||||
const lastUserMessageAt = record.lastUserMessageAt ? new Date(record.lastUserMessageAt) : null;
|
||||
|
||||
const runtimeInfo = buildStoredRuntimeInfo(record);
|
||||
const optionControls = buildStoredOptionControls(record);
|
||||
const providerAvailable = isStoredAgentProviderAvailable(record, validProviders);
|
||||
const persistence = projectPersistenceHandleForWire(
|
||||
buildStoredPersistenceHandle(record, validProviders),
|
||||
@@ -270,6 +286,7 @@ export function buildStoredAgentPayload(
|
||||
capabilities: defaultCapabilities,
|
||||
currentModeId: record.lastModeId ?? null,
|
||||
availableModes: [],
|
||||
...optionControls,
|
||||
pendingPermissions: [],
|
||||
persistence,
|
||||
title: record.title ?? null,
|
||||
@@ -475,7 +492,7 @@ function normalizeControls(
|
||||
return Array.isArray(controls) ? controls.map((control) => ({ ...control })) : [];
|
||||
}
|
||||
|
||||
function sanitizeEffectiveOptions(options: ProviderOptions): ProviderOptions {
|
||||
function sanitizeEffectiveOptions(options: Record<string, unknown>): ProviderOptions {
|
||||
const sanitized = sanitizeOptionalJson(options);
|
||||
return sanitized && isJsonObject(sanitized) ? sanitized : {};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user