fix(native): measure resumed run usage from the prior run's total (#19161)

This commit is contained in:
Nicky Leach authored and GitHub committed 2026-11-04 18:55:14 -08:00
1 parent 6452e964a3
commit 737db73275
8 files changed
+176 -5

No files matched your search

@@ -10983,6 +10983,7 @@ describe("native warm session supervision", () => {
terminal: null,
terminalTurns: [],
pendingRuntimeRequests: [],
codexUsageBaseline: { baseline: { inputTokens: 40, outputTokens: 4 }, latest: { inputTokens: 100, outputTokens: 10 } },
};
const result = {
result: { summary: "completed" },
@@ -11011,6 +11012,7 @@ describe("native warm session supervision", () => {
driverSessionId: checkpoint.driverSessionId,
providerSessionId: checkpoint.providerSessionId,
activeTurnId: checkpoint.activeTurnId,
codexUsageBaseline: checkpoint.codexUsageBaseline,
}),
);
return result;
@@ -11042,6 +11044,102 @@ describe("native warm session supervision", () => {
}
});
it.each([
{ name: "every report accounted", accounted: { inputTokens: 100, outputTokens: 10 }, latest: { inputTokens: 100, outputTokens: 10 } },
{ name: "late usage not yet charged", accounted: { inputTokens: 100, outputTokens: 10 }, latest: { inputTokens: 130, outputTokens: 12 } },
{ name: "no accounted total", accounted: undefined, latest: { inputTokens: 100, outputTokens: 10 } },
])("starts a new run's usage from the prior run's total when a warm checkpoint resumes: $name", async ({ accounted, latest }) => {
const stateBase = await mkdtemp(join(tmpdir(), "paperclip-warm-next-run-usage-"));
const previousPaperclipHome = process.env.PAPERCLIP_HOME;
process.env.PAPERCLIP_HOME = stateBase;
const firstRun = {
...execution,
binding: {
...execution.binding,
runId: "run-warm-next-run-usage-first",
executionWorkspaceId: "workspace-warm-next-run-usage",
},
session: {
...execution.session,
normalizedSessionId: "session-warm-next-run-usage",
lifecyclePolicy: { mode: "warm" as const, idleTimeoutMs: 20 },
},
} as NativeExecutionInputV1;
const secondRun = {
...firstRun,
binding: { ...firstRun.binding, runId: "run-warm-next-run-usage-second" },
} as NativeExecutionInputV1;
const checkpoint = {
identity: {
runId: firstRun.binding.runId,
sessionId: firstRun.session.normalizedSessionId,
companyId: firstRun.binding.companyId,
issueId: firstRun.binding.issueId,
agentId: firstRun.binding.agentId,
},
sessionId: firstRun.session.normalizedSessionId,
driverSessionId: "driver-warm-next-run-usage",
providerSessionId: "provider-warm-next-run-usage",
activeTurnId: null,
semanticResult: null,
terminal: null,
terminalTurns: [],
pendingRuntimeRequests: [],
codexUsageBaseline: { baseline: {}, latest, ...(accounted ? { accounted } : {}) },
};
const result = {
result: { summary: "completed" },
terminal: { runTerminalState: "succeeded" },
turnId: "provider-turn-warm-next-run-usage",
normalizedSessionId: firstRun.session.normalizedSessionId,
providerSessionId: checkpoint.providerSessionId,
driverKind: "test",
driverVersion: "1",
nativeEventCount: 1,
highestContiguousSourceSeq: 1,
usage: null,
};
const firstClose = vi.fn(async () => undefined);
let resumedBaseline: unknown;
state.execute
.mockReset()
.mockImplementationOnce(async (options) => {
await options.onCheckpoint?.(checkpoint);
options.onSession?.({ close: firstClose });
return result;
})
.mockImplementationOnce(async (options) => {
resumedBaseline = options.persistedSession?.codexUsageBaseline;
return result;
});
try {
await executePaperclipNativeSession({
db: leaseDb(firstRun),
execution: firstRun,
runnerInstanceId: "runner-warm-next-run-usage",
});
await vi.waitFor(() => expect(firstClose).toHaveBeenCalled(), { timeout: 500 });
await executePaperclipNativeSession({
db: leaseDb(secondRun),
execution: secondRun,
runnerInstanceId: "runner-warm-next-run-usage",
});
expect(resumedBaseline).toEqual({
baseline: accounted ?? latest,
latest,
...(accounted ? { accounted } : {}),
});
} finally {
if (previousPaperclipHome === undefined) {
delete process.env.PAPERCLIP_HOME;
} else {
process.env.PAPERCLIP_HOME = previousPaperclipHome;
}
await rm(stateBase, { recursive: true, force: true });
}
});
it("reuses one session across distinct governed runs and closes it after idle expiry", async () => {
let releaseClose!: () => void;
const closeBarrier = new Promise<void>(resolve => { releaseClose = resolve; });
@@ -57,6 +57,7 @@ import { isCloudManagedInstance } from "../cloud-instance.js";
import { dotRunnerBroker } from "../dot-runner-broker.js";
import { CURSOR_DISTRIBUTION_PINS, KIMI_DISTRIBUTION_CLOSURE_SHA256, QUALIFIED_ACPX_PROFILES, QUALIFIED_ACPX_VERSION } from "../../vendor/paperclip-runner/index.js";
import { isProviderMode } from "../../vendor/paperclip-runner/index.js";
import { codexUsageBaselineForNextRun } from "../../vendor/paperclip-runner/index.js";
import { PROVIDER_PACK_COMPATIBILITY, bundledRemoteProviderPackManifestPath, bundledRemoteRunnerBinary, runnerBinaryTarget } from "../../vendor/paperclip-runner/index.js";
import { nativeRetryCancellationEligible, rethrowNativeCancellationLockConflict, assertCancellationRequest, cancellationIntentId as callerCancellationIntentId, cancellationRequestId } from "./native-cancellation-request.js";
import { readNativePlanWait } from "./native-plan-wait.js";
@@ -7035,6 +7036,9 @@ function loadWarmNativeCheckpoint(
terminalTurns: [],
pendingRuntimeRequests: [],
governedWait: undefined,
...(envelope.snapshot.codexUsageBaseline
? { codexUsageBaseline: codexUsageBaselineForNextRun(envelope.snapshot.codexUsageBaseline) }
: {}),
};
if (path !== scopedPath || envelope.configDigest !== configDigest) {
// Upgrade the validated checkpoint atomically. When moving from a legacy
+1
View File
@@ -164,6 +164,7 @@ export const parseHarnessRuntimeRequestResolution =
export const parseNativeExecutionInput = runner.parseNativeExecutionInput;
export const buildNativeModelEnvelope = runner.buildNativeModelEnvelope;
export const isProviderMode = runner.isProviderMode;
export const codexUsageBaselineForNextRun = runner.codexUsageBaselineForNextRun;
export const parseNativeRuntimeContext = runner.parseNativeRuntimeContext;
export const parsePaperclipQuestionSet = runner.parsePaperclipQuestionSet;
export const parsePaperclipQuestionResponse =