@seastudio/sdk 3.0.2 → 3.0.3
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/bin/seastudio.js +0 -0
- package/dist/chunk-D7ONFXVY.js +98 -0
- package/dist/chunk-EIOFZMTC.cjs +109 -0
- package/dist/develop-tool/cli/index.cjs +79 -7
- package/dist/develop-tool/cli/index.js +79 -7
- package/dist/index.cjs +39 -189
- package/dist/index.d.cts +2 -7
- package/dist/index.d.ts +2 -7
- package/dist/index.js +1 -7
- package/dist/mcp/core/index.d.cts +2 -2
- package/dist/mcp/core/index.d.ts +2 -2
- package/dist/mcp/index.cjs +11 -161
- package/dist/mcp/index.d.cts +12 -83
- package/dist/mcp/index.d.ts +12 -83
- package/dist/mcp/index.js +1 -7
- package/dist/mcp/seastudio/index.d.cts +1 -1
- package/dist/mcp/seastudio/index.d.ts +1 -1
- package/dist/{types-B1Zqr-0Q.d.cts → types-B32sUvc0.d.cts} +9 -1
- package/dist/{types-B1Zqr-0Q.d.ts → types-B32sUvc0.d.ts} +9 -1
- package/package.json +2 -22
- package/src/develop-tool/templates/plugin/frontend/package.json.tmpl +1 -1
- 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/bin/seastudio.js
CHANGED
|
File without changes
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { allTools } from './chunk-XU5GEWWL.js';
|
|
2
|
+
import { normalizeMCPTool, normalizeMCPToolObjectSchema, getDefaultClient } from './chunk-ANWOL7SM.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 chunkSUF5BPSK_cjs = require('./chunk-SUF5BPSK.cjs');
|
|
4
|
+
var chunkTFOJLA2F_cjs = require('./chunk-TFOJLA2F.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: chunkSUF5BPSK_cjs.allTools }
|
|
15
|
+
];
|
|
16
|
+
function mcpToolToOpenAI(tool) {
|
|
17
|
+
const normalizedTool = chunkTFOJLA2F_cjs.normalizeMCPTool(tool);
|
|
18
|
+
const outputSchema = normalizedTool.outputSchema ? chunkTFOJLA2F_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: chunkTFOJLA2F_cjs.normalizeMCPToolObjectSchema(normalizedTool.inputSchema),
|
|
27
|
+
...outputSchema ? { outputSchema } : {}
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function listAllTools() {
|
|
32
|
+
return [...chunkSUF5BPSK_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 = chunkTFOJLA2F_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
|
+
chunkSUF5BPSK_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 chunkTFOJLA2F_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;
|
|
@@ -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();
|