dsh-mcp 1.3.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.en.md +31 -0
- package/CHANGELOG.md +31 -0
- package/README.en.md +72 -7
- package/README.md +60 -6
- package/lib/client.js +899 -284
- package/lib/index.js +340 -12
- package/lib/oauth.js +170 -50
- package/package.json +1 -1
- package/src/client/GlobalEnvEditor.module.css +204 -0
- package/src/client/GlobalEnvEditor.tsx +254 -0
- package/src/client/McpSettingsSection.module.css +67 -0
- package/src/client/McpSettingsSection.tsx +82 -18
- package/src/client/ServerForm.module.css +0 -47
- package/src/client/ServerForm.tsx +1 -55
- package/src/client/ServersJsonEditor.module.css +90 -0
- package/src/client/ServersJsonEditor.tsx +226 -0
- package/src/client/index.ts +21 -3
- package/src/client/locales.ts +54 -4
- package/src/client/mcp-store.ts +4 -43
- package/src/client/remote-contribution.js +163 -2
- package/src/client/types.ts +2 -0
- package/static/snapshot.en.jpg +0 -0
- package/static/snapshot.en.webp +0 -0
- package/static/snapshot.jpg +0 -0
- package/static/snapshot.webp +0 -0
package/lib/client.js
CHANGED
|
@@ -14572,7 +14572,8 @@ var _deepseek_ai_dsh_mcp_manager_mcpManager_list_result$schema = external_export
|
|
|
14572
14572
|
"env": external_exports.array(external_exports.object({
|
|
14573
14573
|
"name": external_exports.string().readonly(),
|
|
14574
14574
|
"secret": external_exports.boolean().readonly(),
|
|
14575
|
-
"configured": external_exports.boolean().readonly()
|
|
14575
|
+
"configured": external_exports.boolean().readonly(),
|
|
14576
|
+
"value": external_exports.string().readonly().optional()
|
|
14576
14577
|
})).readonly(),
|
|
14577
14578
|
"toolCallTimeoutMs": external_exports.number().readonly(),
|
|
14578
14579
|
"failOnStartupError": external_exports.boolean().readonly(),
|
|
@@ -14604,7 +14605,7 @@ var _deepseek_ai_dsh_mcp_manager_mcpManager_test_parameter_0$schema = external_e
|
|
|
14604
14605
|
"name": external_exports.string().readonly(),
|
|
14605
14606
|
"secret": external_exports.boolean().readonly(),
|
|
14606
14607
|
"value": external_exports.string().readonly().optional()
|
|
14607
|
-
})).readonly()
|
|
14608
|
+
})).readonly().optional()
|
|
14608
14609
|
});
|
|
14609
14610
|
var _deepseek_ai_dsh_mcp_manager_mcpManager_test_result$schema = external_exports.object({
|
|
14610
14611
|
"ok": external_exports.literal(true).readonly(),
|
|
@@ -14641,7 +14642,7 @@ var _deepseek_ai_dsh_mcp_manager_mcpManager_upsert_parameter_0$schema = external
|
|
|
14641
14642
|
"name": external_exports.string().readonly(),
|
|
14642
14643
|
"secret": external_exports.boolean().readonly(),
|
|
14643
14644
|
"value": external_exports.string().readonly().optional()
|
|
14644
|
-
})).readonly()
|
|
14645
|
+
})).readonly().optional()
|
|
14645
14646
|
});
|
|
14646
14647
|
var _deepseek_ai_dsh_mcp_manager_mcpManager_upsert_result$schema = external_exports.union([external_exports.object({
|
|
14647
14648
|
"ok": external_exports.literal(true).readonly(),
|
|
@@ -14661,7 +14662,8 @@ var _deepseek_ai_dsh_mcp_manager_mcpManager_upsert_result$schema = external_expo
|
|
|
14661
14662
|
"env": external_exports.array(external_exports.object({
|
|
14662
14663
|
"name": external_exports.string().readonly(),
|
|
14663
14664
|
"secret": external_exports.boolean().readonly(),
|
|
14664
|
-
"configured": external_exports.boolean().readonly()
|
|
14665
|
+
"configured": external_exports.boolean().readonly(),
|
|
14666
|
+
"value": external_exports.string().readonly().optional()
|
|
14665
14667
|
})).readonly(),
|
|
14666
14668
|
"toolCallTimeoutMs": external_exports.number().readonly(),
|
|
14667
14669
|
"failOnStartupError": external_exports.boolean().readonly(),
|
|
@@ -14678,6 +14680,69 @@ var _deepseek_ai_dsh_mcp_manager_mcpManager_upsert_result$schema = external_expo
|
|
|
14678
14680
|
"message": external_exports.string().readonly()
|
|
14679
14681
|
}).readonly()
|
|
14680
14682
|
})]);
|
|
14683
|
+
var _deepseek_ai_dsh_mcp_manager_mcpManager_upsertJson_parameter_0$schema = external_exports.object({
|
|
14684
|
+
"servers": external_exports.array(external_exports.object({
|
|
14685
|
+
"server": external_exports.object({
|
|
14686
|
+
"serverName": external_exports.string().readonly(),
|
|
14687
|
+
"transport": external_exports.union([external_exports.literal("stdio"), external_exports.literal("streamable-http")]).readonly(),
|
|
14688
|
+
"enabled": external_exports.boolean().readonly().optional(),
|
|
14689
|
+
"command": external_exports.string().readonly().optional(),
|
|
14690
|
+
"args": external_exports.array(external_exports.string()).readonly().optional(),
|
|
14691
|
+
"cwd": external_exports.string().readonly().optional(),
|
|
14692
|
+
"url": external_exports.string().readonly().optional(),
|
|
14693
|
+
"headers": external_exports.union([external_exports.record(external_exports.string(), external_exports.string()), external_exports.array(external_exports.object({
|
|
14694
|
+
"name": external_exports.string().readonly(),
|
|
14695
|
+
"value": external_exports.string().readonly()
|
|
14696
|
+
})).readonly()]).readonly().optional(),
|
|
14697
|
+
"toolCallTimeoutMs": external_exports.number().readonly().optional(),
|
|
14698
|
+
"failOnStartupError": external_exports.boolean().readonly().optional()
|
|
14699
|
+
}).readonly(),
|
|
14700
|
+
"env": external_exports.array(external_exports.object({
|
|
14701
|
+
"name": external_exports.string().readonly(),
|
|
14702
|
+
"secret": external_exports.boolean().readonly().optional(),
|
|
14703
|
+
"value": external_exports.string().readonly().optional()
|
|
14704
|
+
})).readonly().optional()
|
|
14705
|
+
})).readonly()
|
|
14706
|
+
});
|
|
14707
|
+
var _deepseek_ai_dsh_mcp_manager_mcpManager_upsertJson_result$schema = external_exports.union([external_exports.object({
|
|
14708
|
+
"ok": external_exports.literal(true).readonly(),
|
|
14709
|
+
"added": external_exports.number().readonly(),
|
|
14710
|
+
"updated": external_exports.number().readonly(),
|
|
14711
|
+
"removed": external_exports.number().readonly(),
|
|
14712
|
+
"servers": external_exports.array(external_exports.object({
|
|
14713
|
+
"id": external_exports.intersection(external_exports.string(), external_exports.unknown()).readonly(),
|
|
14714
|
+
"serverName": external_exports.string().readonly(),
|
|
14715
|
+
"transport": external_exports.union([external_exports.literal("stdio"), external_exports.literal("streamable-http")]).readonly(),
|
|
14716
|
+
"enabled": external_exports.boolean().readonly(),
|
|
14717
|
+
"command": external_exports.string().readonly(),
|
|
14718
|
+
"args": external_exports.array(external_exports.string()).readonly(),
|
|
14719
|
+
"cwd": external_exports.string().readonly(),
|
|
14720
|
+
"url": external_exports.string().readonly(),
|
|
14721
|
+
"headers": external_exports.array(external_exports.object({
|
|
14722
|
+
"name": external_exports.string().readonly(),
|
|
14723
|
+
"value": external_exports.string().readonly()
|
|
14724
|
+
})).readonly(),
|
|
14725
|
+
"env": external_exports.array(external_exports.object({
|
|
14726
|
+
"name": external_exports.string().readonly(),
|
|
14727
|
+
"secret": external_exports.boolean().readonly(),
|
|
14728
|
+
"configured": external_exports.boolean().readonly(),
|
|
14729
|
+
"value": external_exports.string().readonly().optional()
|
|
14730
|
+
})).readonly(),
|
|
14731
|
+
"toolCallTimeoutMs": external_exports.number().readonly(),
|
|
14732
|
+
"failOnStartupError": external_exports.boolean().readonly(),
|
|
14733
|
+
"status": external_exports.object({
|
|
14734
|
+
"phase": external_exports.union([external_exports.literal("failed"), external_exports.literal("stopped"), external_exports.literal("mounting"), external_exports.literal("live")]).readonly(),
|
|
14735
|
+
"tools": external_exports.array(external_exports.string()).readonly(),
|
|
14736
|
+
"error": external_exports.string().readonly().optional()
|
|
14737
|
+
}).readonly()
|
|
14738
|
+
})).readonly()
|
|
14739
|
+
}), external_exports.object({
|
|
14740
|
+
"ok": external_exports.literal(false).readonly(),
|
|
14741
|
+
"error": external_exports.object({
|
|
14742
|
+
"code": external_exports.union([external_exports.literal("MCP_SERVER_NOT_FOUND"), external_exports.literal("MCP_SERVER_NAME_CONFLICT"), external_exports.literal("MCP_INVALID_SPEC"), external_exports.literal("MCP_MOUNT_FAILED")]).readonly(),
|
|
14743
|
+
"message": external_exports.string().readonly()
|
|
14744
|
+
}).readonly()
|
|
14745
|
+
})]);
|
|
14681
14746
|
var _deepseek_ai_dsh_mcp_manager_mcpManager_toolsList_result$schema = external_exports.object({
|
|
14682
14747
|
"ok": external_exports.literal(true).readonly(),
|
|
14683
14748
|
"tools": external_exports.array(external_exports.object({
|
|
@@ -14715,6 +14780,37 @@ var _deepseek_ai_dsh_mcp_manager_mcpManager_toolsMode_result$schema = external_e
|
|
|
14715
14780
|
"message": external_exports.string().readonly()
|
|
14716
14781
|
}).readonly()
|
|
14717
14782
|
})]);
|
|
14783
|
+
var _deepseek_ai_dsh_mcp_manager_mcpManager_envList_result$schema = external_exports.object({
|
|
14784
|
+
"ok": external_exports.literal(true).readonly(),
|
|
14785
|
+
"vars": external_exports.array(external_exports.object({
|
|
14786
|
+
"name": external_exports.string().readonly(),
|
|
14787
|
+
"secret": external_exports.boolean().readonly(),
|
|
14788
|
+
"configured": external_exports.boolean().readonly(),
|
|
14789
|
+
"value": external_exports.string().readonly().optional()
|
|
14790
|
+
})).readonly()
|
|
14791
|
+
});
|
|
14792
|
+
var _deepseek_ai_dsh_mcp_manager_mcpManager_envSet_parameter_0$schema = external_exports.object({
|
|
14793
|
+
"vars": external_exports.array(external_exports.object({
|
|
14794
|
+
"name": external_exports.string().readonly(),
|
|
14795
|
+
"secret": external_exports.boolean().readonly().optional(),
|
|
14796
|
+
"value": external_exports.string().readonly().optional()
|
|
14797
|
+
})).readonly()
|
|
14798
|
+
});
|
|
14799
|
+
var _deepseek_ai_dsh_mcp_manager_mcpManager_envSet_result$schema = external_exports.union([external_exports.object({
|
|
14800
|
+
"ok": external_exports.literal(true).readonly(),
|
|
14801
|
+
"vars": external_exports.array(external_exports.object({
|
|
14802
|
+
"name": external_exports.string().readonly(),
|
|
14803
|
+
"secret": external_exports.boolean().readonly(),
|
|
14804
|
+
"configured": external_exports.boolean().readonly(),
|
|
14805
|
+
"value": external_exports.string().readonly().optional()
|
|
14806
|
+
})).readonly()
|
|
14807
|
+
}), external_exports.object({
|
|
14808
|
+
"ok": external_exports.literal(false).readonly(),
|
|
14809
|
+
"error": external_exports.object({
|
|
14810
|
+
"code": external_exports.union([external_exports.literal("MCP_INVALID_SPEC")]).readonly(),
|
|
14811
|
+
"message": external_exports.string().readonly()
|
|
14812
|
+
}).readonly()
|
|
14813
|
+
})]);
|
|
14718
14814
|
var TYPERT_REMOTE = {
|
|
14719
14815
|
package: "@deepseek-ai/dsh-mcp-manager",
|
|
14720
14816
|
descriptors: [
|
|
@@ -14807,6 +14903,31 @@ var TYPERT_REMOTE = {
|
|
|
14807
14903
|
},
|
|
14808
14904
|
sourceLocation: { "file": "packages/mcp/mcp-manager/src/index.ts", "line": 329, "column": 9 }
|
|
14809
14905
|
},
|
|
14906
|
+
{
|
|
14907
|
+
id: "@deepseek-ai/dsh-mcp-manager#mcpManager/upsertJson",
|
|
14908
|
+
service: "mcpManager",
|
|
14909
|
+
namespace: "mcpManager",
|
|
14910
|
+
method: "upsertJson",
|
|
14911
|
+
invocation: { kind: "direct" },
|
|
14912
|
+
parameters: [
|
|
14913
|
+
{
|
|
14914
|
+
name: "request",
|
|
14915
|
+
wire: "request",
|
|
14916
|
+
source: "json",
|
|
14917
|
+
codec: {
|
|
14918
|
+
mode: "strict",
|
|
14919
|
+
typeSymbol: "@deepseek-ai/dsh-mcp-manager/types#McpManagerUpsertJsonRequest",
|
|
14920
|
+
schema: _deepseek_ai_dsh_mcp_manager_mcpManager_upsertJson_parameter_0$schema
|
|
14921
|
+
}
|
|
14922
|
+
}
|
|
14923
|
+
],
|
|
14924
|
+
result: {
|
|
14925
|
+
mode: "strict",
|
|
14926
|
+
typeSymbol: "@deepseek-ai/dsh-mcp-manager/types#McpManagerUpsertJsonResult",
|
|
14927
|
+
schema: _deepseek_ai_dsh_mcp_manager_mcpManager_upsertJson_result$schema
|
|
14928
|
+
},
|
|
14929
|
+
sourceLocation: { "file": "lib/index.js" }
|
|
14930
|
+
},
|
|
14810
14931
|
{
|
|
14811
14932
|
id: "@deepseek-ai/dsh-mcp-manager#mcpManager/toolsList",
|
|
14812
14933
|
service: "mcpManager",
|
|
@@ -14870,154 +14991,56 @@ var TYPERT_REMOTE = {
|
|
|
14870
14991
|
schema: _deepseek_ai_dsh_mcp_manager_mcpManager_toolsMode_result$schema
|
|
14871
14992
|
},
|
|
14872
14993
|
sourceLocation: { "file": "lib/index.js" }
|
|
14994
|
+
},
|
|
14995
|
+
{
|
|
14996
|
+
id: "@deepseek-ai/dsh-mcp-manager#mcpManager/envList",
|
|
14997
|
+
service: "mcpManager",
|
|
14998
|
+
namespace: "mcpManager",
|
|
14999
|
+
method: "envList",
|
|
15000
|
+
invocation: { kind: "direct" },
|
|
15001
|
+
parameters: [],
|
|
15002
|
+
result: {
|
|
15003
|
+
mode: "strict",
|
|
15004
|
+
typeSymbol: "@deepseek-ai/dsh-mcp-manager/types#McpManagerEnvListResult",
|
|
15005
|
+
schema: _deepseek_ai_dsh_mcp_manager_mcpManager_envList_result$schema
|
|
15006
|
+
},
|
|
15007
|
+
sourceLocation: { "file": "lib/index.js" }
|
|
15008
|
+
},
|
|
15009
|
+
{
|
|
15010
|
+
id: "@deepseek-ai/dsh-mcp-manager#mcpManager/envSet",
|
|
15011
|
+
service: "mcpManager",
|
|
15012
|
+
namespace: "mcpManager",
|
|
15013
|
+
method: "envSet",
|
|
15014
|
+
invocation: { kind: "direct" },
|
|
15015
|
+
parameters: [
|
|
15016
|
+
{
|
|
15017
|
+
name: "request",
|
|
15018
|
+
wire: "request",
|
|
15019
|
+
source: "json",
|
|
15020
|
+
codec: {
|
|
15021
|
+
mode: "strict",
|
|
15022
|
+
typeSymbol: "@deepseek-ai/dsh-mcp-manager/types#McpManagerEnvSetRequest",
|
|
15023
|
+
schema: _deepseek_ai_dsh_mcp_manager_mcpManager_envSet_parameter_0$schema
|
|
15024
|
+
}
|
|
15025
|
+
}
|
|
15026
|
+
],
|
|
15027
|
+
result: {
|
|
15028
|
+
mode: "strict",
|
|
15029
|
+
typeSymbol: "@deepseek-ai/dsh-mcp-manager/types#McpManagerEnvSetResult",
|
|
15030
|
+
schema: _deepseek_ai_dsh_mcp_manager_mcpManager_envSet_result$schema
|
|
15031
|
+
},
|
|
15032
|
+
sourceLocation: { "file": "lib/index.js" }
|
|
14873
15033
|
}
|
|
14874
15034
|
]
|
|
14875
15035
|
};
|
|
14876
15036
|
var remote_contribution_default = TYPERT_REMOTE;
|
|
14877
15037
|
|
|
14878
15038
|
// src/client/McpSettingsSection.tsx
|
|
14879
|
-
var
|
|
15039
|
+
var import_react4 = require("react");
|
|
14880
15040
|
|
|
14881
15041
|
// src/client/ServerForm.tsx
|
|
14882
15042
|
var import_react = require("react");
|
|
14883
15043
|
|
|
14884
|
-
// src/client/mcp-store.ts
|
|
14885
|
-
var import_client = require("@deepseek-ai/dsh-client-runtime/client");
|
|
14886
|
-
var DEFAULT_TOOL_CALL_TIMEOUT_MS = 6e4;
|
|
14887
|
-
var envRowSeq = 0;
|
|
14888
|
-
function nextEnvRowKey() {
|
|
14889
|
-
envRowSeq += 1;
|
|
14890
|
-
return `env-${envRowSeq}`;
|
|
14891
|
-
}
|
|
14892
|
-
function createEnvRowDraft() {
|
|
14893
|
-
return { key: nextEnvRowKey(), name: "", secret: false, value: "", configured: false };
|
|
14894
|
-
}
|
|
14895
|
-
function emptyDraft() {
|
|
14896
|
-
return {
|
|
14897
|
-
id: null,
|
|
14898
|
-
serverName: "",
|
|
14899
|
-
transport: "stdio",
|
|
14900
|
-
enabled: true,
|
|
14901
|
-
command: "",
|
|
14902
|
-
argsText: "",
|
|
14903
|
-
cwd: "",
|
|
14904
|
-
url: "",
|
|
14905
|
-
headersText: "",
|
|
14906
|
-
env: [],
|
|
14907
|
-
toolCallTimeoutMs: String(DEFAULT_TOOL_CALL_TIMEOUT_MS),
|
|
14908
|
-
// Reject the mount by default when the startup connection fails, so a
|
|
14909
|
-
// broken server never registers stale tools.
|
|
14910
|
-
failOnStartupError: true
|
|
14911
|
-
};
|
|
14912
|
-
}
|
|
14913
|
-
function draftFromServer(server) {
|
|
14914
|
-
return {
|
|
14915
|
-
id: server.id,
|
|
14916
|
-
serverName: server.serverName,
|
|
14917
|
-
transport: server.transport,
|
|
14918
|
-
enabled: server.enabled,
|
|
14919
|
-
command: server.command,
|
|
14920
|
-
argsText: server.args.join("\n"),
|
|
14921
|
-
cwd: server.cwd,
|
|
14922
|
-
url: server.url,
|
|
14923
|
-
headersText: server.headers.map((header) => `${header.name}: ${header.value}`).join("\n"),
|
|
14924
|
-
env: server.env.map((entry) => ({
|
|
14925
|
-
key: nextEnvRowKey(),
|
|
14926
|
-
name: entry.name,
|
|
14927
|
-
secret: entry.secret,
|
|
14928
|
-
value: "",
|
|
14929
|
-
configured: entry.configured
|
|
14930
|
-
})),
|
|
14931
|
-
toolCallTimeoutMs: String(server.toolCallTimeoutMs),
|
|
14932
|
-
failOnStartupError: server.failOnStartupError
|
|
14933
|
-
};
|
|
14934
|
-
}
|
|
14935
|
-
function parseLines(text) {
|
|
14936
|
-
return text.split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
|
|
14937
|
-
}
|
|
14938
|
-
function parseHeaders(text) {
|
|
14939
|
-
const headers = [];
|
|
14940
|
-
for (const line of parseLines(text)) {
|
|
14941
|
-
const separator = line.indexOf(":");
|
|
14942
|
-
if (separator <= 0) continue;
|
|
14943
|
-
const name = line.slice(0, separator).trim();
|
|
14944
|
-
const value = line.slice(separator + 1).trim();
|
|
14945
|
-
if (name.length > 0) headers.push({ name, value });
|
|
14946
|
-
}
|
|
14947
|
-
return headers;
|
|
14948
|
-
}
|
|
14949
|
-
function parseTimeout(text) {
|
|
14950
|
-
const value = Number(text);
|
|
14951
|
-
return Number.isInteger(value) && value > 0 ? value : DEFAULT_TOOL_CALL_TIMEOUT_MS;
|
|
14952
|
-
}
|
|
14953
|
-
function draftToSubmission(draft) {
|
|
14954
|
-
return {
|
|
14955
|
-
server: {
|
|
14956
|
-
serverName: draft.serverName.trim(),
|
|
14957
|
-
transport: draft.transport,
|
|
14958
|
-
enabled: draft.enabled,
|
|
14959
|
-
command: draft.command.trim(),
|
|
14960
|
-
args: parseLines(draft.argsText),
|
|
14961
|
-
cwd: draft.cwd.trim(),
|
|
14962
|
-
url: draft.url.trim(),
|
|
14963
|
-
headers: parseHeaders(draft.headersText),
|
|
14964
|
-
toolCallTimeoutMs: parseTimeout(draft.toolCallTimeoutMs),
|
|
14965
|
-
failOnStartupError: draft.failOnStartupError
|
|
14966
|
-
},
|
|
14967
|
-
env: draft.env.map((row) => ({
|
|
14968
|
-
name: row.name.trim(),
|
|
14969
|
-
secret: row.secret,
|
|
14970
|
-
...row.secret && row.value.trim().length === 0 ? {} : { value: row.value }
|
|
14971
|
-
}))
|
|
14972
|
-
};
|
|
14973
|
-
}
|
|
14974
|
-
function createMcpManagerStore() {
|
|
14975
|
-
return (0, import_client.defineStore)({
|
|
14976
|
-
init: () => ({
|
|
14977
|
-
loadState: "loading",
|
|
14978
|
-
servers: [],
|
|
14979
|
-
draft: null,
|
|
14980
|
-
busy: null,
|
|
14981
|
-
testRunning: false,
|
|
14982
|
-
test: null
|
|
14983
|
-
}),
|
|
14984
|
-
actions: {
|
|
14985
|
-
setLoadState: (d, state) => {
|
|
14986
|
-
d.loadState = state;
|
|
14987
|
-
},
|
|
14988
|
-
setServers: (d, servers) => {
|
|
14989
|
-
d.servers = servers;
|
|
14990
|
-
},
|
|
14991
|
-
beginCreate: (d) => {
|
|
14992
|
-
d.draft = emptyDraft();
|
|
14993
|
-
d.test = null;
|
|
14994
|
-
},
|
|
14995
|
-
beginEdit: (d, server) => {
|
|
14996
|
-
d.draft = draftFromServer(server);
|
|
14997
|
-
d.test = null;
|
|
14998
|
-
},
|
|
14999
|
-
cancelEdit: (d) => {
|
|
15000
|
-
d.draft = null;
|
|
15001
|
-
d.test = null;
|
|
15002
|
-
d.busy = null;
|
|
15003
|
-
},
|
|
15004
|
-
updateDraft: (d, patch) => {
|
|
15005
|
-
if (d.draft === null) return;
|
|
15006
|
-
d.draft = { ...d.draft, ...patch };
|
|
15007
|
-
},
|
|
15008
|
-
setBusy: (d, busy) => {
|
|
15009
|
-
d.busy = busy;
|
|
15010
|
-
},
|
|
15011
|
-
setTestRunning: (d, running) => {
|
|
15012
|
-
d.testRunning = running;
|
|
15013
|
-
},
|
|
15014
|
-
setTest: (d, test) => {
|
|
15015
|
-
d.test = test;
|
|
15016
|
-
}
|
|
15017
|
-
}
|
|
15018
|
-
});
|
|
15019
|
-
}
|
|
15020
|
-
|
|
15021
15044
|
// src/client/ServerForm.module.css
|
|
15022
15045
|
(function() {
|
|
15023
15046
|
if (typeof document !== "undefined") {
|
|
@@ -15026,12 +15049,12 @@ function createMcpManagerStore() {
|
|
|
15026
15049
|
const style = document.createElement("style");
|
|
15027
15050
|
style.setAttribute("data-plugin", "dsh-mcp");
|
|
15028
15051
|
style.setAttribute("data-file", "ServerForm.module.css");
|
|
15029
|
-
style.textContent = ".form {\n display: flex;\n flex-direction: column;\n gap: 14px;\n width: 100%;\n max-width: 760px;\n color: var(--dsw-alias-label-primary);\n}\n\n.titleRow {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n}\n\n.title {\n margin: 0;\n font-size: 15px;\n line-height: 22px;\n font-weight: 600;\n}\n\n.titleActions {\n display: flex;\n gap: 8px;\n}\n\nbutton {\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 6px;\n padding: 5px 12px;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 13px;\n line-height: 20px;\n cursor: pointer;\n}\n\nbutton:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\nbutton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\nbutton:disabled {\n cursor: not-allowed;\n opacity: 0.55;\n}\n\n.primary {\n border-color: var(--dsw-alias-button-primary-fill);\n background: var(--dsw-alias-button-primary-fill);\n color: var(--dsw-alias-label-primary-foreground);\n}\n\n.primary:hover {\n background: var(--dsw-alias-button-primary-hover);\n}\n\n.danger {\n color: var(--dsw-alias-state-error-primary);\n}\n\n.error {\n margin: 0;\n color: var(--dsw-alias-state-error-primary);\n font-size: 13px;\n line-height: 20px;\n}\n\n.field {\n display: flex;\n flex-direction: column;\n gap: 5px;\n font-size: 13px;\n line-height: 20px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.field input,\n.field select,\n.field textarea {\n width: 100%;\n box-sizing: border-box;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n padding: 6px 10px;\n outline: none;\n background: var(--dsw-alias-bg-layer-1);\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 13px;\n resize: vertical;\n}\n\n.field input::placeholder,\n.field textarea::placeholder {\n color: var(--dsw-alias-label-tertiary);\n}\n\n.field input:focus-visible,\n.field select:focus-visible,\n.field textarea:focus-visible {\n border-color: var(--dsw-alias-brand-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--dsw-alias-brand-primary) 18%, transparent);\n}\n\n.
|
|
15052
|
+
style.textContent = ".form {\n display: flex;\n flex-direction: column;\n gap: 14px;\n width: 100%;\n max-width: 760px;\n color: var(--dsw-alias-label-primary);\n}\n\n.titleRow {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n}\n\n.title {\n margin: 0;\n font-size: 15px;\n line-height: 22px;\n font-weight: 600;\n}\n\n.titleActions {\n display: flex;\n gap: 8px;\n}\n\nbutton {\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 6px;\n padding: 5px 12px;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 13px;\n line-height: 20px;\n cursor: pointer;\n}\n\nbutton:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\nbutton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\nbutton:disabled {\n cursor: not-allowed;\n opacity: 0.55;\n}\n\n.primary {\n border-color: var(--dsw-alias-button-primary-fill);\n background: var(--dsw-alias-button-primary-fill);\n color: var(--dsw-alias-label-primary-foreground);\n}\n\n.primary:hover {\n background: var(--dsw-alias-button-primary-hover);\n}\n\n.danger {\n color: var(--dsw-alias-state-error-primary);\n}\n\n.error {\n margin: 0;\n color: var(--dsw-alias-state-error-primary);\n font-size: 13px;\n line-height: 20px;\n}\n\n.field {\n display: flex;\n flex-direction: column;\n gap: 5px;\n font-size: 13px;\n line-height: 20px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.field input,\n.field select,\n.field textarea {\n width: 100%;\n box-sizing: border-box;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n padding: 6px 10px;\n outline: none;\n background: var(--dsw-alias-bg-layer-1);\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 13px;\n resize: vertical;\n}\n\n.field input::placeholder,\n.field textarea::placeholder {\n color: var(--dsw-alias-label-tertiary);\n}\n\n.field input:focus-visible,\n.field select:focus-visible,\n.field textarea:focus-visible {\n border-color: var(--dsw-alias-brand-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--dsw-alias-brand-primary) 18%, transparent);\n}\n\n.hint,\n.muted {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n.checkRow {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n line-height: 20px;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n}\n\n.testResult {\n margin: 0;\n font-size: 13px;\n line-height: 20px;\n}\n\n.testOk {\n color: var(--dsw-alias-state-success-primary);\n}\n\n.testFail {\n color: var(--dsw-alias-state-error-primary);\n}\n\n.actions {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n}\n";
|
|
15030
15053
|
document.head.appendChild(style);
|
|
15031
15054
|
}
|
|
15032
15055
|
}
|
|
15033
15056
|
})();
|
|
15034
|
-
var ServerForm_default = { "form": "form", "titleRow": "titleRow", "title": "title", "titleActions": "titleActions", "primary": "primary", "danger": "danger", "error": "error", "field": "field", "
|
|
15057
|
+
var ServerForm_default = { "form": "form", "titleRow": "titleRow", "title": "title", "titleActions": "titleActions", "primary": "primary", "danger": "danger", "error": "error", "field": "field", "hint": "hint", "muted": "muted", "checkRow": "checkRow", "testResult": "testResult", "testOk": "testOk", "testFail": "testFail", "actions": "actions" };
|
|
15035
15058
|
|
|
15036
15059
|
// src/client/ServerForm.tsx
|
|
15037
15060
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
@@ -15042,15 +15065,6 @@ function McpServerForm(props) {
|
|
|
15042
15065
|
setSaveError(null);
|
|
15043
15066
|
actions.updateDraft(patch);
|
|
15044
15067
|
};
|
|
15045
|
-
const updateEnvRow = (key, patch) => {
|
|
15046
|
-
update({ env: draft.env.map((row) => row.key === key ? { ...row, ...patch } : row) });
|
|
15047
|
-
};
|
|
15048
|
-
const removeEnvRow = (key) => {
|
|
15049
|
-
update({ env: draft.env.filter((row) => row.key !== key) });
|
|
15050
|
-
};
|
|
15051
|
-
const addEnvRow = () => {
|
|
15052
|
-
update({ env: [...draft.env, createEnvRowDraft()] });
|
|
15053
|
-
};
|
|
15054
15068
|
const errorText = (error51) => error51 instanceof Error ? error51.message : String(error51);
|
|
15055
15069
|
const runTest = async () => {
|
|
15056
15070
|
setSaveError(null);
|
|
@@ -15216,52 +15230,6 @@ function McpServerForm(props) {
|
|
|
15216
15230
|
)
|
|
15217
15231
|
] })
|
|
15218
15232
|
] }),
|
|
15219
|
-
stdio ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("fieldset", { className: ServerForm_default.envBlock, children: [
|
|
15220
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("legend", { children: t("envVars") }),
|
|
15221
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: ServerForm_default.hint, children: t("envHint") }),
|
|
15222
|
-
draft.env.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: ServerForm_default.muted, children: [
|
|
15223
|
-
t("envVars"),
|
|
15224
|
-
": 0"
|
|
15225
|
-
] }) : null,
|
|
15226
|
-
draft.env.map((row) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: ServerForm_default.envRow, children: [
|
|
15227
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
15228
|
-
"input",
|
|
15229
|
-
{
|
|
15230
|
-
type: "text",
|
|
15231
|
-
className: ServerForm_default.envName,
|
|
15232
|
-
value: row.name,
|
|
15233
|
-
placeholder: t("envName"),
|
|
15234
|
-
"aria-label": t("envName"),
|
|
15235
|
-
onChange: (event) => updateEnvRow(row.key, { name: event.currentTarget.value })
|
|
15236
|
-
}
|
|
15237
|
-
),
|
|
15238
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
15239
|
-
"input",
|
|
15240
|
-
{
|
|
15241
|
-
type: row.secret ? "password" : "text",
|
|
15242
|
-
className: ServerForm_default.envValue,
|
|
15243
|
-
value: row.value,
|
|
15244
|
-
placeholder: row.secret && row.configured ? "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" : t("envValue"),
|
|
15245
|
-
"aria-label": t("envValue"),
|
|
15246
|
-
onChange: (event) => updateEnvRow(row.key, { value: event.currentTarget.value })
|
|
15247
|
-
}
|
|
15248
|
-
),
|
|
15249
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: ServerForm_default.secretToggle, children: [
|
|
15250
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
15251
|
-
"input",
|
|
15252
|
-
{
|
|
15253
|
-
type: "checkbox",
|
|
15254
|
-
checked: row.secret,
|
|
15255
|
-
title: t("envSecretHint"),
|
|
15256
|
-
onChange: (event) => updateEnvRow(row.key, { secret: event.currentTarget.checked })
|
|
15257
|
-
}
|
|
15258
|
-
),
|
|
15259
|
-
t("envSecret")
|
|
15260
|
-
] }),
|
|
15261
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: ServerForm_default.danger, "aria-label": t("removeEnvVar"), onClick: () => removeEnvRow(row.key), children: "\u2715" })
|
|
15262
|
-
] }, row.key)),
|
|
15263
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", onClick: addEnvRow, children: t("addEnvVar") })
|
|
15264
|
-
] }) : null,
|
|
15265
15233
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: ServerForm_default.field, children: [
|
|
15266
15234
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: t("toolCallTimeoutMs") }),
|
|
15267
15235
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -15306,6 +15274,419 @@ function McpServerForm(props) {
|
|
|
15306
15274
|
] });
|
|
15307
15275
|
}
|
|
15308
15276
|
|
|
15277
|
+
// src/client/ServersJsonEditor.tsx
|
|
15278
|
+
var import_react2 = require("react");
|
|
15279
|
+
|
|
15280
|
+
// src/client/ServersJsonEditor.module.css
|
|
15281
|
+
(function() {
|
|
15282
|
+
if (typeof document !== "undefined") {
|
|
15283
|
+
const existing = document.querySelector('style[data-plugin="dsh-mcp"][data-file="ServersJsonEditor.module.css"]');
|
|
15284
|
+
if (!existing) {
|
|
15285
|
+
const style = document.createElement("style");
|
|
15286
|
+
style.setAttribute("data-plugin", "dsh-mcp");
|
|
15287
|
+
style.setAttribute("data-file", "ServersJsonEditor.module.css");
|
|
15288
|
+
style.textContent = ".panel {\n display: flex;\n flex-direction: column;\n gap: 8px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 10px;\n padding: 10px 14px;\n background: var(--dsw-alias-bg-layer-3);\n}\n\n.editor {\n width: 100%;\n box-sizing: border-box;\n min-height: 260px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n padding: 8px 10px;\n outline: none;\n background: var(--dsw-alias-bg-layer-1);\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 12px;\n line-height: 18px;\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n resize: vertical;\n}\n\n.editor:focus-visible {\n border-color: var(--dsw-alias-brand-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--dsw-alias-brand-primary) 18%, transparent);\n}\n\n.hint {\n margin: 0;\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n line-height: 18px;\n}\n\n.error {\n margin: 0;\n color: var(--dsw-alias-state-error-primary);\n font-size: 12px;\n line-height: 18px;\n word-break: break-all;\n}\n\n.notice {\n margin: 0;\n color: var(--dsw-alias-state-success-primary);\n font-size: 12px;\n line-height: 18px;\n}\n\n.actions {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n}\n\n.actions button {\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 6px;\n padding: 5px 12px;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 13px;\n line-height: 20px;\n cursor: pointer;\n}\n\n.actions button:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.actions button:disabled {\n cursor: not-allowed;\n opacity: 0.55;\n}\n\n.actions .primary {\n border-color: var(--dsw-alias-button-primary-fill);\n background: var(--dsw-alias-button-primary-fill);\n color: var(--dsw-alias-label-primary-foreground);\n}\n\n.actions .primary:hover {\n background: var(--dsw-alias-button-primary-hover);\n}\n";
|
|
15289
|
+
document.head.appendChild(style);
|
|
15290
|
+
}
|
|
15291
|
+
}
|
|
15292
|
+
})();
|
|
15293
|
+
var ServersJsonEditor_default = { "panel": "panel", "editor": "editor", "hint": "hint", "error": "error", "notice": "notice", "actions": "actions", "primary": "primary" };
|
|
15294
|
+
|
|
15295
|
+
// src/client/ServersJsonEditor.tsx
|
|
15296
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
15297
|
+
function serversToJsonText(servers) {
|
|
15298
|
+
const document2 = servers.map((server) => {
|
|
15299
|
+
const entry = {
|
|
15300
|
+
serverName: server.serverName,
|
|
15301
|
+
transport: server.transport,
|
|
15302
|
+
enabled: server.enabled
|
|
15303
|
+
};
|
|
15304
|
+
if (server.transport === "stdio") {
|
|
15305
|
+
entry.command = server.command;
|
|
15306
|
+
entry.args = [...server.args];
|
|
15307
|
+
if (server.cwd.length > 0) entry.cwd = server.cwd;
|
|
15308
|
+
} else {
|
|
15309
|
+
entry.url = server.url;
|
|
15310
|
+
}
|
|
15311
|
+
if (server.headers.length > 0) {
|
|
15312
|
+
entry.headers = Object.fromEntries(server.headers.map((header) => [header.name, header.value]));
|
|
15313
|
+
}
|
|
15314
|
+
entry.toolCallTimeoutMs = server.toolCallTimeoutMs;
|
|
15315
|
+
entry.failOnStartupError = server.failOnStartupError;
|
|
15316
|
+
entry.env = server.env.map((row) => row.secret ? { name: row.name, secret: true, configured: row.configured } : { name: row.name, secret: false, ...row.value !== void 0 && row.value.length > 0 ? { value: row.value } : {} });
|
|
15317
|
+
return entry;
|
|
15318
|
+
});
|
|
15319
|
+
return `${JSON.stringify(document2, null, 2)}
|
|
15320
|
+
`;
|
|
15321
|
+
}
|
|
15322
|
+
function parseServersJson(text) {
|
|
15323
|
+
let value;
|
|
15324
|
+
try {
|
|
15325
|
+
value = JSON.parse(text);
|
|
15326
|
+
} catch (error51) {
|
|
15327
|
+
return { ok: false, error: error51 instanceof Error ? error51.message : String(error51) };
|
|
15328
|
+
}
|
|
15329
|
+
if (!Array.isArray(value)) {
|
|
15330
|
+
return { ok: false, error: "JSON \u9876\u5C42\u5FC5\u987B\u662F\u670D\u52A1\u5668\u914D\u7F6E\u6570\u7EC4\uFF1A[ { serverName, transport, ... }, ... ]" };
|
|
15331
|
+
}
|
|
15332
|
+
if (value.length === 0) {
|
|
15333
|
+
return { ok: false, error: "\u914D\u7F6E\u5217\u8868\u4E0D\u80FD\u4E3A\u7A7A" };
|
|
15334
|
+
}
|
|
15335
|
+
const servers = [];
|
|
15336
|
+
const seen = /* @__PURE__ */ new Set();
|
|
15337
|
+
for (const item of value) {
|
|
15338
|
+
if (item === null || typeof item !== "object" || Array.isArray(item)) {
|
|
15339
|
+
return { ok: false, error: "\u6BCF\u4E2A\u6761\u76EE\u5FC5\u987B\u662F\u5BF9\u8C61\uFF1A{ serverName, transport, ... }" };
|
|
15340
|
+
}
|
|
15341
|
+
const server = item;
|
|
15342
|
+
const serverName = typeof server.serverName === "string" ? server.serverName.trim() : "";
|
|
15343
|
+
if (serverName.length === 0) return { ok: false, error: "serverName \u4E0D\u80FD\u4E3A\u7A7A" };
|
|
15344
|
+
if (seen.has(serverName)) return { ok: false, error: `serverName "${serverName}" \u91CD\u590D` };
|
|
15345
|
+
seen.add(serverName);
|
|
15346
|
+
const transport = server.transport;
|
|
15347
|
+
if (transport !== "stdio" && transport !== "streamable-http") {
|
|
15348
|
+
return { ok: false, error: `\u670D\u52A1\u5668 "${serverName}" \u7684 transport \u5FC5\u987B\u662F stdio \u6216 streamable-http` };
|
|
15349
|
+
}
|
|
15350
|
+
if (transport === "stdio" && (typeof server.command !== "string" || server.command.trim().length === 0)) {
|
|
15351
|
+
return { ok: false, error: `\u670D\u52A1\u5668 "${serverName}"\uFF08stdio\uFF09\u7F3A\u5C11 command` };
|
|
15352
|
+
}
|
|
15353
|
+
if (transport === "streamable-http" && typeof server.url !== "string") {
|
|
15354
|
+
return { ok: false, error: `\u670D\u52A1\u5668 "${serverName}"\uFF08streamable-http\uFF09\u7F3A\u5C11 url` };
|
|
15355
|
+
}
|
|
15356
|
+
if (server.headers !== void 0) {
|
|
15357
|
+
const headers = server.headers;
|
|
15358
|
+
const okHeaders = headers !== null && typeof headers === "object" && !Array.isArray(headers) || Array.isArray(headers) && headers.every((h) => h !== null && typeof h === "object" && typeof h.name === "string");
|
|
15359
|
+
if (!okHeaders) return { ok: false, error: `\u670D\u52A1\u5668 "${serverName}" \u7684 headers \u5FC5\u987B\u662F { "\u540D\u79F0": "\u503C" } \u5BF9\u8C61\u6216 { name, value } \u6570\u7EC4` };
|
|
15360
|
+
}
|
|
15361
|
+
const envValue = server.env;
|
|
15362
|
+
const env = Array.isArray(envValue) ? envValue : [];
|
|
15363
|
+
for (const row of env) {
|
|
15364
|
+
const r = row;
|
|
15365
|
+
if (r === null || typeof r !== "object" || typeof r.name !== "string" || r.name.trim().length === 0) {
|
|
15366
|
+
return { ok: false, error: `\u670D\u52A1\u5668 "${serverName}" \u7684 env \u6761\u76EE\u7F3A\u5C11\u5408\u6CD5\u7684 name` };
|
|
15367
|
+
}
|
|
15368
|
+
if (r.secret !== void 0 && typeof r.secret !== "boolean") {
|
|
15369
|
+
return { ok: false, error: `\u670D\u52A1\u5668 "${serverName}" \u7684 env \u6761\u76EE "${r.name}" \u7684 secret \u5FC5\u987B\u662F\u5E03\u5C14\u503C` };
|
|
15370
|
+
}
|
|
15371
|
+
if (r.value !== void 0 && typeof r.value !== "string") {
|
|
15372
|
+
return { ok: false, error: `\u670D\u52A1\u5668 "${serverName}" \u7684 env \u6761\u76EE "${r.name}" \u7684 value \u5FC5\u987B\u662F\u5B57\u7B26\u4E32` };
|
|
15373
|
+
}
|
|
15374
|
+
}
|
|
15375
|
+
servers.push({ server, env });
|
|
15376
|
+
}
|
|
15377
|
+
return { ok: true, servers };
|
|
15378
|
+
}
|
|
15379
|
+
function ServersJsonEditor({ injected, t, onApplied }) {
|
|
15380
|
+
const [text, setText] = (0, import_react2.useState)("");
|
|
15381
|
+
const [error51, setError] = (0, import_react2.useState)(null);
|
|
15382
|
+
const [notice, setNotice] = (0, import_react2.useState)(null);
|
|
15383
|
+
const [busy, setBusy] = (0, import_react2.useState)(false);
|
|
15384
|
+
const [loaded, setLoaded] = (0, import_react2.useState)(false);
|
|
15385
|
+
const seqRef = (0, import_react2.useRef)(0);
|
|
15386
|
+
(0, import_react2.useEffect)(() => {
|
|
15387
|
+
if (loaded) return;
|
|
15388
|
+
let current = true;
|
|
15389
|
+
void injected.list().then(
|
|
15390
|
+
(servers) => {
|
|
15391
|
+
if (!current) return;
|
|
15392
|
+
setText(serversToJsonText(servers));
|
|
15393
|
+
setLoaded(true);
|
|
15394
|
+
setError(null);
|
|
15395
|
+
},
|
|
15396
|
+
() => {
|
|
15397
|
+
if (current) setError("\u65E0\u6CD5\u8BFB\u53D6\u670D\u52A1\u5668\u5217\u8868");
|
|
15398
|
+
}
|
|
15399
|
+
);
|
|
15400
|
+
return () => {
|
|
15401
|
+
current = false;
|
|
15402
|
+
};
|
|
15403
|
+
}, [injected, loaded]);
|
|
15404
|
+
const reseed = () => {
|
|
15405
|
+
const seq = ++seqRef.current;
|
|
15406
|
+
setBusy(true);
|
|
15407
|
+
setNotice(null);
|
|
15408
|
+
void injected.list().then(
|
|
15409
|
+
(servers) => {
|
|
15410
|
+
if (seq !== seqRef.current) return;
|
|
15411
|
+
setText(serversToJsonText(servers));
|
|
15412
|
+
setError(null);
|
|
15413
|
+
},
|
|
15414
|
+
() => {
|
|
15415
|
+
if (seq === seqRef.current) setError("\u65E0\u6CD5\u8BFB\u53D6\u670D\u52A1\u5668\u5217\u8868");
|
|
15416
|
+
}
|
|
15417
|
+
).finally(() => {
|
|
15418
|
+
if (seq === seqRef.current) setBusy(false);
|
|
15419
|
+
});
|
|
15420
|
+
};
|
|
15421
|
+
const apply2 = () => {
|
|
15422
|
+
const parsed = parseServersJson(text);
|
|
15423
|
+
if (!parsed.ok) {
|
|
15424
|
+
setError(parsed.error);
|
|
15425
|
+
return;
|
|
15426
|
+
}
|
|
15427
|
+
const seq = ++seqRef.current;
|
|
15428
|
+
setBusy(true);
|
|
15429
|
+
setError(null);
|
|
15430
|
+
setNotice(null);
|
|
15431
|
+
void injected.upsertJson(parsed.servers).then(
|
|
15432
|
+
(result) => {
|
|
15433
|
+
if (seq !== seqRef.current) return;
|
|
15434
|
+
setNotice(`${t("serversJsonDone")}: +${result.added} / ~${result.updated} / -${result.removed}`);
|
|
15435
|
+
onApplied();
|
|
15436
|
+
},
|
|
15437
|
+
(error52) => {
|
|
15438
|
+
if (seq !== seqRef.current) return;
|
|
15439
|
+
setError(error52 instanceof Error ? error52.message : String(error52));
|
|
15440
|
+
}
|
|
15441
|
+
).finally(() => {
|
|
15442
|
+
if (seq === seqRef.current) setBusy(false);
|
|
15443
|
+
});
|
|
15444
|
+
};
|
|
15445
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: ServersJsonEditor_default.panel, children: [
|
|
15446
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
15447
|
+
"textarea",
|
|
15448
|
+
{
|
|
15449
|
+
className: ServersJsonEditor_default.editor,
|
|
15450
|
+
rows: 16,
|
|
15451
|
+
spellCheck: false,
|
|
15452
|
+
"aria-label": t("serversJsonLabel"),
|
|
15453
|
+
value: text,
|
|
15454
|
+
onChange: (event) => setText(event.currentTarget.value)
|
|
15455
|
+
}
|
|
15456
|
+
),
|
|
15457
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: ServersJsonEditor_default.hint, children: t("serversJsonHint") }),
|
|
15458
|
+
error51 !== null ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: ServersJsonEditor_default.error, role: "alert", children: error51 }) : null,
|
|
15459
|
+
notice !== null ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: ServersJsonEditor_default.notice, role: "status", children: notice }) : null,
|
|
15460
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: ServersJsonEditor_default.actions, children: [
|
|
15461
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", disabled: busy, onClick: reseed, children: t("serversJsonReseed") }),
|
|
15462
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: ServersJsonEditor_default.primary, disabled: busy, onClick: apply2, children: busy ? t("serversJsonSaving") : t("serversJsonApply") })
|
|
15463
|
+
] })
|
|
15464
|
+
] });
|
|
15465
|
+
}
|
|
15466
|
+
|
|
15467
|
+
// src/client/GlobalEnvEditor.tsx
|
|
15468
|
+
var import_react3 = require("react");
|
|
15469
|
+
|
|
15470
|
+
// src/client/GlobalEnvEditor.module.css
|
|
15471
|
+
(function() {
|
|
15472
|
+
if (typeof document !== "undefined") {
|
|
15473
|
+
const existing = document.querySelector('style[data-plugin="dsh-mcp"][data-file="GlobalEnvEditor.module.css"]');
|
|
15474
|
+
if (!existing) {
|
|
15475
|
+
const style = document.createElement("style");
|
|
15476
|
+
style.setAttribute("data-plugin", "dsh-mcp");
|
|
15477
|
+
style.setAttribute("data-file", "GlobalEnvEditor.module.css");
|
|
15478
|
+
style.textContent = ".panel {\n display: flex;\n flex-direction: column;\n gap: 8px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 10px;\n padding: 10px 14px;\n background: var(--dsw-alias-bg-layer-3);\n}\n\n.hint,\n.muted {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n.row {\n display: grid;\n grid-template-columns: minmax(0, 1.2fr) minmax(0, 1.8fr) auto auto;\n align-items: center;\n gap: 8px;\n}\n\n.row input {\n box-sizing: border-box;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 6px;\n padding: 5px 8px;\n outline: none;\n background: var(--dsw-alias-bg-layer-1);\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 13px;\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n}\n\n.row input:focus-visible {\n border-color: var(--dsw-alias-brand-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--dsw-alias-brand-primary) 18%, transparent);\n}\n\n.name {\n width: 100%;\n}\n\n.value {\n width: 100%;\n}\n\n.secretToggle {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n line-height: 18px;\n white-space: nowrap;\n cursor: pointer;\n user-select: none;\n}\n\n.secretToggle input {\n cursor: pointer;\n}\n\n.secretToggle.secretOn {\n color: var(--dsw-alias-brand-primary);\n font-weight: 600;\n}\n\n.danger {\n border: 1px solid transparent !important;\n background: transparent !important;\n color: var(--dsw-alias-state-error-primary) !important;\n cursor: pointer;\n}\n\n.overlay {\n position: fixed;\n inset: 0;\n z-index: 1000;\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgba(0, 0, 0, 0.4);\n}\n\n.dialog {\n display: flex;\n flex-direction: column;\n gap: 8px;\n width: min(520px, calc(100vw - 48px));\n max-height: 80vh;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 12px;\n padding: 16px;\n background: var(--dsw-alias-bg-overlay);\n box-shadow: 0 12px 32px rgba(0, 0, 0, 0.25);\n}\n\n.dialogTitle {\n margin: 0;\n font-size: 15px;\n line-height: 22px;\n font-weight: 600;\n color: var(--dsw-alias-label-primary);\n}\n\n.bulkText {\n width: 100%;\n box-sizing: border-box;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n padding: 8px 10px;\n outline: none;\n background: var(--dsw-alias-bg-layer-1);\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 12px;\n line-height: 18px;\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n resize: vertical;\n}\n\n.bulkText:focus-visible {\n border-color: var(--dsw-alias-brand-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--dsw-alias-brand-primary) 18%, transparent);\n}\n\n.retryRow {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.retryRow button {\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 6px;\n padding: 3px 10px;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 12px;\n line-height: 18px;\n cursor: pointer;\n}\n\n.retryRow button:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.error {\n margin: 0;\n color: var(--dsw-alias-state-error-primary);\n font-size: 12px;\n line-height: 18px;\n word-break: break-all;\n}\n\n.notice {\n margin: 0;\n color: var(--dsw-alias-state-success-primary);\n font-size: 12px;\n line-height: 18px;\n}\n\n.actions {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n}\n\n.actions button {\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 6px;\n padding: 5px 12px;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 13px;\n line-height: 20px;\n cursor: pointer;\n}\n\n.actions button:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.actions button:disabled {\n cursor: not-allowed;\n opacity: 0.55;\n}\n\n.actions .primary {\n border-color: var(--dsw-alias-button-primary-fill);\n background: var(--dsw-alias-button-primary-fill);\n color: var(--dsw-alias-label-primary-foreground);\n}\n\n.actions .primary:hover {\n background: var(--dsw-alias-button-primary-hover);\n}\n";
|
|
15479
|
+
document.head.appendChild(style);
|
|
15480
|
+
}
|
|
15481
|
+
}
|
|
15482
|
+
})();
|
|
15483
|
+
var GlobalEnvEditor_default = { "panel": "panel", "hint": "hint", "muted": "muted", "row": "row", "name": "name", "value": "value", "secretToggle": "secretToggle", "secretOn": "secretOn", "danger": "danger", "overlay": "overlay", "dialog": "dialog", "dialogTitle": "dialogTitle", "bulkText": "bulkText", "retryRow": "retryRow", "error": "error", "notice": "notice", "actions": "actions", "primary": "primary" };
|
|
15484
|
+
|
|
15485
|
+
// src/client/GlobalEnvEditor.tsx
|
|
15486
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
15487
|
+
var rowSeq = 0;
|
|
15488
|
+
function nextKey() {
|
|
15489
|
+
rowSeq += 1;
|
|
15490
|
+
return `genv-${rowSeq}`;
|
|
15491
|
+
}
|
|
15492
|
+
function emptyRow() {
|
|
15493
|
+
return { key: nextKey(), name: "", secret: true, value: "", configured: false };
|
|
15494
|
+
}
|
|
15495
|
+
function GlobalEnvEditor({ injected, t, onApplied }) {
|
|
15496
|
+
const [rows, setRows] = (0, import_react3.useState)([]);
|
|
15497
|
+
const [error51, setError] = (0, import_react3.useState)(null);
|
|
15498
|
+
const [notice, setNotice] = (0, import_react3.useState)(null);
|
|
15499
|
+
const [busy, setBusy] = (0, import_react3.useState)(false);
|
|
15500
|
+
const [loaded, setLoaded] = (0, import_react3.useState)(false);
|
|
15501
|
+
const [loadFailed, setLoadFailed] = (0, import_react3.useState)(false);
|
|
15502
|
+
const [bulkOpen, setBulkOpen] = (0, import_react3.useState)(false);
|
|
15503
|
+
const [bulkText, setBulkText] = (0, import_react3.useState)("");
|
|
15504
|
+
const seqRef = (0, import_react3.useRef)(0);
|
|
15505
|
+
const reload = () => {
|
|
15506
|
+
const seq = ++seqRef.current;
|
|
15507
|
+
setLoadFailed(false);
|
|
15508
|
+
void injected.envList().then(
|
|
15509
|
+
(state) => {
|
|
15510
|
+
if (seq !== seqRef.current) return;
|
|
15511
|
+
setRows(state.vars.map((row) => ({
|
|
15512
|
+
key: nextKey(),
|
|
15513
|
+
name: row.name,
|
|
15514
|
+
secret: row.secret,
|
|
15515
|
+
// 展示 process.env 优先返回的值(非 secret);secret 值不展示
|
|
15516
|
+
value: row.secret ? "" : row.value ?? "",
|
|
15517
|
+
configured: row.configured
|
|
15518
|
+
})));
|
|
15519
|
+
setLoaded(true);
|
|
15520
|
+
setError(null);
|
|
15521
|
+
},
|
|
15522
|
+
(error52) => {
|
|
15523
|
+
if (seq !== seqRef.current) return;
|
|
15524
|
+
setLoadFailed(true);
|
|
15525
|
+
setError(error52 instanceof Error ? error52.message : String(error52));
|
|
15526
|
+
}
|
|
15527
|
+
);
|
|
15528
|
+
};
|
|
15529
|
+
(0, import_react3.useEffect)(() => {
|
|
15530
|
+
if (loaded) return;
|
|
15531
|
+
reload();
|
|
15532
|
+
}, [injected, loaded]);
|
|
15533
|
+
const update = (key, patch) => {
|
|
15534
|
+
setRows((prev) => prev.map((row) => row.key === key ? { ...row, ...patch } : row));
|
|
15535
|
+
};
|
|
15536
|
+
const remove = (key) => {
|
|
15537
|
+
setRows((prev) => prev.filter((row) => row.key !== key));
|
|
15538
|
+
};
|
|
15539
|
+
const add = () => {
|
|
15540
|
+
setRows((prev) => [...prev, emptyRow()]);
|
|
15541
|
+
};
|
|
15542
|
+
const applyBulk = () => {
|
|
15543
|
+
const parsed = bulkText.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
|
|
15544
|
+
if (parsed.length === 0) {
|
|
15545
|
+
setBulkOpen(false);
|
|
15546
|
+
return;
|
|
15547
|
+
}
|
|
15548
|
+
const next = [];
|
|
15549
|
+
for (const line of parsed) {
|
|
15550
|
+
const eq = line.indexOf("=");
|
|
15551
|
+
if (eq <= 0) {
|
|
15552
|
+
next.push({ key: nextKey(), name: line, secret: false, value: "", configured: false });
|
|
15553
|
+
continue;
|
|
15554
|
+
}
|
|
15555
|
+
const name = line.slice(0, eq).trim();
|
|
15556
|
+
const value = line.slice(eq + 1);
|
|
15557
|
+
if (name.length === 0) continue;
|
|
15558
|
+
next.push({ key: nextKey(), name, secret: false, value, configured: false });
|
|
15559
|
+
}
|
|
15560
|
+
if (next.length > 0) setRows((prev) => [...prev, ...next]);
|
|
15561
|
+
setBulkOpen(false);
|
|
15562
|
+
setBulkText("");
|
|
15563
|
+
};
|
|
15564
|
+
const save = () => {
|
|
15565
|
+
const vars = [];
|
|
15566
|
+
const seen = /* @__PURE__ */ new Set();
|
|
15567
|
+
for (const row of rows) {
|
|
15568
|
+
const name = row.name.trim();
|
|
15569
|
+
if (name.length === 0) {
|
|
15570
|
+
if (row.value.trim().length > 0) {
|
|
15571
|
+
setError("\u5B58\u5728\u672A\u586B\u5199\u53D8\u91CF\u540D\u7684\u884C");
|
|
15572
|
+
return;
|
|
15573
|
+
}
|
|
15574
|
+
continue;
|
|
15575
|
+
}
|
|
15576
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name)) {
|
|
15577
|
+
setError(`\u53D8\u91CF\u540D "${name}" \u5FC5\u987B\u662F\u5B57\u6BCD/\u6570\u5B57/\u4E0B\u5212\u7EBF\uFF0C\u4E14\u4EE5\u5B57\u6BCD\u6216\u4E0B\u5212\u7EBF\u5F00\u5934`);
|
|
15578
|
+
return;
|
|
15579
|
+
}
|
|
15580
|
+
if (seen.has(name)) {
|
|
15581
|
+
setError(`\u53D8\u91CF\u540D "${name}" \u91CD\u590D`);
|
|
15582
|
+
return;
|
|
15583
|
+
}
|
|
15584
|
+
seen.add(name);
|
|
15585
|
+
vars.push({
|
|
15586
|
+
name,
|
|
15587
|
+
secret: row.secret,
|
|
15588
|
+
// 填了值就提交(secret 也会写入凭据文档);留空不提交(secret 保留原值)
|
|
15589
|
+
...row.value.trim().length > 0 ? { value: row.value } : {}
|
|
15590
|
+
});
|
|
15591
|
+
}
|
|
15592
|
+
const seq = ++seqRef.current;
|
|
15593
|
+
setBusy(true);
|
|
15594
|
+
setError(null);
|
|
15595
|
+
setNotice(null);
|
|
15596
|
+
void injected.envSet(vars).then(
|
|
15597
|
+
(state) => {
|
|
15598
|
+
if (seq !== seqRef.current) return;
|
|
15599
|
+
setRows(state.vars.map((row) => ({
|
|
15600
|
+
key: nextKey(),
|
|
15601
|
+
name: row.name,
|
|
15602
|
+
secret: row.secret,
|
|
15603
|
+
value: row.secret ? "" : row.value ?? "",
|
|
15604
|
+
configured: row.configured
|
|
15605
|
+
})));
|
|
15606
|
+
setNotice(t("globalEnvDone"));
|
|
15607
|
+
onApplied();
|
|
15608
|
+
},
|
|
15609
|
+
(error52) => {
|
|
15610
|
+
if (seq !== seqRef.current) return;
|
|
15611
|
+
setError(error52 instanceof Error ? error52.message : String(error52));
|
|
15612
|
+
}
|
|
15613
|
+
).finally(() => {
|
|
15614
|
+
if (seq === seqRef.current) setBusy(false);
|
|
15615
|
+
});
|
|
15616
|
+
};
|
|
15617
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: GlobalEnvEditor_default.panel, children: [
|
|
15618
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: GlobalEnvEditor_default.hint, children: t("globalEnvHint") }),
|
|
15619
|
+
rows.length === 0 && !loadFailed ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: GlobalEnvEditor_default.muted, children: t("globalEnvEmpty") }) : null,
|
|
15620
|
+
rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: GlobalEnvEditor_default.row, children: [
|
|
15621
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
15622
|
+
"input",
|
|
15623
|
+
{
|
|
15624
|
+
type: "text",
|
|
15625
|
+
className: GlobalEnvEditor_default.name,
|
|
15626
|
+
value: row.name,
|
|
15627
|
+
placeholder: t("globalEnvName"),
|
|
15628
|
+
"aria-label": t("globalEnvName"),
|
|
15629
|
+
onChange: (event) => update(row.key, { name: event.currentTarget.value })
|
|
15630
|
+
}
|
|
15631
|
+
),
|
|
15632
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
15633
|
+
"input",
|
|
15634
|
+
{
|
|
15635
|
+
type: row.secret ? "password" : "text",
|
|
15636
|
+
className: GlobalEnvEditor_default.value,
|
|
15637
|
+
value: row.value,
|
|
15638
|
+
placeholder: row.secret && row.configured ? "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" : t("globalEnvValue"),
|
|
15639
|
+
"aria-label": t("globalEnvValue"),
|
|
15640
|
+
onChange: (event) => update(row.key, { value: event.currentTarget.value })
|
|
15641
|
+
}
|
|
15642
|
+
),
|
|
15643
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: `${GlobalEnvEditor_default.secretToggle} ${row.secret ? GlobalEnvEditor_default.secretOn : ""}`, title: t("globalEnvSecretHint"), children: [
|
|
15644
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
15645
|
+
"input",
|
|
15646
|
+
{
|
|
15647
|
+
type: "checkbox",
|
|
15648
|
+
checked: row.secret,
|
|
15649
|
+
"aria-label": t("globalEnvSecret"),
|
|
15650
|
+
onChange: (event) => update(row.key, { secret: event.currentTarget.checked })
|
|
15651
|
+
}
|
|
15652
|
+
),
|
|
15653
|
+
t("globalEnvSecret")
|
|
15654
|
+
] }),
|
|
15655
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: GlobalEnvEditor_default.danger, "aria-label": t("globalEnvRemove"), onClick: () => remove(row.key), children: "\u2715" })
|
|
15656
|
+
] }, row.key)),
|
|
15657
|
+
loadFailed ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: GlobalEnvEditor_default.retryRow, children: [
|
|
15658
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: GlobalEnvEditor_default.error, role: "alert", children: t("globalEnvLoadFailed") }),
|
|
15659
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", onClick: reload, children: t("globalEnvRetry") })
|
|
15660
|
+
] }) : null,
|
|
15661
|
+
error51 !== null && !loadFailed ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: GlobalEnvEditor_default.error, role: "alert", children: error51 }) : null,
|
|
15662
|
+
notice !== null ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: GlobalEnvEditor_default.notice, role: "status", children: notice }) : null,
|
|
15663
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: GlobalEnvEditor_default.actions, children: [
|
|
15664
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", disabled: busy, onClick: add, children: t("globalEnvAdd") }),
|
|
15665
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", disabled: busy, onClick: () => setBulkOpen(true), children: t("globalEnvBulk") }),
|
|
15666
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: GlobalEnvEditor_default.primary, disabled: busy, onClick: save, children: busy ? t("globalEnvSaving") : t("globalEnvSave") })
|
|
15667
|
+
] }),
|
|
15668
|
+
bulkOpen ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: GlobalEnvEditor_default.overlay, onClick: () => setBulkOpen(false), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: GlobalEnvEditor_default.dialog, role: "dialog", "aria-label": t("globalEnvBulk"), onClick: (event) => event.stopPropagation(), children: [
|
|
15669
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: GlobalEnvEditor_default.dialogTitle, children: t("globalEnvBulk") }),
|
|
15670
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: GlobalEnvEditor_default.hint, children: t("globalEnvBulkPrompt") }),
|
|
15671
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
15672
|
+
"textarea",
|
|
15673
|
+
{
|
|
15674
|
+
className: GlobalEnvEditor_default.bulkText,
|
|
15675
|
+
rows: 8,
|
|
15676
|
+
autoFocus: true,
|
|
15677
|
+
spellCheck: false,
|
|
15678
|
+
value: bulkText,
|
|
15679
|
+
onChange: (event) => setBulkText(event.currentTarget.value)
|
|
15680
|
+
}
|
|
15681
|
+
),
|
|
15682
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: GlobalEnvEditor_default.actions, children: [
|
|
15683
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", onClick: () => setBulkOpen(false), children: t("cancel") }),
|
|
15684
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: GlobalEnvEditor_default.primary, onClick: applyBulk, children: t("globalEnvBulkOk") })
|
|
15685
|
+
] })
|
|
15686
|
+
] }) }) : null
|
|
15687
|
+
] });
|
|
15688
|
+
}
|
|
15689
|
+
|
|
15309
15690
|
// src/client/McpSettingsSection.module.css
|
|
15310
15691
|
(function() {
|
|
15311
15692
|
if (typeof document !== "undefined") {
|
|
@@ -15314,15 +15695,15 @@ function McpServerForm(props) {
|
|
|
15314
15695
|
const style = document.createElement("style");
|
|
15315
15696
|
style.setAttribute("data-plugin", "dsh-mcp");
|
|
15316
15697
|
style.setAttribute("data-file", "McpSettingsSection.module.css");
|
|
15317
|
-
style.textContent = ".section {\n display: flex;\n flex-direction: column;\n gap: 14px;\n width: 100%;\n max-width: 760px;\n color: var(--dsw-alias-label-primary);\n}\n\n.header {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n}\n\n.status,\n.failure p {\n margin: 0;\n}\n\n.status,\n.failure {\n font-size: 13px;\n line-height: 20px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n.failure {\n display: flex;\n align-items: center;\n gap: 10px;\n color: var(--dsw-alias-state-error-primary);\n}\n\nbutton {\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 6px;\n padding: 5px 12px;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 13px;\n line-height: 20px;\n cursor: pointer;\n}\n\nbutton:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\nbutton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\nbutton:disabled {\n cursor: not-allowed;\n opacity: 0.55;\n}\n\n.primary {\n border-color: var(--dsw-alias-button-primary-fill);\n background: var(--dsw-alias-button-primary-fill);\n color: var(--dsw-alias-label-primary-foreground);\n}\n\n.primary:hover {\n background: var(--dsw-alias-button-primary-hover);\n}\n\n.list {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 10px;\n padding: 10px 14px;\n background: var(--dsw-alias-bg-layer-3);\n}\n\n.rowMain {\n display: flex;\n flex-direction: column;\n gap: 4px;\n min-width: 0;\n}\n\n.rowTitle {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n}\n\n.serverName {\n overflow: hidden;\n font-size: 14px;\n line-height: 20px;\n font-weight: 600;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.badge {\n display: inline-flex;\n align-items: center;\n min-height: 18px;\n border-radius: 5px;\n padding: 1px 6px;\n font-size: 11px;\n line-height: 16px;\n white-space: nowrap;\n}\n\n.badge.mounting {\n background: color-mix(in srgb, var(--dsw-alias-brand-primary) 12%, transparent);\n color: var(--dsw-alias-brand-primary);\n}\n\n.badge.live {\n background: color-mix(in srgb, var(--dsw-alias-state-success-primary) 12%, transparent);\n color: var(--dsw-alias-state-success-primary);\n}\n\n.badge.failed {\n background: color-mix(in srgb, var(--dsw-alias-state-error-primary) 12%, transparent);\n color: var(--dsw-alias-state-error-primary);\n}\n\n.badge.stopped {\n background: var(--dsw-alias-bg-layer-1);\n color: var(--dsw-alias-label-tertiary);\n}\n\n.muted {\n color: var(--dsw-alias-label-tertiary);\n}\n\n.rowMeta {\n display: flex;\n gap: 14px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n line-height: 18px;\n font-variant-numeric: tabular-nums;\n}\n\n.rowActions {\n flex: none;\n}\n\n.card {\n display: flex;\n flex-direction: column;\n gap: 0;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 10px;\n background: var(--dsw-alias-bg-layer-3);\n}\n\n.card > .row {\n border: 0;\n border-radius: 0;\n background: transparent;\n}\n\n.modeRow {\n display: flex;\n align-items: center;\n gap: 18px;\n flex-wrap: wrap;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 10px;\n padding: 8px 14px;\n background: var(--dsw-alias-bg-layer-3);\n font-size: 13px;\n line-height: 20px;\n}\n\n.modeLabel {\n font-weight: 600;\n}\n\n.modeOption {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n cursor: pointer;\n}\n\n.modeHint {\n margin: 0;\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n line-height: 18px;\n}\n\n.toolPanel {\n border-top: 1px solid var(--dsw-alias-border-l2);\n padding: 10px 14px;\n}\n\n.toolGrid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));\n gap: 4px 14px;\n max-height: 320px;\n overflow-y: auto;\n}\n\n.toolRow {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n padding: 2px 0;\n font-size: 12px;\n line-height: 18px;\n cursor: pointer;\n}\n\n.toolName {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n";
|
|
15698
|
+
style.textContent = ".section {\n display: flex;\n flex-direction: column;\n gap: 14px;\n width: 100%;\n max-width: 760px;\n color: var(--dsw-alias-label-primary);\n}\n\n.header {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n}\n\n.status,\n.failure p {\n margin: 0;\n}\n\n.status,\n.failure {\n font-size: 13px;\n line-height: 20px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n.failure {\n display: flex;\n align-items: center;\n gap: 10px;\n color: var(--dsw-alias-state-error-primary);\n}\n\nbutton {\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 6px;\n padding: 5px 12px;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 13px;\n line-height: 20px;\n cursor: pointer;\n}\n\nbutton:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\nbutton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\nbutton:disabled {\n cursor: not-allowed;\n opacity: 0.55;\n}\n\n.primary {\n border-color: var(--dsw-alias-button-primary-fill);\n background: var(--dsw-alias-button-primary-fill);\n color: var(--dsw-alias-label-primary-foreground);\n}\n\n.primary:hover {\n background: var(--dsw-alias-button-primary-hover);\n}\n\n.active {\n border-color: var(--dsw-alias-brand-primary);\n color: var(--dsw-alias-brand-primary);\n background: color-mix(in srgb, var(--dsw-alias-brand-primary) 10%, transparent);\n}\n\n.module {\n display: flex;\n flex-direction: column;\n gap: 8px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 10px;\n padding: 10px 14px;\n background: var(--dsw-alias-bg-layer-3);\n}\n\n.moduleTitle {\n display: inline-flex !important;\n align-items: center;\n gap: 6px;\n width: fit-content;\n border: none !important;\n background: transparent !important;\n padding: 0 !important;\n font-weight: 600;\n font-size: 14px;\n line-height: 20px;\n color: var(--dsw-alias-label-primary) !important;\n}\n\n.moduleTitle:hover {\n background: transparent !important;\n}\n\n.caret {\n display: inline-block;\n width: 14px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n.configHeader {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n}\n\n.configActions {\n display: flex;\n gap: 8px;\n}\n\n.inlineForm {\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 10px;\n padding: 12px 14px;\n background: var(--dsw-alias-bg-layer-2);\n}\n\n.inlineFormItem {\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 10px;\n padding: 12px 14px;\n background: var(--dsw-alias-bg-layer-2);\n list-style: none;\n}\n\n.list {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 10px;\n padding: 10px 14px;\n background: var(--dsw-alias-bg-layer-3);\n}\n\n.rowMain {\n display: flex;\n flex-direction: column;\n gap: 4px;\n min-width: 0;\n}\n\n.rowTitle {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n}\n\n.serverName {\n overflow: hidden;\n font-size: 14px;\n line-height: 20px;\n font-weight: 600;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.badge {\n display: inline-flex;\n align-items: center;\n min-height: 18px;\n border-radius: 5px;\n padding: 1px 6px;\n font-size: 11px;\n line-height: 16px;\n white-space: nowrap;\n}\n\n.badge.mounting {\n background: color-mix(in srgb, var(--dsw-alias-brand-primary) 12%, transparent);\n color: var(--dsw-alias-brand-primary);\n}\n\n.badge.live {\n background: color-mix(in srgb, var(--dsw-alias-state-success-primary) 12%, transparent);\n color: var(--dsw-alias-state-success-primary);\n}\n\n.badge.failed {\n background: color-mix(in srgb, var(--dsw-alias-state-error-primary) 12%, transparent);\n color: var(--dsw-alias-state-error-primary);\n}\n\n.badge.stopped {\n background: var(--dsw-alias-bg-layer-1);\n color: var(--dsw-alias-label-tertiary);\n}\n\n.muted {\n color: var(--dsw-alias-label-tertiary);\n}\n\n.rowMeta {\n display: flex;\n gap: 14px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n line-height: 18px;\n font-variant-numeric: tabular-nums;\n}\n\n.rowActions {\n flex: none;\n}\n\n.card {\n display: flex;\n flex-direction: column;\n gap: 0;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 10px;\n background: var(--dsw-alias-bg-layer-3);\n}\n\n.card > .row {\n border: 0;\n border-radius: 0;\n background: transparent;\n}\n\n.modeRow {\n display: flex;\n align-items: center;\n gap: 18px;\n flex-wrap: wrap;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 10px;\n padding: 8px 14px;\n background: var(--dsw-alias-bg-layer-3);\n font-size: 13px;\n line-height: 20px;\n}\n\n.modeLabel {\n font-weight: 600;\n}\n\n.modeOption {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n cursor: pointer;\n}\n\n.modeHint {\n margin: 0;\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n line-height: 18px;\n}\n\n.toolPanel {\n border-top: 1px solid var(--dsw-alias-border-l2);\n padding: 10px 14px;\n}\n\n.toolGrid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));\n gap: 4px 14px;\n max-height: 320px;\n overflow-y: auto;\n}\n\n.toolRow {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n padding: 2px 0;\n font-size: 12px;\n line-height: 18px;\n cursor: pointer;\n}\n\n.toolName {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n";
|
|
15318
15699
|
document.head.appendChild(style);
|
|
15319
15700
|
}
|
|
15320
15701
|
}
|
|
15321
15702
|
})();
|
|
15322
|
-
var McpSettingsSection_default = { "section": "section", "header": "header", "status": "status", "failure": "failure", "primary": "primary", "list": "list", "row": "row", "rowMain": "rowMain", "rowTitle": "rowTitle", "serverName": "serverName", "badge": "badge", "mounting": "mounting", "live": "live", "failed": "failed", "stopped": "stopped", "muted": "muted", "rowMeta": "rowMeta", "rowActions": "rowActions", "card": "card", "modeRow": "modeRow", "modeLabel": "modeLabel", "modeOption": "modeOption", "modeHint": "modeHint", "toolPanel": "toolPanel", "toolGrid": "toolGrid", "toolRow": "toolRow", "toolName": "toolName" };
|
|
15703
|
+
var McpSettingsSection_default = { "section": "section", "header": "header", "status": "status", "failure": "failure", "primary": "primary", "active": "active", "module": "module", "moduleTitle": "moduleTitle", "caret": "caret", "configHeader": "configHeader", "configActions": "configActions", "inlineForm": "inlineForm", "inlineFormItem": "inlineFormItem", "list": "list", "row": "row", "rowMain": "rowMain", "rowTitle": "rowTitle", "serverName": "serverName", "badge": "badge", "mounting": "mounting", "live": "live", "failed": "failed", "stopped": "stopped", "muted": "muted", "rowMeta": "rowMeta", "rowActions": "rowActions", "card": "card", "modeRow": "modeRow", "modeLabel": "modeLabel", "modeOption": "modeOption", "modeHint": "modeHint", "toolPanel": "toolPanel", "toolGrid": "toolGrid", "toolRow": "toolRow", "toolName": "toolName" };
|
|
15323
15704
|
|
|
15324
15705
|
// src/client/McpSettingsSection.tsx
|
|
15325
|
-
var
|
|
15706
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
15326
15707
|
function phaseKey(phase) {
|
|
15327
15708
|
switch (phase) {
|
|
15328
15709
|
case "mounting":
|
|
@@ -15351,13 +15732,6 @@ function viewToDraft(server) {
|
|
|
15351
15732
|
cwd: server.cwd,
|
|
15352
15733
|
url: server.url,
|
|
15353
15734
|
headersText: server.headers.map((header) => `${header.name}: ${header.value}`).join("\n"),
|
|
15354
|
-
env: server.env.map((entry, index) => ({
|
|
15355
|
-
key: `view-${index}`,
|
|
15356
|
-
name: entry.name,
|
|
15357
|
-
secret: entry.secret,
|
|
15358
|
-
value: "",
|
|
15359
|
-
configured: entry.configured
|
|
15360
|
-
})),
|
|
15361
15735
|
toolCallTimeoutMs: String(server.toolCallTimeoutMs),
|
|
15362
15736
|
failOnStartupError: server.failOnStartupError
|
|
15363
15737
|
};
|
|
@@ -15367,13 +15741,16 @@ function McpSettingsSection(props) {
|
|
|
15367
15741
|
const state = props.useStore((snapshot) => snapshot);
|
|
15368
15742
|
const { setLoadState, setServers, beginCreate, beginEdit, cancelEdit, updateDraft, setBusy, setTestRunning, setTest } = props.actions;
|
|
15369
15743
|
const t = props.t;
|
|
15370
|
-
const [loadErrorDetail, setLoadErrorDetail] = (0,
|
|
15371
|
-
const [tools, setTools] = (0,
|
|
15372
|
-
const [toolsError, setToolsError] = (0,
|
|
15373
|
-
const [expanded, setExpanded] = (0,
|
|
15374
|
-
const [refreshing, setRefreshing] = (0,
|
|
15375
|
-
const
|
|
15376
|
-
(0,
|
|
15744
|
+
const [loadErrorDetail, setLoadErrorDetail] = (0, import_react4.useState)(null);
|
|
15745
|
+
const [tools, setTools] = (0, import_react4.useState)(null);
|
|
15746
|
+
const [toolsError, setToolsError] = (0, import_react4.useState)(null);
|
|
15747
|
+
const [expanded, setExpanded] = (0, import_react4.useState)(/* @__PURE__ */ new Set());
|
|
15748
|
+
const [refreshing, setRefreshing] = (0, import_react4.useState)(/* @__PURE__ */ new Set());
|
|
15749
|
+
const [jsonOpen, setJsonOpen] = (0, import_react4.useState)(false);
|
|
15750
|
+
const [envOpen, setEnvOpen] = (0, import_react4.useState)(true);
|
|
15751
|
+
const timersRef = (0, import_react4.useRef)([]);
|
|
15752
|
+
let inlineForm = null;
|
|
15753
|
+
(0, import_react4.useEffect)(() => () => {
|
|
15377
15754
|
for (const id of timersRef.current) window.clearTimeout(id);
|
|
15378
15755
|
}, []);
|
|
15379
15756
|
const refreshTools = () => {
|
|
@@ -15405,7 +15782,7 @@ function McpSettingsSection(props) {
|
|
|
15405
15782
|
);
|
|
15406
15783
|
refreshTools();
|
|
15407
15784
|
};
|
|
15408
|
-
(0,
|
|
15785
|
+
(0, import_react4.useEffect)(() => {
|
|
15409
15786
|
let current = true;
|
|
15410
15787
|
void list().then(
|
|
15411
15788
|
(servers) => {
|
|
@@ -15500,13 +15877,13 @@ function McpSettingsSection(props) {
|
|
|
15500
15877
|
const serverTools = (serverName) => (tools?.tools ?? []).filter((tool) => tool.server === serverName);
|
|
15501
15878
|
const mode = tools?.mode ?? "search";
|
|
15502
15879
|
if (state.loadState === "loading") {
|
|
15503
|
-
return /* @__PURE__ */ (0,
|
|
15880
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: McpSettingsSection_default.status, "aria-busy": "true", children: t("loading") });
|
|
15504
15881
|
}
|
|
15505
15882
|
if (state.loadState === "error") {
|
|
15506
|
-
return /* @__PURE__ */ (0,
|
|
15507
|
-
/* @__PURE__ */ (0,
|
|
15508
|
-
loadErrorDetail !== null ? /* @__PURE__ */ (0,
|
|
15509
|
-
/* @__PURE__ */ (0,
|
|
15883
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: McpSettingsSection_default.failure, children: [
|
|
15884
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { role: "alert", children: t("loadError") }),
|
|
15885
|
+
loadErrorDetail !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("pre", { className: McpSettingsSection_default.muted, children: loadErrorDetail }) : null,
|
|
15886
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", onClick: () => {
|
|
15510
15887
|
setLoadState("loading");
|
|
15511
15888
|
load();
|
|
15512
15889
|
}, children: t("retry") })
|
|
@@ -15521,7 +15898,7 @@ function McpSettingsSection(props) {
|
|
|
15521
15898
|
setTest,
|
|
15522
15899
|
setServers
|
|
15523
15900
|
};
|
|
15524
|
-
|
|
15901
|
+
const form = /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
15525
15902
|
McpServerForm,
|
|
15526
15903
|
{
|
|
15527
15904
|
draft: state.draft,
|
|
@@ -15538,13 +15915,13 @@ function McpSettingsSection(props) {
|
|
|
15538
15915
|
}
|
|
15539
15916
|
}
|
|
15540
15917
|
);
|
|
15918
|
+
inlineForm = form;
|
|
15541
15919
|
}
|
|
15542
|
-
return /* @__PURE__ */ (0,
|
|
15543
|
-
/* @__PURE__ */ (0,
|
|
15544
|
-
|
|
15545
|
-
/* @__PURE__ */ (0,
|
|
15546
|
-
|
|
15547
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
15920
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: McpSettingsSection_default.section, children: [
|
|
15921
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: McpSettingsSection_default.modeRow, children: [
|
|
15922
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: McpSettingsSection_default.modeLabel, children: t("toolsModeLabel") }),
|
|
15923
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: McpSettingsSection_default.modeOption, children: [
|
|
15924
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
15548
15925
|
"input",
|
|
15549
15926
|
{
|
|
15550
15927
|
type: "radio",
|
|
@@ -15555,8 +15932,8 @@ function McpSettingsSection(props) {
|
|
|
15555
15932
|
),
|
|
15556
15933
|
t("toolsModeSearch")
|
|
15557
15934
|
] }),
|
|
15558
|
-
/* @__PURE__ */ (0,
|
|
15559
|
-
/* @__PURE__ */ (0,
|
|
15935
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: McpSettingsSection_default.modeOption, children: [
|
|
15936
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
15560
15937
|
"input",
|
|
15561
15938
|
{
|
|
15562
15939
|
type: "radio",
|
|
@@ -15568,53 +15945,115 @@ function McpSettingsSection(props) {
|
|
|
15568
15945
|
t("toolsModeFull")
|
|
15569
15946
|
] })
|
|
15570
15947
|
] }),
|
|
15571
|
-
/* @__PURE__ */ (0,
|
|
15572
|
-
|
|
15573
|
-
|
|
15574
|
-
|
|
15575
|
-
|
|
15576
|
-
|
|
15577
|
-
|
|
15578
|
-
|
|
15579
|
-
|
|
15580
|
-
|
|
15581
|
-
|
|
15582
|
-
|
|
15583
|
-
|
|
15584
|
-
|
|
15585
|
-
|
|
15586
|
-
|
|
15587
|
-
|
|
15588
|
-
|
|
15589
|
-
|
|
15948
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: McpSettingsSection_default.modeHint, children: toolsError !== null ? toolsError : tools === null ? t("toolsLoading") : mode === "search" ? t("toolsHintSearch") : t("toolsHintFull") }),
|
|
15949
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: McpSettingsSection_default.module, children: [
|
|
15950
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
15951
|
+
"button",
|
|
15952
|
+
{
|
|
15953
|
+
type: "button",
|
|
15954
|
+
className: McpSettingsSection_default.moduleTitle,
|
|
15955
|
+
"aria-expanded": envOpen,
|
|
15956
|
+
onClick: () => setEnvOpen((open) => !open),
|
|
15957
|
+
children: [
|
|
15958
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: McpSettingsSection_default.caret, children: envOpen ? "\u25BE" : "\u25B8" }),
|
|
15959
|
+
t("globalEnv")
|
|
15960
|
+
]
|
|
15961
|
+
}
|
|
15962
|
+
),
|
|
15963
|
+
envOpen ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
15964
|
+
GlobalEnvEditor,
|
|
15965
|
+
{
|
|
15966
|
+
injected: { envList: props.envList, envSet: props.envSet },
|
|
15967
|
+
t,
|
|
15968
|
+
onApplied: () => {
|
|
15969
|
+
refreshServer("");
|
|
15970
|
+
}
|
|
15971
|
+
}
|
|
15972
|
+
) : null
|
|
15973
|
+
] }),
|
|
15974
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: McpSettingsSection_default.module, children: [
|
|
15975
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: McpSettingsSection_default.configHeader, children: [
|
|
15976
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: McpSettingsSection_default.moduleTitle, children: t("configTitle") }),
|
|
15977
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: McpSettingsSection_default.configActions, children: [
|
|
15978
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
15979
|
+
"button",
|
|
15980
|
+
{
|
|
15981
|
+
type: "button",
|
|
15982
|
+
className: jsonOpen ? McpSettingsSection_default.active : void 0,
|
|
15983
|
+
"aria-expanded": jsonOpen,
|
|
15984
|
+
onClick: () => setJsonOpen((open) => !open),
|
|
15985
|
+
children: t("serversJson")
|
|
15986
|
+
}
|
|
15987
|
+
),
|
|
15988
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: McpSettingsSection_default.primary, onClick: beginCreate, children: t("addServer") })
|
|
15989
|
+
] })
|
|
15990
|
+
] }),
|
|
15991
|
+
jsonOpen ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
15992
|
+
ServersJsonEditor,
|
|
15993
|
+
{
|
|
15994
|
+
injected: { list: props.list, upsertJson: props.upsertJson },
|
|
15995
|
+
t,
|
|
15996
|
+
onApplied: () => {
|
|
15997
|
+
refreshServer("");
|
|
15998
|
+
refreshTools();
|
|
15999
|
+
setJsonOpen(false);
|
|
16000
|
+
timersRef.current.push(window.setTimeout(() => refreshServer(""), 2e3));
|
|
16001
|
+
timersRef.current.push(window.setTimeout(() => refreshServer(""), 6e3));
|
|
16002
|
+
}
|
|
16003
|
+
}
|
|
16004
|
+
) : null,
|
|
16005
|
+
state.draft !== null && state.draft.id === null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: McpSettingsSection_default.inlineForm, children: inlineForm }) : null,
|
|
16006
|
+
jsonOpen ? null : state.servers.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: McpSettingsSection_default.status, children: t("empty") }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("ul", { className: McpSettingsSection_default.list, children: state.servers.flatMap((server) => {
|
|
16007
|
+
const isExpanded = expanded.has(server.serverName);
|
|
16008
|
+
const isRefreshing = refreshing.has(server.serverName);
|
|
16009
|
+
const serverToolList = serverTools(server.serverName);
|
|
16010
|
+
const card = /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("li", { className: McpSettingsSection_default.card, children: [
|
|
16011
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: McpSettingsSection_default.row, children: [
|
|
16012
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: McpSettingsSection_default.rowMain, children: [
|
|
16013
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: McpSettingsSection_default.rowTitle, children: [
|
|
16014
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: McpSettingsSection_default.serverName, children: server.serverName }),
|
|
16015
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: `${McpSettingsSection_default.badge} ${McpSettingsSection_default[server.status.phase]}`, children: t(phaseKey(server.status.phase)) }),
|
|
16016
|
+
!server.enabled && server.status.phase !== "stopped" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: McpSettingsSection_default.muted, children: t("statusStopped") }) : null
|
|
15590
16017
|
] }),
|
|
15591
|
-
/* @__PURE__ */ (0,
|
|
15592
|
-
|
|
15593
|
-
":
|
|
15594
|
-
|
|
16018
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: McpSettingsSection_default.rowMeta, children: [
|
|
16019
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: server.transport }),
|
|
16020
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { children: [
|
|
16021
|
+
t("toolCount"),
|
|
16022
|
+
": ",
|
|
16023
|
+
server.status.tools.length
|
|
16024
|
+
] }),
|
|
16025
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { children: [
|
|
16026
|
+
t("envVars"),
|
|
16027
|
+
": ",
|
|
16028
|
+
server.env.length
|
|
16029
|
+
] })
|
|
15595
16030
|
] })
|
|
16031
|
+
] }),
|
|
16032
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: McpSettingsSection_default.rowActions, children: [
|
|
16033
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", disabled: isRefreshing, onClick: () => void toggleEnabled(server), children: server.enabled ? t("disable") : t("enabled") }),
|
|
16034
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", disabled: isRefreshing, onClick: () => refreshServer(server.serverName), children: isRefreshing ? t("refreshing") : t("refresh") }),
|
|
16035
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", onClick: () => toggleExpand(server.serverName), children: isExpanded ? t("toolsCollapse") : t("toolsExpand") }),
|
|
16036
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", onClick: () => beginEdit(server), children: t("edit") })
|
|
15596
16037
|
] })
|
|
15597
16038
|
] }),
|
|
15598
|
-
/* @__PURE__ */ (0,
|
|
15599
|
-
/* @__PURE__ */ (0,
|
|
15600
|
-
|
|
15601
|
-
|
|
15602
|
-
|
|
15603
|
-
|
|
15604
|
-
|
|
15605
|
-
|
|
15606
|
-
|
|
15607
|
-
"
|
|
15608
|
-
|
|
15609
|
-
|
|
15610
|
-
|
|
15611
|
-
|
|
15612
|
-
|
|
15613
|
-
|
|
15614
|
-
|
|
15615
|
-
|
|
15616
|
-
] }, server.id);
|
|
15617
|
-
}) })
|
|
16039
|
+
isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: McpSettingsSection_default.toolPanel, children: tools === null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: McpSettingsSection_default.muted, children: toolsError ?? t("toolsLoading") }) : serverToolList.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: McpSettingsSection_default.muted, children: t("toolsEmpty") }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: McpSettingsSection_default.toolGrid, children: serverToolList.map((tool) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: McpSettingsSection_default.toolRow, title: tool.name, children: [
|
|
16040
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
16041
|
+
"input",
|
|
16042
|
+
{
|
|
16043
|
+
type: "checkbox",
|
|
16044
|
+
checked: tool.enabled,
|
|
16045
|
+
onChange: () => toggleTool(tool)
|
|
16046
|
+
}
|
|
16047
|
+
),
|
|
16048
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: McpSettingsSection_default.toolName, children: rawOf(tool.name) })
|
|
16049
|
+
] }, tool.name)) }) }) : null
|
|
16050
|
+
] }, server.id);
|
|
16051
|
+
if (state.draft !== null && state.draft.id === server.id) {
|
|
16052
|
+
return [card, /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("li", { className: McpSettingsSection_default.inlineFormItem, children: inlineForm }, `${server.id}-form`)];
|
|
16053
|
+
}
|
|
16054
|
+
return [card];
|
|
16055
|
+
}) })
|
|
16056
|
+
] })
|
|
15618
16057
|
] });
|
|
15619
16058
|
}
|
|
15620
16059
|
|
|
@@ -15642,9 +16081,9 @@ var zh = {
|
|
|
15642
16081
|
url: "\u670D\u52A1\u5668 URL",
|
|
15643
16082
|
urlPlaceholder: "\u4F8B\u5982 http://localhost:3000/mcp",
|
|
15644
16083
|
headers: "\u8BF7\u6C42\u5934",
|
|
15645
|
-
headersPlaceholder: '\u6BCF\u884C\u4E00\u4E2A "\u540D\u79F0: \u503C"',
|
|
16084
|
+
headersPlaceholder: '\u6BCF\u884C\u4E00\u4E2A "\u540D\u79F0: \u503C"\uFF1B\u503C\u652F\u6301 ${ENV} \u73AF\u5883\u53D8\u91CF\u66FF\u6362',
|
|
15646
16085
|
envVars: "\u73AF\u5883\u53D8\u91CF",
|
|
15647
|
-
envHint: "\u6CE8\u5165\
|
|
16086
|
+
envHint: "stdio\uFF1A\u6CE8\u5165\u5B50\u8FDB\u7A0B\uFF1BHTTP\uFF1A\u4F9B\u8BF7\u6C42\u5934 ${\u53D8\u91CF} \u66FF\u6362\uFF08\u5982 Authorization: Bearer ${TOKEN}\uFF09\u3002\u6807\u8BB0\u4E3A secret \u7684\u503C\u5199\u5165\u51ED\u636E\u6587\u6863\uFF0C\u4E0D\u5728\u6B64\u660E\u6587\u4FDD\u5B58",
|
|
15648
16087
|
envName: "\u53D8\u91CF\u540D",
|
|
15649
16088
|
envValue: "\u503C",
|
|
15650
16089
|
envSecret: "secret",
|
|
@@ -15690,7 +16129,32 @@ var zh = {
|
|
|
15690
16129
|
refresh: "\u5237\u65B0",
|
|
15691
16130
|
refreshing: "\u5237\u65B0\u4E2D\u2026",
|
|
15692
16131
|
toolsExpand: "\u5C55\u5F00\u5DE5\u5177",
|
|
15693
|
-
toolsCollapse: "\u6536\u8D77\u5DE5\u5177"
|
|
16132
|
+
toolsCollapse: "\u6536\u8D77\u5DE5\u5177",
|
|
16133
|
+
serversJson: "JSON \u7EF4\u62A4\u914D\u7F6E",
|
|
16134
|
+
serversJsonLabel: "\u670D\u52A1\u5668\u914D\u7F6E JSON",
|
|
16135
|
+
serversJsonHint: "\u6574\u4E2A MCP \u670D\u52A1\u5668\u914D\u7F6E\u5217\u8868\uFF08\u6570\u7EC4\uFF09\uFF1A\u5E94\u7528\u540E\u5C06\u6309\u6B64\u5217\u8868\u66FF\u6362\u2014\u2014\u5DF2\u5217\u51FA\u7684\u670D\u52A1\u5668\u521B\u5EFA/\u66F4\u65B0\uFF0C\u672A\u5217\u51FA\u7684\u5C06\u88AB\u5220\u9664\uFF1Bsecret \u73AF\u5883\u53D8\u91CF\u503C\u4E0D\u4F1A\u5BFC\u51FA\uFF08configured \u6807\u8BB0\uFF09\uFF0C\u7559\u7A7A\u5219\u4FDD\u7559\u539F\u503C\u3002",
|
|
16136
|
+
serversJsonReseed: "\u91CD\u65B0\u5BFC\u51FA",
|
|
16137
|
+
serversJsonApply: "\u5E94\u7528",
|
|
16138
|
+
serversJsonSaving: "\u5E94\u7528\u4E2D\u2026",
|
|
16139
|
+
serversJsonDone: "\u5DF2\u5E94\u7528",
|
|
16140
|
+
globalEnv: "\u8FDB\u7A0B\u73AF\u5883\u53D8\u91CF",
|
|
16141
|
+
globalEnvHint: "\u8FDB\u7A0B\u7EA7\u73AF\u5883\u53D8\u91CF\uFF0C\u4F9B\u6240\u6709 MCP \u670D\u52A1\u5668\u7684\u8BF7\u6C42\u5934\u66FF\u6362\u5F15\u7528\uFF08headers \u503C\u5199 ${\u53D8\u91CF\u540D} \u6216\u76F4\u63A5\u5199\u53D8\u91CF\u540D\uFF09\u3002secret \u503C\u5199\u5165\u51ED\u636E\u6587\u6863\uFF0C\u4E0D\u5728\u6B64\u660E\u6587\u663E\u793A\uFF1B\u7559\u7A7A\u4FDD\u7559\u539F\u503C\u3002",
|
|
16142
|
+
globalEnvName: "\u53D8\u91CF\u540D",
|
|
16143
|
+
globalEnvValue: "\u503C",
|
|
16144
|
+
globalEnvSecret: "\u79C1\u5BC6",
|
|
16145
|
+
globalEnvSecretHint: "\u503C\u53EA\u5199\uFF0C\u4FDD\u5B58\u540E\u4E0D\u53EF\u89C1\uFF1B\u7559\u7A7A\u8868\u793A\u4FDD\u7559\u539F\u503C",
|
|
16146
|
+
globalEnvAdd: "\u6DFB\u52A0\u53D8\u91CF",
|
|
16147
|
+
globalEnvBulk: "\u6279\u91CF\u6DFB\u52A0",
|
|
16148
|
+
globalEnvBulkPrompt: "\u6BCF\u884C\u4E00\u4E2A\u53D8\u91CF\uFF0C\u683C\u5F0F NAME=value\uFF1B\u53EA\u586B NAME \u7684\u884C\u5C06\u4F5C\u4E3A\u4EC5\u53D8\u91CF\u540D\u884C\u6DFB\u52A0\u3002",
|
|
16149
|
+
globalEnvBulkOk: "\u6DFB\u52A0",
|
|
16150
|
+
globalEnvSave: "\u4FDD\u5B58",
|
|
16151
|
+
globalEnvSaving: "\u4FDD\u5B58\u4E2D\u2026",
|
|
16152
|
+
globalEnvRemove: "\u79FB\u9664\u8BE5\u53D8\u91CF",
|
|
16153
|
+
globalEnvEmpty: "\uFF08\u6682\u65E0\u8FDB\u7A0B\u73AF\u5883\u53D8\u91CF\uFF09",
|
|
16154
|
+
globalEnvLoadFailed: "\u8BFB\u53D6\u73AF\u5883\u53D8\u91CF\u5931\u8D25",
|
|
16155
|
+
globalEnvRetry: "\u91CD\u8BD5",
|
|
16156
|
+
globalEnvDone: "\u5DF2\u4FDD\u5B58",
|
|
16157
|
+
configTitle: "MCP \u914D\u7F6E"
|
|
15694
16158
|
};
|
|
15695
16159
|
var en = {
|
|
15696
16160
|
nav: "MCP",
|
|
@@ -15715,9 +16179,9 @@ var en = {
|
|
|
15715
16179
|
url: "Server URL",
|
|
15716
16180
|
urlPlaceholder: "e.g. http://localhost:3000/mcp",
|
|
15717
16181
|
headers: "Headers",
|
|
15718
|
-
headersPlaceholder: 'One "Name: value" per line',
|
|
16182
|
+
headersPlaceholder: 'One "Name: value" per line; values support ${ENV} substitution',
|
|
15719
16183
|
envVars: "Environment variables",
|
|
15720
|
-
envHint: "
|
|
16184
|
+
envHint: "stdio: injected into the child process; HTTP: used for ${VAR} substitution in headers (e.g. Authorization: Bearer ${TOKEN}). Secret values are stored in the credentials document, never shown here",
|
|
15721
16185
|
envName: "Name",
|
|
15722
16186
|
envValue: "Value",
|
|
15723
16187
|
envSecret: "secret",
|
|
@@ -15763,9 +16227,150 @@ var en = {
|
|
|
15763
16227
|
refresh: "Refresh",
|
|
15764
16228
|
refreshing: "Refreshing\u2026",
|
|
15765
16229
|
toolsExpand: "Expand tools",
|
|
15766
|
-
toolsCollapse: "Collapse tools"
|
|
16230
|
+
toolsCollapse: "Collapse tools",
|
|
16231
|
+
serversJson: "JSON config editor",
|
|
16232
|
+
serversJsonLabel: "Server-config JSON",
|
|
16233
|
+
serversJsonHint: "The whole MCP server list (array): applying replaces the list \u2014 listed servers are created/updated, existing servers absent from the document are removed; secret env values are never exported (a configured flag marks them), a blank value keeps the stored one.",
|
|
16234
|
+
serversJsonReseed: "Re-export",
|
|
16235
|
+
serversJsonApply: "Apply",
|
|
16236
|
+
serversJsonSaving: "Applying\u2026",
|
|
16237
|
+
serversJsonDone: "Applied",
|
|
16238
|
+
globalEnv: "Process env vars",
|
|
16239
|
+
globalEnvHint: "Process-level environment variables referenced by every server's header substitution (write ${NAME} or a bare name in a header value). Secret values are stored in the credentials document, never shown here; blank keeps the stored value.",
|
|
16240
|
+
globalEnvName: "Name",
|
|
16241
|
+
globalEnvValue: "Value",
|
|
16242
|
+
globalEnvSecret: "secret",
|
|
16243
|
+
globalEnvSecretHint: "Write-only; a blank value keeps the stored one",
|
|
16244
|
+
globalEnvAdd: "Add variable",
|
|
16245
|
+
globalEnvBulk: "Add many",
|
|
16246
|
+
globalEnvBulkPrompt: "One variable per line, as NAME=value; a bare NAME adds a name-only row.",
|
|
16247
|
+
globalEnvBulkOk: "Add",
|
|
16248
|
+
globalEnvSave: "Save",
|
|
16249
|
+
globalEnvSaving: "Saving\u2026",
|
|
16250
|
+
globalEnvRemove: "Remove this variable",
|
|
16251
|
+
globalEnvEmpty: "(no process env vars)",
|
|
16252
|
+
globalEnvLoadFailed: "Failed to read environment variables",
|
|
16253
|
+
globalEnvRetry: "Retry",
|
|
16254
|
+
globalEnvDone: "Saved",
|
|
16255
|
+
configTitle: "MCP config"
|
|
15767
16256
|
};
|
|
15768
16257
|
|
|
16258
|
+
// src/client/mcp-store.ts
|
|
16259
|
+
var import_client = require("@deepseek-ai/dsh-client-runtime/client");
|
|
16260
|
+
var DEFAULT_TOOL_CALL_TIMEOUT_MS = 6e4;
|
|
16261
|
+
function emptyDraft() {
|
|
16262
|
+
return {
|
|
16263
|
+
id: null,
|
|
16264
|
+
serverName: "",
|
|
16265
|
+
transport: "stdio",
|
|
16266
|
+
enabled: true,
|
|
16267
|
+
command: "",
|
|
16268
|
+
argsText: "",
|
|
16269
|
+
cwd: "",
|
|
16270
|
+
url: "",
|
|
16271
|
+
headersText: "",
|
|
16272
|
+
toolCallTimeoutMs: String(DEFAULT_TOOL_CALL_TIMEOUT_MS),
|
|
16273
|
+
// Reject the mount by default when the startup connection fails, so a
|
|
16274
|
+
// broken server never registers stale tools.
|
|
16275
|
+
failOnStartupError: true
|
|
16276
|
+
};
|
|
16277
|
+
}
|
|
16278
|
+
function draftFromServer(server) {
|
|
16279
|
+
return {
|
|
16280
|
+
id: server.id,
|
|
16281
|
+
serverName: server.serverName,
|
|
16282
|
+
transport: server.transport,
|
|
16283
|
+
enabled: server.enabled,
|
|
16284
|
+
command: server.command,
|
|
16285
|
+
argsText: server.args.join("\n"),
|
|
16286
|
+
cwd: server.cwd,
|
|
16287
|
+
url: server.url,
|
|
16288
|
+
headersText: server.headers.map((header) => `${header.name}: ${header.value}`).join("\n"),
|
|
16289
|
+
toolCallTimeoutMs: String(server.toolCallTimeoutMs),
|
|
16290
|
+
failOnStartupError: server.failOnStartupError
|
|
16291
|
+
};
|
|
16292
|
+
}
|
|
16293
|
+
function parseLines(text) {
|
|
16294
|
+
return text.split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
|
|
16295
|
+
}
|
|
16296
|
+
function parseHeaders(text) {
|
|
16297
|
+
const headers = [];
|
|
16298
|
+
for (const line of parseLines(text)) {
|
|
16299
|
+
const separator = line.indexOf(":");
|
|
16300
|
+
if (separator <= 0) continue;
|
|
16301
|
+
const name = line.slice(0, separator).trim();
|
|
16302
|
+
const value = line.slice(separator + 1).trim();
|
|
16303
|
+
if (name.length > 0) headers.push({ name, value });
|
|
16304
|
+
}
|
|
16305
|
+
return headers;
|
|
16306
|
+
}
|
|
16307
|
+
function parseTimeout(text) {
|
|
16308
|
+
const value = Number(text);
|
|
16309
|
+
return Number.isInteger(value) && value > 0 ? value : DEFAULT_TOOL_CALL_TIMEOUT_MS;
|
|
16310
|
+
}
|
|
16311
|
+
function draftToSubmission(draft) {
|
|
16312
|
+
return {
|
|
16313
|
+
server: {
|
|
16314
|
+
serverName: draft.serverName.trim(),
|
|
16315
|
+
transport: draft.transport,
|
|
16316
|
+
enabled: draft.enabled,
|
|
16317
|
+
command: draft.command.trim(),
|
|
16318
|
+
args: parseLines(draft.argsText),
|
|
16319
|
+
cwd: draft.cwd.trim(),
|
|
16320
|
+
url: draft.url.trim(),
|
|
16321
|
+
headers: parseHeaders(draft.headersText),
|
|
16322
|
+
toolCallTimeoutMs: parseTimeout(draft.toolCallTimeoutMs),
|
|
16323
|
+
failOnStartupError: draft.failOnStartupError
|
|
16324
|
+
}
|
|
16325
|
+
};
|
|
16326
|
+
}
|
|
16327
|
+
function createMcpManagerStore() {
|
|
16328
|
+
return (0, import_client.defineStore)({
|
|
16329
|
+
init: () => ({
|
|
16330
|
+
loadState: "loading",
|
|
16331
|
+
servers: [],
|
|
16332
|
+
draft: null,
|
|
16333
|
+
busy: null,
|
|
16334
|
+
testRunning: false,
|
|
16335
|
+
test: null
|
|
16336
|
+
}),
|
|
16337
|
+
actions: {
|
|
16338
|
+
setLoadState: (d, state) => {
|
|
16339
|
+
d.loadState = state;
|
|
16340
|
+
},
|
|
16341
|
+
setServers: (d, servers) => {
|
|
16342
|
+
d.servers = servers;
|
|
16343
|
+
},
|
|
16344
|
+
beginCreate: (d) => {
|
|
16345
|
+
d.draft = emptyDraft();
|
|
16346
|
+
d.test = null;
|
|
16347
|
+
},
|
|
16348
|
+
beginEdit: (d, server) => {
|
|
16349
|
+
d.draft = draftFromServer(server);
|
|
16350
|
+
d.test = null;
|
|
16351
|
+
},
|
|
16352
|
+
cancelEdit: (d) => {
|
|
16353
|
+
d.draft = null;
|
|
16354
|
+
d.test = null;
|
|
16355
|
+
d.busy = null;
|
|
16356
|
+
},
|
|
16357
|
+
updateDraft: (d, patch) => {
|
|
16358
|
+
if (d.draft === null) return;
|
|
16359
|
+
d.draft = { ...d.draft, ...patch };
|
|
16360
|
+
},
|
|
16361
|
+
setBusy: (d, busy) => {
|
|
16362
|
+
d.busy = busy;
|
|
16363
|
+
},
|
|
16364
|
+
setTestRunning: (d, running) => {
|
|
16365
|
+
d.testRunning = running;
|
|
16366
|
+
},
|
|
16367
|
+
setTest: (d, test) => {
|
|
16368
|
+
d.test = test;
|
|
16369
|
+
}
|
|
16370
|
+
}
|
|
16371
|
+
});
|
|
16372
|
+
}
|
|
16373
|
+
|
|
15769
16374
|
// src/client/index.ts
|
|
15770
16375
|
var NS = "settings.mcp";
|
|
15771
16376
|
var inject = ["slots", "locale", "remote"];
|
|
@@ -15794,8 +16399,7 @@ async function apply(ctx) {
|
|
|
15794
16399
|
const submission = draftToSubmission(draft);
|
|
15795
16400
|
const result = await manager.upsert({
|
|
15796
16401
|
...draft.id === null ? {} : { id: draft.id },
|
|
15797
|
-
server: submission.server
|
|
15798
|
-
env: submission.env
|
|
16402
|
+
server: submission.server
|
|
15799
16403
|
});
|
|
15800
16404
|
if (result.ok) return null;
|
|
15801
16405
|
return failureOf(result.error);
|
|
@@ -15805,12 +16409,15 @@ async function apply(ctx) {
|
|
|
15805
16409
|
if (result.ok) return null;
|
|
15806
16410
|
return failureOf(result.error);
|
|
15807
16411
|
},
|
|
16412
|
+
upsertJson: async (servers) => {
|
|
16413
|
+
const result = await unwrap(() => manager.upsertJson({ servers }));
|
|
16414
|
+
return { added: result.added, updated: result.updated, removed: result.removed, servers: result.servers };
|
|
16415
|
+
},
|
|
15808
16416
|
test: async (draft) => {
|
|
15809
16417
|
const submission = draftToSubmission(draft);
|
|
15810
16418
|
const result = await unwrap(() => manager.test({
|
|
15811
16419
|
...draft.id === null ? {} : { id: draft.id },
|
|
15812
|
-
server: submission.server
|
|
15813
|
-
env: submission.env
|
|
16420
|
+
server: submission.server
|
|
15814
16421
|
}));
|
|
15815
16422
|
return { probe: result.probe, elapsedMs: result.elapsedMs };
|
|
15816
16423
|
},
|
|
@@ -15825,6 +16432,14 @@ async function apply(ctx) {
|
|
|
15825
16432
|
toolsMode: async (request) => {
|
|
15826
16433
|
const result = await unwrap(() => manager.toolsMode({ mode: request.mode }));
|
|
15827
16434
|
return { ok: result.ok };
|
|
16435
|
+
},
|
|
16436
|
+
envList: async () => {
|
|
16437
|
+
const result = await unwrap(() => manager.envList());
|
|
16438
|
+
return { vars: result.vars };
|
|
16439
|
+
},
|
|
16440
|
+
envSet: async (vars) => {
|
|
16441
|
+
const result = await unwrap(() => manager.envSet({ vars }));
|
|
16442
|
+
return { vars: result.vars };
|
|
15828
16443
|
}
|
|
15829
16444
|
});
|
|
15830
16445
|
ctx.slots.inject("settings.section", () => ctx.slots.register({
|