chore: track Cocos Creator project for future migration
This commit is contained in:
+28014
File diff suppressed because it is too large
Load Diff
+5387
File diff suppressed because it is too large
Load Diff
Vendored
Executable
+390
@@ -0,0 +1,390 @@
|
||||
"use strict";
|
||||
|
||||
// packages/cocos-ext/src/panels/default/index.ts
|
||||
var LOCALE_STORAGE_KEY = "cocos-mcp-panel-locale";
|
||||
var STR = {
|
||||
zh: {
|
||||
panelTitle: "Cocos MCP \u63A7\u5236\u53F0",
|
||||
langLabel: "\u754C\u9762\u8BED\u8A00",
|
||||
server: "\u670D\u52A1",
|
||||
running: "\u8FD0\u884C\u4E2D",
|
||||
stopped: "\u5DF2\u505C\u6B62",
|
||||
port: "\u7AEF\u53E3",
|
||||
connections: "\u8FDE\u63A5\u6570",
|
||||
url: "\u9762\u677F URL\uFF08\u4EC5\u4F9B\u53C2\u8003\uFF09",
|
||||
startServer: "\u542F\u52A8\u670D\u52A1",
|
||||
stopServer: "\u505C\u6B62\u670D\u52A1",
|
||||
refresh: "\u5237\u65B0",
|
||||
runSelfTest: "\u4E00\u952E\u68C0\u6D4B",
|
||||
selfTestTitle: "\u8FDE\u63A5\u8BCA\u65AD",
|
||||
selfTestNever: "\u5C1A\u672A\u8FD0\u884C\u68C0\u6D4B",
|
||||
quickStartTitle: "\u9996\u6B21\u4F7F\u7528",
|
||||
quickStartStepServer: "\u542F\u52A8MCP\u670D\u52A1",
|
||||
quickStartStepConfig: "\u914D\u7F6E\u81F3\u5C11\u4E00\u4E2AMCP\u5BA2\u6237\u7AEF",
|
||||
quickStartStepConnect: "\u91CD\u542F\u5BA2\u6237\u7AEF\u5E76\u5EFA\u7ACB\u8FDE\u63A5",
|
||||
quickStartDone: "\u5B8C\u6210",
|
||||
quickStartPending: "\u5F85\u5B8C\u6210",
|
||||
openGuide: "\u6253\u5F00Quick Start",
|
||||
firstPromptLabel: "\u8FDE\u63A5\u6210\u529F\u540E\uFF0C\u5148\u8BA9AI\u8BFB\u53D6\u573A\u666F\uFF0C\u518D\u505A\u4E00\u4E2A\u5C0F\u6539\u52A8\u3002",
|
||||
autoConfigTitle: "\u4E00\u952E\u914D\u7F6E MCP \u5BA2\u6237\u7AEF",
|
||||
serverNamePh: "MCP \u670D\u52A1\u540D\uFF08\u5199\u5165\u5404\u5BA2\u6237\u7AEF\u914D\u7F6E\uFF09",
|
||||
autoConfigAll: "\u4E00\u952E\u914D\u7F6E\u5168\u90E8\u5BA2\u6237\u7AEF",
|
||||
configured: "\u5DF2\u914D\u7F6E",
|
||||
notConfigured: "\u672A\u914D\u7F6E",
|
||||
autoConfig: "\u4E00\u952E\u914D\u7F6E",
|
||||
openConfig: "\u6253\u5F00\u914D\u7F6E",
|
||||
cliTitle: "\u547D\u4EE4\u884C\u53C2\u8003\uFF08Codex / Gemini CLI\uFF09",
|
||||
operationLogs: "\u64CD\u4F5C\u65E5\u5FD7",
|
||||
clear: "\u6E05\u7A7A",
|
||||
logLevelInfo: "\u4FE1\u606F",
|
||||
logLevelWarn: "\u8B66\u544A",
|
||||
logLevelError: "\u9519\u8BEF"
|
||||
},
|
||||
en: {
|
||||
panelTitle: "Cocos MCP Console",
|
||||
langLabel: "Language",
|
||||
server: "Server",
|
||||
running: "Running",
|
||||
stopped: "Stopped",
|
||||
port: "port",
|
||||
connections: "Connections",
|
||||
url: "Panel URL (reference)",
|
||||
startServer: "Start Server",
|
||||
stopServer: "Stop Server",
|
||||
refresh: "Refresh",
|
||||
runSelfTest: "Run Self-Test",
|
||||
selfTestTitle: "Connection Diagnostics",
|
||||
selfTestNever: "Self-test has not run yet",
|
||||
quickStartTitle: "First Run",
|
||||
quickStartStepServer: "Start the MCP service",
|
||||
quickStartStepConfig: "Configure at least one MCP client",
|
||||
quickStartStepConnect: "Restart the client and connect",
|
||||
quickStartDone: "done",
|
||||
quickStartPending: "pending",
|
||||
openGuide: "Open Quick Start",
|
||||
firstPromptLabel: "After connecting, inspect the scene before one small mutation.",
|
||||
autoConfigTitle: "Auto Config MCP Clients",
|
||||
serverNamePh: "server name (written to each client config)",
|
||||
autoConfigAll: "Auto Config All",
|
||||
configured: "configured",
|
||||
notConfigured: "not configured",
|
||||
autoConfig: "Auto Config",
|
||||
openConfig: "Open Config",
|
||||
cliTitle: "CLI reference (Codex / Gemini CLI)",
|
||||
operationLogs: "Operation Logs",
|
||||
clear: "Clear",
|
||||
logLevelInfo: "info",
|
||||
logLevelWarn: "warn",
|
||||
logLevelError: "error"
|
||||
}
|
||||
};
|
||||
function readLocale() {
|
||||
try {
|
||||
const v = localStorage.getItem(LOCALE_STORAGE_KEY);
|
||||
if (v === "en" || v === "zh") {
|
||||
return v;
|
||||
}
|
||||
} catch {
|
||||
}
|
||||
return "zh";
|
||||
}
|
||||
function writeLocale(l) {
|
||||
try {
|
||||
localStorage.setItem(LOCALE_STORAGE_KEY, l);
|
||||
} catch {
|
||||
}
|
||||
}
|
||||
var locale = readLocale();
|
||||
function t(key) {
|
||||
return STR[locale][key] ?? STR.en[key] ?? key;
|
||||
}
|
||||
var TEMPLATE = `
|
||||
<div class="wrap">
|
||||
<div class="row lang-bar">
|
||||
<span id="langLabel" class="lang-label"></span>
|
||||
<select id="langSelect" class="lang-select">
|
||||
<option value="zh">\u4E2D\u6587</option>
|
||||
<option value="en">English</option>
|
||||
</select>
|
||||
</div>
|
||||
<h2 id="panelTitle"></h2>
|
||||
<div class="card guide-card">
|
||||
<div class="row guide-heading">
|
||||
<h3 id="quickStartTitle"></h3>
|
||||
<ui-button id="openGuideBtn"></ui-button>
|
||||
</div>
|
||||
<div id="quickStartSteps" class="guide-steps"></div>
|
||||
<div id="firstPromptLabel" class="guide-note"></div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div id="serverLine">-</div>
|
||||
<div id="connLine">-</div>
|
||||
<div id="urlLine">-</div>
|
||||
<div class="row">
|
||||
<ui-button id="startBtn"></ui-button>
|
||||
<ui-button id="stopBtn"></ui-button>
|
||||
<ui-button id="refreshBtn"></ui-button>
|
||||
<ui-button id="selfTestBtn"></ui-button>
|
||||
</div>
|
||||
<h3 id="selfTestTitle" class="self-test-title"></h3>
|
||||
<div id="selfTestResults" class="self-test-results"></div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3 id="autoConfigTitle"></h3>
|
||||
<div class="row">
|
||||
<ui-input id="serverNameInput"></ui-input>
|
||||
<ui-button id="addAllBtn"></ui-button>
|
||||
</div>
|
||||
<div id="clientList"></div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3 id="cliTitle"></h3>
|
||||
<div class="mono" id="claudeCmd"></div>
|
||||
<div class="mono" id="geminiCmd"></div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="row">
|
||||
<h3 id="logsTitle"></h3>
|
||||
<ui-button id="clearLogsBtn"></ui-button>
|
||||
</div>
|
||||
<div id="logs" class="logs"></div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
var STYLE = `
|
||||
.wrap { padding: 12px; color: #d4d4d4; font-size: 13px; }
|
||||
.lang-bar { margin-bottom: 10px; }
|
||||
.lang-label { margin-right: 8px; color: #aaa; }
|
||||
.lang-select { background: #2d2d2d; color: #d4d4d4; border: 1px solid #444; border-radius: 4px; padding: 4px 8px; font-size: 13px; }
|
||||
h2 { margin: 0 0 10px 0; font-size: 18px; }
|
||||
h3 { margin: 0 0 8px 0; font-size: 14px; }
|
||||
.card { border: 1px solid #333; border-radius: 6px; padding: 10px; margin-bottom: 10px; background: #1e1e1e; }
|
||||
.row { display: flex; gap: 8px; align-items: center; margin-top: 8px; margin-bottom: 6px; }
|
||||
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; background: #111; padding: 8px; border-radius: 4px; margin-bottom: 6px; word-break: break-all; }
|
||||
.logs { max-height: 220px; overflow: auto; background: #111; border-radius: 4px; padding: 8px; }
|
||||
.log { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; margin-bottom: 4px; white-space: pre-wrap; word-break: break-word; }
|
||||
.log.error { color: #ff8a8a; }
|
||||
.log.warn { color: #f7d774; }
|
||||
.log.info { color: #9bd4ff; }
|
||||
.client-row { display: grid; grid-template-columns: 110px 1fr auto auto; gap: 8px; align-items: center; margin: 6px 0; }
|
||||
.tag { padding: 2px 6px; border-radius: 4px; font-size: 12px; background: #333; }
|
||||
.ok { background: #1f5f2f; }
|
||||
.bad { background: #6a2a2a; }
|
||||
.guide-card { border-color: #315b4f; }
|
||||
.guide-heading { justify-content: space-between; margin-top: 0; }
|
||||
.guide-heading h3 { margin: 0; }
|
||||
.guide-steps { display: grid; gap: 6px; }
|
||||
.guide-step { display: grid; grid-template-columns: 68px 1fr; gap: 8px; align-items: center; }
|
||||
.guide-status { padding: 2px 6px; border-radius: 4px; font-size: 12px; text-align: center; background: #5c4622; }
|
||||
.guide-status.done { background: #1f5f2f; }
|
||||
.guide-note { margin-top: 8px; color: #a8c9bd; }
|
||||
.self-test-title { margin-top: 12px; }
|
||||
.self-test-results { display: grid; gap: 5px; }
|
||||
.self-test-row { display: grid; grid-template-columns: 22px 92px 1fr; gap: 6px; align-items: start; }
|
||||
.self-test-icon.ok-text { color: #63d28b; }
|
||||
.self-test-icon.bad-text { color: #ff8a8a; }
|
||||
.self-test-message { color: #aaa; word-break: break-word; }
|
||||
`;
|
||||
module.exports = Editor.Panel.define({
|
||||
template: TEMPLATE,
|
||||
style: STYLE,
|
||||
$: {
|
||||
langLabel: "#langLabel",
|
||||
langSelect: "#langSelect",
|
||||
panelTitle: "#panelTitle",
|
||||
quickStartTitle: "#quickStartTitle",
|
||||
quickStartSteps: "#quickStartSteps",
|
||||
openGuideBtn: "#openGuideBtn",
|
||||
firstPromptLabel: "#firstPromptLabel",
|
||||
serverLine: "#serverLine",
|
||||
connLine: "#connLine",
|
||||
urlLine: "#urlLine",
|
||||
startBtn: "#startBtn",
|
||||
stopBtn: "#stopBtn",
|
||||
refreshBtn: "#refreshBtn",
|
||||
selfTestBtn: "#selfTestBtn",
|
||||
selfTestTitle: "#selfTestTitle",
|
||||
selfTestResults: "#selfTestResults",
|
||||
autoConfigTitle: "#autoConfigTitle",
|
||||
serverNameInput: "#serverNameInput",
|
||||
addAllBtn: "#addAllBtn",
|
||||
clientList: "#clientList",
|
||||
cliTitle: "#cliTitle",
|
||||
claudeCmd: "#claudeCmd",
|
||||
geminiCmd: "#geminiCmd",
|
||||
logs: "#logs",
|
||||
logsTitle: "#logsTitle",
|
||||
clearLogsBtn: "#clearLogsBtn"
|
||||
},
|
||||
ready() {
|
||||
const pluginName = "cocos-mcp";
|
||||
locale = readLocale();
|
||||
const readServerName = () => {
|
||||
const input = this.$.serverNameInput;
|
||||
const v = (input?.value ?? "").trim();
|
||||
return v || "cocos-creator";
|
||||
};
|
||||
const applyStaticLabels = () => {
|
||||
this.$.langLabel.textContent = t("langLabel");
|
||||
this.$.panelTitle.textContent = t("panelTitle");
|
||||
this.$.quickStartTitle.textContent = t("quickStartTitle");
|
||||
this.$.openGuideBtn.textContent = t("openGuide");
|
||||
this.$.firstPromptLabel.textContent = t("firstPromptLabel");
|
||||
this.$.autoConfigTitle.textContent = t("autoConfigTitle");
|
||||
this.$.cliTitle.textContent = t("cliTitle");
|
||||
this.$.logsTitle.textContent = t("operationLogs");
|
||||
this.$.startBtn.textContent = t("startServer");
|
||||
this.$.stopBtn.textContent = t("stopServer");
|
||||
this.$.refreshBtn.textContent = t("refresh");
|
||||
this.$.selfTestBtn.textContent = t("runSelfTest");
|
||||
this.$.selfTestTitle.textContent = t("selfTestTitle");
|
||||
this.$.addAllBtn.textContent = t("autoConfigAll");
|
||||
this.$.clearLogsBtn.textContent = t("clear");
|
||||
const input = this.$.serverNameInput;
|
||||
if (input) {
|
||||
input.placeholder = t("serverNamePh");
|
||||
}
|
||||
const sel = this.$.langSelect;
|
||||
if (sel) {
|
||||
sel.value = locale;
|
||||
}
|
||||
};
|
||||
const logLevelLabel = (level) => {
|
||||
if (level === "error") {
|
||||
return t("logLevelError");
|
||||
}
|
||||
if (level === "warn") {
|
||||
return t("logLevelWarn");
|
||||
}
|
||||
return t("logLevelInfo");
|
||||
};
|
||||
const render = (state) => {
|
||||
const run = state.server.running ? t("running") : t("stopped");
|
||||
this.$.serverLine.textContent = `${t("server")}: ${run} (${t("port")}: ${state.server.port ?? "-"})`;
|
||||
this.$.connLine.textContent = `${t("connections")}: ${state.server.connections}`;
|
||||
this.$.urlLine.textContent = `${t("url")}: ${state.server.url ?? "-"}`;
|
||||
this.$.claudeCmd.textContent = state.cliCommands.claude;
|
||||
this.$.geminiCmd.textContent = state.cliCommands.gemini;
|
||||
const selfTestResults = this.$.selfTestResults;
|
||||
selfTestResults.innerHTML = "";
|
||||
if (!state.selfTest) {
|
||||
selfTestResults.textContent = t("selfTestNever");
|
||||
} else {
|
||||
for (const check of state.selfTest.checks) {
|
||||
const row = document.createElement("div");
|
||||
row.className = "self-test-row";
|
||||
const icon = document.createElement("span");
|
||||
icon.className = `self-test-icon ${check.ok ? "ok-text" : "bad-text"}`;
|
||||
icon.textContent = check.ok ? "OK" : "X";
|
||||
const id = document.createElement("strong");
|
||||
id.textContent = check.id;
|
||||
const message = document.createElement("span");
|
||||
message.className = "self-test-message";
|
||||
message.textContent = check.message;
|
||||
row.append(icon, id, message);
|
||||
selfTestResults.appendChild(row);
|
||||
}
|
||||
}
|
||||
const guideSteps = this.$.quickStartSteps;
|
||||
guideSteps.innerHTML = "";
|
||||
const onboardingSteps = [
|
||||
{ label: t("quickStartStepServer"), done: state.server.running },
|
||||
{ label: t("quickStartStepConfig"), done: state.clients.some((client) => client.configured) },
|
||||
{ label: t("quickStartStepConnect"), done: state.server.connections > 0 }
|
||||
];
|
||||
for (const step of onboardingSteps) {
|
||||
const row = document.createElement("div");
|
||||
row.className = "guide-step";
|
||||
const status = document.createElement("span");
|
||||
status.className = `guide-status${step.done ? " done" : ""}`;
|
||||
status.textContent = step.done ? t("quickStartDone") : t("quickStartPending");
|
||||
const label = document.createElement("span");
|
||||
label.textContent = step.label;
|
||||
row.append(status, label);
|
||||
guideSteps.appendChild(row);
|
||||
}
|
||||
const list = this.$.clientList;
|
||||
list.innerHTML = "";
|
||||
for (const c of state.clients) {
|
||||
const row = document.createElement("div");
|
||||
row.className = "client-row";
|
||||
const tagText = c.configured ? t("configured") : t("notConfigured");
|
||||
const tagClass = c.configured ? "ok" : "bad";
|
||||
row.innerHTML = `
|
||||
<strong>${c.name}</strong>
|
||||
<span title="${c.configPath}">${c.configPath}</span>
|
||||
<span class="tag ${tagClass}">${tagText}</span>
|
||||
<div>
|
||||
<ui-button class="cfg-btn" data-client="${c.clientType}">${t("autoConfig")}</ui-button>
|
||||
<ui-button class="open-btn" data-client="${c.clientType}">${t("openConfig")}</ui-button>
|
||||
</div>
|
||||
`;
|
||||
list.appendChild(row);
|
||||
}
|
||||
list.querySelectorAll(".cfg-btn").forEach((el) => {
|
||||
el.addEventListener("confirm", async () => {
|
||||
const clientType = el.getAttribute("data-client");
|
||||
await Editor.Message.request(pluginName, "add-mcp-to-client", clientType, readServerName());
|
||||
await refresh();
|
||||
});
|
||||
});
|
||||
list.querySelectorAll(".open-btn").forEach((el) => {
|
||||
el.addEventListener("confirm", async () => {
|
||||
const clientType = el.getAttribute("data-client");
|
||||
await Editor.Message.request(pluginName, "open-client-config", clientType);
|
||||
});
|
||||
});
|
||||
const logs = this.$.logs;
|
||||
logs.innerHTML = "";
|
||||
for (const l of state.logs.slice().reverse()) {
|
||||
const line = document.createElement("div");
|
||||
line.className = `log ${l.level}`;
|
||||
line.textContent = `${l.ts} [${logLevelLabel(l.level)}] ${l.message}`;
|
||||
logs.appendChild(line);
|
||||
}
|
||||
};
|
||||
const refresh = async () => {
|
||||
applyStaticLabels();
|
||||
const state = await Editor.Message.request(pluginName, "get-mcp-panel-state", readServerName());
|
||||
render(state);
|
||||
};
|
||||
this.$.langSelect?.addEventListener("change", () => {
|
||||
const sel = this.$.langSelect;
|
||||
const v = sel?.value === "en" ? "en" : "zh";
|
||||
locale = v;
|
||||
writeLocale(v);
|
||||
refresh().catch((e) => console.error("[cocos-mcp panel] refresh after locale", e));
|
||||
});
|
||||
this.$.startBtn?.addEventListener("confirm", async () => {
|
||||
await Editor.Message.request(pluginName, "start-mcp-server");
|
||||
await refresh();
|
||||
});
|
||||
this.$.stopBtn?.addEventListener("confirm", async () => {
|
||||
await Editor.Message.request(pluginName, "stop-mcp-server");
|
||||
await refresh();
|
||||
});
|
||||
this.$.refreshBtn?.addEventListener("confirm", refresh);
|
||||
this.$.selfTestBtn?.addEventListener("confirm", async () => {
|
||||
await Editor.Message.request(pluginName, "run-mcp-self-test", readServerName());
|
||||
await refresh();
|
||||
});
|
||||
this.$.openGuideBtn?.addEventListener("confirm", async () => {
|
||||
await Editor.Message.request(pluginName, "open-user-guide");
|
||||
});
|
||||
this.$.addAllBtn?.addEventListener("confirm", async () => {
|
||||
await Editor.Message.request(pluginName, "add-mcp-to-all-clients", readServerName());
|
||||
await refresh();
|
||||
});
|
||||
this.$.clearLogsBtn?.addEventListener("confirm", async () => {
|
||||
await Editor.Message.request(pluginName, "clear-panel-logs");
|
||||
await refresh();
|
||||
});
|
||||
this.$.serverNameInput?.addEventListener("change", refresh);
|
||||
refresh().catch((e) => {
|
||||
console.error("[cocos-mcp panel] initial refresh failed", e);
|
||||
});
|
||||
}
|
||||
});
|
||||
+3053
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user