File size: 4,972 Bytes
e249c6d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/**
 * Builds auth forwarding decisions for prepared runtime plans. Provider aliases
 * and harness auth owners are resolved before session auth profiles can be
 * safely forwarded.
 */
import type { OpenClawConfig } from "../../config/types.openclaw.js";
import type { PluginMetadataSnapshot } from "../../plugins/plugin-metadata-snapshot.types.js";
import { normalizeOptionalAgentRuntimeId } from "../agent-runtime-id.js";
import {
  type ProviderAuthAliasLookupParams,
  resolveProviderIdForAuth,
} from "../provider-auth-aliases.js";
import type { AgentRuntimeAuthPlan } from "./types.js";

const CODEX_HARNESS_AUTH_PROVIDER = "openai";
// Empty metadata disables plugin alias lookups without changing the downstream
// resolver contract, matching the "plugins disabled" runtime-plan state.
const EMPTY_PROVIDER_AUTH_ALIAS_METADATA = {
  plugins: [],
} satisfies NonNullable<ProviderAuthAliasLookupParams["metadataSnapshot"]>;

function resolveHarnessAuthProvider(params: {
  harnessId?: string;
  harnessRuntime?: string;
}): string | undefined {
  const harnessId = normalizeOptionalAgentRuntimeId(params.harnessId);
  const runtime = normalizeOptionalAgentRuntimeId(params.harnessRuntime);
  return harnessId === "codex" || runtime === "codex" ? CODEX_HARNESS_AUTH_PROVIDER : undefined;
}

/** Builds the auth forwarding plan for one resolved agent runtime. */
export function buildAgentRuntimeAuthPlan(params: {
  provider: string;
  modelId?: string;
  authProfileProvider?: string;
  authProfileMode?: string;
  sessionAuthProfileId?: string;
  sessionAuthProfileSource?: "auto" | "user" | "user-link";
  sessionAuthProfileCandidateIds?: string[];
  modelRoute?: AgentRuntimeAuthPlan["modelRoute"];
  deferredRouteSupport?: AgentRuntimeAuthPlan["deferredRouteSupport"];
  credentialSource?: AgentRuntimeAuthPlan["credentialSource"];
  config?: OpenClawConfig;
  workspaceDir?: string;
  env?: NodeJS.ProcessEnv;
  metadataSnapshot?: Pick<PluginMetadataSnapshot, "plugins">;
  providerAuthAliasesEnabled?: boolean;
  harnessId?: string;
  harnessRuntime?: string;
  allowHarnessAuthProfileForwarding?: boolean;
}): AgentRuntimeAuthPlan {
  const providerAuthAliasesEnabled =
    params.providerAuthAliasesEnabled ?? params.config?.plugins?.enabled !== false;
  const metadataSnapshot =
    params.metadataSnapshot ??
    (providerAuthAliasesEnabled ? undefined : EMPTY_PROVIDER_AUTH_ALIAS_METADATA);
  const aliasLookupParams = {
    config: params.config,
    workspaceDir: params.workspaceDir,
    env: params.env,
    ...(metadataSnapshot ? { metadataSnapshot } : {}),
  };
  const providerForAuth = resolveProviderIdForAuth(params.provider, aliasLookupParams);
  const authProfileProviderForAuth =
    params.authProfileProvider !== undefined
      ? resolveProviderIdForAuth(params.authProfileProvider, {
          ...aliasLookupParams,
          storedCredential: true,
        })
      : providerForAuth;
  const harnessAuthProvider = resolveHarnessAuthProvider(params);
  const harnessProviderForAuth = harnessAuthProvider
    ? resolveProviderIdForAuth(harnessAuthProvider, aliasLookupParams)
    : undefined;
  const harnessCanForwardProfile =
    params.allowHarnessAuthProfileForwarding !== false &&
    harnessProviderForAuth &&
    harnessProviderForAuth === authProfileProviderForAuth;
  const providerCanForwardProfile =
    !harnessProviderForAuth && providerForAuth === authProfileProviderForAuth;
  const canForwardProfile = providerCanForwardProfile || harnessCanForwardProfile;
  const forwardedAuthProfileId = canForwardProfile ? params.sessionAuthProfileId : undefined;

  // Forward only when the selected provider/harness resolves to the same auth
  // owner as the stored session profile; otherwise the runtime must choose auth.
  return {
    providerForAuth,
    ...(params.modelId ? { modelId: params.modelId } : {}),
    authProfileProviderForAuth,
    ...(harnessProviderForAuth ? { harnessAuthProvider: harnessProviderForAuth } : {}),
    ...(canForwardProfile ? { forwardedAuthProfileId } : {}),
    ...(canForwardProfile && params.sessionAuthProfileId && params.sessionAuthProfileSource
      ? {
          // Person-linked pins forward at user-pin strength; the wire plan
          // keeps the closed auto/user contract.
          forwardedAuthProfileSource: params.sessionAuthProfileSource === "auto" ? "auto" : "user",
        }
      : {}),
    ...(canForwardProfile && params.sessionAuthProfileCandidateIds?.length
      ? { forwardedAuthProfileCandidateIds: params.sessionAuthProfileCandidateIds }
      : {}),
    ...(canForwardProfile && params.authProfileMode
      ? { selectedAuthMode: params.authProfileMode }
      : {}),
    ...(params.modelRoute ? { modelRoute: params.modelRoute } : {}),
    ...(params.deferredRouteSupport ? { deferredRouteSupport: params.deferredRouteSupport } : {}),
    ...(params.credentialSource ? { credentialSource: params.credentialSource } : {}),
  } satisfies AgentRuntimeAuthPlan;
}