@poolzin/pool-bot 2026.2.4 → 2026.2.5
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/agents/model-auth.js +1 -0
- package/dist/agents/model-forward-compat.js +187 -0
- package/dist/agents/pi-embedded-runner/model.js +10 -56
- package/dist/browser/constants.js +1 -1
- package/dist/browser/profiles.js +1 -1
- package/dist/build-info.json +3 -3
- package/dist/cli/program/register.onboard.js +10 -0
- package/dist/commands/auth-choice-options.js +11 -0
- package/dist/commands/auth-choice.apply.api-providers.js +55 -1
- package/dist/commands/auth-choice.apply.plugin-provider.js +1 -56
- package/dist/commands/auth-choice.preferred-provider.js +1 -0
- package/dist/commands/models/auth.js +1 -58
- package/dist/commands/models/list.errors.js +14 -0
- package/dist/commands/models/list.list-command.js +32 -21
- package/dist/commands/models/list.registry.js +120 -28
- package/dist/commands/models/list.status-command.js +1 -0
- package/dist/commands/models/shared.js +14 -0
- package/dist/commands/onboard-auth.config-core.js +60 -2
- package/dist/commands/onboard-auth.credentials.js +12 -1
- package/dist/commands/onboard-auth.js +3 -3
- package/dist/commands/onboard-auth.models.js +22 -0
- package/dist/commands/onboard-non-interactive/local/auth-choice-inference.js +1 -0
- package/dist/commands/onboard-non-interactive/local/auth-choice.js +21 -1
- package/dist/commands/provider-auth-helpers.js +61 -0
- package/dist/terminal/theme.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { DEFAULT_CONTEXT_TOKENS } from "./defaults.js";
|
|
2
|
+
import { normalizeModelCompat } from "./model-compat.js";
|
|
3
|
+
import { normalizeProviderId } from "./model-selection.js";
|
|
4
|
+
const OPENAI_CODEX_GPT_53_MODEL_ID = "gpt-5.3-codex";
|
|
5
|
+
const OPENAI_CODEX_TEMPLATE_MODEL_IDS = ["gpt-5.2-codex"];
|
|
6
|
+
const ANTHROPIC_OPUS_46_MODEL_ID = "claude-opus-4-6";
|
|
7
|
+
const ANTHROPIC_OPUS_46_DOT_MODEL_ID = "claude-opus-4.6";
|
|
8
|
+
const ANTHROPIC_OPUS_TEMPLATE_MODEL_IDS = ["claude-opus-4-5", "claude-opus-4.5"];
|
|
9
|
+
const ZAI_GLM5_MODEL_ID = "glm-5";
|
|
10
|
+
const ZAI_GLM5_TEMPLATE_MODEL_IDS = ["glm-4.7"];
|
|
11
|
+
const ANTIGRAVITY_OPUS_46_MODEL_ID = "claude-opus-4-6";
|
|
12
|
+
const ANTIGRAVITY_OPUS_46_DOT_MODEL_ID = "claude-opus-4.6";
|
|
13
|
+
const ANTIGRAVITY_OPUS_TEMPLATE_MODEL_IDS = ["claude-opus-4-5", "claude-opus-4.5"];
|
|
14
|
+
const ANTIGRAVITY_OPUS_46_THINKING_MODEL_ID = "claude-opus-4-6-thinking";
|
|
15
|
+
const ANTIGRAVITY_OPUS_46_DOT_THINKING_MODEL_ID = "claude-opus-4.6-thinking";
|
|
16
|
+
const ANTIGRAVITY_OPUS_THINKING_TEMPLATE_MODEL_IDS = [
|
|
17
|
+
"claude-opus-4-5-thinking",
|
|
18
|
+
"claude-opus-4.5-thinking",
|
|
19
|
+
];
|
|
20
|
+
export const ANTIGRAVITY_OPUS_46_FORWARD_COMPAT_CANDIDATES = [
|
|
21
|
+
{
|
|
22
|
+
id: ANTIGRAVITY_OPUS_46_THINKING_MODEL_ID,
|
|
23
|
+
templatePrefixes: [
|
|
24
|
+
"google-antigravity/claude-opus-4-5-thinking",
|
|
25
|
+
"google-antigravity/claude-opus-4.5-thinking",
|
|
26
|
+
],
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: ANTIGRAVITY_OPUS_46_MODEL_ID,
|
|
30
|
+
templatePrefixes: ["google-antigravity/claude-opus-4-5", "google-antigravity/claude-opus-4.5"],
|
|
31
|
+
},
|
|
32
|
+
];
|
|
33
|
+
function resolveOpenAICodexGpt53FallbackModel(provider, modelId, modelRegistry) {
|
|
34
|
+
const normalizedProvider = normalizeProviderId(provider);
|
|
35
|
+
const trimmedModelId = modelId.trim();
|
|
36
|
+
if (normalizedProvider !== "openai-codex") {
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
if (trimmedModelId.toLowerCase() !== OPENAI_CODEX_GPT_53_MODEL_ID) {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
for (const templateId of OPENAI_CODEX_TEMPLATE_MODEL_IDS) {
|
|
43
|
+
const template = modelRegistry.find(normalizedProvider, templateId);
|
|
44
|
+
if (!template) {
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
return normalizeModelCompat({
|
|
48
|
+
...template,
|
|
49
|
+
id: trimmedModelId,
|
|
50
|
+
name: trimmedModelId,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
return normalizeModelCompat({
|
|
54
|
+
id: trimmedModelId,
|
|
55
|
+
name: trimmedModelId,
|
|
56
|
+
api: "openai-codex-responses",
|
|
57
|
+
provider: normalizedProvider,
|
|
58
|
+
baseUrl: "https://chatgpt.com/backend-api",
|
|
59
|
+
reasoning: true,
|
|
60
|
+
input: ["text", "image"],
|
|
61
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
62
|
+
contextWindow: DEFAULT_CONTEXT_TOKENS,
|
|
63
|
+
maxTokens: DEFAULT_CONTEXT_TOKENS,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
function resolveAnthropicOpus46ForwardCompatModel(provider, modelId, modelRegistry) {
|
|
67
|
+
const normalizedProvider = normalizeProviderId(provider);
|
|
68
|
+
if (normalizedProvider !== "anthropic") {
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
const trimmedModelId = modelId.trim();
|
|
72
|
+
const lower = trimmedModelId.toLowerCase();
|
|
73
|
+
const isOpus46 = lower === ANTHROPIC_OPUS_46_MODEL_ID ||
|
|
74
|
+
lower === ANTHROPIC_OPUS_46_DOT_MODEL_ID ||
|
|
75
|
+
lower.startsWith(`${ANTHROPIC_OPUS_46_MODEL_ID}-`) ||
|
|
76
|
+
lower.startsWith(`${ANTHROPIC_OPUS_46_DOT_MODEL_ID}-`);
|
|
77
|
+
if (!isOpus46) {
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
const templateIds = [];
|
|
81
|
+
if (lower.startsWith(ANTHROPIC_OPUS_46_MODEL_ID)) {
|
|
82
|
+
templateIds.push(lower.replace(ANTHROPIC_OPUS_46_MODEL_ID, "claude-opus-4-5"));
|
|
83
|
+
}
|
|
84
|
+
if (lower.startsWith(ANTHROPIC_OPUS_46_DOT_MODEL_ID)) {
|
|
85
|
+
templateIds.push(lower.replace(ANTHROPIC_OPUS_46_DOT_MODEL_ID, "claude-opus-4.5"));
|
|
86
|
+
}
|
|
87
|
+
templateIds.push(...ANTHROPIC_OPUS_TEMPLATE_MODEL_IDS);
|
|
88
|
+
for (const templateId of [...new Set(templateIds)].filter(Boolean)) {
|
|
89
|
+
const template = modelRegistry.find(normalizedProvider, templateId);
|
|
90
|
+
if (!template) {
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
return normalizeModelCompat({
|
|
94
|
+
...template,
|
|
95
|
+
id: trimmedModelId,
|
|
96
|
+
name: trimmedModelId,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
// Z.ai's GLM-5 may not be present in pi-ai's built-in model catalog yet.
|
|
102
|
+
// When a user configures zai/glm-5 without a models.json entry, clone glm-4.7 as a forward-compat fallback.
|
|
103
|
+
function resolveZaiGlm5ForwardCompatModel(provider, modelId, modelRegistry) {
|
|
104
|
+
if (normalizeProviderId(provider) !== "zai") {
|
|
105
|
+
return undefined;
|
|
106
|
+
}
|
|
107
|
+
const trimmed = modelId.trim();
|
|
108
|
+
const lower = trimmed.toLowerCase();
|
|
109
|
+
if (lower !== ZAI_GLM5_MODEL_ID && !lower.startsWith(`${ZAI_GLM5_MODEL_ID}-`)) {
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
112
|
+
for (const templateId of ZAI_GLM5_TEMPLATE_MODEL_IDS) {
|
|
113
|
+
const template = modelRegistry.find("zai", templateId);
|
|
114
|
+
if (!template) {
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
return normalizeModelCompat({
|
|
118
|
+
...template,
|
|
119
|
+
id: trimmed,
|
|
120
|
+
name: trimmed,
|
|
121
|
+
reasoning: true,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
return normalizeModelCompat({
|
|
125
|
+
id: trimmed,
|
|
126
|
+
name: trimmed,
|
|
127
|
+
api: "openai-completions",
|
|
128
|
+
provider: "zai",
|
|
129
|
+
reasoning: true,
|
|
130
|
+
input: ["text"],
|
|
131
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
132
|
+
contextWindow: DEFAULT_CONTEXT_TOKENS,
|
|
133
|
+
maxTokens: DEFAULT_CONTEXT_TOKENS,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
function resolveAntigravityOpus46ForwardCompatModel(provider, modelId, modelRegistry) {
|
|
137
|
+
const normalizedProvider = normalizeProviderId(provider);
|
|
138
|
+
if (normalizedProvider !== "google-antigravity") {
|
|
139
|
+
return undefined;
|
|
140
|
+
}
|
|
141
|
+
const trimmedModelId = modelId.trim();
|
|
142
|
+
const lower = trimmedModelId.toLowerCase();
|
|
143
|
+
const isOpus46 = lower === ANTIGRAVITY_OPUS_46_MODEL_ID ||
|
|
144
|
+
lower === ANTIGRAVITY_OPUS_46_DOT_MODEL_ID ||
|
|
145
|
+
lower.startsWith(`${ANTIGRAVITY_OPUS_46_MODEL_ID}-`) ||
|
|
146
|
+
lower.startsWith(`${ANTIGRAVITY_OPUS_46_DOT_MODEL_ID}-`);
|
|
147
|
+
const isOpus46Thinking = lower === ANTIGRAVITY_OPUS_46_THINKING_MODEL_ID ||
|
|
148
|
+
lower === ANTIGRAVITY_OPUS_46_DOT_THINKING_MODEL_ID ||
|
|
149
|
+
lower.startsWith(`${ANTIGRAVITY_OPUS_46_THINKING_MODEL_ID}-`) ||
|
|
150
|
+
lower.startsWith(`${ANTIGRAVITY_OPUS_46_DOT_THINKING_MODEL_ID}-`);
|
|
151
|
+
if (!isOpus46 && !isOpus46Thinking) {
|
|
152
|
+
return undefined;
|
|
153
|
+
}
|
|
154
|
+
const templateIds = [];
|
|
155
|
+
if (lower.startsWith(ANTIGRAVITY_OPUS_46_MODEL_ID)) {
|
|
156
|
+
templateIds.push(lower.replace(ANTIGRAVITY_OPUS_46_MODEL_ID, "claude-opus-4-5"));
|
|
157
|
+
}
|
|
158
|
+
if (lower.startsWith(ANTIGRAVITY_OPUS_46_DOT_MODEL_ID)) {
|
|
159
|
+
templateIds.push(lower.replace(ANTIGRAVITY_OPUS_46_DOT_MODEL_ID, "claude-opus-4.5"));
|
|
160
|
+
}
|
|
161
|
+
if (lower.startsWith(ANTIGRAVITY_OPUS_46_THINKING_MODEL_ID)) {
|
|
162
|
+
templateIds.push(lower.replace(ANTIGRAVITY_OPUS_46_THINKING_MODEL_ID, "claude-opus-4-5-thinking"));
|
|
163
|
+
}
|
|
164
|
+
if (lower.startsWith(ANTIGRAVITY_OPUS_46_DOT_THINKING_MODEL_ID)) {
|
|
165
|
+
templateIds.push(lower.replace(ANTIGRAVITY_OPUS_46_DOT_THINKING_MODEL_ID, "claude-opus-4.5-thinking"));
|
|
166
|
+
}
|
|
167
|
+
templateIds.push(...ANTIGRAVITY_OPUS_TEMPLATE_MODEL_IDS);
|
|
168
|
+
templateIds.push(...ANTIGRAVITY_OPUS_THINKING_TEMPLATE_MODEL_IDS);
|
|
169
|
+
for (const templateId of [...new Set(templateIds)].filter(Boolean)) {
|
|
170
|
+
const template = modelRegistry.find(normalizedProvider, templateId);
|
|
171
|
+
if (!template) {
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
return normalizeModelCompat({
|
|
175
|
+
...template,
|
|
176
|
+
id: trimmedModelId,
|
|
177
|
+
name: trimmedModelId,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
return undefined;
|
|
181
|
+
}
|
|
182
|
+
export function resolveForwardCompatModel(provider, modelId, modelRegistry) {
|
|
183
|
+
return (resolveOpenAICodexGpt53FallbackModel(provider, modelId, modelRegistry) ??
|
|
184
|
+
resolveAnthropicOpus46ForwardCompatModel(provider, modelId, modelRegistry) ??
|
|
185
|
+
resolveZaiGlm5ForwardCompatModel(provider, modelId, modelRegistry) ??
|
|
186
|
+
resolveAntigravityOpus46ForwardCompatModel(provider, modelId, modelRegistry));
|
|
187
|
+
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { discoverAuthStorage, discoverModels } from "../pi-model-discovery.js";
|
|
2
1
|
import { resolvePoolbotAgentDir } from "../agent-paths.js";
|
|
3
2
|
import { DEFAULT_CONTEXT_TOKENS } from "../defaults.js";
|
|
4
3
|
import { normalizeModelCompat } from "../model-compat.js";
|
|
4
|
+
import { resolveForwardCompatModel } from "../model-forward-compat.js";
|
|
5
5
|
import { normalizeProviderId } from "../model-selection.js";
|
|
6
|
+
import { discoverAuthStorage, discoverModels, } from "../pi-model-discovery.js";
|
|
6
7
|
export function buildInlineProviderModels(providers) {
|
|
7
8
|
return Object.entries(providers).flatMap(([providerId, entry]) => {
|
|
8
9
|
const trimmed = providerId.trim();
|
|
@@ -12,7 +13,7 @@ export function buildInlineProviderModels(providers) {
|
|
|
12
13
|
...model,
|
|
13
14
|
provider: trimmed,
|
|
14
15
|
baseUrl: entry?.baseUrl,
|
|
15
|
-
|
|
16
|
+
api: model.api ?? entry?.api,
|
|
16
17
|
}));
|
|
17
18
|
});
|
|
18
19
|
}
|
|
@@ -32,65 +33,12 @@ export function buildModelAliasLines(cfg) {
|
|
|
32
33
|
.toSorted((a, b) => a.alias.localeCompare(b.alias))
|
|
33
34
|
.map((entry) => `- ${entry.alias}: ${entry.model}`);
|
|
34
35
|
}
|
|
35
|
-
// Well-known model IDs for forward-compatible resolution
|
|
36
|
-
export const OPENAI_CODEX_GPT_53_MODEL_ID = "codex-gpt-5.3";
|
|
37
|
-
export const OPENAI_CODEX_TEMPLATE_MODEL_IDS = ["codex-mini-*"];
|
|
38
|
-
export const ANTHROPIC_OPUS_46_MODEL_ID = "claude-opus-4-0624";
|
|
39
|
-
export const ANTHROPIC_OPUS_46_DOT_MODEL_ID = "claude-opus-4.6";
|
|
40
|
-
export const ANTHROPIC_OPUS_TEMPLATE_MODEL_IDS = ["claude-opus-4-*", "claude-opus-4.*"];
|
|
41
|
-
/**
|
|
42
|
-
* Resolve forward-compat fallback for OpenAI codex-gpt-5.3 requests.
|
|
43
|
-
* If the exact model is not in the registry, try `codex-mini-*` template matches.
|
|
44
|
-
*/
|
|
45
|
-
export function resolveOpenAICodexGpt53FallbackModel(modelRegistry, provider) {
|
|
46
|
-
for (const templateId of OPENAI_CODEX_TEMPLATE_MODEL_IDS) {
|
|
47
|
-
const match = modelRegistry.find(provider, templateId);
|
|
48
|
-
if (match)
|
|
49
|
-
return match;
|
|
50
|
-
}
|
|
51
|
-
return null;
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Resolve forward-compat fallback for Anthropic claude-opus-4.6 requests.
|
|
55
|
-
* If the exact model is not in the registry, try `claude-opus-4-*` template matches.
|
|
56
|
-
*/
|
|
57
|
-
export function resolveAnthropicOpus46ForwardCompatModel(modelRegistry, provider, modelId) {
|
|
58
|
-
if (modelId !== ANTHROPIC_OPUS_46_MODEL_ID && modelId !== ANTHROPIC_OPUS_46_DOT_MODEL_ID) {
|
|
59
|
-
return null;
|
|
60
|
-
}
|
|
61
|
-
for (const templateId of ANTHROPIC_OPUS_TEMPLATE_MODEL_IDS) {
|
|
62
|
-
const match = modelRegistry.find(provider, templateId);
|
|
63
|
-
if (match)
|
|
64
|
-
return match;
|
|
65
|
-
}
|
|
66
|
-
return null;
|
|
67
|
-
}
|
|
68
36
|
export function resolveModel(provider, modelId, agentDir, cfg) {
|
|
69
37
|
const resolvedAgentDir = agentDir ?? resolvePoolbotAgentDir();
|
|
70
38
|
const authStorage = discoverAuthStorage(resolvedAgentDir);
|
|
71
39
|
const modelRegistry = discoverModels(authStorage, resolvedAgentDir);
|
|
72
40
|
const model = modelRegistry.find(provider, modelId);
|
|
73
41
|
if (!model) {
|
|
74
|
-
// Try codex forward-compat fallback
|
|
75
|
-
if (modelId === OPENAI_CODEX_GPT_53_MODEL_ID) {
|
|
76
|
-
const codexFallback = resolveOpenAICodexGpt53FallbackModel(modelRegistry, provider);
|
|
77
|
-
if (codexFallback) {
|
|
78
|
-
return {
|
|
79
|
-
model: normalizeModelCompat(codexFallback),
|
|
80
|
-
authStorage,
|
|
81
|
-
modelRegistry,
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
// Try Anthropic opus forward-compat fallback
|
|
86
|
-
const opusFallback = resolveAnthropicOpus46ForwardCompatModel(modelRegistry, provider, modelId);
|
|
87
|
-
if (opusFallback) {
|
|
88
|
-
return {
|
|
89
|
-
model: normalizeModelCompat(opusFallback),
|
|
90
|
-
authStorage,
|
|
91
|
-
modelRegistry,
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
42
|
const providers = cfg?.models?.providers ?? {};
|
|
95
43
|
const inlineModels = buildInlineProviderModels(providers);
|
|
96
44
|
const normalizedProvider = normalizeProviderId(provider);
|
|
@@ -103,6 +51,12 @@ export function resolveModel(provider, modelId, agentDir, cfg) {
|
|
|
103
51
|
modelRegistry,
|
|
104
52
|
};
|
|
105
53
|
}
|
|
54
|
+
// Forward-compat fallbacks must be checked BEFORE the generic providerCfg fallback.
|
|
55
|
+
// Otherwise, configured providers can default to a generic API and break specific transports.
|
|
56
|
+
const forwardCompat = resolveForwardCompatModel(provider, modelId, modelRegistry);
|
|
57
|
+
if (forwardCompat) {
|
|
58
|
+
return { model: forwardCompat, authStorage, modelRegistry };
|
|
59
|
+
}
|
|
106
60
|
const providerCfg = providers[provider];
|
|
107
61
|
if (providerCfg || modelId.startsWith("mock-")) {
|
|
108
62
|
const fallbackModel = normalizeModelCompat({
|
|
@@ -110,12 +64,12 @@ export function resolveModel(provider, modelId, agentDir, cfg) {
|
|
|
110
64
|
name: modelId,
|
|
111
65
|
api: providerCfg?.api ?? "openai-responses",
|
|
112
66
|
provider,
|
|
67
|
+
baseUrl: providerCfg?.baseUrl,
|
|
113
68
|
reasoning: false,
|
|
114
69
|
input: ["text"],
|
|
115
70
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
116
71
|
contextWindow: providerCfg?.models?.[0]?.contextWindow ?? DEFAULT_CONTEXT_TOKENS,
|
|
117
72
|
maxTokens: providerCfg?.models?.[0]?.maxTokens ?? DEFAULT_CONTEXT_TOKENS,
|
|
118
|
-
baseUrl: providerCfg?.baseUrl,
|
|
119
73
|
});
|
|
120
74
|
return { model: fallbackModel, authStorage, modelRegistry };
|
|
121
75
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export const DEFAULT_CLAWD_BROWSER_ENABLED = true;
|
|
2
2
|
export const DEFAULT_BROWSER_EVALUATE_ENABLED = true;
|
|
3
|
-
export const DEFAULT_CLAWD_BROWSER_COLOR = "#
|
|
3
|
+
export const DEFAULT_CLAWD_BROWSER_COLOR = "#A855F7";
|
|
4
4
|
export const DEFAULT_CLAWD_BROWSER_PROFILE_NAME = "clawd";
|
|
5
5
|
export const DEFAULT_BROWSER_DEFAULT_PROFILE_NAME = "chrome";
|
|
6
6
|
export const DEFAULT_AI_SNAPSHOT_MAX_CHARS = 80_000;
|
package/dist/browser/profiles.js
CHANGED
package/dist/build-info.json
CHANGED
|
@@ -46,6 +46,11 @@ export function registerOnboardCommand(program) {
|
|
|
46
46
|
.option("--synthetic-api-key <key>", "Synthetic API key")
|
|
47
47
|
.option("--venice-api-key <key>", "Venice API key")
|
|
48
48
|
.option("--opencode-zen-api-key <key>", "OpenCode Zen API key")
|
|
49
|
+
.option("--xai-api-key <key>", "xAI API key")
|
|
50
|
+
.option("--together-api-key <key>", "Together AI API key")
|
|
51
|
+
.option("--qianfan-api-key <key>", "Qianfan API key")
|
|
52
|
+
.option("--xiaomi-api-key <key>", "Xiaomi API key")
|
|
53
|
+
.option("--nvidia-api-key <key>", "NVIDIA API key")
|
|
49
54
|
.option("--gateway-port <port>", "Gateway port")
|
|
50
55
|
.option("--gateway-bind <mode>", "Gateway bind: loopback|tailnet|lan|auto|custom")
|
|
51
56
|
.option("--gateway-auth <mode>", "Gateway auth: token|password")
|
|
@@ -94,6 +99,11 @@ export function registerOnboardCommand(program) {
|
|
|
94
99
|
syntheticApiKey: opts.syntheticApiKey,
|
|
95
100
|
veniceApiKey: opts.veniceApiKey,
|
|
96
101
|
opencodeZenApiKey: opts.opencodeZenApiKey,
|
|
102
|
+
xaiApiKey: opts.xaiApiKey,
|
|
103
|
+
togetherApiKey: opts.togetherApiKey,
|
|
104
|
+
qianfanApiKey: opts.qianfanApiKey,
|
|
105
|
+
xiaomiApiKey: opts.xiaomiApiKey,
|
|
106
|
+
nvidiaApiKey: opts.nvidiaApiKey,
|
|
97
107
|
gatewayPort: typeof gatewayPort === "number" && Number.isFinite(gatewayPort)
|
|
98
108
|
? gatewayPort
|
|
99
109
|
: undefined,
|
|
@@ -35,6 +35,12 @@ const AUTH_CHOICE_GROUP_DEFS = [
|
|
|
35
35
|
hint: "API key",
|
|
36
36
|
choices: ["xai-api-key"],
|
|
37
37
|
},
|
|
38
|
+
{
|
|
39
|
+
value: "nvidia",
|
|
40
|
+
label: "NVIDIA (Free Tier)",
|
|
41
|
+
hint: "API key — 23+ frontier models",
|
|
42
|
+
choices: ["nvidia-api-key"],
|
|
43
|
+
},
|
|
38
44
|
{
|
|
39
45
|
value: "openrouter",
|
|
40
46
|
label: "OpenRouter",
|
|
@@ -129,6 +135,11 @@ export function buildAuthChoiceOptions(params) {
|
|
|
129
135
|
options.push({ value: "chutes", label: "Chutes (OAuth)" });
|
|
130
136
|
options.push({ value: "openai-api-key", label: "OpenAI API key" });
|
|
131
137
|
options.push({ value: "xai-api-key", label: "xAI (Grok) API key" });
|
|
138
|
+
options.push({
|
|
139
|
+
value: "nvidia-api-key",
|
|
140
|
+
label: "NVIDIA API key",
|
|
141
|
+
hint: "Free tier — Nemotron, DeepSeek, Kimi, Qwen, and more",
|
|
142
|
+
});
|
|
132
143
|
options.push({
|
|
133
144
|
value: "qianfan-api-key",
|
|
134
145
|
label: "Qianfan API key",
|
|
@@ -3,7 +3,7 @@ import { resolveEnvApiKey } from "../agents/model-auth.js";
|
|
|
3
3
|
import { formatApiKeyPreview, normalizeApiKeyInput, validateApiKeyInput, } from "./auth-choice.api-key.js";
|
|
4
4
|
import { applyDefaultModelChoice } from "./auth-choice.default-model.js";
|
|
5
5
|
import { applyGoogleGeminiModelDefault, GOOGLE_GEMINI_DEFAULT_MODEL, } from "./google-gemini-model-default.js";
|
|
6
|
-
import { applyAuthProfileConfig, applyCloudflareAiGatewayConfig, applyCloudflareAiGatewayProviderConfig, applyQianfanConfig, applyQianfanProviderConfig, applyKimiCodeConfig, applyKimiCodeProviderConfig, applyMoonshotConfig, applyMoonshotConfigCn, applyMoonshotProviderConfig, applyMoonshotProviderConfigCn, applyOpencodeZenConfig, applyOpencodeZenProviderConfig, applyOpenrouterConfig, applyOpenrouterProviderConfig, applySyntheticConfig, applySyntheticProviderConfig, applyTogetherConfig, applyTogetherProviderConfig, applyVeniceConfig, applyVeniceProviderConfig, applyVercelAiGatewayConfig, applyVercelAiGatewayProviderConfig, applyXiaomiConfig, applyXiaomiProviderConfig, applyZaiConfig, CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF, QIANFAN_DEFAULT_MODEL_REF, KIMI_CODING_MODEL_REF, MOONSHOT_DEFAULT_MODEL_REF, OPENROUTER_DEFAULT_MODEL_REF, SYNTHETIC_DEFAULT_MODEL_REF, TOGETHER_DEFAULT_MODEL_REF, VENICE_DEFAULT_MODEL_REF, VERCEL_AI_GATEWAY_DEFAULT_MODEL_REF, XIAOMI_DEFAULT_MODEL_REF, setCloudflareAiGatewayConfig, setQianfanApiKey, setGeminiApiKey, setKimiCodingApiKey, setMoonshotApiKey, setOpencodeZenApiKey, setOpenrouterApiKey, setSyntheticApiKey, setTogetherApiKey, setVeniceApiKey, setVercelAiGatewayApiKey, setXiaomiApiKey, setZaiApiKey, ZAI_DEFAULT_MODEL_REF, } from "./onboard-auth.js";
|
|
6
|
+
import { applyAuthProfileConfig, applyCloudflareAiGatewayConfig, applyCloudflareAiGatewayProviderConfig, applyQianfanConfig, applyQianfanProviderConfig, applyKimiCodeConfig, applyKimiCodeProviderConfig, applyMoonshotConfig, applyMoonshotConfigCn, applyMoonshotProviderConfig, applyMoonshotProviderConfigCn, applyOpencodeZenConfig, applyOpencodeZenProviderConfig, applyOpenrouterConfig, applyOpenrouterProviderConfig, applySyntheticConfig, applySyntheticProviderConfig, applyTogetherConfig, applyTogetherProviderConfig, applyVeniceConfig, applyVeniceProviderConfig, applyVercelAiGatewayConfig, applyVercelAiGatewayProviderConfig, applyXiaomiConfig, applyXiaomiProviderConfig, applyZaiConfig, applyNvidiaConfig, applyNvidiaProviderConfig, CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF, NVIDIA_DEFAULT_MODEL_REF, QIANFAN_DEFAULT_MODEL_REF, KIMI_CODING_MODEL_REF, MOONSHOT_DEFAULT_MODEL_REF, OPENROUTER_DEFAULT_MODEL_REF, SYNTHETIC_DEFAULT_MODEL_REF, TOGETHER_DEFAULT_MODEL_REF, VENICE_DEFAULT_MODEL_REF, VERCEL_AI_GATEWAY_DEFAULT_MODEL_REF, XIAOMI_DEFAULT_MODEL_REF, setCloudflareAiGatewayConfig, setQianfanApiKey, setGeminiApiKey, setKimiCodingApiKey, setMoonshotApiKey, setNvidiaApiKey, setOpencodeZenApiKey, setOpenrouterApiKey, setSyntheticApiKey, setTogetherApiKey, setVeniceApiKey, setVercelAiGatewayApiKey, setXiaomiApiKey, setZaiApiKey, ZAI_DEFAULT_MODEL_REF, } from "./onboard-auth.js";
|
|
7
7
|
import { OPENCODE_ZEN_DEFAULT_MODEL } from "./opencode-zen-model-default.js";
|
|
8
8
|
export async function applyAuthChoiceApiProviders(params) {
|
|
9
9
|
let nextConfig = params.config;
|
|
@@ -59,6 +59,9 @@ export async function applyAuthChoiceApiProviders(params) {
|
|
|
59
59
|
else if (params.opts.tokenProvider === "qianfan") {
|
|
60
60
|
authChoice = "qianfan-api-key";
|
|
61
61
|
}
|
|
62
|
+
else if (params.opts.tokenProvider === "nvidia") {
|
|
63
|
+
authChoice = "nvidia-api-key";
|
|
64
|
+
}
|
|
62
65
|
}
|
|
63
66
|
if (authChoice === "openrouter-api-key") {
|
|
64
67
|
const store = ensureAuthProfileStore(params.agentDir, {
|
|
@@ -786,5 +789,56 @@ export async function applyAuthChoiceApiProviders(params) {
|
|
|
786
789
|
}
|
|
787
790
|
return { config: nextConfig, agentModelOverride };
|
|
788
791
|
}
|
|
792
|
+
if (authChoice === "nvidia-api-key") {
|
|
793
|
+
let hasCredential = false;
|
|
794
|
+
if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "nvidia") {
|
|
795
|
+
setNvidiaApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir);
|
|
796
|
+
hasCredential = true;
|
|
797
|
+
}
|
|
798
|
+
if (!hasCredential) {
|
|
799
|
+
await params.prompter.note([
|
|
800
|
+
"Get your API key at: https://build.nvidia.com/settings/api-key",
|
|
801
|
+
"Free tier includes 1,000 requests/day across 23+ frontier models.",
|
|
802
|
+
].join("\n"), "NVIDIA");
|
|
803
|
+
}
|
|
804
|
+
const envKey = resolveEnvApiKey("nvidia");
|
|
805
|
+
if (envKey) {
|
|
806
|
+
const useExisting = await params.prompter.confirm({
|
|
807
|
+
message: `Use existing NVIDIA_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
|
|
808
|
+
initialValue: true,
|
|
809
|
+
});
|
|
810
|
+
if (useExisting) {
|
|
811
|
+
setNvidiaApiKey(envKey.apiKey, params.agentDir);
|
|
812
|
+
hasCredential = true;
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
if (!hasCredential) {
|
|
816
|
+
const key = await params.prompter.text({
|
|
817
|
+
message: "Enter NVIDIA API key",
|
|
818
|
+
validate: validateApiKeyInput,
|
|
819
|
+
});
|
|
820
|
+
setNvidiaApiKey(normalizeApiKeyInput(String(key)), params.agentDir);
|
|
821
|
+
}
|
|
822
|
+
nextConfig = applyAuthProfileConfig(nextConfig, {
|
|
823
|
+
profileId: "nvidia:default",
|
|
824
|
+
provider: "nvidia",
|
|
825
|
+
mode: "api_key",
|
|
826
|
+
});
|
|
827
|
+
{
|
|
828
|
+
const applied = await applyDefaultModelChoice({
|
|
829
|
+
config: nextConfig,
|
|
830
|
+
setDefaultModel: params.setDefaultModel,
|
|
831
|
+
defaultModel: NVIDIA_DEFAULT_MODEL_REF,
|
|
832
|
+
applyDefaultConfig: applyNvidiaConfig,
|
|
833
|
+
applyProviderConfig: applyNvidiaProviderConfig,
|
|
834
|
+
noteDefault: NVIDIA_DEFAULT_MODEL_REF,
|
|
835
|
+
noteAgentModel,
|
|
836
|
+
prompter: params.prompter,
|
|
837
|
+
});
|
|
838
|
+
nextConfig = applied.config;
|
|
839
|
+
agentModelOverride = applied.agentModelOverride ?? agentModelOverride;
|
|
840
|
+
}
|
|
841
|
+
return { config: nextConfig, agentModelOverride };
|
|
842
|
+
}
|
|
789
843
|
return null;
|
|
790
844
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { resolvePoolbotAgentDir } from "../agents/agent-paths.js";
|
|
2
2
|
import { resolveDefaultAgentId, resolveAgentDir, resolveAgentWorkspaceDir, } from "../agents/agent-scope.js";
|
|
3
3
|
import { upsertAuthProfile } from "../agents/auth-profiles.js";
|
|
4
|
-
import { normalizeProviderId } from "../agents/model-selection.js";
|
|
5
4
|
import { resolveDefaultAgentWorkspaceDir } from "../agents/workspace.js";
|
|
6
5
|
import { enablePluginInConfig } from "../plugins/enable.js";
|
|
7
6
|
import { resolvePluginProviders } from "../plugins/providers.js";
|
|
@@ -9,61 +8,7 @@ import { applyAuthProfileConfig } from "./onboard-auth.js";
|
|
|
9
8
|
import { openUrl } from "./onboard-helpers.js";
|
|
10
9
|
import { createVpsAwareOAuthHandlers } from "./oauth-flow.js";
|
|
11
10
|
import { isRemoteEnvironment } from "./oauth-env.js";
|
|
12
|
-
|
|
13
|
-
const normalized = normalizeProviderId(rawProvider);
|
|
14
|
-
return (providers.find((provider) => normalizeProviderId(provider.id) === normalized) ??
|
|
15
|
-
providers.find((provider) => provider.aliases?.some((alias) => normalizeProviderId(alias) === normalized) ?? false) ??
|
|
16
|
-
null);
|
|
17
|
-
}
|
|
18
|
-
function pickAuthMethod(provider, rawMethod) {
|
|
19
|
-
const raw = rawMethod?.trim();
|
|
20
|
-
if (!raw)
|
|
21
|
-
return null;
|
|
22
|
-
const normalized = raw.toLowerCase();
|
|
23
|
-
return (provider.auth.find((method) => method.id.toLowerCase() === normalized) ??
|
|
24
|
-
provider.auth.find((method) => method.label.toLowerCase() === normalized) ??
|
|
25
|
-
null);
|
|
26
|
-
}
|
|
27
|
-
function isPlainRecord(value) {
|
|
28
|
-
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
29
|
-
}
|
|
30
|
-
function mergeConfigPatch(base, patch) {
|
|
31
|
-
if (!isPlainRecord(base) || !isPlainRecord(patch)) {
|
|
32
|
-
return patch;
|
|
33
|
-
}
|
|
34
|
-
const next = { ...base };
|
|
35
|
-
for (const [key, value] of Object.entries(patch)) {
|
|
36
|
-
const existing = next[key];
|
|
37
|
-
if (isPlainRecord(existing) && isPlainRecord(value)) {
|
|
38
|
-
next[key] = mergeConfigPatch(existing, value);
|
|
39
|
-
}
|
|
40
|
-
else {
|
|
41
|
-
next[key] = value;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return next;
|
|
45
|
-
}
|
|
46
|
-
function applyDefaultModel(cfg, model) {
|
|
47
|
-
const models = { ...cfg.agents?.defaults?.models };
|
|
48
|
-
models[model] = models[model] ?? {};
|
|
49
|
-
const existingModel = cfg.agents?.defaults?.model;
|
|
50
|
-
return {
|
|
51
|
-
...cfg,
|
|
52
|
-
agents: {
|
|
53
|
-
...cfg.agents,
|
|
54
|
-
defaults: {
|
|
55
|
-
...cfg.agents?.defaults,
|
|
56
|
-
models,
|
|
57
|
-
model: {
|
|
58
|
-
...(existingModel && typeof existingModel === "object" && "fallbacks" in existingModel
|
|
59
|
-
? { fallbacks: existingModel.fallbacks }
|
|
60
|
-
: undefined),
|
|
61
|
-
primary: model,
|
|
62
|
-
},
|
|
63
|
-
},
|
|
64
|
-
},
|
|
65
|
-
};
|
|
66
|
-
}
|
|
11
|
+
import { applyDefaultModel, mergeConfigPatch, pickAuthMethod, resolveProviderMatch, } from "./provider-auth-helpers.js";
|
|
67
12
|
export async function applyAuthChoicePluginProvider(params, options) {
|
|
68
13
|
if (params.authChoice !== options.authChoice)
|
|
69
14
|
return null;
|
|
@@ -32,6 +32,7 @@ const PREFERRED_PROVIDER_BY_AUTH_CHOICE = {
|
|
|
32
32
|
"xai-api-key": "xai",
|
|
33
33
|
"qwen-portal": "qwen-portal",
|
|
34
34
|
"qianfan-api-key": "qianfan",
|
|
35
|
+
"nvidia-api-key": "nvidia",
|
|
35
36
|
};
|
|
36
37
|
export function resolvePreferredProviderForAuthChoice(choice) {
|
|
37
38
|
return PREFERRED_PROVIDER_BY_AUTH_CHOICE[choice];
|
|
@@ -12,6 +12,7 @@ import { applyAuthProfileConfig } from "../onboard-auth.js";
|
|
|
12
12
|
import { isRemoteEnvironment } from "../oauth-env.js";
|
|
13
13
|
import { openUrl } from "../onboard-helpers.js";
|
|
14
14
|
import { createVpsAwareOAuthHandlers } from "../oauth-flow.js";
|
|
15
|
+
import { applyDefaultModel, mergeConfigPatch, pickAuthMethod, resolveProviderMatch, } from "../provider-auth-helpers.js";
|
|
15
16
|
import { updateConfig } from "./shared.js";
|
|
16
17
|
import { resolvePluginProviders } from "../../plugins/providers.js";
|
|
17
18
|
import { createClackPrompter } from "../../wizard/clack-prompter.js";
|
|
@@ -167,64 +168,6 @@ export async function modelsAuthAddCommand(_opts, runtime) {
|
|
|
167
168
|
: undefined;
|
|
168
169
|
await modelsAuthPasteTokenCommand({ provider: providerId, profileId, expiresIn }, runtime);
|
|
169
170
|
}
|
|
170
|
-
function resolveProviderMatch(providers, rawProvider) {
|
|
171
|
-
const raw = rawProvider?.trim();
|
|
172
|
-
if (!raw)
|
|
173
|
-
return null;
|
|
174
|
-
const normalized = normalizeProviderId(raw);
|
|
175
|
-
return (providers.find((provider) => normalizeProviderId(provider.id) === normalized) ??
|
|
176
|
-
providers.find((provider) => provider.aliases?.some((alias) => normalizeProviderId(alias) === normalized) ?? false) ??
|
|
177
|
-
null);
|
|
178
|
-
}
|
|
179
|
-
function pickAuthMethod(provider, rawMethod) {
|
|
180
|
-
const raw = rawMethod?.trim();
|
|
181
|
-
if (!raw)
|
|
182
|
-
return null;
|
|
183
|
-
const normalized = raw.toLowerCase();
|
|
184
|
-
return (provider.auth.find((method) => method.id.toLowerCase() === normalized) ??
|
|
185
|
-
provider.auth.find((method) => method.label.toLowerCase() === normalized) ??
|
|
186
|
-
null);
|
|
187
|
-
}
|
|
188
|
-
function isPlainRecord(value) {
|
|
189
|
-
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
190
|
-
}
|
|
191
|
-
function mergeConfigPatch(base, patch) {
|
|
192
|
-
if (!isPlainRecord(base) || !isPlainRecord(patch)) {
|
|
193
|
-
return patch;
|
|
194
|
-
}
|
|
195
|
-
const next = { ...base };
|
|
196
|
-
for (const [key, value] of Object.entries(patch)) {
|
|
197
|
-
const existing = next[key];
|
|
198
|
-
if (isPlainRecord(existing) && isPlainRecord(value)) {
|
|
199
|
-
next[key] = mergeConfigPatch(existing, value);
|
|
200
|
-
}
|
|
201
|
-
else {
|
|
202
|
-
next[key] = value;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
return next;
|
|
206
|
-
}
|
|
207
|
-
function applyDefaultModel(cfg, model) {
|
|
208
|
-
const models = { ...cfg.agents?.defaults?.models };
|
|
209
|
-
models[model] = models[model] ?? {};
|
|
210
|
-
const existingModel = cfg.agents?.defaults?.model;
|
|
211
|
-
return {
|
|
212
|
-
...cfg,
|
|
213
|
-
agents: {
|
|
214
|
-
...cfg.agents,
|
|
215
|
-
defaults: {
|
|
216
|
-
...cfg.agents?.defaults,
|
|
217
|
-
models,
|
|
218
|
-
model: {
|
|
219
|
-
...(existingModel && typeof existingModel === "object" && "fallbacks" in existingModel
|
|
220
|
-
? { fallbacks: existingModel.fallbacks }
|
|
221
|
-
: undefined),
|
|
222
|
-
primary: model,
|
|
223
|
-
},
|
|
224
|
-
},
|
|
225
|
-
},
|
|
226
|
-
};
|
|
227
|
-
}
|
|
228
171
|
function credentialMode(credential) {
|
|
229
172
|
if (credential.type === "api_key")
|
|
230
173
|
return "api_key";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const MODEL_AVAILABILITY_UNAVAILABLE_CODE = "MODEL_AVAILABILITY_UNAVAILABLE";
|
|
2
|
+
export function formatErrorWithStack(err) {
|
|
3
|
+
if (err instanceof Error) {
|
|
4
|
+
return err.stack ?? `${err.name}: ${err.message}`;
|
|
5
|
+
}
|
|
6
|
+
return String(err);
|
|
7
|
+
}
|
|
8
|
+
export function shouldFallbackToAuthHeuristics(err) {
|
|
9
|
+
if (!(err instanceof Error)) {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
const code = err.code;
|
|
13
|
+
return code === MODEL_AVAILABILITY_UNAVAILABLE_CODE;
|
|
14
|
+
}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { ensureAuthProfileStore } from "../../agents/auth-profiles.js";
|
|
2
|
+
import { resolveForwardCompatModel } from "../../agents/model-forward-compat.js";
|
|
2
3
|
import { parseModelRef } from "../../agents/model-selection.js";
|
|
4
|
+
import { resolveModel } from "../../agents/pi-embedded-runner/model.js";
|
|
3
5
|
import { loadConfig } from "../../config/config.js";
|
|
4
6
|
import { resolveConfiguredEntries } from "./list.configured.js";
|
|
7
|
+
import { formatErrorWithStack } from "./list.errors.js";
|
|
5
8
|
import { loadModelRegistry, toModelRow } from "./list.registry.js";
|
|
6
9
|
import { printModelTable } from "./list.table.js";
|
|
7
|
-
import { DEFAULT_PROVIDER, ensureFlagCompatibility, modelKey } from "./shared.js";
|
|
10
|
+
import { DEFAULT_PROVIDER, ensureFlagCompatibility, isLocalBaseUrl, modelKey } from "./shared.js";
|
|
8
11
|
export async function modelsListCommand(opts, runtime) {
|
|
9
12
|
ensureFlagCompatibility(opts);
|
|
10
13
|
const cfg = loadConfig();
|
|
@@ -17,35 +20,30 @@ export async function modelsListCommand(opts, runtime) {
|
|
|
17
20
|
return parsed?.provider ?? raw.toLowerCase();
|
|
18
21
|
})();
|
|
19
22
|
let models = [];
|
|
23
|
+
let modelRegistry;
|
|
20
24
|
let availableKeys;
|
|
25
|
+
let availabilityErrorMessage;
|
|
21
26
|
try {
|
|
22
27
|
const loaded = await loadModelRegistry(cfg);
|
|
28
|
+
modelRegistry = loaded.registry;
|
|
23
29
|
models = loaded.models;
|
|
24
30
|
availableKeys = loaded.availableKeys;
|
|
31
|
+
availabilityErrorMessage = loaded.availabilityErrorMessage;
|
|
25
32
|
}
|
|
26
33
|
catch (err) {
|
|
27
|
-
runtime.error(`Model registry unavailable
|
|
34
|
+
runtime.error(`Model registry unavailable:\n${formatErrorWithStack(err)}`);
|
|
35
|
+
process.exitCode = 1;
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (availabilityErrorMessage !== undefined) {
|
|
39
|
+
runtime.error(`Model availability lookup failed; falling back to auth heuristics for discovered models: ${availabilityErrorMessage}`);
|
|
28
40
|
}
|
|
29
41
|
const modelByKey = new Map(models.map((model) => [modelKey(model.provider, model.id), model]));
|
|
30
42
|
const { entries } = resolveConfiguredEntries(cfg);
|
|
31
43
|
const configuredByKey = new Map(entries.map((entry) => [entry.key, entry]));
|
|
32
44
|
const rows = [];
|
|
33
|
-
const isLocalBaseUrl = (baseUrl) => {
|
|
34
|
-
try {
|
|
35
|
-
const url = new URL(baseUrl);
|
|
36
|
-
const host = url.hostname.toLowerCase();
|
|
37
|
-
return (host === "localhost" ||
|
|
38
|
-
host === "127.0.0.1" ||
|
|
39
|
-
host === "0.0.0.0" ||
|
|
40
|
-
host === "::1" ||
|
|
41
|
-
host.endsWith(".local"));
|
|
42
|
-
}
|
|
43
|
-
catch {
|
|
44
|
-
return false;
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
45
|
if (opts.all) {
|
|
48
|
-
const sorted = [...models].
|
|
46
|
+
const sorted = [...models].toSorted((a, b) => {
|
|
49
47
|
const p = a.provider.localeCompare(b.provider);
|
|
50
48
|
if (p !== 0)
|
|
51
49
|
return p;
|
|
@@ -55,8 +53,9 @@ export async function modelsListCommand(opts, runtime) {
|
|
|
55
53
|
if (providerFilter && model.provider.toLowerCase() !== providerFilter) {
|
|
56
54
|
continue;
|
|
57
55
|
}
|
|
58
|
-
if (opts.local && !isLocalBaseUrl(model.baseUrl))
|
|
56
|
+
if (opts.local && !isLocalBaseUrl(model.baseUrl)) {
|
|
59
57
|
continue;
|
|
58
|
+
}
|
|
60
59
|
const key = modelKey(model.provider, model.id);
|
|
61
60
|
const configured = configuredByKey.get(key);
|
|
62
61
|
rows.push(toModelRow({
|
|
@@ -75,11 +74,23 @@ export async function modelsListCommand(opts, runtime) {
|
|
|
75
74
|
if (providerFilter && entry.ref.provider.toLowerCase() !== providerFilter) {
|
|
76
75
|
continue;
|
|
77
76
|
}
|
|
78
|
-
|
|
79
|
-
if (
|
|
77
|
+
let model = modelByKey.get(entry.key);
|
|
78
|
+
if (!model && modelRegistry) {
|
|
79
|
+
const forwardCompat = resolveForwardCompatModel(entry.ref.provider, entry.ref.model, modelRegistry);
|
|
80
|
+
if (forwardCompat) {
|
|
81
|
+
model = forwardCompat;
|
|
82
|
+
modelByKey.set(entry.key, forwardCompat);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (!model) {
|
|
86
|
+
model = resolveModel(entry.ref.provider, entry.ref.model, undefined, cfg).model;
|
|
87
|
+
}
|
|
88
|
+
if (opts.local && model && !isLocalBaseUrl(model.baseUrl)) {
|
|
80
89
|
continue;
|
|
81
|
-
|
|
90
|
+
}
|
|
91
|
+
if (opts.local && !model) {
|
|
82
92
|
continue;
|
|
93
|
+
}
|
|
83
94
|
rows.push(toModelRow({
|
|
84
95
|
model,
|
|
85
96
|
key: entry.key,
|
|
@@ -1,43 +1,129 @@
|
|
|
1
|
-
import { discoverAuthStorage, discoverModels } from "../../agents/pi-model-discovery.js";
|
|
2
1
|
import { resolvePoolbotAgentDir } from "../../agents/agent-paths.js";
|
|
3
2
|
import { listProfilesForProvider } from "../../agents/auth-profiles.js";
|
|
4
3
|
import { getCustomProviderApiKey, resolveAwsSdkEnvVarName, resolveEnvApiKey, } from "../../agents/model-auth.js";
|
|
4
|
+
import { ANTIGRAVITY_OPUS_46_FORWARD_COMPAT_CANDIDATES, resolveForwardCompatModel, } from "../../agents/model-forward-compat.js";
|
|
5
5
|
import { ensurePoolbotModelsJson } from "../../agents/models-config.js";
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
return (host === "localhost" ||
|
|
12
|
-
host === "127.0.0.1" ||
|
|
13
|
-
host === "0.0.0.0" ||
|
|
14
|
-
host === "::1" ||
|
|
15
|
-
host.endsWith(".local"));
|
|
16
|
-
}
|
|
17
|
-
catch {
|
|
6
|
+
import { discoverAuthStorage, discoverModels } from "../../agents/pi-model-discovery.js";
|
|
7
|
+
import { formatErrorWithStack, MODEL_AVAILABILITY_UNAVAILABLE_CODE, shouldFallbackToAuthHeuristics, } from "./list.errors.js";
|
|
8
|
+
import { isLocalBaseUrl, modelKey } from "./shared.js";
|
|
9
|
+
const hasAuthForProvider = (provider, cfg, authStore) => {
|
|
10
|
+
if (!cfg || !authStore) {
|
|
18
11
|
return false;
|
|
19
12
|
}
|
|
20
|
-
|
|
21
|
-
const hasAuthForProvider = (provider, cfg, authStore) => {
|
|
22
|
-
if (listProfilesForProvider(authStore, provider).length > 0)
|
|
13
|
+
if (listProfilesForProvider(authStore, provider).length > 0) {
|
|
23
14
|
return true;
|
|
24
|
-
|
|
15
|
+
}
|
|
16
|
+
if (provider === "amazon-bedrock" && resolveAwsSdkEnvVarName()) {
|
|
25
17
|
return true;
|
|
26
|
-
|
|
18
|
+
}
|
|
19
|
+
if (resolveEnvApiKey(provider)) {
|
|
27
20
|
return true;
|
|
28
|
-
|
|
21
|
+
}
|
|
22
|
+
if (getCustomProviderApiKey(cfg, provider)) {
|
|
29
23
|
return true;
|
|
24
|
+
}
|
|
30
25
|
return false;
|
|
31
26
|
};
|
|
27
|
+
function createAvailabilityUnavailableError(message) {
|
|
28
|
+
const err = new Error(message);
|
|
29
|
+
err.code = MODEL_AVAILABILITY_UNAVAILABLE_CODE;
|
|
30
|
+
return err;
|
|
31
|
+
}
|
|
32
|
+
function normalizeAvailabilityError(err) {
|
|
33
|
+
if (shouldFallbackToAuthHeuristics(err) && err instanceof Error) {
|
|
34
|
+
return err;
|
|
35
|
+
}
|
|
36
|
+
return createAvailabilityUnavailableError(`Model availability unavailable: getAvailable() failed.\n${formatErrorWithStack(err)}`);
|
|
37
|
+
}
|
|
38
|
+
function validateAvailableModels(availableModels) {
|
|
39
|
+
if (!Array.isArray(availableModels)) {
|
|
40
|
+
throw createAvailabilityUnavailableError("Model availability unavailable: getAvailable() returned a non-array value.");
|
|
41
|
+
}
|
|
42
|
+
for (const model of availableModels) {
|
|
43
|
+
if (!model ||
|
|
44
|
+
typeof model !== "object" ||
|
|
45
|
+
typeof model.provider !== "string" ||
|
|
46
|
+
typeof model.id !== "string") {
|
|
47
|
+
throw createAvailabilityUnavailableError("Model availability unavailable: getAvailable() returned invalid model entries.");
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return availableModels;
|
|
51
|
+
}
|
|
52
|
+
function loadAvailableModels(registry) {
|
|
53
|
+
let availableModels;
|
|
54
|
+
try {
|
|
55
|
+
availableModels = registry.getAvailable();
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
throw normalizeAvailabilityError(err);
|
|
59
|
+
}
|
|
60
|
+
try {
|
|
61
|
+
return validateAvailableModels(availableModels);
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
throw normalizeAvailabilityError(err);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
32
67
|
export async function loadModelRegistry(cfg) {
|
|
33
68
|
await ensurePoolbotModelsJson(cfg);
|
|
34
69
|
const agentDir = resolvePoolbotAgentDir();
|
|
35
70
|
const authStorage = discoverAuthStorage(agentDir);
|
|
36
71
|
const registry = discoverModels(authStorage, agentDir);
|
|
37
|
-
const
|
|
38
|
-
const
|
|
39
|
-
const
|
|
40
|
-
|
|
72
|
+
const appended = appendAntigravityForwardCompatModels(registry.getAll(), registry);
|
|
73
|
+
const models = appended.models;
|
|
74
|
+
const synthesizedForwardCompat = appended.synthesizedForwardCompat;
|
|
75
|
+
let availableKeys;
|
|
76
|
+
let availabilityErrorMessage;
|
|
77
|
+
try {
|
|
78
|
+
const availableModels = loadAvailableModels(registry);
|
|
79
|
+
availableKeys = new Set(availableModels.map((model) => modelKey(model.provider, model.id)));
|
|
80
|
+
for (const synthesized of synthesizedForwardCompat) {
|
|
81
|
+
if (hasAvailableTemplate(availableKeys, synthesized.templatePrefixes)) {
|
|
82
|
+
availableKeys.add(synthesized.key);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
if (!shouldFallbackToAuthHeuristics(err)) {
|
|
88
|
+
throw err;
|
|
89
|
+
}
|
|
90
|
+
// Some providers can report model-level availability as unavailable.
|
|
91
|
+
// Fall back to provider-level auth heuristics when availability is undefined.
|
|
92
|
+
availableKeys = undefined;
|
|
93
|
+
if (!availabilityErrorMessage) {
|
|
94
|
+
availabilityErrorMessage = formatErrorWithStack(err);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return { registry, models, availableKeys, availabilityErrorMessage };
|
|
98
|
+
}
|
|
99
|
+
function appendAntigravityForwardCompatModels(models, modelRegistry) {
|
|
100
|
+
const nextModels = [...models];
|
|
101
|
+
const synthesizedForwardCompat = [];
|
|
102
|
+
for (const candidate of ANTIGRAVITY_OPUS_46_FORWARD_COMPAT_CANDIDATES) {
|
|
103
|
+
const key = modelKey("google-antigravity", candidate.id);
|
|
104
|
+
const hasForwardCompat = nextModels.some((model) => modelKey(model.provider, model.id) === key);
|
|
105
|
+
if (hasForwardCompat) {
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
const fallback = resolveForwardCompatModel("google-antigravity", candidate.id, modelRegistry);
|
|
109
|
+
if (!fallback) {
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
nextModels.push(fallback);
|
|
113
|
+
synthesizedForwardCompat.push({
|
|
114
|
+
key,
|
|
115
|
+
templatePrefixes: candidate.templatePrefixes,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
return { models: nextModels, synthesizedForwardCompat };
|
|
119
|
+
}
|
|
120
|
+
function hasAvailableTemplate(availableKeys, templatePrefixes) {
|
|
121
|
+
for (const key of availableKeys) {
|
|
122
|
+
if (templatePrefixes.some((prefix) => key.startsWith(prefix))) {
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return false;
|
|
41
127
|
}
|
|
42
128
|
export function toModelRow(params) {
|
|
43
129
|
const { model, key, tags, aliases = [], availableKeys, cfg, authStore } = params;
|
|
@@ -55,18 +141,24 @@ export function toModelRow(params) {
|
|
|
55
141
|
}
|
|
56
142
|
const input = model.input.join("+") || "text";
|
|
57
143
|
const local = isLocalBaseUrl(model.baseUrl);
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
144
|
+
// Prefer model-level registry availability when present.
|
|
145
|
+
// Fall back to provider-level auth heuristics only if registry availability isn't available.
|
|
146
|
+
const available = availableKeys !== undefined
|
|
147
|
+
? availableKeys.has(modelKey(model.provider, model.id))
|
|
148
|
+
: cfg && authStore
|
|
149
|
+
? hasAuthForProvider(model.provider, cfg, authStore)
|
|
150
|
+
: false;
|
|
61
151
|
const aliasTags = aliases.length > 0 ? [`alias:${aliases.join(",")}`] : [];
|
|
62
152
|
const mergedTags = new Set(tags);
|
|
63
153
|
if (aliasTags.length > 0) {
|
|
64
154
|
for (const tag of mergedTags) {
|
|
65
|
-
if (tag === "alias" || tag.startsWith("alias:"))
|
|
155
|
+
if (tag === "alias" || tag.startsWith("alias:")) {
|
|
66
156
|
mergedTags.delete(tag);
|
|
157
|
+
}
|
|
67
158
|
}
|
|
68
|
-
for (const tag of aliasTags)
|
|
159
|
+
for (const tag of aliasTags) {
|
|
69
160
|
mergedTags.add(tag);
|
|
161
|
+
}
|
|
70
162
|
}
|
|
71
163
|
return {
|
|
72
164
|
key,
|
|
@@ -82,6 +82,20 @@ export function resolveKnownAgentId(params) {
|
|
|
82
82
|
}
|
|
83
83
|
return agentId;
|
|
84
84
|
}
|
|
85
|
+
export const isLocalBaseUrl = (baseUrl) => {
|
|
86
|
+
try {
|
|
87
|
+
const url = new URL(baseUrl);
|
|
88
|
+
const host = url.hostname.toLowerCase();
|
|
89
|
+
return (host === "localhost" ||
|
|
90
|
+
host === "127.0.0.1" ||
|
|
91
|
+
host === "0.0.0.0" ||
|
|
92
|
+
host === "::1" ||
|
|
93
|
+
host.endsWith(".local"));
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
};
|
|
85
99
|
export { modelKey };
|
|
86
100
|
export { DEFAULT_MODEL, DEFAULT_PROVIDER };
|
|
87
101
|
/**
|
|
@@ -3,8 +3,8 @@ import { buildQianfanProvider, buildXiaomiProvider, QIANFAN_DEFAULT_MODEL_ID, XI
|
|
|
3
3
|
import { buildSyntheticModelDefinition, SYNTHETIC_BASE_URL, SYNTHETIC_DEFAULT_MODEL_REF, SYNTHETIC_MODEL_CATALOG, } from "../agents/synthetic-models.js";
|
|
4
4
|
import { buildTogetherModelDefinition, TOGETHER_BASE_URL, TOGETHER_MODEL_CATALOG, } from "../agents/together-models.js";
|
|
5
5
|
import { buildVeniceModelDefinition, VENICE_BASE_URL, VENICE_DEFAULT_MODEL_REF, VENICE_MODEL_CATALOG, } from "../agents/venice-models.js";
|
|
6
|
-
import { CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF, OPENROUTER_DEFAULT_MODEL_REF, TOGETHER_DEFAULT_MODEL_REF, VERCEL_AI_GATEWAY_DEFAULT_MODEL_REF, XIAOMI_DEFAULT_MODEL_REF, ZAI_DEFAULT_MODEL_REF, XAI_DEFAULT_MODEL_REF, } from "./onboard-auth.credentials.js";
|
|
7
|
-
import { buildMoonshotModelDefinition, buildXaiModelDefinition, QIANFAN_BASE_URL, QIANFAN_DEFAULT_MODEL_REF, KIMI_CODING_MODEL_REF, MOONSHOT_BASE_URL, MOONSHOT_CN_BASE_URL, MOONSHOT_DEFAULT_MODEL_ID, MOONSHOT_DEFAULT_MODEL_REF, XAI_BASE_URL, XAI_DEFAULT_MODEL_ID, } from "./onboard-auth.models.js";
|
|
6
|
+
import { CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF, OPENROUTER_DEFAULT_MODEL_REF, TOGETHER_DEFAULT_MODEL_REF, VERCEL_AI_GATEWAY_DEFAULT_MODEL_REF, XIAOMI_DEFAULT_MODEL_REF, ZAI_DEFAULT_MODEL_REF, XAI_DEFAULT_MODEL_REF, NVIDIA_DEFAULT_MODEL_REF, } from "./onboard-auth.credentials.js";
|
|
7
|
+
import { buildMoonshotModelDefinition, buildNvidiaModelDefinition, buildXaiModelDefinition, QIANFAN_BASE_URL, QIANFAN_DEFAULT_MODEL_REF, KIMI_CODING_MODEL_REF, MOONSHOT_BASE_URL, MOONSHOT_CN_BASE_URL, MOONSHOT_DEFAULT_MODEL_ID, MOONSHOT_DEFAULT_MODEL_REF, NVIDIA_BASE_URL, NVIDIA_DEFAULT_MODEL_ID, XAI_BASE_URL, XAI_DEFAULT_MODEL_ID, } from "./onboard-auth.models.js";
|
|
8
8
|
export function applyZaiConfig(cfg) {
|
|
9
9
|
const models = { ...cfg.agents?.defaults?.models };
|
|
10
10
|
models[ZAI_DEFAULT_MODEL_REF] = {
|
|
@@ -722,3 +722,61 @@ export function applyQianfanConfig(cfg) {
|
|
|
722
722
|
},
|
|
723
723
|
};
|
|
724
724
|
}
|
|
725
|
+
export function applyNvidiaProviderConfig(cfg) {
|
|
726
|
+
const models = { ...cfg.agents?.defaults?.models };
|
|
727
|
+
models[NVIDIA_DEFAULT_MODEL_REF] = {
|
|
728
|
+
...models[NVIDIA_DEFAULT_MODEL_REF],
|
|
729
|
+
alias: models[NVIDIA_DEFAULT_MODEL_REF]?.alias ?? "Nemotron",
|
|
730
|
+
};
|
|
731
|
+
const providers = { ...cfg.models?.providers };
|
|
732
|
+
const existingProvider = providers.nvidia;
|
|
733
|
+
const existingModels = Array.isArray(existingProvider?.models) ? existingProvider.models : [];
|
|
734
|
+
const defaultModel = buildNvidiaModelDefinition();
|
|
735
|
+
const hasDefaultModel = existingModels.some((model) => model.id === NVIDIA_DEFAULT_MODEL_ID);
|
|
736
|
+
const mergedModels = hasDefaultModel ? existingModels : [...existingModels, defaultModel];
|
|
737
|
+
const { apiKey: existingApiKey, ...existingProviderRest } = (existingProvider ?? {});
|
|
738
|
+
const resolvedApiKey = typeof existingApiKey === "string" ? existingApiKey : undefined;
|
|
739
|
+
const normalizedApiKey = resolvedApiKey?.trim();
|
|
740
|
+
providers.nvidia = {
|
|
741
|
+
...existingProviderRest,
|
|
742
|
+
baseUrl: NVIDIA_BASE_URL,
|
|
743
|
+
api: "openai-completions",
|
|
744
|
+
...(normalizedApiKey ? { apiKey: normalizedApiKey } : {}),
|
|
745
|
+
models: mergedModels.length > 0 ? mergedModels : [defaultModel],
|
|
746
|
+
};
|
|
747
|
+
return {
|
|
748
|
+
...cfg,
|
|
749
|
+
agents: {
|
|
750
|
+
...cfg.agents,
|
|
751
|
+
defaults: {
|
|
752
|
+
...cfg.agents?.defaults,
|
|
753
|
+
models,
|
|
754
|
+
},
|
|
755
|
+
},
|
|
756
|
+
models: {
|
|
757
|
+
mode: cfg.models?.mode ?? "merge",
|
|
758
|
+
providers,
|
|
759
|
+
},
|
|
760
|
+
};
|
|
761
|
+
}
|
|
762
|
+
export function applyNvidiaConfig(cfg) {
|
|
763
|
+
const next = applyNvidiaProviderConfig(cfg);
|
|
764
|
+
const existingModel = next.agents?.defaults?.model;
|
|
765
|
+
return {
|
|
766
|
+
...next,
|
|
767
|
+
agents: {
|
|
768
|
+
...next.agents,
|
|
769
|
+
defaults: {
|
|
770
|
+
...next.agents?.defaults,
|
|
771
|
+
model: {
|
|
772
|
+
...(existingModel && "fallbacks" in existingModel
|
|
773
|
+
? {
|
|
774
|
+
fallbacks: existingModel.fallbacks,
|
|
775
|
+
}
|
|
776
|
+
: undefined),
|
|
777
|
+
primary: NVIDIA_DEFAULT_MODEL_REF,
|
|
778
|
+
},
|
|
779
|
+
},
|
|
780
|
+
},
|
|
781
|
+
};
|
|
782
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { resolvePoolbotAgentDir } from "../agents/agent-paths.js";
|
|
2
2
|
import { upsertAuthProfile } from "../agents/auth-profiles.js";
|
|
3
3
|
export { CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF } from "../agents/cloudflare-ai-gateway.js";
|
|
4
|
-
export { XAI_DEFAULT_MODEL_REF } from "./onboard-auth.models.js";
|
|
4
|
+
export { XAI_DEFAULT_MODEL_REF, NVIDIA_DEFAULT_MODEL_REF } from "./onboard-auth.models.js";
|
|
5
5
|
const resolveAuthAgentDir = (agentDir) => agentDir ?? resolvePoolbotAgentDir();
|
|
6
6
|
export async function writeOAuthCredentials(provider, creds, agentDir) {
|
|
7
7
|
const email = typeof creds.email === "string" && creds.email.trim() ? creds.email.trim() : "default";
|
|
@@ -207,3 +207,14 @@ export function setXaiApiKey(key, agentDir) {
|
|
|
207
207
|
agentDir: resolveAuthAgentDir(agentDir),
|
|
208
208
|
});
|
|
209
209
|
}
|
|
210
|
+
export function setNvidiaApiKey(key, agentDir) {
|
|
211
|
+
upsertAuthProfile({
|
|
212
|
+
profileId: "nvidia:default",
|
|
213
|
+
credential: {
|
|
214
|
+
type: "api_key",
|
|
215
|
+
provider: "nvidia",
|
|
216
|
+
key,
|
|
217
|
+
},
|
|
218
|
+
agentDir: resolveAuthAgentDir(agentDir),
|
|
219
|
+
});
|
|
220
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { SYNTHETIC_DEFAULT_MODEL_ID, SYNTHETIC_DEFAULT_MODEL_REF, } from "../agents/synthetic-models.js";
|
|
2
2
|
export { VENICE_DEFAULT_MODEL_ID, VENICE_DEFAULT_MODEL_REF } from "../agents/venice-models.js";
|
|
3
|
-
export { applyAuthProfileConfig, applyCloudflareAiGatewayConfig, applyCloudflareAiGatewayProviderConfig, applyQianfanConfig, applyQianfanProviderConfig, applyKimiCodeConfig, applyKimiCodeProviderConfig, applyMoonshotConfig, applyMoonshotConfigCn, applyMoonshotProviderConfig, applyMoonshotProviderConfigCn, applyOpenrouterConfig, applyOpenrouterProviderConfig, applySyntheticConfig, applySyntheticProviderConfig, applyTogetherConfig, applyTogetherProviderConfig, applyVeniceConfig, applyVeniceProviderConfig, applyVercelAiGatewayConfig, applyVercelAiGatewayProviderConfig, applyXaiConfig, applyXaiProviderConfig, applyXiaomiConfig, applyXiaomiProviderConfig, applyZaiConfig, } from "./onboard-auth.config-core.js";
|
|
3
|
+
export { applyAuthProfileConfig, applyCloudflareAiGatewayConfig, applyCloudflareAiGatewayProviderConfig, applyQianfanConfig, applyQianfanProviderConfig, applyKimiCodeConfig, applyKimiCodeProviderConfig, applyMoonshotConfig, applyMoonshotConfigCn, applyMoonshotProviderConfig, applyMoonshotProviderConfigCn, applyOpenrouterConfig, applyOpenrouterProviderConfig, applySyntheticConfig, applySyntheticProviderConfig, applyTogetherConfig, applyTogetherProviderConfig, applyVeniceConfig, applyVeniceProviderConfig, applyVercelAiGatewayConfig, applyVercelAiGatewayProviderConfig, applyNvidiaConfig, applyNvidiaProviderConfig, applyXaiConfig, applyXaiProviderConfig, applyXiaomiConfig, applyXiaomiProviderConfig, applyZaiConfig, } from "./onboard-auth.config-core.js";
|
|
4
4
|
export { applyMinimaxApiConfig, applyMinimaxApiProviderConfig, applyMinimaxConfig, applyMinimaxHostedConfig, applyMinimaxHostedProviderConfig, applyMinimaxProviderConfig, } from "./onboard-auth.config-minimax.js";
|
|
5
5
|
export { applyOpencodeZenConfig, applyOpencodeZenProviderConfig, } from "./onboard-auth.config-opencode.js";
|
|
6
|
-
export { CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF, OPENROUTER_DEFAULT_MODEL_REF, setAnthropicApiKey, setCloudflareAiGatewayConfig, setQianfanApiKey, setGeminiApiKey, setKimiCodingApiKey, setMinimaxApiKey, setMoonshotApiKey, setOpencodeZenApiKey, setOpenrouterApiKey, setSyntheticApiKey, setTogetherApiKey, setVeniceApiKey, setVercelAiGatewayApiKey, setXiaomiApiKey, setZaiApiKey, setXaiApiKey, writeOAuthCredentials, VERCEL_AI_GATEWAY_DEFAULT_MODEL_REF, XIAOMI_DEFAULT_MODEL_REF, ZAI_DEFAULT_MODEL_REF, TOGETHER_DEFAULT_MODEL_REF, XAI_DEFAULT_MODEL_REF, } from "./onboard-auth.credentials.js";
|
|
7
|
-
export { buildMinimaxApiModelDefinition, buildMinimaxModelDefinition, buildMoonshotModelDefinition, DEFAULT_MINIMAX_BASE_URL, MOONSHOT_CN_BASE_URL, QIANFAN_BASE_URL, QIANFAN_DEFAULT_MODEL_ID, QIANFAN_DEFAULT_MODEL_REF, KIMI_CODING_MODEL_ID, KIMI_CODING_MODEL_REF, MINIMAX_API_BASE_URL, MINIMAX_HOSTED_MODEL_ID, MINIMAX_HOSTED_MODEL_REF, MOONSHOT_BASE_URL, MOONSHOT_DEFAULT_MODEL_ID, MOONSHOT_DEFAULT_MODEL_REF, } from "./onboard-auth.models.js";
|
|
6
|
+
export { CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF, OPENROUTER_DEFAULT_MODEL_REF, setAnthropicApiKey, setCloudflareAiGatewayConfig, setQianfanApiKey, setGeminiApiKey, setKimiCodingApiKey, setMinimaxApiKey, setMoonshotApiKey, setOpencodeZenApiKey, setOpenrouterApiKey, setSyntheticApiKey, setTogetherApiKey, setVeniceApiKey, setVercelAiGatewayApiKey, setXiaomiApiKey, setZaiApiKey, setNvidiaApiKey, setXaiApiKey, writeOAuthCredentials, VERCEL_AI_GATEWAY_DEFAULT_MODEL_REF, NVIDIA_DEFAULT_MODEL_REF, XIAOMI_DEFAULT_MODEL_REF, ZAI_DEFAULT_MODEL_REF, TOGETHER_DEFAULT_MODEL_REF, XAI_DEFAULT_MODEL_REF, } from "./onboard-auth.credentials.js";
|
|
7
|
+
export { buildMinimaxApiModelDefinition, buildMinimaxModelDefinition, buildMoonshotModelDefinition, DEFAULT_MINIMAX_BASE_URL, MOONSHOT_CN_BASE_URL, QIANFAN_BASE_URL, QIANFAN_DEFAULT_MODEL_ID, QIANFAN_DEFAULT_MODEL_REF, KIMI_CODING_MODEL_ID, KIMI_CODING_MODEL_REF, MINIMAX_API_BASE_URL, MINIMAX_HOSTED_MODEL_ID, MINIMAX_HOSTED_MODEL_REF, MOONSHOT_BASE_URL, MOONSHOT_DEFAULT_MODEL_ID, MOONSHOT_DEFAULT_MODEL_REF, buildNvidiaModelDefinition, NVIDIA_BASE_URL, NVIDIA_DEFAULT_MODEL_ID, } from "./onboard-auth.models.js";
|
|
@@ -100,3 +100,25 @@ export function buildXaiModelDefinition() {
|
|
|
100
100
|
maxTokens: XAI_DEFAULT_MAX_TOKENS,
|
|
101
101
|
};
|
|
102
102
|
}
|
|
103
|
+
export const NVIDIA_BASE_URL = "https://integrate.api.nvidia.com/v1";
|
|
104
|
+
export const NVIDIA_DEFAULT_MODEL_ID = "llama-3.1-nemotron-ultra-253b-v1";
|
|
105
|
+
export const NVIDIA_DEFAULT_MODEL_REF = `nvidia/${NVIDIA_DEFAULT_MODEL_ID}`;
|
|
106
|
+
export const NVIDIA_DEFAULT_CONTEXT_WINDOW = 131072;
|
|
107
|
+
export const NVIDIA_DEFAULT_MAX_TOKENS = 8192;
|
|
108
|
+
export const NVIDIA_DEFAULT_COST = {
|
|
109
|
+
input: 0,
|
|
110
|
+
output: 0,
|
|
111
|
+
cacheRead: 0,
|
|
112
|
+
cacheWrite: 0,
|
|
113
|
+
};
|
|
114
|
+
export function buildNvidiaModelDefinition() {
|
|
115
|
+
return {
|
|
116
|
+
id: NVIDIA_DEFAULT_MODEL_ID,
|
|
117
|
+
name: "Nemotron Ultra 253B",
|
|
118
|
+
reasoning: false,
|
|
119
|
+
input: ["text"],
|
|
120
|
+
cost: NVIDIA_DEFAULT_COST,
|
|
121
|
+
contextWindow: NVIDIA_DEFAULT_CONTEXT_WINDOW,
|
|
122
|
+
maxTokens: NVIDIA_DEFAULT_MAX_TOKENS,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
@@ -16,6 +16,7 @@ const AUTH_CHOICE_FLAG_MAP = [
|
|
|
16
16
|
{ flag: "zaiApiKey", authChoice: "zai-api-key", label: "--zai-api-key" },
|
|
17
17
|
{ flag: "xiaomiApiKey", authChoice: "xiaomi-api-key", label: "--xiaomi-api-key" },
|
|
18
18
|
{ flag: "xaiApiKey", authChoice: "xai-api-key", label: "--xai-api-key" },
|
|
19
|
+
{ flag: "nvidiaApiKey", authChoice: "nvidia-api-key", label: "--nvidia-api-key" },
|
|
19
20
|
{ flag: "minimaxApiKey", authChoice: "minimax-api", label: "--minimax-api-key" },
|
|
20
21
|
{ flag: "opencodeZenApiKey", authChoice: "opencode-zen", label: "--opencode-zen-api-key" },
|
|
21
22
|
];
|
|
@@ -6,7 +6,7 @@ import { normalizeSecretInput } from "../../../utils/normalize-secret-input.js";
|
|
|
6
6
|
import { buildTokenProfileId, validateAnthropicSetupToken } from "../../auth-token.js";
|
|
7
7
|
import { applyGoogleGeminiModelDefault } from "../../google-gemini-model-default.js";
|
|
8
8
|
import { applyOpenAIConfig } from "../../openai-model-default.js";
|
|
9
|
-
import { applyAuthProfileConfig, applyCloudflareAiGatewayConfig, applyKimiCodeConfig, applyMinimaxApiConfig, applyMinimaxConfig, applyMoonshotConfig, applyMoonshotConfigCn, applyOpencodeZenConfig, applyOpenrouterConfig, applyQianfanConfig, applySyntheticConfig, applyTogetherConfig, applyVeniceConfig, applyVercelAiGatewayConfig, applyXaiConfig, applyXiaomiConfig, applyZaiConfig, setAnthropicApiKey, setCloudflareAiGatewayConfig, setGeminiApiKey, setKimiCodingApiKey, setMinimaxApiKey, setMoonshotApiKey, setOpencodeZenApiKey, setOpenrouterApiKey, setQianfanApiKey, setSyntheticApiKey, setTogetherApiKey, setVeniceApiKey, setVercelAiGatewayApiKey, setXaiApiKey, setXiaomiApiKey, setZaiApiKey, } from "../../onboard-auth.js";
|
|
9
|
+
import { applyAuthProfileConfig, applyCloudflareAiGatewayConfig, applyKimiCodeConfig, applyMinimaxApiConfig, applyMinimaxConfig, applyMoonshotConfig, applyMoonshotConfigCn, applyOpencodeZenConfig, applyOpenrouterConfig, applyQianfanConfig, applySyntheticConfig, applyTogetherConfig, applyVeniceConfig, applyVercelAiGatewayConfig, applyNvidiaConfig, applyXaiConfig, applyXiaomiConfig, applyZaiConfig, setAnthropicApiKey, setCloudflareAiGatewayConfig, setGeminiApiKey, setKimiCodingApiKey, setMinimaxApiKey, setMoonshotApiKey, setNvidiaApiKey, setOpencodeZenApiKey, setOpenrouterApiKey, setQianfanApiKey, setSyntheticApiKey, setTogetherApiKey, setVeniceApiKey, setVercelAiGatewayApiKey, setXaiApiKey, setXiaomiApiKey, setZaiApiKey, } from "../../onboard-auth.js";
|
|
10
10
|
import { resolveNonInteractiveApiKey } from "../api-keys.js";
|
|
11
11
|
import { shortenHomePath } from "../../../utils.js";
|
|
12
12
|
export async function applyNonInteractiveAuthChoice(params) {
|
|
@@ -358,6 +358,26 @@ export async function applyNonInteractiveAuthChoice(params) {
|
|
|
358
358
|
});
|
|
359
359
|
return applyQianfanConfig(nextConfig);
|
|
360
360
|
}
|
|
361
|
+
if (authChoice === "nvidia-api-key") {
|
|
362
|
+
const resolved = await resolveNonInteractiveApiKey({
|
|
363
|
+
provider: "nvidia",
|
|
364
|
+
cfg: baseConfig,
|
|
365
|
+
flagValue: opts.nvidiaApiKey,
|
|
366
|
+
flagName: "--nvidia-api-key",
|
|
367
|
+
envVar: "NVIDIA_API_KEY",
|
|
368
|
+
runtime,
|
|
369
|
+
});
|
|
370
|
+
if (!resolved)
|
|
371
|
+
return null;
|
|
372
|
+
if (resolved.source !== "profile")
|
|
373
|
+
setNvidiaApiKey(resolved.key);
|
|
374
|
+
nextConfig = applyAuthProfileConfig(nextConfig, {
|
|
375
|
+
profileId: "nvidia:default",
|
|
376
|
+
provider: "nvidia",
|
|
377
|
+
mode: "api_key",
|
|
378
|
+
});
|
|
379
|
+
return applyNvidiaConfig(nextConfig);
|
|
380
|
+
}
|
|
361
381
|
if (authChoice === "cloudflare-ai-gateway-api-key") {
|
|
362
382
|
const accountId = opts.cloudflareAiGatewayAccountId?.trim() ?? "";
|
|
363
383
|
const gatewayId = opts.cloudflareAiGatewayGatewayId?.trim() ?? "";
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { normalizeProviderId } from "../agents/model-selection.js";
|
|
2
|
+
export function resolveProviderMatch(providers, rawProvider) {
|
|
3
|
+
const raw = rawProvider?.trim();
|
|
4
|
+
if (!raw) {
|
|
5
|
+
return null;
|
|
6
|
+
}
|
|
7
|
+
const normalized = normalizeProviderId(raw);
|
|
8
|
+
return (providers.find((provider) => normalizeProviderId(provider.id) === normalized) ??
|
|
9
|
+
providers.find((provider) => provider.aliases?.some((alias) => normalizeProviderId(alias) === normalized) ?? false) ??
|
|
10
|
+
null);
|
|
11
|
+
}
|
|
12
|
+
export function pickAuthMethod(provider, rawMethod) {
|
|
13
|
+
const raw = rawMethod?.trim();
|
|
14
|
+
if (!raw) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
const normalized = raw.toLowerCase();
|
|
18
|
+
return (provider.auth.find((method) => method.id.toLowerCase() === normalized) ??
|
|
19
|
+
provider.auth.find((method) => method.label.toLowerCase() === normalized) ??
|
|
20
|
+
null);
|
|
21
|
+
}
|
|
22
|
+
function isPlainRecord(value) {
|
|
23
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
24
|
+
}
|
|
25
|
+
export function mergeConfigPatch(base, patch) {
|
|
26
|
+
if (!isPlainRecord(base) || !isPlainRecord(patch)) {
|
|
27
|
+
return patch;
|
|
28
|
+
}
|
|
29
|
+
const next = { ...base };
|
|
30
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
31
|
+
const existing = next[key];
|
|
32
|
+
if (isPlainRecord(existing) && isPlainRecord(value)) {
|
|
33
|
+
next[key] = mergeConfigPatch(existing, value);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
next[key] = value;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return next;
|
|
40
|
+
}
|
|
41
|
+
export function applyDefaultModel(cfg, model) {
|
|
42
|
+
const models = { ...cfg.agents?.defaults?.models };
|
|
43
|
+
models[model] = models[model] ?? {};
|
|
44
|
+
const existingModel = cfg.agents?.defaults?.model;
|
|
45
|
+
return {
|
|
46
|
+
...cfg,
|
|
47
|
+
agents: {
|
|
48
|
+
...cfg.agents,
|
|
49
|
+
defaults: {
|
|
50
|
+
...cfg.agents?.defaults,
|
|
51
|
+
models,
|
|
52
|
+
model: {
|
|
53
|
+
...(existingModel && typeof existingModel === "object" && "fallbacks" in existingModel
|
|
54
|
+
? { fallbacks: existingModel.fallbacks }
|
|
55
|
+
: undefined),
|
|
56
|
+
primary: model,
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
}
|
package/dist/terminal/theme.js
CHANGED
|
@@ -16,7 +16,7 @@ export const theme = {
|
|
|
16
16
|
muted: hex(POOLBOT_PALETTE.muted),
|
|
17
17
|
heading: baseChalk.bold.hex(POOLBOT_PALETTE.accent),
|
|
18
18
|
command: hex(POOLBOT_PALETTE.accentBright),
|
|
19
|
-
option: hex(POOLBOT_PALETTE.
|
|
19
|
+
option: hex(POOLBOT_PALETTE.info),
|
|
20
20
|
};
|
|
21
21
|
export const isRich = () => Boolean(baseChalk.level > 0);
|
|
22
22
|
export const colorize = (rich, color, value) => rich ? color(value) : value;
|