( sdk: ISdk, kv: StateKV, dedupMap?: DedupMap, maxObservationsPerSession?: number, )
| 35 | } |
| 36 | |
| 37 | export function registerObserveFunction( |
| 38 | sdk: ISdk, |
| 39 | kv: StateKV, |
| 40 | dedupMap?: DedupMap, |
| 41 | maxObservationsPerSession?: number, |
| 42 | ): void { |
| 43 | sdk.registerFunction("mem::observe", |
| 44 | async (payload: HookPayload) => { |
| 45 | |
| 46 | if ( |
| 47 | !payload?.sessionId || |
| 48 | typeof payload.sessionId !== "string" || |
| 49 | !payload.hookType || |
| 50 | typeof payload.hookType !== "string" || |
| 51 | !payload.timestamp || |
| 52 | typeof payload.timestamp !== "string" |
| 53 | ) { |
| 54 | return { |
| 55 | success: false, |
| 56 | error: |
| 57 | "Invalid payload: sessionId, hookType, and timestamp are required", |
| 58 | }; |
| 59 | } |
| 60 | |
| 61 | const obsId = generateId("obs"); |
| 62 | |
| 63 | let dedupHash: string | undefined; |
| 64 | if (dedupMap) { |
| 65 | const d = |
| 66 | typeof payload.data === "object" && payload.data !== null |
| 67 | ? (payload.data as Record<string, unknown>) |
| 68 | : {}; |
| 69 | const toolName = (d["tool_name"] as string) || payload.hookType; |
| 70 | dedupHash = dedupMap.computeHash( |
| 71 | payload.sessionId, |
| 72 | toolName, |
| 73 | d["tool_input"], |
| 74 | ); |
| 75 | if (dedupMap.isDuplicate(dedupHash)) { |
| 76 | return { deduplicated: true, sessionId: payload.sessionId }; |
| 77 | } |
| 78 | } |
| 79 | |
| 80 | let sanitizedRaw: unknown = payload.data; |
| 81 | try { |
| 82 | const jsonStr = JSON.stringify(payload.data); |
| 83 | const sanitized = stripPrivateData(jsonStr); |
| 84 | sanitizedRaw = JSON.parse(sanitized); |
| 85 | } catch { |
| 86 | sanitizedRaw = stripPrivateData(String(payload.data)); |
| 87 | } |
| 88 | |
| 89 | const raw: RawObservation = { |
| 90 | id: obsId, |
| 91 | sessionId: payload.sessionId, |
| 92 | timestamp: payload.timestamp, |
| 93 | hookType: payload.hookType, |
| 94 | raw: sanitizedRaw, |
no test coverage detected