resolveEffectiveCliArgs function

({CliArgs args, EnvProviderPreconfig? faPreconfig, String? incompatibleSavedEndpoint, String provider, String? unknownSavedProvider}) resolveEffectiveCliArgs(
  1. CliArgs parsed,
  2. CliConfig saved, {
  3. required Map<String, String> env,
})

Provider/model restoration. Precedence: an explicit --provider flag (full manual control, preconfigs disabled) > the FA_PROVIDER_* env declaration (faProviderPreconfig) > the saved provider: (the persisted /provider switch) > the parsed default.

The saved kind restores whenever it resolves through the catalog (resolveCliProviderSpec — every catalog name AND adapter kind, chatgpt-codex included; coverage by construction, issue #760) and restores AS THE RESOLVED SPEC'S KIND: a saved catalog name (openai, chatgpt) resolves to its adapter kind here, because everything downstream (AgentCliConfig.providerKind → providerStreamFunction) speaks kinds only. A saved id NO version knows must never brick the boot: it is reported back as unknownSavedProvider and the parsed default (a known provider) takes over — the executable prints the loud named warning (bad value, file, fallback taken) and keeps booting.

The preconfig supplies model/baseUrl too, so the saved restore never leaks through while it is active (--model/--base-url flags still override individual fields). No env-key auto-pick: a bare API key in the environment never activates a provider — the model would be an implicit default, and providers carry none by design. FA_PROVIDER_* stays: it names the model explicitly. The environment is injected (env is required): the CLI passes Platform.environment, tests pass exactly the map they mean — resolution never reads ambient process state.

Returns the effective CliArgs, the resolved provider kind — the same value, the explicit record field saves the caller a re-derivation — the FA_PROVIDER_* declaration when one is active (the caller needs it for the roles pinning, the key decision and the extra redaction), the saved provider id when it was unrecognizable, and the saved provider id when the persisted provider/baseUrl pair was unservable (endpoint-locked kind, foreign baseUrl — the caller degrades it with a named warning). Both report fields are null otherwise.

Implementation

({
  CliArgs args,
  String provider,
  EnvProviderPreconfig? faPreconfig,
  String? unknownSavedProvider,
  String? incompatibleSavedEndpoint,
})
resolveEffectiveCliArgs(
  CliArgs parsed,
  CliConfig saved, {
  required Map<String, String> env,
}) {
  final faPreconfig = faProviderPreconfig(parsed, saved, env: env);
  final restore = _judgeSavedRestore(saved);
  final restoredKind = restore.endpointConflict ? null : restore.spec?.kind;
  final provider = _bootProvider(
    parsed: parsed,
    faPreconfig: faPreconfig,
    restoredKind: restoredKind,
  );
  final reports = _savedRestoreReports(
    savedRaw: restore.raw,
    savedSpec: restore.spec,
    endpointConflict: restore.endpointConflict,
    explicitOverride: parsed.providerExplicit || faPreconfig != null,
  );
  final modelId = parsed.model ?? faPreconfig?.modelId ?? saved.modelId;
  final baseUrl = parsed.baseUrl ?? faPreconfig?.baseUrl ?? saved.baseUrl;
  final effective = CliArgs(
    model: modelId,
    provider: provider,
    baseUrl: baseUrl,
    visionModel: parsed.visionModel,
    visionBaseUrl: parsed.visionBaseUrl,
    transcribeModel: parsed.transcribeModel,
    transcribeBaseUrl: parsed.transcribeBaseUrl,
    plugins: parsed.plugins,
    promptTemplateDirs: parsed.promptTemplateDirs,
    mode: parsed.mode ?? saved.mode,
    tools: parsed.tools,
    redact: parsed.redact ?? saved.redact,
    cwd: parsed.cwd,
    sessionRoot: parsed.sessionRoot,
    session: parsed.session,
  );
  return (
    args: effective,
    provider: provider,
    faPreconfig: faPreconfig,
    unknownSavedProvider: reports.unknownSavedProvider,
    incompatibleSavedEndpoint: reports.incompatibleSavedEndpoint,
  );
}