mirror of
https://github.com/moltbot/moltbot.git
synced 2026-04-18 20:24:47 +00:00
fix: stabilize Codex harness landing checks
This commit is contained in:
@@ -16,7 +16,7 @@ const sourceRoots = ["src/channels", "src/routing", "src/line", "extensions"];
|
||||
const allowedRawFetchCallsites = new Set([
|
||||
bundledPluginCallsite("bluebubbles", "src/test-harness.ts", 128),
|
||||
bundledPluginCallsite("bluebubbles", "src/types.ts", 181),
|
||||
bundledPluginCallsite("browser", "src/browser/cdp.helpers.ts", 235),
|
||||
bundledPluginCallsite("browser", "src/browser/cdp.helpers.ts", 253),
|
||||
bundledPluginCallsite("browser", "src/browser/client-fetch.ts", 192),
|
||||
bundledPluginCallsite("browser", "src/browser/test-fetch.ts", 24),
|
||||
bundledPluginCallsite("browser", "src/browser/test-fetch.ts", 27),
|
||||
@@ -41,8 +41,8 @@ const allowedRawFetchCallsites = new Set([
|
||||
bundledPluginCallsite("minimax", "oauth.ts", 107),
|
||||
bundledPluginCallsite("minimax", "tts.ts", 52),
|
||||
bundledPluginCallsite("msteams", "src/graph.ts", 47),
|
||||
bundledPluginCallsite("msteams", "src/sdk.ts", 292),
|
||||
bundledPluginCallsite("msteams", "src/sdk.ts", 333),
|
||||
bundledPluginCallsite("msteams", "src/sdk.ts", 329),
|
||||
bundledPluginCallsite("msteams", "src/sdk.ts", 370),
|
||||
bundledPluginCallsite("ollama", "src/stream.ts", 649),
|
||||
bundledPluginCallsite("openai", "tts.ts", 133),
|
||||
bundledPluginCallsite("qa-channel", "src/bus-client.ts", 41),
|
||||
|
||||
@@ -29,6 +29,7 @@ vi.mock("@mariozechner/pi-ai", async () => {
|
||||
});
|
||||
|
||||
vi.mock("@mariozechner/pi-coding-agent", () => ({
|
||||
generateSummary: vi.fn(async () => "summary"),
|
||||
SessionManager: {
|
||||
open: () => ({
|
||||
getLeafEntry: getLeafEntryMock,
|
||||
|
||||
@@ -269,6 +269,7 @@ export async function loadCompactHooksHarness(): Promise<{
|
||||
create: vi.fn(() => ({})),
|
||||
},
|
||||
estimateTokens: estimateTokensMock,
|
||||
generateSummary: vi.fn(async () => "summary"),
|
||||
}));
|
||||
|
||||
vi.doMock("../session-tool-result-guard-wrapper.js", () => ({
|
||||
@@ -457,6 +458,7 @@ export async function loadCompactHooksHarness(): Promise<{
|
||||
}));
|
||||
|
||||
vi.doMock("../agent-scope.js", () => ({
|
||||
listAgentEntries: vi.fn(() => []),
|
||||
resolveSessionAgentId: resolveSessionAgentIdMock,
|
||||
resolveSessionAgentIds: vi.fn(() => ({ defaultAgentId: "main", sessionAgentId: "main" })),
|
||||
}));
|
||||
|
||||
@@ -2954,6 +2954,19 @@ export const GENERATED_BASE_CONFIG_SCHEMA: BaseConfigSchemaResponse = {
|
||||
},
|
||||
additionalProperties: {},
|
||||
},
|
||||
embeddedHarness: {
|
||||
type: "object",
|
||||
properties: {
|
||||
runtime: {
|
||||
type: "string",
|
||||
},
|
||||
fallback: {
|
||||
type: "string",
|
||||
enum: ["pi", "none"],
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
model: {
|
||||
anyOf: [
|
||||
{
|
||||
@@ -5415,6 +5428,19 @@ export const GENERATED_BASE_CONFIG_SCHEMA: BaseConfigSchemaResponse = {
|
||||
systemPromptOverride: {
|
||||
type: "string",
|
||||
},
|
||||
embeddedHarness: {
|
||||
type: "object",
|
||||
properties: {
|
||||
runtime: {
|
||||
type: "string",
|
||||
},
|
||||
fallback: {
|
||||
type: "string",
|
||||
enum: ["pi", "none"],
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
model: {
|
||||
anyOf: [
|
||||
{
|
||||
|
||||
@@ -46,6 +46,7 @@ vi.mock("../agents/subagent-registry.js", () => ({
|
||||
}));
|
||||
|
||||
vi.mock("../config/paths.js", () => ({
|
||||
STATE_DIR: "/tmp/openclaw-state",
|
||||
resolveStateDir: vi.fn(() => "/tmp/openclaw-state"),
|
||||
}));
|
||||
|
||||
|
||||
@@ -143,6 +143,7 @@ describe("gateway startup primary model warmup", () => {
|
||||
expect(selectAgentHarnessMock).toHaveBeenCalledWith({
|
||||
provider: "codex",
|
||||
modelId: "gpt-5.4",
|
||||
config: cfg,
|
||||
});
|
||||
expect(ensureOpenClawModelsJsonMock).not.toHaveBeenCalled();
|
||||
expect(resolveModelMock).not.toHaveBeenCalled();
|
||||
@@ -188,6 +189,7 @@ describe("gateway startup primary model warmup", () => {
|
||||
expect(selectAgentHarnessMock).toHaveBeenCalledWith({
|
||||
provider: "openai-codex",
|
||||
modelId: "gpt-5.4",
|
||||
config: cfg,
|
||||
});
|
||||
expect(ensureOpenClawModelsJsonMock).toHaveBeenCalledWith(cfg, "/tmp/agent");
|
||||
expect(resolveModelMock).toHaveBeenCalled();
|
||||
|
||||
@@ -218,7 +218,13 @@ export async function installPackageDir(params: {
|
||||
candidatePaths: [canonicalTargetDir],
|
||||
});
|
||||
stageDir = await fs.mkdtemp(path.join(installBaseRealPath, ".openclaw-install-stage-"));
|
||||
await fs.cp(params.sourceDir, stageDir, { recursive: true, verbatimSymlinks: true });
|
||||
await fs.cp(params.sourceDir, stageDir, {
|
||||
recursive: true,
|
||||
// Keep relative symlinks relative to the staged copy. Node's default
|
||||
// rewrites them toward the source tree, which makes valid vendored
|
||||
// package links look like install-root escapes during post-copy scans.
|
||||
verbatimSymlinks: true,
|
||||
});
|
||||
} catch (err) {
|
||||
return await fail(`${params.copyErrorPrefix}: ${String(err)}`, err);
|
||||
}
|
||||
|
||||
@@ -187,9 +187,11 @@ async function inspectNodeModulesSymlinkTarget(params: {
|
||||
const resolvedTargetStats = await fs.stat(resolvedTargetPath);
|
||||
const resolvedTargetRelativePath = path.relative(params.rootRealPath, resolvedTargetPath);
|
||||
return {
|
||||
blockedDirectoryFinding: findBlockedPackageDirectoryInPath({
|
||||
pathRelativeToRoot: resolvedTargetRelativePath,
|
||||
}),
|
||||
blockedDirectoryFinding: resolvedTargetStats.isDirectory()
|
||||
? findBlockedPackageDirectoryInPath({
|
||||
pathRelativeToRoot: resolvedTargetRelativePath,
|
||||
})
|
||||
: undefined,
|
||||
blockedFileFinding: resolvedTargetStats.isFile()
|
||||
? findBlockedPackageFileAliasInPath({
|
||||
pathRelativeToRoot: resolvedTargetRelativePath,
|
||||
@@ -262,16 +264,6 @@ function resolvePackageManifestTraversalLimits(): PackageManifestTraversalLimits
|
||||
};
|
||||
}
|
||||
|
||||
async function resolvePackageManifestPath(dir: string): Promise<string | undefined> {
|
||||
const manifestPath = path.join(dir, "package.json");
|
||||
try {
|
||||
const stats = await fs.stat(manifestPath);
|
||||
return stats.isFile() ? manifestPath : undefined;
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
async function collectPackageManifestPaths(
|
||||
rootDir: string,
|
||||
): Promise<PackageManifestTraversalResult> {
|
||||
@@ -280,6 +272,8 @@ async function collectPackageManifestPaths(
|
||||
const queue: Array<{ depth: number; dir: string }> = [{ depth: 0, dir: rootDir }];
|
||||
const packageManifestPaths: string[] = [];
|
||||
const visitedDirectories = new Set<string>();
|
||||
let firstBlockedDirectoryFinding: BlockedPackageDirectoryFinding | undefined;
|
||||
let firstBlockedFileFinding: BlockedPackageFileFinding | undefined;
|
||||
let queueIndex = 0;
|
||||
|
||||
while (queueIndex < queue.length) {
|
||||
@@ -331,19 +325,13 @@ async function collectPackageManifestPaths(
|
||||
directoryRelativePath: relativeNextPath,
|
||||
});
|
||||
if (blockedDirectoryFinding) {
|
||||
return {
|
||||
blockedDirectoryFinding,
|
||||
packageManifestPaths,
|
||||
};
|
||||
firstBlockedDirectoryFinding ??= blockedDirectoryFinding;
|
||||
}
|
||||
const blockedFileFinding = findBlockedNodeModulesFileAlias({
|
||||
fileRelativePath: relativeNextPath,
|
||||
});
|
||||
if (blockedFileFinding) {
|
||||
return {
|
||||
blockedFileFinding,
|
||||
packageManifestPaths,
|
||||
};
|
||||
firstBlockedFileFinding ??= blockedFileFinding;
|
||||
}
|
||||
if (pathContainsNodeModulesSegment(relativeNextPath)) {
|
||||
const symlinkTargetInspection = await inspectNodeModulesSymlinkTarget({
|
||||
@@ -352,16 +340,10 @@ async function collectPackageManifestPaths(
|
||||
symlinkRelativePath: relativeNextPath,
|
||||
});
|
||||
if (symlinkTargetInspection.blockedDirectoryFinding) {
|
||||
return {
|
||||
blockedDirectoryFinding: symlinkTargetInspection.blockedDirectoryFinding,
|
||||
packageManifestPaths,
|
||||
};
|
||||
firstBlockedDirectoryFinding ??= symlinkTargetInspection.blockedDirectoryFinding;
|
||||
}
|
||||
if (symlinkTargetInspection.blockedFileFinding) {
|
||||
return {
|
||||
blockedFileFinding: symlinkTargetInspection.blockedFileFinding,
|
||||
packageManifestPaths,
|
||||
};
|
||||
firstBlockedFileFinding ??= symlinkTargetInspection.blockedFileFinding;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
@@ -371,14 +353,7 @@ async function collectPackageManifestPaths(
|
||||
directoryRelativePath: relativeNextPath,
|
||||
});
|
||||
if (blockedDirectoryFinding) {
|
||||
const manifestPath = await resolvePackageManifestPath(nextPath);
|
||||
if (manifestPath) {
|
||||
packageManifestPaths.push(manifestPath);
|
||||
}
|
||||
return {
|
||||
blockedDirectoryFinding,
|
||||
packageManifestPaths,
|
||||
};
|
||||
firstBlockedDirectoryFinding ??= blockedDirectoryFinding;
|
||||
}
|
||||
queue.push({ depth: current.depth + 1, dir: nextPath });
|
||||
continue;
|
||||
@@ -388,10 +363,7 @@ async function collectPackageManifestPaths(
|
||||
fileRelativePath: relativeNextPath,
|
||||
});
|
||||
if (blockedFileFinding) {
|
||||
return {
|
||||
blockedFileFinding,
|
||||
packageManifestPaths,
|
||||
};
|
||||
firstBlockedFileFinding ??= blockedFileFinding;
|
||||
}
|
||||
}
|
||||
if (entry.isFile() && entry.name === "package.json") {
|
||||
@@ -405,7 +377,11 @@ async function collectPackageManifestPaths(
|
||||
}
|
||||
}
|
||||
|
||||
return { packageManifestPaths };
|
||||
return {
|
||||
packageManifestPaths,
|
||||
blockedDirectoryFinding: firstBlockedDirectoryFinding,
|
||||
blockedFileFinding: firstBlockedFileFinding,
|
||||
};
|
||||
}
|
||||
|
||||
async function scanManifestDependencyDenylist(params: {
|
||||
|
||||
Reference in New Issue
Block a user