governed-context.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. import type { ContextPackage } from "../models/input-governance.js";
  2. export function buildGovernedMemoryEvidenceBlocks(
  3. contextPackage: ContextPackage,
  4. language?: "zh" | "en",
  5. ): {
  6. readonly hookDebtBlock?: string;
  7. readonly hooksBlock?: string;
  8. readonly summariesBlock?: string;
  9. readonly volumeSummariesBlock?: string;
  10. readonly titleHistoryBlock?: string;
  11. readonly moodTrailBlock?: string;
  12. readonly canonBlock?: string;
  13. } {
  14. const resolvedLanguage = language ?? "zh";
  15. const hookEntries = contextPackage.selectedContext.filter((entry) =>
  16. entry.source.startsWith("story/pending_hooks.md#"),
  17. );
  18. const hookDebtEntries = contextPackage.selectedContext.filter((entry) =>
  19. entry.source.startsWith("runtime/hook_debt#"),
  20. );
  21. const summaryEntries = contextPackage.selectedContext.filter((entry) =>
  22. entry.source.startsWith("story/chapter_summaries.md#"),
  23. );
  24. const volumeSummaryEntries = contextPackage.selectedContext.filter((entry) =>
  25. entry.source.startsWith("story/volume_summaries.md#"),
  26. );
  27. const titleHistoryEntries = contextPackage.selectedContext.filter((entry) =>
  28. entry.source === "story/chapter_summaries.md#recent_titles",
  29. );
  30. const moodTrailEntries = contextPackage.selectedContext.filter((entry) =>
  31. entry.source === "story/chapter_summaries.md#recent_mood_type_trail",
  32. );
  33. const canonEntries = contextPackage.selectedContext.filter((entry) =>
  34. entry.source === "story/parent_canon.md"
  35. || entry.source === "story/fanfic_canon.md",
  36. );
  37. return {
  38. hookDebtBlock: hookDebtEntries.length > 0
  39. ? renderHookDebtBlock(
  40. resolvedLanguage === "en" ? "Hook Debt Briefs" : "Hook Debt Briefs",
  41. hookDebtEntries,
  42. )
  43. : undefined,
  44. hooksBlock: hookEntries.length > 0
  45. ? renderEvidenceBlock(
  46. resolvedLanguage === "en" ? "Selected Hook Evidence" : "已选伏笔证据",
  47. hookEntries,
  48. )
  49. : undefined,
  50. summariesBlock: summaryEntries.length > 0
  51. ? renderEvidenceBlock(
  52. resolvedLanguage === "en" ? "Selected Chapter Summary Evidence" : "已选章节摘要证据",
  53. summaryEntries,
  54. )
  55. : undefined,
  56. volumeSummariesBlock: volumeSummaryEntries.length > 0
  57. ? renderEvidenceBlock(
  58. resolvedLanguage === "en" ? "Selected Volume Summary Evidence" : "已选卷级摘要证据",
  59. volumeSummaryEntries,
  60. )
  61. : undefined,
  62. titleHistoryBlock: titleHistoryEntries.length > 0
  63. ? renderEvidenceBlock(
  64. resolvedLanguage === "en" ? "Recent Title History" : "近期标题历史",
  65. titleHistoryEntries,
  66. )
  67. : undefined,
  68. moodTrailBlock: moodTrailEntries.length > 0
  69. ? renderEvidenceBlock(
  70. resolvedLanguage === "en" ? "Recent Mood / Chapter Type Trail" : "近期情绪/章节类型轨迹",
  71. moodTrailEntries,
  72. )
  73. : undefined,
  74. canonBlock: canonEntries.length > 0
  75. ? renderEvidenceBlock(
  76. resolvedLanguage === "en" ? "Canon Evidence" : "正典约束证据",
  77. canonEntries,
  78. )
  79. : undefined,
  80. };
  81. }
  82. function renderHookDebtBlock(
  83. heading: string,
  84. entries: ContextPackage["selectedContext"],
  85. ): string {
  86. return `\n## ${heading}\n${entries.map((entry) => `- ${entry.excerpt ?? entry.reason}`).join("\n")}\n`;
  87. }
  88. function renderEvidenceBlock(
  89. heading: string,
  90. entries: ContextPackage["selectedContext"],
  91. ): string {
  92. const lines = entries.map((entry) =>
  93. `- ${entry.source}: ${entry.excerpt ?? entry.reason}`,
  94. );
  95. return `\n## ${heading}\n${lines.join("\n")}\n`;
  96. }