mirror of
https://github.com/mudler/LocalAI.git
synced 2026-11-02 18:44:48 -05:00
A page written for the web UI imports React, the router, i18next and a few shared components. The add-on builder refuses a bundle that holds a host file, so moving such a page into an add-on meant rewriting it. Add a compat mode to the shared builder. It answers those imports from a directory of stand-ins that read the SDK, bundles the dynamic import of the page code into the one output file, and collects the style sheets the page imports. A relative import that is not in the add-on's own source resolves to the file at the same path under the compat directory. Widen the SDK for these pages, without a version change: more host components (spinner, modal, lightbox, model picker) and hooks (models, resources, voice profiles, operations, MCP client), a style on icons, the icon names the pages draw, sdk.navigation.openApp to open a page of the app (only addresses under /app, and the way back as the only state) and sdk.portal. The shell passes the query string to the page. The stand-ins cover the router (the tab in the path, the model in the query), the translator over the host locale files, the core API calls through sdk.core.fetch, and byte copies of the pure helpers, with tests that keep the copies equal to the originals. Assisted-by: Claude Code:claude-sonnet-5-5 node Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
29 lines
1.4 KiB
JavaScript
29 lines
1.4 KiB
JavaScript
// A node resolve hook for tests that import add-on source files directly. The
|
|
// bundler answers a relative import whose target is not in the add-on's src/
|
|
// from the compat directory (see addons/internal/uibuild/uibuild.mjs); this
|
|
// hook does the same for node, so a source file runs without a build.
|
|
import { existsSync, statSync } from 'node:fs'
|
|
import { dirname, join, relative, resolve, sep } from 'node:path'
|
|
import { fileURLToPath, pathToFileURL } from 'node:url'
|
|
|
|
const compatSrc = resolve(dirname(fileURLToPath(import.meta.url)), '../src')
|
|
const tails = ['', '.js', '.jsx', '.mjs']
|
|
const find = (base) => tails.map((t) => base + t).find((f) => existsSync(f) && statSync(f).isFile())
|
|
|
|
export async function resolve_(specifier, context, nextResolve) {
|
|
if (specifier.startsWith('.') && context.parentURL?.startsWith('file:')) {
|
|
const parent = fileURLToPath(context.parentURL)
|
|
const m = /^(.*[\\/]addons[\\/][^\\/]+[\\/]ui[\\/]src)[\\/]/.exec(parent)
|
|
if (m) {
|
|
const target = resolve(dirname(parent), specifier)
|
|
const found = find(target)
|
|
if (found) return nextResolve(pathToFileURL(found).href, context)
|
|
const rel = relative(m[1], target)
|
|
const hit = !rel.startsWith('..') && find(join(compatSrc, rel))
|
|
if (hit) return nextResolve(pathToFileURL(hit).href, context)
|
|
}
|
|
}
|
|
return nextResolve(specifier, context)
|
|
}
|
|
export { resolve_ as resolve }
|