Download src/agents/sessions/extensions/loader.native-js.test.ts from SaylorTwift/openclaw: direct link, hf CLI and curl.
- Browser
- Download file 10.5 kB
-
https://huggingface.co/SaylorTwift/openclaw/resolve/main/src/agents/sessions/extensions/loader.native-js.test.ts
- Command line
-
hf download hf://SaylorTwift/openclaw/src/agents/sessions/extensions/loader.native-js.test.ts
-
curl -L -o loader.native-js.test.ts https://huggingface.co/SaylorTwift/openclaw/resolve/main/src/agents/sessions/extensions/loader.native-js.test.ts
10.5 kB
| // Native JavaScript extension loader tests cover when compiled JS can bypass | |
| // jiti and when alias-sensitive graphs must keep jiti resolution. | |
| import { mkdtemp, rm, stat, utimes, writeFile } from "node:fs/promises"; | |
| import { tmpdir } from "node:os"; | |
| import { join } from "node:path"; | |
| import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; | |
| const jitiCalls = vi.hoisted(() => ({ | |
| imports: [] as string[], | |
| options: [] as Array<Record<string, unknown>>, | |
| })); | |
| vi.mock("jiti/static", () => ({ | |
| createJiti: vi.fn((_url: string, options: Record<string, unknown>) => { | |
| jitiCalls.options.push(options); | |
| return { | |
| import: vi.fn(async (target: string) => { | |
| jitiCalls.imports.push(target); | |
| return async (api: { registerCommand: (id: string, command: unknown) => void }) => { | |
| api.registerCommand(`jiti-${jitiCalls.imports.length}`, { | |
| description: "probe", | |
| handler() {}, | |
| }); | |
| }; | |
| }), | |
| }; | |
| }), | |
| })); | |
| const tempDirs: string[] = []; | |
| let clearExtensionCache: typeof import("./loader.js").clearExtensionCache; | |
| let loadExtensionsCached: typeof import("./loader.js").loadExtensionsCached; | |
| beforeAll(async () => { | |
| vi.resetModules(); | |
| ({ clearExtensionCache, loadExtensionsCached } = await import("./loader.js")); | |
| }); | |
| beforeEach(() => { | |
| jitiCalls.imports.length = 0; | |
| jitiCalls.options.length = 0; | |
| }); | |
| afterEach(async () => { | |
| clearExtensionCache(); | |
| await Promise.all(tempDirs.splice(0).map((dir) => rm(dir, { force: true, recursive: true }))); | |
| }); | |
| describe("loadExtensionsCached native JavaScript path", () => { | |
| it("loads compiled JavaScript extensions without creating a jiti loader", async () => { | |
| const dir = await mkdtemp(join(tmpdir(), "openclaw-extension-js-")); | |
| tempDirs.push(dir); | |
| const extensionPath = join(dir, "extension.mjs"); | |
| await writeFile( | |
| extensionPath, | |
| ` | |
| export default async function extension(api) { | |
| api.registerCommand("native-js-probe", { | |
| description: "probe", | |
| handler() {}, | |
| }); | |
| } | |
| `, | |
| ); | |
| const result = await loadExtensionsCached([extensionPath], dir); | |
| expect(result.errors).toEqual([]); | |
| expect(result.extensions).toHaveLength(1); | |
| expect(result.extensions[0]?.commands.has("native-js-probe")).toBe(true); | |
| expect(jitiCalls.options).toEqual([]); | |
| expect(jitiCalls.imports).toEqual([]); | |
| }); | |
| it("reloads native JavaScript extensions when the file changes without stat-key drift", async () => { | |
| // Explicit reload clears the factory cache. Native imports still need a | |
| // fresh URL so same-size, same-mtime edits are observed. | |
| const dir = await mkdtemp(join(tmpdir(), "openclaw-extension-js-")); | |
| tempDirs.push(dir); | |
| const extensionPath = join(dir, "extension.cjs"); | |
| const beforeSource = ` | |
| module.exports = async function(api) { | |
| api.registerCommand("native-reload-one", { | |
| description: "probe", | |
| handler() {}, | |
| }); | |
| }; | |
| `; | |
| const afterSource = ` | |
| module.exports = async function(api) { | |
| api.registerCommand("native-reload-two", { | |
| description: "probe", | |
| handler() {}, | |
| }); | |
| }; | |
| `; | |
| expect(afterSource).toHaveLength(beforeSource.length); | |
| await writeFile(extensionPath, beforeSource); | |
| const before = await loadExtensionsCached([extensionPath], dir); | |
| const beforeStat = await stat(extensionPath); | |
| await writeFile(extensionPath, afterSource); | |
| await utimes(extensionPath, beforeStat.atime, beforeStat.mtime); | |
| clearExtensionCache(); | |
| const after = await loadExtensionsCached([extensionPath], dir); | |
| expect(before.errors).toEqual([]); | |
| expect(before.extensions[0]?.commands.has("native-reload-one")).toBe(true); | |
| expect(after.errors).toEqual([]); | |
| expect(after.extensions[0]?.commands.has("native-reload-two")).toBe(true); | |
| expect(jitiCalls.options).toEqual([]); | |
| }); | |
| it("loads transpiled CommonJS default exports through the native path", async () => { | |
| const dir = await mkdtemp(join(tmpdir(), "openclaw-extension-js-")); | |
| tempDirs.push(dir); | |
| const extensionPath = join(dir, "extension.cjs"); | |
| await writeFile( | |
| extensionPath, | |
| ` | |
| exports.default = async function(api) { | |
| api.registerCommand("native-cjs-default-probe", { | |
| description: "probe", | |
| handler() {}, | |
| }); | |
| }; | |
| `, | |
| ); | |
| const result = await loadExtensionsCached([extensionPath], dir); | |
| expect(result.errors).toEqual([]); | |
| expect(result.extensions).toHaveLength(1); | |
| expect(result.extensions[0]?.commands.has("native-cjs-default-probe")).toBe(true); | |
| expect(jitiCalls.options).toEqual([]); | |
| }); | |
| it("keeps CommonJS-shaped .js extensions on jiti", async () => { | |
| const dir = await mkdtemp(join(tmpdir(), "openclaw-extension-js-")); | |
| tempDirs.push(dir); | |
| await writeFile(join(dir, "package.json"), '{"type":"module"}\n'); | |
| const extensionPath = join(dir, "extension.js"); | |
| await writeFile( | |
| extensionPath, | |
| ` | |
| module.exports = async function(api) { | |
| api.registerCommand("should-not-native-load", { | |
| description: "probe", | |
| handler() {}, | |
| }); | |
| }; | |
| `, | |
| ); | |
| const result = await loadExtensionsCached([extensionPath], dir); | |
| expect(result.errors).toEqual([]); | |
| expect(result.extensions).toHaveLength(1); | |
| expect(jitiCalls.options).toHaveLength(1); | |
| expect(jitiCalls.imports).toEqual([extensionPath]); | |
| }); | |
| it("keeps plain ESM .js extensions on jiti", async () => { | |
| const dir = await mkdtemp(join(tmpdir(), "openclaw-extension-js-")); | |
| tempDirs.push(dir); | |
| const extensionPath = join(dir, "extension.js"); | |
| await writeFile( | |
| extensionPath, | |
| ` | |
| export default async function extension(api) { | |
| api.registerCommand("should-not-native-load", { | |
| description: "probe", | |
| handler() {}, | |
| }); | |
| } | |
| `, | |
| ); | |
| const result = await loadExtensionsCached([extensionPath], dir); | |
| expect(result.errors).toEqual([]); | |
| expect(result.extensions).toHaveLength(1); | |
| expect(jitiCalls.options).toHaveLength(1); | |
| expect(jitiCalls.imports).toEqual([extensionPath]); | |
| }); | |
| it("keeps SDK-alias JavaScript extensions on one shared jiti loader", async () => { | |
| // SDK aliases need jiti's virtual resolution, but one shared loader keeps | |
| // multi-extension imports consistent and cheap. | |
| const dir = await mkdtemp(join(tmpdir(), "openclaw-extension-js-")); | |
| tempDirs.push(dir); | |
| const firstPath = join(dir, "first.js"); | |
| const secondPath = join(dir, "second.js"); | |
| const source = ` | |
| require("@openclaw/plugin-sdk/agent-sessions"); | |
| module.exports = async function(api) { | |
| api.registerCommand("should-not-native-load", { | |
| description: "probe", | |
| handler() {}, | |
| }); | |
| }; | |
| `; | |
| await writeFile(firstPath, source); | |
| await writeFile(secondPath, source); | |
| const result = await loadExtensionsCached([firstPath, secondPath], dir); | |
| expect(result.errors).toEqual([]); | |
| expect(result.extensions).toHaveLength(2); | |
| expect(jitiCalls.options).toHaveLength(1); | |
| expect(jitiCalls.imports).toEqual([firstPath, secondPath]); | |
| }); | |
| it("keeps TypeBox-alias JavaScript extensions on jiti", async () => { | |
| const dir = await mkdtemp(join(tmpdir(), "openclaw-extension-js-")); | |
| tempDirs.push(dir); | |
| const extensionPath = join(dir, "extension.js"); | |
| await writeFile( | |
| extensionPath, | |
| ` | |
| require("typebox"); | |
| module.exports = async function(api) { | |
| api.registerCommand("should-not-native-load", { | |
| description: "probe", | |
| handler() {}, | |
| }); | |
| }; | |
| `, | |
| ); | |
| const result = await loadExtensionsCached([extensionPath], dir); | |
| expect(result.errors).toEqual([]); | |
| expect(result.extensions).toHaveLength(1); | |
| expect(jitiCalls.options).toHaveLength(1); | |
| expect(jitiCalls.imports).toEqual([extensionPath]); | |
| }); | |
| it("keeps multi-file JavaScript extensions on jiti for graph-wide aliases", async () => { | |
| // Alias detection walks relative helper files; a clean entrypoint can still | |
| // need jiti when its dependency graph imports SDK/TypeBox aliases. | |
| const dir = await mkdtemp(join(tmpdir(), "openclaw-extension-js-")); | |
| tempDirs.push(dir); | |
| const extensionPath = join(dir, "extension.js"); | |
| await writeFile( | |
| extensionPath, | |
| ` | |
| require("./helper.js"); | |
| module.exports = async function(api) { | |
| api.registerCommand("should-not-native-load", { | |
| description: "probe", | |
| handler() {}, | |
| }); | |
| }; | |
| `, | |
| ); | |
| await writeFile(join(dir, "helper.js"), 'require("typebox");\n'); | |
| const result = await loadExtensionsCached([extensionPath], dir); | |
| expect(result.errors).toEqual([]); | |
| expect(result.extensions).toHaveLength(1); | |
| expect(jitiCalls.options).toHaveLength(1); | |
| expect(jitiCalls.imports).toEqual([extensionPath]); | |
| }); | |
| it("keeps ESM re-export JavaScript extensions on jiti for graph-wide aliases", async () => { | |
| const dir = await mkdtemp(join(tmpdir(), "openclaw-extension-js-")); | |
| tempDirs.push(dir); | |
| await writeFile(join(dir, "package.json"), '{"type":"module"}\n'); | |
| const extensionPath = join(dir, "extension.js"); | |
| await writeFile( | |
| extensionPath, | |
| ` | |
| export { helper } from "./helper.js"; | |
| export default async function extension(api) { | |
| api.registerCommand("should-not-native-load", { | |
| description: "probe", | |
| handler() {}, | |
| }); | |
| } | |
| `, | |
| ); | |
| await writeFile(join(dir, "helper.js"), 'import "typebox"; export const helper = true;\n'); | |
| const result = await loadExtensionsCached([extensionPath], dir); | |
| expect(result.errors).toEqual([]); | |
| expect(result.extensions).toHaveLength(1); | |
| expect(jitiCalls.options).toHaveLength(1); | |
| expect(jitiCalls.imports).toEqual([extensionPath]); | |
| }); | |
| it("keeps minified ESM relative imports on jiti for graph-wide aliases", async () => { | |
| const dir = await mkdtemp(join(tmpdir(), "openclaw-extension-js-")); | |
| tempDirs.push(dir); | |
| const extensionPath = join(dir, "extension.mjs"); | |
| await writeFile( | |
| extensionPath, | |
| `import{helper}from"./helper.mjs";export{helper}from"./helper.mjs";export default async function extension(api){api.registerCommand("should-not-native-load",{description:"probe",handler(){}});}`, | |
| ); | |
| await writeFile(join(dir, "helper.mjs"), 'import "typebox"; export const helper = true;\n'); | |
| const result = await loadExtensionsCached([extensionPath], dir); | |
| expect(result.errors).toEqual([]); | |
| expect(result.extensions).toHaveLength(1); | |
| expect(jitiCalls.options).toHaveLength(1); | |
| expect(jitiCalls.imports).toEqual([extensionPath]); | |
| }); | |
| }); | |