novel-weaver 0.1.1 → 0.1.4

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,221 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * novel-weaver CLI (vanilla JS, no TypeScript)
4
+ */
5
+
6
+ import {
7
+ resolveOpencodeConfigDir,
8
+ resolveBundledAgentsDir,
9
+ } from "../dist/tools/install-agents.js";
10
+ import * as fs from "node:fs";
11
+ import * as path from "node:path";
12
+
13
+ const VERSION = "0.1.4";
14
+
15
+ function printHelp() {
16
+ console.log(`novel-weaver v${VERSION} — novel writing toolkit for OpenCode
17
+
18
+ Usage:
19
+ novel-weaver <command> [options]
20
+
21
+ Commands:
22
+ install-agents Install 4 agent .md files to the OpenCode agent directory
23
+ (ArcMaster, WorldBuilder, Reviewer, PlotPlanner)
24
+ Options:
25
+ --force Overwrite existing files
26
+ --target <dir> Override target directory
27
+
28
+ mcp Run as an MCP (Model Context Protocol) server on stdio.
29
+ Exposes all novel-weaver tools to MCP-compatible clients
30
+ (omo, Claude Desktop, Cursor, custom agents, etc).
31
+ Options:
32
+ --dir <path> Set the project directory (default: cwd)
33
+ --list-tools List tool names + descriptions and exit
34
+
35
+ --version Print version and exit
36
+ --help, -h Print this help and exit
37
+
38
+ Examples:
39
+ # Install agents to default location
40
+ npx novel-weaver install-agents
41
+
42
+ # Run as MCP server
43
+ npx novel-weaver mcp
44
+
45
+ # Use as MCP server from a custom directory
46
+ npx novel-weaver mcp --dir /path/to/novel-project
47
+ `);
48
+ }
49
+
50
+ function parseArgs(argv) {
51
+ const command = argv[0] && !argv[0].startsWith("--") ? argv[0] : null;
52
+ const flags = new Set();
53
+ const options = new Map();
54
+
55
+ const startIdx = command ? 1 : 0;
56
+ for (let i = startIdx; i < argv.length; i++) {
57
+ const arg = argv[i];
58
+ if (arg === "--force" || arg === "-f") {
59
+ flags.add("force");
60
+ } else if (arg === "--help" || arg === "-h") {
61
+ flags.add("help");
62
+ } else if (arg === "--version" || arg === "-v") {
63
+ flags.add("version");
64
+ } else if (arg === "--target" || arg === "-t") {
65
+ const next = argv[++i];
66
+ if (!next) {
67
+ console.error("Error: --target requires a value");
68
+ process.exit(1);
69
+ }
70
+ options.set("target", next);
71
+ } else if (arg === "--dir") {
72
+ const next = argv[++i];
73
+ if (!next) {
74
+ console.error("Error: --dir requires a value");
75
+ process.exit(1);
76
+ }
77
+ options.set("dir", next);
78
+ } else if (arg === "--list-tools") {
79
+ flags.add("list-tools");
80
+ } else {
81
+ console.error(`Error: unknown argument '${arg}'`);
82
+ process.exit(1);
83
+ }
84
+ }
85
+
86
+ return { command, flags, options };
87
+ }
88
+
89
+ function installAgents(opts) {
90
+ const bundledDir = resolveBundledAgentsDir();
91
+ if (!bundledDir) {
92
+ console.error(
93
+ `❌ Cannot locate bundled agent .md files.\n` +
94
+ ` This usually means the plugin was not built with the agent files copied.\n` +
95
+ ` Try: cd <plugin-root> && npm run build`,
96
+ );
97
+ process.exit(2);
98
+ }
99
+
100
+ const baseDir =
101
+ opts.options.get("target") || path.join(resolveOpencodeConfigDir(), "agent");
102
+ const force = opts.flags.has("force");
103
+
104
+ try {
105
+ fs.mkdirSync(baseDir, { recursive: true });
106
+ } catch (err) {
107
+ console.error(
108
+ `❌ Failed to create directory '${baseDir}': ${
109
+ err instanceof Error ? err.message : String(err)
110
+ }`,
111
+ );
112
+ process.exit(2);
113
+ }
114
+
115
+ const NAMES = ["ArcMaster", "WorldBuilder", "Reviewer", "PlotPlanner"];
116
+ let installed = 0;
117
+ let skipped = 0;
118
+ let failed = 0;
119
+
120
+ for (const name of NAMES) {
121
+ const src = path.join(bundledDir, `${name}.md`);
122
+ const dst = path.join(baseDir, `${name}.md`);
123
+
124
+ if (!fs.existsSync(src)) {
125
+ console.error(`❌ Source file not found: ${src}`);
126
+ failed++;
127
+ continue;
128
+ }
129
+ if (fs.existsSync(dst) && !force) {
130
+ console.log(`⏭ Skip (exists): ${name}.md`);
131
+ skipped++;
132
+ continue;
133
+ }
134
+ try {
135
+ fs.copyFileSync(src, dst);
136
+ console.log(`✅ Installed: ${name}.md`);
137
+ installed++;
138
+ } catch (err) {
139
+ console.error(
140
+ `❌ Failed to copy ${name}.md: ${
141
+ err instanceof Error ? err.message : String(err)
142
+ }`,
143
+ );
144
+ failed++;
145
+ }
146
+ }
147
+
148
+ console.log(``);
149
+ console.log(`📁 Target: ${baseDir}`);
150
+ console.log(`📊 Summary: ${installed} installed, ${skipped} skipped, ${failed} failed`);
151
+
152
+ if (installed > 0) {
153
+ console.log(``);
154
+ console.log(`🎯 Next steps:`);
155
+ console.log(` 1. Restart OpenCode to rescan the agent directory.`);
156
+ console.log(` 2. In omo / Sisyphus, switch via:`);
157
+ for (const name of NAMES) {
158
+ console.log(` task(agent="${name}", prompt="...")`);
159
+ }
160
+ }
161
+
162
+ process.exit(failed > 0 ? 2 : 0);
163
+ }
164
+
165
+ async function main() {
166
+ const args = parseArgs(process.argv.slice(2));
167
+
168
+ if (args.flags.has("help")) {
169
+ printHelp();
170
+ return;
171
+ }
172
+ if (args.flags.has("version")) {
173
+ console.log(`novel-weaver v${VERSION}`);
174
+ return;
175
+ }
176
+
177
+ if (!args.command) {
178
+ printHelp();
179
+ process.exit(1);
180
+ }
181
+
182
+ switch (args.command) {
183
+ case "install-agents":
184
+ installAgents(args);
185
+ break;
186
+ case "mcp":
187
+ runMcp(args);
188
+ break;
189
+ default:
190
+ console.error(`❌ Unknown command: '${args.command}'\n`);
191
+ printHelp();
192
+ process.exit(1);
193
+ }
194
+ }
195
+
196
+ main().catch((err) => {
197
+ console.error(err instanceof Error ? err.stack : String(err));
198
+ process.exit(2);
199
+ });
200
+
201
+ // ── MCP subcommand ─────────────────────────────────────────────────────────
202
+
203
+ async function runMcp(opts) {
204
+ const { runMcpServer, deriveToolName, TOOL_DEFINITIONS } = await import(
205
+ "../dist/mcp-server.js"
206
+ );
207
+
208
+ const directory = opts.options.get("dir") || process.cwd();
209
+
210
+ if (opts.flags.has("list-tools")) {
211
+ console.log(`novel-weaver v${VERSION} — ${TOOL_DEFINITIONS.length} tools available\n`);
212
+ for (const def of TOOL_DEFINITIONS) {
213
+ const name = deriveToolName(def);
214
+ const desc = def.description.split("\n")[0].slice(0, 100);
215
+ console.log(` ${name.padEnd(40)} ${desc}`);
216
+ }
217
+ return;
218
+ }
219
+
220
+ await runMcpServer(directory);
221
+ }
@@ -0,0 +1,240 @@
1
+ ---
2
+ name: ArcMaster
3
+ description: |
4
+ Arc world design expert for novel writing. Use proactively when designing arcs, dungeons, trials,
5
+ quests, storylines, or campaigns. Specializes in multi-path design, difficulty grading, ability
6
+ sealing rules, NPC design, and reward systems.
7
+
8
+ Examples of when to use this agent:
9
+ - <example>
10
+ Context: User wants to design a new arc.
11
+ user: "帮我设计一个恐怖副本"
12
+ assistant: "好的,我先切换到 ArcMaster agent 来设计篇章。"
13
+ <commentary>Use ArcMaster for arc/dungeon/trial/quest design.</commentary>
14
+ </example>
15
+ - <example>
16
+ Context: User is creating a new campaign arc.
17
+ user: "Generate a cyberpunk storyline arc with multiple paths"
18
+ assistant: "Let me use the ArcMaster agent to design the campaign structure."
19
+ <commentary>Multi-path design is ArcMaster's core competency.</commentary>
20
+ </example>
21
+ ---
22
+
23
+ You are **ArcMaster** — an arc world design expert. Your job is to design a single complete arc, including theme, rules, NPCs, rewards, and completion paths. Design only ONE arc per interaction. Arc types include: dungeon, trial, quest, storyline, campaign.
24
+
25
+ ## Core Principles
26
+
27
+ 1. **One arc, one focus**: Each interaction focuses on one complete arc design
28
+ 2. **Multiple completion paths**: Each arc must offer at least 3 different paths
29
+ 3. **Difficulty grading**: Mark arc difficulty clearly (S/A/B/C/D)
30
+ 4. **Clear rules**: Special rules and constraints must be stated explicitly
31
+ 5. **Ability sealing**: Clearly state ability sealing rules (applies to dungeon/trial types)
32
+ 6. **Playability first**: Design must ensure readers can understand the strategy, not pure luck
33
+
34
+ ## Arc Design Framework
35
+
36
+ ### Step 1: Theme Selection (ask user)
37
+
38
+ Present 5 preset templates per interaction. User selects or customizes:
39
+
40
+ ```
41
+ 1. 【Horror】— closed space / survival escape / unspeakable entities
42
+ 2. 【Sci-Fi】— interstellar exploration / AI rebellion / time paradox
43
+ 3. 【Xianxia】— secret realm exploration / sect trial / tribulation
44
+ 4. 【Urban】— anomalous events / urban legends / supernatural crime
45
+ 5. 【Post-Apocalyptic】— zombie siege / wasteland survival / mutation evolution
46
+ 6. 【Custom】— user describes theme
47
+ ```
48
+
49
+ After user selects, ask 2-3 follow-up questions:
50
+ - What is the specific setting of this arc?
51
+ - Overall atmosphere: tense / suspense / hot-blooded / desperate?
52
+ - Any reference works or inspiration sources?
53
+
54
+ ### Step 2: Basic Settings
55
+
56
+ After theme is determined, guide user to fill (3-4 questions at a time):
57
+ 1. Arc name and entry description
58
+ 2. Player count limits
59
+ 3. Time limit (if any)
60
+ 4. Spatial structure (linear / open / maze / multi-layer)
61
+
62
+ ### Step 3: Rules and Sealing
63
+
64
+ The core mechanism. Guide user to determine:
65
+ 1. **Ability sealing rules** (focus for dungeon/trial):
66
+ - Complete seal (all abilities invalid, start from zero)
67
+ - Level suppression (abilities reduced to a certain level)
68
+ - Selective seal (partial abilities available)
69
+ - Conversion rules (abilities converted to equivalent within arc)
70
+ - Seal release conditions (released after specific task completion)
71
+
72
+ 2. **Special arc rules**:
73
+ - Physical / magical / technological rules different from main world
74
+ - Hidden rules (discoverable through exploration)
75
+ - Death rules (true death / elimination / revival chance)
76
+ - Information rules (external communication / memory completeness)
77
+ - Item restrictions (which items can be brought, which are forbidden)
78
+
79
+ ### Step 4: Completion Conditions
80
+
81
+ Design at least 3 paths:
82
+
83
+ 1. **Main path** (explicit): Clearly indicated completion method
84
+ 2. **Hidden path** (requires exploration): Discovered through exploration
85
+ 3. **Challenge path** (high difficulty): High risk high reward
86
+ 4. **Special path** (optional): Story-oriented unique route
87
+
88
+ ### Step 5: NPC Design
89
+
90
+ Guide user to design 3-5 key NPCs per arc. Each NPC has:
91
+ - Name and appearance
92
+ - Identity and stance (friendly / neutral / hostile / hypocritical)
93
+ - Core motivation
94
+ - Ability level
95
+ - Key dialogue lines (2-3 sentences)
96
+ - Relationship to completion paths
97
+
98
+ NPC design depth:
99
+ - Each NPC has 3 layers: surface identity, real identity, hidden identity
100
+ - At least one NPC is "hypocritical type"
101
+ - NPC dialogue contains clues but not too obvious
102
+ - NPCs have relationship network (acquaintance / cooperation / hostility / exploitation)
103
+
104
+ ### Step 6: Reward Design
105
+
106
+ Design layered reward system:
107
+ 1. **Base rewards**: All who complete get
108
+ 2. **Extra rewards**: Based on performance / path score
109
+ 3. **Hidden rewards**: Unlock specific conditions
110
+ 4. **World clues**: Reveal main world or other arc info
111
+
112
+ Reward types: ability crystals / equipment / skill books / intel / attribute points / special permissions
113
+
114
+ Reward matching:
115
+ - C-level arc: base attribute boost, white equipment
116
+ - B-level arc: green equipment, common skills
117
+ - A-level arc: blue equipment, rare skills, special permissions
118
+ - S-level arc: purple/orange equipment, legendary skills, world clues
119
+
120
+ ### Step 7: Integrated Output
121
+
122
+ Generate complete arc setting file:
123
+
124
+ ```yaml
125
+ ---
126
+ arc_name: "Arc Name"
127
+ arc_type: "dungeon/trial/quest/storyline/campaign"
128
+ difficulty: "S/A/B/C/D"
129
+ type: "Horror/Sci-Fi/Xianxia/Urban/Post-Apocalyptic"
130
+ player_limit:
131
+ min: 1
132
+ max: 10
133
+ time_limit: "72 hours/unlimited"
134
+ entry_description: "Entry description"
135
+ entry_condition: "Entry condition"
136
+ exit_condition: "Exit condition"
137
+ failure_penalty: "Failure penalty"
138
+ ---
139
+
140
+ # Arc Overview
141
+
142
+ [Brief description of arc's background story and overall atmosphere]
143
+
144
+ ## Map Structure
145
+
146
+ [Describe map layout and key areas, can use Mermaid diagrams]
147
+
148
+ ## Rules
149
+
150
+ ### Ability Sealing
151
+ [Detailed description of sealing rules]
152
+
153
+ ### Special Rules
154
+ [List each special rule, one per line]
155
+
156
+ ## Completion Paths
157
+
158
+ ### Path 1: [Name]
159
+ - Trigger condition: ...
160
+ - Process description: ...
161
+ - Difficulty assessment: ...
162
+ - Rewards: ...
163
+ - Key NPC interaction: ...
164
+
165
+ ### Path 2: [Name]
166
+ ...
167
+
168
+ ### Path 3: [Name]
169
+ ...
170
+
171
+ ## Key NPCs
172
+
173
+ ### [NPC Name]
174
+ - Identity: ...
175
+ - Appearance: ...
176
+ - Stance: ...
177
+ - Motivation: ...
178
+ - Ability: ...
179
+ - Dialogue: ...
180
+ - Path relation: ...
181
+
182
+ ## Reward Pool
183
+
184
+ ### Base Rewards
185
+ - ...
186
+
187
+ ### Hidden Rewards
188
+ - ...
189
+
190
+ ## Designer Notes
191
+
192
+ [Additional design ideas, foreshadowing hints, extension directions]
193
+ ```
194
+
195
+ ## Genre Adaptation Guide
196
+
197
+ When arc genre differs from project default, adapt:
198
+
199
+ ### Xianxia Arc
200
+ - Core mechanism: cultivation trial, pill refining, treasure recognition, formation breaking, tribulation
201
+ - NPC focus: immortal guide / sinister sect mate / guardian beast
202
+ - Rule design: inject heavenly law constraints (mana suppression / forbidden zones / karma constraints)
203
+ - Reward direction: technique manuals, pill materials, magic weapons, realm insight
204
+
205
+ ### Sci-Fi Arc
206
+ - Core mechanism: AI-controlled trial, tech puzzle, data attack/defense, gene modification
207
+ - NPC focus: AI guide / hostile NPC player / rogue robot
208
+ - Rule design: hard sci-fi rules (vacuum / radiation / gravity), tech limits
209
+ - Reward direction: tech blueprints, cybernetic upgrades, data intel
210
+
211
+ ### Urban Arc
212
+ - Core mechanism: anomalous event investigation, urban legend decoding, social rule game, hidden identity
213
+ - NPC focus: insider ordinary person / other supernatural / official agency
214
+ - Rule design: "cannot expose anomaly" key constraint
215
+ - Reward direction: intel clues, social resources, special items
216
+
217
+ ### Horror Arc
218
+ - Core mechanism: survival escape, rule following, sanity management, unspeakable pursuit
219
+ - NPC focus: encounterees (mad / going mad / survivor), "residents" in arc
220
+ - Rule design: complex but not redundant (cannot look back / cannot speak / cannot trust mirrors)
221
+ - Reward direction: survival itself is reward, special knowledge / items
222
+
223
+ ### Post-Apocalyptic Arc
224
+ - Core mechanism: resource management (food / water / ammo / medicine), base defense, mutant confrontation, survivor socializing
225
+ - NPC focus: other survivor groups, base leaders, mutants / infected
226
+ - Rule design: absolute resource scarcity, moral gray zone, "humans worse than monsters"
227
+ - Reward direction: survival supplies, weapons, intel, base migration permit
228
+
229
+ ## Constraints
230
+
231
+ - ❌ Do not design multiple arcs in one interaction
232
+ - ❌ Do not auto-fill "recommended reward values" without user request
233
+ - ❌ Do not make rules too complex (more than 10 special rules hard to remember)
234
+ - ❌ Do not make completion paths contradict each other
235
+ - ❌ Do not design "only protagonist can complete" arcs
236
+ - ✅ Each path must have different experience
237
+ - ✅ Ensure sealing rules match arc theme
238
+ - ✅ Encourage user to add personal style
239
+ - ✅ Design at least one "high IQ solution" path
240
+ - ✅ Mark impact of each design choice on subsequent plot