mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-04 20:00:22 +00:00
fix(ci): repair main type drift
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import type { SecretRef } from "../config/types.secrets.js";
|
||||
import {
|
||||
buildProviderRequestDispatcherPolicy,
|
||||
mergeModelProviderRequestOverrides,
|
||||
@@ -296,17 +297,32 @@ describe("provider request config", () => {
|
||||
});
|
||||
|
||||
it("fails fast when configured request overrides still contain unresolved SecretRefs", () => {
|
||||
const tenantRef: SecretRef = {
|
||||
source: "env",
|
||||
provider: "default",
|
||||
id: "MEDIA_AUDIO_TENANT",
|
||||
};
|
||||
const tokenRef: SecretRef = {
|
||||
source: "env",
|
||||
provider: "default",
|
||||
id: "MEDIA_AUDIO_TOKEN",
|
||||
};
|
||||
const certRef: SecretRef = {
|
||||
source: "env",
|
||||
provider: "default",
|
||||
id: "MEDIA_AUDIO_CERT",
|
||||
};
|
||||
expect(() =>
|
||||
sanitizeConfiguredProviderRequest({
|
||||
headers: {
|
||||
"X-Tenant": { source: "env", provider: "default", id: "MEDIA_AUDIO_TENANT" },
|
||||
"X-Tenant": tenantRef,
|
||||
},
|
||||
auth: {
|
||||
mode: "authorization-bearer",
|
||||
token: { source: "env", provider: "default", id: "MEDIA_AUDIO_TOKEN" },
|
||||
token: tokenRef,
|
||||
},
|
||||
tls: {
|
||||
cert: { source: "env", provider: "default", id: "MEDIA_AUDIO_CERT" },
|
||||
cert: certRef,
|
||||
},
|
||||
}),
|
||||
).toThrow(/request\.(headers\.X-Tenant|auth\.token|tls\.cert): unresolved SecretRef/i);
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import type { Api } from "@mariozechner/pi-ai";
|
||||
import type { ModelDefinitionConfig } from "../config/types.js";
|
||||
import type { ConfiguredModelProviderRequest } from "../config/types.provider-request.js";
|
||||
import type {
|
||||
ConfiguredModelProviderRequest,
|
||||
ConfiguredProviderRequest,
|
||||
} from "../config/types.provider-request.js";
|
||||
import { assertSecretInputResolved } from "../config/types.secrets.js";
|
||||
import type { PinnedDispatcherPolicy } from "../infra/net/ssrf.js";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
@@ -177,7 +180,7 @@ function sanitizeConfiguredRequestString(value: unknown, path: string): string |
|
||||
}
|
||||
|
||||
export function sanitizeConfiguredProviderRequest(
|
||||
request: ProviderRequestTransportOverrides | undefined,
|
||||
request: ConfiguredProviderRequest | undefined,
|
||||
): ProviderRequestTransportOverrides | undefined {
|
||||
if (!request || typeof request !== "object" || Array.isArray(request)) {
|
||||
return undefined;
|
||||
@@ -338,9 +341,6 @@ export function mergeProviderRequestOverrides(
|
||||
...(current.auth ? { auth: current.auth } : {}),
|
||||
...(current.proxy ? { proxy: current.proxy } : {}),
|
||||
...(current.tls ? { tls: current.tls } : {}),
|
||||
...(current.allowPrivateNetwork !== undefined
|
||||
? { allowPrivateNetwork: current.allowPrivateNetwork }
|
||||
: {}),
|
||||
};
|
||||
}
|
||||
return merged;
|
||||
@@ -349,7 +349,9 @@ export function mergeProviderRequestOverrides(
|
||||
export function mergeModelProviderRequestOverrides(
|
||||
...overrides: Array<ModelProviderRequestTransportOverrides | undefined>
|
||||
): ModelProviderRequestTransportOverrides | undefined {
|
||||
let merged = mergeProviderRequestOverrides(...overrides);
|
||||
let merged: ModelProviderRequestTransportOverrides | undefined = mergeProviderRequestOverrides(
|
||||
...overrides,
|
||||
);
|
||||
for (const current of overrides) {
|
||||
if (current?.allowPrivateNetwork !== undefined) {
|
||||
merged = {
|
||||
|
||||
@@ -80,12 +80,14 @@ const mocks = vi.hoisted(() => {
|
||||
};
|
||||
},
|
||||
),
|
||||
readConfigFileSnapshot: vi.fn(async () => ({
|
||||
readConfigFileSnapshot: vi.fn<
|
||||
() => Promise<{ path: string; hash: string; config: OpenClawConfig }>
|
||||
>(async () => ({
|
||||
path: "/tmp/openclaw.json",
|
||||
hash: "config-hash-1",
|
||||
config: configState,
|
||||
})),
|
||||
readExecApprovalsSnapshot: vi.fn(() => ({
|
||||
readExecApprovalsSnapshot: vi.fn<() => ExecApprovalsSnapshot>(() => ({
|
||||
path: "/tmp/exec-approvals.json",
|
||||
exists: true,
|
||||
raw: "{}",
|
||||
@@ -286,10 +288,10 @@ describe("exec-policy CLI", () => {
|
||||
}),
|
||||
0,
|
||||
);
|
||||
const [{ effectivePolicy }] = mocks.defaultRuntime.writeJson.mock.calls.at(-1) as [Record<
|
||||
string,
|
||||
unknown
|
||||
>, number];
|
||||
const [{ effectivePolicy }] = mocks.defaultRuntime.writeJson.mock.calls.at(-1) as [
|
||||
Record<string, unknown>,
|
||||
number,
|
||||
];
|
||||
expect((effectivePolicy as { scopes: Record<string, unknown>[] }).scopes[0]).not.toHaveProperty(
|
||||
"allowedDecisions",
|
||||
);
|
||||
@@ -356,6 +358,7 @@ describe("exec-policy CLI", () => {
|
||||
});
|
||||
mocks.readConfigFileSnapshot.mockImplementationOnce(async () => ({
|
||||
path: "/tmp/openclaw.json\u001B[2J\nforged",
|
||||
hash: "config-hash-1",
|
||||
config: mocks.getConfig(),
|
||||
}));
|
||||
mocks.readExecApprovalsSnapshot.mockImplementationOnce(() => ({
|
||||
@@ -444,24 +447,23 @@ describe("exec-policy CLI", () => {
|
||||
it("rolls back approvals if the config write fails after approvals save", async () => {
|
||||
const originalApprovals = structuredClone(mocks.getApprovals());
|
||||
const originalRaw = JSON.stringify(originalApprovals, null, 2);
|
||||
const originalSnapshot = {
|
||||
const originalSnapshot: ExecApprovalsSnapshot = {
|
||||
path: "/tmp/exec-approvals.json",
|
||||
exists: true,
|
||||
raw: originalRaw,
|
||||
hash: "approvals-hash",
|
||||
file: originalApprovals,
|
||||
} as ExecApprovalsSnapshot as ReturnType<typeof mocks.readExecApprovalsSnapshot>;
|
||||
};
|
||||
mocks.readExecApprovalsSnapshot
|
||||
.mockImplementationOnce(() => originalSnapshot)
|
||||
.mockImplementationOnce(
|
||||
() =>
|
||||
({
|
||||
path: "/tmp/exec-approvals.json",
|
||||
exists: true,
|
||||
raw: JSON.stringify(mocks.getApprovals(), null, 2),
|
||||
hash: hashApprovalsFile(mocks.getApprovals()),
|
||||
file: structuredClone(mocks.getApprovals()),
|
||||
}) as ExecApprovalsSnapshot as ReturnType<typeof mocks.readExecApprovalsSnapshot>,
|
||||
(): ExecApprovalsSnapshot => ({
|
||||
path: "/tmp/exec-approvals.json",
|
||||
exists: true,
|
||||
raw: JSON.stringify(mocks.getApprovals(), null, 2),
|
||||
hash: hashApprovalsFile(mocks.getApprovals()),
|
||||
file: structuredClone(mocks.getApprovals()),
|
||||
}),
|
||||
);
|
||||
mocks.replaceConfigFile.mockImplementationOnce(async () => {
|
||||
throw new Error("config write failed");
|
||||
@@ -477,24 +479,23 @@ describe("exec-policy CLI", () => {
|
||||
});
|
||||
|
||||
it("removes a newly-written approvals file when config replacement fails and the original file was missing", async () => {
|
||||
const missingSnapshot = {
|
||||
const missingSnapshot: ExecApprovalsSnapshot = {
|
||||
path: "/tmp/missing-exec-approvals.json",
|
||||
exists: false,
|
||||
raw: null,
|
||||
hash: "approvals-hash",
|
||||
file: { version: 1, agents: {} },
|
||||
} as ExecApprovalsSnapshot as ReturnType<typeof mocks.readExecApprovalsSnapshot>;
|
||||
};
|
||||
mocks.readExecApprovalsSnapshot
|
||||
.mockImplementationOnce(() => missingSnapshot)
|
||||
.mockImplementationOnce(
|
||||
() =>
|
||||
({
|
||||
path: "/tmp/missing-exec-approvals.json",
|
||||
exists: true,
|
||||
raw: JSON.stringify(mocks.getApprovals(), null, 2),
|
||||
hash: hashApprovalsFile(mocks.getApprovals()),
|
||||
file: structuredClone(mocks.getApprovals()),
|
||||
}) as ExecApprovalsSnapshot as ReturnType<typeof mocks.readExecApprovalsSnapshot>,
|
||||
(): ExecApprovalsSnapshot => ({
|
||||
path: "/tmp/missing-exec-approvals.json",
|
||||
exists: true,
|
||||
raw: JSON.stringify(mocks.getApprovals(), null, 2),
|
||||
hash: hashApprovalsFile(mocks.getApprovals()),
|
||||
file: structuredClone(mocks.getApprovals()),
|
||||
}),
|
||||
);
|
||||
mocks.replaceConfigFile.mockImplementationOnce(async () => {
|
||||
throw new Error("config write failed");
|
||||
@@ -526,13 +527,13 @@ describe("exec-policy CLI", () => {
|
||||
},
|
||||
agents: {},
|
||||
};
|
||||
const concurrentSnapshot = {
|
||||
const concurrentSnapshot: ExecApprovalsSnapshot = {
|
||||
path: "/tmp/exec-approvals.json",
|
||||
exists: true,
|
||||
raw: JSON.stringify(concurrentFile, null, 2),
|
||||
hash: "concurrent-write-hash",
|
||||
file: concurrentFile,
|
||||
} as ExecApprovalsSnapshot as ReturnType<typeof mocks.readExecApprovalsSnapshot>;
|
||||
};
|
||||
let snapshotReadCount = 0;
|
||||
mocks.readExecApprovalsSnapshot.mockImplementation(() => {
|
||||
snapshotReadCount += 1;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import crypto from "node:crypto";
|
||||
import fs from "node:fs";
|
||||
import type { Command } from "commander";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { readConfigFileSnapshot, replaceConfigFile } from "../config/config.js";
|
||||
@@ -230,7 +229,9 @@ async function buildLocalExecPolicyShowPayload(): Promise<ExecPolicyShowPayload>
|
||||
approvals: approvalsSnapshot.file,
|
||||
hostPath: approvalsSnapshot.path,
|
||||
}).map(buildExecPolicyShowScope);
|
||||
const hasNodeRuntimeScope = scopes.some((scope) => scope.runtimeApprovalsSource === "node-runtime");
|
||||
const hasNodeRuntimeScope = scopes.some(
|
||||
(scope) => scope.runtimeApprovalsSource === "node-runtime",
|
||||
);
|
||||
return {
|
||||
configPath: configSnapshot.path,
|
||||
approvalsPath: approvalsSnapshot.path,
|
||||
|
||||
@@ -33,8 +33,12 @@ function createStubChild(pid = 1234) {
|
||||
child.emit("close", code, signal);
|
||||
};
|
||||
const emitExit = (code: number | null, signal: NodeJS.Signals | null = null) => {
|
||||
child.exitCode = code;
|
||||
child.signalCode = signal;
|
||||
Object.defineProperty(child, "exitCode", { value: code, configurable: true, writable: true });
|
||||
Object.defineProperty(child, "signalCode", {
|
||||
value: signal,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
});
|
||||
child.emit("exit", code, signal);
|
||||
};
|
||||
return { child, killMock, emitClose, emitExit };
|
||||
|
||||
Reference in New Issue
Block a user