| 3 | import { pathToFileURL } from 'node:url'; |
| 4 | |
| 5 | export async function runPluginNodeEntry(entry: string, args: readonly string[]): Promise<void> { |
| 6 | const pluginRoot = process.env['KIMI_PLUGIN_ROOT']; |
| 7 | if (pluginRoot === undefined || pluginRoot.trim().length === 0) { |
| 8 | throw new Error('KIMI_PLUGIN_ROOT is required to run a plugin node entry.'); |
| 9 | } |
| 10 | |
| 11 | const [rootReal, entryReal] = await Promise.all([ |
| 12 | realpath(pluginRoot), |
| 13 | realpath(entry), |
| 14 | ]); |
| 15 | if (!isWithin(entryReal, rootReal)) { |
| 16 | throw new Error(`Plugin node entry must be inside KIMI_PLUGIN_ROOT: ${entry}`); |
| 17 | } |
| 18 | |
| 19 | process.argv = [process.argv[0] ?? process.execPath, entryReal, ...args]; |
| 20 | await import(pathToFileURL(entryReal).href); |
| 21 | } |
| 22 | |
| 23 | function isWithin(candidate: string, root: string): boolean { |
| 24 | const relative = path.relative(root, candidate); |