@nextclaw/server 0.4.15 → 0.4.17
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 +95 -1
- package/dist/index.js +257 -8
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -214,6 +214,98 @@ type ConfigActionExecuteResult = {
|
|
|
214
214
|
patch?: Record<string, unknown>;
|
|
215
215
|
nextActions?: string[];
|
|
216
216
|
};
|
|
217
|
+
type MarketplaceItemType = "plugin" | "skill";
|
|
218
|
+
type MarketplaceSort = "relevance" | "updated" | "downloads";
|
|
219
|
+
type MarketplaceInstallKind = "npm" | "clawhub" | "git";
|
|
220
|
+
type MarketplaceInstallSpec = {
|
|
221
|
+
kind: MarketplaceInstallKind;
|
|
222
|
+
spec: string;
|
|
223
|
+
command: string;
|
|
224
|
+
};
|
|
225
|
+
type MarketplaceItemMetrics = {
|
|
226
|
+
downloads30d?: number;
|
|
227
|
+
stars?: number;
|
|
228
|
+
};
|
|
229
|
+
type MarketplaceItemSummary = {
|
|
230
|
+
id: string;
|
|
231
|
+
slug: string;
|
|
232
|
+
type: MarketplaceItemType;
|
|
233
|
+
name: string;
|
|
234
|
+
summary: string;
|
|
235
|
+
tags: string[];
|
|
236
|
+
author: string;
|
|
237
|
+
install: MarketplaceInstallSpec;
|
|
238
|
+
metrics?: MarketplaceItemMetrics;
|
|
239
|
+
updatedAt: string;
|
|
240
|
+
};
|
|
241
|
+
type MarketplaceItemView = MarketplaceItemSummary & {
|
|
242
|
+
description?: string;
|
|
243
|
+
sourceRepo?: string;
|
|
244
|
+
homepage?: string;
|
|
245
|
+
publishedAt: string;
|
|
246
|
+
};
|
|
247
|
+
type MarketplaceListView = {
|
|
248
|
+
total: number;
|
|
249
|
+
page: number;
|
|
250
|
+
pageSize: number;
|
|
251
|
+
totalPages: number;
|
|
252
|
+
sort: MarketplaceSort;
|
|
253
|
+
query?: string;
|
|
254
|
+
items: MarketplaceItemSummary[];
|
|
255
|
+
};
|
|
256
|
+
type MarketplaceRecommendationView = {
|
|
257
|
+
sceneId: string;
|
|
258
|
+
title: string;
|
|
259
|
+
description?: string;
|
|
260
|
+
total: number;
|
|
261
|
+
items: MarketplaceItemSummary[];
|
|
262
|
+
};
|
|
263
|
+
type MarketplaceInstalledRecord = {
|
|
264
|
+
type: MarketplaceItemType;
|
|
265
|
+
spec: string;
|
|
266
|
+
label?: string;
|
|
267
|
+
source?: string;
|
|
268
|
+
installedAt?: string;
|
|
269
|
+
};
|
|
270
|
+
type MarketplaceInstalledView = {
|
|
271
|
+
total: number;
|
|
272
|
+
pluginSpecs: string[];
|
|
273
|
+
skillSpecs: string[];
|
|
274
|
+
records: MarketplaceInstalledRecord[];
|
|
275
|
+
};
|
|
276
|
+
type MarketplaceInstallRequest = {
|
|
277
|
+
type: MarketplaceItemType;
|
|
278
|
+
spec: string;
|
|
279
|
+
version?: string;
|
|
280
|
+
registry?: string;
|
|
281
|
+
force?: boolean;
|
|
282
|
+
};
|
|
283
|
+
type MarketplaceInstallResult = {
|
|
284
|
+
type: MarketplaceItemType;
|
|
285
|
+
spec: string;
|
|
286
|
+
message: string;
|
|
287
|
+
output?: string;
|
|
288
|
+
};
|
|
289
|
+
type MarketplaceInstallSkillParams = {
|
|
290
|
+
slug: string;
|
|
291
|
+
version?: string;
|
|
292
|
+
registry?: string;
|
|
293
|
+
force?: boolean;
|
|
294
|
+
};
|
|
295
|
+
type MarketplaceInstaller = {
|
|
296
|
+
installPlugin?: (spec: string) => Promise<{
|
|
297
|
+
message: string;
|
|
298
|
+
output?: string;
|
|
299
|
+
}>;
|
|
300
|
+
installSkill?: (params: MarketplaceInstallSkillParams) => Promise<{
|
|
301
|
+
message: string;
|
|
302
|
+
output?: string;
|
|
303
|
+
}>;
|
|
304
|
+
};
|
|
305
|
+
type MarketplaceApiConfig = {
|
|
306
|
+
apiBaseUrl?: string;
|
|
307
|
+
installer?: MarketplaceInstaller;
|
|
308
|
+
};
|
|
217
309
|
type UiServerEvent = {
|
|
218
310
|
type: "config.updated";
|
|
219
311
|
payload: {
|
|
@@ -238,6 +330,7 @@ type UiServerOptions = {
|
|
|
238
330
|
configPath: string;
|
|
239
331
|
corsOrigins?: string[] | "*";
|
|
240
332
|
staticDir?: string;
|
|
333
|
+
marketplace?: MarketplaceApiConfig;
|
|
241
334
|
};
|
|
242
335
|
type UiServerHandle = {
|
|
243
336
|
host: string;
|
|
@@ -251,6 +344,7 @@ declare function startUiServer(options: UiServerOptions): UiServerHandle;
|
|
|
251
344
|
type UiRouterOptions = {
|
|
252
345
|
configPath: string;
|
|
253
346
|
publish: (event: UiServerEvent) => void;
|
|
347
|
+
marketplace?: MarketplaceApiConfig;
|
|
254
348
|
};
|
|
255
349
|
declare function createUiRouter(options: UiRouterOptions): Hono;
|
|
256
350
|
|
|
@@ -284,4 +378,4 @@ declare function patchSession(configPath: string, key: string, patch: SessionPat
|
|
|
284
378
|
declare function deleteSession(configPath: string, key: string): boolean;
|
|
285
379
|
declare function updateRuntime(configPath: string, patch: RuntimeConfigUpdate): Pick<ConfigView, "agents" | "bindings" | "session">;
|
|
286
380
|
|
|
287
|
-
export { type AgentBindingView, type AgentProfileView, type ApiError, type ApiResponse, type BindingPeerView, type ChannelSpecView, type ConfigActionExecuteRequest, type ConfigActionExecuteResult, type ConfigActionManifest, type ConfigActionType, type ConfigMetaView, type ConfigSchemaResponse, type ConfigUiHint, type ConfigUiHints, type ConfigView, type ProviderConfigUpdate, type ProviderConfigView, type ProviderSpecView, type RuntimeConfigUpdate, type SessionConfigView, type SessionEntryView, type SessionHistoryView, type SessionMessageView, type SessionPatchUpdate, type SessionsListView, type UiServerEvent, type UiServerHandle, type UiServerOptions, buildConfigMeta, buildConfigSchemaView, buildConfigView, createUiRouter, deleteSession, executeConfigAction, getSessionHistory, listSessions, loadConfigOrDefault, patchSession, startUiServer, updateChannel, updateModel, updateProvider, updateRuntime };
|
|
381
|
+
export { type AgentBindingView, type AgentProfileView, type ApiError, type ApiResponse, type BindingPeerView, type ChannelSpecView, type ConfigActionExecuteRequest, type ConfigActionExecuteResult, type ConfigActionManifest, type ConfigActionType, type ConfigMetaView, type ConfigSchemaResponse, type ConfigUiHint, type ConfigUiHints, type ConfigView, type MarketplaceApiConfig, type MarketplaceInstallKind, type MarketplaceInstallRequest, type MarketplaceInstallResult, type MarketplaceInstallSkillParams, type MarketplaceInstallSpec, type MarketplaceInstalledRecord, type MarketplaceInstalledView, type MarketplaceInstaller, type MarketplaceItemMetrics, type MarketplaceItemSummary, type MarketplaceItemType, type MarketplaceItemView, type MarketplaceListView, type MarketplaceRecommendationView, type MarketplaceSort, type ProviderConfigUpdate, type ProviderConfigView, type ProviderSpecView, type RuntimeConfigUpdate, type SessionConfigView, type SessionEntryView, type SessionHistoryView, type SessionMessageView, type SessionPatchUpdate, type SessionsListView, type UiServerEvent, type UiServerHandle, type UiServerOptions, buildConfigMeta, buildConfigSchemaView, buildConfigView, createUiRouter, deleteSession, executeConfigAction, getSessionHistory, listSessions, loadConfigOrDefault, patchSession, startUiServer, updateChannel, updateModel, updateProvider, updateRuntime };
|
package/dist/index.js
CHANGED
|
@@ -3,12 +3,13 @@ import { Hono as Hono2 } from "hono";
|
|
|
3
3
|
import { cors } from "hono/cors";
|
|
4
4
|
import { serve } from "@hono/node-server";
|
|
5
5
|
import { WebSocketServer, WebSocket } from "ws";
|
|
6
|
-
import { existsSync, readFileSync } from "fs";
|
|
6
|
+
import { existsSync as existsSync2, readFileSync } from "fs";
|
|
7
7
|
import { readFile, stat } from "fs/promises";
|
|
8
|
-
import { join } from "path";
|
|
8
|
+
import { join as join2 } from "path";
|
|
9
9
|
|
|
10
10
|
// src/ui/router.ts
|
|
11
11
|
import { Hono } from "hono";
|
|
12
|
+
import { expandHome } from "@nextclaw/core";
|
|
12
13
|
|
|
13
14
|
// src/ui/config.ts
|
|
14
15
|
import {
|
|
@@ -568,6 +569,9 @@ function updateRuntime(configPath, patch) {
|
|
|
568
569
|
}
|
|
569
570
|
|
|
570
571
|
// src/ui/router.ts
|
|
572
|
+
import { existsSync, readdirSync } from "fs";
|
|
573
|
+
import { join, resolve } from "path";
|
|
574
|
+
var DEFAULT_MARKETPLACE_API_BASE = "https://nextclaw-marketplace-api.15353764479037.workers.dev";
|
|
571
575
|
function ok(data) {
|
|
572
576
|
return { ok: true, data };
|
|
573
577
|
}
|
|
@@ -582,8 +586,251 @@ async function readJson(req) {
|
|
|
582
586
|
return { ok: false };
|
|
583
587
|
}
|
|
584
588
|
}
|
|
589
|
+
function isRecord(value) {
|
|
590
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
591
|
+
}
|
|
592
|
+
function readErrorMessage(value, fallback) {
|
|
593
|
+
if (!isRecord(value)) {
|
|
594
|
+
return fallback;
|
|
595
|
+
}
|
|
596
|
+
const maybeError = value.error;
|
|
597
|
+
if (!isRecord(maybeError)) {
|
|
598
|
+
return fallback;
|
|
599
|
+
}
|
|
600
|
+
return typeof maybeError.message === "string" && maybeError.message.trim().length > 0 ? maybeError.message : fallback;
|
|
601
|
+
}
|
|
602
|
+
function normalizeMarketplaceBaseUrl(options) {
|
|
603
|
+
const fromOptions = options.marketplace?.apiBaseUrl?.trim();
|
|
604
|
+
const fromEnv = process.env.NEXTCLAW_MARKETPLACE_API_BASE?.trim();
|
|
605
|
+
const value = fromOptions || fromEnv || DEFAULT_MARKETPLACE_API_BASE;
|
|
606
|
+
return value.endsWith("/") ? value.slice(0, -1) : value;
|
|
607
|
+
}
|
|
608
|
+
function toMarketplaceUrl(baseUrl, path, query = {}) {
|
|
609
|
+
const url = new URL(path, `${baseUrl}/`);
|
|
610
|
+
for (const [key, value] of Object.entries(query)) {
|
|
611
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
612
|
+
url.searchParams.set(key, value);
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
return url.toString();
|
|
616
|
+
}
|
|
617
|
+
async function fetchMarketplaceData(params) {
|
|
618
|
+
const url = toMarketplaceUrl(params.baseUrl, params.path, params.query ?? {});
|
|
619
|
+
try {
|
|
620
|
+
const response = await fetch(url, {
|
|
621
|
+
method: "GET",
|
|
622
|
+
headers: {
|
|
623
|
+
Accept: "application/json"
|
|
624
|
+
}
|
|
625
|
+
});
|
|
626
|
+
let payload = null;
|
|
627
|
+
try {
|
|
628
|
+
payload = await response.json();
|
|
629
|
+
} catch {
|
|
630
|
+
payload = null;
|
|
631
|
+
}
|
|
632
|
+
if (!response.ok) {
|
|
633
|
+
return {
|
|
634
|
+
ok: false,
|
|
635
|
+
status: response.status,
|
|
636
|
+
message: readErrorMessage(payload, `marketplace request failed: ${response.status}`)
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
if (!isRecord(payload) || payload.ok !== true || !Object.prototype.hasOwnProperty.call(payload, "data")) {
|
|
640
|
+
return {
|
|
641
|
+
ok: false,
|
|
642
|
+
status: 502,
|
|
643
|
+
message: "invalid marketplace response"
|
|
644
|
+
};
|
|
645
|
+
}
|
|
646
|
+
return {
|
|
647
|
+
ok: true,
|
|
648
|
+
data: payload.data
|
|
649
|
+
};
|
|
650
|
+
} catch (error) {
|
|
651
|
+
return {
|
|
652
|
+
ok: false,
|
|
653
|
+
status: 502,
|
|
654
|
+
message: `marketplace fetch failed: ${String(error)}`
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
function collectMarketplaceInstalledView(options) {
|
|
659
|
+
const config = loadConfigOrDefault(options.configPath);
|
|
660
|
+
const pluginRecordsMap = config.plugins.installs ?? {};
|
|
661
|
+
const pluginRecords = [];
|
|
662
|
+
const pluginSpecSet = /* @__PURE__ */ new Set();
|
|
663
|
+
for (const [pluginId, installRecord] of Object.entries(pluginRecordsMap)) {
|
|
664
|
+
const normalizedSpec = typeof installRecord.spec === "string" && installRecord.spec.trim().length > 0 ? installRecord.spec.trim() : pluginId;
|
|
665
|
+
pluginRecords.push({
|
|
666
|
+
type: "plugin",
|
|
667
|
+
spec: normalizedSpec,
|
|
668
|
+
label: pluginId,
|
|
669
|
+
source: installRecord.source,
|
|
670
|
+
installedAt: installRecord.installedAt
|
|
671
|
+
});
|
|
672
|
+
pluginSpecSet.add(normalizedSpec);
|
|
673
|
+
}
|
|
674
|
+
const pluginEntries = config.plugins.entries ?? {};
|
|
675
|
+
for (const pluginId of Object.keys(pluginEntries)) {
|
|
676
|
+
if (!pluginSpecSet.has(pluginId)) {
|
|
677
|
+
pluginRecords.push({
|
|
678
|
+
type: "plugin",
|
|
679
|
+
spec: pluginId,
|
|
680
|
+
label: pluginId,
|
|
681
|
+
source: "config"
|
|
682
|
+
});
|
|
683
|
+
pluginSpecSet.add(pluginId);
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
const workspacePath = resolve(expandHome(config.agents.defaults.workspace));
|
|
687
|
+
const skillsPath = join(workspacePath, "skills");
|
|
688
|
+
const skillSpecSet = /* @__PURE__ */ new Set();
|
|
689
|
+
const skillRecords = [];
|
|
690
|
+
if (existsSync(skillsPath)) {
|
|
691
|
+
const entries = readdirSync(skillsPath, { withFileTypes: true });
|
|
692
|
+
for (const entry of entries) {
|
|
693
|
+
if (!entry.isDirectory()) {
|
|
694
|
+
continue;
|
|
695
|
+
}
|
|
696
|
+
const skillSlug = entry.name;
|
|
697
|
+
const skillFile = join(skillsPath, skillSlug, "SKILL.md");
|
|
698
|
+
if (!existsSync(skillFile)) {
|
|
699
|
+
continue;
|
|
700
|
+
}
|
|
701
|
+
skillRecords.push({
|
|
702
|
+
type: "skill",
|
|
703
|
+
spec: skillSlug,
|
|
704
|
+
label: skillSlug,
|
|
705
|
+
source: "workspace"
|
|
706
|
+
});
|
|
707
|
+
skillSpecSet.add(skillSlug);
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
const records = [...pluginRecords, ...skillRecords].sort((left, right) => {
|
|
711
|
+
if (left.type !== right.type) {
|
|
712
|
+
return left.type.localeCompare(right.type);
|
|
713
|
+
}
|
|
714
|
+
return left.spec.localeCompare(right.spec);
|
|
715
|
+
});
|
|
716
|
+
return {
|
|
717
|
+
total: records.length,
|
|
718
|
+
pluginSpecs: Array.from(pluginSpecSet).sort((left, right) => left.localeCompare(right)),
|
|
719
|
+
skillSpecs: Array.from(skillSpecSet).sort((left, right) => left.localeCompare(right)),
|
|
720
|
+
records
|
|
721
|
+
};
|
|
722
|
+
}
|
|
723
|
+
async function installMarketplaceItem(params) {
|
|
724
|
+
const type = params.body.type;
|
|
725
|
+
const spec = typeof params.body.spec === "string" ? params.body.spec.trim() : "";
|
|
726
|
+
if (type !== "plugin" && type !== "skill" || !spec) {
|
|
727
|
+
throw new Error("INVALID_BODY:type and non-empty spec are required");
|
|
728
|
+
}
|
|
729
|
+
const installer = params.options.marketplace?.installer;
|
|
730
|
+
if (!installer) {
|
|
731
|
+
throw new Error("NOT_AVAILABLE:marketplace installer is not configured");
|
|
732
|
+
}
|
|
733
|
+
let result;
|
|
734
|
+
if (type === "plugin") {
|
|
735
|
+
if (!installer.installPlugin) {
|
|
736
|
+
throw new Error("NOT_AVAILABLE:plugin installer is not configured");
|
|
737
|
+
}
|
|
738
|
+
result = await installer.installPlugin(spec);
|
|
739
|
+
} else {
|
|
740
|
+
if (!installer.installSkill) {
|
|
741
|
+
throw new Error("NOT_AVAILABLE:skill installer is not configured");
|
|
742
|
+
}
|
|
743
|
+
result = await installer.installSkill({
|
|
744
|
+
slug: spec,
|
|
745
|
+
version: params.body.version,
|
|
746
|
+
registry: params.body.registry,
|
|
747
|
+
force: params.body.force
|
|
748
|
+
});
|
|
749
|
+
}
|
|
750
|
+
params.options.publish({ type: "config.updated", payload: { path: type === "plugin" ? "plugins" : "skills" } });
|
|
751
|
+
return {
|
|
752
|
+
type,
|
|
753
|
+
spec,
|
|
754
|
+
message: result.message,
|
|
755
|
+
output: result.output
|
|
756
|
+
};
|
|
757
|
+
}
|
|
758
|
+
function registerMarketplaceRoutes(app, options, marketplaceBaseUrl) {
|
|
759
|
+
app.get("/api/marketplace/installed", (c) => {
|
|
760
|
+
return c.json(ok(collectMarketplaceInstalledView(options)));
|
|
761
|
+
});
|
|
762
|
+
app.get("/api/marketplace/items", async (c) => {
|
|
763
|
+
const query = c.req.query();
|
|
764
|
+
const result = await fetchMarketplaceData({
|
|
765
|
+
baseUrl: marketplaceBaseUrl,
|
|
766
|
+
path: "/api/v1/items",
|
|
767
|
+
query: {
|
|
768
|
+
q: query.q,
|
|
769
|
+
type: query.type,
|
|
770
|
+
tag: query.tag,
|
|
771
|
+
sort: query.sort,
|
|
772
|
+
page: query.page,
|
|
773
|
+
pageSize: query.pageSize
|
|
774
|
+
}
|
|
775
|
+
});
|
|
776
|
+
if (!result.ok) {
|
|
777
|
+
return c.json(err("MARKETPLACE_UNAVAILABLE", result.message), result.status);
|
|
778
|
+
}
|
|
779
|
+
return c.json(ok(result.data));
|
|
780
|
+
});
|
|
781
|
+
app.get("/api/marketplace/items/:slug", async (c) => {
|
|
782
|
+
const slug = encodeURIComponent(c.req.param("slug"));
|
|
783
|
+
const type = c.req.query("type");
|
|
784
|
+
const result = await fetchMarketplaceData({
|
|
785
|
+
baseUrl: marketplaceBaseUrl,
|
|
786
|
+
path: `/api/v1/items/${slug}`,
|
|
787
|
+
query: {
|
|
788
|
+
type
|
|
789
|
+
}
|
|
790
|
+
});
|
|
791
|
+
if (!result.ok) {
|
|
792
|
+
return c.json(err("MARKETPLACE_UNAVAILABLE", result.message), result.status);
|
|
793
|
+
}
|
|
794
|
+
return c.json(ok(result.data));
|
|
795
|
+
});
|
|
796
|
+
app.get("/api/marketplace/recommendations", async (c) => {
|
|
797
|
+
const query = c.req.query();
|
|
798
|
+
const result = await fetchMarketplaceData({
|
|
799
|
+
baseUrl: marketplaceBaseUrl,
|
|
800
|
+
path: "/api/v1/recommendations",
|
|
801
|
+
query: {
|
|
802
|
+
scene: query.scene,
|
|
803
|
+
limit: query.limit
|
|
804
|
+
}
|
|
805
|
+
});
|
|
806
|
+
if (!result.ok) {
|
|
807
|
+
return c.json(err("MARKETPLACE_UNAVAILABLE", result.message), result.status);
|
|
808
|
+
}
|
|
809
|
+
return c.json(ok(result.data));
|
|
810
|
+
});
|
|
811
|
+
app.post("/api/marketplace/install", async (c) => {
|
|
812
|
+
const body = await readJson(c.req.raw);
|
|
813
|
+
if (!body.ok || !body.data || typeof body.data !== "object") {
|
|
814
|
+
return c.json(err("INVALID_BODY", "invalid json body"), 400);
|
|
815
|
+
}
|
|
816
|
+
try {
|
|
817
|
+
const payload = await installMarketplaceItem({ options, body: body.data });
|
|
818
|
+
return c.json(ok(payload));
|
|
819
|
+
} catch (error) {
|
|
820
|
+
const message = String(error);
|
|
821
|
+
if (message.startsWith("INVALID_BODY:")) {
|
|
822
|
+
return c.json(err("INVALID_BODY", message.slice("INVALID_BODY:".length)), 400);
|
|
823
|
+
}
|
|
824
|
+
if (message.startsWith("NOT_AVAILABLE:")) {
|
|
825
|
+
return c.json(err("NOT_AVAILABLE", message.slice("NOT_AVAILABLE:".length)), 503);
|
|
826
|
+
}
|
|
827
|
+
return c.json(err("INSTALL_FAILED", message), 400);
|
|
828
|
+
}
|
|
829
|
+
});
|
|
830
|
+
}
|
|
585
831
|
function createUiRouter(options) {
|
|
586
832
|
const app = new Hono();
|
|
833
|
+
const marketplaceBaseUrl = normalizeMarketplaceBaseUrl(options);
|
|
587
834
|
app.notFound((c) => c.json(err("NOT_FOUND", "endpoint not found"), 404));
|
|
588
835
|
app.get("/api/health", (c) => c.json(ok({ status: "ok" })));
|
|
589
836
|
app.get("/api/config", (c) => {
|
|
@@ -719,6 +966,7 @@ function createUiRouter(options) {
|
|
|
719
966
|
}
|
|
720
967
|
return c.json(ok(result.data));
|
|
721
968
|
});
|
|
969
|
+
registerMarketplaceRoutes(app, options, marketplaceBaseUrl);
|
|
722
970
|
return app;
|
|
723
971
|
}
|
|
724
972
|
|
|
@@ -750,17 +998,18 @@ function startUiServer(options) {
|
|
|
750
998
|
"/",
|
|
751
999
|
createUiRouter({
|
|
752
1000
|
configPath: options.configPath,
|
|
753
|
-
publish
|
|
1001
|
+
publish,
|
|
1002
|
+
marketplace: options.marketplace
|
|
754
1003
|
})
|
|
755
1004
|
);
|
|
756
1005
|
const staticDir = options.staticDir;
|
|
757
|
-
if (staticDir &&
|
|
758
|
-
const indexHtml = readFileSync(
|
|
1006
|
+
if (staticDir && existsSync2(join2(staticDir, "index.html"))) {
|
|
1007
|
+
const indexHtml = readFileSync(join2(staticDir, "index.html"), "utf-8");
|
|
759
1008
|
app.use(
|
|
760
1009
|
"/*",
|
|
761
1010
|
serveStatic({
|
|
762
1011
|
root: staticDir,
|
|
763
|
-
join,
|
|
1012
|
+
join: join2,
|
|
764
1013
|
getContent: async (path) => {
|
|
765
1014
|
try {
|
|
766
1015
|
return await readFile(path);
|
|
@@ -802,9 +1051,9 @@ function startUiServer(options) {
|
|
|
802
1051
|
host: options.host,
|
|
803
1052
|
port: options.port,
|
|
804
1053
|
publish,
|
|
805
|
-
close: () => new Promise((
|
|
1054
|
+
close: () => new Promise((resolve2) => {
|
|
806
1055
|
wss.close(() => {
|
|
807
|
-
server.close(() =>
|
|
1056
|
+
server.close(() => resolve2());
|
|
808
1057
|
});
|
|
809
1058
|
})
|
|
810
1059
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextclaw/server",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.17",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Nextclaw UI/API server.",
|
|
6
6
|
"type": "module",
|
|
@@ -17,7 +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.6.
|
|
20
|
+
"@nextclaw/core": "^0.6.27"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"@types/node": "^20.17.6",
|