gm-kilo 2.0.21 → 2.0.23

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.
Files changed (5) hide show
  1. package/cli.js +38 -37
  2. package/gm-kilo.mjs +25 -0
  3. package/gm.js +1 -77
  4. package/index.js +1 -1
  5. package/package.json +2 -1
package/cli.js CHANGED
@@ -2,41 +2,18 @@
2
2
  const fs = require('fs');
3
3
  const path = require('path');
4
4
  const os = require('os');
5
- const { execSync } = require('child_process');
6
5
 
7
6
  const homeDir = process.env.HOME || process.env.USERPROFILE || os.homedir();
8
- const destDir = process.platform === 'win32'
9
- ? path.join(homeDir, 'AppData', 'Roaming', 'kilo', 'plugin')
10
- : path.join(homeDir, '.config', 'kilo', 'plugin');
11
-
7
+ const kiloConfigDir = path.join(homeDir, '.config', 'kilo');
12
8
  const srcDir = __dirname;
13
- const isUpgrade = fs.existsSync(destDir);
9
+ const pluginMarker = path.join(kiloConfigDir, 'plugins', 'gm-kilo.mjs');
10
+ const isUpgrade = fs.existsSync(pluginMarker);
14
11
 
15
12
  console.log(isUpgrade ? 'Upgrading gm-kilo...' : 'Installing gm-kilo...');
16
13
 
