Skip to content

Commit 6235bc5

Browse files
fix: key the workspace-use counters by turn
Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_011AhtJPr3nmT1Po92ZQk4VE
1 parent bd1190b commit 6235bc5

3 files changed

Lines changed: 26 additions & 13 deletions

File tree

‎packages/opencode/src/altimate/telemetry/index.ts‎

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2252,7 +2252,10 @@ export namespace Telemetry {
22522252
// whether any workspace context was in play. Keyed by session so a serve process with several
22532253
// sessions keeps them apart; cleared when the session ends.
22542254
export type WorkspaceUse = { skills: number; memory: number; integrations: number }
2255+
/** Keyed by session and turn, so a cancelled turn unwinding late and its replacement never share
2256+
* counts; a site that carries no turn counts toward the session's current one. */
22552257
const workspaceUse = new Map<string, WorkspaceUse>()
2258+
const useKey = (sessionId: string, turn?: number) => `${sessionId}#${turn ?? sessionTurns.get(sessionId) ?? 0}`
22562259
/** `add` accumulates; `max` records the largest value seen in the turn (memory is injected on every
22572260
* step of a turn, so a sum would multiply the blocks by the step count). */
22582261
export function noteWorkspaceUse(
@@ -2266,15 +2269,17 @@ export namespace Telemetry {
22662269
) {
22672270
if (!sessionId || n <= 0) return
22682271
if (turn !== undefined && sessionTurns.get(sessionId) !== turn) return
2269-
const use = workspaceUse.get(sessionId) ?? { skills: 0, memory: 0, integrations: 0 }
2272+
const key = useKey(sessionId, turn)
2273+
const use = workspaceUse.get(key) ?? { skills: 0, memory: 0, integrations: 0 }
22702274
use[kind] = mode === "max" ? Math.max(use[kind], n) : use[kind] + n
2271-
workspaceUse.set(sessionId, use)
2275+
workspaceUse.set(key, use)
22722276
}
2273-
export function workspaceUseOf(sessionId: string): WorkspaceUse {
2274-
return { skills: 0, memory: 0, integrations: 0, ...workspaceUse.get(sessionId) }
2277+
/** The counts of a turn (the session's current one when no turn is given). */
2278+
export function workspaceUseOf(sessionId: string, turn?: number): WorkspaceUse {
2279+
return { skills: 0, memory: 0, integrations: 0, ...workspaceUse.get(useKey(sessionId, turn)) }
22752280
}
2276-
export function clearWorkspaceUse(sessionId: string) {
2277-
workspaceUse.delete(sessionId)
2281+
export function clearWorkspaceUse(sessionId: string, turn?: number) {
2282+
workspaceUse.delete(useKey(sessionId, turn))
22782283
}
22792284
/** The workspace a session's turn bound, or undefined when unbound or unknown. */
22802285
export function workspaceOf(sessionId: string): number | undefined {
@@ -2284,8 +2289,12 @@ export namespace Telemetry {
22842289
* its workspace entry goes. With `turn` (from `setContext`), a turn that is no longer the session's
22852290
* current one ends nothing: the replacement's entries are the replacement's. */
22862291
export function endSession(sessionId: string, turn?: number) {
2287-
if (turn !== undefined && sessionTurns.get(sessionId) !== turn) return
2288-
workspaceUse.delete(sessionId)
2292+
if (turn !== undefined && sessionTurns.get(sessionId) !== turn) {
2293+
// A turn that was replaced ends only its own counts; the replacement's entries stay.
2294+
workspaceUse.delete(useKey(sessionId, turn))
2295+
return
2296+
}
2297+
workspaceUse.delete(useKey(sessionId, turn))
22892298
sessionWorkspaces.delete(sessionId)
22902299
sessionTurns.delete(sessionId)
22912300
}

‎packages/opencode/src/session/prompt.ts‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,8 @@ import { readLocalBinding } from "@/altimate/workspace/state"
113113
/** The session's workspace use, as session_end fields. Read only: the row is tracked first, then the
114114
* turn ends its telemetry entries (`Telemetry.endSession`), so the row itself still carries the
115115
* workspace. */
116-
function workspaceUseFields(sessionID: string) {
117-
const use = Telemetry.workspaceUseOf(sessionID)
116+
function workspaceUseFields(sessionID: string, turn: number) {
117+
const use = Telemetry.workspaceUseOf(sessionID, turn)
118118
return {
119119
workspace_skills_used: use.skills,
120120
workspace_memory_blocks: use.memory,
@@ -827,7 +827,7 @@ export namespace SessionPrompt {
827827
tool_call_count: toolCallCount,
828828
duration_ms: Date.now() - sessionStartTime,
829829
// altimate_change start — what of the bound workspace this session used
830-
...workspaceUseFields(sessionID),
830+
...workspaceUseFields(sessionID, telemetryTurn),
831831
// altimate_change end
832832
})
833833
Telemetry.endSession(sessionID, telemetryTurn) // altimate_change — after the row, this turn only
@@ -2143,7 +2143,7 @@ export namespace SessionPrompt {
21432143
duration_ms: Date.now() - sessionStartTime,
21442144
last_tool_category: lastToolCategory || "none",
21452145
// altimate_change — whether workspace skills, memory or integrations were in play
2146-
workspace_context_used: Object.values(Telemetry.workspaceUseOf(sessionID)).some((n) => n > 0),
2146+
workspace_context_used: Object.values(Telemetry.workspaceUseOf(sessionID, telemetryTurn)).some((n) => n > 0),
21472147
})
21482148
// Tool chain effectiveness — aggregated tool sequence + outcome
21492149
if (toolChain.length > 0) {
@@ -2236,7 +2236,7 @@ export namespace SessionPrompt {
22362236
tool_call_count: toolCallCount,
22372237
duration_ms: Date.now() - sessionStartTime,
22382238
// altimate_change start — what of the bound workspace this session used
2239-
...workspaceUseFields(sessionID),
2239+
...workspaceUseFields(sessionID, telemetryTurn),
22402240
// altimate_change end
22412241
})
22422242
Telemetry.endSession(sessionID, telemetryTurn) // altimate_change — after the row, this turn only

‎packages/opencode/test/altimate/telemetry/workspace-context.test.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,12 @@ describe("workspace id on the telemetry context", () => {
8888
const second = Telemetry.setContext({ sessionId: "s7", projectId: "p1", workspaceId: 42 })
8989
expect(second).toBeGreaterThan(first)
9090
Telemetry.noteWorkspaceUse("s7", "memory", 2)
91+
// Counts are per turn: the cancelled turn's rows read its own, the replacement's its own.
92+
expect(Telemetry.workspaceUseOf("s7", first)).toEqual({ skills: 1, memory: 0, integrations: 0 })
93+
expect(Telemetry.workspaceUseOf("s7", second)).toEqual({ skills: 0, memory: 2, integrations: 0 })
9194
Telemetry.endSession("s7", first) // the old generation, after the replacement started
9295
expect(Telemetry.workspaceOf("s7")).toBe(42)
96+
expect(Telemetry.workspaceUseOf("s7", first)).toEqual({ skills: 0, memory: 0, integrations: 0 })
9397
expect(Telemetry.workspaceUseOf("s7").memory).toBe(2)
9498
// A use landing with a stale turn does not count toward the replacement.
9599
Telemetry.noteWorkspaceUse("s7", "integrations", 1, "add", first)

0 commit comments

Comments
 (0)