mirror of
https://github.com/getpaseo/paseo.git
synced 2026-11-08 17:34:51 +00:00
Keep stored-record reads tolerant of a legacy option the conversion rejects
This commit is contained in:
@@ -13600,6 +13600,27 @@ describe("agent options", () => {
|
||||
]);
|
||||
});
|
||||
|
||||
test("a stored record with a malformed legacy speed still reads; opening it is what rejects it", () => {
|
||||
const manager = new AgentManager({ clients: { codex: new OptionsClient() }, logger });
|
||||
// An older daemon accepted any value here; this one rejects it on create and on change.
|
||||
const record = parseStoredAgentRecord({
|
||||
id: "agent-legacy-malformed",
|
||||
provider: "codex",
|
||||
cwd: "/repo",
|
||||
createdAt: "2026-01-01T00:00:00.000Z",
|
||||
updatedAt: "2026-01-01T00:00:00.000Z",
|
||||
lastStatus: "closed",
|
||||
config: { providerOptions: { fast_mode: "false" } },
|
||||
persistence: { provider: "codex", sessionId: "thread-2" },
|
||||
});
|
||||
|
||||
const payload = buildStoredAgentPayload(record, ["codex"], (provider, own) =>
|
||||
manager.effectiveOptionsFor(provider, own),
|
||||
);
|
||||
|
||||
expect(payload.options).toEqual({ service_tier: "default", fast_mode: "false" });
|
||||
});
|
||||
|
||||
test("setAgentOptions hands the provider only the keys the patch sets", async () => {
|
||||
const { manager, client, storage, agentId } = await createOptionsAgent({ web_search: true });
|
||||
|
||||
|
||||
@@ -68,6 +68,7 @@ import {
|
||||
applyProviderOptionsPatch,
|
||||
exposeFeatureValuesToHook,
|
||||
convertLegacyOptions,
|
||||
MalformedLegacyOptionError,
|
||||
resolveAdapter,
|
||||
foldHookFeatureValues,
|
||||
type ProviderOptionsPatch,
|
||||
@@ -2578,14 +2579,28 @@ export class AgentManager {
|
||||
/**
|
||||
* What an agent of this provider runs with, given its own options: the defaults under them.
|
||||
* Stored records are read through here before they are reopened, so the legacy conversion
|
||||
* runs here too; a record converted on open passes through unchanged.
|
||||
* runs here too; a record converted on open passes through unchanged. A legacy value the
|
||||
* conversion cannot read stays as stored: this describes the record, and opening or changing
|
||||
* the agent is what rejects the value.
|
||||
*/
|
||||
effectiveOptionsFor(provider: AgentProvider, own: ProviderOptions | undefined): ProviderOptions {
|
||||
const client = this.clients.get(provider);
|
||||
const converted = this.convertLegacyOptions(provider, own);
|
||||
const converted = this.convertStoredOptions(provider, own);
|
||||
return client ? this.launchOptionsFor({ client, own: converted }) : (converted ?? {});
|
||||
}
|
||||
|
||||
private convertStoredOptions(
|
||||
provider: AgentProvider,
|
||||
own: ProviderOptions | undefined,
|
||||
): ProviderOptions | undefined {
|
||||
try {
|
||||
return this.convertLegacyOptions(provider, own);
|
||||
} catch (error) {
|
||||
if (error instanceof MalformedLegacyOptionError) return own;
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async setTitle(agentId: string, title: string): Promise<void> {
|
||||
const agent = this.requireAgent(agentId);
|
||||
const normalizedTitle = title.trim();
|
||||
|
||||
@@ -40,6 +40,14 @@ interface LegacyOptionsInput<O> {
|
||||
options: O;
|
||||
}
|
||||
|
||||
/** A legacy option value the conversion cannot read. */
|
||||
export class MalformedLegacyOptionError extends Error {
|
||||
constructor(message: string) {
|
||||
super(message);
|
||||
this.name = "MalformedLegacyOptionError";
|
||||
}
|
||||
}
|
||||
|
||||
export function convertLegacyOptions(
|
||||
input: LegacyOptionsInput<Record<string, unknown>>,
|
||||
): Record<string, unknown>;
|
||||
@@ -53,7 +61,7 @@ export function convertLegacyOptions(
|
||||
if (provider !== "codex" || !options || !("fast_mode" in options)) return options;
|
||||
const { fast_mode: legacy, ...rest } = options;
|
||||
if (legacy !== undefined && legacy !== null && typeof legacy !== "boolean") {
|
||||
throw new Error("Codex fast_mode must be true, false or null");
|
||||
throw new MalformedLegacyOptionError("Codex fast_mode must be true, false or null");
|
||||
}
|
||||
if ("service_tier" in rest || legacy === undefined) return rest;
|
||||
if (legacy === null) return { ...rest, service_tier: null };
|
||||
|
||||
Reference in New Issue
Block a user