17
14
  try {
18
- // Clean managed subdirectories to remove stale files from old versions
19
- for (const dir of ['agents', 'hooks', 'skills']) {
20
- const p = path.join(destDir, dir);
21
- if (fs.existsSync(p)) fs.rmSync(p, { recursive: true, force: true });
22
- }
23
- fs.mkdirSync(destDir, { recursive: true });
24
-
25
- const filesToCopy = [
26
- ['agents', 'agents'],
27
- ['hooks', 'hooks'],
28
- ['skills', 'skills'],
29
- ['index.js', 'index.js'],
30
- ['gm.js', 'gm.js'],
31
- ['kilocode.json', 'kilocode.json'],
32
- ['package.json', 'package.json'],
33
- ['.mcp.json', '.mcp.json'],
34
- ['README.md', 'README.md'],
35
- ['LICENSE', 'LICENSE'],
36
- ['CONTRIBUTING.md', 'CONTRIBUTING.md'],
37
- ['.gitignore', '.gitignore'],
38
- ['.editorconfig', '.editorconfig']
39
- ];
15
+ fs.mkdirSync(path.join(kiloConfigDir, 'plugins'), { recursive: true });
16
+ fs.mkdirSync(path.join(kiloConfigDir, 'agents'), { recursive: true });
40
17
 
41
18
  function copyRecursive(src, dst) {
42
19
  if (!fs.existsSync(src)) return;
@@ -48,19 +25,43 @@ try {
48
25
  }
49
26
  }
50
27
 
51
- filesToCopy.forEach(([src, dst]) => copyRecursive(path.join(srcDir, src), path.join(destDir, dst)));
28
+ // Install ESM plugin for kilo auto-loading from plugins directory
29
+ fs.copyFileSync(path.join(srcDir, 'gm-kilo.mjs'), path.join(kiloConfigDir, 'plugins', 'gm-kilo.mjs'));
30
+
31
+ // Copy agents and skills into kilo config dir
32
+ copyRecursive(path.join(srcDir, 'agents'), path.join(kiloConfigDir, 'agents'));
33
+ copyRecursive(path.join(srcDir, 'skills'), path.join(kiloConfigDir, 'skills'));
52
34
 
35
+ // Write/fix kilocode.json — merge MCP from package, set default_agent, fix $schema
36
+ const kiloJsonPath = path.join(kiloConfigDir, 'kilocode.json');
37
+ let kiloConfig = {};
53
38
  try {
54
- console.log('Installing dependencies...');
55
- execSync('npm install', { cwd: destDir, stdio: 'inherit' });
56
- } catch (e) {
57
- console.warn('npm install encountered an issue, but installation may still work');
39
+ const raw = fs.readFileSync(kiloJsonPath, 'utf-8');
40
+ kiloConfig = JSON.parse(raw);
41
+ // Fix corrupted $schema key (written as "" in older versions)
42
+ if (kiloConfig['']) { delete kiloConfig['']; }
43
+ } catch (e) {}
44
+ try {
45
+ const pkgConfig = JSON.parse(fs.readFileSync(path.join(srcDir, 'kilocode.json'), 'utf-8'));
46
+ if (pkgConfig.mcp) kiloConfig.mcp = Object.assign({}, pkgConfig.mcp, kiloConfig.mcp);
47
+ } catch (e) {}
48
+ kiloConfig['$schema'] = 'https://kilo.ai/config.json';
49
+ kiloConfig.default_agent = 'gm';
50
+ // Remove stale local-path plugin reference
51
+ if (Array.isArray(kiloConfig.plugin)) {
52
+ kiloConfig.plugin = kiloConfig.plugin.filter(p => !path.isAbsolute(p) && !p.startsWith('C:') && !p.startsWith('/'));
53
+ if (kiloConfig.plugin.length === 0) delete kiloConfig.plugin;
54
+ }
55
+ fs.writeFileSync(kiloJsonPath, JSON.stringify(kiloConfig, null, 2) + '\n');
56
+
57
+ // Clean old AppData install location (no longer used by kilo)
58
+ const oldDir = process.platform === 'win32'
59
+ ? path.join(homeDir, 'AppData', 'Roaming', 'kilo', 'plugin') : null;
60
+ if (oldDir && fs.existsSync(oldDir)) {
61
+ try { fs.rmSync(oldDir, { recursive: true, force: true }); } catch (e) {}
58
62
  }
59
63
 
60
- const destPath = process.platform === 'win32'
61
- ? destDir.replace(/\\/g, '/')
62
- : destDir;
63
- console.log(`✓ gm-kilo ${isUpgrade ? 'upgraded' : 'installed'} to ${destPath}`);
64
+ console.log(`✓ gm-kilo ${isUpgrade ? 'upgraded' : 'installed'} to ${kiloConfigDir}`);
64
65
  console.log('Restart Kilo CLI to activate.');
65
66
  } catch (e) {
66
67
  console.error('Installation failed:', e.message);
package/gm-kilo.mjs ADDED
@@ -0,0 +1,25 @@
1
+ import { readFileSync, existsSync } from 'fs';
2
+ import { join, dirname } from 'path';
3
+ import { fileURLToPath } from 'url';
4
+
5
+ const __dirname = dirname(fileURLToPath(import.meta.url));
6
+
7
+ export async function GmPlugin({ directory }) {
8
+ const agentMd = join(__dirname, '..', 'agents', 'gm.md');
9
+ const prdFile = join(directory, '.prd');
10
+
11
+ return {
12
+ 'experimental.chat.system.transform': async (input, output) => {
13
+ try {
14
+ const rules = readFileSync(agentMd, 'utf-8');
15
+ if (rules) output.system.unshift(rules);
16
+ } catch (e) {}
17
+ try {
18
+ if (existsSync(prdFile)) {
19
+ const prd = readFileSync(prdFile, 'utf-8').trim();
20
+ if (prd) output.system.push('\nPENDING WORK (.prd):\n' + prd);
21
+ }
22
+ } catch (e) {}
23
+ }
24
+ };
25
+ }
package/gm.js CHANGED
@@ -1,77 +1 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
-
4
- const GmPlugin = async ({ project, client, $, directory, worktree }) => {
5
- const pluginDir = __dirname;
6
- let agentRules = '';
7
-
8
- const loadAgentRules = () => {
9
- if (agentRules) return agentRules;
10
- const agentMd = path.join(pluginDir, 'agents', 'gm.md');
11
- try { agentRules = fs.readFileSync(agentMd, 'utf-8'); } catch (e) {}
12
- return agentRules;
13
- };
14
-
15
- const runSessionIdle = async () => {
16
- if (!client || !client.tui) return;
17
- const blockReasons = [];
18
- try {
19
- const status = await $`git status --porcelain`.timeout(2000).nothrow();
20
- if (status.exitCode === 0 && status.stdout.trim().length > 0)
21
- blockReasons.push('Git: Uncommitted changes exist');
22
- } catch (e) {}
23
- try {
24
- const ahead = await $`git rev-list --count @{u}..HEAD`.timeout(2000).nothrow();
25
- if (ahead.exitCode === 0 && parseInt(ahead.stdout.trim()) > 0)
26
- blockReasons.push('Git: ' + ahead.stdout.trim() + ' commit(s) not pushed');
27
- } catch (e) {}
28
- try {
29
- const behind = await $`git rev-list --count HEAD..@{u}`.timeout(2000).nothrow();
30
- if (behind.exitCode === 0 && parseInt(behind.stdout.trim()) > 0)
31
- blockReasons.push('Git: ' + behind.stdout.trim() + ' upstream change(s) not pulled');
32
- } catch (e) {}
33
- const prdFile = path.join(directory, '.prd');
34
- if (fs.existsSync(prdFile)) {
35
- const prd = fs.readFileSync(prdFile, 'utf-8').trim();
36
- if (prd.length > 0) blockReasons.push('Work items remain in .prd:\n' + prd);
37
- }
38
- if (blockReasons.length > 0) throw new Error(blockReasons.join(' | '));
39
- const filesToRun = [];
40
- const evalJs = path.join(directory, 'eval.js');
41
- if (fs.existsSync(evalJs)) filesToRun.push('eval.js');
42
- const evalsDir = path.join(directory, 'evals');
43
- if (fs.existsSync(evalsDir) && fs.statSync(evalsDir).isDirectory()) {
44
- filesToRun.push(...fs.readdirSync(evalsDir)
45
- .filter(f => f.endsWith('.js') && !path.join(evalsDir, f).includes('/lib/'))
46
- .sort().map(f => path.join('evals', f)));
47
- }
48
- for (const file of filesToRun) {
49
- try { await $`node ${file}`.timeout(60000); } catch (e) {
50
- throw new Error('eval error: ' + e.message + '\n' + (e.stdout || '') + '\n' + (e.stderr || ''));
51
- }
52
- }
53
- };
54
-
55
- const prdFile = path.join(directory, '.prd');
56
-
57
- return {
58
- onLoad: async () => {
59
- console.log('✓ gm plugin loaded');
60
- },
61
-
62
- getSystemPrompt: async () => {
63
- const rules = loadAgentRules();
64
- const prd = fs.existsSync(prdFile) ? fs.readFileSync(prdFile, 'utf-8').trim() : '';
65
- let prompt = rules || '';
66
- if (prd) prompt += '\n\nPENDING WORK (.prd):\n' + prd;
67
- return prompt;
68
- },
69
-
70
- onSessionEnd: async () => {
71
- const prd = fs.existsSync(prdFile) ? fs.readFileSync(prdFile, 'utf-8').trim() : '';
72
- if (prd) throw new Error('Work items remain in .prd - commit changes before exiting');
73
- }
74
- };
75
- };
76
-
77
- module.exports = { GmPlugin };
1
+ module.exports = require('./gm-kilo.mjs');
package/index.js CHANGED
@@ -1 +1 @@
1
- module.exports = { GmPlugin: require('./gm.js').GmPlugin };
1
+ module.exports = { GmPlugin: require('./gm-kilo.mjs').GmPlugin };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-kilo",
3
- "version": "2.0.21",
3
+ "version": "2.0.23",
4
4
  "description": "Advanced Claude Code plugin with WFGY integration, MCP tools, and automated hooks",
5
5
  "author": "AnEntrypoint",
6
6
  "license": "MIT",
@@ -42,6 +42,7 @@
42
42
  "skills/",
43
43
  "scripts/",
44
44
  "gm.js",
45
+ "gm-kilo.mjs",
45
46
  "index.js",
46
47
  "kilocode.json",
47
48
  ".github/",