@mushi-mushi/core 1.5.0 → 1.6.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/CONTRIBUTING.md +0 -11
- package/dist/index.d.cts +93 -65
- package/dist/index.d.ts +93 -65
- package/package.json +14 -14
package/CONTRIBUTING.md
CHANGED
|
@@ -101,17 +101,6 @@ Releases are fully automated. Maintainers don't run `npm publish` by hand.
|
|
|
101
101
|
|
|
102
102
|
If GitHub's anti-loop protection suppresses the auto re-fire (the squash merge can be attributed to `github-actions[bot]`), trigger the workflow manually: **Actions → release → Run workflow → master**.
|
|
103
103
|
|
|
104
|
-
### Known CI/CD quirks and their automatic safeguards
|
|
105
|
-
|
|
106
|
-
A handful of GitHub-Actions × Changesets edge cases have caused release-pipeline stalls in the past. Each is now caught automatically — keep these in mind when you see the symptom:
|
|
107
|
-
|
|
108
|
-
| Symptom | Root cause | Automatic safeguard |
|
|
109
|
-
| --- | --- | --- |
|
|
110
|
-
| The `Build & Test` required check never registers on the `chore: version packages` PR — the PR stays "Required check missing" forever | `changeset-release/master` is pushed by `github-actions[bot]`. GitHub silently drops the downstream `pull_request` event to prevent bot loops (observed on PR #45, #102, #124). | `ci.yml` now also triggers on `push` to `changeset-release/master`, so `Build & Test` reports against the head commit directly. No empty-commit nudge needed. |
|
|
111
|
-
| Release workflow fails with `No commits between master and changeset-release/master` after merging a PR with a new changeset. | A `.changeset/*.md` file whose YAML frontmatter only targets packages listed in `.changeset/config.json#ignore` (e.g. `@mushi-mushi/server`, `@mushi-mushi/admin`). `changeset version` produces no bumps, the version PR is empty, the next push errors (PR #102 / #121, 2026-05-19). | `pnpm check:changeset-orphans` runs in both `ci.yml` and `release.yml`. PR CI fails with an actionable message naming the orphan file *before* it can reach master. If you legitimately need to record an internal-only change, omit the changeset entirely — the diff lives in git history. |
|
|
112
|
-
| Release workflow's `Audit signatures of installed dependencies` step fails with `npm ETARGET / No matching version found for @mushi-mushi/<pkg>@<ver>` seconds after the publish step succeeded. | npm's registry CDN can take up to ~30s to propagate a freshly-published manifest. The audit step shells out to `npm install` against the just-published version and races the CDN (observed 2026-05-20, run 26149167393). | The audit step retries with exponential backoff (1, 2, 4, 8, 16, 32s — 63s total) before failing. Sigstore signatures are written at publish time, so a one-off audit failure never indicates a corrupted package — `pnpm view <pkg> version` is the ground truth. |
|
|
113
|
-
| Push to `master` after merging a PR doesn't fire the `Release` workflow. | Same anti-loop protection: when a squash merge is attributed to `github-actions[bot]`, GitHub may suppress the downstream `push` trigger. Sporadic — observed twice in the last 60 days. | `release.yml` keeps `workflow_dispatch` as the manual fallback. Recovery: **Actions → Release → Run workflow → master**. The `Build & Verify` job re-runs identically to the auto-fired path. |
|
|
114
|
-
|
|
115
104
|
### Adding a brand-new publishable package
|
|
116
105
|
|
|
117
106
|
Trusted Publisher bindings are configured **per package** on `npmjs.com` and require the package to already exist on the registry. New packages therefore need a one-time bootstrap before OIDC can take over.
|
package/dist/index.d.cts
CHANGED
|
@@ -19,43 +19,12 @@ interface MushiConfig {
|
|
|
19
19
|
integrations?: MushiIntegrationsConfig;
|
|
20
20
|
offline?: MushiOfflineConfig;
|
|
21
21
|
rewards?: MushiRewardsConfig;
|
|
22
|
-
/**
|
|
23
|
-
* Sentry-spec-1.0 hook fired AFTER preFilter / on-device classifier /
|
|
24
|
-
* rate-limit gates pass and BEFORE the report is sent or queued.
|
|
25
|
-
* Return:
|
|
26
|
-
* - the report (possibly modified) → submit as-is
|
|
27
|
-
* - a Promise<MushiReport> → await, then submit
|
|
28
|
-
* - `null` → drop the report silently (no `report:sent`/`:failed` event)
|
|
29
|
-
*
|
|
30
|
-
* Use this for app-level redaction of sensitive metadata, hard-coded
|
|
31
|
-
* tag overrides, or last-mile category routing. Errors thrown inside
|
|
32
|
-
* the hook are caught and logged; the report still ships unchanged so
|
|
33
|
-
* a buggy hook never silently swallows feedback.
|
|
34
|
-
*
|
|
35
|
-
* Mirrors Sentry's [SDK feedback spec §4](https://develop.sentry.dev/sdk/telemetry/feedbacks/)
|
|
36
|
-
* `beforeSendFeedback` callback.
|
|
37
|
-
*/
|
|
38
|
-
beforeSendFeedback?: (report: MushiReport) => MushiReport | Promise<MushiReport | null> | null;
|
|
39
|
-
/**
|
|
40
|
-
* Sentry-spec-1.0 callback fired exactly once on `init()` after the
|
|
41
|
-
* SDK detects that the previous browser session ended in a crash
|
|
42
|
-
* (uncaught exception, unhandled rejection, or hard navigate during
|
|
43
|
-
* unfinished submit). Use it to surface a "Tell us what went wrong?"
|
|
44
|
-
* prompt to the user — the SDK does NOT auto-open the widget so the
|
|
45
|
-
* host app can decide on copy and timing.
|
|
46
|
-
*
|
|
47
|
-
* The promise resolves with `true` when a crash was detected, `false`
|
|
48
|
-
* when the previous run ended cleanly, and `null` when the SDK can't
|
|
49
|
-
* tell (typically: localStorage unavailable, or first-ever load).
|
|
50
|
-
*
|
|
51
|
-
* Mirrors Sentry's [SDK feedback spec §6](https://develop.sentry.dev/sdk/telemetry/feedbacks/)
|
|
52
|
-
* `onCrashedLastRun` hook.
|
|
53
|
-
*/
|
|
54
|
-
onCrashedLastRun?: (info: {
|
|
55
|
-
crashed: boolean | null;
|
|
56
|
-
}) => void;
|
|
57
22
|
debug?: boolean;
|
|
58
23
|
enabled?: boolean;
|
|
24
|
+
/** Hook called before a report is sent. Return null to cancel, or return the (possibly modified) report. */
|
|
25
|
+
beforeSendFeedback?: (report: MushiReport) => MushiReport | null | Promise<MushiReport | null>;
|
|
26
|
+
/** Called once if the app crashed during the previous session. */
|
|
27
|
+
onCrashedLastRun?: (crashed: boolean) => void;
|
|
59
28
|
}
|
|
60
29
|
interface MushiSentryConfig {
|
|
61
30
|
dsn?: string;
|
|
@@ -109,11 +78,36 @@ interface MushiWidgetConfig {
|
|
|
109
78
|
*/
|
|
110
79
|
betaMode?: MushiBetaModeConfig;
|
|
111
80
|
/**
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
81
|
+
* Absolute base URL of the Mushi admin console (e.g. `https://mushi.example.com`).
|
|
82
|
+
* When set, the success step surfaces a one-tap link to the user's own report
|
|
83
|
+
* on the console so they can watch the status change in real time. Without
|
|
84
|
+
* this the success step still confirms submission but cannot deep-link.
|
|
85
|
+
*
|
|
86
|
+
* This is intentionally separate from the API endpoint — production apps
|
|
87
|
+
* usually have the API on `api.mushi.example.com` and the console on
|
|
88
|
+
* `app.mushi.example.com`.
|
|
89
|
+
*/
|
|
90
|
+
dashboardUrl?: string;
|
|
91
|
+
/**
|
|
92
|
+
* Override the SLA copy shown in the success step's "what happens next"
|
|
93
|
+
* line. Defaults to "We aim to review within 48h". Set to an empty string
|
|
94
|
+
* to hide the line entirely (e.g. internal-only deployments where SLA
|
|
95
|
+
* messaging would be over-promising).
|
|
96
|
+
*/
|
|
97
|
+
responseSlaLabel?: string;
|
|
98
|
+
/**
|
|
99
|
+
* Show a first-class "Feature request" card at the top of the category
|
|
100
|
+
* step. Defaults to true. Set to false for production-only deployments
|
|
101
|
+
* where you don't want to invite feature ideas through the widget.
|
|
102
|
+
* Internally this maps to `category='other'` with
|
|
103
|
+
* `user_category='Feature request'` so no DB migration is needed.
|
|
116
104
|
*/
|
|
105
|
+
featureRequestCard?: boolean;
|
|
106
|
+
/** Override the localised label for the feature-request card. */
|
|
107
|
+
featureRequestLabel?: string;
|
|
108
|
+
/** Override the helper text shown under the feature-request card. */
|
|
109
|
+
featureRequestDescription?: string;
|
|
110
|
+
/** Minimum description character count before the submit button enables. */
|
|
117
111
|
minDescriptionLength?: number;
|
|
118
112
|
}
|
|
119
113
|
interface MushiBetaModeConfig {
|
|
@@ -240,6 +234,17 @@ interface MushiPrivacyConfig {
|
|
|
240
234
|
maskSelectors?: string[];
|
|
241
235
|
/** DOM subtrees to remove from screenshots before upload. */
|
|
242
236
|
blockSelectors?: string[];
|
|
237
|
+
/**
|
|
238
|
+
* CSS selectors whose matching elements are blacked-out (filled with an
|
|
239
|
+
* opaque black rectangle) in screenshots before upload. Intended for
|
|
240
|
+
* sensitive fields that should never appear in any form — passwords, PII,
|
|
241
|
+
* financial data. Applied in addition to `maskSelectors`.
|
|
242
|
+
*
|
|
243
|
+
* Default: `['input[type="password"]', '[data-mushi-redact]']`
|
|
244
|
+
*
|
|
245
|
+
* To disable the default redaction, pass an empty array.
|
|
246
|
+
*/
|
|
247
|
+
redactSelectors?: string[];
|
|
243
248
|
/** Let reporters remove an attached screenshot before submitting. Defaults to true. */
|
|
244
249
|
allowUserRemoveScreenshot?: boolean;
|
|
245
250
|
}
|
|
@@ -249,6 +254,38 @@ interface MushiProactiveConfig {
|
|
|
249
254
|
longTask?: boolean;
|
|
250
255
|
apiCascade?: boolean | MushiApiCascadeConfig;
|
|
251
256
|
cooldown?: MushiCooldownConfig;
|
|
257
|
+
/**
|
|
258
|
+
* Beta-mode nudge: fire after the user has been on the same route for
|
|
259
|
+
* `thresholdMs` continuous milliseconds (default 5min). Pass `true` to
|
|
260
|
+
* accept the default threshold, or a config object to override. Use
|
|
261
|
+
* conservatively — set the per-session cap in `cooldown` to avoid
|
|
262
|
+
* nag fatigue.
|
|
263
|
+
*/
|
|
264
|
+
pageDwell?: boolean | MushiPageDwellConfig;
|
|
265
|
+
/**
|
|
266
|
+
* One-shot welcome prompt for first-time visitors. Fires `delayMs` after
|
|
267
|
+
* `Mushi.init` (default 45s) and is suppressed permanently after the
|
|
268
|
+
* first fire via localStorage. Recommended for beta deployments.
|
|
269
|
+
*/
|
|
270
|
+
firstSession?: boolean | MushiFirstSessionConfig;
|
|
271
|
+
}
|
|
272
|
+
interface MushiPageDwellConfig {
|
|
273
|
+
/** Continuous dwell time before firing. Defaults to 5 minutes. */
|
|
274
|
+
thresholdMs?: number;
|
|
275
|
+
/**
|
|
276
|
+
* Route path prefixes (or glob-style patterns with `*`) that suppress the
|
|
277
|
+
* dwell nudge. Auth routes are excluded by default so users aren't prompted
|
|
278
|
+
* during login/signup flows.
|
|
279
|
+
*
|
|
280
|
+
* Default: `['/login', '/logout', '/signup', '/sso/*', '/auth/*']`
|
|
281
|
+
*/
|
|
282
|
+
excludeRoutes?: string[];
|
|
283
|
+
}
|
|
284
|
+
interface MushiFirstSessionConfig {
|
|
285
|
+
/** Delay before firing the welcome nudge. Defaults to 45 seconds. */
|
|
286
|
+
delayMs?: number;
|
|
287
|
+
/** Override the localStorage key used to mark the user as welcomed. */
|
|
288
|
+
storageKey?: string;
|
|
252
289
|
}
|
|
253
290
|
type MushiUrlMatcher = string | RegExp;
|
|
254
291
|
interface MushiApiCascadeConfig {
|
|
@@ -704,32 +741,16 @@ interface MushiPerformanceMetrics {
|
|
|
704
741
|
lcp?: number;
|
|
705
742
|
cls?: number;
|
|
706
743
|
fid?: number;
|
|
707
|
-
/**
|
|
708
|
-
* Interaction to Next Paint — the worst-observed user interaction
|
|
709
|
-
* latency (ms) since SDK init. Replaces FID as a Core Web Vital
|
|
710
|
-
* since March 2024. Captured via `PerformanceObserver({ type: 'event',
|
|
711
|
-
* durationThreshold: 40 })` per the [web-vitals INP spec](https://web.dev/articles/inp).
|
|
712
|
-
*/
|
|
713
744
|
inp?: number;
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
* interaction. Lets the triage UI surface "the slow click was on
|
|
717
|
-
* <button.checkout>" rather than just "1200 ms INP".
|
|
718
|
-
*/
|
|
745
|
+
ttfb?: number;
|
|
746
|
+
longTasks?: number;
|
|
719
747
|
inpAttribution?: {
|
|
720
|
-
/** PerformanceEventTiming.name (`pointerdown`, `keydown`, …). */
|
|
721
748
|
eventType?: string;
|
|
722
|
-
/** Tag + id + first class of the element that triggered the slow event. */
|
|
723
749
|
targetSelector?: string;
|
|
724
|
-
/** Time between the user input and the start of event processing. */
|
|
725
750
|
inputDelay?: number;
|
|
726
|
-
/** Time spent running the event handler. */
|
|
727
751
|
processingDuration?: number;
|
|
728
|
-
/** Time between handler end and the next paint. */
|
|
729
752
|
presentationDelay?: number;
|
|
730
753
|
};
|
|
731
|
-
ttfb?: number;
|
|
732
|
-
longTasks?: number;
|
|
733
754
|
}
|
|
734
755
|
interface MushiSelectedElement {
|
|
735
756
|
tagName: string;
|
|
@@ -762,14 +783,7 @@ interface MushiTimelineEntry {
|
|
|
762
783
|
kind: MushiTimelineKind;
|
|
763
784
|
payload: Record<string, unknown>;
|
|
764
785
|
}
|
|
765
|
-
type MushiEventType = 'report:submitted' | 'report:queued' | 'report:sent' | 'report:failed'
|
|
766
|
-
/**
|
|
767
|
-
* Fired when the submitted report has been picked up by a Cursor Cloud
|
|
768
|
-
* Agent and an automated fix is in progress. `data.agentId` is the
|
|
769
|
-
* Cursor agent run ID (bc-…); `data.fixId` is the mushi fix_attempt UUID.
|
|
770
|
-
* Useful for showing a toast: "A Cursor agent is working on your report".
|
|
771
|
-
*/
|
|
772
|
-
| 'report:dispatched' | 'widget:opened' | 'widget:closed' | 'proactive:triggered' | 'proactive:dismissed';
|
|
786
|
+
type MushiEventType = 'report:submitted' | 'report:queued' | 'report:sent' | 'report:failed' | 'widget:opened' | 'widget:closed' | 'proactive:triggered' | 'proactive:dismissed' | 'report:dispatched';
|
|
773
787
|
type MushiEventHandler = (event: {
|
|
774
788
|
type: MushiEventType;
|
|
775
789
|
data?: unknown;
|
|
@@ -786,8 +800,16 @@ interface MushiDiagnosticsResult {
|
|
|
786
800
|
sdkVersion: string;
|
|
787
801
|
}
|
|
788
802
|
interface MushiSDKInstance {
|
|
803
|
+
/**
|
|
804
|
+
* Open the reporter widget. With no options, opens to the category
|
|
805
|
+
* picker so the user can choose between bug categories and the
|
|
806
|
+
* feature-request shortcut. Pass `{ category }` to deep-link into a
|
|
807
|
+
* specific bug intent, or `{ featureRequest: true }` to deep-link into
|
|
808
|
+
* the feature-request description step (skips intent picker).
|
|
809
|
+
*/
|
|
789
810
|
report(options?: {
|
|
790
811
|
category?: MushiReportCategory;
|
|
812
|
+
featureRequest?: boolean;
|
|
791
813
|
}): void;
|
|
792
814
|
on(event: MushiEventType, handler: MushiEventHandler): () => void;
|
|
793
815
|
setUser(user: {
|
|
@@ -888,6 +910,12 @@ interface MushiSDKInstance {
|
|
|
888
910
|
* No-op when rewards are disabled or the user has not opted in.
|
|
889
911
|
*/
|
|
890
912
|
recordActivity(action: string, metadata?: Record<string, unknown>): void;
|
|
913
|
+
/**
|
|
914
|
+
* Briefly animate the bug-report trigger button to draw the user's
|
|
915
|
+
* attention without opening the full widget. Ideal for subtle "feedback
|
|
916
|
+
* welcome" nudges (first-session, beta-onboarding).
|
|
917
|
+
*/
|
|
918
|
+
pulseTrigger(): void;
|
|
891
919
|
}
|
|
892
920
|
interface MushiCaptureExceptionOptions {
|
|
893
921
|
/** Override the default `'bug'` category (e.g. `'slow'` for timeouts). */
|
package/dist/index.d.ts
CHANGED
|
@@ -19,43 +19,12 @@ interface MushiConfig {
|
|
|
19
19
|
integrations?: MushiIntegrationsConfig;
|
|
20
20
|
offline?: MushiOfflineConfig;
|
|
21
21
|
rewards?: MushiRewardsConfig;
|
|
22
|
-
/**
|
|
23
|
-
* Sentry-spec-1.0 hook fired AFTER preFilter / on-device classifier /
|
|
24
|
-
* rate-limit gates pass and BEFORE the report is sent or queued.
|
|
25
|
-
* Return:
|
|
26
|
-
* - the report (possibly modified) → submit as-is
|
|
27
|
-
* - a Promise<MushiReport> → await, then submit
|
|
28
|
-
* - `null` → drop the report silently (no `report:sent`/`:failed` event)
|
|
29
|
-
*
|
|
30
|
-
* Use this for app-level redaction of sensitive metadata, hard-coded
|
|
31
|
-
* tag overrides, or last-mile category routing. Errors thrown inside
|
|
32
|
-
* the hook are caught and logged; the report still ships unchanged so
|
|
33
|
-
* a buggy hook never silently swallows feedback.
|
|
34
|
-
*
|
|
35
|
-
* Mirrors Sentry's [SDK feedback spec §4](https://develop.sentry.dev/sdk/telemetry/feedbacks/)
|
|
36
|
-
* `beforeSendFeedback` callback.
|
|
37
|
-
*/
|
|
38
|
-
beforeSendFeedback?: (report: MushiReport) => MushiReport | Promise<MushiReport | null> | null;
|
|
39
|
-
/**
|
|
40
|
-
* Sentry-spec-1.0 callback fired exactly once on `init()` after the
|
|
41
|
-
* SDK detects that the previous browser session ended in a crash
|
|
42
|
-
* (uncaught exception, unhandled rejection, or hard navigate during
|
|
43
|
-
* unfinished submit). Use it to surface a "Tell us what went wrong?"
|
|
44
|
-
* prompt to the user — the SDK does NOT auto-open the widget so the
|
|
45
|
-
* host app can decide on copy and timing.
|
|
46
|
-
*
|
|
47
|
-
* The promise resolves with `true` when a crash was detected, `false`
|
|
48
|
-
* when the previous run ended cleanly, and `null` when the SDK can't
|
|
49
|
-
* tell (typically: localStorage unavailable, or first-ever load).
|
|
50
|
-
*
|
|
51
|
-
* Mirrors Sentry's [SDK feedback spec §6](https://develop.sentry.dev/sdk/telemetry/feedbacks/)
|
|
52
|
-
* `onCrashedLastRun` hook.
|
|
53
|
-
*/
|
|
54
|
-
onCrashedLastRun?: (info: {
|
|
55
|
-
crashed: boolean | null;
|
|
56
|
-
}) => void;
|
|
57
22
|
debug?: boolean;
|
|
58
23
|
enabled?: boolean;
|
|
24
|
+
/** Hook called before a report is sent. Return null to cancel, or return the (possibly modified) report. */
|
|
25
|
+
beforeSendFeedback?: (report: MushiReport) => MushiReport | null | Promise<MushiReport | null>;
|
|
26
|
+
/** Called once if the app crashed during the previous session. */
|
|
27
|
+
onCrashedLastRun?: (crashed: boolean) => void;
|
|
59
28
|
}
|
|
60
29
|
interface MushiSentryConfig {
|
|
61
30
|
dsn?: string;
|
|
@@ -109,11 +78,36 @@ interface MushiWidgetConfig {
|
|
|
109
78
|
*/
|
|
110
79
|
betaMode?: MushiBetaModeConfig;
|
|
111
80
|
/**
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
81
|
+
* Absolute base URL of the Mushi admin console (e.g. `https://mushi.example.com`).
|
|
82
|
+
* When set, the success step surfaces a one-tap link to the user's own report
|
|
83
|
+
* on the console so they can watch the status change in real time. Without
|
|
84
|
+
* this the success step still confirms submission but cannot deep-link.
|
|
85
|
+
*
|
|
86
|
+
* This is intentionally separate from the API endpoint — production apps
|
|
87
|
+
* usually have the API on `api.mushi.example.com` and the console on
|
|
88
|
+
* `app.mushi.example.com`.
|
|
89
|
+
*/
|
|
90
|
+
dashboardUrl?: string;
|
|
91
|
+
/**
|
|
92
|
+
* Override the SLA copy shown in the success step's "what happens next"
|
|
93
|
+
* line. Defaults to "We aim to review within 48h". Set to an empty string
|
|
94
|
+
* to hide the line entirely (e.g. internal-only deployments where SLA
|
|
95
|
+
* messaging would be over-promising).
|
|
96
|
+
*/
|
|
97
|
+
responseSlaLabel?: string;
|
|
98
|
+
/**
|
|
99
|
+
* Show a first-class "Feature request" card at the top of the category
|
|
100
|
+
* step. Defaults to true. Set to false for production-only deployments
|
|
101
|
+
* where you don't want to invite feature ideas through the widget.
|
|
102
|
+
* Internally this maps to `category='other'` with
|
|
103
|
+
* `user_category='Feature request'` so no DB migration is needed.
|
|
116
104
|
*/
|
|
105
|
+
featureRequestCard?: boolean;
|
|
106
|
+
/** Override the localised label for the feature-request card. */
|
|
107
|
+
featureRequestLabel?: string;
|
|
108
|
+
/** Override the helper text shown under the feature-request card. */
|
|
109
|
+
featureRequestDescription?: string;
|
|
110
|
+
/** Minimum description character count before the submit button enables. */
|
|
117
111
|
minDescriptionLength?: number;
|
|
118
112
|
}
|
|
119
113
|
interface MushiBetaModeConfig {
|
|
@@ -240,6 +234,17 @@ interface MushiPrivacyConfig {
|
|
|
240
234
|
maskSelectors?: string[];
|
|
241
235
|
/** DOM subtrees to remove from screenshots before upload. */
|
|
242
236
|
blockSelectors?: string[];
|
|
237
|
+
/**
|
|
238
|
+
* CSS selectors whose matching elements are blacked-out (filled with an
|
|
239
|
+
* opaque black rectangle) in screenshots before upload. Intended for
|
|
240
|
+
* sensitive fields that should never appear in any form — passwords, PII,
|
|
241
|
+
* financial data. Applied in addition to `maskSelectors`.
|
|
242
|
+
*
|
|
243
|
+
* Default: `['input[type="password"]', '[data-mushi-redact]']`
|
|
244
|
+
*
|
|
245
|
+
* To disable the default redaction, pass an empty array.
|
|
246
|
+
*/
|
|
247
|
+
redactSelectors?: string[];
|
|
243
248
|
/** Let reporters remove an attached screenshot before submitting. Defaults to true. */
|
|
244
249
|
allowUserRemoveScreenshot?: boolean;
|
|
245
250
|
}
|
|
@@ -249,6 +254,38 @@ interface MushiProactiveConfig {
|
|
|
249
254
|
longTask?: boolean;
|
|
250
255
|
apiCascade?: boolean | MushiApiCascadeConfig;
|
|
251
256
|
cooldown?: MushiCooldownConfig;
|
|
257
|
+
/**
|
|
258
|
+
* Beta-mode nudge: fire after the user has been on the same route for
|
|
259
|
+
* `thresholdMs` continuous milliseconds (default 5min). Pass `true` to
|
|
260
|
+
* accept the default threshold, or a config object to override. Use
|
|
261
|
+
* conservatively — set the per-session cap in `cooldown` to avoid
|
|
262
|
+
* nag fatigue.
|
|
263
|
+
*/
|
|
264
|
+
pageDwell?: boolean | MushiPageDwellConfig;
|
|
265
|
+
/**
|
|
266
|
+
* One-shot welcome prompt for first-time visitors. Fires `delayMs` after
|
|
267
|
+
* `Mushi.init` (default 45s) and is suppressed permanently after the
|
|
268
|
+
* first fire via localStorage. Recommended for beta deployments.
|
|
269
|
+
*/
|
|
270
|
+
firstSession?: boolean | MushiFirstSessionConfig;
|
|
271
|
+
}
|
|
272
|
+
interface MushiPageDwellConfig {
|
|
273
|
+
/** Continuous dwell time before firing. Defaults to 5 minutes. */
|
|
274
|
+
thresholdMs?: number;
|
|
275
|
+
/**
|
|
276
|
+
* Route path prefixes (or glob-style patterns with `*`) that suppress the
|
|
277
|
+
* dwell nudge. Auth routes are excluded by default so users aren't prompted
|
|
278
|
+
* during login/signup flows.
|
|
279
|
+
*
|
|
280
|
+
* Default: `['/login', '/logout', '/signup', '/sso/*', '/auth/*']`
|
|
281
|
+
*/
|
|
282
|
+
excludeRoutes?: string[];
|
|
283
|
+
}
|
|
284
|
+
interface MushiFirstSessionConfig {
|
|
285
|
+
/** Delay before firing the welcome nudge. Defaults to 45 seconds. */
|
|
286
|
+
delayMs?: number;
|
|
287
|
+
/** Override the localStorage key used to mark the user as welcomed. */
|
|
288
|
+
storageKey?: string;
|
|
252
289
|
}
|
|
253
290
|
type MushiUrlMatcher = string | RegExp;
|
|
254
291
|
interface MushiApiCascadeConfig {
|
|
@@ -704,32 +741,16 @@ interface MushiPerformanceMetrics {
|
|
|
704
741
|
lcp?: number;
|
|
705
742
|
cls?: number;
|
|
706
743
|
fid?: number;
|
|
707
|
-
/**
|
|
708
|
-
* Interaction to Next Paint — the worst-observed user interaction
|
|
709
|
-
* latency (ms) since SDK init. Replaces FID as a Core Web Vital
|
|
710
|
-
* since March 2024. Captured via `PerformanceObserver({ type: 'event',
|
|
711
|
-
* durationThreshold: 40 })` per the [web-vitals INP spec](https://web.dev/articles/inp).
|
|
712
|
-
*/
|
|
713
744
|
inp?: number;
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
* interaction. Lets the triage UI surface "the slow click was on
|
|
717
|
-
* <button.checkout>" rather than just "1200 ms INP".
|
|
718
|
-
*/
|
|
745
|
+
ttfb?: number;
|
|
746
|
+
longTasks?: number;
|
|
719
747
|
inpAttribution?: {
|
|
720
|
-
/** PerformanceEventTiming.name (`pointerdown`, `keydown`, …). */
|
|
721
748
|
eventType?: string;
|
|
722
|
-
/** Tag + id + first class of the element that triggered the slow event. */
|
|
723
749
|
targetSelector?: string;
|
|
724
|
-
/** Time between the user input and the start of event processing. */
|
|
725
750
|
inputDelay?: number;
|
|
726
|
-
/** Time spent running the event handler. */
|
|
727
751
|
processingDuration?: number;
|
|
728
|
-
/** Time between handler end and the next paint. */
|
|
729
752
|
presentationDelay?: number;
|
|
730
753
|
};
|
|
731
|
-
ttfb?: number;
|
|
732
|
-
longTasks?: number;
|
|
733
754
|
}
|
|
734
755
|
interface MushiSelectedElement {
|
|
735
756
|
tagName: string;
|
|
@@ -762,14 +783,7 @@ interface MushiTimelineEntry {
|
|
|
762
783
|
kind: MushiTimelineKind;
|
|
763
784
|
payload: Record<string, unknown>;
|
|
764
785
|
}
|
|
765
|
-
type MushiEventType = 'report:submitted' | 'report:queued' | 'report:sent' | 'report:failed'
|
|
766
|
-
/**
|
|
767
|
-
* Fired when the submitted report has been picked up by a Cursor Cloud
|
|
768
|
-
* Agent and an automated fix is in progress. `data.agentId` is the
|
|
769
|
-
* Cursor agent run ID (bc-…); `data.fixId` is the mushi fix_attempt UUID.
|
|
770
|
-
* Useful for showing a toast: "A Cursor agent is working on your report".
|
|
771
|
-
*/
|
|
772
|
-
| 'report:dispatched' | 'widget:opened' | 'widget:closed' | 'proactive:triggered' | 'proactive:dismissed';
|
|
786
|
+
type MushiEventType = 'report:submitted' | 'report:queued' | 'report:sent' | 'report:failed' | 'widget:opened' | 'widget:closed' | 'proactive:triggered' | 'proactive:dismissed' | 'report:dispatched';
|
|
773
787
|
type MushiEventHandler = (event: {
|
|
774
788
|
type: MushiEventType;
|
|
775
789
|
data?: unknown;
|
|
@@ -786,8 +800,16 @@ interface MushiDiagnosticsResult {
|
|
|
786
800
|
sdkVersion: string;
|
|
787
801
|
}
|
|
788
802
|
interface MushiSDKInstance {
|
|
803
|
+
/**
|
|
804
|
+
* Open the reporter widget. With no options, opens to the category
|
|
805
|
+
* picker so the user can choose between bug categories and the
|
|
806
|
+
* feature-request shortcut. Pass `{ category }` to deep-link into a
|
|
807
|
+
* specific bug intent, or `{ featureRequest: true }` to deep-link into
|
|
808
|
+
* the feature-request description step (skips intent picker).
|
|
809
|
+
*/
|
|
789
810
|
report(options?: {
|
|
790
811
|
category?: MushiReportCategory;
|
|
812
|
+
featureRequest?: boolean;
|
|
791
813
|
}): void;
|
|
792
814
|
on(event: MushiEventType, handler: MushiEventHandler): () => void;
|
|
793
815
|
setUser(user: {
|
|
@@ -888,6 +910,12 @@ interface MushiSDKInstance {
|
|
|
888
910
|
* No-op when rewards are disabled or the user has not opted in.
|
|
889
911
|
*/
|
|
890
912
|
recordActivity(action: string, metadata?: Record<string, unknown>): void;
|
|
913
|
+
/**
|
|
914
|
+
* Briefly animate the bug-report trigger button to draw the user's
|
|
915
|
+
* attention without opening the full widget. Ideal for subtle "feedback
|
|
916
|
+
* welcome" nudges (first-session, beta-onboarding).
|
|
917
|
+
*/
|
|
918
|
+
pulseTrigger(): void;
|
|
891
919
|
}
|
|
892
920
|
interface MushiCaptureExceptionOptions {
|
|
893
921
|
/** Override the default `'bug'` category (e.g. `'slow'` for timeouts). */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mushi-mushi/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "Core types, API client, and pre-filter for Mushi Mushi SDK",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -62,6 +62,15 @@
|
|
|
62
62
|
"provenance": true
|
|
63
63
|
},
|
|
64
64
|
"sideEffects": false,
|
|
65
|
+
"scripts": {
|
|
66
|
+
"build": "tsup",
|
|
67
|
+
"dev": "tsup --watch",
|
|
68
|
+
"clean": "rm -rf dist .turbo",
|
|
69
|
+
"lint": "eslint src/",
|
|
70
|
+
"typecheck": "tsc --noEmit",
|
|
71
|
+
"test": "vitest run",
|
|
72
|
+
"size": "size-limit"
|
|
73
|
+
},
|
|
65
74
|
"size-limit": [
|
|
66
75
|
{
|
|
67
76
|
"path": "dist/index.js",
|
|
@@ -69,27 +78,18 @@
|
|
|
69
78
|
}
|
|
70
79
|
],
|
|
71
80
|
"devDependencies": {
|
|
81
|
+
"@mushi-mushi/eslint-config": "workspace:*",
|
|
82
|
+
"@mushi-mushi/tsconfig": "workspace:*",
|
|
72
83
|
"@size-limit/file": "^12.1.0",
|
|
73
84
|
"eslint": "^10.3.0",
|
|
74
85
|
"jsdom": "^29.1.1",
|
|
75
86
|
"size-limit": "^12.1.0",
|
|
76
87
|
"tsup": "^8.5.1",
|
|
77
88
|
"typescript": "^6.0.3",
|
|
78
|
-
"vitest": "^4.1.5"
|
|
79
|
-
"@mushi-mushi/eslint-config": "0.0.0",
|
|
80
|
-
"@mushi-mushi/tsconfig": "0.0.0"
|
|
89
|
+
"vitest": "^4.1.5"
|
|
81
90
|
},
|
|
82
91
|
"author": "Kenji Sakuramoto",
|
|
83
92
|
"engines": {
|
|
84
93
|
"node": ">=20"
|
|
85
|
-
},
|
|
86
|
-
"scripts": {
|
|
87
|
-
"build": "tsup",
|
|
88
|
-
"dev": "tsup --watch",
|
|
89
|
-
"clean": "rm -rf dist .turbo",
|
|
90
|
-
"lint": "eslint src/",
|
|
91
|
-
"typecheck": "tsc --noEmit",
|
|
92
|
-
"test": "vitest run",
|
|
93
|
-
"size": "size-limit"
|
|
94
94
|
}
|
|
95
|
-
}
|
|
95
|
+
}
|