fix(cypher-executor): FOREACH iter plural 變體 (entity → entities)

舊 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 升級需求。
This commit is contained in:
2026-05-17 10:34:12 +08:00
parent efdd75cbdc
commit 4fd2d3ba6c
+19 -11
View File
@@ -654,22 +654,30 @@ function evaluateCondition(condition: string, context: unknown): boolean {
function getIterableFromContext(context: unknown, key: string): unknown[] { function getIterableFromContext(context: unknown, key: string): unknown[] {
if (!context || typeof context !== 'object') return []; 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<string, unknown>; const obj = context as Record<string, unknown>;
// 先看 top-level(最常見) // 先看 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 場景: // 若找不到,掃一層內部 object 看 nested(巢狀 FOREACH 場景:
// 外層 FOREACH 把 paragraph 注入 ctx,內層 FOREACH 要找 paragraph.triplets // 外層 FOREACH 把 paragraph 注入 ctx,內層 FOREACH 要找 paragraph.triplets
if (!Array.isArray(items)) { for (const val of Object.values(obj)) {
for (const v of Object.values(obj)) { if (val !== null && typeof val === 'object' && !Array.isArray(val)) {
if (v !== null && typeof v === 'object' && !Array.isArray(v)) { for (const v of variants) {
const nested = (v as Record<string, unknown>)[plural] ?? (v as Record<string, unknown>)[key]; const nested = (val as Record<string, unknown>)[v];
if (Array.isArray(nested)) { if (Array.isArray(nested)) return nested;
items = nested;
break;
}
} }
} }
} }
return Array.isArray(items) ? items : []; return [];
} }