@iaforged/context-code 1.0.89 → 1.0.90
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/dist/src/commands/login/login.js +13 -6
- package/dist/src/commands/release-notes/release-notes.js +6 -3
- package/dist/src/components/ConsoleOAuthFlow.js +14 -4
- package/dist/src/components/LogoV2/feedConfigs.js +4 -3
- package/dist/src/components/ModelPicker.js +2 -1
- package/dist/src/components/ThinkingToggle.js +7 -7
- package/dist/src/hooks/useTypeahead.js +1 -1
- package/dist/src/services/api/openai.js +12 -1
- package/dist/src/services/tips/tipRegistry.js +54 -55
- package/dist/src/utils/auth.js +7 -0
- package/dist/src/utils/model/providerBaseUrls.js +3 -1
- package/dist/src/utils/model/providerCatalog.js +12 -0
- package/dist/src/utils/model/providerModels.js +6 -0
- package/dist/src/utils/model/providerSwitch.js +4 -4
- package/dist/src/utils/model/providers.js +22 -2
- package/dist/src/utils/model/validateModel.js +5 -2
- package/dist/src/utils/releaseNoteTranslations.js +18 -0
- package/package.json +1 -1
|
@@ -88,12 +88,19 @@ export async function call(onDone, context, args) {
|
|
|
88
88
|
targetProvider: 'minimax',
|
|
89
89
|
targetProfileName: profileName,
|
|
90
90
|
})
|
|
91
|
-
:
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
91
|
+
: targetProvider === 'nvidia'
|
|
92
|
+
? switchProviderPreference({
|
|
93
|
+
currentModel: previousModel,
|
|
94
|
+
currentProvider: previousProvider,
|
|
95
|
+
targetProvider: 'nvidia',
|
|
96
|
+
targetProfileName: profileName,
|
|
97
|
+
})
|
|
98
|
+
: switchProviderPreference({
|
|
99
|
+
currentModel: previousModel,
|
|
100
|
+
currentProvider: previousProvider,
|
|
101
|
+
targetProvider: 'claude',
|
|
102
|
+
targetProfileName: profileName,
|
|
103
|
+
});
|
|
97
104
|
resetCostState();
|
|
98
105
|
void refreshRemoteManagedSettings();
|
|
99
106
|
void refreshPolicyLimits();
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { CHANGELOG_URL, fetchAndStoreChangelog, getAllReleaseNotes, getStoredChangelog, } from '../../utils/releaseNotes.js';
|
|
2
|
+
import { translateReleaseNoteToSpanish } from '../../utils/releaseNoteTranslations.js';
|
|
2
3
|
function formatReleaseNotes(notes) {
|
|
3
4
|
return notes
|
|
4
5
|
.map(([version, notes]) => {
|
|
5
|
-
const header = `
|
|
6
|
-
const bulletPoints = notes
|
|
6
|
+
const header = `Versión ${version}:`;
|
|
7
|
+
const bulletPoints = notes
|
|
8
|
+
.map(note => `- ${translateReleaseNoteToSpanish(note)}`)
|
|
9
|
+
.join('\n');
|
|
7
10
|
return `${header}\n${bulletPoints}`;
|
|
8
11
|
})
|
|
9
12
|
.join('\n\n');
|
|
@@ -33,6 +36,6 @@ export async function call() {
|
|
|
33
36
|
// Nothing available, show link
|
|
34
37
|
return {
|
|
35
38
|
type: 'text',
|
|
36
|
-
value: `
|
|
39
|
+
value: `Ver changelog completo en: ${CHANGELOG_URL}`,
|
|
37
40
|
};
|
|
38
41
|
}
|
|
@@ -27,6 +27,7 @@ const LOGIN_PROVIDER_ORDER = [
|
|
|
27
27
|
'minimax',
|
|
28
28
|
'openrouter',
|
|
29
29
|
'zai',
|
|
30
|
+
'nvidia',
|
|
30
31
|
'ollama',
|
|
31
32
|
'openai',
|
|
32
33
|
'claudeai',
|
|
@@ -144,6 +145,15 @@ export function ConsoleOAuthFlow({ onDone, startingMessage, mode = 'login', forc
|
|
|
144
145
|
context: 'Confirmation',
|
|
145
146
|
isActive: oauthStatus.state === 'error' && !!oauthStatus.toRetry
|
|
146
147
|
});
|
|
148
|
+
// Handle Esc to cancel from API key input or other setup states
|
|
149
|
+
useKeybinding('cancel', () => {
|
|
150
|
+
setOAuthStatus({
|
|
151
|
+
state: 'idle'
|
|
152
|
+
});
|
|
153
|
+
}, {
|
|
154
|
+
context: 'Confirmation',
|
|
155
|
+
isActive: oauthStatus.state === 'provider_api_key_input' || oauthStatus.state === 'provider_local_setup' || oauthStatus.state === 'provider_google_setup' || oauthStatus.state === 'error'
|
|
156
|
+
});
|
|
147
157
|
useEffect(() => {
|
|
148
158
|
if (pastedCode === 'c' && oauthStatus.state === 'waiting_for_login' && showPastePrompt && !urlCopied) {
|
|
149
159
|
void setClipboard(oauthStatus.url).then(raw => {
|
|
@@ -206,9 +216,6 @@ export function ConsoleOAuthFlow({ onDone, startingMessage, mode = 'login', forc
|
|
|
206
216
|
await saveProviderApiKey(provider, trimmedValue);
|
|
207
217
|
setProviderApiKey('');
|
|
208
218
|
setProviderApiKeyCursorOffset(0);
|
|
209
|
-
setOAuthStatus({
|
|
210
|
-
state: 'success'
|
|
211
|
-
});
|
|
212
219
|
const providerLabel = getVisibleProvider(provider).label;
|
|
213
220
|
void sendNotification({
|
|
214
221
|
message: `API key de ${providerLabel} guardada`,
|
|
@@ -491,6 +498,9 @@ function OAuthStatusMessage(t0) {
|
|
|
491
498
|
}, {
|
|
492
499
|
label: _jsxs(Text, { children: ["MiniMax \u00B7", " ", _jsx(Text, { dimColor: true, children: "API key / Anthropic-compatible" }), "\n"] }),
|
|
493
500
|
value: "minimax"
|
|
501
|
+
}, {
|
|
502
|
+
label: _jsxs(Text, { children: ["NVIDIA API \u00B7", " ", _jsx(Text, { dimColor: true, children: "API key / build.nvidia.com" }), "\n"] }),
|
|
503
|
+
value: "nvidia"
|
|
494
504
|
}];
|
|
495
505
|
$[5] = t6;
|
|
496
506
|
}
|
|
@@ -520,7 +530,7 @@ function OAuthStatusMessage(t0) {
|
|
|
520
530
|
provider: "openrouter"
|
|
521
531
|
});
|
|
522
532
|
}
|
|
523
|
-
else if (value_0 === "gemini-api" || value_0 === "zai" || value_0 === "minimax") {
|
|
533
|
+
else if (value_0 === "gemini-api" || value_0 === "zai" || value_0 === "minimax" || value_0 === "nvidia") {
|
|
524
534
|
setOAuthStatus({
|
|
525
535
|
state: "provider_api_key_input",
|
|
526
536
|
provider: value_0
|
|
@@ -5,6 +5,7 @@ import { Box, Text } from '../../ink.js';
|
|
|
5
5
|
import { formatCreditAmount, getCachedReferrerReward } from '../../services/api/referral.js';
|
|
6
6
|
import { getCwd } from '../../utils/cwd.js';
|
|
7
7
|
import { formatRelativeTimeAgo } from '../../utils/format.js';
|
|
8
|
+
import { translateReleaseNoteToSpanish } from '../../utils/releaseNoteTranslations.js';
|
|
8
9
|
export function createRecentActivityFeed(activities) {
|
|
9
10
|
const lines = activities.map(log => {
|
|
10
11
|
const time = formatRelativeTimeAgo(log.modified);
|
|
@@ -33,12 +34,12 @@ export function createWhatsNewFeed(releaseNotes) {
|
|
|
33
34
|
}
|
|
34
35
|
}
|
|
35
36
|
return {
|
|
36
|
-
text: note
|
|
37
|
+
text: translateReleaseNoteToSpanish(note)
|
|
37
38
|
};
|
|
38
39
|
});
|
|
39
|
-
const emptyMessage = "external" === 'ant' ? '
|
|
40
|
+
const emptyMessage = "external" === 'ant' ? 'No se pudieron obtener los últimos commits de claude-cli-internal' : 'Consulta el changelog de Context Code para ver actualizaciones';
|
|
40
41
|
return {
|
|
41
|
-
title: "external" === 'ant' ?
|
|
42
|
+
title: "external" === 'ant' ? 'Novedades [SOLO ANT: últimos commits de CC]' : 'Novedades',
|
|
42
43
|
lines,
|
|
43
44
|
footer: lines.length > 0 ? '/release-notes para ver más' : undefined,
|
|
44
45
|
emptyMessage
|
|
@@ -63,7 +63,8 @@ export function ModelPicker(t0) {
|
|
|
63
63
|
provider === 'gemini-api' ||
|
|
64
64
|
provider === 'gemini-google' ||
|
|
65
65
|
provider === 'zai' ||
|
|
66
|
-
provider === 'minimax'
|
|
66
|
+
provider === 'minimax' ||
|
|
67
|
+
provider === 'nvidia') {
|
|
67
68
|
const { getCachedProviderModels, fetchProviderModels } = await import('../utils/model/providerModels.js');
|
|
68
69
|
const cached = getCachedProviderModels(provider);
|
|
69
70
|
if (cached) {
|
|
@@ -18,12 +18,12 @@ export function ThinkingToggle(t0) {
|
|
|
18
18
|
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
|
19
19
|
t1 = [{
|
|
20
20
|
value: "true",
|
|
21
|
-
label: "
|
|
22
|
-
description: "
|
|
21
|
+
label: "Activado",
|
|
22
|
+
description: "Context pensará antes de responder"
|
|
23
23
|
}, {
|
|
24
24
|
value: "false",
|
|
25
|
-
label: "
|
|
26
|
-
description: "
|
|
25
|
+
label: "Desactivado",
|
|
26
|
+
description: "Context responderá sin un pensamiento extendido"
|
|
27
27
|
}];
|
|
28
28
|
$[0] = t1;
|
|
29
29
|
}
|
|
@@ -109,7 +109,7 @@ export function ThinkingToggle(t0) {
|
|
|
109
109
|
const handleSelectChange = t7;
|
|
110
110
|
let t8;
|
|
111
111
|
if ($[14] === Symbol.for("react.memo_cache_sentinel")) {
|
|
112
|
-
t8 = _jsxs(Box, { marginBottom: 1, flexDirection: "column", children: [_jsx(Text, { color: "remember", bold: true, children: "
|
|
112
|
+
t8 = _jsxs(Box, { marginBottom: 1, flexDirection: "column", children: [_jsx(Text, { color: "remember", bold: true, children: "Alternar modo de pensamiento" }), _jsx(Text, { dimColor: true, children: "Activa o desactiva el pensamiento para esta sesi\u00F3n." })] });
|
|
113
113
|
$[14] = t8;
|
|
114
114
|
}
|
|
115
115
|
else {
|
|
@@ -117,7 +117,7 @@ export function ThinkingToggle(t0) {
|
|
|
117
117
|
}
|
|
118
118
|
let t9;
|
|
119
119
|
if ($[15] !== confirmationPending || $[16] !== currentValue || $[17] !== handleSelectChange || $[18] !== onCancel) {
|
|
120
|
-
t9 = _jsxs(Box, { flexDirection: "column", children: [t8, confirmationPending !== null ? _jsxs(Box, { flexDirection: "column", marginBottom: 1, gap: 1, children: [_jsx(Text, { color: "warning", children: "
|
|
120
|
+
t9 = _jsxs(Box, { flexDirection: "column", children: [t8, confirmationPending !== null ? _jsxs(Box, { flexDirection: "column", marginBottom: 1, gap: 1, children: [_jsx(Text, { color: "warning", children: "Cambiar el modo de pensamiento a mitad de la conversaci\u00F3n aumentar\u00E1 la latencia y puede reducir la calidad. Para obtener mejores resultados, config\u00FAralo al inicio de la sesi\u00F3n." }), _jsx(Text, { color: "warning", children: "\u00BFDeseas continuar?" })] }) : _jsx(Box, { flexDirection: "column", marginBottom: 1, children: _jsx(Select, { defaultValue: currentValue ? "true" : "false", defaultFocusValue: currentValue ? "true" : "false", options: options, onChange: handleSelectChange, onCancel: onCancel ?? _temp, visibleOptionCount: 2 }) })] });
|
|
121
121
|
$[15] = confirmationPending;
|
|
122
122
|
$[16] = currentValue;
|
|
123
123
|
$[17] = handleSelectChange;
|
|
@@ -129,7 +129,7 @@ export function ThinkingToggle(t0) {
|
|
|
129
129
|
}
|
|
130
130
|
let t10;
|
|
131
131
|
if ($[20] !== confirmationPending || $[21] !== exitState.keyName || $[22] !== exitState.pending) {
|
|
132
|
-
t10 = _jsx(Text, { dimColor: true, italic: true, children: exitState.pending ? _jsxs(_Fragment, { children: ["
|
|
132
|
+
t10 = _jsx(Text, { dimColor: true, italic: true, children: exitState.pending ? _jsxs(_Fragment, { children: ["Presiona ", exitState.keyName, " de nuevo para salir"] }) : confirmationPending !== null ? _jsxs(Byline, { children: [_jsx(KeyboardShortcutHint, { shortcut: "Enter", action: "confirm" }), _jsx(ConfigurableShortcutHint, { action: "confirm:no", context: "Confirmation", fallback: "Esc", description: "cancelar" })] }) : _jsxs(Byline, { children: [_jsx(KeyboardShortcutHint, { shortcut: "Enter", action: "confirm" }), _jsx(ConfigurableShortcutHint, { action: "confirm:no", context: "Confirmation", fallback: "Esc", description: "salir" })] }) });
|
|
133
133
|
$[20] = confirmationPending;
|
|
134
134
|
$[21] = exitState.keyName;
|
|
135
135
|
$[22] = exitState.pending;
|
|
@@ -1564,7 +1564,7 @@ export function useTypeahead({ commands, onInputChange, onSubmit, setCursorOffse
|
|
|
1564
1564
|
e.preventDefault();
|
|
1565
1565
|
addNotification({
|
|
1566
1566
|
key: 'thinking-toggle-hint',
|
|
1567
|
-
jsx: _jsxs(Text, { dimColor: true, children: ["
|
|
1567
|
+
jsx: _jsxs(Text, { dimColor: true, children: ["Usa ", thinkingToggleShortcut, " para alternar el modo de razonamiento"] }),
|
|
1568
1568
|
priority: 'immediate',
|
|
1569
1569
|
timeoutMs: 3000
|
|
1570
1570
|
});
|
|
@@ -51,7 +51,8 @@ function getOpenAICompatibleProvider() {
|
|
|
51
51
|
provider === 'ollama-cloud' ||
|
|
52
52
|
provider === 'gemini-api' ||
|
|
53
53
|
provider === 'gemini-google' ||
|
|
54
|
-
provider === 'zai'
|
|
54
|
+
provider === 'zai' ||
|
|
55
|
+
provider === 'nvidia'
|
|
55
56
|
? provider
|
|
56
57
|
: 'openai';
|
|
57
58
|
}
|
|
@@ -69,6 +70,8 @@ function getOpenAICompatibleProviderLabel(provider = getOpenAICompatibleProvider
|
|
|
69
70
|
return 'Gemini Google';
|
|
70
71
|
case 'zai':
|
|
71
72
|
return 'Z.AI';
|
|
73
|
+
case 'nvidia':
|
|
74
|
+
return 'NVIDIA NIM';
|
|
72
75
|
default:
|
|
73
76
|
return 'OpenAI';
|
|
74
77
|
}
|
|
@@ -124,6 +127,14 @@ function getOpenAIBaseUrl(provider = getOpenAICompatibleProvider()) {
|
|
|
124
127
|
? raw.slice(0, -1)
|
|
125
128
|
: raw;
|
|
126
129
|
}
|
|
130
|
+
if (provider === 'nvidia') {
|
|
131
|
+
const raw = process.env.NVIDIA_BASE_URL ||
|
|
132
|
+
getConfiguredProviderBaseUrl('nvidia') ||
|
|
133
|
+
'https://integrate.api.nvidia.com/v1';
|
|
134
|
+
return raw.endsWith('/')
|
|
135
|
+
? raw.slice(0, -1)
|
|
136
|
+
: raw;
|
|
137
|
+
}
|
|
127
138
|
const raw = process.env.OPENAI_API_BASE_URL ||
|
|
128
139
|
process.env.OPENAI_BASE_URL ||
|
|
129
140
|
'https://api.openai.com/v1';
|
|
@@ -59,7 +59,7 @@ async function isMarketplacePluginRelevant(pluginName, context, signals) {
|
|
|
59
59
|
const externalTips = [
|
|
60
60
|
{
|
|
61
61
|
id: 'new-user-warmup',
|
|
62
|
-
content: async () => `
|
|
62
|
+
content: async () => `Comienza con pequeñas funciones o correcciones, pide a Context que proponga un plan y verifica sus ediciones sugeridas`,
|
|
63
63
|
cooldownSessions: 3,
|
|
64
64
|
async isRelevant() {
|
|
65
65
|
const config = getGlobalConfig();
|
|
@@ -68,7 +68,7 @@ const externalTips = [
|
|
|
68
68
|
},
|
|
69
69
|
{
|
|
70
70
|
id: 'plan-mode-for-complex-tasks',
|
|
71
|
-
content: async () => `
|
|
71
|
+
content: async () => `Usa el Modo Plan para preparar una solicitud compleja antes de realizar cambios. Presiona ${getShortcutDisplay('chat:cycleMode', 'Chat', 'shift+tab')} dos veces para activarlo.`,
|
|
72
72
|
cooldownSessions: 5,
|
|
73
73
|
isRelevant: async () => {
|
|
74
74
|
if (process.env.USER_TYPE === 'ant')
|
|
@@ -83,7 +83,7 @@ const externalTips = [
|
|
|
83
83
|
},
|
|
84
84
|
{
|
|
85
85
|
id: 'default-permission-mode-config',
|
|
86
|
-
content: async () => `
|
|
86
|
+
content: async () => `Usa /config para cambiar tu modo de permisos predeterminado (incluyendo el Modo Plan)`,
|
|
87
87
|
cooldownSessions: 10,
|
|
88
88
|
isRelevant: async () => {
|
|
89
89
|
try {
|
|
@@ -102,7 +102,7 @@ const externalTips = [
|
|
|
102
102
|
},
|
|
103
103
|
{
|
|
104
104
|
id: 'git-worktrees',
|
|
105
|
-
content: async () => '
|
|
105
|
+
content: async () => 'Usa git worktrees para ejecutar múltiples sesiones de Context en paralelo.',
|
|
106
106
|
cooldownSessions: 10,
|
|
107
107
|
isRelevant: async () => {
|
|
108
108
|
try {
|
|
@@ -117,7 +117,7 @@ const externalTips = [
|
|
|
117
117
|
},
|
|
118
118
|
{
|
|
119
119
|
id: 'color-when-multi-clauding',
|
|
120
|
-
content: async () => '
|
|
120
|
+
content: async () => '¿Ejecutando múltiples sesiones de Context? Usa /color y /rename para distinguirlas de un vistazo.',
|
|
121
121
|
cooldownSessions: 10,
|
|
122
122
|
isRelevant: async () => {
|
|
123
123
|
if (getCurrentSessionAgentColor())
|
|
@@ -129,8 +129,8 @@ const externalTips = [
|
|
|
129
129
|
{
|
|
130
130
|
id: 'terminal-setup',
|
|
131
131
|
content: async () => env.terminal === 'Apple_Terminal'
|
|
132
|
-
? '
|
|
133
|
-
: '
|
|
132
|
+
? 'Ejecuta /terminal-setup para habilitar la integración del terminal, como Option + Enter para nueva línea y más'
|
|
133
|
+
: 'Ejecuta /terminal-setup para habilitar la integración del terminal, como Shift + Enter para nueva línea y más',
|
|
134
134
|
cooldownSessions: 10,
|
|
135
135
|
async isRelevant() {
|
|
136
136
|
const config = getGlobalConfig();
|
|
@@ -143,8 +143,8 @@ const externalTips = [
|
|
|
143
143
|
{
|
|
144
144
|
id: 'shift-enter',
|
|
145
145
|
content: async () => env.terminal === 'Apple_Terminal'
|
|
146
|
-
? '
|
|
147
|
-
: '
|
|
146
|
+
? 'Presiona Option+Enter para enviar un mensaje multilínea'
|
|
147
|
+
: 'Presiona Shift+Enter para enviar un mensaje multilínea',
|
|
148
148
|
cooldownSessions: 10,
|
|
149
149
|
async isRelevant() {
|
|
150
150
|
const config = getGlobalConfig();
|
|
@@ -156,8 +156,8 @@ const externalTips = [
|
|
|
156
156
|
{
|
|
157
157
|
id: 'shift-enter-setup',
|
|
158
158
|
content: async () => env.terminal === 'Apple_Terminal'
|
|
159
|
-
? '
|
|
160
|
-
: '
|
|
159
|
+
? 'Ejecuta /terminal-setup para habilitar Option+Enter para nuevas líneas'
|
|
160
|
+
: 'Ejecuta /terminal-setup para habilitar Shift+Enter para nuevas líneas',
|
|
161
161
|
cooldownSessions: 10,
|
|
162
162
|
async isRelevant() {
|
|
163
163
|
if (!shouldOfferTerminalSetup()) {
|
|
@@ -171,7 +171,7 @@ const externalTips = [
|
|
|
171
171
|
},
|
|
172
172
|
{
|
|
173
173
|
id: 'memory-command',
|
|
174
|
-
content: async () => '
|
|
174
|
+
content: async () => 'Usa /memory para ver y gestionar la memoria de Context',
|
|
175
175
|
cooldownSessions: 15,
|
|
176
176
|
async isRelevant() {
|
|
177
177
|
const config = getGlobalConfig();
|
|
@@ -180,32 +180,32 @@ const externalTips = [
|
|
|
180
180
|
},
|
|
181
181
|
{
|
|
182
182
|
id: 'theme-command',
|
|
183
|
-
content: async () => '
|
|
183
|
+
content: async () => 'Usa /theme para cambiar el tema de color',
|
|
184
184
|
cooldownSessions: 20,
|
|
185
185
|
isRelevant: async () => true,
|
|
186
186
|
},
|
|
187
187
|
{
|
|
188
188
|
id: 'colorterm-truecolor',
|
|
189
|
-
content: async () => '
|
|
189
|
+
content: async () => 'Prueba a configurar la variable de entorno COLORTERM=truecolor para obtener colores más vivos',
|
|
190
190
|
cooldownSessions: 30,
|
|
191
191
|
isRelevant: async () => !process.env.COLORTERM && chalk.level < 3,
|
|
192
192
|
},
|
|
193
193
|
{
|
|
194
194
|
id: 'powershell-tool-env',
|
|
195
|
-
content: async () => '
|
|
195
|
+
content: async () => 'Configura CLAUDE_CODE_USE_POWERSHELL_TOOL=1 para habilitar la herramienta PowerShell (vista previa)',
|
|
196
196
|
cooldownSessions: 10,
|
|
197
197
|
isRelevant: async () => getPlatform() === 'windows' &&
|
|
198
198
|
process.env.CLAUDE_CODE_USE_POWERSHELL_TOOL === undefined,
|
|
199
199
|
},
|
|
200
200
|
{
|
|
201
201
|
id: 'status-line',
|
|
202
|
-
content: async () => '
|
|
202
|
+
content: async () => 'Usa /statusline para configurar una línea de estado personalizada que se mostrará debajo del cuadro de entrada',
|
|
203
203
|
cooldownSessions: 25,
|
|
204
204
|
isRelevant: async () => getSettings_DEPRECATED().statusLine === undefined,
|
|
205
205
|
},
|
|
206
206
|
{
|
|
207
207
|
id: 'prompt-queue',
|
|
208
|
-
content: async () => '
|
|
208
|
+
content: async () => 'Pulsa Enter para poner en cola mensajes adicionales mientras Context está trabajando.',
|
|
209
209
|
cooldownSessions: 5,
|
|
210
210
|
async isRelevant() {
|
|
211
211
|
const config = getGlobalConfig();
|
|
@@ -214,19 +214,19 @@ const externalTips = [
|
|
|
214
214
|
},
|
|
215
215
|
{
|
|
216
216
|
id: 'enter-to-steer-in-relatime',
|
|
217
|
-
content: async () => '
|
|
217
|
+
content: async () => 'Envía mensajes a Context mientras trabaja para guiarlo en tiempo real',
|
|
218
218
|
cooldownSessions: 20,
|
|
219
219
|
isRelevant: async () => true,
|
|
220
220
|
},
|
|
221
221
|
{
|
|
222
222
|
id: 'todo-list',
|
|
223
|
-
content: async () => '
|
|
223
|
+
content: async () => 'Pide a Context que cree una lista de tareas cuando trabajes en tareas complejas para seguir el progreso',
|
|
224
224
|
cooldownSessions: 20,
|
|
225
225
|
isRelevant: async () => true,
|
|
226
226
|
},
|
|
227
227
|
{
|
|
228
228
|
id: 'vscode-command-install',
|
|
229
|
-
content: async () => `
|
|
229
|
+
content: async () => `Abre la Paleta de Comandos (Cmd+Shift+P) y ejecuta "Shell Command: Install '${env.terminal === 'vscode' ? 'code' : env.terminal}' command in PATH" para habilitar la integración con el IDE`,
|
|
230
230
|
cooldownSessions: 0,
|
|
231
231
|
async isRelevant() {
|
|
232
232
|
// Only show this tip if we're in a VS Code-style terminal
|
|
@@ -251,7 +251,7 @@ const externalTips = [
|
|
|
251
251
|
},
|
|
252
252
|
{
|
|
253
253
|
id: 'ide-upsell-external-terminal',
|
|
254
|
-
content: async () => '
|
|
254
|
+
content: async () => 'Conecta Context a tu IDE · /ide',
|
|
255
255
|
cooldownSessions: 4,
|
|
256
256
|
async isRelevant() {
|
|
257
257
|
if (isSupportedTerminal()) {
|
|
@@ -268,19 +268,19 @@ const externalTips = [
|
|
|
268
268
|
},
|
|
269
269
|
{
|
|
270
270
|
id: 'install-github-app',
|
|
271
|
-
content: async () => '
|
|
271
|
+
content: async () => 'Ejecuta /install-github-app para etiquetar a @claude directamente desde tus issues y PRs de Github',
|
|
272
272
|
cooldownSessions: 10,
|
|
273
273
|
isRelevant: async () => !getGlobalConfig().githubActionSetupCount,
|
|
274
274
|
},
|
|
275
275
|
{
|
|
276
276
|
id: 'install-slack-app',
|
|
277
|
-
content: async () => '
|
|
277
|
+
content: async () => 'Ejecuta /install-slack-app para usar Context en Slack',
|
|
278
278
|
cooldownSessions: 10,
|
|
279
279
|
isRelevant: async () => !getGlobalConfig().slackAppInstallCount,
|
|
280
280
|
},
|
|
281
281
|
{
|
|
282
282
|
id: 'permissions',
|
|
283
|
-
content: async () => '
|
|
283
|
+
content: async () => 'Usa /permissions para pre-aprobar y pre-denegar herramientas de bash, edición y MCP',
|
|
284
284
|
cooldownSessions: 10,
|
|
285
285
|
async isRelevant() {
|
|
286
286
|
const config = getGlobalConfig();
|
|
@@ -289,25 +289,25 @@ const externalTips = [
|
|
|
289
289
|
},
|
|
290
290
|
{
|
|
291
291
|
id: 'drag-and-drop-images',
|
|
292
|
-
content: async () => '
|
|
292
|
+
content: async () => '¿Sabías que puedes arrastrar y soltar archivos de imagen en tu terminal?',
|
|
293
293
|
cooldownSessions: 10,
|
|
294
294
|
isRelevant: async () => !env.isSSH(),
|
|
295
295
|
},
|
|
296
296
|
{
|
|
297
297
|
id: 'paste-images-mac',
|
|
298
|
-
content: async () => '
|
|
298
|
+
content: async () => 'Pega imágenes en Context Code usando control+v (¡no cmd+v!)',
|
|
299
299
|
cooldownSessions: 10,
|
|
300
300
|
isRelevant: async () => getPlatform() === 'macos',
|
|
301
301
|
},
|
|
302
302
|
{
|
|
303
303
|
id: 'double-esc',
|
|
304
|
-
content: async () => '
|
|
304
|
+
content: async () => 'Pulsa dos veces esc para rebobinar la conversación a un punto anterior en el tiempo',
|
|
305
305
|
cooldownSessions: 10,
|
|
306
306
|
isRelevant: async () => !fileHistoryEnabled(),
|
|
307
307
|
},
|
|
308
308
|
{
|
|
309
309
|
id: 'double-esc-code-restore',
|
|
310
|
-
content: async () => '
|
|
310
|
+
content: async () => 'Pulsa dos veces esc para rebobinar el código y/o la conversación a un punto anterior en el tiempo',
|
|
311
311
|
cooldownSessions: 10,
|
|
312
312
|
isRelevant: async () => fileHistoryEnabled(),
|
|
313
313
|
},
|
|
@@ -319,13 +319,13 @@ const externalTips = [
|
|
|
319
319
|
},
|
|
320
320
|
{
|
|
321
321
|
id: 'rename-conversation',
|
|
322
|
-
content: async () => '
|
|
322
|
+
content: async () => 'Nombra tus conversaciones con /rename para encontrarlas fácilmente en /resume más tarde',
|
|
323
323
|
cooldownSessions: 15,
|
|
324
324
|
isRelevant: async () => isCustomTitleEnabled() && getGlobalConfig().numStartups > 10,
|
|
325
325
|
},
|
|
326
326
|
{
|
|
327
327
|
id: 'custom-commands',
|
|
328
|
-
content: async () => '
|
|
328
|
+
content: async () => 'Crea habilidades añadiendo archivos .md a .context/skills/ en tu proyecto o ~/.context/skills/ para habilidades globales',
|
|
329
329
|
cooldownSessions: 15,
|
|
330
330
|
async isRelevant() {
|
|
331
331
|
const config = getGlobalConfig();
|
|
@@ -335,20 +335,20 @@ const externalTips = [
|
|
|
335
335
|
{
|
|
336
336
|
id: 'shift-tab',
|
|
337
337
|
content: async () => process.env.USER_TYPE === 'ant'
|
|
338
|
-
? `
|
|
339
|
-
: `
|
|
338
|
+
? `Pulsa ${getShortcutDisplay('chat:cycleMode', 'Chat', 'shift+tab')} para alternar entre el modo predeterminado y el modo automático`
|
|
339
|
+
: `Pulsa ${getShortcutDisplay('chat:cycleMode', 'Chat', 'shift+tab')} para alternar entre el modo predeterminado, el modo de edición con auto-aceptación y el modo de planificación`,
|
|
340
340
|
cooldownSessions: 10,
|
|
341
341
|
isRelevant: async () => true,
|
|
342
342
|
},
|
|
343
343
|
{
|
|
344
344
|
id: 'image-paste',
|
|
345
|
-
content: async () => `
|
|
345
|
+
content: async () => `Usa ${getShortcutDisplay('chat:imagePaste', 'Chat', 'ctrl+v')} para pegar imágenes desde tu portapapeles`,
|
|
346
346
|
cooldownSessions: 20,
|
|
347
347
|
isRelevant: async () => true,
|
|
348
348
|
},
|
|
349
349
|
{
|
|
350
350
|
id: 'custom-agents',
|
|
351
|
-
content: async () => '
|
|
351
|
+
content: async () => 'Usa /agents para optimizar tareas específicas. Ej: Arquitecto de Software, Escritor de Código, Revisor de Código',
|
|
352
352
|
cooldownSessions: 15,
|
|
353
353
|
async isRelevant() {
|
|
354
354
|
const config = getGlobalConfig();
|
|
@@ -357,7 +357,7 @@ const externalTips = [
|
|
|
357
357
|
},
|
|
358
358
|
{
|
|
359
359
|
id: 'agent-flag',
|
|
360
|
-
content: async () => '
|
|
360
|
+
content: async () => 'Usa --agent <nombre_agente> para iniciar directamente una conversación con un subagente',
|
|
361
361
|
cooldownSessions: 15,
|
|
362
362
|
async isRelevant() {
|
|
363
363
|
const config = getGlobalConfig();
|
|
@@ -366,7 +366,7 @@ const externalTips = [
|
|
|
366
366
|
},
|
|
367
367
|
{
|
|
368
368
|
id: 'desktop-app',
|
|
369
|
-
content: async () => '
|
|
369
|
+
content: async () => 'Ejecuta Context Code local o remotamente usando la aplicación de escritorio: clau.de/desktop',
|
|
370
370
|
cooldownSessions: 15,
|
|
371
371
|
isRelevant: async () => getPlatform() !== 'linux',
|
|
372
372
|
},
|
|
@@ -374,7 +374,7 @@ const externalTips = [
|
|
|
374
374
|
id: 'desktop-shortcut',
|
|
375
375
|
content: async (ctx) => {
|
|
376
376
|
const blue = color('suggestion', ctx.theme);
|
|
377
|
-
return `
|
|
377
|
+
return `Continúa tu sesión en Context Code Desktop con ${blue('/desktop')}`;
|
|
378
378
|
},
|
|
379
379
|
cooldownSessions: 15,
|
|
380
380
|
isRelevant: async () => {
|
|
@@ -386,19 +386,19 @@ const externalTips = [
|
|
|
386
386
|
},
|
|
387
387
|
{
|
|
388
388
|
id: 'web-app',
|
|
389
|
-
content: async () => '
|
|
389
|
+
content: async () => 'Ejecuta tareas en la nube mientras sigues programando localmente · clau.de/web',
|
|
390
390
|
cooldownSessions: 15,
|
|
391
391
|
isRelevant: async () => true,
|
|
392
392
|
},
|
|
393
393
|
{
|
|
394
394
|
id: 'mobile-app',
|
|
395
|
-
content: async () => '/mobile
|
|
395
|
+
content: async () => '/mobile para usar Context Code desde la aplicación de Context en tu teléfono',
|
|
396
396
|
cooldownSessions: 15,
|
|
397
397
|
isRelevant: async () => true,
|
|
398
398
|
},
|
|
399
399
|
{
|
|
400
400
|
id: 'opusplan-mode-reminder',
|
|
401
|
-
content: async () => `
|
|
401
|
+
content: async () => `Tu modelo predeterminado es Opus Plan Mode. Presiona ${getShortcutDisplay('chat:cycleMode', 'Chat', 'shift+tab')} dos veces para activar el Modo Plan y planificar con Context Opus.`,
|
|
402
402
|
cooldownSessions: 2,
|
|
403
403
|
async isRelevant() {
|
|
404
404
|
if (process.env.USER_TYPE === 'ant')
|
|
@@ -417,7 +417,7 @@ const externalTips = [
|
|
|
417
417
|
id: 'frontend-design-plugin',
|
|
418
418
|
content: async (ctx) => {
|
|
419
419
|
const blue = color('suggestion', ctx.theme);
|
|
420
|
-
return
|
|
420
|
+
return `¿Trabajando con HTML/CSS? Instala el plugin frontend-design:\n${blue(`/plugin install frontend-design@${OFFICIAL_MARKETPLACE_NAME}`)}`;
|
|
421
421
|
},
|
|
422
422
|
cooldownSessions: 3,
|
|
423
423
|
isRelevant: async (context) => isMarketplacePluginRelevant('frontend-design', context, {
|
|
@@ -428,7 +428,7 @@ const externalTips = [
|
|
|
428
428
|
id: 'vercel-plugin',
|
|
429
429
|
content: async (ctx) => {
|
|
430
430
|
const blue = color('suggestion', ctx.theme);
|
|
431
|
-
return
|
|
431
|
+
return `¿Trabajando con Vercel? Instala el plugin vercel:\n${blue(`/plugin install vercel@${OFFICIAL_MARKETPLACE_NAME}`)}`;
|
|
432
432
|
},
|
|
433
433
|
cooldownSessions: 3,
|
|
434
434
|
isRelevant: async (context) => isMarketplacePluginRelevant('vercel', context, {
|
|
@@ -443,8 +443,8 @@ const externalTips = [
|
|
|
443
443
|
const cmd = blue('/effort high');
|
|
444
444
|
const variant = getFeatureValue_CACHED_MAY_BE_STALE('tengu_tide_elm', 'off');
|
|
445
445
|
return variant === 'copy_b'
|
|
446
|
-
? `
|
|
447
|
-
:
|
|
446
|
+
? `Usa ${cmd} para obtener mejores respuestas directas. Context lo analiza profundamente primero.`
|
|
447
|
+
: `¿Trabajando en algo difícil? ${cmd} ofrece mejores respuestas iniciales`;
|
|
448
448
|
},
|
|
449
449
|
cooldownSessions: 3,
|
|
450
450
|
isRelevant: async () => {
|
|
@@ -469,8 +469,8 @@ const externalTips = [
|
|
|
469
469
|
const blue = color('suggestion', ctx.theme);
|
|
470
470
|
const variant = getFeatureValue_CACHED_MAY_BE_STALE('tengu_tern_alloy', 'off');
|
|
471
471
|
return variant === 'copy_b'
|
|
472
|
-
? `
|
|
473
|
-
: `
|
|
472
|
+
? `Para tareas grandes, pide a Context que ${blue('use subagentes')}. Trabajan en paralelo y mantienen limpia la conversación principal.`
|
|
473
|
+
: `Di ${blue('"fan out subagents"')} y Context enviará un equipo. Cada uno profundiza para que no se escape nada.`;
|
|
474
474
|
},
|
|
475
475
|
cooldownSessions: 3,
|
|
476
476
|
isRelevant: async () => {
|
|
@@ -485,8 +485,8 @@ const externalTips = [
|
|
|
485
485
|
const blue = color('suggestion', ctx.theme);
|
|
486
486
|
const variant = getFeatureValue_CACHED_MAY_BE_STALE('tengu_timber_lark', 'off');
|
|
487
487
|
return variant === 'copy_b'
|
|
488
|
-
? `
|
|
489
|
-
: `${blue('/loop')}
|
|
488
|
+
? `Usa ${blue('/loop 5m check the deploy')} para ejecutar cualquier prompt de forma programada. Configúralo y olvídate.`
|
|
489
|
+
: `${blue('/loop')} ejecuta cualquier prompt de forma recurrente. Ideal para monitorear despliegues o estados de PR.`;
|
|
490
490
|
},
|
|
491
491
|
cooldownSessions: 3,
|
|
492
492
|
isRelevant: async () => {
|
|
@@ -500,11 +500,11 @@ const externalTips = [
|
|
|
500
500
|
{
|
|
501
501
|
id: 'guest-passes',
|
|
502
502
|
content: async (ctx) => {
|
|
503
|
-
const
|
|
503
|
+
const contextColor = color('claude', ctx.theme);
|
|
504
504
|
const reward = getCachedReferrerReward();
|
|
505
505
|
return reward
|
|
506
|
-
? `
|
|
507
|
-
: `
|
|
506
|
+
? `Comparte Context Code y gana ${contextColor(formatCreditAmount(reward))} de uso extra · ${contextColor('/passes')}`
|
|
507
|
+
: `Tienes pases de invitado gratuitos para compartir · ${contextColor('/passes')}`;
|
|
508
508
|
},
|
|
509
509
|
cooldownSessions: 3,
|
|
510
510
|
isRelevant: async () => {
|
|
@@ -519,20 +519,19 @@ const externalTips = [
|
|
|
519
519
|
{
|
|
520
520
|
id: 'overage-credit',
|
|
521
521
|
content: async (ctx) => {
|
|
522
|
-
const
|
|
522
|
+
const contextColor = color('claude', ctx.theme);
|
|
523
523
|
const info = getCachedOverageCreditGrant();
|
|
524
524
|
const amount = info ? formatGrantAmount(info) : null;
|
|
525
525
|
if (!amount)
|
|
526
526
|
return '';
|
|
527
|
-
|
|
528
|
-
return `${claude(`${amount} in extra usage, on us`)} · third-party apps · ${claude('/extra-usage')}`;
|
|
527
|
+
return `${contextColor(`${amount} en uso extra, por nuestra cuenta`)} · aplicaciones de terceros · ${contextColor('/extra-usage')}`;
|
|
529
528
|
},
|
|
530
529
|
cooldownSessions: 3,
|
|
531
530
|
isRelevant: async () => shouldShowOverageCreditUpsell(),
|
|
532
531
|
},
|
|
533
532
|
{
|
|
534
533
|
id: 'feedback-command',
|
|
535
|
-
content: async () => '
|
|
534
|
+
content: async () => '¡Usa /feedback para ayudarnos a mejorar!',
|
|
536
535
|
cooldownSessions: 15,
|
|
537
536
|
async isRelevant() {
|
|
538
537
|
if (process.env.USER_TYPE === 'ant') {
|
package/dist/src/utils/auth.js
CHANGED
|
@@ -1503,6 +1503,11 @@ export function getMiniMaxAccessToken() {
|
|
|
1503
1503
|
getStoredProviderApiKey('minimax', getResolvedProviderProfileId('minimax')) ||
|
|
1504
1504
|
null);
|
|
1505
1505
|
}
|
|
1506
|
+
export function getNvidiaAccessToken() {
|
|
1507
|
+
return (process.env.NVIDIA_API_KEY ||
|
|
1508
|
+
getStoredProviderApiKey('nvidia', getResolvedProviderProfileId('nvidia')) ||
|
|
1509
|
+
null);
|
|
1510
|
+
}
|
|
1506
1511
|
export function getOllamaAccessToken() {
|
|
1507
1512
|
return 'ollama';
|
|
1508
1513
|
}
|
|
@@ -1525,6 +1530,8 @@ export function getOpenAICompatibleAccessToken(provider = getAPIProvider()) {
|
|
|
1525
1530
|
return getZAIAccessToken();
|
|
1526
1531
|
case 'minimax':
|
|
1527
1532
|
return getMiniMaxAccessToken();
|
|
1533
|
+
case 'nvidia':
|
|
1534
|
+
return getNvidiaAccessToken();
|
|
1528
1535
|
case 'ollama':
|
|
1529
1536
|
return getOllamaAccessToken();
|
|
1530
1537
|
case 'ollama-cloud':
|
|
@@ -8,6 +8,7 @@ const DEFAULT_PROVIDER_BASE_URLS = {
|
|
|
8
8
|
'gemini-google': 'https://generativelanguage.googleapis.com/v1beta/openai',
|
|
9
9
|
zai: 'https://api.z.ai/api/coding/paas/v4',
|
|
10
10
|
minimax: 'https://api.minimax.io/anthropic',
|
|
11
|
+
nvidia: 'https://integrate.api.nvidia.com/v1',
|
|
11
12
|
};
|
|
12
13
|
function trimTrailingSlash(value) {
|
|
13
14
|
return value.endsWith('/') ? value.slice(0, -1) : value;
|
|
@@ -65,7 +66,8 @@ export function normalizeProviderBaseUrl(provider, rawValue) {
|
|
|
65
66
|
if (provider === 'zai' ||
|
|
66
67
|
provider === 'minimax' ||
|
|
67
68
|
provider === 'gemini-api' ||
|
|
68
|
-
provider === 'gemini-google'
|
|
69
|
+
provider === 'gemini-google' ||
|
|
70
|
+
provider === 'nvidia') {
|
|
69
71
|
return trimTrailingSlash(normalized);
|
|
70
72
|
}
|
|
71
73
|
return ensureV1Suffix(normalized);
|
|
@@ -95,6 +95,18 @@ export const VISIBLE_PROVIDERS = [
|
|
|
95
95
|
},
|
|
96
96
|
implemented: true,
|
|
97
97
|
},
|
|
98
|
+
{
|
|
99
|
+
id: 'nvidia',
|
|
100
|
+
label: 'NVIDIA API',
|
|
101
|
+
description: 'API key propia de NVIDIA NIM / build.nvidia.com. Luego elige un modelo en /model.',
|
|
102
|
+
setup: {
|
|
103
|
+
kind: 'api-key',
|
|
104
|
+
intro: 'Pega tu API key de NVIDIA.',
|
|
105
|
+
nextStep: 'Despues, elige un modelo compatible desde /model.',
|
|
106
|
+
actionLabel: 'Pegar API key',
|
|
107
|
+
},
|
|
108
|
+
implemented: true,
|
|
109
|
+
},
|
|
98
110
|
{
|
|
99
111
|
id: 'claude',
|
|
100
112
|
label: 'Claude (Anthropic)',
|
|
@@ -95,6 +95,8 @@ function getProviderLabel(provider) {
|
|
|
95
95
|
return 'Z.AI';
|
|
96
96
|
case 'minimax':
|
|
97
97
|
return 'MiniMax';
|
|
98
|
+
case 'nvidia':
|
|
99
|
+
return 'NVIDIA NIM';
|
|
98
100
|
default:
|
|
99
101
|
return 'OpenAI';
|
|
100
102
|
}
|
|
@@ -132,6 +134,10 @@ function getProviderBaseUrl(provider) {
|
|
|
132
134
|
return trimTrailingSlash(process.env.MINIMAX_BASE_URL ||
|
|
133
135
|
getConfiguredProviderBaseUrl('minimax') ||
|
|
134
136
|
'https://api.minimax.io/anthropic');
|
|
137
|
+
case 'nvidia':
|
|
138
|
+
return ensureV1Suffix(process.env.NVIDIA_BASE_URL ||
|
|
139
|
+
getConfiguredProviderBaseUrl('nvidia') ||
|
|
140
|
+
'https://integrate.api.nvidia.com/v1');
|
|
135
141
|
default:
|
|
136
142
|
return ensureV1Suffix(process.env.OPENAI_API_BASE_URL ||
|
|
137
143
|
process.env.OPENAI_BASE_URL ||
|
|
@@ -13,12 +13,12 @@ export function toProviderPreference(provider) {
|
|
|
13
13
|
return 'ollama-cloud';
|
|
14
14
|
if (provider === 'gemini-api')
|
|
15
15
|
return 'gemini-api';
|
|
16
|
-
if (provider === 'gemini-google')
|
|
17
|
-
return 'gemini-google';
|
|
18
16
|
if (provider === 'zai')
|
|
19
17
|
return 'zai';
|
|
20
18
|
if (provider === 'minimax')
|
|
21
19
|
return 'minimax';
|
|
20
|
+
if (provider === 'nvidia')
|
|
21
|
+
return 'nvidia';
|
|
22
22
|
return 'claude';
|
|
23
23
|
}
|
|
24
24
|
export function getStoredModelForProvider(provider) {
|
|
@@ -40,10 +40,10 @@ export function switchProviderPreference(params) {
|
|
|
40
40
|
params.currentProvider === 'openrouter' ||
|
|
41
41
|
params.currentProvider === 'ollama' ||
|
|
42
42
|
params.currentProvider === 'ollama-cloud' ||
|
|
43
|
-
params.currentProvider === 'gemini-api' ||
|
|
44
43
|
params.currentProvider === 'gemini-google' ||
|
|
45
44
|
params.currentProvider === 'zai' ||
|
|
46
|
-
params.currentProvider === 'minimax'
|
|
45
|
+
params.currentProvider === 'minimax' ||
|
|
46
|
+
params.currentProvider === 'nvidia'
|
|
47
47
|
? params.currentProvider
|
|
48
48
|
: toProviderPreference(params.currentProvider);
|
|
49
49
|
if (isProfiledProvider(sourceProvider)) {
|
|
@@ -157,6 +157,18 @@ export function isMiniMaxProviderConfigured() {
|
|
|
157
157
|
return Boolean(process.env.MINIMAX_API_KEY);
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
|
+
export function isNvidiaProviderConfigured() {
|
|
161
|
+
try {
|
|
162
|
+
const storage = getSecureStorage().read();
|
|
163
|
+
const scopedKeys = Object.entries(storage?.providerProfileApiKeys ?? {}).some(([key, value]) => key.startsWith('nvidia/') && typeof value === 'string' && value.trim());
|
|
164
|
+
return Boolean(process.env.NVIDIA_API_KEY ||
|
|
165
|
+
storage?.providerApiKeys?.nvidia ||
|
|
166
|
+
scopedKeys);
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
return Boolean(process.env.NVIDIA_API_KEY);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
160
172
|
export function isOpenAICompatibleProvider(provider) {
|
|
161
173
|
return (provider === 'openai' ||
|
|
162
174
|
provider === 'openrouter' ||
|
|
@@ -164,7 +176,8 @@ export function isOpenAICompatibleProvider(provider) {
|
|
|
164
176
|
provider === 'ollama-cloud' ||
|
|
165
177
|
provider === 'gemini-api' ||
|
|
166
178
|
provider === 'gemini-google' ||
|
|
167
|
-
provider === 'zai'
|
|
179
|
+
provider === 'zai' ||
|
|
180
|
+
provider === 'nvidia');
|
|
168
181
|
}
|
|
169
182
|
export function hasDualProviderSessions() {
|
|
170
183
|
return ((isOpenAIProviderConfigured() ||
|
|
@@ -174,7 +187,8 @@ export function hasDualProviderSessions() {
|
|
|
174
187
|
isGeminiApiProviderConfigured() ||
|
|
175
188
|
isGeminiGoogleProviderConfigured() ||
|
|
176
189
|
isZAIProviderConfigured() ||
|
|
177
|
-
isMiniMaxProviderConfigured()
|
|
190
|
+
isMiniMaxProviderConfigured() ||
|
|
191
|
+
isNvidiaProviderConfigured()) &&
|
|
178
192
|
hasStoredClaudeAIOAuthToken());
|
|
179
193
|
}
|
|
180
194
|
export function getAPIProvider() {
|
|
@@ -211,6 +225,8 @@ export function getAPIProvider() {
|
|
|
211
225
|
return 'zai';
|
|
212
226
|
if (preference === 'minimax')
|
|
213
227
|
return 'minimax';
|
|
228
|
+
if (preference === 'nvidia')
|
|
229
|
+
return 'nvidia';
|
|
214
230
|
}
|
|
215
231
|
catch {
|
|
216
232
|
// Config no disponible en arranque temprano.
|
|
@@ -223,6 +239,7 @@ export function getAPIProvider() {
|
|
|
223
239
|
const geminiGoogleConfigured = isGeminiGoogleProviderConfigured();
|
|
224
240
|
const zaiConfigured = isZAIProviderConfigured();
|
|
225
241
|
const minimaxConfigured = isMiniMaxProviderConfigured();
|
|
242
|
+
const nvidiaConfigured = isNvidiaProviderConfigured();
|
|
226
243
|
if (openAIConfigured) {
|
|
227
244
|
return 'openai';
|
|
228
245
|
}
|
|
@@ -235,6 +252,9 @@ export function getAPIProvider() {
|
|
|
235
252
|
if (minimaxConfigured) {
|
|
236
253
|
return 'minimax';
|
|
237
254
|
}
|
|
255
|
+
if (nvidiaConfigured) {
|
|
256
|
+
return 'nvidia';
|
|
257
|
+
}
|
|
238
258
|
if (geminiApiConfigured) {
|
|
239
259
|
return 'gemini-api';
|
|
240
260
|
}
|
|
@@ -78,7 +78,8 @@ async function validateAgainstProviderCatalog(modelName, provider) {
|
|
|
78
78
|
if (provider !== 'openrouter' &&
|
|
79
79
|
provider !== 'ollama' &&
|
|
80
80
|
provider !== 'zai' &&
|
|
81
|
-
provider !== 'minimax'
|
|
81
|
+
provider !== 'minimax' &&
|
|
82
|
+
provider !== 'nvidia') {
|
|
82
83
|
return null;
|
|
83
84
|
}
|
|
84
85
|
const providerModels = await fetchProviderModels(provider);
|
|
@@ -162,7 +163,7 @@ function handleProviderAwareError(error, modelName, provider) {
|
|
|
162
163
|
if (lowerMessage.includes('no credentials were found') ||
|
|
163
164
|
status === 401 ||
|
|
164
165
|
status === 403) {
|
|
165
|
-
if (provider === 'openrouter' || provider === 'zai' || provider === 'minimax') {
|
|
166
|
+
if (provider === 'openrouter' || provider === 'zai' || provider === 'minimax' || provider === 'nvidia') {
|
|
166
167
|
return {
|
|
167
168
|
valid: false,
|
|
168
169
|
error: `${providerLabel} credentials are missing or invalid. Use /login and configure ${providerLabel}.`,
|
|
@@ -251,6 +252,8 @@ function getProviderLabel(provider) {
|
|
|
251
252
|
return 'Z.AI';
|
|
252
253
|
case 'minimax':
|
|
253
254
|
return 'MiniMax';
|
|
255
|
+
case 'nvidia':
|
|
256
|
+
return 'NVIDIA NIM';
|
|
254
257
|
default:
|
|
255
258
|
return 'Context';
|
|
256
259
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Release notes come from the upstream changelog in English. Keep a small,
|
|
3
|
+
* deterministic translation layer for the home feed and /release-notes so the
|
|
4
|
+
* Spanish UI does not regress when known upstream notes are shown.
|
|
5
|
+
*/
|
|
6
|
+
export function translateReleaseNoteToSpanish(note) {
|
|
7
|
+
const trimmed = note.trim();
|
|
8
|
+
if (trimmed.startsWith('Fixed OAuth authentication failing with a 401 retry loop')) {
|
|
9
|
+
return 'Se corrigió un bucle de reintentos 401 en la autenticación OAuth cuando `CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1` está configurado.';
|
|
10
|
+
}
|
|
11
|
+
if (trimmed.startsWith('Added `ANTHROPIC_BEDROCK_SERVICE_TIER` environment variable')) {
|
|
12
|
+
return 'Se agregó la variable de entorno `ANTHROPIC_BEDROCK_SERVICE_TIER` para seleccionar el tier de servicio de Bedrock (`default`, `priority`, etc.).';
|
|
13
|
+
}
|
|
14
|
+
if (trimmed.startsWith('Pasting a PR URL into the `/resume` search box now finds the session')) {
|
|
15
|
+
return 'Pegar una URL de PR en la búsqueda de `/resume` ahora encuentra la sesión que creó esa PR.';
|
|
16
|
+
}
|
|
17
|
+
return note;
|
|
18
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iaforged/context-code",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.90",
|
|
4
4
|
"description": "Context Code es un asistente de desarrollo para la terminal. Puede revisar tu proyecto, editar archivos, ejecutar comandos y apoyarte en tareas reales de programacion.",
|
|
5
5
|
"author": "Context AI",
|
|
6
6
|
"license": "MIT",
|