316 lines · 11.3 KB · TypeScript
RawDownload
import {  isProviderDriverKind,  isProviderAvailable,  resolveProviderInstanceEnabled,  type ModelSelection,  type ProjectId,  type ProviderDriverKind,  type ServerProvider,  ServerSettings,  type ServerSettingsPatch,} from "@t3tools/contracts";import * as Option from "effect/Option";import * as Schema from "effect/Schema";import { deepMerge } from "./Struct.ts";import { fromLenientJson } from "./schemaJson.ts";import { createModelSelection } from "./model.ts";import {  getBackgroundActivityBaseProfile,  normalizeBackgroundActivitySettings,  normalizeServerBackgroundActivitySettings,  resolveBackgroundActivitySettings,} from "./backgroundActivitySettings.ts"; const ServerSettingsJson = fromLenientJson(ServerSettings);const decodeServerSettingsJson = Schema.decodeUnknownOption(ServerSettingsJson); export function resolveProjectAgentBrowserAccess(  settings: Pick<ServerSettings, "enableAgentBrowserAccess" | "projectAgentBrowserAccessOverrides">,  projectId: ProjectId,): boolean {  return (    settings.projectAgentBrowserAccessOverrides[projectId] ?? settings.enableAgentBrowserAccess  );} export function resolveProjectAutoPull(  settings: Pick<ServerSettings, "defaultAutoPull" | "projectAutoPullOverrides">,  projectId: ProjectId,  legacyAutoPull: boolean | undefined,): boolean {  // Existing opt-ins stay enabled until explicitly overridden or reset.  return (    settings.projectAutoPullOverrides[projectId] ??    (legacyAutoPull === true || settings.defaultAutoPull)  );} type LegacyProviderSettings = ServerSettings["providers"][keyof ServerSettings["providers"]]; const getLegacyProviderSettings = (  settings: ServerSettings,  provider: ProviderDriverKind,): LegacyProviderSettings | undefined =>  (settings.providers as Record<string, LegacyProviderSettings | undefined>)[provider]; export function isModelSelectionProviderEnabled(  settings: ServerSettings,  selection: ModelSelection,): boolean {  const instanceConfig = settings.providerInstances[selection.instanceId];  if (instanceConfig !== undefined) {    return resolveProviderInstanceEnabled(instanceConfig);  }   return (    isProviderDriverKind(selection.instanceId) &&    getLegacyProviderSettings(settings, selection.instanceId)?.enabled === true  );} export function resolveSourceControlWriterModelSelection(  settings: ServerSettings,  providers?: ReadonlyArray<ServerProvider>,): ModelSelection {  const selection = settings.sourceControlWriterModelSelection;  if (!selection || !isModelSelectionProviderEnabled(settings, selection)) {    return settings.textGenerationModelSelection;  }  if (providers === undefined) {    return selection;  }   const provider = providers.find((candidate) => candidate.instanceId === selection.instanceId);  return provider?.enabled === true && isProviderAvailable(provider)    ? selection    : settings.textGenerationModelSelection;} export interface PersistedServerObservabilitySettings {  readonly otlpTracesUrl: string | undefined;  readonly otlpMetricsUrl: string | undefined;} function normalizePersistedServerSettingString(  value: string | null | undefined,): string | undefined {  const trimmed = value?.trim();  return trimmed && trimmed.length > 0 ? trimmed : undefined;} function extractPersistedServerObservabilitySettings(input: {  readonly observability?: {    readonly otlpTracesUrl?: string;    readonly otlpMetricsUrl?: string;  };}): PersistedServerObservabilitySettings {  return {    otlpTracesUrl: normalizePersistedServerSettingString(input.observability?.otlpTracesUrl),    otlpMetricsUrl: normalizePersistedServerSettingString(input.observability?.otlpMetricsUrl),  };} export function parsePersistedServerObservabilitySettings(  raw: string,): PersistedServerObservabilitySettings {  const decoded = decodeServerSettingsJson(raw);  if (Option.isSome(decoded)) {    return extractPersistedServerObservabilitySettings(decoded.value);  }  return { otlpTracesUrl: undefined, otlpMetricsUrl: undefined };} function shouldReplaceTextGenerationModelSelection(  patch: ServerSettingsPatch["textGenerationModelSelection"] | undefined,): boolean {  return Boolean(patch && (patch.instanceId !== undefined || patch.model !== undefined));} function mergeModelSelectionOptionsById(input: {  current: ReadonlyArray<{ readonly id: string; readonly value: string | boolean }> | undefined;  patch: ReadonlyArray<{ readonly id: string; readonly value: string | boolean }> | undefined;}): Array<{ id: string; value: string | boolean }> | undefined {  if (input.patch === undefined) {    return input.current ? [...input.current] : undefined;  }  if (input.patch.length === 0) {    return undefined;  }   const merged = new Map((input.current ?? []).map((selection) => [selection.id, selection.value]));  for (const selection of input.patch) {    merged.set(selection.id, selection.value);  }  return [...merged.entries()].map(([id, value]) => ({ id, value }));} /** Upsert each patched entry; `null` removes it. Entries the patch omits are untouched. */function mergeSettingsEntries<Value>(  current: Readonly<Record<string, Value>>,  patch: Readonly<Record<string, Value | null>>,): Record<string, Value> {  const next = new Map(Object.entries(current));  for (const [id, config] of Object.entries(patch)) {    if (config === null) {      next.delete(id);    } else {      next.set(id, config);    }  }  return Object.fromEntries(next);} export function applyServerSettingsPatch(  current: ServerSettings,  patch: ServerSettingsPatch,): ServerSettings {  const selectionPatch = patch.textGenerationModelSelection;  const {    automaticGitFetchInterval,    providerHealthRefreshInterval,    backgroundActivityProfile,    backgroundActivity,    // Merged per entry below; its `null` removals must not reach deepMerge.    usageLimitSources: usageLimitSourcesPatch,    usagePriceOverrides: usagePriceOverridesPatch,    projectAgentBrowserAccessOverrides: projectAgentBrowserAccessOverridesPatch,    projectAutoPullOverrides: projectAutoPullOverridesPatch,    ...patchForMerge  } = patch;  const currentBackgroundActivity = normalizeServerBackgroundActivitySettings(current);  const backgroundActivityPatch =    backgroundActivityProfile !== undefined      ? {          schemaVersion: 1 as const,          profile:            automaticGitFetchInterval !== undefined || providerHealthRefreshInterval !== undefined              ? ("custom" as const)              : backgroundActivityProfile,          ...(automaticGitFetchInterval !== undefined || providerHealthRefreshInterval !== undefined            ? { baseProfile: backgroundActivityProfile }            : {}),          overrides: {            ...(automaticGitFetchInterval !== undefined ? { automaticGitFetchInterval } : {}),            ...(providerHealthRefreshInterval !== undefined              ? { providerHealthRefreshInterval }              : {}),          },        }      : automaticGitFetchInterval !== undefined || providerHealthRefreshInterval !== undefined        ? {            schemaVersion: 1 as const,            profile: "custom" as const,            baseProfile: getBackgroundActivityBaseProfile(currentBackgroundActivity),            overrides: {              ...(currentBackgroundActivity.profile === "custom"                ? currentBackgroundActivity.overrides                : {}),              ...(automaticGitFetchInterval !== undefined ? { automaticGitFetchInterval } : {}),              ...(providerHealthRefreshInterval !== undefined                ? { providerHealthRefreshInterval }                : {}),            },          }        : undefined;  const next = deepMerge(current, patchForMerge);  const nextWithReplacementsBase = {    ...next,    ...(backgroundActivity !== undefined      ? {          backgroundActivity: {            ...deepMerge(currentBackgroundActivity, backgroundActivity),            ...(backgroundActivity.overrides !== undefined              ? { overrides: backgroundActivity.overrides }              : {}),          },        }      : { backgroundActivity: currentBackgroundActivity }),    ...(backgroundActivity === undefined && backgroundActivityPatch !== undefined      ? { backgroundActivity: backgroundActivityPatch }      : {}),    ...(patch.providerInstances !== undefined      ? { providerInstances: patch.providerInstances }      : {}),    ...(projectAgentBrowserAccessOverridesPatch !== undefined      ? {          projectAgentBrowserAccessOverrides: mergeSettingsEntries(            current.projectAgentBrowserAccessOverrides,            projectAgentBrowserAccessOverridesPatch,          ),        }      : {}),    ...(projectAutoPullOverridesPatch !== undefined      ? {          projectAutoPullOverrides: mergeSettingsEntries(            current.projectAutoPullOverrides,            projectAutoPullOverridesPatch,          ),        }      : {}),    ...(patch.defaultModelSelection !== undefined      ? { defaultModelSelection: patch.defaultModelSelection }      : {}),    ...(patch.defaultProjectScripts !== undefined      ? { defaultProjectScripts: patch.defaultProjectScripts }      : {}),    ...(patch.projectScriptOverrides !== undefined      ? {          projectScriptOverrides: {            ...current.projectScriptOverrides,            ...patch.projectScriptOverrides,          },        }      : {}),    ...(usageLimitSourcesPatch !== undefined      ? {          usageLimitSources: mergeSettingsEntries(            current.usageLimitSources,            usageLimitSourcesPatch,          ),        }      : {}),    ...(usagePriceOverridesPatch !== undefined      ? {          usagePriceOverrides: mergeSettingsEntries(            current.usagePriceOverrides,            usagePriceOverridesPatch,          ),        }      : {}),    ...(patch.sourceControlWriterModelSelection !== undefined      ? { sourceControlWriterModelSelection: patch.sourceControlWriterModelSelection }      : {}),    ...(automaticGitFetchInterval !== undefined ? { automaticGitFetchInterval } : {}),    ...(providerHealthRefreshInterval !== undefined ? { providerHealthRefreshInterval } : {}),  };  const normalizedBackgroundActivity = normalizeBackgroundActivitySettings(    nextWithReplacementsBase.backgroundActivity,  );  const resolvedBackgroundActivity = resolveBackgroundActivitySettings(    normalizedBackgroundActivity,  );  const nextWithReplacements = {    ...nextWithReplacementsBase,    backgroundActivity: normalizedBackgroundActivity,    automaticGitFetchInterval: resolvedBackgroundActivity.automaticGitFetchInterval,    providerHealthRefreshInterval: resolvedBackgroundActivity.providerHealthRefreshInterval,    backgroundActivityProfile: resolvedBackgroundActivity.profile,  };  if (!selectionPatch) {    return nextWithReplacements;  }   const instanceId = selectionPatch.instanceId ?? current.textGenerationModelSelection.instanceId;  const model = selectionPatch.model ?? current.textGenerationModelSelection.model;  const options = shouldReplaceTextGenerationModelSelection(selectionPatch)    ? selectionPatch.options    : mergeModelSelectionOptionsById({        current: current.textGenerationModelSelection.options,        patch: selectionPatch.options,      });   return {    ...nextWithReplacements,    textGenerationModelSelection: createModelSelection(instanceId, model, options),  };}