grok-cli-acp 0.1.2

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.
Files changed (100) hide show
  1. package/.env.example +42 -0
  2. package/.github/workflows/ci.yml +30 -0
  3. package/.github/workflows/rust.yml +22 -0
  4. package/.grok/.env.example +85 -0
  5. package/.grok/COMPLETE_FIX_SUMMARY.md +466 -0
  6. package/.grok/ENV_CONFIG_GUIDE.md +173 -0
  7. package/.grok/QUICK_REFERENCE.md +180 -0
  8. package/.grok/README.md +104 -0
  9. package/.grok/TESTING_GUIDE.md +393 -0
  10. package/CHANGELOG.md +465 -0
  11. package/CODE_REVIEW_SUMMARY.md +414 -0
  12. package/COMPLETE_FIX_SUMMARY.md +415 -0
  13. package/CONFIGURATION.md +489 -0
  14. package/CONTEXT_FILES_GUIDE.md +419 -0
  15. package/CONTRIBUTING.md +55 -0
  16. package/CURSOR_POSITION_FIX.md +206 -0
  17. package/Cargo.toml +88 -0
  18. package/ERROR_HANDLING_REPORT.md +361 -0
  19. package/FINAL_FIX_SUMMARY.md +462 -0
  20. package/FIXES.md +37 -0
  21. package/FIXES_SUMMARY.md +87 -0
  22. package/GROK_API_MIGRATION_SUMMARY.md +111 -0
  23. package/LICENSE +22 -0
  24. package/MIGRATION_TO_GROK_API.md +223 -0
  25. package/README.md +504 -0
  26. package/REVIEW_COMPLETE.md +416 -0
  27. package/REVIEW_QUICK_REFERENCE.md +173 -0
  28. package/SECURITY.md +463 -0
  29. package/SECURITY_AUDIT.md +661 -0
  30. package/SETUP.md +287 -0
  31. package/TESTING_TOOLS.md +88 -0
  32. package/TESTING_TOOL_EXECUTION.md +239 -0
  33. package/TOOL_EXECUTION_FIX.md +491 -0
  34. package/VERIFICATION_CHECKLIST.md +419 -0
  35. package/docs/API.md +74 -0
  36. package/docs/CHAT_LOGGING.md +39 -0
  37. package/docs/CURSOR_FIX_DEMO.md +306 -0
  38. package/docs/ERROR_HANDLING_GUIDE.md +547 -0
  39. package/docs/FILE_OPERATIONS.md +449 -0
  40. package/docs/INTERACTIVE.md +401 -0
  41. package/docs/PROJECT_CREATION_GUIDE.md +570 -0
  42. package/docs/QUICKSTART.md +378 -0
  43. package/docs/QUICK_REFERENCE.md +691 -0
  44. package/docs/RELEASE_NOTES_0.1.2.md +240 -0
  45. package/docs/TOOLS.md +459 -0
  46. package/docs/TOOLS_QUICK_REFERENCE.md +210 -0
  47. package/docs/ZED_INTEGRATION.md +371 -0
  48. package/docs/extensions.md +464 -0
  49. package/docs/settings.md +293 -0
  50. package/examples/extensions/logging-hook/README.md +91 -0
  51. package/examples/extensions/logging-hook/extension.json +22 -0
  52. package/package.json +30 -0
  53. package/scripts/test_acp.py +252 -0
  54. package/scripts/test_acp.sh +143 -0
  55. package/scripts/test_acp_simple.sh +72 -0
  56. package/src/acp/mod.rs +741 -0
  57. package/src/acp/protocol.rs +323 -0
  58. package/src/acp/security.rs +298 -0
  59. package/src/acp/tools.rs +697 -0
  60. package/src/bin/banner_demo.rs +216 -0
  61. package/src/bin/docgen.rs +18 -0
  62. package/src/bin/installer.rs +217 -0
  63. package/src/cli/app.rs +310 -0
  64. package/src/cli/commands/acp.rs +721 -0
  65. package/src/cli/commands/chat.rs +485 -0
  66. package/src/cli/commands/code.rs +513 -0
  67. package/src/cli/commands/config.rs +394 -0
  68. package/src/cli/commands/health.rs +442 -0
  69. package/src/cli/commands/history.rs +421 -0
  70. package/src/cli/commands/mod.rs +14 -0
  71. package/src/cli/commands/settings.rs +1384 -0
  72. package/src/cli/mod.rs +166 -0
  73. package/src/config/mod.rs +2212 -0
  74. package/src/display/ascii_art.rs +139 -0
  75. package/src/display/banner.rs +289 -0
  76. package/src/display/components/input.rs +323 -0
  77. package/src/display/components/mod.rs +2 -0
  78. package/src/display/components/settings_list.rs +306 -0
  79. package/src/display/interactive.rs +1255 -0
  80. package/src/display/mod.rs +62 -0
  81. package/src/display/terminal.rs +42 -0
  82. package/src/display/tips.rs +316 -0
  83. package/src/grok_client_ext.rs +177 -0
  84. package/src/hooks/loader.rs +407 -0
  85. package/src/hooks/mod.rs +158 -0
  86. package/src/lib.rs +174 -0
  87. package/src/main.rs +65 -0
  88. package/src/mcp/client.rs +195 -0
  89. package/src/mcp/config.rs +20 -0
  90. package/src/mcp/mod.rs +6 -0
  91. package/src/mcp/protocol.rs +67 -0
  92. package/src/utils/auth.rs +41 -0
  93. package/src/utils/chat_logger.rs +568 -0
  94. package/src/utils/context.rs +390 -0
  95. package/src/utils/mod.rs +16 -0
  96. package/src/utils/network.rs +320 -0
  97. package/src/utils/rate_limiter.rs +166 -0
  98. package/src/utils/session.rs +73 -0
  99. package/src/utils/shell_permissions.rs +389 -0
  100. package/src/utils/telemetry.rs +41 -0
