@@ -5,10 +5,19 @@ import {
55 type ProviderResolveDynamicModelContext ,
66 type ProviderRuntimeModel ,
77} from "openclaw/plugin-sdk/core" ;
8+ import { upsertAuthProfile } from "../../src/agents/auth-profiles.js" ;
89import { normalizeModelCompat } from "../../src/agents/model-compat.js" ;
10+ import { parseDurationMs } from "../../src/cli/parse-duration.js" ;
11+ import {
12+ normalizeSecretInputModeInput ,
13+ promptSecretRefForOnboarding ,
14+ resolveSecretInputModeForEnvSelection ,
15+ } from "../../src/commands/auth-choice.apply-helpers.js" ;
916import { buildTokenProfileId , validateAnthropicSetupToken } from "../../src/commands/auth-token.js" ;
17+ import { applyAuthProfileConfig } from "../../src/commands/onboard-auth.js" ;
1018import { fetchClaudeUsage } from "../../src/infra/provider-usage.fetch.js" ;
1119import type { ProviderAuthResult } from "../../src/plugins/types.js" ;
20+ import { normalizeSecretInput } from "../../src/utils/normalize-secret-input.js" ;
1221
1322const PROVIDER_ID = "anthropic" ;
1423const ANTHROPIC_OPUS_46_MODEL_ID = "claude-opus-4-6" ;
@@ -119,11 +128,41 @@ async function runAnthropicSetupToken(ctx: ProviderAuthContext): Promise<Provide
119128 "Anthropic setup-token" ,
120129 ) ;
121130
122- const tokenRaw = await ctx . prompter . text ( {
123- message : "Paste Anthropic setup-token" ,
124- validate : ( value ) => validateAnthropicSetupToken ( String ( value ?? "" ) ) ,
125- } ) ;
126- const token = String ( tokenRaw ?? "" ) . trim ( ) ;
131+ const requestedSecretInputMode = normalizeSecretInputModeInput ( ctx . secretInputMode ) ;
132+ const selectedMode = ctx . allowSecretRefPrompt
133+ ? await resolveSecretInputModeForEnvSelection ( {
134+ prompter : ctx . prompter ,
135+ explicitMode : requestedSecretInputMode ,
136+ copy : {
137+ modeMessage : "How do you want to provide this setup token?" ,
138+ plaintextLabel : "Paste setup token now" ,
139+ plaintextHint : "Stores the token directly in the auth profile" ,
140+ } ,
141+ } )
142+ : "plaintext" ;
143+
144+ let token = "" ;
145+ let tokenRef : { source : "env" | "file" | "exec" ; provider : string ; id : string } | undefined ;
146+ if ( selectedMode === "ref" ) {
147+ const resolved = await promptSecretRefForOnboarding ( {
148+ provider : "anthropic-setup-token" ,
149+ config : ctx . config ,
150+ prompter : ctx . prompter ,
151+ preferredEnvVar : "ANTHROPIC_SETUP_TOKEN" ,
152+ copy : {
153+ sourceMessage : "Where is this Anthropic setup token stored?" ,
154+ envVarPlaceholder : "ANTHROPIC_SETUP_TOKEN" ,
155+ } ,
156+ } ) ;
157+ token = resolved . resolvedValue . trim ( ) ;
158+ tokenRef = resolved . ref ;
159+ } else {
160+ const tokenRaw = await ctx . prompter . text ( {
161+ message : "Paste Anthropic setup-token" ,
162+ validate : ( value ) => validateAnthropicSetupToken ( String ( value ?? "" ) ) ,
163+ } ) ;
164+ token = String ( tokenRaw ?? "" ) . trim ( ) ;
165+ }
127166 const tokenError = validateAnthropicSetupToken ( token ) ;
128167 if ( tokenError ) {
129168 throw new Error ( tokenError ) ;
@@ -145,12 +184,80 @@ async function runAnthropicSetupToken(ctx: ProviderAuthContext): Promise<Provide
145184 type : "token" ,
146185 provider : PROVIDER_ID ,
147186 token,
187+ ...( tokenRef ? { tokenRef } : { } ) ,
148188 } ,
149189 } ,
150190 ] ,
151191 } ;
152192}
153193
194+ async function runAnthropicSetupTokenNonInteractive ( ctx : {
195+ config : ProviderAuthContext [ "config" ] ;
196+ opts : {
197+ tokenProvider ?: string ;
198+ token ?: string ;
199+ tokenExpiresIn ?: string ;
200+ tokenProfileId ?: string ;
201+ } ;
202+ runtime : ProviderAuthContext [ "runtime" ] ;
203+ agentDir ?: string ;
204+ } ) : Promise < ProviderAuthContext [ "config" ] | null > {
205+ const provider = ctx . opts . tokenProvider ?. trim ( ) . toLowerCase ( ) ;
206+ if ( ! provider ) {
207+ ctx . runtime . error ( "Missing --token-provider for --auth-choice token." ) ;
208+ ctx . runtime . exit ( 1 ) ;
209+ return null ;
210+ }
211+ if ( provider !== PROVIDER_ID ) {
212+ ctx . runtime . error ( "Only --token-provider anthropic is supported for --auth-choice token." ) ;
213+ ctx . runtime . exit ( 1 ) ;
214+ return null ;
215+ }
216+
217+ const token = normalizeSecretInput ( ctx . opts . token ) ;
218+ if ( ! token ) {
219+ ctx . runtime . error ( "Missing --token for --auth-choice token." ) ;
220+ ctx . runtime . exit ( 1 ) ;
221+ return null ;
222+ }
223+ const tokenError = validateAnthropicSetupToken ( token ) ;
224+ if ( tokenError ) {
225+ ctx . runtime . error ( tokenError ) ;
226+ ctx . runtime . exit ( 1 ) ;
227+ return null ;
228+ }
229+
230+ let expires : number | undefined ;
231+ const expiresInRaw = ctx . opts . tokenExpiresIn ?. trim ( ) ;
232+ if ( expiresInRaw ) {
233+ try {
234+ expires = Date . now ( ) + parseDurationMs ( expiresInRaw , { defaultUnit : "d" } ) ;
235+ } catch ( err ) {
236+ ctx . runtime . error ( `Invalid --token-expires-in: ${ String ( err ) } ` ) ;
237+ ctx . runtime . exit ( 1 ) ;
238+ return null ;
239+ }
240+ }
241+
242+ const profileId =
243+ ctx . opts . tokenProfileId ?. trim ( ) || buildTokenProfileId ( { provider : PROVIDER_ID , name : "" } ) ;
244+ upsertAuthProfile ( {
245+ profileId,
246+ agentDir : ctx . agentDir ,
247+ credential : {
248+ type : "token" ,
249+ provider : PROVIDER_ID ,
250+ token,
251+ ...( expires ? { expires } : { } ) ,
252+ } ,
253+ } ) ;
254+ return applyAuthProfileConfig ( ctx . config , {
255+ profileId,
256+ provider : PROVIDER_ID ,
257+ mode : "token" ,
258+ } ) ;
259+ }
260+
154261const anthropicPlugin = {
155262 id : PROVIDER_ID ,
156263 name : "Anthropic Provider" ,
@@ -169,8 +276,23 @@ const anthropicPlugin = {
169276 hint : "Paste a setup-token from `claude setup-token`" ,
170277 kind : "token" ,
171278 run : async ( ctx : ProviderAuthContext ) => await runAnthropicSetupToken ( ctx ) ,
279+ runNonInteractive : async ( ctx ) =>
280+ await runAnthropicSetupTokenNonInteractive ( {
281+ config : ctx . config ,
282+ opts : ctx . opts ,
283+ runtime : ctx . runtime ,
284+ agentDir : ctx . agentDir ,
285+ } ) ,
172286 } ,
173287 ] ,
288+ wizard : {
289+ onboarding : {
290+ choiceId : "token" ,
291+ choiceLabel : "Anthropic token (paste setup-token)" ,
292+ choiceHint : "Run `claude setup-token` elsewhere, then paste the token here" ,
293+ methodId : "setup-token" ,
294+ } ,
295+ } ,
174296 resolveDynamicModel : ( ctx ) => resolveAnthropicForwardCompatModel ( ctx ) ,
175297 capabilities : {
176298 providerFamily : "anthropic" ,
0 commit comments