323ccc8475
問題(「全變成 code」的根):if_control 回 {result, branch} 卻沒有邊讀得懂它,
圖的邊只有 ON_SUCCESS/IF/FOREACH ⇒ 就算照規矩用零件,仍得寫 code 判斷走哪條。
leo 08-01 追問「你改了 if,有改 switch 嗎?switch 更嚴重」——確認 switch(N 路)
與 try_catch(try/catch) 同病,故一次做成通用機制,不留「為 switch 再改一次」的債。
設計:三顆流程控制零件的 output_schema 本來就都收斂到同一形狀 data.branch: string
(if_control→true/false;switch→case 名或 default_branch;try_catch→try/catch)
⇒ 引擎只需「依標籤選邊」一個機制 ON_BRANCH;ON_TRUE/ON_FALSE 是布林路的語法糖,
底層同一條路(測試已證等價)。讀不出分支=不走(誠實,不亂挑一條)。
- types/schemas/constants:新增三邊型(純新增,既有列舉不動)+ GraphEdge.branch
- graph-executor:readBranch() 依 data.branch → branch → data.result → result 四層相容
- 中文語意詞:成立時/為真時=ON_TRUE,不成立時/為假時/否則=ON_FALSE,BRANCH=ON_BRANCH
分支用法要「查得到」(leo 08-01:AI 可能像 n8n 那樣逐顆查、自己組圖):
新增 lib/branch-hints.ts,讓 if_control/switch/try_catch 的查詢回應自帶 branch_hint
(branch_field/branches/edge_types/usage/example)——只看這一顆的回應就知道怎麼接下一步,
不必回頭讀 skill。四條回應路徑全wire:catalog found/legacy 逐顆/步驟4 substitution/
target=component 名字搜尋(=n8n 式那條)。不分岔的零件不加此欄,避免噪音。
測試(先寫測試再改引擎,紅線要求):tests/conditional-edges.test.ts 16 項全綠
——if 兩路/switch 多路+default/try_catch 成功與失敗路/語法糖等價/
context 傳遞/同分支 fan-out/無匹配不走/混合邊時 PIPE 不受影響/schema 放行。
零變化保證:195 passed(前 179 +16 新),失敗數維持既有 9 筆未變(console/portal
HTML 資產未建置+executor 斷言字串漂移,皆與本次無關);tsc --noEmit 綠。
現存 workflow/example 用到新邊型=0 筆(grep 實查)⇒ 既有行為不可能被改動。
SDD: workflow-discovery task 3.11|CP: arcrun-usable 步驟 5
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
67 lines
2.1 KiB
TypeScript
67 lines
2.1 KiB
TypeScript
import type { ComponentRunner, EdgeType } from '../types';
|
||
|
||
export const VALID_EDGE_TYPES = new Set([
|
||
// 現有
|
||
'PIPE', 'IF', 'FOREACH', 'CONTINUE',
|
||
// 新增:執行語意
|
||
'IS_A', 'ON_SUCCESS', 'ON_FAIL',
|
||
// 新增:條件語意(SDD workflow-discovery 3.11)—— 讀上游 if_control/switch 的 branch
|
||
'ON_TRUE', 'ON_FALSE', 'ON_BRANCH',
|
||
// 新增:觸發語意
|
||
'ON_CLICK', 'CALLS_SUBFLOW',
|
||
// 新增:結構語意(記錄圖結構,不執行)
|
||
'CONTAINS', 'HAS_STYLE', 'HAS_BEHAVIOR',
|
||
]);
|
||
|
||
/** 內建零件 ID 集合(Worker 記憶體中已有實作)*/
|
||
export const BUILTIN_IDS = new Set([
|
||
'webhook', 'comp_passthrough', 'comp_uppercase', 'comp_counter',
|
||
]);
|
||
|
||
/** 語意邊 → EdgeType 映射(ADR-057 u6u L1:支援中文語意關係詞)
|
||
* 完成後 → PIPE(成功後觸發下一個)
|
||
* 失敗時 → CONTINUE(失敗後繼續)
|
||
* 對每個 → FOREACH(迭代執行)
|
||
* 條件滿足時 → IF(條件分支)
|
||
*/
|
||
export const SEMANTIC_EDGE_MAP: Record<string, EdgeType> = {
|
||
// 中文語意詞
|
||
'完成後': 'PIPE',
|
||
'失敗時': 'ON_FAIL',
|
||
'對每個': 'FOREACH',
|
||
'條件滿足時': 'IF',
|
||
// 條件分支語意(SDD workflow-discovery 3.11):讓意圖工作流寫得出兩條路
|
||
'成立時': 'ON_TRUE',
|
||
'為真時': 'ON_TRUE',
|
||
'不成立時': 'ON_FALSE',
|
||
'為假時': 'ON_FALSE',
|
||
'否則': 'ON_FALSE',
|
||
// 英文別名
|
||
'SUCCESS': 'ON_SUCCESS',
|
||
'FAIL': 'ON_FAIL',
|
||
'TRUE': 'ON_TRUE',
|
||
'FALSE': 'ON_FALSE',
|
||
'ELSE': 'ON_FALSE',
|
||
'BRANCH': 'ON_BRANCH',
|
||
'CLICK': 'ON_CLICK',
|
||
'SUBFLOW': 'CALLS_SUBFLOW',
|
||
};
|
||
|
||
/**
|
||
* 內建零件表(靜態函數)
|
||
* WASM 零件 = 各自獨立 Worker,cypher-executor 走 HTTP URL 呼叫(不從 R2 讀)
|
||
*/
|
||
export const BUILTIN_COMPONENTS = new Map<string, ComponentRunner>([
|
||
['comp_passthrough', (ctx) => ctx],
|
||
['comp_uppercase', (ctx) => {
|
||
const c = ctx as Record<string, unknown>;
|
||
return { ...c, text: String(c.text || '').toUpperCase() };
|
||
}],
|
||
['comp_counter', (ctx) => {
|
||
const c = ctx as Record<string, unknown>;
|
||
return { ...c, count: (Number(c.count) || 0) + 1 };
|
||
}],
|
||
]);
|
||
|
||
export const SCORE_THRESHOLD = 0.5;
|