





























@@ -5,7 +5,6 @@ import {
55areDiagnosticsEnabledForProcess,
66emitDiagnosticEvent,
77isDiagnosticsEnabled,
8-type DiagnosticSessionActiveWorkKind,
98type DiagnosticLivenessWarningReason,
109} from "../infra/diagnostic-events.js";
1110import { emitDiagnosticMemorySample, resetDiagnosticMemoryForTest } from "./diagnostic-memory.js";
@@ -20,6 +19,10 @@ import {
2019markDiagnosticActivity as markActivity,
2120resetDiagnosticActivityForTest,
2221} from "./diagnostic-runtime.js";
22+import {
23+classifySessionAttention,
24+type SessionAttentionClassification,
25+} from "./diagnostic-session-attention.js";
2326import {
2427diagnosticSessionStates,
2528getDiagnosticSessionState,
@@ -156,74 +159,6 @@ function hasRecentDiagnosticActivity(now: number): boolean {
156159return lastActivityAt > 0 && now - lastActivityAt <= RECENT_DIAGNOSTIC_ACTIVITY_MS;
157160}
158161159-type SessionAttentionClassification =
160-| {
161-eventType: "session.long_running";
162-reason: string;
163-classification: "long_running";
164-activeWorkKind?: DiagnosticSessionActiveWorkKind;
165-recoveryEligible: false;
166-}
167-| {
168-eventType: "session.stalled";
169-reason: string;
170-classification: "blocked_tool_call" | "stalled_agent_run";
171-activeWorkKind?: DiagnosticSessionActiveWorkKind;
172-recoveryEligible: false;
173-}
174-| {
175-eventType: "session.stuck";
176-reason: string;
177-classification: "stale_session_state";
178-activeWorkKind?: undefined;
179-recoveryEligible: true;
180-};
181-182-function classifySessionAttention(params: {
183-queueDepth: number;
184-activity: DiagnosticSessionActivitySnapshot;
185-staleMs: number;
186-}): SessionAttentionClassification {
187-if (params.activity.activeWorkKind) {
188-if (
189-params.activity.activeWorkKind === "tool_call" &&
190-(params.activity.activeToolAgeMs ?? 0) > params.staleMs &&
191-(params.activity.lastProgressAgeMs ?? 0) > params.staleMs
192-) {
193-return {
194-eventType: "session.stalled",
195-reason: "blocked_tool_call",
196-classification: "blocked_tool_call",
197-activeWorkKind: params.activity.activeWorkKind,
198-recoveryEligible: false,
199-};
200-}
201-if ((params.activity.lastProgressAgeMs ?? 0) > params.staleMs) {
202-return {
203-eventType: "session.stalled",
204-reason: "active_work_without_progress",
205-classification: "stalled_agent_run",
206-activeWorkKind: params.activity.activeWorkKind,
207-recoveryEligible: false,
208-};
209-}
210-return {
211-eventType: "session.long_running",
212-reason: params.queueDepth > 0 ? "queued_behind_active_work" : "active_work",
213-classification: "long_running",
214-activeWorkKind: params.activity.activeWorkKind,
215-recoveryEligible: false,
216-};
217-}
218-219-return {
220-eventType: "session.stuck",
221-reason: params.queueDepth > 0 ? "queued_work_without_active_run" : "stale_session_state",
222-classification: "stale_session_state",
223-recoveryEligible: true,
224-};
225-}
226-227162function roundDiagnosticMetric(value: number, digits = 3): number {
228163if (!Number.isFinite(value)) {
229164return 0;
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。