@@ -0,0 +1,293 @@
1
+ # Grok CLI Settings (`settings` command)
2
+
3
+ Grok CLI provides a powerful settings system using `.env` files with hierarchical configuration.
4
+
5
+ ## Configuration Files
6
+
7
+ - **System settings**: `~/.grok/.env` (Linux/macOS) or `%USERPROFILE%\.grok\.env` (Windows)
8
+ - **Project settings**: `.grok/.env` (in your project directory)
9
+
10
+ Note: Project settings override system settings. Environment variables override all files.
11
+
12
+ ## Using the Settings Command
13
+
14
+ ### Interactive Settings Browser
15
+ ```bash
16
+ # Launch interactive settings browser
17
+ grok settings show
18
+
19
+ # Edit settings interactively
20
+ grok settings edit
21
+ ```
22
+
23
+ ### Reset Settings
24
+ ```bash
25
+ # Reset all settings to defaults
26
+ grok settings reset
27
+
28
+ # Reset specific category to defaults
29
+ grok settings reset --category ui
30
+ grok settings reset --category general
31
+ ```
32
+
33
+ ### Import/Export Settings
34
+ ```bash
35
+ # Export current settings to a file
36
+ grok settings export --path my-settings.env
37
+
38
+ # Import settings from a file
39
+ grok settings import --path my-settings.env
40
+ ```
41
+
42
+ ## Settings Categories
43
+
44
+ Settings are organized into logical categories for easier management:
45
+
46
+ ### General
47
+ Core application settings and preferences.
48
+
49
+ ### UI
50
+ User interface appearance, themes, and display options.
51
+
52
+ ### Model
53
+ AI model configuration and behavior settings.
54
+
55
+ ### Context
56
+ File handling, context discovery, and memory management.
57
+
58
+ ### Tools
59
+ Tool execution, shell integration, and external command settings.
60
+
61
+ ### Security
62
+ Security policies, trust settings, and access controls.
63
+
64
+ ### Experimental
65
+ Preview features and experimental functionality.
66
+
67
+ ### ACP
68
+ Agent Client Protocol settings for Zed editor integration.
69
+
70
+ ### Network
71
+ Network configuration, timeouts, and Starlink optimizations.
72
+
73
+ ### Logging
74
+ Logging levels, file output, and debugging options.
75
+
76
+ ## Settings Reference
77
+
78
+ Here is a comprehensive list of all available settings, grouped by category:
79
+
80
+ ### General Settings
81
+
82
+ | Setting | Description | Default | Type |
83
+ |---------|-------------|---------|------|
84
+ | `general.preview_features` | Enable preview features and experimental models | `false` | Boolean |
85
+ | `general.vim_mode` | Enable Vim keybindings throughout the interface | `false` | Boolean |
86
+ | `general.disable_auto_update` | Disable automatic updates | `false` | Boolean |
87
+ | `general.disable_update_nag` | Hide update notification messages | `false` | Boolean |
88
+ | `general.enable_prompt_completion` | Enable AI-powered prompt completion while typing | `false` | Boolean |
89
+ | `general.retry_fetch_errors` | Automatically retry failed network requests | `false` | Boolean |
90
+ | `general.debug_keystroke_logging` | Log keystrokes for debugging purposes | `false` | Boolean |
91
+
92
+ ### UI Settings
93
+
94
+ | Setting | Description | Default | Type |
95
+ |---------|-------------|---------|------|
96
+ | `ui.theme` | Color theme for the interface | `"default"` | String |
97
+ | `ui.colors` | Enable colored output in terminal | `true` | Boolean |
98
+ | `ui.progress_bars` | Show progress indicators during operations | `true` | Boolean |
99
+ | `ui.verbose_errors` | Display detailed error information | `false` | Boolean |
100
+ | `ui.terminal_width` | Terminal width override (0 = auto-detect) | `0` | Number |
101
+ | `ui.unicode` | Enable Unicode characters and emojis | `true` | Boolean |
102
+ | `ui.hide_window_title` | Hide the window title bar | `false` | Boolean |
103
+ | `ui.show_status_in_title` | Show Grok CLI status in terminal title | `false` | Boolean |
104
+ | `ui.hide_tips` | Hide helpful tips and suggestions | `false` | Boolean |
105
+ | `ui.hide_banner` | Hide the ASCII art startup banner | `false` | Boolean |
106
+ | `ui.hide_context_summary` | Hide context summary above input | `false` | Boolean |
107
+ | `ui.hide_footer` | Hide the status footer | `false` | Boolean |
108
+ | `ui.show_memory_usage` | Display memory usage information | `false` | Boolean |
109
+ | `ui.show_line_numbers` | Show line numbers in chat output | `true` | Boolean |
110
+ | `ui.show_citations` | Show citations for generated content | `false` | Boolean |
111
+ | `ui.show_model_info_in_chat` | Display model name in chat responses | `false` | Boolean |
112
+ | `ui.use_full_width` | Use entire terminal width for output | `true` | Boolean |
113
+ | `ui.use_alternate_buffer` | Use alternate screen buffer (preserves history) | `false` | Boolean |
114
+ | `ui.incremental_rendering` | Enable incremental text rendering | `false` | Boolean |
115
+
116
+ ### Footer Settings
117
+
118
+ | Setting | Description | Default | Type |
119
+ |---------|-------------|---------|------|
120
+ | `ui.footer.hide_cwd` | Hide current working directory in footer | `false` | Boolean |
121
+ | `ui.footer.hide_sandbox_status` | Hide sandbox status indicator | `false` | Boolean |
122
+ | `ui.footer.hide_model_info` | Hide model information in footer | `false` | Boolean |
123
+ | `ui.footer.hide_context_percentage` | Hide context usage percentage | `true` | Boolean |
124
+
125
+ ### Accessibility Settings
126
+
127
+ | Setting | Description | Default | Type |
128
+ |---------|-------------|---------|------|
129
+ | `ui.accessibility.disable_loading_phrases` | Disable witty loading phrases | `false` | Boolean |
130
+ | `ui.accessibility.screen_reader` | Optimize output for screen readers | `false` | Boolean |
131
+
132
+ ### Interactive UI Settings
133
+
134
+ | Setting | Description | Default | Type |
135
+ |---------|-------------|---------|------|
136
+ | `ui.interactive.prompt_style` | Prompt style (simple, rich, minimal) | `"rich"` | String |
137
+ | `ui.interactive.show_context_usage` | Enable context usage display | `true` | Boolean |
138
+ | `ui.interactive.auto_save_sessions` | Auto-save sessions | `false` | Boolean |
139
+ | `ui.interactive.check_directory` | Check for home directory usage | `true` | Boolean |
140
+ | `ui.interactive.startup_animation` | Enable startup animation | `true` | Boolean |
141
+ | `ui.interactive.update_check_hours` | Update check frequency in hours (0 = disabled) | `24` | Number |
142
+
143
+ ### Model Settings
144
+
145
+ | Setting | Description | Default | Type |
146
+ |---------|-------------|---------|------|
147
+ | `default_model` | Default Grok model to use | `"grok-3"` | String |
148
+ | `default_temperature` | Default temperature for responses (0.0-2.0) | `0.7` | Number |
149
+ | `default_max_tokens` | Default maximum tokens per response | `4096` | Number |
150
+ | `model.max_session_turns` | Maximum conversation turns (-1 = unlimited) | `-1` | Number |
151
+ | `model.compression_threshold` | Context compression threshold (0.1-1.0) | `0.2` | Number |
152
+ | `model.skip_next_speaker_check` | Skip next speaker validation | `true` | Boolean |
153
+
154
+ ### Context Settings
155
+
156
+ | Setting | Description | Default | Type |
157
+ |---------|-------------|---------|------|
158
+ | `context.discovery_max_dirs` | Maximum directories to search for context | `200` | Number |
159
+ | `context.load_memory_from_include_directories` | Load memory from included directories | `false` | Boolean |
160
+ | `context.file_filtering.respect_git_ignore` | Respect .gitignore files | `true` | Boolean |
161
+ | `context.file_filtering.respect_grok_ignore` | Respect .grokignore files | `true` | Boolean |
162
+ | `context.file_filtering.enable_recursive_file_search` | Enable recursive file search | `true` | Boolean |
163
+ | `context.file_filtering.disable_fuzzy_search` | Disable fuzzy file matching | `false` | Boolean |
164
+
165
+ ### Tools Settings
166
+
167
+ | Setting | Description | Default | Type |
168
+ |---------|-------------|---------|------|
169
+ | `tools.shell.enable_interactive_shell` | Enable interactive shell mode | `true` | Boolean |
170
+ | `tools.shell.show_color` | Show colors in shell output | `false` | Boolean |
171
+ | `tools.auto_accept` | Automatically accept safe tool executions | `false` | Boolean |
172
+ | `tools.use_ripgrep` | Use ripgrep for faster file searches | `true` | Boolean |
173
+ | `tools.enable_tool_output_truncation` | Truncate large tool outputs | `true` | Boolean |
174
+ | `tools.truncate_tool_output_threshold` | Truncation threshold in characters | `10000` | Number |
175
+ | `tools.truncate_tool_output_lines` | Lines to keep when truncating | `100` | Number |
176
+ | `tools.enable_message_bus_integration` | Enable message bus integration | `true` | Boolean |
177
+
178
+ ### Security Settings
179
+
180
+ | Setting | Description | Default | Type |
181
+ |---------|-------------|---------|------|
182
+ | `security.disable_yolo_mode` | Disable YOLO mode even if flagged | `false` | Boolean |
183
+ | `security.enable_permanent_tool_approval` | Allow permanent tool approvals | `false` | Boolean |
184
+ | `security.block_git_extensions` | Block Git-based extensions | `false` | Boolean |
185
+ | `security.folder_trust.enabled` | Enable folder trust system | `false` | Boolean |
186
+ | `security.environment_variable_redaction.enabled` | Enable env var redaction | `false` | Boolean |
187
+
188
+ ### Experimental Settings
189
+
190
+ | Setting | Description | Default | Type |
191
+ |---------|-------------|---------|------|
192
+ | `experimental.enable_agents` | Enable experimental agent features | `false` | Boolean |
193
+ | `experimental.extension_management` | Enable extension management | `false` | Boolean |
194
+ | `experimental.jit_context` | Enable just-in-time context loading | `false` | Boolean |
195
+ | `experimental.codebase_investigator_settings.enabled` | Enable codebase investigator | `true` | Boolean |
196
+ | `experimental.codebase_investigator_settings.max_num_turns` | Max investigator turns | `10` | Number |
197
+
198
+ ### ACP Settings
199
+
200
+ | Setting | Description | Default | Type |
201
+ |---------|-------------|---------|------|
202
+ | `acp.enabled` | Enable Agent Client Protocol | `true` | Boolean |
203
+ | `acp.bind_host` | ACP server bind address | `"127.0.0.1"` | String |
204
+ | `acp.default_port` | Default ACP server port | `None` | Number |
205
+ | `acp.protocol_version` | ACP protocol version | `"1.0"` | String |
206
+ | `acp.dev_mode` | Enable development mode | `false` | Boolean |
207
+
208
+ ### Network Settings
209
+
210
+ | Setting | Description | Default | Type |
211
+ |---------|-------------|---------|------|
212
+ | `network.starlink_optimizations` | Enable Starlink satellite optimizations | `false` | Boolean |
213
+ | `network.base_retry_delay` | Base retry delay in seconds | `1` | Number |
214
+ | `network.max_retry_delay` | Maximum retry delay in seconds | `60` | Number |
215
+ | `network.health_monitoring` | Enable network health monitoring | `true` | Boolean |
216
+ | `network.connect_timeout` | Connection timeout in seconds | `10` | Number |
217
+ | `network.read_timeout` | Read timeout in seconds | `30` | Number |
218
+
219
+ ### Logging Settings
220
+
221
+ | Setting | Description | Default | Type |
222
+ |---------|-------------|---------|------|
223
+ | `logging.level` | Log level (trace/debug/info/warn/error) | `"info"` | String |
224
+ | `logging.file_logging` | Enable logging to file | `false` | Boolean |
225
+ | `logging.max_file_size_mb` | Maximum log file size in MB | `10` | Number |
226
+ | `logging.rotation_count` | Number of rotated log files to keep | `5` | Number |
227
+
228
+ ## Configuration File Example
229
+
230
+ Here's an example of what your `.env` file might look like:
231
+
232
+ ```toml
233
+ api_key = "your-x-api-key-here"
234
+ default_model = "grok-3"
235
+ default_temperature = 0.7
236
+ default_max_tokens = 4096
237
+ timeout_secs = 30
238
+ max_retries = 3
239
+
240
+ [general]
241
+ preview_features = true
242
+ vim_mode = false
243
+ disable_auto_update = false
244
+
245
+ [ui]
246
+ theme = "default"
247
+ colors = true
248
+ hide_banner = false
249
+ hide_tips = false
250
+ show_line_numbers = true
251
+ use_full_width = true
252
+
253
+ [ui.footer]
254
+ hide_cwd = false
255
+ hide_model_info = false
256
+ hide_context_percentage = true
257
+
258
+ [model]
259
+ max_session_turns = -1
260
+ compression_threshold = 0.2
261
+
262
+ [acp]
263
+ enabled = true
264
+ bind_host = "127.0.0.1"
265
+ protocol_version = "1.0"
266
+
267
+ [network]
268
+ starlink_optimizations = true
269
+ base_retry_delay = 2
270
+ max_retry_delay = 60
271
+
272
+ [logging]
273
+ level = "info"
274
+ file_logging = true
275
+ ```
276
+
277
+ ## Tips
278
+
279
+ 1. **Start with defaults**: The interactive settings browser shows current values and defaults for easy comparison.
280
+
281
+ 2. **Category-specific resets**: Use `grok settings reset --category <name>` to reset only specific sections.
282
+
283
+ 3. **Backup your settings**: Use `grok settings export` to create backups before making major changes.
284
+
285
+ 4. **Project-specific configs**: Create a `.grok/.env` file in your project directory for project-specific settings.
286
+
287
+ 5. **Restart requirements**: Some settings require restarting Grok CLI to take effect. The settings browser will indicate these.
288
+
289
+ 6. **Use .env format**: All configuration now uses environment variable format (KEY=value) instead of TOML.
290
+
291
+ 6. **Environment variables**: Many settings can also be overridden with environment variables (e.g., `GROK_API_KEY`).
292
+
293
+ For more information about specific features, see the main [Grok CLI documentation](README.md).
@@ -0,0 +1,91 @@
1
+ # Logging Hook Extension
2
+
3
+ A sample extension that demonstrates the Grok CLI extension system by logging tool invocations.
4
+
5
+ ## Overview
6
+
7
+ This extension provides a simple hook that logs all tool invocations before and after execution, which can be useful for:
8
+ - Debugging tool interactions
9
+ - Monitoring agent behavior
10
+ - Auditing tool usage
11
+ - Performance profiling
12
+
13
+ ## Installation
14
+
15
+ 1. Copy this directory to your Grok extensions folder:
16
+ ```bash
17
+ cp -r logging-hook ~/.grok/extensions/
18
+ ```
19
+
20
+ 2. Enable the extension in your `~/.config/grok-cli/config.toml`:
21
+ ```toml
22
+ [experimental.extensions]
23
+ enabled = true
24
+ enabled_extensions = ["logging-hook"]
25
+ ```
26
+
27
+ 3. Restart Grok CLI to load the extension.
28
+
29
+ ## Configuration
30
+
31
+ The extension can be configured in the `extension.json` file:
32
+
33
+ - **log_level**: Set to "debug", "info", "warn", or "error" (default: "debug")
34
+ - **include_args**: Whether to log tool arguments (default: true)
35
+ - **include_results**: Whether to log tool results (default: true)
36
+ - **max_result_length**: Maximum length of result to log, to avoid huge logs (default: 500)
37
+
38
+ ## How It Works
39
+
40
+ The logging hook implements both `before_tool` and `after_tool` hooks:
41
+
42
+ 1. **before_tool**: Logs when a tool is about to be invoked, including:
43
+ - Tool name
44
+ - Arguments (if enabled)
45
+ - Timestamp
46
+
47
+ 2. **after_tool**: Logs after tool execution completes, including:
48
+ - Tool name
49
+ - Result preview (if enabled)
50
+ - Execution duration
51
+ - Timestamp
52
+
53
+ ## Example Output
54
+
55
+ When enabled, you'll see log entries like:
56
+
57
+ ```
58
+ [DEBUG] Extension 'logging-hook' hook 'tool-logger' executing before tool 'read_file'
59
+ [DEBUG] Tool args: {"path": "src/main.rs"}
60
+ [DEBUG] Extension 'logging-hook' hook 'tool-logger' executing after tool 'read_file'
61
+ [DEBUG] Result length: 1234 bytes
62
+ ```
63
+
64
+ ## Extending This Example
65
+
66
+ You can use this as a template to create your own extensions:
67
+
68
+ 1. Modify `extension.json` to change the extension name and configuration
69
+ 2. Add additional hooks as needed
70
+ 3. In a full implementation, you could:
71
+ - Execute external scripts or commands
72
+ - Send metrics to monitoring systems
73
+ - Implement security policies
74
+ - Transform tool inputs/outputs
75
+ - Add custom validation logic
76
+
77
+ ## Limitations
78
+
79
+ This is a basic config-based extension. For more advanced functionality, you would need to:
80
+ - Implement dynamic library loading (`.so`, `.dll`, `.dylib`)
81
+ - Add scripting language support (Lua, Python, etc.)
82
+ - Create a proper extension SDK with more hook types
83
+ - Add tool registration capabilities for custom tools
84
+
85
+ ## License
86
+
87
+ MIT License - feel free to modify and distribute.
88
+
89
+ ## Author
90
+
91
+ john mcconnell <john.microtech@gmail.com>
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "logging-hook",
3
+ "version": "1.0.0",
4
+ "description": "A sample extension that logs tool invocations for debugging and monitoring",
5
+ "author": "john mcconnell <john.microtech@gmail.com>",
6
+ "extension_type": "hook",
7
+ "hooks": [
8
+ {
9
+ "name": "tool-logger",
10
+ "hook_type": "both",
11
+ "script": null,
12
+ "config": {
13
+ "log_level": "debug",
14
+ "include_args": true,
15
+ "include_results": true,
16
+ "max_result_length": 500
17
+ }
18
+ }
19
+ ],
20
+ "dependencies": [],
21
+ "enabled": true
22
+ }
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "grok-cli-acp",
3
+ "version": "0.1.2",
4
+ "description": "grok-cli in rust with acp access",
5
+ "keywords": [
6
+ "Xai",
7
+ "grok",
8
+ "Zed",
9
+ "ACP"
10
+ ],
11
+ "homepage": "https://github.com/micro-tech/grok-cli#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/micro-tech/grok-cli/issues"
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/micro-tech/grok-cli.git"
18
+ },
19
+ "license": "ISC",
20
+ "author": "john mcconnell",
21
+ "type": "commonjs",
22
+ "main": "H:\\GitHub\\grok-cli\\target\\release\\groke.exe",
23
+ "directories": {
24
+ "doc": "docs",
25
+ "example": "examples"
26
+ },
27
+ "scripts": {
28
+ "test": "echo \"Error: no test specified\" && exit 1"
29
+ }
30
+ }
@@ -0,0 +1,252 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Test script for ACP (Agent Client Protocol) stdio communication
4
+ This script properly handles the JSON-RPC protocol and session management
5
+ """
6
+
7
+ import json
8
+ import subprocess
9
+ import sys
10
+ import time
11
+ from typing import Optional
12
+
13
+
14
+ def send_message(proc, message: dict) -> None:
15
+ """Send a JSON-RPC message to the process"""
16
+ msg_str = json.dumps(message)
17
+ print(f">>> Sending: {msg_str}", file=sys.stderr)
18
+ proc.stdin.write(msg_str + "\n")
19
+ proc.stdin.flush()
20
+
21
+
22
+ def read_response(proc, timeout: float = 5.0) -> Optional[dict]:
23
+ """Read a JSON-RPC response from the process"""
24
+ proc.stdout.flush()
25
+ line = proc.stdout.readline()
26
+ if not line:
27
+ return None
28
+
29
+ line = line.strip()
30
+ if not line:
31
+ return None
32
+
33
+ print(f"<<< Received: {line}", file=sys.stderr)
34
+
35
+ try:
36
+ return json.loads(line)
37
+ except json.JSONDecodeError as e:
38
+ print(f"Error parsing JSON: {e}", file=sys.stderr)
39
+ print(f"Raw line: {line}", file=sys.stderr)
40
+ return None
41
+
42
+
43
+ def main():
44
+ print("=" * 60)
45
+ print("Testing ACP Protocol via stdio")
46
+ print("=" * 60)
47
+ print()
48
+
49
+ # Start grok in ACP stdio mode
50
+ proc = subprocess.Popen(
51
+ ["./target/release/grok.exe", "acp", "stdio"],
52
+ stdin=subprocess.PIPE,
53
+ stdout=subprocess.PIPE,
54
+ stderr=subprocess.PIPE,
55
+ text=True,
56
+ bufsize=1,
57
+ )
58
+
59
+ try:
60
+ # Give it a moment to start
61
+ time.sleep(0.5)
62
+
63
+ # Step 1: Initialize
64
+ print("Step 1: Initialize")
65
+ print("-" * 60)
66
+ init_msg = {
67
+ "jsonrpc": "2.0",
68
+ "id": 1,
69
+ "method": "initialize",
70
+ "params": {
71
+ "protocolVersion": "1",
72
+ "clientInfo": {"name": "test-client", "version": "1.0.0"},
73
+ },
74
+ }
75
+ send_message(proc, init_msg)
76
+ init_response = read_response(proc)
77
+
78
+ if not init_response:
79
+ print("❌ No initialize response")
80
+ return 1
81
+
82
+ if "error" in init_response:
83
+ print(f"❌ Initialize error: {init_response['error']}")
84
+ return 1
85
+
86
+ print(f"✓ Initialize successful")
87
+ print()
88
+
89
+ # Step 2: Create new session
90
+ print("Step 2: Create Session")
91
+ print("-" * 60)
92
+ new_session_msg = {
93
+ "jsonrpc": "2.0",
94
+ "id": 2,
95
+ "method": "session/new",
96
+ "params": {},
97
+ }
98
+ send_message(proc, new_session_msg)
99
+ session_response = read_response(proc)
100
+
101
+ if not session_response:
102
+ print("❌ No session/new response")
103
+ return 1
104
+
105
+ if "error" in session_response:
106
+ print(f"❌ Session creation error: {session_response['error']}")
107
+ return 1
108
+
109
+ session_id = session_response.get("result", {}).get("sessionId")
110
+ if not session_id:
111
+ print(f"❌ No session ID in response: {session_response}")
112
+ return 1
113
+
114
+ print(f"✓ Session created: {session_id}")
115
+ print()
116
+
117
+ # Step 3: Send prompt
118
+ print("Step 3: Send Prompt")
119
+ print("-" * 60)
120
+ prompt_msg = {
121
+ "jsonrpc": "2.0",
122
+ "id": 3,
123
+ "method": "session/prompt",
124
+ "params": {
125
+ "sessionId": session_id,
126
+ "prompt": [
127
+ {
128
+ "type": "text",
129
+ "text": "Hello! Please respond with exactly: Hello World!",
130
+ }
131
+ ],
132
+ },
133
+ }
134
+ send_message(proc, prompt_msg)
135
+
136
+ # Step 4: Read all responses (notifications + final response)
137
+ print()
138
+ print("Step 4: Reading Responses")
139
+ print("-" * 60)
140
+
141
+ notifications = []
142
+ final_response = None
143
+ timeout_counter = 0
144
+ max_timeout = 30 # 30 seconds max
145
+
146
+ while timeout_counter < max_timeout:
147
+ response = read_response(proc, timeout=1.0)
148
+
149
+ if response:
150
+ # Check if it's a notification (no id) or a response (has id)
151
+ if "id" not in response:
152
+ # Notification
153
+ notifications.append(response)
154
+ print(f" 📢 Notification: {response.get('method', 'unknown')}")
155
+
156
+ # Check for session/update with content
157
+ if response.get("method") == "session/update":
158
+ params = response.get("params", {})
159
+ update = params.get("update", {})
160
+ if update.get("sessionUpdate") == "agent_message_chunk":
161
+ content = update.get("content", {})
162
+ if content.get("type") == "text":
163
+ text = content.get("text", "")
164
+ print(f" 💬 Content: {text}")
165
+ elif response.get("id") == 3:
166
+ # Final response to our prompt
167
+ final_response = response
168
+ print(f" ✓ Final response received")
169
+ break
170
+
171
+ timeout_counter = 0
172
+ else:
173
+ timeout_counter += 1
174
+ time.sleep(0.1)
175
+
176
+ print()
177
+ print("=" * 60)
178
+ print("Results")
179
+ print("=" * 60)
180
+
181
+ # Analyze results
182
+ print(f"Notifications received: {len(notifications)}")
183
+
184
+ # Check for session/update notifications
185
+ update_notifications = [
186
+ n for n in notifications if n.get("method") == "session/update"
187
+ ]
188
+ print(f"session/update notifications: {len(update_notifications)}")
189
+
190
+ # Extract content
191
+ content_chunks = []
192
+ for notif in update_notifications:
193
+ params = notif.get("params", {})
194
+ update = params.get("update", {})
195
+ if update.get("sessionUpdate") == "agent_message_chunk":
196
+ content = update.get("content", {})
197
+ if content.get("type") == "text":
198
+ text = content.get("text", "")
199
+ content_chunks.append(text)
200
+
201
+ if content_chunks:
202
+ print(f"✓ Content found: {len(content_chunks)} chunk(s)")
203
+ print()
204
+ print("Combined content:")
205
+ print("-" * 60)
206
+ for i, chunk in enumerate(content_chunks, 1):
207
+ print(f"Chunk {i}: {chunk}")
208
+ print("-" * 60)
209
+ else:
210
+ print("❌ No content found in notifications")
211
+
212
+ # Check final response
213
+ if final_response:
214
+ if "error" in final_response:
215
+ print(f"❌ Error in final response: {final_response['error']}")
216
+ return 1
217
+ else:
218
+ result = final_response.get("result", {})
219
+ stop_reason = result.get("stopReason")
220
+ print(f"✓ Stop reason: {stop_reason}")
221
+ else:
222
+ print("❌ No final response received")
223
+ return 1
224
+
225
+ print()
226
+ if content_chunks and final_response and "error" not in final_response:
227
+ print("✅ Test PASSED - ACP protocol working correctly!")
228
+ return 0
229
+ else:
230
+ print("❌ Test FAILED - Missing content or errors")
231
+ return 1
232
+
233
+ except KeyboardInterrupt:
234
+ print("\nTest interrupted")
235
+ return 1
236
+ except Exception as e:
237
+ print(f"❌ Exception: {e}")
238
+ import traceback
239
+
240
+ traceback.print_exc()
241
+ return 1
242
+ finally:
243
+ # Clean shutdown
244
+ try:
245
+ proc.stdin.close()
246
+ proc.wait(timeout=2)
247
+ except:
248
+ proc.kill()
249
+
250
+
251
+ if __name__ == "__main__":
252
+ sys.exit(main())