@seastudio/sdk 3.0.2 → 3.0.4
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/README.md +14 -0
- package/bin/seastudio.js +0 -0
- package/dist/{chunk-TFOJLA2F.cjs → chunk-3I7UM66P.cjs} +9 -7
- package/dist/{chunk-SUF5BPSK.cjs → chunk-3IVOSJIO.cjs} +3 -3
- package/dist/chunk-AXT6ZLY2.js +98 -0
- package/dist/{chunk-XU5GEWWL.js → chunk-GPM5XGYM.js} +1 -1
- package/dist/chunk-PYYG6U4M.cjs +109 -0
- package/dist/{chunk-ANWOL7SM.js → chunk-TJ3CGHWJ.js} +9 -7
- package/dist/develop-tool/cli/index.cjs +79 -7
- package/dist/develop-tool/cli/index.js +79 -7
- package/dist/index.cjs +96 -246
- package/dist/index.d.cts +3 -8
- package/dist/index.d.ts +3 -8
- package/dist/index.js +3 -9
- package/dist/mcp/core/index.cjs +22 -22
- package/dist/mcp/core/index.d.cts +10 -7
- package/dist/mcp/core/index.d.ts +10 -7
- package/dist/mcp/core/index.js +1 -1
- package/dist/mcp/index.cjs +49 -199
- package/dist/mcp/index.d.cts +13 -84
- package/dist/mcp/index.d.ts +13 -84
- package/dist/mcp/index.js +3 -9
- package/dist/mcp/seastudio/index.cjs +19 -19
- package/dist/mcp/seastudio/index.d.cts +1 -1
- package/dist/mcp/seastudio/index.d.ts +1 -1
- package/dist/mcp/seastudio/index.js +2 -2
- package/dist/{types-B1Zqr-0Q.d.cts → types-CUFTi2bZ.d.cts} +10 -1
- package/dist/{types-B1Zqr-0Q.d.ts → types-CUFTi2bZ.d.ts} +10 -1
- package/package.json +2 -22
- package/src/develop-tool/templates/plugin/frontend/package.json.tmpl +2 -2
- package/src/develop-tool/templates/plugin/frontend/src/main.tsx +3 -0
- package/src/develop-tool/templates/plugin/frontend/src/mcp-entry.ts.tmpl +12 -0
- package/dist/chunk-4ITOR5QE.js +0 -901
- package/dist/chunk-CVF4QHS6.cjs +0 -436
- package/dist/chunk-DSOSHJH2.js +0 -643
- package/dist/chunk-FLATZQA2.js +0 -174
- package/dist/chunk-G66KY35N.js +0 -334
- package/dist/chunk-HJJTBVKQ.cjs +0 -909
- package/dist/chunk-ISI2OLPI.cjs +0 -179
- package/dist/chunk-MYURVLGP.cjs +0 -165
- package/dist/chunk-ORBVHAAS.cjs +0 -341
- package/dist/chunk-QD4KISXM.js +0 -160
- package/dist/chunk-S2UIBWKA.js +0 -99
- package/dist/chunk-SNGU4SHO.cjs +0 -654
- package/dist/chunk-XIPL7VSP.cjs +0 -110
- package/dist/chunk-Z7LV7DCO.js +0 -429
- package/dist/mcp/plugin-editor/index.cjs +0 -47
- package/dist/mcp/plugin-editor/index.d.cts +0 -98
- package/dist/mcp/plugin-editor/index.d.ts +0 -98
- package/dist/mcp/plugin-editor/index.js +0 -2
- package/dist/mcp/plugin-excel/index.cjs +0 -31
- package/dist/mcp/plugin-excel/index.d.cts +0 -86
- package/dist/mcp/plugin-excel/index.d.ts +0 -86
- package/dist/mcp/plugin-excel/index.js +0 -2
- package/dist/mcp/plugin-preview/index.cjs +0 -23
- package/dist/mcp/plugin-preview/index.d.cts +0 -109
- package/dist/mcp/plugin-preview/index.d.ts +0 -109
- package/dist/mcp/plugin-preview/index.js +0 -2
- package/dist/mcp/plugin-seaflow/index.cjs +0 -35
- package/dist/mcp/plugin-seaflow/index.d.cts +0 -318
- package/dist/mcp/plugin-seaflow/index.d.ts +0 -318
- package/dist/mcp/plugin-seaflow/index.js +0 -2
- package/dist/mcp/plugin-word/index.cjs +0 -31
- package/dist/mcp/plugin-word/index.d.cts +0 -86
- package/dist/mcp/plugin-word/index.d.ts +0 -86
- package/dist/mcp/plugin-word/index.js +0 -2
- package/dist/tools-LMW67LIY.js +0 -2
- package/dist/tools-TU7PBMDO.cjs +0 -23
package/README.md
CHANGED
|
@@ -68,6 +68,20 @@ await preview.get('/path/to/file');
|
|
|
68
68
|
|
|
69
69
|
说明:`@seastudio/sdk/mcp` 现在的官方稳定支持面聚焦在 raw MCP catalog、包索引和通用转换能力,不包含额外的上层适配逻辑。
|
|
70
70
|
|
|
71
|
+
### 指定插件实例调用 Tool
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
import { callHostTool } from '@seastudio/sdk';
|
|
75
|
+
|
|
76
|
+
await callHostTool(
|
|
77
|
+
'plugin-editor_open_file',
|
|
78
|
+
{ path: '/tmp/demo.ts' },
|
|
79
|
+
{ pluginInstanceId: 'plugin-123' }
|
|
80
|
+
);
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
`pluginInstanceId` 是 `tools/call` 的可选协议字段,用于在同一插件存在多个实例时精确路由到目标实例。宿主在已知上下文时也可以自动补齐这个字段,因此大多数常规调用不需要手动传入。
|
|
84
|
+
|
|
71
85
|
### 动态加载插件 MCP
|
|
72
86
|
|
|
73
87
|
```typescript
|
package/bin/seastudio.js
CHANGED
|
File without changes
|
|
@@ -294,10 +294,12 @@ var MCPClient = class {
|
|
|
294
294
|
return this.timeout;
|
|
295
295
|
}
|
|
296
296
|
async callTool(name, args = {}, options) {
|
|
297
|
-
|
|
297
|
+
const request = {
|
|
298
298
|
name,
|
|
299
|
-
arguments: args
|
|
300
|
-
|
|
299
|
+
arguments: args,
|
|
300
|
+
...typeof options?.pluginInstanceId === "string" && options.pluginInstanceId.trim() ? { pluginInstanceId: options.pluginInstanceId.trim() } : {}
|
|
301
|
+
};
|
|
302
|
+
return this.request("tools/call", request, {
|
|
301
303
|
timeout: this.resolveToolCallTimeout(name, args, options)
|
|
302
304
|
});
|
|
303
305
|
}
|
|
@@ -379,11 +381,11 @@ function getDefaultClient() {
|
|
|
379
381
|
function setDefaultClient(client) {
|
|
380
382
|
defaultClient = client;
|
|
381
383
|
}
|
|
382
|
-
async function callHostTool(toolName, args = {}) {
|
|
383
|
-
return getDefaultClient().callTool(toolName, args);
|
|
384
|
+
async function callHostTool(toolName, args = {}, options) {
|
|
385
|
+
return getDefaultClient().callTool(toolName, args, options);
|
|
384
386
|
}
|
|
385
|
-
async function callHostToolText(toolName, args = {}) {
|
|
386
|
-
return getDefaultClient().callToolText(toolName, args);
|
|
387
|
+
async function callHostToolText(toolName, args = {}, options) {
|
|
388
|
+
return getDefaultClient().callToolText(toolName, args, options);
|
|
387
389
|
}
|
|
388
390
|
|
|
389
391
|
// src/mcp/core/server.ts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunk3I7UM66P_cjs = require('./chunk-3I7UM66P.cjs');
|
|
4
4
|
|
|
5
5
|
// src/mcp/seastudio/tools-plugin.ts
|
|
6
6
|
var pluginManagementTools = [
|
|
@@ -1127,10 +1127,10 @@ var allTools = [
|
|
|
1127
1127
|
];
|
|
1128
1128
|
var tools = allTools;
|
|
1129
1129
|
async function callTool(name, args = {}) {
|
|
1130
|
-
return
|
|
1130
|
+
return chunk3I7UM66P_cjs.getDefaultClient().callTool(name, args);
|
|
1131
1131
|
}
|
|
1132
1132
|
async function request(method, params) {
|
|
1133
|
-
return
|
|
1133
|
+
return chunk3I7UM66P_cjs.getDefaultClient().request(method, params);
|
|
1134
1134
|
}
|
|
1135
1135
|
function usesAbsolutePathMode(mode) {
|
|
1136
1136
|
return mode === "absolute";
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { allTools } from './chunk-GPM5XGYM.js';
|
|
2
|
+
import { normalizeMCPTool, normalizeMCPToolObjectSchema, getDefaultClient } from './chunk-TJ3CGHWJ.js';
|
|
3
|
+
|
|
4
|
+
// src/mcp/index.ts
|
|
5
|
+
async function loadPlugin(pluginName) {
|
|
6
|
+
if (pluginName === "seastudio") {
|
|
7
|
+
return import('./mcp/seastudio/index.js');
|
|
8
|
+
}
|
|
9
|
+
throw new Error(`Unknown plugin: ${pluginName}. \u63D2\u4EF6 MCP \u4E0D\u518D\u901A\u8FC7 SDK \u9759\u6001\u5BFC\u5165\u3002`);
|
|
10
|
+
}
|
|
11
|
+
var MCP_PACKAGES = [
|
|
12
|
+
{ id: "seastudio", name: "SeaStudio", description: "\u6587\u4EF6/Shell/Git \u57FA\u7840\u80FD\u529B", tools: allTools }
|
|
13
|
+
];
|
|
14
|
+
function mcpToolToOpenAI(tool) {
|
|
15
|
+
const normalizedTool = normalizeMCPTool(tool);
|
|
16
|
+
const outputSchema = normalizedTool.outputSchema ? normalizeMCPToolObjectSchema(normalizedTool.outputSchema) : void 0;
|
|
17
|
+
return {
|
|
18
|
+
type: "function",
|
|
19
|
+
...normalizedTool.annotations ? { annotations: { ...normalizedTool.annotations } } : {},
|
|
20
|
+
...outputSchema ? { outputSchema } : {},
|
|
21
|
+
function: {
|
|
22
|
+
name: normalizedTool.name,
|
|
23
|
+
description: normalizedTool.description,
|
|
24
|
+
parameters: normalizeMCPToolObjectSchema(normalizedTool.inputSchema),
|
|
25
|
+
...outputSchema ? { outputSchema } : {}
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function listAllTools() {
|
|
30
|
+
return [...allTools];
|
|
31
|
+
}
|
|
32
|
+
function toPackageName(source) {
|
|
33
|
+
if (source === "seastudio") {
|
|
34
|
+
return "SeaStudio";
|
|
35
|
+
}
|
|
36
|
+
return source;
|
|
37
|
+
}
|
|
38
|
+
function toPackageDescription(source) {
|
|
39
|
+
if (source === "seastudio") {
|
|
40
|
+
return "SeaStudio \u539F\u751F MCP \u80FD\u529B";
|
|
41
|
+
}
|
|
42
|
+
return `\u6765\u81EA\u63D2\u4EF6 ${source} \u7684 MCP \u80FD\u529B`;
|
|
43
|
+
}
|
|
44
|
+
function normalizeAvailableTool(raw) {
|
|
45
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
const tool = raw;
|
|
49
|
+
if (typeof tool.name !== "string" || typeof tool.description !== "string" || typeof tool.inputSchema !== "object") {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
const normalized = normalizeMCPTool(tool);
|
|
53
|
+
const source = typeof tool.source === "string" && tool.source.trim() ? tool.source.trim() : "seastudio";
|
|
54
|
+
return {
|
|
55
|
+
...normalized,
|
|
56
|
+
source
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
var MCP_TOOL_PACKAGE_INDEX = new Map(
|
|
60
|
+
allTools.map((tool) => [tool.name, "seastudio"])
|
|
61
|
+
);
|
|
62
|
+
function getMCPToolPackageIndex() {
|
|
63
|
+
return new Map(MCP_TOOL_PACKAGE_INDEX);
|
|
64
|
+
}
|
|
65
|
+
async function listAvailableTools() {
|
|
66
|
+
const result = await getDefaultClient().request("tools/list");
|
|
67
|
+
const rawTools = Array.isArray(result?.tools) ? result.tools : [];
|
|
68
|
+
return rawTools.map(normalizeAvailableTool).filter((tool) => Boolean(tool));
|
|
69
|
+
}
|
|
70
|
+
async function getMCPPackageIdForTool(toolName) {
|
|
71
|
+
const tool = (await listAvailableTools()).find((item) => item.name === toolName);
|
|
72
|
+
return tool?.source ?? null;
|
|
73
|
+
}
|
|
74
|
+
async function listAvailableToolsForLLM() {
|
|
75
|
+
return (await listAvailableTools()).map(mcpToolToOpenAI);
|
|
76
|
+
}
|
|
77
|
+
async function getMCPPackages() {
|
|
78
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
79
|
+
for (const tool of await listAvailableTools()) {
|
|
80
|
+
const existing = grouped.get(tool.source);
|
|
81
|
+
if (existing) {
|
|
82
|
+
existing.toolCount += 1;
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
grouped.set(tool.source, {
|
|
86
|
+
id: tool.source,
|
|
87
|
+
name: toPackageName(tool.source),
|
|
88
|
+
description: toPackageDescription(tool.source),
|
|
89
|
+
toolCount: 1
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
return [...grouped.values()];
|
|
93
|
+
}
|
|
94
|
+
async function getToolsForLLM(disabledPackages) {
|
|
95
|
+
return (await listAvailableTools()).filter((tool) => !disabledPackages.has(tool.source)).map(mcpToolToOpenAI);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export { MCP_PACKAGES, getMCPPackageIdForTool, getMCPPackages, getMCPToolPackageIndex, getToolsForLLM, listAllTools, listAvailableTools, listAvailableToolsForLLM, loadPlugin, mcpToolToOpenAI };
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunk3IVOSJIO_cjs = require('./chunk-3IVOSJIO.cjs');
|
|
4
|
+
var chunk3I7UM66P_cjs = require('./chunk-3I7UM66P.cjs');
|
|
5
|
+
|
|
6
|
+
// src/mcp/index.ts
|
|
7
|
+
async function loadPlugin(pluginName) {
|
|
8
|
+
if (pluginName === "seastudio") {
|
|
9
|
+
return import('./mcp/seastudio/index.cjs');
|
|
10
|
+
}
|
|
11
|
+
throw new Error(`Unknown plugin: ${pluginName}. \u63D2\u4EF6 MCP \u4E0D\u518D\u901A\u8FC7 SDK \u9759\u6001\u5BFC\u5165\u3002`);
|
|
12
|
+
}
|
|
13
|
+
var MCP_PACKAGES = [
|
|
14
|
+
{ id: "seastudio", name: "SeaStudio", description: "\u6587\u4EF6/Shell/Git \u57FA\u7840\u80FD\u529B", tools: chunk3IVOSJIO_cjs.allTools }
|
|
15
|
+
];
|
|
16
|
+
function mcpToolToOpenAI(tool) {
|
|
17
|
+
const normalizedTool = chunk3I7UM66P_cjs.normalizeMCPTool(tool);
|
|
18
|
+
const outputSchema = normalizedTool.outputSchema ? chunk3I7UM66P_cjs.normalizeMCPToolObjectSchema(normalizedTool.outputSchema) : void 0;
|
|
19
|
+
return {
|
|
20
|
+
type: "function",
|
|
21
|
+
...normalizedTool.annotations ? { annotations: { ...normalizedTool.annotations } } : {},
|
|
22
|
+
...outputSchema ? { outputSchema } : {},
|
|
23
|
+
function: {
|
|
24
|
+
name: normalizedTool.name,
|
|
25
|
+
description: normalizedTool.description,
|
|
26
|
+
parameters: chunk3I7UM66P_cjs.normalizeMCPToolObjectSchema(normalizedTool.inputSchema),
|
|
27
|
+
...outputSchema ? { outputSchema } : {}
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function listAllTools() {
|
|
32
|
+
return [...chunk3IVOSJIO_cjs.allTools];
|
|
33
|
+
}
|
|
34
|
+
function toPackageName(source) {
|
|
35
|
+
if (source === "seastudio") {
|
|
36
|
+
return "SeaStudio";
|
|
37
|
+
}
|
|
38
|
+
return source;
|
|
39
|
+
}
|
|
40
|
+
function toPackageDescription(source) {
|
|
41
|
+
if (source === "seastudio") {
|
|
42
|
+
return "SeaStudio \u539F\u751F MCP \u80FD\u529B";
|
|
43
|
+
}
|
|
44
|
+
return `\u6765\u81EA\u63D2\u4EF6 ${source} \u7684 MCP \u80FD\u529B`;
|
|
45
|
+
}
|
|
46
|
+
function normalizeAvailableTool(raw) {
|
|
47
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
const tool = raw;
|
|
51
|
+
if (typeof tool.name !== "string" || typeof tool.description !== "string" || typeof tool.inputSchema !== "object") {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
const normalized = chunk3I7UM66P_cjs.normalizeMCPTool(tool);
|
|
55
|
+
const source = typeof tool.source === "string" && tool.source.trim() ? tool.source.trim() : "seastudio";
|
|
56
|
+
return {
|
|
57
|
+
...normalized,
|
|
58
|
+
source
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
var MCP_TOOL_PACKAGE_INDEX = new Map(
|
|
62
|
+
chunk3IVOSJIO_cjs.allTools.map((tool) => [tool.name, "seastudio"])
|
|
63
|
+
);
|
|
64
|
+
function getMCPToolPackageIndex() {
|
|
65
|
+
return new Map(MCP_TOOL_PACKAGE_INDEX);
|
|
66
|
+
}
|
|
67
|
+
async function listAvailableTools() {
|
|
68
|
+
const result = await chunk3I7UM66P_cjs.getDefaultClient().request("tools/list");
|
|
69
|
+
const rawTools = Array.isArray(result?.tools) ? result.tools : [];
|
|
70
|
+
return rawTools.map(normalizeAvailableTool).filter((tool) => Boolean(tool));
|
|
71
|
+
}
|
|
72
|
+
async function getMCPPackageIdForTool(toolName) {
|
|
73
|
+
const tool = (await listAvailableTools()).find((item) => item.name === toolName);
|
|
74
|
+
return tool?.source ?? null;
|
|
75
|
+
}
|
|
76
|
+
async function listAvailableToolsForLLM() {
|
|
77
|
+
return (await listAvailableTools()).map(mcpToolToOpenAI);
|
|
78
|
+
}
|
|
79
|
+
async function getMCPPackages() {
|
|
80
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
81
|
+
for (const tool of await listAvailableTools()) {
|
|
82
|
+
const existing = grouped.get(tool.source);
|
|
83
|
+
if (existing) {
|
|
84
|
+
existing.toolCount += 1;
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
grouped.set(tool.source, {
|
|
88
|
+
id: tool.source,
|
|
89
|
+
name: toPackageName(tool.source),
|
|
90
|
+
description: toPackageDescription(tool.source),
|
|
91
|
+
toolCount: 1
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
return [...grouped.values()];
|
|
95
|
+
}
|
|
96
|
+
async function getToolsForLLM(disabledPackages) {
|
|
97
|
+
return (await listAvailableTools()).filter((tool) => !disabledPackages.has(tool.source)).map(mcpToolToOpenAI);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
exports.MCP_PACKAGES = MCP_PACKAGES;
|
|
101
|
+
exports.getMCPPackageIdForTool = getMCPPackageIdForTool;
|
|
102
|
+
exports.getMCPPackages = getMCPPackages;
|
|
103
|
+
exports.getMCPToolPackageIndex = getMCPToolPackageIndex;
|
|
104
|
+
exports.getToolsForLLM = getToolsForLLM;
|
|
105
|
+
exports.listAllTools = listAllTools;
|
|
106
|
+
exports.listAvailableTools = listAvailableTools;
|
|
107
|
+
exports.listAvailableToolsForLLM = listAvailableToolsForLLM;
|
|
108
|
+
exports.loadPlugin = loadPlugin;
|
|
109
|
+
exports.mcpToolToOpenAI = mcpToolToOpenAI;
|
|
@@ -292,10 +292,12 @@ var MCPClient = class {
|
|
|
292
292
|
return this.timeout;
|
|
293
293
|
}
|
|
294
294
|
async callTool(name, args = {}, options) {
|
|
295
|
-
|
|
295
|
+
const request = {
|
|
296
296
|
name,
|
|
297
|
-
arguments: args
|
|
298
|
-
|
|
297
|
+
arguments: args,
|
|
298
|
+
...typeof options?.pluginInstanceId === "string" && options.pluginInstanceId.trim() ? { pluginInstanceId: options.pluginInstanceId.trim() } : {}
|
|
299
|
+
};
|
|
300
|
+
return this.request("tools/call", request, {
|
|
299
301
|
timeout: this.resolveToolCallTimeout(name, args, options)
|
|
300
302
|
});
|
|
301
303
|
}
|
|
@@ -377,11 +379,11 @@ function getDefaultClient() {
|
|
|
377
379
|
function setDefaultClient(client) {
|
|
378
380
|
defaultClient = client;
|
|
379
381
|
}
|
|
380
|
-
async function callHostTool(toolName, args = {}) {
|
|
381
|
-
return getDefaultClient().callTool(toolName, args);
|
|
382
|
+
async function callHostTool(toolName, args = {}, options) {
|
|
383
|
+
return getDefaultClient().callTool(toolName, args, options);
|
|
382
384
|
}
|
|
383
|
-
async function callHostToolText(toolName, args = {}) {
|
|
384
|
-
return getDefaultClient().callToolText(toolName, args);
|
|
385
|
+
async function callHostToolText(toolName, args = {}, options) {
|
|
386
|
+
return getDefaultClient().callToolText(toolName, args, options);
|
|
385
387
|
}
|
|
386
388
|
|
|
387
389
|
// src/mcp/core/server.ts
|
|
@@ -9,8 +9,8 @@ var fs = require('fs');
|
|
|
9
9
|
var url = require('url');
|
|
10
10
|
var chalk = require('chalk');
|
|
11
11
|
var ora2 = require('ora');
|
|
12
|
-
var os = require('os');
|
|
13
12
|
var child_process = require('child_process');
|
|
13
|
+
var os = require('os');
|
|
14
14
|
var https = require('https');
|
|
15
15
|
var promises$1 = require('stream/promises');
|
|
16
16
|
var archiver = require('archiver');
|
|
@@ -438,6 +438,73 @@ app.listen(port, '127.0.0.1', () => {
|
|
|
438
438
|
process.exit(1);
|
|
439
439
|
}
|
|
440
440
|
});
|
|
441
|
+
function normalizeTools(tools) {
|
|
442
|
+
return tools.map((tool) => JSON.parse(JSON.stringify({
|
|
443
|
+
name: tool.name,
|
|
444
|
+
description: tool.description,
|
|
445
|
+
inputSchema: tool.inputSchema,
|
|
446
|
+
...tool.outputSchema ? { outputSchema: tool.outputSchema } : {},
|
|
447
|
+
...tool.annotations ? { annotations: tool.annotations } : {}
|
|
448
|
+
})));
|
|
449
|
+
}
|
|
450
|
+
function loadManifestFromEntry(entryPath) {
|
|
451
|
+
const readerScript = `
|
|
452
|
+
import { pathToFileURL } from 'node:url';
|
|
453
|
+
const entryPath = process.argv[1];
|
|
454
|
+
const mod = await import(pathToFileURL(entryPath).href);
|
|
455
|
+
const manifest = mod.pluginMcpManifest ?? (Array.isArray(mod.mcpTools)
|
|
456
|
+
? { schemaVersion: 1, tools: mod.mcpTools }
|
|
457
|
+
: null);
|
|
458
|
+
if (!manifest) {
|
|
459
|
+
throw new Error('frontend/src/mcp-entry.ts \u5FC5\u987B\u5BFC\u51FA pluginMcpManifest \u6216 mcpTools');
|
|
460
|
+
}
|
|
461
|
+
process.stdout.write(JSON.stringify(manifest));
|
|
462
|
+
`;
|
|
463
|
+
const result = child_process.spawnSync(process.execPath, [
|
|
464
|
+
"--experimental-strip-types",
|
|
465
|
+
"--experimental-specifier-resolution=node",
|
|
466
|
+
"--input-type=module",
|
|
467
|
+
"-e",
|
|
468
|
+
readerScript,
|
|
469
|
+
entryPath
|
|
470
|
+
], {
|
|
471
|
+
encoding: "utf-8"
|
|
472
|
+
});
|
|
473
|
+
if (result.status !== 0) {
|
|
474
|
+
throw new Error((result.stderr || result.stdout || "\u8BFB\u53D6 frontend/src/mcp-entry.ts \u5931\u8D25").trim());
|
|
475
|
+
}
|
|
476
|
+
const parsed = JSON.parse(result.stdout || "{}");
|
|
477
|
+
return {
|
|
478
|
+
schemaVersion: 1,
|
|
479
|
+
tools: normalizeTools(parsed.tools ?? [])
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
async function generatePluginMcpManifest(projectDir) {
|
|
483
|
+
const frontendDir = fs.existsSync(path.join(projectDir, "src")) ? projectDir : path.join(projectDir, "frontend");
|
|
484
|
+
const entryPath = path.join(frontendDir, "src", "mcp-entry.ts");
|
|
485
|
+
const outputPath = path.join(frontendDir, "dist", "mcp-manifest.json");
|
|
486
|
+
if (!fs.existsSync(entryPath)) {
|
|
487
|
+
throw new Error(`\u672A\u627E\u5230\u6807\u51C6 MCP \u5165\u53E3\u6587\u4EF6: ${entryPath}`);
|
|
488
|
+
}
|
|
489
|
+
const manifest = loadManifestFromEntry(entryPath);
|
|
490
|
+
await promises.mkdir(path.dirname(outputPath), { recursive: true });
|
|
491
|
+
await promises.writeFile(outputPath, `${JSON.stringify(manifest, null, 2)}
|
|
492
|
+
`, "utf-8");
|
|
493
|
+
return {
|
|
494
|
+
outputPath,
|
|
495
|
+
toolCount: manifest.tools.length
|
|
496
|
+
};
|
|
497
|
+
}
|
|
498
|
+
var generateMcpManifestCommand = new commander.Command("generate-mcp-manifest").description("\u4ECE frontend/src/mcp-entry.ts \u751F\u6210 dist/mcp-manifest.json").option("-d, --dir <directory>", "\u63D2\u4EF6\u9879\u76EE\u76EE\u5F55", ".").action(async (options) => {
|
|
499
|
+
try {
|
|
500
|
+
const projectDir = path.resolve(process.cwd(), options.dir || ".");
|
|
501
|
+
const result = await generatePluginMcpManifest(projectDir);
|
|
502
|
+
console.log(`Generated ${result.outputPath} (${result.toolCount} tools)`);
|
|
503
|
+
} catch (error) {
|
|
504
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
505
|
+
process.exit(1);
|
|
506
|
+
}
|
|
507
|
+
});
|
|
441
508
|
var PYTHON_STANDALONE_RELEASE_API = "https://api.github.com/repos/astral-sh/python-build-standalone/releases/latest";
|
|
442
509
|
var TARGET_PYTHON_MINOR = Number(process.env.SEASTUDIO_AGENT_PYTHON_MINOR) || 12;
|
|
443
510
|
var MAX_PYTHON_MINOR = 13;
|
|
@@ -605,11 +672,11 @@ function pickPythonRuntimeAsset(assets, target) {
|
|
|
605
672
|
return matches[0];
|
|
606
673
|
}
|
|
607
674
|
async function fetchText(url, headers) {
|
|
608
|
-
return new Promise((
|
|
675
|
+
return new Promise((resolve4, reject) => {
|
|
609
676
|
https__default.default.get(url, { headers }, (res) => {
|
|
610
677
|
if (res.statusCode && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
611
678
|
res.resume();
|
|
612
|
-
fetchText(res.headers.location, headers).then(
|
|
679
|
+
fetchText(res.headers.location, headers).then(resolve4).catch(reject);
|
|
613
680
|
return;
|
|
614
681
|
}
|
|
615
682
|
if (res.statusCode && res.statusCode >= 400) {
|
|
@@ -619,13 +686,13 @@ async function fetchText(url, headers) {
|
|
|
619
686
|
}
|
|
620
687
|
const chunks = [];
|
|
621
688
|
res.on("data", (chunk) => chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)));
|
|
622
|
-
res.on("end", () =>
|
|
689
|
+
res.on("end", () => resolve4(Buffer.concat(chunks).toString("utf8")));
|
|
623
690
|
res.on("error", reject);
|
|
624
691
|
}).on("error", reject);
|
|
625
692
|
});
|
|
626
693
|
}
|
|
627
694
|
async function sleep(ms) {
|
|
628
|
-
await new Promise((
|
|
695
|
+
await new Promise((resolve4) => setTimeout(resolve4, ms));
|
|
629
696
|
}
|
|
630
697
|
async function withRetries(label, task) {
|
|
631
698
|
let lastError;
|
|
@@ -960,6 +1027,10 @@ var packCommand = new commander.Command("pack").description("\u6253\u5305\u63D2\
|
|
|
960
1027
|
`);
|
|
961
1028
|
process.exit(1);
|
|
962
1029
|
}
|
|
1030
|
+
if (config.type === "plugin") {
|
|
1031
|
+
const generated = await generatePluginMcpManifest(projectDir);
|
|
1032
|
+
logPackStep(`\u751F\u6210 MCP manifest\uFF1A${generated.outputPath} (${generated.toolCount} tools)`);
|
|
1033
|
+
}
|
|
963
1034
|
spinnerDist.succeed("frontend/dist/index.html \u5DF2\u627E\u5230");
|
|
964
1035
|
} else {
|
|
965
1036
|
const spinnerDist = ora2__default.default("\u8FDC\u7A0B\u63D2\u4EF6\uFF0C\u8DF3\u8FC7 frontend build \u68C0\u67E5").start();
|
|
@@ -1093,8 +1164,8 @@ var installCommand = new commander.Command("install").description("\u5B89\u88C5
|
|
|
1093
1164
|
const tempDir = path.join(targetRoot, ".temp-install-" + Date.now());
|
|
1094
1165
|
fs.mkdirSync(tempDir, { recursive: true });
|
|
1095
1166
|
console.log(`\u{1F4E6} \u89E3\u538B\u5B89\u88C5\u5305: ${path.basename(archivePath)}`);
|
|
1096
|
-
await new Promise((
|
|
1097
|
-
fs.createReadStream(archivePath).pipe(unzipper.Extract({ path: tempDir })).on("close",
|
|
1167
|
+
await new Promise((resolve4, reject) => {
|
|
1168
|
+
fs.createReadStream(archivePath).pipe(unzipper.Extract({ path: tempDir })).on("close", resolve4).on("error", reject);
|
|
1098
1169
|
});
|
|
1099
1170
|
const configPath = path.join(tempDir, "seastudio.config.json");
|
|
1100
1171
|
if (!fs.existsSync(configPath)) {
|
|
@@ -1133,6 +1204,7 @@ var installCommand = new commander.Command("install").description("\u5B89\u88C5
|
|
|
1133
1204
|
var program = new commander.Command();
|
|
1134
1205
|
program.name("seastudio").description("SeaStudio Plugin Development CLI").version("1.0.0");
|
|
1135
1206
|
program.addCommand(createCommand);
|
|
1207
|
+
program.addCommand(generateMcpManifestCommand);
|
|
1136
1208
|
program.addCommand(packCommand);
|
|
1137
1209
|
program.addCommand(installCommand);
|
|
1138
1210
|
program.parse();
|
|
@@ -7,8 +7,8 @@ import { existsSync, createWriteStream, mkdirSync, createReadStream } from 'fs';
|
|
|
7
7
|
import { fileURLToPath } from 'url';
|
|
8
8
|
import chalk from 'chalk';
|
|
9
9
|
import ora2 from 'ora';
|
|
10
|
-
import { tmpdir } from 'os';
|
|
11
10
|
import { spawnSync, spawn } from 'child_process';
|
|
11
|
+
import { tmpdir } from 'os';
|
|
12
12
|
import https from 'https';
|
|
13
13
|
import { pipeline } from 'stream/promises';
|
|
14
14
|
import archiver from 'archiver';
|
|
@@ -427,6 +427,73 @@ app.listen(port, '127.0.0.1', () => {
|
|
|
427
427
|
process.exit(1);
|
|
428
428
|
}
|
|
429
429
|
});
|
|
430
|
+
function normalizeTools(tools) {
|
|
431
|
+
return tools.map((tool) => JSON.parse(JSON.stringify({
|
|
432
|
+
name: tool.name,
|
|
433
|
+
description: tool.description,
|
|
434
|
+
inputSchema: tool.inputSchema,
|
|
435
|
+
...tool.outputSchema ? { outputSchema: tool.outputSchema } : {},
|
|
436
|
+
...tool.annotations ? { annotations: tool.annotations } : {}
|
|
437
|
+
})));
|
|
438
|
+
}
|
|
439
|
+
function loadManifestFromEntry(entryPath) {
|
|
440
|
+
const readerScript = `
|
|
441
|
+
import { pathToFileURL } from 'node:url';
|
|
442
|
+
const entryPath = process.argv[1];
|
|
443
|
+
const mod = await import(pathToFileURL(entryPath).href);
|
|
444
|
+
const manifest = mod.pluginMcpManifest ?? (Array.isArray(mod.mcpTools)
|
|
445
|
+
? { schemaVersion: 1, tools: mod.mcpTools }
|
|
446
|
+
: null);
|
|
447
|
+
if (!manifest) {
|
|
448
|
+
throw new Error('frontend/src/mcp-entry.ts \u5FC5\u987B\u5BFC\u51FA pluginMcpManifest \u6216 mcpTools');
|
|
449
|
+
}
|
|
450
|
+
process.stdout.write(JSON.stringify(manifest));
|
|
451
|
+
`;
|
|
452
|
+
const result = spawnSync(process.execPath, [
|
|
453
|
+
"--experimental-strip-types",
|
|
454
|
+
"--experimental-specifier-resolution=node",
|
|
455
|
+
"--input-type=module",
|
|
456
|
+
"-e",
|
|
457
|
+
readerScript,
|
|
458
|
+
entryPath
|
|
459
|
+
], {
|
|
460
|
+
encoding: "utf-8"
|
|
461
|
+
});
|
|
462
|
+
if (result.status !== 0) {
|
|
463
|
+
throw new Error((result.stderr || result.stdout || "\u8BFB\u53D6 frontend/src/mcp-entry.ts \u5931\u8D25").trim());
|
|
464
|
+
}
|
|
465
|
+
const parsed = JSON.parse(result.stdout || "{}");
|
|
466
|
+
return {
|
|
467
|
+
schemaVersion: 1,
|
|
468
|
+
tools: normalizeTools(parsed.tools ?? [])
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
async function generatePluginMcpManifest(projectDir) {
|
|
472
|
+
const frontendDir = existsSync(join(projectDir, "src")) ? projectDir : join(projectDir, "frontend");
|
|
473
|
+
const entryPath = join(frontendDir, "src", "mcp-entry.ts");
|
|
474
|
+
const outputPath = join(frontendDir, "dist", "mcp-manifest.json");
|
|
475
|
+
if (!existsSync(entryPath)) {
|
|
476
|
+
throw new Error(`\u672A\u627E\u5230\u6807\u51C6 MCP \u5165\u53E3\u6587\u4EF6: ${entryPath}`);
|
|
477
|
+
}
|
|
478
|
+
const manifest = loadManifestFromEntry(entryPath);
|
|
479
|
+
await mkdir(dirname(outputPath), { recursive: true });
|
|
480
|
+
await writeFile(outputPath, `${JSON.stringify(manifest, null, 2)}
|
|
481
|
+
`, "utf-8");
|
|
482
|
+
return {
|
|
483
|
+
outputPath,
|
|
484
|
+
toolCount: manifest.tools.length
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
var generateMcpManifestCommand = new Command("generate-mcp-manifest").description("\u4ECE frontend/src/mcp-entry.ts \u751F\u6210 dist/mcp-manifest.json").option("-d, --dir <directory>", "\u63D2\u4EF6\u9879\u76EE\u76EE\u5F55", ".").action(async (options) => {
|
|
488
|
+
try {
|
|
489
|
+
const projectDir = resolve(process.cwd(), options.dir || ".");
|
|
490
|
+
const result = await generatePluginMcpManifest(projectDir);
|
|
491
|
+
console.log(`Generated ${result.outputPath} (${result.toolCount} tools)`);
|
|
492
|
+
} catch (error) {
|
|
493
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
494
|
+
process.exit(1);
|
|
495
|
+
}
|
|
496
|
+
});
|
|
430
497
|
var PYTHON_STANDALONE_RELEASE_API = "https://api.github.com/repos/astral-sh/python-build-standalone/releases/latest";
|
|
431
498
|
var TARGET_PYTHON_MINOR = Number(process.env.SEASTUDIO_AGENT_PYTHON_MINOR) || 12;
|
|
432
499
|
var MAX_PYTHON_MINOR = 13;
|
|
@@ -594,11 +661,11 @@ function pickPythonRuntimeAsset(assets, target) {
|
|
|
594
661
|
return matches[0];
|
|
595
662
|
}
|
|
596
663
|
async function fetchText(url, headers) {
|
|
597
|
-
return new Promise((
|
|
664
|
+
return new Promise((resolve4, reject) => {
|
|
598
665
|
https.get(url, { headers }, (res) => {
|
|
599
666
|
if (res.statusCode && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
600
667
|
res.resume();
|
|
601
|
-
fetchText(res.headers.location, headers).then(
|
|
668
|
+
fetchText(res.headers.location, headers).then(resolve4).catch(reject);
|
|
602
669
|
return;
|
|
603
670
|
}
|
|
604
671
|
if (res.statusCode && res.statusCode >= 400) {
|
|
@@ -608,13 +675,13 @@ async function fetchText(url, headers) {
|
|
|
608
675
|
}
|
|
609
676
|
const chunks = [];
|
|
610
677
|
res.on("data", (chunk) => chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)));
|
|
611
|
-
res.on("end", () =>
|
|
678
|
+
res.on("end", () => resolve4(Buffer.concat(chunks).toString("utf8")));
|
|
612
679
|
res.on("error", reject);
|
|
613
680
|
}).on("error", reject);
|
|
614
681
|
});
|
|
615
682
|
}
|
|
616
683
|
async function sleep(ms) {
|
|
617
|
-
await new Promise((
|
|
684
|
+
await new Promise((resolve4) => setTimeout(resolve4, ms));
|
|
618
685
|
}
|
|
619
686
|
async function withRetries(label, task) {
|
|
620
687
|
let lastError;
|
|
@@ -949,6 +1016,10 @@ var packCommand = new Command("pack").description("\u6253\u5305\u63D2\u4EF6\u621
|
|
|
949
1016
|
`);
|
|
950
1017
|
process.exit(1);
|
|
951
1018
|
}
|
|
1019
|
+
if (config.type === "plugin") {
|
|
1020
|
+
const generated = await generatePluginMcpManifest(projectDir);
|
|
1021
|
+
logPackStep(`\u751F\u6210 MCP manifest\uFF1A${generated.outputPath} (${generated.toolCount} tools)`);
|
|
1022
|
+
}
|
|
952
1023
|
spinnerDist.succeed("frontend/dist/index.html \u5DF2\u627E\u5230");
|
|
953
1024
|
} else {
|
|
954
1025
|
const spinnerDist = ora2("\u8FDC\u7A0B\u63D2\u4EF6\uFF0C\u8DF3\u8FC7 frontend build \u68C0\u67E5").start();
|
|
@@ -1082,8 +1153,8 @@ var installCommand = new Command("install").description("\u5B89\u88C5 .seaplugin
|
|
|
1082
1153
|
const tempDir = join(targetRoot, ".temp-install-" + Date.now());
|
|
1083
1154
|
mkdirSync(tempDir, { recursive: true });
|
|
1084
1155
|
console.log(`\u{1F4E6} \u89E3\u538B\u5B89\u88C5\u5305: ${basename(archivePath)}`);
|
|
1085
|
-
await new Promise((
|
|
1086
|
-
createReadStream(archivePath).pipe(Extract({ path: tempDir })).on("close",
|
|
1156
|
+
await new Promise((resolve4, reject) => {
|
|
1157
|
+
createReadStream(archivePath).pipe(Extract({ path: tempDir })).on("close", resolve4).on("error", reject);
|
|
1087
1158
|
});
|
|
1088
1159
|
const configPath = join(tempDir, "seastudio.config.json");
|
|
1089
1160
|
if (!existsSync(configPath)) {
|
|
@@ -1122,6 +1193,7 @@ var installCommand = new Command("install").description("\u5B89\u88C5 .seaplugin
|
|
|
1122
1193
|
var program = new Command();
|
|
1123
1194
|
program.name("seastudio").description("SeaStudio Plugin Development CLI").version("1.0.0");
|
|
1124
1195
|
program.addCommand(createCommand);
|
|
1196
|
+
program.addCommand(generateMcpManifestCommand);
|
|
1125
1197
|
program.addCommand(packCommand);
|
|
1126
1198
|
program.addCommand(installCommand);
|
|
1127
1199
|
program.parse();
|