mirror of
https://github.com/moltbot/moltbot.git
synced 2026-04-28 08:52:45 +00:00
fix: preserve linked install unsafe flag and baseline regressions
This commit is contained in:
@@ -120,6 +120,7 @@ Docs: https://docs.openclaw.ai
|
|||||||
- Providers/OpenAI Codex: add forward-compat `openai-codex/gpt-5.4-mini` synthesis across provider runtime, model catalog, and model listing so Codex mini works before bundled Pi catalog updates land.
|
- Providers/OpenAI Codex: add forward-compat `openai-codex/gpt-5.4-mini` synthesis across provider runtime, model catalog, and model listing so Codex mini works before bundled Pi catalog updates land.
|
||||||
- Plugins/marketplace: block remote marketplace symlink escapes without rewriting ordinary local marketplace install paths. (#60556) Thanks @eleqtrizit.
|
- Plugins/marketplace: block remote marketplace symlink escapes without rewriting ordinary local marketplace install paths. (#60556) Thanks @eleqtrizit.
|
||||||
- Plugins/Kimi Coding: keep native Anthropic tool payloads on the Kimi coding endpoint while still parsing tagged tool-call text on the response path, so tool calls execute again instead of echoing raw markup. (#60391) Thanks @Eric-Guo.
|
- Plugins/Kimi Coding: keep native Anthropic tool payloads on the Kimi coding endpoint while still parsing tagged tool-call text on the response path, so tool calls execute again instead of echoing raw markup. (#60391) Thanks @Eric-Guo.
|
||||||
|
- Plugins/install: preserve `--dangerously-force-unsafe-install` across linked plugin probes and linked hook-pack fallback probes so local `--link` installs honor the documented unsafe override. (#60624) Thanks @JerrettDavis.
|
||||||
|
|
||||||
## 2026.4.2
|
## 2026.4.2
|
||||||
|
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ export function normalizeCompatibilityConfig({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!changed) {
|
if (!changed && changes.length === 0) {
|
||||||
return { config: cfg, changes: [] };
|
return { config: cfg, changes: [] };
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -12,12 +12,31 @@ export const unsupportedSecretRefSurfacePatterns = [
|
|||||||
"channels.whatsapp.accounts.*.creds.json",
|
"channels.whatsapp.accounts.*.creds.json",
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
export { canonicalizeLegacySessionKey, isLegacyGroupSessionKey } from "./src/session-contract.js";
|
import { whatsappCommandPolicy as whatsappCommandPolicyImpl } from "./src/command-policy.js";
|
||||||
export { createWhatsAppPollFixture, expectWhatsAppPollSent } from "./src/outbound-test-support.js";
|
import { resolveLegacyGroupSessionKey as resolveLegacyGroupSessionKeyImpl } from "./src/group-session-contract.js";
|
||||||
export { whatsappCommandPolicy } from "./src/command-policy.js";
|
import { __testing as whatsappAccessControlTestingImpl } from "./src/inbound/access-control.js";
|
||||||
export { resolveLegacyGroupSessionKey } from "./src/group-session-contract.js";
|
import {
|
||||||
export { isWhatsAppGroupJid, normalizeWhatsAppTarget } from "./src/normalize-target.js";
|
isWhatsAppGroupJid as isWhatsAppGroupJidImpl,
|
||||||
export { __testing as whatsappAccessControlTesting } from "./src/inbound/access-control.js";
|
normalizeWhatsAppTarget as normalizeWhatsAppTargetImpl,
|
||||||
|
} from "./src/normalize-target.js";
|
||||||
|
import {
|
||||||
|
createWhatsAppPollFixture as createWhatsAppPollFixtureImpl,
|
||||||
|
expectWhatsAppPollSent as expectWhatsAppPollSentImpl,
|
||||||
|
} from "./src/outbound-test-support.js";
|
||||||
|
import {
|
||||||
|
canonicalizeLegacySessionKey as canonicalizeLegacySessionKeyImpl,
|
||||||
|
isLegacyGroupSessionKey as isLegacyGroupSessionKeyImpl,
|
||||||
|
} from "./src/session-contract.js";
|
||||||
|
|
||||||
|
export const canonicalizeLegacySessionKey = canonicalizeLegacySessionKeyImpl;
|
||||||
|
export const createWhatsAppPollFixture = createWhatsAppPollFixtureImpl;
|
||||||
|
export const expectWhatsAppPollSent = expectWhatsAppPollSentImpl;
|
||||||
|
export const isLegacyGroupSessionKey = isLegacyGroupSessionKeyImpl;
|
||||||
|
export const isWhatsAppGroupJid = isWhatsAppGroupJidImpl;
|
||||||
|
export const normalizeWhatsAppTarget = normalizeWhatsAppTargetImpl;
|
||||||
|
export const resolveLegacyGroupSessionKey = resolveLegacyGroupSessionKeyImpl;
|
||||||
|
export const whatsappAccessControlTesting = whatsappAccessControlTestingImpl;
|
||||||
|
export const whatsappCommandPolicy = whatsappCommandPolicyImpl;
|
||||||
|
|
||||||
export function collectUnsupportedSecretRefConfigCandidates(
|
export function collectUnsupportedSecretRefConfigCandidates(
|
||||||
raw: unknown,
|
raw: unknown,
|
||||||
|
|||||||
@@ -46,17 +46,29 @@ function createModuleLoader() {
|
|||||||
|
|
||||||
const loadModule = createModuleLoader();
|
const loadModule = createModuleLoader();
|
||||||
|
|
||||||
function resolveContractSurfaceModulePath(rootDir: string | undefined): string | null {
|
function resolveContractSurfaceModulePaths(rootDir: string | undefined): string[] {
|
||||||
if (typeof rootDir !== "string" || rootDir.length === 0) {
|
if (typeof rootDir !== "string" || rootDir.length === 0) {
|
||||||
return null;
|
return [];
|
||||||
}
|
}
|
||||||
|
const modulePaths: string[] = [];
|
||||||
for (const basename of CONTRACT_SURFACE_BASENAMES) {
|
for (const basename of CONTRACT_SURFACE_BASENAMES) {
|
||||||
const modulePath = path.join(rootDir, basename);
|
const modulePath = path.join(rootDir, basename);
|
||||||
if (fs.existsSync(modulePath)) {
|
if (!fs.existsSync(modulePath)) {
|
||||||
return modulePath;
|
continue;
|
||||||
}
|
}
|
||||||
|
const compiledDistModulePath = modulePath.replace(
|
||||||
|
`${path.sep}dist-runtime${path.sep}`,
|
||||||
|
`${path.sep}dist${path.sep}`,
|
||||||
|
);
|
||||||
|
// Prefer the compiled dist module over the dist-runtime shim so Jiti sees
|
||||||
|
// the full named export surface instead of only local wrapper exports.
|
||||||
|
if (compiledDistModulePath !== modulePath && fs.existsSync(compiledDistModulePath)) {
|
||||||
|
modulePaths.push(compiledDistModulePath);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
modulePaths.push(modulePath);
|
||||||
}
|
}
|
||||||
return null;
|
return modulePaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadBundledChannelContractSurfaces(): unknown[] {
|
function loadBundledChannelContractSurfaces(): unknown[] {
|
||||||
@@ -79,14 +91,18 @@ function loadBundledChannelContractSurfaceEntries(): Array<{
|
|||||||
if (manifest.origin !== "bundled" || manifest.channels.length === 0) {
|
if (manifest.origin !== "bundled" || manifest.channels.length === 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const modulePath = resolveContractSurfaceModulePath(manifest.rootDir);
|
const modulePaths = resolveContractSurfaceModulePaths(manifest.rootDir);
|
||||||
if (!modulePath) {
|
if (modulePaths.length === 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
const surface = Object.assign(
|
||||||
|
{},
|
||||||
|
...modulePaths.map((modulePath) => loadModule(modulePath)(modulePath) as object),
|
||||||
|
);
|
||||||
surfaces.push({
|
surfaces.push({
|
||||||
pluginId: manifest.id,
|
pluginId: manifest.id,
|
||||||
surface: loadModule(modulePath)(modulePath),
|
surface,
|
||||||
});
|
});
|
||||||
} catch {
|
} catch {
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -897,8 +897,14 @@ function patchConfigForScopedAccount(params: {
|
|||||||
ensureEnabled: boolean;
|
ensureEnabled: boolean;
|
||||||
}): OpenClawConfig {
|
}): OpenClawConfig {
|
||||||
const { cfg, channel, accountId, patch, ensureEnabled } = params;
|
const { cfg, channel, accountId, patch, ensureEnabled } = params;
|
||||||
|
const channelConfig = cfg.channels?.[channel] as
|
||||||
|
| { accounts?: Record<string, unknown> }
|
||||||
|
| undefined;
|
||||||
|
const hasExistingAccounts = Boolean(
|
||||||
|
channelConfig?.accounts && Object.keys(channelConfig.accounts).length > 0,
|
||||||
|
);
|
||||||
const seededCfg =
|
const seededCfg =
|
||||||
accountId === DEFAULT_ACCOUNT_ID
|
accountId === DEFAULT_ACCOUNT_ID || hasExistingAccounts
|
||||||
? cfg
|
? cfg
|
||||||
: moveSingleAccountChannelSectionToDefaultAccount({
|
: moveSingleAccountChannelSectionToDefaultAccount({
|
||||||
cfg,
|
cfg,
|
||||||
|
|||||||
@@ -567,11 +567,20 @@ function discoverInDirectory(params: {
|
|||||||
candidates: PluginCandidate[];
|
candidates: PluginCandidate[];
|
||||||
diagnostics: PluginDiagnostic[];
|
diagnostics: PluginDiagnostic[];
|
||||||
seen: Set<string>;
|
seen: Set<string>;
|
||||||
|
recurseDirectories?: boolean;
|
||||||
skipDirectories?: Set<string>;
|
skipDirectories?: Set<string>;
|
||||||
|
visitedDirectories?: Set<string>;
|
||||||
}) {
|
}) {
|
||||||
if (!fs.existsSync(params.dir)) {
|
if (!fs.existsSync(params.dir)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const resolvedDir = safeRealpathSync(params.dir) ?? path.resolve(params.dir);
|
||||||
|
if (params.recurseDirectories) {
|
||||||
|
if (params.visitedDirectories?.has(resolvedDir)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
params.visitedDirectories?.add(resolvedDir);
|
||||||
|
}
|
||||||
let entries: fs.Dirent[] = [];
|
let entries: fs.Dirent[] = [];
|
||||||
try {
|
try {
|
||||||
entries = fs.readdirSync(params.dir, { withFileTypes: true });
|
entries = fs.readdirSync(params.dir, { withFileTypes: true });
|
||||||
@@ -695,6 +704,14 @@ function discoverInDirectory(params: {
|
|||||||
manifest,
|
manifest,
|
||||||
packageDir: fullPath,
|
packageDir: fullPath,
|
||||||
});
|
});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.recurseDirectories) {
|
||||||
|
discoverInDirectory({
|
||||||
|
...params,
|
||||||
|
dir: fullPath,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -894,6 +911,18 @@ export function discoverOpenClawPlugins(params: {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (roots.workspace && workspaceRoot) {
|
if (roots.workspace && workspaceRoot) {
|
||||||
|
discoverInDirectory({
|
||||||
|
dir: workspaceRoot,
|
||||||
|
origin: "workspace",
|
||||||
|
ownershipUid: params.ownershipUid,
|
||||||
|
workspaceDir: workspaceRoot,
|
||||||
|
candidates,
|
||||||
|
diagnostics,
|
||||||
|
seen,
|
||||||
|
recurseDirectories: true,
|
||||||
|
skipDirectories: new Set([".openclaw"]),
|
||||||
|
visitedDirectories: new Set<string>(),
|
||||||
|
});
|
||||||
discoverInDirectory({
|
discoverInDirectory({
|
||||||
dir: roots.workspace,
|
dir: roots.workspace,
|
||||||
origin: "workspace",
|
origin: "workspace",
|
||||||
|
|||||||
Reference in New Issue
Block a user