Files
openclaw/src/agents/agent-project-settings.bundle.test.ts
Peter Steinberger bb46b79d3c refactor: internalize OpenClaw agent runtime (#85341)
* refactor: extract agent core package

Introduce packages/agent-core as the OpenClaw-owned home for reusable agent loop, harness, session, prompt, and runtime dependency contracts.

* refactor: extract shared llm runtime

Move provider model registries, stream wrappers, OAuth helpers, and LLM utilities into src/llm with plugin-sdk barrels instead of depending on the old embedded runtime layout.

* refactor: remove pi runtime internals

Rename remaining Pi-shaped agent surfaces to OpenClaw agent runtime names, delete obsolete Pi docs and package graph checks, and add the third-party notice for incorporated code.

* refactor: tighten agent session runtime

Make agent-core/runtime dependencies explicit, consolidate compaction and session transcript helpers, and move model/session helpers behind OpenClaw-owned contracts.

* refactor: remove static model and pi auth paths

Drop static model catalogs and Pi auth bridges, move model/provider facts to manifest-owned runtime contracts, and harden internal embedded-agent utilities.

* refactor: remove legacy provider compat paths

* docs: remove agent parity notes

* fix: skip provider wildcard metadata parsing

* refactor: share session extension sdk loading

* refactor: inline acpx proxy error formatter

* refactor: fold edit recovery into edit tool

* fix: accept extension batch separator

* test: align startup provider plugin expectations

* fix: restore provider-scoped release discovery

* test: align static asset packaging expectations

* fix: run static provider catalogs during scoped discovery

* fix: add provider entry catalogs for scoped live discovery

* fix: load lightweight provider catalog entries

* fix: refresh provider-scoped plugin metadata

* fix: keep provider catalog entries on release live path

* fix: keep static manifest models in release live checks

* fix: harden release model discovery

* fix: reduce OpenAI live cache probe reasoning

* fix: disable OpenAI cache probe reasoning

* ci: extend OpenAI gateway live timeout

* fix: extend live gateway model budget

* fix: stabilize release validation regressions

* fix: honor provider aliases in model rows

* fix: stabilize release validation lanes

* fix: stabilize release memory qa

* ci: stabilize release validation lanes

* ci: prefer ipv4 for live docker node calls

* fix: restore shared tool-call stream wrapper

* ci: remove legacy pi test shard alias

* fix: clean up embedded agent test drift

* fix: stabilize runtime alias status

* fix: clean up embedded agent ci drift

* fix: restore release ci invariants

* fix: clean up post-rebase runtime drift

* fix: restore release ci checks

* fix: restore release ci after rebase

* fix: remove stale pi runtime path

* test: align compaction runtime expectations

* test: update plugin prerelease expectations

* fix: handle claude live tool approvals

* fix: stabilize release validation gates

* fix: finish agent runtime import

* test: finish post-rebase agent runtime mocks

* fix: keep codex compaction native

* fix: stabilize codex app-server hook tests

* test: isolate codex diagnostic active run

* test: remove codex diagnostic completion race

# Conflicts:
#	extensions/codex/src/app-server/run-attempt.test.ts

* ci: fix full release manifest performance run id

* refactor: narrow llm plugin sdk boundary

* chore: drop generated google boundary stamps

* fix: repair rebase fallout

* fix: clean up rebased runtime references

* fix: decode codex jwt payloads as base64url

* fix: preserve shipped pi runtime alias

* fix: add scoped sdk virtual modules

* fix: decode llm codex oauth jwt as base64url

* fix: avoid stale vertex adc negative cache

* fix: harden tool arg decoding and codeql path

* fix: keep vertex adc negative checks live

* refactor: consolidate codex jwt and edit helpers

* fix: await codex oauth node runtime imports

* fix: preserve sdk tool and notice contracts

* fix: preserve shipped compat config boundaries

* fix: align codex oauth callback host

* fix: terminate agent-core loop streams on failure

* fix: keep codex oauth callback alive during fallback

* ci: include session tools in critical codeql scans

* fix: keep Cloudflare Anthropic provider auth header

* docs: redirect legacy pi runtime pages

* fix: honor bundled web provider compat discovery

* fix: protect session output spill files

* fix: keep legacy agent dir env blocked

* fix: contain auto-discovered skill symlinks

* fix: harden agent core sdk proxy surfaces

* fix: restore approval reaction sdk compat

* fix: keep live docker runs bounded

* fix: keep codex oauth redirect host aligned

* fix: resolve post-rebase agent runtime drift

* fix: redact anthropic oauth parse failures

* fix: preserve responses strict tool shaping

* fix: repair agent runtime rebase cleanup

* docs: redirect retired parity pages

* fix: bound auto-discovered resources to roots

* fix: repair post-rebase agent test drift

* fix: preserve bundled provider allowlist migration

* fix: preserve manifest-owned provider aliases

* fix: declare photon image dependency

* fix: keep provider headers out of proxy body

* fix: preserve shipped env aliases

* fix: refresh control ui i18n generated state

* fix: quote read fallback paths

* fix: preview edits through configured backend

* test: satisfy core test typecheck

* fix: preserve ZAI usage auth fallback

* test: repair codex diagnostic test

* fix: repair agent runtime rebase drift

* test: finish embedded runner import rename

* fix: repair agent runtime rebase integrations

* test: align compaction oauth fallback expectations

* fix: allow sdk-auth session models

* fix: update doctor tool schema import

* fix: preserve bedrock plugin region

* fix: stream harmony-like prose immediately

* ci: include session runtime in codeql shards

* fix: repair latest rebase integrations

* fix: honor explicit codex websocket transport

* fix: keep openai-compatible credentials provider-scoped

* fix: refresh sdk api baseline after rebase

* fix: route cli runtime aliases through openclaw harness

* test: rename stale harness mock expectation

* test: rename embedded agent overflow calls

* test: clean embedded auth test wording

* test: use openclaw stream types in deepinfra cache test

* fix: refresh sdk api baseline on latest main

* fix: honor bundled discovery compat allowlists

* fix: refresh sdk api baseline after latest rebase

* fix: remove stale rebase imports

* test: rename stale model catalog mock

* test: mock renamed doctor runtime modules

* fix: map canonical kimi env auth

* fix: use internal model registry in bench script

* fix: migrate deepinfra provider catalog entry

* fix: enforce builtin tool suppression

* fix: route compaction auth and proxy payloads safely

* refactor: prune unused llm registry leftovers

* test: update codex hooks session import

* test: fix model picker ci coverage

* test: align model picker auth mock types
2026-05-27 19:24:04 +01:00

483 lines
16 KiB
TypeScript

import fs from "node:fs/promises";
import path from "node:path";
import { afterEach, describe, expect, it, vi } from "vitest";
import { createTrackedTempDirs } from "../test-utils/tracked-temp-dirs.js";
const pluginMetadataSnapshotMocks = vi.hoisted(() => ({
getCurrentPluginMetadataSnapshot: vi.fn(),
isPluginMetadataSnapshotCompatible: vi.fn(),
loadPluginMetadataSnapshot: vi.fn(),
}));
const bundleTestDeps = await vi.hoisted(async () => {
const fsSync = await import("node:fs");
const pathModule = await import("node:path");
const loadBundleRegistry = (params: { workspaceDir?: string }) => {
const rootDir = pathModule.join(
params.workspaceDir ?? "",
".openclaw",
"extensions",
"claude-bundle",
);
if (!fsSync.existsSync(pathModule.join(rootDir, ".claude-plugin", "plugin.json"))) {
return { plugins: [], diagnostics: [] };
}
const resolvedRootDir = fsSync.realpathSync(rootDir);
return {
diagnostics: [],
plugins: [
{
id: "claude-bundle",
origin: "workspace",
format: "bundle",
bundleFormat: "claude",
settingsFiles: ["settings.json"],
rootDir: resolvedRootDir,
},
],
};
};
const loadEmbeddedAgentMcpConfig = (params: {
workspaceDir: string;
cfg?: { mcp?: { servers?: Record<string, unknown> } };
}) => {
const pluginRoot = pathModule.join(
params.workspaceDir,
".openclaw",
"extensions",
"claude-bundle",
);
const mcpPath = pathModule.join(pluginRoot, ".mcp.json");
let bundleServers: Record<string, unknown> = {};
if (fsSync.existsSync(mcpPath)) {
const raw = JSON.parse(fsSync.readFileSync(mcpPath, "utf-8")) as {
mcpServers?: Record<string, { args?: string[]; command?: string }>;
};
const resolvedRoot = fsSync.realpathSync(pluginRoot);
bundleServers = Object.fromEntries(
Object.entries(raw.mcpServers ?? {}).map(([id, server]) => [
id,
{
...server,
args: server.args?.map((arg) =>
arg.startsWith("./") ? pathModule.join(resolvedRoot, arg) : arg,
),
cwd: resolvedRoot,
},
]),
);
}
return {
diagnostics: [],
mcpServers: {
...bundleServers,
...params.cfg?.mcp?.servers,
},
};
};
return { fsSync, loadBundleRegistry, loadEmbeddedAgentMcpConfig };
});
vi.mock("../infra/boundary-file-read.js", () => {
return {
openRootFileSync: ({ absolutePath }: { absolutePath: string }) => ({
ok: true,
fd: bundleTestDeps.fsSync.openSync(absolutePath, "r"),
}),
};
});
vi.mock("../plugins/manifest-registry-installed.js", () => ({
loadPluginManifestRegistryForInstalledIndex: bundleTestDeps.loadBundleRegistry,
}));
vi.mock("../plugins/plugin-registry.js", () => ({
loadPluginManifestRegistryForPluginRegistry: bundleTestDeps.loadBundleRegistry,
loadPluginRegistrySnapshot: () => ({ plugins: [] }),
}));
vi.mock("../plugins/current-plugin-metadata-snapshot.js", () => ({
getCurrentPluginMetadataSnapshot: pluginMetadataSnapshotMocks.getCurrentPluginMetadataSnapshot,
}));
vi.mock("../plugins/plugin-metadata-snapshot.js", () => {
pluginMetadataSnapshotMocks.isPluginMetadataSnapshotCompatible.mockImplementation(() => false);
pluginMetadataSnapshotMocks.loadPluginMetadataSnapshot.mockImplementation(
(params: { workspaceDir?: string }) => ({
manifestRegistry: bundleTestDeps.loadBundleRegistry(params),
normalizePluginId: (id: string) => id.trim(),
}),
);
return {
isPluginMetadataSnapshotCompatible:
pluginMetadataSnapshotMocks.isPluginMetadataSnapshotCompatible,
loadPluginMetadataSnapshot: pluginMetadataSnapshotMocks.loadPluginMetadataSnapshot,
};
});
vi.mock("./embedded-agent-mcp.js", () => ({
loadEmbeddedAgentMcpConfig: bundleTestDeps.loadEmbeddedAgentMcpConfig,
}));
const { loadEnabledBundleAgentSettingsSnapshot } =
await import("./agent-project-settings-snapshot.js");
const tempDirs = createTrackedTempDirs();
afterEach(async () => {
await tempDirs.cleanup();
pluginMetadataSnapshotMocks.getCurrentPluginMetadataSnapshot.mockReset();
pluginMetadataSnapshotMocks.getCurrentPluginMetadataSnapshot.mockReturnValue(undefined);
pluginMetadataSnapshotMocks.isPluginMetadataSnapshotCompatible.mockClear();
pluginMetadataSnapshotMocks.loadPluginMetadataSnapshot.mockClear();
});
async function createWorkspaceBundle(params: {
workspaceDir: string;
pluginId?: string;
}): Promise<string> {
const pluginId = params.pluginId ?? "claude-bundle";
const pluginRoot = path.join(params.workspaceDir, ".openclaw", "extensions", pluginId);
await fs.mkdir(path.join(pluginRoot, ".claude-plugin"), { recursive: true });
await fs.writeFile(
path.join(pluginRoot, ".claude-plugin", "plugin.json"),
JSON.stringify({
name: pluginId,
}),
"utf-8",
);
return pluginRoot;
}
describe("loadEnabledBundleAgentSettingsSnapshot", () => {
it("reuses a compatible plugin metadata snapshot without loading a fresh one", async () => {
const workspaceDir = await tempDirs.make("openclaw-workspace-");
const pluginRoot = await createWorkspaceBundle({ workspaceDir });
const resolvedPluginRoot = await fs.realpath(pluginRoot);
await fs.writeFile(
path.join(pluginRoot, "settings.json"),
JSON.stringify({ hideThinkingBlock: true }),
"utf-8",
);
pluginMetadataSnapshotMocks.isPluginMetadataSnapshotCompatible.mockReturnValueOnce(true);
pluginMetadataSnapshotMocks.loadPluginMetadataSnapshot.mockClear();
const snapshot = loadEnabledBundleAgentSettingsSnapshot({
cwd: workspaceDir,
cfg: {
plugins: {
entries: {
"claude-bundle": { enabled: true },
},
},
},
pluginMetadataSnapshot: {
manifestRegistry: {
diagnostics: [],
plugins: [
{
id: "claude-bundle",
origin: "workspace",
format: "bundle",
bundleFormat: "claude",
settingsFiles: ["settings.json"],
rootDir: resolvedPluginRoot,
},
],
},
normalizePluginId: (id: string) => id.trim(),
} as unknown as Parameters<
typeof loadEnabledBundleAgentSettingsSnapshot
>[0]["pluginMetadataSnapshot"],
});
expect(snapshot.hideThinkingBlock).toBe(true);
expect(pluginMetadataSnapshotMocks.isPluginMetadataSnapshotCompatible).toHaveBeenCalledOnce();
expect(pluginMetadataSnapshotMocks.loadPluginMetadataSnapshot).not.toHaveBeenCalled();
});
it("falls back to a fresh plugin metadata load for an incompatible snapshot", async () => {
const workspaceDir = await tempDirs.make("openclaw-workspace-");
const pluginRoot = await createWorkspaceBundle({ workspaceDir });
await fs.writeFile(
path.join(pluginRoot, "settings.json"),
JSON.stringify({ hideThinkingBlock: true }),
"utf-8",
);
pluginMetadataSnapshotMocks.isPluginMetadataSnapshotCompatible.mockReturnValueOnce(false);
pluginMetadataSnapshotMocks.loadPluginMetadataSnapshot.mockClear();
const snapshot = loadEnabledBundleAgentSettingsSnapshot({
cwd: workspaceDir,
cfg: {
plugins: {
entries: {
"claude-bundle": { enabled: true },
},
},
},
pluginMetadataSnapshot: {
manifestRegistry: { diagnostics: [], plugins: [] },
normalizePluginId: (id: string) => id.trim(),
} as unknown as Parameters<
typeof loadEnabledBundleAgentSettingsSnapshot
>[0]["pluginMetadataSnapshot"],
});
expect(snapshot.hideThinkingBlock).toBe(true);
expect(pluginMetadataSnapshotMocks.isPluginMetadataSnapshotCompatible).toHaveBeenCalledOnce();
expect(pluginMetadataSnapshotMocks.loadPluginMetadataSnapshot).toHaveBeenCalledOnce();
});
it("reuses the current plugin metadata snapshot for bundle settings", async () => {
const workspaceDir = await tempDirs.make("openclaw-workspace-");
const pluginRoot = await createWorkspaceBundle({ workspaceDir });
const resolvedPluginRoot = await fs.realpath(pluginRoot);
await fs.writeFile(
path.join(pluginRoot, "settings.json"),
JSON.stringify({ hideThinkingBlock: true }),
"utf-8",
);
pluginMetadataSnapshotMocks.getCurrentPluginMetadataSnapshot.mockReturnValueOnce({
manifestRegistry: {
diagnostics: [],
plugins: [
{
id: "claude-bundle",
origin: "workspace",
format: "bundle",
bundleFormat: "claude",
settingsFiles: ["settings.json"],
rootDir: resolvedPluginRoot,
},
],
},
normalizePluginId: (id: string) => id.trim(),
});
pluginMetadataSnapshotMocks.loadPluginMetadataSnapshot.mockClear();
const snapshot = loadEnabledBundleAgentSettingsSnapshot({
cwd: workspaceDir,
cfg: {
plugins: {
entries: {
"claude-bundle": { enabled: true },
},
},
},
});
expect(snapshot.hideThinkingBlock).toBe(true);
expect(pluginMetadataSnapshotMocks.loadPluginMetadataSnapshot).not.toHaveBeenCalled();
});
it("does not reuse an unscoped current snapshot when plugin load paths change", async () => {
const workspaceDir = await tempDirs.make("openclaw-workspace-");
const pluginRoot = await createWorkspaceBundle({ workspaceDir });
await fs.writeFile(
path.join(pluginRoot, "settings.json"),
JSON.stringify({ hideThinkingBlock: true }),
"utf-8",
);
pluginMetadataSnapshotMocks.getCurrentPluginMetadataSnapshot.mockReturnValueOnce(undefined);
pluginMetadataSnapshotMocks.loadPluginMetadataSnapshot.mockClear();
const snapshot = loadEnabledBundleAgentSettingsSnapshot({
cwd: workspaceDir,
cfg: {
plugins: {
load: { paths: ["/tmp/changed-plugin-root"] },
entries: {
"claude-bundle": { enabled: true },
},
},
},
});
expect(snapshot.hideThinkingBlock).toBe(true);
expect(pluginMetadataSnapshotMocks.getCurrentPluginMetadataSnapshot).toHaveBeenCalledOnce();
const [snapshotLookup] =
pluginMetadataSnapshotMocks.getCurrentPluginMetadataSnapshot.mock.calls[0] ?? [];
expect(snapshotLookup?.config?.plugins?.load).toEqual({
paths: ["/tmp/changed-plugin-root"],
});
expect(snapshotLookup?.env).toBe(process.env);
expect(snapshotLookup?.workspaceDir).toBe(workspaceDir);
expect(pluginMetadataSnapshotMocks.loadPluginMetadataSnapshot).toHaveBeenCalledOnce();
});
it("does not reuse a load-path current snapshot for a config with default load paths", async () => {
const workspaceDir = await tempDirs.make("openclaw-workspace-");
const pluginRoot = await createWorkspaceBundle({ workspaceDir });
const resolvedPluginRoot = await fs.realpath(pluginRoot);
await fs.writeFile(
path.join(pluginRoot, "settings.json"),
JSON.stringify({ hideThinkingBlock: true }),
"utf-8",
);
const staleSnapshot = {
policyHash: "policy",
manifestRegistry: {
diagnostics: [],
plugins: [
{
id: "claude-bundle",
origin: "workspace",
format: "bundle",
bundleFormat: "claude",
settingsFiles: ["settings.json"],
rootDir: resolvedPluginRoot,
},
],
},
normalizePluginId: (id: string) => id.trim(),
};
pluginMetadataSnapshotMocks.getCurrentPluginMetadataSnapshot.mockImplementation(
(params: { config?: unknown; requireDefaultDiscoveryContext?: boolean }) => {
if (params.config || params.requireDefaultDiscoveryContext) {
return undefined;
}
return staleSnapshot;
},
);
pluginMetadataSnapshotMocks.loadPluginMetadataSnapshot.mockClear();
const snapshot = loadEnabledBundleAgentSettingsSnapshot({
cwd: workspaceDir,
cfg: {
plugins: {
entries: {
"claude-bundle": { enabled: true },
},
},
},
});
expect(snapshot.hideThinkingBlock).toBe(true);
expect(pluginMetadataSnapshotMocks.getCurrentPluginMetadataSnapshot).toHaveBeenCalledTimes(2);
expect(pluginMetadataSnapshotMocks.getCurrentPluginMetadataSnapshot).toHaveBeenLastCalledWith({
env: process.env,
workspaceDir,
allowWorkspaceScopedSnapshot: true,
requireDefaultDiscoveryContext: true,
});
expect(pluginMetadataSnapshotMocks.loadPluginMetadataSnapshot).toHaveBeenCalledOnce();
});
it("loads sanitized settings and MCP defaults from enabled bundle plugins", async () => {
const workspaceDir = await tempDirs.make("openclaw-workspace-");
const pluginRoot = await createWorkspaceBundle({ workspaceDir });
const resolvedPluginRoot = await fs.realpath(pluginRoot);
await fs.mkdir(path.join(pluginRoot, "servers"), { recursive: true });
const resolvedServerPath = await fs.realpath(path.join(pluginRoot, "servers"));
await fs.writeFile(
path.join(pluginRoot, "settings.json"),
JSON.stringify({
hideThinkingBlock: true,
shellPath: "/tmp/blocked-shell",
compaction: { keepRecentTokens: 64_000 },
}),
"utf-8",
);
await fs.writeFile(
path.join(pluginRoot, ".mcp.json"),
JSON.stringify({
mcpServers: {
bundleProbe: {
command: "node",
args: ["./servers/probe.mjs"],
},
sharedServer: {
command: "node",
args: ["./servers/bundle.mjs"],
},
},
}),
"utf-8",
);
const snapshot = loadEnabledBundleAgentSettingsSnapshot({
cwd: workspaceDir,
cfg: {
plugins: {
entries: {
"claude-bundle": { enabled: true },
},
},
},
});
expect(snapshot.hideThinkingBlock).toBe(true);
expect(snapshot.shellPath).toBeUndefined();
expect(snapshot.compaction?.keepRecentTokens).toBe(64_000);
expect((snapshot as Record<string, unknown>).mcpServers).toEqual({
bundleProbe: {
command: "node",
args: [path.join(resolvedServerPath, "probe.mjs")],
cwd: resolvedPluginRoot,
},
sharedServer: {
command: "node",
args: [path.join(resolvedServerPath, "bundle.mjs")],
cwd: resolvedPluginRoot,
},
});
const overridden = loadEnabledBundleAgentSettingsSnapshot({
cwd: workspaceDir,
cfg: {
mcp: {
servers: {
sharedServer: {
url: "https://example.com/mcp",
},
},
},
plugins: {
entries: {
"claude-bundle": { enabled: true },
},
},
},
});
expect((overridden as Record<string, unknown>).mcpServers).toEqual({
bundleProbe: {
command: "node",
args: [path.join(resolvedServerPath, "probe.mjs")],
cwd: resolvedPluginRoot,
},
sharedServer: {
url: "https://example.com/mcp",
},
});
});
it("ignores disabled bundle plugins", async () => {
const workspaceDir = await tempDirs.make("openclaw-workspace-");
const pluginRoot = await createWorkspaceBundle({ workspaceDir });
await fs.writeFile(
path.join(pluginRoot, "settings.json"),
JSON.stringify({ hideThinkingBlock: true }),
"utf-8",
);
const snapshot = loadEnabledBundleAgentSettingsSnapshot({
cwd: workspaceDir,
cfg: {
plugins: {
entries: {
"claude-bundle": { enabled: false },
},
},
},
});
expect(snapshot).toStrictEqual({});
});
});