inkos-n-core 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/ai-tells.d.ts +26 -0
- package/dist/agents/ai-tells.d.ts.map +1 -0
- package/dist/agents/ai-tells.js +140 -0
- package/dist/agents/ai-tells.js.map +1 -0
- package/dist/agents/architect.d.ts +34 -0
- package/dist/agents/architect.d.ts.map +1 -0
- package/dist/agents/architect.js +906 -0
- package/dist/agents/architect.js.map +1 -0
- package/dist/agents/base.d.ts +30 -0
- package/dist/agents/base.d.ts.map +1 -0
- package/dist/agents/base.js +70 -0
- package/dist/agents/base.js.map +1 -0
- package/dist/agents/chapter-analyzer.d.ts +30 -0
- package/dist/agents/chapter-analyzer.d.ts.map +1 -0
- package/dist/agents/chapter-analyzer.js +476 -0
- package/dist/agents/chapter-analyzer.js.map +1 -0
- package/dist/agents/composer.d.ts +36 -0
- package/dist/agents/composer.d.ts.map +1 -0
- package/dist/agents/composer.js +319 -0
- package/dist/agents/composer.js.map +1 -0
- package/dist/agents/consolidator.d.ts +23 -0
- package/dist/agents/consolidator.d.ts.map +1 -0
- package/dist/agents/consolidator.js +141 -0
- package/dist/agents/consolidator.js.map +1 -0
- package/dist/agents/continuity.d.ts +39 -0
- package/dist/agents/continuity.d.ts.map +1 -0
- package/dist/agents/continuity.js +612 -0
- package/dist/agents/continuity.js.map +1 -0
- package/dist/agents/detection-insights.d.ts +9 -0
- package/dist/agents/detection-insights.d.ts.map +1 -0
- package/dist/agents/detection-insights.js +54 -0
- package/dist/agents/detection-insights.js.map +1 -0
- package/dist/agents/detector.d.ts +17 -0
- package/dist/agents/detector.d.ts.map +1 -0
- package/dist/agents/detector.js +77 -0
- package/dist/agents/detector.js.map +1 -0
- package/dist/agents/en-prompt-sections.d.ts +8 -0
- package/dist/agents/en-prompt-sections.d.ts.map +1 -0
- package/dist/agents/en-prompt-sections.js +120 -0
- package/dist/agents/en-prompt-sections.js.map +1 -0
- package/dist/agents/fanfic-canon-importer.d.ts +15 -0
- package/dist/agents/fanfic-canon-importer.d.ts.map +1 -0
- package/dist/agents/fanfic-canon-importer.js +117 -0
- package/dist/agents/fanfic-canon-importer.js.map +1 -0
- package/dist/agents/fanfic-dimensions.d.ts +14 -0
- package/dist/agents/fanfic-dimensions.d.ts.map +1 -0
- package/dist/agents/fanfic-dimensions.js +63 -0
- package/dist/agents/fanfic-dimensions.js.map +1 -0
- package/dist/agents/fanfic-prompt-sections.d.ts +5 -0
- package/dist/agents/fanfic-prompt-sections.d.ts.map +1 -0
- package/dist/agents/fanfic-prompt-sections.js +85 -0
- package/dist/agents/fanfic-prompt-sections.js.map +1 -0
- package/dist/agents/foundation-reviewer.d.ts +29 -0
- package/dist/agents/foundation-reviewer.d.ts.map +1 -0
- package/dist/agents/foundation-reviewer.js +153 -0
- package/dist/agents/foundation-reviewer.js.map +1 -0
- package/dist/agents/length-normalizer.d.ts +32 -0
- package/dist/agents/length-normalizer.d.ts.map +1 -0
- package/dist/agents/length-normalizer.js +156 -0
- package/dist/agents/length-normalizer.js.map +1 -0
- package/dist/agents/observer-prompts.d.ts +10 -0
- package/dist/agents/observer-prompts.d.ts.map +1 -0
- package/dist/agents/observer-prompts.js +113 -0
- package/dist/agents/observer-prompts.js.map +1 -0
- package/dist/agents/planner.d.ts +57 -0
- package/dist/agents/planner.d.ts.map +1 -0
- package/dist/agents/planner.js +594 -0
- package/dist/agents/planner.js.map +1 -0
- package/dist/agents/post-write-validator.d.ts +34 -0
- package/dist/agents/post-write-validator.d.ts.map +1 -0
- package/dist/agents/post-write-validator.js +696 -0
- package/dist/agents/post-write-validator.js.map +1 -0
- package/dist/agents/radar-source.d.ts +38 -0
- package/dist/agents/radar-source.d.ts.map +1 -0
- package/dist/agents/radar-source.js +92 -0
- package/dist/agents/radar-source.js.map +1 -0
- package/dist/agents/radar.d.ts +24 -0
- package/dist/agents/radar.d.ts.map +1 -0
- package/dist/agents/radar.js +85 -0
- package/dist/agents/radar.js.map +1 -0
- package/dist/agents/reviser.d.ts +32 -0
- package/dist/agents/reviser.d.ts.map +1 -0
- package/dist/agents/reviser.js +282 -0
- package/dist/agents/reviser.js.map +1 -0
- package/dist/agents/rules-reader.d.ts +27 -0
- package/dist/agents/rules-reader.d.ts.map +1 -0
- package/dist/agents/rules-reader.js +99 -0
- package/dist/agents/rules-reader.js.map +1 -0
- package/dist/agents/sensitive-words.d.ts +24 -0
- package/dist/agents/sensitive-words.d.ts.map +1 -0
- package/dist/agents/sensitive-words.js +103 -0
- package/dist/agents/sensitive-words.js.map +1 -0
- package/dist/agents/settler-delta-parser.d.ts +7 -0
- package/dist/agents/settler-delta-parser.d.ts.map +1 -0
- package/dist/agents/settler-delta-parser.js +40 -0
- package/dist/agents/settler-delta-parser.js.map +1 -0
- package/dist/agents/settler-parser.d.ts +13 -0
- package/dist/agents/settler-parser.d.ts.map +1 -0
- package/dist/agents/settler-parser.js +20 -0
- package/dist/agents/settler-parser.js.map +1 -0
- package/dist/agents/settler-prompts.d.ts +22 -0
- package/dist/agents/settler-prompts.d.ts.map +1 -0
- package/dist/agents/settler-prompts.js +193 -0
- package/dist/agents/settler-prompts.js.map +1 -0
- package/dist/agents/state-validator.d.ts +26 -0
- package/dist/agents/state-validator.d.ts.map +1 -0
- package/dist/agents/state-validator.js +229 -0
- package/dist/agents/state-validator.js.map +1 -0
- package/dist/agents/style-analyzer.d.ts +11 -0
- package/dist/agents/style-analyzer.d.ts.map +1 -0
- package/dist/agents/style-analyzer.js +81 -0
- package/dist/agents/style-analyzer.js.map +1 -0
- package/dist/agents/writer-parser.d.ts +17 -0
- package/dist/agents/writer-parser.d.ts.map +1 -0
- package/dist/agents/writer-parser.js +131 -0
- package/dist/agents/writer-parser.js.map +1 -0
- package/dist/agents/writer-prompts.d.ts +11 -0
- package/dist/agents/writer-prompts.d.ts.map +1 -0
- package/dist/agents/writer-prompts.js +549 -0
- package/dist/agents/writer-prompts.js.map +1 -0
- package/dist/agents/writer.d.ts +103 -0
- package/dist/agents/writer.d.ts.map +1 -0
- package/dist/agents/writer.js +1052 -0
- package/dist/agents/writer.js.map +1 -0
- package/dist/index.d.ts +80 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +84 -0
- package/dist/index.js.map +1 -0
- package/dist/interaction/edit-controller.d.ts +55 -0
- package/dist/interaction/edit-controller.d.ts.map +1 -0
- package/dist/interaction/edit-controller.js +187 -0
- package/dist/interaction/edit-controller.js.map +1 -0
- package/dist/interaction/events.d.ts +45 -0
- package/dist/interaction/events.d.ts.map +1 -0
- package/dist/interaction/events.js +32 -0
- package/dist/interaction/events.js.map +1 -0
- package/dist/interaction/intents.d.ts +96 -0
- package/dist/interaction/intents.d.ts.map +1 -0
- package/dist/interaction/intents.js +58 -0
- package/dist/interaction/intents.js.map +1 -0
- package/dist/interaction/modes.d.ts +5 -0
- package/dist/interaction/modes.d.ts.map +1 -0
- package/dist/interaction/modes.js +7 -0
- package/dist/interaction/modes.js.map +1 -0
- package/dist/interaction/nl-router.d.ts +8 -0
- package/dist/interaction/nl-router.d.ts.map +1 -0
- package/dist/interaction/nl-router.js +218 -0
- package/dist/interaction/nl-router.js.map +1 -0
- package/dist/interaction/project-control.d.ts +85 -0
- package/dist/interaction/project-control.d.ts.map +1 -0
- package/dist/interaction/project-control.js +123 -0
- package/dist/interaction/project-control.js.map +1 -0
- package/dist/interaction/project-session-store.d.ts +7 -0
- package/dist/interaction/project-session-store.d.ts.map +1 -0
- package/dist/interaction/project-session-store.js +46 -0
- package/dist/interaction/project-session-store.js.map +1 -0
- package/dist/interaction/project-tools.d.ts +20 -0
- package/dist/interaction/project-tools.d.ts.map +1 -0
- package/dist/interaction/project-tools.js +527 -0
- package/dist/interaction/project-tools.js.map +1 -0
- package/dist/interaction/request-router.d.ts +3 -0
- package/dist/interaction/request-router.d.ts.map +1 -0
- package/dist/interaction/request-router.js +5 -0
- package/dist/interaction/request-router.js.map +1 -0
- package/dist/interaction/runtime.d.ts +54 -0
- package/dist/interaction/runtime.d.ts.map +1 -0
- package/dist/interaction/runtime.js +943 -0
- package/dist/interaction/runtime.js.map +1 -0
- package/dist/interaction/session.d.ts +352 -0
- package/dist/interaction/session.d.ts.map +1 -0
- package/dist/interaction/session.js +98 -0
- package/dist/interaction/session.js.map +1 -0
- package/dist/interaction/truth-authority.d.ts +4 -0
- package/dist/interaction/truth-authority.d.ts.map +1 -0
- package/dist/interaction/truth-authority.js +37 -0
- package/dist/interaction/truth-authority.js.map +1 -0
- package/dist/llm/provider.d.ts +87 -0
- package/dist/llm/provider.d.ts.map +1 -0
- package/dist/llm/provider.js +798 -0
- package/dist/llm/provider.js.map +1 -0
- package/dist/models/book-rules.d.ts +118 -0
- package/dist/models/book-rules.d.ts.map +1 -0
- package/dist/models/book-rules.js +55 -0
- package/dist/models/book-rules.js.map +1 -0
- package/dist/models/book.d.ts +51 -0
- package/dist/models/book.d.ts.map +1 -0
- package/dist/models/book.js +27 -0
- package/dist/models/book.js.map +1 -0
- package/dist/models/chapter.d.ts +136 -0
- package/dist/models/chapter.d.ts.map +1 -0
- package/dist/models/chapter.js +38 -0
- package/dist/models/chapter.js.map +1 -0
- package/dist/models/detection.d.ts +25 -0
- package/dist/models/detection.d.ts.map +1 -0
- package/dist/models/detection.js +2 -0
- package/dist/models/detection.js.map +1 -0
- package/dist/models/genre-profile.d.ts +45 -0
- package/dist/models/genre-profile.d.ts.map +1 -0
- package/dist/models/genre-profile.js +26 -0
- package/dist/models/genre-profile.js.map +1 -0
- package/dist/models/input-governance.d.ts +516 -0
- package/dist/models/input-governance.d.ts.map +1 -0
- package/dist/models/input-governance.js +112 -0
- package/dist/models/input-governance.js.map +1 -0
- package/dist/models/length-governance.d.ts +93 -0
- package/dist/models/length-governance.d.ts.map +1 -0
- package/dist/models/length-governance.js +34 -0
- package/dist/models/length-governance.js.map +1 -0
- package/dist/models/project.d.ts +475 -0
- package/dist/models/project.d.ts.map +1 -0
- package/dist/models/project.js +100 -0
- package/dist/models/project.js.map +1 -0
- package/dist/models/runtime-state.d.ts +588 -0
- package/dist/models/runtime-state.d.ts.map +1 -0
- package/dist/models/runtime-state.js +93 -0
- package/dist/models/runtime-state.js.map +1 -0
- package/dist/models/state.d.ts +48 -0
- package/dist/models/state.d.ts.map +1 -0
- package/dist/models/state.js +6 -0
- package/dist/models/state.js.map +1 -0
- package/dist/models/style-profile.d.ts +16 -0
- package/dist/models/style-profile.d.ts.map +1 -0
- package/dist/models/style-profile.js +2 -0
- package/dist/models/style-profile.js.map +1 -0
- package/dist/notify/dispatcher.d.ts +10 -0
- package/dist/notify/dispatcher.d.ts.map +1 -0
- package/dist/notify/dispatcher.js +55 -0
- package/dist/notify/dispatcher.js.map +1 -0
- package/dist/notify/feishu.d.ts +5 -0
- package/dist/notify/feishu.d.ts.map +1 -0
- package/dist/notify/feishu.js +26 -0
- package/dist/notify/feishu.js.map +1 -0
- package/dist/notify/telegram.d.ts +6 -0
- package/dist/notify/telegram.d.ts.map +1 -0
- package/dist/notify/telegram.js +17 -0
- package/dist/notify/telegram.js.map +1 -0
- package/dist/notify/webhook.d.ts +15 -0
- package/dist/notify/webhook.d.ts.map +1 -0
- package/dist/notify/webhook.js +28 -0
- package/dist/notify/webhook.js.map +1 -0
- package/dist/notify/wechat-work.d.ts +5 -0
- package/dist/notify/wechat-work.d.ts.map +1 -0
- package/dist/notify/wechat-work.js +15 -0
- package/dist/notify/wechat-work.js.map +1 -0
- package/dist/pipeline/agent.d.ts +15 -0
- package/dist/pipeline/agent.d.ts.map +1 -0
- package/dist/pipeline/agent.js +550 -0
- package/dist/pipeline/agent.js.map +1 -0
- package/dist/pipeline/chapter-persistence.d.ts +33 -0
- package/dist/pipeline/chapter-persistence.d.ts.map +1 -0
- package/dist/pipeline/chapter-persistence.js +35 -0
- package/dist/pipeline/chapter-persistence.js.map +1 -0
- package/dist/pipeline/chapter-review-cycle.d.ts +79 -0
- package/dist/pipeline/chapter-review-cycle.d.ts.map +1 -0
- package/dist/pipeline/chapter-review-cycle.js +97 -0
- package/dist/pipeline/chapter-review-cycle.js.map +1 -0
- package/dist/pipeline/chapter-state-recovery.d.ts +59 -0
- package/dist/pipeline/chapter-state-recovery.d.ts.map +1 -0
- package/dist/pipeline/chapter-state-recovery.js +133 -0
- package/dist/pipeline/chapter-state-recovery.js.map +1 -0
- package/dist/pipeline/chapter-truth-validation.d.ts +41 -0
- package/dist/pipeline/chapter-truth-validation.d.ts.map +1 -0
- package/dist/pipeline/chapter-truth-validation.js +67 -0
- package/dist/pipeline/chapter-truth-validation.js.map +1 -0
- package/dist/pipeline/detection-runner.d.ts +31 -0
- package/dist/pipeline/detection-runner.d.ts.map +1 -0
- package/dist/pipeline/detection-runner.js +109 -0
- package/dist/pipeline/detection-runner.js.map +1 -0
- package/dist/pipeline/persisted-governed-plan.d.ts +4 -0
- package/dist/pipeline/persisted-governed-plan.d.ts.map +1 -0
- package/dist/pipeline/persisted-governed-plan.js +85 -0
- package/dist/pipeline/persisted-governed-plan.js.map +1 -0
- package/dist/pipeline/runner.d.ts +212 -0
- package/dist/pipeline/runner.d.ts.map +1 -0
- package/dist/pipeline/runner.js +2265 -0
- package/dist/pipeline/runner.js.map +1 -0
- package/dist/pipeline/scheduler.d.ts +58 -0
- package/dist/pipeline/scheduler.d.ts.map +1 -0
- package/dist/pipeline/scheduler.js +322 -0
- package/dist/pipeline/scheduler.js.map +1 -0
- package/dist/state/manager.d.ts +48 -0
- package/dist/state/manager.d.ts.map +1 -0
- package/dist/state/manager.js +435 -0
- package/dist/state/manager.js.map +1 -0
- package/dist/state/memory-db.d.ts +77 -0
- package/dist/state/memory-db.d.ts.map +1 -0
- package/dist/state/memory-db.js +249 -0
- package/dist/state/memory-db.js.map +1 -0
- package/dist/state/runtime-state-store.d.ts +25 -0
- package/dist/state/runtime-state-store.d.ts.map +1 -0
- package/dist/state/runtime-state-store.js +108 -0
- package/dist/state/runtime-state-store.js.map +1 -0
- package/dist/state/state-bootstrap.d.ts +21 -0
- package/dist/state/state-bootstrap.d.ts.map +1 -0
- package/dist/state/state-bootstrap.js +434 -0
- package/dist/state/state-bootstrap.js.map +1 -0
- package/dist/state/state-projections.d.ts +5 -0
- package/dist/state/state-projections.d.ts.map +1 -0
- package/dist/state/state-projections.js +166 -0
- package/dist/state/state-projections.js.map +1 -0
- package/dist/state/state-reducer.d.ts +13 -0
- package/dist/state/state-reducer.d.ts.map +1 -0
- package/dist/state/state-reducer.js +194 -0
- package/dist/state/state-reducer.js.map +1 -0
- package/dist/state/state-validator.d.ts +12 -0
- package/dist/state/state-validator.d.ts.map +1 -0
- package/dist/state/state-validator.js +67 -0
- package/dist/state/state-validator.js.map +1 -0
- package/dist/utils/analytics.d.ts +39 -0
- package/dist/utils/analytics.d.ts.map +1 -0
- package/dist/utils/analytics.js +50 -0
- package/dist/utils/analytics.js.map +1 -0
- package/dist/utils/cadence-policy.d.ts +36 -0
- package/dist/utils/cadence-policy.d.ts.map +1 -0
- package/dist/utils/cadence-policy.js +38 -0
- package/dist/utils/cadence-policy.js.map +1 -0
- package/dist/utils/chapter-cadence.d.ts +34 -0
- package/dist/utils/chapter-cadence.d.ts.map +1 -0
- package/dist/utils/chapter-cadence.js +142 -0
- package/dist/utils/chapter-cadence.js.map +1 -0
- package/dist/utils/chapter-splitter.d.ts +18 -0
- package/dist/utils/chapter-splitter.d.ts.map +1 -0
- package/dist/utils/chapter-splitter.js +60 -0
- package/dist/utils/chapter-splitter.js.map +1 -0
- package/dist/utils/config-loader.d.ts +15 -0
- package/dist/utils/config-loader.d.ts.map +1 -0
- package/dist/utils/config-loader.js +136 -0
- package/dist/utils/config-loader.js.map +1 -0
- package/dist/utils/context-filter.d.ts +20 -0
- package/dist/utils/context-filter.d.ts.map +1 -0
- package/dist/utils/context-filter.js +134 -0
- package/dist/utils/context-filter.js.map +1 -0
- package/dist/utils/governed-context.d.ts +11 -0
- package/dist/utils/governed-context.d.ts.map +1 -0
- package/dist/utils/governed-context.js +42 -0
- package/dist/utils/governed-context.js.map +1 -0
- package/dist/utils/governed-working-set.d.ts +18 -0
- package/dist/utils/governed-working-set.d.ts.map +1 -0
- package/dist/utils/governed-working-set.js +296 -0
- package/dist/utils/governed-working-set.js.map +1 -0
- package/dist/utils/hook-agenda.d.ts +21 -0
- package/dist/utils/hook-agenda.d.ts.map +1 -0
- package/dist/utils/hook-agenda.js +95 -0
- package/dist/utils/hook-agenda.js.map +1 -0
- package/dist/utils/hook-arbiter.d.ts +15 -0
- package/dist/utils/hook-arbiter.d.ts.map +1 -0
- package/dist/utils/hook-arbiter.js +268 -0
- package/dist/utils/hook-arbiter.js.map +1 -0
- package/dist/utils/hook-governance.d.ts +28 -0
- package/dist/utils/hook-governance.d.ts.map +1 -0
- package/dist/utils/hook-governance.js +144 -0
- package/dist/utils/hook-governance.js.map +1 -0
- package/dist/utils/hook-health.d.ts +15 -0
- package/dist/utils/hook-health.d.ts.map +1 -0
- package/dist/utils/hook-health.js +128 -0
- package/dist/utils/hook-health.js.map +1 -0
- package/dist/utils/hook-lifecycle.d.ts +34 -0
- package/dist/utils/hook-lifecycle.d.ts.map +1 -0
- package/dist/utils/hook-lifecycle.js +125 -0
- package/dist/utils/hook-lifecycle.js.map +1 -0
- package/dist/utils/hook-policy.d.ts +74 -0
- package/dist/utils/hook-policy.d.ts.map +1 -0
- package/dist/utils/hook-policy.js +126 -0
- package/dist/utils/hook-policy.js.map +1 -0
- package/dist/utils/length-metrics.d.ts +10 -0
- package/dist/utils/length-metrics.d.ts.map +1 -0
- package/dist/utils/length-metrics.js +85 -0
- package/dist/utils/length-metrics.js.map +1 -0
- package/dist/utils/logger.d.ts +31 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +79 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/long-span-fatigue.d.ts +28 -0
- package/dist/utils/long-span-fatigue.d.ts.map +1 -0
- package/dist/utils/long-span-fatigue.js +406 -0
- package/dist/utils/long-span-fatigue.js.map +1 -0
- package/dist/utils/memory-retrieval.d.ts +25 -0
- package/dist/utils/memory-retrieval.d.ts.map +1 -0
- package/dist/utils/memory-retrieval.js +319 -0
- package/dist/utils/memory-retrieval.js.map +1 -0
- package/dist/utils/pov-filter.d.ts +30 -0
- package/dist/utils/pov-filter.d.ts.map +1 -0
- package/dist/utils/pov-filter.js +129 -0
- package/dist/utils/pov-filter.js.map +1 -0
- package/dist/utils/spot-fix-patches.d.ts +14 -0
- package/dist/utils/spot-fix-patches.d.ts.map +1 -0
- package/dist/utils/spot-fix-patches.js +75 -0
- package/dist/utils/spot-fix-patches.js.map +1 -0
- package/dist/utils/story-markdown.d.ts +13 -0
- package/dist/utils/story-markdown.d.ts.map +1 -0
- package/dist/utils/story-markdown.js +218 -0
- package/dist/utils/story-markdown.js.map +1 -0
- package/dist/utils/web-search.d.ts +23 -0
- package/dist/utils/web-search.d.ts.map +1 -0
- package/dist/utils/web-search.js +68 -0
- package/dist/utils/web-search.js.map +1 -0
- package/genres/cozy.md +43 -0
- package/genres/cultivation.md +42 -0
- package/genres/dungeon-core.md +40 -0
- package/genres/horror.md +51 -0
- package/genres/isekai.md +43 -0
- package/genres/litrpg.md +43 -0
- package/genres/other.md +24 -0
- package/genres/progression.md +41 -0
- package/genres/romantasy.md +45 -0
- package/genres/sci-fi.md +42 -0
- package/genres/system-apocalypse.md +40 -0
- package/genres/tower-climber.md +41 -0
- package/genres/urban.md +53 -0
- package/genres/xianxia.md +46 -0
- package/genres/xuanhuan.md +64 -0
- package/package.json +58 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"continuity.d.ts","sourceRoot":"","sources":["../../src/agents/continuity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAItC,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAQ/E,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IAC3C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,CAAC,EAAE;QACpB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;QAC9B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;QAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;KAC9B,CAAC;CACH;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,QAAQ,EAAE,UAAU,GAAG,SAAS,GAAG,MAAM,CAAC;IACnD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AA4RD,qBAAa,iBAAkB,SAAQ,SAAS;IAC9C,IAAI,IAAI,IAAI,MAAM,CAEjB;IAEK,YAAY,CAChB,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,MAAM,EACtB,aAAa,EAAE,MAAM,EACrB,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;QACR,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,cAAc,CAAC,EAAE,cAAc,CAAC;QAChC,SAAS,CAAC,EAAE,SAAS,CAAC;QACtB,kBAAkB,CAAC,EAAE;YACnB,YAAY,CAAC,EAAE,MAAM,CAAC;YACtB,MAAM,CAAC,EAAE,MAAM,CAAC;YAChB,KAAK,CAAC,EAAE,MAAM,CAAC;SAChB,CAAC;KACH,GACA,OAAO,CAAC,WAAW,CAAC;IAwNvB,OAAO,CAAC,gBAAgB;IAuExB,OAAO,CAAC,wBAAwB;IA4ChC,OAAO,CAAC,mBAAmB;IAY3B,OAAO,CAAC,iBAAiB;YAqBX,mBAAmB;YAcnB,YAAY;CAO3B"}
|
|
@@ -0,0 +1,612 @@
|
|
|
1
|
+
import { BaseAgent } from "./base.js";
|
|
2
|
+
import { readGenreProfile, readBookLanguage, readBookRules } from "./rules-reader.js";
|
|
3
|
+
import { getFanficDimensionConfig, FANFIC_DIMENSIONS } from "./fanfic-dimensions.js";
|
|
4
|
+
import { readFile, readdir } from "node:fs/promises";
|
|
5
|
+
import { filterHooks, filterSummaries, filterSubplots, filterEmotionalArcs, filterCharacterMatrix } from "../utils/context-filter.js";
|
|
6
|
+
import { buildGovernedMemoryEvidenceBlocks } from "../utils/governed-context.js";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
const DIMENSION_LABELS = {
|
|
9
|
+
1: { zh: "OOC检查", en: "OOC Check" },
|
|
10
|
+
2: { zh: "时间线检查", en: "Timeline Check" },
|
|
11
|
+
3: { zh: "设定冲突", en: "Lore Conflict Check" },
|
|
12
|
+
4: { zh: "战力崩坏", en: "Power Scaling Check" },
|
|
13
|
+
5: { zh: "数值检查", en: "Numerical Consistency Check" },
|
|
14
|
+
6: { zh: "伏笔检查", en: "Hook Check" },
|
|
15
|
+
7: { zh: "节奏检查", en: "Pacing Check" },
|
|
16
|
+
8: { zh: "文风检查", en: "Style Check" },
|
|
17
|
+
9: { zh: "信息越界", en: "Information Boundary Check" },
|
|
18
|
+
10: { zh: "词汇疲劳", en: "Lexical Fatigue Check" },
|
|
19
|
+
11: { zh: "利益链断裂", en: "Incentive Chain Check" },
|
|
20
|
+
12: { zh: "年代考据", en: "Era Accuracy Check" },
|
|
21
|
+
13: { zh: "配角降智", en: "Side Character Competence Check" },
|
|
22
|
+
14: { zh: "配角工具人化", en: "Side Character Instrumentalization Check" },
|
|
23
|
+
15: { zh: "爽点虚化", en: "Payoff Dilution Check" },
|
|
24
|
+
16: { zh: "台词失真", en: "Dialogue Authenticity Check" },
|
|
25
|
+
17: { zh: "流水账", en: "Chronicle Drift Check" },
|
|
26
|
+
18: { zh: "知识库污染", en: "Knowledge Base Pollution Check" },
|
|
27
|
+
19: { zh: "视角一致性", en: "POV Consistency Check" },
|
|
28
|
+
20: { zh: "段落等长", en: "Paragraph Uniformity Check" },
|
|
29
|
+
21: { zh: "套话密度", en: "Cliche Density Check" },
|
|
30
|
+
22: { zh: "公式化转折", en: "Formulaic Twist Check" },
|
|
31
|
+
23: { zh: "列表式结构", en: "List-like Structure Check" },
|
|
32
|
+
24: { zh: "支线停滞", en: "Subplot Stagnation Check" },
|
|
33
|
+
25: { zh: "弧线平坦", en: "Arc Flatline Check" },
|
|
34
|
+
26: { zh: "节奏单调", en: "Pacing Monotony Check" },
|
|
35
|
+
27: { zh: "敏感词检查", en: "Sensitive Content Check" },
|
|
36
|
+
28: { zh: "正传事件冲突", en: "Mainline Canon Event Conflict" },
|
|
37
|
+
29: { zh: "未来信息泄露", en: "Future Knowledge Leak Check" },
|
|
38
|
+
30: { zh: "世界规则跨书一致性", en: "Cross-Book World Rule Check" },
|
|
39
|
+
31: { zh: "番外伏笔隔离", en: "Spinoff Hook Isolation Check" },
|
|
40
|
+
32: { zh: "读者期待管理", en: "Reader Expectation Check" },
|
|
41
|
+
33: { zh: "大纲偏离检测", en: "Outline Drift Check" },
|
|
42
|
+
34: { zh: "角色还原度", en: "Character Fidelity Check" },
|
|
43
|
+
35: { zh: "世界规则遵守", en: "World Rule Compliance Check" },
|
|
44
|
+
36: { zh: "关系动态", en: "Relationship Dynamics Check" },
|
|
45
|
+
37: { zh: "正典事件一致性", en: "Canon Event Consistency Check" },
|
|
46
|
+
};
|
|
47
|
+
function containsChinese(text) {
|
|
48
|
+
return /[\u4e00-\u9fff]/u.test(text);
|
|
49
|
+
}
|
|
50
|
+
function resolveGenreLabel(genreId, profileName, language) {
|
|
51
|
+
if (language === "zh" || !containsChinese(profileName)) {
|
|
52
|
+
return profileName;
|
|
53
|
+
}
|
|
54
|
+
if (genreId === "other") {
|
|
55
|
+
return "general";
|
|
56
|
+
}
|
|
57
|
+
return genreId.replace(/[_-]+/g, " ");
|
|
58
|
+
}
|
|
59
|
+
function dimensionName(id, language) {
|
|
60
|
+
return DIMENSION_LABELS[id]?.[language];
|
|
61
|
+
}
|
|
62
|
+
function joinLocalized(items, language) {
|
|
63
|
+
return items.join(language === "en" ? ", " : "、");
|
|
64
|
+
}
|
|
65
|
+
function formatFanficSeverityNote(severity, language) {
|
|
66
|
+
if (language === "en") {
|
|
67
|
+
return severity === "critical"
|
|
68
|
+
? "Strict check."
|
|
69
|
+
: severity === "info"
|
|
70
|
+
? "Log only; do not fail the chapter."
|
|
71
|
+
: "Warning level.";
|
|
72
|
+
}
|
|
73
|
+
return severity === "critical"
|
|
74
|
+
? "(严格检查)"
|
|
75
|
+
: severity === "info"
|
|
76
|
+
? "(仅记录,不判定失败)"
|
|
77
|
+
: "(警告级别)";
|
|
78
|
+
}
|
|
79
|
+
function buildDimensionNote(id, language, gp, bookRules, fanficMode, fanficConfig) {
|
|
80
|
+
const words = bookRules?.fatigueWordsOverride && bookRules.fatigueWordsOverride.length > 0
|
|
81
|
+
? bookRules.fatigueWordsOverride
|
|
82
|
+
: gp.fatigueWords;
|
|
83
|
+
if (fanficConfig?.notes.has(id) && language === "zh") {
|
|
84
|
+
return fanficConfig.notes.get(id);
|
|
85
|
+
}
|
|
86
|
+
if (id === 1 && fanficMode === "ooc") {
|
|
87
|
+
return language === "en"
|
|
88
|
+
? "In OOC mode, personality drift can be intentional; record only, do not fail. Evaluate against the character dossiers in fanfic_canon.md."
|
|
89
|
+
: "OOC模式下角色可偏离性格底色,此维度仅记录不判定失败。参照 fanfic_canon.md 角色档案评估偏离程度。";
|
|
90
|
+
}
|
|
91
|
+
if (id === 1 && fanficMode === "canon") {
|
|
92
|
+
return language === "en"
|
|
93
|
+
? "Canon-faithful fanfic: characters must stay close to their original personality core. Evaluate against fanfic_canon.md character dossiers."
|
|
94
|
+
: "原作向同人:角色必须严格遵守性格底色。参照 fanfic_canon.md 角色档案中的性格底色和行为模式。";
|
|
95
|
+
}
|
|
96
|
+
if (id === 10 && words.length > 0) {
|
|
97
|
+
return language === "en"
|
|
98
|
+
? `Fatigue words: ${words.join(", ")}. Also check AI tell markers (仿佛/不禁/宛如/竟然/忽然/猛地); warn when any appears more than once per 3,000 words.`
|
|
99
|
+
: `高疲劳词:${words.join("、")}。同时检查AI标记词(仿佛/不禁/宛如/竟然/忽然/猛地)密度,每3000字超过1次即warning`;
|
|
100
|
+
}
|
|
101
|
+
if (id === 15 && gp.satisfactionTypes.length > 0) {
|
|
102
|
+
return language === "en"
|
|
103
|
+
? `Payoff types: ${gp.satisfactionTypes.join(", ")}`
|
|
104
|
+
: `爽点类型:${gp.satisfactionTypes.join("、")}`;
|
|
105
|
+
}
|
|
106
|
+
if (id === 12 && bookRules?.eraConstraints) {
|
|
107
|
+
const era = bookRules.eraConstraints;
|
|
108
|
+
const parts = [era.period, era.region].filter(Boolean);
|
|
109
|
+
if (parts.length > 0) {
|
|
110
|
+
return language === "en"
|
|
111
|
+
? `Era: ${parts.join(", ")}`
|
|
112
|
+
: `年代:${parts.join(",")}`;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
switch (id) {
|
|
116
|
+
case 19:
|
|
117
|
+
return language === "en"
|
|
118
|
+
? "Check whether POV shifts are signaled clearly and stay consistent with the configured viewpoint."
|
|
119
|
+
: "检查视角切换是否有过渡、是否与设定视角一致";
|
|
120
|
+
case 24:
|
|
121
|
+
return language === "en"
|
|
122
|
+
? "Cross-check subplot_board and chapter_summaries: flag any subplot that stays dormant long enough to feel abandoned, or a recent run where every subplot is only restated instead of genuinely moving."
|
|
123
|
+
: "对照 subplot_board 和 chapter_summaries:标记那些沉寂到接近被遗忘的支线,或近期连续只被重复提及、没有真实推进的支线。";
|
|
124
|
+
case 25:
|
|
125
|
+
return language === "en"
|
|
126
|
+
? "Cross-check emotional_arcs and chapter_summaries: flag any major character whose emotional line holds one pressure shape across a run instead of taking new pressure, release, reversal, or reinterpretation. Distinguish unchanged circumstances from unchanged inner movement."
|
|
127
|
+
: "对照 emotional_arcs 和 chapter_summaries:标记主要角色在一段时间内始终停留在同一种情绪压力形态、没有新压力、释放、转折或重估的情况。注意区分'处境未变'和'内心未变'。";
|
|
128
|
+
case 26:
|
|
129
|
+
return language === "en"
|
|
130
|
+
? "Cross-check chapter_summaries for chapter-type distribution: warn when the recent sequence stays in the same mode long enough to flatten rhythm, or when payoff / release beats disappear for too long. Explicitly list the recent type sequence."
|
|
131
|
+
: "对照 chapter_summaries 的章节类型分布:当近期章节长时间停留在同一种模式、把节奏压平,或回收/释放/高潮章节缺席过久时给出 warning。请明确列出最近章节的类型序列。";
|
|
132
|
+
case 28:
|
|
133
|
+
return language === "en"
|
|
134
|
+
? "Check whether spinoff events contradict the mainline canon constraints."
|
|
135
|
+
: "检查番外事件是否与正典约束表矛盾";
|
|
136
|
+
case 29:
|
|
137
|
+
return language === "en"
|
|
138
|
+
? "Check whether characters reference information that should only be revealed after the divergence point (see the information-boundary table)."
|
|
139
|
+
: "检查角色是否引用了分歧点之后才揭示的信息(参照信息边界表)";
|
|
140
|
+
case 30:
|
|
141
|
+
return language === "en"
|
|
142
|
+
? "Check whether the spinoff violates mainline world rules (power system, geography, factions)."
|
|
143
|
+
: "检查番外是否违反正传世界规则(力量体系、地理、阵营)";
|
|
144
|
+
case 31:
|
|
145
|
+
return language === "en"
|
|
146
|
+
? "Check whether the spinoff resolves mainline hooks without authorization (warning level)."
|
|
147
|
+
: "检查番外是否越权回收正传伏笔(warning级别)";
|
|
148
|
+
case 32:
|
|
149
|
+
return language === "en"
|
|
150
|
+
? "Check whether the ending renews curiosity, whether promised payoffs are landing on the cadence their hooks imply, whether pressure gets any release, and whether reader expectation gaps are accumulating faster than they are being satisfied."
|
|
151
|
+
: "检查:章尾是否重新点燃好奇心,已经承诺的回收是否按伏笔自身节奏落地,压力是否得到释放,读者期待缺口是在持续累积还是在被满足。";
|
|
152
|
+
case 33:
|
|
153
|
+
return language === "en"
|
|
154
|
+
? "Cross-check volume_outline: does this chapter match the planned beat for the current chapter range? Did it skip planned nodes or consume later nodes too early? Does actual pacing match the planned chapter span? If a beat planned for N chapters is consumed in 1-2 chapters -> critical."
|
|
155
|
+
: "对照 volume_outline:本章内容是否对应卷纲中当前章节范围的剧情节点?是否跳过了节点或提前消耗了后续节点?剧情推进速度是否与卷纲规划的章节跨度匹配?如果卷纲规划某段剧情跨N章但实际1-2章就讲完→critical";
|
|
156
|
+
case 34:
|
|
157
|
+
case 35:
|
|
158
|
+
case 36:
|
|
159
|
+
case 37: {
|
|
160
|
+
if (!fanficConfig)
|
|
161
|
+
return "";
|
|
162
|
+
const severity = fanficConfig.severityOverrides.get(id) ?? "warning";
|
|
163
|
+
const baseNote = language === "en"
|
|
164
|
+
? {
|
|
165
|
+
34: "Check whether dialogue tics, speaking style, and behavior remain consistent with the character dossiers in fanfic_canon.md. Deviations need clear situational motivation.",
|
|
166
|
+
35: "Check whether the chapter violates world rules documented in fanfic_canon.md (geography, power system, faction relations).",
|
|
167
|
+
36: "Check whether relationship beats remain plausible and aligned with, or meaningfully develop from, the key relationships documented in fanfic_canon.md.",
|
|
168
|
+
37: "Check whether the chapter contradicts the key event timeline in fanfic_canon.md.",
|
|
169
|
+
}[id]
|
|
170
|
+
: FANFIC_DIMENSIONS.find((dimension) => dimension.id === id)?.baseNote;
|
|
171
|
+
return baseNote
|
|
172
|
+
? `${baseNote} ${formatFanficSeverityNote(severity, language)}`
|
|
173
|
+
: "";
|
|
174
|
+
}
|
|
175
|
+
default:
|
|
176
|
+
return "";
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
function buildDimensionList(gp, bookRules, language, hasParentCanon = false, fanficMode) {
|
|
180
|
+
const activeIds = new Set(gp.auditDimensions);
|
|
181
|
+
// Add book-level additional dimensions (supports both numeric IDs and name strings)
|
|
182
|
+
if (bookRules?.additionalAuditDimensions) {
|
|
183
|
+
// Build reverse lookup: name → id
|
|
184
|
+
const nameToId = new Map();
|
|
185
|
+
for (const [id, labels] of Object.entries(DIMENSION_LABELS)) {
|
|
186
|
+
nameToId.set(labels.zh, Number(id));
|
|
187
|
+
nameToId.set(labels.en, Number(id));
|
|
188
|
+
}
|
|
189
|
+
for (const d of bookRules.additionalAuditDimensions) {
|
|
190
|
+
if (typeof d === "number") {
|
|
191
|
+
activeIds.add(d);
|
|
192
|
+
}
|
|
193
|
+
else if (typeof d === "string") {
|
|
194
|
+
// Try exact match first, then substring match
|
|
195
|
+
const exactId = nameToId.get(d);
|
|
196
|
+
if (exactId !== undefined) {
|
|
197
|
+
activeIds.add(exactId);
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
// Fuzzy: find dimension whose name contains the string
|
|
201
|
+
for (const [name, id] of nameToId) {
|
|
202
|
+
if (name.includes(d) || d.includes(name)) {
|
|
203
|
+
activeIds.add(id);
|
|
204
|
+
break;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
// Always-active dimensions
|
|
212
|
+
activeIds.add(32); // 读者期待管理 — universal
|
|
213
|
+
activeIds.add(33); // 大纲偏离检测 — universal
|
|
214
|
+
// Conditional overrides
|
|
215
|
+
if (gp.eraResearch || bookRules?.eraConstraints?.enabled) {
|
|
216
|
+
activeIds.add(12);
|
|
217
|
+
}
|
|
218
|
+
// Spinoff dimensions — activated when parent_canon.md exists (but NOT in fanfic mode)
|
|
219
|
+
if (hasParentCanon && !fanficMode) {
|
|
220
|
+
activeIds.add(28); // 正传事件冲突
|
|
221
|
+
activeIds.add(29); // 未来信息泄露
|
|
222
|
+
activeIds.add(30); // 世界规则跨书一致性
|
|
223
|
+
activeIds.add(31); // 番外伏笔隔离
|
|
224
|
+
}
|
|
225
|
+
// Fanfic dimensions — replace spinoff dims with fanfic-specific checks
|
|
226
|
+
let fanficConfig;
|
|
227
|
+
if (fanficMode) {
|
|
228
|
+
fanficConfig = getFanficDimensionConfig(fanficMode, bookRules?.allowedDeviations);
|
|
229
|
+
for (const id of fanficConfig.activeIds) {
|
|
230
|
+
activeIds.add(id);
|
|
231
|
+
}
|
|
232
|
+
for (const id of fanficConfig.deactivatedIds) {
|
|
233
|
+
activeIds.delete(id);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
const dims = [];
|
|
237
|
+
for (const id of [...activeIds].sort((a, b) => a - b)) {
|
|
238
|
+
const name = dimensionName(id, language);
|
|
239
|
+
if (!name)
|
|
240
|
+
continue;
|
|
241
|
+
const note = buildDimensionNote(id, language, gp, bookRules, fanficMode, fanficConfig);
|
|
242
|
+
dims.push({ id, name, note });
|
|
243
|
+
}
|
|
244
|
+
return dims;
|
|
245
|
+
}
|
|
246
|
+
export class ContinuityAuditor extends BaseAgent {
|
|
247
|
+
get name() {
|
|
248
|
+
return "continuity-auditor";
|
|
249
|
+
}
|
|
250
|
+
async auditChapter(bookDir, chapterContent, chapterNumber, genre, options) {
|
|
251
|
+
const [diskCurrentState, diskLedger, diskHooks, styleGuideRaw, subplotBoard, emotionalArcs, characterMatrix, chapterSummaries, parentCanon, fanficCanon, volumeOutline] = await Promise.all([
|
|
252
|
+
this.readFileSafe(join(bookDir, "story/current_state.md")),
|
|
253
|
+
this.readFileSafe(join(bookDir, "story/particle_ledger.md")),
|
|
254
|
+
this.readFileSafe(join(bookDir, "story/pending_hooks.md")),
|
|
255
|
+
this.readFileSafe(join(bookDir, "story/style_guide.md")),
|
|
256
|
+
this.readFileSafe(join(bookDir, "story/subplot_board.md")),
|
|
257
|
+
this.readFileSafe(join(bookDir, "story/emotional_arcs.md")),
|
|
258
|
+
this.readFileSafe(join(bookDir, "story/character_matrix.md")),
|
|
259
|
+
this.readFileSafe(join(bookDir, "story/chapter_summaries.md")),
|
|
260
|
+
this.readFileSafe(join(bookDir, "story/parent_canon.md")),
|
|
261
|
+
this.readFileSafe(join(bookDir, "story/fanfic_canon.md")),
|
|
262
|
+
this.readFileSafe(join(bookDir, "story/volume_outline.md")),
|
|
263
|
+
]);
|
|
264
|
+
const currentState = options?.truthFileOverrides?.currentState ?? diskCurrentState;
|
|
265
|
+
const ledger = options?.truthFileOverrides?.ledger ?? diskLedger;
|
|
266
|
+
const hooks = options?.truthFileOverrides?.hooks ?? diskHooks;
|
|
267
|
+
const hasParentCanon = parentCanon !== "(文件不存在)";
|
|
268
|
+
const hasFanficCanon = fanficCanon !== "(文件不存在)";
|
|
269
|
+
// Load last chapter full text for fine-grained continuity checking
|
|
270
|
+
const previousChapter = await this.loadPreviousChapter(bookDir, chapterNumber);
|
|
271
|
+
// Load genre profile and book rules
|
|
272
|
+
const genreId = genre ?? "other";
|
|
273
|
+
const [{ profile: gp }, bookLanguage] = await Promise.all([
|
|
274
|
+
readGenreProfile(this.ctx.projectRoot, genreId),
|
|
275
|
+
readBookLanguage(bookDir),
|
|
276
|
+
]);
|
|
277
|
+
const parsedRules = await readBookRules(bookDir);
|
|
278
|
+
const bookRules = parsedRules?.rules ?? null;
|
|
279
|
+
// Fallback: use book_rules body when style_guide.md doesn't exist
|
|
280
|
+
const styleGuide = styleGuideRaw !== "(文件不存在)"
|
|
281
|
+
? styleGuideRaw
|
|
282
|
+
: (parsedRules?.body ?? "(无文风指南)");
|
|
283
|
+
const resolvedLanguage = bookLanguage ?? gp.language;
|
|
284
|
+
const isEnglish = resolvedLanguage === "en";
|
|
285
|
+
const fanficMode = hasFanficCanon ? bookRules?.fanficMode : undefined;
|
|
286
|
+
const dimensions = buildDimensionList(gp, bookRules, resolvedLanguage, hasParentCanon, fanficMode);
|
|
287
|
+
const dimList = dimensions
|
|
288
|
+
.map((d) => `${d.id}. ${d.name}${d.note ? (isEnglish ? ` (${d.note})` : `(${d.note})`) : ""}`)
|
|
289
|
+
.join("\n");
|
|
290
|
+
const genreLabel = resolveGenreLabel(genreId, gp.name, resolvedLanguage);
|
|
291
|
+
const protagonistBlock = bookRules?.protagonist
|
|
292
|
+
? isEnglish
|
|
293
|
+
? `\n\nProtagonist lock: ${bookRules.protagonist.name}; personality locks: ${joinLocalized(bookRules.protagonist.personalityLock, resolvedLanguage)}; behavioral constraints: ${joinLocalized(bookRules.protagonist.behavioralConstraints, resolvedLanguage)}.`
|
|
294
|
+
: `\n主角人设锁定:${bookRules.protagonist.name},${bookRules.protagonist.personalityLock.join("、")},行为约束:${bookRules.protagonist.behavioralConstraints.join("、")}`
|
|
295
|
+
: "";
|
|
296
|
+
const searchNote = gp.eraResearch
|
|
297
|
+
? isEnglish
|
|
298
|
+
? "\n\nYou have web-search capability (search_web / fetch_url). For real-world eras, people, events, geography, or policies, you must verify with search_web instead of relying on memory. Cross-check at least 2 sources."
|
|
299
|
+
: "\n\n你有联网搜索能力(search_web / fetch_url)。对于涉及真实年代、人物、事件、地理、政策的内容,你必须用search_web核实,不可凭记忆判断。至少对比2个来源交叉验证。"
|
|
300
|
+
: "";
|
|
301
|
+
const systemPrompt = isEnglish
|
|
302
|
+
? `You are a strict ${genreLabel} web fiction editor. Audit the chapter for continuity, consistency, and quality. ALL OUTPUT MUST BE IN ENGLISH.${protagonistBlock}${searchNote}
|
|
303
|
+
|
|
304
|
+
Audit dimensions:
|
|
305
|
+
${dimList}
|
|
306
|
+
|
|
307
|
+
Output format MUST be JSON:
|
|
308
|
+
{
|
|
309
|
+
"passed": true/false,
|
|
310
|
+
"issues": [
|
|
311
|
+
{
|
|
312
|
+
"severity": "critical|warning|info",
|
|
313
|
+
"category": "dimension name",
|
|
314
|
+
"description": "specific issue description",
|
|
315
|
+
"suggestion": "fix suggestion"
|
|
316
|
+
}
|
|
317
|
+
],
|
|
318
|
+
"summary": "one-sentence audit conclusion"
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
passed is false ONLY when critical-severity issues exist.`
|
|
322
|
+
: `你是一位严格的${gp.name}网络小说审稿编辑。你的任务是对章节进行连续性、一致性和质量审查。${protagonistBlock}${searchNote}
|
|
323
|
+
|
|
324
|
+
审查维度:
|
|
325
|
+
${dimList}
|
|
326
|
+
|
|
327
|
+
输出格式必须为 JSON:
|
|
328
|
+
{
|
|
329
|
+
"passed": true/false,
|
|
330
|
+
"issues": [
|
|
331
|
+
{
|
|
332
|
+
"severity": "critical|warning|info",
|
|
333
|
+
"category": "审查维度名称",
|
|
334
|
+
"description": "具体问题描述",
|
|
335
|
+
"suggestion": "修改建议"
|
|
336
|
+
}
|
|
337
|
+
],
|
|
338
|
+
"summary": "一句话总结审查结论"
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
只有当存在 critical 级别问题时,passed 才为 false。`;
|
|
342
|
+
const ledgerBlock = gp.numericalSystem
|
|
343
|
+
? isEnglish
|
|
344
|
+
? `\n## Resource Ledger\n${ledger}`
|
|
345
|
+
: `\n## 资源账本\n${ledger}`
|
|
346
|
+
: "";
|
|
347
|
+
// Smart context filtering for auditor — same logic as writer
|
|
348
|
+
const bookRulesForFilter = parsedRules?.rules ?? null;
|
|
349
|
+
const filteredSubplots = filterSubplots(subplotBoard);
|
|
350
|
+
const filteredArcs = filterEmotionalArcs(emotionalArcs, chapterNumber);
|
|
351
|
+
const filteredMatrix = filterCharacterMatrix(characterMatrix, volumeOutline, bookRulesForFilter?.protagonist?.name);
|
|
352
|
+
const filteredSummaries = filterSummaries(chapterSummaries, chapterNumber);
|
|
353
|
+
const filteredHooks = filterHooks(hooks);
|
|
354
|
+
const governedMemoryBlocks = options?.contextPackage
|
|
355
|
+
? buildGovernedMemoryEvidenceBlocks(options.contextPackage, resolvedLanguage)
|
|
356
|
+
: undefined;
|
|
357
|
+
const hooksBlock = governedMemoryBlocks?.hooksBlock
|
|
358
|
+
?? (filteredHooks !== "(文件不存在)"
|
|
359
|
+
? isEnglish
|
|
360
|
+
? `\n## Pending Hooks\n${filteredHooks}\n`
|
|
361
|
+
: `\n## 伏笔池\n${filteredHooks}\n`
|
|
362
|
+
: "");
|
|
363
|
+
const subplotBlock = filteredSubplots !== "(文件不存在)"
|
|
364
|
+
? isEnglish
|
|
365
|
+
? `\n## Subplot Board\n${filteredSubplots}\n`
|
|
366
|
+
: `\n## 支线进度板\n${filteredSubplots}\n`
|
|
367
|
+
: "";
|
|
368
|
+
const emotionalBlock = filteredArcs !== "(文件不存在)"
|
|
369
|
+
? isEnglish
|
|
370
|
+
? `\n## Emotional Arcs\n${filteredArcs}\n`
|
|
371
|
+
: `\n## 情感弧线\n${filteredArcs}\n`
|
|
372
|
+
: "";
|
|
373
|
+
const matrixBlock = filteredMatrix !== "(文件不存在)"
|
|
374
|
+
? isEnglish
|
|
375
|
+
? `\n## Character Interaction Matrix\n${filteredMatrix}\n`
|
|
376
|
+
: `\n## 角色交互矩阵\n${filteredMatrix}\n`
|
|
377
|
+
: "";
|
|
378
|
+
const summariesBlock = governedMemoryBlocks?.summariesBlock
|
|
379
|
+
?? (filteredSummaries !== "(文件不存在)"
|
|
380
|
+
? isEnglish
|
|
381
|
+
? `\n## Chapter Summaries (for pacing checks)\n${filteredSummaries}\n`
|
|
382
|
+
: `\n## 章节摘要(用于节奏检查)\n${filteredSummaries}\n`
|
|
383
|
+
: "");
|
|
384
|
+
const volumeSummariesBlock = governedMemoryBlocks?.volumeSummariesBlock ?? "";
|
|
385
|
+
const canonBlock = hasParentCanon
|
|
386
|
+
? isEnglish
|
|
387
|
+
? `\n## Mainline Canon Reference (for spinoff audit)\n${parentCanon}\n`
|
|
388
|
+
: `\n## 正传正典参照(番外审查专用)\n${parentCanon}\n`
|
|
389
|
+
: "";
|
|
390
|
+
const fanficCanonBlock = hasFanficCanon
|
|
391
|
+
? isEnglish
|
|
392
|
+
? `\n## Fanfic Canon Reference (for fanfic audit)\n${fanficCanon}\n`
|
|
393
|
+
: `\n## 同人正典参照(同人审查专用)\n${fanficCanon}\n`
|
|
394
|
+
: "";
|
|
395
|
+
const outlineBlock = volumeOutline !== "(文件不存在)"
|
|
396
|
+
? isEnglish
|
|
397
|
+
? `\n## Volume Outline (for outline drift checks)\n${volumeOutline}\n`
|
|
398
|
+
: `\n## 卷纲(用于大纲偏离检测)\n${volumeOutline}\n`
|
|
399
|
+
: "";
|
|
400
|
+
const reducedControlBlock = options?.chapterIntent && options.contextPackage && options.ruleStack
|
|
401
|
+
? this.buildReducedControlBlock(options.chapterIntent, options.contextPackage, options.ruleStack, resolvedLanguage)
|
|
402
|
+
: "";
|
|
403
|
+
const styleGuideBlock = reducedControlBlock.length === 0
|
|
404
|
+
? isEnglish
|
|
405
|
+
? `\n## Style Guide\n${styleGuide}`
|
|
406
|
+
: `\n## 文风指南\n${styleGuide}`
|
|
407
|
+
: "";
|
|
408
|
+
const prevChapterBlock = previousChapter
|
|
409
|
+
? isEnglish
|
|
410
|
+
? `\n## Previous Chapter Full Text (for transition checks)\n${previousChapter}\n`
|
|
411
|
+
: `\n## 上一章全文(用于衔接检查)\n${previousChapter}\n`
|
|
412
|
+
: "";
|
|
413
|
+
const userPrompt = isEnglish
|
|
414
|
+
? `Review chapter ${chapterNumber}.
|
|
415
|
+
|
|
416
|
+
## Current State Card
|
|
417
|
+
${currentState}
|
|
418
|
+
${ledgerBlock}
|
|
419
|
+
${hooksBlock}${volumeSummariesBlock}${subplotBlock}${emotionalBlock}${matrixBlock}${summariesBlock}${canonBlock}${fanficCanonBlock}${reducedControlBlock || outlineBlock}${prevChapterBlock}${styleGuideBlock}
|
|
420
|
+
|
|
421
|
+
## Chapter Content Under Review
|
|
422
|
+
${chapterContent}`
|
|
423
|
+
: `请审查第${chapterNumber}章。
|
|
424
|
+
|
|
425
|
+
## 当前状态卡
|
|
426
|
+
${currentState}
|
|
427
|
+
${ledgerBlock}
|
|
428
|
+
${hooksBlock}${volumeSummariesBlock}${subplotBlock}${emotionalBlock}${matrixBlock}${summariesBlock}${canonBlock}${fanficCanonBlock}${reducedControlBlock || outlineBlock}${prevChapterBlock}${styleGuideBlock}
|
|
429
|
+
|
|
430
|
+
## 待审章节内容
|
|
431
|
+
${chapterContent}`;
|
|
432
|
+
const chatMessages = [
|
|
433
|
+
{ role: "system", content: systemPrompt },
|
|
434
|
+
{ role: "user", content: userPrompt },
|
|
435
|
+
];
|
|
436
|
+
const chatOptions = { temperature: options?.temperature ?? 0.3, maxTokens: 8192 };
|
|
437
|
+
// Use web search for fact verification when eraResearch is enabled
|
|
438
|
+
const response = gp.eraResearch
|
|
439
|
+
? await this.chatWithSearch(chatMessages, chatOptions)
|
|
440
|
+
: await this.chat(chatMessages, chatOptions);
|
|
441
|
+
const result = this.parseAuditResult(response.content, resolvedLanguage);
|
|
442
|
+
return { ...result, tokenUsage: response.usage };
|
|
443
|
+
}
|
|
444
|
+
parseAuditResult(content, language) {
|
|
445
|
+
// Try multiple JSON extraction strategies (handles small/local models)
|
|
446
|
+
// Strategy 1: Find balanced JSON object (not greedy)
|
|
447
|
+
const balanced = this.extractBalancedJson(content);
|
|
448
|
+
if (balanced) {
|
|
449
|
+
const result = this.tryParseAuditJson(balanced, language);
|
|
450
|
+
if (result)
|
|
451
|
+
return result;
|
|
452
|
+
}
|
|
453
|
+
// Strategy 2: Try the whole content as JSON (some models output pure JSON)
|
|
454
|
+
const trimmed = content.trim();
|
|
455
|
+
if (trimmed.startsWith("{")) {
|
|
456
|
+
const result = this.tryParseAuditJson(trimmed, language);
|
|
457
|
+
if (result)
|
|
458
|
+
return result;
|
|
459
|
+
}
|
|
460
|
+
// Strategy 3: Look for ```json code blocks
|
|
461
|
+
const codeBlockMatch = content.match(/```(?:json)?\s*\n?([\s\S]*?)\n?```/);
|
|
462
|
+
if (codeBlockMatch) {
|
|
463
|
+
const result = this.tryParseAuditJson(codeBlockMatch[1].trim(), language);
|
|
464
|
+
if (result)
|
|
465
|
+
return result;
|
|
466
|
+
}
|
|
467
|
+
// Strategy 4: Try to extract individual fields via regex (last resort fallback)
|
|
468
|
+
const passedMatch = content.match(/"passed"\s*:\s*(true|false)/);
|
|
469
|
+
const issuesMatch = content.match(/"issues"\s*:\s*\[([\s\S]*?)\]/);
|
|
470
|
+
const summaryMatch = content.match(/"summary"\s*:\s*"([^"]*)"/);
|
|
471
|
+
if (passedMatch) {
|
|
472
|
+
const issues = [];
|
|
473
|
+
if (issuesMatch) {
|
|
474
|
+
// Try to parse individual issue objects
|
|
475
|
+
const issuePattern = /\{[^{}]*"severity"\s*:\s*"[^"]*"[^{}]*\}/g;
|
|
476
|
+
let match;
|
|
477
|
+
while ((match = issuePattern.exec(issuesMatch[1])) !== null) {
|
|
478
|
+
try {
|
|
479
|
+
const issue = JSON.parse(match[0]);
|
|
480
|
+
issues.push({
|
|
481
|
+
severity: issue.severity ?? "warning",
|
|
482
|
+
category: issue.category ?? (language === "en" ? "Uncategorized" : "未分类"),
|
|
483
|
+
description: issue.description ?? "",
|
|
484
|
+
suggestion: issue.suggestion ?? "",
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
catch {
|
|
488
|
+
// skip malformed individual issue
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
return {
|
|
493
|
+
passed: passedMatch[1] === "true",
|
|
494
|
+
issues,
|
|
495
|
+
summary: summaryMatch?.[1] ?? "",
|
|
496
|
+
};
|
|
497
|
+
}
|
|
498
|
+
return {
|
|
499
|
+
passed: false,
|
|
500
|
+
issues: [{
|
|
501
|
+
severity: "critical",
|
|
502
|
+
category: language === "en" ? "System Error" : "系统错误",
|
|
503
|
+
description: language === "en"
|
|
504
|
+
? "Audit output format was invalid and could not be parsed as JSON."
|
|
505
|
+
: "审稿输出格式异常,无法解析为 JSON",
|
|
506
|
+
suggestion: language === "en"
|
|
507
|
+
? "The model may not support reliable structured output. Try a stronger model or inspect the API response format."
|
|
508
|
+
: "可能是模型不支持结构化输出。尝试换一个更大的模型,或检查 API 返回格式。",
|
|
509
|
+
}],
|
|
510
|
+
summary: language === "en" ? "Audit output parsing failed" : "审稿输出解析失败",
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
buildReducedControlBlock(chapterIntent, contextPackage, ruleStack, language) {
|
|
514
|
+
const selectedContext = contextPackage.selectedContext
|
|
515
|
+
.map((entry) => `- ${entry.source}: ${entry.reason}${entry.excerpt ? ` | ${entry.excerpt}` : ""}`)
|
|
516
|
+
.join("\n");
|
|
517
|
+
const overrides = ruleStack.activeOverrides.length > 0
|
|
518
|
+
? ruleStack.activeOverrides
|
|
519
|
+
.map((override) => `- ${override.from} -> ${override.to}: ${override.reason} (${override.target})`)
|
|
520
|
+
.join("\n")
|
|
521
|
+
: "- none";
|
|
522
|
+
return language === "en"
|
|
523
|
+
? `\n## Chapter Control Inputs (compiled by Planner/Composer)
|
|
524
|
+
${chapterIntent}
|
|
525
|
+
|
|
526
|
+
### Selected Context
|
|
527
|
+
${selectedContext || "- none"}
|
|
528
|
+
|
|
529
|
+
### Rule Stack
|
|
530
|
+
- Hard guardrails: ${ruleStack.sections.hard.join(", ") || "(none)"}
|
|
531
|
+
- Soft constraints: ${ruleStack.sections.soft.join(", ") || "(none)"}
|
|
532
|
+
- Diagnostic rules: ${ruleStack.sections.diagnostic.join(", ") || "(none)"}
|
|
533
|
+
|
|
534
|
+
### Active Overrides
|
|
535
|
+
${overrides}\n`
|
|
536
|
+
: `\n## 本章控制输入(由 Planner/Composer 编译)
|
|
537
|
+
${chapterIntent}
|
|
538
|
+
|
|
539
|
+
### 已选上下文
|
|
540
|
+
${selectedContext || "- none"}
|
|
541
|
+
|
|
542
|
+
### 规则栈
|
|
543
|
+
- 硬护栏:${ruleStack.sections.hard.join("、") || "(无)"}
|
|
544
|
+
- 软约束:${ruleStack.sections.soft.join("、") || "(无)"}
|
|
545
|
+
- 诊断规则:${ruleStack.sections.diagnostic.join("、") || "(无)"}
|
|
546
|
+
|
|
547
|
+
### 当前覆盖
|
|
548
|
+
${overrides}\n`;
|
|
549
|
+
}
|
|
550
|
+
extractBalancedJson(text) {
|
|
551
|
+
const start = text.indexOf("{");
|
|
552
|
+
if (start === -1)
|
|
553
|
+
return null;
|
|
554
|
+
let depth = 0;
|
|
555
|
+
for (let i = start; i < text.length; i++) {
|
|
556
|
+
if (text[i] === "{")
|
|
557
|
+
depth++;
|
|
558
|
+
if (text[i] === "}")
|
|
559
|
+
depth--;
|
|
560
|
+
if (depth === 0)
|
|
561
|
+
return text.slice(start, i + 1);
|
|
562
|
+
}
|
|
563
|
+
return null;
|
|
564
|
+
}
|
|
565
|
+
tryParseAuditJson(json, language = "zh") {
|
|
566
|
+
try {
|
|
567
|
+
const parsed = JSON.parse(json);
|
|
568
|
+
if (typeof parsed.passed !== "boolean" && parsed.passed !== undefined)
|
|
569
|
+
return null;
|
|
570
|
+
return {
|
|
571
|
+
passed: Boolean(parsed.passed ?? false),
|
|
572
|
+
issues: Array.isArray(parsed.issues)
|
|
573
|
+
? parsed.issues.map((i) => ({
|
|
574
|
+
severity: i.severity ?? "warning",
|
|
575
|
+
category: i.category ?? (language === "en" ? "Uncategorized" : "未分类"),
|
|
576
|
+
description: i.description ?? "",
|
|
577
|
+
suggestion: i.suggestion ?? "",
|
|
578
|
+
}))
|
|
579
|
+
: [],
|
|
580
|
+
summary: String(parsed.summary ?? ""),
|
|
581
|
+
};
|
|
582
|
+
}
|
|
583
|
+
catch {
|
|
584
|
+
return null;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
async loadPreviousChapter(bookDir, currentChapter) {
|
|
588
|
+
if (currentChapter <= 1)
|
|
589
|
+
return "";
|
|
590
|
+
const chaptersDir = join(bookDir, "chapters");
|
|
591
|
+
try {
|
|
592
|
+
const files = await readdir(chaptersDir);
|
|
593
|
+
const paddedPrev = String(currentChapter - 1).padStart(4, "0");
|
|
594
|
+
const prevFile = files.find((f) => f.startsWith(paddedPrev) && f.endsWith(".md"));
|
|
595
|
+
if (!prevFile)
|
|
596
|
+
return "";
|
|
597
|
+
return await readFile(join(chaptersDir, prevFile), "utf-8");
|
|
598
|
+
}
|
|
599
|
+
catch {
|
|
600
|
+
return "";
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
async readFileSafe(path) {
|
|
604
|
+
try {
|
|
605
|
+
return await readFile(path, "utf-8");
|
|
606
|
+
}
|
|
607
|
+
catch {
|
|
608
|
+
return "(文件不存在)";
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
//# sourceMappingURL=continuity.js.map
|