story-weaver-ai
Version:
A narrative development system for AI-driven storytelling with Jungian psychology
239 lines (215 loc) • 8.68 kB
JavaScript
/**
* Story Weaver CLI
*
* @author Sean Pavlak
* @github https://github.com/seanpavlak/cursor-story-master
*
* A story writing management system with Jungian psychology influences.
*/
import { program } from 'commander';
import { registerStoryCommands } from '../scripts/commands.js';
import { fileURLToPath } from 'url';
import { dirname, resolve } from 'path';
import { spawn } from 'child_process';
import { createRequire } from 'module';
import chalk from 'chalk';
// Get the directory path for the module
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const require = createRequire(import.meta.url);
// Get package info
const packageJson = require('../package.json');
// Welcome message
console.log(chalk.blue(`
┌─────────────────────────────────────────────┐
│ │
│ 🧠 Story Weaver v${packageJson.version.padEnd(5)} │
│ │
│ Narrative Analysis & Refinement System │
│ With Jungian Psychology Influences │
│ │
└─────────────────────────────────────────────┘
`));
// Initialize the CLI
program
.name('story-weaver')
.description('Story Weaver - A story writing system with Jungian psychology influences')
.version(packageJson.version);
// Register story analysis and refinement commands
registerStoryCommands(program);
// Parse concept document
program
.command('parse-concept')
.description('Parse a story concept document to generate story elements')
.requiredOption('-i, --input <file>', 'Path to the concept document')
.option('-o, --output <file>', 'Output file for story elements', 'elements/elements.json')
.option('-a, --archetypes', 'Focus on archetypal analysis')
.option('-s, --symbols', 'Include symbolic analysis')
.option('-d, --dependencies', 'Generate element dependencies')
.option('-m, --model <model>', 'Claude model to use')
.action(async (options) => {
try {
console.log(chalk.blue(`Parsing concept document: ${options.input}`));
const conceptParser = await import('../scripts/modules/concept-parser.js');
await conceptParser.parseConceptDocument(options);
console.log(chalk.green(`Successfully parsed concept document and generated elements at ${options.output}`));
} catch (error) {
console.error(chalk.red(`Failed to parse concept document: ${error.message}`));
process.exit(1);
}
});
// List elements
program
.command('list')
.description('List all story elements')
.option('-f, --file <file>', 'Elements file path', 'elements/elements.json')
.option('-s, --status <status>', 'Filter by status')
.option('-a, --archetype <archetype>', 'Filter by archetype')
.option('-t, --theme <theme>', 'Filter by theme')
.action(async (options) => {
try {
const elementManager = await import('../scripts/modules/element-manager.js');
await elementManager.listElements(options);
} catch (error) {
console.error(chalk.red(`Failed to list elements: ${error.message}`));
process.exit(1);
}
});
// Add element
program
.command('add-element')
.description('Add a new story element')
.option('-f, --file <file>', 'Elements file path', 'elements/elements.json')
.requiredOption('-t, --title <title>', 'Element title')
.option('-d, --description <description>', 'Element description')
.option('-a, --archetypes <archetypes...>', 'Associated archetypes')
.option('-T, --themes <themes...>', 'Associated themes')
.option('-p, --priority <priority>', 'Element priority (high, medium, low)', 'medium')
.option('-D, --dependencies <dependencies...>', 'Element dependencies (IDs)')
.option('--details <details>', 'Detailed element description')
.action(async (options) => {
try {
const elementManager = await import('../scripts/modules/element-manager.js');
await elementManager.addElement(options);
console.log(chalk.green('New element added successfully'));
} catch (error) {
console.error(chalk.red(`Failed to add element: ${error.message}`));
process.exit(1);
}
});
// Set element status
program
.command('set-status')
.description('Set the status of a story element')
.requiredOption('--id <id>', 'Element ID')
.requiredOption('--status <status>', 'New status value')
.option('-f, --file <file>', 'Elements file path', 'elements/elements.json')
.action(async (options) => {
try {
const elementManager = await import('../scripts/modules/element-manager.js');
await elementManager.setElementStatus(options.id, options.status, options.file);
console.log(chalk.green(`Element ${options.id} status set to "${options.status}"`));
} catch (error) {
console.error(chalk.red(`Failed to set element status: ${error.message}`));
process.exit(1);
}
});
// Analyze dependencies
program
.command('analyze-dependencies')
.description('Analyze and validate element dependencies')
.option('-f, --file <file>', 'Elements file path', 'elements/elements.json')
.option('--fix', 'Automatically fix invalid dependencies')
.action(async (options) => {
try {
const dependencyManager = await import('../scripts/modules/dependency-manager.js');
await dependencyManager.analyzeDependencies(options);
} catch (error) {
console.error(chalk.red(`Failed to analyze dependencies: ${error.message}`));
process.exit(1);
}
});
// Next element
program
.command('next')
.description('Show the next element to work on')
.option('-f, --file <file>', 'Elements file path', 'elements/elements.json')
.action(async (options) => {
try {
const elementManager = await import('../scripts/modules/element-manager.js');
await elementManager.showNextElement(options.file);
} catch (error) {
console.error(chalk.red(`Failed to determine next element: ${error.message}`));
process.exit(1);
}
});
// Show element
program
.command('show')
.description('Show details of a specific element')
.argument('<id>', 'Element ID')
.option('-f, --file <file>', 'Elements file path', 'elements/elements.json')
.action(async (id, options) => {
try {
const elementManager = await import('../scripts/modules/element-manager.js');
await elementManager.showElement(id, options.file);
} catch (error) {
console.error(chalk.red(`Failed to show element: ${error.message}`));
process.exit(1);
}
});
// Initialize a new story project
program
.command('init')
.description('Initialize a new story project')
.option('-n, --name <name>', 'Project name')
.option('-y, --yes', 'Skip prompts and use defaults')
.action(() => {
const initScript = resolve(__dirname, 'story-weaver-init.js');
// Pass arguments to the init script
const args = process.argv.slice(process.argv.indexOf('init') + 1);
const child = spawn('node', [initScript, ...args], {
stdio: 'inherit',
cwd: process.cwd()
});
child.on('close', (code) => {
process.exit(code);
});
});
// Psychological archetypes reference
program
.command('archetypes')
.description('Display information about Jungian archetypes')
.option('--details', 'Show detailed descriptions')
.option('--examples', 'Include literary examples')
.action(async (options) => {
try {
const { displayArchetypes } = await import('../scripts/modules/jungian-references.js');
await displayArchetypes(options);
} catch (error) {
console.error(chalk.red(`Failed to display archetypes: ${error.message}`));
process.exit(1);
}
});
// Psychological symbols reference
program
.command('symbols')
.description('Display information about symbolic psychology')
.option('--details', 'Show detailed descriptions')
.option('--category <category>', 'Filter by category')
.action(async (options) => {
try {
const { displaySymbols } = await import('../scripts/modules/jungian-references.js');
await displaySymbols(options);
} catch (error) {
console.error(chalk.red(`Failed to display symbols: ${error.message}`));
process.exit(1);
}
});
// If no arguments are supplied, show help
if (process.argv.length === 2) {
program.help();
}
// Parse the arguments
program.parse(process.argv);