@nextclaw/server 0.12.19 → 0.12.21
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 +15 -42
- package/dist/index.js +163 -81
- package/package.json +7 -8
package/dist/index.d.ts
CHANGED
|
@@ -2,10 +2,9 @@ import * as _$hono from "hono";
|
|
|
2
2
|
import { Context, Hono } from "hono";
|
|
3
3
|
import * as NextclawCore from "@nextclaw/core";
|
|
4
4
|
import { Config, ConfigActionExecuteRequest as ConfigActionExecuteRequest$1, ConfigActionExecuteResult as ConfigActionExecuteResult$1, ThinkingLevel } from "@nextclaw/core";
|
|
5
|
-
import { NcpHttpAgentStreamProvider } from "@nextclaw/ncp-http-agent-server";
|
|
6
5
|
import { PluginChannelBinding, PluginUiMetadata } from "@nextclaw/openclaw-compat";
|
|
7
|
-
import { LlmProviderManager } from "@nextclaw/kernel";
|
|
8
|
-
import {
|
|
6
|
+
import { LlmProviderManager, NextclawKernel } from "@nextclaw/kernel";
|
|
7
|
+
import { NcpMessage, NcpSessionApi, NcpSessionStatus, NcpSessionSummary } from "@nextclaw/ncp";
|
|
9
8
|
import * as _$hono_utils_http_status0 from "hono/utils/http-status";
|
|
10
9
|
import * as _$hono_utils_types0 from "hono/utils/types";
|
|
11
10
|
import { IncomingMessage } from "node:http";
|
|
@@ -67,23 +66,6 @@ declare class EventBus {
|
|
|
67
66
|
private safeInvokeGlobalListener;
|
|
68
67
|
}
|
|
69
68
|
//#endregion
|
|
70
|
-
//#region ../nextclaw-shared/src/services/ingress.service.d.ts
|
|
71
|
-
type IngressEnvelope<TPayload = unknown> = {
|
|
72
|
-
type: Key<TPayload>;
|
|
73
|
-
payload?: TPayload;
|
|
74
|
-
source?: string;
|
|
75
|
-
};
|
|
76
|
-
type IngressContext = {
|
|
77
|
-
source: string;
|
|
78
|
-
token?: string | null;
|
|
79
|
-
};
|
|
80
|
-
type IngressHandler<TPayload = unknown, TResult = unknown> = (envelope: IngressEnvelope<TPayload>, context: IngressContext) => Promise<TResult> | TResult;
|
|
81
|
-
declare class Ingress {
|
|
82
|
-
private readonly handlers;
|
|
83
|
-
readonly addHandler: <TPayload = unknown, TResult = unknown>(type: Key<TPayload>, handler: IngressHandler<TPayload, TResult>) => (() => void);
|
|
84
|
-
readonly handle: <TPayload = unknown, TResult = unknown>(envelope: IngressEnvelope<TPayload>, context: IngressContext) => Promise<TResult>;
|
|
85
|
-
}
|
|
86
|
-
//#endregion
|
|
87
69
|
//#region ../nextclaw-shared/src/types/update.types.d.ts
|
|
88
70
|
type UpdateStatus = "idle" | "checking" | "update-available" | "downloading" | "downloaded" | "applying" | "restart-required" | "up-to-date" | "blocked" | "failed";
|
|
89
71
|
type InstallationKind = "desktop-bundle" | "npm-runtime-bundle" | "npm-global" | "unknown";
|
|
@@ -122,6 +104,7 @@ type UpdateSnapshot = {
|
|
|
122
104
|
declare class NcpAssetRoutesController {
|
|
123
105
|
private readonly options;
|
|
124
106
|
constructor(options: UiRouterOptions);
|
|
107
|
+
private readonly getAssetApi;
|
|
125
108
|
readonly putAssets: (c: Context) => Promise<(Response & _$hono.TypedResponse<{
|
|
126
109
|
ok: boolean;
|
|
127
110
|
error: {
|
|
@@ -1114,21 +1097,15 @@ type SessionTypeDescribeParams = {
|
|
|
1114
1097
|
describeMode?: "observation" | "probe";
|
|
1115
1098
|
};
|
|
1116
1099
|
type UiNcpSessionService = NcpSessionApi;
|
|
1117
|
-
type
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
createdAt?: Date;
|
|
1127
|
-
}) => Promise<UiNcpStoredAssetRecord>;
|
|
1128
|
-
stat: (uri: string) => Promise<UiNcpStoredAssetRecord | null> | UiNcpStoredAssetRecord | null;
|
|
1129
|
-
resolveContentPath: (uri: string) => string | null;
|
|
1130
|
-
};
|
|
1131
|
-
basePath?: string;
|
|
1100
|
+
type UiNcpAssetService = {
|
|
1101
|
+
put: (input: {
|
|
1102
|
+
fileName: string;
|
|
1103
|
+
mimeType?: string | null;
|
|
1104
|
+
bytes: Uint8Array;
|
|
1105
|
+
createdAt?: Date;
|
|
1106
|
+
}) => Promise<UiNcpStoredAssetRecord>;
|
|
1107
|
+
stat: (uri: string) => Promise<UiNcpStoredAssetRecord | null> | UiNcpStoredAssetRecord | null;
|
|
1108
|
+
resolveContentPath: (uri: string) => string | null;
|
|
1132
1109
|
};
|
|
1133
1110
|
type ConfigView = {
|
|
1134
1111
|
companion?: {
|
|
@@ -1497,7 +1474,6 @@ type RuntimeControlActionResult = {
|
|
|
1497
1474
|
//#endregion
|
|
1498
1475
|
//#region src/app/types/router-options.types.d.ts
|
|
1499
1476
|
type UiAppEventBus = Pick<EventBus, "emit" | "subscribeAll">;
|
|
1500
|
-
type UiIngress = Pick<Ingress, "handle">;
|
|
1501
1477
|
type UiBootstrapStatusHost = {
|
|
1502
1478
|
getStatus: () => BootstrapStatusView;
|
|
1503
1479
|
};
|
|
@@ -1505,7 +1481,7 @@ type UiPluginHost = {
|
|
|
1505
1481
|
getChannelBindings: () => PluginChannelBinding[];
|
|
1506
1482
|
getUiMetadata: () => PluginUiMetadata[];
|
|
1507
1483
|
};
|
|
1508
|
-
type
|
|
1484
|
+
type UiKernelHost = Pick<NextclawKernel, "agentRuntimeManager" | "assetStore" | "ingress" | "llmProviders" | "ncpSessionApi" | "sessionRunManager">;
|
|
1509
1485
|
type UiCronHost = {
|
|
1510
1486
|
listJobs: (includeDisabled?: boolean) => CronJobEntry[];
|
|
1511
1487
|
addJob: (params: {
|
|
@@ -1525,9 +1501,9 @@ type UiCronHost = {
|
|
|
1525
1501
|
runJob: (jobId: string, force?: boolean) => Promise<boolean>;
|
|
1526
1502
|
};
|
|
1527
1503
|
type UiRouterOptions = {
|
|
1504
|
+
kernel: UiKernelHost;
|
|
1528
1505
|
configPath: string;
|
|
1529
1506
|
appEventBus: UiAppEventBus;
|
|
1530
|
-
ingress?: UiIngress;
|
|
1531
1507
|
uiConfig?: Pick<NextclawCore.Config["ui"], "enabled" | "host" | "open" | "port">;
|
|
1532
1508
|
uiStaticDir?: string | null;
|
|
1533
1509
|
corsOrigins?: string[] | "*";
|
|
@@ -1536,15 +1512,12 @@ type UiRouterOptions = {
|
|
|
1536
1512
|
initializeAgentHomeDirectory?: (homeDirectory: string) => void;
|
|
1537
1513
|
marketplace?: MarketplaceApiConfig;
|
|
1538
1514
|
cron?: UiCronHost;
|
|
1539
|
-
ncpAgent?: UiNcpAgent;
|
|
1540
|
-
sessions?: UiNcpSessionHost;
|
|
1541
1515
|
authService?: UiAuthService;
|
|
1542
1516
|
remoteAccess?: UiRemoteAccessHost;
|
|
1543
1517
|
runtimeControl?: UiRuntimeControlHost;
|
|
1544
1518
|
runtimeUpdate?: UiRuntimeUpdateHost;
|
|
1545
1519
|
bootstrapStatus?: UiBootstrapStatusHost;
|
|
1546
1520
|
plugins?: UiPluginHost;
|
|
1547
|
-
providers?: LlmProviderManager;
|
|
1548
1521
|
};
|
|
1549
1522
|
type UiRemoteAccessHost = {
|
|
1550
1523
|
getStatus: () => Promise<RemoteAccessView> | RemoteAccessView;
|
|
@@ -2497,4 +2470,4 @@ declare function updateChannel(configPath: string, channelName: string, patch: R
|
|
|
2497
2470
|
declare function updateRuntime(configPath: string, patch: RuntimeConfigUpdate): Pick<ConfigView, "companion" | "agents" | "bindings" | "session">;
|
|
2498
2471
|
declare function updateSecrets(configPath: string, patch: SecretsConfigUpdate): SecretsView;
|
|
2499
2472
|
//#endregion
|
|
2500
|
-
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, ConfigRoutesController, ConfigSchemaResponse, ConfigUiHint, ConfigUiHints, ConfigView, CronActionResult, CronCreateRequest, CronCreateResult, CronEnableRequest, CronJobStateView, CronJobView, CronListView, CronPayloadView, CronRunRequest, CronScheduleView, 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, MarketplaceSceneView, MarketplaceScenesView, MarketplaceSkillContentView, MarketplaceSkillInstallKind, MarketplaceSkillInstallRequest, MarketplaceSkillInstallResult, MarketplaceSkillManageAction, MarketplaceSkillManageRequest, MarketplaceSkillManageResult, MarketplaceSort, NcpAssetRoutesController, 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, RuntimeControlRoutesController, 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, SessionSkillEntryView, SessionTypeDescribeParams, SessionsListView, TavilySearchDepthValue,
|
|
2473
|
+
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, ConfigRoutesController, ConfigSchemaResponse, ConfigUiHint, ConfigUiHints, ConfigView, CronActionResult, CronCreateRequest, CronCreateResult, CronEnableRequest, CronJobStateView, CronJobView, CronListView, CronPayloadView, CronRunRequest, CronScheduleView, 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, MarketplaceSceneView, MarketplaceScenesView, MarketplaceSkillContentView, MarketplaceSkillInstallKind, MarketplaceSkillInstallRequest, MarketplaceSkillInstallResult, MarketplaceSkillManageAction, MarketplaceSkillManageRequest, MarketplaceSkillManageResult, MarketplaceSort, NcpAssetRoutesController, 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, RuntimeControlRoutesController, 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, SessionSkillEntryView, SessionTypeDescribeParams, SessionsListView, TavilySearchDepthValue, UiNcpAssetPutView, UiNcpAssetService, UiNcpAssetView, UiNcpSessionListView, UiNcpSessionMessagesView, UiNcpSessionService, UiNcpStoredAssetRecord, type UiRemoteAccessHost, type UiRouterOptions, type UiRuntimeControlHost, type UiRuntimeUpdateHost, UiServerEvent, UiServerHandle, buildConfigMeta, buildConfigSchemaView, buildConfigView, createCustomProvider, createUiRouter, deleteCustomProvider, ensureUiBridgeSecret, executeConfigAction, getUiBridgeSecretPath, loadConfigOrDefault, readUiBridgeSecret, startUiServer, testProviderConnection, updateChannel, updateModel, updateProvider, updateRuntime, updateSearch, updateSecrets };
|
package/dist/index.js
CHANGED
|
@@ -8,7 +8,6 @@ import path, { dirname, extname, isAbsolute, join, parse, resolve } from "node:p
|
|
|
8
8
|
import { createHash, randomBytes, randomUUID, scryptSync, timingSafeEqual } from "node:crypto";
|
|
9
9
|
import * as NextclawCore from "@nextclaw/core";
|
|
10
10
|
import { ConfigSchema, DEFAULT_WORKSPACE_PATH, buildConfigSchema, createAgentProfile, expandHome, findEffectiveAgentProfile, getDataDir, getPackageVersion, getProviderName, hasSecretRef, isSensitiveConfigPath, loadConfig, normalizeThinkingLevels, parseThinkingLevel, probeFeishu, readAgentAvatarContent, removeAgentProfile, resolveEffectiveAgentProfiles, saveConfig, updateAgentProfile } from "@nextclaw/core";
|
|
11
|
-
import { mountNcpHttpAgentRoutes } from "@nextclaw/ncp-http-agent-server";
|
|
12
11
|
import { discoverPluginStatusReport, enablePluginInConfig, mergePluginConfigView, toPluginConfigView } from "@nextclaw/openclaw-compat";
|
|
13
12
|
import { homedir } from "node:os";
|
|
14
13
|
import { findBuiltinProviderByName, listBuiltinProviders } from "@nextclaw/runtime";
|
|
@@ -65,13 +64,13 @@ async function readJson(req) {
|
|
|
65
64
|
return { ok: false };
|
|
66
65
|
}
|
|
67
66
|
}
|
|
68
|
-
function isRecord(value) {
|
|
67
|
+
function isRecord$1(value) {
|
|
69
68
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
70
69
|
}
|
|
71
70
|
function readErrorMessage(value, fallback) {
|
|
72
|
-
if (!isRecord(value)) return fallback;
|
|
71
|
+
if (!isRecord$1(value)) return fallback;
|
|
73
72
|
const maybeError = value.error;
|
|
74
|
-
if (!isRecord(maybeError)) return fallback;
|
|
73
|
+
if (!isRecord$1(maybeError)) return fallback;
|
|
75
74
|
return typeof maybeError.message === "string" && maybeError.message.trim().length > 0 ? maybeError.message : fallback;
|
|
76
75
|
}
|
|
77
76
|
function readNonEmptyString(value) {
|
|
@@ -441,6 +440,48 @@ var UiAuthService = class {
|
|
|
441
440
|
};
|
|
442
441
|
};
|
|
443
442
|
//#endregion
|
|
443
|
+
//#region ../nextclaw-shared/src/types/typed-key.types.ts
|
|
444
|
+
function createTypedKey(id) {
|
|
445
|
+
const normalizedId = id.trim();
|
|
446
|
+
if (!normalizedId) throw new Error("typed key id is required");
|
|
447
|
+
return { id: normalizedId };
|
|
448
|
+
}
|
|
449
|
+
//#endregion
|
|
450
|
+
//#region ../nextclaw-shared/src/configs/event-keys.config.ts
|
|
451
|
+
function createAppEventKey(id) {
|
|
452
|
+
return createTypedKey(id);
|
|
453
|
+
}
|
|
454
|
+
const eventKeys = {
|
|
455
|
+
configUpdated: createAppEventKey("config.updated"),
|
|
456
|
+
channelConfigApplyStatus: createAppEventKey("channel.config.apply-status"),
|
|
457
|
+
sessionUpdated: createAppEventKey("session.updated"),
|
|
458
|
+
sessionRunStatus: createAppEventKey("session.run-status"),
|
|
459
|
+
ncpEvent: createAppEventKey("ncp.event"),
|
|
460
|
+
sessionSummaryUpsert: createAppEventKey("session.summary.upsert"),
|
|
461
|
+
sessionSummaryDelete: createAppEventKey("session.summary.delete"),
|
|
462
|
+
configReloadStarted: createAppEventKey("config.reload.started"),
|
|
463
|
+
configReloadFinished: createAppEventKey("config.reload.finished"),
|
|
464
|
+
error: createAppEventKey("error"),
|
|
465
|
+
connectionOpen: createAppEventKey("connection.open"),
|
|
466
|
+
connectionClose: createAppEventKey("connection.close"),
|
|
467
|
+
connectionError: createAppEventKey("connection.error"),
|
|
468
|
+
runtimeUpdateSnapshot: createAppEventKey("runtime.update.snapshot")
|
|
469
|
+
};
|
|
470
|
+
//#endregion
|
|
471
|
+
//#region ../nextclaw-shared/src/configs/ingress-keys.config.ts
|
|
472
|
+
const ingressKeys = {
|
|
473
|
+
extension: {
|
|
474
|
+
channelConfigGet: createTypedKey("extension.channel.config.get"),
|
|
475
|
+
channelMessageSubmit: createTypedKey("extension.channel.message.submit"),
|
|
476
|
+
response: createTypedKey("extension.response")
|
|
477
|
+
},
|
|
478
|
+
agentRun: {
|
|
479
|
+
send: createTypedKey("agent-run.send"),
|
|
480
|
+
abort: createTypedKey("agent-run.abort"),
|
|
481
|
+
sessionMessageRequest: createTypedKey("agent-run.session-message.request")
|
|
482
|
+
}
|
|
483
|
+
};
|
|
484
|
+
//#endregion
|
|
444
485
|
//#region src/features/agents/stores/agents.store.ts
|
|
445
486
|
function listAgents(configPath) {
|
|
446
487
|
const config = loadConfig(configPath);
|
|
@@ -515,34 +556,6 @@ function buildAgentAvatarUrl(agentId, avatar) {
|
|
|
515
556
|
if (normalized.startsWith("home://")) return `/api/agents/${encodeURIComponent(agentId)}/avatar`;
|
|
516
557
|
}
|
|
517
558
|
//#endregion
|
|
518
|
-
//#region ../nextclaw-shared/src/types/typed-key.types.ts
|
|
519
|
-
function createTypedKey(id) {
|
|
520
|
-
const normalizedId = id.trim();
|
|
521
|
-
if (!normalizedId) throw new Error("typed key id is required");
|
|
522
|
-
return { id: normalizedId };
|
|
523
|
-
}
|
|
524
|
-
//#endregion
|
|
525
|
-
//#region ../nextclaw-shared/src/configs/event-keys.config.ts
|
|
526
|
-
function createAppEventKey(id) {
|
|
527
|
-
return createTypedKey(id);
|
|
528
|
-
}
|
|
529
|
-
const eventKeys = {
|
|
530
|
-
configUpdated: createAppEventKey("config.updated"),
|
|
531
|
-
channelConfigApplyStatus: createAppEventKey("channel.config.apply-status"),
|
|
532
|
-
sessionUpdated: createAppEventKey("session.updated"),
|
|
533
|
-
sessionRunStatus: createAppEventKey("session.run-status"),
|
|
534
|
-
ncpEvent: createAppEventKey("ncp.event"),
|
|
535
|
-
sessionSummaryUpsert: createAppEventKey("session.summary.upsert"),
|
|
536
|
-
sessionSummaryDelete: createAppEventKey("session.summary.delete"),
|
|
537
|
-
configReloadStarted: createAppEventKey("config.reload.started"),
|
|
538
|
-
configReloadFinished: createAppEventKey("config.reload.finished"),
|
|
539
|
-
error: createAppEventKey("error"),
|
|
540
|
-
connectionOpen: createAppEventKey("connection.open"),
|
|
541
|
-
connectionClose: createAppEventKey("connection.close"),
|
|
542
|
-
connectionError: createAppEventKey("connection.error"),
|
|
543
|
-
runtimeUpdateSnapshot: createAppEventKey("runtime.update.snapshot")
|
|
544
|
-
};
|
|
545
|
-
//#endregion
|
|
546
559
|
//#region src/shared/utils/app-events.utils.ts
|
|
547
560
|
function appEventOptions() {
|
|
548
561
|
return {
|
|
@@ -654,7 +667,7 @@ var AppRoutesController = class {
|
|
|
654
667
|
health = (c) => c.json(ok({
|
|
655
668
|
status: "ok",
|
|
656
669
|
services: {
|
|
657
|
-
ncpAgent:
|
|
670
|
+
ncpAgent: "ready",
|
|
658
671
|
cronService: this.options.cron ? "ready" : "unavailable"
|
|
659
672
|
}
|
|
660
673
|
}));
|
|
@@ -1453,7 +1466,7 @@ var ConfigRoutesController = class {
|
|
|
1453
1466
|
const provider = c.req.param("provider");
|
|
1454
1467
|
const body = await readJson(c.req.raw);
|
|
1455
1468
|
if (!body.ok) return c.json(err("INVALID_BODY", "invalid json body"), 400);
|
|
1456
|
-
const result = await testProviderConnection(this.options.configPath, provider, body.data, this.options.
|
|
1469
|
+
const result = await testProviderConnection(this.options.configPath, provider, body.data, this.options.kernel.llmProviders);
|
|
1457
1470
|
if (!result) return c.json(err("NOT_FOUND", `unknown provider: ${provider}`), 404);
|
|
1458
1471
|
return c.json(ok(result));
|
|
1459
1472
|
};
|
|
@@ -2761,8 +2774,17 @@ var NcpAssetRoutesController = class {
|
|
|
2761
2774
|
constructor(options) {
|
|
2762
2775
|
this.options = options;
|
|
2763
2776
|
}
|
|
2777
|
+
getAssetApi = () => {
|
|
2778
|
+
const kernel = this.options.kernel;
|
|
2779
|
+
if (!kernel) return;
|
|
2780
|
+
return {
|
|
2781
|
+
put: (input) => kernel.assetStore.putBytes(input),
|
|
2782
|
+
stat: kernel.assetStore.statRecord,
|
|
2783
|
+
resolveContentPath: kernel.assetStore.resolveContentPath
|
|
2784
|
+
};
|
|
2785
|
+
};
|
|
2764
2786
|
putAssets = async (c) => {
|
|
2765
|
-
const assetApi = this.
|
|
2787
|
+
const assetApi = this.getAssetApi();
|
|
2766
2788
|
if (!assetApi) return c.json(err("NOT_AVAILABLE", "ncp asset api unavailable"), 503);
|
|
2767
2789
|
let formData;
|
|
2768
2790
|
try {
|
|
@@ -2788,7 +2810,7 @@ var NcpAssetRoutesController = class {
|
|
|
2788
2810
|
return c.json(ok(payload));
|
|
2789
2811
|
};
|
|
2790
2812
|
getAssetContent = async (c) => {
|
|
2791
|
-
const assetApi = this.
|
|
2813
|
+
const assetApi = this.getAssetApi();
|
|
2792
2814
|
if (!assetApi) return c.json(err("NOT_AVAILABLE", "ncp asset api unavailable"), 503);
|
|
2793
2815
|
const uri = c.req.query("uri")?.trim();
|
|
2794
2816
|
if (!uri) return c.json(err("INVALID_URI", "asset uri is required"), 400);
|
|
@@ -3638,7 +3660,7 @@ async function loadPluginReadmeFromNpm(spec) {
|
|
|
3638
3660
|
if (!response.ok) return null;
|
|
3639
3661
|
const payload = await response.json();
|
|
3640
3662
|
const readme = typeof payload.readme === "string" ? payload.readme : "";
|
|
3641
|
-
const latest = isRecord(payload["dist-tags"]) && typeof payload["dist-tags"].latest === "string" ? payload["dist-tags"].latest : void 0;
|
|
3663
|
+
const latest = isRecord$1(payload["dist-tags"]) && typeof payload["dist-tags"].latest === "string" ? payload["dist-tags"].latest : void 0;
|
|
3642
3664
|
const metadata = {
|
|
3643
3665
|
name: typeof payload.name === "string" ? payload.name : spec,
|
|
3644
3666
|
version: latest,
|
|
@@ -4168,19 +4190,13 @@ var NcpSessionRoutesController = class {
|
|
|
4168
4190
|
this.options = options;
|
|
4169
4191
|
this.sessionSkillsViewBuilder = new SessionSkillsViewBuilder(options);
|
|
4170
4192
|
}
|
|
4193
|
+
getSessionApi = () => this.options.kernel.ncpSessionApi;
|
|
4171
4194
|
getSessionTypes = async (c) => {
|
|
4172
|
-
const
|
|
4173
|
-
const payload = listSessionTypes ? await listSessionTypes({ describeMode: "observation" }) : {
|
|
4174
|
-
defaultType: "native",
|
|
4175
|
-
options: [{
|
|
4176
|
-
value: "native",
|
|
4177
|
-
label: "Native"
|
|
4178
|
-
}]
|
|
4179
|
-
};
|
|
4195
|
+
const payload = await this.options.kernel.agentRuntimeManager.listSessionTypes({ describeMode: "observation" });
|
|
4180
4196
|
return c.json(ok(payload));
|
|
4181
4197
|
};
|
|
4182
4198
|
listSessions = async (c) => {
|
|
4183
|
-
const sessionApi = this.
|
|
4199
|
+
const sessionApi = this.getSessionApi();
|
|
4184
4200
|
if (!sessionApi) return c.json(err("NOT_AVAILABLE", "ncp session api unavailable"), 503);
|
|
4185
4201
|
const sessions = await sessionApi.listSessions({ limit: readPositiveInt(c.req.query("limit")) });
|
|
4186
4202
|
const payload = {
|
|
@@ -4190,7 +4206,7 @@ var NcpSessionRoutesController = class {
|
|
|
4190
4206
|
return c.json(ok(payload));
|
|
4191
4207
|
};
|
|
4192
4208
|
getSession = async (c) => {
|
|
4193
|
-
const sessionApi = this.
|
|
4209
|
+
const sessionApi = this.getSessionApi();
|
|
4194
4210
|
if (!sessionApi) return c.json(err("NOT_AVAILABLE", "ncp session api unavailable"), 503);
|
|
4195
4211
|
const sessionId = decodeURIComponent(c.req.param("sessionId"));
|
|
4196
4212
|
const session = await sessionApi.getSession(sessionId);
|
|
@@ -4198,7 +4214,7 @@ var NcpSessionRoutesController = class {
|
|
|
4198
4214
|
return c.json(ok(session));
|
|
4199
4215
|
};
|
|
4200
4216
|
listSessionMessages = async (c) => {
|
|
4201
|
-
const sessionApi = this.
|
|
4217
|
+
const sessionApi = this.getSessionApi();
|
|
4202
4218
|
if (!sessionApi) return c.json(err("NOT_AVAILABLE", "ncp session api unavailable"), 503);
|
|
4203
4219
|
const sessionId = decodeURIComponent(c.req.param("sessionId"));
|
|
4204
4220
|
const session = await sessionApi.getSession(sessionId);
|
|
@@ -4214,7 +4230,7 @@ var NcpSessionRoutesController = class {
|
|
|
4214
4230
|
return c.json(ok(payload));
|
|
4215
4231
|
};
|
|
4216
4232
|
getSessionSkills = async (c) => {
|
|
4217
|
-
const sessionApi = this.
|
|
4233
|
+
const sessionApi = this.getSessionApi();
|
|
4218
4234
|
if (!sessionApi) return c.json(err("NOT_AVAILABLE", "ncp session api unavailable"), 503);
|
|
4219
4235
|
const sessionId = decodeURIComponent(c.req.param("sessionId"));
|
|
4220
4236
|
const query = c.req.query();
|
|
@@ -4237,7 +4253,7 @@ var NcpSessionRoutesController = class {
|
|
|
4237
4253
|
})));
|
|
4238
4254
|
};
|
|
4239
4255
|
patchSession = async (c) => {
|
|
4240
|
-
const sessionApi = this.
|
|
4256
|
+
const sessionApi = this.getSessionApi();
|
|
4241
4257
|
if (!sessionApi) return c.json(err("NOT_AVAILABLE", "ncp session api unavailable"), 503);
|
|
4242
4258
|
const sessionId = decodeURIComponent(c.req.param("sessionId"));
|
|
4243
4259
|
const body = await readJson(c.req.raw);
|
|
@@ -4261,7 +4277,7 @@ var NcpSessionRoutesController = class {
|
|
|
4261
4277
|
return c.json(ok(updated));
|
|
4262
4278
|
};
|
|
4263
4279
|
deleteSession = async (c) => {
|
|
4264
|
-
const sessionApi = this.
|
|
4280
|
+
const sessionApi = this.getSessionApi();
|
|
4265
4281
|
if (!sessionApi) return c.json(err("NOT_AVAILABLE", "ncp session api unavailable"), 503);
|
|
4266
4282
|
const sessionId = decodeURIComponent(c.req.param("sessionId"));
|
|
4267
4283
|
if (!await sessionApi.getSession(sessionId)) return c.json(err("NOT_FOUND", `ncp session not found: ${sessionId}`), 404);
|
|
@@ -4726,13 +4742,7 @@ var ServerPathRoutesController = class {
|
|
|
4726
4742
|
};
|
|
4727
4743
|
//#endregion
|
|
4728
4744
|
//#region src/app/router.ts
|
|
4729
|
-
|
|
4730
|
-
const authorization = request.headers.get("authorization")?.trim() ?? "";
|
|
4731
|
-
return /^Bearer\s+(.+)$/i.exec(authorization)?.[1]?.trim() || null;
|
|
4732
|
-
}
|
|
4733
|
-
function isValidIngressEnvelope(value) {
|
|
4734
|
-
return typeof value.type === "string" && value.type.trim().length > 0;
|
|
4735
|
-
}
|
|
4745
|
+
const NCP_AGENT_BASE_PATH = "/api/ncp/agent";
|
|
4736
4746
|
function createUiRouteControllers(options, authService, marketplaceBaseUrl) {
|
|
4737
4747
|
const { remoteAccess, runtimeControl, runtimeUpdate } = options;
|
|
4738
4748
|
return {
|
|
@@ -4752,6 +4762,62 @@ function createUiRouteControllers(options, authService, marketplaceBaseUrl) {
|
|
|
4752
4762
|
mcpMarketplace: new McpMarketplaceController(options, marketplaceBaseUrl)
|
|
4753
4763
|
};
|
|
4754
4764
|
}
|
|
4765
|
+
function isRecord(value) {
|
|
4766
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
4767
|
+
}
|
|
4768
|
+
function hasOwn(value, key) {
|
|
4769
|
+
return Object.prototype.hasOwnProperty.call(value, key);
|
|
4770
|
+
}
|
|
4771
|
+
function isValidSendEnvelope(value) {
|
|
4772
|
+
if (!isRecord(value)) return false;
|
|
4773
|
+
if (hasOwn(value, "sessionId") && (typeof value.sessionId !== "string" || value.sessionId.trim().length === 0)) return false;
|
|
4774
|
+
const hasMessage = hasOwn(value, "message");
|
|
4775
|
+
if (hasMessage === hasOwn(value, "content")) return false;
|
|
4776
|
+
return hasMessage ? isRecord(value.message) : Array.isArray(value.content);
|
|
4777
|
+
}
|
|
4778
|
+
function readStreamPayload(url) {
|
|
4779
|
+
const sessionId = new URL(url).searchParams.get("sessionId")?.trim();
|
|
4780
|
+
return sessionId ? { sessionId } : null;
|
|
4781
|
+
}
|
|
4782
|
+
function isAbortPayload(value) {
|
|
4783
|
+
return isRecord(value) && typeof value.sessionId === "string" && value.sessionId.trim().length > 0;
|
|
4784
|
+
}
|
|
4785
|
+
function toSseFrame(eventName, data) {
|
|
4786
|
+
return `event: ${eventName}\ndata: ${JSON.stringify(data)}\n\n`;
|
|
4787
|
+
}
|
|
4788
|
+
function createNcpEventStreamResponse(events, signal) {
|
|
4789
|
+
const encoder = new TextEncoder();
|
|
4790
|
+
const stream = new ReadableStream({ start: async (controller) => {
|
|
4791
|
+
let closed = false;
|
|
4792
|
+
const close = () => {
|
|
4793
|
+
if (!closed) {
|
|
4794
|
+
closed = true;
|
|
4795
|
+
controller.close();
|
|
4796
|
+
}
|
|
4797
|
+
};
|
|
4798
|
+
signal.addEventListener("abort", close, { once: true });
|
|
4799
|
+
try {
|
|
4800
|
+
for await (const event of events) {
|
|
4801
|
+
if (closed || signal.aborted) break;
|
|
4802
|
+
controller.enqueue(encoder.encode(toSseFrame("ncp-event", event)));
|
|
4803
|
+
}
|
|
4804
|
+
} catch (error) {
|
|
4805
|
+
if (!closed && !signal.aborted) controller.enqueue(encoder.encode(toSseFrame("error", {
|
|
4806
|
+
code: "STREAM_SOURCE_FAILED",
|
|
4807
|
+
message: error instanceof Error ? error.message : String(error)
|
|
4808
|
+
})));
|
|
4809
|
+
} finally {
|
|
4810
|
+
signal.removeEventListener("abort", close);
|
|
4811
|
+
close();
|
|
4812
|
+
}
|
|
4813
|
+
} });
|
|
4814
|
+
return new Response(stream, { headers: {
|
|
4815
|
+
"Content-Type": "text/event-stream; charset=utf-8",
|
|
4816
|
+
"Cache-Control": "no-cache, no-transform",
|
|
4817
|
+
Connection: "keep-alive",
|
|
4818
|
+
"X-Accel-Buffering": "no"
|
|
4819
|
+
} });
|
|
4820
|
+
}
|
|
4755
4821
|
var UiRouteRegistry = class {
|
|
4756
4822
|
constructor(app, options, controllers) {
|
|
4757
4823
|
this.app = app;
|
|
@@ -4761,6 +4827,40 @@ var UiRouteRegistry = class {
|
|
|
4761
4827
|
mountRoutes = (routes) => {
|
|
4762
4828
|
for (const [method, path, handler] of routes) this.app[method](path, handler);
|
|
4763
4829
|
};
|
|
4830
|
+
mountNcpAgentRoutes = (kernel, ncpAsset) => {
|
|
4831
|
+
this.app.post(`${NCP_AGENT_BASE_PATH}/send`, async (c) => {
|
|
4832
|
+
const body = await readJson(c.req.raw);
|
|
4833
|
+
if (!body.ok || !isValidSendEnvelope(body.data)) return c.json(err("INVALID_BODY", "Invalid NCP request envelope."), 400);
|
|
4834
|
+
const handle = await kernel.ingress.handle({
|
|
4835
|
+
type: ingressKeys.agentRun.send,
|
|
4836
|
+
payload: body.data
|
|
4837
|
+
}, { source: "ui-http" });
|
|
4838
|
+
return c.json(ok(handle));
|
|
4839
|
+
});
|
|
4840
|
+
this.app.get(`${NCP_AGENT_BASE_PATH}/stream`, (c) => {
|
|
4841
|
+
const payload = readStreamPayload(c.req.raw.url);
|
|
4842
|
+
if (!payload) return c.json(err("INVALID_QUERY", "sessionId is required."), 400);
|
|
4843
|
+
return createNcpEventStreamResponse(kernel.sessionRunManager.streamSessionEvents(payload, { signal: c.req.raw.signal }), c.req.raw.signal);
|
|
4844
|
+
});
|
|
4845
|
+
this.app.post(`${NCP_AGENT_BASE_PATH}/abort`, async (c) => {
|
|
4846
|
+
const body = await readJson(c.req.raw);
|
|
4847
|
+
if (!body.ok || !isAbortPayload(body.data)) return c.json(err("INVALID_BODY", "sessionId is required."), 400);
|
|
4848
|
+
await kernel.ingress.handle({
|
|
4849
|
+
type: ingressKeys.agentRun.abort,
|
|
4850
|
+
payload: body.data
|
|
4851
|
+
}, { source: "ui-http" });
|
|
4852
|
+
return c.json(ok({ accepted: true }));
|
|
4853
|
+
});
|
|
4854
|
+
this.mountRoutes([[
|
|
4855
|
+
"post",
|
|
4856
|
+
"/api/ncp/assets",
|
|
4857
|
+
ncpAsset.putAssets
|
|
4858
|
+
], [
|
|
4859
|
+
"get",
|
|
4860
|
+
"/api/ncp/assets/content",
|
|
4861
|
+
ncpAsset.getAssetContent
|
|
4862
|
+
]]);
|
|
4863
|
+
};
|
|
4764
4864
|
register = () => {
|
|
4765
4865
|
const { agents, app, auth, config, cron, ncpAsset, ncpSession, remote, runtimeControl, runtimeUpdate, serverPath } = this.controllers;
|
|
4766
4866
|
this.mountRoutes([
|
|
@@ -4979,23 +5079,7 @@ var UiRouteRegistry = class {
|
|
|
4979
5079
|
serverPath.read
|
|
4980
5080
|
]
|
|
4981
5081
|
]);
|
|
4982
|
-
|
|
4983
|
-
if (ncpAgent) {
|
|
4984
|
-
mountNcpHttpAgentRoutes(this.app, {
|
|
4985
|
-
basePath: ncpAgent.basePath ?? "/api/ncp/agent",
|
|
4986
|
-
agentClientEndpoint: ncpAgent.agentClientEndpoint,
|
|
4987
|
-
streamProvider: ncpAgent.streamProvider
|
|
4988
|
-
});
|
|
4989
|
-
this.mountRoutes([[
|
|
4990
|
-
"post",
|
|
4991
|
-
"/api/ncp/assets",
|
|
4992
|
-
ncpAsset.putAssets
|
|
4993
|
-
], [
|
|
4994
|
-
"get",
|
|
4995
|
-
"/api/ncp/assets/content",
|
|
4996
|
-
ncpAsset.getAssetContent
|
|
4997
|
-
]]);
|
|
4998
|
-
}
|
|
5082
|
+
this.mountNcpAgentRoutes(this.options.kernel, ncpAsset);
|
|
4999
5083
|
this.mountRoutes([
|
|
5000
5084
|
[
|
|
5001
5085
|
"get",
|
|
@@ -5125,13 +5209,13 @@ var UiRouteRegistry = class {
|
|
|
5125
5209
|
]
|
|
5126
5210
|
]);
|
|
5127
5211
|
this.app.post("/webhook", async (c) => {
|
|
5128
|
-
|
|
5212
|
+
const ingress = this.options.kernel.ingress;
|
|
5129
5213
|
const body = await readJson(c.req.raw);
|
|
5130
|
-
if (!body.ok
|
|
5214
|
+
if (!body.ok) return c.json(err("INVALID_BODY", "invalid ingress body"), 400);
|
|
5131
5215
|
try {
|
|
5132
5216
|
const result = await ingress.handle(body.data, {
|
|
5133
5217
|
source: "webhook",
|
|
5134
|
-
token:
|
|
5218
|
+
token: /^Bearer\s+(.+)$/i.exec(c.req.raw.headers.get("authorization")?.trim() ?? "")?.[1]?.trim() || null
|
|
5135
5219
|
});
|
|
5136
5220
|
return c.json(ok(result ?? { accepted: true }));
|
|
5137
5221
|
} catch (error) {
|
|
@@ -5309,9 +5393,7 @@ async function startUiServer(gateway) {
|
|
|
5309
5393
|
close: () => new Promise((resolve) => {
|
|
5310
5394
|
unsubscribeEventBus();
|
|
5311
5395
|
wss.close(() => {
|
|
5312
|
-
server.close(() =>
|
|
5313
|
-
Promise.resolve(gateway.ncpAgent?.agentClientEndpoint.stop()).catch(() => void 0).finally(() => resolve());
|
|
5314
|
-
});
|
|
5396
|
+
server.close(() => resolve());
|
|
5315
5397
|
});
|
|
5316
5398
|
})
|
|
5317
5399
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextclaw/server",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.21",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Nextclaw UI/API server.",
|
|
6
6
|
"type": "module",
|
|
@@ -18,13 +18,12 @@
|
|
|
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/kernel": "0.1.
|
|
23
|
-
"@nextclaw/
|
|
24
|
-
"@nextclaw/ncp
|
|
25
|
-
"@nextclaw/
|
|
26
|
-
"@nextclaw/
|
|
27
|
-
"@nextclaw/runtime": "0.2.51"
|
|
21
|
+
"@nextclaw/core": "0.12.20",
|
|
22
|
+
"@nextclaw/kernel": "0.1.10",
|
|
23
|
+
"@nextclaw/mcp": "0.1.85",
|
|
24
|
+
"@nextclaw/ncp": "0.5.13",
|
|
25
|
+
"@nextclaw/openclaw-compat": "1.0.20",
|
|
26
|
+
"@nextclaw/runtime": "0.2.52"
|
|
28
27
|
},
|
|
29
28
|
"devDependencies": {
|
|
30
29
|
"@types/node": "^20.17.6",
|