(
state: HookRegistryState,
eventName: string,
event: Partial<AIDevtoolsEventEnvelope> & {
runtimeId?: string
timestamp?: number
},
)
| 190 | } |
| 191 | |
| 192 | export function markEventSeen( |
| 193 | state: HookRegistryState, |
| 194 | eventName: string, |
| 195 | event: Partial<AIDevtoolsEventEnvelope> & { |
| 196 | runtimeId?: string |
| 197 | timestamp?: number |
| 198 | }, |
| 199 | ): boolean { |
| 200 | let key: string |
| 201 | if (event.eventId) { |
| 202 | key = event.eventId |
| 203 | } else { |
| 204 | key = [ |
| 205 | eventName, |
| 206 | event.source ?? 'unknown', |
| 207 | event.visibility ?? 'unknown', |
| 208 | event.runtimeId ?? 'no-runtime', |
| 209 | event.hookId ?? event.clientId ?? 'no-hook', |
| 210 | event.threadId ?? 'no-thread', |
| 211 | event.runId ?? 'no-run', |
| 212 | event.messageId ?? 'no-message', |
| 213 | event.toolCallId ?? 'no-tool-call', |
| 214 | event.timestamp ?? 'no-time', |
| 215 | ].join(':') |
| 216 | // If every identifying field fell back to its literal sentinel the synthesised |
| 217 | // key is just `eventName:unknown:unknown:no-runtime:...` — useful for very |
| 218 | // little. Warn so it's obvious in the console why deduplication may be |
| 219 | // collapsing distinct events together. |
| 220 | if ( |
| 221 | !event.source && |
| 222 | !event.visibility && |
| 223 | !event.runtimeId && |
| 224 | !event.hookId && |
| 225 | !event.clientId && |
| 226 | !event.threadId && |
| 227 | !event.runId && |
| 228 | !event.messageId && |
| 229 | !event.toolCallId && |
| 230 | !event.timestamp |
| 231 | ) { |
| 232 | console.warn( |
| 233 | `[ai-devtools] dedupe key for "${eventName}" has no identifying fields; events may collide.`, |
| 234 | ) |
| 235 | } |
| 236 | } |
| 237 | |
| 238 | if (state.seenEventIds[key]) { |
| 239 | return false |
| 240 | } |
| 241 | state.seenEventIds[key] = true |
| 242 | state.seenEventIdOrder.push(key) |
| 243 | if (state.seenEventIdOrder.length > SEEN_EVENT_IDS_CAP) { |
| 244 | const evicted = state.seenEventIdOrder.shift() |
| 245 | if (evicted !== undefined) { |
| 246 | delete state.seenEventIds[evicted] |
| 247 | } |
| 248 | } |
| 249 | return true |
no test coverage detected