@nextclaw/server 0.12.12 → 0.12.13-beta.1
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 +25 -4
- package/dist/index.js +171 -81
- package/package.json +8 -7
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { Config, ConfigActionExecuteRequest as ConfigActionExecuteRequest$1, Con
|
|
|
4
4
|
import { NcpHttpAgentStreamProvider } from "@nextclaw/ncp-http-agent-server";
|
|
5
5
|
import { PluginChannelBinding, PluginUiMetadata } from "@nextclaw/openclaw-compat";
|
|
6
6
|
import { NcpAgentClientEndpoint, NcpMessage, NcpSessionApi, NcpSessionStatus, NcpSessionSummary } from "@nextclaw/ncp";
|
|
7
|
+
import { UpdatePreferences, UpdateSnapshot } from "@nextclaw/kernel/update-contract";
|
|
7
8
|
import { IncomingMessage } from "node:http";
|
|
8
9
|
|
|
9
10
|
//#region src/ui/ncp-attachment.types.d.ts
|
|
@@ -191,6 +192,7 @@ type MarketplaceMcpInstallRequest = {
|
|
|
191
192
|
inputs?: Record<string, string>;
|
|
192
193
|
template?: MarketplaceMcpInstallSpec;
|
|
193
194
|
};
|
|
195
|
+
type MarketplaceInstallRequest = MarketplacePluginInstallRequest | MarketplaceSkillInstallRequest | MarketplaceMcpInstallRequest;
|
|
194
196
|
type MarketplacePluginInstallResult = {
|
|
195
197
|
type: "plugin";
|
|
196
198
|
spec: string;
|
|
@@ -210,9 +212,11 @@ type MarketplaceMcpInstallResult = {
|
|
|
210
212
|
message: string;
|
|
211
213
|
output?: string;
|
|
212
214
|
};
|
|
215
|
+
type MarketplaceInstallResult = MarketplacePluginInstallResult | MarketplaceSkillInstallResult | MarketplaceMcpInstallResult;
|
|
213
216
|
type MarketplacePluginManageAction = "enable" | "disable" | "uninstall";
|
|
214
217
|
type MarketplaceSkillManageAction = "uninstall";
|
|
215
218
|
type MarketplaceMcpManageAction = "enable" | "disable" | "remove";
|
|
219
|
+
type MarketplaceManageAction = MarketplacePluginManageAction | MarketplaceSkillManageAction | MarketplaceMcpManageAction;
|
|
216
220
|
type MarketplacePluginManageRequest = {
|
|
217
221
|
type?: "plugin";
|
|
218
222
|
action: MarketplacePluginManageAction;
|
|
@@ -231,6 +235,7 @@ type MarketplaceMcpManageRequest = {
|
|
|
231
235
|
id?: string;
|
|
232
236
|
spec?: string;
|
|
233
237
|
};
|
|
238
|
+
type MarketplaceManageRequest = MarketplacePluginManageRequest | MarketplaceSkillManageRequest | MarketplaceMcpManageRequest;
|
|
234
239
|
type MarketplacePluginManageResult = {
|
|
235
240
|
type: "plugin";
|
|
236
241
|
action: MarketplacePluginManageAction;
|
|
@@ -252,6 +257,7 @@ type MarketplaceMcpManageResult = {
|
|
|
252
257
|
message: string;
|
|
253
258
|
output?: string;
|
|
254
259
|
};
|
|
260
|
+
type MarketplaceManageResult = MarketplacePluginManageResult | MarketplaceSkillManageResult | MarketplaceMcpManageResult;
|
|
255
261
|
type MarketplaceMcpDoctorResult = {
|
|
256
262
|
name: string;
|
|
257
263
|
enabled: boolean;
|
|
@@ -401,6 +407,7 @@ type UiRouterOptions = {
|
|
|
401
407
|
authService?: UiAuthService;
|
|
402
408
|
remoteAccess?: UiRemoteAccessHost;
|
|
403
409
|
runtimeControl?: UiRuntimeControlHost;
|
|
410
|
+
runtimeUpdate?: UiRuntimeUpdateHost;
|
|
404
411
|
getBootstrapStatus?: () => BootstrapStatusView;
|
|
405
412
|
getPluginChannelBindings?: () => PluginChannelBinding[];
|
|
406
413
|
getPluginUiMetadata?: () => PluginUiMetadata[];
|
|
@@ -422,6 +429,14 @@ type UiRuntimeControlHost = {
|
|
|
422
429
|
restartService: () => Promise<RuntimeControlActionResult> | RuntimeControlActionResult;
|
|
423
430
|
stopService: () => Promise<RuntimeControlActionResult> | RuntimeControlActionResult;
|
|
424
431
|
};
|
|
432
|
+
type UiRuntimeUpdateHost = {
|
|
433
|
+
getState: () => Promise<UpdateSnapshot> | UpdateSnapshot;
|
|
434
|
+
checkForUpdates: () => Promise<UpdateSnapshot> | UpdateSnapshot;
|
|
435
|
+
downloadUpdate: () => Promise<UpdateSnapshot> | UpdateSnapshot;
|
|
436
|
+
applyDownloadedUpdate: () => Promise<UpdateSnapshot> | UpdateSnapshot;
|
|
437
|
+
updatePreferences: (preferences: Partial<UpdatePreferences>) => Promise<UpdateSnapshot> | UpdateSnapshot;
|
|
438
|
+
updateChannel: (channel: UpdateSnapshot["channel"]) => Promise<UpdateSnapshot> | UpdateSnapshot;
|
|
439
|
+
};
|
|
425
440
|
//#endregion
|
|
426
441
|
//#region src/ui/chat-session-type.types.d.ts
|
|
427
442
|
type ChatSessionTypeIconView = {
|
|
@@ -989,6 +1004,9 @@ type CronActionResult = {
|
|
|
989
1004
|
executed?: boolean;
|
|
990
1005
|
};
|
|
991
1006
|
type RuntimeConfigUpdate = {
|
|
1007
|
+
companion?: {
|
|
1008
|
+
enabled?: boolean;
|
|
1009
|
+
};
|
|
992
1010
|
agents?: {
|
|
993
1011
|
defaults?: {
|
|
994
1012
|
contextTokens?: number;
|
|
@@ -1077,6 +1095,9 @@ type UiNcpAgent = {
|
|
|
1077
1095
|
basePath?: string;
|
|
1078
1096
|
};
|
|
1079
1097
|
type ConfigView = {
|
|
1098
|
+
companion?: {
|
|
1099
|
+
enabled?: boolean;
|
|
1100
|
+
};
|
|
1080
1101
|
agents: {
|
|
1081
1102
|
defaults: {
|
|
1082
1103
|
model: string;
|
|
@@ -1094,7 +1115,6 @@ type ConfigView = {
|
|
|
1094
1115
|
bootstrap?: {
|
|
1095
1116
|
files?: string[];
|
|
1096
1117
|
minimalFiles?: string[];
|
|
1097
|
-
heartbeatFiles?: string[];
|
|
1098
1118
|
perFileChars?: number;
|
|
1099
1119
|
totalChars?: number;
|
|
1100
1120
|
};
|
|
@@ -1318,8 +1338,9 @@ type UiServerHandle = {
|
|
|
1318
1338
|
//#region src/ui/server.d.ts
|
|
1319
1339
|
type UiServerStartOptions = UiServerOptions & {
|
|
1320
1340
|
applyLiveConfigReload?: () => Promise<void>;
|
|
1341
|
+
runtimeUpdate?: UiRuntimeUpdateHost;
|
|
1321
1342
|
};
|
|
1322
|
-
declare function startUiServer(options: UiServerStartOptions): UiServerHandle
|
|
1343
|
+
declare function startUiServer(options: UiServerStartOptions): Promise<UiServerHandle>;
|
|
1323
1344
|
//#endregion
|
|
1324
1345
|
//#region src/ui/router.d.ts
|
|
1325
1346
|
declare function createUiRouter(options: UiRouterOptions): Hono;
|
|
@@ -1375,7 +1396,7 @@ declare function patchSession(configPath: string, key: string, patch: SessionPat
|
|
|
1375
1396
|
availableSessionTypes?: string[];
|
|
1376
1397
|
}): SessionHistoryView | null;
|
|
1377
1398
|
declare function deleteSession(configPath: string, key: string): boolean;
|
|
1378
|
-
declare function updateRuntime(configPath: string, patch: RuntimeConfigUpdate): Pick<ConfigView, "agents" | "bindings" | "session">;
|
|
1399
|
+
declare function updateRuntime(configPath: string, patch: RuntimeConfigUpdate): Pick<ConfigView, "companion" | "agents" | "bindings" | "session">;
|
|
1379
1400
|
declare function updateSecrets(configPath: string, patch: SecretsConfigUpdate): SecretsView;
|
|
1380
1401
|
//#endregion
|
|
1381
1402
|
//#region src/ui/auth-bridge.d.ts
|
|
@@ -1383,4 +1404,4 @@ declare function getUiBridgeSecretPath(): string;
|
|
|
1383
1404
|
declare function readUiBridgeSecret(): string | null;
|
|
1384
1405
|
declare function ensureUiBridgeSecret(): string;
|
|
1385
1406
|
//#endregion
|
|
1386
|
-
export { AgentBindingView, AgentCreateRequest, AgentDeleteResult, AgentProfileView, AgentUpdateRequest, ApiError, ApiResponse, AppMetaView, AuthEnabledUpdateRequest, AuthLoginRequest, AuthPasswordUpdateRequest, AuthSetupRequest, AuthStatusView, BindingPeerView, BochaFreshnessValue, BootstrapPhase, BootstrapRemoteState, BootstrapStageState, BootstrapStatusView, ChannelAuthPollRequest, ChannelAuthPollResult, ChannelAuthStartRequest, ChannelAuthStartResult, ChannelSpecView, type ChatSessionTypeCtaView, type ChatSessionTypeOptionView, type ChatSessionTypesView, ConfigActionExecuteRequest, ConfigActionExecuteResult, ConfigActionManifest, ConfigActionType, ConfigMetaView, ConfigSchemaResponse, ConfigUiHint, ConfigUiHints, ConfigView, CronActionResult, CronCreateRequest, CronCreateResult, CronEnableRequest, CronJobStateView, CronJobView, CronListView, CronPayloadView, CronRunRequest, CronScheduleView, DEFAULT_SESSION_TYPE, MarketplaceApiConfig, MarketplaceInstallKind, MarketplaceInstallSkillParams, MarketplaceInstallSpec, MarketplaceInstalledRecord, MarketplaceInstalledView, MarketplaceInstaller, MarketplaceItemSummary, MarketplaceItemType, MarketplaceItemView, MarketplaceListView, MarketplaceLocalizedTextMap, MarketplaceMcpContentView, MarketplaceMcpDoctorResult, MarketplaceMcpInstallKind, MarketplaceMcpInstallRequest, MarketplaceMcpInstallResult, MarketplaceMcpInstallSpec, MarketplaceMcpManageAction, MarketplaceMcpManageRequest, MarketplaceMcpManageResult, MarketplaceMcpTemplateInput, MarketplacePluginContentView, MarketplacePluginInstallKind, MarketplacePluginInstallRequest, MarketplacePluginInstallResult, MarketplacePluginManageAction, MarketplacePluginManageRequest, MarketplacePluginManageResult, MarketplaceRecommendationView, MarketplaceSkillContentView, MarketplaceSkillInstallKind, MarketplaceSkillInstallRequest, MarketplaceSkillInstallResult, MarketplaceSkillManageAction, MarketplaceSkillManageRequest, MarketplaceSkillManageResult, MarketplaceSort, NcpSessionSkillsView, ProviderAuthImportResult, ProviderAuthPollRequest, ProviderAuthPollResult, ProviderAuthStartRequest, ProviderAuthStartResult, ProviderConfigUpdate, ProviderConfigView, ProviderConnectionTestRequest, ProviderConnectionTestResult, ProviderCreateRequest, ProviderCreateResult, ProviderDeleteResult, ProviderSpecView, RemoteAccessView, RemoteAccountProfileUpdateRequest, RemoteAccountView, RemoteBrowserAuthPollRequest, RemoteBrowserAuthPollResult, RemoteBrowserAuthStartRequest, RemoteBrowserAuthStartResult, RemoteDoctorCheckView, RemoteDoctorView, RemoteLoginRequest, RemoteRuntimeView, RemoteServiceAction, RemoteServiceActionResult, RemoteServiceView, RemoteSettingsUpdateRequest, RemoteSettingsView, RuntimeActionCapability, RuntimeActionImpact, RuntimeConfigUpdate, RuntimeControlAction, RuntimeControlActionResult, RuntimeControlEnvironment, RuntimeControlView, RuntimeEntryView, RuntimeLifecycleState, RuntimePendingRestart, RuntimeServiceState, SearchConfigUpdate, SearchConfigView, SearchProviderConfigView, SearchProviderName, SearchProviderSpecView, SecretProviderEnvView, SecretProviderExecView, SecretProviderFileView, SecretProviderView, SecretRefView, SecretSourceView, SecretsConfigUpdate, SecretsView, ServerPathBreadcrumbView, ServerPathBrowseView, ServerPathEntryView, ServerPathReadView, SessionConfigView, SessionEntryView, SessionEventView, SessionHistoryView, SessionMessageView, SessionPatchUpdate, SessionPatchValidationError, SessionSkillEntryView, SessionTypeDescribeParams, SessionsListView, TavilySearchDepthValue, UiNcpAgent, UiNcpAssetPutView, UiNcpAssetView, UiNcpSessionListView, UiNcpSessionMessagesView, UiNcpSessionService, UiNcpStoredAssetRecord, type UiRemoteAccessHost, type UiRuntimeControlHost, UiServerEvent, UiServerHandle, UiServerOptions, buildConfigMeta, buildConfigSchemaView, buildConfigView, createCustomProvider, createUiRouter, deleteCustomProvider, deleteSession, ensureUiBridgeSecret, executeConfigAction, getSessionHistory, getUiBridgeSecretPath, listSessions, loadConfigOrDefault, patchSession, readUiBridgeSecret, startUiServer, testProviderConnection, updateChannel, updateModel, updateProvider, updateRuntime, updateSearch, updateSecrets };
|
|
1407
|
+
export { AgentBindingView, AgentCreateRequest, AgentDeleteResult, AgentProfileView, AgentUpdateRequest, ApiError, ApiResponse, AppMetaView, AuthEnabledUpdateRequest, AuthLoginRequest, AuthPasswordUpdateRequest, AuthSetupRequest, AuthStatusView, BindingPeerView, BochaFreshnessValue, BootstrapPhase, BootstrapRemoteState, BootstrapStageState, BootstrapStatusView, ChannelAuthPollRequest, ChannelAuthPollResult, ChannelAuthStartRequest, ChannelAuthStartResult, ChannelSpecView, type ChatSessionTypeCtaView, type ChatSessionTypeOptionView, type ChatSessionTypesView, ConfigActionExecuteRequest, ConfigActionExecuteResult, ConfigActionManifest, ConfigActionType, ConfigMetaView, ConfigSchemaResponse, ConfigUiHint, ConfigUiHints, ConfigView, CronActionResult, CronCreateRequest, CronCreateResult, CronEnableRequest, CronJobStateView, CronJobView, CronListView, CronPayloadView, CronRunRequest, CronScheduleView, DEFAULT_SESSION_TYPE, MarketplaceApiConfig, MarketplaceInstallKind, MarketplaceInstallRequest, MarketplaceInstallResult, MarketplaceInstallSkillParams, MarketplaceInstallSpec, MarketplaceInstalledRecord, MarketplaceInstalledView, MarketplaceInstaller, MarketplaceItemSummary, MarketplaceItemType, MarketplaceItemView, MarketplaceListView, MarketplaceLocalizedTextMap, MarketplaceManageAction, MarketplaceManageRequest, MarketplaceManageResult, MarketplaceMcpContentView, MarketplaceMcpDoctorResult, MarketplaceMcpInstallKind, MarketplaceMcpInstallRequest, MarketplaceMcpInstallResult, MarketplaceMcpInstallSpec, MarketplaceMcpManageAction, MarketplaceMcpManageRequest, MarketplaceMcpManageResult, MarketplaceMcpTemplateInput, MarketplacePluginContentView, MarketplacePluginInstallKind, MarketplacePluginInstallRequest, MarketplacePluginInstallResult, MarketplacePluginManageAction, MarketplacePluginManageRequest, MarketplacePluginManageResult, MarketplaceRecommendationView, MarketplaceSkillContentView, MarketplaceSkillInstallKind, MarketplaceSkillInstallRequest, MarketplaceSkillInstallResult, MarketplaceSkillManageAction, MarketplaceSkillManageRequest, MarketplaceSkillManageResult, MarketplaceSort, NcpSessionSkillsView, ProviderAuthImportResult, ProviderAuthPollRequest, ProviderAuthPollResult, ProviderAuthStartRequest, ProviderAuthStartResult, ProviderConfigUpdate, ProviderConfigView, ProviderConnectionTestRequest, ProviderConnectionTestResult, ProviderCreateRequest, ProviderCreateResult, ProviderDeleteResult, ProviderSpecView, RemoteAccessView, RemoteAccountProfileUpdateRequest, RemoteAccountView, RemoteBrowserAuthPollRequest, RemoteBrowserAuthPollResult, RemoteBrowserAuthStartRequest, RemoteBrowserAuthStartResult, RemoteDoctorCheckView, RemoteDoctorView, RemoteLoginRequest, RemoteRuntimeView, RemoteServiceAction, RemoteServiceActionResult, RemoteServiceView, RemoteSettingsUpdateRequest, RemoteSettingsView, RuntimeActionCapability, RuntimeActionImpact, RuntimeConfigUpdate, RuntimeControlAction, RuntimeControlActionResult, RuntimeControlEnvironment, RuntimeControlView, RuntimeEntryView, RuntimeLifecycleState, RuntimePendingRestart, RuntimeServiceState, SearchConfigUpdate, SearchConfigView, SearchProviderConfigView, SearchProviderName, SearchProviderSpecView, SecretProviderEnvView, SecretProviderExecView, SecretProviderFileView, SecretProviderView, SecretRefView, SecretSourceView, SecretsConfigUpdate, SecretsView, ServerPathBreadcrumbView, ServerPathBrowseView, ServerPathEntryView, ServerPathReadView, SessionConfigView, SessionEntryView, SessionEventView, SessionHistoryView, SessionMessageView, SessionPatchUpdate, SessionPatchValidationError, SessionSkillEntryView, SessionTypeDescribeParams, SessionsListView, TavilySearchDepthValue, UiNcpAgent, UiNcpAssetPutView, UiNcpAssetView, UiNcpSessionListView, UiNcpSessionMessagesView, UiNcpSessionService, UiNcpStoredAssetRecord, type UiRemoteAccessHost, type UiRuntimeControlHost, type UiRuntimeUpdateHost, UiServerEvent, UiServerHandle, 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
|
@@ -1332,6 +1332,7 @@ function buildConfigView(config, options) {
|
|
|
1332
1332
|
const providers = {};
|
|
1333
1333
|
for (const [name, provider] of Object.entries(config.providers)) providers[name] = toProviderView(config, provider, name, uiHints, findServerBuiltinProviderByName(name));
|
|
1334
1334
|
return {
|
|
1335
|
+
companion: sanitizePublicConfigValue(config.companion, "companion", uiHints),
|
|
1335
1336
|
agents: sanitizePublicConfigValue(config.agents, "agents", uiHints),
|
|
1336
1337
|
providers,
|
|
1337
1338
|
search: buildSearchView(config),
|
|
@@ -1907,18 +1908,22 @@ function deleteSession(configPath, key) {
|
|
|
1907
1908
|
if (!normalizedKey) return false;
|
|
1908
1909
|
return createSessionManager(loadConfigOrDefault(configPath)).delete(normalizedKey);
|
|
1909
1910
|
}
|
|
1910
|
-
function
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
if (defaultsPatch && Object.prototype.hasOwnProperty.call(defaultsPatch, "contextTokens")) {
|
|
1911
|
+
function applyRuntimeAgentDefaultsPatch(config, defaultsPatch) {
|
|
1912
|
+
if (!defaultsPatch) return;
|
|
1913
|
+
if (Object.prototype.hasOwnProperty.call(defaultsPatch, "contextTokens")) {
|
|
1914
1914
|
const nextContextTokens = defaultsPatch.contextTokens;
|
|
1915
1915
|
if (typeof nextContextTokens === "number" && Number.isFinite(nextContextTokens)) config.agents.defaults.contextTokens = Math.max(1e3, Math.trunc(nextContextTokens));
|
|
1916
1916
|
}
|
|
1917
|
-
if (
|
|
1918
|
-
if (
|
|
1917
|
+
if (Object.prototype.hasOwnProperty.call(defaultsPatch, "engine")) config.agents.defaults.engine = normalizeOptionalString(defaultsPatch.engine) ?? "native";
|
|
1918
|
+
if (Object.prototype.hasOwnProperty.call(defaultsPatch, "engineConfig")) {
|
|
1919
1919
|
const nextEngineConfig = defaultsPatch.engineConfig;
|
|
1920
1920
|
if (nextEngineConfig && typeof nextEngineConfig === "object" && !Array.isArray(nextEngineConfig)) config.agents.defaults.engineConfig = { ...nextEngineConfig };
|
|
1921
1921
|
}
|
|
1922
|
+
}
|
|
1923
|
+
function updateRuntime(configPath, patch) {
|
|
1924
|
+
const config = loadConfigOrDefault(configPath);
|
|
1925
|
+
if (patch.companion && Object.prototype.hasOwnProperty.call(patch.companion, "enabled")) config.companion.enabled = Boolean(patch.companion.enabled);
|
|
1926
|
+
applyRuntimeAgentDefaultsPatch(config, patch.agents?.defaults);
|
|
1922
1927
|
if (patch.agents && Object.prototype.hasOwnProperty.call(patch.agents, "list")) config.agents.list = (patch.agents.list ?? []).map((entry) => {
|
|
1923
1928
|
const normalizedEngine = normalizeOptionalString(entry.engine);
|
|
1924
1929
|
const hasEngineConfig = entry.engineConfig && typeof entry.engineConfig === "object" && !Array.isArray(entry.engineConfig);
|
|
@@ -1939,6 +1944,7 @@ function updateRuntime(configPath, patch) {
|
|
|
1939
1944
|
saveConfig(next, configPath);
|
|
1940
1945
|
const view = buildConfigView(next);
|
|
1941
1946
|
return {
|
|
1947
|
+
companion: view.companion,
|
|
1942
1948
|
agents: view.agents,
|
|
1943
1949
|
bindings: view.bindings ?? [],
|
|
1944
1950
|
session: view.session ?? {}
|
|
@@ -2707,6 +2713,7 @@ var ConfigRoutesController = class {
|
|
|
2707
2713
|
if (body.data.agents?.defaults && Object.prototype.hasOwnProperty.call(body.data.agents.defaults, "engine")) changedPaths.push("agents.defaults.engine");
|
|
2708
2714
|
if (body.data.agents?.defaults && Object.prototype.hasOwnProperty.call(body.data.agents.defaults, "engineConfig")) changedPaths.push("agents.defaults.engineConfig");
|
|
2709
2715
|
if (body.data.agents?.runtimes && Object.prototype.hasOwnProperty.call(body.data.agents.runtimes, "entries")) changedPaths.push("agents.runtimes.entries");
|
|
2716
|
+
if (body.data.companion && Object.prototype.hasOwnProperty.call(body.data.companion, "enabled")) changedPaths.push("companion.enabled");
|
|
2710
2717
|
changedPaths.push("agents.list", "bindings", "session");
|
|
2711
2718
|
await this.publishConfigUpdates(changedPaths);
|
|
2712
2719
|
return c.json(ok(result));
|
|
@@ -3207,6 +3214,7 @@ var NcpSessionRoutesController = class {
|
|
|
3207
3214
|
sessionId,
|
|
3208
3215
|
status: session.status ?? "idle",
|
|
3209
3216
|
messages,
|
|
3217
|
+
...session.contextWindow ? { contextWindow: session.contextWindow } : {},
|
|
3210
3218
|
total: messages.length
|
|
3211
3219
|
};
|
|
3212
3220
|
return c.json(ok(payload));
|
|
@@ -4530,6 +4538,64 @@ var RuntimeControlRoutesController = class {
|
|
|
4530
4538
|
};
|
|
4531
4539
|
};
|
|
4532
4540
|
//#endregion
|
|
4541
|
+
//#region src/ui/ui-routes/runtime-update.controller.ts
|
|
4542
|
+
var RuntimeUpdateRoutesController = class {
|
|
4543
|
+
constructor(host) {
|
|
4544
|
+
this.host = host;
|
|
4545
|
+
}
|
|
4546
|
+
getState = async (c) => {
|
|
4547
|
+
try {
|
|
4548
|
+
return c.json(ok(await this.host.getState()));
|
|
4549
|
+
} catch (error) {
|
|
4550
|
+
return c.json(err("RUNTIME_UPDATE_STATE_FAILED", formatUserFacingError(error)), 500);
|
|
4551
|
+
}
|
|
4552
|
+
};
|
|
4553
|
+
checkForUpdates = async (c) => {
|
|
4554
|
+
try {
|
|
4555
|
+
return c.json(ok(await this.host.checkForUpdates()));
|
|
4556
|
+
} catch (error) {
|
|
4557
|
+
return c.json(err("RUNTIME_UPDATE_CHECK_FAILED", formatUserFacingError(error)), 400);
|
|
4558
|
+
}
|
|
4559
|
+
};
|
|
4560
|
+
downloadUpdate = async (c) => {
|
|
4561
|
+
try {
|
|
4562
|
+
return c.json(ok(await this.host.downloadUpdate()));
|
|
4563
|
+
} catch (error) {
|
|
4564
|
+
return c.json(err("RUNTIME_UPDATE_DOWNLOAD_FAILED", formatUserFacingError(error)), 400);
|
|
4565
|
+
}
|
|
4566
|
+
};
|
|
4567
|
+
applyDownloadedUpdate = async (c) => {
|
|
4568
|
+
try {
|
|
4569
|
+
return c.json(ok(await this.host.applyDownloadedUpdate()));
|
|
4570
|
+
} catch (error) {
|
|
4571
|
+
return c.json(err("RUNTIME_UPDATE_APPLY_FAILED", formatUserFacingError(error)), 400);
|
|
4572
|
+
}
|
|
4573
|
+
};
|
|
4574
|
+
updatePreferences = async (c) => {
|
|
4575
|
+
const body = await readJson(c.req.raw);
|
|
4576
|
+
if (!body.ok) return c.json(err("INVALID_BODY", "invalid json body"), 400);
|
|
4577
|
+
try {
|
|
4578
|
+
return c.json(ok(await this.host.updatePreferences({
|
|
4579
|
+
...typeof body.data.automaticChecks === "boolean" ? { automaticChecks: body.data.automaticChecks } : {},
|
|
4580
|
+
...typeof body.data.autoDownload === "boolean" ? { autoDownload: body.data.autoDownload } : {}
|
|
4581
|
+
})));
|
|
4582
|
+
} catch (error) {
|
|
4583
|
+
return c.json(err("RUNTIME_UPDATE_PREFERENCES_FAILED", formatUserFacingError(error)), 400);
|
|
4584
|
+
}
|
|
4585
|
+
};
|
|
4586
|
+
updateChannel = async (c) => {
|
|
4587
|
+
const body = await readJson(c.req.raw);
|
|
4588
|
+
if (!body.ok) return c.json(err("INVALID_BODY", "invalid json body"), 400);
|
|
4589
|
+
const channel = body.data.channel;
|
|
4590
|
+
if (channel !== "stable" && channel !== "beta") return c.json(err("INVALID_BODY", "channel must be stable or beta"), 400);
|
|
4591
|
+
try {
|
|
4592
|
+
return c.json(ok(await this.host.updateChannel(channel)));
|
|
4593
|
+
} catch (error) {
|
|
4594
|
+
return c.json(err("RUNTIME_UPDATE_CHANNEL_FAILED", formatUserFacingError(error)), 400);
|
|
4595
|
+
}
|
|
4596
|
+
};
|
|
4597
|
+
};
|
|
4598
|
+
//#endregion
|
|
4533
4599
|
//#region src/ui/server-path/server-path-browse.utils.ts
|
|
4534
4600
|
var ServerPathBrowseError = class extends Error {
|
|
4535
4601
|
constructor(code, message) {
|
|
@@ -4866,7 +4932,17 @@ function registerRuntimeControlRoutes(app, runtimeControlController) {
|
|
|
4866
4932
|
app.post("/api/runtime/control/restart-service", runtimeControlController.restartService);
|
|
4867
4933
|
app.post("/api/runtime/control/stop-service", runtimeControlController.stopService);
|
|
4868
4934
|
}
|
|
4935
|
+
function registerRuntimeUpdateRoutes(app, runtimeUpdateController) {
|
|
4936
|
+
if (!runtimeUpdateController) return;
|
|
4937
|
+
app.get("/api/runtime/update", runtimeUpdateController.getState);
|
|
4938
|
+
app.post("/api/runtime/update/check", runtimeUpdateController.checkForUpdates);
|
|
4939
|
+
app.post("/api/runtime/update/download", runtimeUpdateController.downloadUpdate);
|
|
4940
|
+
app.post("/api/runtime/update/apply", runtimeUpdateController.applyDownloadedUpdate);
|
|
4941
|
+
app.put("/api/runtime/update/preferences", runtimeUpdateController.updatePreferences);
|
|
4942
|
+
app.put("/api/runtime/update/channel", runtimeUpdateController.updateChannel);
|
|
4943
|
+
}
|
|
4869
4944
|
function createUiRouteControllers(options, authService, marketplaceBaseUrl) {
|
|
4945
|
+
const { remoteAccess, runtimeControl, runtimeUpdate } = options;
|
|
4870
4946
|
return {
|
|
4871
4947
|
app: new AppRoutesController(options),
|
|
4872
4948
|
agents: new AgentsRoutesController(options),
|
|
@@ -4876,8 +4952,9 @@ function createUiRouteControllers(options, authService, marketplaceBaseUrl) {
|
|
|
4876
4952
|
ncpSession: new NcpSessionRoutesController(options),
|
|
4877
4953
|
ncpAsset: new NcpAssetRoutesController(options),
|
|
4878
4954
|
serverPath: new ServerPathRoutesController(),
|
|
4879
|
-
remote:
|
|
4880
|
-
runtimeControl:
|
|
4955
|
+
remote: remoteAccess ? new RemoteRoutesController(remoteAccess) : null,
|
|
4956
|
+
runtimeControl: runtimeControl ? new RuntimeControlRoutesController(runtimeControl) : null,
|
|
4957
|
+
runtimeUpdate: runtimeUpdate ? new RuntimeUpdateRoutesController(runtimeUpdate) : null,
|
|
4881
4958
|
pluginMarketplace: new PluginMarketplaceController(options, marketplaceBaseUrl),
|
|
4882
4959
|
skillMarketplace: new SkillMarketplaceController(options, marketplaceBaseUrl),
|
|
4883
4960
|
mcpMarketplace: new McpMarketplaceController(options, marketplaceBaseUrl)
|
|
@@ -4914,6 +4991,7 @@ function createUiRouter(options) {
|
|
|
4914
4991
|
registerCronRoutes(app, controllers.cron);
|
|
4915
4992
|
registerRemoteRoutes(app, controllers.remote);
|
|
4916
4993
|
registerRuntimeControlRoutes(app, controllers.runtimeControl);
|
|
4994
|
+
registerRuntimeUpdateRoutes(app, controllers.runtimeUpdate);
|
|
4917
4995
|
mountMarketplaceRoutes(app, {
|
|
4918
4996
|
plugin: controllers.pluginMarketplace,
|
|
4919
4997
|
skill: controllers.skillMarketplace,
|
|
@@ -4956,11 +5034,66 @@ function applyCorsHeaders(params) {
|
|
|
4956
5034
|
appendVaryHeader(params.headers, "Origin");
|
|
4957
5035
|
appendVaryHeader(params.headers, "Access-Control-Request-Headers");
|
|
4958
5036
|
}
|
|
4959
|
-
function
|
|
5037
|
+
function createUiEventPublisher(clients) {
|
|
5038
|
+
return (event) => {
|
|
5039
|
+
const payload = JSON.stringify(event);
|
|
5040
|
+
for (const client of clients) if (client.readyState === WebSocket.OPEN) client.send(payload);
|
|
5041
|
+
};
|
|
5042
|
+
}
|
|
5043
|
+
function mountUiStaticAssets(app, staticDir) {
|
|
5044
|
+
if (!existsSync(join(staticDir, "index.html"))) return;
|
|
5045
|
+
const indexHtml = readFileSync(join(staticDir, "index.html"), "utf-8");
|
|
5046
|
+
app.use("/*", serveStatic({
|
|
5047
|
+
root: staticDir,
|
|
5048
|
+
join,
|
|
5049
|
+
getContent: async (path) => {
|
|
5050
|
+
try {
|
|
5051
|
+
return await readFile(path);
|
|
5052
|
+
} catch {
|
|
5053
|
+
return null;
|
|
5054
|
+
}
|
|
5055
|
+
},
|
|
5056
|
+
isDir: async (path) => {
|
|
5057
|
+
try {
|
|
5058
|
+
return (await stat(path)).isDirectory();
|
|
5059
|
+
} catch {
|
|
5060
|
+
return false;
|
|
5061
|
+
}
|
|
5062
|
+
}
|
|
5063
|
+
}));
|
|
5064
|
+
app.get("*", (c) => {
|
|
5065
|
+
const path = c.req.path;
|
|
5066
|
+
if (path.startsWith("/api") || path.startsWith("/ws") || path.startsWith("/_remote")) return c.notFound();
|
|
5067
|
+
return c.html(indexHtml);
|
|
5068
|
+
});
|
|
5069
|
+
}
|
|
5070
|
+
function attachUiSocketServer(httpServer, authService, clients) {
|
|
5071
|
+
const wss = new WebSocketServer({ noServer: true });
|
|
5072
|
+
httpServer.on("upgrade", (request, socket, head) => {
|
|
5073
|
+
const host = request.headers.host ?? "127.0.0.1";
|
|
5074
|
+
const url = request.url ?? "/";
|
|
5075
|
+
if (new URL(url, `http://${host}`).pathname !== "/ws") return;
|
|
5076
|
+
if (!authService.isSocketAuthenticated(request)) {
|
|
5077
|
+
socket.write("HTTP/1.1 401 Unauthorized\r\nConnection: close\r\n\r\n");
|
|
5078
|
+
socket.destroy();
|
|
5079
|
+
return;
|
|
5080
|
+
}
|
|
5081
|
+
wss.handleUpgrade(request, socket, head, (ws) => {
|
|
5082
|
+
wss.emit("connection", ws, request);
|
|
5083
|
+
});
|
|
5084
|
+
});
|
|
5085
|
+
wss.on("connection", (socket) => {
|
|
5086
|
+
clients.add(socket);
|
|
5087
|
+
socket.on("close", () => clients.delete(socket));
|
|
5088
|
+
});
|
|
5089
|
+
return wss;
|
|
5090
|
+
}
|
|
5091
|
+
async function startUiServer(options) {
|
|
5092
|
+
const { applyLiveConfigReload, configPath, corsOrigins, cronService, getBootstrapStatus, getPluginChannelBindings, getPluginUiMetadata, host, initializeAgentHomeDirectory, marketplace, ncpAgent, ncpSessionService, port, productVersion, remoteAccess, runtimeControl, runtimeUpdate, staticDir } = options;
|
|
4960
5093
|
const app = new Hono();
|
|
4961
5094
|
app.use("/*", compress());
|
|
4962
|
-
const corsPolicy =
|
|
4963
|
-
const authService = new UiAuthService(
|
|
5095
|
+
const corsPolicy = corsOrigins ?? DEFAULT_CORS_ORIGINS;
|
|
5096
|
+
const authService = new UiAuthService(configPath);
|
|
4964
5097
|
app.use("/api/*", async (c, next) => {
|
|
4965
5098
|
const allowOrigin = resolveAllowedCorsOrigin(readRequestHeader(c.req.raw, "origin"), corsPolicy);
|
|
4966
5099
|
const allowHeaders = readRequestHeader(c.req.raw, "access-control-request-headers");
|
|
@@ -4987,86 +5120,43 @@ function startUiServer(options) {
|
|
|
4987
5120
|
});
|
|
4988
5121
|
});
|
|
4989
5122
|
const clients = /* @__PURE__ */ new Set();
|
|
4990
|
-
const publish = (
|
|
4991
|
-
const payload = JSON.stringify(event);
|
|
4992
|
-
for (const client of clients) if (client.readyState === WebSocket.OPEN) client.send(payload);
|
|
4993
|
-
};
|
|
5123
|
+
const publish = createUiEventPublisher(clients);
|
|
4994
5124
|
app.route("/", createUiRouter({
|
|
4995
|
-
configPath
|
|
4996
|
-
productVersion
|
|
5125
|
+
configPath,
|
|
5126
|
+
productVersion,
|
|
4997
5127
|
publish,
|
|
4998
|
-
applyLiveConfigReload
|
|
4999
|
-
initializeAgentHomeDirectory
|
|
5000
|
-
marketplace
|
|
5001
|
-
cronService
|
|
5002
|
-
ncpAgent
|
|
5003
|
-
ncpSessionService
|
|
5128
|
+
applyLiveConfigReload,
|
|
5129
|
+
initializeAgentHomeDirectory,
|
|
5130
|
+
marketplace,
|
|
5131
|
+
cronService,
|
|
5132
|
+
ncpAgent,
|
|
5133
|
+
ncpSessionService,
|
|
5004
5134
|
authService,
|
|
5005
|
-
remoteAccess
|
|
5006
|
-
runtimeControl
|
|
5007
|
-
|
|
5008
|
-
|
|
5009
|
-
|
|
5135
|
+
remoteAccess,
|
|
5136
|
+
runtimeControl,
|
|
5137
|
+
runtimeUpdate,
|
|
5138
|
+
getBootstrapStatus,
|
|
5139
|
+
getPluginChannelBindings,
|
|
5140
|
+
getPluginUiMetadata
|
|
5010
5141
|
}));
|
|
5011
|
-
|
|
5012
|
-
|
|
5013
|
-
const
|
|
5014
|
-
|
|
5015
|
-
|
|
5016
|
-
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
return await readFile(path);
|
|
5020
|
-
} catch {
|
|
5021
|
-
return null;
|
|
5022
|
-
}
|
|
5023
|
-
},
|
|
5024
|
-
isDir: async (path) => {
|
|
5025
|
-
try {
|
|
5026
|
-
return (await stat(path)).isDirectory();
|
|
5027
|
-
} catch {
|
|
5028
|
-
return false;
|
|
5029
|
-
}
|
|
5030
|
-
}
|
|
5031
|
-
}));
|
|
5032
|
-
app.get("*", (c) => {
|
|
5033
|
-
const path = c.req.path;
|
|
5034
|
-
if (path.startsWith("/api") || path.startsWith("/ws") || path.startsWith("/_remote")) return c.notFound();
|
|
5035
|
-
return c.html(indexHtml);
|
|
5036
|
-
});
|
|
5037
|
-
}
|
|
5038
|
-
const server = serve({
|
|
5039
|
-
fetch: app.fetch,
|
|
5040
|
-
port: options.port,
|
|
5041
|
-
hostname: options.host
|
|
5042
|
-
});
|
|
5043
|
-
const httpServer = server;
|
|
5044
|
-
const wss = new WebSocketServer({ noServer: true });
|
|
5045
|
-
httpServer.on("upgrade", (request, socket, head) => {
|
|
5046
|
-
const host = request.headers.host ?? "127.0.0.1";
|
|
5047
|
-
const url = request.url ?? "/";
|
|
5048
|
-
if (new URL(url, `http://${host}`).pathname !== "/ws") return;
|
|
5049
|
-
if (!authService.isSocketAuthenticated(request)) {
|
|
5050
|
-
socket.write("HTTP/1.1 401 Unauthorized\r\nConnection: close\r\n\r\n");
|
|
5051
|
-
socket.destroy();
|
|
5052
|
-
return;
|
|
5053
|
-
}
|
|
5054
|
-
wss.handleUpgrade(request, socket, head, (ws) => {
|
|
5055
|
-
wss.emit("connection", ws, request);
|
|
5056
|
-
});
|
|
5057
|
-
});
|
|
5058
|
-
wss.on("connection", (socket) => {
|
|
5059
|
-
clients.add(socket);
|
|
5060
|
-
socket.on("close", () => clients.delete(socket));
|
|
5142
|
+
if (staticDir) mountUiStaticAssets(app, staticDir);
|
|
5143
|
+
const server = await new Promise((resolve, reject) => {
|
|
5144
|
+
const httpServer = serve({
|
|
5145
|
+
fetch: app.fetch,
|
|
5146
|
+
port,
|
|
5147
|
+
hostname: host
|
|
5148
|
+
}, () => resolve(httpServer));
|
|
5149
|
+
httpServer.once("error", reject);
|
|
5061
5150
|
});
|
|
5151
|
+
const wss = attachUiSocketServer(server, authService, clients);
|
|
5062
5152
|
return {
|
|
5063
|
-
host
|
|
5064
|
-
port
|
|
5153
|
+
host,
|
|
5154
|
+
port,
|
|
5065
5155
|
publish,
|
|
5066
5156
|
close: () => new Promise((resolve) => {
|
|
5067
5157
|
wss.close(() => {
|
|
5068
5158
|
server.close(() => {
|
|
5069
|
-
Promise.resolve(
|
|
5159
|
+
Promise.resolve(ncpAgent?.agentClientEndpoint.stop()).catch(() => void 0).finally(() => resolve());
|
|
5070
5160
|
});
|
|
5071
5161
|
});
|
|
5072
5162
|
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextclaw/server",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.13-beta.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Nextclaw UI/API server.",
|
|
6
6
|
"type": "module",
|
|
@@ -18,12 +18,13 @@
|
|
|
18
18
|
"@hono/node-server": "^1.13.3",
|
|
19
19
|
"hono": "^4.6.2",
|
|
20
20
|
"ws": "^8.18.0",
|
|
21
|
-
"@nextclaw/core": "0.12.
|
|
22
|
-
"@nextclaw/
|
|
23
|
-
"@nextclaw/
|
|
24
|
-
"@nextclaw/ncp
|
|
25
|
-
"@nextclaw/openclaw-compat": "1.0.
|
|
26
|
-
"@nextclaw/
|
|
21
|
+
"@nextclaw/core": "0.12.13-beta.1",
|
|
22
|
+
"@nextclaw/kernel": "0.1.2-beta.2",
|
|
23
|
+
"@nextclaw/mcp": "0.1.78-beta.1",
|
|
24
|
+
"@nextclaw/ncp": "0.5.6-beta.0",
|
|
25
|
+
"@nextclaw/openclaw-compat": "1.0.13-beta.1",
|
|
26
|
+
"@nextclaw/ncp-http-agent-server": "0.3.18-beta.1",
|
|
27
|
+
"@nextclaw/runtime": "0.2.45-beta.0"
|
|
27
28
|
},
|
|
28
29
|
"devDependencies": {
|
|
29
30
|
"@types/node": "^20.17.6",
|