Просмотр исходного кода

Merge pull request #124 from Nerdless-ship-it/fix/state-validator-trailing-content-and-import-reset

fix: preserve pending_hooks on import + tighten StateValidator JSON extraction
Junxian Ma 7 месяцев назад
Родитель
Сommit
969fa7e723
2 измененных файлов с 27 добавлено и 7 удалено
  1. 23 2
      packages/core/src/agents/state-validator.ts
  2. 4 5
      packages/core/src/pipeline/runner.ts

+ 23 - 2
packages/core/src/agents/state-validator.ts

@@ -211,6 +211,7 @@ function extractBalancedJsonObject(text: string): string | null {
   let depth = 0;
   let inString = false;
   let escaped = false;
+  let endIndex = -1;
 
   for (let index = start; index < text.length; index += 1) {
     const char = text[index]!;
@@ -243,7 +244,8 @@ function extractBalancedJsonObject(text: string): string | null {
     if (char === "}") {
       depth -= 1;
       if (depth === 0) {
-        return text.slice(start, index + 1);
+        endIndex = index;
+        break;
       }
       if (depth < 0) {
         return null;
@@ -251,5 +253,24 @@ function extractBalancedJsonObject(text: string): string | null {
     }
   }
 
-  return null;
+  if (endIndex < 0) return null;
+
+  // Only accept the candidate if what follows the closing brace is
+  // nothing, whitespace, or a structural JSON terminator.
+  // This rejects trailing content like "{...} more text here"
+  const followingChar = text[endIndex + 1];
+  if (
+    followingChar !== undefined &&
+    followingChar !== "\n" &&
+    followingChar !== "\r" &&
+    followingChar !== "\t" &&
+    followingChar !== " " &&
+    followingChar !== "," &&
+    followingChar !== "]" &&
+    followingChar !== "}"
+  ) {
+    return null;
+  }
+
+  return text.slice(start, endIndex + 1);
 }

+ 4 - 5
packages/core/src/pipeline/runner.ts

@@ -2253,11 +2253,10 @@ ${matrix}`,
         this.buildImportReplayStateSeed(language),
         "utf-8",
       ),
-      writeFile(
-        join(storyDir, "pending_hooks.md"),
-        this.buildImportReplayHooksSeed(language),
-        "utf-8",
-      ),
+      // NOTE: pending_hooks.md intentionally NOT reset here — hooks are
+      // chapter-content-specific and user may have invested significant
+      // effort in tuning them. The replay will incrementally add new hooks
+      // detected from the imported chapters without destroying existing ones.
       rm(join(storyDir, "chapter_summaries.md"), { force: true }),
       rm(join(storyDir, "subplot_board.md"), { force: true }),
       rm(join(storyDir, "emotional_arcs.md"), { force: true }),