@muggleai/mcp 1.0.0 → 1.0.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.
- package/README.md +160 -160
- package/bin/muggle-mcp.js +2 -2
- package/dist/{chunk-6DQWAMGJ.js → chunk-CL6YSSTI.js} +198 -48
- package/dist/chunk-CL6YSSTI.js.map +1 -0
- package/dist/cli/cleanup.d.ts +55 -0
- package/dist/cli/cleanup.d.ts.map +1 -0
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/upgrade.d.ts +26 -0
- package/dist/cli/upgrade.d.ts.map +1 -0
- package/dist/cli.js +620 -24
- package/dist/cli.js.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/local-qa/services/execution-service.d.ts.map +1 -1
- package/dist/shared/checksum.d.ts +59 -0
- package/dist/shared/checksum.d.ts.map +1 -0
- package/dist/shared/config.d.ts +21 -2
- package/dist/shared/config.d.ts.map +1 -1
- package/dist/shared/types.d.ts +24 -0
- package/dist/shared/types.d.ts.map +1 -1
- package/package.json +81 -75
- package/scripts/postinstall.mjs +247 -153
- package/dist/chunk-6DQWAMGJ.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,160 +1,160 @@
|
|
|
1
|
-
# @muggleai/mcp
|
|
2
|
-
|
|
3
|
-
Unified MCP server for Muggle AI - combines Cloud QA and Local Testing tools into a single package.
|
|
4
|
-
|
|
5
|
-
## Installation
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm install -g @muggleai/mcp
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
This automatically:
|
|
12
|
-
1. Installs the package
|
|
13
|
-
2. Downloads the Electron app binary (via postinstall)
|
|
14
|
-
3. Sets up CLI commands
|
|
15
|
-
|
|
16
|
-
## Quick Start
|
|
17
|
-
|
|
18
|
-
### 1. Add to your MCP client
|
|
19
|
-
|
|
20
|
-
**Cursor (`~/.cursor/mcp.json`):**
|
|
21
|
-
|
|
22
|
-
```json
|
|
23
|
-
{
|
|
24
|
-
"mcpServers": {
|
|
25
|
-
"muggle": {
|
|
26
|
-
"command": "muggle-mcp",
|
|
27
|
-
"args": ["serve"]
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
### 2. Start using MCP tools
|
|
34
|
-
|
|
35
|
-
Ask your AI assistant to test your application! Authentication happens automatically when needed.
|
|
36
|
-
|
|
37
|
-
## CLI Commands
|
|
38
|
-
|
|
39
|
-
```bash
|
|
40
|
-
# Server (main command - starts MCP server for AI clients)
|
|
41
|
-
muggle-mcp serve # Start server with all tools (default)
|
|
42
|
-
muggle-mcp serve --qa # Cloud QA tools only
|
|
43
|
-
muggle-mcp serve --local # Local testing tools only
|
|
44
|
-
|
|
45
|
-
# Setup & Diagnostics
|
|
46
|
-
muggle-mcp setup # Download/update Electron app
|
|
47
|
-
muggle-mcp setup --force # Force re-download
|
|
48
|
-
muggle-mcp doctor # Diagnose installation issues
|
|
49
|
-
|
|
50
|
-
# Authentication (optional - auth happens automatically)
|
|
51
|
-
muggle-mcp login # Manually trigger login
|
|
52
|
-
muggle-mcp logout # Clear credentials
|
|
53
|
-
muggle-mcp status # Show auth status
|
|
54
|
-
|
|
55
|
-
# Info
|
|
56
|
-
muggle-mcp --version # Show version
|
|
57
|
-
muggle-mcp --help # Show help
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
## Authentication
|
|
61
|
-
|
|
62
|
-
Authentication happens automatically when you first use a tool that requires it:
|
|
63
|
-
|
|
64
|
-
1. A browser window opens with a verification code
|
|
65
|
-
2. You log in with your Muggle AI account
|
|
66
|
-
3. The tool call continues with your credentials
|
|
67
|
-
|
|
68
|
-
Your credentials are stored in `~/.muggle-ai/credentials.json` and persist across sessions.
|
|
69
|
-
|
|
70
|
-
## Available Tools
|
|
71
|
-
|
|
72
|
-
### Cloud QA Tools
|
|
73
|
-
|
|
74
|
-
Tools that work with the Muggle AI cloud backend:
|
|
75
|
-
|
|
76
|
-
- `qa_project_create` - Create QA project
|
|
77
|
-
- `qa_project_list` - List projects
|
|
78
|
-
- `qa_use_case_create_from_prompts` - Create use cases
|
|
79
|
-
- `qa_test_case_generate_from_prompt` - Generate test cases
|
|
80
|
-
- `qa_workflow_start_*` - Start various workflows
|
|
81
|
-
- And more...
|
|
82
|
-
|
|
83
|
-
### Local QA Tools
|
|
84
|
-
|
|
85
|
-
Tools that work with local testing:
|
|
86
|
-
|
|
87
|
-
- `muggle_project_create` - Create local project
|
|
88
|
-
- `muggle_test_case_save` - Save test case locally
|
|
89
|
-
- `muggle_execute_test_generation` - Generate test script
|
|
90
|
-
- `muggle_execute_replay` - Replay test script
|
|
91
|
-
- `muggle_cloud_pull_project` - Pull from cloud
|
|
92
|
-
- `muggle_publish_project` - Publish to cloud
|
|
93
|
-
- And more...
|
|
94
|
-
|
|
95
|
-
## Data Directory
|
|
96
|
-
|
|
97
|
-
All Muggle AI data is stored in `~/.muggle-ai/`:
|
|
98
|
-
|
|
99
|
-
```
|
|
100
|
-
~/.muggle-ai/
|
|
101
|
-
├── credentials.json # Auth credentials (auto-generated)
|
|
102
|
-
├── projects/ # Local test projects
|
|
103
|
-
├── sessions/ # Test execution sessions
|
|
104
|
-
└── electron-app/ # Downloaded Electron app
|
|
105
|
-
└── 1.0.0/
|
|
106
|
-
└── MuggleAI.exe
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
## Requirements
|
|
110
|
-
|
|
111
|
-
- Node.js 22 or higher
|
|
112
|
-
- For local testing: Electron app (downloaded automatically)
|
|
113
|
-
|
|
114
|
-
## Development
|
|
115
|
-
|
|
116
|
-
### Building
|
|
117
|
-
|
|
118
|
-
```bash
|
|
119
|
-
npm install
|
|
120
|
-
npm run build
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
### Testing
|
|
124
|
-
|
|
125
|
-
```bash
|
|
126
|
-
npm test # Run tests once
|
|
127
|
-
npm run test:watch # Watch mode
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
### Linting
|
|
131
|
-
|
|
132
|
-
```bash
|
|
133
|
-
npm run lint # Auto-fix issues
|
|
134
|
-
npm run lint:check # Check only
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
## CI/CD Workflows
|
|
138
|
-
|
|
139
|
-
| Workflow | Trigger | Description |
|
|
140
|
-
| :------- | :------ | :---------- |
|
|
141
|
-
| `ci.yml` | Push/PR to main | Lint, test, build on multiple platforms/versions |
|
|
142
|
-
| `publish-mcp.yml` | Tag `v*` | Publish package to npm |
|
|
143
|
-
| `release-electron-app.yml` | Tag `electron-app@*` | Build and release Electron binaries |
|
|
144
|
-
|
|
145
|
-
### Publishing a new version
|
|
146
|
-
|
|
147
|
-
1. Update version in `package.json`
|
|
148
|
-
2. Commit and push
|
|
149
|
-
3. Create a git tag: `git tag v1.0.1 && git push --tags`
|
|
150
|
-
4. The `publish-mcp.yml` workflow publishes to npm automatically
|
|
151
|
-
|
|
152
|
-
### Releasing Electron app
|
|
153
|
-
|
|
154
|
-
1. Update `muggleConfig.electronAppVersion` in `package.json`
|
|
155
|
-
2. Run the `release-electron-app.yml` workflow manually
|
|
156
|
-
3. Or create a tag: `git tag electron-app@1.0.1 && git push --tags`
|
|
157
|
-
|
|
158
|
-
## License
|
|
159
|
-
|
|
160
|
-
MIT
|
|
1
|
+
# @muggleai/mcp
|
|
2
|
+
|
|
3
|
+
Unified MCP server for Muggle AI - combines Cloud QA and Local Testing tools into a single package.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @muggleai/mcp
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
This automatically:
|
|
12
|
+
1. Installs the package
|
|
13
|
+
2. Downloads the Electron app binary (via postinstall)
|
|
14
|
+
3. Sets up CLI commands
|
|
15
|
+
|
|
16
|
+
## Quick Start
|
|
17
|
+
|
|
18
|
+
### 1. Add to your MCP client
|
|
19
|
+
|
|
20
|
+
**Cursor (`~/.cursor/mcp.json`):**
|
|
21
|
+
|
|
22
|
+
```json
|
|
23
|
+
{
|
|
24
|
+
"mcpServers": {
|
|
25
|
+
"muggle": {
|
|
26
|
+
"command": "muggle-mcp",
|
|
27
|
+
"args": ["serve"]
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### 2. Start using MCP tools
|
|
34
|
+
|
|
35
|
+
Ask your AI assistant to test your application! Authentication happens automatically when needed.
|
|
36
|
+
|
|
37
|
+
## CLI Commands
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# Server (main command - starts MCP server for AI clients)
|
|
41
|
+
muggle-mcp serve # Start server with all tools (default)
|
|
42
|
+
muggle-mcp serve --qa # Cloud QA tools only
|
|
43
|
+
muggle-mcp serve --local # Local testing tools only
|
|
44
|
+
|
|
45
|
+
# Setup & Diagnostics
|
|
46
|
+
muggle-mcp setup # Download/update Electron app
|
|
47
|
+
muggle-mcp setup --force # Force re-download
|
|
48
|
+
muggle-mcp doctor # Diagnose installation issues
|
|
49
|
+
|
|
50
|
+
# Authentication (optional - auth happens automatically)
|
|
51
|
+
muggle-mcp login # Manually trigger login
|
|
52
|
+
muggle-mcp logout # Clear credentials
|
|
53
|
+
muggle-mcp status # Show auth status
|
|
54
|
+
|
|
55
|
+
# Info
|
|
56
|
+
muggle-mcp --version # Show version
|
|
57
|
+
muggle-mcp --help # Show help
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Authentication
|
|
61
|
+
|
|
62
|
+
Authentication happens automatically when you first use a tool that requires it:
|
|
63
|
+
|
|
64
|
+
1. A browser window opens with a verification code
|
|
65
|
+
2. You log in with your Muggle AI account
|
|
66
|
+
3. The tool call continues with your credentials
|
|
67
|
+
|
|
68
|
+
Your credentials are stored in `~/.muggle-ai/credentials.json` and persist across sessions.
|
|
69
|
+
|
|
70
|
+
## Available Tools
|
|
71
|
+
|
|
72
|
+
### Cloud QA Tools
|
|
73
|
+
|
|
74
|
+
Tools that work with the Muggle AI cloud backend:
|
|
75
|
+
|
|
76
|
+
- `qa_project_create` - Create QA project
|
|
77
|
+
- `qa_project_list` - List projects
|
|
78
|
+
- `qa_use_case_create_from_prompts` - Create use cases
|
|
79
|
+
- `qa_test_case_generate_from_prompt` - Generate test cases
|
|
80
|
+
- `qa_workflow_start_*` - Start various workflows
|
|
81
|
+
- And more...
|
|
82
|
+
|
|
83
|
+
### Local QA Tools
|
|
84
|
+
|
|
85
|
+
Tools that work with local testing:
|
|
86
|
+
|
|
87
|
+
- `muggle_project_create` - Create local project
|
|
88
|
+
- `muggle_test_case_save` - Save test case locally
|
|
89
|
+
- `muggle_execute_test_generation` - Generate test script
|
|
90
|
+
- `muggle_execute_replay` - Replay test script
|
|
91
|
+
- `muggle_cloud_pull_project` - Pull from cloud
|
|
92
|
+
- `muggle_publish_project` - Publish to cloud
|
|
93
|
+
- And more...
|
|
94
|
+
|
|
95
|
+
## Data Directory
|
|
96
|
+
|
|
97
|
+
All Muggle AI data is stored in `~/.muggle-ai/`:
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
~/.muggle-ai/
|
|
101
|
+
├── credentials.json # Auth credentials (auto-generated)
|
|
102
|
+
├── projects/ # Local test projects
|
|
103
|
+
├── sessions/ # Test execution sessions
|
|
104
|
+
└── electron-app/ # Downloaded Electron app
|
|
105
|
+
└── 1.0.0/
|
|
106
|
+
└── MuggleAI.exe
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Requirements
|
|
110
|
+
|
|
111
|
+
- Node.js 22 or higher
|
|
112
|
+
- For local testing: Electron app (downloaded automatically)
|
|
113
|
+
|
|
114
|
+
## Development
|
|
115
|
+
|
|
116
|
+
### Building
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
npm install
|
|
120
|
+
npm run build
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Testing
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
npm test # Run tests once
|
|
127
|
+
npm run test:watch # Watch mode
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Linting
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
npm run lint # Auto-fix issues
|
|
134
|
+
npm run lint:check # Check only
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## CI/CD Workflows
|
|
138
|
+
|
|
139
|
+
| Workflow | Trigger | Description |
|
|
140
|
+
| :------- | :------ | :---------- |
|
|
141
|
+
| `ci.yml` | Push/PR to main | Lint, test, build on multiple platforms/versions |
|
|
142
|
+
| `publish-mcp.yml` | Tag `v*` | Publish package to npm |
|
|
143
|
+
| `release-electron-app.yml` | Tag `electron-app@*` | Build and release Electron binaries |
|
|
144
|
+
|
|
145
|
+
### Publishing a new version
|
|
146
|
+
|
|
147
|
+
1. Update version in `package.json`
|
|
148
|
+
2. Commit and push
|
|
149
|
+
3. Create a git tag: `git tag v1.0.1 && git push --tags`
|
|
150
|
+
4. The `publish-mcp.yml` workflow publishes to npm automatically
|
|
151
|
+
|
|
152
|
+
### Releasing Electron app
|
|
153
|
+
|
|
154
|
+
1. Update `muggleConfig.electronAppVersion` in `package.json`
|
|
155
|
+
2. Run the `release-electron-app.yml` workflow manually
|
|
156
|
+
3. Or create a tag: `git tag electron-app@1.0.1 && git push --tags`
|
|
157
|
+
|
|
158
|
+
## License
|
|
159
|
+
|
|
160
|
+
MIT
|
package/bin/muggle-mcp.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import "../dist/cli.js";
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import "../dist/cli.js";
|
|
@@ -15,6 +15,12 @@ import { ulid } from 'ulid';
|
|
|
15
15
|
import * as fs6 from 'fs/promises';
|
|
16
16
|
|
|
17
17
|
var __defProp = Object.defineProperty;
|
|
18
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
19
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
20
|
+
}) : x)(function(x) {
|
|
21
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
22
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
23
|
+
});
|
|
18
24
|
var __export = (target, all) => {
|
|
19
25
|
for (var name in all)
|
|
20
26
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -51,14 +57,19 @@ function getMuggleConfig() {
|
|
|
51
57
|
const packageJson = JSON.parse(fs4.readFileSync(packageJsonPath, "utf-8"));
|
|
52
58
|
const config = packageJson.muggleConfig;
|
|
53
59
|
if (config?.electronAppVersion && config?.downloadBaseUrl) {
|
|
54
|
-
muggleConfigCache =
|
|
55
|
-
|
|
60
|
+
muggleConfigCache = {
|
|
61
|
+
electronAppVersion: config.electronAppVersion,
|
|
62
|
+
downloadBaseUrl: config.downloadBaseUrl,
|
|
63
|
+
checksums: config.checksums
|
|
64
|
+
};
|
|
65
|
+
return muggleConfigCache;
|
|
56
66
|
}
|
|
57
67
|
} catch {
|
|
58
68
|
}
|
|
59
69
|
muggleConfigCache = {
|
|
60
|
-
electronAppVersion: "1.0.
|
|
61
|
-
downloadBaseUrl: "https://github.com/multiplex-ai/muggle-ai-mcp/releases/download"
|
|
70
|
+
electronAppVersion: "1.0.1",
|
|
71
|
+
downloadBaseUrl: "https://github.com/multiplex-ai/muggle-ai-mcp/releases/download",
|
|
72
|
+
checksums: {}
|
|
62
73
|
};
|
|
63
74
|
return muggleConfigCache;
|
|
64
75
|
}
|
|
@@ -201,12 +212,51 @@ function resetConfig() {
|
|
|
201
212
|
configInstance = null;
|
|
202
213
|
muggleConfigCache = null;
|
|
203
214
|
}
|
|
215
|
+
var VERSION_OVERRIDE_FILE = "electron-app-version-override.json";
|
|
216
|
+
var ELECTRON_APP_VERSION_ENV = "ELECTRON_APP_VERSION";
|
|
204
217
|
function getElectronAppVersion() {
|
|
218
|
+
const envVersion = process.env[ELECTRON_APP_VERSION_ENV];
|
|
219
|
+
if (envVersion && /^\d+\.\d+\.\d+$/.test(envVersion)) {
|
|
220
|
+
return envVersion;
|
|
221
|
+
}
|
|
222
|
+
const overridePath = path4.join(getDataDir(), VERSION_OVERRIDE_FILE);
|
|
223
|
+
if (fs4.existsSync(overridePath)) {
|
|
224
|
+
try {
|
|
225
|
+
const content = JSON.parse(fs4.readFileSync(overridePath, "utf-8"));
|
|
226
|
+
if (content.version && typeof content.version === "string") {
|
|
227
|
+
return content.version;
|
|
228
|
+
}
|
|
229
|
+
} catch {
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return getMuggleConfig().electronAppVersion;
|
|
233
|
+
}
|
|
234
|
+
function getElectronAppVersionSource() {
|
|
235
|
+
const envVersion = process.env[ELECTRON_APP_VERSION_ENV];
|
|
236
|
+
if (envVersion && /^\d+\.\d+\.\d+$/.test(envVersion)) {
|
|
237
|
+
return "env";
|
|
238
|
+
}
|
|
239
|
+
const overridePath = path4.join(getDataDir(), VERSION_OVERRIDE_FILE);
|
|
240
|
+
if (fs4.existsSync(overridePath)) {
|
|
241
|
+
try {
|
|
242
|
+
const content = JSON.parse(fs4.readFileSync(overridePath, "utf-8"));
|
|
243
|
+
if (content.version && typeof content.version === "string") {
|
|
244
|
+
return "override";
|
|
245
|
+
}
|
|
246
|
+
} catch {
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return "bundled";
|
|
250
|
+
}
|
|
251
|
+
function getBundledElectronAppVersion() {
|
|
205
252
|
return getMuggleConfig().electronAppVersion;
|
|
206
253
|
}
|
|
207
254
|
function getDownloadBaseUrl() {
|
|
208
255
|
return getMuggleConfig().downloadBaseUrl;
|
|
209
256
|
}
|
|
257
|
+
function getElectronAppChecksums() {
|
|
258
|
+
return getMuggleConfig().checksums;
|
|
259
|
+
}
|
|
210
260
|
function isElectronAppInstalled() {
|
|
211
261
|
return getDownloadedElectronAppPath() !== null;
|
|
212
262
|
}
|
|
@@ -5376,6 +5426,8 @@ function buildSecretOptionsFromLocalSecrets(params) {
|
|
|
5376
5426
|
}
|
|
5377
5427
|
var DEFAULT_GENERATION_TIMEOUT_MS = 3e5;
|
|
5378
5428
|
var DEFAULT_REPLAY_TIMEOUT_MS = 18e4;
|
|
5429
|
+
var INACTIVITY_TIMEOUT_MS = 12e4;
|
|
5430
|
+
var INACTIVITY_CHECK_INTERVAL_MS = 5e3;
|
|
5379
5431
|
var activeProcesses = /* @__PURE__ */ new Map();
|
|
5380
5432
|
function generateRunId() {
|
|
5381
5433
|
return `run_${ulid()}`;
|
|
@@ -5646,6 +5698,7 @@ async function spawnElectronApp(params) {
|
|
|
5646
5698
|
if (!childProcess.pid) {
|
|
5647
5699
|
throw new Error("Failed to spawn electron-app process");
|
|
5648
5700
|
}
|
|
5701
|
+
const now = Date.now();
|
|
5649
5702
|
const executionProcess = {
|
|
5650
5703
|
runId,
|
|
5651
5704
|
projectId,
|
|
@@ -5653,11 +5706,61 @@ async function spawnElectronApp(params) {
|
|
|
5653
5706
|
runType,
|
|
5654
5707
|
process: childProcess,
|
|
5655
5708
|
pid: childProcess.pid,
|
|
5656
|
-
startedAt:
|
|
5709
|
+
startedAt: now,
|
|
5657
5710
|
status: "running" /* RUNNING */,
|
|
5658
5711
|
inputFilePath,
|
|
5659
|
-
outputFilePath
|
|
5712
|
+
outputFilePath,
|
|
5713
|
+
capturedStdout: "",
|
|
5714
|
+
capturedStderr: "",
|
|
5715
|
+
hasExited: false,
|
|
5716
|
+
lastOutputAt: now,
|
|
5717
|
+
killedDueToInactivity: false
|
|
5660
5718
|
};
|
|
5719
|
+
childProcess.stdout?.on("data", (data) => {
|
|
5720
|
+
executionProcess.capturedStdout += data.toString();
|
|
5721
|
+
executionProcess.lastOutputAt = Date.now();
|
|
5722
|
+
});
|
|
5723
|
+
childProcess.stderr?.on("data", (data) => {
|
|
5724
|
+
executionProcess.capturedStderr += data.toString();
|
|
5725
|
+
executionProcess.lastOutputAt = Date.now();
|
|
5726
|
+
});
|
|
5727
|
+
const inactivityCheck = setInterval(() => {
|
|
5728
|
+
if (executionProcess.hasExited) {
|
|
5729
|
+
clearInterval(inactivityCheck);
|
|
5730
|
+
return;
|
|
5731
|
+
}
|
|
5732
|
+
const inactiveDuration = Date.now() - executionProcess.lastOutputAt;
|
|
5733
|
+
if (inactiveDuration >= INACTIVITY_TIMEOUT_MS) {
|
|
5734
|
+
executionProcess.killedDueToInactivity = true;
|
|
5735
|
+
executionProcess.status = "failed" /* FAILED */;
|
|
5736
|
+
clearInterval(inactivityCheck);
|
|
5737
|
+
try {
|
|
5738
|
+
executionProcess.process.kill("SIGKILL");
|
|
5739
|
+
} catch {
|
|
5740
|
+
}
|
|
5741
|
+
}
|
|
5742
|
+
}, INACTIVITY_CHECK_INTERVAL_MS);
|
|
5743
|
+
executionProcess.inactivityCheckInterval = inactivityCheck;
|
|
5744
|
+
childProcess.on("close", (code, signal) => {
|
|
5745
|
+
executionProcess.hasExited = true;
|
|
5746
|
+
executionProcess.earlyExitInfo = {
|
|
5747
|
+
code,
|
|
5748
|
+
signal,
|
|
5749
|
+
stdout: executionProcess.capturedStdout,
|
|
5750
|
+
stderr: executionProcess.capturedStderr
|
|
5751
|
+
};
|
|
5752
|
+
});
|
|
5753
|
+
childProcess.on("error", (error) => {
|
|
5754
|
+
executionProcess.hasExited = true;
|
|
5755
|
+
executionProcess.capturedStderr += `
|
|
5756
|
+
Spawn error: ${error.message}`;
|
|
5757
|
+
executionProcess.earlyExitInfo = {
|
|
5758
|
+
code: -1,
|
|
5759
|
+
signal: null,
|
|
5760
|
+
stdout: executionProcess.capturedStdout,
|
|
5761
|
+
stderr: executionProcess.capturedStderr
|
|
5762
|
+
};
|
|
5763
|
+
});
|
|
5661
5764
|
const timeoutTimer = setTimeout(() => {
|
|
5662
5765
|
handleTimeout({ executionProcess });
|
|
5663
5766
|
}, timeoutMs);
|
|
@@ -5669,63 +5772,107 @@ function handleTimeout(params) {
|
|
|
5669
5772
|
const { executionProcess } = params;
|
|
5670
5773
|
if (executionProcess.status === "running" /* RUNNING */) {
|
|
5671
5774
|
executionProcess.status = "failed" /* FAILED */;
|
|
5775
|
+
if (executionProcess.inactivityCheckInterval) {
|
|
5776
|
+
clearInterval(executionProcess.inactivityCheckInterval);
|
|
5777
|
+
}
|
|
5672
5778
|
try {
|
|
5673
5779
|
executionProcess.process.kill("SIGTERM");
|
|
5674
5780
|
} catch {
|
|
5675
5781
|
}
|
|
5676
5782
|
}
|
|
5677
5783
|
}
|
|
5784
|
+
async function handleProcessExit(params) {
|
|
5785
|
+
const { executionProcess, code, stderr } = params;
|
|
5786
|
+
if (executionProcess.timeoutTimer) {
|
|
5787
|
+
clearTimeout(executionProcess.timeoutTimer);
|
|
5788
|
+
}
|
|
5789
|
+
if (executionProcess.inactivityCheckInterval) {
|
|
5790
|
+
clearInterval(executionProcess.inactivityCheckInterval);
|
|
5791
|
+
}
|
|
5792
|
+
activeProcesses.delete(executionProcess.runId);
|
|
5793
|
+
if (executionProcess.status === "cancelled" /* CANCELLED */) {
|
|
5794
|
+
return {
|
|
5795
|
+
success: false,
|
|
5796
|
+
status: "FAILURE",
|
|
5797
|
+
summary: "Execution was cancelled",
|
|
5798
|
+
error: "Cancelled by user"
|
|
5799
|
+
};
|
|
5800
|
+
}
|
|
5801
|
+
if (executionProcess.killedDueToInactivity) {
|
|
5802
|
+
executionProcess.status = "failed" /* FAILED */;
|
|
5803
|
+
const stderrSummary = stderr.trim().slice(0, 500);
|
|
5804
|
+
return {
|
|
5805
|
+
success: false,
|
|
5806
|
+
status: "FAILURE",
|
|
5807
|
+
summary: "Process became unresponsive",
|
|
5808
|
+
error: `Process killed after ${INACTIVITY_TIMEOUT_MS / 1e3}s of inactivity (likely stuck on error dialog). ` + (stderrSummary ? `Last stderr: ${stderrSummary}` : "No stderr captured.")
|
|
5809
|
+
};
|
|
5810
|
+
}
|
|
5811
|
+
if (code !== 0 || executionProcess.status === "failed" /* FAILED */) {
|
|
5812
|
+
executionProcess.status = "failed" /* FAILED */;
|
|
5813
|
+
const errorMessage = stderr || `Process exited with code ${code}`;
|
|
5814
|
+
return {
|
|
5815
|
+
success: false,
|
|
5816
|
+
status: "FAILURE",
|
|
5817
|
+
summary: "Execution failed",
|
|
5818
|
+
error: code === -1 ? errorMessage : `Process exited with code ${code}. ${errorMessage}`
|
|
5819
|
+
};
|
|
5820
|
+
}
|
|
5821
|
+
const outputData = await readTempFile(executionProcess.outputFilePath);
|
|
5822
|
+
executionProcess.status = "passed" /* PASSED */;
|
|
5823
|
+
return {
|
|
5824
|
+
success: true,
|
|
5825
|
+
status: "SUCCESS",
|
|
5826
|
+
summary: "Execution completed successfully",
|
|
5827
|
+
actionScript: outputData
|
|
5828
|
+
};
|
|
5829
|
+
}
|
|
5678
5830
|
async function waitForCompletion(params) {
|
|
5679
5831
|
const { executionProcess } = params;
|
|
5680
|
-
|
|
5681
|
-
|
|
5682
|
-
|
|
5683
|
-
|
|
5684
|
-
|
|
5685
|
-
|
|
5686
|
-
executionProcess.process.stderr?.on("data", (data) => {
|
|
5687
|
-
stderr += data.toString();
|
|
5832
|
+
if (executionProcess.hasExited && executionProcess.earlyExitInfo) {
|
|
5833
|
+
const earlyExit = executionProcess.earlyExitInfo;
|
|
5834
|
+
return handleProcessExit({
|
|
5835
|
+
executionProcess,
|
|
5836
|
+
code: earlyExit.code,
|
|
5837
|
+
stderr: earlyExit.stderr
|
|
5688
5838
|
});
|
|
5689
|
-
|
|
5690
|
-
|
|
5691
|
-
|
|
5692
|
-
|
|
5693
|
-
|
|
5694
|
-
|
|
5695
|
-
resolve2(
|
|
5696
|
-
success: false,
|
|
5697
|
-
status: "FAILURE",
|
|
5698
|
-
summary: "Execution was cancelled",
|
|
5699
|
-
error: "Cancelled by user"
|
|
5700
|
-
});
|
|
5701
|
-
return;
|
|
5839
|
+
}
|
|
5840
|
+
return new Promise((resolve2) => {
|
|
5841
|
+
let resolved = false;
|
|
5842
|
+
const resolveOnce = (result) => {
|
|
5843
|
+
if (!resolved) {
|
|
5844
|
+
resolved = true;
|
|
5845
|
+
resolve2(result);
|
|
5702
5846
|
}
|
|
5703
|
-
|
|
5704
|
-
|
|
5705
|
-
|
|
5706
|
-
|
|
5707
|
-
|
|
5708
|
-
|
|
5709
|
-
|
|
5710
|
-
|
|
5711
|
-
|
|
5847
|
+
};
|
|
5848
|
+
const checkEarlyExit = setInterval(() => {
|
|
5849
|
+
if (executionProcess.hasExited && executionProcess.earlyExitInfo) {
|
|
5850
|
+
clearInterval(checkEarlyExit);
|
|
5851
|
+
const earlyExit = executionProcess.earlyExitInfo;
|
|
5852
|
+
handleProcessExit({
|
|
5853
|
+
executionProcess,
|
|
5854
|
+
code: earlyExit.code,
|
|
5855
|
+
stderr: earlyExit.stderr
|
|
5856
|
+
}).then(resolveOnce);
|
|
5712
5857
|
}
|
|
5713
|
-
|
|
5714
|
-
|
|
5715
|
-
|
|
5716
|
-
|
|
5717
|
-
|
|
5718
|
-
|
|
5719
|
-
|
|
5858
|
+
}, 100);
|
|
5859
|
+
executionProcess.process.on("close", async (code) => {
|
|
5860
|
+
clearInterval(checkEarlyExit);
|
|
5861
|
+
const result = await handleProcessExit({
|
|
5862
|
+
executionProcess,
|
|
5863
|
+
code,
|
|
5864
|
+
stderr: executionProcess.capturedStderr
|
|
5720
5865
|
});
|
|
5866
|
+
resolveOnce(result);
|
|
5721
5867
|
});
|
|
5722
|
-
executionProcess.process.on("error", (error) => {
|
|
5868
|
+
executionProcess.process.on("error", async (error) => {
|
|
5869
|
+
clearInterval(checkEarlyExit);
|
|
5723
5870
|
if (executionProcess.timeoutTimer) {
|
|
5724
5871
|
clearTimeout(executionProcess.timeoutTimer);
|
|
5725
5872
|
}
|
|
5726
5873
|
activeProcesses.delete(executionProcess.runId);
|
|
5727
5874
|
executionProcess.status = "failed" /* FAILED */;
|
|
5728
|
-
|
|
5875
|
+
resolveOnce({
|
|
5729
5876
|
success: false,
|
|
5730
5877
|
status: "FAILURE",
|
|
5731
5878
|
summary: "Execution error",
|
|
@@ -5998,6 +6145,9 @@ function cancelExecution(params) {
|
|
|
5998
6145
|
if (executionProcess.timeoutTimer) {
|
|
5999
6146
|
clearTimeout(executionProcess.timeoutTimer);
|
|
6000
6147
|
}
|
|
6148
|
+
if (executionProcess.inactivityCheckInterval) {
|
|
6149
|
+
clearInterval(executionProcess.inactivityCheckInterval);
|
|
6150
|
+
}
|
|
6001
6151
|
try {
|
|
6002
6152
|
executionProcess.process.kill("SIGTERM");
|
|
6003
6153
|
} catch {
|
|
@@ -7621,6 +7771,6 @@ function isLocalOnlyTool(toolName) {
|
|
|
7621
7771
|
return localOnlyTools.includes(toolName);
|
|
7622
7772
|
}
|
|
7623
7773
|
|
|
7624
|
-
export { __export, createApiKeyWithToken, createChildLogger, createUnifiedMcpServer, deleteCredentials, getAuthStatus, getCallerCredentials, getConfig, getCredentialsFilePath, getDataDir, getDownloadBaseUrl, getElectronAppDir, getElectronAppVersion, getLocalQaTools, getLogger, getQaTools, getValidCredentials, isCredentialsExpired, isElectronAppInstalled, loadCredentials, local_qa_exports, openBrowserUrl, performLogin, performLogout, pollDeviceCode, qa_exports, registerTools, resetConfig, resetLogger, saveCredentials, server_exports, startDeviceCodeFlow, startStdioServer, toolRequiresAuth };
|
|
7625
|
-
//# sourceMappingURL=chunk-
|
|
7626
|
-
//# sourceMappingURL=chunk-
|
|
7774
|
+
export { __export, __require, createApiKeyWithToken, createChildLogger, createUnifiedMcpServer, deleteCredentials, getAuthStatus, getBundledElectronAppVersion, getCallerCredentials, getConfig, getCredentialsFilePath, getDataDir, getDownloadBaseUrl, getElectronAppChecksums, getElectronAppDir, getElectronAppVersion, getElectronAppVersionSource, getLocalQaTools, getLogger, getQaTools, getValidCredentials, isCredentialsExpired, isElectronAppInstalled, loadCredentials, local_qa_exports, openBrowserUrl, performLogin, performLogout, pollDeviceCode, qa_exports, registerTools, resetConfig, resetLogger, saveCredentials, server_exports, startDeviceCodeFlow, startStdioServer, toolRequiresAuth };
|
|
7775
|
+
//# sourceMappingURL=chunk-CL6YSSTI.js.map
|
|
7776
|
+
//# sourceMappingURL=chunk-CL6YSSTI.js.map
|