@narrative-os/cli 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.
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.readCommand = readCommand;
4
+ const store_js_1 = require("../config/store.js");
5
+ function readCommand(storyId, chapterNumber) {
6
+ const story = (0, store_js_1.loadStory)(storyId);
7
+ if (!story) {
8
+ console.error(`Story not found: ${storyId}`);
9
+ process.exit(1);
10
+ }
11
+ const { bible, chapters } = story;
12
+ if (chapters.length === 0) {
13
+ console.log(`Story "${bible.title}" has no chapters yet.`);
14
+ console.log(`Run "nos generate ${storyId}" to write Chapter 1.`);
15
+ return;
16
+ }
17
+ if (chapterNumber) {
18
+ // Read specific chapter
19
+ const chapter = chapters.find(ch => ch.number === chapterNumber);
20
+ if (!chapter) {
21
+ console.error(`Chapter ${chapterNumber} not found.`);
22
+ console.log(`Available chapters: 1-${chapters.length}`);
23
+ process.exit(1);
24
+ }
25
+ console.log(`\n# Chapter ${chapter.number}: ${chapter.title}`);
26
+ console.log(`Word count: ${chapter.wordCount}`);
27
+ console.log('─'.repeat(60));
28
+ console.log('');
29
+ console.log(chapter.content);
30
+ console.log('');
31
+ console.log('─'.repeat(60));
32
+ }
33
+ else {
34
+ // List all chapters
35
+ console.log(`\nStory: ${bible.title}`);
36
+ console.log(`Total chapters: ${chapters.length}\n`);
37
+ for (const chapter of chapters) {
38
+ console.log(` Chapter ${chapter.number}: ${chapter.title} (${chapter.wordCount} words)`);
39
+ }
40
+ console.log(`\nUse "nos read ${storyId} <chapter-number>" to read a specific chapter.`);
41
+ }
42
+ }
@@ -0,0 +1 @@
1
+ export declare function regenerateCommand(storyId: string, chapterNumber: number): Promise<void>;
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.regenerateCommand = regenerateCommand;
4
+ const engine_1 = require("@narrative-os/engine");
5
+ const store_js_1 = require("../config/store.js");
6
+ async function regenerateCommand(storyId, chapterNumber) {
7
+ const story = (0, store_js_1.loadStory)(storyId);
8
+ if (!story) {
9
+ console.error(`Story not found: ${storyId}`);
10
+ process.exit(1);
11
+ }
12
+ const { bible, state, chapters, canon } = story;
13
+ // Find the chapter to regenerate
14
+ const chapterIndex = chapters.findIndex(ch => ch.number === chapterNumber);
15
+ if (chapterIndex === -1) {
16
+ console.error(`Chapter ${chapterNumber} not found.`);
17
+ console.log(`Available chapters: 1-${chapters.length}`);
18
+ process.exit(1);
19
+ }
20
+ console.log(`Regenerating Chapter ${chapterNumber}...`);
21
+ console.log(`Current title: ${chapters[chapterIndex].title}\n`);
22
+ // Load or initialize vector store
23
+ const vectorStore = (0, engine_1.getVectorStore)(storyId);
24
+ const existingData = (0, store_js_1.loadVectorStore)(storyId);
25
+ if (existingData) {
26
+ await vectorStore.load(existingData);
27
+ }
28
+ else {
29
+ await vectorStore.initialize();
30
+ }
31
+ // Create context - use state as it was BEFORE this chapter
32
+ const context = {
33
+ bible,
34
+ state: {
35
+ ...state,
36
+ currentChapter: chapterNumber - 1, // Pretend we're at previous chapter
37
+ },
38
+ chapterNumber,
39
+ targetWordCount: 1500,
40
+ };
41
+ try {
42
+ const result = await (0, engine_1.generateChapter)(context, { canon, vectorStore });
43
+ // Replace the old chapter
44
+ const newChapters = [...chapters];
45
+ newChapters[chapterIndex] = result.chapter;
46
+ (0, store_js_1.saveStory)(bible, state, newChapters, canon);
47
+ (0, store_js_1.saveVectorStore)(storyId, vectorStore.serialize());
48
+ console.log(`\n✅ Chapter ${chapterNumber} regenerated!`);
49
+ console.log(`New title: ${result.chapter.title}`);
50
+ console.log(`Words: ${result.chapter.wordCount}`);
51
+ if (result.violations.length > 0) {
52
+ console.log(`⚠️ Canon violations: ${result.violations.length}`);
53
+ }
54
+ console.log(`\nSummary: ${result.summary.summary}`);
55
+ }
56
+ catch (error) {
57
+ console.error('Regeneration failed:', error);
58
+ process.exit(1);
59
+ }
60
+ }
@@ -0,0 +1 @@
1
+ export declare function stateCommand(storyId: string): void;
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.stateCommand = stateCommand;
4
+ const store_js_1 = require("../config/store.js");
5
+ function stateCommand(storyId) {
6
+ const story = (0, store_js_1.loadStory)(storyId);
7
+ const structuredState = (0, store_js_1.loadStructuredState)(storyId);
8
+ if (!story) {
9
+ console.error(`Story not found: ${storyId}`);
10
+ process.exit(1);
11
+ }
12
+ const { bible, state } = story;
13
+ console.log(`\n# Story State: ${bible.title}`);
14
+ console.log('─'.repeat(60));
15
+ console.log(`\n## Progress`);
16
+ console.log(` Current Chapter: ${state.currentChapter} / ${state.totalChapters}`);
17
+ const progress = Math.round((state.currentChapter / state.totalChapters) * 100);
18
+ console.log(` Progress: ${progress}%`);
19
+ console.log(` Current Tension: ${(state.currentTension * 100).toFixed(0)}%`);
20
+ if (structuredState) {
21
+ console.log(`\n## Characters`);
22
+ console.log('─'.repeat(60));
23
+ const characters = Object.values(structuredState.characters);
24
+ if (characters.length === 0) {
25
+ console.log(' No character states tracked.');
26
+ }
27
+ else {
28
+ for (const char of characters) {
29
+ console.log(`\n ${char.name}`);
30
+ console.log(` Emotional State: ${char.emotionalState}`);
31
+ console.log(` Location: ${char.location}`);
32
+ console.log(` Goals: ${char.goals.join(', ')}`);
33
+ if (char.knowledge.length > 0) {
34
+ console.log(` Knowledge: ${char.knowledge.length} facts`);
35
+ }
36
+ if (Object.keys(char.relationships).length > 0) {
37
+ console.log(` Relationships: ${Object.entries(char.relationships).map(([k, v]) => `${k} (${v})`).join(', ')}`);
38
+ }
39
+ }
40
+ }
41
+ console.log(`\n## Plot Threads`);
42
+ console.log('─'.repeat(60));
43
+ const threads = Object.values(structuredState.plotThreads);
44
+ if (threads.length === 0) {
45
+ console.log(' No plot threads tracked.');
46
+ }
47
+ else {
48
+ for (const thread of threads) {
49
+ console.log(`\n ${thread.name}`);
50
+ console.log(` Status: ${thread.status}`);
51
+ console.log(` Tension: ${(thread.tension * 100).toFixed(0)}%`);
52
+ console.log(` Last Chapter: ${thread.lastChapter}`);
53
+ console.log(` Summary: ${thread.summary.substring(0, 60)}...`);
54
+ }
55
+ }
56
+ if (structuredState.unresolvedQuestions.length > 0) {
57
+ console.log(`\n## Unresolved Questions`);
58
+ console.log('─'.repeat(60));
59
+ for (const q of structuredState.unresolvedQuestions) {
60
+ console.log(` • ${q}`);
61
+ }
62
+ }
63
+ if (structuredState.recentEvents.length > 0) {
64
+ console.log(`\n## Recent Events`);
65
+ console.log('─'.repeat(60));
66
+ for (const e of structuredState.recentEvents.slice(-5)) {
67
+ console.log(` • ${e.substring(0, 80)}...`);
68
+ }
69
+ }
70
+ }
71
+ else {
72
+ console.log('\n No structured state available.');
73
+ console.log(' Generate some chapters to track state.');
74
+ }
75
+ console.log('');
76
+ }
@@ -0,0 +1 @@
1
+ export declare function statusCommand(storyId?: string): void;
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.statusCommand = statusCommand;
4
+ const store_js_1 = require("../config/store.js");
5
+ function statusCommand(storyId) {
6
+ if (!storyId) {
7
+ const stories = (0, store_js_1.listStories)();
8
+ if (stories.length === 0) {
9
+ console.log('No stories found.\n');
10
+ console.log('💡 Get started:');
11
+ console.log(' • Create a new story: nos init --title "My Story"');
12
+ console.log(' • Or with options: nos init --help');
13
+ return;
14
+ }
15
+ console.log('Stories:\n');
16
+ for (const story of stories) {
17
+ const progress = Math.round((story.currentChapter / story.totalChapters) * 100);
18
+ console.log(` ${story.id}`);
19
+ console.log(` Title: ${story.title}`);
20
+ console.log(` Progress: ${story.currentChapter}/${story.totalChapters} (${progress}%)`);
21
+ console.log('');
22
+ }
23
+ return;
24
+ }
25
+ const story = (0, store_js_1.loadStory)(storyId);
26
+ if (!story) {
27
+ console.error(`Story not found: ${storyId}`);
28
+ process.exit(1);
29
+ }
30
+ const { bible, state, chapters } = story;
31
+ const progress = Math.round((state.currentChapter / state.totalChapters) * 100);
32
+ console.log(`Story: ${bible.title}`);
33
+ console.log(`ID: ${bible.id}`);
34
+ console.log(`Theme: ${bible.theme}`);
35
+ console.log(`Genre: ${bible.genre}`);
36
+ console.log(`Setting: ${bible.setting}`);
37
+ console.log(`\nProgress: ${state.currentChapter}/${state.totalChapters} (${progress}%)`);
38
+ console.log(`Current Tension: ${(state.currentTension * 100).toFixed(0)}%`);
39
+ if (chapters.length > 0) {
40
+ console.log('\nChapters:');
41
+ for (const ch of chapters) {
42
+ console.log(` ${ch.number}. ${ch.title} (${ch.wordCount} words)`);
43
+ }
44
+ }
45
+ if (state.chapterSummaries.length > 0) {
46
+ console.log('\nRecent Summaries:');
47
+ for (const sum of state.chapterSummaries.slice(-3)) {
48
+ console.log(` Ch ${sum.chapterNumber}: ${sum.summary.substring(0, 80)}...`);
49
+ }
50
+ }
51
+ }
@@ -0,0 +1 @@
1
+ export declare function validateCommand(storyId: string): Promise<void>;
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateCommand = validateCommand;
4
+ const engine_1 = require("@narrative-os/engine");
5
+ const store_js_1 = require("../config/store.js");
6
+ async function validateCommand(storyId) {
7
+ const story = (0, store_js_1.loadStory)(storyId);
8
+ if (!story) {
9
+ console.error(`Story not found: ${storyId}`);
10
+ process.exit(1);
11
+ }
12
+ const { bible, state, chapters, canon, structuredState } = story;
13
+ console.log(`\nValidating Story: ${bible.title}`);
14
+ console.log('─'.repeat(60));
15
+ // Load constraint graph if exists
16
+ const constraintGraph = (0, engine_1.createConstraintGraph)();
17
+ const graphData = (0, store_js_1.loadConstraintGraph)(storyId);
18
+ if (graphData) {
19
+ constraintGraph.load(graphData);
20
+ }
21
+ // Load vector store if exists
22
+ const vectorStore = (0, engine_1.getVectorStore)(storyId);
23
+ const vectorData = (0, store_js_1.loadVectorStore)(storyId);
24
+ if (vectorData) {
25
+ await vectorStore.load(vectorData);
26
+ }
27
+ console.log(`\n## Story Statistics`);
28
+ console.log(` Chapters: ${chapters.length} / ${state.totalChapters}`);
29
+ console.log(` Canon Facts: ${canon.facts.length}`);
30
+ console.log(` Constraint Graph: ${constraintGraph.getStats().nodes} nodes, ${constraintGraph.getStats().edges} edges`);
31
+ console.log(` Vector Memories: ${vectorStore.getAllMemories().length}`);
32
+ // Validate each chapter
33
+ if (chapters.length > 0 && structuredState) {
34
+ console.log(`\n## Chapter Validation`);
35
+ console.log('─'.repeat(60));
36
+ const validator = new engine_1.Validator(constraintGraph);
37
+ let totalViolations = 0;
38
+ for (const chapter of chapters) {
39
+ const result = validator.quickValidate({
40
+ chapter,
41
+ bible,
42
+ structuredState,
43
+ canon,
44
+ previousChapters: chapters.filter(ch => ch.number < chapter.number),
45
+ constraintGraph,
46
+ });
47
+ const errors = result.violations.filter(v => v.severity === 'error').length;
48
+ const warnings = result.violations.filter(v => v.severity === 'warning').length;
49
+ if (errors > 0 || warnings > 0) {
50
+ console.log(`\n Chapter ${chapter.number}: ${chapter.title}`);
51
+ if (errors > 0)
52
+ console.log(` ❌ ${errors} error(s)`);
53
+ if (warnings > 0)
54
+ console.log(` ⚠️ ${warnings} warning(s)`);
55
+ totalViolations += result.violations.length;
56
+ }
57
+ }
58
+ if (totalViolations === 0) {
59
+ console.log(' ✅ All chapters pass validation!');
60
+ }
61
+ else {
62
+ console.log(`\n Total: ${totalViolations} violation(s) found`);
63
+ }
64
+ }
65
+ // Check for common issues
66
+ console.log(`\n## Consistency Checks`);
67
+ console.log('─'.repeat(60));
68
+ const issues = [];
69
+ // Check for chapters without summaries
70
+ const noSummary = chapters.filter(ch => !ch.summary || ch.summary.length < 10);
71
+ if (noSummary.length > 0) {
72
+ issues.push(`${noSummary.length} chapter(s) missing summaries`);
73
+ }
74
+ // Check for very short chapters
75
+ const shortChapters = chapters.filter(ch => ch.wordCount < 500);
76
+ if (shortChapters.length > 0) {
77
+ issues.push(`${shortChapters.length} chapter(s) unusually short (< 500 words)`);
78
+ }
79
+ // Check for canon facts without chapters
80
+ const orphanedFacts = canon.facts.filter(f => f.chapterEstablished > state.currentChapter);
81
+ if (orphanedFacts.length > 0) {
82
+ issues.push(`${orphanedFacts.length} canon fact(s) from future chapters`);
83
+ }
84
+ if (issues.length === 0) {
85
+ console.log(' ✅ No issues found!');
86
+ }
87
+ else {
88
+ for (const issue of issues) {
89
+ console.log(` ⚠️ ${issue}`);
90
+ }
91
+ }
92
+ console.log('\n');
93
+ }
@@ -0,0 +1,24 @@
1
+ import type { StoryBible, StoryState, Chapter, CanonStore, StoryStructuredState } from '@narrative-os/engine';
2
+ export declare function saveStory(bible: StoryBible, state: StoryState, chapters: Chapter[], canon?: CanonStore, structuredState?: StoryStructuredState): void;
3
+ export declare function loadStory(storyId: string): {
4
+ bible: StoryBible;
5
+ state: StoryState;
6
+ chapters: Chapter[];
7
+ canon: CanonStore;
8
+ structuredState: StoryStructuredState | null;
9
+ } | null;
10
+ export declare function listStories(): {
11
+ id: string;
12
+ title: string;
13
+ currentChapter: number;
14
+ totalChapters: number;
15
+ }[];
16
+ export declare function saveVectorStore(storyId: string, data: string): void;
17
+ export declare function loadVectorStore(storyId: string): string | null;
18
+ export declare function saveStructuredState(storyId: string, state: StoryStructuredState): void;
19
+ export declare function loadStructuredState(storyId: string): StoryStructuredState | null;
20
+ export declare function initializeStructuredState(storyId: string, bible: StoryBible): StoryStructuredState;
21
+ export declare function saveConstraintGraph(storyId: string, data: string): void;
22
+ export declare function loadConstraintGraph(storyId: string): string | null;
23
+ export declare function saveWorldState(storyId: string, data: string): void;
24
+ export declare function loadWorldState(storyId: string): string | null;
@@ -0,0 +1,183 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.saveStory = saveStory;
4
+ exports.loadStory = loadStory;
5
+ exports.listStories = listStories;
6
+ exports.saveVectorStore = saveVectorStore;
7
+ exports.loadVectorStore = loadVectorStore;
8
+ exports.saveStructuredState = saveStructuredState;
9
+ exports.loadStructuredState = loadStructuredState;
10
+ exports.initializeStructuredState = initializeStructuredState;
11
+ exports.saveConstraintGraph = saveConstraintGraph;
12
+ exports.loadConstraintGraph = loadConstraintGraph;
13
+ exports.saveWorldState = saveWorldState;
14
+ exports.loadWorldState = loadWorldState;
15
+ const fs_1 = require("fs");
16
+ const path_1 = require("path");
17
+ const os_1 = require("os");
18
+ const engine_1 = require("@narrative-os/engine");
19
+ const DATA_DIR = (0, path_1.join)((0, os_1.homedir)(), '.narrative-os');
20
+ const STORIES_DIR = (0, path_1.join)(DATA_DIR, 'stories');
21
+ function ensureDirs() {
22
+ if (!(0, fs_1.existsSync)(DATA_DIR))
23
+ (0, fs_1.mkdirSync)(DATA_DIR, { recursive: true });
24
+ if (!(0, fs_1.existsSync)(STORIES_DIR))
25
+ (0, fs_1.mkdirSync)(STORIES_DIR, { recursive: true });
26
+ }
27
+ function saveStory(bible, state, chapters, canon, structuredState) {
28
+ ensureDirs();
29
+ const storyDir = (0, path_1.join)(STORIES_DIR, bible.id);
30
+ if (!(0, fs_1.existsSync)(storyDir))
31
+ (0, fs_1.mkdirSync)(storyDir, { recursive: true });
32
+ (0, fs_1.writeFileSync)((0, path_1.join)(storyDir, 'bible.json'), JSON.stringify(bible, null, 2));
33
+ (0, fs_1.writeFileSync)((0, path_1.join)(storyDir, 'state.json'), JSON.stringify(state, null, 2));
34
+ (0, fs_1.writeFileSync)((0, path_1.join)(storyDir, 'chapters.json'), JSON.stringify(chapters, null, 2));
35
+ const canonToSave = canon || (0, engine_1.extractCanonFromBible)(bible);
36
+ (0, fs_1.writeFileSync)((0, path_1.join)(storyDir, 'canon.json'), JSON.stringify(canonToSave, null, 2));
37
+ // Save structured state if provided
38
+ if (structuredState) {
39
+ (0, fs_1.writeFileSync)((0, path_1.join)(storyDir, 'structured-state.json'), JSON.stringify(structuredState, null, 2));
40
+ }
41
+ }
42
+ function loadStory(storyId) {
43
+ const storyDir = (0, path_1.join)(STORIES_DIR, storyId);
44
+ if (!(0, fs_1.existsSync)(storyDir))
45
+ return null;
46
+ try {
47
+ const bible = JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(storyDir, 'bible.json'), 'utf-8'));
48
+ const state = JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(storyDir, 'state.json'), 'utf-8'));
49
+ const chapters = JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(storyDir, 'chapters.json'), 'utf-8'));
50
+ let canon;
51
+ const canonPath = (0, path_1.join)(storyDir, 'canon.json');
52
+ if ((0, fs_1.existsSync)(canonPath)) {
53
+ canon = JSON.parse((0, fs_1.readFileSync)(canonPath, 'utf-8'));
54
+ }
55
+ else {
56
+ canon = (0, engine_1.extractCanonFromBible)(bible);
57
+ }
58
+ // Load structured state
59
+ let structuredState = null;
60
+ const structuredPath = (0, path_1.join)(storyDir, 'structured-state.json');
61
+ if ((0, fs_1.existsSync)(structuredPath)) {
62
+ structuredState = JSON.parse((0, fs_1.readFileSync)(structuredPath, 'utf-8'));
63
+ }
64
+ return { bible, state, chapters, canon, structuredState };
65
+ }
66
+ catch {
67
+ return null;
68
+ }
69
+ }
70
+ function listStories() {
71
+ ensureDirs();
72
+ const stories = [];
73
+ for (const dir of (0, fs_1.existsSync)(STORIES_DIR) ? (0, fs_1.readdirSync)(STORIES_DIR) : []) {
74
+ const storyPath = (0, path_1.join)(STORIES_DIR, dir);
75
+ const statePath = (0, path_1.join)(storyPath, 'state.json');
76
+ const biblePath = (0, path_1.join)(storyPath, 'bible.json');
77
+ if ((0, fs_1.existsSync)(statePath) && (0, fs_1.existsSync)(biblePath)) {
78
+ try {
79
+ const state = JSON.parse((0, fs_1.readFileSync)(statePath, 'utf-8'));
80
+ const bible = JSON.parse((0, fs_1.readFileSync)(biblePath, 'utf-8'));
81
+ stories.push({
82
+ id: dir,
83
+ title: bible.title,
84
+ currentChapter: state.currentChapter,
85
+ totalChapters: state.totalChapters,
86
+ });
87
+ }
88
+ catch { }
89
+ }
90
+ }
91
+ return stories;
92
+ }
93
+ // Vector store persistence
94
+ function saveVectorStore(storyId, data) {
95
+ ensureDirs();
96
+ const storyDir = (0, path_1.join)(STORIES_DIR, storyId);
97
+ if (!(0, fs_1.existsSync)(storyDir))
98
+ (0, fs_1.mkdirSync)(storyDir, { recursive: true });
99
+ (0, fs_1.writeFileSync)((0, path_1.join)(storyDir, 'vector-store.json'), data);
100
+ }
101
+ function loadVectorStore(storyId) {
102
+ const storyDir = (0, path_1.join)(STORIES_DIR, storyId);
103
+ const vectorPath = (0, path_1.join)(storyDir, 'vector-store.json');
104
+ if (!(0, fs_1.existsSync)(vectorPath))
105
+ return null;
106
+ try {
107
+ return (0, fs_1.readFileSync)(vectorPath, 'utf-8');
108
+ }
109
+ catch {
110
+ return null;
111
+ }
112
+ }
113
+ // Structured state persistence
114
+ function saveStructuredState(storyId, state) {
115
+ ensureDirs();
116
+ const storyDir = (0, path_1.join)(STORIES_DIR, storyId);
117
+ if (!(0, fs_1.existsSync)(storyDir))
118
+ (0, fs_1.mkdirSync)(storyDir, { recursive: true });
119
+ (0, fs_1.writeFileSync)((0, path_1.join)(storyDir, 'structured-state.json'), JSON.stringify(state, null, 2));
120
+ }
121
+ function loadStructuredState(storyId) {
122
+ const storyDir = (0, path_1.join)(STORIES_DIR, storyId);
123
+ const statePath = (0, path_1.join)(storyDir, 'structured-state.json');
124
+ if (!(0, fs_1.existsSync)(statePath))
125
+ return null;
126
+ try {
127
+ return JSON.parse((0, fs_1.readFileSync)(statePath, 'utf-8'));
128
+ }
129
+ catch {
130
+ return null;
131
+ }
132
+ }
133
+ // Initialize structured state from bible if it doesn't exist
134
+ function initializeStructuredState(storyId, bible) {
135
+ let state = loadStructuredState(storyId);
136
+ if (!state) {
137
+ state = (0, engine_1.createStructuredState)(storyId);
138
+ state = (0, engine_1.initializeCharactersFromBible)(state, bible);
139
+ state = (0, engine_1.initializePlotThreadsFromBible)(state, bible);
140
+ saveStructuredState(storyId, state);
141
+ }
142
+ return state;
143
+ }
144
+ // Constraint graph persistence
145
+ function saveConstraintGraph(storyId, data) {
146
+ ensureDirs();
147
+ const storyDir = (0, path_1.join)(STORIES_DIR, storyId);
148
+ if (!(0, fs_1.existsSync)(storyDir))
149
+ (0, fs_1.mkdirSync)(storyDir, { recursive: true });
150
+ (0, fs_1.writeFileSync)((0, path_1.join)(storyDir, 'constraint-graph.json'), data);
151
+ }
152
+ function loadConstraintGraph(storyId) {
153
+ const storyDir = (0, path_1.join)(STORIES_DIR, storyId);
154
+ const graphPath = (0, path_1.join)(storyDir, 'constraint-graph.json');
155
+ if (!(0, fs_1.existsSync)(graphPath))
156
+ return null;
157
+ try {
158
+ return (0, fs_1.readFileSync)(graphPath, 'utf-8');
159
+ }
160
+ catch {
161
+ return null;
162
+ }
163
+ }
164
+ // World state persistence
165
+ function saveWorldState(storyId, data) {
166
+ ensureDirs();
167
+ const storyDir = (0, path_1.join)(STORIES_DIR, storyId);
168
+ if (!(0, fs_1.existsSync)(storyDir))
169
+ (0, fs_1.mkdirSync)(storyDir, { recursive: true });
170
+ (0, fs_1.writeFileSync)((0, path_1.join)(storyDir, 'world-state.json'), data);
171
+ }
172
+ function loadWorldState(storyId) {
173
+ const storyDir = (0, path_1.join)(STORIES_DIR, storyId);
174
+ const worldPath = (0, path_1.join)(storyDir, 'world-state.json');
175
+ if (!(0, fs_1.existsSync)(worldPath))
176
+ return null;
177
+ try {
178
+ return (0, fs_1.readFileSync)(worldPath, 'utf-8');
179
+ }
180
+ catch {
181
+ return null;
182
+ }
183
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,130 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const commander_1 = require("commander");
5
+ const init_js_1 = require("./commands/init.js");
6
+ const generate_js_1 = require("./commands/generate.js");
7
+ const status_js_1 = require("./commands/status.js");
8
+ const config_js_1 = require("./commands/config.js");
9
+ const list_js_1 = require("./commands/list.js");
10
+ const delete_js_1 = require("./commands/delete.js");
11
+ const clone_js_1 = require("./commands/clone.js");
12
+ const export_js_1 = require("./commands/export.js");
13
+ const read_js_1 = require("./commands/read.js");
14
+ const bible_js_1 = require("./commands/bible.js");
15
+ const state_js_1 = require("./commands/state.js");
16
+ const hint_js_1 = require("./commands/hint.js");
17
+ (0, config_js_1.applyConfig)();
18
+ const program = new commander_1.Command();
19
+ program
20
+ .name('nos')
21
+ .description('Narrative OS - AI-powered story generation')
22
+ .version('0.1.0');
23
+ // Show welcome when no args provided
24
+ if (process.argv.length <= 2) {
25
+ (0, hint_js_1.showWelcome)();
26
+ process.exit(0);
27
+ }
28
+ // Configuration
29
+ program
30
+ .command('config')
31
+ .description('Configure LLM provider and API key')
32
+ .action(config_js_1.configCommand);
33
+ // Story Management
34
+ program
35
+ .command('init')
36
+ .description('Create a new story')
37
+ .option('-t, --title <title>', 'Story title')
38
+ .option('--theme <theme>', 'Story theme')
39
+ .option('-g, --genre <genre>', 'Genre')
40
+ .option('-s, --setting <setting>', 'Setting')
41
+ .option('--tone <tone>', 'Tone')
42
+ .option('-p, --premise <premise>', 'Story premise')
43
+ .option('-c, --chapters <number>', 'Target chapter count', '5')
44
+ .action(init_js_1.initCommand);
45
+ program
46
+ .command('list')
47
+ .alias('ls')
48
+ .description('List all stories')
49
+ .action(list_js_1.listCommand);
50
+ program
51
+ .command('status [story-id]')
52
+ .description('Show story status (or list all stories)')
53
+ .action(status_js_1.statusCommand);
54
+ program
55
+ .command('delete <story-id>')
56
+ .description('Delete a story')
57
+ .option('-f, --force', 'Skip confirmation')
58
+ .action((storyId, options) => {
59
+ (0, delete_js_1.deleteCommand)(storyId, options.force);
60
+ });
61
+ program
62
+ .command('clone <story-id> <new-title>')
63
+ .description('Clone a story as a template')
64
+ .action(clone_js_1.cloneCommand);
65
+ // Generation
66
+ program
67
+ .command('generate <story-id>')
68
+ .alias('gen')
69
+ .description('Generate the next chapter')
70
+ .action(generate_js_1.generateCommand);
71
+ program
72
+ .command('continue <story-id>')
73
+ .description('Generate all remaining chapters')
74
+ .action(async (storyId) => {
75
+ const { continueCommand } = await import('./commands/continue.js');
76
+ await continueCommand(storyId);
77
+ });
78
+ program
79
+ .command('regenerate <story-id> <chapter-number>')
80
+ .alias('regen')
81
+ .description('Regenerate a specific chapter')
82
+ .action(async (storyId, chapterNum) => {
83
+ const { regenerateCommand } = await import('./commands/regenerate.js');
84
+ await regenerateCommand(storyId, parseInt(chapterNum));
85
+ });
86
+ // Reading & Export
87
+ program
88
+ .command('read <story-id> [chapter-number]')
89
+ .description('Read chapter content (or list chapters)')
90
+ .action((storyId, chapterNum) => {
91
+ (0, read_js_1.readCommand)(storyId, chapterNum ? parseInt(chapterNum) : undefined);
92
+ });
93
+ program
94
+ .command('export <story-id>')
95
+ .description('Export story to file')
96
+ .option('-f, --format <format>', 'Export format (markdown|txt)', 'markdown')
97
+ .option('-o, --output <file>', 'Output filename')
98
+ .action((storyId, options) => {
99
+ (0, export_js_1.exportCommand)(storyId, options.format, options.output);
100
+ });
101
+ // Bible & State
102
+ program
103
+ .command('bible <story-id>')
104
+ .description('View story bible (characters, setting, etc.)')
105
+ .action(bible_js_1.bibleCommand);
106
+ program
107
+ .command('state <story-id>')
108
+ .description('View structured story state')
109
+ .action(state_js_1.stateCommand);
110
+ program
111
+ .command('memories <story-id> [query]')
112
+ .description('Search narrative memories')
113
+ .action(async (storyId, query) => {
114
+ const { memoriesCommand } = await import('./commands/memories.js');
115
+ await memoriesCommand(storyId, query);
116
+ });
117
+ program
118
+ .command('validate <story-id>')
119
+ .description('Validate story consistency')
120
+ .action(async (storyId) => {
121
+ const { validateCommand } = await import('./commands/validate.js');
122
+ await validateCommand(storyId);
123
+ });
124
+ program
125
+ .command('hint [story-id]')
126
+ .description('Show helpful hints and suggestions')
127
+ .action((storyId) => {
128
+ (0, hint_js_1.showHint)({ storyId });
129
+ });
130
+ program.parse();