@mushi-mushi/core 1.13.0 → 1.15.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 CHANGED
@@ -63,7 +63,7 @@ packages/
63
63
  verify/ Fix verification (BSL)
64
64
  apps/
65
65
  admin/ Admin dashboard (React + Tailwind)
66
- docs/ Documentation site (planned)
66
+ docs/ Documentation site (Nextra — apps/docs)
67
67
  tooling/
68
68
  eslint-config/ Shared ESLint flat config
69
69
  tsconfig/ Shared TypeScript configs
@@ -81,6 +81,28 @@ tooling/
81
81
  ```
82
82
  6. Open a pull request
83
83
 
84
+ ### Documentation (docs-as-code)
85
+
86
+ If your PR changes **user-visible SDK or CLI behavior**, update docs in the **same PR**:
87
+
88
+ | Surface | When to update |
89
+ | --- | --- |
90
+ | `packages/*/README.md` | npm-facing install/API/config changes for that package |
91
+ | `apps/docs/content/**/*.mdx` | Long-form guides, quickstarts, admin console docs |
92
+ | Root `README.md` | Marketing stats only when counts change — run `pnpm check:docs-stats` |
93
+
94
+ Guardrails (run locally before pushing):
95
+
96
+ ```bash
97
+ pnpm check:docs-stats # root README stat badges
98
+ pnpm check:sdk-version-matrix # apps/docs/content/sdks/index.mdx versions
99
+ pnpm check:internal-doc-links # dead /foo links in MDX
100
+ pnpm check:bundle-docs # @mushi-mushi/web size-limit vs README
101
+ pnpm gen:llms-txt # regenerate apps/docs/public/llms.txt after nav changes
102
+ ```
103
+
104
+ README changes on npm packages only appear on [npmjs.com](https://www.npmjs.com) after the next **Changesets publish**.
105
+
84
106
  ## Changesets
85
107
 
86
108
  We use [Changesets](https://github.com/changesets/changesets) for versioning. If your PR modifies a published package (`core`, `web`, `react`, `vue`, `svelte`, `angular`, `react-native`, `cli`, `mcp`), add a changeset:
package/README.md CHANGED
@@ -69,4 +69,4 @@ MIT
69
69
  <!-- mushi-readme-stats-footer -->
70
70
  ---
71
71
 
72
- <sub>Monorepo scale (June 2026): 43 edge functions · 234 SQL migrations · 13 outbound plugins · 11 inbound adapters. 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>
72
+ <sub>Monorepo scale (June 2026): 47 edge functions · 256 SQL migrations · 13 outbound plugins · 11 inbound adapters · 18 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/dist/index.cjs CHANGED
@@ -57,7 +57,7 @@ function createApiClient(options) {
57
57
  maxRetries = DEFAULT_MAX_RETRIES
58
58
  } = options;
59
59
  let baseUrl = apiEndpoint.replace(/\/$/, "");
60
- async function request(method, path, body, retries = maxRetries, internalKind) {
60
+ async function request(method, path, body, retries = maxRetries, internalKind, extraHeaders) {
61
61
  const url = `${baseUrl}${path}`;
62
62
  const controller = new AbortController();
63
63
  const timer = setTimeout(() => controller.abort(), timeout);
@@ -68,7 +68,8 @@ function createApiClient(options) {
68
68
  "Content-Type": "application/json",
69
69
  "X-Mushi-Api-Key": apiKey,
70
70
  "X-Mushi-Project": projectId,
71
- ...internalKind ? { [MUSHI_INTERNAL_HEADER]: internalKind } : {}
71
+ ...internalKind ? { [MUSHI_INTERNAL_HEADER]: internalKind } : {},
72
+ ...extraHeaders
72
73
  },
73
74
  body: body ? JSON.stringify(body) : void 0,
74
75
  signal: controller.signal,
@@ -81,7 +82,7 @@ function createApiClient(options) {
81
82
  const targetBase = target.replace(/\/v1\/.*$/, "").replace(/\/$/, "");
82
83
  if (targetBase !== baseUrl) {
83
84
  baseUrl = targetBase;
84
- return request(method, path, body, retries - 1, internalKind);
85
+ return request(method, path, body, retries - 1, internalKind, extraHeaders);
85
86
  }
86
87
  }
87
88
  }
@@ -89,7 +90,7 @@ function createApiClient(options) {
89
90
  const errorBody = await response.json().catch(() => ({}));
90
91
  if (response.status >= 500 && retries > 0) {
91
92
  await sleep(getBackoffDelay(maxRetries - retries));
92
- return request(method, path, body, retries - 1, internalKind);
93
+ return request(method, path, body, retries - 1, internalKind, extraHeaders);
93
94
  }
94
95
  return {
95
96
  ok: false,
@@ -297,6 +298,69 @@ function createApiClient(options) {
297
298
  1,
298
299
  "reporter-poll"
299
300
  );
301
+ },
302
+ // ─── Cross-app community (in-widget tester identity) ──────────
303
+ async sendMagicLink(email) {
304
+ return request(
305
+ "POST",
306
+ "/v1/tester/magic-link",
307
+ { email },
308
+ 1,
309
+ "community"
310
+ );
311
+ },
312
+ async linkReporterToken(reporterTokenHash, jwt) {
313
+ return request(
314
+ "POST",
315
+ "/v1/tester/link-reporter",
316
+ { reporter_token_hash: reporterTokenHash },
317
+ 1,
318
+ "community",
319
+ { Authorization: `Bearer ${jwt}` }
320
+ );
321
+ },
322
+ async getCrossAppReports(jwt, opts) {
323
+ const qs = new URLSearchParams();
324
+ if (opts?.limit) qs.set("limit", String(opts.limit));
325
+ if (opts?.offset) qs.set("offset", String(opts.offset));
326
+ const suffix = qs.size ? `?${qs.toString()}` : "";
327
+ return request(
328
+ "GET",
329
+ `/v1/tester/cross-app-reports${suffix}`,
330
+ void 0,
331
+ 1,
332
+ "community",
333
+ { Authorization: `Bearer ${jwt}` }
334
+ );
335
+ },
336
+ async getMyReputation(jwt) {
337
+ return request(
338
+ "GET",
339
+ "/v1/tester/reputation",
340
+ void 0,
341
+ 1,
342
+ "community",
343
+ { Authorization: `Bearer ${jwt}` }
344
+ );
345
+ },
346
+ async getPublicLeaderboard(limit = 20) {
347
+ return request(
348
+ "GET",
349
+ `/v1/public/tester-leaderboard?limit=${limit}`,
350
+ void 0,
351
+ 1,
352
+ "reporter-poll"
353
+ );
354
+ },
355
+ async getTesterStatus(jwt) {
356
+ return request(
357
+ "GET",
358
+ "/v1/me/tester-status",
359
+ void 0,
360
+ 1,
361
+ "community",
362
+ { Authorization: `Bearer ${jwt}` }
363
+ );
300
364
  }
301
365
  };
302
366
  }
@@ -515,20 +579,27 @@ function formatPretty(entry) {
515
579
  function formatJson(entry) {
516
580
  return JSON.stringify(entry);
517
581
  }
518
- function emit(level, formatted) {
519
- switch (level) {
520
- case "error":
521
- case "fatal":
582
+ function makeEmitter(destination) {
583
+ if (destination === "stderr") {
584
+ return (level, formatted) => {
522
585
  console.error(formatted);
523
- break;
524
- case "warn":
525
- console.warn(formatted);
526
- break;
527
- default:
528
- console.log(formatted);
586
+ };
529
587
  }
588
+ return (level, formatted) => {
589
+ switch (level) {
590
+ case "error":
591
+ case "fatal":
592
+ console.error(formatted);
593
+ break;
594
+ case "warn":
595
+ console.warn(formatted);
596
+ break;
597
+ default:
598
+ console.log(formatted);
599
+ }
600
+ };
530
601
  }
531
- function buildLogger(scope, minLevel, baseMeta, formatter) {
602
+ function buildLogger(scope, minLevel, baseMeta, formatter, emit) {
532
603
  let currentLevel = minLevel;
533
604
  function log(level, msg, meta) {
534
605
  if (LEVEL_VALUE[level] < LEVEL_VALUE[currentLevel]) return;
@@ -553,7 +624,8 @@ function buildLogger(scope, minLevel, baseMeta, formatter) {
553
624
  `${scope}:${childScope}`,
554
625
  currentLevel,
555
626
  { ...baseMeta, ...childMeta },
556
- formatter
627
+ formatter,
628
+ emit
557
629
  );
558
630
  },
559
631
  setLevel(level) {
@@ -566,11 +638,13 @@ function createLogger(options) {
566
638
  scope,
567
639
  level = "info",
568
640
  meta = {},
569
- format = "auto"
641
+ format = "auto",
642
+ destination = "stdout"
570
643
  } = options;
571
644
  const resolvedFormat = format === "auto" ? detectFormat() : format;
572
645
  const formatter = resolvedFormat === "json" ? formatJson : formatPretty;
573
- return buildLogger(scope, level, meta, formatter);
646
+ const emit = makeEmitter(destination);
647
+ return buildLogger(scope, level, meta, formatter, emit);
574
648
  }
575
649
  var noopLogger = {
576
650
  debug: () => {