@spaceflow/core 0.15.0 → 0.17.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.js +172 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/cli-runtime/extension-loader.ts +20 -0
- package/src/commands/mcp/mcp.service.ts +148 -6
- package/src/extension-system/types.ts +25 -0
- package/src/locales/en/mcp.json +1 -0
- package/src/locales/zh-cn/mcp.json +1 -0
- package/src/shared/git-provider/adapters/gitea.adapter.spec.ts +2 -2
- package/src/shared/git-provider/adapters/gitea.adapter.ts +14 -1
package/dist/index.js
CHANGED
|
@@ -1046,7 +1046,17 @@ function parseDiffText(diffText) {
|
|
|
1046
1046
|
return this.request("POST", `/repos/${owner}/${repo}/pulls/${index}/reviews`, options);
|
|
1047
1047
|
}
|
|
1048
1048
|
async listPullReviews(owner, repo, index) {
|
|
1049
|
-
|
|
1049
|
+
const allReviews = [];
|
|
1050
|
+
let page = 1;
|
|
1051
|
+
const limit = 50;
|
|
1052
|
+
while(true){
|
|
1053
|
+
const reviews = await this.request("GET", `/repos/${owner}/${repo}/pulls/${index}/reviews?page=${page}&limit=${limit}`);
|
|
1054
|
+
if (!reviews || reviews.length === 0) break;
|
|
1055
|
+
allReviews.push(...reviews);
|
|
1056
|
+
if (reviews.length < limit) break;
|
|
1057
|
+
page++;
|
|
1058
|
+
}
|
|
1059
|
+
return allReviews;
|
|
1050
1060
|
}
|
|
1051
1061
|
async updatePullReview(owner, repo, index, reviewId, body) {
|
|
1052
1062
|
// Gitea 不支持更新 review,使用删除+创建的方式模拟
|
|
@@ -5462,9 +5472,9 @@ var list_namespaceObject = JSON.parse('{"description":"列出已安装的技能
|
|
|
5462
5472
|
;// CONCATENATED MODULE: ./src/locales/en/list.json
|
|
5463
5473
|
var en_list_namespaceObject = JSON.parse('{"description":"List installed skill packages","extensionDescription":"List installed plugins/skills","noSkills":"📦 No skill packages installed","installHint":"Install skill packages with:","installedExtensions":"📦 Installed extensions ({{installed}}/{{total}}):","commands":"Commands: {{commands}}"}')
|
|
5464
5474
|
;// CONCATENATED MODULE: ./src/locales/zh-cn/mcp.json
|
|
5465
|
-
var zh_cn_mcp_namespaceObject = JSON.parse('{"description":"启动 MCP Server,提供所有已安装扩展的 MCP 工具","options.inspector":"启动 MCP Inspector 进行交互式调试","inspectorStarting":"🔍 启动 MCP Inspector...","inspectorDebugCmd":" 调试命令: pnpm space mcp","inspectorFailed":"❌ 启动 MCP Inspector 失败: {{error}}","extensionDescription":"启动 MCP Server,提供所有已安装扩展的 MCP 工具","cwdInfo":"📂 工作目录: {{cwd}}","cwdEnvHint":" 💡 可通过环境变量 SPACEFLOW_CWD 指定工作区路径","scanning":"🔍 扫描已安装的扩展...","foundExtensions":" 发现 {{count}} 个扩展","checkingExport":" 检查 {{key}}: __mcp_server__={{hasMcpServer}}","containerSuccess":" ✅ 从容器获取 {{key}} 实例成功","containerFailed":" ⚠️ 从容器获取 {{key}} 失败: {{error}}","loadToolsFailed":" ⚠️ {{name}}: 加载 MCP 工具失败","noToolsFound":"❌ 没有找到任何 MCP 工具","noToolsHint":" 提示: 确保已安装支持 MCP 的扩展,并导出 mcpService 或 getMcpTools\\n 如果工作目录不正确,请在 MCP 配置中设置环境变量:\\n \\"env\\": { \\"SPACEFLOW_CWD\\": \\"/path/to/your/project\\" }","toolsFound":"✅ 共发现 {{count}} 个 MCP 工具","ttyHint":"💡 MCP Server 需要由 MCP 客户端(如 Cursor、Claude Desktop)通过管道启动。\\n 请将以下配置添加到你的 MCP 客户端中:\\n\\n \\"spaceflow\\": {\\n \\"command\\": \\"npx\\",\\n \\"args\\": [\\"@spaceflow/cli\\", \\"mcp\\"],\\n \\"env\\": { \\"SPACEFLOW_CWD\\": \\"/path/to/your/project\\" }\\n }","serverStarted":"🚀 MCP Server 已启动,共 {{count}} 个工具"}')
|
|
5475
|
+
var zh_cn_mcp_namespaceObject = JSON.parse('{"description":"启动 MCP Server,提供所有已安装扩展的 MCP 工具","options.inspector":"启动 MCP Inspector 进行交互式调试","inspectorStarting":"🔍 启动 MCP Inspector...","inspectorDebugCmd":" 调试命令: pnpm space mcp","inspectorFailed":"❌ 启动 MCP Inspector 失败: {{error}}","extensionDescription":"启动 MCP Server,提供所有已安装扩展的 MCP 工具","cwdInfo":"📂 工作目录: {{cwd}}","cwdEnvHint":" 💡 可通过环境变量 SPACEFLOW_CWD 指定工作区路径","scanning":"🔍 扫描已安装的扩展...","foundExtensions":" 发现 {{count}} 个扩展","checkingExport":" 检查 {{key}}: __mcp_server__={{hasMcpServer}}","containerSuccess":" ✅ 从容器获取 {{key}} 实例成功","containerFailed":" ⚠️ 从容器获取 {{key}} 失败: {{error}}","loadToolsFailed":" ⚠️ {{name}}: 加载 MCP 工具失败","noToolsFound":"❌ 没有找到任何 MCP 工具","noToolsHint":" 提示: 确保已安装支持 MCP 的扩展,并导出 mcpService 或 getMcpTools\\n 如果工作目录不正确,请在 MCP 配置中设置环境变量:\\n \\"env\\": { \\"SPACEFLOW_CWD\\": \\"/path/to/your/project\\" }","toolsFound":"✅ 共发现 {{count}} 个 MCP 工具","resourcesFound":"📦 共发现 {{count}} 个 MCP 资源","ttyHint":"💡 MCP Server 需要由 MCP 客户端(如 Cursor、Claude Desktop)通过管道启动。\\n 请将以下配置添加到你的 MCP 客户端中:\\n\\n \\"spaceflow\\": {\\n \\"command\\": \\"npx\\",\\n \\"args\\": [\\"@spaceflow/cli\\", \\"mcp\\"],\\n \\"env\\": { \\"SPACEFLOW_CWD\\": \\"/path/to/your/project\\" }\\n }","serverStarted":"🚀 MCP Server 已启动,共 {{count}} 个工具"}')
|
|
5466
5476
|
;// CONCATENATED MODULE: ./src/locales/en/mcp.json
|
|
5467
|
-
var en_mcp_namespaceObject = JSON.parse('{"description":"Start MCP Server with all installed extension tools","options.inspector":"Start MCP Inspector for interactive debugging","inspectorStarting":"🔍 Starting MCP Inspector...","inspectorDebugCmd":" Debug command: pnpm space mcp","inspectorFailed":"❌ Failed to start MCP Inspector: {{error}}","extensionDescription":"Start MCP Server with all installed extension tools","cwdInfo":"📂 Working directory: {{cwd}}","cwdEnvHint":" 💡 Set SPACEFLOW_CWD environment variable to specify workspace path","scanning":"🔍 Scanning installed extensions...","foundExtensions":" Found {{count}} extensions","checkingExport":" Checking {{key}}: __mcp_server__={{hasMcpServer}}","containerSuccess":" ✅ Got {{key}} instance from container","containerFailed":" ⚠️ Failed to get {{key}} from container: {{error}}","loadToolsFailed":" ⚠️ {{name}}: Failed to load MCP tools","noToolsFound":"❌ No MCP tools found","noToolsHint":" Hint: Make sure you have installed MCP-enabled extensions that export mcpService or getMcpTools\\n If the working directory is incorrect, set the environment variable in your MCP config:\\n \\"env\\": { \\"SPACEFLOW_CWD\\": \\"/path/to/your/project\\" }","toolsFound":"✅ Found {{count}} MCP tools","ttyHint":"💡 MCP Server must be started by an MCP client (e.g. Cursor, Claude Desktop) via pipe.\\n Add the following config to your MCP client:\\n\\n \\"spaceflow\\": {\\n \\"command\\": \\"npx\\",\\n \\"args\\": [\\"@spaceflow/cli\\", \\"mcp\\"],\\n \\"env\\": { \\"SPACEFLOW_CWD\\": \\"/path/to/your/project\\" }\\n }","serverStarted":"🚀 MCP Server started with {{count}} tools"}')
|
|
5477
|
+
var en_mcp_namespaceObject = JSON.parse('{"description":"Start MCP Server with all installed extension tools","options.inspector":"Start MCP Inspector for interactive debugging","inspectorStarting":"🔍 Starting MCP Inspector...","inspectorDebugCmd":" Debug command: pnpm space mcp","inspectorFailed":"❌ Failed to start MCP Inspector: {{error}}","extensionDescription":"Start MCP Server with all installed extension tools","cwdInfo":"📂 Working directory: {{cwd}}","cwdEnvHint":" 💡 Set SPACEFLOW_CWD environment variable to specify workspace path","scanning":"🔍 Scanning installed extensions...","foundExtensions":" Found {{count}} extensions","checkingExport":" Checking {{key}}: __mcp_server__={{hasMcpServer}}","containerSuccess":" ✅ Got {{key}} instance from container","containerFailed":" ⚠️ Failed to get {{key}} from container: {{error}}","loadToolsFailed":" ⚠️ {{name}}: Failed to load MCP tools","noToolsFound":"❌ No MCP tools found","noToolsHint":" Hint: Make sure you have installed MCP-enabled extensions that export mcpService or getMcpTools\\n If the working directory is incorrect, set the environment variable in your MCP config:\\n \\"env\\": { \\"SPACEFLOW_CWD\\": \\"/path/to/your/project\\" }","toolsFound":"✅ Found {{count}} MCP tools","resourcesFound":"📦 Found {{count}} MCP resources","ttyHint":"💡 MCP Server must be started by an MCP client (e.g. Cursor, Claude Desktop) via pipe.\\n Add the following config to your MCP client:\\n\\n \\"spaceflow\\": {\\n \\"command\\": \\"npx\\",\\n \\"args\\": [\\"@spaceflow/cli\\", \\"mcp\\"],\\n \\"env\\": { \\"SPACEFLOW_CWD\\": \\"/path/to/your/project\\" }\\n }","serverStarted":"🚀 MCP Server started with {{count}} tools"}')
|
|
5468
5478
|
;// CONCATENATED MODULE: ./src/locales/zh-cn/runx.json
|
|
5469
5479
|
var runx_namespaceObject = JSON.parse('{"description":"全局安装依赖并运行命令","options.name":"指定命令名称(默认从 source 自动提取)","noSource":"❌ 请指定要运行的依赖源","usage":" 用法: spaceflow x <source> [args...]","runFailed":"❌ 运行失败: {{error}}","extensionDescription":"执行插件提供的脚本命令","runningCommand":"▶️ 运行命令: {{command}}","npxExitCode":"npx {{package}} 退出码: {{code}}","commandNotInstalled":"命令 {{name}} 未安装","commandNotBuilt":"命令 {{name}} 未构建,缺少 dist/index.js","pluginNoExport":"插件 {{name}} 没有默认导出"}')
|
|
5470
5480
|
;// CONCATENATED MODULE: ./src/locales/en/runx.json
|
|
@@ -6454,6 +6464,21 @@ registerPluginSchema({
|
|
|
6454
6464
|
}
|
|
6455
6465
|
return result;
|
|
6456
6466
|
}
|
|
6467
|
+
/**
|
|
6468
|
+
* 获取所有 MCP 资源
|
|
6469
|
+
* 返回扩展中定义的 resources 字段
|
|
6470
|
+
*/ getResources() {
|
|
6471
|
+
const result = [];
|
|
6472
|
+
for (const ext of this.extensions.values()){
|
|
6473
|
+
if (ext.resources && ext.resources.length > 0) {
|
|
6474
|
+
result.push({
|
|
6475
|
+
extensionName: ext.name,
|
|
6476
|
+
resources: ext.resources
|
|
6477
|
+
});
|
|
6478
|
+
}
|
|
6479
|
+
}
|
|
6480
|
+
return result;
|
|
6481
|
+
}
|
|
6457
6482
|
}
|
|
6458
6483
|
|
|
6459
6484
|
;// CONCATENATED MODULE: external "@rspack/core"
|
|
@@ -9894,6 +9919,7 @@ class ListService {
|
|
|
9894
9919
|
|
|
9895
9920
|
|
|
9896
9921
|
|
|
9922
|
+
|
|
9897
9923
|
class McpService {
|
|
9898
9924
|
extensionLoader;
|
|
9899
9925
|
constructor(extensionLoader){
|
|
@@ -9943,17 +9969,29 @@ class McpService {
|
|
|
9943
9969
|
});
|
|
9944
9970
|
}
|
|
9945
9971
|
}
|
|
9946
|
-
|
|
9972
|
+
// 收集扩展 resources + 内置 resources
|
|
9973
|
+
const allResources = this.collectResources(verbose);
|
|
9974
|
+
if (allTools.length === 0 && allResources.length === 0) {
|
|
9947
9975
|
console.error(i18n_t("mcp:noToolsFound"));
|
|
9948
9976
|
console.error(i18n_t("mcp:noToolsHint"));
|
|
9949
9977
|
process.exit(1);
|
|
9950
9978
|
}
|
|
9951
9979
|
if (shouldLog(verbose, 1)) {
|
|
9952
|
-
|
|
9953
|
-
|
|
9954
|
-
|
|
9955
|
-
|
|
9956
|
-
|
|
9980
|
+
if (allTools.length > 0) {
|
|
9981
|
+
console.error(i18n_t("mcp:toolsFound", {
|
|
9982
|
+
count: allTools.length
|
|
9983
|
+
}));
|
|
9984
|
+
for (const { tool } of allTools){
|
|
9985
|
+
console.error(` - ${tool.name}`);
|
|
9986
|
+
}
|
|
9987
|
+
}
|
|
9988
|
+
if (allResources.length > 0) {
|
|
9989
|
+
console.error(i18n_t("mcp:resourcesFound", {
|
|
9990
|
+
count: allResources.length
|
|
9991
|
+
}));
|
|
9992
|
+
for (const { resource } of allResources){
|
|
9993
|
+
console.error(` - ${resource.name} (${resource.uri})`);
|
|
9994
|
+
}
|
|
9957
9995
|
}
|
|
9958
9996
|
}
|
|
9959
9997
|
// 如果 stdin 是 TTY(用户手动在终端运行),只打印信息不阻塞
|
|
@@ -9963,11 +10001,102 @@ class McpService {
|
|
|
9963
10001
|
return;
|
|
9964
10002
|
}
|
|
9965
10003
|
// 被 MCP 客户端通过管道调用,正常启动 stdio server
|
|
9966
|
-
await this.runServer(allTools, verbose);
|
|
10004
|
+
await this.runServer(allTools, allResources, verbose);
|
|
10005
|
+
}
|
|
10006
|
+
/**
|
|
10007
|
+
* 收集所有 MCP 资源(扩展 + 内置)
|
|
10008
|
+
*/ collectResources(verbose) {
|
|
10009
|
+
const ctx = this.extensionLoader.getContext();
|
|
10010
|
+
const allResources = [];
|
|
10011
|
+
// 1. 收集扩展声明的 resources
|
|
10012
|
+
const extensionResources = this.extensionLoader.getResources();
|
|
10013
|
+
for (const { extensionName, resources } of extensionResources){
|
|
10014
|
+
if (shouldLog(verbose, 2)) {
|
|
10015
|
+
console.error(` 扩展 ${extensionName} 提供 ${resources.length} 个 MCP 资源`);
|
|
10016
|
+
}
|
|
10017
|
+
for (const resource of resources){
|
|
10018
|
+
allResources.push({
|
|
10019
|
+
resource,
|
|
10020
|
+
ctx
|
|
10021
|
+
});
|
|
10022
|
+
}
|
|
10023
|
+
}
|
|
10024
|
+
// 2. 内置资源:项目配置(过滤敏感字段)
|
|
10025
|
+
allResources.push({
|
|
10026
|
+
resource: {
|
|
10027
|
+
name: "spaceflow-config",
|
|
10028
|
+
uri: "spaceflow://config",
|
|
10029
|
+
title: "Spaceflow Configuration",
|
|
10030
|
+
description: "当前项目的 Spaceflow 配置(已过滤敏感字段)",
|
|
10031
|
+
mimeType: "application/json",
|
|
10032
|
+
handler: async (_uri, ctx)=>{
|
|
10033
|
+
const config = readConfigSync(ctx.cwd);
|
|
10034
|
+
return JSON.stringify(this.sanitizeConfig(config), null, 2);
|
|
10035
|
+
}
|
|
10036
|
+
},
|
|
10037
|
+
ctx
|
|
10038
|
+
});
|
|
10039
|
+
// 3. 内置资源:扩展列表
|
|
10040
|
+
allResources.push({
|
|
10041
|
+
resource: {
|
|
10042
|
+
name: "spaceflow-extensions",
|
|
10043
|
+
uri: "spaceflow://extensions",
|
|
10044
|
+
title: "Installed Extensions",
|
|
10045
|
+
description: "当前项目已安装的 Spaceflow 扩展及其工具/资源",
|
|
10046
|
+
mimeType: "application/json",
|
|
10047
|
+
handler: async ()=>{
|
|
10048
|
+
const extensions = this.extensionLoader.getExtensions();
|
|
10049
|
+
const summary = extensions.map((ext)=>({
|
|
10050
|
+
name: ext.name,
|
|
10051
|
+
version: ext.version,
|
|
10052
|
+
description: ext.description,
|
|
10053
|
+
commands: ext.commands.map((c)=>c.name),
|
|
10054
|
+
tools: (ext.tools || []).map((t)=>({
|
|
10055
|
+
name: t.name,
|
|
10056
|
+
description: t.description
|
|
10057
|
+
})),
|
|
10058
|
+
resources: (ext.resources || []).map((r)=>({
|
|
10059
|
+
name: r.name,
|
|
10060
|
+
uri: r.uri,
|
|
10061
|
+
description: r.description
|
|
10062
|
+
}))
|
|
10063
|
+
}));
|
|
10064
|
+
return JSON.stringify(summary, null, 2);
|
|
10065
|
+
}
|
|
10066
|
+
},
|
|
10067
|
+
ctx
|
|
10068
|
+
});
|
|
10069
|
+
return allResources;
|
|
10070
|
+
}
|
|
10071
|
+
/**
|
|
10072
|
+
* 过滤配置中的敏感字段
|
|
10073
|
+
*/ sanitizeConfig(config) {
|
|
10074
|
+
const sensitiveKeys = [
|
|
10075
|
+
"token",
|
|
10076
|
+
"apiKey",
|
|
10077
|
+
"appSecret",
|
|
10078
|
+
"authToken",
|
|
10079
|
+
"apikey",
|
|
10080
|
+
"secret"
|
|
10081
|
+
];
|
|
10082
|
+
const sanitize = (obj)=>{
|
|
10083
|
+
if (obj === null || obj === undefined || typeof obj !== "object") return obj;
|
|
10084
|
+
if (Array.isArray(obj)) return obj.map(sanitize);
|
|
10085
|
+
const result = {};
|
|
10086
|
+
for (const [key, value] of Object.entries(obj)){
|
|
10087
|
+
if (sensitiveKeys.some((sk)=>key.toLowerCase().includes(sk.toLowerCase()))) {
|
|
10088
|
+
result[key] = value ? "***" : "";
|
|
10089
|
+
} else {
|
|
10090
|
+
result[key] = sanitize(value);
|
|
10091
|
+
}
|
|
10092
|
+
}
|
|
10093
|
+
return result;
|
|
10094
|
+
};
|
|
10095
|
+
return sanitize(config);
|
|
9967
10096
|
}
|
|
9968
10097
|
/**
|
|
9969
10098
|
* 运行 MCP Server
|
|
9970
|
-
*/ async runServer(allTools, verbose) {
|
|
10099
|
+
*/ async runServer(allTools, allResources, verbose) {
|
|
9971
10100
|
const server = new mcp_js_McpServer({
|
|
9972
10101
|
name: "spaceflow",
|
|
9973
10102
|
version: "1.0.0"
|
|
@@ -10003,6 +10132,37 @@ class McpService {
|
|
|
10003
10132
|
}
|
|
10004
10133
|
});
|
|
10005
10134
|
}
|
|
10135
|
+
// 注册所有资源(使用 v2 API: server.registerResource)
|
|
10136
|
+
for (const { resource, ctx } of allResources){
|
|
10137
|
+
server.registerResource(resource.name, resource.uri, {
|
|
10138
|
+
title: resource.title,
|
|
10139
|
+
description: resource.description,
|
|
10140
|
+
mimeType: resource.mimeType || "application/json"
|
|
10141
|
+
}, async (uri)=>{
|
|
10142
|
+
try {
|
|
10143
|
+
const text = await resource.handler(uri.href, ctx);
|
|
10144
|
+
return {
|
|
10145
|
+
contents: [
|
|
10146
|
+
{
|
|
10147
|
+
uri: uri.href,
|
|
10148
|
+
mimeType: resource.mimeType || "application/json",
|
|
10149
|
+
text
|
|
10150
|
+
}
|
|
10151
|
+
]
|
|
10152
|
+
};
|
|
10153
|
+
} catch (error) {
|
|
10154
|
+
return {
|
|
10155
|
+
contents: [
|
|
10156
|
+
{
|
|
10157
|
+
uri: uri.href,
|
|
10158
|
+
mimeType: "text/plain",
|
|
10159
|
+
text: `Error: ${error instanceof Error ? error.message : String(error)}`
|
|
10160
|
+
}
|
|
10161
|
+
]
|
|
10162
|
+
};
|
|
10163
|
+
}
|
|
10164
|
+
});
|
|
10165
|
+
}
|
|
10006
10166
|
// 启动 stdio 传输
|
|
10007
10167
|
const transport = new stdio_js_StdioServerTransport();
|
|
10008
10168
|
await server.connect(transport);
|
|
@@ -11264,7 +11424,7 @@ async function exec(extensions = [], options = {}) {
|
|
|
11264
11424
|
// 6. 创建 CLI 程序
|
|
11265
11425
|
const program = new Command();
|
|
11266
11426
|
const cliVersion = options.cliVersion || "0.0.0";
|
|
11267
|
-
const coreVersion = true ? "0.
|
|
11427
|
+
const coreVersion = true ? "0.17.0" : 0;
|
|
11268
11428
|
const versionOutput = `spaceflow/${cliVersion} core/${coreVersion}`;
|
|
11269
11429
|
program.name("spaceflow").description("Spaceflow CLI").version(versionOutput, "-V, --version", "显示版本信息");
|
|
11270
11430
|
// 定义全局 verbose 选项(支持计数:-v, -vv, -vvv)
|