Files
openclaw/extensions/codex/src/command-rpc.test.ts
T
Peter Steinberger 8885be4756 fix(codex): refresh session meters after /codex compact (#123640)
* fix(codex): route compact through session pipeline

Route /codex compact through host-owned manual compaction so native completion and token snapshots update session meters, and report the terminal outcome to the user.

* test(codex): cover unavailable compact outcome

* fix(plugins): fence command compaction capability

Bind compactCurrent to one command invocation and captured session generation so retained or stale callbacks fail closed without running compaction.

* fix(plugins): lazy-load command session revalidation

Keep compaction session freshness checks at the auto-reply owner without pulling the session accessor into generic plugin command module initialization.

* fix(plugins): keep session revalidation lazy

Avoid loading the session accessor through generic plugin command initialization while preserving pre-compaction session-generation checks.

* fix(compaction): fence session lifecycle admission

Revalidate the exact session id and lifecycle revision immediately before native compaction and again before accounting so resets and rebinds fail closed across awaited work.

* fix(commands): fence plugin compaction authority

* fix(compaction): require accounting commit

* test(compaction): keep regression under lint cap

* fix(codex): preserve compact admission

* fix(codex): preserve compaction target identity

* fix(compaction): bind admitted target

* fix(compaction): fence accounting commit
2026-08-14 09:47:43 -07:00

98 lines
2.8 KiB
TypeScript

// Codex tests cover command rpc plugin behavior.
import { beforeEach, describe, expect, it, vi } from "vitest";
import { codexControlRequest } from "./command-rpc.js";
const requestCodexAppServerJsonMock = vi.hoisted(() => vi.fn());
vi.mock("./app-server/request.js", () => ({
requestCodexAppServerJson: requestCodexAppServerJsonMock,
}));
describe("Codex command RPC helpers", () => {
beforeEach(() => {
requestCodexAppServerJsonMock.mockReset();
});
it("uses an explicit control connection instead of ordinary harness start options", async () => {
requestCodexAppServerJsonMock.mockResolvedValue({ thread: { id: "thread-1" } });
const startOptions = {
transport: "stdio" as const,
homeScope: "user" as const,
command: "codex",
args: ["app-server", "--listen", "stdio://"],
headers: {},
};
await codexControlRequest(
{},
"thread/read",
{ threadId: "thread-1", includeTurns: false },
{ startOptions },
);
expect(requestCodexAppServerJsonMock).toHaveBeenCalledWith(
expect.objectContaining({ startOptions }),
);
});
it("keeps omitted Unix scope on the explicit user-scoped supervision connection", async () => {
requestCodexAppServerJsonMock.mockResolvedValue({ data: [] });
const pluginConfig = {
appServer: {
transport: "unix" as const,
url: "unix:///tmp/codex.sock",
requestTimeoutMs: 321,
},
};
const startOptions = {
transport: "unix" as const,
homeScope: "user" as const,
command: "codex",
args: ["app-server", "--listen", "stdio://"],
url: "unix:///tmp/codex.sock",
headers: {},
};
await codexControlRequest(
pluginConfig,
"thread/list",
{ archived: false },
{
startOptions,
authProfileId: null,
},
);
expect(requestCodexAppServerJsonMock).toHaveBeenCalledWith(
expect.objectContaining({ startOptions, timeoutMs: 321, authProfileId: null }),
);
});
it("forwards explicit native auth for supervised control connections", async () => {
requestCodexAppServerJsonMock.mockResolvedValue({});
await codexControlRequest(
{},
"thread/list",
{ archived: false },
{
authProfileId: null,
},
);
expect(requestCodexAppServerJsonMock).toHaveBeenCalledWith(
expect.objectContaining({ authProfileId: null }),
);
});
it("forwards an explicit per-request timeout budget", async () => {
requestCodexAppServerJsonMock.mockResolvedValue({ data: [] });
await codexControlRequest({}, "thread/list", { archived: false }, { timeoutMs: 321 });
expect(requestCodexAppServerJsonMock).toHaveBeenCalledWith(
expect.objectContaining({ timeoutMs: 321 }),
);
});
});