@khaentertainment/grok-swarm 1.3.3 → 1.3.5
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/README.md +15 -13
- package/dist/README.md +15 -13
- package/dist/VERSION +1 -1
- package/dist/grok_bridge.py +3 -3
- package/dist/package.json +1 -1
- package/package.json +1 -1
- package/src/bridge/grok_bridge.py +3 -3
- package/src/mcp/grok_server.py +62 -8
package/README.md
CHANGED
|
@@ -113,8 +113,9 @@ npm install -g @khaentertainment/grok-swarm
|
|
|
113
113
|
/plugin install grok-swarm@khaentertainment
|
|
114
114
|
```
|
|
115
115
|
|
|
116
|
-
Then run `/grok-swarm
|
|
117
|
-
|
|
116
|
+
Then run `/grok-swarm` or `/grok-swarm-setup` inside Claude Code. That bootstraps
|
|
117
|
+
the plugin-local runtime, registers the Grok MCP server, and launches OAuth if
|
|
118
|
+
your OpenRouter key is not configured yet.
|
|
118
119
|
|
|
119
120
|
### Option 3: ClawHub (OpenClaw)
|
|
120
121
|
|
|
@@ -146,10 +147,10 @@ For detailed instructions for each method, see [INSTALL.md](INSTALL.md).
|
|
|
146
147
|
### For Claude Code
|
|
147
148
|
|
|
148
149
|
```
|
|
149
|
-
/grok-swarm
|
|
150
|
-
/grok-swarm
|
|
151
|
-
/grok-swarm
|
|
152
|
-
/grok-swarm
|
|
150
|
+
/grok-swarm-analyze Review the security of my auth module
|
|
151
|
+
/grok-swarm-refactor Convert these callbacks to async/await
|
|
152
|
+
/grok-swarm-code Write a FastAPI endpoint for user registration
|
|
153
|
+
/grok-swarm-reason Compare microservices vs monolith for this project
|
|
153
154
|
```
|
|
154
155
|
|
|
155
156
|
### For OpenClaw
|
|
@@ -177,10 +178,10 @@ const result = await tools.grok_swarm({
|
|
|
177
178
|
### Claude Code
|
|
178
179
|
|
|
179
180
|
```
|
|
180
|
-
/grok-swarm
|
|
181
|
-
/grok-swarm
|
|
182
|
-
/grok-swarm
|
|
183
|
-
/grok-swarm
|
|
181
|
+
/grok-swarm-analyze Review the security of my auth module
|
|
182
|
+
/grok-swarm-refactor Convert this to async/await
|
|
183
|
+
/grok-swarm-code Write a FastAPI user registration endpoint
|
|
184
|
+
/grok-swarm-reason Compare these two architectural approaches
|
|
184
185
|
```
|
|
185
186
|
|
|
186
187
|
### OpenClaw
|
|
@@ -244,9 +245,10 @@ unset OPENROUTER_API_KEY
|
|
|
244
245
|
|
|
245
246
|
## Release Note
|
|
246
247
|
|
|
247
|
-
`1.3.
|
|
248
|
-
If you previously installed `1.
|
|
249
|
-
|
|
248
|
+
`1.3.4` fixes the Claude command surface after `1.3.3`.
|
|
249
|
+
If you previously installed `1.3.3`, upgrade to `1.3.4` to get searchable
|
|
250
|
+
`/grok-swarm-*` commands plus first-use bootstrap that repairs missing MCP
|
|
251
|
+
registration from inside Claude Code itself.
|
|
250
252
|
|
|
251
253
|
## Morph LLM Integration
|
|
252
254
|
|
package/dist/README.md
CHANGED
|
@@ -113,8 +113,9 @@ npm install -g @khaentertainment/grok-swarm
|
|
|
113
113
|
/plugin install grok-swarm@khaentertainment
|
|
114
114
|
```
|
|
115
115
|
|
|
116
|
-
Then run `/grok-swarm
|
|
117
|
-
|
|
116
|
+
Then run `/grok-swarm` or `/grok-swarm-setup` inside Claude Code. That bootstraps
|
|
117
|
+
the plugin-local runtime, registers the Grok MCP server, and launches OAuth if
|
|
118
|
+
your OpenRouter key is not configured yet.
|
|
118
119
|
|
|
119
120
|
### Option 3: ClawHub (OpenClaw)
|
|
120
121
|
|
|
@@ -146,10 +147,10 @@ For detailed instructions for each method, see [INSTALL.md](INSTALL.md).
|
|
|
146
147
|
### For Claude Code
|
|
147
148
|
|
|
148
149
|
```
|
|
149
|
-
/grok-swarm
|
|
150
|
-
/grok-swarm
|
|
151
|
-
/grok-swarm
|
|
152
|
-
/grok-swarm
|
|
150
|
+
/grok-swarm-analyze Review the security of my auth module
|
|
151
|
+
/grok-swarm-refactor Convert these callbacks to async/await
|
|
152
|
+
/grok-swarm-code Write a FastAPI endpoint for user registration
|
|
153
|
+
/grok-swarm-reason Compare microservices vs monolith for this project
|
|
153
154
|
```
|
|
154
155
|
|
|
155
156
|
### For OpenClaw
|
|
@@ -177,10 +178,10 @@ const result = await tools.grok_swarm({
|
|
|
177
178
|
### Claude Code
|
|
178
179
|
|
|
179
180
|
```
|
|
180
|
-
/grok-swarm
|
|
181
|
-
/grok-swarm
|
|
182
|
-
/grok-swarm
|
|
183
|
-
/grok-swarm
|
|
181
|
+
/grok-swarm-analyze Review the security of my auth module
|
|
182
|
+
/grok-swarm-refactor Convert this to async/await
|
|
183
|
+
/grok-swarm-code Write a FastAPI user registration endpoint
|
|
184
|
+
/grok-swarm-reason Compare these two architectural approaches
|
|
184
185
|
```
|
|
185
186
|
|
|
186
187
|
### OpenClaw
|
|
@@ -244,9 +245,10 @@ unset OPENROUTER_API_KEY
|
|
|
244
245
|
|
|
245
246
|
## Release Note
|
|
246
247
|
|
|
247
|
-
`1.3.
|
|
248
|
-
If you previously installed `1.
|
|
249
|
-
|
|
248
|
+
`1.3.4` fixes the Claude command surface after `1.3.3`.
|
|
249
|
+
If you previously installed `1.3.3`, upgrade to `1.3.4` to get searchable
|
|
250
|
+
`/grok-swarm-*` commands plus first-use bootstrap that repairs missing MCP
|
|
251
|
+
registration from inside Claude Code itself.
|
|
250
252
|
|
|
251
253
|
## Morph LLM Integration
|
|
252
254
|
|
package/dist/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.3.
|
|
1
|
+
1.3.5
|
package/dist/grok_bridge.py
CHANGED
|
@@ -28,7 +28,7 @@ try:
|
|
|
28
28
|
except ImportError:
|
|
29
29
|
print(
|
|
30
30
|
"ERROR: openai package required for this Grok Swarm runtime. "
|
|
31
|
-
"Install from src/requirements.txt or run /grok-swarm
|
|
31
|
+
"Install from src/requirements.txt or run /grok-swarm-setup to bootstrap the plugin-local environment.",
|
|
32
32
|
file=sys.stderr,
|
|
33
33
|
)
|
|
34
34
|
sys.exit(1)
|
|
@@ -330,7 +330,7 @@ def _get_client(api_key=None, timeout=120):
|
|
|
330
330
|
"No OpenRouter API key found. "
|
|
331
331
|
"Tried: OPENROUTER_API_KEY env, ~/.config/grok-swarm/config.json, "
|
|
332
332
|
"~/.claude/grok-swarm.local.md, OpenClaw auth profiles. "
|
|
333
|
-
"Run: python3 src/bridge/oauth_setup.py or /grok-swarm
|
|
333
|
+
"Run: python3 src/bridge/oauth_setup.py or /grok-swarm-setup"
|
|
334
334
|
)
|
|
335
335
|
return OpenAI(base_url=OPENROUTER_BASE, api_key=key, timeout=timeout)
|
|
336
336
|
|
|
@@ -403,7 +403,7 @@ def call_grok(prompt, mode="reason", context="", system_override=None, tools=Non
|
|
|
403
403
|
print(" 2. ~/.config/grok-swarm/config.json", file=sys.stderr)
|
|
404
404
|
print(" 3. ~/.claude/grok-swarm.local.md", file=sys.stderr)
|
|
405
405
|
print(" 4. OpenClaw auth profiles (~/.openclaw/)", file=sys.stderr)
|
|
406
|
-
print("Run: python3 src/bridge/oauth_setup.py or /grok-swarm
|
|
406
|
+
print("Run: python3 src/bridge/oauth_setup.py or /grok-swarm-setup", file=sys.stderr)
|
|
407
407
|
sys.exit(1)
|
|
408
408
|
|
|
409
409
|
# Resolve system prompt
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@khaentertainment/grok-swarm",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.5",
|
|
4
4
|
"description": "Multi-agent intelligence powered by Grok 4.20 via OpenRouter. Give any AI coding agent access to a 4-agent swarm with ~2M token context.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"grok",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@khaentertainment/grok-swarm",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.5",
|
|
4
4
|
"description": "Multi-agent intelligence powered by Grok 4.20 via OpenRouter. Give any AI coding agent access to a 4-agent swarm with ~2M token context.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"grok",
|
|
@@ -28,7 +28,7 @@ try:
|
|
|
28
28
|
except ImportError:
|
|
29
29
|
print(
|
|
30
30
|
"ERROR: openai package required for this Grok Swarm runtime. "
|
|
31
|
-
"Install from src/requirements.txt or run /grok-swarm
|
|
31
|
+
"Install from src/requirements.txt or run /grok-swarm-setup to bootstrap the plugin-local environment.",
|
|
32
32
|
file=sys.stderr,
|
|
33
33
|
)
|
|
34
34
|
sys.exit(1)
|
|
@@ -330,7 +330,7 @@ def _get_client(api_key=None, timeout=120):
|
|
|
330
330
|
"No OpenRouter API key found. "
|
|
331
331
|
"Tried: OPENROUTER_API_KEY env, ~/.config/grok-swarm/config.json, "
|
|
332
332
|
"~/.claude/grok-swarm.local.md, OpenClaw auth profiles. "
|
|
333
|
-
"Run: python3 src/bridge/oauth_setup.py or /grok-swarm
|
|
333
|
+
"Run: python3 src/bridge/oauth_setup.py or /grok-swarm-setup"
|
|
334
334
|
)
|
|
335
335
|
return OpenAI(base_url=OPENROUTER_BASE, api_key=key, timeout=timeout)
|
|
336
336
|
|
|
@@ -403,7 +403,7 @@ def call_grok(prompt, mode="reason", context="", system_override=None, tools=Non
|
|
|
403
403
|
print(" 2. ~/.config/grok-swarm/config.json", file=sys.stderr)
|
|
404
404
|
print(" 3. ~/.claude/grok-swarm.local.md", file=sys.stderr)
|
|
405
405
|
print(" 4. OpenClaw auth profiles (~/.openclaw/)", file=sys.stderr)
|
|
406
|
-
print("Run: python3 src/bridge/oauth_setup.py or /grok-swarm
|
|
406
|
+
print("Run: python3 src/bridge/oauth_setup.py or /grok-swarm-setup", file=sys.stderr)
|
|
407
407
|
sys.exit(1)
|
|
408
408
|
|
|
409
409
|
# Resolve system prompt
|
package/src/mcp/grok_server.py
CHANGED
|
@@ -31,6 +31,7 @@ from bridge.grok_bridge import (
|
|
|
31
31
|
get_api_key,
|
|
32
32
|
read_files,
|
|
33
33
|
strip_pgp_blocks,
|
|
34
|
+
parse_and_write_files,
|
|
34
35
|
MODE_PROMPTS,
|
|
35
36
|
AGENT_COUNTS,
|
|
36
37
|
)
|
|
@@ -57,13 +58,28 @@ log = logging.getLogger("grok-mcp")
|
|
|
57
58
|
# ---------------------------------------------------------------------------
|
|
58
59
|
|
|
59
60
|
SERVER_NAME = "grok-swarm"
|
|
60
|
-
SERVER_VERSION = "1.3.
|
|
61
|
+
SERVER_VERSION = "1.3.4"
|
|
61
62
|
PROTOCOL_VERSION = "2024-11-05"
|
|
62
63
|
|
|
63
64
|
# ---------------------------------------------------------------------------
|
|
64
65
|
# Tool definitions (JSON Schema format for MCP, NOT OpenAI format)
|
|
65
66
|
# ---------------------------------------------------------------------------
|
|
66
67
|
|
|
68
|
+
# JSON Schema fragments parsed at import time so defaults use lowercase JSON
|
|
69
|
+
# true/false rather than Python True/False literals.
|
|
70
|
+
_WRITE_FILES_SCHEMA = json.loads(
|
|
71
|
+
'{"type": "boolean", "default": false, '
|
|
72
|
+
'"description": "Whether to parse and write code blocks from the response to disk."}'
|
|
73
|
+
)
|
|
74
|
+
_OUTPUT_DIR_SCHEMA = json.loads(
|
|
75
|
+
'{"type": "string", "default": "./grok-output/", '
|
|
76
|
+
'"description": "Output directory for write_files mode."}'
|
|
77
|
+
)
|
|
78
|
+
_BOOL_FALSE_SCHEMA = json.loads(
|
|
79
|
+
'{"type": "boolean", "default": false, '
|
|
80
|
+
'"description": "Whether to actually write changes (default: dry-run preview)."}'
|
|
81
|
+
)
|
|
82
|
+
|
|
67
83
|
TOOLS = [
|
|
68
84
|
{
|
|
69
85
|
"name": "grok_query",
|
|
@@ -105,6 +121,8 @@ TOOLS = [
|
|
|
105
121
|
"default": 120,
|
|
106
122
|
"description": "API timeout in seconds.",
|
|
107
123
|
},
|
|
124
|
+
"write_files": _WRITE_FILES_SCHEMA,
|
|
125
|
+
"output_dir": _OUTPUT_DIR_SCHEMA,
|
|
108
126
|
},
|
|
109
127
|
"required": ["prompt"],
|
|
110
128
|
},
|
|
@@ -140,6 +158,16 @@ TOOLS = [
|
|
|
140
158
|
"items": {"type": "string"},
|
|
141
159
|
"description": "File paths to include as initial context.",
|
|
142
160
|
},
|
|
161
|
+
"write_files": {
|
|
162
|
+
"type": "boolean",
|
|
163
|
+
"default": False,
|
|
164
|
+
"description": "Accepted for API consistency; applies only to grok_session_continue.",
|
|
165
|
+
},
|
|
166
|
+
"output_dir": {
|
|
167
|
+
"type": "string",
|
|
168
|
+
"default": "./grok-output/",
|
|
169
|
+
"description": "Accepted for API consistency; applies only to grok_session_continue.",
|
|
170
|
+
},
|
|
143
171
|
},
|
|
144
172
|
"required": [],
|
|
145
173
|
},
|
|
@@ -166,6 +194,8 @@ TOOLS = [
|
|
|
166
194
|
"items": {"type": "string"},
|
|
167
195
|
"description": "Additional file paths to add as context.",
|
|
168
196
|
},
|
|
197
|
+
"write_files": _WRITE_FILES_SCHEMA,
|
|
198
|
+
"output_dir": _OUTPUT_DIR_SCHEMA,
|
|
169
199
|
},
|
|
170
200
|
"required": ["session_id", "message"],
|
|
171
201
|
},
|
|
@@ -189,11 +219,7 @@ TOOLS = [
|
|
|
189
219
|
"default": ".",
|
|
190
220
|
"description": "Target directory or file to operate on.",
|
|
191
221
|
},
|
|
192
|
-
"apply":
|
|
193
|
-
"type": "boolean",
|
|
194
|
-
"default": False,
|
|
195
|
-
"description": "Whether to actually write changes (default: dry-run preview).",
|
|
196
|
-
},
|
|
222
|
+
"apply": _BOOL_FALSE_SCHEMA,
|
|
197
223
|
"max_iterations": {
|
|
198
224
|
"type": "integer",
|
|
199
225
|
"default": 5,
|
|
@@ -222,6 +248,8 @@ def _handle_grok_query(params):
|
|
|
222
248
|
system = params.get("system")
|
|
223
249
|
thinking = params.get("thinking", "low")
|
|
224
250
|
timeout = params.get("timeout", 120)
|
|
251
|
+
write_files = params.get("write_files", False)
|
|
252
|
+
output_dir = params.get("output_dir", "./grok-output/")
|
|
225
253
|
|
|
226
254
|
if mode == "orchestrate" and not system:
|
|
227
255
|
return _error_content("orchestrate mode requires the 'system' parameter")
|
|
@@ -255,7 +283,19 @@ def _handle_grok_query(params):
|
|
|
255
283
|
return _error_content("Empty response from Grok API")
|
|
256
284
|
|
|
257
285
|
content = response.choices[0].message.content or ""
|
|
258
|
-
|
|
286
|
+
cleaned = strip_pgp_blocks(content)
|
|
287
|
+
|
|
288
|
+
if write_files:
|
|
289
|
+
try:
|
|
290
|
+
written = parse_and_write_files(cleaned, output_dir)
|
|
291
|
+
except (OSError, IOError) as exc:
|
|
292
|
+
log.error("Failed to write files: %s", exc)
|
|
293
|
+
return _error_content(f"Failed to write files: {exc}")
|
|
294
|
+
if written:
|
|
295
|
+
paths = ", ".join(p for p, _ in written)
|
|
296
|
+
return _text_content(f"{len(written)} file(s) written to {output_dir}: {paths}")
|
|
297
|
+
# Fall back to printing the response text if no files were written
|
|
298
|
+
return _text_content(cleaned)
|
|
259
299
|
|
|
260
300
|
|
|
261
301
|
def _handle_grok_session_start(params):
|
|
@@ -266,6 +306,8 @@ def _handle_grok_session_start(params):
|
|
|
266
306
|
system = params.get("system")
|
|
267
307
|
thinking = params.get("thinking", "low")
|
|
268
308
|
files = params.get("files", [])
|
|
309
|
+
# write_files and output_dir params are accepted for API consistency
|
|
310
|
+
# but apply to grok_session_continue, not the session start itself
|
|
269
311
|
|
|
270
312
|
# Read initial file context
|
|
271
313
|
file_context = ""
|
|
@@ -296,6 +338,8 @@ def _handle_grok_session_continue(params):
|
|
|
296
338
|
session_id = params["session_id"]
|
|
297
339
|
message = params["message"]
|
|
298
340
|
files = params.get("files", [])
|
|
341
|
+
write_files = params.get("write_files", False)
|
|
342
|
+
output_dir = params.get("output_dir", "./grok-output/")
|
|
299
343
|
|
|
300
344
|
session = session_mod.get_session(session_id)
|
|
301
345
|
if session is None:
|
|
@@ -312,7 +356,17 @@ def _handle_grok_session_continue(params):
|
|
|
312
356
|
log.error("Session %s error: %s", session_id, exc)
|
|
313
357
|
return _error_content(f"Grok API error: {exc}")
|
|
314
358
|
|
|
315
|
-
|
|
359
|
+
cleaned = strip_pgp_blocks(response)
|
|
360
|
+
if write_files:
|
|
361
|
+
try:
|
|
362
|
+
written = parse_and_write_files(cleaned, output_dir)
|
|
363
|
+
except (OSError, IOError) as exc:
|
|
364
|
+
log.error("Failed to write files to %s: %s", output_dir, exc)
|
|
365
|
+
return _error_content(f"Failed to write files: {exc}")
|
|
366
|
+
if written:
|
|
367
|
+
paths = ", ".join(p for p, _ in written)
|
|
368
|
+
return _text_content(f"{len(written)} file(s) written to {output_dir}: {paths}")
|
|
369
|
+
return _text_content(cleaned)
|
|
316
370
|
|
|
317
371
|
|
|
318
372
|
def _handle_grok_agent(params):
|