@mushi-mushi/core 1.31.0 → 1.31.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +47 -126
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -2,143 +2,64 @@
2
2
 
3
3
  > **Your AI wrote it. Mushi tells you why it broke.**
4
4
 
5
- Core types, API client, and shared utilities for every Mushi SDK package.
6
-
7
- > **You almost certainly don't need to install this directly.** Run `npx mushi-mushi` and the wizard will pick the right framework SDK ([`@mushi-mushi/react`](https://npmjs.com/package/@mushi-mushi/react), [`@mushi-mushi/vue`](https://npmjs.com/package/@mushi-mushi/vue), [`@mushi-mushi/svelte`](https://npmjs.com/package/@mushi-mushi/svelte), [`@mushi-mushi/angular`](https://npmjs.com/package/@mushi-mushi/angular), [`@mushi-mushi/react-native`](https://npmjs.com/package/@mushi-mushi/react-native), [`@mushi-mushi/capacitor`](https://npmjs.com/package/@mushi-mushi/capacitor), or [`@mushi-mushi/web`](https://npmjs.com/package/@mushi-mushi/web)) which depends on this package.
8
-
9
- ## What's Inside
10
-
11
- - **Types**: `MushiConfig`, `MushiReport`, `MushiEnvironment`, and all shared interfaces
12
- - **API Client**: Fetch-based HTTP client with retry and exponential backoff. Tags every internal request with `X-Mushi-Internal: <kind>` so framework SDKs can filter their own traffic out of network capture and `apiCascade`. Ships HMAC-signed reporter helpers (`getLatestSdkVersion`, `listReporterReports`, `listReporterComments`, `replyToReporterReport`) for the two-way reply pipeline, plus `postDiscoveryEvent` (v2.1) for the passive inventory channel
13
- - **Pre-Filter**: On-device Stage 0 spam/gibberish filter (runs client-side, zero server cost)
14
- - **Offline Queue**: IndexedDB-backed queue with auto-sync on reconnect
15
- - **Environment Capture**: Browser/device snapshot — viewport, user agent (with **User-Agent Client Hints** when supported), connection info, screen + DPR, accessibility prefs (`prefers-reduced-motion`, `prefers-color-scheme`, `prefers-contrast`), online/displayMode/title, and a one-shot **page load timing** read from `PerformanceNavigationTiming` (TTFB, DOMContentLoaded, FCP, LCP)
16
- - **Reporter Token**: Anonymous persistent identity for report attribution
17
- - **Session ID**: Tab-scoped session correlation
18
- - **Rate Limiter**: Token bucket self-throttle to prevent API flooding
19
- - **Breadcrumb Buffer** (1.0+ — `createBreadcrumbBuffer`): 50-entry ring of `{timestamp, category, level, message, data?}` rows; framework SDKs auto-capture route changes, `console.error/warn`, `[data-testid]` clicks, and SDK lifecycle events. Snapshot is attached to every `MushiReport` (server promotes it to a dedicated `reports.breadcrumbs` jsonb column for GIN-indexed filtering)
20
- - **Exception Normaliser** (1.0+ — `normaliseThrown`): turns any thrown value (`Error`, string, plain object, `null`, `undefined`) into a stable `{ name, message, stack?, cause? }` shape with truncated stacks and cyclic-cause guards. Powers `Mushi.captureException()` in `@mushi-mushi/web`
21
-
22
- ## Public types added in 0.7 → 0.11
23
-
24
- | Type | Purpose |
25
- |----------------------------|-----------------------------------------------------------------------------------------------|
26
- | `MushiPreset` | Posture bundles: `'production-calm' \| 'beta-loud' \| 'internal-debug' \| 'manual-only'` plus the tiers `'minimal' \| 'standard' \| 'full'`. See [Config presets](#config-presets--precedence). |
27
- | `MushiWidgetAnchor` | Raw-CSS positioning (`top` / `right` / `bottom` / `left`) for the widget launcher. |
28
- | `MushiPrivacyConfig` | `maskSelectors`, `blockSelectors`, `allowUserRemoveScreenshot` for screenshot redaction. |
29
- | `MushiUrlMatcher` | `string \| RegExp` element used by `capture.ignoreUrls` and `apiCascade.ignoreUrls`. |
30
- | `MushiApiCascadeConfig` | Object form of `proactive.apiCascade` so URL filters can be declared per-host-app. |
31
- | `MushiDiagnosticsResult` | Return shape of `Mushi.diagnose()` (CSP, runtime-config, capture, widget health). |
32
- | `MushiSdkVersionInfo` | Response shape for `getLatestSdkVersion(packageName)`; powers the outdated-banner UI. |
33
- | `MushiTimelineEntry` | `{ ts, kind: 'route' \| 'click' \| 'request' \| 'log' \| 'screen', payload }` repro entries. |
34
- | `MushiReporterReport` | Reporter-facing report row (HMAC-authed) with `unread_count` for the widget badge. |
35
- | `MushiReporterComment` | Reporter-facing comment row (HMAC-authed) tagged `author_kind: 'admin' \| 'reporter'`. |
36
- | `MushiDiscoverInventoryConfig` | Mushi v2.1 — fine-grained controls for `capture.discoverInventory` (`enabled`, `throttleMs`, `routeTemplates`, `userIdSource`, `captureDomSummary`). Pass `true` for defaults. |
37
- | `MushiDiscoveryEventPayload` | Mushi v2.1 — wire shape for `POST /v1/sdk/discovery`. Mirrored server-side by `_shared/schemas.ts::discoveryEventSchema`; route + page title + testids + network paths + query-param **keys only** + sha256 user id hash. |
38
- | `MushiBreadcrumb` | 1.0+ — `{ timestamp, category, level: 'debug' \| 'info' \| 'warning' \| 'error' \| 'critical', message, data? }`. Mirrors the Sentry breadcrumb shape so the admin can interleave Mushi + Sentry breadcrumbs on one timeline. |
39
- | `MushiSentryContext` | 1.0+ — rich Sentry handshake the SDK captures via `@sentry/browser` v7/v8/v9: `eventId`, `replayId`, `traceId`, `spanId`, `transaction`, `release`, `environment`, `user`, `tags`, `breadcrumbs`, `issueUrl`, `mushiReportId` (bidirectional). |
40
- | `MushiCaptureExceptionOptions` | 1.0+ — options for `Mushi.captureException(err, opts)`: `level`, `tags`, `extras`, `category`, `userIntent` overrides for the structured report. |
41
- | `NormalisedException` | 1.0+ — return type of `normaliseThrown(err)` (`{ name, message, stack?, cause? }`); used internally by `captureException` and exposed for adapters that want to ship their own thin wrappers. |
42
- | `MushiBannerLink` | 1.8+ — flat action on the rich banner layout: `{ label, href? }` opens an external URL in a new tab, `{ label, featureRequest: true }` opens the widget in feature-request mode. Consumed via `MushiBannerConfig.links`. |
43
- | `screenshotSensitiveHint` (on `MushiWidgetConfig`) | 1.19+ — privacy caption under the screenshot preview: `true` = localized default, `string` = custom copy, `false` = hide caption (preview + Remove remain). Console-configurable via `GET /v1/sdk/config`. See [`docs/SDK_SCREENSHOT_PREVIEW.md`](../../docs/SDK_SCREENSHOT_PREVIEW.md). |
44
-
45
- Constants: `MUSHI_INTERNAL_HEADER` (`'X-Mushi-Internal'`),
46
- `MUSHI_INTERNAL_INIT_MARKER`, and the `MushiInternalRequestKind` literal union
47
- are re-exported so framework adapters can build their own self-noise filters.
48
-
49
- ## Config presets & precedence
50
-
51
- Pass `preset` to pick a posture bundle instead of hand-assembling
52
- `widget` / `capture` / `proactive` flags. `expandPreset(config)` expands the
53
- preset into those nested objects; **your explicit config always wins** on every
54
- key (the merge is per-sub-object, so overriding one `capture` flag keeps the
55
- rest of the preset's defaults).
56
-
57
- | Field | `minimal` | `standard` | `full` |
58
- |----------------------|----------------|--------------------|------------------|
59
- | Widget | on (`auto`) | on (SDK default) | on (`auto`) |
60
- | `capture.console` | ✅ | default | ✅ |
61
- | `capture.network` | ❌ | default | ✅ |
62
- | `capture.performance`| ❌ | default | ✅ |
63
- | `capture.screenshot` | `on-report` | default | `auto` |
64
- | `capture.replay` | `off` | default | `lite` |
65
- | Proactive triggers | none | default | all on |
66
-
67
- - **`minimal`** — widget + console capture only, screenshot on report; no
68
- network/performance/replay, no proactive nudges. Leanest footprint.
69
- - **`standard`** — today's SDK defaults. Expansion is a **no-op** (the config
70
- is returned untouched); the preset exists so the intent is explicit and
71
- documented.
72
- - **`full`** — every capture channel on (including a self-contained `lite`
73
- session replay) and all proactive triggers. Loudest / most data.
74
-
75
- The four legacy postures — `production-calm`, `beta-loud`, `internal-debug`,
76
- `manual-only` — are still supported and expand the same way.
77
-
78
- ### Precedence
79
-
80
- Highest wins. `resolveEnvConfig()` only ever supplies
81
- `projectId` / `apiKey` / `apiEndpoint`, so it never competes with a preset for
82
- the nested option objects.
83
-
84
- | Priority | Source | Example |
85
- |----------|-------------------------------------|-------------------------------------------|
86
- | 1 (wins) | Explicit config | `capture: { network: true }` |
87
- | 2 | `preset` | `preset: 'minimal'` → `network: false` |
88
- | 3 | Environment variables | `NEXT_PUBLIC_MUSHI_*` / `VITE_MUSHI_*` |
89
- | 4 | SDK defaults | built-in fallbacks |
90
-
91
- ### Sampling & `beforeSend`
92
-
93
- Top-level `MushiConfig` fields (consumed by `@mushi-mushi/web` and framework wrappers):
94
-
95
- | Field | Default | Behavior |
96
- |-------|---------|----------|
97
- | `sampleRate` | `1` | Probabilistic gate for **automatic** error reports (`0`–`1`). User-initiated feedback always sends. |
98
- | `replaySampleRate` | `1` | Probabilistic gate for session replay; decided once at session init. Independent of `sampleRate`. |
99
- | `replaysOnErrorSampleRate` | `0` | Start a replay buffer on automatic errors when session sample missed. Keep `0` unless you explicitly want rrweb. |
100
- | `tunnel` | — | Same-origin ingest base (e.g. `/api/mushi-tunnel`). Wins over `apiEndpoint` so browser calls stay first-party. Pagehide uses `fetch` keepalive, then a `{ mushiBeacon, path, headers, body }` envelope because `sendBeacon` cannot set headers. |
101
- | `ignoreErrors` / `denyUrls` / `allowUrls` | — | Drop **automatic** captures only. Never applied to user widget feedback. |
102
- | `beforeSend` | — | `(report) => report \| null \| Promise<…>` after built-in PII scrub. Return `null` to drop. |
103
- | `beforeSendFeedback` | — | Deprecated feedback-only hook; ignored when `beforeSend` is set. |
104
-
105
- ### Validation
106
-
107
- `validateConfig(config)` runs at init and **fails loud but never throws**: it
108
- `console.error`s on unknown top-level keys (usually a typo) and on an invalid
109
- `preset` value, then continues. Set `MUSHI_SILENT=1` to suppress the warnings.
5
+ The shared types, API client and utilities under every [Mushi Mushi](https://github.com/kensaurus/mushi-mushi) SDK.
110
6
 
111
- ```typescript
112
- import { expandPreset, validateConfig } from '@mushi-mushi/core';
7
+ **You probably don't need to install this directly.** Run `npx mushi-mushi` and the wizard installs the SDK for your framework ([`react`](https://npmjs.com/package/@mushi-mushi/react), [`vue`](https://npmjs.com/package/@mushi-mushi/vue), [`svelte`](https://npmjs.com/package/@mushi-mushi/svelte), [`angular`](https://npmjs.com/package/@mushi-mushi/angular), [`react-native`](https://npmjs.com/package/@mushi-mushi/react-native), [`capacitor`](https://npmjs.com/package/@mushi-mushi/capacitor) or [`web`](https://npmjs.com/package/@mushi-mushi/web)), which depends on this one. Reach for `core` when you build your own adapter or need the types.
113
8
 
114
- validateConfig(config); // warns on typos / bad preset (never throws)
115
- const resolved = expandPreset(config); // preset → nested objects, explicit wins
9
+ ```mermaid
10
+ flowchart LR
11
+ A["Framework SDK<br/>react, vue, web…"] --> B["@mushi-mushi/core<br/>types · API client · queue"] --> C["Mushi API"]
116
12
  ```
117
13
 
118
- ## Usage
14
+ ## What's inside
15
+
16
+ | Piece | What it does |
17
+ | --- | --- |
18
+ | Types | `MushiConfig`, `MushiReport`, `MushiEnvironment` and every shared interface |
19
+ | API client (`createApiClient`) | Fetch with retry and backoff. Tags its own requests with `X-Mushi-Internal` so SDKs never report on Mushi |
20
+ | Pre-filter (`createPreFilter`) | On-device spam and gibberish filter, before anything is sent |
21
+ | Offline queue (`createOfflineQueue`) | IndexedDB queue that syncs on reconnect |
22
+ | Environment (`captureEnvironment`) | Viewport, user agent and client hints, connection, accessibility preferences, page-load timing |
23
+ | Identity | Anonymous reporter token (`getReporterToken`) and tab-scoped session id (`getSessionId`) |
24
+ | Rate limiter (`createRateLimiter`) | Token bucket that stops an SDK flooding the API |
25
+ | Breadcrumbs (`createBreadcrumbBuffer`) | 50-entry ring of recent events, in Sentry's breadcrumb shape |
26
+ | Errors (`normaliseThrown`) | Turns any thrown value into `{ name, message, stack?, cause? }` |
27
+
28
+ ## Presets
29
+
30
+ Pass `preset` instead of setting every `widget`, `capture` and `proactive` flag. Your explicit config always wins, key by key.
31
+
32
+ | | `minimal` | `standard` | `full` |
33
+ | --- | --- | --- | --- |
34
+ | Console capture | on | SDK default | on |
35
+ | Network and performance | off | SDK default | on |
36
+ | Screenshot | on report | SDK default | automatic |
37
+ | Session replay | off | SDK default | `lite` |
38
+ | Proactive prompts | none | SDK default | all on |
39
+
40
+ The postures `production-calm`, `beta-loud`, `internal-debug` and `manual-only` also work. Precedence, highest first: **explicit config → `preset` → env vars (`NEXT_PUBLIC_MUSHI_*`, `VITE_MUSHI_*`) → SDK defaults.**
119
41
 
120
42
  ```typescript
121
- import {
122
- createApiClient,
123
- createPreFilter,
124
- captureEnvironment,
125
- createRateLimiter,
126
- MUSHI_INTERNAL_HEADER,
127
- } from '@mushi-mushi/core';
43
+ import { expandPreset, validateConfig } from '@mushi-mushi/core';
44
+
45
+ validateConfig(config); // warns on typos or a bad preset, never throws (MUSHI_SILENT=1 hides it)
46
+ const resolved = expandPreset(config); // preset → nested options, explicit values win
128
47
  ```
129
48
 
130
- This package is used internally by `@mushi-mushi/web` and `@mushi-mushi/react`. Most consumers should use those packages instead.
49
+ ## Sampling and filters
50
+
51
+ Sampling and URL filters apply to **automatic** error reports only, so a report a user sends from the widget is never sampled or filtered out. Only your own `beforeSend` can change or drop it.
131
52
 
132
- ## Bundle Size
53
+ | Field | Default | What it does |
54
+ | --- | --- | --- |
55
+ | `sampleRate` | `1` | Share of automatic error reports to send (`0`–`1`) |
56
+ | `replaySampleRate` | `1` | Share of sessions that record replay |
57
+ | `ignoreErrors` / `denyUrls` / `allowUrls` | — | Drop matching automatic captures |
58
+ | `beforeSend` | — | `(report) => report \| null` for every report, after the PII scrubber. Return `null` to drop |
59
+ | `tunnel` | — | Same-origin ingest path (e.g. `/api/mushi-tunnel`) so ad blockers don't drop reports |
133
60
 
134
- ~3.15 KB brotli (limit: 15 KB)
61
+ Full option reference: [Core SDK docs](https://kensaur.us/mushi-mushi/docs/sdks/core) · [Presets](https://kensaur.us/mushi-mushi/docs/sdks/presets) · [Runtime config](https://kensaur.us/mushi-mushi/docs/concepts/runtime-config).
135
62
 
136
63
  ## License
137
64
 
138
65
  MIT
139
-
140
-
141
- <!-- mushi-readme-stats-footer -->
142
- ---
143
-
144
- <sub>Monorepo scale (July 2026): 64 edge functions · 410 SQL migrations · 13 outbound plugins · 11 inbound adapters · 19 pipeline agents. Canonical counts: <a href="https://github.com/kensaurus/mushi-mushi/blob/master/docs/stats.md">docs/stats.md</a> · <code>pnpm docs-stats</code></sub>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mushi-mushi/core",
3
- "version": "1.31.0",
3
+ "version": "1.31.2",
4
4
  "description": "Types, API client and pre-filter for Mushi SDKs. The bug mediator for AI-built apps: plain-English diagnosis + a ready fix, in your editor.",
5
5
  "license": "MIT",
6
6
  "type": "module",