@zwbigi/ink-xy 0.1.2 → 0.1.4

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.
Files changed (598) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-path-routes-manifest.json +2 -2
  3. package/.next/build-manifest.json +2 -2
  4. package/.next/server/app/_global-error.html +1 -1
  5. package/.next/server/app/_global-error.rsc +1 -1
  6. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  7. package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  8. package/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  9. package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  10. package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  11. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  12. package/.next/server/app/_not-found.html +1 -1
  13. package/.next/server/app/_not-found.rsc +1 -1
  14. package/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  15. package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  16. package/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  17. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  18. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  19. package/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  20. package/.next/server/app/api/inkos/route.js.nft.json +1 -1
  21. package/.next/server/app/api/skills/install/route.js.nft.json +1 -1
  22. package/.next/server/app/api/skills/search/route.js.nft.json +1 -1
  23. package/.next/server/app/index.html +1 -1
  24. package/.next/server/app/index.rsc +1 -1
  25. package/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  26. package/.next/server/app/index.segments/_full.segment.rsc +1 -1
  27. package/.next/server/app/index.segments/_head.segment.rsc +1 -1
  28. package/.next/server/app/index.segments/_index.segment.rsc +1 -1
  29. package/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  30. package/.next/server/app-paths-manifest.json +2 -2
  31. package/.next/server/chunks/162.js +1 -1
  32. package/.next/server/middleware-build-manifest.js +1 -1
  33. package/.next/server/pages/404.html +1 -1
  34. package/.next/server/pages/500.html +1 -1
  35. package/.next/trace +4 -4
  36. package/.next/trace-build +1 -1
  37. package/bin/pi-web.js +4 -1
  38. package/inkos/.env.example +20 -0
  39. package/inkos/.node-version +1 -0
  40. package/inkos/.nvmrc +1 -0
  41. package/inkos/CHANGELOG.md +787 -0
  42. package/inkos/CONTRIBUTING.md +89 -0
  43. package/inkos/LICENSE +661 -0
  44. package/inkos/README.en.md +483 -0
  45. package/inkos/README.ja.md +461 -0
  46. package/inkos/README.md +272 -0
  47. package/inkos/assets/15qun.jpg +0 -0
  48. package/inkos/assets/41777702961_.pic.jpg +0 -0
  49. package/inkos/assets/inkos-short-demo-cover.png +0 -0
  50. package/inkos/assets/inkos-text.svg +40 -0
  51. package/inkos/assets/logo.svg +47 -0
  52. package/inkos/assets/screenshot-chapters.png +0 -0
  53. package/inkos/assets/screenshot-pipeline.png +0 -0
  54. package/inkos/assets/screenshot-state.png +0 -0
  55. package/inkos/assets/screenshot-terminal.png +0 -0
  56. package/inkos/assets/wechat-group-v8.jpg +0 -0
  57. package/inkos/package.json +42 -0
  58. package/inkos/packages/cli/package.json +74 -0
  59. package/inkos/packages/cli/src/__tests__/analytics.test.ts +154 -0
  60. package/inkos/packages/cli/src/__tests__/cli-integration.test.ts +1031 -0
  61. package/inkos/packages/cli/src/__tests__/daemon.test.ts +93 -0
  62. package/inkos/packages/cli/src/__tests__/doctor.test.ts +36 -0
  63. package/inkos/packages/cli/src/__tests__/interact-command.test.ts +142 -0
  64. package/inkos/packages/cli/src/__tests__/interaction-tools.test.ts +107 -0
  65. package/inkos/packages/cli/src/__tests__/llm-overrides.test.ts +25 -0
  66. package/inkos/packages/cli/src/__tests__/localization.test.ts +121 -0
  67. package/inkos/packages/cli/src/__tests__/progress-text.test.ts +92 -0
  68. package/inkos/packages/cli/src/__tests__/project-bootstrap.test.ts +71 -0
  69. package/inkos/packages/cli/src/__tests__/publish-package.test.ts +272 -0
  70. package/inkos/packages/cli/src/__tests__/revision-command.test.ts +82 -0
  71. package/inkos/packages/cli/src/__tests__/runtime-requirements.test.ts +89 -0
  72. package/inkos/packages/cli/src/__tests__/short-fiction-command.test.ts +48 -0
  73. package/inkos/packages/cli/src/__tests__/studio-runtime.test.ts +142 -0
  74. package/inkos/packages/cli/src/__tests__/studio.test.ts +87 -0
  75. package/inkos/packages/cli/src/__tests__/tui-activity-state.test.ts +20 -0
  76. package/inkos/packages/cli/src/__tests__/tui-agent-session.test.ts +213 -0
  77. package/inkos/packages/cli/src/__tests__/tui-chat-depth.test.ts +27 -0
  78. package/inkos/packages/cli/src/__tests__/tui-chat-draft.test.ts +44 -0
  79. package/inkos/packages/cli/src/__tests__/tui-command.test.ts +86 -0
  80. package/inkos/packages/cli/src/__tests__/tui-composer-caret.test.ts +46 -0
  81. package/inkos/packages/cli/src/__tests__/tui-composer-display.test.ts +40 -0
  82. package/inkos/packages/cli/src/__tests__/tui-dashboard.test.tsx +219 -0
  83. package/inkos/packages/cli/src/__tests__/tui-effects-i18n.test.ts +29 -0
  84. package/inkos/packages/cli/src/__tests__/tui-i18n.test.ts +22 -0
  85. package/inkos/packages/cli/src/__tests__/tui-input-chrome.test.ts +10 -0
  86. package/inkos/packages/cli/src/__tests__/tui-input-history.test.ts +40 -0
  87. package/inkos/packages/cli/src/__tests__/tui-layout.test.ts +55 -0
  88. package/inkos/packages/cli/src/__tests__/tui-local-commands.test.ts +47 -0
  89. package/inkos/packages/cli/src/__tests__/tui-session-store.test.ts +81 -0
  90. package/inkos/packages/cli/src/__tests__/tui-setup-i18n.test.ts +31 -0
  91. package/inkos/packages/cli/src/__tests__/tui-slash-autocomplete.test.ts +33 -0
  92. package/inkos/packages/cli/src/commands/agent.ts +65 -0
  93. package/inkos/packages/cli/src/commands/analytics.ts +77 -0
  94. package/inkos/packages/cli/src/commands/audit.ts +52 -0
  95. package/inkos/packages/cli/src/commands/book.ts +260 -0
  96. package/inkos/packages/cli/src/commands/compose.ts +50 -0
  97. package/inkos/packages/cli/src/commands/config.ts +328 -0
  98. package/inkos/packages/cli/src/commands/consolidate.ts +50 -0
  99. package/inkos/packages/cli/src/commands/daemon.ts +121 -0
  100. package/inkos/packages/cli/src/commands/detect.ts +125 -0
  101. package/inkos/packages/cli/src/commands/doctor.ts +391 -0
  102. package/inkos/packages/cli/src/commands/draft.ts +43 -0
  103. package/inkos/packages/cli/src/commands/eval.ts +217 -0
  104. package/inkos/packages/cli/src/commands/export.ts +45 -0
  105. package/inkos/packages/cli/src/commands/fanfic.ts +183 -0
  106. package/inkos/packages/cli/src/commands/genre.ts +160 -0
  107. package/inkos/packages/cli/src/commands/import.ts +158 -0
  108. package/inkos/packages/cli/src/commands/init.ts +47 -0
  109. package/inkos/packages/cli/src/commands/interact.ts +109 -0
  110. package/inkos/packages/cli/src/commands/plan.ts +54 -0
  111. package/inkos/packages/cli/src/commands/radar.ts +60 -0
  112. package/inkos/packages/cli/src/commands/review.ts +253 -0
  113. package/inkos/packages/cli/src/commands/revise.ts +58 -0
  114. package/inkos/packages/cli/src/commands/short-fiction.ts +294 -0
  115. package/inkos/packages/cli/src/commands/status.ts +138 -0
  116. package/inkos/packages/cli/src/commands/studio.ts +194 -0
  117. package/inkos/packages/cli/src/commands/style.ts +99 -0
  118. package/inkos/packages/cli/src/commands/tui.ts +18 -0
  119. package/inkos/packages/cli/src/commands/update.ts +45 -0
  120. package/inkos/packages/cli/src/commands/write.ts +324 -0
  121. package/inkos/packages/cli/src/index.ts +5 -0
  122. package/inkos/packages/cli/src/interaction/tools.ts +49 -0
  123. package/inkos/packages/cli/src/localization.ts +215 -0
  124. package/inkos/packages/cli/src/program.ts +106 -0
  125. package/inkos/packages/cli/src/progress-text.ts +85 -0
  126. package/inkos/packages/cli/src/project-bootstrap.ts +175 -0
  127. package/inkos/packages/cli/src/runtime-requirements.ts +135 -0
  128. package/inkos/packages/cli/src/tui/__tests__/markdown.test.ts +64 -0
  129. package/inkos/packages/cli/src/tui/activity-state.ts +41 -0
  130. package/inkos/packages/cli/src/tui/agent-input.ts +264 -0
  131. package/inkos/packages/cli/src/tui/ansi.ts +72 -0
  132. package/inkos/packages/cli/src/tui/app.ts +130 -0
  133. package/inkos/packages/cli/src/tui/chat-depth.ts +22 -0
  134. package/inkos/packages/cli/src/tui/chat-draft.ts +42 -0
  135. package/inkos/packages/cli/src/tui/composer-caret.ts +22 -0
  136. package/inkos/packages/cli/src/tui/composer-display.ts +26 -0
  137. package/inkos/packages/cli/src/tui/dashboard-model.ts +164 -0
  138. package/inkos/packages/cli/src/tui/dashboard.tsx +544 -0
  139. package/inkos/packages/cli/src/tui/effects.ts +542 -0
  140. package/inkos/packages/cli/src/tui/i18n.ts +278 -0
  141. package/inkos/packages/cli/src/tui/input-history.ts +69 -0
  142. package/inkos/packages/cli/src/tui/local-commands.ts +55 -0
  143. package/inkos/packages/cli/src/tui/markdown.ts +64 -0
  144. package/inkos/packages/cli/src/tui/session-store.ts +6 -0
  145. package/inkos/packages/cli/src/tui/setup.ts +397 -0
  146. package/inkos/packages/cli/src/tui/slash-autocomplete.ts +62 -0
  147. package/inkos/packages/cli/src/tui/theme.ts +17 -0
  148. package/inkos/packages/cli/src/utils.ts +222 -0
  149. package/inkos/packages/cli/tsconfig.json +9 -0
  150. package/inkos/packages/core/genres/cozy.md +43 -0
  151. package/inkos/packages/core/genres/cultivation.md +42 -0
  152. package/inkos/packages/core/genres/dungeon-core.md +40 -0
  153. package/inkos/packages/core/genres/horror.md +51 -0
  154. package/inkos/packages/core/genres/isekai.md +43 -0
  155. package/inkos/packages/core/genres/litrpg.md +43 -0
  156. package/inkos/packages/core/genres/other.md +24 -0
  157. package/inkos/packages/core/genres/progression.md +41 -0
  158. package/inkos/packages/core/genres/romantasy.md +45 -0
  159. package/inkos/packages/core/genres/sci-fi.md +42 -0
  160. package/inkos/packages/core/genres/system-apocalypse.md +40 -0
  161. package/inkos/packages/core/genres/tower-climber.md +41 -0
  162. package/inkos/packages/core/genres/urban.md +53 -0
  163. package/inkos/packages/core/genres/xianxia.md +46 -0
  164. package/inkos/packages/core/genres/xuanhuan.md +64 -0
  165. package/inkos/packages/core/package.json +61 -0
  166. package/inkos/packages/core/src/__tests__/agent-max-tokens-policy.test.ts +29 -0
  167. package/inkos/packages/core/src/__tests__/agent-session.test.ts +866 -0
  168. package/inkos/packages/core/src/__tests__/agent-system-prompt.test.ts +167 -0
  169. package/inkos/packages/core/src/__tests__/agent-tools-params.test.ts +197 -0
  170. package/inkos/packages/core/src/__tests__/agent-tools.test.ts +421 -0
  171. package/inkos/packages/core/src/__tests__/ai-tells.test.ts +90 -0
  172. package/inkos/packages/core/src/__tests__/architect-phase5-consolidated.test.ts +445 -0
  173. package/inkos/packages/core/src/__tests__/architect-phase5.test.ts +455 -0
  174. package/inkos/packages/core/src/__tests__/architect-phase7.test.ts +210 -0
  175. package/inkos/packages/core/src/__tests__/architect.test.ts +859 -0
  176. package/inkos/packages/core/src/__tests__/audit-parse.test.ts +78 -0
  177. package/inkos/packages/core/src/__tests__/book-id.test.ts +26 -0
  178. package/inkos/packages/core/src/__tests__/book-session-store.test.ts +447 -0
  179. package/inkos/packages/core/src/__tests__/book-session.test.ts +113 -0
  180. package/inkos/packages/core/src/__tests__/chapter-analyzer.test.ts +574 -0
  181. package/inkos/packages/core/src/__tests__/chapter-memo-parser.test.ts +247 -0
  182. package/inkos/packages/core/src/__tests__/chapter-persistence.test.ts +198 -0
  183. package/inkos/packages/core/src/__tests__/chapter-review-cycle.test.ts +294 -0
  184. package/inkos/packages/core/src/__tests__/chapter-splitter.test.ts +156 -0
  185. package/inkos/packages/core/src/__tests__/chapter-state-recovery.test.ts +235 -0
  186. package/inkos/packages/core/src/__tests__/chapter-truth-validation.test.ts +253 -0
  187. package/inkos/packages/core/src/__tests__/composer.test.ts +627 -0
  188. package/inkos/packages/core/src/__tests__/config-loader.test.ts +325 -0
  189. package/inkos/packages/core/src/__tests__/config-migration.test.ts +102 -0
  190. package/inkos/packages/core/src/__tests__/consolidator.test.ts +32 -0
  191. package/inkos/packages/core/src/__tests__/context-filter.test.ts +60 -0
  192. package/inkos/packages/core/src/__tests__/context-transform.test.ts +108 -0
  193. package/inkos/packages/core/src/__tests__/continuity.test.ts +391 -0
  194. package/inkos/packages/core/src/__tests__/detection-insights.test.ts +59 -0
  195. package/inkos/packages/core/src/__tests__/detector.test.ts +86 -0
  196. package/inkos/packages/core/src/__tests__/draft-directive-parser.test.ts +386 -0
  197. package/inkos/packages/core/src/__tests__/edit-controller.test.ts +190 -0
  198. package/inkos/packages/core/src/__tests__/effective-llm-config.test.ts +486 -0
  199. package/inkos/packages/core/src/__tests__/fanfic-dimensions.test.ts +58 -0
  200. package/inkos/packages/core/src/__tests__/fanfic-models.test.ts +69 -0
  201. package/inkos/packages/core/src/__tests__/governed-working-set.test.ts +155 -0
  202. package/inkos/packages/core/src/__tests__/hook-arbiter.test.ts +124 -0
  203. package/inkos/packages/core/src/__tests__/hook-governance.test.ts +228 -0
  204. package/inkos/packages/core/src/__tests__/hook-health.test.ts +166 -0
  205. package/inkos/packages/core/src/__tests__/hook-ledger-validator.test.ts +236 -0
  206. package/inkos/packages/core/src/__tests__/hook-promotion.test.ts +192 -0
  207. package/inkos/packages/core/src/__tests__/hook-stale-detection.test.ts +136 -0
  208. package/inkos/packages/core/src/__tests__/index-notify-lazy.test.ts +20 -0
  209. package/inkos/packages/core/src/__tests__/interaction-chat-tokens.test.ts +170 -0
  210. package/inkos/packages/core/src/__tests__/interaction-models.test.ts +155 -0
  211. package/inkos/packages/core/src/__tests__/interaction-nl-router.test.ts +223 -0
  212. package/inkos/packages/core/src/__tests__/interaction-runtime.test.ts +633 -0
  213. package/inkos/packages/core/src/__tests__/interaction-tools.test.ts +343 -0
  214. package/inkos/packages/core/src/__tests__/length-metrics.test.ts +82 -0
  215. package/inkos/packages/core/src/__tests__/length-normalizer.test.ts +331 -0
  216. package/inkos/packages/core/src/__tests__/list-models.test.ts +109 -0
  217. package/inkos/packages/core/src/__tests__/llm-env.test.ts +31 -0
  218. package/inkos/packages/core/src/__tests__/logger.test.ts +175 -0
  219. package/inkos/packages/core/src/__tests__/long-span-fatigue.test.ts +160 -0
  220. package/inkos/packages/core/src/__tests__/memory-retrieval.test.ts +1303 -0
  221. package/inkos/packages/core/src/__tests__/models.test.ts +918 -0
  222. package/inkos/packages/core/src/__tests__/outline-paths.test.ts +97 -0
  223. package/inkos/packages/core/src/__tests__/path-safety.test.ts +22 -0
  224. package/inkos/packages/core/src/__tests__/persisted-governed-plan.test.ts +134 -0
  225. package/inkos/packages/core/src/__tests__/phase5-cleanup.test.ts +393 -0
  226. package/inkos/packages/core/src/__tests__/phase5-hotfix.test.ts +288 -0
  227. package/inkos/packages/core/src/__tests__/phase7-hotfix.test.ts +614 -0
  228. package/inkos/packages/core/src/__tests__/pipeline-agent.test.ts +354 -0
  229. package/inkos/packages/core/src/__tests__/pipeline-runner-memory-sync.test.ts +317 -0
  230. package/inkos/packages/core/src/__tests__/pipeline-runner.test.ts +5200 -0
  231. package/inkos/packages/core/src/__tests__/planner-context.test.ts +137 -0
  232. package/inkos/packages/core/src/__tests__/planner-prompts-ratio.test.ts +11 -0
  233. package/inkos/packages/core/src/__tests__/planner-prompts.test.ts +171 -0
  234. package/inkos/packages/core/src/__tests__/planner.test.ts +362 -0
  235. package/inkos/packages/core/src/__tests__/planning-materials.test.ts +90 -0
  236. package/inkos/packages/core/src/__tests__/polisher.test.ts +189 -0
  237. package/inkos/packages/core/src/__tests__/post-write-validator.test.ts +291 -0
  238. package/inkos/packages/core/src/__tests__/probe.test.ts +77 -0
  239. package/inkos/packages/core/src/__tests__/project-interaction.test.ts +241 -0
  240. package/inkos/packages/core/src/__tests__/provider.test.ts +953 -0
  241. package/inkos/packages/core/src/__tests__/providers-group.test.ts +34 -0
  242. package/inkos/packages/core/src/__tests__/providers-lookup.test.ts +81 -0
  243. package/inkos/packages/core/src/__tests__/providers-schema.test.ts +158 -0
  244. package/inkos/packages/core/src/__tests__/proxy-fetch.test.ts +75 -0
  245. package/inkos/packages/core/src/__tests__/revise-foundation.test.ts +514 -0
  246. package/inkos/packages/core/src/__tests__/reviser.test.ts +859 -0
  247. package/inkos/packages/core/src/__tests__/runtime-state-store.test.ts +388 -0
  248. package/inkos/packages/core/src/__tests__/scheduler.test.ts +123 -0
  249. package/inkos/packages/core/src/__tests__/secrets-migration.test.ts +71 -0
  250. package/inkos/packages/core/src/__tests__/secrets.test.ts +95 -0
  251. package/inkos/packages/core/src/__tests__/sensitive-words.test.ts +88 -0
  252. package/inkos/packages/core/src/__tests__/service-presets-regression.test.ts +73 -0
  253. package/inkos/packages/core/src/__tests__/service-resolver-regression.test.ts +75 -0
  254. package/inkos/packages/core/src/__tests__/service-resolver.test.ts +228 -0
  255. package/inkos/packages/core/src/__tests__/session-transcript-restore.test.ts +1311 -0
  256. package/inkos/packages/core/src/__tests__/session-transcript.test.ts +195 -0
  257. package/inkos/packages/core/src/__tests__/settler-delta-parser.test.ts +133 -0
  258. package/inkos/packages/core/src/__tests__/short-fiction-public.test.ts +241 -0
  259. package/inkos/packages/core/src/__tests__/spot-fix-patches.test.ts +104 -0
  260. package/inkos/packages/core/src/__tests__/state-manager.test.ts +1298 -0
  261. package/inkos/packages/core/src/__tests__/state-projections.test.ts +130 -0
  262. package/inkos/packages/core/src/__tests__/state-reducer.test.ts +372 -0
  263. package/inkos/packages/core/src/__tests__/state-validator-agent.test.ts +165 -0
  264. package/inkos/packages/core/src/__tests__/state-validator.test.ts +122 -0
  265. package/inkos/packages/core/src/__tests__/style-analyzer.test.ts +61 -0
  266. package/inkos/packages/core/src/__tests__/temperature-constraints.test.ts +57 -0
  267. package/inkos/packages/core/src/__tests__/v13-hotfix-round4.test.ts +343 -0
  268. package/inkos/packages/core/src/__tests__/verify-service.test.ts +77 -0
  269. package/inkos/packages/core/src/__tests__/webhook.test.ts +91 -0
  270. package/inkos/packages/core/src/__tests__/writer-parser.test.ts +348 -0
  271. package/inkos/packages/core/src/__tests__/writer-prompts.test.ts +269 -0
  272. package/inkos/packages/core/src/__tests__/writer.test.ts +1360 -0
  273. package/inkos/packages/core/src/agent/agent-session.ts +737 -0
  274. package/inkos/packages/core/src/agent/agent-system-prompt.ts +199 -0
  275. package/inkos/packages/core/src/agent/agent-tools.ts +835 -0
  276. package/inkos/packages/core/src/agent/context-transform.ts +85 -0
  277. package/inkos/packages/core/src/agent/index.ts +14 -0
  278. package/inkos/packages/core/src/agents/ai-tells.ts +161 -0
  279. package/inkos/packages/core/src/agents/architect.ts +1291 -0
  280. package/inkos/packages/core/src/agents/base.ts +100 -0
  281. package/inkos/packages/core/src/agents/chapter-analyzer.ts +634 -0
  282. package/inkos/packages/core/src/agents/composer.ts +469 -0
  283. package/inkos/packages/core/src/agents/consolidator.ts +218 -0
  284. package/inkos/packages/core/src/agents/continuity.ts +824 -0
  285. package/inkos/packages/core/src/agents/detection-insights.ts +72 -0
  286. package/inkos/packages/core/src/agents/detector.ts +224 -0
  287. package/inkos/packages/core/src/agents/en-prompt-sections.ts +129 -0
  288. package/inkos/packages/core/src/agents/fanfic-canon-importer.ts +146 -0
  289. package/inkos/packages/core/src/agents/fanfic-dimensions.ts +87 -0
  290. package/inkos/packages/core/src/agents/fanfic-prompt-sections.ts +109 -0
  291. package/inkos/packages/core/src/agents/foundation-reviewer.ts +204 -0
  292. package/inkos/packages/core/src/agents/length-normalizer.ts +218 -0
  293. package/inkos/packages/core/src/agents/observer-prompts.ts +127 -0
  294. package/inkos/packages/core/src/agents/planner-context.ts +297 -0
  295. package/inkos/packages/core/src/agents/planner-prompts.ts +404 -0
  296. package/inkos/packages/core/src/agents/planner.ts +783 -0
  297. package/inkos/packages/core/src/agents/polisher.ts +153 -0
  298. package/inkos/packages/core/src/agents/post-write-validator.ts +873 -0
  299. package/inkos/packages/core/src/agents/radar-source.ts +123 -0
  300. package/inkos/packages/core/src/agents/radar.ts +120 -0
  301. package/inkos/packages/core/src/agents/reviser.ts +701 -0
  302. package/inkos/packages/core/src/agents/rules-reader.ts +155 -0
  303. package/inkos/packages/core/src/agents/sensitive-words.ts +142 -0
  304. package/inkos/packages/core/src/agents/settler-delta-parser.ts +53 -0
  305. package/inkos/packages/core/src/agents/settler-parser.ts +38 -0
  306. package/inkos/packages/core/src/agents/settler-prompts.ts +230 -0
  307. package/inkos/packages/core/src/agents/short-fiction.ts +429 -0
  308. package/inkos/packages/core/src/agents/state-validator.ts +322 -0
  309. package/inkos/packages/core/src/agents/style-analyzer.ts +93 -0
  310. package/inkos/packages/core/src/agents/writer-parser.ts +178 -0
  311. package/inkos/packages/core/src/agents/writer-prompts.ts +899 -0
  312. package/inkos/packages/core/src/agents/writer.ts +1450 -0
  313. package/inkos/packages/core/src/index.ts +392 -0
  314. package/inkos/packages/core/src/interaction/book-session-store.ts +226 -0
  315. package/inkos/packages/core/src/interaction/draft-directive-parser.ts +266 -0
  316. package/inkos/packages/core/src/interaction/edit-controller.ts +270 -0
  317. package/inkos/packages/core/src/interaction/events.ts +41 -0
  318. package/inkos/packages/core/src/interaction/export-artifact.ts +151 -0
  319. package/inkos/packages/core/src/interaction/intents.ts +63 -0
  320. package/inkos/packages/core/src/interaction/modes.ts +13 -0
  321. package/inkos/packages/core/src/interaction/nl-router.ts +258 -0
  322. package/inkos/packages/core/src/interaction/project-control.ts +150 -0
  323. package/inkos/packages/core/src/interaction/project-session-store.ts +81 -0
  324. package/inkos/packages/core/src/interaction/project-tools.ts +704 -0
  325. package/inkos/packages/core/src/interaction/request-router.ts +5 -0
  326. package/inkos/packages/core/src/interaction/runtime.ts +1167 -0
  327. package/inkos/packages/core/src/interaction/session-transcript-legacy.ts +113 -0
  328. package/inkos/packages/core/src/interaction/session-transcript-restore.ts +607 -0
  329. package/inkos/packages/core/src/interaction/session-transcript-schema.ts +76 -0
  330. package/inkos/packages/core/src/interaction/session-transcript.ts +189 -0
  331. package/inkos/packages/core/src/interaction/session.ts +226 -0
  332. package/inkos/packages/core/src/interaction/truth-authority.ts +45 -0
  333. package/inkos/packages/core/src/llm/config-migration.ts +58 -0
  334. package/inkos/packages/core/src/llm/cover-providers.ts +45 -0
  335. package/inkos/packages/core/src/llm/provider.ts +1331 -0
  336. package/inkos/packages/core/src/llm/providers/endpoints/ai360.ts +42 -0
  337. package/inkos/packages/core/src/llm/providers/endpoints/anthropic.ts +82 -0
  338. package/inkos/packages/core/src/llm/providers/endpoints/astronCodingPlan.ts +30 -0
  339. package/inkos/packages/core/src/llm/providers/endpoints/baichuan.ts +28 -0
  340. package/inkos/packages/core/src/llm/providers/endpoints/bailian.ts +65 -0
  341. package/inkos/packages/core/src/llm/providers/endpoints/bailianCodingPlan.ts +30 -0
  342. package/inkos/packages/core/src/llm/providers/endpoints/custom.ts +22 -0
  343. package/inkos/packages/core/src/llm/providers/endpoints/deepseek.ts +35 -0
  344. package/inkos/packages/core/src/llm/providers/endpoints/giteeai.ts +41 -0
  345. package/inkos/packages/core/src/llm/providers/endpoints/githubCopilot.ts +43 -0
  346. package/inkos/packages/core/src/llm/providers/endpoints/glmCodingPlan.ts +28 -0
  347. package/inkos/packages/core/src/llm/providers/endpoints/google.ts +51 -0
  348. package/inkos/packages/core/src/llm/providers/endpoints/hunyuan.ts +42 -0
  349. package/inkos/packages/core/src/llm/providers/endpoints/infiniai.ts +72 -0
  350. package/inkos/packages/core/src/llm/providers/endpoints/internlm.ts +28 -0
  351. package/inkos/packages/core/src/llm/providers/endpoints/kimiCode.ts +23 -0
  352. package/inkos/packages/core/src/llm/providers/endpoints/kimiCodingPlan.ts +24 -0
  353. package/inkos/packages/core/src/llm/providers/endpoints/kkaiapi.ts +56 -0
  354. package/inkos/packages/core/src/llm/providers/endpoints/longcat.ts +25 -0
  355. package/inkos/packages/core/src/llm/providers/endpoints/minimax.ts +39 -0
  356. package/inkos/packages/core/src/llm/providers/endpoints/minimaxCodingPlan.ts +28 -0
  357. package/inkos/packages/core/src/llm/providers/endpoints/mistral.ts +40 -0
  358. package/inkos/packages/core/src/llm/providers/endpoints/modelscope.ts +30 -0
  359. package/inkos/packages/core/src/llm/providers/endpoints/moonshot.ts +39 -0
  360. package/inkos/packages/core/src/llm/providers/endpoints/newapi.ts +21 -0
  361. package/inkos/packages/core/src/llm/providers/endpoints/ollama.ts +73 -0
  362. package/inkos/packages/core/src/llm/providers/endpoints/openai.ts +77 -0
  363. package/inkos/packages/core/src/llm/providers/endpoints/opencodeCodingPlan.ts +30 -0
  364. package/inkos/packages/core/src/llm/providers/endpoints/openrouter.ts +87 -0
  365. package/inkos/packages/core/src/llm/providers/endpoints/ppio.ts +86 -0
  366. package/inkos/packages/core/src/llm/providers/endpoints/qiniu.ts +32 -0
  367. package/inkos/packages/core/src/llm/providers/endpoints/sensenova.ts +45 -0
  368. package/inkos/packages/core/src/llm/providers/endpoints/siliconcloud.ts +126 -0
  369. package/inkos/packages/core/src/llm/providers/endpoints/spark.ts +33 -0
  370. package/inkos/packages/core/src/llm/providers/endpoints/stepfun.ts +35 -0
  371. package/inkos/packages/core/src/llm/providers/endpoints/tencentcloud.ts +25 -0
  372. package/inkos/packages/core/src/llm/providers/endpoints/volcengine.ts +52 -0
  373. package/inkos/packages/core/src/llm/providers/endpoints/volcengineCodingPlan.ts +42 -0
  374. package/inkos/packages/core/src/llm/providers/endpoints/wenxin.ts +106 -0
  375. package/inkos/packages/core/src/llm/providers/endpoints/xai.ts +34 -0
  376. package/inkos/packages/core/src/llm/providers/endpoints/xiaomimimo.ts +26 -0
  377. package/inkos/packages/core/src/llm/providers/endpoints/zeroone.ts +34 -0
  378. package/inkos/packages/core/src/llm/providers/endpoints/zhipu.ts +61 -0
  379. package/inkos/packages/core/src/llm/providers/index.ts +71 -0
  380. package/inkos/packages/core/src/llm/providers/lookup.ts +70 -0
  381. package/inkos/packages/core/src/llm/providers/probe.ts +35 -0
  382. package/inkos/packages/core/src/llm/providers/types.ts +89 -0
  383. package/inkos/packages/core/src/llm/providers/verify.ts +104 -0
  384. package/inkos/packages/core/src/llm/secrets.ts +77 -0
  385. package/inkos/packages/core/src/llm/service-presets.ts +215 -0
  386. package/inkos/packages/core/src/llm/service-resolver.ts +91 -0
  387. package/inkos/packages/core/src/models/book-rules.ts +126 -0
  388. package/inkos/packages/core/src/models/book.ts +70 -0
  389. package/inkos/packages/core/src/models/chapter.ts +42 -0
  390. package/inkos/packages/core/src/models/detection.ts +25 -0
  391. package/inkos/packages/core/src/models/genre-profile.ts +36 -0
  392. package/inkos/packages/core/src/models/input-governance.ts +99 -0
  393. package/inkos/packages/core/src/models/length-governance.ts +46 -0
  394. package/inkos/packages/core/src/models/project.ts +161 -0
  395. package/inkos/packages/core/src/models/runtime-state.ts +144 -0
  396. package/inkos/packages/core/src/models/state.ts +52 -0
  397. package/inkos/packages/core/src/models/style-profile.ts +15 -0
  398. package/inkos/packages/core/src/notify/dispatcher.ts +96 -0
  399. package/inkos/packages/core/src/notify/feishu.ts +34 -0
  400. package/inkos/packages/core/src/notify/telegram.ts +25 -0
  401. package/inkos/packages/core/src/notify/webhook.ts +58 -0
  402. package/inkos/packages/core/src/notify/wechat-work.ts +22 -0
  403. package/inkos/packages/core/src/pipeline/agent.ts +691 -0
  404. package/inkos/packages/core/src/pipeline/chapter-persistence.ts +79 -0
  405. package/inkos/packages/core/src/pipeline/chapter-review-cycle.ts +324 -0
  406. package/inkos/packages/core/src/pipeline/chapter-state-recovery.ts +236 -0
  407. package/inkos/packages/core/src/pipeline/chapter-truth-validation.ts +145 -0
  408. package/inkos/packages/core/src/pipeline/detection-runner.ts +164 -0
  409. package/inkos/packages/core/src/pipeline/persisted-governed-plan.ts +216 -0
  410. package/inkos/packages/core/src/pipeline/runner.ts +3438 -0
  411. package/inkos/packages/core/src/pipeline/scheduler.ts +411 -0
  412. package/inkos/packages/core/src/pipeline/short-fiction-runner.ts +801 -0
  413. package/inkos/packages/core/src/prompts/index.ts +1 -0
  414. package/inkos/packages/core/src/prompts/short-fiction.ts +273 -0
  415. package/inkos/packages/core/src/state/manager.ts +560 -0
  416. package/inkos/packages/core/src/state/memory-db.ts +359 -0
  417. package/inkos/packages/core/src/state/runtime-state-store.ts +164 -0
  418. package/inkos/packages/core/src/state/state-bootstrap.ts +657 -0
  419. package/inkos/packages/core/src/state/state-projections.ts +255 -0
  420. package/inkos/packages/core/src/state/state-reducer.ts +260 -0
  421. package/inkos/packages/core/src/state/state-validator.ts +117 -0
  422. package/inkos/packages/core/src/utils/analytics.ts +92 -0
  423. package/inkos/packages/core/src/utils/book-id.ts +31 -0
  424. package/inkos/packages/core/src/utils/cadence-policy.ts +46 -0
  425. package/inkos/packages/core/src/utils/chapter-cadence.ts +211 -0
  426. package/inkos/packages/core/src/utils/chapter-memo-parser.ts +157 -0
  427. package/inkos/packages/core/src/utils/chapter-splitter.ts +80 -0
  428. package/inkos/packages/core/src/utils/config-loader.ts +29 -0
  429. package/inkos/packages/core/src/utils/context-assembly.ts +98 -0
  430. package/inkos/packages/core/src/utils/context-filter.ts +190 -0
  431. package/inkos/packages/core/src/utils/effective-llm-config.ts +529 -0
  432. package/inkos/packages/core/src/utils/governed-context.ts +101 -0
  433. package/inkos/packages/core/src/utils/governed-working-set.ts +395 -0
  434. package/inkos/packages/core/src/utils/hook-arbiter.ts +332 -0
  435. package/inkos/packages/core/src/utils/hook-governance.ts +199 -0
  436. package/inkos/packages/core/src/utils/hook-health.ts +189 -0
  437. package/inkos/packages/core/src/utils/hook-ledger-validator.ts +277 -0
  438. package/inkos/packages/core/src/utils/hook-lifecycle.ts +224 -0
  439. package/inkos/packages/core/src/utils/hook-policy.ts +115 -0
  440. package/inkos/packages/core/src/utils/hook-promotion.ts +313 -0
  441. package/inkos/packages/core/src/utils/hook-stale-detection.ts +168 -0
  442. package/inkos/packages/core/src/utils/length-metrics.ts +123 -0
  443. package/inkos/packages/core/src/utils/llm-endpoint-auth.ts +40 -0
  444. package/inkos/packages/core/src/utils/llm-env.ts +74 -0
  445. package/inkos/packages/core/src/utils/logger.ts +123 -0
  446. package/inkos/packages/core/src/utils/long-span-fatigue.ts +545 -0
  447. package/inkos/packages/core/src/utils/memory-retrieval.ts +527 -0
  448. package/inkos/packages/core/src/utils/narrative-control.ts +177 -0
  449. package/inkos/packages/core/src/utils/outline-paths.ts +275 -0
  450. package/inkos/packages/core/src/utils/path-safety.ts +11 -0
  451. package/inkos/packages/core/src/utils/planning-materials.ts +185 -0
  452. package/inkos/packages/core/src/utils/pov-filter.ts +149 -0
  453. package/inkos/packages/core/src/utils/proxy-fetch.ts +44 -0
  454. package/inkos/packages/core/src/utils/runtime-writer.ts +41 -0
  455. package/inkos/packages/core/src/utils/spot-fix-patches.ts +189 -0
  456. package/inkos/packages/core/src/utils/story-markdown.ts +346 -0
  457. package/inkos/packages/core/src/utils/web-search.ts +82 -0
  458. package/inkos/packages/core/src/utils/writing-methodology.ts +164 -0
  459. package/inkos/packages/core/tsconfig.json +8 -0
  460. package/inkos/packages/core/vitest.config.ts +7 -0
  461. package/inkos/packages/studio/components.json +25 -0
  462. package/inkos/packages/studio/index.html +13 -0
  463. package/inkos/packages/studio/package.json +72 -0
  464. package/inkos/packages/studio/postcss.config.js +3 -0
  465. package/inkos/packages/studio/src/App.test.ts +25 -0
  466. package/inkos/packages/studio/src/App.tsx +280 -0
  467. package/inkos/packages/studio/src/api/__tests__/normalize-base-url.test.ts +40 -0
  468. package/inkos/packages/studio/src/api/book-create.test.ts +104 -0
  469. package/inkos/packages/studio/src/api/book-create.ts +94 -0
  470. package/inkos/packages/studio/src/api/errors.ts +17 -0
  471. package/inkos/packages/studio/src/api/index.ts +30 -0
  472. package/inkos/packages/studio/src/api/lib/run-store.ts +177 -0
  473. package/inkos/packages/studio/src/api/lib/sse.ts +50 -0
  474. package/inkos/packages/studio/src/api/phase5-hotfix.test.ts +335 -0
  475. package/inkos/packages/studio/src/api/safety.ts +6 -0
  476. package/inkos/packages/studio/src/api/server.test.ts +3162 -0
  477. package/inkos/packages/studio/src/api/server.ts +3666 -0
  478. package/inkos/packages/studio/src/api/v13-hotfix-round4.test.ts +226 -0
  479. package/inkos/packages/studio/src/app-state.test.ts +8 -0
  480. package/inkos/packages/studio/src/app-state.ts +1 -0
  481. package/inkos/packages/studio/src/components/ConfirmDialog.tsx +95 -0
  482. package/inkos/packages/studio/src/components/ServiceConfigSourceCard.tsx +139 -0
  483. package/inkos/packages/studio/src/components/ServiceQuickLinks.tsx +65 -0
  484. package/inkos/packages/studio/src/components/Sidebar.tsx +652 -0
  485. package/inkos/packages/studio/src/components/ai-elements/code-block.tsx +562 -0
  486. package/inkos/packages/studio/src/components/ai-elements/confirmation.tsx +174 -0
  487. package/inkos/packages/studio/src/components/ai-elements/message.tsx +360 -0
  488. package/inkos/packages/studio/src/components/ai-elements/prompt-input.tsx +1457 -0
  489. package/inkos/packages/studio/src/components/ai-elements/reasoning.tsx +226 -0
  490. package/inkos/packages/studio/src/components/ai-elements/shimmer.tsx +77 -0
  491. package/inkos/packages/studio/src/components/ai-elements/tool.tsx +173 -0
  492. package/inkos/packages/studio/src/components/chat/BookSidebar.tsx +291 -0
  493. package/inkos/packages/studio/src/components/chat/ChatMessage.tsx +39 -0
  494. package/inkos/packages/studio/src/components/chat/QuickActions.tsx +73 -0
  495. package/inkos/packages/studio/src/components/chat/ToolExecutionSteps.tsx +320 -0
  496. package/inkos/packages/studio/src/components/chat/__tests__/ToolExecutionSteps.test.ts +114 -0
  497. package/inkos/packages/studio/src/components/chat-utils.ts +56 -0
  498. package/inkos/packages/studio/src/components/chatbar-state.test.ts +69 -0
  499. package/inkos/packages/studio/src/components/sidebar/ChaptersSection.tsx +66 -0
  500. package/inkos/packages/studio/src/components/sidebar/CharacterSection.tsx +129 -0
  501. package/inkos/packages/studio/src/components/sidebar/FoundationSection.tsx +61 -0
  502. package/inkos/packages/studio/src/components/sidebar/ProgressSection.tsx +124 -0
  503. package/inkos/packages/studio/src/components/sidebar/SidebarCard.tsx +30 -0
  504. package/inkos/packages/studio/src/components/sidebar/SummarySection.tsx +89 -0
  505. package/inkos/packages/studio/src/components/ui/alert.tsx +76 -0
  506. package/inkos/packages/studio/src/components/ui/badge.tsx +52 -0
  507. package/inkos/packages/studio/src/components/ui/button-group.tsx +87 -0
  508. package/inkos/packages/studio/src/components/ui/button.tsx +58 -0
  509. package/inkos/packages/studio/src/components/ui/collapsible.tsx +19 -0
  510. package/inkos/packages/studio/src/components/ui/command.tsx +194 -0
  511. package/inkos/packages/studio/src/components/ui/dialog.tsx +158 -0
  512. package/inkos/packages/studio/src/components/ui/dropdown-menu.tsx +266 -0
  513. package/inkos/packages/studio/src/components/ui/hover-card.tsx +51 -0
  514. package/inkos/packages/studio/src/components/ui/input-group.tsx +158 -0
  515. package/inkos/packages/studio/src/components/ui/input.tsx +20 -0
  516. package/inkos/packages/studio/src/components/ui/select.tsx +199 -0
  517. package/inkos/packages/studio/src/components/ui/separator.tsx +23 -0
  518. package/inkos/packages/studio/src/components/ui/spinner.tsx +10 -0
  519. package/inkos/packages/studio/src/components/ui/textarea.tsx +18 -0
  520. package/inkos/packages/studio/src/components/ui/tooltip.tsx +66 -0
  521. package/inkos/packages/studio/src/constants/service-groups.ts +29 -0
  522. package/inkos/packages/studio/src/hooks/use-api.test.ts +93 -0
  523. package/inkos/packages/studio/src/hooks/use-api.ts +189 -0
  524. package/inkos/packages/studio/src/hooks/use-book-activity.test.ts +129 -0
  525. package/inkos/packages/studio/src/hooks/use-book-activity.ts +180 -0
  526. package/inkos/packages/studio/src/hooks/use-colors.ts +27 -0
  527. package/inkos/packages/studio/src/hooks/use-hash-route.test.ts +101 -0
  528. package/inkos/packages/studio/src/hooks/use-hash-route.ts +89 -0
  529. package/inkos/packages/studio/src/hooks/use-i18n.ts +289 -0
  530. package/inkos/packages/studio/src/hooks/use-session-events.ts +64 -0
  531. package/inkos/packages/studio/src/hooks/use-sse.test.ts +52 -0
  532. package/inkos/packages/studio/src/hooks/use-sse.ts +92 -0
  533. package/inkos/packages/studio/src/hooks/use-theme.test.ts +31 -0
  534. package/inkos/packages/studio/src/hooks/use-theme.ts +75 -0
  535. package/inkos/packages/studio/src/index.css +323 -0
  536. package/inkos/packages/studio/src/lib/error-copy.test.ts +34 -0
  537. package/inkos/packages/studio/src/lib/error-copy.ts +37 -0
  538. package/inkos/packages/studio/src/lib/utils.ts +6 -0
  539. package/inkos/packages/studio/src/main.tsx +10 -0
  540. package/inkos/packages/studio/src/pages/Analytics.tsx +80 -0
  541. package/inkos/packages/studio/src/pages/BookCreate.tsx +895 -0
  542. package/inkos/packages/studio/src/pages/BookDetail.tsx +652 -0
  543. package/inkos/packages/studio/src/pages/ChapterReader.tsx +266 -0
  544. package/inkos/packages/studio/src/pages/ChatPage.tsx +521 -0
  545. package/inkos/packages/studio/src/pages/DaemonControl.tsx +116 -0
  546. package/inkos/packages/studio/src/pages/Dashboard.tsx +379 -0
  547. package/inkos/packages/studio/src/pages/DoctorView.tsx +82 -0
  548. package/inkos/packages/studio/src/pages/GenreManager.tsx +464 -0
  549. package/inkos/packages/studio/src/pages/ImportManager.tsx +216 -0
  550. package/inkos/packages/studio/src/pages/LanguageSelector.tsx +74 -0
  551. package/inkos/packages/studio/src/pages/LogViewer.tsx +82 -0
  552. package/inkos/packages/studio/src/pages/RadarView.tsx +157 -0
  553. package/inkos/packages/studio/src/pages/ServiceDetailPage.tsx +393 -0
  554. package/inkos/packages/studio/src/pages/ServiceListPage.tsx +463 -0
  555. package/inkos/packages/studio/src/pages/StyleManager.tsx +225 -0
  556. package/inkos/packages/studio/src/pages/TruthFiles.tsx +194 -0
  557. package/inkos/packages/studio/src/pages/chat-page-state.test.ts +206 -0
  558. package/inkos/packages/studio/src/pages/chat-page-state.ts +112 -0
  559. package/inkos/packages/studio/src/pages/page-state.test.ts +258 -0
  560. package/inkos/packages/studio/src/pages/service-detail-state.test.ts +294 -0
  561. package/inkos/packages/studio/src/pages/service-detail-state.ts +234 -0
  562. package/inkos/packages/studio/src/pages/style-manager-state.test.ts +22 -0
  563. package/inkos/packages/studio/src/pages/truth-files-state.test.ts +61 -0
  564. package/inkos/packages/studio/src/shared/contracts.ts +143 -0
  565. package/inkos/packages/studio/src/store/chat/__tests__/message-parts.test.ts +172 -0
  566. package/inkos/packages/studio/src/store/chat/index.ts +3 -0
  567. package/inkos/packages/studio/src/store/chat/initialState.ts +8 -0
  568. package/inkos/packages/studio/src/store/chat/message-policy.test.ts +16 -0
  569. package/inkos/packages/studio/src/store/chat/message-policy.ts +5 -0
  570. package/inkos/packages/studio/src/store/chat/parts-builder.ts +187 -0
  571. package/inkos/packages/studio/src/store/chat/selectors.ts +13 -0
  572. package/inkos/packages/studio/src/store/chat/slices/create/action.ts +10 -0
  573. package/inkos/packages/studio/src/store/chat/slices/create/initialState.ts +9 -0
  574. package/inkos/packages/studio/src/store/chat/slices/message/action.ts +417 -0
  575. package/inkos/packages/studio/src/store/chat/slices/message/initialState.ts +10 -0
  576. package/inkos/packages/studio/src/store/chat/slices/message/runtime.test.ts +21 -0
  577. package/inkos/packages/studio/src/store/chat/slices/message/runtime.ts +233 -0
  578. package/inkos/packages/studio/src/store/chat/slices/message/stream-events.ts +272 -0
  579. package/inkos/packages/studio/src/store/chat/store.ts +11 -0
  580. package/inkos/packages/studio/src/store/chat/types.ts +169 -0
  581. package/inkos/packages/studio/src/store/service/index.ts +2 -0
  582. package/inkos/packages/studio/src/store/service/store.ts +123 -0
  583. package/inkos/packages/studio/src/store/service/types.ts +50 -0
  584. package/inkos/packages/studio/tsconfig.json +24 -0
  585. package/inkos/packages/studio/tsconfig.server.json +11 -0
  586. package/inkos/packages/studio/vite.config.ts +34 -0
  587. package/inkos/packages/studio/vitest.config.ts +14 -0
  588. package/inkos/pnpm-lock.yaml +9569 -0
  589. package/inkos/pnpm-workspace.yaml +2 -0
  590. package/inkos/scripts/prepare-package-for-publish.mjs +135 -0
  591. package/inkos/scripts/restore-package-json.mjs +31 -0
  592. package/inkos/scripts/set-package-versions.mjs +74 -0
  593. package/inkos/scripts/verify-no-workspace-protocol.mjs +140 -0
  594. package/inkos/skills/SKILL.md +654 -0
  595. package/inkos/tsconfig.json +19 -0
  596. package/package.json +4 -3
  597. /package/.next/static/{F2hMZMf1IyCVAWpkbtRz7 → -3vIrBZXdQ0rp7Wa3Kz40}/_buildManifest.js +0 -0
  598. /package/.next/static/{F2hMZMf1IyCVAWpkbtRz7 → -3vIrBZXdQ0rp7Wa3Kz40}/_ssgManifest.js +0 -0
