@nextclaw/server 0.10.8 → 0.10.9

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.
Files changed (3) hide show
  1. package/dist/index.d.ts +132 -52
  2. package/dist/index.js +156 -44
  3. package/package.json +4 -4
package/dist/index.d.ts CHANGED
@@ -2,8 +2,8 @@ import * as NextclawCore from '@nextclaw/core';
2
2
  import { ThinkingLevel, CronService, Config, ConfigActionExecuteRequest as ConfigActionExecuteRequest$1, ConfigActionExecuteResult as ConfigActionExecuteResult$1 } from '@nextclaw/core';
3
3
  import { NcpAgentClientEndpoint, NcpSessionApi, NcpSessionSummary, NcpMessage } from '@nextclaw/ncp';
4
4
  import { NcpHttpAgentStreamProvider } from '@nextclaw/ncp-http-agent-server';
5
- import { Hono } from 'hono';
6
5
  import { IncomingMessage } from 'node:http';
6
+ import { Hono } from 'hono';
7
7
 
8
8
  type MarketplaceItemType = "plugin" | "skill" | "mcp";
9
9
  type MarketplaceSort = "relevance" | "updated";
@@ -283,6 +283,65 @@ type MarketplaceApiConfig = {
283
283
  installer?: MarketplaceInstaller;
284
284
  };
285
285
 
