@poolzin/pool-bot 2026.2.5 → 2026.2.7
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/auth-profiles/profiles.js +9 -0
- package/dist/agents/auth-profiles.js +1 -1
- package/dist/agents/huggingface-models.js +166 -0
- package/dist/agents/model-auth.js +5 -0
- package/dist/build-info.json +3 -3
- package/dist/cli/config-cli.js +17 -3
- package/dist/cli/program/register.onboard.js +34 -11
- package/dist/commands/auth-choice-options.js +60 -7
- package/dist/commands/auth-choice.apply.api-providers.js +149 -98
- package/dist/commands/auth-choice.apply.huggingface.js +130 -0
- package/dist/commands/auth-choice.apply.openrouter.js +77 -0
- package/dist/commands/auth-choice.apply.vllm.js +92 -0
- package/dist/commands/auth-choice.preferred-provider.js +9 -0
- package/dist/commands/onboard-auth.config-core.js +207 -8
- package/dist/commands/onboard-auth.credentials.js +35 -5
- package/dist/commands/onboard-auth.js +3 -3
- package/dist/commands/onboard-auth.models.js +45 -0
- package/dist/commands/onboard-custom.js +181 -70
- package/dist/commands/onboard-non-interactive/api-keys.js +10 -1
- package/dist/commands/onboard-non-interactive/local/auth-choice-inference.js +14 -7
- package/dist/commands/onboard-non-interactive/local/auth-choice.js +322 -144
- package/dist/commands/zai-endpoint-detect.js +97 -0
- package/dist/config/legacy.migrations.part-3.js +57 -0
- package/dist/daemon/constants.js +7 -3
- package/dist/tui/components/filterable-select-list.js +5 -2
- package/dist/tui/components/searchable-select-list.js +6 -1
- package/dist/tui/tui-command-handlers.js +13 -5
- package/package.json +5 -5
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { fetchWithTimeout } from "../utils/fetch-timeout.js";
|
|
2
|
+
import { ZAI_CN_BASE_URL, ZAI_CODING_CN_BASE_URL, ZAI_CODING_GLOBAL_BASE_URL, ZAI_GLOBAL_BASE_URL, } from "./onboard-auth.models.js";
|
|
3
|
+
async function probeZaiChatCompletions(params) {
|
|
4
|
+
try {
|
|
5
|
+
const res = await fetchWithTimeout(`${params.baseUrl}/chat/completions`, {
|
|
6
|
+
method: "POST",
|
|
7
|
+
headers: {
|
|
8
|
+
authorization: `Bearer ${params.apiKey}`,
|
|
9
|
+
"content-type": "application/json",
|
|
10
|
+
},
|
|
11
|
+
body: JSON.stringify({
|
|
12
|
+
model: params.modelId,
|
|
13
|
+
stream: false,
|
|
14
|
+
max_tokens: 1,
|
|
15
|
+
messages: [{ role: "user", content: "ping" }],
|
|
16
|
+
}),
|
|
17
|
+
}, params.timeoutMs, params.fetchFn);
|
|
18
|
+
if (res.ok) {
|
|
19
|
+
return { ok: true };
|
|
20
|
+
}
|
|
21
|
+
let errorCode;
|
|
22
|
+
let errorMessage;
|
|
23
|
+
try {
|
|
24
|
+
const json = (await res.json());
|
|
25
|
+
const code = json?.error?.code;
|
|
26
|
+
const msg = json?.error?.message ?? json?.msg ?? json?.message;
|
|
27
|
+
if (typeof code === "string") {
|
|
28
|
+
errorCode = code;
|
|
29
|
+
}
|
|
30
|
+
else if (typeof code === "number") {
|
|
31
|
+
errorCode = String(code);
|
|
32
|
+
}
|
|
33
|
+
if (typeof msg === "string") {
|
|
34
|
+
errorMessage = msg;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
// ignore
|
|
39
|
+
}
|
|
40
|
+
return { ok: false, status: res.status, errorCode, errorMessage };
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return { ok: false };
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export async function detectZaiEndpoint(params) {
|
|
47
|
+
// Never auto-probe in vitest; it would create flaky network behavior.
|
|
48
|
+
if (process.env.VITEST && !params.fetchFn) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
const timeoutMs = params.timeoutMs ?? 5_000;
|
|
52
|
+
// Prefer GLM-5 on the general API endpoints.
|
|
53
|
+
const glm5 = [
|
|
54
|
+
{ endpoint: "global", baseUrl: ZAI_GLOBAL_BASE_URL },
|
|
55
|
+
{ endpoint: "cn", baseUrl: ZAI_CN_BASE_URL },
|
|
56
|
+
];
|
|
57
|
+
for (const candidate of glm5) {
|
|
58
|
+
const result = await probeZaiChatCompletions({
|
|
59
|
+
baseUrl: candidate.baseUrl,
|
|
60
|
+
apiKey: params.apiKey,
|
|
61
|
+
modelId: "glm-5",
|
|
62
|
+
timeoutMs,
|
|
63
|
+
fetchFn: params.fetchFn,
|
|
64
|
+
});
|
|
65
|
+
if (result.ok) {
|
|
66
|
+
return {
|
|
67
|
+
endpoint: candidate.endpoint,
|
|
68
|
+
baseUrl: candidate.baseUrl,
|
|
69
|
+
modelId: "glm-5",
|
|
70
|
+
note: `Verified GLM-5 on ${candidate.endpoint} endpoint.`,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// Fallback: Coding Plan endpoint (GLM-5 not available there).
|
|
75
|
+
const coding = [
|
|
76
|
+
{ endpoint: "coding-global", baseUrl: ZAI_CODING_GLOBAL_BASE_URL },
|
|
77
|
+
{ endpoint: "coding-cn", baseUrl: ZAI_CODING_CN_BASE_URL },
|
|
78
|
+
];
|
|
79
|
+
for (const candidate of coding) {
|
|
80
|
+
const result = await probeZaiChatCompletions({
|
|
81
|
+
baseUrl: candidate.baseUrl,
|
|
82
|
+
apiKey: params.apiKey,
|
|
83
|
+
modelId: "glm-4.7",
|
|
84
|
+
timeoutMs,
|
|
85
|
+
fetchFn: params.fetchFn,
|
|
86
|
+
});
|
|
87
|
+
if (result.ok) {
|
|
88
|
+
return {
|
|
89
|
+
endpoint: candidate.endpoint,
|
|
90
|
+
baseUrl: candidate.baseUrl,
|
|
91
|
+
modelId: "glm-4.7",
|
|
92
|
+
note: "Coding Plan endpoint detected; GLM-5 is not available there. Defaulting to GLM-4.7.",
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
@@ -161,4 +161,61 @@ export const LEGACY_CONFIG_MIGRATIONS_PART_3 = [
|
|
|
161
161
|
delete raw.identity;
|
|
162
162
|
},
|
|
163
163
|
},
|
|
164
|
+
{
|
|
165
|
+
id: "gateway.bind-enum-fix",
|
|
166
|
+
describe: "Fix invalid gateway.bind values to 'auto'",
|
|
167
|
+
apply: (raw, changes) => {
|
|
168
|
+
const gateway = getRecord(raw.gateway);
|
|
169
|
+
if (!gateway)
|
|
170
|
+
return;
|
|
171
|
+
const bind = gateway.bind;
|
|
172
|
+
if (bind === undefined)
|
|
173
|
+
return;
|
|
174
|
+
const validBindValues = new Set(["auto", "lan", "loopback", "custom", "tailnet"]);
|
|
175
|
+
if (typeof bind !== "string" || !validBindValues.has(bind)) {
|
|
176
|
+
gateway.bind = "auto";
|
|
177
|
+
changes.push(`Fixed gateway.bind from ${JSON.stringify(bind)} → "auto".`);
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
id: "gateway.nodes.browser.mode-enum-fix",
|
|
183
|
+
describe: "Fix invalid gateway.nodes.browser.mode values to 'auto'",
|
|
184
|
+
apply: (raw, changes) => {
|
|
185
|
+
const gateway = getRecord(raw.gateway);
|
|
186
|
+
if (!gateway)
|
|
187
|
+
return;
|
|
188
|
+
const nodes = getRecord(gateway.nodes);
|
|
189
|
+
if (!nodes)
|
|
190
|
+
return;
|
|
191
|
+
const browser = getRecord(nodes.browser);
|
|
192
|
+
if (!browser)
|
|
193
|
+
return;
|
|
194
|
+
const mode = browser.mode;
|
|
195
|
+
if (mode === undefined)
|
|
196
|
+
return;
|
|
197
|
+
const validModes = new Set(["auto", "manual", "off"]);
|
|
198
|
+
if (typeof mode !== "string" || !validModes.has(mode)) {
|
|
199
|
+
browser.mode = "auto";
|
|
200
|
+
changes.push(`Fixed gateway.nodes.browser.mode from ${JSON.stringify(mode)} → "auto".`);
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
id: "gateway.mode-enum-fix",
|
|
206
|
+
describe: "Fix invalid gateway.mode values to 'local'",
|
|
207
|
+
apply: (raw, changes) => {
|
|
208
|
+
const gateway = getRecord(raw.gateway);
|
|
209
|
+
if (!gateway)
|
|
210
|
+
return;
|
|
211
|
+
const mode = gateway.mode;
|
|
212
|
+
if (mode === undefined)
|
|
213
|
+
return;
|
|
214
|
+
const validModes = new Set(["local", "remote"]);
|
|
215
|
+
if (typeof mode !== "string" || !validModes.has(mode)) {
|
|
216
|
+
gateway.mode = "local";
|
|
217
|
+
changes.push(`Fixed gateway.mode from ${JSON.stringify(mode)} → "local".`);
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
},
|
|
164
221
|
];
|
package/dist/daemon/constants.js
CHANGED
|
@@ -10,9 +10,13 @@ export const NODE_WINDOWS_TASK_NAME = "Poolbot Node";
|
|
|
10
10
|
export const NODE_SERVICE_MARKER = "poolbot";
|
|
11
11
|
export const NODE_SERVICE_KIND = "node";
|
|
12
12
|
export const NODE_WINDOWS_TASK_SCRIPT_NAME = "node.cmd";
|
|
13
|
-
export const LEGACY_GATEWAY_LAUNCH_AGENT_LABELS = [
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
export const LEGACY_GATEWAY_LAUNCH_AGENT_LABELS = [
|
|
14
|
+
"com.steipete.poolbot.gateway",
|
|
15
|
+
"com.moltbot.gateway",
|
|
16
|
+
"com.clawdbot.gateway",
|
|
17
|
+
];
|
|
18
|
+
export const LEGACY_GATEWAY_SYSTEMD_SERVICE_NAMES = ["moltbot-gateway", "clawdbot-gateway"];
|
|
19
|
+
export const LEGACY_GATEWAY_WINDOWS_TASK_NAMES = ["Moltbot Gateway", "Clawdbot Gateway"];
|
|
16
20
|
export function normalizeGatewayProfile(profile) {
|
|
17
21
|
const trimmed = profile?.trim();
|
|
18
22
|
if (!trimmed || trimmed.toLowerCase() === "default")
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Input, matchesKey, SelectList, getEditorKeybindings, } from "@mariozechner/pi-tui";
|
|
1
|
+
import { Input, matchesKey, SelectList, getEditorKeybindings, truncateToWidth, } from "@mariozechner/pi-tui";
|
|
2
2
|
import chalk from "chalk";
|
|
3
3
|
import { fuzzyFilterLower, prepareSearchItems } from "./fuzzy-filter.js";
|
|
4
4
|
/**
|
|
@@ -46,7 +46,10 @@ export class FilterableSelectList {
|
|
|
46
46
|
// Select list
|
|
47
47
|
const listLines = this.selectList.render(width);
|
|
48
48
|
lines.push(...listLines);
|
|
49
|
-
|
|
49
|
+
// Defensive truncation: ensure no line exceeds the target width after
|
|
50
|
+
// all ANSI formatting. Prevents pi-tui compositeLineAt crash on
|
|
51
|
+
// ANSI-heavy backgrounds ("Rendered line N exceeds terminal width").
|
|
52
|
+
return lines.map((line) => truncateToWidth(line, width));
|
|
50
53
|
}
|
|
51
54
|
handleInput(keyData) {
|
|
52
55
|
const allowVimNav = !this.filterText.trim();
|
|
@@ -149,7 +149,12 @@ export class SearchableSelectList {
|
|
|
149
149
|
const scrollInfo = `${this.selectedIndex + 1}/${this.filteredItems.length}`;
|
|
150
150
|
lines.push(this.theme.scrollInfo(` ${scrollInfo}`));
|
|
151
151
|
}
|
|
152
|
-
|
|
152
|
+
// Defensive truncation: ensure no line exceeds the target width after
|
|
153
|
+
// all ANSI formatting has been applied. pi-tui's compositeLineAt can
|
|
154
|
+
// miscalculate visible widths on ANSI-heavy lines, causing a crash
|
|
155
|
+
// ("Rendered line N exceeds terminal width"). Truncating here is a
|
|
156
|
+
// safe final guard that prevents the crash.
|
|
157
|
+
return lines.map((line) => truncateToWidth(line, width));
|
|
153
158
|
}
|
|
154
159
|
renderItemLine(item, isSelected, width, query) {
|
|
155
160
|
const prefix = isSelected ? "→ " : " ";
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { truncateToWidth } from "@mariozechner/pi-tui";
|
|
1
2
|
import { formatThinkingLevels, normalizeUsageDisplay, resolveResponseUsageMode, } from "../auto-reply/thinking.js";
|
|
2
3
|
import { normalizeAgentId } from "../routing/session-key.js";
|
|
3
4
|
import { formatRelativeTime } from "../utils/time-format.js";
|
|
@@ -10,6 +11,10 @@ export function createCommandHandlers(context) {
|
|
|
10
11
|
state.currentAgentId = normalizeAgentId(id);
|
|
11
12
|
await setSession("");
|
|
12
13
|
};
|
|
14
|
+
// Maximum visible width for overlay item strings. The overlay has its own
|
|
15
|
+
// padding/chrome (~4 chars). We subtract a generous margin so that even
|
|
16
|
+
// after ANSI formatting, lines stay within terminal bounds.
|
|
17
|
+
const overlayItemWidth = () => Math.max(30, (tui.terminal.columns ?? 80) - 6);
|
|
13
18
|
const openModelSelector = async () => {
|
|
14
19
|
try {
|
|
15
20
|
const models = await client.listModels();
|
|
@@ -18,10 +23,11 @@ export function createCommandHandlers(context) {
|
|
|
18
23
|
tui.requestRender();
|
|
19
24
|
return;
|
|
20
25
|
}
|
|
26
|
+
const maxW = overlayItemWidth();
|
|
21
27
|
const items = models.map((model) => ({
|
|
22
28
|
value: `${model.provider}/${model.id}`,
|
|
23
|
-
label: `${model.provider}/${model.id}`,
|
|
24
|
-
description: model.name && model.name !== model.id ? model.name : "",
|
|
29
|
+
label: truncateToWidth(`${model.provider}/${model.id}`, maxW),
|
|
30
|
+
description: model.name && model.name !== model.id ? truncateToWidth(model.name, maxW) : "",
|
|
25
31
|
}));
|
|
26
32
|
const selector = createSearchableSelectList(items, 9);
|
|
27
33
|
selector.onSelect = (item) => {
|
|
@@ -60,9 +66,10 @@ export function createCommandHandlers(context) {
|
|
|
60
66
|
tui.requestRender();
|
|
61
67
|
return;
|
|
62
68
|
}
|
|
69
|
+
const maxW = overlayItemWidth();
|
|
63
70
|
const items = state.agents.map((agent) => ({
|
|
64
71
|
value: agent.id,
|
|
65
|
-
label: agent.name ? `${agent.id} (${agent.name})` : agent.id,
|
|
72
|
+
label: truncateToWidth(agent.name ? `${agent.id} (${agent.name})` : agent.id, maxW),
|
|
66
73
|
description: agent.id === state.agentDefaultId ? "default" : "",
|
|
67
74
|
}));
|
|
68
75
|
const selector = createSearchableSelectList(items, 9);
|
|
@@ -89,6 +96,7 @@ export function createCommandHandlers(context) {
|
|
|
89
96
|
includeLastMessage: true,
|
|
90
97
|
agentId: state.currentAgentId,
|
|
91
98
|
});
|
|
99
|
+
const maxW = overlayItemWidth();
|
|
92
100
|
const items = result.sessions.map((session) => {
|
|
93
101
|
const title = session.derivedTitle ?? session.displayName;
|
|
94
102
|
const formattedKey = formatSessionKey(session.key);
|
|
@@ -100,8 +108,8 @@ export function createCommandHandlers(context) {
|
|
|
100
108
|
const description = timePart && preview ? `${timePart} · ${preview}` : (preview ?? timePart);
|
|
101
109
|
return {
|
|
102
110
|
value: session.key,
|
|
103
|
-
label,
|
|
104
|
-
description,
|
|
111
|
+
label: truncateToWidth(label, maxW),
|
|
112
|
+
description: truncateToWidth(description, maxW),
|
|
105
113
|
searchText: [
|
|
106
114
|
session.displayName,
|
|
107
115
|
session.label,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@poolzin/pool-bot",
|
|
3
|
-
"version": "2026.2.
|
|
3
|
+
"version": "2026.2.7",
|
|
4
4
|
"description": "🎱 Pool Bot - AI assistant with PLCODE integrations",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"license": "MIT",
|
|
@@ -110,10 +110,10 @@
|
|
|
110
110
|
"@larksuiteoapi/node-sdk": "^1.58.0",
|
|
111
111
|
"@line/bot-sdk": "^10.6.0",
|
|
112
112
|
"@lydell/node-pty": "1.2.0-beta.3",
|
|
113
|
-
"@mariozechner/pi-agent-core": "0.52.
|
|
114
|
-
"@mariozechner/pi-ai": "0.52.
|
|
115
|
-
"@mariozechner/pi-coding-agent": "0.52.
|
|
116
|
-
"@mariozechner/pi-tui": "0.52.
|
|
113
|
+
"@mariozechner/pi-agent-core": "0.52.12",
|
|
114
|
+
"@mariozechner/pi-ai": "0.52.12",
|
|
115
|
+
"@mariozechner/pi-coding-agent": "0.52.12",
|
|
116
|
+
"@mariozechner/pi-tui": "0.52.12",
|
|
117
117
|
"@mozilla/readability": "^0.6.0",
|
|
118
118
|
"@sinclair/typebox": "0.34.48",
|
|
119
119
|
"@slack/bolt": "^4.6.0",
|