novelforge-agent 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +240 -0
  3. package/dist/src/cli/index.js +125 -0
  4. package/dist/src/core/contextBuilder.js +128 -0
  5. package/dist/src/core/fileNames.js +41 -0
  6. package/dist/src/core/index.js +9 -0
  7. package/dist/src/core/projectDiscovery.js +141 -0
  8. package/dist/src/core/projectStore.js +85 -0
  9. package/dist/src/core/prompts/en-US.js +363 -0
  10. package/dist/src/core/prompts/types.js +1 -0
  11. package/dist/src/core/prompts/zh-CN.js +362 -0
  12. package/dist/src/core/prompts.js +15 -0
  13. package/dist/src/core/retrieval/chunker.js +77 -0
  14. package/dist/src/core/retrieval/index.js +125 -0
  15. package/dist/src/core/retrieval/tokenizer.js +43 -0
  16. package/dist/src/core/retrieval/types.js +1 -0
  17. package/dist/src/core/schemas.js +91 -0
  18. package/dist/src/core/steps/architecture.js +16 -0
  19. package/dist/src/core/steps/chapter.js +16 -0
  20. package/dist/src/core/steps/chapterReview.js +16 -0
  21. package/dist/src/core/steps/chapterRevision.js +20 -0
  22. package/dist/src/core/steps/continuityReview.js +13 -0
  23. package/dist/src/core/steps/crossChapterReview.js +15 -0
  24. package/dist/src/core/steps/index.js +20 -0
  25. package/dist/src/core/steps/memoryCard.js +22 -0
  26. package/dist/src/core/steps/novelMetadata.js +12 -0
  27. package/dist/src/core/steps/storyBible.js +13 -0
  28. package/dist/src/core/steps/types.js +7 -0
  29. package/dist/src/core/types.js +1 -0
  30. package/dist/src/core/workflow.js +186 -0
  31. package/dist/src/mcp/server.js +13 -0
  32. package/dist/src/mcp/tools.js +126 -0
  33. package/package.json +61 -0
  34. package/src/cli/index.ts +147 -0
  35. package/src/core/contextBuilder.ts +131 -0
  36. package/src/core/fileNames.ts +48 -0
  37. package/src/core/index.ts +9 -0
  38. package/src/core/projectDiscovery.ts +174 -0
  39. package/src/core/projectStore.ts +111 -0
  40. package/src/core/prompts/en-US.ts +376 -0
  41. package/src/core/prompts/types.ts +28 -0
  42. package/src/core/prompts/zh-CN.ts +375 -0
  43. package/src/core/prompts.ts +27 -0
  44. package/src/core/retrieval/chunker.ts +80 -0
  45. package/src/core/retrieval/index.ts +136 -0
  46. package/src/core/retrieval/tokenizer.ts +44 -0
  47. package/src/core/retrieval/types.ts +24 -0
  48. package/src/core/schemas.ts +101 -0
  49. package/src/core/steps/architecture.ts +17 -0
  50. package/src/core/steps/chapter.ts +17 -0
  51. package/src/core/steps/chapterReview.ts +17 -0
  52. package/src/core/steps/chapterRevision.ts +21 -0
  53. package/src/core/steps/continuityReview.ts +14 -0
  54. package/src/core/steps/crossChapterReview.ts +16 -0
  55. package/src/core/steps/index.ts +25 -0
  56. package/src/core/steps/memoryCard.ts +23 -0
  57. package/src/core/steps/novelMetadata.ts +13 -0
  58. package/src/core/steps/storyBible.ts +14 -0
  59. package/src/core/steps/types.ts +21 -0
  60. package/src/core/types.ts +115 -0
  61. package/src/core/workflow.ts +250 -0
  62. package/src/mcp/server.ts +15 -0
  63. package/src/mcp/tools.ts +227 -0
