gm-kilo 2.0.1064 → 2.0.1066

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/gm-kilo.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { readFileSync, existsSync, writeFileSync, unlinkSync } from 'fs';
2
2
  import { join, dirname, extname, basename } from 'path';
3
3
  import { fileURLToPath } from 'url';
4
- import { spawnSync } from 'child_process';
4
+ import { spawn, spawnSync } from 'child_process';
5
5
 
6
6
  const __dirname = dirname(fileURLToPath(import.meta.url));
7
7
  const LANG_ALIASES = { js:'nodejs',javascript:'nodejs',ts:'typescript',node:'nodejs',py:'python',sh:'bash',shell:'bash',zsh:'bash' };
@@ -14,11 +14,20 @@ function runPlugkit(args) {
14
14
  const bin = join(__dirname, '..', 'bin', 'plugkit.js');
15
15
  if (!existsSync(bin)) return '';
16
16
  try {
17
- const r = spawnSync('node', [bin, ...args], { encoding: 'utf-8', timeout: 300000, windowsHide: true });
17
+ const r = spawnSync('node', [bin, ...args], { encoding: 'utf-8', timeout: 15000, windowsHide: true });
18
18
  return (r.stdout || '').trim() || (r.stderr || '').trim();
19
19
  } catch(e) { return ''; }
20
20
  }
21
21
 
