@nextclaw/server 0.12.3 → 0.12.4

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.
Files changed (2) hide show
  1. package/dist/index.js +61 -44
  2. package/package.json +6 -6
package/dist/index.js CHANGED
@@ -2,9 +2,9 @@ import { Hono } from "hono";
2
2
  import { compress } from "hono/compress";
3
3
  import { serve } from "@hono/node-server";
4
4
  import { WebSocket, WebSocketServer } from "ws";
5
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
5
+ import fs, { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
6
6
  import { readFile, readdir, realpath, stat } from "node:fs/promises";
7
- import { dirname, isAbsolute, join, parse, resolve } from "node:path";
7
+ import path, { dirname, isAbsolute, join, parse, resolve } from "node:path";
8
8
  import * as NextclawCore from "@nextclaw/core";
9
9
  import { ConfigSchema, DEFAULT_WORKSPACE_PATH, LiteLLMProvider, SessionManager, buildConfigSchema, createAgentProfile, expandHome, findEffectiveAgentProfile, getDataDir, getPackageVersion, getProviderName, getWorkspacePathFromConfig, hasSecretRef, isSensitiveConfigPath, loadConfig, normalizeThinkingLevels, parseThinkingLevel, probeFeishu, readAgentAvatarContent, removeAgentProfile, resolveEffectiveAgentProfiles, saveConfig, updateAgentProfile } from "@nextclaw/core";
10
10
  import { createHash, randomBytes, randomUUID, scryptSync, timingSafeEqual } from "node:crypto";
@@ -1077,6 +1077,7 @@ const PREFERRED_PROVIDER_ORDER_INDEX = new Map([
1077
1077
  "deepseek",
1078
1078
  "minimax",
1079
1079
  "moonshot",
1080
+ "kimi-coding",
1080
1081
  "zhipu"
1081
1082
  ].map((name, index) => [name, index]));
1082
1083
  const BUILTIN_PROVIDERS = listServerBuiltinProviders();
@@ -3491,6 +3492,21 @@ var McpMarketplaceController = class {
3491
3492
  };
3492
3493
  //#endregion
3493
3494
  //#region src/ui/ui-routes/marketplace/spec.ts
3495
+ function readPluginPackageNameFromSource(source) {
3496
+ const trimmed = source?.trim();
3497
+ if (!trimmed) return;
3498
+ let cursor = path.dirname(path.resolve(trimmed));
3499
+ for (let index = 0; index < 8; index += 1) {
3500
+ try {
3501
+ const manifestPath = path.join(cursor, "package.json");
3502
+ const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
3503
+ if (typeof manifest.name === "string" && manifest.name.trim().length > 0) return manifest.name.trim();
3504
+ } catch {}
3505
+ const parent = path.dirname(cursor);
3506
+ if (parent === cursor) break;
3507
+ cursor = parent;
3508
+ }
3509
+ }
3494
3510
  function normalizePluginNpmSpec(rawSpec) {
3495
3511
  const spec = rawSpec.trim();
3496
3512
  if (!spec.startsWith("@")) return spec;
@@ -3512,6 +3528,12 @@ function resolvePluginCanonicalSpec(params) {
3512
3528
  }
3513
3529
  return params.pluginId;
3514
3530
  }
3531
+ function resolveDiscoveredPluginCanonicalSpec(params) {
3532
+ return resolvePluginCanonicalSpec({
3533
+ pluginId: params.pluginId,
3534
+ installSpec: params.installSpec ?? readPluginPackageNameFromSource(params.source)
3535
+ });
3536
+ }
3515
3537
  function readPluginRuntimeStatusPriority(status) {
3516
3538
  if (status === "loaded") return 400;
3517
3539
  if (status === "disabled") return 300;
@@ -3606,36 +3628,32 @@ function buildDiscoveredPluginMap(params) {
3606
3628
  }
3607
3629
  return discoveredById;
3608
3630
  }
3609
- function appendDiscoveredPluginRecords(params) {
3610
- for (const plugin of params.discoveredById.values()) {
3631
+ function collectDiscoveredPluginRecords(params) {
3632
+ return Array.from(params.discoveredById.values()).map((plugin) => {
3611
3633
  const installRecord = params.pluginRecordsMap[plugin.id];
3612
3634
  const entry = params.pluginEntries[plugin.id];
3613
- const normalizedSpec = resolvePluginCanonicalSpec({
3614
- pluginId: plugin.id,
3615
- installSpec: installRecord?.spec
3616
- });
3617
- const enabled = entry?.enabled === false ? false : plugin.enabled;
3618
- const runtimeStatus = entry?.enabled === false ? "disabled" : plugin.status;
3619
- params.pluginRecords.push({
3635
+ return {
3620
3636
  type: "plugin",
3621
3637
  id: plugin.id,
3622
- spec: normalizedSpec,
3638
+ spec: resolveDiscoveredPluginCanonicalSpec({
3639
+ pluginId: plugin.id,
3640
+ installSpec: installRecord?.spec,
3641
+ source: plugin.source
3642
+ }),
3623
3643
  label: plugin.name && plugin.name.trim().length > 0 ? plugin.name : plugin.id,
3624
3644
  source: plugin.source,
3625
3645
  installedAt: installRecord?.installedAt,
3626
- enabled,
3627
- runtimeStatus,
3646
+ enabled: entry?.enabled === false ? false : plugin.enabled,
3647
+ runtimeStatus: entry?.enabled === false ? "disabled" : plugin.status,
3628
3648
  origin: plugin.origin,
3629
3649
  installPath: installRecord?.installPath
3630
- });
3631
- params.seenPluginIds.add(plugin.id);
3632
- }
3650
+ };
3651
+ });
3633
3652
  }
3634
- function appendInstalledOnlyPluginRecords(params) {
3635
- for (const [pluginId, installRecord] of Object.entries(params.pluginRecordsMap)) {
3636
- if (params.seenPluginIds.has(pluginId)) continue;
3653
+ function collectInstalledOnlyPluginRecords(params) {
3654
+ return Object.entries(params.pluginRecordsMap).filter(([pluginId]) => !params.seenPluginIds.has(pluginId)).map(([pluginId, installRecord]) => {
3637
3655
  const entry = params.pluginEntries[pluginId];
3638
- params.pluginRecords.push({
3656
+ return {
3639
3657
  type: "plugin",
3640
3658
  id: pluginId,
3641
3659
  spec: resolvePluginCanonicalSpec({
@@ -3648,14 +3666,12 @@ function appendInstalledOnlyPluginRecords(params) {
3648
3666
  enabled: entry?.enabled !== false,
3649
3667
  runtimeStatus: entry?.enabled === false ? "disabled" : "unresolved",
3650
3668
  installPath: installRecord.installPath
3651
- });
3652
- params.seenPluginIds.add(pluginId);
3653
- }
3669
+ };
3670
+ });
3654
3671
  }
3655
- function appendConfigOnlyPluginRecords(params) {
3656
- for (const [pluginId, entry] of Object.entries(params.pluginEntries)) {
3657
- if (params.seenPluginIds.has(pluginId)) continue;
3658
- params.pluginRecords.push({
3672
+ function collectConfigOnlyPluginRecords(params) {
3673
+ return Object.entries(params.pluginEntries).filter(([pluginId]) => !params.seenPluginIds.has(pluginId)).map(([pluginId, entry]) => {
3674
+ return {
3659
3675
  type: "plugin",
3660
3676
  id: pluginId,
3661
3677
  spec: resolvePluginCanonicalSpec({ pluginId }),
@@ -3663,9 +3679,8 @@ function appendConfigOnlyPluginRecords(params) {
3663
3679
  source: "config",
3664
3680
  enabled: entry?.enabled !== false,
3665
3681
  runtimeStatus: entry?.enabled === false ? "disabled" : "unresolved"
3666
- });
3667
- params.seenPluginIds.add(pluginId);
3668
- }
3682
+ };
3683
+ });
3669
3684
  }
3670
3685
  function findPluginIdByExactId(pluginRecords, lowerTargetId) {
3671
3686
  for (const record of pluginRecords) {
@@ -3681,12 +3696,13 @@ function findPluginIdByNormalizedSpec(pluginRecords, normalizedSpec) {
3681
3696
  if (normalizePluginNpmSpec(record.spec).toLowerCase() === normalizedSpec) return recordId;
3682
3697
  }
3683
3698
  }
3699
+ function collectDefinedRecordIds(records) {
3700
+ return new Set(records.map((record) => readNonEmptyString(record.id)).filter((recordId) => Boolean(recordId)));
3701
+ }
3684
3702
  function collectInstalledPluginRecords(options) {
3685
3703
  const config = loadConfigOrDefault(options.configPath);
3686
3704
  const pluginRecordsMap = config.plugins.installs ?? {};
3687
3705
  const pluginEntries = config.plugins.entries ?? {};
3688
- const pluginRecords = [];
3689
- const seenPluginIds = /* @__PURE__ */ new Set();
3690
3706
  const installedPluginIds = new Set(Object.keys(pluginRecordsMap));
3691
3707
  let discoveredPlugins = [];
3692
3708
  try {
@@ -3697,28 +3713,29 @@ function collectInstalledPluginRecords(options) {
3697
3713
  } catch {
3698
3714
  discoveredPlugins = [];
3699
3715
  }
3700
- appendDiscoveredPluginRecords({
3716
+ const discoveredRecords = collectDiscoveredPluginRecords({
3701
3717
  discoveredById: buildDiscoveredPluginMap({
3702
3718
  discoveredPlugins,
3703
3719
  installedPluginIds
3704
3720
  }),
3705
3721
  pluginRecordsMap,
3706
- pluginEntries,
3707
- pluginRecords,
3708
- seenPluginIds
3722
+ pluginEntries
3709
3723
  });
3710
- appendInstalledOnlyPluginRecords({
3724
+ const seenDiscoveredPluginIds = collectDefinedRecordIds(discoveredRecords);
3725
+ const installedOnlyRecords = collectInstalledOnlyPluginRecords({
3711
3726
  pluginRecordsMap,
3712
3727
  pluginEntries,
3713
- pluginRecords,
3714
- seenPluginIds
3728
+ seenPluginIds: seenDiscoveredPluginIds
3715
3729
  });
3716
- appendConfigOnlyPluginRecords({
3730
+ const configOnlyRecords = collectConfigOnlyPluginRecords({
3717
3731
  pluginEntries,
3718
- pluginRecords,
3719
- seenPluginIds
3732
+ seenPluginIds: new Set([...seenDiscoveredPluginIds, ...collectDefinedRecordIds(installedOnlyRecords)])
3720
3733
  });
3721
- const dedupedPluginRecords = dedupeInstalledPluginRecordsByCanonicalSpec(pluginRecords);
3734
+ const dedupedPluginRecords = dedupeInstalledPluginRecordsByCanonicalSpec([
3735
+ ...discoveredRecords,
3736
+ ...installedOnlyRecords,
3737
+ ...configOnlyRecords
3738
+ ]);
3722
3739
  dedupedPluginRecords.sort((left, right) => {
3723
3740
  return left.spec.localeCompare(right.spec);
3724
3741
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextclaw/server",
3
- "version": "0.12.3",
3
+ "version": "0.12.4",
4
4
  "private": false,
5
5
  "description": "Nextclaw UI/API server.",
6
6
  "type": "module",
@@ -18,12 +18,12 @@
18
18
  "@hono/node-server": "^1.13.3",
19
19
  "hono": "^4.6.2",
20
20
  "ws": "^8.18.0",
21
- "@nextclaw/core": "0.12.3",
22
- "@nextclaw/mcp": "0.1.68",
23
- "@nextclaw/ncp-http-agent-server": "0.3.12",
24
- "@nextclaw/openclaw-compat": "1.0.3",
21
+ "@nextclaw/core": "0.12.4",
22
+ "@nextclaw/mcp": "0.1.69",
25
23
  "@nextclaw/ncp": "0.5.0",
26
- "@nextclaw/runtime": "0.2.35"
24
+ "@nextclaw/ncp-http-agent-server": "0.3.12",
25
+ "@nextclaw/openclaw-compat": "1.0.4",
26
+ "@nextclaw/runtime": "0.2.36"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@types/node": "^20.17.6",