oc-metricboard 0.1.17 → 0.1.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assistant-progress.js +2 -2
- package/dist/event-bus.js +32 -0
- package/dist/event-handlers.js +11 -11
- package/dist/tui-v2.js +14 -2
- package/package.json +1 -1
- package/src/assistant-progress.ts +2 -2
- package/src/event-bus.ts +30 -0
- package/src/event-handlers.ts +11 -11
- package/src/tui-v2.tsx +14 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { estimateTokens } from "./metrics";
|
|
2
2
|
import { parseAssistantTextDelta } from "./event-shapes";
|
|
3
3
|
import { currentRequest } from "./request-state";
|
|
4
|
-
import { eventAggregateID, eventID, eventProperties, stringEventProperty } from "./event-bus";
|
|
4
|
+
import { eventAggregateID, eventID, eventPerfTime, eventProperties, stringEventProperty } from "./event-bus";
|
|
5
5
|
import { recordLiveTokens } from "./live-speed";
|
|
6
6
|
import { ensureTurn, recordTurnFirstToken } from "./turn-state";
|
|
7
7
|
function partEstimateKey(sessionID, messageID, partID) {
|
|
@@ -51,7 +51,7 @@ export function applyAssistantDelta(ctx, event) {
|
|
|
51
51
|
sessionAliases.add(aggregateID);
|
|
52
52
|
state.sessionAliases.set(text.sessionID, sessionAliases);
|
|
53
53
|
}
|
|
54
|
-
const now = performance.now();
|
|
54
|
+
const now = eventPerfTime(event, performance.now());
|
|
55
55
|
actions.startSessionTiming(text.sessionID, now);
|
|
56
56
|
const key = partEstimateKey(text.sessionID, text.messageID, text.partID);
|
|
57
57
|
const deltaTokens = estimateTokens(text.delta, ctx.config.estimationRatio);
|
package/dist/event-bus.js
CHANGED
|
@@ -51,6 +51,38 @@ export function statusType(event) {
|
|
|
51
51
|
return "";
|
|
52
52
|
return typeof status.type === "string" ? status.type : "";
|
|
53
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Host-stamped wall-clock time of an event (V2 envelope `created`, epoch ms),
|
|
56
|
+
* or null when absent/implausible. V1 events carry no timestamp at all.
|
|
57
|
+
*/
|
|
58
|
+
export function eventCreatedWallTime(event) {
|
|
59
|
+
if (!isRecord(event))
|
|
60
|
+
return null;
|
|
61
|
+
const created = event.created;
|
|
62
|
+
if (typeof created !== "number" || !Number.isFinite(created) || created <= 0)
|
|
63
|
+
return null;
|
|
64
|
+
// Guard against a foreign epoch or clock skew: anything more than a day out
|
|
65
|
+
// is not usable as event time.
|
|
66
|
+
if (Math.abs(created - Date.now()) > 86_400_000)
|
|
67
|
+
return null;
|
|
68
|
+
return created;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Performance-base timestamp for an event. Prefers the host stamp converted
|
|
72
|
+
* into this process's performance.now() base; falls back to `now`.
|
|
73
|
+
*
|
|
74
|
+
* WHY: the V2 host delivers events in batches — a whole turn's deltas can
|
|
75
|
+
* arrive in one flush long after generation. Stamping flush time
|
|
76
|
+
* (performance.now() at handling) collapses the generation window to
|
|
77
|
+
* milliseconds and inflates frozen TPS absurdly (e.g. 259 tokens / 6ms =
|
|
78
|
+
* 42627 t/s). V1 events have no `created`, so this is a no-op for V1.
|
|
79
|
+
*/
|
|
80
|
+
export function eventPerfTime(event, now) {
|
|
81
|
+
const wall = eventCreatedWallTime(event);
|
|
82
|
+
if (wall === null)
|
|
83
|
+
return now;
|
|
84
|
+
return now - Math.max(0, Date.now() - wall);
|
|
85
|
+
}
|
|
54
86
|
export function isMetricsEventApi(value) {
|
|
55
87
|
if (!isRecord(value))
|
|
56
88
|
return false;
|
package/dist/event-handlers.js
CHANGED
|
@@ -3,7 +3,7 @@ import { createFreshMetrics, estimateTokens } from "./metrics";
|
|
|
3
3
|
import { parseAssistantMessage, parseAssistantProgressPart, parseAssistantStepEnded, parseAssistantStepStarted, parseSessionInfo, parseTextPart, parseUserMessage, } from "./event-shapes";
|
|
4
4
|
import { applyAssistantTokens, applySessionModel, hasPositiveAssistantTokens, mergeAssistantModel } from "./request-updates";
|
|
5
5
|
import { completeRequest, currentRequest } from "./request-state";
|
|
6
|
-
import { eventAggregateID, eventID, eventProperties, eventProperty, statusType, stringEventProperty } from "./event-bus";
|
|
6
|
+
import { eventAggregateID, eventID, eventPerfTime, eventProperties, eventProperty, statusType, stringEventProperty } from "./event-bus";
|
|
7
7
|
import { clearLiveSpeed, resetLiveSpeed } from "./live-speed";
|
|
8
8
|
import { ensureTurn, retireRequestIntoTurn, startTurn } from "./turn-state";
|
|
9
9
|
export function registerEventHandlers(ctx) {
|
|
@@ -86,7 +86,7 @@ export function registerEventHandlers(ctx) {
|
|
|
86
86
|
const type = statusType(event);
|
|
87
87
|
log(`session.status: ${sessionID} -> ${type}`);
|
|
88
88
|
if (type === "busy") {
|
|
89
|
-
const now = performance.now();
|
|
89
|
+
const now = eventPerfTime(event, performance.now());
|
|
90
90
|
actions.startSessionTiming(sessionID, now);
|
|
91
91
|
actions.clearHoldTimer(sessionID);
|
|
92
92
|
const existingTurn = state.turns.get(sessionID);
|
|
@@ -108,7 +108,7 @@ export function registerEventHandlers(ctx) {
|
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
110
|
if (type === "idle") {
|
|
111
|
-
completeRequest({ state, actions, sessionID, now: performance.now(), holdDurationMs: config.holdDurationMs, log });
|
|
111
|
+
completeRequest({ state, actions, sessionID, now: eventPerfTime(event, performance.now()), holdDurationMs: config.holdDurationMs, log });
|
|
112
112
|
}
|
|
113
113
|
});
|
|
114
114
|
on("session.idle", (event) => {
|
|
@@ -116,7 +116,7 @@ export function registerEventHandlers(ctx) {
|
|
|
116
116
|
if (sessionID.length === 0)
|
|
117
117
|
return;
|
|
118
118
|
recordEventAlias(event, sessionID);
|
|
119
|
-
completeRequest({ state, actions, sessionID, now: performance.now(), holdDurationMs: config.holdDurationMs, log });
|
|
119
|
+
completeRequest({ state, actions, sessionID, now: eventPerfTime(event, performance.now()), holdDurationMs: config.holdDurationMs, log });
|
|
120
120
|
});
|
|
121
121
|
// ── message.part.delta ──
|
|
122
122
|
on("message.part.delta", (event) => {
|
|
@@ -130,8 +130,8 @@ export function registerEventHandlers(ctx) {
|
|
|
130
130
|
recordEventAlias(event, sessionID);
|
|
131
131
|
if (field !== "text")
|
|
132
132
|
return;
|
|
133
|
-
actions.startSessionTiming(sessionID, performance.now());
|
|
134
|
-
const now = performance.now();
|
|
133
|
+
actions.startSessionTiming(sessionID, eventPerfTime(event, performance.now()));
|
|
134
|
+
const now = eventPerfTime(event, performance.now());
|
|
135
135
|
ensureTurn(state.turns, sessionID, now);
|
|
136
136
|
applyAssistantPartDelta(ctx, sessionID, messageID, partID, delta, now);
|
|
137
137
|
});
|
|
@@ -140,7 +140,7 @@ export function registerEventHandlers(ctx) {
|
|
|
140
140
|
if (!step)
|
|
141
141
|
return;
|
|
142
142
|
recordEventAlias(event, step.sessionID);
|
|
143
|
-
const now = performance.now();
|
|
143
|
+
const now = eventPerfTime(event, performance.now());
|
|
144
144
|
actions.startSessionTiming(step.sessionID, now);
|
|
145
145
|
const existingTurn = state.turns.get(step.sessionID);
|
|
146
146
|
if (!existingTurn || existingTurn.isComplete)
|
|
@@ -164,7 +164,7 @@ export function registerEventHandlers(ctx) {
|
|
|
164
164
|
if (!step)
|
|
165
165
|
return;
|
|
166
166
|
recordEventAlias(event, step.sessionID);
|
|
167
|
-
const now = performance.now();
|
|
167
|
+
const now = eventPerfTime(event, performance.now());
|
|
168
168
|
actions.startSessionTiming(step.sessionID, now);
|
|
169
169
|
const turn = ensureTurn(state.turns, step.sessionID, now);
|
|
170
170
|
const existing = state.requests.get(step.sessionID);
|
|
@@ -205,7 +205,7 @@ export function registerEventHandlers(ctx) {
|
|
|
205
205
|
recordEventAlias(event, sessionID);
|
|
206
206
|
const rawPart = eventProperty(event, "part");
|
|
207
207
|
const part = parseTextPart(rawPart);
|
|
208
|
-
const now = performance.now();
|
|
208
|
+
const now = eventPerfTime(event, performance.now());
|
|
209
209
|
const msgIds = state.userMessageIds.get(sessionID);
|
|
210
210
|
if (part && msgIds?.has(part.messageID)) {
|
|
211
211
|
const current = state.requests.get(sessionID);
|
|
@@ -235,7 +235,7 @@ export function registerEventHandlers(ctx) {
|
|
|
235
235
|
const nextModel = mergeAssistantModel(state.sessionModels.get(sessionID), assistant);
|
|
236
236
|
if (nextModel)
|
|
237
237
|
state.sessionModels.set(sessionID, nextModel);
|
|
238
|
-
const now = performance.now();
|
|
238
|
+
const now = eventPerfTime(event, performance.now());
|
|
239
239
|
const tokens = assistant.tokens;
|
|
240
240
|
const existing = state.requests.get(sessionID);
|
|
241
241
|
const turn = ensureTurn(state.turns, sessionID, now);
|
|
@@ -278,7 +278,7 @@ export function registerEventHandlers(ctx) {
|
|
|
278
278
|
if (userMsgID && state.userMessageIds.get(sessionID)?.has(userMsgID)) {
|
|
279
279
|
return;
|
|
280
280
|
}
|
|
281
|
-
const now = performance.now();
|
|
281
|
+
const now = eventPerfTime(event, performance.now());
|
|
282
282
|
const previous = state.requests.get(sessionID);
|
|
283
283
|
const previousTurn = state.turns.get(sessionID);
|
|
284
284
|
if (previous && previousTurn)
|
package/dist/tui-v2.js
CHANGED
|
@@ -81,7 +81,14 @@ export function translateExecutionStartedToBusy(event) {
|
|
|
81
81
|
const sessionID = str(data.sessionID);
|
|
82
82
|
if (!sessionID)
|
|
83
83
|
return null;
|
|
84
|
-
|
|
84
|
+
// Preserve the host stamp so downstream timing uses generation time,
|
|
85
|
+
// not the (possibly batched) delivery time.
|
|
86
|
+
const created = typeof event.created === "number" ? event.created : undefined;
|
|
87
|
+
return {
|
|
88
|
+
type: "session.status",
|
|
89
|
+
...(created !== undefined ? { created } : {}),
|
|
90
|
+
properties: { sessionID, status: { type: "busy" } },
|
|
91
|
+
};
|
|
85
92
|
}
|
|
86
93
|
/**
|
|
87
94
|
* Turn-settled execution maps to the V1 `session.idle` shape that drives
|
|
@@ -93,7 +100,12 @@ export function translateExecutionSettledToIdle(event) {
|
|
|
93
100
|
const sessionID = str(data.sessionID);
|
|
94
101
|
if (!sessionID)
|
|
95
102
|
return null;
|
|
96
|
-
|
|
103
|
+
const created = typeof event.created === "number" ? event.created : undefined;
|
|
104
|
+
return {
|
|
105
|
+
type: "session.idle",
|
|
106
|
+
...(created !== undefined ? { created } : {}),
|
|
107
|
+
properties: { sessionID },
|
|
108
|
+
};
|
|
97
109
|
}
|
|
98
110
|
function eventSessionID(event) {
|
|
99
111
|
if (!isRecord(event))
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { estimateTokens } from "./metrics"
|
|
2
2
|
import { parseAssistantTextDelta } from "./event-shapes"
|
|
3
3
|
import { currentRequest } from "./request-state"
|
|
4
|
-
import { eventAggregateID, eventID, eventProperties, stringEventProperty } from "./event-bus"
|
|
4
|
+
import { eventAggregateID, eventID, eventPerfTime, eventProperties, stringEventProperty } from "./event-bus"
|
|
5
5
|
import type { EventHandlerContext } from "./collector-state"
|
|
6
6
|
import { recordLiveTokens } from "./live-speed"
|
|
7
7
|
import { ensureTurn, recordTurnFirstToken } from "./turn-state"
|
|
@@ -78,7 +78,7 @@ export function applyAssistantDelta(ctx: EventHandlerContext, event: unknown): v
|
|
|
78
78
|
sessionAliases.add(aggregateID)
|
|
79
79
|
state.sessionAliases.set(text.sessionID, sessionAliases)
|
|
80
80
|
}
|
|
81
|
-
const now = performance.now()
|
|
81
|
+
const now = eventPerfTime(event, performance.now())
|
|
82
82
|
actions.startSessionTiming(text.sessionID, now)
|
|
83
83
|
const key = partEstimateKey(text.sessionID, text.messageID, text.partID)
|
|
84
84
|
const deltaTokens = estimateTokens(text.delta, ctx.config.estimationRatio)
|
package/src/event-bus.ts
CHANGED
|
@@ -54,6 +54,36 @@ export function statusType(event: unknown): string {
|
|
|
54
54
|
return typeof status.type === "string" ? status.type : ""
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Host-stamped wall-clock time of an event (V2 envelope `created`, epoch ms),
|
|
59
|
+
* or null when absent/implausible. V1 events carry no timestamp at all.
|
|
60
|
+
*/
|
|
61
|
+
export function eventCreatedWallTime(event: unknown): number | null {
|
|
62
|
+
if (!isRecord(event)) return null
|
|
63
|
+
const created = event.created
|
|
64
|
+
if (typeof created !== "number" || !Number.isFinite(created) || created <= 0) return null
|
|
65
|
+
// Guard against a foreign epoch or clock skew: anything more than a day out
|
|
66
|
+
// is not usable as event time.
|
|
67
|
+
if (Math.abs(created - Date.now()) > 86_400_000) return null
|
|
68
|
+
return created
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Performance-base timestamp for an event. Prefers the host stamp converted
|
|
73
|
+
* into this process's performance.now() base; falls back to `now`.
|
|
74
|
+
*
|
|
75
|
+
* WHY: the V2 host delivers events in batches — a whole turn's deltas can
|
|
76
|
+
* arrive in one flush long after generation. Stamping flush time
|
|
77
|
+
* (performance.now() at handling) collapses the generation window to
|
|
78
|
+
* milliseconds and inflates frozen TPS absurdly (e.g. 259 tokens / 6ms =
|
|
79
|
+
* 42627 t/s). V1 events have no `created`, so this is a no-op for V1.
|
|
80
|
+
*/
|
|
81
|
+
export function eventPerfTime(event: unknown, now: number): number {
|
|
82
|
+
const wall = eventCreatedWallTime(event)
|
|
83
|
+
if (wall === null) return now
|
|
84
|
+
return now - Math.max(0, Date.now() - wall)
|
|
85
|
+
}
|
|
86
|
+
|
|
57
87
|
export function isMetricsEventApi(value: unknown): value is MetricsEventApi {
|
|
58
88
|
if (!isRecord(value)) return false
|
|
59
89
|
const event = value.event
|
package/src/event-handlers.ts
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
} from "./event-shapes"
|
|
12
12
|
import { applyAssistantTokens, applySessionModel, hasPositiveAssistantTokens, mergeAssistantModel } from "./request-updates"
|
|
13
13
|
import { completeRequest, currentRequest } from "./request-state"
|
|
14
|
-
import { eventAggregateID, eventID, eventProperties, eventProperty, statusType, stringEventProperty } from "./event-bus"
|
|
14
|
+
import { eventAggregateID, eventID, eventPerfTime, eventProperties, eventProperty, statusType, stringEventProperty } from "./event-bus"
|
|
15
15
|
import type { EventHandlerContext } from "./collector-state"
|
|
16
16
|
import { clearLiveSpeed, resetLiveSpeed } from "./live-speed"
|
|
17
17
|
import { ensureTurn, retireRequestIntoTurn, startTurn } from "./turn-state"
|
|
@@ -97,7 +97,7 @@ export function registerEventHandlers(ctx: EventHandlerContext): Array<() => voi
|
|
|
97
97
|
log(`session.status: ${sessionID} -> ${type}`)
|
|
98
98
|
|
|
99
99
|
if (type === "busy") {
|
|
100
|
-
const now = performance.now()
|
|
100
|
+
const now = eventPerfTime(event, performance.now())
|
|
101
101
|
actions.startSessionTiming(sessionID, now)
|
|
102
102
|
actions.clearHoldTimer(sessionID)
|
|
103
103
|
const existingTurn = state.turns.get(sessionID)
|
|
@@ -118,7 +118,7 @@ export function registerEventHandlers(ctx: EventHandlerContext): Array<() => voi
|
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
if (type === "idle") {
|
|
121
|
-
completeRequest({ state, actions, sessionID, now: performance.now(), holdDurationMs: config.holdDurationMs, log })
|
|
121
|
+
completeRequest({ state, actions, sessionID, now: eventPerfTime(event, performance.now()), holdDurationMs: config.holdDurationMs, log })
|
|
122
122
|
}
|
|
123
123
|
})
|
|
124
124
|
|
|
@@ -126,7 +126,7 @@ export function registerEventHandlers(ctx: EventHandlerContext): Array<() => voi
|
|
|
126
126
|
const sessionID = stringEventProperty(event, "sessionID")
|
|
127
127
|
if (sessionID.length === 0) return
|
|
128
128
|
recordEventAlias(event, sessionID)
|
|
129
|
-
completeRequest({ state, actions, sessionID, now: performance.now(), holdDurationMs: config.holdDurationMs, log })
|
|
129
|
+
completeRequest({ state, actions, sessionID, now: eventPerfTime(event, performance.now()), holdDurationMs: config.holdDurationMs, log })
|
|
130
130
|
})
|
|
131
131
|
|
|
132
132
|
// ── message.part.delta ──
|
|
@@ -139,9 +139,9 @@ export function registerEventHandlers(ctx: EventHandlerContext): Array<() => voi
|
|
|
139
139
|
if (sessionID.length === 0 || messageID.length === 0) return
|
|
140
140
|
recordEventAlias(event, sessionID)
|
|
141
141
|
if (field !== "text") return
|
|
142
|
-
actions.startSessionTiming(sessionID, performance.now())
|
|
142
|
+
actions.startSessionTiming(sessionID, eventPerfTime(event, performance.now()))
|
|
143
143
|
|
|
144
|
-
const now = performance.now()
|
|
144
|
+
const now = eventPerfTime(event, performance.now())
|
|
145
145
|
ensureTurn(state.turns, sessionID, now)
|
|
146
146
|
applyAssistantPartDelta(ctx, sessionID, messageID, partID, delta, now)
|
|
147
147
|
})
|
|
@@ -150,7 +150,7 @@ export function registerEventHandlers(ctx: EventHandlerContext): Array<() => voi
|
|
|
150
150
|
const step = parseAssistantStepStarted(eventProperties(event), eventID(event))
|
|
151
151
|
if (!step) return
|
|
152
152
|
recordEventAlias(event, step.sessionID)
|
|
153
|
-
const now = performance.now()
|
|
153
|
+
const now = eventPerfTime(event, performance.now())
|
|
154
154
|
actions.startSessionTiming(step.sessionID, now)
|
|
155
155
|
const existingTurn = state.turns.get(step.sessionID)
|
|
156
156
|
if (!existingTurn || existingTurn.isComplete) startTurn(state.turns, step.sessionID, now)
|
|
@@ -175,7 +175,7 @@ export function registerEventHandlers(ctx: EventHandlerContext): Array<() => voi
|
|
|
175
175
|
const step = parseAssistantStepEnded(eventProperties(event), fallbackMessageID)
|
|
176
176
|
if (!step) return
|
|
177
177
|
recordEventAlias(event, step.sessionID)
|
|
178
|
-
const now = performance.now()
|
|
178
|
+
const now = eventPerfTime(event, performance.now())
|
|
179
179
|
actions.startSessionTiming(step.sessionID, now)
|
|
180
180
|
const turn = ensureTurn(state.turns, step.sessionID, now)
|
|
181
181
|
const existing = state.requests.get(step.sessionID)
|
|
@@ -215,7 +215,7 @@ export function registerEventHandlers(ctx: EventHandlerContext): Array<() => voi
|
|
|
215
215
|
recordEventAlias(event, sessionID)
|
|
216
216
|
const rawPart = eventProperty(event, "part")
|
|
217
217
|
const part = parseTextPart(rawPart)
|
|
218
|
-
const now = performance.now()
|
|
218
|
+
const now = eventPerfTime(event, performance.now())
|
|
219
219
|
const msgIds = state.userMessageIds.get(sessionID)
|
|
220
220
|
if (part && msgIds?.has(part.messageID)) {
|
|
221
221
|
const current = state.requests.get(sessionID)
|
|
@@ -246,7 +246,7 @@ export function registerEventHandlers(ctx: EventHandlerContext): Array<() => voi
|
|
|
246
246
|
const nextModel = mergeAssistantModel(state.sessionModels.get(sessionID), assistant)
|
|
247
247
|
if (nextModel) state.sessionModels.set(sessionID, nextModel)
|
|
248
248
|
|
|
249
|
-
const now = performance.now()
|
|
249
|
+
const now = eventPerfTime(event, performance.now())
|
|
250
250
|
const tokens = assistant.tokens
|
|
251
251
|
const existing = state.requests.get(sessionID)
|
|
252
252
|
const turn = ensureTurn(state.turns, sessionID, now)
|
|
@@ -288,7 +288,7 @@ export function registerEventHandlers(ctx: EventHandlerContext): Array<() => voi
|
|
|
288
288
|
if (userMsgID && state.userMessageIds.get(sessionID)?.has(userMsgID)) {
|
|
289
289
|
return
|
|
290
290
|
}
|
|
291
|
-
const now = performance.now()
|
|
291
|
+
const now = eventPerfTime(event, performance.now())
|
|
292
292
|
const previous = state.requests.get(sessionID)
|
|
293
293
|
const previousTurn = state.turns.get(sessionID)
|
|
294
294
|
if (previous && previousTurn) retireRequestIntoTurn(previousTurn, previous)
|
package/src/tui-v2.tsx
CHANGED
|
@@ -133,7 +133,14 @@ export function translateExecutionStartedToBusy(event: V2EventLike): unknown {
|
|
|
133
133
|
const data = isRecord(event.data) ? event.data : {}
|
|
134
134
|
const sessionID = str(data.sessionID)
|
|
135
135
|
if (!sessionID) return null
|
|
136
|
-
|
|
136
|
+
// Preserve the host stamp so downstream timing uses generation time,
|
|
137
|
+
// not the (possibly batched) delivery time.
|
|
138
|
+
const created = typeof event.created === "number" ? event.created : undefined
|
|
139
|
+
return {
|
|
140
|
+
type: "session.status",
|
|
141
|
+
...(created !== undefined ? { created } : {}),
|
|
142
|
+
properties: { sessionID, status: { type: "busy" } },
|
|
143
|
+
}
|
|
137
144
|
}
|
|
138
145
|
|
|
139
146
|
/**
|
|
@@ -145,7 +152,12 @@ export function translateExecutionSettledToIdle(event: V2EventLike): unknown {
|
|
|
145
152
|
const data = isRecord(event.data) ? event.data : {}
|
|
146
153
|
const sessionID = str(data.sessionID)
|
|
147
154
|
if (!sessionID) return null
|
|
148
|
-
|
|
155
|
+
const created = typeof event.created === "number" ? event.created : undefined
|
|
156
|
+
return {
|
|
157
|
+
type: "session.idle",
|
|
158
|
+
...(created !== undefined ? { created } : {}),
|
|
159
|
+
properties: { sessionID },
|
|
160
|
+
}
|
|
149
161
|
}
|
|
150
162
|
|
|
151
163
|
function eventSessionID(event: unknown): string {
|