@nextclaw/server 0.3.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.
- package/dist/index.d.ts +145 -0
- package/dist/index.js +323 -0
- package/package.json +42 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { Hono } from 'hono';
|
|
2
|
+
import { Config } from '@nextclaw/core';
|
|
3
|
+
|
|
4
|
+
type ApiError = {
|
|
5
|
+
code: string;
|
|
6
|
+
message: string;
|
|
7
|
+
details?: Record<string, unknown>;
|
|
8
|
+
};
|
|
9
|
+
type ApiResponse<T> = {
|
|
10
|
+
ok: true;
|
|
11
|
+
data: T;
|
|
12
|
+
} | {
|
|
13
|
+
ok: false;
|
|
14
|
+
error: ApiError;
|
|
15
|
+
};
|
|
16
|
+
type ProviderConfigView = {
|
|
17
|
+
apiKeySet: boolean;
|
|
18
|
+
apiKeyMasked?: string;
|
|
19
|
+
apiBase?: string | null;
|
|
20
|
+
extraHeaders?: Record<string, string> | null;
|
|
21
|
+
wireApi?: "auto" | "chat" | "responses" | null;
|
|
22
|
+
};
|
|
23
|
+
type ProviderConfigUpdate = {
|
|
24
|
+
apiKey?: string | null;
|
|
25
|
+
apiBase?: string | null;
|
|
26
|
+
extraHeaders?: Record<string, string> | null;
|
|
27
|
+
wireApi?: "auto" | "chat" | "responses" | null;
|
|
28
|
+
};
|
|
29
|
+
type ConfigView = {
|
|
30
|
+
agents: {
|
|
31
|
+
defaults: {
|
|
32
|
+
model: string;
|
|
33
|
+
workspace?: string;
|
|
34
|
+
maxTokens?: number;
|
|
35
|
+
temperature?: number;
|
|
36
|
+
maxToolIterations?: number;
|
|
37
|
+
};
|
|
38
|
+
context?: {
|
|
39
|
+
bootstrap?: {
|
|
40
|
+
files?: string[];
|
|
41
|
+
minimalFiles?: string[];
|
|
42
|
+
heartbeatFiles?: string[];
|
|
43
|
+
perFileChars?: number;
|
|
44
|
+
totalChars?: number;
|
|
45
|
+
};
|
|
46
|
+
memory?: {
|
|
47
|
+
enabled?: boolean;
|
|
48
|
+
maxChars?: number;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
providers: Record<string, ProviderConfigView>;
|
|
53
|
+
channels: Record<string, Record<string, unknown>>;
|
|
54
|
+
tools?: Record<string, unknown>;
|
|
55
|
+
gateway?: Record<string, unknown>;
|
|
56
|
+
ui?: Record<string, unknown>;
|
|
57
|
+
plugins?: Record<string, unknown>;
|
|
58
|
+
};
|
|
59
|
+
type ProviderSpecView = {
|
|
60
|
+
name: string;
|
|
61
|
+
displayName?: string;
|
|
62
|
+
keywords: string[];
|
|
63
|
+
envKey: string;
|
|
64
|
+
isGateway?: boolean;
|
|
65
|
+
isLocal?: boolean;
|
|
66
|
+
defaultApiBase?: string;
|
|
67
|
+
supportsWireApi?: boolean;
|
|
68
|
+
wireApiOptions?: Array<"auto" | "chat" | "responses">;
|
|
69
|
+
defaultWireApi?: "auto" | "chat" | "responses";
|
|
70
|
+
};
|
|
71
|
+
type ChannelSpecView = {
|
|
72
|
+
name: string;
|
|
73
|
+
displayName?: string;
|
|
74
|
+
enabled: boolean;
|
|
75
|
+
tutorialUrl?: string;
|
|
76
|
+
};
|
|
77
|
+
type ConfigMetaView = {
|
|
78
|
+
providers: ProviderSpecView[];
|
|
79
|
+
channels: ChannelSpecView[];
|
|
80
|
+
};
|
|
81
|
+
type ConfigUiHint = {
|
|
82
|
+
label?: string;
|
|
83
|
+
help?: string;
|
|
84
|
+
group?: string;
|
|
85
|
+
order?: number;
|
|
86
|
+
advanced?: boolean;
|
|
87
|
+
sensitive?: boolean;
|
|
88
|
+
placeholder?: string;
|
|
89
|
+
};
|
|
90
|
+
type ConfigUiHints = Record<string, ConfigUiHint>;
|
|
91
|
+
type ConfigSchemaResponse = {
|
|
92
|
+
schema: Record<string, unknown>;
|
|
93
|
+
uiHints: ConfigUiHints;
|
|
94
|
+
version: string;
|
|
95
|
+
generatedAt: string;
|
|
96
|
+
};
|
|
97
|
+
type UiServerEvent = {
|
|
98
|
+
type: "config.updated";
|
|
99
|
+
payload: {
|
|
100
|
+
path: string;
|
|
101
|
+
};
|
|
102
|
+
} | {
|
|
103
|
+
type: "config.reload.started";
|
|
104
|
+
payload?: Record<string, unknown>;
|
|
105
|
+
} | {
|
|
106
|
+
type: "config.reload.finished";
|
|
107
|
+
payload?: Record<string, unknown>;
|
|
108
|
+
} | {
|
|
109
|
+
type: "error";
|
|
110
|
+
payload: {
|
|
111
|
+
message: string;
|
|
112
|
+
code?: string;
|
|
113
|
+
};
|
|
114
|
+
};
|
|
115
|
+
type UiServerOptions = {
|
|
116
|
+
host: string;
|
|
117
|
+
port: number;
|
|
118
|
+
configPath: string;
|
|
119
|
+
corsOrigins?: string[] | "*";
|
|
120
|
+
staticDir?: string;
|
|
121
|
+
};
|
|
122
|
+
type UiServerHandle = {
|
|
123
|
+
host: string;
|
|
124
|
+
port: number;
|
|
125
|
+
close: () => Promise<void>;
|
|
126
|
+
publish: (event: UiServerEvent) => void;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
declare function startUiServer(options: UiServerOptions): UiServerHandle;
|
|
130
|
+
|
|
131
|
+
type UiRouterOptions = {
|
|
132
|
+
configPath: string;
|
|
133
|
+
publish: (event: UiServerEvent) => void;
|
|
134
|
+
};
|
|
135
|
+
declare function createUiRouter(options: UiRouterOptions): Hono;
|
|
136
|
+
|
|
137
|
+
declare function buildConfigView(config: Config): ConfigView;
|
|
138
|
+
declare function buildConfigMeta(config: Config): ConfigMetaView;
|
|
139
|
+
declare function buildConfigSchemaView(config: Config): ConfigSchemaResponse;
|
|
140
|
+
declare function loadConfigOrDefault(configPath: string): Config;
|
|
141
|
+
declare function updateModel(configPath: string, model: string): ConfigView;
|
|
142
|
+
declare function updateProvider(configPath: string, providerName: string, patch: ProviderConfigUpdate): ProviderConfigView | null;
|
|
143
|
+
declare function updateChannel(configPath: string, channelName: string, patch: Record<string, unknown>): Record<string, unknown> | null;
|
|
144
|
+
|
|
145
|
+
export { type ApiError, type ApiResponse, type ChannelSpecView, type ConfigMetaView, type ConfigSchemaResponse, type ConfigUiHint, type ConfigUiHints, type ConfigView, type ProviderConfigUpdate, type ProviderConfigView, type ProviderSpecView, type UiServerEvent, type UiServerHandle, type UiServerOptions, buildConfigMeta, buildConfigSchemaView, buildConfigView, createUiRouter, loadConfigOrDefault, startUiServer, updateChannel, updateModel, updateProvider };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
// src/ui/server.ts
|
|
2
|
+
import { Hono as Hono2 } from "hono";
|
|
3
|
+
import { cors } from "hono/cors";
|
|
4
|
+
import { serve } from "@hono/node-server";
|
|
5
|
+
import { WebSocketServer, WebSocket } from "ws";
|
|
6
|
+
import { existsSync, readFileSync } from "fs";
|
|
7
|
+
import { readFile, stat } from "fs/promises";
|
|
8
|
+
import { join } from "path";
|
|
9
|
+
|
|
10
|
+
// src/ui/router.ts
|
|
11
|
+
import { Hono } from "hono";
|
|
12
|
+
|
|
13
|
+
// src/ui/config.ts
|
|
14
|
+
import {
|
|
15
|
+
loadConfig,
|
|
16
|
+
saveConfig,
|
|
17
|
+
ConfigSchema,
|
|
18
|
+
PROVIDERS,
|
|
19
|
+
buildConfigSchema,
|
|
20
|
+
findProviderByName,
|
|
21
|
+
getPackageVersion,
|
|
22
|
+
getWorkspacePathFromConfig
|
|
23
|
+
} from "@nextclaw/core";
|
|
24
|
+
import { loadPluginUiMetadata } from "@nextclaw/openclaw-compat";
|
|
25
|
+
var MASK_MIN_LENGTH = 8;
|
|
26
|
+
function maskApiKey(value) {
|
|
27
|
+
if (!value) {
|
|
28
|
+
return { apiKeySet: false };
|
|
29
|
+
}
|
|
30
|
+
if (value.length < MASK_MIN_LENGTH) {
|
|
31
|
+
return { apiKeySet: true, apiKeyMasked: "****" };
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
apiKeySet: true,
|
|
35
|
+
apiKeyMasked: `${value.slice(0, 2)}****${value.slice(-4)}`
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function toProviderView(provider, spec) {
|
|
39
|
+
const masked = maskApiKey(provider.apiKey);
|
|
40
|
+
const view = {
|
|
41
|
+
apiKeySet: masked.apiKeySet,
|
|
42
|
+
apiKeyMasked: masked.apiKeyMasked,
|
|
43
|
+
apiBase: provider.apiBase ?? null,
|
|
44
|
+
extraHeaders: provider.extraHeaders ?? null
|
|
45
|
+
};
|
|
46
|
+
if (spec?.supportsWireApi) {
|
|
47
|
+
view.wireApi = provider.wireApi ?? spec.defaultWireApi ?? "auto";
|
|
48
|
+
}
|
|
49
|
+
return view;
|
|
50
|
+
}
|
|
51
|
+
function buildConfigView(config) {
|
|
52
|
+
const providers = {};
|
|
53
|
+
for (const [name, provider] of Object.entries(config.providers)) {
|
|
54
|
+
const spec = findProviderByName(name);
|
|
55
|
+
providers[name] = toProviderView(provider, spec);
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
agents: config.agents,
|
|
59
|
+
providers,
|
|
60
|
+
channels: config.channels,
|
|
61
|
+
tools: config.tools,
|
|
62
|
+
gateway: config.gateway,
|
|
63
|
+
ui: config.ui,
|
|
64
|
+
plugins: config.plugins
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function buildConfigMeta(config) {
|
|
68
|
+
const providers = PROVIDERS.map((spec) => ({
|
|
69
|
+
name: spec.name,
|
|
70
|
+
displayName: spec.displayName,
|
|
71
|
+
keywords: spec.keywords,
|
|
72
|
+
envKey: spec.envKey,
|
|
73
|
+
isGateway: spec.isGateway,
|
|
74
|
+
isLocal: spec.isLocal,
|
|
75
|
+
defaultApiBase: spec.defaultApiBase,
|
|
76
|
+
supportsWireApi: spec.supportsWireApi,
|
|
77
|
+
wireApiOptions: spec.wireApiOptions,
|
|
78
|
+
defaultWireApi: spec.defaultWireApi
|
|
79
|
+
}));
|
|
80
|
+
const channels = Object.keys(config.channels).map((name) => ({
|
|
81
|
+
name,
|
|
82
|
+
displayName: name,
|
|
83
|
+
enabled: Boolean(config.channels[name]?.enabled)
|
|
84
|
+
}));
|
|
85
|
+
return { providers, channels };
|
|
86
|
+
}
|
|
87
|
+
function buildConfigSchemaView(config) {
|
|
88
|
+
const workspaceDir = getWorkspacePathFromConfig(config);
|
|
89
|
+
const plugins = loadPluginUiMetadata({ config, workspaceDir });
|
|
90
|
+
return buildConfigSchema({ version: getPackageVersion(), plugins });
|
|
91
|
+
}
|
|
92
|
+
function loadConfigOrDefault(configPath) {
|
|
93
|
+
return loadConfig(configPath);
|
|
94
|
+
}
|
|
95
|
+
function updateModel(configPath, model) {
|
|
96
|
+
const config = loadConfigOrDefault(configPath);
|
|
97
|
+
config.agents.defaults.model = model;
|
|
98
|
+
const next = ConfigSchema.parse(config);
|
|
99
|
+
saveConfig(next, configPath);
|
|
100
|
+
return buildConfigView(next);
|
|
101
|
+
}
|
|
102
|
+
function updateProvider(configPath, providerName, patch) {
|
|
103
|
+
const config = loadConfigOrDefault(configPath);
|
|
104
|
+
const provider = config.providers[providerName];
|
|
105
|
+
if (!provider) {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
const spec = findProviderByName(providerName);
|
|
109
|
+
if (Object.prototype.hasOwnProperty.call(patch, "apiKey")) {
|
|
110
|
+
provider.apiKey = patch.apiKey ?? "";
|
|
111
|
+
}
|
|
112
|
+
if (Object.prototype.hasOwnProperty.call(patch, "apiBase")) {
|
|
113
|
+
provider.apiBase = patch.apiBase ?? null;
|
|
114
|
+
}
|
|
115
|
+
if (Object.prototype.hasOwnProperty.call(patch, "extraHeaders")) {
|
|
116
|
+
provider.extraHeaders = patch.extraHeaders ?? null;
|
|
117
|
+
}
|
|
118
|
+
if (Object.prototype.hasOwnProperty.call(patch, "wireApi") && spec?.supportsWireApi) {
|
|
119
|
+
provider.wireApi = patch.wireApi ?? spec.defaultWireApi ?? "auto";
|
|
120
|
+
}
|
|
121
|
+
const next = ConfigSchema.parse(config);
|
|
122
|
+
saveConfig(next, configPath);
|
|
123
|
+
const updated = next.providers[providerName];
|
|
124
|
+
return toProviderView(updated, spec ?? void 0);
|
|
125
|
+
}
|
|
126
|
+
function updateChannel(configPath, channelName, patch) {
|
|
127
|
+
const config = loadConfigOrDefault(configPath);
|
|
128
|
+
const channel = config.channels[channelName];
|
|
129
|
+
if (!channel) {
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
config.channels[channelName] = { ...channel, ...patch };
|
|
133
|
+
const next = ConfigSchema.parse(config);
|
|
134
|
+
saveConfig(next, configPath);
|
|
135
|
+
return next.channels[channelName];
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// src/ui/router.ts
|
|
139
|
+
import { probeFeishu } from "@nextclaw/core";
|
|
140
|
+
function ok(data) {
|
|
141
|
+
return { ok: true, data };
|
|
142
|
+
}
|
|
143
|
+
function err(code, message, details) {
|
|
144
|
+
return { ok: false, error: { code, message, details } };
|
|
145
|
+
}
|
|
146
|
+
async function readJson(req) {
|
|
147
|
+
try {
|
|
148
|
+
const data = await req.json();
|
|
149
|
+
return { ok: true, data };
|
|
150
|
+
} catch {
|
|
151
|
+
return { ok: false };
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
function createUiRouter(options) {
|
|
155
|
+
const app = new Hono();
|
|
156
|
+
app.notFound((c) => c.json(err("NOT_FOUND", "endpoint not found"), 404));
|
|
157
|
+
app.get("/api/health", (c) => c.json(ok({ status: "ok" })));
|
|
158
|
+
app.get("/api/config", (c) => {
|
|
159
|
+
const config = loadConfigOrDefault(options.configPath);
|
|
160
|
+
return c.json(ok(buildConfigView(config)));
|
|
161
|
+
});
|
|
162
|
+
app.get("/api/config/meta", (c) => {
|
|
163
|
+
const config = loadConfigOrDefault(options.configPath);
|
|
164
|
+
return c.json(ok(buildConfigMeta(config)));
|
|
165
|
+
});
|
|
166
|
+
app.get("/api/config/schema", (c) => {
|
|
167
|
+
const config = loadConfigOrDefault(options.configPath);
|
|
168
|
+
return c.json(ok(buildConfigSchemaView(config)));
|
|
169
|
+
});
|
|
170
|
+
app.put("/api/config/model", async (c) => {
|
|
171
|
+
const body = await readJson(c.req.raw);
|
|
172
|
+
if (!body.ok || !body.data.model) {
|
|
173
|
+
return c.json(err("INVALID_BODY", "model is required"), 400);
|
|
174
|
+
}
|
|
175
|
+
const view = updateModel(options.configPath, body.data.model);
|
|
176
|
+
options.publish({ type: "config.updated", payload: { path: "agents.defaults.model" } });
|
|
177
|
+
return c.json(ok({ model: view.agents.defaults.model }));
|
|
178
|
+
});
|
|
179
|
+
app.put("/api/config/providers/:provider", async (c) => {
|
|
180
|
+
const provider = c.req.param("provider");
|
|
181
|
+
const body = await readJson(c.req.raw);
|
|
182
|
+
if (!body.ok) {
|
|
183
|
+
return c.json(err("INVALID_BODY", "invalid json body"), 400);
|
|
184
|
+
}
|
|
185
|
+
const result = updateProvider(options.configPath, provider, body.data);
|
|
186
|
+
if (!result) {
|
|
187
|
+
return c.json(err("NOT_FOUND", `unknown provider: ${provider}`), 404);
|
|
188
|
+
}
|
|
189
|
+
options.publish({ type: "config.updated", payload: { path: `providers.${provider}` } });
|
|
190
|
+
return c.json(ok(result));
|
|
191
|
+
});
|
|
192
|
+
app.put("/api/config/channels/:channel", async (c) => {
|
|
193
|
+
const channel = c.req.param("channel");
|
|
194
|
+
const body = await readJson(c.req.raw);
|
|
195
|
+
if (!body.ok) {
|
|
196
|
+
return c.json(err("INVALID_BODY", "invalid json body"), 400);
|
|
197
|
+
}
|
|
198
|
+
const result = updateChannel(options.configPath, channel, body.data);
|
|
199
|
+
if (!result) {
|
|
200
|
+
return c.json(err("NOT_FOUND", `unknown channel: ${channel}`), 404);
|
|
201
|
+
}
|
|
202
|
+
options.publish({ type: "config.updated", payload: { path: `channels.${channel}` } });
|
|
203
|
+
return c.json(ok(result));
|
|
204
|
+
});
|
|
205
|
+
app.post("/api/channels/feishu/probe", async (c) => {
|
|
206
|
+
const config = loadConfigOrDefault(options.configPath);
|
|
207
|
+
const feishu = config.channels.feishu;
|
|
208
|
+
if (!feishu?.appId || !feishu?.appSecret) {
|
|
209
|
+
return c.json(err("MISSING_CREDENTIALS", "Feishu appId/appSecret not configured"), 400);
|
|
210
|
+
}
|
|
211
|
+
const result = await probeFeishu(String(feishu.appId), String(feishu.appSecret));
|
|
212
|
+
if (!result.ok) {
|
|
213
|
+
return c.json(err("PROBE_FAILED", result.error), 400);
|
|
214
|
+
}
|
|
215
|
+
return c.json(
|
|
216
|
+
ok({
|
|
217
|
+
appId: result.appId,
|
|
218
|
+
botName: result.botName ?? null,
|
|
219
|
+
botOpenId: result.botOpenId ?? null
|
|
220
|
+
})
|
|
221
|
+
);
|
|
222
|
+
});
|
|
223
|
+
return app;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// src/ui/server.ts
|
|
227
|
+
import { serveStatic } from "hono/serve-static";
|
|
228
|
+
var DEFAULT_CORS_ORIGINS = (origin) => {
|
|
229
|
+
if (!origin) {
|
|
230
|
+
return void 0;
|
|
231
|
+
}
|
|
232
|
+
if (origin.startsWith("http://localhost:") || origin.startsWith("http://127.0.0.1:")) {
|
|
233
|
+
return origin;
|
|
234
|
+
}
|
|
235
|
+
return void 0;
|
|
236
|
+
};
|
|
237
|
+
function startUiServer(options) {
|
|
238
|
+
const app = new Hono2();
|
|
239
|
+
const origin = options.corsOrigins ?? DEFAULT_CORS_ORIGINS;
|
|
240
|
+
app.use("/api/*", cors({ origin }));
|
|
241
|
+
const clients = /* @__PURE__ */ new Set();
|
|
242
|
+
const publish = (event) => {
|
|
243
|
+
const payload = JSON.stringify(event);
|
|
244
|
+
for (const client of clients) {
|
|
245
|
+
if (client.readyState === WebSocket.OPEN) {
|
|
246
|
+
client.send(payload);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
app.route(
|
|
251
|
+
"/",
|
|
252
|
+
createUiRouter({
|
|
253
|
+
configPath: options.configPath,
|
|
254
|
+
publish
|
|
255
|
+
})
|
|
256
|
+
);
|
|
257
|
+
const staticDir = options.staticDir;
|
|
258
|
+
if (staticDir && existsSync(join(staticDir, "index.html"))) {
|
|
259
|
+
const indexHtml = readFileSync(join(staticDir, "index.html"), "utf-8");
|
|
260
|
+
app.use(
|
|
261
|
+
"/*",
|
|
262
|
+
serveStatic({
|
|
263
|
+
root: staticDir,
|
|
264
|
+
join,
|
|
265
|
+
getContent: async (path) => {
|
|
266
|
+
try {
|
|
267
|
+
return await readFile(path);
|
|
268
|
+
} catch {
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
isDir: async (path) => {
|
|
273
|
+
try {
|
|
274
|
+
return (await stat(path)).isDirectory();
|
|
275
|
+
} catch {
|
|
276
|
+
return false;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
})
|
|
280
|
+
);
|
|
281
|
+
app.get("*", (c) => {
|
|
282
|
+
const path = c.req.path;
|
|
283
|
+
if (path.startsWith("/api") || path.startsWith("/ws")) {
|
|
284
|
+
return c.notFound();
|
|
285
|
+
}
|
|
286
|
+
return c.html(indexHtml);
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
const server = serve({
|
|
290
|
+
fetch: app.fetch,
|
|
291
|
+
port: options.port,
|
|
292
|
+
hostname: options.host
|
|
293
|
+
});
|
|
294
|
+
const wss = new WebSocketServer({
|
|
295
|
+
server,
|
|
296
|
+
path: "/ws"
|
|
297
|
+
});
|
|
298
|
+
wss.on("connection", (socket) => {
|
|
299
|
+
clients.add(socket);
|
|
300
|
+
socket.on("close", () => clients.delete(socket));
|
|
301
|
+
});
|
|
302
|
+
return {
|
|
303
|
+
host: options.host,
|
|
304
|
+
port: options.port,
|
|
305
|
+
publish,
|
|
306
|
+
close: () => new Promise((resolve) => {
|
|
307
|
+
wss.close(() => {
|
|
308
|
+
server.close(() => resolve());
|
|
309
|
+
});
|
|
310
|
+
})
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
export {
|
|
314
|
+
buildConfigMeta,
|
|
315
|
+
buildConfigSchemaView,
|
|
316
|
+
buildConfigView,
|
|
317
|
+
createUiRouter,
|
|
318
|
+
loadConfigOrDefault,
|
|
319
|
+
startUiServer,
|
|
320
|
+
updateChannel,
|
|
321
|
+
updateModel,
|
|
322
|
+
updateProvider
|
|
323
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nextclaw/server",
|
|
3
|
+
"version": "0.3.4",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "Nextclaw UI/API server.",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"default": "./dist/index.js"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist"
|
|
15
|
+
],
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@hono/node-server": "^1.13.3",
|
|
18
|
+
"hono": "^4.6.2",
|
|
19
|
+
"ws": "^8.18.0",
|
|
20
|
+
"@nextclaw/core": "^0.4.8",
|
|
21
|
+
"@nextclaw/openclaw-compat": "^0.1.1"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@types/node": "^20.17.6",
|
|
25
|
+
"@types/ws": "^8.5.14",
|
|
26
|
+
"@typescript-eslint/eslint-plugin": "^7.18.0",
|
|
27
|
+
"@typescript-eslint/parser": "^7.18.0",
|
|
28
|
+
"eslint": "^8.57.1",
|
|
29
|
+
"eslint-config-prettier": "^9.1.0",
|
|
30
|
+
"prettier": "^3.3.3",
|
|
31
|
+
"tsup": "^8.3.5",
|
|
32
|
+
"tsx": "^4.19.2",
|
|
33
|
+
"typescript": "^5.6.3",
|
|
34
|
+
"vitest": "^2.1.2"
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "tsup src/index.ts --format esm --dts --out-dir dist",
|
|
38
|
+
"lint": "eslint .",
|
|
39
|
+
"tsc": "tsc -p tsconfig.json",
|
|
40
|
+
"test": "vitest"
|
|
41
|
+
}
|
|
42
|
+
}
|