286
+ declare class UiAuthService {
287
+ private readonly configPath;
288
+ private readonly sessions;
289
+ constructor(configPath: string);
290
+ private loadCurrentConfig;
291
+ private saveCurrentConfig;
292
+ private readAuthConfig;
293
+ private isConfigured;
294
+ isProtectionEnabled(): boolean;
295
+ private getSessionIdFromCookieHeader;
296
+ private getValidSession;
297
+ isRequestAuthenticated(request: Request): boolean;
298
+ isSocketAuthenticated(request: IncomingMessage): boolean;
299
+ getStatus(request: Request): AuthStatusView;
300
+ private createSession;
301
+ private clearAllSessions;
302
+ private deleteRequestSession;
303
+ private buildLoginCookie;
304
+ buildTrustedRequestCookieHeader(): string | null;
305
+ buildLogoutCookie(request: Request): string;
306
+ setup(request: Request, payload: AuthSetupRequest): {
307
+ status: AuthStatusView;
308
+ cookie: string;
309
+ };
310
+ login(request: Request, payload: AuthLoginRequest): {
311
+ status: AuthStatusView;
312
+ cookie: string;
313
+ };
314
+ logout(request: Request): void;
315
+ updatePassword(request: Request, payload: AuthPasswordUpdateRequest): {
316
+ status: AuthStatusView;
317
+ cookie?: string;
318
+ };
319
+ updateEnabled(request: Request, payload: AuthEnabledUpdateRequest): {
320
+ status: AuthStatusView;
321
+ cookie?: string;
322
+ };
323
+ }
324
+
325
+ type UiRouterOptions = {
326
+ configPath: string;
327
+ productVersion?: string;
328
+ publish: (event: UiServerEvent) => void;
329
+ marketplace?: MarketplaceApiConfig;
330
+ cronService?: InstanceType<typeof NextclawCore.CronService>;
331
+ chatRuntime?: UiChatRuntime;
332
+ ncpAgent?: UiNcpAgent;
333
+ authService?: UiAuthService;
334
+ remoteAccess?: UiRemoteAccessHost;
335
+ };
336
+ type UiRemoteAccessHost = {
337
+ getStatus: () => Promise<RemoteAccessView> | RemoteAccessView;
338
+ login: (input: RemoteLoginRequest) => Promise<RemoteAccessView>;
339
+ logout: () => Promise<RemoteAccessView> | RemoteAccessView;
340
+ updateSettings: (input: RemoteSettingsUpdateRequest) => Promise<RemoteAccessView> | RemoteAccessView;
341
+ runDoctor: () => Promise<RemoteDoctorView>;
342
+ controlService: (action: RemoteServiceAction) => Promise<RemoteServiceActionResult>;
343
+ };
344
+
286
345
  type ChatSessionTypeCtaView = {
287
346
  kind: string;
288
347
  label?: string;
@@ -454,6 +513,76 @@ type AuthPasswordUpdateRequest = {
454
513
  type AuthEnabledUpdateRequest = {
455
514
  enabled: boolean;
456
515
  };
516
+ type RemoteAccountView = {
517
+ loggedIn: boolean;
518
+ email?: string;
519
+ role?: string;
520
+ platformBase?: string | null;
521
+ apiBase?: string | null;
522
+ };
523
+ type RemoteRuntimeView = {
524
+ enabled: boolean;
525
+ mode: "service" | "foreground";
526
+ state: "disabled" | "connecting" | "connected" | "disconnected" | "error";
527
+ deviceId?: string;
528
+ deviceName?: string;
529
+ platformBase?: string;
530
+ localOrigin?: string;
531
+ lastConnectedAt?: string | null;
532
+ lastError?: string | null;
533
+ updatedAt: string;
534
+ };
535
+ type RemoteServiceView = {
536
+ running: boolean;
537
+ pid?: number;
538
+ uiUrl?: string;
539
+ uiPort?: number;
540
+ currentProcess: boolean;
541
+ };
542
+ type RemoteSettingsView = {
543
+ enabled: boolean;
544
+ deviceName: string;
545
+ platformApiBase: string;
546
+ };
547
+ type RemoteAccessView = {
548
+ account: RemoteAccountView;
549
+ settings: RemoteSettingsView;
550
+ service: RemoteServiceView;
551
+ localOrigin: string;
552
+ configuredEnabled: boolean;
553
+ platformBase?: string | null;
554
+ runtime: RemoteRuntimeView | null;
555
+ };
556
+ type RemoteDoctorCheckView = {
557
+ name: string;
558
+ ok: boolean;
559
+ detail: string;
560
+ };
561
+ type RemoteDoctorView = {
562
+ generatedAt: string;
563
+ checks: RemoteDoctorCheckView[];
564
+ snapshot: {
565
+ configuredEnabled: boolean;
566
+ runtime: RemoteRuntimeView | null;
567
+ };
568
+ };
569
+ type RemoteLoginRequest = {
570
+ email: string;
571
+ password: string;
572
+ apiBase?: string;
573
+ register?: boolean;
574
+ };
575
+ type RemoteSettingsUpdateRequest = {
576
+ enabled?: boolean;
577
+ deviceName?: string;
578
+ platformApiBase?: string;
579
+ };
580
+ type RemoteServiceAction = "start" | "restart" | "stop";
581
+ type RemoteServiceActionResult = {
582
+ accepted: boolean;
583
+ action: RemoteServiceAction;
584
+ message: string;
585
+ };
457
586
  type AgentProfileView = {
458
587
  id: string;
459
588
  default?: boolean;
@@ -965,6 +1094,7 @@ type UiServerOptions = {
965
1094
  cronService?: CronService;
966
1095
  chatRuntime?: UiChatRuntime;
967
1096
  ncpAgent?: UiNcpAgent;
1097
+ remoteAccess?: UiRemoteAccessHost;
968
1098
  };
969
1099
  type UiServerHandle = {
970
1100
  host: string;
@@ -975,56 +1105,6 @@ type UiServerHandle = {
975
1105
 
976
1106
  declare function startUiServer(options: UiServerOptions): UiServerHandle;
977
1107
 
978
- declare class UiAuthService {
979
- private readonly configPath;
980
- private readonly sessions;
981
- constructor(configPath: string);
982
- private loadCurrentConfig;
983
- private saveCurrentConfig;
984
- private readAuthConfig;
985
- private isConfigured;
986
- isProtectionEnabled(): boolean;
987
- private getSessionIdFromCookieHeader;
988
- private getValidSession;
989
- isRequestAuthenticated(request: Request): boolean;
990
- isSocketAuthenticated(request: IncomingMessage): boolean;
991
- getStatus(request: Request): AuthStatusView;
992
- private createSession;
993
- private clearAllSessions;
994
- private deleteRequestSession;
995
- private buildLoginCookie;
996
- buildTrustedRequestCookieHeader(): string | null;
997
- buildLogoutCookie(request: Request): string;
998
- setup(request: Request, payload: AuthSetupRequest): {
999
- status: AuthStatusView;
1000
- cookie: string;
1001
- };
1002
- login(request: Request, payload: AuthLoginRequest): {
1003
- status: AuthStatusView;
1004
- cookie: string;
1005
- };
1006
- logout(request: Request): void;
1007
- updatePassword(request: Request, payload: AuthPasswordUpdateRequest): {
1008
- status: AuthStatusView;
1009
- cookie?: string;
1010
- };
1011
- updateEnabled(request: Request, payload: AuthEnabledUpdateRequest): {
1012
- status: AuthStatusView;
1013
- cookie?: string;
1014
- };
1015
- }
1016
-
1017
- type UiRouterOptions = {
1018
- configPath: string;
1019
- productVersion?: string;
1020
- publish: (event: UiServerEvent) => void;
1021
- marketplace?: MarketplaceApiConfig;
1022
- cronService?: InstanceType<typeof NextclawCore.CronService>;
1023
- chatRuntime?: UiChatRuntime;
1024
- ncpAgent?: UiNcpAgent;
1025
- authService?: UiAuthService;
1026
- };
1027
-
1028
1108
  declare function createUiRouter(options: UiRouterOptions): Hono;
1029
1109
 
1030
1110
  type ExecuteActionResult = {
@@ -1075,4 +1155,4 @@ declare function getUiBridgeSecretPath(): string;
1075
1155
  declare function readUiBridgeSecret(): string | null;
1076
1156
  declare function ensureUiBridgeSecret(): string;
1077
1157
 
1078
- 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 };
1158
+ 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 RemoteAccessView, type RemoteAccountView, type RemoteDoctorCheckView, type RemoteDoctorView, type RemoteLoginRequest, type RemoteRuntimeView, type RemoteServiceAction, type RemoteServiceActionResult, type RemoteServiceView, type RemoteSettingsUpdateRequest, type RemoteSettingsView, 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 UiRemoteAccessHost, 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
@@ -4847,6 +4847,88 @@ var SkillMarketplaceController = class {
4847
4847
  };
4848
4848
  };
4849
4849
 
4850
+ // src/ui/router/remote.controller.ts
4851
+ var REMOTE_SERVICE_ACTIONS = /* @__PURE__ */ new Set(["start", "restart", "stop"]);
4852
+ function readBoolean(value) {
4853
+ return typeof value === "boolean" ? value : void 0;
4854
+ }
4855
+ function readTrimmedString(value) {
4856
+ return typeof value === "string" ? value.trim() : void 0;
4857
+ }
4858
+ var RemoteRoutesController = class {
4859
+ constructor(host) {
4860
+ this.host = host;
4861
+ }
4862
+ getStatus = async (c) => {
4863
+ try {
4864
+ return c.json(ok(await this.host.getStatus()));
4865
+ } catch (error) {
4866
+ return c.json(err("REMOTE_STATUS_FAILED", formatUserFacingError(error)), 500);
4867
+ }
4868
+ };
4869
+ getDoctor = async (c) => {
4870
+ try {
4871
+ return c.json(ok(await this.host.runDoctor()));
4872
+ } catch (error) {
4873
+ return c.json(err("REMOTE_DOCTOR_FAILED", formatUserFacingError(error)), 500);
4874
+ }
4875
+ };
4876
+ login = async (c) => {
4877
+ const body = await readJson(c.req.raw);
4878
+ if (!body.ok) {
4879
+ return c.json(err("INVALID_BODY", "invalid json body"), 400);
4880
+ }
4881
+ const email = readNonEmptyString(body.data.email);
4882
+ const password = readNonEmptyString(body.data.password);
4883
+ if (!email || !password) {
4884
+ return c.json(err("INVALID_BODY", "email and password are required"), 400);
4885
+ }
4886
+ try {
4887
+ return c.json(ok(await this.host.login({
4888
+ email,
4889
+ password,
4890
+ apiBase: readTrimmedString(body.data.apiBase),
4891
+ register: readBoolean(body.data.register)
4892
+ })));
4893
+ } catch (error) {
4894
+ return c.json(err("REMOTE_LOGIN_FAILED", formatUserFacingError(error)), 400);
4895
+ }
4896
+ };
4897
+ logout = async (c) => {
4898
+ try {
4899
+ return c.json(ok(await this.host.logout()));
4900
+ } catch (error) {
4901
+ return c.json(err("REMOTE_LOGOUT_FAILED", formatUserFacingError(error)), 500);
4902
+ }
4903
+ };
4904
+ updateSettings = async (c) => {
4905
+ const body = await readJson(c.req.raw);
4906
+ if (!body.ok) {
4907
+ return c.json(err("INVALID_BODY", "invalid json body"), 400);
4908
+ }
4909
+ try {
4910
+ return c.json(ok(await this.host.updateSettings({
4911
+ enabled: readBoolean(body.data.enabled),
4912
+ deviceName: readTrimmedString(body.data.deviceName),
4913
+ platformApiBase: readTrimmedString(body.data.platformApiBase)
4914
+ })));
4915
+ } catch (error) {
4916
+ return c.json(err("REMOTE_SETTINGS_FAILED", formatUserFacingError(error)), 400);
4917
+ }
4918
+ };
4919
+ controlService = async (c) => {
4920
+ const action = c.req.param("action");
4921
+ if (!REMOTE_SERVICE_ACTIONS.has(action)) {
4922
+ return c.json(err("INVALID_ACTION", "unsupported remote service action"), 400);
4923
+ }
4924
+ try {
4925
+ return c.json(ok(await this.host.controlService(action)));
4926
+ } catch (error) {
4927
+ return c.json(err("REMOTE_SERVICE_FAILED", formatUserFacingError(error)), 400);
4928
+ }
4929
+ };
4930
+ };
4931
+
4850
4932
  // src/ui/router/session.controller.ts
4851
4933
  var SessionRoutesController = class {
4852
4934
  constructor(options) {
@@ -4926,37 +5008,7 @@ function registerAuthRoutes(app, authController) {
4926
5008
  app.put("/api/auth/enabled", authController.updateEnabled);
4927
5009
  app.post("/api/auth/bridge", authController.issueBridgeSession);
4928
5010
  }
4929
- function createUiRouter(options) {
4930
- const app = new Hono();
4931
- const marketplaceBaseUrl = normalizeMarketplaceBaseUrl(options);
4932
- const authService = options.authService ?? new UiAuthService(options.configPath);
4933
- const appController = new AppRoutesController(options);
4934
- const authController = new AuthRoutesController(authService);
4935
- const configController = new ConfigRoutesController(options);
4936
- const chatController = new ChatRoutesController(options);
4937
- const sessionController = new SessionRoutesController(options);
4938
- const cronController = new CronRoutesController(options);
4939
- const ncpSessionController = new NcpSessionRoutesController(options);
4940
- const pluginMarketplaceController = new PluginMarketplaceController(options, marketplaceBaseUrl);
4941
- const skillMarketplaceController = new SkillMarketplaceController(options, marketplaceBaseUrl);
4942
- const mcpMarketplaceController = new McpMarketplaceController(options, marketplaceBaseUrl);
4943
- app.notFound((c) => c.json(err("NOT_FOUND", "endpoint not found"), 404));
4944
- app.use("/api/*", async (c, next) => {
4945
- const path = c.req.path;
4946
- if (path === "/api/health" || path.startsWith("/api/auth/")) {
4947
- await next();
4948
- return;
4949
- }
4950
- if (!authService.isProtectionEnabled() || authService.isRequestAuthenticated(c.req.raw)) {
4951
- await next();
4952
- return;
4953
- }
4954
- c.status(401);
4955
- return c.json(err("UNAUTHORIZED", "Authentication required."), 401);
4956
- });
4957
- app.get("/api/health", appController.health);
4958
- app.get("/api/app/meta", appController.appMeta);
4959
- registerAuthRoutes(app, authController);
5011
+ function registerConfigRoutes(app, configController) {
4960
5012
  app.get("/api/config", configController.getConfig);
4961
5013
  app.get("/api/config/meta", configController.getConfigMeta);
4962
5014
  app.get("/api/config/schema", configController.getConfigSchema);
@@ -4973,6 +5025,8 @@ function createUiRouter(options) {
4973
5025
  app.put("/api/config/secrets", configController.updateSecrets);
4974
5026
  app.put("/api/config/runtime", configController.updateRuntime);
4975
5027
  app.post("/api/config/actions/:actionId/execute", configController.executeAction);
5028
+ }
5029
+ function registerChatRoutes(app, chatController) {
4976
5030
  app.get("/api/chat/capabilities", chatController.getCapabilities);
4977
5031
  app.get("/api/chat/session-types", chatController.getSessionTypes);
4978
5032
  app.get("/api/chat/commands", chatController.getCommands);
@@ -4982,27 +5036,84 @@ function createUiRouter(options) {
4982
5036
  app.get("/api/chat/runs", chatController.listRuns);
4983
5037
  app.get("/api/chat/runs/:runId", chatController.getRun);
4984
5038
  app.get("/api/chat/runs/:runId/stream", chatController.streamRun);
5039
+ }
5040
+ function registerSessionRoutes(app, sessionController) {
4985
5041
  app.get("/api/sessions", sessionController.listSessions);
4986
5042
  app.get("/api/sessions/:key/history", sessionController.getSessionHistory);
4987
5043
  app.put("/api/sessions/:key", sessionController.patchSession);
4988
5044
  app.delete("/api/sessions/:key", sessionController.deleteSession);
4989
- if (options.ncpAgent) {
4990
- mountNcpHttpAgentRoutes(app, {
4991
- basePath: options.ncpAgent.basePath ?? "/api/ncp/agent",
4992
- agentClientEndpoint: options.ncpAgent.agentClientEndpoint,
4993
- streamProvider: options.ncpAgent.streamProvider
4994
- });
4995
- app.get("/api/ncp/session-types", ncpSessionController.getSessionTypes);
4996
- app.get("/api/ncp/sessions", ncpSessionController.listSessions);
4997
- app.get("/api/ncp/sessions/:sessionId", ncpSessionController.getSession);
4998
- app.put("/api/ncp/sessions/:sessionId", ncpSessionController.patchSession);
4999
- app.get("/api/ncp/sessions/:sessionId/messages", ncpSessionController.listSessionMessages);
5000
- app.delete("/api/ncp/sessions/:sessionId", ncpSessionController.deleteSession);
5045
+ }
5046
+ function registerNcpRoutes(app, options, ncpSessionController) {
5047
+ if (!options.ncpAgent) {
5048
+ return;
5001
5049
  }
5050
+ mountNcpHttpAgentRoutes(app, {
5051
+ basePath: options.ncpAgent.basePath ?? "/api/ncp/agent",
5052
+ agentClientEndpoint: options.ncpAgent.agentClientEndpoint,
5053
+ streamProvider: options.ncpAgent.streamProvider
5054
+ });
5055
+ app.get("/api/ncp/session-types", ncpSessionController.getSessionTypes);
5056
+ app.get("/api/ncp/sessions", ncpSessionController.listSessions);
5057
+ app.get("/api/ncp/sessions/:sessionId", ncpSessionController.getSession);
5058
+ app.put("/api/ncp/sessions/:sessionId", ncpSessionController.patchSession);
5059
+ app.get("/api/ncp/sessions/:sessionId/messages", ncpSessionController.listSessionMessages);
5060
+ app.delete("/api/ncp/sessions/:sessionId", ncpSessionController.deleteSession);
5061
+ }
5062
+ function registerCronRoutes(app, cronController) {
5002
5063
  app.get("/api/cron", cronController.listJobs);
5003
5064
  app.delete("/api/cron/:id", cronController.deleteJob);
5004
5065
  app.put("/api/cron/:id/enable", cronController.enableJob);
5005
5066
  app.post("/api/cron/:id/run", cronController.runJob);
5067
+ }
5068
+ function registerRemoteRoutes(app, remoteController) {
5069
+ if (!remoteController) {
5070
+ return;
5071
+ }
5072
+ app.get("/api/remote/status", remoteController.getStatus);
5073
+ app.get("/api/remote/doctor", remoteController.getDoctor);
5074
+ app.post("/api/remote/login", remoteController.login);
5075
+ app.post("/api/remote/logout", remoteController.logout);
5076
+ app.put("/api/remote/settings", remoteController.updateSettings);
5077
+ app.post("/api/remote/service/:action", remoteController.controlService);
5078
+ }
5079
+ function createUiRouter(options) {
5080
+ const app = new Hono();
5081
+ const marketplaceBaseUrl = normalizeMarketplaceBaseUrl(options);
5082
+ const authService = options.authService ?? new UiAuthService(options.configPath);
5083
+ const appController = new AppRoutesController(options);
5084
+ const authController = new AuthRoutesController(authService);
5085
+ const configController = new ConfigRoutesController(options);
5086
+ const chatController = new ChatRoutesController(options);
5087
+ const sessionController = new SessionRoutesController(options);
5088
+ const cronController = new CronRoutesController(options);
5089
+ const ncpSessionController = new NcpSessionRoutesController(options);
5090
+ const remoteController = options.remoteAccess ? new RemoteRoutesController(options.remoteAccess) : null;
5091
+ const pluginMarketplaceController = new PluginMarketplaceController(options, marketplaceBaseUrl);
5092
+ const skillMarketplaceController = new SkillMarketplaceController(options, marketplaceBaseUrl);
5093
+ const mcpMarketplaceController = new McpMarketplaceController(options, marketplaceBaseUrl);
5094
+ app.notFound((c) => c.json(err("NOT_FOUND", "endpoint not found"), 404));
5095
+ app.use("/api/*", async (c, next) => {
5096
+ const path = c.req.path;
5097
+ if (path === "/api/health" || path.startsWith("/api/auth/")) {
5098
+ await next();
5099
+ return;
5100
+ }
5101
+ if (!authService.isProtectionEnabled() || authService.isRequestAuthenticated(c.req.raw)) {
5102
+ await next();
5103
+ return;
5104
+ }
5105
+ c.status(401);
5106
+ return c.json(err("UNAUTHORIZED", "Authentication required."), 401);
5107
+ });
5108
+ app.get("/api/health", appController.health);
5109
+ app.get("/api/app/meta", appController.appMeta);
5110
+ registerAuthRoutes(app, authController);
5111
+ registerConfigRoutes(app, configController);
5112
+ registerChatRoutes(app, chatController);
5113
+ registerSessionRoutes(app, sessionController);
5114
+ registerNcpRoutes(app, options, ncpSessionController);
5115
+ registerCronRoutes(app, cronController);
5116
+ registerRemoteRoutes(app, remoteController);
5006
5117
  mountMarketplaceRoutes(app, {
5007
5118
  plugin: pluginMarketplaceController,
5008
5119
  skill: skillMarketplaceController,
@@ -5047,7 +5158,8 @@ function startUiServer(options) {
5047
5158
  cronService: options.cronService,
5048
5159
  chatRuntime: options.chatRuntime,
5049
5160
  ncpAgent: options.ncpAgent,
5050
- authService
5161
+ authService,
5162
+ remoteAccess: options.remoteAccess
5051
5163
  })
5052
5164
  );
5053
5165
  const staticDir = options.staticDir;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextclaw/server",
3
- "version": "0.10.8",
3
+ "version": "0.10.9",
4
4
  "private": false,
5
5
  "description": "Nextclaw UI/API server.",
6
6
  "type": "module",
@@ -18,12 +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/openclaw-compat": "0.3.8",
22
+ "@nextclaw/ncp": "0.3.1",
23
23
  "@nextclaw/ncp-http-agent-server": "0.3.1",
24
24
  "@nextclaw/runtime": "0.2.5",
25
- "@nextclaw/core": "0.9.5",
26
- "@nextclaw/mcp": "0.1.8"
25
+ "@nextclaw/mcp": "0.1.9",
26
+ "@nextclaw/core": "0.9.5"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@types/node": "^20.17.6",