mirror of
https://github.com/getpaseo/paseo.git
synced 2026-11-04 23:44:41 +00:00
The agent snapshot's `options` are the state and `controls` only draw them. Running and closed agents draw from the snapshot; drafts and profile forms ask `provider.controls.list.request` with their `providerOptions`, so aliases such as a legacy Fast profile's `service_tier: "fast"` are resolved once, by the daemon, and the draft keeps Fast highlighted. A draft adds only the user's edits and each provider's last-used control values; applying a profile seeds its non-control options (e.g. `sandbox_mode`) into the draft, and a profile form saves them back instead of pruning to the controls it can draw. A daemon without `server_info.features.providerOptionControls` still sends `features` and `featureValues`. `LegacyProviderOptions` in the client package is the one place that translates snapshots, draft listings, create and apply requests, and daemon-config profiles, so the app never branches on it. Persisted preferences and tab layouts rename `featureValues` through tagged COMPAT preprocessors. The features/controls bridge moves from the server into the protocol package so the client can reuse it.
30 lines
1.3 KiB
TypeScript
30 lines
1.3 KiB
TypeScript
import type { AgentOptionControl, ProviderOptions } from "@getpaseo/protocol/agent-types";
|
|
|
|
/**
|
|
* What a draft agent shows and runs with, from its layers:
|
|
* - `seed`: options the draft started from (a profile, a forked agent). The daemon resolves them
|
|
* into `resolved`, so a legacy Fast profile is drawn as the model's Fast tier.
|
|
* - `persisted`: last-used control values, applied to keys the seed leaves alone and that the
|
|
* provider still draws a control for.
|
|
* - `edits`: toggles made in this draft.
|
|
*/
|
|
export function composeDraftOptions(input: {
|
|
seed: ProviderOptions;
|
|
persisted: ProviderOptions;
|
|
edits: ProviderOptions;
|
|
controls: readonly AgentOptionControl[] | undefined;
|
|
resolved: ProviderOptions | undefined;
|
|
}): { shown: ProviderOptions; own: ProviderOptions | undefined } {
|
|
const { seed, persisted, edits, controls, resolved } = input;
|
|
const controlKeys = new Set((controls ?? []).map((control) => control.key));
|
|
const remembered = Object.fromEntries(
|
|
Object.entries(persisted).filter(([key]) => controlKeys.has(key) && !(key in seed)),
|
|
);
|
|
const own = { ...seed, ...remembered, ...edits };
|
|
return {
|
|
shown: { ...resolved, ...remembered, ...edits },
|
|
// The daemon resolves defaults again on create, so only what differs from them travels.
|
|
own: Object.keys(own).length > 0 ? own : undefined,
|
|
};
|
|
}
|