最近读了一遍 InkOS 的项目结构,重点看了 packages/core。这是一个很有意思的项目:表面上它是一个“自动写小说”的 CLI / Studio 工具,底层实际上更像一个面向长篇叙事生产的本地操作系统。它不是简单地把“请续写下一章”塞给 LLM,而是把建书、规划、上下文编译、正文生成、状态结算、连续性审计、修订、回滚、导出、会话恢复都工程化了。

项目仓库:https://github.com/Narcooo/inkos

总览

InkOS 是一个 pnpm workspace,主要由三个包组成:

inkos
├── packages/core      # @actalk/inkos-core,核心引擎
├── packages/cli       # @actalk/inkos,命令行与 TUI 入口
└── packages/studio    # @actalk/inkos-studio,Web 工作台

其中 inkos-core 是绝对核心。CLI 和 Studio 都只是不同形态的上层外壳,真正的小说生产能力、LLM 适配、状态管理、agent 调度、长期记忆、审计规则、导出逻辑都在 core 里。

从技术栈看,core 使用 TypeScript ESM、Zod、@mariozechner/pi-ai@mariozechner/pi-agent-core。Zod 被大量用于模型约束和 LLM 输出校验;pi-ai 承担模型协议适配;pi-agent-core 用于新的可恢复 agent session。

一张知识图谱

下面是我对 InkOS 的核心知识图谱理解:

                              +----------------------+
                              |      User / Author   |
                              +----------+-----------+
                                         |
                +------------------------+------------------------+
                |                                                 |
        +-------v-------+                                 +-------v-------+
        |      CLI      |                                 |    Studio     |
        | commander/TUI |                                 | Hono + React  |
        +-------+-------+                                 +-------+-------+
                |                                                 |
                +------------------------+------------------------+
                                         |
                              +----------v-----------+
                              |      inkos-core      |
                              | public API facade    |
                              +----------+-----------+
                                         |
         +-------------------------------+--------------------------------+
         |                               |                                |
 +-------v--------+              +-------v--------+               +-------v-------+
 | LLM Provider   |              | PipelineRunner |               | Interaction   |
 | pi-ai/custom   |              | orchestration  |               | NL router     |
 +-------+--------+              +-------+--------+               +-------+-------+
         |                               |                                |
         |                               |
         |        +----------------------+----------------------+
         |        |                      |                      |
 +-------v--------v--+          +--------v---------+    +--------v---------+
 | Planner / Composer|          | Writer / Settler |    | Auditor/Reviser |
 | intent/context    |          | chapter + delta  |    | quality loop    |
 +---------+---------+          +--------+---------+    +--------+---------+
           |                             |                       |
           +-----------------------------+-----------------------+
                                         |
                              +----------v-----------+
                              |     State System     |
                              +----------+-----------+
                                         |
          +------------------------------+------------------------------+
          |                              |                              |
 +--------v---------+           +--------v---------+           +--------v---------+
 | Markdown truth   |           | story/state json |           | SQLite memory   |
 | human readable   |           | Zod validated    |           | disposable idx  |
 +------------------+           +------------------+           +------------------+

这个图里最重要的点是:InkOS 不是以 LLM 的上下文窗口为唯一记忆,而是有本地、可审计、可回滚、可迁移的叙事状态系统。

核心链路:从“写下一章”到“可审阅章节”

InkOS 的主生产链路集中在 PipelineRunner。这个类很大,接近一个小型内核调度器。一次 write next 大致会走下面的阶段:

