@nextclaw/server 0.9.3 → 0.10.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 +296 -179
- package/dist/index.js +334 -28
- package/package.json +5 -4
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,284 @@ import { NcpHttpAgentStreamProvider } from '@nextclaw/ncp-http-agent-server';
|
|
|
5
5
|
import { Hono } from 'hono';
|
|
6
6
|
import { IncomingMessage } from 'node:http';
|
|
7
7
|
|
|
8
|
+
type MarketplaceItemType = "plugin" | "skill" | "mcp";
|
|
9
|
+
type MarketplaceSort = "relevance" | "updated";
|
|
10
|
+
type MarketplacePluginInstallKind = "npm";
|
|
11
|
+
type MarketplaceSkillInstallKind = "builtin" | "marketplace";
|
|
12
|
+
type MarketplaceMcpInstallKind = "template";
|
|
13
|
+
type MarketplaceInstallKind = MarketplacePluginInstallKind | MarketplaceSkillInstallKind | MarketplaceMcpInstallKind;
|
|
14
|
+
type MarketplaceInstallSpec = {
|
|
15
|
+
kind: MarketplaceInstallKind;
|
|
16
|
+
spec: string;
|
|
17
|
+
command: string;
|
|
18
|
+
};
|
|
19
|
+
type MarketplaceMcpTemplateInput = {
|
|
20
|
+
id: string;
|
|
21
|
+
label: string;
|
|
22
|
+
description?: string;
|
|
23
|
+
required?: boolean;
|
|
24
|
+
secret?: boolean;
|
|
25
|
+
defaultValue?: string;
|
|
26
|
+
};
|
|
27
|
+
type MarketplaceMcpInstallSpec = MarketplaceInstallSpec & {
|
|
28
|
+
kind: "template";
|
|
29
|
+
defaultName: string;
|
|
30
|
+
transportTypes: Array<"stdio" | "http" | "sse">;
|
|
31
|
+
template: Record<string, unknown>;
|
|
32
|
+
inputs: MarketplaceMcpTemplateInput[];
|
|
33
|
+
};
|
|
34
|
+
type MarketplaceLocalizedTextMap = Record<string, string>;
|
|
35
|
+
type MarketplaceItemSummary = {
|
|
36
|
+
id: string;
|
|
37
|
+
slug: string;
|
|
38
|
+
type: MarketplaceItemType;
|
|
39
|
+
name: string;
|
|
40
|
+
summary: string;
|
|
41
|
+
summaryI18n: MarketplaceLocalizedTextMap;
|
|
42
|
+
tags: string[];
|
|
43
|
+
author: string;
|
|
44
|
+
install: MarketplaceInstallSpec;
|
|
45
|
+
updatedAt: string;
|
|
46
|
+
};
|
|
47
|
+
type MarketplaceItemView = MarketplaceItemSummary & {
|
|
48
|
+
description?: string;
|
|
49
|
+
descriptionI18n?: MarketplaceLocalizedTextMap;
|
|
50
|
+
sourceRepo?: string;
|
|
51
|
+
homepage?: string;
|
|
52
|
+
publishedAt: string;
|
|
53
|
+
};
|
|
54
|
+
type MarketplaceSkillContentView = {
|
|
55
|
+
type: "skill";
|
|
56
|
+
slug: string;
|
|
57
|
+
name: string;
|
|
58
|
+
install: MarketplaceInstallSpec;
|
|
59
|
+
source: "builtin" | "marketplace" | "remote";
|
|
60
|
+
raw: string;
|
|
61
|
+
metadataRaw?: string;
|
|
62
|
+
bodyRaw: string;
|
|
63
|
+
sourceUrl?: string;
|
|
64
|
+
};
|
|
65
|
+
type MarketplacePluginContentView = {
|
|
66
|
+
type: "plugin";
|
|
67
|
+
slug: string;
|
|
68
|
+
name: string;
|
|
69
|
+
install: MarketplaceInstallSpec;
|
|
70
|
+
source: "npm" | "repo" | "remote";
|
|
71
|
+
raw?: string;
|
|
72
|
+
bodyRaw?: string;
|
|
73
|
+
metadataRaw?: string;
|
|
74
|
+
sourceUrl?: string;
|
|
75
|
+
};
|
|
76
|
+
type MarketplaceMcpContentView = {
|
|
77
|
+
type: "mcp";
|
|
78
|
+
slug: string;
|
|
79
|
+
name: string;
|
|
80
|
+
install: MarketplaceMcpInstallSpec;
|
|
81
|
+
source: "marketplace" | "remote";
|
|
82
|
+
raw: string;
|
|
83
|
+
metadataRaw?: string;
|
|
84
|
+
bodyRaw: string;
|
|
85
|
+
sourceUrl?: string;
|
|
86
|
+
};
|
|
87
|
+
type MarketplaceListView = {
|
|
88
|
+
total: number;
|
|
89
|
+
page: number;
|
|
90
|
+
pageSize: number;
|
|
91
|
+
totalPages: number;
|
|
92
|
+
sort: MarketplaceSort;
|
|
93
|
+
query?: string;
|
|
94
|
+
items: MarketplaceItemSummary[];
|
|
95
|
+
};
|
|
96
|
+
type MarketplaceRecommendationView = {
|
|
97
|
+
type: MarketplaceItemType;
|
|
98
|
+
sceneId: string;
|
|
99
|
+
title: string;
|
|
100
|
+
description?: string;
|
|
101
|
+
total: number;
|
|
102
|
+
items: MarketplaceItemSummary[];
|
|
103
|
+
};
|
|
104
|
+
type MarketplaceInstalledRecord = {
|
|
105
|
+
type: MarketplaceItemType;
|
|
106
|
+
id?: string;
|
|
107
|
+
spec: string;
|
|
108
|
+
label?: string;
|
|
109
|
+
description?: string;
|
|
110
|
+
descriptionZh?: string;
|
|
111
|
+
source?: string;
|
|
112
|
+
installedAt?: string;
|
|
113
|
+
enabled?: boolean;
|
|
114
|
+
runtimeStatus?: string;
|
|
115
|
+
origin?: string;
|
|
116
|
+
installPath?: string;
|
|
117
|
+
transport?: "stdio" | "http" | "sse";
|
|
118
|
+
scope?: {
|
|
119
|
+
allAgents: boolean;
|
|
120
|
+
agents: string[];
|
|
121
|
+
};
|
|
122
|
+
catalogSlug?: string;
|
|
123
|
+
vendor?: string;
|
|
124
|
+
docsUrl?: string;
|
|
125
|
+
homepage?: string;
|
|
126
|
+
trustLevel?: "official" | "verified" | "community";
|
|
127
|
+
toolCount?: number;
|
|
128
|
+
accessible?: boolean;
|
|
129
|
+
lastReadyAt?: string;
|
|
130
|
+
lastDoctorAt?: string;
|
|
131
|
+
lastError?: string;
|
|
132
|
+
};
|
|
133
|
+
type MarketplaceInstalledView = {
|
|
134
|
+
type: MarketplaceItemType;
|
|
135
|
+
total: number;
|
|
136
|
+
specs: string[];
|
|
137
|
+
records: MarketplaceInstalledRecord[];
|
|
138
|
+
};
|
|
139
|
+
type MarketplaceInstallSkillParams = {
|
|
140
|
+
slug: string;
|
|
141
|
+
kind?: MarketplaceSkillInstallKind;
|
|
142
|
+
skill?: string;
|
|
143
|
+
installPath?: string;
|
|
144
|
+
force?: boolean;
|
|
145
|
+
};
|
|
146
|
+
type MarketplacePluginInstallRequest = {
|
|
147
|
+
type?: "plugin";
|
|
148
|
+
spec: string;
|
|
149
|
+
};
|
|
150
|
+
type MarketplaceSkillInstallRequest = {
|
|
151
|
+
type?: "skill";
|
|
152
|
+
spec: string;
|
|
153
|
+
kind?: MarketplaceSkillInstallKind;
|
|
154
|
+
skill?: string;
|
|
155
|
+
installPath?: string;
|
|
156
|
+
force?: boolean;
|
|
157
|
+
};
|
|
158
|
+
type MarketplaceMcpInstallRequest = {
|
|
159
|
+
type?: "mcp";
|
|
160
|
+
spec: string;
|
|
161
|
+
name?: string;
|
|
162
|
+
enabled?: boolean;
|
|
163
|
+
allAgents?: boolean;
|
|
164
|
+
agents?: string[];
|
|
165
|
+
inputs?: Record<string, string>;
|
|
166
|
+
template?: MarketplaceMcpInstallSpec;
|
|
167
|
+
};
|
|
168
|
+
type MarketplacePluginInstallResult = {
|
|
169
|
+
type: "plugin";
|
|
170
|
+
spec: string;
|
|
171
|
+
message: string;
|
|
172
|
+
output?: string;
|
|
173
|
+
};
|
|
174
|
+
type MarketplaceSkillInstallResult = {
|
|
175
|
+
type: "skill";
|
|
176
|
+
spec: string;
|
|
177
|
+
message: string;
|
|
178
|
+
output?: string;
|
|
179
|
+
};
|
|
180
|
+
type MarketplaceMcpInstallResult = {
|
|
181
|
+
type: "mcp";
|
|
182
|
+
spec: string;
|
|
183
|
+
name: string;
|
|
184
|
+
message: string;
|
|
185
|
+
output?: string;
|
|
186
|
+
};
|
|
187
|
+
type MarketplacePluginManageAction = "enable" | "disable" | "uninstall";
|
|
188
|
+
type MarketplaceSkillManageAction = "uninstall";
|
|
189
|
+
type MarketplaceMcpManageAction = "enable" | "disable" | "remove";
|
|
190
|
+
type MarketplacePluginManageRequest = {
|
|
191
|
+
type?: "plugin";
|
|
192
|
+
action: MarketplacePluginManageAction;
|
|
193
|
+
id?: string;
|
|
194
|
+
spec?: string;
|
|
195
|
+
};
|
|
196
|
+
type MarketplaceSkillManageRequest = {
|
|
197
|
+
type?: "skill";
|
|
198
|
+
action: MarketplaceSkillManageAction;
|
|
199
|
+
id?: string;
|
|
200
|
+
spec?: string;
|
|
201
|
+
};
|
|
202
|
+
type MarketplaceMcpManageRequest = {
|
|
203
|
+
type?: "mcp";
|
|
204
|
+
action: MarketplaceMcpManageAction;
|
|
205
|
+
id?: string;
|
|
206
|
+
spec?: string;
|
|
207
|
+
};
|
|
208
|
+
type MarketplacePluginManageResult = {
|
|
209
|
+
type: "plugin";
|
|
210
|
+
action: MarketplacePluginManageAction;
|
|
211
|
+
id: string;
|
|
212
|
+
message: string;
|
|
213
|
+
output?: string;
|
|
214
|
+
};
|
|
215
|
+
type MarketplaceSkillManageResult = {
|
|
216
|
+
type: "skill";
|
|
217
|
+
action: MarketplaceSkillManageAction;
|
|
218
|
+
id: string;
|
|
219
|
+
message: string;
|
|
220
|
+
output?: string;
|
|
221
|
+
};
|
|
222
|
+
type MarketplaceMcpManageResult = {
|
|
223
|
+
type: "mcp";
|
|
224
|
+
action: MarketplaceMcpManageAction;
|
|
225
|
+
id: string;
|
|
226
|
+
message: string;
|
|
227
|
+
output?: string;
|
|
228
|
+
};
|
|
229
|
+
type MarketplaceMcpDoctorResult = {
|
|
230
|
+
name: string;
|
|
231
|
+
enabled: boolean;
|
|
232
|
+
transport: "stdio" | "http" | "sse";
|
|
233
|
+
accessible: boolean;
|
|
234
|
+
toolCount: number;
|
|
235
|
+
error?: string;
|
|
236
|
+
};
|
|
237
|
+
type MarketplaceInstaller = {
|
|
238
|
+
installPlugin?: (spec: string) => Promise<{
|
|
239
|
+
message: string;
|
|
240
|
+
output?: string;
|
|
241
|
+
}>;
|
|
242
|
+
installSkill?: (params: MarketplaceInstallSkillParams) => Promise<{
|
|
243
|
+
message: string;
|
|
244
|
+
output?: string;
|
|
245
|
+
}>;
|
|
246
|
+
enablePlugin?: (id: string) => Promise<{
|
|
247
|
+
message: string;
|
|
248
|
+
output?: string;
|
|
249
|
+
}>;
|
|
250
|
+
disablePlugin?: (id: string) => Promise<{
|
|
251
|
+
message: string;
|
|
252
|
+
output?: string;
|
|
253
|
+
}>;
|
|
254
|
+
uninstallPlugin?: (id: string) => Promise<{
|
|
255
|
+
message: string;
|
|
256
|
+
output?: string;
|
|
257
|
+
}>;
|
|
258
|
+
uninstallSkill?: (slug: string) => Promise<{
|
|
259
|
+
message: string;
|
|
260
|
+
output?: string;
|
|
261
|
+
}>;
|
|
262
|
+
installMcp?: (params: MarketplaceMcpInstallRequest) => Promise<{
|
|
263
|
+
name: string;
|
|
264
|
+
message: string;
|
|
265
|
+
output?: string;
|
|
266
|
+
}>;
|
|
267
|
+
enableMcp?: (name: string) => Promise<{
|
|
268
|
+
message: string;
|
|
269
|
+
output?: string;
|
|
270
|
+
}>;
|
|
271
|
+
disableMcp?: (name: string) => Promise<{
|
|
272
|
+
message: string;
|
|
273
|
+
output?: string;
|
|
274
|
+
}>;
|
|
275
|
+
removeMcp?: (name: string) => Promise<{
|
|
276
|
+
message: string;
|
|
277
|
+
output?: string;
|
|
278
|
+
}>;
|
|
279
|
+
doctorMcp?: (name: string) => Promise<MarketplaceMcpDoctorResult>;
|
|
280
|
+
};
|
|
281
|
+
type MarketplaceApiConfig = {
|
|
282
|
+
apiBaseUrl?: string;
|
|
283
|
+
installer?: MarketplaceInstaller;
|
|
284
|
+
};
|
|
285
|
+
|
|
8
286
|
type ApiError = {
|
|
9
287
|
code: string;
|
|
10
288
|
message: string;
|
|
@@ -190,6 +468,7 @@ type SessionEntryView = {
|
|
|
190
468
|
updatedAt: string;
|
|
191
469
|
label?: string;
|
|
192
470
|
preferredModel?: string;
|
|
471
|
+
preferredThinking?: ThinkingLevel | null;
|
|
193
472
|
sessionType: string;
|
|
194
473
|
sessionTypeMutable: boolean;
|
|
195
474
|
messageCount: number;
|
|
@@ -379,9 +658,20 @@ type ChatCapabilitiesView = {
|
|
|
379
658
|
stopSupported: boolean;
|
|
380
659
|
stopReason?: string;
|
|
381
660
|
};
|
|
661
|
+
type ChatSessionTypeCtaView = {
|
|
662
|
+
kind: string;
|
|
663
|
+
label?: string;
|
|
664
|
+
href?: string;
|
|
665
|
+
};
|
|
382
666
|
type ChatSessionTypeOptionView = {
|
|
383
667
|
value: string;
|
|
384
668
|
label: string;
|
|
669
|
+
ready?: boolean;
|
|
670
|
+
reason?: string | null;
|
|
671
|
+
reasonMessage?: string | null;
|
|
672
|
+
supportedModels?: string[];
|
|
673
|
+
recommendedModel?: string | null;
|
|
674
|
+
cta?: ChatSessionTypeCtaView | null;
|
|
385
675
|
};
|
|
386
676
|
type ChatSessionTypesView = {
|
|
387
677
|
defaultType: string;
|
|
@@ -634,184 +924,6 @@ type ConfigActionExecuteResult = {
|
|
|
634
924
|
patch?: Record<string, unknown>;
|
|
635
925
|
nextActions?: string[];
|
|
636
926
|
};
|
|
637
|
-
type MarketplaceItemType = "plugin" | "skill";
|
|
638
|
-
type MarketplaceSort = "relevance" | "updated";
|
|
639
|
-
type MarketplacePluginInstallKind = "npm";
|
|
640
|
-
type MarketplaceSkillInstallKind = "builtin" | "marketplace";
|
|
641
|
-
type MarketplaceInstallKind = MarketplacePluginInstallKind | MarketplaceSkillInstallKind;
|
|
642
|
-
type MarketplaceInstallSpec = {
|
|
643
|
-
kind: MarketplaceInstallKind;
|
|
644
|
-
spec: string;
|
|
645
|
-
command: string;
|
|
646
|
-
};
|
|
647
|
-
type MarketplaceLocalizedTextMap = Record<string, string>;
|
|
648
|
-
type MarketplaceItemSummary = {
|
|
649
|
-
id: string;
|
|
650
|
-
slug: string;
|
|
651
|
-
type: MarketplaceItemType;
|
|
652
|
-
name: string;
|
|
653
|
-
summary: string;
|
|
654
|
-
summaryI18n: MarketplaceLocalizedTextMap;
|
|
655
|
-
tags: string[];
|
|
656
|
-
author: string;
|
|
657
|
-
install: MarketplaceInstallSpec;
|
|
658
|
-
updatedAt: string;
|
|
659
|
-
};
|
|
660
|
-
type MarketplaceItemView = MarketplaceItemSummary & {
|
|
661
|
-
description?: string;
|
|
662
|
-
descriptionI18n?: MarketplaceLocalizedTextMap;
|
|
663
|
-
sourceRepo?: string;
|
|
664
|
-
homepage?: string;
|
|
665
|
-
publishedAt: string;
|
|
666
|
-
};
|
|
667
|
-
type MarketplaceSkillContentView = {
|
|
668
|
-
type: "skill";
|
|
669
|
-
slug: string;
|
|
670
|
-
name: string;
|
|
671
|
-
install: MarketplaceInstallSpec;
|
|
672
|
-
source: "builtin" | "marketplace" | "remote";
|
|
673
|
-
raw: string;
|
|
674
|
-
metadataRaw?: string;
|
|
675
|
-
bodyRaw: string;
|
|
676
|
-
sourceUrl?: string;
|
|
677
|
-
};
|
|
678
|
-
type MarketplacePluginContentView = {
|
|
679
|
-
type: "plugin";
|
|
680
|
-
slug: string;
|
|
681
|
-
name: string;
|
|
682
|
-
install: MarketplaceInstallSpec;
|
|
683
|
-
source: "npm" | "repo" | "remote";
|
|
684
|
-
raw?: string;
|
|
685
|
-
bodyRaw?: string;
|
|
686
|
-
metadataRaw?: string;
|
|
687
|
-
sourceUrl?: string;
|
|
688
|
-
};
|
|
689
|
-
type MarketplaceListView = {
|
|
690
|
-
total: number;
|
|
691
|
-
page: number;
|
|
692
|
-
pageSize: number;
|
|
693
|
-
totalPages: number;
|
|
694
|
-
sort: MarketplaceSort;
|
|
695
|
-
query?: string;
|
|
696
|
-
items: MarketplaceItemSummary[];
|
|
697
|
-
};
|
|
698
|
-
type MarketplaceRecommendationView = {
|
|
699
|
-
type: MarketplaceItemType;
|
|
700
|
-
sceneId: string;
|
|
701
|
-
title: string;
|
|
702
|
-
description?: string;
|
|
703
|
-
total: number;
|
|
704
|
-
items: MarketplaceItemSummary[];
|
|
705
|
-
};
|
|
706
|
-
type MarketplaceInstalledRecord = {
|
|
707
|
-
type: MarketplaceItemType;
|
|
708
|
-
id?: string;
|
|
709
|
-
spec: string;
|
|
710
|
-
label?: string;
|
|
711
|
-
description?: string;
|
|
712
|
-
descriptionZh?: string;
|
|
713
|
-
source?: string;
|
|
714
|
-
installedAt?: string;
|
|
715
|
-
enabled?: boolean;
|
|
716
|
-
runtimeStatus?: string;
|
|
717
|
-
origin?: string;
|
|
718
|
-
installPath?: string;
|
|
719
|
-
};
|
|
720
|
-
type MarketplaceInstalledView = {
|
|
721
|
-
type: MarketplaceItemType;
|
|
722
|
-
total: number;
|
|
723
|
-
specs: string[];
|
|
724
|
-
records: MarketplaceInstalledRecord[];
|
|
725
|
-
};
|
|
726
|
-
type MarketplaceInstallSkillParams = {
|
|
727
|
-
slug: string;
|
|
728
|
-
kind?: MarketplaceSkillInstallKind;
|
|
729
|
-
skill?: string;
|
|
730
|
-
installPath?: string;
|
|
731
|
-
force?: boolean;
|
|
732
|
-
};
|
|
733
|
-
type MarketplacePluginInstallRequest = {
|
|
734
|
-
type?: "plugin";
|
|
735
|
-
spec: string;
|
|
736
|
-
};
|
|
737
|
-
type MarketplaceSkillInstallRequest = {
|
|
738
|
-
type?: "skill";
|
|
739
|
-
spec: string;
|
|
740
|
-
kind?: MarketplaceSkillInstallKind;
|
|
741
|
-
skill?: string;
|
|
742
|
-
installPath?: string;
|
|
743
|
-
force?: boolean;
|
|
744
|
-
};
|
|
745
|
-
type MarketplacePluginInstallResult = {
|
|
746
|
-
type: "plugin";
|
|
747
|
-
spec: string;
|
|
748
|
-
message: string;
|
|
749
|
-
output?: string;
|
|
750
|
-
};
|
|
751
|
-
type MarketplaceSkillInstallResult = {
|
|
752
|
-
type: "skill";
|
|
753
|
-
spec: string;
|
|
754
|
-
message: string;
|
|
755
|
-
output?: string;
|
|
756
|
-
};
|
|
757
|
-
type MarketplacePluginManageAction = "enable" | "disable" | "uninstall";
|
|
758
|
-
type MarketplaceSkillManageAction = "uninstall";
|
|
759
|
-
type MarketplacePluginManageRequest = {
|
|
760
|
-
type?: "plugin";
|
|
761
|
-
action: MarketplacePluginManageAction;
|
|
762
|
-
id?: string;
|
|
763
|
-
spec?: string;
|
|
764
|
-
};
|
|
765
|
-
type MarketplaceSkillManageRequest = {
|
|
766
|
-
type?: "skill";
|
|
767
|
-
action: MarketplaceSkillManageAction;
|
|
768
|
-
id?: string;
|
|
769
|
-
spec?: string;
|
|
770
|
-
};
|
|
771
|
-
type MarketplacePluginManageResult = {
|
|
772
|
-
type: "plugin";
|
|
773
|
-
action: MarketplacePluginManageAction;
|
|
774
|
-
id: string;
|
|
775
|
-
message: string;
|
|
776
|
-
output?: string;
|
|
777
|
-
};
|
|
778
|
-
type MarketplaceSkillManageResult = {
|
|
779
|
-
type: "skill";
|
|
780
|
-
action: MarketplaceSkillManageAction;
|
|
781
|
-
id: string;
|
|
782
|
-
message: string;
|
|
783
|
-
output?: string;
|
|
784
|
-
};
|
|
785
|
-
type MarketplaceInstaller = {
|
|
786
|
-
installPlugin?: (spec: string) => Promise<{
|
|
787
|
-
message: string;
|
|
788
|
-
output?: string;
|
|
789
|
-
}>;
|
|
790
|
-
installSkill?: (params: MarketplaceInstallSkillParams) => Promise<{
|
|
791
|
-
message: string;
|
|
792
|
-
output?: string;
|
|
793
|
-
}>;
|
|
794
|
-
enablePlugin?: (id: string) => Promise<{
|
|
795
|
-
message: string;
|
|
796
|
-
output?: string;
|
|
797
|
-
}>;
|
|
798
|
-
disablePlugin?: (id: string) => Promise<{
|
|
799
|
-
message: string;
|
|
800
|
-
output?: string;
|
|
801
|
-
}>;
|
|
802
|
-
uninstallPlugin?: (id: string) => Promise<{
|
|
803
|
-
message: string;
|
|
804
|
-
output?: string;
|
|
805
|
-
}>;
|
|
806
|
-
uninstallSkill?: (slug: string) => Promise<{
|
|
807
|
-
message: string;
|
|
808
|
-
output?: string;
|
|
809
|
-
}>;
|
|
810
|
-
};
|
|
811
|
-
type MarketplaceApiConfig = {
|
|
812
|
-
apiBaseUrl?: string;
|
|
813
|
-
installer?: MarketplaceInstaller;
|
|
814
|
-
};
|
|
815
927
|
type UiServerEvent = {
|
|
816
928
|
type: "config.updated";
|
|
817
929
|
payload: {
|
|
@@ -879,6 +991,7 @@ declare class UiAuthService {
|
|
|
879
991
|
private clearAllSessions;
|
|
880
992
|
private deleteRequestSession;
|
|
881
993
|
private buildLoginCookie;
|
|
994
|
+
buildTrustedRequestCookieHeader(): string | null;
|
|
882
995
|
buildLogoutCookie(request: Request): string;
|
|
883
996
|
setup(request: Request, payload: AuthSetupRequest): {
|
|
884
997
|
status: AuthStatusView;
|
|
@@ -956,4 +1069,8 @@ declare function deleteSession(configPath: string, key: string): boolean;
|
|
|
956
1069
|
declare function updateRuntime(configPath: string, patch: RuntimeConfigUpdate): Pick<ConfigView, "agents" | "bindings" | "session">;
|
|
957
1070
|
declare function updateSecrets(configPath: string, patch: SecretsConfigUpdate): SecretsView;
|
|
958
1071
|
|
|
959
|
-
|
|
1072
|
+
declare function getUiBridgeSecretPath(): string;
|
|
1073
|
+
declare function readUiBridgeSecret(): string | null;
|
|
1074
|
+
declare function ensureUiBridgeSecret(): string;
|
|
1075
|
+
|
|
1076
|
+
export { type AgentBindingView, type AgentProfileView, type ApiError, type ApiResponse, type AppMetaView, type AuthEnabledUpdateRequest, type AuthLoginRequest, type AuthPasswordUpdateRequest, type AuthSetupRequest, type AuthStatusView, type BindingPeerView, type BochaFreshnessValue, type ChannelSpecView, type ChatCapabilitiesView, type ChatCommandOptionView, type ChatCommandView, type ChatCommandsView, type ChatRunListView, type ChatRunState, type ChatRunView, type ChatSessionTypeCtaView, type ChatSessionTypeOptionView, type ChatSessionTypesView, type ChatTurnRequest, type ChatTurnResult, type ChatTurnStopRequest, type ChatTurnStopResult, type ChatTurnStreamEvent, type ChatTurnView, type ConfigActionExecuteRequest, type ConfigActionExecuteResult, type ConfigActionManifest, type ConfigActionType, type ConfigMetaView, type ConfigSchemaResponse, type ConfigUiHint, type ConfigUiHints, type ConfigView, type CronActionResult, type CronEnableRequest, type CronJobStateView, type CronJobView, type CronListView, type CronPayloadView, type CronRunRequest, type CronScheduleView, DEFAULT_SESSION_TYPE, type MarketplaceApiConfig, type MarketplaceInstallKind, type MarketplaceInstallSkillParams, type MarketplaceInstallSpec, type MarketplaceInstalledRecord, type MarketplaceInstalledView, type MarketplaceInstaller, type MarketplaceItemSummary, type MarketplaceItemType, type MarketplaceItemView, type MarketplaceListView, type MarketplaceLocalizedTextMap, type MarketplaceMcpContentView, type MarketplaceMcpDoctorResult, type MarketplaceMcpInstallKind, type MarketplaceMcpInstallRequest, type MarketplaceMcpInstallResult, type MarketplaceMcpInstallSpec, type MarketplaceMcpManageAction, type MarketplaceMcpManageRequest, type MarketplaceMcpManageResult, type MarketplaceMcpTemplateInput, type MarketplacePluginContentView, type MarketplacePluginInstallKind, type MarketplacePluginInstallRequest, type MarketplacePluginInstallResult, type MarketplacePluginManageAction, type MarketplacePluginManageRequest, type MarketplacePluginManageResult, type MarketplaceRecommendationView, type MarketplaceSkillContentView, type MarketplaceSkillInstallKind, type MarketplaceSkillInstallRequest, type MarketplaceSkillInstallResult, type MarketplaceSkillManageAction, type MarketplaceSkillManageRequest, type MarketplaceSkillManageResult, type MarketplaceSort, type ProviderAuthImportResult, type ProviderAuthPollRequest, type ProviderAuthPollResult, type ProviderAuthStartRequest, type ProviderAuthStartResult, type ProviderConfigUpdate, type ProviderConfigView, type ProviderConnectionTestRequest, type ProviderConnectionTestResult, type ProviderCreateRequest, type ProviderCreateResult, type ProviderDeleteResult, type ProviderSpecView, type RuntimeConfigUpdate, type SearchConfigUpdate, type SearchConfigView, type SearchProviderConfigView, type SearchProviderName, type SearchProviderSpecView, type SecretProviderEnvView, type SecretProviderExecView, type SecretProviderFileView, type SecretProviderView, type SecretRefView, type SecretSourceView, type SecretsConfigUpdate, type SecretsView, type SessionConfigView, type SessionEntryView, type SessionEventView, type SessionHistoryView, type SessionMessageView, type SessionPatchUpdate, SessionPatchValidationError, type SessionsListView, type UiChatRuntime, type UiNcpAgent, type UiNcpSessionListView, type UiNcpSessionMessagesView, type UiServerEvent, type UiServerHandle, type UiServerOptions, buildConfigMeta, buildConfigSchemaView, buildConfigView, createCustomProvider, createUiRouter, deleteCustomProvider, deleteSession, ensureUiBridgeSecret, executeConfigAction, getSessionHistory, getUiBridgeSecretPath, listSessions, loadConfigOrDefault, patchSession, readUiBridgeSecret, startUiServer, testProviderConnection, updateChannel, updateModel, updateProvider, updateRuntime, updateSearch, updateSecrets };
|
package/dist/index.js
CHANGED
|
@@ -4,9 +4,9 @@ import { compress } from "hono/compress";
|
|
|
4
4
|
import { cors } from "hono/cors";
|
|
5
5
|
import { serve } from "@hono/node-server";
|
|
6
6
|
import { WebSocketServer, WebSocket } from "ws";
|
|
7
|
-
import { existsSync, readFileSync } from "fs";
|
|
7
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
8
8
|
import { readFile as readFile2, stat } from "fs/promises";
|
|
9
|
-
import { join } from "path";
|
|
9
|
+
import { join as join2 } from "path";
|
|
10
10
|
|
|
11
11
|
// src/ui/auth.service.ts
|
|
12
12
|
import { ConfigSchema, loadConfig, saveConfig } from "@nextclaw/core";
|
|
@@ -179,6 +179,18 @@ var UiAuthService = class {
|
|
|
179
179
|
secure: resolveSecureRequest(request.url, request.headers.get("x-forwarded-proto"))
|
|
180
180
|
});
|
|
181
181
|
}
|
|
182
|
+
buildTrustedRequestCookieHeader() {
|
|
183
|
+
const auth = this.readAuthConfig();
|
|
184
|
+
if (!auth.enabled || !this.isConfigured(auth)) {
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
const username = normalizeUsername(auth.username);
|
|
188
|
+
if (!username) {
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
const sessionId = this.createSession(username);
|
|
192
|
+
return `${SESSION_COOKIE_NAME}=${encodeURIComponent(sessionId)}`;
|
|
193
|
+
}
|
|
182
194
|
buildLogoutCookie(request) {
|
|
183
195
|
return buildSetCookie({
|
|
184
196
|
value: "",
|
|
@@ -393,6 +405,39 @@ var AppRoutesController = class {
|
|
|
393
405
|
appMeta = (c) => c.json(ok(buildAppMetaView(this.options)));
|
|
394
406
|
};
|
|
395
407
|
|
|
408
|
+
// src/ui/auth-bridge.ts
|
|
409
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
410
|
+
import { join } from "path";
|
|
411
|
+
import { randomBytes as randomBytes2 } from "crypto";
|
|
412
|
+
import { getDataDir } from "@nextclaw/core";
|
|
413
|
+
var REMOTE_BRIDGE_DIR = join(getDataDir(), "remote");
|
|
414
|
+
var REMOTE_BRIDGE_SECRET_PATH = join(REMOTE_BRIDGE_DIR, "ui-bridge-secret");
|
|
415
|
+
function getUiBridgeSecretPath() {
|
|
416
|
+
return REMOTE_BRIDGE_SECRET_PATH;
|
|
417
|
+
}
|
|
418
|
+
function readUiBridgeSecret() {
|
|
419
|
+
if (!existsSync(REMOTE_BRIDGE_SECRET_PATH)) {
|
|
420
|
+
return null;
|
|
421
|
+
}
|
|
422
|
+
try {
|
|
423
|
+
const raw = readFileSync(REMOTE_BRIDGE_SECRET_PATH, "utf-8").trim();
|
|
424
|
+
return raw.length > 0 ? raw : null;
|
|
425
|
+
} catch {
|
|
426
|
+
return null;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
function ensureUiBridgeSecret() {
|
|
430
|
+
const existing = readUiBridgeSecret();
|
|
431
|
+
if (existing) {
|
|
432
|
+
return existing;
|
|
433
|
+
}
|
|
434
|
+
mkdirSync(REMOTE_BRIDGE_DIR, { recursive: true });
|
|
435
|
+
const secret = randomBytes2(24).toString("hex");
|
|
436
|
+
writeFileSync(REMOTE_BRIDGE_SECRET_PATH, `${secret}
|
|
437
|
+
`, "utf-8");
|
|
438
|
+
return secret;
|
|
439
|
+
}
|
|
440
|
+
|
|
396
441
|
// src/ui/router/auth.controller.ts
|
|
397
442
|
function isAuthenticationRequiredError(message) {
|
|
398
443
|
return message === "Authentication required.";
|
|
@@ -492,6 +537,16 @@ var AuthRoutesController = class {
|
|
|
492
537
|
return c.json(err(code, message), status);
|
|
493
538
|
}
|
|
494
539
|
};
|
|
540
|
+
issueBridgeSession = (c) => {
|
|
541
|
+
const providedSecret = c.req.header("x-nextclaw-ui-bridge-secret")?.trim();
|
|
542
|
+
const expectedSecret = ensureUiBridgeSecret();
|
|
543
|
+
if (!providedSecret || providedSecret !== expectedSecret) {
|
|
544
|
+
return c.json(err("FORBIDDEN", "Invalid bridge secret."), 403);
|
|
545
|
+
}
|
|
546
|
+
return c.json(ok({
|
|
547
|
+
cookie: this.authService.buildTrustedRequestCookieHeader()
|
|
548
|
+
}));
|
|
549
|
+
};
|
|
495
550
|
};
|
|
496
551
|
|
|
497
552
|
// src/ui/router/chat.controller.ts
|
|
@@ -512,7 +567,7 @@ import {
|
|
|
512
567
|
SessionManager,
|
|
513
568
|
getWorkspacePathFromConfig,
|
|
514
569
|
normalizeThinkingLevels,
|
|
515
|
-
parseThinkingLevel as
|
|
570
|
+
parseThinkingLevel as parseThinkingLevel3
|
|
516
571
|
} from "@nextclaw/core";
|
|
517
572
|
|
|
518
573
|
// src/ui/provider-overrides.ts
|
|
@@ -639,6 +694,18 @@ function applySessionPreferencePatch(params) {
|
|
|
639
694
|
return nextMetadata;
|
|
640
695
|
}
|
|
641
696
|
|
|
697
|
+
// src/ui/session-list-metadata.ts
|
|
698
|
+
import { parseThinkingLevel as parseThinkingLevel2 } from "@nextclaw/core";
|
|
699
|
+
function readSessionListMetadata(metadata) {
|
|
700
|
+
const rawLabel = typeof metadata.label === "string" ? metadata.label.trim() : "";
|
|
701
|
+
const rawPreferredModel = typeof metadata.preferred_model === "string" ? metadata.preferred_model.trim() : "";
|
|
702
|
+
return {
|
|
703
|
+
label: rawLabel || void 0,
|
|
704
|
+
preferredModel: rawPreferredModel || void 0,
|
|
705
|
+
preferredThinking: parseThinkingLevel2(metadata.preferred_thinking) ?? null
|
|
706
|
+
};
|
|
707
|
+
}
|
|
708
|
+
|
|
642
709
|
// src/ui/config.ts
|
|
643
710
|
var MASK_MIN_LENGTH = 8;
|
|
644
711
|
var EXTRA_SENSITIVE_PATH_PATTERNS = [/authorization/i, /cookie/i, /session/i, /bearer/i];
|
|
@@ -991,7 +1058,7 @@ function normalizeModelThinkingConfig(input) {
|
|
|
991
1058
|
if (supported.length === 0) {
|
|
992
1059
|
continue;
|
|
993
1060
|
}
|
|
994
|
-
const defaultLevel =
|
|
1061
|
+
const defaultLevel = parseThinkingLevel3(rawValue.default);
|
|
995
1062
|
if (defaultLevel && supported.includes(defaultLevel)) {
|
|
996
1063
|
normalized[model] = { supported, default: defaultLevel };
|
|
997
1064
|
} else {
|
|
@@ -1578,8 +1645,7 @@ function listSessions(configPath, query) {
|
|
|
1578
1645
|
const messages = session?.messages ?? [];
|
|
1579
1646
|
const lastMessage = messages.length > 0 ? messages[messages.length - 1] : null;
|
|
1580
1647
|
const metadata = item.metadata && typeof item.metadata === "object" ? item.metadata : {};
|
|
1581
|
-
const label
|
|
1582
|
-
const preferredModel = typeof metadata.preferred_model === "string" ? metadata.preferred_model.trim() : "";
|
|
1648
|
+
const { label, preferredModel, preferredThinking } = readSessionListMetadata(metadata);
|
|
1583
1649
|
const createdAt = typeof item.created_at === "string" ? item.created_at : (/* @__PURE__ */ new Date(0)).toISOString();
|
|
1584
1650
|
const updatedAt = typeof item.updated_at === "string" ? item.updated_at : createdAt;
|
|
1585
1651
|
const sessionType = readSessionType({
|
|
@@ -1594,8 +1660,9 @@ function listSessions(configPath, query) {
|
|
|
1594
1660
|
key,
|
|
1595
1661
|
createdAt,
|
|
1596
1662
|
updatedAt,
|
|
1597
|
-
label
|
|
1598
|
-
preferredModel
|
|
1663
|
+
label,
|
|
1664
|
+
preferredModel,
|
|
1665
|
+
preferredThinking,
|
|
1599
1666
|
sessionType,
|
|
1600
1667
|
sessionTypeMutable,
|
|
1601
1668
|
messageCount: messages.length,
|
|
@@ -2429,7 +2496,7 @@ var ChatRoutesController = class {
|
|
|
2429
2496
|
};
|
|
2430
2497
|
|
|
2431
2498
|
// src/ui/provider-auth.ts
|
|
2432
|
-
import { createHash, randomBytes as
|
|
2499
|
+
import { createHash, randomBytes as randomBytes3, randomUUID as randomUUID2 } from "crypto";
|
|
2433
2500
|
import { readFile } from "fs/promises";
|
|
2434
2501
|
import { homedir } from "os";
|
|
2435
2502
|
import { isAbsolute, resolve } from "path";
|
|
@@ -2457,7 +2524,7 @@ function toBase64Url(buffer) {
|
|
|
2457
2524
|
return buffer.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
|
2458
2525
|
}
|
|
2459
2526
|
function buildPkce() {
|
|
2460
|
-
const verifier = toBase64Url(
|
|
2527
|
+
const verifier = toBase64Url(randomBytes3(48));
|
|
2461
2528
|
const challenge = toBase64Url(createHash("sha256").update(verifier).digest());
|
|
2462
2529
|
return { verifier, challenge };
|
|
2463
2530
|
}
|
|
@@ -2674,7 +2741,7 @@ async function startProviderAuth(configPath, providerName, options) {
|
|
|
2674
2741
|
if (!pkce) {
|
|
2675
2742
|
throw new Error("MiniMax OAuth requires PKCE");
|
|
2676
2743
|
}
|
|
2677
|
-
const state = toBase64Url(
|
|
2744
|
+
const state = toBase64Url(randomBytes3(16));
|
|
2678
2745
|
const body = new URLSearchParams({
|
|
2679
2746
|
response_type: "code",
|
|
2680
2747
|
client_id: resolvedMethod.clientId,
|
|
@@ -3708,6 +3775,13 @@ async function fetchAllSkillMarketplaceItems(params) {
|
|
|
3708
3775
|
query: params.query
|
|
3709
3776
|
});
|
|
3710
3777
|
}
|
|
3778
|
+
async function fetchAllMcpMarketplaceItems(params) {
|
|
3779
|
+
return fetchAllMarketplaceItems({
|
|
3780
|
+
baseUrl: params.baseUrl,
|
|
3781
|
+
path: "/api/v1/mcp/items",
|
|
3782
|
+
query: params.query
|
|
3783
|
+
});
|
|
3784
|
+
}
|
|
3711
3785
|
function sanitizeMarketplaceListItems(items) {
|
|
3712
3786
|
return items.map((item) => sanitizeMarketplaceItem(item));
|
|
3713
3787
|
}
|
|
@@ -3715,6 +3789,216 @@ function sanitizeMarketplaceItemView(item) {
|
|
|
3715
3789
|
return sanitizeMarketplaceItem(item);
|
|
3716
3790
|
}
|
|
3717
3791
|
|
|
3792
|
+
// src/ui/router/marketplace/mcp.controller.ts
|
|
3793
|
+
import { McpInstalledViewService } from "@nextclaw/mcp";
|
|
3794
|
+
var McpMarketplaceController = class {
|
|
3795
|
+
constructor(options, marketplaceBaseUrl) {
|
|
3796
|
+
this.options = options;
|
|
3797
|
+
this.marketplaceBaseUrl = marketplaceBaseUrl;
|
|
3798
|
+
}
|
|
3799
|
+
getInstalled = (c) => {
|
|
3800
|
+
const service = new McpInstalledViewService({
|
|
3801
|
+
getConfig: () => loadConfigOrDefault(this.options.configPath)
|
|
3802
|
+
});
|
|
3803
|
+
const records = service.listInstalled().map((record) => ({
|
|
3804
|
+
type: "mcp",
|
|
3805
|
+
id: record.name,
|
|
3806
|
+
spec: record.catalogSlug ?? record.name,
|
|
3807
|
+
label: record.displayName ?? record.name,
|
|
3808
|
+
enabled: record.enabled,
|
|
3809
|
+
runtimeStatus: record.enabled ? "enabled" : "disabled",
|
|
3810
|
+
transport: record.transport,
|
|
3811
|
+
scope: record.scope,
|
|
3812
|
+
catalogSlug: record.catalogSlug,
|
|
3813
|
+
vendor: record.vendor,
|
|
3814
|
+
docsUrl: record.docsUrl,
|
|
3815
|
+
homepage: record.homepage,
|
|
3816
|
+
trustLevel: record.trustLevel,
|
|
3817
|
+
source: record.source,
|
|
3818
|
+
installedAt: record.installedAt,
|
|
3819
|
+
toolCount: record.toolCount,
|
|
3820
|
+
accessible: record.accessible,
|
|
3821
|
+
lastReadyAt: record.lastReadyAt,
|
|
3822
|
+
lastDoctorAt: record.lastReadyAt,
|
|
3823
|
+
lastError: record.lastError
|
|
3824
|
+
}));
|
|
3825
|
+
return c.json(ok({
|
|
3826
|
+
type: "mcp",
|
|
3827
|
+
total: records.length,
|
|
3828
|
+
specs: records.map((record) => record.spec),
|
|
3829
|
+
records
|
|
3830
|
+
}));
|
|
3831
|
+
};
|
|
3832
|
+
listItems = async (c) => {
|
|
3833
|
+
const query = c.req.query();
|
|
3834
|
+
const result = await fetchAllMcpMarketplaceItems({
|
|
3835
|
+
baseUrl: this.marketplaceBaseUrl,
|
|
3836
|
+
query: {
|
|
3837
|
+
q: query.q,
|
|
3838
|
+
tag: query.tag,
|
|
3839
|
+
sort: query.sort,
|
|
3840
|
+
page: query.page,
|
|
3841
|
+
pageSize: query.pageSize
|
|
3842
|
+
}
|
|
3843
|
+
});
|
|
3844
|
+
if (!result.ok) {
|
|
3845
|
+
return c.json(err("MARKETPLACE_UNAVAILABLE", result.message), result.status);
|
|
3846
|
+
}
|
|
3847
|
+
const items = sanitizeMarketplaceListItems(result.data.items).map((item) => normalizeMarketplaceItemForUi(item));
|
|
3848
|
+
const pageSize = Math.min(100, toPositiveInt(query.pageSize, 20));
|
|
3849
|
+
const requestedPage = toPositiveInt(query.page, 1);
|
|
3850
|
+
const totalPages = items.length === 0 ? 0 : Math.ceil(items.length / pageSize);
|
|
3851
|
+
const currentPage = totalPages === 0 ? 1 : Math.min(requestedPage, totalPages);
|
|
3852
|
+
return c.json(ok({
|
|
3853
|
+
total: items.length,
|
|
3854
|
+
page: currentPage,
|
|
3855
|
+
pageSize,
|
|
3856
|
+
totalPages,
|
|
3857
|
+
sort: result.data.sort,
|
|
3858
|
+
query: result.data.query,
|
|
3859
|
+
items: items.slice((currentPage - 1) * pageSize, currentPage * pageSize)
|
|
3860
|
+
}));
|
|
3861
|
+
};
|
|
3862
|
+
getItem = async (c) => {
|
|
3863
|
+
const slug = encodeURIComponent(c.req.param("slug"));
|
|
3864
|
+
const result = await fetchMarketplaceData({
|
|
3865
|
+
baseUrl: this.marketplaceBaseUrl,
|
|
3866
|
+
path: `/api/v1/mcp/items/${slug}`
|
|
3867
|
+
});
|
|
3868
|
+
if (!result.ok) {
|
|
3869
|
+
return c.json(err("MARKETPLACE_UNAVAILABLE", result.message), result.status);
|
|
3870
|
+
}
|
|
3871
|
+
return c.json(ok(normalizeMarketplaceItemForUi(sanitizeMarketplaceItemView(result.data))));
|
|
3872
|
+
};
|
|
3873
|
+
getItemContent = async (c) => {
|
|
3874
|
+
const slug = encodeURIComponent(c.req.param("slug"));
|
|
3875
|
+
const result = await fetchMarketplaceData({
|
|
3876
|
+
baseUrl: this.marketplaceBaseUrl,
|
|
3877
|
+
path: `/api/v1/mcp/items/${slug}/content`
|
|
3878
|
+
});
|
|
3879
|
+
if (!result.ok) {
|
|
3880
|
+
return c.json(err("MARKETPLACE_UNAVAILABLE", result.message), result.status);
|
|
3881
|
+
}
|
|
3882
|
+
return c.json(ok(result.data));
|
|
3883
|
+
};
|
|
3884
|
+
install = async (c) => {
|
|
3885
|
+
const body = await readJson(c.req.raw);
|
|
3886
|
+
if (!body.ok || !body.data || typeof body.data !== "object") {
|
|
3887
|
+
return c.json(err("INVALID_BODY", "invalid json body"), 400);
|
|
3888
|
+
}
|
|
3889
|
+
if (body.data.type && body.data.type !== "mcp") {
|
|
3890
|
+
return c.json(err("INVALID_BODY", "body.type does not match route type"), 400);
|
|
3891
|
+
}
|
|
3892
|
+
const slug = typeof body.data.spec === "string" ? body.data.spec.trim() : "";
|
|
3893
|
+
if (!slug) {
|
|
3894
|
+
return c.json(err("INVALID_BODY", "non-empty spec is required"), 400);
|
|
3895
|
+
}
|
|
3896
|
+
const installer = this.options.marketplace?.installer;
|
|
3897
|
+
if (!installer?.installMcp) {
|
|
3898
|
+
return c.json(err("NOT_AVAILABLE", "mcp installer is not configured"), 503);
|
|
3899
|
+
}
|
|
3900
|
+
const itemResult = await fetchMarketplaceData({
|
|
3901
|
+
baseUrl: this.marketplaceBaseUrl,
|
|
3902
|
+
path: `/api/v1/mcp/items/${encodeURIComponent(slug)}`
|
|
3903
|
+
});
|
|
3904
|
+
if (!itemResult.ok) {
|
|
3905
|
+
return c.json(err("MARKETPLACE_UNAVAILABLE", itemResult.message), itemResult.status);
|
|
3906
|
+
}
|
|
3907
|
+
const template = itemResult.data.install;
|
|
3908
|
+
if (template.kind !== "template") {
|
|
3909
|
+
return c.json(err("MARKETPLACE_CONTRACT_MISMATCH", `unsupported mcp install kind: ${template.kind}`), 502);
|
|
3910
|
+
}
|
|
3911
|
+
try {
|
|
3912
|
+
const result = await installer.installMcp({
|
|
3913
|
+
...body.data,
|
|
3914
|
+
template
|
|
3915
|
+
});
|
|
3916
|
+
this.options.publish({ type: "config.updated", payload: { path: "mcp" } });
|
|
3917
|
+
return c.json(ok({
|
|
3918
|
+
type: "mcp",
|
|
3919
|
+
spec: slug,
|
|
3920
|
+
name: result.name,
|
|
3921
|
+
message: result.message,
|
|
3922
|
+
output: result.output
|
|
3923
|
+
}));
|
|
3924
|
+
} catch (error) {
|
|
3925
|
+
return c.json(err("INSTALL_FAILED", error instanceof Error ? error.message : String(error)), 400);
|
|
3926
|
+
}
|
|
3927
|
+
};
|
|
3928
|
+
manage = async (c) => {
|
|
3929
|
+
const body = await readJson(c.req.raw);
|
|
3930
|
+
if (!body.ok || !body.data || typeof body.data !== "object") {
|
|
3931
|
+
return c.json(err("INVALID_BODY", "invalid json body"), 400);
|
|
3932
|
+
}
|
|
3933
|
+
if (body.data.type && body.data.type !== "mcp") {
|
|
3934
|
+
return c.json(err("INVALID_BODY", "body.type does not match route type"), 400);
|
|
3935
|
+
}
|
|
3936
|
+
const target = typeof body.data.id === "string" && body.data.id.trim().length > 0 ? body.data.id.trim() : typeof body.data.spec === "string" && body.data.spec.trim().length > 0 ? body.data.spec.trim() : "";
|
|
3937
|
+
if (!target) {
|
|
3938
|
+
return c.json(err("INVALID_BODY", "non-empty id/spec is required"), 400);
|
|
3939
|
+
}
|
|
3940
|
+
const installer = this.options.marketplace?.installer;
|
|
3941
|
+
if (!installer) {
|
|
3942
|
+
return c.json(err("NOT_AVAILABLE", "marketplace installer is not configured"), 503);
|
|
3943
|
+
}
|
|
3944
|
+
try {
|
|
3945
|
+
const action = body.data.action;
|
|
3946
|
+
const result = action === "enable" ? await installer.enableMcp?.(target) : action === "disable" ? await installer.disableMcp?.(target) : await installer.removeMcp?.(target);
|
|
3947
|
+
if (!result) {
|
|
3948
|
+
return c.json(err("NOT_AVAILABLE", `mcp ${action} is not configured`), 503);
|
|
3949
|
+
}
|
|
3950
|
+
this.options.publish({ type: "config.updated", payload: { path: "mcp" } });
|
|
3951
|
+
return c.json(ok({
|
|
3952
|
+
type: "mcp",
|
|
3953
|
+
action,
|
|
3954
|
+
id: target,
|
|
3955
|
+
message: result.message,
|
|
3956
|
+
output: result.output
|
|
3957
|
+
}));
|
|
3958
|
+
} catch (error) {
|
|
3959
|
+
return c.json(err("MANAGE_FAILED", error instanceof Error ? error.message : String(error)), 400);
|
|
3960
|
+
}
|
|
3961
|
+
};
|
|
3962
|
+
doctor = async (c) => {
|
|
3963
|
+
const body = await readJson(c.req.raw);
|
|
3964
|
+
if (!body.ok || !body.data || typeof body.data !== "object") {
|
|
3965
|
+
return c.json(err("INVALID_BODY", "invalid json body"), 400);
|
|
3966
|
+
}
|
|
3967
|
+
const target = typeof body.data.name === "string" && body.data.name.trim().length > 0 ? body.data.name.trim() : typeof body.data.id === "string" && body.data.id.trim().length > 0 ? body.data.id.trim() : typeof body.data.spec === "string" && body.data.spec.trim().length > 0 ? body.data.spec.trim() : "";
|
|
3968
|
+
if (!target) {
|
|
3969
|
+
return c.json(err("INVALID_BODY", "name/id/spec is required"), 400);
|
|
3970
|
+
}
|
|
3971
|
+
const installer = this.options.marketplace?.installer;
|
|
3972
|
+
if (!installer?.doctorMcp) {
|
|
3973
|
+
return c.json(err("NOT_AVAILABLE", "mcp doctor is not configured"), 503);
|
|
3974
|
+
}
|
|
3975
|
+
try {
|
|
3976
|
+
const result = await installer.doctorMcp(target);
|
|
3977
|
+
return c.json(ok(result));
|
|
3978
|
+
} catch (error) {
|
|
3979
|
+
return c.json(err("DOCTOR_FAILED", error instanceof Error ? error.message : String(error)), 400);
|
|
3980
|
+
}
|
|
3981
|
+
};
|
|
3982
|
+
getRecommendations = async (c) => {
|
|
3983
|
+
const query = c.req.query();
|
|
3984
|
+
const result = await fetchMarketplaceData({
|
|
3985
|
+
baseUrl: this.marketplaceBaseUrl,
|
|
3986
|
+
path: "/api/v1/mcp/recommendations",
|
|
3987
|
+
query: {
|
|
3988
|
+
scene: query.scene,
|
|
3989
|
+
limit: query.limit
|
|
3990
|
+
}
|
|
3991
|
+
});
|
|
3992
|
+
if (!result.ok) {
|
|
3993
|
+
return c.json(err("MARKETPLACE_UNAVAILABLE", result.message), result.status);
|
|
3994
|
+
}
|
|
3995
|
+
return c.json(ok({
|
|
3996
|
+
...result.data,
|
|
3997
|
+
items: sanitizeMarketplaceListItems(result.data.items).map((item) => normalizeMarketplaceItemForUi(item))
|
|
3998
|
+
}));
|
|
3999
|
+
};
|
|
4000
|
+
};
|
|
4001
|
+
|
|
3718
4002
|
// src/ui/router/marketplace/installed.ts
|
|
3719
4003
|
import * as NextclawCore3 from "@nextclaw/core";
|
|
3720
4004
|
import { buildPluginStatusReport } from "@nextclaw/openclaw-compat";
|
|
@@ -4313,6 +4597,32 @@ var PluginMarketplaceController = class {
|
|
|
4313
4597
|
};
|
|
4314
4598
|
};
|
|
4315
4599
|
|
|
4600
|
+
// src/ui/router/marketplace/routes.ts
|
|
4601
|
+
function mountMarketplaceRoutes(app, controllers) {
|
|
4602
|
+
app.get("/api/marketplace/plugins/installed", controllers.plugin.getInstalled);
|
|
4603
|
+
app.get("/api/marketplace/plugins/items", controllers.plugin.listItems);
|
|
4604
|
+
app.get("/api/marketplace/plugins/items/:slug", controllers.plugin.getItem);
|
|
4605
|
+
app.get("/api/marketplace/plugins/items/:slug/content", controllers.plugin.getItemContent);
|
|
4606
|
+
app.post("/api/marketplace/plugins/install", controllers.plugin.install);
|
|
4607
|
+
app.post("/api/marketplace/plugins/manage", controllers.plugin.manage);
|
|
4608
|
+
app.get("/api/marketplace/plugins/recommendations", controllers.plugin.getRecommendations);
|
|
4609
|
+
app.get("/api/marketplace/skills/installed", controllers.skill.getInstalled);
|
|
4610
|
+
app.get("/api/marketplace/skills/items", controllers.skill.listItems);
|
|
4611
|
+
app.get("/api/marketplace/skills/items/:slug", controllers.skill.getItem);
|
|
4612
|
+
app.get("/api/marketplace/skills/items/:slug/content", controllers.skill.getItemContent);
|
|
4613
|
+
app.post("/api/marketplace/skills/install", controllers.skill.install);
|
|
4614
|
+
app.post("/api/marketplace/skills/manage", controllers.skill.manage);
|
|
4615
|
+
app.get("/api/marketplace/skills/recommendations", controllers.skill.getRecommendations);
|
|
4616
|
+
app.get("/api/marketplace/mcp/installed", controllers.mcp.getInstalled);
|
|
4617
|
+
app.get("/api/marketplace/mcp/items", controllers.mcp.listItems);
|
|
4618
|
+
app.get("/api/marketplace/mcp/items/:slug", controllers.mcp.getItem);
|
|
4619
|
+
app.get("/api/marketplace/mcp/items/:slug/content", controllers.mcp.getItemContent);
|
|
4620
|
+
app.post("/api/marketplace/mcp/install", controllers.mcp.install);
|
|
4621
|
+
app.post("/api/marketplace/mcp/manage", controllers.mcp.manage);
|
|
4622
|
+
app.post("/api/marketplace/mcp/doctor", controllers.mcp.doctor);
|
|
4623
|
+
app.get("/api/marketplace/mcp/recommendations", controllers.mcp.getRecommendations);
|
|
4624
|
+
}
|
|
4625
|
+
|
|
4316
4626
|
// src/ui/router/marketplace/skill.controller.ts
|
|
4317
4627
|
async function installMarketplaceSkill(params) {
|
|
4318
4628
|
const spec = typeof params.body.spec === "string" ? params.body.spec.trim() : "";
|
|
@@ -4620,6 +4930,7 @@ function createUiRouter(options) {
|
|
|
4620
4930
|
const ncpSessionController = new NcpSessionRoutesController(options);
|
|
4621
4931
|
const pluginMarketplaceController = new PluginMarketplaceController(options, marketplaceBaseUrl);
|
|
4622
4932
|
const skillMarketplaceController = new SkillMarketplaceController(options, marketplaceBaseUrl);
|
|
4933
|
+
const mcpMarketplaceController = new McpMarketplaceController(options, marketplaceBaseUrl);
|
|
4623
4934
|
app.notFound((c) => c.json(err("NOT_FOUND", "endpoint not found"), 404));
|
|
4624
4935
|
app.use("/api/*", async (c, next) => {
|
|
4625
4936
|
const path = c.req.path;
|
|
@@ -4642,6 +4953,7 @@ function createUiRouter(options) {
|
|
|
4642
4953
|
app.post("/api/auth/logout", authController.logout);
|
|
4643
4954
|
app.put("/api/auth/password", authController.updatePassword);
|
|
4644
4955
|
app.put("/api/auth/enabled", authController.updateEnabled);
|
|
4956
|
+
app.post("/api/auth/bridge", authController.issueBridgeSession);
|
|
4645
4957
|
app.get("/api/config", configController.getConfig);
|
|
4646
4958
|
app.get("/api/config/meta", configController.getConfigMeta);
|
|
4647
4959
|
app.get("/api/config/schema", configController.getConfigSchema);
|
|
@@ -4688,20 +5000,11 @@ function createUiRouter(options) {
|
|
|
4688
5000
|
app.delete("/api/cron/:id", cronController.deleteJob);
|
|
4689
5001
|
app.put("/api/cron/:id/enable", cronController.enableJob);
|
|
4690
5002
|
app.post("/api/cron/:id/run", cronController.runJob);
|
|
4691
|
-
app
|
|
4692
|
-
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
|
|
4696
|
-
app.post("/api/marketplace/plugins/manage", pluginMarketplaceController.manage);
|
|
4697
|
-
app.get("/api/marketplace/plugins/recommendations", pluginMarketplaceController.getRecommendations);
|
|
4698
|
-
app.get("/api/marketplace/skills/installed", skillMarketplaceController.getInstalled);
|
|
4699
|
-
app.get("/api/marketplace/skills/items", skillMarketplaceController.listItems);
|
|
4700
|
-
app.get("/api/marketplace/skills/items/:slug", skillMarketplaceController.getItem);
|
|
4701
|
-
app.get("/api/marketplace/skills/items/:slug/content", skillMarketplaceController.getItemContent);
|
|
4702
|
-
app.post("/api/marketplace/skills/install", skillMarketplaceController.install);
|
|
4703
|
-
app.post("/api/marketplace/skills/manage", skillMarketplaceController.manage);
|
|
4704
|
-
app.get("/api/marketplace/skills/recommendations", skillMarketplaceController.getRecommendations);
|
|
5003
|
+
mountMarketplaceRoutes(app, {
|
|
5004
|
+
plugin: pluginMarketplaceController,
|
|
5005
|
+
skill: skillMarketplaceController,
|
|
5006
|
+
mcp: mcpMarketplaceController
|
|
5007
|
+
});
|
|
4705
5008
|
return app;
|
|
4706
5009
|
}
|
|
4707
5010
|
|
|
@@ -4745,13 +5048,13 @@ function startUiServer(options) {
|
|
|
4745
5048
|
})
|
|
4746
5049
|
);
|
|
4747
5050
|
const staticDir = options.staticDir;
|
|
4748
|
-
if (staticDir &&
|
|
4749
|
-
const indexHtml =
|
|
5051
|
+
if (staticDir && existsSync2(join2(staticDir, "index.html"))) {
|
|
5052
|
+
const indexHtml = readFileSync2(join2(staticDir, "index.html"), "utf-8");
|
|
4750
5053
|
app.use(
|
|
4751
5054
|
"/*",
|
|
4752
5055
|
serveStatic({
|
|
4753
5056
|
root: staticDir,
|
|
4754
|
-
join,
|
|
5057
|
+
join: join2,
|
|
4755
5058
|
getContent: async (path) => {
|
|
4756
5059
|
try {
|
|
4757
5060
|
return await readFile2(path);
|
|
@@ -4826,11 +5129,14 @@ export {
|
|
|
4826
5129
|
createUiRouter,
|
|
4827
5130
|
deleteCustomProvider,
|
|
4828
5131
|
deleteSession,
|
|
5132
|
+
ensureUiBridgeSecret,
|
|
4829
5133
|
executeConfigAction,
|
|
4830
5134
|
getSessionHistory,
|
|
5135
|
+
getUiBridgeSecretPath,
|
|
4831
5136
|
listSessions,
|
|
4832
5137
|
loadConfigOrDefault,
|
|
4833
5138
|
patchSession,
|
|
5139
|
+
readUiBridgeSecret,
|
|
4834
5140
|
startUiServer,
|
|
4835
5141
|
testProviderConnection,
|
|
4836
5142
|
updateChannel,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextclaw/server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Nextclaw UI/API server.",
|
|
6
6
|
"type": "module",
|
|
@@ -18,11 +18,12 @@
|
|
|
18
18
|
"@hono/node-server": "^1.13.3",
|
|
19
19
|
"hono": "^4.6.2",
|
|
20
20
|
"ws": "^8.18.0",
|
|
21
|
-
"@nextclaw/ncp": "0.3.1",
|
|
22
21
|
"@nextclaw/core": "0.9.2",
|
|
23
|
-
"@nextclaw/runtime": "0.2.2",
|
|
24
22
|
"@nextclaw/ncp-http-agent-server": "0.3.1",
|
|
25
|
-
"@nextclaw/
|
|
23
|
+
"@nextclaw/mcp": "0.1.1",
|
|
24
|
+
"@nextclaw/ncp": "0.3.1",
|
|
25
|
+
"@nextclaw/openclaw-compat": "0.3.5",
|
|
26
|
+
"@nextclaw/runtime": "0.2.2"
|
|
26
27
|
},
|
|
27
28
|
"devDependencies": {
|
|
28
29
|
"@types/node": "^20.17.6",
|