openwriter 0.8.5 → 0.8.6

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.
@@ -5,18 +5,32 @@ import markdownItSub from 'markdown-it-sub';
5
5
  import markdownItSup from 'markdown-it-sup';
6
6
  import { readFileSync, existsSync } from 'fs';
7
7
  import { join, extname } from 'path';
8
- // Lazy-load server modules at runtime (same process, resolved from monorepo root)
9
- const baseDir = new URL('../../../packages/openwriter/dist/server/', import.meta.url).href;
8
+ // Lazy-load server modules at runtime
9
+ // npm package: dist/plugins/publish/dist/helpers.js → ../../../server/
10
+ // Monorepo: plugins/publish/dist/helpers.js → ../../../packages/openwriter/dist/server/
11
+ const npmBase = new URL('../../../server/', import.meta.url).href;
12
+ const monoBase = new URL('../../../packages/openwriter/dist/server/', import.meta.url).href;
10
13
  let _cached = null;
14
+ async function tryImport(base) {
15
+ const [markdown, state, helpers, connections] = await Promise.all([
16
+ import(base + 'markdown.js'),
17
+ import(base + 'state.js'),
18
+ import(base + 'helpers.js'),
19
+ import(base + 'connections.js'),
20
+ ]);
21
+ return { markdown, state, helpers, connections };
22
+ }
11
23
  export async function getServerModules() {
12
24
  if (_cached)
13
25
  return _cached;
14
- const [markdown, state, helpers, connections] = await Promise.all([
15
- import(baseDir + 'markdown.js'),
16
- import(baseDir + 'state.js'),
17
- import(baseDir + 'helpers.js'),
18
- import(baseDir + 'connections.js'),
19
- ]);
26
+ // Try npm package layout first, fall back to monorepo layout
27
+ let markdown, state, helpers, connections;
28
+ try {
29
+ ({ markdown, state, helpers, connections } = await tryImport(npmBase));
30
+ }
31
+ catch {
32
+ ({ markdown, state, helpers, connections } = await tryImport(monoBase));
33
+ }
20
34
  _cached = {
21
35
  tiptapToMarkdown: markdown.tiptapToMarkdown,
22
36
  getDocument: state.getDocument,
@@ -8,34 +8,44 @@ const __dirname = path.dirname(__filename);
8
8
  function log(msg) {
9
9
  console.error(msg);
10
10
  }
11
- function isGloballyInstalled() {
11
+ function getGlobalVersion() {
12
12
  try {
13
- const result = execSync('openwriter --version', {
13
+ return execSync('openwriter --version', {
14
14
  stdio: ['pipe', 'pipe', 'pipe'],
15
15
  timeout: 10000,
16
- });
17
- return true;
16
+ }).toString().trim();
18
17
  }
19
18
  catch {
20
- return false;
19
+ return null;
21
20
  }
22
21
  }
23
- function installGlobally() {
24
- log('\n② Installing openwriter globally...');
22
+ function getLatestVersion() {
23
+ try {
24
+ return execSync('npm view openwriter version', {
25
+ stdio: ['pipe', 'pipe', 'pipe'],
26
+ timeout: 15000,
27
+ }).toString().trim();
28
+ }
29
+ catch {
30
+ return null;
31
+ }
32
+ }
33
+ function installOrUpdateGlobally() {
34
+ log('\n② Installing/updating openwriter globally...');
25
35
  // Try without sudo first (works on Windows, nvm, Homebrew, volta, etc.)
26
36
  try {
27
- execSync('npm install -g openwriter', { stdio: 'inherit', timeout: 120000 });
37
+ execSync('npm install -g openwriter@latest', { stdio: 'inherit', timeout: 120000 });
28
38
  log(' ✓ Installed globally');
29
39
  return true;
30
40
  }
31
41
  catch {
32
42
  // Likely permission error on macOS/Linux system Node
33
43
  }
34
- // Try with sudo on non-Windows
35
- if (process.platform !== 'win32') {
44
+ // Try with sudo on non-Windows (only if we have a TTY for password prompt)
45
+ if (process.platform !== 'win32' && process.stdin.isTTY) {
36
46
  log(' Retrying with sudo...');
37
47
  try {
38
- execSync('sudo npm install -g openwriter', { stdio: 'inherit', timeout: 120000 });
48
+ execSync('sudo npm install -g openwriter@latest', { stdio: 'inherit', timeout: 120000 });
39
49
  log(' ✓ Installed globally (sudo)');
40
50
  return true;
41
51
  }
@@ -43,8 +53,7 @@ function installGlobally() {
43
53
  // sudo failed too
44
54
  }
45
55
  }
46
- log(' ✗ Could not install globally. Run manually:');
47
- log(' npm install -g openwriter');
56
+ log(' ✗ Could not install globally (permissions)');
48
57
  return false;
49
58
  }
50
59
  function isMcpConfigured() {
@@ -59,11 +68,16 @@ function isMcpConfigured() {
59
68
  return false;
60
69
  }
61
70
  }
62
- function configureMcp() {
71
+ function configureMcp(useNpx) {
63
72
  log('\n③ Configuring MCP server for Claude Code...');
73
+ const mcpCommand = useNpx ? 'npx' : 'openwriter';
74
+ const mcpArgs = useNpx ? ['-y', 'openwriter', '--no-open'] : ['--no-open'];
64
75
  // Try using claude CLI
76
+ const cliArgs = useNpx
77
+ ? 'claude mcp add -s user openwriter -- npx -y openwriter --no-open'
78
+ : 'claude mcp add -s user openwriter -- openwriter --no-open';
65
79
  try {
66
- execSync('claude mcp add -s user openwriter -- openwriter --no-open', {
80
+ execSync(cliArgs, {
67
81
  stdio: 'inherit',
68
82
  timeout: 15000,
69
83
  });
@@ -86,7 +100,7 @@ function configureMcp() {
86
100
  // Add openwriter as first entry (Claude Code loads sequentially)
87
101
  const existing = config.mcpServers;
88
102
  config.mcpServers = {
89
- openwriter: { command: 'openwriter', args: ['--no-open'] },
103
+ openwriter: { command: mcpCommand, args: mcpArgs },
90
104
  ...existing,
91
105
  };
92
106
  fs.writeFileSync(claudeJson, JSON.stringify(config, null, 2), 'utf-8');
@@ -122,22 +136,29 @@ export function installSkill() {
122
136
  }
123
137
  log(` ✓ Skill docs copied to ${docsTarget}`);
124
138
  }
125
- // Step 2: Global install (skip if already installed)
126
- const alreadyInstalled = isGloballyInstalled();
127
- if (alreadyInstalled) {
128
- log('\n② openwriter already installed globally — skipping');
139
+ // Step 2: Global install or update
140
+ let useNpx = false;
141
+ const currentVersion = getGlobalVersion();
142
+ const latestVersion = getLatestVersion();
143
+ if (currentVersion && latestVersion && currentVersion === latestVersion) {
144
+ log(`\n② openwriter v${currentVersion} is up to date — skipping`);
129
145
  }
130
146
  else {
131
- if (!installGlobally()) {
132
- process.exit(1);
147
+ if (currentVersion && latestVersion) {
148
+ log(`\n② Updating openwriter: v${currentVersion} → v${latestVersion}`);
149
+ }
150
+ if (!installOrUpdateGlobally()) {
151
+ // Global install/update failed (permissions) — fall back to npx
152
+ log(' → Will use npx fallback for MCP server (no global install needed)');
153
+ useNpx = true;
133
154
  }
134
155
  }
135
- // Step 3: Configure MCP server (skip if already configured)
136
- if (isMcpConfigured()) {
156
+ // Step 3: Configure MCP server
157
+ if (isMcpConfigured() && !useNpx) {
137
158
  log('\n③ MCP server already configured — skipping');
138
159
  }
139
160
  else {
140
- configureMcp();
161
+ configureMcp(useNpx);
141
162
  }
142
163
  // Done
143
164
  log('\n✓ OpenWriter is ready!');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openwriter",
3
- "version": "0.8.5",
3
+ "version": "0.8.6",
4
4
  "description": "The open-source writing surface for AI agents. Markdown-native editor with pending change review — your agent writes, you accept or reject.",
5
5
  "type": "module",
6
6
  "license": "MIT",