From eaac52473eec5036d3152ff2a9328055ae73cd04 Mon Sep 17 00:00:00 2001 From: Youzini-afk <13153778771cx@gmail.com> Date: Fri, 10 Apr 2026 15:14:05 +0800 Subject: [PATCH] Fix CI test compatibility on Node 20 --- tests/extractor-owner-scope.mjs | 60 +++++++++--------- tests/helpers/generation-recall-harness.mjs | 15 ++++- tests/helpers/register-hooks-compat.mjs | 54 +++++++++++++++++ tests/llm-model-fetch.mjs | 61 +++++++++---------- tests/llm-streaming.mjs | 61 +++++++++---------- tests/p0-regressions.mjs | 67 ++++++++++----------- tests/prompt-builder-defaults.mjs | 44 ++++++-------- tests/prompt-builder-mvu.mjs | 61 +++++++++---------- tests/st-context-task-ejs.mjs | 26 ++++---- tests/summary-rollup-threshold.mjs | 60 +++++++++--------- tests/task-regex.mjs | 27 ++++----- tests/task-worldinfo.mjs | 43 ++++++------- 12 files changed, 301 insertions(+), 278 deletions(-) create mode 100644 tests/helpers/register-hooks-compat.mjs diff --git a/tests/extractor-owner-scope.mjs b/tests/extractor-owner-scope.mjs index 1bb0040..2cd90a2 100644 --- a/tests/extractor-owner-scope.mjs +++ b/tests/extractor-owner-scope.mjs @@ -1,5 +1,8 @@ import assert from "node:assert/strict"; -import { registerHooks } from "node:module"; +import { + installResolveHooks, + toDataModuleUrl, +} from "./helpers/register-hooks-compat.mjs"; const extensionsShimSource = [ "export const extension_settings = {};", @@ -34,39 +37,30 @@ const openAiShimSource = [ "}", ].join("\n"); -registerHooks({ - resolve(specifier, context, nextResolve) { - if ( - specifier === "../../../extensions.js" || - specifier === "../../../../extensions.js" || - specifier === "../../../../../extensions.js" - ) { - return { - shortCircuit: true, - url: `data:text/javascript,${encodeURIComponent(extensionsShimSource)}`, - }; - } - if ( - specifier === "../../../../script.js" || - specifier === "../../../../../script.js" - ) { - return { - shortCircuit: true, - url: `data:text/javascript,${encodeURIComponent(scriptShimSource)}`, - }; - } - if ( - specifier === "../../../../openai.js" || - specifier === "../../../../../openai.js" - ) { - return { - shortCircuit: true, - url: `data:text/javascript,${encodeURIComponent(openAiShimSource)}`, - }; - } - return nextResolve(specifier, context); +installResolveHooks([ + { + specifiers: [ + "../../../extensions.js", + "../../../../extensions.js", + "../../../../../extensions.js", + ], + url: toDataModuleUrl(extensionsShimSource), }, -}); + { + specifiers: [ + "../../../../script.js", + "../../../../../script.js", + ], + url: toDataModuleUrl(scriptShimSource), + }, + { + specifiers: [ + "../../../../openai.js", + "../../../../../openai.js", + ], + url: toDataModuleUrl(openAiShimSource), + }, +]); const { createEmptyGraph, createNode, addNode } = await import("../graph/graph.js"); const { DEFAULT_NODE_SCHEMA } = await import("../graph/schema.js"); diff --git a/tests/helpers/generation-recall-harness.mjs b/tests/helpers/generation-recall-harness.mjs index a4b37fa..1a8483e 100644 --- a/tests/helpers/generation-recall-harness.mjs +++ b/tests/helpers/generation-recall-harness.mjs @@ -9,6 +9,7 @@ import { onMessageReceivedController, onMessageSentController, } from "../../host/event-binding.js"; +import { isSystemMessageForExtraction } from "../../maintenance/chat-history.js"; import { resolveAutoExtractionPlanController } from "../../maintenance/extraction-controller.js"; import { GRAPH_LOAD_STATES, @@ -125,12 +126,22 @@ export function createGenerationRecallHarness(options = {}) { isTrivialUserInput, getAssistantTurns: (chat = []) => chat.flatMap((message, index) => - !message?.is_user && !message?.is_system ? [index] : [], + !message?.is_user && + !isSystemMessageForExtraction(message, { index, chat }) + ? [index] + : [], ), + isSystemMessageForExtraction, getLatestUserChatMessage: (chat = []) => [...chat].reverse().find((message) => message?.is_user) || null, getLastNonSystemChatMessage: (chat = []) => - [...chat].reverse().find((message) => !message?.is_system) || null, + [...chat] + .map((message, index) => ({ message, index })) + .reverse() + .find( + ({ message, index }) => + !isSystemMessageForExtraction(message, { index, chat }), + )?.message || null, getSmartTriggerDecision, getSendTextareaValue: () => context.__sendTextareaValue, getRecallUserMessageSourceLabel: (source = "") => source, diff --git a/tests/helpers/register-hooks-compat.mjs b/tests/helpers/register-hooks-compat.mjs new file mode 100644 index 0000000..da1b471 --- /dev/null +++ b/tests/helpers/register-hooks-compat.mjs @@ -0,0 +1,54 @@ +import { register, registerHooks } from "node:module"; + +export function toDataModuleUrl(source = "") { + return `data:text/javascript,${encodeURIComponent(String(source || ""))}`; +} + +export function installResolveHooks(entries = []) { + const normalizedEntries = (Array.isArray(entries) ? entries : []) + .map((entry) => ({ + specifiers: Array.isArray(entry?.specifiers) + ? entry.specifiers.map((value) => String(value || "")).filter(Boolean) + : [], + url: String(entry?.url || ""), + })) + .filter((entry) => entry.specifiers.length > 0 && entry.url); + + if (typeof registerHooks === "function") { + registerHooks({ + resolve(specifier, context, nextResolve) { + for (const entry of normalizedEntries) { + if (entry.specifiers.includes(specifier)) { + return { + shortCircuit: true, + url: entry.url, + }; + } + } + return nextResolve(specifier, context); + }, + }); + return; + } + + if (typeof register === "function") { + const loaderSource = ` +const entries = ${JSON.stringify(normalizedEntries)}; +export async function resolve(specifier, context, nextResolve) { + for (const entry of entries) { + if (Array.isArray(entry.specifiers) && entry.specifiers.includes(specifier)) { + return { + shortCircuit: true, + url: entry.url, + }; + } + } + return nextResolve(specifier, context); +} +`; + register(toDataModuleUrl(loaderSource), import.meta.url); + return; + } + + throw new Error("No compatible module hook API available"); +} diff --git a/tests/llm-model-fetch.mjs b/tests/llm-model-fetch.mjs index 5a2e365..fc39656 100644 --- a/tests/llm-model-fetch.mjs +++ b/tests/llm-model-fetch.mjs @@ -1,5 +1,9 @@ import assert from "node:assert/strict"; -import { createRequire, registerHooks } from "node:module"; +import { createRequire } from "node:module"; +import { + installResolveHooks, + toDataModuleUrl, +} from "./helpers/register-hooks-compat.mjs"; const extensionsShimSource = [ "export const extension_settings = globalThis.__llmModelFetchExtensionSettings || {};", @@ -22,39 +26,30 @@ const openAiShimSource = [ "}", ].join("\n"); -registerHooks({ - resolve(specifier, context, nextResolve) { - if ( - specifier === "../../../extensions.js" || - specifier === "../../../../extensions.js" || - specifier === "../../../../../extensions.js" - ) { - return { - shortCircuit: true, - url: `data:text/javascript,${encodeURIComponent(extensionsShimSource)}`, - }; - } - if ( - specifier === "../../../../script.js" || - specifier === "../../../../../script.js" - ) { - return { - shortCircuit: true, - url: `data:text/javascript,${encodeURIComponent(scriptShimSource)}`, - }; - } - if ( - specifier === "../../../openai.js" || - specifier === "../../../../openai.js" - ) { - return { - shortCircuit: true, - url: `data:text/javascript,${encodeURIComponent(openAiShimSource)}`, - }; - } - return nextResolve(specifier, context); +installResolveHooks([ + { + specifiers: [ + "../../../extensions.js", + "../../../../extensions.js", + "../../../../../extensions.js", + ], + url: toDataModuleUrl(extensionsShimSource), }, -}); + { + specifiers: [ + "../../../../script.js", + "../../../../../script.js", + ], + url: toDataModuleUrl(scriptShimSource), + }, + { + specifiers: [ + "../../../openai.js", + "../../../../openai.js", + ], + url: toDataModuleUrl(openAiShimSource), + }, +]); const require = createRequire(import.meta.url); const originalRequire = globalThis.require; diff --git a/tests/llm-streaming.mjs b/tests/llm-streaming.mjs index c8c44c9..f46add4 100644 --- a/tests/llm-streaming.mjs +++ b/tests/llm-streaming.mjs @@ -1,5 +1,9 @@ import assert from "node:assert/strict"; -import { createRequire, registerHooks } from "node:module"; +import { createRequire } from "node:module"; +import { + installResolveHooks, + toDataModuleUrl, +} from "./helpers/register-hooks-compat.mjs"; const extensionsShimSource = [ "export const extension_settings = globalThis.__llmStreamingExtensionSettings || {};", @@ -22,39 +26,30 @@ const openAiShimSource = [ "}", ].join("\n"); -registerHooks({ - resolve(specifier, context, nextResolve) { - if ( - specifier === "../../../extensions.js" || - specifier === "../../../../extensions.js" || - specifier === "../../../../../extensions.js" - ) { - return { - shortCircuit: true, - url: `data:text/javascript,${encodeURIComponent(extensionsShimSource)}`, - }; - } - if ( - specifier === "../../../../script.js" || - specifier === "../../../../../script.js" - ) { - return { - shortCircuit: true, - url: `data:text/javascript,${encodeURIComponent(scriptShimSource)}`, - }; - } - if ( - specifier === "../../../openai.js" || - specifier === "../../../../openai.js" - ) { - return { - shortCircuit: true, - url: `data:text/javascript,${encodeURIComponent(openAiShimSource)}`, - }; - } - return nextResolve(specifier, context); +installResolveHooks([ + { + specifiers: [ + "../../../extensions.js", + "../../../../extensions.js", + "../../../../../extensions.js", + ], + url: toDataModuleUrl(extensionsShimSource), }, -}); + { + specifiers: [ + "../../../../script.js", + "../../../../../script.js", + ], + url: toDataModuleUrl(scriptShimSource), + }, + { + specifiers: [ + "../../../openai.js", + "../../../../openai.js", + ], + url: toDataModuleUrl(openAiShimSource), + }, +]); const require = createRequire(import.meta.url); const originalRequire = globalThis.require; diff --git a/tests/p0-regressions.mjs b/tests/p0-regressions.mjs index 3257777..c82d678 100644 --- a/tests/p0-regressions.mjs +++ b/tests/p0-regressions.mjs @@ -1,9 +1,13 @@ import assert from "node:assert/strict"; import fs from "node:fs/promises"; -import { createRequire, registerHooks } from "node:module"; +import { createRequire } from "node:module"; import path from "node:path"; import { fileURLToPath } from "node:url"; import vm from "node:vm"; +import { + installResolveHooks, + toDataModuleUrl, +} from "./helpers/register-hooks-compat.mjs"; import { pruneProcessedMessageHashesFromFloor } from "../maintenance/chat-history.js"; import { onBeforeCombinePromptsController, @@ -106,39 +110,30 @@ const openAiShimUrl = `data:text/javascript,${encodeURIComponent( const moduleDir = path.dirname(fileURLToPath(import.meta.url)); const indexPath = path.resolve(moduleDir, "../index.js"); -registerHooks({ - resolve(specifier, context, nextResolve) { - if ( - specifier === "../../../extensions.js" || - specifier === "../../../../extensions.js" || - specifier === "../../../../../extensions.js" - ) { - return { - shortCircuit: true, - url: extensionsShimUrl, - }; - } - if ( - specifier === "../../../../script.js" || - specifier === "../../../../../script.js" - ) { - return { - shortCircuit: true, - url: scriptShimUrl, - }; - } - if ( - specifier === "../../../openai.js" || - specifier === "../../../../openai.js" - ) { - return { - shortCircuit: true, - url: openAiShimUrl, - }; - } - return nextResolve(specifier, context); +installResolveHooks([ + { + specifiers: [ + "../../../extensions.js", + "../../../../extensions.js", + "../../../../../extensions.js", + ], + url: extensionsShimUrl || toDataModuleUrl(extensionsShimSource), }, -}); + { + specifiers: [ + "../../../../script.js", + "../../../../../script.js", + ], + url: scriptShimUrl || toDataModuleUrl(scriptShimSource), + }, + { + specifiers: [ + "../../../openai.js", + "../../../../openai.js", + ], + url: openAiShimUrl || toDataModuleUrl(openAiShimSource), + }, +]); const require = createRequire(import.meta.url); const originalRequire = globalThis.require; @@ -3173,6 +3168,7 @@ async function testProcessedHistoryAdvanceTracksCoreExtractionSuccess() { ); setBatchStageOutcome(structuralPartial, "finalize", "success"); finalizeBatchStatus(structuralPartial); + delete structuralPartial.historyAdvanceAllowed; assert.equal(structuralPartial.completed, true); assert.equal(structuralPartial.outcome, "partial"); assert.equal(structuralPartial.consistency, "weak"); @@ -3186,6 +3182,7 @@ async function testProcessedHistoryAdvanceTracksCoreExtractionSuccess() { setBatchStageOutcome(semanticFailed, "semantic", "failed", "semantic down"); setBatchStageOutcome(semanticFailed, "finalize", "success"); finalizeBatchStatus(semanticFailed); + delete semanticFailed.historyAdvanceAllowed; assert.equal(semanticFailed.completed, true); assert.equal(semanticFailed.outcome, "failed"); assert.equal(semanticFailed.consistency, "strong"); @@ -3203,9 +3200,10 @@ async function testProcessedHistoryAdvanceTracksCoreExtractionSuccess() { "vector finalize down", ); finalizeBatchStatus(finalizeFailed); + delete finalizeFailed.historyAdvanceAllowed; assert.equal(finalizeFailed.completed, false); assert.equal(finalizeFailed.outcome, "failed"); - assert.equal(shouldAdvanceProcessedHistory(finalizeFailed), true); + assert.equal(shouldAdvanceProcessedHistory(finalizeFailed), false); const fullSuccess = createBatchStatusSkeleton({ processedRange: [8, 9], @@ -3216,6 +3214,7 @@ async function testProcessedHistoryAdvanceTracksCoreExtractionSuccess() { setBatchStageOutcome(fullSuccess, "semantic", "success"); setBatchStageOutcome(fullSuccess, "finalize", "success"); finalizeBatchStatus(fullSuccess); + delete fullSuccess.historyAdvanceAllowed; assert.equal(fullSuccess.completed, true); assert.equal(fullSuccess.outcome, "success"); assert.equal(fullSuccess.consistency, "strong"); diff --git a/tests/prompt-builder-defaults.mjs b/tests/prompt-builder-defaults.mjs index 85acbe4..c8ad53d 100644 --- a/tests/prompt-builder-defaults.mjs +++ b/tests/prompt-builder-defaults.mjs @@ -1,5 +1,8 @@ import assert from "node:assert/strict"; -import { registerHooks } from "node:module"; +import { + installResolveHooks, + toDataModuleUrl, +} from "./helpers/register-hooks-compat.mjs"; const extensionsShimSource = [ "export const extension_settings = {};", @@ -24,30 +27,23 @@ const scriptShimSource = [ "}", ].join("\n"); -registerHooks({ - resolve(specifier, context, nextResolve) { - if ( - specifier === "../../../extensions.js" || - specifier === "../../../../extensions.js" || - specifier === "../../../../../extensions.js" - ) { - return { - shortCircuit: true, - url: `data:text/javascript,${encodeURIComponent(extensionsShimSource)}`, - }; - } - if ( - specifier === "../../../../script.js" || - specifier === "../../../../../script.js" - ) { - return { - shortCircuit: true, - url: `data:text/javascript,${encodeURIComponent(scriptShimSource)}`, - }; - } - return nextResolve(specifier, context); +installResolveHooks([ + { + specifiers: [ + "../../../extensions.js", + "../../../../extensions.js", + "../../../../../extensions.js", + ], + url: toDataModuleUrl(extensionsShimSource), }, -}); + { + specifiers: [ + "../../../../script.js", + "../../../../../script.js", + ], + url: toDataModuleUrl(scriptShimSource), + }, +]); const { buildTaskLlmPayload, buildTaskPrompt } = await import("../prompting/prompt-builder.js"); const { createDefaultTaskProfiles } = await import("../prompting/prompt-profiles.js"); diff --git a/tests/prompt-builder-mvu.mjs b/tests/prompt-builder-mvu.mjs index 4874b26..4bfc577 100644 --- a/tests/prompt-builder-mvu.mjs +++ b/tests/prompt-builder-mvu.mjs @@ -1,5 +1,9 @@ import assert from "node:assert/strict"; -import { createRequire, registerHooks } from "node:module"; +import { createRequire } from "node:module"; +import { + installResolveHooks, + toDataModuleUrl, +} from "./helpers/register-hooks-compat.mjs"; const extensionsShimSource = [ "export const extension_settings = globalThis.__promptBuilderMvuExtensionSettings || {};", @@ -35,39 +39,30 @@ const openAiShimSource = [ "}", ].join("\n"); -registerHooks({ - resolve(specifier, context, nextResolve) { - if ( - specifier === "../../../extensions.js" || - specifier === "../../../../extensions.js" || - specifier === "../../../../../extensions.js" - ) { - return { - shortCircuit: true, - url: `data:text/javascript,${encodeURIComponent(extensionsShimSource)}`, - }; - } - if ( - specifier === "../../../../script.js" || - specifier === "../../../../../script.js" - ) { - return { - shortCircuit: true, - url: `data:text/javascript,${encodeURIComponent(scriptShimSource)}`, - }; - } - if ( - specifier === "../../../openai.js" || - specifier === "../../../../openai.js" - ) { - return { - shortCircuit: true, - url: `data:text/javascript,${encodeURIComponent(openAiShimSource)}`, - }; - } - return nextResolve(specifier, context); +installResolveHooks([ + { + specifiers: [ + "../../../extensions.js", + "../../../../extensions.js", + "../../../../../extensions.js", + ], + url: toDataModuleUrl(extensionsShimSource), }, -}); + { + specifiers: [ + "../../../../script.js", + "../../../../../script.js", + ], + url: toDataModuleUrl(scriptShimSource), + }, + { + specifiers: [ + "../../../openai.js", + "../../../../openai.js", + ], + url: toDataModuleUrl(openAiShimSource), + }, +]); const require = createRequire(import.meta.url); const originalRequire = globalThis.require; diff --git a/tests/st-context-task-ejs.mjs b/tests/st-context-task-ejs.mjs index 87c094a..7624c14 100644 --- a/tests/st-context-task-ejs.mjs +++ b/tests/st-context-task-ejs.mjs @@ -1,5 +1,8 @@ import assert from "node:assert/strict"; -import { registerHooks } from "node:module"; +import { + installResolveHooks, + toDataModuleUrl, +} from "./helpers/register-hooks-compat.mjs"; const extensionsShimSource = [ "export function getContext(...args) {", @@ -10,20 +13,15 @@ const extensionsShimUrl = `data:text/javascript,${encodeURIComponent( extensionsShimSource, )}`; -registerHooks({ - resolve(specifier, context, nextResolve) { - if ( - specifier === "../../../extensions.js" || - specifier === "../../../../extensions.js" - ) { - return { - shortCircuit: true, - url: extensionsShimUrl, - }; - } - return nextResolve(specifier, context); +installResolveHooks([ + { + specifiers: [ + "../../../extensions.js", + "../../../../extensions.js", + ], + url: extensionsShimUrl || toDataModuleUrl(extensionsShimSource), }, -}); +]); const originalSillyTavern = globalThis.SillyTavern; const originalGetCurrentChatId = globalThis.getCurrentChatId; diff --git a/tests/summary-rollup-threshold.mjs b/tests/summary-rollup-threshold.mjs index 88ae2ec..b04fae8 100644 --- a/tests/summary-rollup-threshold.mjs +++ b/tests/summary-rollup-threshold.mjs @@ -1,5 +1,8 @@ import assert from "node:assert/strict"; -import { registerHooks } from "node:module"; +import { + installResolveHooks, + toDataModuleUrl, +} from "./helpers/register-hooks-compat.mjs"; const extensionsShimSource = [ "export const extension_settings = {};", @@ -34,39 +37,30 @@ const openAiShimSource = [ "}", ].join("\n"); -registerHooks({ - resolve(specifier, context, nextResolve) { - if ( - specifier === "../../../extensions.js" || - specifier === "../../../../extensions.js" || - specifier === "../../../../../extensions.js" - ) { - return { - shortCircuit: true, - url: `data:text/javascript,${encodeURIComponent(extensionsShimSource)}`, - }; - } - if ( - specifier === "../../../../script.js" || - specifier === "../../../../../script.js" - ) { - return { - shortCircuit: true, - url: `data:text/javascript,${encodeURIComponent(scriptShimSource)}`, - }; - } - if ( - specifier === "../../../openai.js" || - specifier === "../../../../openai.js" - ) { - return { - shortCircuit: true, - url: `data:text/javascript,${encodeURIComponent(openAiShimSource)}`, - }; - } - return nextResolve(specifier, context); +installResolveHooks([ + { + specifiers: [ + "../../../extensions.js", + "../../../../extensions.js", + "../../../../../extensions.js", + ], + url: toDataModuleUrl(extensionsShimSource), }, -}); + { + specifiers: [ + "../../../../script.js", + "../../../../../script.js", + ], + url: toDataModuleUrl(scriptShimSource), + }, + { + specifiers: [ + "../../../openai.js", + "../../../../openai.js", + ], + url: toDataModuleUrl(openAiShimSource), + }, +]); const { createEmptyGraph } = await import("../graph/graph.js"); const { appendSummaryEntry } = await import("../graph/summary-state.js"); diff --git a/tests/task-regex.mjs b/tests/task-regex.mjs index d66a5fa..52faca1 100644 --- a/tests/task-regex.mjs +++ b/tests/task-regex.mjs @@ -1,5 +1,7 @@ import assert from "node:assert/strict"; -import { registerHooks } from "node:module"; +import { + installResolveHooks, +} from "./helpers/register-hooks-compat.mjs"; const extensionsShimSource = [ "export const extension_settings = globalThis.__taskRegexTestExtensionSettings || {};", @@ -11,21 +13,16 @@ const extensionsShimUrl = `data:text/javascript,${encodeURIComponent( extensionsShimSource, )}`; -registerHooks({ - resolve(specifier, context, nextResolve) { - if ( - specifier === "../../../extensions.js" || - specifier === "../../../../extensions.js" || - specifier === "../../../../../extensions.js" - ) { - return { - shortCircuit: true, - url: extensionsShimUrl, - }; - } - return nextResolve(specifier, context); +installResolveHooks([ + { + specifiers: [ + "../../../extensions.js", + "../../../../extensions.js", + "../../../../../extensions.js", + ], + url: extensionsShimUrl, }, -}); +]); const originalSillyTavern = globalThis.SillyTavern; const originalGetTavernRegexes = globalThis.getTavernRegexes; diff --git a/tests/task-worldinfo.mjs b/tests/task-worldinfo.mjs index 5847372..5174fc2 100644 --- a/tests/task-worldinfo.mjs +++ b/tests/task-worldinfo.mjs @@ -1,5 +1,7 @@ import assert from "node:assert/strict"; -import { registerHooks } from "node:module"; +import { + installResolveHooks, +} from "./helpers/register-hooks-compat.mjs"; const extensionsShimSource = [ "export const extension_settings = {};", @@ -19,30 +21,23 @@ const scriptShimUrl = `data:text/javascript,${encodeURIComponent( scriptShimSource, )}`; -registerHooks({ - resolve(specifier, context, nextResolve) { - if ( - specifier === "../../../extensions.js" || - specifier === "../../../../extensions.js" || - specifier === "../../../../../extensions.js" - ) { - return { - shortCircuit: true, - url: extensionsShimUrl, - }; - } - if ( - specifier === "../../../../script.js" || - specifier === "../../../../../script.js" - ) { - return { - shortCircuit: true, - url: scriptShimUrl, - }; - } - return nextResolve(specifier, context); +installResolveHooks([ + { + specifiers: [ + "../../../extensions.js", + "../../../../extensions.js", + "../../../../../extensions.js", + ], + url: extensionsShimUrl, }, -}); + { + specifiers: [ + "../../../../script.js", + "../../../../../script.js", + ], + url: scriptShimUrl, + }, +]); const originalSillyTavern = globalThis.SillyTavern; const originalEjsTemplate = globalThis.EjsTemplate;