From d3f353094ccb84e61928cafd421878dc449964ef Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Sat, 5 Sep 2026 01:05:30 +0000 Subject: [PATCH 1/6] build: compile on one Rspack engine with Rslib 1.0 and Rsbuild 2.2 (#566) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bump @rslib/core to 1.0.0 and @rsbuild/core to 2.2.3 in every workspace package, example, and scaffolder template, and @rstest/* to 0.11.12, so a consumer installs one @rspack/core (2.2.2) and one native binding. Compiler (src/build/rslib.ts): output.autoExternal: false (v1 form); URL and worker parsing off for plugin builds so generated `new URL(…)` and `new Worker(new URL(…))` expressions survive verbatim; inspectConfig runs in production mode with NODE_ENV restored; persistent cache off. externalsType stays Rslib's ESM default, which reproduces the 0.x createRequire shim for CommonJS requires of Node builtins. Own sources resolve sibling modules with fileURLToPath + path.join instead of new URL(…, import.meta.url). Tests: lowered-config and packed assertions that plugin output is self-contained (Node builtins the only externals), a packed guard for a single Rspack engine, and inspect coverage under NODE_ENV=development. --- .changeset/rslib-1.md | 14 + docs/effect-conventions.md | 1 - docs/entry-conventions.md | 36 +- examples/audiobook-curator/package.json | 2 +- examples/host-test/package.json | 2 +- examples/mcp-app/package.json | 6 +- examples/rsc-agent-runtime/README.md | 2 +- examples/rsc-agent-runtime/package.json | 4 +- examples/worktree-proximity/package.json | 2 +- package.json | 14 +- packages/agent-bundle/package.json | 4 +- packages/agent-bundle/rslib.config.ts | 11 + packages/agent-bundle/src/build/entries.ts | 17 +- .../agent-bundle/src/build/entry-shell.ts | 23 +- packages/agent-bundle/src/build/rslib.ts | 62 +- .../playground/lifecycle-replay-service.ts | 16 +- .../host-contracts/codex-plugin-validation.ts | 7 +- packages/agent-bundle/tests/build.test.ts | 87 +++ .../tests/inspect-bundler.test.ts | 3 + .../tests/packed-consumer.test.ts | 89 ++- .../tests/public-api-packed.test.ts | 90 ++- .../self-contained-bundler-config.test.ts | 179 +++++ packages/create-agent-bundle/package.json | 4 +- .../create-agent-bundle/src/scaffold-cli.ts | 21 +- .../templates/cli-tool/package_json | 2 +- .../templates/mcp-server/package_json | 2 +- .../templates/minimal/package_json | 2 +- packages/rsc-markdown-stream/package.json | 4 +- packages/rsc-runtime/package.json | 6 +- packages/workbench/package.json | 2 +- pnpm-lock.yaml | 654 +++++++----------- pnpm-workspace.yaml | 4 - rstest.integration-tests.ts | 1 + .../en/guide/authoring/package-entries.mdx | 20 +- website/docs/en/reference/cli.mdx | 2 +- website/docs/en/reference/configuration.mdx | 13 +- .../zh/guide/authoring/package-entries.mdx | 15 +- website/docs/zh/reference/cli.mdx | 2 +- website/docs/zh/reference/configuration.mdx | 9 +- 39 files changed, 899 insertions(+), 535 deletions(-) create mode 100644 .changeset/rslib-1.md create mode 100644 packages/agent-bundle/tests/self-contained-bundler-config.test.ts diff --git a/.changeset/rslib-1.md b/.changeset/rslib-1.md new file mode 100644 index 000000000..62e6738bf --- /dev/null +++ b/.changeset/rslib-1.md @@ -0,0 +1,14 @@ +--- +"agent-bundle": patch +"@agent-bundle/runtime": patch +"create-agent-bundle": patch +--- + +Build on Rslib 1.0 and Rsbuild 2.2 so a project installs one Rspack engine and one native +binding instead of two; `create-agent-bundle` templates pin `@rstest/core` 0.11.12. Plugin +builds stay self-contained (`output.autoExternal: false`, Node builtins the only externals) and +keep `new URL(…, import.meta.url)` and `new Worker(new URL(…))` expressions verbatim. +`agent-bundle inspect --bundler` lowers in production mode regardless of `NODE_ENV` and shows the +new `bundlerChain` invariant beside `tools.rspack`. Published `.d.ts` files now import their +siblings with `.js` specifiers, and `@agent-bundle/runtime`'s shared chunks are named +`~0.js`; every `exports` entry resolves as before. (#PR) diff --git a/docs/effect-conventions.md b/docs/effect-conventions.md index 996242b1f..2e1a2f2f4 100644 --- a/docs/effect-conventions.md +++ b/docs/effect-conventions.md @@ -853,7 +853,6 @@ soon as the trigger fires and retire the row. | Recorded | Pin (where) | Observed registry state | Trigger / action | | --- | --- | --- | --- | -| 2026-09-03 | `@rslib/core` **`0.23.2`** — root, `packages/agent-bundle`, `packages/rsc-runtime`, `packages/create-agent-bundle` devDependencies. Stays on `0.23.x` until rslib 1.0 leaves rc. | `npm view @rslib/core dist-tags`: `latest` `0.23.2`, `rc` `1.0.0-rc.2`, `beta` `1.0.0-beta.3`, `canary` `0.20.0-canary-202603101`. | `latest` becomes `1.x`. Bump all four pins in one chore; re-run `pnpm build` (publint runs inside it), `check:release`, and the Rslib-driven compile tests. | | 2026-09-03 | `effect-rstest` **pkg.pr.new preview `e5f8d5f`** (`https://pkg.pr.new/ScriptedAlchemy/effect-rstest@e5f8d5f`) — `packages/agent-bundle`, `packages/rsc-runtime`, `packages/create-agent-bundle` devDependencies (three pins). Needs a real release pin once published. | `npm view effect-rstest versions`: **E404 — not published to npm** (no versions, no dist-tags). | First npm publish of `effect-rstest`. Replace all three preview URLs with the exact published version, refresh `pnpm-lock.yaml`, re-run `pnpm test:unit` (`it.effect` / `it.live` suites). | | 2026-09-03 | `effect` **`4.0.0-rc.112`** (`packages/agent-bundle`, `packages/rsc-runtime`, `packages/workbench`, `packages/create-agent-bundle`), `@effect/atom-react` `4.0.0-rc.112` (`packages/workbench`), `@effect/platform-node` `4.0.0-rc.112` (`packages/create-agent-bundle`), `@effect/platform-node-shared` `4.0.0-rc.112` (`packages/agent-bundle`), `@effect/language-service` `0.87.2` and `@effect/tsgo` `0.39.0` (root). Auto re-pin in lockstep + `repos/effect` subtree + Workbench atom phase 4 unblock (stream-backed derived atoms) once the post-rc.112 disposal fix ships. | `npm view effect dist-tags`: `rc` **`4.0.0-rc.112`** (unchanged), `beta` `4.0.0-beta.107`, `latest` `3.22.1`. `@effect/atom-react`: `rc` `4.0.0-rc.112`. `@effect/language-service`: `latest` `0.87.2`. `@effect/tsgo`: `latest` `0.39.1` (patch ahead of the `0.39.0` pin; rides the lockstep chore). | `effect@rc` advances past `4.0.0-rc.112`. Run the re-pin chore steps 1–6 above, bumping `effect`, `@effect/atom-react`, `@effect/language-service`, and `@effect/tsgo` together, then lift the stream-backed derived-atom ban in the Workbench if the disposal fix is in the new RC. | | 2026-09-03 | Agent Plugins specification **`1.0.0`** — `packages/agent-bundle/src/adapters/schemas/portable/{plugin,mcp}.schema.json` + `PROVENANCE.json` (spec repo `agentplugins/agent-plugins-spec` @ `ff8ab5e392cc87bd88d87c060815a87490e51003`, 2026-08-19), portable `adapterRevision` `1.8.0`, pins in `tests/adapter-metadata.test.ts`. Spec watch for #426; not an npm pin, so re-verify with `curl`/`gh api`, not `npm view`. | Live `https://agent-plugins.org/schemas/1.0.0/{plugin,mcp}.schema.json` rehash to the pinned sha256 (1805 / 3408 bytes). Repo `main` HEAD unchanged at the pinned commit; **no tags, no GitHub releases**. `spec/1.1.0.md` is "Status: Working Draft" (started 2026-08-15, `a2afd7ec`); in-repo `schemas/1.1.0/*.schema.json` differ from 1.0.0 only in the `$id`/`const`/`description` version strings; `https://agent-plugins.org/schemas/1.1.0/*.schema.json` → 404. Observed latest published version: **1.0.0**. | `spec/1.1.0.md` (or later) flips to "Published" **and** `agent-plugins.org/schemas//` serves both schemas. Re-pin under `schemas/portable/` with a dated `PROVENANCE.json` (sha/bytes/date/commit), bump the portable `adapterRevision`, refresh the metadata pins, run `pnpm test:unit` (portable adapter + plugin-validation suites) and `pnpm test:host-install:build`, and add a capability row per additive field. | diff --git a/docs/entry-conventions.md b/docs/entry-conventions.md index d68a201c3..b8fc9f3a0 100644 --- a/docs/entry-conventions.md +++ b/docs/entry-conventions.md @@ -1206,8 +1206,13 @@ way: a hatch that externalizes `agent-bundle/mcp-entry` or a generated module specifier (`agent-bundle/meta`, or a registry specifier such as `agent-bundle/mcp-apps`) fails the build with a hard diagnostic — at config inspection for statically visible `externals`, and through a post-build scan of the emitted bundle for function-form -`externals` — because generated executables must stay self-contained. The -hatch customizes *how code compiles*, never *what the artifact promises*. +`externals` — because generated executables must stay self-contained. +Run-time path references are kept the same way: a `new URL(…, import.meta.url)` +or `new Worker(new URL(…))` in consumer or generated code names a file beside +the artifact, so the invariant layer turns the bundler's URL and worker asset +processing off after the hatch and the expression reaches the artifact +verbatim. The hatch customizes *how code compiles*, never *what the artifact +promises*. The hatch merges *beside* the framework profile, not over it: `plugins` arrays concatenate, and Rsbuild's plugin manager appends every plugin it is @@ -1219,16 +1224,17 @@ reports that as `AB4724` (an error, like the other `tools` shape checks) with the plugin and package name; remove the entry, the framework already registers it. -The hatch executes under two different bundler engine copies. Artifact -scripts, MCP entries, hook wrappers, and the package build compile through -Rslib, which runs the Rsbuild/Rspack versions nested inside `@rslib/core` -(currently the 2.1.x line); MCP App views compile through the -workspace-pinned `@rsbuild/core` (currently 2.2.x), until Rslib catches up to -the Rsbuild 2.2 line. So a hatch must never construct plugins or run -`instanceof` checks against an imported `@rspack/core`: a class imported from -a separately installed `@rspack/core` has a different identity than whichever -engine executes the config. Use instead the utils argument Rslib/Rsbuild pass -to `tools.rspack` mutator functions — +The hatch executes on one bundler engine. Artifact scripts, MCP entries, +hook wrappers, and the package build compile through Rslib; MCP App views +compile through `@rsbuild/core`; and agent-bundle pins `@rsbuild/core` inside +the range its `@rslib/core` accepts, so a consumer installs a single +`@rsbuild/core`, a single `@rspack/core`, and a single native Rspack binding +(a packed-consumer test holds that line). That engine is agent-bundle's +dependency, not the consumer's: a class imported from a separately installed +`@rspack/core` can have a different identity than the engine executing the +config. So a hatch must never construct plugins or run `instanceof` checks +against an imported `@rspack/core`. Use instead the utils argument +Rslib/Rsbuild pass to `tools.rspack` mutator functions — `tools: { rspack: (config, { rspack }) => { ... } }` — which always hands the engine's own `rspack` object. @@ -1281,9 +1287,9 @@ agent-bundle inspect --bundler [--target ] [--json] Dumps the synthesized bundler configuration for every output the build composes — artifact scripts, MCP entries, hook wrappers, the per-target MCP Apps Rsbuild config, and the `dist/` package build — exactly as the build -lowers it: the framework profile with the consumer `tools` hatch merged over -it and the invariant hook appended last (functions render as -`[function ]`). Entries the framework wraps also carry the generated +lowers it: in production mode whatever `NODE_ENV` says, the framework profile +with the consumer `tools` hatch merged over it and the invariant hook appended +last (functions render as `[function ]`). Entries the framework wraps also carry the generated wrapper module source (`generatedEntry`). The composition comes from the same functions the build uses, so the dump cannot drift from what compiles. diff --git a/examples/audiobook-curator/package.json b/examples/audiobook-curator/package.json index 6801c5138..51604f8b7 100644 --- a/examples/audiobook-curator/package.json +++ b/examples/audiobook-curator/package.json @@ -32,7 +32,7 @@ }, "devDependencies": { "@agent-bundle/runtime": "workspace:*", - "@rstest/core": "0.11.10", + "@rstest/core": "0.11.12", "@types/react": "19.2.18", "agent-bundle": "workspace:*", "react": "19.2.8", diff --git a/examples/host-test/package.json b/examples/host-test/package.json index f967c19ed..d3b3d8809 100644 --- a/examples/host-test/package.json +++ b/examples/host-test/package.json @@ -30,7 +30,7 @@ "devDependencies": { "@agent-bundle/runtime": "workspace:*", "@modelcontextprotocol/server": "2.0.0", - "@rstest/core": "0.11.10", + "@rstest/core": "0.11.12", "@types/react": "19.2.18", "agent-bundle": "workspace:*", "react": "19.2.8", diff --git a/examples/mcp-app/package.json b/examples/mcp-app/package.json index 00af95fa4..bee9f0615 100644 --- a/examples/mcp-app/package.json +++ b/examples/mcp-app/package.json @@ -14,9 +14,9 @@ "devDependencies": { "@modelcontextprotocol/ext-apps": "1.7.5", "@modelcontextprotocol/server": "2.0.0", - "@rstest/browser": "0.11.10", - "@rstest/core": "0.11.10", - "@rstest/playwright": "0.11.10", + "@rstest/browser": "0.11.12", + "@rstest/core": "0.11.12", + "@rstest/playwright": "0.11.12", "agent-bundle": "workspace:*", "playwright": "1.62.1", "zod": "4.5.4" diff --git a/examples/rsc-agent-runtime/README.md b/examples/rsc-agent-runtime/README.md index fef1170d3..1fdfa79a7 100644 --- a/examples/rsc-agent-runtime/README.md +++ b/examples/rsc-agent-runtime/README.md @@ -311,7 +311,7 @@ for stateless consumers because the driver lives behind its own subpath. It is suitable local single-workspace storage, not concurrent/distributed production storage. The RSC-facing packages are exact pins because their framework-facing surface is not treated as stable here: React `19.2.8`, `react-dom` `19.2.8`, -`react-server-dom-rspack` `0.1.0`, Rsbuild `2.2.1`, and `rsbuild-plugin-rsc` +`react-server-dom-rspack` `0.1.0`, Rsbuild `2.2.3`, and `rsbuild-plugin-rsc` `0.1.1`. Existing Agent Bundle skills, static MCPs, evaluations, and normal hooks neither require nor activate this runtime. Nothing under `packages/agent-bundle` imports the example or React/RSC runtime packages. diff --git a/examples/rsc-agent-runtime/package.json b/examples/rsc-agent-runtime/package.json index 42450c5d5..6c9ad9e04 100644 --- a/examples/rsc-agent-runtime/package.json +++ b/examples/rsc-agent-runtime/package.json @@ -25,9 +25,9 @@ "zod": "4.5.4" }, "devDependencies": { - "@rsbuild/core": "2.2.1", + "@rsbuild/core": "2.2.3", "@rsbuild/plugin-react": "2.1.0", - "@rstest/core": "0.11.10", + "@rstest/core": "0.11.12", "@types/express": "5.0.6", "@types/react": "19.2.18", "@types/react-dom": "19.2.5", diff --git a/examples/worktree-proximity/package.json b/examples/worktree-proximity/package.json index f4272c2d8..1c3b142b4 100644 --- a/examples/worktree-proximity/package.json +++ b/examples/worktree-proximity/package.json @@ -23,7 +23,7 @@ }, "devDependencies": { "@agent-bundle/runtime": "workspace:*", - "@rstest/core": "0.11.10", + "@rstest/core": "0.11.12", "@types/react": "19.2.18", "agent-bundle": "workspace:*", "react": "19.2.8", diff --git a/package.json b/package.json index 36d6b6c22..8327aa2c3 100644 --- a/package.json +++ b/package.json @@ -65,15 +65,15 @@ "@effect/tsgo": "0.39.0", "@modelcontextprotocol/conformance": "0.1.16", "@modelcontextprotocol/server": "2.0.0", - "@rsbuild/core": "2.2.1", + "@rsbuild/core": "2.2.3", "@rsbuild/plugin-react": "2.1.0", - "@rslib/core": "0.23.2", + "@rslib/core": "1.0.0", "@rslint/core": "0.8.2", - "@rstest/adapter-rslib": "0.11.10", - "@rstest/browser": "0.11.10", - "@rstest/browser-react": "0.11.10", - "@rstest/core": "0.11.10", - "@rstest/playwright": "0.11.10", + "@rstest/adapter-rslib": "0.11.12", + "@rstest/browser": "0.11.12", + "@rstest/browser-react": "0.11.12", + "@rstest/core": "0.11.12", + "@rstest/playwright": "0.11.12", "@types/node": "26.4.0", "agent-bundle": "workspace:*", "commander": "15.0.0", diff --git a/packages/agent-bundle/package.json b/packages/agent-bundle/package.json index 49ca5535e..1c50dfa4b 100644 --- a/packages/agent-bundle/package.json +++ b/packages/agent-bundle/package.json @@ -98,9 +98,9 @@ "@modelcontextprotocol/client": "2.0.0", "@modelcontextprotocol/node": "2.0.0", "@modelcontextprotocol/server": "2.0.0", - "@rsbuild/core": "2.2.1", + "@rsbuild/core": "2.2.3", "@rsbuild/plugin-react": "2.1.0", - "@rslib/core": "0.23.2", + "@rslib/core": "1.0.0", "@rslint/core": "0.8.2", "@rstackjs/load-config": "0.1.2", "acorn": "8.18.0", diff --git a/packages/agent-bundle/rslib.config.ts b/packages/agent-bundle/rslib.config.ts index 94b02cdbb..76bd53803 100644 --- a/packages/agent-bundle/rslib.config.ts +++ b/packages/agent-bundle/rslib.config.ts @@ -85,6 +85,17 @@ export default defineConfig({ // extractor never reaches it. config.ignoreWarnings = [...(config.ignoreWarnings ?? []), /Can't resolve 'source-map-support'/u]; config.node = { ...(typeof config.node === 'object' ? config.node : {}), __dirname: false, __filename: false }; + // `externalsType` stays Rslib 1.x's ESM default, `modern-module`, on + // purpose. The only externals this bundle loads through CommonJS + // `require()` are the Node builtins the bundled TypeScript parser + // reads (`fs`, `path`, `os`, `crypto`, `inspector`, `perf_hooks`), and + // Rslib 0.x already emitted those through a `createRequire()` shim + // chunk; `modern-module` reproduces that chunk byte for byte, while + // pinning `module-import` would turn them into hoisted + // `import * as` namespaces — a change, not a preservation. The shim + // chunk is reachable only from the parser chunk, never from the + // runtime entries the compiler re-bundles into consumer artifacts, so + // the artifact bundler never has to see through a `createRequire()`. }, }, source: { diff --git a/packages/agent-bundle/src/build/entries.ts b/packages/agent-bundle/src/build/entries.ts index 093faf16d..937e2f048 100644 --- a/packages/agent-bundle/src/build/entries.ts +++ b/packages/agent-bundle/src/build/entries.ts @@ -1,6 +1,6 @@ import { existsSync } from 'node:fs'; import { readFile, stat } from 'node:fs/promises'; -import { basename, dirname, extname, relative, resolve } from 'node:path'; +import { basename, dirname, extname, join, relative, resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; import type { NoticeDeliveryAdvertisement } from '../adapters/notice-delivery.ts'; @@ -49,13 +49,18 @@ import type { CompiledMcpApp } from './mcp-apps.ts'; import type { ArtifactOutputKind } from './provenance.ts'; import type { RslibEntry, RslibSurfacePlan } from './rslib.ts'; +/** + * Spelled as paths, not `new URL(…, import.meta.url)`: the package's own + * Rslib build would otherwise read the template as a directory context and + * replace it with a lookup that throws at run time. + */ const eventRuntimeModulePath = (module: 'ipc' | 'project'): string => { - for (const candidate of [ - new URL(`./event-${module}.js`, import.meta.url), - new URL(`../../dist/event-${module}.js`, import.meta.url), - new URL(`../events/${module}.ts`, import.meta.url), + const here = dirname(fileURLToPath(import.meta.url)); + for (const path of [ + join(here, `event-${module}.js`), + join(here, '..', '..', 'dist', `event-${module}.js`), + join(here, '..', 'events', `${module}.ts`), ]) { - const path = fileURLToPath(candidate); if (existsSync(path)) return path; } throw new Error(`Unable to locate the compiler-owned event ${module} runtime module.`); diff --git a/packages/agent-bundle/src/build/entry-shell.ts b/packages/agent-bundle/src/build/entry-shell.ts index 014ece222..b4ab4899c 100644 --- a/packages/agent-bundle/src/build/entry-shell.ts +++ b/packages/agent-bundle/src/build/entry-shell.ts @@ -1,4 +1,5 @@ import { existsSync } from 'node:fs'; +import { dirname, join } from 'node:path'; import { fileURLToPath } from 'node:url'; import { eventIpcRuntimeSpecifier, eventProjectRuntimeSpecifier } from '../adapters/hook-contract.ts'; @@ -36,14 +37,13 @@ const noticeInboxRuntimeSpecifier = '@agent-bundle/runtime/notices/inbox-route'; * the emitted artifact (artifacts must stay self-contained). From the bundled * package this module's URL is `dist/.js` with `.js` as a * sibling; from checked-out sources it is `src/build/entry-shell.ts` with - * `../.ts`. + * `../.ts`. Spelled as paths, not `new URL(…, import.meta.url)`: the + * package's own Rslib build would otherwise read the template as a directory + * context and replace it with a lookup that throws at run time. */ const runtimeModulePath = (name: string): string => { - for (const candidate of [ - new URL(`./${name}.js`, import.meta.url), - new URL(`../${name}.ts`, import.meta.url), - ]) { - const path = fileURLToPath(candidate); + const here = dirname(fileURLToPath(import.meta.url)); + for (const path of [join(here, `${name}.js`), join(here, '..', `${name}.ts`)]) { if (existsSync(path)) return path; } throw new Error(`Unable to locate the agent-bundle/${name} runtime module for generated entries.`); @@ -158,16 +158,7 @@ export const cliEntryRuntimeSpecifier = 'agent-bundle/cli-entry'; * aliased into generated CLI executables exactly like the mcp-entry * lifecycle so emitted bins stay self-contained. */ -export const cliEntryRuntimePath = (): string => { - for (const candidate of [ - new URL('./cli-entry.js', import.meta.url), - new URL('../cli-entry.ts', import.meta.url), - ]) { - const path = fileURLToPath(candidate); - if (existsSync(path)) return path; - } - throw new Error('Unable to locate the agent-bundle/cli-entry runtime module for generated CLI executables.'); -}; +export const cliEntryRuntimePath = (): string => runtimeModulePath('cli-entry'); export const installEntryRuntimeSpecifier = 'agent-bundle/install-entry'; diff --git a/packages/agent-bundle/src/build/rslib.ts b/packages/agent-bundle/src/build/rslib.ts index 837c75cb0..8c9707f08 100644 --- a/packages/agent-bundle/src/build/rslib.ts +++ b/packages/agent-bundle/src/build/rslib.ts @@ -58,6 +58,38 @@ export interface RslibEntry { } type RslibInstance = Awaited>; +type RslibBundlerChain = Exclude['bundlerChain']>, readonly unknown[]>; + +/** + * Rslib 1.x adds a module rule (its `NEW_URL_RULE`, `rslib:new-url`) whose + * rule-level `parser.javascript.url` outranks the global parser option + * `composeEntryLibConfig` pins off, so the rule's own option is turned off + * too: a `new URL(…, import.meta.url)` in plugin or generated code names a + * run-time path, not an asset to emit. + */ +const preserveResourceReferences: RslibBundlerChain = (chain) => { + chain.module.rule('rslib:new-url').parser({ url: false }); +}; + +/** + * Lowers the composed lib configs to bundler configs, always as the + * production build `rslib.build()` runs. Rslib 1.x otherwise infers the mode + * from `NODE_ENV`, and under `development` inspects only `mf` libs — none + * here — so `assertExecutableConfig` and `inspect --bundler` would fail. Rslib + * writes the inspected mode back to `NODE_ENV`; a process that had set it + * (a development server, a test runner) keeps its own value, while an unset + * one is left at `production`, exactly as `rslib.build()` leaves it. + */ +const inspectProductionConfig = async ( + rslib: Pick, +): Promise>> => { + const nodeEnv = process.env.NODE_ENV; + try { + return await rslib.inspectConfig({ mode: 'production' }); + } finally { + if (nodeEnv !== undefined) process.env.NODE_ENV = nodeEnv; + } +}; type RslibLibConfig = LibConfig; type RslibToolsRspack = NonNullable['rspack']>; @@ -529,6 +561,22 @@ export const composeEntryLibConfig = ( ]); const enforceInvariants = (config: Rspack.Configuration): Rspack.Configuration => { config.output = { ...config.output, asyncChunks: false }; + // Rslib 1.x treats a statically analyzable `new URL(…, import.meta.url)` + // as a static asset to emit and `new Worker(new URL(…))` as a worker + // entry to bundle. Generated entries spell their sibling Flight worker + // and their artifact root exactly that way, naming files that exist only + // in the build output, and consumer code points at run-time filesystem + // paths beside the artifact. Both parsers stay off, as Rslib 0.x left + // them, so every such expression survives into the artifact verbatim; + // `preserveResourceReferences` switches Rslib's own `rslib:new-url` rule + // off for the same reason (a rule-level parser option outranks this one). + config.module = { + ...config.module, + parser: { + ...config.module?.parser, + javascript: { ...config.module?.parser?.javascript, url: false, worker: false }, + }, + }; if (entry.reactServer === true) { config.resolve = { ...config.resolve, conditionNames: ['react-server', '...'] }; } @@ -610,7 +658,6 @@ export const composeEntryLibConfig = ( }; const profile: RslibLibConfig = { id: libId, - autoExternal: false, ...(entry.banner === undefined ? {} : { banner: { js: entry.banner } }), bundle: true, dts: entry.dts === true, @@ -632,6 +679,10 @@ export const composeEntryLibConfig = ( splitChunks: false, syntax: 'es2022', output: { + // Nothing is externalized by declaration: an artifact is self-contained, + // and AB7014/AB7015 judge the consumer's declared dependencies against + // what the bundle actually reached. + autoExternal: false, distPath: { root: options.outputRoot }, filename: { js: entry.outputRelativePath }, filenameHash: false, @@ -640,6 +691,10 @@ export const composeEntryLibConfig = ( sourceMap: false, target: 'node', }, + // `externalsType` stays Rslib's ESM default (`modern-module`): a CommonJS + // `require()` of a Node builtin inside a bundled dependency reaches the + // artifact as the same `createRequire()` shim Rslib 0.x emitted for it + // (`packages/agent-bundle/rslib.config.ts` has the comparison). source: { // Always the authored program, even when a generated wrapper is the // real compilation root: Rslib checks that every entry exists on disk, @@ -653,8 +708,9 @@ export const composeEntryLibConfig = ( }; // Every layer is keyed by the synthesized lib id so `mergeRslibConfig` // folds them into one lib entry in `composeToolsLayers` order. + const invariants = frameworkInvariantLayer(enforceInvariants); const merged = mergeRslibConfig(...composeToolsLayers({ - invariants: { id: libId, ...frameworkInvariantLayer(enforceInvariants) }, + invariants: { id: libId, ...invariants, tools: { ...invariants.tools, bundlerChain: preserveResourceReferences } }, lift: { rsbuild: (fragment) => ({ ...asRslibEnvironmentFragment(fragment), id: libId }), rspack: (hatch) => ({ id: libId, tools: { rspack: asRslibRspackHatch(hatch) } }), @@ -767,7 +823,7 @@ export const buildRslibSurfaces = async ( }, }); - const inspection = await rslib.inspectConfig(); + const inspection = await inspectProductionConfig(rslib); assertExecutableConfig(entries, inspection.origin, options); let result: Awaited> | undefined; try { diff --git a/packages/agent-bundle/src/dev/playground/lifecycle-replay-service.ts b/packages/agent-bundle/src/dev/playground/lifecycle-replay-service.ts index 0a6cafebe..24dba928f 100644 --- a/packages/agent-bundle/src/dev/playground/lifecycle-replay-service.ts +++ b/packages/agent-bundle/src/dev/playground/lifecycle-replay-service.ts @@ -182,17 +182,23 @@ const lazyRenderRouteEvents: typeof renderRouteEvents = async (target, options) return renderer.renderRouteEvents(target, options); }; -/** Synchronous probe from a sync resolver; stays on `node:fs` (no `FileSystem` sync API). */ +/** + * Synchronous probe from a sync resolver; stays on `node:fs` (no `FileSystem` + * sync API). Spelled as paths, not `new URL(…, import.meta.url)`: the + * package's own Rslib build would otherwise copy the child into the bundle's + * static assets and point the URL there. + */ const lifecycleRenderChildPath = (): string => { const current = fileURLToPath(import.meta.url); + const here = dirname(current); const candidates = current.endsWith('.ts') ? [ - fileURLToPath(new URL('./lifecycle-render-child.ts', import.meta.url)), - fileURLToPath(new URL('../../../dist/lifecycle-render-child.js', import.meta.url)), + join(here, 'lifecycle-render-child.ts'), + join(here, '..', '..', '..', 'dist', 'lifecycle-render-child.js'), ] : [ - fileURLToPath(new URL('./lifecycle-render-child.js', import.meta.url)), - fileURLToPath(new URL('./lifecycle-render-child.ts', import.meta.url)), + join(here, 'lifecycle-render-child.js'), + join(here, 'lifecycle-render-child.ts'), resolve(process.cwd(), 'packages/agent-bundle/src/dev/playground/lifecycle-render-child.ts'), ]; for (const candidate of candidates) { diff --git a/packages/agent-bundle/src/host-contracts/codex-plugin-validation.ts b/packages/agent-bundle/src/host-contracts/codex-plugin-validation.ts index c6decfd6d..2837a02b1 100644 --- a/packages/agent-bundle/src/host-contracts/codex-plugin-validation.ts +++ b/packages/agent-bundle/src/host-contracts/codex-plugin-validation.ts @@ -1,5 +1,6 @@ import { readFile, readdir } from 'node:fs/promises'; import { dirname, join, resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; import { Effect, FileSystem, Option } from 'effect'; import type { PlatformError } from 'effect/PlatformError'; @@ -208,14 +209,16 @@ const compareGeneratedSchemas = async ( strict: boolean, target: string, ): Promise => { - const pinnedDirectory = new URL('../adapters/schemas/codex/generated/', import.meta.url); + // A path, not `new URL(…, import.meta.url)`: the package's own Rslib build + // would otherwise try to bundle the directory as a static asset. + const pinnedDirectory = join(dirname(fileURLToPath(import.meta.url)), '..', 'adapters', 'schemas', 'codex', 'generated'); const missing: string[] = []; const changed: string[] = []; for (const name of generatedSchemaNames) { try { const [live, pinned] = await Promise.all([ readFile(join(liveDirectory, name)), - readFile(new URL(name, pinnedDirectory)), + readFile(join(pinnedDirectory, name)), ]); if (sha256Hex(live) !== sha256Hex(pinned)) changed.push(name); } catch (error) { diff --git a/packages/agent-bundle/tests/build.test.ts b/packages/agent-bundle/tests/build.test.ts index ceec3224a..c1b0d1e0c 100644 --- a/packages/agent-bundle/tests/build.test.ts +++ b/packages/agent-bundle/tests/build.test.ts @@ -5,6 +5,7 @@ import { dirname, join, relative } from 'node:path'; import { fileURLToPath, pathToFileURL } from 'node:url'; import { expect, it } from '@rstest/core'; import { spawn } from 'node:child_process'; +import { createRslib } from '@rslib/core'; import { createJiti } from 'jiti'; import { build as buildArtifact, type BuildOptions as LowLevelBuildOptions, type BuildResult } from '../src/build/build.ts'; @@ -1162,6 +1163,92 @@ it('inlines reserved specifiers through exact-match aliases and virtual generate } }, 20_000); +it('lowers every bundler config and builds under NODE_ENV=development, leaving NODE_ENV as it found it', async () => { + const { entry, root } = await reservedSpecifierProject(); + const previousNodeEnv = process.env.NODE_ENV; + const inspectedConfigCounts: number[] = []; + process.env.NODE_ENV = 'development'; + try { + await buildWithRslib({ cwd: root, entries: [entry], meta: testMeta, outputRoot: join(root, 'dist') }, { + createRslib: async (options) => { + const rslib = await createRslib(options); + return { + build: (buildOptions) => rslib.build(buildOptions), + inspectConfig: async (inspectOptions) => { + const inspection = await rslib.inspectConfig(inspectOptions); + inspectedConfigCounts.push(inspection.origin.bundlerConfigs.length); + return inspection; + }, + }; + }, + }); + // Rslib 1.x infers the inspect mode from NODE_ENV and, under development, + // inspects only `mf` libs — none here — unless the compiler asks for the + // production configs explicitly, which it does for every entry. + expect(inspectedConfigCounts).toEqual([1]); + // Rslib writes the inspected mode to NODE_ENV; the compiler hands the + // process its own value back. + expect(process.env.NODE_ENV).toBe('development'); + await expect(readFile(join(root, 'dist', 'scripts', 'reserved-probe.mjs'), 'utf8')).resolves + .toContain('generated-wrapper-marker'); + } finally { + if (previousNodeEnv === undefined) delete process.env.NODE_ENV; + else process.env.NODE_ENV = previousNodeEnv; + await rm(root, { force: true, recursive: true }); + } +}, 20_000); + +it('leaves filesystem URL and worker expressions in the emitted bundle untouched', async () => { + const root = await mkdtemp(join(tmpdir(), 'agent-bundle-resource-references-')); + const sourceRoot = join(root, 'src'); + await mkdir(sourceRoot, { recursive: true }); + await writeFile(join(root, 'package.json'), '{"type":"module"}\n'); + await writeFile(join(sourceRoot, 'sibling.json'), '{"present":true}\n'); + // The shapes generated entries and plugin code spell: the artifact root, a + // sibling that exists only in the output, a sibling that exists beside the + // source, a templated sibling, and the Flight worker. Rslib 1.x would + // otherwise fail the build on the first two, copy the third into + // `static/`, turn the fourth into a directory lookup that throws at run + // time, and bundle the fifth as a worker entry. + await writeFile(join(sourceRoot, 'entry.ts'), [ + "import { Worker } from 'node:worker_threads';", + "export const artifactRoot = new URL('../', import.meta.url);", + "export const generated = new URL('./generated.js', import.meta.url);", + "export const present = new URL('./sibling.json', import.meta.url);", + 'export const templated = (name: string) => new URL(`./event-${name}.js`, import.meta.url);', + "export const spawn = () => new Worker(new URL('./entry-flight.mjs', import.meta.url), { stderr: true, stdout: true });", + '', + ].join('\n')); + try { + await buildWithRslib({ + cwd: root, + entries: [{ + name: 'references', + outputRelativePath: 'scripts/references.mjs', + source: join(sourceRoot, 'entry.ts'), + sourceInputs: [join(sourceRoot, 'entry.ts')], + }], + meta: testMeta, + outputRoot: join(root, 'dist'), + }); + const bundle = await readFile(join(root, 'dist', 'scripts', 'references.mjs'), 'utf8'); + for (const expression of [ + "new URL('../', import.meta.url)", + "new URL('./generated.js', import.meta.url)", + "new URL('./sibling.json', import.meta.url)", + 'new URL(`./event-${name}.js`, import.meta.url)', + "new Worker(new URL('./entry-flight.mjs', import.meta.url)", + ]) { + expect(bundle).toContain(expression); + } + // Nothing was copied out as a static asset or built as a worker entry. + await expect(readdir(join(root, 'dist'))).resolves.toEqual(['scripts']); + await expect(readdir(join(root, 'dist', 'scripts'))).resolves.toEqual(['references.mjs']); + } finally { + await rm(root, { force: true, recursive: true }); + } +}, 20_000); + /** * A workspace layout as a package manager lays it out: the project's dependency * `linked-a` is a symlink to a sibling package, and `linked-a`'s own dependency diff --git a/packages/agent-bundle/tests/inspect-bundler.test.ts b/packages/agent-bundle/tests/inspect-bundler.test.ts index 2a9198b3f..d61ff5049 100644 --- a/packages/agent-bundle/tests/inspect-bundler.test.ts +++ b/packages/agent-bundle/tests/inspect-bundler.test.ts @@ -111,6 +111,9 @@ it('surfaces every synthesized bundler config with the tools hatch merged over t }, syntax: 'es2022', tools: { + // Rslib's `new URL()` rule is switched off so filesystem URLs in + // generated and plugin code survive verbatim. + bundlerChain: '[function preserveResourceReferences]', // The consumer rspack hatch is merged before the framework invariant // hook, which always runs last. rspack: [ diff --git a/packages/agent-bundle/tests/packed-consumer.test.ts b/packages/agent-bundle/tests/packed-consumer.test.ts index 1d6fb6714..7a3abaf0c 100644 --- a/packages/agent-bundle/tests/packed-consumer.test.ts +++ b/packages/agent-bundle/tests/packed-consumer.test.ts @@ -11,12 +11,14 @@ import { stat, writeFile, } from 'node:fs/promises'; +import { isBuiltin } from 'node:module'; import { tmpdir } from 'node:os'; -import { join, relative } from 'node:path'; +import { dirname, join, relative, resolve } from 'node:path'; import { pathToFileURL } from 'node:url'; import { promisify } from 'node:util'; import { expect, it } from '@rstest/core'; +import { init, parse } from 'es-module-lexer'; import { sha256Hex } from '../src/core/digest.ts'; import { cachedNpmInstallArguments, installedEnvironment, linkWorkspaceTypes, packOutputFromJson } from './support/shared-pack.ts'; @@ -56,6 +58,66 @@ const artifactDigest = async (root: string): Promise => { return (await collect(root)).sort((left, right) => left.path.localeCompare(right.path)); }; +interface EmittedModule { + /** Path relative to the walked root. */ + readonly path: string; + /** Literal specifiers of the module's live imports; `import.meta` is not an import. */ + readonly specifiers: readonly string[]; +} + +interface EmittedModuleReport { + readonly modules: readonly EmittedModule[]; + /** One entry per import that breaks the constraint, naming the importing module and the specifier. */ + readonly violations: readonly string[]; +} + +/** + * Walks every `.js`/`.mjs` module under `root` — a plugin artifact or a + * package build's `dist/` — and checks the self-containment constraint on + * the emitted JavaScript itself. A plugin build bundles every dependency of + * each generated executable, so Node builtins are the only external modules + * an emitted module may import; every other specifier must be a relative + * path (`./` or `../`) to a file inside the same output tree. The author's + * own `tools` hatch is the only way a non-builtin may remain external, and + * this fixture declares none. `AB6005` (src/build/validate-artifact-modules.ts) + * enforces the same rule inside every build; this walk proves it on the + * outputs a real consumer builds from the installed tarball. + */ +const emittedModuleReport = async (root: string): Promise => { + await init; + const entries = await readdir(root, { recursive: true, withFileTypes: true }); + const files = entries + .filter((entry) => entry.isFile() && /\.m?js$/u.test(entry.name)) + .map((entry) => join(entry.parentPath, entry.name)) + .sort(); + const violations: string[] = []; + const modules = await Promise.all(files.map(async (file): Promise => { + const path = relative(root, file); + const [imports] = parse(await readFile(file, 'utf8'), path); + const specifiers: string[] = []; + // `import.meta` is reported as a pseudo-import (`d === -2`) without a specifier. + for (const record of imports.filter((candidate) => candidate.d !== -2)) { + if (record.n === undefined) { + violations.push(`${path} has a non-literal dynamic import`); + continue; + } + specifiers.push(record.n); + if (isBuiltin(record.n)) continue; + if (!record.n.startsWith('./') && !record.n.startsWith('../')) { + violations.push(`${path} imports ${JSON.stringify(record.n)}`); + continue; + } + const target = resolve(dirname(file), record.n); + const location = relative(root, target); + const inside = location !== '' && location !== '..' && !location.startsWith('../'); + const exists = inside && await stat(target).then((metadata) => metadata.isFile(), () => false); + if (!exists) violations.push(`${path} imports ${JSON.stringify(record.n)}, which is not a file inside the output tree`); + } + return { path, specifiers }; + })); + return { modules, violations: violations.sort() }; +}; + const runInstalled = async ( cli: string, root: string, @@ -366,6 +428,23 @@ it('uses only an installed tarball after source deletion', async () => { const frameworkArtifact = join(frameworkRoot, 'artifact'); await runInstalled(frameworkCli, frameworkRoot, ['build', '--root', frameworkRoot, '--output', frameworkArtifact]); + // Self-containment on the outputs a consumer builds from the installed + // tarball: every host tree of the artifact and the package build's dist/ + // import nothing but Node builtins. A violation names the importer and + // the specifier that survived bundling. + const [artifactModules, packageModules] = await Promise.all([ + emittedModuleReport(frameworkArtifact), + emittedModuleReport(join(frameworkRoot, 'dist')), + ]); + expect(artifactModules.violations).toEqual([]); + expect(packageModules.violations).toEqual([]); + expect(artifactModules.modules.filter((module) => /^(?:claude|codex|portable)\/mcp\/[^/]+\.mjs$/u.test(module.path))).toHaveLength(3); + expect(packageModules.modules.map((module) => module.path)).toEqual(expect.arrayContaining([ + 'bin/framework-build-fixture-install.js', + 'bin/framework-build-fixture.js', + 'index.js', + ])); + const packedBin = join(frameworkRoot, 'dist', 'bin', 'framework-build-fixture.js'); const packedInstallerBin = join(frameworkRoot, 'dist', 'bin', 'framework-build-fixture-install.js'); expect((await stat(packedBin)).mode & 0o111).not.toBe(0); @@ -386,6 +465,14 @@ it('uses only an installed tarball after source deletion', async () => { const greeterBundle = await readFile(greeterEntry, 'utf8'); expect(greeterBundle).not.toMatch(agentBundleImport); expect(greeterBundle).toContain('stdio heartbeat'); + // `@modelcontextprotocol/server` is inlined: its tool registry is in the + // bundle and no live import names it. The inlined SDK's own doc comments + // still spell `from '@modelcontextprotocol/server'`, so the lexed + // specifiers are the evidence, not a text search. + expect(greeterBundle).toContain('registerTool'); + const greeterModule = artifactModules.modules.find((module) => module.path === relative(frameworkArtifact, greeterEntry)); + expect(greeterModule).toBeDefined(); + expect(greeterModule?.specifiers.filter((specifier) => !isBuiltin(specifier))).toEqual([]); // The packaged lifecycle shell exits 0 on stdin EOF so clients can // respawn. execFile never closes the child's stdin pipe, so deliver the // EOF explicitly — the real server's transport holds the process alive diff --git a/packages/agent-bundle/tests/public-api-packed.test.ts b/packages/agent-bundle/tests/public-api-packed.test.ts index e207ed96d..ab7688c9b 100644 --- a/packages/agent-bundle/tests/public-api-packed.test.ts +++ b/packages/agent-bundle/tests/public-api-packed.test.ts @@ -1,12 +1,14 @@ import { execFile as executeFile } from 'node:child_process'; -import { mkdtemp, mkdir, readFile, rm, stat, writeFile } from 'node:fs/promises'; +import type { Dirent } from 'node:fs'; +import { mkdtemp, mkdir, readFile, readdir, rm, stat, writeFile } from 'node:fs/promises'; import { tmpdir } from 'node:os'; -import { join } from 'node:path'; +import { join, relative } from 'node:path'; import { promisify } from 'node:util'; import { beforeAll, expect, it } from '@rstest/core'; import { isolatedCommandEnvironment } from '../../../rstest.worker-isolation.ts'; +import { isErrno } from '../src/core/errors.ts'; import { writeFixtureManifest } from './support/manifest.ts'; import { cachedNpmInstallArguments, linkWorkspaceTypes, sharedPackedTarball } from './support/shared-pack.ts'; @@ -44,6 +46,53 @@ const createBuildProject = async (root: string): Promise<{ readonly output: stri return { output, project }; }; +/** One installed copy of a package: where npm placed it and which version it is. */ +interface InstalledCopy { + readonly name: string; + /** Directory relative to the consumer's `node_modules`, so a nested duplicate names its host. */ + readonly path: string; + readonly version: string; +} + +/** + * Every copy of the packages `selected` names anywhere under a consumer's + * `node_modules`, nested duplicates included: npm hoists one version of a + * package and nests the others beneath whichever dependency pinned them, so + * a second engine version shows up as + * `@rslib/core/node_modules/@rsbuild/core`, never at the top level. + */ +const installedCopies = async (nodeModules: string, selected: (name: string) => boolean): Promise => { + const copies: InstalledCopy[] = []; + const visitPackage = async (name: string, directory: string): Promise => { + if (selected(name)) { + const manifest = JSON.parse(await readFile(join(directory, 'package.json'), 'utf8')) as { readonly version: string }; + copies.push({ name, path: relative(nodeModules, directory), version: manifest.version }); + } + await visitNodeModules(join(directory, 'node_modules')); + }; + const visitNodeModules = async (directory: string): Promise => { + let entries: Dirent[]; + try { + entries = await readdir(directory, { withFileTypes: true }); + } catch (error) { + if (isErrno(error, 'ENOENT')) return; + throw error; + } + for (const entry of entries) { + if (!entry.isDirectory() || entry.name.startsWith('.')) continue; + if (!entry.name.startsWith('@')) { + await visitPackage(entry.name, join(directory, entry.name)); + continue; + } + for (const scoped of await readdir(join(directory, entry.name), { withFileTypes: true })) { + if (scoped.isDirectory()) await visitPackage(`${entry.name}/${scoped.name}`, join(directory, entry.name, scoped.name)); + } + } + }; + await visitNodeModules(nodeModules); + return copies.sort((left, right) => left.path.localeCompare(right.path)); +}; + const producerFrom = async (output: string): Promise<{ readonly name: string; readonly version: string }> => { const manifest = JSON.parse( await readFile(join(output, 'agent-bundle.manifest.json'), 'utf8'), @@ -108,6 +157,43 @@ it('writes the package version as the producer of a packed CLI manifest', async } }, 30_000); +/** + * The compiler (`@rslib/core`) and MCP Apps (`@rsbuild/core`) must run one + * Rspack: a consumer that installs the tarball gets exactly one + * `@rspack/core`, one native `@rspack/binding-` of the same + * version, one `@rsbuild/core`, and one `@rslib/core`. Two engines is what + * a mismatched `@rslib/core` / `@rsbuild/core` pair produces (#566), and it + * costs every consumer a second native binding download. + */ +it('installs one Rspack engine into a packed consumer', async () => { + const { tarball } = await sharedPackedTarball('agent-bundle'); + + const consumerRoot = await mkdtemp(join(tmpdir(), 'agent-bundle-packed-engine-')); + try { + await writeFile(join(consumerRoot, 'package.json'), '{"type":"module"}\n'); + await execFile( + 'npm', ['install', ...cachedNpmInstallArguments, tarball], + { cwd: consumerRoot, env: isolatedCommandEnvironment() }, + ); + + const engine = await installedCopies( + join(consumerRoot, 'node_modules'), + (name) => name === '@rspack/core' || name.startsWith('@rspack/binding-') || name === '@rsbuild/core' || name === '@rslib/core', + ); + const installed = (name: string): readonly InstalledCopy[] => engine.filter((copy) => copy.name === name); + const bindings = engine.filter((copy) => copy.name.startsWith('@rspack/binding-')); + const report = engine.map((copy) => `${copy.path}@${copy.version}`).join('\n'); + + expect(installed('@rspack/core'), report).toHaveLength(1); + expect(installed('@rsbuild/core'), report).toHaveLength(1); + expect(installed('@rslib/core'), report).toHaveLength(1); + expect(bindings, report).toHaveLength(1); + expect(bindings[0]!.version, report).toBe(installed('@rspack/core')[0]!.version); + } finally { + await rm(consumerRoot, { force: true, recursive: true }); + } +}, 30_000); + it('imports the externalized config entry from a packed npm consumer', async () => { const { tarball } = await sharedPackedTarball('agent-bundle'); diff --git a/packages/agent-bundle/tests/self-contained-bundler-config.test.ts b/packages/agent-bundle/tests/self-contained-bundler-config.test.ts new file mode 100644 index 000000000..2dab859bc --- /dev/null +++ b/packages/agent-bundle/tests/self-contained-bundler-config.test.ts @@ -0,0 +1,179 @@ +import { createRsbuild } from '@rsbuild/core'; +import { createRslib } from '@rslib/core'; +import { expect, it } from '@rstest/core'; +import { init, parse } from 'es-module-lexer'; +import { mkdir, mkdtemp, readFile, readdir, rm, symlink, writeFile } from 'node:fs/promises'; +import { isBuiltin } from 'node:module'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; + +import { composeMcpAppsRsbuildConfig } from '../src/build/mcp-apps.ts'; +import { buildWithRslib, composeEntryLibConfig, entryLibId, type RslibEntry } from '../src/build/rslib.ts'; +import type { AgentBundleMeta } from '../src/meta.ts'; +import { agentBundleNodeModules } from './helpers/workspace-paths.ts'; + +type RslibInspection = Awaited>['inspectConfig']>>; + +const testMeta: AgentBundleMeta = Object.freeze({ + name: 'self-contained-probe-plugin', + packageName: 'self-contained-probe-package', + packageVersion: '1.0.0', + version: '1.0.0', +}); + +const probeEntry = (root: string): RslibEntry => ({ + name: 'probe', + outputRelativePath: 'scripts/probe.mjs', + source: join(root, 'src', 'entry.ts'), + sourceInputs: [join(root, 'src', 'entry.ts')], +}); + +/** + * A minimal plugin project whose one executable imports a Node builtin (the + * only kind of module a generated executable may leave external) and a real + * registry package, `yaml`, so the build has a dependency to inline rather + * than merely a program to compile. `yaml` ships CommonJS that `require()`s + * the `buffer` and `process` builtins, which also exercises how a bundled + * dependency reaches an external builtin. It resolves through this package's + * own installed dependencies; the workspace root hoists nothing. The MCP App + * view is only composed and inspected, never built, but Rsbuild still + * requires the entry to exist on disk. + */ +const selfContainedProject = async (): Promise<{ readonly entry: RslibEntry; readonly root: string; readonly view: string }> => { + const root = await mkdtemp(join(tmpdir(), 'agent-bundle-self-contained-')); + await mkdir(join(root, 'src'), { recursive: true }); + await mkdir(join(root, 'views'), { recursive: true }); + await writeFile(join(root, 'package.json'), '{"type":"module"}\n'); + await symlink(agentBundleNodeModules, join(root, 'node_modules'), 'dir'); + await writeFile(join(root, 'src', 'entry.ts'), [ + "import { basename } from 'node:path';", + "import { parse } from 'yaml';", + "console.log(basename('/probe/config.yaml'), parse('probe: true'));", + '', + ].join('\n')); + await writeFile(join(root, 'views', 'dashboard.ts'), "document.title = 'dashboard';\n"); + return { entry: probeEntry(root), root, view: join(root, 'views', 'dashboard.ts') }; +}; + +/** + * Rspack accepts one external declaration or arbitrarily nested arrays of + * them; the assertions below judge each declaration on its own. + */ +const externalDeclarations = (externals: unknown): readonly unknown[] => { + if (externals === undefined) return []; + return Array.isArray(externals) ? externals.flatMap(externalDeclarations) : [externals]; +}; + +/** + * The only external declarations a generated executable may carry, exactly + * the list Rslib itself attaches to a `node` target: a Node builtin by name, + * the `node:`-scheme pattern, or Yarn PnP's `pnpapi`. Never a function, an + * object map, or a package name. + */ +const isNodeBuiltinExternal = (external: unknown): boolean => { + if (typeof external === 'string') return isBuiltin(external) || external === 'pnpapi'; + return external instanceof RegExp && external.source === '^node:'; +}; + +/** Every declaration is a Node builtin, and there is at least one, so the check cannot pass vacuously. */ +const expectOnlyNodeBuiltinExternals = (externals: unknown): void => { + const declarations = externalDeclarations(externals); + expect(declarations.length).toBeGreaterThan(0); + expect(declarations.filter((external) => !isNodeBuiltinExternal(external))).toEqual([]); +}; + +it('composes the executable lib profile with nothing externalized', () => { + // Composition never touches the filesystem, so no fixture is created. + const root = join(tmpdir(), 'agent-bundle-self-contained-profile'); + const lib = composeEntryLibConfig(probeEntry(root), { cwd: root, meta: testMeta, outputRoot: join(root, 'dist') }); + expect(lib.bundle).toBe(true); + expect(lib.splitChunks).toBe(false); + // Rslib 1.x reads the option under `output`; the deprecated top-level + // spelling must not creep back in through a merge layer, where it would + // shadow the profile with Rslib's `true` default. + expect(lib.output?.autoExternal).toBe(false); + expect(lib.autoExternal).toBeUndefined(); + expect(lib.output?.externals).toBeUndefined(); +}); + +it('lowers a generated executable with only Node builtins external and inlines its dependencies', async () => { + const { entry, root } = await selfContainedProject(); + const inspections: RslibInspection[] = []; + try { + await buildWithRslib({ cwd: root, entries: [entry], meta: testMeta, outputRoot: join(root, 'dist') }, { + createRslib: async (options) => { + const rslib = await createRslib(options); + return { + build: (buildOptions) => rslib.build(buildOptions), + inspectConfig: async (inspectOptions) => { + const inspection = await rslib.inspectConfig(inspectOptions); + inspections.push(inspection); + return inspection; + }, + }; + }, + }); + expect(inspections).toHaveLength(1); + const { bundlerConfigs, environmentConfigs } = inspections[0]!.origin; + expect(bundlerConfigs).toHaveLength(1); + const bundler = bundlerConfigs[0]!; + expectOnlyNodeBuiltinExternals(bundler.externals); + expect(bundler.output?.asyncChunks).toBe(false); + // Rslib's ESM format layer sets this over Rsbuild's lowering of + // `splitChunks: false`; it splits only async chunks, of which + // `asyncChunks: false` leaves none, so the artifact stays one file. + expect(bundler.optimization?.splitChunks).toEqual({ chunks: 'async' }); + // Rslib's ESM default, deliberately kept: it governs only how the + // already-external Node builtins are emitted, so a CommonJS `require()` + // of a builtin inside a bundled dependency becomes the same + // `createRequire()` shim Rslib 0.x produced. + expect(bundler.externalsType).toBe('modern-module'); + + const environment = environmentConfigs[entryLibId(entry)]!; + expect(environment.splitChunks).toBe(false); + // The profile's `output.autoExternal: false` survives normalization; the + // Node builtin list is Rslib's own `node` target contribution. + expect(environment.output).toHaveProperty('autoExternal', false); + expectOnlyNodeBuiltinExternals(environment.output.externals); + + const bundle = await readFile(join(root, 'dist', 'scripts', 'probe.mjs'), 'utf8'); + await init; + const [imports] = parse(bundle); + // `import.meta` is reported as a pseudo-import without a specifier. + const specifiers = imports.filter((record) => record.d !== -2).map((record) => record.n); + expect(specifiers.length).toBeGreaterThan(0); + expect(specifiers.filter((specifier) => specifier === undefined || !isBuiltin(specifier))).toEqual([]); + expect(bundle).toContain('YAMLParseError'); + expect(bundle).toMatch(/createRequire\(import\.meta\.url\)/u); + await expect(readdir(join(root, 'dist'))).resolves.toEqual(['scripts']); + await expect(readdir(join(root, 'dist', 'scripts'))).resolves.toEqual(['probe.mjs']); + } finally { + await rm(root, { force: true, recursive: true }); + } +}, 20_000); + +it('composes MCP App views as fully inlined web bundles with nothing externalized', async () => { + const { root, view } = await selfContainedProject(); + try { + const config = composeMcpAppsRsbuildConfig( + [{ name: 'dashboard', source: view }], + { cwd: root, meta: testMeta, outDir: join(root, 'dist', 'portable') }, + ); + const rsbuild = await createRsbuild({ cwd: root, config }); + const inspection = await rsbuild.inspectConfig({ mode: 'production' }); + const environment = inspection.origin.environmentConfigs.dashboard!; + expect(environment.splitChunks).toBe(false); + expect(environment.output.inlineScripts).toBe(true); + expect(environment.output.inlineStyles).toBe(true); + // A `web` target has no builtins to leave external, and `autoExternal` + // is an Rslib concept the browser path never grows. + expect(externalDeclarations(environment.output.externals)).toEqual([]); + expect(environment.output).not.toHaveProperty('autoExternal'); + expect(inspection.origin.bundlerConfigs).toHaveLength(1); + const bundler = inspection.origin.bundlerConfigs[0]!; + expect(externalDeclarations(bundler.externals)).toEqual([]); + expect(bundler.output?.asyncChunks).toBe(false); + } finally { + await rm(root, { force: true, recursive: true }); + } +}); diff --git a/packages/create-agent-bundle/package.json b/packages/create-agent-bundle/package.json index a67bcdd77..a342ae0ad 100644 --- a/packages/create-agent-bundle/package.json +++ b/packages/create-agent-bundle/package.json @@ -44,8 +44,8 @@ "devDependencies": { "@clack/prompts": "1.7.0", "@effect/platform-node": "4.0.0-rc.112", - "@rslib/core": "0.23.2", - "@rstest/core": "0.11.10", + "@rslib/core": "1.0.0", + "@rstest/core": "0.11.12", "@types/node": "26.4.0", "effect": "4.0.0-rc.112", "effect-rstest": "https://pkg.pr.new/ScriptedAlchemy/effect-rstest@e5f8d5f" diff --git a/packages/create-agent-bundle/src/scaffold-cli.ts b/packages/create-agent-bundle/src/scaffold-cli.ts index b8cdd1388..20980d6f4 100644 --- a/packages/create-agent-bundle/src/scaffold-cli.ts +++ b/packages/create-agent-bundle/src/scaffold-cli.ts @@ -1,4 +1,6 @@ import { spawn } from 'node:child_process'; +import { dirname } from 'node:path'; +import { fileURLToPath } from 'node:url'; import { cancel, intro, isCancel, log, multiselect, note, outro, select, text } from '@clack/prompts'; import * as NodeServices from '@effect/platform-node/NodeServices'; @@ -52,6 +54,16 @@ const clackPrompter: Prompter = { })), }; +/** + * The directory of this module on disk (`dist/` once bundled). The manifest + * and template paths below are joined onto it rather than spelled as + * `new URL('../…', import.meta.url)`: Rslib would otherwise copy + * `package.json` into the bundle's static assets — freezing the version that + * pkg.pr.new rewrites after the build — and turn the template directory into + * a lookup that throws at run time. + */ +const ownDirectory = dirname(fileURLToPath(import.meta.url)); + /** * The version must be read from disk at run time, not inlined at build time: * pkg.pr.new rewrites the manifest version to `-preview-` when @@ -61,10 +73,7 @@ const clackPrompter: Prompter = { const ownVersion = Effect.gen(function* () { const fs = yield* FileSystem.FileSystem; const path = yield* Path.Path; - const manifestPath = yield* path.fromFileUrl(new URL('../package.json', import.meta.url)).pipe( - // The URL is built from import.meta.url, so a `BadArgument` here is a bug. - Effect.orDie, - ); + const manifestPath = path.join(ownDirectory, '..', 'package.json'); const manifest = JSON.parse(yield* fs.readFileString(manifestPath)) as { readonly version: string }; return manifest.version; }); @@ -110,9 +119,7 @@ const scaffoldProgram = Effect.fnUntraced(function* ( const targetDirectory = path.resolve(process.cwd(), options.targetDir); yield* assertScaffoldTarget(targetDirectory, options.targetDir); - const templateRoot = yield* path.fromFileUrl(new URL(`../templates/${options.template}`, import.meta.url)).pipe( - Effect.orDie, - ); + const templateRoot = path.join(ownDirectory, '..', 'templates', options.template); const files = yield* scaffold({ frameworkSpec, packageName: options.packageName, diff --git a/packages/create-agent-bundle/templates/cli-tool/package_json b/packages/create-agent-bundle/templates/cli-tool/package_json index 3f11ae749..6680c8ef7 100644 --- a/packages/create-agent-bundle/templates/cli-tool/package_json +++ b/packages/create-agent-bundle/templates/cli-tool/package_json @@ -32,7 +32,7 @@ "validate": "agent-bundle validate --json" }, "devDependencies": { - "@rstest/core": "0.11.10", + "@rstest/core": "0.11.12", "@types/node": "26.4.0", "agent-bundle": "workspace:*", "typescript": "7.0.2", diff --git a/packages/create-agent-bundle/templates/mcp-server/package_json b/packages/create-agent-bundle/templates/mcp-server/package_json index 464af67b6..ae5bcca22 100644 --- a/packages/create-agent-bundle/templates/mcp-server/package_json +++ b/packages/create-agent-bundle/templates/mcp-server/package_json @@ -33,7 +33,7 @@ "validate": "agent-bundle validate --json" }, "devDependencies": { - "@rstest/core": "0.11.10", + "@rstest/core": "0.11.12", "@types/node": "26.4.0", "agent-bundle": "workspace:*", "typescript": "7.0.2", diff --git a/packages/create-agent-bundle/templates/minimal/package_json b/packages/create-agent-bundle/templates/minimal/package_json index a00d014ce..0f3e87d17 100644 --- a/packages/create-agent-bundle/templates/minimal/package_json +++ b/packages/create-agent-bundle/templates/minimal/package_json @@ -16,7 +16,7 @@ "validate": "agent-bundle validate --json" }, "devDependencies": { - "@rstest/core": "0.11.10", + "@rstest/core": "0.11.12", "@types/node": "26.4.0", "agent-bundle": "workspace:*", "typescript": "7.0.2" diff --git a/packages/rsc-markdown-stream/package.json b/packages/rsc-markdown-stream/package.json index a956f3334..6e9a1df2d 100644 --- a/packages/rsc-markdown-stream/package.json +++ b/packages/rsc-markdown-stream/package.json @@ -51,8 +51,8 @@ "react": "^19.0.0" }, "devDependencies": { - "@rslib/core": "0.23.2", - "@rstest/core": "0.11.10", + "@rslib/core": "1.0.0", + "@rstest/core": "0.11.12", "@types/react": "19.2.18", "react": "19.2.8" } diff --git a/packages/rsc-runtime/package.json b/packages/rsc-runtime/package.json index 83299f60d..99bb46f64 100644 --- a/packages/rsc-runtime/package.json +++ b/packages/rsc-runtime/package.json @@ -90,9 +90,9 @@ }, "devDependencies": { "@modelcontextprotocol/client": "2.0.0", - "@rslib/core": "0.23.2", - "@rspack/core": "2.2.1", - "@rstest/core": "0.11.10", + "@rslib/core": "1.0.0", + "@rspack/core": "2.2.2", + "@rstest/core": "0.11.12", "@types/react": "19.2.18", "effect-rstest": "https://pkg.pr.new/ScriptedAlchemy/effect-rstest@e5f8d5f", "micromark": "4.0.2", diff --git a/packages/workbench/package.json b/packages/workbench/package.json index c6239c1bc..5114c48cd 100644 --- a/packages/workbench/package.json +++ b/packages/workbench/package.json @@ -27,7 +27,7 @@ "zod": "4.5.4" }, "devDependencies": { - "@rsbuild/core": "2.2.1", + "@rsbuild/core": "2.2.3", "@rsbuild/plugin-react": "2.1.0", "@types/react": "19.2.18", "@types/react-dom": "19.2.5" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c6efd6094..0f11829fc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -31,32 +31,32 @@ importers: specifier: 2.0.0 version: 2.0.0 '@rsbuild/core': - specifier: 2.2.1 - version: 2.2.1 + specifier: 2.2.3 + version: 2.2.3 '@rsbuild/plugin-react': specifier: 2.1.0 - version: 2.1.0(@rsbuild/core@2.2.1)(@rspack/core@2.2.1(@swc/helpers@0.5.23)) + version: 2.1.0(@rsbuild/core@2.2.3)(@rspack/core@2.2.2(@swc/helpers@0.5.23)) '@rslib/core': - specifier: 0.23.2 - version: 0.23.2(typescript@7.0.2) + specifier: 1.0.0 + version: 1.0.0(typescript@7.0.2) '@rslint/core': specifier: 0.8.2 version: 0.8.2(jiti@2.7.0) '@rstest/adapter-rslib': - specifier: 0.11.10 - version: 0.11.10(@rslib/core@0.23.2(typescript@7.0.2))(@rstest/core@0.11.10)(typescript@7.0.2) + specifier: 0.11.12 + version: 0.11.12(@rslib/core@1.0.0(typescript@7.0.2))(@rstest/core@0.11.12)(typescript@7.0.2) '@rstest/browser': - specifier: 0.11.10 - version: 0.11.10(@rstest/core@0.11.10)(playwright@1.62.1) + specifier: 0.11.12 + version: 0.11.12(@rstest/core@0.11.12)(playwright@1.62.1) '@rstest/browser-react': - specifier: 0.11.10 - version: 0.11.10(@rstest/core@0.11.10)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + specifier: 0.11.12 + version: 0.11.12(@rstest/core@0.11.12)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) '@rstest/core': - specifier: 0.11.10 - version: 0.11.10 + specifier: 0.11.12 + version: 0.11.12 '@rstest/playwright': - specifier: 0.11.10 - version: 0.11.10(@rstest/core@0.11.10)(playwright@1.62.1) + specifier: 0.11.12 + version: 0.11.12(@rstest/core@0.11.12)(playwright@1.62.1) '@types/node': specifier: 26.4.0 version: 26.4.0 @@ -77,7 +77,7 @@ importers: version: 1.62.1 rsbuild-plugin-publint: specifier: 1.0.0 - version: 1.0.0(@rsbuild/core@2.2.1) + version: 1.0.0(@rsbuild/core@2.2.3) typescript: specifier: 7.0.2 version: 7.0.2 @@ -88,8 +88,8 @@ importers: specifier: workspace:* version: link:../../packages/rsc-runtime '@rstest/core': - specifier: 0.11.10 - version: 0.11.10 + specifier: 0.11.12 + version: 0.11.12 '@types/react': specifier: 19.2.18 version: 19.2.18 @@ -118,8 +118,8 @@ importers: specifier: 2.0.0 version: 2.0.0 '@rstest/core': - specifier: 0.11.10 - version: 0.11.10 + specifier: 0.11.12 + version: 0.11.12 '@types/react': specifier: 19.2.18 version: 19.2.18 @@ -142,14 +142,14 @@ importers: specifier: 2.0.0 version: 2.0.0 '@rstest/browser': - specifier: 0.11.10 - version: 0.11.10(@rstest/core@0.11.10)(playwright@1.62.1) + specifier: 0.11.12 + version: 0.11.12(@rstest/core@0.11.12)(playwright@1.62.1) '@rstest/core': - specifier: 0.11.10 - version: 0.11.10 + specifier: 0.11.12 + version: 0.11.12 '@rstest/playwright': - specifier: 0.11.10 - version: 0.11.10(@rstest/core@0.11.10)(playwright@1.62.1) + specifier: 0.11.12 + version: 0.11.12(@rstest/core@0.11.12)(playwright@1.62.1) agent-bundle: specifier: workspace:* version: link:../../packages/agent-bundle @@ -182,20 +182,20 @@ importers: version: 19.2.8(react@19.2.8) react-server-dom-rspack: specifier: 0.1.0 - version: 0.1.0(@rspack/core@2.2.1(@swc/helpers@0.5.23))(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + version: 0.1.0(@rspack/core@2.2.2(@swc/helpers@0.5.23))(react-dom@19.2.8(react@19.2.8))(react@19.2.8) zod: specifier: 4.5.4 version: 4.5.4 devDependencies: '@rsbuild/core': - specifier: 2.2.1 - version: 2.2.1 + specifier: 2.2.3 + version: 2.2.3 '@rsbuild/plugin-react': specifier: 2.1.0 - version: 2.1.0(@rsbuild/core@2.2.1)(@rspack/core@2.2.1(@swc/helpers@0.5.23)) + version: 2.1.0(@rsbuild/core@2.2.3)(@rspack/core@2.2.2(@swc/helpers@0.5.23)) '@rstest/core': - specifier: 0.11.10 - version: 0.11.10 + specifier: 0.11.12 + version: 0.11.12 '@types/express': specifier: 5.0.6 version: 5.0.6 @@ -213,7 +213,7 @@ importers: version: 1.62.1 rsbuild-plugin-rsc: specifier: 0.1.1 - version: 0.1.1(@rsbuild/core@2.2.1)(react-server-dom-rspack@0.1.0(@rspack/core@2.2.1(@swc/helpers@0.5.23))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)) + version: 0.1.1(@rsbuild/core@2.2.3)(react-server-dom-rspack@0.1.0(@rspack/core@2.2.2(@swc/helpers@0.5.23))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)) examples/skills-starter: devDependencies: @@ -227,8 +227,8 @@ importers: specifier: workspace:* version: link:../../packages/rsc-runtime '@rstest/core': - specifier: 0.11.10 - version: 0.11.10 + specifier: 0.11.12 + version: 0.11.12 '@types/react': specifier: 19.2.18 version: 19.2.18 @@ -260,14 +260,14 @@ importers: specifier: 2.0.0 version: 2.0.0 '@rsbuild/core': - specifier: 2.2.1 - version: 2.2.1 + specifier: 2.2.3 + version: 2.2.3 '@rsbuild/plugin-react': specifier: 2.1.0 - version: 2.1.0(@rsbuild/core@2.2.1)(@rspack/core@2.2.1(@swc/helpers@0.5.23)) + version: 2.1.0(@rsbuild/core@2.2.3)(@rspack/core@2.2.2(@swc/helpers@0.5.23)) '@rslib/core': - specifier: 0.23.2 - version: 0.23.2(typescript@7.0.2) + specifier: 1.0.0 + version: 1.0.0(typescript@7.0.2) '@rslint/core': specifier: 0.8.2 version: 0.8.2(jiti@2.7.0) @@ -276,7 +276,7 @@ importers: version: 0.1.2(jiti@2.7.0) '@rstest/core': specifier: ^0.11.10 - version: 0.11.10 + version: 0.11.12 acorn: specifier: 8.18.0 version: 8.18.0 @@ -331,7 +331,7 @@ importers: version: 8.18.1 effect-rstest: specifier: https://pkg.pr.new/ScriptedAlchemy/effect-rstest@e5f8d5f - version: https://pkg.pr.new/ScriptedAlchemy/effect-rstest@e5f8d5f(@rstest/core@0.11.10)(effect@4.0.0-rc.112) + version: https://pkg.pr.new/ScriptedAlchemy/effect-rstest@e5f8d5f(@rstest/core@0.11.12)(effect@4.0.0-rc.112) react: specifier: 19.2.8 version: 19.2.8 @@ -351,11 +351,11 @@ importers: specifier: 4.0.0-rc.112 version: 4.0.0-rc.112(effect@4.0.0-rc.112)(redis@6.2.1) '@rslib/core': - specifier: 0.23.2 - version: 0.23.2(typescript@7.0.2) + specifier: 1.0.0 + version: 1.0.0(typescript@7.0.2) '@rstest/core': - specifier: 0.11.10 - version: 0.11.10 + specifier: 0.11.12 + version: 0.11.12 '@types/node': specifier: 26.4.0 version: 26.4.0 @@ -364,16 +364,16 @@ importers: version: 4.0.0-rc.112 effect-rstest: specifier: https://pkg.pr.new/ScriptedAlchemy/effect-rstest@e5f8d5f - version: https://pkg.pr.new/ScriptedAlchemy/effect-rstest@e5f8d5f(@rstest/core@0.11.10)(effect@4.0.0-rc.112) + version: https://pkg.pr.new/ScriptedAlchemy/effect-rstest@e5f8d5f(@rstest/core@0.11.12)(effect@4.0.0-rc.112) packages/rsc-markdown-stream: devDependencies: '@rslib/core': - specifier: 0.23.2 - version: 0.23.2(typescript@7.0.2) + specifier: 1.0.0 + version: 1.0.0(typescript@7.0.2) '@rstest/core': - specifier: 0.11.10 - version: 0.11.10 + specifier: 0.11.12 + version: 0.11.12 '@types/react': specifier: 19.2.18 version: 19.2.18 @@ -397,7 +397,7 @@ importers: version: 1.6.1 react-server-dom-rspack: specifier: 0.1.0 - version: 0.1.0(@rspack/core@2.2.1(@swc/helpers@0.5.23))(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + version: 0.1.0(@rspack/core@2.2.2(@swc/helpers@0.5.23))(react-dom@19.2.8(react@19.2.8))(react@19.2.8) rsc-markdown-stream: specifier: workspace:* version: link:../rsc-markdown-stream @@ -409,20 +409,20 @@ importers: specifier: 2.0.0 version: 2.0.0 '@rslib/core': - specifier: 0.23.2 - version: 0.23.2(typescript@7.0.2) + specifier: 1.0.0 + version: 1.0.0(typescript@7.0.2) '@rspack/core': - specifier: 2.2.1 - version: 2.2.1(@swc/helpers@0.5.23) + specifier: 2.2.2 + version: 2.2.2(@swc/helpers@0.5.23) '@rstest/core': - specifier: 0.11.10 - version: 0.11.10 + specifier: 0.11.12 + version: 0.11.12 '@types/react': specifier: 19.2.18 version: 19.2.18 effect-rstest: specifier: https://pkg.pr.new/ScriptedAlchemy/effect-rstest@e5f8d5f - version: https://pkg.pr.new/ScriptedAlchemy/effect-rstest@e5f8d5f(@rstest/core@0.11.10)(effect@4.0.0-rc.112) + version: https://pkg.pr.new/ScriptedAlchemy/effect-rstest@e5f8d5f(@rstest/core@0.11.12)(effect@4.0.0-rc.112) micromark: specifier: 4.0.2 version: 4.0.2(supports-color@7.2.0) @@ -476,11 +476,11 @@ importers: version: 4.5.4 devDependencies: '@rsbuild/core': - specifier: 2.2.1 - version: 2.2.1 + specifier: 2.2.3 + version: 2.2.3 '@rsbuild/plugin-react': specifier: 2.1.0 - version: 2.1.0(@rsbuild/core@2.2.1)(@rspack/core@2.2.1(@swc/helpers@0.5.23)) + version: 2.1.0(@rsbuild/core@2.2.3)(@rspack/core@2.2.2(@swc/helpers@0.5.23)) '@types/react': specifier: 19.2.18 version: 19.2.18 @@ -495,19 +495,19 @@ importers: version: 3.1.1(@types/react@19.2.18)(react@19.2.8) '@rspress/core': specifier: 2.0.21 - version: 2.0.21(@rspack/core@2.2.1(@swc/helpers@0.5.23))(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@7.2.0))(supports-color@7.2.0) + version: 2.0.21(@rspack/core@2.2.2(@swc/helpers@0.5.23))(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@7.2.0))(supports-color@7.2.0) '@rspress/plugin-llms': specifier: 2.0.21 - version: 2.0.21(@rspress/core@2.0.21(@rspack/core@2.2.1(@swc/helpers@0.5.23))(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@7.2.0))(supports-color@7.2.0))(supports-color@7.2.0) + version: 2.0.21(@rspress/core@2.0.21(@rspack/core@2.2.2(@swc/helpers@0.5.23))(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@7.2.0))(supports-color@7.2.0))(supports-color@7.2.0) '@rspress/plugin-sitemap': specifier: 2.0.21 - version: 2.0.21(@rspress/core@2.0.21(@rspack/core@2.2.1(@swc/helpers@0.5.23))(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@7.2.0))(supports-color@7.2.0)) + version: 2.0.21(@rspress/core@2.0.21(@rspack/core@2.2.2(@swc/helpers@0.5.23))(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@7.2.0))(supports-color@7.2.0)) '@rspress/plugin-twoslash': specifier: 2.0.21 - version: 2.0.21(@rspress/core@2.0.21(@rspack/core@2.2.1(@swc/helpers@0.5.23))(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@7.2.0))(supports-color@7.2.0))(react@19.2.8)(supports-color@7.2.0)(typescript@6.0.3) + version: 2.0.21(@rspress/core@2.0.21(@rspack/core@2.2.2(@swc/helpers@0.5.23))(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@7.2.0))(supports-color@7.2.0))(react@19.2.8)(supports-color@7.2.0)(typescript@6.0.3) '@rspress/plugin-typedoc': specifier: 2.0.21 - version: 2.0.21(@rspress/core@2.0.21(@rspack/core@2.2.1(@swc/helpers@0.5.23))(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@7.2.0))(supports-color@7.2.0))(typescript@6.0.3) + version: 2.0.21(@rspress/core@2.0.21(@rspack/core@2.2.2(@swc/helpers@0.5.23))(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@7.2.0))(supports-color@7.2.0))(typescript@6.0.3) '@shikijs/transformers': specifier: 4.4.3 version: 4.4.3 @@ -553,66 +553,66 @@ packages: resolution: {integrity: sha512-9ytjzGwxjm9Uz7I9avfbt5vlQt6uk9uRRESzJjqrznl6WKvI6dwYTo+vJ3U02Wrq/mR3iql/PzhvHhKdJIAjDQ==} engines: {node: '>=20'} - '@ast-grep/napi-darwin-arm64@0.37.0': - resolution: {integrity: sha512-QAiIiaAbLvMEg/yBbyKn+p1gX2/FuaC0SMf7D7capm/oG4xGMzdeaQIcSosF4TCxxV+hIH4Bz9e4/u7w6Bnk3Q==} + '@ast-grep/napi-darwin-arm64@0.45.2': + resolution: {integrity: sha512-29+sfXTJ7xxqgTuWAHA89gDAQIiJyAZ1ZiHoupjKIqyn0mhXrktO1WOghlDzyYs++hITEPOeXftxy48Y0tDGDQ==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@ast-grep/napi-darwin-x64@0.37.0': - resolution: {integrity: sha512-zvcvdgekd4ySV3zUbUp8HF5nk5zqwiMXTuVzTUdl/w08O7JjM6XPOIVT+d2o/MqwM9rsXdzdergY5oY2RdhSPA==} + '@ast-grep/napi-darwin-x64@0.45.2': + resolution: {integrity: sha512-PUjh7Zf4dKNzYLOYhX5wU6O4BgRPdJnD9zkS1n+/5SeK0U1L5YL486RjNgFt9Xyff0PGtP/wDeoHMF5PhKEwsw==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@ast-grep/napi-linux-arm64-gnu@0.37.0': - resolution: {integrity: sha512-L7Sj0lXy8X+BqSMgr1LB8cCoWk0rericdeu+dC8/c8zpsav5Oo2IQKY1PmiZ7H8IHoFBbURLf8iklY9wsD+cyA==} + '@ast-grep/napi-linux-arm64-gnu@0.45.2': + resolution: {integrity: sha512-bnGKLLHWO13pjPChOFq7Ifqj3HJdOAxMQAGDCUC2JSJhO2YL8/xBZrpN0cHIWNuoUNSAXjCtr5AsCnPz/3jlFg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] libc: [glibc] - '@ast-grep/napi-linux-arm64-musl@0.37.0': - resolution: {integrity: sha512-LF9sAvYy6es/OdyJDO3RwkX3I82Vkfsng1sqUBcoWC1jVb1wX5YVzHtpQox9JrEhGl+bNp7FYxB4Qba9OdA5GA==} + '@ast-grep/napi-linux-arm64-musl@0.45.2': + resolution: {integrity: sha512-FXVb4/V55THjhKxi5zWVrAO8JQj+/DiYP7JLsqenkm5V3UNuC8p2opGOyQpUvNpvcqJiZA9Hl+Onj/yfwSVr/A==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] libc: [musl] - '@ast-grep/napi-linux-x64-gnu@0.37.0': - resolution: {integrity: sha512-TViz5/klqre6aSmJzswEIjApnGjJzstG/SE8VDWsrftMBMYt2PTu3MeluZVwzSqDao8doT/P+6U11dU05UOgxw==} + '@ast-grep/napi-linux-x64-gnu@0.45.2': + resolution: {integrity: sha512-mtEIPLV9MW2PBswFcp3ydM4T5Ub73s89SRd0QMT2+DfA9XBLCLhnC+r/Yt4eRgnf8FyNx49bFTPxXvFKscr9hw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] libc: [glibc] - '@ast-grep/napi-linux-x64-musl@0.37.0': - resolution: {integrity: sha512-/BcCH33S9E3ovOAEoxYngUNXgb+JLg991sdyiNP2bSoYd30a9RHrG7CYwW6fMgua3ijQ474eV6cq9yZO1bCpXg==} + '@ast-grep/napi-linux-x64-musl@0.45.2': + resolution: {integrity: sha512-WLLHxDmuXkb/e3mz/xDCrB2dZPzv1ntsepuRTtpaIGczxnQTgFSzX/CXPD0e1MfsU/QL1AiXxxni8w+NGy/ZpQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] libc: [musl] - '@ast-grep/napi-win32-arm64-msvc@0.37.0': - resolution: {integrity: sha512-TjQA4cFoIEW2bgjLkaL9yqT4XWuuLa5MCNd0VCDhGRDMNQ9+rhwi9eLOWRaap3xzT7g+nlbcEHL3AkVCD2+b3A==} + '@ast-grep/napi-win32-arm64-msvc@0.45.2': + resolution: {integrity: sha512-04iOFaMzD2nf8CKw3nURWN42900wqPtUTQaMo1I2KRk3qbgtHSJjJoVJGAWUXkCq4LhPg3Xlk1s+ssWf4rNm2A==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@ast-grep/napi-win32-ia32-msvc@0.37.0': - resolution: {integrity: sha512-uNmVka8fJCdYsyOlF9aZqQMLTatEYBynjChVTzUfFMDfmZ0bihs/YTqJVbkSm8TZM7CUX82apvn50z/dX5iWRA==} + '@ast-grep/napi-win32-ia32-msvc@0.45.2': + resolution: {integrity: sha512-tE3y0RQcajocKwpYLbgHKd4lzGGAx1wGMA0bGPsWdoFK8VSob6ZDuYdSlSdnaRs8jAc4F3axToNRKn15p+0/Dg==} engines: {node: '>= 10'} cpu: [ia32] os: [win32] - '@ast-grep/napi-win32-x64-msvc@0.37.0': - resolution: {integrity: sha512-vCiFOT3hSCQuHHfZ933GAwnPzmL0G04JxQEsBRfqONywyT8bSdDc/ECpAfr3S9VcS4JZ9/F6tkePKW/Om2Dq2g==} + '@ast-grep/napi-win32-x64-msvc@0.45.2': + resolution: {integrity: sha512-o8Z5Z42TAJe0fPnb11rrjtte58wlw/MuR4KpVMHl8IhJLBBR7gHR0E8wfMz88TxzsQz0U2KYev0k0a2fV4i0sQ==} engines: {node: '>= 10'} cpu: [x64] os: [win32] - '@ast-grep/napi@0.37.0': - resolution: {integrity: sha512-Hb4o6h1Pf6yRUAX07DR4JVY7dmQw+RVQMW5/m55GoiAT/VRoKCWBtIUPPOnqDVhbx1Cjfil9b6EDrgJsUAujEQ==} + '@ast-grep/napi@0.45.2': + resolution: {integrity: sha512-hBA5c7JV6OM7zFWoLjUNZhsDpxEIEIeew5S3z1giwK5tPQqobuFfM2OhS45bN3E0+yQtgCX/o8/AEHKbGD3ykg==} engines: {node: '>= 10'} '@braidai/lang@1.1.2': @@ -1024,18 +1024,8 @@ packages: peerDependencies: '@redis/client': ^6.2.1 - '@rsbuild/core@2.1.13': - resolution: {integrity: sha512-Z+6MzmjOio4+bFZQ24k+7ge/oNCOdXIunAssrswTNE8AIf6mcyXpJZevRXRiOEMZasRPA8VNyh+9JngQLg729Q==} - engines: {node: ^20.19.0 || >=22.12.0} - hasBin: true - peerDependencies: - core-js: '>= 3.0.0' - peerDependenciesMeta: - core-js: - optional: true - - '@rsbuild/core@2.2.1': - resolution: {integrity: sha512-JcGtG4bo7PBihj6fBL6gaxaJihqLf7nGWW/t4zEmXpMJkV6XNdr1jAo9B0xI4mLAOmtFeva8cUbn9SE2ZEmAIw==} + '@rsbuild/core@2.2.3': + resolution: {integrity: sha512-oJrYtYDhb7AMwY8HIda2hgMuuxHkYPYar4svdS5uTq0fXY0M1wLfllkTQz0d729pNJ4S//6GUM1WX5LsW2mFLw==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: @@ -1052,13 +1042,13 @@ packages: '@rsbuild/core': optional: true - '@rslib/core@0.23.2': - resolution: {integrity: sha512-KxSp+/y0BJ1O4oKwxX4ydBY7/ZVeJCUpWAmQniCIct8mTxIQFPGO/ibKbKq2IxZYqRuRpM8g+Dtyq0VbEQf9HQ==} + '@rslib/core@1.0.0': + resolution: {integrity: sha512-eZNXCWU1v5oti4+DKCunc76DkNnYqMgRtks9UyZRRFlmaK4pKAxhejeCUS+XkbMurGIAa+aDyVynQD7DXEgK1w==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: '@microsoft/api-extractor': ^7 - typescript: ^5 || ^6 || ^7.0.1-0 + typescript: ^5 || ^6 || ^7 peerDependenciesMeta: '@microsoft/api-extractor': optional: true @@ -1118,180 +1108,88 @@ packages: cpu: [x64] os: [win32] - '@rspack/binding-darwin-arm64@2.1.10': - resolution: {integrity: sha512-DZlcTpbIb2mjeS1aSG4k01UH33Zj7T+k8ZylPK6HmsKs4JvK4wgpWFC78WVv3p/Aj3MZS6DwtDLwpZ2Ihj/fpg==} - cpu: [arm64] - os: [darwin] - - '@rspack/binding-darwin-arm64@2.2.1': - resolution: {integrity: sha512-Y/Naw/7V76QiUYdYRuBzBZtzRjt/3fjDUuF8GK0+/BO7BP1RrpY4tk1ln+iiqegRUD8u9uGn08fi8No1rwfyUg==} + '@rspack/binding-darwin-arm64@2.2.2': + resolution: {integrity: sha512-/le/AvV4HSinXTPs2Lqpujxt189Z5T10Ggt96QzckLRPvIchzqoavVDDjltzC7XcaZ87XCH/X06jNKgzkcBBNA==} cpu: [arm64] os: [darwin] - '@rspack/binding-darwin-x64@2.1.10': - resolution: {integrity: sha512-my/0h2LwxCRT6cg3oDDC2e0ZOxQLVajAdIcv0fqnQk5JRNvVuL89PuTutitnSqie1A0/JSL8OQz5XHwmoS3kow==} - cpu: [x64] - os: [darwin] - - '@rspack/binding-darwin-x64@2.2.1': - resolution: {integrity: sha512-rTIG/xZIW7RbEEuMR9hnNn5dv3fDBpX0N4FAQUwfhUYy3tN2+3vibTTq/Nj1Sd9Vn4yWydbWIEwBX6m/aGejig==} + '@rspack/binding-darwin-x64@2.2.2': + resolution: {integrity: sha512-uFIcUPUXiPxM6ljenLafp5TemT8eLZm1riRn8fJYmpqNCK+aCcTaud18XHZpI5SjzzcY+xUHfVShgvNzKXuf2g==} cpu: [x64] os: [darwin] - '@rspack/binding-linux-arm64-gnu@2.1.10': - resolution: {integrity: sha512-laevn9g+E5PAUEGqiKe6Ju5KApsuQYp+bPI17XS3Lkl8eqL5pS/BmHYU7QMlst4GzV8+wlruVTMh//+st6Vqzg==} - cpu: [arm64] - os: [linux] - libc: [glibc] - - '@rspack/binding-linux-arm64-gnu@2.2.1': - resolution: {integrity: sha512-53rAMU6Hqiat21IMU1hTt4Si2F33h+ZbXOt+Y18W39AFjcwmleIBId2u7beqJeGXLJuBgIAm31jcbJj/PN7mWQ==} + '@rspack/binding-linux-arm64-gnu@2.2.2': + resolution: {integrity: sha512-Pjby4pDSMNJQK2VBzpgCj6lb+DGuenS1fEDb6xi5/apbJb9v5WE+e43Mz7i+XqgXS8e846pjaONV3KM5WKB1LQ==} cpu: [arm64] os: [linux] libc: [glibc] - '@rspack/binding-linux-arm64-musl@2.1.10': - resolution: {integrity: sha512-V71+Qz5G72+ROZXrJn5zxOszdG1AEbO8pcC/itXXtf4yRR6a3bVHKNKGhipBNxb8eI6cnD/01FH1h3ZG655jLw==} + '@rspack/binding-linux-arm64-musl@2.2.2': + resolution: {integrity: sha512-0u9O7tTVT2z+F6o/eEY6f6+My8Jn9U56QiBwkfy90ZaoAfZyQSSTxqaK/zA7W43oFxQefeCpiPas27VUzrSakw==} cpu: [arm64] os: [linux] libc: [musl] - '@rspack/binding-linux-arm64-musl@2.2.1': - resolution: {integrity: sha512-o7zFiWkt4MqSfSdTbxUdF27fcrWKpRizcuVB8H3yd2G6xW9V2OfYbhVGQnOlbKi+GK74RkCmoJtANB+QboIqKQ==} - cpu: [arm64] - os: [linux] - libc: [musl] - - '@rspack/binding-linux-ppc64-gnu@2.1.10': - resolution: {integrity: sha512-U7HlNzHcDtZ+LYOtOJmtx67kHEybZzUUAaP7aEXjGYO5WTCgh/176sW2UYP0rmZLrgUNFUuzn+B98RLaClNaVg==} + '@rspack/binding-linux-ppc64-gnu@2.2.2': + resolution: {integrity: sha512-N3lVnhq5qOvpmP5n386JzR1GcE8HzAqq4/r440Z6yle9m7PhVFJ6oXVWxgaDTYV0mtv9YLJmaG+YrjYfUa1vuA==} cpu: [ppc64] os: [linux] libc: [glibc] - '@rspack/binding-linux-ppc64-gnu@2.2.1': - resolution: {integrity: sha512-pvx1oeg1z7cr8OcNt7PAt1SJTHzdsN/pvu7HkGnfks2fWE7GDs9DLL2KvN7tUkzQvJm6bGgUwqSCOrqV4uSwAg==} - cpu: [ppc64] - os: [linux] - libc: [glibc] - - '@rspack/binding-linux-riscv64-gnu@2.1.10': - resolution: {integrity: sha512-GMGTJpy9/ecE+5F5IfxZH4bXv0Wx/b2TiehTlCbTksbL+pKpLHYy0rwGdjWDKbmBkhxMMqPiC7PDnn9LbdnnLA==} - cpu: [riscv64] - os: [linux] - libc: [glibc] - - '@rspack/binding-linux-riscv64-gnu@2.2.1': - resolution: {integrity: sha512-WQ6P94Wz2tgwOsgifTWP2/bV63iZH5+rkxngQwF22FC8KmIXXy/Yug7lyMH1ld8Hzg4p1qXjBBr4i1cCyJTR+w==} + '@rspack/binding-linux-riscv64-gnu@2.2.2': + resolution: {integrity: sha512-ReClZyp32/rJkUDV/oGDU0X6BCFyEkTR6r4stFwm/qOOaG6mUMRzZe4gur8Yh979p4Hiz9EdkmfEHY02GBXcaQ==} cpu: [riscv64] os: [linux] libc: [glibc] - '@rspack/binding-linux-riscv64-musl@2.1.10': - resolution: {integrity: sha512-rkurnAWc04vIbzG1QCrPBWSJadZvaOt1mazFH3EdiJO8VUiu0I1T9zdiwuDOPrd50lOKIZlcTXbd5aaAkWEnvQ==} + '@rspack/binding-linux-riscv64-musl@2.2.2': + resolution: {integrity: sha512-mqsorvTNerr3r8zI35NFTPYATPDlhepdiUhZjKT6ylqpHlP7vLU9fp4aEMK/CuTv2f+IVsa0+iZqtMxHs2tSjw==} cpu: [riscv64] os: [linux] libc: [musl] - '@rspack/binding-linux-riscv64-musl@2.2.1': - resolution: {integrity: sha512-GEFUFHQkjKU7OYyHXnrIo8wWcUHM7jeKov5z6Lxd3i+3hKo11yBOgb7b+uD94Rx2tPuWF4jyFdWmcNu46Njb/A==} - cpu: [riscv64] - os: [linux] - libc: [musl] - - '@rspack/binding-linux-s390x-gnu@2.1.10': - resolution: {integrity: sha512-X+DyxkriZEAF/wihI7ERDv+CAS0mbMv36aEuQ+vXzTlvS6cSmpou/r29AHbvIF3NlG1UeAbDVlOs9QrMBZjpUQ==} + '@rspack/binding-linux-s390x-gnu@2.2.2': + resolution: {integrity: sha512-ql2Jub8QYWSugBppmj2u0SjcIj6fOQuAaLCYQOqU7zbvz/uuWTfoqmdWKExwrxeCU9Tzt7emVM0ETuVEpoca+A==} cpu: [s390x] os: [linux] libc: [glibc] - '@rspack/binding-linux-s390x-gnu@2.2.1': - resolution: {integrity: sha512-Cqw2UjSmFGZaw1EjQXClKDud86ThynGEEIazy2PZfPzZG4WjICK1WjdeFCJd7xWsSbUQ3jGyzb7/EHiDVa+sKA==} - cpu: [s390x] - os: [linux] - libc: [glibc] - - '@rspack/binding-linux-x64-gnu@2.1.10': - resolution: {integrity: sha512-Fat09V6jUuyo9qG7Wyj9cQ31VDfLmokXyBtGqKxY5OvSWHereB7QUub5btbPXHwbp6Iq4aAQyUbbLTzvR1YaBw==} + '@rspack/binding-linux-x64-gnu@2.2.2': + resolution: {integrity: sha512-MNYKYEHrtIVEno2q5rgpou/JVffRwn109xPK3kxct95EojHsniNa8jwy6eEHeOazP4EN60Si7NElE3aQ6JssHw==} cpu: [x64] os: [linux] libc: [glibc] - '@rspack/binding-linux-x64-gnu@2.2.1': - resolution: {integrity: sha512-QX+gRxg2CS9ri2fUG5eNurdsrOCWoJ56SsD2O7kcVGiRm+S2+muNb/QhkdkAdt/u/m++7Ve5TMIpHTnaKYCpCw==} - cpu: [x64] - os: [linux] - libc: [glibc] - - '@rspack/binding-linux-x64-musl@2.1.10': - resolution: {integrity: sha512-lhHOnIJ4ClpIlA1f1L8aoxEZivYLjnjq5A6jKKz7BKsm+cHK8kqqEm6lO5KqA5xQT0Lonq1o28bmKHEj6JHInw==} + '@rspack/binding-linux-x64-musl@2.2.2': + resolution: {integrity: sha512-y9/9CmE8lrECaF17GAhacibTL+SvlEPEotQnUuBFC/WFtXh8hU2E7a7bAkpYGSLH6kM0nrJZHO3hTvM1wdWOJw==} cpu: [x64] os: [linux] libc: [musl] - '@rspack/binding-linux-x64-musl@2.2.1': - resolution: {integrity: sha512-mBZQl1NdGbEB3y5M9d0tkuF7RL1GLz3Hb3gqFa3QRZBymP9PCV83Jiji8s2PJimNUJIVcdZRIw8+VGYs/35c2A==} - cpu: [x64] - os: [linux] - libc: [musl] - - '@rspack/binding-wasm32-wasi@2.1.10': - resolution: {integrity: sha512-KY5YbWbuvYcoaLXnV+vzZOvGRCeb6jt4EpVpKdph1h1IJjwX/ju15EQ+GOe3iecZEdf0OttQcNVcwBkLkFT9ag==} - cpu: [wasm32] - - '@rspack/binding-wasm32-wasi@2.2.1': - resolution: {integrity: sha512-/d2ImKDS+lT+FJ07MxKBeUkTat84tr2Nm2+nIRt8HmZK7/N8odkQml9vb4MHr8E7oYOp4B+jm6W5frdRzKrkJQ==} + '@rspack/binding-wasm32-wasi@2.2.2': + resolution: {integrity: sha512-VbDIjjeFwZvMSKAOGY5IbU6lLzt6AHHHncTdMMkZ94Xk7O2BOHe9BXDV32Ln29TIW2C8m1fdxfPZWDiecVghUQ==} cpu: [wasm32] - '@rspack/binding-win32-arm64-msvc@2.1.10': - resolution: {integrity: sha512-z4GWzMLofaDGpAt9Z+MlN88LlUBDm+zM6R2GdOOPM6/4g/h3/+47OP7casmSL3AwTGYBEJqogwt08sRSosB6Cg==} - cpu: [arm64] - os: [win32] - - '@rspack/binding-win32-arm64-msvc@2.2.1': - resolution: {integrity: sha512-TfmaKPF3KC7uoZb6A+8ZUbLS8g8P5EdeXFGLCaJ+UgdkJ20TsapcfJXZXWNnKzFEkV8dUO/t5oNxNLYy2URusw==} + '@rspack/binding-win32-arm64-msvc@2.2.2': + resolution: {integrity: sha512-rfcNg0W3ZPZvXma1gTyEt9/Z8FxASIaQr+sMWTSaTPPaeU3xY1+0hYcrD0kUFNs3/5L4u63myI4R8qRXiuW3pA==} cpu: [arm64] os: [win32] - '@rspack/binding-win32-ia32-msvc@2.1.10': - resolution: {integrity: sha512-7qcWdsZ+GuGtzKjqgy7wTN7Dso/ezIY8yhx1r2yIbcczdmXj4FhaEampMDp/25HwtKwIGBBoh6HHSt3JWxpTUg==} - cpu: [ia32] - os: [win32] - - '@rspack/binding-win32-ia32-msvc@2.2.1': - resolution: {integrity: sha512-rdBXayngvpQFMSUIC4b71FDZrSBJszSHNEkln/Nis3a17DMAE7IkgJcqe7SqLWbk2OPF/N920AOWmBEDQQCaMg==} + '@rspack/binding-win32-ia32-msvc@2.2.2': + resolution: {integrity: sha512-TFPvr9RZw9oHIhooDhXHzWjKcHpGPTxkznSeM2poIWU0CdEuua2rVUfsrriTF1Dmx+9kMly61DQmyOHCbb+b2g==} cpu: [ia32] os: [win32] - '@rspack/binding-win32-x64-msvc@2.1.10': - resolution: {integrity: sha512-pgp23pLrzfhGnKycxzr7ifP17lAbWZEfnx1bX8gXtYrnpJ66DRNyTKSzxB6sa/HBWjS1L8PX5TjMZ44WfPydqQ==} + '@rspack/binding-win32-x64-msvc@2.2.2': + resolution: {integrity: sha512-GvEGyL594dtWN9SoVnKWh0exrM8WLInaUjwcuA2JKbCi1ak/9iHxip/U1dY3DuVqBYBhmvYq96JPbl91xnzFjg==} cpu: [x64] os: [win32] - '@rspack/binding-win32-x64-msvc@2.2.1': - resolution: {integrity: sha512-l3K4s7nrQJc+3LacPFjZGjX8Jk1sf8Q4TK6IXAsdSucOjTqYSpD8PMl2NUXCBDXOl8T2V4v323z1LfxwW8BPmA==} - cpu: [x64] - os: [win32] - - '@rspack/binding@2.1.10': - resolution: {integrity: sha512-vnu/UP5HnrND15lO9+VeG6eUrbTyycHNQNQ3XEiRiFojuoiGZkIZC3Hbzr8qQH44C6vScPODEPvvIVvLcO2LpQ==} - - '@rspack/binding@2.2.1': - resolution: {integrity: sha512-56TqztuEMd+aHGv1jDXnkJQGSLTb4NoO146flFxJqPG8931UdXPO2pNR9M0Q2Pz+GvmO0fLHGPLYBHoRVrRlHw==} + '@rspack/binding@2.2.2': + resolution: {integrity: sha512-gWjKDQfVQJSBh/I+y9WTlyERsiShSJ7eI6Yl0SJs/6gjx8t4ixuwWCsaEFFjwSL4nSn6ML5hNQ7UFY3gj72BWA==} - '@rspack/core@2.1.10': - resolution: {integrity: sha512-YSS2/Xxz8uiG/KXDkqOoA3dTetNo/vysk7bAexQOrU8iuq7JuzDTTAwLKvWZnwmvME8M8m5wcM4YvfIwYmidHA==} - engines: {node: ^20.19.0 || >=22.12.0} - peerDependencies: - '@module-federation/runtime-tools': ^0.24.1 || ^2.0.0 - '@swc/helpers': ^0.5.23 - peerDependenciesMeta: - '@module-federation/runtime-tools': - optional: true - '@swc/helpers': - optional: true - - '@rspack/core@2.2.1': - resolution: {integrity: sha512-EHFX2oWCY1HkHJkG/Ev8HXCcl4gQzgETyairdIlBkKaypuW8i7kowBxUFzpHHg/ObF70vB3focToel9Wwg4MRA==} + '@rspack/core@2.2.2': + resolution: {integrity: sha512-/yztfDZR5syIPBrUpzBpL+6fhhl0IHBPcXlNr4tOMBULbocFIz7Z4/cqvf1ix0DBbKpIGx99v6N1IDbk2gi8hw==} engines: {node: ^20.19.0 || >=22.12.0} peerDependencies: '@module-federation/runtime-tools': ^0.24.1 || ^2.0.0 @@ -1353,8 +1251,8 @@ packages: jiti: optional: true - '@rstest/adapter-rslib@0.11.10': - resolution: {integrity: sha512-yocKR4QBzerK21J+xJkg4Ixv5Z3N8Jul64nX70ErbRruXyTJm4EMqggzfxX9a7EpR0XnCzE/fNWxZug8/CECeg==} + '@rstest/adapter-rslib@0.11.12': + resolution: {integrity: sha512-YIJ+4uTmTYCPWtsoePZ9nTsA9j0OVa24sM0nvwWig4inhKJi50Aa7+yd//N9CtQ0Gc608BJ5S5fo9w/DfCSWYA==} peerDependencies: '@rslib/core': '>=0.18.6 || ^1.0.0-0' '@rstest/core': ^0.11.0 @@ -1363,26 +1261,26 @@ packages: typescript: optional: true - '@rstest/browser-react@0.11.10': - resolution: {integrity: sha512-LFMjeUfMmfM2HnEk/5YHGXNXLMQCwKdA0fHcNzQztYYeTVb9FB0SPwv6FrqduNXZUAyNyHryxS2TO4jDYaYWvg==} + '@rstest/browser-react@0.11.12': + resolution: {integrity: sha512-qkchnPdhNZOMnVYtleOBXhNSf2r61vvzMgtO/dUtJeNSLtecMBIhOQSmQMBxCKjZhuZfJuhwlLqmgNGwpCZA8g==} engines: {node: ^20.19.0 || >=22.12.0} peerDependencies: '@rstest/core': ^0.11.0 react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 - '@rstest/browser@0.11.10': - resolution: {integrity: sha512-Ic9QD8uA2aDaUaFeDgXZoEwEJerV4pwcHo2113hS/UfgpdIgi7n1ygG/tsrRUCzHPDPL3JrN+YYMcntDACAxow==} + '@rstest/browser@0.11.12': + resolution: {integrity: sha512-mCrRj8pXvdGeYpouUrFkV/GVLAbq5mOIx94+5jRCSLSgJNBMU1+OGu+aav3kFgyajORKEI+cKWT35hkPMj6+dQ==} engines: {node: ^20.19.0 || >=22.12.0} peerDependencies: - '@rstest/core': 0.11.10 + '@rstest/core': 0.11.12 playwright: ^1.49.1 peerDependenciesMeta: playwright: optional: true - '@rstest/core@0.11.10': - resolution: {integrity: sha512-x/PNGPdyKQWbiVhpoOQco8xXevh4P/QamuyJ0/YdTrdEiUcUglT6tGSnxaudwyrQr8e/5gwWuOt6zykZKWmSUg==} + '@rstest/core@0.11.12': + resolution: {integrity: sha512-dklEYLtL1eip/11K+o3xEchEs2nCGua2u2W8Pycf6PS8TE0PDJH2Bn9y/txuQI4YVHyIQ88PISWtS6fVnxSyXQ==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: @@ -1394,8 +1292,8 @@ packages: jsdom: optional: true - '@rstest/playwright@0.11.10': - resolution: {integrity: sha512-GY8aE9oNavl7m5hbdpxvO5ot0cH3rSISnzeZU5IeO3lgd7+2OszfWS/EbohwjEq5qr6W64ByQ3sDZBboq6vMEQ==} + '@rstest/playwright@0.11.12': + resolution: {integrity: sha512-fU9BjRnCTsJNw2oEOY1aq/ozSt5gGuZMW6NwVHZrdxmi/uwypoYIcWSAE/kWukRzAazaSdO+wYZ4fB2IC8kLCA==} engines: {node: ^20.19.0 || >=22.12.0} peerDependencies: '@rstest/core': ^0.11.9 @@ -3002,19 +2900,16 @@ packages: resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} engines: {node: '>= 18'} - rsbuild-plugin-dts@0.23.2: - resolution: {integrity: sha512-Ve8WOSPyTBjxH40O/6fChJtflL7yqcUtt5zbF0eHDM4hIt35jqLocRlSdCxFJdQm0blTjl6+hkmPa/vNI06ArA==} + rsbuild-plugin-dts@1.0.0: + resolution: {integrity: sha512-FVoTsiTfSc0LPeSjrVhpvFOBRig0YXJq3Hp+bVxzh9/bzFvODzLRWOEux8q1Phe1oVCIIVSc2+Nb7kDcxIhosw==} engines: {node: ^20.19.0 || >=22.12.0} peerDependencies: '@microsoft/api-extractor': ^7 - '@rsbuild/core': ^1.0.0 || ^2.0.0-0 - '@typescript/native-preview': ^7.0.0-0 - typescript: ^5 || ^6 || ^7.0.1-0 + '@rsbuild/core': ^2.0.0 + typescript: ^5 || ^6 || ^7 peerDependenciesMeta: '@microsoft/api-extractor': optional: true - '@typescript/native-preview': - optional: true typescript: optional: true @@ -3412,44 +3307,44 @@ snapshots: typescript: 5.6.1-rc validate-npm-package-name: 5.0.1 - '@ast-grep/napi-darwin-arm64@0.37.0': + '@ast-grep/napi-darwin-arm64@0.45.2': optional: true - '@ast-grep/napi-darwin-x64@0.37.0': + '@ast-grep/napi-darwin-x64@0.45.2': optional: true - '@ast-grep/napi-linux-arm64-gnu@0.37.0': + '@ast-grep/napi-linux-arm64-gnu@0.45.2': optional: true - '@ast-grep/napi-linux-arm64-musl@0.37.0': + '@ast-grep/napi-linux-arm64-musl@0.45.2': optional: true - '@ast-grep/napi-linux-x64-gnu@0.37.0': + '@ast-grep/napi-linux-x64-gnu@0.45.2': optional: true - '@ast-grep/napi-linux-x64-musl@0.37.0': + '@ast-grep/napi-linux-x64-musl@0.45.2': optional: true - '@ast-grep/napi-win32-arm64-msvc@0.37.0': + '@ast-grep/napi-win32-arm64-msvc@0.45.2': optional: true - '@ast-grep/napi-win32-ia32-msvc@0.37.0': + '@ast-grep/napi-win32-ia32-msvc@0.45.2': optional: true - '@ast-grep/napi-win32-x64-msvc@0.37.0': + '@ast-grep/napi-win32-x64-msvc@0.45.2': optional: true - '@ast-grep/napi@0.37.0': + '@ast-grep/napi@0.45.2': optionalDependencies: - '@ast-grep/napi-darwin-arm64': 0.37.0 - '@ast-grep/napi-darwin-x64': 0.37.0 - '@ast-grep/napi-linux-arm64-gnu': 0.37.0 - '@ast-grep/napi-linux-arm64-musl': 0.37.0 - '@ast-grep/napi-linux-x64-gnu': 0.37.0 - '@ast-grep/napi-linux-x64-musl': 0.37.0 - '@ast-grep/napi-win32-arm64-msvc': 0.37.0 - '@ast-grep/napi-win32-ia32-msvc': 0.37.0 - '@ast-grep/napi-win32-x64-msvc': 0.37.0 + '@ast-grep/napi-darwin-arm64': 0.45.2 + '@ast-grep/napi-darwin-x64': 0.45.2 + '@ast-grep/napi-linux-arm64-gnu': 0.45.2 + '@ast-grep/napi-linux-arm64-musl': 0.45.2 + '@ast-grep/napi-linux-x64-gnu': 0.45.2 + '@ast-grep/napi-linux-x64-musl': 0.45.2 + '@ast-grep/napi-win32-arm64-msvc': 0.45.2 + '@ast-grep/napi-win32-ia32-msvc': 0.45.2 + '@ast-grep/napi-win32-x64-msvc': 0.45.2 '@braidai/lang@1.1.2': {} @@ -3944,38 +3839,30 @@ snapshots: dependencies: '@redis/client': 6.2.1 - '@rsbuild/core@2.1.13': - dependencies: - '@rspack/core': 2.1.10(@swc/helpers@0.5.23) - '@swc/helpers': 0.5.23 - transitivePeerDependencies: - - '@module-federation/runtime-tools' - - '@rsbuild/core@2.2.1': + '@rsbuild/core@2.2.3': dependencies: - '@rspack/core': 2.2.1(@swc/helpers@0.5.23) + '@rspack/core': 2.2.2(@swc/helpers@0.5.23) '@swc/helpers': 0.5.23 transitivePeerDependencies: - '@module-federation/runtime-tools' - '@rsbuild/plugin-react@2.1.0(@rsbuild/core@2.2.1)(@rspack/core@2.2.1(@swc/helpers@0.5.23))': + '@rsbuild/plugin-react@2.1.0(@rsbuild/core@2.2.3)(@rspack/core@2.2.2(@swc/helpers@0.5.23))': dependencies: - '@rspack/plugin-react-refresh': 2.0.2(@rspack/core@2.2.1(@swc/helpers@0.5.23))(react-refresh@0.18.0) + '@rspack/plugin-react-refresh': 2.0.2(@rspack/core@2.2.2(@swc/helpers@0.5.23))(react-refresh@0.18.0) react-refresh: 0.18.0 optionalDependencies: - '@rsbuild/core': 2.2.1 + '@rsbuild/core': 2.2.3 transitivePeerDependencies: - '@rspack/core' - '@rslib/core@0.23.2(typescript@7.0.2)': + '@rslib/core@1.0.0(typescript@7.0.2)': dependencies: - '@rsbuild/core': 2.1.13 - rsbuild-plugin-dts: 0.23.2(@rsbuild/core@2.1.13)(typescript@7.0.2) + '@rsbuild/core': 2.2.3 + rsbuild-plugin-dts: 1.0.0(@rsbuild/core@2.2.3)(typescript@7.0.2) optionalDependencies: typescript: 7.0.2 transitivePeerDependencies: - '@module-federation/runtime-tools' - - '@typescript/native-preview' - core-js '@rslint/core@0.8.2(jiti@2.7.0)': @@ -4016,156 +3903,87 @@ snapshots: '@rslint/native-win32-x64-msvc@0.8.2': optional: true - '@rspack/binding-darwin-arm64@2.1.10': - optional: true - - '@rspack/binding-darwin-arm64@2.2.1': - optional: true - - '@rspack/binding-darwin-x64@2.1.10': - optional: true - - '@rspack/binding-darwin-x64@2.2.1': - optional: true - - '@rspack/binding-linux-arm64-gnu@2.1.10': + '@rspack/binding-darwin-arm64@2.2.2': optional: true - '@rspack/binding-linux-arm64-gnu@2.2.1': + '@rspack/binding-darwin-x64@2.2.2': optional: true - '@rspack/binding-linux-arm64-musl@2.1.10': + '@rspack/binding-linux-arm64-gnu@2.2.2': optional: true - '@rspack/binding-linux-arm64-musl@2.2.1': + '@rspack/binding-linux-arm64-musl@2.2.2': optional: true - '@rspack/binding-linux-ppc64-gnu@2.1.10': + '@rspack/binding-linux-ppc64-gnu@2.2.2': optional: true - '@rspack/binding-linux-ppc64-gnu@2.2.1': + '@rspack/binding-linux-riscv64-gnu@2.2.2': optional: true - '@rspack/binding-linux-riscv64-gnu@2.1.10': + '@rspack/binding-linux-riscv64-musl@2.2.2': optional: true - '@rspack/binding-linux-riscv64-gnu@2.2.1': + '@rspack/binding-linux-s390x-gnu@2.2.2': optional: true - '@rspack/binding-linux-riscv64-musl@2.1.10': + '@rspack/binding-linux-x64-gnu@2.2.2': optional: true - '@rspack/binding-linux-riscv64-musl@2.2.1': + '@rspack/binding-linux-x64-musl@2.2.2': optional: true - '@rspack/binding-linux-s390x-gnu@2.1.10': - optional: true - - '@rspack/binding-linux-s390x-gnu@2.2.1': - optional: true - - '@rspack/binding-linux-x64-gnu@2.1.10': - optional: true - - '@rspack/binding-linux-x64-gnu@2.2.1': - optional: true - - '@rspack/binding-linux-x64-musl@2.1.10': - optional: true - - '@rspack/binding-linux-x64-musl@2.2.1': - optional: true - - '@rspack/binding-wasm32-wasi@2.1.10': + '@rspack/binding-wasm32-wasi@2.2.2': dependencies: '@emnapi/core': 1.11.3 '@emnapi/runtime': 1.11.3 '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.3)(@emnapi/runtime@1.11.3) optional: true - '@rspack/binding-wasm32-wasi@2.2.1': - dependencies: - '@emnapi/core': 1.11.3 - '@emnapi/runtime': 1.11.3 - '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.3)(@emnapi/runtime@1.11.3) - optional: true - - '@rspack/binding-win32-arm64-msvc@2.1.10': - optional: true - - '@rspack/binding-win32-arm64-msvc@2.2.1': - optional: true - - '@rspack/binding-win32-ia32-msvc@2.1.10': + '@rspack/binding-win32-arm64-msvc@2.2.2': optional: true - '@rspack/binding-win32-ia32-msvc@2.2.1': + '@rspack/binding-win32-ia32-msvc@2.2.2': optional: true - '@rspack/binding-win32-x64-msvc@2.1.10': + '@rspack/binding-win32-x64-msvc@2.2.2': optional: true - '@rspack/binding-win32-x64-msvc@2.2.1': - optional: true - - '@rspack/binding@2.1.10': - optionalDependencies: - '@rspack/binding-darwin-arm64': 2.1.10 - '@rspack/binding-darwin-x64': 2.1.10 - '@rspack/binding-linux-arm64-gnu': 2.1.10 - '@rspack/binding-linux-arm64-musl': 2.1.10 - '@rspack/binding-linux-ppc64-gnu': 2.1.10 - '@rspack/binding-linux-riscv64-gnu': 2.1.10 - '@rspack/binding-linux-riscv64-musl': 2.1.10 - '@rspack/binding-linux-s390x-gnu': 2.1.10 - '@rspack/binding-linux-x64-gnu': 2.1.10 - '@rspack/binding-linux-x64-musl': 2.1.10 - '@rspack/binding-wasm32-wasi': 2.1.10 - '@rspack/binding-win32-arm64-msvc': 2.1.10 - '@rspack/binding-win32-ia32-msvc': 2.1.10 - '@rspack/binding-win32-x64-msvc': 2.1.10 - - '@rspack/binding@2.2.1': - optionalDependencies: - '@rspack/binding-darwin-arm64': 2.2.1 - '@rspack/binding-darwin-x64': 2.2.1 - '@rspack/binding-linux-arm64-gnu': 2.2.1 - '@rspack/binding-linux-arm64-musl': 2.2.1 - '@rspack/binding-linux-ppc64-gnu': 2.2.1 - '@rspack/binding-linux-riscv64-gnu': 2.2.1 - '@rspack/binding-linux-riscv64-musl': 2.2.1 - '@rspack/binding-linux-s390x-gnu': 2.2.1 - '@rspack/binding-linux-x64-gnu': 2.2.1 - '@rspack/binding-linux-x64-musl': 2.2.1 - '@rspack/binding-wasm32-wasi': 2.2.1 - '@rspack/binding-win32-arm64-msvc': 2.2.1 - '@rspack/binding-win32-ia32-msvc': 2.2.1 - '@rspack/binding-win32-x64-msvc': 2.2.1 - - '@rspack/core@2.1.10(@swc/helpers@0.5.23)': - dependencies: - '@rspack/binding': 2.1.10 + '@rspack/binding@2.2.2': optionalDependencies: - '@swc/helpers': 0.5.23 - - '@rspack/core@2.2.1(@swc/helpers@0.5.23)': - dependencies: - '@rspack/binding': 2.2.1 + '@rspack/binding-darwin-arm64': 2.2.2 + '@rspack/binding-darwin-x64': 2.2.2 + '@rspack/binding-linux-arm64-gnu': 2.2.2 + '@rspack/binding-linux-arm64-musl': 2.2.2 + '@rspack/binding-linux-ppc64-gnu': 2.2.2 + '@rspack/binding-linux-riscv64-gnu': 2.2.2 + '@rspack/binding-linux-riscv64-musl': 2.2.2 + '@rspack/binding-linux-s390x-gnu': 2.2.2 + '@rspack/binding-linux-x64-gnu': 2.2.2 + '@rspack/binding-linux-x64-musl': 2.2.2 + '@rspack/binding-wasm32-wasi': 2.2.2 + '@rspack/binding-win32-arm64-msvc': 2.2.2 + '@rspack/binding-win32-ia32-msvc': 2.2.2 + '@rspack/binding-win32-x64-msvc': 2.2.2 + + '@rspack/core@2.2.2(@swc/helpers@0.5.23)': + dependencies: + '@rspack/binding': 2.2.2 optionalDependencies: '@swc/helpers': 0.5.23 - '@rspack/plugin-react-refresh@2.0.2(@rspack/core@2.2.1(@swc/helpers@0.5.23))(react-refresh@0.18.0)': + '@rspack/plugin-react-refresh@2.0.2(@rspack/core@2.2.2(@swc/helpers@0.5.23))(react-refresh@0.18.0)': dependencies: react-refresh: 0.18.0 optionalDependencies: - '@rspack/core': 2.2.1(@swc/helpers@0.5.23) + '@rspack/core': 2.2.2(@swc/helpers@0.5.23) - '@rspress/core@2.0.21(@rspack/core@2.2.1(@swc/helpers@0.5.23))(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@7.2.0))(supports-color@7.2.0)': + '@rspress/core@2.0.21(@rspack/core@2.2.2(@swc/helpers@0.5.23))(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@7.2.0))(supports-color@7.2.0)': dependencies: '@mdx-js/mdx': 3.1.1(supports-color@7.2.0) '@mdx-js/react': 3.1.1(@types/react@19.2.18)(react@19.2.8) - '@rsbuild/core': 2.2.1 - '@rsbuild/plugin-react': 2.1.0(@rsbuild/core@2.2.1)(@rspack/core@2.2.1(@swc/helpers@0.5.23)) + '@rsbuild/core': 2.2.3 + '@rsbuild/plugin-react': 2.1.0(@rsbuild/core@2.2.3)(@rspack/core@2.2.2(@swc/helpers@0.5.23)) '@rspress/shared': 2.0.21(supports-color@7.2.0) '@shikijs/rehype': 4.4.3 '@types/mdast': 4.0.4 @@ -4208,9 +4026,9 @@ snapshots: - micromark-util-types - supports-color - '@rspress/plugin-llms@2.0.21(@rspress/core@2.0.21(@rspack/core@2.2.1(@swc/helpers@0.5.23))(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@7.2.0))(supports-color@7.2.0))(supports-color@7.2.0)': + '@rspress/plugin-llms@2.0.21(@rspress/core@2.0.21(@rspack/core@2.2.2(@swc/helpers@0.5.23))(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@7.2.0))(supports-color@7.2.0))(supports-color@7.2.0)': dependencies: - '@rspress/core': 2.0.21(@rspack/core@2.2.1(@swc/helpers@0.5.23))(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@7.2.0))(supports-color@7.2.0) + '@rspress/core': 2.0.21(@rspack/core@2.2.2(@swc/helpers@0.5.23))(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@7.2.0))(supports-color@7.2.0) remark-mdx: 3.1.1(supports-color@7.2.0) remark-parse: 11.0.0(supports-color@7.2.0) remark-stringify: 11.0.0 @@ -4219,14 +4037,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@rspress/plugin-sitemap@2.0.21(@rspress/core@2.0.21(@rspack/core@2.2.1(@swc/helpers@0.5.23))(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@7.2.0))(supports-color@7.2.0))': + '@rspress/plugin-sitemap@2.0.21(@rspress/core@2.0.21(@rspack/core@2.2.2(@swc/helpers@0.5.23))(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@7.2.0))(supports-color@7.2.0))': dependencies: - '@rspress/core': 2.0.21(@rspack/core@2.2.1(@swc/helpers@0.5.23))(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@7.2.0))(supports-color@7.2.0) + '@rspress/core': 2.0.21(@rspack/core@2.2.2(@swc/helpers@0.5.23))(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@7.2.0))(supports-color@7.2.0) - '@rspress/plugin-twoslash@2.0.21(@rspress/core@2.0.21(@rspack/core@2.2.1(@swc/helpers@0.5.23))(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@7.2.0))(supports-color@7.2.0))(react@19.2.8)(supports-color@7.2.0)(typescript@6.0.3)': + '@rspress/plugin-twoslash@2.0.21(@rspress/core@2.0.21(@rspack/core@2.2.2(@swc/helpers@0.5.23))(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@7.2.0))(supports-color@7.2.0))(react@19.2.8)(supports-color@7.2.0)(typescript@6.0.3)': dependencies: '@floating-ui/dom': 1.8.0 - '@rspress/core': 2.0.21(@rspack/core@2.2.1(@swc/helpers@0.5.23))(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@7.2.0))(supports-color@7.2.0) + '@rspress/core': 2.0.21(@rspack/core@2.2.2(@swc/helpers@0.5.23))(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@7.2.0))(supports-color@7.2.0) '@shikijs/twoslash': 4.4.3(supports-color@7.2.0)(typescript@6.0.3) mdast-util-from-markdown: 2.0.3(supports-color@7.2.0) mdast-util-gfm: 3.1.0(supports-color@7.2.0) @@ -4238,9 +4056,9 @@ snapshots: transitivePeerDependencies: - supports-color - '@rspress/plugin-typedoc@2.0.21(@rspress/core@2.0.21(@rspack/core@2.2.1(@swc/helpers@0.5.23))(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@7.2.0))(supports-color@7.2.0))(typescript@6.0.3)': + '@rspress/plugin-typedoc@2.0.21(@rspress/core@2.0.21(@rspack/core@2.2.2(@swc/helpers@0.5.23))(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@7.2.0))(supports-color@7.2.0))(typescript@6.0.3)': dependencies: - '@rspress/core': 2.0.21(@rspack/core@2.2.1(@swc/helpers@0.5.23))(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@7.2.0))(supports-color@7.2.0) + '@rspress/core': 2.0.21(@rspack/core@2.2.2(@swc/helpers@0.5.23))(micromark-util-types@2.0.2)(micromark@4.0.2(supports-color@7.2.0))(supports-color@7.2.0) typedoc: 0.28.20(typescript@6.0.3) typedoc-plugin-markdown: 4.12.0(typedoc@0.28.20(typescript@6.0.3)) transitivePeerDependencies: @@ -4248,7 +4066,7 @@ snapshots: '@rspress/shared@2.0.21(supports-color@7.2.0)': dependencies: - '@rsbuild/core': 2.2.1 + '@rsbuild/core': 2.2.3 '@shikijs/rehype': 4.4.3 '@types/react': 19.2.18 mdast-util-mdx-jsx: 3.2.0(supports-color@7.2.0) @@ -4262,23 +4080,23 @@ snapshots: optionalDependencies: jiti: 2.7.0 - '@rstest/adapter-rslib@0.11.10(@rslib/core@0.23.2(typescript@7.0.2))(@rstest/core@0.11.10)(typescript@7.0.2)': + '@rstest/adapter-rslib@0.11.12(@rslib/core@1.0.0(typescript@7.0.2))(@rstest/core@0.11.12)(typescript@7.0.2)': dependencies: - '@rslib/core': 0.23.2(typescript@7.0.2) - '@rstest/core': 0.11.10 + '@rslib/core': 1.0.0(typescript@7.0.2) + '@rstest/core': 0.11.12 optionalDependencies: typescript: 7.0.2 - '@rstest/browser-react@0.11.10(@rstest/core@0.11.10)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': + '@rstest/browser-react@0.11.12(@rstest/core@0.11.12)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': dependencies: - '@rstest/core': 0.11.10 + '@rstest/core': 0.11.12 react: 19.2.8 react-dom: 19.2.8(react@19.2.8) - '@rstest/browser@0.11.10(@rstest/core@0.11.10)(playwright@1.62.1)': + '@rstest/browser@0.11.12(@rstest/core@0.11.12)(playwright@1.62.1)': dependencies: '@jridgewell/trace-mapping': 0.3.31 - '@rstest/core': 0.11.10 + '@rstest/core': 0.11.12 convert-source-map: 2.0.0 open-editor: 6.0.0 pathe: 2.0.3 @@ -4290,17 +4108,17 @@ snapshots: - bufferutil - utf-8-validate - '@rstest/core@0.11.10': + '@rstest/core@0.11.12': dependencies: - '@rsbuild/core': 2.2.1 + '@rsbuild/core': 2.2.3 '@types/chai': 5.2.3 transitivePeerDependencies: - '@module-federation/runtime-tools' - core-js - '@rstest/playwright@0.11.10(@rstest/core@0.11.10)(playwright@1.62.1)': + '@rstest/playwright@0.11.12(@rstest/core@0.11.12)(playwright@1.62.1)': dependencies: - '@rstest/core': 0.11.10 + '@rstest/core': 0.11.12 playwright: 1.62.1 '@sec-ant/readable-stream@0.4.1': {} @@ -4792,9 +4610,9 @@ snapshots: ee-first@1.1.1: {} - effect-rstest@https://pkg.pr.new/ScriptedAlchemy/effect-rstest@e5f8d5f(@rstest/core@0.11.10)(effect@4.0.0-rc.112): + effect-rstest@https://pkg.pr.new/ScriptedAlchemy/effect-rstest@e5f8d5f(@rstest/core@0.11.12)(effect@4.0.0-rc.112): dependencies: - '@rstest/core': 0.11.10 + '@rstest/core': 0.11.12 effect: 4.0.0-rc.112 effect@4.0.0-rc.112: @@ -6073,9 +5891,9 @@ snapshots: optionalDependencies: react-dom: 19.2.8(react@19.2.8) - react-server-dom-rspack@0.1.0(@rspack/core@2.2.1(@swc/helpers@0.5.23))(react-dom@19.2.8(react@19.2.8))(react@19.2.8): + react-server-dom-rspack@0.1.0(@rspack/core@2.2.2(@swc/helpers@0.5.23))(react-dom@19.2.8(react@19.2.8))(react@19.2.8): dependencies: - '@rspack/core': 2.2.1(@swc/helpers@0.5.23) + '@rspack/core': 2.2.2(@swc/helpers@0.5.23) react: 19.2.8 react-dom: 19.2.8(react@19.2.8) @@ -6236,23 +6054,23 @@ snapshots: transitivePeerDependencies: - supports-color - rsbuild-plugin-dts@0.23.2(@rsbuild/core@2.1.13)(typescript@7.0.2): + rsbuild-plugin-dts@1.0.0(@rsbuild/core@2.2.3)(typescript@7.0.2): dependencies: - '@ast-grep/napi': 0.37.0 - '@rsbuild/core': 2.1.13 + '@ast-grep/napi': 0.45.2 + '@rsbuild/core': 2.2.3 optionalDependencies: typescript: 7.0.2 - rsbuild-plugin-publint@1.0.0(@rsbuild/core@2.2.1): + rsbuild-plugin-publint@1.0.0(@rsbuild/core@2.2.3): dependencies: publint: 0.3.24 optionalDependencies: - '@rsbuild/core': 2.2.1 + '@rsbuild/core': 2.2.3 - rsbuild-plugin-rsc@0.1.1(@rsbuild/core@2.2.1)(react-server-dom-rspack@0.1.0(@rspack/core@2.2.1(@swc/helpers@0.5.23))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)): + rsbuild-plugin-rsc@0.1.1(@rsbuild/core@2.2.3)(react-server-dom-rspack@0.1.0(@rspack/core@2.2.2(@swc/helpers@0.5.23))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)): dependencies: - '@rsbuild/core': 2.2.1 - react-server-dom-rspack: 0.1.0(@rspack/core@2.2.1(@swc/helpers@0.5.23))(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + '@rsbuild/core': 2.2.3 + react-server-dom-rspack: 0.1.0(@rspack/core@2.2.2(@swc/helpers@0.5.23))(react-dom@19.2.8(react@19.2.8))(react@19.2.8) run-applescript@7.1.0: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index bec90f869..38bfbd41a 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -13,15 +13,11 @@ packages: overrides: '@agent-bundle/runtime': workspace:* rsc-markdown-stream: workspace:* -peerDependencyRules: - allowedVersions: - 'effect-rstest>@rstest/core': 0.11.10 allowBuilds: '@google/genai': false msgpackr-extract: false protobufjs: false minimumReleaseAgeExclude: - - '@rsbuild/core@2.2.1' - '@effect/tsgo-darwin-arm64@0.39.0' - '@effect/tsgo-darwin-x64@0.39.0' - '@effect/tsgo-linux-arm64@0.39.0' diff --git a/rstest.integration-tests.ts b/rstest.integration-tests.ts index c6b3a3db8..091cb2e8b 100644 --- a/rstest.integration-tests.ts +++ b/rstest.integration-tests.ts @@ -64,6 +64,7 @@ export const integrationTestFiles: readonly string[] = [ 'packages/agent-bundle/tests/rsc-runtime-topology-script.test.ts', 'packages/agent-bundle/tests/rstest-meta-consumer.test.ts', 'packages/agent-bundle/tests/script-playground-service.test.ts', + 'packages/agent-bundle/tests/self-contained-bundler-config.test.ts', 'packages/agent-bundle/tests/serve-app.test.ts', 'packages/agent-bundle/tests/target-hook-contract.test.ts', 'packages/agent-bundle/tests/target-mcp-runtime.test.ts', diff --git a/website/docs/en/guide/authoring/package-entries.mdx b/website/docs/en/guide/authoring/package-entries.mdx index 1577f283a..139f95b74 100644 --- a/website/docs/en/guide/authoring/package-entries.mdx +++ b/website/docs/en/guide/authoring/package-entries.mdx @@ -251,8 +251,11 @@ async chunks, output roots, self-containment — fails the build with a hard dia silently overriding the contract. Reserved module specifiers are protected the same way: a hatch that externalizes `agent-bundle/mcp-entry`, `agent-bundle/meta`, or `agent-bundle/mcp-apps` fails the build, at config inspection for statically visible `externals` and through a post-build scan -for function-form ones. The hatch customizes *how code compiles*, never *what the artifact -promises*. +for function-form ones. Run-time path references are kept the same way: a +`new URL(…, import.meta.url)` or `new Worker(new URL(…))` in your code or a generated entry names +a file beside the artifact, so the invariant layer turns the bundler's URL and worker asset +processing off after the hatch and the expression reaches the artifact verbatim. The hatch +customizes *how code compiles*, never *what the artifact promises*. The hatch merges *beside* the framework profile: `plugins` arrays concatenate, and Rsbuild never dedupes plugins by name. Re-adding a plugin the framework already registers — `@rsbuild/plugin-react` @@ -260,12 +263,13 @@ dedupes plugins by name. Re-adding a plugin the framework already registers — through `tools.rsbuild.plugins` would run it twice, so `agent-bundle validate` reports it as `AB4724` naming the plugin and its package. Remove the entry; the framework registers it for you. -One dual-engine caveat: artifact scripts, MCP entries, hook wrappers, and the package build -compile through Rslib and run under the bundler versions nested inside `@rslib/core`, while MCP -App views compile through the workspace-pinned `@rsbuild/core`. A class imported from a -separately installed `@rspack/core` therefore has a different identity than whichever engine -executes the config. Never construct plugins or run `instanceof` checks against an imported -`@rspack/core` — use the utils argument passed to mutator functions instead: +One engine-identity caveat: artifact scripts, MCP entries, hook wrappers, and the package build +compile through Rslib, and MCP App views through `@rsbuild/core`; agent-bundle pins both so a +project installs a single `@rsbuild/core` and a single `@rspack/core`, but that engine is +agent-bundle's dependency, not yours. A class imported from a separately installed `@rspack/core` +can therefore have a different identity than the engine executing the config. Never construct +plugins or run `instanceof` checks against an imported `@rspack/core` — use the utils argument +passed to mutator functions instead: ```ts tools: { diff --git a/website/docs/en/reference/cli.mdx b/website/docs/en/reference/cli.mdx index 2a6015505..dfa7387d0 100644 --- a/website/docs/en/reference/cli.mdx +++ b/website/docs/en/reference/cli.mdx @@ -240,7 +240,7 @@ from `eval`. | Flag | Focus | | --- | --- | -| `--bundler` | The synthesized bundler configuration. | +| `--bundler` | The synthesized bundler configuration, lowered as the production build lowers it regardless of `NODE_ENV`. | | `--hooks` | Hooks. | | `--routes` | The compiled route graph. | | `--skills` | Skills. | diff --git a/website/docs/en/reference/configuration.mdx b/website/docs/en/reference/configuration.mdx index 8f56a74d0..780b86d75 100644 --- a/website/docs/en/reference/configuration.mdx +++ b/website/docs/en/reference/configuration.mdx @@ -185,12 +185,13 @@ hatch value that breaks an artifact contract is a hard diagnostic rather than a (`@rsbuild/plugin-react`, `rsbuild:react`), because `plugins` arrays concatenate and Rsbuild never dedupes plugins by name — the framework registers it for you. -The hatch executes under two bundler engine copies: artifact scripts, MCP entries, hooks, and the -package build compile through Rslib's nested Rsbuild/Rspack, while MCP App views compile through -the workspace-pinned `@rsbuild/core`. Never construct plugins or perform `instanceof` checks -against an imported `@rspack/core` — use the `utils` argument passed to `tools.rspack` mutator -functions (`(config, { rspack }) => ...`), which always hands you the executing engine's own -`rspack` object. +The hatch executes on one bundler engine — the `@rspack/core` behind agent-bundle's pinned +`@rsbuild/core`, shared by the Rslib-compiled outputs (artifact scripts, MCP entries, hooks, the +package build) and the MCP App views — but that engine is agent-bundle's dependency, not your +project's. Never construct plugins or perform `instanceof` checks against an imported +`@rspack/core` — use the `utils` argument passed to `tools.rspack` mutator functions +(`(config, { rspack }) => ...`), which always hands you the executing engine's own `rspack` +object. ### Plugins diff --git a/website/docs/zh/guide/authoring/package-entries.mdx b/website/docs/zh/guide/authoring/package-entries.mdx index 9cfd9ab0f..0784eb299 100644 --- a/website/docs/zh/guide/authoring/package-entries.mdx +++ b/website/docs/zh/guide/authoring/package-entries.mdx @@ -221,18 +221,21 @@ npx agent-bundle prepack --root . --output artifact --json 合并之后运行。破坏产物契约的取值——异步 chunk、输出根目录、自包含性——会以硬诊断让构建失败,而不是 悄悄覆盖契约。保留的模块 specifier 也以同样方式受到保护:把 `agent-bundle/mcp-entry`、 `agent-bundle/meta` 或 `agent-bundle/mcp-apps` 外部化的逃生舱会让构建失败——对静态可见的 `externals` -在配置检查阶段失败,对函数形式的则通过构建后扫描失败。逃生舱定制的是*代码如何编译*,绝不是*产物承诺 -了什么*。 +在配置检查阶段失败,对函数形式的则通过构建后扫描失败。运行时路径引用也以同样方式得到保留:你的代码或 +生成入口中的 `new URL(…, import.meta.url)` 或 `new Worker(new URL(…))` 指向的是产物旁的一个文件,因此 +不变量层会在逃生舱之后关闭打包器对 URL 与 worker 的静态资源处理,让该表达式原样进入产物。逃生舱定制的是 +*代码如何编译*,绝不是*产物承诺了什么*。 逃生舱是*并列*合并到框架配置旁边的:`plugins` 数组会拼接,而 Rsbuild 从不按名称去重插件。通过 `tools.rsbuild.plugins` 再次添加框架已经注册的插件——`@rsbuild/plugin-react`(`rsbuild:react`), 每个合成入口与每个使用 React 语法的 MCP App 视图都带着它——会让它运行两次,因此 `agent-bundle validate` 会以 `AB4724` 报告,并点名该插件及其包名。删除这一项即可;框架会替你注册它。 -有一个双引擎注意事项:产物脚本、MCP 入口、钩子包装层与包构建通过 Rslib 编译,运行在 `@rslib/core` -内嵌的打包器版本之下;而 MCP App 视图通过工作区固定的 `@rsbuild/core` 编译。因此,从单独安装的 -`@rspack/core` 导入的类,与实际执行配置的那个引擎的类身份并不相同。切勿针对导入的 `@rspack/core` -构造插件或执行 `instanceof` 检查——请改用传给 mutator 函数的 utils 参数: +有一个引擎身份注意事项:产物脚本、MCP 入口、钩子包装层与包构建通过 Rslib 编译,MCP App 视图通过 +`@rsbuild/core` 编译;agent-bundle 固定了两者的版本,使项目只安装一个 `@rsbuild/core` 与一个 +`@rspack/core`,但这个引擎是 agent-bundle 的依赖,而不是你的依赖。因此,从单独安装的 `@rspack/core` +导入的类,与实际执行配置的那个引擎的类身份可能并不相同。切勿针对导入的 `@rspack/core` 构造插件或执行 +`instanceof` 检查——请改用传给 mutator 函数的 utils 参数: ```ts tools: { diff --git a/website/docs/zh/reference/cli.mdx b/website/docs/zh/reference/cli.mdx index e74e56c53..fef1d32f5 100644 --- a/website/docs/zh/reference/cli.mdx +++ b/website/docs/zh/reference/cli.mdx @@ -222,7 +222,7 @@ keep-data 选项)。相对包的安装器 bin 接受带同样标志的 `uninst | 标志 | 聚焦于 | | --- | --- | -| `--bundler` | 合成出来的打包器配置。 | +| `--bundler` | 合成出来的打包器配置,无论 `NODE_ENV` 为何,都按生产构建的方式降级。 | | `--hooks` | 钩子。 | | `--routes` | 编译后的路由图。 | | `--skills` | Skill。 | diff --git a/website/docs/zh/reference/configuration.mdx b/website/docs/zh/reference/configuration.mdx index 55ffc84f0..387764123 100644 --- a/website/docs/zh/reference/configuration.mdx +++ b/website/docs/zh/reference/configuration.mdx @@ -169,10 +169,11 @@ export default defineConfig({ `tools.rsbuild.plugins` 中再次添加框架自有插件(`@rsbuild/plugin-react`,`rsbuild:react`)的条目, 因为 `plugins` 数组会拼接、而 Rsbuild 从不按名称去重插件——框架会替你注册它。 -逃生舱在两份打包器引擎副本下执行:产物脚本、MCP 入口、钩子与包构建通过 Rslib 内嵌的 Rsbuild/Rspack 编译, -而 MCP App 视图通过工作区固定的 `@rsbuild/core` 编译。绝不要基于导入的 `@rspack/core` 构造插件或执行 -`instanceof` 检查——请使用传给 `tools.rspack` 变更函数的 `utils` 参数 -(`(config, { rspack }) => ...`),它总会交给你当前执行引擎自己的 `rspack` 对象。 +逃生舱在同一个打包器引擎上执行——即 agent-bundle 所固定的 `@rsbuild/core` 背后的那个 `@rspack/core`, +由 Rslib 编译的输出(产物脚本、MCP 入口、钩子、包构建)与 MCP App 视图共用——但这个引擎是 agent-bundle +的依赖,而不是你项目的依赖。绝不要基于导入的 `@rspack/core` 构造插件或执行 `instanceof` 检查——请使用 +传给 `tools.rspack` 变更函数的 `utils` 参数(`(config, { rspack }) => ...`),它总会交给你当前执行引擎 +自己的 `rspack` 对象。 ### 插件 From 2de1c824d8a54600923654f81661105ce0d6823c Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Sat, 5 Sep 2026 01:23:14 +0000 Subject: [PATCH 2/6] chore: reference #575 in the rslib-1 changeset --- .changeset/rslib-1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/rslib-1.md b/.changeset/rslib-1.md index 62e6738bf..2f2943224 100644 --- a/.changeset/rslib-1.md +++ b/.changeset/rslib-1.md @@ -11,4 +11,4 @@ keep `new URL(…, import.meta.url)` and `new Worker(new URL(…))` expressions `agent-bundle inspect --bundler` lowers in production mode regardless of `NODE_ENV` and shows the new `bundlerChain` invariant beside `tools.rspack`. Published `.d.ts` files now import their siblings with `.js` specifiers, and `@agent-bundle/runtime`'s shared chunks are named -`~0.js`; every `exports` entry resolves as before. (#PR) +`~0.js`; every `exports` entry resolves as before. (#575) From 261ff7a2e723109cb204d959317649d317bb9e57 Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Sat, 5 Sep 2026 01:30:10 +0000 Subject: [PATCH 3/6] fix(build): hand an unset NODE_ENV back after inspecting, even when the inspection throws --- packages/agent-bundle/src/build/rslib.ts | 11 +++++++---- packages/agent-bundle/tests/build.test.ts | 23 +++++++++++++++++++++++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/packages/agent-bundle/src/build/rslib.ts b/packages/agent-bundle/src/build/rslib.ts index 8c9707f08..2744c4571 100644 --- a/packages/agent-bundle/src/build/rslib.ts +++ b/packages/agent-bundle/src/build/rslib.ts @@ -76,9 +76,11 @@ const preserveResourceReferences: RslibBundlerChain = (chain) => { * production build `rslib.build()` runs. Rslib 1.x otherwise infers the mode * from `NODE_ENV`, and under `development` inspects only `mf` libs — none * here — so `assertExecutableConfig` and `inspect --bundler` would fail. Rslib - * writes the inspected mode back to `NODE_ENV`; a process that had set it - * (a development server, a test runner) keeps its own value, while an unset - * one is left at `production`, exactly as `rslib.build()` leaves it. + * writes the inspected mode back to `NODE_ENV`; the process gets its own value + * back — set or unset — whether the inspection succeeded or threw, so a + * development server or test runner that inspects a config is not left + * running as `production`. (`rslib.build()` sets `production` itself when it + * finds `NODE_ENV` unset; that is the build's business, not the inspection's.) */ const inspectProductionConfig = async ( rslib: Pick, @@ -87,7 +89,8 @@ const inspectProductionConfig = async ( try { return await rslib.inspectConfig({ mode: 'production' }); } finally { - if (nodeEnv !== undefined) process.env.NODE_ENV = nodeEnv; + if (nodeEnv === undefined) delete process.env.NODE_ENV; + else process.env.NODE_ENV = nodeEnv; } }; type RslibLibConfig = LibConfig; diff --git a/packages/agent-bundle/tests/build.test.ts b/packages/agent-bundle/tests/build.test.ts index c1b0d1e0c..5d2570d50 100644 --- a/packages/agent-bundle/tests/build.test.ts +++ b/packages/agent-bundle/tests/build.test.ts @@ -1198,6 +1198,29 @@ it('lowers every bundler config and builds under NODE_ENV=development, leaving N } }, 20_000); +it('leaves NODE_ENV unset when a failing inspection had set it', async () => { + const { entry, root } = await reservedSpecifierProject(); + const previousNodeEnv = process.env.NODE_ENV; + delete process.env.NODE_ENV; + try { + await expect(buildWithRslib({ cwd: root, entries: [entry], meta: testMeta, outputRoot: join(root, 'dist') }, { + createRslib: async () => ({ + build: () => Promise.reject(new Error('build must not run after a failed inspection')), + inspectConfig: async () => { + // Rslib writes the requested mode to NODE_ENV before it can fail. + process.env.NODE_ENV = 'production'; + throw new Error('inspection failed'); + }, + }), + })).rejects.toThrow('inspection failed'); + expect(process.env.NODE_ENV).toBeUndefined(); + } finally { + if (previousNodeEnv === undefined) delete process.env.NODE_ENV; + else process.env.NODE_ENV = previousNodeEnv; + await rm(root, { force: true, recursive: true }); + } +}); + it('leaves filesystem URL and worker expressions in the emitted bundle untouched', async () => { const root = await mkdtemp(join(tmpdir(), 'agent-bundle-resource-references-')); const sourceRoot = join(root, 'src'); From f023b4bc2f8e883bda2ef10cbc12137f3d5c7689 Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Sat, 5 Sep 2026 01:32:26 +0000 Subject: [PATCH 4/6] docs: name the Rslib 1 option shape (output.autoExternal) in AGENTS.md --- AGENTS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index 68eb083ab..97603ca35 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -66,7 +66,7 @@ - Generated plugin output is self-contained. The compiler profile in `packages/agent-bundle/src/build/rslib.ts` (`composeEntryLibConfig`) bundles - every dependency of a generated executable — `autoExternal: false`, + every dependency of a generated executable — `output.autoExternal: false`, `bundle: true`, `splitChunks: false`, no `externals`. Rslib's `node` target leaves only Node built-ins (and `pnpapi`) external, and the only bare specifiers `AB6005` accepts in a host-pack module are Node built-ins, so a From 3bcaa47bf4a1d53bb1ab4d7eec2bb7544c8e10e2 Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Sat, 5 Sep 2026 01:52:53 +0000 Subject: [PATCH 5/6] docs(types): state the one-engine hatch reality on AgentBundleToolsConfig (Codex review) --- packages/agent-bundle/src/build/meta.ts | 7 ++++--- packages/agent-bundle/src/build/rslib.ts | 13 +++++++------ packages/agent-bundle/src/core/types.ts | 21 +++++++++++---------- 3 files changed, 22 insertions(+), 19 deletions(-) diff --git a/packages/agent-bundle/src/build/meta.ts b/packages/agent-bundle/src/build/meta.ts index 7187b23bb..203cd250c 100644 --- a/packages/agent-bundle/src/build/meta.ts +++ b/packages/agent-bundle/src/build/meta.ts @@ -121,9 +121,10 @@ interface VirtualModulesEngine { * surface is the cost of never touching the artifact tree with build-time * scratch files. This narrow feature check turns an upstream rename or * removal into an actionable diagnostic instead of an opaque resolution - * failure deep inside a build. Rsbuild and Rslib carry independent Rspack - * copies (the dual-engine reality documented on `AgentBundleToolsConfig`), - * so each build path checks its own `rspack` and names its own package. + * failure deep inside a build. Rsbuild and Rslib resolve their Rspack + * independently (one engine today, held by a packed test; see + * `AgentBundleToolsConfig`), so each build path checks the `rspack` it + * actually executes under and names its own package. */ export const virtualModulesPluginConstructor = ( rspack: Engine, diff --git a/packages/agent-bundle/src/build/rslib.ts b/packages/agent-bundle/src/build/rslib.ts index 2744c4571..5588c957d 100644 --- a/packages/agent-bundle/src/build/rslib.ts +++ b/packages/agent-bundle/src/build/rslib.ts @@ -105,12 +105,13 @@ const rslibVirtualModulesPlugin = (): typeof rspack.experiments.VirtualModulesPl virtualModulesPluginConstructor(rspack, '@rslib/core', 'serve generated wrapper and registry modules'); /** - * The tools escape hatch is typed against the workspace `@rsbuild/core` (the - * engine of the MCP Apps path), while this build path executes under the - * Rsbuild/Rspack copies nested in `@rslib/core` (the dual-engine reality - * documented on {@link AgentBundleToolsConfig}). These two functions are the - * single deliberate crossing between those type universes; everything else - * in this module stays inside Rslib's own types. + * The tools escape hatch is typed against the workspace `@rsbuild/core`, + * while this build path speaks Rslib's `LibConfig`, which imports its + * Rsbuild types through `@rslib/core`'s own dependency edge (the same + * package today — see {@link AgentBundleToolsConfig} — but a separate type + * universe for the compiler). These two functions are the single deliberate + * crossing between them; everything else in this module stays inside Rslib's + * own types. */ const asRslibEnvironmentFragment = ( fragment: NonNullable, diff --git a/packages/agent-bundle/src/core/types.ts b/packages/agent-bundle/src/core/types.ts index 4abdb265e..242089d14 100644 --- a/packages/agent-bundle/src/core/types.ts +++ b/packages/agent-bundle/src/core/types.ts @@ -243,16 +243,17 @@ export type AgentBundleLibConfig = false | string | AgentBundleLibEntry; * breaks an artifact contract is a hard diagnostic, never a silent override. * Consumers never need a second bundler config file. * - * Dual-engine reality: the hatch executes under two bundler engine copies. - * Artifact scripts, MCP entries, hooks, and the package build compile - * through Rslib and run under the Rsbuild/Rspack versions nested in - * `@rslib/core` (currently the 2.1.x line); MCP App views compile through - * the workspace-pinned `@rsbuild/core` (2.2.x). These types come from the - * latter. Hatch authors must therefore never construct plugins or perform - * `instanceof` checks against an imported `@rspack/core` — use the utils - * argument Rslib/Rsbuild pass to `tools.rspack` mutator functions - * (`(config, { rspack }) => ...`), which always hands the executing - * engine's own `rspack` object. + * Engine identity: the hatch executes on one bundler engine — the + * `@rspack/core` behind agent-bundle's pinned `@rsbuild/core`, shared by the + * Rslib-compiled outputs (artifact scripts, MCP entries, hooks, the package + * build) and the MCP App views — and these types come from that + * `@rsbuild/core`. That engine is agent-bundle's dependency, not the + * consumer's: a class imported from a separately installed `@rspack/core` + * can have a different identity, so hatch authors must never construct + * plugins or perform `instanceof` checks against an imported `@rspack/core` + * — use the utils argument Rslib/Rsbuild pass to `tools.rspack` mutator + * functions (`(config, { rspack }) => ...`), which always hands the + * executing engine's own `rspack` object. */ export interface AgentBundleToolsConfig { /** Rsbuild environment-config fragment merged after the synthesized profile. */ From d6a509e4e53684d7037dd41d457233dd5dbfc9d1 Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Sat, 5 Sep 2026 02:35:14 +0000 Subject: [PATCH 6/6] chore: drop the runtime chunk-name note from the rslib-1 changeset (superseded by #571's single module graph) --- .changeset/rslib-1.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.changeset/rslib-1.md b/.changeset/rslib-1.md index 2f2943224..9d3b9544f 100644 --- a/.changeset/rslib-1.md +++ b/.changeset/rslib-1.md @@ -9,6 +9,6 @@ binding instead of two; `create-agent-bundle` templates pin `@rstest/core` 0.11. builds stay self-contained (`output.autoExternal: false`, Node builtins the only externals) and keep `new URL(…, import.meta.url)` and `new Worker(new URL(…))` expressions verbatim. `agent-bundle inspect --bundler` lowers in production mode regardless of `NODE_ENV` and shows the -new `bundlerChain` invariant beside `tools.rspack`. Published `.d.ts` files now import their -siblings with `.js` specifiers, and `@agent-bundle/runtime`'s shared chunks are named -`~0.js`; every `exports` entry resolves as before. (#575) +new `bundlerChain` invariant beside `tools.rspack`. Published `.d.ts` files (`agent-bundle`, +`@agent-bundle/runtime`) now import their siblings with `.js` specifiers; every `exports` entry +resolves as before. (#575)