@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.
- package/.next/BUILD_ID +1 -1
- package/.next/app-path-routes-manifest.json +2 -2
- package/.next/build-manifest.json +2 -2
- package/.next/server/app/_global-error.html +1 -1
- package/.next/server/app/_global-error.rsc +1 -1
- package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found.html +1 -1
- package/.next/server/app/_not-found.rsc +1 -1
- package/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/api/inkos/route.js.nft.json +1 -1
- package/.next/server/app/api/skills/install/route.js.nft.json +1 -1
- package/.next/server/app/api/skills/search/route.js.nft.json +1 -1
- package/.next/server/app/index.html +1 -1
- package/.next/server/app/index.rsc +1 -1
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/.next/server/app-paths-manifest.json +2 -2
- package/.next/server/chunks/162.js +1 -1
- package/.next/server/middleware-build-manifest.js +1 -1
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/trace +4 -4
- package/.next/trace-build +1 -1
- package/bin/pi-web.js +4 -1
- package/inkos/.env.example +20 -0
- package/inkos/.node-version +1 -0
- package/inkos/.nvmrc +1 -0
- package/inkos/CHANGELOG.md +787 -0
- package/inkos/CONTRIBUTING.md +89 -0
- package/inkos/LICENSE +661 -0
- package/inkos/README.en.md +483 -0
- package/inkos/README.ja.md +461 -0
- package/inkos/README.md +272 -0
- package/inkos/assets/15qun.jpg +0 -0
- package/inkos/assets/41777702961_.pic.jpg +0 -0
- package/inkos/assets/inkos-short-demo-cover.png +0 -0
- package/inkos/assets/inkos-text.svg +40 -0
- package/inkos/assets/logo.svg +47 -0
- package/inkos/assets/screenshot-chapters.png +0 -0
- package/inkos/assets/screenshot-pipeline.png +0 -0
- package/inkos/assets/screenshot-state.png +0 -0
- package/inkos/assets/screenshot-terminal.png +0 -0
- package/inkos/assets/wechat-group-v8.jpg +0 -0
- package/inkos/package.json +42 -0
- package/inkos/packages/cli/package.json +74 -0
- package/inkos/packages/cli/src/__tests__/analytics.test.ts +154 -0
- package/inkos/packages/cli/src/__tests__/cli-integration.test.ts +1031 -0
- package/inkos/packages/cli/src/__tests__/daemon.test.ts +93 -0
- package/inkos/packages/cli/src/__tests__/doctor.test.ts +36 -0
- package/inkos/packages/cli/src/__tests__/interact-command.test.ts +142 -0
- package/inkos/packages/cli/src/__tests__/interaction-tools.test.ts +107 -0
- package/inkos/packages/cli/src/__tests__/llm-overrides.test.ts +25 -0
- package/inkos/packages/cli/src/__tests__/localization.test.ts +121 -0
- package/inkos/packages/cli/src/__tests__/progress-text.test.ts +92 -0
- package/inkos/packages/cli/src/__tests__/project-bootstrap.test.ts +71 -0
- package/inkos/packages/cli/src/__tests__/publish-package.test.ts +272 -0
- package/inkos/packages/cli/src/__tests__/revision-command.test.ts +82 -0
- package/inkos/packages/cli/src/__tests__/runtime-requirements.test.ts +89 -0
- package/inkos/packages/cli/src/__tests__/short-fiction-command.test.ts +48 -0
- package/inkos/packages/cli/src/__tests__/studio-runtime.test.ts +142 -0
- package/inkos/packages/cli/src/__tests__/studio.test.ts +87 -0
- package/inkos/packages/cli/src/__tests__/tui-activity-state.test.ts +20 -0
- package/inkos/packages/cli/src/__tests__/tui-agent-session.test.ts +213 -0
- package/inkos/packages/cli/src/__tests__/tui-chat-depth.test.ts +27 -0
- package/inkos/packages/cli/src/__tests__/tui-chat-draft.test.ts +44 -0
- package/inkos/packages/cli/src/__tests__/tui-command.test.ts +86 -0
- package/inkos/packages/cli/src/__tests__/tui-composer-caret.test.ts +46 -0
- package/inkos/packages/cli/src/__tests__/tui-composer-display.test.ts +40 -0
- package/inkos/packages/cli/src/__tests__/tui-dashboard.test.tsx +219 -0
- package/inkos/packages/cli/src/__tests__/tui-effects-i18n.test.ts +29 -0
- package/inkos/packages/cli/src/__tests__/tui-i18n.test.ts +22 -0
- package/inkos/packages/cli/src/__tests__/tui-input-chrome.test.ts +10 -0
- package/inkos/packages/cli/src/__tests__/tui-input-history.test.ts +40 -0
- package/inkos/packages/cli/src/__tests__/tui-layout.test.ts +55 -0
- package/inkos/packages/cli/src/__tests__/tui-local-commands.test.ts +47 -0
- package/inkos/packages/cli/src/__tests__/tui-session-store.test.ts +81 -0
- package/inkos/packages/cli/src/__tests__/tui-setup-i18n.test.ts +31 -0
- package/inkos/packages/cli/src/__tests__/tui-slash-autocomplete.test.ts +33 -0
- package/inkos/packages/cli/src/commands/agent.ts +65 -0
- package/inkos/packages/cli/src/commands/analytics.ts +77 -0
- package/inkos/packages/cli/src/commands/audit.ts +52 -0
- package/inkos/packages/cli/src/commands/book.ts +260 -0
- package/inkos/packages/cli/src/commands/compose.ts +50 -0
- package/inkos/packages/cli/src/commands/config.ts +328 -0
- package/inkos/packages/cli/src/commands/consolidate.ts +50 -0
- package/inkos/packages/cli/src/commands/daemon.ts +121 -0
- package/inkos/packages/cli/src/commands/detect.ts +125 -0
- package/inkos/packages/cli/src/commands/doctor.ts +391 -0
- package/inkos/packages/cli/src/commands/draft.ts +43 -0
- package/inkos/packages/cli/src/commands/eval.ts +217 -0
- package/inkos/packages/cli/src/commands/export.ts +45 -0
- package/inkos/packages/cli/src/commands/fanfic.ts +183 -0
- package/inkos/packages/cli/src/commands/genre.ts +160 -0
- package/inkos/packages/cli/src/commands/import.ts +158 -0
- package/inkos/packages/cli/src/commands/init.ts +47 -0
- package/inkos/packages/cli/src/commands/interact.ts +109 -0
- package/inkos/packages/cli/src/commands/plan.ts +54 -0
- package/inkos/packages/cli/src/commands/radar.ts +60 -0
- package/inkos/packages/cli/src/commands/review.ts +253 -0
- package/inkos/packages/cli/src/commands/revise.ts +58 -0
- package/inkos/packages/cli/src/commands/short-fiction.ts +294 -0
- package/inkos/packages/cli/src/commands/status.ts +138 -0
- package/inkos/packages/cli/src/commands/studio.ts +194 -0
- package/inkos/packages/cli/src/commands/style.ts +99 -0
- package/inkos/packages/cli/src/commands/tui.ts +18 -0
- package/inkos/packages/cli/src/commands/update.ts +45 -0
- package/inkos/packages/cli/src/commands/write.ts +324 -0
- package/inkos/packages/cli/src/index.ts +5 -0
- package/inkos/packages/cli/src/interaction/tools.ts +49 -0
- package/inkos/packages/cli/src/localization.ts +215 -0
- package/inkos/packages/cli/src/program.ts +106 -0
- package/inkos/packages/cli/src/progress-text.ts +85 -0
- package/inkos/packages/cli/src/project-bootstrap.ts +175 -0
- package/inkos/packages/cli/src/runtime-requirements.ts +135 -0
- package/inkos/packages/cli/src/tui/__tests__/markdown.test.ts +64 -0
- package/inkos/packages/cli/src/tui/activity-state.ts +41 -0
- package/inkos/packages/cli/src/tui/agent-input.ts +264 -0
- package/inkos/packages/cli/src/tui/ansi.ts +72 -0
- package/inkos/packages/cli/src/tui/app.ts +130 -0
- package/inkos/packages/cli/src/tui/chat-depth.ts +22 -0
- package/inkos/packages/cli/src/tui/chat-draft.ts +42 -0
- package/inkos/packages/cli/src/tui/composer-caret.ts +22 -0
- package/inkos/packages/cli/src/tui/composer-display.ts +26 -0
- package/inkos/packages/cli/src/tui/dashboard-model.ts +164 -0
- package/inkos/packages/cli/src/tui/dashboard.tsx +544 -0
- package/inkos/packages/cli/src/tui/effects.ts +542 -0
- package/inkos/packages/cli/src/tui/i18n.ts +278 -0
- package/inkos/packages/cli/src/tui/input-history.ts +69 -0
- package/inkos/packages/cli/src/tui/local-commands.ts +55 -0
- package/inkos/packages/cli/src/tui/markdown.ts +64 -0
- package/inkos/packages/cli/src/tui/session-store.ts +6 -0
- package/inkos/packages/cli/src/tui/setup.ts +397 -0
- package/inkos/packages/cli/src/tui/slash-autocomplete.ts +62 -0
- package/inkos/packages/cli/src/tui/theme.ts +17 -0
- package/inkos/packages/cli/src/utils.ts +222 -0
- package/inkos/packages/cli/tsconfig.json +9 -0
- package/inkos/packages/core/genres/cozy.md +43 -0
- package/inkos/packages/core/genres/cultivation.md +42 -0
- package/inkos/packages/core/genres/dungeon-core.md +40 -0
- package/inkos/packages/core/genres/horror.md +51 -0
- package/inkos/packages/core/genres/isekai.md +43 -0
- package/inkos/packages/core/genres/litrpg.md +43 -0
- package/inkos/packages/core/genres/other.md +24 -0
- package/inkos/packages/core/genres/progression.md +41 -0
- package/inkos/packages/core/genres/romantasy.md +45 -0
- package/inkos/packages/core/genres/sci-fi.md +42 -0
- package/inkos/packages/core/genres/system-apocalypse.md +40 -0
- package/inkos/packages/core/genres/tower-climber.md +41 -0
- package/inkos/packages/core/genres/urban.md +53 -0
- package/inkos/packages/core/genres/xianxia.md +46 -0
- package/inkos/packages/core/genres/xuanhuan.md +64 -0
- package/inkos/packages/core/package.json +61 -0
- package/inkos/packages/core/src/__tests__/agent-max-tokens-policy.test.ts +29 -0
- package/inkos/packages/core/src/__tests__/agent-session.test.ts +866 -0
- package/inkos/packages/core/src/__tests__/agent-system-prompt.test.ts +167 -0
- package/inkos/packages/core/src/__tests__/agent-tools-params.test.ts +197 -0
- package/inkos/packages/core/src/__tests__/agent-tools.test.ts +421 -0
- package/inkos/packages/core/src/__tests__/ai-tells.test.ts +90 -0
- package/inkos/packages/core/src/__tests__/architect-phase5-consolidated.test.ts +445 -0
- package/inkos/packages/core/src/__tests__/architect-phase5.test.ts +455 -0
- package/inkos/packages/core/src/__tests__/architect-phase7.test.ts +210 -0
- package/inkos/packages/core/src/__tests__/architect.test.ts +859 -0
- package/inkos/packages/core/src/__tests__/audit-parse.test.ts +78 -0
- package/inkos/packages/core/src/__tests__/book-id.test.ts +26 -0
- package/inkos/packages/core/src/__tests__/book-session-store.test.ts +447 -0
- package/inkos/packages/core/src/__tests__/book-session.test.ts +113 -0
- package/inkos/packages/core/src/__tests__/chapter-analyzer.test.ts +574 -0
- package/inkos/packages/core/src/__tests__/chapter-memo-parser.test.ts +247 -0
- package/inkos/packages/core/src/__tests__/chapter-persistence.test.ts +198 -0
- package/inkos/packages/core/src/__tests__/chapter-review-cycle.test.ts +294 -0
- package/inkos/packages/core/src/__tests__/chapter-splitter.test.ts +156 -0
- package/inkos/packages/core/src/__tests__/chapter-state-recovery.test.ts +235 -0
- package/inkos/packages/core/src/__tests__/chapter-truth-validation.test.ts +253 -0
- package/inkos/packages/core/src/__tests__/composer.test.ts +627 -0
- package/inkos/packages/core/src/__tests__/config-loader.test.ts +325 -0
- package/inkos/packages/core/src/__tests__/config-migration.test.ts +102 -0
- package/inkos/packages/core/src/__tests__/consolidator.test.ts +32 -0
- package/inkos/packages/core/src/__tests__/context-filter.test.ts +60 -0
- package/inkos/packages/core/src/__tests__/context-transform.test.ts +108 -0
- package/inkos/packages/core/src/__tests__/continuity.test.ts +391 -0
- package/inkos/packages/core/src/__tests__/detection-insights.test.ts +59 -0
- package/inkos/packages/core/src/__tests__/detector.test.ts +86 -0
- package/inkos/packages/core/src/__tests__/draft-directive-parser.test.ts +386 -0
- package/inkos/packages/core/src/__tests__/edit-controller.test.ts +190 -0
- package/inkos/packages/core/src/__tests__/effective-llm-config.test.ts +486 -0
- package/inkos/packages/core/src/__tests__/fanfic-dimensions.test.ts +58 -0
- package/inkos/packages/core/src/__tests__/fanfic-models.test.ts +69 -0
- package/inkos/packages/core/src/__tests__/governed-working-set.test.ts +155 -0
- package/inkos/packages/core/src/__tests__/hook-arbiter.test.ts +124 -0
- package/inkos/packages/core/src/__tests__/hook-governance.test.ts +228 -0
- package/inkos/packages/core/src/__tests__/hook-health.test.ts +166 -0
- package/inkos/packages/core/src/__tests__/hook-ledger-validator.test.ts +236 -0
- package/inkos/packages/core/src/__tests__/hook-promotion.test.ts +192 -0
- package/inkos/packages/core/src/__tests__/hook-stale-detection.test.ts +136 -0
- package/inkos/packages/core/src/__tests__/index-notify-lazy.test.ts +20 -0
- package/inkos/packages/core/src/__tests__/interaction-chat-tokens.test.ts +170 -0
- package/inkos/packages/core/src/__tests__/interaction-models.test.ts +155 -0
- package/inkos/packages/core/src/__tests__/interaction-nl-router.test.ts +223 -0
- package/inkos/packages/core/src/__tests__/interaction-runtime.test.ts +633 -0
- package/inkos/packages/core/src/__tests__/interaction-tools.test.ts +343 -0
- package/inkos/packages/core/src/__tests__/length-metrics.test.ts +82 -0
- package/inkos/packages/core/src/__tests__/length-normalizer.test.ts +331 -0
- package/inkos/packages/core/src/__tests__/list-models.test.ts +109 -0
- package/inkos/packages/core/src/__tests__/llm-env.test.ts +31 -0
- package/inkos/packages/core/src/__tests__/logger.test.ts +175 -0
- package/inkos/packages/core/src/__tests__/long-span-fatigue.test.ts +160 -0
- package/inkos/packages/core/src/__tests__/memory-retrieval.test.ts +1303 -0
- package/inkos/packages/core/src/__tests__/models.test.ts +918 -0
- package/inkos/packages/core/src/__tests__/outline-paths.test.ts +97 -0
- package/inkos/packages/core/src/__tests__/path-safety.test.ts +22 -0
- package/inkos/packages/core/src/__tests__/persisted-governed-plan.test.ts +134 -0
- package/inkos/packages/core/src/__tests__/phase5-cleanup.test.ts +393 -0
- package/inkos/packages/core/src/__tests__/phase5-hotfix.test.ts +288 -0
- package/inkos/packages/core/src/__tests__/phase7-hotfix.test.ts +614 -0
- package/inkos/packages/core/src/__tests__/pipeline-agent.test.ts +354 -0
- package/inkos/packages/core/src/__tests__/pipeline-runner-memory-sync.test.ts +317 -0
- package/inkos/packages/core/src/__tests__/pipeline-runner.test.ts +5200 -0
- package/inkos/packages/core/src/__tests__/planner-context.test.ts +137 -0
- package/inkos/packages/core/src/__tests__/planner-prompts-ratio.test.ts +11 -0
- package/inkos/packages/core/src/__tests__/planner-prompts.test.ts +171 -0
- package/inkos/packages/core/src/__tests__/planner.test.ts +362 -0
- package/inkos/packages/core/src/__tests__/planning-materials.test.ts +90 -0
- package/inkos/packages/core/src/__tests__/polisher.test.ts +189 -0
- package/inkos/packages/core/src/__tests__/post-write-validator.test.ts +291 -0
- package/inkos/packages/core/src/__tests__/probe.test.ts +77 -0
- package/inkos/packages/core/src/__tests__/project-interaction.test.ts +241 -0
- package/inkos/packages/core/src/__tests__/provider.test.ts +953 -0
- package/inkos/packages/core/src/__tests__/providers-group.test.ts +34 -0
- package/inkos/packages/core/src/__tests__/providers-lookup.test.ts +81 -0
- package/inkos/packages/core/src/__tests__/providers-schema.test.ts +158 -0
- package/inkos/packages/core/src/__tests__/proxy-fetch.test.ts +75 -0
- package/inkos/packages/core/src/__tests__/revise-foundation.test.ts +514 -0
- package/inkos/packages/core/src/__tests__/reviser.test.ts +859 -0
- package/inkos/packages/core/src/__tests__/runtime-state-store.test.ts +388 -0
- package/inkos/packages/core/src/__tests__/scheduler.test.ts +123 -0
- package/inkos/packages/core/src/__tests__/secrets-migration.test.ts +71 -0
- package/inkos/packages/core/src/__tests__/secrets.test.ts +95 -0
- package/inkos/packages/core/src/__tests__/sensitive-words.test.ts +88 -0
- package/inkos/packages/core/src/__tests__/service-presets-regression.test.ts +73 -0
- package/inkos/packages/core/src/__tests__/service-resolver-regression.test.ts +75 -0
- package/inkos/packages/core/src/__tests__/service-resolver.test.ts +228 -0
- package/inkos/packages/core/src/__tests__/session-transcript-restore.test.ts +1311 -0
- package/inkos/packages/core/src/__tests__/session-transcript.test.ts +195 -0
- package/inkos/packages/core/src/__tests__/settler-delta-parser.test.ts +133 -0
- package/inkos/packages/core/src/__tests__/short-fiction-public.test.ts +241 -0
- package/inkos/packages/core/src/__tests__/spot-fix-patches.test.ts +104 -0
- package/inkos/packages/core/src/__tests__/state-manager.test.ts +1298 -0
- package/inkos/packages/core/src/__tests__/state-projections.test.ts +130 -0
- package/inkos/packages/core/src/__tests__/state-reducer.test.ts +372 -0
- package/inkos/packages/core/src/__tests__/state-validator-agent.test.ts +165 -0
- package/inkos/packages/core/src/__tests__/state-validator.test.ts +122 -0
- package/inkos/packages/core/src/__tests__/style-analyzer.test.ts +61 -0
- package/inkos/packages/core/src/__tests__/temperature-constraints.test.ts +57 -0
- package/inkos/packages/core/src/__tests__/v13-hotfix-round4.test.ts +343 -0
- package/inkos/packages/core/src/__tests__/verify-service.test.ts +77 -0
- package/inkos/packages/core/src/__tests__/webhook.test.ts +91 -0
- package/inkos/packages/core/src/__tests__/writer-parser.test.ts +348 -0
- package/inkos/packages/core/src/__tests__/writer-prompts.test.ts +269 -0
- package/inkos/packages/core/src/__tests__/writer.test.ts +1360 -0
- package/inkos/packages/core/src/agent/agent-session.ts +737 -0
- package/inkos/packages/core/src/agent/agent-system-prompt.ts +199 -0
- package/inkos/packages/core/src/agent/agent-tools.ts +835 -0
- package/inkos/packages/core/src/agent/context-transform.ts +85 -0
- package/inkos/packages/core/src/agent/index.ts +14 -0
- package/inkos/packages/core/src/agents/ai-tells.ts +161 -0
- package/inkos/packages/core/src/agents/architect.ts +1291 -0
- package/inkos/packages/core/src/agents/base.ts +100 -0
- package/inkos/packages/core/src/agents/chapter-analyzer.ts +634 -0
- package/inkos/packages/core/src/agents/composer.ts +469 -0
- package/inkos/packages/core/src/agents/consolidator.ts +218 -0
- package/inkos/packages/core/src/agents/continuity.ts +824 -0
- package/inkos/packages/core/src/agents/detection-insights.ts +72 -0
- package/inkos/packages/core/src/agents/detector.ts +224 -0
- package/inkos/packages/core/src/agents/en-prompt-sections.ts +129 -0
- package/inkos/packages/core/src/agents/fanfic-canon-importer.ts +146 -0
- package/inkos/packages/core/src/agents/fanfic-dimensions.ts +87 -0
- package/inkos/packages/core/src/agents/fanfic-prompt-sections.ts +109 -0
- package/inkos/packages/core/src/agents/foundation-reviewer.ts +204 -0
- package/inkos/packages/core/src/agents/length-normalizer.ts +218 -0
- package/inkos/packages/core/src/agents/observer-prompts.ts +127 -0
- package/inkos/packages/core/src/agents/planner-context.ts +297 -0
- package/inkos/packages/core/src/agents/planner-prompts.ts +404 -0
- package/inkos/packages/core/src/agents/planner.ts +783 -0
- package/inkos/packages/core/src/agents/polisher.ts +153 -0
- package/inkos/packages/core/src/agents/post-write-validator.ts +873 -0
- package/inkos/packages/core/src/agents/radar-source.ts +123 -0
- package/inkos/packages/core/src/agents/radar.ts +120 -0
- package/inkos/packages/core/src/agents/reviser.ts +701 -0
- package/inkos/packages/core/src/agents/rules-reader.ts +155 -0
- package/inkos/packages/core/src/agents/sensitive-words.ts +142 -0
- package/inkos/packages/core/src/agents/settler-delta-parser.ts +53 -0
- package/inkos/packages/core/src/agents/settler-parser.ts +38 -0
- package/inkos/packages/core/src/agents/settler-prompts.ts +230 -0
- package/inkos/packages/core/src/agents/short-fiction.ts +429 -0
- package/inkos/packages/core/src/agents/state-validator.ts +322 -0
- package/inkos/packages/core/src/agents/style-analyzer.ts +93 -0
- package/inkos/packages/core/src/agents/writer-parser.ts +178 -0
- package/inkos/packages/core/src/agents/writer-prompts.ts +899 -0
- package/inkos/packages/core/src/agents/writer.ts +1450 -0
- package/inkos/packages/core/src/index.ts +392 -0
- package/inkos/packages/core/src/interaction/book-session-store.ts +226 -0
- package/inkos/packages/core/src/interaction/draft-directive-parser.ts +266 -0
- package/inkos/packages/core/src/interaction/edit-controller.ts +270 -0
- package/inkos/packages/core/src/interaction/events.ts +41 -0
- package/inkos/packages/core/src/interaction/export-artifact.ts +151 -0
- package/inkos/packages/core/src/interaction/intents.ts +63 -0
- package/inkos/packages/core/src/interaction/modes.ts +13 -0
- package/inkos/packages/core/src/interaction/nl-router.ts +258 -0
- package/inkos/packages/core/src/interaction/project-control.ts +150 -0
- package/inkos/packages/core/src/interaction/project-session-store.ts +81 -0
- package/inkos/packages/core/src/interaction/project-tools.ts +704 -0
- package/inkos/packages/core/src/interaction/request-router.ts +5 -0
- package/inkos/packages/core/src/interaction/runtime.ts +1167 -0
- package/inkos/packages/core/src/interaction/session-transcript-legacy.ts +113 -0
- package/inkos/packages/core/src/interaction/session-transcript-restore.ts +607 -0
- package/inkos/packages/core/src/interaction/session-transcript-schema.ts +76 -0
- package/inkos/packages/core/src/interaction/session-transcript.ts +189 -0
- package/inkos/packages/core/src/interaction/session.ts +226 -0
- package/inkos/packages/core/src/interaction/truth-authority.ts +45 -0
- package/inkos/packages/core/src/llm/config-migration.ts +58 -0
- package/inkos/packages/core/src/llm/cover-providers.ts +45 -0
- package/inkos/packages/core/src/llm/provider.ts +1331 -0
- package/inkos/packages/core/src/llm/providers/endpoints/ai360.ts +42 -0
- package/inkos/packages/core/src/llm/providers/endpoints/anthropic.ts +82 -0
- package/inkos/packages/core/src/llm/providers/endpoints/astronCodingPlan.ts +30 -0
- package/inkos/packages/core/src/llm/providers/endpoints/baichuan.ts +28 -0
- package/inkos/packages/core/src/llm/providers/endpoints/bailian.ts +65 -0
- package/inkos/packages/core/src/llm/providers/endpoints/bailianCodingPlan.ts +30 -0
- package/inkos/packages/core/src/llm/providers/endpoints/custom.ts +22 -0
- package/inkos/packages/core/src/llm/providers/endpoints/deepseek.ts +35 -0
- package/inkos/packages/core/src/llm/providers/endpoints/giteeai.ts +41 -0
- package/inkos/packages/core/src/llm/providers/endpoints/githubCopilot.ts +43 -0
- package/inkos/packages/core/src/llm/providers/endpoints/glmCodingPlan.ts +28 -0
- package/inkos/packages/core/src/llm/providers/endpoints/google.ts +51 -0
- package/inkos/packages/core/src/llm/providers/endpoints/hunyuan.ts +42 -0
- package/inkos/packages/core/src/llm/providers/endpoints/infiniai.ts +72 -0
- package/inkos/packages/core/src/llm/providers/endpoints/internlm.ts +28 -0
- package/inkos/packages/core/src/llm/providers/endpoints/kimiCode.ts +23 -0
- package/inkos/packages/core/src/llm/providers/endpoints/kimiCodingPlan.ts +24 -0
- package/inkos/packages/core/src/llm/providers/endpoints/kkaiapi.ts +56 -0
- package/inkos/packages/core/src/llm/providers/endpoints/longcat.ts +25 -0
- package/inkos/packages/core/src/llm/providers/endpoints/minimax.ts +39 -0
- package/inkos/packages/core/src/llm/providers/endpoints/minimaxCodingPlan.ts +28 -0
- package/inkos/packages/core/src/llm/providers/endpoints/mistral.ts +40 -0
- package/inkos/packages/core/src/llm/providers/endpoints/modelscope.ts +30 -0
- package/inkos/packages/core/src/llm/providers/endpoints/moonshot.ts +39 -0
- package/inkos/packages/core/src/llm/providers/endpoints/newapi.ts +21 -0
- package/inkos/packages/core/src/llm/providers/endpoints/ollama.ts +73 -0
- package/inkos/packages/core/src/llm/providers/endpoints/openai.ts +77 -0
- package/inkos/packages/core/src/llm/providers/endpoints/opencodeCodingPlan.ts +30 -0
- package/inkos/packages/core/src/llm/providers/endpoints/openrouter.ts +87 -0
- package/inkos/packages/core/src/llm/providers/endpoints/ppio.ts +86 -0
- package/inkos/packages/core/src/llm/providers/endpoints/qiniu.ts +32 -0
- package/inkos/packages/core/src/llm/providers/endpoints/sensenova.ts +45 -0
- package/inkos/packages/core/src/llm/providers/endpoints/siliconcloud.ts +126 -0
- package/inkos/packages/core/src/llm/providers/endpoints/spark.ts +33 -0
- package/inkos/packages/core/src/llm/providers/endpoints/stepfun.ts +35 -0
- package/inkos/packages/core/src/llm/providers/endpoints/tencentcloud.ts +25 -0
- package/inkos/packages/core/src/llm/providers/endpoints/volcengine.ts +52 -0
- package/inkos/packages/core/src/llm/providers/endpoints/volcengineCodingPlan.ts +42 -0
- package/inkos/packages/core/src/llm/providers/endpoints/wenxin.ts +106 -0
- package/inkos/packages/core/src/llm/providers/endpoints/xai.ts +34 -0
- package/inkos/packages/core/src/llm/providers/endpoints/xiaomimimo.ts +26 -0
- package/inkos/packages/core/src/llm/providers/endpoints/zeroone.ts +34 -0
- package/inkos/packages/core/src/llm/providers/endpoints/zhipu.ts +61 -0
- package/inkos/packages/core/src/llm/providers/index.ts +71 -0
- package/inkos/packages/core/src/llm/providers/lookup.ts +70 -0
- package/inkos/packages/core/src/llm/providers/probe.ts +35 -0
- package/inkos/packages/core/src/llm/providers/types.ts +89 -0
- package/inkos/packages/core/src/llm/providers/verify.ts +104 -0
- package/inkos/packages/core/src/llm/secrets.ts +77 -0
- package/inkos/packages/core/src/llm/service-presets.ts +215 -0
- package/inkos/packages/core/src/llm/service-resolver.ts +91 -0
- package/inkos/packages/core/src/models/book-rules.ts +126 -0
- package/inkos/packages/core/src/models/book.ts +70 -0
- package/inkos/packages/core/src/models/chapter.ts +42 -0
- package/inkos/packages/core/src/models/detection.ts +25 -0
- package/inkos/packages/core/src/models/genre-profile.ts +36 -0
- package/inkos/packages/core/src/models/input-governance.ts +99 -0
- package/inkos/packages/core/src/models/length-governance.ts +46 -0
- package/inkos/packages/core/src/models/project.ts +161 -0
- package/inkos/packages/core/src/models/runtime-state.ts +144 -0
- package/inkos/packages/core/src/models/state.ts +52 -0
- package/inkos/packages/core/src/models/style-profile.ts +15 -0
- package/inkos/packages/core/src/notify/dispatcher.ts +96 -0
- package/inkos/packages/core/src/notify/feishu.ts +34 -0
- package/inkos/packages/core/src/notify/telegram.ts +25 -0
- package/inkos/packages/core/src/notify/webhook.ts +58 -0
- package/inkos/packages/core/src/notify/wechat-work.ts +22 -0
- package/inkos/packages/core/src/pipeline/agent.ts +691 -0
- package/inkos/packages/core/src/pipeline/chapter-persistence.ts +79 -0
- package/inkos/packages/core/src/pipeline/chapter-review-cycle.ts +324 -0
- package/inkos/packages/core/src/pipeline/chapter-state-recovery.ts +236 -0
- package/inkos/packages/core/src/pipeline/chapter-truth-validation.ts +145 -0
- package/inkos/packages/core/src/pipeline/detection-runner.ts +164 -0
- package/inkos/packages/core/src/pipeline/persisted-governed-plan.ts +216 -0
- package/inkos/packages/core/src/pipeline/runner.ts +3438 -0
- package/inkos/packages/core/src/pipeline/scheduler.ts +411 -0
- package/inkos/packages/core/src/pipeline/short-fiction-runner.ts +801 -0
- package/inkos/packages/core/src/prompts/index.ts +1 -0
- package/inkos/packages/core/src/prompts/short-fiction.ts +273 -0
- package/inkos/packages/core/src/state/manager.ts +560 -0
- package/inkos/packages/core/src/state/memory-db.ts +359 -0
- package/inkos/packages/core/src/state/runtime-state-store.ts +164 -0
- package/inkos/packages/core/src/state/state-bootstrap.ts +657 -0
- package/inkos/packages/core/src/state/state-projections.ts +255 -0
- package/inkos/packages/core/src/state/state-reducer.ts +260 -0
- package/inkos/packages/core/src/state/state-validator.ts +117 -0
- package/inkos/packages/core/src/utils/analytics.ts +92 -0
- package/inkos/packages/core/src/utils/book-id.ts +31 -0
- package/inkos/packages/core/src/utils/cadence-policy.ts +46 -0
- package/inkos/packages/core/src/utils/chapter-cadence.ts +211 -0
- package/inkos/packages/core/src/utils/chapter-memo-parser.ts +157 -0
- package/inkos/packages/core/src/utils/chapter-splitter.ts +80 -0
- package/inkos/packages/core/src/utils/config-loader.ts +29 -0
- package/inkos/packages/core/src/utils/context-assembly.ts +98 -0
- package/inkos/packages/core/src/utils/context-filter.ts +190 -0
- package/inkos/packages/core/src/utils/effective-llm-config.ts +529 -0
- package/inkos/packages/core/src/utils/governed-context.ts +101 -0
- package/inkos/packages/core/src/utils/governed-working-set.ts +395 -0
- package/inkos/packages/core/src/utils/hook-arbiter.ts +332 -0
- package/inkos/packages/core/src/utils/hook-governance.ts +199 -0
- package/inkos/packages/core/src/utils/hook-health.ts +189 -0
- package/inkos/packages/core/src/utils/hook-ledger-validator.ts +277 -0
- package/inkos/packages/core/src/utils/hook-lifecycle.ts +224 -0
- package/inkos/packages/core/src/utils/hook-policy.ts +115 -0
- package/inkos/packages/core/src/utils/hook-promotion.ts +313 -0
- package/inkos/packages/core/src/utils/hook-stale-detection.ts +168 -0
- package/inkos/packages/core/src/utils/length-metrics.ts +123 -0
- package/inkos/packages/core/src/utils/llm-endpoint-auth.ts +40 -0
- package/inkos/packages/core/src/utils/llm-env.ts +74 -0
- package/inkos/packages/core/src/utils/logger.ts +123 -0
- package/inkos/packages/core/src/utils/long-span-fatigue.ts +545 -0
- package/inkos/packages/core/src/utils/memory-retrieval.ts +527 -0
- package/inkos/packages/core/src/utils/narrative-control.ts +177 -0
- package/inkos/packages/core/src/utils/outline-paths.ts +275 -0
- package/inkos/packages/core/src/utils/path-safety.ts +11 -0
- package/inkos/packages/core/src/utils/planning-materials.ts +185 -0
- package/inkos/packages/core/src/utils/pov-filter.ts +149 -0
- package/inkos/packages/core/src/utils/proxy-fetch.ts +44 -0
- package/inkos/packages/core/src/utils/runtime-writer.ts +41 -0
- package/inkos/packages/core/src/utils/spot-fix-patches.ts +189 -0
- package/inkos/packages/core/src/utils/story-markdown.ts +346 -0
- package/inkos/packages/core/src/utils/web-search.ts +82 -0
- package/inkos/packages/core/src/utils/writing-methodology.ts +164 -0
- package/inkos/packages/core/tsconfig.json +8 -0
- package/inkos/packages/core/vitest.config.ts +7 -0
- package/inkos/packages/studio/components.json +25 -0
- package/inkos/packages/studio/index.html +13 -0
- package/inkos/packages/studio/package.json +72 -0
- package/inkos/packages/studio/postcss.config.js +3 -0
- package/inkos/packages/studio/src/App.test.ts +25 -0
- package/inkos/packages/studio/src/App.tsx +280 -0
- package/inkos/packages/studio/src/api/__tests__/normalize-base-url.test.ts +40 -0
- package/inkos/packages/studio/src/api/book-create.test.ts +104 -0
- package/inkos/packages/studio/src/api/book-create.ts +94 -0
- package/inkos/packages/studio/src/api/errors.ts +17 -0
- package/inkos/packages/studio/src/api/index.ts +30 -0
- package/inkos/packages/studio/src/api/lib/run-store.ts +177 -0
- package/inkos/packages/studio/src/api/lib/sse.ts +50 -0
- package/inkos/packages/studio/src/api/phase5-hotfix.test.ts +335 -0
- package/inkos/packages/studio/src/api/safety.ts +6 -0
- package/inkos/packages/studio/src/api/server.test.ts +3162 -0
- package/inkos/packages/studio/src/api/server.ts +3666 -0
- package/inkos/packages/studio/src/api/v13-hotfix-round4.test.ts +226 -0
- package/inkos/packages/studio/src/app-state.test.ts +8 -0
- package/inkos/packages/studio/src/app-state.ts +1 -0
- package/inkos/packages/studio/src/components/ConfirmDialog.tsx +95 -0
- package/inkos/packages/studio/src/components/ServiceConfigSourceCard.tsx +139 -0
- package/inkos/packages/studio/src/components/ServiceQuickLinks.tsx +65 -0
- package/inkos/packages/studio/src/components/Sidebar.tsx +652 -0
- package/inkos/packages/studio/src/components/ai-elements/code-block.tsx +562 -0
- package/inkos/packages/studio/src/components/ai-elements/confirmation.tsx +174 -0
- package/inkos/packages/studio/src/components/ai-elements/message.tsx +360 -0
- package/inkos/packages/studio/src/components/ai-elements/prompt-input.tsx +1457 -0
- package/inkos/packages/studio/src/components/ai-elements/reasoning.tsx +226 -0
- package/inkos/packages/studio/src/components/ai-elements/shimmer.tsx +77 -0
- package/inkos/packages/studio/src/components/ai-elements/tool.tsx +173 -0
- package/inkos/packages/studio/src/components/chat/BookSidebar.tsx +291 -0
- package/inkos/packages/studio/src/components/chat/ChatMessage.tsx +39 -0
- package/inkos/packages/studio/src/components/chat/QuickActions.tsx +73 -0
- package/inkos/packages/studio/src/components/chat/ToolExecutionSteps.tsx +320 -0
- package/inkos/packages/studio/src/components/chat/__tests__/ToolExecutionSteps.test.ts +114 -0
- package/inkos/packages/studio/src/components/chat-utils.ts +56 -0
- package/inkos/packages/studio/src/components/chatbar-state.test.ts +69 -0
- package/inkos/packages/studio/src/components/sidebar/ChaptersSection.tsx +66 -0
- package/inkos/packages/studio/src/components/sidebar/CharacterSection.tsx +129 -0
- package/inkos/packages/studio/src/components/sidebar/FoundationSection.tsx +61 -0
- package/inkos/packages/studio/src/components/sidebar/ProgressSection.tsx +124 -0
- package/inkos/packages/studio/src/components/sidebar/SidebarCard.tsx +30 -0
- package/inkos/packages/studio/src/components/sidebar/SummarySection.tsx +89 -0
- package/inkos/packages/studio/src/components/ui/alert.tsx +76 -0
- package/inkos/packages/studio/src/components/ui/badge.tsx +52 -0
- package/inkos/packages/studio/src/components/ui/button-group.tsx +87 -0
- package/inkos/packages/studio/src/components/ui/button.tsx +58 -0
- package/inkos/packages/studio/src/components/ui/collapsible.tsx +19 -0
- package/inkos/packages/studio/src/components/ui/command.tsx +194 -0
- package/inkos/packages/studio/src/components/ui/dialog.tsx +158 -0
- package/inkos/packages/studio/src/components/ui/dropdown-menu.tsx +266 -0
- package/inkos/packages/studio/src/components/ui/hover-card.tsx +51 -0
- package/inkos/packages/studio/src/components/ui/input-group.tsx +158 -0
- package/inkos/packages/studio/src/components/ui/input.tsx +20 -0
- package/inkos/packages/studio/src/components/ui/select.tsx +199 -0
- package/inkos/packages/studio/src/components/ui/separator.tsx +23 -0
- package/inkos/packages/studio/src/components/ui/spinner.tsx +10 -0
- package/inkos/packages/studio/src/components/ui/textarea.tsx +18 -0
- package/inkos/packages/studio/src/components/ui/tooltip.tsx +66 -0
- package/inkos/packages/studio/src/constants/service-groups.ts +29 -0
- package/inkos/packages/studio/src/hooks/use-api.test.ts +93 -0
- package/inkos/packages/studio/src/hooks/use-api.ts +189 -0
- package/inkos/packages/studio/src/hooks/use-book-activity.test.ts +129 -0
- package/inkos/packages/studio/src/hooks/use-book-activity.ts +180 -0
- package/inkos/packages/studio/src/hooks/use-colors.ts +27 -0
- package/inkos/packages/studio/src/hooks/use-hash-route.test.ts +101 -0
- package/inkos/packages/studio/src/hooks/use-hash-route.ts +89 -0
- package/inkos/packages/studio/src/hooks/use-i18n.ts +289 -0
- package/inkos/packages/studio/src/hooks/use-session-events.ts +64 -0
- package/inkos/packages/studio/src/hooks/use-sse.test.ts +52 -0
- package/inkos/packages/studio/src/hooks/use-sse.ts +92 -0
- package/inkos/packages/studio/src/hooks/use-theme.test.ts +31 -0
- package/inkos/packages/studio/src/hooks/use-theme.ts +75 -0
- package/inkos/packages/studio/src/index.css +323 -0
- package/inkos/packages/studio/src/lib/error-copy.test.ts +34 -0
- package/inkos/packages/studio/src/lib/error-copy.ts +37 -0
- package/inkos/packages/studio/src/lib/utils.ts +6 -0
- package/inkos/packages/studio/src/main.tsx +10 -0
- package/inkos/packages/studio/src/pages/Analytics.tsx +80 -0
- package/inkos/packages/studio/src/pages/BookCreate.tsx +895 -0
- package/inkos/packages/studio/src/pages/BookDetail.tsx +652 -0
- package/inkos/packages/studio/src/pages/ChapterReader.tsx +266 -0
- package/inkos/packages/studio/src/pages/ChatPage.tsx +521 -0
- package/inkos/packages/studio/src/pages/DaemonControl.tsx +116 -0
- package/inkos/packages/studio/src/pages/Dashboard.tsx +379 -0
- package/inkos/packages/studio/src/pages/DoctorView.tsx +82 -0
- package/inkos/packages/studio/src/pages/GenreManager.tsx +464 -0
- package/inkos/packages/studio/src/pages/ImportManager.tsx +216 -0
- package/inkos/packages/studio/src/pages/LanguageSelector.tsx +74 -0
- package/inkos/packages/studio/src/pages/LogViewer.tsx +82 -0
- package/inkos/packages/studio/src/pages/RadarView.tsx +157 -0
- package/inkos/packages/studio/src/pages/ServiceDetailPage.tsx +393 -0
- package/inkos/packages/studio/src/pages/ServiceListPage.tsx +463 -0
- package/inkos/packages/studio/src/pages/StyleManager.tsx +225 -0
- package/inkos/packages/studio/src/pages/TruthFiles.tsx +194 -0
- package/inkos/packages/studio/src/pages/chat-page-state.test.ts +206 -0
- package/inkos/packages/studio/src/pages/chat-page-state.ts +112 -0
- package/inkos/packages/studio/src/pages/page-state.test.ts +258 -0
- package/inkos/packages/studio/src/pages/service-detail-state.test.ts +294 -0
- package/inkos/packages/studio/src/pages/service-detail-state.ts +234 -0
- package/inkos/packages/studio/src/pages/style-manager-state.test.ts +22 -0
- package/inkos/packages/studio/src/pages/truth-files-state.test.ts +61 -0
- package/inkos/packages/studio/src/shared/contracts.ts +143 -0
- package/inkos/packages/studio/src/store/chat/__tests__/message-parts.test.ts +172 -0
- package/inkos/packages/studio/src/store/chat/index.ts +3 -0
- package/inkos/packages/studio/src/store/chat/initialState.ts +8 -0
- package/inkos/packages/studio/src/store/chat/message-policy.test.ts +16 -0
- package/inkos/packages/studio/src/store/chat/message-policy.ts +5 -0
- package/inkos/packages/studio/src/store/chat/parts-builder.ts +187 -0
- package/inkos/packages/studio/src/store/chat/selectors.ts +13 -0
- package/inkos/packages/studio/src/store/chat/slices/create/action.ts +10 -0
- package/inkos/packages/studio/src/store/chat/slices/create/initialState.ts +9 -0
- package/inkos/packages/studio/src/store/chat/slices/message/action.ts +417 -0
- package/inkos/packages/studio/src/store/chat/slices/message/initialState.ts +10 -0
- package/inkos/packages/studio/src/store/chat/slices/message/runtime.test.ts +21 -0
- package/inkos/packages/studio/src/store/chat/slices/message/runtime.ts +233 -0
- package/inkos/packages/studio/src/store/chat/slices/message/stream-events.ts +272 -0
- package/inkos/packages/studio/src/store/chat/store.ts +11 -0
- package/inkos/packages/studio/src/store/chat/types.ts +169 -0
- package/inkos/packages/studio/src/store/service/index.ts +2 -0
- package/inkos/packages/studio/src/store/service/store.ts +123 -0
- package/inkos/packages/studio/src/store/service/types.ts +50 -0
- package/inkos/packages/studio/tsconfig.json +24 -0
- package/inkos/packages/studio/tsconfig.server.json +11 -0
- package/inkos/packages/studio/vite.config.ts +34 -0
- package/inkos/packages/studio/vitest.config.ts +14 -0
- package/inkos/pnpm-lock.yaml +9569 -0
- package/inkos/pnpm-workspace.yaml +2 -0
- package/inkos/scripts/prepare-package-for-publish.mjs +135 -0
- package/inkos/scripts/restore-package-json.mjs +31 -0
- package/inkos/scripts/set-package-versions.mjs +74 -0
- package/inkos/scripts/verify-no-workspace-protocol.mjs +140 -0
- package/inkos/skills/SKILL.md +654 -0
- package/inkos/tsconfig.json +19 -0
- package/package.json +4 -3
- /package/.next/static/{F2hMZMf1IyCVAWpkbtRz7 → -3vIrBZXdQ0rp7Wa3Kz40}/_buildManifest.js +0 -0
- /package/.next/static/{F2hMZMf1IyCVAWpkbtRz7 → -3vIrBZXdQ0rp7Wa3Kz40}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Temporal memory database for InkOS truth files.
|
|
3
|
+
*
|
|
4
|
+
* Uses Node.js built-in SQLite (node:sqlite, Node 22+).
|
|
5
|
+
* Stores facts with temporal validity (valid_from/valid_until chapter numbers),
|
|
6
|
+
* enabling precise queries like "what did character X know in chapter 5?"
|
|
7
|
+
*
|
|
8
|
+
* Backward compatible: existing markdown truth files are still the primary
|
|
9
|
+
* persistence layer. MemoryDB is an acceleration index built alongside them.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { createRequire } from "node:module";
|
|
13
|
+
import { join } from "node:path";
|
|
14
|
+
|
|
15
|
+
const require = createRequire(import.meta.url);
|
|
16
|
+
|
|
17
|
+
const FACT_SELECT_COLUMNS = `
|
|
18
|
+
id,
|
|
19
|
+
subject,
|
|
20
|
+
predicate,
|
|
21
|
+
object,
|
|
22
|
+
valid_from_chapter AS validFromChapter,
|
|
23
|
+
valid_until_chapter AS validUntilChapter,
|
|
24
|
+
source_chapter AS sourceChapter
|
|
25
|
+
`;
|
|
26
|
+
|
|
27
|
+
export interface Fact {
|
|
28
|
+
readonly id?: number;
|
|
29
|
+
readonly subject: string;
|
|
30
|
+
readonly predicate: string;
|
|
31
|
+
readonly object: string;
|
|
32
|
+
readonly validFromChapter: number;
|
|
33
|
+
readonly validUntilChapter: number | null;
|
|
34
|
+
readonly sourceChapter: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface StoredSummary {
|
|
38
|
+
readonly chapter: number;
|
|
39
|
+
readonly title: string;
|
|
40
|
+
readonly characters: string;
|
|
41
|
+
readonly events: string;
|
|
42
|
+
readonly stateChanges: string;
|
|
43
|
+
readonly hookActivity: string;
|
|
44
|
+
readonly mood: string;
|
|
45
|
+
readonly chapterType: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface StoredHook {
|
|
49
|
+
readonly hookId: string;
|
|
50
|
+
readonly startChapter: number;
|
|
51
|
+
readonly type: string;
|
|
52
|
+
readonly status: string;
|
|
53
|
+
readonly lastAdvancedChapter: number;
|
|
54
|
+
readonly expectedPayoff: string;
|
|
55
|
+
readonly payoffTiming?: string;
|
|
56
|
+
readonly notes: string;
|
|
57
|
+
// Phase 7 — hook causality / promotion metadata.
|
|
58
|
+
readonly dependsOn?: ReadonlyArray<string>;
|
|
59
|
+
readonly paysOffInArc?: string;
|
|
60
|
+
readonly coreHook?: boolean;
|
|
61
|
+
readonly halfLifeChapters?: number;
|
|
62
|
+
readonly advancedCount?: number;
|
|
63
|
+
// Phase 7 hotfix 2 — whether the seed has been promoted into the live ledger
|
|
64
|
+
// (architect-time structural rules + consolidator-time advanced_count rule).
|
|
65
|
+
// Reviewer uses this to gate critical-severity escalation.
|
|
66
|
+
readonly promoted?: boolean;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export class MemoryDB {
|
|
70
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
71
|
+
private db: any;
|
|
72
|
+
|
|
73
|
+
constructor(bookDir: string) {
|
|
74
|
+
// node:sqlite requires Node 22+; require() via createRequire for ESM compat
|
|
75
|
+
const { DatabaseSync } = require("node:sqlite");
|
|
76
|
+
const dbPath = join(bookDir, "story", "memory.db");
|
|
77
|
+
this.db = new DatabaseSync(dbPath);
|
|
78
|
+
this.db.exec("PRAGMA journal_mode = WAL");
|
|
79
|
+
this.migrate();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
private migrate(): void {
|
|
83
|
+
this.db.exec(`
|
|
84
|
+
CREATE TABLE IF NOT EXISTS facts (
|
|
85
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
86
|
+
subject TEXT NOT NULL,
|
|
87
|
+
predicate TEXT NOT NULL,
|
|
88
|
+
object TEXT NOT NULL,
|
|
89
|
+
valid_from_chapter INTEGER NOT NULL,
|
|
90
|
+
valid_until_chapter INTEGER,
|
|
91
|
+
source_chapter INTEGER NOT NULL,
|
|
92
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
CREATE TABLE IF NOT EXISTS chapter_summaries (
|
|
96
|
+
chapter INTEGER PRIMARY KEY,
|
|
97
|
+
title TEXT NOT NULL,
|
|
98
|
+
characters TEXT NOT NULL DEFAULT '',
|
|
99
|
+
events TEXT NOT NULL DEFAULT '',
|
|
100
|
+
state_changes TEXT NOT NULL DEFAULT '',
|
|
101
|
+
hook_activity TEXT NOT NULL DEFAULT '',
|
|
102
|
+
mood TEXT NOT NULL DEFAULT '',
|
|
103
|
+
chapter_type TEXT NOT NULL DEFAULT ''
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
CREATE TABLE IF NOT EXISTS hooks (
|
|
107
|
+
hook_id TEXT PRIMARY KEY,
|
|
108
|
+
start_chapter INTEGER NOT NULL DEFAULT 0,
|
|
109
|
+
type TEXT NOT NULL DEFAULT '',
|
|
110
|
+
status TEXT NOT NULL DEFAULT 'open',
|
|
111
|
+
last_advanced_chapter INTEGER NOT NULL DEFAULT 0,
|
|
112
|
+
expected_payoff TEXT NOT NULL DEFAULT '',
|
|
113
|
+
payoff_timing TEXT NOT NULL DEFAULT '',
|
|
114
|
+
notes TEXT NOT NULL DEFAULT ''
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
CREATE INDEX IF NOT EXISTS idx_facts_subject ON facts(subject);
|
|
118
|
+
CREATE INDEX IF NOT EXISTS idx_facts_valid ON facts(valid_from_chapter, valid_until_chapter);
|
|
119
|
+
CREATE INDEX IF NOT EXISTS idx_facts_source ON facts(source_chapter);
|
|
120
|
+
CREATE INDEX IF NOT EXISTS idx_hooks_status ON hooks(status);
|
|
121
|
+
CREATE INDEX IF NOT EXISTS idx_hooks_last_advanced ON hooks(last_advanced_chapter);
|
|
122
|
+
`);
|
|
123
|
+
|
|
124
|
+
this.ensureColumn("hooks", "payoff_timing", "TEXT NOT NULL DEFAULT ''");
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
private ensureColumn(table: string, column: string, definition: string): void {
|
|
128
|
+
try {
|
|
129
|
+
this.db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
|
|
130
|
+
} catch {
|
|
131
|
+
// Column already exists on existing databases.
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// ---------------------------------------------------------------------------
|
|
136
|
+
// Facts (temporal)
|
|
137
|
+
// ---------------------------------------------------------------------------
|
|
138
|
+
|
|
139
|
+
/** Add a new fact. */
|
|
140
|
+
addFact(fact: Omit<Fact, "id">): number {
|
|
141
|
+
const stmt = this.db.prepare(
|
|
142
|
+
`INSERT INTO facts (subject, predicate, object, valid_from_chapter, valid_until_chapter, source_chapter)
|
|
143
|
+
VALUES (?, ?, ?, ?, ?, ?)`,
|
|
144
|
+
);
|
|
145
|
+
const result = stmt.run(
|
|
146
|
+
fact.subject, fact.predicate, fact.object,
|
|
147
|
+
fact.validFromChapter, fact.validUntilChapter ?? null, fact.sourceChapter,
|
|
148
|
+
);
|
|
149
|
+
return Number(result.lastInsertRowid);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** Invalidate a fact (set valid_until). */
|
|
153
|
+
invalidateFact(id: number, untilChapter: number): void {
|
|
154
|
+
this.db.prepare(
|
|
155
|
+
"UPDATE facts SET valid_until_chapter = ? WHERE id = ?",
|
|
156
|
+
).run(untilChapter, id);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/** Get all currently valid facts (valid_until is null). */
|
|
160
|
+
getCurrentFacts(): ReadonlyArray<Fact> {
|
|
161
|
+
return this.db.prepare(
|
|
162
|
+
`SELECT ${FACT_SELECT_COLUMNS}
|
|
163
|
+
FROM facts
|
|
164
|
+
WHERE valid_until_chapter IS NULL
|
|
165
|
+
ORDER BY subject, predicate`,
|
|
166
|
+
).all() as unknown as Fact[];
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/** Get facts about a specific subject that are valid at a given chapter. */
|
|
170
|
+
getFactsAt(subject: string, chapter: number): ReadonlyArray<Fact> {
|
|
171
|
+
return this.db.prepare(
|
|
172
|
+
`SELECT ${FACT_SELECT_COLUMNS}
|
|
173
|
+
FROM facts
|
|
174
|
+
WHERE subject = ? AND valid_from_chapter <= ?
|
|
175
|
+
AND (valid_until_chapter IS NULL OR valid_until_chapter > ?)
|
|
176
|
+
ORDER BY predicate`,
|
|
177
|
+
).all(subject, chapter, chapter) as unknown as Fact[];
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/** Get all facts about a subject (including historical). */
|
|
181
|
+
getFactHistory(subject: string): ReadonlyArray<Fact> {
|
|
182
|
+
return this.db.prepare(
|
|
183
|
+
`SELECT ${FACT_SELECT_COLUMNS}
|
|
184
|
+
FROM facts
|
|
185
|
+
WHERE subject = ?
|
|
186
|
+
ORDER BY valid_from_chapter`,
|
|
187
|
+
).all(subject) as unknown as Fact[];
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/** Search facts by predicate (e.g., all "location" facts). */
|
|
191
|
+
getFactsByPredicate(predicate: string): ReadonlyArray<Fact> {
|
|
192
|
+
return this.db.prepare(
|
|
193
|
+
`SELECT ${FACT_SELECT_COLUMNS}
|
|
194
|
+
FROM facts
|
|
195
|
+
WHERE predicate = ? AND valid_until_chapter IS NULL
|
|
196
|
+
ORDER BY subject`,
|
|
197
|
+
).all(predicate) as unknown as Fact[];
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/** Get facts relevant to a set of character names. */
|
|
201
|
+
getFactsForCharacters(names: ReadonlyArray<string>): ReadonlyArray<Fact> {
|
|
202
|
+
if (names.length === 0) return [];
|
|
203
|
+
const placeholders = names.map(() => "?").join(",");
|
|
204
|
+
return this.db.prepare(
|
|
205
|
+
`SELECT ${FACT_SELECT_COLUMNS}
|
|
206
|
+
FROM facts
|
|
207
|
+
WHERE subject IN (${placeholders}) AND valid_until_chapter IS NULL
|
|
208
|
+
ORDER BY subject, predicate`,
|
|
209
|
+
).all(...names) as unknown as Fact[];
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
replaceCurrentFacts(facts: ReadonlyArray<Omit<Fact, "id">>): void {
|
|
213
|
+
this.db.exec("DELETE FROM facts WHERE valid_until_chapter IS NULL");
|
|
214
|
+
for (const fact of facts) {
|
|
215
|
+
this.addFact(fact);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
resetFacts(): void {
|
|
220
|
+
this.db.exec("DELETE FROM facts");
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// ---------------------------------------------------------------------------
|
|
224
|
+
// Chapter summaries
|
|
225
|
+
// ---------------------------------------------------------------------------
|
|
226
|
+
|
|
227
|
+
/** Upsert a chapter summary. */
|
|
228
|
+
upsertSummary(summary: StoredSummary): void {
|
|
229
|
+
this.db.prepare(
|
|
230
|
+
`INSERT OR REPLACE INTO chapter_summaries (chapter, title, characters, events, state_changes, hook_activity, mood, chapter_type)
|
|
231
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
232
|
+
).run(
|
|
233
|
+
summary.chapter, summary.title, summary.characters, summary.events,
|
|
234
|
+
summary.stateChanges, summary.hookActivity, summary.mood, summary.chapterType,
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
replaceSummaries(summaries: ReadonlyArray<StoredSummary>): void {
|
|
239
|
+
this.db.exec("DELETE FROM chapter_summaries");
|
|
240
|
+
for (const summary of summaries) {
|
|
241
|
+
this.upsertSummary(summary);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/** Get summaries for a range of chapters. */
|
|
246
|
+
getSummaries(fromChapter: number, toChapter: number): ReadonlyArray<StoredSummary> {
|
|
247
|
+
return this.db.prepare(
|
|
248
|
+
`SELECT
|
|
249
|
+
chapter,
|
|
250
|
+
title,
|
|
251
|
+
characters,
|
|
252
|
+
events,
|
|
253
|
+
state_changes AS stateChanges,
|
|
254
|
+
hook_activity AS hookActivity,
|
|
255
|
+
mood,
|
|
256
|
+
chapter_type AS chapterType
|
|
257
|
+
FROM chapter_summaries
|
|
258
|
+
WHERE chapter >= ? AND chapter <= ?
|
|
259
|
+
ORDER BY chapter`,
|
|
260
|
+
).all(fromChapter, toChapter) as unknown as StoredSummary[];
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/** Get summaries matching any of the given character names. */
|
|
264
|
+
getSummariesByCharacters(names: ReadonlyArray<string>): ReadonlyArray<StoredSummary> {
|
|
265
|
+
if (names.length === 0) return [];
|
|
266
|
+
const conditions = names.map(() => "characters LIKE ?").join(" OR ");
|
|
267
|
+
const params = names.map((n) => `%${n}%`);
|
|
268
|
+
return this.db.prepare(
|
|
269
|
+
`SELECT
|
|
270
|
+
chapter,
|
|
271
|
+
title,
|
|
272
|
+
characters,
|
|
273
|
+
events,
|
|
274
|
+
state_changes AS stateChanges,
|
|
275
|
+
hook_activity AS hookActivity,
|
|
276
|
+
mood,
|
|
277
|
+
chapter_type AS chapterType
|
|
278
|
+
FROM chapter_summaries
|
|
279
|
+
WHERE ${conditions}
|
|
280
|
+
ORDER BY chapter`,
|
|
281
|
+
).all(...params) as unknown as StoredSummary[];
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/** Get total chapter count. */
|
|
285
|
+
getChapterCount(): number {
|
|
286
|
+
const row = this.db.prepare("SELECT COUNT(*) as count FROM chapter_summaries").get() as unknown as { count: number };
|
|
287
|
+
return row.count;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/** Get the most recent N summaries. */
|
|
291
|
+
getRecentSummaries(count: number): ReadonlyArray<StoredSummary> {
|
|
292
|
+
return this.db.prepare(
|
|
293
|
+
`SELECT
|
|
294
|
+
chapter,
|
|
295
|
+
title,
|
|
296
|
+
characters,
|
|
297
|
+
events,
|
|
298
|
+
state_changes AS stateChanges,
|
|
299
|
+
hook_activity AS hookActivity,
|
|
300
|
+
mood,
|
|
301
|
+
chapter_type AS chapterType
|
|
302
|
+
FROM chapter_summaries
|
|
303
|
+
ORDER BY chapter DESC
|
|
304
|
+
LIMIT ?`,
|
|
305
|
+
).all(count) as unknown as ReadonlyArray<StoredSummary>;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// ---------------------------------------------------------------------------
|
|
309
|
+
// Hooks
|
|
310
|
+
// ---------------------------------------------------------------------------
|
|
311
|
+
|
|
312
|
+
upsertHook(hook: StoredHook): void {
|
|
313
|
+
this.db.prepare(
|
|
314
|
+
`INSERT OR REPLACE INTO hooks (hook_id, start_chapter, type, status, last_advanced_chapter, expected_payoff, payoff_timing, notes)
|
|
315
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
316
|
+
).run(
|
|
317
|
+
hook.hookId,
|
|
318
|
+
hook.startChapter,
|
|
319
|
+
hook.type,
|
|
320
|
+
hook.status,
|
|
321
|
+
hook.lastAdvancedChapter,
|
|
322
|
+
hook.expectedPayoff,
|
|
323
|
+
hook.payoffTiming ?? "",
|
|
324
|
+
hook.notes,
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
replaceHooks(hooks: ReadonlyArray<StoredHook>): void {
|
|
329
|
+
this.db.exec("DELETE FROM hooks");
|
|
330
|
+
for (const hook of hooks) {
|
|
331
|
+
this.upsertHook(hook);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
getActiveHooks(): ReadonlyArray<StoredHook> {
|
|
336
|
+
return this.db.prepare(
|
|
337
|
+
`SELECT
|
|
338
|
+
hook_id AS hookId,
|
|
339
|
+
start_chapter AS startChapter,
|
|
340
|
+
type,
|
|
341
|
+
status,
|
|
342
|
+
last_advanced_chapter AS lastAdvancedChapter,
|
|
343
|
+
expected_payoff AS expectedPayoff,
|
|
344
|
+
payoff_timing AS payoffTiming,
|
|
345
|
+
notes
|
|
346
|
+
FROM hooks
|
|
347
|
+
WHERE lower(status) NOT IN ('resolved', 'closed', '已回收', '已解决')
|
|
348
|
+
ORDER BY last_advanced_chapter DESC, start_chapter DESC, hook_id ASC`,
|
|
349
|
+
).all() as unknown as ReadonlyArray<StoredHook>;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// ---------------------------------------------------------------------------
|
|
353
|
+
// Lifecycle
|
|
354
|
+
// ---------------------------------------------------------------------------
|
|
355
|
+
|
|
356
|
+
close(): void {
|
|
357
|
+
this.db.close();
|
|
358
|
+
}
|
|
359
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import {
|
|
4
|
+
ChapterSummariesStateSchema,
|
|
5
|
+
CurrentStateStateSchema,
|
|
6
|
+
HooksStateSchema,
|
|
7
|
+
StateManifestSchema,
|
|
8
|
+
type RuntimeStateDelta,
|
|
9
|
+
} from "../models/runtime-state.js";
|
|
10
|
+
import type { Fact, StoredHook, StoredSummary } from "./memory-db.js";
|
|
11
|
+
import { bootstrapStructuredStateFromMarkdown, parseCurrentStateFacts } from "./state-bootstrap.js";
|
|
12
|
+
import { renderChapterSummariesProjection, renderCurrentStateProjection, renderHooksProjection } from "./state-projections.js";
|
|
13
|
+
import { applyRuntimeStateDelta, type RuntimeStateSnapshot } from "./state-reducer.js";
|
|
14
|
+
import { validateRuntimeState } from "./state-validator.js";
|
|
15
|
+
import { arbitrateRuntimeStateDeltaHooks } from "../utils/hook-arbiter.js";
|
|
16
|
+
|
|
17
|
+
export interface RuntimeStateArtifacts {
|
|
18
|
+
readonly snapshot: RuntimeStateSnapshot;
|
|
19
|
+
readonly resolvedDelta: RuntimeStateDelta;
|
|
20
|
+
readonly currentStateMarkdown: string;
|
|
21
|
+
readonly hooksMarkdown: string;
|
|
22
|
+
readonly chapterSummariesMarkdown: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface NarrativeMemorySeed {
|
|
26
|
+
readonly summaries: ReadonlyArray<StoredSummary>;
|
|
27
|
+
readonly hooks: ReadonlyArray<StoredHook>;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export async function loadRuntimeStateSnapshot(bookDir: string): Promise<RuntimeStateSnapshot> {
|
|
31
|
+
await bootstrapStructuredStateFromMarkdown({ bookDir });
|
|
32
|
+
const stateDir = join(bookDir, "story", "state");
|
|
33
|
+
|
|
34
|
+
const [manifest, currentState, hooks, chapterSummaries] = await Promise.all([
|
|
35
|
+
readJson(join(stateDir, "manifest.json"), StateManifestSchema),
|
|
36
|
+
readJson(join(stateDir, "current_state.json"), CurrentStateStateSchema),
|
|
37
|
+
readJson(join(stateDir, "hooks.json"), HooksStateSchema),
|
|
38
|
+
readJson(join(stateDir, "chapter_summaries.json"), ChapterSummariesStateSchema),
|
|
39
|
+
]);
|
|
40
|
+
|
|
41
|
+
const snapshot = {
|
|
42
|
+
manifest,
|
|
43
|
+
currentState,
|
|
44
|
+
hooks,
|
|
45
|
+
chapterSummaries,
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const issues = validateRuntimeState(snapshot);
|
|
49
|
+
if (issues.length > 0) {
|
|
50
|
+
const summary = issues
|
|
51
|
+
.map((issue) => `${issue.code}${issue.path ? `@${issue.path}` : ""}`)
|
|
52
|
+
.join(", ");
|
|
53
|
+
throw new Error(`Invalid persisted runtime state: ${summary}`);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return snapshot;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export async function buildRuntimeStateArtifacts(params: {
|
|
60
|
+
readonly bookDir: string;
|
|
61
|
+
readonly delta: RuntimeStateDelta;
|
|
62
|
+
readonly language: "zh" | "en";
|
|
63
|
+
readonly allowReapply?: boolean;
|
|
64
|
+
}): Promise<RuntimeStateArtifacts> {
|
|
65
|
+
const snapshot = await loadRuntimeStateSnapshot(params.bookDir);
|
|
66
|
+
const { resolvedDelta } = arbitrateRuntimeStateDeltaHooks({
|
|
67
|
+
hooks: snapshot.hooks.hooks,
|
|
68
|
+
delta: params.delta,
|
|
69
|
+
});
|
|
70
|
+
const next = applyRuntimeStateDelta({
|
|
71
|
+
snapshot,
|
|
72
|
+
delta: resolvedDelta,
|
|
73
|
+
allowReapply: params.allowReapply,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
snapshot: next,
|
|
78
|
+
resolvedDelta,
|
|
79
|
+
currentStateMarkdown: renderCurrentStateProjection(next.currentState, params.language),
|
|
80
|
+
// Pass the chapter number so the projection can tag stale / blocked hooks.
|
|
81
|
+
hooksMarkdown: renderHooksProjection(next.hooks, params.language, {
|
|
82
|
+
currentChapter: resolvedDelta.chapter,
|
|
83
|
+
}),
|
|
84
|
+
chapterSummariesMarkdown: renderChapterSummariesProjection(next.chapterSummaries, params.language),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export async function saveRuntimeStateSnapshot(
|
|
89
|
+
bookDir: string,
|
|
90
|
+
snapshot: RuntimeStateSnapshot,
|
|
91
|
+
): Promise<void> {
|
|
92
|
+
const stateDir = join(bookDir, "story", "state");
|
|
93
|
+
await mkdir(stateDir, { recursive: true });
|
|
94
|
+
|
|
95
|
+
await Promise.all([
|
|
96
|
+
writeFile(join(stateDir, "manifest.json"), JSON.stringify(snapshot.manifest, null, 2), "utf-8"),
|
|
97
|
+
writeFile(join(stateDir, "current_state.json"), JSON.stringify(snapshot.currentState, null, 2), "utf-8"),
|
|
98
|
+
writeFile(join(stateDir, "hooks.json"), JSON.stringify(snapshot.hooks, null, 2), "utf-8"),
|
|
99
|
+
writeFile(join(stateDir, "chapter_summaries.json"), JSON.stringify(snapshot.chapterSummaries, null, 2), "utf-8"),
|
|
100
|
+
]);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export async function loadNarrativeMemorySeed(bookDir: string): Promise<NarrativeMemorySeed> {
|
|
104
|
+
const snapshot = await loadRuntimeStateSnapshot(bookDir);
|
|
105
|
+
|
|
106
|
+
return {
|
|
107
|
+
summaries: snapshot.chapterSummaries.rows.map((row) => ({
|
|
108
|
+
chapter: row.chapter,
|
|
109
|
+
title: row.title,
|
|
110
|
+
characters: row.characters,
|
|
111
|
+
events: row.events,
|
|
112
|
+
stateChanges: row.stateChanges,
|
|
113
|
+
hookActivity: row.hookActivity,
|
|
114
|
+
mood: row.mood,
|
|
115
|
+
chapterType: row.chapterType,
|
|
116
|
+
})),
|
|
117
|
+
hooks: snapshot.hooks.hooks.map((hook) => ({
|
|
118
|
+
hookId: hook.hookId,
|
|
119
|
+
startChapter: hook.startChapter,
|
|
120
|
+
type: hook.type,
|
|
121
|
+
status: hook.status,
|
|
122
|
+
lastAdvancedChapter: hook.lastAdvancedChapter,
|
|
123
|
+
expectedPayoff: hook.expectedPayoff,
|
|
124
|
+
payoffTiming: hook.payoffTiming,
|
|
125
|
+
notes: hook.notes,
|
|
126
|
+
})),
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export async function loadSnapshotCurrentStateFacts(
|
|
131
|
+
bookDir: string,
|
|
132
|
+
chapterNumber: number,
|
|
133
|
+
): Promise<ReadonlyArray<Fact>> {
|
|
134
|
+
const snapshotDir = join(bookDir, "story", "snapshots", String(chapterNumber));
|
|
135
|
+
const structuredState = await readJsonOrNull(
|
|
136
|
+
join(snapshotDir, "state", "current_state.json"),
|
|
137
|
+
CurrentStateStateSchema,
|
|
138
|
+
);
|
|
139
|
+
if (structuredState) {
|
|
140
|
+
return structuredState.facts;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const markdown = await readFile(join(snapshotDir, "current_state.md"), "utf-8").catch(() => "");
|
|
144
|
+
return parseCurrentStateFacts(markdown, chapterNumber);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
async function readJson<T>(
|
|
148
|
+
path: string,
|
|
149
|
+
schema: { parse(value: unknown): T },
|
|
150
|
+
): Promise<T> {
|
|
151
|
+
const raw = await readFile(path, "utf-8");
|
|
152
|
+
return schema.parse(JSON.parse(raw));
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
async function readJsonOrNull<T>(
|
|
156
|
+
path: string,
|
|
157
|
+
schema: { parse(value: unknown): T },
|
|
158
|
+
): Promise<T | null> {
|
|
159
|
+
try {
|
|
160
|
+
return await readJson(path, schema);
|
|
161
|
+
} catch {
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
}
|