moderado 0.4.8 → 0.4.10

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.
package/README.md CHANGED
@@ -90,8 +90,9 @@ moderado --help
90
90
 
91
91
  The latest published release is 0.4.8. Its `/login` command uses the Moderado
92
92
  Gateway for model routes and inference; `/connect` remains available for direct
93
- providers. The previous 0.3.10 release is self-contained and works without the
94
- Gateway. Both releases use the `moderado` command name.
93
+ providers. The 0.4.10 source build uses `/connect` for all providers and does
94
+ not offer `/login`. The previous 0.3.10 release is self-contained and works
95
+ without the Gateway. All three use the `moderado` command name.
95
96
 
96
97
  Install the latest release with `npm install -g moderado`. To stay on the
97
98
  self-contained 0.3.10 CLI, run `npm install -g moderado@0.3.10`.
@@ -116,15 +117,16 @@ Maintainers can install a verified release artifact directly with
116
117
 
117
118
  ### Connect to the Moderado Gateway
118
119
 
119
- Run `/login` in the TUI and choose the public Gateway for keyless inference.
120
+ In the current source build, run `/connect`, choose Moderado Gateway, and then
121
+ choose public access or sign in.
120
122
  Browser authorization or a Moderado Cloud `mrd_` API key is optional for account
121
123
  features. `/model` lists configured Gateway routes: `auto` follows Gateway
122
124
  routing, while selecting a route pins requests to it. Existing BYOK and local
123
125
  provider profiles remain independent.
124
126
 
125
- Use `/connect` to connect directly to OpenRouter, NVIDIA NIM, Agnes AI,
126
- OrcaRouter, Ollama, LM Studio, or a custom OpenAI-compatible provider. `/login`
127
- selects the Moderado Gateway; `/connect` selects a direct provider.
127
+ The same `/connect` menu offers OpenRouter, NVIDIA NIM, Agnes AI, OrcaRouter,
128
+ Ollama, LM Studio, and custom OpenAI-compatible providers. The published 0.4.8
129
+ release still uses `/login` for the Gateway.
128
130
 
129
131
  Cloud OAuth credentials last 30 days and have no refresh token; authorize again
130
132
  after expiry. On Windows, credentials are stored in Windows Credential Manager.
@@ -146,12 +148,12 @@ Run `moderado doctor` to inspect local setup without exposing secrets. Add
146
148
 
147
149
  Run `moderado` to open the TUI immediately. A fresh installation does not require
148
150
  an API key or a preselected model. The welcome card shows **No model connected —
149
- use `/login`** until you add one.
151
+ use `/connect`** until you add one.
150
152
 
151
- Use `/login` for the public Moderado Gateway and `/model` to browse configured routes.
152
- Cloud `auto` follows the Gateway's configured pool; choosing a route in `/model`
153
- pins it for subsequent requests. Existing direct BYOK and local profiles remain
154
- available separately.
153
+ Use `/connect` to choose the Gateway or another provider. The Gateway offers a
154
+ route picker after connection; `/model` can change the route later. Cloud `auto`
155
+ follows the Gateway's configured pool, while choosing a route pins subsequent
156
+ requests to it.
155
157
 
156
158
  ### Sessions and usage
157
159
 
@@ -230,7 +232,7 @@ Run `moderado doctor` to check the local Node runtime, workspace, Moderado home
230
232
 
231
233
  ## Windows credential storage
232
234
 
233
- On Windows, `/login` stores Moderado Cloud credentials in Windows Credential
235
+ On Windows, Gateway sign-in through `/connect` stores credentials in Windows Credential
234
236
  Manager and keeps only a credential reference in `~/.moderado/config.json`.
235
237
  Non-Windows platforms use the current memory-only credential store, so log in
236
238
  again for each new CLI process. Existing BYOK environment variables and saved
@@ -3,14 +3,15 @@ import { discoverMcpServers } from '@moderado/tools';
3
3
  import type { WebSearchProviderName, WebSearchToolOptions } from '@moderado/tools';
4
4
  import { ApprovalDecision, ApprovalRequest, ChatMessage, IToolRegistry, McpServerConfig, ToolResult } from '@moderado/contracts';
5
5
  import { CliParsedArgs } from '../args.js';
6
- import { ModeradoConfig } from '../config.js';
6
+ import { ModeradoConfig, ProviderConnection } from '../config.js';
7
7
  import { StoredSession } from '../sessions.js';
