docs: 为 CLI、网页编排器和插件协议补充学习向注释

在核心类型、图执行器、stdio 插件和前端入口写清职责与对照路径,不改运行行为。
This commit is contained in:
2026-08-28 11:51:48 +08:00
parent a3cca78592
commit 950d09ddb0
38 changed files with 206 additions and 3 deletions
+17
View File
@@ -1,3 +1,14 @@
/**
* 可视化编排器前端(无框架)。
*
* 学习路径:
* 1. init → loadCatalog:拉系统节点和插件节点
* 2. 示例图 / 拖节点、点端口连线;图数据在 state.nodes / state.edges
* 3. runGraph POST /api/run;若 status=needsDecision 弹出确认框
* 4. 确认走 /api/run/{id}/decide;超时则 pollRun 等服务端自动采用默认方案
*
* selected / pending 只用于点击交互。发给后端的 JSON 不含 API Key,只有 credentialId。
*/
const state = {
catalog: [],
system: [],
@@ -44,6 +55,7 @@ function pickNode(list, inputName) {
return (list || []).find((item) => item.inputs?.some((p) => p.name === inputName));
}
/** 生成「抽城市 → 有城市才查天气」的示例图。连线 when=hasValidCities。 */
function exampleGraph() {
const fileInfo = pickNode(state.system, "filePath") || pickNode(state.catalog, "filePath");
const weatherInfo = pickNode(state.plugins, "cities") || pickNode(state.system, "cities") || pickNode(state.catalog, "cities");
@@ -110,6 +122,7 @@ function addNode(type) {
render();
}
/** 根据 state 重画节点 DOM;连线是 SVG,在 drawWires。 */
function render() {
canvas.innerHTML = "";
for (const node of state.nodes) {
@@ -172,6 +185,7 @@ function startDrag(e, node) {
window.addEventListener("mouseup", up);
}
/** 先点输出端口记下 pending,再点输入端口生成一条边。 */
function onPort(nodeId, port, dir) {
if (dir === "out") {
state.pending = { nodeId, port };
@@ -293,6 +307,7 @@ function renderInspector() {
};
}
/** 把画布图交给后端。可能直接完成,也可能弹出 decisionModal。 */
async function runGraph() {
closeDecision();
logEl.textContent = "运行中…";
@@ -379,6 +394,7 @@ function syncDecisionText() {
}
}
/** 倒计时到 0 后去 GET 运行结果,因为服务端会自己按默认方案继续。 */
function startDecisionTimer(deadline) {
if (decisionTimer) {
clearInterval(decisionTimer);
@@ -447,6 +463,7 @@ decisionSubmit.onclick = async () => {
}
};
/** 拉节点目录和凭据列表,刷新左侧面板。 */
async function loadCatalog() {
const [catalog, credentials] = await Promise.all([
(await fetch("/api/catalog")).json(),