@nextclaw/server 0.11.21 → 0.11.23
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 +35 -1
- package/dist/index.js +426 -109
- package/package.json +7 -7
package/dist/index.d.ts
CHANGED
|
@@ -760,8 +760,42 @@ type SessionPatchUpdate = {
|
|
|
760
760
|
preferredModel?: string | null;
|
|
761
761
|
preferredThinking?: ThinkingLevel | null;
|
|
762
762
|
sessionType?: string | null;
|
|
763
|
+
projectRoot?: string | null;
|
|
763
764
|
clearHistory?: boolean;
|
|
764
765
|
};
|
|
766
|
+
type SessionSkillEntryView = {
|
|
767
|
+
ref: string;
|
|
768
|
+
name: string;
|
|
769
|
+
path: string;
|
|
770
|
+
scope: "project" | "workspace";
|
|
771
|
+
source: "project" | "workspace";
|
|
772
|
+
available: boolean;
|
|
773
|
+
description?: string;
|
|
774
|
+
descriptionZh?: string;
|
|
775
|
+
};
|
|
776
|
+
type NcpSessionSkillsView = {
|
|
777
|
+
sessionId: string;
|
|
778
|
+
total: number;
|
|
779
|
+
refs: string[];
|
|
780
|
+
records: SessionSkillEntryView[];
|
|
781
|
+
};
|
|
782
|
+
type ServerPathEntryView = {
|
|
783
|
+
name: string;
|
|
784
|
+
path: string;
|
|
785
|
+
kind: "directory" | "file";
|
|
786
|
+
hidden: boolean;
|
|
787
|
+
};
|
|
788
|
+
type ServerPathBreadcrumbView = {
|
|
789
|
+
label: string;
|
|
790
|
+
path: string;
|
|
791
|
+
};
|
|
792
|
+
type ServerPathBrowseView = {
|
|
793
|
+
currentPath: string;
|
|
794
|
+
parentPath: string | null;
|
|
795
|
+
homePath: string;
|
|
796
|
+
breadcrumbs: ServerPathBreadcrumbView[];
|
|
797
|
+
entries: ServerPathEntryView[];
|
|
798
|
+
};
|
|
765
799
|
type CronScheduleView = {
|
|
766
800
|
kind: "at";
|
|
767
801
|
atMs?: number | null;
|
|
@@ -1183,4 +1217,4 @@ declare function getUiBridgeSecretPath(): string;
|
|
|
1183
1217
|
declare function readUiBridgeSecret(): string | null;
|
|
1184
1218
|
declare function ensureUiBridgeSecret(): string;
|
|
1185
1219
|
|
|
1186
|
-
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 BootstrapPhase, type BootstrapRemoteState, type BootstrapStageState, type BootstrapStatusView, type ChannelAuthPollRequest, type ChannelAuthPollResult, type ChannelAuthStartRequest, type ChannelAuthStartResult, type ChannelSpecView, type ChatSessionTypeCtaView, type ChatSessionTypeOptionView, type ChatSessionTypesView, 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 SessionTypeDescribeParams, type SessionsListView, type UiNcpAgent, type UiNcpAssetPutView, type UiNcpAssetView, type UiNcpSessionListView, type UiNcpSessionMessagesView, type UiNcpSessionService, type UiNcpStoredAssetRecord, 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 };
|
|
1220
|
+
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 BootstrapPhase, type BootstrapRemoteState, type BootstrapStageState, type BootstrapStatusView, type ChannelAuthPollRequest, type ChannelAuthPollResult, type ChannelAuthStartRequest, type ChannelAuthStartResult, type ChannelSpecView, type ChatSessionTypeCtaView, type ChatSessionTypeOptionView, type ChatSessionTypesView, 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 NcpSessionSkillsView, 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 ServerPathBreadcrumbView, type ServerPathBrowseView, type ServerPathEntryView, type SessionConfigView, type SessionEntryView, type SessionEventView, type SessionHistoryView, type SessionMessageView, type SessionPatchUpdate, SessionPatchValidationError, type SessionSkillEntryView, type SessionTypeDescribeParams, type SessionsListView, type UiNcpAgent, type UiNcpAssetPutView, type UiNcpAssetView, type UiNcpSessionListView, type UiNcpSessionMessagesView, type UiNcpSessionService, type UiNcpStoredAssetRecord, 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
|
@@ -4,7 +4,7 @@ import { compress } from "hono/compress";
|
|
|
4
4
|
import { serve } from "@hono/node-server";
|
|
5
5
|
import { WebSocketServer, WebSocket } from "ws";
|
|
6
6
|
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
7
|
-
import { readFile as readFile3, stat } from "fs/promises";
|
|
7
|
+
import { readFile as readFile3, stat as stat3 } from "fs/promises";
|
|
8
8
|
import { join as join2 } from "path";
|
|
9
9
|
|
|
10
10
|
// src/ui/auth.service.ts
|
|
@@ -3128,6 +3128,199 @@ var NcpAssetRoutesController = class {
|
|
|
3128
3128
|
};
|
|
3129
3129
|
};
|
|
3130
3130
|
|
|
3131
|
+
// src/ui/session-project/session-project-root.ts
|
|
3132
|
+
import { realpath, stat } from "fs/promises";
|
|
3133
|
+
import { resolve as resolve2 } from "path";
|
|
3134
|
+
import { expandHome } from "@nextclaw/core";
|
|
3135
|
+
var SessionProjectRootValidationError = class extends Error {
|
|
3136
|
+
constructor(code, message) {
|
|
3137
|
+
super(message);
|
|
3138
|
+
this.code = code;
|
|
3139
|
+
this.name = "SessionProjectRootValidationError";
|
|
3140
|
+
}
|
|
3141
|
+
};
|
|
3142
|
+
function resolveCandidateProjectRoot(value) {
|
|
3143
|
+
return resolve2(expandHome(value));
|
|
3144
|
+
}
|
|
3145
|
+
async function normalizeSessionProjectRoot(value) {
|
|
3146
|
+
if (value == null) {
|
|
3147
|
+
return null;
|
|
3148
|
+
}
|
|
3149
|
+
if (typeof value !== "string") {
|
|
3150
|
+
throw new SessionProjectRootValidationError(
|
|
3151
|
+
"PROJECT_ROOT_INVALID_TYPE",
|
|
3152
|
+
"projectRoot must be a string or null"
|
|
3153
|
+
);
|
|
3154
|
+
}
|
|
3155
|
+
const trimmed = value.trim();
|
|
3156
|
+
if (!trimmed) {
|
|
3157
|
+
return null;
|
|
3158
|
+
}
|
|
3159
|
+
const candidate = resolveCandidateProjectRoot(trimmed);
|
|
3160
|
+
let canonicalPath;
|
|
3161
|
+
try {
|
|
3162
|
+
canonicalPath = await realpath(candidate);
|
|
3163
|
+
} catch {
|
|
3164
|
+
throw new SessionProjectRootValidationError(
|
|
3165
|
+
"PROJECT_ROOT_NOT_FOUND",
|
|
3166
|
+
"projectRoot directory does not exist"
|
|
3167
|
+
);
|
|
3168
|
+
}
|
|
3169
|
+
const projectRootStats = await stat(canonicalPath);
|
|
3170
|
+
if (!projectRootStats.isDirectory()) {
|
|
3171
|
+
throw new SessionProjectRootValidationError(
|
|
3172
|
+
"PROJECT_ROOT_NOT_DIRECTORY",
|
|
3173
|
+
"projectRoot must point to a directory"
|
|
3174
|
+
);
|
|
3175
|
+
}
|
|
3176
|
+
return canonicalPath;
|
|
3177
|
+
}
|
|
3178
|
+
function isSessionProjectRootValidationError(error) {
|
|
3179
|
+
return error instanceof SessionProjectRootValidationError;
|
|
3180
|
+
}
|
|
3181
|
+
|
|
3182
|
+
// src/ui/session-project/session-skills.ts
|
|
3183
|
+
import * as NextclawCore from "@nextclaw/core";
|
|
3184
|
+
|
|
3185
|
+
// src/ui/router/marketplace/constants.ts
|
|
3186
|
+
var DEFAULT_MARKETPLACE_API_BASE = "https://marketplace-api.nextclaw.io";
|
|
3187
|
+
var NEXTCLAW_PLUGIN_NPM_PREFIX = "@nextclaw/channel-plugin-";
|
|
3188
|
+
var BUILTIN_CHANNEL_PLUGIN_ID_PREFIX = "builtin-channel-";
|
|
3189
|
+
var MARKETPLACE_REMOTE_PAGE_SIZE = 100;
|
|
3190
|
+
var MARKETPLACE_REMOTE_MAX_PAGES = 20;
|
|
3191
|
+
var MARKETPLACE_ZH_COPY_BY_SLUG = {
|
|
3192
|
+
weather: {
|
|
3193
|
+
summary: "NextClaw \u5185\u7F6E\u6280\u80FD\uFF0C\u7528\u4E8E\u5929\u6C14\u67E5\u8BE2\u5DE5\u4F5C\u6D41\u3002",
|
|
3194
|
+
description: "\u5728 NextClaw \u4E2D\u63D0\u4F9B\u5FEB\u901F\u5929\u6C14\u67E5\u8BE2\u5DE5\u4F5C\u6D41\u3002"
|
|
3195
|
+
},
|
|
3196
|
+
summarize: {
|
|
3197
|
+
summary: "NextClaw \u5185\u7F6E\u6280\u80FD\uFF0C\u7528\u4E8E\u7ED3\u6784\u5316\u6458\u8981\u3002",
|
|
3198
|
+
description: "\u5728 NextClaw \u4E2D\u63D0\u4F9B\u6587\u4EF6\u4E0E\u957F\u6587\u672C\u7684\u6458\u8981\u5DE5\u4F5C\u6D41\u3002"
|
|
3199
|
+
},
|
|
3200
|
+
github: {
|
|
3201
|
+
summary: "NextClaw \u5185\u7F6E\u6280\u80FD\uFF0C\u7528\u4E8E GitHub \u5DE5\u4F5C\u6D41\u3002",
|
|
3202
|
+
description: "\u5728 NextClaw \u4E2D\u63D0\u4F9B Issue\u3001PR \u4E0E\u4ED3\u5E93\u76F8\u5173\u5DE5\u4F5C\u6D41\u6307\u5F15\u3002"
|
|
3203
|
+
},
|
|
3204
|
+
tmux: {
|
|
3205
|
+
summary: "NextClaw \u5185\u7F6E\u6280\u80FD\uFF0C\u7528\u4E8E\u7EC8\u7AEF/Tmux \u534F\u4F5C\u5DE5\u4F5C\u6D41\u3002",
|
|
3206
|
+
description: "\u5728 NextClaw \u4E2D\u63D0\u4F9B\u57FA\u4E8E Tmux \u7684\u4EFB\u52A1\u6267\u884C\u5DE5\u4F5C\u6D41\u6307\u5F15\u3002"
|
|
3207
|
+
},
|
|
3208
|
+
gog: {
|
|
3209
|
+
summary: "NextClaw \u5185\u7F6E\u6280\u80FD\uFF0C\u7528\u4E8E\u56FE\u8C31\u5BFC\u5411\u751F\u6210\u5DE5\u4F5C\u6D41\u3002",
|
|
3210
|
+
description: "\u5728 NextClaw \u4E2D\u63D0\u4F9B\u56FE\u8C31\u4E0E\u89C4\u5212\u5BFC\u5411\u5DE5\u4F5C\u6D41\u6307\u5F15\u3002"
|
|
3211
|
+
},
|
|
3212
|
+
pdf: {
|
|
3213
|
+
summary: "Anthropic \u6280\u80FD\uFF0C\u7528\u4E8E PDF \u8BFB\u53D6/\u5408\u5E76/\u62C6\u5206/OCR \u5DE5\u4F5C\u6D41\u3002",
|
|
3214
|
+
description: "\u4F7F\u7528\u8BE5\u6280\u80FD\u53EF\u8BFB\u53D6\u3001\u63D0\u53D6\u3001\u5408\u5E76\u3001\u62C6\u5206\u3001\u65CB\u8F6C\u5E76\u5BF9 PDF \u6267\u884C OCR \u5904\u7406\u3002"
|
|
3215
|
+
},
|
|
3216
|
+
docx: {
|
|
3217
|
+
summary: "Anthropic \u6280\u80FD\uFF0C\u7528\u4E8E\u521B\u5EFA\u548C\u7F16\u8F91 Word \u6587\u6863\u3002",
|
|
3218
|
+
description: "\u4F7F\u7528\u8BE5\u6280\u80FD\u53EF\u521B\u5EFA\u3001\u8BFB\u53D6\u3001\u7F16\u8F91\u5E76\u91CD\u6784 .docx \u6587\u6863\u3002"
|
|
3219
|
+
},
|
|
3220
|
+
pptx: {
|
|
3221
|
+
summary: "Anthropic \u6280\u80FD\uFF0C\u7528\u4E8E\u6F14\u793A\u6587\u7A3F\u64CD\u4F5C\u3002",
|
|
3222
|
+
description: "\u4F7F\u7528\u8BE5\u6280\u80FD\u53EF\u521B\u5EFA\u3001\u89E3\u6790\u3001\u7F16\u8F91\u5E76\u91CD\u7EC4 .pptx \u6F14\u793A\u6587\u7A3F\u3002"
|
|
3223
|
+
},
|
|
3224
|
+
xlsx: {
|
|
3225
|
+
summary: "Anthropic \u6280\u80FD\uFF0C\u7528\u4E8E\u8868\u683C\u6587\u6863\u5DE5\u4F5C\u6D41\u3002",
|
|
3226
|
+
description: "\u4F7F\u7528\u8BE5\u6280\u80FD\u53EF\u6253\u5F00\u3001\u7F16\u8F91\u3001\u6E05\u6D17\u5E76\u8F6C\u6362 .xlsx \u4E0E .csv \u7B49\u8868\u683C\u6587\u4EF6\u3002"
|
|
3227
|
+
},
|
|
3228
|
+
bird: {
|
|
3229
|
+
summary: "OpenClaw \u793E\u533A\u6280\u80FD\uFF0C\u7528\u4E8E X/Twitter \u8BFB\u53D6/\u641C\u7D22/\u53D1\u5E03\u5DE5\u4F5C\u6D41\u3002",
|
|
3230
|
+
description: "\u4F7F\u7528 bird CLI \u5728\u4EE3\u7406\u5DE5\u4F5C\u6D41\u4E2D\u8BFB\u53D6\u7EBF\u7A0B\u3001\u641C\u7D22\u5E16\u5B50\u5E76\u8D77\u8349\u63A8\u6587/\u56DE\u590D\u3002"
|
|
3231
|
+
},
|
|
3232
|
+
"cloudflare-deploy": {
|
|
3233
|
+
summary: "OpenAI \u7CBE\u9009\u6280\u80FD\uFF0C\u7528\u4E8E\u5728 Cloudflare \u4E0A\u90E8\u7F72\u5E94\u7528\u4E0E\u57FA\u7840\u8BBE\u65BD\u3002",
|
|
3234
|
+
description: "\u4F7F\u7528\u8BE5\u6280\u80FD\u53EF\u9009\u62E9 Cloudflare \u4EA7\u54C1\u5E76\u90E8\u7F72 Workers\u3001Pages \u53CA\u76F8\u5173\u670D\u52A1\u3002"
|
|
3235
|
+
},
|
|
3236
|
+
"channel-plugin-discord": {
|
|
3237
|
+
summary: "NextClaw \u5B98\u65B9\u63D2\u4EF6\uFF0C\u7528\u4E8E Discord \u6E20\u9053\u96C6\u6210\u3002",
|
|
3238
|
+
description: "\u901A\u8FC7 NextClaw \u63D2\u4EF6\u8FD0\u884C\u65F6\u63D0\u4F9B Discord \u6E20\u9053\u7684\u5165\u7AD9/\u51FA\u7AD9\u652F\u6301\u3002"
|
|
3239
|
+
},
|
|
3240
|
+
"channel-plugin-telegram": {
|
|
3241
|
+
summary: "NextClaw \u5B98\u65B9\u63D2\u4EF6\uFF0C\u7528\u4E8E Telegram \u6E20\u9053\u96C6\u6210\u3002",
|
|
3242
|
+
description: "\u901A\u8FC7 NextClaw \u63D2\u4EF6\u8FD0\u884C\u65F6\u63D0\u4F9B Telegram \u6E20\u9053\u7684\u5165\u7AD9/\u51FA\u7AD9\u652F\u6301\u3002"
|
|
3243
|
+
},
|
|
3244
|
+
"channel-plugin-slack": {
|
|
3245
|
+
summary: "NextClaw \u5B98\u65B9\u63D2\u4EF6\uFF0C\u7528\u4E8E Slack \u6E20\u9053\u96C6\u6210\u3002",
|
|
3246
|
+
description: "\u901A\u8FC7 NextClaw \u63D2\u4EF6\u8FD0\u884C\u65F6\u63D0\u4F9B Slack \u6E20\u9053\u7684\u5165\u7AD9/\u51FA\u7AD9\u652F\u6301\u3002"
|
|
3247
|
+
},
|
|
3248
|
+
"channel-plugin-wecom": {
|
|
3249
|
+
summary: "NextClaw \u5B98\u65B9\u63D2\u4EF6\uFF0C\u7528\u4E8E\u4F01\u4E1A\u5FAE\u4FE1\u6E20\u9053\u96C6\u6210\u3002",
|
|
3250
|
+
description: "\u901A\u8FC7 NextClaw \u63D2\u4EF6\u8FD0\u884C\u65F6\u63D0\u4F9B\u4F01\u4E1A\u5FAE\u4FE1\u6E20\u9053\u7684\u5165\u7AD9/\u51FA\u7AD9\u652F\u6301\u3002"
|
|
3251
|
+
},
|
|
3252
|
+
"channel-plugin-email": {
|
|
3253
|
+
summary: "NextClaw \u5B98\u65B9\u63D2\u4EF6\uFF0C\u7528\u4E8E Email \u6E20\u9053\u96C6\u6210\u3002",
|
|
3254
|
+
description: "\u901A\u8FC7 NextClaw \u63D2\u4EF6\u8FD0\u884C\u65F6\u63D0\u4F9B Email \u6E20\u9053\u7684\u5165\u7AD9/\u51FA\u7AD9\u652F\u6301\u3002"
|
|
3255
|
+
},
|
|
3256
|
+
"channel-plugin-whatsapp": {
|
|
3257
|
+
summary: "NextClaw \u5B98\u65B9\u63D2\u4EF6\uFF0C\u7528\u4E8E WhatsApp \u6E20\u9053\u96C6\u6210\u3002",
|
|
3258
|
+
description: "\u901A\u8FC7 NextClaw \u63D2\u4EF6\u8FD0\u884C\u65F6\u63D0\u4F9B WhatsApp \u6E20\u9053\u7684\u5165\u7AD9/\u51FA\u7AD9\u652F\u6301\u3002"
|
|
3259
|
+
},
|
|
3260
|
+
"channel-plugin-clawbay": {
|
|
3261
|
+
summary: "Clawbay \u5B98\u65B9\u6E20\u9053\u63D2\u4EF6\uFF0C\u7528\u4E8E NextClaw \u96C6\u6210\u3002",
|
|
3262
|
+
description: "\u901A\u8FC7\u63D2\u4EF6\u8FD0\u884C\u65F6\u4E3A NextClaw \u63D0\u4F9B Clawbay \u6E20\u9053\u80FD\u529B\u3002"
|
|
3263
|
+
}
|
|
3264
|
+
};
|
|
3265
|
+
|
|
3266
|
+
// src/ui/session-project/session-skills.ts
|
|
3267
|
+
var SCOPE_SORT_ORDER = {
|
|
3268
|
+
project: 0,
|
|
3269
|
+
workspace: 1
|
|
3270
|
+
};
|
|
3271
|
+
var SessionSkillsViewBuilder = class {
|
|
3272
|
+
constructor(options) {
|
|
3273
|
+
this.options = options;
|
|
3274
|
+
}
|
|
3275
|
+
build = (params) => {
|
|
3276
|
+
const config = loadConfigOrDefault(this.options.configPath);
|
|
3277
|
+
const projectContext = NextclawCore.resolveSessionProjectContext({
|
|
3278
|
+
sessionMetadata: params.sessionMetadata,
|
|
3279
|
+
workspace: NextclawCore.getWorkspacePathFromConfig(config)
|
|
3280
|
+
});
|
|
3281
|
+
const skillsLoader = new NextclawCore.SkillsLoader({
|
|
3282
|
+
workspace: projectContext.hostWorkspace,
|
|
3283
|
+
projectRoot: projectContext.projectRoot
|
|
3284
|
+
});
|
|
3285
|
+
const availableRefs = new Set(
|
|
3286
|
+
skillsLoader.listSkills(true).map((skill) => skill.ref)
|
|
3287
|
+
);
|
|
3288
|
+
const records = skillsLoader.listSkills(false).map((skill) => this.buildRecord(skill, skillsLoader, availableRefs)).sort((left, right) => this.compareRecords(left, right));
|
|
3289
|
+
return {
|
|
3290
|
+
sessionId: params.sessionId,
|
|
3291
|
+
total: records.length,
|
|
3292
|
+
refs: records.map((record) => record.ref),
|
|
3293
|
+
records
|
|
3294
|
+
};
|
|
3295
|
+
};
|
|
3296
|
+
buildRecord = (skill, skillsLoader, availableRefs) => {
|
|
3297
|
+
const metadata = skillsLoader.getSkillMetadata(skill) ?? {};
|
|
3298
|
+
const description = readNonEmptyString(metadata.description);
|
|
3299
|
+
const descriptionZh = readNonEmptyString(metadata.description_zh) ?? readNonEmptyString(metadata.descriptionZh) ?? readNonEmptyString(MARKETPLACE_ZH_COPY_BY_SLUG[skill.name]?.description);
|
|
3300
|
+
return {
|
|
3301
|
+
ref: skill.ref,
|
|
3302
|
+
name: skill.name,
|
|
3303
|
+
path: skill.path,
|
|
3304
|
+
scope: skill.scope,
|
|
3305
|
+
source: skill.source,
|
|
3306
|
+
available: availableRefs.has(skill.ref),
|
|
3307
|
+
...description ? { description } : {},
|
|
3308
|
+
...descriptionZh ? { descriptionZh } : {}
|
|
3309
|
+
};
|
|
3310
|
+
};
|
|
3311
|
+
compareRecords = (left, right) => {
|
|
3312
|
+
const scopeCompare = SCOPE_SORT_ORDER[left.scope] - SCOPE_SORT_ORDER[right.scope];
|
|
3313
|
+
if (scopeCompare !== 0) {
|
|
3314
|
+
return scopeCompare;
|
|
3315
|
+
}
|
|
3316
|
+
const nameCompare = left.name.localeCompare(right.name);
|
|
3317
|
+
if (nameCompare !== 0) {
|
|
3318
|
+
return nameCompare;
|
|
3319
|
+
}
|
|
3320
|
+
return left.ref.localeCompare(right.ref);
|
|
3321
|
+
};
|
|
3322
|
+
};
|
|
3323
|
+
|
|
3131
3324
|
// src/ui/router/ncp-session.controller.ts
|
|
3132
3325
|
function readPositiveInt(value) {
|
|
3133
3326
|
if (typeof value !== "string") {
|
|
@@ -3139,10 +3332,54 @@ function readPositiveInt(value) {
|
|
|
3139
3332
|
}
|
|
3140
3333
|
return parsed;
|
|
3141
3334
|
}
|
|
3335
|
+
function readSessionMetadata(metadata) {
|
|
3336
|
+
if (!metadata || typeof metadata !== "object" || Array.isArray(metadata)) {
|
|
3337
|
+
return {};
|
|
3338
|
+
}
|
|
3339
|
+
return metadata;
|
|
3340
|
+
}
|
|
3341
|
+
function applySessionTypePatch(metadata, patch) {
|
|
3342
|
+
if (!Object.prototype.hasOwnProperty.call(patch, "sessionType")) {
|
|
3343
|
+
return;
|
|
3344
|
+
}
|
|
3345
|
+
const sessionType = typeof patch.sessionType === "string" ? patch.sessionType.trim() : "";
|
|
3346
|
+
if (sessionType) {
|
|
3347
|
+
metadata.session_type = sessionType;
|
|
3348
|
+
delete metadata.sessionType;
|
|
3349
|
+
return;
|
|
3350
|
+
}
|
|
3351
|
+
delete metadata.session_type;
|
|
3352
|
+
delete metadata.sessionType;
|
|
3353
|
+
}
|
|
3354
|
+
async function applyProjectRootPatch(metadata, patch) {
|
|
3355
|
+
if (!Object.prototype.hasOwnProperty.call(patch, "projectRoot")) {
|
|
3356
|
+
return;
|
|
3357
|
+
}
|
|
3358
|
+
const projectRoot = await normalizeSessionProjectRoot(patch.projectRoot);
|
|
3359
|
+
if (projectRoot) {
|
|
3360
|
+
metadata.project_root = projectRoot;
|
|
3361
|
+
delete metadata.projectRoot;
|
|
3362
|
+
return;
|
|
3363
|
+
}
|
|
3364
|
+
delete metadata.project_root;
|
|
3365
|
+
delete metadata.projectRoot;
|
|
3366
|
+
}
|
|
3367
|
+
async function buildPatchedSessionMetadata(params) {
|
|
3368
|
+
const nextMetadata = applySessionPreferencePatch({
|
|
3369
|
+
metadata: structuredClone(params.metadata),
|
|
3370
|
+
patch: params.patch,
|
|
3371
|
+
createInvalidThinkingError: () => new Error("PREFERRED_THINKING_INVALID")
|
|
3372
|
+
});
|
|
3373
|
+
applySessionTypePatch(nextMetadata, params.patch);
|
|
3374
|
+
await applyProjectRootPatch(nextMetadata, params.patch);
|
|
3375
|
+
return nextMetadata;
|
|
3376
|
+
}
|
|
3142
3377
|
var NcpSessionRoutesController = class {
|
|
3143
3378
|
constructor(options) {
|
|
3144
3379
|
this.options = options;
|
|
3380
|
+
this.sessionSkillsViewBuilder = new SessionSkillsViewBuilder(options);
|
|
3145
3381
|
}
|
|
3382
|
+
sessionSkillsViewBuilder;
|
|
3146
3383
|
getSessionTypes = async (c) => {
|
|
3147
3384
|
const listSessionTypes = this.options.ncpAgent?.listSessionTypes;
|
|
3148
3385
|
const payload = listSessionTypes ? await listSessionTypes({ describeMode: "observation" }) : {
|
|
@@ -3197,6 +3434,37 @@ var NcpSessionRoutesController = class {
|
|
|
3197
3434
|
};
|
|
3198
3435
|
return c.json(ok(payload));
|
|
3199
3436
|
};
|
|
3437
|
+
getSessionSkills = async (c) => {
|
|
3438
|
+
const sessionApi = this.options.ncpSessionService;
|
|
3439
|
+
if (!sessionApi) {
|
|
3440
|
+
return c.json(err("NOT_AVAILABLE", "ncp session api unavailable"), 503);
|
|
3441
|
+
}
|
|
3442
|
+
const sessionId = decodeURIComponent(c.req.param("sessionId"));
|
|
3443
|
+
const query = c.req.query();
|
|
3444
|
+
const hasProjectRootOverride = Object.prototype.hasOwnProperty.call(query, "projectRoot");
|
|
3445
|
+
const existing = await sessionApi.getSession(sessionId);
|
|
3446
|
+
const metadata = readSessionMetadata(existing?.metadata);
|
|
3447
|
+
if (hasProjectRootOverride) {
|
|
3448
|
+
try {
|
|
3449
|
+
const projectRoot = await normalizeSessionProjectRoot(query.projectRoot);
|
|
3450
|
+
if (projectRoot) {
|
|
3451
|
+
metadata.project_root = projectRoot;
|
|
3452
|
+
} else {
|
|
3453
|
+
delete metadata.project_root;
|
|
3454
|
+
delete metadata.projectRoot;
|
|
3455
|
+
}
|
|
3456
|
+
} catch (error) {
|
|
3457
|
+
if (isSessionProjectRootValidationError(error)) {
|
|
3458
|
+
return c.json(err(error.code, error.message), 400);
|
|
3459
|
+
}
|
|
3460
|
+
throw error;
|
|
3461
|
+
}
|
|
3462
|
+
}
|
|
3463
|
+
return c.json(ok(this.sessionSkillsViewBuilder.build({
|
|
3464
|
+
sessionId,
|
|
3465
|
+
sessionMetadata: metadata
|
|
3466
|
+
})));
|
|
3467
|
+
};
|
|
3200
3468
|
patchSession = async (c) => {
|
|
3201
3469
|
const sessionApi = this.options.ncpSessionService;
|
|
3202
3470
|
if (!sessionApi) {
|
|
@@ -3212,25 +3480,13 @@ var NcpSessionRoutesController = class {
|
|
|
3212
3480
|
return c.json(err("UNSUPPORTED_PATCH", "clearHistory is not supported for ncp sessions"), 400);
|
|
3213
3481
|
}
|
|
3214
3482
|
const existing = await sessionApi.getSession(sessionId);
|
|
3215
|
-
|
|
3216
|
-
return c.json(err("NOT_FOUND", `ncp session not found: ${sessionId}`), 404);
|
|
3217
|
-
}
|
|
3218
|
-
const metadata = existing.metadata && typeof existing.metadata === "object" && !Array.isArray(existing.metadata) ? existing.metadata : {};
|
|
3483
|
+
const metadata = readSessionMetadata(existing?.metadata);
|
|
3219
3484
|
let updated;
|
|
3220
3485
|
try {
|
|
3221
|
-
const nextMetadata =
|
|
3222
|
-
metadata
|
|
3223
|
-
patch
|
|
3224
|
-
createInvalidThinkingError: () => new Error("PREFERRED_THINKING_INVALID")
|
|
3486
|
+
const nextMetadata = await buildPatchedSessionMetadata({
|
|
3487
|
+
metadata,
|
|
3488
|
+
patch
|
|
3225
3489
|
});
|
|
3226
|
-
if (Object.prototype.hasOwnProperty.call(patch, "sessionType")) {
|
|
3227
|
-
const sessionType = typeof patch.sessionType === "string" ? patch.sessionType.trim() : "";
|
|
3228
|
-
if (sessionType) {
|
|
3229
|
-
nextMetadata.session_type = sessionType;
|
|
3230
|
-
} else {
|
|
3231
|
-
delete nextMetadata.session_type;
|
|
3232
|
-
}
|
|
3233
|
-
}
|
|
3234
3490
|
updated = await sessionApi.updateSession(sessionId, {
|
|
3235
3491
|
metadata: nextMetadata
|
|
3236
3492
|
});
|
|
@@ -3238,6 +3494,9 @@ var NcpSessionRoutesController = class {
|
|
|
3238
3494
|
if (error instanceof Error && error.message === "PREFERRED_THINKING_INVALID") {
|
|
3239
3495
|
return c.json(err("PREFERRED_THINKING_INVALID", "preferredThinking must be a supported thinking level"), 400);
|
|
3240
3496
|
}
|
|
3497
|
+
if (isSessionProjectRootValidationError(error)) {
|
|
3498
|
+
return c.json(err(error.code, error.message), 400);
|
|
3499
|
+
}
|
|
3241
3500
|
throw error;
|
|
3242
3501
|
}
|
|
3243
3502
|
if (!updated) {
|
|
@@ -3260,93 +3519,12 @@ var NcpSessionRoutesController = class {
|
|
|
3260
3519
|
};
|
|
3261
3520
|
};
|
|
3262
3521
|
|
|
3263
|
-
// src/ui/router/marketplace/constants.ts
|
|
3264
|
-
var DEFAULT_MARKETPLACE_API_BASE = "https://marketplace-api.nextclaw.io";
|
|
3265
|
-
var NEXTCLAW_PLUGIN_NPM_PREFIX = "@nextclaw/channel-plugin-";
|
|
3266
|
-
var BUILTIN_CHANNEL_PLUGIN_ID_PREFIX = "builtin-channel-";
|
|
3267
|
-
var MARKETPLACE_REMOTE_PAGE_SIZE = 100;
|
|
3268
|
-
var MARKETPLACE_REMOTE_MAX_PAGES = 20;
|
|
3269
|
-
var MARKETPLACE_ZH_COPY_BY_SLUG = {
|
|
3270
|
-
weather: {
|
|
3271
|
-
summary: "NextClaw \u5185\u7F6E\u6280\u80FD\uFF0C\u7528\u4E8E\u5929\u6C14\u67E5\u8BE2\u5DE5\u4F5C\u6D41\u3002",
|
|
3272
|
-
description: "\u5728 NextClaw \u4E2D\u63D0\u4F9B\u5FEB\u901F\u5929\u6C14\u67E5\u8BE2\u5DE5\u4F5C\u6D41\u3002"
|
|
3273
|
-
},
|
|
3274
|
-
summarize: {
|
|
3275
|
-
summary: "NextClaw \u5185\u7F6E\u6280\u80FD\uFF0C\u7528\u4E8E\u7ED3\u6784\u5316\u6458\u8981\u3002",
|
|
3276
|
-
description: "\u5728 NextClaw \u4E2D\u63D0\u4F9B\u6587\u4EF6\u4E0E\u957F\u6587\u672C\u7684\u6458\u8981\u5DE5\u4F5C\u6D41\u3002"
|
|
3277
|
-
},
|
|
3278
|
-
github: {
|
|
3279
|
-
summary: "NextClaw \u5185\u7F6E\u6280\u80FD\uFF0C\u7528\u4E8E GitHub \u5DE5\u4F5C\u6D41\u3002",
|
|
3280
|
-
description: "\u5728 NextClaw \u4E2D\u63D0\u4F9B Issue\u3001PR \u4E0E\u4ED3\u5E93\u76F8\u5173\u5DE5\u4F5C\u6D41\u6307\u5F15\u3002"
|
|
3281
|
-
},
|
|
3282
|
-
tmux: {
|
|
3283
|
-
summary: "NextClaw \u5185\u7F6E\u6280\u80FD\uFF0C\u7528\u4E8E\u7EC8\u7AEF/Tmux \u534F\u4F5C\u5DE5\u4F5C\u6D41\u3002",
|
|
3284
|
-
description: "\u5728 NextClaw \u4E2D\u63D0\u4F9B\u57FA\u4E8E Tmux \u7684\u4EFB\u52A1\u6267\u884C\u5DE5\u4F5C\u6D41\u6307\u5F15\u3002"
|
|
3285
|
-
},
|
|
3286
|
-
gog: {
|
|
3287
|
-
summary: "NextClaw \u5185\u7F6E\u6280\u80FD\uFF0C\u7528\u4E8E\u56FE\u8C31\u5BFC\u5411\u751F\u6210\u5DE5\u4F5C\u6D41\u3002",
|
|
3288
|
-
description: "\u5728 NextClaw \u4E2D\u63D0\u4F9B\u56FE\u8C31\u4E0E\u89C4\u5212\u5BFC\u5411\u5DE5\u4F5C\u6D41\u6307\u5F15\u3002"
|
|
3289
|
-
},
|
|
3290
|
-
pdf: {
|
|
3291
|
-
summary: "Anthropic \u6280\u80FD\uFF0C\u7528\u4E8E PDF \u8BFB\u53D6/\u5408\u5E76/\u62C6\u5206/OCR \u5DE5\u4F5C\u6D41\u3002",
|
|
3292
|
-
description: "\u4F7F\u7528\u8BE5\u6280\u80FD\u53EF\u8BFB\u53D6\u3001\u63D0\u53D6\u3001\u5408\u5E76\u3001\u62C6\u5206\u3001\u65CB\u8F6C\u5E76\u5BF9 PDF \u6267\u884C OCR \u5904\u7406\u3002"
|
|
3293
|
-
},
|
|
3294
|
-
docx: {
|
|
3295
|
-
summary: "Anthropic \u6280\u80FD\uFF0C\u7528\u4E8E\u521B\u5EFA\u548C\u7F16\u8F91 Word \u6587\u6863\u3002",
|
|
3296
|
-
description: "\u4F7F\u7528\u8BE5\u6280\u80FD\u53EF\u521B\u5EFA\u3001\u8BFB\u53D6\u3001\u7F16\u8F91\u5E76\u91CD\u6784 .docx \u6587\u6863\u3002"
|
|
3297
|
-
},
|
|
3298
|
-
pptx: {
|
|
3299
|
-
summary: "Anthropic \u6280\u80FD\uFF0C\u7528\u4E8E\u6F14\u793A\u6587\u7A3F\u64CD\u4F5C\u3002",
|
|
3300
|
-
description: "\u4F7F\u7528\u8BE5\u6280\u80FD\u53EF\u521B\u5EFA\u3001\u89E3\u6790\u3001\u7F16\u8F91\u5E76\u91CD\u7EC4 .pptx \u6F14\u793A\u6587\u7A3F\u3002"
|
|
3301
|
-
},
|
|
3302
|
-
xlsx: {
|
|
3303
|
-
summary: "Anthropic \u6280\u80FD\uFF0C\u7528\u4E8E\u8868\u683C\u6587\u6863\u5DE5\u4F5C\u6D41\u3002",
|
|
3304
|
-
description: "\u4F7F\u7528\u8BE5\u6280\u80FD\u53EF\u6253\u5F00\u3001\u7F16\u8F91\u3001\u6E05\u6D17\u5E76\u8F6C\u6362 .xlsx \u4E0E .csv \u7B49\u8868\u683C\u6587\u4EF6\u3002"
|
|
3305
|
-
},
|
|
3306
|
-
bird: {
|
|
3307
|
-
summary: "OpenClaw \u793E\u533A\u6280\u80FD\uFF0C\u7528\u4E8E X/Twitter \u8BFB\u53D6/\u641C\u7D22/\u53D1\u5E03\u5DE5\u4F5C\u6D41\u3002",
|
|
3308
|
-
description: "\u4F7F\u7528 bird CLI \u5728\u4EE3\u7406\u5DE5\u4F5C\u6D41\u4E2D\u8BFB\u53D6\u7EBF\u7A0B\u3001\u641C\u7D22\u5E16\u5B50\u5E76\u8D77\u8349\u63A8\u6587/\u56DE\u590D\u3002"
|
|
3309
|
-
},
|
|
3310
|
-
"cloudflare-deploy": {
|
|
3311
|
-
summary: "OpenAI \u7CBE\u9009\u6280\u80FD\uFF0C\u7528\u4E8E\u5728 Cloudflare \u4E0A\u90E8\u7F72\u5E94\u7528\u4E0E\u57FA\u7840\u8BBE\u65BD\u3002",
|
|
3312
|
-
description: "\u4F7F\u7528\u8BE5\u6280\u80FD\u53EF\u9009\u62E9 Cloudflare \u4EA7\u54C1\u5E76\u90E8\u7F72 Workers\u3001Pages \u53CA\u76F8\u5173\u670D\u52A1\u3002"
|
|
3313
|
-
},
|
|
3314
|
-
"channel-plugin-discord": {
|
|
3315
|
-
summary: "NextClaw \u5B98\u65B9\u63D2\u4EF6\uFF0C\u7528\u4E8E Discord \u6E20\u9053\u96C6\u6210\u3002",
|
|
3316
|
-
description: "\u901A\u8FC7 NextClaw \u63D2\u4EF6\u8FD0\u884C\u65F6\u63D0\u4F9B Discord \u6E20\u9053\u7684\u5165\u7AD9/\u51FA\u7AD9\u652F\u6301\u3002"
|
|
3317
|
-
},
|
|
3318
|
-
"channel-plugin-telegram": {
|
|
3319
|
-
summary: "NextClaw \u5B98\u65B9\u63D2\u4EF6\uFF0C\u7528\u4E8E Telegram \u6E20\u9053\u96C6\u6210\u3002",
|
|
3320
|
-
description: "\u901A\u8FC7 NextClaw \u63D2\u4EF6\u8FD0\u884C\u65F6\u63D0\u4F9B Telegram \u6E20\u9053\u7684\u5165\u7AD9/\u51FA\u7AD9\u652F\u6301\u3002"
|
|
3321
|
-
},
|
|
3322
|
-
"channel-plugin-slack": {
|
|
3323
|
-
summary: "NextClaw \u5B98\u65B9\u63D2\u4EF6\uFF0C\u7528\u4E8E Slack \u6E20\u9053\u96C6\u6210\u3002",
|
|
3324
|
-
description: "\u901A\u8FC7 NextClaw \u63D2\u4EF6\u8FD0\u884C\u65F6\u63D0\u4F9B Slack \u6E20\u9053\u7684\u5165\u7AD9/\u51FA\u7AD9\u652F\u6301\u3002"
|
|
3325
|
-
},
|
|
3326
|
-
"channel-plugin-wecom": {
|
|
3327
|
-
summary: "NextClaw \u5B98\u65B9\u63D2\u4EF6\uFF0C\u7528\u4E8E\u4F01\u4E1A\u5FAE\u4FE1\u6E20\u9053\u96C6\u6210\u3002",
|
|
3328
|
-
description: "\u901A\u8FC7 NextClaw \u63D2\u4EF6\u8FD0\u884C\u65F6\u63D0\u4F9B\u4F01\u4E1A\u5FAE\u4FE1\u6E20\u9053\u7684\u5165\u7AD9/\u51FA\u7AD9\u652F\u6301\u3002"
|
|
3329
|
-
},
|
|
3330
|
-
"channel-plugin-email": {
|
|
3331
|
-
summary: "NextClaw \u5B98\u65B9\u63D2\u4EF6\uFF0C\u7528\u4E8E Email \u6E20\u9053\u96C6\u6210\u3002",
|
|
3332
|
-
description: "\u901A\u8FC7 NextClaw \u63D2\u4EF6\u8FD0\u884C\u65F6\u63D0\u4F9B Email \u6E20\u9053\u7684\u5165\u7AD9/\u51FA\u7AD9\u652F\u6301\u3002"
|
|
3333
|
-
},
|
|
3334
|
-
"channel-plugin-whatsapp": {
|
|
3335
|
-
summary: "NextClaw \u5B98\u65B9\u63D2\u4EF6\uFF0C\u7528\u4E8E WhatsApp \u6E20\u9053\u96C6\u6210\u3002",
|
|
3336
|
-
description: "\u901A\u8FC7 NextClaw \u63D2\u4EF6\u8FD0\u884C\u65F6\u63D0\u4F9B WhatsApp \u6E20\u9053\u7684\u5165\u7AD9/\u51FA\u7AD9\u652F\u6301\u3002"
|
|
3337
|
-
},
|
|
3338
|
-
"channel-plugin-clawbay": {
|
|
3339
|
-
summary: "Clawbay \u5B98\u65B9\u6E20\u9053\u63D2\u4EF6\uFF0C\u7528\u4E8E NextClaw \u96C6\u6210\u3002",
|
|
3340
|
-
description: "\u901A\u8FC7\u63D2\u4EF6\u8FD0\u884C\u65F6\u4E3A NextClaw \u63D0\u4F9B Clawbay \u6E20\u9053\u80FD\u529B\u3002"
|
|
3341
|
-
}
|
|
3342
|
-
};
|
|
3343
|
-
|
|
3344
3522
|
// src/ui/router/marketplace/marketplace-network-retry.ts
|
|
3345
3523
|
var MARKETPLACE_NETWORK_RETRY_ATTEMPTS = 5;
|
|
3346
3524
|
var MARKETPLACE_NETWORK_RETRY_BASE_MS = 350;
|
|
3347
3525
|
function sleepMs(ms) {
|
|
3348
|
-
return new Promise((
|
|
3349
|
-
setTimeout(
|
|
3526
|
+
return new Promise((resolve4) => {
|
|
3527
|
+
setTimeout(resolve4, ms);
|
|
3350
3528
|
});
|
|
3351
3529
|
}
|
|
3352
3530
|
function isRetryableMarketplaceNetworkError(error) {
|
|
@@ -3810,7 +3988,7 @@ var McpMarketplaceController = class {
|
|
|
3810
3988
|
};
|
|
3811
3989
|
|
|
3812
3990
|
// src/ui/router/marketplace/installed.ts
|
|
3813
|
-
import * as
|
|
3991
|
+
import * as NextclawCore2 from "@nextclaw/core";
|
|
3814
3992
|
import { discoverPluginStatusReport } from "@nextclaw/openclaw-compat";
|
|
3815
3993
|
|
|
3816
3994
|
// src/ui/router/marketplace/spec.ts
|
|
@@ -3917,9 +4095,9 @@ function dedupeInstalledPluginRecordsByCanonicalSpec(records) {
|
|
|
3917
4095
|
}
|
|
3918
4096
|
|
|
3919
4097
|
// src/ui/router/marketplace/installed.ts
|
|
3920
|
-
var
|
|
4098
|
+
var getWorkspacePathFromConfig4 = NextclawCore2.getWorkspacePathFromConfig;
|
|
3921
4099
|
function createSkillsLoader(workspace) {
|
|
3922
|
-
const ctor =
|
|
4100
|
+
const ctor = NextclawCore2.SkillsLoader;
|
|
3923
4101
|
if (!ctor) {
|
|
3924
4102
|
return null;
|
|
3925
4103
|
}
|
|
@@ -4076,7 +4254,7 @@ function collectInstalledPluginRecords(options) {
|
|
|
4076
4254
|
try {
|
|
4077
4255
|
const pluginReport = discoverPluginStatusReport({
|
|
4078
4256
|
config,
|
|
4079
|
-
workspaceDir:
|
|
4257
|
+
workspaceDir: getWorkspacePathFromConfig4(config)
|
|
4080
4258
|
});
|
|
4081
4259
|
discoveredPlugins = pluginReport.plugins;
|
|
4082
4260
|
} catch {
|
|
@@ -4112,7 +4290,7 @@ function collectInstalledPluginRecords(options) {
|
|
|
4112
4290
|
}
|
|
4113
4291
|
function collectInstalledSkillRecords(options) {
|
|
4114
4292
|
const config = loadConfigOrDefault(options.configPath);
|
|
4115
|
-
const workspacePath =
|
|
4293
|
+
const workspacePath = getWorkspacePathFromConfig4(config);
|
|
4116
4294
|
const skillsLoader = createSkillsLoader(workspacePath);
|
|
4117
4295
|
const availableSkillSet = new Set((skillsLoader?.listSkills(true) ?? []).map((skill) => skill.name));
|
|
4118
4296
|
const listedSkills = skillsLoader?.listSkills(false) ?? [];
|
|
@@ -4181,7 +4359,7 @@ function resolvePluginManageTargetId(options, rawTargetId, rawSpec) {
|
|
|
4181
4359
|
}
|
|
4182
4360
|
function collectKnownSkillNames(options) {
|
|
4183
4361
|
const config = loadConfigOrDefault(options.configPath);
|
|
4184
|
-
const loader = createSkillsLoader(
|
|
4362
|
+
const loader = createSkillsLoader(getWorkspacePathFromConfig4(config));
|
|
4185
4363
|
return new Set((loader?.listSkills(false) ?? []).map((skill) => skill.name));
|
|
4186
4364
|
}
|
|
4187
4365
|
function isSupportedMarketplacePluginItem(item) {
|
|
@@ -4831,6 +5009,139 @@ var RemoteRoutesController = class {
|
|
|
4831
5009
|
};
|
|
4832
5010
|
};
|
|
4833
5011
|
|
|
5012
|
+
// src/ui/server-path/server-path-browse.utils.ts
|
|
5013
|
+
import { readdir, stat as stat2 } from "fs/promises";
|
|
5014
|
+
import { homedir as homedir2 } from "os";
|
|
5015
|
+
import { dirname, parse, resolve as resolve3 } from "path";
|
|
5016
|
+
import { expandHome as expandHome2 } from "@nextclaw/core";
|
|
5017
|
+
var ServerPathBrowseError = class extends Error {
|
|
5018
|
+
constructor(code, message) {
|
|
5019
|
+
super(message);
|
|
5020
|
+
this.code = code;
|
|
5021
|
+
this.name = "ServerPathBrowseError";
|
|
5022
|
+
}
|
|
5023
|
+
};
|
|
5024
|
+
function normalizeBrowsePath(path) {
|
|
5025
|
+
const trimmed = typeof path === "string" ? path.trim() : "";
|
|
5026
|
+
return resolve3(expandHome2(trimmed || homedir2()));
|
|
5027
|
+
}
|
|
5028
|
+
function readRootLabel(rootPath) {
|
|
5029
|
+
const normalized = rootPath.replace(/[\\/]+$/, "");
|
|
5030
|
+
return normalized || rootPath;
|
|
5031
|
+
}
|
|
5032
|
+
function buildBreadcrumbs(currentPath) {
|
|
5033
|
+
const parsedPath = parse(currentPath);
|
|
5034
|
+
const rootPath = parsedPath.root || currentPath;
|
|
5035
|
+
const rootBreadcrumb = {
|
|
5036
|
+
label: readRootLabel(rootPath),
|
|
5037
|
+
path: rootPath
|
|
5038
|
+
};
|
|
5039
|
+
const relativeSegments = currentPath.slice(rootPath.length).split(/[\\/]+/).filter(Boolean);
|
|
5040
|
+
const breadcrumbs = [rootBreadcrumb];
|
|
5041
|
+
let breadcrumbPath = rootPath;
|
|
5042
|
+
for (const segment of relativeSegments) {
|
|
5043
|
+
breadcrumbPath = resolve3(breadcrumbPath, segment);
|
|
5044
|
+
breadcrumbs.push({
|
|
5045
|
+
label: segment,
|
|
5046
|
+
path: breadcrumbPath
|
|
5047
|
+
});
|
|
5048
|
+
}
|
|
5049
|
+
return breadcrumbs;
|
|
5050
|
+
}
|
|
5051
|
+
async function resolveEntryView(params) {
|
|
5052
|
+
const entryPath = resolve3(params.parentPath, params.entryName);
|
|
5053
|
+
let entryStats;
|
|
5054
|
+
try {
|
|
5055
|
+
entryStats = await stat2(entryPath);
|
|
5056
|
+
} catch {
|
|
5057
|
+
return null;
|
|
5058
|
+
}
|
|
5059
|
+
const isDirectory = entryStats.isDirectory();
|
|
5060
|
+
if (!isDirectory && !params.includeFiles) {
|
|
5061
|
+
return null;
|
|
5062
|
+
}
|
|
5063
|
+
return {
|
|
5064
|
+
name: params.entryName,
|
|
5065
|
+
path: entryPath,
|
|
5066
|
+
kind: isDirectory ? "directory" : "file",
|
|
5067
|
+
hidden: params.entryName.startsWith(".")
|
|
5068
|
+
};
|
|
5069
|
+
}
|
|
5070
|
+
function sortEntryViews(left, right) {
|
|
5071
|
+
if (left.kind !== right.kind) {
|
|
5072
|
+
return left.kind === "directory" ? -1 : 1;
|
|
5073
|
+
}
|
|
5074
|
+
return left.name.localeCompare(right.name);
|
|
5075
|
+
}
|
|
5076
|
+
async function browseServerPath(options = {}) {
|
|
5077
|
+
const currentPath = normalizeBrowsePath(options.path);
|
|
5078
|
+
let currentPathStats;
|
|
5079
|
+
try {
|
|
5080
|
+
currentPathStats = await stat2(currentPath);
|
|
5081
|
+
} catch {
|
|
5082
|
+
throw new ServerPathBrowseError(
|
|
5083
|
+
"SERVER_PATH_NOT_FOUND",
|
|
5084
|
+
"server path does not exist"
|
|
5085
|
+
);
|
|
5086
|
+
}
|
|
5087
|
+
if (!currentPathStats.isDirectory()) {
|
|
5088
|
+
throw new ServerPathBrowseError(
|
|
5089
|
+
"SERVER_PATH_NOT_DIRECTORY",
|
|
5090
|
+
"server path must point to a directory"
|
|
5091
|
+
);
|
|
5092
|
+
}
|
|
5093
|
+
let entryNames;
|
|
5094
|
+
try {
|
|
5095
|
+
entryNames = await readdir(currentPath);
|
|
5096
|
+
} catch {
|
|
5097
|
+
throw new ServerPathBrowseError(
|
|
5098
|
+
"SERVER_PATH_NOT_READABLE",
|
|
5099
|
+
"server path is not readable"
|
|
5100
|
+
);
|
|
5101
|
+
}
|
|
5102
|
+
const entries = (await Promise.all(
|
|
5103
|
+
entryNames.map(
|
|
5104
|
+
(entryName) => resolveEntryView({
|
|
5105
|
+
parentPath: currentPath,
|
|
5106
|
+
entryName,
|
|
5107
|
+
includeFiles: options.includeFiles ?? false
|
|
5108
|
+
})
|
|
5109
|
+
)
|
|
5110
|
+
)).filter((entry) => entry !== null).sort(sortEntryViews);
|
|
5111
|
+
const parentPath = dirname(currentPath);
|
|
5112
|
+
return {
|
|
5113
|
+
currentPath,
|
|
5114
|
+
parentPath: parentPath === currentPath ? null : parentPath,
|
|
5115
|
+
homePath: resolve3(homedir2()),
|
|
5116
|
+
breadcrumbs: buildBreadcrumbs(currentPath),
|
|
5117
|
+
entries
|
|
5118
|
+
};
|
|
5119
|
+
}
|
|
5120
|
+
function isServerPathBrowseError(error) {
|
|
5121
|
+
return error instanceof ServerPathBrowseError;
|
|
5122
|
+
}
|
|
5123
|
+
|
|
5124
|
+
// src/ui/router/server-path.controller.ts
|
|
5125
|
+
function readIncludeFilesFlag(value) {
|
|
5126
|
+
return value === "1" || value === "true";
|
|
5127
|
+
}
|
|
5128
|
+
var ServerPathRoutesController = class {
|
|
5129
|
+
browse = async (c) => {
|
|
5130
|
+
try {
|
|
5131
|
+
const payload = await browseServerPath({
|
|
5132
|
+
path: c.req.query("path"),
|
|
5133
|
+
includeFiles: readIncludeFilesFlag(c.req.query("includeFiles"))
|
|
5134
|
+
});
|
|
5135
|
+
return c.json(ok(payload));
|
|
5136
|
+
} catch (error) {
|
|
5137
|
+
if (isServerPathBrowseError(error)) {
|
|
5138
|
+
return c.json(err(error.code, error.message), 400);
|
|
5139
|
+
}
|
|
5140
|
+
throw error;
|
|
5141
|
+
}
|
|
5142
|
+
};
|
|
5143
|
+
};
|
|
5144
|
+
|
|
4834
5145
|
// src/ui/router.ts
|
|
4835
5146
|
function registerAuthRoutes(app, authController) {
|
|
4836
5147
|
app.get("/api/auth/status", authController.getStatus);
|
|
@@ -4867,8 +5178,12 @@ function registerNcpSessionRoutes(app, ncpSessionController) {
|
|
|
4867
5178
|
app.get("/api/ncp/sessions/:sessionId", ncpSessionController.getSession);
|
|
4868
5179
|
app.put("/api/ncp/sessions/:sessionId", ncpSessionController.patchSession);
|
|
4869
5180
|
app.get("/api/ncp/sessions/:sessionId/messages", ncpSessionController.listSessionMessages);
|
|
5181
|
+
app.get("/api/ncp/sessions/:sessionId/skills", ncpSessionController.getSessionSkills);
|
|
4870
5182
|
app.delete("/api/ncp/sessions/:sessionId", ncpSessionController.deleteSession);
|
|
4871
5183
|
}
|
|
5184
|
+
function registerServerPathRoutes(app, serverPathController) {
|
|
5185
|
+
app.get("/api/server-paths/browse", serverPathController.browse);
|
|
5186
|
+
}
|
|
4872
5187
|
function registerNcpRuntimeRoutes(app, options, ncpAssetController) {
|
|
4873
5188
|
if (!options.ncpAgent) {
|
|
4874
5189
|
return;
|
|
@@ -4910,6 +5225,7 @@ function createUiRouter(options) {
|
|
|
4910
5225
|
const cronController = new CronRoutesController(options);
|
|
4911
5226
|
const ncpSessionController = new NcpSessionRoutesController(options);
|
|
4912
5227
|
const ncpAssetController = new NcpAssetRoutesController(options);
|
|
5228
|
+
const serverPathController = new ServerPathRoutesController();
|
|
4913
5229
|
const remoteController = options.remoteAccess ? new RemoteRoutesController(options.remoteAccess) : null;
|
|
4914
5230
|
const pluginMarketplaceController = new PluginMarketplaceController(options, marketplaceBaseUrl);
|
|
4915
5231
|
const skillMarketplaceController = new SkillMarketplaceController(options, marketplaceBaseUrl);
|
|
@@ -4934,6 +5250,7 @@ function createUiRouter(options) {
|
|
|
4934
5250
|
registerAuthRoutes(app, authController);
|
|
4935
5251
|
registerConfigRoutes(app, configController);
|
|
4936
5252
|
registerNcpSessionRoutes(app, ncpSessionController);
|
|
5253
|
+
registerServerPathRoutes(app, serverPathController);
|
|
4937
5254
|
registerNcpRuntimeRoutes(app, options, ncpAssetController);
|
|
4938
5255
|
registerCronRoutes(app, cronController);
|
|
4939
5256
|
registerRemoteRoutes(app, remoteController);
|
|
@@ -5069,7 +5386,7 @@ function startUiServer(options) {
|
|
|
5069
5386
|
},
|
|
5070
5387
|
isDir: async (path) => {
|
|
5071
5388
|
try {
|
|
5072
|
-
return (await
|
|
5389
|
+
return (await stat3(path)).isDirectory();
|
|
5073
5390
|
} catch {
|
|
5074
5391
|
return false;
|
|
5075
5392
|
}
|
|
@@ -5115,10 +5432,10 @@ function startUiServer(options) {
|
|
|
5115
5432
|
host: options.host,
|
|
5116
5433
|
port: options.port,
|
|
5117
5434
|
publish,
|
|
5118
|
-
close: () => new Promise((
|
|
5435
|
+
close: () => new Promise((resolve4) => {
|
|
5119
5436
|
wss.close(() => {
|
|
5120
5437
|
server.close(() => {
|
|
5121
|
-
Promise.resolve(options.ncpAgent?.agentClientEndpoint.stop()).catch(() => void 0).finally(() =>
|
|
5438
|
+
Promise.resolve(options.ncpAgent?.agentClientEndpoint.stop()).catch(() => void 0).finally(() => resolve4());
|
|
5122
5439
|
});
|
|
5123
5440
|
});
|
|
5124
5441
|
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextclaw/server",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.23",
|
|
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
|
|
22
|
-
"@nextclaw/
|
|
23
|
-
"@nextclaw/
|
|
24
|
-
"@nextclaw/
|
|
25
|
-
"@nextclaw/
|
|
26
|
-
"@nextclaw/runtime": "0.2.
|
|
21
|
+
"@nextclaw/ncp": "0.4.6",
|
|
22
|
+
"@nextclaw/core": "0.11.16",
|
|
23
|
+
"@nextclaw/openclaw-compat": "0.3.57",
|
|
24
|
+
"@nextclaw/ncp-http-agent-server": "0.3.10",
|
|
25
|
+
"@nextclaw/mcp": "0.1.63",
|
|
26
|
+
"@nextclaw/runtime": "0.2.30"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/node": "^20.17.6",
|