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 +14 -12
- package/dist/commands/chat.d.ts +3 -2
- package/dist/commands/chat.d.ts.map +1 -1
- package/dist/commands/chat.js +44 -39
- package/dist/commands/chat.js.map +1 -1
- package/dist/ui/model_selector.d.ts +1 -0
- package/dist/ui/model_selector.d.ts.map +1 -1
- package/dist/ui/model_selector.js +5 -5
- package/dist/ui/model_selector.js.map +1 -1
- package/dist/ui/popup.d.ts.map +1 -1
- package/dist/ui/popup.js +22 -2
- package/dist/ui/popup.js.map +1 -1
- package/dist/ui/provider_connect.d.ts +26 -2
- package/dist/ui/provider_connect.d.ts.map +1 -1
- package/dist/ui/provider_connect.js +100 -16
- package/dist/ui/provider_connect.js.map +1 -1
- package/dist/ui/welcome.d.ts +0 -2
- package/dist/ui/welcome.d.ts.map +1 -1
- package/dist/ui/welcome.js +2 -25
- package/dist/ui/welcome.js.map +1 -1
- package/dist/vendor/contracts/models.d.ts +4 -0
- package/dist/vendor/contracts/models.d.ts.map +1 -1
- package/dist/vendor/contracts/models.js +2 -0
- package/dist/vendor/contracts/models.js.map +1 -1
- package/dist/vendor/providers/presets.d.ts +1 -1
- package/dist/vendor/providers/presets.d.ts.map +1 -1
- package/dist/vendor/providers/presets.js +3 -5
- package/dist/vendor/providers/presets.js.map +1 -1
- package/package.json +2 -1
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
|
|
94
|
-
|
|
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
|
-
|
|
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
|
-
|
|
126
|
-
|
|
127
|
-
|
|
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 `/
|
|
151
|
+
use `/connect`** until you add one.
|
|
150
152
|
|
|
151
|
-
Use `/
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
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, `/
|
|
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
|
package/dist/commands/chat.d.ts
CHANGED
|
@@ -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", "/
|
|
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":"AAIA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAkG,kBAAkB,EAA0D,MAAM,iBAAiB,CAAC;AAC7M,OAAO,KAAK,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACnF,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,WAAW,EAAoB,aAAa,EAAE,eAAe,EAAyB,UAAU,EAAmB,MAAM,qBAAqB,CAAC;AAC3L,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAuD,cAAc,
|
|
1
|
+
{"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../src/commands/chat.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/chat.js
CHANGED
|
@@ -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
|
|
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 /
|
|
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 =
|
|
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 /
|
|
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 /
|
|
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 /
|
|
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 /
|
|
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 /
|
|
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 /
|
|
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 -
|
|
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 /
|
|
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 /
|
|
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 /
|
|
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 /
|
|
1372
|
-
const connection = await
|
|
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 /
|
|
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 /
|
|
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
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
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
|
|
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 /
|
|
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,
|