docs: document auth profile discovery helpers

This commit is contained in:
Peter Steinberger
2026-06-03 22:23:37 -04:00
parent a2a4924679
commit 003bb8546d
5 changed files with 34 additions and 0 deletions
@@ -5,6 +5,7 @@ import {
type ExternalCliAuthScope,
} from "./external-cli-scope.js";
/** External CLI auth discovery mode used while loading auth profile stores. */
export type ExternalCliAuthDiscovery =
| {
mode: "none";
@@ -24,6 +25,8 @@ export type ExternalCliAuthDiscovery =
profileIds?: Iterable<string>;
};
// External CLI auth discovery is scoped to avoid keychain prompts or broad CLI
// probing unless the caller is explicitly resolving a provider/profile set.
type ProviderAuthDiscoveryParams = {
cfg?: OpenClawConfig;
provider: string;
@@ -47,6 +50,7 @@ function normalizeStringList(values: Iterable<string | undefined>): string[] {
return normalizeTrimmedStringList([...values]);
}
/** Disables external CLI auth discovery. */
export function externalCliDiscoveryNone(params?: {
config?: OpenClawConfig;
}): ExternalCliAuthDiscovery {
@@ -57,6 +61,7 @@ export function externalCliDiscoveryNone(params?: {
};
}
/** Allows discovery of already-existing external CLI auth profiles. */
export function externalCliDiscoveryExisting(params?: {
config?: OpenClawConfig;
allowKeychainPrompt?: boolean;
@@ -70,6 +75,7 @@ export function externalCliDiscoveryExisting(params?: {
};
}
/** Allows external CLI auth discovery for specific providers and/or profiles. */
export function externalCliDiscoveryScoped(params: {
config?: OpenClawConfig;
providerIds?: Iterable<string>;
@@ -87,6 +93,7 @@ export function externalCliDiscoveryScoped(params: {
};
}
/** Builds external CLI discovery options for a provider auth lookup. */
export function externalCliDiscoveryForProviderAuth(
params: ProviderAuthDiscoveryParams,
): ExternalCliAuthDiscovery {
@@ -99,6 +106,7 @@ export function externalCliDiscoveryForProviderAuth(
});
}
/** Builds external CLI discovery options for config status checks. */
export function externalCliDiscoveryForConfigStatus(
params: ConfigStatusDiscoveryParams,
): ExternalCliAuthDiscovery {
@@ -110,6 +118,7 @@ export function externalCliDiscoveryForConfigStatus(
});
}
/** Builds external CLI discovery options for a provider set. */
export function externalCliDiscoveryForProviders(
params: ProviderSetDiscoveryParams,
): ExternalCliAuthDiscovery {
@@ -6,11 +6,14 @@ import {
import type { AgentModelConfig } from "../../config/types.agents-shared.js";
import type { OpenClawConfig } from "../../config/types.openclaw.js";
/** Provider/profile ids that may need external CLI auth discovery. */
export type ExternalCliAuthScope = {
providerIds: string[];
profileIds: string[];
};
// Include both raw and normalized provider ids so config aliases and canonical
// provider ids can both match external CLI auth providers.
function addProviderScopeId(out: Set<string>, value: string | undefined): void {
const raw = value?.trim();
if (!raw) {
@@ -23,6 +26,8 @@ function addProviderScopeId(out: Set<string>, value: string | undefined): void {
}
}
// Model refs are provider/model strings. Only the provider prefix matters for
// deciding which external CLI auth source may be queried.
function addProviderScopeFromModelRef(out: Set<string>, value: string | undefined): void {
const raw = value?.trim();
if (!raw) {
@@ -42,6 +47,8 @@ function addProviderScopeFromModelConfig(out: Set<string>, model: AgentModelConf
}
}
// Some runtime ids imply an external CLI auth source even when the model ref is
// not provider-qualified, so include known CLI runtimes in provider scope.
function addExternalCliRuntimeScope(out: Set<string>, value: string | undefined): void {
const normalized = normalizeProviderId(value?.trim() ?? "");
if (
@@ -67,6 +74,7 @@ function addExternalCliRuntimeScopeFromModelMap(
}
}
/** Resolves external CLI auth discovery scope from configured auth/model surfaces. */
export function resolveExternalCliAuthScopeFromConfig(
cfg: OpenClawConfig,
): ExternalCliAuthScope | undefined {
+7
View File
@@ -1,17 +1,21 @@
import { AUTH_STORE_VERSION } from "./constants.js";
import type { AuthProfileCredential, AuthProfileSecretsStore, AuthProfileStore } from "./types.js";
/** Reason a credential is or is not portable into an agent copy. */
export type AuthProfilePortabilityReason =
| "portable-static-credential"
| "non-portable-oauth-refresh-token"
| "credential-opted-out"
| "oauth-provider-opted-in";
/** Portability decision for copying credentials into an agent-local store. */
export type AuthProfilePortability = {
portable: boolean;
reason: AuthProfilePortabilityReason;
};
// OAuth refresh material is not copied by default because it can be tied to a
// local profile/keychain flow. Static credentials are portable unless opted out.
function hasAgentCopyOverride(credential: AuthProfileCredential): boolean | undefined {
return typeof credential.copyToAgents === "boolean" ? credential.copyToAgents : undefined;
}
@@ -25,6 +29,7 @@ function hasCopyableOAuthMaterial(credential: AuthProfileCredential): boolean {
);
}
/** Resolves whether a credential can be copied into an agent-local store. */
export function resolveAuthProfilePortability(
credential: AuthProfileCredential,
): AuthProfilePortability {
@@ -43,12 +48,14 @@ export function resolveAuthProfilePortability(
return { portable: true, reason: "portable-static-credential" };
}
/** Returns true when a credential can be copied into an agent-local store. */
export function isAuthProfileCredentialPortableForAgentCopy(
credential: AuthProfileCredential,
): boolean {
return resolveAuthProfilePortability(credential).portable;
}
/** Builds an agent-copy store containing only portable credentials. */
export function buildPortableAuthProfileSecretsStoreForAgentCopy(store: AuthProfileStore): {
store: AuthProfileSecretsStore;
copiedProfileIds: string[];
+2
View File
@@ -2,10 +2,12 @@ import { uniqueStrings } from "@openclaw/normalization-core/string-normalization
import { resolveProviderIdForAuth } from "../provider-auth-aliases.js";
import type { AuthProfileStore } from "./types.js";
/** Deduplicates profile ids while preserving first-seen order. */
export function dedupeProfileIds(profileIds: string[]): string[] {
return uniqueStrings(profileIds);
}
/** Lists auth profile ids whose credential provider matches the requested provider. */
export function listProfilesForProvider(store: AuthProfileStore, provider: string): string[] {
const providerKey = resolveProviderIdForAuth(provider);
return Object.entries(store.profiles)
@@ -4,10 +4,13 @@ import type { AuthProfileStore } from "./types.js";
const runtimeAuthStoreSnapshots = new Map<string, AuthProfileStore>();
// Runtime snapshots are keyed by the resolved auth store path so default-agent
// and per-agent stores do not overwrite each other.
function resolveRuntimeStoreKey(agentDir?: string): string {
return resolveAuthStorePath(agentDir);
}
/** Reads a cloned runtime auth profile store snapshot for an agent dir. */
export function getRuntimeAuthProfileStoreSnapshot(
agentDir?: string,
): AuthProfileStore | undefined {
@@ -15,10 +18,12 @@ export function getRuntimeAuthProfileStoreSnapshot(
return store ? cloneAuthProfileStore(store) : undefined;
}
/** Returns true when a runtime snapshot exists for an agent dir. */
export function hasRuntimeAuthProfileStoreSnapshot(agentDir?: string): boolean {
return runtimeAuthStoreSnapshots.has(resolveRuntimeStoreKey(agentDir));
}
/** Returns true when requested or main runtime snapshots contain profiles. */
export function hasAnyRuntimeAuthProfileStoreSource(agentDir?: string): boolean {
const requestedStore = getRuntimeAuthProfileStoreSnapshot(agentDir);
if (requestedStore && Object.keys(requestedStore.profiles).length > 0) {
@@ -31,6 +36,7 @@ export function hasAnyRuntimeAuthProfileStoreSource(agentDir?: string): boolean
return Boolean(mainStore && Object.keys(mainStore.profiles).length > 0);
}
/** Replaces all runtime auth profile snapshots with cloned entries. */
export function replaceRuntimeAuthProfileStoreSnapshots(
entries: Array<{ agentDir?: string; store: AuthProfileStore }>,
): void {
@@ -43,10 +49,12 @@ export function replaceRuntimeAuthProfileStoreSnapshots(
}
}
/** Clears all runtime auth profile snapshots. */
export function clearRuntimeAuthProfileStoreSnapshots(): void {
runtimeAuthStoreSnapshots.clear();
}
/** Stores a cloned runtime auth profile snapshot for an agent dir. */
export function setRuntimeAuthProfileStoreSnapshot(
store: AuthProfileStore,
agentDir?: string,