@seastudio/sdk 3.3.0 → 3.3.2
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/{chunk-2MGJLIRZ.cjs → chunk-2SQFLDTT.cjs} +4 -4
- package/dist/{chunk-VFDZPHJD.js → chunk-BUC7WN5U.js} +1 -1
- package/dist/chunk-GCE3TTCJ.cjs +184 -0
- package/dist/{chunk-CJ2BXMJ3.js → chunk-IZRKT6NQ.js} +25 -1
- package/dist/chunk-O2C4Z5B5.cjs +65 -0
- package/dist/chunk-OVBIWRAB.js +170 -0
- package/dist/{chunk-RRDE5HQX.cjs → chunk-UXBJODKS.cjs} +25 -1
- package/dist/chunk-ZOGVKB2Z.js +57 -0
- package/dist/index.cjs +133 -51
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +5 -3
- package/dist/mcp/index.cjs +24 -24
- package/dist/mcp/index.js +2 -2
- package/dist/mcp/seastudio/index.cjs +29 -29
- package/dist/mcp/seastudio/index.d.cts +6 -0
- package/dist/mcp/seastudio/index.d.ts +6 -0
- package/dist/mcp/seastudio/index.js +1 -1
- package/dist/registry-OS2Xo46V.d.cts +138 -0
- package/dist/registry-OS2Xo46V.d.ts +138 -0
- package/dist/skill/index.cjs +87 -0
- package/dist/skill/index.d.cts +60 -0
- package/dist/skill/index.d.ts +60 -0
- package/dist/skill/index.js +2 -0
- package/dist/skill/registry.cjs +34 -0
- package/dist/skill/registry.d.cts +1 -0
- package/dist/skill/registry.d.ts +1 -0
- package/dist/skill/registry.js +1 -0
- package/package.json +11 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkUXBJODKS_cjs = require('./chunk-UXBJODKS.cjs');
|
|
4
4
|
var chunk3I7UM66P_cjs = require('./chunk-3I7UM66P.cjs');
|
|
5
5
|
|
|
6
6
|
// src/mcp/index.ts
|
|
@@ -11,7 +11,7 @@ async function loadPlugin(pluginName) {
|
|
|
11
11
|
throw new Error(`Unknown plugin: ${pluginName}. \u63D2\u4EF6 MCP \u4E0D\u518D\u901A\u8FC7 SDK \u9759\u6001\u5BFC\u5165\u3002`);
|
|
12
12
|
}
|
|
13
13
|
var MCP_PACKAGES = [
|
|
14
|
-
{ id: "seastudio", name: "SeaStudio", description: "\u6587\u4EF6/Shell/AIGC \u57FA\u7840\u80FD\u529B", tools:
|
|
14
|
+
{ id: "seastudio", name: "SeaStudio", description: "\u6587\u4EF6/Shell/AIGC \u57FA\u7840\u80FD\u529B", tools: chunkUXBJODKS_cjs.allTools }
|
|
15
15
|
];
|
|
16
16
|
function mcpToolToOpenAI(tool) {
|
|
17
17
|
const normalizedTool = chunk3I7UM66P_cjs.normalizeMCPTool(tool);
|
|
@@ -29,7 +29,7 @@ function mcpToolToOpenAI(tool) {
|
|
|
29
29
|
};
|
|
30
30
|
}
|
|
31
31
|
function listAllTools() {
|
|
32
|
-
return [...
|
|
32
|
+
return [...chunkUXBJODKS_cjs.allTools];
|
|
33
33
|
}
|
|
34
34
|
function toPackageName(source) {
|
|
35
35
|
if (source === "seastudio") {
|
|
@@ -59,7 +59,7 @@ function normalizeAvailableTool(raw) {
|
|
|
59
59
|
};
|
|
60
60
|
}
|
|
61
61
|
var MCP_TOOL_PACKAGE_INDEX = new Map(
|
|
62
|
-
|
|
62
|
+
chunkUXBJODKS_cjs.allTools.map((tool) => [tool.name, "seastudio"])
|
|
63
63
|
);
|
|
64
64
|
function getMCPToolPackageIndex() {
|
|
65
65
|
return new Map(MCP_TOOL_PACKAGE_INDEX);
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/skill/parser.ts
|
|
4
|
+
var FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
|
|
5
|
+
function stripQuotes(value) {
|
|
6
|
+
const trimmed = value.trim();
|
|
7
|
+
if (trimmed.length >= 2) {
|
|
8
|
+
const first = trimmed[0];
|
|
9
|
+
const last = trimmed[trimmed.length - 1];
|
|
10
|
+
if (first === '"' && last === '"' || first === "'" && last === "'") {
|
|
11
|
+
return trimmed.slice(1, -1);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return trimmed;
|
|
15
|
+
}
|
|
16
|
+
function parseInlineList(value) {
|
|
17
|
+
const trimmed = value.trim();
|
|
18
|
+
if (!trimmed.startsWith("[") || !trimmed.endsWith("]")) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
const inner = trimmed.slice(1, -1).trim();
|
|
22
|
+
if (!inner) return [];
|
|
23
|
+
return inner.split(",").map((part) => stripQuotes(part)).filter((s) => s.length > 0);
|
|
24
|
+
}
|
|
25
|
+
function parseSkillFrontmatter(markdown) {
|
|
26
|
+
const match = FRONTMATTER_RE.exec(markdown);
|
|
27
|
+
if (!match) return {};
|
|
28
|
+
const block = match[1];
|
|
29
|
+
const result = { extra: {} };
|
|
30
|
+
const lines = block.split(/\r?\n/);
|
|
31
|
+
let pendingListKey = null;
|
|
32
|
+
const pendingList = [];
|
|
33
|
+
const flushPendingList = () => {
|
|
34
|
+
if (pendingListKey) {
|
|
35
|
+
if (pendingListKey === "tags") {
|
|
36
|
+
result.tags = [...pendingList];
|
|
37
|
+
} else {
|
|
38
|
+
result.extra[pendingListKey] = pendingList.join(",");
|
|
39
|
+
}
|
|
40
|
+
pendingListKey = null;
|
|
41
|
+
pendingList.length = 0;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
for (const rawLine of lines) {
|
|
45
|
+
const line = rawLine.replace(/\s+$/g, "");
|
|
46
|
+
if (!line.trim()) {
|
|
47
|
+
flushPendingList();
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const listItemMatch = /^\s*-\s+(.*)$/.exec(line);
|
|
51
|
+
if (listItemMatch && pendingListKey) {
|
|
52
|
+
pendingList.push(stripQuotes(listItemMatch[1]));
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
flushPendingList();
|
|
56
|
+
const kvMatch = /^([A-Za-z0-9_-]+)\s*:\s*(.*)$/.exec(line);
|
|
57
|
+
if (!kvMatch) continue;
|
|
58
|
+
const key = kvMatch[1];
|
|
59
|
+
const value = kvMatch[2];
|
|
60
|
+
if (value === "") {
|
|
61
|
+
pendingListKey = key;
|
|
62
|
+
pendingList.length = 0;
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
if (key === "tags") {
|
|
66
|
+
const inline = parseInlineList(value);
|
|
67
|
+
if (inline !== null) {
|
|
68
|
+
result.tags = inline;
|
|
69
|
+
} else {
|
|
70
|
+
result.tags = stripQuotes(value).split(",").map((s) => s.trim()).filter(Boolean);
|
|
71
|
+
}
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const cleaned = stripQuotes(value);
|
|
75
|
+
if (key === "name") result.name = cleaned;
|
|
76
|
+
else if (key === "description") result.description = cleaned;
|
|
77
|
+
else result.extra[key] = cleaned;
|
|
78
|
+
}
|
|
79
|
+
flushPendingList();
|
|
80
|
+
if (result.extra && Object.keys(result.extra).length === 0) {
|
|
81
|
+
delete result.extra;
|
|
82
|
+
}
|
|
83
|
+
return result;
|
|
84
|
+
}
|
|
85
|
+
function buildSkillId(source, dirName) {
|
|
86
|
+
const safe = dirName.trim().replace(/[\\/]+/g, "-").replace(/\s+/g, "-");
|
|
87
|
+
return `${source}:${safe}`;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// src/skill/client.ts
|
|
91
|
+
var currentTransport = null;
|
|
92
|
+
function setSkillTransport(transport) {
|
|
93
|
+
currentTransport = transport;
|
|
94
|
+
}
|
|
95
|
+
function getSkillTransport() {
|
|
96
|
+
if (currentTransport) {
|
|
97
|
+
return currentTransport;
|
|
98
|
+
}
|
|
99
|
+
const auto = tryAutoBindElectronTransport();
|
|
100
|
+
if (auto) {
|
|
101
|
+
currentTransport = auto;
|
|
102
|
+
return auto;
|
|
103
|
+
}
|
|
104
|
+
throw new Error(
|
|
105
|
+
"[skill] No SkillTransport configured. Call setSkillTransport() or useElectronSkillTransport() first."
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
async function listSkills() {
|
|
109
|
+
return getSkillTransport().list();
|
|
110
|
+
}
|
|
111
|
+
async function getSkill(id) {
|
|
112
|
+
return getSkillTransport().get(id);
|
|
113
|
+
}
|
|
114
|
+
async function rescanSkills() {
|
|
115
|
+
return getSkillTransport().rescan();
|
|
116
|
+
}
|
|
117
|
+
function onSkillsChanged(listener) {
|
|
118
|
+
const transport = getSkillTransport();
|
|
119
|
+
if (!transport.onChanged) {
|
|
120
|
+
return () => {
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
return transport.onChanged(listener);
|
|
124
|
+
}
|
|
125
|
+
async function setSkillEnabled(id, value) {
|
|
126
|
+
const t = getSkillTransport();
|
|
127
|
+
if (!t.setEnabled) throw new Error("[skill] transport.setEnabled not supported");
|
|
128
|
+
return t.setEnabled(id, value);
|
|
129
|
+
}
|
|
130
|
+
async function setSkillScope(id, scope) {
|
|
131
|
+
const t = getSkillTransport();
|
|
132
|
+
if (!t.setScope) throw new Error("[skill] transport.setScope not supported");
|
|
133
|
+
return t.setScope(id, scope);
|
|
134
|
+
}
|
|
135
|
+
async function uninstallSkill(id) {
|
|
136
|
+
const t = getSkillTransport();
|
|
137
|
+
if (!t.uninstall) throw new Error("[skill] transport.uninstall not supported");
|
|
138
|
+
return t.uninstall(id);
|
|
139
|
+
}
|
|
140
|
+
async function listSkillProjects() {
|
|
141
|
+
const t = getSkillTransport();
|
|
142
|
+
if (!t.listProjects) throw new Error("[skill] transport.listProjects not supported");
|
|
143
|
+
return t.listProjects();
|
|
144
|
+
}
|
|
145
|
+
function readElectronSkillBridge() {
|
|
146
|
+
const globalAny = globalThis;
|
|
147
|
+
return globalAny.electronAPI?.engine?.skill ?? null;
|
|
148
|
+
}
|
|
149
|
+
function tryAutoBindElectronTransport() {
|
|
150
|
+
const bridge = readElectronSkillBridge();
|
|
151
|
+
if (!bridge) return null;
|
|
152
|
+
return {
|
|
153
|
+
list: () => bridge.list(),
|
|
154
|
+
get: (id) => bridge.get(id),
|
|
155
|
+
rescan: () => bridge.rescan(),
|
|
156
|
+
onChanged: bridge.onChanged ? (cb) => bridge.onChanged(cb) : void 0,
|
|
157
|
+
setEnabled: bridge.setEnabled ? (id, value) => bridge.setEnabled(id, value) : void 0,
|
|
158
|
+
setScope: bridge.setScope ? (id, scope) => bridge.setScope(id, scope) : void 0,
|
|
159
|
+
uninstall: bridge.uninstall ? (id) => bridge.uninstall(id) : void 0,
|
|
160
|
+
listProjects: bridge.listProjects ? () => bridge.listProjects() : void 0
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
function useElectronSkillTransport() {
|
|
164
|
+
const transport = tryAutoBindElectronTransport();
|
|
165
|
+
if (transport) {
|
|
166
|
+
setSkillTransport(transport);
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
exports.buildSkillId = buildSkillId;
|
|
173
|
+
exports.getSkill = getSkill;
|
|
174
|
+
exports.getSkillTransport = getSkillTransport;
|
|
175
|
+
exports.listSkillProjects = listSkillProjects;
|
|
176
|
+
exports.listSkills = listSkills;
|
|
177
|
+
exports.onSkillsChanged = onSkillsChanged;
|
|
178
|
+
exports.parseSkillFrontmatter = parseSkillFrontmatter;
|
|
179
|
+
exports.rescanSkills = rescanSkills;
|
|
180
|
+
exports.setSkillEnabled = setSkillEnabled;
|
|
181
|
+
exports.setSkillScope = setSkillScope;
|
|
182
|
+
exports.setSkillTransport = setSkillTransport;
|
|
183
|
+
exports.uninstallSkill = uninstallSkill;
|
|
184
|
+
exports.useElectronSkillTransport = useElectronSkillTransport;
|
|
@@ -173,7 +173,7 @@ var fileTools = [
|
|
|
173
173
|
}, rootedWriteEvidenceOutputSchema),
|
|
174
174
|
annotateTool({
|
|
175
175
|
name: "seastudio-file_list",
|
|
176
|
-
description: "\u5217\u51FA\u6307\u5B9A\u76EE\u5F55\
|
|
176
|
+
description: "\u5217\u51FA\u6307\u5B9A\u76EE\u5F55\u7684\u76F4\u63A5\u5B50\u9879\uFF08\u4E0D\u9012\u5F52\uFF0C\u7C7B\u4F3C ls\uFF09\u3002\u9002\u7528\u4E8E\u5728\u6267\u884C\u8BFB\u5199\u524D\u786E\u8BA4\u76EE\u5F55\u5185\u5BB9\u6216\u5B9A\u4F4D\u76EE\u6807\u8DEF\u5F84\u3002\u5982\u9700\u9012\u5F52\u904D\u5386\u5B50\u6811\u8BF7\u4F7F\u7528 seastudio-file_tree\u3002",
|
|
177
177
|
inputSchema: {
|
|
178
178
|
type: "object",
|
|
179
179
|
properties: {
|
|
@@ -187,6 +187,24 @@ var fileTools = [
|
|
|
187
187
|
requiresExecutionEvidence: false,
|
|
188
188
|
rawDomain: "filesystem"
|
|
189
189
|
}),
|
|
190
|
+
annotateTool({
|
|
191
|
+
name: "seastudio-file_tree",
|
|
192
|
+
description: "\u9012\u5F52\u5217\u51FA\u6307\u5B9A\u76EE\u5F55\u7684\u6574\u4E2A\u5B50\u6811\uFF08\u6241\u5E73 items \u5217\u8868\uFF0C\u6BCF\u9879\u542B\u76F8\u5BF9 rootId \u7684\u6839\u76F8\u5BF9\u8DEF\u5F84\uFF09\u3002\u4EC5\u5728\u786E\u5B9E\u9700\u8981\u5168\u6811\u89C6\u56FE\u65F6\u4F7F\u7528\uFF1B\u8FD4\u56DE\u7ED3\u679C\u53EF\u80FD\u5F88\u5927\uFF0C\u5EFA\u8BAE\u4F18\u5148\u4F7F\u7528 seastudio-file_list \u6309\u9700\u9010\u5C42\u63A2\u7D22\u3002",
|
|
193
|
+
inputSchema: {
|
|
194
|
+
type: "object",
|
|
195
|
+
properties: {
|
|
196
|
+
rootId: { type: "string", description: "\u76EE\u6807\u9879\u76EE\u6839\uFF1A'workspace' \u8868\u793A\u5F53\u524D\u6FC0\u6D3B\u9879\u76EE\uFF1B'proj-<projectId>' \u8868\u793A\u6309 id \u5BFB\u5740\u67D0\u4E2A\u9879\u76EE" },
|
|
197
|
+
path: { type: "string", description: "\u76EE\u5F55\u8DEF\u5F84\uFF08\u76F8\u5BF9\u4E8E rootId\uFF09" },
|
|
198
|
+
maxDepth: { type: "number", description: "\u6700\u5927\u9012\u5F52\u6DF1\u5EA6\uFF080 \u8868\u793A\u53EA\u5217\u5F53\u524D\u76EE\u5F55\uFF0C\u7B49\u4EF7\u4E8E file_list\uFF1B\u7701\u7565\u8868\u793A\u4E0D\u9650\u5236\uFF09" },
|
|
199
|
+
maxEntries: { type: "number", description: "\u6700\u591A\u8FD4\u56DE\u591A\u5C11\u4E2A\u6761\u76EE\uFF0C\u8D85\u51FA\u540E\u622A\u65AD\u5E76\u5728\u54CD\u5E94\u91CC truncated=true\uFF08\u9ED8\u8BA4 50000\uFF09" }
|
|
200
|
+
},
|
|
201
|
+
required: ["rootId", "path"]
|
|
202
|
+
}
|
|
203
|
+
}, {
|
|
204
|
+
operationKind: "read",
|
|
205
|
+
requiresExecutionEvidence: false,
|
|
206
|
+
rawDomain: "filesystem"
|
|
207
|
+
}),
|
|
190
208
|
annotateTool({
|
|
191
209
|
name: "seastudio-file_delete",
|
|
192
210
|
description: "\u5220\u9664\u6307\u5B9A\u8DEF\u5F84\u7684\u6587\u4EF6\u6216\u76EE\u5F55\u3002\u4EC5\u5728\u7528\u6237\u660E\u786E\u8981\u6C42\u79FB\u9664\u76EE\u6807\u65F6\u4F7F\u7528\uFF0C\u6210\u529F\u540E\u76EE\u6807\u4F1A\u4ECE\u9879\u76EE\u4E2D\u6D88\u5931\u3002",
|
|
@@ -841,6 +859,12 @@ var seastudio = {
|
|
|
841
859
|
rootId: options?.rootId ?? "workspace",
|
|
842
860
|
path
|
|
843
861
|
}),
|
|
862
|
+
tree: (path = "", options) => callTool("seastudio-file_tree", {
|
|
863
|
+
rootId: options?.rootId ?? "workspace",
|
|
864
|
+
path,
|
|
865
|
+
...typeof options?.maxDepth === "number" ? { maxDepth: options.maxDepth } : {},
|
|
866
|
+
...typeof options?.maxEntries === "number" ? { maxEntries: options.maxEntries } : {}
|
|
867
|
+
}),
|
|
844
868
|
delete: (path, options) => callTool("seastudio-file_delete", { rootId: options?.rootId ?? "workspace", path }),
|
|
845
869
|
mkdir: (path, options) => callTool("seastudio-file_mkdir", { rootId: options?.rootId ?? "workspace", path }),
|
|
846
870
|
exists: (path, options) => callTool("seastudio-file_exists", { rootId: options?.rootId ?? "workspace", path }),
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/skill/registry.ts
|
|
4
|
+
var currentTransport = null;
|
|
5
|
+
function setSkillRegistryTransport(transport) {
|
|
6
|
+
currentTransport = transport;
|
|
7
|
+
}
|
|
8
|
+
function getSkillRegistryTransport() {
|
|
9
|
+
if (currentTransport) return currentTransport;
|
|
10
|
+
const auto = tryAutoBindElectronTransport();
|
|
11
|
+
if (auto) {
|
|
12
|
+
currentTransport = auto;
|
|
13
|
+
return auto;
|
|
14
|
+
}
|
|
15
|
+
throw new Error(
|
|
16
|
+
"[skill/registry] No SkillRegistryTransport configured. Call setSkillRegistryTransport() or useElectronSkillRegistryTransport() first."
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
async function listMarketSkills() {
|
|
20
|
+
const payload = await getSkillRegistryTransport().list();
|
|
21
|
+
return Array.isArray(payload.skills) ? payload.skills : [];
|
|
22
|
+
}
|
|
23
|
+
async function getMarketSkill(id) {
|
|
24
|
+
return getSkillRegistryTransport().detail(id);
|
|
25
|
+
}
|
|
26
|
+
async function selectPublishSkillFile() {
|
|
27
|
+
const t = getSkillRegistryTransport();
|
|
28
|
+
if (!t.selectPublishFile) throw new Error("[skill/registry] transport.selectPublishFile not supported");
|
|
29
|
+
return t.selectPublishFile();
|
|
30
|
+
}
|
|
31
|
+
async function publishSkill(archivePath, publishPassword) {
|
|
32
|
+
const t = getSkillRegistryTransport();
|
|
33
|
+
if (!t.publishFile) throw new Error("[skill/registry] transport.publishFile not supported");
|
|
34
|
+
return t.publishFile(archivePath, publishPassword);
|
|
35
|
+
}
|
|
36
|
+
function readElectronSkillRegistryBridge() {
|
|
37
|
+
const globalAny = globalThis;
|
|
38
|
+
return globalAny.electronAPI?.engine?.skillRegistry ?? null;
|
|
39
|
+
}
|
|
40
|
+
function tryAutoBindElectronTransport() {
|
|
41
|
+
const bridge = readElectronSkillRegistryBridge();
|
|
42
|
+
if (!bridge) return null;
|
|
43
|
+
return {
|
|
44
|
+
list: () => bridge.list(),
|
|
45
|
+
detail: (id) => bridge.detail(id),
|
|
46
|
+
selectPublishFile: bridge.selectPublishFile ? () => bridge.selectPublishFile() : void 0,
|
|
47
|
+
publishFile: bridge.publishFile ? (archivePath, password) => bridge.publishFile(archivePath, password) : void 0
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function useElectronSkillRegistryTransport() {
|
|
51
|
+
const transport = tryAutoBindElectronTransport();
|
|
52
|
+
if (transport) {
|
|
53
|
+
setSkillRegistryTransport(transport);
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
exports.getMarketSkill = getMarketSkill;
|
|
60
|
+
exports.getSkillRegistryTransport = getSkillRegistryTransport;
|
|
61
|
+
exports.listMarketSkills = listMarketSkills;
|
|
62
|
+
exports.publishSkill = publishSkill;
|
|
63
|
+
exports.selectPublishSkillFile = selectPublishSkillFile;
|
|
64
|
+
exports.setSkillRegistryTransport = setSkillRegistryTransport;
|
|
65
|
+
exports.useElectronSkillRegistryTransport = useElectronSkillRegistryTransport;
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
// src/skill/parser.ts
|
|
2
|
+
var FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
|
|
3
|
+
function stripQuotes(value) {
|
|
4
|
+
const trimmed = value.trim();
|
|
5
|
+
if (trimmed.length >= 2) {
|
|
6
|
+
const first = trimmed[0];
|
|
7
|
+
const last = trimmed[trimmed.length - 1];
|
|
8
|
+
if (first === '"' && last === '"' || first === "'" && last === "'") {
|
|
9
|
+
return trimmed.slice(1, -1);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
return trimmed;
|
|
13
|
+
}
|
|
14
|
+
function parseInlineList(value) {
|
|
15
|
+
const trimmed = value.trim();
|
|
16
|
+
if (!trimmed.startsWith("[") || !trimmed.endsWith("]")) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
const inner = trimmed.slice(1, -1).trim();
|
|
20
|
+
if (!inner) return [];
|
|
21
|
+
return inner.split(",").map((part) => stripQuotes(part)).filter((s) => s.length > 0);
|
|
22
|
+
}
|
|
23
|
+
function parseSkillFrontmatter(markdown) {
|
|
24
|
+
const match = FRONTMATTER_RE.exec(markdown);
|
|
25
|
+
if (!match) return {};
|
|
26
|
+
const block = match[1];
|
|
27
|
+
const result = { extra: {} };
|
|
28
|
+
const lines = block.split(/\r?\n/);
|
|
29
|
+
let pendingListKey = null;
|
|
30
|
+
const pendingList = [];
|
|
31
|
+
const flushPendingList = () => {
|
|
32
|
+
if (pendingListKey) {
|
|
33
|
+
if (pendingListKey === "tags") {
|
|
34
|
+
result.tags = [...pendingList];
|
|
35
|
+
} else {
|
|
36
|
+
result.extra[pendingListKey] = pendingList.join(",");
|
|
37
|
+
}
|
|
38
|
+
pendingListKey = null;
|
|
39
|
+
pendingList.length = 0;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
for (const rawLine of lines) {
|
|
43
|
+
const line = rawLine.replace(/\s+$/g, "");
|
|
44
|
+
if (!line.trim()) {
|
|
45
|
+
flushPendingList();
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
const listItemMatch = /^\s*-\s+(.*)$/.exec(line);
|
|
49
|
+
if (listItemMatch && pendingListKey) {
|
|
50
|
+
pendingList.push(stripQuotes(listItemMatch[1]));
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
flushPendingList();
|
|
54
|
+
const kvMatch = /^([A-Za-z0-9_-]+)\s*:\s*(.*)$/.exec(line);
|
|
55
|
+
if (!kvMatch) continue;
|
|
56
|
+
const key = kvMatch[1];
|
|
57
|
+
const value = kvMatch[2];
|
|
58
|
+
if (value === "") {
|
|
59
|
+
pendingListKey = key;
|
|
60
|
+
pendingList.length = 0;
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (key === "tags") {
|
|
64
|
+
const inline = parseInlineList(value);
|
|
65
|
+
if (inline !== null) {
|
|
66
|
+
result.tags = inline;
|
|
67
|
+
} else {
|
|
68
|
+
result.tags = stripQuotes(value).split(",").map((s) => s.trim()).filter(Boolean);
|
|
69
|
+
}
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
const cleaned = stripQuotes(value);
|
|
73
|
+
if (key === "name") result.name = cleaned;
|
|
74
|
+
else if (key === "description") result.description = cleaned;
|
|
75
|
+
else result.extra[key] = cleaned;
|
|
76
|
+
}
|
|
77
|
+
flushPendingList();
|
|
78
|
+
if (result.extra && Object.keys(result.extra).length === 0) {
|
|
79
|
+
delete result.extra;
|
|
80
|
+
}
|
|
81
|
+
return result;
|
|
82
|
+
}
|
|
83
|
+
function buildSkillId(source, dirName) {
|
|
84
|
+
const safe = dirName.trim().replace(/[\\/]+/g, "-").replace(/\s+/g, "-");
|
|
85
|
+
return `${source}:${safe}`;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// src/skill/client.ts
|
|
89
|
+
var currentTransport = null;
|
|
90
|
+
function setSkillTransport(transport) {
|
|
91
|
+
currentTransport = transport;
|
|
92
|
+
}
|
|
93
|
+
function getSkillTransport() {
|
|
94
|
+
if (currentTransport) {
|
|
95
|
+
return currentTransport;
|
|
96
|
+
}
|
|
97
|
+
const auto = tryAutoBindElectronTransport();
|
|
98
|
+
if (auto) {
|
|
99
|
+
currentTransport = auto;
|
|
100
|
+
return auto;
|
|
101
|
+
}
|
|
102
|
+
throw new Error(
|
|
103
|
+
"[skill] No SkillTransport configured. Call setSkillTransport() or useElectronSkillTransport() first."
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
async function listSkills() {
|
|
107
|
+
return getSkillTransport().list();
|
|
108
|
+
}
|
|
109
|
+
async function getSkill(id) {
|
|
110
|
+
return getSkillTransport().get(id);
|
|
111
|
+
}
|
|
112
|
+
async function rescanSkills() {
|
|
113
|
+
return getSkillTransport().rescan();
|
|
114
|
+
}
|
|
115
|
+
function onSkillsChanged(listener) {
|
|
116
|
+
const transport = getSkillTransport();
|
|
117
|
+
if (!transport.onChanged) {
|
|
118
|
+
return () => {
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
return transport.onChanged(listener);
|
|
122
|
+
}
|
|
123
|
+
async function setSkillEnabled(id, value) {
|
|
124
|
+
const t = getSkillTransport();
|
|
125
|
+
if (!t.setEnabled) throw new Error("[skill] transport.setEnabled not supported");
|
|
126
|
+
return t.setEnabled(id, value);
|
|
127
|
+
}
|
|
128
|
+
async function setSkillScope(id, scope) {
|
|
129
|
+
const t = getSkillTransport();
|
|
130
|
+
if (!t.setScope) throw new Error("[skill] transport.setScope not supported");
|
|
131
|
+
return t.setScope(id, scope);
|
|
132
|
+
}
|
|
133
|
+
async function uninstallSkill(id) {
|
|
134
|
+
const t = getSkillTransport();
|
|
135
|
+
if (!t.uninstall) throw new Error("[skill] transport.uninstall not supported");
|
|
136
|
+
return t.uninstall(id);
|
|
137
|
+
}
|
|
138
|
+
async function listSkillProjects() {
|
|
139
|
+
const t = getSkillTransport();
|
|
140
|
+
if (!t.listProjects) throw new Error("[skill] transport.listProjects not supported");
|
|
141
|
+
return t.listProjects();
|
|
142
|
+
}
|
|
143
|
+
function readElectronSkillBridge() {
|
|
144
|
+
const globalAny = globalThis;
|
|
145
|
+
return globalAny.electronAPI?.engine?.skill ?? null;
|
|
146
|
+
}
|
|
147
|
+
function tryAutoBindElectronTransport() {
|
|
148
|
+
const bridge = readElectronSkillBridge();
|
|
149
|
+
if (!bridge) return null;
|
|
150
|
+
return {
|
|
151
|
+
list: () => bridge.list(),
|
|
152
|
+
get: (id) => bridge.get(id),
|
|
153
|
+
rescan: () => bridge.rescan(),
|
|
154
|
+
onChanged: bridge.onChanged ? (cb) => bridge.onChanged(cb) : void 0,
|
|
155
|
+
setEnabled: bridge.setEnabled ? (id, value) => bridge.setEnabled(id, value) : void 0,
|
|
156
|
+
setScope: bridge.setScope ? (id, scope) => bridge.setScope(id, scope) : void 0,
|
|
157
|
+
uninstall: bridge.uninstall ? (id) => bridge.uninstall(id) : void 0,
|
|
158
|
+
listProjects: bridge.listProjects ? () => bridge.listProjects() : void 0
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
function useElectronSkillTransport() {
|
|
162
|
+
const transport = tryAutoBindElectronTransport();
|
|
163
|
+
if (transport) {
|
|
164
|
+
setSkillTransport(transport);
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export { buildSkillId, getSkill, getSkillTransport, listSkillProjects, listSkills, onSkillsChanged, parseSkillFrontmatter, rescanSkills, setSkillEnabled, setSkillScope, setSkillTransport, uninstallSkill, useElectronSkillTransport };
|
|
@@ -175,7 +175,7 @@ var fileTools = [
|
|
|
175
175
|
}, rootedWriteEvidenceOutputSchema),
|
|
176
176
|
annotateTool({
|
|
177
177
|
name: "seastudio-file_list",
|
|
178
|
-
description: "\u5217\u51FA\u6307\u5B9A\u76EE\u5F55\
|
|
178
|
+
description: "\u5217\u51FA\u6307\u5B9A\u76EE\u5F55\u7684\u76F4\u63A5\u5B50\u9879\uFF08\u4E0D\u9012\u5F52\uFF0C\u7C7B\u4F3C ls\uFF09\u3002\u9002\u7528\u4E8E\u5728\u6267\u884C\u8BFB\u5199\u524D\u786E\u8BA4\u76EE\u5F55\u5185\u5BB9\u6216\u5B9A\u4F4D\u76EE\u6807\u8DEF\u5F84\u3002\u5982\u9700\u9012\u5F52\u904D\u5386\u5B50\u6811\u8BF7\u4F7F\u7528 seastudio-file_tree\u3002",
|
|
179
179
|
inputSchema: {
|
|
180
180
|
type: "object",
|
|
181
181
|
properties: {
|
|
@@ -189,6 +189,24 @@ var fileTools = [
|
|
|
189
189
|
requiresExecutionEvidence: false,
|
|
190
190
|
rawDomain: "filesystem"
|
|
191
191
|
}),
|
|
192
|
+
annotateTool({
|
|
193
|
+
name: "seastudio-file_tree",
|
|
194
|
+
description: "\u9012\u5F52\u5217\u51FA\u6307\u5B9A\u76EE\u5F55\u7684\u6574\u4E2A\u5B50\u6811\uFF08\u6241\u5E73 items \u5217\u8868\uFF0C\u6BCF\u9879\u542B\u76F8\u5BF9 rootId \u7684\u6839\u76F8\u5BF9\u8DEF\u5F84\uFF09\u3002\u4EC5\u5728\u786E\u5B9E\u9700\u8981\u5168\u6811\u89C6\u56FE\u65F6\u4F7F\u7528\uFF1B\u8FD4\u56DE\u7ED3\u679C\u53EF\u80FD\u5F88\u5927\uFF0C\u5EFA\u8BAE\u4F18\u5148\u4F7F\u7528 seastudio-file_list \u6309\u9700\u9010\u5C42\u63A2\u7D22\u3002",
|
|
195
|
+
inputSchema: {
|
|
196
|
+
type: "object",
|
|
197
|
+
properties: {
|
|
198
|
+
rootId: { type: "string", description: "\u76EE\u6807\u9879\u76EE\u6839\uFF1A'workspace' \u8868\u793A\u5F53\u524D\u6FC0\u6D3B\u9879\u76EE\uFF1B'proj-<projectId>' \u8868\u793A\u6309 id \u5BFB\u5740\u67D0\u4E2A\u9879\u76EE" },
|
|
199
|
+
path: { type: "string", description: "\u76EE\u5F55\u8DEF\u5F84\uFF08\u76F8\u5BF9\u4E8E rootId\uFF09" },
|
|
200
|
+
maxDepth: { type: "number", description: "\u6700\u5927\u9012\u5F52\u6DF1\u5EA6\uFF080 \u8868\u793A\u53EA\u5217\u5F53\u524D\u76EE\u5F55\uFF0C\u7B49\u4EF7\u4E8E file_list\uFF1B\u7701\u7565\u8868\u793A\u4E0D\u9650\u5236\uFF09" },
|
|
201
|
+
maxEntries: { type: "number", description: "\u6700\u591A\u8FD4\u56DE\u591A\u5C11\u4E2A\u6761\u76EE\uFF0C\u8D85\u51FA\u540E\u622A\u65AD\u5E76\u5728\u54CD\u5E94\u91CC truncated=true\uFF08\u9ED8\u8BA4 50000\uFF09" }
|
|
202
|
+
},
|
|
203
|
+
required: ["rootId", "path"]
|
|
204
|
+
}
|
|
205
|
+
}, {
|
|
206
|
+
operationKind: "read",
|
|
207
|
+
requiresExecutionEvidence: false,
|
|
208
|
+
rawDomain: "filesystem"
|
|
209
|
+
}),
|
|
192
210
|
annotateTool({
|
|
193
211
|
name: "seastudio-file_delete",
|
|
194
212
|
description: "\u5220\u9664\u6307\u5B9A\u8DEF\u5F84\u7684\u6587\u4EF6\u6216\u76EE\u5F55\u3002\u4EC5\u5728\u7528\u6237\u660E\u786E\u8981\u6C42\u79FB\u9664\u76EE\u6807\u65F6\u4F7F\u7528\uFF0C\u6210\u529F\u540E\u76EE\u6807\u4F1A\u4ECE\u9879\u76EE\u4E2D\u6D88\u5931\u3002",
|
|
@@ -843,6 +861,12 @@ var seastudio = {
|
|
|
843
861
|
rootId: options?.rootId ?? "workspace",
|
|
844
862
|
path
|
|
845
863
|
}),
|
|
864
|
+
tree: (path = "", options) => callTool("seastudio-file_tree", {
|
|
865
|
+
rootId: options?.rootId ?? "workspace",
|
|
866
|
+
path,
|
|
867
|
+
...typeof options?.maxDepth === "number" ? { maxDepth: options.maxDepth } : {},
|
|
868
|
+
...typeof options?.maxEntries === "number" ? { maxEntries: options.maxEntries } : {}
|
|
869
|
+
}),
|
|
846
870
|
delete: (path, options) => callTool("seastudio-file_delete", { rootId: options?.rootId ?? "workspace", path }),
|
|
847
871
|
mkdir: (path, options) => callTool("seastudio-file_mkdir", { rootId: options?.rootId ?? "workspace", path }),
|
|
848
872
|
exists: (path, options) => callTool("seastudio-file_exists", { rootId: options?.rootId ?? "workspace", path }),
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// src/skill/registry.ts
|
|
2
|
+
var currentTransport = null;
|
|
3
|
+
function setSkillRegistryTransport(transport) {
|
|
4
|
+
currentTransport = transport;
|
|
5
|
+
}
|
|
6
|
+
function getSkillRegistryTransport() {
|
|
7
|
+
if (currentTransport) return currentTransport;
|
|
8
|
+
const auto = tryAutoBindElectronTransport();
|
|
9
|
+
if (auto) {
|
|
10
|
+
currentTransport = auto;
|
|
11
|
+
return auto;
|
|
12
|
+
}
|
|
13
|
+
throw new Error(
|
|
14
|
+
"[skill/registry] No SkillRegistryTransport configured. Call setSkillRegistryTransport() or useElectronSkillRegistryTransport() first."
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
async function listMarketSkills() {
|
|
18
|
+
const payload = await getSkillRegistryTransport().list();
|
|
19
|
+
return Array.isArray(payload.skills) ? payload.skills : [];
|
|
20
|
+
}
|
|
21
|
+
async function getMarketSkill(id) {
|
|
22
|
+
return getSkillRegistryTransport().detail(id);
|
|
23
|
+
}
|
|
24
|
+
async function selectPublishSkillFile() {
|
|
25
|
+
const t = getSkillRegistryTransport();
|
|
26
|
+
if (!t.selectPublishFile) throw new Error("[skill/registry] transport.selectPublishFile not supported");
|
|
27
|
+
return t.selectPublishFile();
|
|
28
|
+
}
|
|
29
|
+
async function publishSkill(archivePath, publishPassword) {
|
|
30
|
+
const t = getSkillRegistryTransport();
|
|
31
|
+
if (!t.publishFile) throw new Error("[skill/registry] transport.publishFile not supported");
|
|
32
|
+
return t.publishFile(archivePath, publishPassword);
|
|
33
|
+
}
|
|
34
|
+
function readElectronSkillRegistryBridge() {
|
|
35
|
+
const globalAny = globalThis;
|
|
36
|
+
return globalAny.electronAPI?.engine?.skillRegistry ?? null;
|
|
37
|
+
}
|
|
38
|
+
function tryAutoBindElectronTransport() {
|
|
39
|
+
const bridge = readElectronSkillRegistryBridge();
|
|
40
|
+
if (!bridge) return null;
|
|
41
|
+
return {
|
|
42
|
+
list: () => bridge.list(),
|
|
43
|
+
detail: (id) => bridge.detail(id),
|
|
44
|
+
selectPublishFile: bridge.selectPublishFile ? () => bridge.selectPublishFile() : void 0,
|
|
45
|
+
publishFile: bridge.publishFile ? (archivePath, password) => bridge.publishFile(archivePath, password) : void 0
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function useElectronSkillRegistryTransport() {
|
|
49
|
+
const transport = tryAutoBindElectronTransport();
|
|
50
|
+
if (transport) {
|
|
51
|
+
setSkillRegistryTransport(transport);
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export { getMarketSkill, getSkillRegistryTransport, listMarketSkills, publishSkill, selectPublishSkillFile, setSkillRegistryTransport, useElectronSkillRegistryTransport };
|