writeNextChapter(bookId)
  |
  |-- acquireBookLock(bookId)
  |-- resolve next chapter number
  |-- PlannerAgent.planChapter()
  |     |-- read author_intent/current_focus/story state
  |     |-- retrieve relevant memory
  |     `-- emit chapter intent + memo
  |
  |-- composeGovernedChapter()
  |     |-- selected context package
  |     |-- rule-stack.yaml
  |     `-- trace.json
  |
  |-- WriterAgent.writeChapter()
  |     |-- creative writing
  |     |-- state settlement
  |     |-- runtime state delta
  |     `-- post-write validation
  |
  |-- length normalization
  |-- merged audit
  |     |-- LLM continuity audit
  |     |-- AI-tell detection
  |     |-- sensitive words
  |     `-- long-span fatigue
  |
  |-- revise if needed
  |-- persist chapter artifacts
  |-- validate truth persistence
  |-- snapshot state
  `-- sync memory index

这个设计的关键在于:写手不是直接面对全量 truth files,而是先由 Planner 和 Composer 编译出本章所需的输入包。也就是说,InkOS 把 prompt engineering 提升成了一个“输入治理”问题。

三层状态系统

我认为 InkOS 最值得研究的是它的状态设计。

第一层是 Markdown truth files。它们是人类可读的权威材料,例如:

  • current_state.md
  • particle_ledger.md
  • pending_hooks.md
  • chapter_summaries.md
  • subplot_board.md
  • emotional_arcs.md
  • character_matrix.md

这些文件承载世界状态、角色关系、物资账本、伏笔、章节摘要、情感弧线和角色信息边界。对于长篇小说来说,这些恰好是 LLM 最容易忘、最容易编错、最需要外部化的内容。

第二层是 story/state/*.json。这是结构化投影层,使用 Zod schema 校验。LLM 不再可靠地输出整份 Markdown,而是输出 runtime delta,再由代码层做 immutable apply 和 schema validation。这样可以避免“LLM 一次性重写整份状态文件时污染历史事实”的问题。

第三层是 story/memory.db。这是 SQLite 加速索引,用于按相关性检索 facts、hooks、chapter summaries。重要的是,它只是索引,不是权威来源。Node 运行时没有 node:sqlite 时,系统可以退回 Markdown / JSON 路径。这是一个很实用的工程选择。

Planner / Composer:把意图编译成运行时输入

Planner 负责回答“这一章到底要干什么”。它读取:

  • 长期作者意图 author_intent.md
  • 当前焦点 current_focus.md
  • 卷纲 / 世界观 / 规则
  • 最近章节摘要
  • 可回收伏笔和相关记忆

然后生成 chapter intent 和更详细的 chapter memo。Memo 有严格 parser,解析失败会把错误反馈给 LLM 重试。这体现了一个很好的零信任原则:LLM 输出不是天然可信的,需要格式校验、重试和失败显式化。

Composer 则负责把 Planner 的结果编译成:

  • chapter-XXXX.context.json
  • chapter-XXXX.rule-stack.yaml
  • chapter-XXXX.trace.json

这三类运行时产物非常重要。它们让“这章到底带了哪些上下文、哪些规则优先、为什么选择这些材料”变得可追踪。对于长流程 agent 来说,这类 trace 是排查问题的基础设施。

Writer / Settler:正文和状态分离

WriterAgent 实际做两件事:

  1. 创作正文。
  2. 根据正文结算状态。

这两个阶段温度和 prompt 都不同。创作阶段允许更高自由度;结算阶段则要低温、稳定、结构化。写完之后还会做零 LLM 成本的规则校验,例如段落形态、跨章重复、AI 味表达、敏感词等。

这个拆分很合理。正文生成是开放任务,状态结算是账务任务。如果把两者混在一个输出里,会导致正文质量、结构化准确性和可恢复性互相拖累。

审计循环

InkOS 的审计不是单一 LLM 判断,而是合并多种信号:

  • 连续性审计
  • AI 痕迹分析
  • 敏感词检测
  • 长跨度疲劳检测
  • 章节标题 / 开头 / 结尾模式重复

当审计失败时,系统可以进入修订流程。Reviser 支持 spot-fixpolishrewritereworkanti-detect 等模式。这里比较成熟的一点是,它不是每次都鼓励大改,而是有“局部修复”的概念。对于已经写出的长篇内容,最小必要修改通常比重写更安全。

上层:CLI、Studio、TUI 和 Agent Session

CLI 是 commander 命令集合,包含建书、写作、审计、修订、导入、导出、雷达、配置、doctor 等命令。默认运行 inkos 会启动 Studio。

Studio 是 Hono API + React/Vite 工作台。它把 core 的能力暴露为 Web API,并提供 SSE 进度事件。它不只是 UI,而是对同一套 pipeline 的可视化控制面。

core 里同时存在两套 agent 入口:

  • 旧式 pipeline/agent.ts:手写 tool loop。
  • 新式 agent/agent-session.ts:基于 pi-agent-core,支持 transcript restore、tool message 持久化、session cache。

这说明项目正在从“命令式工具调用”向“可恢复对话式 agent runtime”演进。

工程优点

我认为 InkOS 做得好的地方主要有五点。

第一,它把长篇写作当成状态机,而不是聊天记录。对小说这类长周期内容来说,这是正确方向。

第二,它对 LLM 输出采取零信任策略。Planner memo、runtime delta、hook record、project config 都有 schema 或 parser 保护。

第三,它保留人类可读层。Markdown truth files 让作者可以直接理解、修改和审阅系统记忆。

第四,它有快照和回滚。长篇写作不可避免会出现坏章,能回滚状态比单纯重写文本更重要。

第五,它把模型兼容放在 provider 层统一处理。OpenAI-compatible、Anthropic、Responses API、streaming、temperature clamp、partial response salvage 都集中在一处,避免 agent 逻辑里到处散落 provider 特判。

工程风险

InkOS 也有明显的复杂度风险。

最大的问题是 PipelineRunner 太大。它同时承担建书、章节生产、导入、风格、同人、状态同步、审计修订、记忆索引等职责。这个类已经接近“上帝对象”。短期内这能快速迭代,长期会增加修改成本。

第二个问题是多入口漂移。CLI 原子命令、旧 agent loop、新 agent session、Studio API 都能触发相似动作。只要其中一个入口少做了某个 guard,就可能出现行为不一致。项目目前靠大量测试兜底,但架构上仍然值得收敛。

第三个问题是兼容层很多。新旧 layout、Markdown 和 JSON 双写、SQLite 可选、不同模型协议、Studio 与 CLI 配置隔离,这些都很实用,但每一层都会带来边界条件。

第四个问题是 Node 运行时能力差异。memory.db 使用 node:sqlite,而 package engine 写的是 node >=20。代码已经做了降级,但用户对“为什么这台机器没有 SQLite 加速”的理解成本仍然存在。

我对它的定位

InkOS 不是简单的“AI 小说生成器”。更准确地说,它是一个面向长篇叙事的本地 agentic production system。它把作者意图、规则、状态、记忆、审计和模型调用都纳入一个可控流程。

如果用软件工程术语类比:

  • author_intent.mdcurrent_focus.md 像产品需求。
  • chapter intent/context/rule-stack/trace 像编译产物。
  • WriterAgent 像生成器。
  • Settler 像事务结算器。
  • StateManager 像文件系统和事务日志。
  • Auditor/Reviser 像 CI 和自动修复。
  • Studio 像控制台。

这个项目最值得借鉴的不是“怎么写小说”,而是它如何把一个本来非常模糊的 LLM 创作任务,拆成可验证、可恢复、可审计的工程流水线。

如果继续演进

如果我来继续打磨这个项目,我会优先做三件事:

  1. 拆分 PipelineRunner,至少拆成 foundation service、chapter pipeline、import service、audit service、memory sync service。
  2. 收敛多入口工具调用,把 CLI、Studio、agent session 都压到同一组 deterministic core tools 上。
  3. 明确 runtime capability report,让用户知道当前 Node 是否支持 SQLite memory index、当前模型是否支持 tool call、streaming、system role、Responses API。

InkOS 的方向是对的:长任务 agent 不能只靠 prompt,必须有状态、约束、审计和恢复机制。小说只是一个载体,背后的工程模式可以迁移到很多复杂内容生产场景。