fix: sink nodes should be Component not Output unless named output/result/end

Previously, the last node in any triplet chain was classified as Output type
and skipped by the executor (passthrough only). Now only nodes explicitly named
output/result/end/done are Output; all other sink nodes are Component and
will have their WASM executed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-16 16:16:28 +08:00
parent 65769fc0dd
commit 9590083851
+15 -2
View File
@@ -101,10 +101,23 @@ export function parseTriplets(rawTriplets: unknown[]): ParsedTriplets | null {
return { edges, nodeNames, sourceNodes, sinkNodes };
}
/** 根據節點在圖中的位置決定其 type */
/** 保留字節點名稱 — 明確宣告為 Input 或 Output 端點 */
const INPUT_NAMES = new Set(['input', 'trigger', 'webhook', 'start']);
const OUTPUT_NAMES = new Set(['output', 'result', 'end', 'done']);
/** 根據節點在圖中的位置決定其 type
*
* 規則:
* - 名稱在 INPUT_NAMES → Input(無論位置)
* - 名稱在 OUTPUT_NAMES → Output(無論位置)
* - sourceNode(只出現在 from)且名稱不在 INPUT_NAMES → Component(例如 cron 作為觸發源)
* - sinkNode(只出現在 to)且名稱不在 OUTPUT_NAMES → Component(最常見情況:最後一個實際零件)
* - 其他中間節點 → Component
*/
export function resolveNodeRole(name: string, parsed: ParsedTriplets): NodeRole {
if (INPUT_NAMES.has(name.toLowerCase())) return 'Input';
if (OUTPUT_NAMES.has(name.toLowerCase())) return 'Output';
if (parsed.sourceNodes.has(name)) return 'Input';
if (parsed.sinkNodes.has(name)) return 'Output';
return 'Component';
}