@@ -0,0 +1,109 @@
1
+ import type { FanficMode } from "../models/book.js";
2
+
3
+ const MODE_PREAMBLES: Record<FanficMode, string> = {
4
+ canon: `你正在写**原作向同人**。严格遵守正典:
5
+ - 角色的语癖、说话风格、行为模式必须与原作一致
6
+ - 世界规则不可违反
7
+ - 关键事件时间线不可矛盾
8
+ - 可以填充原作空白、探索未详述的角度`,
9
+
10
+ au: `你正在写**AU(平行世界)同人**:
11
+ - 世界规则可以改变(已在 allowedDeviations 中声明的偏离)
12
+ - 角色的核心性格和说话方式应保持辨识度——读者要能认出是谁
13
+ - AU 设定偏离必须内部一致(改了一条规则,相关的都要跟着变)`,
14
+
15
+ ooc: `你正在写**OOC 同人**:
16
+ - 角色在极端情境下可以偏离性格底色
17
+ - 但偏离必须有情境驱动,不能无缘无故变性格
18
+ - 保留角色的语癖和说话特征——即使性格变了,说话方式也应有辨识度`,
19
+
20
+ cp: `你正在写**CP 同人**,以角色互动和关系发展为核心:
21
+ - 配对双方每章必须有有效互动
22
+ - 互动风格要有化学反应——不是两个人在同一个场景各干各的
23
+ - 关系发展应有节奏感:推进、试探、阻碍、突破`,
24
+ };
25
+
26
+ export function buildFanficCanonSection(
27
+ fanficCanon: string,
28
+ mode: FanficMode,
29
+ ): string {
30
+ return `
31
+ ## 同人正典参照
32
+
33
+ ${MODE_PREAMBLES[mode]}
34
+
35
+ 以下是原作正典信息,写作时必须参照:
36
+
37
+ ${fanficCanon}`;
38
+ }
39
+
40
+ export function buildCharacterVoiceProfiles(fanficCanon: string): string {
41
+ // Extract character table from fanfic_canon.md
42
+ const tableMatch = fanficCanon.match(
43
+ /## 角色档案[\s\S]*?\n(\|[^\n]+\|\n\|[-|\s]+\|\n(?:\|[^\n]+\|\n)*)/,
44
+ );
45
+ if (!tableMatch) return "";
46
+
47
+ const rows = tableMatch[1]!
48
+ .split("\n")
49
+ .filter((line) => line.startsWith("|") && !line.startsWith("|--") && !line.startsWith("| 角色"))
50
+ .map((line) =>
51
+ line
52
+ .split("|")
53
+ .map((cell) => cell.trim())
54
+ .filter(Boolean),
55
+ )
56
+ .filter((cells) => cells.length >= 5);
57
+
58
+ if (rows.length === 0) return "";
59
+
60
+ const profiles = rows.map((cells) => {
61
+ const [name, , , catchphrases, speakingStyle, behavior] = cells;
62
+ const parts: string[] = [`### ${name}`];
63
+ if (catchphrases && catchphrases !== "(素材未提及)") {
64
+ parts.push(`- 口头禅/语癖:${catchphrases}`);
65
+ }
66
+ if (speakingStyle && speakingStyle !== "(素材未提及)") {
67
+ parts.push(`- 说话风格:${speakingStyle}`);
68
+ }
69
+ if (behavior && behavior !== "(素材未提及)") {
70
+ parts.push(`- 典型行为:${behavior}`);
71
+ }
72
+ return parts.join("\n");
73
+ });
74
+
75
+ return `
76
+ ## 角色语音参照(同人写作专用)
77
+
78
+ 以下角色的对话和行为必须参照原作特征。写对话时,先想"这个角色在原作里会怎么说"。
79
+
80
+ ${profiles.join("\n\n")}`;
81
+ }
82
+
83
+ const MODE_CHECKS: Record<FanficMode, string> = {
84
+ canon: `- 正典合规检查:本章是否违反原作设定?角色对话是否符合原作语癖?
85
+ - 信息边界检查:角色是否引用了不该知道的信息?`,
86
+
87
+ au: `- AU 偏离清单:本章改变了哪些世界规则?改变是否内部一致?
88
+ - 角色辨识度检查:读者能否从对话中认出角色?`,
89
+
90
+ ooc: `- OOC 偏离记录:角色在哪些方面偏离了性格底色?偏离驱动力是什么?
91
+ - 语癖保留检查:即使 OOC,说话方式是否还有原作特征?`,
92
+
93
+ cp: `- CP 互动检查:配对双方本章是否有有效互动?关系发展是否推进?
94
+ - 互动质量检查:互动是否有化学反应(不是各干各的)?`,
95
+ };
96
+
97
+ export function buildFanficModeInstructions(
98
+ mode: FanficMode,
99
+ allowedDeviations: ReadonlyArray<string>,
100
+ ): string {
101
+ const deviationsBlock = allowedDeviations.length > 0
102
+ ? `\n允许的偏离(不视为违规):\n${allowedDeviations.map((d) => `- ${d}`).join("\n")}\n`
103
+ : "";
104
+
105
+ return `
106
+ ## 同人写作自检(在 PRE_WRITE_CHECK 中额外检查)
107
+
108
+ ${MODE_CHECKS[mode]}${deviationsBlock}`;
109
+ }
@@ -0,0 +1,204 @@
1
+ import { BaseAgent } from "./base.js";
2
+ import type { ArchitectOutput } from "./architect.js";
3
+
4
+ export interface FoundationReviewResult {
5
+ readonly passed: boolean;
6
+ readonly totalScore: number;
7
+ readonly dimensions: ReadonlyArray<{
8
+ readonly name: string;
9
+ readonly score: number;
10
+ readonly feedback: string;
11
+ }>;
12
+ readonly overallFeedback: string;
13
+ }
14
+
15
+ const PASS_THRESHOLD = 80;
16
+ const DIMENSION_FLOOR = 60;
17
+
18
+ export class FoundationReviewerAgent extends BaseAgent {
19
+ get name(): string {
20
+ return "foundation-reviewer";
21
+ }
22
+
23
+ async review(params: {
24
+ readonly foundation: ArchitectOutput;
25
+ readonly mode: "original" | "fanfic" | "series";
26
+ readonly sourceCanon?: string;
27
+ readonly styleGuide?: string;
28
+ readonly language: "zh" | "en";
29
+ }): Promise<FoundationReviewResult> {
30
+ const canonBlock = params.sourceCanon
31
+ ? `\n## 原作正典参照\n${params.sourceCanon.slice(0, 8000)}\n`
32
+ : "";
33
+ const styleBlock = params.styleGuide
34
+ ? `\n## 原作风格参照\n${params.styleGuide.slice(0, 2000)}\n`
35
+ : "";
36
+
37
+ const dimensions = params.mode === "original"
38
+ ? this.originalDimensions(params.language)
39
+ : this.derivativeDimensions(params.language, params.mode);
40
+
41
+ const systemPrompt = params.language === "en"
42
+ ? this.buildEnglishReviewPrompt(dimensions, canonBlock, styleBlock)
43
+ : this.buildChineseReviewPrompt(dimensions, canonBlock, styleBlock);
44
+
45
+ const userPrompt = this.buildFoundationExcerpt(params.foundation, params.language);
46
+
47
+ const response = await this.chat([
48
+ { role: "system", content: systemPrompt },
49
+ { role: "user", content: userPrompt },
50
+ ], { temperature: 0.3 });
51
+
52
+ return this.parseReviewResult(response.content, dimensions);
53
+ }
54
+
55
+ private originalDimensions(language: "zh" | "en"): ReadonlyArray<string> {
56
+ return language === "en"
57
+ ? [
58
+ "Core Conflict (Is there a clear, compelling central conflict that can sustain 40 chapters?)",
59
+ "Opening Momentum (Can the first 5 chapters create a page-turning hook?)",
60
+ "World Coherence (Is the worldbuilding internally consistent and specific?)",
61
+ "Character Differentiation (Are the main characters distinct in voice and motivation?)",
62
+ "Pacing Feasibility (Does the volume outline have enough variety — not the same beat for 10 chapters?)",
63
+ ]
64
+ : [
65
+ "核心冲突(是否有清晰且有足够张力的核心冲突支撑40章?)",
66
+ "开篇节奏(前5章能否形成翻页驱动力?)",
67
+ "世界一致性(世界观是否内洽且具体?)",
68
+ "角色区分度(主要角色的声音和动机是否各不相同?)",
69
+ "节奏可行性(卷纲是否有足够变化——不会连续10章同一种节拍?)",
70
+ ];
71
+ }
72
+
73
+ private derivativeDimensions(language: "zh" | "en", mode: "fanfic" | "series"): ReadonlyArray<string> {
74
+ const modeLabel = mode === "fanfic"
75
+ ? (language === "en" ? "Fan Fiction" : "同人")
76
+ : (language === "en" ? "Series" : "系列");
77
+
78
+ return language === "en"
79
+ ? [
80
+ `Source DNA Preservation (Does the ${modeLabel} respect the original's world rules, character personalities, and established facts?)`,
81
+ `New Narrative Space (Is there a clear divergence point or new territory that gives the story room to be ORIGINAL, not a retelling?)`,
82
+ "Core Conflict (Is the new story's central conflict compelling and distinct from the original?)",
83
+ "Opening Momentum (Can the first 5 chapters create a page-turning hook without requiring 3 chapters of setup?)",
84
+ `Pacing Feasibility (Does the outline avoid the trap of re-walking the original's plot beats?)`,
85
+ ]
86
+ : [
87
+ `原作DNA保留(${modeLabel}是否尊重原作的世界规则、角色性格、已确立事实?)`,
88
+ `新叙事空间(是否有明确的分岔点或新领域,让故事有原创空间,而非复述原作?)`,
89
+ "核心冲突(新故事的核心冲突是否有足够张力且区别于原作?)",
90
+ "开篇节奏(前5章能否形成翻页驱动力,不需要3章铺垫?)",
91
+ `节奏可行性(卷纲是否避免了重走原作剧情节拍的陷阱?)`,
92
+ ];
93
+ }
94
+
95
+ private buildChineseReviewPrompt(
96
+ dimensions: ReadonlyArray<string>,
97
+ canonBlock: string,
98
+ styleBlock: string,
99
+ ): string {
100
+ return `你是一位资深小说编辑,正在审核一本新书的基础设定(世界观 + 大纲 + 规则)。
101
+
102
+ 你需要从以下维度逐项打分(0-100),并给出具体意见:
103
+
104
+ ${dimensions.map((dim, i) => `${i + 1}. ${dim}`).join("\n")}
105
+
106
+ ## 评分标准
107
+ - 80+ 通过,可以开始写作
108
+ - 60-79 有明显问题,需要修改
109
+ - <60 方向性错误,需要重新设计
110
+
111
+ ## 输出格式(严格遵守)
112
+ === DIMENSION: 1 ===
113
+ 分数:{0-100}
114
+ 意见:{具体反馈}
115
+
116
+ === DIMENSION: 2 ===
117
+ 分数:{0-100}
118
+ 意见:{具体反馈}
119
+
120
+ ...(每个维度一个 block)
121
+
122
+ === OVERALL ===
123
+ 总分:{加权平均}
124
+ 通过:{是/否}
125
+ 总评:{1-2段总结,指出最大的问题和最值得保留的优点}
126
+ ${canonBlock}${styleBlock}
127
+
128
+ 审核时要严格。不要因为"还行"就给高分。80分意味着"可以直接开写,不需要改"。`;
129
+ }
130
+
131
+ private buildEnglishReviewPrompt(
132
+ dimensions: ReadonlyArray<string>,
133
+ canonBlock: string,
134
+ styleBlock: string,
135
+ ): string {
136
+ return `You are a senior fiction editor reviewing a new book's foundation (worldbuilding + outline + rules).
137
+
138
+ Score each dimension (0-100) with specific feedback:
139
+
140
+ ${dimensions.map((dim, i) => `${i + 1}. ${dim}`).join("\n")}
141
+
142
+ ## Scoring
143
+ - 80+ Pass — ready to write
144
+ - 60-79 Needs revision
145
+ - <60 Fundamental direction problem
146
+
147
+ ## Output format (strict)
148
+ === DIMENSION: 1 ===
149
+ Score: {0-100}
150
+ Feedback: {specific feedback}
151
+
152
+ === DIMENSION: 2 ===
153
+ Score: {0-100}
154
+ Feedback: {specific feedback}
155
+
156
+ ...
157
+
158
+ === OVERALL ===
159
+ Total: {weighted average}
160
+ Passed: {yes/no}
161
+ Summary: {1-2 paragraphs — biggest problem and best quality}
162
+ ${canonBlock}${styleBlock}
163
+
164
+ Be strict. 80 means "ready to write without changes."`;
165
+ }
166
+
167
+ private buildFoundationExcerpt(foundation: ArchitectOutput, language: "zh" | "en"): string {
168
+ return language === "en"
169
+ ? `## Story Bible\n${foundation.storyBible.slice(0, 3000)}\n\n## Volume Outline\n${foundation.volumeOutline.slice(0, 3000)}\n\n## Book Rules\n${foundation.bookRules.slice(0, 1500)}\n\n## Initial State\n${foundation.currentState.slice(0, 1000)}\n\n## Initial Hooks\n${foundation.pendingHooks.slice(0, 1000)}`
170
+ : `## 世界设定\n${foundation.storyBible.slice(0, 3000)}\n\n## 卷纲\n${foundation.volumeOutline.slice(0, 3000)}\n\n## 规则\n${foundation.bookRules.slice(0, 1500)}\n\n## 初始状态\n${foundation.currentState.slice(0, 1000)}\n\n## 初始伏笔\n${foundation.pendingHooks.slice(0, 1000)}`;
171
+ }
172
+
173
+ private parseReviewResult(
174
+ content: string,
175
+ dimensions: ReadonlyArray<string>,
176
+ ): FoundationReviewResult {
177
+ const parsedDimensions: Array<{ readonly name: string; readonly score: number; readonly feedback: string }> = [];
178
+
179
+ for (let i = 0; i < dimensions.length; i++) {
180
+ const regex = new RegExp(
181
+ `=== DIMENSION: ${i + 1} ===\\s*[\\s\\S]*?(?:分数|Score)[::]\\s*(\\d+)[\\s\\S]*?(?:意见|Feedback)[::]\\s*([\\s\\S]*?)(?==== |$)`,
182
+ );
183
+ const match = content.match(regex);
184
+ parsedDimensions.push({
185
+ name: dimensions[i]!,
186
+ score: match ? parseInt(match[1]!, 10) : 50,
187
+ feedback: match ? match[2]!.trim() : "(parse failed)",
188
+ });
189
+ }
190
+
191
+ const totalScore = parsedDimensions.length > 0
192
+ ? Math.round(parsedDimensions.reduce((sum, d) => sum + d.score, 0) / parsedDimensions.length)
193
+ : 0;
194
+ const anyBelowFloor = parsedDimensions.some((d) => d.score < DIMENSION_FLOOR);
195
+ const passed = totalScore >= PASS_THRESHOLD && !anyBelowFloor;
196
+
197
+ const overallMatch = content.match(
198
+ /=== OVERALL ===[\s\S]*?(?:总评|Summary)[::]\s*([\s\S]*?)$/,
199
+ );
200
+ const overallFeedback = overallMatch ? overallMatch[1]!.trim() : "(parse failed)";
201
+
202
+ return { passed, totalScore, dimensions: parsedDimensions, overallFeedback };
203
+ }
204
+ }
@@ -0,0 +1,218 @@
1
+ import { BaseAgent } from "./base.js";
2
+ import type { LengthNormalizeMode, LengthSpec } from "../models/length-governance.js";
3
+ import { countChapterLength, chooseNormalizeMode, isOutsideHardRange, isOutsideSoftRange } from "../utils/length-metrics.js";
4
+
5
+ export interface NormalizeLengthInput {
6
+ readonly chapterContent: string;
7
+ readonly lengthSpec: LengthSpec;
8
+ readonly chapterIntent?: string;
9
+ readonly reducedControlBlock?: string;
10
+ }
11
+
12
+ export interface NormalizeLengthOutput {
13
+ readonly normalizedContent: string;
14
+ readonly finalCount: number;
15
+ readonly applied: boolean;
16
+ readonly mode: LengthNormalizeMode;
17
+ readonly warning?: string;
18
+ readonly tokenUsage?: {
19
+ readonly promptTokens: number;
20
+ readonly completionTokens: number;
21
+ readonly totalTokens: number;
22
+ };
23
+ }
24
+
25
+ export class LengthNormalizerAgent extends BaseAgent {
26
+ get name(): string {
27
+ return "length-normalizer";
28
+ }
29
+
30
+ async normalizeChapter(input: NormalizeLengthInput): Promise<NormalizeLengthOutput> {
31
+ const originalCount = countChapterLength(input.chapterContent, input.lengthSpec.countingMode);
32
+ const mode = input.lengthSpec.normalizeMode === "none"
33
+ ? chooseNormalizeMode(originalCount, input.lengthSpec)
34
+ : input.lengthSpec.normalizeMode;
35
+
36
+ if (mode === "none") {
37
+ return {
38
+ normalizedContent: input.chapterContent,
39
+ finalCount: originalCount,
40
+ applied: false,
41
+ mode,
42
+ };
43
+ }
44
+
45
+ const systemPrompt = this.buildSystemPrompt(mode);
46
+ const userPrompt = this.buildUserPrompt(input, originalCount, mode);
47
+ const response = await this.chat(
48
+ [
49
+ { role: "system", content: systemPrompt },
50
+ { role: "user", content: userPrompt },
51
+ ],
52
+ {
53
+ temperature: 0.2,
54
+ },
55
+ );
56
+
57
+ const sanitizedContent = this.sanitizeNormalizedContent(response.content, input.chapterContent);
58
+ const sanitizedCount = countChapterLength(sanitizedContent, input.lengthSpec.countingMode);
59
+ const wasTruncated = sanitizedContent !== input.chapterContent
60
+ && sanitizedCount < input.lengthSpec.hardMin
61
+ && this.looksTruncated(sanitizedContent);
62
+ const normalizedContent = wasTruncated ? input.chapterContent : sanitizedContent;
63
+ const finalCount = countChapterLength(normalizedContent, input.lengthSpec.countingMode);
64
+ const warning = wasTruncated
65
+ ? "Length normalizer output appeared truncated; kept original chapter."
66
+ : this.buildWarning(finalCount, input.lengthSpec);
67
+
68
+ return {
69
+ normalizedContent,
70
+ finalCount,
71
+ applied: true,
72
+ mode,
73
+ warning,
74
+ tokenUsage: response.usage,
75
+ };
76
+ }
77
+
78
+ private buildSystemPrompt(mode: LengthNormalizeMode): string {
79
+ const action = mode === "compress"
80
+ ? "compress"
81
+ : "expand";
82
+
83
+ return `你是一位章节长度修正器。你的任务是对章节正文做一次单次修正,只能执行一次,不得递归重写。
84
+
85
+ 修正目标:
86
+ - ${action} 章节长度到给定目标区间
87
+ - 保留章节原有事实、关键钩子、角色名和必须保留的标记
88
+ - 不要引入新的支线、未来揭示或额外总结
89
+ - 不要在正文外输出任何解释`;
90
+ }
91
+
92
+ private buildUserPrompt(
93
+ input: NormalizeLengthInput,
94
+ originalCount: number,
95
+ mode: LengthNormalizeMode,
96
+ ): string {
97
+ const intentBlock = input.chapterIntent
98
+ ? `\n## Chapter Intent\n${input.chapterIntent}\n`
99
+ : "";
100
+ const controlBlock = input.reducedControlBlock
101
+ ? `\n## Reduced Control Block\n${input.reducedControlBlock}\n`
102
+ : "";
103
+
104
+ return `请对下面正文做一次${mode === "compress" ? "压缩" : "扩写"}修正。
105
+
106
+ ## Length Spec
107
+ - Target: ${input.lengthSpec.target}
108
+ - Soft Range: ${input.lengthSpec.softMin}-${input.lengthSpec.softMax}
109
+ - Hard Range: ${input.lengthSpec.hardMin}-${input.lengthSpec.hardMax}
110
+ - Counting Mode: ${input.lengthSpec.countingMode}
111
+
112
+ ## Current Count
113
+ ${originalCount}
114
+
115
+ ## Correction Rules
116
+ - 只修正一次,不要递归
117
+ - 保留正文中的关键标记、人物名、地点名和已有事实
118
+ - 不要凭空新增子情节
119
+ - 不要插入解释性总结或分析
120
+ - 输出修正后的完整正文,不要加标签
121
+
122
+ ${intentBlock}${controlBlock}
123
+ ## Chapter Content
124
+ ${input.chapterContent}`;
125
+ }
126
+
127
+ private buildWarning(finalCount: number, lengthSpec: LengthSpec): string | undefined {
128
+ if (!isOutsideSoftRange(finalCount, lengthSpec)) {
129
+ return undefined;
130
+ }
131
+
132
+ if (isOutsideHardRange(finalCount, lengthSpec)) {
133
+ return `Final count ${finalCount} is outside the hard range ${lengthSpec.hardMin}-${lengthSpec.hardMax} after one normalization pass.`;
134
+ }
135
+
136
+ return `Final count ${finalCount} is outside the soft range ${lengthSpec.softMin}-${lengthSpec.softMax} after one normalization pass.`;
137
+ }
138
+
139
+ private sanitizeNormalizedContent(rawContent: string, fallbackContent: string): string {
140
+ const trimmed = rawContent.trim();
141
+ if (!trimmed) return fallbackContent;
142
+
143
+ const fenced = this.extractFirstFencedBlock(trimmed);
144
+ if (fenced) return fenced;
145
+
146
+ const stripped = this.stripCommonWrappers(trimmed);
147
+ if (stripped !== undefined) {
148
+ // Empty after stripping = response was only wrapper text, use original
149
+ if (!stripped) return fallbackContent;
150
+ // Guard: if stripping removed more than 50% of content, the regex was too aggressive.
151
+ if (stripped.length < trimmed.length * 0.5) return trimmed;
152
+ return stripped;
153
+ }
154
+
155
+ return trimmed;
156
+ }
157
+
158
+ private looksTruncated(content: string): boolean {
159
+ const trimmed = content.trim();
160
+ if (!trimmed) return false;
161
+ if (trimmed.endsWith("```")) return false;
162
+ if (/[。!?!?」』”’))\]】》…]$/.test(trimmed)) return false;
163
+ if (/\n\s*$/.test(content) && /[,,;;::]$/.test(trimmed)) return true;
164
+ return /[,,;;::、]$/.test(trimmed) || /[\u4e00-\u9fffA-Za-z0-9]$/.test(trimmed);
165
+ }
166
+
167
+ private extractFirstFencedBlock(content: string): string | undefined {
168
+ const match = content.match(/```(?:[a-zA-Z-]+)?\s*\n([\s\S]*?)\n```/);
169
+ if (!match) return undefined;
170
+ const body = match[1]?.trim();
171
+ return body ? body : undefined;
172
+ }
173
+
174
+ private stripCommonWrappers(content: string): string | undefined {
175
+ const lines = content.split("\n");
176
+ let removedAny = false;
177
+ const keptLines: string[] = [];
178
+
179
+ for (const rawLine of lines) {
180
+ const trimmed = rawLine.trim();
181
+ if (this.isWrapperLine(trimmed)) {
182
+ removedAny = true;
183
+ continue;
184
+ }
185
+ keptLines.push(rawLine);
186
+ }
187
+
188
+ if (!removedAny) {
189
+ return undefined;
190
+ }
191
+
192
+ return keptLines.join("\n").trim();
193
+ }
194
+
195
+ private isWrapperLine(line: string): boolean {
196
+ if (!line) return false;
197
+ if (/^```/.test(line)) return true;
198
+ if (/^#+\s*(说明|解释|注释|analysis|analysis note)\b/i.test(line)) return true;
199
+
200
+ if (/^(下面是|以下是).*(正文|章节|压缩|扩写|修正|修改|调整|改写|润色|结果|内容|输出|版本)/i.test(line)) {
201
+ return true;
202
+ }
203
+
204
+ if (/^我先.*(压缩|扩写|修正|修改|调整|改写|润色|处理).*(正文|章节)?/i.test(line)) {
205
+ return true;
206
+ }
207
+
208
+ if (/^(here(?:'s| is)|below is).*(chapter|draft|content|rewrite|revised|compressed|expanded|normalized|adjusted|output|version|result)/i.test(line)) {
209
+ return true;
210
+ }
211
+
212
+ if (/^i(?:'ll| will)\s+(rewrite|revise|reword|compress|expand|normalize|adjust|shorten|lengthen|trim|fix)\b/i.test(line)) {
213
+ return true;
214
+ }
215
+
216
+ return false;
217
+ }
218
+ }
@@ -0,0 +1,127 @@
1
+ import type { BookConfig } from "../models/book.js";
2
+ import type { GenreProfile } from "../models/genre-profile.js";
3
+
4
+ /**
5
+ * Observer phase: extract ALL facts from the chapter.
6
+ * Intentionally over-extracts — better to catch too much than miss something.
7
+ * The Reflector phase will merge observations into truth files with cross-validation.
8
+ */
9
+ export function buildObserverSystemPrompt(
10
+ book: BookConfig,
11
+ genreProfile: GenreProfile,
12
+ language?: "zh" | "en",
13
+ ): string {
14
+ const isEnglish = (language ?? genreProfile.language) === "en";
15
+
16
+ const langPrefix = isEnglish
17
+ ? "【LANGUAGE OVERRIDE】ALL output MUST be in English.\n\n"
18
+ : "";
19
+
20
+ return `${langPrefix}${isEnglish ? "You are" : "你是"}${isEnglish ? " a fact extraction specialist" : "一个事实提取专家"}。${isEnglish ? "Read the chapter text and extract EVERY observable fact change." : "阅读章节正文,提取每一个可观察到的事实变化。"}
21
+
22
+ ${isEnglish ? "## Extraction Categories" : "## 提取类别"}
23
+
24
+ ${isEnglish ? `1. **Character actions**: Who did what, to whom, why
25
+ 2. **Location changes**: Who moved where, from where
26
+ 3. **Resource changes**: Items gained, lost, consumed, quantities
27
+ 4. **Relationship changes**: New encounters, trust/distrust shifts, alliances, betrayals
28
+ 5. **Emotional shifts**: Character mood before → after, trigger event
29
+ 6. **Information flow**: Who learned what, who is still unaware
30
+ 7. **Plot threads**: New mysteries planted, existing threads advanced, threads resolved
31
+ 8. **Time progression**: How much time passed, time markers mentioned
32
+ 9. **Physical state**: Injuries, healing, fatigue, power changes` : `1. **角色行为**:谁做了什么,对谁,为什么
33
+ 2. **位置变化**:谁去了哪里,从哪里来
34
+ 3. **资源变化**:获得、失去、消耗了什么,具体数量
35
+ 4. **关系变化**:新相遇、信任/不信任转变、结盟、背叛
36
+ 5. **情绪变化**:角色情绪从X到Y,触发事件是什么
37
+ 6. **信息流动**:谁知道了什么新信息,谁仍然不知情
38
+ 7. **剧情线索**:新埋下的悬念、已有线索的推进、线索的解答
39
+ 8. **时间推进**:过了多少时间,提到的时间标记
40
+ 9. **身体状态**:受伤、恢复、疲劳、战力变化`}
41
+
42
+ ${isEnglish ? "## Rules" : "## 规则"}
43
+
44
+ ${isEnglish ? `- Extract from the TEXT ONLY — do not infer what might happen
45
+ - Over-extract: if unsure whether something is significant, include it
46
+ - Be specific: "Lin Chen's left arm fractured" not "Lin Chen got hurt"
47
+ - Include chapter-internal time markers
48
+ - Note which characters are present in each scene` : `- 只从正文提取——不推测可能发生的事
49
+ - 宁多勿少:不确定是否重要时也要记录
50
+ - 具体化:"陆承烬左肩旧伤开裂" 而非 "陆承烬受伤了"
51
+ - 记录章节内的时间标记
52
+ - 标注每个场景中在场的角色`}
53
+
54
+ ${isEnglish ? "## Output Format" : "## 输出格式"}
55
+
56
+ === OBSERVATIONS ===
57
+
58
+ ${isEnglish ? `[CHARACTERS]
59
+ - <name>: <action/state change> (scene: <location>)
60
+
61
+ [LOCATIONS]
62
+ - <character> moved from <A> to <B>
63
+
64
+ [RESOURCES]
65
+ - <character> gained/lost <item> (quantity: <n>)
66
+
67
+ [RELATIONSHIPS]
68
+ - <charA> → <charB>: <change description>
69
+
70
+ [EMOTIONS]
71
+ - <character>: <before> → <after> (trigger: <event>)
72
+
73
+ [INFORMATION]
74
+ - <character> learned: <fact> (source: <how>)
75
+ - <character> still unaware of: <fact>
76
+
77
+ [PLOT_THREADS]
78
+ - NEW: <description>
79
+ - ADVANCED: <existing thread> — <progress>
80
+ - RESOLVED: <thread> — <resolution>
81
+
82
+ [TIME]
83
+ - <time markers, duration>
84
+
85
+ [PHYSICAL_STATE]
86
+ - <character>: <injury/healing/fatigue/power change>` : `[角色行为]
87
+ - <角色名>: <行为/状态变化> (场景: <地点>)
88
+
89
+ [位置变化]
90
+ - <角色> 从 <A> 到 <B>
91
+
92
+ [资源变化]
93
+ - <角色> 获得/失去 <物品> (数量: <n>)
94
+
95
+ [关系变化]
96
+ - <角色A> → <角色B>: <变化描述>
97
+
98
+ [情绪变化]
99
+ - <角色>: <之前> → <之后> (触发: <事件>)
100
+
101
+ [信息流动]
102
+ - <角色> 得知: <事实> (来源: <途径>)
103
+ - <角色> 仍不知: <事实>
104
+
105
+ [剧情线索]
106
+ - 新埋: <描述>
107
+ - 推进: <已有线索> — <进展>
108
+ - 回收: <线索> — <解答>
109
+
110
+ [时间]
111
+ - <时间标记、时长>
112
+
113
+ [身体状态]
114
+ - <角色>: <受伤/恢复/疲劳/战力变化>`}`;
115
+ }
116
+
117
+ export function buildObserverUserPrompt(
118
+ chapterNumber: number,
119
+ title: string,
120
+ content: string,
121
+ language?: "zh" | "en",
122
+ ): string {
123
+ const isEnglish = language === "en";
124
+ return isEnglish
125
+ ? `Extract all facts from Chapter ${chapterNumber} "${title}":\n\n${content}`
126
+ : `请提取第${chapterNumber}章「${title}」中的所有事实:\n\n${content}`;
127
+ }