@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,72 @@
1
+ /**
2
+ * Detection feedback loop — analyze detection_history.json to extract insights.
3
+ */
4
+
5
+ import type { DetectionHistoryEntry, DetectionStats } from "../models/detection.js";
6
+
7
+ /**
8
+ * Analyze detection history and produce aggregated statistics.
9
+ */
10
+ export function analyzeDetectionInsights(
11
+ history: ReadonlyArray<DetectionHistoryEntry>,
12
+ ): DetectionStats {
13
+ if (history.length === 0) {
14
+ return {
15
+ totalDetections: 0,
16
+ totalRewrites: 0,
17
+ avgOriginalScore: 0,
18
+ avgFinalScore: 0,
19
+ avgScoreReduction: 0,
20
+ passRate: 0,
21
+ chapterBreakdown: [],
22
+ };
23
+ }
24
+
25
+ const detections = history.filter((h) => h.action === "detect");
26
+ const rewrites = history.filter((h) => h.action === "rewrite");
27
+
28
+ // Group by chapter
29
+ const chapterMap = new Map<number, DetectionHistoryEntry[]>();
30
+ for (const entry of history) {
31
+ const existing = chapterMap.get(entry.chapterNumber) ?? [];
32
+ chapterMap.set(entry.chapterNumber, [...existing, entry]);
33
+ }
34
+
35
+ const chapterBreakdown: Array<{
36
+ chapterNumber: number;
37
+ originalScore: number;
38
+ finalScore: number;
39
+ rewriteAttempts: number;
40
+ }> = [];
41
+
42
+ let totalOriginal = 0;
43
+ let totalFinal = 0;
44
+
45
+ for (const [chapterNumber, entries] of chapterMap) {
46
+ const sorted = [...entries].sort((a, b) => a.attempt - b.attempt);
47
+ const originalScore = sorted[0]?.score ?? 0;
48
+ const finalScore = sorted[sorted.length - 1]?.score ?? originalScore;
49
+ const rewriteAttempts = sorted.filter((e) => e.action === "rewrite").length;
50
+
51
+ chapterBreakdown.push({ chapterNumber, originalScore, finalScore, rewriteAttempts });
52
+ totalOriginal += originalScore;
53
+ totalFinal += finalScore;
54
+ }
55
+
56
+ const chapterCount = chapterBreakdown.length;
57
+ const avgOriginalScore = chapterCount > 0 ? totalOriginal / chapterCount : 0;
58
+ const avgFinalScore = chapterCount > 0 ? totalFinal / chapterCount : 0;
59
+
60
+ // Pass rate = chapters where final score decreased (or no rewrite needed)
61
+ const passedChapters = chapterBreakdown.filter((c) => c.finalScore <= c.originalScore).length;
62
+
63
+ return {
64
+ totalDetections: detections.length,
65
+ totalRewrites: rewrites.length,
66
+ avgOriginalScore: Math.round(avgOriginalScore * 1000) / 1000,
67
+ avgFinalScore: Math.round(avgFinalScore * 1000) / 1000,
68
+ avgScoreReduction: Math.round((avgOriginalScore - avgFinalScore) * 1000) / 1000,
69
+ passRate: chapterCount > 0 ? Math.round((passedChapters / chapterCount) * 100) / 100 : 0,
70
+ chapterBreakdown,
71
+ };
72
+ }
@@ -0,0 +1,224 @@
1
+ /**
2
+ * AIGC detection — calls external API (GPTZero, Originality, or custom endpoint) or local rule-based/LLM model.
3
+ * Not a BaseAgent subclass since it doesn't use the LLM provider exclusively.
4
+ */
5
+
6
+ import type { DetectionConfig } from "../models/project.js";
7
+ import type { AgentContext } from "./base.js";
8
+ import { chatCompletion } from "../llm/provider.js";
9
+ import { analyzeAITells } from "./ai-tells.js";
10
+
11
+ export interface DetectionResult {
12
+ readonly score: number; // 0-1, higher = more likely AI
13
+ readonly provider: string;
14
+ readonly detectedAt: string;
15
+ readonly raw?: Record<string, unknown>;
16
+ }
17
+
18
+ /**
19
+ * Detect AI-generated content by calling an external detection API,
20
+ * running local rule-based analysis, or querying the default LLM.
21
+ * Returns a normalized score between 0 (human) and 1 (AI).
22
+ */
23
+ export async function detectAIContent(
24
+ config: DetectionConfig,
25
+ content: string,
26
+ ctx?: AgentContext,
27
+ ): Promise<DetectionResult> {
28
+ const detectedAt = new Date().toISOString();
29
+
30
+ switch (config.provider) {
31
+ case "gptzero": {
32
+ const apiKey = getApiKey(config);
33
+ return detectGPTZero(config.apiUrl || "https://api.gptzero.me/v2/predict/text", apiKey, content, detectedAt);
34
+ }
35
+ case "originality": {
36
+ const apiKey = getApiKey(config);
37
+ return detectOriginality(config.apiUrl || "https://api.originality.ai/api/v1/scan/ai", apiKey, content, detectedAt);
38
+ }
39
+ case "custom": {
40
+ const apiKey = getApiKey(config);
41
+ return detectCustom(config.apiUrl || "", apiKey, content, detectedAt);
42
+ }
43
+ case "local":
44
+ return detectLocal(content, detectedAt);
45
+ case "llm":
46
+ if (!ctx) {
47
+ throw new Error("AIGC detection using LLM provider requires an AgentContext.");
48
+ }
49
+ return detectLLM(ctx, content, detectedAt);
50
+ }
51
+ }
52
+
53
+ function getApiKey(config: DetectionConfig): string {
54
+ const keyName = config.apiKeyEnv || "DETECTION_API_KEY";
55
+ const apiKey = process.env[keyName];
56
+ if (!apiKey) {
57
+ throw new Error(
58
+ `Detection API key not found. Set ${keyName} in your environment.`,
59
+ );
60
+ }
61
+ return apiKey;
62
+ }
63
+
64
+ async function detectGPTZero(
65
+ apiUrl: string,
66
+ apiKey: string,
67
+ content: string,
68
+ detectedAt: string,
69
+ ): Promise<DetectionResult> {
70
+ const response = await fetch(apiUrl, {
71
+ method: "POST",
72
+ headers: {
73
+ "Content-Type": "application/json",
74
+ "X-Api-Key": apiKey,
75
+ },
76
+ body: JSON.stringify({ document: content }),
77
+ });
78
+
79
+ if (!response.ok) {
80
+ const body = await response.text();
81
+ throw new Error(`GPTZero API failed: ${response.status} ${body}`);
82
+ }
83
+
84
+ const data = await response.json() as Record<string, unknown>;
85
+ const documents = data.documents as Array<Record<string, unknown>> | undefined;
86
+ const score = documents?.[0]?.completely_generated_prob as number ?? 0;
87
+
88
+ return { score, provider: "gptzero", detectedAt, raw: data };
89
+ }
90
+
91
+ async function detectOriginality(
92
+ apiUrl: string,
93
+ apiKey: string,
94
+ content: string,
95
+ detectedAt: string,
96
+ ): Promise<DetectionResult> {
97
+ const response = await fetch(apiUrl, {
98
+ method: "POST",
99
+ headers: {
100
+ "Content-Type": "application/json",
101
+ Authorization: `Bearer ${apiKey}`,
102
+ },
103
+ body: JSON.stringify({ content }),
104
+ });
105
+
106
+ if (!response.ok) {
107
+ const body = await response.text();
108
+ throw new Error(`Originality API failed: ${response.status} ${body}`);
109
+ }
110
+
111
+ const data = await response.json() as Record<string, unknown>;
112
+ const score = (data.score as Record<string, unknown>)?.ai as number ?? 0;
113
+
114
+ return { score, provider: "originality", detectedAt, raw: data };
115
+ }
116
+
117
+ async function detectCustom(
118
+ apiUrl: string,
119
+ apiKey: string,
120
+ content: string,
121
+ detectedAt: string,
122
+ ): Promise<DetectionResult> {
123
+ if (!apiUrl) {
124
+ throw new Error("Detection API URL (apiUrl) must be configured for custom provider.");
125
+ }
126
+ const response = await fetch(apiUrl, {
127
+ method: "POST",
128
+ headers: {
129
+ "Content-Type": "application/json",
130
+ Authorization: `Bearer ${apiKey}`,
131
+ },
132
+ body: JSON.stringify({ content }),
133
+ });
134
+
135
+ if (!response.ok) {
136
+ const body = await response.text();
137
+ throw new Error(`Detection API failed: ${response.status} ${body}`);
138
+ }
139
+
140
+ const data = await response.json() as Record<string, unknown>;
141
+ const score = typeof data.score === "number" ? data.score : 0;
142
+
143
+ return { score, provider: "custom", detectedAt, raw: data };
144
+ }
145
+
146
+ function detectLocal(
147
+ content: string,
148
+ detectedAt: string,
149
+ ): DetectionResult {
150
+ const result = analyzeAITells(content, "zh");
151
+ const warnings = result.issues.filter(i => i.severity === "warning");
152
+ const infos = result.issues.filter(i => i.severity === "info");
153
+
154
+ // Base score 0.05, +0.25 per warning, +0.10 per info, max 0.95
155
+ let score = 0.05 + warnings.length * 0.25 + infos.length * 0.10;
156
+ score = Math.min(0.95, score);
157
+
158
+ return {
159
+ score,
160
+ provider: "local",
161
+ detectedAt,
162
+ raw: { ...result, score },
163
+ };
164
+ }
165
+
166
+ async function detectLLM(
167
+ ctx: AgentContext,
168
+ content: string,
169
+ detectedAt: string,
170
+ ): Promise<DetectionResult> {
171
+ const prompt = `你是一位顶尖的中文文学编辑和小说AIGC写作特征(“AI味”)检测专家。
172
+ 请仔细评估以下小说章节文本的“AI味”和写作风格,并给出详细的评估结果。
173
+
174
+ 常见的中文小说“AI味”特征包括:
175
+ 1. 段落长度高度均匀,缺乏长短结合的节奏变化。
176
+ 2. 过度使用套话、假大空的抒情和转折词(如“然而”、“与此同时”、“在某种意义上”、“似乎”、“大概”、“不禁”等)。
177
+ 3. 列表式排比句式或连续用相同开头(如多句以“他…”或“营地…”开头)。
178
+ 4. 缺乏粗粝、真实的细节描写,多用泛化的、诗意化的概念(例如“时间流逝”、“命运纠缠”)。
179
+ 5. 叙事逻辑过于温和或圆滑,缺乏突发冲突和人物真实的心理张力。
180
+
181
+ 请按照以下JSON格式返回您的评估结果,绝对不要包含任何Markdown包装(如 \`\`\`json 和 \`\`\` 标记),直接返回 JSON 文本:
182
+ {
183
+ "score": 0.0到1.0之间的浮点数(分值越高,表示AI痕迹越重,>=0.5为超标),
184
+ "issues": [
185
+ {
186
+ "severity": "warning" 或 "info",
187
+ "category": "特征类别名称",
188
+ "description": "具体的AI痕迹或写作风格缺陷描述",
189
+ "suggestion": "具体的修改与润色建议"
190
+ }
191
+ ]
192
+ }
193
+
194
+ 待评估文本:
195
+ ${content}`;
196
+
197
+ const response = await chatCompletion(ctx.client, ctx.model, [
198
+ { role: "user", content: prompt }
199
+ ], { temperature: 0.3 });
200
+
201
+ let score = 0.5;
202
+ let raw: any = {};
203
+ try {
204
+ const text = response.content.trim();
205
+ const jsonStr = text.replace(/^```json\s*/i, "").replace(/```$/, "").trim();
206
+ const data = JSON.parse(jsonStr);
207
+ score = typeof data.score === "number" ? data.score : 0.5;
208
+ raw = data;
209
+ } catch (e) {
210
+ ctx.logger?.warn(`[detector] Failed to parse LLM response as JSON: ${e}. Response was: ${response.content}`);
211
+ const match = response.content.match(/score["'\s:]+(\d+\.\d+|\d+)/i);
212
+ if (match && match[1]) {
213
+ score = parseFloat(match[1]);
214
+ }
215
+ }
216
+
217
+ return {
218
+ score,
219
+ provider: `llm (${ctx.model})`,
220
+ detectedAt,
221
+ raw,
222
+ };
223
+ }
224
+
@@ -0,0 +1,129 @@
1
+ import type { BookConfig } from "../models/book.js";
2
+ import type { GenreProfile } from "../models/genre-profile.js";
3
+ import type { BookRules } from "../models/book-rules.js";
4
+
5
+ // English equivalent of buildCoreRules() — universal writing rules for English fiction
6
+ export function buildEnglishCoreRules(_book: BookConfig): string {
7
+ return `## Universal Writing Rules
8
+
9
+ ### Character Rules
10
+ 1. **Consistency**: Behavior driven by "past experience + current interests + core personality." Never break character without cause.
11
+ 2. **Dimensionality**: Core trait + contrasting detail = real person. Perfect characters are failed characters.
12
+ 3. **No puppets**: Side characters must have independent motivation and agency. MC's strength comes from outmaneuvering smart people, not steamrolling idiots.
13
+ 4. **Voice distinction**: Different characters must speak differently—vocabulary, sentence length, slang, verbal tics.
14
+ 5. **Relationship logic**: Any relationship change must be set up by events and motivated by interests.
15
+
16
+ ### Narrative Technique
17
+ 6. **Show, don't tell**: Convey through action and sensory detail, not exposition. Values expressed through behavior, not declared.
18
+ 7. **Sensory grounding**: Each scene includes 1-2 sensory details beyond the visual.
19
+ 8. **Chapter hooks**: Every chapter ending needs a hook—question, reveal, threat, promise.
20
+ 9. **Information layering**: Worldbuilding emerges through action. Key lore revealed at plot-critical moments. Never dump exposition.
21
+ 10. **Description serves narrative**: Environment descriptions set mood or foreshadow. One line is enough.
22
+ 11. **Downtime earns its place**: Quiet scenes must plant hooks, advance relationships, or build contrast. Pure filler is padding.
23
+ 12. **Dialogue-driven**: In scenes with character interaction, deliver conflict and information through dialogue first, narration second. Solo/escape/exploration scenes are exempt.
24
+
25
+ ### Logic / Consistency
26
+ 12. **World rules are law**: Once established, physics/magic/social rules cannot bend for plot convenience.
27
+ 13. **Cost matters**: Every power, ability, or advantage must have a cost or limitation that creates real trade-offs.
28
+ 14. **Consequences stick**: Actions have consequences. Characters can't escape repercussions through luck or author fiat.
29
+ 15. **No reset buttons**: The world must change permanently in response to major events.
30
+
31
+ ### Reader Psychology
32
+ 16. **Promise and payoff**: Every planted hook must be resolved. Every mystery must have an answer.
33
+ 17. **Escalation**: Each conflict should feel higher-stakes than the last—either externally or emotionally.
34
+ 18. **Reader proxy**: One character should react with surprise/excitement/fear when remarkable things happen, giving readers permission to feel the same.
35
+ 19. **Pacing breathing room**: After a high-intensity sequence, give 0.5-1 chapter of lower intensity before the next escalation.`;
36
+ }
37
+
38
+ // English equivalent of buildAntiAIExamples()
39
+ export function buildEnglishAntiAIRules(): string {
40
+ return `## Anti-AI Iron Laws
41
+
42
+ **[IRON LAW 1]** The narrator never tells the reader what to conclude.
43
+ If the reader can infer intent from action, the narrator must not state it.
44
+ - ✗ "He realized this was the most important battle of his life."
45
+ - ✓ Just write the battle—let the stakes speak.
46
+
47
+ **[IRON LAW 2]** No analytical/report language in prose.
48
+ Banned in narrative text: "core motivation," "information asymmetry," "strategic advantage," "calculated risk," "optimal outcome," "key takeaway," "it's worth noting."
49
+ - ✗ "His core motivation was survival."
50
+ - ✓ "He needed to get out. That was it. Everything else was noise."
51
+
52
+ **[IRON LAW 3]** AI-tell words are rate-limited (max 1 per 3,000 words):
53
+ delve, tapestry, testament, intricate, pivotal, vibrant, embark, comprehensive, nuanced, landscape (metaphorical), realm (metaphorical), foster, underscore.
54
+
55
+ **[IRON LAW 4]** No repetitive image cycling.
56
+ If the same metaphor appears twice, the third occurrence MUST switch to a new image.
57
+
58
+ **[IRON LAW 5]** Planning terms never appear in chapter text.
59
+ "Current situation," "core motivation," "information boundary" are PRE_WRITE_CHECK tools only.
60
+
61
+ **[IRON LAW 6]** Ban the "Not X; Y" construction. Max once per chapter.
62
+ - ✗ "It wasn't fear. It was something deeper."
63
+ - ✓ State the thing directly.
64
+
65
+ **[IRON LAW 7]** Ban lists of three in descriptive prose. Max once per 2,000 words.
66
+ - ✗ "ancient, terrible, and vast"
67
+ - ✓ Use pairs or single precise words.
68
+
69
+ ### Anti-AI Example Table
70
+
71
+ | AI Pattern | Human Version | Why |
72
+ |---|---|---|
73
+ | He felt a surge of anger. | He slammed the table. The water glass toppled. | Action externalizes emotion |
74
+ | She was overwhelmed with sadness. | She held the phone with both hands, knuckles white. | Physical detail replaces label |
75
+ | However, things were not as simple. | Yeah, right. Nothing's ever that easy. | Character voice replaces narrator hedge |
76
+ | He saw a shadow move across the wall. | A shadow slid across the wall. | Remove filter word "saw" |
77
+ | "I won't do it," she exclaimed defiantly. | "I won't do it." She crossed her arms. | Action beat > adverb + fancy tag |`;
78
+ }
79
+
80
+ // English equivalent of buildCharacterPsychologyMethod()
81
+ export function buildEnglishCharacterMethod(): string {
82
+ return `## Character Psychology Method (Internal Planning Tool)
83
+
84
+ Before writing any character's action or dialogue, run this mental checklist (NOT in prose):
85
+ 1. **Situation**: What does this character know RIGHT NOW? (Information boundary)
86
+ 2. **Want**: What do they want in this scene? (Immediate goal)
87
+ 3. **Personality filter**: How does their personality shape their approach?
88
+ 4. **Action**: What do they DO? (Behavior, not internal monologue)
89
+ 5. **Reaction**: How do others respond to their action?
90
+
91
+ This method is for YOUR planning. The terms never appear in the chapter text.`;
92
+ }
93
+
94
+ // English pre-write checklist
95
+ export function buildEnglishPreWriteChecklist(book: BookConfig, gp: GenreProfile): string {
96
+ const items = [
97
+ "Outline anchor: Which volume_outline plot point does this chapter advance?",
98
+ "POV: Whose perspective? Consistent throughout?",
99
+ "Hook planted: What question/promise/threat carries reader to next chapter?",
100
+ "Sensory grounding: At least 2 non-visual senses per major scene",
101
+ "Character consistency: Does every character act from their established motivation?",
102
+ "Information boundary: No character references info they haven't witnessed",
103
+ `Pacing: Chapter targets ${book.chapterWordCount} words. ${gp.pacingRule}`,
104
+ "Show don't tell: Are emotions shown through action, not labeled?",
105
+ "AI-tell check: No banned analytical language in prose?",
106
+ "Conflict: What is the core tension driving this chapter?",
107
+ ];
108
+
109
+ if (gp.powerScaling) {
110
+ items.push("Power scaling: Does any power usage follow established rules?");
111
+ }
112
+ if (gp.numericalSystem) {
113
+ items.push("Numerical check: Are all stats/resources consistent with ledger?");
114
+ }
115
+
116
+ return `## Pre-Write Checklist
117
+
118
+ Before writing, output a PRE_WRITE_CHECK addressing:
119
+ ${items.map((item, i) => `${i + 1}. ${item}`).join("\n")}`;
120
+ }
121
+
122
+ // English genre intro
123
+ export function buildEnglishGenreIntro(book: BookConfig, gp: GenreProfile): string {
124
+ return `You are a professional ${gp.name} web fiction author writing for English-speaking platforms (Royal Road, Kindle Unlimited, Scribble Hub).
125
+
126
+ Target: ${book.chapterWordCount} words per chapter, ${book.targetChapters} total chapters.
127
+
128
+ Write in English. Vary sentence length. Mix short punchy sentences with longer flowing ones. Maintain consistent narrative voice throughout.`;
129
+ }
@@ -0,0 +1,146 @@
1
+ import { BaseAgent } from "./base.js";
2
+ import type { FanficMode } from "../models/book.js";
3
+
4
+ export interface FanficCanonOutput {
5
+ readonly worldRules: string;
6
+ readonly characterProfiles: string;
7
+ readonly keyEvents: string;
8
+ readonly powerSystem: string;
9
+ readonly writingStyle: string;
10
+ readonly fullDocument: string;
11
+ }
12
+
13
+ const MODE_LABELS: Record<FanficMode, string> = {
14
+ canon: "原作向(严格遵守原作设定)",
15
+ au: "AU/平行世界(世界规则可改,角色保留)",
16
+ ooc: "OOC(角色性格可偏离原作)",
17
+ cp: "CP(以配对关系为核心)",
18
+ };
19
+
20
+ export class FanficCanonImporter extends BaseAgent {
21
+ get name(): string {
22
+ return "fanfic-canon-importer";
23
+ }
24
+
25
+ async importFromText(
26
+ sourceText: string,
27
+ sourceName: string,
28
+ fanficMode: FanficMode,
29
+ ): Promise<FanficCanonOutput> {
30
+ // Truncate if too long (>50k chars ≈ ~25k words)
31
+ const maxLen = 50000;
32
+ const truncated = sourceText.length > maxLen;
33
+ const text = truncated ? sourceText.slice(0, maxLen) : sourceText;
34
+
35
+ const modeLabel = MODE_LABELS[fanficMode];
36
+
37
+ const systemPrompt = `你是一个专业的同人创作素材分析师。你的任务是从用户提供的原作素材中提取结构化正典信息,供同人写作系统使用。
38
+
39
+ 同人模式:${modeLabel}
40
+
41
+ 你需要从原作素材中提取以下内容,每个部分用 === SECTION: <name> === 分隔:
42
+
43
+ === SECTION: world_rules ===
44
+ 世界规则(地理、物理法则、魔法/力量体系、阵营组织、社会结构)。
45
+ 如果原作素材不包含明确的世界规则,从已有信息合理推断。
46
+
47
+ === SECTION: character_profiles ===
48
+ 角色档案表格,每个重要角色一行:
49
+
50
+ | 角色 | 身份 | 性格底色 | 语癖/口头禅 | 说话风格 | 行为模式 | 关键关系 | 信息边界 |
51
+ |------|------|----------|-------------|----------|----------|----------|----------|
52
+
53
+ 要求:
54
+ - 语癖/口头禅必须从原文中精确提取,如有的话
55
+ - 说话风格描述该角色的语气、用词偏好、句式特征
56
+ - 行为模式描述该角色在特定情境下的典型反应
57
+ - 信息边界标注该角色知道什么、不知道什么
58
+ - 至少提取 3 个角色,不超过 15 个
59
+
60
+ === SECTION: key_events ===
61
+ 关键事件时间线:
62
+
63
+ | 序号 | 事件 | 涉及角色 | 对同人写作的约束 |
64
+ |------|------|----------|------------------|
65
+
66
+ 按时间/出现顺序排列,标注每个事件对同人创作的约束程度。
67
+
68
+ === SECTION: power_system ===
69
+ 力量/能力体系(如果适用)。包括等级划分、核心规则、已知限制。
70
+ 如果原作没有明确的力量体系,输出"(原作无明确力量体系)"。
71
+
72
+ === SECTION: writing_style ===
73
+ 原作写作风格特征(供同人写作模仿):
74
+
75
+ 1. 叙事人称与视角(第一人称/第三人称有限/全知,是否频繁切换)
76
+ 2. 句式节奏(长短句交替模式、段落平均长度感受、对话占比)
77
+ 3. 场景描写手法(五感偏好、意象选择、环境描写密度)
78
+ 4. 对话标记习惯(说/道/笑道 等用法,对话前后是否有动作/表情补充)
79
+ 5. 情绪表达方式(直白内心独白 vs 动作外化 vs 环境映射)
80
+ 6. 比喻/修辞倾向(常用比喻类型、修辞频率)
81
+ 7. 节奏转换(紧张→舒缓的过渡方式、章节结尾习惯)
82
+
83
+ 每项用1-2个原文例句佐证。只提取原文实际存在的特征,不要泛泛描述。
84
+
85
+ 提取原则:
86
+ - 忠实于原作素材,不捏造原作中没有的信息
87
+ - 信息不足时标注"(素材未提及)"而非编造
88
+ - 角色语癖是最重要的字段——同人读者最在意角色"像不像"
89
+ - 写作风格提取必须基于实际文本特征,附原文例句
90
+ ${truncated ? "\n注意:原作素材过长,已截断。请基于已有部分提取。" : ""}`;
91
+
92
+ const response = await this.chat(
93
+ [
94
+ { role: "system", content: systemPrompt },
95
+ { role: "user", content: `以下是原作《${sourceName}》的素材:\n\n${text}` },
96
+ ],
97
+ { temperature: 0.3 },
98
+ );
99
+
100
+ const content = response.content;
101
+ const extract = (tag: string): string => {
102
+ const regex = new RegExp(
103
+ `=== SECTION: ${tag} ===\\s*([\\s\\S]*?)(?==== SECTION:|$)`,
104
+ );
105
+ const match = content.match(regex);
106
+ return match?.[1]?.trim() ?? "";
107
+ };
108
+
109
+ const worldRules = extract("world_rules");
110
+ const characterProfiles = extract("character_profiles");
111
+ const keyEvents = extract("key_events");
112
+ const powerSystem = extract("power_system");
113
+ const writingStyle = extract("writing_style");
114
+
115
+ const meta = [
116
+ "---",
117
+ "meta:",
118
+ ` sourceFile: "${sourceName}"`,
119
+ ` fanficMode: "${fanficMode}"`,
120
+ ` generatedAt: "${new Date().toISOString()}"`,
121
+ ].join("\n");
122
+
123
+ const fullDocument = [
124
+ `# 同人正典(《${sourceName}》)`,
125
+ "",
126
+ "## 世界规则",
127
+ worldRules || "(素材中未提取到明确世界规则)",
128
+ "",
129
+ "## 角色档案",
130
+ characterProfiles || "(素材中未提取到角色信息)",
131
+ "",
132
+ "## 关键事件时间线",
133
+ keyEvents || "(素材中未提取到关键事件)",
134
+ "",
135
+ "## 力量体系",
136
+ powerSystem || "(原作无明确力量体系)",
137
+ "",
138
+ "## 原作写作风格",
139
+ writingStyle || "(素材不足以提取风格特征)",
140
+ "",
141
+ meta,
142
+ ].join("\n");
143
+
144
+ return { worldRules, characterProfiles, keyEvents, powerSystem, writingStyle, fullDocument };
145
+ }
146
+ }
@@ -0,0 +1,87 @@
1
+ import type { FanficMode } from "../models/book.js";
2
+
3
+ export interface FanficDimensionConfig {
4
+ readonly activeIds: ReadonlyArray<number>;
5
+ readonly severityOverrides: ReadonlyMap<number, "critical" | "warning" | "info">;
6
+ readonly deactivatedIds: ReadonlyArray<number>;
7
+ readonly notes: ReadonlyMap<number, string>;
8
+ }
9
+
10
+ // Fanfic-specific audit dimensions (34-37)
11
+ export const FANFIC_DIMENSIONS: ReadonlyArray<{
12
+ readonly id: number;
13
+ readonly name: string;
14
+ readonly baseNote: string;
15
+ }> = [
16
+ {
17
+ id: 34,
18
+ name: "角色还原度",
19
+ baseNote: "检查角色的语癖、说话风格、行为模式是否与 fanfic_canon.md 角色档案一致。偏离必须有情境驱动。",
20
+ },
21
+ {
22
+ id: 35,
23
+ name: "世界规则遵守",
24
+ baseNote: "检查章节内容是否违反 fanfic_canon.md 中的世界规则(地理、力量体系、阵营关系)。",
25
+ },
26
+ {
27
+ id: 36,
28
+ name: "关系动态",
29
+ baseNote: "检查角色之间的关系互动是否合理,是否与 fanfic_canon.md 中标注的关键关系一致或有合理发展。",
30
+ },
31
+ {
32
+ id: 37,
33
+ name: "正典事件一致性",
34
+ baseNote: "检查章节是否与 fanfic_canon.md 关键事件时间线矛盾。",
35
+ },
36
+ ];
37
+
38
+ // Mode → dimension severity mapping
39
+ const SEVERITY_MAP: Record<FanficMode, Record<number, "critical" | "warning" | "info">> = {
40
+ canon: { 34: "critical", 35: "critical", 36: "warning", 37: "critical" },
41
+ au: { 34: "critical", 35: "info", 36: "warning", 37: "info" },
42
+ ooc: { 34: "info", 35: "warning", 36: "warning", 37: "info" },
43
+ cp: { 34: "warning", 35: "warning", 36: "critical", 37: "info" },
44
+ };
45
+
46
+ // Spinoff dims (28-31) are deactivated in fanfic mode — they're for same-author spinoffs
47
+ const SPINOFF_DIMS = [28, 29, 30, 31];
48
+
49
+ // OOC mode relaxes the built-in OOC check (dim 1)
50
+ const OOC_DIM = 1;
51
+
52
+ export function getFanficDimensionConfig(
53
+ mode: FanficMode,
54
+ _allowedDeviations: ReadonlyArray<string> = [],
55
+ ): FanficDimensionConfig {
56
+ const severityMap = SEVERITY_MAP[mode];
57
+ const severityOverrides = new Map<number, "critical" | "warning" | "info">();
58
+ const notes = new Map<number, string>();
59
+
60
+ for (const dim of FANFIC_DIMENSIONS) {
61
+ severityOverrides.set(dim.id, severityMap[dim.id]!);
62
+
63
+ const severity = severityMap[dim.id]!;
64
+ const severityLabel = severity === "critical" ? "(严格检查)"
65
+ : severity === "info" ? "(仅记录,不判定失败)"
66
+ : "(警告级别)";
67
+ notes.set(dim.id, `${dim.baseNote} ${severityLabel}`);
68
+ }
69
+
70
+ // OOC mode relaxes the built-in OOC check
71
+ if (mode === "ooc") {
72
+ severityOverrides.set(OOC_DIM, "info");
73
+ notes.set(OOC_DIM, "OOC模式下角色可偏离性格底色,此维度仅记录不判定失败。参照 fanfic_canon.md 角色档案评估偏离程度。");
74
+ }
75
+
76
+ // Canon mode strengthens the built-in OOC check
77
+ if (mode === "canon") {
78
+ notes.set(OOC_DIM, "原作向同人:角色必须严格遵守性格底色。参照 fanfic_canon.md 角色档案中的性格底色和行为模式。");
79
+ }
80
+
81
+ return {
82
+ activeIds: FANFIC_DIMENSIONS.map((d) => d.id),
83
+ severityOverrides,
84
+ deactivatedIds: SPINOFF_DIMS,
85
+ notes,
86
+ };
87
+ }