gm-gc 2.0.75 → 2.0.78

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm",
3
- "version": "2.0.75",
3
+ "version": "2.0.78",
4
4
  "description": "State machine agent with hooks, skills, and automated git enforcement",
5
5
  "author": "AnEntrypoint",
6
6
  "homepage": "https://github.com/AnEntrypoint/gm",
@@ -76,22 +76,12 @@ try {
76
76
  if (isGemini) {
77
77
  console.log(JSON.stringify({ decision: 'deny', reason: result.reason }));
78
78
  } else {
79
- console.log(JSON.stringify({ hookSpecificOutput: { hookEventName: 'PreToolUse', permissionDecision: 'deny', permissionDecisionReason: result.reason } }));
79
+ console.log(JSON.stringify({ decision: 'block', reason: result.reason }));
80
80
  }
81
81
  process.exit(0);
82
82
  }
83
83
 
84
- if (isGemini) {
85
- console.log(JSON.stringify({ decision: 'allow' }));
86
- } else {
87
- console.log(JSON.stringify({ hookSpecificOutput: { hookEventName: 'PreToolUse', permissionDecision: 'allow' } }));
88
- }
89
84
  process.exit(0);
90
85
  } catch (error) {
91
- if (isGemini) {
92
- console.log(JSON.stringify({ decision: 'allow' }));
93
- } else {
94
- console.log(JSON.stringify({ hookSpecificOutput: { hookEventName: 'PreToolUse', permissionDecision: 'allow' } }));
95
- }
96
86
  process.exit(0);
97
87
  }
@@ -65,7 +65,7 @@ const emit = (additionalContext) => {
65
65
  } else if (isOpenCode) {
66
66
  console.log(JSON.stringify({ hookSpecificOutput: { hookEventName: 'message.updated', additionalContext } }, null, 2));
67
67
  } else {
68
- console.log(JSON.stringify({ hookSpecificOutput: { hookEventName: 'UserPromptSubmit', additionalContext } }, null, 2));
68
+ console.log(JSON.stringify({ additionalContext }, null, 2));
69
69
  }
70
70
  };
71
71
 
@@ -4,7 +4,7 @@ const fs = require('fs');
4
4
  const path = require('path');
5
5
  const { execSync } = require('child_process');
6
6
 
7
- const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT || process.env.GEMINI_PROJECT_DIR || process.env.OC_PLUGIN_ROOT || process.env.KILO_PLUGIN_ROOT;
7
+ const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT || process.env.GEMINI_PROJECT_DIR || process.env.OC_PLUGIN_ROOT || process.env.KILO_PLUGIN_ROOT || path.join(__dirname, '..');
8
8
  const projectDir = process.env.CLAUDE_PROJECT_DIR || process.env.GEMINI_PROJECT_DIR || process.env.OC_PROJECT_DIR || process.env.KILO_PROJECT_DIR;
9
9
 
