fix(plugins): alias runtime dependency export subpaths

This commit is contained in:
Peter Steinberger
2026-04-25 15:01:08 +01:00
parent 9e9aa4722a
commit 14c9cfb637
3 changed files with 55 additions and 17 deletions

View File

@@ -112,6 +112,7 @@ Docs: https://docs.openclaw.ai
- Feishu: keep streaming cards to one live card per turn, flush throttled card edits after meaningful text boundaries, and skip exact block/partial repeats so tool-heavy replies do not duplicate card output. Thanks @allan0509.
- Feishu: finish the streaming-card duplicate closeout by stripping leaked reasoning tags, preserving cross-block partial snapshots, enabling topic-thread streaming cards, omitting the generic `main` card header, surfacing transient tool/compaction status, and cleaning streaming state after close failures. Thanks @sesame437, @Vicky-v7, @maoku-family, @Pengxiao-Wang, and @Maple778.
- Telegram: recover incomplete partial-stream previews by falling back to a final send when an ambiguous final edit failure would otherwise retain a strict prefix of the answer. Fixes #71525. (#71554) Thanks @sahilsatralkar.
- Packaged installs: preserve package-root runtime dependencies and their exported subpaths when bundled plugin runtime mirrors fall back to copying shared chunks, fixing Windows npm updates that could fail to load copied `dist` modules.
- Heartbeat: clamp oversized scheduler delays through the shared safe timer helper, preventing `every` values over Node's timeout cap from becoming a 1 ms crash loop. Fixes #71414. (#71478) Thanks @hclsys.
- Control UI/chat: collapse assistant token/model context details behind an explicit Context disclosure and show full dates in message footers, making historical transcript timing clear without noisy default metadata. (#71337) Thanks @BunsDev.
- OpenAI/Codex OAuth: explain `unsupported_country_region_territory` token-exchange failures with a proxy/region hint instead of surfacing a generic OAuth error. Fixes #51175. (#71501) Thanks @vincentkoc and @wulala-xjj.

View File

@@ -1586,6 +1586,9 @@ module.exports = {
".": {
import: "./index.js",
},
"./oauth": {
import: "./oauth.js",
},
},
}),
"utf-8",
@@ -1595,11 +1598,19 @@ module.exports = {
"export default { marker: 'root-ok' };\n",
"utf-8",
);
fs.writeFileSync(
path.join(packageDepRoot, "oauth.js"),
"export const oauthMarker = 'oauth-ok';\n",
"utf-8",
);
fs.writeFileSync(
path.join(packageRoot, "dist", "manifest-support.js"),
[`import support from "root-support";`, `export const marker = support.marker;`, ""].join(
"\n",
),
[
`import support from "root-support";`,
`import { oauthMarker } from "root-support/oauth";`,
`export const marker = [support.marker, oauthMarker].join(":");`,
"",
].join("\n"),
"utf-8",
);
fs.writeFileSync(

View File

@@ -516,6 +516,35 @@ function resolveRuntimePackageImportTarget(exportsField: unknown): string | null
return null;
}
function collectRuntimePackageImportTargets(
pkg: RuntimeDependencyPackageJson,
): Map<string, string> {
const targets = new Map<string, string>();
const exportsField = pkg.exports;
if (
exportsField &&
typeof exportsField === "object" &&
!Array.isArray(exportsField) &&
Object.keys(exportsField).some((key) => key.startsWith("."))
) {
for (const [exportKey, exportValue] of Object.entries(exportsField)) {
if (!exportKey.startsWith(".") || exportKey.includes("*")) {
continue;
}
const resolved = resolveRuntimePackageImportTarget(exportValue);
if (resolved) {
targets.set(exportKey, resolved);
}
}
return targets;
}
const rootEntry = resolveRuntimePackageImportTarget(exportsField) ?? pkg.module ?? pkg.main;
if (rootEntry) {
targets.set(".", rootEntry);
}
return targets;
}
function registerBundledRuntimeDependencyJitiAliases(rootDir: string): void {
const rootPackageJson = readRuntimeDependencyPackageJson(path.join(rootDir, "package.json"));
if (!rootPackageJson) {
@@ -532,22 +561,19 @@ function registerBundledRuntimeDependencyJitiAliases(rootDir: string): void {
if (!dependencyPackageJson) {
continue;
}
const entry =
resolveRuntimePackageImportTarget(dependencyPackageJson.exports) ??
dependencyPackageJson.module ??
dependencyPackageJson.main;
if (!entry || entry.startsWith("#")) {
continue;
}
const dependencyRoot = path.dirname(dependencyPackageJsonPath);
const targetPath = path.resolve(dependencyRoot, entry);
if (!isPathInside(dependencyRoot, targetPath) || !fs.existsSync(targetPath)) {
continue;
for (const [exportKey, entry] of collectRuntimePackageImportTargets(dependencyPackageJson)) {
if (!entry || entry.startsWith("#")) {
continue;
}
const targetPath = path.resolve(dependencyRoot, entry);
if (!isPathInside(dependencyRoot, targetPath) || !fs.existsSync(targetPath)) {
continue;
}
const aliasKey =
exportKey === "." ? dependencyName : `${dependencyName}${exportKey.slice(1)}`;
bundledRuntimeDependencyJitiAliases.set(aliasKey, normalizeJitiAliasTargetPath(targetPath));
}
bundledRuntimeDependencyJitiAliases.set(
dependencyName,
normalizeJitiAliasTargetPath(targetPath),
);
}
}