myclaude-code 8.8.8 → 8.8.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,427 @@
1
+ import {
2
+ DEFAULT_PROVIDER_ROUTE_DIAGNOSTIC_MODELS,
3
+ activateProviderProfile,
4
+ clearActiveProviderConfiguration,
5
+ findProviderProfiles,
6
+ getActiveProviderProfileId,
7
+ getCredentialLabel,
8
+ getProviderProfiles,
9
+ getResolvedCurrentProviderProfile,
10
+ inspectProviderModelRoutes,
11
+ maskCredential,
12
+ attemptAutoRepairProviderProfile,
13
+ validateProviderProfile,
14
+ } from './provider-setup.js'
15
+
16
+ function getDisplayCurrentProfile() {
17
+ return getResolvedCurrentProviderProfile()
18
+ }
19
+
20
+ function getRoutingDisplayValue(value, fallback) {
21
+ const trimmed = String(value || '').trim()
22
+ return trimmed || fallback
23
+ }
24
+
25
+ function formatProviderSummary(profile) {
26
+ return [
27
+ `Name: ${profile.name}`,
28
+ `API URL: ${profile.baseUrl}`,
29
+ `${getCredentialLabel(profile.authType)}: ${maskCredential(profile.credential)}`,
30
+ `Primary model: ${getRoutingDisplayValue(
31
+ profile.modelRouting?.primaryModel,
32
+ 'provider default',
33
+ )}`,
34
+ `Subagent model: ${getRoutingDisplayValue(
35
+ profile.modelRouting?.subagentModel,
36
+ 'inherit from primary model',
37
+ )}`,
38
+ `Fast helper model: ${getRoutingDisplayValue(
39
+ profile.modelRouting?.smallFastModel,
40
+ 'provider default',
41
+ )}`,
42
+ ].join('\n')
43
+ }
44
+
45
+ function buildHelpText() {
46
+ return [
47
+ 'Usage: /provider [list|current|clear|validate [profile]|matrix [profile]|repair [profile]|use <profile>|<profile>]',
48
+ '',
49
+ 'Quick provider switching for myclaude.',
50
+ 'For full setup, restart myclaude and choose reconfigure, or run: myclaude auth login',
51
+ '',
52
+ 'Examples:',
53
+ ' /provider list',
54
+ ' /provider current',
55
+ ' /provider validate',
56
+ ' /provider matrix',
57
+ ' /provider repair',
58
+ ' /provider use kimi',
59
+ ' /provider gpt54-main',
60
+ ' /provider clear',
61
+ ].join('\n')
62
+ }
63
+
64
+ function formatListOutput() {
65
+ const profiles = getProviderProfiles()
66
+ const activeProfileId = getActiveProviderProfileId()
67
+ const currentProfile = getDisplayCurrentProfile()
68
+
69
+ if (profiles.length === 0 && !currentProfile) {
70
+ return 'No provider profiles are configured yet. Restart myclaude and choose reconfigure, or run: myclaude auth login'
71
+ }
72
+
73
+ const sections = [buildHelpText()]
74
+
75
+ if (profiles.length > 0) {
76
+ sections.push(
77
+ [
78
+ 'Saved provider profiles:',
79
+ ...profiles.map(profile => {
80
+ const suffix = activeProfileId === profile.id ? ' (active)' : ''
81
+ return `- ${profile.name}${suffix} · ${profile.baseUrl} · Main ${getRoutingDisplayValue(
82
+ profile.modelRouting?.primaryModel,
83
+ 'provider default',
84
+ )}`
85
+ }),
86
+ ].join('\n'),
87
+ )
88
+ }
89
+
90
+ if (currentProfile) {
91
+ sections.push(
92
+ `Current active configuration:\n${formatProviderSummary(currentProfile)}`,
93
+ )
94
+ }
95
+
96
+ return sections.join('\n\n')
97
+ }
98
+
99
+ function syncLiveSession(context, profile) {
100
+ if (typeof context?.onChangeAPIKey === 'function') {
101
+ context.onChangeAPIKey()
102
+ }
103
+
104
+ if (typeof context?.setAppState === 'function') {
105
+ const mainLoopModel =
106
+ String(profile?.modelRouting?.primaryModel || '').trim() || null
107
+ context.setAppState(prev => ({
108
+ ...prev,
109
+ mainLoopModel,
110
+ mainLoopModelForSession: null,
111
+ authVersion: (prev.authVersion || 0) + 1,
112
+ }))
113
+ }
114
+ }
115
+
116
+ function formatMatchList(matches) {
117
+ return matches.map(profile => `- ${profile.name} (${profile.baseUrl})`).join('\n')
118
+ }
119
+
120
+ async function formatRouteMatrix(profile) {
121
+ const routes = await inspectProviderModelRoutes(
122
+ profile,
123
+ DEFAULT_PROVIDER_ROUTE_DIAGNOSTIC_MODELS,
124
+ )
125
+ const guidance = buildValidationGuidance(
126
+ profile,
127
+ { status: 'ok', lines: [] },
128
+ routes,
129
+ )
130
+
131
+ return [
132
+ `GPT-5.x route matrix for ${profile.name}:`,
133
+ ...routes.map(route => route.line),
134
+ ...(guidance.length > 0 ? ['', ...guidance] : []),
135
+ ].join('\n')
136
+ }
137
+
138
+ function buildValidationGuidance(profile, validation, routeMatrix) {
139
+ const gpt54Route = routeMatrix.find(route => route.model === 'gpt-5.4')
140
+ const codexRoute = routeMatrix.find(route => route.model === 'gpt-5.3-codex')
141
+
142
+ if (gpt54Route?.status === 'recommended') {
143
+ const guidance = [
144
+ 'Guidance:',
145
+ '- This provider is currently best routed as gpt-5.4 for primary, subagent, and fast helper work.',
146
+ ]
147
+
148
+ if (gpt54Route.effortLevels.includes('max')) {
149
+ guidance.push(
150
+ '- Use `/effort low|medium|high|max` with gpt-5.4 here. `max` is mapped to Responses `reasoning.effort = xhigh` on this validated route.',
151
+ )
152
+ }
153
+
154
+ if (codexRoute?.status === 'avoid') {
155
+ guidance.push(
156
+ '- Do not route subagents to gpt-5.3-codex on this provider until `/provider validate` shows it as SUPPORTED.',
157
+ )
158
+ }
159
+
160
+ if (!validation || validation.status === 'ok') {
161
+ return guidance
162
+ }
163
+ }
164
+
165
+ if (!profile || !validation || validation.status === 'ok') {
166
+ return []
167
+ }
168
+
169
+ const primaryModel = String(profile.modelRouting?.primaryModel || '').trim()
170
+ if (
171
+ primaryModel === 'gpt-5.4' &&
172
+ Array.isArray(validation.details) &&
173
+ validation.details.some(
174
+ detail =>
175
+ detail &&
176
+ detail.status !== 'ok' &&
177
+ Array.isArray(detail.roles) &&
178
+ detail.roles.some(role => role !== 'primary'),
179
+ )
180
+ ) {
181
+ return [
182
+ 'Guidance:',
183
+ '- This gateway is currently verified for native myclaude workflows on gpt-5.4.',
184
+ '- One or more secondary routes are degraded here. Restart myclaude and choose reconfigure to switch all roles to gpt-5.4.',
185
+ ]
186
+ }
187
+
188
+ if (validation.status === 'warn') {
189
+ return [
190
+ 'Guidance:',
191
+ '- The provider can answer chat requests, but some native workflows may still degrade on the current routing.',
192
+ '- Restart myclaude and choose reconfigure, or run `myclaude auth login`, to adjust the provider and model route.',
193
+ ]
194
+ }
195
+
196
+ return []
197
+ }
198
+
199
+ export async function call(args, context) {
200
+ const trimmedArgs = String(args || '').trim()
201
+
202
+ if (
203
+ !trimmedArgs ||
204
+ trimmedArgs === 'help' ||
205
+ trimmedArgs === '--help' ||
206
+ trimmedArgs === '-h' ||
207
+ trimmedArgs === 'list'
208
+ ) {
209
+ return {
210
+ type: 'text',
211
+ value: formatListOutput(),
212
+ }
213
+ }
214
+
215
+ if (trimmedArgs === 'current') {
216
+ const currentProfile = getDisplayCurrentProfile()
217
+ return {
218
+ type: 'text',
219
+ value: currentProfile
220
+ ? `Current provider configuration:\n${formatProviderSummary(
221
+ currentProfile,
222
+ )}`
223
+ : 'No active provider configuration is set.',
224
+ }
225
+ }
226
+
227
+ if (trimmedArgs === 'clear') {
228
+ clearActiveProviderConfiguration()
229
+ syncLiveSession(context, null)
230
+ return {
231
+ type: 'text',
232
+ value: 'Cleared the active provider configuration.',
233
+ }
234
+ }
235
+
236
+ const matrixMatch = trimmedArgs.match(/^matrix(?:\s+(.+))?$/i)
237
+ if (matrixMatch) {
238
+ const profileQuery = matrixMatch[1]?.trim()
239
+ let profile = null
240
+
241
+ if (profileQuery) {
242
+ const matches = findProviderProfiles(profileQuery)
243
+ if (matches.length === 0) {
244
+ return {
245
+ type: 'text',
246
+ value: `No saved provider matched '${profileQuery}'. Run /provider list to inspect saved names.`,
247
+ }
248
+ }
249
+ if (matches.length > 1) {
250
+ return {
251
+ type: 'text',
252
+ value: `Multiple providers matched '${profileQuery}'. Be more specific:\n${formatMatchList(
253
+ matches,
254
+ )}`,
255
+ }
256
+ }
257
+ profile = matches[0]
258
+ } else {
259
+ profile = getDisplayCurrentProfile()
260
+ }
261
+
262
+ if (!profile) {
263
+ return {
264
+ type: 'text',
265
+ value: 'No active provider configuration is set.',
266
+ }
267
+ }
268
+
269
+ return {
270
+ type: 'text',
271
+ value: await formatRouteMatrix(profile),
272
+ }
273
+ }
274
+
275
+ const validateMatch = trimmedArgs.match(/^(validate|test)(?:\s+(.+))?$/i)
276
+ if (validateMatch) {
277
+ const profileQuery = validateMatch[2]?.trim()
278
+ let profile = null
279
+
280
+ if (profileQuery) {
281
+ const matches = findProviderProfiles(profileQuery)
282
+ if (matches.length === 0) {
283
+ return {
284
+ type: 'text',
285
+ value: `No saved provider matched '${profileQuery}'. Run /provider list to inspect saved names.`,
286
+ }
287
+ }
288
+ if (matches.length > 1) {
289
+ return {
290
+ type: 'text',
291
+ value: `Multiple providers matched '${profileQuery}'. Be more specific:\n${formatMatchList(
292
+ matches,
293
+ )}`,
294
+ }
295
+ }
296
+ profile = matches[0]
297
+ } else {
298
+ profile = getDisplayCurrentProfile()
299
+ }
300
+
301
+ if (!profile) {
302
+ return {
303
+ type: 'text',
304
+ value: 'No active provider configuration is set.',
305
+ }
306
+ }
307
+
308
+ const validation = await validateProviderProfile(profile)
309
+ const routeMatrix = await inspectProviderModelRoutes(
310
+ profile,
311
+ DEFAULT_PROVIDER_ROUTE_DIAGNOSTIC_MODELS,
312
+ )
313
+ return {
314
+ type: 'text',
315
+ value: [
316
+ `Validation for ${profile.name}:`,
317
+ ...validation.lines,
318
+ `Status: ${validation.status}`,
319
+ '',
320
+ 'GPT-5.x route matrix:',
321
+ ...routeMatrix.map(route => route.line),
322
+ ...buildValidationGuidance(profile, validation, routeMatrix),
323
+ ].join('\n'),
324
+ }
325
+ }
326
+
327
+ const repairMatch = trimmedArgs.match(/^repair(?:\s+(.+))?$/i)
328
+ if (repairMatch) {
329
+ const profileQuery = repairMatch[1]?.trim()
330
+ let profile = null
331
+
332
+ if (profileQuery) {
333
+ const matches = findProviderProfiles(profileQuery)
334
+ if (matches.length === 0) {
335
+ return {
336
+ type: 'text',
337
+ value: `No saved provider matched '${profileQuery}'. Run /provider list to inspect saved names.`,
338
+ }
339
+ }
340
+ if (matches.length > 1) {
341
+ return {
342
+ type: 'text',
343
+ value: `Multiple providers matched '${profileQuery}'. Be more specific:\n${formatMatchList(
344
+ matches,
345
+ )}`,
346
+ }
347
+ }
348
+ profile = matches[0]
349
+ } else {
350
+ profile = getDisplayCurrentProfile()
351
+ }
352
+
353
+ if (!profile) {
354
+ return {
355
+ type: 'text',
356
+ value: 'No active provider configuration is set.',
357
+ }
358
+ }
359
+
360
+ const repairResult = await attemptAutoRepairProviderProfile(profile)
361
+ if (repairResult.repaired) {
362
+ syncLiveSession(context, repairResult.profile)
363
+ return {
364
+ type: 'text',
365
+ value: [
366
+ `Auto-repaired provider ${repairResult.profile.name}:`,
367
+ ...repairResult.repairLines,
368
+ ...repairResult.validation.lines,
369
+ `Status: ${repairResult.validation.status}`,
370
+ ].join('\n'),
371
+ }
372
+ }
373
+
374
+ return {
375
+ type: 'text',
376
+ value: [
377
+ `No automatic repair was applied for ${profile.name}.`,
378
+ ...repairResult.originalValidation.lines,
379
+ `Status: ${repairResult.validation.status}`,
380
+ ].join('\n'),
381
+ }
382
+ }
383
+
384
+ if (trimmedArgs === 'setup' || trimmedArgs === 'login') {
385
+ return {
386
+ type: 'text',
387
+ value:
388
+ 'Restart myclaude and choose reconfigure, or run `myclaude auth login` in the shell to open the full provider setup wizard.',
389
+ }
390
+ }
391
+
392
+ const useMatch = trimmedArgs.match(/^use\s+(.+)$/i)
393
+ const profileQuery = useMatch?.[1]?.trim() || trimmedArgs
394
+ const matches = findProviderProfiles(profileQuery)
395
+
396
+ if (matches.length === 0) {
397
+ return {
398
+ type: 'text',
399
+ value: `No saved provider matched '${profileQuery}'. Run /provider list to inspect saved names.`,
400
+ }
401
+ }
402
+
403
+ if (matches.length > 1) {
404
+ return {
405
+ type: 'text',
406
+ value: `Multiple providers matched '${profileQuery}'. Be more specific:\n${formatMatchList(
407
+ matches,
408
+ )}`,
409
+ }
410
+ }
411
+
412
+ const activatedProfile = activateProviderProfile(matches[0].id)
413
+ if (!activatedProfile) {
414
+ return {
415
+ type: 'text',
416
+ value: `Provider '${matches[0].name}' is no longer available.`,
417
+ }
418
+ }
419
+
420
+ syncLiveSession(context, activatedProfile)
421
+ return {
422
+ type: 'text',
423
+ value: `Activated provider ${activatedProfile.name}\n${formatProviderSummary(
424
+ activatedProfile,
425
+ )}`,
426
+ }
427
+ }