gm-copilot-cli 2.0.76 → 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.
- package/copilot-profile.md +1 -1
- package/hooks/pre-tool-use-hook.js +1 -11
- package/hooks/prompt-submit-hook.js +1 -1
- package/hooks/session-start-hook.js +7 -34
- package/manifest.yml +1 -1
- package/package.json +1 -1
- package/scripts/postinstall-kilo.js +119 -0
- package/scripts/postinstall-oc.js +118 -0
- package/tools.json +1 -1
package/copilot-profile.md
CHANGED
|
@@ -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({
|
|
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({
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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/manifest.yml
CHANGED
package/package.json
CHANGED
|
@@ -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();
|