gm-plugkit 2.0.1217 → 2.0.1218

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-plugkit",
3
- "version": "2.0.1217",
3
+ "version": "2.0.1218",
4
4
  "description": "Bootstrap and daemon-spawn tool for gm plugkit binary. Downloads the correct platform binary, verifies SHA256, and starts the spool watcher daemon. Includes plugkit-wasm-wrapper for WASM-based spool watching.",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -70,6 +70,32 @@ function isSpoolPollCommand(command) {
70
70
  return null;
71
71
  }
72
72
 
73
+ function isBrowserRunningFileLocal(rel) {
74
+ if (!rel) return false;
75
+ const norm = String(rel).replace(/\\\\/g, '/');
76
+ if (/\\.(html?|tsx|jsx|vue|svelte)$/i.test(norm)) return true;
77
+ if (/\\.(mjs|cjs|js|ts|css|scss|sass)$/i.test(norm) && /^(src|public|site|app|pages|components|client|web)\\//i.test(norm)) return true;
78
+ return false;
79
+ }
80
+
81
+ function recordBrowserEditLocal(cwd, filePath) {
82
+ try {
83
+ const fs = require('fs');
84
+ const path = require('path');
85
+ let rel = filePath;
86
+ try { rel = path.relative(cwd, filePath); } catch (_) {}
87
+ if (!isBrowserRunningFileLocal(rel)) return false;
88
+ const editsFile = path.join(cwd, '.gm', 'exec-spool', '.turn-browser-edits.json');
89
+ fs.mkdirSync(path.dirname(editsFile), { recursive: true });
90
+ let list = [];
91
+ try { list = JSON.parse(fs.readFileSync(editsFile, 'utf8')); if (!Array.isArray(list)) list = []; } catch (_) {}
92
+ const entry = { file: rel.replace(/\\\\/g, '/'), ts: Date.now() };
93
+ if (!list.some(e => e && e.file === entry.file)) list.push(entry);
94
+ fs.writeFileSync(editsFile, JSON.stringify(list));
95
+ return true;
96
+ } catch (_) { return false; }
97
+ }
98
+
73
99
  let raw = '';
74
100
  process.stdin.setEncoding('utf8');
75
101
  process.stdin.on('data', (chunk) => { raw += chunk; });
@@ -78,6 +104,17 @@ process.stdin.on('end', () => {
78
104
  try { event = JSON.parse(raw || '{}'); } catch (_) { event = {}; }
79
105
  const tool = event.tool_name || event.tool || '';
80
106
  const input = event.tool_input || event.input || {};
107
+ const cwd = event.cwd || process.env.CLAUDE_PROJECT_DIR || process.cwd();
108
+
109
+ if (tool === 'Write' || tool === 'Edit' || tool === 'MultiEdit') {
110
+ const fp = input.file_path || input.filePath || input.path || '';
111
+ if (fp) {
112
+ try { recordBrowserEditLocal(cwd, fp); } catch (_) {}
113
+ }
114
+ process.stdout.write(JSON.stringify({ continue: true }));
115
+ process.exit(0);
116
+ }
117
+
81
118
  if (tool !== 'Bash') {
82
119
  process.stdout.write(JSON.stringify({ continue: true }));
83
120
  process.exit(0);
@@ -165,15 +202,17 @@ function ensureSpoolPollGate(cwd) {
165
202
  if (!settings.hooks || typeof settings.hooks !== 'object') settings.hooks = {};
166
203
  if (!Array.isArray(settings.hooks.PreToolUse)) settings.hooks.PreToolUse = [];
167
204
  const wantCommand = `node "\${CLAUDE_PROJECT_DIR}/.gm/hooks/spool-poll-gate.js"`;
168
- let bashEntry = settings.hooks.PreToolUse.find(e => e && e.matcher === 'Bash');
169
- if (!bashEntry) {
170
- bashEntry = { matcher: 'Bash', hooks: [] };
171
- settings.hooks.PreToolUse.push(bashEntry);
172
- }
173
- if (!Array.isArray(bashEntry.hooks)) bashEntry.hooks = [];
174
- const already = bashEntry.hooks.some(h => h && typeof h.command === 'string' && h.command.includes('spool-poll-gate.js'));
175
- if (!already) {
176
- bashEntry.hooks.push({ type: 'command', command: wantCommand });
205
+ for (const matcher of ['Bash', 'Write', 'Edit', 'MultiEdit']) {
206
+ let entry = settings.hooks.PreToolUse.find(e => e && e.matcher === matcher);
207
+ if (!entry) {
208
+ entry = { matcher, hooks: [] };
209
+ settings.hooks.PreToolUse.push(entry);
210
+ }
211
+ if (!Array.isArray(entry.hooks)) entry.hooks = [];
212
+ const already = entry.hooks.some(h => h && typeof h.command === 'string' && h.command.includes('spool-poll-gate.js'));
213
+ if (!already) {
214
+ entry.hooks.push({ type: 'command', command: wantCommand });
215
+ }
177
216
  }
178
217
  fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n');
179
218
  } catch (_) {}