mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-12 09:41:11 +00:00
Secrets: fast-path core target discovery
This commit is contained in:
@@ -445,8 +445,8 @@ describe("resolveCommandSecretRefsViaGateway", () => {
|
||||
callGateway.mockResolvedValueOnce({
|
||||
assignments: [
|
||||
{
|
||||
path: TALK_TEST_PROVIDER_API_KEY_PATH,
|
||||
pathSegments: [...TALK_TEST_PROVIDER_API_KEY_PATH_SEGMENTS],
|
||||
path: "talk.providers.missing.apiKey",
|
||||
pathSegments: ["talk", "providers", "missing", "apiKey"],
|
||||
value: "sk-live",
|
||||
},
|
||||
],
|
||||
|
||||
@@ -11,6 +11,7 @@ import { resolveSession } from "../agents/command/session.js";
|
||||
import { loadModelCatalog } from "../agents/model-catalog.js";
|
||||
import * as modelSelectionModule from "../agents/model-selection.js";
|
||||
import { runEmbeddedPiAgent } from "../agents/pi-embedded.js";
|
||||
import * as commandConfigResolutionModule from "../cli/command-config-resolution.js";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import * as configModule from "../config/config.js";
|
||||
import { clearSessionStoreCacheForTest } from "../config/sessions.js";
|
||||
@@ -100,43 +101,6 @@ async function withTempHome<T>(fn: (home: string) => Promise<T>): Promise<T> {
|
||||
return withTempHomeBase(fn, { prefix: "openclaw-agent-" });
|
||||
}
|
||||
|
||||
async function loadFreshAgentCommandModulesForTest() {
|
||||
vi.resetModules();
|
||||
const runEmbeddedPiAgentMock = vi.fn();
|
||||
const loadModelCatalogMock = vi.fn();
|
||||
const isCliProviderMock = vi.fn(() => false);
|
||||
vi.doMock("../agents/pi-embedded.js", () => ({
|
||||
abortEmbeddedPiRun: vi.fn().mockReturnValue(false),
|
||||
runEmbeddedPiAgent: runEmbeddedPiAgentMock,
|
||||
resolveEmbeddedSessionLane: (key: string) => `session:${key.trim() || "main"}`,
|
||||
}));
|
||||
vi.doMock("../agents/model-catalog.js", () => ({
|
||||
loadModelCatalog: loadModelCatalogMock,
|
||||
}));
|
||||
vi.doMock("../agents/model-selection.js", async () => {
|
||||
const actual = await vi.importActual<typeof import("../agents/model-selection.js")>(
|
||||
"../agents/model-selection.js",
|
||||
);
|
||||
return {
|
||||
...actual,
|
||||
isCliProvider: isCliProviderMock,
|
||||
};
|
||||
});
|
||||
const [agentModule, configModuleFresh, commandSecretGatewayModuleFresh] = await Promise.all([
|
||||
import("./agent.js"),
|
||||
import("../config/config.js"),
|
||||
import("../cli/command-secret-gateway.js"),
|
||||
]);
|
||||
return {
|
||||
agentCommand: agentModule.agentCommand,
|
||||
configModuleFresh,
|
||||
commandSecretGatewayModuleFresh,
|
||||
runEmbeddedPiAgentMock,
|
||||
loadModelCatalogMock,
|
||||
isCliProviderMock,
|
||||
};
|
||||
}
|
||||
|
||||
function mockConfig(
|
||||
home: string,
|
||||
storePath: string,
|
||||
@@ -346,26 +310,7 @@ beforeEach(() => {
|
||||
describe("agentCommand", () => {
|
||||
it("sets runtime snapshots from source config before embedded agent run", async () => {
|
||||
await withTempHome(async (home) => {
|
||||
const {
|
||||
agentCommand: freshAgentCommand,
|
||||
configModuleFresh,
|
||||
commandSecretGatewayModuleFresh,
|
||||
runEmbeddedPiAgentMock,
|
||||
loadModelCatalogMock,
|
||||
isCliProviderMock,
|
||||
} = await loadFreshAgentCommandModulesForTest();
|
||||
const freshConfigSpy = vi.spyOn(configModuleFresh, "loadConfig");
|
||||
const freshReadConfigFileSnapshotForWriteSpy = vi.spyOn(
|
||||
configModuleFresh,
|
||||
"readConfigFileSnapshotForWrite",
|
||||
);
|
||||
const freshSetRuntimeConfigSnapshotSpy = vi.spyOn(
|
||||
configModuleFresh,
|
||||
"setRuntimeConfigSnapshot",
|
||||
);
|
||||
runEmbeddedPiAgentMock.mockResolvedValue(createDefaultAgentResult());
|
||||
loadModelCatalogMock.mockResolvedValue([]);
|
||||
isCliProviderMock.mockImplementation(() => false);
|
||||
const setRuntimeConfigSnapshotSpy = vi.spyOn(configModule, "setRuntimeConfigSnapshot");
|
||||
|
||||
const store = path.join(home, "sessions.json");
|
||||
const loadedConfig = {
|
||||
@@ -412,29 +357,29 @@ describe("agentCommand", () => {
|
||||
},
|
||||
} as unknown as OpenClawConfig;
|
||||
|
||||
freshConfigSpy.mockReturnValue(loadedConfig);
|
||||
freshReadConfigFileSnapshotForWriteSpy.mockResolvedValue({
|
||||
configSpy.mockReturnValue(loadedConfig);
|
||||
readConfigFileSnapshotForWriteSpy.mockResolvedValue({
|
||||
snapshot: { valid: true, resolved: sourceConfig },
|
||||
writeOptions: {},
|
||||
} as Awaited<ReturnType<typeof configModule.readConfigFileSnapshotForWrite>>);
|
||||
const resolveSecretsSpy = vi
|
||||
.spyOn(commandSecretGatewayModuleFresh, "resolveCommandSecretRefsViaGateway")
|
||||
const resolveConfigWithSecretsSpy = vi
|
||||
.spyOn(commandConfigResolutionModule, "resolveCommandConfigWithSecrets")
|
||||
.mockResolvedValueOnce({
|
||||
resolvedConfig,
|
||||
effectiveConfig: resolvedConfig,
|
||||
diagnostics: [],
|
||||
targetStatesByPath: {},
|
||||
hadUnresolvedTargets: false,
|
||||
});
|
||||
|
||||
await freshAgentCommand({ message: "hello", to: "+1555" }, runtime);
|
||||
await agentCommand({ message: "hello", to: "+1555" }, runtime);
|
||||
|
||||
expect(resolveSecretsSpy).toHaveBeenCalledWith({
|
||||
expect(resolveConfigWithSecretsSpy).toHaveBeenCalledWith({
|
||||
config: loadedConfig,
|
||||
commandName: "agent",
|
||||
targetIds: expect.any(Set),
|
||||
runtime,
|
||||
});
|
||||
expect(freshSetRuntimeConfigSnapshotSpy).toHaveBeenCalledWith(resolvedConfig, sourceConfig);
|
||||
expect(runEmbeddedPiAgentMock.mock.calls.at(-1)?.[0]?.config).toBe(resolvedConfig);
|
||||
expect(setRuntimeConfigSnapshotSpy).toHaveBeenCalledWith(resolvedConfig, sourceConfig);
|
||||
expect(vi.mocked(runEmbeddedPiAgent).mock.calls.at(-1)?.[0]?.config).toBe(resolvedConfig);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1101,7 +1046,7 @@ describe("agentCommand", () => {
|
||||
await expectPersistedSessionFile({
|
||||
seedKey: "agent:main:telegram:group:123:topic:456",
|
||||
sessionId: "sess-topic",
|
||||
expectedPathFragment: "sess-topic-topic-456.jsonl",
|
||||
expectedPathFragment: `${path.sep}agents${path.sep}main${path.sep}sessions${path.sep}sess-topic.jsonl`,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -466,6 +466,10 @@ const CORE_SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
|
||||
let cachedSecretTargetRegistry: SecretTargetRegistryEntry[] | null = null;
|
||||
|
||||
export function getCoreSecretTargetRegistry(): SecretTargetRegistryEntry[] {
|
||||
return CORE_SECRET_TARGET_REGISTRY;
|
||||
}
|
||||
|
||||
export function getSecretTargetRegistry(): SecretTargetRegistryEntry[] {
|
||||
if (cachedSecretTargetRegistry) {
|
||||
return cachedSecretTargetRegistry;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { getPath } from "./path-utils.js";
|
||||
import { getSecretTargetRegistry } from "./target-registry-data.js";
|
||||
import { getCoreSecretTargetRegistry, getSecretTargetRegistry } from "./target-registry-data.js";
|
||||
import {
|
||||
compileTargetRegistryEntry,
|
||||
expandPathTokens,
|
||||
@@ -24,6 +24,12 @@ let compiledSecretTargetRegistryState: {
|
||||
targetsByType: Map<string, CompiledTargetRegistryEntry[]>;
|
||||
} | null = null;
|
||||
|
||||
let compiledCoreOpenClawTargetState: {
|
||||
knownTargetIds: Set<string>;
|
||||
openClawCompiledSecretTargets: CompiledTargetRegistryEntry[];
|
||||
openClawTargetsById: Map<string, CompiledTargetRegistryEntry[]>;
|
||||
} | null = null;
|
||||
|
||||
function buildTargetTypeIndex(
|
||||
compiledSecretTargetRegistry: CompiledTargetRegistryEntry[],
|
||||
): Map<string, CompiledTargetRegistryEntry[]> {
|
||||
@@ -83,6 +89,21 @@ function getCompiledSecretTargetRegistryState() {
|
||||
return compiledSecretTargetRegistryState;
|
||||
}
|
||||
|
||||
function getCompiledCoreOpenClawTargetState() {
|
||||
if (compiledCoreOpenClawTargetState) {
|
||||
return compiledCoreOpenClawTargetState;
|
||||
}
|
||||
const openClawCompiledSecretTargets = getCoreSecretTargetRegistry()
|
||||
.filter((entry) => entry.configFile === "openclaw.json")
|
||||
.map(compileTargetRegistryEntry);
|
||||
compiledCoreOpenClawTargetState = {
|
||||
knownTargetIds: new Set(openClawCompiledSecretTargets.map((entry) => entry.id)),
|
||||
openClawCompiledSecretTargets,
|
||||
openClawTargetsById: buildConfigTargetIdIndex(openClawCompiledSecretTargets),
|
||||
};
|
||||
return compiledCoreOpenClawTargetState;
|
||||
}
|
||||
|
||||
function normalizeAllowedTargetIds(targetIds?: Iterable<string>): Set<string> | null {
|
||||
if (targetIds === undefined) {
|
||||
return null;
|
||||
@@ -281,7 +302,13 @@ export function discoverConfigSecretTargetsByIds(
|
||||
targetIds?: Iterable<string>,
|
||||
): DiscoveredConfigSecretTarget[] {
|
||||
const allowedTargetIds = normalizeAllowedTargetIds(targetIds);
|
||||
const registryState = getCompiledSecretTargetRegistryState();
|
||||
const registryState =
|
||||
allowedTargetIds !== null &&
|
||||
Array.from(allowedTargetIds).every((targetId) =>
|
||||
getCompiledCoreOpenClawTargetState().knownTargetIds.has(targetId),
|
||||
)
|
||||
? getCompiledCoreOpenClawTargetState()
|
||||
: getCompiledSecretTargetRegistryState();
|
||||
const discoveryEntries = resolveDiscoveryEntries({
|
||||
allowedTargetIds,
|
||||
defaultEntries: registryState.openClawCompiledSecretTargets,
|
||||
|
||||
Reference in New Issue
Block a user