@uniqueli/openwork 0.3.0 → 0.4.1
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 +123 -1
- package/out/main/index.js +5222 -271
- package/out/preload/index.js +41 -0
- package/out/renderer/assets/{index-0WBq9FlY.css → index-BUG0lOAH.css} +55 -0
- package/out/renderer/assets/{index-ZbiHA5we.js → index-BwYKBEJR.js} +773 -42
- package/out/renderer/index.html +2 -2
- package/package.json +3 -1
|
@@ -12813,10 +12813,20 @@ const Pencil = createLucideIcon("Pencil", [
|
|
|
12813
12813
|
],
|
|
12814
12814
|
["path", { d: "m15 5 4 4", key: "1mk7zo" }]
|
|
12815
12815
|
]);
|
|
12816
|
+
const Plug = createLucideIcon("Plug", [
|
|
12817
|
+
["path", { d: "M12 22v-5", key: "1ega77" }],
|
|
12818
|
+
["path", { d: "M9 8V2", key: "14iosj" }],
|
|
12819
|
+
["path", { d: "M15 8V2", key: "18g5xt" }],
|
|
12820
|
+
["path", { d: "M18 8v5a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4V8Z", key: "osxo6l" }]
|
|
12821
|
+
]);
|
|
12816
12822
|
const Plus = createLucideIcon("Plus", [
|
|
12817
12823
|
["path", { d: "M5 12h14", key: "1ays0h" }],
|
|
12818
12824
|
["path", { d: "M12 5v14", key: "s699le" }]
|
|
12819
12825
|
]);
|
|
12826
|
+
const Power = createLucideIcon("Power", [
|
|
12827
|
+
["path", { d: "M12 2v10", key: "mnfbl" }],
|
|
12828
|
+
["path", { d: "M18.4 6.6a9 9 0 1 1-12.77.04", key: "obofu9" }]
|
|
12829
|
+
]);
|
|
12820
12830
|
const RotateCw = createLucideIcon("RotateCw", [
|
|
12821
12831
|
["path", { d: "M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8", key: "1p45f6" }],
|
|
12822
12832
|
["path", { d: "M21 3v5h-5", key: "1q7to0" }]
|
|
@@ -17995,6 +18005,13 @@ function convertToV1FromResponses(message) {
|
|
|
17995
18005
|
};
|
|
17996
18006
|
continue;
|
|
17997
18007
|
} else if (_isContentBlock(toolOutput, "image_generation_call")) {
|
|
18008
|
+
if (_isString(toolOutput.result)) yield {
|
|
18009
|
+
type: "image",
|
|
18010
|
+
mimeType: "image/png",
|
|
18011
|
+
data: toolOutput.result,
|
|
18012
|
+
id: _isString(toolOutput.id) ? toolOutput.id : void 0,
|
|
18013
|
+
metadata: { status: _isString(toolOutput.status) ? toolOutput.status : void 0 }
|
|
18014
|
+
};
|
|
17998
18015
|
yield {
|
|
17999
18016
|
type: "non_standard",
|
|
18000
18017
|
value: toolOutput
|
|
@@ -18238,8 +18255,8 @@ const DEFAULT_MERGE_IGNORE_KEYS = [
|
|
|
18238
18255
|
];
|
|
18239
18256
|
function _mergeDicts(left, right, options) {
|
|
18240
18257
|
const ignoreKeys = options?.ignoreKeys ?? DEFAULT_MERGE_IGNORE_KEYS;
|
|
18241
|
-
if (left
|
|
18242
|
-
if (left
|
|
18258
|
+
if (left == null && right == null) return void 0;
|
|
18259
|
+
if (left == null || right == null) return left ?? right;
|
|
18243
18260
|
const merged = { ...left };
|
|
18244
18261
|
for (const [key2, value] of Object.entries(right)) if (merged[key2] == null) merged[key2] = value;
|
|
18245
18262
|
else if (value == null) continue;
|
|
@@ -18264,8 +18281,8 @@ function _mergeDicts(left, right, options) {
|
|
|
18264
18281
|
return merged;
|
|
18265
18282
|
}
|
|
18266
18283
|
function _mergeLists(left, right, options) {
|
|
18267
|
-
if (left
|
|
18268
|
-
else if (left
|
|
18284
|
+
if (left == null && right == null) return void 0;
|
|
18285
|
+
else if (left == null || right == null) return left || right;
|
|
18269
18286
|
else {
|
|
18270
18287
|
const merged = [...left];
|
|
18271
18288
|
for (const item of right) if (typeof item === "object" && item !== null && "index" in item && typeof item.index === "number") {
|
|
@@ -18284,8 +18301,8 @@ function _mergeLists(left, right, options) {
|
|
|
18284
18301
|
}
|
|
18285
18302
|
}
|
|
18286
18303
|
function _mergeObj(left, right, options) {
|
|
18287
|
-
if (left
|
|
18288
|
-
if (left
|
|
18304
|
+
if (left == null && right == null) return void 0;
|
|
18305
|
+
if (left == null || right == null) return left ?? right;
|
|
18289
18306
|
else if (typeof left !== typeof right) throw new Error(`Cannot merge objects of different types.
|
|
18290
18307
|
Left ${typeof left}
|
|
18291
18308
|
Right ${typeof right}`);
|
|
@@ -30375,7 +30392,7 @@ var CallbackManager = class CallbackManager2 extends BaseCallbackManager {
|
|
|
30375
30392
|
callbackManager = callbackManager.copy(Array.isArray(localHandlers) ? localHandlers.map(ensureHandler) : localHandlers?.handlers, false);
|
|
30376
30393
|
}
|
|
30377
30394
|
const verboseEnabled = getEnvironmentVariable$2("LANGCHAIN_VERBOSE") === "true" || options?.verbose;
|
|
30378
|
-
const tracingV2Enabled = LangChainTracer.getTraceableRunTree()?.tracingEnabled
|
|
30395
|
+
const tracingV2Enabled = LangChainTracer.getTraceableRunTree()?.tracingEnabled ?? isTracingEnabled();
|
|
30379
30396
|
const tracingEnabled = tracingV2Enabled || (getEnvironmentVariable$2("LANGCHAIN_TRACING") ?? false);
|
|
30380
30397
|
if (verboseEnabled || tracingEnabled) {
|
|
30381
30398
|
if (!callbackManager) callbackManager = new CallbackManager2();
|
|
@@ -31950,7 +31967,9 @@ const defaultFailedAttemptHandler = (error) => {
|
|
|
31950
31967
|
if (typeof error !== "object" || error === null) return;
|
|
31951
31968
|
if ("message" in error && typeof error.message === "string" && (error.message.startsWith("Cancel") || error.message.startsWith("AbortError")) || "name" in error && typeof error.name === "string" && error.name === "AbortError") throw error;
|
|
31952
31969
|
if ("code" in error && typeof error.code === "string" && error.code === "ECONNABORTED") throw error;
|
|
31953
|
-
const
|
|
31970
|
+
const responseStatus = "response" in error && typeof error.response === "object" && error.response !== null && "status" in error.response && typeof error.response.status === "number" ? error.response.status : void 0;
|
|
31971
|
+
const directStatus = "status" in error && typeof error.status === "number" ? error.status : void 0;
|
|
31972
|
+
const status = responseStatus ?? directStatus;
|
|
31954
31973
|
if (status && STATUS_NO_RETRY$1.includes(+status)) throw error;
|
|
31955
31974
|
const code2 = "error" in error && typeof error.error === "object" && error.error !== null && "code" in error.error && typeof error.error.code === "string" ? error.error.code : void 0;
|
|
31956
31975
|
if (code2 === "insufficient_quota") {
|
|
@@ -41351,14 +41370,15 @@ var StreamManager = class {
|
|
|
41351
41370
|
};
|
|
41352
41371
|
getMutateFn = (kind, historyValues) => {
|
|
41353
41372
|
return (update) => {
|
|
41373
|
+
const stateValues = (this.state.values ?? [null, "stream"])[0];
|
|
41354
41374
|
const prev = {
|
|
41355
41375
|
...historyValues,
|
|
41356
|
-
...
|
|
41376
|
+
...stateValues ?? {}
|
|
41357
41377
|
};
|
|
41358
41378
|
const next = typeof update === "function" ? update(prev) : update;
|
|
41359
41379
|
this.setStreamValues({
|
|
41360
41380
|
...prev,
|
|
41361
|
-
...next
|
|
41381
|
+
...next ?? {}
|
|
41362
41382
|
}, kind);
|
|
41363
41383
|
};
|
|
41364
41384
|
};
|
|
@@ -41395,8 +41415,8 @@ var StreamManager = class {
|
|
|
41395
41415
|
if (this.matchEventType("checkpoints", event, data)) options.callbacks.onCheckpointEvent?.(data, { namespace });
|
|
41396
41416
|
if (this.matchEventType("tasks", event, data)) options.callbacks.onTaskEvent?.(data, { namespace });
|
|
41397
41417
|
if (this.matchEventType("debug", event, data)) options.callbacks.onDebugEvent?.(data, { namespace });
|
|
41398
|
-
if (event === "values") if ("__interrupt__" in data) this.setStreamValues((prev) => ({
|
|
41399
|
-
...prev,
|
|
41418
|
+
if (event === "values") if (data != null && typeof data === "object" && "__interrupt__" in data) this.setStreamValues((prev) => ({
|
|
41419
|
+
...prev ?? {},
|
|
41400
41420
|
...data
|
|
41401
41421
|
}));
|
|
41402
41422
|
else this.setStreamValues(data);
|
|
@@ -41410,7 +41430,7 @@ var StreamManager = class {
|
|
|
41410
41430
|
this.setStreamValues((streamValues) => {
|
|
41411
41431
|
const values$1 = {
|
|
41412
41432
|
...options.initialValues,
|
|
41413
|
-
...streamValues
|
|
41433
|
+
...streamValues ?? {}
|
|
41414
41434
|
};
|
|
41415
41435
|
let messages = options.getMessages(values$1).slice();
|
|
41416
41436
|
const { chunk, index: index2 } = this.messages.get(messageId, messages.length) ?? {};
|
|
@@ -42976,7 +42996,7 @@ var BaseClient = class {
|
|
|
42976
42996
|
const [url, init] = this.prepareFetchOptions(path2, options);
|
|
42977
42997
|
let finalInit = init;
|
|
42978
42998
|
if (this.onRequest) finalInit = await this.onRequest(url, init);
|
|
42979
|
-
const response = await this.asyncCaller.fetch(url, finalInit);
|
|
42999
|
+
const response = await this.asyncCaller.fetch(url.toString(), finalInit);
|
|
42980
43000
|
const body2 = (() => {
|
|
42981
43001
|
if (response.status === 202 || response.status === 204) return;
|
|
42982
43002
|
return response.json();
|
|
@@ -43006,7 +43026,7 @@ var BaseClient = class {
|
|
|
43006
43026
|
json: isReconnect ? void 0 : config2.json
|
|
43007
43027
|
});
|
|
43008
43028
|
if (this.onRequest != null) init = await this.onRequest(url, init);
|
|
43009
|
-
const response = await this.asyncCaller.fetch(url, init);
|
|
43029
|
+
const response = await this.asyncCaller.fetch(url.toString(), init);
|
|
43010
43030
|
if (!isReconnect && config2.onInitialResponse) await config2.onInitialResponse(response);
|
|
43011
43031
|
return {
|
|
43012
43032
|
response,
|
|
@@ -43973,7 +43993,7 @@ var UiClient = class UiClient2 extends BaseClient {
|
|
|
43973
43993
|
json: { name: agentName }
|
|
43974
43994
|
});
|
|
43975
43995
|
if (this.onRequest != null) init = await this.onRequest(url, init);
|
|
43976
|
-
return (await this.asyncCaller.fetch(url, init)).text();
|
|
43996
|
+
return (await this.asyncCaller.fetch(url.toString(), init)).text();
|
|
43977
43997
|
});
|
|
43978
43998
|
}
|
|
43979
43999
|
};
|
|
@@ -44038,6 +44058,13 @@ function unique(array) {
|
|
|
44038
44058
|
function findLast(array, predicate) {
|
|
44039
44059
|
for (let i2 = array.length - 1; i2 >= 0; i2 -= 1) if (predicate(array[i2])) return array[i2];
|
|
44040
44060
|
}
|
|
44061
|
+
async function* filterStream(stream, filter) {
|
|
44062
|
+
while (true) {
|
|
44063
|
+
const { value, done } = await stream.next();
|
|
44064
|
+
if (done) return value;
|
|
44065
|
+
if (filter(value)) yield value;
|
|
44066
|
+
}
|
|
44067
|
+
}
|
|
44041
44068
|
function getBranchSequence(history) {
|
|
44042
44069
|
const nodeIds = /* @__PURE__ */ new Set();
|
|
44043
44070
|
const childrenMap = {};
|
|
@@ -44497,11 +44524,12 @@ function useStreamLGP(options) {
|
|
|
44497
44524
|
};
|
|
44498
44525
|
await stream.start(async (signal) => {
|
|
44499
44526
|
threadIdStreamingRef.current = threadId;
|
|
44500
|
-
|
|
44527
|
+
const stream$1 = client2.runs.joinStream(threadId, runId, {
|
|
44501
44528
|
signal,
|
|
44502
44529
|
lastEventId,
|
|
44503
44530
|
streamMode: joinOptions?.streamMode
|
|
44504
44531
|
});
|
|
44532
|
+
return joinOptions?.filter != null ? filterStream(stream$1, joinOptions.filter) : stream$1;
|
|
44505
44533
|
}, {
|
|
44506
44534
|
getMessages,
|
|
44507
44535
|
setMessages,
|
|
@@ -77075,6 +77103,639 @@ function SkillsPanel(_props) {
|
|
|
77075
77103
|
)
|
|
77076
77104
|
] });
|
|
77077
77105
|
}
|
|
77106
|
+
const TRANSPORT_TYPES = [
|
|
77107
|
+
{ value: "stdio", label: "STDIO", description: "标准输入/输出 (本地进程)" },
|
|
77108
|
+
{ value: "sse", label: "SSE", description: "服务器发送事件 (HTTP端点)" }
|
|
77109
|
+
];
|
|
77110
|
+
const CATEGORIES = [
|
|
77111
|
+
{ value: "filesystem", label: "文件系统", description: "文件操作工具" },
|
|
77112
|
+
{ value: "database", label: "数据库", description: "数据库访问工具" },
|
|
77113
|
+
{ value: "api", label: "API", description: "外部API集成" },
|
|
77114
|
+
{ value: "development", label: "开发", description: "开发工具" },
|
|
77115
|
+
{ value: "productivity", label: "生产力", description: "生产力工具" },
|
|
77116
|
+
{ value: "custom", label: "自定义", description: "其他工具" }
|
|
77117
|
+
];
|
|
77118
|
+
function CreateMCPServerDialog({ open, onClose, onCreated }) {
|
|
77119
|
+
const [formData, setFormData] = reactExports.useState({
|
|
77120
|
+
id: "",
|
|
77121
|
+
name: "",
|
|
77122
|
+
type: "stdio",
|
|
77123
|
+
command: "",
|
|
77124
|
+
args: "",
|
|
77125
|
+
url: "",
|
|
77126
|
+
description: "",
|
|
77127
|
+
category: "custom",
|
|
77128
|
+
enabled: true,
|
|
77129
|
+
env: {}
|
|
77130
|
+
});
|
|
77131
|
+
const [envVars, setEnvVars] = reactExports.useState([{ key: "", value: "" }]);
|
|
77132
|
+
const [errors, setErrors] = reactExports.useState({});
|
|
77133
|
+
const [testing, setTesting] = reactExports.useState(false);
|
|
77134
|
+
const [testResult, setTestResult] = reactExports.useState(null);
|
|
77135
|
+
const handleEnvVarChange = (index2, field, value) => {
|
|
77136
|
+
const newEnvVars = [...envVars];
|
|
77137
|
+
newEnvVars[index2][field] = value;
|
|
77138
|
+
setEnvVars(newEnvVars);
|
|
77139
|
+
const env2 = {};
|
|
77140
|
+
newEnvVars.forEach((envVar) => {
|
|
77141
|
+
if (envVar.key.trim()) {
|
|
77142
|
+
env2[envVar.key.trim()] = envVar.value;
|
|
77143
|
+
}
|
|
77144
|
+
});
|
|
77145
|
+
setFormData({ ...formData, env: env2 });
|
|
77146
|
+
};
|
|
77147
|
+
const addEnvVar = () => {
|
|
77148
|
+
setEnvVars([...envVars, { key: "", value: "" }]);
|
|
77149
|
+
};
|
|
77150
|
+
const removeEnvVar = (index2) => {
|
|
77151
|
+
const newEnvVars = envVars.filter((_2, i2) => i2 !== index2);
|
|
77152
|
+
setEnvVars(newEnvVars);
|
|
77153
|
+
const env2 = {};
|
|
77154
|
+
newEnvVars.forEach((envVar) => {
|
|
77155
|
+
if (envVar.key.trim()) {
|
|
77156
|
+
env2[envVar.key.trim()] = envVar.value;
|
|
77157
|
+
}
|
|
77158
|
+
});
|
|
77159
|
+
setFormData({ ...formData, env: env2 });
|
|
77160
|
+
};
|
|
77161
|
+
if (!open) return null;
|
|
77162
|
+
const validateForm = () => {
|
|
77163
|
+
const newErrors = {};
|
|
77164
|
+
if (!formData.id.trim()) {
|
|
77165
|
+
newErrors.id = "ID不能为空";
|
|
77166
|
+
} else if (!/^[a-z0-9-]+$/.test(formData.id)) {
|
|
77167
|
+
newErrors.id = "ID只能包含小写字母、数字和连字符";
|
|
77168
|
+
}
|
|
77169
|
+
if (!formData.name.trim()) {
|
|
77170
|
+
newErrors.name = "名称不能为空";
|
|
77171
|
+
}
|
|
77172
|
+
if (formData.type === "stdio" && !formData.command.trim()) {
|
|
77173
|
+
newErrors.command = "STDIO类型需要命令";
|
|
77174
|
+
}
|
|
77175
|
+
if (formData.type === "sse") {
|
|
77176
|
+
try {
|
|
77177
|
+
new URL(formData.url);
|
|
77178
|
+
} catch {
|
|
77179
|
+
newErrors.url = "请输入有效的URL";
|
|
77180
|
+
}
|
|
77181
|
+
}
|
|
77182
|
+
setErrors(newErrors);
|
|
77183
|
+
return Object.keys(newErrors).length === 0;
|
|
77184
|
+
};
|
|
77185
|
+
const handleSubmit = async (e) => {
|
|
77186
|
+
e.preventDefault();
|
|
77187
|
+
if (!validateForm()) return;
|
|
77188
|
+
try {
|
|
77189
|
+
const argsArray = formData.args.split(" ").map((arg) => arg.trim()).filter(Boolean);
|
|
77190
|
+
const result = await window.api.mcp.create({
|
|
77191
|
+
id: formData.id.trim(),
|
|
77192
|
+
name: formData.name.trim(),
|
|
77193
|
+
type: formData.type,
|
|
77194
|
+
command: formData.type === "stdio" ? formData.command.trim() : void 0,
|
|
77195
|
+
args: formData.type === "stdio" && argsArray.length > 0 ? argsArray : void 0,
|
|
77196
|
+
url: formData.type === "sse" ? formData.url.trim() : void 0,
|
|
77197
|
+
description: formData.description.trim() || void 0,
|
|
77198
|
+
category: formData.category,
|
|
77199
|
+
enabled: formData.enabled,
|
|
77200
|
+
env: Object.keys(formData.env).length > 0 ? formData.env : void 0
|
|
77201
|
+
});
|
|
77202
|
+
if (result.success) {
|
|
77203
|
+
onCreated();
|
|
77204
|
+
onClose();
|
|
77205
|
+
} else {
|
|
77206
|
+
setErrors({ id: result.error || "创建失败" });
|
|
77207
|
+
}
|
|
77208
|
+
} catch (error) {
|
|
77209
|
+
console.error("[CreateMCPServerDialog] Create error:", error);
|
|
77210
|
+
setErrors({ id: "创建失败,请重试" });
|
|
77211
|
+
}
|
|
77212
|
+
};
|
|
77213
|
+
const handleTest = async () => {
|
|
77214
|
+
if (formData.type === "stdio" && !formData.command.trim()) {
|
|
77215
|
+
setErrors({ command: "请先输入命令" });
|
|
77216
|
+
return;
|
|
77217
|
+
}
|
|
77218
|
+
if (formData.type === "sse" && !formData.url.trim()) {
|
|
77219
|
+
setErrors({ url: "请先输入URL" });
|
|
77220
|
+
return;
|
|
77221
|
+
}
|
|
77222
|
+
setTesting(true);
|
|
77223
|
+
setTestResult(null);
|
|
77224
|
+
try {
|
|
77225
|
+
const argsArray = formData.args.split(" ").map((arg) => arg.trim()).filter(Boolean);
|
|
77226
|
+
const result = await window.api.mcp.test({
|
|
77227
|
+
type: formData.type,
|
|
77228
|
+
command: formData.type === "stdio" ? formData.command.trim() : void 0,
|
|
77229
|
+
args: formData.type === "stdio" && argsArray.length > 0 ? argsArray : void 0,
|
|
77230
|
+
url: formData.type === "sse" ? formData.url.trim() : void 0,
|
|
77231
|
+
env: Object.keys(formData.env).length > 0 ? formData.env : void 0
|
|
77232
|
+
});
|
|
77233
|
+
setTestResult({
|
|
77234
|
+
success: result.success,
|
|
77235
|
+
message: result.success ? `连接成功!发现 ${result.tools || 0} 个工具` : result.error || "连接失败",
|
|
77236
|
+
tools: result.tools
|
|
77237
|
+
});
|
|
77238
|
+
} catch (error) {
|
|
77239
|
+
setTestResult({
|
|
77240
|
+
success: false,
|
|
77241
|
+
message: error instanceof Error ? error.message : "测试失败"
|
|
77242
|
+
});
|
|
77243
|
+
} finally {
|
|
77244
|
+
setTesting(false);
|
|
77245
|
+
}
|
|
77246
|
+
};
|
|
77247
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-full max-w-2xl bg-[#1A1A1D] rounded-lg shadow-xl border border-white/10 flex flex-col max-h-[90vh]", children: [
|
|
77248
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between px-6 py-4 border-b border-white/5 flex-shrink-0", children: [
|
|
77249
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "text-lg font-semibold text-white", children: "添加MCP服务器" }),
|
|
77250
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: onClose, className: "text-gray-400 hover:text-white transition-colors", children: /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
77251
|
+
"path",
|
|
77252
|
+
{
|
|
77253
|
+
strokeLinecap: "round",
|
|
77254
|
+
strokeLinejoin: "round",
|
|
77255
|
+
strokeWidth: 2,
|
|
77256
|
+
d: "M6 18L18 6M6 6l12 12"
|
|
77257
|
+
}
|
|
77258
|
+
) }) })
|
|
77259
|
+
] }),
|
|
77260
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("form", { onSubmit: handleSubmit, className: "p-6 space-y-4 overflow-y-auto flex-1", children: [
|
|
77261
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
77262
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "block text-sm font-medium text-gray-300 mb-2", children: [
|
|
77263
|
+
"传输类型 ",
|
|
77264
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-red-500", children: "*" })
|
|
77265
|
+
] }),
|
|
77266
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "grid grid-cols-2 gap-2", children: TRANSPORT_TYPES.map((type) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
77267
|
+
"button",
|
|
77268
|
+
{
|
|
77269
|
+
type: "button",
|
|
77270
|
+
onClick: () => setFormData({ ...formData, type: type.value }),
|
|
77271
|
+
className: `px-3 py-2 text-left text-sm rounded-md transition-colors ${formData.type === type.value ? "bg-blue-500/20 text-blue-400 border border-blue-500/50" : "bg-white/5 text-gray-400 border border-white/10 hover:bg-white/10"}`,
|
|
77272
|
+
children: [
|
|
77273
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-medium", children: type.label }),
|
|
77274
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs opacity-75", children: type.description })
|
|
77275
|
+
]
|
|
77276
|
+
},
|
|
77277
|
+
type.value
|
|
77278
|
+
)) })
|
|
77279
|
+
] }),
|
|
77280
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
77281
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "block text-sm font-medium text-gray-300 mb-1", children: [
|
|
77282
|
+
"服务器ID ",
|
|
77283
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-red-500", children: "*" })
|
|
77284
|
+
] }),
|
|
77285
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
77286
|
+
"input",
|
|
77287
|
+
{
|
|
77288
|
+
type: "text",
|
|
77289
|
+
value: formData.id,
|
|
77290
|
+
onChange: (e) => setFormData({ ...formData, id: e.target.value }),
|
|
77291
|
+
placeholder: "例如: filesystem-server",
|
|
77292
|
+
className: "w-full px-3 py-2 text-sm text-white placeholder-gray-500 bg-white/5 border border-white/10 rounded-md focus:outline-none focus:border-blue-500",
|
|
77293
|
+
required: true
|
|
77294
|
+
}
|
|
77295
|
+
),
|
|
77296
|
+
errors.id && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-status-critical mt-1", children: errors.id }),
|
|
77297
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-gray-500 mt-1", children: "唯一标识符,只能包含小写字母、数字和连字符" })
|
|
77298
|
+
] }),
|
|
77299
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
77300
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "block text-sm font-medium text-gray-300 mb-1", children: [
|
|
77301
|
+
"显示名称 ",
|
|
77302
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-red-500", children: "*" })
|
|
77303
|
+
] }),
|
|
77304
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
77305
|
+
"input",
|
|
77306
|
+
{
|
|
77307
|
+
type: "text",
|
|
77308
|
+
value: formData.name,
|
|
77309
|
+
onChange: (e) => setFormData({ ...formData, name: e.target.value }),
|
|
77310
|
+
placeholder: "例如: 文件系统服务器",
|
|
77311
|
+
className: "w-full px-3 py-2 text-sm text-white placeholder-gray-500 bg-white/5 border border-white/10 rounded-md focus:outline-none focus:border-blue-500",
|
|
77312
|
+
required: true
|
|
77313
|
+
}
|
|
77314
|
+
),
|
|
77315
|
+
errors.name && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-status-critical mt-1", children: errors.name })
|
|
77316
|
+
] }),
|
|
77317
|
+
formData.type === "stdio" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
77318
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "block text-sm font-medium text-gray-300 mb-1", children: [
|
|
77319
|
+
"命令 ",
|
|
77320
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-red-500", children: "*" })
|
|
77321
|
+
] }),
|
|
77322
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
77323
|
+
"input",
|
|
77324
|
+
{
|
|
77325
|
+
type: "text",
|
|
77326
|
+
value: formData.command,
|
|
77327
|
+
onChange: (e) => setFormData({ ...formData, command: e.target.value }),
|
|
77328
|
+
placeholder: "例如: npx",
|
|
77329
|
+
className: "w-full px-3 py-2 text-sm text-white placeholder-gray-500 bg-white/5 border border-white/10 rounded-md focus:outline-none focus:border-blue-500",
|
|
77330
|
+
required: formData.type === "stdio"
|
|
77331
|
+
}
|
|
77332
|
+
),
|
|
77333
|
+
errors.command && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-status-critical mt-1", children: errors.command })
|
|
77334
|
+
] }),
|
|
77335
|
+
formData.type === "stdio" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
77336
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "block text-sm font-medium text-gray-300 mb-1", children: "命令参数" }),
|
|
77337
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
77338
|
+
"input",
|
|
77339
|
+
{
|
|
77340
|
+
type: "text",
|
|
77341
|
+
value: formData.args,
|
|
77342
|
+
onChange: (e) => setFormData({ ...formData, args: e.target.value }),
|
|
77343
|
+
placeholder: "例如: @modelcontextprotocol/server-filesystem /path/to/dir",
|
|
77344
|
+
className: "w-full px-3 py-2 text-sm text-white placeholder-gray-500 bg-white/5 border border-white/10 rounded-md focus:outline-none focus:border-blue-500"
|
|
77345
|
+
}
|
|
77346
|
+
),
|
|
77347
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-gray-500 mt-1", children: "多个参数用空格分隔" })
|
|
77348
|
+
] }),
|
|
77349
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
77350
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "block text-sm font-medium text-gray-300 mb-2", children: "环境变量" }),
|
|
77351
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-2", children: envVars.map((envVar, index2) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [
|
|
77352
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
77353
|
+
"input",
|
|
77354
|
+
{
|
|
77355
|
+
type: "text",
|
|
77356
|
+
value: envVar.key,
|
|
77357
|
+
onChange: (e) => handleEnvVarChange(index2, "key", e.target.value),
|
|
77358
|
+
placeholder: "变量名 (如: YAPI_BASE_URL)",
|
|
77359
|
+
className: "flex-1 px-3 py-2 text-sm text-white placeholder-gray-500 bg-white/5 border border-white/10 rounded-md focus:outline-none focus:border-blue-500"
|
|
77360
|
+
}
|
|
77361
|
+
),
|
|
77362
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
77363
|
+
"input",
|
|
77364
|
+
{
|
|
77365
|
+
type: "text",
|
|
77366
|
+
value: envVar.value,
|
|
77367
|
+
onChange: (e) => handleEnvVarChange(index2, "value", e.target.value),
|
|
77368
|
+
placeholder: "值 (不要包含引号)",
|
|
77369
|
+
className: "flex-1 px-3 py-2 text-sm text-white placeholder-gray-500 bg-white/5 border border-white/10 rounded-md focus:outline-none focus:border-blue-500"
|
|
77370
|
+
}
|
|
77371
|
+
),
|
|
77372
|
+
envVars.length > 1 && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
77373
|
+
"button",
|
|
77374
|
+
{
|
|
77375
|
+
type: "button",
|
|
77376
|
+
onClick: () => removeEnvVar(index2),
|
|
77377
|
+
className: "px-2 py-1 text-status-critical hover:bg-status-critical/20 rounded-md transition-colors",
|
|
77378
|
+
title: "删除",
|
|
77379
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
|
|
77380
|
+
}
|
|
77381
|
+
)
|
|
77382
|
+
] }, index2)) }),
|
|
77383
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
77384
|
+
"button",
|
|
77385
|
+
{
|
|
77386
|
+
type: "button",
|
|
77387
|
+
onClick: addEnvVar,
|
|
77388
|
+
className: "mt-2 text-xs text-blue-400 hover:text-blue-300 transition-colors",
|
|
77389
|
+
children: "+ 添加环境变量"
|
|
77390
|
+
}
|
|
77391
|
+
),
|
|
77392
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-gray-500 mt-1", children: "可选,用于传递敏感信息或配置参数。直接输入值即可,不要包含引号或JSON格式" })
|
|
77393
|
+
] }),
|
|
77394
|
+
formData.type === "sse" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
77395
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "block text-sm font-medium text-gray-300 mb-1", children: [
|
|
77396
|
+
"服务器URL ",
|
|
77397
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-red-500", children: "*" })
|
|
77398
|
+
] }),
|
|
77399
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
77400
|
+
"input",
|
|
77401
|
+
{
|
|
77402
|
+
type: "text",
|
|
77403
|
+
value: formData.url,
|
|
77404
|
+
onChange: (e) => setFormData({ ...formData, url: e.target.value }),
|
|
77405
|
+
placeholder: "例如: http://localhost:3000/sse",
|
|
77406
|
+
className: "w-full px-3 py-2 text-sm text-white placeholder-gray-500 bg-white/5 border border-white/10 rounded-md focus:outline-none focus:border-blue-500",
|
|
77407
|
+
required: formData.type === "sse"
|
|
77408
|
+
}
|
|
77409
|
+
),
|
|
77410
|
+
errors.url && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-status-critical mt-1", children: errors.url })
|
|
77411
|
+
] }),
|
|
77412
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
77413
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "block text-sm font-medium text-gray-300 mb-1", children: "描述" }),
|
|
77414
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
77415
|
+
"input",
|
|
77416
|
+
{
|
|
77417
|
+
type: "text",
|
|
77418
|
+
value: formData.description,
|
|
77419
|
+
onChange: (e) => setFormData({ ...formData, description: e.target.value }),
|
|
77420
|
+
placeholder: "可选的服务器描述",
|
|
77421
|
+
className: "w-full px-3 py-2 text-sm text-white placeholder-gray-500 bg-white/5 border border-white/10 rounded-md focus:outline-none focus:border-blue-500"
|
|
77422
|
+
}
|
|
77423
|
+
)
|
|
77424
|
+
] }),
|
|
77425
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
77426
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "block text-sm font-medium text-gray-300 mb-2", children: "分类" }),
|
|
77427
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "grid grid-cols-3 gap-2", children: CATEGORIES.map((cat) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
77428
|
+
"button",
|
|
77429
|
+
{
|
|
77430
|
+
type: "button",
|
|
77431
|
+
onClick: () => setFormData({ ...formData, category: cat.value }),
|
|
77432
|
+
className: `px-3 py-2 text-left text-sm rounded-md transition-colors ${formData.category === cat.value ? "bg-blue-500/20 text-blue-400 border border-blue-500/50" : "bg-white/5 text-gray-400 border border-white/10 hover:bg-white/10"}`,
|
|
77433
|
+
children: [
|
|
77434
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-medium", children: cat.label }),
|
|
77435
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs opacity-75", children: cat.description })
|
|
77436
|
+
]
|
|
77437
|
+
},
|
|
77438
|
+
cat.value
|
|
77439
|
+
)) })
|
|
77440
|
+
] }),
|
|
77441
|
+
testResult && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
77442
|
+
"div",
|
|
77443
|
+
{
|
|
77444
|
+
className: `p-3 rounded-md text-sm ${testResult.success ? "bg-status-nominal/20 text-status-nominal border border-status-nominal/50" : "bg-status-critical/20 text-status-critical border border-status-critical/50"}`,
|
|
77445
|
+
children: testResult.message
|
|
77446
|
+
}
|
|
77447
|
+
)
|
|
77448
|
+
] }),
|
|
77449
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-end gap-3 px-6 py-4 border-t border-white/5 flex-shrink-0", children: [
|
|
77450
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
77451
|
+
Button,
|
|
77452
|
+
{
|
|
77453
|
+
type: "button",
|
|
77454
|
+
variant: "ghost",
|
|
77455
|
+
onClick: handleTest,
|
|
77456
|
+
disabled: testing,
|
|
77457
|
+
className: "text-xs",
|
|
77458
|
+
children: testing ? "测试中..." : "测试连接"
|
|
77459
|
+
}
|
|
77460
|
+
),
|
|
77461
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1" }),
|
|
77462
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Button, { type: "button", variant: "ghost", onClick: onClose, children: "取消" }),
|
|
77463
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Button, { type: "button", onClick: handleSubmit, children: "创建服务器" })
|
|
77464
|
+
] })
|
|
77465
|
+
] }) });
|
|
77466
|
+
}
|
|
77467
|
+
function MCPPanel() {
|
|
77468
|
+
const [servers, setServers] = reactExports.useState([]);
|
|
77469
|
+
const [loading, setLoading] = reactExports.useState(true);
|
|
77470
|
+
const [showCreateDialog, setShowCreateDialog] = reactExports.useState(false);
|
|
77471
|
+
reactExports.useEffect(() => {
|
|
77472
|
+
loadServers();
|
|
77473
|
+
}, []);
|
|
77474
|
+
reactExports.useEffect(() => {
|
|
77475
|
+
const interval = setInterval(async () => {
|
|
77476
|
+
const result = await window.api.mcp.getAllStates();
|
|
77477
|
+
if (result.success && result.states) {
|
|
77478
|
+
const stateMap = /* @__PURE__ */ new Map();
|
|
77479
|
+
result.states.forEach((state) => {
|
|
77480
|
+
stateMap.set(state.serverId, state);
|
|
77481
|
+
});
|
|
77482
|
+
setServers(
|
|
77483
|
+
(prev) => prev.map((server) => {
|
|
77484
|
+
const state = stateMap.get(server.id);
|
|
77485
|
+
return {
|
|
77486
|
+
...server,
|
|
77487
|
+
connectionStatus: state?.status,
|
|
77488
|
+
toolCount: state?.tools?.length || 0
|
|
77489
|
+
};
|
|
77490
|
+
})
|
|
77491
|
+
);
|
|
77492
|
+
}
|
|
77493
|
+
}, 2e3);
|
|
77494
|
+
return () => clearInterval(interval);
|
|
77495
|
+
}, []);
|
|
77496
|
+
async function loadServers() {
|
|
77497
|
+
setLoading(true);
|
|
77498
|
+
try {
|
|
77499
|
+
const result = await window.api.mcp.list();
|
|
77500
|
+
if (result.success && result.servers) {
|
|
77501
|
+
const statesResult = await window.api.mcp.getAllStates();
|
|
77502
|
+
const stateMap = /* @__PURE__ */ new Map();
|
|
77503
|
+
if (statesResult.success && statesResult.states) {
|
|
77504
|
+
statesResult.states.forEach((state) => {
|
|
77505
|
+
stateMap.set(state.serverId, state);
|
|
77506
|
+
});
|
|
77507
|
+
}
|
|
77508
|
+
setServers(
|
|
77509
|
+
result.servers.map((server) => ({
|
|
77510
|
+
...server,
|
|
77511
|
+
connectionStatus: stateMap.get(server.id)?.status,
|
|
77512
|
+
toolCount: stateMap.get(server.id)?.tools?.length || 0
|
|
77513
|
+
}))
|
|
77514
|
+
);
|
|
77515
|
+
}
|
|
77516
|
+
} catch (error) {
|
|
77517
|
+
console.error("[MCPPanel] Failed to load servers:", error);
|
|
77518
|
+
} finally {
|
|
77519
|
+
setLoading(false);
|
|
77520
|
+
}
|
|
77521
|
+
}
|
|
77522
|
+
async function handleToggleServer(serverId, currentEnabled) {
|
|
77523
|
+
console.log("[MCPPanel] Toggling server:", serverId, "from", currentEnabled, "to", !currentEnabled);
|
|
77524
|
+
try {
|
|
77525
|
+
const result = await window.api.mcp.toggle(serverId, !currentEnabled);
|
|
77526
|
+
console.log("[MCPPanel] Toggle result:", result);
|
|
77527
|
+
if (result.success) {
|
|
77528
|
+
setServers(
|
|
77529
|
+
(prev) => prev.map(
|
|
77530
|
+
(s2) => s2.id === serverId ? { ...s2, enabled: !currentEnabled } : s2
|
|
77531
|
+
)
|
|
77532
|
+
);
|
|
77533
|
+
await loadServers();
|
|
77534
|
+
} else {
|
|
77535
|
+
alert(`切换失败: ${result.error}`);
|
|
77536
|
+
}
|
|
77537
|
+
} catch (error) {
|
|
77538
|
+
console.error("[MCPPanel] Failed to toggle server:", error);
|
|
77539
|
+
alert(`切换失败: ${error instanceof Error ? error.message : "未知错误"}`);
|
|
77540
|
+
}
|
|
77541
|
+
}
|
|
77542
|
+
async function handleDeleteServer(serverId) {
|
|
77543
|
+
if (!confirm("确定要删除这个MCP服务器吗?")) return;
|
|
77544
|
+
console.log("[MCPPanel] Deleting server:", serverId);
|
|
77545
|
+
try {
|
|
77546
|
+
const result = await window.api.mcp.delete(serverId);
|
|
77547
|
+
console.log("[MCPPanel] Delete result:", result);
|
|
77548
|
+
if (result.success) {
|
|
77549
|
+
setServers((prev) => prev.filter((s2) => s2.id !== serverId));
|
|
77550
|
+
await loadServers();
|
|
77551
|
+
} else {
|
|
77552
|
+
alert(`删除失败: ${result.error}`);
|
|
77553
|
+
}
|
|
77554
|
+
} catch (error) {
|
|
77555
|
+
console.error("[MCPPanel] Failed to delete server:", error);
|
|
77556
|
+
alert(`删除失败: ${error instanceof Error ? error.message : "未知错误"}`);
|
|
77557
|
+
}
|
|
77558
|
+
}
|
|
77559
|
+
async function handleConnect(serverId) {
|
|
77560
|
+
console.log("[MCPPanel] Connecting to server:", serverId, "type:", typeof serverId);
|
|
77561
|
+
try {
|
|
77562
|
+
setServers(
|
|
77563
|
+
(prev) => prev.map(
|
|
77564
|
+
(s2) => s2.id === serverId ? { ...s2, connectionStatus: "connecting" } : s2
|
|
77565
|
+
)
|
|
77566
|
+
);
|
|
77567
|
+
console.log("[MCPPanel] Calling window.api.mcp.connect with:", serverId);
|
|
77568
|
+
const result = await window.api.mcp.connect(serverId);
|
|
77569
|
+
console.log("[MCPPanel] Connect result:", result);
|
|
77570
|
+
if (result.success) {
|
|
77571
|
+
await loadServers();
|
|
77572
|
+
} else {
|
|
77573
|
+
alert(`连接失败: ${result.error}`);
|
|
77574
|
+
await loadServers();
|
|
77575
|
+
}
|
|
77576
|
+
} catch (error) {
|
|
77577
|
+
console.error("[MCPPanel] Failed to connect:", error);
|
|
77578
|
+
alert(`连接失败: ${error instanceof Error ? error.message : "未知错误"}`);
|
|
77579
|
+
await loadServers();
|
|
77580
|
+
}
|
|
77581
|
+
}
|
|
77582
|
+
async function handleDisconnect(serverId) {
|
|
77583
|
+
console.log("[MCPPanel] Disconnecting from server:", serverId);
|
|
77584
|
+
try {
|
|
77585
|
+
const result = await window.api.mcp.disconnect(serverId);
|
|
77586
|
+
console.log("[MCPPanel] Disconnect result:", result);
|
|
77587
|
+
if (result.success) {
|
|
77588
|
+
setServers(
|
|
77589
|
+
(prev) => prev.map(
|
|
77590
|
+
(s2) => s2.id === serverId ? { ...s2, connectionStatus: "disconnected", toolCount: 0 } : s2
|
|
77591
|
+
)
|
|
77592
|
+
);
|
|
77593
|
+
await loadServers();
|
|
77594
|
+
} else {
|
|
77595
|
+
alert(`断开连接失败: ${result.error}`);
|
|
77596
|
+
}
|
|
77597
|
+
} catch (error) {
|
|
77598
|
+
console.error("[MCPPanel] Failed to disconnect:", error);
|
|
77599
|
+
alert(`断开连接失败: ${error instanceof Error ? error.message : "未知错误"}`);
|
|
77600
|
+
}
|
|
77601
|
+
}
|
|
77602
|
+
if (loading) {
|
|
77603
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center justify-center h-40", children: /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-5 animate-spin text-muted-foreground" }) });
|
|
77604
|
+
}
|
|
77605
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col h-full", children: [
|
|
77606
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between px-3 py-2 border-b border-border/50 bg-background/30", children: [
|
|
77607
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[10px] text-muted-foreground", children: [
|
|
77608
|
+
servers.filter((s2) => s2.enabled).length,
|
|
77609
|
+
" / ",
|
|
77610
|
+
servers.length,
|
|
77611
|
+
" 启用"
|
|
77612
|
+
] }),
|
|
77613
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
77614
|
+
Button,
|
|
77615
|
+
{
|
|
77616
|
+
variant: "ghost",
|
|
77617
|
+
size: "sm",
|
|
77618
|
+
onClick: () => setShowCreateDialog(true),
|
|
77619
|
+
className: "h-5 px-1.5 text-[10px]",
|
|
77620
|
+
children: [
|
|
77621
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { className: "size-3" }),
|
|
77622
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ml-1", children: "添加" })
|
|
77623
|
+
]
|
|
77624
|
+
}
|
|
77625
|
+
)
|
|
77626
|
+
] }),
|
|
77627
|
+
servers.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center justify-center text-center text-sm text-muted-foreground py-8 px-4 flex-1", children: [
|
|
77628
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Plug, { className: "size-8 mb-2 opacity-50" }),
|
|
77629
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "没有MCP服务器" }),
|
|
77630
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs mt-1", children: '点击"添加"配置服务器' })
|
|
77631
|
+
] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "py-2 overflow-auto flex-1", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-3 space-y-2", children: servers.map((server) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
77632
|
+
ServerCard,
|
|
77633
|
+
{
|
|
77634
|
+
server,
|
|
77635
|
+
onToggle: handleToggleServer,
|
|
77636
|
+
onDelete: handleDeleteServer,
|
|
77637
|
+
onConnect: handleConnect,
|
|
77638
|
+
onDisconnect: handleDisconnect
|
|
77639
|
+
},
|
|
77640
|
+
server.id
|
|
77641
|
+
)) }) }),
|
|
77642
|
+
showCreateDialog && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
77643
|
+
CreateMCPServerDialog,
|
|
77644
|
+
{
|
|
77645
|
+
open: showCreateDialog,
|
|
77646
|
+
onClose: () => setShowCreateDialog(false),
|
|
77647
|
+
onCreated: loadServers
|
|
77648
|
+
}
|
|
77649
|
+
)
|
|
77650
|
+
] });
|
|
77651
|
+
}
|
|
77652
|
+
function ServerCard({ server, onToggle, onDelete, onConnect, onDisconnect }) {
|
|
77653
|
+
const getStatusIcon = () => {
|
|
77654
|
+
if (!server.enabled) {
|
|
77655
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Circle, { className: "size-3 text-muted-foreground" });
|
|
77656
|
+
}
|
|
77657
|
+
switch (server.connectionStatus) {
|
|
77658
|
+
case "connected":
|
|
77659
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(CircleCheck, { className: "size-3 text-status-nominal" });
|
|
77660
|
+
case "connecting":
|
|
77661
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-3 animate-spin text-status-info" });
|
|
77662
|
+
case "error":
|
|
77663
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(CircleX, { className: "size-3 text-status-critical" });
|
|
77664
|
+
default:
|
|
77665
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Circle, { className: "size-3 text-muted-foreground" });
|
|
77666
|
+
}
|
|
77667
|
+
};
|
|
77668
|
+
const getStatusText = () => {
|
|
77669
|
+
if (!server.enabled) return "已禁用";
|
|
77670
|
+
switch (server.connectionStatus) {
|
|
77671
|
+
case "connected":
|
|
77672
|
+
return "已连接";
|
|
77673
|
+
case "connecting":
|
|
77674
|
+
return "连接中";
|
|
77675
|
+
case "error":
|
|
77676
|
+
return "错误";
|
|
77677
|
+
default:
|
|
77678
|
+
return "未连接";
|
|
77679
|
+
}
|
|
77680
|
+
};
|
|
77681
|
+
const getTransportTypeLabel = () => {
|
|
77682
|
+
return server.type === "stdio" ? "STDIO" : "SSE";
|
|
77683
|
+
};
|
|
77684
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-3 rounded-sm border border-border bg-background/50 hover:bg-background transition-colors", children: [
|
|
77685
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 mb-2", children: [
|
|
77686
|
+
getStatusIcon(),
|
|
77687
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1 text-sm font-medium truncate", children: server.name }),
|
|
77688
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Badge, { variant: "outline", className: "text-[9px] px-1 py-0 h-4", children: getTransportTypeLabel() })
|
|
77689
|
+
] }),
|
|
77690
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-xs text-muted-foreground mb-2 space-y-0.5", children: [
|
|
77691
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
77692
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "状态:" }),
|
|
77693
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: server.connectionStatus === "connected" ? "text-status-nominal" : "", children: getStatusText() })
|
|
77694
|
+
] }),
|
|
77695
|
+
server.connectionStatus === "connected" && server.toolCount !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
77696
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "工具:" }),
|
|
77697
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: server.toolCount })
|
|
77698
|
+
] }),
|
|
77699
|
+
server.description && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[10px] truncate", title: server.description, children: server.description })
|
|
77700
|
+
] }),
|
|
77701
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1 mt-2", children: [
|
|
77702
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
77703
|
+
Button,
|
|
77704
|
+
{
|
|
77705
|
+
variant: "ghost",
|
|
77706
|
+
size: "sm",
|
|
77707
|
+
onClick: () => onToggle(server.id, server.enabled),
|
|
77708
|
+
className: `h-6 px-2 text-[10px] flex-1 ${server.enabled ? "text-status-nominal hover:text-status-nominal" : ""}`,
|
|
77709
|
+
title: server.enabled ? "禁用" : "启用",
|
|
77710
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(Power, { className: "size-3" })
|
|
77711
|
+
}
|
|
77712
|
+
),
|
|
77713
|
+
server.enabled && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
77714
|
+
Button,
|
|
77715
|
+
{
|
|
77716
|
+
variant: "ghost",
|
|
77717
|
+
size: "sm",
|
|
77718
|
+
onClick: () => server.connectionStatus === "connected" ? onDisconnect(server.id) : onConnect(server.id),
|
|
77719
|
+
className: "h-6 px-2 text-[10px] flex-1",
|
|
77720
|
+
disabled: server.connectionStatus === "connecting",
|
|
77721
|
+
title: server.connectionStatus === "connected" ? "断开" : "连接",
|
|
77722
|
+
children: server.connectionStatus === "connecting" ? /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-3 animate-spin" }) : server.connectionStatus === "connected" ? /* @__PURE__ */ jsxRuntimeExports.jsx(CircleX, { className: "size-3" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Plug, { className: "size-3" })
|
|
77723
|
+
}
|
|
77724
|
+
),
|
|
77725
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
77726
|
+
Button,
|
|
77727
|
+
{
|
|
77728
|
+
variant: "ghost",
|
|
77729
|
+
size: "sm",
|
|
77730
|
+
onClick: () => onDelete(server.id),
|
|
77731
|
+
className: "h-6 px-2 text-[10px] text-status-critical hover:text-status-critical",
|
|
77732
|
+
title: "删除",
|
|
77733
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "size-3" })
|
|
77734
|
+
}
|
|
77735
|
+
)
|
|
77736
|
+
] })
|
|
77737
|
+
] });
|
|
77738
|
+
}
|
|
77078
77739
|
const HEADER_HEIGHT = 40;
|
|
77079
77740
|
const HANDLE_HEIGHT = 6;
|
|
77080
77741
|
const MIN_CONTENT_HEIGHT = 60;
|
|
@@ -77153,31 +77814,34 @@ function RightPanel() {
|
|
|
77153
77814
|
const [filesOpen, setFilesOpen] = reactExports.useState(true);
|
|
77154
77815
|
const [agentsOpen, setAgentsOpen] = reactExports.useState(true);
|
|
77155
77816
|
const [skillsOpen, setSkillsOpen] = reactExports.useState(false);
|
|
77817
|
+
const [mcpOpen, setMcpOpen] = reactExports.useState(false);
|
|
77156
77818
|
const [tasksHeight, setTasksHeight] = reactExports.useState(null);
|
|
77157
77819
|
const [filesHeight, setFilesHeight] = reactExports.useState(null);
|
|
77158
77820
|
const [agentsHeight, setAgentsHeight] = reactExports.useState(null);
|
|
77159
77821
|
const [skillsHeight, setSkillsHeight] = reactExports.useState(null);
|
|
77822
|
+
const [mcpHeight, setMcpHeight] = reactExports.useState(null);
|
|
77160
77823
|
const dragStartHeights = reactExports.useRef(null);
|
|
77161
77824
|
const getAvailableContentHeight = reactExports.useCallback(() => {
|
|
77162
77825
|
if (!containerRef.current) return 0;
|
|
77163
77826
|
const totalHeight = containerRef.current.clientHeight;
|
|
77164
|
-
let used = HEADER_HEIGHT *
|
|
77165
|
-
const openPanels = [tasksOpen, filesOpen, agentsOpen, skillsOpen].filter(Boolean).length;
|
|
77827
|
+
let used = HEADER_HEIGHT * 5;
|
|
77828
|
+
const openPanels = [tasksOpen, filesOpen, agentsOpen, skillsOpen, mcpOpen].filter(Boolean).length;
|
|
77166
77829
|
used += HANDLE_HEIGHT * (openPanels - 1);
|
|
77167
77830
|
return Math.max(0, totalHeight - used);
|
|
77168
|
-
}, [tasksOpen, filesOpen, agentsOpen, skillsOpen]);
|
|
77831
|
+
}, [tasksOpen, filesOpen, agentsOpen, skillsOpen, mcpOpen]);
|
|
77169
77832
|
const getContentHeights = reactExports.useCallback(() => {
|
|
77170
77833
|
const available = getAvailableContentHeight();
|
|
77171
|
-
const openCount = [tasksOpen, filesOpen, agentsOpen, skillsOpen].filter(Boolean).length;
|
|
77834
|
+
const openCount = [tasksOpen, filesOpen, agentsOpen, skillsOpen, mcpOpen].filter(Boolean).length;
|
|
77172
77835
|
if (openCount === 0) {
|
|
77173
|
-
return { tasks: 0, files: 0, agents: 0, skills: 0 };
|
|
77836
|
+
return { tasks: 0, files: 0, agents: 0, skills: 0, mcp: 0 };
|
|
77174
77837
|
}
|
|
77175
77838
|
const defaultHeight = available / openCount;
|
|
77176
77839
|
return {
|
|
77177
77840
|
tasks: tasksOpen ? tasksHeight ?? defaultHeight : 0,
|
|
77178
77841
|
files: filesOpen ? filesHeight ?? defaultHeight : 0,
|
|
77179
77842
|
agents: agentsOpen ? agentsHeight ?? defaultHeight : 0,
|
|
77180
|
-
skills: skillsOpen ? skillsHeight ?? defaultHeight : 0
|
|
77843
|
+
skills: skillsOpen ? skillsHeight ?? defaultHeight : 0,
|
|
77844
|
+
mcp: mcpOpen ? mcpHeight ?? defaultHeight : 0
|
|
77181
77845
|
};
|
|
77182
77846
|
}, [
|
|
77183
77847
|
getAvailableContentHeight,
|
|
@@ -77185,10 +77849,12 @@ function RightPanel() {
|
|
|
77185
77849
|
filesOpen,
|
|
77186
77850
|
agentsOpen,
|
|
77187
77851
|
skillsOpen,
|
|
77852
|
+
mcpOpen,
|
|
77188
77853
|
tasksHeight,
|
|
77189
77854
|
filesHeight,
|
|
77190
77855
|
agentsHeight,
|
|
77191
|
-
skillsHeight
|
|
77856
|
+
skillsHeight,
|
|
77857
|
+
mcpHeight
|
|
77192
77858
|
]);
|
|
77193
77859
|
const handleTasksResize = reactExports.useCallback(
|
|
77194
77860
|
(totalDelta) => {
|
|
@@ -77300,38 +77966,86 @@ function RightPanel() {
|
|
|
77300
77966
|
}
|
|
77301
77967
|
const start = dragStartHeights.current;
|
|
77302
77968
|
const available = getAvailableContentHeight();
|
|
77303
|
-
const tasksH = tasksOpen ? tasksHeight ?? available /
|
|
77304
|
-
const filesH = filesOpen ? filesHeight ?? available /
|
|
77969
|
+
const tasksH = tasksOpen ? tasksHeight ?? available / 5 : 0;
|
|
77970
|
+
const filesH = filesOpen ? filesHeight ?? available / 5 : 0;
|
|
77305
77971
|
const aboveHeight = tasksH + filesH;
|
|
77306
|
-
|
|
77972
|
+
let nextPanel = null;
|
|
77973
|
+
if (skillsOpen) nextPanel = "skills";
|
|
77974
|
+
else if (mcpOpen) nextPanel = "mcp";
|
|
77975
|
+
if (!nextPanel) return;
|
|
77976
|
+
const maxForAgentsAndNext = available - aboveHeight;
|
|
77307
77977
|
let newAgentsHeight = start.agents + totalDelta;
|
|
77308
|
-
let
|
|
77978
|
+
let newNextHeight = start[nextPanel] - totalDelta;
|
|
77309
77979
|
if (newAgentsHeight < MIN_CONTENT_HEIGHT) {
|
|
77310
77980
|
newAgentsHeight = MIN_CONTENT_HEIGHT;
|
|
77311
|
-
|
|
77981
|
+
newNextHeight = start[nextPanel] + (start.agents - MIN_CONTENT_HEIGHT);
|
|
77312
77982
|
}
|
|
77313
|
-
if (
|
|
77314
|
-
|
|
77315
|
-
newAgentsHeight = start.agents + (start
|
|
77983
|
+
if (newNextHeight < MIN_CONTENT_HEIGHT) {
|
|
77984
|
+
newNextHeight = MIN_CONTENT_HEIGHT;
|
|
77985
|
+
newAgentsHeight = start.agents + (start[nextPanel] - MIN_CONTENT_HEIGHT);
|
|
77316
77986
|
}
|
|
77317
|
-
if (newAgentsHeight +
|
|
77318
|
-
const excess = newAgentsHeight +
|
|
77987
|
+
if (newAgentsHeight + newNextHeight > maxForAgentsAndNext) {
|
|
77988
|
+
const excess = newAgentsHeight + newNextHeight - maxForAgentsAndNext;
|
|
77319
77989
|
if (totalDelta > 0) {
|
|
77320
|
-
|
|
77990
|
+
newNextHeight = Math.max(MIN_CONTENT_HEIGHT, newNextHeight - excess);
|
|
77321
77991
|
} else {
|
|
77322
77992
|
newAgentsHeight = Math.max(MIN_CONTENT_HEIGHT, newAgentsHeight - excess);
|
|
77323
77993
|
}
|
|
77324
77994
|
}
|
|
77325
77995
|
setAgentsHeight(newAgentsHeight);
|
|
77326
|
-
setSkillsHeight(
|
|
77996
|
+
if (nextPanel === "skills") setSkillsHeight(newNextHeight);
|
|
77997
|
+
else if (nextPanel === "mcp") setMcpHeight(newNextHeight);
|
|
77327
77998
|
if (newAgentsHeight < COLLAPSE_THRESHOLD) {
|
|
77328
77999
|
setAgentsOpen(false);
|
|
77329
78000
|
}
|
|
78001
|
+
if (newNextHeight < COLLAPSE_THRESHOLD) {
|
|
78002
|
+
if (nextPanel === "skills") setSkillsOpen(false);
|
|
78003
|
+
else if (nextPanel === "mcp") setMcpOpen(false);
|
|
78004
|
+
}
|
|
78005
|
+
},
|
|
78006
|
+
[getContentHeights, getAvailableContentHeight, tasksOpen, filesOpen, tasksHeight, filesHeight, skillsOpen, mcpOpen]
|
|
78007
|
+
);
|
|
78008
|
+
const handleSkillsResize = reactExports.useCallback(
|
|
78009
|
+
(totalDelta) => {
|
|
78010
|
+
if (!dragStartHeights.current) {
|
|
78011
|
+
const heights2 = getContentHeights();
|
|
78012
|
+
dragStartHeights.current = { ...heights2 };
|
|
78013
|
+
}
|
|
78014
|
+
const start = dragStartHeights.current;
|
|
78015
|
+
const available = getAvailableContentHeight();
|
|
78016
|
+
const tasksH = tasksOpen ? tasksHeight ?? available / 5 : 0;
|
|
78017
|
+
const filesH = filesOpen ? filesHeight ?? available / 5 : 0;
|
|
78018
|
+
const agentsH = agentsOpen ? agentsHeight ?? available / 5 : 0;
|
|
78019
|
+
const aboveHeight = tasksH + filesH + agentsH;
|
|
78020
|
+
const maxForSkillsAndMcp = available - aboveHeight;
|
|
78021
|
+
let newSkillsHeight = start.skills + totalDelta;
|
|
78022
|
+
let newMcpHeight = start.mcp - totalDelta;
|
|
78023
|
+
if (newSkillsHeight < MIN_CONTENT_HEIGHT) {
|
|
78024
|
+
newSkillsHeight = MIN_CONTENT_HEIGHT;
|
|
78025
|
+
newMcpHeight = start.mcp + (start.skills - MIN_CONTENT_HEIGHT);
|
|
78026
|
+
}
|
|
78027
|
+
if (newMcpHeight < MIN_CONTENT_HEIGHT) {
|
|
78028
|
+
newMcpHeight = MIN_CONTENT_HEIGHT;
|
|
78029
|
+
newSkillsHeight = start.skills + (start.mcp - MIN_CONTENT_HEIGHT);
|
|
78030
|
+
}
|
|
78031
|
+
if (newSkillsHeight + newMcpHeight > maxForSkillsAndMcp) {
|
|
78032
|
+
const excess = newSkillsHeight + newMcpHeight - maxForSkillsAndMcp;
|
|
78033
|
+
if (totalDelta > 0) {
|
|
78034
|
+
newMcpHeight = Math.max(MIN_CONTENT_HEIGHT, newMcpHeight - excess);
|
|
78035
|
+
} else {
|
|
78036
|
+
newSkillsHeight = Math.max(MIN_CONTENT_HEIGHT, newSkillsHeight - excess);
|
|
78037
|
+
}
|
|
78038
|
+
}
|
|
78039
|
+
setSkillsHeight(newSkillsHeight);
|
|
78040
|
+
setMcpHeight(newMcpHeight);
|
|
77330
78041
|
if (newSkillsHeight < COLLAPSE_THRESHOLD) {
|
|
77331
78042
|
setSkillsOpen(false);
|
|
77332
78043
|
}
|
|
78044
|
+
if (newMcpHeight < COLLAPSE_THRESHOLD) {
|
|
78045
|
+
setMcpOpen(false);
|
|
78046
|
+
}
|
|
77333
78047
|
},
|
|
77334
|
-
[getContentHeights, getAvailableContentHeight, tasksOpen, filesOpen, tasksHeight, filesHeight]
|
|
78048
|
+
[getContentHeights, getAvailableContentHeight, tasksOpen, filesOpen, agentsOpen, tasksHeight, filesHeight, agentsHeight]
|
|
77335
78049
|
);
|
|
77336
78050
|
reactExports.useEffect(() => {
|
|
77337
78051
|
const handleMouseUp = () => {
|
|
@@ -77345,8 +78059,9 @@ function RightPanel() {
|
|
|
77345
78059
|
setFilesHeight(null);
|
|
77346
78060
|
setAgentsHeight(null);
|
|
77347
78061
|
setSkillsHeight(null);
|
|
77348
|
-
|
|
77349
|
-
|
|
78062
|
+
setMcpHeight(null);
|
|
78063
|
+
}, [tasksOpen, filesOpen, agentsOpen, skillsOpen, mcpOpen]);
|
|
78064
|
+
const [heights, setHeights] = reactExports.useState({ tasks: 0, files: 0, agents: 0, skills: 0, mcp: 0 });
|
|
77350
78065
|
reactExports.useEffect(() => {
|
|
77351
78066
|
setHeights(getContentHeights());
|
|
77352
78067
|
}, [getContentHeights]);
|
|
@@ -77397,8 +78112,8 @@ function RightPanel() {
|
|
|
77397
78112
|
),
|
|
77398
78113
|
agentsOpen && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "overflow-auto", style: { height: heights.agents }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(AgentsContent, {}) })
|
|
77399
78114
|
] }),
|
|
77400
|
-
agentsOpen && skillsOpen && /* @__PURE__ */ jsxRuntimeExports.jsx(ResizeHandle$1, { onDrag: handleAgentsResize }),
|
|
77401
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col shrink-0", children: [
|
|
78115
|
+
agentsOpen && (skillsOpen || mcpOpen) && /* @__PURE__ */ jsxRuntimeExports.jsx(ResizeHandle$1, { onDrag: handleAgentsResize }),
|
|
78116
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col shrink-0 border-b border-border", children: [
|
|
77402
78117
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
77403
78118
|
SectionHeader,
|
|
77404
78119
|
{
|
|
@@ -77409,6 +78124,19 @@ function RightPanel() {
|
|
|
77409
78124
|
}
|
|
77410
78125
|
),
|
|
77411
78126
|
skillsOpen && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "overflow-auto", style: { height: heights.skills }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(SkillsContent, {}) })
|
|
78127
|
+
] }),
|
|
78128
|
+
skillsOpen && mcpOpen && /* @__PURE__ */ jsxRuntimeExports.jsx(ResizeHandle$1, { onDrag: handleSkillsResize }),
|
|
78129
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col shrink-0", children: [
|
|
78130
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
78131
|
+
SectionHeader,
|
|
78132
|
+
{
|
|
78133
|
+
title: "MCP",
|
|
78134
|
+
icon: Plug,
|
|
78135
|
+
isOpen: mcpOpen,
|
|
78136
|
+
onToggle: () => setMcpOpen((prev) => !prev)
|
|
78137
|
+
}
|
|
78138
|
+
),
|
|
78139
|
+
mcpOpen && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "overflow-auto", style: { height: heights.mcp }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(MCPContent, {}) })
|
|
77412
78140
|
] })
|
|
77413
78141
|
]
|
|
77414
78142
|
}
|
|
@@ -77833,6 +78561,9 @@ function AgentsContent() {
|
|
|
77833
78561
|
function SkillsContent() {
|
|
77834
78562
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(SkillsPanel, {});
|
|
77835
78563
|
}
|
|
78564
|
+
function MCPContent() {
|
|
78565
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(MCPPanel, {});
|
|
78566
|
+
}
|
|
77836
78567
|
function formatSize(bytes) {
|
|
77837
78568
|
if (bytes < 1024) return `${bytes}B`;
|
|
77838
78569
|
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
|
|
@@ -78231,7 +78962,7 @@ function App() {
|
|
|
78231
78962
|
},
|
|
78232
78963
|
children: [
|
|
78233
78964
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "app-badge-name", children: "OPENWORK" }),
|
|
78234
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "app-badge-version", children: "0.
|
|
78965
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "app-badge-version", children: "0.4.1" })
|
|
78235
78966
|
]
|
|
78236
78967
|
}
|
|
78237
78968
|
),
|