22
+ function runPlugkitDetached(args) {
23
+ const bin = join(__dirname, '..', 'bin', 'plugkit.js');
24
+ if (!existsSync(bin)) return;
25
+ try {
26
+ const child = spawn('node', [bin, ...args], { detached: true, stdio: 'ignore', windowsHide: true });
27
+ child.unref();
28
+ } catch(e) {}
29
+ }
30
+
22
31
  function safePrintf(s) {
23
32
  return "printf '%s' '" + String(s).replace(/'/g,"'\\\\''")+"'";
24
33
  }
@@ -68,11 +77,12 @@ function ensureSpoolWatcher(dir) {
68
77
  try { fs.mkdirSync(spoolBase, { recursive: true }); } catch(e) {}
69
78
  const alreadyRunning = existsSync(pidFile) && (() => { try { const p = parseInt(readFileSync(pidFile,'utf-8')); process.kill(p,0); return true; } catch(e) { return false; } })();
70
79
  if (!alreadyRunning) {
71
- const r = spawnSync('node', [join(__dirname, '..', 'bin', 'plugkit.js'), 'spool'], {
80
+ const child = spawn('node', [join(__dirname, '..', 'bin', 'plugkit.js'), 'spool'], {
72
81
  detached: true, stdio: 'ignore', windowsHide: true,
73
- env: { ...process.env, GM_SPOOL_DIR: spoolBase }
82
+ env: { ...process.env, RS_EXEC_SPOOL_DIR: spoolBase }
74
83
  });
75
- if (r.pid) { try { writeFileSync(pidFile, String(r.pid), 'utf-8'); } catch(e) {} }
84
+ child.unref();
85
+ if (child.pid) { try { writeFileSync(pidFile, String(child.pid), 'utf-8'); } catch(e) {} }
76
86
  }
77
87
  } catch(e) {}
78
88
  }
@@ -94,18 +104,19 @@ export async function GmPlugin({ directory }) {
94
104
  'session.created': async () => {
95
105
  if (!sessionStarted) {
96
106
  sessionStarted = true;
97
- try { runPlugkit(['hook', 'session-start']); } catch(e) {}
107
+ try { runPlugkitDetached(['hook', 'session-start']); } catch(e) {}
98
108
  try {
99
109
  const spoolBase = join(directory, '.gm', 'exec-spool');
100
110
  const pidFile = join(spoolBase, '.watcher.pid');
101
111
  try { fs.mkdirSync(spoolBase, { recursive: true }); } catch(e) {}
102
112
  const alreadyRunning = existsSync(pidFile) && (() => { try { const p = parseInt(readFileSync(pidFile,'utf-8')); process.kill(p,0); return true; } catch(e) { return false; } })();
103
113
  if (!alreadyRunning) {
104
- const r = spawnSync('node', [join(__dirname, '..', 'bin', 'plugkit.js'), 'spool'], {
114
+ const child = spawn('node', [join(__dirname, '..', 'bin', 'plugkit.js'), 'spool'], {
105
115
  detached: true, stdio: 'ignore', windowsHide: true,
106
- env: { ...process.env, GM_SPOOL_DIR: spoolBase }
116
+ env: { ...process.env, RS_EXEC_SPOOL_DIR: spoolBase }
107
117
  });
108
- if (r.pid) { try { writeFileSync(pidFile, String(r.pid), 'utf-8'); } catch(e) {} }
118
+ child.unref();
119
+ if (child.pid) { try { writeFileSync(pidFile, String(child.pid), 'utf-8'); } catch(e) {} }
109
120
  }
110
121
  } catch(e) {}
111
122
  }
@@ -126,7 +137,7 @@ export async function GmPlugin({ directory }) {
126
137
  } catch(e) {}
127
138
  if (!sessionStarted) {
128
139
  sessionStarted = true;
129
- try { runPlugkit(['hook', 'session-start']); } catch(e) {}
140
+ try { runPlugkitDetached(['hook', 'session-start']); } catch(e) {}
130
141
  try { ensureSpoolWatcher(directory); } catch(e) {}
131
142
  }
132
143
  try { const rules = readFileSync(agentMd,'utf-8'); if (rules) output.system.unshift(rules); } catch(e) {}
@@ -177,7 +188,7 @@ export async function GmPlugin({ directory }) {
177
188
  const args = (input.args || (output && output.args) || {});
178
189
  if (!sessionStarted) {
179
190
  sessionStarted = true;
180
- try { runPlugkit(['hook', 'session-start']); } catch(e) {}
191
+ try { runPlugkitDetached(['hook', 'session-start']); } catch(e) {}
181
192
  try { ensureSpoolWatcher(directory); } catch(e) {}
182
193
  }
183
194
  const skillName = (args.skill || args.name || '').toString();
package/install.js CHANGED
@@ -36,7 +36,6 @@ function install() {
36
36
  const kiloDir = path.join(projectRoot, '.kilo', 'plugins', 'gm-kilo');
37
37
  const sourceDir = __dirname;
38
38
  safeCopyDirectory(path.join(sourceDir, 'agents'), path.join(kiloDir, 'agents'));
39
- safeCopyDirectory(path.join(sourceDir, 'hooks'), path.join(kiloDir, 'hooks'));
40
39
  safeCopyDirectory(path.join(sourceDir, 'bin'), path.join(kiloDir, 'bin'));
41
40
  safeCopyDirectory(path.join(sourceDir, 'skills'), path.join(kiloDir, 'skills'));
42
41
  safeCopyDirectory(path.join(sourceDir, 'lang'), path.join(kiloDir, 'lang'));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-kilo",
3
- "version": "2.0.1064",
3
+ "version": "2.0.1066",
4
4
  "description": "State machine agent with hooks, skills, and automated git enforcement",
5
5
  "author": "AnEntrypoint",
6
6
  "license": "MIT",
@@ -6,7 +6,7 @@ allowed-tools: Skill
6
6
 
7
7
  # Browser automation
8
8
 
9
- Two pathways — never mix in the same Bash call.
9
+ Two pathways — never mix in the same spool dispatch.
10
10
 
11
11
  `exec:browser` runs JS against `page`. Globals available: `page`, `snapshot`, `screenshotWithAccessibilityLabels`, `state`. 15s live window, then backgrounds; output drains automatically on every subsequent plugkit call.
12
12
 
@@ -14,8 +14,9 @@ Two pathways — never mix in the same Bash call.
14
14
 
15
15
  ## Core
16
16
 
17
+ Write to `.gm/exec-spool/in/browser/<N>.txt`:
18
+
17
19
  ```
18
- exec:browser
19
20
  await page.goto('https://example.com')
20
21
  await snapshot({ page })
21
22
  ```
@@ -36,8 +37,9 @@ Session state persists across `browser:` calls. `-e` arg uses single quotes outs
36
37
 
37
38
  Never `await setTimeout(N)` with N > 10000. Poll instead.
38
39
 
40
+ Write to `.gm/exec-spool/in/browser/<N>.txt`:
41
+
39
42
  ```
40
- exec:browser
41
43
  const start = Date.now()
42
44
  while (!state.done && Date.now() - start < 12000) {
43
45
  await new Promise(r => setTimeout(r, 500))
@@ -49,31 +51,30 @@ console.log(state.result)
49
51
 
50
52
  ## Patterns
51
53
 
52
- Data extraction:
54
+ Data extraction — write to `.gm/exec-spool/in/browser/<N>.txt`:
53
55
 
54
56
  ```
55
- exec:browser
56
57
  const items = await page.$$eval('.title', els => els.map(e => e.textContent))
57
58
  console.log(JSON.stringify(items))
58
59
  ```
59
60
 
60
- Console monitoring — set listeners first, then poll:
61
+ Console monitoring — set listeners first, then poll. Write to `.gm/exec-spool/in/browser/<N>.txt`:
61
62
 
62
63
  ```
63
- exec:browser
64
64
  state.logs = []
65
65
  page.on('console', msg => state.logs.push({ type: msg.type(), text: msg.text() }))
66
66
  ```
67
67
 
68
+ Then write to `.gm/exec-spool/in/browser/<N+1>.txt`:
69
+
68
70
  ```
69
- exec:browser
70
71
  console.log(JSON.stringify(state.logs.slice(-20)))
71
72
  ```
72
73
 
73
74
  ## Constraints
74
75
 
75
76
  - One playwriter command per `browser:` block
76
- - `exec:browser` is plain JS, no shell quoting
77
+ - `exec:browser` body is plain JS, no shell quoting
77
78
  - Browser tasks drain automatically on every plugkit interaction
78
79
  - Sessions reap after 5–15 min idle; cleaned up on session end
79
80
  - Never write standalone `.mjs`/`.js` Playwright scripts as a fallback — `exec:browser` errors must be debugged through `exec:browser` retries, not by creating test files on disk
@@ -98,16 +98,16 @@ context: `=== mytool ===\nexec:mytool\n<expression>\n\nRuns via <how>. Use for <
98
98
 
99
99
  ## Verify
100
100
 
101
- ```
102
- exec:nodejs
101
+ Write to `.gm/exec-spool/in/nodejs/<N>.js`:
102
+
103
+ ```js
103
104
  const p = require('/abs/path/lang/mytool.js');
104
105
  console.log(p.id, typeof p.exec.run, p.exec.match.toString());
105
106
  ```
106
107
 
107
- Then test dispatch:
108
+ Then test dispatch by writing to `.gm/exec-spool/in/mytool/<N>.txt`:
108
109
 
109
110
  ```
110
- exec:mytool
111
111
  <simple test expression>
112
112
  ```
113
113
 
@@ -17,7 +17,7 @@ The user's request is authorization. When scope is unclear, pick the maximum rea
17
17
 
18
18
  **Every issue surfaces this turn**: pre-existing breaks, lint failures, drift, broken deps, stale generated files — all become PRD items and finish before COMPLETE.
19
19
 
20
- **LLM provider**: acptoapi (127.0.0.1:4800) is the preferred provider when available. rs-plugkit session_start spawns acptoapi daemon and auto-detects ACP agents (opencode, kilo-code, codex, gemini-cli, qwen-code). All downstream platforms (rs-learn, freddie, gm-skill daemon mode) read OPENAI_BASE_URL environment variable and default to 127.0.0.1:4800. Anthropic SDK is fallback only when acptoapi socket is unavailable (CI, headless mode).
20
+ **LLM provider**: rs-learn uses a 3-tier fallback chain: acptoapi HTTP (127.0.0.1:4800) ACP subprocess (opencode/kilo-code/codex/gemini-cli/qwen-code) → AGENTS.md content. All errors reported explicitly never silently absorbed. SWE-bench scores rank model fallback ordering (highest first). Downstream platforms read OPENAI_BASE_URL defaulting to 127.0.0.1:4800. Anthropic SDK only when acptoapi socket unavailable. acptoapi strips internal tools (fs_*, bash, python, ssh, recall, memorize, codesearch, etc.) before forwarding to providers.
21
21
 
22
22
  **rs-learn failure contract**: memorize, recall, and codesearch spool dispatch failures must be reported explicitly with error details to the user. Fallback to AGENTS.md for memory preservation when socket/network unavailable. Never silently absorb errors because memory preservation requires explicit fallback. This rule applies across all phases (PLAN through UPDATE-DOCS).
23
23
 
@@ -25,6 +25,10 @@ The user's request is authorization. When scope is unclear, pick the maximum rea
25
25
 
26
26
  **Spool dispatch chain**: write to `.gm/exec-spool/in/<lang>/<N>.<ext>` or `in/<verb>/<N>.txt`. Watcher executes and streams `out/<N>.out` + `out/<N>.err` + `out/<N>.json` metadata. Languages: nodejs, python, bash, typescript, go, rust, c, cpp, java, deno. Verbs: codesearch, recall, memorize, wait, sleep, status, close, browser, runner, type, kill-port, forget, feedback, learn-status, learn-debug, learn-build, discipline, pause, health.
27
27
 
28
+ **Data layout**: `.gm/` for ephemeral state (excluded from git), `gm-data/` for persistent DBs (rs-learn.db, code-search/ — tracked in git). Legacy `.gm/rs-learn.db` auto-migrates to `gm-data/rs-learn.db` on first access.
29
+
30
+ **WASM parity**: All CLI verbs available in browser/WASM via thebird host emulation. Python/bash/ssh/powershell map to exec_js; status/wait/sleep/close/kill-port/forget/feedback/learn-status/learn-debug/learn-build/discipline/pause/runner/type/browser all have WASM handlers. rs-search WASM uses fusion search (vector + BM25 + git via RRF scoring).
31
+
28
32
  **Session isolation**: SESSION_ID environment variable (or uuid fallback) threads through task dispatch for cleanup scope. rs-exec RPC handlers verify session_id match on all task-scoped operations.
29
33
 
30
34
  **Code does mechanics; meaning routes through textprocessing skill**: summarize, classify, extract intent, rewrite, translate, semantic dedup, rank, label — all via `Agent(subagent_type='gm:textprocessing', ...)`.
@@ -60,9 +60,12 @@ setsid nohup bash -c 'myprogram > /tmp/out.log 2>&1' &
60
60
 
61
61
  ## Dependency
62
62
 
63
- Requires `ssh2` in `~/.claude/gm-tools`:
64
-
65
- ```
66
- exec:bash
67
- cd ~/.claude/gm-tools && npm install ssh2
63
+ Requires `ssh2` in `~/.claude/gm-tools`. Write to `.gm/exec-spool/in/nodejs/<N>.js`:
64
+
65
+ ```js
66
+ const { execSync } = require('child_process');
67
+ const path = require('path');
68
+ const os = require('os');
69
+ const gmTools = path.join(os.homedir(), '.claude', 'gm-tools');
70
+ execSync('npm install ssh2', { cwd: gmTools, stdio: 'inherit' });
68
71
  ```
package/hooks/hooks.json DELETED
@@ -1,46 +0,0 @@
1
- {
2
- "description": "Hooks for gm Kilo CLI extension",
3
- "hooks": {
4
- "tool.execute.before": [
5
- {
6
- "matcher": "*",
7
- "hooks": [
8
- {
9
- "type": "command",
10
- "command": "node ${KILO_PLUGIN_ROOT}/bin/plugkit.js hook pre-tool-use",
11
- "timeout": 3600
12
- }
13
- ]
14
- }
15
- ],
16
- "message.updated": [
17
- {
18
- "matcher": "*",
19
- "hooks": [
20
- {
21
- "type": "command",
22
- "command": "node ${KILO_PLUGIN_ROOT}/bin/plugkit.js hook prompt-submit",
23
- "timeout": 60000
24
- }
25
- ]
26
- }
27
- ],
28
- "session.closing": [
29
- {
30
- "matcher": "*",
31
- "hooks": [
32
- {
33
- "type": "command",
34
- "command": "node ${KILO_PLUGIN_ROOT}/bin/plugkit.js hook stop",
35
- "timeout": 300000
36
- },
37
- {
38
- "type": "command",
39
- "command": "node ${KILO_PLUGIN_ROOT}/bin/plugkit.js hook stop-git",
40
- "timeout": 60000
41
- }
42
- ]
43
- }
44
- ]
45
- }
46
- }
@@ -1,43 +0,0 @@
1
- {
2
- "schemaVersion": 1,
3
- "description": "Hook spec for gm Kilo CLI extension",
4
- "envVar": "KILO_PLUGIN_ROOT",
5
- "plugkitInvoker": "node",
6
- "events": [
7
- {
8
- "eventKey": "tool.execute.before",
9
- "commands": [
10
- {
11
- "kind": "plugkit",
12
- "subcommand": "pre-tool-use",
13
- "timeout": 3600
14
- }
15
- ]
16
- },
17
- {
18
- "eventKey": "message.updated",
19
- "commands": [
20
- {
21
- "kind": "plugkit",
22
- "subcommand": "prompt-submit",
23
- "timeout": 60000
24
- }
25
- ]
26
- },
27
- {
28
- "eventKey": "session.closing",
29
- "commands": [
30
- {
31
- "kind": "plugkit",
32
- "subcommand": "stop",
33
- "timeout": 300000
34
- },
35
- {
36
- "kind": "plugkit",
37
- "subcommand": "stop-git",
38
- "timeout": 60000
39
- }
40
- ]
41
- }
42
- ]
43
- }