Reapply "refactor: move runtime state to SQLite"

This reverts commit 694ca50e97.
This commit is contained in:
Peter Steinberger
2026-05-13 13:34:30 +01:00
parent 05db911775
commit c6ee68b751
3003 changed files with 128551 additions and 130603 deletions

View File

@@ -4,6 +4,7 @@ import path from "node:path";
import {
clearRuntimeAuthProfileStoreSnapshots,
ensureAuthProfileStore,
saveAuthProfileStore,
} from "openclaw/plugin-sdk/agent-runtime";
import type {
OpenClawConfig,
@@ -14,7 +15,7 @@ import type {
} from "openclaw/plugin-sdk/plugin-entry";
import { createTestPluginApi } from "openclaw/plugin-sdk/plugin-test-api";
import { afterAll, afterEach, describe, expect, it, vi } from "vitest";
import { setGitHubCopilotDeviceFlowFetchGuardForTesting } from "./login.js";
import { _setGitHubCopilotDeviceFlowFetchGuardForTesting } from "./login.js";
const mocks = vi.hoisted(() => ({
githubCopilotLoginCommand: vi.fn(),
@@ -64,7 +65,7 @@ type GithubCopilotTestModelCatalogProvider = {
afterEach(async () => {
vi.clearAllMocks();
vi.unstubAllGlobals();
setGitHubCopilotDeviceFlowFetchGuardForTesting(null);
_setGitHubCopilotDeviceFlowFetchGuardForTesting(null);
clearRuntimeAuthProfileStoreSnapshots();
await Promise.all(tempDirs.splice(0).map((dir) => fs.rm(dir, { recursive: true, force: true })));
});
@@ -80,7 +81,23 @@ async function createAgentDir() {
return dir;
}
function registerProviderForTest() {
function seedGithubCopilotTokenProfile(agentDir: string, token = "existing-token") {
saveAuthProfileStore(
{
version: 1,
profiles: {
"github-copilot:github": {
type: "token",
provider: "github-copilot",
token,
},
},
},
agentDir,
);
}
function _registerProvider() {
return registerProviderWithPluginConfig({});
}
@@ -259,19 +276,7 @@ describe("github-copilot plugin", () => {
const provider = registerProviderWithPluginConfig({});
const method = provider.auth[0];
const agentDir = await createAgentDir();
await fs.writeFile(
path.join(agentDir, "auth-profiles.json"),
JSON.stringify({
version: 1,
profiles: {
"github-copilot:github": {
type: "token",
provider: "github-copilot",
token: "existing-token",
},
},
}),
);
seedGithubCopilotTokenProfile(agentDir);
const prompter = {
confirm: vi.fn(async () => false),
note: vi.fn(),
@@ -316,20 +321,8 @@ describe("github-copilot plugin", () => {
const provider = registerProviderWithPluginConfig({});
const method = provider.auth[0];
const agentDir = await createAgentDir();
await fs.writeFile(
path.join(agentDir, "auth-profiles.json"),
JSON.stringify({
version: 1,
profiles: {
"github-copilot:github": {
type: "token",
provider: "github-copilot",
token: "existing-token",
},
},
}),
);
const fetchMock = vi.fn(async (input: unknown, _init?: RequestInit) => {
seedGithubCopilotTokenProfile(agentDir);
const fetchMock = vi.fn(async (input: unknown) => {
const target =
typeof input === "string"
? input
@@ -359,7 +352,7 @@ describe("github-copilot plugin", () => {
throw new Error(`unexpected fetch in github-copilot refresh test: ${target}`);
});
vi.stubGlobal("fetch", fetchMock);
setGitHubCopilotDeviceFlowFetchGuardForTesting(async (params) => ({
_setGitHubCopilotDeviceFlowFetchGuardForTesting(async (params) => ({
response: await fetchMock(params.url, params.init),
finalUrl: params.url,
release: async () => {},
@@ -596,19 +589,7 @@ describe("github-copilot plugin", () => {
const method = provider.auth[0];
const agentDir = await createAgentDir();
const runtime = { error: vi.fn(), exit: vi.fn() };
await fs.writeFile(
path.join(agentDir, "auth-profiles.json"),
JSON.stringify({
version: 1,
profiles: {
"github-copilot:github": {
type: "token",
provider: "github-copilot",
token: "existing-token",
},
},
}),
);
seedGithubCopilotTokenProfile(agentDir);
const result = await method.runNonInteractive({
authChoice: "github-copilot",

View File

@@ -1,5 +1,8 @@
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { createProviderUsageFetch, makeResponse } from "openclaw/plugin-sdk/test-env";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { describe, expect, it, vi } from "vitest";
import { buildCopilotModelDefinition, getDefaultCopilotModelIds } from "./models-defaults.js";
import { deriveCopilotApiBaseUrlFromToken, resolveCopilotApiToken } from "./token.js";
import { fetchCopilotUsage } from "./usage.js";
@@ -13,16 +16,6 @@ vi.mock("openclaw/plugin-sdk/provider-model-shared", () => ({
}),
}));
const jsonStoreMocks = vi.hoisted(() => ({
loadJsonFile: vi.fn(),
saveJsonFile: vi.fn(),
}));
vi.mock("openclaw/plugin-sdk/json-store", () => ({
loadJsonFile: jsonStoreMocks.loadJsonFile,
saveJsonFile: jsonStoreMocks.saveJsonFile,
}));
vi.mock("openclaw/plugin-sdk/state-paths", () => ({
resolveStateDir: () => "/tmp/openclaw-state",
}));
@@ -324,12 +317,12 @@ describe("fetchCopilotUsage", () => {
});
describe("github-copilot token", () => {
const cachePath = "/tmp/openclaw-state/credentials/github-copilot.token.json";
beforeEach(() => {
jsonStoreMocks.loadJsonFile.mockClear();
jsonStoreMocks.saveJsonFile.mockClear();
});
function makeCopilotEnv(): NodeJS.ProcessEnv {
return {
...process.env,
OPENCLAW_STATE_DIR: fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-copilot-token-")),
};
}
it("derives baseUrl from token", () => {
expect(deriveCopilotApiBaseUrlFromToken("token;proxy-ep=proxy.example.com;")).toBe(
@@ -341,32 +334,35 @@ describe("github-copilot token", () => {
});
it("uses cache when token is still valid", async () => {
const now = Date.now();
jsonStoreMocks.loadJsonFile.mockReturnValue({
token: "cached;proxy-ep=proxy.example.com;",
expiresAt: now + 60 * 60 * 1000,
updatedAt: now,
integrationId: "vscode-chat",
const env = makeCopilotEnv();
const fetchImpl = vi.fn().mockResolvedValue({
ok: true,
status: 200,
json: async () => ({
token: "cached;proxy-ep=proxy.example.com;",
expires_at: Math.floor(Date.now() / 1000) + 3600,
}),
});
const fetchImpl = vi.fn();
const res = await resolveCopilotApiToken({
const first = await resolveCopilotApiToken({
githubToken: "gh",
cachePath,
loadJsonFileImpl: jsonStoreMocks.loadJsonFile,
saveJsonFileImpl: jsonStoreMocks.saveJsonFile,
env,
fetchImpl: fetchImpl as unknown as typeof fetch,
});
const second = await resolveCopilotApiToken({
githubToken: "gh",
env,
fetchImpl: fetchImpl as unknown as typeof fetch,
});
expect(res.token).toBe("cached;proxy-ep=proxy.example.com;");
expect(res.baseUrl).toBe("https://api.example.com");
expect(res.source).toContain("cache:");
expect(fetchImpl).not.toHaveBeenCalled();
expect(fetchImpl).toHaveBeenCalledTimes(1);
expect(first.source).toContain("fetched:");
expect(second.token).toBe("cached;proxy-ep=proxy.example.com;");
expect(second.baseUrl).toBe("https://api.example.com");
expect(second.source).toContain("cache:sqlite:");
});
it("fetches and stores token when cache is missing", async () => {
jsonStoreMocks.loadJsonFile.mockReturnValue(undefined);
const env = makeCopilotEnv();
const fetchImpl = vi.fn().mockResolvedValue({
ok: true,
status: 200,
@@ -378,19 +374,13 @@ describe("github-copilot token", () => {
const res = await resolveCopilotApiToken({
githubToken: "gh",
cachePath,
loadJsonFileImpl: jsonStoreMocks.loadJsonFile,
saveJsonFileImpl: jsonStoreMocks.saveJsonFile,
env,
fetchImpl: fetchImpl as unknown as typeof fetch,
});
expect(res.token).toBe("fresh;proxy-ep=https://proxy.contoso.test;");
expect(res.baseUrl).toBe("https://api.contoso.test");
const [, calledInit] = fetchImpl.mock.calls[0] ?? [];
expect(((calledInit as RequestInit).headers as Record<string, string>)["Accept-Encoding"]).toBe(
"identity",
);
expect(jsonStoreMocks.saveJsonFile).toHaveBeenCalledTimes(1);
expect(fetchImpl).toHaveBeenCalledTimes(1);
});
});
@@ -515,9 +505,6 @@ describe("fetchCopilotModelCatalog", () => {
expect(((calledInit as RequestInit).headers as Record<string, string>).Authorization).toBe(
"Bearer tid=test",
);
expect(((calledInit as RequestInit).headers as Record<string, string>)["Accept-Encoding"]).toBe(
"identity",
);
expect(out.map((m) => m.id)).toEqual([
"gpt-5.5",

View File

@@ -1,6 +1,6 @@
import type { StreamFn } from "openclaw/plugin-sdk/agent-core";
import type { Context } from "openclaw/plugin-sdk/llm";
import type { ProviderWrapStreamFnContext } from "openclaw/plugin-sdk/plugin-entry";
import type { Context } from "openclaw/plugin-sdk/provider-ai";
import { buildCopilotIdeHeaders, COPILOT_INTEGRATION_ID } from "openclaw/plugin-sdk/provider-auth";
import {
applyAnthropicEphemeralCacheControlMarkers,