gm-kilo 2.0.1061 → 2.0.1062
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/gm-kilo.mjs +61 -15
- package/package.json +1 -1
package/gm-kilo.mjs
CHANGED
|
@@ -2,7 +2,6 @@ import { readFileSync, existsSync, writeFileSync, unlinkSync } from 'fs';
|
|
|
2
2
|
import { join, dirname, extname, basename } from 'path';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
4
|
import { spawnSync } from 'child_process';
|
|
5
|
-
import { tmpdir } from 'os';
|
|
6
5
|
|
|
7
6
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
7
|
const LANG_ALIASES = { js:'nodejs',javascript:'nodejs',ts:'typescript',node:'nodejs',py:'python',sh:'bash',shell:'bash',zsh:'bash' };
|
|
@@ -29,18 +28,53 @@ function stripFooter(s) { return s ? s.replace(/\n\[Running tools\][\s\S]*$/, ''
|
|
|
29
28
|
function runExecSync(rawLang, code, cwd) {
|
|
30
29
|
const lang = LANG_ALIASES[rawLang] || rawLang || 'nodejs';
|
|
31
30
|
const projectDir = cwd || process.cwd();
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
31
|
+
const spoolBase = join(projectDir, '.gm', 'exec-spool');
|
|
32
|
+
const taskId = Date.now() + '-' + Math.random().toString(16).slice(2, 8);
|
|
33
|
+
|
|
34
|
+
const isVerb = ['codesearch','recall','memorize','wait','sleep','status','close','browser','runner','type','kill-port','forget','feedback','discipline','pause','health'].includes(lang);
|
|
35
|
+
const langDir = lang.match(/^(nodejs|python|bash|typescript|go|rust|c|cpp|java|deno)$/) ? lang : 'nodejs';
|
|
36
|
+
const ext = {nodejs:'js',python:'py',bash:'sh',typescript:'ts',go:'go',rust:'rs',c:'c',cpp:'cpp',java:'java',deno:'ts'}[langDir] || 'js';
|
|
37
|
+
|
|
38
|
+
const inDir = join(spoolBase, 'in', isVerb ? lang : langDir);
|
|
39
|
+
const outDir = join(spoolBase, 'out');
|
|
40
|
+
const inFile = join(inDir, taskId + (isVerb ? '.txt' : '.' + ext));
|
|
41
|
+
const jsonFile = join(outDir, taskId + '.json');
|
|
42
|
+
|
|
43
|
+
try { fs.mkdirSync(inDir, { recursive: true }); fs.mkdirSync(outDir, { recursive: true }); } catch(e) {}
|
|
44
|
+
writeFileSync(inFile, code, 'utf-8');
|
|
45
|
+
|
|
46
|
+
const start = Date.now();
|
|
47
|
+
while (Date.now() - start < 28000) {
|
|
48
|
+
if (existsSync(jsonFile)) {
|
|
49
|
+
try {
|
|
50
|
+
const meta = JSON.parse(readFileSync(jsonFile, 'utf-8'));
|
|
51
|
+
const outFile = jsonFile.replace(/\.json$/, '.out');
|
|
52
|
+
const errFile = jsonFile.replace(/\.json$/, '.err');
|
|
53
|
+
const stdout = existsSync(outFile) ? readFileSync(outFile, 'utf-8') : '';
|
|
54
|
+
const stderr = existsSync(errFile) ? readFileSync(errFile, 'utf-8') : '';
|
|
55
|
+
const o = stdout.trimEnd(), e = stripFooter(stderr).trimEnd();
|
|
56
|
+
return o && e ? o + '\n[stderr]\n' + e : o || e || '(no output)';
|
|
57
|
+
} catch(e) {}
|
|
58
|
+
}
|
|
59
|
+
try { require('child_process').execSync('sleep 0.05', { stdio: 'ignore' }); } catch(e) { const s = Date.now(); while(Date.now()-s<50){} }
|
|
42
60
|
}
|
|
43
|
-
return
|
|
61
|
+
return '[spool dispatch timeout after 28s]';
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function ensureSpoolWatcher(dir) {
|
|
65
|
+
try {
|
|
66
|
+
const spoolBase = join(dir, '.gm', 'exec-spool');
|
|
67
|
+
const pidFile = join(spoolBase, '.watcher.pid');
|
|
68
|
+
try { fs.mkdirSync(spoolBase, { recursive: true }); } catch(e) {}
|
|
69
|
+
const alreadyRunning = existsSync(pidFile) && (() => { try { const p = parseInt(readFileSync(pidFile,'utf-8')); process.kill(p,0); return true; } catch(e) { return false; } })();
|
|
70
|
+
if (!alreadyRunning) {
|
|
71
|
+
const r = spawnSync('node', [join(__dirname, '..', 'bin', 'plugkit.js'), 'spool'], {
|
|
72
|
+
detached: true, stdio: 'ignore', windowsHide: true,
|
|
73
|
+
env: { ...process.env, GM_SPOOL_DIR: spoolBase }
|
|
74
|
+
});
|
|
75
|
+
if (r.pid) { try { writeFileSync(pidFile, String(r.pid), 'utf-8'); } catch(e) {} }
|
|
76
|
+
}
|
|
77
|
+
} catch(e) {}
|
|
44
78
|
}
|
|
45
79
|
|
|
46
80
|
const BANNED_BASH = ['grep','rg','find','glob','awk','sed','cat','head','tail'];
|
|
@@ -61,7 +95,19 @@ export async function GmPlugin({ directory }) {
|
|
|
61
95
|
if (!sessionStarted) {
|
|
62
96
|
sessionStarted = true;
|
|
63
97
|
try { runPlugkit(['hook', 'session-start']); } catch(e) {}
|
|
64
|
-
try {
|
|
98
|
+
try {
|
|
99
|
+
const spoolBase = join(directory, '.gm', 'exec-spool');
|
|
100
|
+
const pidFile = join(spoolBase, '.watcher.pid');
|
|
101
|
+
try { fs.mkdirSync(spoolBase, { recursive: true }); } catch(e) {}
|
|
102
|
+
const alreadyRunning = existsSync(pidFile) && (() => { try { const p = parseInt(readFileSync(pidFile,'utf-8')); process.kill(p,0); return true; } catch(e) { return false; } })();
|
|
103
|
+
if (!alreadyRunning) {
|
|
104
|
+
const r = spawnSync('node', [join(__dirname, '..', 'bin', 'plugkit.js'), 'spool'], {
|
|
105
|
+
detached: true, stdio: 'ignore', windowsHide: true,
|
|
106
|
+
env: { ...process.env, GM_SPOOL_DIR: spoolBase }
|
|
107
|
+
});
|
|
108
|
+
if (r.pid) { try { writeFileSync(pidFile, String(r.pid), 'utf-8'); } catch(e) {} }
|
|
109
|
+
}
|
|
110
|
+
} catch(e) {}
|
|
65
111
|
}
|
|
66
112
|
},
|
|
67
113
|
|
|
@@ -81,7 +127,7 @@ export async function GmPlugin({ directory }) {
|
|
|
81
127
|
if (!sessionStarted) {
|
|
82
128
|
sessionStarted = true;
|
|
83
129
|
try { runPlugkit(['hook', 'session-start']); } catch(e) {}
|
|
84
|
-
try {
|
|
130
|
+
try { ensureSpoolWatcher(directory); } catch(e) {}
|
|
85
131
|
}
|
|
86
132
|
try { const rules = readFileSync(agentMd,'utf-8'); if (rules) output.system.unshift(rules); } catch(e) {}
|
|
87
133
|
try {
|
|
@@ -132,7 +178,7 @@ export async function GmPlugin({ directory }) {
|
|
|
132
178
|
if (!sessionStarted) {
|
|
133
179
|
sessionStarted = true;
|
|
134
180
|
try { runPlugkit(['hook', 'session-start']); } catch(e) {}
|
|
135
|
-
try {
|
|
181
|
+
try { ensureSpoolWatcher(directory); } catch(e) {}
|
|
136
182
|
}
|
|
137
183
|
const skillName = (args.skill || args.name || '').toString();
|
|
138
184
|
if (FORBIDDEN_TOOLS.has(input.tool)) {
|