



























@@ -2,6 +2,7 @@ import {
22removeProviderAuthProfilesWithLock,
33buildApiKeyCredential,
44ensureApiKeyFromEnvOrPrompt,
5+hasConfiguredSecretInput,
56normalizeOptionalSecretInput,
67type OpenClawConfig,
78type SecretInput,
@@ -363,6 +364,7 @@ async function discoverLmstudioSetupModels(params: {
363364/** Interactive LM Studio setup with connectivity and model-availability checks. */
364365export async function promptAndConfigureLmstudioInteractive(params: {
365366config: OpenClawConfig;
367+agentDir?: string;
366368prompter?: WizardPrompter;
367369secretInputMode?: SecretInputMode;
368370allowSecretRefPrompt?: boolean;
@@ -395,7 +397,7 @@ export async function promptAndConfigureLmstudioInteractive(params: {
395397envLabel: LMSTUDIO_DEFAULT_API_KEY_ENV_VAR,
396398promptMessage: `${LMSTUDIO_PROVIDER_LABEL} API key`,
397399normalize: (value) => value.trim(),
398-validate: (value) => (value.trim() ? undefined : "Required"),
400+validate: () => undefined,
399401prompter: params.prompter,
400402secretInputMode:
401403params.allowSecretRefPrompt === false
@@ -406,30 +408,38 @@ export async function promptAndConfigureLmstudioInteractive(params: {
406408credentialMode = mode;
407409},
408410})
409- : String(
410-await promptText({
411+ : (
412+(await promptText({
411413message: `${LMSTUDIO_PROVIDER_LABEL} API key`,
412-placeholder: "sk-...",
413-validate: (value) => (value?.trim() ? undefined : "Required"),
414-}),
414+placeholder: "sk-... (leave blank if auth is disabled)",
415+validate: () => undefined,
416+})) ?? ""
415417).trim();
416-const credential = params.prompter
417- ? buildApiKeyCredential(
418-PROVIDER_ID,
419-credentialInput ??
420-(implicitRefMode && autoRefEnvKey ? `\${${LMSTUDIO_DEFAULT_API_KEY_ENV_VAR}}` : apiKey),
421-undefined,
422-credentialMode
423- ? { secretInputMode: credentialMode }
424- : implicitRefMode && autoRefEnvKey
425- ? { secretInputMode: "ref" }
426- : undefined,
427-)
428- : {
429-type: "api_key" as const,
430-provider: PROVIDER_ID,
431-key: apiKey,
432-};
418+const normalizedApiKey = normalizeOptionalSecretInput(apiKey);
419+const credentialSource =
420+credentialInput ??
421+(implicitRefMode && autoRefEnvKey ? `\${${LMSTUDIO_DEFAULT_API_KEY_ENV_VAR}}` : apiKey);
422+const shouldStoreCredential = params.prompter
423+ ? credentialMode === "ref" || hasConfiguredSecretInput(credentialSource)
424+ : normalizedApiKey !== undefined;
425+const credential = shouldStoreCredential
426+ ? params.prompter
427+ ? buildApiKeyCredential(
428+PROVIDER_ID,
429+credentialSource,
430+undefined,
431+credentialMode
432+ ? { secretInputMode: credentialMode }
433+ : implicitRefMode && autoRefEnvKey
434+ ? { secretInputMode: "ref" }
435+ : undefined,
436+)
437+ : {
438+type: "api_key" as const,
439+provider: PROVIDER_ID,
440+key: normalizedApiKey ?? apiKey,
441+}
442+ : undefined;
433443const existingProvider = params.config.models?.providers?.[PROVIDER_ID];
434444// Auth setup updates auth/profile/provider model fields but does not mutate
435445// user-provided header overrides. Runtime request assembly is the source of truth for auth.
@@ -439,9 +449,19 @@ export async function promptAndConfigureLmstudioInteractive(params: {
439449env: process.env,
440450headers: persistedHeaders,
441451});
452+const hasAuthorizationHeader = hasLmstudioAuthorizationHeader(resolvedHeaders);
453+const setupDiscoveryApiKey =
454+normalizedApiKey ??
455+(shouldUseLmstudioApiKeyPlaceholder({
456+hasModels: true,
457+resolvedApiKey: undefined,
458+ hasAuthorizationHeader,
459+})
460+ ? LMSTUDIO_LOCAL_API_KEY_PLACEHOLDER
461+ : undefined);
442462const setupDiscovery = await discoverLmstudioSetupModels({
443463 baseUrl,
444- apiKey,
464+apiKey: setupDiscoveryApiKey,
445465 ...(resolvedHeaders ? { headers: resolvedHeaders } : {}),
446466timeoutMs: 5000,
447467});
@@ -475,21 +495,29 @@ export async function promptAndConfigureLmstudioInteractive(params: {
475495const defaultModel = setupDiscovery.value.defaultModel;
476496const persistedApiKey =
477497resolvePersistedLmstudioApiKey({
478-currentApiKey: existingProvider?.apiKey,
479-explicitAuth: resolveLmstudioProviderAuthMode(apiKey),
480-fallbackApiKey: LMSTUDIO_DEFAULT_API_KEY_ENV_VAR,
498+currentApiKey: normalizedApiKey ? existingProvider?.apiKey : undefined,
499+explicitAuth: resolveLmstudioProviderAuthMode(normalizedApiKey),
500+fallbackApiKey: normalizedApiKey ? LMSTUDIO_DEFAULT_API_KEY_ENV_VAR : undefined,
481501preferFallbackApiKey: true,
482502hasModels: discoveredModels.length > 0,
483-hasAuthorizationHeader: hasLmstudioAuthorizationHeader(resolvedHeaders),
484-}) ?? LMSTUDIO_DEFAULT_API_KEY_ENV_VAR;
503+ hasAuthorizationHeader,
504+}) ?? (normalizedApiKey ? LMSTUDIO_DEFAULT_API_KEY_ENV_VAR : undefined);
505+if (!credential) {
506+await removeProviderAuthProfilesWithLock({
507+provider: PROVIDER_ID,
508+agentDir: params.agentDir,
509+});
510+}
485511486512return {
487-profiles: [
488-{
489-profileId: `${PROVIDER_ID}:default`,
490- credential,
491-},
492-],
513+profiles: credential
514+ ? [
515+{
516+profileId: `${PROVIDER_ID}:default`,
517+ credential,
518+},
519+]
520+ : [],
493521configPatch: {
494522agents: {
495523defaults: {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。