reasonix 0.26.0 → 0.27.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/README.md +113 -67
- package/README.zh-CN.md +115 -69
- package/dashboard/app.css +14 -3
- package/dashboard/dist/app.js +315 -21
- package/dashboard/dist/app.js.map +1 -1
- package/dist/cli/index.js +2229 -905
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +68 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dashboard/dist/app.js
CHANGED
|
@@ -19013,7 +19013,33 @@ var en = {
|
|
|
19013
19013
|
promptsTitle: "Prompts \xB7 {count}",
|
|
19014
19014
|
colName: "name",
|
|
19015
19015
|
colDesc: "description",
|
|
19016
|
-
colUri: "uri"
|
|
19016
|
+
colUri: "uri",
|
|
19017
|
+
marketplace: "marketplace",
|
|
19018
|
+
marketplaceSearch: "search the registry\u2026",
|
|
19019
|
+
marketplaceLoading: "loading registry\u2026",
|
|
19020
|
+
marketplaceMore: "load 5 more pages",
|
|
19021
|
+
marketplaceMoreLabel: "load 50 more \xB7 showing {shown} / {total}",
|
|
19022
|
+
marketplaceMoreHint: "fetches more pages from the registry",
|
|
19023
|
+
marketplaceMoreCachedHint: "more entries already cached locally",
|
|
19024
|
+
marketplaceExhausted: "all pages loaded",
|
|
19025
|
+
marketplaceExhaustedFull: "showing all {total} entries \u2014 registry exhausted",
|
|
19026
|
+
marketplaceCount: "{loaded} loaded \xB7 {matched} match \xB7 source: {source}{cached}",
|
|
19027
|
+
marketplaceCachedSuffix: " \xB7 cached",
|
|
19028
|
+
marketplaceNoMatches: "No matches. Try different terms or load more pages.",
|
|
19029
|
+
marketplaceInstall: "Install",
|
|
19030
|
+
marketplacePickHint: "Pick a server on the left, then Install.",
|
|
19031
|
+
marketplaceInstalled: "installed \u2192 {spec}",
|
|
19032
|
+
marketplaceInstalledBridged: "installed + bridged \u2192 {spec}",
|
|
19033
|
+
marketplaceAlready: "already installed",
|
|
19034
|
+
marketplaceNeedsEnv: "needs env: {names}",
|
|
19035
|
+
marketplaceSourceTag: "[{source}]",
|
|
19036
|
+
marketplaceNoInstall: "smithery listing \u2014 install metadata not exposed; use `npx -y @smithery/cli install {name}` directly",
|
|
19037
|
+
marketplaceFetchOnInstall: "Smithery listing \u2014 install detail fetched on Install. http servers map to streamable-http remotes; stdio servers run via @smithery/cli.",
|
|
19038
|
+
marketplaceInstalledBadge: "installed",
|
|
19039
|
+
marketplaceUninstall: "Uninstall",
|
|
19040
|
+
marketplaceEnvTitle: "Required environment variables",
|
|
19041
|
+
marketplaceEnvHint: "Set these in your shell before next `reasonix code` so the bridged server can authenticate.",
|
|
19042
|
+
marketplaceRestartHint: "Spec written to ~/.reasonix/config.json. Restart `reasonix code` to bridge the server (live hot-reload is on the roadmap)."
|
|
19017
19043
|
},
|
|
19018
19044
|
memory: {
|
|
19019
19045
|
loading: "loading memory\u2026",
|
|
@@ -19500,7 +19526,33 @@ var zhCN = {
|
|
|
19500
19526
|
promptsTitle: "\u63D0\u793A \xB7 {count}",
|
|
19501
19527
|
colName: "\u540D\u79F0",
|
|
19502
19528
|
colDesc: "\u63CF\u8FF0",
|
|
19503
|
-
colUri: "URI"
|
|
19529
|
+
colUri: "URI",
|
|
19530
|
+
marketplace: "\u5E02\u573A",
|
|
19531
|
+
marketplaceSearch: "\u641C\u7D22\u6CE8\u518C\u8868\u2026",
|
|
19532
|
+
marketplaceLoading: "\u52A0\u8F7D\u6CE8\u518C\u8868\u2026",
|
|
19533
|
+
marketplaceMore: "\u518D\u52A0\u8F7D 5 \u9875",
|
|
19534
|
+
marketplaceMoreLabel: "\u518D\u52A0\u8F7D 50 \u6761 \xB7 \u5F53\u524D {shown} / {total}",
|
|
19535
|
+
marketplaceMoreHint: "\u9700\u8981\u4ECE\u8FDC\u7AEF\u6CE8\u518C\u8868\u518D\u62C9\u51E0\u9875",
|
|
19536
|
+
marketplaceMoreCachedHint: "\u672C\u5730\u7F13\u5B58\u5DF2\u6709\u66F4\u591A\u6761\u76EE",
|
|
19537
|
+
marketplaceExhausted: "\u5DF2\u52A0\u8F7D\u5168\u90E8\u9875",
|
|
19538
|
+
marketplaceExhaustedFull: "\u5DF2\u5C55\u793A\u5168\u90E8 {total} \u6761 \u2014 \u6CE8\u518C\u8868\u8017\u5C3D",
|
|
19539
|
+
marketplaceCount: "\u5DF2\u8F7D\u5165 {loaded} \xB7 \u5339\u914D {matched} \xB7 \u6765\u6E90\uFF1A{source}{cached}",
|
|
19540
|
+
marketplaceCachedSuffix: " \xB7 \u7F13\u5B58\u4E2D",
|
|
19541
|
+
marketplaceNoMatches: "\u65E0\u5339\u914D\u7ED3\u679C\u3002\u6362\u5173\u952E\u8BCD\u6216\u52A0\u8F7D\u66F4\u591A\u9875\u3002",
|
|
19542
|
+
marketplaceInstall: "\u5B89\u88C5",
|
|
19543
|
+
marketplacePickHint: "\u5728\u5DE6\u4FA7\u9009\u62E9\u670D\u52A1\u5668\uFF0C\u7136\u540E\u70B9\u5B89\u88C5\u3002",
|
|
19544
|
+
marketplaceInstalled: "\u5DF2\u5B89\u88C5 \u2192 {spec}",
|
|
19545
|
+
marketplaceInstalledBridged: "\u5DF2\u5B89\u88C5\u5E76\u6865\u63A5 \u2192 {spec}",
|
|
19546
|
+
marketplaceAlready: "\u5DF2\u5B89\u88C5\u8FC7",
|
|
19547
|
+
marketplaceNeedsEnv: "\u9700\u8BBE\u7F6E\u73AF\u5883\u53D8\u91CF\uFF1A{names}",
|
|
19548
|
+
marketplaceSourceTag: "[{source}]",
|
|
19549
|
+
marketplaceNoInstall: "Smithery \u5217\u8868\u9879 \u2014 \u4E0D\u66B4\u9732\u5B89\u88C5\u5143\u6570\u636E\uFF1B\u8BF7\u76F4\u63A5 `npx -y @smithery/cli install {name}`",
|
|
19550
|
+
marketplaceFetchOnInstall: "Smithery \u5217\u8868 \u2014 \u5B89\u88C5\u65F6\u518D\u62C9\u8BE6\u60C5\u3002HTTP \u670D\u52A1\u6620\u5C04\u4E3A streamable-http \u8FDC\u7AEF\uFF1Bstdio \u670D\u52A1\u901A\u8FC7 @smithery/cli \u8FD0\u884C\u3002",
|
|
19551
|
+
marketplaceInstalledBadge: "\u5DF2\u5B89\u88C5",
|
|
19552
|
+
marketplaceUninstall: "\u5378\u8F7D",
|
|
19553
|
+
marketplaceEnvTitle: "\u5FC5\u9700\u7684\u73AF\u5883\u53D8\u91CF",
|
|
19554
|
+
marketplaceEnvHint: "\u4E0B\u6B21\u542F\u52A8 `reasonix code` \u4E4B\u524D\u5728 shell \u91CC\u8BBE\u597D\uFF0C\u6865\u63A5\u7684\u670D\u52A1\u5668\u624D\u80FD\u6B63\u5E38\u9274\u6743\u3002",
|
|
19555
|
+
marketplaceRestartHint: "\u5DF2\u5199\u5165 ~/.reasonix/config.json\u3002\u91CD\u542F `reasonix code` \u540E\u670D\u52A1\u5668\u624D\u4F1A\u771F\u6B63\u6865\u63A5\uFF08\u70ED\u91CD\u8F7D\u5728\u8DEF\u7EBF\u56FE\u4E0A\uFF09\u3002"
|
|
19504
19556
|
},
|
|
19505
19557
|
memory: {
|
|
19506
19558
|
loading: "\u52A0\u8F7D\u8BB0\u5FC6\u2026",
|
|
@@ -23432,6 +23484,24 @@ function HooksPanel() {
|
|
|
23432
23484
|
}
|
|
23433
23485
|
|
|
23434
23486
|
// dashboard/src/panels/mcp.ts
|
|
23487
|
+
function specForEntry(e3) {
|
|
23488
|
+
if (!e3.install) return null;
|
|
23489
|
+
const localName = e3.name.split("/").pop() ?? e3.name;
|
|
23490
|
+
const safe = localName.replace(/[^a-zA-Z0-9_-]/g, "-").replace(/^-+|-+$/g, "") || "mcp";
|
|
23491
|
+
const trail = e3.install.extraArgs?.length ? ` ${e3.install.extraArgs.join(" ")}` : "";
|
|
23492
|
+
if (e3.install.runtime === "remote" && e3.install.url) {
|
|
23493
|
+
if (e3.install.transport === "streamable-http") return `${safe}=streamable+${e3.install.url}`;
|
|
23494
|
+
return `${safe}=${e3.install.url}`;
|
|
23495
|
+
}
|
|
23496
|
+
if (e3.install.runtime === "npm" && e3.install.packageId) {
|
|
23497
|
+
const pinned = e3.install.version ? `${e3.install.packageId}@${e3.install.version}` : e3.install.packageId;
|
|
23498
|
+
return `${safe}=npx -y ${pinned}${trail}`;
|
|
23499
|
+
}
|
|
23500
|
+
if (e3.install.runtime === "pypi" && e3.install.packageId) {
|
|
23501
|
+
return `${safe}=uvx ${e3.install.packageId}${trail}`;
|
|
23502
|
+
}
|
|
23503
|
+
return null;
|
|
23504
|
+
}
|
|
23435
23505
|
function specLabel(spec) {
|
|
23436
23506
|
const eq = spec.indexOf("=");
|
|
23437
23507
|
return eq > 0 ? spec.slice(0, eq) : spec;
|
|
@@ -23451,6 +23521,57 @@ function McpPanel() {
|
|
|
23451
23521
|
const [open, setOpen] = p2(null);
|
|
23452
23522
|
const [openUnbridged, setOpenUnbridged] = p2(null);
|
|
23453
23523
|
const [filter, setFilter] = p2("all");
|
|
23524
|
+
const [registry, setRegistry] = p2(null);
|
|
23525
|
+
const [registryQuery, setRegistryQuery] = p2("");
|
|
23526
|
+
const [registryLoading, setRegistryLoading] = p2(false);
|
|
23527
|
+
const [openRegistry, setOpenRegistry] = p2(null);
|
|
23528
|
+
const [displayLimit, setDisplayLimit] = p2(50);
|
|
23529
|
+
const loadRegistry = x2(async (q3, pages, limit) => {
|
|
23530
|
+
setRegistryLoading(true);
|
|
23531
|
+
try {
|
|
23532
|
+
const params = new URLSearchParams();
|
|
23533
|
+
if (q3.trim()) params.set("q", q3.trim());
|
|
23534
|
+
params.set("pages", String(pages));
|
|
23535
|
+
params.set("maxPages", String(Math.max(20, pages)));
|
|
23536
|
+
params.set("limit", String(limit));
|
|
23537
|
+
const r3 = await api(`/mcp/registry?${params.toString()}`);
|
|
23538
|
+
setRegistry(r3);
|
|
23539
|
+
} catch (err) {
|
|
23540
|
+
setError(err.message);
|
|
23541
|
+
} finally {
|
|
23542
|
+
setRegistryLoading(false);
|
|
23543
|
+
}
|
|
23544
|
+
}, []);
|
|
23545
|
+
_2(() => {
|
|
23546
|
+
if (filter !== "marketplace") return;
|
|
23547
|
+
if (registry) return;
|
|
23548
|
+
void loadRegistry("", 1, displayLimit);
|
|
23549
|
+
}, [filter, registry, loadRegistry, displayLimit]);
|
|
23550
|
+
_2(() => {
|
|
23551
|
+
if (filter !== "marketplace") return;
|
|
23552
|
+
setDisplayLimit(50);
|
|
23553
|
+
const handle = setTimeout(() => void loadRegistry(registryQuery, 1, 50), 300);
|
|
23554
|
+
return () => clearTimeout(handle);
|
|
23555
|
+
}, [registryQuery, filter, loadRegistry]);
|
|
23556
|
+
const installFromRegistry = x2(async (entry) => {
|
|
23557
|
+
setBusy(true);
|
|
23558
|
+
try {
|
|
23559
|
+
const r3 = await api("/mcp/registry/install", { method: "POST", body: { name: entry.name } });
|
|
23560
|
+
if (r3.alreadyPresent) {
|
|
23561
|
+
setInfo(t4("mcp.marketplaceAlready"));
|
|
23562
|
+
} else if (r3.bridged) {
|
|
23563
|
+
setInfo(t4("mcp.marketplaceInstalledBridged", { spec: r3.spec }));
|
|
23564
|
+
} else {
|
|
23565
|
+
setInfo(t4("mcp.marketplaceInstalled", { spec: r3.spec }));
|
|
23566
|
+
}
|
|
23567
|
+
setTimeout(() => setInfo(null), 5e3);
|
|
23568
|
+
await load();
|
|
23569
|
+
} catch (err) {
|
|
23570
|
+
setError(err.message);
|
|
23571
|
+
} finally {
|
|
23572
|
+
setBusy(false);
|
|
23573
|
+
}
|
|
23574
|
+
}, []);
|
|
23454
23575
|
const load = x2(async () => {
|
|
23455
23576
|
try {
|
|
23456
23577
|
setData(await api("/mcp"));
|
|
@@ -23470,9 +23591,7 @@ function McpPanel() {
|
|
|
23470
23591
|
method: "POST",
|
|
23471
23592
|
body: { spec: newSpec.trim() }
|
|
23472
23593
|
});
|
|
23473
|
-
setInfo(
|
|
23474
|
-
r3.requiresRestart ? t4("mcp.savedRestart") : t4("mcp.saved")
|
|
23475
|
-
);
|
|
23594
|
+
setInfo(r3.requiresRestart ? t4("mcp.savedRestart") : t4("mcp.saved"));
|
|
23476
23595
|
setTimeout(() => setInfo(null), 4e3);
|
|
23477
23596
|
setNewSpec("");
|
|
23478
23597
|
await load();
|
|
@@ -23499,14 +23618,16 @@ function McpPanel() {
|
|
|
23499
23618
|
},
|
|
23500
23619
|
[load]
|
|
23501
23620
|
);
|
|
23502
|
-
if (!data && !error)
|
|
23621
|
+
if (!data && !error)
|
|
23622
|
+
return html4`<div class="card" style="color:var(--fg-3)">${t4("mcp.loading")}</div>`;
|
|
23503
23623
|
if (error && !data) return html4`<div class="card accent-err">${error}</div>`;
|
|
23504
23624
|
if (!data) return null;
|
|
23505
23625
|
const liveCount = data.servers.length;
|
|
23506
23626
|
const unbridgedSpecs = (specs ?? []).filter((spec) => !data.servers.some((s3) => s3.spec === spec));
|
|
23507
23627
|
const unbridgedCount = unbridgedSpecs.length;
|
|
23508
|
-
const showLive = filter
|
|
23509
|
-
const showUnbridged = filter
|
|
23628
|
+
const showLive = filter === "all" || filter === "live";
|
|
23629
|
+
const showUnbridged = filter === "all" || filter === "unbridged";
|
|
23630
|
+
const showMarketplace = filter === "marketplace";
|
|
23510
23631
|
return html4`
|
|
23511
23632
|
<div class="sessions-grid">
|
|
23512
23633
|
<div class="sessions-list">
|
|
@@ -23518,25 +23639,63 @@ function McpPanel() {
|
|
|
23518
23639
|
<span class=${`chip-f ${filter === "all" ? "active" : ""}`} onClick=${() => setFilter("all")}>${t4("mcp.all")} <span class="ct">${liveCount + unbridgedCount}</span></span>
|
|
23519
23640
|
<span class=${`chip-f ${filter === "live" ? "active" : ""}`} onClick=${() => setFilter("live")}>${t4("mcp.live")} <span class="ct">${liveCount}</span></span>
|
|
23520
23641
|
<span class=${`chip-f ${filter === "unbridged" ? "active" : ""}`} onClick=${() => setFilter("unbridged")}>${t4("mcp.unbridged")} <span class="ct">${unbridgedCount}</span></span>
|
|
23642
|
+
<span class=${`chip-f ${filter === "marketplace" ? "active" : ""}`} onClick=${() => setFilter("marketplace")}>${t4("mcp.marketplace")}</span>
|
|
23521
23643
|
</div>
|
|
23522
23644
|
</div>
|
|
23523
|
-
|
|
23524
|
-
|
|
23525
|
-
|
|
23526
|
-
|
|
23527
|
-
|
|
23528
|
-
|
|
23529
|
-
|
|
23530
|
-
|
|
23531
|
-
|
|
23532
|
-
|
|
23645
|
+
${showMarketplace ? html4`
|
|
23646
|
+
<div style="padding:8px 12px;display:flex;gap:6px">
|
|
23647
|
+
<input
|
|
23648
|
+
type="text"
|
|
23649
|
+
placeholder=${t4("mcp.marketplaceSearch")}
|
|
23650
|
+
value=${registryQuery}
|
|
23651
|
+
onInput=${(e3) => setRegistryQuery(e3.target.value)}
|
|
23652
|
+
style="flex:1;font-size:11px"
|
|
23653
|
+
/>
|
|
23654
|
+
</div>
|
|
23655
|
+
${registry ? html4`<div style="padding:0 12px 6px;font-size:11px;color:var(--fg-3)">
|
|
23656
|
+
${t4("mcp.marketplaceCount", {
|
|
23657
|
+
loaded: registry.loaded,
|
|
23658
|
+
matched: registry.matched,
|
|
23659
|
+
source: registry.source,
|
|
23660
|
+
cached: registry.fromCache ? t4("mcp.marketplaceCachedSuffix") : ""
|
|
23661
|
+
})}
|
|
23662
|
+
</div>` : null}
|
|
23663
|
+
` : html4`
|
|
23664
|
+
<div style="padding:8px 12px;display:flex;gap:6px">
|
|
23665
|
+
<input
|
|
23666
|
+
type="text"
|
|
23667
|
+
placeholder=${t4("mcp.specPlaceholder")}
|
|
23668
|
+
value=${newSpec}
|
|
23669
|
+
onInput=${(e3) => setNewSpec(e3.target.value)}
|
|
23670
|
+
style="flex:1;font-size:11px"
|
|
23671
|
+
/>
|
|
23672
|
+
<button class="btn primary" disabled=${busy || !newSpec.trim()} onClick=${addSpec}>+</button>
|
|
23673
|
+
</div>
|
|
23674
|
+
`}
|
|
23533
23675
|
${info ? html4`<div style="padding:0 12px 8px"><span class="pill ok">${info}</span></div>` : null}
|
|
23534
23676
|
${error ? html4`<div class="card accent-err" style="margin:0 12px 8px">${error}</div>` : null}
|
|
23535
23677
|
|
|
23536
23678
|
<div class="ssl-rows">
|
|
23537
|
-
${liveCount === 0 && unbridgedCount === 0 ? html4`<div style="color:var(--fg-3);padding:14px;font-size:12px">
|
|
23679
|
+
${!showMarketplace && liveCount === 0 && unbridgedCount === 0 ? html4`<div style="color:var(--fg-3);padding:14px;font-size:12px">
|
|
23538
23680
|
${t4("mcp.noServers")}
|
|
23539
23681
|
</div>` : null}
|
|
23682
|
+
${showMarketplace ? renderMarketplaceRows({
|
|
23683
|
+
registry,
|
|
23684
|
+
registryLoading,
|
|
23685
|
+
openRegistry,
|
|
23686
|
+
setOpenRegistry: (e3) => {
|
|
23687
|
+
setOpenRegistry(e3);
|
|
23688
|
+
setOpen(null);
|
|
23689
|
+
setOpenUnbridged(null);
|
|
23690
|
+
},
|
|
23691
|
+
loadMore: () => {
|
|
23692
|
+
const nextLimit = displayLimit + 50;
|
|
23693
|
+
setDisplayLimit(nextLimit);
|
|
23694
|
+
const pagesNeeded = Math.ceil(nextLimit / 30) + 3;
|
|
23695
|
+
void loadRegistry(registryQuery, pagesNeeded, nextLimit);
|
|
23696
|
+
},
|
|
23697
|
+
installedSpecs: new Set(specs ?? [])
|
|
23698
|
+
}) : null}
|
|
23540
23699
|
${showLive ? data.servers.map(
|
|
23541
23700
|
(s3) => html4`
|
|
23542
23701
|
<div
|
|
@@ -23571,7 +23730,17 @@ function McpPanel() {
|
|
|
23571
23730
|
</div>
|
|
23572
23731
|
|
|
23573
23732
|
<div class="sessions-detail">
|
|
23574
|
-
${
|
|
23733
|
+
${openRegistry != null ? renderRegistryDetail({
|
|
23734
|
+
entry: openRegistry,
|
|
23735
|
+
busy,
|
|
23736
|
+
installedSpec: (() => {
|
|
23737
|
+
const spec = specForEntry(openRegistry);
|
|
23738
|
+
return spec && (specs ?? []).includes(spec) ? spec : null;
|
|
23739
|
+
})(),
|
|
23740
|
+
onInstall: () => installFromRegistry(openRegistry),
|
|
23741
|
+
onUninstall: (spec) => removeSpec(spec),
|
|
23742
|
+
onClose: () => setOpenRegistry(null)
|
|
23743
|
+
}) : openUnbridged != null ? html4`
|
|
23575
23744
|
<div class="sessions-detail-h">
|
|
23576
23745
|
<span class="name">${specLabel(openUnbridged)}</span>
|
|
23577
23746
|
<span class="ws"><span class="pill">${t4("mcp.unbridgedTitle")}</span></span>
|
|
@@ -23595,7 +23764,7 @@ function McpPanel() {
|
|
|
23595
23764
|
</div>
|
|
23596
23765
|
</div>
|
|
23597
23766
|
` : open == null ? html4`<div style="color:var(--fg-3);font-size:13px;text-align:center;padding:60px 20px">
|
|
23598
|
-
${t4("mcp.pickHint")}
|
|
23767
|
+
${showMarketplace ? t4("mcp.marketplacePickHint") : t4("mcp.pickHint")}
|
|
23599
23768
|
</div>` : html4`
|
|
23600
23769
|
<div class="sessions-detail-h">
|
|
23601
23770
|
<span class="name">${open.label}</span>
|
|
@@ -23664,6 +23833,131 @@ function McpPanel() {
|
|
|
23664
23833
|
</div>
|
|
23665
23834
|
`;
|
|
23666
23835
|
}
|
|
23836
|
+
function renderLoadMoreFooter({
|
|
23837
|
+
registry,
|
|
23838
|
+
registryLoading,
|
|
23839
|
+
loadMore
|
|
23840
|
+
}) {
|
|
23841
|
+
if (!registry) return null;
|
|
23842
|
+
const shown = registry.entries.length;
|
|
23843
|
+
const total = registry.matched;
|
|
23844
|
+
const moreCached = total > shown;
|
|
23845
|
+
const moreOnNetwork = registry.hasMore;
|
|
23846
|
+
const canDoSomething = moreCached || moreOnNetwork;
|
|
23847
|
+
if (canDoSomething) {
|
|
23848
|
+
const label = registryLoading ? t4("mcp.marketplaceLoading") : t4("mcp.marketplaceMoreLabel", {
|
|
23849
|
+
shown,
|
|
23850
|
+
total: moreOnNetwork ? `${total}+` : `${total}`
|
|
23851
|
+
});
|
|
23852
|
+
return html4`<div style="padding:10px 12px;display:flex;align-items:center;gap:10px">
|
|
23853
|
+
<button class="btn primary" disabled=${registryLoading} onClick=${loadMore}>${label}</button>
|
|
23854
|
+
<span style="font-size:11px;color:var(--fg-3)">
|
|
23855
|
+
${moreOnNetwork ? t4("mcp.marketplaceMoreHint") : t4("mcp.marketplaceMoreCachedHint")}
|
|
23856
|
+
</span>
|
|
23857
|
+
</div>`;
|
|
23858
|
+
}
|
|
23859
|
+
return html4`<div style="padding:12px;background:var(--bg-elev-2,rgba(36,143,242,0.07));border-top:1px solid var(--bd);display:flex;align-items:center;gap:8px;font-size:12px;color:var(--fg-2)">
|
|
23860
|
+
<span style="color:var(--c-ok)">✓</span>
|
|
23861
|
+
<span>${t4("mcp.marketplaceExhaustedFull", { total })}</span>
|
|
23862
|
+
</div>`;
|
|
23863
|
+
}
|
|
23864
|
+
function renderMarketplaceRows({
|
|
23865
|
+
registry,
|
|
23866
|
+
registryLoading,
|
|
23867
|
+
openRegistry,
|
|
23868
|
+
setOpenRegistry,
|
|
23869
|
+
loadMore,
|
|
23870
|
+
installedSpecs
|
|
23871
|
+
}) {
|
|
23872
|
+
if (!registry && registryLoading) {
|
|
23873
|
+
return html4`<div style="color:var(--fg-3);padding:14px;font-size:12px">${t4("mcp.marketplaceLoading")}</div>`;
|
|
23874
|
+
}
|
|
23875
|
+
if (!registry || registry.entries.length === 0) {
|
|
23876
|
+
return html4`<div style="color:var(--fg-3);padding:14px;font-size:12px">${t4("mcp.marketplaceNoMatches")}</div>`;
|
|
23877
|
+
}
|
|
23878
|
+
return html4`
|
|
23879
|
+
${registry.entries.map((e3) => {
|
|
23880
|
+
const sel = openRegistry?.name === e3.name;
|
|
23881
|
+
const tag2 = t4("mcp.marketplaceSourceTag", { source: e3.source });
|
|
23882
|
+
const spec = specForEntry(e3);
|
|
23883
|
+
const installed = spec !== null && installedSpecs.has(spec);
|
|
23884
|
+
const pop = e3.popularity !== void 0 ? html4` <span class="dim">· ${fmtNum(e3.popularity)}</span>` : null;
|
|
23885
|
+
const icon = e3.iconUrl ? html4`<img src=${e3.iconUrl} alt="" style="width:16px;height:16px;border-radius:3px;margin-right:6px;vertical-align:middle;object-fit:cover" loading="lazy" referrerpolicy="no-referrer" onError=${(ev) => ev.target.style.display = "none"} />` : null;
|
|
23886
|
+
return html4`
|
|
23887
|
+
<div class=${`ssl-row ${sel ? "sel" : ""}`} onClick=${() => setOpenRegistry(e3)}>
|
|
23888
|
+
<span class="name">${icon}${e3.name} <span class="pill">${tag2}</span>${installed ? html4` <span class="pill ok">${t4("mcp.marketplaceInstalledBadge")}</span>` : null}</span>
|
|
23889
|
+
<span class="preview">${e3.description}</span>
|
|
23890
|
+
<span class="meta">${pop}</span>
|
|
23891
|
+
</div>
|
|
23892
|
+
`;
|
|
23893
|
+
})}
|
|
23894
|
+
${renderLoadMoreFooter({ registry, registryLoading, loadMore })}
|
|
23895
|
+
`;
|
|
23896
|
+
}
|
|
23897
|
+
function renderRegistryDetail({
|
|
23898
|
+
entry,
|
|
23899
|
+
busy,
|
|
23900
|
+
installedSpec,
|
|
23901
|
+
onInstall,
|
|
23902
|
+
onUninstall,
|
|
23903
|
+
onClose
|
|
23904
|
+
}) {
|
|
23905
|
+
const installable = !!entry.install || entry.source === "smithery";
|
|
23906
|
+
const installed = installedSpec !== null;
|
|
23907
|
+
const specPreview = entry.install ? `${entry.install.runtime} \xB7 ${entry.install.transport}${entry.install.packageId ? ` \xB7 ${entry.install.packageId}` : entry.install.url ? ` \xB7 ${entry.install.url}` : ""}${entry.install.version ? `@${entry.install.version}` : ""}` : "";
|
|
23908
|
+
const icon = entry.iconUrl ? html4`<img src=${entry.iconUrl} alt="" style="width:24px;height:24px;border-radius:4px;margin-right:8px;vertical-align:middle;object-fit:cover" loading="lazy" referrerpolicy="no-referrer" onError=${(ev) => ev.target.style.display = "none"} />` : null;
|
|
23909
|
+
return html4`
|
|
23910
|
+
<div class="sessions-detail-h">
|
|
23911
|
+
<span class="name">${icon}${entry.name}${installed ? html4` <span class="pill ok">${t4("mcp.marketplaceInstalledBadge")}</span>` : null}</span>
|
|
23912
|
+
<span class="ws">${t4("mcp.marketplaceSourceTag", { source: entry.source })}${entry.popularity !== void 0 ? ` \xB7 ${fmtNum(entry.popularity)} uses` : ""}${entry.homepage ? html4` · <a href=${entry.homepage} target="_blank" rel="noopener noreferrer">homepage</a>` : ""}</span>
|
|
23913
|
+
<span class="actions">
|
|
23914
|
+
${installed ? html4`<button
|
|
23915
|
+
class="btn"
|
|
23916
|
+
disabled=${busy}
|
|
23917
|
+
onClick=${() => onUninstall(installedSpec)}
|
|
23918
|
+
style="border-color:var(--c-err);color:var(--c-err)"
|
|
23919
|
+
>${t4("mcp.marketplaceUninstall")}</button>` : html4`<button class="btn primary" disabled=${busy || !installable} onClick=${onInstall}>${t4("mcp.marketplaceInstall")}</button>`}
|
|
23920
|
+
<button class="btn ghost" onClick=${onClose}>${t4("common.back")}</button>
|
|
23921
|
+
</span>
|
|
23922
|
+
</div>
|
|
23923
|
+
|
|
23924
|
+
<div class="card" style="margin-bottom:12px">
|
|
23925
|
+
<div class="card-b" style="font-size:13px;line-height:1.6">${entry.description || "\u2014"}</div>
|
|
23926
|
+
</div>
|
|
23927
|
+
|
|
23928
|
+
${entry.install ? html4`<div class="card" style="margin-bottom:12px">
|
|
23929
|
+
<div class="card-h"><span class="title">${t4("mcp.spec")}</span></div>
|
|
23930
|
+
<div class="card-b">
|
|
23931
|
+
<code class="mono" style="font-size:11.5px;color:var(--fg-2);word-break:break-all;display:block">${specPreview}</code>
|
|
23932
|
+
${installedSpec ? html4`<div style="margin-top:8px;font-size:11px;color:var(--fg-3)">
|
|
23933
|
+
<span class="dim">on disk:</span> <code class="mono">${installedSpec}</code>
|
|
23934
|
+
</div>` : null}
|
|
23935
|
+
</div>
|
|
23936
|
+
</div>` : entry.source === "smithery" ? html4`<div class="card" style="margin-bottom:12px">
|
|
23937
|
+
<div class="card-b" style="font-size:13px;line-height:1.6;color:var(--fg-3)">
|
|
23938
|
+
${t4("mcp.marketplaceFetchOnInstall")}
|
|
23939
|
+
</div>
|
|
23940
|
+
</div>` : null}
|
|
23941
|
+
|
|
23942
|
+
${entry.install?.requiredEnv?.length ? html4`<div class="card accent-brand" style="margin-bottom:12px">
|
|
23943
|
+
<div class="card-h"><span class="title">${t4("mcp.marketplaceEnvTitle")}</span></div>
|
|
23944
|
+
<div class="card-b" style="font-size:13px">
|
|
23945
|
+
${entry.install.requiredEnv.map(
|
|
23946
|
+
(name) => html4`<div><code class="mono" style="color:var(--c-warn)">${name}</code></div>`
|
|
23947
|
+
)}
|
|
23948
|
+
<div style="margin-top:6px;color:var(--fg-3);font-size:12px">
|
|
23949
|
+
${t4("mcp.marketplaceEnvHint")}
|
|
23950
|
+
</div>
|
|
23951
|
+
</div>
|
|
23952
|
+
</div>` : null}
|
|
23953
|
+
|
|
23954
|
+
${installed ? html4`<div class="card accent-warn">
|
|
23955
|
+
<div class="card-b" style="font-size:12.5px;line-height:1.6">
|
|
23956
|
+
${t4("mcp.marketplaceRestartHint")}
|
|
23957
|
+
</div>
|
|
23958
|
+
</div>` : null}
|
|
23959
|
+
`;
|
|
23960
|
+
}
|
|
23667
23961
|
|
|
23668
23962
|
// dashboard/src/panels/memory.ts
|
|
23669
23963
|
function MemoryPanel() {
|