@poolzin/pool-bot 2026.2.3 → 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/agent-paths.js +3 -1
- package/dist/agents/anthropic-payload-log.js +2 -1
- package/dist/agents/bash-tools.exec.js +2 -1
- package/dist/agents/cache-trace.js +8 -4
- package/dist/agents/live-auth-keys.js +2 -1
- 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/agents/pi-embedded-runner/session-manager-cache.js +2 -1
- package/dist/agents/pi-embedded-subscribe.raw-stream.js +2 -1
- package/dist/agents/skills/bundled-dir.js +2 -1
- package/dist/browser/constants.js +1 -1
- package/dist/browser/profiles.js +1 -1
- package/dist/build-info.json +3 -3
- package/dist/channels/plugins/catalog.js +6 -1
- package/dist/cli/daemon-cli/install.js +4 -1
- package/dist/cli/daemon-cli/status.gather.js +4 -2
- package/dist/cli/memory-cli.js +9 -3
- package/dist/cli/profile.js +6 -2
- 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/configure.wizard.js +29 -10
- package/dist/commands/dashboard.js +4 -1
- package/dist/commands/doctor-gateway-daemon-flow.js +8 -2
- package/dist/commands/doctor-gateway-services.js +6 -2
- package/dist/commands/doctor-platform-notes.js +3 -1
- package/dist/commands/gateway-status/helpers.js +3 -1
- 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/commands/status-all.js +4 -2
- package/dist/commands/status.gateway-probe.js +4 -2
- package/dist/commands/status.scan.js +2 -1
- package/dist/config/paths.js +18 -6
- package/dist/daemon/launchd.js +4 -1
- package/dist/daemon/schtasks.js +4 -1
- package/dist/daemon/systemd.js +4 -1
- package/dist/entry.js +4 -2
- package/dist/gateway/auth.js +4 -1
- package/dist/gateway/call.js +4 -2
- package/dist/gateway/server/ws-connection/message-handler.js +4 -1
- package/dist/gateway/server-browser.js +4 -2
- package/dist/gateway/server-constants.js +5 -2
- package/dist/gateway/server-cron.js +3 -1
- package/dist/gateway/server-discovery-runtime.js +5 -2
- package/dist/infra/restart.js +2 -1
- package/dist/infra/shell-env.js +3 -2
- package/dist/infra/state-migrations.js +3 -1
- package/dist/infra/system-presence.js +4 -1
- package/dist/infra/update-runner.js +4 -1
- package/dist/macos/gateway-daemon.js +6 -3
- package/dist/macos/relay-smoke.js +5 -1
- package/dist/macos/relay.js +2 -1
- package/dist/media/image-ops.js +3 -1
- package/dist/node-host/runner.js +2 -1
- package/dist/plugins/bundled-dir.js +2 -1
- package/dist/plugins/manifest-registry.js +2 -1
- package/dist/security/audit.js +2 -1
- package/dist/telegram/bot-message-dispatch.js +1 -1
- package/dist/telegram/network-config.js +4 -2
- package/dist/terminal/palette.js +8 -6
- package/dist/terminal/theme.js +12 -12
- package/dist/tui/gateway-chat.js +2 -1
- package/dist/tui/theme/theme.js +5 -5
- package/dist/tui/tui.js +12 -6
- package/dist/version.js +2 -1
- package/dist/wizard/onboarding.js +6 -2
- package/package.json +1 -1
|
@@ -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];
|
|
@@ -132,8 +132,12 @@ export async function runConfigureWizard(opts, runtime = defaultRuntime) {
|
|
|
132
132
|
const localUrl = "ws://127.0.0.1:18789";
|
|
133
133
|
const localProbe = await probeGatewayReachable({
|
|
134
134
|
url: localUrl,
|
|
135
|
-
token: baseConfig.gateway?.auth?.token ??
|
|
136
|
-
|
|
135
|
+
token: baseConfig.gateway?.auth?.token ??
|
|
136
|
+
process.env.POOLBOT_GATEWAY_TOKEN ??
|
|
137
|
+
process.env.CLAWDBOT_GATEWAY_TOKEN,
|
|
138
|
+
password: baseConfig.gateway?.auth?.password ??
|
|
139
|
+
process.env.POOLBOT_GATEWAY_PASSWORD ??
|
|
140
|
+
process.env.CLAWDBOT_GATEWAY_PASSWORD,
|
|
137
141
|
});
|
|
138
142
|
const remoteUrl = baseConfig.gateway?.remote?.url?.trim() ?? "";
|
|
139
143
|
const remoteProbe = remoteUrl
|
|
@@ -192,7 +196,8 @@ export async function runConfigureWizard(opts, runtime = defaultRuntime) {
|
|
|
192
196
|
let gatewayPort = resolveGatewayPort(baseConfig);
|
|
193
197
|
let gatewayToken = nextConfig.gateway?.auth?.token ??
|
|
194
198
|
baseConfig.gateway?.auth?.token ??
|
|
195
|
-
process.env.POOLBOT_GATEWAY_TOKEN ??
|
|
199
|
+
process.env.POOLBOT_GATEWAY_TOKEN ??
|
|
200
|
+
process.env.CLAWDBOT_GATEWAY_TOKEN;
|
|
196
201
|
const persistConfig = async () => {
|
|
197
202
|
nextConfig = applyWizardMetadata(nextConfig, {
|
|
198
203
|
command: opts.command,
|
|
@@ -277,8 +282,12 @@ export async function runConfigureWizard(opts, runtime = defaultRuntime) {
|
|
|
277
282
|
});
|
|
278
283
|
const remoteUrl = nextConfig.gateway?.remote?.url?.trim();
|
|
279
284
|
const wsUrl = nextConfig.gateway?.mode === "remote" && remoteUrl ? remoteUrl : localLinks.wsUrl;
|
|
280
|
-
const token = nextConfig.gateway?.auth?.token ??
|
|
281
|
-
|
|
285
|
+
const token = nextConfig.gateway?.auth?.token ??
|
|
286
|
+
process.env.POOLBOT_GATEWAY_TOKEN ??
|
|
287
|
+
process.env.CLAWDBOT_GATEWAY_TOKEN;
|
|
288
|
+
const password = nextConfig.gateway?.auth?.password ??
|
|
289
|
+
process.env.POOLBOT_GATEWAY_PASSWORD ??
|
|
290
|
+
process.env.CLAWDBOT_GATEWAY_PASSWORD;
|
|
282
291
|
await waitForGatewayReachable({
|
|
283
292
|
url: wsUrl,
|
|
284
293
|
token,
|
|
@@ -386,8 +395,12 @@ export async function runConfigureWizard(opts, runtime = defaultRuntime) {
|
|
|
386
395
|
});
|
|
387
396
|
const remoteUrl = nextConfig.gateway?.remote?.url?.trim();
|
|
388
397
|
const wsUrl = nextConfig.gateway?.mode === "remote" && remoteUrl ? remoteUrl : localLinks.wsUrl;
|
|
389
|
-
const token = nextConfig.gateway?.auth?.token ??
|
|
390
|
-
|
|
398
|
+
const token = nextConfig.gateway?.auth?.token ??
|
|
399
|
+
process.env.POOLBOT_GATEWAY_TOKEN ??
|
|
400
|
+
process.env.CLAWDBOT_GATEWAY_TOKEN;
|
|
401
|
+
const password = nextConfig.gateway?.auth?.password ??
|
|
402
|
+
process.env.POOLBOT_GATEWAY_PASSWORD ??
|
|
403
|
+
process.env.CLAWDBOT_GATEWAY_PASSWORD;
|
|
391
404
|
await waitForGatewayReachable({
|
|
392
405
|
url: wsUrl,
|
|
393
406
|
token,
|
|
@@ -429,9 +442,15 @@ export async function runConfigureWizard(opts, runtime = defaultRuntime) {
|
|
|
429
442
|
basePath: nextConfig.gateway?.controlUi?.basePath,
|
|
430
443
|
});
|
|
431
444
|
// Try both new and old passwords since gateway may still have old config.
|
|
432
|
-
const newPassword = nextConfig.gateway?.auth?.password ??
|
|
433
|
-
|
|
434
|
-
|
|
445
|
+
const newPassword = nextConfig.gateway?.auth?.password ??
|
|
446
|
+
process.env.POOLBOT_GATEWAY_PASSWORD ??
|
|
447
|
+
process.env.CLAWDBOT_GATEWAY_PASSWORD;
|
|
448
|
+
const oldPassword = baseConfig.gateway?.auth?.password ??
|
|
449
|
+
process.env.POOLBOT_GATEWAY_PASSWORD ??
|
|
450
|
+
process.env.CLAWDBOT_GATEWAY_PASSWORD;
|
|
451
|
+
const token = nextConfig.gateway?.auth?.token ??
|
|
452
|
+
process.env.POOLBOT_GATEWAY_TOKEN ??
|
|
453
|
+
process.env.CLAWDBOT_GATEWAY_TOKEN;
|
|
435
454
|
let gatewayProbe = await probeGatewayReachable({
|
|
436
455
|
url: links.wsUrl,
|
|
437
456
|
token,
|
|
@@ -9,7 +9,10 @@ export async function dashboardCommand(runtime = defaultRuntime, options = {}) {
|
|
|
9
9
|
const bind = cfg.gateway?.bind ?? "loopback";
|
|
10
10
|
const basePath = cfg.gateway?.controlUi?.basePath;
|
|
11
11
|
const customBindHost = cfg.gateway?.customBindHost;
|
|
12
|
-
const token = cfg.gateway?.auth?.token ??
|
|
12
|
+
const token = cfg.gateway?.auth?.token ??
|
|
13
|
+
process.env.POOLBOT_GATEWAY_TOKEN ??
|
|
14
|
+
process.env.CLAWDBOT_GATEWAY_TOKEN ??
|
|
15
|
+
"";
|
|
13
16
|
const links = resolveControlUiLinks({
|
|
14
17
|
port,
|
|
15
18
|
bind,
|
|
@@ -72,7 +72,11 @@ export async function maybeRepairGatewayDaemon(params) {
|
|
|
72
72
|
prompter: params.prompter,
|
|
73
73
|
});
|
|
74
74
|
await maybeRepairLaunchAgentBootstrap({
|
|
75
|
-
env: {
|
|
75
|
+
env: {
|
|
76
|
+
...process.env,
|
|
77
|
+
POOLBOT_LAUNCHD_LABEL: resolveNodeLaunchAgentLabel(),
|
|
78
|
+
CLAWDBOT_LAUNCHD_LABEL: resolveNodeLaunchAgentLabel(),
|
|
79
|
+
},
|
|
76
80
|
title: "Node",
|
|
77
81
|
runtime: params.runtime,
|
|
78
82
|
prompter: params.prompter,
|
|
@@ -121,7 +125,9 @@ export async function maybeRepairGatewayDaemon(params) {
|
|
|
121
125
|
const { programArguments, workingDirectory, environment } = await buildGatewayInstallPlan({
|
|
122
126
|
env: process.env,
|
|
123
127
|
port,
|
|
124
|
-
token: params.cfg.gateway?.auth?.token ??
|
|
128
|
+
token: params.cfg.gateway?.auth?.token ??
|
|
129
|
+
process.env.POOLBOT_GATEWAY_TOKEN ??
|
|
130
|
+
process.env.CLAWDBOT_GATEWAY_TOKEN,
|
|
125
131
|
runtime: daemonRuntime,
|
|
126
132
|
warn: (message, title) => note(message, title),
|
|
127
133
|
config: params.cfg,
|
|
@@ -80,7 +80,9 @@ export async function maybeMigrateLegacyGatewayService(cfg, mode, runtime, promp
|
|
|
80
80
|
const { programArguments, workingDirectory, environment } = await buildGatewayInstallPlan({
|
|
81
81
|
env: process.env,
|
|
82
82
|
port,
|
|
83
|
-
token: cfg.gateway?.auth?.token ??
|
|
83
|
+
token: cfg.gateway?.auth?.token ??
|
|
84
|
+
process.env.POOLBOT_GATEWAY_TOKEN ??
|
|
85
|
+
process.env.CLAWDBOT_GATEWAY_TOKEN,
|
|
84
86
|
runtime: daemonRuntime,
|
|
85
87
|
warn: (message, title) => note(message, title),
|
|
86
88
|
config: cfg,
|
|
@@ -138,7 +140,9 @@ export async function maybeRepairGatewayServiceConfig(cfg, mode, runtime, prompt
|
|
|
138
140
|
const { programArguments, workingDirectory, environment } = await buildGatewayInstallPlan({
|
|
139
141
|
env: process.env,
|
|
140
142
|
port,
|
|
141
|
-
token: cfg.gateway?.auth?.token ??
|
|
143
|
+
token: cfg.gateway?.auth?.token ??
|
|
144
|
+
process.env.POOLBOT_GATEWAY_TOKEN ??
|
|
145
|
+
process.env.CLAWDBOT_GATEWAY_TOKEN,
|
|
142
146
|
runtime: needsNodeRuntime && systemNodePath ? "node" : runtimeChoice,
|
|
143
147
|
nodePath: systemNodePath ?? undefined,
|
|
144
148
|
warn: (message, title) => note(message, title),
|
|
@@ -69,7 +69,9 @@ export async function noteMacLaunchctlGatewayEnvOverrides(cfg, deps) {
|
|
|
69
69
|
passwordUnsets.push(" launchctl unsetenv CLAWDBOT_GATEWAY_PASSWORD");
|
|
70
70
|
const lines = [
|
|
71
71
|
"- launchctl environment overrides detected (can cause confusing unauthorized errors).",
|
|
72
|
-
hasToken
|
|
72
|
+
hasToken
|
|
73
|
+
? `- \`${poolbotToken ? "POOLBOT" : "CLAWDBOT"}_GATEWAY_TOKEN\` is set; it overrides config tokens.`
|
|
74
|
+
: undefined,
|
|
73
75
|
hasPassword
|
|
74
76
|
? `- \`${poolbotPassword ? "POOLBOT" : "CLAWDBOT"}_GATEWAY_PASSWORD\` is set; it overrides config passwords.`
|
|
75
77
|
: undefined,
|
|
@@ -92,7 +92,9 @@ export function resolveAuthForTarget(cfg, target, overrides) {
|
|
|
92
92
|
};
|
|
93
93
|
}
|
|
94
94
|
const envToken = process.env.POOLBOT_GATEWAY_TOKEN?.trim() || process.env.CLAWDBOT_GATEWAY_TOKEN?.trim() || "";
|
|
95
|
-
const envPassword = process.env.POOLBOT_GATEWAY_PASSWORD?.trim() ||
|
|
95
|
+
const envPassword = process.env.POOLBOT_GATEWAY_PASSWORD?.trim() ||
|
|
96
|
+
process.env.CLAWDBOT_GATEWAY_PASSWORD?.trim() ||
|
|
97
|
+
"";
|
|
96
98
|
const cfgToken = typeof cfg.gateway?.auth?.token === "string" ? cfg.gateway.auth.token.trim() : "";
|
|
97
99
|
const cfgPassword = typeof cfg.gateway?.auth?.password === "string" ? cfg.gateway.auth.password.trim() : "";
|
|
98
100
|
return {
|
|
@@ -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,
|