gm-kilo 2.0.1058 → 2.0.1060

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/cli.js CHANGED
@@ -33,6 +33,7 @@ try {
33
33
  copyRecursive(path.join(srcDir, 'lang'), path.join(kiloConfigDir, 'lang'));
34
34
  copyRecursive(path.join(srcDir, 'bin'), path.join(kiloConfigDir, 'bin'));
35
35
  copyRecursive(path.join(srcDir, 'hooks'), path.join(kiloConfigDir, 'hooks'));
36
+ copyRecursive(path.join(srcDir, 'scripts'), path.join(kiloConfigDir, 'scripts'));
36
37
 
37
38
  const kiloJsonPath = path.join(kiloConfigDir, 'kilocode.json');
38
39
  let kiloConfig = {};
package/gm-kilo.mjs CHANGED
@@ -15,64 +15,32 @@ function runPlugkit(args) {
15
15
  const bin = join(__dirname, '..', 'bin', 'plugkit.js');
16
16
  if (!existsSync(bin)) return '';
17
17
  try {
18
- const r = spawnSync('node', [bin, ...args], { encoding: 'utf-8', timeout: 15000, windowsHide: true });
18
+ const r = spawnSync('node', [bin, ...args], { encoding: 'utf-8', timeout: 300000, windowsHide: true });
19
19
  return (r.stdout || '').trim() || (r.stderr || '').trim();
20
20
  } catch(e) { return ''; }
21
21
  }
22
22
 
23
23
  function safePrintf(s) {
24
- return "printf '%s' '" + String(s).replace(/\\\\/g,'\\\\\\\\').replace(/'/g,"'\\\\''")+"'";
24
+ return "printf '%s' '" + String(s).replace(/'/g,"'\\\\''")+"'";
25
25
  }
26
26
 
27
27
  function stripFooter(s) { return s ? s.replace(/\n\[Running tools\][\s\S]*$/, '').trimEnd() : ''; }
28
28
 
29
- function tryLangPlugin(lang, code, cwd) {
30
- const projectDir = cwd || process.cwd();
31
- const candidates = [join(projectDir, 'lang', lang+'.js'), join(__dirname, '..', 'lang', lang+'.js')];
32
- for (const langPluginFile of candidates) {
33
- if (!existsSync(langPluginFile)) continue;
34
- try {
35
- const plugin = require(langPluginFile);
36
- if (plugin && plugin.exec && plugin.exec.run) {
37
- const result = plugin.exec.run(code, projectDir);
38
- if (result && typeof result.then === 'function') continue;
39
- return String(result === undefined ? '' : result);
40
- }
41
- } catch(e) {}
42
- }
43
- return null;
44
- }
45
-
46
29
  function runExecSync(rawLang, code, cwd) {
47
30
  const lang = LANG_ALIASES[rawLang] || rawLang || 'nodejs';
48
- const opts = { encoding: 'utf-8', timeout: 30000, windowsHide: true, ...(cwd && { cwd }) };
49
- const out = (r) => { const o = (r.stdout||'').trimEnd(), e = stripFooter(r.stderr||'').trimEnd(); return o && e ? o+'\n[stderr]\n'+e : o||e||'(no output)'; };
50
- if (lang === 'codesearch' || lang === 'search') return runPlugkit(['search', '--path', cwd || process.cwd(), code.trim()]);
51
- if (lang === 'runner') return runPlugkit(['runner', code.trim()]);
52
- if (lang === 'status') return runPlugkit(['status', code.trim()]);
53
- if (lang === 'sleep') return runPlugkit(['sleep', code.trim()]);
54
- if (lang === 'close') return runPlugkit(['close', code.trim()]);
55
- if (lang === 'browser') return runPlugkit(['exec', '--lang', 'browser', '--code', code.trim(), '--cwd', cwd || process.cwd()]);
56
- if (lang === 'cmd') return out(spawnSync('cmd',['/c',code],opts));
57
- const pluginResult = tryLangPlugin(lang, code, cwd);
58
- if (pluginResult !== null) return pluginResult;
59
- if (lang === 'python') return out(spawnSync('python3',['-c',code],opts));
60
- if (lang === 'bash' || lang === 'sh') {
61
- const tmp = join(tmpdir(),'gm-exec-'+Date.now()+'.sh');
62
- writeFileSync(tmp,code,'utf-8');
63
- const r = spawnSync('bash',[tmp],opts);
64
- try { unlinkSync(tmp); } catch(e) {}
65
- return out(r);
31
+ const projectDir = cwd || process.cwd();
32
+ if (lang === 'codesearch' || lang === 'search') return runPlugkit(['search', '--path', projectDir, code.trim()]);
33
+ if (['runner','status','sleep','close'].includes(lang)) return runPlugkit([lang, code.trim()]);
34
+ if (['browser','tail','watch','wait','type','kill-port','health','recall','memorize','forget','feedback','discipline','pause'].includes(lang)) {
35
+ return runPlugkit(['exec', '--lang', lang, '--code', code.trim(), '--cwd', projectDir]);
66
36
  }
67
- const ext = lang === 'typescript' ? 'ts' : 'mjs';
68
- const tmp = join(tmpdir(),'gm-exec-'+Date.now()+'.'+ext);
69
- const src = lang === 'typescript' ? code : 'const __r=await(async()=>{\n'+code+'\n})();if(__r!==undefined){if(typeof __r==="object"){console.log(JSON.stringify(__r,null,2));}else{console.log(__r);}}';
70
- writeFileSync(tmp,src,'utf-8');
71
- const r = spawnSync('bun',['run',tmp],opts);
72
- try { unlinkSync(tmp); } catch(e) {}
73
- let result = out(r);
74
- if (result) result = result.split(tmp).join('<script>');
75
- return result;
37
+ if (lang === 'cmd') {
38
+ const opts = { encoding: 'utf-8', timeout: 30000, windowsHide: true, cwd: projectDir };
39
+ const r = spawnSync('cmd', ['/c', code], opts);
40
+ const o = (r.stdout || '').trimEnd(), e = stripFooter(r.stderr || '').trimEnd();
41
+ return o && e ? o + '\n[stderr]\n' + e : o || e || '(no output)';
42
+ }
43
+ return runPlugkit(['exec', '--lang', lang, '--code', code.trim(), '--cwd', projectDir]);
76
44
  }
77
45
 
78
46
  const BANNED_BASH = ['grep','rg','find','glob','awk','sed','cat','head','tail'];
@@ -90,6 +58,7 @@ export async function GmPlugin({ directory }) {
90
58
 
91
59
  return {
92
60
  'experimental.chat.system.transform': async (input, output) => {
61
+ const gmDir = join(directory, '.gm');
93
62
  try {
94
63
  const giPath = join(directory, '.gitignore');
95
64
  const entry = '.gm-stop-verified';
@@ -113,6 +82,12 @@ export async function GmPlugin({ directory }) {
113
82
  if (prd) output.system.push('\nPENDING WORK (.prd):\n'+prd);
114
83
  }
115
84
  } catch(e) {}
85
+ try {
86
+ const needsGmPath = join(gmDir, 'needs-gm');
87
+ if (existsSync(needsGmPath)) {
88
+ output.system.push('\nCRITICAL: You MUST invoke the `gm` skill before any other tool. Your current state is BLOCKED by a safety gate until gm runs.');
89
+ }
90
+ } catch(e) {}
116
91
  },
117
92
 
118
93
  'experimental.chat.messages.transform': async (input, output) => {
@@ -207,10 +182,10 @@ export async function GmPlugin({ directory }) {
207
182
  if (input.tool !== 'bash' && input.tool !== 'Bash' && input.tool !== 'shell' && input.tool !== 'Shell' && input.tool !== 'spawn/exec') return;
208
183
  const cmd = (output.args && output.args.command) || '';
209
184
  if (!cmd) return;
210
- if (/^\s*git(?:\s|$)/.test(cmd)) return;
211
- const m = cmd.match(/^exec(?::(\S+))?\n([\s\S]+)$/);
185
+ if (/^\s*(git|gh)(?:\s|$)/.test(cmd)) return;
186
+ const m = cmd.match(/^exec(?::(\S+))?\s*\n([\s\S]+)$/);
212
187
  if (!m) {
213
- throw new Error('Use exec: prefix for Bash. The command must start with `exec` or `exec:<lang>` on its own line, then the body on the next line. Examples:\n\nexec\nls -la\n\nexec:nodejs\nconsole.log("hello")\n\nexec:bash\ngit status\n\nLanguages: nodejs (default), bash, python, typescript, go, rust, deno, cmd. File I/O via exec:nodejs + require("fs"). Raw JIT execution can also bypass Bash entirely: write to `.gm/exec-spool/in/<lang>/<N>.<ext>` (e.g. in/nodejs/42.js) and the spool watcher executes it and writes `.gm/exec-spool/out/<N>.json`. Codebase search: exec:codesearch on its own line, then a two-word query.');
188
+ throw new Error('Use exec: prefix for Bash. The command must start with `exec` or `exec:<lang>` on its own line, then the body on the next line. Examples:\\n\\nexec\\nls -la\\n\\nexec:nodejs\\nconsole.log("hello")\\n\\nexec:bash\\ngit status\\n\\nLanguages: nodejs (default), bash, python, typescript, go, rust, deno, cmd. File I/O via exec:nodejs + require("fs"). Raw JIT execution can also bypass Bash entirely: write to `.gm/exec-spool/in/<lang>/<N>.<ext>` (e.g. in/nodejs/42.js) and the spool watcher executes it and writes `.gm/exec-spool/out/<N>.json`. Codebase search: exec:codesearch on its own line, then a two-word query.');
214
189
  }
215
190
  const rawLang = (m[1]||'').toLowerCase();
216
191
  if (rawLang === 'bash' || rawLang === 'sh' || rawLang === '') {
@@ -218,7 +193,7 @@ export async function GmPlugin({ directory }) {
218
193
  if (banned) throw new Error('`'+banned+'` is blocked in exec:bash. Use exec:codesearch instead. For raw JIT execution, write code to `.gm/exec-spool/in/<lang>/<N>.<ext>` (e.g. in/nodejs/42.js); the spool watcher executes it and writes out/<N>.json.');
219
194
  }
220
195
  const result = runExecSync(m[1]||'', m[2], output.args.workdir || directory);
221
- output.args = { ...output.args, command: safePrintf('exec:'+(m[1]||'nodejs')+' output:\n\n'+result) };
196
+ throw new Error('exec:'+(m[1]||'nodejs')+' output:\n\n'+result);
222
197
  },
223
198
  'message.updated': async (input, output) => {
224
199
  try {
package/install.js CHANGED
@@ -33,10 +33,14 @@ function install() {
33
33
  if (!isInsideNodeModules()) return;
34
34
  const projectRoot = getProjectRoot();
35
35
  if (!projectRoot) return;
36
- const kiloDir = path.join(projectRoot, '.config', 'kilo', 'plugin');
36
+ const kiloDir = path.join(projectRoot, '.kilo', 'plugins', 'gm-kilo');
37
37
  const sourceDir = __dirname;
38
38
  safeCopyDirectory(path.join(sourceDir, 'agents'), path.join(kiloDir, 'agents'));
39
39
  safeCopyDirectory(path.join(sourceDir, 'hooks'), path.join(kiloDir, 'hooks'));
40
+ safeCopyDirectory(path.join(sourceDir, 'bin'), path.join(kiloDir, 'bin'));
41
+ safeCopyDirectory(path.join(sourceDir, 'skills'), path.join(kiloDir, 'skills'));
42
+ safeCopyDirectory(path.join(sourceDir, 'lang'), path.join(kiloDir, 'lang'));
43
+ safeCopyDirectory(path.join(sourceDir, 'scripts'), path.join(kiloDir, 'scripts'));
40
44
  }
41
45
 
42
46
  install();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-kilo",
3
- "version": "2.0.1058",
3
+ "version": "2.0.1060",
4
4
  "description": "State machine agent with hooks, skills, and automated git enforcement",
5
5
  "author": "AnEntrypoint",
6
6
  "license": "MIT",