@nextclaw/server 0.10.8 → 0.10.10

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 +154 -52
  2. package/dist/index.js +189 -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,67 @@ 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
+ startBrowserAuth: (input: RemoteBrowserAuthStartRequest) => Promise<RemoteBrowserAuthStartResult>;
340
+ pollBrowserAuth: (input: RemoteBrowserAuthPollRequest) => Promise<RemoteBrowserAuthPollResult>;
341
+ logout: () => Promise<RemoteAccessView> | RemoteAccessView;
342
+ updateSettings: (input: RemoteSettingsUpdateRequest) => Promise<RemoteAccessView> | RemoteAccessView;
343
+ runDoctor: () => Promise<RemoteDoctorView>;
344
+ controlService: (action: RemoteServiceAction) => Promise<RemoteServiceActionResult>;
345
+ };
346
+
286
347
  type ChatSessionTypeCtaView = {
287
348
  kind: string;
288
349
  label?: string;
@@ -454,6 +515,96 @@ type AuthPasswordUpdateRequest = {
454
515
  type AuthEnabledUpdateRequest = {
455
516
  enabled: boolean;
456
517
  };
518
+ type RemoteAccountView = {
519
+ loggedIn: boolean;
520
+ email?: string;
521
+ role?: string;
522
+ platformBase?: string | null;
523
+ apiBase?: string | null;
524
+ };
525
+ type RemoteRuntimeView = {
526
+ enabled: boolean;
527
+ mode: "service" | "foreground";
528
+ state: "disabled" | "connecting" | "connected" | "disconnected" | "error";
529
+ deviceId?: string;
530
+ deviceName?: string;
531
+ platformBase?: string;
532
+ localOrigin?: string;
533
+ lastConnectedAt?: string | null;
534
+ lastError?: string | null;
535
+ updatedAt: string;
536
+ };
537
+ type RemoteServiceView = {
538
+ running: boolean;
539
+ pid?: number;
540
+ uiUrl?: string;
541
+ uiPort?: number;
542
+ currentProcess: boolean;
543
+ };
544
+ type RemoteSettingsView = {
545
+ enabled: boolean;
546
+ deviceName: string;
547
+ platformApiBase: string;
548
+ };
549
+ type RemoteAccessView = {
550
+ account: RemoteAccountView;
551
+ settings: RemoteSettingsView;
552
+ service: RemoteServiceView;
553
+ localOrigin: string;
554
+ configuredEnabled: boolean;
555
+ platformBase?: string | null;
556
+ runtime: RemoteRuntimeView | null;
557
+ };
558
+ type RemoteDoctorCheckView = {
559
+ name: string;
560
+ ok: boolean;
561
+ detail: string;
562
+ };
563
+ type RemoteDoctorView = {
564
+ generatedAt: string;
565
+ checks: RemoteDoctorCheckView[];
566
+ snapshot: {
567
+ configuredEnabled: boolean;
568
+ runtime: RemoteRuntimeView | null;
569
+ };
570
+ };
571
+ type RemoteLoginRequest = {
572
+ email: string;
573
+ password: string;
574
+ apiBase?: string;
575
+ register?: boolean;
576
+ };
577
+ type RemoteBrowserAuthStartRequest = {
578
+ apiBase?: string;
579
+ };
580
+ type RemoteBrowserAuthStartResult = {
581
+ sessionId: string;
582
+ verificationUri: string;
583
+ expiresAt: string;
584
+ intervalMs: number;
585
+ };
586
+ type RemoteBrowserAuthPollRequest = {
587
+ sessionId: string;
588
+ apiBase?: string;
589
+ };
590
+ type RemoteBrowserAuthPollResult = {
591
+ status: "pending" | "authorized" | "expired";
592
+ message?: string;
593
+ nextPollMs?: number;
594
+ email?: string;
595
+ role?: string;
596
+ };
597
+ type RemoteSettingsUpdateRequest = {
598
+ enabled?: boolean;
599
+ deviceName?: string;
600
+ platformApiBase?: string;
601
+ };
602
+ type RemoteServiceAction = "start" | "restart" | "stop";
603
+ type RemoteServiceActionResult = {
604
+ accepted: boolean;
605
+ action: RemoteServiceAction;
606
+ message: string;
607
+ };
457
608
  type AgentProfileView = {
458
609
  id: string;
459
610
  default?: boolean;
@@ -965,6 +1116,7 @@ type UiServerOptions = {
965
1116
  cronService?: CronService;
966
1117
  chatRuntime?: UiChatRuntime;
967
1118
  ncpAgent?: UiNcpAgent;
1119
+ remoteAccess?: UiRemoteAccessHost;
968
1120
  };
969
1121
  type UiServerHandle = {
970
1122
  host: string;
@@ -975,56 +1127,6 @@ type UiServerHandle = {
975
1127
 
976
1128
  declare function startUiServer(options: UiServerOptions): UiServerHandle;
977
1129
 
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
1130
  declare function createUiRouter(options: UiRouterOptions): Hono;
1029
1131
 
1030
1132
  type ExecuteActionResult = {
@@ -1075,4 +1177,4 @@ declare function getUiBridgeSecretPath(): string;
1075
1177
  declare function readUiBridgeSecret(): string | null;
1076
1178
  declare function ensureUiBridgeSecret(): string;
1077
1179
 
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 };
1180
+ 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 RemoteBrowserAuthPollRequest, type RemoteBrowserAuthPollResult, type RemoteBrowserAuthStartRequest, type RemoteBrowserAuthStartResult, 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,119 @@ 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
+ startBrowserAuth = async (c) => {
4898
+ const body = await readJson(c.req.raw);
4899
+ if (!body.ok) {
4900
+ return c.json(err("INVALID_BODY", "invalid json body"), 400);
4901
+ }
4902
+ try {
4903
+ return c.json(ok(await this.host.startBrowserAuth({
4904
+ apiBase: readTrimmedString(body.data.apiBase)
4905
+ })));
4906
+ } catch (error) {
4907
+ return c.json(err("REMOTE_BROWSER_AUTH_START_FAILED", formatUserFacingError(error)), 400);
4908
+ }
4909
+ };
4910
+ pollBrowserAuth = async (c) => {
4911
+ const body = await readJson(c.req.raw);
4912
+ if (!body.ok) {
4913
+ return c.json(err("INVALID_BODY", "invalid json body"), 400);
4914
+ }
4915
+ const sessionId = readNonEmptyString(body.data.sessionId);
4916
+ if (!sessionId) {
4917
+ return c.json(err("INVALID_BODY", "sessionId is required"), 400);
4918
+ }
4919
+ try {
4920
+ return c.json(ok(await this.host.pollBrowserAuth({
4921
+ sessionId,
4922
+ apiBase: readTrimmedString(body.data.apiBase)
4923
+ })));
4924
+ } catch (error) {
4925
+ return c.json(err("REMOTE_BROWSER_AUTH_POLL_FAILED", formatUserFacingError(error)), 400);
4926
+ }
4927
+ };
4928
+ logout = async (c) => {
4929
+ try {
4930
+ return c.json(ok(await this.host.logout()));
4931
+ } catch (error) {
4932
+ return c.json(err("REMOTE_LOGOUT_FAILED", formatUserFacingError(error)), 500);
4933
+ }
4934
+ };
4935
+ updateSettings = async (c) => {
4936
+ const body = await readJson(c.req.raw);
4937
+ if (!body.ok) {
4938
+ return c.json(err("INVALID_BODY", "invalid json body"), 400);
4939
+ }
4940
+ try {
4941
+ return c.json(ok(await this.host.updateSettings({
4942
+ enabled: readBoolean(body.data.enabled),
4943
+ deviceName: readTrimmedString(body.data.deviceName),
4944
+ platformApiBase: readTrimmedString(body.data.platformApiBase)
4945
+ })));
4946
+ } catch (error) {
4947
+ return c.json(err("REMOTE_SETTINGS_FAILED", formatUserFacingError(error)), 400);
4948
+ }
4949
+ };
4950
+ controlService = async (c) => {
4951
+ const action = c.req.param("action");
4952
+ if (!REMOTE_SERVICE_ACTIONS.has(action)) {
4953
+ return c.json(err("INVALID_ACTION", "unsupported remote service action"), 400);
4954
+ }
4955
+ try {
4956
+ return c.json(ok(await this.host.controlService(action)));
4957
+ } catch (error) {
4958
+ return c.json(err("REMOTE_SERVICE_FAILED", formatUserFacingError(error)), 400);
4959
+ }
4960
+ };
4961
+ };
4962
+
4850
4963
  // src/ui/router/session.controller.ts
4851
4964
  var SessionRoutesController = class {
4852
4965
  constructor(options) {
@@ -4926,37 +5039,7 @@ function registerAuthRoutes(app, authController) {
4926
5039
  app.put("/api/auth/enabled", authController.updateEnabled);
4927
5040
  app.post("/api/auth/bridge", authController.issueBridgeSession);
4928
5041
  }
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);
5042
+ function registerConfigRoutes(app, configController) {
4960
5043
  app.get("/api/config", configController.getConfig);
4961
5044
  app.get("/api/config/meta", configController.getConfigMeta);
4962
5045
  app.get("/api/config/schema", configController.getConfigSchema);
@@ -4973,6 +5056,8 @@ function createUiRouter(options) {
4973
5056
  app.put("/api/config/secrets", configController.updateSecrets);
4974
5057
  app.put("/api/config/runtime", configController.updateRuntime);
4975
5058
  app.post("/api/config/actions/:actionId/execute", configController.executeAction);
5059
+ }
5060
+ function registerChatRoutes(app, chatController) {
4976
5061
  app.get("/api/chat/capabilities", chatController.getCapabilities);
4977
5062
  app.get("/api/chat/session-types", chatController.getSessionTypes);
4978
5063
  app.get("/api/chat/commands", chatController.getCommands);
@@ -4982,27 +5067,86 @@ function createUiRouter(options) {
4982
5067
  app.get("/api/chat/runs", chatController.listRuns);
4983
5068
  app.get("/api/chat/runs/:runId", chatController.getRun);
4984
5069
  app.get("/api/chat/runs/:runId/stream", chatController.streamRun);
5070
+ }
5071
+ function registerSessionRoutes(app, sessionController) {
4985
5072
  app.get("/api/sessions", sessionController.listSessions);
4986
5073
  app.get("/api/sessions/:key/history", sessionController.getSessionHistory);
4987
5074
  app.put("/api/sessions/:key", sessionController.patchSession);
4988
5075
  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);
5076
+ }
5077
+ function registerNcpRoutes(app, options, ncpSessionController) {
5078
+ if (!options.ncpAgent) {
5079
+ return;
5001
5080
  }
5081
+ mountNcpHttpAgentRoutes(app, {
5082
+ basePath: options.ncpAgent.basePath ?? "/api/ncp/agent",
5083
+ agentClientEndpoint: options.ncpAgent.agentClientEndpoint,
5084
+ streamProvider: options.ncpAgent.streamProvider
5085
+ });
5086
+ app.get("/api/ncp/session-types", ncpSessionController.getSessionTypes);
5087
+ app.get("/api/ncp/sessions", ncpSessionController.listSessions);
5088
+ app.get("/api/ncp/sessions/:sessionId", ncpSessionController.getSession);
5089
+ app.put("/api/ncp/sessions/:sessionId", ncpSessionController.patchSession);
5090
+ app.get("/api/ncp/sessions/:sessionId/messages", ncpSessionController.listSessionMessages);
5091
+ app.delete("/api/ncp/sessions/:sessionId", ncpSessionController.deleteSession);
5092
+ }
5093
+ function registerCronRoutes(app, cronController) {
5002
5094
  app.get("/api/cron", cronController.listJobs);
5003
5095
  app.delete("/api/cron/:id", cronController.deleteJob);
5004
5096
  app.put("/api/cron/:id/enable", cronController.enableJob);
5005
5097
  app.post("/api/cron/:id/run", cronController.runJob);
5098
+ }
5099
+ function registerRemoteRoutes(app, remoteController) {
5100
+ if (!remoteController) {
5101
+ return;
5102
+ }
5103
+ app.get("/api/remote/status", remoteController.getStatus);
5104
+ app.get("/api/remote/doctor", remoteController.getDoctor);
5105
+ app.post("/api/remote/login", remoteController.login);
5106
+ app.post("/api/remote/auth/start", remoteController.startBrowserAuth);
5107
+ app.post("/api/remote/auth/poll", remoteController.pollBrowserAuth);
5108
+ app.post("/api/remote/logout", remoteController.logout);
5109
+ app.put("/api/remote/settings", remoteController.updateSettings);
5110
+ app.post("/api/remote/service/:action", remoteController.controlService);
5111
+ }
5112
+ function createUiRouter(options) {
5113
+ const app = new Hono();
5114
+ const marketplaceBaseUrl = normalizeMarketplaceBaseUrl(options);
5115
+ const authService = options.authService ?? new UiAuthService(options.configPath);
5116
+ const appController = new AppRoutesController(options);
5117
+ const authController = new AuthRoutesController(authService);
5118
+ const configController = new ConfigRoutesController(options);
5119
+ const chatController = new ChatRoutesController(options);
5120
+ const sessionController = new SessionRoutesController(options);
5121
+ const cronController = new CronRoutesController(options);
5122
+ const ncpSessionController = new NcpSessionRoutesController(options);
5123
+ const remoteController = options.remoteAccess ? new RemoteRoutesController(options.remoteAccess) : null;
5124
+ const pluginMarketplaceController = new PluginMarketplaceController(options, marketplaceBaseUrl);
5125
+ const skillMarketplaceController = new SkillMarketplaceController(options, marketplaceBaseUrl);
5126
+ const mcpMarketplaceController = new McpMarketplaceController(options, marketplaceBaseUrl);
5127
+ app.notFound((c) => c.json(err("NOT_FOUND", "endpoint not found"), 404));
5128
+ app.use("/api/*", async (c, next) => {
5129
+ const path = c.req.path;
5130
+ if (path === "/api/health" || path.startsWith("/api/auth/")) {
5131
+ await next();
5132
+ return;
5133
+ }
5134
+ if (!authService.isProtectionEnabled() || authService.isRequestAuthenticated(c.req.raw)) {
5135
+ await next();
5136
+ return;
5137
+ }
5138
+ c.status(401);
5139
+ return c.json(err("UNAUTHORIZED", "Authentication required."), 401);
5140
+ });
5141
+ app.get("/api/health", appController.health);
5142
+ app.get("/api/app/meta", appController.appMeta);
5143
+ registerAuthRoutes(app, authController);
5144
+ registerConfigRoutes(app, configController);
5145
+ registerChatRoutes(app, chatController);
5146
+ registerSessionRoutes(app, sessionController);
5147
+ registerNcpRoutes(app, options, ncpSessionController);
5148
+ registerCronRoutes(app, cronController);
5149
+ registerRemoteRoutes(app, remoteController);
5006
5150
  mountMarketplaceRoutes(app, {
5007
5151
  plugin: pluginMarketplaceController,
5008
5152
  skill: skillMarketplaceController,
@@ -5047,7 +5191,8 @@ function startUiServer(options) {
5047
5191
  cronService: options.cronService,
5048
5192
  chatRuntime: options.chatRuntime,
5049
5193
  ncpAgent: options.ncpAgent,
5050
- authService
5194
+ authService,
5195
+ remoteAccess: options.remoteAccess
5051
5196
  })
5052
5197
  );
5053
5198
  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.10",
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/mcp": "0.1.10",
21
22
  "@nextclaw/ncp": "0.3.1",
22
23
  "@nextclaw/openclaw-compat": "0.3.8",
23
- "@nextclaw/ncp-http-agent-server": "0.3.1",
24
- "@nextclaw/runtime": "0.2.5",
25
24
  "@nextclaw/core": "0.9.5",
26
- "@nextclaw/mcp": "0.1.8"
25
+ "@nextclaw/ncp-http-agent-server": "0.3.1",
26
+ "@nextclaw/runtime": "0.2.5"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@types/node": "^20.17.6",