Fix OpenCode usage regression and update workspace tests

Re-add usage stamping on turn_completed events for OpenCode agents —
the extractAndResetUsage callsite was removed during context window
meter work, causing token counts and cost to be lost after each turn.

Update workspace tests to account for the new async reconciliation
that fires after workspace update fanout.
This commit is contained in:
Mohamed Boudra
2026-04-07 20:02:48 +07:00
parent 1279f1d556
commit 8088c39fd6
3 changed files with 23 additions and 4 deletions
@@ -2041,6 +2041,17 @@ class OpenCodeAgentSession implements AgentSession {
if (translatedEvent.type === "permission_requested") {
this.pendingPermissions.set(translatedEvent.request.id, translatedEvent.request);
}
if (translatedEvent.type === "turn_completed") {
if (hasNormalizedOpenCodeUsage(this.accumulatedUsage)) {
translatedEvent.usage = this.accumulatedUsage;
}
const contextWindowMaxTokens =
this.resolveSelectedModelContextWindowMaxTokens();
this.accumulatedUsage =
contextWindowMaxTokens !== undefined
? { contextWindowMaxTokens }
: {};
}
}
return translated;
@@ -255,7 +255,8 @@ describe("workspace git watch targets", () => {
diffStat: { additions: 1, deletions: 0 },
};
sessionAny.listWorkspaceDescriptorsSnapshot = async () => [descriptor];
sessionAny.buildWorkspaceDescriptorMap = async () =>
new Map([[descriptor.id, descriptor]]);
await sessionAny.ensureWorkspaceRegistered("/tmp/repo");
sessionAny.primeWorkspaceGitWatchFingerprints([descriptor]);
@@ -477,7 +478,8 @@ describe("workspace git watch targets", () => {
diffStat: { additions: 1, deletions: 0 },
};
sessionAny.listWorkspaceDescriptorsSnapshot = async () => [descriptor];
sessionAny.buildWorkspaceDescriptorMap = async () =>
new Map([[descriptor.id, descriptor]]);
await sessionAny.ensureWorkspaceRegistered("/tmp/repo");
sessionAny.primeWorkspaceGitWatchFingerprints([descriptor]);
@@ -1127,15 +1127,21 @@ describe("workspace aggregation", () => {
};
await session.emitWorkspaceUpdateForCwd("/tmp/repo/worktree");
await new Promise((resolve) => setTimeout(resolve, 0));
const workspaceUpdates = emitted.filter(
(message) => message.type === "workspace_update",
) as any[];
expect(workspaceUpdates).toHaveLength(2);
expect(workspaceUpdates.map((entry) => entry.payload.kind)).toEqual(["upsert", "upsert"]);
expect(workspaceUpdates).toHaveLength(3);
expect(workspaceUpdates.map((entry) => entry.payload.kind)).toEqual([
"upsert",
"upsert",
"upsert",
]);
expect(workspaceUpdates.map((entry) => entry.payload.workspace.id).sort()).toEqual([
"/tmp/repo",
"/tmp/repo/worktree",
"/tmp/repo/worktree",
]);
});