10
10
  const ensureGitignore = () => {
@@ -116,26 +116,11 @@ When exploring unfamiliar code, finding similar patterns, understanding integrat
116
116
  const isKilo = process.env.KILO_PLUGIN_ROOT !== undefined;
117
117
 
118
118
  if (isGemini) {
119
- const result = {
120
- systemMessage: additionalContext
121
- };
122
- console.log(JSON.stringify(result, null, 2));
119
+ console.log(JSON.stringify({ systemMessage: additionalContext }, null, 2));
123
120
  } else if (isOpenCode || isKilo) {
124
- const result = {
125
- hookSpecificOutput: {
126
- hookEventName: 'session.created',
127
- additionalContext
128
- }
129
- };
130
- console.log(JSON.stringify(result, null, 2));
121
+ console.log(JSON.stringify({ hookSpecificOutput: { hookEventName: 'session.created', additionalContext } }, null, 2));
131
122
  } else {
132
- const result = {
133
- hookSpecificOutput: {
134
- hookEventName: 'SessionStart',
135
- additionalContext
136
- }
137
- };
138
- console.log(JSON.stringify(result, null, 2));
123
+ console.log(JSON.stringify({ additionalContext }, null, 2));
139
124
  }
140
125
  } catch (error) {
141
126
  const isGemini = process.env.GEMINI_PROJECT_DIR !== undefined;
@@ -143,23 +128,11 @@ When exploring unfamiliar code, finding similar patterns, understanding integrat
143
128
  const isKilo = process.env.KILO_PLUGIN_ROOT !== undefined;
144
129
 
145
130
  if (isGemini) {
146
- console.log(JSON.stringify({
147
- systemMessage: `Error executing hook: ${error.message}`
148
- }, null, 2));
131
+ console.log(JSON.stringify({ systemMessage: `Error executing hook: ${error.message}` }, null, 2));
149
132
  } else if (isOpenCode || isKilo) {
150
- console.log(JSON.stringify({
151
- hookSpecificOutput: {
152
- hookEventName: 'session.created',
153
- additionalContext: `Error executing hook: ${error.message}`
154
- }
155
- }, null, 2));
133
+ console.log(JSON.stringify({ hookSpecificOutput: { hookEventName: 'session.created', additionalContext: `Error executing hook: ${error.message}` } }, null, 2));
156
134
  } else {
157
- console.log(JSON.stringify({
158
- hookSpecificOutput: {
159
- hookEventName: 'SessionStart',
160
- additionalContext: `Error executing hook: ${error.message}`
161
- }
162
- }, null, 2));
135
+ console.log(JSON.stringify({ additionalContext: `Error executing hook: ${error.message}` }, null, 2));
163
136
  }
164
137
  process.exit(0);
165
138
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-gc",
3
- "version": "2.0.75",
3
+ "version": "2.0.78",
4
4
  "description": "State machine agent with hooks, skills, and automated git enforcement",
5
5
  "author": "AnEntrypoint",
6
6
  "license": "MIT",
@@ -0,0 +1,119 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const { execSync } = require('child_process');
6
+
7
+ function isInsideNodeModules() {
8
+ return __dirname.includes(path.sep + 'node_modules' + path.sep);
9
+ }
10
+
11
+ function getProjectRoot() {
12
+ if (!isInsideNodeModules()) return null;
13
+ let current = __dirname;
14
+ while (current !== path.dirname(current)) {
15
+ current = path.dirname(current);
16
+ if (path.basename(current) === 'node_modules') {
17
+ return path.dirname(current);
18
+ }
19
+ }
20
+ return null;
21
+ }
22
+
23
+ function safeCopyFile(src, dst) {
24
+ try {
25
+ const content = fs.readFileSync(src, 'utf-8');
26
+ const dstDir = path.dirname(dst);
27
+ if (!fs.existsSync(dstDir)) fs.mkdirSync(dstDir, { recursive: true });
28
+ fs.writeFileSync(dst, content, 'utf-8');
29
+ return true;
30
+ } catch (e) {
31
+ return false;
32
+ }
33
+ }
34
+
35
+ function safeCopyDirectory(src, dst) {
36
+ try {
37
+ if (!fs.existsSync(src)) return false;
38
+ fs.mkdirSync(dst, { recursive: true });
39
+ fs.readdirSync(src, { withFileTypes: true }).forEach(entry => {
40
+ const srcPath = path.join(src, entry.name);
41
+ const dstPath = path.join(dst, entry.name);
42
+ if (entry.isDirectory()) safeCopyDirectory(srcPath, dstPath);
43
+ else if (entry.isFile()) safeCopyFile(srcPath, dstPath);
44
+ });
45
+ return true;
46
+ } catch (e) {
47
+ return false;
48
+ }
49
+ }
50
+
51
+ function updateGitignore(projectRoot) {
52
+ try {
53
+ const gitignorePath = path.join(projectRoot, '.gitignore');
54
+ const entry = '.gm-stop-verified';
55
+ let content = fs.existsSync(gitignorePath) ? fs.readFileSync(gitignorePath, 'utf-8') : '';
56
+ if (content.includes(entry)) return true;
57
+ if (content && !content.endsWith('\n')) content += '\n';
58
+ fs.writeFileSync(gitignorePath, content + entry + '\n', 'utf-8');
59
+ return true;
60
+ } catch (e) {
61
+ return false;
62
+ }
63
+ }
64
+
65
+ function install() {
66
+ if (!isInsideNodeModules()) return;
67
+ const projectRoot = getProjectRoot();
68
+ if (!projectRoot) return;
69
+ const kiloDir = path.join(projectRoot, '.config', 'kilo');
70
+ const sourceDir = __dirname.replace(/[/\\]scripts$/, '');
71
+
72
+ // Copy files
73
+ safeCopyDirectory(path.join(sourceDir, 'agents'), path.join(kiloDir, 'agents'));
74
+ safeCopyDirectory(path.join(sourceDir, 'hooks'), path.join(kiloDir, 'hooks'));
75
+ safeCopyDirectory(path.join(sourceDir, 'skills'), path.join(kiloDir, 'skills'));
76
+ safeCopyFile(path.join(sourceDir, 'kilocode.json'), path.join(kiloDir, 'kilocode.json'));
77
+ safeCopyFile(path.join(sourceDir, '.mcp.json'), path.join(kiloDir, '.mcp.json'));
78
+ safeCopyFile(path.join(sourceDir, 'gm.mjs'), path.join(kiloDir, 'gm.mjs'));
79
+ safeCopyFile(path.join(sourceDir, 'index.mjs'), path.join(kiloDir, 'index.mjs'));
80
+ safeCopyFile(path.join(sourceDir, 'README.md'), path.join(kiloDir, 'README.md'));
81
+ safeCopyFile(path.join(sourceDir, 'LICENSE'), path.join(kiloDir, 'LICENSE'));
82
+ safeCopyFile(path.join(sourceDir, 'CONTRIBUTING.md'), path.join(kiloDir, 'CONTRIBUTING.md'));
83
+ safeCopyFile(path.join(sourceDir, '.gitignore'), path.join(kiloDir, '.gitignore'));
84
+ safeCopyFile(path.join(sourceDir, '.editorconfig'), path.join(kiloDir, '.editorconfig'));
85
+
86
+ // Also write plugin/ directory - Kilo loads from ~/.config/kilo/plugin/ as a local file plugin
87
+ const pluginDir = path.join(kiloDir, 'plugin');
88
+ if (!fs.existsSync(pluginDir)) fs.mkdirSync(pluginDir, { recursive: true });
89
+ const gmMjsSrc = path.join(sourceDir, 'gm.mjs');
90
+ if (fs.existsSync(gmMjsSrc)) {
91
+ safeCopyFile(gmMjsSrc, path.join(pluginDir, 'gm.mjs'));
92
+ }
93
+ fs.writeFileSync(path.join(pluginDir, 'index.js'), "export { default } from './gm.mjs';\n", 'utf-8');
94
+
95
+ // Update .gitignore
96
+ updateGitignore(projectRoot);
97
+
98
+ // Warm bun x cache for packages used by hooks
99
+ warmBunCache();
100
+
101
+ // Silent success
102
+ }
103
+
104
+ function warmBunCache() {
105
+ const packages = ['mcp-thorns@latest', 'codebasesearch@latest'];
106
+ for (const pkg of packages) {
107
+ try {
108
+ execSync(`bun x ${pkg} --version`, {
109
+ encoding: 'utf-8',
110
+ stdio: 'pipe',
111
+ timeout: 60000
112
+ });
113
+ } catch (e) {
114
+ // Silent - cache warming is best-effort
115
+ }
116
+ }
117
+ }
118
+
119
+ install();
@@ -0,0 +1,118 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const { execSync } = require('child_process');
6
+
7
+ function isInsideNodeModules() {
8
+ return __dirname.includes(path.sep + 'node_modules' + path.sep);
9
+ }
10
+
11
+ function getProjectRoot() {
12
+ if (!isInsideNodeModules()) return null;
13
+ let current = __dirname;
14
+ while (current !== path.dirname(current)) {
15
+ current = path.dirname(current);
16
+ if (path.basename(current) === 'node_modules') {
17
+ return path.dirname(current);
18
+ }
19
+ }
20
+ return null;
21
+ }
22
+
23
+ function safeCopyFile(src, dst) {
24
+ try {
25
+ const content = fs.readFileSync(src, 'utf-8');
26
+ const dstDir = path.dirname(dst);
27
+ if (!fs.existsSync(dstDir)) fs.mkdirSync(dstDir, { recursive: true });
28
+ fs.writeFileSync(dst, content, 'utf-8');
29
+ return true;
30
+ } catch (e) {
31
+ return false;
32
+ }
33
+ }
34
+
35
+ function safeCopyDirectory(src, dst) {
36
+ try {
37
+ if (!fs.existsSync(src)) return false;
38
+ fs.mkdirSync(dst, { recursive: true });
39
+ fs.readdirSync(src, { withFileTypes: true }).forEach(entry => {
40
+ const srcPath = path.join(src, entry.name);
41
+ const dstPath = path.join(dst, entry.name);
42
+ if (entry.isDirectory()) safeCopyDirectory(srcPath, dstPath);
43
+ else if (entry.isFile()) safeCopyFile(srcPath, dstPath);
44
+ });
45
+ return true;
46
+ } catch (e) {
47
+ return false;
48
+ }
49
+ }
50
+
51
+ function updateGitignore(projectRoot) {
52
+ try {
53
+ const gitignorePath = path.join(projectRoot, '.gitignore');
54
+ const entry = '.gm-stop-verified';
55
+ let content = fs.existsSync(gitignorePath) ? fs.readFileSync(gitignorePath, 'utf-8') : '';
56
+ if (content.includes(entry)) return true;
57
+ if (content && !content.endsWith('\n')) content += '\n';
58
+ fs.writeFileSync(gitignorePath, content + entry + '\n', 'utf-8');
59
+ return true;
60
+ } catch (e) {
61
+ return false;
62
+ }
63
+ }
64
+
65
+ function install() {
66
+ if (!isInsideNodeModules()) return;
67
+ const projectRoot = getProjectRoot();
68
+ if (!projectRoot) return;
69
+ const ocDir = path.join(projectRoot, '.config', 'opencode');
70
+ const sourceDir = __dirname.replace(/[/\\]scripts$/, '');
71
+
72
+ // Copy files
73
+ safeCopyDirectory(path.join(sourceDir, 'agents'), path.join(ocDir, 'agents'));
74
+ safeCopyDirectory(path.join(sourceDir, 'hooks'), path.join(ocDir, 'hooks'));
75
+ safeCopyDirectory(path.join(sourceDir, 'skills'), path.join(ocDir, 'skills'));
76
+ safeCopyFile(path.join(sourceDir, 'opencode.json'), path.join(ocDir, 'opencode.json'));
77
+ safeCopyFile(path.join(sourceDir, '.mcp.json'), path.join(ocDir, '.mcp.json'));
78
+ safeCopyFile(path.join(sourceDir, 'gm.mjs'), path.join(ocDir, 'gm.mjs'));
79
+ safeCopyFile(path.join(sourceDir, 'index.mjs'), path.join(ocDir, 'index.mjs'));
80
+ safeCopyFile(path.join(sourceDir, 'README.md'), path.join(ocDir, 'README.md'));
81
+ safeCopyFile(path.join(sourceDir, 'LICENSE'), path.join(ocDir, 'LICENSE'));
82
+ safeCopyFile(path.join(sourceDir, 'CONTRIBUTING.md'), path.join(ocDir, 'CONTRIBUTING.md'));
83
+ safeCopyFile(path.join(sourceDir, '.gitignore'), path.join(ocDir, '.gitignore'));
84
+ safeCopyFile(path.join(sourceDir, '.editorconfig'), path.join(ocDir, '.editorconfig'));
85
+
86
+ // Also write to plugins/gm-oc.mjs - the actual file OpenCode loads
87
+ const pluginsDir = path.join(ocDir, 'plugins');
88
+ if (!fs.existsSync(pluginsDir)) fs.mkdirSync(pluginsDir, { recursive: true });
89
+ const gmMjsSrc = path.join(sourceDir, 'gm.mjs');
90
+ if (fs.existsSync(gmMjsSrc)) {
91
+ safeCopyFile(gmMjsSrc, path.join(pluginsDir, 'gm-oc.mjs'));
92
+ }
93
+
94
+ // Update .gitignore
95
+ updateGitignore(projectRoot);
96
+
97
+ // Warm bun x cache for packages used by hooks
98
+ warmBunCache();
99
+
100
+ // Silent success
101
+ }
102
+
103
+ function warmBunCache() {
104
+ const packages = ['mcp-thorns@latest', 'codebasesearch@latest'];
105
+ for (const pkg of packages) {
106
+ try {
107
+ execSync(`bun x ${pkg} --version`, {
108
+ encoding: 'utf-8',
109
+ stdio: 'pipe',
110
+ timeout: 60000
111
+ });
112
+ } catch (e) {
113
+ // Silent - cache warming is best-effort
114
+ }
115
+ }
116
+ }
117
+
118
+ install();