UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

322 lines (321 loc) 13.8 kB
import { f as onInternalDiagnosticEvent } from "./diagnostic-events-Chmz2PSy.js"; //#region src/logging/diagnostic-run-activity.ts const activityByRef = /* @__PURE__ */ new Map(); const activityByRunId = /* @__PURE__ */ new Map(); let embeddedRunSequence = 0; function sessionRefs(params) { const refs = []; const sessionId = params.sessionId?.trim(); const sessionKey = params.sessionKey?.trim(); if (sessionId) refs.push(`id:${sessionId}`); if (sessionKey) refs.push(`key:${sessionKey}`); return refs; } function registerSessionActivityRefs(activity, params) { activity.sessionId ??= params.sessionId; activity.sessionKey ??= params.sessionKey; for (const ref of sessionRefs(params)) activityByRef.set(ref, activity); if (params.runId) activityByRunId.set(params.runId, activity); } function replaceSessionActivityReferences(source, target) { for (const [ref, activity] of activityByRef) if (activity === source) activityByRef.set(ref, target); for (const [runId, activity] of activityByRunId) if (activity === source) activityByRunId.set(runId, target); } function mergeSessionActivity(target, source) { target.sessionId ??= source.sessionId; target.sessionKey ??= source.sessionKey; for (const [key, embeddedRun] of source.activeEmbeddedRuns) target.activeEmbeddedRuns.set(key, embeddedRun); for (const [key, tool] of source.activeTools) target.activeTools.set(key, tool); for (const [key, modelCall] of source.activeModelCalls) target.activeModelCalls.set(key, modelCall); for (const [ownerRef, cutoff] of source.recoveredOwnerStartEventCutoffs) target.recoveredOwnerStartEventCutoffs.set(ownerRef, Math.max(cutoff, target.recoveredOwnerStartEventCutoffs.get(ownerRef) ?? 0)); if (source.lastProgressAt > target.lastProgressAt) { target.lastProgressAt = source.lastProgressAt; target.lastProgressReason = source.lastProgressReason; } replaceSessionActivityReferences(source, target); } function resolveSessionActivity(params) { let activity; if (params.runId) { const byRun = activityByRunId.get(params.runId); if (byRun) activity = byRun; } for (const ref of sessionRefs(params)) { const byRef = activityByRef.get(ref); if (!byRef) continue; if (!activity) activity = byRef; else if (activity !== byRef) mergeSessionActivity(activity, byRef); } if (activity) { registerSessionActivityRefs(activity, params); return activity; } if (!params.create) return; const created = { sessionId: params.sessionId, sessionKey: params.sessionKey, activeEmbeddedRuns: /* @__PURE__ */ new Map(), activeTools: /* @__PURE__ */ new Map(), activeModelCalls: /* @__PURE__ */ new Map(), recoveredOwnerStartEventCutoffs: /* @__PURE__ */ new Map(), lastProgressAt: Date.now() }; registerSessionActivityRefs(created, params); return created; } function touchSessionActivity(activity, reason, now = Date.now()) { activity.lastProgressAt = now; activity.lastProgressReason = reason; } function toolKey(event) { return `${event.runId ?? event.sessionId ?? event.sessionKey ?? "unknown"}:${event.toolCallId ?? event.toolName}`; } function modelCallKey(event) { return `${event.runId ?? "unknown"}:${event.provider ?? "provider"}:${event.model ?? "model"}`; } function recordToolStarted(event) { const activity = resolveSessionActivity({ ...event, create: true }); if (!activity) return; if (shouldIgnoreRecoveredOwnerStartEvent(activity, event)) return; const now = Date.now(); activity.activeTools.set(toolKey(event), { runId: event.runId, sessionId: event.sessionId, sessionKey: event.sessionKey, sequence: event.seq, toolName: event.toolName, toolCallId: event.toolCallId, startedAt: now, lastProgressAt: now }); touchSessionActivity(activity, `tool:${event.toolName}:started`, now); } function recordToolEnded(event) { const activity = resolveSessionActivity(event); if (!activity) return; activity.activeTools.delete(toolKey(event)); touchSessionActivity(activity, `tool:${event.toolName}:ended`); } function recordModelStarted(event) { const activity = resolveSessionActivity({ ...event, create: true }); if (!activity) return; if (shouldIgnoreRecoveredOwnerStartEvent(activity, event)) return; activity.activeModelCalls.set(modelCallKey(event), { runId: event.runId, sessionId: event.sessionId, sessionKey: event.sessionKey, sequence: event.seq }); touchSessionActivity(activity, "model_call:started"); } function recordModelEnded(event) { const activity = resolveSessionActivity(event); if (!activity) return; activity.activeModelCalls.delete(modelCallKey(event)); touchSessionActivity(activity, "model_call:ended"); } function recordRunProgress(event) { markDiagnosticRunProgress(event); } function markDiagnosticRunProgress(params) { const activity = resolveSessionActivity({ ...params, create: true }); if (!activity) return; touchSessionActivity(activity, params.reason); } function recordRunCompleted(event) { const activity = resolveSessionActivity(event); if (!activity) return; activityByRunId.delete(event.runId); activity.activeTools.clear(); activity.activeModelCalls.clear(); activity.activeEmbeddedRuns.clear(); touchSessionActivity(activity, "run:completed"); } function markDiagnosticEmbeddedRunStarted(params) { const activity = resolveSessionActivity({ ...params, create: true }); if (!activity) return; activity.activeEmbeddedRuns.set(resolveEmbeddedRunWorkKey(params), { sessionId: params.sessionId, sessionKey: params.sessionKey, sequence: ++embeddedRunSequence }); touchSessionActivity(activity, "embedded_run:started"); } function markDiagnosticEmbeddedRunEnded(params) { const activity = resolveSessionActivity(params); if (!activity) return; activity.activeEmbeddedRuns.delete(resolveEmbeddedRunWorkKey(params)); if (params.clearRunActivity !== false) { activity.activeTools.clear(); activity.activeModelCalls.clear(); } touchSessionActivity(activity, "embedded_run:ended"); } function resolveEmbeddedRunWorkKey(params) { return params.workKey ?? params.sessionId; } function ownerRefsForRecovery(params) { const refs = [params.activeSessionId?.trim(), params.sessionId?.trim()].filter((ref) => Boolean(ref)); return new Set(refs); } function ownerRefsForStartedEvent(event) { return [event.runId?.trim(), event.sessionId?.trim()].filter((ref) => Boolean(ref)); } function markerBelongsToRecoveredOwner(marker, ownerRefs) { return marker.runId !== void 0 && ownerRefs.has(marker.runId) || marker.sessionId !== void 0 && ownerRefs.has(marker.sessionId); } function embeddedRunStartedAfter(embeddedRun, sequence) { return sequence !== void 0 && embeddedRun.sequence > sequence; } function activityMarkerStartedAfter(marker, sequence) { return sequence !== void 0 && marker.sequence !== void 0 && marker.sequence > sequence; } function clearRecoveredOwnerEmbeddedRuns(activity, ownerRefs, recoveryStartedAfterSequence) { if (ownerRefs.size === 0) return; for (const [key, embeddedRun] of activity.activeEmbeddedRuns) if (embeddedRun.sessionId !== void 0 && ownerRefs.has(embeddedRun.sessionId) && !embeddedRunStartedAfter(embeddedRun, recoveryStartedAfterSequence)) activity.activeEmbeddedRuns.delete(key); } function hasEmbeddedRunStartedAfter(activity, sequence) { if (sequence === void 0) return activity.activeEmbeddedRuns.size > 0; for (const embeddedRun of activity.activeEmbeddedRuns.values()) if (embeddedRun.sequence > sequence) return true; return false; } function clearRecoveredOwnerMarkers(activity, ownerRefs, recoveryStartedAfterSequence) { if (ownerRefs.size === 0) return; for (const [key, tool] of activity.activeTools) if (markerBelongsToRecoveredOwner(tool, ownerRefs) && !activityMarkerStartedAfter(tool, recoveryStartedAfterSequence)) activity.activeTools.delete(key); for (const [key, modelCall] of activity.activeModelCalls) if (markerBelongsToRecoveredOwner(modelCall, ownerRefs) && !activityMarkerStartedAfter(modelCall, recoveryStartedAfterSequence)) activity.activeModelCalls.delete(key); } function pruneActivityStartedBeforeRecoveryCutoff(activity, recoveryStartedAfterEmbeddedRunSequence, recoveryStartedAfterDiagnosticEventSequence) { if (recoveryStartedAfterEmbeddedRunSequence === void 0 && recoveryStartedAfterDiagnosticEventSequence === void 0) return; for (const [key, embeddedRun] of activity.activeEmbeddedRuns) if (!embeddedRunStartedAfter(embeddedRun, recoveryStartedAfterEmbeddedRunSequence)) activity.activeEmbeddedRuns.delete(key); for (const [key, tool] of activity.activeTools) if (!activityMarkerStartedAfter(tool, recoveryStartedAfterDiagnosticEventSequence)) activity.activeTools.delete(key); for (const [key, modelCall] of activity.activeModelCalls) if (!activityMarkerStartedAfter(modelCall, recoveryStartedAfterDiagnosticEventSequence)) activity.activeModelCalls.delete(key); } function rememberRecoveredOwnerStartEventCutoffs(activity, ownerRefs, recoveryStartedAfterSequence) { if (recoveryStartedAfterSequence === void 0) return; for (const ownerRef of ownerRefs) activity.recoveredOwnerStartEventCutoffs.set(ownerRef, Math.max(recoveryStartedAfterSequence, activity.recoveredOwnerStartEventCutoffs.get(ownerRef) ?? 0)); } function shouldIgnoreRecoveredOwnerStartEvent(activity, event) { if (event.seq === void 0) return false; for (const ownerRef of ownerRefsForStartedEvent(event)) { const cutoff = activity.recoveredOwnerStartEventCutoffs.get(ownerRef); if (cutoff !== void 0 && event.seq <= cutoff) return true; } return false; } function clearDiagnosticEmbeddedRunActivityForSession(params) { const shouldCreateCutoffActivity = params.recoveryStartedAfterDiagnosticEventSequence !== void 0; const activity = resolveSessionActivity({ sessionId: params.sessionId, sessionKey: params.sessionKey, runId: params.activeSessionId, create: shouldCreateCutoffActivity }); if (!activity) return { cleared: false, blockedByActiveEmbeddedRun: false }; if (params.activeSessionId) registerSessionActivityRefs(activity, { sessionId: params.activeSessionId, sessionKey: params.sessionKey, runId: params.activeSessionId }); const ownerRefs = ownerRefsForRecovery(params); rememberRecoveredOwnerStartEventCutoffs(activity, ownerRefs, params.recoveryStartedAfterDiagnosticEventSequence); if (activity.activeEmbeddedRuns.size === 0 && activity.activeTools.size === 0 && activity.activeModelCalls.size === 0) return { cleared: false, blockedByActiveEmbeddedRun: false }; clearRecoveredOwnerEmbeddedRuns(activity, ownerRefs, params.recoveryStartedAfterEmbeddedRunSequence); clearRecoveredOwnerMarkers(activity, ownerRefs, params.recoveryStartedAfterDiagnosticEventSequence); if (activity.activeEmbeddedRuns.size > 0) { if (hasEmbeddedRunStartedAfter(activity, params.recoveryStartedAfterEmbeddedRunSequence)) { pruneActivityStartedBeforeRecoveryCutoff(activity, params.recoveryStartedAfterEmbeddedRunSequence, params.recoveryStartedAfterDiagnosticEventSequence); touchSessionActivity(activity, "embedded_run:recovery_skipped_active_owner"); return { cleared: false, blockedByActiveEmbeddedRun: true }; } activity.activeEmbeddedRuns.clear(); } activity.activeTools.clear(); activity.activeModelCalls.clear(); touchSessionActivity(activity, "embedded_run:ended"); return { cleared: true, blockedByActiveEmbeddedRun: false }; } function getDiagnosticSessionActivitySnapshot(params, now = Date.now()) { const activity = resolveSessionActivity(params); if (!activity) return {}; let activeWorkKind; if (activity.activeTools.size > 0) activeWorkKind = "tool_call"; else if (activity.activeModelCalls.size > 0) activeWorkKind = "model_call"; else if (activity.activeEmbeddedRuns.size > 0) activeWorkKind = "embedded_run"; let activeTool; for (const tool of activity.activeTools.values()) if (!activeTool || tool.startedAt < activeTool.startedAt) activeTool = tool; return { activeWorkKind, ...activity.activeEmbeddedRuns.size > 0 ? { hasActiveEmbeddedRun: true } : {}, activeToolName: activeTool?.toolName, activeToolCallId: activeTool?.toolCallId, activeToolAgeMs: activeTool ? Math.max(0, now - activeTool.startedAt) : void 0, lastProgressAgeMs: Math.max(0, now - activity.lastProgressAt), lastProgressReason: activity.lastProgressReason }; } function getDiagnosticEmbeddedRunActivitySequence() { return embeddedRunSequence; } function resetDiagnosticRunActivityForTest() { activityByRef.clear(); activityByRunId.clear(); embeddedRunSequence = 0; unregisterDiagnosticRunActivityListener?.(); unregisterDiagnosticRunActivityListener = void 0; registerDiagnosticRunActivityListener(); } let unregisterDiagnosticRunActivityListener; function registerDiagnosticRunActivityListener() { if (unregisterDiagnosticRunActivityListener) return; unregisterDiagnosticRunActivityListener = onInternalDiagnosticEvent((event) => { switch (event.type) { case "tool.execution.started": recordToolStarted(event); return; case "tool.execution.completed": case "tool.execution.error": case "tool.execution.blocked": recordToolEnded(event); return; case "model.call.started": recordModelStarted(event); return; case "model.call.completed": case "model.call.error": recordModelEnded(event); return; case "run.progress": recordRunProgress(event); return; case "run.completed": recordRunCompleted(event); default: } }); } registerDiagnosticRunActivityListener(); //#endregion export { markDiagnosticEmbeddedRunStarted as a, markDiagnosticEmbeddedRunEnded as i, getDiagnosticEmbeddedRunActivitySequence as n, markDiagnosticRunProgress as o, getDiagnosticSessionActivitySnapshot as r, resetDiagnosticRunActivityForTest as s, clearDiagnosticEmbeddedRunActivityForSession as t };