@nextclaw/server 0.7.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  import * as NextclawCore from '@nextclaw/core';
2
2
  import { ThinkingLevel, CronService, Config, ConfigActionExecuteRequest as ConfigActionExecuteRequest$1, ConfigActionExecuteResult as ConfigActionExecuteResult$1 } from '@nextclaw/core';
3
+ import { NcpAgentClientEndpoint, NcpSessionApi, NcpSessionSummary, NcpMessage } from '@nextclaw/ncp';
4
+ import { NcpHttpAgentStreamProvider } from '@nextclaw/ncp-http-agent-server';
3
5
  import { Hono } from 'hono';
4
6
  import { IncomingMessage } from 'node:http';
5
7
 
@@ -226,6 +228,7 @@ type SessionHistoryView = {
226
228
  type SessionPatchUpdate = {
227
229
  label?: string | null;
228
230
  preferredModel?: string | null;
231
+ preferredThinking?: ThinkingLevel | null;
229
232
  sessionType?: string | null;
230
233
  clearHistory?: boolean;
231
234
  };
@@ -450,6 +453,22 @@ type UiChatRuntime = {
450
453
  listSessionTypes?: () => Promise<ChatSessionTypesView> | ChatSessionTypesView;
451
454
  stopTurn?: (params: ChatTurnStopRequest) => Promise<ChatTurnStopResult> | ChatTurnStopResult;
452
455
  };
456
+ type UiNcpSessionListView = {
457
+ sessions: NcpSessionSummary[];
458
+ total: number;
459
+ };
460
+ type UiNcpSessionMessagesView = {
461
+ sessionId: string;
462
+ messages: NcpMessage[];
463
+ total: number;
464
+ };
465
+ type UiNcpAgent = {
466
+ agentClientEndpoint: NcpAgentClientEndpoint;
467
+ streamProvider?: NcpHttpAgentStreamProvider;
468
+ sessionApi?: NcpSessionApi;
469
+ listSessionTypes?: () => Promise<ChatSessionTypesView> | ChatSessionTypesView;
470
+ basePath?: string;
471
+ };
453
472
  type ConfigView = {
454
473
  agents: {
455
474
  defaults: {
@@ -831,6 +850,7 @@ type UiServerOptions = {
831
850
  marketplace?: MarketplaceApiConfig;
832
851
  cronService?: CronService;
833
852
  chatRuntime?: UiChatRuntime;
853
+ ncpAgent?: UiNcpAgent;
834
854
  };
835
855
  type UiServerHandle = {
836
856
  host: string;
@@ -886,6 +906,7 @@ type UiRouterOptions = {
886
906
  marketplace?: MarketplaceApiConfig;
887
907
  cronService?: InstanceType<typeof NextclawCore.CronService>;
888
908
  chatRuntime?: UiChatRuntime;
909
+ ncpAgent?: UiNcpAgent;
889
910
  authService?: UiAuthService;
890
911
  };
891
912
 
@@ -919,8 +940,8 @@ declare function testProviderConnection(configPath: string, providerName: string
919
940
  declare function updateChannel(configPath: string, channelName: string, patch: Record<string, unknown>): Record<string, unknown> | null;
920
941
  declare const DEFAULT_SESSION_TYPE = "native";
921
942
  declare class SessionPatchValidationError extends Error {
922
- readonly code: "SESSION_TYPE_INVALID" | "SESSION_TYPE_IMMUTABLE" | "SESSION_TYPE_UNAVAILABLE";
923
- constructor(code: "SESSION_TYPE_INVALID" | "SESSION_TYPE_IMMUTABLE" | "SESSION_TYPE_UNAVAILABLE", message: string);
943
+ readonly code: "SESSION_TYPE_INVALID" | "SESSION_TYPE_IMMUTABLE" | "SESSION_TYPE_UNAVAILABLE" | "PREFERRED_THINKING_INVALID";
944
+ constructor(code: "SESSION_TYPE_INVALID" | "SESSION_TYPE_IMMUTABLE" | "SESSION_TYPE_UNAVAILABLE" | "PREFERRED_THINKING_INVALID", message: string);
924
945
  }
925
946
  declare function listSessions(configPath: string, query?: {
926
947
  q?: string;
@@ -935,4 +956,4 @@ declare function deleteSession(configPath: string, key: string): boolean;
935
956
  declare function updateRuntime(configPath: string, patch: RuntimeConfigUpdate): Pick<ConfigView, "agents" | "bindings" | "session">;
936
957
  declare function updateSecrets(configPath: string, patch: SecretsConfigUpdate): SecretsView;
937
958
 
938
- 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 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 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 UiServerEvent, type UiServerHandle, type UiServerOptions, buildConfigMeta, buildConfigSchemaView, buildConfigView, createCustomProvider, createUiRouter, deleteCustomProvider, deleteSession, executeConfigAction, getSessionHistory, listSessions, loadConfigOrDefault, patchSession, startUiServer, testProviderConnection, updateChannel, updateModel, updateProvider, updateRuntime, updateSearch, updateSecrets };
959
+ 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 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 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, executeConfigAction, getSessionHistory, listSessions, loadConfigOrDefault, patchSession, startUiServer, testProviderConnection, updateChannel, updateModel, updateProvider, updateRuntime, updateSearch, updateSecrets };
package/dist/index.js CHANGED
@@ -320,6 +320,7 @@ var UiAuthService = class {
320
320
 
321
321
  // src/ui/router.ts
322
322
  import { Hono } from "hono";
323
+ import { mountNcpHttpAgentRoutes } from "@nextclaw/ncp-http-agent-server";
323
324
 
324
325
  // src/ui/router/response.ts
325
326
  function ok(data) {
@@ -511,7 +512,7 @@ import {
511
512
  SessionManager,
512
513
  getWorkspacePathFromConfig,
513
514
  normalizeThinkingLevels,
514
- parseThinkingLevel
515
+ parseThinkingLevel as parseThinkingLevel2
515
516
  } from "@nextclaw/core";
516
517
 
517
518
  // src/ui/provider-overrides.ts
@@ -602,6 +603,42 @@ function findServerBuiltinProviderByName(name) {
602
603
  return SERVER_BUILTIN_PROVIDER_OVERRIDE_MAP.get(name) ?? findBuiltinProviderByName(name);
603
604
  }
604
605
 
606
+ // src/ui/session-preference-patch.ts
607
+ import { parseThinkingLevel } from "@nextclaw/core";
608
+ function applySessionPreferencePatch(params) {
609
+ const nextMetadata = params.metadata;
610
+ const { patch } = params;
611
+ if (Object.prototype.hasOwnProperty.call(patch, "label")) {
612
+ const label = typeof patch.label === "string" ? patch.label.trim() : "";
613
+ if (label) {
614
+ nextMetadata.label = label;
615
+ } else {
616
+ delete nextMetadata.label;
617
+ }
618
+ }
619
+ if (Object.prototype.hasOwnProperty.call(patch, "preferredModel")) {
620
+ const preferredModel = typeof patch.preferredModel === "string" ? patch.preferredModel.trim() : "";
621
+ if (preferredModel) {
622
+ nextMetadata.preferred_model = preferredModel;
623
+ } else {
624
+ delete nextMetadata.preferred_model;
625
+ }
626
+ }
627
+ if (Object.prototype.hasOwnProperty.call(patch, "preferredThinking")) {
628
+ const preferredThinking = typeof patch.preferredThinking === "string" ? patch.preferredThinking.trim() : "";
629
+ if (!preferredThinking) {
630
+ delete nextMetadata.preferred_thinking;
631
+ } else {
632
+ const normalizedThinking = parseThinkingLevel(preferredThinking);
633
+ if (!normalizedThinking) {
634
+ throw params.createInvalidThinkingError("preferredThinking must be a supported thinking level");
635
+ }
636
+ nextMetadata.preferred_thinking = normalizedThinking;
637
+ }
638
+ }
639
+ return nextMetadata;
640
+ }
641
+
605
642
  // src/ui/config.ts
606
643
  var MASK_MIN_LENGTH = 8;
607
644
  var EXTRA_SENSITIVE_PATH_PATTERNS = [/authorization/i, /cookie/i, /session/i, /bearer/i];
@@ -954,7 +991,7 @@ function normalizeModelThinkingConfig(input) {
954
991
  if (supported.length === 0) {
955
992
  continue;
956
993
  }
957
- const defaultLevel = parseThinkingLevel(rawValue.default);
994
+ const defaultLevel = parseThinkingLevel2(rawValue.default);
958
995
  if (defaultLevel && supported.includes(defaultLevel)) {
959
996
  normalized[model] = { supported, default: defaultLevel };
960
997
  } else {
@@ -1668,22 +1705,11 @@ function patchSession(configPath, key, patch, options) {
1668
1705
  if (patch.clearHistory) {
1669
1706
  sessionManager.clear(session);
1670
1707
  }
1671
- if (Object.prototype.hasOwnProperty.call(patch, "label")) {
1672
- const label = typeof patch.label === "string" ? patch.label.trim() : "";
1673
- if (label) {
1674
- session.metadata.label = label;
1675
- } else {
1676
- delete session.metadata.label;
1677
- }
1678
- }
1679
- if (Object.prototype.hasOwnProperty.call(patch, "preferredModel")) {
1680
- const preferredModel = typeof patch.preferredModel === "string" ? patch.preferredModel.trim() : "";
1681
- if (preferredModel) {
1682
- session.metadata.preferred_model = preferredModel;
1683
- } else {
1684
- delete session.metadata.preferred_model;
1685
- }
1686
- }
1708
+ applySessionPreferencePatch({
1709
+ metadata: session.metadata,
1710
+ patch,
1711
+ createInvalidThinkingError: (message) => new SessionPatchValidationError("PREFERRED_THINKING_INVALID", message)
1712
+ });
1687
1713
  if (Object.prototype.hasOwnProperty.call(patch, "sessionType")) {
1688
1714
  const normalizedSessionType = normalizeSessionType(patch.sessionType);
1689
1715
  if (!normalizedSessionType) {
@@ -1821,13 +1847,7 @@ function resolveSessionTypeLabel(sessionType) {
1821
1847
  if (sessionType === "native") {
1822
1848
  return "Native";
1823
1849
  }
1824
- if (sessionType === "codex-sdk") {
1825
- return "Codex";
1826
- }
1827
- if (sessionType === "claude-agent-sdk") {
1828
- return "Claude Code";
1829
- }
1830
- return sessionType;
1850
+ return sessionType.trim().split(/[-_]+/g).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ") || sessionType;
1831
1851
  }
1832
1852
  async function buildChatSessionTypesView(chatRuntime) {
1833
1853
  if (!chatRuntime?.listSessionTypes) {
@@ -3267,10 +3287,143 @@ var CronRoutesController = class {
3267
3287
  };
3268
3288
  };
3269
3289
 
3290
+ // src/ui/router/ncp-session.controller.ts
3291
+ function readPositiveInt(value) {
3292
+ if (typeof value !== "string") {
3293
+ return void 0;
3294
+ }
3295
+ const parsed = Number.parseInt(value, 10);
3296
+ if (!Number.isFinite(parsed) || parsed <= 0) {
3297
+ return void 0;
3298
+ }
3299
+ return parsed;
3300
+ }
3301
+ var NcpSessionRoutesController = class {
3302
+ constructor(options) {
3303
+ this.options = options;
3304
+ }
3305
+ getSessionTypes = async (c) => {
3306
+ const listSessionTypes = this.options.ncpAgent?.listSessionTypes;
3307
+ const payload = listSessionTypes ? await listSessionTypes() : {
3308
+ defaultType: "native",
3309
+ options: [{ value: "native", label: "Native" }]
3310
+ };
3311
+ return c.json(ok(payload));
3312
+ };
3313
+ listSessions = async (c) => {
3314
+ const sessionApi = this.options.ncpAgent?.sessionApi;
3315
+ if (!sessionApi) {
3316
+ return c.json(err("NOT_AVAILABLE", "ncp session api unavailable"), 503);
3317
+ }
3318
+ const sessions = await sessionApi.listSessions({
3319
+ limit: readPositiveInt(c.req.query("limit"))
3320
+ });
3321
+ const payload = {
3322
+ sessions,
3323
+ total: sessions.length
3324
+ };
3325
+ return c.json(ok(payload));
3326
+ };
3327
+ getSession = async (c) => {
3328
+ const sessionApi = this.options.ncpAgent?.sessionApi;
3329
+ if (!sessionApi) {
3330
+ return c.json(err("NOT_AVAILABLE", "ncp session api unavailable"), 503);
3331
+ }
3332
+ const sessionId = decodeURIComponent(c.req.param("sessionId"));
3333
+ const session = await sessionApi.getSession(sessionId);
3334
+ if (!session) {
3335
+ return c.json(err("NOT_FOUND", `ncp session not found: ${sessionId}`), 404);
3336
+ }
3337
+ return c.json(ok(session));
3338
+ };
3339
+ listSessionMessages = async (c) => {
3340
+ const sessionApi = this.options.ncpAgent?.sessionApi;
3341
+ if (!sessionApi) {
3342
+ return c.json(err("NOT_AVAILABLE", "ncp session api unavailable"), 503);
3343
+ }
3344
+ const sessionId = decodeURIComponent(c.req.param("sessionId"));
3345
+ const session = await sessionApi.getSession(sessionId);
3346
+ if (!session) {
3347
+ return c.json(err("NOT_FOUND", `ncp session not found: ${sessionId}`), 404);
3348
+ }
3349
+ const messages = await sessionApi.listSessionMessages(sessionId, {
3350
+ limit: readPositiveInt(c.req.query("limit"))
3351
+ });
3352
+ const payload = {
3353
+ sessionId,
3354
+ messages,
3355
+ total: messages.length
3356
+ };
3357
+ return c.json(ok(payload));
3358
+ };
3359
+ patchSession = async (c) => {
3360
+ const sessionApi = this.options.ncpAgent?.sessionApi;
3361
+ if (!sessionApi) {
3362
+ return c.json(err("NOT_AVAILABLE", "ncp session api unavailable"), 503);
3363
+ }
3364
+ const sessionId = decodeURIComponent(c.req.param("sessionId"));
3365
+ const body = await readJson(c.req.raw);
3366
+ if (!body.ok || !body.data || typeof body.data !== "object") {
3367
+ return c.json(err("INVALID_BODY", "invalid json body"), 400);
3368
+ }
3369
+ const patch = body.data;
3370
+ if (patch.clearHistory) {
3371
+ return c.json(err("UNSUPPORTED_PATCH", "clearHistory is not supported for ncp sessions"), 400);
3372
+ }
3373
+ const existing = await sessionApi.getSession(sessionId);
3374
+ if (!existing) {
3375
+ return c.json(err("NOT_FOUND", `ncp session not found: ${sessionId}`), 404);
3376
+ }
3377
+ const metadata = existing.metadata && typeof existing.metadata === "object" && !Array.isArray(existing.metadata) ? existing.metadata : {};
3378
+ let updated;
3379
+ try {
3380
+ const nextMetadata = applySessionPreferencePatch({
3381
+ metadata: structuredClone(metadata),
3382
+ patch,
3383
+ createInvalidThinkingError: () => new Error("PREFERRED_THINKING_INVALID")
3384
+ });
3385
+ if (Object.prototype.hasOwnProperty.call(patch, "sessionType")) {
3386
+ const sessionType = typeof patch.sessionType === "string" ? patch.sessionType.trim() : "";
3387
+ if (sessionType) {
3388
+ nextMetadata.session_type = sessionType;
3389
+ } else {
3390
+ delete nextMetadata.session_type;
3391
+ }
3392
+ }
3393
+ updated = await sessionApi.updateSession(sessionId, {
3394
+ metadata: nextMetadata
3395
+ });
3396
+ } catch (error) {
3397
+ if (error instanceof Error && error.message === "PREFERRED_THINKING_INVALID") {
3398
+ return c.json(err("PREFERRED_THINKING_INVALID", "preferredThinking must be a supported thinking level"), 400);
3399
+ }
3400
+ throw error;
3401
+ }
3402
+ if (!updated) {
3403
+ return c.json(err("NOT_FOUND", `ncp session not found: ${sessionId}`), 404);
3404
+ }
3405
+ this.options.publish({ type: "config.updated", payload: { path: "session" } });
3406
+ return c.json(ok(updated));
3407
+ };
3408
+ deleteSession = async (c) => {
3409
+ const sessionApi = this.options.ncpAgent?.sessionApi;
3410
+ if (!sessionApi) {
3411
+ return c.json(err("NOT_AVAILABLE", "ncp session api unavailable"), 503);
3412
+ }
3413
+ const sessionId = decodeURIComponent(c.req.param("sessionId"));
3414
+ const existing = await sessionApi.getSession(sessionId);
3415
+ if (!existing) {
3416
+ return c.json(err("NOT_FOUND", `ncp session not found: ${sessionId}`), 404);
3417
+ }
3418
+ await sessionApi.deleteSession(sessionId);
3419
+ this.options.publish({ type: "config.updated", payload: { path: "session" } });
3420
+ return c.json(ok({ deleted: true, sessionId }));
3421
+ };
3422
+ };
3423
+
3270
3424
  // src/ui/router/marketplace/constants.ts
3271
3425
  var DEFAULT_MARKETPLACE_API_BASE = "https://marketplace-api.nextclaw.io";
3272
3426
  var NEXTCLAW_PLUGIN_NPM_PREFIX = "@nextclaw/channel-plugin-";
3273
- var CLAWBAY_CHANNEL_PLUGIN_NPM_SPEC = "@clawbay/clawbay-channel";
3274
3427
  var BUILTIN_CHANNEL_PLUGIN_ID_PREFIX = "builtin-channel-";
3275
3428
  var MARKETPLACE_REMOTE_PAGE_SIZE = 100;
3276
3429
  var MARKETPLACE_REMOTE_MAX_PAGES = 20;
@@ -3584,7 +3737,7 @@ function normalizePluginNpmSpec(rawSpec) {
3584
3737
  }
3585
3738
  function isSupportedMarketplacePluginSpec(rawSpec) {
3586
3739
  const spec = normalizePluginNpmSpec(rawSpec);
3587
- return spec.startsWith(NEXTCLAW_PLUGIN_NPM_PREFIX) || spec === CLAWBAY_CHANNEL_PLUGIN_NPM_SPEC;
3740
+ return spec.length > 0;
3588
3741
  }
3589
3742
  function resolvePluginCanonicalSpec(params) {
3590
3743
  const rawInstallSpec = typeof params.installSpec === "string" ? params.installSpec.trim() : "";
@@ -4464,6 +4617,7 @@ function createUiRouter(options) {
4464
4617
  const chatController = new ChatRoutesController(options);
4465
4618
  const sessionController = new SessionRoutesController(options);
4466
4619
  const cronController = new CronRoutesController(options);
4620
+ const ncpSessionController = new NcpSessionRoutesController(options);
4467
4621
  const pluginMarketplaceController = new PluginMarketplaceController(options, marketplaceBaseUrl);
4468
4622
  const skillMarketplaceController = new SkillMarketplaceController(options, marketplaceBaseUrl);
4469
4623
  app.notFound((c) => c.json(err("NOT_FOUND", "endpoint not found"), 404));
@@ -4517,6 +4671,19 @@ function createUiRouter(options) {
4517
4671
  app.get("/api/sessions/:key/history", sessionController.getSessionHistory);
4518
4672
  app.put("/api/sessions/:key", sessionController.patchSession);
4519
4673
  app.delete("/api/sessions/:key", sessionController.deleteSession);
4674
+ if (options.ncpAgent) {
4675
+ mountNcpHttpAgentRoutes(app, {
4676
+ basePath: options.ncpAgent.basePath ?? "/api/ncp/agent",
4677
+ agentClientEndpoint: options.ncpAgent.agentClientEndpoint,
4678
+ streamProvider: options.ncpAgent.streamProvider
4679
+ });
4680
+ app.get("/api/ncp/session-types", ncpSessionController.getSessionTypes);
4681
+ app.get("/api/ncp/sessions", ncpSessionController.listSessions);
4682
+ app.get("/api/ncp/sessions/:sessionId", ncpSessionController.getSession);
4683
+ app.put("/api/ncp/sessions/:sessionId", ncpSessionController.patchSession);
4684
+ app.get("/api/ncp/sessions/:sessionId/messages", ncpSessionController.listSessionMessages);
4685
+ app.delete("/api/ncp/sessions/:sessionId", ncpSessionController.deleteSession);
4686
+ }
4520
4687
  app.get("/api/cron", cronController.listJobs);
4521
4688
  app.delete("/api/cron/:id", cronController.deleteJob);
4522
4689
  app.put("/api/cron/:id/enable", cronController.enableJob);
@@ -4573,6 +4740,7 @@ function startUiServer(options) {
4573
4740
  marketplace: options.marketplace,
4574
4741
  cronService: options.cronService,
4575
4742
  chatRuntime: options.chatRuntime,
4743
+ ncpAgent: options.ncpAgent,
4576
4744
  authService
4577
4745
  })
4578
4746
  );
@@ -4641,7 +4809,9 @@ function startUiServer(options) {
4641
4809
  publish,
4642
4810
  close: () => new Promise((resolve2) => {
4643
4811
  wss.close(() => {
4644
- server.close(() => resolve2());
4812
+ server.close(() => {
4813
+ Promise.resolve(options.ncpAgent?.agentClientEndpoint.stop()).catch(() => void 0).finally(() => resolve2());
4814
+ });
4645
4815
  });
4646
4816
  })
4647
4817
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextclaw/server",
3
- "version": "0.7.0",
3
+ "version": "0.9.0",
4
4
  "private": false,
5
5
  "description": "Nextclaw UI/API server.",
6
6
  "type": "module",
@@ -18,9 +18,11 @@
18
18
  "@hono/node-server": "^1.13.3",
19
19
  "hono": "^4.6.2",
20
20
  "ws": "^8.18.0",
21
- "@nextclaw/openclaw-compat": "0.2.7",
22
- "@nextclaw/runtime": "0.1.7",
23
- "@nextclaw/core": "0.8.0"
21
+ "@nextclaw/ncp-http-agent-server": "0.3.0",
22
+ "@nextclaw/openclaw-compat": "0.3.1",
23
+ "@nextclaw/runtime": "0.2.0",
24
+ "@nextclaw/core": "0.9.0",
25
+ "@nextclaw/ncp": "0.3.0"
24
26
  },
25
27
  "devDependencies": {
26
28
  "@types/node": "^20.17.6",