8
8
  import { selectConfirmPopup, selectListPopup } from '../ui/popup.js';
9
+ export declare function createConnectionProvider(connection: ProviderConnection): NvidiaAdapter;
9
10
  export declare function formatSessionExitSummary(session: StoredSession, modelId?: string): string;
10
11
  export declare function createAgentTask(request: string, mode: 'Plan' | 'Execute'): string;
11
12
  export declare function createReviewTask(changedFiles: string[]): string;
12
13
  export declare function createReviewToolRegistry(): IToolRegistry;
13
- export declare const STANDARD_SLASH_COMMANDS: readonly ["/connect", "/login", "/model", "/init", "/btw", "/mcp", "/session", "/queue", "/workflow", "/review", "/map", "/budget", "/skills", "/clear", "/help", "/exit", "/quit"];
14
+ export declare const STANDARD_SLASH_COMMANDS: readonly ["/connect", "/model", "/init", "/btw", "/mcp", "/session", "/queue", "/workflow", "/review", "/map", "/budget", "/skills", "/clear", "/help", "/exit", "/quit"];
14
15
  export declare function levenshteinDistance(a: string, b: string): number;
15
16
  export interface SlashCommandAdvice {
16
17
  isSlashCommand: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../src/commands/chat.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../src/commands/chat.ts"],"names":[],"mappings":"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"}
@@ -23,6 +23,9 @@ import { inspectGitWorkspace, readGitDiff } from '../vendor/tools/index.js';
23
23
  import { buildWorkspaceMap } from '../repo_map.js';
24
24
  import { evaluateTokenBudget, parseBudgetCommand } from '../budget.js';
25
25
  import { discoverSkills, formatSkillContext, formatSkillsList, getEnabledSkillNames, selectEnabledSkills, setSkillEnabled } from '../skills.js';
26
+ export function createConnectionProvider(connection) {
27
+ return new NvidiaAdapter({ apiKey: connection.apiKey, baseUrl: connection.baseUrl, providerId: connection.id, providerName: connection.displayName });
28
+ }
26
29
  export function formatSessionExitSummary(session, modelId) {
27
30
  const usage = session.usage;
28
31
  const tokens = usage.available
@@ -64,7 +67,6 @@ export function createReviewToolRegistry() {
64
67
  }
65
68
  export const STANDARD_SLASH_COMMANDS = [
66
69
  '/connect',
67
- '/login',
68
70
  '/model',
69
71
  '/init',
70
72
  '/btw',
@@ -170,7 +172,7 @@ export function formatTurnFailureAnswer(status, errorEvent, modelId, otherConnec
170
172
  const cleanDetail = rawDetail
171
173
  .replace(/^(?:NVIDIA NIM|OpenAI|OpenRouter|[a-zA-Z0-9_-]+)\s*(?:request failed|rate limit exceeded|service or model unavailable)?\s*(?:\([^)]*\))?\s*(?:during\s*streamChat)?:\s*/i, '')
172
174
  .trim();
173
- return `⚠️ **Model Error (${errorEvent?.code || 'ERR_INFERENCE_FAILED'}):**\n${cleanDetail || 'Model returned no response.'}\n\n👉 **Suggestion:** The model \`${modelId}\` encountered an error. Switch models with \`/model\`, connect directly with \`/connect\`, or reconnect to the Gateway with \`/login\`${altSuggestion}.`;
175
+ return `⚠️ **Model Error (${errorEvent?.code || 'ERR_INFERENCE_FAILED'}):**\n${cleanDetail || 'Model returned no response.'}\n\n👉 **Suggestion:** The model \`${modelId}\` encountered an error. Switch models with \`/model\` or choose a provider with \`/connect\`${altSuggestion}.`;
174
176
  }
175
177
  export function resolveTurnAssistantAnswer(result, previousHistoryLength, lastErrorEvent, streamedAnswer = '', currentModel = 'unknown', otherConnections = []) {
176
178
  if (result.status === 'cancelled') {
@@ -625,7 +627,7 @@ export async function executeBtwQuery(command, drawFrame, provider, currentModel
625
627
  if (!provider || !currentModel) {
626
628
  await drawFrame(renderBoxLines('By The Way (/btw)', [
627
629
  'No model or provider connected.',
628
- 'Use /login for the Gateway or /connect for a direct provider, then select a model with /model.',
630
+ 'Use /connect to choose a provider and model.',
629
631
  '',
630
632
  'Press Esc or Enter to return.',
631
633
  ], 72));
@@ -721,7 +723,7 @@ export async function handleChatSession(args, version, signal) {
721
723
  const activateConnection = (connection, explicitModel) => {
722
724
  activeConnection = connection;
723
725
  currentModel = explicitModel ?? connection.defaultModel ?? (connection.kind === 'nvidia-nim' ? 'auto' : undefined);
724
- provider = new NvidiaAdapter({ apiKey: connection.id === 'moderado-cloud' ? undefined : connection.apiKey, baseUrl: connection.baseUrl, providerId: connection.id, providerName: connection.displayName });
726
+ provider = createConnectionProvider(connection);
725
727
  };
726
728
  if (activeConnection)
727
729
  activateConnection(activeConnection, args.model);
@@ -796,7 +798,7 @@ export async function handleChatSession(args, version, signal) {
796
798
  }
797
799
  else {
798
800
  const turn = await promptInteractiveTurn({
799
- model: currentModel ?? 'No model connected — use /login or /connect', tokens: Math.round(sessionTokens), cost: costLabel(), workspace: canonicalWorkspace, version,
801
+ model: currentModel ?? 'No model connected — use /connect', tokens: Math.round(sessionTokens), cost: costLabel(), workspace: canonicalWorkspace, version,
800
802
  usageAvailable: activeSession.usage.available, usageEstimated: activeSession.usage.estimated, initialMode: activeMode, initialAutoApprove: activeAutoApprove, isFirstTurn: isFirst, signal, chatQuestion: lastQuestion || undefined, chatAnswer: lastAnswer || undefined, chatThoughtTime: lastThoughtTime, outputTokenRate: lastOutputTokenRate, tokenUsage: lastTokenUsage,
801
803
  queuedCommands: commandQueue.items,
802
804
  onExit: exitMessage,
@@ -833,24 +835,12 @@ export async function handleChatSession(args, version, signal) {
833
835
  }
834
836
  return selection.modelId;
835
837
  },
836
- onLogin: async (drawFrame) => {
837
- const connection = await loginModeradoCloudInteractive({
838
- signal,
839
- drawFrame,
840
- gatewayUrl: config.connections?.['moderado-cloud']?.baseUrl,
841
- });
842
- if (!connection)
843
- return currentModel;
844
- const runtimeConnection = requiresCredentialReference(connection) ? await storeConnectionCredential(connection, credentialStore) : connection;
845
- saveConnection(runtimeConnection);
846
- config = loadConfig();
847
- activateConnection(runtimeConnection);
848
- return currentModel ?? 'No model connected — use /login or /connect';
849
- },
850
838
  onConnect: async (drawFrame) => {
851
839
  const connection = await connectProviderInteractive({
852
840
  signal,
853
841
  drawFrame,
842
+ gatewayUrl: config.connections?.['moderado-cloud']?.baseUrl,
843
+ activeConnection,
854
844
  savedConnections: config.connections,
855
845
  connectProviders: config.connectProviders,
856
846
  resolveSavedConnection: (saved) => resolveConnectionCredential(saved, credentialStore),
@@ -1100,7 +1090,7 @@ export async function handleChatSession(args, version, signal) {
1100
1090
  lastTokenUsage = undefined;
1101
1091
  process.stdout.write('\x1b[H\x1b[J');
1102
1092
  process.stdout.write(renderFullWelcomeScreen({
1103
- model: currentModel ?? 'No model connected — use /login or /connect', tokens: Math.round(sessionTokens), cost: costLabel(),
1093
+ model: currentModel ?? 'No model connected — use /connect', tokens: Math.round(sessionTokens), cost: costLabel(),
1104
1094
  usageAvailable: activeSession.usage.available, usageEstimated: activeSession.usage.estimated, workspace: canonicalWorkspace, mode: activeMode,
1105
1095
  autoApprove: activeAutoApprove, chatQuestion: lastQuestion, chatAnswer: lastAnswer,
1106
1096
  chatThoughtTime: lastThoughtTime, queuedCommands: commandQueue.items,
@@ -1116,7 +1106,7 @@ export async function handleChatSession(args, version, signal) {
1116
1106
  lastTokenUsage = undefined;
1117
1107
  process.stdout.write('\x1b[H\x1b[J');
1118
1108
  process.stdout.write(renderFullWelcomeScreen({
1119
- model: currentModel ?? 'No model connected — use /login or /connect', tokens: Math.round(sessionTokens), cost: costLabel(),
1109
+ model: currentModel ?? 'No model connected — use /connect', tokens: Math.round(sessionTokens), cost: costLabel(),
1120
1110
  usageAvailable: activeSession.usage.available, usageEstimated: activeSession.usage.estimated, workspace: canonicalWorkspace, mode: activeMode,
1121
1111
  autoApprove: activeAutoApprove, chatQuestion: lastQuestion, chatAnswer: lastAnswer,
1122
1112
  chatThoughtTime: lastThoughtTime, queuedCommands: commandQueue.items,
@@ -1151,7 +1141,7 @@ export async function handleChatSession(args, version, signal) {
1151
1141
  }
1152
1142
  process.stdout.write('\x1b[H\x1b[J');
1153
1143
  process.stdout.write(renderFullWelcomeScreen({
1154
- model: currentModel ?? 'No model connected — use /login or /connect', tokens: Math.round(sessionTokens), cost: costLabel(),
1144
+ model: currentModel ?? 'No model connected — use /connect', tokens: Math.round(sessionTokens), cost: costLabel(),
1155
1145
  usageAvailable: activeSession.usage.available, usageEstimated: activeSession.usage.estimated, workspace: canonicalWorkspace, mode: activeMode,
1156
1146
  autoApprove: activeAutoApprove, chatQuestion: lastQuestion, chatAnswer: lastAnswer,
1157
1147
  chatThoughtTime: lastThoughtTime,
@@ -1190,7 +1180,7 @@ export async function handleChatSession(args, version, signal) {
1190
1180
  lastTokenUsage = undefined;
1191
1181
  process.stdout.write('\x1b[H\x1b[J');
1192
1182
  process.stdout.write(renderFullWelcomeScreen({
1193
- model: currentModel ?? 'No model connected — use /login or /connect', tokens: Math.round(sessionTokens), cost: costLabel(),
1183
+ model: currentModel ?? 'No model connected — use /connect', tokens: Math.round(sessionTokens), cost: costLabel(),
1194
1184
  usageAvailable: activeSession.usage.available, usageEstimated: activeSession.usage.estimated, workspace: canonicalWorkspace, mode: activeMode,
1195
1185
  autoApprove: activeAutoApprove, chatQuestion: lastQuestion, chatAnswer: lastAnswer,
1196
1186
  chatThoughtTime: lastThoughtTime,
@@ -1229,7 +1219,7 @@ export async function handleChatSession(args, version, signal) {
1229
1219
  lastOutputTokenRate = undefined;
1230
1220
  lastTokenUsage = undefined;
1231
1221
  process.stdout.write('\x1b[H\x1b[J');
1232
- process.stdout.write(renderFullWelcomeScreen({ model: currentModel ?? 'No model connected — use /login or /connect', tokens: Math.round(sessionTokens), cost: costLabel(), usageAvailable: activeSession.usage.available, usageEstimated: activeSession.usage.estimated, workspace: canonicalWorkspace, mode: activeMode, autoApprove: activeAutoApprove, chatQuestion: lastQuestion, chatAnswer: lastAnswer, chatThoughtTime: lastThoughtTime, queuedCommands: commandQueue.items }, process.stdout.rows));
1222
+ process.stdout.write(renderFullWelcomeScreen({ model: currentModel ?? 'No model connected — use /connect', tokens: Math.round(sessionTokens), cost: costLabel(), usageAvailable: activeSession.usage.available, usageEstimated: activeSession.usage.estimated, workspace: canonicalWorkspace, mode: activeMode, autoApprove: activeAutoApprove, chatQuestion: lastQuestion, chatAnswer: lastAnswer, chatThoughtTime: lastThoughtTime, queuedCommands: commandQueue.items }, process.stdout.rows));
1233
1223
  process.stdout.write(renderChatComposerCursor({ width: process.stdout.columns }, 0));
1234
1224
  continue;
1235
1225
  }
@@ -1239,8 +1229,7 @@ export async function handleChatSession(args, version, signal) {
1239
1229
  if (trimmed === '/help') {
1240
1230
  lastQuestion = trimmed;
1241
1231
  lastAnswer = 'Available slash commands:\n' +
1242
- ' /connect - Connect directly to an external or local provider\n' +
1243
- ' /login - Connect to the Moderado Gateway or log in to Moderado Cloud\n' +
1232
+ ' /connect - Choose a Gateway, hosted, or local provider\n' +
1244
1233
  ' /model - Switch active AI model\n' +
1245
1234
  ' /init - Scaffold AGENTS.md from workspace scan\n' +
1246
1235
  ' /mcp - Manage local MCP servers\n' +
@@ -1259,7 +1248,7 @@ export async function handleChatSession(args, version, signal) {
1259
1248
  lastTokenUsage = undefined;
1260
1249
  process.stdout.write('\x1b[H\x1b[J');
1261
1250
  process.stdout.write(renderFullWelcomeScreen({
1262
- model: currentModel ?? 'No model connected — use /login or /connect', tokens: Math.round(sessionTokens), cost: costLabel(),
1251
+ model: currentModel ?? 'No model connected — use /connect', tokens: Math.round(sessionTokens), cost: costLabel(),
1263
1252
  usageAvailable: activeSession.usage.available, usageEstimated: activeSession.usage.estimated, workspace: canonicalWorkspace, mode: activeMode,
1264
1253
  autoApprove: activeAutoApprove, chatQuestion: lastQuestion, chatAnswer: lastAnswer,
1265
1254
  chatThoughtTime: lastThoughtTime,
@@ -1292,7 +1281,7 @@ export async function handleChatSession(args, version, signal) {
1292
1281
  sessionStore.save(activeSession);
1293
1282
  process.stdout.write('\x1b[H\x1b[J');
1294
1283
  process.stdout.write(renderFullWelcomeScreen({
1295
- model: currentModel ?? 'No model connected — use /login or /connect', tokens: Math.round(sessionTokens), cost: costLabel(),
1284
+ model: currentModel ?? 'No model connected — use /connect', tokens: Math.round(sessionTokens), cost: costLabel(),
1296
1285
  usageAvailable: activeSession.usage.available, usageEstimated: activeSession.usage.estimated, workspace: canonicalWorkspace, mode: activeMode,
1297
1286
  autoApprove: activeAutoApprove, chatQuestion: lastQuestion, chatAnswer: lastAnswer,
1298
1287
  chatThoughtTime: lastThoughtTime,
@@ -1312,7 +1301,7 @@ export async function handleChatSession(args, version, signal) {
1312
1301
  sessionStore.save(activeSession);
1313
1302
  process.stdout.write('\x1b[H\x1b[J');
1314
1303
  process.stdout.write(renderFullWelcomeScreen({
1315
- model: currentModel ?? 'No model connected — use /login or /connect', tokens: Math.round(sessionTokens), cost: costLabel(),
1304
+ model: currentModel ?? 'No model connected — use /connect', tokens: Math.round(sessionTokens), cost: costLabel(),
1316
1305
  usageAvailable: activeSession.usage.available, usageEstimated: activeSession.usage.estimated, workspace: canonicalWorkspace, mode: activeMode,
1317
1306
  autoApprove: activeAutoApprove, chatQuestion: lastQuestion, chatAnswer: lastAnswer,
1318
1307
  chatThoughtTime: lastThoughtTime,
@@ -1368,13 +1357,26 @@ export async function handleChatSession(args, version, signal) {
1368
1357
  }
1369
1358
  }
1370
1359
  if (!provider) {
1371
- process.stdout.write('\nNo model is connected. Use /login for the Gateway or /connect for a direct provider.\n');
1372
- const connection = await loginModeradoCloudInteractive({
1360
+ process.stdout.write('\nNo model is connected. Use /connect to choose a provider.\n');
1361
+ const connection = await connectProviderInteractive({
1373
1362
  signal,
1363
+ drawFrame: (popupLines) => {
1364
+ process.stdout.write('\x1b[H\x1b[J');
1365
+ process.stdout.write(renderWelcomePopupLayer({
1366
+ model: currentModel ?? 'No model connected — use /connect',
1367
+ tokens: Math.round(sessionTokens), cost: costLabel(), workspace: canonicalWorkspace,
1368
+ mode: activeMode, autoApprove: activeAutoApprove,
1369
+ chatQuestion: lastQuestion, chatAnswer: lastAnswer,
1370
+ }, popupLines, process.stdout.columns, process.stdout.rows));
1371
+ },
1374
1372
  gatewayUrl: config.connections?.['moderado-cloud']?.baseUrl,
1373
+ activeConnection,
1374
+ savedConnections: config.connections,
1375
+ connectProviders: config.connectProviders,
1376
+ resolveSavedConnection: (saved) => resolveConnectionCredential(saved, credentialStore),
1375
1377
  });
1376
1378
  if (!connection) {
1377
- process.stdout.write('No provider connected. Use /login or /connect whenever you are ready.\n\n');
1379
+ process.stdout.write('No provider connected. Use /connect whenever you are ready.\n\n');
1378
1380
  continue;
1379
1381
  }
1380
1382
  const runtimeConnection = requiresCredentialReference(connection) ? await storeConnectionCredential(connection, credentialStore) : connection;
@@ -1416,7 +1418,7 @@ export async function handleChatSession(args, version, signal) {
1416
1418
  const displayAnswer = streamedAnswer || lastAnswer;
1417
1419
  process.stdout.write('\x1b[H\x1b[J');
1418
1420
  process.stdout.write(renderFullWelcomeScreen({
1419
- model: currentModel ?? 'No model connected — use /login or /connect',
1421
+ model: currentModel ?? 'No model connected — use /connect',
1420
1422
  tokens: Math.round(sessionTokens + (usageRecorded ? 0 : turnUsage?.usage.totalTokens ?? 0)),
1421
1423
  cost: costLabel(),
1422
1424
  usageAvailable: activeSession.usage.available, usageEstimated: activeSession.usage.estimated,
@@ -1594,10 +1596,13 @@ export async function handleChatSession(args, version, signal) {
1594
1596
  if (thinkingTimer)
1595
1597
  clearInterval(thinkingTimer);
1596
1598
  const cloudOAuth = isModeradoCloudOAuthConnection(activeConnection);
1597
- process.stdout.write(cloudOAuth
1598
- ? '\nModerado Cloud rejected this browser login. Sign in again to retry once.\n'
1599
- : `\nThe saved ${activeConnection.displayName} API key was rejected. Enter a replacement key to retry once.\n`);
1600
- const replacement = cloudOAuth
1599
+ const cloudWithoutKey = activeConnection.id === 'moderado-cloud' && !activeConnection.apiKey;
1600
+ process.stdout.write(cloudWithoutKey
1601
+ ? '\nThis free Gateway route requires a Moderado website API key. Sign in or enter a key to retry once.\n'
1602
+ : cloudOAuth
1603
+ ? '\nModerado Cloud rejected this browser login. Sign in again to retry once.\n'
1604
+ : `\nThe saved ${activeConnection.displayName} API key was rejected. Enter a replacement key to retry once.\n`);
1605
+ const replacement = cloudOAuth || cloudWithoutKey
1601
1606
  ? await loginModeradoCloudInteractive({ signal, gatewayUrl: activeConnection.baseUrl })
1602
1607
  : await replaceProviderKeyInteractive(activeConnection, { signal });
1603
1608
  if (!replacement)
@@ -1695,12 +1700,12 @@ export async function handleChatSession(args, version, signal) {
1695
1700
  const cleanErr = rawErr
1696
1701
  .replace(/^(?:NVIDIA NIM|OpenAI|OpenRouter|[a-zA-Z0-9_-]+)\s*(?:request failed|rate limit exceeded|service or model unavailable)?\s*(?:\([^)]*\))?\s*(?:during\s*streamChat)?:\s*/i, '')
1697
1702
  .trim();
1698
- lastAnswer = `⚠️ **Error:** ${cleanErr || rawErr}\n\n👉 **Suggestion:** Switch models with \`/model\`, connect directly with \`/connect\`, or reconnect to the Gateway with \`/login\`${altSuggestion}.`;
1703
+ lastAnswer = `⚠️ **Error:** ${cleanErr || rawErr}\n\n👉 **Suggestion:** Switch models with \`/model\` or choose a provider with \`/connect\`${altSuggestion}.`;
1699
1704
  lastThoughtTime = Math.max(0.001, (Date.now() - startedAt) / 1000);
1700
1705
  lastOutputTokenRate = undefined;
1701
1706
  process.stdout.write('\x1b[H\x1b[J');
1702
1707
  process.stdout.write(renderFullWelcomeScreen({
1703
- model: currentModel ?? 'No model connected — use /login or /connect',
1708
+ model: currentModel ?? 'No model connected — use /connect',
1704
1709
  tokens: Math.round(sessionTokens),
1705
1710
  cost: costLabel(),
1706
1711
  usageAvailable: activeSession.usage.available, usageEstimated: activeSession.usage.estimated,