@nextclaw/server 0.3.7 → 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 +1 -2
- package/dist/index.js +89 -23
- package/package.json +2 -3
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;
|
|
@@ -137,7 +136,7 @@ declare function createUiRouter(options: UiRouterOptions): Hono;
|
|
|
137
136
|
|
|
138
137
|
declare function buildConfigView(config: Config): ConfigView;
|
|
139
138
|
declare function buildConfigMeta(config: Config): ConfigMetaView;
|
|
140
|
-
declare function buildConfigSchemaView(
|
|
139
|
+
declare function buildConfigSchemaView(_config: Config): ConfigSchemaResponse;
|
|
141
140
|
declare function loadConfigOrDefault(configPath: string): Config;
|
|
142
141
|
declare function updateModel(configPath: string, model: string): ConfigView;
|
|
143
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
|
-
|
|
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:
|
|
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:
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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(
|
|
88
|
-
|
|
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
|
-
|
|
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
|
+
"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.
|
|
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",
|