@muggleai/works 5.0.0 → 5.0.1

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.
@@ -924,11 +924,12 @@ var AuthService = class {
924
924
  });
925
925
  let browserUrl = data.verification_uri_complete;
926
926
  if (options?.forceNewSession) {
927
+ this.logout();
927
928
  const logoutUrl = new URL(`https://${domain}/v2/logout`);
928
929
  logoutUrl.searchParams.set("client_id", clientId);
929
930
  logoutUrl.searchParams.set("returnTo", data.verification_uri_complete);
930
931
  browserUrl = logoutUrl.toString();
931
- logger6.info("Force new session: opening logout-redirect URL", {
932
+ logger6.info("Force new session: cleared local token, opening logout-redirect URL", {
932
933
  logoutUrl: browserUrl
933
934
  });
934
935
  }
@@ -1,4 +1,4 @@
1
- import { __export, getLogger, getConfig, createChildLogger, buildElectronAppReleaseAssetUrl, getAuthService, hasApiKey, getElectronAppVersion, getElectronAppDir, getPlatformKey, isFirstRun, writePreferences, DEFAULT_PREFERENCES, getDataDir, PREFERENCES_FILE_NAME, isElectronAppInstalled, getElectronAppChecksums, getChecksumForPlatform, verifyFileChecksum, calculateFileChecksum, initTelemetry, Surface, ServiceName, track, EventName, getQaTools, getLocalQaTools, performLogout, performLogin, toolRequiresAuth, getCallerCredentials, hasShownDisclosure, getDisclosureCopy, markDisclosureShown, getBundledElectronAppVersion, getElectronAppVersionSource, getCredentialsFilePath, buildElectronAppChecksumsUrl, __require } from './chunk-YKR2TQ24.js';
1
+ import { __export, getLogger, getConfig, createChildLogger, buildElectronAppReleaseAssetUrl, getAuthService, hasApiKey, getElectronAppVersion, getElectronAppDir, getPlatformKey, isFirstRun, writePreferences, DEFAULT_PREFERENCES, getDataDir, PREFERENCES_FILE_NAME, isElectronAppInstalled, getElectronAppChecksums, getChecksumForPlatform, verifyFileChecksum, calculateFileChecksum, initTelemetry, Surface, ServiceName, track, EventName, getQaTools, getLocalQaTools, performLogout, performLogin, toolRequiresAuth, getCallerCredentials, hasShownDisclosure, getDisclosureCopy, markDisclosureShown, getBundledElectronAppVersion, getElectronAppVersionSource, getCredentialsFilePath, buildElectronAppChecksumsUrl, __require } from './chunk-KDRSEHK5.js';
2
2
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
3
3
  import { ListToolsRequestSchema, CallToolRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema } from '@modelcontextprotocol/sdk/types.js';
4
4
  import { v4 } from 'uuid';
@@ -736,7 +736,7 @@ async function resolveGsScreenshotUrls(report, opts) {
736
736
  if (gsUrls.length === 0) {
737
737
  return report;
738
738
  }
739
- const mcps = await import('./src-ECRJW2LY.js');
739
+ const mcps = await import('./src-2O5UH4FA.js');
740
740
  const credentials = await mcps.getCallerCredentialsAsync();
741
741
  if (!credentials.bearerToken && !credentials.apiKey) {
742
742
  stderrWrite(
package/dist/cli.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { runCli } from './chunk-5G7WI7IY.js';
3
- import './chunk-YKR2TQ24.js';
2
+ import { runCli } from './chunk-XO5BQZM3.js';
3
+ import './chunk-KDRSEHK5.js';
4
4
 
5
5
  // src/cli/main.ts
6
6
  runCli().catch((error) => {
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- export { src_exports as commands, createUnifiedMcpServer, server_exports as server } from './chunk-5G7WI7IY.js';
2
- export { createChildLogger, e2e_exports as e2e, getConfig, getLocalQaTools, getLogger, getQaTools, local_exports as localQa, mcp_exports as mcp, e2e_exports as qa, src_exports as shared } from './chunk-YKR2TQ24.js';
1
+ export { src_exports as commands, createUnifiedMcpServer, server_exports as server } from './chunk-XO5BQZM3.js';
2
+ export { createChildLogger, e2e_exports as e2e, getConfig, getLocalQaTools, getLogger, getQaTools, local_exports as localQa, mcp_exports as mcp, e2e_exports as qa, src_exports as shared } from './chunk-KDRSEHK5.js';
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "muggle",
3
3
  "description": "Run real-browser end-to-end (E2E) acceptance tests on your web app from any AI coding agent. Generate test scripts from plain English, replay them on localhost, capture screenshots, and validate user flows like signup, checkout, and dashboards. Works across Claude Code, Cursor, Codex, and Windsurf.",
4
- "version": "5.0.0",
4
+ "version": "5.0.1",
5
5
  "author": {
6
6
  "name": "Muggle AI",
7
7
  "email": "support@muggle-ai.com"
@@ -2,7 +2,7 @@
2
2
  "name": "muggle",
3
3
  "displayName": "Muggle AI",
4
4
  "description": "Ship quality products with AI-powered end-to-end (E2E) acceptance testing that validates your web app like a real user — from Claude Code and Cursor to PR.",
5
- "version": "5.0.0",
5
+ "version": "5.0.1",
6
6
  "author": {
7
7
  "name": "Muggle AI",
8
8
  "email": "support@muggle-ai.com"
@@ -113,13 +113,15 @@ If no changes detected (clean tree), tell the user and ask what they want to tes
113
113
 
114
114
  ## Step 3: Authenticate
115
115
 
116
- 1. Call `muggle-remote-auth-status`
117
- 2. If **authenticated and not expired** → gate `autoLogin` (per `preference-gates/README.md`):
118
- - `always` → reuse saved session.
116
+ 1. Call `muggle-remote-auth-status`. Three states: **valid** (`authenticated: true`), **expired** (`authenticated: false` + `isExpired: true`, `email` still present), **absent** (`authenticated: false`, no `email`).
117
+ 2. **Valid OR expired** (any stored identity) → gate `autoLogin` (per `preference-gates/README.md`). An expired token is NOT a reason to silently re-login the same account — surface the switch choice:
118
+ - `always` → reuse if valid; if expired, re-login the **same** account (`muggle-remote-auth-login`, then `muggle-remote-auth-poll`).
119
119
  - `never` → `muggle-remote-auth-login` with `forceNewSession: true`, then `muggle-remote-auth-poll`.
120
120
  - `ask` → run Picker 1 from `preference-gates/autoLogin.md` via `AskUserQuestion`; map the answer back to one of the actions above.
121
- 3. If **not authenticated or expired** → call `muggle-remote-auth-login`
122
- 4. If login pending → call `muggle-remote-auth-poll`
121
+ 3. **Absent** (no stored identity) → `muggle-remote-auth-login` directly, then `muggle-remote-auth-poll`.
122
+ 4. If login pending → call `muggle-remote-auth-poll`.
123
+
124
+ **Account-switch caveat (`never` / "Switch account").** The device flow has no `prompt=select_account`; switching relies on `forceNewSession` first clearing the Auth0 session via `/v2/logout?returnTo=<device-activation URL>`. That redirect only works if the activation URL is in the app's Auth0 *Allowed Logout URLs* — otherwise the browser shows an Auth0 error page and the session is silently reused. If that happens, tell the user to complete login in a **fresh incognito window** (no live SSO session) so Auth0 presents an account login.
123
125
 
124
126
  If auth fails repeatedly, suggest: `muggle logout && muggle login` from terminal.
125
127
 
@@ -147,14 +147,16 @@ Run the shared loop in [`../_shared/dev-loop/run.md`](../_shared/dev-loop/run.md
147
147
 
148
148
  Caller glue: `mode` is the path chosen in §5; `localUrl` from §4; `cwd` = the repo root, or the prepared worktree when one is in use.
149
149
 
150
- ### 7. Execute (no approval prompt; `showUi` gated by `showElectronBrowser`)
150
+ ### 7. Execute (`showUi` gated by `showElectronBrowser`)
151
151
 
152
- Call `muggle-local-execute-test-generation` or `muggle-local-execute-replay` directly. **Do not** ask the user to re-approve the Electron launch — the user choosing this skill in the first place is the approval.
152
+ Resolve the `showElectronBrowser` gate **first**, then call `muggle-local-execute-test-generation` or `muggle-local-execute-replay`. **Do not** ask the user to re-approve the Electron launch itself — choosing this skill is the approval. That run-approval suppression does **not** extend to the gate below: when `showElectronBrowser=ask` you must still fire its picker.
153
153
 
154
- Gate `showElectronBrowser` (per `preference-gates/README.md`). Reuse choice within a session.
155
- - `always` → omit `showUi`.
154
+ Gate `showElectronBrowser` (per `preference-gates/README.md`). Reuse the choice within a session.
155
+ - `always` → omit `showUi` (the browser shows by default).
156
156
  - `never` → pass `showUi: false`.
157
- - `ask` → run Picker 1 from `preference-gates/showElectronBrowser.md` via `AskUserQuestion`; map the answer back to one of the actions above.
157
+ - `ask` → you **must** call `AskUserQuestion` (Picker 1 from `preference-gates/showElectronBrowser.md`) **before** the execute call, then map the answer to the `always`/`never` action above. Do not decide for the user.
158
+
159
+ `showUi` is only ever omitted or `false` — never pass `showUi: true`.
158
160
 
159
161
  ### 8. Upload run to cloud (every completed run; open `viewUrl` gated by `openTestResultsAfterRun`)
160
162
 
@@ -1,7 +1,7 @@
1
1
  {
2
- "release": "5.0.0",
3
- "buildId": "run-48-1",
4
- "commitSha": "31c2dbefd3e75f56ea239b5953efbef859290db9",
5
- "buildTime": "2026-06-03T19:09:10Z",
2
+ "release": "5.0.1",
3
+ "buildId": "run-49-1",
4
+ "commitSha": "a12a3252381af4fb34b79598208ba62f9764154d",
5
+ "buildTime": "2026-06-04T17:35:40Z",
6
6
  "serviceName": "muggle-ai-works-mcp"
7
7
  }
@@ -1 +1 @@
1
- export { DEFAULT_PREFERENCES, PREFERENCES_FILE_NAME, PREFERENCES_PROJECT_DIR_NAME, PREFERENCES_SCHEMA, PREFERENCES_VERSION, PREFERENCE_ALLOWED_VALUES, PreferenceKey, PreferenceValue, buildElectronAppChecksumsUrl, buildElectronAppReleaseAssetUrl, buildElectronAppReleaseTag, calculateFileChecksum, createApiKeyWithToken, createChildLogger, deleteApiKeyData, deleteCredentials, e2e_exports as e2e, formatPreferencesOneLiner, getApiKey, getApiKeyFilePath, getAuthService, getBundledElectronAppVersion, getCallerCredentials, getCallerCredentialsAsync, getChecksumForPlatform, getConfig, getCredentialsFilePath, getDataDir, getDownloadBaseUrl, getElectronAppChecksums, getElectronAppDir, getElectronAppVersion, getElectronAppVersionSource, getLocalQaTools, getLogger, getPlatformKey, getQaTools, getValidApiKeyData, getValidCredentials, hasApiKey, isElectronAppInstalled, isFirstRun, loadApiKeyData, loadCredentials, local_exports as localQa, mcp_exports as mcp, openBrowserUrl, performLogin, performLogout, pollDeviceCode, e2e_exports as qa, readGlobalPreferences, readProjectPreferences, resetConfig, resetLogger, resetPreference, resolveElectronAppPathOrNull, resolvePreferences, saveApiKey, saveApiKeyData, saveCredentials, startDeviceCodeFlow, toolRequiresAuth, validatePreference, verifyFileChecksum, writePreferences } from './chunk-YKR2TQ24.js';
1
+ export { DEFAULT_PREFERENCES, PREFERENCES_FILE_NAME, PREFERENCES_PROJECT_DIR_NAME, PREFERENCES_SCHEMA, PREFERENCES_VERSION, PREFERENCE_ALLOWED_VALUES, PreferenceKey, PreferenceValue, buildElectronAppChecksumsUrl, buildElectronAppReleaseAssetUrl, buildElectronAppReleaseTag, calculateFileChecksum, createApiKeyWithToken, createChildLogger, deleteApiKeyData, deleteCredentials, e2e_exports as e2e, formatPreferencesOneLiner, getApiKey, getApiKeyFilePath, getAuthService, getBundledElectronAppVersion, getCallerCredentials, getCallerCredentialsAsync, getChecksumForPlatform, getConfig, getCredentialsFilePath, getDataDir, getDownloadBaseUrl, getElectronAppChecksums, getElectronAppDir, getElectronAppVersion, getElectronAppVersionSource, getLocalQaTools, getLogger, getPlatformKey, getQaTools, getValidApiKeyData, getValidCredentials, hasApiKey, isElectronAppInstalled, isFirstRun, loadApiKeyData, loadCredentials, local_exports as localQa, mcp_exports as mcp, openBrowserUrl, performLogin, performLogout, pollDeviceCode, e2e_exports as qa, readGlobalPreferences, readProjectPreferences, resetConfig, resetLogger, resetPreference, resolveElectronAppPathOrNull, resolvePreferences, saveApiKey, saveApiKeyData, saveCredentials, startDeviceCodeFlow, toolRequiresAuth, validatePreference, verifyFileChecksum, writePreferences } from './chunk-KDRSEHK5.js';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@muggleai/works",
3
3
  "mcpName": "io.github.multiplex-ai/muggle",
4
- "version": "5.0.0",
4
+ "version": "5.0.1",
5
5
  "description": "Ship quality products with AI-powered E2E acceptance testing that validates your web app like a real user — from Claude Code and Cursor to PR.",
6
6
  "type": "module",
7
7
  "main": "dist/index.js",
@@ -41,14 +41,14 @@
41
41
  "test:watch": "vitest"
42
42
  },
43
43
  "muggleConfig": {
44
- "electronAppVersion": "1.0.113",
44
+ "electronAppVersion": "1.0.116",
45
45
  "downloadBaseUrl": "https://github.com/multiplex-ai/muggle-ai-works/releases/download",
46
46
  "runtimeTargetDefault": "production",
47
47
  "checksums": {
48
- "darwin-arm64": "f3edf2d40ae81c88ae579c9a5835cd8a84b5864610926a4ca31c4b62478103a8",
49
- "darwin-x64": "3f13399eb957a214dabaab3bdd921c9c2293205972b84b7f788a2cb862ba55b9",
50
- "linux-x64": "dfbbd32eca72903f5cfd7545caf0583bb609de8feb47ebf0d4580f3d1cdffbf2",
51
- "win32-x64": "0e4838e12a99ec86bc66289503cfb43de018cb518c952b2fb72fbe5e6233f1d4"
48
+ "darwin-arm64": "382466a6eefe49cddc5662556cb6b744c60c2eed9984e520df9f62726bc468a0",
49
+ "darwin-x64": "9c57b10b1ed03bcd6629cb36abd5c0e0b5d095a27a38305ad4272c77cd6334af",
50
+ "linux-x64": "d6b10a829f99027747349ab37521b765041343676f59e59792afcec1de024080",
51
+ "win32-x64": "77981c9d77dd49a786cfca7156ce326f56a75716cf911adad270521230435f75"
52
52
  }
53
53
  },
54
54
  "dependencies": {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "muggle",
3
3
  "description": "Run real-browser end-to-end (E2E) acceptance tests on your web app from any AI coding agent. Generate test scripts from plain English, replay them on localhost, capture screenshots, and validate user flows like signup, checkout, and dashboards. Works across Claude Code, Cursor, Codex, and Windsurf.",
4
- "version": "5.0.0",
4
+ "version": "5.0.1",
5
5
  "author": {
6
6
  "name": "Muggle AI",
7
7
  "email": "support@muggle-ai.com"
@@ -2,7 +2,7 @@
2
2
  "name": "muggle",
3
3
  "displayName": "Muggle AI",
4
4
  "description": "Ship quality products with AI-powered end-to-end (E2E) acceptance testing that validates your web app like a real user — from Claude Code and Cursor to PR.",
5
- "version": "5.0.0",
5
+ "version": "5.0.1",
6
6
  "author": {
7
7
  "name": "Muggle AI",
8
8
  "email": "support@muggle-ai.com"
@@ -113,13 +113,15 @@ If no changes detected (clean tree), tell the user and ask what they want to tes
113
113
 
114
114
  ## Step 3: Authenticate
115
115
 
116
- 1. Call `muggle-remote-auth-status`
117
- 2. If **authenticated and not expired** → gate `autoLogin` (per `preference-gates/README.md`):
118
- - `always` → reuse saved session.
116
+ 1. Call `muggle-remote-auth-status`. Three states: **valid** (`authenticated: true`), **expired** (`authenticated: false` + `isExpired: true`, `email` still present), **absent** (`authenticated: false`, no `email`).
117
+ 2. **Valid OR expired** (any stored identity) → gate `autoLogin` (per `preference-gates/README.md`). An expired token is NOT a reason to silently re-login the same account — surface the switch choice:
118
+ - `always` → reuse if valid; if expired, re-login the **same** account (`muggle-remote-auth-login`, then `muggle-remote-auth-poll`).
119
119
  - `never` → `muggle-remote-auth-login` with `forceNewSession: true`, then `muggle-remote-auth-poll`.
120
120
  - `ask` → run Picker 1 from `preference-gates/autoLogin.md` via `AskUserQuestion`; map the answer back to one of the actions above.
121
- 3. If **not authenticated or expired** → call `muggle-remote-auth-login`
122
- 4. If login pending → call `muggle-remote-auth-poll`
121
+ 3. **Absent** (no stored identity) → `muggle-remote-auth-login` directly, then `muggle-remote-auth-poll`.
122
+ 4. If login pending → call `muggle-remote-auth-poll`.
123
+
124
+ **Account-switch caveat (`never` / "Switch account").** The device flow has no `prompt=select_account`; switching relies on `forceNewSession` first clearing the Auth0 session via `/v2/logout?returnTo=<device-activation URL>`. That redirect only works if the activation URL is in the app's Auth0 *Allowed Logout URLs* — otherwise the browser shows an Auth0 error page and the session is silently reused. If that happens, tell the user to complete login in a **fresh incognito window** (no live SSO session) so Auth0 presents an account login.
123
125
 
124
126
  If auth fails repeatedly, suggest: `muggle logout && muggle login` from terminal.
125
127
 
@@ -147,14 +147,16 @@ Run the shared loop in [`../_shared/dev-loop/run.md`](../_shared/dev-loop/run.md
147
147
 
148
148
  Caller glue: `mode` is the path chosen in §5; `localUrl` from §4; `cwd` = the repo root, or the prepared worktree when one is in use.
149
149
 
150
- ### 7. Execute (no approval prompt; `showUi` gated by `showElectronBrowser`)
150
+ ### 7. Execute (`showUi` gated by `showElectronBrowser`)
151
151
 
152
- Call `muggle-local-execute-test-generation` or `muggle-local-execute-replay` directly. **Do not** ask the user to re-approve the Electron launch — the user choosing this skill in the first place is the approval.
152
+ Resolve the `showElectronBrowser` gate **first**, then call `muggle-local-execute-test-generation` or `muggle-local-execute-replay`. **Do not** ask the user to re-approve the Electron launch itself — choosing this skill is the approval. That run-approval suppression does **not** extend to the gate below: when `showElectronBrowser=ask` you must still fire its picker.
153
153
 
154
- Gate `showElectronBrowser` (per `preference-gates/README.md`). Reuse choice within a session.
155
- - `always` → omit `showUi`.
154
+ Gate `showElectronBrowser` (per `preference-gates/README.md`). Reuse the choice within a session.
155
+ - `always` → omit `showUi` (the browser shows by default).
156
156
  - `never` → pass `showUi: false`.
157
- - `ask` → run Picker 1 from `preference-gates/showElectronBrowser.md` via `AskUserQuestion`; map the answer back to one of the actions above.
157
+ - `ask` → you **must** call `AskUserQuestion` (Picker 1 from `preference-gates/showElectronBrowser.md`) **before** the execute call, then map the answer to the `always`/`never` action above. Do not decide for the user.
158
+
159
+ `showUi` is only ever omitted or `false` — never pass `showUi: true`.
158
160
 
159
161
  ### 8. Upload run to cloud (every completed run; open `viewUrl` gated by `openTestResultsAfterRun`)
160
162