From 4fd2d3ba6c1dc9d0db03e8e4de01970cc69c08fe Mon Sep 17 00:00:00 2001 From: richblack Date: Sun, 17 May 2026 10:34:12 +0800 Subject: [PATCH] =?UTF-8?q?fix(cypher-executor):=20FOREACH=20iter=20plural?= =?UTF-8?q?=20=E8=AE=8A=E9=AB=94=20(entity=20=E2=86=92=20entities)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 舊 getIterableFromContext 只試 'key+s',遇 irregular plural 不命中: entity + s = entitys ≠ entities (Claude 真實 output) 加變體: - key + 's' (paragraph → paragraphs) - key.replace(/y$/, 'ies') (entity → entities) - key.replace(/(s|x|z|ch|sh)$/, '$1es') (box → boxes) - key (singular fallback) 對應 mira wiki_synthesis V3 multi-entity 升級需求。 --- cypher-executor/src/graph-executor.ts | 30 +++++++++++++++++---------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/cypher-executor/src/graph-executor.ts b/cypher-executor/src/graph-executor.ts index 869e86e..44c9ed0 100644 --- a/cypher-executor/src/graph-executor.ts +++ b/cypher-executor/src/graph-executor.ts @@ -654,22 +654,30 @@ function evaluateCondition(condition: string, context: unknown): boolean { function getIterableFromContext(context: unknown, key: string): unknown[] { if (!context || typeof context !== 'object') return []; - const plural = key + 's'; + // 多種 plural 變體:entity → entities / paragraph → paragraphs / box → boxes / 等 + // 2026-05-17:原本只試 key+'s','entity+s=entitys' ≠ 'entities' 無法命中,加 irregular + const variants = [ + key + 's', // paragraph → paragraphs + key.replace(/y$/, 'ies'), // entity → entities + key.replace(/(s|x|z|ch|sh)$/, '$1es'), // box → boxes + key, // singular fallback + ]; const obj = context as Record; + // 先看 top-level(最常見) - let items = obj[plural] ?? obj[key]; + for (const v of variants) { + if (Array.isArray(obj[v])) return obj[v] as unknown[]; + } + // 若找不到,掃一層內部 object 看 nested(巢狀 FOREACH 場景: // 外層 FOREACH 把 paragraph 注入 ctx,內層 FOREACH 要找 paragraph.triplets) - if (!Array.isArray(items)) { - for (const v of Object.values(obj)) { - if (v !== null && typeof v === 'object' && !Array.isArray(v)) { - const nested = (v as Record)[plural] ?? (v as Record)[key]; - if (Array.isArray(nested)) { - items = nested; - break; - } + for (const val of Object.values(obj)) { + if (val !== null && typeof val === 'object' && !Array.isArray(val)) { + for (const v of variants) { + const nested = (val as Record)[v]; + if (Array.isArray(nested)) return nested; } } } - return Array.isArray(items) ? items : []; + return []; }