gm-oc 2.0.10 → 2.0.12
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/.mcp.json +2 -2
- package/gm.js +11 -73
- package/opencode.json +2 -2
- package/package.json +1 -1
package/.mcp.json
CHANGED
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
"$schema": "https://schemas.modelcontextprotocol.io/0.1.0/mcp.json",
|
|
3
3
|
"mcpServers": {
|
|
4
4
|
"dev": {
|
|
5
|
-
"command": "
|
|
5
|
+
"command": "bun x",
|
|
6
6
|
"args": [
|
|
7
7
|
"mcp-gm@latest"
|
|
8
8
|
],
|
|
9
9
|
"timeout": 360000
|
|
10
10
|
},
|
|
11
11
|
"code-search": {
|
|
12
|
-
"command": "
|
|
12
|
+
"command": "bun x",
|
|
13
13
|
"args": [
|
|
14
14
|
"codebasesearch@latest"
|
|
15
15
|
],
|
package/gm.js
CHANGED
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
|
-
const { analyze } = require('mcp-thorns');
|
|
4
|
-
|
|
5
|
-
const SHELL_TOOLS = ['bash'];
|
|
6
|
-
const SEARCH_TOOLS = ['glob', 'grep', 'list'];
|
|
7
|
-
|
|
8
|
-
let thornsOutput = '';
|
|
9
3
|
|
|
10
4
|
const GmPlugin = async ({ project, client, $, directory, worktree }) => {
|
|
11
5
|
const pluginDir = __dirname;
|
|
@@ -18,80 +12,24 @@ const GmPlugin = async ({ project, client, $, directory, worktree }) => {
|
|
|
18
12
|
return agentRules;
|
|
19
13
|
};
|
|
20
14
|
|
|
21
|
-
const
|
|
22
|
-
try {
|
|
23
|
-
thornsOutput = '=== mcp-thorns ===\n' + analyze(directory);
|
|
24
|
-
} catch (e) {
|
|
25
|
-
thornsOutput = '=== mcp-thorns ===\nSkipped (' + e.message + ')';
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const runSessionIdle = async () => {
|
|
30
|
-
if (!client || !client.tui) return;
|
|
31
|
-
const blockReasons = [];
|
|
32
|
-
try {
|
|
33
|
-
const status = await $`git status --porcelain`.timeout(2000).nothrow();
|
|
34
|
-
if (status.exitCode === 0 && status.stdout.trim().length > 0)
|
|
35
|
-
blockReasons.push('Git: Uncommitted changes exist');
|
|
36
|
-
} catch (e) {}
|
|
37
|
-
try {
|
|
38
|
-
const ahead = await $`git rev-list --count @{u}..HEAD`.timeout(2000).nothrow();
|
|
39
|
-
if (ahead.exitCode === 0 && parseInt(ahead.stdout.trim()) > 0)
|
|
40
|
-
blockReasons.push('Git: ' + ahead.stdout.trim() + ' commit(s) not pushed');
|
|
41
|
-
} catch (e) {}
|
|
42
|
-
try {
|
|
43
|
-
const behind = await $`git rev-list --count HEAD..@{u}`.timeout(2000).nothrow();
|
|
44
|
-
if (behind.exitCode === 0 && parseInt(behind.stdout.trim()) > 0)
|
|
45
|
-
blockReasons.push('Git: ' + behind.stdout.trim() + ' upstream change(s) not pulled');
|
|
46
|
-
} catch (e) {}
|
|
47
|
-
const prdFile = path.join(directory, '.prd');
|
|
48
|
-
if (fs.existsSync(prdFile)) {
|
|
49
|
-
const prd = fs.readFileSync(prdFile, 'utf-8').trim();
|
|
50
|
-
if (prd.length > 0) blockReasons.push('Work items remain in .prd:\n' + prd);
|
|
51
|
-
}
|
|
52
|
-
if (blockReasons.length > 0) throw new Error(blockReasons.join(' | '));
|
|
53
|
-
};
|
|
15
|
+
const prdFile = path.join(directory, '.prd');
|
|
54
16
|
|
|
55
17
|
return {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
else if (event.type === 'session.idle') await runSessionIdle();
|
|
18
|
+
onLoad: async () => {
|
|
19
|
+
console.log('✓ gm plugin loaded');
|
|
59
20
|
},
|
|
60
21
|
|
|
61
|
-
|
|
62
|
-
const tool = input.tool;
|
|
63
|
-
if (SHELL_TOOLS.includes(tool)) {
|
|
64
|
-
throw new Error('Use dev MCP tool for command execution');
|
|
65
|
-
}
|
|
66
|
-
if (SEARCH_TOOLS.includes(tool)) {
|
|
67
|
-
throw new Error('Use code-search MCP tool or dev MCP tool for code exploration');
|
|
68
|
-
}
|
|
69
|
-
if (tool === 'write' || tool === 'edit' || tool === 'patch') {
|
|
70
|
-
const fp = output.args?.file_path || output.args?.filePath || output.args?.path || '';
|
|
71
|
-
const ext = path.extname(fp);
|
|
72
|
-
const base = path.basename(fp).toLowerCase();
|
|
73
|
-
const inSkills = fp.includes('/skills/');
|
|
74
|
-
if ((ext === '.md' || ext === '.txt' || base.startsWith('features_list')) &&
|
|
75
|
-
!base.startsWith('claude') && !base.startsWith('readme') && !base.startsWith('gm') && !inSkills) {
|
|
76
|
-
throw new Error('Cannot create documentation files. Only CLAUDE.md, GM.md, and README.md are maintained.');
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
},
|
|
80
|
-
|
|
81
|
-
'experimental.chat.system.transform': async (input, output) => {
|
|
22
|
+
getSystemPrompt: async () => {
|
|
82
23
|
const rules = loadAgentRules();
|
|
83
|
-
|
|
84
|
-
|
|
24
|
+
const prd = fs.existsSync(prdFile) ? fs.readFileSync(prdFile, 'utf-8').trim() : '';
|
|
25
|
+
let prompt = rules || '';
|
|
26
|
+
if (prd) prompt += '\n\nPENDING WORK (.prd):\n' + prd;
|
|
27
|
+
return prompt;
|
|
85
28
|
},
|
|
86
29
|
|
|
87
|
-
|
|
88
|
-
const
|
|
89
|
-
if (
|
|
90
|
-
const prdFile = path.join(directory, '.prd');
|
|
91
|
-
if (fs.existsSync(prdFile)) {
|
|
92
|
-
const prd = fs.readFileSync(prdFile, 'utf-8').trim();
|
|
93
|
-
if (prd.length > 0) output.context.push('PENDING WORK (.prd):\n' + prd);
|
|
94
|
-
}
|
|
30
|
+
onSessionEnd: async () => {
|
|
31
|
+
const prd = fs.existsSync(prdFile) ? fs.readFileSync(prdFile, 'utf-8').trim() : '';
|
|
32
|
+
if (prd) throw new Error('Work items remain in .prd - commit changes before exiting');
|
|
95
33
|
}
|
|
96
34
|
};
|
|
97
35
|
};
|
package/opencode.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"mcp": {
|
|
5
5
|
"dev": {
|
|
6
6
|
"type": "local",
|
|
7
|
-
"command": "
|
|
7
|
+
"command": "bun x",
|
|
8
8
|
"args": [
|
|
9
9
|
"mcp-gm@latest"
|
|
10
10
|
],
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
},
|
|
14
14
|
"code-search": {
|
|
15
15
|
"type": "local",
|
|
16
|
-
"command": "
|
|
16
|
+
"command": "bun x",
|
|
17
17
|
"args": [
|
|
18
18
|
"codebasesearch@latest"
|
|
19
19
|
],
|