@nextclaw/server 0.5.22 → 0.5.24

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 NextClaw contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/index.d.ts CHANGED
@@ -20,12 +20,14 @@ type ProviderConfigView = {
20
20
  apiBase?: string | null;
21
21
  extraHeaders?: Record<string, string> | null;
22
22
  wireApi?: "auto" | "chat" | "responses" | null;
23
+ models?: string[];
23
24
  };
24
25
  type ProviderConfigUpdate = {
25
26
  apiKey?: string | null;
26
27
  apiBase?: string | null;
27
28
  extraHeaders?: Record<string, string> | null;
28
29
  wireApi?: "auto" | "chat" | "responses" | null;
30
+ models?: string[] | null;
29
31
  };
30
32
  type ProviderConnectionTestRequest = ProviderConfigUpdate & {
31
33
  model?: string | null;
@@ -286,11 +288,13 @@ type ConfigView = {
286
288
  type ProviderSpecView = {
287
289
  name: string;
288
290
  displayName?: string;
291
+ modelPrefix?: string;
289
292
  keywords: string[];
290
293
  envKey: string;
291
294
  isGateway?: boolean;
292
295
  isLocal?: boolean;
293
296
  defaultApiBase?: string;
297
+ defaultModels?: string[];
294
298
  supportsWireApi?: boolean;
295
299
  wireApiOptions?: Array<"auto" | "chat" | "responses">;
296
300
  defaultWireApi?: "auto" | "chat" | "responses";
@@ -300,6 +304,11 @@ type ChannelSpecView = {
300
304
  displayName?: string;
301
305
  enabled: boolean;
302
306
  tutorialUrl?: string;
307
+ tutorialUrls?: {
308
+ default?: string;
309
+ en?: string;
310
+ zh?: string;
311
+ };
303
312
  };
304
313
  type ConfigMetaView = {
305
314
  providers: ProviderSpecView[];
package/dist/index.js CHANGED
@@ -33,17 +33,49 @@ import {
33
33
  var MASK_MIN_LENGTH = 8;
34
34
  var EXTRA_SENSITIVE_PATH_PATTERNS = [/authorization/i, /cookie/i, /session/i, /bearer/i];
35
35
  var PROVIDER_TEST_MODEL_FALLBACKS = {
36
- openai: "gpt-4o-mini",
37
- deepseek: "deepseek-chat",
38
- gemini: "gemini-2.0-flash",
39
- zhipu: "glm-4-flash",
40
- dashscope: "qwen-plus",
41
- moonshot: "moonshot-v1-8k",
42
- minimax: "minimax-text-01",
36
+ openai: "gpt-5-mini",
37
+ deepseek: "deepseek-v3.2",
38
+ gemini: "gemini-3-flash-preview",
39
+ zhipu: "glm-5",
40
+ dashscope: "qwen3.5-flash",
41
+ moonshot: "kimi-k2.5",
42
+ minimax: "MiniMax-M2.5",
43
43
  groq: "llama-3.1-8b-instant",
44
- openrouter: "openai/gpt-4o-mini",
45
- aihubmix: "gpt-4o-mini",
46
- anthropic: "claude-3-5-haiku-latest"
44
+ openrouter: "openai/gpt-5.3-codex",
45
+ aihubmix: "gpt-5.3-codex",
46
+ anthropic: "claude-opus-4-6"
47
+ };
48
+ var PREFERRED_PROVIDER_ORDER = [
49
+ "openai",
50
+ "anthropic",
51
+ "gemini",
52
+ "openrouter",
53
+ "dashscope",
54
+ "deepseek",
55
+ "minimax",
56
+ "moonshot",
57
+ "zhipu"
58
+ ];
59
+ var PREFERRED_PROVIDER_ORDER_INDEX = new Map(
60
+ PREFERRED_PROVIDER_ORDER.map((name, index) => [name, index])
61
+ );
62
+ var DOCS_BASE_URL = "https://docs.nextclaw.io";
63
+ var CHANNEL_DEFAULT_TUTORIAL_URL = `${DOCS_BASE_URL}/guide/channels`;
64
+ var CHANNEL_TUTORIAL_URLS = {
65
+ telegram: { default: CHANNEL_DEFAULT_TUTORIAL_URL },
66
+ whatsapp: { default: CHANNEL_DEFAULT_TUTORIAL_URL },
67
+ discord: { default: CHANNEL_DEFAULT_TUTORIAL_URL },
68
+ feishu: {
69
+ default: `${DOCS_BASE_URL}/guide/tutorials/feishu`,
70
+ en: `${DOCS_BASE_URL}/en/guide/tutorials/feishu`,
71
+ zh: `${DOCS_BASE_URL}/zh/guide/tutorials/feishu`
72
+ },
73
+ mochat: { default: CHANNEL_DEFAULT_TUTORIAL_URL },
74
+ dingtalk: { default: CHANNEL_DEFAULT_TUTORIAL_URL },
75
+ wecom: { default: CHANNEL_DEFAULT_TUTORIAL_URL },
76
+ email: { default: CHANNEL_DEFAULT_TUTORIAL_URL },
77
+ slack: { default: CHANNEL_DEFAULT_TUTORIAL_URL },
78
+ qq: { default: CHANNEL_DEFAULT_TUTORIAL_URL }
47
79
  };
48
80
  function matchesExtraSensitivePath(path) {
49
81
  if (path === "session" || path.startsWith("session.")) {
@@ -246,6 +278,23 @@ function maskApiKey(value) {
246
278
  apiKeyMasked: `${value.slice(0, 2)}****${value.slice(-4)}`
247
279
  };
248
280
  }
281
+ function normalizeModelList(input) {
282
+ if (!input || input.length === 0) {
283
+ return [];
284
+ }
285
+ const deduped = /* @__PURE__ */ new Set();
286
+ for (const item of input) {
287
+ if (typeof item !== "string") {
288
+ continue;
289
+ }
290
+ const trimmed = item.trim();
291
+ if (!trimmed) {
292
+ continue;
293
+ }
294
+ deduped.add(trimmed);
295
+ }
296
+ return [...deduped];
297
+ }
249
298
  function toProviderView(config, provider, providerName, uiHints, spec) {
250
299
  const apiKeyPath = `providers.${providerName}.apiKey`;
251
300
  const apiKeyRefSet = hasSecretRef(config, apiKeyPath);
@@ -259,7 +308,8 @@ function toProviderView(config, provider, providerName, uiHints, spec) {
259
308
  apiKeySet: masked.apiKeySet || apiKeyRefSet,
260
309
  apiKeyMasked: masked.apiKeyMasked ?? (apiKeyRefSet ? "****" : void 0),
261
310
  apiBase: provider.apiBase ?? null,
262
- extraHeaders: extraHeaders && Object.keys(extraHeaders).length > 0 ? extraHeaders : null
311
+ extraHeaders: extraHeaders && Object.keys(extraHeaders).length > 0 ? extraHeaders : null,
312
+ models: normalizeModelList(provider.models ?? [])
263
313
  };
264
314
  if (spec?.supportsWireApi) {
265
315
  view.wireApi = provider.wireApi ?? spec.defaultWireApi ?? "auto";
@@ -303,20 +353,41 @@ function buildConfigMeta(config) {
303
353
  const providers = PROVIDERS.map((spec) => ({
304
354
  name: spec.name,
305
355
  displayName: spec.displayName,
356
+ modelPrefix: spec.modelPrefix,
306
357
  keywords: spec.keywords,
307
358
  envKey: spec.envKey,
308
359
  isGateway: spec.isGateway,
309
360
  isLocal: spec.isLocal,
310
361
  defaultApiBase: spec.defaultApiBase,
362
+ defaultModels: normalizeModelList(spec.defaultModels ?? []),
311
363
  supportsWireApi: spec.supportsWireApi,
312
364
  wireApiOptions: spec.wireApiOptions,
313
365
  defaultWireApi: spec.defaultWireApi
314
- }));
315
- const channels = Object.keys(config.channels).map((name) => ({
316
- name,
317
- displayName: name,
318
- enabled: Boolean(config.channels[name]?.enabled)
319
- }));
366
+ })).sort((left, right) => {
367
+ const leftRank = PREFERRED_PROVIDER_ORDER_INDEX.get(left.name);
368
+ const rightRank = PREFERRED_PROVIDER_ORDER_INDEX.get(right.name);
369
+ if (leftRank !== void 0 && rightRank !== void 0) {
370
+ return leftRank - rightRank;
371
+ }
372
+ if (leftRank !== void 0) {
373
+ return -1;
374
+ }
375
+ if (rightRank !== void 0) {
376
+ return 1;
377
+ }
378
+ return left.name.localeCompare(right.name);
379
+ });
380
+ const channels = Object.keys(config.channels).map((name) => {
381
+ const tutorialUrls = CHANNEL_TUTORIAL_URLS[name] ?? { default: CHANNEL_DEFAULT_TUTORIAL_URL };
382
+ const tutorialUrl = tutorialUrls.default ?? tutorialUrls.en ?? tutorialUrls.zh;
383
+ return {
384
+ name,
385
+ displayName: name,
386
+ enabled: Boolean(config.channels[name]?.enabled),
387
+ tutorialUrl,
388
+ tutorialUrls
389
+ };
390
+ });
320
391
  return { providers, channels };
321
392
  }
322
393
  function buildConfigSchemaView(_config) {
@@ -409,6 +480,9 @@ function updateProvider(configPath, providerName, patch) {
409
480
  if (Object.prototype.hasOwnProperty.call(patch, "wireApi") && spec?.supportsWireApi) {
410
481
  provider.wireApi = patch.wireApi ?? spec.defaultWireApi ?? "auto";
411
482
  }
483
+ if (Object.prototype.hasOwnProperty.call(patch, "models")) {
484
+ provider.models = normalizeModelList(patch.models ?? []);
485
+ }
412
486
  const next = ConfigSchema.parse(config);
413
487
  saveConfig(next, configPath);
414
488
  const uiHints = buildUiHints(next);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextclaw/server",
3
- "version": "0.5.22",
3
+ "version": "0.5.24",
4
4
  "private": false,
5
5
  "description": "Nextclaw UI/API server.",
6
6
  "type": "module",
@@ -15,10 +15,10 @@
15
15
  ],
16
16
  "dependencies": {
17
17
  "@hono/node-server": "^1.13.3",
18
- "@nextclaw/openclaw-compat": "^0.1.29",
18
+ "@nextclaw/openclaw-compat": "^0.1.30",
19
19
  "hono": "^4.6.2",
20
20
  "ws": "^8.18.0",
21
- "@nextclaw/core": "^0.6.38"
21
+ "@nextclaw/core": "^0.6.39"
22
22
  },
23
23
  "devDependencies": {
24
24
  "@types/node": "^20.17.6",