@qihuang02/world-book-mcp 0.0.4-beta.5 → 0.0.5
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/README.md +21 -25
- package/README_ZH.md +21 -25
- package/dist/core/delivery-checklist.js +2 -2
- package/dist/core/delivery-checklist.js.map +1 -1
- package/dist/core/worldbook-draft-editor.d.ts +24 -0
- package/dist/core/worldbook-draft-editor.js +221 -0
- package/dist/core/worldbook-draft-editor.js.map +1 -0
- package/dist/core/worldbook-entry-factory.d.ts +2 -2
- package/dist/core/worldbook-entry-factory.js +3 -3
- package/dist/core/worldbook-entry-factory.js.map +1 -1
- package/dist/core/worldbook-patch.js +3 -3
- package/dist/core/worldbook-patch.js.map +1 -1
- package/dist/core/worldbook-planning.d.ts +10 -1
- package/dist/core/worldbook-planning.js.map +1 -1
- package/dist/prompts/register.js +2 -2
- package/dist/prompts/register.js.map +1 -1
- package/dist/resources/usage-resources.js +3 -3
- package/dist/resources/usage-resources.js.map +1 -1
- package/dist/schemas/character-card.d.ts +1 -1
- package/dist/schemas/derivative-outline.d.ts +4 -4
- package/dist/schemas/extraction.d.ts +12 -12
- package/dist/schemas/project.d.ts +2 -65
- package/dist/schemas/project.js +1 -6
- package/dist/schemas/project.js.map +1 -1
- package/dist/schemas/worldbook-draft.d.ts +114 -42
- package/dist/schemas/worldbook-draft.js +62 -14
- package/dist/schemas/worldbook-draft.js.map +1 -1
- package/dist/schemas/worldbook-patch.d.ts +1 -1
- package/dist/storage/project-store.d.ts +0 -1
- package/dist/storage/project-store.js +0 -26
- package/dist/storage/project-store.js.map +1 -1
- package/dist/storage/workspace-store.js +0 -2
- package/dist/storage/workspace-store.js.map +1 -1
- package/dist/tools/character-card-tools.js +72 -5
- package/dist/tools/character-card-tools.js.map +1 -1
- package/dist/tools/extraction-tools.js +0 -9
- package/dist/tools/extraction-tools.js.map +1 -1
- package/dist/tools/project-tools.js +1 -26
- package/dist/tools/project-tools.js.map +1 -1
- package/dist/tools/register.js +0 -2
- package/dist/tools/register.js.map +1 -1
- package/dist/tools/worldbook-tools.js +149 -23
- package/dist/tools/worldbook-tools.js.map +1 -1
- package/package.json +1 -1
- package/dist/core/config-explainer.d.ts +0 -2
- package/dist/core/config-explainer.js +0 -44
- package/dist/core/config-explainer.js.map +0 -1
- package/dist/core/entry-planner.d.ts +0 -8
- package/dist/core/entry-planner.js +0 -79
- package/dist/core/entry-planner.js.map +0 -1
- package/dist/core/entry-templates.d.ts +0 -7
- package/dist/core/entry-templates.js +0 -66
- package/dist/core/entry-templates.js.map +0 -1
- package/dist/schemas/research.d.ts +0 -56
- package/dist/schemas/research.js +0 -21
- package/dist/schemas/research.js.map +0 -1
- package/dist/schemas/source.d.ts +0 -40
- package/dist/schemas/source.js +0 -20
- package/dist/schemas/source.js.map +0 -1
- package/dist/tools/reference-tools.d.ts +0 -2
- package/dist/tools/reference-tools.js +0 -10
- package/dist/tools/reference-tools.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# world-book-mcp
|
|
2
2
|
|
|
3
|
-
`world-book-mcp` is an MCP server built with Node.js and TypeScript. It
|
|
3
|
+
`world-book-mcp` is an MCP server built with Node.js and TypeScript. It manages a `.worldbook/` drafting workspace and helps AI validate, patch, and export SillyTavern-compatible World Book JSON, basic `chara_card_v3` character card JSON, and optional MVU/ZOD, HTML beautification, and EJS dynamic content assets. Source reading, web search, and fact extraction are handled by the host AI in conversation; this server stores structured project state, draft entries, configurations, and exported JSON.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -48,25 +48,20 @@ args = ["-y", "@qihuang02/world-book-mcp"]
|
|
|
48
48
|
|
|
49
49
|
The current version supports:
|
|
50
50
|
|
|
51
|
-
-
|
|
52
|
-
- Ingesting web-search summaries.
|
|
51
|
+
- Explicitly initializing a project, suitable for first-time use in an empty directory.
|
|
53
52
|
- Creating information extraction outlines.
|
|
54
|
-
- Submitting structured extraction results.
|
|
55
|
-
-
|
|
56
|
-
- Returning World Book entry templates.
|
|
57
|
-
- Querying the usage guide for a single tool.
|
|
58
|
-
- Explaining SillyTavern World Book configuration fields.
|
|
53
|
+
- Submitting structured extraction results prepared by the host AI.
|
|
54
|
+
- Creating explicit World Book entry plans from caller-provided card type, characters, world sections, items, scenes, and events.
|
|
59
55
|
- Scanning forbidden terms and common writing issues.
|
|
60
|
-
-
|
|
61
|
-
- Saving, updating, and validating World Book drafts through simplified input: AI only needs to submit core fields such as `comment`, `keys`, and `content`; MCP automatically completes the full structure.
|
|
56
|
+
- Creating `.worldbook/draft/*.json` slice templates first, then updating them field by field, confirming completeness, and merging them into exported JSON.
|
|
62
57
|
- Exporting standalone SillyTavern World Book JSON.
|
|
63
|
-
- Importing existing World Book JSON
|
|
58
|
+
- Importing existing World Book JSON by slicing it into `.worldbook/draft/*.json`, then applying safe patches / merged exports.
|
|
64
59
|
- Generating basic character card JSON that can embed the project World Book draft; when exporting a character card, the basic settings and personality settings of the same character are merged into the same embedded World Book entry.
|
|
65
60
|
- MVU/ZOD configuration templates, validation, and asset building, with automatic merging into character card JSON.
|
|
66
61
|
- HTML beautification configuration templates, validation, and asset building, with automatic merging into character card JSON.
|
|
67
62
|
- EJS dynamic content configuration templates, validation, and entry building, with automatic merging into the embedded World Book of a character card.
|
|
68
63
|
- Querying exported World Book JSON and character card JSON.
|
|
69
|
-
- Importing existing character card JSON and applying patches to profile fields or embedded World Book entries.
|
|
64
|
+
- Importing existing character card JSON, slicing the embedded World Book into draft entries, and applying patches to profile fields or embedded World Book entries.
|
|
70
65
|
|
|
71
66
|
Not supported yet:
|
|
72
67
|
- Built-in web search.
|
|
@@ -86,7 +81,7 @@ The primary role of `init_project` is to create or reuse the single MCP workspac
|
|
|
86
81
|
└─ <exported world book or character card>.json
|
|
87
82
|
```
|
|
88
83
|
|
|
89
|
-
`
|
|
84
|
+
`create_worldbook_draft_entry` / `create_worldbook_draft_entries` first create slice templates at `.worldbook/draft/<safe-comment>.json`; then `update_worldbook_draft_field` / `update_worldbook_draft_fields` fill them field by field. Split files store MCP draft entries, not final SillyTavern entries:
|
|
90
85
|
|
|
91
86
|
```json
|
|
92
87
|
{
|
|
@@ -104,7 +99,7 @@ The primary role of `init_project` is to create or reuse the single MCP workspac
|
|
|
104
99
|
}
|
|
105
100
|
```
|
|
106
101
|
|
|
107
|
-
Validation, review, lint, World Book export, and character card export
|
|
102
|
+
Validation, review, lint, World Book export, and character card export merge `.worldbook/draft/*.json`; split draft files are the draft source of truth. `.worldbook/draft/` is the long-lived workspace: `generate_worldbook_json` / `generate_character_card_json` do not clear drafts after export, and `apply_worldbook_patch` / `apply_character_card_patch` retain the updated split draft entries after merging into exported JSON. By default, exports are written to `<name>.json` in the current working directory. Relative and absolute output paths must stay inside the current working directory; out-of-bound writes are rejected.
|
|
108
103
|
|
|
109
104
|
`init_project` also scans one level of `*.json` files in the current working directory. If no SillyTavern World Book or `chara_card_v3` JSON exists, it safely creates a root template JSON. If a Tavern-format JSON already exists, it does not create another template and never overwrites existing JSON files. The returned `root_template` field reports whether a template was created, its path, or the existing files that caused creation to be skipped. `kind=worldbook` creates a standalone World Book template; `kind=character_card` and `kind=mixed` create a `chara_card_v3` template, with `mixed` explicitly meaning a character card plus an empty embedded World Book.
|
|
110
105
|
|
|
@@ -112,29 +107,29 @@ Validation, review, lint, World Book export, and character card export preferent
|
|
|
112
107
|
|
|
113
108
|
Writes for the same `project_id` are serialized inside the MCP process and return an incremented `revision`. Tools that accept `expected_revision` can use it for concurrency control: if a caller writes based on a stale revision, the tool returns a `project revision conflict` error.
|
|
114
109
|
|
|
115
|
-
`apply_worldbook_patch` / `apply_character_card_patch` write the exported JSON file and update project state together. The implementation writes a temp file, replaces the target file, then updates the project; if the project update fails, it best-effort restores the previous exported file or removes the newly written target. When a patch returns `ok=false` or throws a revision conflict, reload the project before retrying.
|
|
110
|
+
`apply_worldbook_patch` / `apply_character_card_patch` use the current project draft as input, write the exported JSON file, and update project state together; on success, the updated `.worldbook/draft/*.json` files are retained. The implementation writes a temp file, replaces the target file, then updates the project; if the project update fails, it best-effort restores the previous exported file or removes the newly written target. When a patch returns `ok=false` or throws a revision conflict, reload the project before retrying.
|
|
116
111
|
|
|
117
|
-
Patch `match.uid` first matches the `sourceUid` preserved from an imported World Book, so it targets the original SillyTavern entry uid. For newly created drafts
|
|
112
|
+
Patch `match.uid` first matches the `sourceUid` preserved from an imported World Book, so it targets the original SillyTavern entry uid. For newly created drafts without `sourceUid`, prefer `index` or a unique `comment` to avoid confusing uid with the regenerated contiguous export index.
|
|
118
113
|
|
|
119
114
|
## Tools Overview
|
|
120
115
|
|
|
121
|
-
Task routing, workflow choice, and clarification strategy are handled by the bundled `skill/world-book-mcp/` documentation rather than MCP tools.
|
|
116
|
+
Task routing, workflow choice, and clarification strategy are handled by the bundled `skill/world-book-mcp-skill/` documentation rather than MCP tools.
|
|
122
117
|
|
|
123
118
|
| Category | Tool | Description |
|
|
124
119
|
| --- | --- | --- |
|
|
125
120
|
| Workflow, Projects, and Specs | `init_project` | Initializes `.worldbook/project.json` and `.worldbook/draft/`; safely creates a root template JSON when no Tavern-format JSON exists; existing projects can be reused or overwritten with `if_exists`. |
|
|
126
121
|
| Workflow, Projects, and Specs | `list_projects` | Returns the current `.worldbook/project.json` workspace project, or an empty list if no workspace exists. |
|
|
127
122
|
| Workflow, Projects, and Specs | `get_project` | Views project details or a summary. |
|
|
128
|
-
| Workflow, Projects, and Specs | `get_entry_template` | Returns a World Book entry template. |
|
|
129
|
-
| Workflow, Projects, and Specs | `explain_worldbook_config` | Explains configuration fields such as position, constant, order, keys, and recursion. |
|
|
130
123
|
| Workflow, Projects, and Specs | `lint_worldbook_content` | Scans forbidden terms and common writing issues. |
|
|
131
|
-
| Material Input | `ingest_text_source` | Ingests novel excerpts, settings, user notes, and other text. |
|
|
132
|
-
| Material Input | `ingest_web_research` | Ingests web-search summaries organized by AI. |
|
|
133
124
|
| Extraction | `create_extraction_outline` | Creates an extraction template for characters, worldbuilding, items, and events. |
|
|
134
125
|
| Extraction | `submit_extraction_result` | Submits structured facts extracted by the main AI. |
|
|
135
|
-
| World Book Building | `
|
|
136
|
-
| World Book Building | `
|
|
137
|
-
| World Book Building | `
|
|
126
|
+
| World Book Building | `create_worldbook_entry_plan` | Creates an explicit entry plan from caller-provided card type, characters, world sections, items, scenes, and events. |
|
|
127
|
+
| World Book Building | `validate_worldbook_entry_plan` | Validates an explicit entry plan's position, order, and keyword-trigger rules. |
|
|
128
|
+
| World Book Building | `create_worldbook_draft_entry` | Creates one `.worldbook/draft/*.json` slice template. |
|
|
129
|
+
| World Book Building | `create_worldbook_draft_entries` | Creates multiple slice templates. |
|
|
130
|
+
| World Book Building | `update_worldbook_draft_field` | Locates a draft by comment and updates one field. |
|
|
131
|
+
| World Book Building | `update_worldbook_draft_fields` | Updates a small set of draft fields at once. |
|
|
132
|
+
| World Book Building | `confirm_worldbook_draft_complete` | Confirms all drafts are complete and ready to merge/export. |
|
|
138
133
|
| World Book Building | `list_worldbook_draft_entries` | Lists `.worldbook/draft/*.json` split draft entries. |
|
|
139
134
|
| World Book Building | `get_worldbook_draft_entry` | Reads one split draft entry by comment. |
|
|
140
135
|
| World Book Building | `delete_worldbook_draft_entry` | Deletes one split draft entry by comment. |
|
|
@@ -143,6 +138,7 @@ Task routing, workflow choice, and clarification strategy are handled by the bun
|
|
|
143
138
|
| Character Card | `import_character_card_json` | Imports an existing `chara_card_v3` JSON in the current directory and extracts profile plus embedded World Book draft. |
|
|
144
139
|
| Character Card | `upsert_character_profile` | Creates or updates character card profile configuration through simplified fields; MCP automatically fills default `chara_card_v3` fields. |
|
|
145
140
|
| Character Card | `validate_character_card_config` | Validates character card configuration and the embedded World Book. |
|
|
141
|
+
| Character Card | `confirm_character_card_draft_complete` | Confirms character-card profile, embedded World Book drafts, and assets are ready to merge/export. |
|
|
146
142
|
| Character Card | `generate_character_card_json` | Exports `chara_card_v3` character card JSON; `character_basic` and `character_personality` for the same character are merged into the same embedded World Book entry. |
|
|
147
143
|
| Character Card | `create_character_card_patch` | Creates a patch plan for profile, worldbook config, or embedded World Book entries. |
|
|
148
144
|
| Character Card | `preview_character_card_patch` | Previews character card patch diffs and validation. |
|
|
@@ -172,7 +168,7 @@ Task routing, workflow choice, and clarification strategy are handled by the bun
|
|
|
172
168
|
|
|
173
169
|
## Skill
|
|
174
170
|
|
|
175
|
-
This repository includes a standard Claude Code Skill at [`skill/world-book-mcp/`](skill/world-book-mcp/). It is a directory package containing `SKILL.md` and `references/`, used to guide AI in correctly orchestrating all tools of this MCP server when users request World Book or character card related tasks.
|
|
171
|
+
This repository includes a standard Claude Code Skill named `world-book-mcp-skill` at [`skill/world-book-mcp-skill/`](skill/world-book-mcp-skill/). It is a directory package containing `SKILL.md` and `references/`, used to guide AI in correctly orchestrating all tools of this MCP server when users request World Book or character card related tasks. The skill name is intentionally distinct from the MCP server name `world-book-mcp` to avoid confusion in agent tooling.
|
|
176
172
|
|
|
177
173
|
## Future Capability Extensions
|
|
178
174
|
|
package/README_ZH.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# world-book-mcp
|
|
2
2
|
|
|
3
|
-
`world-book-mcp` 是一个使用 Node.js + TypeScript 编写的 MCP
|
|
3
|
+
`world-book-mcp` 是一个使用 Node.js + TypeScript 编写的 MCP 服务器,用于管理 `.worldbook/` 草稿工作区,并辅助 AI 校验、patch 和导出符合 SillyTavern 格式的世界书 JSON、基础 `chara_card_v3` 角色卡 JSON,以及可选 MVU/ZOD、HTML 美化和 EJS 动态内容资产。原文阅读、网页搜索和事实提取由宿主 AI 在对话中完成;本服务器只保存结构化 project 状态、draft 条目、配置和导出 JSON。
|
|
4
4
|
|
|
5
5
|
## 安装
|
|
6
6
|
|
|
@@ -48,25 +48,20 @@ args = ["-y", "@qihuang02/world-book-mcp"]
|
|
|
48
48
|
|
|
49
49
|
当前版本支持:
|
|
50
50
|
|
|
51
|
-
-
|
|
52
|
-
- 接收网页搜索摘要。
|
|
51
|
+
- 显式初始化 project,适合空白目录首次使用。
|
|
53
52
|
- 创建信息提取 outline。
|
|
54
|
-
-
|
|
55
|
-
-
|
|
56
|
-
- 返回世界书条目模板。
|
|
57
|
-
- 查询单个 tool 的使用指南。
|
|
58
|
-
- 解释 SillyTavern 世界书配置字段。
|
|
53
|
+
- 提交由宿主 AI 整理好的结构化提取结果。
|
|
54
|
+
- 根据调用方显式提供的卡型、角色、世界分区、物品、场景和事件创建世界书条目规划。
|
|
59
55
|
- 扫描禁词与常见写作问题。
|
|
60
|
-
-
|
|
61
|
-
- 通过简化输入保存、更新、校验世界书草稿:AI 只需提交 `comment`、`keys`、`content` 等核心字段,MCP 自动补全完整结构。
|
|
56
|
+
- 先创建 `.worldbook/draft/*.json` 切片模板,再逐字段更新、确认完整并合并导出,避免 AI 一次提交完整条目对象。
|
|
62
57
|
- 导出独立 SillyTavern 世界书 JSON。
|
|
63
|
-
- 导入已有世界书 JSON
|
|
58
|
+
- 导入已有世界书 JSON,先切片为 `.worldbook/draft/*.json`,再进行安全 patch / 合并导出。
|
|
64
59
|
- 基础角色卡 JSON 生成,可嵌入项目世界书 draft;导出角色卡时同一角色的基础设定和性格设定会聚合为同一个内嵌世界书条目。
|
|
65
60
|
- MVU/ZOD 配置模板、校验、资产构建,并可自动合并进角色卡 JSON。
|
|
66
61
|
- HTML 美化配置模板、校验、资产构建,并可自动合并进角色卡 JSON。
|
|
67
62
|
- EJS 动态内容配置模板、校验、entries 构建,并可自动合并进角色卡内嵌世界书。
|
|
68
63
|
- 查询导出的世界书 JSON 和角色卡 JSON。
|
|
69
|
-
- 导入已有角色卡 JSON,并通过 patch 修改角色卡字段或内嵌世界书条目。
|
|
64
|
+
- 导入已有角色卡 JSON,将内嵌世界书切片为 draft,并通过 patch 修改角色卡字段或内嵌世界书条目。
|
|
70
65
|
|
|
71
66
|
暂不支持:
|
|
72
67
|
- 内置网页搜索。
|
|
@@ -86,7 +81,7 @@ args = ["-y", "@qihuang02/world-book-mcp"]
|
|
|
86
81
|
└─ <导出的世界书或角色卡>.json
|
|
87
82
|
```
|
|
88
83
|
|
|
89
|
-
`
|
|
84
|
+
`create_worldbook_draft_entry` / `create_worldbook_draft_entries` 会先把每个切片模板写为 `.worldbook/draft/<safe-comment>.json`;随后使用 `update_worldbook_draft_field` / `update_worldbook_draft_fields` 逐字段填充。分片文件保存的是 MCP draft entry,而不是最终 SillyTavern entry:
|
|
90
85
|
|
|
91
86
|
```json
|
|
92
87
|
{
|
|
@@ -104,7 +99,7 @@ args = ["-y", "@qihuang02/world-book-mcp"]
|
|
|
104
99
|
}
|
|
105
100
|
```
|
|
106
101
|
|
|
107
|
-
校验、审查、lint
|
|
102
|
+
校验、审查、lint、世界书导出和角色卡导出会合并读取 `.worldbook/draft/*.json`;分片 draft 文件是草稿的唯一事实来源。`.worldbook/draft/` 是长期工作区:`generate_worldbook_json` / `generate_character_card_json` 导出后不会清空草稿,`apply_worldbook_patch` / `apply_character_card_patch` 合并导出后也会保留更新后的分片草稿,供下次继续修改。默认导出路径是当前工作目录的 `<名称>.json`,相对路径和绝对路径都必须位于当前工作目录内,越界写入会失败。
|
|
108
103
|
|
|
109
104
|
此外,`init_project` 会扫描当前工作目录根目录的一层 `*.json`:如果没有发现酒馆格式世界书或 `chara_card_v3` 角色卡 JSON,会自动创建一个根目录模板 JSON;如果已经存在酒馆格式 JSON,则不会额外创建模板,也不会覆盖已有 JSON。返回值中的 `root_template` 会说明模板是否创建、路径或已有文件列表。`kind=worldbook` 会创建独立世界书模板;`kind=character_card` 和 `kind=mixed` 会创建 `chara_card_v3` 模板,其中 `mixed` 明确表示角色卡 + 内嵌空世界书的一体化模板。
|
|
110
105
|
|
|
@@ -112,29 +107,29 @@ args = ["-y", "@qihuang02/world-book-mcp"]
|
|
|
112
107
|
|
|
113
108
|
同一 `project_id` 的写入会在 MCP 进程内串行化,并在返回值中递增 `revision`。支持 `expected_revision` 的写入工具可用它做并发冲突检测:如果调用方基于旧 revision 写入,会返回 `project revision conflict`。
|
|
114
109
|
|
|
115
|
-
`apply_worldbook_patch` / `apply_character_card_patch`
|
|
110
|
+
`apply_worldbook_patch` / `apply_character_card_patch` 会以当前 project draft 为输入,同时写导出的 JSON 文件并更新 project 状态;成功后保留更新后的 `.worldbook/draft/*.json`。实现会先写临时文件并替换目标文件,再更新 project;如果 project 更新失败,会尽力恢复旧导出文件或删除新写入文件。返回 `ok=false` 或抛出冲突错误时,调用方应重新读取 project 后再重试。
|
|
116
111
|
|
|
117
|
-
patch 的 `match.uid` 优先匹配从已导入世界书保留的 `sourceUid`,用于定位原始 SillyTavern 条目 uid
|
|
112
|
+
patch 的 `match.uid` 优先匹配从已导入世界书保留的 `sourceUid`,用于定位原始 SillyTavern 条目 uid。对没有 `sourceUid` 的新建草稿,建议使用 `index` 或唯一 `comment` 定位,避免把 uid 误当作导出后的连续下标。
|
|
118
113
|
|
|
119
114
|
## Tools 一览
|
|
120
115
|
|
|
121
|
-
任务分类、工作流选择和澄清策略由随包 `skill/world-book-mcp/` 文档指导,不再作为 MCP tools 暴露。
|
|
116
|
+
任务分类、工作流选择和澄清策略由随包 `skill/world-book-mcp-skill/` 文档指导,不再作为 MCP tools 暴露。
|
|
122
117
|
|
|
123
118
|
| 分类 | Tool | 说明 |
|
|
124
119
|
| --- | --- | --- |
|
|
125
|
-
| 工作流、项目与规范 | `get_entry_template` | 返回世界书条目模板。 |
|
|
126
120
|
| 工作流、项目与规范 | `init_project` | 初始化 `.worldbook/project.json` 与 `.worldbook/draft/`;若根目录没有酒馆格式 JSON,会安全创建模板 JSON;已有项目可用 `if_exists` 控制复用或覆盖。 |
|
|
127
121
|
| 工作流、项目与规范 | `list_projects` | 返回当前 `.worldbook/project.json` 工作区项目;未初始化时返回空列表。 |
|
|
128
122
|
| 工作流、项目与规范 | `get_project` | 查看项目详情或摘要。 |
|
|
129
|
-
| 工作流、项目与规范 | `explain_worldbook_config` | 解释 position、constant、order、keys、递归等配置。 |
|
|
130
123
|
| 工作流、项目与规范 | `lint_worldbook_content` | 扫描禁词和常见写作问题。 |
|
|
131
|
-
| 素材输入 | `ingest_text_source` | 接收小说片段、设定、用户笔记等文本。 |
|
|
132
|
-
| 素材输入 | `ingest_web_research` | 接收 AI 整理后的网页搜索摘要。 |
|
|
133
124
|
| 提取 | `create_extraction_outline` | 创建角色、世界观、物品、事件的提取模板。 |
|
|
134
125
|
| 提取 | `submit_extraction_result` | 提交主 AI 提取好的结构化事实。 |
|
|
135
|
-
| 世界书构建 | `
|
|
136
|
-
| 世界书构建 | `
|
|
137
|
-
| 世界书构建 | `
|
|
126
|
+
| 世界书构建 | `create_worldbook_entry_plan` | 根据调用方显式提供的卡型、角色、世界分区、物品、场景和事件创建条目规划。 |
|
|
127
|
+
| 世界书构建 | `validate_worldbook_entry_plan` | 校验显式条目规划的 position、order 和关键词触发规则。 |
|
|
128
|
+
| 世界书构建 | `create_worldbook_draft_entry` | 创建单个 `.worldbook/draft/*.json` 切片模板。 |
|
|
129
|
+
| 世界书构建 | `create_worldbook_draft_entries` | 批量创建切片模板。 |
|
|
130
|
+
| 世界书构建 | `update_worldbook_draft_field` | 按 comment 定位并逐字段更新 draft。 |
|
|
131
|
+
| 世界书构建 | `update_worldbook_draft_fields` | 一次更新少量 draft 字段。 |
|
|
132
|
+
| 世界书构建 | `confirm_worldbook_draft_complete` | 确认所有 draft 完整且可合并导出。 |
|
|
138
133
|
| 世界书构建 | `list_worldbook_draft_entries` | 列出 `.worldbook/draft/*.json` 分片草稿。 |
|
|
139
134
|
| 世界书构建 | `get_worldbook_draft_entry` | 按 comment 读取单个分片草稿。 |
|
|
140
135
|
| 世界书构建 | `delete_worldbook_draft_entry` | 按 comment 删除单个分片草稿。 |
|
|
@@ -143,6 +138,7 @@ patch 的 `match.uid` 优先匹配从已导入世界书保留的 `sourceUid`,
|
|
|
143
138
|
| 角色卡 | `import_character_card_json` | 导入当前目录内已有 `chara_card_v3` 角色卡 JSON,提取 profile 与内嵌世界书 draft。 |
|
|
144
139
|
| 角色卡 | `upsert_character_profile` | 用简化字段创建/更新角色卡人设配置,MCP 自动补齐 `chara_card_v3` 默认字段。 |
|
|
145
140
|
| 角色卡 | `validate_character_card_config` | 校验角色卡配置和嵌入世界书。 |
|
|
141
|
+
| 角色卡 | `confirm_character_card_draft_complete` | 确认角色卡 profile、内嵌世界书 draft 与资产可合并导出。 |
|
|
146
142
|
| 角色卡 | `generate_character_card_json` | 导出 `chara_card_v3` 角色卡 JSON;同一角色的 `character_basic` 与 `character_personality` 会合并为同一个内嵌世界书条目。 |
|
|
147
143
|
| 角色卡 | `create_character_card_patch` | 为已有角色卡 project 创建 profile / worldbook config / 内嵌世界书修改计划。 |
|
|
148
144
|
| 角色卡 | `preview_character_card_patch` | 预览角色卡 patch diff 与校验结果。 |
|
|
@@ -172,7 +168,7 @@ patch 的 `match.uid` 优先匹配从已导入世界书保留的 `sourceUid`,
|
|
|
172
168
|
|
|
173
169
|
## Skill
|
|
174
170
|
|
|
175
|
-
|
|
171
|
+
仓库自带一个名为 `world-book-mcp-skill` 的标准 Claude Code Skill,位于 [`skill/world-book-mcp-skill/`](skill/world-book-mcp-skill/)。它是一个 `SKILL.md` + `references/` 的目录包,用于指导 AI 在用户提出世界书 / 角色卡相关需求时,正确编排本 MCP 服务器的全部工具。skill 名称刻意区别于 MCP server 名称 `world-book-mcp`,避免在 Agent 工具中混淆。
|
|
176
172
|
|
|
177
173
|
## 未来能力扩展
|
|
178
174
|
|
|
@@ -11,10 +11,10 @@ export function createDeliveryChecklist(input) {
|
|
|
11
11
|
}
|
|
12
12
|
// 世界书 draft
|
|
13
13
|
if (!input.project.draft || input.project.draft.length === 0) {
|
|
14
|
-
items.push({ section: "worldbook_draft", status: input.export_target === "worldbook" ? "blocking" : "warning", message: "项目尚未保存世界书 draft", related_tools: ["
|
|
14
|
+
items.push({ section: "worldbook_draft", status: input.export_target === "worldbook" ? "blocking" : "warning", message: "项目尚未保存世界书 draft", related_tools: ["create_worldbook_draft_entry", "create_worldbook_draft_entries"] });
|
|
15
15
|
}
|
|
16
16
|
else {
|
|
17
|
-
items.push({ section: "worldbook_draft", status: review.sections.worldbook?.ok ? "ok" : "blocking", message: review.sections.worldbook?.ok ? "世界书 draft 校验通过" : "世界书 draft 存在阻塞性错误", related_tools: ["validate_worldbook_draft", "list_worldbook_draft_entries", "
|
|
17
|
+
items.push({ section: "worldbook_draft", status: review.sections.worldbook?.ok ? "ok" : "blocking", message: review.sections.worldbook?.ok ? "世界书 draft 校验通过" : "世界书 draft 存在阻塞性错误", related_tools: ["confirm_worldbook_draft_complete", "validate_worldbook_draft", "list_worldbook_draft_entries", "update_worldbook_draft_field"] });
|
|
18
18
|
}
|
|
19
19
|
// 角色卡
|
|
20
20
|
if (input.export_target === "character_card") {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"delivery-checklist.js","sourceRoot":"","sources":["../../src/core/delivery-checklist.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAA0B,MAAM,mBAAmB,CAAC;AAoBpF,MAAM,UAAU,uBAAuB,CAAC,KAA0E;IAChH,MAAM,MAAM,GAAG,uBAAuB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACtD,MAAM,KAAK,GAA4B,EAAE,CAAC;IAE1C,MAAM;IACN,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,oBAAoB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,iBAAiB,EAAE,CAAC;QAC5E,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,8BAA8B,EAAE,aAAa,EAAE,CAAC,8BAA8B,EAAE,sCAAsC,CAAC,EAAE,CAAC,CAAC;IAChM,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,EAAE,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,EAAE,aAAa,EAAE,CAAC,gCAAgC,EAAE,+BAA+B,CAAC,EAAE,CAAC,CAAC;IACnQ,CAAC;IAED,YAAY;IACZ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7D,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,EAAE,KAAK,CAAC,aAAa,KAAK,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,EAAE,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"delivery-checklist.js","sourceRoot":"","sources":["../../src/core/delivery-checklist.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type CreateWorldbookDraftTemplateInput, type WorldbookDraftEntry, type WorldbookDraftField } from "../schemas/worldbook-draft.js";
|
|
2
|
+
import { validateWorldbookDraft } from "./worldbook-validator.js";
|
|
3
|
+
export interface DraftCompletenessIssue {
|
|
4
|
+
comment?: string;
|
|
5
|
+
field: string;
|
|
6
|
+
message: string;
|
|
7
|
+
}
|
|
8
|
+
export interface DraftNextAction {
|
|
9
|
+
tool: "create_worldbook_draft_entry" | "update_worldbook_draft_field";
|
|
10
|
+
comment?: string;
|
|
11
|
+
field?: WorldbookDraftField;
|
|
12
|
+
}
|
|
13
|
+
export interface WorldbookDraftCompletenessResult {
|
|
14
|
+
ok: boolean;
|
|
15
|
+
ready_to_merge: boolean;
|
|
16
|
+
entry_count: number;
|
|
17
|
+
missing_fields: DraftCompletenessIssue[];
|
|
18
|
+
next_actions: DraftNextAction[];
|
|
19
|
+
validation: ReturnType<typeof validateWorldbookDraft>;
|
|
20
|
+
}
|
|
21
|
+
export declare function createWorldbookDraftTemplate(input: CreateWorldbookDraftTemplateInput): WorldbookDraftEntry;
|
|
22
|
+
export declare function updateWorldbookDraftField(entry: WorldbookDraftEntry, field: WorldbookDraftField, value: unknown): WorldbookDraftEntry;
|
|
23
|
+
export declare function updateWorldbookDraftFields(entry: WorldbookDraftEntry, changes: Partial<Record<WorldbookDraftField, unknown>>): WorldbookDraftEntry;
|
|
24
|
+
export declare function confirmWorldbookDraftComplete(entries: WorldbookDraftEntry[] | undefined): WorldbookDraftCompletenessResult;
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { EntryTypeSchema, PositionNameSchema } from "../schemas/worldbook-draft.js";
|
|
3
|
+
import { validateWorldbookDraft } from "./worldbook-validator.js";
|
|
4
|
+
const FieldValueSchemas = {
|
|
5
|
+
comment: z.string().min(1),
|
|
6
|
+
entry_type: EntryTypeSchema,
|
|
7
|
+
keys: z.array(z.string()),
|
|
8
|
+
secondary_keys: z.array(z.string()),
|
|
9
|
+
content: z.string(),
|
|
10
|
+
character_name: z.string().nullable(),
|
|
11
|
+
constant: z.boolean(),
|
|
12
|
+
position: PositionNameSchema,
|
|
13
|
+
order: z.number(),
|
|
14
|
+
enabled: z.boolean(),
|
|
15
|
+
depth: z.number().int().min(0).nullable(),
|
|
16
|
+
scan_depth: z.number().int().min(0).nullable(),
|
|
17
|
+
};
|
|
18
|
+
export function createWorldbookDraftTemplate(input) {
|
|
19
|
+
const comment = input.comment.trim();
|
|
20
|
+
const entryType = input.entryType ?? input.entry_type ?? "other";
|
|
21
|
+
const characterName = input.characterName ?? input.character_name;
|
|
22
|
+
const keySeed = characterName?.trim() || comment;
|
|
23
|
+
return {
|
|
24
|
+
comment,
|
|
25
|
+
entryType,
|
|
26
|
+
keys: uniqueStrings([keySeed]),
|
|
27
|
+
secondaryKeys: [],
|
|
28
|
+
content: "",
|
|
29
|
+
...(characterName?.trim() ? { characterName: characterName.trim() } : {}),
|
|
30
|
+
constant: input.constant ?? true,
|
|
31
|
+
position: input.position ?? "before_char",
|
|
32
|
+
order: input.order ?? defaultOrderForEntryType(entryType),
|
|
33
|
+
enabled: input.enabled ?? true,
|
|
34
|
+
preventRecursion: true,
|
|
35
|
+
excludeRecursion: true,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export function updateWorldbookDraftField(entry, field, value) {
|
|
39
|
+
const next = cloneEntry(entry);
|
|
40
|
+
switch (field) {
|
|
41
|
+
case "comment": {
|
|
42
|
+
next.comment = FieldValueSchemas.comment.parse(value).trim();
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
case "entry_type": {
|
|
46
|
+
next.entryType = FieldValueSchemas.entry_type.parse(value);
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
case "keys": {
|
|
50
|
+
next.keys = uniqueStrings(FieldValueSchemas.keys.parse(value));
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
case "secondary_keys": {
|
|
54
|
+
next.secondaryKeys = uniqueStrings(FieldValueSchemas.secondary_keys.parse(value));
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
case "content": {
|
|
58
|
+
next.content = FieldValueSchemas.content.parse(value);
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
case "character_name": {
|
|
62
|
+
const parsed = FieldValueSchemas.character_name.parse(value);
|
|
63
|
+
if (parsed === null || parsed.trim() === "")
|
|
64
|
+
delete next.characterName;
|
|
65
|
+
else
|
|
66
|
+
next.characterName = parsed.trim();
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
case "constant": {
|
|
70
|
+
next.constant = FieldValueSchemas.constant.parse(value);
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
case "position": {
|
|
74
|
+
next.position = FieldValueSchemas.position.parse(value);
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
case "order": {
|
|
78
|
+
next.order = FieldValueSchemas.order.parse(value);
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
case "enabled": {
|
|
82
|
+
next.enabled = FieldValueSchemas.enabled.parse(value);
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
case "depth": {
|
|
86
|
+
const parsed = FieldValueSchemas.depth.parse(value);
|
|
87
|
+
if (parsed === null)
|
|
88
|
+
delete next.depth;
|
|
89
|
+
else
|
|
90
|
+
next.depth = parsed;
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
case "scan_depth": {
|
|
94
|
+
const parsed = FieldValueSchemas.scan_depth.parse(value);
|
|
95
|
+
if (parsed === null)
|
|
96
|
+
delete next.scanDepth;
|
|
97
|
+
else
|
|
98
|
+
next.scanDepth = parsed;
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return next;
|
|
103
|
+
}
|
|
104
|
+
export function updateWorldbookDraftFields(entry, changes) {
|
|
105
|
+
let next = entry;
|
|
106
|
+
for (const field of Object.keys(changes)) {
|
|
107
|
+
next = updateWorldbookDraftField(next, field, changes[field]);
|
|
108
|
+
}
|
|
109
|
+
return next;
|
|
110
|
+
}
|
|
111
|
+
export function confirmWorldbookDraftComplete(entries) {
|
|
112
|
+
const draft = entries ?? [];
|
|
113
|
+
const missing = [];
|
|
114
|
+
const nextActions = [];
|
|
115
|
+
if (draft.length === 0) {
|
|
116
|
+
missing.push({ field: "draft", message: "尚未创建任何 .worldbook/draft/*.json 切片模板" });
|
|
117
|
+
nextActions.push({ tool: "create_worldbook_draft_entry" });
|
|
118
|
+
}
|
|
119
|
+
const seen = new Set();
|
|
120
|
+
for (const entry of draft) {
|
|
121
|
+
if (!entry.comment.trim()) {
|
|
122
|
+
missing.push({ comment: entry.comment, field: "comment", message: "comment 不能为空" });
|
|
123
|
+
nextActions.push({ tool: "update_worldbook_draft_field", comment: entry.comment, field: "comment" });
|
|
124
|
+
}
|
|
125
|
+
else if (seen.has(entry.comment)) {
|
|
126
|
+
missing.push({ comment: entry.comment, field: "comment", message: `comment 重复:${entry.comment}` });
|
|
127
|
+
}
|
|
128
|
+
seen.add(entry.comment);
|
|
129
|
+
if (!entry.content.trim()) {
|
|
130
|
+
missing.push({ comment: entry.comment, field: "content", message: "content 为空,不能合并导出" });
|
|
131
|
+
nextActions.push({ tool: "update_worldbook_draft_field", comment: entry.comment, field: "content" });
|
|
132
|
+
}
|
|
133
|
+
if (!entry.constant && entry.keys.length === 0) {
|
|
134
|
+
missing.push({ comment: entry.comment, field: "keys", message: "constant=false 的绿灯条目必须有 keys" });
|
|
135
|
+
nextActions.push({ tool: "update_worldbook_draft_field", comment: entry.comment, field: "keys" });
|
|
136
|
+
}
|
|
137
|
+
if ((entry.entryType === "character_basic" || entry.entryType === "character_personality") && !entry.characterName?.trim() && !inferCharacterNameFromComment(entry.comment)) {
|
|
138
|
+
missing.push({ comment: entry.comment, field: "character_name", message: "角色类条目建议填写 character_name,或使用“角色名-基础设定/性格”格式的 comment" });
|
|
139
|
+
nextActions.push({ tool: "update_worldbook_draft_field", comment: entry.comment, field: "character_name" });
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
const validation = validateWorldbookDraft(draft);
|
|
143
|
+
const missingKeys = new Set(missing.map(missingIssueKey));
|
|
144
|
+
for (const issue of [...validation.errors, ...validation.warnings].filter((issue) => issue.severity === "error")) {
|
|
145
|
+
const completenessIssue = { comment: issue.entry, field: issue.field ?? "validation", message: issue.message };
|
|
146
|
+
const key = missingIssueKey(completenessIssue);
|
|
147
|
+
if (missingKeys.has(key) || isCoveredByCompletenessChecks(completenessIssue))
|
|
148
|
+
continue;
|
|
149
|
+
missingKeys.add(key);
|
|
150
|
+
missing.push(completenessIssue);
|
|
151
|
+
}
|
|
152
|
+
const ready = missing.length === 0 && validation.valid;
|
|
153
|
+
return {
|
|
154
|
+
ok: ready,
|
|
155
|
+
ready_to_merge: ready,
|
|
156
|
+
entry_count: draft.length,
|
|
157
|
+
missing_fields: missing,
|
|
158
|
+
next_actions: dedupeNextActions(nextActions),
|
|
159
|
+
validation,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
function defaultOrderForEntryType(entryType) {
|
|
163
|
+
switch (entryType) {
|
|
164
|
+
case "world_summary":
|
|
165
|
+
return 1;
|
|
166
|
+
case "background":
|
|
167
|
+
return 10;
|
|
168
|
+
case "character_overview":
|
|
169
|
+
return 20;
|
|
170
|
+
case "character_basic":
|
|
171
|
+
return 30;
|
|
172
|
+
case "character_personality":
|
|
173
|
+
return 31;
|
|
174
|
+
case "faction":
|
|
175
|
+
return 40;
|
|
176
|
+
case "item":
|
|
177
|
+
case "ability":
|
|
178
|
+
return 50;
|
|
179
|
+
case "scene":
|
|
180
|
+
case "event":
|
|
181
|
+
return 60;
|
|
182
|
+
case "npc":
|
|
183
|
+
return 70;
|
|
184
|
+
case "other":
|
|
185
|
+
default:
|
|
186
|
+
return 100;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
function inferCharacterNameFromComment(comment) {
|
|
190
|
+
const match = comment.match(/^(.+?)[-_](基础设定|基础|性格设定|性格|人格)$/);
|
|
191
|
+
return match?.[1]?.trim() || undefined;
|
|
192
|
+
}
|
|
193
|
+
function cloneEntry(entry) {
|
|
194
|
+
return {
|
|
195
|
+
...entry,
|
|
196
|
+
keys: [...entry.keys],
|
|
197
|
+
secondaryKeys: [...entry.secondaryKeys],
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
function uniqueStrings(values) {
|
|
201
|
+
return Array.from(new Set(values.map((value) => value.trim()).filter(Boolean)));
|
|
202
|
+
}
|
|
203
|
+
function dedupeNextActions(actions) {
|
|
204
|
+
const seen = new Set();
|
|
205
|
+
return actions.filter((action) => {
|
|
206
|
+
const key = `${action.tool}:${action.comment ?? ""}:${action.field ?? ""}`;
|
|
207
|
+
if (seen.has(key))
|
|
208
|
+
return false;
|
|
209
|
+
seen.add(key);
|
|
210
|
+
return true;
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
function missingIssueKey(issue) {
|
|
214
|
+
return `${issue.comment ?? ""}:${issue.field}`;
|
|
215
|
+
}
|
|
216
|
+
function isCoveredByCompletenessChecks(issue) {
|
|
217
|
+
if (issue.field === "entries")
|
|
218
|
+
return true;
|
|
219
|
+
return ["comment", "content", "keys", "character_name"].includes(issue.field);
|
|
220
|
+
}
|
|
221
|
+
//# sourceMappingURL=worldbook-draft-editor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worldbook-draft-editor.js","sourceRoot":"","sources":["../../src/core/worldbook-draft-editor.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,11 +18,11 @@ export interface SimplifiedWorldbookEntryInput {
|
|
|
18
18
|
characterName?: string;
|
|
19
19
|
}
|
|
20
20
|
export declare function normalizeWorldbookEntry(input: SimplifiedWorldbookEntryInput, existing?: WorldbookDraftEntry): WorldbookDraftEntry;
|
|
21
|
-
export declare function
|
|
21
|
+
export declare function applyAddOrUpdateDraftEntry(entries: WorldbookDraftEntry[] | undefined, input: SimplifiedWorldbookEntryInput, options?: {
|
|
22
22
|
matchByKeys?: boolean;
|
|
23
23
|
}): {
|
|
24
24
|
entries: WorldbookDraftEntry[];
|
|
25
|
-
|
|
25
|
+
action: "created" | "updated";
|
|
26
26
|
index: number;
|
|
27
27
|
entry: WorldbookDraftEntry;
|
|
28
28
|
};
|
|
@@ -25,17 +25,17 @@ export function normalizeWorldbookEntry(input, existing) {
|
|
|
25
25
|
excludeRecursion: true,
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
|
-
export function
|
|
28
|
+
export function applyAddOrUpdateDraftEntry(entries, input, options = {}) {
|
|
29
29
|
const current = entries ? [...entries] : [];
|
|
30
30
|
const index = findEntryIndex(current, input, options);
|
|
31
31
|
if (index >= 0) {
|
|
32
32
|
const entry = normalizeWorldbookEntry(input, current[index]);
|
|
33
33
|
current[index] = entry;
|
|
34
|
-
return { entries: current,
|
|
34
|
+
return { entries: current, action: "updated", index, entry };
|
|
35
35
|
}
|
|
36
36
|
const entry = normalizeWorldbookEntry(input);
|
|
37
37
|
current.push(entry);
|
|
38
|
-
return { entries: current,
|
|
38
|
+
return { entries: current, action: "created", index: current.length - 1, entry };
|
|
39
39
|
}
|
|
40
40
|
function findEntryIndex(entries, input, options) {
|
|
41
41
|
const normalizedComment = input.comment.trim();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worldbook-entry-factory.js","sourceRoot":"","sources":["../../src/core/worldbook-entry-factory.ts"],"names":[],"mappings":"AAqBA,MAAM,UAAU,uBAAuB,CAAC,KAAoC,EAAE,QAA8B;IAC1G,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,UAAU,IAAI,QAAQ,EAAE,SAAS,IAAI,OAAO,CAAC;IACxF,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,QAAQ,EAAE,QAAQ,IAAI,IAAI,CAAC;IAC9D,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,QAAQ,EAAE,QAAQ,IAAI,aAAa,CAAC;IACvE,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,QAAQ,EAAE,KAAK,IAAI,wBAAwB,CAAC,SAAS,CAAC,CAAC;IACpF,MAAM,aAAa,GAAG,KAAK,CAAC,aAAa,IAAI,KAAK,CAAC,cAAc,IAAI,QAAQ,EAAE,aAAa,IAAI,EAAE,CAAC;IACnG,MAAM,cAAc,GAAG,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,UAAU,CAAC;IAC3D,MAAM,aAAa,GAAG,KAAK,CAAC,aAAa,IAAI,KAAK,CAAC,cAAc,IAAI,QAAQ,EAAE,aAAa,CAAC;IAE7F,OAAO;QACL,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE;QAC7B,SAAS;QACT,IAAI,EAAE,aAAa,CAAC,KAAK,CAAC,IAAI,IAAI,QAAQ,EAAE,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACpE,aAAa,EAAE,aAAa,CAAC,aAAa,CAAC;QAC3C,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjE,QAAQ;QACR,QAAQ;QACR,KAAK;QACL,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,QAAQ,EAAE,OAAO,IAAI,IAAI;QACnD,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,IAAI,QAAQ,EAAE,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChH,GAAG,CAAC,cAAc,KAAK,SAAS;YAC9B,CAAC,CAAC,cAAc,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,cAAc,EAAE;YAC9D,CAAC,CAAC,QAAQ,EAAE,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/E,gBAAgB,EAAE,IAAI;QACtB,gBAAgB,EAAE,IAAI;KACvB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"worldbook-entry-factory.js","sourceRoot":"","sources":["../../src/core/worldbook-entry-factory.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createId, nowIso } from "../utils/ids.js";
|
|
2
|
-
import {
|
|
2
|
+
import { applyAddOrUpdateDraftEntry, normalizeWorldbookEntry } from "./worldbook-entry-factory.js";
|
|
3
3
|
import { validateWorldbookDraft } from "./worldbook-validator.js";
|
|
4
4
|
export function createPatch(input) {
|
|
5
5
|
return {
|
|
@@ -22,8 +22,8 @@ export function applyPatchToDraft(entries, operations) {
|
|
|
22
22
|
break;
|
|
23
23
|
}
|
|
24
24
|
case "add_or_update_entry": {
|
|
25
|
-
const applied =
|
|
26
|
-
const before = applied.created ? undefined : cloneEntry(next[applied.index]);
|
|
25
|
+
const applied = applyAddOrUpdateDraftEntry(next, operation.entry, { matchByKeys: operation.match_by_keys });
|
|
26
|
+
const before = applied.action === "created" ? undefined : cloneEntry(next[applied.index]);
|
|
27
27
|
next.splice(0, next.length, ...applied.entries);
|
|
28
28
|
diff.push({ op: operation.op, target: targetLabel(applied.entry, applied.index), before, after: applied.entry });
|
|
29
29
|
break;
|