gm-skill 2.0.1269 → 2.0.1271
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/README.md +1 -1
- package/gm-plugkit/plugkit-wasm-wrapper.js +132 -158
- package/gm.json +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -35,7 +35,7 @@ An earlier generation fanned out fifteen per-platform downstream repos (gm-cc, g
|
|
|
35
35
|
|
|
36
36
|
## Version
|
|
37
37
|
|
|
38
|
-
`2.0.
|
|
38
|
+
`2.0.1271` — auto-bumped from the canonical `gm` repo. Every push to `AnEntrypoint/gm` (or any cascading sibling crate) republishes this package.
|
|
39
39
|
|
|
40
40
|
## Source of truth
|
|
41
41
|
|
|
@@ -420,106 +420,6 @@ function writeJsonFile(fp, value) {
|
|
|
420
420
|
try { fs.writeFileSync(fp, JSON.stringify(value, null, 2)); } catch (_) {}
|
|
421
421
|
}
|
|
422
422
|
|
|
423
|
-
function bundledBrowserCacheRoots() {
|
|
424
|
-
const roots = [];
|
|
425
|
-
const envOverride = process.env.PLAYWRIGHT_BROWSERS_PATH;
|
|
426
|
-
if (envOverride) roots.push(envOverride);
|
|
427
|
-
if (process.platform === 'win32') {
|
|
428
|
-
if (process.env.LOCALAPPDATA) roots.push(path.join(process.env.LOCALAPPDATA, 'ms-playwright'));
|
|
429
|
-
} else if (process.platform === 'darwin') {
|
|
430
|
-
if (process.env.HOME) roots.push(path.join(process.env.HOME, 'Library', 'Caches', 'ms-playwright'));
|
|
431
|
-
} else {
|
|
432
|
-
if (process.env.HOME) roots.push(path.join(process.env.HOME, '.cache', 'ms-playwright'));
|
|
433
|
-
}
|
|
434
|
-
return roots.filter(r => r && fs.existsSync(r));
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
function chromiumExeFromCacheRoot(root) {
|
|
438
|
-
try {
|
|
439
|
-
const entries = fs.readdirSync(root)
|
|
440
|
-
.filter(n => /^chromium-\d+$/.test(n))
|
|
441
|
-
.sort((a, b) => parseInt(b.split('-')[1], 10) - parseInt(a.split('-')[1], 10));
|
|
442
|
-
const subdirs = process.platform === 'win32'
|
|
443
|
-
? ['chrome-win64', 'chrome-win']
|
|
444
|
-
: process.platform === 'darwin'
|
|
445
|
-
? ['chrome-mac/Chromium.app/Contents/MacOS/Chromium']
|
|
446
|
-
: ['chrome-linux'];
|
|
447
|
-
const exeName = process.platform === 'win32' ? 'chrome.exe'
|
|
448
|
-
: process.platform === 'darwin' ? null
|
|
449
|
-
: 'chrome';
|
|
450
|
-
for (const e of entries) {
|
|
451
|
-
for (const sub of subdirs) {
|
|
452
|
-
const p = exeName ? path.join(root, e, sub, exeName) : path.join(root, e, sub);
|
|
453
|
-
if (fs.existsSync(p)) return p;
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
} catch (_) {}
|
|
457
|
-
return null;
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
function findBundledChromium() {
|
|
461
|
-
for (const root of bundledBrowserCacheRoots()) {
|
|
462
|
-
const exe = chromiumExeFromCacheRoot(root);
|
|
463
|
-
if (exe) return exe;
|
|
464
|
-
}
|
|
465
|
-
try {
|
|
466
|
-
const npmR = spawnSync('npm', ['root', '-g'], { encoding: 'utf-8', shell: true, windowsHide: true, timeout: 5000 });
|
|
467
|
-
if (npmR.status === 0 && npmR.stdout.trim()) {
|
|
468
|
-
const root = npmR.stdout.trim().split(/\r?\n/).pop();
|
|
469
|
-
const localBrowsers = path.join(root, 'playwriter', 'node_modules', '@xmorse', 'playwright-core', '.local-browsers');
|
|
470
|
-
if (fs.existsSync(localBrowsers)) {
|
|
471
|
-
const exe = chromiumExeFromCacheRoot(localBrowsers);
|
|
472
|
-
if (exe) return exe;
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
} catch (_) {}
|
|
476
|
-
return null;
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
function ensureBundledChromium(pw) {
|
|
480
|
-
const existing = findBundledChromium();
|
|
481
|
-
if (existing) return { exe: existing, installed: false };
|
|
482
|
-
if (!pw || !pw.cmd) {
|
|
483
|
-
return { exe: null, installed: false, error: 'playwriter not available to install browser' };
|
|
484
|
-
}
|
|
485
|
-
const installer = { cmd: pw.cmd, args: [...pw.baseArgs, 'install', 'chromium'], shell: pw.shell };
|
|
486
|
-
logEvent('bootstrap', 'browser.bundled-install.start', { via: 'playwriter' });
|
|
487
|
-
const r = spawnSync(installer.cmd, installer.args, {
|
|
488
|
-
encoding: 'utf-8',
|
|
489
|
-
timeout: 600000,
|
|
490
|
-
shell: installer.shell,
|
|
491
|
-
windowsHide: true,
|
|
492
|
-
});
|
|
493
|
-
logEvent('bootstrap', 'browser.bundled-install.done', { status: r.status });
|
|
494
|
-
const after = findBundledChromium();
|
|
495
|
-
if (after) return { exe: after, installed: true };
|
|
496
|
-
return { exe: null, installed: false, error: r.stderr || r.stdout || 'install failed' };
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
function findChrome() {
|
|
500
|
-
const bundled = findBundledChromium();
|
|
501
|
-
if (bundled) return bundled;
|
|
502
|
-
if (process.platform === 'win32') {
|
|
503
|
-
const candidates = [
|
|
504
|
-
path.join(process.env.PROGRAMFILES || 'C:\\Program Files', 'Google', 'Chrome', 'Application', 'chrome.exe'),
|
|
505
|
-
path.join(process.env['PROGRAMFILES(X86)'] || 'C:\\Program Files (x86)', 'Google', 'Chrome', 'Application', 'chrome.exe'),
|
|
506
|
-
path.join(process.env.LOCALAPPDATA || '', 'Google', 'Chrome', 'Application', 'chrome.exe'),
|
|
507
|
-
];
|
|
508
|
-
for (const c of candidates) { if (c && fs.existsSync(c)) return c; }
|
|
509
|
-
return null;
|
|
510
|
-
}
|
|
511
|
-
if (process.platform === 'darwin') {
|
|
512
|
-
const mac = '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome';
|
|
513
|
-
if (fs.existsSync(mac)) return mac;
|
|
514
|
-
return null;
|
|
515
|
-
}
|
|
516
|
-
for (const bin of ['google-chrome', 'chromium', 'chromium-browser']) {
|
|
517
|
-
const r = spawnSync('which', [bin], { encoding: 'utf-8' });
|
|
518
|
-
if (r.status === 0 && r.stdout.trim()) return r.stdout.trim();
|
|
519
|
-
}
|
|
520
|
-
return null;
|
|
521
|
-
}
|
|
522
|
-
|
|
523
423
|
function findPlaywriter() {
|
|
524
424
|
const npmR = spawnSync('npm', ['root', '-g'], { encoding: 'utf-8', shell: true });
|
|
525
425
|
if (npmR.status === 0 && npmR.stdout.trim()) {
|
|
@@ -716,6 +616,124 @@ function scrubBrowserRunnerText(s) {
|
|
|
716
616
|
return t;
|
|
717
617
|
}
|
|
718
618
|
|
|
619
|
+
function findInstalledChromiumBinary() {
|
|
620
|
+
try {
|
|
621
|
+
if (process.env.PLAYWRITER_BROWSER_PATH && fs.existsSync(process.env.PLAYWRITER_BROWSER_PATH)) {
|
|
622
|
+
return process.env.PLAYWRITER_BROWSER_PATH;
|
|
623
|
+
}
|
|
624
|
+
const roots = [];
|
|
625
|
+
if (process.platform === 'win32') {
|
|
626
|
+
const lad = process.env.LOCALAPPDATA;
|
|
627
|
+
if (lad) roots.push(path.join(lad, 'ms-playwright'));
|
|
628
|
+
} else {
|
|
629
|
+
const home = process.env.HOME || '';
|
|
630
|
+
if (home) {
|
|
631
|
+
roots.push(path.join(home, '.cache', 'ms-playwright'));
|
|
632
|
+
roots.push(path.join(home, 'Library', 'Caches', 'ms-playwright'));
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
const exeName = process.platform === 'win32' ? 'chrome.exe' : (process.platform === 'darwin' ? 'Chromium.app/Contents/MacOS/Chromium' : 'chrome');
|
|
636
|
+
const subdirs = process.platform === 'win32'
|
|
637
|
+
? ['chrome-win64', 'chrome-win']
|
|
638
|
+
: process.platform === 'darwin' ? ['chrome-mac'] : ['chrome-linux'];
|
|
639
|
+
const found = [];
|
|
640
|
+
for (const root of roots) {
|
|
641
|
+
if (!fs.existsSync(root)) continue;
|
|
642
|
+
for (const name of fs.readdirSync(root)) {
|
|
643
|
+
if (!/^chromium-\d+$/.test(name)) continue;
|
|
644
|
+
for (const sub of subdirs) {
|
|
645
|
+
const candidate = path.join(root, name, sub, exeName);
|
|
646
|
+
if (fs.existsSync(candidate)) {
|
|
647
|
+
const ver = parseInt(name.split('-')[1], 10) || 0;
|
|
648
|
+
found.push({ ver, candidate });
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
if (found.length === 0) return null;
|
|
654
|
+
found.sort((a, b) => b.ver - a.ver);
|
|
655
|
+
return found[0].candidate;
|
|
656
|
+
} catch (_) {
|
|
657
|
+
return null;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
function startManagedBrowser(pw, profileDir) {
|
|
662
|
+
const args = [...pw.baseArgs, 'browser', 'start', '--user-data-dir', profileDir, '--headless'];
|
|
663
|
+
const env = { ...process.env };
|
|
664
|
+
if (!env.PLAYWRITER_BROWSER_PATH) {
|
|
665
|
+
const browserBin = findInstalledChromiumBinary();
|
|
666
|
+
if (browserBin) {
|
|
667
|
+
env.PLAYWRITER_BROWSER_PATH = browserBin;
|
|
668
|
+
logEvent('plugkit', 'browser.binary-resolved', { path: browserBin });
|
|
669
|
+
} else {
|
|
670
|
+
logEvent('plugkit', 'browser.binary-missing', {});
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
const child = spawn(pw.cmd, args, {
|
|
674
|
+
detached: true,
|
|
675
|
+
stdio: 'ignore',
|
|
676
|
+
shell: pw.shell,
|
|
677
|
+
windowsHide: true,
|
|
678
|
+
env,
|
|
679
|
+
...(process.platform === 'win32' ? { creationFlags: 0x08000000 | 0x00000008 } : {}),
|
|
680
|
+
});
|
|
681
|
+
const pid = child.pid;
|
|
682
|
+
child.unref();
|
|
683
|
+
return pid;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
function isColdRunProfile(profileDir) {
|
|
687
|
+
try {
|
|
688
|
+
if (!fs.existsSync(profileDir)) return true;
|
|
689
|
+
const entries = fs.readdirSync(profileDir);
|
|
690
|
+
if (entries.length === 0) return true;
|
|
691
|
+
if (!entries.some(n => n === 'Default' || n === 'Local State')) return true;
|
|
692
|
+
return false;
|
|
693
|
+
} catch (_) {
|
|
694
|
+
return true;
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
function waitForExtensionReady(pw, profileDir, opts) {
|
|
699
|
+
const cold = (opts && typeof opts.cold === 'boolean') ? opts.cold : isColdRunProfile(profileDir);
|
|
700
|
+
const timeoutMs = (opts && opts.timeoutMs) || (cold ? 180000 : 30000);
|
|
701
|
+
const start = Date.now();
|
|
702
|
+
const deadline = start + timeoutMs;
|
|
703
|
+
const backoff = [2000, 4000, 8000];
|
|
704
|
+
let attempt = 0;
|
|
705
|
+
let lastErr = '';
|
|
706
|
+
let lastProgressAt = start;
|
|
707
|
+
while (Date.now() < deadline) {
|
|
708
|
+
const remaining = deadline - Date.now();
|
|
709
|
+
const innerTimeout = Math.max(28000, Math.min(remaining, 30000));
|
|
710
|
+
const r = runPlaywriter(pw, ['session', 'new'], innerTimeout);
|
|
711
|
+
if (r && r.status === 0) return r;
|
|
712
|
+
lastErr = scrubBrowserRunnerText((r && (r.stderr || r.stdout)) || '');
|
|
713
|
+
const now = Date.now();
|
|
714
|
+
if (now - lastProgressAt >= 10000) {
|
|
715
|
+
logEvent('plugkit', 'browser.extension-wait', {
|
|
716
|
+
elapsed_ms: now - start,
|
|
717
|
+
cold_run: cold,
|
|
718
|
+
profileDir,
|
|
719
|
+
attempt,
|
|
720
|
+
});
|
|
721
|
+
lastProgressAt = now;
|
|
722
|
+
}
|
|
723
|
+
const sleepMs = backoff[Math.min(attempt, backoff.length - 1)];
|
|
724
|
+
attempt++;
|
|
725
|
+
if (Date.now() + sleepMs >= deadline) break;
|
|
726
|
+
sleepSync(sleepMs);
|
|
727
|
+
}
|
|
728
|
+
const flavor = cold
|
|
729
|
+
? `cold-run timeout after ${Math.round((Date.now() - start) / 1000)}s waiting for managed browser extension to connect (first run downloads chromium ~150MB and installs the extension; if this persists the extension never registered with the relay server)`
|
|
730
|
+
: `warm-run timeout after ${Math.round((Date.now() - start) / 1000)}s waiting for managed browser extension to reconnect (profile exists but extension is not registering; relay server may be wedged)`;
|
|
731
|
+
const err = new Error(`managed browser session start failed: ${flavor}${lastErr ? ` :: ${lastErr}` : ''}`);
|
|
732
|
+
err._lastErr = lastErr;
|
|
733
|
+
err._coldRun = cold;
|
|
734
|
+
throw err;
|
|
735
|
+
}
|
|
736
|
+
|
|
719
737
|
function getOrCreateBrowserSession(cwd, claudeSessionId, pw) {
|
|
720
738
|
migrateLegacyBrowserState(cwd);
|
|
721
739
|
const portsFile = browserPortsFile(cwd);
|
|
@@ -723,20 +741,18 @@ function getOrCreateBrowserSession(cwd, claudeSessionId, pw) {
|
|
|
723
741
|
const ports = readJsonFile(portsFile, {});
|
|
724
742
|
const sessions = readJsonFile(sessionsFile, {});
|
|
725
743
|
const existing = ports[claudeSessionId];
|
|
726
|
-
if (existing && existing.
|
|
744
|
+
if (existing && existing.pid) {
|
|
727
745
|
const wantProfile = path.join(cwd, '.gm', 'browser-profile');
|
|
728
|
-
const pidOk =
|
|
746
|
+
const pidOk = isProcessAliveSync(existing.pid);
|
|
729
747
|
const profileOk = !existing.profileDir || existing.profileDir === wantProfile || existing.profileDir.startsWith(path.join(cwd, '.gm', 'browser-profile'));
|
|
730
|
-
|
|
731
|
-
if (pidOk && profileOk && portOk) {
|
|
748
|
+
if (pidOk && profileOk) {
|
|
732
749
|
const pwIds = sessions[claudeSessionId] || [];
|
|
733
750
|
if (pwIds.length > 0) return pwIds[0];
|
|
734
751
|
} else {
|
|
735
|
-
const reason = !pidOk ? 'pid-dead' :
|
|
752
|
+
const reason = !pidOk ? 'pid-dead' : 'profile-drift';
|
|
736
753
|
logEvent('hook', 'deviation.browser-profile-collision', {
|
|
737
754
|
sid: claudeSessionId,
|
|
738
755
|
stale_pid: existing.pid || null,
|
|
739
|
-
stale_port: existing.port || null,
|
|
740
756
|
stale_profile: existing.profileDir || null,
|
|
741
757
|
want_profile: wantProfile,
|
|
742
758
|
reason,
|
|
@@ -748,44 +764,12 @@ function getOrCreateBrowserSession(cwd, claudeSessionId, pw) {
|
|
|
748
764
|
}
|
|
749
765
|
}
|
|
750
766
|
cleanDeadProfileFragments(cwd);
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
const ensured = ensureBundledChromium(pw);
|
|
754
|
-
if (ensured.exe) chrome = ensured.exe;
|
|
755
|
-
}
|
|
756
|
-
if (!chrome) chrome = findChrome();
|
|
757
|
-
if (!chrome) throw new Error('No chromium binary available. Run: bun x playwriter@latest install chromium');
|
|
767
|
+
const probedProfile = path.join(cwd, '.gm', 'browser-profile');
|
|
768
|
+
const coldRun = isColdRunProfile(probedProfile);
|
|
758
769
|
const profileDir = acquireProfileDir(cwd);
|
|
759
|
-
|
|
760
|
-
const
|
|
761
|
-
|
|
762
|
-
`--user-data-dir=${profileDir}`,
|
|
763
|
-
'--no-first-run',
|
|
764
|
-
'--no-default-browser-check',
|
|
765
|
-
'--disable-features=Translate',
|
|
766
|
-
];
|
|
767
|
-
// Chrome itself is GUI but its remote-debugging port creates conhost
|
|
768
|
-
// when launched from a console-attached parent. CREATE_NO_WINDOW
|
|
769
|
-
// (0x08000000) | DETACHED_PROCESS (0x00000008) prevents the helper
|
|
770
|
-
// processes (sandbox, GPU, network service) from allocating consoles.
|
|
771
|
-
// Inherited by the entire chrome subprocess tree on Windows.
|
|
772
|
-
const child = spawn(chrome, chromeArgs, {
|
|
773
|
-
detached: true,
|
|
774
|
-
stdio: 'ignore',
|
|
775
|
-
windowsHide: true,
|
|
776
|
-
...(process.platform === 'win32' ? { creationFlags: 0x08000000 | 0x00000008 } : {}),
|
|
777
|
-
});
|
|
778
|
-
const chromePid = child.pid;
|
|
779
|
-
child.unref();
|
|
780
|
-
const deadline = Date.now() + 10000;
|
|
781
|
-
let alive = false;
|
|
782
|
-
while (Date.now() < deadline) {
|
|
783
|
-
if (isPortAliveSync(port)) { alive = true; break; }
|
|
784
|
-
sleepSync(300);
|
|
785
|
-
}
|
|
786
|
-
if (!alive) throw new Error(`Chrome failed to open debug port ${port}`);
|
|
787
|
-
const newR = runPlaywriter(pw, ['session', 'new', '--direct', `localhost:${port}`], 30000);
|
|
788
|
-
if (newR.status !== 0) throw new Error(`managed browser session start failed: ${scrubBrowserRunnerText(newR.stderr || newR.stdout || 'unknown')}`);
|
|
770
|
+
logEvent('plugkit', 'browser.start', { profileDir, cold_run: coldRun });
|
|
771
|
+
const browserPid = startManagedBrowser(pw, profileDir);
|
|
772
|
+
const newR = waitForExtensionReady(pw, profileDir, { cold: coldRun });
|
|
789
773
|
const stripAnsi = (s) => s.replace(/\x1b\[[0-9;]*m/g, '');
|
|
790
774
|
const out = stripAnsi(newR.stdout || '').trim();
|
|
791
775
|
let pwSessionId = null;
|
|
@@ -799,7 +783,7 @@ function getOrCreateBrowserSession(cwd, claudeSessionId, pw) {
|
|
|
799
783
|
try { const j = JSON.parse(out); pwSessionId = j.id || j.session_id || j.session; } catch (_) {}
|
|
800
784
|
}
|
|
801
785
|
if (!pwSessionId) throw new Error(`could not parse managed browser session id from: ${scrubBrowserRunnerText(out)}`);
|
|
802
|
-
ports[claudeSessionId] = {
|
|
786
|
+
ports[claudeSessionId] = { profileDir, pid: browserPid };
|
|
803
787
|
sessions[claudeSessionId] = [pwSessionId];
|
|
804
788
|
writeJsonFile(portsFile, ports);
|
|
805
789
|
writeJsonFile(sessionsFile, sessions);
|
|
@@ -1413,12 +1397,7 @@ function makeHostFunctions(instanceRef) {
|
|
|
1413
1397
|
if (!pw) return writeWasmJson(instanceRef.value, { ok: false, error: 'managed browser session runner not available' });
|
|
1414
1398
|
if (body.startsWith('session ')) {
|
|
1415
1399
|
const parts = body.slice(8).trim().split(/\s+/);
|
|
1416
|
-
const
|
|
1417
|
-
const existing = ports[sessionId];
|
|
1418
|
-
const directArgs = (existing && existing.port && isPortAliveSync(existing.port))
|
|
1419
|
-
? [`--direct=localhost:${existing.port}`]
|
|
1420
|
-
: [];
|
|
1421
|
-
const r = runPlaywriter(pw, ['session', ...parts, ...directArgs], 30000);
|
|
1400
|
+
const r = runPlaywriter(pw, ['session', ...parts], 30000);
|
|
1422
1401
|
return writeWasmJson(instanceRef.value, {
|
|
1423
1402
|
ok: r.status === 0,
|
|
1424
1403
|
stdout: scrubBrowserRunnerText(r.stdout || ''),
|
|
@@ -1427,12 +1406,7 @@ function makeHostFunctions(instanceRef) {
|
|
|
1427
1406
|
});
|
|
1428
1407
|
}
|
|
1429
1408
|
const pwSessionId = getOrCreateBrowserSession(cwd, sessionId, pw);
|
|
1430
|
-
const
|
|
1431
|
-
const livePort = portsAfter[sessionId] && portsAfter[sessionId].port;
|
|
1432
|
-
const directArgs = (livePort && isPortAliveSync(livePort))
|
|
1433
|
-
? [`--direct=localhost:${livePort}`]
|
|
1434
|
-
: [];
|
|
1435
|
-
const r = runPlaywriter(pw, ['-s', pwSessionId, '--timeout', '14000', ...directArgs, '-e', body], 60000);
|
|
1409
|
+
const r = runPlaywriter(pw, ['-s', pwSessionId, '--timeout', '14000', '-e', body], 60000);
|
|
1436
1410
|
return writeWasmJson(instanceRef.value, {
|
|
1437
1411
|
ok: r.status === 0,
|
|
1438
1412
|
stdout: scrubBrowserRunnerText(r.stdout || ''),
|
|
@@ -1801,9 +1775,9 @@ async function runSpoolWatcher(instance, spoolDir) {
|
|
|
1801
1775
|
const ports = readJsonFile(browserPortsFile(process.cwd()), {});
|
|
1802
1776
|
let browserAlive = false;
|
|
1803
1777
|
for (const entry of Object.values(ports)) {
|
|
1804
|
-
if (entry && Number.isFinite(entry.
|
|
1778
|
+
if (entry && Number.isFinite(entry.pid) && isProcessAliveSync(entry.pid)) { browserAlive = true; break; }
|
|
1805
1779
|
}
|
|
1806
|
-
if (browserAlive) { markActivity('browser-
|
|
1780
|
+
if (browserAlive) { markActivity('browser-pid-alive'); return; }
|
|
1807
1781
|
} catch (_) {}
|
|
1808
1782
|
try {
|
|
1809
1783
|
let anyRunning = false;
|
package/gm.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gm-skill",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1271",
|
|
4
4
|
"description": "Canonical universal harness — AI-native software engineering via skill-driven orchestration; bootstraps plugkit for task execution and session isolation. Install in any AI coding agent host.",
|
|
5
5
|
"author": "AnEntrypoint",
|
|
6
6
|
"license": "MIT",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"gm.json"
|
|
40
40
|
],
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"gm-plugkit": "^2.0.
|
|
42
|
+
"gm-plugkit": "^2.0.1271"
|
|
43
43
|
},
|
|
44
44
|
"engines": {
|
|
45
45
|
"node": ">=16.0.0"
|