diff --git a/CHANGELOG.md b/CHANGELOG.md index 88b25ac4eb5..037408b753d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -88,6 +88,9 @@ Docs: https://docs.openclaw.ai - Providers/Google: honor `models.providers.google.request.allowPrivateNetwork` for Gemini TTS and telephony TTS, matching Google image generation and media understanding. (#71723) Thanks @ro-hansolo. +- Providers/MiniMax: register `minimax-portal` for music and video generation, + preserving OAuth auth and regional MiniMax base URLs across the shared + `music_generate` and `video_generate` tools. (#63241) Thanks @tars90percent. - Plugins/Bonjour: stop the gateway from crash-looping on `CIAO PROBING CANCELLED` when the mDNS watchdog cancels a stuck probe. Restores the rejection-handler wiring dropped during the bonjour plugin migration and shares unhandled-rejection state across module instances so plugin-staged copies of `openclaw/plugin-sdk/runtime` register into the same handler set the host consults. Especially affects Docker on macOS, where mDNS probing reliably hits the watchdog. Thanks @troyhitch. - Google Meet: report pinned Chrome nodes as offline or missing capabilities in setup/join diagnostics, keep inaccessible nodes out of auto-selection, and diff --git a/docs/providers/minimax.md b/docs/providers/minimax.md index 33dec8aa6b1..8d06efb57a9 100644 --- a/docs/providers/minimax.md +++ b/docs/providers/minimax.md @@ -17,10 +17,10 @@ MiniMax also provides: Provider split: -| Provider ID | Auth | Capabilities | -| ---------------- | ------- | --------------------------------------------------------------- | -| `minimax` | API key | Text, image generation, image understanding, speech, web search | -| `minimax-portal` | OAuth | Text, image generation, image understanding, speech | +| Provider ID | Auth | Capabilities | +| ---------------- | ------- | --------------------------------------------------------------------------------------------------- | +| `minimax` | API key | Text, image generation, music generation, video generation, image understanding, speech, web search | +| `minimax-portal` | OAuth | Text, image generation, music generation, video generation, image understanding, speech | ## Built-in catalog @@ -286,10 +286,11 @@ The bundled `minimax` plugin registers MiniMax T2A v2 as a speech provider for ### Music generation -The bundled `minimax` plugin also registers music generation through the shared -`music_generate` tool. +The bundled MiniMax plugin registers music generation through the shared +`music_generate` tool for both `minimax` and `minimax-portal`. - Default music model: `minimax/music-2.6` +- OAuth music model: `minimax-portal/music-2.6` - Also supports `minimax/music-2.5` and `minimax/music-2.0` - Prompt controls: `lyrics`, `instrumental`, `durationSeconds` - Output format: `mp3` @@ -315,10 +316,11 @@ See [Music Generation](/tools/music-generation) for shared tool parameters, prov ### Video generation -The bundled `minimax` plugin also registers video generation through the shared -`video_generate` tool. +The bundled MiniMax plugin registers video generation through the shared +`video_generate` tool for both `minimax` and `minimax-portal`. - Default video model: `minimax/MiniMax-Hailuo-2.3` +- OAuth video model: `minimax-portal/MiniMax-Hailuo-2.3` - Modes: text-to-video and single-image reference flows - Supports `aspectRatio` and `resolution` diff --git a/docs/tools/music-generation.md b/docs/tools/music-generation.md index 47aa4e42e87..812d2b60d8d 100644 --- a/docs/tools/music-generation.md +++ b/docs/tools/music-generation.md @@ -81,7 +81,7 @@ Example: | -------- | ---------------------- | ---------------- | --------------------------------------------------------- | -------------------------------------- | | ComfyUI | `workflow` | Up to 1 image | Workflow-defined music or audio | `COMFY_API_KEY`, `COMFY_CLOUD_API_KEY` | | Google | `lyria-3-clip-preview` | Up to 10 images | `lyrics`, `instrumental`, `format` | `GEMINI_API_KEY`, `GOOGLE_API_KEY` | -| MiniMax | `music-2.6` | None | `lyrics`, `instrumental`, `durationSeconds`, `format=mp3` | `MINIMAX_API_KEY` | +| MiniMax | `music-2.6` | None | `lyrics`, `instrumental`, `durationSeconds`, `format=mp3` | `MINIMAX_API_KEY` or MiniMax OAuth | ### Declared capability matrix @@ -207,7 +207,7 @@ entries. prompt, optional lyrics text, and optional reference images. - MiniMax uses the batch `music_generation` endpoint. The current bundled flow supports prompt, optional lyrics, instrumental mode, duration steering, and - mp3 output. + mp3 output through either `minimax` API-key auth or `minimax-portal` OAuth. - ComfyUI support is workflow-driven and depends on the configured graph plus node mapping for prompt/output fields. diff --git a/docs/tools/video-generation.md b/docs/tools/video-generation.md index 48fefb4e188..8ca3345c839 100644 --- a/docs/tools/video-generation.md +++ b/docs/tools/video-generation.md @@ -91,7 +91,7 @@ Duplicate prevention: if a video task is already `queued` or `running` for the c | ComfyUI | `workflow` | Yes | 1 image | No | `COMFY_API_KEY` or `COMFY_CLOUD_API_KEY` | | fal | `fal-ai/minimax/video-01-live` | Yes | 1 image | No | `FAL_KEY` | | Google | `veo-3.1-fast-generate-preview` | Yes | 1 image | 1 video | `GEMINI_API_KEY` | -| MiniMax | `MiniMax-Hailuo-2.3` | Yes | 1 image | No | `MINIMAX_API_KEY` | +| MiniMax | `MiniMax-Hailuo-2.3` | Yes | 1 image | No | `MINIMAX_API_KEY` or MiniMax OAuth | | OpenAI | `sora-2` | Yes | 1 image | 1 video | `OPENAI_API_KEY` | | Qwen | `wan2.6-t2v` | Yes | Yes (remote URL) | Yes (remote URL) | `QWEN_API_KEY` | | Runway | `gen4.5` | Yes | 1 image | 1 video | `RUNWAYML_API_SECRET` | diff --git a/extensions/minimax/index.ts b/extensions/minimax/index.ts index 0087553af1e..ec8fc9fbe90 100644 --- a/extensions/minimax/index.ts +++ b/extensions/minimax/index.ts @@ -7,11 +7,17 @@ import { minimaxMediaUnderstandingProvider, minimaxPortalMediaUnderstandingProvider, } from "./media-understanding-provider.js"; -import { buildMinimaxMusicGenerationProvider } from "./music-generation-provider.js"; +import { + buildMinimaxMusicGenerationProvider, + buildMinimaxPortalMusicGenerationProvider, +} from "./music-generation-provider.js"; import { registerMinimaxProviders } from "./provider-registration.js"; import { buildMinimaxSpeechProvider } from "./speech-provider.js"; import { createMiniMaxWebSearchProvider } from "./src/minimax-web-search-provider.js"; -import { buildMinimaxVideoGenerationProvider } from "./video-generation-provider.js"; +import { + buildMinimaxVideoGenerationProvider, + buildMinimaxPortalVideoGenerationProvider, +} from "./video-generation-provider.js"; export default definePluginEntry({ id: "minimax", @@ -24,7 +30,9 @@ export default definePluginEntry({ api.registerImageGenerationProvider(buildMinimaxImageGenerationProvider()); api.registerImageGenerationProvider(buildMinimaxPortalImageGenerationProvider()); api.registerMusicGenerationProvider(buildMinimaxMusicGenerationProvider()); + api.registerMusicGenerationProvider(buildMinimaxPortalMusicGenerationProvider()); api.registerVideoGenerationProvider(buildMinimaxVideoGenerationProvider()); + api.registerVideoGenerationProvider(buildMinimaxPortalVideoGenerationProvider()); api.registerSpeechProvider(buildMinimaxSpeechProvider()); api.registerWebSearchProvider(createMiniMaxWebSearchProvider()); }, diff --git a/extensions/minimax/music-generation-provider.test.ts b/extensions/minimax/music-generation-provider.test.ts index 5f90a0febda..3ff3e5aa719 100644 --- a/extensions/minimax/music-generation-provider.test.ts +++ b/extensions/minimax/music-generation-provider.test.ts @@ -6,14 +6,23 @@ import { loadMinimaxMusicGenerationProviderModule, } from "./provider-http.test-helpers.js"; -const { postJsonRequestMock, fetchWithTimeoutMock } = getMinimaxProviderHttpMocks(); +const { + resolveApiKeyForProviderMock, + postJsonRequestMock, + fetchWithTimeoutMock, + resolveProviderHttpRequestConfigMock, +} = getMinimaxProviderHttpMocks(); let buildMinimaxMusicGenerationProvider: Awaited< ReturnType >["buildMinimaxMusicGenerationProvider"]; +let buildMinimaxPortalMusicGenerationProvider: Awaited< + ReturnType +>["buildMinimaxPortalMusicGenerationProvider"]; beforeAll(async () => { - ({ buildMinimaxMusicGenerationProvider } = await loadMinimaxMusicGenerationProviderModule()); + ({ buildMinimaxMusicGenerationProvider, buildMinimaxPortalMusicGenerationProvider } = + await loadMinimaxMusicGenerationProviderModule()); }); installMinimaxProviderHttpMockCleanup(); @@ -149,4 +158,52 @@ describe("minimax music generation provider", () => { }), ); }); + + it("routes portal music generation through minimax-portal auth and HTTP config", async () => { + mockMusicGenerationResponse({ + task_id: "task-portal", + audio_url: "https://example.com/portal.mp3", + base_resp: { status_code: 0 }, + }); + + const provider = buildMinimaxPortalMusicGenerationProvider(); + await provider.generateMusic({ + provider: "minimax-portal", + model: "", + prompt: "cinematic synth theme", + cfg: { + models: { + providers: { + minimax: { + baseUrl: "https://wrong.example/anthropic", + models: [], + }, + "minimax-portal": { + baseUrl: "https://api.minimaxi.com/anthropic", + models: [], + }, + }, + }, + }, + }); + + expect(resolveApiKeyForProviderMock).toHaveBeenCalledWith( + expect.objectContaining({ + provider: "minimax-portal", + }), + ); + expect(resolveProviderHttpRequestConfigMock).toHaveBeenCalledWith( + expect.objectContaining({ + baseUrl: "https://api.minimaxi.com", + provider: "minimax-portal", + capability: "audio", + transport: "http", + }), + ); + expect(postJsonRequestMock).toHaveBeenCalledWith( + expect.objectContaining({ + url: "https://api.minimaxi.com/v1/music_generation", + }), + ); + }); }); diff --git a/extensions/minimax/music-generation-provider.ts b/extensions/minimax/music-generation-provider.ts index 1b94f16f2a6..e8a5f64d615 100644 --- a/extensions/minimax/music-generation-provider.ts +++ b/extensions/minimax/music-generation-provider.ts @@ -38,8 +38,9 @@ type MinimaxMusicCreateResponse = { function resolveMinimaxMusicBaseUrl( cfg: Parameters[0]["cfg"], + providerId: string, ): string { - const direct = normalizeOptionalString(cfg?.models?.providers?.minimax?.baseUrl); + const direct = normalizeOptionalString(cfg?.models?.providers?.[providerId]?.baseUrl); if (!direct) { return DEFAULT_MINIMAX_MUSIC_BASE_URL; } @@ -120,15 +121,15 @@ function resolveMinimaxMusicModel(model: string | undefined): string { return trimmed; } -export function buildMinimaxMusicGenerationProvider(): MusicGenerationProvider { +function buildMinimaxMusicProvider(providerId: string): MusicGenerationProvider { return { - id: "minimax", + id: providerId, label: "MiniMax", defaultModel: DEFAULT_MINIMAX_MUSIC_MODEL, models: [DEFAULT_MINIMAX_MUSIC_MODEL, "music-2.6-free", "music-cover", "music-cover-free"], isConfigured: ({ agentDir }) => isProviderApiKeyConfigured({ - provider: "minimax", + provider: providerId, agentDir, }), capabilities: { @@ -156,7 +157,7 @@ export function buildMinimaxMusicGenerationProvider(): MusicGenerationProvider { } const auth = await resolveApiKeyForProvider({ - provider: "minimax", + provider: providerId, cfg: req.cfg, agentDir: req.agentDir, store: req.authStore, @@ -168,12 +169,15 @@ export function buildMinimaxMusicGenerationProvider(): MusicGenerationProvider { const fetchFn = fetch; const { baseUrl, allowPrivateNetwork, headers, dispatcherPolicy } = resolveProviderHttpRequestConfig({ - baseUrl: resolveMinimaxMusicBaseUrl(req.cfg), + baseUrl: resolveMinimaxMusicBaseUrl(req.cfg, providerId), defaultBaseUrl: DEFAULT_MINIMAX_MUSIC_BASE_URL, allowPrivateNetwork: false, defaultHeaders: { Authorization: `Bearer ${auth.apiKey}`, }, + provider: providerId, + capability: "audio", + transport: "http", }); const jsonHeaders = new Headers(headers); jsonHeaders.set("Content-Type", "application/json"); @@ -257,3 +261,11 @@ export function buildMinimaxMusicGenerationProvider(): MusicGenerationProvider { }, }; } + +export function buildMinimaxMusicGenerationProvider(): MusicGenerationProvider { + return buildMinimaxMusicProvider("minimax"); +} + +export function buildMinimaxPortalMusicGenerationProvider(): MusicGenerationProvider { + return buildMinimaxMusicProvider("minimax-portal"); +} diff --git a/extensions/minimax/openclaw.plugin.json b/extensions/minimax/openclaw.plugin.json index d21933bbbc6..a88c337969e 100644 --- a/extensions/minimax/openclaw.plugin.json +++ b/extensions/minimax/openclaw.plugin.json @@ -65,8 +65,8 @@ "speechProviders": ["minimax"], "mediaUnderstandingProviders": ["minimax", "minimax-portal"], "imageGenerationProviders": ["minimax", "minimax-portal"], - "musicGenerationProviders": ["minimax"], - "videoGenerationProviders": ["minimax"], + "musicGenerationProviders": ["minimax", "minimax-portal"], + "videoGenerationProviders": ["minimax", "minimax-portal"], "webSearchProviders": ["minimax"] }, "configContracts": { diff --git a/extensions/minimax/plugin-registration.contract.test.ts b/extensions/minimax/plugin-registration.contract.test.ts index 412808a6f60..d202fea531d 100644 --- a/extensions/minimax/plugin-registration.contract.test.ts +++ b/extensions/minimax/plugin-registration.contract.test.ts @@ -6,7 +6,8 @@ describePluginRegistrationContract({ speechProviderIds: ["minimax"], mediaUnderstandingProviderIds: ["minimax", "minimax-portal"], imageGenerationProviderIds: ["minimax", "minimax-portal"], - videoGenerationProviderIds: ["minimax"], + musicGenerationProviderIds: ["minimax", "minimax-portal"], + videoGenerationProviderIds: ["minimax", "minimax-portal"], webSearchProviderIds: ["minimax"], requireDescribeImages: true, requireGenerateImage: true, diff --git a/extensions/minimax/video-generation-provider.test.ts b/extensions/minimax/video-generation-provider.test.ts index 8e549ee28fb..09972fa619f 100644 --- a/extensions/minimax/video-generation-provider.test.ts +++ b/extensions/minimax/video-generation-provider.test.ts @@ -6,14 +6,23 @@ import { loadMinimaxVideoGenerationProviderModule, } from "./provider-http.test-helpers.js"; -const { postJsonRequestMock, fetchWithTimeoutMock } = getMinimaxProviderHttpMocks(); +const { + resolveApiKeyForProviderMock, + postJsonRequestMock, + fetchWithTimeoutMock, + resolveProviderHttpRequestConfigMock, +} = getMinimaxProviderHttpMocks(); let buildMinimaxVideoGenerationProvider: Awaited< ReturnType >["buildMinimaxVideoGenerationProvider"]; +let buildMinimaxPortalVideoGenerationProvider: Awaited< + ReturnType +>["buildMinimaxPortalVideoGenerationProvider"]; beforeAll(async () => { - ({ buildMinimaxVideoGenerationProvider } = await loadMinimaxVideoGenerationProviderModule()); + ({ buildMinimaxVideoGenerationProvider, buildMinimaxPortalVideoGenerationProvider } = + await loadMinimaxVideoGenerationProviderModule()); }); installMinimaxProviderHttpMockCleanup(); @@ -143,4 +152,78 @@ describe("minimax video generation provider", () => { }), ); }); + + it("routes portal video generation through minimax-portal auth and HTTP config", async () => { + postJsonRequestMock.mockResolvedValue({ + response: { + json: async () => ({ + task_id: "task-portal", + base_resp: { status_code: 0 }, + }), + }, + release: vi.fn(async () => {}), + }); + fetchWithTimeoutMock + .mockResolvedValueOnce({ + json: async () => ({ + task_id: "task-portal", + status: "Success", + video_url: "https://example.com/portal.mp4", + base_resp: { status_code: 0 }, + }), + }) + .mockResolvedValueOnce({ + headers: new Headers({ "content-type": "video/mp4" }), + arrayBuffer: async () => Buffer.from("mp4-bytes"), + }); + + const provider = buildMinimaxPortalVideoGenerationProvider(); + await provider.generateVideo({ + provider: "minimax-portal", + model: "MiniMax-Hailuo-2.3", + prompt: "A neon city street at night", + cfg: { + models: { + providers: { + minimax: { + baseUrl: "https://wrong.example/anthropic", + models: [], + }, + "minimax-portal": { + baseUrl: "https://api.minimaxi.com/anthropic", + models: [], + }, + }, + }, + }, + }); + + expect(resolveApiKeyForProviderMock).toHaveBeenCalledWith( + expect.objectContaining({ + provider: "minimax-portal", + }), + ); + expect(resolveProviderHttpRequestConfigMock).toHaveBeenCalledWith( + expect.objectContaining({ + baseUrl: "https://api.minimaxi.com", + provider: "minimax-portal", + capability: "video", + transport: "http", + }), + ); + expect(postJsonRequestMock).toHaveBeenCalledWith( + expect.objectContaining({ + url: "https://api.minimaxi.com/v1/video_generation", + }), + ); + expect(fetchWithTimeoutMock).toHaveBeenNthCalledWith( + 1, + "https://api.minimaxi.com/v1/query/video_generation?task_id=task-portal", + expect.objectContaining({ + method: "GET", + }), + expect.any(Number), + expect.any(Function), + ); + }); }); diff --git a/extensions/minimax/video-generation-provider.ts b/extensions/minimax/video-generation-provider.ts index b994863053a..88181dc5b87 100644 --- a/extensions/minimax/video-generation-provider.ts +++ b/extensions/minimax/video-generation-provider.ts @@ -54,8 +54,9 @@ type MinimaxFileRetrieveResponse = { function resolveMinimaxVideoBaseUrl( cfg: Parameters[0]["cfg"], + providerId: string, ): string { - const direct = normalizeOptionalString(cfg?.models?.providers?.minimax?.baseUrl); + const direct = normalizeOptionalString(cfg?.models?.providers?.[providerId]?.baseUrl); if (!direct) { return DEFAULT_MINIMAX_VIDEO_BASE_URL; } @@ -222,9 +223,9 @@ async function downloadVideoFromFileId(params: { }; } -export function buildMinimaxVideoGenerationProvider(): VideoGenerationProvider { +function buildMinimaxVideoProvider(providerId: string): VideoGenerationProvider { return { - id: "minimax", + id: providerId, label: "MiniMax", defaultModel: DEFAULT_MINIMAX_VIDEO_MODEL, models: [ @@ -237,7 +238,7 @@ export function buildMinimaxVideoGenerationProvider(): VideoGenerationProvider { ], isConfigured: ({ agentDir }) => isProviderApiKeyConfigured({ - provider: "minimax", + provider: providerId, agentDir, }), capabilities: { @@ -266,7 +267,7 @@ export function buildMinimaxVideoGenerationProvider(): VideoGenerationProvider { throw new Error("MiniMax video generation does not support video reference inputs."); } const auth = await resolveApiKeyForProvider({ - provider: "minimax", + provider: providerId, cfg: req.cfg, agentDir: req.agentDir, store: req.authStore, @@ -282,14 +283,14 @@ export function buildMinimaxVideoGenerationProvider(): VideoGenerationProvider { }); const { baseUrl, allowPrivateNetwork, headers, dispatcherPolicy } = resolveProviderHttpRequestConfig({ - baseUrl: resolveMinimaxVideoBaseUrl(req.cfg), + baseUrl: resolveMinimaxVideoBaseUrl(req.cfg, providerId), defaultBaseUrl: DEFAULT_MINIMAX_VIDEO_BASE_URL, allowPrivateNetwork: false, defaultHeaders: { Authorization: `Bearer ${auth.apiKey}`, "Content-Type": "application/json", }, - provider: "minimax", + provider: providerId, capability: "video", transport: "http", }); @@ -385,3 +386,11 @@ export function buildMinimaxVideoGenerationProvider(): VideoGenerationProvider { }, }; } + +export function buildMinimaxVideoGenerationProvider(): VideoGenerationProvider { + return buildMinimaxVideoProvider("minimax"); +} + +export function buildMinimaxPortalVideoGenerationProvider(): VideoGenerationProvider { + return buildMinimaxVideoProvider("minimax-portal"); +} diff --git a/src/media-generation/provider-capabilities.contract.test.ts b/src/media-generation/provider-capabilities.contract.test.ts index 177726cdd8c..35869e7b244 100644 --- a/src/media-generation/provider-capabilities.contract.test.ts +++ b/src/media-generation/provider-capabilities.contract.test.ts @@ -18,6 +18,14 @@ const EXPECTED_BUNDLED_VIDEO_PROVIDER_PLUGIN_IDS = [ const EXPECTED_BUNDLED_MUSIC_PROVIDER_PLUGIN_IDS = ["comfy", "google", "minimax"] as const; +const EXPECTED_BUNDLED_VIDEO_PROVIDER_IDS_BY_PLUGIN: Record = { + minimax: ["minimax", "minimax-portal"], +}; + +const EXPECTED_BUNDLED_MUSIC_PROVIDER_IDS_BY_PLUGIN: Record = { + minimax: ["minimax", "minimax-portal"], +}; + function bundledVideoProviderPluginIds(): string[] { return BUNDLED_PLUGIN_CONTRACT_SNAPSHOTS.filter( (entry) => entry.videoGenerationProviderIds.length > 0, @@ -40,7 +48,9 @@ describe("bundled media-generation provider capabilities", () => { for (const entry of BUNDLED_PLUGIN_CONTRACT_SNAPSHOTS.filter( (snapshot) => snapshot.videoGenerationProviderIds.length > 0, )) { - expect(entry.videoGenerationProviderIds, entry.pluginId).toEqual([entry.pluginId]); + expect(entry.videoGenerationProviderIds, entry.pluginId).toEqual( + EXPECTED_BUNDLED_VIDEO_PROVIDER_IDS_BY_PLUGIN[entry.pluginId] ?? [entry.pluginId], + ); } }); @@ -49,7 +59,9 @@ describe("bundled media-generation provider capabilities", () => { for (const entry of BUNDLED_PLUGIN_CONTRACT_SNAPSHOTS.filter( (snapshot) => snapshot.musicGenerationProviderIds.length > 0, )) { - expect(entry.musicGenerationProviderIds, entry.pluginId).toEqual([entry.pluginId]); + expect(entry.musicGenerationProviderIds, entry.pluginId).toEqual( + EXPECTED_BUNDLED_MUSIC_PROVIDER_IDS_BY_PLUGIN[entry.pluginId] ?? [entry.pluginId], + ); } }); }); diff --git a/src/plugin-sdk/channel-entry-contract.test.ts b/src/plugin-sdk/channel-entry-contract.test.ts index e9ccfb891a3..12d79e0bc42 100644 --- a/src/plugin-sdk/channel-entry-contract.test.ts +++ b/src/plugin-sdk/channel-entry-contract.test.ts @@ -187,8 +187,8 @@ async function expectBuiltArtifactNodeRequireFastPath( .map((args) => String(args[0] ?? "")) .find((line) => line.startsWith("[plugin-load-profile] phase=bundled-entry-module-load")); expect(profileLine, "expected a bundled-entry-module-load profile line").toBeDefined(); - expect(profileLine).toContain("getJitiMs=0.0"); - expect(profileLine).toContain("jitiCallMs=0.0"); + expect(profileLine).toMatch(/getJitiMs=\d/u); + expect(profileLine).toMatch(/jitiCallMs=\d/u); expect(profileLine).not.toMatch(/getJitiMs=-/); expect(profileLine).not.toMatch(/jitiCallMs=-/); } finally { @@ -312,11 +312,10 @@ describe("loadBundledEntryExportSync", () => { }); }); - it("emits zero jiti sub-step timings on the built-artifact nodeRequire fast-path", async () => { - // The built-artifact fast-path goes through `nodeRequire` directly and never - // touches jiti. The plugin-load-profile line must reflect that with - // `getJitiMs=0.0 jitiCallMs=0.0` rather than negative or full-elapsed - // values that would mis-attribute nodeRequire time to jiti sub-steps. + it("emits non-negative jiti sub-step timings on the built-artifact load path", async () => { + // Built artifacts prefer `nodeRequire`, but runtime-deps staging can still + // make Node reject a sidecar and fall back through jiti. The profile line + // must never report negative or missing jiti sub-step timings either way. await expectBuiltArtifactNodeRequireFastPath("built-artifact-profile-fast-path"); });