gm-copilot-cli 2.0.244 → 2.0.246
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 +23 -8
- package/hooks/prompt-submit-hook.js +14 -4
- package/hooks/session-start-hook.js +40 -30
- package/index.html +1 -1
- package/manifest.yml +1 -1
- package/package.json +1 -1
- package/tools.json +1 -1
package/copilot-profile.md
CHANGED
|
@@ -13,7 +13,7 @@ const projectDir = process.env.CLAUDE_PROJECT_DIR || process.env.GEMINI_PROJECT_
|
|
|
13
13
|
const TOOLS_DIR = path.join(os.homedir(), '.claude', 'gm-tools');
|
|
14
14
|
const CHECK_STAMP = path.join(TOOLS_DIR, '.last-check');
|
|
15
15
|
const PKG_JSON = path.join(TOOLS_DIR, 'package.json');
|
|
16
|
-
const MANAGED_PKGS = ['
|
|
16
|
+
const MANAGED_PKGS = ['agent-browser'];
|
|
17
17
|
const CHECK_INTERVAL_MS = 60 * 1000; // 60 seconds
|
|
18
18
|
|
|
19
19
|
function ensureToolsDir() {
|
|
@@ -124,12 +124,27 @@ function loadLangPlugins(projectDir) {
|
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
// Helper: run a local binary (falls back to bunx if not installed)
|
|
127
|
+
function pkgEntry(name) {
|
|
128
|
+
try {
|
|
129
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(TOOLS_DIR, 'node_modules', name, 'package.json'), 'utf8'));
|
|
130
|
+
const binVal = pkg.bin;
|
|
131
|
+
const rel = typeof binVal === 'string' ? binVal : (binVal?.[name] || Object.values(binVal || {})[0]);
|
|
132
|
+
if (rel) return path.join(TOOLS_DIR, 'node_modules', name, rel);
|
|
133
|
+
} catch {}
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
|
|
127
137
|
function runLocal(name, args, opts = {}) {
|
|
138
|
+
if (IS_WIN) {
|
|
139
|
+
const entry = pkgEntry(name);
|
|
140
|
+
if (entry && fs.existsSync(entry)) {
|
|
141
|
+
return spawnSync('bun', [entry, ...args], { encoding: 'utf8', windowsHide: true, timeout: 65000, ...opts });
|
|
142
|
+
}
|
|
143
|
+
}
|
|
128
144
|
const bin = localBin(name);
|
|
129
145
|
if (fs.existsSync(bin)) {
|
|
130
146
|
return spawnSync(bin, args, { encoding: 'utf8', windowsHide: true, timeout: 65000, ...opts });
|
|
131
147
|
}
|
|
132
|
-
// Fallback to bunx
|
|
133
148
|
return spawnSync('bun', ['x', name, ...args], { encoding: 'utf8', windowsHide: true, timeout: 65000, ...opts });
|
|
134
149
|
}
|
|
135
150
|
|
|
@@ -163,15 +178,15 @@ const allowWithNoop = (context) => {
|
|
|
163
178
|
};
|
|
164
179
|
};
|
|
165
180
|
|
|
166
|
-
// ───
|
|
167
|
-
function
|
|
181
|
+
// ─── plugkit runner helper ────────────────────────────────────────────────────
|
|
182
|
+
function plugkitBin() { return path.join(TOOLS_DIR, IS_WIN ? 'plugkit.exe' : 'plugkit'); }
|
|
168
183
|
|
|
169
184
|
function runGmExec(args, opts = {}) {
|
|
170
|
-
const bin =
|
|
185
|
+
const bin = plugkitBin();
|
|
171
186
|
if (fs.existsSync(bin)) {
|
|
172
187
|
return spawnSync(bin, args, { encoding: 'utf8', windowsHide: true, timeout: 65000, ...opts });
|
|
173
188
|
}
|
|
174
|
-
return spawnSync('
|
|
189
|
+
return spawnSync('plugkit', args, { encoding: 'utf8', windowsHide: true, timeout: 65000, ...opts });
|
|
175
190
|
}
|
|
176
191
|
|
|
177
192
|
// ─── Main hook ────────────────────────────────────────────────────────────────
|
|
@@ -394,7 +409,7 @@ const run = () => {
|
|
|
394
409
|
|
|
395
410
|
if (['codesearch', 'search'].includes(lang)) {
|
|
396
411
|
const query = safeCode.trim();
|
|
397
|
-
const r =
|
|
412
|
+
const r = runGmExec(['search', ...(cwd ? ['--path', cwd] : []), query], { timeout: 30000, ...(cwd && { cwd }) });
|
|
398
413
|
return allowWithNoop(`exec:${lang} output:\n\n${stripFooter((r.stdout || '') + (r.stderr || '')) || '(no results)'}`);
|
|
399
414
|
}
|
|
400
415
|
if (lang === 'status') {
|
|
@@ -462,7 +477,7 @@ const run = () => {
|
|
|
462
477
|
}
|
|
463
478
|
}
|
|
464
479
|
|
|
465
|
-
if (/^bun\s+x\s+(gm-exec|rs-exec|codebasesearch)/.test(command)) {
|
|
480
|
+
if (/^bun\s+x\s+(gm-exec|rs-exec|plugkit|codebasesearch)/.test(command)) {
|
|
466
481
|
return deny(`Do not call ${command.match(/^bun\s+x\s+(\S+)/)[1]} directly. Use exec:<lang> syntax instead.\n\nExamples:\n exec:nodejs\n console.log("hello")\n\n exec:codesearch\n find all database queries\n\n exec:bash\n ls -la\n\nThe exec: prefix routes through the hook dispatcher which handles language detection, background tasks, and tool management automatically.`);
|
|
467
482
|
}
|
|
468
483
|
|
|
@@ -26,6 +26,16 @@ function runLocal(name, args, opts = {}) {
|
|
|
26
26
|
return spawnSync('bun', ['x', name, ...args], { encoding: 'utf8', windowsHide: true, timeout: 30000, ...opts });
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
function plugkitBin() { return path.join(TOOLS_DIR, IS_WIN ? 'plugkit.exe' : 'plugkit'); }
|
|
30
|
+
|
|
31
|
+
function runPlugkit(args, opts = {}) {
|
|
32
|
+
const bin = plugkitBin();
|
|
33
|
+
if (fs.existsSync(bin)) {
|
|
34
|
+
return spawnSync(bin, args, { encoding: 'utf8', windowsHide: true, timeout: 30000, ...opts });
|
|
35
|
+
}
|
|
36
|
+
return spawnSync('plugkit', args, { encoding: 'utf8', windowsHide: true, timeout: 30000, ...opts });
|
|
37
|
+
}
|
|
38
|
+
|
|
29
39
|
const projectDir = process.env.CLAUDE_PROJECT_DIR || process.env.GEMINI_PROJECT_DIR || process.env.OC_PROJECT_DIR || process.env.KILO_PROJECT_DIR;
|
|
30
40
|
|
|
31
41
|
function loadLangPlugins(dir) {
|
|
@@ -107,9 +117,9 @@ const ensureGitignore = () => {
|
|
|
107
117
|
const runThorns = () => {
|
|
108
118
|
if (!projectDir || !fs.existsSync(projectDir)) return '';
|
|
109
119
|
try {
|
|
110
|
-
const r =
|
|
120
|
+
const r = runPlugkit(['codeinsight', projectDir], { timeout: 15000 });
|
|
111
121
|
const out = ((r.stdout || '') + (r.stderr || '')).trim();
|
|
112
|
-
return out ? `===
|
|
122
|
+
return out ? `=== codeinsight ===\n${out}` : '';
|
|
113
123
|
} catch (e) {
|
|
114
124
|
return '';
|
|
115
125
|
}
|
|
@@ -118,9 +128,9 @@ const runThorns = () => {
|
|
|
118
128
|
const runCodeSearch = (prompt) => {
|
|
119
129
|
if (!prompt || !projectDir) return '';
|
|
120
130
|
try {
|
|
121
|
-
const r =
|
|
131
|
+
const r = runPlugkit(['search', '--path', projectDir, prompt], { timeout: 10000, cwd: projectDir });
|
|
122
132
|
const out = ((r.stdout || '') + (r.stderr || '')).trim();
|
|
123
|
-
return out ? `===
|
|
133
|
+
return out ? `=== search ===\n${out}` : '';
|
|
124
134
|
} catch (e) {
|
|
125
135
|
return '';
|
|
126
136
|
}
|
|
@@ -13,7 +13,23 @@ function localBin(name) {
|
|
|
13
13
|
return path.join(TOOLS_DIR, 'node_modules', '.bin', name + ext);
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
function pkgEntry(name) {
|
|
17
|
+
try {
|
|
18
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(TOOLS_DIR, 'node_modules', name, 'package.json'), 'utf8'));
|
|
19
|
+
const binVal = pkg.bin;
|
|
20
|
+
const rel = typeof binVal === 'string' ? binVal : (binVal?.[name] || Object.values(binVal || {})[0]);
|
|
21
|
+
if (rel) return path.join(TOOLS_DIR, 'node_modules', name, rel);
|
|
22
|
+
} catch {}
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
|
|
16
26
|
function runLocal(name, args, opts = {}) {
|
|
27
|
+
if (IS_WIN) {
|
|
28
|
+
const entry = pkgEntry(name);
|
|
29
|
+
if (entry && fs.existsSync(entry)) {
|
|
30
|
+
return spawnSync('bun', [entry, ...args], { encoding: 'utf8', windowsHide: true, timeout: 30000, ...opts });
|
|
31
|
+
}
|
|
32
|
+
}
|
|
17
33
|
const bin = localBin(name);
|
|
18
34
|
if (fs.existsSync(bin)) {
|
|
19
35
|
return spawnSync(bin, args, { encoding: 'utf8', windowsHide: true, timeout: 30000, ...opts });
|
|
@@ -21,28 +37,22 @@ function runLocal(name, args, opts = {}) {
|
|
|
21
37
|
return spawnSync('bun', ['x', name, ...args], { encoding: 'utf8', windowsHide: true, timeout: 30000, ...opts });
|
|
22
38
|
}
|
|
23
39
|
|
|
24
|
-
const MANAGED_PKGS = ['
|
|
40
|
+
const MANAGED_PKGS = ['agent-browser'];
|
|
25
41
|
const PKG_JSON = path.join(TOOLS_DIR, 'package.json');
|
|
26
42
|
|
|
27
|
-
const
|
|
43
|
+
const PLUGKIT_REPO = 'AnEntrypoint/rs-plugkit';
|
|
28
44
|
const archMap = { x64: 'x86_64', arm64: 'aarch64', ia32: 'x86_64' };
|
|
29
|
-
const
|
|
30
|
-
win32: a => `
|
|
31
|
-
darwin: a => `
|
|
32
|
-
linux: a => `
|
|
33
|
-
};
|
|
34
|
-
const osProcTargets = {
|
|
35
|
-
win32: a => `rs-exec-process-${a}-pc-windows-msvcexe`,
|
|
36
|
-
darwin: a => `rs-exec-process-${a}-apple-darwin`,
|
|
37
|
-
linux: a => `rs-exec-process-${a}-unknown-linux-gnu`,
|
|
45
|
+
const plugkitTargets = {
|
|
46
|
+
win32: a => `plugkit-x86_64-pc-windows-msvc/plugkit.exe`,
|
|
47
|
+
darwin: a => `plugkit-x86_64-unknown-linux-gnu/plugkit`,
|
|
48
|
+
linux: a => `plugkit-x86_64-unknown-linux-gnu/plugkit`,
|
|
38
49
|
};
|
|
39
50
|
|
|
40
|
-
function
|
|
41
|
-
function rsExecProcessBin() { return path.join(TOOLS_DIR, IS_WIN ? 'rs-exec-process.exe' : 'rs-exec-process'); }
|
|
51
|
+
function plugkitBin() { return path.join(TOOLS_DIR, IS_WIN ? 'plugkit.exe' : 'plugkit'); }
|
|
42
52
|
|
|
43
|
-
function downloadBin(
|
|
53
|
+
function downloadBin(assetPath, dest) {
|
|
44
54
|
const https = require('https');
|
|
45
|
-
const url = `https://github.com/${
|
|
55
|
+
const url = `https://github.com/${PLUGKIT_REPO}/releases/latest/download/${assetPath}`;
|
|
46
56
|
return new Promise((resolve) => {
|
|
47
57
|
const follow = (u) => https.get(u, { headers: { 'User-Agent': 'gm' } }, res => {
|
|
48
58
|
if (res.statusCode >= 300 && res.statusCode < 400) return follow(res.headers.location);
|
|
@@ -54,15 +64,12 @@ function downloadBin(assetName, dest) {
|
|
|
54
64
|
});
|
|
55
65
|
}
|
|
56
66
|
|
|
57
|
-
async function
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
if (!fs.existsSync(mainBin)) downloads.push(downloadBin(osTargets[plat]?.(arch) || osTargets.linux(arch), mainBin));
|
|
64
|
-
if (!fs.existsSync(procBin)) downloads.push(downloadBin(osProcTargets[plat]?.(arch) || osProcTargets.linux(arch), procBin));
|
|
65
|
-
if (downloads.length) await Promise.all(downloads);
|
|
67
|
+
async function ensurePlugkit() {
|
|
68
|
+
const bin = plugkitBin();
|
|
69
|
+
if (!fs.existsSync(bin)) {
|
|
70
|
+
const assetPath = plugkitTargets[process.platform]?.(archMap[process.arch] || 'x86_64') || plugkitTargets.linux('x86_64');
|
|
71
|
+
await downloadBin(assetPath, bin);
|
|
72
|
+
}
|
|
66
73
|
}
|
|
67
74
|
|
|
68
75
|
function ensureTools() {
|
|
@@ -81,7 +88,7 @@ function ensureTools() {
|
|
|
81
88
|
}
|
|
82
89
|
|
|
83
90
|
ensureTools();
|
|
84
|
-
|
|
91
|
+
ensurePlugkit().catch(() => {});
|
|
85
92
|
|
|
86
93
|
const projectDir = process.env.CLAUDE_PROJECT_DIR || process.env.GEMINI_PROJECT_DIR || process.env.OC_PROJECT_DIR || process.env.KILO_PROJECT_DIR;
|
|
87
94
|
|
|
@@ -134,14 +141,17 @@ ensureGitignore();
|
|
|
134
141
|
try {
|
|
135
142
|
let outputs = [];
|
|
136
143
|
|
|
137
|
-
outputs.push('Use the Skill tool with skill: "gm" to begin — do NOT use the Agent tool to load skills. Skills are invoked via the Skill tool only, never as agents. All code execution uses exec:<lang> via the Bash tool — never direct Bash(node ...) or Bash(npm ...) or Bash(npx ...) or Bash(
|
|
144
|
+
outputs.push('Use the Skill tool with skill: "gm" to begin — do NOT use the Agent tool to load skills. Skills are invoked via the Skill tool only, never as agents. All code execution uses exec:<lang> via the Bash tool — never direct Bash(node ...) or Bash(npm ...) or Bash(npx ...) or Bash(plugkit ...).');
|
|
138
145
|
|
|
139
146
|
if (projectDir && fs.existsSync(projectDir)) {
|
|
140
147
|
try {
|
|
141
|
-
const
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
|
|
148
|
+
const bin = plugkitBin();
|
|
149
|
+
const r = fs.existsSync(bin)
|
|
150
|
+
? spawnSync(bin, ['codeinsight', projectDir], { encoding: 'utf8', windowsHide: true, timeout: 15000 })
|
|
151
|
+
: spawnSync('plugkit', ['codeinsight', projectDir], { encoding: 'utf8', windowsHide: true, timeout: 15000 });
|
|
152
|
+
const insightOutput = ((r.stdout || '') + (r.stderr || '')).trim();
|
|
153
|
+
if (insightOutput) {
|
|
154
|
+
outputs.push(`=== This is your initial insight of the repository, look at every possible aspect of this for initial opinionation and to offset the need for code exploration ===\n${insightOutput}`);
|
|
145
155
|
}
|
|
146
156
|
} catch (e) {}
|
|
147
157
|
}
|
package/index.html
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
<script type="module">
|
|
19
19
|
import { createElement as h, applyDiff, Fragment } from "webjsx";
|
|
20
20
|
const PLATFORM_NAME="Copilot CLI",PLATFORM_TYPE="CLI Tool",PLATFORM_TYPE_COLOR="#3b82f6";
|
|
21
|
-
const DESCRIPTION="State machine agent with hooks, skills, and automated git enforcement",VERSION="2.0.
|
|
21
|
+
const DESCRIPTION="State machine agent with hooks, skills, and automated git enforcement",VERSION="2.0.246";
|
|
22
22
|
const GITHUB_URL="https://github.com/AnEntrypoint/gm-copilot-cli",BADGE_LABEL="copilot-cli";
|
|
23
23
|
const FEATURES=[{"title":"State Machine","desc":"Immutable PLAN→EXECUTE→EMIT→VERIFY→COMPLETE phases with full mutable tracking"},{"title":"Semantic Search","desc":"Natural language codebase exploration via codesearch skill — no grep needed"},{"title":"Hooks","desc":"Pre-tool, session-start, prompt-submit, and stop hooks for full lifecycle control"},{"title":"Agents","desc":"gm, codesearch, and websearch agents pre-configured and ready to use"},{"title":"MCP Integration","desc":"Model Context Protocol server support built in"},{"title":"Auto-Recovery","desc":"Supervisor hierarchy ensures the system never crashes"}],INSTALL_STEPS=[{"desc":"Install via GitHub CLI","cmd":"gh extension install AnEntrypoint/gm-copilot-cli"},{"desc":"Restart your terminal — activates automatically"}];
|
|
24
24
|
const CURRENT_PLATFORM="gm-copilot-cli";
|
package/manifest.yml
CHANGED
package/package.json
CHANGED