@muggleai/works 4.10.0 → 4.11.0
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 +3 -3
- package/dist/{chunk-RK6XKSZK.js → chunk-Q7WNEMN4.js} +109 -43
- package/dist/{chunk-UVXOHXY2.js → chunk-ZKRHFTIC.js} +832 -89
- package/dist/cli.js +2 -2
- package/dist/index.js +2 -2
- package/dist/plugin/.claude-plugin/plugin.json +1 -1
- package/dist/plugin/.cursor-plugin/plugin.json +1 -1
- package/dist/plugin/README.md +4 -2
- package/dist/plugin/agents/acceptance-tester.md +24 -10
- package/dist/plugin/commands/m.md +7 -0
- package/dist/plugin/commands/mdo.md +7 -0
- package/dist/plugin/commands/mfeedback.md +7 -0
- package/dist/plugin/commands/mimport.md +7 -0
- package/dist/plugin/commands/mpr.md +7 -0
- package/dist/plugin/commands/mprefs.md +7 -0
- package/dist/plugin/commands/mregen.md +7 -0
- package/dist/plugin/commands/mrelease.md +7 -0
- package/dist/plugin/commands/mrepair.md +7 -0
- package/dist/plugin/commands/mstatus.md +7 -0
- package/dist/plugin/commands/mtest.md +7 -0
- package/dist/plugin/commands/mtestlocal.md +7 -0
- package/dist/plugin/commands/mtestprep.md +7 -0
- package/dist/plugin/commands/mupgrade.md +7 -0
- package/dist/plugin/scripts/ensure-electron-app.sh +35 -8
- package/dist/plugin/skills/_aliases.json +18 -0
- package/dist/plugin/skills/_shared/dev-server-readiness.md +231 -0
- package/dist/plugin/skills/_shared/failure-mode-handling.md +244 -0
- package/dist/plugin/skills/_shared/post-merge-cleanup.md +10 -0
- package/dist/plugin/skills/_shared/pr-followup-helpers.md +150 -0
- package/dist/plugin/skills/_shared/rebase-before-e2e.md +15 -0
- package/dist/plugin/skills/_shared/telemetry-emit.md +15 -0
- package/dist/plugin/skills/_shared/use-worktrees.md +53 -0
- package/dist/plugin/skills/do/build.md +51 -0
- package/dist/plugin/skills/do/e2e-acceptance.md +64 -19
- package/dist/plugin/skills/do/impact-analysis.md +47 -7
- package/dist/plugin/skills/do/open-prs.md +72 -74
- package/dist/plugin/skills/do/pre-flight.md +21 -14
- package/dist/plugin/skills/do/requirements.md +2 -2
- package/dist/plugin/skills/do/unit-tests.md +2 -2
- package/dist/plugin/skills/m/SKILL.md +8 -0
- package/dist/plugin/skills/mdo/SKILL.md +8 -0
- package/dist/plugin/skills/mfeedback/SKILL.md +8 -0
- package/dist/plugin/skills/mimport/SKILL.md +8 -0
- package/dist/plugin/skills/mpr/SKILL.md +8 -0
- package/dist/plugin/skills/mprefs/SKILL.md +8 -0
- package/dist/plugin/skills/mregen/SKILL.md +8 -0
- package/dist/plugin/skills/mrelease/SKILL.md +8 -0
- package/dist/plugin/skills/mrepair/SKILL.md +8 -0
- package/dist/plugin/skills/mstatus/SKILL.md +8 -0
- package/dist/plugin/skills/mtest/SKILL.md +8 -0
- package/dist/plugin/skills/mtestlocal/SKILL.md +8 -0
- package/dist/plugin/skills/mtestprep/SKILL.md +8 -0
- package/dist/plugin/skills/muggle/SKILL.md +9 -6
- package/dist/plugin/skills/muggle-do/SKILL.md +36 -61
- package/dist/plugin/skills/muggle-do-task/SKILL.md +134 -0
- package/dist/plugin/skills/muggle-feedback/SKILL.md +39 -0
- package/dist/plugin/skills/muggle-feedback/ops/delete.md +49 -0
- package/dist/plugin/skills/muggle-feedback/ops/list.md +65 -0
- package/dist/plugin/skills/muggle-feedback/ops/submit.md +130 -0
- package/dist/plugin/skills/muggle-pr-followup/SKILL.md +59 -0
- package/dist/plugin/skills/muggle-pr-followup/contract.md +191 -0
- package/dist/plugin/skills/muggle-pr-visual-walkthrough/SKILL.md +68 -43
- package/dist/plugin/skills/muggle-pr-visual-walkthrough/e2e-report-assembly.md +86 -0
- package/dist/plugin/skills/muggle-preferences/SKILL.md +16 -108
- package/dist/plugin/skills/muggle-preferences/ops/change-one.md +10 -0
- package/dist/plugin/skills/muggle-preferences/ops/configure.md +49 -0
- package/dist/plugin/skills/muggle-preferences/ops/list.md +9 -0
- package/dist/plugin/skills/muggle-preferences/ops/reset.md +6 -0
- package/dist/plugin/skills/muggle-preferences/ops/set.md +10 -0
- package/dist/plugin/skills/muggle-preferences/preference-gates/README.md +1 -1
- package/dist/plugin/skills/muggle-preferences/preference-gates/autoCleanup.md +11 -0
- package/dist/plugin/skills/muggle-preferences/preference-gates/autoCreatePR.md +13 -0
- package/dist/plugin/skills/muggle-preferences/preference-gates/autoDetectChanges.md +3 -3
- package/dist/plugin/skills/muggle-preferences/preference-gates/autoE2ETest.md +11 -0
- package/dist/plugin/skills/muggle-preferences/preference-gates/autoLogin.md +1 -1
- package/dist/plugin/skills/muggle-preferences/preference-gates/autoPublishLocalResults.md +2 -2
- package/dist/plugin/skills/muggle-preferences/preference-gates/autoRebase.md +11 -0
- package/dist/plugin/skills/muggle-preferences/preference-gates/autoSelectLocalHost.md +19 -0
- package/dist/plugin/skills/muggle-preferences/preference-gates/autoSelectProject.md +1 -2
- package/dist/plugin/skills/muggle-preferences/preference-gates/autoUseWorktree.md +11 -0
- package/dist/plugin/skills/muggle-preferences/preference-gates/checkForUpdates.md +4 -4
- package/dist/plugin/skills/muggle-preferences/preference-gates/defaultExecutionMode.md +1 -1
- package/dist/plugin/skills/muggle-preferences/preference-gates/openTestResultsAfterRun.md +1 -1
- package/dist/plugin/skills/muggle-preferences/preference-gates/postPRVisualWalkthrough.md +8 -25
- package/dist/plugin/skills/muggle-preferences/preference-gates/showElectronBrowser.md +1 -1
- package/dist/plugin/skills/muggle-preferences/preference-gates/suggestRelatedTestCases.md +4 -4
- package/dist/plugin/skills/muggle-preferences/preference-gates/suggestRelatedUseCases.md +4 -4
- package/dist/plugin/skills/muggle-repair/SKILL.md +4 -2
- package/dist/plugin/skills/muggle-status/SKILL.md +8 -5
- package/dist/plugin/skills/muggle-test/SKILL.md +110 -86
- package/dist/plugin/skills/muggle-test-feature-local/SKILL.md +83 -62
- package/dist/plugin/skills/muggle-test-import/SKILL.md +28 -23
- package/dist/plugin/skills/muggle-test-prepare/SKILL.md +79 -18
- package/dist/plugin/skills/muggle-test-regenerate-missing/SKILL.md +34 -18
- package/dist/plugin/skills/muggle-test-regenerate-missing/evals/evals.json +9 -9
- package/dist/plugin/skills/muggle-upgrade/SKILL.md +4 -2
- package/dist/plugin/skills/muggle-works-npm-release/SKILL.md +6 -4
- package/dist/plugin/skills/mupgrade/SKILL.md +8 -0
- package/dist/release-manifest.json +4 -4
- package/dist/{src-GD3YFCCW.js → src-2G7ENRGI.js} +1 -1
- package/package.json +9 -7
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.cursor-plugin/plugin.json +1 -1
- package/plugin/README.md +4 -2
- package/plugin/agents/acceptance-tester.md +24 -10
- package/plugin/commands/m.md +7 -0
- package/plugin/commands/mdo.md +7 -0
- package/plugin/commands/mfeedback.md +7 -0
- package/plugin/commands/mimport.md +7 -0
- package/plugin/commands/mpr.md +7 -0
- package/plugin/commands/mprefs.md +7 -0
- package/plugin/commands/mregen.md +7 -0
- package/plugin/commands/mrelease.md +7 -0
- package/plugin/commands/mrepair.md +7 -0
- package/plugin/commands/mstatus.md +7 -0
- package/plugin/commands/mtest.md +7 -0
- package/plugin/commands/mtestlocal.md +7 -0
- package/plugin/commands/mtestprep.md +7 -0
- package/plugin/commands/mupgrade.md +7 -0
- package/plugin/scripts/ensure-electron-app.sh +35 -8
- package/plugin/skills/_aliases.json +18 -0
- package/plugin/skills/_shared/dev-server-readiness.md +231 -0
- package/plugin/skills/_shared/failure-mode-handling.md +244 -0
- package/plugin/skills/_shared/post-merge-cleanup.md +10 -0
- package/plugin/skills/_shared/pr-followup-helpers.md +150 -0
- package/plugin/skills/_shared/rebase-before-e2e.md +15 -0
- package/plugin/skills/_shared/telemetry-emit.md +15 -0
- package/plugin/skills/_shared/use-worktrees.md +53 -0
- package/plugin/skills/do/build.md +51 -0
- package/plugin/skills/do/e2e-acceptance.md +64 -19
- package/plugin/skills/do/impact-analysis.md +47 -7
- package/plugin/skills/do/open-prs.md +72 -74
- package/plugin/skills/do/pre-flight.md +21 -14
- package/plugin/skills/do/requirements.md +2 -2
- package/plugin/skills/do/unit-tests.md +2 -2
- package/plugin/skills/m/SKILL.md +8 -0
- package/plugin/skills/mdo/SKILL.md +8 -0
- package/plugin/skills/mfeedback/SKILL.md +8 -0
- package/plugin/skills/mimport/SKILL.md +8 -0
- package/plugin/skills/mpr/SKILL.md +8 -0
- package/plugin/skills/mprefs/SKILL.md +8 -0
- package/plugin/skills/mregen/SKILL.md +8 -0
- package/plugin/skills/mrelease/SKILL.md +8 -0
- package/plugin/skills/mrepair/SKILL.md +8 -0
- package/plugin/skills/mstatus/SKILL.md +8 -0
- package/plugin/skills/mtest/SKILL.md +8 -0
- package/plugin/skills/mtestlocal/SKILL.md +8 -0
- package/plugin/skills/mtestprep/SKILL.md +8 -0
- package/plugin/skills/muggle/SKILL.md +9 -6
- package/plugin/skills/muggle-do/SKILL.md +36 -61
- package/plugin/skills/muggle-do-task/SKILL.md +134 -0
- package/plugin/skills/muggle-feedback/SKILL.md +39 -0
- package/plugin/skills/muggle-feedback/ops/delete.md +49 -0
- package/plugin/skills/muggle-feedback/ops/list.md +65 -0
- package/plugin/skills/muggle-feedback/ops/submit.md +130 -0
- package/plugin/skills/muggle-pr-followup/SKILL.md +59 -0
- package/plugin/skills/muggle-pr-followup/contract.md +191 -0
- package/plugin/skills/muggle-pr-visual-walkthrough/SKILL.md +68 -43
- package/plugin/skills/muggle-pr-visual-walkthrough/e2e-report-assembly.md +86 -0
- package/plugin/skills/muggle-preferences/SKILL.md +16 -108
- package/plugin/skills/muggle-preferences/ops/change-one.md +10 -0
- package/plugin/skills/muggle-preferences/ops/configure.md +49 -0
- package/plugin/skills/muggle-preferences/ops/list.md +9 -0
- package/plugin/skills/muggle-preferences/ops/reset.md +6 -0
- package/plugin/skills/muggle-preferences/ops/set.md +10 -0
- package/plugin/skills/muggle-preferences/preference-gates/README.md +1 -1
- package/plugin/skills/muggle-preferences/preference-gates/autoCleanup.md +11 -0
- package/plugin/skills/muggle-preferences/preference-gates/autoCreatePR.md +13 -0
- package/plugin/skills/muggle-preferences/preference-gates/autoDetectChanges.md +3 -3
- package/plugin/skills/muggle-preferences/preference-gates/autoE2ETest.md +11 -0
- package/plugin/skills/muggle-preferences/preference-gates/autoLogin.md +1 -1
- package/plugin/skills/muggle-preferences/preference-gates/autoPublishLocalResults.md +2 -2
- package/plugin/skills/muggle-preferences/preference-gates/autoRebase.md +11 -0
- package/plugin/skills/muggle-preferences/preference-gates/autoSelectLocalHost.md +19 -0
- package/plugin/skills/muggle-preferences/preference-gates/autoSelectProject.md +1 -2
- package/plugin/skills/muggle-preferences/preference-gates/autoUseWorktree.md +11 -0
- package/plugin/skills/muggle-preferences/preference-gates/checkForUpdates.md +4 -4
- package/plugin/skills/muggle-preferences/preference-gates/defaultExecutionMode.md +1 -1
- package/plugin/skills/muggle-preferences/preference-gates/openTestResultsAfterRun.md +1 -1
- package/plugin/skills/muggle-preferences/preference-gates/postPRVisualWalkthrough.md +8 -25
- package/plugin/skills/muggle-preferences/preference-gates/showElectronBrowser.md +1 -1
- package/plugin/skills/muggle-preferences/preference-gates/suggestRelatedTestCases.md +4 -4
- package/plugin/skills/muggle-preferences/preference-gates/suggestRelatedUseCases.md +4 -4
- package/plugin/skills/muggle-repair/SKILL.md +4 -2
- package/plugin/skills/muggle-status/SKILL.md +8 -5
- package/plugin/skills/muggle-test/SKILL.md +110 -86
- package/plugin/skills/muggle-test-feature-local/SKILL.md +83 -62
- package/plugin/skills/muggle-test-import/SKILL.md +28 -23
- package/plugin/skills/muggle-test-prepare/SKILL.md +79 -18
- package/plugin/skills/muggle-test-regenerate-missing/SKILL.md +34 -18
- package/plugin/skills/muggle-test-regenerate-missing/evals/evals.json +9 -9
- package/plugin/skills/muggle-upgrade/SKILL.md +4 -2
- package/plugin/skills/muggle-works-npm-release/SKILL.md +6 -4
- package/plugin/skills/mupgrade/SKILL.md +8 -0
- package/scripts/postinstall.mjs +11 -1
- package/dist/plugin/skills/do/validate-code.md +0 -38
- package/plugin/skills/do/validate-code.md +0 -38
|
@@ -11,6 +11,7 @@ import { fileURLToPath } from 'url';
|
|
|
11
11
|
import { spawn, exec } from 'child_process';
|
|
12
12
|
import axios, { AxiosError } from 'axios';
|
|
13
13
|
import * as fs7 from 'fs/promises';
|
|
14
|
+
import AppInsights from 'applicationinsights';
|
|
14
15
|
import { z } from 'zod';
|
|
15
16
|
|
|
16
17
|
var __defProp = Object.defineProperty;
|
|
@@ -84,6 +85,7 @@ __export(src_exports, {
|
|
|
84
85
|
resetConfig: () => resetConfig,
|
|
85
86
|
resetLogger: () => resetLogger,
|
|
86
87
|
resetPreference: () => resetPreference,
|
|
88
|
+
resolveElectronAppPathOrNull: () => resolveElectronAppPathOrNull,
|
|
87
89
|
resolvePreferences: () => resolvePreferences,
|
|
88
90
|
saveApiKey: () => saveApiKey,
|
|
89
91
|
saveApiKeyData: () => saveApiKeyData,
|
|
@@ -395,7 +397,6 @@ function buildLocalQaConfig() {
|
|
|
395
397
|
tempDir: path2.join(dataDir, "temp"),
|
|
396
398
|
apiKeyFilePath: path2.join(dataDir, API_KEY_FILE),
|
|
397
399
|
oauthSessionFilePath: path2.join(dataDir, "oauth-session.json"),
|
|
398
|
-
electronAppPath: resolveElectronAppPathOrNull(),
|
|
399
400
|
webServicePath: resolveWebServicePath(),
|
|
400
401
|
webServicePidFile: path2.join(dataDir, "web-service.pid"),
|
|
401
402
|
auth0: {
|
|
@@ -527,9 +528,9 @@ function resetLogger() {
|
|
|
527
528
|
// packages/mcps/src/shared/checksum.ts
|
|
528
529
|
var logger = getLogger();
|
|
529
530
|
function getPlatformKey() {
|
|
530
|
-
const
|
|
531
|
+
const os5 = platform();
|
|
531
532
|
const arch2 = process.arch;
|
|
532
|
-
switch (
|
|
533
|
+
switch (os5) {
|
|
533
534
|
case "darwin":
|
|
534
535
|
return arch2 === "arm64" ? "darwin-arm64" : "darwin-x64";
|
|
535
536
|
case "win32":
|
|
@@ -537,7 +538,7 @@ function getPlatformKey() {
|
|
|
537
538
|
case "linux":
|
|
538
539
|
return "linux-x64";
|
|
539
540
|
default:
|
|
540
|
-
throw new Error(`Unsupported platform: ${
|
|
541
|
+
throw new Error(`Unsupported platform: ${os5}`);
|
|
541
542
|
}
|
|
542
543
|
}
|
|
543
544
|
async function calculateFileChecksum(filePath) {
|
|
@@ -2101,29 +2102,28 @@ async function writeExecutionLogs(params) {
|
|
|
2101
2102
|
});
|
|
2102
2103
|
}
|
|
2103
2104
|
function getElectronAppPathOrThrow() {
|
|
2104
|
-
const
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
const version = getElectronAppVersion();
|
|
2108
|
-
const versionDir = getElectronAppDir(version);
|
|
2109
|
-
const envPath = process.env.ELECTRON_APP_PATH;
|
|
2110
|
-
const errorLines = [
|
|
2111
|
-
"Electron app binary not found.",
|
|
2112
|
-
"",
|
|
2113
|
-
` Expected version: ${version}`,
|
|
2114
|
-
` Checked directory: ${versionDir}`
|
|
2115
|
-
];
|
|
2116
|
-
if (envPath) {
|
|
2117
|
-
errorLines.push(` ELECTRON_APP_PATH: ${envPath} (not found or invalid)`);
|
|
2118
|
-
} else {
|
|
2119
|
-
errorLines.push(" ELECTRON_APP_PATH: (not set)");
|
|
2120
|
-
}
|
|
2121
|
-
errorLines.push("");
|
|
2122
|
-
errorLines.push("To fix this, run: muggle setup");
|
|
2123
|
-
errorLines.push("Or set ELECTRON_APP_PATH to the path of the MuggleAI executable.");
|
|
2124
|
-
throw new Error(errorLines.join("\n"));
|
|
2105
|
+
const electronAppPath = resolveElectronAppPathOrNull();
|
|
2106
|
+
if (electronAppPath && electronAppPath.trim() !== "") {
|
|
2107
|
+
return electronAppPath;
|
|
2125
2108
|
}
|
|
2126
|
-
|
|
2109
|
+
const version = getElectronAppVersion();
|
|
2110
|
+
const versionDir = getElectronAppDir(version);
|
|
2111
|
+
const envPath = process.env.ELECTRON_APP_PATH;
|
|
2112
|
+
const errorLines = [
|
|
2113
|
+
"Electron app binary not found.",
|
|
2114
|
+
"",
|
|
2115
|
+
` Expected version: ${version}`,
|
|
2116
|
+
` Checked directory: ${versionDir}`
|
|
2117
|
+
];
|
|
2118
|
+
if (envPath) {
|
|
2119
|
+
errorLines.push(` ELECTRON_APP_PATH: ${envPath} (not found or invalid)`);
|
|
2120
|
+
} else {
|
|
2121
|
+
errorLines.push(" ELECTRON_APP_PATH: (not set)");
|
|
2122
|
+
}
|
|
2123
|
+
errorLines.push("");
|
|
2124
|
+
errorLines.push("To fix this, run: muggle setup");
|
|
2125
|
+
errorLines.push("Or set ELECTRON_APP_PATH to the path of the MuggleAI executable.");
|
|
2126
|
+
throw new Error(errorLines.join("\n"));
|
|
2127
2127
|
}
|
|
2128
2128
|
function getRequiredStringField(params) {
|
|
2129
2129
|
const value = params.source[params.fieldName];
|
|
@@ -2223,7 +2223,7 @@ function buildReplayActionScript(params) {
|
|
|
2223
2223
|
async function executeElectronAppAsync(params) {
|
|
2224
2224
|
const mode = params.runType === "generation" ? "explore" : "engine";
|
|
2225
2225
|
const electronAppPath = getElectronAppPathOrThrow();
|
|
2226
|
-
const spawnArgs = [mode, params.scriptFilePath, "", params.authFilePath];
|
|
2226
|
+
const spawnArgs = [mode, params.scriptFilePath, params.mutationsFilePath ?? "", params.authFilePath];
|
|
2227
2227
|
if (params.showUi) {
|
|
2228
2228
|
spawnArgs.push("--show-ui");
|
|
2229
2229
|
}
|
|
@@ -2371,11 +2371,16 @@ async function executeTestGeneration(params) {
|
|
|
2371
2371
|
filename: `${runId}_auth.json`,
|
|
2372
2372
|
data: authContent
|
|
2373
2373
|
});
|
|
2374
|
+
const mutationsFilePath = params.mutations && params.mutations.length > 0 ? await writeTempFile({
|
|
2375
|
+
filename: `${runId}_mutations.json`,
|
|
2376
|
+
data: params.mutations
|
|
2377
|
+
}) : void 0;
|
|
2374
2378
|
try {
|
|
2375
2379
|
const executionResult = await executeElectronAppAsync({
|
|
2376
2380
|
runId,
|
|
2377
2381
|
runType: "generation",
|
|
2378
2382
|
scriptFilePath: inputFilePath,
|
|
2383
|
+
mutationsFilePath,
|
|
2379
2384
|
authFilePath,
|
|
2380
2385
|
timeoutMs,
|
|
2381
2386
|
showUi: params.showUi,
|
|
@@ -2518,11 +2523,16 @@ async function executeReplay(params) {
|
|
|
2518
2523
|
filename: `${runId}_auth.json`,
|
|
2519
2524
|
data: authContent
|
|
2520
2525
|
});
|
|
2526
|
+
const mutationsFilePath = params.mutations && params.mutations.length > 0 ? await writeTempFile({
|
|
2527
|
+
filename: `${runId}_mutations.json`,
|
|
2528
|
+
data: params.mutations
|
|
2529
|
+
}) : void 0;
|
|
2521
2530
|
try {
|
|
2522
2531
|
const executionResult = await executeElectronAppAsync({
|
|
2523
2532
|
runId,
|
|
2524
2533
|
runType: "replay",
|
|
2525
2534
|
scriptFilePath: inputFilePath,
|
|
2535
|
+
mutationsFilePath,
|
|
2526
2536
|
authFilePath,
|
|
2527
2537
|
timeoutMs,
|
|
2528
2538
|
showUi: params.showUi,
|
|
@@ -2991,6 +3001,268 @@ __export(e2e_exports, {
|
|
|
2991
3001
|
executeQaTool: () => executeQaTool,
|
|
2992
3002
|
getQaToolByName: () => getQaToolByName
|
|
2993
3003
|
});
|
|
3004
|
+
|
|
3005
|
+
var ENV_CONNECTION_STRING = "APPLICATIONINSIGHTS_CONNECTION_STRING";
|
|
3006
|
+
var ENV_VITE_CONNECTION_STRING = "VITE_APPLICATIONINSIGHTS_CONNECTION_STRING";
|
|
3007
|
+
var ENV_TELEMETRY_DISABLED = "MUGGLE_TELEMETRY_DISABLED";
|
|
3008
|
+
|
|
3009
|
+
var DATA_DIR_NAME2 = ".muggle-ai";
|
|
3010
|
+
var INSTALL_ID_FILENAME = "install-id.json";
|
|
3011
|
+
var PREFS_FILENAME = "preferences.json";
|
|
3012
|
+
var OAUTH_SESSION_FILENAME = "oauth-session.json";
|
|
3013
|
+
var RELEASE_MANIFEST_FILENAME = "release-manifest.json";
|
|
3014
|
+
function getDataDir3() {
|
|
3015
|
+
return path2.join(os3.homedir(), DATA_DIR_NAME2);
|
|
3016
|
+
}
|
|
3017
|
+
|
|
3018
|
+
var cachedInstallId;
|
|
3019
|
+
function installIdFilePath() {
|
|
3020
|
+
return join(getDataDir3(), INSTALL_ID_FILENAME);
|
|
3021
|
+
}
|
|
3022
|
+
function generateAndPersist(filePath) {
|
|
3023
|
+
const installId = randomUUID();
|
|
3024
|
+
const contents = { installId };
|
|
3025
|
+
mkdirSync(dirname(filePath), { recursive: true });
|
|
3026
|
+
writeFileSync(filePath, JSON.stringify(contents, null, 2) + "\n", "utf8");
|
|
3027
|
+
return installId;
|
|
3028
|
+
}
|
|
3029
|
+
function isValid(value) {
|
|
3030
|
+
return typeof value === "object" && value !== null && typeof value.installId === "string" && value.installId.length > 0;
|
|
3031
|
+
}
|
|
3032
|
+
function getInstallId() {
|
|
3033
|
+
if (cachedInstallId !== void 0)
|
|
3034
|
+
return cachedInstallId;
|
|
3035
|
+
const filePath = installIdFilePath();
|
|
3036
|
+
if (!existsSync(filePath)) {
|
|
3037
|
+
cachedInstallId = generateAndPersist(filePath);
|
|
3038
|
+
return cachedInstallId;
|
|
3039
|
+
}
|
|
3040
|
+
try {
|
|
3041
|
+
const raw = readFileSync(filePath, "utf8");
|
|
3042
|
+
const parsed = JSON.parse(raw);
|
|
3043
|
+
if (isValid(parsed)) {
|
|
3044
|
+
cachedInstallId = parsed.installId;
|
|
3045
|
+
return cachedInstallId;
|
|
3046
|
+
}
|
|
3047
|
+
cachedInstallId = generateAndPersist(filePath);
|
|
3048
|
+
return cachedInstallId;
|
|
3049
|
+
} catch {
|
|
3050
|
+
cachedInstallId = generateAndPersist(filePath);
|
|
3051
|
+
return cachedInstallId;
|
|
3052
|
+
}
|
|
3053
|
+
}
|
|
3054
|
+
|
|
3055
|
+
var DEV_MANIFEST2 = {
|
|
3056
|
+
release: "dev",
|
|
3057
|
+
buildId: "dev",
|
|
3058
|
+
commitSha: "dev",
|
|
3059
|
+
buildTime: "1970-01-01T00:00:00Z",
|
|
3060
|
+
serviceName: "muggle-ai-telemetry"
|
|
3061
|
+
};
|
|
3062
|
+
|
|
3063
|
+
var MANIFEST_PATH2 = (() => {
|
|
3064
|
+
try {
|
|
3065
|
+
return join(dirname(fileURLToPath(import.meta.url)), RELEASE_MANIFEST_FILENAME);
|
|
3066
|
+
} catch {
|
|
3067
|
+
return RELEASE_MANIFEST_FILENAME;
|
|
3068
|
+
}
|
|
3069
|
+
})();
|
|
3070
|
+
var cachedManifest2;
|
|
3071
|
+
function isValid2(value) {
|
|
3072
|
+
if (typeof value !== "object" || value === null)
|
|
3073
|
+
return false;
|
|
3074
|
+
const m = value;
|
|
3075
|
+
return typeof m.release === "string" && typeof m.buildId === "string" && typeof m.commitSha === "string" && typeof m.buildTime === "string" && typeof m.serviceName === "string";
|
|
3076
|
+
}
|
|
3077
|
+
function readReleaseManifest2() {
|
|
3078
|
+
if (cachedManifest2 !== void 0)
|
|
3079
|
+
return cachedManifest2;
|
|
3080
|
+
const path15 = MANIFEST_PATH2;
|
|
3081
|
+
try {
|
|
3082
|
+
const raw = readFileSync(path15, "utf8");
|
|
3083
|
+
const parsed = JSON.parse(raw);
|
|
3084
|
+
cachedManifest2 = isValid2(parsed) ? parsed : DEV_MANIFEST2;
|
|
3085
|
+
return cachedManifest2;
|
|
3086
|
+
} catch (err) {
|
|
3087
|
+
const code = err.code;
|
|
3088
|
+
if (code !== "ENOENT") {
|
|
3089
|
+
console.warn("release-manifest: unexpected read error, using DEV fallback", {
|
|
3090
|
+
error: err.message
|
|
3091
|
+
});
|
|
3092
|
+
}
|
|
3093
|
+
cachedManifest2 = DEV_MANIFEST2;
|
|
3094
|
+
return cachedManifest2;
|
|
3095
|
+
}
|
|
3096
|
+
}
|
|
3097
|
+
function readUserId() {
|
|
3098
|
+
const filePath = join(getDataDir3(), OAUTH_SESSION_FILENAME);
|
|
3099
|
+
if (!existsSync(filePath))
|
|
3100
|
+
return void 0;
|
|
3101
|
+
try {
|
|
3102
|
+
const raw = readFileSync(filePath, "utf8");
|
|
3103
|
+
const parsed = JSON.parse(raw);
|
|
3104
|
+
if (typeof parsed.userId === "string" && parsed.userId.length > 0) {
|
|
3105
|
+
return parsed.userId;
|
|
3106
|
+
}
|
|
3107
|
+
return void 0;
|
|
3108
|
+
} catch {
|
|
3109
|
+
return void 0;
|
|
3110
|
+
}
|
|
3111
|
+
}
|
|
3112
|
+
|
|
3113
|
+
var state = null;
|
|
3114
|
+
function resolveConnectionString(explicit) {
|
|
3115
|
+
if (explicit && explicit.length > 0)
|
|
3116
|
+
return explicit;
|
|
3117
|
+
return process.env[ENV_CONNECTION_STRING] ?? process.env[ENV_VITE_CONNECTION_STRING] ?? void 0;
|
|
3118
|
+
}
|
|
3119
|
+
function buildCommonProperties(serviceName, surface) {
|
|
3120
|
+
const manifest = readReleaseManifest2();
|
|
3121
|
+
const props = {
|
|
3122
|
+
source: "client",
|
|
3123
|
+
serviceName,
|
|
3124
|
+
surface,
|
|
3125
|
+
release: manifest.release,
|
|
3126
|
+
buildId: manifest.buildId,
|
|
3127
|
+
commitSha: manifest.commitSha,
|
|
3128
|
+
buildTime: manifest.buildTime,
|
|
3129
|
+
installId: getInstallId(),
|
|
3130
|
+
nodeVersion: process.version,
|
|
3131
|
+
platform: process.platform
|
|
3132
|
+
};
|
|
3133
|
+
const userId = readUserId();
|
|
3134
|
+
if (userId !== void 0)
|
|
3135
|
+
props.userId = userId;
|
|
3136
|
+
return props;
|
|
3137
|
+
}
|
|
3138
|
+
function initTelemetry(options) {
|
|
3139
|
+
if (state !== null && state.initialized)
|
|
3140
|
+
return;
|
|
3141
|
+
const connectionString = resolveConnectionString(options.connectionString);
|
|
3142
|
+
if (!connectionString) {
|
|
3143
|
+
state = {
|
|
3144
|
+
client: null,
|
|
3145
|
+
serviceName: options.serviceName,
|
|
3146
|
+
surface: options.surface,
|
|
3147
|
+
initialized: true
|
|
3148
|
+
};
|
|
3149
|
+
return;
|
|
3150
|
+
}
|
|
3151
|
+
try {
|
|
3152
|
+
AppInsights.setup(connectionString).setUseDiskRetryCaching(true).setDistributedTracingMode(AppInsights.DistributedTracingModes.AI_AND_W3C).setAutoCollectRequests(false).setAutoCollectPerformance(false, false).setAutoCollectExceptions(true).setAutoCollectDependencies(false).setAutoCollectConsole(false).setSendLiveMetrics(false);
|
|
3153
|
+
const client = AppInsights.defaultClient;
|
|
3154
|
+
const manifest = readReleaseManifest2();
|
|
3155
|
+
client.context.tags[client.context.keys.cloudRole] = options.serviceName;
|
|
3156
|
+
client.context.tags[client.context.keys.applicationVersion] = manifest.release;
|
|
3157
|
+
client.commonProperties = {
|
|
3158
|
+
...client.commonProperties,
|
|
3159
|
+
...buildCommonProperties(options.serviceName, options.surface)
|
|
3160
|
+
};
|
|
3161
|
+
AppInsights.start();
|
|
3162
|
+
state = {
|
|
3163
|
+
client,
|
|
3164
|
+
serviceName: options.serviceName,
|
|
3165
|
+
surface: options.surface,
|
|
3166
|
+
initialized: true
|
|
3167
|
+
};
|
|
3168
|
+
} catch (err) {
|
|
3169
|
+
console.warn("[muggle-telemetry] init failed; events will be dropped", {
|
|
3170
|
+
error: err.message
|
|
3171
|
+
});
|
|
3172
|
+
state = {
|
|
3173
|
+
client: null,
|
|
3174
|
+
serviceName: options.serviceName,
|
|
3175
|
+
surface: options.surface,
|
|
3176
|
+
initialized: true
|
|
3177
|
+
};
|
|
3178
|
+
}
|
|
3179
|
+
}
|
|
3180
|
+
function getClient() {
|
|
3181
|
+
return state?.client ?? null;
|
|
3182
|
+
}
|
|
3183
|
+
function prefsFilePath() {
|
|
3184
|
+
return join(getDataDir3(), PREFS_FILENAME);
|
|
3185
|
+
}
|
|
3186
|
+
function readPreferences() {
|
|
3187
|
+
const filePath = prefsFilePath();
|
|
3188
|
+
if (!existsSync(filePath))
|
|
3189
|
+
return {};
|
|
3190
|
+
try {
|
|
3191
|
+
const raw = readFileSync(filePath, "utf8");
|
|
3192
|
+
const parsed = JSON.parse(raw);
|
|
3193
|
+
if (typeof parsed === "object" && parsed !== null) {
|
|
3194
|
+
return parsed;
|
|
3195
|
+
}
|
|
3196
|
+
return {};
|
|
3197
|
+
} catch {
|
|
3198
|
+
return {};
|
|
3199
|
+
}
|
|
3200
|
+
}
|
|
3201
|
+
|
|
3202
|
+
function isTelemetryEnabled() {
|
|
3203
|
+
if (process.env[ENV_TELEMETRY_DISABLED] === "1")
|
|
3204
|
+
return false;
|
|
3205
|
+
const prefs = readPreferences();
|
|
3206
|
+
if (prefs.telemetryEnabled === false)
|
|
3207
|
+
return false;
|
|
3208
|
+
return true;
|
|
3209
|
+
}
|
|
3210
|
+
|
|
3211
|
+
function track(event) {
|
|
3212
|
+
if (!isTelemetryEnabled())
|
|
3213
|
+
return;
|
|
3214
|
+
const client = getClient();
|
|
3215
|
+
if (!client)
|
|
3216
|
+
return;
|
|
3217
|
+
try {
|
|
3218
|
+
client.trackEvent({
|
|
3219
|
+
name: event.name,
|
|
3220
|
+
properties: event.props
|
|
3221
|
+
});
|
|
3222
|
+
} catch {
|
|
3223
|
+
}
|
|
3224
|
+
}
|
|
3225
|
+
|
|
3226
|
+
var Trigger;
|
|
3227
|
+
(function(Trigger2) {
|
|
3228
|
+
Trigger2["UserSlash"] = "user-slash";
|
|
3229
|
+
Trigger2["ClaudeProactive"] = "claude-proactive";
|
|
3230
|
+
Trigger2["NestedSkill"] = "nested-skill";
|
|
3231
|
+
})(Trigger || (Trigger = {}));
|
|
3232
|
+
var Outcome;
|
|
3233
|
+
(function(Outcome2) {
|
|
3234
|
+
Outcome2["Success"] = "success";
|
|
3235
|
+
Outcome2["Error"] = "error";
|
|
3236
|
+
Outcome2["Cancelled"] = "cancelled";
|
|
3237
|
+
})(Outcome || (Outcome = {}));
|
|
3238
|
+
var ToolSurface;
|
|
3239
|
+
(function(ToolSurface2) {
|
|
3240
|
+
ToolSurface2["Local"] = "local";
|
|
3241
|
+
ToolSurface2["Remote"] = "remote";
|
|
3242
|
+
})(ToolSurface || (ToolSurface = {}));
|
|
3243
|
+
var Surface;
|
|
3244
|
+
(function(Surface2) {
|
|
3245
|
+
Surface2["McpLocal"] = "mcp-local";
|
|
3246
|
+
Surface2["McpRemote"] = "mcp-remote";
|
|
3247
|
+
Surface2["Skill"] = "skill";
|
|
3248
|
+
Surface2["Electron"] = "electron";
|
|
3249
|
+
})(Surface || (Surface = {}));
|
|
3250
|
+
var ServiceName;
|
|
3251
|
+
(function(ServiceName2) {
|
|
3252
|
+
ServiceName2["MuggleMcp"] = "muggle-mcp";
|
|
3253
|
+
ServiceName2["MuggleElectron"] = "muggle-electron";
|
|
3254
|
+
ServiceName2["MuggleSkill"] = "muggle-skill";
|
|
3255
|
+
})(ServiceName || (ServiceName = {}));
|
|
3256
|
+
var EventName;
|
|
3257
|
+
(function(EventName2) {
|
|
3258
|
+
EventName2["SkillInvoked"] = "skill.invoked";
|
|
3259
|
+
EventName2["SkillCompleted"] = "skill.completed";
|
|
3260
|
+
EventName2["McpToolInvoked"] = "mcp.tool.invoked";
|
|
3261
|
+
EventName2["McpToolCompleted"] = "mcp.tool.completed";
|
|
3262
|
+
EventName2["SystemStartup"] = "system.startup";
|
|
3263
|
+
EventName2["SystemOptOutChanged"] = "system.opt_out_changed";
|
|
3264
|
+
EventName2["SystemDisclosureShown"] = "system.disclosure_shown";
|
|
3265
|
+
})(EventName || (EventName = {}));
|
|
2994
3266
|
var MuggleEntityIdSchema = z.string().uuid();
|
|
2995
3267
|
var LocalExecutionContextInputSchema = z.object({
|
|
2996
3268
|
originalUrl: z.string().url().describe("Original local URL used during local execution (typically localhost)"),
|
|
@@ -3134,6 +3406,21 @@ var UseCaseUpdateFromPromptInputSchema = z.object({
|
|
|
3134
3406
|
useCaseId: IdSchema.describe("Use case ID (UUID) to update"),
|
|
3135
3407
|
instruction: z.string().min(1).describe("Natural language instruction to regenerate the use case from")
|
|
3136
3408
|
});
|
|
3409
|
+
var UseCaseUpdateInputSchema = z.object({
|
|
3410
|
+
useCaseId: IdSchema.describe("Use case ID (UUID) to update"),
|
|
3411
|
+
title: z.string().min(1).optional().describe("Updated use case title"),
|
|
3412
|
+
description: z.string().min(1).optional().describe("Updated description"),
|
|
3413
|
+
userStory: z.string().min(1).optional().describe("Updated one-line user story"),
|
|
3414
|
+
url: z.string().url().optional().describe("Updated target URL"),
|
|
3415
|
+
useCaseBreakdown: z.array(z.object({
|
|
3416
|
+
requirement: z.string().min(1).describe("One requirement of the use case"),
|
|
3417
|
+
acceptanceCriteria: z.string().min(1).describe("Concrete, measurable acceptance criteria for the requirement")
|
|
3418
|
+
})).optional().describe("Updated main/alternative/error flows as requirement + acceptance criteria pairs"),
|
|
3419
|
+
status: z.enum(["DRAFT", "IN_REVIEW", "APPROVED", "IMPLEMENTED", "ARCHIVED"]).optional().describe("Updated status"),
|
|
3420
|
+
priority: z.enum(["LOW", "MEDIUM", "HIGH", "CRITICAL"]).optional().describe("Updated priority"),
|
|
3421
|
+
source: z.enum(["PRD_FILE", "SITEMAP", "CRAWLER", "PROMPT", "MANUAL"]).optional().describe("Updated source"),
|
|
3422
|
+
category: z.string().optional().describe("Updated category")
|
|
3423
|
+
});
|
|
3137
3424
|
var UseCaseCreateInputSchema = z.object({
|
|
3138
3425
|
projectId: IdSchema.describe("Project ID (UUID) the use case belongs to"),
|
|
3139
3426
|
title: z.string().min(1).describe("Use case title"),
|
|
@@ -3217,6 +3504,20 @@ var TestCaseCreateInputSchema = z.object({
|
|
|
3217
3504
|
category: z.string().optional().describe("Test case category"),
|
|
3218
3505
|
automated: z.boolean().optional().describe("Whether this test case is automated (default: true)")
|
|
3219
3506
|
});
|
|
3507
|
+
var TestCaseUpdateInputSchema = z.object({
|
|
3508
|
+
testCaseId: IdSchema.describe("Test case ID (UUID) to update"),
|
|
3509
|
+
title: z.string().min(1).optional().describe("Updated test case title"),
|
|
3510
|
+
description: z.string().min(1).optional().describe("Updated description"),
|
|
3511
|
+
goal: z.string().min(1).optional().describe("Updated goal"),
|
|
3512
|
+
precondition: z.string().optional().describe("Updated precondition"),
|
|
3513
|
+
expectedResult: z.string().min(1).optional().describe("Updated expected result"),
|
|
3514
|
+
url: z.string().url().optional().describe("Updated target URL"),
|
|
3515
|
+
status: z.enum(["DRAFT", "ACTIVE", "DEPRECATED", "ARCHIVED"]).optional().describe("Updated status"),
|
|
3516
|
+
priority: z.enum(["HIGH", "MEDIUM", "LOW"]).optional().describe("Updated priority"),
|
|
3517
|
+
tags: z.array(z.string()).optional().describe("Updated tags"),
|
|
3518
|
+
category: z.string().optional().describe("Updated category"),
|
|
3519
|
+
automated: z.boolean().optional().describe("Whether this test case is automated")
|
|
3520
|
+
});
|
|
3220
3521
|
var TestScriptListInputSchema = z.object({
|
|
3221
3522
|
projectId: IdSchema.describe("Project ID (UUID) to list test scripts for"),
|
|
3222
3523
|
testCaseId: IdSchema.optional().describe("Optional test case ID (UUID) to filter scripts by")
|
|
@@ -3367,6 +3668,34 @@ var ApiKeyGetInputSchema = z.object({
|
|
|
3367
3668
|
var ApiKeyRevokeInputSchema = z.object({
|
|
3368
3669
|
apiKeyId: ApiKeyRecordIdSchema.describe("ID of the API key record to revoke")
|
|
3369
3670
|
});
|
|
3671
|
+
var UserFeedbackTargetTypeSchema = z.enum(["actionScript", "step"]);
|
|
3672
|
+
var UserFeedbackTargetSchema = z.object({
|
|
3673
|
+
targetType: UserFeedbackTargetTypeSchema.describe("Target entity kind: 'actionScript' for whole-script feedback, 'step' for a specific step"),
|
|
3674
|
+
targetId: z.string().min(1).describe("Target identifier. For 'actionScript' use the actionScriptId; for 'step' use `${actionScriptId}:${stepIndex}` (0-based stepIndex)")
|
|
3675
|
+
});
|
|
3676
|
+
var UserFeedbackCreateInputSchema = z.object({
|
|
3677
|
+
projectId: IdSchema.describe("Project ID (UUID) the feedback belongs to"),
|
|
3678
|
+
target: UserFeedbackTargetSchema.describe("What entity this feedback is about (action script or a specific step)"),
|
|
3679
|
+
feedbackText: z.string().min(1).describe("Free-form paragraph describing what went wrong and what the expected behavior should be")
|
|
3680
|
+
});
|
|
3681
|
+
var UserFeedbackListInputSchema = z.object({
|
|
3682
|
+
projectId: IdSchema.describe("Project ID (UUID) to list feedback for. Always required \u2014 defines the auth boundary."),
|
|
3683
|
+
actionScriptId: IdSchema.optional().describe("Narrow to feedback whose target resolves to this action script. Mutually exclusive with the other narrowing filters."),
|
|
3684
|
+
testScriptId: IdSchema.optional().describe("Narrow to feedback on the action script of this test script. Mutually exclusive with the other narrowing filters."),
|
|
3685
|
+
testCaseId: IdSchema.optional().describe("Narrow to feedback on any action script ever generated for this test case. Mutually exclusive with the other narrowing filters."),
|
|
3686
|
+
useCaseId: IdSchema.optional().describe("Narrow to feedback on any action script ever generated under this use case. Mutually exclusive with the other narrowing filters."),
|
|
3687
|
+
limit: z.number().int().positive().max(1e3).optional().describe("Max entries to return (default 100)"),
|
|
3688
|
+
offset: z.number().int().min(0).optional().describe("Offset for pagination (default 0)")
|
|
3689
|
+
}).refine(
|
|
3690
|
+
(data) => {
|
|
3691
|
+
const set = [data.actionScriptId, data.testScriptId, data.testCaseId, data.useCaseId].filter(Boolean);
|
|
3692
|
+
return set.length <= 1;
|
|
3693
|
+
},
|
|
3694
|
+
{ message: "At most one of actionScriptId / testScriptId / testCaseId / useCaseId may be set" }
|
|
3695
|
+
);
|
|
3696
|
+
var UserFeedbackDeleteInputSchema = z.object({
|
|
3697
|
+
feedbackId: IdSchema.describe("User feedback ID (UUID) to soft-delete")
|
|
3698
|
+
});
|
|
3370
3699
|
var AuthLoginInputSchema = z.object({
|
|
3371
3700
|
waitForCompletion: z.boolean().optional().describe("Whether to wait for browser login completion before returning. Default: true"),
|
|
3372
3701
|
timeoutMs: z.number().int().positive().min(1e3).max(9e5).optional().describe("Maximum time to wait for login completion in milliseconds. Default: 120000"),
|
|
@@ -3419,40 +3748,40 @@ function detectMcpHost(env = process.env) {
|
|
|
3419
3748
|
}
|
|
3420
3749
|
return "unknown";
|
|
3421
3750
|
}
|
|
3422
|
-
var
|
|
3423
|
-
var
|
|
3424
|
-
function
|
|
3425
|
-
return join(getDataDir(),
|
|
3751
|
+
var INSTALL_ID_FILENAME2 = "install-id.json";
|
|
3752
|
+
var cachedInstallId2;
|
|
3753
|
+
function installIdFilePath2() {
|
|
3754
|
+
return join(getDataDir(), INSTALL_ID_FILENAME2);
|
|
3426
3755
|
}
|
|
3427
|
-
function
|
|
3756
|
+
function generateAndPersist2(filePath) {
|
|
3428
3757
|
const installId = randomUUID();
|
|
3429
3758
|
const contents = { installId };
|
|
3430
3759
|
mkdirSync(dirname(filePath), { recursive: true });
|
|
3431
3760
|
writeFileSync(filePath, JSON.stringify(contents, null, 2) + "\n", "utf8");
|
|
3432
3761
|
return installId;
|
|
3433
3762
|
}
|
|
3434
|
-
function
|
|
3763
|
+
function isValid3(value) {
|
|
3435
3764
|
return typeof value === "object" && value !== null && typeof value.installId === "string" && value.installId.length > 0;
|
|
3436
3765
|
}
|
|
3437
|
-
function
|
|
3438
|
-
if (
|
|
3439
|
-
const filePath =
|
|
3766
|
+
function getInstallId2() {
|
|
3767
|
+
if (cachedInstallId2 !== void 0) return cachedInstallId2;
|
|
3768
|
+
const filePath = installIdFilePath2();
|
|
3440
3769
|
if (!existsSync(filePath)) {
|
|
3441
|
-
|
|
3442
|
-
return
|
|
3770
|
+
cachedInstallId2 = generateAndPersist2(filePath);
|
|
3771
|
+
return cachedInstallId2;
|
|
3443
3772
|
}
|
|
3444
3773
|
try {
|
|
3445
3774
|
const raw = readFileSync(filePath, "utf8");
|
|
3446
3775
|
const parsed = JSON.parse(raw);
|
|
3447
|
-
if (
|
|
3448
|
-
|
|
3449
|
-
return
|
|
3776
|
+
if (isValid3(parsed)) {
|
|
3777
|
+
cachedInstallId2 = parsed.installId;
|
|
3778
|
+
return cachedInstallId2;
|
|
3450
3779
|
}
|
|
3451
|
-
|
|
3452
|
-
return
|
|
3780
|
+
cachedInstallId2 = generateAndPersist2(filePath);
|
|
3781
|
+
return cachedInstallId2;
|
|
3453
3782
|
} catch {
|
|
3454
|
-
|
|
3455
|
-
return
|
|
3783
|
+
cachedInstallId2 = generateAndPersist2(filePath);
|
|
3784
|
+
return cachedInstallId2;
|
|
3456
3785
|
}
|
|
3457
3786
|
}
|
|
3458
3787
|
|
|
@@ -3482,17 +3811,17 @@ var PromptServiceClient = class {
|
|
|
3482
3811
|
* @param path - Path to validate.
|
|
3483
3812
|
* @throws GatewayError if path is not allowed.
|
|
3484
3813
|
*/
|
|
3485
|
-
validatePath(
|
|
3486
|
-
const isAllowed = ALLOWED_UPSTREAM_PREFIXES.some((prefix) =>
|
|
3814
|
+
validatePath(path15) {
|
|
3815
|
+
const isAllowed = ALLOWED_UPSTREAM_PREFIXES.some((prefix) => path15.startsWith(prefix));
|
|
3487
3816
|
if (!isAllowed) {
|
|
3488
3817
|
const logger6 = getLogger();
|
|
3489
3818
|
logger6.error("Path not in allowlist", {
|
|
3490
|
-
path:
|
|
3819
|
+
path: path15,
|
|
3491
3820
|
allowedPrefixes: ALLOWED_UPSTREAM_PREFIXES
|
|
3492
3821
|
});
|
|
3493
3822
|
throw new GatewayError({
|
|
3494
3823
|
code: "FORBIDDEN" /* FORBIDDEN */,
|
|
3495
|
-
message: `Path '${
|
|
3824
|
+
message: `Path '${path15}' is not allowed`
|
|
3496
3825
|
});
|
|
3497
3826
|
}
|
|
3498
3827
|
}
|
|
@@ -3504,7 +3833,7 @@ var PromptServiceClient = class {
|
|
|
3504
3833
|
*/
|
|
3505
3834
|
buildHeaders(credentials, correlationId) {
|
|
3506
3835
|
const manifest = readReleaseManifest();
|
|
3507
|
-
const installId =
|
|
3836
|
+
const installId = getInstallId2();
|
|
3508
3837
|
const host = detectMcpHost();
|
|
3509
3838
|
const headers = {
|
|
3510
3839
|
"X-Correlation-Id": correlationId,
|
|
@@ -3890,6 +4219,29 @@ var useCaseTools = [
|
|
|
3890
4219
|
};
|
|
3891
4220
|
}
|
|
3892
4221
|
},
|
|
4222
|
+
{
|
|
4223
|
+
name: "muggle-remote-use-case-update",
|
|
4224
|
+
description: "Directly update an existing use case's fields without invoking the LLM. Pass only the fields you want to change \u2014 others are left untouched. Use this for cheap, deterministic edits (rename, flip status DRAFT\u2192APPROVED, change priority, edit acceptance criteria). For LLM regeneration from a new instruction, use muggle-remote-use-case-update-from-prompt instead. Note: changing title, description, or url triggers background regeneration of dependent test cases on the server.",
|
|
4225
|
+
inputSchema: UseCaseUpdateInputSchema,
|
|
4226
|
+
mapToUpstream: (input) => {
|
|
4227
|
+
const data = input;
|
|
4228
|
+
const body = { id: data.useCaseId };
|
|
4229
|
+
if (data.title !== void 0) body.title = data.title;
|
|
4230
|
+
if (data.description !== void 0) body.description = data.description;
|
|
4231
|
+
if (data.userStory !== void 0) body.userStory = data.userStory;
|
|
4232
|
+
if (data.url !== void 0) body.url = data.url;
|
|
4233
|
+
if (data.useCaseBreakdown !== void 0) body.useCaseBreakdown = data.useCaseBreakdown;
|
|
4234
|
+
if (data.status !== void 0) body.status = data.status;
|
|
4235
|
+
if (data.priority !== void 0) body.priority = data.priority;
|
|
4236
|
+
if (data.source !== void 0) body.source = data.source;
|
|
4237
|
+
if (data.category !== void 0) body.category = data.category;
|
|
4238
|
+
return {
|
|
4239
|
+
method: "PUT",
|
|
4240
|
+
path: `${MUGGLE_TEST_PREFIX}/use-cases/${data.useCaseId}`,
|
|
4241
|
+
body
|
|
4242
|
+
};
|
|
4243
|
+
}
|
|
4244
|
+
},
|
|
3893
4245
|
{
|
|
3894
4246
|
name: "muggle-remote-use-case-create",
|
|
3895
4247
|
description: "Create a single use case from a fully-specified payload. Use this to persist use cases returned by muggle-remote-use-case-bulk-preview-submit \u2014 no LLM is invoked.",
|
|
@@ -4012,6 +4364,31 @@ var testCaseTools = [
|
|
|
4012
4364
|
};
|
|
4013
4365
|
}
|
|
4014
4366
|
},
|
|
4367
|
+
{
|
|
4368
|
+
name: "muggle-remote-test-case-update",
|
|
4369
|
+
description: "Directly update an existing test case's fields. Pass only the fields you want to change \u2014 others are left untouched. Use this for cheap, deterministic edits (rename, change status/priority, fix expected result, add tags). Does not touch the associated test script \u2014 script regeneration is a separate workflow (muggle-remote-workflow-start-test-script-generation).",
|
|
4370
|
+
inputSchema: TestCaseUpdateInputSchema,
|
|
4371
|
+
mapToUpstream: (input) => {
|
|
4372
|
+
const data = input;
|
|
4373
|
+
const body = { id: data.testCaseId };
|
|
4374
|
+
if (data.title !== void 0) body.title = data.title;
|
|
4375
|
+
if (data.description !== void 0) body.description = data.description;
|
|
4376
|
+
if (data.goal !== void 0) body.goal = data.goal;
|
|
4377
|
+
if (data.precondition !== void 0) body.precondition = data.precondition;
|
|
4378
|
+
if (data.expectedResult !== void 0) body.expectedResult = data.expectedResult;
|
|
4379
|
+
if (data.url !== void 0) body.url = data.url;
|
|
4380
|
+
if (data.status !== void 0) body.status = data.status;
|
|
4381
|
+
if (data.priority !== void 0) body.priority = data.priority;
|
|
4382
|
+
if (data.tags !== void 0) body.tags = data.tags;
|
|
4383
|
+
if (data.category !== void 0) body.category = data.category;
|
|
4384
|
+
if (data.automated !== void 0) body.automated = data.automated;
|
|
4385
|
+
return {
|
|
4386
|
+
method: "PUT",
|
|
4387
|
+
path: `${MUGGLE_TEST_PREFIX}/test-cases/${data.testCaseId}`,
|
|
4388
|
+
body
|
|
4389
|
+
};
|
|
4390
|
+
}
|
|
4391
|
+
},
|
|
4015
4392
|
{
|
|
4016
4393
|
name: "muggle-remote-test-case-bulk-preview-submit",
|
|
4017
4394
|
description: "Submit an async bulk-preview job that uses the OpenAI Batch API to generate test cases for a single use case from many prompts at ~50% of normal LLM cost. Returns a job ID immediately; poll with muggle-remote-bulk-preview-job-get until the job reaches a terminal status, then persist each successful result via muggle-remote-test-case-create. Note: one input prompt may fan out to 1\u20135 test cases.",
|
|
@@ -4980,6 +5357,58 @@ var apiKeyTools = [
|
|
|
4980
5357
|
}
|
|
4981
5358
|
}
|
|
4982
5359
|
];
|
|
5360
|
+
var userFeedbackTools = [
|
|
5361
|
+
{
|
|
5362
|
+
name: "muggle-remote-user-feedback-create",
|
|
5363
|
+
description: "Submit user feedback on a generated action script \u2014 either the whole script (targetType='actionScript', targetId=actionScriptId) or a specific step (targetType='step', targetId=`${actionScriptId}:${stepIndex}` with 0-based stepIndex). Persists the feedback and triggers an async feedback-analysis workflow that may regenerate the script. The response includes the saved feedback and, when the analysis workflow was started, a feedbackAnalysisWorkflowRuntimeId for polling.",
|
|
5364
|
+
inputSchema: UserFeedbackCreateInputSchema,
|
|
5365
|
+
mapToUpstream: (input) => {
|
|
5366
|
+
const data = input;
|
|
5367
|
+
return {
|
|
5368
|
+
method: "POST",
|
|
5369
|
+
path: `${MUGGLE_TEST_PREFIX}/user-feedback`,
|
|
5370
|
+
body: {
|
|
5371
|
+
projectId: data.projectId,
|
|
5372
|
+
target: data.target,
|
|
5373
|
+
feedbackText: data.feedbackText
|
|
5374
|
+
}
|
|
5375
|
+
};
|
|
5376
|
+
}
|
|
5377
|
+
},
|
|
5378
|
+
{
|
|
5379
|
+
name: "muggle-remote-user-feedback-list",
|
|
5380
|
+
description: "List active user feedback entries for a project. Optionally narrow by exactly one of actionScriptId / testScriptId / testCaseId / useCaseId \u2014 the typical query is 'show me feedback on this test case (or test script, or use case).' Supports limit/offset pagination. Response: { feedback: IUserFeedback[], total: number, hasMore: boolean }.",
|
|
5381
|
+
inputSchema: UserFeedbackListInputSchema,
|
|
5382
|
+
mapToUpstream: (input) => {
|
|
5383
|
+
const data = input;
|
|
5384
|
+
return {
|
|
5385
|
+
method: "GET",
|
|
5386
|
+
path: `${MUGGLE_TEST_PREFIX}/user-feedback`,
|
|
5387
|
+
queryParams: {
|
|
5388
|
+
projectId: data.projectId,
|
|
5389
|
+
actionScriptId: data.actionScriptId,
|
|
5390
|
+
testScriptId: data.testScriptId,
|
|
5391
|
+
testCaseId: data.testCaseId,
|
|
5392
|
+
useCaseId: data.useCaseId,
|
|
5393
|
+
limit: data.limit,
|
|
5394
|
+
offset: data.offset
|
|
5395
|
+
}
|
|
5396
|
+
};
|
|
5397
|
+
}
|
|
5398
|
+
},
|
|
5399
|
+
{
|
|
5400
|
+
name: "muggle-remote-user-feedback-delete",
|
|
5401
|
+
description: "Soft-delete a user feedback entry by ID. Returns 204 on success.",
|
|
5402
|
+
inputSchema: UserFeedbackDeleteInputSchema,
|
|
5403
|
+
mapToUpstream: (input) => {
|
|
5404
|
+
const data = input;
|
|
5405
|
+
return {
|
|
5406
|
+
method: "DELETE",
|
|
5407
|
+
path: `${MUGGLE_TEST_PREFIX}/user-feedback/${data.feedbackId}`
|
|
5408
|
+
};
|
|
5409
|
+
}
|
|
5410
|
+
}
|
|
5411
|
+
];
|
|
4983
5412
|
var authTools = [
|
|
4984
5413
|
{
|
|
4985
5414
|
name: "muggle-remote-auth-status",
|
|
@@ -5116,6 +5545,7 @@ var allQaToolDefinitions = [
|
|
|
5116
5545
|
...walletTools,
|
|
5117
5546
|
...recommendationTools,
|
|
5118
5547
|
...apiKeyTools,
|
|
5548
|
+
...userFeedbackTools,
|
|
5119
5549
|
...authTools
|
|
5120
5550
|
];
|
|
5121
5551
|
function getQaToolByName(name) {
|
|
@@ -5133,6 +5563,13 @@ async function executeQaTool(toolName, input, correlationId) {
|
|
|
5133
5563
|
isError: true
|
|
5134
5564
|
};
|
|
5135
5565
|
}
|
|
5566
|
+
const startTime = Date.now();
|
|
5567
|
+
safeTrack({
|
|
5568
|
+
name: EventName.McpToolInvoked,
|
|
5569
|
+
props: { toolName, toolSurface: ToolSurface.Remote, correlationId }
|
|
5570
|
+
});
|
|
5571
|
+
let outcome = Outcome.Success;
|
|
5572
|
+
let errorCode;
|
|
5136
5573
|
try {
|
|
5137
5574
|
const validatedInput = tool.inputSchema.parse(input);
|
|
5138
5575
|
if (tool.localHandler) {
|
|
@@ -5165,7 +5602,9 @@ async function executeQaTool(toolName, input, correlationId) {
|
|
|
5165
5602
|
throw error;
|
|
5166
5603
|
}
|
|
5167
5604
|
} catch (error) {
|
|
5605
|
+
outcome = Outcome.Error;
|
|
5168
5606
|
if (error instanceof GatewayError) {
|
|
5607
|
+
errorCode = error.code;
|
|
5169
5608
|
logger6.warn("Tool call failed with gateway error", {
|
|
5170
5609
|
tool: toolName,
|
|
5171
5610
|
code: error.code,
|
|
@@ -5176,12 +5615,31 @@ async function executeQaTool(toolName, input, correlationId) {
|
|
|
5176
5615
|
isError: true
|
|
5177
5616
|
};
|
|
5178
5617
|
}
|
|
5618
|
+
errorCode = error instanceof Error ? error.name : "UnknownError";
|
|
5179
5619
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
5180
5620
|
logger6.error("Tool call failed", { tool: toolName, error: errorMessage });
|
|
5181
5621
|
return {
|
|
5182
5622
|
content: JSON.stringify({ error: "INTERNAL_ERROR", message: errorMessage }),
|
|
5183
5623
|
isError: true
|
|
5184
5624
|
};
|
|
5625
|
+
} finally {
|
|
5626
|
+
safeTrack({
|
|
5627
|
+
name: EventName.McpToolCompleted,
|
|
5628
|
+
props: {
|
|
5629
|
+
toolName,
|
|
5630
|
+
toolSurface: ToolSurface.Remote,
|
|
5631
|
+
correlationId,
|
|
5632
|
+
durationMs: Date.now() - startTime,
|
|
5633
|
+
outcome,
|
|
5634
|
+
...errorCode !== void 0 ? { errorCode } : {}
|
|
5635
|
+
}
|
|
5636
|
+
});
|
|
5637
|
+
}
|
|
5638
|
+
}
|
|
5639
|
+
function safeTrack(event) {
|
|
5640
|
+
try {
|
|
5641
|
+
track(event);
|
|
5642
|
+
} catch {
|
|
5185
5643
|
}
|
|
5186
5644
|
}
|
|
5187
5645
|
|
|
@@ -5240,7 +5698,9 @@ var ExecuteTestGenerationInputSchema = z.object({
|
|
|
5240
5698
|
/** Show the electron-app UI during execution. Default: visible window. Pass false to run headless. */
|
|
5241
5699
|
showUi: z.boolean().optional().describe("Show the electron-app UI during generation. Defaults to visible; pass false to run headless."),
|
|
5242
5700
|
/** Clear all session storage (cookies, localStorage, etc.) before execution. Use for test cases that require a clean browser state, such as registration, login, or cookie consent flows. */
|
|
5243
|
-
freshSession: z.boolean().optional().describe("Clear all session storage (cookies, localStorage, etc.) before execution. Use for test cases that require a clean browser state \u2014 e.g. registration, login, or cookie consent flows. Default: false.")
|
|
5701
|
+
freshSession: z.boolean().optional().describe("Clear all session storage (cookies, localStorage, etc.) before execution. Use for test cases that require a clean browser state \u2014 e.g. registration, login, or cookie consent flows. Default: false."),
|
|
5702
|
+
/** Mutation parameters providing variable context for this generation run — a string[] where each element is a plain-English instruction or a local file path for uploads (e.g. "Attach the image at C:\\Users\\user\\photo.jpg"). Matches the electron-app's string[] mutation file format. */
|
|
5703
|
+
mutations: z.array(z.string()).optional().describe(`Mutation parameters: string[] where each element is a plain-English instruction or a local file path (e.g. ["The post content should be 'Hello'", "Attach the image at C:\\\\Users\\\\user\\\\photo.jpg"]).`)
|
|
5244
5704
|
});
|
|
5245
5705
|
var ExecuteReplayInputSchema = z.object({
|
|
5246
5706
|
/** Test script metadata from muggle-remote-test-script-get. */
|
|
@@ -5254,7 +5714,9 @@ var ExecuteReplayInputSchema = z.object({
|
|
|
5254
5714
|
/** Show the electron-app UI during execution. Default: visible window. Pass false to run headless. */
|
|
5255
5715
|
showUi: z.boolean().optional().describe("Show the electron-app UI during replay. Defaults to visible; pass false to run headless."),
|
|
5256
5716
|
/** Clear all session storage (cookies, localStorage, etc.) before execution. Use for test cases that require a clean browser state, such as registration, login, or cookie consent flows. */
|
|
5257
|
-
freshSession: z.boolean().optional().describe("Clear all session storage (cookies, localStorage, etc.) before execution. Use for test cases that require a clean browser state \u2014 e.g. registration, login, or cookie consent flows. Default: false.")
|
|
5717
|
+
freshSession: z.boolean().optional().describe("Clear all session storage (cookies, localStorage, etc.) before execution. Use for test cases that require a clean browser state \u2014 e.g. registration, login, or cookie consent flows. Default: false."),
|
|
5718
|
+
/** Mutation parameters passed to the LLM step predictor — a string[] where each element is an instruction describing what varies this run. Supports plain-English instructions (e.g. "The post content should be 'Hello world'") and local file paths for uploads (e.g. "Attach the image at C:\\Users\\user\\photo.jpg"). Matches the electron-app's string[] mutation file format. When provided, the electron app uses LLM-driven step prediction instead of deterministic replay. */
|
|
5719
|
+
mutations: z.array(z.string()).optional().describe(`Mutation parameters: string[] where each element is a plain-English instruction or a local file path (e.g. ["The post content should be 'Hello'", "Attach the image at C:\\\\Users\\\\user\\\\photo.jpg"]).`)
|
|
5258
5720
|
});
|
|
5259
5721
|
var CancelExecutionInputSchema = z.object({
|
|
5260
5722
|
runId: MuggleEntityIdSchema.describe("Run ID (UUID) to cancel")
|
|
@@ -5288,6 +5750,7 @@ var EmptyInputSchema2 = z.object({});
|
|
|
5288
5750
|
var PreferenceKey = /* @__PURE__ */ ((PreferenceKey2) => {
|
|
5289
5751
|
PreferenceKey2["AutoLogin"] = "autoLogin";
|
|
5290
5752
|
PreferenceKey2["AutoSelectProject"] = "autoSelectProject";
|
|
5753
|
+
PreferenceKey2["AutoSelectLocalHost"] = "autoSelectLocalHost";
|
|
5291
5754
|
PreferenceKey2["ShowElectronBrowser"] = "showElectronBrowser";
|
|
5292
5755
|
PreferenceKey2["OpenTestResultsAfterRun"] = "openTestResultsAfterRun";
|
|
5293
5756
|
PreferenceKey2["DefaultExecutionMode"] = "defaultExecutionMode";
|
|
@@ -5296,8 +5759,13 @@ var PreferenceKey = /* @__PURE__ */ ((PreferenceKey2) => {
|
|
|
5296
5759
|
PreferenceKey2["SuggestRelatedTestCases"] = "suggestRelatedTestCases";
|
|
5297
5760
|
PreferenceKey2["AutoDetectChanges"] = "autoDetectChanges";
|
|
5298
5761
|
PreferenceKey2["PostPRVisualWalkthrough"] = "postPRVisualWalkthrough";
|
|
5762
|
+
PreferenceKey2["AutoCreatePR"] = "autoCreatePR";
|
|
5299
5763
|
PreferenceKey2["CheckForUpdates"] = "checkForUpdates";
|
|
5300
5764
|
PreferenceKey2["VerboseOutput"] = "verboseOutput";
|
|
5765
|
+
PreferenceKey2["AutoUseWorktree"] = "autoUseWorktree";
|
|
5766
|
+
PreferenceKey2["AutoRebase"] = "autoRebase";
|
|
5767
|
+
PreferenceKey2["AutoCleanup"] = "autoCleanup";
|
|
5768
|
+
PreferenceKey2["AutoE2ETest"] = "autoE2ETest";
|
|
5301
5769
|
return PreferenceKey2;
|
|
5302
5770
|
})(PreferenceKey || {});
|
|
5303
5771
|
var PreferenceValue = /* @__PURE__ */ ((PreferenceValue2) => {
|
|
@@ -5316,6 +5784,7 @@ var PREFERENCES_VERSION = 1;
|
|
|
5316
5784
|
var DEFAULT_PREFERENCES = {
|
|
5317
5785
|
["autoLogin" /* AutoLogin */]: "ask" /* Ask */,
|
|
5318
5786
|
["autoSelectProject" /* AutoSelectProject */]: "ask" /* Ask */,
|
|
5787
|
+
["autoSelectLocalHost" /* AutoSelectLocalHost */]: "ask" /* Ask */,
|
|
5319
5788
|
["showElectronBrowser" /* ShowElectronBrowser */]: "ask" /* Ask */,
|
|
5320
5789
|
["openTestResultsAfterRun" /* OpenTestResultsAfterRun */]: "ask" /* Ask */,
|
|
5321
5790
|
["defaultExecutionMode" /* DefaultExecutionMode */]: "ask" /* Ask */,
|
|
@@ -5324,14 +5793,23 @@ var DEFAULT_PREFERENCES = {
|
|
|
5324
5793
|
["suggestRelatedTestCases" /* SuggestRelatedTestCases */]: "ask" /* Ask */,
|
|
5325
5794
|
["autoDetectChanges" /* AutoDetectChanges */]: "ask" /* Ask */,
|
|
5326
5795
|
["postPRVisualWalkthrough" /* PostPRVisualWalkthrough */]: "ask" /* Ask */,
|
|
5796
|
+
["autoCreatePR" /* AutoCreatePR */]: "ask" /* Ask */,
|
|
5327
5797
|
["checkForUpdates" /* CheckForUpdates */]: "ask" /* Ask */,
|
|
5328
|
-
["verboseOutput" /* VerboseOutput */]: "ask" /* Ask
|
|
5798
|
+
["verboseOutput" /* VerboseOutput */]: "ask" /* Ask */,
|
|
5799
|
+
["autoUseWorktree" /* AutoUseWorktree */]: "ask" /* Ask */,
|
|
5800
|
+
["autoRebase" /* AutoRebase */]: "ask" /* Ask */,
|
|
5801
|
+
["autoCleanup" /* AutoCleanup */]: "ask" /* Ask */,
|
|
5802
|
+
["autoE2ETest" /* AutoE2ETest */]: "always" /* Always */
|
|
5329
5803
|
};
|
|
5330
5804
|
var ALWAYS_ASK_NEVER = [
|
|
5331
5805
|
"always" /* Always */,
|
|
5332
5806
|
"ask" /* Ask */,
|
|
5333
5807
|
"never" /* Never */
|
|
5334
5808
|
];
|
|
5809
|
+
var ALWAYS_ASK = [
|
|
5810
|
+
"always" /* Always */,
|
|
5811
|
+
"ask" /* Ask */
|
|
5812
|
+
];
|
|
5335
5813
|
var LOCAL_REMOTE_ASK = [
|
|
5336
5814
|
"local" /* Local */,
|
|
5337
5815
|
"remote" /* Remote */,
|
|
@@ -5340,6 +5818,7 @@ var LOCAL_REMOTE_ASK = [
|
|
|
5340
5818
|
var PREFERENCE_ALLOWED_VALUES = {
|
|
5341
5819
|
["autoLogin" /* AutoLogin */]: ALWAYS_ASK_NEVER,
|
|
5342
5820
|
["autoSelectProject" /* AutoSelectProject */]: ALWAYS_ASK_NEVER,
|
|
5821
|
+
["autoSelectLocalHost" /* AutoSelectLocalHost */]: ALWAYS_ASK_NEVER,
|
|
5343
5822
|
["showElectronBrowser" /* ShowElectronBrowser */]: ALWAYS_ASK_NEVER,
|
|
5344
5823
|
["openTestResultsAfterRun" /* OpenTestResultsAfterRun */]: ALWAYS_ASK_NEVER,
|
|
5345
5824
|
["defaultExecutionMode" /* DefaultExecutionMode */]: LOCAL_REMOTE_ASK,
|
|
@@ -5348,27 +5827,35 @@ var PREFERENCE_ALLOWED_VALUES = {
|
|
|
5348
5827
|
["suggestRelatedTestCases" /* SuggestRelatedTestCases */]: ALWAYS_ASK_NEVER,
|
|
5349
5828
|
["autoDetectChanges" /* AutoDetectChanges */]: ALWAYS_ASK_NEVER,
|
|
5350
5829
|
["postPRVisualWalkthrough" /* PostPRVisualWalkthrough */]: ALWAYS_ASK_NEVER,
|
|
5830
|
+
["autoCreatePR" /* AutoCreatePR */]: ALWAYS_ASK_NEVER,
|
|
5351
5831
|
["checkForUpdates" /* CheckForUpdates */]: ALWAYS_ASK_NEVER,
|
|
5352
|
-
["verboseOutput" /* VerboseOutput */]: ALWAYS_ASK_NEVER
|
|
5832
|
+
["verboseOutput" /* VerboseOutput */]: ALWAYS_ASK_NEVER,
|
|
5833
|
+
["autoUseWorktree" /* AutoUseWorktree */]: ALWAYS_ASK_NEVER,
|
|
5834
|
+
["autoRebase" /* AutoRebase */]: ALWAYS_ASK_NEVER,
|
|
5835
|
+
["autoCleanup" /* AutoCleanup */]: ALWAYS_ASK_NEVER,
|
|
5836
|
+
["autoE2ETest" /* AutoE2ETest */]: ALWAYS_ASK
|
|
5353
5837
|
};
|
|
5354
5838
|
var PREFERENCES_SCHEMA = {
|
|
5355
5839
|
["autoLogin" /* AutoLogin */]: {
|
|
5356
5840
|
description: "When a tool requires auth and saved credentials exist, reuse them without prompting"
|
|
5357
5841
|
},
|
|
5358
5842
|
["autoSelectProject" /* AutoSelectProject */]: {
|
|
5359
|
-
description: "When a skill needs a Muggle project and one was used previously in this repo, reuse it without prompting"
|
|
5843
|
+
description: "When a skill needs a Muggle Test project and one was used previously in this repo, reuse it without prompting"
|
|
5844
|
+
},
|
|
5845
|
+
["autoSelectLocalHost" /* AutoSelectLocalHost */]: {
|
|
5846
|
+
description: "When running local tests, reuse the dev server URL from the previous run in this repo without prompting"
|
|
5360
5847
|
},
|
|
5361
5848
|
["showElectronBrowser" /* ShowElectronBrowser */]: {
|
|
5362
5849
|
description: "When running local E2E tests, show the Electron browser window"
|
|
5363
5850
|
},
|
|
5364
5851
|
["openTestResultsAfterRun" /* OpenTestResultsAfterRun */]: {
|
|
5365
|
-
description: "After a local E2E test run completes, open the per-run results page on Muggle dashboard"
|
|
5852
|
+
description: "After a local E2E test run completes, open the per-run results page on Muggle Test dashboard"
|
|
5366
5853
|
},
|
|
5367
5854
|
["defaultExecutionMode" /* DefaultExecutionMode */]: {
|
|
5368
5855
|
description: "When a skill supports both local and remote test execution, which to default to"
|
|
5369
5856
|
},
|
|
5370
5857
|
["autoPublishLocalResults" /* AutoPublishLocalResults */]: {
|
|
5371
|
-
description: "After a local E2E test run completes, upload results to Muggle cloud for team visibility"
|
|
5858
|
+
description: "After a local E2E test run completes, upload results to Muggle Test cloud for team visibility"
|
|
5372
5859
|
},
|
|
5373
5860
|
["suggestRelatedUseCases" /* SuggestRelatedUseCases */]: {
|
|
5374
5861
|
description: "After creating or running a use case, suggest related use cases to add"
|
|
@@ -5382,11 +5869,26 @@ var PREFERENCES_SCHEMA = {
|
|
|
5382
5869
|
["postPRVisualWalkthrough" /* PostPRVisualWalkthrough */]: {
|
|
5383
5870
|
description: "After test results are available, post visual walkthrough comment with screenshots to the PR"
|
|
5384
5871
|
},
|
|
5872
|
+
["autoCreatePR" /* AutoCreatePR */]: {
|
|
5873
|
+
description: "At the end of the muggle-do dev cycle (or when a test needs an open PR to post results to), push the branch and open a PR without prompting"
|
|
5874
|
+
},
|
|
5385
5875
|
["checkForUpdates" /* CheckForUpdates */]: {
|
|
5386
|
-
description: "At session start, check if a newer Muggle version is available and notify"
|
|
5876
|
+
description: "At session start, check if a newer Muggle Test version is available and notify"
|
|
5387
5877
|
},
|
|
5388
5878
|
["verboseOutput" /* VerboseOutput */]: {
|
|
5389
5879
|
description: "Show detailed progress logs during skill and tool execution"
|
|
5880
|
+
},
|
|
5881
|
+
["autoUseWorktree" /* AutoUseWorktree */]: {
|
|
5882
|
+
description: "When starting non-trivial development work, create a git worktree to isolate the change from the current checkout"
|
|
5883
|
+
},
|
|
5884
|
+
["autoRebase" /* AutoRebase */]: {
|
|
5885
|
+
description: "Before running dev servers or E2E tests on a branch behind origin, rebase onto the default branch first"
|
|
5886
|
+
},
|
|
5887
|
+
["autoCleanup" /* AutoCleanup */]: {
|
|
5888
|
+
description: "After a PR is merged, automatically run the cleanup sequence: remove worktree, delete branches, clear local artifacts, prune [gone] branches"
|
|
5889
|
+
},
|
|
5890
|
+
["autoE2ETest" /* AutoE2ETest */]: {
|
|
5891
|
+
description: "Run Stage 6 (E2E acceptance) at the end of every /muggle-do cycle (default always \u2014 running E2E is the point of muggle-do; never is not an option)"
|
|
5390
5892
|
}
|
|
5391
5893
|
};
|
|
5392
5894
|
|
|
@@ -5413,15 +5915,75 @@ var LastProjectGetInputSchema = z.object({
|
|
|
5413
5915
|
});
|
|
5414
5916
|
var LastProjectSetInputSchema = z.object({
|
|
5415
5917
|
cwd: z.string().describe("Project root directory to save the cached project to."),
|
|
5416
|
-
projectId: z.string().min(1).describe("Muggle project ID."),
|
|
5417
|
-
projectUrl: z.string().min(1).describe("Muggle project URL."),
|
|
5418
|
-
projectName: z.string().min(1).describe("Muggle project name.")
|
|
5918
|
+
projectId: z.string().min(1).describe("Muggle Test project ID."),
|
|
5919
|
+
projectUrl: z.string().min(1).describe("Muggle Test project URL."),
|
|
5920
|
+
projectName: z.string().min(1).describe("Muggle Test project name.")
|
|
5419
5921
|
});
|
|
5420
5922
|
var LastProjectClearInputSchema = z.object({
|
|
5421
5923
|
cwd: z.string().describe("Project root directory whose last-used project cache to remove.")
|
|
5422
5924
|
});
|
|
5423
|
-
|
|
5424
|
-
|
|
5925
|
+
var LastHostGetInputSchema = z.object({
|
|
5926
|
+
cwd: z.string().describe("Project root directory whose last-used host to return.")
|
|
5927
|
+
});
|
|
5928
|
+
var LastHostSetInputSchema = z.object({
|
|
5929
|
+
cwd: z.string().describe("Project root directory to save the cached host to."),
|
|
5930
|
+
host: z.string().min(1).describe("Local dev server URL (e.g. http://localhost:3000).")
|
|
5931
|
+
});
|
|
5932
|
+
var LastHostClearInputSchema = z.object({
|
|
5933
|
+
cwd: z.string().describe("Project root directory whose last-used host cache to remove.")
|
|
5934
|
+
});
|
|
5935
|
+
var SkillTelemetryEmitInputSchema = z.object({
|
|
5936
|
+
skillName: z.string().min(1).describe("Name of the skill being invoked, e.g. 'muggle-test'."),
|
|
5937
|
+
trigger: z.nativeEnum(Trigger).default(Trigger.UserSlash).describe("Why this skill ran. Defaults to 'user-slash' (user typed /skill-name).")
|
|
5938
|
+
});
|
|
5939
|
+
var FailureEventType = /* @__PURE__ */ ((FailureEventType2) => {
|
|
5940
|
+
FailureEventType2["PreExecutionClassification"] = "pre-execution-classification";
|
|
5941
|
+
FailureEventType2["ReplayFailureClassified"] = "replay-failure-classified";
|
|
5942
|
+
FailureEventType2["ReplayFailureResolved"] = "replay-failure-resolved";
|
|
5943
|
+
FailureEventType2["RegenFailureClassified"] = "regen-failure-classified";
|
|
5944
|
+
FailureEventType2["RegenFailureResolved"] = "regen-failure-resolved";
|
|
5945
|
+
return FailureEventType2;
|
|
5946
|
+
})(FailureEventType || {});
|
|
5947
|
+
var EventTelemetryEmitInputSchema = z.object({
|
|
5948
|
+
eventType: z.nativeEnum(FailureEventType).describe(
|
|
5949
|
+
"Which decision point this event records. Five values cover the AI's pre-execution replay-vs-regen choice and the four post-failure classify\u2192resolve pairs."
|
|
5950
|
+
),
|
|
5951
|
+
skillName: z.string().min(1).describe("Skill that emitted this event (e.g. 'muggle-test', 'muggle-test-feature-local')."),
|
|
5952
|
+
aiClassification: z.string().optional().describe(
|
|
5953
|
+
"What the AI classified the situation as. pre-execution: 'replay' or 'regen'. replay-failure: 'infra' | 'stale-script' | 'product-defect'. regen-failure: 'transient' | 'infra' | 'agent-course' | 'product-uxux'."
|
|
5954
|
+
),
|
|
5955
|
+
aiSuggestion: z.string().optional().describe(
|
|
5956
|
+
"What the AI suggested the user do. Examples: 'regenerate', 'report-bug', 'muggle-feedback', 'retry', 'wait-and-share'."
|
|
5957
|
+
),
|
|
5958
|
+
userAction: z.string().optional().describe(
|
|
5959
|
+
"What the user actually picked (only set on *-resolved events). Compare against aiSuggestion to measure classification accuracy."
|
|
5960
|
+
),
|
|
5961
|
+
runId: z.string().optional().describe("Anchor: local run ID for the affected execution."),
|
|
5962
|
+
testCaseId: z.string().optional().describe("Anchor: cloud test case ID."),
|
|
5963
|
+
projectId: z.string().optional().describe("Anchor: cloud project ID."),
|
|
5964
|
+
signals: z.array(z.string()).optional().describe(
|
|
5965
|
+
"Signals that drove the classification, e.g. ['element-not-found', 'selector-timeout', 'electron-exit-26', 'goal-not-achievable']. Used to refine the rules later."
|
|
5966
|
+
),
|
|
5967
|
+
metadata: z.record(z.string(), z.unknown()).optional().describe("Free-form additional context (e.g. error excerpt, last step name).")
|
|
5968
|
+
});
|
|
5969
|
+
var TELEMETRY_DIR_NAME = "telemetry";
|
|
5970
|
+
var FAILURE_EVENTS_FILE_NAME = "failure-events.jsonl";
|
|
5971
|
+
function appendFailureEvent(record) {
|
|
5972
|
+
try {
|
|
5973
|
+
const dir = path2.join(getDataDir(), TELEMETRY_DIR_NAME);
|
|
5974
|
+
fs5.mkdirSync(dir, { recursive: true });
|
|
5975
|
+
const filePath = path2.join(dir, FAILURE_EVENTS_FILE_NAME);
|
|
5976
|
+
const full = { ts: (/* @__PURE__ */ new Date()).toISOString(), ...record };
|
|
5977
|
+
fs5.appendFileSync(filePath, `${JSON.stringify(full)}
|
|
5978
|
+
`, "utf-8");
|
|
5979
|
+
} catch (error) {
|
|
5980
|
+
getLogger().warn("Failed to append failure event", {
|
|
5981
|
+
error: error instanceof Error ? error.message : String(error)
|
|
5982
|
+
});
|
|
5983
|
+
}
|
|
5984
|
+
}
|
|
5985
|
+
function isFirstRun(dataDirOverride2) {
|
|
5986
|
+
const filePath = path2.join(dataDirOverride2 ?? getDataDir(), PREFERENCES_FILE_NAME);
|
|
5425
5987
|
return !fs5.existsSync(filePath);
|
|
5426
5988
|
}
|
|
5427
5989
|
function readPreferencesFile(filePath) {
|
|
@@ -5439,8 +6001,8 @@ function readPreferencesFile(filePath) {
|
|
|
5439
6001
|
return {};
|
|
5440
6002
|
}
|
|
5441
6003
|
}
|
|
5442
|
-
function readGlobalPreferences(
|
|
5443
|
-
const filePath = path2.join(
|
|
6004
|
+
function readGlobalPreferences(dataDirOverride2) {
|
|
6005
|
+
const filePath = path2.join(dataDirOverride2 ?? getDataDir(), PREFERENCES_FILE_NAME);
|
|
5444
6006
|
const partial = readPreferencesFile(filePath);
|
|
5445
6007
|
return { ...DEFAULT_PREFERENCES, ...partial };
|
|
5446
6008
|
}
|
|
@@ -5448,16 +6010,16 @@ function readProjectPreferences(cwd) {
|
|
|
5448
6010
|
const filePath = path2.join(cwd, PREFERENCES_PROJECT_DIR_NAME, PREFERENCES_FILE_NAME);
|
|
5449
6011
|
return readPreferencesFile(filePath);
|
|
5450
6012
|
}
|
|
5451
|
-
function resolvePreferences(
|
|
5452
|
-
const global = readGlobalPreferences(
|
|
6013
|
+
function resolvePreferences(dataDirOverride2, cwd) {
|
|
6014
|
+
const global = readGlobalPreferences(dataDirOverride2);
|
|
5453
6015
|
if (!cwd) {
|
|
5454
6016
|
return global;
|
|
5455
6017
|
}
|
|
5456
6018
|
const project = readProjectPreferences(cwd);
|
|
5457
6019
|
return { ...global, ...project };
|
|
5458
6020
|
}
|
|
5459
|
-
function writePreferences(prefs, scope,
|
|
5460
|
-
const dir = scope === "project" && cwd ? path2.join(cwd, PREFERENCES_PROJECT_DIR_NAME) :
|
|
6021
|
+
function writePreferences(prefs, scope, dataDirOverride2, cwd) {
|
|
6022
|
+
const dir = scope === "project" && cwd ? path2.join(cwd, PREFERENCES_PROJECT_DIR_NAME) : dataDirOverride2 ?? getDataDir();
|
|
5461
6023
|
fs5.mkdirSync(dir, { recursive: true });
|
|
5462
6024
|
const filePath = path2.join(dir, PREFERENCES_FILE_NAME);
|
|
5463
6025
|
const existing = readPreferencesFile(filePath);
|
|
@@ -5469,8 +6031,8 @@ function writePreferences(prefs, scope, dataDirOverride, cwd) {
|
|
|
5469
6031
|
fs5.writeFileSync(filePath, `${JSON.stringify(file, null, 2)}
|
|
5470
6032
|
`, "utf-8");
|
|
5471
6033
|
}
|
|
5472
|
-
function resetPreference(key, scope,
|
|
5473
|
-
const dir = scope === "project" && cwd ? path2.join(cwd, PREFERENCES_PROJECT_DIR_NAME) :
|
|
6034
|
+
function resetPreference(key, scope, dataDirOverride2, cwd) {
|
|
6035
|
+
const dir = scope === "project" && cwd ? path2.join(cwd, PREFERENCES_PROJECT_DIR_NAME) : dataDirOverride2 ?? getDataDir();
|
|
5474
6036
|
const filePath = path2.join(dir, PREFERENCES_FILE_NAME);
|
|
5475
6037
|
if (!fs5.existsSync(filePath)) {
|
|
5476
6038
|
return;
|
|
@@ -5534,6 +6096,42 @@ function clearLastProject(cwd) {
|
|
|
5534
6096
|
fs5.unlinkSync(filePath);
|
|
5535
6097
|
}
|
|
5536
6098
|
}
|
|
6099
|
+
var LAST_HOST_FILE_NAME = "last-host.json";
|
|
6100
|
+
var LAST_HOST_DIR_NAME = ".muggle-ai";
|
|
6101
|
+
var LAST_HOST_VERSION = 1;
|
|
6102
|
+
function readLastHost(cwd) {
|
|
6103
|
+
const filePath = path2.join(cwd, LAST_HOST_DIR_NAME, LAST_HOST_FILE_NAME);
|
|
6104
|
+
try {
|
|
6105
|
+
if (!fs5.existsSync(filePath)) {
|
|
6106
|
+
return null;
|
|
6107
|
+
}
|
|
6108
|
+
const raw = JSON.parse(fs5.readFileSync(filePath, "utf-8"));
|
|
6109
|
+
return raw.lastHost ?? null;
|
|
6110
|
+
} catch (error) {
|
|
6111
|
+
getLogger().warn("Failed to read last-host file", {
|
|
6112
|
+
path: filePath,
|
|
6113
|
+
error: error instanceof Error ? error.message : String(error)
|
|
6114
|
+
});
|
|
6115
|
+
return null;
|
|
6116
|
+
}
|
|
6117
|
+
}
|
|
6118
|
+
function writeLastHost(cwd, host) {
|
|
6119
|
+
const dir = path2.join(cwd, LAST_HOST_DIR_NAME);
|
|
6120
|
+
fs5.mkdirSync(dir, { recursive: true });
|
|
6121
|
+
const filePath = path2.join(dir, LAST_HOST_FILE_NAME);
|
|
6122
|
+
const file = {
|
|
6123
|
+
version: LAST_HOST_VERSION,
|
|
6124
|
+
lastHost: { host, savedAt: (/* @__PURE__ */ new Date()).toISOString() }
|
|
6125
|
+
};
|
|
6126
|
+
fs5.writeFileSync(filePath, `${JSON.stringify(file, null, 2)}
|
|
6127
|
+
`, "utf-8");
|
|
6128
|
+
}
|
|
6129
|
+
function clearLastHost(cwd) {
|
|
6130
|
+
const filePath = path2.join(cwd, LAST_HOST_DIR_NAME, LAST_HOST_FILE_NAME);
|
|
6131
|
+
if (fs5.existsSync(filePath)) {
|
|
6132
|
+
fs5.unlinkSync(filePath);
|
|
6133
|
+
}
|
|
6134
|
+
}
|
|
5537
6135
|
|
|
5538
6136
|
// packages/mcps/src/mcp/tools/local/tool-registry.ts
|
|
5539
6137
|
function createChildLogger2(correlationId) {
|
|
@@ -5757,6 +6355,7 @@ var executeTestGenerationTool = {
|
|
|
5757
6355
|
const result = await executeTestGeneration({
|
|
5758
6356
|
testCase: input.testCase,
|
|
5759
6357
|
localUrl: input.localUrl,
|
|
6358
|
+
mutations: input.mutations,
|
|
5760
6359
|
timeoutMs: input.timeoutMs,
|
|
5761
6360
|
showUi,
|
|
5762
6361
|
freshSession: input.freshSession
|
|
@@ -5797,6 +6396,7 @@ var executeReplayTool = {
|
|
|
5797
6396
|
testScript: input.testScript,
|
|
5798
6397
|
actionScript: input.actionScript,
|
|
5799
6398
|
localUrl: input.localUrl,
|
|
6399
|
+
mutations: input.mutations,
|
|
5800
6400
|
timeoutMs: input.timeoutMs,
|
|
5801
6401
|
showUi,
|
|
5802
6402
|
freshSession: input.freshSession
|
|
@@ -5990,22 +6590,15 @@ var preferencesSetTool = {
|
|
|
5990
6590
|
void 0,
|
|
5991
6591
|
input.cwd
|
|
5992
6592
|
);
|
|
5993
|
-
|
|
5994
|
-
|
|
5995
|
-
|
|
5996
|
-
|
|
5997
|
-
"",
|
|
5998
|
-
`Preferences file: ~/.muggle-ai/${PREFERENCES_FILE_NAME}`,
|
|
5999
|
-
"",
|
|
6000
|
-
"Current resolved preferences:",
|
|
6001
|
-
`\`${oneLiner}\``
|
|
6002
|
-
].join("\n");
|
|
6003
|
-
return { content, isError: false };
|
|
6593
|
+
return {
|
|
6594
|
+
content: `**${input.key}** set to **${input.value}** (${input.scope}).`,
|
|
6595
|
+
isError: false
|
|
6596
|
+
};
|
|
6004
6597
|
}
|
|
6005
6598
|
};
|
|
6006
6599
|
var lastProjectGetTool = {
|
|
6007
6600
|
name: "muggle-local-last-project-get",
|
|
6008
|
-
description: "Get the cached last-used Muggle project for a repo (read from <cwd>/.muggle-ai/last-project.json). Returns the project ID, URL, name, and saved-at timestamp, or null if no cache exists. Skills consult this when 'autoSelectProject = always' to silently reuse the project the user picked previously, instead of presenting the project picker every time.",
|
|
6601
|
+
description: "Get the cached last-used Muggle Test project for a repo (read from <cwd>/.muggle-ai/last-project.json). Returns the project ID, URL, name, and saved-at timestamp, or null if no cache exists. Skills consult this when 'autoSelectProject = always' to silently reuse the project the user picked previously, instead of presenting the project picker every time.",
|
|
6009
6602
|
inputSchema: LastProjectGetInputSchema,
|
|
6010
6603
|
execute: async (ctx) => {
|
|
6011
6604
|
const logger6 = createChildLogger2(ctx.correlationId);
|
|
@@ -6035,7 +6628,7 @@ var lastProjectGetTool = {
|
|
|
6035
6628
|
};
|
|
6036
6629
|
var lastProjectSetTool = {
|
|
6037
6630
|
name: "muggle-local-last-project-set",
|
|
6038
|
-
description: "Save the user's selected Muggle project as the cached last-used project for this repo. Writes to <cwd>/.muggle-ai/last-project.json. Subsequent skill invocations honor 'autoSelectProject = always' by silently reusing this entry \u2014 no project picker shown. Always pair this call with 'muggle-local-preferences-set autoSelectProject=always' when the user chose 'Yes, save it'.",
|
|
6631
|
+
description: "Save the user's selected Muggle Test project as the cached last-used project for this repo. Writes to <cwd>/.muggle-ai/last-project.json. Subsequent skill invocations honor 'autoSelectProject = always' by silently reusing this entry \u2014 no project picker shown. Always pair this call with 'muggle-local-preferences-set autoSelectProject=always' when the user chose 'Yes, save it'.",
|
|
6039
6632
|
inputSchema: LastProjectSetInputSchema,
|
|
6040
6633
|
execute: async (ctx) => {
|
|
6041
6634
|
const logger6 = createChildLogger2(ctx.correlationId);
|
|
@@ -6073,6 +6666,96 @@ var lastProjectClearTool = {
|
|
|
6073
6666
|
return { content, isError: false };
|
|
6074
6667
|
}
|
|
6075
6668
|
};
|
|
6669
|
+
var lastHostGetTool = {
|
|
6670
|
+
name: "muggle-local-last-host-get",
|
|
6671
|
+
description: "Get the cached last-used local dev server URL for a repo (read from <cwd>/.muggle-ai/last-host.json). Returns the URL and saved-at timestamp, or null if no cache exists. Skills consult this when 'autoSelectLocalHost = always' to silently reuse the URL the user used previously.",
|
|
6672
|
+
inputSchema: LastHostGetInputSchema,
|
|
6673
|
+
execute: async (ctx) => {
|
|
6674
|
+
const logger6 = createChildLogger2(ctx.correlationId);
|
|
6675
|
+
logger6.info("Executing muggle-local-last-host-get");
|
|
6676
|
+
const input = LastHostGetInputSchema.parse(ctx.input);
|
|
6677
|
+
const cached = readLastHost(input.cwd);
|
|
6678
|
+
if (!cached) {
|
|
6679
|
+
const content2 = [
|
|
6680
|
+
"No cached last-used host for this repo.",
|
|
6681
|
+
"",
|
|
6682
|
+
`Looked at: \`${input.cwd}/.muggle-ai/${LAST_HOST_FILE_NAME}\``
|
|
6683
|
+
].join("\n");
|
|
6684
|
+
return { content: content2, isError: false };
|
|
6685
|
+
}
|
|
6686
|
+
const content = [
|
|
6687
|
+
"**Cached last-used host:**",
|
|
6688
|
+
"",
|
|
6689
|
+
`- URL: ${cached.host}`,
|
|
6690
|
+
`- Saved at: ${cached.savedAt}`
|
|
6691
|
+
].join("\n");
|
|
6692
|
+
return { content, isError: false };
|
|
6693
|
+
}
|
|
6694
|
+
};
|
|
6695
|
+
var lastHostSetTool = {
|
|
6696
|
+
name: "muggle-local-last-host-set",
|
|
6697
|
+
description: "Save the user's chosen local dev server URL as the cached last-used host for this repo. Writes to <cwd>/.muggle-ai/last-host.json. Call this on every host pick (independent of 'Remember this URL?' Picker 2) so future runs can offer 'Use {lastHost}' regardless of whether the user opted to set autoSelectLocalHost=always.",
|
|
6698
|
+
inputSchema: LastHostSetInputSchema,
|
|
6699
|
+
execute: async (ctx) => {
|
|
6700
|
+
const logger6 = createChildLogger2(ctx.correlationId);
|
|
6701
|
+
logger6.info("Executing muggle-local-last-host-set");
|
|
6702
|
+
const input = LastHostSetInputSchema.parse(ctx.input);
|
|
6703
|
+
writeLastHost(input.cwd, input.host);
|
|
6704
|
+
return {
|
|
6705
|
+
content: `Cached **${input.host}** as the last-used host for this repo.`,
|
|
6706
|
+
isError: false
|
|
6707
|
+
};
|
|
6708
|
+
}
|
|
6709
|
+
};
|
|
6710
|
+
var lastHostClearTool = {
|
|
6711
|
+
name: "muggle-local-last-host-clear",
|
|
6712
|
+
description: "Remove the cached last-used host for this repo. After this, `autoSelectLocalHost = always` will fall through to ask until the user picks a new URL. No-op if no cache exists.",
|
|
6713
|
+
inputSchema: LastHostClearInputSchema,
|
|
6714
|
+
execute: async (ctx) => {
|
|
6715
|
+
const logger6 = createChildLogger2(ctx.correlationId);
|
|
6716
|
+
logger6.info("Executing muggle-local-last-host-clear");
|
|
6717
|
+
const input = LastHostClearInputSchema.parse(ctx.input);
|
|
6718
|
+
clearLastHost(input.cwd);
|
|
6719
|
+
return {
|
|
6720
|
+
content: `Cleared the cached last-used host for this repo.`,
|
|
6721
|
+
isError: false
|
|
6722
|
+
};
|
|
6723
|
+
}
|
|
6724
|
+
};
|
|
6725
|
+
var telemetrySkillEmitTool = {
|
|
6726
|
+
name: "muggle-local-telemetry-skill-emit",
|
|
6727
|
+
description: "Emit a client telemetry event recording that a Muggle Test skill was invoked. Each muggle-* skill calls this in its first step so we can measure skill usage. Never fails the skill on telemetry errors.",
|
|
6728
|
+
inputSchema: SkillTelemetryEmitInputSchema,
|
|
6729
|
+
execute: async (ctx) => {
|
|
6730
|
+
const input = SkillTelemetryEmitInputSchema.parse(ctx.input);
|
|
6731
|
+
safeTrack2({
|
|
6732
|
+
name: EventName.SkillInvoked,
|
|
6733
|
+
props: { skillName: input.skillName, trigger: input.trigger }
|
|
6734
|
+
});
|
|
6735
|
+
return { content: "ok", isError: false, data: { recorded: true } };
|
|
6736
|
+
}
|
|
6737
|
+
};
|
|
6738
|
+
var telemetryEventEmitTool = {
|
|
6739
|
+
name: "muggle-local-telemetry-event-emit",
|
|
6740
|
+
description: "Emit a structured failure-mode telemetry event recording how a Muggle Test skill classified a situation and what action the user took. Used at five decision points: 'pre-execution-classification' (replay vs regen), 'replay-failure-classified', 'replay-failure-resolved', 'regen-failure-classified', 'regen-failure-resolved'. Records to ~/.muggle-ai/telemetry/failure-events.jsonl. Never fails the skill on telemetry errors.",
|
|
6741
|
+
inputSchema: EventTelemetryEmitInputSchema,
|
|
6742
|
+
execute: async (ctx) => {
|
|
6743
|
+
const input = EventTelemetryEmitInputSchema.parse(ctx.input);
|
|
6744
|
+
appendFailureEvent({
|
|
6745
|
+
eventType: input.eventType,
|
|
6746
|
+
skillName: input.skillName,
|
|
6747
|
+
aiClassification: input.aiClassification,
|
|
6748
|
+
aiSuggestion: input.aiSuggestion,
|
|
6749
|
+
userAction: input.userAction,
|
|
6750
|
+
runId: input.runId,
|
|
6751
|
+
testCaseId: input.testCaseId,
|
|
6752
|
+
projectId: input.projectId,
|
|
6753
|
+
signals: input.signals,
|
|
6754
|
+
metadata: input.metadata
|
|
6755
|
+
});
|
|
6756
|
+
return { content: "ok", isError: false, data: { recorded: true } };
|
|
6757
|
+
}
|
|
6758
|
+
};
|
|
6076
6759
|
var allLocalQaTools = [
|
|
6077
6760
|
// Status tools
|
|
6078
6761
|
checkStatusTool,
|
|
@@ -6091,10 +6774,17 @@ var allLocalQaTools = [
|
|
|
6091
6774
|
publishTestScriptTool,
|
|
6092
6775
|
// Preferences tools
|
|
6093
6776
|
preferencesSetTool,
|
|
6094
|
-
// Last-project cache tools (per-repo "last used Muggle project")
|
|
6777
|
+
// Last-project cache tools (per-repo "last used Muggle Test project")
|
|
6095
6778
|
lastProjectGetTool,
|
|
6096
6779
|
lastProjectSetTool,
|
|
6097
|
-
lastProjectClearTool
|
|
6780
|
+
lastProjectClearTool,
|
|
6781
|
+
// Last-host cache tools (per-repo "last used local dev server URL")
|
|
6782
|
+
lastHostGetTool,
|
|
6783
|
+
lastHostSetTool,
|
|
6784
|
+
lastHostClearTool,
|
|
6785
|
+
// Client telemetry: skills emit invocation events through this tool
|
|
6786
|
+
telemetrySkillEmitTool,
|
|
6787
|
+
telemetryEventEmitTool
|
|
6098
6788
|
];
|
|
6099
6789
|
var toolMap = new Map(
|
|
6100
6790
|
allLocalQaTools.map((tool) => [tool.name, tool])
|
|
@@ -6110,7 +6800,44 @@ async function executeTool(name, input, correlationId) {
|
|
|
6110
6800
|
isError: true
|
|
6111
6801
|
};
|
|
6112
6802
|
}
|
|
6113
|
-
|
|
6803
|
+
const startTime = Date.now();
|
|
6804
|
+
safeTrack2({
|
|
6805
|
+
name: EventName.McpToolInvoked,
|
|
6806
|
+
props: { toolName: name, toolSurface: ToolSurface.Local, correlationId }
|
|
6807
|
+
});
|
|
6808
|
+
try {
|
|
6809
|
+
const result = await tool.execute({ input, correlationId });
|
|
6810
|
+
safeTrack2({
|
|
6811
|
+
name: EventName.McpToolCompleted,
|
|
6812
|
+
props: {
|
|
6813
|
+
toolName: name,
|
|
6814
|
+
toolSurface: ToolSurface.Local,
|
|
6815
|
+
correlationId,
|
|
6816
|
+
durationMs: Date.now() - startTime,
|
|
6817
|
+
outcome: result.isError ? Outcome.Error : Outcome.Success
|
|
6818
|
+
}
|
|
6819
|
+
});
|
|
6820
|
+
return result;
|
|
6821
|
+
} catch (err) {
|
|
6822
|
+
safeTrack2({
|
|
6823
|
+
name: EventName.McpToolCompleted,
|
|
6824
|
+
props: {
|
|
6825
|
+
toolName: name,
|
|
6826
|
+
toolSurface: ToolSurface.Local,
|
|
6827
|
+
correlationId,
|
|
6828
|
+
durationMs: Date.now() - startTime,
|
|
6829
|
+
outcome: Outcome.Error,
|
|
6830
|
+
errorCode: err instanceof Error ? err.name : "UnknownError"
|
|
6831
|
+
}
|
|
6832
|
+
});
|
|
6833
|
+
throw err;
|
|
6834
|
+
}
|
|
6835
|
+
}
|
|
6836
|
+
function safeTrack2(event) {
|
|
6837
|
+
try {
|
|
6838
|
+
track(event);
|
|
6839
|
+
} catch {
|
|
6840
|
+
}
|
|
6114
6841
|
}
|
|
6115
6842
|
|
|
6116
6843
|
// packages/mcps/src/mcp/e2e/index.ts
|
|
@@ -6172,6 +6899,7 @@ __export(e2e_exports2, {
|
|
|
6172
6899
|
TestCaseGetInputSchema: () => TestCaseGetInputSchema,
|
|
6173
6900
|
TestCaseListByUseCaseInputSchema: () => TestCaseListByUseCaseInputSchema,
|
|
6174
6901
|
TestCaseListInputSchema: () => TestCaseListInputSchema,
|
|
6902
|
+
TestCaseUpdateInputSchema: () => TestCaseUpdateInputSchema,
|
|
6175
6903
|
TestScriptGetInputSchema: () => TestScriptGetInputSchema,
|
|
6176
6904
|
TestScriptListInputSchema: () => TestScriptListInputSchema,
|
|
6177
6905
|
TokenPackageIdSchema: () => TokenPackageIdSchema,
|
|
@@ -6184,6 +6912,12 @@ __export(e2e_exports2, {
|
|
|
6184
6912
|
UseCaseListInputSchema: () => UseCaseListInputSchema,
|
|
6185
6913
|
UseCasePromptPreviewInputSchema: () => UseCasePromptPreviewInputSchema,
|
|
6186
6914
|
UseCaseUpdateFromPromptInputSchema: () => UseCaseUpdateFromPromptInputSchema,
|
|
6915
|
+
UseCaseUpdateInputSchema: () => UseCaseUpdateInputSchema,
|
|
6916
|
+
UserFeedbackCreateInputSchema: () => UserFeedbackCreateInputSchema,
|
|
6917
|
+
UserFeedbackDeleteInputSchema: () => UserFeedbackDeleteInputSchema,
|
|
6918
|
+
UserFeedbackListInputSchema: () => UserFeedbackListInputSchema,
|
|
6919
|
+
UserFeedbackTargetSchema: () => UserFeedbackTargetSchema,
|
|
6920
|
+
UserFeedbackTargetTypeSchema: () => UserFeedbackTargetTypeSchema,
|
|
6187
6921
|
WalletAutoTopUpSetPaymentMethodInputSchema: () => WalletAutoTopUpSetPaymentMethodInputSchema,
|
|
6188
6922
|
WalletAutoTopUpUpdateInputSchema: () => WalletAutoTopUpUpdateInputSchema,
|
|
6189
6923
|
WalletPaymentMethodCreateSetupSessionInputSchema: () => WalletPaymentMethodCreateSetupSessionInputSchema,
|
|
@@ -6230,10 +6964,15 @@ __export(local_exports2, {
|
|
|
6230
6964
|
CloudMappingEntityType: () => CloudMappingEntityType,
|
|
6231
6965
|
DeviceCodePollStatus: () => DeviceCodePollStatus,
|
|
6232
6966
|
EmptyInputSchema: () => EmptyInputSchema2,
|
|
6967
|
+
EventTelemetryEmitInputSchema: () => EventTelemetryEmitInputSchema,
|
|
6233
6968
|
ExecuteReplayInputSchema: () => ExecuteReplayInputSchema,
|
|
6234
6969
|
ExecuteTestGenerationInputSchema: () => ExecuteTestGenerationInputSchema,
|
|
6235
6970
|
ExecutionStatus: () => ExecutionStatus,
|
|
6971
|
+
FailureEventType: () => FailureEventType,
|
|
6236
6972
|
HealthStatus: () => HealthStatus,
|
|
6973
|
+
LastHostClearInputSchema: () => LastHostClearInputSchema,
|
|
6974
|
+
LastHostGetInputSchema: () => LastHostGetInputSchema,
|
|
6975
|
+
LastHostSetInputSchema: () => LastHostSetInputSchema,
|
|
6237
6976
|
LastProjectClearInputSchema: () => LastProjectClearInputSchema,
|
|
6238
6977
|
LastProjectGetInputSchema: () => LastProjectGetInputSchema,
|
|
6239
6978
|
LastProjectSetInputSchema: () => LastProjectSetInputSchema,
|
|
@@ -6250,6 +6989,7 @@ __export(local_exports2, {
|
|
|
6250
6989
|
RunResultListInputSchema: () => RunResultListInputSchema,
|
|
6251
6990
|
RunResultStorageService: () => RunResultStorageService,
|
|
6252
6991
|
SessionStatus: () => SessionStatus,
|
|
6992
|
+
SkillTelemetryEmitInputSchema: () => SkillTelemetryEmitInputSchema,
|
|
6253
6993
|
StorageService: () => StorageService,
|
|
6254
6994
|
TestCaseDetailsSchema: () => TestCaseDetailsSchema,
|
|
6255
6995
|
TestResultStatus: () => TestResultStatus,
|
|
@@ -6299,7 +7039,10 @@ function isLocalOnlyTool(toolName) {
|
|
|
6299
7039
|
"muggle_run_result_list",
|
|
6300
7040
|
"muggle_run_result_get",
|
|
6301
7041
|
"muggle_test_script_list",
|
|
6302
|
-
"muggle_test_script_get"
|
|
7042
|
+
"muggle_test_script_get",
|
|
7043
|
+
// Client telemetry — purely local, no backend call
|
|
7044
|
+
"muggle-local-telemetry-skill-emit",
|
|
7045
|
+
"muggle-local-telemetry-event-emit"
|
|
6303
7046
|
];
|
|
6304
7047
|
return localOnlyTools.includes(toolName);
|
|
6305
7048
|
}
|
|
@@ -6313,4 +7056,4 @@ var plugins_exports = {};
|
|
|
6313
7056
|
// packages/mcps/src/mcp/agents/index.ts
|
|
6314
7057
|
var agents_exports = {};
|
|
6315
7058
|
|
|
6316
|
-
export { DEFAULT_PREFERENCES, PREFERENCES_FILE_NAME, PREFERENCES_PROJECT_DIR_NAME, PREFERENCES_SCHEMA, PREFERENCES_VERSION, PREFERENCE_ALLOWED_VALUES, PreferenceKey, PreferenceValue, __export, __require, buildElectronAppChecksumsUrl, buildElectronAppReleaseAssetUrl, buildElectronAppReleaseTag, calculateFileChecksum, createApiKeyWithToken, createChildLogger, deleteApiKeyData, deleteCredentials, e2e_exports2 as e2e_exports, formatPreferencesOneLiner, getApiKey, getApiKeyFilePath, getAuthService, getBundledElectronAppVersion, getCallerCredentials, getCallerCredentialsAsync, getChecksumForPlatform, getConfig, getCredentialsFilePath, getDataDir2 as getDataDir, getDownloadBaseUrl, getElectronAppChecksums, getElectronAppDir, getElectronAppVersion, getElectronAppVersionSource, getLocalQaTools, getLogger, getPlatformKey, getQaTools, getValidApiKeyData, getValidCredentials, hasApiKey, isElectronAppInstalled, isFirstRun, loadApiKeyData, loadCredentials, local_exports2 as local_exports, mcp_exports, openBrowserUrl, performLogin, performLogout, pollDeviceCode, readGlobalPreferences, readProjectPreferences, resetConfig, resetLogger, resetPreference, resolvePreferences, saveApiKey, saveApiKeyData, saveCredentials, src_exports, startDeviceCodeFlow, toolRequiresAuth, validatePreference, verifyFileChecksum, writePreferences };
|
|
7059
|
+
export { DEFAULT_PREFERENCES, EventName, PREFERENCES_FILE_NAME, PREFERENCES_PROJECT_DIR_NAME, PREFERENCES_SCHEMA, PREFERENCES_VERSION, PREFERENCE_ALLOWED_VALUES, PreferenceKey, PreferenceValue, ServiceName, Surface, __export, __require, buildElectronAppChecksumsUrl, buildElectronAppReleaseAssetUrl, buildElectronAppReleaseTag, calculateFileChecksum, createApiKeyWithToken, createChildLogger, deleteApiKeyData, deleteCredentials, e2e_exports2 as e2e_exports, formatPreferencesOneLiner, getApiKey, getApiKeyFilePath, getAuthService, getBundledElectronAppVersion, getCallerCredentials, getCallerCredentialsAsync, getChecksumForPlatform, getConfig, getCredentialsFilePath, getDataDir2 as getDataDir, getDownloadBaseUrl, getElectronAppChecksums, getElectronAppDir, getElectronAppVersion, getElectronAppVersionSource, getLocalQaTools, getLogger, getPlatformKey, getQaTools, getValidApiKeyData, getValidCredentials, hasApiKey, initTelemetry, isElectronAppInstalled, isFirstRun, loadApiKeyData, loadCredentials, local_exports2 as local_exports, mcp_exports, openBrowserUrl, performLogin, performLogout, pollDeviceCode, readGlobalPreferences, readProjectPreferences, resetConfig, resetLogger, resetPreference, resolveElectronAppPathOrNull, resolvePreferences, saveApiKey, saveApiKeyData, saveCredentials, src_exports, startDeviceCodeFlow, toolRequiresAuth, track, validatePreference, verifyFileChecksum, writePreferences };
|