@nextclaw/server 0.3.6 → 0.4.0

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/index.d.ts CHANGED
@@ -54,7 +54,6 @@ type ConfigView = {
54
54
  tools?: Record<string, unknown>;
55
55
  gateway?: Record<string, unknown>;
56
56
  ui?: Record<string, unknown>;
57
- plugins?: Record<string, unknown>;
58
57
  };
59
58
  type ProviderSpecView = {
60
59
  name: string;
@@ -86,6 +85,7 @@ type ConfigUiHint = {
86
85
  advanced?: boolean;
87
86
  sensitive?: boolean;
88
87
  placeholder?: string;
88
+ readOnly?: boolean;
89
89
  };
90
90
  type ConfigUiHints = Record<string, ConfigUiHint>;
91
91
  type ConfigSchemaResponse = {
@@ -136,7 +136,7 @@ declare function createUiRouter(options: UiRouterOptions): Hono;
136
136
 
137
137
  declare function buildConfigView(config: Config): ConfigView;
138
138
  declare function buildConfigMeta(config: Config): ConfigMetaView;
139
- declare function buildConfigSchemaView(config: Config): ConfigSchemaResponse;
139
+ declare function buildConfigSchemaView(_config: Config): ConfigSchemaResponse;
140
140
  declare function loadConfigOrDefault(configPath: string): Config;
141
141
  declare function updateModel(configPath: string, model: string): ConfigView;
142
142
  declare function updateProvider(configPath: string, providerName: string, patch: ProviderConfigUpdate): ProviderConfigView | null;
package/dist/index.js CHANGED
@@ -19,10 +19,70 @@ import {
19
19
  buildConfigSchema,
20
20
  findProviderByName,
21
21
  getPackageVersion,
22
- getWorkspacePathFromConfig
22
+ isSensitiveConfigPath
23
23
  } from "@nextclaw/core";
24
- import { loadOpenClawPlugins, getPluginUiMetadataFromRegistry } from "@nextclaw/openclaw-compat";
25
24
  var MASK_MIN_LENGTH = 8;
25
+ var EXTRA_SENSITIVE_PATH_PATTERNS = [/authorization/i, /cookie/i, /session/i, /bearer/i];
26
+ function matchesExtraSensitivePath(path) {
27
+ return EXTRA_SENSITIVE_PATH_PATTERNS.some((pattern) => pattern.test(path));
28
+ }
29
+ function matchHint(path, hints) {
30
+ const direct = hints[path];
31
+ if (direct) {
32
+ return direct;
33
+ }
34
+ const segments = path.split(".");
35
+ for (const [hintKey, hint] of Object.entries(hints)) {
36
+ if (!hintKey.includes("*")) {
37
+ continue;
38
+ }
39
+ const hintSegments = hintKey.split(".");
40
+ if (hintSegments.length !== segments.length) {
41
+ continue;
42
+ }
43
+ let match = true;
44
+ for (let index = 0; index < segments.length; index += 1) {
45
+ if (hintSegments[index] !== "*" && hintSegments[index] !== segments[index]) {
46
+ match = false;
47
+ break;
48
+ }
49
+ }
50
+ if (match) {
51
+ return hint;
52
+ }
53
+ }
54
+ return void 0;
55
+ }
56
+ function isSensitivePath(path, hints) {
57
+ if (hints) {
58
+ const hint = matchHint(path, hints);
59
+ if (hint?.sensitive !== void 0) {
60
+ return Boolean(hint.sensitive);
61
+ }
62
+ }
63
+ return isSensitiveConfigPath(path) || matchesExtraSensitivePath(path);
64
+ }
65
+ function sanitizePublicConfigValue(value, prefix, hints) {
66
+ if (Array.isArray(value)) {
67
+ const nextPath = prefix ? `${prefix}[]` : "[]";
68
+ return value.map((entry) => sanitizePublicConfigValue(entry, nextPath, hints));
69
+ }
70
+ if (!value || typeof value !== "object") {
71
+ return value;
72
+ }
73
+ const output = {};
74
+ for (const [key, val] of Object.entries(value)) {
75
+ const nextPath = prefix ? `${prefix}.${key}` : key;
76
+ if (isSensitivePath(nextPath, hints)) {
77
+ continue;
78
+ }
79
+ output[key] = sanitizePublicConfigValue(val, nextPath, hints);
80
+ }
81
+ return output;
82
+ }
83
+ function buildUiHints(config) {
84
+ return buildConfigSchemaView(config).uiHints;
85
+ }
26
86
  function maskApiKey(value) {
27
87
  if (!value) {
28
88
  return { apiKeySet: false };
@@ -35,13 +95,18 @@ function maskApiKey(value) {
35
95
  apiKeyMasked: `${value.slice(0, 2)}****${value.slice(-4)}`
36
96
  };
37
97
  }
38
- function toProviderView(provider, spec) {
98
+ function toProviderView(provider, providerName, uiHints, spec) {
39
99
  const masked = maskApiKey(provider.apiKey);
100
+ const extraHeaders = provider.extraHeaders && Object.keys(provider.extraHeaders).length > 0 ? sanitizePublicConfigValue(
101
+ provider.extraHeaders,
102
+ `providers.${providerName}.extraHeaders`,
103
+ uiHints
104
+ ) : null;
40
105
  const view = {
41
106
  apiKeySet: masked.apiKeySet,
42
107
  apiKeyMasked: masked.apiKeyMasked,
43
108
  apiBase: provider.apiBase ?? null,
44
- extraHeaders: provider.extraHeaders ?? null
109
+ extraHeaders: extraHeaders && Object.keys(extraHeaders).length > 0 ? extraHeaders : null
45
110
  };
46
111
  if (spec?.supportsWireApi) {
47
112
  view.wireApi = provider.wireApi ?? spec.defaultWireApi ?? "auto";
@@ -49,19 +114,23 @@ function toProviderView(provider, spec) {
49
114
  return view;
50
115
  }
51
116
  function buildConfigView(config) {
117
+ const uiHints = buildUiHints(config);
52
118
  const providers = {};
53
119
  for (const [name, provider] of Object.entries(config.providers)) {
54
120
  const spec = findProviderByName(name);
55
- providers[name] = toProviderView(provider, spec);
121
+ providers[name] = toProviderView(provider, name, uiHints, spec);
56
122
  }
57
123
  return {
58
124
  agents: config.agents,
59
125
  providers,
60
- channels: config.channels,
61
- tools: config.tools,
62
- gateway: config.gateway,
63
- ui: config.ui,
64
- plugins: config.plugins
126
+ channels: sanitizePublicConfigValue(
127
+ config.channels,
128
+ "channels",
129
+ uiHints
130
+ ),
131
+ tools: sanitizePublicConfigValue(config.tools, "tools", uiHints),
132
+ gateway: sanitizePublicConfigValue(config.gateway, "gateway", uiHints),
133
+ ui: sanitizePublicConfigValue(config.ui, "ui", uiHints)
65
134
  };
66
135
  }
67
136
  function buildConfigMeta(config) {
@@ -84,17 +153,8 @@ function buildConfigMeta(config) {
84
153
  }));
85
154
  return { providers, channels };
86
155
  }
87
- function buildConfigSchemaView(config) {
88
- const workspaceDir = getWorkspacePathFromConfig(config);
89
- const registry = loadOpenClawPlugins({
90
- config,
91
- workspaceDir,
92
- mode: "full",
93
- reservedChannelIds: Object.keys(config.channels),
94
- reservedProviderIds: PROVIDERS.map((provider) => provider.name)
95
- });
96
- const plugins = getPluginUiMetadataFromRegistry(registry);
97
- return buildConfigSchema({ version: getPackageVersion(), plugins });
156
+ function buildConfigSchemaView(_config) {
157
+ return buildConfigSchema({ version: getPackageVersion() });
98
158
  }
99
159
  function loadConfigOrDefault(configPath) {
100
160
  return loadConfig(configPath);
@@ -127,8 +187,9 @@ function updateProvider(configPath, providerName, patch) {
127
187
  }
128
188
  const next = ConfigSchema.parse(config);
129
189
  saveConfig(next, configPath);
190
+ const uiHints = buildUiHints(next);
130
191
  const updated = next.providers[providerName];
131
- return toProviderView(updated, spec ?? void 0);
192
+ return toProviderView(updated, providerName, uiHints, spec ?? void 0);
132
193
  }
133
194
  function updateChannel(configPath, channelName, patch) {
134
195
  const config = loadConfigOrDefault(configPath);
@@ -139,7 +200,12 @@ function updateChannel(configPath, channelName, patch) {
139
200
  config.channels[channelName] = { ...channel, ...patch };
140
201
  const next = ConfigSchema.parse(config);
141
202
  saveConfig(next, configPath);
142
- return next.channels[channelName];
203
+ const uiHints = buildUiHints(next);
204
+ return sanitizePublicConfigValue(
205
+ next.channels[channelName],
206
+ `channels.${channelName}`,
207
+ uiHints
208
+ );
143
209
  }
144
210
 
145
211
  // src/ui/router.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextclaw/server",
3
- "version": "0.3.6",
3
+ "version": "0.4.0",
4
4
  "private": false,
5
5
  "description": "Nextclaw UI/API server.",
6
6
  "type": "module",
@@ -17,8 +17,7 @@
17
17
  "@hono/node-server": "^1.13.3",
18
18
  "hono": "^4.6.2",
19
19
  "ws": "^8.18.0",
20
- "@nextclaw/core": "^0.5.0",
21
- "@nextclaw/openclaw-compat": "^0.1.3"
20
+ "@nextclaw/core": "^0.6.0"
22
21
  },
23
22
  "devDependencies": {
24
23
  "@types/node": "^20.17.6",