gm-skill 2.0.1606 → 2.0.1608
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/bin/gm-shell-validate.js +19 -6
- package/bin/plugkit.version +1 -1
- package/bin/plugkit.wasm.sha256 +1 -1
- package/gm-plugkit/package.json +1 -1
- package/gm-plugkit/plugkit.version +1 -1
- package/gm.json +2 -2
- package/lib/spool.js +7 -1
- package/package.json +13 -2
- package/gm-plugkit/browser-idle.test.js +0 -46
- package/gm-plugkit/child-script-alias.test.js +0 -25
package/bin/gm-shell-validate.js
CHANGED
|
@@ -10,6 +10,18 @@ const { pathToFileURL } = require('url');
|
|
|
10
10
|
const ROOT = process.cwd();
|
|
11
11
|
const WITNESS_DIR = path.join(ROOT, '.gm', 'witness');
|
|
12
12
|
|
|
13
|
+
function freePort() {
|
|
14
|
+
const net = require('net');
|
|
15
|
+
return new Promise((resolve, reject) => {
|
|
16
|
+
const srv = net.createServer();
|
|
17
|
+
srv.once('error', reject);
|
|
18
|
+
srv.listen(0, '127.0.0.1', () => {
|
|
19
|
+
const p = srv.address().port;
|
|
20
|
+
srv.close(() => resolve(p));
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
13
25
|
function sleep(ms) { return new Promise((r) => setTimeout(r, ms)); }
|
|
14
26
|
function rmrf(p) { try { fs.rmSync(p, { recursive: true, force: true }); } catch (_) {} }
|
|
15
27
|
function write(file, text) { fs.mkdirSync(path.dirname(file), { recursive: true }); fs.writeFileSync(file, text); }
|
|
@@ -26,7 +38,7 @@ function which(cmds) {
|
|
|
26
38
|
async function renderPreview() {
|
|
27
39
|
const preview = fs.mkdtempSync(path.join(os.tmpdir(), 'gm-shell-preview-'));
|
|
28
40
|
fs.mkdirSync(path.join(preview, 'vendor'), { recursive: true });
|
|
29
|
-
|
|
41
|
+
fs.cpSync(path.join(ROOT, 'site', 'vendor'), path.join(preview, 'vendor'), { recursive: true });
|
|
30
42
|
|
|
31
43
|
const renderScript = `
|
|
32
44
|
import { writeFileSync } from 'fs';
|
|
@@ -44,17 +56,18 @@ async function renderPreview() {
|
|
|
44
56
|
}
|
|
45
57
|
};
|
|
46
58
|
const out = await mod.default.render(ctx);
|
|
47
|
-
writeFileSync(resolve(
|
|
59
|
+
writeFileSync(resolve(process.env.GM_SHELL_PREVIEW, 'index.html'), out[0].html);
|
|
48
60
|
`;
|
|
49
61
|
const tmp = path.join(os.tmpdir(), `gm-shell-render-${Date.now()}.mjs`);
|
|
50
62
|
fs.writeFileSync(tmp, renderScript);
|
|
51
|
-
cp.execFileSync('node', [tmp], { stdio: 'inherit', windowsHide: true });
|
|
63
|
+
cp.execFileSync('node', [tmp], { stdio: 'inherit', windowsHide: true, env: { ...process.env, GM_SHELL_PREVIEW: preview } });
|
|
52
64
|
try { fs.unlinkSync(tmp); } catch (_) {}
|
|
53
65
|
|
|
54
|
-
const
|
|
66
|
+
const port = await freePort();
|
|
67
|
+
const server = cp.spawn('python', ['-m', 'http.server', String(port), '--directory', preview], { cwd: ROOT, detached: true, stdio: 'ignore', windowsHide: true });
|
|
55
68
|
server.unref();
|
|
56
69
|
await sleep(1500);
|
|
57
|
-
return { preview, port
|
|
70
|
+
return { preview, port, serverPid: server.pid };
|
|
58
71
|
}
|
|
59
72
|
|
|
60
73
|
function killServer(pid) {
|
|
@@ -96,7 +109,7 @@ return JSON.stringify(result);
|
|
|
96
109
|
const response = await fetch(relayUrl, {
|
|
97
110
|
method: 'POST',
|
|
98
111
|
headers: { 'Content-Type': 'application/json' },
|
|
99
|
-
body: JSON.stringify({ sessionId:
|
|
112
|
+
body: JSON.stringify({ sessionId: `gm-shell-${process.pid}-${Date.now()}`, code: script, timeout: 60000, cwd: ROOT }),
|
|
100
113
|
});
|
|
101
114
|
const result = await response.json();
|
|
102
115
|
const out = result.text || '';
|
package/bin/plugkit.version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.1.
|
|
1
|
+
0.1.684
|
package/bin/plugkit.wasm.sha256
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
598494162a781d6626d9afec9a9b403f481364a97b10b257b80dda6e064206b1 plugkit.wasm
|
package/gm-plugkit/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gm-plugkit",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1608",
|
|
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": {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
0.1.
|
|
1
|
+
0.1.684
|
package/gm.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gm",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1608",
|
|
4
4
|
"description": "Spool-dispatch orchestration engine with unified state machine, skills, and automated git enforcement",
|
|
5
5
|
"author": "AnEntrypoint",
|
|
6
6
|
"license": "MIT",
|
|
@@ -17,5 +17,5 @@
|
|
|
17
17
|
"publishConfig": {
|
|
18
18
|
"access": "public"
|
|
19
19
|
},
|
|
20
|
-
"plugkitVersion": "0.1.
|
|
20
|
+
"plugkitVersion": "0.1.684"
|
|
21
21
|
}
|
package/lib/spool.js
CHANGED
|
@@ -55,7 +55,13 @@ function writeSpool(body, lang = 'nodejs', options = {}) {
|
|
|
55
55
|
fs.mkdirSync(inDir, { recursive: true });
|
|
56
56
|
|
|
57
57
|
const sessionId = options.sessionId || process.env.CLAUDE_SESSION_ID;
|
|
58
|
-
|
|
58
|
+
let code = body;
|
|
59
|
+
if (sessionId) {
|
|
60
|
+
const prelude = validLang === 'bash'
|
|
61
|
+
? `SESSION_ID=${JSON.stringify(String(sessionId))}\n`
|
|
62
|
+
: `const SESSION_ID = ${JSON.stringify(sessionId)};\n`;
|
|
63
|
+
code = prelude + body;
|
|
64
|
+
}
|
|
59
65
|
|
|
60
66
|
fs.writeFileSync(inFile, code, 'utf8');
|
|
61
67
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gm-skill",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1608",
|
|
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",
|
|
@@ -38,7 +38,18 @@
|
|
|
38
38
|
"bin/plugkit.sha256",
|
|
39
39
|
"bin/plugkit.version",
|
|
40
40
|
"bin/plugkit.wasm.sha256",
|
|
41
|
-
"gm-plugkit/",
|
|
41
|
+
"gm-plugkit/bootstrap.js",
|
|
42
|
+
"gm-plugkit/browser-idle.js",
|
|
43
|
+
"gm-plugkit/cli.js",
|
|
44
|
+
"gm-plugkit/index.js",
|
|
45
|
+
"gm-plugkit/lang-host-runner.js",
|
|
46
|
+
"gm-plugkit/package.json",
|
|
47
|
+
"gm-plugkit/plugkit-wasm-wrapper.js",
|
|
48
|
+
"gm-plugkit/supervisor.js",
|
|
49
|
+
"gm-plugkit/plugkit.version",
|
|
50
|
+
"gm-plugkit/plugkit.sha256",
|
|
51
|
+
"gm-plugkit/instructions/",
|
|
52
|
+
"gm-plugkit/scripts/",
|
|
42
53
|
"AGENTS.md",
|
|
43
54
|
"README.md",
|
|
44
55
|
"gm.json"
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
const assert = require('assert');
|
|
2
|
-
const { selectIdleBrowserSessions } = require('./browser-idle.js');
|
|
3
|
-
|
|
4
|
-
const NOW = 1_000_000;
|
|
5
|
-
const LIMIT = 10 * 60 * 1000;
|
|
6
|
-
|
|
7
|
-
(function onlyPastLimitSelected() {
|
|
8
|
-
const ports = {
|
|
9
|
-
active: { pid: 1, lastUse: NOW - 1000 },
|
|
10
|
-
idle: { pid: 2, lastUse: NOW - (LIMIT + 5000) },
|
|
11
|
-
};
|
|
12
|
-
const idle = selectIdleBrowserSessions(ports, NOW, LIMIT);
|
|
13
|
-
assert.strictEqual(idle.length, 1, 'exactly one idle session selected');
|
|
14
|
-
assert.strictEqual(idle[0].sid, 'idle', 'the idle session is selected, active untouched');
|
|
15
|
-
})();
|
|
16
|
-
|
|
17
|
-
(function boundaryIsInclusive() {
|
|
18
|
-
const ports = { edge: { pid: 1, lastUse: NOW - LIMIT } };
|
|
19
|
-
const idle = selectIdleBrowserSessions(ports, NOW, LIMIT);
|
|
20
|
-
assert.strictEqual(idle.length, 1, 'idleMs == limit closes (>=)');
|
|
21
|
-
})();
|
|
22
|
-
|
|
23
|
-
(function missingLastUseReapedAsStale() {
|
|
24
|
-
const ports = { orphan: { pid: 1 } };
|
|
25
|
-
const idle = selectIdleBrowserSessions(ports, NOW, LIMIT);
|
|
26
|
-
assert.strictEqual(idle.length, 1, 'entry with no lastUse is treated as stale (epoch 0) and reaped');
|
|
27
|
-
assert.strictEqual(idle[0].sid, 'orphan');
|
|
28
|
-
})();
|
|
29
|
-
|
|
30
|
-
(function concurrentIsolation() {
|
|
31
|
-
const ports = {
|
|
32
|
-
sessA: { pid: 1, lastUse: NOW - 2000 },
|
|
33
|
-
sessB: { pid: 2, lastUse: NOW - (LIMIT + 1) },
|
|
34
|
-
sessC: { pid: 3, lastUse: NOW - (LIMIT + 999999) },
|
|
35
|
-
};
|
|
36
|
-
const idle = selectIdleBrowserSessions(ports, NOW, LIMIT).map(x => x.sid).sort();
|
|
37
|
-
assert.deepStrictEqual(idle, ['sessB', 'sessC'], 'only the idle sessions, active sessA preserved');
|
|
38
|
-
})();
|
|
39
|
-
|
|
40
|
-
(function emptyAndMalformed() {
|
|
41
|
-
assert.deepStrictEqual(selectIdleBrowserSessions({}, NOW, LIMIT), [], 'empty ports');
|
|
42
|
-
assert.deepStrictEqual(selectIdleBrowserSessions(null, NOW, LIMIT), [], 'null ports');
|
|
43
|
-
assert.deepStrictEqual(selectIdleBrowserSessions({ bad: null, str: 'x' }, NOW, LIMIT), [], 'malformed entries skipped');
|
|
44
|
-
})();
|
|
45
|
-
|
|
46
|
-
console.log('browser-idle.test.js: all assertions passed');
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
const assert = require('assert');
|
|
2
|
-
const fs = require('fs');
|
|
3
|
-
const path = require('path');
|
|
4
|
-
|
|
5
|
-
const wrapper = fs.readFileSync(path.join(__dirname, 'plugkit-wasm-wrapper.js'), 'utf-8');
|
|
6
|
-
|
|
7
|
-
const aliasInChildScript = /\bspawnSync\s*\(\s*process\.execPath\s*,\s*\[\s*['"]-e['"]\s*,\s*`[^`]*\b_(?:net|http|https|crypto|childProcess)Module\b[^`]*`/;
|
|
8
|
-
|
|
9
|
-
(function noParentAliasInChildEvalTemplates() {
|
|
10
|
-
assert.strictEqual(
|
|
11
|
-
aliasInChildScript.test(wrapper),
|
|
12
|
-
false,
|
|
13
|
-
'no spawnSync(process.execPath, ["-e", `...`]) child-script template may reference a parent-scope _*Module alias; the spawned child has no such binding (use require() inside the template). This regression broke findFreePortSync/isPort*/fetchJsonSync and surfaced only as "could not allocate free port" at browser-spawn time.'
|
|
14
|
-
);
|
|
15
|
-
})();
|
|
16
|
-
|
|
17
|
-
(function childTemplatesUseRequire() {
|
|
18
|
-
const childEvalBlocks = wrapper.match(/spawnSync\s*\(\s*process\.execPath\s*,\s*\[\s*['"]-e['"]\s*,\s*`[^`]*`/g) || [];
|
|
19
|
-
for (const block of childEvalBlocks) {
|
|
20
|
-
if (/\brequire\s*\(\s*['"](?:net|http|https)['"]\s*\)/.test(block) || !/\b(?:net|http|https)\b/.test(block)) continue;
|
|
21
|
-
assert.fail(`child -e template uses a node builtin without require(): ${block.slice(0, 80)}...`);
|
|
22
|
-
}
|
|
23
|
-
})();
|
|
24
|
-
|
|
25
|
-
console.log('child-script-alias.test.js: all assertions passed');
|