Files
openclaw/src/agents/agent-auth-discovery.ts
T
Peter SteinbergerandGitHub 06f5f73e47 refactor: own model discovery by runtime lifecycle (#111173)
* refactor(agents): prepare model runtime catalogs

Build lifecycle-owned model and auth snapshots, carry prepared stores into hot agent paths, and serialize config/auth publication.

Credits @zeroaltitude's #90741 investigation and benchmark approach.

* refactor: finish lifecycle-owned model discovery

* fix: align prepared model catalog contracts

* test: align lifecycle catalog mocks

* test: fix prepared catalog type fixtures

* refactor: split prepared model runtime ownership

* fix: import prepared runtime replacement gate type

* test: split media runtime coverage

* test: preserve image auth fixture key types

* test: isolate lifecycle gate fixtures

* chore: keep release changelog owned

* refactor: finish prepared model catalog migration

* test: keep catalog review fixtures scanner-safe

* refactor: preserve lifecycle model runtime ownership

* fix: close prepared runtime lifecycle races

* fix: preserve compaction workspace fallback

* chore: document btw generation rebinding

* fix: preserve prepared generation boundaries

* fix: keep model-list discovery flag explicit

* fix: serialize standalone model runtime activation

* refactor: migrate subagent model catalog lookup

* refactor: clarify doctor catalog lookup seam

* chore: refresh plugin sdk api baseline

* test: migrate swarm catalog dependency

* refactor(telegram): rename runtime catalog seam

* refactor: extract model-aware tool context

* test(models): isolate lifecycle catalog fixtures

* refactor(agents): avoid btw parameter rebinding

* fix(net-policy): align root ipaddr dependency

* fix(build): keep net policy dependency bundled

* fix(deadcode): document net policy compile dependency
2026-07-19 05:30:54 -07:00

96 lines
3.6 KiB
TypeScript

/** Discovers agent runtime credentials from auth profiles, env, and synthetic providers. */
import { resolveProviderSyntheticAuthWithPlugin } from "../plugins/provider-runtime.js";
import { resolveRuntimeSyntheticAuthProviderRefs } from "../plugins/synthetic-auth.runtime.js";
import {
resolveAgentCredentialMapFromStore,
type AgentCredentialMap,
} from "./agent-auth-credentials.js";
import {
addEnvBackedAgentCredentials,
type AgentDiscoveryAuthLookupOptions,
} from "./agent-auth-discovery-core.js";
import type { ExternalCliAuthDiscovery } from "./auth-profiles/external-cli-discovery.js";
import {
ensureAuthProfileStore,
ensureAuthProfileStoreWithoutExternalProfiles,
loadAuthProfileStoreWithoutExternalProfiles,
loadAuthProfileStoreForRuntime,
loadAuthProfileStoreForSecretsRuntime,
} from "./auth-profiles/store.js";
/** Options for discovering credentials without prompting for secret material. */
export type DiscoverAuthStorageOptions = {
externalCli?: ExternalCliAuthDiscovery;
inheritedAuthDir?: string;
readOnly?: boolean;
skipExternalAuthProfiles?: boolean;
skipCredentials?: boolean;
syntheticAuthProviderRefs?: Iterable<string>;
} & AgentDiscoveryAuthLookupOptions;
/** Resolves agent credentials from auth profiles, env, and synthetic auth hooks. */
export function resolveAgentCredentialsForDiscovery(
agentDir: string,
options?: DiscoverAuthStorageOptions,
): AgentCredentialMap {
const storeOptions = {
allowKeychainPrompt: false,
...(options?.config ? { config: options.config } : {}),
...(options?.externalCli ? { externalCli: options.externalCli } : {}),
...(options?.inheritedAuthDir ? { inheritedAuthDir: options.inheritedAuthDir } : {}),
};
const store =
options?.skipExternalAuthProfiles === true
? options.readOnly === true
? loadAuthProfileStoreWithoutExternalProfiles(
agentDir,
options.inheritedAuthDir ? { inheritedAuthDir: options.inheritedAuthDir } : undefined,
)
: ensureAuthProfileStoreWithoutExternalProfiles(agentDir, {
allowKeychainPrompt: false,
...(options?.inheritedAuthDir ? { inheritedAuthDir: options.inheritedAuthDir } : {}),
})
: options?.readOnly === true
? options.externalCli || options.config || options.inheritedAuthDir
? loadAuthProfileStoreForRuntime(agentDir, { readOnly: true, ...storeOptions })
: loadAuthProfileStoreForSecretsRuntime(agentDir)
: ensureAuthProfileStore(agentDir, storeOptions);
const credentials = addEnvBackedAgentCredentials(
resolveAgentCredentialMapFromStore(store, {
includeSecretRefPlaceholders: options?.readOnly === true,
config: options?.config,
}),
{
config: options?.config,
workspaceDir: options?.workspaceDir,
env: options?.env,
},
);
const syntheticAuthProviderRefs =
options?.syntheticAuthProviderRefs ?? resolveRuntimeSyntheticAuthProviderRefs();
for (const provider of syntheticAuthProviderRefs) {
if (credentials[provider]) {
continue;
}
// Synthetic auth is a plugin/runtime fallback. Only fill empty providers so
// persisted profiles and env-backed credentials remain authoritative.
const resolved = resolveProviderSyntheticAuthWithPlugin({
provider,
context: {
config: undefined,
provider,
providerConfig: undefined,
},
});
const apiKey = resolved?.apiKey?.trim();
if (!apiKey) {
continue;
}
credentials[provider] = {
type: "api_key",
key: apiKey,
};
}
return credentials;
}