@@ -0,0 +1,376 @@
1
+ import { BuiltPrompt, PromptBuildInput, PromptPack } from './types.js';
2
+
3
+ function strictJsonOutputRules(): string {
4
+ return [
5
+ 'JSON output rules:',
6
+ '- Output valid JSON only. Do not include Markdown, code fences, explanations, prefixes, or suffixes.',
7
+ '- Strings must use double quotes.',
8
+ '- Do not use undefined, NaN, Infinity, comments, or trailing commas.',
9
+ '- Array fields must be real arrays, not stringified arrays.',
10
+ ].join('\n');
11
+ }
12
+
13
+ function buildMetadataPrompt(input: PromptBuildInput): BuiltPrompt {
14
+ return {
15
+ purpose: 'novel_metadata',
16
+ expectedFormat: 'JSON matching NovelMetadataSchema',
17
+ prompt: `You are the lead planner for a long-form serialized novel. Generate the foundational metadata for a new novel from the user's premise.
18
+
19
+ ## User Prompt
20
+ ${input.state.initialPrompt}
21
+
22
+ ## Output Requirements
23
+ Output valid JSON only, in this shape:
24
+ {
25
+ "title": "Novel title",
26
+ "genre": "Genre",
27
+ "premise": "Story premise, 80-200 words",
28
+ "language": "en-US",
29
+ "style": "Style guidance",
30
+ "coreCast": [
31
+ {
32
+ "name": "Character name",
33
+ "role": "Character role",
34
+ "description": "Character description"
35
+ }
36
+ ]
37
+ }
38
+
39
+ Rules:
40
+ - title, genre, premise, language, and style must be non-empty strings.
41
+ - coreCast must include at least one central character.
42
+ - The premise must support a long-form serial, not just a one-line concept.
43
+ ${strictJsonOutputRules()}`,
44
+ };
45
+ }
46
+
47
+ function buildStoryBiblePrompt(input: PromptBuildInput): BuiltPrompt {
48
+ return {
49
+ purpose: 'story_bible',
50
+ expectedFormat: 'Markdown',
51
+ prompt: `You are a story bible editor. Create a reusable Markdown story bible for this long-form novel.
52
+
53
+ ## User Prompt
54
+ ${input.state.initialPrompt}
55
+
56
+ ${input.context ? `## Existing Context\n${input.context}\n` : ''}## Output Structure
57
+ Use Markdown and include at least:
58
+
59
+ ## Core Characters
60
+ - Goals, weaknesses, relationships, and long-term change direction for the main cast.
61
+
62
+ ## Relationships
63
+ - Core bonds, conflicts, hidden relationships, and future development points.
64
+
65
+ ## World Rules
66
+ - Hard genre rules, limits, costs, social structures, factions, or power systems.
67
+
68
+ ## Main Plot And Subplots
69
+ - Main objective.
70
+ - At least three long-running threads or subplots.
71
+
72
+ ## Style Constraints
73
+ - Narrative voice, pacing, forbidden patterns, and dialogue boundaries.
74
+
75
+ Rules:
76
+ - Make this useful for repeated reference during chapter generation.
77
+ - Do not write chapter prose.
78
+ - Do not output JSON.`,
79
+ };
80
+ }
81
+
82
+ function buildArchitecturePrompt(input: PromptBuildInput): BuiltPrompt {
83
+ return {
84
+ purpose: 'architecture',
85
+ expectedFormat: 'JSON matching ArchitecturePayloadSchema',
86
+ prompt: `You are the chief architect for a long-form novel. Generate full-book, volume, and chapter architecture.
87
+
88
+ ## User Prompt
89
+ ${input.state.initialPrompt}
90
+
91
+ ## Goals
92
+ - Generate at least ${input.state.targetChapters} chapter architectures for this first run.
93
+ - The full-book architecture should define the long-term main line and ending direction.
94
+ - Volume architecture should define phase conflict, climax, and volume-end hooks.
95
+ - Chapter architecture must cover only what should happen in that chapter and must not reveal later concrete events early.
96
+
97
+ ${input.context ? `## Existing Context\n${input.context}\n` : ''}## Output Requirements
98
+ Output valid JSON only, in this shape:
99
+ {
100
+ "full": "Complete full-book main line, phase progression, central conflict, theme, and ending direction",
101
+ "volumes": [
102
+ {
103
+ "id": "v1",
104
+ "title": "Volume title",
105
+ "summary": "Volume goal, conflict, climax, and end hook",
106
+ "order": 1
107
+ }
108
+ ],
109
+ "chapters": [
110
+ {
111
+ "chapterNumber": 1,
112
+ "title": "Chapter title",
113
+ "volumeId": "v1",
114
+ "summary": "Chapter plot summary",
115
+ "requiredBeats": ["Required beat 1", "Required beat 2"]
116
+ }
117
+ ]
118
+ }
119
+
120
+ Rules:
121
+ - chapters.length must be at least ${input.state.targetChapters}.
122
+ - chapterNumber must start at 1 and increase contiguously.
123
+ - volumeId must reference an id from volumes.
124
+ - requiredBeats must include at least one concrete, actionable beat.
125
+ ${strictJsonOutputRules()}`,
126
+ };
127
+ }
128
+
129
+ function buildChapterPrompt(input: PromptBuildInput): BuiltPrompt {
130
+ return {
131
+ purpose: 'chapter',
132
+ expectedFormat: 'Markdown',
133
+ prompt: `You are a professional long-form fiction writer. Write chapter ${input.state.currentChapter} directly.
134
+
135
+ ## Priority Order
136
+ 1. Strictly follow the current chapter architecture, user additions, story bible hard constraints, and previous-chapter continuity.
137
+ 2. Use relevant memory and prior text evidence to preserve consistency.
138
+ 3. Treat full-book and volume plans as distant planning context only. Do not write concrete future events early.
139
+
140
+ ## Style And Length
141
+ - Match the novel's genre, world, character identities, and emotional tone.
142
+ - Keep the language natural, stable, and readable. Prioritize narrative progress, character work, and emotional accumulation.
143
+ - Dialogue must fit each character's identity, relationship, and immediate situation.
144
+ - Important emotion should appear through action, body language, pacing, and subtext where possible.
145
+ - Scene description should provide useful sensory and atmospheric detail, but never stall the plot.
146
+ - Conflict, turns, suspense, and the chapter-end hook should be clear.
147
+
148
+ ## Execution Rules
149
+ - Write only what the current chapter architecture authorizes.
150
+ - Do not introduce unauthorized major characters. Functional background characters should stay light.
151
+ - Keep names, items, places, abilities, timeline, injuries, relationships, and knowledge boundaries consistent.
152
+ - If the previous chapter ends mid-action, mid-dialogue, or in the same scene, this chapter must continue from that point.
153
+ - Avoid cost-free power jumps, forced stupidity, mechanical twists, info-dumps, and empty lyricism.
154
+ - Do not output summaries, bullet points, lectures, or explanatory prefaces.
155
+
156
+ ${input.context ? `## Generation Context\n${input.context}\n` : ''}## Output Requirements
157
+ - Output Markdown.
158
+ - First line must be the chapter title as H1, for example: # Chapter Title
159
+ - After the H1, begin the prose directly.`,
160
+ };
161
+ }
162
+
163
+ function buildMemoryPrompt(input: PromptBuildInput): BuiltPrompt {
164
+ return {
165
+ purpose: 'memory_card',
166
+ expectedFormat: 'JSON matching MemoryCardSchema',
167
+ prompt: `You are a continuity editor for a long-form novel. Extract a memory card from chapter ${input.state.currentChapter}.
168
+
169
+ ${input.context ? `## Current Chapter Context\n${input.context}\n` : ''}## Output Requirements
170
+ Output valid JSON only, in this shape:
171
+ {
172
+ "summary": "Chapter summary",
173
+ "keyEvents": ["Key event 1"],
174
+ "entities": [
175
+ {
176
+ "name": "Character/place/item/faction name",
177
+ "type": "person | location | item | faction | concept",
178
+ "state": "State at the end of this chapter"
179
+ }
180
+ ],
181
+ "facts": [
182
+ {
183
+ "subject": "Subject",
184
+ "predicate": "Relation or action",
185
+ "object": "Object"
186
+ }
187
+ ],
188
+ "stateChanges": [
189
+ {
190
+ "entity": "Entity",
191
+ "before": "Before",
192
+ "after": "After"
193
+ }
194
+ ],
195
+ "openThreads": ["Unresolved promise, danger, question, or plot thread"]
196
+ }
197
+
198
+ Rules:
199
+ - Record only information that happened or was confirmed in this chapter.
200
+ - Do not speculate about future plot.
201
+ - Make facts and stateChanges concrete enough for later chapter reference.
202
+ ${strictJsonOutputRules()}`,
203
+ };
204
+ }
205
+
206
+ function buildContinuityReviewPrompt(input: PromptBuildInput): BuiltPrompt {
207
+ const end = Math.max(input.state.targetChapters, input.state.currentChapter - 1);
208
+ return {
209
+ purpose: 'continuity_review',
210
+ expectedFormat: 'JSON matching ContinuityReviewSchema',
211
+ prompt: `You are a continuity reviewer for a long-form novel. Review chapters 1-${end} for continuity issues.
212
+
213
+ ${input.context ? `## Review Context\n${input.context}\n` : ''}## Review Focus
214
+ - Character state, location, injuries, and relationships.
215
+ - Item ownership, ability limits, and world rules.
216
+ - Misread, forgotten, or prematurely revealed plot threads.
217
+ - Violations of chapter architecture requirements.
218
+
219
+ ## Output Requirements
220
+ Output valid JSON only, in this shape:
221
+ {
222
+ "range": {
223
+ "start": 1,
224
+ "end": ${end}
225
+ },
226
+ "status": "clean",
227
+ "issues": [
228
+ {
229
+ "severity": "low | medium | high",
230
+ "description": "Issue description",
231
+ "evidence": "Specific evidence from the context",
232
+ "suggestion": "Suggested fix"
233
+ }
234
+ ]
235
+ }
236
+
237
+ Rules:
238
+ - If there are no issues, use status "clean" and an empty issues array.
239
+ - If there are issues, use status "issues_found".
240
+ - evidence must be specific. Do not write vague claims like "possibly inconsistent".
241
+ ${strictJsonOutputRules()}`,
242
+ };
243
+ }
244
+
245
+ function buildChapterReviewPrompt(input: PromptBuildInput): BuiltPrompt {
246
+ const chapter = input.state.pendingAction?.chapterNumber ?? input.state.currentChapter;
247
+ return {
248
+ purpose: 'chapter_review',
249
+ expectedFormat: 'JSON matching ChapterReviewSchema',
250
+ prompt: `You are a strict editor reviewing a single chapter of a serial novel for in-chapter problems and conflicts with established context.
251
+
252
+ ${input.context ? `## Review Context\n${input.context}\n` : ''}## Review Focus
253
+ - Character voice, motivation, and state vs the story bible and prior memory.
254
+ - World rules, item ownership, and ability limits.
255
+ - Timeline, location, and continuity with the previous chapter ending.
256
+ - Whether the chapter fulfills the requiredBeats of its chapter architecture.
257
+ - Style: pacing, info-dump, forced twists, empty lyricism, bullet-style narration.
258
+
259
+ ## Output Requirements
260
+ Output valid JSON only, in this shape:
261
+ {
262
+ "chapterNumber": ${chapter},
263
+ "status": "clean",
264
+ "issues": [
265
+ {
266
+ "severity": "low | medium | high",
267
+ "category": "character | world | timeline | item | knowledge | pacing | style | architecture",
268
+ "description": "Specific issue",
269
+ "evidence": "Quote or paraphrase the exact passage that proves the issue",
270
+ "suggestion": "Concrete fix"
271
+ }
272
+ ]
273
+ }
274
+
275
+ Rules:
276
+ - If there are no issues, use status "clean" with an empty issues array.
277
+ - Otherwise use status "issues_found".
278
+ - evidence must be specific; do not write "possibly" or "maybe".
279
+ ${strictJsonOutputRules()}`,
280
+ };
281
+ }
282
+
283
+ function buildChapterRevisionPrompt(input: PromptBuildInput): BuiltPrompt {
284
+ const chapter = input.state.pendingAction?.chapterNumber ?? input.state.currentChapter;
285
+ return {
286
+ purpose: 'chapter_revision',
287
+ expectedFormat: 'Markdown',
288
+ prompt: `You are revising chapter ${chapter} of a serial novel based on editor feedback. Produce a full revised chapter draft.
289
+
290
+ ## Priority Order
291
+ 1. Resolve every issue in the feedback. Do not skip any.
292
+ 2. Preserve everything else that already works: structure, tone, character voice, working dialogue.
293
+ 3. Keep continuity with story bible, prior chapter ending, and existing memory.
294
+
295
+ ## Style Rules
296
+ - Keep the same chapter title and Markdown shape.
297
+ - Do not output bullet summaries, change logs, or "what I changed" explanations.
298
+ - Do not introduce new major characters or plot threads that the architecture does not authorize.
299
+
300
+ ${input.context ? `## Revision Context\n${input.context}\n` : ''}## Output Requirements
301
+ - Output Markdown only.
302
+ - First line must be the chapter title as H1 (\`# Chapter Title\`).
303
+ - After the H1, output the full revised prose. Do not output diff markers.`,
304
+ };
305
+ }
306
+
307
+ function buildCrossChapterReviewPrompt(input: PromptBuildInput): BuiltPrompt {
308
+ const range = input.state.pendingAction?.range ?? { start: 1, end: input.state.currentChapter - 1 };
309
+ return {
310
+ purpose: 'cross_chapter_review',
311
+ expectedFormat: 'JSON matching CrossChapterReviewSchema',
312
+ prompt: `You are a senior continuity editor. Review chapters ${range.start}-${range.end} together and surface cross-chapter conflicts that single-chapter review cannot catch.
313
+
314
+ ${input.context ? `## Review Context\n${input.context}\n` : ''}## Review Focus
315
+ - Drifting character state across chapters (e.g. an injury that vanishes).
316
+ - Conflicting facts established in different chapters.
317
+ - Open threads that were silently dropped.
318
+ - World-rule violations introduced in later chapters.
319
+ - Pacing problems visible only across multiple chapters.
320
+
321
+ ## Output Requirements
322
+ Output valid JSON only, in this shape:
323
+ {
324
+ "range": { "start": ${range.start}, "end": ${range.end} },
325
+ "status": "clean",
326
+ "issues": [
327
+ {
328
+ "severity": "low | medium | high",
329
+ "chapters": [${range.start}, ${range.end}],
330
+ "description": "Specific issue",
331
+ "evidence": "Cite the conflicting passages or memory entries by chapter",
332
+ "suggestion": "Concrete fix"
333
+ }
334
+ ]
335
+ }
336
+
337
+ Rules:
338
+ - chapters must list every chapter implicated by the issue.
339
+ - evidence must reference specific chapter content or memory, not vague claims.
340
+ ${strictJsonOutputRules()}`,
341
+ };
342
+ }
343
+
344
+ function buildPromptForStep(input: PromptBuildInput): BuiltPrompt {
345
+ switch (input.state.currentStep) {
346
+ case 'novel_metadata':
347
+ return buildMetadataPrompt(input);
348
+ case 'story_bible':
349
+ return buildStoryBiblePrompt(input);
350
+ case 'architecture':
351
+ return buildArchitecturePrompt(input);
352
+ case 'chapter':
353
+ return buildChapterPrompt(input);
354
+ case 'memory_card':
355
+ return buildMemoryPrompt(input);
356
+ case 'continuity_review':
357
+ return buildContinuityReviewPrompt(input);
358
+ case 'chapter_review':
359
+ return buildChapterReviewPrompt(input);
360
+ case 'chapter_revision':
361
+ return buildChapterRevisionPrompt(input);
362
+ case 'cross_chapter_review':
363
+ return buildCrossChapterReviewPrompt(input);
364
+ case 'complete':
365
+ return {
366
+ purpose: 'continuity_review',
367
+ expectedFormat: 'No output required',
368
+ prompt: 'The workflow is complete.',
369
+ };
370
+ }
371
+ }
372
+
373
+ export const enUSPromptPack: PromptPack = {
374
+ buildPromptForStep,
375
+ strictJsonOutputRules,
376
+ };
@@ -0,0 +1,28 @@
1
+ import { AgentState } from '../types.js';
2
+
3
+ export type PromptPurpose =
4
+ | 'novel_metadata'
5
+ | 'story_bible'
6
+ | 'architecture'
7
+ | 'chapter'
8
+ | 'memory_card'
9
+ | 'continuity_review'
10
+ | 'chapter_review'
11
+ | 'chapter_revision'
12
+ | 'cross_chapter_review';
13
+
14
+ export interface PromptBuildInput {
15
+ state: AgentState;
16
+ context?: string;
17
+ }
18
+
19
+ export interface BuiltPrompt {
20
+ purpose: PromptPurpose;
21
+ prompt: string;
22
+ expectedFormat: string;
23
+ }
24
+
25
+ export interface PromptPack {
26
+ buildPromptForStep(input: PromptBuildInput): BuiltPrompt;
27
+ strictJsonOutputRules(): string;
28
+ }