gm-plugkit 2.0.1124 → 2.0.1126

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/bootstrap.js CHANGED
@@ -190,6 +190,49 @@ async function extractNpmPackageWasm(destPath, version) {
190
190
  }
191
191
  }
192
192
 
193
+ function httpGetBuffer(url, timeoutMs) {
194
+ const https = require('https');
195
+ return new Promise((resolve, reject) => {
196
+ const req = https.get(url, { timeout: timeoutMs || 30000, headers: { 'user-agent': 'gm-plugkit-bootstrap' } }, (res) => {
197
+ if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
198
+ res.resume();
199
+ httpGetBuffer(res.headers.location, timeoutMs).then(resolve, reject);
200
+ return;
201
+ }
202
+ if (res.statusCode !== 200) {
203
+ res.resume();
204
+ reject(new Error(`HTTP ${res.statusCode} ${url}`));
205
+ return;
206
+ }
207
+ const chunks = [];
208
+ res.on('data', c => chunks.push(c));
209
+ res.on('end', () => resolve(Buffer.concat(chunks)));
210
+ res.on('error', reject);
211
+ });
212
+ req.on('timeout', () => req.destroy(new Error(`timeout ${url}`)));
213
+ req.on('error', reject);
214
+ });
215
+ }
216
+
217
+ async function downloadFromGithubReleases(destPath, version) {
218
+ const base = `https://github.com/AnEntrypoint/plugkit-bin/releases/download/v${version}`;
219
+ log(`gh-releases download: ${base}/plugkit.wasm`);
220
+ const buf = await httpGetBuffer(`${base}/plugkit.wasm`, 60000);
221
+ if (!buf || buf.length < 1024) throw new Error(`gh-releases download too small: ${buf ? buf.length : 0} bytes`);
222
+ let remoteSha = '';
223
+ try {
224
+ const shaBuf = await httpGetBuffer(`${base}/plugkit.wasm.sha256`, 10000);
225
+ remoteSha = shaBuf.toString('utf-8').trim().split(/\s+/)[0];
226
+ } catch (e) { log(`gh-releases sha fetch failed: ${e.message}`); }
227
+ if (remoteSha) {
228
+ const got = require('crypto').createHash('sha256').update(buf).digest('hex');
229
+ if (got !== remoteSha) throw new Error(`gh-releases sha mismatch: got ${got}, expected ${remoteSha}`);
230
+ log(`gh-releases sha verified ${got.slice(0, 16)}...`);
231
+ }
232
+ fs.writeFileSync(destPath, buf);
233
+ log(`gh-releases wrote ${buf.length} bytes to ${destPath}`);
234
+ }
235
+
193
236
  async function extractNpmPackageWithRetry(destPath, version) {
194
237
  let lastErr;
195
238
  for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
@@ -547,12 +590,17 @@ async function bootstrap(opts) {
547
590
  try {
548
591
  await extractNpmPackageWithRetry(partialPath, version);
549
592
  } catch (extractErr) {
550
- writeBootstrapError({
551
- expected_version: version, cached_version: null,
552
- error_phase: 'npm-extract',
553
- error_message: extractErr && extractErr.message ? extractErr.message : String(extractErr),
554
- });
555
- throw extractErr;
593
+ log(`npm-extract failed (${extractErr.message || extractErr}); falling back to GitHub Releases`);
594
+ try {
595
+ await downloadFromGithubReleases(partialPath, version);
596
+ } catch (ghErr) {
597
+ writeBootstrapError({
598
+ expected_version: version, cached_version: null,
599
+ error_phase: 'npm-extract+gh-fallback',
600
+ error_message: `npm: ${extractErr.message}; gh: ${ghErr.message}`,
601
+ });
602
+ throw ghErr;
603
+ }
556
604
  }
557
605
 
558
606
  if (expectedSha) {
@@ -634,18 +682,143 @@ function isReady() {
634
682
  return fs.existsSync(wasm);
635
683
  }
636
684
 
637
- async function ensureReady() {
638
- if (isReady()) {
639
- return { ok: true, wasmPath: getWasmPath(), status: 'already-ready' };
685
+ function ensureWrapperFresh() {
686
+ try {
687
+ const wrapperSrc = path.join(__dirname, 'plugkit-wasm-wrapper.js');
688
+ const wrapperDst = path.join(gmToolsDir(), 'plugkit-wasm-wrapper.js');
689
+ if (!fs.existsSync(wrapperSrc)) return false;
690
+ let same = false;
691
+ if (fs.existsSync(wrapperDst)) {
692
+ try {
693
+ const a = sha256OfFileSync(wrapperSrc);
694
+ const b = sha256OfFileSync(wrapperDst);
695
+ if (a === b) same = true;
696
+ } catch (_) {}
697
+ }
698
+ if (!same) {
699
+ fs.mkdirSync(gmToolsDir(), { recursive: true });
700
+ fs.copyFileSync(wrapperSrc, wrapperDst);
701
+ return true;
702
+ }
703
+ return false;
704
+ } catch (_) { return false; }
705
+ }
706
+
707
+ function installedVersionAtTools() {
708
+ try {
709
+ const p = path.join(gmToolsDir(), 'plugkit.version');
710
+ if (!fs.existsSync(p)) return null;
711
+ return fs.readFileSync(p, 'utf-8').trim();
712
+ } catch (_) { return null; }
713
+ }
714
+
715
+ async function resolveLatestRemoteVersion(timeoutMs) {
716
+ try {
717
+ const buf = await httpGetBuffer('https://api.github.com/repos/AnEntrypoint/plugkit-bin/releases?per_page=50', timeoutMs || 3000);
718
+ const releases = JSON.parse(buf.toString('utf-8'));
719
+ if (!Array.isArray(releases)) return null;
720
+ for (const rel of releases) {
721
+ const tag = rel && rel.tag_name;
722
+ if (!tag) continue;
723
+ const m = /^v(\d+\.\d+\.\d+(?:-[A-Za-z0-9.]+)?)$/.exec(tag);
724
+ if (!m) continue;
725
+ const hasPlugkitWasm = Array.isArray(rel.assets) && rel.assets.some(a => a && a.name === 'plugkit.wasm');
726
+ if (hasPlugkitWasm) return m[1];
727
+ }
728
+ } catch (_) {}
729
+ return null;
730
+ }
731
+
732
+ async function ensureReady(opts) {
733
+ opts = opts || {};
734
+ const offline = opts.offline === true;
735
+ let pinnedVersion = null;
736
+ try { pinnedVersion = readVersionFile(); } catch (_) {}
737
+ let targetVersion = pinnedVersion;
738
+ if (!offline) {
739
+ const latest = await resolveLatestRemoteVersion(3000);
740
+ if (latest) targetVersion = latest;
741
+ }
742
+ if (!targetVersion) targetVersion = pinnedVersion;
743
+
744
+ const installed = installedVersionAtTools();
745
+ const versionDrift = targetVersion && installed && installed !== targetVersion;
746
+
747
+ if (isReady() && !versionDrift) {
748
+ const wasmPath = getWasmPath();
749
+ const wrapperUpdated = ensureWrapperFresh();
750
+ return { ok: true, wasmPath, binaryPath: wasmPath, status: wrapperUpdated ? 'wrapper-refreshed' : 'already-ready', version: installed };
751
+ }
752
+ if (versionDrift) {
753
+ try { killRunningDaemons(`version_drift:${installed}->${targetVersion}`); } catch (_) {}
754
+ }
755
+
756
+ if (targetVersion && targetVersion !== pinnedVersion) {
757
+ try {
758
+ const verFilePath = path.join(wrapperDir, 'plugkit.version');
759
+ fs.writeFileSync(verFilePath, targetVersion + '\n');
760
+ log(`overrode bundled plugkit.version: ${pinnedVersion} -> ${targetVersion} (remote latest)`);
761
+ } catch (e) { log(`could not override plugkit.version: ${e.message}`); }
640
762
  }
763
+
641
764
  const wasmPath = await bootstrap();
642
- return { ok: true, wasmPath, status: 'bootstrapped' };
765
+ ensureWrapperFresh();
766
+ return { ok: true, wasmPath, binaryPath: wasmPath, status: 'bootstrapped', version: targetVersion || installed };
767
+ }
768
+
769
+ function getBinaryPath() {
770
+ return getWasmPath();
771
+ }
772
+
773
+ function startSpoolDaemon() {
774
+ try {
775
+ const wrapper = path.join(gmToolsDir(), 'plugkit-wasm-wrapper.js');
776
+ if (!fs.existsSync(wrapper)) {
777
+ return { ok: false, error: `wrapper not at ${wrapper} — ensureReady() must run first` };
778
+ }
779
+ const runtime = process.platform === 'win32' ? 'bun.exe' : 'bun';
780
+ let cmd = runtime;
781
+ let args = [wrapper, 'spool'];
782
+ try {
783
+ require('child_process').execFileSync(runtime, ['--version'], { stdio: 'ignore' });
784
+ } catch (_) {
785
+ cmd = process.execPath;
786
+ args = [wrapper, 'spool'];
787
+ }
788
+ const projectDir = process.env.CLAUDE_PROJECT_DIR || process.cwd();
789
+ const spoolDir = path.join(projectDir, '.gm', 'exec-spool');
790
+ fs.mkdirSync(spoolDir, { recursive: true });
791
+ const logPath = path.join(spoolDir, '.watcher.log');
792
+ try {
793
+ const stat = fs.statSync(logPath);
794
+ if (stat.size > 10 * 1024 * 1024) {
795
+ try { fs.unlinkSync(path.join(spoolDir, '.watcher.log.1')); } catch (_) {}
796
+ fs.renameSync(logPath, path.join(spoolDir, '.watcher.log.1'));
797
+ }
798
+ } catch (_) {}
799
+ const logFd = fs.openSync(logPath, 'a');
800
+ try { fs.writeSync(logFd, `\n--- daemon spawn ${new Date().toISOString()} parent=${process.pid} ---\n`); } catch (_) {}
801
+ const child = require('child_process').spawn(cmd, args, {
802
+ detached: true,
803
+ stdio: ['ignore', logFd, logFd],
804
+ windowsHide: true,
805
+ env: { ...process.env, CLAUDE_PROJECT_DIR: projectDir },
806
+ });
807
+ try { fs.closeSync(logFd); } catch (_) {}
808
+ const pid = child.pid;
809
+ child.unref();
810
+ return { ok: true, pid, wrapper, runtime: cmd, logPath };
811
+ } catch (e) {
812
+ return { ok: false, error: e.message };
813
+ }
643
814
  }
644
815
 
645
816
  module.exports = {
646
817
  bootstrap,
647
818
  ensureReady,
648
819
  getWasmPath,
820
+ getBinaryPath,
821
+ startSpoolDaemon,
649
822
  isReady,
650
823
  rtkBinaryName,
651
824
  cacheRoot,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-plugkit",
3
- "version": "2.0.1124",
3
+ "version": "2.0.1126",
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": {
package/plugkit.sha256 CHANGED
@@ -1,6 +1 @@
1
- e5569efe81e4ef06c8349678253ca2845571495e619babb0a79be9268ea83c2a plugkit-win32-x64.exe
2
- ce2f09f8ea0dd522345a9d9c3e5b04ba44bc37b2046d311d7ff1737f1b3fbf1a plugkit-win32-arm64.exe
3
- a1a1d376986551828e5a39e4ae931accf66f00663aceac1439b2778cb4fffd27 plugkit-darwin-x64
4
- 7c36d730edab5cddf678211146ca670c9ce1def17d8b454234ce4bc04a4d7e85 plugkit-darwin-arm64
5
- c9db60a399caf53c490dc08705713c7d83a1f62db057585a3950d64ab8fa449a plugkit-linux-x64
6
- b9ebabaace995b1768d1d96ae13ca18a6dc5e2ca65b774fcdd457f069a7d115c plugkit-linux-arm64
1
+ {"plugkit.wasm":"874f5a3524d8a080a2880567cc3808ae727f4c2b4f35ad6fc33e932fd6c4c567"}
package/plugkit.version CHANGED
@@ -1 +1 @@
1
- 0.1.366
1
+ 0.1.396