gm-plugkit 2.0.1635 → 2.0.1637
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/SKILL.md +1 -1
- package/package.json +1 -1
- package/plugkit-wasm-wrapper.js +24 -9
package/SKILL.md
CHANGED
|
@@ -34,7 +34,7 @@ Every turn: dispatch `instruction`, read it, follow the imperative, dispatch the
|
|
|
34
34
|
cat .gm/exec-spool/.status.json 2>/dev/null; echo ---; cat .gm/exec-spool/.turn-summary.json 2>/dev/null; echo ---; date +%s%3N
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
-
`.turn-summary.json` carries `phase`, `last_skill`, `prd_pending`, `last_instruction_ts`, `last_instruction_age_ms`, `long_gap_threshold_ms`, `browser_sessions_alive`, `update_available`, `deviations_30m`, `watcher_uptime_ms`. Age over threshold: your next non-orienting verb is gated, dispatch `instruction` first. `update_available` non-null:
|
|
37
|
+
`.turn-summary.json` carries `phase`, `last_skill`, `prd_pending`, `last_instruction_ts`, `last_instruction_age_ms`, `long_gap_threshold_ms`, `browser_sessions_alive`, `update_available`, `deviations_30m`, `watcher_uptime_ms`. Age over threshold: your next non-orienting verb is gated, dispatch `instruction` first. `update_available` non-null: the watcher auto-updates itself when idle (cache-busted self-respawn to latest), so it usually clears on its own within a few minutes -- keep working. To land it immediately, just re-run the idempotent `bun x gm-plugkit@latest spool` (blocks until serving); only add `--kill-stale-watchers` first if it stays stuck across several turns. `PLUGKIT_NO_AUTO_UPDATE=1` pins the version. `deviations_30m` non-zero indicates active drift to investigate before continuing.
|
|
38
38
|
|
|
39
39
|
Compare `.status.json` `ts` to the printed epoch: gap > 15000 = dead, boot it. Exception: a future `busy_until` means a long verb (browser/chromium spawn blocks the heartbeat ~15-18s) -- wait, do not boot a second watcher.
|
|
40
40
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gm-plugkit",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1637",
|
|
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-wasm-wrapper.js
CHANGED
|
@@ -308,7 +308,7 @@ function injectUpdateWarning(parsed) {
|
|
|
308
308
|
if (!upd || !upd.installed || !upd.latest || upd.installed === upd.latest) return;
|
|
309
309
|
const target = (parsed.data && typeof parsed.data === 'object') ? parsed.data : parsed;
|
|
310
310
|
target.update_available = { installed: upd.installed, latest: upd.latest, update_url: upd.update_url || null };
|
|
311
|
-
target.update_warning = `STALE RUNTIME: running plugkit ${upd.installed} but ${upd.latest} is published
|
|
311
|
+
target.update_warning = `STALE RUNTIME: running plugkit ${upd.installed} but ${upd.latest} is published. The watcher auto-updates when idle (cache-busted self-respawn to latest), so this usually clears on its own within a few minutes; just keep working. If it persists, re-run the idempotent boot to land latest now: bun x gm-plugkit@latest spool (add --kill-stale-watchers first only if it stays stuck). Set PLUGKIT_NO_AUTO_UPDATE=1 to pin. This warning repeats until the running version catches up.`;
|
|
312
312
|
}
|
|
313
313
|
|
|
314
314
|
function mergeAutoRecallIntoInstructionResponse(resultStr, autoRecall) {
|
|
@@ -1457,8 +1457,9 @@ function createWasiShim(instanceRef) {
|
|
|
1457
1457
|
const dv = new DataView(buf);
|
|
1458
1458
|
const chunks = [];
|
|
1459
1459
|
let total = 0;
|
|
1460
|
+
const iovsBase = iovs_ptr >>> 0; // >>>0: high-bit iovs pointer is negative in JS -> getUint32 would throw
|
|
1460
1461
|
for (let i = 0; i < iovs_len; i++) {
|
|
1461
|
-
const base =
|
|
1462
|
+
const base = iovsBase + i * 8;
|
|
1462
1463
|
const ptr = dv.getUint32(base, true);
|
|
1463
1464
|
const len = dv.getUint32(base + 4, true);
|
|
1464
1465
|
if (len > 0 && ptr + len <= buf.byteLength) {
|
|
@@ -1480,7 +1481,7 @@ function createWasiShim(instanceRef) {
|
|
|
1480
1481
|
},
|
|
1481
1482
|
random_get: (buf_ptr, buf_len) => {
|
|
1482
1483
|
try {
|
|
1483
|
-
crypto.randomFillSync(new Uint8Array(getMemory(), buf_ptr, buf_len));
|
|
1484
|
+
crypto.randomFillSync(new Uint8Array(getMemory(), buf_ptr >>> 0, buf_len >>> 0)); // >>>0: high-bit ptr is negative in JS
|
|
1484
1485
|
return 0;
|
|
1485
1486
|
} catch (e) {
|
|
1486
1487
|
return 28;
|
|
@@ -1489,7 +1490,7 @@ function createWasiShim(instanceRef) {
|
|
|
1489
1490
|
clock_time_get: (clock_id, precision, time_ptr) => {
|
|
1490
1491
|
try {
|
|
1491
1492
|
const ns = BigInt(Date.now()) * 1000000n;
|
|
1492
|
-
new DataView(getMemory()).setBigUint64(time_ptr, ns, true);
|
|
1493
|
+
new DataView(getMemory()).setBigUint64(time_ptr >>> 0, ns, true); // >>>0: high-bit ptr is negative in JS
|
|
1493
1494
|
return 0;
|
|
1494
1495
|
} catch (e) {
|
|
1495
1496
|
return 28;
|
|
@@ -1548,8 +1549,15 @@ function decodeWasmResult(instance, result, where) {
|
|
|
1548
1549
|
|
|
1549
1550
|
function writeWasmInput(instance, bytes, where) {
|
|
1550
1551
|
if (bytes.length === 0) return 0;
|
|
1551
|
-
|
|
1552
|
+
// COERCE the alloc pointer to UNSIGNED 32-bit: a wasm i32 return with the high bit set (a pointer
|
|
1553
|
+
// > 0x7fffffff, which occurs once the linear memory grows past ~2GB in a long session) arrives in JS
|
|
1554
|
+
// as a NEGATIVE number, and new Uint8Array(buffer, negativePtr, len) throws the raw V8 "Start offset
|
|
1555
|
+
// <neg> is outside the bounds of the buffer" -- the deterministic long-session corruption that blocked
|
|
1556
|
+
// dispatches. >>>0 reinterprets the i32 as the true unsigned offset. Guard the range too so a genuinely
|
|
1557
|
+
// bad (ptr,len) raises the clean wasm-memory-read-out-of-bounds error instead of a raw typed-array throw.
|
|
1558
|
+
const ptr = instance.exports.plugkit_alloc(bytes.length) >>> 0;
|
|
1552
1559
|
if (ptr === 0) throw new Error(`wasm-alloc-failed at ${where}: plugkit_alloc returned 0 (wasm OOM)`);
|
|
1560
|
+
guardWasmRange(instance.exports.memory.buffer, ptr, bytes.length, `${where}:writeWasmInput`);
|
|
1553
1561
|
new Uint8Array(instance.exports.memory.buffer, ptr, bytes.length).set(bytes); // fresh buffer post-alloc
|
|
1554
1562
|
return ptr;
|
|
1555
1563
|
}
|
|
@@ -1571,8 +1579,11 @@ function readWasmStr(instance, ptr, len) {
|
|
|
1571
1579
|
|
|
1572
1580
|
function writeWasmBytes(instance, bytes) {
|
|
1573
1581
|
if (bytes.length === 0) return 0n;
|
|
1574
|
-
|
|
1582
|
+
// >>>0: same signed-pointer fix as writeWasmInput -- a high-bit alloc pointer is negative in JS and
|
|
1583
|
+
// throws "Start offset <neg> is outside the bounds" on the Uint8Array write below.
|
|
1584
|
+
const ptr = instance.exports.plugkit_alloc(bytes.length) >>> 0;
|
|
1575
1585
|
if (ptr === 0) return 0n;
|
|
1586
|
+
guardWasmRange(instance.exports.memory.buffer, ptr, bytes.length, 'writeWasmBytes');
|
|
1576
1587
|
new Uint8Array(instance.exports.memory.buffer, ptr, bytes.length).set(bytes);
|
|
1577
1588
|
return (BigInt(ptr) & 0xffffffffn) | (BigInt(bytes.length) << 32n);
|
|
1578
1589
|
}
|
|
@@ -2256,7 +2267,7 @@ function makeHostFunctions(instanceRef) {
|
|
|
2256
2267
|
host_random_fill: (ptr, len) => {
|
|
2257
2268
|
try {
|
|
2258
2269
|
const buf = instanceRef.value.exports.memory.buffer;
|
|
2259
|
-
crypto.randomFillSync(new Uint8Array(buf, ptr, len));
|
|
2270
|
+
crypto.randomFillSync(new Uint8Array(buf, ptr >>> 0, len >>> 0)); // >>>0: high-bit ptr is negative in JS
|
|
2260
2271
|
return 1;
|
|
2261
2272
|
} catch (_) {
|
|
2262
2273
|
return 0;
|
|
@@ -2904,6 +2915,10 @@ async function runSpoolWatcher(instance, spoolDir) {
|
|
|
2904
2915
|
let _selfStaleProbeErrorLogged = false;
|
|
2905
2916
|
function probeGmPlugkitSelfStale() {
|
|
2906
2917
|
try {
|
|
2918
|
+
if (process.env.PLUGKIT_NO_AUTO_UPDATE === '1') return;
|
|
2919
|
+
const { sids: _ifSids } = (typeof inflightPids === 'function') ? inflightPids() : { sids: new Set() };
|
|
2920
|
+
if (_ifSids.size > 0) return;
|
|
2921
|
+
if ((Date.now() - lastActivityMs) < 30000) return;
|
|
2907
2922
|
const ownPkgVersionFile = path.join(GM_TOOLS_ROOT, 'gm-plugkit.version');
|
|
2908
2923
|
const ownPkgJsonFile = path.join(__dirname, 'package.json');
|
|
2909
2924
|
let own = null;
|
|
@@ -2975,7 +2990,7 @@ async function runSpoolWatcher(instance, spoolDir) {
|
|
|
2975
2990
|
try {
|
|
2976
2991
|
const cp = _childProcess;
|
|
2977
2992
|
const bunPath = process.env.GM_BUN_PATH || 'bun';
|
|
2978
|
-
const bustCache =
|
|
2993
|
+
const bustCache = true;
|
|
2979
2994
|
if (bustCache) {
|
|
2980
2995
|
try { cp.execFileSync(bunPath, ['pm', 'cache', 'rm'], { stdio: 'ignore', timeout: 30000, windowsHide: true }); } catch (_) {}
|
|
2981
2996
|
try {
|
|
@@ -3002,7 +3017,7 @@ async function runSpoolWatcher(instance, spoolDir) {
|
|
|
3002
3017
|
env: { ...process.env, PLUGKIT_BOOT_REASON: 'self-respawn-from-self-stale' },
|
|
3003
3018
|
});
|
|
3004
3019
|
child.unref();
|
|
3005
|
-
try { logEvent('plugkit', '
|
|
3020
|
+
try { logEvent('plugkit', 'update.auto-applying', { running_version: own, latest_version: latest, cache_busted: bustCache, attempt: (respawnGuard.attempts || 0) + 1, note: 'auto-update: cache-busted self-respawn to latest' }); } catch (_) {}
|
|
3006
3021
|
try { fs.writeFileSync(path.join(spoolDir, '.shutdown-reason.json'), JSON.stringify({ reason: 'gm-plugkit-self-stale', ts: Date.now(), pid: process.pid, running_version: own, latest_version: latest })); } catch (_) {}
|
|
3007
3022
|
const myPid = process.pid;
|
|
3008
3023
|
const respawnDeadline = Date.now() + 90000;
|