gm-skill 2.0.1223 → 2.0.1225
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 +42 -0
- package/gm.json +1 -1
- package/lib/spool-dispatch.js +1 -86
- 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.1225` — 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
|
|
|
@@ -733,6 +733,46 @@ function cleanDeadProfileFragments(cwd) {
|
|
|
733
733
|
}
|
|
734
734
|
}
|
|
735
735
|
|
|
736
|
+
function isPortReachableSync(host, port, timeoutMs) {
|
|
737
|
+
const r = spawnSync(process.execPath, ['-e', `
|
|
738
|
+
const net = require('net');
|
|
739
|
+
const s = net.connect({ port: ${port}, host: ${JSON.stringify(host)} });
|
|
740
|
+
let done = false;
|
|
741
|
+
s.on('connect', () => { done = true; s.destroy(); process.exit(0); });
|
|
742
|
+
s.on('error', () => { if (!done) process.exit(1); });
|
|
743
|
+
setTimeout(() => { if (!done) { s.destroy(); process.exit(1); } }, ${timeoutMs || 800});
|
|
744
|
+
`], { timeout: (timeoutMs || 800) + 2000 });
|
|
745
|
+
return r.status === 0;
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
let _acptoapiBoot = { spawned_at: 0, pid: null };
|
|
749
|
+
function ensureAcptoapi() {
|
|
750
|
+
const host = '127.0.0.1';
|
|
751
|
+
const port = 4800;
|
|
752
|
+
try {
|
|
753
|
+
if (isPortReachableSync(host, port, 500)) {
|
|
754
|
+
_acptoapiBoot = { spawned_at: 0, pid: null, status: 'already-running' };
|
|
755
|
+
return;
|
|
756
|
+
}
|
|
757
|
+
if (_acptoapiBoot.spawned_at && Date.now() - _acptoapiBoot.spawned_at < 30000) {
|
|
758
|
+
return;
|
|
759
|
+
}
|
|
760
|
+
const isWindows = process.platform === 'win32';
|
|
761
|
+
const cmd = isWindows ? 'bun.exe' : 'bun';
|
|
762
|
+
const child = spawn(cmd, ['x', 'acptoapi@latest'], {
|
|
763
|
+
detached: true,
|
|
764
|
+
stdio: 'ignore',
|
|
765
|
+
windowsHide: true,
|
|
766
|
+
shell: false,
|
|
767
|
+
});
|
|
768
|
+
child.unref();
|
|
769
|
+
_acptoapiBoot = { spawned_at: Date.now(), pid: child.pid, status: 'spawned' };
|
|
770
|
+
logEvent('bootstrap', 'acptoapi.spawned', { pid: child.pid, port });
|
|
771
|
+
} catch (e) {
|
|
772
|
+
logEvent('bootstrap', 'acptoapi.spawn-failed', { error: e && e.message });
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
|
|
736
776
|
function findFreePortSync() {
|
|
737
777
|
const r = spawnSync(process.execPath, ['-e', `
|
|
738
778
|
const net = require('net');
|
|
@@ -1555,6 +1595,7 @@ async function runSpoolWatcher(instance, spoolDir) {
|
|
|
1555
1595
|
fs.mkdirSync(outDir, { recursive: true });
|
|
1556
1596
|
|
|
1557
1597
|
try { ensureSpoolPollGate(process.env.CLAUDE_PROJECT_DIR || process.cwd()); } catch (_) {}
|
|
1598
|
+
try { ensureAcptoapi(); } catch (_) {}
|
|
1558
1599
|
|
|
1559
1600
|
const LOCK_PATH = path.join(spoolDir, '.watcher.lock');
|
|
1560
1601
|
let _ownWrapperSha12 = '';
|
|
@@ -2061,6 +2102,7 @@ async function runSpoolWatcher(instance, spoolDir) {
|
|
|
2061
2102
|
}
|
|
2062
2103
|
setInterval(writeStatus, 5000);
|
|
2063
2104
|
writeStatus();
|
|
2105
|
+
setInterval(() => { try { ensureAcptoapi(); } catch (_) {} }, 60000);
|
|
2064
2106
|
|
|
2065
2107
|
const UPDATE_AVAILABLE_PATH = path.join(spoolDir, '.update-available.json');
|
|
2066
2108
|
const UPDATE_CHECK_INTERVAL_MS = 5 * 60 * 1000;
|
package/gm.json
CHANGED
package/lib/spool-dispatch.js
CHANGED
|
@@ -173,91 +173,6 @@ function unsolicitedDocs(cwd) {
|
|
|
173
173
|
}
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
-
async function dispatchSpool(cmd, lang, body, timeoutMs, sessionId) {
|
|
177
|
-
const taskId = `${Date.now()}-${Math.random().toString(16).slice(2, 8)}`;
|
|
178
|
-
const langDir = lang.match(/^(nodejs|python|bash|typescript|go|rust|c|cpp|java|deno)$/) ? lang : 'nodejs';
|
|
179
|
-
const ext = {
|
|
180
|
-
nodejs: 'js',
|
|
181
|
-
python: 'py',
|
|
182
|
-
bash: 'sh',
|
|
183
|
-
typescript: 'ts',
|
|
184
|
-
go: 'go',
|
|
185
|
-
rust: 'rs',
|
|
186
|
-
c: 'c',
|
|
187
|
-
cpp: 'cpp',
|
|
188
|
-
java: 'java',
|
|
189
|
-
deno: 'ts'
|
|
190
|
-
}[langDir] || 'js';
|
|
191
|
-
|
|
192
|
-
const inDir = path.join(process.cwd(), '.gm', 'exec-spool', 'in', langDir);
|
|
193
|
-
const outDir = path.join(process.cwd(), '.gm', 'exec-spool', 'out');
|
|
194
|
-
const inFile = path.join(inDir, `${taskId}.${ext}`);
|
|
195
|
-
const jsonFile = path.join(outDir, `${taskId}.json`);
|
|
196
|
-
|
|
197
|
-
fs.mkdirSync(inDir, { recursive: true });
|
|
198
|
-
fs.mkdirSync(outDir, { recursive: true });
|
|
199
|
-
|
|
200
|
-
let sess = sessionId || process.env.CLAUDE_SESSION_ID || process.env.GM_SESSION_ID || '';
|
|
201
|
-
try {
|
|
202
|
-
const spoolDir = path.join(process.cwd(), '.gm', 'exec-spool');
|
|
203
|
-
if (!sess) {
|
|
204
|
-
const fallbackFile = path.join(spoolDir, '.session-fallback');
|
|
205
|
-
try { sess = fs.readFileSync(fallbackFile, 'utf8').trim(); } catch (_) {}
|
|
206
|
-
if (!sess) {
|
|
207
|
-
const cwdHash = require('crypto').createHash('sha1').update(process.cwd()).digest('hex').slice(0, 8);
|
|
208
|
-
sess = `machine-${cwdHash}-${Date.now().toString(36)}`;
|
|
209
|
-
try { fs.writeFileSync(fallbackFile, sess); } catch (_) {}
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
fs.writeFileSync(path.join(spoolDir, '.session-current'), sess);
|
|
213
|
-
} catch (_) {}
|
|
214
|
-
|
|
215
|
-
const code = sessionId ? `const SESSION_ID = '${sessionId}';\n${body}` : body;
|
|
216
|
-
fs.writeFileSync(inFile, code, 'utf8');
|
|
217
|
-
|
|
218
|
-
return pollForCompletion(jsonFile, timeoutMs, taskId);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
async function pollForCompletion(jsonFile, timeoutMs, taskId) {
|
|
222
|
-
const start = Date.now();
|
|
223
|
-
const interval = 50;
|
|
224
|
-
|
|
225
|
-
while (Date.now() - start < timeoutMs) {
|
|
226
|
-
if (fs.existsSync(jsonFile)) {
|
|
227
|
-
try {
|
|
228
|
-
const metadata = JSON.parse(fs.readFileSync(jsonFile, 'utf8'));
|
|
229
|
-
const outFile = jsonFile.replace(/\.json$/, '.out');
|
|
230
|
-
const errFile = jsonFile.replace(/\.json$/, '.err');
|
|
231
|
-
const stdout = fs.existsSync(outFile) ? fs.readFileSync(outFile, 'utf8') : '';
|
|
232
|
-
const stderr = fs.existsSync(errFile) ? fs.readFileSync(errFile, 'utf8') : '';
|
|
233
|
-
return {
|
|
234
|
-
ok: metadata.exitCode === 0 && !metadata.timedOut,
|
|
235
|
-
exitCode: metadata.exitCode,
|
|
236
|
-
stdout,
|
|
237
|
-
stderr,
|
|
238
|
-
durationMs: metadata.durationMs,
|
|
239
|
-
taskId,
|
|
240
|
-
timedOut: metadata.timedOut || false
|
|
241
|
-
};
|
|
242
|
-
} catch (e) {
|
|
243
|
-
await new Promise(r => setTimeout(r, interval));
|
|
244
|
-
}
|
|
245
|
-
} else {
|
|
246
|
-
await new Promise(r => setTimeout(r, interval));
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
return {
|
|
251
|
-
ok: false,
|
|
252
|
-
exitCode: -1,
|
|
253
|
-
stdout: '',
|
|
254
|
-
stderr: `[spool dispatch timeout after ${timeoutMs}ms]`,
|
|
255
|
-
durationMs: Date.now() - start,
|
|
256
|
-
taskId,
|
|
257
|
-
timedOut: true
|
|
258
|
-
};
|
|
259
|
-
}
|
|
260
|
-
|
|
261
176
|
function sessionMarkerPath(sessionId, kind) {
|
|
262
177
|
const cwd = process.cwd();
|
|
263
178
|
return path.join(cwd, '.gm', 'exec-spool', `.session-${kind}-${sessionId || 'anon'}`);
|
|
@@ -458,4 +373,4 @@ function checkDispatchGates(sessionId, operation, extra) {
|
|
|
458
373
|
return { allowed: true };
|
|
459
374
|
}
|
|
460
375
|
|
|
461
|
-
module.exports = {
|
|
376
|
+
module.exports = { checkDispatchGates, isWorktreeDirty, hasUnpushedCommits, unsolicitedDocs, logDeviation, markInstructionSeen, hasDispatchedInstruction, isSpoolPollCommand, SPOOL_POLL_REASON, recordBrowserEdit, markBrowserWitnessed, clearBrowserTurnMarkers, isBrowserRunningFile, readBrowserEdits, isBrowserWitnessed };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gm-skill",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1225",
|
|
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.1225"
|
|
43
43
|
},
|
|
44
44
|
"engines": {
|
|
45
45
|
"node": ">=16.0.0"
|